EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
: n; h% I' F1 W, [, P7 I  g" D" P8 P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) ~6 k9 R0 m0 T7 V, C- \8 X9 I( e这里有相应的模拟器源码,就当送给大侠了~~
8 R) k5 Q5 Z# I, Qhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 , p( F+ \) b0 K4 B$ S* d$ A
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 |: S7 y& n! w( e% ~! B
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  S" l$ e: K# U: K( o/ a1 L这里有相应的模拟器源码,就当送给大侠 ...
% Y/ c$ _$ p) h* }
聲音部分(Audoi Process Unit = APU):  k+ v8 I* z" B4 z& g* A
.\NES\APU.cpp" N# z0 W+ i$ O  C: ^) c
.\NES\APU.h3 }5 w; }7 n+ t4 Y  y  M0 G

1 B4 _+ o' T1 ?- v& V+ V* t
/ i# q7 z; @5 v( C- {! U: |  X影像處理部份(Picture Processing Unit = PPU):( q; d( s6 N8 C. _1 C
.\NES\PPU.cpp0 L; |0 K. W$ ?; y: o  f! g& \
.\NES\PPU.h' G7 g/ [- O9 }5 R; d- K4 X

: B8 p) l9 M0 k如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  M' R$ I$ g# t. h* q% X! w
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
5 s, e& B$ v! F$ c- \" Y//////////////////////////////////////////////////////////////////////////& ~  K- w; J- e' _
//                                                                      //+ r; V5 N: P* Q/ X9 o! t0 W
//      NES APU core                                                    //
* S* g% u- F/ y- |  {) J//                                                           Norix      //- i& P6 `6 J% E4 T: n; d( `
//                                               written     2002/06/27 //+ V2 ]5 J, U' m2 }
//                                               last modify ----/--/-- //
  R6 @2 u) g7 Y  M- \1 v//////////////////////////////////////////////////////////////////////////$ E' k+ r+ d6 m6 O
#include "DebugOut.h"
) h* O5 O* d! o; U+ Y$ x9 t#include "App.h"
$ ]" s7 _7 |. f: I9 @#include "Config.h"  @  F7 X3 H; F" y( K' C4 v- y
4 r8 b, |. W4 h6 C6 K6 G
#include "nes.h"
' e9 X* a9 ^: R& @- w#include "mmu.h"
: o- t- B. e2 N9 ~#include "cpu.h") x! m, y) R# Y+ v* o/ h8 E
#include "ppu.h"
' n8 ]/ J! v$ ~5 S4 {$ `#include "rom.h"
! S6 W( r' U& l/ t, Z3 R8 _/ _$ W#include "apu.h"- \; `& l$ S( _5 Q) r$ ^

0 a. C, i) S& ~# v// Volume adjust
5 b: q# s( K5 U( `// Internal sounds
& p' Q! l  z% x! B#define        RECTANGLE_VOL        (0x0F0)
' Y. y" v9 H0 _! o% ^! j- r# o#define        TRIANGLE_VOL        (0x130)
" ~- u( G+ {8 q1 F" |% t: G! b! w#define        NOISE_VOL        (0x0C0)* V1 W1 }/ C" I
#define        DPCM_VOL        (0x0F0)  v% F9 k/ d7 H3 ]. }2 ^. g5 X& v
// Extra sounds& q5 b8 y1 W/ v9 t9 U5 s
#define        VRC6_VOL        (0x0F0): r9 c9 b( Y' r/ {' {
#define        VRC7_VOL        (0x130)
3 g2 X5 @1 Q* C& K+ S5 j6 c0 Z4 g6 @9 K#define        FDS_VOL                (0x0F0)
# R. f. Y% s0 b: ]# `. z" Q6 u#define        MMC5_VOL        (0x0F0)
+ ^- _5 U# a8 W$ F0 E5 t' g" G#define        N106_VOL        (0x088)
, F0 g0 o; ]% I, L- `#define        FME7_VOL        (0x130)0 i0 D) x3 m8 t4 `  y4 L/ C
- s" W5 J% Q( d6 W6 M7 j' i
APU::APU( NES* parent )
  [) @2 N, I% J5 e  n& Y! r{, _7 Y( ~4 u2 j
        exsound_select = 0;2 h' O8 x  K0 m% P
" b! t# ]% C+ b9 K- z# r; H
        nes = parent;
! O" c% s* \4 i* |/ S/ M% x        internal.SetParent( parent );7 V' p1 @$ x3 [1 v1 D

" j$ ^9 Y* b+ S+ Y  t        last_data = last_diff = 0;
) C3 f: w& y; m3 n% L( k  m- O9 U0 {" }5 y# [$ k& n
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 Z4 D) ~3 I/ ^5 Y$ `5 ^
5 T* O$ V9 R8 x( ^3 b: A0 T( @
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
4 i& @4 t3 X- Z  ^0 ^        ZEROMEMORY( &queue, sizeof(queue) );6 z) m7 b% }& a! p4 W1 j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& j2 O5 ^$ T" h
$ n) h( ]( I0 d9 m4 z
        for( INT i = 0; i < 16; i++ ) {
8 v$ G6 D) x' F9 g$ Q/ m) b1 e; k( b, r8 l                m_bMute = TRUE;
* e' q! m) ~# v5 B; j        }; e0 `6 _2 \+ _' _2 u; |
}/ w- x, S, h: J! g+ \

2 P# q# v: t- T$ q- jAPU::~APU()) T- w: _0 [1 Q) `
{
+ v" |: H" f5 j3 ~, h# n}
) f: b1 {; U$ R3 _$ j, z) R, h
& n. m1 Q0 H; H. E% l; s( D8 ^2 ]void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
* E% t! H. o; e0 h  b{
5 G5 {  J5 S4 B8 N! C0 c! L        queue.data[queue.wrptr].time = writetime;
0 W! h" o/ p/ M5 H7 K2 F$ M# t        queue.data[queue.wrptr].addr = addr;- U+ x2 n7 c3 {; ~
        queue.data[queue.wrptr].data = data;  \6 j) @$ u+ }2 ?+ P
        queue.wrptr++;
8 X  a" X+ v+ Z0 I6 [        queue.wrptr&=QUEUE_LENGTH-1;
6 P0 J' v, {! o* m6 E3 `! \        if( queue.wrptr == queue.rdptr ) {( m% ~$ i; {& R6 a- w/ q7 B
                DEBUGOUT( "queue overflow.\n" );8 q; W' J; X, u
        }
