EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" E# v, L- \: ?6 m( p
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; U( m, q% a: A" {4 m- Y
这里有相应的模拟器源码,就当送给大侠了~~" S+ C9 _, U' u# I1 E
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 % a" ~' t" z! K$ Z) U7 P
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ K' c0 Y7 o, F楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- E$ ~1 F% s4 v
这里有相应的模拟器源码,就当送给大侠 ...
4 P6 X/ Y$ e& J5 a; c
聲音部分(Audoi Process Unit = APU):
0 a5 k0 |: _  [.\NES\APU.cpp
6 d# R' q3 C3 p.\NES\APU.h3 ]' i) Y2 t, R  c. N* O5 i& S" \
: Q1 l: ?8 X- f) r  V! L1 u  ?/ u

+ r. ~" L, C# |影像處理部份(Picture Processing Unit = PPU):' g* d; p" X8 w0 E0 V4 N, K
.\NES\PPU.cpp
5 @) A) b0 e: g! ]/ ]2 t. |) g.\NES\PPU.h; P  f' P1 S" y7 l8 b3 k
* S8 s  r. D7 z3 n
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:+ O2 t5 E# A3 {. P1 K' q: s+ Q/ {
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 [6 i' t7 C* Z/ u//////////////////////////////////////////////////////////////////////////
5 b  b/ R/ E& c9 y/ a1 ?* U9 Z//                                                                      //
  X* F( u" s; G) }. Q//      NES APU core                                                    //
: U% b2 ]5 p: @  {//                                                           Norix      //" X, H) E+ {" L6 c' U
//                                               written     2002/06/27 //
& _2 p6 G: a0 S( M% d5 A3 ^//                                               last modify ----/--/-- //
. }5 C9 @( J8 ?0 W8 N( d//////////////////////////////////////////////////////////////////////////
3 O7 Y! W- }. m' q' L#include "DebugOut.h"
$ |! q4 b( i( t2 u; i#include "App.h"
: C- c! A6 \' O* O4 S. r#include "Config.h"
* r; z; V! y8 |$ g+ K$ a0 d" M1 x/ x, g
#include "nes.h"( }/ j0 [  a2 u/ i" H9 I' v
#include "mmu.h"
% d/ i: T. c0 c8 b3 d9 P+ i8 m#include "cpu.h"1 n$ V/ `: F# _" W
#include "ppu.h") A: _5 }7 t4 J/ F3 T& u% q, m2 P
#include "rom.h"+ z% Z6 A/ R$ q2 i6 a$ G
#include "apu.h"6 \' W+ B6 n; ]8 s' W3 ~* f; `
# K0 @! E* K: }6 e
// Volume adjust: a. t- ^1 t3 D
// Internal sounds5 N# T6 K' i; f2 s$ G
#define        RECTANGLE_VOL        (0x0F0)
- ^" y6 z* x( j: @8 p9 G! I#define        TRIANGLE_VOL        (0x130)7 i+ R1 P0 N2 x9 b4 ]1 x) V4 S, d
#define        NOISE_VOL        (0x0C0)
% o# Z) V; f* _, S6 _$ V#define        DPCM_VOL        (0x0F0)- e* e% a; Z" ~  x8 _% }& O
// Extra sounds- d  [8 s* V7 V) n+ g
#define        VRC6_VOL        (0x0F0)3 L% ?! E9 z; u( |! W
#define        VRC7_VOL        (0x130)
/ A0 A  H: J/ ^) b* `#define        FDS_VOL                (0x0F0)
+ `$ c1 m- N2 J4 i( z#define        MMC5_VOL        (0x0F0)1 k4 @0 V2 j/ P6 r
#define        N106_VOL        (0x088)
. g* ?0 p' K3 r0 {#define        FME7_VOL        (0x130)
- [; Y3 M1 i1 z& u
4 ~5 B! ~1 J5 m" C8 xAPU::APU( NES* parent )6 ^9 @5 E# f" _# ^6 R8 D) g/ Z
{2 @6 R( K9 n: ?, y* j
        exsound_select = 0;: U6 Q1 a( Y6 x/ W% n# e

4 Q% O! u2 c' T+ n- m6 R! [3 t        nes = parent;  Y1 ~6 G: R' l* ?9 Y
        internal.SetParent( parent );3 X/ R8 Z: X$ L/ `

. D0 b! q& V& a6 }( Z& S/ Y        last_data = last_diff = 0;: K+ p. k6 Z; G1 f8 Q
6 n$ g6 Q6 U) |4 X( a: A  ^" m; t
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );9 Q! I  V7 j' ]! V( U! X( b% V' k

* z9 ^5 Q$ C) X0 q5 W& h! N        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );; r/ w3 x9 A( A' F  a. V
        ZEROMEMORY( &queue, sizeof(queue) );0 t) V% @( @* B) o1 M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( t9 Y" c2 J+ m* P6 z1 f$ ], d
+ [- [- d- ~- Y1 j7 T. x/ f  z
        for( INT i = 0; i < 16; i++ ) {2 X; N$ P1 Z) n# D
                m_bMute = TRUE;
/ c4 K) r# D2 _0 U9 C7 Q! Y# f        }3 \' ^" Z* Z" k" Y2 j# M
}6 h& y( g6 K# R7 J+ t$ n+ I  w" A
/ [+ ^, J4 C3 q3 |
APU::~APU()
9 N2 h+ A# y0 \  G$ u8 i% ^{
3 F; K' C6 x" X}' w8 y8 o5 u+ N
. {8 B$ S! L& X
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 R: g  X% J* ^/ Q% d
{
! }; i6 ^5 _/ ?        queue.data[queue.wrptr].time = writetime;
# d4 h+ X' w) l7 w! Q1 `        queue.data[queue.wrptr].addr = addr;" X9 ]8 R9 m) C- J2 C/ Z6 z
        queue.data[queue.wrptr].data = data;' i+ {4 w' Y: e) {; k. @. b0 T
        queue.wrptr++;
5 C, c1 S0 `; D" Z" Z0 c5 M) Y7 K        queue.wrptr&=QUEUE_LENGTH-1;
+ _3 z5 K0 g# M9 \        if( queue.wrptr == queue.rdptr ) {
5 M$ g# [* }- B1 U: x: ?+ E0 W                DEBUGOUT( "queue overflow.\n" );
. `7 [& E2 A4 |* A7 p1 L        }5 T( B5 B2 P7 A
}. X) V: q# e# Z9 U7 R# }
% ^+ F; X" a# t) U: |3 Z4 R; {5 |/ |
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )1 S8 }0 H# _) J# d" f3 }
{
" D  ~- G: p) r$ T        if( queue.wrptr == queue.rdptr ) {
2 @+ y  h$ P# f* S6 k7 H# e                return        FALSE;+ S% D/ Z2 v$ r$ A
        }; C! e2 r* [2 |$ m9 ~
        if( queue.data[queue.rdptr].time <= writetime ) {
! V0 k8 Q  r1 e7 j. a% c                ret = queue.data[queue.rdptr];; n9 k8 ?) O+ m( @! b( W3 F
                queue.rdptr++;. J5 {# h7 ?+ ?' w" J+ K
                queue.rdptr&=QUEUE_LENGTH-1;
/ g- f3 v5 [! y7 f2 Q; C                return        TRUE;
  B" d4 B! N7 m2 v# V        }
9 m* E7 n- }( ?        return        FALSE;
3 \) b! |% @  w# W; G& X" U}; Y" @  w. K1 v. s5 f) S. i+ i; J3 R
& Z' H- `* U8 x5 I
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* f) f. S8 r7 I2 b{$ }) E7 n  A* s9 S2 o0 r5 v
        exqueue.data[exqueue.wrptr].time = writetime;
- g% m9 o3 \; \4 U7 g; p0 k        exqueue.data[exqueue.wrptr].addr = addr;7 [' H4 h) a* l' w& K( M0 I3 Y! u% W, G
        exqueue.data[exqueue.wrptr].data = data;
) P- o8 i$ h- t- w. u+ i        exqueue.wrptr++;
6 H2 a+ I! f: ~        exqueue.wrptr&=QUEUE_LENGTH-1;) Y, v, n0 Y8 o
        if( exqueue.wrptr == exqueue.rdptr ) {( U) a/ P6 n8 d+ A- |
                DEBUGOUT( "exqueue overflow.\n" );
  H& k1 Z4 j) ?$ r        }
! I; U6 w0 \; ~7 V. a% ~8 V}
6 e- C# Q% V: x7 ?2 @% f
  _9 L* R4 s. G9 @1 FBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 u( u$ v9 g" F0 l
{% h7 l+ _& E, d% b" ~
        if( exqueue.wrptr == exqueue.rdptr ) {7 U. j" r$ t8 o* `
                return        FALSE;
1 F' M+ V2 h2 l+ \9 f& |        }
$ E7 n0 O! {# ^) d* f/ T        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' v% N: I* r* x6 y* T( y
                ret = exqueue.data[exqueue.rdptr];% D( B; t5 P; ^0 Y6 p7 |
                exqueue.rdptr++;% B' l8 r! c) a; n& k: A
                exqueue.rdptr&=QUEUE_LENGTH-1;9 o- m. o7 y8 p9 j, U1 @
                return        TRUE;
6 `( Z2 e$ s/ ?' V" U        }# Z# `- }8 k3 e1 M. \$ A* V
        return        FALSE;4 {0 o5 M7 I/ |. W! K
}
3 k$ Q* a, P' ]; Z) ^% {& W7 W4 {% }: A  a3 v
void        APU::QueueClear()
$ @2 q# @% @$ `( Q5 G! F! K& s{
% r4 r! }  V1 }( E% k        ZEROMEMORY( &queue, sizeof(queue) );2 Z% n2 A. z/ N' ^  O* j) T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 B9 e; g5 f' }2 T3 \% P  v$ ?}
, ^! X& o9 ]' V' P# F6 `. c
5 ]& L' M. @& ovoid        APU::QueueFlush()1 k. c4 V/ n- ?. j1 O
{* s/ ^. ]' @9 T) Z3 h0 O3 ~: s
        while( queue.wrptr != queue.rdptr ) {
# K. e9 `9 d7 ~/ {4 I; x- H( O                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
, {+ @" V0 T7 b$ M1 r, B                queue.rdptr++;( m6 h; [; b( O/ {) ], l
                queue.rdptr&=QUEUE_LENGTH-1;9 h2 Q1 T' R! V/ X. b6 V; L0 l
        }+ \. ^0 n$ P  Z" k

8 f8 Z4 @+ A5 i& Z$ D' Y        while( exqueue.wrptr != exqueue.rdptr ) {/ k, D& c8 x6 A! Y5 p* G! f
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: A: q0 v4 }# g* [                exqueue.rdptr++;
. P, y' k! G+ A& u/ |                exqueue.rdptr&=QUEUE_LENGTH-1;
. C9 p/ [6 v- F+ }5 p8 p        }
! ?! U9 K; \( E- h}
5 S3 ?. Y: Q3 `9 e, B. M! J4 J1 t- A1 L# i1 F
void        APU::SoundSetup()
# }; j4 r  W2 R6 N0 ]! G{
9 x- b! z  M  I# b0 \7 Z        FLOAT        fClock = nes->nescfg->CpuClock;
6 w! L% _5 }6 B  |% {) R5 T. b        INT        nRate = (INT)Config.sound.nRate;
( v; N' A; I4 k7 H        internal.Setup( fClock, nRate );
- v2 V: v: `+ N6 u4 u2 ~        vrc6.Setup( fClock, nRate );3 l" T4 z, d5 Y8 n/ O
        vrc7.Setup( fClock, nRate );% b% n, J  {# \" I0 E) V8 }( ^
        mmc5.Setup( fClock, nRate );4 h( r6 h5 s* W- o: W) B
        fds.Setup ( fClock, nRate );
: W# R& B- \& q2 _: y' j( p        n106.Setup( fClock, nRate );
5 B* v/ f4 a' \+ i: N, E1 X        fme7.Setup( fClock, nRate );2 |2 A7 {/ [) n
}1 p% B$ `3 f1 @1 H) H5 e

" c7 o# H9 a- v. Cvoid        APU::Reset()* n7 O+ z8 Z  U. t$ c
{
" E5 F0 b7 G8 F: H' |        ZEROMEMORY( &queue, sizeof(queue) );# o8 i" O2 g# l6 n6 h; ?) D2 k0 j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" t! r" X5 E" k% `$ l1 V! |  r1 u" Y6 b" I  z: O2 u
        elapsed_time = 0;& V' n/ V- T. Y  I, i8 F) a; ?
- r# O8 u- h0 z" r$ H/ t
        FLOAT        fClock = nes->nescfg->CpuClock;) t' j: L3 K4 Z& X" H! k6 P
        INT        nRate = (INT)Config.sound.nRate;
9 J% U2 [/ v) R0 E+ y        internal.Reset( fClock, nRate );
) X* Q' e8 {8 o( W) x        vrc6.Reset( fClock, nRate );/ T- E2 v1 B$ _% q' P( i/ R
        vrc7.Reset( fClock, nRate );7 f1 W$ J; Z2 o  c
        mmc5.Reset( fClock, nRate );
' p  I: T% L! d8 r        fds.Reset ( fClock, nRate );
" ]$ M2 l; G: T; _7 p; L2 {3 R        n106.Reset( fClock, nRate );! x8 I* U# P4 A7 P( e5 C
        fme7.Reset( fClock, nRate );
0 b5 b' T3 |  o$ [( W' Z- E7 _* @0 ]- P0 P; @0 `# t( ]
        SoundSetup();
9 w( I+ a+ m5 D+ c" ?% T. Q}
# [/ v* }5 `# O6 v9 L1 @5 }5 e) q7 `% `  q; Q" _3 Y7 |! x6 k
void        APU::SelectExSound( BYTE data )# N& v+ x3 O: k5 P7 d
{
8 c( M2 M# k. J        exsound_select = data;2 H% h6 \% O7 f
}
' c! J) v1 H6 q1 P" w* i" Z% j+ V/ z  ~8 _% O/ {) U8 J
BYTE        APU::Read( WORD addr )0 |8 X0 h8 Z: t
{  M; X+ ^* |  I$ B6 f
        return        internal.SyncRead( addr );
" R5 Y- |  I! A3 `: h}
1 c# L  C$ g* {+ y% F9 k8 ]# y/ y1 S1 u% l" b
void        APU::Write( WORD addr, BYTE data )& E8 M  M+ @& X& K$ g/ T# b
{
& L8 m. u% l. i        // $4018偼VirtuaNES屌桳億乕僩
9 D: t- ^# D$ M) f2 R        if( addr >= 0x4000 && addr <= 0x401F ) {
3 q5 Q( a3 W4 k. L& |+ }6 g                internal.SyncWrite( addr, data );3 `4 _# T! ~& m5 q% G1 z
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' \2 P" W4 y2 j  {        }
# I! s5 G: c1 N' l}
! A: g7 Q$ ?  }0 Y$ {/ r/ p, r$ u+ z, M4 G/ Y1 Y$ E
BYTE        APU::ExRead( WORD addr )0 M5 X% i$ q. u( f( Z0 x& @
{
& t5 y, ]4 V# y6 DBYTE        data = 0;; e) ^' g) |( D. R& W

5 e0 K& \$ p% @- K5 S; r3 I0 D* D        if( exsound_select & 0x10 ) {- O( f' {% |' `3 I- R
                if( addr == 0x4800 ) {
% T7 H: `! w, o8 R* e                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
8 i0 U' ^# y. O3 m: l" i                }! E' `- _! C+ D, [3 d% O  J
        }, `  u" }( J7 S6 s# F6 @, ?: d
        if( exsound_select & 0x04 ) {- d8 Y" D2 [+ x+ ^/ b6 q8 R
                if( addr >= 0x4040 && addr < 0x4100 ) {
& k$ |8 E: i7 V8 a; J                        data = fds.SyncRead( addr );  l( M: y( i: o! e- C+ V
                }
4 C, `% ], Q9 R        }
4 W" v& g! F6 a3 f9 R: a" L5 S        if( exsound_select & 0x08 ) {9 Y, l4 Y; O9 _- e, l
                if( addr >= 0x5000 && addr <= 0x5015 ) {# @3 f3 i  N) k
                        data = mmc5.SyncRead( addr );
% v- K: H* R$ |4 o% P6 e0 p                }
; P3 B+ ]7 k6 r; y, C        }! g/ U! s2 |: ~0 }8 I! X6 s

! S/ R; C9 |  B+ B0 ~        return        data;' I* K$ b5 k! h6 ^+ c. i$ n. V
}. \% R2 \8 j- X6 u
4 Z  @6 r( V5 O& T( e% X
void        APU::ExWrite( WORD addr, BYTE data )
- K1 Z- m9 @8 K+ a& K{
* {& p( [# }$ l8 _0 x; N$ M$ \        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
) u& D$ ~/ S3 N4 }# d4 ]$ L
% X3 @# a/ Q: l        if( exsound_select & 0x04 ) {% D1 e4 \0 i: A: D' {$ p
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 b' U6 M3 [* |7 i1 c" j( Y( U' d                        fds.SyncWrite( addr, data );" `) k5 K! q1 ]% X6 ]2 N8 ~8 {
                }/ Y9 A% y& c( z
        }$ k; }, l' E3 x+ h9 E4 T# ?  D, y/ B- `
. L: k& A' |; P) ?
        if( exsound_select & 0x08 ) {  W6 j& y+ L4 u
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, h4 F9 h2 g7 x6 e                        mmc5.SyncWrite( addr, data );9 U- i$ o0 c9 N4 l: q: g2 i
                }
% p, ], A8 n6 B4 E        }
+ f2 e6 K1 ^9 B' ?9 ]2 C1 d9 R}, m, W1 m7 B! {( O" T2 |

- A8 y+ s4 ?7 M( q+ K$ q6 R8 H4 \void        APU::Sync()
7 t4 H+ H3 }, o4 Y  \, q4 F{3 u  w2 z0 f* u% W2 s* q
}
5 g. k  }$ p( z  J/ ?" u; Y! l% X1 y
) S* D2 V0 N# o- V' W: h1 xvoid        APU::SyncDPCM( INT cycles )- I: B7 a3 S# i" k4 V5 j2 D
{
& o, m6 O  K+ \! M0 E        internal.Sync( cycles );! y, a5 O* B$ `+ l
/ ~1 z2 F: h/ I
        if( exsound_select & 0x04 ) {6 J# [# l) z9 E+ v
                fds.Sync( cycles );+ P8 @0 c' J% e. p" R
        }& Y- v* j7 j8 W- Z6 W/ t' c
        if( exsound_select & 0x08 ) {8 v- ^  d1 c; i" H/ H
                mmc5.Sync( cycles );
0 W  C! K- @" |; c) B        }
" _+ e3 D, C- h" \}' \/ s! C5 f8 _9 \7 d
5 P/ M4 G' a, \8 m! ~& _( k
void        APU::WriteProcess( WORD addr, BYTE data )
* a  }4 A! \" G, N( O; {, K) {* A{, S. b. v, x* r* U
        // $4018偼VirtuaNES屌桳億乕僩% c. A2 [5 R8 L; R/ J
        if( addr >= 0x4000 && addr <= 0x401F ) {( t- v  W/ m! @4 V" F6 v
                internal.Write( addr, data );
5 f, ~4 _  C# R$ ?        }, N, `/ U# M, Y+ r( L+ a5 q
}
- n' @% r7 K$ o4 S3 |! h3 g- K4 i' w: @5 f: k" k
void        APU::WriteExProcess( WORD addr, BYTE data )2 o, C9 W) p) ]5 D
{' y# I6 T; E# D+ L+ Q5 Q5 [, k2 |0 Z
        if( exsound_select & 0x01 ) {
5 O/ h! s5 ?+ g7 p                vrc6.Write( addr, data );
+ \" |* q! V5 J2 w2 K        }1 v+ L8 c) r3 T  n4 _0 `( g
        if( exsound_select & 0x02 ) {! X8 Z6 q9 t  f, }4 u6 g
                vrc7.Write( addr, data );5 r' K6 b) q! u1 Z8 c) U
        }2 p5 I6 c3 `3 R; p
        if( exsound_select & 0x04 ) {$ w* L$ }5 Y- M7 f
                fds.Write( addr, data );0 m+ n3 b) L' }0 u9 J1 D8 `0 i
        }
