EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
2 i. B: {! p0 }  N* D& {! kPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 ^7 g& Z0 Q- q# J$ O- Q( c( g; v楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& Z) {+ W- _$ [  C. p) b
这里有相应的模拟器源码,就当送给大侠了~~
/ E: g* b4 [+ _" Khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 @% k7 G8 B& c3 c
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% H9 t, ?5 B* ]9 a+ Y. V2 [
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& V8 g$ m2 z( I! C$ d  r9 _: \这里有相应的模拟器源码,就当送给大侠 ...
, q7 u; S2 B5 f- P3 `' _+ E' L
聲音部分(Audoi Process Unit = APU):
, R/ _& _' q' C  u.\NES\APU.cpp
$ w, R+ `/ W1 t. p. f.\NES\APU.h1 S1 ]6 c0 i! \4 V/ B9 Q1 L2 M/ l
& ~9 H  t. X0 r

! d1 D! G1 x5 F; u  g! m2 b影像處理部份(Picture Processing Unit = PPU):
& W7 M: d4 Z6 c# Y2 N' u4 P9 E; {! A.\NES\PPU.cpp% y# {! {8 a6 {! M3 d. ~
.\NES\PPU.h
8 e% F# \$ P3 Q1 n9 J' Z9 S  e* \( |" D. q
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
" O  U/ y5 ^6 p; t& ](由于很多专用术语和算法机理都不明白,所以看不大懂……)
$ J2 B" Z1 Y; E( ^3 I9 T$ }, C//////////////////////////////////////////////////////////////////////////
5 W( ]8 N! N' D  t+ b6 A- {; t//                                                                      //
! l) U- R7 K. A% ]& J: }//      NES APU core                                                    //( ^6 W, J$ k  _( B; K
//                                                           Norix      //& l: X1 }  P. c' L' S+ ?- M9 X# ?
//                                               written     2002/06/27 //3 x1 R& y  v2 y3 u5 }' E" x
//                                               last modify ----/--/-- //* p4 \. ]0 j6 z: o( \
//////////////////////////////////////////////////////////////////////////
6 y4 n3 T; S( }, f#include "DebugOut.h"3 W5 u! r2 M4 b
#include "App.h"5 W5 v1 o; J& G% v
#include "Config.h"- H( M7 v1 O& G% n" v" S
* g: ]; J* f- t% A
#include "nes.h"4 e# [" D* f) {3 U
#include "mmu.h"/ P+ ?4 W5 U( H7 w+ J& Q
#include "cpu.h"  I& M% ~6 ~/ R1 e) L" }1 s- i0 D; S
#include "ppu.h": {# [' I& h- x- J
#include "rom.h"  O2 d1 O. h  {. R& t% N$ R
#include "apu.h"& c0 T) v. R, D* A! ]& q3 B9 x

  V  b6 K" R' q- x// Volume adjust" X- ]+ C. {5 Y  F3 |5 R
// Internal sounds) f$ _, l! r1 B* q
#define        RECTANGLE_VOL        (0x0F0); ~0 s8 c3 f* y+ t3 E2 e7 Z
#define        TRIANGLE_VOL        (0x130)
0 i# e* A: d" ?$ h) `" O# \#define        NOISE_VOL        (0x0C0)3 i8 `: y: q6 Q$ _+ C! z( [, g8 F7 f
#define        DPCM_VOL        (0x0F0), ?5 j* u7 q7 H% m* X
// Extra sounds2 f$ [' S+ V. n$ `" s8 Y. u
#define        VRC6_VOL        (0x0F0)
- _7 O1 `* q+ b( {! j#define        VRC7_VOL        (0x130)
4 M2 |! K' b2 C9 p6 \0 F! Y7 J#define        FDS_VOL                (0x0F0)
7 W6 o6 f! I1 l# B% e#define        MMC5_VOL        (0x0F0)8 I6 V4 r7 M7 y  I" p- U
#define        N106_VOL        (0x088)1 U9 M' N& d: ?) G3 d
#define        FME7_VOL        (0x130)3 x# V: \% I/ b

9 N: v1 L' X/ g* Y6 OAPU::APU( NES* parent )
+ L9 \3 A* U. G{7 g* r& D5 n. t
        exsound_select = 0;7 H9 G  q0 Z3 L( Y

* m* c1 k& j; H" I" f/ Y        nes = parent;
& q* H& r# x& ~: K+ T- N        internal.SetParent( parent );: w% k2 \; ~! D, `0 V. J- I/ u- f7 S

8 V! y  o3 R5 d+ Y. X( E        last_data = last_diff = 0;/ T/ L9 S! \; {0 o' A: A

9 J$ y. Z8 ?4 f& h- `6 L) r        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: D, D7 T* m4 M

# h; `( k) e' L3 ~0 L' r2 @  c        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& Q2 o" ?. _' E        ZEROMEMORY( &queue, sizeof(queue) );, e, u) O; z& K3 m2 r- q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: `  l) {1 s. w2 K; B& P, @' D+ ~

3 G1 q3 U$ O/ `6 E1 }        for( INT i = 0; i < 16; i++ ) {  y$ c* \8 I: V) j/ Y8 f( X6 ]% V
                m_bMute = TRUE;" e: m; D& D2 ]# I& c
        }
; \8 b8 d; h% y" E6 }7 j- k}5 w7 O/ r5 u3 x: I, p
/ k& M  `8 J8 K0 ^3 z
APU::~APU()
7 h' B9 O2 {, V  ], T! W8 j4 B% _{* p+ m4 m' \0 s0 b- x
}
% a7 H& y5 L) O. l) L5 A9 H% c8 ^( g) U! r' n/ `6 m6 K- K
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
1 w9 R# ^2 C: ]$ n0 x3 h% x{' q9 d/ z) c1 m1 y4 x% ^
        queue.data[queue.wrptr].time = writetime;
