EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 z& e$ d3 B# N' C0 \8 S" ]9 c
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' p! q- F% J7 h7 U, }5 ]$ J这里有相应的模拟器源码,就当送给大侠了~~
4 F  O. x2 v$ D! ahttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 / x4 d2 k$ _0 X6 G& o- U
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 @, P" u) w+ [/ O. S# o2 C9 Y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' O; G, [* V' h# {  [# j3 E这里有相应的模拟器源码,就当送给大侠 ...
' D) \7 X  C3 p3 y9 M
聲音部分(Audoi Process Unit = APU):5 m4 y% ~8 ?: s+ U! C5 e, T( f, c
.\NES\APU.cpp
4 P4 \6 {) x  w9 H.\NES\APU.h1 `$ |! e$ f3 r4 N" @9 u; N
! |! s: M( p& _# C* ]" [0 U
; g  G) h8 J% J1 `0 |- T
影像處理部份(Picture Processing Unit = PPU):$ g6 N% h2 O* A/ t9 }; x
.\NES\PPU.cpp2 a, i3 X/ Q0 M  U
.\NES\PPU.h
. c; p. t" v% H9 p( W4 z
* G7 V7 o3 p5 M如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
. i9 n, m3 [1 S0 m2 |(由于很多专用术语和算法机理都不明白,所以看不大懂……)
2 Z" @, W5 c6 \6 r+ |. }' X//////////////////////////////////////////////////////////////////////////4 }  L" B& r7 |) Q+ a) q
//                                                                      //9 H" U& N8 ]8 m2 Z  r0 o+ L5 z/ s
//      NES APU core                                                    //
, |2 c" u3 D) i7 ?/ u//                                                           Norix      //
' A/ X# k  A9 M/ {) P% d. c7 y//                                               written     2002/06/27 //8 ^" g; q: R. \
//                                               last modify ----/--/-- //. t1 s, K; M% n; p& ]: F3 ]) ~3 f
//////////////////////////////////////////////////////////////////////////" \4 q$ w* W5 J
#include "DebugOut.h"
( E& a. n) w1 `$ T7 Y! K3 V#include "App.h"! y2 y/ G" c, E4 E# p
#include "Config.h"3 N/ h7 n/ m1 F( G9 Q& K
6 r3 n% z6 l7 B  k
#include "nes.h"7 e* d, D: Y  `) F, Y
#include "mmu.h"" e5 m$ F9 A2 k9 K! C  i
#include "cpu.h"
$ G6 Z8 [2 \6 n: _6 [6 H$ H#include "ppu.h"2 E, _3 a8 C$ b7 Q7 ]
#include "rom.h"5 Q' T2 W2 Z" t6 c' s9 K7 H
#include "apu.h"
0 ~, p7 i0 s! V  m& w2 F
0 O  i9 u; X7 [  U4 B  {; V4 a// Volume adjust& f0 J7 @) F4 P! M8 m% [  U4 N
// Internal sounds
4 q4 p5 x$ Z  y5 A8 g#define        RECTANGLE_VOL        (0x0F0)
  n( U& }0 R  r4 ^% ^3 ~#define        TRIANGLE_VOL        (0x130), r% I. A# k# n" {* f
#define        NOISE_VOL        (0x0C0). g. D) h/ i0 K  D4 C9 ~0 F
#define        DPCM_VOL        (0x0F0)3 o6 m) y6 [* ?
// Extra sounds& S! a" o) r8 s
#define        VRC6_VOL        (0x0F0)
; h0 }9 d% O9 i" [#define        VRC7_VOL        (0x130), ~; o! n$ l, b# B
#define        FDS_VOL                (0x0F0)
. S% i6 f/ l. ~* m& h  w3 a2 z#define        MMC5_VOL        (0x0F0)1 G' X+ d/ {& b. a  p) w% K. x
#define        N106_VOL        (0x088)
- C" }  v2 @( K#define        FME7_VOL        (0x130)
, t3 Q) |8 R% Z' I1 f
- z2 G# A# h4 W4 u% |APU::APU( NES* parent )) X' Z2 x3 W% w* J. t" `9 [$ X9 m# `
{" u* s/ P1 C& S+ o  b5 b. q
        exsound_select = 0;- y; p5 A$ ]4 c2 ~5 i7 [
) `7 Z8 p3 m$ d2 r2 N; Z; ^( @
        nes = parent;4 Y4 S, r4 h* t# h2 A! G
        internal.SetParent( parent );
& Y% F; i& x2 q3 M0 K* ~6 w0 y( B; ], }2 L) f: c/ c
        last_data = last_diff = 0;
) f4 K$ ?& A* e6 [" _* h9 f! s! B- u- Q' B
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 j  E: N. r. @" H2 d% J# J( r! S. J# @
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
$ ]: `2 a9 k6 T% M- t! J        ZEROMEMORY( &queue, sizeof(queue) );
0 d7 g% W. R" @: M: P        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 @$ _) A) M0 r( I' d: M

8 i( g3 U$ E8 O5 ]        for( INT i = 0; i < 16; i++ ) {
. O1 l: ]0 R# {9 S) V  h                m_bMute = TRUE;: m& r" I* s2 k- M- y- c
        }
; ~  J2 P) p7 L! a# x# L}
5 F3 e' y% n  K) H. N$ I2 e
: Z3 e3 ?: E% T: }APU::~APU()# R" h4 Y- H6 Z6 m; s6 {% b
{
2 S& g) u6 z" G9 ]}" m, G( j9 H8 x* j
6 u$ ]& R8 B+ e' |
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )7 G& r" @) S" W+ `0 p
{$ n! T  g# C* e: N9 p4 `, o
        queue.data[queue.wrptr].time = writetime;" Q" O2 B7 J- j, e
        queue.data[queue.wrptr].addr = addr;. u& T; S/ V' u+ s
        queue.data[queue.wrptr].data = data;. [  Y0 ~! {' _  P% W+ T) N9 j
        queue.wrptr++;8 S" y& D$ s4 L+ N& z6 O& g2 N
        queue.wrptr&=QUEUE_LENGTH-1;
& t1 `( A$ r, Q% z7 s        if( queue.wrptr == queue.rdptr ) {6 W) h8 t* q! F% m: t
                DEBUGOUT( "queue overflow.\n" );
. f3 w* }8 T/ s  C/ ~% q        }
9 I0 A+ e: b/ A}
( ]4 p2 m# [  }" p- U
$ G2 }! a' w1 f- i! G0 {! Y7 F' HBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )- `# r/ g- R  @: n) z
{
- T0 b5 K2 k! Z/ h: t( q        if( queue.wrptr == queue.rdptr ) {
* O) D0 s, F+ ?* j) v5 A' d                return        FALSE;8 J+ a% f+ J5 f/ ]$ d
        }3 t# R4 H6 M' \; S+ z& o4 Q% t
        if( queue.data[queue.rdptr].time <= writetime ) {* W2 w4 c& i: @
                ret = queue.data[queue.rdptr];/ X: L# d; M! [6 W  G
                queue.rdptr++;$ ?2 e0 ]/ D: d. h. c
                queue.rdptr&=QUEUE_LENGTH-1;
: s! Z8 s+ T7 {0 j* A0 r                return        TRUE;
! O# J  P& q- a% X        }2 w* P8 c" N7 K; q* r) b
        return        FALSE;
3 T- r5 y9 e" t3 k! X  V}
! r$ }( d; [9 ?7 r5 [2 @/ }4 K0 L6 c* J" d) \1 s0 s; r
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); o* B+ D: m# ^7 X6 ~
{
( Q9 A2 R. |& C        exqueue.data[exqueue.wrptr].time = writetime;
8 Y9 K# p& \, e" G+ P        exqueue.data[exqueue.wrptr].addr = addr;* g! l: j8 v; t& ]# Z- D
        exqueue.data[exqueue.wrptr].data = data;; F* g7 I& Y9 X3 B) e
        exqueue.wrptr++;. F2 z+ u' a  \  h- @
        exqueue.wrptr&=QUEUE_LENGTH-1;# h7 [3 @8 a" u: d; ]8 r
        if( exqueue.wrptr == exqueue.rdptr ) {
; F- s( B$ X+ M3 a' @                DEBUGOUT( "exqueue overflow.\n" );
( q- E) K/ N3 j) N$ d* }        }$ u1 m- ?# z! R' ^
}
3 R! v( B6 O. k7 E1 A
* t% s1 Z+ F. @- K; Y/ b8 |" z& ~BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 @; I' `1 M" `; s+ u
{3 v% _0 k! X$ N2 w" o. T. ^8 x
        if( exqueue.wrptr == exqueue.rdptr ) {
5 j& h* T3 b+ s/ e8 i6 I                return        FALSE;
- r' O. x- B4 }        }  J8 q! D. l9 W  L( ~1 e; G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; }, t9 f8 o$ v% C. G- k
                ret = exqueue.data[exqueue.rdptr];
; z3 j% X8 X4 l: u                exqueue.rdptr++;* }4 }+ w' a5 O8 ^
                exqueue.rdptr&=QUEUE_LENGTH-1;" L* A( k5 O8 {% s' j# y4 P
                return        TRUE;
6 \8 q- M; b- B        }. \/ c/ ]0 U' X4 G1 K- L
        return        FALSE;1 x( Z9 O* `2 l1 B  X  n, j3 L7 r
}+ L$ |! L- B: |" b% r6 ]
' d, c3 j- e8 ^& I$ T" H9 H
void        APU::QueueClear()
- Y: t+ ]2 ]% q% ]0 b, e# j1 _* v{, I" X5 L. P0 w$ m2 O
        ZEROMEMORY( &queue, sizeof(queue) );
