EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( [. l7 z) e2 f, ]% J8 |: D; v6 c楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 I$ m$ F$ _; y1 d这里有相应的模拟器源码,就当送给大侠了~~
$ F2 a; q4 T- U! {6 n; a3 g- ^) t" \http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( S" c1 B( r- C0 m5 ]( }: a能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
0 W' S7 j, S6 @; g% n0 ^( T$ j楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ t* @4 J, |! `: B这里有相应的模拟器源码,就当送给大侠 ...

# b  b* B3 n9 d聲音部分(Audoi Process Unit = APU):
+ ?7 t& K7 q4 r9 B; m.\NES\APU.cpp
9 J0 m3 D! p0 l+ F7 ~  Z; |.\NES\APU.h, V" F/ z! C- I6 I
/ Z5 z9 x  W5 [% u* o* \6 ?

% @1 f/ X- B7 M7 x  y, S$ y影像處理部份(Picture Processing Unit = PPU):
2 }1 Z9 |/ K$ L.\NES\PPU.cpp* P/ z" Q5 L/ ?7 _0 V. M
.\NES\PPU.h
6 v6 k$ U( }: A( f( `, Z! p
( O" `1 z, j; I! R4 J* V1 O+ S如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
$ ?, a1 N& k1 E9 w9 e(由于很多专用术语和算法机理都不明白,所以看不大懂……)
9 }+ v* h0 \. k1 W# u8 T//////////////////////////////////////////////////////////////////////////4 E, k; g) h2 c
//                                                                      //0 H7 f1 f' `, s3 o2 e; e2 r1 q
//      NES APU core                                                    //
2 J; C; {/ F" V5 @' j$ k! o+ h9 ?//                                                           Norix      //! @' g6 u  c; c# T8 |' L
//                                               written     2002/06/27 //* n* t8 ^% {5 _" e! L3 h& D
//                                               last modify ----/--/-- //4 b+ Y- w7 R8 Z- G: X9 @5 `
//////////////////////////////////////////////////////////////////////////
1 ^. D/ P; E: K  {+ \- H#include "DebugOut.h"
! @. B" r- ]" K, z#include "App.h"  j9 v' d9 Q' w( m6 M) K. B# g
#include "Config.h"7 a0 X( C. [6 h4 V* ?  W
) @, p0 |6 h+ E. b9 I& n/ g) V
#include "nes.h"
0 {7 Y* @! q8 W2 R#include "mmu.h"0 d  g. v. F  e
#include "cpu.h"
6 @" B5 A, V' z& @% L6 ]0 N2 @#include "ppu.h"
! Y" {% |- D+ x#include "rom.h"
0 S3 }$ ]; y0 S& h9 q- J$ n' B; H! M#include "apu.h"  x. i8 Z" d$ t3 @* N

$ u2 Q1 T, q; z9 K( V, w; ^// Volume adjust
9 w( S9 `0 ^* N7 F0 P0 b6 f, z// Internal sounds
& m0 D! ~2 N2 h) g4 l#define        RECTANGLE_VOL        (0x0F0)3 h/ p" j/ x. q
#define        TRIANGLE_VOL        (0x130)" X" o& Q2 A: `! H- E3 x
#define        NOISE_VOL        (0x0C0)4 @! h1 I2 r6 E* A, m; j0 p
#define        DPCM_VOL        (0x0F0)9 e* t7 `6 t! I3 ^" ]
// Extra sounds' E1 w" W9 y6 k& i
#define        VRC6_VOL        (0x0F0). \$ l: s5 f& e7 s
#define        VRC7_VOL        (0x130)
% t+ a0 c. B5 b) a. U#define        FDS_VOL                (0x0F0)  i4 b7 t6 J7 u3 ~* E. v
#define        MMC5_VOL        (0x0F0)
# y4 @; G5 ?( \7 B5 X4 ?! y#define        N106_VOL        (0x088)
/ u, r/ a/ x% S#define        FME7_VOL        (0x130)4 R' `2 i! s$ K, ^" B3 t) c
5 E( w' [# A$ }5 N: M7 L, w
APU::APU( NES* parent )8 J4 s; J3 [' n' x) R3 v: h1 g, Z
{
0 ^; Y3 [  x; h' V. S! [, L        exsound_select = 0;- [$ y" @7 g1 ?2 z% p7 \7 [

, Q4 l& q+ A% F. v% u        nes = parent;
. x8 \: l! t" s1 k        internal.SetParent( parent );
' B& f5 O7 R3 `. l" B8 B' R* s0 Z  a- \4 Z& D) e
        last_data = last_diff = 0;: q% }8 P! M& R* O, L7 ]% M
) H* J6 M( L" i8 l- ?/ |: j
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
5 m4 t% f' W; J$ M! k3 [6 y8 b3 R2 q  s8 H" `' `2 w
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );  y* Q4 b- j+ e9 ?
        ZEROMEMORY( &queue, sizeof(queue) );
) J7 A" G! k9 g: W7 p; V        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" {& Q' a8 q) v% y. m% z: D
1 V8 \, L* l4 v! S        for( INT i = 0; i < 16; i++ ) {
% Y, N/ l1 o1 d, q" p4 u# d6 x                m_bMute = TRUE;
3 H- [9 y  e* j0 f        }- l+ J/ I! L; M6 c& l. B3 q
}: ]+ h# G6 Q0 J6 M+ {7 Q$ _7 {+ }  h
* Z; ]* p) f8 ?1 S3 g& x$ ^, M  C
APU::~APU()+ T1 U3 p) [9 |2 K, f* n. T5 b5 N
{4 w  J1 E' B' D% X1 {( h- b
}
# ?8 A5 ?3 D1 Z, t# d) }/ J9 H- s% c4 H- b7 B. Q" Q
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) `3 m2 [% b! F3 W  g{
4 `2 J. W! h* W% H        queue.data[queue.wrptr].time = writetime;( y8 ?/ @7 i& u, C3 E' x2 \6 ^
        queue.data[queue.wrptr].addr = addr;$ X; Y7 H" O1 m/ Q1 J
        queue.data[queue.wrptr].data = data;
# j4 s0 [& ^7 @. F: x" i, k! D        queue.wrptr++;
1 _4 G* V3 T2 s0 e        queue.wrptr&=QUEUE_LENGTH-1;  u6 u- X3 I. _8 L
        if( queue.wrptr == queue.rdptr ) {+ H7 n, }1 x4 @
                DEBUGOUT( "queue overflow.\n" );9 q% I6 {9 @/ b0 `# [. }
        }+ _4 G- w6 G! Y
}1 }0 A* Y4 x# s9 [- c- X

