EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
' ]* A- @% S1 Z: w4 @1 J# fPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. D6 s& \" Z5 J/ o0 @9 s9 e2 ]$ g0 Q楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 Q' x! o" s: A3 {& p这里有相应的模拟器源码,就当送给大侠了~~
8 e% q! U0 d4 d8 @+ e8 `1 Fhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 7 m: c# W  i2 W, Q3 }7 ]; K& F
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 j- b+ {, f5 K: @! w9 n楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  q5 S# H% e0 E' Y  Q( w
这里有相应的模拟器源码,就当送给大侠 ...
0 p4 n7 i2 ~& m
聲音部分(Audoi Process Unit = APU):) [* G2 {1 \% ~5 s+ K5 g
.\NES\APU.cpp
3 J, y* F' e* P. e! e.\NES\APU.h9 t. i1 F4 s$ v7 z
5 o8 }9 k( Y5 E

0 ]3 p+ [: o7 Y8 v" W4 x影像處理部份(Picture Processing Unit = PPU):
8 p) T& ^2 G0 ~5 t+ w4 O7 F9 ~.\NES\PPU.cpp
5 ?1 ?$ z  m) S6 N.\NES\PPU.h
5 G$ m! P& U) f+ J) k9 w# G9 U! C
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
) t: @1 n+ l+ Y+ N" |! S(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 W; P  G6 d; L
//////////////////////////////////////////////////////////////////////////8 B' F* w  K: m) t  g) I
//                                                                      //
5 E" T3 G3 F1 R, X; A0 S7 q//      NES APU core                                                    //# M$ \7 f4 ]/ H5 A2 z  B) M
//                                                           Norix      //
: p4 E/ u. s2 C, r" T8 B1 _' i6 V//                                               written     2002/06/27 //* M6 L; s+ W- w) C
//                                               last modify ----/--/-- //
5 G/ F6 y" ~" W. L5 Q//////////////////////////////////////////////////////////////////////////
4 ~% m+ k7 H8 h: G#include "DebugOut.h"
# N7 {+ G6 o0 v#include "App.h"% U% O' r+ F' ]
#include "Config.h"
6 Y# @2 p5 o! K/ L, I% t, M- R3 t+ f/ x+ j2 r. v/ w
#include "nes.h"6 m. x2 |. ~4 l% `) z& A
#include "mmu.h"  b; w6 V2 Q  `; v
#include "cpu.h"8 M& u" b8 r* B* q" ]0 D
#include "ppu.h"
# g! n; x1 ?' r$ k2 y2 A+ r3 z#include "rom.h"2 T& B5 D5 \+ ~  M* E1 {
#include "apu.h"( S- v/ Z$ x3 J' N, D" J, |9 ^7 {
9 S  h( E; ?# u% `
// Volume adjust
, r3 V# D: H6 j6 q// Internal sounds" _0 A" n1 x1 e
#define        RECTANGLE_VOL        (0x0F0)/ J. A1 R; F5 I% V+ J0 b
#define        TRIANGLE_VOL        (0x130)
( P) G6 o4 v* _#define        NOISE_VOL        (0x0C0)
9 ]* H( f; A& m6 U2 S#define        DPCM_VOL        (0x0F0)
0 Z$ n* S( N  b3 w// Extra sounds0 {/ P6 ~- ~; X$ [+ X5 M. G% Z9 c
#define        VRC6_VOL        (0x0F0)8 _$ p4 g4 ?; b) b
#define        VRC7_VOL        (0x130)
% g3 ?( V. E. J#define        FDS_VOL                (0x0F0)" ^6 L* I4 T% ~7 W4 _1 H/ P0 n
#define        MMC5_VOL        (0x0F0)9 F6 b, I# z4 E! X/ J* w2 i
#define        N106_VOL        (0x088)
2 j! A, I& i# a+ @" w#define        FME7_VOL        (0x130)
( l4 y% J1 U+ U8 e6 _9 c7 E- R* K
3 Y: l" h) c3 x! q, l2 NAPU::APU( NES* parent )
" A, u9 O6 D% o% r9 j# K1 e  y0 K{
' {8 k2 q% C0 s, g        exsound_select = 0;! O( `1 K, s1 a1 U& K/ ^

: Q: ?+ y8 b8 ]; ?        nes = parent;
, @  j5 p& f8 I        internal.SetParent( parent );
% ]& i! j, y3 m% a! `! f3 M4 C0 k& U. |  k; O0 T
        last_data = last_diff = 0;  l4 r( i' ^# [! N. L9 P

& c  D5 Q$ z) T- c4 l        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
/ {" P; g. o; \: r3 |
6 x5 M; J+ J" ]# d) R# T3 c  d        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );4 _2 f7 p9 u5 T3 x5 ?3 Q
        ZEROMEMORY( &queue, sizeof(queue) );3 L* V; s5 L1 E' h, s% v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 J9 ~2 I" F8 o( d: O& R' `# H2 V4 ]+ J9 d% {' y: M+ u
        for( INT i = 0; i < 16; i++ ) {
$ f. b# g) O: F6 J# Q                m_bMute = TRUE;  I; ^3 s2 r/ L) D
        }
& ]- J* P# E# k; Q% U# s}
0 Y# h2 O# b3 k. g, b
8 u8 }0 Y) H) u; \APU::~APU()
* W1 L4 L/ @& U& D{# V0 x  _1 J$ c0 Y7 q* {
}5 o9 V8 ?3 g: O4 j& n1 Z

/ Y, @$ s7 N+ Q7 ]7 r9 mvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ D. A+ _1 Q: Q( l' s* d8 l{& m& J. U- x' J/ |
        queue.data[queue.wrptr].time = writetime;
1 E, i; f$ y4 h& H# A& {* Y; \        queue.data[queue.wrptr].addr = addr;
9 x8 f+ }- \9 U4 ~$ N        queue.data[queue.wrptr].data = data;( r3 ^, w2 B0 e) ]& d, q9 Q
        queue.wrptr++;4 U# k! l6 k; L) p! j
        queue.wrptr&=QUEUE_LENGTH-1;7 h' R6 S$ y* q0 t* X6 ]
        if( queue.wrptr == queue.rdptr ) {
3 M7 c/ j! T/ l. S                DEBUGOUT( "queue overflow.\n" );
9 P( N7 s1 ?9 K9 p% D% ]; }  P        }% `) x# P9 g, c/ S! m/ C4 N! x
}; r/ }, U  C) y) h8 D
/ K% @3 W) @: Z, S0 t1 q
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
! h  m' u- r! }. B{  C0 f0 ?  G: t
        if( queue.wrptr == queue.rdptr ) {
! e: p) l' _: \5 r. r4 ~0 M3 i                return        FALSE;- `% U- p5 e3 L/ j
        }