# P, n- u" ^, k2 _! n+ H        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 [' X+ |7 N2 R( C- S  Q: k4 N
}
' l6 N: X' P* Y$ _! N/ r  Q4 _+ A$ [
; |3 y' C% B5 u; g: Hvoid        APU::QueueFlush()
1 {- ]$ Z: L& o6 }( o2 _, T* V{5 {: m% a% F8 H0 U+ L
        while( queue.wrptr != queue.rdptr ) {
$ B# U) X1 |" C( J: Y  `                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
' t' K. s8 q- C1 ?+ G                queue.rdptr++;
; Z8 c9 z, E  i) Y! V/ R                queue.rdptr&=QUEUE_LENGTH-1;
1 d5 P9 C2 p( m1 W9 M7 G# F        }) \# l4 M- l' j9 e0 l4 v2 ^' r

& F6 |$ a% S; h- @$ |% |        while( exqueue.wrptr != exqueue.rdptr ) {/ k, P! l/ M+ h- Q
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );/ ]7 b, z: E) f! q9 d
                exqueue.rdptr++;
- ~" b! d8 x8 I: y4 d6 U3 e- _3 P                exqueue.rdptr&=QUEUE_LENGTH-1;9 ^4 C* D; x1 Q
        }
& E, T; y8 P+ E, W4 X# Z& \}9 G* D/ Q) N6 I' c* ^
. }, q) z( r5 i# n. p3 S
void        APU::SoundSetup()
/ i# ^# p3 W/ N+ k& }{
+ ?0 D' |, q5 ^$ T        FLOAT        fClock = nes->nescfg->CpuClock;
5 Z4 P) o- S& {        INT        nRate = (INT)Config.sound.nRate;
1 x$ ^9 n; _  x, }- p        internal.Setup( fClock, nRate );
) G+ E1 a% @  d1 r2 @        vrc6.Setup( fClock, nRate );4 ^( P/ x/ n  z3 I
        vrc7.Setup( fClock, nRate );4 b! @( k1 o6 I# H
        mmc5.Setup( fClock, nRate );" p, G. D5 Q, D, ]  _: A! |
        fds.Setup ( fClock, nRate );4 }5 W8 G& \- Z9 L
        n106.Setup( fClock, nRate );) U7 K8 B1 T3 I0 v' B
        fme7.Setup( fClock, nRate );% {& K3 f4 x' u3 Y7 [: U% _  C1 A% F
}
$ j4 k! [* P/ P  W% k$ {$ i' {$ X  P: P: B7 n/ r- m& H- J+ J
void        APU::Reset()1 I0 h( `; V9 C+ T
{& A9 A7 {+ t3 j4 x: Q& u: b
        ZEROMEMORY( &queue, sizeof(queue) );
% Q# @3 d& y+ ~5 g( F9 w" r4 }" N        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 L& \& k' _$ }0 t/ y) n

# q2 q* u8 M; k8 J% P$ w2 C        elapsed_time = 0;
; X$ L* r( w8 a8 c6 F. o8 V( l% Z  p# ~* m' Z
        FLOAT        fClock = nes->nescfg->CpuClock;. Q: ~3 g* S1 y7 H) k9 n
        INT        nRate = (INT)Config.sound.nRate;: L$ w6 G! O: a1 o' P
        internal.Reset( fClock, nRate );' m6 ]' t+ O! [* V( T' y6 j
        vrc6.Reset( fClock, nRate );8 k! e- D+ Q- A" V3 U6 P
        vrc7.Reset( fClock, nRate );4 }2 {( Q* i6 v9 ^" X' h0 u% f
        mmc5.Reset( fClock, nRate );
/ N% O& L6 t2 R6 l' N. [        fds.Reset ( fClock, nRate );  P' ?! Q1 i9 l2 V
        n106.Reset( fClock, nRate );
+ K' I. w* ?' c# p, A: \        fme7.Reset( fClock, nRate );
9 W( S) `$ Q/ f) M5 C% \
% n5 n% I7 K; q% n) r        SoundSetup();
8 V6 }" _" `$ a) s3 z' S5 E* T}/ y( `* U( Z' |4 Q7 D

- x. b! o6 ?# ~+ a  X9 `& A* b# u- ?void        APU::SelectExSound( BYTE data )8 a7 L, K/ f( F: w( }8 V
{
1 C# t- u* V; P- o$ m7 b0 H        exsound_select = data;
! u7 f6 K! g% X! t* ^}
! F% V: H, T& [
0 z, P* n! J8 t; T) ]BYTE        APU::Read( WORD addr )
  c. E% Q  u7 Y0 W  v' w+ O{
