EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
1 l8 S) M4 |) C* d/ }, R  [+ mPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 K7 V- q- H. U
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 W0 h  H& r0 [4 [1 l0 L7 N# @
这里有相应的模拟器源码,就当送给大侠了~~) K# d/ J+ A6 ?5 ^* J5 N
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ) q; u  C$ ~, t1 L
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 T) A. Y& a/ ^0 h" E楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
0 N, f# s% Z2 D& P, F这里有相应的模拟器源码,就当送给大侠 ...

3 `7 @" I/ Q1 C" W聲音部分(Audoi Process Unit = APU):( u! y+ n2 _. F; |9 x% ]' n
.\NES\APU.cpp
4 S/ ]9 x9 K2 c. v; w4 M6 v7 n) I.\NES\APU.h
3 P% \" E0 o7 }+ w1 m7 D' n6 a0 @8 U( H, S

# H) _+ h% g& I' `2 R0 t影像處理部份(Picture Processing Unit = PPU):
6 M( h. _, D# ?. E" u; j: b0 _.\NES\PPU.cpp
6 \/ w- |: Z6 d  H( l) R.\NES\PPU.h/ ~2 a: ]5 Y% ]" u4 z3 `  }

% s& ?0 a+ D: \  F; D/ j' C# X5 l如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
4 C; c2 \/ N8 [% s' ?; i感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:+ u9 F% T3 |: ?. O
(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 k3 C: N2 ?7 t+ m
//////////////////////////////////////////////////////////////////////////
0 i+ k) r: ]! @9 S7 ^; o3 H//                                                                      //% Y  x+ }. K/ o  t
//      NES APU core                                                    //
' Y, r9 X# v3 S7 |! q6 Y/ M  {//                                                           Norix      //7 _+ K# I3 |2 g7 C. u) ?
//                                               written     2002/06/27 //
5 y, |5 K5 Y$ z! p6 C//                                               last modify ----/--/-- //
: k$ l. h" Q$ M/ ]9 e//////////////////////////////////////////////////////////////////////////
4 {% ^; Y( T" I* M6 ~0 Q- J3 D#include "DebugOut.h"
0 q+ P0 E6 W9 x7 I, A8 ~#include "App.h"
. d+ s. I5 L3 t9 t5 [# t#include "Config.h"
6 |8 D  S2 _+ l/ I
# w0 ^: r1 |8 f7 `2 b* T9 D#include "nes.h": y" C# ?# \0 s, C
#include "mmu.h"
* n" j& I+ e. J5 T#include "cpu.h"
5 _' @- y, D- C4 v/ l) R#include "ppu.h"1 v! v" r( J4 Q: @5 r2 `; V2 k
#include "rom.h"6 E, f+ w2 n% g! f
#include "apu.h"
* F* g& D5 \+ M( C" b
' G/ ~1 Q) j; g) b' c// Volume adjust
: u0 w. k1 g( l  K1 }# p1 P: i// Internal sounds
- g* _' ]/ G( Q! {# x+ _: _0 q#define        RECTANGLE_VOL        (0x0F0)( {% z( x/ _7 q9 A& [4 O
#define        TRIANGLE_VOL        (0x130)
& u1 O+ f0 U1 E7 k1 }#define        NOISE_VOL        (0x0C0)
' C: u+ R6 k! O2 v#define        DPCM_VOL        (0x0F0)9 h7 K1 R9 M% d" b1 a( h
// Extra sounds
( Y8 r9 w0 ^/ t3 p#define        VRC6_VOL        (0x0F0)
1 g- e. f2 A2 |" v#define        VRC7_VOL        (0x130)
$ ?& T+ H+ K1 m) D#define        FDS_VOL                (0x0F0)
! @9 K! Q8 o9 Q) b1 j7 F  ]#define        MMC5_VOL        (0x0F0); I1 Q9 ^+ q2 B$ h
#define        N106_VOL        (0x088)
4 x% o$ n8 ^! x: R2 a& A#define        FME7_VOL        (0x130)
; T  F( t8 \- l0 ?0 q; O6 H) ]% ?0 b! T' k8 n
APU::APU( NES* parent )
3 T, y' U% E; I6 M( C, P/ G2 b  W{4 v1 y1 J1 ?5 R" w# K! ^4 j! @
        exsound_select = 0;
  Y* G' l7 S* z3 b2 i; R# V