; ]& h7 z# o0 PBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )( a6 [+ w  H8 r' ]. ~
{
+ P, \5 c# c8 S# L9 ?7 A        if( queue.wrptr == queue.rdptr ) {
4 ^4 m, N' A/ H! b1 ~                return        FALSE;
! x* w0 X( j9 o0 F        }0 u3 d# g1 N. O* a: A
        if( queue.data[queue.rdptr].time <= writetime ) {- w5 M* f" e$ h" x, u
                ret = queue.data[queue.rdptr];& r$ |- i7 ^7 c
                queue.rdptr++;
$ E' h9 t6 R+ l6 ~3 V5 d# V                queue.rdptr&=QUEUE_LENGTH-1;$ R1 e8 B- f) @; s% H
                return        TRUE;* \' C  J* _4 Q% W5 g/ p
        }' K6 L% f, S1 l
        return        FALSE;" c8 E% f+ x: m9 J
}6 X0 [% x$ ]* I1 P6 t. n( L; T
- p, k2 H6 B$ g) T
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )$ c9 y7 C: ~1 o: N/ b7 @. p
{+ _7 n4 o3 t9 j3 N2 V; t
        exqueue.data[exqueue.wrptr].time = writetime;  H( H% t1 T3 {6 v  ]4 _4 C  X% j
        exqueue.data[exqueue.wrptr].addr = addr;
9 f! b9 p( G3 L' ~) [        exqueue.data[exqueue.wrptr].data = data;
: f1 B9 u8 M2 W2 x" C# M        exqueue.wrptr++;! X- H2 s( }% S4 o# d: y" B* l: C
        exqueue.wrptr&=QUEUE_LENGTH-1;
$ b% d9 `( h( @1 t6 B5 M) |        if( exqueue.wrptr == exqueue.rdptr ) {
/ Q0 }+ f3 D# f                DEBUGOUT( "exqueue overflow.\n" );
8 t6 U0 C  I$ ^" }+ x$ K9 W        }# v; R5 O& t2 ^
}
: b  b' @% ~- U9 i8 b! g0 _  W; ?0 S6 j+ `% B- r
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )4 P0 m' c$ A& K
{" [5 |$ e5 M) E8 ~; p
        if( exqueue.wrptr == exqueue.rdptr ) {8 x2 z1 s3 L5 ~6 v2 h/ ?# ^
                return        FALSE;
. S8 r) {# J# W; P: c        }
' C9 P8 j3 j" i& t4 y5 h        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( `, D) W  m0 D2 J( z                ret = exqueue.data[exqueue.rdptr];- p% f6 G! D& ]
                exqueue.rdptr++;: b/ u$ ^1 j9 Y7 d* V/ G% ?/ F1 ^
                exqueue.rdptr&=QUEUE_LENGTH-1;7 ~8 h  e! a& ?4 e
                return        TRUE;# C) D& |, X9 |6 d
        }
0 |9 R* C2 X  ^. h4 k. E        return        FALSE;9 s8 c# b; j1 S* W" d) _  y/ r
}# B7 [& u* H5 S& l/ P9 B
, A* {4 c3 J3 G$ y
void        APU::QueueClear()
- O* U. H, _4 X{: S- g" m( e3 c" Q2 }
        ZEROMEMORY( &queue, sizeof(queue) );
, ~  Y  M! y/ z; t8 m        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 I6 x( z3 y( o; z: q! q}# w0 z1 U9 z! s9 j

" W% S% q$ ?. r" L! n& O4 j9 }5 xvoid        APU::QueueFlush()( f2 G2 S/ p3 w8 A! o/ E& q
{
% i0 {2 K# M8 r% l! t        while( queue.wrptr != queue.rdptr ) {2 R7 P' t6 a- u, {
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ o9 D( }4 k3 M, v4 {+ |6 c5 }/ Y' i6 C                queue.rdptr++;9 {7 s  M/ o& r  K  ]; a7 {+ p
                queue.rdptr&=QUEUE_LENGTH-1;  O, m9 c. v% p* _3 P
        }
* T; U: U2 c4 C9 H7 `
8 k: Q7 M7 K/ ^7 e        while( exqueue.wrptr != exqueue.rdptr ) {7 c8 p( U5 c5 `5 i
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: _- ~3 T6 L  ^- ^1 |                exqueue.rdptr++;
9 ]3 C) S3 Y7 m7 x                exqueue.rdptr&=QUEUE_LENGTH-1;
8 `* z1 s3 ?5 `+ T5 Y        }
  z. S9 z$ q% g* k}
. T1 ^+ U* k+ E: T1 v+ J9 l
3 N% c+ s4 I/ s' pvoid        APU::SoundSetup()
0 X6 [$ p9 X" I+ W{
- E0 n8 U- N7 e1 ~, f' S6 q0 ]        FLOAT        fClock = nes->nescfg->CpuClock;
8 N; @) ^4 j" t( B0 z1 o! Q        INT        nRate = (INT)Config.sound.nRate;% ]" u5 `- C7 r  F7 P4 _2 G1 K
        internal.Setup( fClock, nRate );
8 s/ e# l9 O. Q) X. L        vrc6.Setup( fClock, nRate );2 d9 N9 g: u1 q4 t" K' I  H- t9 Y, o6 B9 G
        vrc7.Setup( fClock, nRate );' g& t1 H/ h& j! e
        mmc5.Setup( fClock, nRate );
, h" @( B8 I4 y        fds.Setup ( fClock, nRate );
  d) {; O0 Y( H6 `. Z; M. S7 n        n106.Setup( fClock, nRate );
4 \( l+ X6 z, G0 F& ]% H& \        fme7.Setup( fClock, nRate );/ |; q7 M# X/ A/ I- d
}
% O! I6 T& P5 h+ O# r6 u
7 L, x6 I: L% [# xvoid        APU::Reset()6 |3 B* d, g9 @0 J9 h
{7 y. u" @3 c9 ~
        ZEROMEMORY( &queue, sizeof(queue) );
3 L' G" y7 T$ Y$ q/ g        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: E0 D4 O0 _' \" e  C! y$ @& \4 b" a- g6 _# a
        elapsed_time = 0;
3 C  e$ q9 i( V4 R$ B! o$ ~. l% b
. ]2 c; m+ L* H        FLOAT        fClock = nes->nescfg->CpuClock;7 ~1 \9 t; Y1 F, \
        INT        nRate = (INT)Config.sound.nRate;4 S7 J0 ^8 I4 t& W7 z& T: u
        internal.Reset( fClock, nRate );
/ e6 I0 `( v8 |! G  Z# s% j, S        vrc6.Reset( fClock, nRate );/ g) a/ c+ p6 h  ~6 L# Z3 n) z
        vrc7.Reset( fClock, nRate );; v* K1 \/ F3 _& j
        mmc5.Reset( fClock, nRate );: l% d* }/ W6 H" h: A4 V0 q' }* p2 x7 B
        fds.Reset ( fClock, nRate );5 z0 w0 N: U7 z" z* t7 T
        n106.Reset( fClock, nRate );- w* s& R) S  t) J5 `& C
        fme7.Reset( fClock, nRate );
) P8 h$ T- g$ C% d$ s
/ P. s1 J: H8 c8 [! ]        SoundSetup();
" Y5 o1 X% b2 n- E& [( G  p% i  P}
& z( q0 B4 C3 w3 _) x: N; ]0 l" e" c, B
void        APU::SelectExSound( BYTE data )9 i8 k; C; C) [; B( e
{) M. k+ k7 m. Q8 `4 L3 |1 }* O
        exsound_select = data;
1 }! @- N8 \: w9 C}
: o  o, Y3 W9 o0 D( N2 I* W8 B$ C) A7 `& \, e# O
BYTE        APU::Read( WORD addr )/ T$ z2 d1 W4 O& H" x
{
5 H, R6 U3 k: i( h7 q: Q+ i' D        return        internal.SyncRead( addr );. F" [9 D# T" D8 Z% [2 N5 {$ l! z
}9 ]* b/ U1 T8 ~! `* l! _
$ Q5 D  o% |6 q' c% K. w
void        APU::Write( WORD addr, BYTE data )8 P9 Y  N9 ], y) E9 v9 y* A
{
) p* H, q4 l( P3 X5 n4 \        // $4018偼VirtuaNES屌桳億乕僩$ ?" \: W  f" ?
        if( addr >= 0x4000 && addr <= 0x401F ) {5 z# O5 I: R( r1 b
                internal.SyncWrite( addr, data );# J1 z$ g! a; e. `8 a6 I+ v
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );6 T8 e: Y) \) H7 R6 g) c' o
        }