, ]' Z* {  {2 t        return        internal.SyncRead( addr );* ~; `8 T, B- O$ \
}
- J) V/ u, I7 }# b% F/ ]) ^( r  }1 x6 k$ P
void        APU::Write( WORD addr, BYTE data )$ h& m% W  }  X7 V  S" L
{# {4 _0 F6 i. s
        // $4018偼VirtuaNES屌桳億乕僩( W% A8 ^9 M" }6 [$ p) S* D, Z
        if( addr >= 0x4000 && addr <= 0x401F ) {
, m( a9 G3 V+ k& S7 }' `- T. G. D                internal.SyncWrite( addr, data );; Z5 I% `; \4 _; L4 w+ i6 _
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );$ C, S% R) f  e$ Y4 }
        }
8 \/ @% ?% T5 K" W7 N; K}* l& P+ d1 z" N; F/ x
* O4 `& |; w; Y) T* W) N( p! ^
BYTE        APU::ExRead( WORD addr )
. z* P0 R4 m" I2 Y{
* {+ G3 u9 ?: p2 n* CBYTE        data = 0;
6 y! M! {) m$ S( k: |1 ~' h3 e9 Z; y) w9 z( Z3 X; L
        if( exsound_select & 0x10 ) {
0 E9 f# t1 Y' }- O. s1 X                if( addr == 0x4800 ) {' I: C! x8 l6 F6 E3 {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
& }, R0 N! i: |& r  s; P                }4 S% B- L# q! g) D8 F
        }
+ X4 s5 w; c" E: U/ N        if( exsound_select & 0x04 ) {: `" X& I" |. _; P0 A
                if( addr >= 0x4040 && addr < 0x4100 ) {
" X; }8 g" m3 L. v: e/ y4 M; [                        data = fds.SyncRead( addr );0 H) T. z: U4 I( H7 V" }5 {
                }
1 C9 o& |6 ^- I: y' Y6 S- c        }6 _7 t/ r( P- J( N
        if( exsound_select & 0x08 ) {
3 [$ L" O- l9 _; p# J+ n; r                if( addr >= 0x5000 && addr <= 0x5015 ) {, z* s+ G0 y! T- j
                        data = mmc5.SyncRead( addr );. R, G5 j% |9 I8 B( ?6 X2 [7 o/ d
                }9 R2 m6 n& G) L4 |0 r. l
        }8 c- q" r7 p6 [; `
2 |8 ~* @: |2 a' f; E! S
        return        data;
, @3 ~% M( I# P1 r9 U}. `' ^7 i& D$ O3 e, W7 M1 g1 m
0 X! X. n3 x( a) l( S
void        APU::ExWrite( WORD addr, BYTE data )
! X. b3 t" T, |  z: b{
4 z" z# U6 S# d. z7 D. s        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );+ F  A$ P3 ~# [% b) I
1 w, C$ \: V" o
        if( exsound_select & 0x04 ) {/ i- H% L8 O" h" ]
                if( addr >= 0x4040 && addr < 0x4100 ) {
5 E, |& I. q; |: `                        fds.SyncWrite( addr, data );" H( _! y* J* u- M
                }9 R  B( N0 `: r% _) i
        }
8 W2 w' R* y! |2 [% L( N1 e8 n# z- c( L0 H% l+ J
        if( exsound_select & 0x08 ) {
2 `' W$ x' V" [+ O0 a; G                if( addr >= 0x5000 && addr <= 0x5015 ) {
. b/ u+ J2 X1 U1 k4 [                        mmc5.SyncWrite( addr, data );
" b1 X1 ?9 ~5 ^# ^                }8 |8 U6 _1 P4 }1 M2 Y
        }6 v  O9 c4 h: x2 I5 {  r: {' e8 q# r
}
) c; Z% j7 x0 }' ?  ]8 q- ~5 F/ w( T  Z# L0 S8 _
void        APU::Sync()4 G1 K5 B8 {0 L2 s4 y; P
{
: U7 N2 B/ p6 r  S8 M/ [2 V}/ F4 {  B; ?$ b2 F
* i8 M6 v( v, T# A% V
void        APU::SyncDPCM( INT cycles )- _5 o$ M' O% V* ^; [
{
) w+ e: J, \0 e% t) \+ {/ Z        internal.Sync( cycles );
& d1 x- B4 W6 `# k/ ]' L! ^6 J  X: s' {/ e; T
        if( exsound_select & 0x04 ) {& D7 Z, ]7 X+ q8 F6 M1 i
                fds.Sync( cycles );
" Z$ R! ^1 ^4 E% C% F* d0 T; }        }: Y# R5 Y1 l  J, }2 i, |8 e" i+ h. Y
        if( exsound_select & 0x08 ) {2 [9 K! ^3 a1 q3 e) T3 }3 v$ C
                mmc5.Sync( cycles );; L6 D3 t3 X: E; L- R; M
        }
( m4 L) E. d6 e% {" @  V- [4 s! V}4 u) t4 O0 j: X" P
5 w$ Y9 U8 [. ^& b. `
void        APU::WriteProcess( WORD addr, BYTE data ). K$ m3 q" Y( d; C4 ]( \" @' F
{7 c4 \; @5 [# S" c
        // $4018偼VirtuaNES屌桳億乕僩+ D+ D- c* K; B1 S2 W7 Z" z
        if( addr >= 0x4000 && addr <= 0x401F ) {1 x, k% Y3 H( V
                internal.Write( addr, data );
; o4 x' v7 H, @. x' }        }& W3 x) `6 x9 x( ^; q
}! z6 _* b/ U% u- u4 s1 b1 Y7 m0 j

' H' w4 Z0 n' {3 U5 Xvoid        APU::WriteExProcess( WORD addr, BYTE data )9 Q8 A2 I6 y9 f  h
{) l& e$ p7 O) b" N/ F0 N3 s
        if( exsound_select & 0x01 ) {# g9 H) C$ v/ o* r
                vrc6.Write( addr, data );0 L5 ?& S9 h8 V
        }1 k1 E1 s/ ]+ Z8 Z7 w
        if( exsound_select & 0x02 ) {' Y& D, Q* Q9 G
                vrc7.Write( addr, data );6 K7 c% w8 v9 f' p
        }
" r, `9 M, c3 U. D; J; |6 N        if( exsound_select & 0x04 ) {
0 c! H4 X# R( \5 o- T                fds.Write( addr, data );6 E9 ?' B$ D0 K7 H- e
        }
9 F) u! S6 J0 v2 N2 `1 P& {4 C0 Q+ c0 C5 @        if( exsound_select & 0x08 ) {& m, p, p: I5 E# Z- h& a
                mmc5.Write( addr, data );
0 Q6 g0 P8 I9 x2 ]( \9 [( ]& ~8 G        }
9 m  o% A3 Q: E) ^# w- R# S/ H        if( exsound_select & 0x10 ) {
  k( [/ O( O$ ]                if( addr == 0x0000 ) {
# r; g( S( \; G. P1 R3 l& y                        BYTE        dummy = n106.Read( addr );0 A- p$ |( r7 N
                } else {
2 {# @9 ~! N. `9 A+ b/ l) K; v                        n106.Write( addr, data );
9 }+ {2 b( g+ J5 s- }& T4 o) y, W! s' k                }
$ @! o9 H& I% Q! B, R$ A# f$ ^        }
" X1 v& X. q- T8 {7 N# ~% t, o" Y, q        if( exsound_select & 0x20 ) {6 [& u  D( z! A- P  H" E6 G
                fme7.Write( addr, data );
; A2 f9 f  t4 Y( a, L  V        }. X: c# D1 {/ n5 J
}
' O# k$ v7 [# S/ o0 R# n$ a7 D: x0 x% M4 r. E
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
  U1 h$ J' I* `" d  U6 C5 s{) W- Q: s, T9 L: @$ v" y
INT        nBits = Config.sound.nBits;
! ^& F8 I; a* nDWORD        dwLength = dwSize / (nBits/8);
' J, G4 _7 c- KINT        output;
  @) n, g, M' f. IQUEUEDATA q;
4 X! ^3 `2 y* F7 EDWORD        writetime;
7 z5 \) f, r. `' n9 B1 ~
1 p- e! n  [5 `) S- FLPSHORT        pSoundBuf = m_SoundBuffer;" F" P6 T1 E5 K5 |
INT        nCcount = 0;: k" j8 N2 T# I/ i; }8 G
2 H. U9 K: A0 p& B% }4 \
INT        nFilterType = Config.sound.nFilterType;) L& o* c% r% F$ t

4 N- [6 W. k; t- w+ T" n  c        if( !Config.sound.bEnable ) {- ~9 j; Y  b3 b0 K
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" s/ H: {1 `, r, R" R                return;
' ^2 y  r2 m+ ~        }+ J5 V! s% ]2 s7 h& y5 ?$ ]* w; J! {; t) g

. E3 e& P/ A2 D- Q6 T) V/ P        // Volume setup
' p7 S2 M9 m, ?% t; f/ e& |        //  0:Master1 W6 z2 F, U3 ^4 g( M, D$ {  i
        //  1:Rectangle 1
& t: I" r6 E7 n, H' \        //  2:Rectangle 2
8 u" ^1 e" ^# w8 T8 t& p( H! L& P        //  3:Triangle
: ^6 j, W' @, L+ U7 _        //  4:Noise
' F" r! i% S; n4 Y3 ~% S( x5 X        //  5:DPCM
' V& L" u: F% M$ A& |8 R        //  6:VRC6# x! K" E6 z) k* G) ~" H) q; y- @1 m
        //  7:VRC7
0 V# z1 s, V" |7 t$ N& {) S        //  8:FDS  Q7 A+ J: F5 {
        //  9:MMC5% y' n  V5 N9 ?& D# e" B! U
        // 10:N106; N9 _& H* L" t9 Y4 \% ]
        // 11:FME7
7 a; ?+ b0 F7 V# u) ~, r4 V        INT        vol[24];
- |* f! j+ }8 D" ^3 |        BOOL*        bMute = m_bMute;  U4 \" o6 k, q
        SHORT*        nVolume = Config.sound.nVolume;
