EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# U9 R; c' Q/ z9 u6 W/ f
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( {" `( |$ V; z
这里有相应的模拟器源码,就当送给大侠了~~
* `1 L" T! Z9 H# B, |; s) Bhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # I% Q+ X/ o. @! I
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 f, q" v; z3 B) x- q/ e
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~6 B% ~& h  I3 P. Z
这里有相应的模拟器源码,就当送给大侠 ...
( e+ }7 D! F. Y) J/ a
聲音部分(Audoi Process Unit = APU):
; T' v  ?4 [8 O5 g% O" I! d! `.\NES\APU.cpp" ^4 }/ v' f- `9 x4 N; E" M
.\NES\APU.h( z6 I* `+ W  p# v1 ]6 G

+ A2 p( C8 |# B2 I. O% i7 D1 j9 J* F
影像處理部份(Picture Processing Unit = PPU):
" e7 t) Y3 Y5 Y5 u: [2 G1 \8 O.\NES\PPU.cpp2 y6 Y, G: d7 P. A- j2 q
.\NES\PPU.h7 E6 _! ?" g3 M6 E
3 B# E3 B: q( S6 I
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& t4 Y/ n8 e& f( a
(由于很多专用术语和算法机理都不明白,所以看不大懂……)4 h5 q* J1 f' S9 o+ j6 b
//////////////////////////////////////////////////////////////////////////
" s" t( e+ y. C/ L* {//                                                                      //8 i5 y; t( L$ x! J% j% H) D3 j) I
//      NES APU core                                                    //
1 c" t4 W3 |* t; `, B* a3 b7 U, U//                                                           Norix      //
6 ]' s: `9 Q* g; _# m8 W5 s//                                               written     2002/06/27 //- ^* c: }) P1 u4 e5 r
//                                               last modify ----/--/-- //
2 z$ {; i0 i  V3 V0 P9 _( f* e- v+ S% C//////////////////////////////////////////////////////////////////////////
' t/ N/ F& D3 x$ q/ q#include "DebugOut.h"
4 m5 m' c% r0 `4 B/ k#include "App.h"
, U% q; P$ \4 [+ ~* T#include "Config.h"1 H% ]" D+ s- C/ w  @& j8 \# U
5 H9 t' [. I$ Y. t8 X" U
#include "nes.h"3 L: [( h7 ^5 U* u
#include "mmu.h"
; }8 k! A( n/ F$ b5 z& s#include "cpu.h"( X: d$ K! D( I. ]5 Z" a  u
#include "ppu.h"
; N  e% O6 Z6 X#include "rom.h"" p& K- d: `5 S! o
#include "apu.h"/ `& M0 m# {9 x+ R% Q
7 ]6 H8 g' z. `. F
// Volume adjust
0 h- x7 d0 @  j& x// Internal sounds. i) J( o6 e/ T; K& x2 V
#define        RECTANGLE_VOL        (0x0F0)0 [6 Q: {/ V' |. J
#define        TRIANGLE_VOL        (0x130)
/ N2 x3 j  ^' F! t; O#define        NOISE_VOL        (0x0C0)3 k" e! h# j" V& u4 w8 Z- x% p
#define        DPCM_VOL        (0x0F0)" t/ H1 o! b+ O
// Extra sounds
2 a, J% F$ R5 Q  C3 }#define        VRC6_VOL        (0x0F0)7 ?1 m) B/ A- B6 a6 b
#define        VRC7_VOL        (0x130)" Y- j  b: `6 E
#define        FDS_VOL                (0x0F0)
$ k1 a% U' C, @#define        MMC5_VOL        (0x0F0)& ]5 D/ N* p$ {8 H5 B3 z
#define        N106_VOL        (0x088)* F# j& |) U. t
#define        FME7_VOL        (0x130)
, X$ w9 J: ?8 [6 n' b7 K5 k
! I- h5 e( }, }& B/ rAPU::APU( NES* parent )
* M9 z  \4 O* D& X- P{5 {% k* U' J2 p: \8 a: `, I& p
        exsound_select = 0;
8 z6 T; p1 n1 u* I4 a! R6 H- b
7 y2 r% ~# I  c        nes = parent;6 Y( G9 Y! i# U
        internal.SetParent( parent );6 \' W3 T( j% B) A1 M9 I
5 a! ^0 M# S2 P+ D$ S1 L
        last_data = last_diff = 0;" H- G# R, A  R/ D" r! S* W3 S
8 D" _+ e3 u% T" Z7 l! P* |9 g
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
9 p& F  [, j1 [( L& ?8 @: ?5 I
7 f  V, f4 H1 W4 j0 R6 w7 U" k        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 v9 e/ o$ T6 k& A+ H7 N        ZEROMEMORY( &queue, sizeof(queue) );
3 n9 @1 D( V0 z, A        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( g4 @4 g: Z% ^/ {- z+ x8 ]! B% d1 a  [- a7 u2 E' S
        for( INT i = 0; i < 16; i++ ) {
) T( [- _. A1 c' ]8 I. R                m_bMute = TRUE;
5 u$ B: S8 D& A- O        }7 y- M5 a  U4 Z3 n4 [+ [
}
/ k2 @% l7 h" r: [/ m, C2 _+ h5 y$ X
APU::~APU()7 d$ Z2 y0 N, S! p. {7 i
{
4 g: ^( C' y- \* v9 |, K+ e  H}
# q: I) o; E0 I/ s" ^* {' d& e/ L) I' W5 T3 V9 V; p) U8 K% }
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
$ r8 f( O) q% y7 d' J{! P% I( x+ Z! b" `1 q: d
        queue.data[queue.wrptr].time = writetime;; x6 d. ?) T0 [$ _# V
        queue.data[queue.wrptr].addr = addr;, K8 F( V6 d' X" Y, o4 c& u$ _- Y. |
        queue.data[queue.wrptr].data = data;
. R# z0 S* x4 c1 C1 A8 ]/ i        queue.wrptr++;8 Q( }9 o( G' a' M# }8 U
        queue.wrptr&=QUEUE_LENGTH-1;
) I3 J9 ?  J9 X        if( queue.wrptr == queue.rdptr ) {
4 M! j- f5 H* p' A- R/ z                DEBUGOUT( "queue overflow.\n" );; i1 D4 @; a! I8 o) S
        }
5 j7 \0 X. G: z7 H- b- ^+ ^' i$ i}, U  @+ w3 R  v8 }; {

4 i0 _% D) d' W& `0 sBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 ~# J; ]/ o8 s4 N( d! T" J( }+ Y
{5 D4 \  {! o) S$ h' F7 ~
        if( queue.wrptr == queue.rdptr ) {
( `2 \, k$ c* F5 E+ P; P7 ]0 M                return        FALSE;
" i* R6 m8 M( l! h5 f4 a        }1 t: ~1 W$ ~9 ]
        if( queue.data[queue.rdptr].time <= writetime ) {5 l6 V' M5 a0 Y
                ret = queue.data[queue.rdptr];0 w9 f6 h( T) `. y. g+ j0 \
                queue.rdptr++;
1 s! x7 H. }3 c4 |2 k2 N: C                queue.rdptr&=QUEUE_LENGTH-1;5 z  W+ f4 l1 [# n8 i  c
                return        TRUE;# Q$ j4 A4 `9 V* D1 u- R" E) ~
        }
! i) @. Q* b6 G* K& f. i        return        FALSE;
: o# o  S0 S2 _* B) z! G}
/ a" e* y/ e: t9 ^
: \/ D) V& z) I& q9 Jvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
" a8 }7 F5 o3 T9 n6 Z9 ]{# w/ {' {7 ]6 j8 j1 \& h1 a9 L
        exqueue.data[exqueue.wrptr].time = writetime;
9 o3 p4 z$ W0 k& s5 E1 z& m        exqueue.data[exqueue.wrptr].addr = addr;4 b7 m0 B- j3 e; L! F2 Y5 B
        exqueue.data[exqueue.wrptr].data = data;
$ K$ n6 w( E: W- f  c  C8 ]3 ]        exqueue.wrptr++;
3 A1 k' |; X- F; g: k, _* I. x        exqueue.wrptr&=QUEUE_LENGTH-1;
" [4 D) ?' _/ y" o        if( exqueue.wrptr == exqueue.rdptr ) {
+ }3 S, u. C: T  E                DEBUGOUT( "exqueue overflow.\n" );0 N$ b/ N* @6 ^, c5 V* [
        }
8 W3 c7 h( E3 @3 x& x" f; I}
- L% a8 G- P* V% l6 k8 y4 r9 V, i0 d4 j3 C
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 Q* c' n( s+ Q
{) w' O+ ~, k. g$ h% Z9 M$ E+ y# ], }9 s
        if( exqueue.wrptr == exqueue.rdptr ) {/ K5 e( P! `. f! Z
                return        FALSE;( l3 Y8 _5 `* O  B( f% x9 d( z
        }) P  h3 n7 u9 d  I5 P6 d0 P
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
) U% g; T( ?1 ]% J% G# l" c                ret = exqueue.data[exqueue.rdptr];4 @7 L7 \2 E5 k$ i0 E
                exqueue.rdptr++;/ \# J) x6 d. G, T
                exqueue.rdptr&=QUEUE_LENGTH-1;9 t, I  B. c; T% ]3 X  u$ t/ K
                return        TRUE;
$ c# Z7 r1 a3 C, X- W1 C( q        }
+ e" B* Y- @5 U" H        return        FALSE;
2 v# o. ?9 P: G8 X$ D$ z}
# }( t5 T4 |* q# f( `* \$ m' E0 X% w+ b# y) y
void        APU::QueueClear()+ B8 v! h' G% L
{
: \9 C- Q; G2 b: z& s        ZEROMEMORY( &queue, sizeof(queue) );
/ e* r$ ?4 B0 x, `& P        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 o: a: r2 d2 D; K}
& p# E( q. h1 C  r1 h- c
# ?+ S; D6 H2 M6 r  e5 U# s. Xvoid        APU::QueueFlush()* `9 R8 V0 i' ]3 \) P9 ]
{
. ]: u/ F4 t# ^2 [) D* D        while( queue.wrptr != queue.rdptr ) {# N* J% O6 e) g* ?( ]8 ?8 {" k
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
0 V8 z% B% z' o                queue.rdptr++;
' Z( Z" @) H+ u( m# k. k  F& b                queue.rdptr&=QUEUE_LENGTH-1;$ I/ h' z# t- m
        }# R& J' y7 v2 [1 v  X! I
2 W7 J' u# v2 a
        while( exqueue.wrptr != exqueue.rdptr ) {- z+ T% ?* A' M' Q/ m# S+ B
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
+ s% }! T" s+ S9 I8 N                exqueue.rdptr++;1 B" {% x* g. [( L
                exqueue.rdptr&=QUEUE_LENGTH-1;7 \2 S  P# R' V% W) M
        }
+ e0 D, x5 s6 U8 S! T3 |( y}
/ Z  b# f2 Q: U& y- S! ]: e" X) F# C* }0 {4 ?
void        APU::SoundSetup()
- y/ Y+ P0 A1 o" L* J/ x# h{
6 P9 d& \  Y: ~& g! t- T8 ^7 s        FLOAT        fClock = nes->nescfg->CpuClock;
2 M2 ^$ ~0 w0 S4 C  R) a        INT        nRate = (INT)Config.sound.nRate;! P6 J" p% {; R, f
        internal.Setup( fClock, nRate );
7 C7 l" Y" j& a! c- x        vrc6.Setup( fClock, nRate );
4 M" k, Q. I8 ?2 [+ W& T' e        vrc7.Setup( fClock, nRate );% J6 q8 w2 [& I  L$ X3 C
        mmc5.Setup( fClock, nRate );* p+ X; L  M  `7 q
        fds.Setup ( fClock, nRate );
5 c! w; o1 j; w6 `5 I+ R- ^        n106.Setup( fClock, nRate );, `3 h4 x- _; {
        fme7.Setup( fClock, nRate );3 r  Z3 z( F1 u
}
3 ?+ O( k) O( ~. h* S5 @  x
0 Z8 q  S* Z& A/ @void        APU::Reset()' p! y+ j6 Q9 q$ B0 u' D+ g
{) n- j# ?5 Q5 U
        ZEROMEMORY( &queue, sizeof(queue) );
- d9 o$ @. Z; n$ r" @$ I1 W) X        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ X. ?" B7 D% S# v
* T7 _/ u5 x! z1 N  H# n
        elapsed_time = 0;
9 x, l2 ~3 |4 \) ~% d% x
; L0 c0 n& I" y; w) {  z        FLOAT        fClock = nes->nescfg->CpuClock;
3 S/ G9 f4 o4 E7 B4 z4 O$ [( J        INT        nRate = (INT)Config.sound.nRate;
+ t1 V  k& k: M6 G" d# d        internal.Reset( fClock, nRate );0 U9 l! y$ E% ~! ]" }
        vrc6.Reset( fClock, nRate );0 m, V# m' ]. L8 ?5 R& U
        vrc7.Reset( fClock, nRate );" W$ l! l9 f  Y
        mmc5.Reset( fClock, nRate );! g8 Q4 E* J+ `3 Z$ @# R2 {
        fds.Reset ( fClock, nRate );
6 z- ], b/ @! P        n106.Reset( fClock, nRate );8 G9 b4 h+ J- D8 d7 J' f2 K
        fme7.Reset( fClock, nRate );3 i5 L/ M) z! g1 k

6 B5 }! H, e" C! N- t6 U  g        SoundSetup();2 Y2 R. E! Q) j. L
}. b1 j( l$ p* W& l1 z& h

$ m+ o1 `: m) Q( v  \( @1 xvoid        APU::SelectExSound( BYTE data )+ J# b& p1 `* h
{/ z  k# s" ^5 Q5 h9 s2 B
        exsound_select = data;
  _: r" @2 W. ~. p}" S/ U# v; h8 @6 [0 e/ T2 \
8 l$ L6 J) o; f
BYTE        APU::Read( WORD addr )& V! _1 g: Y( d. B- X6 M/ k
{
/ Y! t' q* P1 @        return        internal.SyncRead( addr );
- r. B/ W- Y+ f2 \}
, I" ?& C7 j* I4 |! U1 J0 u. c( E. s3 ^+ u- Y. k) L+ N
void        APU::Write( WORD addr, BYTE data )' J- P! u2 |* d% F) f! P" t) k
{
- I2 P& Y2 p9 I2 G9 `; |8 _        // $4018偼VirtuaNES屌桳億乕僩# @: O& d; H& P; ?, N
        if( addr >= 0x4000 && addr <= 0x401F ) {3 E2 U6 t- E: \8 U6 X. N3 a/ n
                internal.SyncWrite( addr, data );
7 W8 v/ e0 L) O. l& j8 k8 F$ T                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
* k. G$ V/ D1 j$ A( J        }+ r/ j' t$ w- B; I. p9 W8 g
}
7 ^+ p! t, s* c5 \5 F: r' T! L6 _. N+ q) Z* x5 H
BYTE        APU::ExRead( WORD addr )$ @+ C% t4 O3 O( S" a' h; ?* S
{4 L4 Z# Z8 ~# D7 q9 q
BYTE        data = 0;
9 |& F9 B  [' V# m; s- b/ [- ]. V4 ?4 V
        if( exsound_select & 0x10 ) {
  k& F8 c* n3 R( |6 a                if( addr == 0x4800 ) {
# O4 P$ k1 U; p2 T% J6 c                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );  d) m+ x! `& ?3 A
                }
8 G, e; p; H9 _" i3 w  b5 |$ F- b        }
; N' r5 m3 I, p- K        if( exsound_select & 0x04 ) {/ w1 b8 A& a* g, w+ s
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 z  s( ^( Z- n; U; C" [                        data = fds.SyncRead( addr );3 w; e8 H3 ~- b% Z/ @  G: V/ ]
                }) Z! O/ ]* p/ F- P
        }  N  J6 r# ?" X5 l0 `. @5 N
        if( exsound_select & 0x08 ) {
, \& H* N% l. V1 x/ o2 h  V  H) B                if( addr >= 0x5000 && addr <= 0x5015 ) {
( i; d- I, Q7 \# F( ^5 h+ a$ ?6 b: [/ x                        data = mmc5.SyncRead( addr );
1 x0 [5 S+ X2 y8 [, L- q) C5 c6 s                }, E7 ~  ~& w0 U. B3 W
        }7 p- i2 U$ S  s/ V6 ~

( }- `. @! \  U, O9 e# X  T5 M5 O        return        data;& y" H" _6 t5 D0 C, r1 b
}
1 t7 ^+ K1 \' O
) {% s, I0 ?. T, G8 j/ tvoid        APU::ExWrite( WORD addr, BYTE data )
3 ?! B6 m+ @9 n+ I( }- S{
) ^- z" C- _2 ~% J+ R        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );6 I( I9 y# K3 k0 v$ l
. T9 x/ [/ J1 {: C6 P/ ~
        if( exsound_select & 0x04 ) {+ `8 w% m; c$ u9 y
                if( addr >= 0x4040 && addr < 0x4100 ) {
; P% r' u) C& B9 M: R: {                        fds.SyncWrite( addr, data );
6 q1 B5 s0 b* O6 t$ K3 ^  ]                }
& ^; R7 {+ J  X4 g# Q; z+ H9 l2 l        }/ ~( K! I" u  A/ A2 V7 a
) H) m& e# E/ r8 w) I3 A9 L
        if( exsound_select & 0x08 ) {
* s, ?) l$ o' B" o" b                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 J1 G# j6 Y4 x' Z                        mmc5.SyncWrite( addr, data );7 y: l+ \  W# |  U3 a( O
                }
2 [) u3 l/ h4 I% h! D        }
; Y6 g4 k6 M( Y) S+ l}; T! X/ G8 u/ V' u! x# `, k" @7 W
$ p+ u$ w: U. V/ {4 U1 [
void        APU::Sync(): C5 U" u- C# j) p3 x* x
{
9 K+ _. v8 v% ], r/ H9 V$ m) ]}8 `6 T( J" B6 s1 y* E' W7 w% y
1 h0 ]" e& x$ q6 _- ^
void        APU::SyncDPCM( INT cycles )- Z( E" ]6 q( k' N; z5 X, Q& [
{$ S/ @1 I3 @+ j1 D
        internal.Sync( cycles );
7 V) _( ~: N! T! L9 \( v# Q1 e
. [- R* }( c6 o1 p6 u- F' m        if( exsound_select & 0x04 ) {
9 ?$ ~. f/ z% t4 V- }) O8 H                fds.Sync( cycles );) u. S  \1 [) s( l. V; F5 E8 g: f) R
        }
1 G7 o: W+ S! K2 v* [& y& c0 n        if( exsound_select & 0x08 ) {
8 v: g5 ~% a, G) q$ ^. w                mmc5.Sync( cycles );$ r; j+ X7 L9 @( C1 `: D
        }2 m6 n! \! ?  }! i- L6 y; n
}
& e' i$ Y% [3 f/ |) E0 Z
9 A/ Z- l+ e0 _% rvoid        APU::WriteProcess( WORD addr, BYTE data )
5 n. ?# ]8 z5 \3 |{+ t6 s* x9 z" {' e% J! ~$ j3 q
        // $4018偼VirtuaNES屌桳億乕僩
. H; `/ s, w3 |        if( addr >= 0x4000 && addr <= 0x401F ) {* z* H7 o3 C. Y0 d
                internal.Write( addr, data );
) K1 C, d3 D3 V  i0 X        }" I6 K0 X: r" [! _1 M! U8 p+ l
}
: f& @4 J7 R% q6 e6 }6 q9 F+ N/ F7 }# P% X: K, _
void        APU::WriteExProcess( WORD addr, BYTE data )2 g3 X  L8 G: O- x& W# S; A
{
6 o" _/ O8 ^' ~3 {0 H2 e' o        if( exsound_select & 0x01 ) {# l, @5 n; N: e6 f, ^
                vrc6.Write( addr, data );
. Y- \# j/ d  I# I6 ^" s        }
; Q7 M1 f- N, K6 L* a9 r/ F- ?0 L1 p        if( exsound_select & 0x02 ) {
/ x+ X: C/ B7 `9 Z' s                vrc7.Write( addr, data );
/ h) |! h: W. s+ k$ |        }
0 n% s  n1 i; b) J8 d        if( exsound_select & 0x04 ) {. C2 q3 e* O8 P- ?2 F* [7 k! w+ M/ t3 f
                fds.Write( addr, data );
& A& q% Q  q$ B! ?7 z        }
9 P, Y" X/ r! v& ]        if( exsound_select & 0x08 ) {
: z! f2 v  s/ d, G" a/ A                mmc5.Write( addr, data );6 |+ a7 Q) `) F0 x
        }
