EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" A: @/ x. e+ ^: w  A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 J3 N  L! m# W这里有相应的模拟器源码,就当送给大侠了~~1 ^. z% j$ x2 T! c
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
. M9 Y; Z8 v' E$ r3 r% ~# `能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! V4 |" U6 v& ]2 I# i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~5 Y. W! R7 P0 d- J$ f! ^
这里有相应的模拟器源码,就当送给大侠 ...
6 I5 K% I- l% m+ b% t4 y
聲音部分(Audoi Process Unit = APU):& g6 z2 I8 I* p  h& {! L2 i
.\NES\APU.cpp- ^& q4 C7 Z& S* @. Q; h
.\NES\APU.h
5 q- a  D# C8 B% Z( c4 t% S
# X. u+ c& R& C/ Q: ?% g! `: e5 v7 T
4 g2 _3 L% }5 n- I& h* a! K  z影像處理部份(Picture Processing Unit = PPU):
7 }. b/ L4 e) [" u9 k3 w8 [.\NES\PPU.cpp" K$ d: i4 q1 _9 E8 B: O
.\NES\PPU.h: Z* K3 |8 N# T: x) p0 |

* j$ \! |+ Z  A  o如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:! T$ q0 {. D1 N  ]
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
" l9 o4 b5 ^+ |3 s# X; g0 o/ q, o//////////////////////////////////////////////////////////////////////////
: w5 n6 Z( e3 }" v/ W//                                                                      //
/ E' O6 n) l6 j- y/ D//      NES APU core                                                    //
* d1 h/ }. G1 y//                                                           Norix      //
+ [4 X3 D7 ^3 V2 X# r5 p. M//                                               written     2002/06/27 //& p! U5 e! {8 a" A( ^
//                                               last modify ----/--/-- //6 q+ j& x9 {8 M7 ^
//////////////////////////////////////////////////////////////////////////
3 |& A; W- k$ w+ f% K' q/ h#include "DebugOut.h"8 K- x6 H$ z$ T2 a
#include "App.h"
% D& A& ?" }& Z4 H#include "Config.h"
+ L- g/ }; t5 {# l9 {+ m+ T! W. c3 y2 [) K0 P) W$ a( y7 u" {* \( v7 Z
#include "nes.h"1 e0 c0 j, Q! L: J: w7 z/ l
#include "mmu.h"
- L7 |1 W4 X6 c/ \, ]#include "cpu.h"' w" Z" u# p2 p+ S# M0 t) I4 j) o
#include "ppu.h"# H8 c1 q1 \2 S% d1 Y% c5 u
#include "rom.h"
4 t# S" x( Y( @/ h2 u8 C( C#include "apu.h", _4 D: a- {$ P/ P) J
8 O4 g! ~0 z- D$ L; B
// Volume adjust
$ L4 B- b3 Z" n/ P8 z// Internal sounds  ^& s2 m3 N- f: B+ q4 O# V$ M$ K6 [
#define        RECTANGLE_VOL        (0x0F0)
# m$ ~4 s1 s' j& o7 G#define        TRIANGLE_VOL        (0x130)
' c. K+ h, Z( O5 j1 Y6 G#define        NOISE_VOL        (0x0C0)
" S% V/ d& S# Y8 R! D3 ]#define        DPCM_VOL        (0x0F0)2 l' P9 p& D4 D! d& v
// Extra sounds
& M' A7 X% X! z2 _#define        VRC6_VOL        (0x0F0)$ C% K3 F1 q8 L( f' U/ s' g
#define        VRC7_VOL        (0x130)
) @& V6 F" H9 S8 h& g, b+ m#define        FDS_VOL                (0x0F0)2 |+ {( v" r8 `
#define        MMC5_VOL        (0x0F0)
" w% q' k4 V/ ~) F3 |% W#define        N106_VOL        (0x088)1 c" X5 R5 f3 X: c- z  E! p
#define        FME7_VOL        (0x130)8 E& p6 q; H. ]6 Y3 E
: ^, k  v' w7 a2 y5 r0 \; g
APU::APU( NES* parent )
( B& ?! D. t4 a6 v& \{
0 A7 n& o8 {7 t6 I2 p        exsound_select = 0;
' o- \+ z/ q6 r4 a7 B
: _5 E( R$ z( D9 v1 }- r        nes = parent;+ |+ m9 U" Z2 Q9 E" V6 S  C
        internal.SetParent( parent );
8 K! B  a  t* C$ _- l6 Y
) ~2 w. b3 w" Z6 ?+ O$ W1 B        last_data = last_diff = 0;( n9 L5 k  z' C0 Q
* G- Y0 p/ l" a; _, R
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- j) m: D: G9 u7 x7 G% m7 \' y; E
+ ~+ i1 Y# G1 n0 j9 Y9 R" x6 M3 X; h+ O
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 ~' A* s+ H! R) D% G2 |7 t
        ZEROMEMORY( &queue, sizeof(queue) );: B7 e2 I. {/ a( n( m. ]
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 {  }5 N7 j, }

( G6 L) x0 L$ e3 E* X) A        for( INT i = 0; i < 16; i++ ) {
4 n1 }/ |* H1 d$ `# W; S                m_bMute = TRUE;
5 Y7 b9 c& G: f        }' ~' L. \6 r; a( ^- E4 M3 l' o
}
7 G( x+ \  ?8 w3 `* N. i  Z  m3 e0 {( ^' H/ T7 r
APU::~APU()* C& c( O; p3 h! E# B* _; c
{
6 e5 j0 Q6 [3 q  g' A}9 Z9 l- J: Y0 f- O
; K: Y4 X% u$ W
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )7 [* M7 h# Y2 O" N- k
{
7 _& w5 E6 U3 V) O! j+ W9 V( B        queue.data[queue.wrptr].time = writetime;
  g3 v" O  d9 j- y7 a7 L        queue.data[queue.wrptr].addr = addr;: I" v( r  N! o& D
        queue.data[queue.wrptr].data = data;9 C! [% J. I4 F  I% k0 Z% k
        queue.wrptr++;  {7 f, V9 p4 v0 z3 W6 E" C3 s
        queue.wrptr&=QUEUE_LENGTH-1;- g: }) P9 Q+ A# B, S( l
        if( queue.wrptr == queue.rdptr ) {
7 w$ G' m2 Y' M9 O  [; [7 W- {                DEBUGOUT( "queue overflow.\n" );
; H" \1 X# J6 M        }5 }' C' C( g4 W$ ^
}
' ?. b# a, t& u' E
$ e9 N/ u3 I" P/ U4 E. s1 SBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& ]$ ^6 Y1 I, ?8 q, }( j- }{9 R! @( a8 i) t0 C
        if( queue.wrptr == queue.rdptr ) {
0 U  E) c6 m% c" d/ R5 a4 P                return        FALSE;5 x" E$ z% M2 C; K# w
        }& v8 Z. c% i0 P
        if( queue.data[queue.rdptr].time <= writetime ) {; O2 L7 c- W$ f
                ret = queue.data[queue.rdptr];' ?; p: U2 X0 q% p) }
                queue.rdptr++;  ~. t  z. G0 z; V( J% C6 x+ l- Y
                queue.rdptr&=QUEUE_LENGTH-1;# \$ e2 W+ p& N# Q% ?3 O4 H4 K7 H9 C
                return        TRUE;
# o& |6 j+ r8 w$ r5 H2 z+ r" e        }& C5 g5 r( E1 [4 \$ V, ^
        return        FALSE;
' I( Q$ k, D3 K}
6 B+ D1 b9 [( ]+ p; `; L# s6 U8 S9 U/ d1 u
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )# l+ J) `! p- R. T& ~' q( }
{% ?" L  p5 U0 a
        exqueue.data[exqueue.wrptr].time = writetime;1 L& v% B6 P" Q
        exqueue.data[exqueue.wrptr].addr = addr;5 v( s; \# _1 i' X
        exqueue.data[exqueue.wrptr].data = data;+ S" O, ^. ?" @' V
        exqueue.wrptr++;
  `. j2 @. Y  K+ k7 i$ S        exqueue.wrptr&=QUEUE_LENGTH-1;
% Y+ ]: ^4 q4 e$ J2 y        if( exqueue.wrptr == exqueue.rdptr ) {$ H8 x7 G# d6 I. Z, }
                DEBUGOUT( "exqueue overflow.\n" );$ g, V! g& H$ W; o0 g! v% R5 K; S
        }
* r7 C$ b& @* E: x/ J  p}2 ]$ E9 f# J. v3 m* H: o- D* i

$ I& w1 p5 |, z/ zBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
2 N6 s  A# w% r. A' i{: a. i* r( C  ~! G! \/ q$ K
        if( exqueue.wrptr == exqueue.rdptr ) {3 v7 Y, x, \, P# n3 T7 Q% a
                return        FALSE;8 Z: o1 y% j$ G
        }
( F6 e* h2 x* H$ a( N        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( Z  }4 Z0 d, E  y0 N, @, K                ret = exqueue.data[exqueue.rdptr];
0 s# P' L( z1 S                exqueue.rdptr++;' p, k% {- m! J5 B
                exqueue.rdptr&=QUEUE_LENGTH-1;
% O$ O7 d: I/ N' Z  O" k5 ^                return        TRUE;& ~2 G2 Z7 Y4 M
        }- f* o8 F4 m! q+ T
        return        FALSE;, U; v1 k$ p/ ~" e  ]
}
8 l* E2 V$ _; V. B2 [8 Z9 j
: h2 ~- W& a% M  m7 Q0 x, yvoid        APU::QueueClear()9 m1 L- W7 y8 U
{
2 _5 m5 U7 G$ K3 w1 i        ZEROMEMORY( &queue, sizeof(queue) );! S$ O/ r/ Q. \4 {8 `% J7 H9 s
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ A, ]! h: _; f2 p/ k}$ e  ?# {) k) s& K, ]/ u