7 l8 I3 M9 I) g  ]        if( queue.data[queue.rdptr].time <= writetime ) {6 s7 C, ^( F" C. |' x
                ret = queue.data[queue.rdptr];
) C) y  Z+ m+ |! ^& A                queue.rdptr++;4 ?! d9 q6 M9 T/ E7 y+ C/ H: F
                queue.rdptr&=QUEUE_LENGTH-1;
; z- `$ G" O+ s                return        TRUE;' b9 n- g3 y1 y# S' u: q
        }
  n" o# N( `/ ~2 O4 q1 I' P8 A/ @        return        FALSE;
$ m1 @% F1 k- f4 U1 ^+ L}
- [) h; h: @, v/ s) S+ ~) a) w1 P
  v# J  G7 c* r. H2 p4 t* U- Ovoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
% j4 L  i0 h; g1 ?{
: ^  y2 N) {+ Z+ z7 m5 e8 G9 j        exqueue.data[exqueue.wrptr].time = writetime;! E( y% m6 L4 M- r+ j- c: o
        exqueue.data[exqueue.wrptr].addr = addr;
! e! h8 v2 p8 M        exqueue.data[exqueue.wrptr].data = data;6 P# O7 q6 d" a. v
        exqueue.wrptr++;/ r3 O9 u" g9 E, d) J9 z
        exqueue.wrptr&=QUEUE_LENGTH-1;
/ v- K, W* O1 }1 T9 Z* i$ ?        if( exqueue.wrptr == exqueue.rdptr ) {
0 `# d. Y7 Z5 i. \9 d, [                DEBUGOUT( "exqueue overflow.\n" );
& J' @$ k" k& x( w- P: z7 S        }' J8 E& G: C( ~
}
% Z8 B2 r) d5 n" s. E5 B
. N7 A& F6 H" i/ d! gBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )$ Q5 g; c. D, v0 K2 p
{! q5 P$ q' n3 z: B  y& @
        if( exqueue.wrptr == exqueue.rdptr ) {, a3 }/ b' C6 d
                return        FALSE;
1 D" S! }( H- X3 y9 X. e        }
0 n- b. ?5 p1 J5 M! T        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ n; p$ P% q5 ^1 T3 A- ?- ?/ r
                ret = exqueue.data[exqueue.rdptr];
6 w& ]; v; l. d" x8 j/ n                exqueue.rdptr++;5 m5 `' q6 s) b; |
                exqueue.rdptr&=QUEUE_LENGTH-1;2 Z: N$ g, S4 O. A
                return        TRUE;8 p/ I4 m* h. l5 s  g
        }
3 ?" e4 e; N3 K- Z) W        return        FALSE;
8 ~0 e6 J) Q: }}3 G" B' I- U0 c8 b# T" _. V3 i