( U- _7 A2 ?$ l6 H: i        queue.data[queue.wrptr].addr = addr;; J3 R& Y4 B2 v( k7 Q- B+ n$ \  e
        queue.data[queue.wrptr].data = data;% s9 d* C* D* k. Q' h9 {
        queue.wrptr++;, L6 ?5 X+ O8 O4 P
        queue.wrptr&=QUEUE_LENGTH-1;
* R2 z  F# C7 W* B        if( queue.wrptr == queue.rdptr ) {( d" N" n: B1 S4 l; Y: H2 ~
                DEBUGOUT( "queue overflow.\n" );7 @( J, U( I/ m/ t+ |' l/ f9 T8 A
        }$ ~8 x- p4 K6 Y0 b7 @/ X# }
}3 B6 r4 ?, ?6 O
# r3 g& T/ s! u! J6 k( J  u
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ); u% l: n, H- u6 u, u
{5 x/ N/ A$ c4 f
        if( queue.wrptr == queue.rdptr ) {
% V3 C0 z1 f8 x- \2 _                return        FALSE;
2 }: e6 g7 d) q& _4 ~9 ~        }! g7 o+ M/ s& d( P. h' N7 ]
        if( queue.data[queue.rdptr].time <= writetime ) {7 [" a3 V% H: D" V2 o5 S
                ret = queue.data[queue.rdptr];$ }) e' D  j3 n7 d, {
                queue.rdptr++;4 a0 z: J: w4 Y: |. A1 C
                queue.rdptr&=QUEUE_LENGTH-1;) X9 O0 Y* Y& _2 k& u! I! z
                return        TRUE;4 H0 j+ q8 b9 V  Z7 M" M
        }9 |; X, d, ]7 `) t5 y, ?
        return        FALSE;# K! R% f' D/ I; X. J. |# V. E" p
}' d) |8 n7 ]  J. ~
' s# m' p* K5 i7 t( @( F& t5 C& r
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )" p1 k  _1 ]% t/ U- S
{
& T3 s2 K7 f) U2 w5 ~) D        exqueue.data[exqueue.wrptr].time = writetime;
& r% [6 J7 ]' E$ K4 M        exqueue.data[exqueue.wrptr].addr = addr;
( l+ q+ s0 _: }        exqueue.data[exqueue.wrptr].data = data;, s% l2 V  z+ Z6 u8 t6 m9 \8 `. Z8 C- w
        exqueue.wrptr++;" a& q) w  ?! b* O0 b: W* h5 r
        exqueue.wrptr&=QUEUE_LENGTH-1;, q$ K) T( X7 j4 p3 N& {% W! C' L
        if( exqueue.wrptr == exqueue.rdptr ) {
  y) y. r1 W1 s4 e7 k. v2 O; F                DEBUGOUT( "exqueue overflow.\n" );7 O$ \3 r7 x4 @5 N! _$ H& o# D% g. I
        }" P# k, d/ {) Z% v0 F8 O( o
}
8 ^) q0 C1 m; {8 v, `7 t3 s: l: z0 v, ^0 [
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )# G3 u/ l1 ?. R5 R, s- w
{. d- [' x" T9 d* W( F
        if( exqueue.wrptr == exqueue.rdptr ) {# b! _: @% Y) c& L1 M
                return        FALSE;. o. W+ u. L) Z, b; T" l* i, k
        }
3 m0 U2 Q/ X# f3 U& h) e        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
6 m. ~' G+ x" B                ret = exqueue.data[exqueue.rdptr];
1 }1 o5 I1 \7 |1 v" K8 q                exqueue.rdptr++;
& ]4 G% G  R* J6 K5 s6 q                exqueue.rdptr&=QUEUE_LENGTH-1;
6 X6 ~2 F; G6 s+ Q+ F* x1 p                return        TRUE;  z! W! f, D- m  Y. \+ F& P
        }1 `9 ]. M; s2 |7 g3 z9 U
        return        FALSE;2 O1 ?- I$ |3 @
}$ \- R7 C0 N# m

6 h- v0 Q& L! D# Rvoid        APU::QueueClear()  v3 r/ [2 B. m4 J
{5 ?! o: ?! C, F+ ]# l$ X3 [0 P
        ZEROMEMORY( &queue, sizeof(queue) );& w( H- X  Q& I/ b! G1 B" m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! y( G$ [& Q( s) F
}
1 |+ e  G2 U* {/ \" \( c
$ J2 ~: J. ~' W- u" Zvoid        APU::QueueFlush()) V% `+ X( R+ ^8 a0 o
{
, D( ?0 y6 S6 D) t7 f        while( queue.wrptr != queue.rdptr ) {9 n1 r+ U3 r. Y
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );8 l1 j2 h# k" `3 T8 R
                queue.rdptr++;
" P1 ~( Y; J2 K! K                queue.rdptr&=QUEUE_LENGTH-1;
+ H9 s5 L) b* i- d, N) z  N: _( q        }8 S+ J+ t; W: n, m# Q( ?

9 G+ R  e$ F, B% L) v* O        while( exqueue.wrptr != exqueue.rdptr ) {2 U9 c/ q) ?8 R
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );* G  ^" z3 ~* w& V
                exqueue.rdptr++;) b& ]/ v2 K3 x: v7 f4 ^2 B
                exqueue.rdptr&=QUEUE_LENGTH-1;8 R4 q& i1 g/ G) r# A
        }# S& \. X1 b  i9 U4 a. |& y) E
}! r7 ~  \6 R) U  U

