EMU618社区

 找回密码
 立即注册
搜索
查看: 1841|回复: 14

[求助] 【模拟器代码问题】模拟器如何通过代码控制Rom的背景音乐

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?- p/ ^/ e% U0 s
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

发表于 2009-11-2 22:57:37 | 显示全部楼层
看了下VirtualNes的源码,是APU那部分,全称应该是Audio Process Unit

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" W+ ]8 m( c) f+ o" S
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# ~9 m# @( x- Z' ?7 x! B7 Y
这里有相应的模拟器源码,就当送给大侠了~~$ D* S  N9 R! W) V9 k
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ) E- R( ^1 w6 r; r, J  M' z  i+ s5 v
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 k  |2 F( k# B$ m楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( B$ R1 S* E$ l; F2 U% J8 u这里有相应的模拟器源码,就当送给大侠 ...

& L, Z1 n, m# _1 c. M聲音部分(Audoi Process Unit = APU):
, K' z' Q. E; _) u.\NES\APU.cpp9 I$ e$ h# o" X2 i7 g
.\NES\APU.h
" O  R9 j- r+ t+ B3 m! O: f
& R+ G. p# d9 ~5 U3 V! f
' R1 M) `$ z. _+ }1 o) {影像處理部份(Picture Processing Unit = PPU):9 \9 d3 L" X: R3 D) b6 {
.\NES\PPU.cpp
- Z8 B9 x- C6 F, F0 R$ W0 h4 E.\NES\PPU.h5 [; u! k, v" ]. ]7 P( E

' l2 B- `2 H$ \1 s( E7 s: h如果原碼用C跟ASM混搭也不錯

该用户从未签到

发表于 2009-11-8 13:03:26 | 显示全部楼层
楼上是高手 哈哈

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ e0 t8 n) i1 Q; d; o/ a( @
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( h- u: ^: |. C$ j7 k* Y(由于很多专用术语和算法机理都不明白,所以看不大懂……)
# q, e; v1 y2 M( L  P2 m' m8 G6 d! `//////////////////////////////////////////////////////////////////////////
0 v: N+ L. X* @! {//                                                                      //
$ K( G8 V6 [3 r# ?: F//      NES APU core                                                    //' Z6 R" ^& `$ Q" l( ?! u: ?4 W) ]. T
//                                                           Norix      /// I8 y7 i$ g  G& I
//                                               written     2002/06/27 //& q2 x3 |, ^9 G2 N8 V' [1 N2 @' q
//                                               last modify ----/--/-- //9 _" Z0 f. ~( E) w& O2 i
//////////////////////////////////////////////////////////////////////////
  L0 Q) i! A) V" `# ]+ Z#include "DebugOut.h". j8 J  C, C$ x% s6 a  p
#include "App.h"3 r) k4 e+ F- z$ ~, ]& n: J/ w/ @
#include "Config.h"
7 E  K) b; g; g" K+ ]
6 @/ C5 W0 \& R- Y6 F5 Q! }- Z#include "nes.h"
- i- V: Q7 q2 f5 o% q1 H0 {4 o#include "mmu.h"' G& u' }4 ~  F5 k8 S4 T7 M
#include "cpu.h"* z4 ]" P* B2 ?1 x1 J. f1 \
#include "ppu.h"
$ z7 E6 E3 K8 |9 V8 D. L) Q#include "rom.h"" W. n1 z; n0 ~  k  N
#include "apu.h"  F( t! d! T8 m" D6 n
9 D: x) W3 U+ \, x4 P
// Volume adjust% i* N7 R% I8 t9 t
// Internal sounds
4 J' L' e0 y& ?/ x#define        RECTANGLE_VOL        (0x0F0)
0 C2 q( o6 A8 N#define        TRIANGLE_VOL        (0x130)# Z" t/ m1 l6 {( t. N; P
#define        NOISE_VOL        (0x0C0)9 [: U* z  d$ ?4 d( W( ?& }; Q
#define        DPCM_VOL        (0x0F0). V" p9 X$ |, R* l) H4 {
// Extra sounds
; p& v( S5 ^7 x7 n- \) i- X#define        VRC6_VOL        (0x0F0)
- h! |5 g  u2 k$ O' H' q3 w% w#define        VRC7_VOL        (0x130)1 F( \9 y+ i0 t9 a
#define        FDS_VOL                (0x0F0)8 V2 @7 g! k1 a, [6 e$ f
#define        MMC5_VOL        (0x0F0)4 \- T! H% N- \# T* u. G& c% v- o
#define        N106_VOL        (0x088)" n* r1 ~% F, V/ S5 Q: P( @
#define        FME7_VOL        (0x130)
/ b5 _# Z4 Z* N, F$ o- M1 e- d
; M/ v$ j! W/ IAPU::APU( NES* parent )
1 w' o# P4 T; |) Z0 q{
# J6 k8 b, o. T  ^        exsound_select = 0;
$ t5 p2 c% g6 K
+ @& j/ ?% Y/ E" X4 k  c        nes = parent;
( u' K" r3 I; ~: h  @% J1 W3 U        internal.SetParent( parent );
8 O  m& y- ]# l% {5 X- _
" O" B( p( ~2 y        last_data = last_diff = 0;
1 A, ~% q: w. ]# C+ Z$ h: f; v% {: k
7 G4 \1 F. g  e2 X4 ~        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );1 y* v" a4 {& b' N* b

3 F: {6 Q! P' J' H& E6 N% P/ }& ~        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 Z1 ?+ R2 D( B5 z( v" m. V# Q- ?, o
        ZEROMEMORY( &queue, sizeof(queue) );2 f, |6 B. s3 p+ ^3 z) O* n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ ]( U! k! q) d! E' M
+ z1 z: U; G4 c2 X0 x, ?: |8 @        for( INT i = 0; i < 16; i++ ) {
) n( r8 ]* V* d  ~! I4 M  i                m_bMute = TRUE;$ \7 `2 P8 f$ v+ s8 m/ W- R* t! m+ e
        }& x) Z/ p3 }+ ~2 |2 L: U5 _1 Z/ a
}
/ P% S0 B( k% F9 V' ]
, |: R4 W4 H, pAPU::~APU()6 c, U/ |! @  c3 e/ m# k
{
0 Y+ n7 }4 k7 b& v3 _5 A7 Q2 ^}5 r2 r( d$ I- m$ N7 J
4 c2 H, p) }! I2 ?& V
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
! w, ~7 @( f+ |) u" ^: i{% o/ ]# W- r: s! E% N2 I
        queue.data[queue.wrptr].time = writetime;
, M: p1 T. q  X6 G& T        queue.data[queue.wrptr].addr = addr;
' r$ H5 y( `: g% f+ d& N  J, h: I        queue.data[queue.wrptr].data = data;
! M7 a' G, N* W4 x. _: u: F/ v        queue.wrptr++;/ k. ]# ]* }$ R3 P
        queue.wrptr&=QUEUE_LENGTH-1;
6 b  P8 ^  m' H8 _0 \        if( queue.wrptr == queue.rdptr ) {
6 \: y  d# U0 N7 @                DEBUGOUT( "queue overflow.\n" );
+ H, H1 `- _. h( g: }* E        }' H$ z" p. b1 r' S3 h  P. I
}
6 o2 m+ N! V( m0 n4 ^8 A
9 q5 C' t: }, \4 I' q# qBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
7 x% f! Q1 N% t. h! ^+ S{
; {. S: L# D) A' ^. I! g        if( queue.wrptr == queue.rdptr ) {" E) f# c1 ^/ O& [! N& m# m
                return        FALSE;
4 E/ h: _- V7 m2 h/ W  d8 @( y        }+ o; f7 q! ~! D# K8 Q- C- ~
        if( queue.data[queue.rdptr].time <= writetime ) {8 V# s' I  `7 N- T7 C: k* X* E
                ret = queue.data[queue.rdptr];
% u; \% n0 a% F2 }- J# G                queue.rdptr++;% p, V1 _: U5 a/ {: p% ?4 r# m# ?
                queue.rdptr&=QUEUE_LENGTH-1;
% g+ y$ a* d  r) d                return        TRUE;& g. t! z$ B6 F9 q( J" q$ F
        }