; I1 {  Z, V* J9 t2 {' l; `void        APU::QueueClear()
% p) T0 u4 O; k5 D9 W* l) F( [{
7 o3 A5 p' A& p+ h$ f& e& K! I- ]        ZEROMEMORY( &queue, sizeof(queue) );: k5 q8 ]$ p2 N9 d6 ~; w- M- q! }0 T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 t7 C1 a8 D0 I% x& ?4 z& u}( k7 I6 Q1 d/ l  l; m+ k( [

4 |0 b" @  t: h; ~7 zvoid        APU::QueueFlush()
, i6 p/ B. k% `: |{9 @. y8 L7 W1 K) o5 \& e3 t
        while( queue.wrptr != queue.rdptr ) {% Z- b  r/ h6 i8 W# v; N' J/ `
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
( t6 e; \% N! B# W. |( X                queue.rdptr++;
* H; D& S4 @& H  H4 e2 _1 k7 q                queue.rdptr&=QUEUE_LENGTH-1;
2 j; ~* o/ C# n% J+ u6 Y/ t: d        }1 X, m% T  I& I- r
1 K* h2 J& l6 F8 Q: f6 P) [# B. V
        while( exqueue.wrptr != exqueue.rdptr ) {  e- d5 q. T! M, E0 f
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. G! C, j& Z* X: U  {: ?
                exqueue.rdptr++;8 ~0 C3 d" f& [; I: F" `9 ~
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 r- t4 I6 w8 {2 N" s4 }        }- `2 j, ~+ s( F" f) g( U( V4 I
}5 K( _& j: G* r" w% K

: j+ C# `- Z& _- W, E  _void        APU::SoundSetup()
2 L, n! z# Y8 I+ j" W/ S{. n5 E1 q3 j- y9 u1 D
        FLOAT        fClock = nes->nescfg->CpuClock;
! K: O7 S* _+ P        INT        nRate = (INT)Config.sound.nRate;
% b, f) S! N! p  l& O        internal.Setup( fClock, nRate );) @; P  w- e; J8 }
        vrc6.Setup( fClock, nRate );
& v) C4 ]; q2 k; k9 G        vrc7.Setup( fClock, nRate );
2 D4 Z2 g) \" s+ y2 Y$ d        mmc5.Setup( fClock, nRate );4 p% @, r5 u5 X( J
        fds.Setup ( fClock, nRate );
7 S9 O  P' e; f& x" p9 J+ B, l        n106.Setup( fClock, nRate );
! L, @, B7 }: _: Z        fme7.Setup( fClock, nRate );* o/ |/ [9 j4 l* f6 t8 }
}
" E) r* j+ W0 k' n+ t+ M+ O- G0 a7 Y( O( P* y+ ]+ ?0 `
void        APU::Reset()
4 C* J& f9 e1 U- r8 g0 C& q( m% v{
. j/ Y5 r$ {  t" C; b! `8 E. t$ q        ZEROMEMORY( &queue, sizeof(queue) );
- ], A( o7 p+ i" \5 }1 f        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 W* `9 I. c& u4 S6 i% A
- I1 q$ W* E" s7 r) b        elapsed_time = 0;$ E9 c0 o& s* ]: n# P+ y7 G

8 ?  _0 \1 }# p" A9 D- _        FLOAT        fClock = nes->nescfg->CpuClock;2 S# Y% }4 H4 S- |  F
        INT        nRate = (INT)Config.sound.nRate;7 g# i' x& K: |% ?9 g
        internal.Reset( fClock, nRate );
* `/ \1 I2 e6 S' J1 ~        vrc6.Reset( fClock, nRate );
( W" p( M  D0 l4 }% C        vrc7.Reset( fClock, nRate );
* a  C' U: N" p0 M+ ]        mmc5.Reset( fClock, nRate );5 [- ?" G; b/ c; H" w( _' S* d  T
        fds.Reset ( fClock, nRate );
7 H9 L1 n1 j+ p- A- ]; a$ z        n106.Reset( fClock, nRate );
( v! @" s6 w; e, C7 |% R6 t        fme7.Reset( fClock, nRate );
" P( _% i0 m' y
8 C& c$ w3 h1 n- e' N0 U        SoundSetup();( q" H- H+ u# F+ l
}2 @7 w9 d+ f: {; u! P
( R0 J# @4 U+ a
void        APU::SelectExSound( BYTE data )
0 I' ^( }. p) M$ N9 N2 L7 m0 |{
( I2 [4 y' E- ]7 |( ?* G9 L        exsound_select = data;
4 j7 y! S. O% V: _! l}
9 e! m; K0 Z, A8 I: Q2 I% c: r  _8 [, g
BYTE        APU::Read( WORD addr )
5 S( T& o/ x/ @. j' z{
! ^5 v% M( K3 z! V3 f" q5 L        return        internal.SyncRead( addr );. C) i2 S2 J" ?' z
}& G. H+ t) ?0 J& O

' l, V1 c; e6 f' D4 \3 _% Qvoid        APU::Write( WORD addr, BYTE data )* q( N9 y7 Y( R# b
{
9 w  Z- e5 \! f0 w/ \6 G5 I        // $4018偼VirtuaNES屌桳億乕僩8 j3 M: T, z2 T
        if( addr >= 0x4000 && addr <= 0x401F ) {" u7 W; m$ T; A7 {5 ^
                internal.SyncWrite( addr, data );6 Y) a+ K5 {& Z6 ?' t) x/ A
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
( y# O  W7 u! }( T8 A! T5 k8 N) V% G        }
4 ]) @3 \1 I9 w9 f1 E3 f}! ~+ I* Q4 h" `" `$ K

% {3 c; h: \2 LBYTE        APU::ExRead( WORD addr )
7 O, O' o8 V: a{
: b: z# Y4 X7 e% V5 l  W$ cBYTE        data = 0;/ k5 q2 X0 b# `6 [
- I% ^+ W1 H" ~/ F0 L
        if( exsound_select & 0x10 ) {* Z/ A* g! K$ D% q1 n
                if( addr == 0x4800 ) {- }8 Y0 A/ A7 [) Z% T2 {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, I0 o: c9 `  C2 h( @
                }
3 Y. K; |0 H; P  r0 Z        }
$ x% I( w( ^2 h# U; w" |        if( exsound_select & 0x04 ) {: C7 [. A# _) i. m" W" K) \
                if( addr >= 0x4040 && addr < 0x4100 ) {
+ e0 k7 K% P- q$ s5 z8 T                        data = fds.SyncRead( addr );
  K" b2 A. b& O                }
$ F6 }1 J4 ~7 g* ^& _        }
! _5 |, V' J7 b0 f# y- r5 C1 r+ U        if( exsound_select & 0x08 ) {( `2 R+ Z2 b) W1 `5 y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
4 R/ O; ], c& ]$ T% z                        data = mmc5.SyncRead( addr );& |, q' o- n9 R- p3 L/ f
                }, y- N+ u7 z% i; a: {, _
        }
! o! l% ]; Y8 ?, O: ^  Y- {1 o
& c3 {" h8 P- s  @' L" R% l+ R. |        return        data;& ]2 @5 d4 _$ O- L3 U
}
* a- y+ }# Y$ l1 H4 y: R: _( k$ g: X  ~
void        APU::ExWrite( WORD addr, BYTE data )
( ?7 ~2 s' g: h9 F1 L6 P{/ A2 }5 y2 S5 w6 n! w" ~, w
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );1 Q* F0 k9 \( q! B# ?9 x( q4 z

$ a. [' R1 C" G9 E/ h( U4 Q/ A5 G        if( exsound_select & 0x04 ) {
# D7 ^4 W; I* `                if( addr >= 0x4040 && addr < 0x4100 ) {
) K3 |3 A- U( _. f. y5 t  f                        fds.SyncWrite( addr, data );
4 r) q) |; P1 J7 Y1 M                }
; [3 i  w0 z  A        }1 }) [0 a6 \( p0 b' X1 i

8 n5 W+ c! y7 a8 R) y* g" L: s        if( exsound_select & 0x08 ) {7 V; F1 q4 Z) s& \5 N
                if( addr >= 0x5000 && addr <= 0x5015 ) {! S  j5 g# F- C. {- v# D+ h
                        mmc5.SyncWrite( addr, data );% [, t* S& ^: B# _% ^
                }
1 S! w1 z$ M# ~, |( E6 s        }* j- B& a5 }& Y
}6 I8 C) k! \- H9 x: e7 D