# ~1 j& V+ g0 W        nes = parent;
/ ~( G. }4 _+ u; Q        internal.SetParent( parent );  ~( M+ l; ?3 `( q& a

$ X+ N4 [( T' C# Y# P0 d  k: G: W        last_data = last_diff = 0;% f) ~4 |. s/ O* R& ]) N9 _8 J9 e
3 F! E: K0 N% R+ s" X% b
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );% y0 v. J: B  p0 e. Y  G

- O- m$ l2 [  f' s) `$ }  b* n        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& {( i6 w' \2 W0 p$ K        ZEROMEMORY( &queue, sizeof(queue) );  ]. i) S2 I% I& t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ V- i" c' k  x

1 O5 d; ~/ L+ B        for( INT i = 0; i < 16; i++ ) {
9 Y# v$ V' C  P4 E* f: j                m_bMute = TRUE;( ~0 R4 ~: O( K: n% Q" v* c
        }
) b4 t' F9 m0 L/ y  N}
( ]+ ?1 Z4 b" y$ ]; u0 r4 y3 j/ n  f' B
APU::~APU()# O" L  q3 ?7 B: C7 U& T' J  g
{; X, _: _" X" L* F" l( L+ `
}
7 d% ?5 ]9 C0 @: b/ T- R, s, }) s5 f; W8 C, N) W' [/ C
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 ?  y$ u$ B2 o( f  X( I
{" B! D. n' G6 q0 i( }0 K
        queue.data[queue.wrptr].time = writetime;( |  s# A3 k8 X% J8 G6 S  r
        queue.data[queue.wrptr].addr = addr;
$ A8 I& x3 W; }        queue.data[queue.wrptr].data = data;
; D7 x' p# w6 v. y4 N: f        queue.wrptr++;
# b+ k9 |6 T3 }: u& |! K        queue.wrptr&=QUEUE_LENGTH-1;
* |; `  @2 `- }  f' K+ N        if( queue.wrptr == queue.rdptr ) {. e0 s2 P' f3 E: J
                DEBUGOUT( "queue overflow.\n" );
* F0 o' s! f. J        }
0 i) }6 m0 S: K1 C}
; s5 t8 q, X8 u# [! r1 j/ `# I
* v! J8 p. D( j6 d( j* N* K# N5 eBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  u! T4 R7 D: e4 j$ j{$ @: H. q$ ?2 C
        if( queue.wrptr == queue.rdptr ) {( r& V) C9 O: t) ~1 ~
                return        FALSE;3 @2 l- i( V8 P/ M5 d- n
        }- j: L$ _4 T& A2 }
        if( queue.data[queue.rdptr].time <= writetime ) {
: k1 v4 Z, c0 Z: w( t                ret = queue.data[queue.rdptr];
. x1 [/ a$ v$ i1 o  q2 W( f                queue.rdptr++;
# P! t4 F( y2 w$ ], H) r( o                queue.rdptr&=QUEUE_LENGTH-1;5 O2 m) C7 S; @) l  E
                return        TRUE;8 E8 y) R" |- C* N6 L8 H- f3 j
        }+ \. ~* Y; z; ?$ g# v2 y8 m& L3 ~
        return        FALSE;
# i* H/ p  g% E% V, V% k}
8 |( y$ a7 _( E; m( _0 Q. c4 b8 ?" A3 l2 t+ {. Z1 E
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )1 s  h5 |7 S+ R6 ]  ~/ l) E2 i8 u
{3 F2 |/ `/ u: p9 o% z7 R
        exqueue.data[exqueue.wrptr].time = writetime;
) H/ B; s. E/ c6 b/ u, E! E        exqueue.data[exqueue.wrptr].addr = addr;
$ [5 }$ V# n! u) P6 H% X        exqueue.data[exqueue.wrptr].data = data;, ~- ^+ n$ r3 e
        exqueue.wrptr++;+ F5 _' Y0 k, e3 r0 j* S
        exqueue.wrptr&=QUEUE_LENGTH-1;
4 r; X  o: s8 t  X* s$ D3 V        if( exqueue.wrptr == exqueue.rdptr ) {
% s) J5 v: Y; h* K; ~3 a9 U                DEBUGOUT( "exqueue overflow.\n" );
9 T  ?- [& z, E. L9 b  g        }* N: q! f/ j7 U
}
& p; L2 _7 _) x" S* C8 V+ d0 H8 Y& k; a( r2 ]
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
: p' g6 l. D, x+ [; ^) y* t{
2 O- |! T* n# R' \0 C% T5 c) j        if( exqueue.wrptr == exqueue.rdptr ) {7 j- P' ?" r: U" n' M
                return        FALSE;
% c  S& ^, D0 s& g0 b6 A1 b        }
- I# o0 J( E( u' Y! r, P  g( p        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ S" `. L* B/ x0 i
                ret = exqueue.data[exqueue.rdptr];
% b7 X& y( W/ o- v& ~                exqueue.rdptr++;5 A" y5 W5 d) _* [
                exqueue.rdptr&=QUEUE_LENGTH-1;4 C+ W+ N3 G$ U- C) ~
                return        TRUE;
3 \" P% v! Z; l2 s/ m/ h        }1 _! v( o4 P. Q. C9 [
        return        FALSE;
# A0 c  g/ N! I' M( X* V: h; _. \}: U# V( ~& v$ ?- |4 c, W
& `) d, g1 s; e
void        APU::QueueClear()- e3 u$ Y* R1 e7 }  l8 D" j! ~) M
{$ H; U) z- _6 O" P  `
        ZEROMEMORY( &queue, sizeof(queue) );6 h& @2 _* m9 B2 |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( h  J2 u4 d, }
}
- v, |2 C& y8 W0 P) o9 J3 N7 v* q$ I# ]# C
void        APU::QueueFlush()4 b: K. ]) J6 o1 N
{
# R" D* W; k9 A4 Z! u        while( queue.wrptr != queue.rdptr ) {
; I% s/ I. V$ @. ]" R" e; w                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );1 d! N) H- |- c; v/ Z( h
                queue.rdptr++;2 ~6 c3 Y. K8 ]0 W4 l7 p% S
                queue.rdptr&=QUEUE_LENGTH-1;0 d5 o' {. o$ X3 |% ^) v0 E
        }
( k% a6 a- K9 M+ N  G: A
* g( }* C2 a. h5 V) z        while( exqueue.wrptr != exqueue.rdptr ) {
* P% C. Y. o0 X- k/ j# K: X% u                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );' _  S/ J3 q- F( l6 t9 m$ h  t
                exqueue.rdptr++;
) ~' ~4 b$ D4 \                exqueue.rdptr&=QUEUE_LENGTH-1;  d& X3 b" m  A- O  M: J. W* R5 o
        }
, V3 ?/ W  y- A+ O/ ?$ [& F}; a# R. L8 X1 A8 ~9 y* k) X4 H( B0 y
2 i$ w& ^8 \# }
void        APU::SoundSetup()1 j% Z+ l; B0 C! Q! z7 a. d# m. ?
{$ Q3 T7 }) V' t: Q
        FLOAT        fClock = nes->nescfg->CpuClock;
. s' X8 o- D8 S9 g        INT        nRate = (INT)Config.sound.nRate;4 X; G* r+ ^( y7 l2 i  l
        internal.Setup( fClock, nRate );6 t$ f8 K$ E& ?+ F
        vrc6.Setup( fClock, nRate );  I' J* s) m0 {$ d% J9 b& C; Z
        vrc7.Setup( fClock, nRate );5 t0 w4 G  n  n: s# o+ @) N
        mmc5.Setup( fClock, nRate );
/ }9 U: w; e! k" L) h$ r# R' D        fds.Setup ( fClock, nRate );
0 X& X9 U! L* A4 }' O; I9 h2 a4 t        n106.Setup( fClock, nRate );
9 w, F5 @) ~1 Z9 {+ U" r$ [        fme7.Setup( fClock, nRate );- ?8 y) E+ ^2 z" \% y2 l
}; `" G7 P% p! I5 q
% v  m+ A, x( c* Z' B
void        APU::Reset(); a* j! S( a1 W0 ^- N$ e! C' ?
{/ O  ^3 T' V( c4 P
        ZEROMEMORY( &queue, sizeof(queue) );8 `: O: X; k+ u; I# b; ^
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# w$ p5 m' u* w! r5 Z
9 J# a! p2 N/ ~7 x8 {0 W- ^3 [        elapsed_time = 0;: ]5 O& z7 x5 ]0 H2 a