# I( w, Y& a% D+ |  f3 E, }* G}
9 @: _: r) \, a& J5 Y0 N! `) W) W4 M, ~0 j. [, L& T! {/ a
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. l( y0 {' [& d  w6 C4 O{( f  w8 I4 r2 B& h2 c# N
        if( queue.wrptr == queue.rdptr ) {
4 C4 l) p4 C/ ~/ c( `                return        FALSE;) y. `) e& E. S8 ?/ a& o- U
        }* W) [# h) R) [  Y4 M  w
        if( queue.data[queue.rdptr].time <= writetime ) {
! y# w1 H9 \& c* E( S  f) f9 t+ z                ret = queue.data[queue.rdptr];& m, [; a& U/ K* U5 s( X0 ^
                queue.rdptr++;: E/ v& ?: G0 N% N  S' o3 m! U
                queue.rdptr&=QUEUE_LENGTH-1;( H' M( X: g+ f! w
                return        TRUE;
1 Z0 t# N5 H; x& {8 B/ m3 T$ {        }+ K% @+ |# X" W' a
        return        FALSE;
- [1 G: h+ }9 `- c}
8 H5 |# X: y, ^* T+ @; V$ ~3 k0 v& Y9 q* j1 N( ~
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
, u, [3 Q* L) r/ r* ?{1 C5 _; A* d9 ~% P
        exqueue.data[exqueue.wrptr].time = writetime;+ C( m$ h$ q) j% ~9 r9 F
        exqueue.data[exqueue.wrptr].addr = addr;
9 T& ]8 A) J: D: x# A2 y2 D        exqueue.data[exqueue.wrptr].data = data;) O% y8 S, E' H8 ^& k
        exqueue.wrptr++;