/ x5 G! [) A# [+ T' `* M8 G) r  R}
9 o8 H- p: T+ L3 }: _. y3 V
) s: J- I- V, yBYTE        APU::ExRead( WORD addr )
8 i$ v8 M% I4 J{/ ?" B$ I& N: Y8 \
BYTE        data = 0;( d. b2 d; z- h! v& f
$ S8 B# g* d3 @0 w! a  u
        if( exsound_select & 0x10 ) {
- z7 ~* E9 i, U* A: B                if( addr == 0x4800 ) {: ^4 I9 j  |6 l, c/ `
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
( p( W/ T+ P; R" G                }
1 f" Q. g. f3 P        }% P' [0 U) W/ `$ ~4 q
        if( exsound_select & 0x04 ) {
5 U/ R. r' F- X                if( addr >= 0x4040 && addr < 0x4100 ) {
' J7 |# l1 y, O+ S, M' A                        data = fds.SyncRead( addr );2 T7 @8 y7 l; v! k
                }
# y" c% g0 i% Q- d- u        }# o5 [3 ~6 Q4 |# P
        if( exsound_select & 0x08 ) {
+ T7 |1 k' J* O; c( V                if( addr >= 0x5000 && addr <= 0x5015 ) {6 b7 `, R% J9 y+ _- I, `; i7 E4 S
                        data = mmc5.SyncRead( addr );1 j' a1 Z# q7 Q  x5 _$ D
                }* F4 a+ F3 b$ ^: Q2 _' {3 Q
        }% N* k) P* V! z% M# A8 z8 [

2 |1 R8 c5 W" c1 \0 _0 [2 V        return        data;
1 Y0 [  a8 V1 L, a}1 [& d& S. ^  p  j

7 ?! K, e  ^! G/ Qvoid        APU::ExWrite( WORD addr, BYTE data )* R4 Y8 ], @# D; J6 c- b
{
+ i/ d9 r3 k) A: ]+ I3 h% W8 [        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 t) z7 \9 Z& \/ F$ \6 q
; @+ f9 p4 A! }3 d% X% s        if( exsound_select & 0x04 ) {/ A% e1 D" w: Q2 X1 Z6 k7 E
                if( addr >= 0x4040 && addr < 0x4100 ) {. r3 `& S! ]0 R
                        fds.SyncWrite( addr, data );. V# Y4 ~) o' r' b
                }
4 r( b: N. h) e$ D; B6 B4 h: `/ m- y! Y        }" k/ e7 V7 u9 L: L7 ?

. m' |" Q9 }1 M( R! e: A3 w# J        if( exsound_select & 0x08 ) {# n$ l. |: W( Z" ?7 c
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: S- N/ H  @: N4 t5 f+ D                        mmc5.SyncWrite( addr, data );) T" J. }: q' ^
                }