! D/ e' W  j, S1 B9 a' C        if( exsound_select & 0x08 ) {: {9 D, `% Z5 Y6 r8 N5 u1 B
                mmc5.Write( addr, data );
0 d, t8 ~: }7 _6 x& q5 Y4 a        }2 i# E6 w9 N% ?$ n2 Z9 @/ q+ C% i6 S
        if( exsound_select & 0x10 ) {
; l& Y( A+ O0 F2 U$ K- n                if( addr == 0x0000 ) {
9 W. c3 D; z2 P                        BYTE        dummy = n106.Read( addr );
) Y8 |7 U) n) Z7 \( c                } else {' R  H' |9 n. U+ V: x
                        n106.Write( addr, data );
' i# I! R5 d+ ^* ~                }
" K0 n, I- B$ r        }
& h+ O; F; t" e3 k' O: ?1 j        if( exsound_select & 0x20 ) {
. x7 D+ N- w4 P4 b: h                fme7.Write( addr, data );5 U$ H' M- s7 M, b$ j: ^
        }
, K2 y5 Y  ]. d* S* m}! m$ J% i5 Z; C- k
9 }% x7 G% y* c: l- l
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
' ]# \' _5 z; Z{- z+ l* k- F7 E$ I, [2 ?
INT        nBits = Config.sound.nBits;
+ J! s" o8 c5 eDWORD        dwLength = dwSize / (nBits/8);6 E: Y6 s1 P, G: ?& S
INT        output;1 Q6 N' P& `4 E! p
QUEUEDATA q;
0 x' y( {2 L6 xDWORD        writetime;& v. E# W; @" B3 N/ n
( a) H' e- P' q# y
LPSHORT        pSoundBuf = m_SoundBuffer;
8 n7 U2 ^" F8 l  EINT        nCcount = 0;
; w0 D. e- W9 g2 d3 Q
+ c9 {* N- d5 p+ w, c% d$ xINT        nFilterType = Config.sound.nFilterType;2 n8 H0 E' k2 g1 k) ]

6 F7 O8 [, k, M0 o4 k* a6 H* |        if( !Config.sound.bEnable ) {$ ?' S! b; T0 W  ^& q( `
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
; t; G* Y$ n5 z8 s& `                return;/ f1 l+ ?( ^' r* u# H# ?5 `3 u! b8 v
        }
/ F7 R' l$ ?" ^* |7 q
, j! y/ Q9 h# `+ F: ~) M3 |        // Volume setup- y& @: ^$ @1 R* M' y' T) a$ [* W
        //  0:Master
$ D! i. E6 T( I9 ?6 n( t' E        //  1:Rectangle 1. ~  j$ n2 B: \# c& f# m& K1 Z
        //  2:Rectangle 2
& E8 A5 X  ~1 y7 S        //  3:Triangle
# J6 n% o7 D( V! f        //  4:Noise& m, g% E/ A  x6 l
        //  5:DPCM- L; X% E6 h5 C1 y
        //  6:VRC60 |& ^$ q$ D6 Z3 a, R) C8 v
        //  7:VRC7
$ [5 P% Y# D0 `2 Y9 R) `        //  8:FDS
7 S0 {5 M! Q& C        //  9:MMC58 e' h- k$ ?8 q0 {+ s& A
        // 10:N1062 C2 y: K' ]( W/ w0 k
        // 11:FME79 J/ q! O- U4 w9 a8 v' U4 S& F
        INT        vol[24];
( x3 d: H" h7 c2 J        BOOL*        bMute = m_bMute;6 i- w! r2 e, d0 U3 [
        SHORT*        nVolume = Config.sound.nVolume;
( F" O0 Y% F- T5 o- l; m7 V  M
) g$ ~9 M, S5 r7 O) `        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- I& F7 ?3 q( W! a8 m
$ U: c* O5 d* f8 w1 C        // Internal8 T0 V! U/ F6 v/ \* k% Y1 B
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( A- a$ X9 Z. N# Y- g# |
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
0 ^2 M; j2 K) D& M" s& `: ~( ?. G        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
7 s. ~4 b. V$ S0 Q        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
* A  x" W: R- f) I, h2 o) `        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, H$ F5 {8 e6 i! D/ ]- X" b" |

* K% @+ p' Q1 l( e        // VRC6
! w; k+ M6 W% h" \, Y6 t        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- w4 d, u4 e( T' G        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ G. G# N, s+ G' ~, m- k8 [        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# r! i7 g! z  W3 ~4 r# k- C7 R2 v3 y" L$ g( B' b$ a+ S! G
        // VRC7
( K3 q/ y& a; g        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;# V# q$ y5 K7 h# @2 @7 g4 ~
9 Y* f  N) P' o) o& a
        // FDS- N* x" p* k9 i+ r( X
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;% x* k: s; H, i$ e) c$ V
0 U- Z6 @* S0 T
        // MMC5
# b/ U1 p! G# T. c        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 g  @8 _1 o) \9 D$ I& ~. o        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 }6 {& _5 y7 f* i) f$ k( Z        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 y, x# A7 w* h4 j
- C8 t' H: u& x& D& @+ \
        // N106
3 U* a2 N7 g$ X7 e' {$ v5 s        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 J1 G5 l  M0 o* x* d# @5 y9 P2 u
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 U9 |' C0 D  F( U4 }        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% X( ~! L, p6 F% L# b: l7 i  l
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 [+ x8 E5 |( }1 I        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) \& e1 W6 b0 C( N        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; _, z& B3 D1 m
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" P9 B( |, c  D
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 J% C* d4 f: P# k
7 _5 f: n; R+ o        // FME7) b6 T/ y6 y: E5 G: k
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: F5 E4 z8 p7 @. c% T; a
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* A( p' J, T0 e) U1 I/ z
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( l* J, F, s1 `2 q! v
3 H* O3 h$ \) A/ c- p: C1 I9 S3 m//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" K" n2 s, m$ o6 U0 g8 y        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 ?: I/ f+ i7 G( A
* j( c. G0 O3 y1 Y; y
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟! ]+ @  B/ t! G, v; e
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- m/ p8 J! Z+ k
                QueueFlush();
) m; ^9 d8 X0 G8 l: S7 P- ?% |        }1 W% }1 K7 L  {& }
8 v  c7 ^, A- x. x6 y/ Y
        while( dwLength-- ) {" Y1 Q4 J3 D: V
                writetime = (DWORD)elapsed_time;1 q  ~+ _) I. v: ]6 j$ N, [
" [. D2 D# z* ^7 r
                while( GetQueue( writetime, q ) ) {
+ \; `% W7 k4 S8 c$ @                        WriteProcess( q.addr, q.data );6 O; |3 H. M- g% D
                }. N8 {  o6 _. n9 v1 _2 J

* j7 [8 a4 U, x( Z" u1 `                while( GetExQueue( writetime, q ) ) {+ x% K1 I3 i" T/ H. s" E
                        WriteExProcess( q.addr, q.data );( \# I( j1 \0 e7 r: F4 N
                }3 u" m$ @: @' N( c6 g& k( P

1 C+ k; f6 `: c8 i. f                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 V1 v+ y3 q5 r5 m3 |% C! v7 a1 P6 _                output = 0;
& |2 ]7 c! p/ X. G: N                output += internal.Process( 0 )*vol[0];
& w1 E1 k0 G: u, ]1 O, j! _                output += internal.Process( 1 )*vol[1];- t3 f$ f0 w. L" D$ q- z% g3 F  S
                output += internal.Process( 2 )*vol[2];
) O% J2 v* Y) y2 F! O) ~                output += internal.Process( 3 )*vol[3];
2 z7 x2 t' l, t                output += internal.Process( 4 )*vol[4];% o! U7 L1 p' d3 _+ Q1 v' W
! z) f# a# a0 f2 g7 x: i9 Y4 q
                if( exsound_select & 0x01 ) {1 d: G/ K- e3 C! W5 _, s
                        output += vrc6.Process( 0 )*vol[5];
; o3 Q5 _( f$ `) ~% ?                        output += vrc6.Process( 1 )*vol[6];* l# e% U& Q, t! ]$ d
                        output += vrc6.Process( 2 )*vol[7];) f. E4 S( ~) C9 \
                }! Q& z$ S4 O9 W8 U+ y9 `
                if( exsound_select & 0x02 ) {
2 m1 H& I- K- J& A                        output += vrc7.Process( 0 )*vol[8];
' C- ~( F( ]  e3 Q# A/ q7 K7 m                }
$ m  Z. L% t8 }! M                if( exsound_select & 0x04 ) {0 a. f# Z: `) C7 ~
                        output += fds.Process( 0 )*vol[9];2 ~" Y& g; a0 C$ L
                }
' R' T" ]# ~% r. {) R1 ?                if( exsound_select & 0x08 ) {  H8 P) E# g- n) ~* }! O
                        output += mmc5.Process( 0 )*vol[10];
0 r, G0 S. v- B# c                        output += mmc5.Process( 1 )*vol[11];
5 u  M  @7 Z+ Z                        output += mmc5.Process( 2 )*vol[12];* b" H; w+ @8 n# i1 [3 i
                }
" }& S) M. a' r( z  v" }+ q& q( }" [                if( exsound_select & 0x10 ) {* M7 k- y+ J. ]) B; a
                        output += n106.Process( 0 )*vol[13];  z9 b/ V  U* A. R+ r
                        output += n106.Process( 1 )*vol[14];$ ~) X4 c. f3 Q; K8 Z6 `- N9 K+ y
                        output += n106.Process( 2 )*vol[15];  J4 [- R0 l; ]1 d& F" t
                        output += n106.Process( 3 )*vol[16];  w$ G- x' s* o, H# ^1 A3 m
                        output += n106.Process( 4 )*vol[17];
: `6 A) k- D* Z3 O                        output += n106.Process( 5 )*vol[18];
* R' P2 R1 B: u                        output += n106.Process( 6 )*vol[19];
- o* _# z, S8 u5 X5 J                        output += n106.Process( 7 )*vol[20];* G- z7 _9 t! A0 g$ `! N
                }( `* x! Z/ U" ?% S& u/ x
                if( exsound_select & 0x20 ) {# |; M3 ^+ w/ w3 A. X' T9 z) |
                        fme7.Process( 3 );        // Envelope & Noise
. f$ D0 h$ u# {5 Z9 V9 {( k                        output += fme7.Process( 0 )*vol[21];
: P$ _* R2 {. x) y; |1 e- j                        output += fme7.Process( 1 )*vol[22];1 ^, v5 ~! S; a
                        output += fme7.Process( 2 )*vol[23];/ N, h) |5 J; N% ~% a, Y; T
                }
) C: @9 a: M; a' P: \
7 w" @4 G% w# Q/ j& k- H- B                output >>= 8;% s2 Z* ~, s+ R0 j

7 d% v3 b3 }! T2 W2 @                if( nFilterType == 1 ) {
7 [2 w" z; h+ q  w* C3 w' l; R                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
; K5 [! Q0 u1 }7 J2 l3 t                        output = (lowpass_filter[0]+output)/2;2 K( j4 y; D  v8 ~, S
                        lowpass_filter[0] = output;6 S! Y1 |( U7 f$ V4 E6 v6 l
                } else if( nFilterType == 2 ) {
8 O' I. K8 c, z1 E* y                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
1 S; ?8 `* |! {/ [                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: u0 @4 ]; w% B& ^" Z( b* K                        lowpass_filter[1] = lowpass_filter[0];
7 I. Y2 U( A7 b1 N# ]                        lowpass_filter[0] = output;
: n" h3 d9 C& A/ A0 o# a                } else if( nFilterType == 3 ) {& d* p( p  l# W1 q5 |# h/ G
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 ]5 J) b3 M/ @* R. c) k2 N" O/ [
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 |( f5 Z" Z8 s% s                        lowpass_filter[2] = lowpass_filter[1];) a0 Z# ~& @+ y3 }; L6 d4 M+ R
                        lowpass_filter[1] = lowpass_filter[0];
, A" ?/ J$ z' g3 M1 K* ~, N* u3 }                        lowpass_filter[0] = output;; E- p; }% c7 n  N
                } else if( nFilterType == 4 ) {* w% @, W0 S( U- d7 h
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& P1 y; C) l4 |" N( W6 [% t                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
  `  o% `5 D1 p+ j2 s5 b* }                        lowpass_filter[1] = lowpass_filter[0];
+ _) o0 k, f" Y5 Q! {                        lowpass_filter[0] = output;
( |+ O& ~- {% J) a" i                }# N7 C' R8 r6 \9 ?' P/ S& G
* X2 F1 Z/ |4 E- Q, F- r! ^
#if        0# O* }! O" {" y2 I/ P  J7 _# p2 ~0 E
                // DC惉暘偺僇僢僩
) N% I' h7 o) S; B) g: j! E                {' W% v3 {; Q6 {# H# [5 s, n
                static double ave = 0.0, max=0.0, min=0.0;
4 z. k6 h  B5 e; U( E( z1 e                double delta;
0 [  P$ R8 `7 J' v- u* m                delta = (max-min)/32768.0;
4 n$ u& s4 `0 j: g7 U                max -= delta;" s# ~6 Z8 M% {7 V
                min += delta;
! c" q$ k0 s8 o1 _9 x# m: s; K                if( output > max ) max = output;
6 X& ^5 a* O) r$ V, M2 B                if( output < min ) min = output;
6 e; S# |5 Z1 G; a2 U                ave -= ave/1024.0;
5 ]6 z' T# o+ D) b( _                ave += (max+min)/2048.0;
' B3 N. b: d# |                output -= (INT)ave;
; y+ E! z6 n" d9 i$ g                }
% [/ W+ `0 l2 R7 y( F, W+ Q& E#endif
9 U  L$ Z! O2 }& e#if        1. ~' J8 e& ^* V( l. j  K/ A5 g) o: u
                // DC惉暘偺僇僢僩(HPF TEST)
# P) l" t4 n8 e& k% T                {" u9 H  x8 k6 ^) l7 O! W' W4 w( J
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
, [' K3 _3 \; w! a8 B                static        double        cutofftemp = (2.0*3.141592653579*40.0);
" [' _  `7 T5 J                double        cutoff = cutofftemp/(double)Config.sound.nRate;. _2 X0 J: L" V. o! {  L
                static        double        tmp = 0.0;1 m, [* L( }* Y" x0 z
                double        in, out;9 U. E2 X) w% V$ Z" q1 }% t

3 {5 e& ^: W! j6 n) m                in = (double)output;* G" d' O3 X/ {
                out = (in - tmp);
8 j1 R$ ^. b7 ^5 X2 W& d, v; v5 B                tmp = tmp + cutoff * out;9 E; ^+ m2 P% W: p; F
7 r* g! K6 y: E+ e5 L
                output = (INT)out;( v- U6 F9 M# P4 N1 h& z
                }
  k1 y- c3 `+ j1 t4 U# l#endif8 f8 p% d. c! R: \) `
#if        0* n" I/ _2 J9 z; D) V
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% U/ h2 O; \6 t9 I$ v+ ^9 A
                {
& J* V) p6 m1 {: y/ Q2 d7 k                INT        diff = abs(output-last_data);
" z$ i$ S+ y' i/ S1 X                if( diff > 0x4000 ) {( Q9 S& W% E9 u) A0 s! V+ o/ ~( @
                        output /= 4;
; z( I7 D& u0 f9 ?! g/ D( F                } else * Y+ }; I' F* s* v8 c/ Y
                if( diff > 0x3000 ) {+ a! E1 C$ m( ~2 A  r7 Q5 }6 l
                        output /= 3;
  Z' C, w: A/ q# `& C                } else8 J  X- N7 H4 _% n
                if( diff > 0x2000 ) {
7 W7 t/ r2 C& t) w% h$ j                        output /= 2;
4 k& S' r- R* \+ Q3 @- N* W                }
: {' \: H1 ]4 z* Z4 I) n* X0 r                last_data = output;
/ h; ^: l) ~  G( {2 H                }" Y8 T8 }$ }) o# D* Q
#endif8 V8 o9 H: ?& }) y  V
                // Limit
- u" @# s/ z% c" ~                if( output > 0x7FFF ) {' s5 B8 ~: l" c! k  \  V0 O
                        output = 0x7FFF;
7 ~( @; X5 s& q- [3 C( H& l; N# W                } else if( output < -0x8000 ) {! W$ O# Y. p! I( S) N
                        output = -0x8000;( Z' j, q3 ~. [5 c: K" ~: x
                }. [' j, I' q9 _) A2 f/ s: Q; P

0 E- ~: Z/ g! |                if( nBits != 8 ) {) N+ S3 A8 O  b4 |/ G
                        *(SHORT*)lpBuffer = (SHORT)output;0 s' n/ C7 y7 p7 h& P$ n
                        lpBuffer += sizeof(SHORT);
4 u, R% }( D: q2 _* d$ m$ e                } else {# p: G9 p  _4 J. ^7 H9 P
                        *lpBuffer++ = (output>>8)^0x80;
) [9 |7 o! o; `4 J                }+ k% w6 {/ s* P: k+ c$ I

2 l  c, ]5 }' {  B* S6 |4 J                if( nCcount < 0x0100 )
  p- N+ X" @/ ^                        pSoundBuf[nCcount++] = (SHORT)output;
1 ?% }$ ]3 f6 i: o  P4 x1 s
9 m: C+ T( f8 Z% h3 x2 S//                elapsedtime += cycle_rate;
" Z1 |! j" I% b8 c* _& Z                elapsed_time += cycle_rate;
* ?8 I( z0 i: H5 W        }
' D8 a0 H* ?$ `6 S4 D% _! Y, s# |/ u) `) {9 d
#if        1& D) ~0 `  H5 n7 P: _/ ^/ u
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 a$ H! s( w3 O9 U' `% J9 `                elapsed_time = nes->cpu->GetTotalCycles();
& r! v* k7 T: \8 q! [: u. r        }
& b. Y6 D; x) M) U9 [        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 ^5 ~7 ?' R+ q, t: ~; H7 [
                elapsed_time = nes->cpu->GetTotalCycles();
8 K! M1 t7 m- |8 v9 T7 ]        }2 r' Q! `1 \" e: U! f
#else
% u8 M9 L8 f" s! U! `' v5 [" f        elapsed_time = nes->cpu->GetTotalCycles();8 _/ Z6 u- O- f3 n& X  a
#endif
; F$ r4 R5 i7 p  m( n9 z# }, `}
$ V* X( d, i) s; p2 b. N7 D2 y/ E+ Y1 S
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
0 }- ^8 u% z1 ~INT        APU::GetChannelFrequency( INT no )
* s3 c: ^. N5 U0 |6 Q{
! o. y  t7 ^; P+ E/ n% l* j8 V* G        if( !m_bMute[0] )7 `, l$ b7 v' ^& J, U
                return        0;3 Q$ E& W) h8 N. }$ X; Z3 B( w
9 B0 T3 Q: y' c; F
        // Internal
2 M) B4 L7 e! T2 l        if( no < 5 ) {
  z9 D1 H# W/ C) l                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 D, P% E+ r+ f0 P7 p8 x        }* V: |0 O, u) G0 g! s0 B6 V
        // VRC6
- s9 C( K6 [8 ]9 `% G        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ {( ~9 O  T) m2 N/ Q8 @8 ?8 W1 q                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( ^+ D3 d" |/ w0 _        }3 E; `2 n- c; C; u* E8 w) K! B
        // FDS% J2 Z' P+ P  c: e: H  D" O& c
        if( (exsound_select & 0x04) && no == 0x300 ) {
8 m3 S5 c+ i3 p8 ?( a' N                return        m_bMute[6]?fds.GetFreq( 0 ):0;- @7 A2 |! m9 T: l' `  a
        }
' p' y* w: o( R) Q( B5 i2 |        // MMC5
6 m7 H# H6 C% F& G7 ?0 w% ~, j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, S; f; V; d9 ~% E/ A1 d2 F                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 ?8 D4 A. ~% k' f9 i, x        }
) h0 a; U" \) b+ f. l- D        // N106
# \/ Q2 [. g6 T' I7 S# C9 N        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 i0 V/ r7 N! v! C, ?, q8 N                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 F$ P9 r6 i* A
        }! ^( ?' @0 `: W- Q/ d
        // FME7
) B, j- \& O7 n        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
: q: L& Z/ J$ B9 V+ z, e                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
6 [: B5 B5 @" Y        }% d4 R" v6 D" _4 q; ~) b" E
        // VRC7
! t( m: Y5 ]3 @) }, w/ j) E+ U/ ~        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
! a% _  b# [0 D$ _% ?                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
6 {0 K8 C8 j: G1 H: c8 _9 \. l4 n        }
  S' s/ G; V$ t. c/ I% i1 d- Y+ R4 J        return        0;
9 ~) Q; d' J4 \" J6 {* N& H8 I}$ Y) A# R& y- h$ h% W4 ^$ }
- d$ m) b# W+ i
// State Save/Load1 ~6 H+ Y% s" k- k
void        APU::SaveState( LPBYTE p )# R: U  b' a- |6 T$ K6 V
{# l2 z# |, U/ {/ U5 ~- W
#ifdef        _DEBUG! S' S1 E( J% w! B* `
LPBYTE        pold = p;
! N3 B- }. L3 ]#endif
. l2 m7 c& n  t- \; \6 a) l; {( a
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ E+ P: ~0 s) D. W' u9 q2 h
        QueueFlush();2 e( f. l" U; w- s8 s
$ q2 J8 z5 Y8 K  o" X8 e6 u6 _0 g5 [
        internal.SaveState( p );3 M8 Y9 Y# S8 z  M- F5 A3 G9 s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 p& y+ t+ G9 g
+ v+ p7 M* O2 z' b- J) p
        // VRC61 X0 s  t5 q( c6 s9 E
        if( exsound_select & 0x01 ) {! _. n% S& s  X
                vrc6.SaveState( p );9 u/ B/ @- E. q5 Q# N' N7 S  ]9 x
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# ]' ]& I/ u7 u/ N7 b% V
        }
3 \# Z9 \6 ^% l! S/ V* }# u% D6 k2 ]        // VRC7 (not support)9 [' J0 I4 Q# {1 T% ~0 S
        if( exsound_select & 0x02 ) {" O7 v" n% @% c, O+ d, E% Z
                vrc7.SaveState( p );
8 J1 X, K9 |/ h) x+ w1 Z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ P5 p7 v  Y+ F8 P
        }
# Z; b" _* ~+ y+ L  i1 t        // FDS
5 E5 \6 U4 O' V' E& V8 w8 y        if( exsound_select & 0x04 ) {1 k/ O* U% H& m1 N1 c# y
                fds.SaveState( p );
+ @5 b3 E2 T8 o. ]* C; S. Y5 V                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 }' ~( l' t: l/ i$ V5 s
        }4 u2 `- @4 b/ n+ |" h2 f! a
        // MMC5# s# S' S$ r- p# \+ @+ s& e
        if( exsound_select & 0x08 ) {( ?3 I/ ]. v' x0 h5 ?- j+ w% O+ m% Y2 z
                mmc5.SaveState( p );, s- E0 {  L& F3 a) z9 Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: u6 ?! _, r- B, R+ ?        }
5 x  ~- B) o" ]# w5 T- f$ G0 C        // N106
, @8 _( V8 d8 G, l9 z        if( exsound_select & 0x10 ) {& F0 I' n3 d+ c" d2 U
                n106.SaveState( p );
7 `/ m5 p# K) T) Q1 e" V, k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: K8 ~  ]2 [" V
        }
/ P  u4 ^, Y4 w2 w3 J        // FME7
2 c7 \* i" s3 v; R1 t/ Z! E        if( exsound_select & 0x20 ) {
* K! X. @" u$ b! @9 A                fme7.SaveState( p );
9 H3 S3 K. {) R3 }2 M+ c                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* D. x9 G( F5 ^1 }/ |        }
1 W+ C/ I; T9 ~  [: j8 y  o  b
+ o. M+ a0 i+ l0 E$ g- h#ifdef        _DEBUG2 u( i3 a7 ?- L" W
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 R9 z; C' ?: k4 J! A# G- `2 J- G( j#endif$ V- s3 E5 a: E1 |' Q1 [( \5 R, s9 p
}
) }  ]2 [; P. r% T3 d+ n6 K5 L6 e" N3 x" M( |2 d! g0 s* t" i
void        APU::LoadState( LPBYTE p )
, r" u# o/ X" S{
: Y$ ~( c/ ^  T9 t! k* V8 z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
& K6 x  n0 I! U0 l+ a# `1 w1 h& o        QueueClear();
. n. ~4 i# @+ k0 W* T; ]$ V& D. C2 t  E1 [
        internal.LoadState( p );
0 i$ D& [" S8 U# m. y        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ A; h# k7 v2 \* C

  s4 F0 Z) l1 i. a        // VRC67 @8 |- N3 r; a" H1 p  V
        if( exsound_select & 0x01 ) {. G6 E% M+ C. u# E" t
                vrc6.LoadState( p );. P( H5 g" h% o( l
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, j7 M: ]% H' h7 K- j0 f
        }; d' h, j+ R6 m: t! a2 J4 A
        // VRC7 (not support); A; C. w( y& r
        if( exsound_select & 0x02 ) {0 N2 E1 K, @+ J8 ^" D
                vrc7.LoadState( p );1 P$ _) f$ P; f% l/ @; C4 \% h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 E- \  Z; a* F5 x6 @# ~# B5 X& L
        }6 x% P* B' h, T' y2 H7 h+ o8 h8 h
        // FDS
' U( g6 o! B# w" l/ L1 h: a& ?        if( exsound_select & 0x04 ) {- X. y% n* d9 Y
                fds.LoadState( p );
: \7 j) v. b2 [+ t# e; P                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: F. K! M7 p6 M5 I+ ~( Y
        }
3 B# D% j9 ?- T% H7 I# s8 I        // MMC5
* J* e& C) K# p( W        if( exsound_select & 0x08 ) {
& ]/ c* \5 x+ x& \. c3 ?                mmc5.LoadState( p );
  P; h( q  t- I% l                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 P0 V+ Z4 o3 g, U
        }
3 M2 n0 u$ h3 }3 k: q% C        // N106# W% m/ X0 F- I7 y4 g
        if( exsound_select & 0x10 ) {
& g5 G: l9 \: r  g+ K% l4 m8 u                n106.LoadState( p );. n( X4 V( L4 q* r2 g/ l$ f" |# e- `0 J
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 O- s' A8 \$ h1 A" R        }
5 G& I: S0 }6 ?" b# t5 }        // FME7
1 ]" I0 Z) Q) k( ~7 P        if( exsound_select & 0x20 ) {
. c; @$ g- N5 |' m' \$ \2 G                fme7.LoadState( p );9 M4 h9 G6 ], d; d( l. l
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ r$ w  V) p3 M& Y$ }( a1 |$ A        }: U) ^' M0 y* N
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 4 K, v+ c* x' q, z! A, R
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: X* r8 z9 B: {$ q( S感激不尽~~

; `9 s! l) ~( Q. {( _) i恩 我對模擬器不是很有研究,
, }- f1 d8 E3 v, A2 x" |6 s雖然要了解源碼內容,可能不是很困難,1 }- `! ?  Q# p, H$ R
不過還是要花時間,個人目前蠻忙碌的。
0 B0 y2 L4 c" [1 h7 f' Y
5 q# t, ?# o8 e" v1 P+ A給你一個朋友的MSN,你可以跟他討論看看,
  S& {9 `5 S8 W. G& T5 e他本身是程式設計師,也對FC模擬器很有興趣。
) o0 |9 K) \) m+ q8 B' ~$ P1 w1 }' P4 a: c) j9 }
MSN我就PM到你的信箱了。
, p& ^& O8 I- A: @8 a/ o3 D2 p- L. }' l/ b. N, ^/ [( y
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 3 e% W! d* A& z0 M' l( {* u3 r: g
呵…… 谢过团长大人~~
7 p& _$ J0 @' N% M; C6 s8 F

$ r' @, W  a6 b" g哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
8 g7 W' }. O' R, |! z% v' f团长的朋友都是神,那团长就是神的boss。

- @: {9 K* A8 ?4 Z哈 不敢當,我只是個平凡人,$ M% W; s" _3 t! d
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙6 k6 C! `0 d, O
ZYH; r- p# @* ~8 V  `  X
QQ:414734306! ]) [) I9 ]' k0 w6 [4 s
Mail:zyh-01@126.com& @+ P# C5 [5 @) G

2 Y7 S& f3 p3 Z/ Q$ f他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
2 e* E' W' m0 n$ [  A再次对团长大人和悠悠哥的无私帮助表示感谢~~
1 w0 K) P1 {' |0 x7 J
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-9 17:16 , Processed in 1.123047 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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