& e4 h: J1 E$ K+ zvoid        APU::Sync()2 @2 `5 I- e' H1 T& y6 D  [
{
: x. I$ N" w9 c}- U. f- ]2 v, H* T# L! D6 p8 |

5 e1 A# M4 @8 V' {4 _" y7 n: P( @0 Ovoid        APU::SyncDPCM( INT cycles )3 B( R8 A+ {+ ]- n6 Q( N6 f3 h
{1 z+ ~0 g6 ^, L2 u( m
        internal.Sync( cycles );
; D! y) o2 m/ l6 I8 J, X. k# z! B5 S6 i: Z9 _* W/ J
        if( exsound_select & 0x04 ) {
0 v& B) r- m/ a- j; n                fds.Sync( cycles );% h+ B$ T0 s' e2 l$ B
        }6 O/ E4 i% X& j  |7 z2 p
        if( exsound_select & 0x08 ) {
4 L& Y$ }4 [7 Q                mmc5.Sync( cycles );/ V: D  P3 t/ j8 m! T. V
        }$ `+ V/ h/ q! j
}$ `0 }3 C, I( l! m* ]
1 c; M1 A  `' E0 ~8 {* B+ c7 W
void        APU::WriteProcess( WORD addr, BYTE data )5 C6 |( Z( m& u  R1 V8 G
{
: X5 l6 \7 i1 M2 h        // $4018偼VirtuaNES屌桳億乕僩3 l# S+ Y& W  C$ E- Y- z: Z
        if( addr >= 0x4000 && addr <= 0x401F ) {- ]4 y0 |% r% q1 F5 I2 J2 u
                internal.Write( addr, data );
$ W4 |7 ?6 p- I( N5 U        }
, F: s+ W/ m6 }- K: L6 b0 Z}/ f& m' j6 u5 v7 X- c

4 L+ m( n" S0 G8 B+ H" Y% lvoid        APU::WriteExProcess( WORD addr, BYTE data )
8 H1 I1 d3 u5 @$ Q3 x4 Y{9 z, l* H2 B5 q. d* S/ G* ?8 i" y# \
        if( exsound_select & 0x01 ) {4 W5 _1 y0 v+ q
                vrc6.Write( addr, data );' J# t' R3 m# C( k1 }( |1 o3 u
        }9 @  G% b1 D# y& r/ C
        if( exsound_select & 0x02 ) {
5 @8 b# y) m8 V                vrc7.Write( addr, data );& H! H* @5 `1 N: z6 z; A
        }5 a% S5 `/ F- D( L& e* i; L4 w
        if( exsound_select & 0x04 ) {
, D" a& d% X" o, V                fds.Write( addr, data );. x6 I7 H# N  Q* ]6 K4 Y, J
        }6 E! R& C' c5 K2 |- _
        if( exsound_select & 0x08 ) {5 m! a/ i+ t0 J( i3 r% p$ q4 g* z
                mmc5.Write( addr, data );; R- _, r- r  R$ z8 o
        }' r& w* d- I, [. ]6 O
        if( exsound_select & 0x10 ) {
, ^6 r. Z) [1 @3 J# `                if( addr == 0x0000 ) {! \; U( Z8 i, y, w+ X
                        BYTE        dummy = n106.Read( addr );: \, }4 W' r0 u4 s# c( h" ^$ D
                } else {
8 X; f. K8 a0 [# G                        n106.Write( addr, data );
9 q# K6 w8 A" t6 o) {: y5 ]) z                }5 R& N& X: B& H: [( M
        }
2 F1 m/ ^+ o1 A7 L  n        if( exsound_select & 0x20 ) {
" l0 _9 L- m' v+ P! n                fme7.Write( addr, data );6 k1 n8 w5 @+ e6 d. U5 @0 z" s: @8 V
        }$ s5 z. J, N# v6 H9 s
}
- [5 G5 b, Q. K
) n! B5 @, V# k7 E& T; m# h6 r/ a( y/ Bvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )8 M* T( Z0 X6 N# R8 g
{4 B# n/ z. Y" k( N$ V4 f
INT        nBits = Config.sound.nBits;
0 S) x# f- ~& T( U! dDWORD        dwLength = dwSize / (nBits/8);
5 S( J% g0 {* `/ h- ^' EINT        output;- {" d3 o4 C7 A" s4 _7 a0 v
QUEUEDATA q;. f4 B  |9 j" A4 e3 z( D# x- n  I
DWORD        writetime;
/ s% N/ g) ~- [  J) @
) ^0 t. h4 M7 a  bLPSHORT        pSoundBuf = m_SoundBuffer;& o. Q# p  s) e7 n& W; a9 k; x$ r
INT        nCcount = 0;
0 ]( k3 E5 n5 t0 B1 z- ^6 r
8 t+ h8 ]0 h7 ?: V2 p1 OINT        nFilterType = Config.sound.nFilterType;
6 e6 a' g; {: N" H6 ]5 W; J7 v: P% i7 `% y0 g( v0 k/ e0 y2 a" p. @
        if( !Config.sound.bEnable ) {
" }& k3 B0 I& q" P% n                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; P% c3 |6 y* ^! h3 m* Q
                return;9 w0 V% ^/ g( y1 w
        }8 z7 n, q4 n' V4 S& K

5 j. l/ ]" a9 Z; g        // Volume setup
0 g/ v9 S! r. ~) ~/ \) D        //  0:Master
) V. S# i3 N, O        //  1:Rectangle 1
6 I- J; z2 v' x3 p! g1 r        //  2:Rectangle 2- C- H7 ?0 X2 Q0 x
        //  3:Triangle" Y6 m7 p; i9 N. C
        //  4:Noise
1 k" m2 Q8 {- ?- H7 w- u1 [2 ^        //  5:DPCM5 {& o* G) L! M2 h. N+ l  {  G
        //  6:VRC6
, K; B* F1 q, d        //  7:VRC7+ L! S1 a$ J3 J, Z/ W
        //  8:FDS
6 k  @9 p7 w- {/ M: H+ f        //  9:MMC5
7 |+ ]. k- L! a0 q  }        // 10:N106/ s$ t' X; u1 k' s. r( W
        // 11:FME70 `; V: C" ^- X0 a! b
        INT        vol[24];: m+ \4 W* J- N0 f6 w/ v
        BOOL*        bMute = m_bMute;
- x6 F  {$ e! ?) M4 `  M$ W        SHORT*        nVolume = Config.sound.nVolume;& a8 w! l( t) _# s! H

/ x& N( h1 z# v8 m9 p) O, v        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
. d6 g+ P! N* i. B
$ h% y5 o  |; i: ~: C! [5 U% Q        // Internal
! h% l$ U5 k# E3 [* C  `2 @8 e$ k0 {        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
" l" |  T/ G  e/ p* C        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;! [: X$ a# p* n+ _% ^
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;8 n2 X4 T  V# Z" l2 b7 O
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ n; ~( X! s+ U
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ h: U5 D' w  Z+ q$ y$ p  \. u" `) j) h1 O
        // VRC6
1 P4 a/ Y* ?0 V+ M6 q7 Z6 d        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) v/ q) @# Y( ]8 X
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! O& @$ k* n; \, l
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 v6 K8 L' R% z, @4 C

& q. [* E! |$ U* E6 O        // VRC7
3 o0 Q, Y2 T1 ?2 C2 z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;' C% _7 p7 }3 k$ R  c- W# K9 R' U/ X& v
1 e* Z+ C! E1 [' M
        // FDS; ^, U# H( a! B! B1 |0 @" f/ O" M
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
" A( G) N7 x( F# w
' V, H( Q/ J% O/ @  c- ?        // MMC5
8 h6 e3 k7 }7 u1 ^" [. N        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* O+ R" d3 \  V$ X* g# F9 j) {
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 {- c9 _: v' ?- |8 ^4 R% @
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, B5 _! U8 u6 ?) F# k
/ Q, R% G7 W7 [) n        // N106$ K; Q6 C6 x! m: X% P7 F: }3 [" \5 |
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 F% [1 j( ]2 b" C9 C) Z
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, N5 x' z; `1 P& |* V- n9 M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 M& v% Y8 Q, d
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 s. h  {, n2 Y- E! e
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 t- h" l& D+ T1 B5 `  [        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 U" X. d  _4 a1 @8 U, g( a
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 d9 Z7 z+ I3 v! T' V, l: c5 D. c
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' @* \! {$ ^+ ], K
0 P$ T$ X. X5 {! c$ h& b, w9 G2 e* M
        // FME7
& i  ?" l! L! P3 ^' H+ J        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ ]) U: l0 I0 q; `        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 m: }, C+ M/ I4 Q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 b# ?! ~% V7 |
8 S% C8 J  q0 u% D( {' k//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;- s: W! l( H/ I  M0 n4 A' S5 N" O  P
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; N" z4 N4 I7 m
5 n) q1 F* b$ n9 G! B        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 W' Q8 Z4 f" C  ?# g* [* X" ~        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
. s. v9 N" J$ m                QueueFlush();& @" ~) l2 x- z
        }' b( e: w7 X1 Y
. v9 i$ m5 K" Z$ Q
        while( dwLength-- ) {$ r5 o: U; v1 F* r) U; n) h! a
                writetime = (DWORD)elapsed_time;+ C5 m$ k4 o4 ]5 O& M$ b3 A

/ @" _. j/ Y1 a! @) ^* _% d2 e) d9 z                while( GetQueue( writetime, q ) ) {
/ Y  H0 z' ~0 N* \! b' [                        WriteProcess( q.addr, q.data );
$ x: \/ K$ D. W5 P4 v' g                }
/ P- t6 y, V0 @7 ?4 P% P3 ^3 K7 T! y  g
                while( GetExQueue( writetime, q ) ) {8 T, @  K3 v' t# Y' D3 g
                        WriteExProcess( q.addr, q.data );! v9 \" k4 I4 x
                }
- E, \. @5 e+ j  n
- t. A% p. h' ^1 B                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7* C" d; s0 E7 @1 q
                output = 0;
3 x$ f$ b/ r% P4 R& A6 U; Y                output += internal.Process( 0 )*vol[0];
: Y: E! ]+ M* {: J, ^6 p. z0 j                output += internal.Process( 1 )*vol[1];. \' C, }! b6 Y- z8 p- F& v# F
                output += internal.Process( 2 )*vol[2];2 Y, N0 ^$ O6 ~/ Q& }
                output += internal.Process( 3 )*vol[3];
# G1 k1 x/ L6 Y: g( |2 [* _                output += internal.Process( 4 )*vol[4];  G+ u% Y! [8 A0 ], Z2 a

1 J" R( Z% m0 `& _; b$ t                if( exsound_select & 0x01 ) {/ b6 m3 S7 A; g- J" z5 K: b  I8 x, ~% i
                        output += vrc6.Process( 0 )*vol[5];
3 b  c- x6 I: J/ }& t) Z8 o: K                        output += vrc6.Process( 1 )*vol[6];/ j3 a3 ~4 o* K$ B; y) P
                        output += vrc6.Process( 2 )*vol[7];3 d2 W. O% k9 r9 v7 @* v! |6 v
                }
