EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ A6 O4 m' N/ P& T楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 \& P' w9 M' N; H0 q5 N
这里有相应的模拟器源码,就当送给大侠了~~5 Q2 S4 K; E1 A/ W8 M% d
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" h1 n9 }1 _' h( L1 F9 b4 }7 \能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% e$ |4 F+ ^* v  I4 ~
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
- x" K2 }# X) }, a- g& A这里有相应的模拟器源码,就当送给大侠 ...
% ~/ G* Y7 r$ t- X9 Q) ]. f+ s$ J7 y2 l
聲音部分(Audoi Process Unit = APU):1 l" M  A' G2 Q2 R. f( R/ v" S
.\NES\APU.cpp
5 [! i) Z5 N7 i* l$ k; N7 {.\NES\APU.h# P4 ]9 a+ x1 A3 @# f; K

1 W- F, h) V" L; A: m+ d5 g0 |5 Q5 ~8 {: n% m" W# O2 w
影像處理部份(Picture Processing Unit = PPU):: D  h! H) W3 E5 j) K$ J9 Z
.\NES\PPU.cpp
! o* |5 f3 r+ B.\NES\PPU.h
+ w8 q3 r. O& a  C  {2 _9 e9 C" ~' \) u' j& M! X, v
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:, b' R0 l, P6 S
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) z: C" x- P9 o- {% h2 `3 n( N//////////////////////////////////////////////////////////////////////////
$ T  S/ p1 o( `) p//                                                                      //6 N( C7 T5 N; e, `
//      NES APU core                                                    //
' n' x5 w& J) L3 X) Y//                                                           Norix      //
: v- u7 C& [7 j/ [//                                               written     2002/06/27 //
% e/ K9 C( l! E2 W//                                               last modify ----/--/-- //) ]0 I- n" U; C0 H* h# P/ ]' s. R
//////////////////////////////////////////////////////////////////////////
2 V5 r1 Q# S8 ^+ m+ O#include "DebugOut.h"7 [8 e" `# M- A1 e. j
#include "App.h"3 c8 D: A" W% q" a$ U3 `
#include "Config.h"
- v( x0 |% Q8 r! `2 w! Q
6 g( t. B- Y8 [5 J* d  _- a6 D#include "nes.h"1 F9 E1 L: v% G% A9 U, X
#include "mmu.h"
( ~5 h; k, u( L/ g2 r/ P9 c" N$ ?#include "cpu.h"
, c  n$ y% |; x#include "ppu.h"
: g7 u) J( h2 m#include "rom.h"; {' J9 v' c7 S: H
#include "apu.h"
1 e% ]. ~+ D- Q. P. Y/ p. V
6 Q; ~/ x1 x; T7 ]/ |! u/ O// Volume adjust% w, B6 v% G1 C+ t" g( h/ S8 z
// Internal sounds
. M$ @2 A8 C$ q* x3 k#define        RECTANGLE_VOL        (0x0F0)7 w% b8 A1 x" T$ D2 _7 [" G
#define        TRIANGLE_VOL        (0x130)  y: d, i- v. y) d9 S* j3 c
#define        NOISE_VOL        (0x0C0)
( E, _( i1 m- C: A6 f/ ]6 a#define        DPCM_VOL        (0x0F0)
6 B0 ]8 w" C- K// Extra sounds
6 y9 \6 l; s: a# ]. Y#define        VRC6_VOL        (0x0F0)2 d$ B- |. ?3 D
#define        VRC7_VOL        (0x130)
6 |8 d/ P$ H9 U) Z5 z#define        FDS_VOL                (0x0F0)
* C( l( {  E8 j$ A$ t- Q* p#define        MMC5_VOL        (0x0F0)! _- p4 B5 d$ L$ T& r
#define        N106_VOL        (0x088)) I* q5 ]% E- s4 Y3 s9 W, N
#define        FME7_VOL        (0x130)
( \3 F" }  l+ t$ u; H- Z# l' a" a& k
APU::APU( NES* parent )
) k' ?' g6 N# n; b; e& z4 ~& D4 X3 b{
0 q! t: L! G7 U" c# u5 S        exsound_select = 0;
1 O) j3 z# w# l" x6 J5 ^# K' v! ?* [5 Q! z: f
        nes = parent;- R) E& M5 E# w+ g
        internal.SetParent( parent );
" s0 e9 e! u! c* _6 u- a& z6 j" E0 }& O* Y! W
        last_data = last_diff = 0;) s2 ~5 g+ p4 {0 n
; ^- |7 I. X, N: m& @* k$ B# U
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) n# ?9 O* P0 e+ n( Z
. _6 e6 G0 \" ]/ r; N2 l# H# K
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# `" c, T9 j/ j! b3 K0 V# `2 e6 s        ZEROMEMORY( &queue, sizeof(queue) );6 @: Y) F* s: N  G! @7 C" c
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 l/ y! A- C8 N# w  A% w; J8 u9 S3 N# q& x, j; Z
        for( INT i = 0; i < 16; i++ ) {7 u* M: }9 X4 @, C4 G6 I
                m_bMute = TRUE;" B7 m4 L6 Y+ e1 t
        }1 V: g; E' q# S# i
}6 `* Q4 j7 D; _# M- ^/ y2 u7 u
1 J! m1 ?8 |: Y2 ]9 _
APU::~APU()  Y2 F0 h0 i+ p4 z
{
+ F* @6 @9 L; V/ }  h! ~' c}9 @2 }0 ?9 J" i; Z

+ D5 ?# v# b9 H9 _) \% Ovoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& C% Y' _$ P9 T% N; \9 w
{
4 b' p" d- q. q7 ]        queue.data[queue.wrptr].time = writetime;
6 O& P9 m7 [$ _        queue.data[queue.wrptr].addr = addr;( r2 ?3 s5 w/ m1 |5 \4 B! }& r
        queue.data[queue.wrptr].data = data;
# X( L0 _) o% o, U! o) W        queue.wrptr++;0 s3 |0 ~+ t, t0 l6 T- I: Y" y1 e
        queue.wrptr&=QUEUE_LENGTH-1;
7 \4 V& O- p* z        if( queue.wrptr == queue.rdptr ) {
, W* z3 L$ c. e" X# H                DEBUGOUT( "queue overflow.\n" );
3 n" L( i& R( H        }
  u8 l8 G! K) n  V0 F4 u1 y5 J3 }}4 F  R' \# C: c8 t6 ^

( J$ U7 Z: L- q# P; _& h% j- g) OBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
" H( f- q% {9 f. U* c; [: [+ @{8 W2 u' C5 i1 T: H0 \( N! K
        if( queue.wrptr == queue.rdptr ) {
8 c& N" D: d; U2 T$ v2 ]8 S                return        FALSE;9 ^3 E& s4 Q# X7 I+ W
        }
6 D" N8 q- K' J$ h  R6 ]        if( queue.data[queue.rdptr].time <= writetime ) {
8 {5 V; b) a3 T' T* s                ret = queue.data[queue.rdptr];
4 G7 f. E8 y) |  z                queue.rdptr++;0 ^7 F6 K$ R& N- E0 C4 s6 I( Z" U
                queue.rdptr&=QUEUE_LENGTH-1;+ d) V1 D6 Q& I" Y: j8 ]% f! I
                return        TRUE;7 K3 N  d5 F3 n
        }4 G0 v0 n8 U* d; _
        return        FALSE;+ j( v9 s! f3 |% T8 L$ E
}
* D/ e5 J5 L0 O# E# }$ e4 ~" z5 g3 _
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
) ?2 w4 |8 @& |$ U: |; j, C- O) X9 |{
9 F# a% R- t" O, s5 ]0 S7 y        exqueue.data[exqueue.wrptr].time = writetime;
$ T. W) C" m# G! {        exqueue.data[exqueue.wrptr].addr = addr;! D5 ^) b8 p; e8 B. e: d
        exqueue.data[exqueue.wrptr].data = data;
) w$ Y/ [$ n1 j4 ~3 s. K0 w        exqueue.wrptr++;5 q5 [  P/ T. c% s! W' u
        exqueue.wrptr&=QUEUE_LENGTH-1;
0 X" y# i+ c  e! P7 f% F4 J        if( exqueue.wrptr == exqueue.rdptr ) {$ \2 Z/ e  Z8 Y, w8 d2 E
                DEBUGOUT( "exqueue overflow.\n" );# i# R1 z2 L! ~* X( f; d- u6 {
        }4 m! g! w  Y" i3 V$ `) V  o3 m% }9 L
}
. R  {5 U4 C) M; A7 @# S1 C+ I6 Y
& i+ n8 G# M8 \5 t* b: n* IBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ). I. L$ H4 O  _+ Q
{
" Y8 ?7 f3 h; A7 B: O- f. t) Q# ^        if( exqueue.wrptr == exqueue.rdptr ) {' a' u% f8 f/ }0 R, R7 P
                return        FALSE;/ Q+ O4 v3 S9 z# K' j
        }