' \2 @! g- S7 t$ ~8 J" l2 S        if( exsound_select & 0x10 ) {
1 P, I4 @9 O" O$ q# O2 R# I                if( addr == 0x0000 ) {: k) C5 n9 I/ P0 D
                        BYTE        dummy = n106.Read( addr );
% }# R6 J$ D, ]0 i/ i: @                } else {2 R/ I& H0 ]0 Y3 N
                        n106.Write( addr, data );  @4 Z# P, w6 ?& t8 `
                }
  R( ~- K0 g: X! e        }6 N# G1 ~4 I8 r( }, D" y
        if( exsound_select & 0x20 ) {. N/ h' F$ ?) K8 @/ L% a- |  |
                fme7.Write( addr, data );
# K! j) M9 o) S2 }        }- N* N3 C) S( H8 j3 ]! f
}, r) I& {6 m" b& @

9 q/ r1 q5 e. i5 _8 V6 ]! ~void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
3 U% T' s8 e4 r: r{3 S6 k: x. X9 \6 X% p. S% c% r" {
INT        nBits = Config.sound.nBits;
7 m0 H. C; B9 ~8 FDWORD        dwLength = dwSize / (nBits/8);
9 c5 k+ ?/ [$ [; T/ iINT        output;0 W0 s! ]" I: @
QUEUEDATA q;
5 R& [- y: ]" |6 |0 B' k" YDWORD        writetime;, S2 A- d; J6 U+ B6 T
8 z2 C) z3 r" L+ K! c) ]* y% U
LPSHORT        pSoundBuf = m_SoundBuffer;
! v* S7 u3 x6 z  E0 }9 Q  AINT        nCcount = 0;
. @; E$ j9 h' ~  Q) Q# O/ x5 R' g/ F  T! n
INT        nFilterType = Config.sound.nFilterType;
6 @; |3 R1 W- ?! e, R8 ^2 B# J/ p& B) n. E$ Y% \0 }
        if( !Config.sound.bEnable ) {$ q8 k! [7 d' Y0 n. u- p! u. r
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );, ?  m& ?7 m7 m4 K/ r
                return;! P1 I0 j/ R/ d1 ^& o' d
        }
