EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( q# s9 P- e8 D! B! K; S& _楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) ~2 j+ }' _( ~, A
这里有相应的模拟器源码,就当送给大侠了~~
4 I( z& n4 |( zhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
) F- h5 `# s& ?+ J* n能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. H. t  f1 B0 ^7 T6 f6 E, z' a) G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 I" n: l& P4 k/ \6 G6 ?& Y1 h8 w
这里有相应的模拟器源码,就当送给大侠 ...

" m) a: l: h4 j; W. {聲音部分(Audoi Process Unit = APU):
' d' P& t& U/ I5 R3 i.\NES\APU.cpp
. ^8 ?! F! r) f: o4 {6 R/ L* @.\NES\APU.h
8 c. |: L4 E3 t5 F" O" J  i! ^8 H- `2 e' d% e& Q5 |* s

/ |* M+ x. }9 T影像處理部份(Picture Processing Unit = PPU):& B. Z, N+ c. r* y
.\NES\PPU.cpp: T! p1 T5 f* c' Y
.\NES\PPU.h! f6 n' c: Y  k% ?+ P& ]- D

  U6 }8 t- w1 ]如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
/ \3 ?) N( B7 a) u( ~) g2 z, h4 M- ?感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* Z# a& Q- L( u( E/ R/ o, @(由于很多专用术语和算法机理都不明白,所以看不大懂……)9 F! x* Z; @  p. z
/////////////////////////////////////////////////////////////////////////// u# D( q# U2 |" P
//                                                                      //
8 J7 K- ]# R& X! k3 I//      NES APU core                                                    //
2 W. o' k: Y1 @; d) n6 Q- v//                                                           Norix      //
2 p; S: L* @( w//                                               written     2002/06/27 //
3 F4 v% f4 M1 U% n% ~1 J$ }//                                               last modify ----/--/-- //
8 s, z! g- e1 h; ?; V//////////////////////////////////////////////////////////////////////////- R- U' T# t' @- c
#include "DebugOut.h"
( P. T% `5 K/ m! F" ]#include "App.h"
+ P+ @9 a* I% U; h/ X4 \! P- e) J#include "Config.h"
3 g# G8 n9 S" H$ X. O5 y) B9 h- h# H  g
#include "nes.h"
5 D; c# k% b; c#include "mmu.h"  P9 G, X+ x- D2 r0 i
#include "cpu.h"2 J: m& R9 O; D0 ]; s; R  Z
#include "ppu.h"8 O. ^* ~1 M/ j" y
#include "rom.h"
: Q/ r# A1 V1 S* x4 M% d#include "apu.h"
* g* _- g  v# e4 c* Z
. s$ F0 t( r) W8 ~/ m: R// Volume adjust/ S" l6 J0 Q" U
// Internal sounds3 `8 B& E: D" a5 @; ?0 O! X3 d( ^
#define        RECTANGLE_VOL        (0x0F0). J3 y5 E* d1 }& ^+ B% a) T
#define        TRIANGLE_VOL        (0x130)
" F$ H* Z3 O7 g7 u& R#define        NOISE_VOL        (0x0C0)
1 _  \$ P  _& U& @#define        DPCM_VOL        (0x0F0)7 X& H. K3 g* j, T' k* m' [
// Extra sounds: Q# X6 ^7 x, c8 n
#define        VRC6_VOL        (0x0F0)$ ?' S# {, b; Z$ L  p
#define        VRC7_VOL        (0x130)! R* ?, I) _' a9 K) q$ f
#define        FDS_VOL                (0x0F0)
9 O  ~/ g3 x3 M" u- L& {# Z9 S#define        MMC5_VOL        (0x0F0), ?: ~' }# J6 `9 x1 c0 e1 F
#define        N106_VOL        (0x088)4 ]' R, k" c/ n
#define        FME7_VOL        (0x130)4 p- X& r* W" v! k

% E9 P% y% n, t7 M' g, p9 Z6 {APU::APU( NES* parent )) m$ S7 t" Y( S
{& V" R0 a7 |0 J1 J) G- G# b
        exsound_select = 0;) n5 Y* g% e; h* H  P- F' ^
  R% ]0 V/ L" ~4 o2 z
        nes = parent;