" @) x& F' {% ]5 R0 c        return        FALSE;
6 m5 y% ]9 d  Z7 ^5 d$ `}
2 u$ F3 m  Q% V# c2 [9 h, I5 Z5 R) X/ x0 G& B2 ?4 q9 L
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
8 ?1 ?1 n" n& V. @{2 J6 Y7 ~  ~0 P* B( l& D
        exqueue.data[exqueue.wrptr].time = writetime;
7 }5 p2 D- q0 |4 o/ x1 M        exqueue.data[exqueue.wrptr].addr = addr;- D. y0 H8 |. M* W6 z! Y
        exqueue.data[exqueue.wrptr].data = data;
9 [8 u# }5 ~) M" g. W$ P6 `% \2 {        exqueue.wrptr++;# @# ~; U" b7 @& [  ]
        exqueue.wrptr&=QUEUE_LENGTH-1;
# `0 {7 U" ~! o1 {. X        if( exqueue.wrptr == exqueue.rdptr ) {# q$ ]* M& X! `6 N7 t/ T. o) ~$ s
                DEBUGOUT( "exqueue overflow.\n" );( d; B- g& Q- g$ I" r
        }
1 X- {( L. j- H' n" D}
# o" S$ y5 A& a3 z9 S3 M; G5 n
9 M% C% l% u" }3 mBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )" v& |8 v0 L* o$ q0 A$ U
{
$ h; d, G$ X. }( B2 I* E        if( exqueue.wrptr == exqueue.rdptr ) {2 z) X! O) s3 e& k- @
                return        FALSE;
  e2 Y. t! ~* i$ W0 l/ L! `8 ~        }
% u4 d6 Z2 B7 b. {        if( exqueue.data[exqueue.rdptr].time <= writetime ) {0 q) v9 _9 L! q
                ret = exqueue.data[exqueue.rdptr];) T( L# M+ D( K" W
                exqueue.rdptr++;; G- f  V! C  E" B  D2 |
                exqueue.rdptr&=QUEUE_LENGTH-1;
  P7 T- R7 W- Q9 X# W9 `                return        TRUE;
8 b! ~# [" C' ~: J% ~6 D8 j$ o; a        }9 O4 w4 w6 c; J% {( _
        return        FALSE;6 n9 g4 q  o  w+ X* J
}1 k* p. Q! f5 ~& |1 d  N" |

; n; _3 V2 `3 B) N& B; Rvoid        APU::QueueClear()& k; i1 o7 l  w) ?6 ?9 x
{7 K- l  ?0 y+ X: I* W
        ZEROMEMORY( &queue, sizeof(queue) );
' N  W! {* C2 Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 o! C) E, B% y9 d* @/ V) N) i
}
  x2 B. o5 J$ W: \! \' B! t6 V2 ~8 C; @0 K& B; \& o" A/ F% o
void        APU::QueueFlush()
0 K# G* `  Z9 w& g. X; Y{
6 o1 y2 }2 q, Z9 I5 V0 o. \        while( queue.wrptr != queue.rdptr ) {
6 ]! _' a+ p$ F* Z                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
9 M0 A8 o/ A! d6 z8 i  n. M6 ^                queue.rdptr++;/ o+ F, f! a; {' |
                queue.rdptr&=QUEUE_LENGTH-1;; {3 L2 I( u2 A- ]; e' ?
        }, [" A: u) C$ E, V/ y$ K- w" ^0 z

1 }5 W% R  i+ S$ q2 H# W% c- L6 o        while( exqueue.wrptr != exqueue.rdptr ) {1 y; c5 \5 ?* C! C1 x- `# r6 {1 j# k
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ i. _. H/ w7 e1 X" a- [, X                exqueue.rdptr++;/ I% Q* F' b* K  d& l2 d
                exqueue.rdptr&=QUEUE_LENGTH-1;
6 q1 {  ~; R' f3 r# i  ~6 ~$ Z2 t- A        }2 a0 M+ g  f" a+ @( X8 r
}4 w$ _6 M! G* C6 \

) W! H8 j! N! O- F1 |! Kvoid        APU::SoundSetup()1 P: l( u" X' S3 R% i
{
6 E6 i8 Z# f- ~3 X        FLOAT        fClock = nes->nescfg->CpuClock;
; E  _7 n" n/ K3 B# s5 P6 _; o- l        INT        nRate = (INT)Config.sound.nRate;
4 f- ]/ Y9 ?) ?) K7 [: P        internal.Setup( fClock, nRate );- K+ T: I( q+ c( x) b9 P
        vrc6.Setup( fClock, nRate );8 H3 q& `! k$ @4 l
        vrc7.Setup( fClock, nRate );2 j" h3 Z& t! \& D: h. \
        mmc5.Setup( fClock, nRate );% O* k* x. j& Z" N2 v) Y
        fds.Setup ( fClock, nRate );' b: d; K! T, [6 u
        n106.Setup( fClock, nRate );
% q5 `: S+ g( y0 D8 q: A9 r9 y        fme7.Setup( fClock, nRate );8 E% s7 m7 x5 P8 A, D, Q, `
}8 c9 ~  N; ^/ `) |
: a0 U1 \/ a) t) e: M. @2 n
void        APU::Reset()2 u# k0 q) z( c
{
$ S' |+ S4 E2 i* U7 C* o; L        ZEROMEMORY( &queue, sizeof(queue) );7 r( N0 X/ B1 a/ A
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% g0 k" S) Y: ]$ G) _3 A* p" J7 p: N0 N1 m4 D! h: N3 F: ^
        elapsed_time = 0;
) e$ i" }+ h" K6 ^5 z
; s* }- f) s  B$ }        FLOAT        fClock = nes->nescfg->CpuClock;2 }3 E8 k8 k9 o
        INT        nRate = (INT)Config.sound.nRate;0 U! M; R, }9 g2 x! a: H0 b
        internal.Reset( fClock, nRate );, h7 z3 i/ ?2 L* @' G4 G- D
        vrc6.Reset( fClock, nRate );
