EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ W2 D5 l0 n8 t- j' N+ s楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ ~- k: a% A7 `( l: F# E
这里有相应的模拟器源码,就当送给大侠了~~
' X& p& }7 u0 N' F! E" Z3 W7 ~. c$ Chttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # n! Z: Z6 [& H  L% t+ b) j
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ p7 ~! F/ Y! w; a& J2 t/ e楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 v6 d" s( e7 S这里有相应的模拟器源码,就当送给大侠 ...

: l9 g$ B$ A# y/ h  U聲音部分(Audoi Process Unit = APU):
) W. n; F& s3 B* n8 M# V" B# t.\NES\APU.cpp
& S7 `5 s* Z! N& ?9 d/ @# f.\NES\APU.h
1 @; B% ^* s5 b5 b
2 }  Y& K: d" X5 @( ^! g# s* J9 W$ ]9 I# o' l9 H
影像處理部份(Picture Processing Unit = PPU):
: N% c) U& b& d9 S9 m.\NES\PPU.cpp/ ^5 [5 e, F6 c# U1 H4 p
.\NES\PPU.h
/ C, u/ }' Y/ Z! u+ h$ L/ b" N% F: O- F3 p6 u
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:4 D+ d: ^' F9 p
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 t" F) t; u6 }, U+ Z//////////////////////////////////////////////////////////////////////////
0 @( }; F$ k! |//                                                                      //
" }- p4 b9 V0 @7 l/ A//      NES APU core                                                    //
- T7 s' E- v$ K, e0 y2 t# q//                                                           Norix      //9 [$ b7 Y8 @. H* u8 I' n
//                                               written     2002/06/27 //7 m8 o$ r" J+ y% B8 M  ]
//                                               last modify ----/--/-- //" t1 h( S  M8 h
//////////////////////////////////////////////////////////////////////////
2 w7 I9 u8 q4 g#include "DebugOut.h"
6 C% C+ E" N* z# R- ^5 u  g; _5 G' `; g#include "App.h"
4 c) l, J. Y) T8 y4 H6 O#include "Config.h"+ o, v4 F2 a- E  B
& P* v$ D& \" z& K' G- F
#include "nes.h"/ u5 L& X; b( @+ w
#include "mmu.h"
( L- x* n% ?' ~# ~4 b; `#include "cpu.h"7 |0 z2 s! _5 n
#include "ppu.h"* e; V; a0 Q* v; r$ p8 v. }" Y
#include "rom.h"  D6 T; C" N/ Z2 h
#include "apu.h"
$ f+ f% i. q+ l* [" i  K! ]4 V  T5 t
// Volume adjust
3 n& R; D! s) \  u( E// Internal sounds
7 F3 h1 c( i3 c" g#define        RECTANGLE_VOL        (0x0F0)
8 l1 |, ?4 n7 w, w+ H#define        TRIANGLE_VOL        (0x130)% v% f' T$ R% h5 }! M9 M: C6 R: J
#define        NOISE_VOL        (0x0C0)
& Y, H, V/ w1 m* l1 U#define        DPCM_VOL        (0x0F0)
3 n4 p4 u5 m+ s  `: O8 g0 B) y: e3 _/ u// Extra sounds- l3 X5 T- a0 ^8 \0 c7 y
#define        VRC6_VOL        (0x0F0)
) d* \  y  k4 u3 N0 S6 K; `6 Q1 K4 @5 b#define        VRC7_VOL        (0x130)
) W$ _3 x& H, z6 a1 g#define        FDS_VOL                (0x0F0)/ ~/ X2 ^3 k- K
#define        MMC5_VOL        (0x0F0)0 F9 O; ?3 k5 B" S; q- L* j
#define        N106_VOL        (0x088)
, J6 Y2 R- \9 F# f( @#define        FME7_VOL        (0x130)2 E) ^& x) C- _3 P) Q0 ~. H; u- i

. I5 O3 U0 Y9 L+ ?3 J- k1 \APU::APU( NES* parent )  @7 e8 `- g9 p# [) R$ X" I
{# c: V! M+ r4 C2 d9 Y
        exsound_select = 0;2 |4 M; G$ o4 Q! n2 I8 O
7 S7 [8 N9 }' }# C5 T& H8 N
        nes = parent;
! L2 }+ o2 O+ y" ~7 M7 J; o+ M  S        internal.SetParent( parent );# V. k3 Z  _; T
9 c: b. j: Z1 W
        last_data = last_diff = 0;
2 s/ E+ }: J# H- l4 v1 k
0 z2 H" ?% ]8 d( a( K, m7 a        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );& ]6 `, m2 }( w( G

1 w* R# i  ?+ V6 _' G1 O        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );- a1 o+ U) c7 X4 q
        ZEROMEMORY( &queue, sizeof(queue) );
! _" U/ s7 ]& m/ U% C        ZEROMEMORY( &exqueue, sizeof(exqueue) );- {* _- o) ]. c& k1 V5 m
: M; a" D" h9 J, X* K. `
        for( INT i = 0; i < 16; i++ ) {! c* ^+ d* H5 P! [( {7 X
                m_bMute = TRUE;' j9 Y+ S" k& L: \; d+ F
        }$ `  Z* F7 k! Z0 Q/ q5 A; [
}1 X. N! L  U+ ]1 s
- Q8 x* w$ P( ^8 n. k
APU::~APU()
: S( n$ i5 w0 {5 w{
: ]# b, ]" I4 `  Y' e5 W}, n( B9 \  W/ n9 Y0 j
% j& |6 B8 ]3 Q( v6 [; ^& A
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
$ x- }/ ?) i- F* T5 E* V{
5 G1 X) R/ B6 k+ h        queue.data[queue.wrptr].time = writetime;
0 K2 Q% a; h, [  z  `        queue.data[queue.wrptr].addr = addr;
# Y& J- F, j& t1 X* ]7 _+ K        queue.data[queue.wrptr].data = data;
& k: D# f% ~: p3 b! d& e        queue.wrptr++;
! X  i5 d- {, m5 p        queue.wrptr&=QUEUE_LENGTH-1;$ w+ }& C, }9 F, A/ g; z) F2 \
        if( queue.wrptr == queue.rdptr ) {; h5 u. r# `9 _4 X. _. e* F
                DEBUGOUT( "queue overflow.\n" );
3 u: z- B" u- v, q( d        }
0 \. w; C$ ]1 x) n}' k& s! B5 E9 S( r  J: f- H
3 v5 j, C: A$ m3 U5 Y3 }# Z) y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
( P# `" e, g# D/ J' N4 t{4 n. t. c7 y  p7 s: M
        if( queue.wrptr == queue.rdptr ) {
' {  V7 _3 D. M3 W$ y# X$ c                return        FALSE;7 L' Q$ \& u; z  V9 C% n% U2 K6 b
        }5 ^$ M4 c" A" J& ?4 h
        if( queue.data[queue.rdptr].time <= writetime ) {
( u: h( B  b% k% Q+ R# o3 T                ret = queue.data[queue.rdptr];; U) L0 a5 l) m+ b
                queue.rdptr++;
+ e, A$ `( K7 A1 \$ j/ H                queue.rdptr&=QUEUE_LENGTH-1;
2 m1 F& N) Y4 g' F+ ?0 J$ t                return        TRUE;' I- ?! y0 y; g
        }3 F3 f( Q, j+ h7 f
        return        FALSE;
! s2 a+ r7 h$ C6 a}
1 W9 T# W5 Z4 u3 A9 _
+ E5 g1 w' r8 n% T/ c1 |! s+ ?$ Kvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 b# [& \7 a3 Z, z* ~2 g1 E
{
9 U/ p  o% ^: a% X$ f3 Q  k' J        exqueue.data[exqueue.wrptr].time = writetime;
3 l$ ?$ W9 P3 G# u, l6 a        exqueue.data[exqueue.wrptr].addr = addr;
. m$ L+ \0 Z0 v3 p5 {        exqueue.data[exqueue.wrptr].data = data;
0 V* M# c0 J1 f1 q        exqueue.wrptr++;1 Z  h. P$ x" J! t. L* L
        exqueue.wrptr&=QUEUE_LENGTH-1;
, s5 C: y5 j4 K" a$ L# R5 y+ m        if( exqueue.wrptr == exqueue.rdptr ) {
, Y/ a( G' G9 u( v7 [                DEBUGOUT( "exqueue overflow.\n" );- W: I7 R9 P; }# Y% C
        }3 N4 D' |3 u8 n4 F9 n
}4 b- {" [5 m4 G
' \, x* T: i6 C# B- i6 t
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )3 P. B* R& l; B% i3 n
{6 p# _5 [' |1 P8 C1 q( N' n' h
        if( exqueue.wrptr == exqueue.rdptr ) {
# P; y' U  E9 Z5 D9 o: L* t6 P                return        FALSE;
' ^, p$ C8 @5 Z0 O- A0 u        }
+ G' S1 `* M' L$ X4 F5 S) H        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
7 W) v# [3 K0 ]2 Q; R- E1 ?4 q  {, e                ret = exqueue.data[exqueue.rdptr];* [' s) g: B& \0 S: M
                exqueue.rdptr++;2 N" @+ Y5 d4 p5 A5 h
                exqueue.rdptr&=QUEUE_LENGTH-1;2 J& l. J& g2 u
                return        TRUE;# h: b2 [, }0 _1 Y
        }
2 v4 _& _/ X+ j9 B& T- m- x  @: m3 w        return        FALSE;6 \) r& d) g3 s8 Z+ `+ Z1 y6 }- `" x
}/ x4 z% @# @# g# T( \& z
- `1 y1 \) v) s. ^
void        APU::QueueClear()
) X1 p$ c, D+ y{" x: Z' i" n0 [/ @/ T* X3 K
        ZEROMEMORY( &queue, sizeof(queue) );* X" z) p. e% ~# @3 `
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. E; |. R' P7 _* a: v0 R  }}5 O) }. P7 Q9 L6 z5 F( _) ^, T) D
  l2 r. @/ x$ o1 }% O7 l* u
