EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& f  ^) U8 t* k! h1 ~
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) k: Z$ S6 K1 ^
这里有相应的模拟器源码,就当送给大侠了~~& d1 p/ v: `3 p& j; {
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ' S4 ~% E- z9 q. s7 a
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 u8 j  b7 {# Z, @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( t, }3 E; T, B" L
这里有相应的模拟器源码,就当送给大侠 ...
5 x* [7 N: k+ E% r' r" P
聲音部分(Audoi Process Unit = APU):
) b* w& J1 G! u- [0 }  F8 s.\NES\APU.cpp7 N$ h" L/ y0 r
.\NES\APU.h) L" \" e2 T# a: D. p; \4 o5 ~7 T

& W( \6 Q9 A" \3 c3 c, e; C9 i* x% {5 \
影像處理部份(Picture Processing Unit = PPU):7 x. t3 y/ f+ l: @; _& M9 `
.\NES\PPU.cpp( b' b( _4 [0 V* @7 I5 c
.\NES\PPU.h
* \. Q8 n& b. C0 y; e0 t
9 o' P( e- a, p如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
) _7 X5 ~  W% `$ ?2 k5 h, u' w1 N(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ i4 c6 d2 z8 C# C* u
//////////////////////////////////////////////////////////////////////////0 R2 E7 z# s6 B  d/ D. r  \4 e* ?
//                                                                      //$ ]; F5 s8 C$ N! x3 J0 O# {/ |) x5 o
//      NES APU core                                                    //
0 B( f; ?3 I$ W% x# I  z: B) V+ ^//                                                           Norix      //  d. D9 v. H% Q9 K  J1 Z
//                                               written     2002/06/27 //- Q8 c2 `0 v& u2 M
//                                               last modify ----/--/-- //( x$ ]% K6 O4 L: B# g( A" V) M
//////////////////////////////////////////////////////////////////////////
/ C/ A' x& p$ i#include "DebugOut.h"
2 h9 U' r. q& E% F#include "App.h"
( Y- ^: F, H( Q0 g2 K+ o#include "Config.h"
/ c% G. x  i1 I* y8 r, t4 D, y; z( v! d, r6 g
#include "nes.h"- V- \( F- q* B: G% L5 o  K. @
#include "mmu.h"
7 A; M- P+ z: t3 L, H$ W( W#include "cpu.h"
+ w1 v% x8 F4 Q% V#include "ppu.h"
; p' E  a& h1 o( |  d#include "rom.h"# A0 w- k! b3 r* I& Z
#include "apu.h", m9 ]+ t  Q# v4 b$ N) j

8 B9 q, X7 G( c" R& v# [7 A$ v// Volume adjust% }2 M9 i0 j% e9 y1 a; y6 ]4 L) S
// Internal sounds
* F  L/ e# }, A7 _1 [#define        RECTANGLE_VOL        (0x0F0)
. H- d% U' Z0 c# @* _6 }0 H0 y" d% N#define        TRIANGLE_VOL        (0x130)( P$ T- K3 N8 T' Z( }* o
#define        NOISE_VOL        (0x0C0)
0 F* @4 U- ^9 t. W" _$ n#define        DPCM_VOL        (0x0F0)
3 @& l3 K0 b6 d, V2 q: S4 `// Extra sounds
; @/ J8 Z. L  ]) ~1 l1 u3 r#define        VRC6_VOL        (0x0F0). k% v* E% z3 L5 j
#define        VRC7_VOL        (0x130)
# J. F1 e! r3 X1 c* ]+ A2 F" k2 M#define        FDS_VOL                (0x0F0)! c- g, e. q# g- ^' ^* T8 D
#define        MMC5_VOL        (0x0F0)
" `: E7 ?8 ~3 g#define        N106_VOL        (0x088)2 L, v1 Y* x, I/ F+ J
#define        FME7_VOL        (0x130)
8 }+ }6 J9 c1 F& |* W" ?
  q0 f5 M6 v. j+ K! `* N; gAPU::APU( NES* parent )
- B1 P  W# x4 E2 _( D- Y" l{6 F; V) M& C* @9 q- ?) |
        exsound_select = 0;4 V( ~1 ^" n0 `4 u* H  b% A/ M
* ], [- o* h; n1 \  e* n
        nes = parent;
2 V! L" {  v; X( `6 ~0 P        internal.SetParent( parent );
2 H; s& S% o, \' {4 P
, {0 y4 ~4 M$ `9 n, G        last_data = last_diff = 0;
& K5 C7 u6 T. v% b- V( S( K
: h+ b8 {  m0 f3 s+ t/ D0 ?        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 R6 L3 U( v% ~! K: e2 h

; y7 g- j2 c) \9 z" ?# G        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- ]5 Z8 ^3 H( x* e0 j/ X0 [5 K        ZEROMEMORY( &queue, sizeof(queue) );) M1 {: X% p4 P+ ]4 o( D3 B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: w$ R5 X/ s* w+ B# P$ g

- ~- E# L, g3 V' ~$ p/ c7 |        for( INT i = 0; i < 16; i++ ) {0 r' j9 T. i$ u5 p
                m_bMute = TRUE;
- Q# `; b- {) |$ k        }
5 x; _' g, z7 z: D" }" `4 [. H' S( J}; j: u" I: T* s3 ~  E/ B

0 r9 Q9 ~7 J; A) OAPU::~APU()
0 V5 n* e* c$ R7 z: l9 z{8 F" `9 W' M$ Q. P: ^! k! o7 ^
}- e1 S9 a9 g; v5 @& S5 e
2 N. i( p# \0 D# Q& M, Q
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
7 w' w# k8 X% W- q) g( x) P: Z% w{
1 i& ^8 e  K. N/ }5 y: I0 ?9 r        queue.data[queue.wrptr].time = writetime;3 Q' ~5 l' n: t; ^
        queue.data[queue.wrptr].addr = addr;- \& J; M7 j( i  J7 d; p+ S
        queue.data[queue.wrptr].data = data;. A9 x8 x3 [8 t+ U" g" O
        queue.wrptr++;. A: n* u- m( s/ }! j
        queue.wrptr&=QUEUE_LENGTH-1;
* f9 Y$ H0 \1 G# v: W9 t# D. p3 [        if( queue.wrptr == queue.rdptr ) {
5 r% e( P& Q# ?0 f: n& \8 W( @/ B                DEBUGOUT( "queue overflow.\n" );
9 [% @' m0 C" }% ^' p) R6 D        }0 r$ G5 L- P' a! _
}
9 I5 i- b# J8 a9 }6 k1 n8 w: s* T* f( X, k  J
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ): D6 r' S; N% F; v
{: v  R* r9 @$ K8 z
        if( queue.wrptr == queue.rdptr ) {: Z/ J9 z- g; G$ I8 Y2 ]
                return        FALSE;
1 P+ F2 y3 H  m% q2 _9 k) `. j        }: n* k, I" H0 d* R$ _7 i/ |
        if( queue.data[queue.rdptr].time <= writetime ) {/ Z; o) ~. s( e( }; p
                ret = queue.data[queue.rdptr];" e  H1 E- F9 |, Z: a$ E
                queue.rdptr++;
( [  T' |. _, h5 Q9 M% @! b                queue.rdptr&=QUEUE_LENGTH-1;% w1 D" t) U( \8 ~) F6 N
                return        TRUE;9 I: C, P/ D( s, A8 R
        }" V( |, Q, q+ a) f( V3 y/ y% S
        return        FALSE;1 R$ ?- [# m2 z+ Z, b
}/ F( h( {- ]  x2 r6 Q) T9 c0 m- o

# F& ]2 H  a( K0 b& vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
" R# l  w& F- s+ J. H{
2 a: }* f" I% L# U; A7 A        exqueue.data[exqueue.wrptr].time = writetime;8 t; b8 Z9 M- J# G/ z% F
        exqueue.data[exqueue.wrptr].addr = addr;- G3 P8 _7 s4 I% h# L( |8 L5 d
        exqueue.data[exqueue.wrptr].data = data;
9 ~1 n  p. x; c  k9 n1 @        exqueue.wrptr++;
5 t7 \- N( \* s/ G4 E0 U- i        exqueue.wrptr&=QUEUE_LENGTH-1;5 [. `/ r; z4 Q# v& a" i
        if( exqueue.wrptr == exqueue.rdptr ) {/ C/ m& }/ f% q1 R) M2 v7 O2 E
                DEBUGOUT( "exqueue overflow.\n" );
* n3 [2 d6 o  l        }
& D; ^; x9 l! G! p}
! O' A7 x; z. m( g1 A! g
9 i% B( j* G; v  K5 N8 V+ uBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' M) ~, |) }7 X* o( N- c{3 J. G7 \* h4 ?) H$ i0 v& [8 O
        if( exqueue.wrptr == exqueue.rdptr ) {/ [7 }( V( I$ b6 h6 R7 q3 o
                return        FALSE;3 b8 }5 [( }1 D/ D, q& W+ t% o* [
        }1 j# D9 l, j8 M
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* X# H( J! |( l# |2 q( u
                ret = exqueue.data[exqueue.rdptr];
  s: w) z) ?6 T  J; ~' x                exqueue.rdptr++;* M2 @$ |% M+ Y& h
                exqueue.rdptr&=QUEUE_LENGTH-1;. j" Z3 [# F' H" Y) ^; f
                return        TRUE;! I& i9 T+ V2 q( j) Y
        }& o! ~8 ~0 S( m5 y* e, a* T6 j4 V
        return        FALSE;
( O9 c( B* u+ E8 }}
  B7 H! U, U8 f! J) v5 g, w( t' j2 d4 b* d. B, Y
void        APU::QueueClear()
0 ^. A; e# h. p0 Y{" ^+ {, b( D" Z9 a6 T
        ZEROMEMORY( &queue, sizeof(queue) );7 A" Q! T4 D1 y. K6 I; B. T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 p6 M& r. j4 i/ @1 l! r4 n, F% f) M}* d5 `- h1 H* g  H1 A: r7 u
3 v7 i) r* Z# Y& s0 B9 q. g. _4 B
void        APU::QueueFlush()
. R; _9 }( I, j1 E/ m{9 N& S2 u3 T' K% B4 K) s
        while( queue.wrptr != queue.rdptr ) {1 Z, K7 j, r1 {3 \( {
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& R6 f! w; O* Y
                queue.rdptr++;
; `( e1 ~! @4 Z/ L* V* p/ Y7 |* L& Y                queue.rdptr&=QUEUE_LENGTH-1;. S4 P: E5 d* b/ k% I+ z! H
        }0 P& ]( ^+ o3 G
# }( U" {* e' h* A8 A, t
        while( exqueue.wrptr != exqueue.rdptr ) {" C. }/ j% z, S; ~
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
) R/ W% s: [' T9 ^3 ]6 K  h                exqueue.rdptr++;% T* y8 g" C- Q; W9 `9 }
                exqueue.rdptr&=QUEUE_LENGTH-1;
( A3 i" H/ l1 X7 Y        }
% N; h: F; A$ j& w" H0 C}
) e0 r% X* E. i5 m0 Z  s$ @3 D5 \' }, r; V* m9 A$ S
void        APU::SoundSetup()6 r- Q/ k  _8 |" o
{
4 T. P6 i8 T5 T8 e0 r" j" m9 u0 @        FLOAT        fClock = nes->nescfg->CpuClock;
( D% y, M) r* K- w4 C# w" y        INT        nRate = (INT)Config.sound.nRate;
1 V1 H; I9 K/ Y0 n        internal.Setup( fClock, nRate );
! R! M/ f( }$ \; b# ~        vrc6.Setup( fClock, nRate );
% R/ D! j5 M2 \) C6 o        vrc7.Setup( fClock, nRate );" j$ z; r- s' k3 x3 P, Z8 r
        mmc5.Setup( fClock, nRate );
8 V+ G* x& O( e        fds.Setup ( fClock, nRate );
- n) R( L- i; W6 k9 I# X5 I        n106.Setup( fClock, nRate );; i$ _5 c0 V. g- `& N, f
        fme7.Setup( fClock, nRate );
# B: I5 i0 |+ ~8 {1 G: h7 d}
7 P$ I7 Y6 }8 B& Z) {. M+ \/ B1 H, a0 x# g) O  q! w
void        APU::Reset()1 x3 f4 M, F/ `1 E7 [8 B
{
6 j1 C4 z" A) e, |" }/ R        ZEROMEMORY( &queue, sizeof(queue) );
% M6 J! R* [' }: o1 s        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 l0 \) X5 ]  V8 t

* N' {% t: Z) I6 f* Z8 e        elapsed_time = 0;
* `+ t9 n) X% ~3 f0 E8 ?1 b* @: u: P% D* m4 V5 Y9 v& g9 d6 ]
        FLOAT        fClock = nes->nescfg->CpuClock;) z2 c5 Z  v' U1 N% v( o( \
        INT        nRate = (INT)Config.sound.nRate;9 n+ D2 H0 \9 D4 I: t. L
        internal.Reset( fClock, nRate );
5 P6 J0 l) g) A6 F, D: o" y4 B        vrc6.Reset( fClock, nRate );
! |. z- X0 m: h- C        vrc7.Reset( fClock, nRate );
, G& n; R; t1 B( S6 }        mmc5.Reset( fClock, nRate );/ g3 Q& w2 k+ c6 u: x4 C8 l
        fds.Reset ( fClock, nRate );