; ^' z  M1 v3 q        }
3 {* z' o! {; R8 _* C% V* V}) J+ A6 x& Q1 l
* [  `' H0 Y9 ^9 m8 y
void        APU::Sync()
; E1 N& n3 j6 [) ^* U) \% [7 e  t{2 B, X1 r5 Q4 {# S5 X- i7 w% c1 s4 V
}) `3 m$ {( r/ V" V+ v; V# o; c0 X7 ?
5 ?  p" z9 F! ?/ S
void        APU::SyncDPCM( INT cycles )7 I$ y/ H0 r. U' Y5 J" x# X+ N9 G
{) _$ y  s) {4 ~) v+ u
        internal.Sync( cycles );6 X' U1 Y3 j- y& x; R! _

! V  s5 G0 }4 v8 L        if( exsound_select & 0x04 ) {  w& `/ Z: b* `* U1 C; G7 s
                fds.Sync( cycles );, m4 U6 P7 a/ T
        }0 `& R& U& h/ ]1 y
        if( exsound_select & 0x08 ) {
& ~( D: U7 I# k                mmc5.Sync( cycles );# E; ~9 j2 S* S; l
        }
' R+ ?0 L& A: U2 y: H}3 b* k# M' A% l+ t. l6 D- o+ n

. n1 p) M0 Y; e. @void        APU::WriteProcess( WORD addr, BYTE data )3 L+ I# R+ z2 P7 ~8 a
{. W5 \2 y4 |4 ^3 P# ~9 ^( B6 `
        // $4018偼VirtuaNES屌桳億乕僩
/ t/ d7 i: @; Z3 G) A8 ^4 h        if( addr >= 0x4000 && addr <= 0x401F ) {
- \& J: N  c4 R1 j" ^9 Z  j5 @                internal.Write( addr, data );
9 e9 O: \: k+ y& G% }% n        }/ |1 G- l! c+ _
}
; ~' s" L- X* S; s. C0 k$ R7 c4 r( c# b2 I0 p3 L( q
void        APU::WriteExProcess( WORD addr, BYTE data ). D! f2 V6 v$ J! n6 }9 }; k
{/ [( l3 l6 b) {+ _) F
        if( exsound_select & 0x01 ) {
1 J* R0 Q1 |8 f5 n( y. L1 t                vrc6.Write( addr, data );
! k# e* F7 O# d7 ]0 {5 A        }1 L& S3 d4 h& u! T0 b$ y* D" o
        if( exsound_select & 0x02 ) {
6 ^+ x" Z3 h2 D9 D) I% C                vrc7.Write( addr, data );; ^7 Q8 O) c2 A/ p, t0 L% y
        }* s. s/ h. d9 m
        if( exsound_select & 0x04 ) {
( f$ S3 }2 @4 [( l                fds.Write( addr, data );
2 t; i; ^( R0 C6 z8 u& {1 t, S0 G        }: M( {- Q! U5 }' G
        if( exsound_select & 0x08 ) {; d2 s5 x! V/ q% q* j" R+ E( }4 L/ Q
                mmc5.Write( addr, data );
) x& \3 P: ]- v5 N* H0 D0 O) j        }+ @" U- j& g4 a
        if( exsound_select & 0x10 ) {  @# p- k8 j0 X
                if( addr == 0x0000 ) {
: w) E' O0 o% S                        BYTE        dummy = n106.Read( addr );
" t; n1 H; C. W. {) B                } else {
1 T. r, L2 J+ t7 W: P$ ]                        n106.Write( addr, data );
% w6 \5 z8 _7 v4 X  j  ^                }
7 _0 q1 W7 d2 Z        }2 x2 ?7 h/ b# u& \0 C  l
        if( exsound_select & 0x20 ) {
3 `$ x( E8 X- Y' J2 @& W                fme7.Write( addr, data );
- e+ K/ C+ F0 K1 w        }' E4 {. A+ K% {8 ^6 o9 @# S
}
1 f9 N. i- }6 e- D, S0 R
4 n  `5 ^( [1 F8 |5 Svoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& @( B  U' ]# c{7 ^* M) v8 O3 P
INT        nBits = Config.sound.nBits;* y! O: ^+ A4 S( s
DWORD        dwLength = dwSize / (nBits/8);
4 T) M7 Q* W! vINT        output;
3 @3 R9 H) h2 q5 BQUEUEDATA q;9 j1 ^. U* Z$ w
DWORD        writetime;  P4 z8 c% W; q; @; s
5 _5 l7 q0 i$ w- E8 T% H! {4 p
LPSHORT        pSoundBuf = m_SoundBuffer;
1 N" n) H( @; l6 QINT        nCcount = 0;( B: b. c1 s1 |9 Y
% T( C$ H& @3 ^5 K6 ~
INT        nFilterType = Config.sound.nFilterType;
0 l" q- Y, S! P( Q0 c
6 F4 c' E' E* }/ |" o& E        if( !Config.sound.bEnable ) {; {) H$ U2 v) k9 E: x
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );( p4 g9 o- |. v  T2 n) n
                return;
  X% @; R7 J2 M4 @. G8 c6 Y4 l% c; N        }
; n$ l% E# k% `9 ]( v! H1 u2 T* L( n6 H
        // Volume setup. O) o* c  r; K" K
        //  0:Master
' y3 w# [' K# p  p; p0 M( G        //  1:Rectangle 10 k! p; s: e- E" Y' w
        //  2:Rectangle 2
. |5 b9 G( p4 h- K7 X        //  3:Triangle: f0 H9 \/ g7 F9 n; i! K
        //  4:Noise
3 ~' S7 ]* {0 E0 \        //  5:DPCM; v1 b, n! h; {( }
        //  6:VRC6
1 @1 s! U& a' Y, v' A        //  7:VRC7
4 z1 X0 ?* O* P' z- j( y        //  8:FDS
  t6 J' C2 F$ `7 x/ N8 L6 T' f        //  9:MMC5. ]/ C1 `7 ~( S( J
        // 10:N106. ~3 `% v: R  k- \1 U
        // 11:FME7
0 R3 ^. x+ W' _2 }! t        INT        vol[24];5 j% p* k1 u$ [5 U
        BOOL*        bMute = m_bMute;3 O  ]( l& T& a: A
        SHORT*        nVolume = Config.sound.nVolume;
6 [. T4 e" ~0 X& C1 a8 g
. q$ }+ T0 Y+ H" I        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
. Z1 j# w% T! ]3 [6 v! P
1 ]' O+ k) _7 ~' e. ]        // Internal6 K1 _* w% W  a- }$ \8 C* W, p) h
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 m3 I2 k/ D2 |# n
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 s& w" n' q. {4 e  r/ K' J        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 i( a+ L' G' T" }! Z6 b' j! x" z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;8 `+ o: ^5 ]6 P; b1 q
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
8 v" R) {. ^, D/ R2 e3 I0 M, G6 z7 a+ D  ~! E# v! p# F
        // VRC6
% h& ?! t+ E" k3 H8 m1 m        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 I! B6 _. Y+ A/ ~
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* T3 M: D% k8 C* h- a3 ^) n
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- L  k7 g, q% K' s- I: h" V# A0 q2 U

* W8 T$ C/ y4 e, c. V        // VRC7
5 g" s4 w' |5 x/ [  J2 x% Q        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- [0 `( m" \6 e3 x0 Z# T, M' |* @* T+ ?% D: P5 }7 O; @# O
        // FDS
/ n: p5 R, n" a* v6 b        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;) L4 `5 n* c- V2 a9 N

4 E- O  i# W0 n% r- k" C9 Y        // MMC5% T0 I6 b3 a) i
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# {+ C+ T% o" a+ E+ V
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* ]2 @9 {/ x* ?        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" E+ n! c2 w# D6 b/ v) A3 x9 ~
4 o5 w% z% ?7 C! n; v# K0 _. g  {
        // N106
9 G5 z3 E' s) W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 F/ n. u- l( E; f  u
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 M# J: ?! C: u! N
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 y+ F2 m- A4 V  k1 O$ T( [        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ x; E) ]* X8 n" S7 C        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% m: C/ k) \  B+ X
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 r# n% F4 i+ Z( t( a        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& c! `0 t' ]% p9 g) B0 u, n        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 s$ W, x; M8 F" b6 w

& k) J7 L/ W' b* ?; t2 |        // FME7
+ J: P( P2 ~* H+ ~        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 v6 v) b# ]4 a. y% x6 R        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, [1 a5 F$ ]/ M: J/ q$ `0 q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 b+ [- l* e" c5 J! v0 w  K- Y4 O
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;4 M( p+ Q& X7 V. ?  `
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
" ]3 ~3 F# u$ O4 L
. H) s' C/ m' W& j$ V        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟; Q% V; R5 \( K5 i9 G! V
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {, j: R7 N+ T  R$ v, P) G0 @
                QueueFlush();6 O4 w  Y, E# X5 @+ I' l
        }" k+ G7 S/ ~( J3 j- U6 A
) m; K/ l* k& h/ G3 {
        while( dwLength-- ) {
6 i" q. m8 r* E7 ?5 u                writetime = (DWORD)elapsed_time;
! W3 `& b3 n& u) ^2 Z; N5 D  C/ l' u# r1 l
                while( GetQueue( writetime, q ) ) {8 I, P1 w8 ]. R1 {9 p& I) N4 V  l
                        WriteProcess( q.addr, q.data );1 m" @! z: Q  i7 P
                }, z! W; L* a1 v
8 t" Z( R+ ]6 c. _
                while( GetExQueue( writetime, q ) ) {6 R7 s. [  u" L
                        WriteExProcess( q.addr, q.data );
9 H! R* `4 e2 f  e7 n: H, f8 I                }
' ?6 |, B3 n" r& [' y& t
+ v* R6 e3 t5 h) j- V' _                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 ]. K, `9 J0 O* E6 ?. o+ l
                output = 0;
8 C% V9 O* v+ `3 x, x$ O+ X/ U! K                output += internal.Process( 0 )*vol[0];& ^- p# m) X3 G6 z5 [2 H
                output += internal.Process( 1 )*vol[1];* [  K3 N8 X. t: c
                output += internal.Process( 2 )*vol[2];: `9 e2 r2 r; C5 |
                output += internal.Process( 3 )*vol[3];( |+ _  Z- P1 y! t3 q: w' ?2 R
                output += internal.Process( 4 )*vol[4];
' @. d3 R9 N& O! _' [
4 E" M: Q, L# @' q5 i) C$ \                if( exsound_select & 0x01 ) {3 l1 k  e2 i, f. K- A
                        output += vrc6.Process( 0 )*vol[5];1 n3 ]) O- V4 Q  G1 Q' E. B
                        output += vrc6.Process( 1 )*vol[6];- B& V9 ~5 @, d# v! t' |
                        output += vrc6.Process( 2 )*vol[7];$ k1 b7 R5 u  T& p- @
                }
6 |% U! t4 T' z5 W                if( exsound_select & 0x02 ) {
8 T: ^( c& P# ~5 [( o5 X9 i                        output += vrc7.Process( 0 )*vol[8];
+ n; q7 U2 F; A4 j                }# U, v' W# i  U9 b1 ^
                if( exsound_select & 0x04 ) {
; V& B" d9 I- z' b                        output += fds.Process( 0 )*vol[9];
2 H* D5 R( l; X2 \4 U( p- B! r9 b                }- K% N* M, k4 [* q2 q
                if( exsound_select & 0x08 ) {) Q% Q) a! B6 k# r; ~4 P
                        output += mmc5.Process( 0 )*vol[10];
4 ?9 @5 p8 B2 J                        output += mmc5.Process( 1 )*vol[11];
+ Z6 n0 l* N- h+ e                        output += mmc5.Process( 2 )*vol[12];. D% n9 f% c8 s, Y
                }% _. [. X4 X9 \% j6 y
                if( exsound_select & 0x10 ) {
. `" w5 W- ~8 A( n; l                        output += n106.Process( 0 )*vol[13];$ T) @& E5 G4 ?. i0 H" ]1 \
                        output += n106.Process( 1 )*vol[14];
% n% l: G! ^; y  M7 q                        output += n106.Process( 2 )*vol[15];" \% K' c1 _) X6 C8 q4 R, ^/ J3 P( t% B
                        output += n106.Process( 3 )*vol[16];1 e9 K8 h6 s* j
                        output += n106.Process( 4 )*vol[17];; {7 ~- `: K6 b5 _' v9 b# p9 Y- B
                        output += n106.Process( 5 )*vol[18];1 J9 P# @  a6 u8 [
                        output += n106.Process( 6 )*vol[19];
8 I% o7 g. @. v, H5 L9 U" y                        output += n106.Process( 7 )*vol[20];
' X1 l1 |  E; b! S" K                }0 f6 x# S6 Y3 W% P) V. X1 P4 g
                if( exsound_select & 0x20 ) {. x" n0 }/ \# m/ \
                        fme7.Process( 3 );        // Envelope & Noise8 N# O3 Z% E1 v5 ^1 \, Y% m
                        output += fme7.Process( 0 )*vol[21];
/ l9 J4 _5 j0 J: r: d# _. q                        output += fme7.Process( 1 )*vol[22];
% t( i% @9 B. _                        output += fme7.Process( 2 )*vol[23];
4 I9 n8 Q7 u4 z9 o; ~: c                }
! S1 T# e7 `: v4 h$ n% b( J  p( d, ^- G9 v# Y
                output >>= 8;+ m# [* u, b/ L. v

+ V$ N" S8 |! z                if( nFilterType == 1 ) {
' I/ k$ J0 k  U. O- A                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& z; O; w9 O5 L7 x                        output = (lowpass_filter[0]+output)/2;" s" V0 k1 i5 }- S
                        lowpass_filter[0] = output;0 o1 v2 ~6 o5 e2 U- Z
                } else if( nFilterType == 2 ) {) W) U- C3 H; S" m3 r7 }
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 v1 D8 W0 H; u; ?: {+ P  \" Q8 l
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
8 p. S. ]8 @+ e  ^# @                        lowpass_filter[1] = lowpass_filter[0];1 d. n" e) i3 D; d- a, d0 Z" E
                        lowpass_filter[0] = output;2 T7 A4 b9 K$ S" L) Q; d  s
                } else if( nFilterType == 3 ) {2 C. i) z) u4 \# v0 r
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 p; q# f  G8 W) l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;4 e8 l9 X8 g% X/ E
                        lowpass_filter[2] = lowpass_filter[1];8 [1 C1 Z( H' i8 ^7 I. f# d
                        lowpass_filter[1] = lowpass_filter[0];
3 G' D# k1 p# }, X. q. D                        lowpass_filter[0] = output;
6 u2 k' J2 N# e                } else if( nFilterType == 4 ) {. n/ w8 p+ f( |9 c
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); _" A' n8 |6 j- C" Z9 B8 ^0 m; ^
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ v5 J9 K6 K' E                        lowpass_filter[1] = lowpass_filter[0];- |4 ^: t  e( D- b
                        lowpass_filter[0] = output;
$ I: |2 }: e! M                }
$ h, _" b1 j7 H5 w6 s  ~  }6 d' h  J- B0 l
#if        0; m' I( ~: [6 Y2 H- w0 s
                // DC惉暘偺僇僢僩
& G$ P8 ^8 _6 D: {; _, k" T                {
9 U4 o. z) H! J( F: i2 c: ^3 l                static double ave = 0.0, max=0.0, min=0.0;- k1 ?# c, J' Z/ c' l
                double delta;
: D0 u# G" @  R! u. q- g                delta = (max-min)/32768.0;
2 q* g# x- v7 Z6 [" s                max -= delta;% G" y7 B. Z8 a
                min += delta;
/ G, h& z6 `3 g7 j0 {                if( output > max ) max = output;8 b# S. K, t9 `- P" n- P
                if( output < min ) min = output;
% t* i% J. L: ~% z                ave -= ave/1024.0;
/ z  x2 r( D  H, F: p* K: y9 a. |                ave += (max+min)/2048.0;
  W8 C, ]5 g% i5 Y+ p                output -= (INT)ave;
, J- @; ~8 t/ P: J# p& \                }
, m  D! j8 ]# b# U( b#endif' l! r0 Y4 T4 V# i5 n3 f1 p5 x
#if        1
. B1 p. {+ c" j5 U6 G9 I; o  s& ^. n                // DC惉暘偺僇僢僩(HPF TEST)
" v2 y4 n9 O9 t: A% @5 K% A                {: p% F: B% b3 j* l5 d* D
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 m" y5 I4 |0 d; `8 J1 {                static        double        cutofftemp = (2.0*3.141592653579*40.0);
' |$ v& R. \! [, g5 J8 v                double        cutoff = cutofftemp/(double)Config.sound.nRate;
% p3 j- `0 I2 A4 n6 G. S- {6 [+ D& h                static        double        tmp = 0.0;* }* I+ T9 k3 L
                double        in, out;
2 e" ^, z2 y+ h; D" d* H6 I6 D+ v
                in = (double)output;
5 [0 C1 p- {; ~; q7 p                out = (in - tmp);5 i, r/ Z% K1 c
                tmp = tmp + cutoff * out;
0 O8 h# i1 Q* H' a& i0 {+ u7 @7 T& y. ^3 E- Y
                output = (INT)out;
; x8 b1 h5 t; `+ y                }9 k+ _4 ]. a8 n" c; o' N0 [
#endif
) F1 P! x' i' j" y: r+ E( r2 o0 L#if        0% k8 ]4 \* e& W: L' k
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
! r. C9 t. l' B% B6 @: A* }                {" f: s0 g/ r% e
                INT        diff = abs(output-last_data);
