EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?# g* I5 T3 F6 a3 e0 P( \! _9 ^: v
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 E" H/ N/ P( g, v5 h0 m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 Y) W' J6 ]4 w9 g: j% W这里有相应的模拟器源码,就当送给大侠了~~
( Y+ t5 O7 I, W# l2 ]http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ' u) C9 e; Z2 _% f! g
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; ?" E# Y! p: v楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  m0 t% b% V' A) L0 m: \
这里有相应的模拟器源码,就当送给大侠 ...
3 m1 ]% \) z. r+ z0 b% J9 z
聲音部分(Audoi Process Unit = APU):
3 r# G6 g* g% T% R9 M3 M.\NES\APU.cpp% u: H; i% H8 K4 e- J; f* ?
.\NES\APU.h; w5 L2 [$ V6 z+ t$ o& j7 p' w. Q8 I
9 y: D7 n& |6 ]; C7 O
# d% |: {; y: k0 N: T/ `4 W7 Q
影像處理部份(Picture Processing Unit = PPU):( o' Z2 ^3 r% v
.\NES\PPU.cpp
$ @4 M4 K, N* G9 o( t' _. T.\NES\PPU.h
, X* `6 o9 D6 ~) f( ~; ?" L5 B* w5 c0 ~/ `# _) d
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:+ W1 b- G# F$ y. [( w! y" ]
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 f6 j/ m/ s) |$ M/ g//////////////////////////////////////////////////////////////////////////
; k" r& @1 S, F/ n9 x//                                                                      //' R- f4 N2 b# [8 R( N. m& o2 I0 u( E
//      NES APU core                                                    //
: ^; C* I7 P' ^0 K) _//                                                           Norix      //
. K: M- M7 D0 c//                                               written     2002/06/27 //
8 [* K4 u- ]/ J0 a6 l* C' \+ u//                                               last modify ----/--/-- //
1 x% U: ?  r% k/////////////////////////////////////////////////////////////////////////// ^: l& W1 l& b2 f, N; l
#include "DebugOut.h"
& y0 X( M) A( m- W#include "App.h"$ S' b) c$ u# J: h8 W) l
#include "Config.h"$ p  Q+ Y& C% ^) _4 g+ i
! @# B0 T# x  B5 |5 {9 F
#include "nes.h"- }: M6 {6 t. y" ?9 {* H
#include "mmu.h"  F0 }/ i5 U5 x, D- j
#include "cpu.h"
8 G9 j0 q- v3 |/ p8 t#include "ppu.h"7 b- M0 Z6 H1 [! B
#include "rom.h"" Y5 B* |) H9 H# z
#include "apu.h"- O* h& c" S, V$ k4 L$ ~

7 v' R; {, ~  I! @8 I// Volume adjust) Q( B  }! U) A, o+ U4 V
// Internal sounds
6 d3 [1 H+ p% {% i  [#define        RECTANGLE_VOL        (0x0F0)3 }3 l1 G- r1 K; v7 U( g; F& ]
#define        TRIANGLE_VOL        (0x130)
# T0 j! d: ?) A& ~#define        NOISE_VOL        (0x0C0)7 z2 L5 b9 D1 y! ]" z7 ?) c! b
#define        DPCM_VOL        (0x0F0)) G6 [: O) e5 r' \2 t% X
// Extra sounds
! c, N% ?* l: R, s& ^; m#define        VRC6_VOL        (0x0F0)* {) }( o( D* l/ c1 d
#define        VRC7_VOL        (0x130)
: b7 {- {) g/ a  X; j4 A#define        FDS_VOL                (0x0F0)5 D3 ~$ ?& @* F* v9 L" X7 ^" m
#define        MMC5_VOL        (0x0F0)" j3 C# Z, E0 b# ^) R6 H" t
#define        N106_VOL        (0x088)  R/ a& F3 u6 j& w$ y/ x7 q5 Z, n0 Q; c
#define        FME7_VOL        (0x130)8 }3 z; y/ N2 m0 n9 n
: e9 s' f' D, N) \6 C2 E) w& h
APU::APU( NES* parent )
4 U# @$ r1 ^1 p5 E4 _2 g5 r  \{; K4 ?- T' {4 D3 W/ R
        exsound_select = 0;
5 b' _; B( ~  e# F4 B' C9 k& x4 b7 V& m# i( a' l& F9 u7 G; d4 e
        nes = parent;9 a1 ]* h9 e  J+ q* l$ a
        internal.SetParent( parent );
; c( R! a; t( k; @: h6 d, O" K: t1 [8 \0 \9 T
        last_data = last_diff = 0;  p8 |/ ~. o/ A7 M9 H

6 d% k5 g  n  h% s        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 v' r' n6 _8 k! G/ E+ c

  f' h. y9 x( w( ^* c( t: j        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );4 \4 u& [4 k& J3 \- }- X
        ZEROMEMORY( &queue, sizeof(queue) );. y/ x" a7 ^; F% ]0 K; h' s
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) m- \" |  T3 q8 C
  u% X* q; F# a8 Q/ \
        for( INT i = 0; i < 16; i++ ) {
% j5 J( [6 `6 @# u                m_bMute = TRUE;
- T0 G% T; r+ F: [5 J% O- z6 z        }3 f0 C! d3 @, W1 {" ~
}
  Q1 i9 Z3 ?2 o& {4 ^! L
% O; H+ p7 A7 L& U2 o/ ^APU::~APU()9 s- T) H( a% W1 w7 q
{" r6 c8 |/ [$ ^* T8 h/ l9 C
}
5 n) p# e# U3 b
6 G( N8 ?3 P* w2 Wvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& t# @/ o0 k. T1 \6 K$ H{
3 ^0 S  y0 p; h+ q' O" I        queue.data[queue.wrptr].time = writetime;5 l6 |! p0 w! C1 f- I. G! G9 k
        queue.data[queue.wrptr].addr = addr;$ `) l9 D3 b- _# R! S1 b
        queue.data[queue.wrptr].data = data;9 ~7 ]5 l7 w- h/ o! T2 ]8 H6 O+ Z
        queue.wrptr++;
/ e2 Z( z) `% C8 _. X1 ~( P1 j        queue.wrptr&=QUEUE_LENGTH-1;% l+ G) ^$ d( P$ U( b/ g
        if( queue.wrptr == queue.rdptr ) {
$ o1 A9 g1 U" x# c4 @  N                DEBUGOUT( "queue overflow.\n" );
' T! X$ \# ^3 r, J+ l        }
1 Z% D0 y/ y6 M* }}
' n# G+ R, v% q0 d% l
6 i7 O" i; p  b; e: ?4 Z' \- bBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ }! g; P* y& z1 H: \
{1 s( @! M* V  F$ a* X( T3 e. P
        if( queue.wrptr == queue.rdptr ) {+ D6 \+ _. c) d0 i) ~
                return        FALSE;
0 Z+ G9 b& d7 |$ b        }2 ?7 \6 s% X2 }* r0 e. ]
        if( queue.data[queue.rdptr].time <= writetime ) {
% k7 Q. D2 W/ x0 v% m& v, h& u$ D                ret = queue.data[queue.rdptr];3 s8 B' C1 ]# E% Y4 j6 J
                queue.rdptr++;
& O" [5 R. s, `0 C                queue.rdptr&=QUEUE_LENGTH-1;
6 |  v9 H8 B: J                return        TRUE;$ @5 e: T6 Y# {6 S( ?' {; s
        }, g" h9 n1 c, b7 o  a: U! L
        return        FALSE;
# U( P4 o3 X2 R$ A. h& S- w}
6 s. ~/ {7 X& X3 b
  E: Y* S- X2 l: Yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
6 w# y  N7 y" q6 X, W{
; T# U/ r" g+ m8 E0 F8 B" P        exqueue.data[exqueue.wrptr].time = writetime;2 n4 H8 |5 R* P2 F+ e
        exqueue.data[exqueue.wrptr].addr = addr;
7 Q. E( h+ b) X! Q        exqueue.data[exqueue.wrptr].data = data;9 C6 u% P( O  i1 |
        exqueue.wrptr++;
; a* {9 N. w% E        exqueue.wrptr&=QUEUE_LENGTH-1;
4 W+ g) E+ F5 N        if( exqueue.wrptr == exqueue.rdptr ) {! P  p6 V0 D$ T& r6 h
                DEBUGOUT( "exqueue overflow.\n" );% h) U9 z2 B0 p7 f* q( ^8 D" m" @
        }* z7 u' l  b% @
}
+ |6 T" p; c7 _/ @
2 p. c2 n2 u& v7 X+ {" CBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 {" e' O! X2 b/ f3 b7 \  n
{
5 L( e9 Z+ v1 H5 o9 c' C        if( exqueue.wrptr == exqueue.rdptr ) {/ X, I& `" I4 k5 x3 {9 {
                return        FALSE;
. J" E9 j( [0 m0 P        }# T. I: J  `$ ?' C+ \
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
5 u" _  o" l, B; w                ret = exqueue.data[exqueue.rdptr];( a( Y2 {" X( a& y- M
                exqueue.rdptr++;
0 m9 ~1 ^' z  u/ U: z2 C                exqueue.rdptr&=QUEUE_LENGTH-1;" v7 e9 s; n2 X  p/ l9 C2 p) ]
                return        TRUE;
) l7 i; }* _" ~& q2 G        }
: e$ s9 {$ g( P1 v' M. r' N, e        return        FALSE;
0 E' S: s! s! y}
' i: t: h# h! s. U  G6 }" R, S* f) S
void        APU::QueueClear()$ I9 ^. t- y3 {) e! [3 i* B
{" F3 w$ z4 D/ R# J  {
        ZEROMEMORY( &queue, sizeof(queue) );; w& z1 ~5 V  X" ?: q! Y! ]
        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 t' H4 q3 Z9 f8 {
}% G8 E0 V4 V4 l
6 p" t) p1 G& ?: v
void        APU::QueueFlush()
+ o) G! G: n/ D7 Z: _- m{2 V$ }% J$ T6 E, @" V9 G
        while( queue.wrptr != queue.rdptr ) {
9 y/ S! z- ~! |                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );* x/ ]0 U5 y0 @, C4 D
                queue.rdptr++;
* X& _8 K5 p9 [; ^) v  n5 m                queue.rdptr&=QUEUE_LENGTH-1;8 y+ `* \* |- _+ B9 ]7 S5 L
        }9 y  L% D0 z* [8 O6 D. Q
* T7 r6 c/ `, t# J2 A. Q
        while( exqueue.wrptr != exqueue.rdptr ) {
4 V$ a1 D% s+ K; r$ M8 t' r                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
) p2 N6 d. u- Q                exqueue.rdptr++;! @; U! [& l: r
                exqueue.rdptr&=QUEUE_LENGTH-1;
% k( A0 u7 M+ \        }3 @. k( h2 n  w( T
}- \* q" ^7 x" B0 w' x5 m

' W, s8 C% v4 Dvoid        APU::SoundSetup()
- c0 ]" b" X3 F' H4 a{
0 v. K$ k5 V7 C2 S        FLOAT        fClock = nes->nescfg->CpuClock;/ V  C; J' m: ?: v! c" Y4 T1 A
        INT        nRate = (INT)Config.sound.nRate;
/ {2 ]- i% g- k( s; O6 b  a: D) N        internal.Setup( fClock, nRate );( L! R! Q" U* d+ e2 t0 X
        vrc6.Setup( fClock, nRate );% H" \3 {; L1 {: s' q/ m
        vrc7.Setup( fClock, nRate );. Y+ l: l- p7 y1 Z: [& R% f4 D8 v
        mmc5.Setup( fClock, nRate );# ^- M" u8 {& P& x  V: \0 j
        fds.Setup ( fClock, nRate );
7 p  e0 @1 t% b+ }5 F        n106.Setup( fClock, nRate );
& _* \7 {% Y- C+ d% j6 H        fme7.Setup( fClock, nRate );$ p) e& y) \0 _- n+ `: P$ B/ P
}1 K( T5 A- [* y7 y

' G! m: f' T7 M- `8 Svoid        APU::Reset()
+ j0 l' C: s! u. p{; r- s9 S( f1 J* h8 W; I7 t! J
        ZEROMEMORY( &queue, sizeof(queue) );% V- `- U5 ]. J7 @- [" a/ z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: F- s7 i, ^" }1 G; U4 g& d/ @' R" J
        elapsed_time = 0;$ Q0 B' L% L3 A: c  V
) t# D  `$ I9 n2 V/ O. w$ x5 Q
        FLOAT        fClock = nes->nescfg->CpuClock;7 B* h/ G4 Q% l6 R8 s
        INT        nRate = (INT)Config.sound.nRate;
. f/ q7 G+ `1 x6 W        internal.Reset( fClock, nRate );2 j" J6 [4 ^5 E. y
        vrc6.Reset( fClock, nRate );4 X& u: S5 K; T6 `- |' x" x
        vrc7.Reset( fClock, nRate );  b# l+ K" u9 D8 O) j; z' m
        mmc5.Reset( fClock, nRate );& `! D9 O$ t$ ~: L
        fds.Reset ( fClock, nRate );( y5 `& S* k- l3 y2 _' K
        n106.Reset( fClock, nRate );4 @7 q6 J( l) [5 i8 W
        fme7.Reset( fClock, nRate );
8 N: d4 l" U# Z8 E6 m8 Y/ p: z+ x; k% ~
        SoundSetup();
3 \7 d# o1 y/ f/ _}4 F: I+ i1 w/ d! S
* I% u* ]+ g( l
void        APU::SelectExSound( BYTE data )
, ^5 q1 m6 l0 e. a" Z& c{
5 e" H# E$ B. _+ ?, O        exsound_select = data;
$ j. L6 H" X2 U6 x/ ?% E4 n}
& I7 Y1 U3 \' e' Q; e6 v% e$ l# a2 ~& [8 X( l
BYTE        APU::Read( WORD addr )
; z8 F2 s0 v9 O1 J, k9 z8 `: t{
4 X+ `, a2 Y8 k        return        internal.SyncRead( addr );
8 [# E0 h: U( a* F+ ~1 D}  C* a4 o$ s% @  j* o+ {7 W* u7 f6 A

* h- ~! i# ?! z7 f2 V# uvoid        APU::Write( WORD addr, BYTE data )6 D) _4 U( j4 S
{% o4 i+ e. O. e8 E
        // $4018偼VirtuaNES屌桳億乕僩
. P: m" y1 t' b% i6 ~        if( addr >= 0x4000 && addr <= 0x401F ) {
5 T. h+ n+ c  F* k                internal.SyncWrite( addr, data );4 |, ?, O4 {0 n3 K1 i
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
5 U2 |* n0 u6 i9 ^( P; O4 y. X0 F        }
, c9 ^( g4 w1 J$ e4 A}
5 V3 s+ _- U: x& _* x- p7 X. X+ N- r* K: d5 M
BYTE        APU::ExRead( WORD addr )! Z" k/ @! a8 a* V; |; p% |6 o
{) |0 r1 v, E6 T) R, {
BYTE        data = 0;
2 ~3 l7 S- \8 c$ Q" W* G% A+ }6 P2 A4 |& \
        if( exsound_select & 0x10 ) {: y! ~$ V; W8 z( N* J8 |: c; l
                if( addr == 0x4800 ) {. |  @9 M% z: a9 Y) |  y: L# O
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
- _# t* @' z! l- _" C! p                }
6 z0 m$ B# @' e9 d0 {+ g+ j7 b        }
/ i: ]5 o- b( h; h: L# j8 W* ], V        if( exsound_select & 0x04 ) {8 f- L$ e4 W" f: v1 g! o
                if( addr >= 0x4040 && addr < 0x4100 ) {
1 ^, e' E; O( s* H2 d, S# J# A8 @                        data = fds.SyncRead( addr );
; I0 Z+ }  Q: X( ?. e1 G                }( N' }. d0 P! M4 v! ]! Z
        }/ U: S# c6 A5 Y$ b4 I; S5 g6 E+ h
        if( exsound_select & 0x08 ) {! e8 M' D4 V# D8 b; V8 V
                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 Y$ Q; B& r" X                        data = mmc5.SyncRead( addr );8 a9 N4 N* w8 C2 p* K4 f1 Z
                }
3 v# X1 A$ i* M, l8 |+ c" m$ V" H' Z        }5 k1 P8 t4 K* L2 g; L
, D" \" l- d/ R& ~! q4 j- U
        return        data;
7 r% B4 q( [8 L5 t7 l! a. m7 T}5 H. O5 E# |) m6 ^, D

" O* u; C% a5 w/ V& k+ G0 g: v4 P' h# hvoid        APU::ExWrite( WORD addr, BYTE data )" X9 G$ i; A) O/ j
{9 a3 s2 b/ w. P
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; _' ~7 b* h. Q+ z8 [
; J9 z- a5 a8 c( ~        if( exsound_select & 0x04 ) {
+ Q5 X7 C  G2 J, F                if( addr >= 0x4040 && addr < 0x4100 ) {% ?# b5 [9 s& `! }( S, z  N
                        fds.SyncWrite( addr, data );' t' ]7 c3 B- g; a& Q$ d4 ~
                }
7 t- R7 o+ V- ?" N3 _1 S        }
$ X# e& \. E: t# C9 N
  I, J1 X# M1 m. J. Z        if( exsound_select & 0x08 ) {
% z+ H# F% _* i9 |' G' I/ o                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 t+ W7 w, O! b                        mmc5.SyncWrite( addr, data );
+ |) I! b+ R- Y) P; V8 p                }2 g) W! j  Q1 }: I, @( B" V/ ?# h
        }
  a& n; o1 D; n}
) U1 S3 T2 r7 y: s  n& K2 j+ P$ W" }+ v0 ^$ Q
void        APU::Sync(); f/ e) _: c; Y
{
# L- P3 K; V/ q% C}
9 c! X& Y9 L) u* _# R$ o5 G2 q/ Z) F; j, O1 S% v  H2 K  _# Z
void        APU::SyncDPCM( INT cycles )
  o5 g4 k& E+ u) ~" y5 ?{5 J% g% S- ^+ t) r% p
        internal.Sync( cycles );
8 M2 U8 O' B1 x7 N; |/ A! R
, Q2 e: a. T' }5 @# q        if( exsound_select & 0x04 ) {% O' }5 }, Y, ]& d0 m+ z" o
                fds.Sync( cycles );
( Q3 a, u- J( r! @2 Z0 Z        }( v1 h0 h( m) y) I: t+ d# Q
        if( exsound_select & 0x08 ) {
! s5 o% |8 c" m* r( u7 V( {+ b                mmc5.Sync( cycles );
4 v% ^5 r% a! n7 _7 U( v        }$ ~( F% ^( K$ L) w3 j/ D1 Y
}" I) b2 F; x+ _/ p* g: g0 W" Y

; i0 @7 r: j1 mvoid        APU::WriteProcess( WORD addr, BYTE data )
/ v. L# G3 j1 P9 S{5 I* d4 [3 C) X& @7 X3 g* B
        // $4018偼VirtuaNES屌桳億乕僩! n0 B- D' v( i: P7 v7 b
        if( addr >= 0x4000 && addr <= 0x401F ) {! v& N& M; i' [8 l
                internal.Write( addr, data );7 w! J2 J6 \4 i
        }
' a2 u* ^6 A; C" J}3 ]# O( N- T  ~

. X) w9 p) k# s) W3 A/ z# @: \+ `# \void        APU::WriteExProcess( WORD addr, BYTE data )
7 }4 S7 T1 b) f. l& N{2 @* t3 p8 ~+ q. r, r/ V
        if( exsound_select & 0x01 ) {" ?6 D3 i9 B# ]( T8 _) H' M
                vrc6.Write( addr, data );
" T, ~- Q- [0 o5 f$ I9 p' v! e        }1 ]8 S0 d* ?/ o2 x6 c+ L: ?* ?
        if( exsound_select & 0x02 ) {
3 P& D& u# k9 N! G                vrc7.Write( addr, data );9 U$ S7 g. B& Q+ Z7 p4 R( u
        }* e( E7 [% q" ?. m+ L+ m1 E
        if( exsound_select & 0x04 ) {
& c8 B. O# G% }2 _/ u* E. Y" A                fds.Write( addr, data );# L5 U. C7 @" ?$ e' g, m3 x, ^; n
        }
3 y6 s" a" a$ O* R: e        if( exsound_select & 0x08 ) {
$ |+ r$ M3 P- t  g9 G3 I                mmc5.Write( addr, data );
( p- z0 H2 @, ]7 D. M  ?0 {! f        }0 L) t6 u9 d- M
        if( exsound_select & 0x10 ) {
0 i! S2 A+ U$ ?/ i                if( addr == 0x0000 ) {" j; Y- U  F3 A% B3 p
                        BYTE        dummy = n106.Read( addr );  K; n7 q/ h. n' R7 h
                } else {. s. ?2 Z9 W. R3 r: b8 _
                        n106.Write( addr, data );* |5 n: ^1 V, [# w
                }
3 x% u- F2 l) j, P3 ^        }
. r+ c& s4 i# l1 |        if( exsound_select & 0x20 ) {4 v% R: _: ^- L0 u3 {
                fme7.Write( addr, data );( w6 O/ w* w9 p% d; m0 l
        }
8 E( ~0 Z8 p5 M! O}; L/ S3 T6 I7 x  S9 M! C# q
3 d+ g' m; @8 M4 ?/ F. _: p/ o( i4 h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )! Z3 i# u3 P7 G$ s( ]6 E2 [
{* Q+ Q8 S% d5 c& M' o, ]9 ?$ o
INT        nBits = Config.sound.nBits;
$ T  b& u. x: U0 q: o3 I! dDWORD        dwLength = dwSize / (nBits/8);
8 e3 Z  C9 }8 N$ Q8 G9 p, hINT        output;2 x% `, Z: W- W5 M
QUEUEDATA q;
9 o" t: Y: |! _DWORD        writetime;# x; Z) N4 y5 P6 L

9 L1 O# `7 c! G: `& H/ S* G+ zLPSHORT        pSoundBuf = m_SoundBuffer;
+ \. o& ~% p5 `' |/ X' ?INT        nCcount = 0;
+ V+ \+ B- n& {& _3 f' U( @$ W8 G& q8 E7 j# \" V
INT        nFilterType = Config.sound.nFilterType;
# s! v( x4 ?8 ]9 t0 b1 W/ J- Y4 ]4 N  F: S& c2 k6 Y! U
        if( !Config.sound.bEnable ) {+ `. ~  W( x+ N+ r2 e0 ?) r
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
) m8 k6 k2 x  \6 q* I; B  d8 U# k                return;
$ m! D7 {7 e7 j        }8 E8 Q- f+ I- A1 w4 D8 F, @
0 j3 @/ @, T/ j' M4 M
        // Volume setup! O  M* T6 M9 Q
        //  0:Master
' i$ h* a( j/ f: n        //  1:Rectangle 18 J. v  O+ |" ^) s
        //  2:Rectangle 2, D6 f/ S" G: F
        //  3:Triangle
) B  H) P0 h9 B) i& C' j        //  4:Noise, c  n% n$ B$ m- N
        //  5:DPCM/ N' u/ j" h' x. d
        //  6:VRC6
+ q. ~/ K* A' `  s0 {, I, J4 J        //  7:VRC7
( Y" X# U2 X# E% ~2 i        //  8:FDS% a5 H* t$ h& a3 d% Y
        //  9:MMC52 c$ ^$ f# Q. H; o8 f) H* R# q- K
        // 10:N106+ c' G/ S8 {; j+ O+ {
        // 11:FME7; I) V9 B9 k" f# u9 m% A; H' B
        INT        vol[24];
) O1 E, \: l5 ?9 t9 [        BOOL*        bMute = m_bMute;& R1 Q6 {3 U5 p" n5 k# e
        SHORT*        nVolume = Config.sound.nVolume;
+ m) C6 E* N5 `: ?1 u& f& C
1 p* S. \8 n4 A+ Q+ c: P" p        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
. `, U8 E# B' O# Y6 N8 X
2 n3 b7 A- S8 K' B; N        // Internal
" u, ^* W, Y! R        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: E+ r( ]+ A7 ~
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 a6 L2 b; E  q: F
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;/ E1 ~7 T  L. V0 j; Q/ |: N/ O
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' g/ h! R3 L; p9 \; g5 I
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, a) y( g$ [$ [3 `9 t

: c4 }9 h5 s: b3 s        // VRC6
* ?; f8 H  z* P* k/ J2 S, @4 u- A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) _% o* d, y& g( a7 ~  w5 w$ z        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 w0 u- D- p; U& [0 `" W: K
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 N- Z7 ~; M" D- D: v3 T
  C5 ~# P: i, ]7 o" |* ~
        // VRC7
/ L" E- U4 ~1 _% F: c# }        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 n0 {1 n8 ~, R  r

( a8 \  k$ w# e8 W3 Y4 U( `        // FDS4 R0 [- d$ e5 ]) l& V- ^9 {/ G- g* z
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ R; ^& z9 p4 M3 r3 }+ F2 X
! i- K) F' D8 \
        // MMC5
$ u4 s6 v6 V4 @2 P, K$ q        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 D) g+ S! [% N1 \, L* F7 w! t        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  B5 g* D' ~2 v0 C+ h/ a
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# Y8 z2 W2 _) ~4 a3 ~# U9 P3 T; Y1 x2 V- M
        // N106
1 n' q% }8 z7 C- m* R: Z        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 ]5 f1 }9 D7 r) C) w- s
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! N+ t5 Y5 ]# H+ a0 _; q
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# C8 `( E5 l& V3 Z7 _
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 T; z  n( P! d8 [* S5 ]
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, T" E6 Q5 {- ~1 y
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 R$ _& D4 C) L9 D+ J# X        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 m5 h4 ?; i/ C" C- r$ x
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; A" ~5 ]; N8 ]( b- _9 @6 H% G5 [2 d9 S8 v5 N: g( c
        // FME72 f! p/ P2 i! s+ q
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 u/ ~% ]9 ?9 ~! s; D5 R# c
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 S9 f$ l# H' M
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 I8 ~* K3 r' w# j" s% m# [
7 a) x7 }. X$ d+ V
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
+ b9 v" r/ w/ ~) `1 ^7 j        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 f! K! ~# I& V

3 ~! T- L5 W, t$ Q7 N' L& ?) b- }        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ p7 ?* s1 X8 N" U) }
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
9 N# e0 S" K( @) L" p                QueueFlush();" V% J6 ?$ }) p0 k  \
        }
" o& U+ f# u$ Q0 R
, q- \4 J0 ^1 O7 t/ Z7 `& {. L        while( dwLength-- ) {
0 p- r/ _3 Z" i+ S0 r                writetime = (DWORD)elapsed_time;
$ x- f$ O7 F! X+ S
0 J5 f' Q( v9 D* A8 N                while( GetQueue( writetime, q ) ) {8 V4 v( _- e& M
                        WriteProcess( q.addr, q.data );: ]' U: N; a* L: k
                }
) ]6 Z$ V3 o" f- R0 N& a# L- ~% j1 K! n+ t
                while( GetExQueue( writetime, q ) ) {
7 t$ X  d, F; S& z6 F                        WriteExProcess( q.addr, q.data );; [6 G/ b: B1 Q) F; m  a: h: A
                }2 H3 E# k& n6 |7 Z% Q2 r. D
6 g4 X3 H- o4 C" w
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
1 h! Z4 t$ \$ r1 Y/ l4 a3 r2 |. I                output = 0;
. T# P3 P6 s: Q! g/ D" \! ^1 Z                output += internal.Process( 0 )*vol[0];
7 M: u$ [" a) ^! e* B& C                output += internal.Process( 1 )*vol[1];
+ G$ D0 W3 |* M7 j, A                output += internal.Process( 2 )*vol[2];
8 G  I5 f0 i: ^: D* F                output += internal.Process( 3 )*vol[3];/ G- w- i2 n) v" E, o  H
                output += internal.Process( 4 )*vol[4];
. F8 b& ]1 u- L, s- E) h$ R- ]3 ]. c8 s
                if( exsound_select & 0x01 ) {
) N/ t2 Y$ U/ d1 H7 G                        output += vrc6.Process( 0 )*vol[5];
7 o6 ]+ Z+ p& V5 g1 g7 Y                        output += vrc6.Process( 1 )*vol[6];" M7 P) @9 y2 R: I$ @: _% U
                        output += vrc6.Process( 2 )*vol[7];' V# u* ]/ O: \; c5 c
                }
) Y( `" s. A' p& C  w, K& @                if( exsound_select & 0x02 ) {
% l$ `2 P8 z% C( a, F                        output += vrc7.Process( 0 )*vol[8];1 p3 U; x; }4 Q+ O7 p
                }  a* `7 b8 n% ~! V9 M& M. O5 n
                if( exsound_select & 0x04 ) {0 b3 Q; l  J, h* \, E5 h
                        output += fds.Process( 0 )*vol[9];
8 ~3 o  w& t- p$ I( n& _6 c                }2 G& C, C" V+ S& P, w& i, w4 L  j3 e0 p
                if( exsound_select & 0x08 ) {9 c/ d) P7 m/ d
                        output += mmc5.Process( 0 )*vol[10];
- n% s) F  ^2 z* {( l6 w' |: c6 `                        output += mmc5.Process( 1 )*vol[11];
% [( _' F- A0 \' L+ @. W: l                        output += mmc5.Process( 2 )*vol[12];
6 _& p3 J; n3 `" h- f5 q3 T                }
3 \4 B9 ^" U- E" i# g                if( exsound_select & 0x10 ) {
- v  [( q3 u7 h3 u9 C5 R$ ?( _                        output += n106.Process( 0 )*vol[13];* S' }* w: \: N' F4 M8 u6 r1 ~
                        output += n106.Process( 1 )*vol[14];
: T8 s9 G1 u1 V8 N                        output += n106.Process( 2 )*vol[15];* j' e/ |8 m! \/ S9 J& C
                        output += n106.Process( 3 )*vol[16];% e6 K" D5 B& N8 H
                        output += n106.Process( 4 )*vol[17];! R0 c1 i5 x* o8 h" _  p9 C
                        output += n106.Process( 5 )*vol[18];
+ N! h* W6 q$ O' ]0 ~' v( K1 J                        output += n106.Process( 6 )*vol[19];0 v: U! i5 i$ _" D% C( z1 @
                        output += n106.Process( 7 )*vol[20];3 I0 o( k. z: S2 e. E3 [3 V* i. S
                }" w1 _7 H+ ?$ b) `6 D& u
                if( exsound_select & 0x20 ) {
5 f5 ^4 L0 {  x- l, d- ]5 H$ o7 g, V                        fme7.Process( 3 );        // Envelope & Noise
6 f( v& L) Q9 P  g, Y9 x2 @                        output += fme7.Process( 0 )*vol[21];. j" _: }1 ^7 x6 n3 h9 S8 o
                        output += fme7.Process( 1 )*vol[22];. \6 ^$ m. |' c( k# }7 g
                        output += fme7.Process( 2 )*vol[23];
" [4 m. O) Z% `4 ~& i7 Y9 ?                }
- \9 h& R( U+ f' Q4 a3 i: ?9 ~2 F; p% {! j1 Q  [) h) U
                output >>= 8;
  }" r) x8 j3 v# L9 g$ Y1 {# d( v' ]3 ?9 K1 R
                if( nFilterType == 1 ) {
/ a  V& H9 B$ A' G1 ]                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& {/ ?, b" ?% k  |5 b3 V+ w5 t                        output = (lowpass_filter[0]+output)/2;. ?* l5 K  v* Z- B0 }! i+ N
                        lowpass_filter[0] = output;9 Y' D& H& h6 F; q/ O' p2 u
                } else if( nFilterType == 2 ) {
2 v* s! T4 u! F% p/ Q                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)! d+ _6 R& Z& ?: S& u* ~% S
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;2 D. M  F8 |( H# v& @5 ]0 D* m- M
                        lowpass_filter[1] = lowpass_filter[0];
4 Z& _7 V' z* J* w1 T6 D                        lowpass_filter[0] = output;
3 d! m$ g0 o! r& a; h                } else if( nFilterType == 3 ) {
* B4 L/ \' m7 h  n                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' I; h6 S- D6 C$ r                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
* @- L  `# D' {% |' X4 L$ X" o                        lowpass_filter[2] = lowpass_filter[1];
. W- s" `* |; D) f                        lowpass_filter[1] = lowpass_filter[0];! r( ?% u. x1 V# d1 e
                        lowpass_filter[0] = output;
0 o2 W1 X7 z' C; N! y5 N* ^                } else if( nFilterType == 4 ) {4 ~: V  a8 {+ ]4 `
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 O1 V  q$ s; n/ g8 P) b                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' N: w5 u: i8 d6 l, p
                        lowpass_filter[1] = lowpass_filter[0];
" v0 Y7 o1 t3 a. x& m                        lowpass_filter[0] = output;
  O4 D, ]" H; q$ g) X3 Z                }
) d6 S8 h# y7 V& j, c. d/ {6 j% x
#if        0
, D3 ~, T, e: C1 b                // DC惉暘偺僇僢僩$ U2 A4 s2 ?2 o0 u, V1 G
                {
# r% w& N& c$ A: t9 ?8 J                static double ave = 0.0, max=0.0, min=0.0;
8 ^) `0 s* i+ o* }5 i& R# R                double delta;" {4 g( K8 E# ~4 n
                delta = (max-min)/32768.0;
5 X$ z. ]& u0 [8 w, ]                max -= delta;5 x( f7 F3 i9 v/ s. i3 N
                min += delta;/ T8 C' k; K+ x9 S1 @3 _  k
                if( output > max ) max = output;2 X7 Z+ n9 V0 e; n
                if( output < min ) min = output;
  z0 W3 x, {1 |% }* ^) ?! r                ave -= ave/1024.0;
# U4 G: g/ w' m# B; z7 l- ]' k                ave += (max+min)/2048.0;/ b. f8 v- A( h+ u( A  {
                output -= (INT)ave;3 [1 w8 B& m6 p+ z% h4 O
                }  V; G3 Q9 \* J8 M2 H
#endif+ P# v1 b0 t+ Q& }, h* ]2 v
#if        1* {2 p2 P5 W* [( R3 j4 x
                // DC惉暘偺僇僢僩(HPF TEST)
9 \$ ?  J* [+ P8 B* P3 _' a0 z                {' R) f3 I. \$ b' s
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 W! z  p/ m# Q! S7 n* q
                static        double        cutofftemp = (2.0*3.141592653579*40.0);/ r$ l! P& z  b0 K, ?
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
- \% `0 W. r) K" u  O5 K6 {9 G                static        double        tmp = 0.0;
# b7 l/ E& W1 b6 E  r( q                double        in, out;
( D  n" f5 V; m3 Y( o
) x& c! d0 U  s- s( O7 F9 V                in = (double)output;3 }0 R  W7 {% C9 b$ Z6 r
                out = (in - tmp);
/ o4 t0 |$ D' A9 }+ [2 j                tmp = tmp + cutoff * out;9 r, Z; P- [' g

3 ?( Z' e& L9 |; A1 i* I                output = (INT)out;
9 S) y9 Q' G) o6 S( Y& e                }  o% n* i; P: X# i
#endif" |  a. D) A& T/ M  f' C9 [! z
#if        0+ G$ Y* C; X2 Q9 r2 |
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 r- [; U5 ~( l' _/ F! R
                {
0 a* }& N1 m1 z8 v                INT        diff = abs(output-last_data);7 M' J/ U* q; r. l( F: t
                if( diff > 0x4000 ) {. a/ q7 I( v$ H7 n* @
                        output /= 4;
' m" E$ m( F) u7 w' t                } else
: Y1 ?  \; |5 {$ [9 T                if( diff > 0x3000 ) {
+ r5 y; K1 d* k                        output /= 3;
' W  }& ~! J& x3 h+ _0 M! ^. \                } else. i+ o+ k1 E, N
                if( diff > 0x2000 ) {8 K6 z' m$ J# X6 @' E5 u
                        output /= 2;
' z* {9 {7 c4 X7 ]: Y" N                }
% V3 f* @9 Q, u$ _+ N# `5 q: b                last_data = output;( t2 u2 O" T+ H/ I* w
                }0 z5 P* }: a9 T) Z6 C9 t4 o# A
#endif
5 ]8 z+ o5 x3 [) J                // Limit
4 k1 i4 I8 B4 K% f. R8 }0 V                if( output > 0x7FFF ) {+ n, D- B" F. u! ]. L
                        output = 0x7FFF;
6 k& Y: h1 N: `' z" ^+ k                } else if( output < -0x8000 ) {& F( c' _: ]1 v
                        output = -0x8000;: U& o, K4 ~0 E+ h
                }. U$ d- G* ]; f* t. u/ W  n

6 b0 e: }) J) B! _. [# Y                if( nBits != 8 ) {
9 v6 a/ K$ ^+ p. a4 C# Q4 h9 l                        *(SHORT*)lpBuffer = (SHORT)output;
! J) J- @+ ^6 r" {$ n4 A* F/ r) ~                        lpBuffer += sizeof(SHORT);4 Y- T+ X5 z/ h" B, a
                } else {1 U8 p7 U, x6 E5 N# d2 Q
                        *lpBuffer++ = (output>>8)^0x80;2 ]( C: d2 H% {: I$ u; s
                }
! c: q. A0 ~4 U4 S) N8 @0 ~4 M7 b; C9 B* H5 @* P# a$ c+ \' ?
                if( nCcount < 0x0100 )
1 O5 O! C& O7 H# U9 k; g5 W  Q3 _  t                        pSoundBuf[nCcount++] = (SHORT)output;5 k9 f9 q- j' {2 e
$ q# s" r! y) p! \6 u9 m" D
//                elapsedtime += cycle_rate;
3 @2 B+ C4 ^: C  J4 ~/ x                elapsed_time += cycle_rate;
8 C& {  u9 _3 @$ W        }
( J- Z3 I$ ?2 z  I- Q* T! ~: L7 X( a- c' r( s
#if        1
& V5 L. j& P/ ^, h3 U        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {  `0 X$ V3 i, g* I5 _% T
                elapsed_time = nes->cpu->GetTotalCycles();5 R* f4 J& f% k+ C' i  S
        }
) g- ~( C1 V4 F        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: F3 c1 D) t% h1 F- N/ f                elapsed_time = nes->cpu->GetTotalCycles();
7 e. g0 O1 z, i" V        }9 I) F! E# H! ?
#else5 L. n6 C( F* g5 p
        elapsed_time = nes->cpu->GetTotalCycles();* M6 P+ N$ N4 i  T
#endif
1 Q* j( y8 O( F5 `}
; y1 q; R+ \8 Z
) j% o( m/ I- i4 H0 X// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
% S1 b4 |6 R8 E# f# I3 w1 Y5 V- r- bINT        APU::GetChannelFrequency( INT no )
' m6 t; ]* ?/ ]. C- M{
1 q* I. \0 G; q& I        if( !m_bMute[0] ), R% M* u9 {$ i- E' F( x: h* W+ e
                return        0;
, x4 a9 A5 E* z2 t8 P( \
; j/ e  h( C0 q: ~5 S+ B7 j        // Internal
) f7 P2 x# t* y$ Y3 u1 q& ~- p        if( no < 5 ) {
  e: @: ?. n, t# I" Z1 e                return        m_bMute[no+1]?internal.GetFreq( no ):0;# W7 `& y2 ]/ |: D7 u
        }- X8 a  S: k7 `, F7 y1 N% @! L
        // VRC6
: c9 t. e1 n6 C/ d1 f9 G        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 p- Q. a, T% k+ w4 S/ U
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 w4 f" W% ~  y$ P
        }- I) K: W6 ^) d8 U  h
        // FDS0 M, H" G( y3 L
        if( (exsound_select & 0x04) && no == 0x300 ) {
* R- n( m3 e2 D. t                return        m_bMute[6]?fds.GetFreq( 0 ):0;5 M  ?/ Y: d; i6 {7 M, f
        }
+ F' B' ], S% d) Q% c9 t        // MMC5( ~8 i$ Y# \/ t
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {, c: k. R* L6 k2 I, [$ R
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
  b8 C. r  |. [1 ]4 ^9 v9 |        }) R* ?$ e1 g& J  d
        // N106
- y# p% X' j$ s5 {8 K* |        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* B9 s, Y' o1 l. r1 H
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 W" ]% E6 Q9 k: z  L
        }
0 ~( v4 D5 B$ m: _. d& e$ Z        // FME7
; [" B8 \# q( ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {0 }0 q/ \' Y0 H* x
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;: l  \/ ~; P# A$ P: r
        }
2 D5 q# m0 ~, M        // VRC7
9 q+ H" A( J6 t4 H  o" R8 Q" K) R$ b        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! t* I6 o* E' _3 L! ^3 L
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;6 Y$ {; c/ a# a) ~$ b( S0 g
        }
/ [  ?3 a# |9 t8 U$ t        return        0;' ?5 Z, v' u3 \- Z7 ~; l# \
}# `/ j+ ?  |2 `# n
! ~' W! j4 }6 r- G" l" L/ Q
// State Save/Load  \7 e) N7 s8 F8 M4 H  v
void        APU::SaveState( LPBYTE p )' H$ @$ [2 A3 ^& u
{
! I+ @! V1 d' {8 b+ c# l/ q7 S! q#ifdef        _DEBUG4 e7 ~$ B7 E( C
LPBYTE        pold = p;/ T. u* q5 ^3 }7 o2 }  K6 R! y
#endif
$ ^. `+ H/ u& g- k4 G' K# _( y/ |: \, M3 ~1 [
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& f$ x& ~: J7 L$ ^        QueueFlush();
, y, k, Z: u) I! ?2 {; N; {( }
3 K6 u7 l# V0 J+ @8 [* y7 s        internal.SaveState( p );
/ v& S9 A- U$ c        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* t, r4 d! \! P% N) g, S5 F; ^2 b) Q
  `/ f, h; m/ a. E  v        // VRC6
' I5 ]+ C5 M) G" @  g! {2 h        if( exsound_select & 0x01 ) {
$ i9 g; Q. Y6 ~9 m8 X7 s# K" w                vrc6.SaveState( p );% N, x2 c7 A! O0 u4 O
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 e- K2 N% k# \8 `# L        }( E) p7 v2 f- f% q+ r$ K8 u: x3 U
        // VRC7 (not support)& R% n# n6 ]9 h/ Q0 i
        if( exsound_select & 0x02 ) {
4 {" m: c5 T/ y                vrc7.SaveState( p );6 T# e2 f! o% i5 r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding8 M- r( g( G( _7 r
        }. u8 I  T2 V% |* F0 K! v* @- j
        // FDS
0 f. J7 S7 m& ~1 u2 ~' X0 |        if( exsound_select & 0x04 ) {4 ]1 R( Q/ @4 s; H
                fds.SaveState( p );
! q9 e9 T: h5 v/ V2 D                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. q9 c2 n/ ]) e) l; H3 k. r/ v        }# x( S2 Q/ B$ p+ x
        // MMC5
5 z0 S, f: I* T9 R0 N! D+ \+ S        if( exsound_select & 0x08 ) {: _2 B% ?$ i& p5 p5 \% O2 M
                mmc5.SaveState( p );/ `" \3 N9 n0 G0 T/ k7 p
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# a" V' H# ~9 ^! d7 s
        }0 U9 g0 p3 i! \% r
        // N106
8 Y/ K! v. E+ y3 i2 U  ~        if( exsound_select & 0x10 ) {  b& W$ f- X- O' ^8 S
                n106.SaveState( p );8 `' m! C/ [+ c- w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. F  `4 N1 p( [' }. x        }: m2 Q; l0 n" r
        // FME7; N* D, D% d3 E8 q/ {& D; \
        if( exsound_select & 0x20 ) {
  h" k3 ]7 j, O9 i+ z* s                fme7.SaveState( p );' v/ C: P. ]7 {; z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. P2 z3 t4 w. M. s
        }
: |( n9 r1 x; X( d- m0 f$ p" g- u( d* f  z, q2 u: G
#ifdef        _DEBUG5 U  G0 z1 T0 M' \) M
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ A2 x5 u1 m, r. ?1 G# I0 U& y  J% Z#endif: Y" o7 K3 B6 m: l/ N
}' a/ E5 ~" _+ ~: X6 [

3 p6 r9 [4 x+ y7 O$ Z9 hvoid        APU::LoadState( LPBYTE p )$ B% i. @5 x. ]5 d
{5 u, d2 e2 u+ V
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡8 v# Q! s6 t" @& Q* Z
        QueueClear();( Y9 U7 A. p, @3 C4 }4 K' O# R
% _! w2 ^5 K6 }3 R8 y+ r
        internal.LoadState( p );
+ w$ q' q; ~7 X4 @6 p        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. r8 ], @6 z2 ?6 G
3 P0 J4 Z5 f# W, J* b( R
        // VRC6/ m/ U+ N" B5 c. z/ c0 f# W
        if( exsound_select & 0x01 ) {+ T! ?$ y! H' E) x. ~
                vrc6.LoadState( p );
, N$ D+ e2 S! l  A: L7 G. S                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 q3 o) Q* X9 \3 _9 ?, D        }
' q! F: N3 g+ r6 u0 |9 q3 O) n        // VRC7 (not support): s' H# H: W5 F  Z7 K& f
        if( exsound_select & 0x02 ) {
2 Q. b" N- ^5 Y6 f+ |. z                vrc7.LoadState( p );- J0 R' z8 Y- u6 T" p
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* h, E- J8 p+ v& ?' b
        }2 d$ N+ g7 ^- ~
        // FDS$ r" O0 a5 Q8 i6 ]1 @0 V  y( `
        if( exsound_select & 0x04 ) {
* b8 u  O, J1 q- o8 |1 ?: C                fds.LoadState( p );
0 u/ O$ m; `/ o  z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 z) F. q9 M/ }
        }* c5 O* H  o8 C1 x3 I4 m" t
        // MMC5
( R$ D. e! e3 \6 ?8 c- g! ^1 a        if( exsound_select & 0x08 ) {
9 n# s! N7 W" \1 {2 U( f                mmc5.LoadState( p );% j$ L1 \( P+ t* N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; j7 O# A& }% S' t        }
- M8 d- O+ f$ b9 K3 p        // N106  A7 I0 J7 u; ?
        if( exsound_select & 0x10 ) {* K; x6 o  n) \; D% o6 p0 c
                n106.LoadState( p );; ^! m# \3 A5 Y' _5 z( a( Y
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 N6 z& N: z( _/ q4 Y* w1 M        }8 p1 S7 n+ u& Q) n9 ?
        // FME7+ s# m' e. G3 t+ k
        if( exsound_select & 0x20 ) {) t. _. W" x' `( ~1 F' }: a9 o4 k
                fme7.LoadState( p );
0 ]$ b6 P$ v9 p+ B1 ^7 \                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding8 Q& I. U! F! o/ R
        }: P$ t! K" d/ i5 p  C  [. u
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
) W$ Z  y+ }$ Y. w) ~3 L1 T可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
# Z9 a6 Q1 `  }7 l感激不尽~~

" Y: }& j! I" f5 W- |9 d恩 我對模擬器不是很有研究,. L- Q0 y+ v$ v* O
雖然要了解源碼內容,可能不是很困難,$ T5 E, ^1 w2 q6 Z9 ~% e! Y( \. G
不過還是要花時間,個人目前蠻忙碌的。  D: B/ l6 Z: |: _

2 e/ g# d2 t( A( T0 H4 R給你一個朋友的MSN,你可以跟他討論看看,
$ R( R! f8 {9 F& c/ c$ c1 y5 N7 t他本身是程式設計師,也對FC模擬器很有興趣。
& o: a! z& C) ~8 r0 h
! [6 k& V) ~8 Y  jMSN我就PM到你的信箱了。
4 x7 ~4 v6 s" R9 B
+ J* m- _" m7 Q2 K* {. h5 v$ g' d希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ; J7 ^" n4 Y8 Z/ U
呵…… 谢过团长大人~~
$ q  w3 S. d8 F' h- o
% U+ h1 F2 M0 v* M6 f
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 " x4 m) m2 ^# h$ }7 M7 e
团长的朋友都是神,那团长就是神的boss。
# a+ C# ]( z6 S6 S8 m6 t9 P
哈 不敢當,我只是個平凡人,# v' N: Y/ s" W$ N) [
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
7 d' }. h$ k+ G+ GZYH3 a1 `5 s5 Y0 f4 N# P
QQ:414734306; |3 L! L9 n/ P. `' Z& e$ M
Mail:zyh-01@126.com- b: i9 M  P; \, q* M$ h0 E

! _; x) X7 N- R* C他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
& Q( z; n& J0 D8 F: g5 h再次对团长大人和悠悠哥的无私帮助表示感谢~~

3 r( r( n! J: C  b$ L不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-29 13:29 , Processed in 1.110351 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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