' W- S7 o, c- K# y6 h& C3 D: Z6 C) @        n106.Reset( fClock, nRate );
7 ~1 s/ y3 \0 W+ f, ]( ^        fme7.Reset( fClock, nRate );
7 Y$ s/ _3 r- M& G
6 @3 K* `9 X" J4 q! _% B3 T5 ~2 ^5 [        SoundSetup();  P& `- z' h- x5 ^8 \+ ]
}
6 c8 O5 Q. ?! O: n( d
; {0 l- f2 G0 {' G0 f7 X  m& evoid        APU::SelectExSound( BYTE data ): k% M/ p3 Q& Q: u# S
{, I$ E8 J) W  w0 ~# L
        exsound_select = data;; F9 `3 |4 k: k% F- c$ P
}
; g: v% [- `  _' M9 Y* ^
5 P$ W  b( c% e  P" N* ?BYTE        APU::Read( WORD addr )
, F! m6 w0 o, Q( Y) \- y# Q7 P! n{! I; z+ I" h2 G% X! s* y
        return        internal.SyncRead( addr );
' o! r& S/ T: I* m& n8 d}
8 |" I8 z, [5 j  P& E/ d$ n
. w( U# {  j4 `$ G+ Avoid        APU::Write( WORD addr, BYTE data )
: L' M6 y$ G# Z: d# q% ^9 m{0 B* O+ v0 S7 O; |
        // $4018偼VirtuaNES屌桳億乕僩% d% T; ?+ T8 ~& [7 O0 b* f# w% [
        if( addr >= 0x4000 && addr <= 0x401F ) {8 q! e' _+ v4 _) m5 r5 S* ~
                internal.SyncWrite( addr, data );
: Q$ r* c' }) z& `* ^                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' k4 |0 i* i, p! W4 o! ^! S        }2 X# W/ q, w% l7 F, M! J, B
}
, R4 Z+ ~8 P! g5 y5 f9 l2 E% |/ }4 B! C
BYTE        APU::ExRead( WORD addr )" r7 G6 G5 B% [( D; G
{2 z4 J3 u3 C, A* U' f2 o
BYTE        data = 0;1 L3 p0 I# v( [( i+ `. i3 {( K  n

+ F; m& J/ Y5 V        if( exsound_select & 0x10 ) {! W8 G" o; j" P0 P
                if( addr == 0x4800 ) {
# B0 B: @  A0 R                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
3 y9 n0 F" x/ e  x                }/ F" b0 {' G9 P+ Z) o( `2 p
        }
5 |) r* s. O1 k$ ^        if( exsound_select & 0x04 ) {# Y7 q: C: O; V. x" j- T1 y
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 ?& O' t0 l# ?. X& R8 s                        data = fds.SyncRead( addr );1 ?) |* R/ F8 o% _/ H7 l  [
                }; y; {: f& ]/ B/ ]. i4 J
        }$ a/ P/ F9 L. S
        if( exsound_select & 0x08 ) {( _! Q0 k7 `4 @, z5 z
                if( addr >= 0x5000 && addr <= 0x5015 ) {/ \$ r1 n! K5 x0 R6 N' e
                        data = mmc5.SyncRead( addr );# G# E1 t( y1 |; m. p
                }
3 Z. Y- n8 [- B2 S! T6 ^9 L        }+ W* {3 \% Z! f, t" F

2 ~- n& C: A0 b; i2 _        return        data;
' |8 D6 {, T6 L. W9 `. K; ]" B; Q}
2 X3 E5 }! K" W/ C& ~% M! X! N: ^) ^, Q5 ~" }8 g; B
void        APU::ExWrite( WORD addr, BYTE data )
- K8 w2 A- ~9 B8 @. |{
; M, P3 U5 O, f! ]        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
7 D9 A$ h! K7 x& e2 T5 R  g9 Y/ A( {$ q8 c2 a0 W7 u! g/ K3 k
        if( exsound_select & 0x04 ) {0 _& _% J3 r6 F. t
                if( addr >= 0x4040 && addr < 0x4100 ) {6 U( t- ?0 a  M2 {
                        fds.SyncWrite( addr, data );
% s0 _9 N" H9 L2 p: X                }
; s2 Z$ r5 q% C" \" D( T        }
. A: M) ]! Z5 d' W
# S* H8 s. B% I3 b$ C        if( exsound_select & 0x08 ) {: f! d% s$ f" o3 a# q
                if( addr >= 0x5000 && addr <= 0x5015 ) {* t$ v6 j1 V( s/ n
                        mmc5.SyncWrite( addr, data );5 O* K+ a/ o* m0 r# g
                }
+ _( _" ?4 N7 Z* c8 ~9 Q        }: h' Q2 T, b( Y& D% l6 l0 H
}/ b" ~) [  o6 @- {

' O% v& t& Y) cvoid        APU::Sync(); j) ?( |3 v$ w8 e" X1 u. _
{' e$ q/ I* P" r! _5 Z) a
}
: b# T) T5 @# Z9 i' `
" Y* I% g- p- w6 Tvoid        APU::SyncDPCM( INT cycles )
" I4 ]: e! g. R+ \{/ f/ `: q" d; @, m
        internal.Sync( cycles );
$ ]" I4 d( I% B7 ?" V" z- i
; }/ T0 B5 ^# `8 Y        if( exsound_select & 0x04 ) {$ `4 b7 H" F9 m! S( ]
                fds.Sync( cycles );
. O6 e9 y% [+ w6 o, a0 F8 J        }! |; k+ |6 d6 b* D/ W; }- k3 u) B
        if( exsound_select & 0x08 ) {  L5 R# @* @/ U9 h. ]
                mmc5.Sync( cycles );) ^6 p6 k& Z& u3 H( X( ?0 m. F. S
        }$ P! |0 ]- z& Y/ q0 s
}5 ^( H, \; N* g" p6 n% X
1 a* U1 |2 V$ P0 r
void        APU::WriteProcess( WORD addr, BYTE data )% f- b2 P, l. w
{; n9 ?& ~+ p! b7 Z8 m/ j
        // $4018偼VirtuaNES屌桳億乕僩
- g6 Z) c5 x; N& X. f; R        if( addr >= 0x4000 && addr <= 0x401F ) {
; o5 c& `1 m- X! I                internal.Write( addr, data );9 `3 I& K+ d0 j/ f/ R
        }) k7 _9 G' }% v/ V
}9 R0 ]: Z2 o( [/ q

4 ^) ?( H, E8 K  ~void        APU::WriteExProcess( WORD addr, BYTE data )
4 u" K0 u/ ^: a6 C8 t: L{1 V7 s/ Y1 E* ~6 n5 p8 s
        if( exsound_select & 0x01 ) {# C8 ~% m! o3 ~: w8 M. j
                vrc6.Write( addr, data );6 O2 P5 d% x# z1 h
        }8 H* V& H* c2 D# E, L: O/ e# k
        if( exsound_select & 0x02 ) {! j. W* U2 j4 C1 r4 }4 f( M4 Q
                vrc7.Write( addr, data );/ K. U1 V* U0 i2 s& S& o4 Q
        }
( [0 D) O& i5 w2 G$ z5 w        if( exsound_select & 0x04 ) {5 H$ O' f* s: N- `+ u
                fds.Write( addr, data );
) {! K' h9 i. [$ t, F; O0 q        }
; d5 h/ o0 J) ~* O        if( exsound_select & 0x08 ) {- D1 @) g' T# I2 O6 E% i) B
                mmc5.Write( addr, data );3 o9 |5 L: W; |
        }. [  D& u) z. V, O$ j3 f, f  |
        if( exsound_select & 0x10 ) {
/ a  J: l8 \% i7 W5 ]  T' d                if( addr == 0x0000 ) {; O. R0 ?8 K* B
                        BYTE        dummy = n106.Read( addr );/ ]$ h% X& \+ ]' ~/ L- u
                } else {% d+ J! t$ |" D; ~
                        n106.Write( addr, data );) r- {* W+ B, j# r5 r
                }0 y8 ~4 T* f, T6 [. S. @, C4 G
        }
