EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
. S$ @! |$ c! C4 m& l8 H2 b, pPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  [! Z8 W" S* |0 [8 C( u楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, a# E4 {  E7 U; Q, G3 S5 I7 }这里有相应的模拟器源码,就当送给大侠了~~
# t) c# b0 r  e) Bhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
0 T* r3 U/ n/ ^) z5 O4 W9 [能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. U7 `" u0 K1 t& [* X
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) m! z1 [7 X4 ]; r. g0 p, ^
这里有相应的模拟器源码,就当送给大侠 ...

8 w# l# P" W! S: ^! U/ }聲音部分(Audoi Process Unit = APU):
  `+ t- c9 [8 a; [0 ?3 |# v# R; u& o; a.\NES\APU.cpp
$ y+ p( d7 Q: \( m+ o! I1 d3 ^.\NES\APU.h- Q' N; N2 q! P6 c3 W

) @# [/ y3 u4 y+ r+ w1 Z  j& z5 ^& `) g
影像處理部份(Picture Processing Unit = PPU):
8 @2 J% H/ P6 \.\NES\PPU.cpp6 x5 V  k% G/ S' q& L9 A5 C0 v
.\NES\PPU.h$ |, T" e3 w9 }& ]
0 N/ k- S! b! W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
: M; o; S! @5 r2 F1 M2 r# `(由于很多专用术语和算法机理都不明白,所以看不大懂……)
1 W+ Y$ g$ w% c7 _6 w- P4 i//////////////////////////////////////////////////////////////////////////: ?- P  `$ B/ {0 W4 a4 c$ E4 S
//                                                                      //! z5 R1 H, D/ B% {5 m. Q+ y0 x
//      NES APU core                                                    //! _' t" p, |0 G: u( }' b4 t! m
//                                                           Norix      //" r8 |6 M& A% ~+ ?( W3 @  H
//                                               written     2002/06/27 //
" A, P% R- O+ k: Z+ d//                                               last modify ----/--/-- //
% V" M. }- V/ w' M* P0 ?//////////////////////////////////////////////////////////////////////////1 L$ N3 h% e9 }0 C: n! K3 s
#include "DebugOut.h"+ p. i; C1 b: M/ ]+ b4 R
#include "App.h"/ ^) F0 _. ^  |2 n
#include "Config.h"0 D  j" R2 c* G: a6 o5 g
' {+ X, c. \) B; a
#include "nes.h") C8 L, ?0 j( W" A0 d- Y
#include "mmu.h"
0 c1 L, _/ [8 i#include "cpu.h"
& H8 E1 u& [- A, a#include "ppu.h"
* r% ~4 s% u9 R% k  V#include "rom.h"1 U( A5 g9 Q( s0 U  K' ?+ T( {& x5 a
#include "apu.h"' E, f2 o9 ]6 m, R% k4 {
" l' k: q$ D0 y; `
// Volume adjust
2 U! i7 M$ h2 i! [: h2 w, O( R// Internal sounds+ c6 b8 w% u, F
#define        RECTANGLE_VOL        (0x0F0)
5 m- u! P3 d" y4 R8 u  {8 |#define        TRIANGLE_VOL        (0x130)
# [" h0 e* C$ ^) `* ]/ c#define        NOISE_VOL        (0x0C0)
& @8 B$ z( W' }, @#define        DPCM_VOL        (0x0F0)
  K  [) h! |( a) W4 P// Extra sounds5 R3 f! K( o5 Z3 L
#define        VRC6_VOL        (0x0F0)4 S3 S, p- f  W; W
#define        VRC7_VOL        (0x130)( z# x# a3 [  H2 T7 s
#define        FDS_VOL                (0x0F0)
$ X& ^9 L) t, m3 l4 x: U& P5 A/ ]#define        MMC5_VOL        (0x0F0), H; @# X( [4 S; q2 I, U* a3 p
#define        N106_VOL        (0x088)
, o6 G. d; X, P3 z1 i& u#define        FME7_VOL        (0x130)
$ A; h& P8 d: [7 `+ i
8 q' H' J8 X; V" Z, aAPU::APU( NES* parent )1 i7 D. c( t2 A
{
3 g' W- C" o- G0 k* t        exsound_select = 0;& l  y: \& `  T

  _1 d' c4 O2 n. s9 m        nes = parent;
. p3 f$ k- B' b7 }& U' [1 g0 q! ]        internal.SetParent( parent );& S8 l( ?" f- y/ f
( U$ ^2 x6 \. r
        last_data = last_diff = 0;3 L3 O, U0 ]$ ~# l

0 y, O6 d  X' N0 t6 c' W/ n9 W% y6 P% @        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );* F4 v, t' P" a2 E, }3 K

5 \% T( e4 \* j6 j2 t: ~8 z+ x, U        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' R' X2 F0 P6 Z) w  r5 K
        ZEROMEMORY( &queue, sizeof(queue) );
+ H, T% H( `" ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 V2 U& Q7 z3 ]6 l7 Z: y

4 ^4 @5 r0 k) C2 Q        for( INT i = 0; i < 16; i++ ) {
; k, o  W, i$ k; w; _! N                m_bMute = TRUE;
) F4 G7 P+ x. t9 ~        }
( r* `$ m: h. |$ k9 m}$ S9 i% [4 D, i; V$ o

! c0 }0 ~$ s5 e( {. U( h4 L  t) R0 wAPU::~APU()
# k# V+ }# J: P& h3 \{" Q' v7 m. w7 R7 s) [0 J. w# s
}, ^5 V. {; y5 |' m5 ?8 r. X! }, f
6 X+ E4 G* J$ l7 E: M4 x
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: h+ u9 [* Z3 C9 I{
9 L$ [) r3 ?1 I5 g; f, M& N4 J        queue.data[queue.wrptr].time = writetime;# N! b0 x6 _+ v7 V# E
        queue.data[queue.wrptr].addr = addr;
9 o' H. z# B2 Y% U; b) j; ^. [" |2 b  V8 a        queue.data[queue.wrptr].data = data;
7 @, ~1 z: U/ x4 j. s$ ?' H5 _        queue.wrptr++;
/ @1 ?% |" q1 M" @: S; f9 u/ b; d  l' Q        queue.wrptr&=QUEUE_LENGTH-1;' b2 O+ k) R- U
        if( queue.wrptr == queue.rdptr ) {$ P; o7 ^+ }* V
                DEBUGOUT( "queue overflow.\n" );
% v1 i$ k2 D& c# m# C* Y        }
. Y# Y; v3 ]- {}
! i$ v( @( a4 f  [4 H
4 {9 @, Z& D, @+ g! {BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 _* f  K* D& l/ p9 v) @) |
{
6 |8 e1 ]4 y* b  s/ O$ G" l' n3 ?7 X( I        if( queue.wrptr == queue.rdptr ) {
6 ~- \% }$ e% \" t                return        FALSE;7 [4 l. e+ B: U) x
        }
5 h# G7 w# N6 z2 W% a( a        if( queue.data[queue.rdptr].time <= writetime ) {+ \  w3 W* y, {) K3 Y7 @6 p
                ret = queue.data[queue.rdptr];
+ q# M- F; b# P/ z1 F# y' q! P                queue.rdptr++;
2 z, b7 v3 [, g8 M9 V. V0 |                queue.rdptr&=QUEUE_LENGTH-1;' N% S/ V* o5 E7 H/ U- P
                return        TRUE;7 |% F6 X2 \- k
        }
1 ~! I! j* m. d5 o* w& |4 @        return        FALSE;
2 l7 ~. j& h# v5 W) ~7 L: k}
( g: l  G. w* r% S5 Q, m3 [( k6 R$ O- C
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
7 L; O: A3 O# Z# i{% U+ @1 _& C" w1 ~6 h4 @  L
        exqueue.data[exqueue.wrptr].time = writetime;
/ x& x8 ^( P" n        exqueue.data[exqueue.wrptr].addr = addr;
& v  M  X4 n! c        exqueue.data[exqueue.wrptr].data = data;( A* b0 C5 ?/ y0 ]
        exqueue.wrptr++;! o1 ]; s1 R! v9 z
        exqueue.wrptr&=QUEUE_LENGTH-1;7 O6 j7 Q) R6 @  `0 E- w2 |( ?
        if( exqueue.wrptr == exqueue.rdptr ) {- s2 |- T& i; H. i; w) K7 {  B
                DEBUGOUT( "exqueue overflow.\n" );3 P( K) q7 c6 A7 q. e- v$ t5 _
        }
& [* M  ~$ t% D& w7 a, s}
' J- N9 e" Y- n% v
/ ~& W9 y& p) tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )# u0 r8 U. G2 p7 [' F
{
$ H" X+ c9 _' u        if( exqueue.wrptr == exqueue.rdptr ) {
, @4 j5 U  ^8 s; z1 P0 B" |                return        FALSE;8 g% z3 D/ N' [4 W
        }5 s/ g# ]; w5 ~8 l0 M# z, a
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, m( s  p6 J: Z/ `+ v5 ~/ t6 F
                ret = exqueue.data[exqueue.rdptr];; ^" a9 y$ C3 M; ]/ L' m
                exqueue.rdptr++;8 ^- P+ }7 q9 L3 S2 V. v
                exqueue.rdptr&=QUEUE_LENGTH-1;
* t9 c# _- Q1 S* e+ {* V  r) E                return        TRUE;0 q# c" w, z; T
        }
4 B3 s! |) R% P* l( s        return        FALSE;
. c* E! f5 V1 K5 h- b6 O0 c}" B9 m% O$ O! U% b' ?
: T9 t+ z6 r) F. q# ]
void        APU::QueueClear(); I: P, x% g  l; u7 S4 V
{
; I* |- t* C3 t& v3 f7 e3 v        ZEROMEMORY( &queue, sizeof(queue) );3 X! [0 I; V& k, }& c
        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 ]- ^3 I1 c( L: [1 a3 p
}
/ I, \1 B' i8 n/ {, {: x2 e" }
* Q* R0 D: Q* {" b0 e7 u$ ?void        APU::QueueFlush(); d, M4 U8 y: i! c
{: d& g4 S( h3 F1 Y& @, Z
        while( queue.wrptr != queue.rdptr ) {1 N8 ?( ]/ Q6 f. \0 q! s" @
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
/ f- L5 t, H1 M% g                queue.rdptr++;
/ p  N: e( k' Y6 W                queue.rdptr&=QUEUE_LENGTH-1;
6 g9 V# u* N7 w1 a) J        }
4 p" j8 w' g- P" _) u
! N+ p" R) i& {        while( exqueue.wrptr != exqueue.rdptr ) {
, B4 J- u5 m) K  O6 u1 P                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
; t+ B6 z/ q( Y) F, U                exqueue.rdptr++;' U8 s; O5 y% N5 ?$ {  V$ ^, T' a
                exqueue.rdptr&=QUEUE_LENGTH-1;2 J0 r9 p" v; ]9 g& B' |( Q
        }  T- K( a$ l7 c- |1 ^& Z* N( |" N& K* ~
}0 w( p9 F2 z, ^
6 p! w3 f5 ]3 y$ _
void        APU::SoundSetup()
2 e+ H6 ]  b" w8 O7 w{: U. m+ y3 P8 \
        FLOAT        fClock = nes->nescfg->CpuClock;1 a! N- H! n  B: [9 i; ^$ d
        INT        nRate = (INT)Config.sound.nRate;6 t- T: U  t. c* J8 f& u
        internal.Setup( fClock, nRate );; H" x" l- q, @1 w0 L  e
        vrc6.Setup( fClock, nRate );
, p; E0 X5 h% l$ ^/ Y6 k# ?        vrc7.Setup( fClock, nRate );3 A7 ]8 A" ?" Q+ O# h; W* l0 g. n% o
        mmc5.Setup( fClock, nRate );
9 _8 J. D* t1 x, E* f        fds.Setup ( fClock, nRate );
4 `9 Q3 z+ R% @' O$ A: O( X- A9 T        n106.Setup( fClock, nRate );
- G7 ~  v- A6 ~; q8 W% d, K        fme7.Setup( fClock, nRate );1 I: C# J1 {; M+ Y6 Q
}# c: G; Z1 l/ _
. C1 d4 X4 Y* n# j
void        APU::Reset()
4 e# h8 E, R! G/ |- n- t( u{1 T7 Y( k! a- ~
        ZEROMEMORY( &queue, sizeof(queue) );5 a, L# D( Y1 p3 u3 Y% \8 a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: L* H+ y& k$ `  v, |
8 T1 l$ ]8 R0 Y! d) E        elapsed_time = 0;2 B8 H2 o: U0 N- s9 K" S  O
3 a0 k/ n* ?- _3 I5 s# N
        FLOAT        fClock = nes->nescfg->CpuClock;7 l( ?5 E# k4 |+ p& f2 r2 t
        INT        nRate = (INT)Config.sound.nRate;0 M- e6 _' I) F1 Z( B! C
        internal.Reset( fClock, nRate );) O) @' E0 `5 o0 T0 v7 w# H9 J- M) a
        vrc6.Reset( fClock, nRate );
: p/ n- C9 j6 a' ^2 J7 n$ e        vrc7.Reset( fClock, nRate );
3 I" L; e9 m! h) k6 I! R9 B6 H) b        mmc5.Reset( fClock, nRate );
. e7 ?# f- _  T) d! u6 H        fds.Reset ( fClock, nRate );$ C% `; q& z; z0 N) m
        n106.Reset( fClock, nRate );, G; z" c$ D7 z5 w
        fme7.Reset( fClock, nRate );
( u' r5 j7 \5 L7 ?! X9 _
/ S# i, s+ L4 f: y" E        SoundSetup();
& N0 g5 e$ X2 H$ v9 E1 h5 \3 t6 ~/ L}
1 A, u+ l  I* i- G3 C# p( A) H' X$ {) c* H5 c
void        APU::SelectExSound( BYTE data )
, O: K) D) ]6 @% E- v1 ~, O{
" {( V- y9 p. o7 j( b  ^. P        exsound_select = data;
* H( Q/ e% S$ B, `' n}/ B# L. i  {4 e

9 y; B( J/ @; [  D& [BYTE        APU::Read( WORD addr )1 S" e# R3 o/ `9 h) g0 W- F
{' S4 ~% S. X! W) \* Y. r
        return        internal.SyncRead( addr );# b. \; m. E- x; Q0 T  N# D$ _8 K
}: v3 e4 l8 d- b0 i

2 O8 {: R5 r! S$ V: k9 }$ [, Dvoid        APU::Write( WORD addr, BYTE data ); g) |* O4 ^) j) S- T5 s# H
{
" a/ o+ ~- v8 a0 ~1 F) h        // $4018偼VirtuaNES屌桳億乕僩3 @) U1 k, M0 ]1 f9 u& A( B
        if( addr >= 0x4000 && addr <= 0x401F ) {  d, ]! Q8 L9 i0 F
                internal.SyncWrite( addr, data );7 ]) q% d% q; i0 U$ q* _% J2 z
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );/ D" X& k! d! d$ y& f# l" Y; k
        }2 ?7 M* F) t' j4 K! ^% a8 J" e: I
}1 u! Z9 }2 H# i