. o1 Z9 l5 C, @- ~3 W+ g2 `) @        FLOAT        fClock = nes->nescfg->CpuClock;
' D) g( d' _8 l3 \' E4 F  V: O        INT        nRate = (INT)Config.sound.nRate;
* [& K& g& [, u  _6 r" r9 ~        internal.Reset( fClock, nRate );
) ]6 W/ T3 d* \- o% A: f& [        vrc6.Reset( fClock, nRate );
. E3 {2 l. S3 e1 S8 n  f$ |+ C0 P        vrc7.Reset( fClock, nRate );
% n3 @5 o& {0 n3 E1 s' w8 t7 l        mmc5.Reset( fClock, nRate );
/ `* L9 R% Y& A  K; u+ C/ B        fds.Reset ( fClock, nRate );: Y, j  o' z. q0 W& X2 ^- ]
        n106.Reset( fClock, nRate );! A8 l) Z8 k8 s; s
        fme7.Reset( fClock, nRate );" z1 f' ?: U+ e% l" h' i
, Q  }. l  h% S9 R- h, L8 _
        SoundSetup();
( n5 i% p) J. t! |}
3 @1 S  h. \" @6 T* F! t9 W
) J7 I' r$ x; a6 J2 a+ r# C9 Cvoid        APU::SelectExSound( BYTE data )0 M1 X, w* u7 s0 ]
{
1 W4 ?. E9 Q+ A* u        exsound_select = data;! T" P8 Q& d. e8 N2 t+ U4 n
}) q: Y) m" |+ a6 W0 |