, T+ W# i1 u9 Z        exqueue.wrptr&=QUEUE_LENGTH-1;, B3 E" v- X8 ~; x) @% x2 a
        if( exqueue.wrptr == exqueue.rdptr ) {
2 R( r* X+ F  b$ B+ X, m9 H                DEBUGOUT( "exqueue overflow.\n" );9 a4 d3 A6 P, g3 {/ o$ v) y
        }4 T$ o- s8 M$ @. B, k5 A* p
}
/ S) X) q8 Z& E8 @) o% Z% K# z# }% h  d; L* g4 |8 C
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ); U. V$ |3 \  R+ n# l# t6 q
{0 e3 p. z& l9 U
        if( exqueue.wrptr == exqueue.rdptr ) {
  Z0 |" a8 T4 u                return        FALSE;- E* N* ^4 E$ L* [, ~; o
        }9 f7 H& q4 Y7 P+ a0 J6 p6 q
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: R$ B4 X( m2 ?: H+ O
                ret = exqueue.data[exqueue.rdptr];2 x( l2 s- L  X4 ^0 }, V+ F9 _
                exqueue.rdptr++;; h# ]' a# _. @' E( S  P/ a$ j  S
                exqueue.rdptr&=QUEUE_LENGTH-1;# n( }( y/ n, \  ?. O# W
                return        TRUE;
+ J# B1 y% j5 x/ q0 P% j; `/ O        }
+ y8 u' F. J6 p# Z        return        FALSE;
( A. c- t1 V7 q% D* [: h8 r}
  [/ O5 c5 O( G4 O; o$ |: f5 M  j! s" {% X
void        APU::QueueClear()
+ }8 [- ]3 d; G/ V  l( f+ D{2 D( ~, n  H  E' c1 i
        ZEROMEMORY( &queue, sizeof(queue) );
* N1 r1 g! H+ p3 u  m* ~2 T* k, X        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 Q5 x; K6 S. n/ w# t* L* U7 m- Q}
8 B0 O/ _/ h: P$ r
% ?7 k- R" Y" Z9 T% evoid        APU::QueueFlush()
; g2 H! B; K: r  d& n4 ?{5 j4 L3 e* a$ X) R" I$ H
        while( queue.wrptr != queue.rdptr ) {1 _4 r" o# o+ Z: e# F# P
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 c7 y& z, p& g$ `7 d+ D3 t* h" ?                queue.rdptr++;2 A0 W; E2 m3 V
                queue.rdptr&=QUEUE_LENGTH-1;9 v* I+ S) I: A9 k6 E9 I
        }. q  F8 D1 L) l/ t9 T3 q

2 l, d- R/ i$ ~6 m4 P        while( exqueue.wrptr != exqueue.rdptr ) {
( y* X$ i6 B) W& ]' _                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );$ w4 Q& `4 x/ w0 C( g
                exqueue.rdptr++;7 m# u4 }+ L" \
                exqueue.rdptr&=QUEUE_LENGTH-1;  G0 l0 }5 z5 o9 K& o) o
        }1 w0 a, x) Z5 y
}% y0 m- Q: `! k- P* `9 |, g
* ~2 u3 U7 w2 [2 Q
void        APU::SoundSetup()
% [% Q4 K% ]: r; A- i2 q# v{0 i" V1 m( d, l) {/ j0 s; _
        FLOAT        fClock = nes->nescfg->CpuClock;" ^, p! f5 |7 |; a. u2 `: X$ {: }8 o
        INT        nRate = (INT)Config.sound.nRate;  f$ N2 y2 r1 i4 e7 j) b
        internal.Setup( fClock, nRate );
/ E1 [8 ~( I6 |/ W+ _( B        vrc6.Setup( fClock, nRate );
& t3 m* g) j* T& K        vrc7.Setup( fClock, nRate );1 Q% E% k7 J+ e8 V; M0 ~
        mmc5.Setup( fClock, nRate );4 l5 j" G0 I& k: [" d8 [, p) ?9 j8 i
        fds.Setup ( fClock, nRate );
. H5 ^+ `: ^; X2 e; I8 A! y        n106.Setup( fClock, nRate );
; ?0 [5 G$ h: h$ O* ]( Q        fme7.Setup( fClock, nRate );
; }  j4 T; Z* o5 t* X) Y0 u/ H- m4 ]}2 S( G3 `& A/ [9 Y. ^( L

/ I; A/ ?% E" J* T! wvoid        APU::Reset()" U+ t) H1 L# j, p5 [- S4 c2 y
{$ \$ @2 @3 i: s! r/ w5 k$ J
        ZEROMEMORY( &queue, sizeof(queue) );  p: ^- r5 w6 a; q* [6 {4 y' }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% K: \( c$ d' L! U. b9 U; m5 {' r- @$ E! j' A+ V' p
        elapsed_time = 0;* b: v3 t. `3 L0 Q
$ R$ c. M& {3 Z/ {% m
        FLOAT        fClock = nes->nescfg->CpuClock;
2 ]. c' z4 a/ F( n        INT        nRate = (INT)Config.sound.nRate;
* c- n! K# |7 g/ ~        internal.Reset( fClock, nRate );
+ Y/ A. B8 Y& o1 U0 t        vrc6.Reset( fClock, nRate );
) B0 w  A! \* m! p% Q+ e        vrc7.Reset( fClock, nRate );
- j8 Q% S8 N1 e4 u; I        mmc5.Reset( fClock, nRate );- I. P% X# Z3 ]/ k
        fds.Reset ( fClock, nRate );2 C* d% u0 f$ l& O# W8 M
        n106.Reset( fClock, nRate );. j9 A( t4 G+ C- Q4 c6 S
        fme7.Reset( fClock, nRate );' C  G' l; h& c5 w- w- y( q
7 d- a% a9 r- [
        SoundSetup();. y5 B, l7 s* v+ s
}4 r- v5 h' ]* w

0 I& p  R- h) m1 B8 Rvoid        APU::SelectExSound( BYTE data )! S* |$ d  l8 D5 o
{0 V9 L  z0 r! m: S2 _  w
        exsound_select = data;
" O9 @! v/ T$ k. Q0 g}$ {" r! W# y# @

! E# |4 p- R2 P9 ?' DBYTE        APU::Read( WORD addr )% P% N( x' t0 t4 m7 i, K$ u
{
$ P$ m1 G9 P* u4 d+ F' [. N4 m        return        internal.SyncRead( addr );
6 l( g/ T7 `, Q+ K) y4 W; b9 i}4 y% k" q7 ^, F) ^1 L

; Q1 M3 U6 @. p* K% K3 zvoid        APU::Write( WORD addr, BYTE data )
+ E; a  y% \! }9 S* b{
! y" m6 w  j+ Y1 ~, v+ I+ x2 {& C        // $4018偼VirtuaNES屌桳億乕僩
7 j! {# \$ T3 m: m2 [$ R/ O        if( addr >= 0x4000 && addr <= 0x401F ) {
7 t/ T2 k7 I9 V- ?( i& `                internal.SyncWrite( addr, data );% I& o% o1 s2 L6 N3 I: E
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
8 v' K( q; B& a- k        }
5 I2 d3 m4 n! U# K}
/ l2 k; ~- i/ H+ Y
' J6 r+ u+ {$ Y/ f- f( j/ P: mBYTE        APU::ExRead( WORD addr )" f* a/ Z. K9 b1 [3 O8 Y( ?) h
{
# H% K& ?6 g$ v0 W3 E/ f+ wBYTE        data = 0;/ y4 s/ ?+ R5 M( D& C: l( m
$ j2 Z* T0 i  I, M& |' F
        if( exsound_select & 0x10 ) {
# G' B* d& E( J" V! E0 \                if( addr == 0x4800 ) {
0 l# b/ U5 w4 W. Z. N4 D' R                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );) e/ B( ?6 u3 \1 j: C
                }, _2 l: S+ `, ^* @9 Q% N0 v; c
        }) d) W$ F0 O! q+ Z2 [+ L
        if( exsound_select & 0x04 ) {
; c" e0 s$ U1 e8 L& s1 b+ {# n* f                if( addr >= 0x4040 && addr < 0x4100 ) {9 o% d4 S. C( _0 V' u
                        data = fds.SyncRead( addr );$ m6 |; T, x: K& ?& I5 i
                }
" P) a5 M* I( i8 f' p; y+ D        }
6 O* l$ x0 J" a) D        if( exsound_select & 0x08 ) {
$ y( J& e9 T% X  S                if( addr >= 0x5000 && addr <= 0x5015 ) {
  B! d- t* v& n% B1 [: I# c                        data = mmc5.SyncRead( addr );) J  B! N3 z' w4 S2 ?+ w
                }
& [  z& m6 q; s) _8 l/ @- |        }+ S5 e8 `4 x% }$ K

! G- ^! y) j* w/ }1 R        return        data;* _) d) K5 y4 o5 \, Y9 P0 N. {
}
. E' x1 {2 o  _* E) ?1 V
+ `8 Q9 @6 y) M7 J4 [void        APU::ExWrite( WORD addr, BYTE data ): @6 W1 M- W5 n2 N; f! ~1 J; J
{
" j2 B3 N$ w7 d8 c6 Z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );1 x) n' q  t3 ~, s! \5 ]' {+ G- w* ^

* [- @* p0 S  |6 d& O        if( exsound_select & 0x04 ) {1 j; Q. \- k' ^% H7 ^. [! H. v
                if( addr >= 0x4040 && addr < 0x4100 ) {8 e( i6 ]  I+ C* o
                        fds.SyncWrite( addr, data );; ~9 T* Z( i6 e6 V! ]) s8 d7 |! K
                }( U: q2 m$ m  Z6 l) r. b* Z
        }. [' v# y7 M2 R; E
6 n% Q. |7 ]% p
        if( exsound_select & 0x08 ) {0 y- {3 b0 O. v+ ~
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 w1 v$ G: B8 f
                        mmc5.SyncWrite( addr, data );% W% f4 q% \9 E  Q% M4 e
                }
, N/ E6 X8 P! X5 y2 d        }
4 t' P+ ^! U. u% D8 {% M}% x6 y2 c" U/ J5 I+ k- @
, u4 a6 p6 s% c6 f& r. T
void        APU::Sync()
& Q1 U, |9 b7 n( C! H{  m- I2 ~# O' H: h
}! l8 b+ i, j) S) ?
% o( m1 y* x. N: |' e+ R3 L
void        APU::SyncDPCM( INT cycles )
- v, _# ?% }" b8 G, \{9 _" W7 N) n7 h8 r' n
        internal.Sync( cycles );: r* \& H. L1 G% P; O4 e
6 s$ b) O( c' b, p
        if( exsound_select & 0x04 ) {
' ~$ K1 L* M( e                fds.Sync( cycles );6 y2 V+ ~: Z) b& z7 Q2 ?5 _; v& v
        }+ l7 i2 C( h2 R: @1 r' E$ C
        if( exsound_select & 0x08 ) {
% O* z3 V$ Y; W' D                mmc5.Sync( cycles );% a. U; l! v, h0 }8 m- A
        }
+ ~, p" F& X9 V( r}6 G2 D6 D5 ~  u
* F+ a" p3 N1 V, I6 D
void        APU::WriteProcess( WORD addr, BYTE data )
! F: i9 f) x! U7 e{- n  ?- q. m3 H& Z7 W+ _
        // $4018偼VirtuaNES屌桳億乕僩
0 W" U. W( L6 `( f  _/ h' F! m        if( addr >= 0x4000 && addr <= 0x401F ) {- E- b; G  d  F: }, b
                internal.Write( addr, data );: U  ~/ i) ], Q9 X, M7 Q2 J. c
        }2 Y. E  O! U' `, f. ~
}0 n% W! X) t7 r4 H9 g# q4 W  @0 }% f
' W3 T. h* o: n) {5 |" Z- K, c
void        APU::WriteExProcess( WORD addr, BYTE data )
- g8 j% V- v- v( u! S{
4 a4 N; u' w, W8 L' R        if( exsound_select & 0x01 ) {
- b6 F4 d3 W/ d& I! D                vrc6.Write( addr, data );
% Y$ }, {" E: F: K* N: v' L        }
) m1 w+ }2 p% o6 H& z5 Q0 S        if( exsound_select & 0x02 ) {) `5 X- |$ f8 C; Y+ S, Z
                vrc7.Write( addr, data );
6 }* P% ~8 G2 m4 P3 S        }
4 ?( [; w+ t4 y        if( exsound_select & 0x04 ) {
, E- g/ ]% b7 C# j0 ^                fds.Write( addr, data );
5 ?  [5 M" [; Q! E& V) f! h        }
% R2 z; s- Z9 ^. P- L: m3 C        if( exsound_select & 0x08 ) {
! v; h8 u& W* f3 t! F3 T- Z6 |                mmc5.Write( addr, data );- {7 n; V, V5 ^: e1 ?7 d
        }6 Y: r/ ~% m6 V; ~( j, a) k. p
        if( exsound_select & 0x10 ) {
. g- a$ `( n/ S                if( addr == 0x0000 ) {% k' \3 f# f7 E3 Y' \2 ^$ m
                        BYTE        dummy = n106.Read( addr );
; F3 t) j, a9 B9 R3 d% H0 a! w3 ~                } else {( K- o! P* ?3 L+ U: Y
                        n106.Write( addr, data );
% b6 F0 o1 r% N3 B/ Q8 k9 W/ v& f                }2 S* U% Z: y2 ^3 k
        }. W  G3 f+ ~5 e6 L7 f
        if( exsound_select & 0x20 ) {$ M' X; J3 V, U( {/ @3 n" s" c
                fme7.Write( addr, data );: h$ ]( s3 n3 O8 w; t0 @
        }6 L; v( N# B/ K+ c1 X: r. W
}
! G5 H, B% [: i: k0 s1 Q
' L/ O: Z  f7 w6 h9 \, x. W: Evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )1 ?% s2 w( B) i$ n0 h5 [+ n
{
8 ?/ [3 H/ D/ W5 J* b& E  x( jINT        nBits = Config.sound.nBits;
3 m8 N3 {6 Z7 kDWORD        dwLength = dwSize / (nBits/8);9 h) E+ z1 C8 z; |6 s
INT        output;) G2 F! E; U5 r0 Z/ m4 \' j5 x
QUEUEDATA q;
( ^) Q% a$ {6 VDWORD        writetime;
- x7 H5 n+ Z  N( b5 A; L# G+ S3 d# I. W2 I8 L
LPSHORT        pSoundBuf = m_SoundBuffer;- C8 f; B+ O" M) z5 ?" |3 g
INT        nCcount = 0;
; C% g( ]/ ]# L) R' O$ q3 C* M7 f2 b0 S- t7 h6 Q0 i, F
INT        nFilterType = Config.sound.nFilterType;/ `) I- }0 e, Q1 H3 L( H, q
# O* w0 ^: r0 r4 r* \
        if( !Config.sound.bEnable ) {
; Y% P! j2 S( b3 U  z* S% I                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );) z& U2 ]9 a" i  r9 T1 G
                return;
: @7 A; U/ K; |" |" }9 H0 v5 ], s% o        }; M5 ?) Q6 R) _6 v

+ `/ g: A/ R( \2 t        // Volume setup8 }6 _3 `, ?( z! y, o
        //  0:Master/ Y5 E3 L6 |) B# h9 A8 w- s+ ^5 F
        //  1:Rectangle 1
* D2 X1 z$ ~9 W2 D        //  2:Rectangle 2! I# E) w" q- A( W3 b4 t
        //  3:Triangle( e5 p) F* w# L4 ]% L) r! |9 X
        //  4:Noise' C6 Z, c; i, y6 t* e# J. v( q
        //  5:DPCM
! Z1 m( R* t# b; _! p% C6 d        //  6:VRC6
; g! i' o* n3 ~3 x/ Y        //  7:VRC7
  `  K! h' M5 y5 \        //  8:FDS) a( K: I2 w. }$ |0 u3 q: N
        //  9:MMC5
! {( C1 z1 Y- j$ n* R- W        // 10:N106
8 l8 H9 Z2 `1 g2 q2 e2 a9 v        // 11:FME7# R8 P" {8 x5 P& x; x8 e
        INT        vol[24];& W  z. _9 G1 v4 W! E
        BOOL*        bMute = m_bMute;$ e5 m. ?# ]: v. `2 N3 P
        SHORT*        nVolume = Config.sound.nVolume;
7 i- R3 d0 g) A  Q4 |
0 [: x) }- \3 R4 r* b, c  s! u, x8 D        INT        nMasterVolume = bMute[0]?nVolume[0]:0;, N3 G  o! h. W
- t' z+ H! p+ m4 l+ E; w* ~6 j
        // Internal; J0 c) Z  V  x7 c4 X
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 l! b* w4 @; b- u. N
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
8 s; G) z' v5 m  N        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;) o0 @, i5 k) \; a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;# {+ ~2 `/ Q" b
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;) O, v* L9 R$ \" d. D
( `& |6 U* ^/ t* e
        // VRC6
  Z$ @& U+ r+ l2 X6 H/ T9 Z        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( E) ^6 K% k7 ~
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# L+ G& f+ c" j
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ i8 D' J' O  k- c3 v) J6 f1 @

( R8 z. Q& n+ [4 D. F        // VRC7
* C; B. t# e& P2 |: u        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
% C" O6 E$ t/ R( H" C( T4 {) `% u7 q/ D" z1 P
        // FDS% ^  ]% _0 P, E! S
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
$ Q& m& u) v' F  m2 g, _6 X
- r' `  N* k* M& k3 ?        // MMC5
) m' m7 F% Z# z; p5 G0 u* o# E; z        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( Y3 V0 l7 Y3 K$ {        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 h+ |5 q$ i0 _7 u        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. w* ?7 d- f/ }* T. f; [$ J9 z( |/ P% R# t
        // N106# T  c3 k2 U4 Y6 z. F
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# c" u3 g; y* v. @2 g$ s* G3 |+ s        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  m' I8 O  a9 M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 g) ?$ u3 d( Y; N9 T8 |        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 {/ |/ l8 ]/ d; L* L! |4 S        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* }" y5 c0 Q7 s5 L/ @
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* v% \) [8 `8 t; R
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( z" h1 N" W# ?/ P) L
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: h6 f" t) r1 K/ G' ~
8 U) T' ?8 c& O* j& g' \# h
        // FME7
* \" \, G" K1 i5 e        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( D8 U- O1 g, I, C+ V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 \8 Q% U0 R& u4 g* q. F; _
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) M4 U8 z1 e/ p2 ?0 Q$ g- x) T
6 o, r4 t; H7 q//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
+ F: W! d- d' c9 ~; Q' F+ T! b        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
" E1 l6 d. c* p* l
2 f3 ~4 o( L, S" T0 s# M        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& I8 X4 Z0 J. J
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
3 J2 l. `; }2 \) Y& q. ?; l) X                QueueFlush();
; z4 C" H, M3 D7 ^# X7 |" Y1 x        }. M6 M6 G  K8 q) h$ `9 k
( n2 o( _9 s# l% ]8 d
        while( dwLength-- ) {
1 k4 l0 R) [% J5 p                writetime = (DWORD)elapsed_time;( f8 k' U9 B: ?

3 _3 H% ^7 E! [  t2 r                while( GetQueue( writetime, q ) ) {
5 |( ]; s7 N  x                        WriteProcess( q.addr, q.data );' J! z% e. L; r+ b3 d* D5 z0 K7 H  K
                }
) D7 h$ ~) K$ n4 t4 X1 c6 O  v0 g5 n+ a( q; i2 L
                while( GetExQueue( writetime, q ) ) {8 u$ f7 t" c8 N* s
                        WriteExProcess( q.addr, q.data );
) {( S. z. V5 M9 p( _8 S" G# r* R4 K" q                }! M5 }6 Z+ M/ T8 L4 p

2 f9 Q8 l, i# u7 L                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  [! g5 L' ]3 o- U                output = 0;6 ]* x% z- U2 k" ?2 I; d7 \
                output += internal.Process( 0 )*vol[0];1 I0 C2 t' a  Z' F) H) _1 p
                output += internal.Process( 1 )*vol[1];
& U7 P$ Z7 I' {$ i# T                output += internal.Process( 2 )*vol[2];
; a3 K# V: d3 l( F" k                output += internal.Process( 3 )*vol[3];
) }( y6 k1 E( z+ M& [                output += internal.Process( 4 )*vol[4];
) ?" X- D, e. r, P/ J3 Y. ~1 {6 S1 A$ y
                if( exsound_select & 0x01 ) {
( K+ w& _+ D  O( p% m                        output += vrc6.Process( 0 )*vol[5];" R) P3 ~' H6 e% ?
                        output += vrc6.Process( 1 )*vol[6];  @" ^$ p- P6 ?# o4 n. l# f) R
                        output += vrc6.Process( 2 )*vol[7];
, f  Q. e& k, G  d                }7 `8 r( f- u: c- G( Z
                if( exsound_select & 0x02 ) {4 r( c1 L2 N  t: c! u
                        output += vrc7.Process( 0 )*vol[8];5 F" Q* M0 b* z( s; O" b3 B
                }9 T1 T! z2 x# L1 a8 `
                if( exsound_select & 0x04 ) {+ N1 ^/ x7 o4 Q6 D  k7 u( X/ d* o
                        output += fds.Process( 0 )*vol[9];+ q! s* ^/ ^; ]& e
                }
4 J( e. n! X3 ^# i                if( exsound_select & 0x08 ) {" T: H- I5 m) B6 Y
                        output += mmc5.Process( 0 )*vol[10];
' d7 o' }" h$ W) S                        output += mmc5.Process( 1 )*vol[11];
% M  v/ x/ g: T; L! t                        output += mmc5.Process( 2 )*vol[12];1 B$ O/ O% X4 V& M5 @) _
                }/ v$ p& @# e+ p# f1 d5 j
                if( exsound_select & 0x10 ) {8 N/ S& d+ T/ W  f
                        output += n106.Process( 0 )*vol[13];
8 q, |- `* v; v3 t& l$ h# Y. D                        output += n106.Process( 1 )*vol[14];
, M( Y1 `/ n6 Z5 l                        output += n106.Process( 2 )*vol[15];
5 V2 ?8 Y1 v: I8 i                        output += n106.Process( 3 )*vol[16];- j) L: }3 k" b1 v1 w, `5 o
                        output += n106.Process( 4 )*vol[17];
5 z( }" x7 x2 f                        output += n106.Process( 5 )*vol[18];/ Y4 F- B5 M- d
                        output += n106.Process( 6 )*vol[19];9 ^0 @/ D+ @; o
                        output += n106.Process( 7 )*vol[20];5 P5 D- g4 x5 W9 f3 I% u
                }  b$ k5 c3 @: Q, R. r7 K8 T
                if( exsound_select & 0x20 ) {6 k* j0 n/ M5 H1 `
                        fme7.Process( 3 );        // Envelope & Noise' }* V% u1 H9 H+ P8 e
                        output += fme7.Process( 0 )*vol[21];
2 l) K0 v0 m# i+ s                        output += fme7.Process( 1 )*vol[22];
$ Q) E2 ?, ?3 A: Y: L                        output += fme7.Process( 2 )*vol[23];) W- H0 L+ M8 R1 a) B  _& F0 x
                }+ P; D+ j# c& r* ^8 t* L6 r# q, s

" u! j7 N2 z# B$ ~                output >>= 8;
% ?, Z' C' A& a' h
" t! T) R0 m5 B8 c( n                if( nFilterType == 1 ) {: C' q" z, u# h% \4 T3 H3 o
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  S) X6 |( e. _! \9 U8 b) C5 \
                        output = (lowpass_filter[0]+output)/2;
9 A: Z& r3 V" F4 q& `                        lowpass_filter[0] = output;# @4 _$ H! M; g, w8 q* d
                } else if( nFilterType == 2 ) {
& Q! `% R4 t  ?( X6 N. K                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)* m. X' m2 Z  _0 b
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;1 m! x  U; i& m  T, L+ u& k/ {- A
                        lowpass_filter[1] = lowpass_filter[0];0 h) ^9 d  ~2 E  J0 k% Z
                        lowpass_filter[0] = output;
# x: J2 E, g( E; q  t5 G8 O                } else if( nFilterType == 3 ) {. W; a. Y2 c, Y9 x# Y
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% N% A9 D3 M8 j9 A( V% L: E                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ E8 Q, O8 O  i! I& T$ k$ o4 S1 |
                        lowpass_filter[2] = lowpass_filter[1];0 D% H) t" s% R/ E7 }) N) \; s
                        lowpass_filter[1] = lowpass_filter[0];
# \( Y# ^* b2 ?5 L: S" ~( T                        lowpass_filter[0] = output;
* y- x7 \$ Q. q1 _4 _) j1 Q                } else if( nFilterType == 4 ) {, i8 m; f* v/ h7 P
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 A% c9 Y0 G, [+ W2 d& g2 t: E                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 v0 L5 T/ S9 W; ]5 g                        lowpass_filter[1] = lowpass_filter[0];
2 m, C8 ~6 o$ Q* @# T/ e+ }                        lowpass_filter[0] = output;2 R1 B4 Z0 U$ L4 r4 v9 K7 H
                }
+ e2 K. M, X9 a, q  y
# ?1 x: T" x  g' Y8 l1 n#if        0' ~6 [) E# H+ b' I! `
                // DC惉暘偺僇僢僩0 l  E; l4 k/ C' C
                {' q% z8 Y( f" i' p  J- r0 P
                static double ave = 0.0, max=0.0, min=0.0;
" [% d( A6 _9 t7 v" s) q1 `                double delta;
8 [8 k# A6 t" T! Z; ~; s8 g# A                delta = (max-min)/32768.0;% r6 w% G) M* x) z7 ]1 ^' l' W! _
                max -= delta;4 f# [- R6 ~" F0 e
                min += delta;' h2 y* G; R  R( i0 r. i
                if( output > max ) max = output;
/ e5 z/ a$ c* w                if( output < min ) min = output;
. B$ `# T# G/ W4 e( p                ave -= ave/1024.0;
6 J. ~) U9 R9 r3 V! ~6 l- U                ave += (max+min)/2048.0;
. f; I5 x9 r7 x, {                output -= (INT)ave;
: F2 X) i5 G; z3 P                }
3 c5 {1 q: U6 g/ `2 e- v" S% v# Y#endif
, r  W6 `7 T# d) s+ R8 v' Y3 B% @; x#if        1/ p' r) O$ G+ `2 e3 W+ n
                // DC惉暘偺僇僢僩(HPF TEST). f- ^! ?1 T0 Y4 T6 s1 {! e
                {
4 i1 m, w. y1 O# ?( D+ ?//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
) |5 K$ `/ s. O0 y8 V                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 r8 B8 M0 n  }0 Y5 S* s5 b                double        cutoff = cutofftemp/(double)Config.sound.nRate;$ y0 J8 S; F" K/ z% V/ a1 N
                static        double        tmp = 0.0;0 t8 p* S# i; r- R8 X! w9 C
                double        in, out;
, m* T) I" ^3 e6 y- z1 ?$ o, S- ^0 }3 C- N( e. L: d6 o
                in = (double)output;4 V; }2 g) q, B6 I5 t$ d2 a& l
                out = (in - tmp);* {6 t/ p* x, ]* T
                tmp = tmp + cutoff * out;, ?( }9 t2 H, A
% C3 ~" a0 ~8 Y
                output = (INT)out;
6 M/ ?9 M8 O+ J. a1 q8 c                }
# a# {- H. c( x1 ~6 n9 B#endif" y; p) J% k( T) B- w3 {2 t
#if        0$ Q/ T, |. A" Z8 N3 w2 V$ {
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
" ]0 f; }3 R8 J9 o( h- \                {- H9 z1 I, Q- t, F. y' T" H: i
                INT        diff = abs(output-last_data);
  L) `8 M/ F) y, h1 c                if( diff > 0x4000 ) {$ ^( k- i1 j% s1 n2 x! I
                        output /= 4;( ~* O0 \5 |1 z& }: V
                } else % L" O' @6 {' y' [& ?. A! M4 ]! Q
                if( diff > 0x3000 ) {( }; J3 m1 H( [  p
                        output /= 3;
. d* a, d7 f& J; m                } else+ r4 O9 f0 c  ~5 }
                if( diff > 0x2000 ) {( G0 f, l1 l* R, S
                        output /= 2;9 ?6 S( P. c- s- U! L5 b
                }7 b# s" D6 g# U2 ]
                last_data = output;  E: m1 k4 x1 q) W
                }3 e% s; Q4 U: c8 S8 v% H* C
#endif! J) v7 C( {1 C1 C6 M8 v; \
                // Limit) k; i3 U& O9 d$ i( i. j2 n1 O: O
                if( output > 0x7FFF ) {
4 V9 m8 p  x% G1 E2 x8 W                        output = 0x7FFF;% k. T4 d$ P* Z- N( R8 R$ d# |5 V
                } else if( output < -0x8000 ) {* h- }, g! K/ W# ^% x5 B1 |0 P
                        output = -0x8000;' r& t( R; l" R- p5 R  X
                }
; F% E3 l! Y7 [# W; Y* Q1 w/ ^& I0 X$ T! `+ V4 C) k
                if( nBits != 8 ) {
. S8 M% ~) _0 r+ i, Z# g* c: Z                        *(SHORT*)lpBuffer = (SHORT)output;  T* r- ~6 ^5 |2 s& r6 Z4 u8 @
                        lpBuffer += sizeof(SHORT);
) `" m2 Q: ]( P' F                } else {
9 _  l% |5 W& ^2 u4 Z                        *lpBuffer++ = (output>>8)^0x80;
# x: Q& d; n2 P' v4 q6 K% Z2 c                }
$ V* O0 f0 }! d1 U  z) _8 R9 ]+ R5 r
                if( nCcount < 0x0100 )
4 v+ V6 y9 P2 o, Y+ l2 ^                        pSoundBuf[nCcount++] = (SHORT)output;
8 I5 Y1 r% A$ U; ^# H1 E5 f$ g
0 I& o, v+ u0 i0 ^: F' E6 n//                elapsedtime += cycle_rate;/ C! g. H7 ?) n9 a- {. F- g
                elapsed_time += cycle_rate;& c7 Z5 T, {3 h* Z, j9 X! q
        }
- W* o1 U+ z# N9 w3 o) N* e$ C5 T" x
- e( r/ y4 i2 [#if        1' n: j# @$ u6 |) V( d! O% m' Q
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ Q. ?6 v3 Y- e' ~* e                elapsed_time = nes->cpu->GetTotalCycles();
' O: `& J. `( u$ H        }- d5 ^. r! e  t
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {+ `3 o  z) e+ y% m
                elapsed_time = nes->cpu->GetTotalCycles();9 d2 e7 s* L% E9 w! L# |' Z
        }- O$ w7 P* v' d5 q  t$ S1 g5 _) J
#else
- R$ h2 t  C( l( \        elapsed_time = nes->cpu->GetTotalCycles();
$ d1 e# T* y, Y3 G& A( q#endif3 [: y0 N( ?+ ~/ W
}6 U1 r! Y3 f' M/ s0 S( [

: H1 A; C" g) I$ Z// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. c- ~8 e; h. |, C, ^. {  sINT        APU::GetChannelFrequency( INT no )) f9 _" w+ {. U% P
{
9 v, f1 z+ X7 y' l! \& i9 T        if( !m_bMute[0] )
# K7 u3 l7 p/ n' O0 `( s# ~                return        0;
' k& l- O: U: K6 A( [  N3 q3 [
* u& m# O/ a( M        // Internal
$ o3 s" R" U- F, R' r1 D        if( no < 5 ) {
4 l. G6 f2 J. A& H, S4 ]- J                return        m_bMute[no+1]?internal.GetFreq( no ):0;- S. p3 U$ _) c4 ]
        }
/ x9 L, A5 |3 e' j' q8 b6 |$ C7 h        // VRC6
! F, M; n* t' y* t1 h* W        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
$ {* O  ]) q+ T7 m4 o' t                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;1 G0 d7 e/ }- @: J! }
        }
  i1 A0 h  m! H  c0 \5 V% S        // FDS' b4 x+ {) P4 Q$ e: y" K
        if( (exsound_select & 0x04) && no == 0x300 ) {  g2 G/ w+ ~& B2 B3 w9 i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: H( m/ X5 ~6 B3 n) C/ t& _        }