9 w  s& K' V0 |0 s% N% z/ x( A        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- \2 H- U% q; V. b% s
                ret = exqueue.data[exqueue.rdptr];" C: J/ K: Y7 U7 w7 i6 H  A
                exqueue.rdptr++;
' Q8 Q; a# m2 B) `- R4 J$ a" s" o                exqueue.rdptr&=QUEUE_LENGTH-1;( q$ ]% U  t0 ~' n& \1 u/ B/ `
                return        TRUE;& D5 C* g: t6 R9 }8 g
        }( p+ a! E- B! Z0 u
        return        FALSE;
. l! |7 B  m9 f8 G: P1 [! M  h}
7 M0 B! Z, a4 U" L: l# M9 W
- K% t  @8 {' J  hvoid        APU::QueueClear()
' f! r6 E& i" I( |8 a" B' j{) o1 o' g% A! g) Y* L. j7 o
        ZEROMEMORY( &queue, sizeof(queue) );: q9 C$ a% u9 A' E) F
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& Z) v# E7 \" T& x+ x8 n
}
0 {( F' C2 X: M6 ~! Y( q9 u! c: Z+ C* |2 p+ h0 n- k
void        APU::QueueFlush()
# x4 f+ |  w2 [' M{4 X* z& V: P. x/ ?& X- |- T
        while( queue.wrptr != queue.rdptr ) {4 O7 ]$ ~' T- ?! n" B9 t
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# W. K) f# I+ Y  F# K
                queue.rdptr++;5 F  @8 b- Z. H- i& Z
                queue.rdptr&=QUEUE_LENGTH-1;
+ p. z+ l" |" v        }
. G# @4 N: g! R. m  |/ c3 C0 S. T4 P3 [9 G8 ]1 o
        while( exqueue.wrptr != exqueue.rdptr ) {
, X! H. P* s0 m6 n+ ]' s                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
! [: l* _: g* _# v8 w                exqueue.rdptr++;" E' r7 w3 |: l
                exqueue.rdptr&=QUEUE_LENGTH-1;4 d& ^' ]9 Z2 r- @
        }* v, x- I4 W# i1 `6 q: ^
}
* u3 ^: t( s5 F# G: u& Y  n' |% }. g3 x! l  F! M: I
void        APU::SoundSetup()( E( }. k/ u' ^% c+ B# e! I3 H0 k
{
" e$ s8 T5 b' d8 k        FLOAT        fClock = nes->nescfg->CpuClock;6 M# ~; P3 n" X. }, r* b5 L; |
        INT        nRate = (INT)Config.sound.nRate;7 Y; z* R( P5 G2 S
        internal.Setup( fClock, nRate );
. `( o+ |9 Q. Y0 v        vrc6.Setup( fClock, nRate );/ I& z. [# `& P1 W' A4 H" d9 A
        vrc7.Setup( fClock, nRate );0 v8 X+ J) `3 B+ L7 k
        mmc5.Setup( fClock, nRate );$ \4 \, I- c  G5 c8 O# @, X
        fds.Setup ( fClock, nRate );
9 O/ |' I0 O, O* w1 ~$ K        n106.Setup( fClock, nRate );: c% p. T$ [+ i. ^
        fme7.Setup( fClock, nRate );
8 v" f' `% [5 D7 s! N}
0 `  n; N) L, P) T8 \0 o) Z! ~3 u
void        APU::Reset()
& ~) ~3 A, s+ A4 A. L' J) l{8 `! Q( G7 K8 Y2 _
        ZEROMEMORY( &queue, sizeof(queue) );0 o/ P- `5 C: x3 g$ p+ ]; t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 U! n. T5 t* F

+ N) D) P5 I. w+ I- H2 r9 x        elapsed_time = 0;4 f" I) O) ]4 D; s, b) N

. f( w5 q* N9 M* ?' }        FLOAT        fClock = nes->nescfg->CpuClock;
0 S3 }. S9 A$ B# n" y$ w) P! C        INT        nRate = (INT)Config.sound.nRate;
, e, K6 q; v. l        internal.Reset( fClock, nRate );% F  w! N* T! t* C, a! j) t
        vrc6.Reset( fClock, nRate );" s  G) U* f( R. z
        vrc7.Reset( fClock, nRate );. t5 d. f9 V' V
        mmc5.Reset( fClock, nRate );
+ w' n9 S$ m. ]        fds.Reset ( fClock, nRate );
! o5 L/ F: J- J# {+ x        n106.Reset( fClock, nRate );
7 D- a2 O7 _3 f# m& ]# {( Y. u7 z        fme7.Reset( fClock, nRate );
# {. q- u! ^+ {: ]& D/ V9 I% l* I0 W6 G. z
        SoundSetup();
+ `9 D# a! C4 ~( |+ v5 Z$ J6 f$ x* X}
4 I; F2 s1 B( s; v& I7 i* k5 K
  _/ S* v8 y5 r, `$ A! I2 Mvoid        APU::SelectExSound( BYTE data )1 w( [) ^- j- i) A4 {
{6 I+ D- ^* a' f! R6 B, }
        exsound_select = data;, k! K7 n1 @$ U) Z" O: C( |( {
}4 B# W! d& ^$ f2 S. u1 W0 u

9 k1 {1 l4 G8 j$ fBYTE        APU::Read( WORD addr ); {0 x$ O) y6 N' J: @
{  ?6 ~1 F2 o" w$ l1 X" n/ \
        return        internal.SyncRead( addr );& s$ D9 m. p/ A5 i* K8 E$ \  B
}
1 D; }& ~8 H+ u& O2 m& M" W0 N# l, F+ {8 e
void        APU::Write( WORD addr, BYTE data )% M9 F) p. A: D' \# _# e. X% V
{
4 c9 W; z9 f3 y; a; [7 R; D: T, ]5 U        // $4018偼VirtuaNES屌桳億乕僩% \3 J& F' V& U# d7 |
        if( addr >= 0x4000 && addr <= 0x401F ) {
* d5 ~/ L* i3 X% ^                internal.SyncWrite( addr, data );5 i1 a- I( ?7 {/ K+ ^  z3 o1 F
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );$ X3 T, {' o, Q' Z3 W+ C
        }0 L! E* x" A2 {3 P. e
}+ P" b! x' d2 U3 d$ T4 ]* q  B

6 P  ^+ }8 ?% b, IBYTE        APU::ExRead( WORD addr )$ T5 v9 k% ~) T. K/ |( l$ J9 b+ j
{- H& n0 s4 p6 i
BYTE        data = 0;9 C  m* \  j! s+ {
' g4 h# ~2 G  o5 P' m+ m! t! {1 P
        if( exsound_select & 0x10 ) {
" H' I6 m" ]* k                if( addr == 0x4800 ) {7 y& c* T2 k+ W% N# z
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
! V8 ?6 p) i  I+ F8 y                }+ x/ S6 ]* Y2 C& |8 k9 p( L0 P
        }
/ R$ v' B7 `# q! P, z8 X        if( exsound_select & 0x04 ) {
: @6 A8 }) s, S8 U. l3 I( g8 A                if( addr >= 0x4040 && addr < 0x4100 ) {
+ o1 l5 v7 Q" T6 f4 o- b                        data = fds.SyncRead( addr );/ D/ R6 X/ U! ?+ e/ X; k2 V- l
                }$ ?" q6 r- n  j* f
        }, V$ u4 P3 V6 D/ n, K8 x5 s
        if( exsound_select & 0x08 ) {
3 W' [4 c! m: A3 j( H3 P                if( addr >= 0x5000 && addr <= 0x5015 ) {
4 L, [. {* I3 P$ s5 x                        data = mmc5.SyncRead( addr );
. e) R% F. Y7 P) M                }( K: m) F; Q& q* ]
        }