' V7 Y. ~) a9 e: j                if( diff > 0x4000 ) {
; c7 K0 [# U. W' J% S                        output /= 4;& e3 K, P" |4 @5 O& f  f
                } else ) n2 Y2 E. T& `# G4 ^, e8 n" V
                if( diff > 0x3000 ) {
! ?! L  ]3 H9 N/ ~  m" O( Y! ]                        output /= 3;
/ H! i) o- C! i  u                } else; m: V% P6 o, n' |/ X- p1 p
                if( diff > 0x2000 ) {$ e: ^$ a. o9 J* v1 t0 h5 q
                        output /= 2;
; u9 u: \/ L8 |4 f                }
' f0 n+ v/ K- k5 [% }                last_data = output;$ _- M3 ~3 Y$ Q9 Z6 d
                }' ]; u# a$ [3 e/ y" {! x* B9 i! \
#endif# `( Z5 r! h$ ]* y8 a/ F0 j+ y
                // Limit: Y( A( P5 v( f& [* t
                if( output > 0x7FFF ) {
$ U' u1 Q9 R# O% P) e3 @                        output = 0x7FFF;
& ^0 B9 C3 C! X5 t  V. n, L' I" T) h                } else if( output < -0x8000 ) {
, `6 F3 s! s! `; N% u. H                        output = -0x8000;( y2 M' j0 C3 W" \) s8 I
                }4 l) @" j6 N$ B* p/ Z1 v