% a3 [' R' S6 I5 J8 m  G/ C        // MMC5
5 n! s% e9 H0 ]0 A9 L        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
* i: C( O1 E5 R# f/ B                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; Z7 v" g* O) z0 u. {        }
  b; K9 W# v6 Y0 _) {! V8 r9 b$ O' Y        // N106# S4 \/ k0 k3 ?3 n
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 w6 ~3 ?9 q0 q0 m2 j( l- L4 V' [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;# v. L8 [+ Z4 e4 f2 @2 O) p/ o  d
        }* P  F+ p; V. C' M& o
        // FME78 X/ i6 f! k  u: f: w: b
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {0 Z' K7 s" J7 u5 Z' K0 S
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! }& b" c  ?# }' T
        }3 \% U; Z" D" x& ~  @3 e
        // VRC7- }- }; ?) ?% y& c  C
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 v: w8 }% j, k* o9 {2 Q8 }% l                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& a8 q$ C; U2 H+ G        }
$ T. [- A( w4 j: c# y/ V0 S        return        0;8 l: \( V+ I: x  A& l  J
}
! H- n# A' B# n& Q" t. o! T$ c9 y
// State Save/Load7 a: ~$ o3 ^3 Y2 q$ v8 L; v- }
void        APU::SaveState( LPBYTE p )" C4 c, u! r5 Y/ q  ?% X! @8 [. j
{9 \7 \7 i+ q4 K
#ifdef        _DEBUG
+ f; j$ V3 X* E! C1 S5 wLPBYTE        pold = p;
& o. p1 l" o! F4 ]) o#endif  Y" h1 ]1 ^6 Y" R, @! q* F

7 G& L; G$ D7 }        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ [5 N- d" i8 E% Y% e; K
        QueueFlush();
: ^; s& e0 K- M7 I% n+ a/ C- p) [  F, x3 W1 L. m0 {6 A
        internal.SaveState( p );) N$ h: c$ r; {- E2 x4 B" ~, f7 M
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. Y8 Z9 q! m5 k+ X* J$ R. a
# F  H0 W2 ~0 [% e/ s* B& C        // VRC6) c: |. M. o, l  Y' M
        if( exsound_select & 0x01 ) {
$ C; A! }% a% z                vrc6.SaveState( p );
5 q0 l' Z! _' r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( ^  `- u8 l7 C- q1 O
        }
& }' V/ z1 J8 J        // VRC7 (not support)
- c! E: E' `5 ?- [$ ~        if( exsound_select & 0x02 ) {7 h6 F$ ]$ j) |8 `
                vrc7.SaveState( p );
" D  `: N/ L( K' Y$ U4 L) L# [4 A6 I                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! Z- E; j9 O5 s4 t. I        }
/ |9 k4 h+ h# U0 a0 ^& Y8 G        // FDS
: i: {# [, U- A7 O9 c/ P        if( exsound_select & 0x04 ) {
- T* S! ~+ l! x                fds.SaveState( p );& m8 p3 x7 s6 S
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 \, a0 H$ B% u( Q
        }
  }  |1 \& b+ c, r- Z& o8 f        // MMC5# C: x" c( a6 f  `8 h% ^
        if( exsound_select & 0x08 ) {" D3 \$ T3 y9 k; y/ ]* j
                mmc5.SaveState( p );
* `% d; g7 o( W                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  W; i/ j+ h! O' E; ?; U1 F
        }
9 M  o8 h, }! N& m4 y  ?3 N        // N106
& Y) ]. x$ Z: {" x        if( exsound_select & 0x10 ) {9 S5 {& i# x. s6 Y6 T2 m5 z
                n106.SaveState( p );2 b3 h2 M( \5 W7 e0 `
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 o3 W5 P! S" c( f6 S! G
        }8 r9 P- ?# q' `" I
        // FME7
  A4 @  v( @: \8 p- e& E  F        if( exsound_select & 0x20 ) {/ n5 a# o5 ?- d+ D# c9 G
                fme7.SaveState( p );& p3 W! Q2 X4 c
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 ?( F- |' U1 d% ?& L6 x
        }
. ?- Y' l+ ?4 A# W5 T
% S$ o7 D6 x5 p  F2 w) U( G; M#ifdef        _DEBUG
# O) }5 Y7 l; p- h* ?" TDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );( @% x  [8 O, `, v0 F/ T0 ~3 O  A% X
#endif
/ e. S/ f- K' U; a}
2 z1 P( \' g* }# D) S; Z* @( T& `6 h( |+ e$ b( a9 [- ?
void        APU::LoadState( LPBYTE p )
6 W, `8 X( ^' {# R{6 \/ N  X) A2 V1 K% U0 y" {
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 L, H4 e. Q, g% u7 Q( j        QueueClear();8 i1 h+ L& x& J  w% u3 Q
# U- D3 a( {, ?
        internal.LoadState( p );" `" P/ q2 H: H# ^
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. R2 T" F6 F# @( L' U
# I' f0 a; h. Q/ E
        // VRC6
8 N4 {( n. s/ K, i* u0 D# s/ ]        if( exsound_select & 0x01 ) {
. w. i5 c  n# r5 i7 c7 n                vrc6.LoadState( p );* q' u$ @$ ]: f% E7 e; ~
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 M! |. ?( g- U8 v9 {5 w# x( }9 t
        }$ ~7 ^4 r! N/ N! u  i) z" N. L
        // VRC7 (not support)- ]% g; D% k  h0 _
        if( exsound_select & 0x02 ) {
( M* d: D) @% K  g/ \* }                vrc7.LoadState( p );  e4 w' N% f! M% @3 p4 J: A
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 S5 M, U5 [$ W6 t7 ?' ^        }0 g# [, _2 q+ u
        // FDS- D( f7 @5 Q# p$ N8 Y) y+ x. R; s1 k9 M
        if( exsound_select & 0x04 ) {( T0 S& D) o8 }- e$ Y
                fds.LoadState( p );6 C3 g& ~! D+ ?, D- m9 B% D1 `0 P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 T% r2 ?  u2 u" Q5 T6 G% D
        }
7 ]" V4 K! x0 r  V) o        // MMC5
2 n! J0 i) M7 b# E" D5 E        if( exsound_select & 0x08 ) {% O0 M" V/ a4 G7 c
                mmc5.LoadState( p );
5 V# G" ?" F9 F$ W8 d7 W                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 Q9 F& V  R6 J
        }
' d: I& j! T) o, K        // N106
4 n0 s4 t3 z( E, }  U        if( exsound_select & 0x10 ) {- }0 i- S4 u8 j; ~9 o3 A1 |
                n106.LoadState( p );. _. G' T' l' O- ~3 m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# C( o( r. s. h
        }
8 t$ i" C  q& B* q' Z        // FME7" _7 _) K2 k# d$ e. Z
        if( exsound_select & 0x20 ) {
$ p' R6 t! M  K$ [: @                fme7.LoadState( p );# c# F) g; B  B8 O4 [  h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 a) p5 s8 j% k+ N8 X% D        }- R. k( S4 [% }$ [' C
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % Z, C) B& \/ l3 i, T
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! T. F  Y. b6 a: a3 s
感激不尽~~

0 M9 K5 M" _) ]% D) a2 u恩 我對模擬器不是很有研究,
+ M& u; W: _4 y7 j$ L! V* g% z' ~: V雖然要了解源碼內容,可能不是很困難,( a" l+ ~# \0 H4 Z
不過還是要花時間,個人目前蠻忙碌的。
  `( R6 e7 d4 b0 E& w) W9 x4 ?
" Y7 M* X: L; J# Z* j/ k; g給你一個朋友的MSN,你可以跟他討論看看,
5 s& d9 o8 z' ?+ p& B7 p+ i他本身是程式設計師,也對FC模擬器很有興趣。  u2 O; h9 e1 O' m/ T

/ ^( i8 f3 @. x' T; W# l$ d& f' z, T- XMSN我就PM到你的信箱了。1 ~+ C: z0 J& a6 \- k! f. c: U
* G1 E6 F" x" E* ?1 A. }
希望你能有所得。

该用户从未签到

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

签到天数: 80 天

[LV.6]常住居民II

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

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
4 {) g4 e4 U) \7 B0 }# Y6 b5 J呵…… 谢过团长大人~~
# X; ~; m% d# @+ O* ^' q. h5 C

1 q* R# g2 V7 m1 f1 F+ h哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
; m& R; m6 w+ {1 u" j) Z团长的朋友都是神,那团长就是神的boss。

5 U: b* E% _# ]哈 不敢當,我只是個平凡人,& H  t1 m2 v! A6 r# \, o
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
( w0 v( V8 T9 x  p* CZYH+ g* ]. |$ U8 ?# U3 @: @
QQ:414734306; u9 w" |2 K& m  W
Mail:zyh-01@126.com
" l# Z4 n& Q3 _+ z( F/ f8 _# Q' ^/ M; C0 `8 F( Z6 q
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ) G7 B* V0 w- g( Q4 K9 C" ?9 f
再次对团长大人和悠悠哥的无私帮助表示感谢~~

' \3 T* R' |& x- W% E! i4 m不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2024-9-25 18:27 , Processed in 1.061524 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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