' C6 t8 U5 `9 Y1 X& a; V$ Z6 v( g2 y
! k; a: y" i" M. v        // Volume setup* B+ B6 w/ \0 Y0 M6 ]
        //  0:Master
3 f: o4 Z) Q( h) v5 m" q6 N. \- D        //  1:Rectangle 1
  f8 E, j7 U5 V% D        //  2:Rectangle 29 ]' H0 U* O% R
        //  3:Triangle
% X& t4 y, Y" N        //  4:Noise
" N/ y9 G8 h. M  V* k        //  5:DPCM
7 t) h8 O- L7 j2 S7 e6 O4 M        //  6:VRC6
. j+ S1 u0 q" m: v6 u' {" s. v: m% N        //  7:VRC7
; F* _5 w$ E: @4 d2 c: n) N        //  8:FDS
" }, T0 C2 m- w6 N        //  9:MMC5
/ F# C1 [) ~) s! q        // 10:N106
( F9 ^: m: o/ i: m$ h        // 11:FME7
! Y/ p& V1 |- c        INT        vol[24];
8 U  N. A. g1 s7 x; w8 K, W) Y& t% g0 p        BOOL*        bMute = m_bMute;
7 s: e# Q) B+ y& u4 K4 Z        SHORT*        nVolume = Config.sound.nVolume;3 w  U0 c% n. W. f, }& I