void        APU::QueueFlush()6 O* \% n& x5 l
{
# T; d% t0 |8 y8 O7 `        while( queue.wrptr != queue.rdptr ) {% {! J/ k4 q- }8 p2 M
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
& c7 k  p7 ]/ Z' r# Y' Z3 Z# |                queue.rdptr++;
; Y9 Z8 P* b" m6 e  d, ~9 b6 [9 R                queue.rdptr&=QUEUE_LENGTH-1;
# `/ Y6 P, W3 ~" B2 N/ h$ P        }
) Q, l' V  R( S4 m! ?
8 w" j" H5 K7 F/ m5 Q% C& J/ l: p        while( exqueue.wrptr != exqueue.rdptr ) {! \" w4 g! V6 \0 T! C. O2 O
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );# Y% Q6 W2 l6 u8 e2 P$ ~
                exqueue.rdptr++;5 V, I3 H: f/ x
                exqueue.rdptr&=QUEUE_LENGTH-1;
# J$ m% r' W. V$ q6 n, E7 R        }* w- N& ~6 U5 F2 b& D# n
}" ]9 J: B+ v* m0 i* H
8 A4 t7 Z4 w" e4 [$ w! \: b4 [) J
void        APU::SoundSetup()
6 `0 A- l1 r) s- i/ C+ g{
: v' o; H1 e: y2 j  o  q$ W. @        FLOAT        fClock = nes->nescfg->CpuClock;
2 U0 w4 M+ e! J1 R5 R0 n& }9 S        INT        nRate = (INT)Config.sound.nRate;
' L, H, c7 R- `& X        internal.Setup( fClock, nRate );
/ M6 r& X1 \2 C4 V        vrc6.Setup( fClock, nRate );
: V) A8 Q- ]" |# W; {9 U        vrc7.Setup( fClock, nRate );
4 S: }& @( v  L- J; D% B        mmc5.Setup( fClock, nRate );% f& S; S; ?3 W1 q% Y0 ^- z1 g
        fds.Setup ( fClock, nRate );! f2 J/ h6 z4 z; ?5 g$ |
        n106.Setup( fClock, nRate );
# j. L! ^. b  }( G! q. b3 L! d        fme7.Setup( fClock, nRate );
1 s7 O9 ~% V6 Q: R}
/ A- u: W- {/ e
( W8 H5 K( M3 v5 X0 T& Zvoid        APU::Reset()& H8 m  o: Q3 R7 T: A
{
' G  U& x1 c# e" G4 q        ZEROMEMORY( &queue, sizeof(queue) );
3 P/ ?8 y2 `2 h, C6 U9 P7 h        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, b: M. h" ^+ o, A: ]6 r6 Z- W
1 |: H5 p- b% ~        elapsed_time = 0;, {+ p: E. }; {1 C. Z. t
- B- D& W  _2 j1 D' Y, x0 y4 O, d
        FLOAT        fClock = nes->nescfg->CpuClock;& L6 Z  i: V+ b9 m. U
        INT        nRate = (INT)Config.sound.nRate;6 u) u& c* R& o4 i; z
        internal.Reset( fClock, nRate );  ^$ g5 q: ^+ J3 N8 z! c
        vrc6.Reset( fClock, nRate );
& e+ b( r% k8 D# k; d0 {- l        vrc7.Reset( fClock, nRate );5 f$ z' z+ f8 I$ T6 X* E
        mmc5.Reset( fClock, nRate );
( `% M  o7 _! X$ ?5 X        fds.Reset ( fClock, nRate );( C- N, T" f0 s! m6 G" e6 T$ \
        n106.Reset( fClock, nRate );
$ g' Y# n: l% Q, H' p        fme7.Reset( fClock, nRate );
6 i: F& G, c  U9 U: v; t3 {+ v' Y2 b' k! @2 Z) X  L) \
        SoundSetup();6 N8 ?% L2 O8 p
}+ P6 V$ s9 r9 ]2 D+ k

, e$ |4 O8 b" h4 h$ vvoid        APU::SelectExSound( BYTE data )
1 J3 d: U. v1 \7 I& A2 @' D7 R{
" l6 t) |& X* h+ X        exsound_select = data;" A0 Q/ g  H7 x+ x- y: f
}
" h$ X, A% f2 K9 K4 [8 M0 l( `( g: ]1 O. R6 w. l
BYTE        APU::Read( WORD addr )4 M: U, M) m3 \# w* G4 J, ]- W
{
2 }7 e3 {7 G6 z        return        internal.SyncRead( addr );
' g; b5 L7 G9 c7 _}9 X6 `7 l8 d3 I  o
2 Q" p7 m( i7 J& w6 i* A
void        APU::Write( WORD addr, BYTE data )
9 h8 A3 S) l) T, o+ v{5 x/ @3 H+ t$ L/ R& }
        // $4018偼VirtuaNES屌桳億乕僩