, g! j0 Y3 `! |9 j  B                if( exsound_select & 0x02 ) {' G7 Y+ M' C: a3 C, a) M
                        output += vrc7.Process( 0 )*vol[8];' F7 I4 h7 y! S
                }
7 p' E! i. }1 s! Q5 A" w                if( exsound_select & 0x04 ) {
" w- I! q% Q  n" i  E                        output += fds.Process( 0 )*vol[9];7 W( Q/ Z0 z/ V3 }, v6 G
                }; ]* G9 _, b0 D7 H
                if( exsound_select & 0x08 ) {/ U% [" M  `, a
                        output += mmc5.Process( 0 )*vol[10];
, I6 s+ g2 E, w  x2 N- F/ W5 a                        output += mmc5.Process( 1 )*vol[11];
4 R: A# N: W+ ^# [8 @/ ]& Z# D8 E                        output += mmc5.Process( 2 )*vol[12];! l# ?. h" F& y" |7 S" O6 U
                }1 m0 n2 B3 A& ?* }; s7 J
                if( exsound_select & 0x10 ) {+ W+ J% t0 y5 ?% L* e; d* {
                        output += n106.Process( 0 )*vol[13];
  W  f5 d7 G2 X/ A1 v* b                        output += n106.Process( 1 )*vol[14];3 H* Z2 `  l* _% I+ m
                        output += n106.Process( 2 )*vol[15];, s0 B3 T) s4 x$ G; [; ^
                        output += n106.Process( 3 )*vol[16];
6 t# Y$ n3 Y. ^) f1 y1 g) `- V! F5 w                        output += n106.Process( 4 )*vol[17];% H% z6 B& u7 t* p$ R
                        output += n106.Process( 5 )*vol[18];+ I4 D% q# Q2 y+ X# B6 A7 F
                        output += n106.Process( 6 )*vol[19];# g7 a& H" ^; F5 y
                        output += n106.Process( 7 )*vol[20];
. b, r2 X* G- Y4 @# }5 U1 ?                }( {: g  j0 @2 N  g+ Z
                if( exsound_select & 0x20 ) {* Z+ \* s/ K# Y
                        fme7.Process( 3 );        // Envelope & Noise( ^' l" K7 \. g5 z! N
                        output += fme7.Process( 0 )*vol[21];
) P  p; g9 c1 t4 K! p1 S6 f) F                        output += fme7.Process( 1 )*vol[22];. J0 i2 y* l( S+ ~. d# N6 s
                        output += fme7.Process( 2 )*vol[23];. b. o6 c4 m- l* y" C) _; K4 [9 ^2 R
                }
7 e' h! q+ m. ?5 d( l6 k$ O: r/ L
7 G! o) ~' |1 F; h: b# T1 `                output >>= 8;; h$ y7 J3 C. m+ p6 \3 B
" `& w, N* h4 r7 z. W. J! H
                if( nFilterType == 1 ) {$ t0 l* Q. Z; f  j1 p1 u) W9 s) \2 M
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 r5 g: c" f' `5 Q  d$ H- v
                        output = (lowpass_filter[0]+output)/2;