$ Y7 F5 P7 u+ [& F1 e! y0 Nvoid        APU::QueueFlush()
7 a% c* P/ p' `+ E: b! z{
& g; R) z8 y9 S2 T! r        while( queue.wrptr != queue.rdptr ) {
6 |6 e. A& e" S                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
1 F1 j. ?2 D9 X                queue.rdptr++;
4 \4 [4 C& q3 ]  O8 b% Q                queue.rdptr&=QUEUE_LENGTH-1;
' ~& x/ f7 P! k5 E, O5 a        }
+ b  t6 x$ m. {4 y$ d, X* e) w8 t* W
/ p* k/ A/ d0 \6 ^5 W( C7 O7 V( @        while( exqueue.wrptr != exqueue.rdptr ) {+ N  d1 H' C; t) g" e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
! E5 G- \2 J1 w; S                exqueue.rdptr++;+ P8 k* p: E* |+ L- f
                exqueue.rdptr&=QUEUE_LENGTH-1;
) S* _6 H/ H9 u) ~8 ]8 S6 M        }
  Q9 Z. O3 h! T5 c4 {}- Z: V1 v8 G! w7 p/ w  ^
5 \& u- K5 T8 E% h" _
void        APU::SoundSetup()
/ c  I5 E/ p% t0 U{
' Z- W) G6 v9 n  a' b1 Z        FLOAT        fClock = nes->nescfg->CpuClock;* d# D+ K- b8 k( V" [- O0 r; G4 l
        INT        nRate = (INT)Config.sound.nRate;* Y& y! v6 j4 e( b8 M
        internal.Setup( fClock, nRate );
3 f) j# r( @, {( A, Z" h! Y        vrc6.Setup( fClock, nRate );
0 V) b3 S0 k/ l% v* x  ]9 y        vrc7.Setup( fClock, nRate );
6 G% J3 k% \# V4 L9 o& F1 u$ ?" p6 a        mmc5.Setup( fClock, nRate );
- _8 u* }( G2 l5 I4 N4 y# A        fds.Setup ( fClock, nRate );+ S) n9 O* a- N, N
        n106.Setup( fClock, nRate );
# Z& c, P6 L- q; v& `: G        fme7.Setup( fClock, nRate );3 Y$ d  n3 T: D' Q' O' Y; _
}, F# ~6 u" e0 h3 t- T* r
  X- u4 p* C: w  u! t% F