7 M- p& {% j+ H5 l% b6 ^6 \        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 V: ?7 k% f: f3 v
; |7 [3 t/ ^5 C4 {) b9 ?7 A        // Internal6 y& O" b2 w( u9 H
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 b- q) G/ U2 }        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;1 `7 L# r2 V1 [
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;# L: R# ?* t( \) a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
0 _0 R5 V2 A. F6 G7 n. t        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
# X1 G' O- [0 J( ~* m& K( Y/ S( j0 j7 T4 O0 s  U
        // VRC6
- p" g% S5 ]) a; K3 {0 J        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 z' K; J: N% B- y# |+ R9 b- g
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" I6 E8 q" _9 e3 I
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: ~/ l. [/ f5 n

/ ^. W( z, d: ?- V/ k  n6 ~1 m        // VRC7
; Q( D* r  Y+ i0 H& }        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 |5 M- l0 h* H$ L# O" e+ U4 t  P! {0 M
+ s- c, u, S2 n7 i% d8 T        // FDS. C7 e. P8 R& @- Z# ]
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;( ?  r7 L, h& V+ ?! F

) A: C4 h" ]! `0 p' e% a# _& E( N        // MMC5
; F' @/ A3 L. l        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; Z/ G# y" ]7 y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# i$ B  n+ G; ]
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ \) y) y/ J' o. Y" _' {* ?2 @4 l/ C, ?8 u
        // N106
8 n; |6 a9 X- l6 p; R/ W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( A8 J6 a8 a+ U9 i+ |        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ v) H. x1 V/ s9 u1 u
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ T& z, f: Q) w- t; C( _6 `! v; `0 z        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- v2 A5 W  D) Q7 M; S) T$ U        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  L/ U3 }6 x5 d6 P5 J        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 j% A) `# E, g
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: u4 s8 c( E  A# n( U0 u
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  {1 ~' r0 i8 O1 K5 v/ H
* w, r. ~5 b, w7 u& o" |
        // FME7
" D. J$ X- ~5 m; Z8 S        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, _, m, I/ \& c# i7 I
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& V' @* z2 L8 T/ W  |& |' S' S
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ ]2 [7 ^& o+ A$ T. n" [0 @% f1 A1 u! B
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 Z+ \8 v1 \( E2 F1 M2 |3 p
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* P, e: R( w6 \5 U0 A) g' U$ [
: W! Q+ H: l/ Y1 ]5 N; E1 m/ J        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 ~$ [6 X- V$ M, j5 g7 ]        if( elapsed_time > nes->cpu->GetTotalCycles() ) {3 m. Q) s% M2 y* d7 S
                QueueFlush();3 K. `4 k5 |" M# l4 }& ]
        }