3 F6 }6 u' b9 e( H% G6 e& `- q! h: r6 y
        return        data;" g0 q& C/ v. n
}
! ?  j: _* G( Z. D% _% G
: b7 W0 x* f3 _0 L5 D$ t' h) jvoid        APU::ExWrite( WORD addr, BYTE data )
8 m2 [1 }- O4 s{
1 ~( u1 p1 u5 F) Y        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );6 Z: s1 N' L8 ~2 I0 p

! e7 o5 M  v4 Y* t- I0 N  v3 L' J        if( exsound_select & 0x04 ) {2 V2 E4 e/ g5 B: i
                if( addr >= 0x4040 && addr < 0x4100 ) {$ g! `5 Y% p0 p! {. a2 X7 k
                        fds.SyncWrite( addr, data );
. C* }! b( Y1 e' N; h                }
5 m5 B! _6 ~  f1 p9 c5 o        }
9 |% z* f9 [1 Y) D  r. `! q. ^8 V9 a& F
        if( exsound_select & 0x08 ) {
" m: R4 O8 E1 F4 X. I0 y                if( addr >= 0x5000 && addr <= 0x5015 ) {/ m% S  M+ c7 s% Y
                        mmc5.SyncWrite( addr, data );
/ X( K- n$ p. V) K. B" R3 m0 p                }
, X/ w  d7 S( y, p# \" J        }- j; z7 Q8 ]: {
}
! w# _4 i! ~3 q& K  r7 a
) y9 P3 @* n; l5 ovoid        APU::Sync()  o1 L. T: l6 m+ q; k1 v
{
7 a9 A+ F$ ]% ~( ^}; ^/ c! M. a* z  Z& }  t4 @

& V; L6 V: c0 e8 J; I4 fvoid        APU::SyncDPCM( INT cycles )% E+ D0 z7 A/ N
{! \9 [$ a1 o0 z% m4 O
        internal.Sync( cycles );
, A, s9 H+ p3 A1 K8 i
/ I& k% v) h5 T9 Y% x3 P2 Y( m        if( exsound_select & 0x04 ) {" t# n# t/ \' K
                fds.Sync( cycles );! a# _# |" A, ]. P, n; e) X
        }9 x. x. U8 z+ c% g+ S
        if( exsound_select & 0x08 ) {
" x4 F* n. J5 m* m: k1 N                mmc5.Sync( cycles );( v; A1 M' q5 D2 D9 Q* g2 ]  G; b
        }
0 E% }: |) M2 X9 A}: K, m( Y7 C+ L+ i* i! m$ G
9 i' T- h/ q) C' z1 @+ s
void        APU::WriteProcess( WORD addr, BYTE data )! I7 ]5 O* A% S6 }4 `: w5 `% n
{
0 s& A  @) f' A: ]* \' f9 f3 Y% u        // $4018偼VirtuaNES屌桳億乕僩: k2 F- T. x0 d) s' H
        if( addr >= 0x4000 && addr <= 0x401F ) {- S! c4 P# Y; R
                internal.Write( addr, data );
- g9 o: |! i5 T- i        }
+ `4 B5 t2 Z% {$ C) H7 V}
4 K  N0 X  H/ T1 v3 G
0 E, N6 w6 j) ^void        APU::WriteExProcess( WORD addr, BYTE data )9 u- |/ ~2 D: `- Z8 t; ^0 Q/ L
{
7 k5 T& W6 C" o3 j. z        if( exsound_select & 0x01 ) {6 T5 e% r4 m0 G9 _% r! i2 X9 v
                vrc6.Write( addr, data );: N4 H- v* X3 V. k/ }
        }' _! b3 Q. ~: i# G3 b- W" t8 u
        if( exsound_select & 0x02 ) {
3 r; h! |& S. R                vrc7.Write( addr, data );
# M% W+ N" q( m% k  [$ N+ [7 O        }
6 A6 k9 x$ H$ V! N/ L        if( exsound_select & 0x04 ) {: f1 s1 U% l( F; T
                fds.Write( addr, data );/ c9 A" ?) Y7 C1 a! ?: B5 V
        }: Q( P5 V: x* l* u5 m
        if( exsound_select & 0x08 ) {
* y7 m# U5 W# V0 k+ P                mmc5.Write( addr, data );
% f, P! q, \/ Y( X! G        }
- h: T/ [- U5 U" s5 D) C9 g        if( exsound_select & 0x10 ) {
  @0 \- M; r  X% M                if( addr == 0x0000 ) {* G0 I# z! Y5 ?% J: G
                        BYTE        dummy = n106.Read( addr );
5 ]. C! s, b, t/ H  Q0 k                } else {
' H$ c0 t) K/ A  o                        n106.Write( addr, data );
9 ~  H* l0 q0 a: \                }& H9 O! Q0 P6 `- N0 h. n4 `- j
        }5 x! m+ e# d$ `; L+ Q) }1 f
        if( exsound_select & 0x20 ) {) H. u( a' l* g& E; m, ~- y3 J3 I
                fme7.Write( addr, data );
) V- @1 u% y) h) G2 `        }- }/ W, ], U6 J+ N1 J' V- z
}
) q& x- G( }+ p0 k1 M9 H" N5 v0 t7 ^; [, ]2 `2 G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 z: r2 K* K* h4 B( _$ Y4 U{
, z; n) l3 b0 H8 k% \* B) NINT        nBits = Config.sound.nBits;
/ b% B& T* O: E3 gDWORD        dwLength = dwSize / (nBits/8);
" `! N! ~$ {/ ?' a+ V. }INT        output;
) U4 _0 B3 K! T& P0 ?' P9 K4 `QUEUEDATA q;
, [  e; i3 }8 Q( @1 X8 Y; DDWORD        writetime;+ u  H, Z. h' n# F
3 z0 R% j7 ?; Q/ w
LPSHORT        pSoundBuf = m_SoundBuffer;
& G& [) \8 v1 s. V1 OINT        nCcount = 0;8 C  f/ ?+ m2 P; d6 D& i' ]7 g) r

2 J$ r0 [) t5 e9 b& _0 s* {- `/ iINT        nFilterType = Config.sound.nFilterType;( m; T. r" a4 s% I3 U) A; o" n5 k
% i4 u# ]6 i6 c
        if( !Config.sound.bEnable ) {
/ v) q9 n  k- s                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 _" Q4 }4 l2 {2 D
                return;
4 g* {$ y# Q& H. I! A! r( {        }  ]$ _! d5 c# q/ A) s

: S0 Q6 H$ P! d: ^# P" `, U. ?        // Volume setup
/ `, S0 ], F, |        //  0:Master
0 @+ E0 F9 B- I3 F2 r        //  1:Rectangle 1
& o1 K7 q2 r+ M7 A, u5 t. i        //  2:Rectangle 2/ E7 |7 @0 t; p' J) O
        //  3:Triangle
* V2 t/ M2 [% Y        //  4:Noise' w" Y' [2 s; G) D9 h1 a
        //  5:DPCM
7 j& b' _) E: d; \7 ~  x% y. }0 C        //  6:VRC6
3 |: `5 n+ @' s* U1 p) _        //  7:VRC7+ ?# s; A. V4 C% o$ [
        //  8:FDS
) F1 Q, q* ]3 f8 _( s: a+ O1 D        //  9:MMC51 S* S( _7 U) H2 K9 ~8 A6 M% M1 V, }
        // 10:N106
& {1 m. {$ t& t* Q        // 11:FME7! _3 R' ^3 u& G. C
        INT        vol[24];
6 J$ b& l0 w0 p9 h        BOOL*        bMute = m_bMute;
6 o0 ]+ j" H4 r" w        SHORT*        nVolume = Config.sound.nVolume;
7 w7 i2 H5 s! D+ K5 R: W/ A5 @& V, |. O* ?/ a0 Z$ {7 w/ D2 d0 |7 ^' v
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
/ X# K" p# x( v, s# \7 k6 F9 `7 ]( `8 U1 n& F% m9 z
        // Internal4 p; {- B; i6 e, a; l- S: C
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 I4 H) O3 z: }! j3 }( x* |
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( D5 A0 a/ P) S* b! \+ ^4 o
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 m+ c$ C  _" Y3 @( g        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' d0 l6 o+ C# Z$ f9 T; s
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) _# E2 U5 |2 u, j& u6 i! ^% V0 \9 [9 v
        // VRC6& }! R5 S6 T# [8 i# U: k
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 D/ y# [  G  ?        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ `" z# z4 x9 \0 n        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 J' A! a  T; }2 r2 v& y9 P9 m. a; _+ w+ D
        // VRC7