% L/ L/ s0 k: d( C        if( exsound_select & 0x20 ) {% y- h# H! C1 C& c  h
                fme7.Write( addr, data );
9 k2 c' G5 p* L+ D3 u8 Z* `4 a        }  X% T. b) ]% K$ Z
}$ C6 a  |. P5 j! b  E6 w. q- t  f: s

8 i& Z3 G& C0 J# K+ b" yvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
# G2 I2 h8 B  J1 G% j# x: _5 K{
6 r/ v7 g# e6 Q& @3 fINT        nBits = Config.sound.nBits;5 j9 k2 L9 V! n
DWORD        dwLength = dwSize / (nBits/8);+ k) o& W' ^4 i9 q' r0 g
INT        output;+ p6 Y8 V, j; l$ T
QUEUEDATA q;
8 s: J. Z: Q+ E5 `DWORD        writetime;. A( o; @% P: G- i7 v0 r
' D( H  G, m/ X: b/ z, t- J9 \  s
LPSHORT        pSoundBuf = m_SoundBuffer;
, A: Y2 K, P- @  q. M5 v: UINT        nCcount = 0;
) Z+ @3 I+ g1 v1 q2 Z2 ~# e- x7 Q% k
4 |0 {0 `8 r' Q5 O5 tINT        nFilterType = Config.sound.nFilterType;
$ ^- t2 \  H: s! Q/ o1 c
7 O- x  Z$ M) p, w' |! a1 v0 M8 S        if( !Config.sound.bEnable ) {
0 N4 f! d2 o! V! N3 f                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );- }& V2 S( t) n6 D% m1 h
                return;