. z+ B/ `* E: x0 Z, D. D  @BYTE        APU::ExRead( WORD addr )
3 v  c6 s; M& x: q{
% s3 H' c' U! r" S. FBYTE        data = 0;1 [. A% [9 j5 }. \7 e/ Y
7 A! x: R! ?$ r! n' W/ W0 }
        if( exsound_select & 0x10 ) {" E) t; {9 w# r2 J# I; Y
                if( addr == 0x4800 ) {
- [. e9 p: h  Q. \% I                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );/ Z% D) `# Y" G, B5 L! G9 g
                }
  m- K, r2 V# [, l- v5 f" S        }
& i; X- ~, e4 I4 t7 W& s        if( exsound_select & 0x04 ) {4 {. m. d5 G. w% K
                if( addr >= 0x4040 && addr < 0x4100 ) {
+ N* v- q! r& T8 f! O                        data = fds.SyncRead( addr );1 x+ B- G3 z3 o' W& T
                }- y. H7 Q# l: G* D- \/ u
        }7 o) C& c, Z. ?! ?! k7 M: [
        if( exsound_select & 0x08 ) {
$ o- h8 W. t* E1 j                if( addr >= 0x5000 && addr <= 0x5015 ) {- i3 E% n3 V+ N  ]8 Z" l: r
                        data = mmc5.SyncRead( addr );. P" ]  g# ^% G# }7 ^
                }
$ b* {' Y: }8 G+ ~        }
" t4 d% _6 u2 a, A- s! l( W( T; C; w
        return        data;
2 [) m$ X2 k0 n0 Q}' I' K( ?" B6 T; X7 ?# P
- u9 O$ W; B$ V- e$ R9 J  U+ d
void        APU::ExWrite( WORD addr, BYTE data )
8 K5 f# j* R" H" I, P{
9 ~2 U2 H* \, e        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
. N  P$ l( t8 h; c: o; h% m
3 y' o: z0 s! ~) R1 s        if( exsound_select & 0x04 ) {2 S. r- k( O- B; R% w+ S" A8 x
                if( addr >= 0x4040 && addr < 0x4100 ) {& L. n/ ]& b2 d7 C7 R, \
                        fds.SyncWrite( addr, data );2 f" _5 Z# {; W$ M% D( M
                }
+ \" t* m* Q& ^4 e8 G7 n        }
7 R( }! L; ^5 ^1 d. p. A2 l4 F5 c) e; `
        if( exsound_select & 0x08 ) {% ]! N: z0 \: @  g' D
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# ]( N4 o  F! W3 y2 \                        mmc5.SyncWrite( addr, data );
/ `4 _6 A- ?$ C2 m! y/ m4 }) I0 d                }
2 R4 ^* j- j$ H. {; g4 ^+ M        }0 [" B( n! j5 G- C$ c4 c
}1 t9 G0 n9 c6 w1 E; X- B- c