$ w' g  U4 E& n% |BYTE        APU::Read( WORD addr )
& y1 A# b  U2 I; C# t" o) _{
0 T0 p4 h$ N4 N0 w: _        return        internal.SyncRead( addr );# o8 l3 R. H' f" @. }( W
}
$ b# n: j9 k+ H+ N# X  }& i% J5 i( }# m. f) A. Y. o
void        APU::Write( WORD addr, BYTE data )
0 Q9 s, G- E& B0 [  ~{7 ^8 E# ^- I0 s$ U9 l. E$ v
        // $4018偼VirtuaNES屌桳億乕僩3 U* R, G+ A6 [5 y5 I+ P1 s( b
        if( addr >= 0x4000 && addr <= 0x401F ) {
1 t! p0 O2 Y" e  @6 ?& }                internal.SyncWrite( addr, data );
9 X" [9 B' q4 f0 o5 ]                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& r' P; Q, q, A4 m0 S( A
        }
, E0 T( h9 W/ y6 G4 P( E4 D& r- m}
; k7 t$ p/ E9 l
! b& _  L  U2 h+ W7 ^1 v* |9 bBYTE        APU::ExRead( WORD addr )
9 }5 s! ?( }, @4 B{
, r, Z# \3 P* Z1 DBYTE        data = 0;
; Q; c5 k+ O4 ?/ y$ }$ g$ V- J: ^' `3 h* u2 Z
        if( exsound_select & 0x10 ) {
1 P& b4 T8 _! ~, ~8 A8 O                if( addr == 0x4800 ) {
) {4 ^- T$ ]. p1 n! o                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- R' o6 k/ k; A2 z. T# E" X
                }
( Q7 Z' n9 ~3 \* J4 E        }
' q0 s) J- {8 I, T( r8 z# U        if( exsound_select & 0x04 ) {
( \/ y4 L, \  y  P. M                if( addr >= 0x4040 && addr < 0x4100 ) {
$ z( O- M, G3 p' l6 q( T5 k. ?& d                        data = fds.SyncRead( addr );
/ O- A0 H1 q! B4 R                }
( T: g" V9 {3 U( a3 S) j        }* Z" E7 Z7 @9 x+ ]3 R1 |1 t# W* y- q4 x
        if( exsound_select & 0x08 ) {
5 ^+ f  S$ _3 K                if( addr >= 0x5000 && addr <= 0x5015 ) {: d; l% l. f; B+ u; X8 H
                        data = mmc5.SyncRead( addr );. A% t& [( q$ T* Y: E& Y) F
                }$ _$ b  A6 W% h1 i
        }6 {- ?7 U6 i$ |/ d
2 L7 S6 F0 E/ x; {  E# t% v: l( j
        return        data;. _0 \5 S3 B7 v, y+ }  b4 H
}
& T( s0 H" y6 V8 N
. z2 v9 ]# I  g/ O; R# n3 Zvoid        APU::ExWrite( WORD addr, BYTE data )
1 A8 j0 D1 L" ]6 k{
+ Q* d- A( f6 ]; b& J( f        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 E  o9 h- C+ a2 W) O( i

5 o" U: e+ d3 o) r# Z1 n$ y        if( exsound_select & 0x04 ) {6 c! H7 W0 g3 w  f# w
                if( addr >= 0x4040 && addr < 0x4100 ) {* |4 s8 o& X6 ^, ]5 _0 n
                        fds.SyncWrite( addr, data );
! y$ L+ i$ P% P4 ]                }
" I6 M- Z& s% y        }
& A% e$ h5 j7 \# `
9 [4 a+ |# c+ B4 z+ K        if( exsound_select & 0x08 ) {6 s* b8 h0 ?: R3 \1 y4 v
                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ B% [* ?$ J9 C                        mmc5.SyncWrite( addr, data );: b6 G9 `- f4 }7 C
                }# m% }( I7 C! G: n( m) p
        }
' b- \8 Q# x. H% m& v}
3 D& x1 H* ], ^+ _; @5 D- {  N8 W/ [1 y, _4 p6 Z# n7 ?* a1 P3 e
void        APU::Sync()
& I2 @$ Q" m5 l0 p6 k* {5 i{. h" ^; ?+ O, E2 v% S, C" c
}
& [/ Z( D* {0 g( ]
* O6 R$ x. p/ a# \: m$ X$ E) Rvoid        APU::SyncDPCM( INT cycles )  F* h/ l+ G7 `2 [& W8 a+ W
{5 c+ J2 l( M. A4 t. r" c
        internal.Sync( cycles );7 m: u$ ]4 K, S6 a( d

. \4 f0 K# R% w( A        if( exsound_select & 0x04 ) {8 T8 u9 J. g: u1 c
                fds.Sync( cycles );' s$ @: O  ?8 \5 K  l1 M8 V
        }0 }6 p% T& N6 M5 ]
        if( exsound_select & 0x08 ) {# u# R$ Q% g5 {# `
                mmc5.Sync( cycles );$ n4 z5 H, e$ a$ a- _& T
        }- T. Q! i+ o. e. S0 L1 `; D8 U2 D
}
2 `. x1 X/ _% q4 G+ p5 l# y, h. [# X4 d1 D7 k& Z
void        APU::WriteProcess( WORD addr, BYTE data )
1 X( p1 Y' s$ o{, |) q! H- r% ]2 L, v7 p* @0 B
        // $4018偼VirtuaNES屌桳億乕僩, p& ^' N$ ?$ O1 E5 f- t7 O" I
        if( addr >= 0x4000 && addr <= 0x401F ) {
! V5 H" H& A5 }                internal.Write( addr, data );
/ ~; i4 @  B( b0 k        }
8 ~1 o1 r! a) N$ ^/ t' B6 L5 D' {}
0 ]7 Z8 s, F) d9 {! [  G: R
) F" `8 R9 U+ b, k* B" ?' [void        APU::WriteExProcess( WORD addr, BYTE data )
. [) N8 e0 u$ {0 ~4 @9 b/ _{  s  X0 C8 ?9 N$ R* f% {4 S
        if( exsound_select & 0x01 ) {7 X) H/ h- G% m2 a
                vrc6.Write( addr, data );
; ^) w. q1 n0 S6 J) {/ x+ y8 n4 `4 i; W        }
0 L5 X9 B. ?; g+ ]( d1 P# K        if( exsound_select & 0x02 ) {) n0 L  E3 P* I2 f$ c
                vrc7.Write( addr, data );
! f. W& v# `4 b# S& `2 ]+ T        }. d% w7 b2 b- e; E
        if( exsound_select & 0x04 ) {
5 X& v# j! p) R+ S) }! y; Q                fds.Write( addr, data );1 e! g# I1 ?7 p0 X
        }
( W* [; b) P; F* U8 x        if( exsound_select & 0x08 ) {
9 c1 T, d# @5 B" H: ^# z- e                mmc5.Write( addr, data );, p0 Y! w0 h0 v( K1 s1 F; `
        }2 u7 l% q  B6 d
        if( exsound_select & 0x10 ) {% B; H/ b9 l; D' k3 P' q5 s$ Y/ U, K
                if( addr == 0x0000 ) {
) |9 W# f& n& Z2 a" q. k- q                        BYTE        dummy = n106.Read( addr );& y4 d( \% _+ m- L
                } else {
9 R1 |" b( g, j                        n106.Write( addr, data );# d! h- J0 j" `- }/ }" X1 j0 i% g
                }
( i+ g/ q  y9 ]: W+ j# U. c: _        }) C) w; O" S3 {' g5 I$ Q* W% A
        if( exsound_select & 0x20 ) {7 e. c- w& `$ [* ~* ?
                fme7.Write( addr, data );
& U4 f/ V& N. b: m( `. G! a        }
, I2 O  P- x8 u$ Q3 _5 M}' F  {2 C6 Y4 f3 U5 }" v6 s
& Z) v. k. K) F9 y, ]7 g
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
2 C4 f: `, I* y& h* E1 i{
8 A' C' t2 \9 X- D6 \* J% vINT        nBits = Config.sound.nBits;; D2 d, r$ i/ `: _( h5 u- Q; u/ q% }
DWORD        dwLength = dwSize / (nBits/8);
' n* `5 b- t/ t1 q4 F; UINT        output;
3 ?* o* j) F2 r# v- V' `QUEUEDATA q;" z4 c4 Y1 G, R; [
DWORD        writetime;
6 D2 a* p! f6 r; R5 R6 r/ [! O
$ v8 x% {- G% ?4 E6 ZLPSHORT        pSoundBuf = m_SoundBuffer;' X5 O; a, C( x1 ?, z! a# ]
INT        nCcount = 0;; F' r: ^+ E( B& s  O. g

7 ~$ C; }3 `9 EINT        nFilterType = Config.sound.nFilterType;( w1 ]1 A# V, A

: B7 Z0 m% @& z6 f  \1 w7 q        if( !Config.sound.bEnable ) {
7 ?1 s* Y. s+ b% A7 v& r2 z                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! C- Y% `7 [" ]* y' p! W
                return;
. l6 J9 `  \5 _# z) Y        }
) b7 {: E$ h# h/ R+ j! E
' D) g$ a/ }1 ~( g0 M        // Volume setup) m% t4 s5 m5 O2 G$ l4 B& p7 ^1 ~
        //  0:Master! Z9 E, |' I& h& x6 k1 K: G' i
        //  1:Rectangle 1
# c; ~( t# y6 K" _5 Y8 `- x. q5 e" j        //  2:Rectangle 2
" U& c, Y& S  [/ a$ U        //  3:Triangle
% [( Z. E5 ^3 X. [( H4 s        //  4:Noise8 ^+ }3 E; S! J9 _8 P
        //  5:DPCM
+ U  Q  x$ d  I" i2 m5 M        //  6:VRC6* w6 d( z0 N% e: }" E$ E, B
        //  7:VRC7
8 t0 w" M2 @7 B# }- O+ k0 J        //  8:FDS; K8 M  W/ N, |" w+ q: U
        //  9:MMC5% i, r% f$ k7 C
        // 10:N106
4 j5 w  M, g$ B5 @% m        // 11:FME7' k  A* `6 A& r' ?. p6 f
        INT        vol[24];& Y( X' G' k  i: @
        BOOL*        bMute = m_bMute;7 u5 x2 B5 @: t& @) I& {" L
        SHORT*        nVolume = Config.sound.nVolume;/ K" H; O7 ?& o- u2 i) O

* c( M! Q3 R1 n. D        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
" d% A8 m; m8 p( ]' u/ E' S& ^" ^9 u
        // Internal, h4 Y8 L) @( M# i5 f
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;4 Q/ ?$ m- \* e, T
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
5 t# i( h  h' r+ o; {! b! W3 t/ L        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
+ ^4 K) M9 l  j; o% j        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
3 D8 i- w( B: f/ q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
7 ^( f8 F* W+ m2 y: n2 l; R3 W. ?# ?5 N: l: e
        // VRC68 t! b- U0 {% n; g
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( a. D7 `6 A  H- \7 S& v  r; ^$ w7 t        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% ~4 Y3 ~7 I  ]7 E- l8 p        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# t  I8 \7 F% T6 i5 g8 [. p, Q& Y( E! U+ `6 c8 b
        // VRC73 z' l) X0 W1 f! `8 x6 c6 g
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;3 b! Z' y' L$ k. a

" S2 ]$ X9 x4 E6 M2 N- i3 k  ?, Z        // FDS, ^$ U# j9 A, P/ G
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;" j7 E4 U, P8 j5 d% o3 r3 N' P: b

: S5 i7 A( w4 s  n2 Q5 k& ^7 @% r        // MMC58 f5 b/ J$ G# Q" Y2 w
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& K- J1 Z$ v+ Q; M2 ?9 o        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* C. t3 r" q0 X, x9 b        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- p7 W$ B" X0 n
* s& X+ {. }5 N9 A
        // N1060 I: w# u& w6 a8 s; u- Q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& b% x( j: O( F9 n) o
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 ?; f* c+ d) _* q! s% b3 A
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* f/ Q  N+ S& c1 O        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' }1 b; C( C+ [" ~. F
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) a- e# r, A' f! U$ k
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, w% k/ w% M* m- L        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! O# k' Q! G0 u6 {; V        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ _! ^7 X/ j* Y. Q( L% x, @9 x* b9 S
        // FME7
- N1 L. ~" P6 ?- }1 P! c# H. F9 v        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 G0 Y% ?! [: H6 E+ ?
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) t& o) `& v/ D/ K+ E- l, `% b        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 h. Z3 e+ t3 ^: x/ n6 V2 Q

, Y6 q% i8 D% v4 K) i- Y& K' s//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;' e) R, D/ b7 |5 U8 C
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
% \1 {' x1 O: d1 E" j6 w* E, y4 ~! g" _% h2 d1 A+ M; z
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟" M. ]: V, B  }8 g
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {8 V, V. n# \2 H6 z& D
                QueueFlush();  g  f+ z* H4 ~7 }
        }
5 i8 Z; `6 M: i5 L* \# f9 }6 S  i$ B1 N: u
        while( dwLength-- ) {
" ~1 P! j' R, G, |! b; e, C                writetime = (DWORD)elapsed_time;
& f& T& a+ Z( i
7 c: o: C0 Z$ I* Z5 _                while( GetQueue( writetime, q ) ) {
, u6 L! h) t6 s, }# i                        WriteProcess( q.addr, q.data );
( |0 p0 t2 w( y3 b3 G% u( L                }
! x3 _4 I) O/ F; d
; U8 }, ]2 ^6 F                while( GetExQueue( writetime, q ) ) {
! `" G" z: g0 l* U) j$ w; S2 x                        WriteExProcess( q.addr, q.data );0 ?' {+ F: P" V: s4 E
                }; }: ~9 b2 m6 l; }* N. r
6 u5 `# ]; W; I1 c: m
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7) U3 G* ^! O5 t
                output = 0;! Q3 ?- c6 D# n
                output += internal.Process( 0 )*vol[0];
( s; f  A. L1 g$ z6 t; p" z2 M                output += internal.Process( 1 )*vol[1];
$ y; B  Z( a4 [2 v/ ~" ]1 w                output += internal.Process( 2 )*vol[2];
+ a; o" x% k8 k. b' f                output += internal.Process( 3 )*vol[3];; \/ [+ X3 V5 ]3 [4 r; Z
                output += internal.Process( 4 )*vol[4];% x/ P. n( |* L

. R. f; g' T6 _& s! ]                if( exsound_select & 0x01 ) {
6 a  Y9 u' ^3 f  B. I6 Y                        output += vrc6.Process( 0 )*vol[5];2 N. p" s% {/ |+ h  l  {$ _; y
                        output += vrc6.Process( 1 )*vol[6];
( I1 j/ x" y" m6 M7 q) O                        output += vrc6.Process( 2 )*vol[7];
! m8 K9 g6 O8 H: @2 Y  ]                }( c$ X- N. K: l! O1 L4 {
                if( exsound_select & 0x02 ) {
3 h; j2 c2 q# D) z0 ^                        output += vrc7.Process( 0 )*vol[8];
* w2 P" C2 U4 ?1 T                }" t. x9 ~- ]' r1 D% ~
                if( exsound_select & 0x04 ) {
- g! z' N- M/ m+ p                        output += fds.Process( 0 )*vol[9];
% U, N0 C+ L- h$ T                }
3 A# ?- [5 H8 b, `1 \/ `( A# `. D                if( exsound_select & 0x08 ) {, m: ^- |8 k8 m0 F! I
                        output += mmc5.Process( 0 )*vol[10];
" |  q0 d9 T2 j3 w7 U. F! k% P6 z                        output += mmc5.Process( 1 )*vol[11];
% a7 M$ a$ l5 i1 J( o$ o1 d                        output += mmc5.Process( 2 )*vol[12];% k# ^0 l- ^0 |' g5 g3 p6 }+ e
                }
; I/ p# l" t  g/ M; o5 [                if( exsound_select & 0x10 ) {" z: I8 z. z1 R$ T. M% t
                        output += n106.Process( 0 )*vol[13];
# P; n" Z) F% n4 d4 G                        output += n106.Process( 1 )*vol[14];
" j" S/ A- b2 L                        output += n106.Process( 2 )*vol[15];- j/ I6 @" ]% ~/ s0 d+ M1 y5 E
                        output += n106.Process( 3 )*vol[16];' X* s. U4 @; V0 M* p
                        output += n106.Process( 4 )*vol[17];
' x: V5 b5 r. R5 q2 [  e8 X9 \! u                        output += n106.Process( 5 )*vol[18];* {5 ^/ ^! F  w
                        output += n106.Process( 6 )*vol[19];0 B: Z) ^- U' z. E
                        output += n106.Process( 7 )*vol[20];
5 L9 X6 R( r. f1 Q1 q                }
1 W% Y0 s6 X6 [                if( exsound_select & 0x20 ) {
2 H/ q% j! U  N7 a8 K                        fme7.Process( 3 );        // Envelope & Noise
0 |$ t% m$ u6 Z' N1 |                        output += fme7.Process( 0 )*vol[21];
7 R8 u+ t# ]  T3 \/ H# d                        output += fme7.Process( 1 )*vol[22];# ?: K" @$ Y) Q, e% n! Z- ^
                        output += fme7.Process( 2 )*vol[23];
" K1 ^' {; Y0 D0 A7 X                }
/ K4 J/ j( q! z+ G; U
- l1 {! s9 a7 ~( T0 t& n4 t' g                output >>= 8;5 x% |! t) b# W$ @. ]' G  g

0 U% W" j" m1 z! o8 A- a                if( nFilterType == 1 ) {
+ t/ o! D; `. {  P  U( E- J0 \                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple): A* b8 u8 E2 H
                        output = (lowpass_filter[0]+output)/2;
$ c) F3 E) g' x! ^, z+ o( t, L" L                        lowpass_filter[0] = output;% B2 ~) I) G) Y, K
                } else if( nFilterType == 2 ) {  t5 ]5 I% a( l: G$ y4 Y/ b2 K
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
: ?0 v% o" W9 n% R. N' h                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
2 P4 u# q* o2 P6 B* B9 h                        lowpass_filter[1] = lowpass_filter[0];4 Q& U. ?5 E# V, e) {3 K6 I
                        lowpass_filter[0] = output;
% a2 }! p4 U" V% [; ]4 i                } else if( nFilterType == 3 ) {' Q' b# M& ^) k7 Y: n$ T3 }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
( h- `: _+ U# ^0 i" y. F1 `                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ |& Y$ b4 Q: x0 J4 Z3 K
                        lowpass_filter[2] = lowpass_filter[1];
3 _9 h' F' \1 @% F; C; o                        lowpass_filter[1] = lowpass_filter[0];
. y$ T# }; K- A. U* m7 O                        lowpass_filter[0] = output;4 b& m3 C: c) s! c* A
                } else if( nFilterType == 4 ) {
4 u* `$ T) w4 O1 j; q' X+ [) |                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 M* p9 j0 i- W+ s" a7 p
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;# m4 {/ Q4 q: q# q8 h
                        lowpass_filter[1] = lowpass_filter[0];+ S% O* N7 [( x. y6 L+ V3 @
                        lowpass_filter[0] = output;: C& }7 i+ y5 |
                }
* I  X/ y4 p6 U2 x7 R1 |% C1 D, U+ N- u
#if        09 R8 J) m+ w6 t$ M/ |$ p! G
                // DC惉暘偺僇僢僩9 Y  q/ X7 |2 Q8 p0 n
                {  ?8 Q4 l2 m4 B- ?
                static double ave = 0.0, max=0.0, min=0.0;
8 \0 L- M: y! _  Y+ @                double delta;
( T4 G: h4 o8 C0 P. Q                delta = (max-min)/32768.0;
0 n7 R7 G2 a( x% a                max -= delta;9 V1 v) ?1 u  }
                min += delta;8 j) C' h5 ^/ ^3 B5 `( S8 b
                if( output > max ) max = output;% g( A& H9 I$ q& ]5 T% I0 b
                if( output < min ) min = output;
9 z" B# H1 G$ s6 L1 ?- ^5 R# H                ave -= ave/1024.0;- {7 m- P) }' \' ~! F; o
                ave += (max+min)/2048.0;* c* O# ]& |) n  j3 c! a
                output -= (INT)ave;
4 z, k) Z. J* P! d. Y/ L5 B                }
3 x- ?1 ~* B2 I/ J, o2 k9 _#endif$ I5 g1 v" ^5 ^' l
#if        1
0 c8 B4 r# u( U                // DC惉暘偺僇僢僩(HPF TEST)
: x$ K7 ^% a1 P, D! K5 ?                {
( K1 v8 H6 w! [- h+ w! A//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);8 N. v$ N% q+ l: C6 Y) C
                static        double        cutofftemp = (2.0*3.141592653579*40.0);! w; l( Q+ {0 r  F: Z0 S
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
$ [. l, v+ x% q# l" s" G# z4 W* Y. k                static        double        tmp = 0.0;% l) X1 y$ Y' ~! P7 j
                double        in, out;2 L' K( l' Z- Q$ K
( C1 d& F1 [2 A, e5 r! }1 {, Q$ L
                in = (double)output;  V% O2 v9 e! p& y( ^9 |0 o
                out = (in - tmp);. y  {: B* \5 {0 l
                tmp = tmp + cutoff * out;
. ^: U1 |4 v; u
$ }6 G% z: i( `& D( v/ i+ \/ I9 Z                output = (INT)out;7 \6 V# \. P6 M0 ?& `# ?$ h
                }2 e" I+ |- ~% F1 m8 C7 S; c
#endif
7 H& x$ M! }/ Y* \9 j; u#if        0
  J/ T" c# E+ P: Q                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' S- f" X, r6 q                {
/ E3 f1 L1 y! u& p8 m: U& u7 n                INT        diff = abs(output-last_data);; z$ h' H% K' z: X3 {4 H9 N
                if( diff > 0x4000 ) {
4 k  D' J( s7 j. N0 F! _; a3 R+ U                        output /= 4;- x  `* D' P! g' D
                } else
6 p' D* e% |7 @, H* z& Q& V# N                if( diff > 0x3000 ) {
. M% B7 C7 T1 `0 d( R$ J4 U                        output /= 3;
/ O+ r8 C9 T5 A& H; v7 ]                } else6 X0 Q3 F- c" Q3 E' B  e6 ?
                if( diff > 0x2000 ) {$ i, s' n0 M( u
                        output /= 2;+ J4 \. K0 r" }3 M  R
                }+ B7 f  g# ~, w8 E, ^' g' V
                last_data = output;( I3 p' p! G2 p& m. l9 o
                }' y. a' f& t% A2 b- T
#endif
1 p, w( c2 t( A                // Limit
1 a/ K" ]$ R  o" @+ H/ ?2 p                if( output > 0x7FFF ) {' r0 P) B/ N5 f! X* k
                        output = 0x7FFF;
/ U5 i+ l% H( @4 U                } else if( output < -0x8000 ) {6 l& j9 f+ e2 P5 ^2 n
                        output = -0x8000;
- T) {; U9 {: [1 a                }
# E  Z+ q9 X+ a+ S4 h" w" Y
) }- T3 h8 G$ @2 `# K' z                if( nBits != 8 ) {
2 R; Q9 J' F" a7 E0 V                        *(SHORT*)lpBuffer = (SHORT)output;
- T5 ?- M1 d# [; C/ g! m; r                        lpBuffer += sizeof(SHORT);( ?! V) z# Y, y( O) y" L. D8 q
                } else {" ~/ r' w1 n+ t9 T/ l& P
                        *lpBuffer++ = (output>>8)^0x80;
8 h: T% Y7 @6 s0 z! a& G                }. r3 }3 q, n) f6 U* B7 F
1 k" F* ^3 G6 }* M( a
                if( nCcount < 0x0100 )8 p* _  W: H" b/ ^
                        pSoundBuf[nCcount++] = (SHORT)output;/ @) p  s* A: d8 A% \( f

6 A1 l' C8 B8 C1 Y% o//                elapsedtime += cycle_rate;
6 b8 E. b% C7 Z9 \                elapsed_time += cycle_rate;
* M" y* I1 c2 n: _        }) K; h: _. J% o% C; M, \- o

% R: C7 a7 L3 X0 x. Z#if        1
5 ~, I7 J1 V/ T        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
7 [, ]; n, V1 r8 r% m; _                elapsed_time = nes->cpu->GetTotalCycles();
, R: u1 f+ o! Y        }
5 u  ?$ r9 Z4 }  e  k8 M7 r        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 h( u' U0 ~/ u2 e2 m* l
                elapsed_time = nes->cpu->GetTotalCycles();
. |( Z. |0 \2 z& P        }' x4 q$ U5 _* v
#else) P; Z3 S4 o1 n0 ]- P6 E3 g2 z
        elapsed_time = nes->cpu->GetTotalCycles();  l3 O# M3 H0 Z3 i% S% h- B
#endif
5 w  ?5 `, d3 ?' v}
, N# q; \8 R& {: l9 i
6 y5 S( @2 q. K5 w// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- R8 ^4 |( e/ ?INT        APU::GetChannelFrequency( INT no )5 k3 A3 }" g) T# V* t3 S6 y
{
- A4 {8 Y+ C" c2 H* ^+ a' w$ S        if( !m_bMute[0] )
9 A0 j1 ~: S+ j9 ^- w/ U                return        0;: y2 C( @8 v$ B+ @

% M4 e  o( j, K        // Internal; F; N0 [# h; u: M+ i
        if( no < 5 ) {, `# m2 `1 ], D% x
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
8 j; G3 Z6 N' R        }
- g9 }- r& @/ D9 y, K        // VRC6
" T8 K5 y. }, n! t4 n/ r! s! s        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {2 t* L0 p9 ^4 \) I- n& I
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) u7 ^4 j8 t  c) {) Q; T0 b
        }
2 ]  I$ m+ p7 Q; |* o. }        // FDS3 ]7 g' `4 b: R2 z$ r' t
        if( (exsound_select & 0x04) && no == 0x300 ) {
; A3 P, W& o6 e9 Q                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 h9 K$ F2 k. N) d8 F  \
        }
# u' Q* h  s: w/ e9 d3 Z. t4 P        // MMC5& Y  K8 }, k) O# ?1 d
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* Z6 M; d* ?& W8 ~
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;$ b! V% Q0 G. r) a. a3 W
        }
8 e. n0 S; _+ N8 z! x        // N106; M8 Z* E7 v4 k0 }' H! _
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
! `8 F' r" d4 j: m: w                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;% y- S0 D# F% X' `# @4 @8 [7 r
        }& u9 n' R  c: I8 ?' U  U
        // FME7
2 r: [, @; w. S        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {8 K; {& R4 ?- k4 Q! A9 K5 f$ Q
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
9 K$ p4 Z8 I# j8 P6 U$ C) \+ ?( `        }
' A4 O# H( t4 x2 |" {" z$ `8 d        // VRC7
* [5 Z; M. H9 U: G2 F, N+ E        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
2 [! {: q, H7 J) B: D" u2 p* l0 J                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 ~' L0 n1 a2 F, ]" o) {        }9 m/ I' s  M' x- s$ T4 j0 f
        return        0;. ?* p6 z; [% n* }; M, `# u5 {
}# m& s- i9 y; `9 Y% [% W; L
: g* x, B( n5 W+ h& z0 p) X
// State Save/Load0 [6 f' {  X1 c! I: n- a
void        APU::SaveState( LPBYTE p )
5 [( a  {% p' a+ Z* X$ ~9 \8 h{1 n6 L5 E) g. h7 C
#ifdef        _DEBUG
* t+ z7 G1 H3 G& |6 c# vLPBYTE        pold = p;& d# _# d' N  @
#endif
; e# }0 V: c; e9 {# ^# M6 o) {2 m& i
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! H* a  y* X$ ?8 @/ N% O* `5 E        QueueFlush();6 n( m/ a3 |! F+ m
* D+ z- ~8 {0 m3 m
        internal.SaveState( p );
/ ^2 H4 P. t9 W9 d3 v) {! C        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. E9 I5 Q- L3 W1 X
% r8 W) h5 J3 k9 g$ e
        // VRC6
9 ?) [: K; y3 W- g6 i        if( exsound_select & 0x01 ) {, J: Z8 ~$ k7 F4 U, L7 o
                vrc6.SaveState( p );  r1 s; `; ~* e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- U& F' E" y+ s( K        }
& \; ]$ x# ^$ `( h  Y1 i        // VRC7 (not support)
/ d! F% c7 e! z. G        if( exsound_select & 0x02 ) {7 s# U& q/ n+ r9 D) F) e
                vrc7.SaveState( p );) N( o% l5 P+ A
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' _3 H, B# r, f0 ~# P* g) r2 ]        }
  ?! j% ?; `3 ]4 M/ z3 I        // FDS2 @; d$ a& L' h; w1 L0 Y5 `# E
        if( exsound_select & 0x04 ) {
9 E3 I( S1 \/ S# A% G6 Z1 m                fds.SaveState( p );
5 z& n0 R5 h( q. V                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 f) u  {) n9 {9 q4 Y- u5 P9 d        }
5 L$ T. x0 G% a3 q8 V        // MMC52 g, F  y0 x- m; O$ d  U$ L
        if( exsound_select & 0x08 ) {
  _; c' o! z6 ^. ~- h; o4 p                mmc5.SaveState( p );
, R9 K% |5 o) {, h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. Z3 e0 ^& V( F* R$ v# M
        }4 l; Q4 p1 p+ k
        // N106
1 C" p8 s% z' N) g  R5 w* v        if( exsound_select & 0x10 ) {
# U$ g1 o: M# N( ^! e: a                n106.SaveState( p );" G! y, j7 B4 X. N& p
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( W7 W9 ~% ]4 X: \/ d
        }
  T3 k8 O, J7 Y; t( r% Z) _        // FME7
0 z. J, c; @, y" L1 |1 \        if( exsound_select & 0x20 ) {
' D. C$ X4 L; M: r7 s! m" i                fme7.SaveState( p );0 c1 Z+ }* P+ G  o2 |1 j% I) e% o; b
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% d9 y$ K8 F: F        }  J7 G7 i5 O7 W+ C6 Y

& K7 q3 E% l, ^( i) d* F4 \. O' e#ifdef        _DEBUG. R  f( g0 W5 Z0 l" U# H# I0 E
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
) w( Q+ }8 C% a4 m) S# S#endif
* e, S4 h3 X% m}; P6 }3 n, m% N
8 z5 S; p0 `# H( B: G' S
void        APU::LoadState( LPBYTE p )
! [( g' p( H% `{: g- _: l4 w& l" n7 q9 Z
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡( l: \9 t  J# b$ e; f
        QueueClear();
# |: i$ M8 d4 v7 k! ^. G. S. V7 M) m
        internal.LoadState( p );+ @" Q! k/ R2 M# W7 L5 c, _
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) X, S6 h$ o; k3 h) A/ V) _+ J* N! i2 ~5 |
        // VRC6) _) I: ?* u( U6 ?' _6 _1 Q1 g
        if( exsound_select & 0x01 ) {
6 x- u2 {% w" K+ }" W                vrc6.LoadState( p );
2 Y( G' ^" W( |) l0 a8 \7 I. k, Q                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 N2 w$ l$ K4 ?' ~6 R+ u: ?$ a. Z
        }
0 w- R- p, J, y0 m3 J: x        // VRC7 (not support)% r1 [4 a' T* I2 k
        if( exsound_select & 0x02 ) {) l7 w6 ^3 X: {) A0 Q
                vrc7.LoadState( p );; Y# \# E+ M' j
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 l5 {, m) ?# X) Z
        }
  ?9 L3 @5 Z7 e6 f  J  Z        // FDS- V* J0 Q& B' V2 g9 b% ~% \' s8 W# A
        if( exsound_select & 0x04 ) {5 L# F* p7 n! F
                fds.LoadState( p );
% u; E$ m  W1 a7 q( d                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 \' Y2 I& Q/ K. H! ?( m        }  e# z& E8 Y6 p* r; |- K
        // MMC52 L& s$ }2 u7 N! b' s
        if( exsound_select & 0x08 ) {
  f2 }8 r3 ~2 w2 Q  a! W  [                mmc5.LoadState( p );
, b7 O! R- t! O# y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding! t) r% I  `! Y) L! l; E
        }
5 B; ]& y! d( C4 y        // N106
. P* F1 I( a& m3 m! e0 F3 b        if( exsound_select & 0x10 ) {
9 X4 B6 L7 j7 E6 G3 W. }3 q                n106.LoadState( p );
6 `& f0 |5 z# d                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' |6 G$ B6 o' q9 T( |! d( ^
        }5 U$ F( p; x  L+ ]! g3 E6 {  s' v0 t( E
        // FME7
5 }2 g, Z' S0 t: F        if( exsound_select & 0x20 ) {
8 H- Y2 t; P& a6 h                fme7.LoadState( p );/ i  V! Y& z. S7 Q" G
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 X! L0 y. ]- R3 u* J% [% V
        }
. A+ F8 P9 T* u6 i}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; N& f6 m6 ~# W% E
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& k+ M8 \1 a: _感激不尽~~
, S. x6 t: d' r
恩 我對模擬器不是很有研究,
9 H* F2 }+ t% E* j7 W- v: e$ `雖然要了解源碼內容,可能不是很困難,
7 W. O" Q2 w: M7 T. e0 Z  t4 ?7 D不過還是要花時間,個人目前蠻忙碌的。2 o3 ]9 C( V1 z" t
& D" |$ S7 f" o3 `
給你一個朋友的MSN,你可以跟他討論看看,
- R/ ^  }+ N4 J$ C; k: |) G他本身是程式設計師,也對FC模擬器很有興趣。! P3 @  R5 f' B! A/ |; u& c  L$ E# z

1 d' C- C8 {8 S) uMSN我就PM到你的信箱了。
* {5 p2 g: J0 j( @/ P  j2 A3 w2 i1 F: t" L% d
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ h/ O8 X/ ?9 Z6 w5 u
呵…… 谢过团长大人~~

& I: F6 j) f7 C# W; h9 y& n( w, u0 h# Y
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
% `8 R0 q5 }7 A5 M( E团长的朋友都是神,那团长就是神的boss。

# T8 C% m& X+ v; B, ?6 A" \9 J2 E哈 不敢當,我只是個平凡人,
! V1 x1 K  d  _5 c/ ^要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) M" f4 U/ o) y1 \+ n( W. t4 DZYH
7 v! |. j( d7 D* ]  w5 t! wQQ:414734306
; x( V3 H% d8 V- y. JMail:zyh-01@126.com
6 P# q* T) E" k1 k0 q2 z1 x, `8 Q" t2 Z0 m+ O1 B" y% H
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
  Y* T; i: m* ^& G" t- D; @+ n9 s再次对团长大人和悠悠哥的无私帮助表示感谢~~
( ^+ A% o1 D) L0 U& M
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-8 11:50 , Processed in 1.099610 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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