7 x2 p- R0 _( t1 s$ m& d7 Y0 z        }! a: F( x* B9 \5 V
. Z( L8 c: @& \7 a; R( x7 A0 t- K
        // Volume setup
# u( W4 w. F5 f: {" [        //  0:Master
6 f3 f9 x0 U' u5 e+ P        //  1:Rectangle 1
1 m* K* T/ B! C( w$ Q7 s: v        //  2:Rectangle 2
6 A. O# H" s8 M' d. g        //  3:Triangle$ Q, F+ J# Y4 T+ T5 ?3 \1 Z. R0 l
        //  4:Noise) u  V# N7 Z: x# }2 ], A" O
        //  5:DPCM
' ]: H- k$ p, }2 U2 ^+ p        //  6:VRC6- }6 e- s+ u+ R" M
        //  7:VRC7
' \9 L) e4 q% k2 |        //  8:FDS$ h1 G4 s3 d2 r, l1 s& a
        //  9:MMC5
2 S. h/ @  Q5 t6 e        // 10:N106
* B* H1 r+ V) i        // 11:FME7! h: a! S& F8 i+ B! M
        INT        vol[24];
, m/ X& C: c) D0 C        BOOL*        bMute = m_bMute;9 s" v+ r/ o& @1 A0 l' R+ @* V6 b& |
        SHORT*        nVolume = Config.sound.nVolume;
+ ?" L" d# E, q5 s/ x7 S! j
. t! B8 |2 C, l) w8 _; d  N; x* |        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 v6 |3 r. D- @" m, C/ \6 Z
5 N, y9 H! F5 p/ P2 w
        // Internal% \3 `, b+ u; e' e; B: }
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;2 [6 M$ j8 ]' K1 P* }
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
: z: Y" O% G7 i0 u9 N        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
( E" x: o" ?' I* N        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;! a( o7 x5 b& }9 ?5 t+ Z: v
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
8 P" a: ~/ O  ?$ g% h3 u
: l9 d5 r( l. X- u+ O        // VRC6
; N9 g6 F2 u2 A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 b( n+ J  s2 n        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, Z: z* ~7 r, d# C& [* Q& ~        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 }) ~3 e0 _* [- ~! O: w
& ]4 I5 g6 j6 U) ?# D        // VRC75 m& t$ n1 S/ y1 K* C7 k% {2 m
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 s6 C0 f$ s( k
) L0 O, Y4 U+ w( [5 T4 i9 V. S- L. J: v
        // FDS
- S/ ^8 E) z7 E+ D0 B* N        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;- t: u$ E8 W7 k  F8 K
( u, X! B& D) V
        // MMC52 c: o) T; x/ H& t: ~* f4 F2 g
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 Y/ ^, O; t. B8 {) r
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ j1 w8 ?2 y- D( ^, w7 e" z- V5 g2 v        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! k0 q) u+ q' T; S6 T6 f- b* D$ V5 n( |
        // N106+ N5 F/ u# N1 d% F/ g
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" b) ^2 r4 }' @! [/ g9 @
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ I: h! }- v* @
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* \3 L5 v9 s, P5 |+ {2 }        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# ^: w, E$ T" V5 O1 D8 E
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 b' A+ Z! G) ?& j+ [4 _% h4 Z5 q
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 E% m  q! ]; ?; i+ r5 h
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! Y$ s" `8 W; E& G$ Q: O- b
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& c# I- w$ j( e* T/ }3 T
3 f" @. p. e, c$ U/ {        // FME78 }; J" x: w. c' s5 ^
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ _; e% C" O2 b! z
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* x7 H; B- i4 d1 O        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- c1 C4 ~/ J# @/ K" t* [0 I, L. o% {' @$ V! B. H+ K8 s: {
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
! E$ \: e7 f  I        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;0 R* N2 ]2 R2 {, z
- N$ e$ F4 ^3 v1 y+ E0 @& {! Z
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 L7 X; z. D0 _( g* G
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: x. L, h( _7 _' ]9 K( S; Q4 E
                QueueFlush();
: q' V' Q, |, p( t        }  R9 S# O/ r/ f: l& ^

9 S2 O* m6 l" v6 y5 R        while( dwLength-- ) {1 y' p7 l# K$ a/ S: x: c
                writetime = (DWORD)elapsed_time;3 ?& ^$ b. G4 `* l2 m
) Q1 d4 b; q( U# ]: h  F
                while( GetQueue( writetime, q ) ) {
, i; p/ X+ W/ F; z' F9 E) |                        WriteProcess( q.addr, q.data );
! ^* C8 ~; Z6 n; M& n! e                }
6 {) M! \) \6 `$ k0 m9 W% v, h: I, o" [. a- I7 N/ @# D" Y
                while( GetExQueue( writetime, q ) ) {
) [7 b% T; m3 W: j) u                        WriteExProcess( q.addr, q.data );3 W: H* p' U5 z2 {; f
                }
( ^9 b$ D0 w& {, ?2 L  N- Z7 m: b( t7 B1 }& B6 Y& E1 S
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
& I$ A6 |1 w# ]+ n( `/ B                output = 0;
  R' B6 D6 w% A7 V# \% R                output += internal.Process( 0 )*vol[0];
; p$ w/ a; U8 |) K( T: K  m                output += internal.Process( 1 )*vol[1];
# T+ e0 ?, k0 V/ l3 Q7 \                output += internal.Process( 2 )*vol[2];9 p0 M1 ^) i! {4 J- z8 {
                output += internal.Process( 3 )*vol[3];
) g  G/ b6 z% B                output += internal.Process( 4 )*vol[4];
3 R9 z# S; R0 j$ V: x! n% I) U& i+ I% `( u
                if( exsound_select & 0x01 ) {
- U7 Y4 h3 v/ v6 g% U) V                        output += vrc6.Process( 0 )*vol[5];- W4 S$ {" L2 F
                        output += vrc6.Process( 1 )*vol[6];* w5 ^9 O3 m, _# w0 _+ f4 Q* R
                        output += vrc6.Process( 2 )*vol[7];# n& d3 a( Q! m6 g) j
                }
8 J9 x) X% p7 b. k& ?; m5 m                if( exsound_select & 0x02 ) {
5 q2 J/ }" j9 A  `8 ]2 Z- i                        output += vrc7.Process( 0 )*vol[8];
( o  F7 q& j& v$ T* E                }
" g7 b) Q' A. B/ `                if( exsound_select & 0x04 ) {
8 q1 I# G# P" {8 I) i* P5 w                        output += fds.Process( 0 )*vol[9];
0 B3 Y4 p7 X" R8 W8 m0 y                }
# U! E# U4 O. E0 U                if( exsound_select & 0x08 ) {
" @" s: S9 o0 ]                        output += mmc5.Process( 0 )*vol[10];
" L6 F* H: X2 q; n' H                        output += mmc5.Process( 1 )*vol[11];
% L7 U1 C/ a& b1 Z" |+ ?, J2 S                        output += mmc5.Process( 2 )*vol[12];
' ~( o3 C: D$ V. H                }
5 i" X; a% s  Y: M5 ]                if( exsound_select & 0x10 ) {
' ^$ F; Y% a! r                        output += n106.Process( 0 )*vol[13];
% e" e" f' Y) c7 j: a3 S! L                        output += n106.Process( 1 )*vol[14];
1 P5 q6 k% H- B, a                        output += n106.Process( 2 )*vol[15];
; y8 }& V2 m, C$ I9 i                        output += n106.Process( 3 )*vol[16];
4 N6 }7 H3 {7 l' |5 S) C                        output += n106.Process( 4 )*vol[17];
, e1 `4 `+ B! A1 a                        output += n106.Process( 5 )*vol[18];
: k4 z. `5 g! N9 @                        output += n106.Process( 6 )*vol[19];
* g, T( e$ d* X: H& a2 ^                        output += n106.Process( 7 )*vol[20];5 T! s7 F; u" d& H$ J$ T: F9 D
                }
# M2 u3 P1 j0 A                if( exsound_select & 0x20 ) {2 C' K  Z5 }$ y* G
                        fme7.Process( 3 );        // Envelope & Noise
5 ~) V6 D  z4 _1 ]9 i                        output += fme7.Process( 0 )*vol[21];+ W" T# \$ R- v7 p: [8 B$ x  r1 [8 M- p
                        output += fme7.Process( 1 )*vol[22];
+ q' h, |- B. M+ {& i, H                        output += fme7.Process( 2 )*vol[23];
. u$ X, Y, E, k6 k) R                }* t7 u( B7 y6 P. K3 o
, s+ v9 j; f1 z" z5 ?5 J
                output >>= 8;
! D2 O( B+ C2 u5 S) m( y, ^5 T/ R4 P; s
                if( nFilterType == 1 ) {
8 ?# o5 o7 |8 \% h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)1 h/ @% a2 t' [' s* a2 ~; j
                        output = (lowpass_filter[0]+output)/2;: H$ x0 g1 X( h7 ~8 v! D
                        lowpass_filter[0] = output;) Y- C, F2 Y' m; d2 U/ N( I/ X
                } else if( nFilterType == 2 ) {: N, F9 f. Q* H& r4 c. @$ r) j
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
3 f3 ^4 L. e- a- D  W5 i                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;" A  [# ?# U5 C0 g' r) @
                        lowpass_filter[1] = lowpass_filter[0];/ [; I6 X8 G' J9 |( N$ G
                        lowpass_filter[0] = output;
& ~% {- D; d3 R: Q                } else if( nFilterType == 3 ) {+ ~- R3 B; w8 L& z% c8 u- ^+ B
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)+ Q8 m7 `# b8 I
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
$ i) ^* }5 w+ @2 B5 U( B3 F$ }                        lowpass_filter[2] = lowpass_filter[1];* @# a- Y. O$ O6 p2 q4 H4 M1 Z# U
                        lowpass_filter[1] = lowpass_filter[0];