: f- u2 z; n) m% [        if( addr >= 0x4000 && addr <= 0x401F ) {' ]0 b! r* m) I, N/ n' L- N" X
                internal.SyncWrite( addr, data );
5 y" @3 k$ a1 x* y5 m                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
+ g# |5 r$ f0 E  q3 K$ ^' y# f( i        }) q* n; M: e8 v+ I
}1 c. q& |5 N+ H0 A, Q, z/ o8 d# o; l

: B7 l9 |0 G3 L0 X9 W  ], X) IBYTE        APU::ExRead( WORD addr )/ l' i4 b3 l- D* W5 z2 c
{% }, R, x4 b. W# Y
BYTE        data = 0;
( m3 l/ y- L8 W% e  G
' z3 D, P" h( M: S5 Y        if( exsound_select & 0x10 ) {! n; z, o' k9 f0 y. e* ?
                if( addr == 0x4800 ) {9 u* m4 V. w" f: h& N# e- Q& I
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );7 l# J' l, F8 O9 m  M- ?/ V2 l
                }
' e8 c0 w  V  q9 Z6 d) I        }
; _2 L) [" i  t6 B8 i; U0 l        if( exsound_select & 0x04 ) {
+ D3 h0 M. x) k                if( addr >= 0x4040 && addr < 0x4100 ) {6 z& _, k5 i% N8 Z5 ]0 v' C. C
                        data = fds.SyncRead( addr );
7 \; _# ~6 X+ x/ j6 P5 A                }
4 V, Y) O5 P$ E4 v( [        }6 A8 l3 A5 p: f; e
        if( exsound_select & 0x08 ) {
0 x" `, C7 S( s) q( I+ Q                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 ~' O* t8 U2 c, X* H                        data = mmc5.SyncRead( addr );
* p% N* T$ |, x! ^                }
1 P. A4 ~: M2 o4 Q, P+ y" G5 _        }. b! A0 z% T# P8 t% K% K2 C7 ^

( l/ W* i/ [/ [+ [: k3 ]        return        data;
% a  T  E2 Z- {9 ]. N7 ?- ?/ m}( Y) Q' u) S7 c  ~. f/ ^
" }8 l$ `# M$ z
void        APU::ExWrite( WORD addr, BYTE data )
- O; `% d$ h6 |/ p{8 ~) J1 y, y! t5 j, E9 L& @$ a, o$ r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
- h- q6 N/ D- Z2 s
* V2 R# A+ j  V6 L        if( exsound_select & 0x04 ) {* a# `* r1 u! q$ e8 W. a5 s5 E
                if( addr >= 0x4040 && addr < 0x4100 ) {* t( ^; P$ f! k
                        fds.SyncWrite( addr, data );
) y0 ?9 s  v* ?; J; y0 ~! O7 ^3 S# b                }7 G  b4 s: w& J2 v9 i# m0 q
        }0 V4 K' U" w% f+ ^' r5 R; L

8 M  V: s+ @% m: {4 ^) Q        if( exsound_select & 0x08 ) {
9 G  N: G* c3 f  U                if( addr >= 0x5000 && addr <= 0x5015 ) {
) c4 Q0 y0 D8 \2 x                        mmc5.SyncWrite( addr, data );
+ ]5 Y+ u- S8 k- K1 Y6 R                }
" U3 T% b' }. H& _' q- j( d5 y        }& p8 G8 T8 J& W; C) C" F
}  F4 k) \- u8 Q) l7 O2 I: }* L- _$ l

