EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?* {7 l5 X9 k; [3 r$ t# I/ Y# G3 m
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。4 Y$ D3 K( t8 [  s  o2 m& a8 b
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: t. c! M# X0 Y/ Y这里有相应的模拟器源码,就当送给大侠了~~8 P+ z8 u- e- w2 E* |5 w& B3 i
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
7 \* X% \* a' ?  f, r1 _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! E, t' m8 t* b3 F楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ s6 ?4 q7 g/ L% |6 y* E0 z
这里有相应的模拟器源码,就当送给大侠 ...

! g1 q& ]9 i3 J5 }/ L聲音部分(Audoi Process Unit = APU):4 z( |5 G5 @8 M3 A* {
.\NES\APU.cpp
& L) O/ m' q  Q: }.\NES\APU.h4 \4 Z. s6 C( r+ T/ k* s
  `% O+ a# z! Q8 g6 d8 Q

3 v1 r0 A7 l$ \* v8 h  G6 V影像處理部份(Picture Processing Unit = PPU):1 A7 Z0 ^* f' P! g
.\NES\PPU.cpp
5 A3 [9 F; p- o.\NES\PPU.h. K" ]* r6 _7 R5 j: J% S% Y
  k8 T% f3 c3 @7 s. X
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" G; I  i& S1 a+ d8 y/ m
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
# e% m& L* m! Z(由于很多专用术语和算法机理都不明白,所以看不大懂……)
1 `$ f, u  c/ s9 n$ ^  W//////////////////////////////////////////////////////////////////////////) l+ _( y/ T8 n% X" B# F/ U
//                                                                      //1 A6 Q( L7 w/ O* M. C& _
//      NES APU core                                                    //5 X/ |$ @% e4 q; Q7 p
//                                                           Norix      //6 H% U( h, n! ^( X
//                                               written     2002/06/27 //+ r& c" B- d1 l* T. C2 T
//                                               last modify ----/--/-- //
- N9 A: z$ }7 H: `  M* R//////////////////////////////////////////////////////////////////////////$ `5 U5 I0 z8 I, R- q
#include "DebugOut.h"% `- `  g1 |2 O& J) s
#include "App.h"
( S8 B! Q+ Y3 m9 C#include "Config.h"/ k2 D1 d/ Y" C  a, h

: |) a1 U/ {1 N  X7 b#include "nes.h"; [4 Q) b1 m" A! L
#include "mmu.h"
# v: T( \# z& a$ P* ?8 ~! u#include "cpu.h"
/ t6 a& ?) T# S% y* ^8 n0 o2 x#include "ppu.h"' {* J  n. A3 U# R% W
#include "rom.h"5 H" N% x+ t+ F
#include "apu.h"
/ s% F. r% ^  g& [1 X5 A) d" U! R: v# X; i8 {9 f# ~% j) T
// Volume adjust6 O* o  m" S0 T' Z
// Internal sounds
0 W1 A2 `9 `3 m" @' k#define        RECTANGLE_VOL        (0x0F0)
% k& \4 ~7 n( ?- J#define        TRIANGLE_VOL        (0x130)) S+ u: W, Z1 z( c5 b+ G, \
#define        NOISE_VOL        (0x0C0): l0 N- v  r# o( o: ~
#define        DPCM_VOL        (0x0F0)
" ~9 D* y4 J; m// Extra sounds
/ c* r0 O# Z7 T#define        VRC6_VOL        (0x0F0)
4 i' c& S8 u  z: `7 m/ y#define        VRC7_VOL        (0x130)
- G1 g- F: U$ r8 T; y: R% K#define        FDS_VOL                (0x0F0)
$ B9 K% _8 U: \. d% X( d* W! ^0 \#define        MMC5_VOL        (0x0F0): M' ?- g) o) o
#define        N106_VOL        (0x088)
/ c! b' m3 G- x' h( B; {: M#define        FME7_VOL        (0x130)7 _5 }/ f/ s9 t& o- O- h: k8 W
" X0 J  |* I8 e
APU::APU( NES* parent )
5 O% ?& [: `/ Z3 W{
4 J0 I2 N6 \7 l0 D8 b) j        exsound_select = 0;
( D2 a6 t% z# V( q& g+ m# r6 Y+ Y* \. W% r
        nes = parent;
" b5 B2 V2 v+ Z. _, P. ]% f3 F        internal.SetParent( parent );
8 V( b( a/ V' ~+ c1 x* K- o/ Z& }( O5 X& H2 O
        last_data = last_diff = 0;/ S+ ]/ ~2 t  \: D$ S1 s! U+ H
* X9 t6 j( e/ k& }9 j
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ A* u% l7 \  ^/ z
% c* o8 R+ y+ P0 p& N5 R
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
8 ?0 ]9 ^# c, q! m6 T5 q        ZEROMEMORY( &queue, sizeof(queue) );
0 o6 w% ?( X3 o/ o+ m        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ C+ S, o; G  R5 N8 N2 a4 e

+ E' P: u- v) e4 y. _: ?' z( @2 N        for( INT i = 0; i < 16; i++ ) {& e! p( b' D, J0 |. n0 O+ ^
                m_bMute = TRUE;; q2 j6 g' |: l+ W
        }- V( N" x6 t/ y# F+ \
}
- H& Q& w- x# K2 `4 _, ^# _) l2 x# |7 d
APU::~APU()% G- j! h: ~" _. m, [! k( O
{
4 N9 i+ V" S8 Y}4 `5 W" N' Q0 U* q+ h# M' o! y
% @( g* p- }2 b$ T3 ?% ^- P; {' Y8 w
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# s8 H: z6 P! t0 X) |{- c( s% X9 b& L; s9 O6 I) [9 g
        queue.data[queue.wrptr].time = writetime;0 k6 h5 x  S$ v# q
        queue.data[queue.wrptr].addr = addr;" ^8 Y+ j6 h, A+ h: R
        queue.data[queue.wrptr].data = data;
" S" \  i0 f  a  v) |! N        queue.wrptr++;) c2 b, m4 l5 I$ q# K
        queue.wrptr&=QUEUE_LENGTH-1;- \. ]2 b* U5 t
        if( queue.wrptr == queue.rdptr ) {
3 w+ X- B) o# L                DEBUGOUT( "queue overflow.\n" );
! b6 M2 U! U& f6 a        }
  {/ B$ M! a( \}
, D3 h0 d0 J# A8 X7 }0 \! Z+ p" S1 ~! u  L: Z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& d' X0 M( N( Y! s6 P{$ g! Y+ G& ^2 O, a) z* m
        if( queue.wrptr == queue.rdptr ) {; H! }& i) T5 {. v# Z9 l
                return        FALSE;
1 z4 [. z6 H; g/ X2 E        }
% {6 V$ q" B+ L, B0 }        if( queue.data[queue.rdptr].time <= writetime ) {
+ h& q& Z+ k, o$ ^# |0 m! W4 J  }                ret = queue.data[queue.rdptr];' Q3 R  m/ G- ^9 T2 M' R
                queue.rdptr++;
+ R, K  x, q+ S2 z" f3 a! k                queue.rdptr&=QUEUE_LENGTH-1;# l2 N* D+ R! |
                return        TRUE;
* b5 L, i9 `, _, x1 U) x( |        }, r  B: `7 g* w, {" J
        return        FALSE;+ \. @* K! m/ X3 ~
}- [5 G5 G! D# M7 _
5 i4 d, Q# s# ], t* z) o
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: J8 y4 q9 z0 k3 L; ^{
3 w' Q2 A6 B8 j! x! c        exqueue.data[exqueue.wrptr].time = writetime;/ L# c/ O/ u$ z/ \5 P
        exqueue.data[exqueue.wrptr].addr = addr;1 ~# U2 r0 _" c, i" l2 T+ ]
        exqueue.data[exqueue.wrptr].data = data;
5 F. m, V: ]& C' F! B        exqueue.wrptr++;5 e3 _& x6 \1 t  M
        exqueue.wrptr&=QUEUE_LENGTH-1;
9 t3 p! z8 V& `& l$ j        if( exqueue.wrptr == exqueue.rdptr ) {
  E# w# H# F! L& G/ r* C                DEBUGOUT( "exqueue overflow.\n" );; g, k' e3 O: s
        }
7 q# g* c) ?  I( Q}
; f7 v# L, G8 x! ]6 A  m5 p7 O5 c0 c/ M
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 y" r8 p) F9 y{
' x0 q, h* i  W8 D        if( exqueue.wrptr == exqueue.rdptr ) {
0 e( r- r! \: T, K; K8 M- p                return        FALSE;7 h* O7 ^1 X1 v4 s. B: F; \
        }6 T; j' x7 e: _
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, e/ a2 w8 L# j) C' V; @% X: d8 T) Z4 t
                ret = exqueue.data[exqueue.rdptr];' W+ Y" ~' O2 j; Z4 j* ]
                exqueue.rdptr++;2 P3 H( @2 j" S9 p( j- h0 d  O
                exqueue.rdptr&=QUEUE_LENGTH-1;- L, D8 x* p8 m6 g
                return        TRUE;
+ t& T; C2 M: \, g9 C2 _        }4 |  ^" N6 n+ |8 w
        return        FALSE;
$ q& G- E5 x; K5 t1 F) ]8 E: @. _5 i" h}
1 B" P: C$ R& P& k" g2 y
$ c+ I) B2 Q4 m" F" v$ fvoid        APU::QueueClear()
4 c& l- M, K# C; \7 B{, \( b0 z' |& o5 f# r7 C& P
        ZEROMEMORY( &queue, sizeof(queue) );
' ?7 B- ^5 \6 i! _        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 Q  V$ p7 {4 h) u7 H# A. R
}" [/ f2 F+ p9 ]$ ?+ x, f/ M

" J4 ^5 d; B; G: t$ m  O; Q; Nvoid        APU::QueueFlush()* k3 X1 e: U" O/ C. H$ O& e+ `9 m
{
% q, ^4 P. @# X5 w. _% z; N        while( queue.wrptr != queue.rdptr ) {
! Z3 N) @$ |  Q                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );+ Y! A( X4 t1 ]9 \. M
                queue.rdptr++;
5 k: n) N1 U0 {5 S                queue.rdptr&=QUEUE_LENGTH-1;
% R$ s. m/ j- X0 \/ ^! _        }
- }7 V  n. T; V, V% H. k% G
/ N- F' b1 e0 k% n! B2 y$ r8 l" I        while( exqueue.wrptr != exqueue.rdptr ) {! Z3 [) p+ b8 U9 k3 `# u
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ X8 R0 C( k# l: Z: q                exqueue.rdptr++;( I1 z* ^+ n# I2 M; V3 @$ B
                exqueue.rdptr&=QUEUE_LENGTH-1;
' S  ]4 N: A: D        }
6 Z' ~. K2 n3 L# Y}( Q. }" ?8 C9 \9 x) v8 T0 v" F
, \$ |+ j  ^- Q
void        APU::SoundSetup()5 q) P3 T1 F- Y' L2 F8 e# G
{
' G) V5 A* X9 a$ ?3 |6 J        FLOAT        fClock = nes->nescfg->CpuClock;
" H7 P5 N0 W+ N& C! [7 j' K5 q        INT        nRate = (INT)Config.sound.nRate;* |% E: v) d& X5 p# ?3 b
        internal.Setup( fClock, nRate );
$ n+ D; t  W; J- R/ y        vrc6.Setup( fClock, nRate );
$ S$ \: p9 _( ~! R/ \        vrc7.Setup( fClock, nRate );- v8 J3 X- q. Z2 v( c7 S5 t9 p
        mmc5.Setup( fClock, nRate );
# u% e# k( a* y( v7 i7 i9 x& Z        fds.Setup ( fClock, nRate );
& {2 J" T; {- c" E  {' d. p        n106.Setup( fClock, nRate );2 C& _" I1 A+ u, n# s
        fme7.Setup( fClock, nRate );
  o' F( z* v- S7 w8 Y}2 f1 N4 Z. m* k) {( F6 ]

: H7 ~" ~* x5 ~' ~! p0 hvoid        APU::Reset()
( ^8 b" ~6 l' m+ H! d% i3 H+ b{$ I3 p1 B( }' G3 c
        ZEROMEMORY( &queue, sizeof(queue) );
" O3 T( z8 V2 z1 N/ Q& m% x        ZEROMEMORY( &exqueue, sizeof(exqueue) );
8 r4 k: x* s+ H( o$ T) L- @
& |5 w/ U# t5 O2 [) o        elapsed_time = 0;% E4 U  y$ t. o" m
& g* J7 i' e+ a8 ?9 W7 l% E
        FLOAT        fClock = nes->nescfg->CpuClock;
5 y  [/ s% e/ J6 j! u, a. E        INT        nRate = (INT)Config.sound.nRate;+ H" z  b1 m* g- \3 x; ^
        internal.Reset( fClock, nRate );! j+ l1 `0 [9 B+ J
        vrc6.Reset( fClock, nRate );
# H2 x. `0 m8 L( g' X        vrc7.Reset( fClock, nRate );' |5 r. N# v9 X4 v' J
        mmc5.Reset( fClock, nRate );( U; v* }3 Y- t
        fds.Reset ( fClock, nRate );
8 j+ ~( @8 x0 G" g" j. O2 D        n106.Reset( fClock, nRate );) u) P+ I) G/ |9 c2 Y
        fme7.Reset( fClock, nRate );+ H1 G* e. s7 T2 L: ?8 S2 i# U

" S3 Y8 N. ~; u; R% s# u& T        SoundSetup();  `' y  U! P- L; d6 }& e
}% u9 I& T1 n- V8 I' i7 {4 N' b/ C; ?" @: A
5 w( y2 F6 ]! q1 q9 z* A
void        APU::SelectExSound( BYTE data )
2 g2 m/ Q$ e! T/ D. k{
6 i  q% ?. V7 {3 j% e% U        exsound_select = data;
8 w* X. K+ Q: r/ b4 r}) W6 I3 q( U: k

2 S9 j5 [+ p, R8 S  W/ yBYTE        APU::Read( WORD addr )
/ y6 K% C1 g, R% a# U- y{/ x  W1 d1 X# O0 P: c( d
        return        internal.SyncRead( addr );
" _4 Y& N0 N) x- G9 m}
, [+ N; {( k, T* f$ Y! ~+ m3 ~9 i( P+ j7 t* {. G
void        APU::Write( WORD addr, BYTE data ). s* E8 S8 T" u5 k! c
{
1 H" D- T* i/ r4 S1 d- C        // $4018偼VirtuaNES屌桳億乕僩0 j0 }8 ]6 ]: N% R8 o1 H
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 z5 q+ ]9 j$ u! h1 L: t/ e                internal.SyncWrite( addr, data );6 ?/ g( t3 O7 g2 y: ?  ?( ?; C
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );/ g: F$ O% }( q" ^' s- V
        }
, b7 N. B8 G7 {' {2 V}# H$ l3 K) x7 |
. o5 I, A6 t* u. [5 {) H5 l. H, d
BYTE        APU::ExRead( WORD addr )2 ^8 `& d0 ^0 j. ~
{
& ~- H$ f+ k* W! |BYTE        data = 0;$ f  E- y+ G& Q5 n
9 ~4 X2 q- B  J  X9 X+ x
        if( exsound_select & 0x10 ) {, V( R) `2 N7 x' `# }, z& ^+ n  Y& u
                if( addr == 0x4800 ) {8 K6 K7 [; p3 A" I3 \5 o
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, x7 |( s) X# h, p# y& F+ A
                }
+ O6 T7 B7 Z/ A        }
; |3 G) M/ H: ]  H        if( exsound_select & 0x04 ) {" K, H: V5 o$ S
                if( addr >= 0x4040 && addr < 0x4100 ) {3 y( P  z9 Y! }6 L8 [; k' y. i4 }3 d7 h
                        data = fds.SyncRead( addr );
: b* N; ^* z2 [8 J& d1 S9 L                }! L5 H6 K; t( X% s1 U! }
        }
- S! R* t1 X$ M$ y, e; M4 M$ |$ L4 h        if( exsound_select & 0x08 ) {
5 C* x" R$ Z$ v) t. M0 f                if( addr >= 0x5000 && addr <= 0x5015 ) {
  u0 A/ ^( B1 F& @( A                        data = mmc5.SyncRead( addr );
" V8 K! c6 [* f                }
) y9 u1 A/ [  U% F! `+ s        }4 r( Q7 R0 i% }5 N$ t8 U5 D# ]

% ?+ d! W1 c: q: E% V        return        data;
, K5 @6 X4 [" I7 U}
) D& g3 ]. l: h" m* [
& [% u5 ?  ?& B5 `' {- hvoid        APU::ExWrite( WORD addr, BYTE data )5 F& g$ M2 d, S2 Z# r
{$ q3 i* Q. C- F$ _7 ^
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
+ M9 N, q2 t# P8 u8 V( h6 I& ?/ u# B2 j& C0 u" C. |
        if( exsound_select & 0x04 ) {$ A# y' h. O2 K7 a3 m3 M1 c
                if( addr >= 0x4040 && addr < 0x4100 ) {
* X1 W5 ]0 L4 a3 d$ ?' @                        fds.SyncWrite( addr, data );8 g* x# D6 ]+ G' e$ ^% s$ h4 T9 Q
                }4 j5 t. X" `' O
        }
8 R  {6 ]" w1 H; H0 B
8 S+ J' p2 q5 o# m        if( exsound_select & 0x08 ) {
2 V- b8 f; x" E9 y# ^* M                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 c7 X6 g' r7 N; n                        mmc5.SyncWrite( addr, data );
$ t1 y* {& G  g+ ]. y. E                }
* L2 O0 q" [% N! g0 g1 q        }
# h' ^8 R* H& Y+ a}, s) O* N' y. x/ {
( t. ?9 m# A9 i# B- e7 T1 _1 i
void        APU::Sync()" O5 @2 {8 [6 ~# R3 M+ i
{
& F9 B( i0 C- {" \; }/ g6 e}/ k( l, i0 A* v- R

1 p- ~6 m& F- W! Bvoid        APU::SyncDPCM( INT cycles ), \3 \: c" L5 a, \% i8 ]3 d# R1 ^
{
; H( g) k8 [5 Z: e; B* l        internal.Sync( cycles );6 j8 ?; Z+ o9 ^( l

( f/ @2 X/ |+ f; y" W. A. l        if( exsound_select & 0x04 ) {- j) @, r* k  p7 l+ V
                fds.Sync( cycles );
9 Z8 G, [. G7 ]' [* ~        }
* Q; w$ e: a, G9 b        if( exsound_select & 0x08 ) {0 _6 I" I5 b9 y
                mmc5.Sync( cycles );
( H7 ]. w" B. V( p5 P  J1 }' F" c        }
+ W; N4 S. Y3 A}
/ H& n3 v- ?/ ~0 K1 R
* \0 s6 m$ k# k3 b8 ^6 Yvoid        APU::WriteProcess( WORD addr, BYTE data )
( d5 c6 U, _& {' m3 j7 n- M{& }6 b0 }0 Q+ \) Y2 r
        // $4018偼VirtuaNES屌桳億乕僩
! X' {8 T9 k. ]: ^8 j8 ?8 C        if( addr >= 0x4000 && addr <= 0x401F ) {
: S- I" T2 E. F) {8 G' s                internal.Write( addr, data );# Q7 P* p+ n- R; j, p
        }
& ?% a% e) P2 I2 ^9 {}' o: G! N$ [' K7 ^, l8 p: V
4 e# g" G( h) u  L8 ^; ]0 a5 L
void        APU::WriteExProcess( WORD addr, BYTE data )* X7 u: Z0 g9 n% O
{
" R4 R- o0 X7 j) \7 d- B        if( exsound_select & 0x01 ) {
) f% }# r* B8 j                vrc6.Write( addr, data );( q  z1 ^7 w4 ]  E
        }
; U8 q# f9 S' c: ^. [        if( exsound_select & 0x02 ) {
9 t/ \! H0 _$ g% U. i                vrc7.Write( addr, data );( P" N1 S: v3 K
        }9 K9 f  M$ K. A# U" \0 {
        if( exsound_select & 0x04 ) {8 s# ?1 |$ j, K* q# E
                fds.Write( addr, data );9 {/ {  r" S) O8 b" v! X, L" a
        }
( O: @# `2 P  F0 C! z* o( u# i        if( exsound_select & 0x08 ) {5 o+ c6 D$ q! k! E3 k" O) S$ i
                mmc5.Write( addr, data );
9 E0 H* t! Y; T: u        }7 ?- z* ~  F% h1 p) y2 P$ z8 f8 p  ^
        if( exsound_select & 0x10 ) {
) n- r+ P/ J+ U* o# |$ X* T! g  b3 Q                if( addr == 0x0000 ) {. ^" V( C. L" M8 C1 f; f3 U- f
                        BYTE        dummy = n106.Read( addr );
3 ]* }  J2 N" q) N  D; A9 t                } else {
8 p$ k( O2 O9 O                        n106.Write( addr, data );0 x5 p8 @; a, b1 I* z7 _9 `2 w  A: J1 y
                }
; e1 \: v: ~- r2 t  O# o        }
5 m$ B5 v3 u" [! v9 c8 C2 L        if( exsound_select & 0x20 ) {% A1 Q* [5 l4 q7 R/ _* _3 k' F
                fme7.Write( addr, data );2 Z  [8 v! ], ^) `7 G6 a' x7 a
        }, O0 y- x# w- J, o; ]# O
}
  X3 O+ k# S; ?' N" f. c4 C, z" }* K+ d/ P3 G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& l$ I8 r2 w( k5 @1 ^" N! }; D{
; h& R4 |  F% k  I) QINT        nBits = Config.sound.nBits;
% U' R5 ]# e6 L' J5 t( R$ r; V0 _DWORD        dwLength = dwSize / (nBits/8);1 [1 {4 i  A# x. K2 [
INT        output;: b2 t/ B: f5 F1 H" V3 a; h9 b
QUEUEDATA q;; @+ w+ }7 ?# m3 r# p6 p' T0 W8 `
DWORD        writetime;
1 ^  j; O! i+ @
/ |! Q9 V( z0 i. C' CLPSHORT        pSoundBuf = m_SoundBuffer;. P3 j( n, ^7 ?. I
INT        nCcount = 0;, r$ f; }; G% \1 h
* S! C- A% K0 Q/ J7 ^; ?+ a9 G
INT        nFilterType = Config.sound.nFilterType;$ y8 q8 e* u0 p  M6 T
2 a+ r. G. k4 i8 }" R5 d# Q" E+ Z
        if( !Config.sound.bEnable ) {8 J1 N  j3 g- U- o9 {2 ?2 E
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; D, d; {4 [1 x+ x3 Q
                return;
& d4 r. A2 i. t" C6 {. V4 _/ w0 u        }
* Q* P6 ~! _$ ?9 E) m
6 f+ G( b* @+ V/ b" m8 v% `" Q3 q        // Volume setup, b5 c7 \. W' x' Z. a6 e$ K! w( d
        //  0:Master% E/ ?% o: s/ ?1 d! Y1 M4 F
        //  1:Rectangle 1
- i6 [9 t8 F; c, W$ d        //  2:Rectangle 2
! i2 g+ x5 J, O3 Z        //  3:Triangle
: X5 J2 c* R9 W3 J3 J+ E8 J+ A2 P        //  4:Noise
! ?5 H; O4 d) K3 f/ o, a        //  5:DPCM6 t. u* t) x, }4 @8 T9 b/ ^
        //  6:VRC6
. F. c& D2 e  Z$ }! b/ k        //  7:VRC7
2 Q! S# ~/ V5 D# {* _        //  8:FDS1 w9 w* {5 F! [9 q1 d
        //  9:MMC5
" C5 L3 S) h$ T# r% S        // 10:N106
- C" k/ P2 ?6 }% t" B1 {        // 11:FME7
. z* e" p7 W: Y; ~$ K3 ?        INT        vol[24];, n' y8 e  }3 r
        BOOL*        bMute = m_bMute;
! A7 W( B! h/ y, [5 |# w        SHORT*        nVolume = Config.sound.nVolume;
/ D. w( w0 }. Y. v4 G
3 U) K9 a. j. ?' ?3 @, p& B0 J5 ?7 x, ^        INT        nMasterVolume = bMute[0]?nVolume[0]:0;: m$ X2 G+ z( `3 c/ a
& k3 Y- b0 G" ~: y
        // Internal0 y2 O8 L" c6 y  I/ ^7 ]
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
$ _5 `, C4 {+ b! D- R4 K, r        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
$ j, X* |' `- u, E        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
3 e. B- E2 N5 ^3 e- I, T        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
, W; C+ U) }" s% F6 ^  H4 m( Q/ i        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& i- R7 D; T/ F; [* H: p4 g' w4 O/ ?! {! v6 u- s$ i
        // VRC6+ e- u! U1 Y: f( C& }- }5 z& I
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 m; @' w3 K3 h2 J        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 W6 {! h- E0 J$ }% y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ C# u; D: \( w
4 T! h/ D) y9 w# V- X( a        // VRC7+ ~$ e7 i" }- G# i' a6 F. @
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
9 L# j/ c* G) _" T! q1 n' Y0 e' _8 I" b2 _8 _# Y+ `- ]# N
        // FDS- I) ]8 b, W; I' y5 l3 \- T
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;3 c: a1 v$ h5 I4 `5 [

/ ]1 u. T5 T7 W0 [, @        // MMC5  W; n% S5 E$ U2 Q5 S+ b) Q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: E: T; z5 ~  E& [
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
7 }/ q) ?# N' U5 M. U        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, T! X, d( y) I! D7 ~' h7 E, C5 d, |  z# ?8 K" A4 m7 f% U
        // N106, d; Y! L* w7 S- D9 W2 W9 `, D
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 D# `. b5 K' P6 D4 R5 x7 G
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 v( u" E% `" J% I
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 j" L- A7 n; F7 l/ `7 i- A  i
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 R1 R$ H8 I; D4 [
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' p( T8 o* Y: f- B/ V        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ S& C6 C+ C7 A: X" W        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- B/ Q/ Z# v& y3 [" i
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  t2 L; w1 A% ?0 r  ]! V& M' }) g
" t$ n. h' z" J- @; q
        // FME72 @9 v0 B4 z! m' m$ ~# T; ]1 T
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& a9 W& I: A0 ~; Y' Z$ y" \
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 h! f  ^! d& ]7 V' r
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* \. [. C' v: G1 Q; u! T
  @* h* N5 ^- j- {//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;2 }: o0 a, w+ Q. U' i5 o( ]# ]! k- G
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;6 O. z! K! D+ ~! `% I, J

; ?2 D0 g. y3 v  M  U        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
; u/ Z1 H2 e% h" R. |        if( elapsed_time > nes->cpu->GetTotalCycles() ) {5 @8 F4 D1 ?0 J" g
                QueueFlush();
) ?3 e" y. Z! x! [& V& F% X        }5 r) f6 L( {, A. \
1 }; m! r! A" Q  _% }
        while( dwLength-- ) {) T% ~' _: I7 ~0 S
                writetime = (DWORD)elapsed_time;
1 M( A3 t3 t# @& V# t0 {" G7 O% H# C. ?* X9 W
                while( GetQueue( writetime, q ) ) {% ^3 x$ B. H2 z" A
                        WriteProcess( q.addr, q.data );% j& s" v1 y# K. f" P  Q; H
                }) f4 B: S  {* M" q# M

3 E0 J; S6 q* T  V                while( GetExQueue( writetime, q ) ) {* o. [0 K& r# J6 k
                        WriteExProcess( q.addr, q.data );6 X) k+ c: ^! P5 r
                }
: t9 n" B5 x/ H  o, J' K: {* s7 i& w, o/ a; j8 D+ M
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
2 x( R0 e) W0 x                output = 0;. m. Z+ @  s! B, P, H; g
                output += internal.Process( 0 )*vol[0];# M7 X; P/ @! @! N
                output += internal.Process( 1 )*vol[1];( J) S2 }' g( U. T
                output += internal.Process( 2 )*vol[2];6 U- i% A4 n9 q: ~* @! R0 G
                output += internal.Process( 3 )*vol[3];1 `, Y7 i" ]3 b- ^6 N9 z% N0 V
                output += internal.Process( 4 )*vol[4];& g' X6 t4 g/ h7 y) U9 ~
; R* u# B8 u0 p, L  `( G2 w6 x5 N( j
                if( exsound_select & 0x01 ) {% v; s6 D6 \0 W+ F$ H
                        output += vrc6.Process( 0 )*vol[5];
2 c" K, ~) H5 m9 X1 I                        output += vrc6.Process( 1 )*vol[6];
: e4 K; i4 m6 t: A                        output += vrc6.Process( 2 )*vol[7];' t; s) M- w( ^; \" W" ^
                }' x1 d: j! w+ i1 X% w8 w
                if( exsound_select & 0x02 ) {
1 K. b3 q- q0 u3 Y                        output += vrc7.Process( 0 )*vol[8];5 w- {# }: [. V- ?7 x- C6 O
                }
* T' ^7 k* ~) L. |. L- r                if( exsound_select & 0x04 ) {$ |1 B: O% J* e' p9 ^/ e6 r
                        output += fds.Process( 0 )*vol[9];
" v  S1 m( Y8 _$ v- A) W9 F5 ^7 B9 \6 G# ]                }8 t+ ?# N0 l+ I! J& c8 M
                if( exsound_select & 0x08 ) {
2 p" [6 ~7 l7 g                        output += mmc5.Process( 0 )*vol[10];. d) O* g6 F& J- i0 p! r& Y
                        output += mmc5.Process( 1 )*vol[11];! d; t  o* z6 x7 I# X" u1 B! I
                        output += mmc5.Process( 2 )*vol[12];- K  z0 e8 P5 }3 i, @5 c, c
                }
; h4 d' b: F+ o7 k  a/ a                if( exsound_select & 0x10 ) {6 h6 t% j9 A) M) m& d8 ?  _
                        output += n106.Process( 0 )*vol[13];
  V. O0 ~5 ^3 @/ Y( f8 u! e                        output += n106.Process( 1 )*vol[14];. z5 X- d( N- t7 r0 ~2 ^  |
                        output += n106.Process( 2 )*vol[15];8 e1 _9 Y( u5 s. U- Q. z
                        output += n106.Process( 3 )*vol[16];! D. w9 H$ U% f5 w9 Y
                        output += n106.Process( 4 )*vol[17];5 I5 b# @# n. G+ F; t+ B
                        output += n106.Process( 5 )*vol[18];
" h5 x7 f$ _9 ?, k* `- E8 N  j7 J                        output += n106.Process( 6 )*vol[19];
3 ?/ w$ w$ U3 k! W                        output += n106.Process( 7 )*vol[20];
3 O9 W, I% }7 L* Z0 S9 L                }
% l' ?; H" n) e' k                if( exsound_select & 0x20 ) {
! \# O4 [% @/ C                        fme7.Process( 3 );        // Envelope & Noise3 }5 a% S2 Z: A: T4 \: R6 F- q( v( Q
                        output += fme7.Process( 0 )*vol[21];
  l) |5 y# U$ P7 m8 G                        output += fme7.Process( 1 )*vol[22];% C% h& I- T, k1 m+ i& L
                        output += fme7.Process( 2 )*vol[23];9 e2 X  J& j, K* L4 ^' g, P; H
                }5 |" m6 U5 ?( o. d

3 Q$ ], e5 [9 W6 a# w* M                output >>= 8;. e$ C: r8 J9 ~* l! h' W
' s8 F$ ]+ s% d7 N
                if( nFilterType == 1 ) {
8 p4 U: h1 ]' A$ L, ^% I                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple); a! A9 Y# P9 _  W$ E2 }1 u
                        output = (lowpass_filter[0]+output)/2;
2 e" c* T. d: K+ h                        lowpass_filter[0] = output;
; O/ `: L1 r- E3 a" M# c& s                } else if( nFilterType == 2 ) {3 E9 M3 a0 \% i) e! c2 b7 U, D8 z2 y! y
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)( ~- @6 ?0 I+ o  S! G
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ P* L% e" p* j4 T6 K' g, m                        lowpass_filter[1] = lowpass_filter[0];
2 O! {- n2 E9 i, Z2 g. z$ p: h5 g. ~2 P                        lowpass_filter[0] = output;
  S  o! e/ l2 G8 p                } else if( nFilterType == 3 ) {  @  ~4 v& d+ \( N+ F* j! i% I
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)- Q0 v# |! R" |6 x, ?0 ~
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; w5 Q" d, D* G# u0 y5 B8 I$ a                        lowpass_filter[2] = lowpass_filter[1];# a& H+ p6 p1 ]5 V
                        lowpass_filter[1] = lowpass_filter[0];( D+ B, x6 z# Y( k9 T
                        lowpass_filter[0] = output;9 b5 {: l- }3 M" d' Z
                } else if( nFilterType == 4 ) {
2 ]# `0 G$ i3 |3 Q                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
$ ~) s* `. B$ q6 y                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' h& e/ f, C+ W& [8 ^$ l
                        lowpass_filter[1] = lowpass_filter[0];' s/ ^1 w& ?/ A$ C3 A# V
                        lowpass_filter[0] = output;
  G+ _3 J3 p; a                }
; s5 S5 i9 S! i! @9 a& I$ \( t- \5 m, f5 E. V$ g
#if        07 ^5 a$ P% q+ M/ P0 m& h2 `
                // DC惉暘偺僇僢僩
- O4 [& A$ v' D5 e                {- f. Y, S0 Z9 @6 V" C
                static double ave = 0.0, max=0.0, min=0.0;0 f/ }" l2 P' R7 S
                double delta;& S" X5 C- {5 _; u$ ^3 R
                delta = (max-min)/32768.0;
+ P8 ~) @0 j! i  r' g8 T7 N. @                max -= delta;
+ x* U& j6 m0 _$ P. l  ~                min += delta;6 i8 c3 K$ ?1 S1 [. d4 N% m9 t
                if( output > max ) max = output;- {. [1 c) ?$ t; f
                if( output < min ) min = output;8 B: b' r7 b! i1 T& x& H+ t
                ave -= ave/1024.0;
& L- |1 Q- ]" o, g; B                ave += (max+min)/2048.0;$ V0 S2 @3 i  {& T" _
                output -= (INT)ave;
/ X8 l! A! i& m" J6 b0 }. O' @                }
5 P- D0 G4 {# D# n, O6 F# t& Q#endif/ o% A  j+ |* f4 P$ Q1 ?
#if        1
; b) m+ ]" j: W: H- {9 z                // DC惉暘偺僇僢僩(HPF TEST)
  V, Y$ _& t0 s% h                {
1 t/ O# R3 Z: _: t: _5 F7 }//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
3 u& ^' M2 `4 Z; v; r6 J" T                static        double        cutofftemp = (2.0*3.141592653579*40.0);' d0 W  A) n& E6 F3 t# E
                double        cutoff = cutofftemp/(double)Config.sound.nRate;. K; [; v( h0 U( J1 c. v0 O
                static        double        tmp = 0.0;& w' U  e1 l7 W7 s; v) |( f$ a8 ?% s+ k
                double        in, out;
  }4 P: @; h6 j- F; S5 g
- M$ F7 D% ]) R% N' _/ s                in = (double)output;
/ J( Y7 T9 I- V3 q                out = (in - tmp);5 S7 V% C3 \: y( q* |8 C$ s2 I
                tmp = tmp + cutoff * out;
+ |3 G( x* h$ Y0 F* @% ^$ v2 t, f6 Q/ Q: P' r
                output = (INT)out;
) i" T) O% o) |" U                }- C! k% Q1 z- W  M6 Z
#endif1 o$ {5 n2 n' v; Z1 ]/ S" k9 I
#if        0- N: y& {1 o& d! i9 s
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)/ d' P% s* x& b+ w" F4 R7 n/ q
                {
+ ~: V4 ]% Z) a- R, v4 `                INT        diff = abs(output-last_data);5 a& O+ u$ }  _4 f
                if( diff > 0x4000 ) {
/ l& u/ k. F" O7 F                        output /= 4;
4 ~! u) J% G4 a5 M2 T) J                } else
1 ?  q: x6 F$ p4 H                if( diff > 0x3000 ) {
, w/ W0 D% z- B+ Z                        output /= 3;; _& J; j4 Y1 j6 z' N' k1 F& {
                } else& a, v. I0 Y4 w  ?
                if( diff > 0x2000 ) {" V4 W$ h5 {+ `0 K9 x# D
                        output /= 2;
& O+ v/ g6 i) L! R! G                }
+ X9 l  s7 R: P0 X                last_data = output;  Y: q. F  [4 A$ A
                }) u- R) ?$ [! K. L
#endif: Q1 f6 L$ Q4 z# O3 c5 i3 W+ S' A
                // Limit  r% f9 {7 \8 R/ |; E7 ^( r% d
                if( output > 0x7FFF ) {
/ z7 V4 B2 D7 V  O2 V+ H0 W+ \$ W, ?4 k                        output = 0x7FFF;
0 J. w# Y. G; y                } else if( output < -0x8000 ) {7 L" ?& v9 t8 G/ D# d" W
                        output = -0x8000;% |. C$ D% [: z4 r  b
                }2 G0 v& t4 J" |, H
. T3 t- S2 a7 g8 i  u; f8 L
                if( nBits != 8 ) {
" t! u" U2 K, A- @4 z                        *(SHORT*)lpBuffer = (SHORT)output;
) ~7 b6 R5 r" n7 T2 ^9 n) a6 I, z" q. R                        lpBuffer += sizeof(SHORT);
/ C0 p7 Z8 x1 m# x5 J$ \+ w# R                } else {
8 [( `0 f4 h, |0 b9 K                        *lpBuffer++ = (output>>8)^0x80;! J  m) W! k$ W- H. \9 Q- T9 w
                }" s. ~4 S. K+ Q8 H8 e, \8 C: g
1 Q0 f, m. }) @
                if( nCcount < 0x0100 )! v1 i6 d7 ]/ i0 ^" K$ B7 Y3 Q
                        pSoundBuf[nCcount++] = (SHORT)output;- ~, ?1 H9 D6 b* \" G. k+ q5 Z/ @
5 q' K; l7 G& n" m5 t
//                elapsedtime += cycle_rate;+ ]+ }! m4 ]' U2 O$ c! ^* Z
                elapsed_time += cycle_rate;
# q; ]  Z; R, {6 `1 \        }
6 n! P7 I3 T4 v- {) t* a7 W
8 i8 B! b3 ?/ D7 H: ^( A#if        17 ^! _* [/ H* h
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {. i9 x2 |( H- i7 Q. s! _/ P9 J8 n( O
                elapsed_time = nes->cpu->GetTotalCycles();
; q, x: x4 w+ S# X9 j  g8 R        }
6 p  |: [3 M7 }        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# o, a! n- |7 {' f- k5 w5 @$ n
                elapsed_time = nes->cpu->GetTotalCycles();6 r' V6 S! p0 u
        }, M4 s4 d$ `% v6 q" w* f) W: n
#else
( I6 G9 [$ T5 }- L( \& |2 u8 L        elapsed_time = nes->cpu->GetTotalCycles();5 b6 I5 x- |* Y9 I& p0 l# A6 m. u
#endif; w# e; D3 U  u$ f! z- z3 g
}
% w2 |) d! C' B
/ P9 F0 }2 z6 X. u// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
; Q! O1 P7 E, ~INT        APU::GetChannelFrequency( INT no )- y& R' j4 ~3 S9 f4 ]0 f
{+ a2 q9 h& m3 S: T# w/ P8 V8 p
        if( !m_bMute[0] )
) U( T* Y# ?& B                return        0;4 R0 W" _- M4 Z7 p

1 A: _1 `% R. _6 H        // Internal4 r: t" f/ q2 m9 {1 S) u: U; K
        if( no < 5 ) {
" d9 c5 o, X3 D6 a$ D                return        m_bMute[no+1]?internal.GetFreq( no ):0;1 ?. I$ j5 M' s3 H  D/ i/ f3 \
        }/ v+ H, i: k" H/ g" i# X* d0 N2 C; q
        // VRC6* c5 N# W; [; G% w( }) P
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
3 E  ^# j; W2 L4 L4 {$ `                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 S4 x5 b( h! }( y% K! X0 \" ?        }2 C; ?2 g4 C3 k' @5 r0 E
        // FDS
2 h8 \' a. ?% d- m6 Q& Z' x2 g        if( (exsound_select & 0x04) && no == 0x300 ) {% ?) P+ S0 ]3 L% n
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
( M" E3 |$ r/ @4 N5 L) ~; A+ \6 y+ {! @& ^        }; i& A) p5 m( |8 y. v' N! ~! O1 S
        // MMC50 ?: a0 U5 X+ c* m
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {+ x7 A, u5 W9 s" l& _( Y4 e
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; k9 z& H/ o: z/ W3 z7 A4 S. a        }. ]# E& H3 I- x
        // N106
. e: W# C. f+ _$ l( E! j        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 F# k5 n0 d0 z1 @1 Q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: L* y: M) f( b( [" S
        }; G6 Q) E) \+ @$ U+ `
        // FME72 Y# \( d# X  _4 ]( B/ r: y: V3 ^
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* U2 F- n! m# Z/ l, E
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;. d* B/ K1 ?) ]- }5 H& x
        }
: ?' o9 l, N5 a% m- |" U        // VRC7" g1 T% A$ E* r4 m# r1 S$ ?& S0 q
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {9 x( L! f$ j7 b: m
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;% _, l. c* t8 X- i7 Q/ |
        }. Y; O; Q" N+ [
        return        0;
# H& I, N' d5 p}
$ _+ A1 i5 R, a% q# R3 r9 n! g5 i8 K% p' u
// State Save/Load
" |# h8 B/ F& x4 F5 z3 l& V" Fvoid        APU::SaveState( LPBYTE p )2 J5 C+ v% b0 U6 W
{
7 Q9 e5 E' u& M#ifdef        _DEBUG
" z) N4 D& x+ v& ]5 y# mLPBYTE        pold = p;  ^# n# a1 {# O, ?0 v6 K
#endif2 F" ^5 Z- a& q

8 W& w9 ?# R9 _* q7 p/ T        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞& g/ H) |0 d1 B6 f; K
        QueueFlush();# a! ]( q3 X4 Q, P

+ w. ?( d7 J' T( `  h+ ?        internal.SaveState( p );
5 f9 }4 m0 b/ t. V        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ I% o+ q1 [* u+ ^, B
: h% q6 q- u* A/ n& t7 D
        // VRC6
3 p' E& ~) ~7 e+ T/ [        if( exsound_select & 0x01 ) {4 x, _, g$ t+ x" @3 V$ g- a0 n: {
                vrc6.SaveState( p );
$ [3 C+ K# P: ?3 ~" v                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! `+ O& j! i1 N. D
        }* C' _" l; [6 g8 n% D
        // VRC7 (not support)
& H; h( a# w) T6 P        if( exsound_select & 0x02 ) {
* B  A" `8 D4 a! j                vrc7.SaveState( p );
8 j) o. |0 t% U7 ?. U5 C                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; H" G; W! A0 L$ l, Z, q* {
        }, B7 K# K* w% {2 t
        // FDS- o$ S2 J* B) j& Q
        if( exsound_select & 0x04 ) {
3 T7 V3 R" ^% L; _# E1 b( {                fds.SaveState( p );1 X+ Y% ~# W! B0 _7 ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 q; ~1 M6 T2 m  t* w7 ~$ a
        }
; R& q; }0 Y3 M; Z        // MMC5: S- J+ }9 q# j* x% _
        if( exsound_select & 0x08 ) {
% X+ n# c" A: m& d  P; [' }' X/ E                mmc5.SaveState( p );
# t4 R3 R/ o; e* |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  b' i' X/ }: T4 G1 T
        }# }8 |& S1 w3 h% T( v2 W$ A- M+ b
        // N1060 v' C; H  i( F4 W, r' x. [9 o7 Z
        if( exsound_select & 0x10 ) {5 ]: `% Q; C: H, J& A( L$ t
                n106.SaveState( p );
7 ?" B0 a, u; j/ m8 P3 `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ P3 `% A, w/ r" |+ o2 |" P
        }/ g. Z& u) ]. z) k  {; N7 W
        // FME7$ M2 Y3 J! @3 \8 V0 ~  V  C
        if( exsound_select & 0x20 ) {) }8 Z3 F7 A2 G3 s
                fme7.SaveState( p );
7 h2 K: q0 L; N( ^                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 ?; d" c" X* m        }
3 m& P0 r' ]# Y  e2 e7 a2 c: n7 ^+ }. {
#ifdef        _DEBUG
9 ~/ S3 E: [3 ~0 |# {6 q& UDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! y$ C3 e( I. e5 Q, R#endif
0 r- k* |. n2 z5 ^2 u}
6 c+ g. h/ _4 Y& Y- o4 c  H
. g+ g5 b4 e4 e; r" [) G+ I8 mvoid        APU::LoadState( LPBYTE p )
2 G9 J. C7 d! Z& E& @! h% A{
/ U# \! m0 s  n' h' z' c        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
  w1 `6 g7 _$ c; z: G% I& C        QueueClear();
" p8 k6 ]0 Z" ^7 X7 I$ T% O- v( K4 M5 w
! c2 l/ M. A5 v        internal.LoadState( p );  ?  e! X- y, z/ h) x$ x. h
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 U, d* a2 ~# _6 Q% B; z5 l. ]6 \( @* G  |- H
        // VRC6
  s5 A3 p+ U, v        if( exsound_select & 0x01 ) {) C- d: `% p8 c: r( {: ?
                vrc6.LoadState( p );
& E9 l% f6 {) j7 [, f. w' h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 p. t  z' E. P% ^4 r" [        }
' I  ?) Q# w5 Z5 T* j0 A4 k2 i        // VRC7 (not support)# U9 ~+ y4 Z* d9 j
        if( exsound_select & 0x02 ) {
9 p7 |* x# A) M; X. P# m/ W+ j                vrc7.LoadState( p );6 V. E: X0 @3 E6 O# D2 V1 p# O! t' T
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 m# d, ~/ ~  P: Y        }/ N- T: ^7 \$ v$ x
        // FDS
6 N$ n' U6 M' t- n4 i* b, F6 ~        if( exsound_select & 0x04 ) {* ~4 Z9 m' H, V1 h1 `$ b* Q
                fds.LoadState( p );7 `6 t* l; a' }# I; Z7 M. o
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- F# s1 \! G! S. \: r
        }
1 M$ H9 j& _, t  _; B) T' s        // MMC5
+ p$ |; U9 _; c) W) v  w! k        if( exsound_select & 0x08 ) {
: M, K' \; M, a* a6 O                mmc5.LoadState( p );
6 s, O- Y' L( {9 |1 A, m                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
/ \2 v2 f3 e, G4 z+ E, F( C        }
9 P0 ~$ V0 Z5 N! H        // N106
; s( N4 \/ U9 {" v& q        if( exsound_select & 0x10 ) {
& ~$ ~# l9 V3 l. e% }" [" ^( q9 u                n106.LoadState( p );
7 ~+ D% ]  `+ F- ~: R. n                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, a2 k( k) O. [2 v2 z        }
( D* U, W4 Z4 c: t# P: p        // FME7
3 L9 k2 K6 r  O        if( exsound_select & 0x20 ) {
0 _, g# x& x0 l& `# |& H7 i' C8 V# u                fme7.LoadState( p );
! w# `* r! S, F1 o                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding& K, x  a  w& N- W
        }6 h. S" r. r! D  r3 w! k
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ) g* H1 `$ R8 ^! N" x
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
+ O8 w% R7 W" k9 L/ G7 F感激不尽~~

" C0 l$ z" x! X2 D- s/ u恩 我對模擬器不是很有研究,+ c, x& t$ Q( E8 ]7 b* ]
雖然要了解源碼內容,可能不是很困難,
9 c3 ?" H/ W, g9 l; p( V" n; U" x( l不過還是要花時間,個人目前蠻忙碌的。
/ z" N) V1 W0 ?; c( O: v7 Y% Y, h8 ?: s* H, y5 r* y. D- a
給你一個朋友的MSN,你可以跟他討論看看,
  B/ g0 d* H; m0 j$ e他本身是程式設計師,也對FC模擬器很有興趣。
: C, W9 ~. h0 \8 O
8 x: o& R- @& @7 mMSN我就PM到你的信箱了。7 N! P6 N; V' q; E

% o/ I- m) @2 @+ \$ x7 C- S希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
, c8 V! b5 g8 v% \, _: B呵…… 谢过团长大人~~

$ @  ?  Z& I4 m# f' N" O$ _5 L& |1 s" C1 T% _8 ]' m) j8 _6 [5 B
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , Q) m8 e2 h8 I, f& l- I
团长的朋友都是神,那团长就是神的boss。
* G9 B" U; W9 G% O
哈 不敢當,我只是個平凡人,# X( G! z/ H% N/ t0 Y! G" r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) [2 b" J2 V* E* X' sZYH
, f7 |# t9 I6 v1 ?: J+ [( uQQ:414734306
+ X- w3 q$ g! @& ?" z2 l. M) ?; sMail:zyh-01@126.com
1 Z/ I2 k) j9 _6 x! l, N! e2 @. P4 n' C! s0 e$ E# P, [( t+ Y7 m( y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
; t3 v# K3 k# U) y; v3 ~再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 {# T7 V. h2 k& K' ]( p' M, v
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-24 08:02 , Processed in 1.091797 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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