# K( ^* T& n1 T; h' u" {                        lowpass_filter[0] = output;
' |4 C% f  e6 W6 D                } else if( nFilterType == 4 ) {
& f$ m( G2 e1 u- L                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! b  z- N' e  w( Q                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;) L# L# H/ ?, F5 _8 r
                        lowpass_filter[1] = lowpass_filter[0];1 V1 P3 P' }& r9 Z2 I2 [
                        lowpass_filter[0] = output;
2 W9 n$ c! Q3 n2 B. g  h& j                }9 x9 q) @# v: q0 f9 }( s: o

) t3 W6 y6 [, \2 F* \#if        06 u3 ?  _% J. D: h7 s* R
                // DC惉暘偺僇僢僩* B- N) b2 O1 d2 \7 `+ e
                {
- M- }5 f- k' K4 u                static double ave = 0.0, max=0.0, min=0.0;
6 L; M% g/ E8 P( q* M& Z                double delta;
8 a# o1 n' M6 S# U6 \5 L                delta = (max-min)/32768.0;' P0 r5 c' {2 a& M! b1 b! q
                max -= delta;* G% s) V1 |$ R& A
                min += delta;& {' v0 D4 Q+ X, _+ Z5 ~  p
                if( output > max ) max = output;0 L" i6 \. g8 _! J  |- R$ i7 x
                if( output < min ) min = output;7 e8 \! P3 e0 R; ]1 l$ m3 d2 z
                ave -= ave/1024.0;
, C) Y4 w; a6 v& F4 H& p$ ]                ave += (max+min)/2048.0;3 ]! I# O1 @$ l% p( I
                output -= (INT)ave;