& b2 f7 D) R4 _                        lowpass_filter[0] = output;) V$ ~, ^1 F) H  p& n5 {  ]3 Y
                } else if( nFilterType == 2 ) {; M7 @9 j8 b/ I' r/ G, t6 h: t  y
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
+ i* f4 k  k7 I6 P+ u3 F# b6 C                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
# I9 A* C% @& _9 n& d* d( o! l                        lowpass_filter[1] = lowpass_filter[0];) }" k! z4 G6 T. G! b  j
                        lowpass_filter[0] = output;* `. g% Y: w% \% b& |, Q4 o
                } else if( nFilterType == 3 ) {
+ Z; k9 s, ?2 L6 v0 D) g* w                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)% _* i2 A) H/ @/ ?4 v2 I
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
+ e, `- U+ ^9 Z2 w; V# t& X                        lowpass_filter[2] = lowpass_filter[1];
% f$ O# }" D' ^% P. |                        lowpass_filter[1] = lowpass_filter[0];  `7 ]8 ~# f& i
                        lowpass_filter[0] = output;
6 @& I6 v( j( {: F; K                } else if( nFilterType == 4 ) {
/ v1 h: S; c6 `. `" t4 G1 G                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
4 T, S3 F3 s. s/ E, t9 }$ P                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
& {/ _9 l0 ~- [4 }- t, v6 j                        lowpass_filter[1] = lowpass_filter[0];, D* c7 I: c. W# d$ Z" r. Q2 {
                        lowpass_filter[0] = output;
) b7 p/ }+ T- e: J7 j) q                }
& h) L0 x+ t: ], ~+ y: c5 v% M  H  [5 v% I7 ^
#if        0
- W. Z  t$ M& y3 t8 a& h                // DC惉暘偺僇僢僩
$ y  G% c7 \( w0 H5 E  m. @                {1 V$ k/ X5 X1 `
                static double ave = 0.0, max=0.0, min=0.0;/ |, b# u# E2 T' w! l- X2 C8 Y
                double delta;
  t) b0 @) S: M4 n; t: m6 Y: R                delta = (max-min)/32768.0;
7 K7 {" v& y% k2 Q6 \/ d8 I                max -= delta;
* O0 h( W( r) B% ^; t                min += delta;+ {) A( C- t, ^1 o! S( o9 x; N, X
                if( output > max ) max = output;
% H& Y3 |+ N  l. X4 d3 ~                if( output < min ) min = output;
4 P7 f7 n  G( `                ave -= ave/1024.0;- x( |6 Z3 l* R. N8 E& y1 R; ^  D
                ave += (max+min)/2048.0;
( N3 d$ g# }9 B$ D                output -= (INT)ave;
2 D6 y3 T6 Q$ U8 b0 e# i, ^                }$ B) ^0 @- j. @0 O3 U2 K
#endif
4 G4 E1 M. o. p#if        1
/ }( g9 ]# ^/ a+ |; g# K, R                // DC惉暘偺僇僢僩(HPF TEST)
4 h: u. z% t9 o: Q                {, D8 Z# i1 }9 n2 p
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 K: _! w& Z' ~9 v% o8 {) w                static        double        cutofftemp = (2.0*3.141592653579*40.0);: S" I+ D- M) q# X3 k
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
. K) W& f# Q- I  q) D                static        double        tmp = 0.0;
0 Z. U% j+ h" c% l8 |% P% c                double        in, out;
2 ?$ |7 `  U/ e* q, `" w. A0 P% y- W. j/ ]
                in = (double)output;
* Z4 t7 D: V! l; M  D. A                out = (in - tmp);
& Q1 s5 g  N; q! j6 F                tmp = tmp + cutoff * out;. N0 a* A6 W; C$ N' w, u

, b( P8 }, j$ L' f) v3 ?7 }                output = (INT)out;$ t& [0 m  m* Q* Q! e7 G
                }
: [5 W' Z  c; ]! m3 H! t. W5 y0 o#endif. p- H- f, ]( ?- K( Z) X( @
#if        0, M1 U( V* [$ I1 i9 w2 Q$ r! U
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
- @$ D8 O2 P: o$ O3 I                {
& i7 a. `3 S! W9 O8 [2 D7 ~                INT        diff = abs(output-last_data);7 B$ Q4 P  {. n+ w( U: {
                if( diff > 0x4000 ) {
% Y/ [; j* M6 Q! ?! }6 ^                        output /= 4;% J1 Z3 }. F. ?+ z7 \/ G
                } else * f" {$ {% h3 e4 k9 ?0 l$ K
                if( diff > 0x3000 ) {
4 Y# Q/ `) |8 Y! O! O+ K" r                        output /= 3;4 m3 m* C1 k. X+ \9 [5 c
                } else5 u$ V" H+ A% ~# k
                if( diff > 0x2000 ) {
) \, H# h, ?! ?2 y! m: @% q6 f                        output /= 2;' c$ B1 l- b& k5 b9 j
                }) G- _' ^' ^  a* N+ h  E7 V
                last_data = output;
/ e/ l, v" B8 e/ I                }. e5 ^/ ~/ b7 N+ }& b3 i5 p
#endif
6 r- y- X/ S$ ~' c! g5 I1 \                // Limit( F# g$ B2 [1 [! B1 Y' \* z
                if( output > 0x7FFF ) {
$ F5 A3 F" R1 \: S6 C                        output = 0x7FFF;
' G% \  E7 g" o                } else if( output < -0x8000 ) {
6 Z! L( h  T! j) `! h                        output = -0x8000;
6 u& J$ ~6 M6 s6 T5 h* _$ D                }) O* t( k+ d1 \( {. j

) u$ E( |1 I! |4 {1 U* @/ C  E                if( nBits != 8 ) {( r6 |5 ]5 B6 I! [! G
                        *(SHORT*)lpBuffer = (SHORT)output;9 N" X6 t1 v3 o% W; K
                        lpBuffer += sizeof(SHORT);
) x' Y+ \) @( U4 p                } else {
0 d2 `9 U# \+ q- d3 L' h. q                        *lpBuffer++ = (output>>8)^0x80;
5 o: R9 r9 `% ^; T2 }                }( f& o; B0 y+ m
9 q- f' E9 y0 |; D" i0 Y+ s
                if( nCcount < 0x0100 )
% E7 L; H% Y" W6 ?1 p) E  l6 w1 _                        pSoundBuf[nCcount++] = (SHORT)output;) ^! K9 |( H  M+ G0 _6 A

0 H# S& ?+ r1 I) C0 p//                elapsedtime += cycle_rate;
/ a/ p! ^# s1 g* S0 h7 y" A3 O5 v                elapsed_time += cycle_rate;
" G4 U4 U3 c5 w; {1 O9 w        }! n7 h) f# f) X* Y; x- E+ }( _
. r8 t# }* t- n& ~7 @1 g& B
#if        1/ }0 Z% s+ q8 ?  O9 g* c) A
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 w2 m# {. F, H+ V- Z: d
                elapsed_time = nes->cpu->GetTotalCycles();" {1 y9 W! \6 q! q1 \7 x$ ^' I
        }5 q9 n7 T( j0 O" B
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {  n6 O2 f4 e. _  m
                elapsed_time = nes->cpu->GetTotalCycles();
  n  G1 H: @% G3 H; v) f, v        }+ _& o! G0 U4 z) n3 A' o/ k
#else
+ y( K+ o  Q- I- k1 c& m* I        elapsed_time = nes->cpu->GetTotalCycles();! \  w& z( N5 _6 k& T3 e1 ~/ i
#endif5 a4 o( U$ ]8 b3 u, r; r
}
! h8 w! M2 [, S5 Z9 T, Y" j) y6 G- B$ g. ~" ?  f4 L! p4 `
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
% B0 h, r/ o0 W7 Q1 kINT        APU::GetChannelFrequency( INT no ), A+ x$ I6 Q/ m+ O% E  O1 }7 ?) u
{0 p' d" A$ E3 q
        if( !m_bMute[0] )/ g3 l. H7 N1 e
                return        0;$ S+ D, M0 S( ~7 l
5 `# u& m% h1 K' {5 g7 z
        // Internal
( l+ Q% X$ K, B$ J/ q! q: p' L& y        if( no < 5 ) {6 o5 H: r! U+ d: e( O+ T$ Z
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
4 S) l+ |' `2 `1 A9 u" |$ X& }        }8 s0 s! F+ X5 j' b2 A3 w# }; i
        // VRC6
% u* K; k) M0 y4 y5 U% Q$ o        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
3 Q# l  H+ Y& N- c                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  O% t* F: E- s+ Y
        }: C, V0 M7 F1 z. x+ \7 b0 k
        // FDS
- }5 S# h. J8 @% [. \- f3 R* q6 r        if( (exsound_select & 0x04) && no == 0x300 ) {
3 k& I3 Y2 A/ k. S6 S                return        m_bMute[6]?fds.GetFreq( 0 ):0;( `6 }, K% E, G
        }& z8 F/ D. Z0 O' i  ^% G! L
        // MMC5