3 v* T: V" @: q        vrc7.Reset( fClock, nRate );
+ C, R7 E# W5 m3 G# s) Z  b/ B        mmc5.Reset( fClock, nRate );
" \* H  I8 R/ f+ d! m        fds.Reset ( fClock, nRate );/ s1 v/ j. K& Y, e# W
        n106.Reset( fClock, nRate );2 ~; ?; }9 r4 N4 Z! y
        fme7.Reset( fClock, nRate );/ l# p2 ~$ ^6 V

8 e' i/ r/ U3 v& T        SoundSetup();1 h" J  C' g$ a/ V, M
}
+ a: @% _$ Q4 |+ M" H$ |' }; }; W' _& u9 A
void        APU::SelectExSound( BYTE data )4 |. k0 X4 |0 v& Y8 H4 Q
{
* w% `5 Y7 V7 u        exsound_select = data;
' T" P% d$ c' v% X* X3 T}
$ c; i! X8 k1 W9 B- x; g6 I
& \7 V5 ]: q7 J) v9 ]3 bBYTE        APU::Read( WORD addr )/ m4 J, Z6 o$ K% ]' I/ [* p
{
1 d1 A' u+ h7 `, ?. U        return        internal.SyncRead( addr );
. y: f! d) k0 ?}
4 {; [9 d, O5 z$ a# I/ l6 N# E* Z' c# c+ X  K  w
void        APU::Write( WORD addr, BYTE data )
  u  z! L- [" Y$ y- M  w{, b9 \8 `% C7 x) w0 t+ J, v1 V
        // $4018偼VirtuaNES屌桳億乕僩3 P7 v0 u9 k, H
        if( addr >= 0x4000 && addr <= 0x401F ) {
# ?* V( z, Q$ J: Z: L* X                internal.SyncWrite( addr, data );
( O$ C- x. R  r- X                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
5 f/ o9 S3 q" K0 T" X  B+ P        }1 H/ ?; u. P1 Z( ^
}
" K; |5 _  d) s$ Y* T+ V0 R: f0 O: V  M1 f& c% B
BYTE        APU::ExRead( WORD addr )
- d3 O" P7 w4 d0 j. y{
( z, k  d" s* e4 [( i( [BYTE        data = 0;
' Y3 O, T% A& w% I( h9 O5 s* ^2 Y/ D. z  d6 I, v5 D8 w% h
        if( exsound_select & 0x10 ) {
5 S) i# v) {1 ^, P                if( addr == 0x4800 ) {
% Z( ?  L' V0 H6 t2 ?3 M5 o: F* U                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );0 I# f7 e8 [% z) K" G1 W
                }' f5 A% u& E  i! r2 [" A+ H6 r
        }# E) _% u. R* j9 C7 h( g  L* k
        if( exsound_select & 0x04 ) {2 @3 B4 H  V2 f  a1 s
                if( addr >= 0x4040 && addr < 0x4100 ) {$ _5 J: `4 e6 O; W; H- L
                        data = fds.SyncRead( addr );
' Y3 G6 M7 @' l) Q7 |9 M' E& O1 O                }+ i+ I, f$ v, o- D+ T  Y% n
        }5 J$ A2 d0 l) Z* Q2 W9 I
        if( exsound_select & 0x08 ) {8 K2 V0 G9 s8 u9 e7 V/ i# l5 {+ H7 s2 G
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: I. P, @& Q& ~  K/ E                        data = mmc5.SyncRead( addr );
4 ]9 t) k9 m, y; a: \/ b! B. @3 d                }
) E2 A! Q- V, |9 J        }
9 N9 t+ N5 o) p/ ]$ D) ^3 C
1 I% Z9 R0 M- E, Q  h9 H* f        return        data;, t: t3 [+ h% v9 e3 f# i4 I  o2 P# k
}
% Q: R2 i5 @  x$ P5 _3 d
9 \4 {  ^/ Q9 O& R5 vvoid        APU::ExWrite( WORD addr, BYTE data )
4 A; X9 l& n! ~: j( e{
5 s5 |: ?) X. n1 g) U        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" L4 l% Q* _- u
1 C5 E+ V: k: W+ T' H        if( exsound_select & 0x04 ) {4 a2 e! c: f4 w0 K
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 f* \" ]# v/ q+ V                        fds.SyncWrite( addr, data );
& f$ Q* ]1 D! F  y; M, Y) R  b1 p                }
& A9 X, g$ a' O8 u7 B3 A8 o        }
0 C1 H* b& g! l  _. O! X% E0 I) ]
. S3 t0 @+ i4 |/ C8 B5 W        if( exsound_select & 0x08 ) {& z' B: a- }/ H3 Z+ p
                if( addr >= 0x5000 && addr <= 0x5015 ) {$ R) L/ @7 d4 [
                        mmc5.SyncWrite( addr, data );
; r! g" h( k/ O, j! }  h                }" O) i% c* n6 J
        }
) ?  m3 d( K. D5 ]+ W}
4 s6 w0 Q* k- G3 g+ h. J
+ ?9 i  H) q9 A0 p" g! u/ u7 \void        APU::Sync()5 o( x1 M4 G) k. R; m# D7 @8 L
{2 s! B( M3 ^0 Y3 o) o. o4 l: V: Z
}9 ]5 d  Z1 Z+ e' q1 D

$ }/ \" d0 T6 `1 h" hvoid        APU::SyncDPCM( INT cycles )
+ W+ n1 v$ a! [5 F{
3 i/ `) x( o+ z; f. _* M" r        internal.Sync( cycles );
" l  N% l0 p( M
+ D) }# Q- V  M( \4 _        if( exsound_select & 0x04 ) {
3 V; q$ t* c/ [8 G5 |4 M& X                fds.Sync( cycles );: x3 ~+ a( l- K. |' Q
        }7 u+ l! R' q7 M, ~+ t
        if( exsound_select & 0x08 ) {, W7 B& e# L, N9 P6 L& x
                mmc5.Sync( cycles );* ^9 q7 B1 x$ G- Q" V* _
        }
) ]2 N# c9 v6 }& Y+ K}
$ V8 ]6 k( H) Q, {
, l' V" ^6 T2 ^% k/ Svoid        APU::WriteProcess( WORD addr, BYTE data )0 W2 \: Y5 |7 K7 M: t  N0 D/ j% k
{8 i8 t1 `: f5 W' U) s
        // $4018偼VirtuaNES屌桳億乕僩$ d" h, q6 \/ c9 c* ]7 @
        if( addr >= 0x4000 && addr <= 0x401F ) {/ G8 o& N3 N7 e
                internal.Write( addr, data );
# _& `; ]. ^+ `0 C. P; H* e        }
% Q/ k% n0 y9 |  h+ @$ A}* ^" h  c* h" |+ _
4 W' k/ A0 y' v- f
void        APU::WriteExProcess( WORD addr, BYTE data )! o) |# J+ f3 M) E/ y. L- k, }
{
0 b9 z2 ^% i! D4 |8 v        if( exsound_select & 0x01 ) {# p" ]& l5 D# }+ G& x% M/ z$ G
                vrc6.Write( addr, data );
" U8 m1 i* g  \! L9 O        }# L8 |+ W  N! h: q$ x
        if( exsound_select & 0x02 ) {
6 w; t- i/ D  r  ^8 n. ]                vrc7.Write( addr, data );9 |1 I: l9 Y; }& d2 L
        }0 `( j) ^) m5 |) Q9 y: r
        if( exsound_select & 0x04 ) {; }8 k  w$ U. V4 M+ G$ X
                fds.Write( addr, data );
5 }3 }- Y3 P4 C        }
' ^9 o# d/ r; w5 ^5 R# h- L' P        if( exsound_select & 0x08 ) {7 Q5 y- o/ }* w
                mmc5.Write( addr, data );  X% c; z4 p' _  @
        }/ s0 F" m% d% y7 J4 E
        if( exsound_select & 0x10 ) {
9 Y$ Q% p( C* d) O                if( addr == 0x0000 ) {0 L" M7 T% A6 V& o3 m# j
                        BYTE        dummy = n106.Read( addr );$ H( }" U. ?0 W8 M
                } else {
7 M7 E& x6 W4 |5 ?3 `( [2 W. w( g                        n106.Write( addr, data );
, ?# d, B! U' ^/ G6 \7 g" e/ m- m                }7 b; x" t7 M& s4 L
        }
- D3 g# q3 [+ G- z/ H% p" u, [        if( exsound_select & 0x20 ) {8 R' F9 w+ _# w, f/ `
                fme7.Write( addr, data );
1 t  g, F& O( B: u/ f; _        }
% `7 u4 E! [$ G( d2 ^8 x}
( Q! W4 C# K& [0 _& a# P
7 }  N( a- I- i7 B7 ?2 Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
( U, S$ z  h9 i# M{! D7 H$ h! d: O' N
INT        nBits = Config.sound.nBits;1 C3 ~$ d  ]7 I  u& `" k
DWORD        dwLength = dwSize / (nBits/8);' ^1 j1 y' D0 c  c5 s4 X  F$ j
INT        output;
/ ?/ ]* ]: f$ ~7 x; i/ iQUEUEDATA q;% P. k6 r. t9 l1 e' s" x: E
DWORD        writetime;1 y2 Y' `8 a+ W: `2 L# Y2 W( S

9 Z1 a# w; }% z! }  i% cLPSHORT        pSoundBuf = m_SoundBuffer;' @) T% n  K) D6 u
INT        nCcount = 0;
* P! k/ r) w, m9 q' e) h, d6 \) b$ j& g+ ^
INT        nFilterType = Config.sound.nFilterType;
/ C7 R8 R3 s2 O  E; R) Z$ x5 C% |: U+ M/ g
        if( !Config.sound.bEnable ) {% P2 G! S4 U; D
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, U9 g# |! J9 s& ^$ w+ L8 t2 Q: O0 i                return;
' x, B; Y7 \/ x' f        }5 g0 B1 k8 u, w
' f% Z$ H/ H; |) S) T$ s
        // Volume setup
, ~: @2 h$ t. j" A/ \- `        //  0:Master. \! _2 D: v9 x
        //  1:Rectangle 1
# w" Y, u. G; y        //  2:Rectangle 2- o1 M/ ?+ Z" {9 R; \' d
        //  3:Triangle
0 W; d% v3 ?/ \# @, O        //  4:Noise
4 W+ f+ Y9 I% a# D0 x) S        //  5:DPCM
' z, c/ b% Q& F$ a7 [        //  6:VRC6
5 f2 J$ F2 Z9 x; h        //  7:VRC7
+ G& b7 l  p, Z- m' _, c$ t        //  8:FDS; W9 Z" O7 I; W2 u" h
        //  9:MMC5
) b: t$ ~* G0 Y6 {' [        // 10:N106! F9 x: c/ ]# @+ _
        // 11:FME7
4 L' y" A* l, N( \% o0 S8 q, ?        INT        vol[24];
, |; U# H3 q4 f& E3 c! Q        BOOL*        bMute = m_bMute;
; g% i  F3 y. v+ ]( Q# g- j) \% ?% G        SHORT*        nVolume = Config.sound.nVolume;
5 O2 |5 L1 C% \- n! U* z+ a- Y8 [: N; `( T; D/ Y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
  H- S* W, \' }1 \; C$ j3 D& L7 T3 G: p- l# I; s+ l
        // Internal/ [4 O) ^, a+ R+ C
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 a* c: h9 q' j) T
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
8 ~# h9 N( P/ ?7 S' I- W5 q        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;) b8 B& b- H" k. x( o
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 d/ s0 M4 r* V% n4 k: i, ]0 \        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& x3 [& g/ X; z7 }  h

6 b; X' v6 R* G. W& N% g        // VRC6
5 U+ o  e4 Z* t6 F. S        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* m; f! s. D" Q2 _& d        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 E# `+ |$ H+ L: M% U1 Z
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 V3 T, C" x, E. G7 w
3 R5 s2 z6 v4 ^1 T6 T& B& N! G        // VRC7
% H$ d9 C+ s$ j3 Z% N" G        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  ^4 E# e5 h3 O& M7 h/ x& K( `
  w" ^' u! |( C% F& u- t4 s        // FDS' s4 R* D' ^5 B9 k
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;- L. l& B4 F; h! F- L

' X; G; S/ n5 U% ]- J        // MMC5
; l6 u  ?$ s/ T: a# n& C. m        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 h1 J8 E; @' ^        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) U- `. n2 }$ c. @
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 N! k  W/ m7 s( @3 Q
, m  @& @- A/ c- M, ]
        // N106
$ g$ c8 l/ J9 Y1 w7 c        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# C# \1 B- W. q% ?9 \4 c1 p        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; I* |, d% a( Q        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; q& ?- J# ^$ M, y" X. b5 ~2 T
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 I7 |+ V5 w$ u- U& o9 |, I
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: W. x& T$ @# ^  e1 }# j
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ h$ t% O7 q9 l" s) z# U. U        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: [9 s* ^: o6 m        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- _3 I* t4 C! g" f2 m  A) C. ~6 A6 g
        // FME7! o, g3 K2 z3 Q6 n! F& M4 u
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. @( s0 ]& J: }$ y1 f0 m
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 [4 \. x& [* W& \: ]/ V
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) {# J8 E- T6 W5 B' X7 Z2 b# V
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;* v0 W. E9 t/ ~# ~8 S: m
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
6 _" {( A2 V0 l3 W5 H* x- W2 R% ^3 a
9 N. ~6 a1 e# k  d/ w6 K; l  i$ w' D        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 d6 e! F2 V2 R4 H        if( elapsed_time > nes->cpu->GetTotalCycles() ) {, g2 c# X- v# Y; V- s& w9 d
                QueueFlush();
9 K. v$ e2 `0 N; e; v        }
: q5 u$ Z; d8 u" d0 r
$ R" K# y$ N# v  z, d; g5 ~, N) g1 I+ A        while( dwLength-- ) {
+ a; f* M5 ]$ V" f4 R                writetime = (DWORD)elapsed_time;
% l" t4 O9 ~: I) ^3 O5 z
+ j! k& F+ ]0 W0 I! P6 }                while( GetQueue( writetime, q ) ) {
7 x, ~# q1 C- I7 S( G5 i8 N# x                        WriteProcess( q.addr, q.data );
  k7 ?8 k& j2 Z! K                }
9 m4 {1 V3 a6 b7 H. D' h7 s' d) ]7 F6 g) D% m) c/ h
                while( GetExQueue( writetime, q ) ) {; I. I! B% _4 r) c+ N  g# S$ i
                        WriteExProcess( q.addr, q.data );" B3 F! {! W+ p
                }
+ c2 u2 O5 x5 y2 J3 c, u- t/ a" l* E1 i+ u
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ v+ l; `6 N/ `! ?$ J6 B3 T2 Y                output = 0;
: m$ }" W  G' z! o                output += internal.Process( 0 )*vol[0];0 \/ a( O3 f1 p& w1 A
                output += internal.Process( 1 )*vol[1];
( B( j- E5 d2 a( E                output += internal.Process( 2 )*vol[2];
1 A% O; Q3 f, h6 _$ z                output += internal.Process( 3 )*vol[3];
4 L8 o2 e! Z  W) D                output += internal.Process( 4 )*vol[4];, c; W7 `! `! r3 D* R, J+ T) I7 R

+ [; {* T0 l* I" J0 `. E* Z" b                if( exsound_select & 0x01 ) {
, G' U0 Y5 u7 `  P5 n/ ]4 i                        output += vrc6.Process( 0 )*vol[5];# t$ f. e+ Y; r7 N" z
                        output += vrc6.Process( 1 )*vol[6];$ Q% Q2 }: Y7 q9 T- v7 v8 x
                        output += vrc6.Process( 2 )*vol[7];4 E, P* {2 {& h% A
                }+ v0 d( k* G/ |
                if( exsound_select & 0x02 ) {! V8 F& ^" f" W) e. \
                        output += vrc7.Process( 0 )*vol[8];7 C5 H  V1 w& N5 p
                }
9 f# B& [' D2 {2 D7 ^8 G' o4 h- s4 Q                if( exsound_select & 0x04 ) {
3 O( A* ]4 Y. Y3 j9 }5 a6 V                        output += fds.Process( 0 )*vol[9];
& z0 o% v8 ^5 y, w                }0 Q. f3 P2 L5 Y; ?$ z
                if( exsound_select & 0x08 ) {
& \* U* q9 _  @" y: l                        output += mmc5.Process( 0 )*vol[10];1 r0 o8 T  m5 V  K, z6 n) r
                        output += mmc5.Process( 1 )*vol[11];( x* B( C3 F$ X% S4 @& ~- F; W
                        output += mmc5.Process( 2 )*vol[12];
2 e- H; @+ d! p                }$ ~4 U! H+ C! @" d: n
                if( exsound_select & 0x10 ) {8 p* ?1 Q. P9 D, T. h
                        output += n106.Process( 0 )*vol[13];) j6 K, b4 J: `
                        output += n106.Process( 1 )*vol[14];) Q1 t% l: G% b( D
                        output += n106.Process( 2 )*vol[15];* T2 T, t+ \  ^1 S5 x7 K
                        output += n106.Process( 3 )*vol[16];
! w% h7 _7 U& H; E                        output += n106.Process( 4 )*vol[17];
0 I. E1 @2 }! R$ p& d                        output += n106.Process( 5 )*vol[18];. X+ [7 ^! ~3 Q) j
                        output += n106.Process( 6 )*vol[19];
; T+ K1 r+ n) ~                        output += n106.Process( 7 )*vol[20];0 G8 D) a8 A' U6 ?% F; s2 z5 D$ f
                }
8 n% a0 M# L5 f6 ^( a& l  Q                if( exsound_select & 0x20 ) {% b9 v- e) T4 w6 {/ L
                        fme7.Process( 3 );        // Envelope & Noise
; R& Q9 t  [+ h7 d: n* Q1 }                        output += fme7.Process( 0 )*vol[21];2 l7 y, f5 _. j' H; o
                        output += fme7.Process( 1 )*vol[22];% `5 Z. \5 L' F! O0 h
                        output += fme7.Process( 2 )*vol[23];
. Y" D* o& m* z/ D+ U5 j                }8 _' k' J& f4 v4 J; I: H
2 V& R5 |0 ~! O* X' B0 [
                output >>= 8;1 i5 H) |: i8 q2 F% F

) o$ M+ ^# M' u2 P5 u" v5 u7 N3 Y                if( nFilterType == 1 ) {4 p& E5 j; _  L- a3 L- [  S
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, q. |9 n$ \$ X. ^) V" a                        output = (lowpass_filter[0]+output)/2;* t" G. G0 d% p/ q  l& n
                        lowpass_filter[0] = output;
1 E% e- J' H& R                } else if( nFilterType == 2 ) {
6 a: c$ C) O/ P                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)) t+ @& c: H, N: T- }1 ]4 h
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* J8 Q# n2 P2 d) a0 U+ N
                        lowpass_filter[1] = lowpass_filter[0];( l. R2 x+ W3 A# B+ f8 Y
                        lowpass_filter[0] = output;
! e, u$ S# c- ~8 [3 z/ }7 Z                } else if( nFilterType == 3 ) {
9 f- s( A; S4 [9 L& Q' S                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; \  E8 U) |; z6 J( c                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 ~( z! K8 P' b& r" s8 j                        lowpass_filter[2] = lowpass_filter[1];
2 S9 D8 Y- _- b6 C% d6 q                        lowpass_filter[1] = lowpass_filter[0];
& f- }1 Z! G+ p5 L' ^                        lowpass_filter[0] = output;
4 w9 c, X. l  k9 U( V! J+ p* p                } else if( nFilterType == 4 ) {% Z- u$ r3 S' Z9 p6 [$ Q
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)/ s5 |* b2 o& s( H; K, U& q0 Z6 P
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* T' ~: F8 e/ c" f# }0 L3 G                        lowpass_filter[1] = lowpass_filter[0];' ^" S# T# [7 {9 W
                        lowpass_filter[0] = output;* f: @9 b2 l( o! f- m8 }/ N# M
                }
4 O6 i9 _  s4 d& W0 c* T* a* `9 h2 S8 J  }0 W9 l
#if        04 k. ?0 e+ z5 O8 `( J, O. T. C
                // DC惉暘偺僇僢僩4 Q+ C! c8 o) a- C1 }0 F; o: o
                {' g  S) ]) B0 y, x1 O
                static double ave = 0.0, max=0.0, min=0.0;
# d6 P+ {0 p; w& Q3 t  Y: M' ]                double delta;2 }  U5 b5 T: S4 w
                delta = (max-min)/32768.0;
" e. |, E; h# v& r                max -= delta;, k( q0 N+ n. ]- V* n
                min += delta;
! L3 T% [* r" N8 K7 M5 s  o" V                if( output > max ) max = output;
5 {2 F, p3 D7 @                if( output < min ) min = output;
- h' {* j: f  a6 P4 \; ~0 G                ave -= ave/1024.0;! R2 Q. V# o8 V9 u* d2 \8 M
                ave += (max+min)/2048.0;1 w2 D8 X  F2 ?
                output -= (INT)ave;- f2 G% J6 J/ W0 G/ b1 {
                }5 H9 g9 y. b$ a8 P1 X% D
#endif8 f& {  l$ O1 ~7 A' w
#if        11 q" h% T% J# [+ N; `, R
                // DC惉暘偺僇僢僩(HPF TEST)7 [/ N1 y; ~* U3 z0 Y9 M
                {4 Y: {1 W3 r- S2 I
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* q  M( h0 u: B" Y. ?6 d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
3 u8 }1 b: ^9 Z9 l6 @                double        cutoff = cutofftemp/(double)Config.sound.nRate;) c- g- k4 ]1 {* j, r4 E* x
                static        double        tmp = 0.0;5 |) I, J. U0 I& f3 q2 }( V
                double        in, out;6 u6 u0 }& N+ y  y2 C% g2 x

- u' h& ]7 Y7 d. L                in = (double)output;9 T. P% U* {5 r' ?& _0 |  R, D
                out = (in - tmp);; g9 e2 `. q  r, z4 J
                tmp = tmp + cutoff * out;+ p5 B; ~0 [3 F# F  _( Y9 Z  n; I

  E# Q$ j1 Z, X% l1 I                output = (INT)out;1 P& M5 P5 m/ z, x& m9 C5 H$ a
                }
3 E6 Y$ Y# Q# V/ j; l9 e- z#endif
5 h2 P" |  T" y, A3 ^- S) T#if        0
. Y. q3 |8 }- q9 V+ ]6 q7 ]                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)0 Z: D" B; x* F  R8 q! y2 _
                {/ j; _# i. x" l9 E( i. q/ v
                INT        diff = abs(output-last_data);
& t" L/ _; e# ~8 r/ o7 z% Y, l                if( diff > 0x4000 ) {! }& I5 M7 s$ T# m1 I. K
                        output /= 4;
: E& G/ X0 M7 q1 w+ U" a                } else 4 `% }0 k( H3 T( U( V
                if( diff > 0x3000 ) {
0 q. U+ ~# j! C$ C, i                        output /= 3;
, {  K$ ^- f. i" H+ q1 ?' F* _% h                } else
: p: x: u) s( B: g% W/ ^7 Z  w                if( diff > 0x2000 ) {
# M) @" Y8 h9 |) D3 `                        output /= 2;
) k9 j( }: j' o& a8 T                }
$ J4 W+ z7 N! P7 E0 L                last_data = output;  K% {+ G2 \" W$ p. r* M
                }
; Y; m/ e/ L& u3 p; H' r0 ^5 I#endif
$ z! w& P% I' f! a( g" R                // Limit  M8 W  }& ^- s! a
                if( output > 0x7FFF ) {( l1 Z3 V3 p& C
                        output = 0x7FFF;# j7 ]4 e! r# x* P5 z
                } else if( output < -0x8000 ) {
2 T; |% A1 V! |+ y                        output = -0x8000;3 y. c4 S; _7 c( ?" ?$ K! j
                }
$ f8 y# [5 ]& z5 x5 b
7 `2 S, B; _* J# C( `                if( nBits != 8 ) {
1 E  h3 y! H; @3 j$ _                        *(SHORT*)lpBuffer = (SHORT)output;
$ G4 ^# o/ A  Z3 n) J' m9 k$ S- n                        lpBuffer += sizeof(SHORT);
5 v4 |: W9 S8 a8 p$ F+ m5 J                } else {# F, u  y) V- R. ^8 E
                        *lpBuffer++ = (output>>8)^0x80;
" J/ t) Q. B$ j6 T; h* F4 `                }
- |: e5 y, A* z. \% c* d/ A! P' F9 e9 g8 R- }- f. ]0 z" i
                if( nCcount < 0x0100 )
3 L% z3 Z" W  e9 o7 q                        pSoundBuf[nCcount++] = (SHORT)output;- \4 P& K, x( p5 F9 v
4 Q- n2 N0 ?5 w( u6 R
//                elapsedtime += cycle_rate;( S; p- c" j' ]1 [4 k+ S! g9 P8 B
                elapsed_time += cycle_rate;, }2 \+ b' {" {& T  `' `2 b. C/ R
        }, y7 m8 H9 \0 N

# p3 w  F2 g  ~6 j5 j$ l4 n#if        1
: d" i4 ]% X& V6 _9 R3 A0 w        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
1 U0 G+ n. \" [& ]! @7 {' a                elapsed_time = nes->cpu->GetTotalCycles();  S. }8 i$ ]9 f0 m5 E
        }
/ R4 _- ^3 {8 W0 q2 A; i! l        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
6 a6 }8 N. A) u8 n( [* c5 }. A7 I                elapsed_time = nes->cpu->GetTotalCycles();/ P' l: W1 P9 v# }- C1 R
        }
4 _( F0 F0 E5 E5 A8 X$ p7 ]#else
. a* f2 p9 J: S" v4 m        elapsed_time = nes->cpu->GetTotalCycles();
# \) |+ E" c; B: `6 n9 M#endif3 w5 M. i! ~- v( g  e) \3 b
}! _7 d3 H$ Y* ^

6 k& g1 _8 i  F# l// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
6 U7 ^- m" t0 c+ p8 r  V! ?INT        APU::GetChannelFrequency( INT no )% |# s( N0 T1 j- R) |4 M- f* Q
{+ M: n9 R3 l7 v' s7 V& z$ x  ^
        if( !m_bMute[0] )- r( c& {$ v, f, A) ?3 P
                return        0;
& d9 e$ H, h& p$ k1 U% g: J3 {2 H  O
        // Internal
, k2 N0 V! f; f7 {' K# q        if( no < 5 ) {' B4 u# S! M% i! s' m2 a
                return        m_bMute[no+1]?internal.GetFreq( no ):0;, U; f" g# M* U' a
        }& ^) G: c' k0 U$ n  \$ Z
        // VRC64 W: v! W6 t9 H; S
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
. T+ |( _2 u; t2 m3 V# Q7 n                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  B+ i6 N3 n) C
        }4 t4 o# t( ^- g* ^9 p. L/ x
        // FDS9 [. x# P8 |$ {; z* c- ?
        if( (exsound_select & 0x04) && no == 0x300 ) {7 V' F: g9 a9 s4 T
                return        m_bMute[6]?fds.GetFreq( 0 ):0;3 A" P& j! A, Y) Q, \
        }
: |- y$ Y4 Y( F7 U+ h        // MMC5
" X( J, R5 i+ y' C        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {# J. S$ K6 q* H; c: K! z8 t
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 y2 G+ A3 H4 F$ N! v2 f
        }2 @4 k% {# u# a
        // N106
1 o3 y( i) c  X        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" X2 G3 N. r/ g2 x3 {" w6 T                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
( `0 ~" K' ?0 X; i        }, Q. z6 E5 {5 J4 f- o) X
        // FME71 D* D+ c$ w4 a% _8 ]% T( j
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" E4 L9 v. m" Y5 @, ~+ \3 q                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
2 e" B6 h9 [' f4 d        }2 Y: W6 ?% G, Y  C* e# `0 N
        // VRC7
2 _7 c/ R* q0 A. X/ c+ g, a! j9 {        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {6 |! f, e4 s% g* H' E( O
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
( Q$ l+ O7 y# T( g( O- m5 `" {/ L        }
. L. ]! y  x8 C% q) O% J        return        0;2 ~" t( w! u, ]" k9 i7 ?" J" G
}- C- D& O0 h) |# ]: w

+ Y, S9 e( I; w7 i( h  ^  u$ X  Q0 y// State Save/Load' f1 e5 J! m; u: ?) e8 L' e# g' q% g
void        APU::SaveState( LPBYTE p ); M! ^( }6 y1 E$ X
{; d3 L/ m" u' X5 i; R+ h
#ifdef        _DEBUG
( P' N( _( t% P" N$ u8 V3 ]LPBYTE        pold = p;
# a; I  J8 p. E1 C, N0 S2 T: \. x7 U9 R#endif& h4 |9 a6 I4 O* }

8 j0 k* \3 g& O. b9 v, ~, t        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 w7 O( K% n' q) j- D" `        QueueFlush();
# _8 @# F/ s! @, G# b! E
7 i5 m2 J6 u5 s0 o" h' \        internal.SaveState( p );3 n. h+ e: S  P8 i2 d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 ]1 Q7 w" N# ?1 @- n2 O  z4 Q$ i/ M- u$ z% @
        // VRC6
6 J( s* X1 }& Q5 u0 k# Z* I$ {$ I        if( exsound_select & 0x01 ) {
  H: s: w* ~+ w1 C                vrc6.SaveState( p );5 P+ d, E3 U; H& s8 K4 m/ g) Z; s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; U3 S& ^# e, T        }
( Q3 t9 x3 S; \/ o2 M4 {, V        // VRC7 (not support)+ g$ |/ b: c- j* e& W
        if( exsound_select & 0x02 ) {% W6 }8 D; A* C7 o/ ?* h9 q) x
                vrc7.SaveState( p );
4 v8 X- U; O' s2 w  s7 z0 D+ _                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 T4 o: a, U) h7 n        }
- }* T, \5 X2 }! ^+ [" M/ p4 _        // FDS
8 w/ @# L) q( `, C& J- }        if( exsound_select & 0x04 ) {: E0 e4 m8 s$ [: U$ `! ~. d- E
                fds.SaveState( p );
* ?. d' I& L2 O; ^$ e0 S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 y0 p$ o+ ~$ V8 I
        }
) K% {0 ~8 K8 B9 `  t) Z9 ]# P# z. O        // MMC56 p; r7 e9 m; V7 z3 o2 R
        if( exsound_select & 0x08 ) {
7 ~* G- ]: L% N                mmc5.SaveState( p );
+ H: u  c: ^* K" V2 g0 ]0 m+ I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- l7 }- z5 A0 g! s7 H        }6 f* ?; p8 h: y$ I7 d: n" o
        // N106. W. _) \' Y8 G- z
        if( exsound_select & 0x10 ) {
% v. ]/ M5 D' e; m1 S" T2 W/ w                n106.SaveState( p );8 H) {3 L* [( h
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 i+ {0 G, s+ G' `1 K6 Z% h        }: `6 W, u; W2 a: K: s% t9 e% Y
        // FME7# L& R! Y8 s* F  {
        if( exsound_select & 0x20 ) {) l' a1 u' q0 @( y" ?- ^
                fme7.SaveState( p );
7 a0 b( \: B) M, E. |' {                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 ^1 Z) S3 _- [/ x        }
8 n* z' @; u4 `) E+ Z. K4 [' ~) U) _7 R6 v
#ifdef        _DEBUG
: H0 Q& k6 A3 J5 h6 p  W" _  E6 ]DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 \; K) {& Y5 O; s( e. R
#endif; S8 Q( ^" _7 \3 N& ^
}
4 P9 s) q, b. o/ d. F+ W: y' H" G
void        APU::LoadState( LPBYTE p )
0 U; N( C, I# s# ?. ~{, P! o8 @+ K* R% J6 G1 |" @
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 ]/ S: t/ B, C7 k0 z        QueueClear();
2 W7 E& i9 t2 {
- m& k% \: M7 d( ]* L# s        internal.LoadState( p );! ~0 ?7 _% P: T' ^2 S; H
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding* H8 i: v% u! y9 h
7 ^4 f' s! B, J5 q4 Q
        // VRC6
5 R- ^7 L  J  o5 \( f: G* q        if( exsound_select & 0x01 ) {
/ r4 {+ i1 E% |8 H                vrc6.LoadState( p );
) F  L% k: k) `                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 _/ T+ Y7 I# B        }  Y, |1 x" R: H0 R8 d: u4 h
        // VRC7 (not support)
  g/ J2 R  U% r2 Y$ O- b        if( exsound_select & 0x02 ) {, [( H! t' P, Y. Z* d" F
                vrc7.LoadState( p );
& v$ I( K# H$ t& z8 t3 {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- o) P2 J3 d% U0 F/ i        }
$ b, ~; I" S9 O) g! P2 ]9 u        // FDS
, m/ W" k4 {& k) X  B1 l7 w        if( exsound_select & 0x04 ) {
3 z/ G# u. I: ^( Y/ J- z8 ?, Q                fds.LoadState( p );& q) v  |/ U& _( q3 g
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ g% Q% f5 K1 [0 K; `        }
9 C, t$ U+ Q$ r+ K$ V        // MMC5& `+ f* y6 \' H/ y, S' X
        if( exsound_select & 0x08 ) {
5 g& k& _* Z$ ?( c3 Z6 m                mmc5.LoadState( p );' I/ w4 [( Z$ ]$ _
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  [0 u3 P, I5 D* }+ z
        }
3 A/ P( D2 K) {- s( y+ F; X1 Y        // N106- @* k5 n6 Y' Q7 x' p. Y
        if( exsound_select & 0x10 ) {$ z8 C$ D1 g, b( |6 S
                n106.LoadState( p );" _- n0 d& M4 Q; X. y2 J$ y4 t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 Z6 C7 ]3 }: v% `) V+ t        }
' ^9 Q) v, m5 k2 r- j% T        // FME7- D( x  L2 B7 e3 h+ u3 ~. z
        if( exsound_select & 0x20 ) {
( E* B! Q# i9 c6 [                fme7.LoadState( p );) x4 z9 ^1 h1 c, o
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 E7 s. i* a0 o8 ?1 z. e
        }
1 `( z3 G: q4 e}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& ]" U3 |) O2 v+ X& ^0 U  M4 o7 F可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 ^" e# [4 i+ J9 R% w7 j感激不尽~~
/ U: ?/ L3 `! P8 a' n
恩 我對模擬器不是很有研究,
  e& S0 w! K: x  S6 z9 D雖然要了解源碼內容,可能不是很困難,
3 l* l* k2 J' Z( o5 M! i不過還是要花時間,個人目前蠻忙碌的。( i! T1 E3 H3 Z5 i7 M9 ~. R# O
6 [" T8 W, Z7 I* m: C9 m" @* M
給你一個朋友的MSN,你可以跟他討論看看,, q; P! @- g; H3 q8 J  p
他本身是程式設計師,也對FC模擬器很有興趣。1 V4 O' ]4 f* E9 B* [
$ H! E: R1 q9 C4 ?+ |  g
MSN我就PM到你的信箱了。
# ?* `# M* e4 S- _) U9 W- G
8 m/ [- T. m$ g: I: \8 w, M希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 - x; v( r0 H$ T4 s
呵…… 谢过团长大人~~

, q+ R3 [- O& @- J2 H5 K( h) ?1 `( I$ E0 u4 Y) X% R
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 2 n6 n: }  V+ E8 y  q
团长的朋友都是神,那团长就是神的boss。

9 e$ m1 }3 i3 j. Q哈 不敢當,我只是個平凡人,+ I1 ?; p6 K, p) w- |
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
6 a4 P' f% g# P- U) SZYH4 V& Q' K9 `( ]
QQ:414734306
: A5 M, ?: o: g5 m8 R7 LMail:zyh-01@126.com
# g" x5 f  p4 N3 B
+ B* ]) ], q- ~% x$ `- B他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

 楼主| 发表于 2009-11-27 09:48:23 | 显示全部楼层
再次对团长大人和悠悠哥的无私帮助表示感谢~~

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 A* ~/ D" ^/ j* w; Y9 X
再次对团长大人和悠悠哥的无私帮助表示感谢~~
1 [5 t$ a! d0 r1 C2 W# z* M7 f
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|国治模拟精品屋 ( 沪ICP备15012945号-1 )

GMT+8, 2026-1-27 10:13 , Processed in 1.106446 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表