: f, \" n: f! E4 R$ M3 ^        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( l, M$ q! Q# C8 Q/ k: [" Z
, [- e9 I: u3 p/ ]! q1 A' F& V
        // FDS: X8 ]- {) ^5 k: `. i- Q
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;3 ?' R" S. O3 f  \4 y/ K9 B/ ?; I
; z) t1 S0 X7 i! ^7 _$ _: |
        // MMC5
6 B; z6 _3 M2 w; K& _        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# b6 z* {8 b4 Z; `4 B
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 I7 C# ?6 }5 B: O6 ]% }. e        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: b$ I3 |" ~! M$ a2 Z1 c
4 A" K: F3 M: n- |        // N106
0 S! g( N: z" [0 Y0 e  C- F/ `' O" G        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# C' r% a8 ^& l0 u8 O8 x3 f; @        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* L& Z9 z! k% L" r( y1 Q        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ k0 i8 H% A6 ]- V. {8 h& r% c6 e
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" n- G# C- @6 c( H
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( i( n% ]! q5 T( ?, j+ j: G) M
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 a7 L3 j  ]! C. B3 t
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 H) Z: f. p6 \3 f        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! [! }# e  T/ e2 s
4 e+ D, b$ ^" U0 Y" x8 d# H        // FME7
& W% U/ X, O$ C5 E        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 x3 a  R5 b+ i! p/ A
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. y# T! T% ^. _
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* G& e# w; B# g1 `" v
0 h" v4 ], q" I5 [, F& ^, W3 a8 B  }
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" d8 D* D( \( r' G* C3 E/ G( K+ u
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 K/ ], O' \# X. w  u1 Q: Y' @+ I2 g
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟! _- q1 K& L3 d3 z  F% J4 ?7 R
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {0 X1 p1 p0 N% P# C4 m+ }
                QueueFlush();! y) A, o$ r7 Z' U" h4 w
        }
