EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 z( [. u% `: ^5 q$ {$ t楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ ~; J" _+ U; E. X  B9 f" |5 j' G
这里有相应的模拟器源码,就当送给大侠了~~
0 D* G& Y+ [/ S, ^% k2 V- xhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
! k$ P0 [7 U5 _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  L7 B/ z) t' \' _- }1 _
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ Y, L! b$ _! a% v& ^' r+ T这里有相应的模拟器源码,就当送给大侠 ...
* y+ z% y0 A- X$ g) b1 i4 d  K) o/ V
聲音部分(Audoi Process Unit = APU):
% K3 [3 f6 T. T; A- w.\NES\APU.cpp
& i; q* e) m/ O, }0 m+ V.\NES\APU.h7 O. x( w0 ?  H! t$ i

& h* _! x0 l7 S/ v' J# D2 O) Y/ u3 k, r; d' C, H3 V" U
影像處理部份(Picture Processing Unit = PPU):' w  {: t2 q5 X( o) h/ z
.\NES\PPU.cpp% }: e0 a; R0 q$ H9 B
.\NES\PPU.h! ~9 K. C) I. l: t9 W2 q
: A: n0 V% e  e3 r
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
5 m( E- s0 [* T  ?(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; V* a( |1 d% e( \//////////////////////////////////////////////////////////////////////////
4 H/ \4 d6 Q: |//                                                                      //: j; r2 u! W: L9 Y% m8 ?
//      NES APU core                                                    //
( v$ m& _9 Y/ x7 }4 ~- D9 |//                                                           Norix      //
5 R1 H  n6 F) z$ A0 T//                                               written     2002/06/27 //9 n$ D4 B4 @5 B! y
//                                               last modify ----/--/-- //
. X2 t5 i, X4 z; u  o& x; s//////////////////////////////////////////////////////////////////////////
2 X+ N4 u( B( `8 ^) G#include "DebugOut.h"
# p* V2 f( v! A( V#include "App.h". y7 J2 Z% \2 _- `4 B5 C
#include "Config.h"7 j/ i3 D; t5 ?& U4 {5 h
: e4 d7 c! H, F( a- ~& }& ?8 r
#include "nes.h"
& D" l  `. L9 G0 f2 Q- P- S#include "mmu.h"5 {, _6 S* x& J
#include "cpu.h"/ x# }; l2 t2 R0 ^
#include "ppu.h"; B! l. S. v. t, V9 z4 v( E5 o4 n
#include "rom.h"
* {* i6 A) [: q% e#include "apu.h"
+ p0 E" f3 [4 w
/ Z& L2 r. x' [0 q// Volume adjust* h, ^- ~0 l& E
// Internal sounds: S+ d; w8 u) E, q2 B& w. @
#define        RECTANGLE_VOL        (0x0F0): N& p' s9 H$ h* {& |& H) U1 O8 T, Q
#define        TRIANGLE_VOL        (0x130)2 b' K) v8 e! k0 r' H+ ]
#define        NOISE_VOL        (0x0C0)
2 M: g' T2 V6 f1 T! w! V6 N#define        DPCM_VOL        (0x0F0)
  C3 ]6 d  O" m4 I0 ?. _2 F// Extra sounds5 L( D9 f0 q5 D+ U5 ^
#define        VRC6_VOL        (0x0F0). K) l6 A( f* K) Y$ o% o
#define        VRC7_VOL        (0x130)
7 ]* v' q6 ]: @4 x# E6 d; l#define        FDS_VOL                (0x0F0)
! P( f0 b- O. a1 ~#define        MMC5_VOL        (0x0F0)% h' P" T# Q1 O
#define        N106_VOL        (0x088)4 }4 N& r$ f4 |5 r7 _. w
#define        FME7_VOL        (0x130)1 l5 m5 m: p$ ^% V7 U

: v) [& |2 A5 s3 ~6 S2 W% ZAPU::APU( NES* parent )
; \; g; a9 T; @/ v1 ]7 L* q$ e! p{3 ]; \" l- a- Q" |3 M3 i
        exsound_select = 0;
& c) I" e& k- l* q+ A7 [" y4 j7 C
$ t; o; A2 x$ A; x; I4 E( K3 D        nes = parent;
$ M- B* \8 j2 ?        internal.SetParent( parent );
1 [+ ?. z5 w1 t/ @' B, }7 ?) W* P! L- L" s1 I- Y1 E) r
        last_data = last_diff = 0;! ^& p! M! P6 s7 T& p' p
. w, D6 Z4 T5 V
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
$ V) n9 h+ G9 [8 C, C8 r
% C, K8 U8 y6 v1 P7 J  n        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
* J" L, U! s- i  a. q1 k" @        ZEROMEMORY( &queue, sizeof(queue) );
2 H# G$ U1 Z6 d$ @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( B- o1 O9 y) [0 T6 w& f" B1 |
: e; n7 l. s# b0 v# N) j        for( INT i = 0; i < 16; i++ ) {- D- Q' Q& C7 B
                m_bMute = TRUE;
9 J" a- C" E  {- J' q; I( }8 ]        }
, n& r) ~4 _1 k8 g5 L7 M2 K}
8 q7 ^4 \& W8 b' G0 b9 N* @% e7 e( ?3 ^) g+ ]
APU::~APU()
+ H) g  C& v( F& q: B4 S2 s{/ C! U7 m1 z8 F" w0 D5 H
}
' ^3 |' z% p6 o$ k& J
: v, r7 s* i& U$ R) p: d8 `& Svoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
, C! Q9 x/ P3 T# V4 i+ U4 P{* B8 s) `& [1 Y* x: X8 r
        queue.data[queue.wrptr].time = writetime;) a3 F3 @& H, ]) }3 j
        queue.data[queue.wrptr].addr = addr;/ n% J/ m: b* e/ v
        queue.data[queue.wrptr].data = data;
& d2 T) J+ C. W' N: O& W, E' _3 j        queue.wrptr++;
$ u+ z' k& [: E3 J! H) M/ A0 F        queue.wrptr&=QUEUE_LENGTH-1;, A$ U  G  |& \
        if( queue.wrptr == queue.rdptr ) {