& P" O, s5 y9 P  B# I        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {; g0 Q  V/ R5 y6 q0 g# n- Q
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 {7 A. O! _4 u. ^: {" G
        }( S1 B! J7 R1 d, H6 \
        // N106  ]0 b  [# R. {! f
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
# x2 B3 W  g; x- f% Q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: W" v) B! A$ @2 n& F. F1 f' P
        }" P8 j; Y4 P4 }
        // FME7% }' Z% K' U& c. w* j" Q1 l* }
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% [+ B+ l9 s1 ]1 u
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;; ]/ Y; F9 r4 a) E# S7 T" V9 U. o
        }
) p2 c: K4 T2 N( J; R6 c& P        // VRC7! ~5 V" j4 L5 T7 d7 k9 _
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 L: \% t- K" n$ w0 S                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 L$ G; [# k& q2 G9 k: }4 L2 B        }! L  b- F1 Y/ ?1 @& p7 c
        return        0;  \) @, B$ p: A
}2 v4 l+ Z- t: @2 x4 l% d# Z

3 w. {5 e4 R' w. G// State Save/Load
  X! F- a9 ^: H% E% \8 Pvoid        APU::SaveState( LPBYTE p ). A7 A8 J# b( a
{
5 ~* g* A" F# O8 C1 K5 I#ifdef        _DEBUG! Z+ {" g/ I: s# `( i5 [% e
LPBYTE        pold = p;
8 P* e  _# C% N: A+ y#endif- i0 J( [0 X% u

, ?/ b# H0 m) U7 R; @) l        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; S2 T: t; s7 H/ o, b1 O# T
        QueueFlush();
0 b: ]1 u1 g0 i" `) x$ L) A5 ?4 ^2 W; j" i
        internal.SaveState( p );0 q; r+ u% v2 x+ @$ V$ Z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
1 R/ H; U: \( ?  g) g
; {. L( O2 k2 F6 n6 P        // VRC6* G3 S: ~/ B: w) Y/ B4 e
        if( exsound_select & 0x01 ) {
4 e. T6 D) D  [* t                vrc6.SaveState( p );
5 W8 Q% O+ l, k5 \! L; t8 f/ K                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 p' o+ f8 G" C# C/ X, G
        }
8 i0 X! F! T! _' ^" c        // VRC7 (not support)1 _; j$ H. G( q3 k3 P
        if( exsound_select & 0x02 ) {
! h! E% u' N7 N( Y/ N4 H                vrc7.SaveState( p );
+ Z0 |# G# A8 P) v! u0 i! ]* t0 [                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ S/ y% @% m; }0 T  C  ~5 K6 m9 M
        }2 z1 Y8 {" O" }' Q$ H3 @
        // FDS8 Y9 S7 k* t( B. J
        if( exsound_select & 0x04 ) {. \- a1 N( t( i: z2 t) P
                fds.SaveState( p );
& P. ?. ?5 l# [6 Q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 @4 F6 N9 k5 m- F+ S
        }
$ K) n5 i7 J9 |        // MMC5
" k& ~  w# H/ c1 Z# O0 \6 d        if( exsound_select & 0x08 ) {7 v/ G3 X8 D+ d9 Q2 W5 h
                mmc5.SaveState( p );
3 G- j+ ], K) u: B  l8 n: K                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 s% a' O" q$ z3 Q+ Y' V
        }9 x. h/ i1 |  L
        // N106