# ^! o( E$ |- G( u6 V% C# J& u        internal.SetParent( parent );8 y" ]1 Q3 {& ~$ [" \
' J3 S7 f- q. n6 |
        last_data = last_diff = 0;  o8 k4 S/ r1 k3 ]( z1 o

) H( P* R3 T; V% ]& S        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
  U7 O: D5 L0 M- F) p- z/ C+ f" b- i; s9 M8 C' ^6 I
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );  d) o8 b+ y+ B) `0 F  f( N" v' [9 e
        ZEROMEMORY( &queue, sizeof(queue) );$ {% }+ q( m& L) a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& t+ ]  T2 j' w! ^, H' Z0 g6 G  ~( P% P7 j) o# l3 q
        for( INT i = 0; i < 16; i++ ) {
  k' y) [4 Y, `                m_bMute = TRUE;- _+ r0 i- A9 ~+ w$ ~% i
        }+ n! o2 o( `- V
}
) R) P4 J$ p+ x; C
" Z) F- @( ^& w( k- n! gAPU::~APU()
# Z4 I! e8 r9 E0 y- l{
: F$ F- z6 |( ^5 d$ _! m( ?}5 J/ |7 Y8 h4 X8 k

- G1 f3 ^2 R$ s  A: b' d/ ?4 qvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
  m0 C+ Q+ {# b% {$ ^4 P$ l{, v8 g$ J. X$ U0 S
        queue.data[queue.wrptr].time = writetime;  x# S6 T/ u- S8 v6 a* Y0 \
        queue.data[queue.wrptr].addr = addr;
4 ^% b. W% m; z        queue.data[queue.wrptr].data = data;1 s: d0 J; m) a9 n' ~
        queue.wrptr++;
% w  A$ W* Y- O: e6 [. M8 l        queue.wrptr&=QUEUE_LENGTH-1;
4 V" K* k4 b7 v0 Y        if( queue.wrptr == queue.rdptr ) {
5 Y4 a& X2 T6 ?* d( z2 b                DEBUGOUT( "queue overflow.\n" );
9 h7 m# U3 e8 I7 s7 U: y# @. p        }
5 P( @0 E! W! D* ?3 b* [) a. f; p& g9 Z, S}
: `1 B+ I. B) k! }+ ]
& q5 o3 j# U" HBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  Z4 O2 H; W# L" ]0 W* B$ ]1 c{: x  @6 r. s0 d9 ?
        if( queue.wrptr == queue.rdptr ) {0 C( A2 M" v" T; {+ I9 ?) {
                return        FALSE;
8 M( G4 I" D8 P$ |# C8 u/ ], T: [+ c( T4 u        }
+ r; j0 Y& J; X5 P) ?        if( queue.data[queue.rdptr].time <= writetime ) {; F0 P- c7 r, p! b! W' E/ k; n3 C
                ret = queue.data[queue.rdptr];
' B2 O# n- Z+ u6 s/ f& @) ~' w                queue.rdptr++;( b6 f; F' ?0 F: L1 l
                queue.rdptr&=QUEUE_LENGTH-1;, B, B4 p) J$ |" ~+ j( g  T
                return        TRUE;- R; t2 b% W$ l0 l
        }
8 f& T; D7 M2 V" Q' z' V5 V2 b        return        FALSE;
. d0 n. S$ L* G5 E! J; d% x}' ]+ u4 S: O9 h2 R
6 K; r/ j8 a; g+ u
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
9 k% g. ?. w/ B6 S{% K& _- i6 L0 |3 z8 o
        exqueue.data[exqueue.wrptr].time = writetime;
; j# e# h) x4 E, U) e        exqueue.data[exqueue.wrptr].addr = addr;
4 @8 S  O& P5 b! D1 F. A6 F        exqueue.data[exqueue.wrptr].data = data;4 f% N( p9 y. f
        exqueue.wrptr++;
" \/ i- u0 ]8 ^3 B9 r        exqueue.wrptr&=QUEUE_LENGTH-1;
! e! c3 v, l6 |- p0 [        if( exqueue.wrptr == exqueue.rdptr ) {
6 a. y/ M7 z" {# A) F6 j* m                DEBUGOUT( "exqueue overflow.\n" );
# \- S' d+ p5 N8 @# Y5 a) j* N0 x        }
% p! }/ j3 s4 N% e1 o( W}
- u( b5 y, R; g1 ]5 \" t% `5 h& Z# [' d3 e$ U& A8 @" Z
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )4 {& \7 _) G3 a3 a; c$ L
{2 G# s9 R! n3 w5 k
        if( exqueue.wrptr == exqueue.rdptr ) {
7 m0 V. R$ v# N4 h0 s. _. b- F2 o                return        FALSE;2 D4 r/ T' i1 p  y% p
        }& S; u* E+ k3 ~$ E: E$ e
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) f- {: v" C0 q0 h, a% |" s# W
                ret = exqueue.data[exqueue.rdptr];
" f$ Q1 p7 Q3 ?0 {7 ^9 @                exqueue.rdptr++;
+ ~% s8 C  {% F8 r' Z7 W                exqueue.rdptr&=QUEUE_LENGTH-1;! |6 H$ g, t8 U& M
                return        TRUE;
6 K1 q9 x9 `0 p) n' S8 N% h        }8 \& w" h" [& t- `) [
        return        FALSE;- O! L- {& T) h3 [  J9 M
}
* i5 t. F  w% W) F9 Y3 V
) Z- f' R+ K. K7 Bvoid        APU::QueueClear()
' [/ a( h. b3 N{% T  N& C3 |0 L. ^+ }+ r
        ZEROMEMORY( &queue, sizeof(queue) );. W- e- e" W1 \( H9 {0 |* Z) Z' j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: @% a6 A6 @* |6 t}
) Q0 V- j- |# Q3 y. p7 t
  ^1 J7 P- f$ T* _  |6 e+ cvoid        APU::QueueFlush()) B( e1 G/ Y  J! Z) E9 \( ~
{
7 Y8 u" T1 F- Z6 s; J" m        while( queue.wrptr != queue.rdptr ) {7 {. j. A' C' w% u* u7 E0 O9 T( s
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: b! H7 G+ _& J, ~/ `                queue.rdptr++;* I2 W5 \: H6 T2 s% Z* l
                queue.rdptr&=QUEUE_LENGTH-1;2 m( K2 g. R- |2 |% o
        }
1 F( l( w5 b# H* ~. F
) D+ G9 X  |2 X1 a" I4 N        while( exqueue.wrptr != exqueue.rdptr ) {7 j& p7 m( ~/ v& L
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
+ {4 S- r: Q6 ]9 Y. V9 X+ ?1 j# J                exqueue.rdptr++;
1 u3 G; n! l& i# e* f" a                exqueue.rdptr&=QUEUE_LENGTH-1;( ^! Z! L/ f2 Y
        }/ c1 x( B+ ]' t9 I' t0 E9 v7 P
}
2 ?# k0 w  c7 l  ]1 ~1 K3 S  I
; T! @' n  e! k  s' `4 o' t( Svoid        APU::SoundSetup()* b5 C- }+ F4 e$ o' }
{! F, _' d' }, p. n6 W5 N% Z
        FLOAT        fClock = nes->nescfg->CpuClock;- j" L( v: d' X( ^
        INT        nRate = (INT)Config.sound.nRate;
6 Y, {! d/ J# J1 b        internal.Setup( fClock, nRate );) N& ^  D2 L4 ]- B" h" r$ j4 u
        vrc6.Setup( fClock, nRate );
) R3 P5 q! @0 R        vrc7.Setup( fClock, nRate );6 O- p) q. X, x
        mmc5.Setup( fClock, nRate );
, ~" x- s8 ~  A) ?7 m/ g        fds.Setup ( fClock, nRate );
% Z! R9 x3 [* _        n106.Setup( fClock, nRate );
* A- T/ a/ z" d/ v& Y4 K( l# \+ u        fme7.Setup( fClock, nRate );
* D+ O% d7 i# F! X9 a}' E2 |! P" d' A7 t8 s+ p, [

- U" d- u! q8 `+ ?* m& Ivoid        APU::Reset()
, o4 F; R8 R2 ~4 L5 c) E; L{( x/ {/ f/ y; w7 q" r: a* @
        ZEROMEMORY( &queue, sizeof(queue) );; V/ l6 S$ I( g3 Y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* l+ I% f2 f+ z9 L0 @2 Y0 [& e: o# r5 o. _
        elapsed_time = 0;
( w7 m' m, P1 q3 z9 ^+ F  E4 G7 u
# d6 N* m7 i1 h, F1 u( Y        FLOAT        fClock = nes->nescfg->CpuClock;! ?, b5 Z5 w& }5 t
        INT        nRate = (INT)Config.sound.nRate;
" j3 X, i+ G6 N/ ?& d# Z+ G  C* W        internal.Reset( fClock, nRate );
( Z* V/ t+ c% S2 z  o# [( [/ ]        vrc6.Reset( fClock, nRate );- a9 [) ~6 S) Y! }$ Z0 F2 p: x
        vrc7.Reset( fClock, nRate );
0 y" r( f! x; B$ X2 J/ \6 X8 b  m) m3 u8 T        mmc5.Reset( fClock, nRate );  c- m) I2 P( C- v- s5 V) T
        fds.Reset ( fClock, nRate );' [" q0 U0 l( ]+ Z' a& M7 T* @
        n106.Reset( fClock, nRate );
: m9 k+ C' t! c$ V8 p5 ^        fme7.Reset( fClock, nRate );- _( c0 V8 D( R" |7 }; o( i

) X& G2 p: v& L1 @/ n        SoundSetup();
: x7 Z4 |' k" a2 R}
- P# E1 o7 ?+ n2 y
) \  t7 r4 P" Evoid        APU::SelectExSound( BYTE data )$ N: I4 B% {- Q. S$ ~" q: n9 m
{- ?& x, c4 A0 p# {% N/ _6 H0 i
        exsound_select = data;
: ~, D$ }! r" b}) }: w+ _! ?4 F
5 d( f3 M- i- _: M) H6 [4 c
BYTE        APU::Read( WORD addr )
8 ~- |7 t* J% \- G3 s- r{7 E: r# l; m; r1 B
        return        internal.SyncRead( addr );& k0 _9 Q* k) ]! L4 J
}
& Z6 R8 ^7 C- k5 j/ N+ v) J3 q- ?' h
void        APU::Write( WORD addr, BYTE data )" ~3 E. X% b5 k' n$ S
{
( ~* H+ v2 `9 C+ U        // $4018偼VirtuaNES屌桳億乕僩8 i, E5 c) T  s: _8 e5 e  m3 e
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 [0 C8 H9 e) y* |: n, b                internal.SyncWrite( addr, data );
* \7 a* s4 U! t6 ~9 Q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
: x5 z( b) u- y+ @4 ]8 r        }4 _3 Q; w5 F; i2 ?
}
, A& J2 h4 ?% h, D% f8 \
! l4 i4 Y" p3 j$ K, H: ^BYTE        APU::ExRead( WORD addr )7 z, G9 t$ o, ^/ Q# B5 {+ _
{! a, I' D4 Q+ v" ]4 L+ P# B" A
BYTE        data = 0;& c! G" Y  L4 s  @; g4 M2 I

9 k) P: b6 K3 s4 r        if( exsound_select & 0x10 ) {
/ ?$ Z  x3 P; P                if( addr == 0x4800 ) {
7 Z! f/ g- J5 ~$ x! h  ^                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
7 o% s& ~. R5 x3 ~                }
; m) e1 U" G$ Z( k" i        }
' [. F3 W/ T% A" k$ ~1 }        if( exsound_select & 0x04 ) {
7 b/ U: O. X1 ^8 R& I- _) ~                if( addr >= 0x4040 && addr < 0x4100 ) {# C. A" [' t) e; X
                        data = fds.SyncRead( addr );
$ J. p. p& E* D7 d5 Y                }) |* A1 ~% x, t; ?
        }
5 D9 g' t3 @* ^& P3 y  S3 l        if( exsound_select & 0x08 ) {& V, ?2 q% t, P& h4 G# U' g6 _
                if( addr >= 0x5000 && addr <= 0x5015 ) {' U8 R; X7 z# E9 b2 T
                        data = mmc5.SyncRead( addr );
9 `2 S! }5 `/ I                }
* _! n9 {/ J; J0 [: X: R# r        }
0 Y4 C9 u( l# d9 _2 z5 Q2 g3 |5 @8 |1 E1 T4 H
        return        data;
6 I0 Y4 h9 m% G: B4 @}2 e: ?7 E% s( K" p2 L4 x9 T

2 _# U$ C# e5 a3 s/ mvoid        APU::ExWrite( WORD addr, BYTE data )) S4 J5 L" u1 d9 u: W# Z
{0 T+ q8 M7 l8 r9 f4 q+ h$ ^8 |! l5 v6 G
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 T9 B% \! G; e% b# L/ a: @( O# _
        if( exsound_select & 0x04 ) {
$ E: c6 d6 v  N, S' v$ N. T                if( addr >= 0x4040 && addr < 0x4100 ) {* m- l- T4 Z; b2 f: [; o5 \
                        fds.SyncWrite( addr, data );
* H! g# C8 m: @& D% ^" Z: X3 E                }
4 B  C, ]8 L8 v& x+ G* N        }
) ^4 D" W+ N4 {: X: _! p5 v: t5 S! Q
        if( exsound_select & 0x08 ) {
! u& n+ f4 i, F0 ~, Y! k4 o                if( addr >= 0x5000 && addr <= 0x5015 ) {( u8 F0 c/ n' [* p
                        mmc5.SyncWrite( addr, data );+ C9 M7 Q3 q( e3 p  y0 W9 h3 a& s
                }
6 k  O" T, d' h. Q/ Z        }6 H  {; k4 i5 {" v' i/ `) Z
}5 z, J, P: }$ ?1 n7 r

) z8 i2 Q5 |- w- H. _* k" j# vvoid        APU::Sync()
; a1 L3 [' s8 c9 p4 v+ ?* Y0 e{
( g, j% y+ o, o5 _}+ P+ K8 K- B/ {# f# a( c$ y
! H2 R% a5 o) F1 h) x" B
void        APU::SyncDPCM( INT cycles )$ x) Q' T) H0 ~. _
{
+ i  R; x& Q. F/ h% d! X" y, [        internal.Sync( cycles );1 L3 F: b8 H7 P
# f: V% Z; v7 b) ~4 b% \
        if( exsound_select & 0x04 ) {
$ c9 V6 {( Q( z0 r% @. A                fds.Sync( cycles );% w* G5 ~) h9 t% W8 x' n
        }9 {9 |: V* k* P7 r/ G8 {' P* g9 t# c
        if( exsound_select & 0x08 ) {
( v& l/ z5 f) I: Y                mmc5.Sync( cycles );
3 P7 }  [. ]. d5 e1 {        }
( Z  s9 G! E8 |2 b}/ c. w  ?2 I5 d8 f1 w) y
" S% A# h! T4 C; D% _" K* ^: h# g# h
void        APU::WriteProcess( WORD addr, BYTE data )
7 S# z/ A. X" C  ^/ V) w{
5 N6 [% b9 ~. J        // $4018偼VirtuaNES屌桳億乕僩
2 H, t6 s: Z$ o- O, |+ x, U        if( addr >= 0x4000 && addr <= 0x401F ) {8 s* R6 ^2 i- S# c/ X
                internal.Write( addr, data );6 ^6 u3 i0 H" p; |
        }; F( D$ g2 n, G9 h9 Z+ S) X+ ?
}- v- _) `& K9 e& U1 B

' N$ ~7 w8 T4 J; ovoid        APU::WriteExProcess( WORD addr, BYTE data )
$ b3 t3 h' v0 [  X) m8 L{
- x( C) k6 r: r% k        if( exsound_select & 0x01 ) {
7 p6 O  _( O0 m" h0 d                vrc6.Write( addr, data );' p4 b6 l; ?* V$ O" p, f
        }
! y$ k( K7 l4 W- H7 k- D        if( exsound_select & 0x02 ) {  v: e- c! L# S4 d6 n/ r, b/ V
                vrc7.Write( addr, data );
; K3 R; H9 j. b9 h8 X* ^        }; n& p$ |# Y- N( T  G2 |; L
        if( exsound_select & 0x04 ) {
2 _$ `0 j0 T/ ~9 w; {                fds.Write( addr, data );
) E. |* f, Y; m. _) g        }
" J& e7 r" l! Y2 S1 \; c        if( exsound_select & 0x08 ) {
% \1 j: A- S3 o: \0 ?- A                mmc5.Write( addr, data );, M9 |" q0 v/ [9 T3 y9 ^. {
        }; s8 D5 N; Z! I; D
        if( exsound_select & 0x10 ) {& X0 J3 ]; ?: j0 [
                if( addr == 0x0000 ) {
1 O+ V# ?. @. V8 ~                        BYTE        dummy = n106.Read( addr );
! A7 q* P) a( I% b                } else {
- ~, C" r5 _/ y- A2 @& U! U1 @9 T                        n106.Write( addr, data );
( `( ^# n9 N+ [0 k/ j                }
, a2 X, `2 t4 a  v8 ^4 q$ U        }
9 x" p5 L9 |- k8 b, o. S# z        if( exsound_select & 0x20 ) {
9 [' a1 _$ g; n! E9 J( p8 C7 A3 b                fme7.Write( addr, data );% |# M  F" [0 [
        }; V0 e# Q6 D6 c) E4 O8 a  u
}
5 x% m7 k/ D5 t9 ?9 I5 d
/ Q, v, O7 \/ Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
7 }1 o3 a0 Y) P$ U0 K9 j{( q+ v% h8 f' \* ~
INT        nBits = Config.sound.nBits;6 n* ]$ @- g4 K8 q% e3 q
DWORD        dwLength = dwSize / (nBits/8);4 k9 ]" [, L3 J+ O$ A1 K$ O7 b
INT        output;- }7 N6 f- `7 b/ B
QUEUEDATA q;$ V0 |1 `5 s5 z6 f' \
DWORD        writetime;! Y- n0 e2 n: ~( }

" @. h/ `- v* k/ y- {+ ZLPSHORT        pSoundBuf = m_SoundBuffer;
9 ^9 D* _1 n9 xINT        nCcount = 0;
$ `  b9 U! w5 Y1 c7 f; u; w0 R  F: L" l9 I
INT        nFilterType = Config.sound.nFilterType;) ^* e4 s6 G7 E8 L2 P) Y, ~
  f/ H& ?" {1 F* e
        if( !Config.sound.bEnable ) {
9 T. J0 C* m9 B6 M; H* x3 V                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
7 @+ }2 r6 ~. p6 T1 L                return;
5 S1 P4 ~) b6 ]& g: Q/ C        }
7 d% R0 h/ x- Q$ r% p8 F+ F7 D+ l7 e4 R  S
        // Volume setup0 C% K1 Q: A$ J8 e% Y
        //  0:Master# q- a7 s+ O3 P3 l( X8 |
        //  1:Rectangle 1& _, L( f. b; m& x" l
        //  2:Rectangle 2
3 ?2 J. T  q9 {+ l5 h        //  3:Triangle- x- }$ j, U9 h1 j$ k" w$ U
        //  4:Noise
& o! a, l4 [% A8 B6 s        //  5:DPCM$ f. O& A( V1 D6 l) |6 X0 F/ n
        //  6:VRC6+ `1 b9 W. D: T
        //  7:VRC7
; P4 L1 Y/ {7 S$ ?- b' F3 e        //  8:FDS( Y! w/ Z* a( T; r, d
        //  9:MMC5
" A% j( P( N; V' o& H' q+ |        // 10:N106# }. ~: c7 A  x5 x0 p
        // 11:FME7  x5 y' [/ t& _6 I- m% w
        INT        vol[24];
3 N$ C" r' l8 u1 g7 U) x% m        BOOL*        bMute = m_bMute;5 T6 X: A  x5 P2 Y2 t
        SHORT*        nVolume = Config.sound.nVolume;7 P0 e" p+ B3 r* \& G3 Q

% Z  D* C- Y$ e" O1 }6 x        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
) m* k6 O. c6 D3 k9 ]2 O
! V; [' P" h9 o% ^# U( l$ b2 V        // Internal
. _! M$ m1 Q+ {' l4 l9 l& A        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( G+ l# c* Y% j4 v) K# {: L        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 Q, x- p/ u- h' E9 ^2 `) H        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 C2 B* a7 u% S, `* Z/ f5 H" {
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' l6 L- G) U, G- w# i( w1 `1 W
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
1 _  |$ P4 n/ g# P; c' l
3 ]3 w+ \' w: g1 S1 w        // VRC6, r% h' a* l7 l& w
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& T$ e1 `* t5 `( B5 n8 u
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: Q8 H" P0 }* g  I        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ C* I+ l# U5 p9 x* ~
9 h; E) k5 H) r6 j# w
        // VRC71 H7 J2 [, [: i& h0 x5 |
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
# @; s# q- [$ ^) G, ~2 G& B; l3 |! D; o% B$ [
        // FDS" ^8 }/ k2 p5 {
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 s  ]$ [$ S  `" Z7 r
4 _7 n0 G% `6 M$ ?& Z        // MMC5% s! v8 W4 m! ?
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 Y, ]) V# T9 g" r, Z
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% k1 Y# x* q6 i
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  e0 W2 B, Y+ ~' A5 p6 l$ v
5 P( u) c3 n( C$ [7 C$ t8 X; [. j        // N1062 t% Q" ~' B/ V) @) }. w
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 f4 k+ X+ i  K" d# _, n
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( t  L3 y2 b8 k3 A: p: s( o+ _        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, ?. s9 @$ I; C4 l# X3 `& b
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 h7 F% O* z/ h0 ]: s        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 P! y3 x6 T& B) x4 T        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- T1 {- q% M4 j/ L! i; o        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; j$ j) Y2 t' ~' h  f. z
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( [% t7 N3 z7 R8 R+ j# Z+ X/ |
2 K+ h9 O* w6 D1 I1 S
        // FME7
6 p9 ~# _2 l6 I9 g        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 B' z+ _4 p9 }7 u/ H        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. F$ L+ @7 [! m  _, ~9 d- J1 e. u        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 Q0 {+ b0 K; g# A6 O
. ]$ E. c1 p) p; ?//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;9 r5 p# N) \6 H2 f7 [! W5 ~2 Y7 S
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) Z. \8 r2 [0 r5 `
* a4 n* ~# J% D        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
; _" W8 c  S" k  w' q4 [/ U% _        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
% S8 _6 R7 N/ |& p+ y& ]2 ^- @                QueueFlush();4 y" n# v* j1 m0 s
        }, ^0 z8 a& R7 w7 h
% d, I1 s& J( V1 n
        while( dwLength-- ) {- H0 f1 K8 \4 I6 ^
                writetime = (DWORD)elapsed_time;
3 Q6 _* Z3 M# o. N+ ~
4 j* d0 y/ J5 r. T5 G/ W; Y                while( GetQueue( writetime, q ) ) {
# x& p: z1 s* g: X" I. @0 b& W                        WriteProcess( q.addr, q.data );
7 c6 Y, f$ u5 B- C# e                }9 q4 G! Z4 K8 K) J- W5 f+ `

" L0 ^4 _) b2 x3 |1 O/ I( I) k3 ?+ @                while( GetExQueue( writetime, q ) ) {  o& @8 a8 H0 `( h
                        WriteExProcess( q.addr, q.data );! F% l* e! F5 B+ z9 H' y4 x$ V
                }
: v- `& o& o, Y+ _" p
/ N9 S0 \' D( C2 X5 s# J% t                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 e, M7 f( o$ t4 w( U. o7 n$ t- m
                output = 0;  N$ J# o* k4 k* D: ?& t
                output += internal.Process( 0 )*vol[0];
& Z- m) F0 j4 x2 E" H' M+ v, G- [$ O/ s                output += internal.Process( 1 )*vol[1];
1 {0 @% r8 F2 W, b3 k                output += internal.Process( 2 )*vol[2];. U$ @# J# J6 V0 W" G" X1 C
                output += internal.Process( 3 )*vol[3];
; B- k  F' o+ [, J0 h" a1 T                output += internal.Process( 4 )*vol[4];
5 K. C" T- Q, m9 ^2 k, b* t, E
- C0 S% _9 ^2 x0 A( Z6 \                if( exsound_select & 0x01 ) {( u4 E9 F( Q6 |2 ^
                        output += vrc6.Process( 0 )*vol[5];9 p3 C$ v4 j- {- `
                        output += vrc6.Process( 1 )*vol[6];9 Z) E$ A1 P+ U9 F4 w! k! k$ D
                        output += vrc6.Process( 2 )*vol[7];0 R( ~2 v# t( W' T5 I$ \2 r9 y
                }/ W0 Z* U* g( I  [& i/ B$ C
                if( exsound_select & 0x02 ) {) B4 q8 N, r) F9 e5 Z' b' q$ r0 H
                        output += vrc7.Process( 0 )*vol[8];) Y* w- E& A% c% q, R; K
                }9 y8 w6 K" [9 @" T
                if( exsound_select & 0x04 ) {
6 I) _2 z- p7 _8 y% a& e& r                        output += fds.Process( 0 )*vol[9];
" n& {7 g8 Q0 m* T                }
4 N7 F% K! Z9 e  u1 K                if( exsound_select & 0x08 ) {
. l1 W; ^# T) z) M2 ?! @5 @5 A                        output += mmc5.Process( 0 )*vol[10];
0 D4 a. p) z" l) {1 ~' ], _3 Y                        output += mmc5.Process( 1 )*vol[11];
+ ?9 m4 n  C- h  z% n+ T                        output += mmc5.Process( 2 )*vol[12];
1 x* H0 f6 H3 |1 O                }
# {* q+ h6 G, {, y0 @% H, Y3 B( L0 j                if( exsound_select & 0x10 ) {: B5 i8 A% t) W8 ^8 a
                        output += n106.Process( 0 )*vol[13];3 C: o7 H- ^% l0 K
                        output += n106.Process( 1 )*vol[14];