; {+ d1 q1 g$ }  _! s  z) H# @void        APU::Sync()# i$ p6 N) r5 ^. L
{
8 W& f4 A+ O" w6 `$ |}
& ^" Q( C6 X0 f9 b0 `  n6 G
# D5 |" D$ w6 ]. m( R( y/ B- i8 x: Yvoid        APU::SyncDPCM( INT cycles )* b: m5 s  F1 Q. [% d, A: @
{
5 d8 U+ ]# S4 Q4 L        internal.Sync( cycles );" _% G7 c  c+ R# H9 a

: r! F# z0 m2 \' X5 O2 P        if( exsound_select & 0x04 ) {6 |% X+ o% [- N# U) K+ r6 M" d
                fds.Sync( cycles );
$ V" Z* T* T! K& q        }
# b9 @2 b. \9 `- H$ W: A        if( exsound_select & 0x08 ) {8 F6 Z. @" E! ^
                mmc5.Sync( cycles );: {: z+ x# @9 X; X
        }
( Q7 |0 i' f/ |* w* c; h6 N}
7 \4 J- [, n: Q7 X8 {2 k. G5 N8 z/ m6 s5 d" N
void        APU::WriteProcess( WORD addr, BYTE data )$ I: n! o/ B  ]6 y: C0 U3 b
{
  C. c' c4 J; x, Z% q        // $4018偼VirtuaNES屌桳億乕僩: d5 h- w( C: R) B$ j7 Y, x
        if( addr >= 0x4000 && addr <= 0x401F ) {
( }) a# B! ?2 u  G! B" Q! K                internal.Write( addr, data );  `/ N- q) q/ a6 z1 g% @) @
        }/ y5 \  N8 W5 [. z# a; ]0 J, f2 a
}
9 B- V2 I& \4 W! \# W/ C4 E8 J, F# s
void        APU::WriteExProcess( WORD addr, BYTE data )
1 d4 B- q; d- n{: k. T0 Z* }% o  N
        if( exsound_select & 0x01 ) {( j4 N" I: U, m: H0 b
                vrc6.Write( addr, data );4 N5 L3 {9 b  d2 [7 N( ]
        }
" O7 R1 ?3 f  A1 ]6 S# S. H        if( exsound_select & 0x02 ) {
, a4 `, E" [1 C! e" H; e                vrc7.Write( addr, data );# y, U  B4 P5 x1 M" d& w+ N0 ]3 Z! [
        }( L: [( R3 O6 O& e9 c/ a
        if( exsound_select & 0x04 ) {
+ ^3 r4 Z+ S5 @& d/ o                fds.Write( addr, data );8 |% |( H8 a) G2 a) j6 @
        }
# x- W; s% Y9 a5 l8 {        if( exsound_select & 0x08 ) {
: U4 j# L5 c& H1 v' D                mmc5.Write( addr, data );
+ u5 Y& l- J, I  U- V        }" L5 B+ C  [3 S  q. [; \
        if( exsound_select & 0x10 ) {
; }9 b; L0 s9 k# w                if( addr == 0x0000 ) {1 t% D! g1 m& Q& G, w
                        BYTE        dummy = n106.Read( addr );3 y0 _$ {8 H& T6 F+ Y
                } else {2 n0 m# f; K( S% J6 ~: O0 \
                        n106.Write( addr, data );- G2 c/ r( K/ ^
                }7 `6 I( b3 [* s
        }! E- P  {  O+ D* G
        if( exsound_select & 0x20 ) {
9 E; T' R8 O( @2 ~                fme7.Write( addr, data );) N& `& U6 n) u2 {/ l1 j
        }0 q# s0 ^( V7 g) g8 y: k' m6 E2 Y  v
}- v5 V4 N' y7 {: N8 j% n. ~0 z, G1 l
2 V3 Y9 c1 \' f8 A% W
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 f3 ~( g4 g8 {3 A, r. \
{
1 O) g  d  b' ?/ a" hINT        nBits = Config.sound.nBits;6 W, P8 L+ I' P" U, e4 H' N# Y( l
DWORD        dwLength = dwSize / (nBits/8);
" T( C/ u. `( K: b1 h2 X/ tINT        output;
- P2 E0 C! B4 r; AQUEUEDATA q;
+ x" p  W/ ^+ w3 x% Q2 ]+ l- RDWORD        writetime;" K7 w6 v- z' F# V8 O

9 T" t" R& w  Y, QLPSHORT        pSoundBuf = m_SoundBuffer;9 c5 v) B* t* m7 t9 `
INT        nCcount = 0;5 A- i, |  y& P+ Q/ o: {1 T7 |5 Z

; j9 f. s9 {$ y2 ^2 i( \INT        nFilterType = Config.sound.nFilterType;
; ^9 t+ T' N0 v( @  w, j. m0 T( s3 r! j; A# b% R
        if( !Config.sound.bEnable ) {
, O1 _( y( N) l+ G# W                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
0 a: m& `$ w* }" i0 x* V4 |                return;
) B: _- z2 b4 u; \& _        }) S2 }2 `  M. e. P

6 e6 b7 V% ]5 ]        // Volume setup; m8 R) o8 v' [  {
        //  0:Master$ H; Y% w. L* G8 [6 N4 H0 i
        //  1:Rectangle 17 x: Z5 H9 J9 E9 e5 d; o
        //  2:Rectangle 2
4 R- o- `" j" K% T: \! q        //  3:Triangle5 I9 ]& m# g8 p8 g+ K  K! U( Y6 Q
        //  4:Noise" Z- ?5 T+ r5 z2 f& U0 m
        //  5:DPCM$ X4 C0 c' u( d
        //  6:VRC6, i* @& y- R. i2 U- F" g3 u
        //  7:VRC79 Q9 Z# `& c+ N% G; ]' H( S4 w
        //  8:FDS
9 f: Q3 v% G" V, f, q" P        //  9:MMC5+ |& b: i0 L. b# X5 F$ Q
        // 10:N106& u, f" R+ D: U: q* D2 z3 U/ \/ U
        // 11:FME71 h: X; L' O" J3 {% [& l
        INT        vol[24];5 K/ j( O+ ?. @
        BOOL*        bMute = m_bMute;
) B$ a- W! ^7 t$ T) {; d        SHORT*        nVolume = Config.sound.nVolume;' \9 [( \$ ^& v1 n3 l/ X8 U

. a# M* R- ^4 F" m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
: H2 n; I4 `1 G' h* l- _
- K+ L& j5 @9 O8 G6 a        // Internal8 V6 r. e% z5 A
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: |, k6 r8 c! ^4 `
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;8 X2 u% r2 i) c
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- q! p* w3 u4 @1 T
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
/ ^5 s# p* m% ~. `' q; a        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) c3 e7 U# D1 X0 D! H: u, N  G: H  [5 ?" Y4 l
        // VRC6
9 J2 S& h& e1 ^        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- [- H9 k# n1 @  M& J, d! Q
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! V- r: `" O$ O- D        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 [) s( d* W# m; U! {' ~2 j

7 ?; R7 u. |% u  d! K' u        // VRC74 t7 b. g2 {& A
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% t+ D' n" w4 Z6 q

4 l8 I& A5 q5 T% x        // FDS/ G9 e5 z' i. }/ y5 h
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;/ H, J4 F5 B: Y) K& a$ ^

; A5 a  d% ?8 }# g7 |/ \        // MMC5$ U$ y8 B/ k! T4 f. L
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 O" _8 a6 }$ y1 }; H6 K" s( s
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; d' |( ?0 K" C5 w        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 t; u$ c: O$ G2 l& [! M( i9 f
; `3 K: l2 U. D
        // N106
) f. Q! u. }% g- s6 j; n8 S        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) x) a4 m. W. O" z+ G! }# f        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% i# E4 D% J) `4 L  ]        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" J$ e* e; s7 d3 a5 i2 W$ w; i        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 c' g8 ~) q9 B. {
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  n' `: N! L$ z        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; ^1 V  c6 o) F7 I# r9 l        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) a( D5 J- \/ w4 y" K4 R9 @' ^8 ^
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" r# E4 D$ c7 F1 d5 t- j/ O0 X
6 X( g; E% h! L1 [+ d3 n+ E8 {
        // FME7
5 ~1 N* O5 w' p' p' C        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 n2 e% W9 h3 Y" r# u! [) R$ F
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' r' b6 e+ b5 C2 z  }* N        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 u( F: k; L" g! I  {! q
5 x/ y, h/ `7 M  L" e- q) D
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;. H: o, x/ ^3 b; `* [$ E& c
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 C4 X4 O  |' t9 v4 n
/ Z4 d9 V  }: y  O! P! e. N        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 U: ]- p- ^/ \+ \4 O- _7 A  k        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
* d! X. A" U. z2 U- j                QueueFlush();
# r- m3 a9 }4 b3 a        }7 [5 {2 V. r0 r+ ^& @: b

1 R  n4 h* K& G! c        while( dwLength-- ) {* e! w' V) Z* o: C/ U& X
                writetime = (DWORD)elapsed_time;/ n, p' O$ V2 y) t' s+ `1 E6 Q
! r1 w) h# x2 X
                while( GetQueue( writetime, q ) ) {6 q+ S8 B7 C# C( J" W
                        WriteProcess( q.addr, q.data );
5 c* B' i2 h, `% D2 n/ q" |                }
0 S) |3 J* C. G% w. E0 v5 Q: z& O4 u6 l, R' ?
                while( GetExQueue( writetime, q ) ) {
5 {% V' i+ ^6 c" `# R                        WriteExProcess( q.addr, q.data );
! e4 B& i( l" f! U8 C& [9 c                }; c% {) ^- l7 N% R5 L
+ `; g' B; s( G+ l8 G
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
& }9 u2 J. i( J$ I# c                output = 0;1 C6 f1 n" z: }
                output += internal.Process( 0 )*vol[0];
0 X) K, o+ H- Y                output += internal.Process( 1 )*vol[1];
5 d: V: C* Z3 i8 V# l/ X# t! P  n( y7 v                output += internal.Process( 2 )*vol[2];
: _/ O/ n/ {: J0 W( X3 V                output += internal.Process( 3 )*vol[3];4 P  r0 h. U, ]$ |4 r5 R$ k. }9 P
                output += internal.Process( 4 )*vol[4];
# s8 s; o0 {! w0 J! R1 f' z# \* C# b* v. s/ W. H: _9 Y
                if( exsound_select & 0x01 ) {
& z  U% j% Q# @/ |( S  Z$ X' [4 f                        output += vrc6.Process( 0 )*vol[5];1 E: s) I8 |# E4 z
                        output += vrc6.Process( 1 )*vol[6];
& N8 B- Z: V% e0 L4 q+ Z; W                        output += vrc6.Process( 2 )*vol[7];
7 M$ w, v. |; [4 d                }9 @5 D8 K  T9 U( m
                if( exsound_select & 0x02 ) {7 s: }, P$ L$ B' B
                        output += vrc7.Process( 0 )*vol[8];% G" I7 [3 R! ^; Y6 I$ `
                }
  ^0 }( v! y& w  p3 }9 V0 I/ x1 d) X                if( exsound_select & 0x04 ) {
# T/ d0 ~- U: n" l  Y! ^4 F4 c                        output += fds.Process( 0 )*vol[9];4 U) ^6 Q8 ~4 P% u% M. r
                }
  A: A9 T4 A" R4 d) |: w" C5 N                if( exsound_select & 0x08 ) {' _8 M0 U, n3 a& O2 t  G- N
                        output += mmc5.Process( 0 )*vol[10];! D: S6 [9 R- d  J* j1 h
                        output += mmc5.Process( 1 )*vol[11];8 r0 C/ C3 V7 q7 v) i' N7 y
                        output += mmc5.Process( 2 )*vol[12];
& L8 ]# P% ~6 [: s5 x7 C                }
4 W4 x9 u4 O% k, z                if( exsound_select & 0x10 ) {/ c" L' @+ \+ W, g
                        output += n106.Process( 0 )*vol[13];, M7 I7 d  B7 Y- f
                        output += n106.Process( 1 )*vol[14];: h- I! e  O; w
                        output += n106.Process( 2 )*vol[15];$ H. u0 B3 H& n0 J  u% x: b' R
                        output += n106.Process( 3 )*vol[16];
# l% Z; g0 `8 O2 O+ ^- }# A0 {' ?                        output += n106.Process( 4 )*vol[17];- [  D4 [, a0 l' G
                        output += n106.Process( 5 )*vol[18];
3 v  `" t1 \! k) V% H+ [  r9 v                        output += n106.Process( 6 )*vol[19];# {# Y) S8 C4 k% P3 t3 A
                        output += n106.Process( 7 )*vol[20];. n5 N4 q/ J2 E/ B4 J$ n
                }1 I- K$ R, P* R& r$ ~: S& v
                if( exsound_select & 0x20 ) {7 H& O1 K( W! A
                        fme7.Process( 3 );        // Envelope & Noise
$ ^; F8 N2 d4 U                        output += fme7.Process( 0 )*vol[21];
  T' S* \, N& X3 p/ E0 E6 A                        output += fme7.Process( 1 )*vol[22];2 {$ {: q3 b8 U0 S0 g7 F4 q  o8 g
                        output += fme7.Process( 2 )*vol[23];8 j4 t, @0 }0 w: f$ \
                }
- L/ M( J. @: G) m2 p# i# D6 F5 f% D9 Z' T  f
                output >>= 8;
5 c6 P. F. \' `5 Y
3 _/ b3 f( q$ b5 A                if( nFilterType == 1 ) {. v' J9 G% K+ ^
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
0 n2 K  A# d1 X% Z5 d! c) D# {                        output = (lowpass_filter[0]+output)/2;
+ [: _8 e$ r6 [0 W$ x6 {                        lowpass_filter[0] = output;: x. }7 Z- f7 B+ j
                } else if( nFilterType == 2 ) {
) e1 G' V7 E/ s. Z: R                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ V. H5 t* W% t& d4 d" a5 H                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;' {2 I- o0 q* R8 V; V/ {5 u
                        lowpass_filter[1] = lowpass_filter[0];
$ ]3 f, x( d7 ~  H                        lowpass_filter[0] = output;& b( N! s$ ^: k. e
                } else if( nFilterType == 3 ) {
5 `2 P1 `  T3 j5 K                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 x& X5 O  B# ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;# \& c) V- R3 I6 W2 ?% d- Q
                        lowpass_filter[2] = lowpass_filter[1];
+ n+ Q9 m# x, _9 g, J5 X                        lowpass_filter[1] = lowpass_filter[0];
, y& u5 J; Z6 o0 g( V; t" N- y& L                        lowpass_filter[0] = output;; i8 V& B% W2 U0 ^$ }
                } else if( nFilterType == 4 ) {
9 C4 u# J( P! N8 g                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3). F7 V$ R- X- B% p& Q+ R- q
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ K4 R9 a( F) P& O6 x3 x# K6 s. V                        lowpass_filter[1] = lowpass_filter[0];# T  J) ]! J3 |  P  X0 o" p
                        lowpass_filter[0] = output;
( O& M& j/ G2 I5 B                }4 n( L+ `& j4 x. T/ |( [

( j2 B" \, o) v% t: g2 U  c#if        0
2 ]. A7 R8 m( {1 f                // DC惉暘偺僇僢僩
- N; r  P. R9 e$ _0 b6 q" D' u! r. g                {
/ m( C8 i' X8 G4 A. f$ G4 p; z                static double ave = 0.0, max=0.0, min=0.0;
& v- ?& |$ k! R6 F, ^                double delta;+ `5 q& s; |( p4 X- }& b& s
                delta = (max-min)/32768.0;
1 [- {4 @& O, N                max -= delta;( L& u; G1 B- J
                min += delta;
! M& K- ~/ b- X2 r                if( output > max ) max = output;. [$ R9 W8 {& n$ t2 b
                if( output < min ) min = output;3 Y) L# N: @5 k' S& p2 I
                ave -= ave/1024.0;# O) G, C" L1 t! ^, P
                ave += (max+min)/2048.0;
9 g7 L0 c# l) o" {# C  a$ ^                output -= (INT)ave;
- Q% A" Z. X2 \9 K0 c9 a) W                }' ~+ e3 [, I' `, C& p
#endif/ f3 e+ ^2 r2 s6 Q# [' I
#if        1
. J! J1 X- F0 D" z                // DC惉暘偺僇僢僩(HPF TEST)/ P7 l5 N$ q' W2 ?& X
                {
  B. c1 }  b, ?9 o//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. X; ]( G, x' H                static        double        cutofftemp = (2.0*3.141592653579*40.0);1 E, L; ]. y6 Z& x" c; P9 B
                double        cutoff = cutofftemp/(double)Config.sound.nRate;4 Y, N3 D: E7 A- Z" y  W7 X9 Z
                static        double        tmp = 0.0;
' c1 I5 T9 j2 D7 D                double        in, out;
& S& N) q$ C8 [' e+ X
2 \6 g8 q! Q1 y% D4 Y: J( }* a                in = (double)output;3 U2 \1 F, j! Y% O9 g
                out = (in - tmp);. U" w# Y4 }* b5 D$ I( j
                tmp = tmp + cutoff * out;
, U: E+ Q3 r1 F; Y
2 G" ]+ ^* s* @6 q" \                output = (INT)out;+ C! |: K! s1 I. e8 a( G
                }. M3 z. [3 D6 O; L" p- K
#endif# X$ |/ G( m" S0 m- h+ {
#if        0: T( B$ X3 H0 E! n" `- D% K3 r' b; z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 z* ?3 x2 E' p3 m
                {
) o: L8 r. D4 G8 p! {/ m. m% a                INT        diff = abs(output-last_data);# f  ?2 k, `8 t0 W
                if( diff > 0x4000 ) {
' Y2 V0 I4 Z9 E1 m' {, J0 R- g                        output /= 4;
3 c$ {/ ~9 l% d0 n! v                } else
) c2 c& n4 x, ?5 p                if( diff > 0x3000 ) {
/ N/ {& o3 l/ l/ L0 u$ y                        output /= 3;
  v" U9 i6 g9 [) V1 V2 r5 |                } else
; k: C' D7 {9 c" @# ~# @                if( diff > 0x2000 ) {
; {2 N; G6 y- Q3 ?8 `+ Y, Q* F9 }% s# |                        output /= 2;: f! r& k" k! e  F
                }+ H2 Y+ ~" ~! a) y( P% ^( g4 W3 p
                last_data = output;5 ?  I1 X0 `3 E. J
                }
# f" Q. s0 M7 t  V#endif
+ ^* B8 I9 J2 f5 z) E  w  P                // Limit
* Y! t( m# _2 c                if( output > 0x7FFF ) {1 g/ R/ Y6 G9 j# p
                        output = 0x7FFF;5 U  T+ F$ s8 t( T" s% I
                } else if( output < -0x8000 ) {0 l! o: r2 q3 [- b/ B8 x4 }8 h- b0 t
                        output = -0x8000;
$ N) l% f9 L. n8 G" W8 _* n8 e* Y, g                }
9 Z) R, C! U7 [4 g; V' ?1 L( G4 c/ s$ |, e- G. C5 B5 t+ U
                if( nBits != 8 ) {
# H  v- b* \! B) e9 Z                        *(SHORT*)lpBuffer = (SHORT)output;
9 s- i% t0 A$ h9 f6 v                        lpBuffer += sizeof(SHORT);
8 i1 B) M6 w, d1 h                } else {7 v' U+ Q1 ?' _1 a  Z2 ?
                        *lpBuffer++ = (output>>8)^0x80;
% c/ {$ n2 q2 f& z                }. p! i, T( x7 i. ]% d+ M* b

& S0 r2 \* ]3 I- V& F  l                if( nCcount < 0x0100 )- t: r# B! f3 b: [4 V9 m
                        pSoundBuf[nCcount++] = (SHORT)output;
+ I# R) ~, `& n7 _4 p( r" B: C7 L" G+ q' e& j. S$ {) ~4 K
//                elapsedtime += cycle_rate;
  U; b5 \3 z: A) @; Y( a                elapsed_time += cycle_rate;+ t; b; V& c6 S" ^7 q
        }
, v2 s. p% v" A- L
5 @" ^/ D# S) _% u2 U#if        1
, K& L1 W. W4 E# `  O% h3 _        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" {, h8 ?. w( O& b& Z
                elapsed_time = nes->cpu->GetTotalCycles();
% x( f0 z8 [' s% A* q0 v6 s" \# J3 @2 o        }5 ]! Y& U% R* J8 @6 K" s% J
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 Q- g: _6 X5 ~; Z& Q
                elapsed_time = nes->cpu->GetTotalCycles();+ m' M- F* m( [% H) A
        }5 H9 C- R: }9 Z
#else) _* z4 _) a  S5 l% e$ \
        elapsed_time = nes->cpu->GetTotalCycles();' _5 I* j( A- b1 N* Q  {0 _
#endif" @6 K/ s  O/ b) t. |* z( W0 V1 u+ I
}# e/ p$ y; R8 F+ f; S. }6 v

7 y  L. ]6 X7 T/ J8 |% K- J  O% d// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)2 ^1 D4 M1 `& ~- x2 _5 N4 [( l4 m
INT        APU::GetChannelFrequency( INT no )$ S6 G4 r' C7 c$ r) ~9 D; K2 G3 r
{
, j5 {7 g& z% v# t- B6 j        if( !m_bMute[0] ). [1 e3 V3 Z$ u4 q  o
                return        0;0 a: k) {* ]$ ?
( ]* H+ I8 U9 f, d' ?2 E
        // Internal# |9 ^# O  n* [) f- E, [# h* G
        if( no < 5 ) {
" W3 M: k: l+ B" q5 [; w                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ e( ?' _8 a* |
        }
4 A4 a( w5 ]( u0 C' f+ h2 `        // VRC6
& t3 \; m1 W5 y$ ~0 g; ^# q9 f7 }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {7 ~& W7 ~! F! W, F- ?# f5 o* Q
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;6 Y  x, ?! Q+ R# V. ]
        }
: Z: }/ h/ q9 G! k        // FDS7 E" z2 n, Z7 R0 L) S& ~
        if( (exsound_select & 0x04) && no == 0x300 ) {
) F- f/ b5 r3 U  v' E4 Y                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 w+ t) D! K# K( x! e* n
        }" ~$ J+ D$ ?1 F- Q
        // MMC5
% ^  B) h. |' \! h        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
* L6 G+ S& \, [4 X* t                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;3 F4 ]% {0 d% n, ^0 \* D
        }
- G8 ?# {4 H0 U        // N106( i- Q% _+ _, _
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 E3 L# n( c4 J3 T( N                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
1 x2 @3 A6 s0 \, H: h8 ?* g. D        }
2 ^- h4 ~( c  F$ i( Q$ L) L        // FME78 ]9 Y, T  z" M9 Z
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
1 \$ F% l. X5 k; }                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
6 Z, h# |: v8 I        }3 u3 X5 d4 z9 e+ q/ @* z
        // VRC7# N3 T, g5 q7 u  j) o  q
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
* [0 e% N( j; |) ]1 k5 C: T( n                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
% C# O& F9 P! T) @/ ?+ [2 M        }
4 ~( n: r* [, J' ~2 Q! l0 `        return        0;
; [; B/ o% Z7 m4 T# t}- K1 V; ^4 L+ J- w

1 T8 }+ ~3 b# I" E1 d// State Save/Load
8 q+ t5 J$ f. n2 Q) D/ Wvoid        APU::SaveState( LPBYTE p )
$ }6 T4 p. Q# O! u{
4 W9 s$ O2 K+ h% Q5 E#ifdef        _DEBUG  I2 s/ j& [4 ?
LPBYTE        pold = p;: v7 w. K3 ?! _: f1 }
#endif0 Q# v) B. Q) E1 j. v# p; q( B
9 w, @; C8 u: b$ M/ K4 N
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞/ K* `; }  k: u+ t( u8 o7 o
        QueueFlush();
7 d6 L- E6 k* o7 d+ r7 ?6 m9 Z5 c
        internal.SaveState( p );
& A. p8 [1 c9 L% X8 c% R1 R        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ e9 B; ~  B* _6 Q
# ]/ k5 B3 I  m/ C. q$ q2 X        // VRC6
6 X% q& a* E# F4 }. z5 a        if( exsound_select & 0x01 ) {
2 c  z+ G  Y5 U' v  T) [1 _" p                vrc6.SaveState( p );  e. ^( i' Y& R+ U' v! V/ G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* H8 [$ y0 k8 v2 j  m2 W        }
& ~$ T" @/ z  Z  O        // VRC7 (not support)# W+ g' i! ]2 h( j7 a( H' B
        if( exsound_select & 0x02 ) {# K' v: C, w8 h/ g0 o9 ]/ W8 o
                vrc7.SaveState( p );, a9 [8 V1 j6 G! F5 e. d
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ c/ p( i1 u7 ~/ N+ k; U. K; b
        }
  k& k; B. R7 i9 [        // FDS& ~) P7 R& g- |9 P- J
        if( exsound_select & 0x04 ) {
$ q8 A% \% e2 g$ [                fds.SaveState( p );
% |4 f8 \7 w. F                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. d# O) k" k5 X1 `0 e
        }' a' I& K& ~7 Z0 B; w9 h
        // MMC5
0 r* g& D, ~7 l7 V. Y        if( exsound_select & 0x08 ) {
6 F5 L7 Q* K# y) [- n6 S+ Y                mmc5.SaveState( p );! t0 c. Y2 M% d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. n+ ]7 d+ N- e* ?( U        }) Q3 |1 E: D  @8 R
        // N106
# T/ p& m* K" h& x( x9 C        if( exsound_select & 0x10 ) {
9 v! x( ?8 e3 B5 Z; H: o% d/ E                n106.SaveState( p );& M7 R$ t; I' m% M
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ ^/ t' e7 l5 C! V$ t        }
& R, m) e# B3 M+ x3 A* ]% B        // FME7* O( W3 G% t8 C
        if( exsound_select & 0x20 ) {
3 p" b  g" l1 [* l                fme7.SaveState( p );( T/ w  R7 v% g0 G+ x
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 `' X( `" m. k! _4 ?2 x
        }
' \0 Y* \0 ?. [( T! `
) p) a5 Z% K; k3 G, A$ _1 f$ f5 ^#ifdef        _DEBUG7 p6 J: V4 R: u
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );' C6 l& c2 M( {0 S# ?+ U
#endif
$ [$ w. O8 _2 [' Q8 C+ Z: @$ E}: J& p! B7 W4 f$ [

! A( g% P% ^3 f0 a6 u4 Bvoid        APU::LoadState( LPBYTE p )
# @' |) S0 s8 K! l- P6 P, f{
/ c& l6 `  _4 i8 v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡1 K( J- S" J" v' b6 y+ {
        QueueClear();7 m' ]3 G! }* G6 y5 E' K% J! I

6 I; A8 R. q+ ~# S: q& |        internal.LoadState( p );
: x& m$ c! a7 k1 E1 S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( `/ Q2 Y( z( ?! l0 y1 H/ i1 p- o6 c# _" t) k% c2 f
        // VRC6
+ _, ]4 ?% K0 |& W) W6 C7 T8 d# S        if( exsound_select & 0x01 ) {* z4 q2 q. n, Q$ C; Y& S
                vrc6.LoadState( p );
6 K% Z4 S# H+ p; \% C7 ^1 _" ?- r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 D* f" W2 t  f' M  }; M: P( o
        }
1 h  y  H& r" M  y+ W! u, n        // VRC7 (not support)0 j; C2 @  p; a8 o
        if( exsound_select & 0x02 ) {
8 X8 e. P& D8 R& W& ?: I) v                vrc7.LoadState( p );6 I6 K0 r5 C1 x' z' k% E" h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ x7 \8 a+ N6 W# n9 |3 |) l        }( N* a; b. E, m. C9 X: W
        // FDS4 R, X% x( Q) j. |# ]" ]; I
        if( exsound_select & 0x04 ) {# g5 m. W% L: z5 I7 Y
                fds.LoadState( p );
! l$ C7 b- B6 s9 ]( h! a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding, m# ?5 s) A5 |* B7 T* d
        }
  k  }  `& \4 v6 n5 r0 j        // MMC5
7 P. C0 W* }% `. Q2 r. V        if( exsound_select & 0x08 ) {' f# m5 L  W8 i2 ^5 C" s2 r$ N
                mmc5.LoadState( p );
3 L$ @0 Q: F8 X- A9 l- V( f                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 n  ]+ O6 n& z, N( p
        }
  D- n5 `( p6 D4 L$ c* w        // N106; n: W1 _2 s& q) n2 i0 V
        if( exsound_select & 0x10 ) {+ ^5 ?0 q: G! t/ I# b% G8 v- b+ i
                n106.LoadState( p );' R8 k- z$ {8 r: {! W
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' g9 g, a: F5 ?7 v- d! X2 T$ D8 a# K/ ?
        }
) i! N/ c4 D9 {  t: E        // FME70 z! i; C( i8 l$ M% R  ]
        if( exsound_select & 0x20 ) {
) c& j, w* a" g                fme7.LoadState( p );; r, D* |4 }( A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; R7 a; {9 B3 {0 _. T% _5 b$ n# ]
        }
* p! T! [3 T" [3 t}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 s* [% O5 F; E4 ^
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
7 u8 P- b8 C6 d* C6 Z" v" U感激不尽~~
- |! e; x: v9 Q. }
恩 我對模擬器不是很有研究,
' h6 k  j6 B1 k- B' E" M2 U雖然要了解源碼內容,可能不是很困難,
$ b+ j% {2 B% T9 W9 ~# [& S) \7 m, y不過還是要花時間,個人目前蠻忙碌的。
2 Z* x- ?/ M6 z. w. ^7 H- G5 W5 O$ W' Q* ?
給你一個朋友的MSN,你可以跟他討論看看,! g6 d7 J. }5 T+ Z9 ]2 z5 d
他本身是程式設計師,也對FC模擬器很有興趣。
, E/ L0 @: P  h3 z
8 p0 K. ]' G9 G) {2 l% e- ^1 nMSN我就PM到你的信箱了。4 h. z. K: I, z! V7 D3 D( H; Z
- t2 g$ ^! N/ ~! Q! I! e
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ( B. b% H# R( e
呵…… 谢过团长大人~~

8 Q9 Y' P5 h1 h+ k2 F
; e: V0 P# X3 L' ^$ U( p+ t哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
$ `. P% U3 a4 b1 e  k团长的朋友都是神,那团长就是神的boss。
6 Q6 |* W- T" s
哈 不敢當,我只是個平凡人,
# D0 u) J& H. r) s; _$ b9 w, o, n) ^3 t要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙% H2 l0 K0 _, s; f2 R% ^
ZYH
2 [& h$ C6 H/ h) p" @QQ:414734306* z, Z/ W" {& c, ^( s: o3 Y8 ^0 R8 u
Mail:zyh-01@126.com
) d# d' y* h7 t1 r. Z9 r- ^* f7 L6 O$ u7 x0 T6 r: x2 p& D% s
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
0 N' _$ C* G! N& `$ _+ Z) _% O/ a再次对团长大人和悠悠哥的无私帮助表示感谢~~

2 v& w: `- Z: A. C9 [: q+ d4 a不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-31 21:44 , Processed in 1.099609 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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