! g6 ^% p! C8 Z1 d' V$ Y3 g                DEBUGOUT( "queue overflow.\n" );
; b- D3 H5 s& B; B        }
: q  I7 r* Q; g}
, B; |( K$ W* [" R" @; D( k0 ?$ W1 b0 y7 J& M
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* N! E0 B+ H; J2 ]8 N8 g& K5 y$ ^! d7 t{% D8 \! l# |# T- r
        if( queue.wrptr == queue.rdptr ) {5 \, c; L, N/ `' @: b8 }
                return        FALSE;9 T" A& i, S5 a4 q* c( r
        }
, G# t) N' u# F8 c8 O8 T' Q( B        if( queue.data[queue.rdptr].time <= writetime ) {( _* s7 _1 ~7 `  O- V) n
                ret = queue.data[queue.rdptr];
5 `+ Z5 L: Y; |% y% ^0 z, U                queue.rdptr++;
5 v" n* z/ N3 U# z( p4 @! N0 X                queue.rdptr&=QUEUE_LENGTH-1;
  q3 C* r% M9 ~% I% A. f                return        TRUE;: r4 J# R* F3 P. C( e. e: b% E
        }+ m- F$ k5 D/ m, U. a4 a+ V6 |( v( r, s" c
        return        FALSE;; Q$ f4 X! Q( ~6 ?" q
}
, N  ^7 L6 _+ B" E
" A7 U4 \- G" e4 e- K9 b7 nvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% ~# E; d! g+ M6 k7 {0 }% L
{
. k7 X3 b. d. K# g$ O        exqueue.data[exqueue.wrptr].time = writetime;' X& d4 @( ~% _' S9 Q
        exqueue.data[exqueue.wrptr].addr = addr;% E8 o% P2 R+ z* N$ j5 V6 N9 k
        exqueue.data[exqueue.wrptr].data = data;
* D5 |% I8 ?. e7 ]. r1 X5 S4 K1 K+ P7 u' f        exqueue.wrptr++;
: N2 e5 M+ x& d& S* u3 d        exqueue.wrptr&=QUEUE_LENGTH-1;1 M7 i' W' D+ r2 d! _6 a
        if( exqueue.wrptr == exqueue.rdptr ) {
7 ]& P$ N/ x$ [$ [                DEBUGOUT( "exqueue overflow.\n" );% F/ K) R4 C+ x( E  s
        }
( R# E& ^2 d4 o# L+ T6 e* O}
& Y3 w& b, ]1 z& ^; E+ m1 S- _+ _# u/ ^. P6 I& M
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )0 U- T7 l5 p) K. H' ]
{! v& ~9 q4 |  T, u5 q
        if( exqueue.wrptr == exqueue.rdptr ) {; m" E) H1 [8 p' }3 t
                return        FALSE;. g, k5 c: y7 @1 C5 Q
        }7 @' _! E' y6 x+ O7 c
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' j. k! @# M# `% u
                ret = exqueue.data[exqueue.rdptr];1 D# K! N% ?; {
                exqueue.rdptr++;
, d% _1 C6 m0 P  _- m3 n                exqueue.rdptr&=QUEUE_LENGTH-1;
" _; z8 y8 q5 `% W, E4 R2 f                return        TRUE;
5 D! |+ N  U. E7 r+ s6 n        }
9 M! C/ A( ^+ `) \+ S- M" u        return        FALSE;
. u0 D4 R, f% @5 |: l4 x( R( N}
: S" P& q; J% ^: q* @8 U6 x. m0 R6 a, K5 D0 n4 n( U4 f" Z
void        APU::QueueClear()
' _  N! ~: c% C1 I{# f3 M$ E8 Q) m& h' m& r2 B
        ZEROMEMORY( &queue, sizeof(queue) );! F. R% u7 L2 e5 ^* G: K" i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' s8 ~& I/ m, a}
! u' @  g' n, z1 R3 t( L
2 V& {. M! o* L6 J8 Cvoid        APU::QueueFlush()
, b3 Q% \. |; k( E4 C5 g/ Q{6 Y- W" L: b0 j$ f9 Y
        while( queue.wrptr != queue.rdptr ) {  M2 b$ K: B* q
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );" `2 \' d! S; O: k
                queue.rdptr++;8 j6 Y3 r; ~% B4 E: v
                queue.rdptr&=QUEUE_LENGTH-1;* Q' S% z3 C: h4 R" @5 S9 j6 Q- Y
        }
, w0 z. a: O/ X# w* \4 t
7 _' @7 Y' i5 ?        while( exqueue.wrptr != exqueue.rdptr ) {
8 n7 j2 P5 a8 z; G& N6 j                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* g0 E3 ~  {& d( Z* ?; v4 H                exqueue.rdptr++;% ?# t. s3 C7 K6 K
                exqueue.rdptr&=QUEUE_LENGTH-1;
  ]( k0 a( @7 U        }
/ t+ i  x* H- j}4 ?( h# E9 g5 O) \" q. c0 P
* K" P/ i3 \* E* z8 \( ?* k( ]
void        APU::SoundSetup()
; E% @5 T: ^5 n% C{
  k; w% `# s+ G0 S8 y        FLOAT        fClock = nes->nescfg->CpuClock;+ a$ }% H# R) H; A+ M7 p2 {2 r
        INT        nRate = (INT)Config.sound.nRate;
1 d5 i% W6 U( x0 O        internal.Setup( fClock, nRate );
3 N  E/ @$ ^  J. p        vrc6.Setup( fClock, nRate );" D' @% n& E! }8 L$ v
        vrc7.Setup( fClock, nRate );9 l7 G  f$ q  m& p7 y
        mmc5.Setup( fClock, nRate );
. y2 e$ O% O. x# Q9 Y+ \        fds.Setup ( fClock, nRate );
8 Y) A6 B. i5 Y5 z5 @8 h. D        n106.Setup( fClock, nRate );0 a+ D/ R+ S& b6 g7 D
        fme7.Setup( fClock, nRate );/ m: X" B3 \! x! o' N9 T
}
' e! s) y/ `3 y" Q/ ^, X* M! h+ N7 L! x6 E7 D; C
void        APU::Reset()
( v2 u4 m  ?$ S$ d{
* i1 {' w9 ]. C        ZEROMEMORY( &queue, sizeof(queue) );
9 ]2 L) p* m' H# w) J2 }& n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% v" p: v2 Z% U- N. d9 A- [+ _
4 @8 y2 S' L/ U' T+ S3 ]        elapsed_time = 0;3 u# ~) l7 Q; K# S7 ?; |% K- K

! ]. h2 F" S+ U& t1 ~+ W        FLOAT        fClock = nes->nescfg->CpuClock;4 Q' e- e9 I, o) j
        INT        nRate = (INT)Config.sound.nRate;
% g# {* H) X1 a5 ~        internal.Reset( fClock, nRate );9 p4 ?& p+ Z4 g8 q
        vrc6.Reset( fClock, nRate );# J; A0 r6 ~, C
        vrc7.Reset( fClock, nRate );0 V* k" K4 }0 r8 P1 X: ^- m
        mmc5.Reset( fClock, nRate );* W) n3 R& k# {+ P. z) ?9 h% p+ @; `
        fds.Reset ( fClock, nRate );
% v. S# A& T9 Q  f" j7 O9 ^) G        n106.Reset( fClock, nRate );
/ p: g* ^# H% h9 n) T/ B- Y        fme7.Reset( fClock, nRate );
1 p: |$ {  z! A9 J: X; ^- O/ m4 S' T6 @, T9 [3 n) ?# p4 k
        SoundSetup();1 C3 i+ `- l  Q
}
# L$ X7 F/ O5 P2 c: }( N( X' G, C" V
void        APU::SelectExSound( BYTE data )
5 G7 W( M* t: A& X7 V( M7 \{
+ Z* j2 R. `. ]+ y3 Z6 ^* }8 M        exsound_select = data;
4 U" k1 L6 l# h# n3 }; W+ _}
: C/ C6 M6 p$ q# [& h- A5 W. l# e' d0 c! i, j1 X
BYTE        APU::Read( WORD addr )% ]3 @( Y2 @9 \7 H+ S
{
' @! X  l! x0 m1 K" O, _        return        internal.SyncRead( addr );- F( C; g8 ?# ^* t
}
4 |5 x3 L  T* k8 |" _7 J9 F5 D$ z  f9 i- o4 Z* |
void        APU::Write( WORD addr, BYTE data )
; w# n* f+ }7 B5 G+ P5 c, E4 P{& ^  e, J) K: T
        // $4018偼VirtuaNES屌桳億乕僩' R- @. K+ e3 n5 t. d- S1 U3 K
        if( addr >= 0x4000 && addr <= 0x401F ) {
- `, q* q* J; l( M/ r! G                internal.SyncWrite( addr, data );0 O2 |/ R. O6 a7 i6 }+ R  c/ k' b( b
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 E: H% ], }# d        }
* L$ f2 G8 D. A/ L" Y3 t}0 d2 ^0 S0 e9 K" L# r1 p5 m

2 a! P$ H* v4 _& ]BYTE        APU::ExRead( WORD addr )
8 N/ W7 d7 ^  m3 L* o{
/ _- q8 e  k5 _0 BBYTE        data = 0;
1 B! i9 u( u4 w4 [; U) [8 P
+ S" O9 Y7 A6 L! v  y: d        if( exsound_select & 0x10 ) {
! h9 C& s& n8 h, R$ n: p8 P                if( addr == 0x4800 ) {
) q/ H1 L/ R3 i8 a) Z/ n                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: ]4 t' s& o. Q! J/ F' F
                }" x( F9 w5 _5 I( F! [, z6 ]$ j4 {, T3 m
        }0 P1 Q' J+ w' V" Z9 R( N) n; `0 f* D
        if( exsound_select & 0x04 ) {9 b: N* s1 Z( C& v9 @  i8 T
                if( addr >= 0x4040 && addr < 0x4100 ) {
) @& g# n: ]0 `8 J7 B0 F/ W- t/ y( S                        data = fds.SyncRead( addr );  ~$ [  g. z! l# A" W+ t
                }4 _4 P6 b& s$ B5 `) h8 }* K7 X
        }) G, c% b" @0 A: U* Z  ]
        if( exsound_select & 0x08 ) {
- J8 l6 u: L2 r+ Q8 v                if( addr >= 0x5000 && addr <= 0x5015 ) {( B7 b7 @/ q% P$ d0 P
                        data = mmc5.SyncRead( addr );/ }5 d" b0 W! [
                }
* n- o1 `2 d. h& X- A% z8 W) p0 e        }
0 o) `5 I( C, M9 M0 g# ]" j6 k, \. I
        return        data;
- Y7 P% P/ e7 r6 ^1 i}
) f2 g1 Z' p  ]3 t% j$ k8 O! a
void        APU::ExWrite( WORD addr, BYTE data )
7 i# z3 ^  c3 B4 j. O{
5 K+ g0 w7 C2 ~7 Q9 G9 K) |$ f        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );2 {0 Z8 V* u0 c. {' i! ]# U

7 G6 Z  s4 Z2 M! \/ ~        if( exsound_select & 0x04 ) {& \7 k0 {( s" E: ~
                if( addr >= 0x4040 && addr < 0x4100 ) {
! U7 l- z7 v* u  ?7 q                        fds.SyncWrite( addr, data );  Z; |: `- l$ d6 M
                }
5 Y, Y$ m  C- C7 H! [/ t# x        }
- \. A4 k: s( X- x7 S6 A2 N# `' N
        if( exsound_select & 0x08 ) {
4 B# O$ S# V* @# a! M                if( addr >= 0x5000 && addr <= 0x5015 ) {
" r6 L$ R$ p0 H* U; _/ q$ S% N                        mmc5.SyncWrite( addr, data );
, X! W% B5 R5 D( J% {8 W9 J9 p* W% y                }
& K2 q" G7 [/ S9 j3 w/ ~        }- V; C0 M6 j* p* B* B
}
, M  w" H% d9 }& `0 \' l; K+ B# Z: k2 A% `" D
void        APU::Sync()2 j# v3 ?' Y5 L8 f+ K# s6 i
{
9 _0 Z* N2 @0 o; R' s& F}
) O2 s9 E6 s8 e6 A6 J( y4 f# y6 @; H& ^3 a
void        APU::SyncDPCM( INT cycles )
8 R7 V' |  R4 I2 A) K6 E{
% P4 k3 q4 x9 ^& _- }7 X5 R        internal.Sync( cycles );$ m. q( v6 z3 @6 B8 |

( R( \* E9 E# H/ {$ D        if( exsound_select & 0x04 ) {3 @) }. v8 t/ U2 ~2 R3 c* N/ a
                fds.Sync( cycles );8 ^4 E+ D9 O& Q* {/ j6 Z3 m: T
        }  u1 [# Q! H; f/ Y) j8 Y; q1 i% W; M
        if( exsound_select & 0x08 ) {
0 A4 D) V$ Z' d2 S) I                mmc5.Sync( cycles );3 S) K" d* l$ r1 g% ]
        }
) p7 t( U, r' C* t, B- ?* S9 q}+ J7 N. O: D+ ]/ ~/ Y

& q* Z; O3 s+ a/ \& Cvoid        APU::WriteProcess( WORD addr, BYTE data )0 c+ u5 S3 P( |5 P- `: X- u
{1 B/ Z6 R+ b7 S+ u
        // $4018偼VirtuaNES屌桳億乕僩
0 n  f2 u5 M. B        if( addr >= 0x4000 && addr <= 0x401F ) {
0 R  s& f" p6 K% Z* E                internal.Write( addr, data );9 ]0 y0 q1 l1 I. {- |4 x, l  U& E
        }4 t/ C3 m1 {8 {0 h8 r: g
}
6 e, @5 h( h6 Q- ]! W2 r, S  J/ b+ X- M
void        APU::WriteExProcess( WORD addr, BYTE data )
0 c" T# ^. @. l3 \, w: J- a. {, X{
, p6 [' o! B4 i  y        if( exsound_select & 0x01 ) {) f4 t; [/ X+ M* G
                vrc6.Write( addr, data );8 q* A9 n, o- Z( M- n5 x4 W
        }# v; a& |! n& m; A& l! G1 ]6 d
        if( exsound_select & 0x02 ) {, ?' \  a. I$ Z7 q; O
                vrc7.Write( addr, data );2 l- q0 h; ^: V2 z, i. z1 _3 D; C
        }- F2 x1 f1 c$ j/ k) a
        if( exsound_select & 0x04 ) {- W8 U# ^) j# r
                fds.Write( addr, data );
5 E4 i. ?, P/ \6 {% I6 P" e        }) c9 w  M5 z3 o! w- M
        if( exsound_select & 0x08 ) {
1 p% S1 Q" o/ T) `                mmc5.Write( addr, data );
( s6 j( ~+ C5 V3 u  |- ?        }
; `5 p3 I2 N( N        if( exsound_select & 0x10 ) {) }! K, _+ t9 v7 ?& n- t
                if( addr == 0x0000 ) {+ I+ D: r+ n3 t- C& N& g3 P9 s
                        BYTE        dummy = n106.Read( addr );2 z% Y1 s" `1 f# j: G9 `, _7 u
                } else {
, Y/ t1 \+ {# E+ t8 e. Q$ C( ]; L' J                        n106.Write( addr, data );9 F: b! [- w+ H( q" O! H9 l5 T
                }
9 }9 }6 I' y! U/ G! I        }8 Y+ l' ~& F, J- p$ W6 u; \
        if( exsound_select & 0x20 ) {6 F8 Q/ n, L( b. a, V  X" N
                fme7.Write( addr, data );
8 U9 K" j& n' g% ]        }
6 y# |% J, o2 ^" k% d; M}3 Z2 ]: U# d8 u. t
2 T5 y4 ]( [$ [2 q& P0 ~: P6 W0 a0 }  m
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
' v1 R2 y% H3 z! N# ?9 K+ `{) ]# a- S' s% p! v' g; u% Q2 {- B
INT        nBits = Config.sound.nBits;
0 C! C) h  |& l0 E/ P7 z4 E4 VDWORD        dwLength = dwSize / (nBits/8);! j  y5 R- L1 P" L* `+ ~
INT        output;" ~5 o  d3 p8 \
QUEUEDATA q;
. a& {9 @0 v, ^# q( M$ ~DWORD        writetime;
( V; z: N& P: M* \5 u7 a* W( h4 g( ?! l6 i4 E, H
LPSHORT        pSoundBuf = m_SoundBuffer;
/ E& H; R+ ~5 l- f) B- V$ ]INT        nCcount = 0;" P4 c7 a7 M& j5 h0 n
; _% w0 g/ W: g' D( n4 {
INT        nFilterType = Config.sound.nFilterType;/ ?  ]: Z  {* C. V

4 t. A9 g2 s- ~4 G        if( !Config.sound.bEnable ) {8 y8 J" p/ E1 x" K% E/ Y; E+ Z. m1 ]
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 v, s# T7 X" w, Q: F
                return;+ M+ M. `& r: v( E; B
        }
# s# o/ {* V0 R' E  g' t: S8 b* [4 u$ A% i
        // Volume setup
" u  l0 E( ?' l6 X0 J$ P4 a1 |6 `        //  0:Master* L: J. ^+ |# o8 [9 k7 ~2 x
        //  1:Rectangle 1" F5 G( s" g8 F( z9 w1 q2 I
        //  2:Rectangle 2
% k7 ]5 J& ~5 g1 @        //  3:Triangle2 }* x8 c6 C" ]0 Q
        //  4:Noise2 x+ {+ ]. e1 ?) ]
        //  5:DPCM
& Y& G1 P1 T  l( b0 R1 M7 l        //  6:VRC6" b6 F% t- f$ Q) k" Z+ S
        //  7:VRC7
! J8 F7 h$ l# D# x3 [0 \, H+ P" q, h        //  8:FDS
; Y3 |( T7 n5 K; Z        //  9:MMC51 g/ i% M0 I6 ~+ c, i
        // 10:N106. I; e3 D- r/ a8 C3 G
        // 11:FME7- }- X. v7 e4 [6 ]& p) A$ |9 z
        INT        vol[24];! {* S) v! ]8 R+ T
        BOOL*        bMute = m_bMute;
/ b6 z  h, ~5 n$ P  h1 p) w" c) f        SHORT*        nVolume = Config.sound.nVolume;
+ O2 {6 o1 V1 E9 i& {  g& w/ }' k" t3 A% l; w% Q% X" ~) x1 y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
1 H: ]: u5 Z6 r" ]. G; M7 M, S  D% d0 L0 ]' [5 S7 Z
        // Internal# h, l8 Q2 O0 k2 q0 [8 ?8 Q) c
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 `& i1 O6 A# f5 }# t        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( q& Y& v& U/ M
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
' h* k. C+ f& P, I5 c5 B' t' ?        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 T5 j. T/ s- Q1 {        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' b: p' N8 G6 P9 |0 j# [4 p
* L+ g# H- }8 l: c! q! P' K        // VRC63 K% V6 n8 I0 w/ y3 |) j6 r
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 k( @6 q! o: |% r9 Z. o        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* |2 }" e; \" z& t1 q: d2 A. b
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 }% L, X% x% A: k

9 g! a. [# y: O        // VRC7# P' X$ U7 m8 s1 e) F3 J
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;2 w+ [+ C' ?7 y' s/ C# I
  N. [& p& W- V9 m+ Q
        // FDS+ ?6 f2 I- E+ y# @  k7 h
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
( L8 g% O) b3 h+ L; F, m( [' |4 t3 c% X7 K; F# L( C+ t: z7 P0 A
        // MMC5
7 j* x! N' I; A        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' y5 q/ t/ Z3 }  x+ W
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 O( I. D7 O+ E* [, w2 x& \, {
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ z/ `/ \5 q  @- [
0 s2 [1 N/ a, w4 T. L        // N106- D6 a, }8 B2 L) o4 u" |7 Z
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 q2 k1 y7 v: x        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 j9 r" g3 [# u7 W9 O2 r
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 y; D: F. w7 ^7 c
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) D& j( k; \1 @/ Y+ s2 s
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 d* z  }& z" `+ e        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! u& u( i. K+ c1 V  C        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% O' W- M$ K8 D6 ^
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  o) }3 ^' V! V4 A* d
- ?$ U* `0 @& D# ~" X& M3 }        // FME7
1 x; P. `3 S. b' w$ c        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 s1 N6 d1 C, z) L9 ~4 X- H/ y        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# H: q& w7 I( D0 ]5 z/ A        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 W7 \! j) A, G6 y  E" y* R/ h( ?
+ c$ V$ O3 r; C  u
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 e0 R  e2 N- O+ _! f, A
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;' M( [# t0 S! w$ O0 B) r8 ^
8 C4 r: E; t* N7 i3 Z" \) B( I  Z; s
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟8 Y3 A" Q0 B( M; z; N. h" N
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {4 ~# u  g# R, H
                QueueFlush();
2 d' y9 C& O- J; A  x: T        }" U( v4 D- Z0 ~) V

+ @& ]9 c# x& Q        while( dwLength-- ) {$ {" P  d: f6 S% x/ J  i
                writetime = (DWORD)elapsed_time;
  n+ ~/ e# f# @1 f- W
' Z, q7 \  ~! |9 V5 ?! r                while( GetQueue( writetime, q ) ) {
+ @& P: x7 Q; f$ q0 X                        WriteProcess( q.addr, q.data );
0 p& y1 w5 l/ S1 l  ~1 @+ N$ G                }* \' ]8 X& Z- _2 B3 C% ~- _
+ W' L+ i2 N' f4 t- n
                while( GetExQueue( writetime, q ) ) {. [& S1 z% P. u" x0 N" ^4 o
                        WriteExProcess( q.addr, q.data );3 M/ J, D: Y- L4 m( S
                }( H6 x, n* F$ q7 J/ d+ d
. v2 }) x$ D, `
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7+ `. G- w; I3 v# i8 ~" {" ?* d3 x- c
                output = 0;! B8 v9 {7 M; k: l8 \, Q  L
                output += internal.Process( 0 )*vol[0];
3 f4 ]7 k) _0 X) V' L                output += internal.Process( 1 )*vol[1];" h& k7 h  `( h- X# m0 E, e
                output += internal.Process( 2 )*vol[2];
" L2 j; [$ ~8 g! Q) I$ c                output += internal.Process( 3 )*vol[3];
3 Y( P2 ~+ J. @. W8 D8 J# g6 T6 M* y                output += internal.Process( 4 )*vol[4];2 M5 n, k& @! \2 u4 A
, F4 n" g' f, f/ }5 Z
                if( exsound_select & 0x01 ) {2 L! k  g. l0 l9 O
                        output += vrc6.Process( 0 )*vol[5];+ c8 h- u/ N) B1 Z* N$ ?% |! y( s
                        output += vrc6.Process( 1 )*vol[6];
- |5 F' x* V) `8 e  F( m                        output += vrc6.Process( 2 )*vol[7];
, C( K* T4 {+ U# L                }1 `0 [; {7 A" j9 X& R
                if( exsound_select & 0x02 ) {
- ^  v* i5 C) l: t9 ?. p                        output += vrc7.Process( 0 )*vol[8];
2 ?% _) F! w  [                }2 a; _3 [: \. Q% Z9 V" K
                if( exsound_select & 0x04 ) {
& R* m& M7 A" A4 c8 O7 a+ u9 Q                        output += fds.Process( 0 )*vol[9];' n7 E( G* q2 U$ h7 {/ e" }
                }
7 f! E7 I& m& ~' ^' J1 s2 k0 @                if( exsound_select & 0x08 ) {$ X- B1 q2 |. b( o, J
                        output += mmc5.Process( 0 )*vol[10];
( s( ^, d* S4 E9 l, k) o                        output += mmc5.Process( 1 )*vol[11];
# f% S! D( Z9 A9 M' x" K                        output += mmc5.Process( 2 )*vol[12];
' G$ e7 W. z# O+ Q8 M                }
' N+ X  i; J3 ^$ D: B6 I* m                if( exsound_select & 0x10 ) {
/ D2 F8 H/ I" j0 _4 L% V) w                        output += n106.Process( 0 )*vol[13];* `' \" l" H9 F4 O9 v
                        output += n106.Process( 1 )*vol[14];
# m! ?; ^4 b6 U- Y                        output += n106.Process( 2 )*vol[15];
, P0 Q& L$ i& `- n1 g, W1 O5 w5 l                        output += n106.Process( 3 )*vol[16];$ v4 F/ `3 G) }7 x
                        output += n106.Process( 4 )*vol[17];
8 |  {% x/ J0 L! P                        output += n106.Process( 5 )*vol[18];; E' p) _' p  W% x+ O9 C3 U
                        output += n106.Process( 6 )*vol[19];
* L6 u6 ]) ?1 h, v' I( _( N                        output += n106.Process( 7 )*vol[20];
& m' `( [+ h) P2 a, m                }$ }4 a3 K5 y- ]; Z! L3 n* Z9 |  Y
                if( exsound_select & 0x20 ) {
8 C/ u2 T( z' Q) O# N                        fme7.Process( 3 );        // Envelope & Noise& q, d  @6 B2 M$ x( U
                        output += fme7.Process( 0 )*vol[21];: m! H! i% J3 Z; v& G2 R8 h
                        output += fme7.Process( 1 )*vol[22];
5 S6 t" G# r/ u6 N                        output += fme7.Process( 2 )*vol[23];
0 Q2 U. Z" m1 E, D  X' N                }1 \& m7 B- G5 i* z0 L

0 f: G& r' q3 z. c2 J                output >>= 8;
  x* k8 ^2 E% ^: ~/ g' S2 L" t' W, R, t% D7 h1 k6 H
                if( nFilterType == 1 ) {
1 }+ C7 R6 c9 X5 s2 u                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
# \7 P0 e5 @# `* i+ ?                        output = (lowpass_filter[0]+output)/2;. u( P% _( i" ]
                        lowpass_filter[0] = output;
' m% M# X8 M& I% h. p* Y                } else if( nFilterType == 2 ) {
- w( m) l; j# _                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 }$ W( G% A7 }. W3 o* w                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ H& _1 v% r9 F/ [                        lowpass_filter[1] = lowpass_filter[0];& h8 s& y5 S& A% `" `) E, p& R0 O
                        lowpass_filter[0] = output;: _% f1 [! X: [. n: q6 u
                } else if( nFilterType == 3 ) {
& i" P# d( \2 @) ~                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 Y/ t- p( [* S$ r                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 e: o& W/ C5 Z6 m2 }                        lowpass_filter[2] = lowpass_filter[1];; q. ]& p7 D* b6 a! {
                        lowpass_filter[1] = lowpass_filter[0];
; j5 {& |9 ?8 O/ Y% C9 }+ f1 I( y/ b                        lowpass_filter[0] = output;4 J* `# ~8 L4 u& M1 b
                } else if( nFilterType == 4 ) {
& k# R' m% Y5 c6 R/ |                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
0 F$ X; x1 Y9 C                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
% w, I- d$ C2 a/ R5 B, Y                        lowpass_filter[1] = lowpass_filter[0];: u6 Q' u1 K: a" x+ T# U. G
                        lowpass_filter[0] = output;
4 X% m5 L+ t/ y9 r8 C- ?/ V' E: M  f1 O                }
! G% I, a! a1 j7 c3 s
, m% {7 |- K9 `0 R) T1 x/ j#if        06 T' N0 b! H  w  T
                // DC惉暘偺僇僢僩9 H4 w# B! Z7 O+ f) r5 V, u; f
                {
& [* \" F% Y, E/ X8 Y9 F4 f                static double ave = 0.0, max=0.0, min=0.0;+ [: S( F9 i& Y& e9 p+ f+ L
                double delta;1 H$ G) [. B8 C; f5 }' }, h6 `0 ^
                delta = (max-min)/32768.0;
8 [9 E) Q1 `9 p% h, `. }$ q4 }                max -= delta;* @2 k$ _3 ?: h0 q
                min += delta;
. N2 H# I& X- J' B                if( output > max ) max = output;
1 Z4 Y9 z4 z- ]! j1 _                if( output < min ) min = output;7 ]8 I6 P+ s, T$ \' ?
                ave -= ave/1024.0;
! F( \! ?' E, M) t                ave += (max+min)/2048.0;# _5 D$ W# V$ q( }) n
                output -= (INT)ave;
' L0 X( g6 D3 S2 m                }
. o4 b3 ]/ \, I8 E+ `, y" T3 y+ F#endif
8 t) c0 ~# ~7 ]4 g; Z4 @/ h0 V, ]#if        1' [9 t5 c0 F# `, h5 w
                // DC惉暘偺僇僢僩(HPF TEST)9 L8 Y* f& i7 y
                {
) _/ D+ W& f! @9 e9 P- o. c  {$ E//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);+ o$ Q( q% V8 i6 ^
                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 L. O3 v' x8 S8 n! \' U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;7 E4 i; O* }1 q
                static        double        tmp = 0.0;' X0 y, B! |) Z+ h$ ~1 T6 C
                double        in, out;# M0 D* R% e4 z5 x  x& n: q

7 z+ W8 Y( A' U# W' g. [. G7 D                in = (double)output;6 [1 Q' T9 F. ]8 ^) \
                out = (in - tmp);
" ~8 r/ v( J2 |8 Y  I                tmp = tmp + cutoff * out;" M3 p& K( z, ^2 ?* [7 o

6 v' L+ w: G* C7 D/ I/ @' Y& B/ c9 N                output = (INT)out;5 V6 s+ N: d, u  m
                }
/ N% B& g& [4 p* p#endif
% P! m3 u/ B5 c7 \5 Q) @( m#if        0
: l' f3 q/ a! h/ b- c                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 O; [5 ^* d# B) L2 ^3 F2 i
                {  f! w! @: p* D6 j
                INT        diff = abs(output-last_data);
8 E% J: Q. Y! J5 `9 _- O; A                if( diff > 0x4000 ) {
* j, W, T3 I- }                        output /= 4;" o: @; L! L( x; {# g
                } else # m. G# p3 ~# m3 `5 R
                if( diff > 0x3000 ) {/ I/ R. P6 t" j) E6 k
                        output /= 3;+ r/ |) V  C! K) o
                } else) ^) H7 ]$ J! c2 x0 d
                if( diff > 0x2000 ) {
6 H) \5 r# i# X9 ]1 S7 h) f2 j5 s                        output /= 2;" f! n- }% ?0 E; t/ H( H6 _9 h
                }
# t" P! L$ A; _) d7 h                last_data = output;
; L# X3 p4 r5 N/ L                }5 e' ~8 L3 Z' B8 U
#endif: a. k% \" }! ?
                // Limit
  D( [$ L* m- n& P* h: L5 V. x* D- Y# t                if( output > 0x7FFF ) {
( `2 i5 {5 p0 F                        output = 0x7FFF;
/ r* S1 {% p4 H& a6 J2 B3 U                } else if( output < -0x8000 ) {
3 s* C2 _. H& x( K) J& R8 O, r- C                        output = -0x8000;& j3 |. {/ J/ s5 |7 T6 C, \
                }" m- e) t2 R! n; H9 I* p  p

( e; O! P5 t4 {                if( nBits != 8 ) {
9 G. R7 G( Y7 T2 M1 S/ h; P; G3 G                        *(SHORT*)lpBuffer = (SHORT)output;! c+ f9 W! {/ Z. |9 Y0 I
                        lpBuffer += sizeof(SHORT);
1 S$ O5 r! M# [1 e% t                } else {* b- {$ e0 }+ m" H  U2 ?% [
                        *lpBuffer++ = (output>>8)^0x80;' \% m/ n, G' \5 j- p' i" v2 ^
                }
, \; A# V  F8 k0 L- }) }& F, |9 T+ _+ r, j
                if( nCcount < 0x0100 ), O2 a: Z" f8 J
                        pSoundBuf[nCcount++] = (SHORT)output;
. e  z- R6 A- c7 L! R; z
( X3 u% L$ V4 a( p5 u//                elapsedtime += cycle_rate;
/ {1 M% J# R! M                elapsed_time += cycle_rate;
6 x! d) }6 P+ S$ y% M        }$ h8 a9 K. x7 r5 V# j

2 x" e4 M( ]/ Y9 m, L, F1 e#if        1# }" |; {8 G" |' ^+ k/ e7 c
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: x0 _5 D" G; [3 y9 d0 K7 c# k8 V, v* K
                elapsed_time = nes->cpu->GetTotalCycles();
" g, H6 N/ T& j' G* |8 q3 c        }% k* d4 j, M9 P) r1 x  f+ W- `3 S( G5 s
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {, R1 z- Z" \( M. c. U1 A
                elapsed_time = nes->cpu->GetTotalCycles();+ r3 h( H( v$ H( I
        }
3 T% o8 h- Z) z2 d#else
+ |0 k: N9 c0 c9 J( r9 c/ d, v        elapsed_time = nes->cpu->GetTotalCycles();. }' J1 K8 j$ ~
#endif2 R7 e3 e9 _. y" C! D4 N, {
}
: q: M: A' S# w' g- N1 s1 D, X) f3 m: p2 F) X) q+ ~$ V2 c
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ D. ]' N8 K( c- E& f9 rINT        APU::GetChannelFrequency( INT no )
& a' m5 d7 M8 ?, ], B% a+ s* z{# W3 D( J) H/ b' Y+ a4 Y
        if( !m_bMute[0] )+ r# x' G. o- t! J9 b
                return        0;
+ P- \/ Q, K8 U( Q! G, O2 K6 |; F8 l+ L8 Z; H
        // Internal
9 E/ C3 q# M. X# b  M; c. r        if( no < 5 ) {) `; O/ ~: [1 I! Q" ~9 t2 }$ v! |' J
                return        m_bMute[no+1]?internal.GetFreq( no ):0;. }$ N+ E" |+ Z4 c) \: n* J8 i
        }) i$ v0 Z6 i; s
        // VRC65 ]& o4 F! g' Q+ d# N# [$ j; k" e: ?
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {7 A: B% J. T- @7 u! e
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;& w9 U  p4 @7 X3 x$ z8 A! \' k+ `
        }% q9 e8 N$ h7 }, u( g
        // FDS
4 C$ S. M" O1 [+ y1 r        if( (exsound_select & 0x04) && no == 0x300 ) {" Q# J6 Q8 s7 }* S+ e7 ]" ]
                return        m_bMute[6]?fds.GetFreq( 0 ):0;+ S6 i; N; O0 |+ {
        }
/ p3 e  t" F; r" ~$ o- {! q! A4 N        // MMC5
& k/ D( b/ ]  ?# z) u; Z$ Y- M4 q% q        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) H* e0 R& `: K1 t- K+ _7 [0 H8 R
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;. [  }9 ?* o5 m
        }! \  I* u6 a7 J, ~8 w/ q+ t0 \) Y
        // N106
2 B% l; R% g8 _4 @        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
6 ?! p, e# ~- u2 J) ?. B, {                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;& z8 I/ `  |% L- A. }" B
        }
; q7 h$ D9 z- e) H        // FME7
8 Q2 o: Z1 I3 I  M, g1 w        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
5 ~4 l  b" Y$ U- W& o                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
" o9 j- ?, A& H6 [        }+ ?: X9 L, K; @" Y4 ?/ N; m
        // VRC7
- t: u8 K( w* `! u, H! |0 _2 S& g        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' M9 L8 X' o4 k0 H: F! B
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
6 m9 \+ I3 j: J' |# K) c        }5 l& C% U3 }4 B( d+ ?5 R
        return        0;
3 q1 T/ g5 L$ B& E& H' n}
( Z; A/ k7 f0 j% u0 G- ^- {8 s  G# @3 F+ `0 ^/ O
// State Save/Load
8 s$ G% m) K! V, T) x+ g- k% @void        APU::SaveState( LPBYTE p )1 m+ t& {0 |0 U+ w$ k1 D
{! ]- j1 t+ n. }: W  z
#ifdef        _DEBUG7 b/ w9 p8 @1 N4 P3 n6 e
LPBYTE        pold = p;
  z6 {1 V& ]! M/ B* x. d#endif* b* |9 S* N& A! h+ r

4 F) E2 }6 |  B        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
" d: G1 r; j9 ?( ~) t7 ~        QueueFlush();9 o7 T4 r, _4 I( r# Z. W

  Z* b; J: r" Y* @1 y# x0 S/ y$ s3 ?        internal.SaveState( p );- x5 j$ q2 {4 K' c2 ?
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& m  e; I! u1 N# W

  J# [/ q" ^; X  k: D; U7 k        // VRC6
# x6 I& o" h# [: d        if( exsound_select & 0x01 ) {4 R0 q3 k  d* R- a: Z; ^6 w
                vrc6.SaveState( p );
9 _1 s+ \* r3 v4 U8 \6 L' A                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ g4 `; D- i3 y* M( W" y
        }8 \# P3 q' J8 o- b; _2 }! e$ E
        // VRC7 (not support)# p% C2 d' N1 r$ B0 G
        if( exsound_select & 0x02 ) {
3 z' c: S0 i# i7 `' H                vrc7.SaveState( p );
9 ?4 N; }2 Z  E& P& a                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# Y& m6 N, P+ l& E# w        }& T+ i; ^9 q  I% T" Y( H
        // FDS; {$ L2 T+ \2 l+ m+ ]% N% V$ c" H
        if( exsound_select & 0x04 ) {
7 S- O9 B  S- r. l# a( R$ C  x                fds.SaveState( p );) }" A% F7 d: C+ e; x( @( V' Y0 Q
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: H# W4 L- w- S; {) c: Y1 @
        }9 f( S. c8 ]2 Y; f$ ^$ |+ z
        // MMC5- u, z9 v, M$ p
        if( exsound_select & 0x08 ) {
2 B" G/ n# }3 U* @                mmc5.SaveState( p );
) K4 l: M* O$ q) X1 B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- h( I2 G) i- L$ F8 C2 r* z0 k) b        }
. u9 k' `6 Z9 }/ `2 A! h. X* Q        // N1069 b+ Z$ W3 _4 z; z8 F7 M: P% ^
        if( exsound_select & 0x10 ) {! M* Q$ t0 H3 {  C) s* H
                n106.SaveState( p );! O$ ~- v4 v* K8 s
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ E/ `4 s) \* |0 H: C
        }7 Q- c( [; ]4 I. r
        // FME7# c0 S4 U# H! R
        if( exsound_select & 0x20 ) {2 A% W3 R- G4 E6 Q
                fme7.SaveState( p );; i$ t& b2 w* u# y; ?9 D  S
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! @7 h& u) E- R$ z8 R( W
        }+ k1 a2 M! J. Y- H' W/ r- d

4 D  k9 K  u$ ~7 Z; @3 m#ifdef        _DEBUG
2 d% W) w2 B2 s4 }2 uDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );% ^; p5 p  w$ K$ I8 b
#endif# B* @" i% p* V2 D
}) r: |% f/ y: c9 j
/ x1 [$ v+ r1 v+ g3 t( L0 a8 ]1 |
void        APU::LoadState( LPBYTE p ); b8 A2 `( L( j! ^/ Z
{
% i' y9 b4 p3 s  g% e        // 帪娫幉傪摨婜偝偣傞堊偵徚偡# Z$ H* m6 [4 V/ T* Z* f3 H$ G5 A
        QueueClear();
& |+ B  v1 b" r6 V. {& S% F" G( I* f+ L, y+ `
        internal.LoadState( p );
8 Z" u; P) P# |% [' U. O* S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
5 g( v9 ]" z& b
4 \  {8 m5 `) ^: Q  Z: z$ a        // VRC6! r' l' \$ x) K: w8 U# J
        if( exsound_select & 0x01 ) {
5 ~8 D4 |9 b5 _; Q                vrc6.LoadState( p );
; l, a; U: B+ Y                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! }! Q" u+ x# x6 c" {9 N        }
2 O$ m) A# m0 y/ R, S! ?        // VRC7 (not support)
, e' F; I* ]' a7 q        if( exsound_select & 0x02 ) {4 n5 Q7 b2 J6 B/ o) n, ?
                vrc7.LoadState( p );
! O  o$ @! R& M" J! c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 Y8 R# N7 l5 G        }6 }* f! R" L$ a; g
        // FDS
$ a7 Q* a6 F" W% S6 |        if( exsound_select & 0x04 ) {2 m8 T, D5 k: B) S) }0 b
                fds.LoadState( p );
/ D0 b: m. P5 F$ E1 f/ |                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 G- i. E* P" A3 M( G7 X7 W4 L
        }
0 G! q. ~- v) J! D. j        // MMC5
5 ?- N: O% t* m        if( exsound_select & 0x08 ) {
5 ?6 |+ R/ a" w8 z$ p3 w                mmc5.LoadState( p );# U. r7 i) w+ e- M
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# P* R7 k* y" V; t; w1 A$ P+ f2 e
        }
, g( X8 l2 n% @  p/ M        // N106% O+ I" f( k# H, e
        if( exsound_select & 0x10 ) {4 ]; c4 p/ Q, d* \- _
                n106.LoadState( p );
8 K! {" w; Y* Q# m7 W0 Y' A: o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# Z  O( t1 R4 y6 }" @        }
9 C3 |3 r; t4 O5 G* e5 ~        // FME7
9 b; ?* E" p" B        if( exsound_select & 0x20 ) {
( j0 S/ T& E% @                fme7.LoadState( p );2 R# V+ e: M. m3 v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 h* Z/ J. L1 P4 i6 \
        }
8 a5 f7 L( N- r8 f! W, U}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ) @- W# \" @3 B2 H( X
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. l8 b) w) O5 P( `感激不尽~~

4 ?& Y0 c$ ^& z) F/ ~恩 我對模擬器不是很有研究,
$ d1 H  w& A3 T8 f雖然要了解源碼內容,可能不是很困難,6 a$ A! N8 |- A" l( }5 O
不過還是要花時間,個人目前蠻忙碌的。9 I: C5 l8 T  [$ p9 m

, ~( h# h6 t# l$ A+ H給你一個朋友的MSN,你可以跟他討論看看,
$ z. G+ m5 u! ^他本身是程式設計師,也對FC模擬器很有興趣。( D" ^/ [% _% o" b/ D7 m7 O
" B! u% B3 _0 F' w3 O
MSN我就PM到你的信箱了。! U2 q3 v: Q* p* q

3 B9 H% G  W9 I: i5 I8 U希望你能有所得。

该用户从未签到

 楼主| 发表于 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 n8 c- S) z5 a7 u  k6 ?- J# ?呵…… 谢过团长大人~~

. |7 _8 X# ~. ]5 I8 T, x, L* O
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , Y6 P3 R* r% W4 x& D4 E, x' b8 _
团长的朋友都是神,那团长就是神的boss。
5 ^  w- W- {( v9 N; ]1 X3 c$ s; ?3 @/ c
哈 不敢當,我只是個平凡人,
* Z/ e. t4 D/ G6 `# ^+ u# z要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  I  {5 [# Y3 b/ t# l1 N
ZYH5 G8 c' B+ F7 C1 U
QQ:414734306% c9 U& Z- r# ]1 V
Mail:zyh-01@126.com
1 {/ X2 a1 G; k& A6 ^0 r7 X' l: b- k$ S
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 + r& }- @: ~0 S0 r! }) L* W0 c
再次对团长大人和悠悠哥的无私帮助表示感谢~~

6 x0 i: l7 _% M: P5 N3 R不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-21 20:18 , Processed in 1.070312 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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