& e# T2 M4 R; O6 A/ g3 s/ ^                }/ ~& ]# N: I# G# D- g' @
#endif
9 }8 m2 L( s( o! d#if        1
* j- }  K% g  _                // DC惉暘偺僇僢僩(HPF TEST)
+ z0 g4 X. n8 o2 w4 L, c                {9 N! H  N6 e3 H. z( m3 n
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* _. \0 b, s! J
                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 d# T. s& J" G" q# t2 A
                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ J0 C* O! k# {/ U
                static        double        tmp = 0.0;% N0 F' A$ D# u( ^! X" o9 |: T: r0 Z
                double        in, out;
& X2 ^% W0 \  I# |, K5 L& o
6 G4 t* H; I+ u. z; Q2 Y  i  I                in = (double)output;
# [6 [- g) {8 S5 y' x1 }) s* m( A$ J- P( u                out = (in - tmp);
) \5 X' I7 C9 y6 J7 M, H1 o0 ~$ a5 ?                tmp = tmp + cutoff * out;
% T4 c9 ?  t  _7 E
+ p# P+ z/ }5 Z# b                output = (INT)out;4 V; u& a( d6 B. L  h3 f; f
                }
3 {# \+ e+ I$ E0 ?#endif4 m! f9 G# p2 S4 \; W; h9 P
#if        0( S, h: r* K$ Z) g4 ~% n
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 q$ L6 E  l- S
                {
  i1 C5 p9 ]6 P/ H. q                INT        diff = abs(output-last_data);' f% v1 u2 B1 u8 t, a3 j
                if( diff > 0x4000 ) {6 M1 m$ _" h/ K+ S$ Z& B
                        output /= 4;
8 }( a, B' m) d' X                } else ! }, U! X, H+ u& M% e) G1 `  i
                if( diff > 0x3000 ) {
# O3 `; ~# e( t% T: `% g                        output /= 3;
% x+ S% z( P8 w& p. g8 V                } else. y4 g+ S! _# W7 z9 E
                if( diff > 0x2000 ) {
- t5 t, x% `/ b4 ^' e                        output /= 2;: p8 J% p7 T7 Z- ~1 Q
                }. V6 t# y& S! M7 U
                last_data = output;1 O+ d3 @! [, O! p) O) L  |- Q& K
                }
& |# d' U/ Q' I+ B  ]9 L#endif
" @3 c9 X1 A3 f+ R; r9 ~0 E4 k$ Y# ~5 n                // Limit. f, ^7 u* ?. j( ^2 b0 k: t
                if( output > 0x7FFF ) {- f* M6 ?$ H! ^; z6 ~
                        output = 0x7FFF;
0 Y0 L3 N' l$ M$ `& ^+ V- C  w                } else if( output < -0x8000 ) {4 q8 C& T, ^4 V
                        output = -0x8000;
4 g  a4 t9 p8 Q0 Y                }! x% h7 w7 J$ F# t! o. w8 a( ~% ?