1 B, s) \: {8 `4 f/ ^4 i; d4 e. K                        output += n106.Process( 2 )*vol[15];
6 W" S( C; T8 m) g: m6 r                        output += n106.Process( 3 )*vol[16];
* }" m4 @1 w; C$ W                        output += n106.Process( 4 )*vol[17];( @- b! ]. h! }; G8 s. x$ @+ p# J
                        output += n106.Process( 5 )*vol[18];' K8 N  y. [/ }# ~
                        output += n106.Process( 6 )*vol[19];6 n# s% a! M! ]5 z
                        output += n106.Process( 7 )*vol[20];
$ I: Y, [- o; C- U                }
  ^. |. f% i6 t7 c: c8 c5 e) a                if( exsound_select & 0x20 ) {
& V9 }6 a8 Z# M" @* V                        fme7.Process( 3 );        // Envelope & Noise
  U; H& d( Q0 o( I                        output += fme7.Process( 0 )*vol[21];* w9 t. p! ~) H" X6 H
                        output += fme7.Process( 1 )*vol[22];3 Y, ^( m: h, A
                        output += fme7.Process( 2 )*vol[23];8 ~9 _& R( ~, V$ f& W/ L
                }3 u8 M( j' G% k
( \$ Y7 F- }/ Y8 a; P6 Z( I
                output >>= 8;/ r# D+ @4 N5 i- a0 J
7 `& O1 a  `9 W/ @1 j( {3 R
                if( nFilterType == 1 ) {3 g1 x8 u$ ]  {, c: i
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
6 Y' I) v0 u3 v) Y% G+ s$ p1 D* k                        output = (lowpass_filter[0]+output)/2;
0 }+ h' E2 F, b4 W                        lowpass_filter[0] = output;9 M7 s" K6 p4 ]
                } else if( nFilterType == 2 ) {9 n7 n7 b! t* s4 N
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
; j" c4 M' @- U. n  s: _% u$ w                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
" J/ v6 W1 a: ]                        lowpass_filter[1] = lowpass_filter[0];
5 h. P4 H8 \7 ^$ s                        lowpass_filter[0] = output;) C" G1 v0 X6 H- w
                } else if( nFilterType == 3 ) {
# l2 g3 z! j9 X+ F: \6 |4 V! r$ [) `                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
+ k3 g3 q, U9 h* N9 g' G. r2 I                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;6 R% [2 Q0 S/ V
                        lowpass_filter[2] = lowpass_filter[1];
0 E  `. t% I8 d+ d3 N/ Q- \                        lowpass_filter[1] = lowpass_filter[0];
9 {5 T9 l# t2 R! J* h" O                        lowpass_filter[0] = output;
# ~, \  M7 H4 i3 [2 }5 r/ `8 W7 |                } else if( nFilterType == 4 ) {& X, q7 h2 o. X7 `4 w9 u
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- N  T( V' C+ _* o6 t% H& p                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
  [- j  s# M6 t/ J& Z                        lowpass_filter[1] = lowpass_filter[0];2 @: N. p; a* ]1 c
                        lowpass_filter[0] = output;$ d; v$ v- ~& W& L- t
                }0 v6 Y! R" T& Y! C: f8 W+ q
  P$ w* Z/ X% v1 K& R3 N7 n
#if        08 s: k3 `+ M; X5 m2 a4 i0 v
                // DC惉暘偺僇僢僩4 O; }& C8 ^7 ]% A; A; \
                {9 e2 H$ Z: d0 c
                static double ave = 0.0, max=0.0, min=0.0;
+ S7 V+ L) D" v/ q, W7 [0 J/ g                double delta;
. W; g8 A' H; }9 `+ ~                delta = (max-min)/32768.0;) v+ F/ r+ W* o6 e: ]
                max -= delta;
. V! c( z3 J0 W: k& |                min += delta;
5 P- g6 x' j7 P( O# u1 J5 g$ \                if( output > max ) max = output;$ ^4 u9 G' d4 R
                if( output < min ) min = output;* ?6 h- r5 b/ S! H
                ave -= ave/1024.0;# t: {  u. ~9 G
                ave += (max+min)/2048.0;% s+ C( Z5 n1 T4 ]2 U
                output -= (INT)ave;
, [7 r8 `* W1 M7 \. q! D) ~# f: D4 r                }
( L. K9 \' V" n4 o3 c3 A+ `, a#endif
8 x8 @- @9 \: c7 }. b7 i4 y#if        1
" q- p$ h$ r/ [+ N5 h1 h- ?                // DC惉暘偺僇僢僩(HPF TEST)2 J6 t- W7 W& f
                {
$ ], u, W8 p: ]0 B& h6 b3 z! _//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( c4 P9 B8 p8 T8 K& S) E
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
2 i* {: ]! H0 r# {" ~, v# I1 h                double        cutoff = cutofftemp/(double)Config.sound.nRate;
! G1 R( d" y1 k) J6 o; ^+ K8 b3 [& }                static        double        tmp = 0.0;# ^" Q' V4 z( Y( E( ^1 U
                double        in, out;* O1 V+ U6 q) k8 |$ ^/ d
# F& }1 d5 J3 @) Y$ h- {
                in = (double)output;
% H9 f# K' m. d. s( U                out = (in - tmp);) q" k7 q' l& k
                tmp = tmp + cutoff * out;
  N" J# J+ k# j" U# O% h7 x( U* \; u1 v
                output = (INT)out;9 |# Q5 M$ |, D5 U, F
                }