5 {; N3 t- o: b+ Q8 M# b2 U. Mvoid        APU::SoundSetup()1 R  h* p; A& T, L! m5 q; b! p
{
9 X+ x0 W! w& n1 r8 C        FLOAT        fClock = nes->nescfg->CpuClock;
( ^; @" @8 H/ S) l/ m$ N4 x        INT        nRate = (INT)Config.sound.nRate;
( J1 H( p3 ]( |  W: U        internal.Setup( fClock, nRate );
8 h5 Y+ i5 m$ j& a4 A        vrc6.Setup( fClock, nRate );
  E/ R) E3 r% ?6 u        vrc7.Setup( fClock, nRate );
. A: {( r- K' @# o. R9 u        mmc5.Setup( fClock, nRate );
$ G, K5 ~% o8 {- \0 G5 [        fds.Setup ( fClock, nRate );, x$ q- R* c6 }1 E8 ?
        n106.Setup( fClock, nRate );0 L' n* M4 R7 o# A% F9 g8 V
        fme7.Setup( fClock, nRate );
9 Y  m& H6 I) G4 s5 ^}
/ ^( E/ [$ G4 u' l9 a, \: t9 p# r4 E" f$ ]/ ?
void        APU::Reset()) W8 t3 O7 ]1 s
{
$ R9 |5 ]% W. g3 s6 a- l9 M# v        ZEROMEMORY( &queue, sizeof(queue) );( V9 ?/ g! l/ Z) X: m9 Q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# W) K. ~! _8 G* |6 z
7 Z5 J% X5 A  B        elapsed_time = 0;
; h: F# b4 K# D" N( G2 t  _, q% ^/ ]# U9 V! u3 J: h* O+ W
        FLOAT        fClock = nes->nescfg->CpuClock;8 [' k  T/ S$ J4 |2 K% B: _/ d
        INT        nRate = (INT)Config.sound.nRate;
# l. Q: k. _3 @" S$ k/ W        internal.Reset( fClock, nRate );- B0 U  e1 n7 v: N9 _; p- p" L
        vrc6.Reset( fClock, nRate );
) }* g! ]8 ~$ r        vrc7.Reset( fClock, nRate );, G" ^4 f4 M8 X- S* U- ?
        mmc5.Reset( fClock, nRate );9 x. z3 o! G4 G% V5 Y. R- I
        fds.Reset ( fClock, nRate );
8 A( p  k3 J- ~        n106.Reset( fClock, nRate );! ~! C% y! @1 x
        fme7.Reset( fClock, nRate );( W! @. g- g0 @3 h7 ?7 b" \
7 K& V2 j0 b3 D9 L: q
        SoundSetup();$ k" V2 Q7 u6 H9 U1 |; h5 ~, r
}. F$ K$ N4 S2 T

( r- m: S' N0 }. ^* m. \void        APU::SelectExSound( BYTE data )4 W* D8 {0 r) \# {0 [0 Y
{
: n4 N. n2 {  z- G& f        exsound_select = data;
  \/ U, O5 U3 N, k}" g% N# f9 R" E2 J4 J8 Y; i  b

, I# J: P. l- v$ b  v- RBYTE        APU::Read( WORD addr )  E. P! v2 _  }) D
{
. h2 z% o8 m0 y, h+ u: o! p* W        return        internal.SyncRead( addr );2 T. d6 q( Q/ I- V2 C9 q2 \" y
}, J8 @# L+ I/ t0 L( I& K7 X7 D! ]4 R

' p3 |- N- Q5 b7 E* W0 fvoid        APU::Write( WORD addr, BYTE data )
0 B6 u' b; B9 i' u9 _; F- i{
3 D4 A/ w1 G" c6 i, C0 ]        // $4018偼VirtuaNES屌桳億乕僩3 O" G( m6 A  j6 L! P
        if( addr >= 0x4000 && addr <= 0x401F ) {
" L- [! S9 N/ T- M! y                internal.SyncWrite( addr, data );8 A1 e( _+ c0 i1 O
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );) O) d6 y, p7 u* C' X3 C1 R& I
        }2 h# t% {5 S; ^. P; v! F
}" [" `" R  M* r$ B: ?

) m: `4 W& v7 {4 g7 b9 m3 CBYTE        APU::ExRead( WORD addr )# G2 n  G2 h! D% u$ x7 v; K
{6 z( k/ X! h8 ]  [
BYTE        data = 0;
  U" X, a" R- B3 @* V8 q
" x/ m5 O  l; k" R9 x5 C        if( exsound_select & 0x10 ) {/ _: n: `5 A, `
                if( addr == 0x4800 ) {2 \2 P# ~  g6 u* c0 w
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- h) l7 @( |; t, H
                }' g; j! |7 F( s& b( Z! e
        }! F* H0 Y3 a0 C0 _1 r
        if( exsound_select & 0x04 ) {& r, A8 ~  a- T% y  p
                if( addr >= 0x4040 && addr < 0x4100 ) {6 U# C# q4 ]3 Z9 }; [2 v% y1 v/ P
                        data = fds.SyncRead( addr );
( {- ?' Z4 X' s0 }6 F7 N' Q# V) e                }
3 h! B1 J* \- J/ }& w8 g2 ~        }
5 X  y+ `' T' t" Y( G8 w; `: S+ s        if( exsound_select & 0x08 ) {0 ^/ O, s7 Z' ~3 v& I5 C- h1 ?7 i
                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 W, h' N$ y8 |( f) T5 ]: `: F                        data = mmc5.SyncRead( addr );! X# n& g; K3 Z5 s1 \
                }% m8 p! [5 Y4 P$ W( O6 h, d
        }4 i% Z1 _$ D5 b4 g7 H( {! b

* N1 j5 i; m  P$ e6 n5 Z0 ]  [        return        data;# F1 Z5 k2 {1 R. J2 b
}7 E6 H8 i4 Y0 [# ?% }; j- ~

( ^( R2 @( T) Z( x- J2 H+ Z$ Svoid        APU::ExWrite( WORD addr, BYTE data )
' P8 N3 n3 {, W/ p{3 C. b  ^, J, a6 t
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# Z& z5 P2 S* K! `9 X1 A9 q% L4 @& M: K) i3 M* M
        if( exsound_select & 0x04 ) {
. G( R3 k, ?* {; f$ s( f: J- K8 Z                if( addr >= 0x4040 && addr < 0x4100 ) {, Z5 p0 J5 s: w, P1 c" \9 ^/ x
                        fds.SyncWrite( addr, data );3 D8 C5 ^1 E8 e
                }$ @7 D* L! m) L2 s0 ^$ Y
        }9 m' j0 m# ~' [) [: h& s

" p& g# Y% ^% u2 {* b1 b        if( exsound_select & 0x08 ) {/ P7 X. t; m3 O5 k3 J
                if( addr >= 0x5000 && addr <= 0x5015 ) {$ r+ I& T  B+ K
                        mmc5.SyncWrite( addr, data );2 B5 ~( D$ {# A
                }
" j6 A* ~8 L( c5 g, [2 l        }" Y! R, Y9 t, x2 F
}; ?( O9 F4 l9 W" `# K+ ?* `! l

# D6 h+ a( B6 J2 Q  ^+ gvoid        APU::Sync()
5 o3 D; b% |! @$ R, d. H! ~{! c9 E$ L7 F$ Q* v8 x7 G
}# P' x9 Q3 z1 q7 J- K, O% ]: @, N) i3 I! ]

, T) J# \4 m+ ?void        APU::SyncDPCM( INT cycles )
0 D1 F) d1 w0 c8 F8 q6 \4 @% w# u{
; v2 a1 ?  \, `        internal.Sync( cycles );
" ^- b0 p$ m" R# s4 p4 ~# u8 Y2 X
3 [. j$ L- [! @        if( exsound_select & 0x04 ) {- H: B. A0 s" u
                fds.Sync( cycles );
+ J+ [+ l' W7 l6 A) F  Z- J) Q        }2 ?: H: N2 Z$ i! [+ z. v
        if( exsound_select & 0x08 ) {, X5 I% E- Q- [& z% z) y& [3 h
                mmc5.Sync( cycles );- `4 P$ E- t) I8 v- P) v
        }5 C6 K( h6 i/ g1 y% N
}
& n! l) n% e- f$ U: x! w7 _5 d/ C2 h' @$ F6 a& V
void        APU::WriteProcess( WORD addr, BYTE data )" s" O+ _+ e4 a) U2 B) m
{* \7 Q6 |, e" F/ l- G
        // $4018偼VirtuaNES屌桳億乕僩
+ c- d7 `. `/ y& S# t        if( addr >= 0x4000 && addr <= 0x401F ) {
) I; q. l6 U* e5 {( F                internal.Write( addr, data );
, ~1 z9 z& z  a" }4 t        }8 ]4 {. z9 ?* W* I+ `- ~
}. l0 Z0 b6 k* Y4 \' o: f

7 Q( H* d. g, ]+ x9 F* Xvoid        APU::WriteExProcess( WORD addr, BYTE data )
/ q$ N' z! f0 F& I4 u, B{
1 b1 v! B/ b: \  [5 S' K        if( exsound_select & 0x01 ) {# E" h5 N- l  M1 M
                vrc6.Write( addr, data );* _7 @! K* p5 p& }, R8 X. b% b; O+ R1 Y
        }
1 J- q9 ~" N0 R7 M9 Q+ Q7 Z        if( exsound_select & 0x02 ) {' n9 h$ u* ^& Q- l& ^
                vrc7.Write( addr, data );
) @" x. |2 t% I6 A7 ^; M        }
, l" m0 c* w+ d. |        if( exsound_select & 0x04 ) {( S5 i8 n" z* C% l2 B3 o
                fds.Write( addr, data );
8 P& c5 z- q, i' v7 R/ z        }
$ R6 |4 _- Y8 |8 O        if( exsound_select & 0x08 ) {
8 R) R1 ?% M1 Y# a+ m                mmc5.Write( addr, data );
' }# o: f8 d4 a! u- U/ J        }
0 ~* c$ F) P# }) f6 [3 ~        if( exsound_select & 0x10 ) {+ f+ Q# g) h" t; m/ _
                if( addr == 0x0000 ) {% Y4 E# P9 u! e& x0 O7 h
                        BYTE        dummy = n106.Read( addr );
6 _1 C$ U0 W% u: m  C                } else {
! Z, r$ \+ u6 s- w2 _1 E1 H                        n106.Write( addr, data );
# ?' B2 ^* A, h' D  {2 Y' ^                }
. Z$ f) a, B4 O/ W- n! |        }
) v8 F" a) k/ R) A: t. o. E        if( exsound_select & 0x20 ) {
& a' g6 D: {$ k  I% S6 ]                fme7.Write( addr, data );3 Y4 m/ i' W9 O8 h
        }0 b9 F& M; R% f* V
}% d; K" u. E% K& e- J
5 h! V2 f- [* n2 C+ x4 d
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ x5 H. W1 Z8 P, |  }) F& M* \{  [4 S) s, N7 j3 ^5 q" Q
INT        nBits = Config.sound.nBits;
) m1 R4 Y! x4 z, ]" _2 g$ VDWORD        dwLength = dwSize / (nBits/8);
( X6 ~1 [: I! Z& SINT        output;
4 [! @& U) o4 e) z: Z1 c0 EQUEUEDATA q;
- ]' @5 ]8 N. v/ {( V/ LDWORD        writetime;, W  [5 ?' ^1 F- `+ W) i

/ V9 H* j: K9 u1 gLPSHORT        pSoundBuf = m_SoundBuffer;! [3 E* \7 i! B6 u
INT        nCcount = 0;9 I- W2 L3 C: l& M+ V) `

; z1 [7 |1 s' K" b, M6 eINT        nFilterType = Config.sound.nFilterType;
$ M( k5 R2 q4 x5 b2 `+ O: q" P9 y* x( p" f4 ~3 S" l
        if( !Config.sound.bEnable ) {* [0 d" |# w* L& U! P
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );' U- t! C6 s! Q5 L* a) }
                return;5 I8 L7 e" i2 W0 i7 y  D
        }
: n. [* I4 y" o$ r. }  q7 ~
0 s+ }: T  v: v        // Volume setup. M) M6 E& E  O* w! n0 ^
        //  0:Master
- Q, x' ~  ?3 W' E: ]# L        //  1:Rectangle 1
, ^% v- [& X2 B6 [8 v        //  2:Rectangle 2& H4 F' g+ H! A
        //  3:Triangle
* o+ k+ r, z4 ?% w5 m# Y        //  4:Noise. N/ D9 O  G3 J/ O
        //  5:DPCM+ [& X! Y$ d6 v/ _- F& ~
        //  6:VRC6
  Q! p- [0 J) H% T4 [# B        //  7:VRC7* C+ j8 i$ ~8 ~6 J
        //  8:FDS
' N8 Z# s( s* p2 x% H        //  9:MMC5
+ H1 o) k- L7 x        // 10:N1064 Y4 A1 {8 w! l5 S7 Y& r: `
        // 11:FME7
! o( k- m+ [; q$ h, ?# ~- Z        INT        vol[24];
- V* J0 W) d" E        BOOL*        bMute = m_bMute;% l* M. Q, e" A1 S$ k
        SHORT*        nVolume = Config.sound.nVolume;
3 F8 _/ p8 K' @1 @1 }( ?; z4 w
3 {2 Q1 Q/ @/ g. W. n9 K        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
6 l9 }+ g9 `3 O6 e3 r, W9 X3 B1 L; P' g7 w& \6 a5 I9 U
        // Internal
8 J  U$ n2 F3 _7 g8 z        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
6 [9 y, P6 S3 ?0 k; C        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;" g3 y; w0 `* V# f0 J1 l* x& ?
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;% y: n' y1 V8 W# I+ a6 H9 v
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: h1 N9 X* x% K+ @        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 m0 F' l% S/ q: p, _. \
. S3 c3 F( W- [: E: G
        // VRC6
! A1 ^6 \: z+ D! J. ?        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* \$ [' q& G; a! A$ m
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* N! P' V# a( y  u        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 H2 b0 X5 @8 O

& i* |1 a( h9 r. o" G        // VRC7+ U! j2 R) a- I9 ^( {
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;& d4 T0 O( a7 x% y3 e9 L  ?$ B: A
4 P& a+ u# R- \6 Q
        // FDS; ^$ ]  C' R! R( |/ q' N! X' J
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
8 `, U, s$ R7 H# o9 w$ u+ m
( q& o, F, l' Y5 x        // MMC50 o1 s0 m: D; o$ h, x% H
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& o0 O/ w( I8 E) x        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: Y) w* ~' S; Y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) y7 N' [& x9 k7 i* b2 D+ N
. N3 E8 J$ _" [5 G
        // N106
! d7 t" w* c5 F7 c6 Y        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; {' i' U& d) u4 y        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 g2 I7 w4 g2 i; ^, Z0 G0 m3 U
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 y' t8 [& k/ |6 b$ P, r9 q        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 a7 P4 I5 k" K0 j4 _% [        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 H6 ^& K" {9 n        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: b' v6 K, D/ h( p- b1 b        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 t2 ]0 A2 L1 E. m# ~/ M/ y( I& H        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ Y, h: I+ U, \" T8 h
( c$ u9 S2 e$ o# B
        // FME7
4 J% b/ d* y2 c# C, S% ~        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* W& O$ ]7 z3 k( H' h
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; ^! G0 p5 Q: s' ~0 |
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" O3 R; w; f$ ^4 K  @& a. J; R8 f

. H. z+ [/ l/ i& l; x6 L$ W//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 n& P8 U- E2 J% D, B% H        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
! ~* ~+ j' A' i9 K: O+ C8 P7 p1 y1 i( H) t! V( _0 a. G# v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
  s+ [6 ]: l4 c1 y& I! c9 L( D8 u        if( elapsed_time > nes->cpu->GetTotalCycles() ) {3 D. ]. a2 r% |9 H! U6 N" h; D( j
                QueueFlush();) F3 i0 ^5 g9 g8 g* F  _
        }
/ H3 U& b4 F: m+ _& s4 \; n4 t
0 z$ e1 M! D+ \) f2 F        while( dwLength-- ) {1 x: S: {6 E; n
                writetime = (DWORD)elapsed_time;
- d" F) f: k1 Y( \
& X9 R, q' |7 \; Q: b  U                while( GetQueue( writetime, q ) ) {- L$ b3 B5 G0 Q' ^
                        WriteProcess( q.addr, q.data );$ n; b+ v  G. A4 I& C# `
                }
  Q  G" |& j6 |% o2 a$ |- m: ~
% k! q+ R  {; b7 M3 m8 R5 w+ B8 O0 m                while( GetExQueue( writetime, q ) ) {' H4 P, {1 S' E6 r( [
                        WriteExProcess( q.addr, q.data );
, c! u8 ~7 Q0 \; o" m. ^! E& k% L                }7 s' N/ G+ \) \$ L( {+ T) Y% w1 v

' A% S3 Q' B  t/ s3 c                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 r- u# E  X- _, f. i' `
                output = 0;$ u: b$ _% p8 k7 o) X/ ^
                output += internal.Process( 0 )*vol[0];  F! I( p  N5 ^& n
                output += internal.Process( 1 )*vol[1];' H1 V1 D; u' G% {- l
                output += internal.Process( 2 )*vol[2];. i$ v+ ?2 E& @- }; F' r* M
                output += internal.Process( 3 )*vol[3];7 j! X& z: m/ ]9 S+ l
                output += internal.Process( 4 )*vol[4];: |9 v( y! N3 ?/ L2 ?) i0 \
2 F/ A" L; T0 D5 L- \# y
                if( exsound_select & 0x01 ) {
. _) Z. G4 `4 o2 C                        output += vrc6.Process( 0 )*vol[5];
1 d6 ?6 s: F3 W+ Y! |6 W9 u                        output += vrc6.Process( 1 )*vol[6];' h" H% W4 m1 @
                        output += vrc6.Process( 2 )*vol[7];+ N$ X5 t8 J% ~, x& l
                }
/ l) F) v. h/ @+ r1 L. z2 y                if( exsound_select & 0x02 ) {
! d6 x9 P# D5 R" O                        output += vrc7.Process( 0 )*vol[8];2 i2 g/ ]) V3 O% \7 U6 V& u6 u
                }
9 Y4 S% H$ \/ S6 }) f* ^' _                if( exsound_select & 0x04 ) {
8 }- D2 I9 f2 z  |                        output += fds.Process( 0 )*vol[9];$ S& e* D6 [! S  J7 i* u2 {2 G. ]9 I
                }
* z1 k- a9 K2 |/ M. H                if( exsound_select & 0x08 ) {
. a* ~+ R* n+ q+ q                        output += mmc5.Process( 0 )*vol[10];% V4 _, u# z  Y3 c! u0 b
                        output += mmc5.Process( 1 )*vol[11];: A6 t: q. Y, X8 A( ^+ ?: ]" v7 p
                        output += mmc5.Process( 2 )*vol[12];. g4 l: l# `7 `7 x8 F
                }
1 \* o. c( h/ U+ u3 _% {: }9 a                if( exsound_select & 0x10 ) {
, u2 x# f/ E8 u& r7 ]' _                        output += n106.Process( 0 )*vol[13];
& N2 q3 h7 m9 d2 I* ?" _                        output += n106.Process( 1 )*vol[14];* V0 A5 x9 g( s. z# q7 A+ r
                        output += n106.Process( 2 )*vol[15];6 I6 b2 Q5 Z1 v, ~" Y* e4 O7 a
                        output += n106.Process( 3 )*vol[16];
8 K! e) o9 l+ u0 F9 v                        output += n106.Process( 4 )*vol[17];
. \6 f" J9 H5 I) ^& G) ?5 e                        output += n106.Process( 5 )*vol[18];0 p4 q! I; S! D/ b
                        output += n106.Process( 6 )*vol[19];
- L/ d5 ?* {- b: ?( Q. l9 z: L                        output += n106.Process( 7 )*vol[20];
4 p; Y$ Y1 p4 _                }
. O! F3 N: g3 @% W" k( @                if( exsound_select & 0x20 ) {. L/ N& a7 j: u) p' ~! W
                        fme7.Process( 3 );        // Envelope & Noise
2 }) S0 j9 f' [: N                        output += fme7.Process( 0 )*vol[21];
6 g1 f2 M# j/ z2 h5 q+ S/ w  b$ X) a                        output += fme7.Process( 1 )*vol[22];' j& u& Y% q3 x; D) |
                        output += fme7.Process( 2 )*vol[23];
; n+ J2 S4 m/ X2 s6 P, ?4 z                }, V9 ]# k, @  o0 t. b
0 j' i3 l" x7 H$ m) h0 w8 F
                output >>= 8;: q6 O. I# I* g: ]

/ ?4 g, M4 P7 u" p3 B                if( nFilterType == 1 ) {1 D7 c# a+ B, j0 S2 |
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)( Y2 G. f& q% y1 ~
                        output = (lowpass_filter[0]+output)/2;
3 B0 N4 X' P! O; G1 o                        lowpass_filter[0] = output;
* _7 T4 `) u& h: V0 d                } else if( nFilterType == 2 ) {
+ D' S9 M2 G- s% Z: E# K0 r8 L                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- V0 p2 }- |2 z4 z0 |0 u8 K
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;& {" i" n$ Q& _2 ?8 ?% X1 H4 B
                        lowpass_filter[1] = lowpass_filter[0];% N1 a' Z4 |+ R3 {
                        lowpass_filter[0] = output;
2 r/ E  ^& a( d- B                } else if( nFilterType == 3 ) {2 f6 L; L7 Z! @* t5 J
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
( ^# M3 g7 }& R3 a6 G* e/ y/ l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;( a% F1 w0 C2 z3 Z6 G! }
                        lowpass_filter[2] = lowpass_filter[1];
; m8 q, D3 q1 D  k/ ?) G( Q# ]# b8 }5 {                        lowpass_filter[1] = lowpass_filter[0];
9 y$ A0 h% ^) f5 B% k                        lowpass_filter[0] = output;- Q8 r' k( i1 V) R; L& l
                } else if( nFilterType == 4 ) {
3 ^' Q8 {+ g; s4 Q, }                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* T7 t, ~3 u. c3 X) }                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;& I7 h; `0 ]  @( l# {
                        lowpass_filter[1] = lowpass_filter[0];* l2 q* ~, x9 Q5 p" i( L) X' x
                        lowpass_filter[0] = output;7 L! `$ _! J: d5 c2 o
                }" a9 y- T6 N" v! B; n$ I2 E7 m

" S, `5 _% P. m- m+ y% h& t  e#if        08 j- Z* ~: q% x- m5 g
                // DC惉暘偺僇僢僩' w9 u1 v' P( t3 e0 ^' j4 V/ v
                {3 _. C$ u1 ?  I" x" ?6 x
                static double ave = 0.0, max=0.0, min=0.0;
0 m! K' q& f; K! I+ Z( M8 H% W                double delta;
1 o- j4 h* i+ d9 g) x# P                delta = (max-min)/32768.0;
7 p: s& ?, S, U9 ]) y                max -= delta;; B5 @" `5 |; B" j* z' R7 _1 J+ I
                min += delta;
$ \5 Q+ P$ |1 u/ @) m! r                if( output > max ) max = output;
4 Y4 j  {" F+ r+ d% t                if( output < min ) min = output;9 _5 w8 A( t7 O% h% z- ]
                ave -= ave/1024.0;
$ L, c9 [; ?. _1 D" U                ave += (max+min)/2048.0;
6 K7 ]" |; o0 J" g                output -= (INT)ave;( T( b0 b+ r6 V8 a; l
                }9 @# Z7 _# c: z2 y% G. ^
#endif
" e$ Q" D9 ]1 d  J#if        1
3 ?: _2 K* d# Q                // DC惉暘偺僇僢僩(HPF TEST)
) h) v: q1 O1 s0 l; @3 F$ [                {
; {  \$ q# \7 ]0 H% ~//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. _$ o3 }$ }/ x$ b8 O5 k9 \0 q- W
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) j# v7 m9 m8 n& n3 z                double        cutoff = cutofftemp/(double)Config.sound.nRate;
; u- ^' h7 @. |4 {                static        double        tmp = 0.0;  \  g/ D+ s( Q8 |( X5 K) h
                double        in, out;
, }7 U$ m5 B5 z; g, C2 J! f, _, W- ~+ e& n
                in = (double)output;3 j; k+ G: b% S, P2 R
                out = (in - tmp);
6 j% Q( n6 u1 v" Y( q, [                tmp = tmp + cutoff * out;
  O: o3 f% x. ~) S; I$ C+ S3 t: N' V  L6 r$ b0 r1 j# n; i
                output = (INT)out;
& {7 b( [' ~- m7 d+ G) V3 P                }, R5 v4 C% X" z4 G9 ]8 N( ?$ P; }, c
#endif+ n6 F! V4 I( p! w# s
#if        08 J) h9 G  o! X( l3 q! ?2 W
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)8 s8 ~0 N, E7 j) }  E8 F2 r
                {
4 ?/ O$ j' @1 [1 j                INT        diff = abs(output-last_data);
+ D4 `" T: C6 T8 O' `                if( diff > 0x4000 ) {' \5 d" @. h5 E! C8 j' o' e% S
                        output /= 4;
; X8 d  o0 O5 [5 I( n" A                } else 7 K: U1 a' w6 ^
                if( diff > 0x3000 ) {% |* z$ g5 |. x% z! K) D/ g: w. q4 Y
                        output /= 3;
$ ~/ J: ^9 N1 t9 s                } else
" r4 y' \; b$ k" Q1 N                if( diff > 0x2000 ) {
$ O, `; g- K# u, d+ P  g! {" V- R                        output /= 2;
' a: q+ M+ q' |! y8 Q                }+ z2 ^3 B6 I1 r/ l9 t) Q* n' M
                last_data = output;
# K9 X- r& O) s! F, t                }$ `( ~7 z! R4 Q/ c4 M9 T) p. p
#endif
* {3 L4 g2 {  u                // Limit
! G# |$ @4 n: x6 ~/ T                if( output > 0x7FFF ) {8 X8 k# @" E5 l5 Q# y' ]) t
                        output = 0x7FFF;
1 q+ q) W7 }" l+ e                } else if( output < -0x8000 ) {
  j( s) p) R7 L7 l4 U, S9 p8 @                        output = -0x8000;
+ q' M2 i( g5 I; H* I6 A# {$ d                }
/ d% F2 b( L( t# Z4 A: |
( ?8 J0 ]* b; Y$ m, P3 x                if( nBits != 8 ) {
4 o4 |3 _  U- m" v) m/ F                        *(SHORT*)lpBuffer = (SHORT)output;
3 g( \- p8 `' T1 b$ J' ^                        lpBuffer += sizeof(SHORT);4 J) [6 p# c7 Z
                } else {- e- }0 z( v' ]
                        *lpBuffer++ = (output>>8)^0x80;
6 \# m% I8 ~4 z5 G6 T% f& d                }
4 K# x/ ?+ C) a3 r
( h9 O$ p  Z' d  f, w+ ^                if( nCcount < 0x0100 )! c1 _! @, i4 C- f% g' `3 z$ f
                        pSoundBuf[nCcount++] = (SHORT)output;' C% h4 ]) m) s1 S5 G/ j0 B/ V6 J
/ F6 h* ?- c( [0 V6 K5 ~. u$ @
//                elapsedtime += cycle_rate;# Y6 t0 B7 r* B6 v3 @
                elapsed_time += cycle_rate;6 V( v/ R8 G% Y: B1 N
        }4 ~/ W: }  m) Q! m, T; a
) e( I: p9 i' j# i
#if        1# g2 {0 ^$ b4 P* \# D
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ i) `' o; W: r/ m* d                elapsed_time = nes->cpu->GetTotalCycles();
& W& Q8 \! V) g9 n        }; |; ]. q6 C; U
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {0 s7 N+ @# V# Q
                elapsed_time = nes->cpu->GetTotalCycles();
! t0 h5 y0 @# d5 q" S% B9 Y& f: Z        }8 \9 d" U  A7 R; o  N: u9 \. H* K
#else4 A) e0 \3 A0 w  H) a0 U5 X3 V
        elapsed_time = nes->cpu->GetTotalCycles();& j1 o5 {* s" q/ [
#endif
* r* Z* C3 B% z}& H/ |& L# R9 K& w% K
( G5 Q# w2 r- j0 I, i" n1 q! k& h
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
8 N1 v. _7 s+ z. L; W- _INT        APU::GetChannelFrequency( INT no )/ S  j5 d7 b9 K& Y, O* K' {
{
. N* I/ j. {' h        if( !m_bMute[0] )
- G! L" F4 ^6 r% [9 r; l& x                return        0;6 q% Y5 n+ ?' U% o: U- v1 ]

: X- N" o6 _7 @1 c" I! m        // Internal
# G6 R9 `3 T* ?7 s6 u, w% c- K6 `        if( no < 5 ) {; |  L8 s5 |  D1 c  [2 M
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
& d, c; l! @8 w" |- S        }
4 @; V! W# [4 H6 @        // VRC6- ~9 }2 \; q8 m: P
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {7 r( B0 b; N$ q8 V
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 H* X- L% z; a) N7 {* r2 @( ?" v
        }* ^+ ~; `3 o! V; l
        // FDS
, N3 s2 H6 m+ b& `/ |# q6 n1 z& j        if( (exsound_select & 0x04) && no == 0x300 ) {; l0 }. |8 _) _+ a/ U  B- Y& e! F
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# ^, G  U3 r5 a9 w6 v
        }
# V) p  J# O8 t; A        // MMC51 N. D0 _* K" X: _* D
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
' ^$ A+ k& b3 c+ l                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
5 v4 L& h2 `5 L5 A( q        }0 N3 l! [4 [8 D( C1 j! [9 }
        // N106+ j8 ^) p6 m, t( H+ [) z
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {/ ^5 M8 ?. N; }8 u& p
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 F9 v  i3 E4 p        }
0 S& I0 m2 y! ~: U. J9 |        // FME71 P) t  \: B% w% z
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
1 Z  Z, E! V+ \. d7 l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' H' h, x3 b, v% A- h        }
7 c* ?. R7 z: ?        // VRC7
/ V$ o  k3 H2 A' X8 u0 c        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {. o7 `0 e$ ?! [; X% @  H$ F
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
# S8 F8 X  @" A6 Q        }. q( I' ^% g" a
        return        0;
4 G# D& T. F9 q# P% Q2 k7 v) \7 n/ a}5 B5 D! ], r+ a# w; V; Z

9 u9 k5 I- A$ m% ~& k) _( T// State Save/Load) a3 B$ k  T+ f1 u5 L) ~! F  r
void        APU::SaveState( LPBYTE p )
! j) `' I: e4 K{6 E9 h4 l/ o# k8 C& Q% l
#ifdef        _DEBUG
$ |$ g7 s1 x$ h6 ULPBYTE        pold = p;. a4 _" D6 O, y) k1 c* G
#endif
( Q) i( L4 u4 c! h. A+ @5 W0 m  N$ w  O
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- w! V8 \0 k- o        QueueFlush();
- i. z5 k- U$ E! |8 K/ S
* F5 {( n0 y  X( g        internal.SaveState( p );
% D3 [0 T8 E6 x  p3 e9 P- v6 \        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) W$ q* O& Y( Z- H4 |! W  E' r( h4 P1 a+ o
        // VRC6
# b7 S# r2 |7 t6 x$ I/ _        if( exsound_select & 0x01 ) {0 }) q6 N/ ]% A& [9 R7 d6 E
                vrc6.SaveState( p );$ @; n, b0 |5 U: H( E
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# ]7 H+ x$ ?7 x
        }
0 ~) ~- `  B4 y7 e: ^        // VRC7 (not support)
/ y0 [" k% ^! l$ O  `. _- j) }3 I        if( exsound_select & 0x02 ) {, f0 `4 U# `+ c
                vrc7.SaveState( p );
; X8 W1 f8 \. q3 r( o# x                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 O0 |  C3 r0 s  w2 ^        }$ x9 C3 ]2 M$ k- I
        // FDS
, |& M$ D  w$ R# Q        if( exsound_select & 0x04 ) {& u- k2 b1 @7 g: \3 R
                fds.SaveState( p );
6 u* B/ p6 i+ O/ [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 Z1 M4 q; ?8 p+ h. l: C+ z        }
. Y; K. c) q& B2 f; l        // MMC5
9 u  {( d8 |+ r4 n7 m( g7 e        if( exsound_select & 0x08 ) {
5 a5 c6 l& `6 d) }& G                mmc5.SaveState( p );, I' o& M& d! O% V" R% V3 ^5 ^- [
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- m" O) `4 |' ?        }
* h3 x& E! `% z5 j) W        // N106& R6 T! r6 F0 h6 C, l
        if( exsound_select & 0x10 ) {
  q% v2 J- u( Q                n106.SaveState( p );5 v- q8 s0 \6 f) b0 M0 C
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* T; K3 h- ?- _' C  G
        }" y$ D8 X9 f* q1 @2 o2 @
        // FME7: T" `' Y# ?- y& l0 u
        if( exsound_select & 0x20 ) {
0 v) T" U' o0 F$ _- N                fme7.SaveState( p );# S$ G1 v( Y& V2 _9 G9 G
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- ^& M7 _* i/ N2 P        }  q: p3 g! `7 {& }5 n6 T# O/ i
" J$ D2 Z, r& u
#ifdef        _DEBUG
9 z, p, i! I( T. i% MDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" H$ B; d9 A: A+ Z& S3 J#endif! i4 p/ x7 n, P1 f# `
}
0 X1 L! M/ O, q/ \, V. R5 W/ Q- y& e  Z* v/ ?3 V! k
void        APU::LoadState( LPBYTE p )" X# r) s& j% @9 J8 E7 Y6 e% Y
{
. s2 ]5 s8 u0 p2 v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 T. ~8 F6 ?. _* Z! Y- u0 U        QueueClear();
8 M3 _  p( |  c2 ^* V. O+ c
8 n* O7 k' p5 F        internal.LoadState( p );. i8 v, y" c$ B2 @# p- L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 c9 \) x5 w  P; r4 \1 Z

! {3 \( f6 h) c! }; ]) }        // VRC6
0 k- `* a- Y" H+ z0 N& |. @$ G/ I/ f" _        if( exsound_select & 0x01 ) {" X* i+ }4 Q1 ^
                vrc6.LoadState( p );, B5 M3 z! W1 R) w& V
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; a  w; k' }6 F# k& [, P
        }
6 W0 W+ Y5 f- }9 R) \8 \! O# @        // VRC7 (not support)
  d. p, |! F  u$ i! s        if( exsound_select & 0x02 ) {8 G+ D: @2 I; f8 W; q5 i3 [
                vrc7.LoadState( p );  e% {! f  q$ i# Q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' z' ?0 U# A, ?9 H6 P
        }
0 }  N- T) A% T$ t% k4 B        // FDS1 d1 u  J0 e$ E' C2 V5 u$ {6 j
        if( exsound_select & 0x04 ) {
& ~7 s( s4 G+ |. N9 P                fds.LoadState( p );+ i  P4 S6 A, T1 H$ L. [4 R! u: r* c
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 t- Q. Q; |7 ^0 E% Y3 U4 E        }
$ Z! F/ y$ f" h3 z; p& E( ^" |1 m        // MMC50 |! D( a$ ^2 Q. n
        if( exsound_select & 0x08 ) {
& G7 t/ b- p! q3 x8 b                mmc5.LoadState( p );
5 ^  F9 D% O0 T0 _/ x                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 A0 V. f8 W  M8 a, J& q7 l
        }  L, A) o4 J; v4 `1 o4 P4 a5 Y
        // N106
& T8 p7 U7 {9 p6 V* t6 O        if( exsound_select & 0x10 ) {3 }4 T$ V6 l2 i; B: ?0 E( K
                n106.LoadState( p );. D8 q4 n  O/ S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: i& E9 v/ ]1 c* L9 c1 i' G" B  L
        }- J1 ~# H. x+ x$ [7 d8 B  |
        // FME7
; W6 L7 R5 T% w        if( exsound_select & 0x20 ) {
# e# M" D8 [" v4 b( M. x. H                fme7.LoadState( p );
; D4 O  [" |2 ~: A$ Y' a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 |* v; q! ]/ h' S, N$ J/ Q8 g        }
: j4 ~% m6 I# f3 D$ Z$ V- l}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ! t/ l; U; u. j
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 k  R8 [( h" C( R/ ^; q- a感激不尽~~

' B# t' b, C$ {/ M* S# `7 T恩 我對模擬器不是很有研究,
8 L+ R. }# x/ |6 E雖然要了解源碼內容,可能不是很困難,
: Q5 |8 y2 |, q不過還是要花時間,個人目前蠻忙碌的。
6 B3 H; o; V  R# ]+ e, p
+ ]% S4 a4 G& i( ^給你一個朋友的MSN,你可以跟他討論看看,6 E3 F5 v, B6 K
他本身是程式設計師,也對FC模擬器很有興趣。
( ^0 l5 f) V, @( y( x9 j3 A+ Y- h8 O2 Q
MSN我就PM到你的信箱了。/ o+ |! C: K5 o& D% s
3 O6 ^5 `: R% O( 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 发表
4 _) s! |+ s" F" a呵…… 谢过团长大人~~
6 z6 ^7 J% b9 k$ u$ u2 p+ g) [
* v- G3 K1 e% c
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 Q$ U9 h, F; h( i  @2 H0 n
团长的朋友都是神,那团长就是神的boss。
: c4 n# t. i2 l+ s6 E
哈 不敢當,我只是個平凡人,
5 L$ O$ C2 Q; D3 p要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# v6 v* J+ ~$ ~1 l0 {2 q
ZYH8 k) q  O! l: C1 `. {" C
QQ:414734306
$ q6 d: J$ d) A& t* V) PMail:zyh-01@126.com+ i; h$ ?, y, I: i
1 D7 v7 S0 ^" \4 {& `/ F% S. E' C9 @
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 i4 T8 X6 V  W1 N$ H
再次对团长大人和悠悠哥的无私帮助表示感谢~~

* n3 S  U# v1 i, H/ w不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-1 08:39 , Processed in 1.110352 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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