( O8 d5 q. I5 _% t% C6 ^) Cvoid        APU::Sync()
: |5 M6 `7 ^& v7 E3 ^) t  \{0 i7 }* ]& L: @& Y! Y
}
4 j& ^' B& R2 O& e. _, o( F" j! l/ i+ T6 q6 _3 q
void        APU::SyncDPCM( INT cycles )7 T5 ~# Y' k4 Y7 v& v
{
' I: }9 K( o+ I# g        internal.Sync( cycles );( Z9 ^  a5 d7 s9 W- j: c* z* P
4 ^0 W. w' @3 T7 P& m  e: [
        if( exsound_select & 0x04 ) {9 \' o1 `; \- `. ?: N) Q: C
                fds.Sync( cycles );
* o) G9 |# t8 O' N        }
# D0 K/ _4 R- x* j        if( exsound_select & 0x08 ) {
: U0 Y7 }+ K+ ]                mmc5.Sync( cycles );
/ G; v- `( t2 A7 U, g5 z! R+ Y        }! h/ p- \2 E8 H; a" h: ^0 b& w  M
}
* o! }" q1 k6 q4 x4 I9 A, i0 j% B" T; M* i6 V8 D# f5 I2 D6 a5 H
void        APU::WriteProcess( WORD addr, BYTE data )% u7 q7 \& W0 a: c! A
{5 W$ r$ |6 o, s( }! ~
        // $4018偼VirtuaNES屌桳億乕僩2 L5 s+ q! F- \2 ^
        if( addr >= 0x4000 && addr <= 0x401F ) {
/ d" {3 T" @$ A) q, ~                internal.Write( addr, data );; ~3 v  X! s8 [* H! v- S
        }, q# i- C3 j. E4 x2 E  Q' S4 D
}$ z) x2 @; C. h8 _' m: k0 L( P

2 p% @4 ^/ l. ^2 `& R+ Rvoid        APU::WriteExProcess( WORD addr, BYTE data )& ^# [9 I( g2 [
{
& L6 @! Z5 C1 `8 p' p. I. d( S        if( exsound_select & 0x01 ) {7 ^+ D# S/ a2 z; ?/ d* o
                vrc6.Write( addr, data );