" z/ R; u) u' @#endif
) D; o( U) B! k9 m#if        05 e% K& B5 @! o4 P9 ~7 ^7 w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ Y! S& V5 H. h5 n) D1 p                {
2 b' j: h2 Z# N* r* S9 R3 ^                INT        diff = abs(output-last_data);0 Q+ y1 T+ f/ v) E& o
                if( diff > 0x4000 ) {9 g6 f& O, x: x" Q0 X
                        output /= 4;& {; t2 V7 B8 ?: ?# [4 l. `
                } else 1 u0 w) `  f& h$ j' \7 {
                if( diff > 0x3000 ) {9 t( ^1 J3 G" K1 V/ @, t6 x; [( ]4 r
                        output /= 3;
# q, R0 h0 b% n+ _                } else- y5 P& R: |3 X7 C( w$ ?9 y
                if( diff > 0x2000 ) {
& ~0 g4 Z) _- y$ N# v7 t                        output /= 2;
; _/ r' h5 k% v/ X% w1 L4 n9 H                }4 m2 U9 e* C3 M8 R- S: D0 N$ D
                last_data = output;
9 d2 Y# e9 W$ ?% L% C' Z                }2 S- d! y2 S/ X7 ^$ Z. G3 H
#endif
9 D  \- c; U& _! F- P1 F. W3 N5 c' X0 f                // Limit8 l' M1 l9 w2 e- Y$ f' e! ~
                if( output > 0x7FFF ) {" v: s+ j- i% z' w$ b. l
                        output = 0x7FFF;3 a& s& X8 n4 S  {
                } else if( output < -0x8000 ) {8 e9 D) O9 F9 W1 j
                        output = -0x8000;
, \0 ^# E* }9 S4 p+ v2 M  o                }
: \9 i3 _9 @. l4 {3 O8 s' H
8 e* t# |" I( f7 q2 ?2 T                if( nBits != 8 ) {6 i' o: T- d" ]3 x1 D* e& u
                        *(SHORT*)lpBuffer = (SHORT)output;
) y6 B# Q9 L" d/ W# n                        lpBuffer += sizeof(SHORT);
! k7 c' N/ y! k2 n: z9 I                } else {. e$ a; s: C, z* }
                        *lpBuffer++ = (output>>8)^0x80;- b; r1 x& R5 g* m7 K. Y$ A. n/ |
                }( B$ Y: Q/ _% A% d; v

) T) r3 k5 j$ s( r) [6 Y+ e- K( K                if( nCcount < 0x0100 ), E  u8 ~0 a/ v* Y/ o. p. e5 Z! v1 J
                        pSoundBuf[nCcount++] = (SHORT)output;
- n+ i4 Y$ J  J0 X& X- D7 O# ?2 ]$ K6 s5 k- I" t+ \
//                elapsedtime += cycle_rate;
. O2 n; E& P: S' Y                elapsed_time += cycle_rate;
$ X8 I9 M0 k% k: t6 ?+ j- M4 y        }
# S- ?- h; N5 m  J! u8 R5 Y& g9 U" k/ v  }4 p2 I. w  D& L
#if        1
" @/ ^3 L4 j" X' B) y5 ]        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {1 a9 l: B. s  f0 m0 U
                elapsed_time = nes->cpu->GetTotalCycles();2 O( k# c8 O$ A/ a3 k" b
        }
( q, O, w( i+ [4 f* e# G3 d        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {3 W. Y6 W7 y: i4 s8 e1 ]$ ?1 `  Z: K
                elapsed_time = nes->cpu->GetTotalCycles();% J" S* C$ y0 f* R# E8 [( f
        }/ m: u# t. @: {* E( q, L( x3 H