void        APU::Reset()
9 b9 Z% q7 F. E{/ V7 @$ b( p. T0 V
        ZEROMEMORY( &queue, sizeof(queue) );2 m9 s- u0 A+ d8 z! D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 O( v) i9 s6 G  p- G

5 S9 }! `& l6 z$ R9 t        elapsed_time = 0;1 \* X# b4 }. _* h/ L6 y, r1 A4 r
) A$ J; E6 v# g) \8 f1 t1 x
        FLOAT        fClock = nes->nescfg->CpuClock;! U' t6 z0 \8 H) B* p7 @5 }7 U
        INT        nRate = (INT)Config.sound.nRate;
) C+ S2 N0 s% j0 h4 I        internal.Reset( fClock, nRate );7 ?# n& U/ F5 Y9 w4 ?0 L! c
        vrc6.Reset( fClock, nRate );# O. ^6 u+ W( {/ f% y: z( }1 Y, f9 J
        vrc7.Reset( fClock, nRate );3 f- Q# f* i1 _/ K, Y5 _
        mmc5.Reset( fClock, nRate );7 {1 Y( `: [) b0 m9 U% q+ H
        fds.Reset ( fClock, nRate );
' T- z/ G+ Q& @3 b, @$ A3 }        n106.Reset( fClock, nRate );6 G, B; \) i7 b7 S/ ?  X4 @
        fme7.Reset( fClock, nRate );
4 M2 b$ B" S1 w3 ~- D) N& k
0 V( |( v( ]" S) P        SoundSetup();( i' L! A3 @: u4 }
}- V7 n+ }1 T; \2 r" S5 E, z. _
: n- F0 ]# Y- R8 F, w* O( [  o! [7 v+ E
void        APU::SelectExSound( BYTE data )$ Q  S0 p( ^+ P" u( ]1 a
{
1 F. O# B8 A: C1 [        exsound_select = data;$ L5 }5 G( e/ S2 D& r
}
: q* G9 {6 a' x7 S6 Y) ?9 w
8 ?' H8 @( e2 F8 A9 b( tBYTE        APU::Read( WORD addr )
6 h& A) ~  n3 F8 x8 [2 l2 b; Q) t{( z2 P* p$ H8 v4 Y# t! K
        return        internal.SyncRead( addr );; N3 `2 b/ D. w  G8 U( ]; I
}
8 z1 j/ a! o8 L; r, D0 S/ x- b( |3 @+ K! c4 B& ?- w* \
void        APU::Write( WORD addr, BYTE data )9 S1 a7 N1 j5 g& m8 Z% F* V
{
1 L8 v6 a9 S  d, H+ b5 [        // $4018偼VirtuaNES屌桳億乕僩
9 u7 o. w" s8 E        if( addr >= 0x4000 && addr <= 0x401F ) {0 Y* f7 ^6 A7 r/ z
                internal.SyncWrite( addr, data );6 Y( Q  b3 v$ e. W* A/ p
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );# Z( r  o: Z, B9 Q/ I9 D4 S& g- ?
        }
- y% a; u$ i; ?4 R, X% C7 L" E}% p7 T3 S! O2 R: b* O8 O$ V
9 E6 X3 \5 H$ b1 K
BYTE        APU::ExRead( WORD addr ); i8 ?7 ]0 p! b) R2 p4 P( l9 R2 U3 H
{$ A% g% M' h/ u3 }( a  Q
BYTE        data = 0;
& i( d0 e5 R# ]. |( n' T+ O6 N7 U$ o3 H* F7 ?. e
        if( exsound_select & 0x10 ) {
" Y# u8 `( J7 z                if( addr == 0x4800 ) {
( k( }, Y, K. u                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
( f, U  [: ]7 u3 y                }3 z8 n, `2 p2 Q" _; p
        }
4 b+ q1 {9 M( N5 r& n0 @. {2 e! H; g! @        if( exsound_select & 0x04 ) {" z1 j/ M: Z7 h( u% B
                if( addr >= 0x4040 && addr < 0x4100 ) {
  d3 D  B0 S- O3 P# t3 y0 B7 _                        data = fds.SyncRead( addr );
3 X* U! D% F7 q5 B                }
, `0 G: j8 f+ u) B        }
% _5 U9 V4 F; R0 L2 w/ ?4 c        if( exsound_select & 0x08 ) {
! N7 B, ?- \, O) L/ b/ `1 s                if( addr >= 0x5000 && addr <= 0x5015 ) {9 i, c0 m4 i; g$ E, T3 z  f
                        data = mmc5.SyncRead( addr );% k' P! |: @1 c. B. B+ @# u
                }
( v5 u1 O9 j/ q8 P% i( s& W* m        }- H8 b$ k$ A0 l+ R
# l0 m$ r9 F- x! [
        return        data;* s) h; c8 f5 z
}
5 L5 E2 I8 d2 n; G; [2 E' q: a# V/ D
) f- i. [# ^* m6 R% E6 ~, Ivoid        APU::ExWrite( WORD addr, BYTE data )0 ~. m( T/ O# d
{
2 ]% v' Z9 Q) `0 u# B        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );2 ^% k! {2 t; ]6 m) i9 s
4 a9 S( s& B, ]/ u: W9 Q
        if( exsound_select & 0x04 ) {
5 t: S& L1 l+ H) N                if( addr >= 0x4040 && addr < 0x4100 ) {
' }% X) o: q2 S. F6 A4 ]                        fds.SyncWrite( addr, data );
* z3 S+ E* x3 w7 w, f" }& P7 o3 f, n                }* Y5 B; `; j' w& j% ^5 t$ |& I
        }
* G/ ~; j4 j' i" }
' V) I' E3 c& O, ~- \& x        if( exsound_select & 0x08 ) {* d  x+ ^3 O: C
                if( addr >= 0x5000 && addr <= 0x5015 ) {: E; _) b& }3 L. M+ J1 R# a6 y/ ]
                        mmc5.SyncWrite( addr, data );
) N6 R' f: _+ N                }
; d* |2 I: l1 l- J6 @/ {  b) ~/ z* F        }
" L3 X+ g, s3 S) n! p# L  K}
* D( Q4 I. ?6 e1 _* C6 v; r8 C$ E$ w
  e/ B  D1 t6 j% _void        APU::Sync()+ _7 ~: n# j5 ^+ L$ M; i
{
* M) n/ ?# g* Z; V}
6 n. l" X, A; q& X- k2 c  U9 m0 [* W& Y5 d4 d1 s
void        APU::SyncDPCM( INT cycles )
/ U6 J& Y2 l5 |$ e& F{
" g# P* s  p9 y8 k1 n7 O$ `        internal.Sync( cycles );  m7 R1 l2 e! p
" b) j5 \. R1 C+ d6 x
        if( exsound_select & 0x04 ) {2 S/ Q9 m; T3 P% @  A; J
                fds.Sync( cycles );2 N7 h& o; E: j: v" Q# c* L' D
        }" S$ m* l% v5 z0 b
        if( exsound_select & 0x08 ) {
/ a( [" N& z4 m                mmc5.Sync( cycles );
) U' Y. i$ R6 E, Z' o        }
$ m( V# ?2 C' g3 ?' C& Y}6 V; O4 m- b% ]. v
$ j; V7 K4 e/ d" \4 ?) d
void        APU::WriteProcess( WORD addr, BYTE data )) @8 q( W! t! Q3 [" @
{0 Y- U7 y9 e, J+ L3 V! D
        // $4018偼VirtuaNES屌桳億乕僩& N3 Q% }8 @  ^, U
        if( addr >= 0x4000 && addr <= 0x401F ) {
( S# z0 p1 X5 K3 x4 F' F                internal.Write( addr, data );
: Z; A2 y0 H. ]* v; E  Z        }3 Z% B1 n1 b& c2 A
}9 l- F+ u, g% _% |  G( g

+ S# j6 r9 M/ K' P: y* ]void        APU::WriteExProcess( WORD addr, BYTE data )
  p. u+ `$ t" G2 O{4 H& S& Q; ]. f8 X
        if( exsound_select & 0x01 ) {
% J) N' h) ?6 b* I8 g6 l, x0 V/ S                vrc6.Write( addr, data );
1 x9 m8 d0 C/ U8 `        }! ]5 \: K- p+ L: b
        if( exsound_select & 0x02 ) {. ^& b8 Q) _( s
                vrc7.Write( addr, data );* b% b" V) \' ~: T; x3 [
        }7 ]# X/ _2 L/ s0 l
        if( exsound_select & 0x04 ) {
. O6 z1 _1 N  c6 ~* }& `  y3 F7 X                fds.Write( addr, data );
) k' x) B: f. D, @5 H9 j+ ]        }: c0 m& {* k* e( ?" n, `5 Q
        if( exsound_select & 0x08 ) {
' m& p$ d- |4 z                mmc5.Write( addr, data );
0 d0 @" F: u9 [        }+ w; h) `5 ?6 ]' B/ p
        if( exsound_select & 0x10 ) {& e% k8 t5 B# |
                if( addr == 0x0000 ) {
& d+ l0 W( g' Y4 U1 g8 L                        BYTE        dummy = n106.Read( addr );
2 {8 L- W/ R& u* q7 S4 H                } else {; S- _) _4 P0 a/ z% [/ Y$ l
                        n106.Write( addr, data );7 [& x/ w( h$ E& W- a# l  ?4 r# L' k
                }, z! Z' Y' l4 @
        }
4 R$ }1 z/ _( ?# v6 ^6 U        if( exsound_select & 0x20 ) {
/ d. m- x5 E% R& [  ]! q& b. v' P4 ^                fme7.Write( addr, data );8 @1 ~4 b6 V. m; \
        }2 s$ f: |* c) [7 }0 N: \
}- G* p, l5 I8 _* @, J2 o5 ]
/ W. _5 Z9 w) P
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )& c1 s6 R4 o$ ~2 ^6 ?5 q% v
{
5 g) g, X5 j7 b3 HINT        nBits = Config.sound.nBits;
7 X  \; M, {4 A' {0 `" j- yDWORD        dwLength = dwSize / (nBits/8);& d3 ~3 |! f, J! @
INT        output;
: k# X( U( X2 _' w' i3 i0 K% uQUEUEDATA q;0 y) F3 e4 K3 B# J$ x  v
DWORD        writetime;
9 }4 V  t$ ?7 m" j# W# s
+ E3 _6 t  f, s$ KLPSHORT        pSoundBuf = m_SoundBuffer;
. d1 A' @1 y- N; g; h- S: bINT        nCcount = 0;7 s3 u/ C! I* j" F9 b/ n  N9 J

1 Q5 f& ~. C9 A. A, ?INT        nFilterType = Config.sound.nFilterType;
2 X1 K2 s! q3 F0 Z
, B, r4 i8 V7 }7 b1 o        if( !Config.sound.bEnable ) {
. k3 p) J1 L, w& C: S                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 O$ C( w) W8 r# }/ r
                return;. w0 ?* N4 C8 \( q) P  [6 f/ h5 }- s
        }1 g* W) @! k/ {3 h3 `8 D, `
( f( H1 Y/ @1 U# O4 \1 z( J7 {
        // Volume setup1 `) {: d4 r; K( Z3 z" {6 H
        //  0:Master
$ K* e& b( i. R: k% J. V        //  1:Rectangle 10 ?0 g  |& y- {4 [
        //  2:Rectangle 2
2 y7 ~8 g( X  M! \! {1 ^% G% U        //  3:Triangle7 b% _/ G6 M# x/ C, g% o+ R( U
        //  4:Noise) G# ?* Z3 k2 J
        //  5:DPCM4 N: F3 e* D3 O) \/ z0 b" i
        //  6:VRC6
6 a8 k1 x5 E- u, y  W) T+ ~- q        //  7:VRC7
" e5 c- d  F' h& k& t        //  8:FDS
- }2 X/ V  @2 e/ Q        //  9:MMC5+ N5 O$ d/ c( e2 E. K  s
        // 10:N106
: a4 d& D+ M+ x* z! b7 [, L  E) a        // 11:FME7
9 n$ N4 ?9 O) u' A7 C        INT        vol[24];* n' m. }7 L2 {" x
        BOOL*        bMute = m_bMute;
) t8 F, a8 x  _        SHORT*        nVolume = Config.sound.nVolume;) n, L& X5 o8 x$ N
: r3 o0 @5 f& }
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; x6 f2 p2 V' ?7 h, A+ P

6 s5 h# f/ x# [        // Internal; d2 Z! u" D! |8 e, ~
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;+ l6 O, T- L( y2 r# B) |) r
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;1 m7 D6 G: p+ x8 S
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, D' v- @/ d3 ^/ h( ]7 M3 G        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
$ H  J/ l" \6 r- k        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
+ ~* n4 m  G( t( u. a" q5 `) E* _" |8 N/ _/ {' B7 K
        // VRC6# L& C  K* Q# ?4 J1 L" q
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 o# i0 c2 p* g9 @- ?
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" k/ f. U; S  v" K        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 l- Q9 U3 t0 q, b& X2 d
+ c5 _$ s, V" l) D" V7 L
        // VRC7. h& v. H, }6 X6 y- a
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. w- w9 A5 A% ^+ h# I

  q2 |& H$ f) M% q4 I3 m        // FDS$ J# y% n5 Y1 _: Y% K& g
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
7 b+ i4 R% X) b7 ~% s6 B, ~2 Y3 S3 Y) _2 q) d( {3 D
        // MMC5
. d, a% \' g* a, C8 ?        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 ~( v  \* w- T2 @' V        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& L$ f+ b, C+ i# t$ N/ X6 O        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* G+ d% g! T+ }3 s+ R$ U
4 J) \6 I) y, L' E0 Q" K        // N106
$ x$ m4 \" y# [5 P. S9 c        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) D6 @2 L2 p) J  z3 l# N
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 X* ?8 W5 ?$ D1 J+ y        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 r2 L; @# X9 V2 b8 X: I
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 Z$ O& l( Q6 n0 N! M        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( p- R8 v4 H) l: R
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 G. y2 d4 I6 @: i5 ~5 u" q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- E" E  M2 _7 q2 o5 F
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# s: R4 I* k; s9 ~" V8 s7 v  G' e( A
        // FME7
3 K1 H% x6 n2 H$ H        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 l, d6 t, S0 A, N
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  j7 F# U9 ?' m+ h; j+ Z; A        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! I/ m; C% u" F% i, \

- [5 A0 c9 N! T9 V9 f) f; g, x- |//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" l; F+ j# o; t) J, i7 V5 b
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;& ], H8 @/ O9 e7 r9 U8 D

. O3 U  W, o8 M        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' W& V0 s  S9 [. @1 m7 @( O        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 w& a6 X0 u: L9 T# O                QueueFlush();8 `+ B8 |& V/ Q/ d9 O+ r9 \6 ^4 y. f
        }
& A/ d7 m. K4 N
- H# S. O: @% S7 K' _) _        while( dwLength-- ) {
4 r$ Z7 k0 U5 G- a                writetime = (DWORD)elapsed_time;; Y0 j3 X5 W5 O/ q" p- p; g
7 k6 K- O$ j$ K& _
                while( GetQueue( writetime, q ) ) {! n, w8 T" |2 e8 ]/ D
                        WriteProcess( q.addr, q.data );
, x) A$ b! U1 ~6 H8 T# c. ?. ~# d8 ?                }6 H; ]. P0 g! u. s* r! `

: f/ u4 c* i# n" |7 x9 Y5 }7 D) g                while( GetExQueue( writetime, q ) ) {
% c& {! s8 ~" X7 W1 E, H                        WriteExProcess( q.addr, q.data );( U" U# r9 ~/ j' |1 R
                }$ X' Q  r/ s0 Q+ F% ?$ p$ o

3 K' W- E8 E! O# f                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 B7 z1 u- M' O
                output = 0;( ]& p4 O) V7 K( k8 `! {+ Y
                output += internal.Process( 0 )*vol[0];7 z0 T# {& d" M9 e
                output += internal.Process( 1 )*vol[1];
( Y; [+ H2 k& u4 ]                output += internal.Process( 2 )*vol[2];
+ O% S1 e: q! @- T4 c                output += internal.Process( 3 )*vol[3];% L0 e. ~1 |3 d
                output += internal.Process( 4 )*vol[4];
; E" u9 j' F0 U3 e) L" O
. q* ^6 T' m" Q) [1 O" N                if( exsound_select & 0x01 ) {, v- T5 u% f$ O; ?2 s
                        output += vrc6.Process( 0 )*vol[5];6 V0 O: E; R9 N
                        output += vrc6.Process( 1 )*vol[6];
- J% m3 V4 L0 [) _" e                        output += vrc6.Process( 2 )*vol[7];$ G% ^6 d; e" z3 q" R1 y- T
                }
4 y) d1 F& v% |7 o5 h' T1 l                if( exsound_select & 0x02 ) {5 ~8 ?- _, b4 W  p5 s
                        output += vrc7.Process( 0 )*vol[8];
! G5 M; M/ ]7 v( f& ^                }
3 X0 o3 z6 R5 U% l0 e8 o4 S6 T                if( exsound_select & 0x04 ) {) t5 V4 `% f' {4 Z' ~, ~' p% U0 V6 l
                        output += fds.Process( 0 )*vol[9];
$ [( e# N' n1 C                }' z4 I3 h8 T5 ~3 I  v# g
                if( exsound_select & 0x08 ) {* c0 ^3 d: v1 A' i+ K" H6 e
                        output += mmc5.Process( 0 )*vol[10];
0 n" n6 s# d0 W9 i                        output += mmc5.Process( 1 )*vol[11];
$ d9 Q& _% X9 U: n1 r                        output += mmc5.Process( 2 )*vol[12];7 H% o9 `! C# \0 V+ r
                }- d6 r9 z  \' Q  s4 n5 b
                if( exsound_select & 0x10 ) {
5 b9 ?! r, o0 L1 Y                        output += n106.Process( 0 )*vol[13];- \7 X- W/ M" y' E6 o
                        output += n106.Process( 1 )*vol[14];
4 c- F9 ]9 W1 b8 k+ O# K1 O                        output += n106.Process( 2 )*vol[15];
, r% [( Z  J6 P- T, w* E                        output += n106.Process( 3 )*vol[16];
8 v5 s" \2 d3 i7 h2 x                        output += n106.Process( 4 )*vol[17];2 j, y6 Q! c3 r4 \5 P" N, f
                        output += n106.Process( 5 )*vol[18];
0 C/ w1 L  i  ?2 a                        output += n106.Process( 6 )*vol[19];
- {, x5 S: r- p- E! z! u0 n% f                        output += n106.Process( 7 )*vol[20];
! X$ L7 \7 [) M/ z                }
) v; I' k* d0 \& u& {" h3 v                if( exsound_select & 0x20 ) {! l' j3 V* }1 q( w
                        fme7.Process( 3 );        // Envelope & Noise
5 o1 d0 b- H2 q1 H4 p                        output += fme7.Process( 0 )*vol[21];
( G  h2 _' W+ y9 O% D7 h; `                        output += fme7.Process( 1 )*vol[22];' u% m5 S: ~7 @  x
                        output += fme7.Process( 2 )*vol[23];4 z" `5 ~$ Z& _  g% `+ X" ~5 j
                }3 ]& G+ }: D% n3 {& l' T2 f

- @5 f* g# F. X- M  l+ w1 {+ z                output >>= 8;; Q/ g, G" ]7 x9 {6 N$ A
( ]4 {' @6 F) h" s$ X( Q
                if( nFilterType == 1 ) {
8 \# C  H) P1 L) e; R                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
" C  t  h: f! `, F                        output = (lowpass_filter[0]+output)/2;
  c& R/ y( c# H; x4 @                        lowpass_filter[0] = output;/ E# j/ _0 A2 y- R" m+ @+ {
                } else if( nFilterType == 2 ) {
* n  X% v* @; z3 [. I                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)% `7 i$ v: H- f" b1 `. Z2 }3 s, }5 x
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- E0 C+ p6 f* b7 C, _                        lowpass_filter[1] = lowpass_filter[0];
& g& g' H4 W# |' \7 G                        lowpass_filter[0] = output;! o+ V# _  F5 Q8 t6 m6 @+ Y. |
                } else if( nFilterType == 3 ) {; q1 \, Y* r' m; D) K: c5 J' J
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)+ p) G7 ?( H. V1 t) \
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
% `: U$ W4 S, b                        lowpass_filter[2] = lowpass_filter[1];6 B+ F9 Y( f- V: ]1 n- C9 a( M
                        lowpass_filter[1] = lowpass_filter[0];/ j  T+ C6 f! t4 g7 I2 {) v
                        lowpass_filter[0] = output;" }. v& z$ X- i. Z6 o) o
                } else if( nFilterType == 4 ) {
. K; l/ H6 b  j/ a                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)( ^8 k% {- ^" |7 e3 h
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 A7 g2 ~6 \4 V3 g1 a                        lowpass_filter[1] = lowpass_filter[0];% @' d. Y1 b8 F" }& I& R
                        lowpass_filter[0] = output;
$ v6 b# D' i8 s0 y* t0 l                }8 v& y9 |) R5 p) P- |7 x5 K1 Z5 d

7 W! ]# N) {7 w# h#if        0+ i8 T/ X* x# H, z$ \7 m  J
                // DC惉暘偺僇僢僩
# F* {4 p( `- N" }( c                {
. k7 S2 O$ \+ g; S                static double ave = 0.0, max=0.0, min=0.0;
; H3 g; w1 z! [$ R. Q7 `                double delta;" o6 o: W5 i5 e0 `) }4 Q+ d) k+ l/ n
                delta = (max-min)/32768.0;8 a5 M5 q& p& _$ q" ?8 w
                max -= delta;  s1 U9 c: a- i9 N4 W! E  K3 `& J
                min += delta;
+ G& H/ N( `' G9 O: @                if( output > max ) max = output;
( p  e/ U6 [, y0 n                if( output < min ) min = output;
5 @2 Y! D% [. e0 W$ Z                ave -= ave/1024.0;/ ^2 o4 G* c6 |
                ave += (max+min)/2048.0;
  K9 I  k2 S. Q2 q! k9 o                output -= (INT)ave;. u/ A7 M& M& `" x8 o1 s" o
                }
3 S6 V5 C, u3 S" t! }#endif( C& b; g3 I; {: n
#if        1! b$ S' j; |$ a6 ^* a# G
                // DC惉暘偺僇僢僩(HPF TEST)
5 e0 W# k7 N$ a. G4 H/ N9 A' N7 k' @7 F                {% F8 [3 Y% N2 Y- Z  z9 K, o2 z5 Q
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
7 e( ]% C  W: K$ x- [4 w* c                static        double        cutofftemp = (2.0*3.141592653579*40.0);
+ t9 l9 X; I4 Z3 _5 f6 [1 W                double        cutoff = cutofftemp/(double)Config.sound.nRate;
) L" O  \" v- D8 U7 w                static        double        tmp = 0.0;* ?" ?) g" w+ M- S
                double        in, out;# w, C% c0 g7 A$ u* G% n* ?5 `; i" u

) B$ w' q2 d" S/ C( V1 q                in = (double)output;  N- h6 Z$ V# o/ w6 U
                out = (in - tmp);2 B- a1 W; y8 t, W7 _0 Q7 z$ l9 p3 z
                tmp = tmp + cutoff * out;" S# }% n& w' O1 X1 G4 @. }
+ c2 S* V' J- o
                output = (INT)out;
5 n( Z- {# Y9 j                }
! t& ]' j; V' J, E#endif# l0 c+ K( F7 R$ H5 C9 L
#if        0
0 |- S! P1 K0 v2 i/ N; o                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
# @- K# e! c% X' x9 @3 K                {
7 j3 w8 r: E) Z                INT        diff = abs(output-last_data);
+ a! p/ E3 n8 ?9 E+ p                if( diff > 0x4000 ) {3 O+ H. ~% F0 j9 H: j2 r, |
                        output /= 4;1 X9 W$ }$ M# C5 a0 E1 o7 [" g
                } else
% f$ @& o8 A2 E/ p, R4 C4 ~# [                if( diff > 0x3000 ) {
5 I3 ^1 ]- Y2 t. O2 B. T                        output /= 3;
. N: y: C! {- b; M                } else1 R9 f4 J4 |% |7 }' }. E4 E; a
                if( diff > 0x2000 ) {
# O' O+ x, x& X4 Q# l& D                        output /= 2;
! a! x. s9 D% G" ?+ Q) y                }
( f$ b( q- B  F4 n" V* o3 ^                last_data = output;+ O9 l1 `4 B6 `4 I9 ]7 I
                }% j% T1 f/ j- B
#endif
/ x0 S* k( R6 A3 a( r$ D                // Limit. u( f. U3 y0 t7 M
                if( output > 0x7FFF ) {
0 g' a2 E8 Y) N4 M- a. ^                        output = 0x7FFF;
! R) v! u3 h* l: @                } else if( output < -0x8000 ) {; _; e4 Z- j% D0 R/ ]" e
                        output = -0x8000;+ e# p, T+ R1 x0 [0 o
                }
  Q2 @9 z, J$ D( p1 J$ O/ {
/ ~! G% ^$ b: ~' r                if( nBits != 8 ) {" _: s6 U% D- f1 f& b- @# U
                        *(SHORT*)lpBuffer = (SHORT)output;
! F$ v' t5 f; ]9 c1 d# Z$ c1 s                        lpBuffer += sizeof(SHORT);
" ^! i' M: N7 w6 m: K: M' q) `                } else {3 ]) C& ]2 A9 j0 C* L+ y; E' R
                        *lpBuffer++ = (output>>8)^0x80;. J& h3 b8 j$ J3 ?
                }% b8 w" i  H: G1 M  J! V! x: P, D

; c- d* y' c2 y+ b3 `( c) A; }                if( nCcount < 0x0100 )6 w4 k8 Q* Q9 U/ Z& d% N
                        pSoundBuf[nCcount++] = (SHORT)output;5 K  Q# T( U/ f- F: d" G
% _" I: e$ a# Y# d5 [, x3 @
//                elapsedtime += cycle_rate;- _, w: c7 Y+ o& `! E. ~
                elapsed_time += cycle_rate;
2 c% K" N2 O& Y4 F$ k9 n: x        }, {: \) x+ v; n

. t2 Y% C9 h3 O0 ^0 v/ o#if        18 d0 q6 y( `$ j' _6 @+ L2 p3 L
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
8 ~  ]1 P+ d: k                elapsed_time = nes->cpu->GetTotalCycles();- w& L2 t2 A$ U# _/ B
        }
6 f; ]$ q6 g- i8 Q        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {" V6 O0 L; X8 a: V; K" ?( E
                elapsed_time = nes->cpu->GetTotalCycles();7 M9 _' P/ T4 v3 }1 M
        }
7 F2 f/ ^. A7 x  h; i: U! K3 @#else
( u" Q8 E) J7 ]- k  q2 p' |# `7 H8 m: n5 C        elapsed_time = nes->cpu->GetTotalCycles();
6 N; i; N3 K9 ]/ O#endif
8 U! u8 r" _0 H}
5 M# {9 f9 H+ g; U+ ~* [) P. I0 c4 D% g4 Z* B0 p2 E5 i
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)% E$ D) Z7 |) K* j
INT        APU::GetChannelFrequency( INT no )
$ B, ?( q. ?4 [. M{
- d5 ?4 V  o2 \        if( !m_bMute[0] )
7 k6 N: e, }' l' k- x' n                return        0;2 G' s4 P$ ]& O6 |5 g, O" h6 T
/ _+ U& C3 ^  R
        // Internal
7 O- |) ~# s5 o" z- P        if( no < 5 ) {! e! [: k0 a9 F3 H0 g7 d' y0 ~# ~! a
                return        m_bMute[no+1]?internal.GetFreq( no ):0;- b$ j1 p1 x7 b+ R
        }: m# G3 F! E" D% w/ d2 v9 K
        // VRC6
  ^0 K3 G2 O3 ]  w& w4 U  ]/ V        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