, ]( B1 J2 t0 T$ f+ m: \' Z2 h+ Q: L$ m/ h2 u0 g
        while( dwLength-- ) {
! P2 l2 W9 t- A- q+ J                writetime = (DWORD)elapsed_time;
; c2 @6 b# \5 Z4 ^' h
0 x! i+ Y( K3 X9 T/ p( d7 e+ B8 K                while( GetQueue( writetime, q ) ) {
" ?' ^" E3 l' S1 _                        WriteProcess( q.addr, q.data );
6 [3 f& H! y# L                }
: ~: i, j$ q6 ^6 B! X' f1 @' B2 r+ Z4 y0 N' e3 U' X; a" D
                while( GetExQueue( writetime, q ) ) {- O) J6 d' Z* o
                        WriteExProcess( q.addr, q.data );
$ [9 v; j2 k) W$ G9 U, M5 @+ P                }: I3 F* T" k) c$ @3 W% j

) J" ?0 j  B4 @. T% T                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- W& q: x0 Z$ D8 a. _
                output = 0;
' f- j& d" ~4 Z- j                output += internal.Process( 0 )*vol[0];5 B, ?. O* A) p( b( Q4 s
                output += internal.Process( 1 )*vol[1];
( c: e. `, {; t2 s+ c! `                output += internal.Process( 2 )*vol[2];
! h9 c1 z$ P  j4 ^                output += internal.Process( 3 )*vol[3];% @8 M% D( Z* e, X. A
                output += internal.Process( 4 )*vol[4];9 e5 L' k) r8 s3 X% o

2 Q! m  v( Q9 r2 E                if( exsound_select & 0x01 ) {
( `% \8 H. H  G* `2 X                        output += vrc6.Process( 0 )*vol[5];4 `5 A2 V; N8 M5 X
                        output += vrc6.Process( 1 )*vol[6];9 n! S, U& G& X, D3 `1 P; b6 p8 I
                        output += vrc6.Process( 2 )*vol[7];6 U6 Z& s/ @- k7 i
                }
6 w; S1 U8 Z0 b3 V) M" n                if( exsound_select & 0x02 ) {; ?# s+ z1 D3 K4 ]+ m
                        output += vrc7.Process( 0 )*vol[8];
0 w3 ]# S% W4 t. q4 c/ ~2 o                }
& D" o8 g, q4 ~7 s+ K7 U                if( exsound_select & 0x04 ) {7 j: I  o! ?& |  g, L; Y
                        output += fds.Process( 0 )*vol[9];) w" N1 S9 }# o* |
                }: W1 G/ p8 S3 c8 O* l+ C5 a, }2 ~. R
                if( exsound_select & 0x08 ) {4 Y. x8 @2 u& y" @, z8 _* j; \( I
                        output += mmc5.Process( 0 )*vol[10];
5 l' O3 P0 ~1 p8 g% [. u3 J- h                        output += mmc5.Process( 1 )*vol[11];/ D5 r% S( D) ~) |5 S6 |
                        output += mmc5.Process( 2 )*vol[12];
5 Z$ F* Y6 Z+ v9 M% n                }/ O' M6 l; a0 c" w* \( A
                if( exsound_select & 0x10 ) {6 R" p& I/ @0 f
                        output += n106.Process( 0 )*vol[13];' E1 n! _2 W% a# L. n
                        output += n106.Process( 1 )*vol[14];
9 J2 H6 H) k1 g/ [' J                        output += n106.Process( 2 )*vol[15];
% A2 [9 ?- \+ Y" E! [, O                        output += n106.Process( 3 )*vol[16];
3 M* ]4 W9 @: \7 m+ o; k8 E# ~                        output += n106.Process( 4 )*vol[17];7 E# J4 B7 _- N
                        output += n106.Process( 5 )*vol[18];9 [+ k0 [( W3 Y
                        output += n106.Process( 6 )*vol[19];
' \) T1 o4 n5 c) ^" P5 q9 I                        output += n106.Process( 7 )*vol[20];# V: H" ]  D% M
                }, S9 s6 h+ h1 H
                if( exsound_select & 0x20 ) {
  O: B1 g& _; e) X                        fme7.Process( 3 );        // Envelope & Noise
1 g, I7 w7 n2 h7 s+ @% ^                        output += fme7.Process( 0 )*vol[21];
' \0 n9 E/ H% x: e% K$ [! x4 f                        output += fme7.Process( 1 )*vol[22];8 j) A, g- F# |
                        output += fme7.Process( 2 )*vol[23];% T, I8 H3 S+ k. ?
                }' z6 N/ `1 u/ }. P  }, R: S' v

) g; a9 ~% j" l/ C: h8 w3 k2 }' n3 d                output >>= 8;+ f) y4 C7 ?' h% v) }* U: q7 k
! O$ ~/ Q% o* U% f. t
                if( nFilterType == 1 ) {! C! j* O! S9 r8 Z
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 M. F. q4 j8 I6 F0 h- W9 k! x
                        output = (lowpass_filter[0]+output)/2;4 x; h, ?: c) [8 a( b
                        lowpass_filter[0] = output;
% T9 O  y* v% b2 B8 u                } else if( nFilterType == 2 ) {9 _) {& Q6 t/ K, X0 ~  y1 J( i7 B
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 @9 o, A$ e, @# N                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 P% f! M, ~% \8 o( y2 E- i/ X                        lowpass_filter[1] = lowpass_filter[0];+ a/ x! t6 V$ L& e: c+ u
                        lowpass_filter[0] = output;
& W# c4 D" o( d- K- K3 f  }2 o                } else if( nFilterType == 3 ) {
- L3 [( ]3 ?0 l: T# h                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)# G4 H! ?8 B! n1 S0 g
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# x+ Q* }+ V% X& n5 k# J, Q* y                        lowpass_filter[2] = lowpass_filter[1];; i. F! Z2 U! o  s/ _0 a
                        lowpass_filter[1] = lowpass_filter[0];
% b" Q1 V# e- `' R, `7 G. U3 k: i                        lowpass_filter[0] = output;3 x  k2 E( O3 u- g8 d0 Y
                } else if( nFilterType == 4 ) {1 l, y4 i! T% G# a' p7 l  H
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
/ W! ~* P/ ]; \; E2 ~4 ~                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;7 W! Z  q( M: S* Q% J
                        lowpass_filter[1] = lowpass_filter[0];; o) k% |" A* y: N# z" p' _
                        lowpass_filter[0] = output;& j, {, ^" J' I( ?$ N7 K. l& I
                }
( P, T# H0 L. X
" S( u& C" d" S& G+ j#if        0
6 g: C  z1 F1 F: s0 k                // DC惉暘偺僇僢僩0 L6 G% ~9 \' \" [
                {3 T! f) L7 F3 w: H; R, V
                static double ave = 0.0, max=0.0, min=0.0;
* n7 ]" K/ ]" G# {2 R                double delta;
& j5 m6 c7 A* c                delta = (max-min)/32768.0;: n# ~# o2 A1 u: A
                max -= delta;
1 F0 A$ f5 [' Y( b( q7 U                min += delta;
# A/ _) ?4 ~& m: @( }# I$ g                if( output > max ) max = output;  U8 t. Z! p7 P& O1 Y1 X% E
                if( output < min ) min = output;
' j! n/ |$ v+ B. Q                ave -= ave/1024.0;
' g6 n: A! W1 y: z+ c                ave += (max+min)/2048.0;3 J5 ^; B9 E- _2 P2 ^: }' s
                output -= (INT)ave;5 O0 i7 `. A2 h$ s
                }
3 q1 c: R. b- e% A  r#endif
" z4 j9 @8 u% [0 N2 h( r#if        1, ~: t) g' r) e
                // DC惉暘偺僇僢僩(HPF TEST)4 q7 v" t* ]" |8 w
                {
/ f* b& y! {4 N/ e$ Z//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% l3 W+ r7 r/ S
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 t* ~: U# |/ R9 k) x% o& ^                double        cutoff = cutofftemp/(double)Config.sound.nRate;/ O8 s) y3 J1 v$ @! _/ L
                static        double        tmp = 0.0;' l. j! M/ l: ~
                double        in, out;
# Y7 ~& S& a; j' G# Y" V" S, I: S: W  K0 W; S( x" I! L+ ]0 q( v
                in = (double)output;. Z: h* u7 v$ O2 `: ?
                out = (in - tmp);
2 F+ |4 ]; J4 k( i5 |; R                tmp = tmp + cutoff * out;
8 S6 l  O0 o. \8 @$ o: v, l# W! ]! T
                output = (INT)out;- G) y, _2 X' v* v
                }$ h1 Z5 v3 Y! A$ I: o
#endif
. H) Q: W" P" c7 b" U" M#if        0
- z: j1 C  p' |% [* j                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' E( s9 q3 T  Q! }8 y2 f1 `" I                {" a2 P" u# j/ O4 J- Y0 B
                INT        diff = abs(output-last_data);3 N8 I3 X" c% {. B5 m, Y  h- u
                if( diff > 0x4000 ) {7 `" V% v: f; Y( \0 P9 a% x8 d/ R7 |7 a: z/ N
                        output /= 4;( I* g1 K$ X9 ~, G- \) R
                } else
' h4 r. \$ d- X" @7 M                if( diff > 0x3000 ) {8 b; D1 U* u, H! b% X/ [! f# Q
                        output /= 3;, e$ I# p8 H( l& m- B1 N
                } else" U, `' S/ I0 l7 ?1 H
                if( diff > 0x2000 ) {
  w" Q# N" }3 s: c# P                        output /= 2;0 H) |: O# `, F! Z. c: ~" [3 ^) T
                }) F7 w, r1 z- Z8 |5 w
                last_data = output;" a5 B8 P: f! n4 {
                }" D8 u8 G% `1 X% |2 M# e8 o  S