#else/ e- P/ q/ A8 f$ v" J( ?1 J
        elapsed_time = nes->cpu->GetTotalCycles();
% k4 }" a' ^1 L9 r#endif1 Z0 z. T# C, r* B$ _9 u
}) [+ |( ]: n5 `) ~

) s0 A  X" ^$ L// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! y+ u+ B7 [0 \" qINT        APU::GetChannelFrequency( INT no )
8 ~' G1 l' m0 G% I& v8 M{
8 i: W" S$ H$ p0 A( v& {' G        if( !m_bMute[0] )
  i. Z6 y/ I2 s. t! W                return        0;
2 L7 p! ]9 ?0 E3 O7 p6 G, W5 f# o1 z& T" _  Z
        // Internal
( J% X2 i8 R; I/ |& y        if( no < 5 ) {
- V0 A# m3 y1 C, Q  Z5 M& y8 b8 D                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* V  s5 u% D- J0 u4 r        }, e# _9 v/ h# r. F4 q
        // VRC67 k- w: _3 W1 G" K
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {: T4 d6 v3 S: g* e: e+ x
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# r; w4 Y; N. z( }) I0 o1 G5 i; e" W
        }
2 u! S3 ?$ J; V% X; k        // FDS$ H9 \9 C/ B6 v  u2 B. E; j
        if( (exsound_select & 0x04) && no == 0x300 ) {
8 f9 `5 p0 v: e. w% ]0 ^                return        m_bMute[6]?fds.GetFreq( 0 ):0;  ^+ B# ?: Q: |) o
        }& w( U- }$ A9 k5 J
        // MMC5