0 q) t; ~3 g" C+ |' j8 k" [        }! A- i, a% r5 a( ~
        if( exsound_select & 0x02 ) {
7 O5 X/ q, ]# G3 Y                vrc7.Write( addr, data );
7 ?  ?4 K8 K7 x: w7 x# F2 J/ h8 t        }, O3 n" |+ N, n/ D
        if( exsound_select & 0x04 ) {( G' h0 w/ S% t1 R2 Z! k
                fds.Write( addr, data );! L  C0 o$ u) Q' j  e8 X1 S0 B) {
        }
4 ~( }6 m* S  e6 g6 O8 m4 |        if( exsound_select & 0x08 ) {
7 B3 T! T& \0 ^" R. A. v                mmc5.Write( addr, data );1 S7 Z. w4 e9 s: Q" s5 I6 L( v
        }# Z3 b7 R# A6 u2 [! U
        if( exsound_select & 0x10 ) {
/ V! M+ X* n+ j5 z1 m                if( addr == 0x0000 ) {
$ l( r  M9 Y8 O3 q& W( j                        BYTE        dummy = n106.Read( addr );, ?6 r: W, _5 s6 M$ F5 R. j' l+ n
                } else {
- a" g3 I* Q2 {/ G1 H                        n106.Write( addr, data );4 F6 Z7 {! @7 j% ]
                }
' Q$ u- g5 j9 m4 m, f2 e        }
7 q/ X( k6 X/ j1 Z: R; F* {        if( exsound_select & 0x20 ) {( w4 p2 L* A4 f. I( @8 s0 O
                fme7.Write( addr, data );- G4 a' ~" s$ d- b: x
        }
0 j( Q! i) Y' T& O0 \. t8 g" G}
8 U, A0 M1 ~  H; Z, Z
0 M4 `- o* L4 U. `2 u$ cvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )( T' K3 f% ^! A7 G: r% X# b: v7 O
{
! y9 Z. Y& E6 w" v. u+ S/ d: vINT        nBits = Config.sound.nBits;1 i( P! b: c5 L) B$ M8 s
DWORD        dwLength = dwSize / (nBits/8);
2 U( P" o" ?, b, ^7 b; B  f2 gINT        output;
! B) v$ T1 T/ Z4 J6 U+ HQUEUEDATA q;
: }- }" K) p7 c2 D# q2 W' Q/ PDWORD        writetime;# X& T/ \  U  B( R3 c2 O/ q9 [, {- O6 }- H

8 Z$ c. w5 Y/ m7 n0 V4 ]LPSHORT        pSoundBuf = m_SoundBuffer;% c) A( F5 c+ U2 o5 a
INT        nCcount = 0;* U. @; u) c. C

; D5 @8 |9 ~" nINT        nFilterType = Config.sound.nFilterType;
9 y, c* I. |" O4 j, L9 k, G
" r# y2 s9 y8 z: @2 \& V& @        if( !Config.sound.bEnable ) {
% ^- W% m; M; R8 e8 q                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! G1 P+ l  x- r" {# W& d
                return;+ w# h6 b0 R& K! V$ Q" U4 E
        }- s* N* W- L4 t( |

/ F+ Z* p6 @+ k) \        // Volume setup2 g4 L( q% j3 Q& u6 @6 F
        //  0:Master" E& _* @; Q1 u) x6 a
        //  1:Rectangle 1
1 N) F4 y- \$ m' ?        //  2:Rectangle 2
& C: @9 _. q1 y/ ~        //  3:Triangle2 A$ @9 C. p' i' y9 u# m
        //  4:Noise
" b. h! e% C* {        //  5:DPCM( ?9 ?5 P# z* L3 b. R9 a& u
        //  6:VRC6
5 @8 R( Z, W5 G* M. U1 I: ]: @        //  7:VRC7
6 r% A% Y3 b5 r        //  8:FDS% G  Z, V1 T) B
        //  9:MMC5
) w& K& _& ^' x! x        // 10:N106
/ h$ W5 }. f* T  n        // 11:FME7! N- I3 p) t4 U% D' c
        INT        vol[24];
& O2 t& [! h7 L1 m- a        BOOL*        bMute = m_bMute;
3 O8 E, P0 Y  K( B        SHORT*        nVolume = Config.sound.nVolume;: ^6 p  y* z0 E, A8 a' H5 d5 y. z

" v! I; p) j1 `8 n. C9 A        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 C  C/ L" \! e

7 g& @  }5 ]# n0 B3 ]' x/ p: p7 m        // Internal
# x( w; L6 U8 z+ i( m* e. [        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: ^, z. n; v, X5 @* W
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 r4 o4 i- W2 k- Y  [" @        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 y: v# [! g% K        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 X' R0 y1 Y2 T* H) Z  @        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
3 C: O. K. X: w! {0 ]9 m6 w: z" P! o( p* F9 Z, X
        // VRC6- y( _( Q; o% l: u# S! W' L
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% X9 Y; I( l$ ?7 W' x6 t) Z
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& p' `" U' D0 _! E% s: z
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% q$ R9 i. H1 U. O
* V5 p8 e! H- K% ]        // VRC73 K* q/ w' f* L
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. f/ Z' S5 e4 z. l

6 ]* H& i' `7 j4 s        // FDS: w) X- L- O' f% }# X! `4 r7 p
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;( v- P# D; z, M+ {
" y7 s4 w3 H; {# m: l9 {; E  N
        // MMC5; a* p7 I, U! |6 u1 O
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ [0 `0 N/ @4 \4 H. I/ U/ N        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% D" }9 n* ]( F# I- B8 `        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, M5 e& Q+ ^. V/ p$ [& d
! y: h, W8 \8 `# z' e& B        // N106/ Z/ P7 X  s/ y: ?, e# x  B3 \
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 F( }$ ?5 Z- @. Z
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 m5 u$ j$ j1 P+ u6 H8 |
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( W0 c3 f( K" G8 g. S8 P        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) e7 [3 ]! Q4 U* e- `+ T        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. J: B0 D  i7 t( R4 ~. S& O        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  t# K% H$ Q7 r0 v4 l& |        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 N: v' I) [5 a        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 n- z4 t* Q4 ?2 _0 l, |3 V% b  P
8 Z/ x  `9 |$ t" ~* f8 ?( i
        // FME7
, |- h0 R- i% H" c5 J2 W        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ f5 P, E6 a6 P( Y        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 r. R, J: ?* K- s- M        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 O- e6 a) {1 E4 n+ ^/ h. C3 a! Q* F  c; g
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
. ~% t2 u4 u$ d4 ]/ a: u" E$ o        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;$ n0 G1 P) ~1 F5 ]3 F
% x  A1 h  S% l2 M7 X5 X+ I' \8 i
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
6 q0 o, _' ~* [2 ]  J) |- G# u& H        if( elapsed_time > nes->cpu->GetTotalCycles() ) {3 p; M; Y! e( m
                QueueFlush();' W+ Y1 Z( a9 X
        }
9 m2 [/ I& F4 F  ^' R
5 |; z% G  i- J/ G0 W        while( dwLength-- ) {
; _" U  {; `7 B. m& B4 p" e% r                writetime = (DWORD)elapsed_time;
, k" j& E0 z8 n( L5 e# Q& T
) w- H! S, x) H: Z                while( GetQueue( writetime, q ) ) {
% v/ S7 M  ~, C+ H                        WriteProcess( q.addr, q.data );7 l# ~" J1 c# e3 k! V/ }
                }& b1 B* t% {; l5 `
- O; h2 A* H2 H" y
                while( GetExQueue( writetime, q ) ) {
3 w# P; r) @# X1 _; o' U                        WriteExProcess( q.addr, q.data );% I6 e" G1 s5 F$ o" Q
                }) w9 N# S) Q; u) L4 N; R: e) Q
8 D2 O$ F9 B9 ]/ ]9 i+ w
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7' o' y5 ?9 U# `3 R6 g
                output = 0;
8 a) i  p) ]: ]) P4 }$ V4 J, T# J                output += internal.Process( 0 )*vol[0];+ r8 ^' G+ H' t6 x. m+ t
                output += internal.Process( 1 )*vol[1];* U& d; `6 p8 j
                output += internal.Process( 2 )*vol[2];. n/ z2 s& ]/ z, ?7 G3 n
                output += internal.Process( 3 )*vol[3];
0 ^! b1 `3 t% X% K9 g8 M                output += internal.Process( 4 )*vol[4];! j7 K% [" o7 F" {# c3 Q

# x% }% N" _& H$ ^                if( exsound_select & 0x01 ) {( [, b2 ~# I' }" Z* J
                        output += vrc6.Process( 0 )*vol[5];
$ @+ Q0 I5 y( A2 n8 V  l, _                        output += vrc6.Process( 1 )*vol[6];
7 ?4 ^1 A+ i1 c' a2 o1 n                        output += vrc6.Process( 2 )*vol[7];& [" `' s! x+ C, l" t
                }  d# z9 A9 Z# C9 q' S7 t7 O
                if( exsound_select & 0x02 ) {6 R4 y, ]/ r1 H4 ^
                        output += vrc7.Process( 0 )*vol[8];
$ s% v- h, J' g9 z( z; q! F                }8 N. N3 \; {, e0 c: R
                if( exsound_select & 0x04 ) {
. ^7 I  ^/ t6 I# q+ Y                        output += fds.Process( 0 )*vol[9];$ T8 N) @, D# j/ m+ w) O1 Y; V
                }& k0 G: z+ \7 V1 n
                if( exsound_select & 0x08 ) {) R8 @; z! ^# e) K$ P
                        output += mmc5.Process( 0 )*vol[10];7 [2 S6 x7 R  |- i: |! a* U1 W& \
                        output += mmc5.Process( 1 )*vol[11];/ M; I+ n* m' b7 v/ f. ]  c; Q- |
                        output += mmc5.Process( 2 )*vol[12];( z% a4 B: Y- H% u/ E4 Y
                }
3 Z, n. ]0 m8 B; D4 w1 }                if( exsound_select & 0x10 ) {
( m% c3 ]4 ~$ [9 R. ^                        output += n106.Process( 0 )*vol[13];3 P+ h9 g- r* Z" q( a1 f
                        output += n106.Process( 1 )*vol[14];
4 d6 H; h1 H- y# a& F: S' k                        output += n106.Process( 2 )*vol[15];
. M! p2 d& b- l4 I9 R. O3 }                        output += n106.Process( 3 )*vol[16];
3 A! X. O7 F0 e" }3 j6 p2 x- [" [                        output += n106.Process( 4 )*vol[17];) G  t" D8 o8 T; }2 W
                        output += n106.Process( 5 )*vol[18];
' z- ]7 F: [9 K2 k+ \                        output += n106.Process( 6 )*vol[19];
$ _! D& `' X3 V! j6 {$ u& ]& v                        output += n106.Process( 7 )*vol[20];
! b; n4 U0 A- A# d                }- J6 J7 B/ d. T8 }9 `! N8 T' D
                if( exsound_select & 0x20 ) {
/ s" r5 ^% X- p& g2 W                        fme7.Process( 3 );        // Envelope & Noise
/ F1 r2 Y  ~# I' z/ j- x                        output += fme7.Process( 0 )*vol[21];
: F2 K- l5 J5 {                        output += fme7.Process( 1 )*vol[22];: e) b! ^/ C8 N9 k2 p) g0 A& h
                        output += fme7.Process( 2 )*vol[23];, B- T9 I, w1 s6 G: m2 o/ n
                }. F. r0 k% @  T. b4 V0 ?. U* c

8 y3 T. b7 L& d* W( I                output >>= 8;) N/ ?. M/ D& U$ T3 h; V
+ D0 I# F+ Q5 F! I7 ]& ^/ `
                if( nFilterType == 1 ) {, \% K3 C- |8 {5 c$ D0 ]& j
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  h7 [! R* b8 a( w. V
                        output = (lowpass_filter[0]+output)/2;! {7 V: |( y: q& O6 x  |( N; {
                        lowpass_filter[0] = output;. t# y3 R4 A0 B( v5 L
                } else if( nFilterType == 2 ) {
) L+ m0 Y- e- o1 |  v                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1): e5 P7 H, N5 B0 U# @% ^$ R
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; O, E5 z3 r+ H0 ]: q: w7 u/ J9 L                        lowpass_filter[1] = lowpass_filter[0];
0 f3 o9 L* V6 w+ j" K                        lowpass_filter[0] = output;
6 o- F) w- f5 ^. U8 Y                } else if( nFilterType == 3 ) {/ y. o1 l8 r) z2 \. i
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 X/ g+ p6 \3 Z" ]* B; ?/ W; o8 n
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
9 f/ ~8 ^  y3 a: I9 _3 W8 _                        lowpass_filter[2] = lowpass_filter[1];: x; j! q( q3 d- M
                        lowpass_filter[1] = lowpass_filter[0];) O8 @6 D: F/ b( S- ^# P: ^
                        lowpass_filter[0] = output;
2 t7 B- V; @5 W+ f                } else if( nFilterType == 4 ) {3 D# j6 S) q5 H6 l7 A0 k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); _$ c; M# a. r3 |! y6 U* K
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( l$ F6 {" N) c5 T/ B) K
                        lowpass_filter[1] = lowpass_filter[0];
& y% V/ }; ?# P( m  ~# ~  H                        lowpass_filter[0] = output;  H. f4 j1 G- o+ b+ h$ K" k4 @
                }
2 V  C3 n9 X  f7 L/ R( e4 O5 Y' ]* c  P7 l& w; J
#if        0& r8 I, @* {! n, {
                // DC惉暘偺僇僢僩9 |- Q, ]8 }- g+ H$ ^
                {
$ a: Z! Z( C' S2 a$ h                static double ave = 0.0, max=0.0, min=0.0;2 G8 q, h4 i$ Q  v# J% ]
                double delta;! U$ S' }) f2 j! E+ p$ ~
                delta = (max-min)/32768.0;
- {9 k1 L/ v& e2 @, o                max -= delta;( Y0 z6 d( t. h, d
                min += delta;) g- ]: Q8 k9 }: S; Z8 `
                if( output > max ) max = output;
+ V. l( I8 ]+ ]- S" E2 Z                if( output < min ) min = output;- ?3 [# j7 V6 ?: v( P! t4 v3 o& v
                ave -= ave/1024.0;6 D2 D1 P, v. V0 ^1 w
                ave += (max+min)/2048.0;, ?5 U  x; [9 |, @/ N2 k
                output -= (INT)ave;
8 L9 _) ?) K& U* |; Z                }
1 G/ u# s3 J# ~) V#endif
  D0 |' j5 Z/ p/ B#if        1
- H, H* t' B5 ]4 g. k                // DC惉暘偺僇僢僩(HPF TEST)
6 ?1 ]# M7 H, `5 p) [/ ^, {( }                {2 v" q5 y! M% q
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& w- l2 m7 K1 J1 u! h% m8 v                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- F4 k6 t: B$ Y+ e4 G8 n* X                double        cutoff = cutofftemp/(double)Config.sound.nRate;
7 m5 z, X' Z5 _  J0 p9 F                static        double        tmp = 0.0;
# Z5 Y  g# U2 x% |                double        in, out;) w8 {7 n1 {# T6 I3 N& [

  x5 b) E7 z, M                in = (double)output;
/ }# w, ]# z' p& n. a: b; E                out = (in - tmp);
1 D" A) G4 K7 y$ A' S6 @                tmp = tmp + cutoff * out;, e& v) H- P3 |; u
$ K! z- O* u& Q- H( M
                output = (INT)out;
6 z: w7 \( E$ a  T                }1 L7 n9 [+ }  S6 u
#endif# D' g% z3 P& O5 V8 b2 B8 u) A. L
#if        05 U: e' E$ d0 P' b
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
, i6 ?) O6 @" N+ Z' {* U4 Y                {! a  s( x1 V& O
                INT        diff = abs(output-last_data);- M6 ]- R0 `: r) V, Z& C
                if( diff > 0x4000 ) {
# R) N' c3 P: n8 b3 M: u                        output /= 4;/ Q9 I3 `6 H7 G* t: _
                } else / x+ F) S9 N' W2 Y% S
                if( diff > 0x3000 ) {: s$ _% J0 Q% R1 i; K: H# M0 Q3 o9 v
                        output /= 3;
/ I- f. z; ]$ M                } else8 R( M" E* y: C/ p
                if( diff > 0x2000 ) {
, j4 M6 [* n$ t                        output /= 2;8 Q8 v& D$ [6 ?( W5 r
                }% _) _" n; O% Z/ z
                last_data = output;, `. }; |# V  D0 C) H$ g4 }4 F3 w% D
                }
: H: g6 O! ~6 Y+ G3 l#endif4 i: j( x. t6 M" ?
                // Limit
& W  Q/ G: r7 X; P: Z                if( output > 0x7FFF ) {
9 Q- ~( `2 Z# g0 H                        output = 0x7FFF;
' P, p6 ?$ z* L/ B6 ]2 z8 K  a                } else if( output < -0x8000 ) {8 m3 `" }9 b3 d( C  N
                        output = -0x8000;* S3 U6 G5 a1 t! l* w% h) V" D
                }+ K6 o' A& g6 I9 [" m( d
. W' i( I% {9 e/ _0 d9 a
                if( nBits != 8 ) {- W2 t) c9 L( x
                        *(SHORT*)lpBuffer = (SHORT)output;2 T$ T- K, B! ^) ?$ o+ d2 C
                        lpBuffer += sizeof(SHORT);. j2 D0 v  z; @+ P9 U
                } else {
, v/ o8 s) \% }2 C1 o( l1 W; p                        *lpBuffer++ = (output>>8)^0x80;
! m+ e" b6 s7 K' e. k1 W0 I! t- ?* H6 M                }
! z: u7 Z( a7 Z6 x$ L# I
+ p) z' d& |; R8 Y9 }! x4 t                if( nCcount < 0x0100 )
+ G; i# o1 \- ~4 N' J$ c                        pSoundBuf[nCcount++] = (SHORT)output;: y" ]" s8 W' j0 {% |* C1 @  Z

3 K. p! w: s. r7 _% q& u//                elapsedtime += cycle_rate;
3 `% ], M$ q5 J" x+ p0 L3 g" B                elapsed_time += cycle_rate;
0 a# ^8 n" X( o8 A        }. O! Z6 U% x( I6 s

# v" ^: l( {6 a: y* P#if        1
0 ^/ F, c# C* z/ ~2 }        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" g) `, w% E9 z" l6 t) F" z
                elapsed_time = nes->cpu->GetTotalCycles();
% m1 ]2 f$ b4 B* k5 y# Z4 y        }
/ A8 `# _: ~3 k4 A7 R0 K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {% T7 T  @. ?7 v7 a* |
                elapsed_time = nes->cpu->GetTotalCycles();
% Y2 u3 \5 |  u6 E8 w        }+ b8 x% K9 m" t) }5 m( G2 m2 p, a  o
#else; U" K5 e* t4 y' ~
        elapsed_time = nes->cpu->GetTotalCycles();
; l% U$ I2 ~% P, I: X. c#endif
9 x8 G) q2 Y2 ]  a# k}! z' a- ^, r' |; a. K

% t, S) {2 e/ n% ^: r2 _' s* V6 l& c// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 h2 w* \* n8 L( V4 E. UINT        APU::GetChannelFrequency( INT no )
" U: c0 Y; p" _" p+ @% c: l{4 `; {0 W* \5 F5 l, ]
        if( !m_bMute[0] )& x9 t9 w# x: Z) r
                return        0;
! Z" k) ?* D. S) E7 A3 J! H* B; `% g
        // Internal
- c: Q  Z$ U% j* A        if( no < 5 ) {
+ I. M8 O  H5 x' b, C& g/ ?7 v                return        m_bMute[no+1]?internal.GetFreq( no ):0;
0 U4 f3 w# K. K1 N: O5 B7 d  \        }
* R4 p3 x, U3 N        // VRC6
( C/ ~& o/ i% _% u# Q; L) b        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; `) R6 \* E5 ]4 ~" f8 {0 u                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& ?( |* o. C. M+ |$ `' A, h+ Z        }2 u% Z5 n  m2 s! V7 b# u
        // FDS
. u" }8 F" m+ I        if( (exsound_select & 0x04) && no == 0x300 ) {
- t- M, C) U5 k: L- ^1 N1 k                return        m_bMute[6]?fds.GetFreq( 0 ):0;
' @" L! D  M0 Y( m, L  L  {        }* e& i' h; C0 k6 z/ |
        // MMC5: c* l0 T* D9 T% Z% ?
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) Y$ B* s+ `/ M" N" `5 j
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) n! V9 S7 u: _6 W        }
; V) c& P7 u* i        // N106
  o' l, \4 M9 Z# {        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' g4 N4 [% G: w. G                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 T  I5 C5 K, I        }
) j/ l) @9 ]/ w/ ]3 n/ l$ b' Q        // FME7
# H- g' y& O1 ^. I6 [2 \/ ]        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {5 E) J8 m2 c; E" X
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
+ }: c9 `: p3 ]0 n        }
9 ]# y, |, B% Z' ]/ o9 i        // VRC74 p5 U) G4 @/ P  p6 L. b+ ?
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {/ b- w8 ~# h' o: `
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 `4 @5 v. ^+ E# k  x
        }
# ~7 ^4 {0 @$ w5 m+ A, q* a        return        0;* V0 P3 o7 [' T9 M' Z& K
}
  e6 M7 Q* v, p( S! l7 |7 a  Q1 k/ `% m* w4 o$ e/ k