3 E3 e9 n( J5 \$ p' C7 W
7 J- s! c0 H+ i" i  P* y5 y        while( dwLength-- ) {
% B  r: V, Q/ G                writetime = (DWORD)elapsed_time;
( P" L. J: l4 t* i
" J1 y: V# Y1 x6 u! ]6 ]+ S                while( GetQueue( writetime, q ) ) {
+ E1 e8 Y0 j6 T& K* _2 A                        WriteProcess( q.addr, q.data );
. ]; X1 l: Q, c& |" }" Q                }' [7 J# p& u8 C' E7 a7 M* O$ ~
( d1 p3 `: K3 R# Y$ }
                while( GetExQueue( writetime, q ) ) {1 V4 C+ g% C+ u( J$ T
                        WriteExProcess( q.addr, q.data );
8 t6 Q: k# A% I  M$ W& ]* |                }+ }7 S& ], B+ E& L

! b& U) d5 m9 O                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
# W1 M; b& ?9 i4 M                output = 0;8 q# ~7 Z5 `6 Z6 g
                output += internal.Process( 0 )*vol[0];; G, {, w+ k2 b0 D' j$ t
                output += internal.Process( 1 )*vol[1];
" H9 i4 y( J: l! x                output += internal.Process( 2 )*vol[2];' @- \: T$ h5 m+ F; Q) Y( n
                output += internal.Process( 3 )*vol[3];
* f+ w+ f2 D( ^- o                output += internal.Process( 4 )*vol[4];
8 m4 g) m5 W0 \' Z; U0 w9 Z' n3 C: l+ t% h! F8 l( C2 G' S
                if( exsound_select & 0x01 ) {' Q7 ~+ J) E# \3 y' |2 B; e
                        output += vrc6.Process( 0 )*vol[5];
% i* F/ J! L' n" k! r                        output += vrc6.Process( 1 )*vol[6];, j0 N4 H( m+ |" t
                        output += vrc6.Process( 2 )*vol[7];- F0 S" _+ n% i0 M
                }& z. O" K* c6 S9 k
                if( exsound_select & 0x02 ) {. _# J0 w. P' X- }: C
                        output += vrc7.Process( 0 )*vol[8];
% B- @( f% N( Z                }" ]: Q! b- y# \0 I- u
                if( exsound_select & 0x04 ) {
7 ~! s9 ?) l, A) u9 Q1 V2 p                        output += fds.Process( 0 )*vol[9];
( b  O# ^5 B& t% D7 U: D                }. P7 F( B9 u. V$ L0 h
                if( exsound_select & 0x08 ) {! O* x; C9 ~$ B% f
                        output += mmc5.Process( 0 )*vol[10];0 G7 h! `: {6 [* W! n4 v4 s! I
                        output += mmc5.Process( 1 )*vol[11];+ p' e) ?/ e, K% H3 M2 C
                        output += mmc5.Process( 2 )*vol[12];
: W' V4 l/ ~9 i! F: C1 E                }& S: X" ?" K6 h) L" s% J
                if( exsound_select & 0x10 ) {
: f- \" u. h3 J                        output += n106.Process( 0 )*vol[13];- I! ^5 B& x. H) t! i4 ]! s5 J$ w
                        output += n106.Process( 1 )*vol[14];
' B4 _. Q  v* m& \# ]% ]" g                        output += n106.Process( 2 )*vol[15];+ Q5 x! T5 n& c8 q
                        output += n106.Process( 3 )*vol[16];5 Z% }) ^2 ^" l+ A" o1 S' \
                        output += n106.Process( 4 )*vol[17];
3 S9 k6 ]. x* ^                        output += n106.Process( 5 )*vol[18];
" Z8 f$ C- t, k( C3 ^: J/ n3 }                        output += n106.Process( 6 )*vol[19];
! a4 v% a' Z) E' s: Q  i# ]& O                        output += n106.Process( 7 )*vol[20];
/ K5 u* S( O4 m- _$ k                }3 h; F1 S  X- H8 y
                if( exsound_select & 0x20 ) {, s7 Z2 t: h8 _* J6 _
                        fme7.Process( 3 );        // Envelope & Noise! E0 F" [3 R& ^) d& Y- f. F7 p! N6 [
                        output += fme7.Process( 0 )*vol[21];- Z4 u& ?3 f, I! Y
                        output += fme7.Process( 1 )*vol[22];
+ \6 \* l6 u& A                        output += fme7.Process( 2 )*vol[23];! J: l1 ~9 `. F0 V: Q1 @
                }
0 @- X+ g- Q! a" o" F/ g2 c
7 x, Y- F) U0 S5 V, s5 ?% D                output >>= 8;. i) e' s3 U% c4 e. b1 h

0 z1 L8 P& B3 {- f) Y9 ~% B                if( nFilterType == 1 ) {
2 E/ j( ^9 m( {' u                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)/ D- [, y9 p: q8 j) Q
                        output = (lowpass_filter[0]+output)/2;
  u2 @6 s& Z5 Z                        lowpass_filter[0] = output;5 c% ~, N) }3 E$ p0 S# N3 H- z
                } else if( nFilterType == 2 ) {
' c& S; w% z/ m. P1 P/ ?+ y3 C                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 `% `9 E( N+ Q0 l5 k' O" P
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 s; u9 G% ?: n3 x                        lowpass_filter[1] = lowpass_filter[0];6 U" o, f% ?3 m8 X
                        lowpass_filter[0] = output;
3 P0 Z) F+ [8 f                } else if( nFilterType == 3 ) {
0 y- Y- t" C% @  G0 d- R/ b                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
! C) \% v8 \0 }; L9 G0 ?+ k/ F, H1 l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
9 f7 Z* d0 v5 ~- o                        lowpass_filter[2] = lowpass_filter[1];
3 O4 C; t5 R! a                        lowpass_filter[1] = lowpass_filter[0];$ o+ e% t8 l! O+ Q$ U: Y, u
                        lowpass_filter[0] = output;% h6 k- u9 P9 A8 `
                } else if( nFilterType == 4 ) {# J  l1 e5 k. l' W4 p# \
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
% l( A! y, N8 O. H                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ w/ ~: `& d7 |
                        lowpass_filter[1] = lowpass_filter[0];
  h1 B4 a, a9 ~& r2 g. H" ~  J3 G                        lowpass_filter[0] = output;
/ W3 k# L2 v6 Z2 p1 B                }
! n. q/ Q2 @7 m1 G% Q) V
, O5 \7 d0 |- X#if        06 h/ d; V0 @! `8 \& |' }2 O
                // DC惉暘偺僇僢僩
' R, H0 ^' ^/ n" |, C                {3 n, V+ t' ]" ]- |) e: d! G
                static double ave = 0.0, max=0.0, min=0.0;% P$ Z  ^* |1 _: R+ D3 T" B1 B
                double delta;4 L7 C9 R5 |* |( @. Y
                delta = (max-min)/32768.0;" ~  n) ~2 _: J2 S6 f' }
                max -= delta;3 E, e5 E3 {/ u# f
                min += delta;
# u) \4 t$ i7 C* M; Y) H/ W                if( output > max ) max = output;
  D3 N# S8 }  D( K: T  R8 R                if( output < min ) min = output;
5 C% O7 ]. X; P/ `0 |                ave -= ave/1024.0;' t/ A; R5 o% l5 T+ h
                ave += (max+min)/2048.0;
$ ], }0 P; I# V1 [                output -= (INT)ave;: Z2 }4 n! {- V
                }: l2 T1 M( e  T
#endif
, g# {8 c3 R. k0 H#if        1/ @! C1 M5 i0 F- f8 {
                // DC惉暘偺僇僢僩(HPF TEST)
$ l1 M# c% \3 m! J' D: I( ?- z+ s' ?                {3 X3 B! s! x1 F0 W
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
/ [2 ?; O# B  M$ I- i! ?, ]& m9 W' m. s                static        double        cutofftemp = (2.0*3.141592653579*40.0);7 r" X8 S: a/ M# `3 D
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
; j1 v" @6 m: z8 Z  j4 Q/ ~9 ~                static        double        tmp = 0.0;
5 O& s. d. _- v, f6 B6 A: ^                double        in, out;; A5 k. c# l2 e* E( B
& b& V8 [2 ~$ F5 q
                in = (double)output;; D. @1 R& B4 q# J* |5 O
                out = (in - tmp);' h7 u# ~% s. |2 X
                tmp = tmp + cutoff * out;/ d) K0 q# e5 }; ]  L- k1 k

. f! s% R; X4 R) F                output = (INT)out;
9 ]- P( O' v  A$ U( m" J' j' k                }
8 z0 d$ b9 }  C3 z#endif$ d' o1 e: S! k% U! T$ j4 Q, ^
#if        0! N2 @# O7 q; ?, T
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  l* A9 ]& y8 o
                {& v& T8 h, B7 g$ ?
                INT        diff = abs(output-last_data);/ c. u0 T5 F3 G+ `, a9 R
                if( diff > 0x4000 ) {
3 c! T6 n( }) w1 y% p9 ]                        output /= 4;
) w: L6 U/ }) Y7 S6 n5 R( l/ a                } else ( w+ M$ }8 L+ `' O' N! \( p" l
                if( diff > 0x3000 ) {
3 p1 O4 g; |8 f; X                        output /= 3;
4 f( ~2 b$ @8 o# f# }& Y( ^5 z                } else
* B5 \& y& Y# g8 b: Y2 s+ L                if( diff > 0x2000 ) {# b- d, A, {. c5 v6 V: V
                        output /= 2;! y9 h: Q9 X# i) K
                }+ a9 \* i( x, @% r9 F/ k# t  L* i* W
                last_data = output;
6 @5 m9 Y4 o" t1 ^& {, a5 Q                }
' A+ |4 h" C/ t2 q; Z#endif: k* u' K* u2 A* ?; f4 p# [# h
                // Limit. @3 \2 I2 C2 z2 W' e
                if( output > 0x7FFF ) {& Q5 k6 W. j. C) c+ |
                        output = 0x7FFF;# A$ s3 j" j3 o' \, q" [
                } else if( output < -0x8000 ) {" t  v5 I" l6 j" o6 [& X
                        output = -0x8000;
& }: @1 Q: L% G+ `/ E' d                }
, Q7 ?9 |2 {2 _3 d9 d$ ^9 {- Y& o& a& \, {/ H; I  F
                if( nBits != 8 ) {4 H  B3 {( l! T
                        *(SHORT*)lpBuffer = (SHORT)output;
" l( y1 E+ ]! p) R8 o                        lpBuffer += sizeof(SHORT);
/ I1 r3 H7 u& X( E                } else {
7 p9 F7 ?# P9 B' t! r! T                        *lpBuffer++ = (output>>8)^0x80;
0 [  b8 J# ^6 o$ D6 `9 E                }' E9 O( V+ |3 I6 j& j7 X

7 u0 b4 U; H- @$ U" f$ ?                if( nCcount < 0x0100 )9 R) Y( M3 `: b9 r/ c7 I( P
                        pSoundBuf[nCcount++] = (SHORT)output;
4 i( f" |: D; e* ?) q7 \
7 z, g' y3 l- ?! t( \+ g& [+ S//                elapsedtime += cycle_rate;9 q8 a7 g/ S) e% M0 z; I
                elapsed_time += cycle_rate;
- o( P+ l: Q. W: [5 g2 S9 z        }
, G( G0 l& v2 h9 [9 P% @" I" H( I9 p& t8 L1 D& U- D
#if        1
% A+ {( |" B( q3 {5 a2 E' p$ m        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {4 H' \4 m- W1 M( c1 m2 N
                elapsed_time = nes->cpu->GetTotalCycles();
/ \' B: l+ |0 L3 W! R% b% v        }7 I* v6 m( U2 o- _% f7 L" W' L' n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {0 N2 ^8 }3 _/ ~  d) |/ m3 n; j
                elapsed_time = nes->cpu->GetTotalCycles();
' n* G# v. Z8 X% W  t2 _        }
) e$ N* Y5 ]6 K$ h9 q) b+ V* q#else
# \5 P# U7 ^: c2 H& x        elapsed_time = nes->cpu->GetTotalCycles();: C: S  J; N$ G
#endif2 w  |* t8 c% {, ~; j" b/ T9 U' o
}' ?+ s$ K8 b9 w& P/ X. l
- ^2 j' T" W& n  U& N
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
2 i/ o! S% N( T& }INT        APU::GetChannelFrequency( INT no )
8 H: Q! Q7 Q+ `( M{
4 P; G$ X2 I- Y+ \" Y        if( !m_bMute[0] )
$ I% ?& H9 J8 Z" y                return        0;
) i8 e3 V6 D  Z
9 [+ b# }( b2 W- W: d5 i8 B. k        // Internal
" N7 }* t5 Y9 m, n" f8 A0 p        if( no < 5 ) {
, Z) w& A" [$ t% _                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, m& j8 l+ Z3 J        }
3 N* N; f- D6 I0 T/ I        // VRC63 e9 z% [3 O% r. x" r
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
2 b2 A5 j3 X- d  C3 i  h                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 v3 v# N4 X( h0 l
        }4 E2 O# j! n) ]
        // FDS
3 O2 W# u/ b* y        if( (exsound_select & 0x04) && no == 0x300 ) {
- d+ D+ b6 W. C                return        m_bMute[6]?fds.GetFreq( 0 ):0;
3 w" J2 ]2 d4 J0 C) I% l5 g: N4 S8 P        }, W3 @0 X. X  R0 \) |
        // MMC5
; Q8 w( I2 `# E( r4 N. O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {! n, g$ C& K4 o0 K* y; ^
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 q& q$ c: F5 R
        }& G6 u& _6 ?8 h; f8 Y
        // N106# k. `( @, u0 Z7 U" |
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {' Q$ H: {' U4 p  w
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;3 M5 h, O" t/ \. o6 g" l
        }3 X5 L, t- M" r. r
        // FME7
- h9 W& F% N  W9 o! l# j) [        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {- t5 ?0 |4 s. S1 r) f3 `) {: J& F
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
/ e, Z( Z$ z/ S; M; ]        }2 q& E. s' c, ?( r
        // VRC7
' J2 o; e+ _: ^6 P5 o        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
' `6 w( ?$ w  K  u: x( ^                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;( x0 J2 I1 `# L2 n# e
        }# \& R* Y- {1 N/ E# Y# r. _$ _
        return        0;
% n. Z8 H7 f( y( @/ W! s; ~4 P}
; N+ f4 b  }  C7 [8 _. r
0 A/ s$ k  `% Y# \1 U// State Save/Load
8 m( }  d9 K  G) t' z+ @9 uvoid        APU::SaveState( LPBYTE p )
" r$ i0 Q- V& ?: d8 @{
9 T2 P7 f/ y9 t* M* N! c5 R#ifdef        _DEBUG% J; x* F" b5 ]$ T+ r
LPBYTE        pold = p;
! N0 D/ d1 }4 p2 a7 Y6 _#endif
. F7 |+ b2 ]1 O% Z$ o! r7 R3 ]7 S8 M- |) p8 D/ t3 ]. d
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* t. d- _$ n: ]        QueueFlush();4 E# W. k* M4 \

9 g  Q: y$ N# X; q* c        internal.SaveState( p );8 N4 ^1 C& ]1 p4 j3 s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, O9 v0 E; s6 z4 f( d' a( C. Q5 t

! M( d$ \# h# T/ S+ Q/ i. ^! R, `& h4 O( Z        // VRC6& e2 d$ _; I$ I- I- S
        if( exsound_select & 0x01 ) {
' _( \4 b8 u6 r                vrc6.SaveState( p );
* I- X: l5 |: M8 D0 H2 Q; Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) i6 ~- n( w: |: Y  H
        }" e) B; U8 p( H) b
        // VRC7 (not support)& B0 n0 \& P& X; P
        if( exsound_select & 0x02 ) {9 \3 `# L( M- g. _3 `& }  }
                vrc7.SaveState( p );' E, R4 U0 j" O+ I6 L8 R
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) i/ S6 f; y$ C9 Q+ O% B5 O2 T( z        }
! \& x; D: V! Y" k1 Z        // FDS! B2 b  o! U9 @, s
        if( exsound_select & 0x04 ) {9 l& @! R/ E+ F  d, _, }2 g0 h) M
                fds.SaveState( p );
+ X/ y+ v) G! T, A6 _0 v0 {  Q$ m                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 O+ z$ E$ G! V3 M  P4 a        }
$ ~" j- H" Q4 v0 X% u        // MMC5# {- c! P6 }# h0 F: d
        if( exsound_select & 0x08 ) {1 s- i! t  c3 |9 g/ x9 ]; p
                mmc5.SaveState( p );( `3 P0 J; L7 y, N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 ~! e  ?5 N' e8 I- L% g
        }
9 I, R4 B. F+ r% T1 k        // N106; \; B: G* y5 ]  a+ o0 Y9 M
        if( exsound_select & 0x10 ) {3 ~5 E# s) X% Q- m# `
                n106.SaveState( p );& H# z. A1 n4 ^/ h
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( |* G" M% k; V- [- G0 x% W
        }$ i8 T" g6 N2 X$ ?% }7 }7 T
        // FME7
9 T3 L6 m/ Y( D. }1 o- {        if( exsound_select & 0x20 ) {9 e3 Y# k# O6 z4 C1 @3 E" y0 S9 k
                fme7.SaveState( p );8 h* s$ w: m, ~. v$ }  J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) b5 d; N) H4 R        }