9 S% a1 Y* T( T( \( u" S        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
: h! Q0 F& w% }0 D4 ?2 C& h                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
0 ?( T! L0 H3 M3 F4 B1 r0 R        }" G4 V/ x7 q# W& h2 y
        // N106$ h8 Y! ]* b- H" p; F
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- a1 B% R2 o' C                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;* o8 z! a' h  f# M4 r! D
        }
* l! Q+ c9 }! K  w$ X1 |4 h3 Y+ F        // FME7# u) O" D" p2 w. r# }1 ?6 l2 \
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 u$ I( V8 l4 G
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* `& Z# u  f; ~/ o; l        }
+ D/ g5 ~( }! R% y, o' Y) q        // VRC7' W8 ~- P6 B  d3 z' X
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" k* F* S; Y; X8 o. A8 k" r                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
( s  I) G5 L3 u4 l2 y4 J        }
( Q& \4 b- ?* h6 t+ N: g        return        0;
5 k& ], p! o, X, Y5 f}
3 k% y( {, T3 k3 S
' a5 A; n" k+ O7 C4 j* |  u3 J// State Save/Load3 p/ N$ k% h8 y/ G! Q. J
void        APU::SaveState( LPBYTE p )1 o5 ~/ |6 F. }5 Q8 ?2 ?$ W% E
{
) Z1 B% ?; A. Q$ U" l. v7 B#ifdef        _DEBUG0 W9 `. [0 a8 y5 G
LPBYTE        pold = p;6 }- _8 g8 U+ k, l( F3 a5 M' m
#endif
4 U( h: ^& x9 Y, k+ p+ x
0 ^4 Y; c* I+ l/ [/ \        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
$ q2 s: Y1 j  ~6 G  u3 X1 \        QueueFlush();9 U4 x3 p0 ?# d2 M/ _! V# ]" I- D

; L; M+ u8 A# A9 W* H' }: ?1 h& S        internal.SaveState( p );
& t. c: ^- Y4 E/ @* M        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  b- U4 k7 l9 p$ B* `5 }
, r' \. c( i; R' `) B! w
        // VRC63 T. e0 y! D  O5 a, q6 k
        if( exsound_select & 0x01 ) {' i8 ~$ Y( ], ~
                vrc6.SaveState( p );
  G/ V$ Z) y- k                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 p$ H0 c* F( Q% L1 |0 K
        }
7 {( c1 Z8 o( k3 Z3 {/ |" s( S+ \        // VRC7 (not support)' M- u5 T/ v. J) t
        if( exsound_select & 0x02 ) {+ l: m3 `; k/ s+ V1 C% W  ~* D
                vrc7.SaveState( p );8 [4 ]- K/ c" t1 `' x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ i/ _  ~; x, t- [. K# V
        }
9 T, R0 V* R# y        // FDS# Q. M8 \7 L& m2 B
        if( exsound_select & 0x04 ) {' `: O  S, S0 v0 b) [6 p1 t; ?* E( c
                fds.SaveState( p );7 T$ U) S7 N% o1 [& ?0 p: T
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" [* X, m3 [# y/ k
        }8 d6 N( B( g: X" {8 l
        // MMC5
( C5 V8 C7 Q5 H! C: o& L8 @        if( exsound_select & 0x08 ) {7 u+ }, p% V0 x+ C0 L5 C
                mmc5.SaveState( p );
; j& ~; O( U3 b: Q- H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* I: d* ]9 g1 u8 x8 V/ ]/ y4 T        }
9 k- T& F- i  d+ z        // N106
; n6 ^+ e6 _* p/ {2 g8 o; R- V' c        if( exsound_select & 0x10 ) {
9 ?% V3 U" s1 |' r" ~; Z                n106.SaveState( p );$ n4 f6 B- Y( X, x
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& T2 b: W: z9 t8 B) \# ?( s  k" E
        }; `# \  K. Z3 h, e6 e2 D
        // FME7
/ V0 ^6 e# O* f9 m$ l' j5 I* Q, N" p        if( exsound_select & 0x20 ) {
2 ]& C1 ?. {% l                fme7.SaveState( p );' o8 Y3 n. k4 C# b& n4 S- v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! e) q% x+ A  C
        }
8 Z0 l+ G7 D: U( I  P8 F" e0 \/ ?# ?) o1 M9 T! L& z
#ifdef        _DEBUG$ C; I6 I2 U7 i4 Y! T  a5 a: t
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );* P) r- W+ n. A% z
#endif% s" I' d; A6 r8 v) g% Q8 {: ~
}
7 |) c2 K, ~) ?5 q( ~
6 k1 X" O) w" x, E+ ]void        APU::LoadState( LPBYTE p )
  ^  t. {8 V3 D6 u7 e{) o  [' h$ }+ D
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 i- Q; Y; G$ k
        QueueClear();$ ?; d: d$ N0 ?: u9 y$ |' K

8 c9 \3 I, g. C8 p! d" R8 Y        internal.LoadState( p );
/ H' m, E" V; a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  ^/ y" b5 t$ f, z, O8 C( J+ R  r" T2 O3 |, q# h! j( @; S# e
        // VRC6! F$ z: g( m" C8 t
        if( exsound_select & 0x01 ) {6 M. u& E3 }# W! Y; a, k: T; r; N3 t# e
                vrc6.LoadState( p );  r! n3 I9 s* u) _/ I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* y" v# o- n7 S: {8 {, Q        }
" _+ g6 N' U8 X        // VRC7 (not support)
% w2 r6 W6 S9 S5 i        if( exsound_select & 0x02 ) {' B, N( E" g) B& [6 h
                vrc7.LoadState( p );
# y' H# Y, r; V" v: S                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( i9 c( S7 V0 f! f- E
        }
  |) F1 ]9 e& Y4 D        // FDS: S6 P; A( \! G( C( Z3 J0 c
        if( exsound_select & 0x04 ) {
6 b# d6 [# Z3 {- `0 Q: C                fds.LoadState( p );  E2 P; L0 E7 A8 h0 O- A% c
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 G* d, L% e8 {9 h, V( a6 |" c* t6 B& N  e        }. F+ ~9 S3 |) I* T7 o' {! ]
        // MMC52 O; Q8 G2 J) C, I- r6 m) {% B
        if( exsound_select & 0x08 ) {
: ~, M! V/ P6 U" t1 D, g                mmc5.LoadState( p );
8 G( {- G5 g$ o0 b9 Q2 i, f5 g                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; S* K. K" G, `4 U3 E, j
        }
* O: F+ q  L7 G" z: q5 g        // N1060 V0 P3 F* a& M: a- S/ e
        if( exsound_select & 0x10 ) {
' d; N  g% l: R                n106.LoadState( p );) G% g& B9 {0 F
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ w  w' F7 X5 t. @! W* _% A        }9 ^# h. i4 z0 ^# E1 ~9 c1 O
        // FME73 v5 s, e, Z2 h# U' J
        if( exsound_select & 0x20 ) {
# m5 {: M* t4 p                fme7.LoadState( p );
3 h! R& x- f9 G                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) y3 T. W8 {( l% J. f7 O( `2 I( N
        }
2 C, }0 |2 N4 p! j! D1 f3 Q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 - j9 {0 v% O& }9 }  {. i* y
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
0 k, u  z- e/ J2 v: H9 e感激不尽~~
" O% S( ^4 P) I7 e; R3 W1 @3 m
恩 我對模擬器不是很有研究,$ S+ s0 s* E" T9 l. a
雖然要了解源碼內容,可能不是很困難,$ }+ x8 h% W+ Q% ~) G7 I
不過還是要花時間,個人目前蠻忙碌的。
4 Y7 @8 q/ l2 @0 ?: [) K
( n7 u3 P" H2 D! b0 U. _8 S4 [# n給你一個朋友的MSN,你可以跟他討論看看,$ ?# X& H7 |' k( z3 u+ T  b
他本身是程式設計師,也對FC模擬器很有興趣。
8 b* W% k0 U3 K7 h0 A. C. }
# z8 U( \7 R5 i2 MMSN我就PM到你的信箱了。
* Y0 i* l% Y2 V* t/ f, `
- t, r8 G4 T" l) W3 i2 i' \希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 - L0 R* T: y0 I# x) ]) `& B
呵…… 谢过团长大人~~

3 o) I$ H' x& O3 ]/ q9 T% b
! B' k6 R7 {( }" q哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
- W/ _) I# H7 F) W( e# F& Q! @1 g团长的朋友都是神,那团长就是神的boss。

0 \4 z8 O  q. P7 J. g哈 不敢當,我只是個平凡人,9 N' s# |) j7 N" C  l
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙( |$ T+ D& ?) ^; o& u. n
ZYH
9 h8 x8 C% ^, j$ ^: y: ZQQ:414734306
; A" G5 |! s# l3 B- |8 f% oMail:zyh-01@126.com
6 l5 ^; ^, c& k- J% I/ p9 Z; g7 {
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
2 c6 O* `, n" v0 S再次对团长大人和悠悠哥的无私帮助表示感谢~~
4 y( i. S6 O' n$ p
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 23:40 , Processed in 1.073242 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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