// State Save/Load5 I! M% E; h7 [* Q, M5 I
void        APU::SaveState( LPBYTE p )
) a) V/ |4 D, ~. \8 f) u3 n{
+ Z  G* c9 \; a#ifdef        _DEBUG
% P: D% l) |# s6 F5 f. w$ S; aLPBYTE        pold = p;' G1 z8 h9 @& w0 d! c
#endif" @! F7 j5 r6 K) u: h7 M" G
9 U4 q  O) I% `% o6 k0 v9 u$ _
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
) q) [# e' n5 b6 u# E* P% S        QueueFlush();: @# Z* a; x2 Q. m% e& p
+ l; u# ?! C8 S4 D% t* L0 ?
        internal.SaveState( p );+ `& S/ [6 v9 t' \. X* b5 Q- F" f
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- ]5 A. U7 k7 s! C4 N" R) b, C( e4 U7 \
        // VRC6
4 g7 i' z$ i. h, N. S! V        if( exsound_select & 0x01 ) {( w4 ?* s) j3 w  b: g3 _
                vrc6.SaveState( p );
( B* q0 t1 ~0 U7 ?( g6 z/ c6 X" i                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding/ m% E9 b! {% ^3 ~
        }. Y$ D) w; V  s, B3 u+ d: K  k/ c
        // VRC7 (not support)