9 {8 t3 p% e2 Y8 w/ l2 _& N
                if( nBits != 8 ) {
* [% V% X' r1 ?! \! O1 T5 x8 f8 {                        *(SHORT*)lpBuffer = (SHORT)output;
, Y2 p! K6 W' B* |/ d( g- u4 b! ]3 T+ A                        lpBuffer += sizeof(SHORT);0 k& l) P0 q$ n% W9 N: J
                } else {  {/ {- y8 M0 |  X
                        *lpBuffer++ = (output>>8)^0x80;
! N6 I1 ?$ r. _* t  R7 `9 |                }
% m+ c  O  b* c+ m& V4 j6 E% _" G: l' W! _4 Q; H$ l  R
                if( nCcount < 0x0100 )
4 f1 B8 U! C! i) x                        pSoundBuf[nCcount++] = (SHORT)output;% z/ J! w+ I2 X

. J% ]" [( `3 D( h5 y* E' D. @//                elapsedtime += cycle_rate;% ~- K: |2 @9 h5 X: J% ^" b
                elapsed_time += cycle_rate;
4 U2 x: L' ^' S" N        }
+ ^* c2 _: b6 H4 d
7 t! ]6 z( _% b% c! `) N. S$ B7 S& s#if        15 d9 }$ s$ v, v  I+ @
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
( O; D' l  `1 `5 _+ G1 p% R                elapsed_time = nes->cpu->GetTotalCycles();
- ~. j) E2 \$ Z        }" o2 P, Z/ h/ ]
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {' y2 ?1 _. ^2 {& @
                elapsed_time = nes->cpu->GetTotalCycles();
% r$ r0 U! }& Z' F        }* T: L1 f8 t3 x5 ^" T* i' d  ]* v
#else
) i+ v( q3 V% m) ?. B: U7 h2 s7 e        elapsed_time = nes->cpu->GetTotalCycles();5 Y" o. T: p3 N( p0 e) o4 J* O
#endif- h- E+ `, J4 p& \" I' B; i
}& {/ {9 g- T4 c: T- v7 r. y

7 q7 i( R$ n0 Y" Z+ G! B// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ R* |5 }( u( WINT        APU::GetChannelFrequency( INT no )
, Z* S1 s3 M( a3 v6 v% |& A( @{
5 I+ {5 [% ^6 J' A+ ~' n  ^; e        if( !m_bMute[0] )
  O! c* {0 }8 q. f                return        0;
, b2 `: |$ {' G  h( o) _
8 R( C. Q$ [; f6 i- ]) W0 ]: L        // Internal
! L1 q4 U' B* m" w# f0 |        if( no < 5 ) {
4 k* X( g- k  ?( ^; D                return        m_bMute[no+1]?internal.GetFreq( no ):0;9 K& K9 s, \' S8 s
        }
! b* ?0 d( C0 M# b: A% r        // VRC6$ o& a) K3 @0 `( \7 B
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {5 ^& K  g5 M; S2 r4 X. h- D  n
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
. W4 z! [- J; ?& H8 F' z        }
9 c. E, [& I! [' l! n! b6 c        // FDS
6 |0 k7 c# x2 M2 h        if( (exsound_select & 0x04) && no == 0x300 ) {" x$ R0 }' x9 [. {" D; y9 N
                return        m_bMute[6]?fds.GetFreq( 0 ):0;% C$ P: \, `, K; x# E* c% Q
        }7 V; V- D; p" M* @: y# g; l" f; n
        // MMC5
0 j; ]$ P7 `  m, j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. S  f2 K& y/ [; x                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 O, E/ g  }- q5 k
        }4 w1 H- w% G2 {
        // N1068 r9 [$ m8 O' T/ r2 {7 z- u
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
* ]! Q3 F" t. \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;8 o, {# j; O( ?* u
        }" b3 L, A; R  {$ A# B' e
        // FME76 }: T& m1 n* U/ c! n, l- A% e, k
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% Z( a$ y# t/ E1 S6 n# V
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 e% X3 A0 [* ^7 ~: U, `$ _* c        }4 z) |  z; [& H+ }* X0 s
        // VRC77 y! y1 g8 I! I9 z2 {) g
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# A! \. l' \2 g. j4 ~2 H+ j                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 G) a5 T$ R( Z5 P2 K9 R
        }/ m( x8 i' v, m7 k/ l
        return        0;
+ e  H& E9 Q" ~! y3 a7 a}/ O  ?! Q# t. H# v, c/ @

; t; Z: T! R' D7 P  U// State Save/Load2 z. @& M4 E, c1 a( Z# @! o
void        APU::SaveState( LPBYTE p )" H; C& S2 Z& `# {' l' J4 c
{
* b4 k0 p. C: Z# O6 t; w#ifdef        _DEBUG/ e' o; L; v+ A: i
LPBYTE        pold = p;. \2 `* p+ ^' R" N* h1 g4 V. h6 n
#endif' b+ V0 p& P6 V+ ]2 ?& r& \1 \6 n9 S
; K! o& V. y" z9 H& V
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
+ ]9 S0 w; e# l5 N1 J- D        QueueFlush();! q& \' M1 g' \4 j& G. d; p
/ Q+ g) S; b' Q! y- s0 O2 r
        internal.SaveState( p );
$ v7 t+ r  b* H) ]5 A        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% E8 n+ }; y+ i# u; z# E' c
9 E& ~4 Q6 H# A. W, E3 r
        // VRC6$ U! Y' g8 s( M& S, E$ J
        if( exsound_select & 0x01 ) {
) e3 |& w6 p7 G                vrc6.SaveState( p );3 t8 o* Y" P- N; E9 r
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 q3 V3 u9 w& G. z0 v        }
0 ^. R- M' w: }1 z3 z% b# n2 B9 V        // VRC7 (not support)
% F8 ]' l5 e7 Z! f9 a        if( exsound_select & 0x02 ) {
6 b  Q0 d2 F, T" v: x% H# i( g3 P, Q) t& G                vrc7.SaveState( p );( R& q' i$ N- e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" O( B1 E2 o2 m        }
  k1 k( R0 O7 A9 ?8 \9 v        // FDS
2 G5 o! a# s6 h5 f6 j        if( exsound_select & 0x04 ) {
  c. L  i4 ~) ^                fds.SaveState( p );. z" [6 Y1 N  L1 d* g# A5 J0 h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding( B( J9 J: \6 }2 X3 l
        }4 X: V2 a. |% N+ s9 q. P
        // MMC57 t1 t8 E1 L2 h" g
        if( exsound_select & 0x08 ) {
& v2 \, T) E8 e7 P                mmc5.SaveState( p );
4 ^& t2 y! g) x1 \                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
" _0 k$ ]8 l/ z8 f0 X9 X        }2 O& s8 d% I2 m" a; i
        // N106, _4 R, L6 u* z$ G
        if( exsound_select & 0x10 ) {! h- d7 b5 d: _, ~
                n106.SaveState( p );4 j+ u( p% k0 l
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. Q6 H# Y- h" X, E6 a: R        }, b% y$ U1 X/ ?7 R
        // FME7  N2 |% V, Q8 R$ W' h$ s- g
        if( exsound_select & 0x20 ) {% l, A$ q: f% K# ]! {. r! G) j
                fme7.SaveState( p );
) L! _4 x( q9 \                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" R7 l9 `% D( s( v5 I
        }
! l5 \1 p+ [4 Y, s+ M+ }; A: `* V
#ifdef        _DEBUG
1 R* V1 l+ R& h$ i: MDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 z$ J5 S- m3 W: d9 z- L5 b#endif9 K3 Z) n+ V1 D7 l) s8 J
}2 @  j' P, M! d
3 ?: c+ v0 k  _& u0 p0 l+ `  x
void        APU::LoadState( LPBYTE p )
+ l# y0 Z3 q: }2 U3 g* v- ^{6 ]4 Q9 s8 `9 C+ A& y8 ]
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡/ n# f0 t3 g2 O3 f, B
        QueueClear();
5 Q9 [( }" J: k* A1 {
8 k, O: d) `. d$ u6 d# O; s        internal.LoadState( p );# N0 e0 h5 s' Q4 N4 }- }5 S
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, k( b4 Q$ b. \

. B% ^  n) D* M1 t, P) l        // VRC6; T& \* f/ o& A6 F1 k$ b+ F
        if( exsound_select & 0x01 ) {& N( C( B" s. A, I. M8 K
                vrc6.LoadState( p );/ x  ?% O, U, d+ G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding7 k! \- t0 d2 J2 Y9 z
        }
/ r6 o; g: s1 E! T- _        // VRC7 (not support)
4 k1 o0 j% H# s$ i7 u' J0 C        if( exsound_select & 0x02 ) {
9 {2 v- r- b8 [3 J* `* \                vrc7.LoadState( p );
  ?( F3 |6 A$ S; {0 j& u7 K' U# O4 u# q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 N: v) Y( I6 @* R: V7 B
        }$ G( r) k" d/ I% }
        // FDS
! T: V" C) ^& D& R; I        if( exsound_select & 0x04 ) {1 r) T1 _+ ?# \6 r* G# W4 Z
                fds.LoadState( p );2 ]: O4 Q! r5 ~) }$ A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ N' g; d8 ]% s* n' o" w: a
        }# Q$ R; i* n, `) x0 K1 |( A8 F: U
        // MMC5
: \( e- ?  w  K0 R+ i        if( exsound_select & 0x08 ) {/ I& l7 m5 _8 P
                mmc5.LoadState( p );
& k6 U5 j& ^3 L. F$ N8 |+ n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding$ J. w& L! `+ {+ J; X  @- [
        }
5 d; Y9 }8 x, y  W7 M) j. X        // N106
' k; _# `1 _/ P% W2 Q" N0 A        if( exsound_select & 0x10 ) {$ G$ s. j1 n$ G4 S; x. _% @+ V3 T. K% e
                n106.LoadState( p );
! r* W# P  `# B, C8 D+ y, \                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 z4 \6 [1 j" H% F& G* Q
        }2 K% q9 Y2 Z$ W7 g* r9 v0 H. r, q
        // FME7
1 ^& _1 U6 K: G9 T) w" V9 \* W        if( exsound_select & 0x20 ) {
; h4 n: q, c2 J$ I$ p- `# }                fme7.LoadState( p );. Q0 l  I% ]8 {
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 P  e. S# G6 ]4 O; l        }5 j/ [. W; f* w$ R7 r4 p% H  k6 d
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ ^+ ?5 G( K, H' P可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, k3 N  N; i0 \# Q' g+ x感激不尽~~

3 k8 P% t3 K: x( U  `' ^6 t0 K4 _恩 我對模擬器不是很有研究,
% J9 g* `! Y, R" |$ F4 N雖然要了解源碼內容,可能不是很困難,2 e+ _) f7 i5 k+ Y" K; B0 ?+ ?
不過還是要花時間,個人目前蠻忙碌的。
$ o( g8 K& F1 U) ]9 l$ W' X5 c. e+ d& j# A9 A0 F6 X  B$ t" i+ m
給你一個朋友的MSN,你可以跟他討論看看,# e/ _0 k9 P4 j+ S. A: A
他本身是程式設計師,也對FC模擬器很有興趣。9 C$ J6 U! U5 M7 [+ B2 y
8 p2 Q5 B% E" e: o7 J
MSN我就PM到你的信箱了。4 d6 p" n9 P5 R+ i2 Z
0 r% N. q# V, \5 p/ M: s( |5 H. W0 K
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
, ?4 @( ^  N' i' N- R呵…… 谢过团长大人~~

4 s# p( [+ H. v$ ~2 k( L% e# @7 U  K& f" N  b3 d
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 0 M3 Z8 [$ g; g# b0 B
团长的朋友都是神,那团长就是神的boss。

8 D1 M* o" b  x. J$ X: i哈 不敢當,我只是個平凡人,. Z2 Z5 t0 c( I  A1 W
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
/ W2 U" ]- Q" S( n- U( rZYH
) Q$ K& f' b& R( Z4 x6 @* h% m$ ^QQ:414734306
0 F/ m0 R3 C) B. ^, _) qMail:zyh-01@126.com
2 u2 w; ~5 C' q
$ J& [* ~! K+ @% n3 s1 M3 J0 g他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
6 ]" p9 R3 |8 ?再次对团长大人和悠悠哥的无私帮助表示感谢~~
, s5 C1 X# q$ m7 g
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 02:40 , Processed in 1.100586 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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