, }9 K* Q/ s, \3 U+ u
$ c5 u$ I9 r- m4 W* _        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
; A; U7 V  N/ r: s+ g
' u6 T. Z* N# v; w3 h0 `5 y        // Internal9 ?* }( |4 _* H: I0 U3 b! |8 R0 D
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
# j2 a, u3 ~  R        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;: j! ^0 h4 S1 W8 ]% a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
0 ~, n9 ]& U+ T2 T" z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;2 G: A+ a/ X2 q9 O, Z6 L
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& l  v8 A" @! Y/ g' _5 Z

  [; m7 I- D* P2 }3 d2 N- k) b        // VRC68 G1 i% Y0 I/ T# k+ |2 F
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' T% k3 D" J/ N5 Y        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" j" z- ]( T, @/ p        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ v- o# w8 o8 [4 G1 s
$ `% T4 m4 v  \' W( M        // VRC7* V( \7 g; U7 V1 w/ s% ~6 d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 u7 v0 }: n7 W6 B2 S! I. S+ }9 t, P$ @; f9 ~; m
        // FDS+ c/ T, T) I4 G  v& w
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;2 E0 y3 H0 B5 u+ P5 H

* d, J  w/ }5 q: x! ?        // MMC5
7 g; M$ Z9 }3 ]: s6 |- E6 g; c        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 N. ?% q, R" I$ {1 D! x" ^/ f  w        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( T$ G" b6 n# t6 e2 C. h        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 X/ v$ n1 z# ]9 t( K* O& I6 L

6 [4 O4 M- x7 D        // N106& H. q; J5 A& n! K. x0 F
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. V. R8 i$ m" e& J        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  \9 ]; `! q. G8 X        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# V3 y( H5 a) k; n+ X/ y; @
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( \5 F; k2 E+ N1 e! \9 m8 l: J        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( f# X4 l% K8 C  R! J
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 ^+ C2 {) e( @6 H! a
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" w+ t+ v7 j5 K: w2 W$ I        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 q/ B8 Z7 t7 B: I3 s- l! b' K1 A0 m7 B& R) [: B4 g: [3 e4 K
        // FME7
- b" Y7 R, U5 z        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 s" _6 E6 e( ?
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 @( X; n2 M& {$ c- f' k. D' q" @+ ]- y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) F# @) x4 O) R2 w2 K6 t# o) C  X2 r/ J
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;5 r9 ~) h8 L* g+ w
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;! o( {; f9 a; w
# k; m! [6 v" P, l5 m
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
6 b/ m( g5 A6 u4 a8 y/ F% D        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
, a' G+ g2 n( t+ B& O                QueueFlush();
' x6 N* P  Y& N8 _! E/ H/ c        }' t# i6 i+ ]% l
( V' _8 F+ t" M: B( B7 F
        while( dwLength-- ) {6 P7 P8 e. y. A, M
                writetime = (DWORD)elapsed_time;
% U3 ~* f+ N1 W: }1 K- A6 ~8 Q+ j" P  N
' O; C: J$ [: j2 G                while( GetQueue( writetime, q ) ) {2 Z& f! Y+ o; _1 ]0 w
                        WriteProcess( q.addr, q.data );
9 ~0 H# l% |9 ]; s8 s" g                }+ r# E4 r' b& y0 o; V

" V7 D9 G7 Z4 E2 y4 Y                while( GetExQueue( writetime, q ) ) {
, R' h: Y- K: b) B( l, i                        WriteExProcess( q.addr, q.data );4 l$ h* ~* V, l2 R7 O
                }( h8 ~1 b( @( N8 M0 V
6 a( ]6 j1 M5 o! K* |
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7  E% a" M2 ~$ u8 i; Q( f$ i
                output = 0;1 i  f/ ]8 E8 y) ~6 i+ D" \
                output += internal.Process( 0 )*vol[0];
( Y' B: [) N5 r3 t$ X; T3 o: p0 e                output += internal.Process( 1 )*vol[1];
# o% f2 d' u+ ?2 F                output += internal.Process( 2 )*vol[2];
' q4 C5 L! J! W' Y0 [! ?                output += internal.Process( 3 )*vol[3];
" J- z. H# y( I                output += internal.Process( 4 )*vol[4];* H8 a$ H" M5 `4 ?

0 H2 D4 f# ?- x( C; w) ~0 D6 |/ H                if( exsound_select & 0x01 ) {* A" U$ l, h+ w, J; w4 L
                        output += vrc6.Process( 0 )*vol[5];
9 z. X& u( [) q+ J                        output += vrc6.Process( 1 )*vol[6];5 h* E3 X& F9 H% A& L, F) [
                        output += vrc6.Process( 2 )*vol[7];# ?+ q3 v  m3 h$ r) A" p$ n7 |# e
                }+ n' O/ l5 J2 _1 R. N3 U
                if( exsound_select & 0x02 ) {
8 T* }& m. `8 I9 m                        output += vrc7.Process( 0 )*vol[8];6 u' _4 ~+ L7 A7 w2 t* D
                }
! a0 _  I; H0 G$ u0 V/ f                if( exsound_select & 0x04 ) {
: m: c+ Q7 a2 v1 u                        output += fds.Process( 0 )*vol[9];5 T" P2 o! B& W' d+ a, z
                }6 q# u" O4 b  }5 p: m9 w8 Y' A
                if( exsound_select & 0x08 ) {/ b4 y4 n! _7 k5 C1 ~
                        output += mmc5.Process( 0 )*vol[10];7 r& ^$ [" N8 z4 h
                        output += mmc5.Process( 1 )*vol[11];9 j+ @* Y0 g- T; A& Z( g
                        output += mmc5.Process( 2 )*vol[12];; }  r+ I8 p! k* h1 D5 B! Q
                }, A9 m- z4 y- s, X# o
                if( exsound_select & 0x10 ) {
9 y, N5 N' P# }4 Y' e! x8 E  N                        output += n106.Process( 0 )*vol[13];* N  C. ~1 N  C1 P, M
                        output += n106.Process( 1 )*vol[14];
4 H! C9 H& {$ N9 d  y) d# l0 c4 o. |                        output += n106.Process( 2 )*vol[15];* H0 Q/ _  C; s/ w& v1 T4 G% q) k" s
                        output += n106.Process( 3 )*vol[16];, u9 k7 q" k6 a% \9 X
                        output += n106.Process( 4 )*vol[17];
4 z/ c% z% ]0 Y' j9 X                        output += n106.Process( 5 )*vol[18];
! a( F* k2 A, W7 e7 H" r                        output += n106.Process( 6 )*vol[19];- C" d  R( a1 n& Y
                        output += n106.Process( 7 )*vol[20];
0 S; V/ r! q1 w9 F. y. r8 v                }* @  K0 v" {( q% v* @
                if( exsound_select & 0x20 ) {
, L/ J7 A% C! K; c                        fme7.Process( 3 );        // Envelope & Noise
2 L& r* t% Y# J) I# o                        output += fme7.Process( 0 )*vol[21];% T& H& N9 ]& W  Q: E
                        output += fme7.Process( 1 )*vol[22];- x) C% z" n1 h, Q2 v/ @2 t; C
                        output += fme7.Process( 2 )*vol[23];
( }( k3 s- n! I% f" \& N                }( b* b9 Y6 p# ]8 I, L( V
, `0 O. W, {4 f" B( ~
                output >>= 8;+ _0 |4 e' E  w8 r7 l7 C1 t& C; u
5 O- {" y, t0 G! [% y/ x
                if( nFilterType == 1 ) {
9 C; _; T/ ?8 g" o/ D3 c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& T- O5 Z5 h! r+ G" K) Z/ j                        output = (lowpass_filter[0]+output)/2;; ?6 C2 ~% ~" H7 b* |' E
                        lowpass_filter[0] = output;* _9 r$ v6 J8 K
                } else if( nFilterType == 2 ) {5 R! E3 @- p3 j9 k6 f/ m2 ~$ W
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 T, ?( i0 w; z5 q5 |( U$ J
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 d' b( S' ~. e4 x# P: Y                        lowpass_filter[1] = lowpass_filter[0];
( ?7 V, n, }3 s7 X! U0 A                        lowpass_filter[0] = output;+ T1 F- @" w7 a, m' G9 [
                } else if( nFilterType == 3 ) {
  c4 A$ j0 m. h$ O0 O; U                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 M! q5 S; V5 {" O                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
$ }% ~5 B4 q8 A3 _% Q9 `7 t+ \                        lowpass_filter[2] = lowpass_filter[1];" H4 ?) ^0 }; O8 e( y- ~2 E& g
                        lowpass_filter[1] = lowpass_filter[0];( n$ ?* @: o& d  n2 S
                        lowpass_filter[0] = output;
5 o1 |6 _- Q6 t5 s                } else if( nFilterType == 4 ) {. Y9 Q# H7 r5 w! O# s% a5 e
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- R3 C& L1 u( b+ d                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* _2 v/ V; Q9 W' b+ f3 ~" ]% |" @9 V                        lowpass_filter[1] = lowpass_filter[0];
! `$ T# \) [- O, @6 n" N) V0 k                        lowpass_filter[0] = output;  }1 e2 y# o2 Y, |9 N' Q( E
                }
$ m: t* j( n" G( v7 X7 g
* i' [6 @9 k; {; Q! D( q, ~+ a#if        0
/ ?/ q8 s9 f& L% B2 V& `                // DC惉暘偺僇僢僩$ _# p6 B" T; z6 {  S1 j* z
                {1 A% r# a. J+ y1 R% K
                static double ave = 0.0, max=0.0, min=0.0;
7 B' e, L! y1 P                double delta;
; M. B5 u7 b5 S1 S1 G                delta = (max-min)/32768.0;9 w0 t7 \# t+ m' H' i+ _6 D
                max -= delta;0 q2 s" N) U  l; p
                min += delta;
" k9 Y/ R  t/ k- J( B  y7 X9 m8 B                if( output > max ) max = output;: m; Q% x7 o$ ]7 d  C
                if( output < min ) min = output;, V- U! b  p" z# F) i
                ave -= ave/1024.0;0 O; d7 k8 A7 f
                ave += (max+min)/2048.0;
7 K+ t( t  k; Y) P* ]+ S. x: F                output -= (INT)ave;7 b3 ]+ L1 P* s1 t. K
                }3 e/ @, Y6 d! [. t
#endif
5 w4 B, Y  l6 f" ~4 B#if        1
) Q. T/ Q) |7 E9 ~1 {                // DC惉暘偺僇僢僩(HPF TEST)3 O1 C) l# p* ~5 ]' q7 T2 r3 _
                {& Y+ c, c, \/ d. e
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. \* k1 {& X: H0 p
                static        double        cutofftemp = (2.0*3.141592653579*40.0);% h( H# m: h4 e
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 E1 O% \5 p1 y! B: g3 N                static        double        tmp = 0.0;- S* I2 G1 w; [* `) z. S- ]
                double        in, out;
7 ?' y# K+ W3 ~3 T( k+ Y
9 l3 E( g& u+ G5 c! M; I                in = (double)output;
5 a& n" b  }& q5 g6 G                out = (in - tmp);8 M/ t2 s2 |; c4 ~8 @8 ]. e$ v
                tmp = tmp + cutoff * out;' ~+ U7 I6 q+ H# R# p

1 U3 p, h  g" L9 n: D8 p0 G. I                output = (INT)out;" I$ R  v+ d4 U  }# o* c: C
                }
$ e  r9 k' L6 g#endif
3 D7 ?' A- D" g% ~& T/ P, o# H2 y6 Z#if        0
, Z; A1 G. ~! ^0 t+ e                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
2 P! ]# d3 r3 a( M                {
% v6 Q& ^3 Y* F" t, G* ^                INT        diff = abs(output-last_data);
6 {& u' k* G; \                if( diff > 0x4000 ) {
5 {6 {5 q1 x0 i                        output /= 4;
3 T/ ^+ O; u% J, N5 Q2 p6 ~6 N' u                } else
; P3 u! {5 m9 B                if( diff > 0x3000 ) {$ C7 Z5 z8 u3 s7 k5 i
                        output /= 3;! w2 k2 `% G! G2 C2 j* ^
                } else; j9 f( i5 n$ X" Q9 k+ Q3 l
                if( diff > 0x2000 ) {8 M4 b0 T/ ^' J9 A9 W4 w7 K6 [
                        output /= 2;0 ?( x! p* {* i- ^6 a
                }
/ H* {& {$ U- ^( J/ Y                last_data = output;+ [" l1 @. X0 f& k
                }& c; e  c5 g- @
#endif; t' ]0 n  v; w3 j) x0 d5 k
                // Limit
+ k0 A+ l( a& n                if( output > 0x7FFF ) {
* H9 Q/ h' p. |4 z$ P2 x                        output = 0x7FFF;. _6 \" ]' \* d% _$ x% D
                } else if( output < -0x8000 ) {
. \5 }: Y. Y8 x. P- H: l& g2 R' M) K                        output = -0x8000;
) Y, k: d: t& p  g                }2 c3 S1 o: I2 D" h& ^. w
' ^2 Z8 }* T: F* \
                if( nBits != 8 ) {1 t7 g' z& Z" e) J5 w* u
                        *(SHORT*)lpBuffer = (SHORT)output;
! @, c9 {+ {2 f& }! i9 K8 N                        lpBuffer += sizeof(SHORT);& w' I1 Y8 _% c# q& W# B
                } else {% x5 ?) c( F! F
                        *lpBuffer++ = (output>>8)^0x80;
+ x! m' u) ~0 J0 r: s                }" j/ M% T2 r0 a3 o, M

5 @1 X7 N. T' X1 \) o( |$ ^                if( nCcount < 0x0100 )
) |7 X) V, U' J! k2 Q- w* ~                        pSoundBuf[nCcount++] = (SHORT)output;5 x% ^+ u/ ]7 o

3 S9 R! K: a0 U2 e8 Z//                elapsedtime += cycle_rate;. \* q6 x, z. [, z: U# }
                elapsed_time += cycle_rate;% D4 n$ z" i4 d! g5 S# i
        }
2 u) ]( X2 P* Q* R; Q  U
4 t. k9 ?1 k4 `0 A# D" G#if        1: B* v5 S2 a! E
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {4 p! H4 t! M% @
                elapsed_time = nes->cpu->GetTotalCycles();
$ o& X$ m1 g3 w+ O; W        }* H* e) m5 d8 B8 _4 I1 v6 U
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 g/ A3 x" o3 g# W                elapsed_time = nes->cpu->GetTotalCycles();* Q$ w  l. l" k
        }
3 H, J. O8 w" E7 x  A2 P6 S$ L: L  n#else
$ U! v1 E  T8 P$ g1 O        elapsed_time = nes->cpu->GetTotalCycles();2 B- K* L$ U3 @5 K6 {& s
#endif6 l- |% `6 K2 n
}
$ r4 Q6 ]6 ]/ u5 Q9 }  T, d
5 g" J7 n+ ~6 O7 y9 a// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 g! d( I$ _# Y5 s; }" |INT        APU::GetChannelFrequency( INT no )
: S  y3 x' A5 c& y2 \, `4 U{5 F6 P( u7 F1 j, ^8 g# C
        if( !m_bMute[0] )% i2 J# q. U! N3 B- H
                return        0;
0 U( Q( M0 v' Q: e3 e
) O8 E. d- I' G# q; t        // Internal
. q: r+ `) w2 m' e% W9 B! Q        if( no < 5 ) {
* A9 e; Z# A8 P, b  k: D3 H- w                return        m_bMute[no+1]?internal.GetFreq( no ):0;
3 C' ?3 W$ l' R8 X        }4 K1 I+ c1 W" _% T0 {. N
        // VRC6
; D; D- q& |( z( G. j3 ~        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {8 j3 Z& k% Q5 l) [0 u$ S$ D
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
3 b1 J# v+ R8 g        }1 \0 v$ j7 {3 j- n9 j5 W- K
        // FDS
8 j# F2 m# e& H( X4 `! @# H        if( (exsound_select & 0x04) && no == 0x300 ) {
) B, S- A2 p1 `                return        m_bMute[6]?fds.GetFreq( 0 ):0;
) b! K: ]; x) g# v        }' m" i3 r  F. `
        // MMC5
2 l& B0 e/ y7 S        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
0 u  l. g, M& e                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;& o8 {2 A: m* o8 z8 d9 V8 W
        }
. v- [% v6 s9 `9 e        // N106
( Y7 V" l7 B. v( w; |; c- L& L/ ]        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {3 C' O, `# r) |+ s! J# ~1 V  ?
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ q% ^6 i0 `, |4 Q* {$ h# q5 [        }
6 n; b* ^, r+ ^( ?/ |        // FME7+ `( S  ^( X: t4 W9 g4 Y7 B  r! s
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) l% J) j8 n$ U9 |2 D+ S
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
% l, \5 X$ P  A6 p# z9 \% }        }9 ?# |# Q: C5 y) y* f, d! O. S
        // VRC7
& l, S! K( s+ F) H- D6 K& _        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
7 F$ m8 g4 G' K7 n4 V9 k                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
* y. L. D: M9 k        }% u! h. y! j8 U" @+ g
        return        0;4 G8 z! e4 e; F+ X" \
}
8 f& B0 H) c' r1 `7 h! b( E
4 t2 x& c) w. L4 P// State Save/Load$ M0 T- ?6 e) T8 i. t$ R, s; y
void        APU::SaveState( LPBYTE p )
* a2 E* D" t0 V- v6 }: m' x5 e{+ K5 l2 k. T! c0 b; l
#ifdef        _DEBUG
. m5 C8 X3 m+ ?& z' nLPBYTE        pold = p;
9 h7 o  o6 P0 I2 q/ P- ^#endif3 q5 P- K9 x6 |0 x; V: c

( O1 ]8 f4 u; o9 i# N6 t9 `        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
, L2 z' C6 T/ t* Q        QueueFlush();
' |; O, E: K! S! H) N5 X
0 ]1 N2 Z6 j/ H8 u! T: l" y, A        internal.SaveState( p );
# h( r" f9 R7 i) ~0 h0 S: a; N* A        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 g& K6 Z% }# R$ s$ y

9 ?$ K- Q1 c4 ~2 `3 R) }        // VRC6
. D1 L7 v% m0 j: w& ~        if( exsound_select & 0x01 ) {
5 B( k8 J# n2 K                vrc6.SaveState( p );
! W8 {3 }* Z8 J4 J                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  Q2 A8 p! \) Y7 [) |/ {, h
        }# O1 E2 r8 [* L( p( U  t" f  G
        // VRC7 (not support)2 o, q: w6 [# G' ?
        if( exsound_select & 0x02 ) {( Q6 c; T3 M# M# |& ~7 X$ r
                vrc7.SaveState( p );
9 V2 Q( ]4 _$ ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% C4 _$ ^0 N- w* [* ]( p        }, R% G8 z. W3 K8 B, j$ _# b& j( M& W2 r
        // FDS
& a  F( U5 @8 {3 n        if( exsound_select & 0x04 ) {" {, n1 g1 f  p* H% A  H1 l
                fds.SaveState( p );
5 e& q$ |/ I  ~& Z3 i, A( ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 e/ A3 R3 ~- P! j
        }$ k* ]* X8 D0 P1 ?, z1 l
        // MMC58 p7 J& }7 f6 w3 h% g7 `
        if( exsound_select & 0x08 ) {! _6 b" o7 C/ s
                mmc5.SaveState( p );
: O0 B( [( D9 Y6 H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* h$ b7 L% D2 ?5 s* |" B  P' `
        }
: n& ?; O; K& a: G        // N106
" t6 U0 r/ ?( N" u  `; ~        if( exsound_select & 0x10 ) {1 R- y1 q0 F% w+ P% a/ P7 [
                n106.SaveState( p );
: k; C+ J  o# j3 \                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 L' U/ |- Z% O; z$ p6 D7 d        }' y( F) L1 s4 n. r. t* W/ f" E6 Y. \
        // FME7
1 P8 S" X& {; Q/ H) b        if( exsound_select & 0x20 ) {
7 e4 I$ D$ n. N' i  s, q* `0 E2 Z                fme7.SaveState( p );
$ W" r0 S% b9 L3 F* T$ d. q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( `) K1 s; S# x' Q- C        }4 s7 R6 _  u0 |4 f" _, ?

3 O' K$ a, z, l  j! o#ifdef        _DEBUG, Q7 Z# e  v" u2 u1 J
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" _7 Z1 ?- @% a( r
#endif
* y1 R6 }* A  H3 f' a' S5 D}
7 ^% N6 r* a, s$ ~
4 G, P% ~9 G+ u  R9 [4 Hvoid        APU::LoadState( LPBYTE p )
/ [% k/ P7 \1 v8 G+ Q! a$ a9 C" v' y2 B{
. C) T: I$ D8 m' p3 R! o5 x1 W        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. K0 Y4 T5 f9 L! ^        QueueClear();
6 U) ?7 l* @3 K
! v/ c* J& {9 B- p, o& V        internal.LoadState( p );. r  a+ s" t" A9 w1 a( W
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ i& o+ ?4 @/ a( _

8 k# z% _2 b! k  h: d! L        // VRC6& Z  I- z5 r% V1 p/ c
        if( exsound_select & 0x01 ) {
2 v, i4 e6 O& D. t" v3 ^: h                vrc6.LoadState( p );
# T4 y- X* c. i+ N0 c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 t& B6 R" C7 r; `: s
        }
$ O1 y' J) L. k& V8 @. d( F5 Q: v        // VRC7 (not support)
0 m- M5 o- [9 w7 \9 V        if( exsound_select & 0x02 ) {$ |1 j  l6 j9 N7 u0 E8 `% y
                vrc7.LoadState( p );0 \! U& C0 X6 i
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; z, R0 P) _7 N2 I8 ^
        }2 J4 }5 F8 Y! L: P. q
        // FDS
" _, J. y' g7 P7 R" c        if( exsound_select & 0x04 ) {, P/ F# R9 @8 a" m& U) |  o
                fds.LoadState( p );  h% E: A- I" b& d& W+ D' B
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& N: J' x& m7 O& @- E  i
        }
( Z! Q" n1 A4 L+ b; F3 Z        // MMC5
' c. u% {' W" E# H% [9 t        if( exsound_select & 0x08 ) {0 f# e- h  d9 t9 G& ^, [2 a
                mmc5.LoadState( p );  S3 @3 d3 m% S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  H. J2 D5 O) q5 y        }6 m! ?% |5 k* k  `# M
        // N106# f& g' i& t0 d/ H
        if( exsound_select & 0x10 ) {, a$ b' t2 ]4 V
                n106.LoadState( p );
7 m( L8 j- e* s8 o# E: G7 D. `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; k  i" e& E# y7 f        }
/ A# \2 o8 B2 e$ C% s. L        // FME7
& C' a" {3 g( W. @  J8 `- g        if( exsound_select & 0x20 ) {
5 d8 H+ o$ U0 i1 r9 q  J, h& \6 E* p                fme7.LoadState( p );0 \: y7 G, L, j8 Z& e
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. X, U! ]( m9 p1 E
        }) v5 h3 p; l5 x* q* ?4 q
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& _: F- C8 U: I5 F可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。; ^, h* _. [: h/ R) {% A
感激不尽~~

# O. E1 f3 x: [0 ~' N+ D恩 我對模擬器不是很有研究,4 ^1 @) x1 Q; H# {9 \# X* S
雖然要了解源碼內容,可能不是很困難,2 J$ k  X3 V+ H, R
不過還是要花時間,個人目前蠻忙碌的。
3 W# Y8 e2 I1 {* a% q2 R0 `3 a4 k7 p* ^
給你一個朋友的MSN,你可以跟他討論看看,% q# @" L7 k/ z9 l& _" g- q2 j8 q8 d+ @
他本身是程式設計師,也對FC模擬器很有興趣。
% j. c, q0 B, \
# k1 B9 ~' M1 L& R7 fMSN我就PM到你的信箱了。
; |, J+ u: `8 e5 U$ E1 }4 p9 p
/ B8 q, y( b& K: b希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' _: a8 w, y- y4 a, N' B
呵…… 谢过团长大人~~
. u. q, z% A3 @5 l: Z5 o$ q
6 z9 I( L2 d2 ^  @
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
( X7 H, Q' f1 G; t) d; ?团长的朋友都是神,那团长就是神的boss。
5 B2 _8 k3 m0 b0 P3 d: Y/ e
哈 不敢當,我只是個平凡人,' P% P) d2 D5 E! v- S
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
  |. g3 h0 X- X( XZYH
( g4 \7 @* v, o: p0 E! WQQ:414734306- Y% F; _7 S& j2 G* y9 U( C7 J
Mail:zyh-01@126.com
( ^2 }9 D3 E, f: H$ d& O- T& F: F. w
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
$ O: d8 o( ^1 Y8 ]再次对团长大人和悠悠哥的无私帮助表示感谢~~

# U$ F" ]+ {, ~( F  H不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-10 03:51 , Processed in 1.075196 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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