- S  T2 f4 S$ H8 c: m" T        if( exsound_select & 0x02 ) {
) T# C0 }. N  C                vrc7.SaveState( p );6 E1 ?* s: w2 D1 H: ?, |
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( n8 z, z" U& N/ \7 Z, ~. G        }
8 B8 H% D9 W- P        // FDS- x$ _, @& ]% U% r. Q
        if( exsound_select & 0x04 ) {
9 A/ G/ M) ~6 {' I) @                fds.SaveState( p );( v( e9 u. ]9 O9 @7 I+ l& T& ?, a8 h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ D! ]7 Y' A: O- p" T+ O& L5 H4 M        }
- c; K# s9 s& ?        // MMC5
+ }$ l; j# c. W: v* T) O% C        if( exsound_select & 0x08 ) {/ i( |8 q; L2 N) G( M0 H
                mmc5.SaveState( p );5 `1 k: Q  q) ^3 L1 `2 H+ E" e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' r4 q. u1 P7 ]  G* U$ M0 O        }/ P- j$ C3 r4 @* K# }- \. V
        // N106
* l: N' f6 r& x* x6 I4 x+ p        if( exsound_select & 0x10 ) {$ Z+ S: \3 d* w9 X' E9 f
                n106.SaveState( p );
1 N! e# \4 Z9 W  p: o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( t9 J' S: ~' z' f
        }- h, R( m5 u6 _  f5 G
        // FME7. M9 L0 _* N3 a: ?- k  I9 L2 @
        if( exsound_select & 0x20 ) {
, }  h' a( W. ]! C' e6 H                fme7.SaveState( p );
0 L4 f9 f' j; S& ~                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ h2 b5 @* N- S" x) j. u# \        }
$ F0 ]- @5 V4 ?4 Y: u6 \' d; a
/ Z! q7 P0 _/ U$ L#ifdef        _DEBUG
; q7 L5 ^5 M7 Y9 M& p. s: _* ]9 JDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );, Q5 D7 T; F* q6 k
#endif
; |2 v7 A( i4 e4 P- T. i6 R5 A}) C9 {9 q" x) o$ K( ]
  y4 z$ ?7 y$ x" H; r2 M
void        APU::LoadState( LPBYTE p )
, ~3 b5 [* X' V2 T{, M+ \; Y# u+ f
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 w, g5 x% j( V  b; f        QueueClear();+ a: M( G- ]$ n* \# O

2 L3 c: ]; S1 o9 M        internal.LoadState( p );, d+ Q+ d* {: h- c
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, l) o5 [1 u! u( x1 p* J6 n5 C: u; `1 i3 F5 Z# s5 F
        // VRC6
4 E& N& X7 X+ p6 G7 B        if( exsound_select & 0x01 ) {* D6 d1 S5 c! X2 n8 A
                vrc6.LoadState( p );
6 L6 q; |- k, S0 m7 `6 ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. D4 ]" @7 H4 m        }6 I, E( a& f( E* B# G
        // VRC7 (not support)
9 S1 c" S. ?  f  u( G3 u$ u% _        if( exsound_select & 0x02 ) {: C) {# N7 E* l9 `/ Z& y0 Q* w# ?
                vrc7.LoadState( p );
% }2 ~/ J- C  A' F. P! }                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 \* }6 o/ Z5 ?
        }
( t6 N; X5 B! r+ b        // FDS" b, ~2 a  t7 E! P
        if( exsound_select & 0x04 ) {4 Q" D3 q9 X9 n) m
                fds.LoadState( p );
7 T; x" s8 E5 I/ w# @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& d7 C. {, H* j/ K( j
        }
: H- K% N! t1 |* J" N! u        // MMC5
) [1 H6 f1 b- i' P( C        if( exsound_select & 0x08 ) {
% F; ~6 X  ?% g$ T                mmc5.LoadState( p );
' U) W( r: i( a                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ y$ c! J, ~% l8 t        }
" x. j) b7 z  C" d3 @9 Q0 ]  n        // N106& x: E5 `: I1 y* I
        if( exsound_select & 0x10 ) {- [4 b+ U2 _) }6 _5 _7 Q
                n106.LoadState( p );# \+ V- u7 n2 G! F- ^
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  `1 }$ _. H& |9 K' d. b        }) k& P* |% x( J1 @& r
        // FME73 J- h9 @9 a, L/ C
        if( exsound_select & 0x20 ) {8 |; h4 H. P! u* |* L1 ?
                fme7.LoadState( p );, X* P5 f' Y* \; S# s( H. M5 n
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ ^2 O# E6 _3 D) s0 i" |5 W; F        }
; \9 x3 U) `! K9 |7 l: j}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ V( s# K8 z8 \- s5 r" U可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 x9 C8 v2 Q0 E8 }: p- X' l
感激不尽~~
8 {/ x& d& W" k$ G+ b, b: B0 W
恩 我對模擬器不是很有研究,
! s  O5 n6 u6 ~$ e2 Z雖然要了解源碼內容,可能不是很困難,
* `# N$ U. `) B( Q( U" g+ z* s) v不過還是要花時間,個人目前蠻忙碌的。# ^* A0 ^, v' z$ {0 C4 L$ l0 L

8 a6 O& M/ v" X. h) J% c% W給你一個朋友的MSN,你可以跟他討論看看," N" w; t1 d5 Z2 l3 t/ i! L" V
他本身是程式設計師,也對FC模擬器很有興趣。
. g* V% t) F& ]* q7 E4 [
, ]4 c  m# l5 r5 ]3 x9 {' gMSN我就PM到你的信箱了。" f4 N! o( i& j5 ^9 J
9 V* K2 F8 d2 `: A  u* S- d5 S% r7 N% p
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# |0 W. @8 X. I7 V呵…… 谢过团长大人~~

% v% }8 {. E) W: E0 i3 D" C5 M7 o5 s1 W: p# R2 m
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
6 N0 C2 q& R# b: D团长的朋友都是神,那团长就是神的boss。

+ v% P2 U; H3 ^8 m/ A& M: Z$ y: b哈 不敢當,我只是個平凡人,
# n& k. F; w5 W- z' q/ }* t& t要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ P) I% t: j, `ZYH; F4 z2 m* L3 z3 G# {
QQ:414734306# Y0 _& `8 ]3 U2 N! G
Mail:zyh-01@126.com
& Q' n+ C4 l/ j* r$ W  n# a" B" m; d) D( Y; k  G
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 # n% {/ }1 y3 O* M
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ U, T& O' \$ n# p
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-24 16:37 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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