. |7 g/ ?2 \$ ~: j                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;: g  {+ S& u( U3 p! F: B/ }! q! }
        }
2 V/ A( d9 F# g& t" Z9 t5 A, I        // FDS" p1 r8 m, t3 {# A) Z& `
        if( (exsound_select & 0x04) && no == 0x300 ) {6 J6 e1 {" x1 h6 g! {5 Y3 K
                return        m_bMute[6]?fds.GetFreq( 0 ):0;, `, g" J! \1 j
        }
2 o# B5 f2 G& }1 R- `6 b, _        // MMC50 C, e. N+ \7 k3 u2 Z3 f: y! O4 K
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {$ M3 J: p5 J. I7 F$ l" ^$ w3 D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
, y5 P( X/ Q& c1 J9 C- |        }
# p7 m% k! x2 f- o) ?7 i7 T* V        // N106& v4 O6 k' s0 D3 V  T# u
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
! {8 D5 {) @: {8 c4 Z0 W( W, M8 `                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 s; M' _8 y& D0 h( R3 c5 u7 e& G        }9 B& B7 d* D  u
        // FME7) F& u( M& K4 O- _$ u
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* k* \1 w; |6 S3 t5 i, X  u( t' o/ W+ F
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
# |+ C$ Y) {* K- z' F9 F# O        }) k9 f: N/ `+ F" i, Y
        // VRC7/ }; I0 @! M9 ]
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
' t7 L2 ]: Y( E9 l                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;# O% e7 B+ Q* y8 A3 U
        }
, [! J) C/ j0 ]* y) D, ^        return        0;
& _2 P3 e" |! X- K0 `5 f* L2 v}
( o3 j- r; L$ K/ R
! {& S% O8 b. x* a// State Save/Load* w+ ]3 Y% \: Q$ |6 A" Q0 J# i
void        APU::SaveState( LPBYTE p )# z$ i6 [, Q8 W1 N3 M
{, ~9 U$ D- T* ]3 _- ^
#ifdef        _DEBUG& ~8 {- Q3 ^* f+ G, F
LPBYTE        pold = p;# e. u* f- |$ |! h' `
#endif
' d$ L! `: Y- h, K9 T6 {+ ^0 x" m% D' r
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
) {1 `0 k' A( B$ d7 ^        QueueFlush();
7 C0 Z7 S7 y8 F6 ~+ E, Q9 i. ]
& k; m9 Q% u  B        internal.SaveState( p );0 x. e8 g# {+ g# M1 `) Z+ a4 G
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. _: c3 q$ o( D. M$ s& \0 @! `) n, v1 x. l1 X9 g) N# F
        // VRC66 ?- U0 R" W3 |" S1 }. J
        if( exsound_select & 0x01 ) {  L& @5 V) [7 B
                vrc6.SaveState( p );
2 {3 t8 p0 k) I" e& H; t                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. Z2 _, b; `" w  Y5 s
        }& @" o) b8 m6 Z% h
        // VRC7 (not support), ^. p  n( s) }: ]) B  M; V
        if( exsound_select & 0x02 ) {
" R' v! z% a/ g  e0 [- p                vrc7.SaveState( p );
$ v8 ~" j' @! U                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 g  l9 b9 Y0 ^' O1 |
        }3 i% I3 ~9 X& E+ R
        // FDS4 |- ^6 M$ f" T, b' u4 x3 r
        if( exsound_select & 0x04 ) {
5 P" U* L- g. O2 m  y4 `7 v                fds.SaveState( p );
' d: Q9 E+ T0 h/ L: _- z: @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding) C# P  N6 z8 N* E( s
        }
9 {( a! L/ U. f3 \7 g! G        // MMC5& y  {1 A7 c5 V& G
        if( exsound_select & 0x08 ) {) b: E4 P! g" I! m' l& j2 q, z
                mmc5.SaveState( p );- q) O6 i" v, T8 J6 Y
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding! P  r: w: N; x+ C0 x& U% {
        }9 L9 q" o% ^- y; ?9 T3 e" f
        // N106
) }3 X' B" ?- ]. a4 ?' o        if( exsound_select & 0x10 ) {4 X3 p6 i2 M5 a$ _$ v! Z5 x- [$ d' w* f
                n106.SaveState( p );
1 Y( n; Z- m, s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& H1 C7 o) X. D
        }# h' c" {9 j8 F+ G2 T* U- n
        // FME7
4 H" c* I3 M) e% m        if( exsound_select & 0x20 ) {9 z% x( {! S0 E' F5 h3 h! j
                fme7.SaveState( p );
3 {+ b4 G1 N0 Y' r  F% [3 H                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; s6 k+ ^, O" s" E
        }
" |% c" C2 K1 D) }: J% t' ~5 s6 U$ g) V
#ifdef        _DEBUG4 G! |% @' ^+ t5 X/ l* i
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );0 r# D% q3 G+ f5 L
#endif6 |( M* L1 b4 G
}
; ]: p6 A" ~% R4 e; e1 h& U
' Y. h( y" ]! k) ?8 q+ |0 hvoid        APU::LoadState( LPBYTE p ); h$ N6 v2 B* j7 o$ t; G) S2 f( M7 M9 a
{2 L) R$ Q# W. |0 \% d' f
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡9 K  l8 Y0 B! Y
        QueueClear();, Q9 ?* Z$ U7 l