#endif1 y! N; L) O& e9 h) {6 i- R" n4 W- v
                // Limit
+ J1 @) A- y8 V: c+ r                if( output > 0x7FFF ) {/ ?  T8 y9 V) W; a# Y
                        output = 0x7FFF;
0 }; X1 J/ ]# v7 X! T2 S" l                } else if( output < -0x8000 ) {) g: ^6 P; @9 l: ]
                        output = -0x8000;. B9 W; x9 A' ?2 Z6 c
                }
. n& \5 `  q8 e" u9 B% p! L* r' e2 r. {" u
                if( nBits != 8 ) {
) d7 W8 r/ i' e( g                        *(SHORT*)lpBuffer = (SHORT)output;+ m6 l& V* Q  I. [; q5 I! ]
                        lpBuffer += sizeof(SHORT);" ^8 X" ~/ }5 ]1 U+ D" Z
                } else {
. ^% c5 j0 w8 u7 o                        *lpBuffer++ = (output>>8)^0x80;
6 t1 ~& W! n  n                }
' d3 Y7 T# ^  ?2 B4 S
, _: @. ~  |6 o0 U                if( nCcount < 0x0100 )
5 z: }/ ]. s- P4 ^" V. n                        pSoundBuf[nCcount++] = (SHORT)output;
* Q: G- @" V1 u4 L2 ?" V# R* V/ \0 M7 g( d7 u) I% L% F
//                elapsedtime += cycle_rate;
+ X) y2 [4 F' S1 c+ p                elapsed_time += cycle_rate;6 L5 M+ J$ i0 x# R$ \
        }
4 ?7 N0 o9 C' @1 `- S
9 E9 N/ \2 P  o) M0 [#if        1
, ~9 l+ N' ]8 ?        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: A- L3 s5 l; f0 N1 I
                elapsed_time = nes->cpu->GetTotalCycles();/ d4 J: r" H2 b: {3 @# M
        }" v3 R2 j; d! I0 I; Y1 z4 W( p
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 h2 ?5 q2 C7 y" s5 Y( |8 a
                elapsed_time = nes->cpu->GetTotalCycles();