7 ~2 X) V4 x: c6 z% n( j        if( exsound_select & 0x10 ) {& j( e; a  F* E+ f7 V6 b6 E- \1 I* J
                n106.SaveState( p );  Y1 S" j* B2 z0 d9 a& c4 m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& h1 Q6 K& h- r. Y: I% r        }
* P7 C. Q9 J& k, }) y* G, A8 p        // FME7
1 `* o* J0 U" c4 q: x( m        if( exsound_select & 0x20 ) {
0 h6 |2 e; V. b4 t  i                fme7.SaveState( p );
. p. d1 ^, Z/ t# I( m( e                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! s& I# I. W4 @3 R        }
" C' G7 [) D7 f6 p5 q+ y% y: E6 |" q. u
#ifdef        _DEBUG  k* E/ o2 N' f7 w
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 V/ C/ d% a0 S) F#endif
% [% j' L7 E" m# n, l}5 P" c- @* k$ W0 n
" x) w8 V& d! x+ j& R
void        APU::LoadState( LPBYTE p )9 R" Z. `! D' C# @+ A) y/ @/ Y
{3 a8 P& G) C5 V9 v) C
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡4 l  A  {0 U! P1 q: N' n& Q
        QueueClear();  L) m, H, Z  l$ W
+ v& i5 b" F: v' l1 h. e
        internal.LoadState( p );
8 ]' _) [! Q; X  k3 b6 n        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 ]  {* C# A2 o( f+ W0 g: H5 A- R0 I
: O5 Q# T! A" U- ?        // VRC6% z+ N% H# f/ O" d% S* Q6 D  Z
        if( exsound_select & 0x01 ) {( Y1 A% p- b- q2 g: N) u
                vrc6.LoadState( p );- ]% Q( ]  n0 L* a: Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 _# o) _/ J  p/ S, s) _        }6 N( t$ g+ P/ v
        // VRC7 (not support)8 k7 v4 [9 g9 p4 S; G9 \1 r, e
        if( exsound_select & 0x02 ) {
  ?; a3 O* p1 w8 W" ?# Z2 V* W                vrc7.LoadState( p );
5 R  U7 t6 p) Y0 j                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 q1 S6 ^! t; x* x3 R4 Q3 u        }+ d6 ]' h: P# U3 z! g( w. Z0 ]
        // FDS- J! h! Q3 \2 n/ r* v
        if( exsound_select & 0x04 ) {6 r5 G0 I: N  `) I# r! p, C
                fds.LoadState( p );
- r' Q; V5 j% ^; ^: ?) I" _                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- G2 ?; O5 ^7 L, U: I. O        }3 i/ O6 K' L( M* r) x$ t4 q1 h
        // MMC5: T% ]- H0 v2 f
        if( exsound_select & 0x08 ) {
6 t; V4 x& k) d/ }- l  V  z4 b% D                mmc5.LoadState( p );
" s/ E3 f6 v. j8 }                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding) i, v/ D0 ^3 w9 k8 V
        }+ D& L( p& @  {* G
        // N106
. K' ]: }% {; l% v        if( exsound_select & 0x10 ) {- k. E2 q' N1 \' P/ p
                n106.LoadState( p );$ V2 N& \8 h: ~/ A2 {& ^5 V7 j3 u  o. ~
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 ?, G' V* u+ c+ t2 Y2 K' W  w
        }7 k  _& b, B& }# v0 ~" c, `
        // FME71 M2 t: m: H4 z) i
        if( exsound_select & 0x20 ) {; f1 D, C2 }+ X& e. `% F4 X1 r+ O; f
                fme7.LoadState( p );
8 X. C7 X$ s5 r                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 R. K1 T! j0 [7 y& t4 @
        }
' ^: M7 _0 F  s}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, W+ ~! ^$ l" k% K* @9 }: w8 e可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。  _& A' B) w1 H+ z
感激不尽~~

2 t1 E8 K- R; H3 V! T% a恩 我對模擬器不是很有研究,
" ^: B7 S  @- h雖然要了解源碼內容,可能不是很困難,/ _0 t/ U6 t) f- K2 \$ ~- V% j( a
不過還是要花時間,個人目前蠻忙碌的。+ S% T' U" P+ w% Q4 ~
0 _# E4 ?0 D* o" }
給你一個朋友的MSN,你可以跟他討論看看,
# s  d3 k, g# X  S/ m3 m+ f. W他本身是程式設計師,也對FC模擬器很有興趣。: h& M. s! @2 c- m
* M8 L. T3 y) h% m
MSN我就PM到你的信箱了。  P! y" w0 L$ z6 N% ^3 ?8 w* n
4 Q0 q1 w+ K3 h7 m: Z# s% z
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 1 F! \/ J) V) w0 W! C# L* f5 {8 ~8 l$ N- \
呵…… 谢过团长大人~~
) ]3 R5 B+ n8 |$ o: u8 G4 Y

3 J/ F. X$ n) G( w$ f哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 8 m# P! s: @) c
团长的朋友都是神,那团长就是神的boss。
; J2 b$ X. Y, h6 O9 X
哈 不敢當,我只是個平凡人,- ?* t0 ~* O& _9 a  S
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙3 I7 a/ S, s" F$ W( {
ZYH7 A/ s, j$ E' d& Q. d5 x! H
QQ:414734306: Y% |1 n5 x/ M$ Y$ [
Mail:zyh-01@126.com/ b9 V1 N, o5 U; B, ~9 m

- ?1 ?3 z; B  z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 k8 X1 A9 h* F7 U. e! {) Y9 K; g
再次对团长大人和悠悠哥的无私帮助表示感谢~~
, u" ^/ ^2 V8 Y$ v$ {- n$ w/ x
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-13 07:03 , Processed in 1.126953 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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