( D4 T; b0 v  y        internal.LoadState( p );
% L4 }# [  k6 V9 e- y7 o3 H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  @/ [8 H& ^7 ]% N4 i; |( V" S' {# V" B* \; b  x
        // VRC6. l& \: `" @' y0 o3 K6 T
        if( exsound_select & 0x01 ) {
, q6 `' {( F! l, I                vrc6.LoadState( p );" f+ p& N( F7 W9 J$ D: }
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) L0 w( M% A  W% R
        }( k$ z+ f* ~3 V  A2 B
        // VRC7 (not support)
4 Z% p2 {' A' u7 T2 \        if( exsound_select & 0x02 ) {. h2 J8 D/ o2 }% P$ r: F
                vrc7.LoadState( p );2 q) f2 G0 |8 Z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 v1 q  F; o; C- R
        }8 W6 F; s2 X6 u3 N) R
        // FDS
' L5 b$ J; o$ e* `4 s0 {  O        if( exsound_select & 0x04 ) {
9 g8 \$ _1 G3 K+ [9 ]                fds.LoadState( p );2 M% o4 E8 f9 L0 O8 z' M
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# e0 _/ \, S- W7 V$ i9 L1 F
        }
- P8 z* U% U, R" Y, A        // MMC5
: q( Z9 k: P  {! n; B        if( exsound_select & 0x08 ) {
- H1 p0 r% v* p1 t9 ]) p. e) K                mmc5.LoadState( p );2 `0 n) ?/ b: w* P) |" z* U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 V7 w  M0 s0 Q  o- G
        }/ s- z/ K- _1 v2 u
        // N106# s! J/ Z, m7 [- ^* T. ~7 H
        if( exsound_select & 0x10 ) {1 D, S* `+ a0 Y! k
                n106.LoadState( p );! D3 l  x. C2 t5 U5 B  o  ]
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 k6 ]- }" [/ R9 z  G& p6 z
        }9 \# |3 j" ?# _4 c9 Q' K
        // FME75 q8 K3 P+ P1 x+ T
        if( exsound_select & 0x20 ) {8 X$ k' n* h! h: Q
                fme7.LoadState( p );5 h* s' n  t* d* h0 h) o+ Y  M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: w- W7 r5 O! S" A; Z        }% v% H, s6 a7 C- i) f" c" u& F
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
) c6 _# U4 j2 C可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# o! V7 r7 r& T$ S' l, G/ G$ A7 x
感激不尽~~