- a8 d8 L$ D4 [" _        }$ U  ^* }$ N# J# @" T' J: d1 I
#else
3 L9 d& h  y7 H+ g* c# W; l2 G8 b        elapsed_time = nes->cpu->GetTotalCycles();
" T0 s1 Q* W* \8 s( _. G#endif& R$ }) H1 f) i6 H  `
}
' @0 p6 m0 i5 D) d# ^7 A* v  F
. b$ i! X: @8 w// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- S* k- j3 M% d! F* }2 b* pINT        APU::GetChannelFrequency( INT no )
, ?$ `' i! A! p$ X{7 y/ |& T* M6 M3 u9 u2 v- ~
        if( !m_bMute[0] )2 K* J% x# t& Z
                return        0;
/ |. S* T' P7 T( U0 V0 I/ x6 Y; d' c
( F; O% f1 N/ M' K        // Internal& u* W: {7 Z( q& D9 |* q: ]
        if( no < 5 ) {
5 V; y5 y. e% z; C1 f                return        m_bMute[no+1]?internal.GetFreq( no ):0;
8 p& V4 n. W4 j/ U: h        }
  x5 i- |+ m! K        // VRC69 y8 K- I/ s  D
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
# `2 P7 w1 M: U% f5 x                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 `% `6 N, Y. M& Y6 \
        }
8 B0 Z! E7 y* c$ z4 @7 H& A        // FDS
9 E+ }: y" r+ d; b4 B        if( (exsound_select & 0x04) && no == 0x300 ) {
1 k* r% {. _0 Z+ [% @) f5 g                return        m_bMute[6]?fds.GetFreq( 0 ):0;# g2 e4 f9 R; a) ^& ^5 j: K. W8 I
        }
0 s" R0 ?( m$ _  M2 {! {        // MMC5& [; ^/ J$ z  c( {3 M* ~
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
! L' ]* ]* k1 x$ K                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 W, y" g9 ~) ]: K
        }