. Y" a* }" k% ?5 i1 J3 k. N                if( nBits != 8 ) {5 |" P0 y. t3 ^
                        *(SHORT*)lpBuffer = (SHORT)output;
; J. U8 S$ b7 Q                        lpBuffer += sizeof(SHORT);
# y4 j7 O. D) q" @$ h                } else {
0 W9 T" R9 Z* a3 M* ?, K2 a                        *lpBuffer++ = (output>>8)^0x80;4 q3 V( _, F3 c* S; G) E
                }( L% X4 }$ _1 }3 G! v, ^
0 U& D$ t- O$ U! Z/ N
                if( nCcount < 0x0100 )5 F/ ]( O) X( K+ y
                        pSoundBuf[nCcount++] = (SHORT)output;0 I: B7 a1 Y( Y' ?  b9 I
& d5 r3 I2 z# p" X7 [4 R
//                elapsedtime += cycle_rate;5 a# X: @6 _+ u$ W3 \- E" V! }" A1 Z4 V
                elapsed_time += cycle_rate;
4 U( |0 ], M3 s        }( p7 L. U- J3 e' u" c+ B

5 @% c) }% j% `6 D4 z#if        1
' J5 N: [, u. U" x! q( P        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {0 s6 |$ y! C& N* N2 e. e
                elapsed_time = nes->cpu->GetTotalCycles();
9 G+ }8 S, A( H. ]4 n. A        }$ @/ ]: U, z; e# n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
# V" u: L7 [3 I) }                elapsed_time = nes->cpu->GetTotalCycles();
6 ?! T3 h8 t7 p1 e( t8 V        }
$ z; {0 d2 p, ~8 a# Q) q. l. {#else
7 _! r9 H4 N  R7 S; q6 e, c3 K        elapsed_time = nes->cpu->GetTotalCycles();
8 z0 q' k' P  W% F9 V#endif
1 l) }) J/ c$ k" ~}8 p9 J* G0 v7 c' r

6 A9 W" d: F, X) Y6 {3 D9 H# p$ L// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ U7 T" B$ R# h, ]2 GINT        APU::GetChannelFrequency( INT no )2 B+ E: d( [$ H
{
2 t6 \6 [1 \  O2 N        if( !m_bMute[0] )
! {- B6 D, m# J6 C                return        0;: C; N! y" J$ u8 _

) [' A/ V. M; g        // Internal
7 ?9 P: d  J6 |$ m+ q, B5 X% ~        if( no < 5 ) {
% L0 ?# t% }+ T! ]- [5 F                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* P* j; r9 y2 V6 V8 p" H# o* b        }0 j( k! S: {9 ?4 b: `5 s8 h* ^
        // VRC6
' K4 g3 D( s6 F# Z5 t2 P) d) w6 T        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {' b: S# z+ P; f' K5 `* A: o8 `; \
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;; }3 k# _: n5 O  x& h
        }