" U/ r1 |4 H! ?2 L5 L8 }" }0 O! K& F3 q3 S$ }) `$ Y& Z  X
#ifdef        _DEBUG
  ]& l. \8 J" F1 T" pDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );6 D1 y  [. X' z$ e1 q
#endif
1 S% W6 K3 H. a, f( X! j( A7 Y}0 z; k5 z( I6 e& v5 `9 F
" i0 r0 L0 |& ?0 }6 w; x2 K
void        APU::LoadState( LPBYTE p )
, {: \2 w+ h3 j8 D, H. F+ X# b- i$ m{
$ o+ ^4 E+ F2 R% i" N, r        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
, u: }5 e9 @4 U! E; Z        QueueClear();6 Y5 ]2 U0 V" w7 f9 d

0 O8 G/ h9 v! X) m, z4 ?! x3 ]  h        internal.LoadState( p );1 t9 L! c* }9 d6 i) L& O/ D8 ^9 [( K
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) A- c& @: t* O& ^% ~. S
6 }) Q. J8 @$ T        // VRC6
$ ^, Z: O* s& `% b7 V9 `7 Y        if( exsound_select & 0x01 ) {
2 _1 q- [) V9 M9 X( n9 n8 D                vrc6.LoadState( p );. y; U2 o1 X% x: |, s0 Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( q4 e$ A6 e8 U: r3 N- `        }+ ~! }% t2 p/ U4 X
        // VRC7 (not support)
- c3 G7 C* H+ E6 B  q0 B; v        if( exsound_select & 0x02 ) {, O0 A$ C% b4 j- K
                vrc7.LoadState( p );5 b/ K1 I- h# J/ m2 Z; W- F% L) S
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 U- g2 M' ?! V        }
. f1 N3 h* x, k6 a$ @        // FDS
( s6 H3 F# h3 E, C  e" ~3 b        if( exsound_select & 0x04 ) {
: E% _+ {" O0 ^/ j1 u$ N8 ]                fds.LoadState( p );+ b+ S9 q1 \- w* s
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ o5 k/ V! `- {- X* R        }
* ]6 V, ^' V2 V2 m        // MMC5
! p7 H0 ]- y9 t        if( exsound_select & 0x08 ) {  I6 E4 b& ]1 E1 `; ?% N8 {( ^* Z
                mmc5.LoadState( p );: c5 Y8 W  r3 h  u6 d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 |) q+ o2 ~. \5 B        }8 W) _' p0 H- T; P* }
        // N106$ E: w* e0 w4 m; V5 y) s- i
        if( exsound_select & 0x10 ) {
# d7 ^- H. l% K! X6 k6 V$ }                n106.LoadState( p );
9 g# b! O& n; v& v) ~* N) s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- d& X" ^7 W: }1 L- L        }  v0 a# D' o0 A. ]6 |' ~$ O
        // FME7
7 p' f  u3 ?7 A: |; ?        if( exsound_select & 0x20 ) {2 g$ r$ X( D- V9 x- H- b
                fme7.LoadState( p );
" M4 T% j: ]9 n  \! e7 p: h* Q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 E* ]  |0 G1 f9 t6 S
        }
7 @0 R7 w+ z& o- t3 J}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / {5 @- B  U9 }
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- i4 w, ?  Z% m8 u
感激不尽~~

8 M: g8 Z: q5 ^恩 我對模擬器不是很有研究,
8 b0 K/ z, T7 q雖然要了解源碼內容,可能不是很困難,
3 f+ @1 o' q8 G/ h6 D4 T* z不過還是要花時間,個人目前蠻忙碌的。5 o* q6 J" K  Y/ j( p
$ p  @- i! z$ C2 `8 F" R
給你一個朋友的MSN,你可以跟他討論看看,
" T; W. }/ C$ U! e  K- t  S! k5 G他本身是程式設計師,也對FC模擬器很有興趣。
* Y8 O4 R) g5 y& l0 L* |7 M) r  i) o# s& z0 F# B7 t, Z
MSN我就PM到你的信箱了。0 q8 I3 P, ^1 t/ R

/ q# U. x: K8 D) q希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " n3 o+ w  b# z# B3 c1 T
呵…… 谢过团长大人~~
% j# C) [: \  H  U
; p8 [6 l* _9 a. ^
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + R6 S9 ^" f! [: ~: ?
团长的朋友都是神,那团长就是神的boss。

* q& `' u6 u! k哈 不敢當,我只是個平凡人,
+ u1 f7 W% A+ @3 o/ _4 j6 D5 D9 o要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
: Q+ o8 |- }9 p2 w: YZYH  a- R. b4 \3 r9 S
QQ:414734306
- r2 O* z7 V$ |* A4 O# @Mail:zyh-01@126.com% o- N* g& W' O. L1 E3 S$ l: N

  w& A7 D# i/ i( w他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ( k$ b" f. ^( i% r/ U" z8 ^
再次对团长大人和悠悠哥的无私帮助表示感谢~~

. Q# H/ n6 _# e$ W, N不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-10 00:59 , Processed in 1.098633 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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