! X( d$ u* B5 m/ q3 _% k" Q        // N106& g6 C6 f! B6 B( x, A9 l
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
  O5 Z/ a0 _3 A8 i1 T                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;1 `& C4 C' O0 B- Y1 ^
        }
* B; d6 g; ~0 B& \+ w& Z% V, S5 l1 `        // FME7) L% ~& j4 p( D8 W# g7 \( f
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {$ G- k' W& Y% `6 u0 s$ ~0 b
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
: t8 V( W8 C5 Q6 {        }
0 ^% s* R& N( e9 o- h        // VRC7
) X. {% c  j* O) F        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: T4 w5 p! [1 E( E* R+ D( U                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- \& F' v" y/ |, h2 P" m
        }
& m0 ^8 [  J+ c% u        return        0;
9 j; ]* |1 N4 u5 P: d; H}6 r3 _* \7 W9 r* x" k  D: b3 G
" S! E! ~: z1 n7 R* b) v
// State Save/Load
/ j( _' E5 [) t# X0 Cvoid        APU::SaveState( LPBYTE p )4 q8 g  z7 N, P4 s7 o) R
{
7 B" M- m, e$ J. U#ifdef        _DEBUG) [+ d! V2 T7 _, c8 V6 n
LPBYTE        pold = p;# O4 T, |# A) ?  ~
#endif
; `" {/ F6 a- N  U2 r8 M) N& S& q% ~& G# u. y2 R; J
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞. Y& H. Z/ {, R( K$ c
        QueueFlush();" o7 w2 w! O( R* i6 k
! \. N2 h% M2 M. h
        internal.SaveState( p );
+ [' s0 x% l" S5 f) ]        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 T8 C$ x- z" M# }- A7 x0 L9 d' a
: N) }& i5 z% ^+ I7 i  ]& I
        // VRC6
, D$ C) J7 R' c" `( Q# M        if( exsound_select & 0x01 ) {: z& Q( s2 q& H* e
                vrc6.SaveState( p );5 g5 O( r6 T$ B9 I: O
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% o( d  Z; ^4 {5 g3 Y1 o# I8 V8 A4 p
        }
1 Y2 n8 ?( g* v; [/ w; [/ v        // VRC7 (not support)
, @# I4 m$ W" i7 n0 L5 u        if( exsound_select & 0x02 ) {
$ j7 c4 ~/ p  W2 I( {                vrc7.SaveState( p );
- g/ |9 y) q  Q5 O! s                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) t1 Q" K, j2 @; x- P        }+ }: q0 S, G: ?& S0 z2 w
        // FDS- o. V) t0 Y2 y3 s9 F5 u/ [+ E0 G+ w
        if( exsound_select & 0x04 ) {
9 K# ]% E' w8 m$ z                fds.SaveState( p );0 \; ?1 n8 v: i7 l: v: T8 {" [) Y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
; L+ x* M/ |; H' c' @: i5 _        }. U7 q$ Q, C0 ^5 M
        // MMC5
, W: C+ y& d8 c3 y3 N/ k. @4 l        if( exsound_select & 0x08 ) {
+ P; j/ M* I! u$ i                mmc5.SaveState( p );
2 B! |( s1 o- q' c                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# ~" i6 W( v9 u5 o0 J, Q        }3 Z" e7 v! N* z9 _8 y# m& q
        // N106' A" B+ E: a* i; Y5 P( Y; i
        if( exsound_select & 0x10 ) {
) y5 `6 M+ B/ s                n106.SaveState( p );- p2 W6 P  b) Z( \/ b
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ H% B! p, G% E
        }
1 P+ \) t( t  k5 R! ~- d( U0 ?        // FME75 X) R8 V% \: R) X
        if( exsound_select & 0x20 ) {7 L1 z) @% [6 y$ I" C
                fme7.SaveState( p );( s7 v$ I0 B  u6 R- H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 ^" t# y. w# R( m: t3 ~) I        }0 a- w% g+ B. s$ R8 F
, D7 E0 @$ h* I
#ifdef        _DEBUG! a6 {- I* L9 }/ l( v; [
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );- Z0 Q- ~4 D: r" ]& m) g) f4 i
#endif
6 m$ I7 {7 ?- V' b: a}5 w6 n1 m9 D0 Z9 e1 J) p
0 F/ d7 |" b) v
void        APU::LoadState( LPBYTE p )
1 e8 H" W9 V" _0 S+ p{
+ }% d3 n% k8 u9 r3 M; z: B        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
& w: A2 o. A. ?, u9 t0 W        QueueClear();
  x2 ^% Q  a; I! O3 b
; G1 q$ ]+ R, o        internal.LoadState( p );
7 w/ P8 a/ g( i, k7 N6 ~5 e        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding' L7 [+ {$ _! m# T  r% ]
; R% H) F& h$ o2 |, b# F
        // VRC6
& M) `# s) K3 M  o, K7 B        if( exsound_select & 0x01 ) {
, ^2 v1 j9 L/ t; V+ C                vrc6.LoadState( p );; y9 K2 h7 _2 w% Y- I8 h
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 d( U- t0 V1 R5 }' r        }
4 ]2 L0 I3 U* C5 Q" b0 l        // VRC7 (not support)
9 s' W3 S! o6 o2 [( S6 |        if( exsound_select & 0x02 ) {
0 ~; Z- i9 [$ Z3 b; K1 z8 c                vrc7.LoadState( p );
3 x- }: u5 T# _0 u$ T# f; }                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  D) a; x. s' }
        }
6 |! o9 j9 p% [2 E3 U0 U        // FDS& }1 q5 V$ T6 F% w9 I' ^/ l& D/ }
        if( exsound_select & 0x04 ) {
/ W" |/ q2 D) i7 ^  ^+ ^. {                fds.LoadState( p );7 T: @. x% L* X$ K# B% R# s
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 \- ~& k. s5 [& x4 @$ c: ]" A- a! Y4 W        }
7 I# S4 B5 t! a- t1 Z3 a        // MMC5
. [2 F/ R3 u2 O0 H( [3 M6 \        if( exsound_select & 0x08 ) {
5 U: ?1 b1 m. j$ `$ a                mmc5.LoadState( p );# s; [6 d$ i& V% \; l
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& ^: v5 |9 _, y1 Z% D
        }+ r8 E# S/ U% M+ M% @; `
        // N1064 d  O  U! a! H: b3 c5 E
        if( exsound_select & 0x10 ) {
+ P: H# t7 s( d9 h. Q/ M                n106.LoadState( p );
& ]1 Y- F% {. [: r5 C/ x- v$ i                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* s! y1 j, P) T/ w- t        }0 W. o  n2 v! u9 L5 Q
        // FME7; H3 s1 D* B, I& Q9 w
        if( exsound_select & 0x20 ) {  i1 i0 [; e3 T1 @& j0 o
                fme7.LoadState( p );  o, T3 `% f2 u( F( s9 X
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 A0 U, |/ P* p6 \# m        }/ i) c0 G# o: z; a. y
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& K  I" B9 I& I( Z1 X- x& T可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。9 S: T9 X1 \3 e" l8 M
感激不尽~~

+ w" |: h7 j& s0 L4 K恩 我對模擬器不是很有研究,
9 ]% L+ @% z1 c9 ^/ Q雖然要了解源碼內容,可能不是很困難,
) x) O6 h; t4 [5 Z- ?! q' Y不過還是要花時間,個人目前蠻忙碌的。
. m( {5 q. |+ z  c7 q$ Y  F) k; |& o3 U6 ]6 f
給你一個朋友的MSN,你可以跟他討論看看,2 |3 U. P2 I3 Q2 J7 f$ K6 I' g
他本身是程式設計師,也對FC模擬器很有興趣。
5 n' N, q5 q1 F9 R7 z  c6 E1 d% s( T1 b5 o+ P) C( I; i
MSN我就PM到你的信箱了。- w0 D( v1 e2 O2 N* ~& i
9 m2 r3 z5 c7 Z. f" E9 P' h# j' X
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 q- b' {. [: ~1 _
呵…… 谢过团长大人~~

9 Q8 [4 N/ b5 N3 G0 u- O+ w+ |4 a& M1 e0 R% l. V
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# q! `& h2 p1 b1 Z. L团长的朋友都是神,那团长就是神的boss。
4 l0 n: }2 N) f# o5 N
哈 不敢當,我只是個平凡人,, V  N8 A, k, f# b1 ?
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙2 O9 z& N0 o/ p- R9 R) F* n1 t
ZYH
1 r3 }" I& J5 @. s: FQQ:414734306+ \1 ~) N5 M  u% M" S
Mail:zyh-01@126.com
; j, Q& E  R7 u6 c6 l. F/ G
& ^6 H. h' R2 K1 Z2 U" Z  p他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 $ R* v& Q0 X) ~* e$ \
再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 ?9 m& b6 W, X8 X不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-9 23:05 , Processed in 1.106445 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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