! a, i7 ^- A, W, }( P5 z2 k恩 我對模擬器不是很有研究,% e+ A, r* O7 D& `  H
雖然要了解源碼內容,可能不是很困難,! ?( x8 C1 t/ O' {) t; ?
不過還是要花時間,個人目前蠻忙碌的。4 ?: f: j) \1 U8 n. Z5 u. U+ ^

! m# W5 \, H0 N- x" k, Y" F# d8 Y* \給你一個朋友的MSN,你可以跟他討論看看,8 |7 i& Y( P, Z/ C& N$ _+ Q
他本身是程式設計師,也對FC模擬器很有興趣。4 O6 t, j( _; u$ C: g6 i6 Z& A
* }: P; V$ W5 ~: m4 I
MSN我就PM到你的信箱了。
7 ?* Z9 @* L4 N  `  r4 l4 B' E) W6 C% v* I/ n: }1 H# i+ }
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " G* a& X# O1 C4 |* ]# [2 d4 \6 _
呵…… 谢过团长大人~~
# T$ {" E0 M- N6 w" m
2 X: g9 t+ ?8 u% v
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表   R7 ]1 T3 g" i0 g
团长的朋友都是神,那团长就是神的boss。
! S- p2 t  u  e! k' Y8 e, g4 b2 ^
哈 不敢當,我只是個平凡人,5 D% V% u* o$ F( M. p
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# K8 W6 g: Y" K* s  F
ZYH& r5 n2 _9 Q+ P$ l
QQ:4147343066 K% J& J3 D1 a! Z( S) x# y" h
Mail:zyh-01@126.com4 ^; R% U1 }8 }: R9 h

1 D7 ^1 ^( J. B/ N他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ' S% @" \& a8 R, F
再次对团长大人和悠悠哥的无私帮助表示感谢~~

7 C8 b) N2 S, t' J& t7 _# c不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-10 11:39 , Processed in 1.132812 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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