' x+ f' B- X7 F' y" ~0 U6 R        // FDS
  V4 ~& W% |2 h& b2 n$ }& Y/ I7 U+ N        if( (exsound_select & 0x04) && no == 0x300 ) {. K  P0 m/ H) O  v
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ {: v/ S. r; B+ h1 ?        }! q5 C, p6 J  _2 u* T8 @- I
        // MMC5- |" ~  w7 l% Y, }( y+ i# g
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
2 k$ ?( R: ?& K! e& N5 R                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;& x. G7 |# g! L. t8 I4 s
        }; r8 U% }) H2 T# r& }' [
        // N106! \4 E8 h# h) ]3 G: f! ]( k; Z% b
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 L, S8 {6 b7 C7 \. j
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 p7 X" c' L, @" R        }
8 H6 R1 U- Z3 T% L4 a        // FME7# n' A( K. ]8 ?2 D8 z
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {; C, P9 J8 `) {/ O
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 t7 c* o5 c# P  y8 ]        }* X! s+ C1 ~% L& R
        // VRC7
$ V0 k7 ?3 T) A- P# h" `+ D: k7 e/ r        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {+ O2 @: D( I/ L; r2 _
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;! q& M$ R( f7 o1 C# a0 S4 b) I
        }* r9 A9 A1 Z0 d( n0 A8 W
        return        0;/ {% S4 _/ g! i7 C
}' |4 J2 M. b, n. S% N

2 W3 X" R* n1 K// State Save/Load& W' x* @  c* H0 l9 e
void        APU::SaveState( LPBYTE p )
' P! T8 H; [/ ?2 @! A+ {{  M7 R8 U5 _; a' |
#ifdef        _DEBUG3 c0 W* h" x$ @% ?) Y. Q: A. I
LPBYTE        pold = p;
# ]1 ~( m9 ^& _6 H% y5 @#endif5 [, O  U& \. \+ I  _8 ?

- ~+ Z* }  S9 Y& w1 ~4 `1 ]# e        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞) ]7 P' x, D( v+ h* v# D/ B, O
        QueueFlush();
$ f5 Q  W* [4 Z2 d  s8 _' _7 Q: r, j0 T
        internal.SaveState( p );
4 }* K0 s9 y: K+ H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; _! R: G6 d$ t) N$ c' q0 ]

1 `  @9 J- u- J. [( F0 }6 d) S( X        // VRC6
( l% E9 y: S. o- E7 I3 s  R        if( exsound_select & 0x01 ) {+ y* B6 g4 I9 J
                vrc6.SaveState( p );; i3 |  @) j; \0 g6 J3 h6 n
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% n9 m+ H- }! n% L6 x+ N
        }$ G/ f0 H' c! W' @' a) I: f- s
        // VRC7 (not support)
. O1 a6 f& [: |) w6 {0 M2 k! y$ h        if( exsound_select & 0x02 ) {. |" v) ]" h3 @) H- q; R7 B$ N
                vrc7.SaveState( p );
* ^( H! w3 h9 R                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 v: f1 Y% Y, ~9 G, U; i
        }6 Y5 T/ _- E3 X5 J. M: i+ e
        // FDS! O7 P/ s$ x0 d/ C' C
        if( exsound_select & 0x04 ) {. V/ q: _0 c9 Y' v4 G
                fds.SaveState( p );
9 j) H" m% d6 f                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 J6 r* W/ _% B6 q. ?: @. p0 }
        }
; o2 @4 }# Q+ I# S& I        // MMC5
$ L* D& n9 u1 r; O        if( exsound_select & 0x08 ) {
$ J1 C; n3 T7 y$ i7 @                mmc5.SaveState( p );. o' ~) q, }8 J& l0 g1 n- o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- t  v7 k! F, J+ L( @% F# I6 P        }0 T# Q/ [! t1 V6 c' H' `/ }4 r
        // N106. M6 E/ K- m; e& J& f0 M) E
        if( exsound_select & 0x10 ) {
2 K9 x' X+ o/ V4 x" T, R                n106.SaveState( p );2 z* J$ c+ a! d2 v% {; d
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# [; J4 U5 k7 G; n! A1 \/ C
        }
& @! g! J* G& f/ }2 |        // FME7
2 G; w0 `0 `( x( Q' y! ~        if( exsound_select & 0x20 ) {9 f' |! n' L% V0 [0 u7 g  U$ H6 r
                fme7.SaveState( p );& v& l3 `0 c( P( w  `
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) z$ x# J2 _: L6 |        }
' b4 `6 N* O& c
% n) a6 n# ~( g#ifdef        _DEBUG" J# L2 M0 h% p) c/ ?+ q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );( n" m, e# D* \
#endif
- |1 R  S8 W9 G% k/ B}; i0 B" R# ^, F) h/ C, X0 m# `) h
$ |* h9 `  V! j. a7 H
void        APU::LoadState( LPBYTE p )
& T) i# \0 ?: o1 A4 ]{& }% @: i, a5 Z/ C* |  n+ g0 ?# @
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡) @1 w: ^3 G( K) s
        QueueClear();
* i8 m, T- y( D* ^7 N  |* ?! n2 Q" t# E. t* x" F6 H
        internal.LoadState( p );
9 o$ [2 E5 U0 p; S* ]  t9 \5 V  k        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& D! M! n& K! ]5 X
; Y' e. o, |0 _" n& V9 S
        // VRC6
) S! x/ l6 D( \; W& `' U- R* Q' z% S        if( exsound_select & 0x01 ) {
6 ?3 ~5 D2 J+ {; J2 o                vrc6.LoadState( p );7 I+ ?  A2 ~! d/ L, y) Z5 |
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ m- x9 T! M; i" q/ G        }  k: K) j" V" y. Z5 D, Q
        // VRC7 (not support)
. x. l! G/ d2 `1 v+ B4 e% A; E        if( exsound_select & 0x02 ) {% ^% i" O# F  u1 e0 U' @3 c7 I9 l" q
                vrc7.LoadState( p );
7 t9 A1 a2 k4 r1 ?                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' |6 p! x8 t4 ~' u" g        }
$ h, R8 K6 e5 w/ N! ?4 u: I        // FDS$ K2 v9 S# Y+ ]2 F; @9 z
        if( exsound_select & 0x04 ) {
- `$ ?; h: u) j4 [7 v                fds.LoadState( p );, f  P- k( B% M, Y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding( L  w  `+ Y. I: J+ O
        }
4 G% w6 s' T1 i9 z/ r        // MMC5$ J' u! S/ I9 y7 ~$ G2 U' B7 M
        if( exsound_select & 0x08 ) {
2 W9 T3 A- j$ v* y" D8 d6 m                mmc5.LoadState( p );4 T- |( A) @" w. L
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& S& B" |( Z6 t9 \, H% p( E        }
) L5 b# b5 F* b+ b        // N106
' z5 a5 u& \4 j. O3 D0 J7 v% \9 R, V3 L        if( exsound_select & 0x10 ) {
4 G% T' W  `% K) G% I                n106.LoadState( p );, {, t8 E9 s3 H: U3 f/ G8 M1 `
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 ^* u3 ^# c3 `
        }
$ N- p- H8 l+ p& ^$ J+ d1 ]        // FME7! E9 F6 K8 g$ g5 [' V2 y. ?3 m
        if( exsound_select & 0x20 ) {
" R1 T2 j. A* |                fme7.LoadState( p );
$ V* j) I$ o8 _; u; N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 |0 D* P# {. ]. q. _1 M
        }! V. H# ~- u6 u! y/ q$ Z
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, ^) {* W! l3 k: ]( a可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' M& W( a8 W0 |8 J  W( e. e2 p感激不尽~~
! V9 z3 g, c; \8 t. y  v
恩 我對模擬器不是很有研究,
" M+ f! O6 s: x& o8 B雖然要了解源碼內容,可能不是很困難,- p$ ~! M5 _# d# F. Q3 P6 L3 d
不過還是要花時間,個人目前蠻忙碌的。, }/ P! Q+ p# j" B5 C9 w4 n

3 D* w) c( \) Y- L( {/ w" c給你一個朋友的MSN,你可以跟他討論看看,7 p  X/ k4 I3 Q# [6 ?$ L/ b, s; ~( s( H
他本身是程式設計師,也對FC模擬器很有興趣。
7 f  f& Y9 {9 J! M- v+ Y3 N* n. s5 b
MSN我就PM到你的信箱了。7 T  h7 k* w- F
4 F7 _: c. D7 ?  |4 r) o, g
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
" u& I. p( c+ N+ G& R* H4 d0 ?呵…… 谢过团长大人~~

: F  D/ Y# j# E$ S8 F1 w$ N2 V# J3 A0 U) Z; D  o' R
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 . \# W8 Z6 G& x) |
团长的朋友都是神,那团长就是神的boss。
$ `% b* `! n( Z/ S# [) `
哈 不敢當,我只是個平凡人,$ F5 B( @2 {* W, s0 R# e
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙( ^( N8 }. i! e1 V) |7 I9 @- @# X8 n
ZYH5 K: |) m* C- Z  k: I
QQ:414734306
  K6 A! C6 Q# ?; v5 U# h/ l8 VMail:zyh-01@126.com
& E/ n  r. Z0 j9 }
) m8 D1 ?- N. j他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
' O0 _% `3 [' E; E+ k再次对团长大人和悠悠哥的无私帮助表示感谢~~

8 `) u0 S- S$ ], T) ]0 U不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-3 09:01 , Processed in 1.099610 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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