EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
8 H/ C4 z) @2 [+ g0 e% ZPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" b5 c! [7 o' l( W# C8 H9 S楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! v8 I4 Q, R( Z% w% {1 O这里有相应的模拟器源码,就当送给大侠了~~9 N7 @7 |- ~& |3 g' N
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 o9 c) K% J6 @) ?能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" z9 r, |) B% |! H( L6 A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, N! K& }) a' z8 H( t- _  ?这里有相应的模拟器源码,就当送给大侠 ...

3 A& G" y! X) P2 q* N聲音部分(Audoi Process Unit = APU):
. V/ `4 ^2 z3 Y1 }; l.\NES\APU.cpp1 N- h$ Y1 l% Y
.\NES\APU.h' C* g7 Q* ?, f( G

1 D7 K- ]5 {& B2 k# K% S
; t- D+ X# r: }; u影像處理部份(Picture Processing Unit = PPU):
0 g6 C4 M# ^/ Y0 j9 k.\NES\PPU.cpp
+ c5 }+ [( j- r.\NES\PPU.h: e- C5 O( H' s! I0 s  {& j; A

4 u1 {, c1 t( J8 s; z3 s- i  z如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* `8 o/ f! z3 B/ G(由于很多专用术语和算法机理都不明白,所以看不大懂……)& E, L' K; h: q
//////////////////////////////////////////////////////////////////////////. T1 g+ J0 {5 E9 D4 K4 [4 E
//                                                                      //
. X5 d1 F" r+ Q* ]# q$ [//      NES APU core                                                    //- ~- z, d( s/ p% S# W  i1 R/ A- @% \
//                                                           Norix      //
# R* c8 ~4 G# }8 D- b7 O//                                               written     2002/06/27 //6 z6 U& v  }. G3 I- V$ A
//                                               last modify ----/--/-- //. X) V# S0 b* ?7 r+ g6 m0 [- S, I
//////////////////////////////////////////////////////////////////////////
, {6 O( }0 U) P) a1 R* a5 [#include "DebugOut.h"
9 t7 n' E' j2 d, V  ]2 J2 i#include "App.h"0 C) ~: y. E7 ?; t/ I7 H
#include "Config.h"; k: |' t! F) E

0 T! T; }' d( f$ \3 e! P6 \/ G- o#include "nes.h"+ l8 a& }7 W- V3 Q( d: d( X* R
#include "mmu.h"; _3 t/ E8 f8 x7 R: ?
#include "cpu.h"% h8 w1 g8 [8 h8 Y
#include "ppu.h"
7 X& Q9 Z1 c5 n0 {2 ~#include "rom.h"
* o8 ^5 Z6 @5 `) {3 ]9 e#include "apu.h"1 s7 r" O: d; ]  j! D  ]
. H) E4 f: c) k7 N
// Volume adjust
# n! M) X. [. W5 T// Internal sounds" B" m: A$ k$ p/ N
#define        RECTANGLE_VOL        (0x0F0)
* @2 Q" K# K8 B5 t0 Y#define        TRIANGLE_VOL        (0x130)
2 v1 S. i, `% q( Q9 e6 J' S6 A) J#define        NOISE_VOL        (0x0C0)) n! T" M! O% E
#define        DPCM_VOL        (0x0F0)
/ H  M6 }, Q6 y8 w& h' x// Extra sounds
& g$ q: @, V3 Z+ A8 Q#define        VRC6_VOL        (0x0F0)! ^3 m3 q( S3 C# e/ }4 O
#define        VRC7_VOL        (0x130)
9 a( x# k# n$ [8 K4 r#define        FDS_VOL                (0x0F0)
9 R# V, S% F% x# m#define        MMC5_VOL        (0x0F0)7 |, @4 j3 ~) _/ F8 Y
#define        N106_VOL        (0x088)
* Z# S) Y% B* `7 x1 K: F- H9 M#define        FME7_VOL        (0x130)
# R& |/ X6 M8 [7 P' P) m/ C6 l4 R
& F$ k0 b& D! ~) N" N  ~APU::APU( NES* parent )2 v/ f5 i) T4 T) |  r
{
+ M$ A( Z4 s& K; Y: H; p6 v& |        exsound_select = 0;: U) e' O% U$ M: l) L1 ^

( q2 |4 S: H) `) y+ c+ J8 S        nes = parent;
- s4 e0 I9 B7 n6 M  S        internal.SetParent( parent );1 J& z% t( P. l5 c

5 e7 h$ N* J8 @: I        last_data = last_diff = 0;
) t8 p+ H, Z3 i5 i- j. k
4 C. Y- B2 B7 E        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 c" d7 a% j/ [: O: J* i  p

% p. S6 R+ s7 s( M/ b4 u        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( R3 |, a; D! r8 j7 m
        ZEROMEMORY( &queue, sizeof(queue) );* h7 z% H" Q3 R4 n$ F4 S& B; D3 D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ L+ T6 d9 u9 e. E+ k! z
5 h+ Z' m5 K+ D2 ?" F; u        for( INT i = 0; i < 16; i++ ) {
) f- [9 T# C2 A, X                m_bMute = TRUE;$ Y; B1 X' @5 ?4 ~( l: W
        }
; c# }* n; E# @}* _% e! v# s9 A  j5 q' Q* X

6 \6 w/ y) G- p3 E4 g3 gAPU::~APU()
3 J1 \9 k' r  S" Y* h) ~5 C{
- j2 M: @4 a/ \& h}
% J) S2 Z/ w( j, V# R% }" {( A& j3 s. o) {9 x
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )1 n8 z# s+ m2 S/ k5 S
{
. I/ n+ \* w/ h% ]. N# M. x        queue.data[queue.wrptr].time = writetime;7 g* _! a8 k" L$ V7 E8 N& \
        queue.data[queue.wrptr].addr = addr;
4 `# L6 L: C0 P- \5 L        queue.data[queue.wrptr].data = data;/ z9 R& `2 h  P  v7 J1 {
        queue.wrptr++;
  }9 U' U! S" _% O: u" S' [4 U        queue.wrptr&=QUEUE_LENGTH-1;: ]- G. E% v& y9 e1 h
        if( queue.wrptr == queue.rdptr ) {0 Y7 {' M# D7 ]! ]. r
                DEBUGOUT( "queue overflow.\n" );* G+ v  \, J7 {: D$ @
        }
* Z+ B# T, e3 {; `1 \}
" q+ u" E: Z# X1 r# f& \( _/ h1 o' O' o- q( b6 \
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )$ x( L. J" L( g0 F
{% d$ Q. S1 Q- p6 T+ T# d! f
        if( queue.wrptr == queue.rdptr ) {7 }+ _* ?5 y3 R6 j" Q/ B' T
                return        FALSE;
/ h% L, |. x: i+ t# K& P        }% W2 X3 d) r: l2 {8 Q7 c+ t- z
        if( queue.data[queue.rdptr].time <= writetime ) {
9 {: F6 u9 ]2 ]7 F$ G                ret = queue.data[queue.rdptr];
, p+ P9 Q; A* [# a( N. l                queue.rdptr++;$ K  t- _; K8 F6 d# {' @
                queue.rdptr&=QUEUE_LENGTH-1;7 l2 d. p! Q: S' ^; t8 F
                return        TRUE;
2 C' J! k' O5 a% Z7 I        }
; D. W4 Z, u) C, _: e        return        FALSE;
7 K0 h, _+ D2 h3 J7 S" J}8 y8 A& N6 \' T) F  G
6 l( ^9 O9 n6 _
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ): a4 V2 E3 U; m! u# ~" X1 Q$ q
{
5 Q3 C& K$ m2 h9 y1 a: v% @        exqueue.data[exqueue.wrptr].time = writetime;
" N( \; f8 Z1 ?; T  f) [        exqueue.data[exqueue.wrptr].addr = addr;; o. w9 R9 I6 h4 F$ \0 S% j; ?  Z
        exqueue.data[exqueue.wrptr].data = data;
0 K7 T; r: I  E- u        exqueue.wrptr++;
3 y/ O6 u: ~1 _$ e4 e9 L        exqueue.wrptr&=QUEUE_LENGTH-1;/ @( W" M" _# b, d8 k. Z
        if( exqueue.wrptr == exqueue.rdptr ) {* u2 E5 p) g6 C' j
                DEBUGOUT( "exqueue overflow.\n" );
4 N  K! L3 V& L6 k8 w* R, i7 c        }- r5 x2 Z$ K3 u- t6 X+ {# ~
}) l/ V) m* i, a* F( N- r+ B3 c
3 d$ Q; W/ @- p) E) j$ s4 \
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
- I0 b7 K& @8 J{
$ p6 O6 ?9 x' P) y1 E        if( exqueue.wrptr == exqueue.rdptr ) {+ O9 a3 G5 Z$ g; t/ T
                return        FALSE;% E. x+ Q! Y" F3 j
        }
4 o' _  ~! r7 F+ W        if( exqueue.data[exqueue.rdptr].time <= writetime ) {9 A+ d2 D, l9 p& Z
                ret = exqueue.data[exqueue.rdptr];2 ?( d$ ~2 S" Y# x- b5 X
                exqueue.rdptr++;6 a5 U) u. B' w
                exqueue.rdptr&=QUEUE_LENGTH-1;: o% s5 e9 q8 c/ M# n
                return        TRUE;
" H$ [8 t( e6 x: G        }3 ?7 \# ^( V5 f/ o4 h0 p9 Z) e
        return        FALSE;+ O9 Q1 `5 z3 m6 L- L# B- l3 z
}% [% ^& v! R, n# g2 t
8 G. o, z4 J9 Q9 ^5 E- R
void        APU::QueueClear()
" j5 r/ L+ j9 ^8 g{
/ a5 V: U5 h, |. ^0 \0 ]        ZEROMEMORY( &queue, sizeof(queue) );
: |, ?( Z" p& A# t: y- x+ c        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 _* r. A: U, y) R8 G}  w% o/ n4 Z8 d+ n7 ?& s

) v- U/ {- H! r/ w6 u$ _void        APU::QueueFlush()
) f8 M4 Q- k6 I$ d8 ~* J/ M{
1 L% T, S+ p! |, t% B6 L        while( queue.wrptr != queue.rdptr ) {+ {. W1 e, H6 ~( q" D( k
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );7 o2 _6 h/ I' E
                queue.rdptr++;
4 J3 x7 b+ Q/ D$ p$ I# B                queue.rdptr&=QUEUE_LENGTH-1;
6 J3 W+ g/ u$ {0 w        }/ f# O1 X2 d/ ~+ u5 K
. C2 k. d  Y# R% X1 U& X
        while( exqueue.wrptr != exqueue.rdptr ) {
3 r0 `5 c5 u6 X                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. _$ \# d. }0 ?6 b: Z- G' J
                exqueue.rdptr++;8 d0 d5 r4 _2 X  m& B( |
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 [" ^( U  P7 Q! ~8 a* v5 N0 k        }
! r  d+ H2 z' J7 X/ x}
) X; P% D6 l+ H+ c8 l* y3 a( ^6 B& O1 r1 t7 _
void        APU::SoundSetup()
1 ]9 H! O( q( ?( U% b) [; m8 t. w{
% v7 x" S5 {: q3 S        FLOAT        fClock = nes->nescfg->CpuClock;, o! m0 E* d5 W: x' S
        INT        nRate = (INT)Config.sound.nRate;+ z9 X" ?& {% D6 d4 w: z1 b
        internal.Setup( fClock, nRate );1 e9 v/ J3 X6 a1 _
        vrc6.Setup( fClock, nRate );
* O5 l( Y( |, e4 Q0 L! a' y* g        vrc7.Setup( fClock, nRate );/ J) B' n+ d3 I4 T  }7 d, l
        mmc5.Setup( fClock, nRate );
- v# L  l$ e* J3 S4 o0 `        fds.Setup ( fClock, nRate );5 H" i6 ^+ C% |1 D: j4 N' Q7 V
        n106.Setup( fClock, nRate );( Y& C: U7 w, D0 h# b
        fme7.Setup( fClock, nRate );
" z# b+ Z0 O1 [}7 z  k: r2 [8 m6 z
$ ?: z+ q- X7 h0 r; q3 i
void        APU::Reset()
; a  y$ R: Y4 ~; U{
* S5 X& z; t) P2 Q        ZEROMEMORY( &queue, sizeof(queue) );
& |$ ^6 F9 Y, W# H2 E* S; R        ZEROMEMORY( &exqueue, sizeof(exqueue) );( E6 g* u. E/ y1 p

" R/ n2 U: Z7 W6 Q$ G        elapsed_time = 0;# O1 _# h) C/ Z! K) i2 B" m! v
: @5 g" ^9 D/ m, E! n1 p! U
        FLOAT        fClock = nes->nescfg->CpuClock;
4 j0 y  j' ~  T4 x        INT        nRate = (INT)Config.sound.nRate;
7 L" X% D) [- K. c        internal.Reset( fClock, nRate );
. A: F7 G! ^& W, w8 S2 D        vrc6.Reset( fClock, nRate );
2 Q$ a, e& t$ q2 Z        vrc7.Reset( fClock, nRate );* u% Z% [. Y0 v/ o+ \( J) n- M
        mmc5.Reset( fClock, nRate );+ X8 S% x$ ]2 p. y  K
        fds.Reset ( fClock, nRate );0 l4 W* o1 G) @
        n106.Reset( fClock, nRate );
. d1 a  I% _, N( ^! n0 m7 G        fme7.Reset( fClock, nRate );3 ?5 ]. B! M2 }0 W1 ~! p6 W- q

- i! G$ l* o# ]; n5 D7 ^6 `( z% |        SoundSetup();
6 {* g) g  ^# W( Q1 ~( `0 C2 _6 j! f}
; g. k) ?' M* d0 Y4 l7 T% v
/ N9 o) ^0 {# @/ B: i1 N  ?3 tvoid        APU::SelectExSound( BYTE data )
' r0 P( ^0 }/ k/ g* j: |{
# B6 B' `: y* R- [        exsound_select = data;' g% e) i! u0 H8 |
}
# B& ?2 M, {, F4 D7 N3 h
  j: m; v0 {7 I4 l+ S  ?! gBYTE        APU::Read( WORD addr )! s: {0 x  L- Q/ n- t- s
{
* S5 [0 z. t8 W        return        internal.SyncRead( addr );; \0 {) O* c" c# r3 [, z
}) S! \: Z3 [- l0 C

& I0 b7 m/ Z2 ], |/ e. ]8 t8 s) V8 {void        APU::Write( WORD addr, BYTE data )% K$ b# Q5 d2 b
{
0 j, e1 V" `( ]1 Z, {        // $4018偼VirtuaNES屌桳億乕僩
$ L7 I- T7 {6 u! t2 b        if( addr >= 0x4000 && addr <= 0x401F ) {( l$ w+ l/ t, g9 G, [
                internal.SyncWrite( addr, data );
6 s3 t$ d9 @- L9 ~/ T                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% t, @) A- K; V# i
        }7 Q1 k6 z! w* v7 V% I7 i
}
+ R0 I6 z- t8 m* Q, n4 [6 C6 W. Z6 W7 j9 L2 x' w( I# M
BYTE        APU::ExRead( WORD addr )! |: t# \) X: i7 I  @& Q
{5 b2 w* w. w* }
BYTE        data = 0;
5 e$ H+ V0 y2 L; i' \2 D8 ~: I! f; L+ U  b$ J: t
        if( exsound_select & 0x10 ) {4 J7 `# x  `: }# l
                if( addr == 0x4800 ) {$ b+ E# c9 @) M
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* [. A0 S* i/ A2 I# o' H
                }. @% i3 o/ B9 \" Z7 k
        }
& c+ y- R& K( i( C6 B! S  {        if( exsound_select & 0x04 ) {" Z+ R" c% |/ D+ y6 M+ ]
                if( addr >= 0x4040 && addr < 0x4100 ) {
/ Q$ M) p7 d  U( Q4 v                        data = fds.SyncRead( addr );
$ N1 ?3 I& c$ m& e( |; M                }
" A0 L$ N7 N$ v5 p- U1 D        }! |! b) _& h! J
        if( exsound_select & 0x08 ) {7 }$ z# C2 E- y7 V$ P: }8 y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 y1 {% }% T6 N                        data = mmc5.SyncRead( addr );! H: I1 e* S7 G6 S3 _3 h4 u
                }
' Z1 N  d! B9 q        }
  N' x: i0 @' S. F4 ^; Y7 E3 g% f
        return        data;* e5 m' o; i3 ?$ I4 T" B" k! {
}. \, F  I5 d2 z" W
4 C2 w! r9 G/ u2 x  Q* h) d  D
void        APU::ExWrite( WORD addr, BYTE data )  B2 q* V! h! g" x& T6 j  E: U" I
{) j$ x/ y& d: q7 A3 H. h
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );; x- h$ q" q# o1 \& p# F
  p; `$ O0 A8 v. E/ ~/ p
        if( exsound_select & 0x04 ) {. a0 I$ H$ W3 _% S
                if( addr >= 0x4040 && addr < 0x4100 ) {. g1 n  {4 d- N) b& _: E
                        fds.SyncWrite( addr, data );+ @1 P5 p" I$ ^% v" Q  F, V6 Y
                }
4 h) @1 e( j4 `7 h) f+ e4 ~        }
5 O5 L8 R- f8 C1 r& L- D/ F: X- B! g" o! H1 y# H/ c6 n
        if( exsound_select & 0x08 ) {3 u% F9 e/ L) L9 Z2 ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {8 ~5 h2 r% i2 {; @" [' g' W- O
                        mmc5.SyncWrite( addr, data );
) }1 s4 C& V4 b6 I+ i                }
* e8 X. L) R: w        }
# `9 q' B" o& E% C. |" H" F}
* Q* m  @* E  a2 y# a. Y9 j. X
4 l( Y. m, l8 b# F3 A% U% r' ]void        APU::Sync()
. I1 k0 I' I, Y! Y% F2 ^$ V{
) k* H8 O1 m+ j( {& |& U}1 X6 i3 x: O) W3 f7 H  Z& b, `

& d9 f  [' E5 avoid        APU::SyncDPCM( INT cycles )
/ M7 E% t4 b8 ~, i3 x/ b0 y( _{
+ P$ h8 [  e6 f4 v2 [        internal.Sync( cycles );
* q) m. x  W0 ]6 m  Q, S
* q6 Z# B+ g4 p" Q6 ]% B        if( exsound_select & 0x04 ) {; W9 K, f9 v. ]$ f$ s' V; y$ D
                fds.Sync( cycles );
" t) m: Q. O/ @        }
% a* x1 Y/ c% z: ]' D6 Q, @% r        if( exsound_select & 0x08 ) {
/ [( p8 k& U. {! V                mmc5.Sync( cycles );. v$ {. s7 g, U7 P+ a$ O
        }, R8 y4 H# {& j$ ^
}
5 n+ y! W, k# Z3 q5 R! p  G7 o! B
1 r( @7 T9 [: D* ovoid        APU::WriteProcess( WORD addr, BYTE data )
; J& D& J; z4 F) j' j0 D7 p% _{8 y% `! ^3 i6 B
        // $4018偼VirtuaNES屌桳億乕僩
6 h- O+ t& X4 [& f  E/ V        if( addr >= 0x4000 && addr <= 0x401F ) {! _( v$ Z4 }' c
                internal.Write( addr, data );) ?% X& E) Y1 v" _& \
        }
( p$ S& t# J9 @' \9 f}) z) F3 f8 _6 L
; s! P( x* t( i
void        APU::WriteExProcess( WORD addr, BYTE data )
' G$ @. ^; m, r2 i: x4 S, i{
. y' W! F  S9 T# u8 G9 j6 N        if( exsound_select & 0x01 ) {
: v* t9 v/ u* ^                vrc6.Write( addr, data );
2 m$ Y7 K. }# x1 g7 k) d        }
0 C7 F+ m) x: }2 V/ o! p        if( exsound_select & 0x02 ) {
/ O. t1 b; m% {: |+ t1 g                vrc7.Write( addr, data );
: |! q- y# h8 ~. O) Q" V        }
  o2 t: \  Q, L4 H- P  u" u( |+ q7 }        if( exsound_select & 0x04 ) {3 f+ o$ U9 P! y4 T1 U: B# K
                fds.Write( addr, data );8 k) r% B/ [! e/ @! `8 A# |
        }
: T- o- K5 {; @( c        if( exsound_select & 0x08 ) {
1 w; H- S6 x7 ], T. Y+ L( `                mmc5.Write( addr, data );
2 l2 F4 o6 i+ T( [) o        }
2 S" k# F& K; o- ^& W6 ?        if( exsound_select & 0x10 ) {/ |0 E+ R9 \! ~, L$ z
                if( addr == 0x0000 ) {
9 ?' i  P) K/ Z$ D' c9 H6 m                        BYTE        dummy = n106.Read( addr );
4 S% n0 N9 M7 w( |" |2 r" s2 f- e1 ^                } else {, E; _; D3 R( _$ m! R4 D
                        n106.Write( addr, data );1 z3 D2 Q7 W7 }
                }
7 P# ]' ^/ T% E' ?5 h1 L  `        }
: {( ^8 M) g; L1 V- F" [        if( exsound_select & 0x20 ) {( a8 ?- t% q: y/ J0 P. K! l& p8 a6 {
                fme7.Write( addr, data );- s0 W4 ?1 I$ H: q4 @% c
        }/ e1 }$ p! r' v% u: u
}
% l# F# D& s) @# U  B% n9 h  w2 l3 M5 v1 e9 j5 k3 ?6 V
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )0 `  h8 k$ ?$ o" \- `& g
{
- w2 B5 |3 n+ P- KINT        nBits = Config.sound.nBits;
, H( F/ w) S# HDWORD        dwLength = dwSize / (nBits/8);4 C; `; q, O  g: `
INT        output;& A1 ]9 }4 Z( i* }( K* [1 P
QUEUEDATA q;
1 b6 V" k' z! Q' A7 eDWORD        writetime;
% e( p0 {  C3 y
$ L) P: [5 X1 F  ?1 P# `$ ?LPSHORT        pSoundBuf = m_SoundBuffer;7 d- t1 _) l! v6 K* o1 M/ q! s: x- {4 X0 [
INT        nCcount = 0;
; p! h9 _( I4 L. d- H# E& q& d, C2 a, f
INT        nFilterType = Config.sound.nFilterType;. h. J+ D- \5 ?' g( t

8 x, q$ \- ^* d' D8 f: N7 E; u        if( !Config.sound.bEnable ) {6 \# P7 ]6 _: ~) _0 J; k! ^
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
+ L& M3 U1 g1 k  z2 B                return;
7 ^6 a- |5 K' W# M& X        }
( F- V3 U* D. U; _; {1 U$ E* f9 Y4 ~6 i  w# r' |
        // Volume setup. u* h- ^6 S2 R( F( J
        //  0:Master
' {2 p: P. q9 Q        //  1:Rectangle 13 W( \/ \" C' k6 p* b
        //  2:Rectangle 2
( c/ a: H9 q: R. W% i: ?% f        //  3:Triangle
: w( S6 M$ p( C1 U# G% ]        //  4:Noise
; o1 H/ q' \3 ^: |# k( Y& z        //  5:DPCM: \0 `3 n& A$ ~8 C" s
        //  6:VRC6# y3 n& z! R8 b1 o
        //  7:VRC7
7 w' j* n! \" c  q" k9 y        //  8:FDS
) Y  j$ F! U0 m2 q- w        //  9:MMC5+ \: D  ^* e" m: I1 ?$ F. X
        // 10:N106: ~9 p5 N) H; ~6 ]( N
        // 11:FME7
+ c7 }  r( R3 I+ u" H# |. F: d        INT        vol[24];6 r/ C* ?% q1 G  `
        BOOL*        bMute = m_bMute;+ W# o0 k* ?- [! _) ?7 W: m
        SHORT*        nVolume = Config.sound.nVolume;. k* x  Z# M. F( K

; }2 `5 A! h) P8 l        INT        nMasterVolume = bMute[0]?nVolume[0]:0;% M, d5 H  A0 S

! P$ a/ t7 ]# H0 R* N8 O2 B1 T        // Internal* e8 q2 R' Y$ b: g
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 @( \" n% A. @2 U        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  K) P0 b+ L7 u+ \5 W* l
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;* Q3 Y* ?6 A& N1 H0 T
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;! G8 Y1 ~0 ^1 l- H; q# K7 d5 M
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 L4 N, X  Z' H0 H8 U3 [

% i4 ~# I, w' b& k+ M- W* V        // VRC6
  r: @- q" E' J! X4 c        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, Z- w7 f! l  Y# x: K& p
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! B7 q/ l: C! w1 O        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* \, n' Y# m1 u. O  `8 c8 a/ x7 _6 H+ Z$ W2 X5 G( o% }
        // VRC7
1 S  y' D3 |% ^' |        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;& h/ i7 N! Q( t  m# v2 O

3 O1 l3 F. i' ^+ ^) M8 p7 \' P        // FDS, g- U% p5 u2 X' `, d( E! z7 Z0 x
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
% \1 m7 D/ t) _( s, e) J9 r3 N& d5 [$ d' R/ b/ H1 K6 @, r( e
        // MMC5! @/ M% K  d$ x9 D+ v7 Q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 z+ r3 k' z5 e0 G7 F8 u& e" i
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 J9 j" P+ H7 G1 P2 P. c        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( z7 U& C* K4 r  m, z7 n
2 o# J. z" B$ q+ i        // N106. O, Q! ~* ]7 {" D7 w8 ]
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 C% ?3 T% H( C! `+ ?+ K7 o/ a
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 E  _9 c) N/ \( C. T* g
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# G6 m0 M6 k! \+ R, u3 B2 b  a        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ~9 E( ]( N- c3 V
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, f7 u# `8 W# \' U# ^1 \: y        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) x1 N0 E" ^' }8 }        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ R3 c# r% q4 o7 C  l6 P& ~
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ Q) a6 i# F4 V+ \, I4 Q) c
" h. m/ y1 _/ v' ]% `$ h! l
        // FME7( M6 o9 ?3 @3 d" G- b+ Q
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' ^- S" Z% @4 X4 D! D. _4 z6 h        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 c. j/ T  C0 T( s' D3 ]
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, j# T" ]; @, c

* B8 ]. B: M6 r! f* m( ~# Z; j//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
, T/ @# r$ O) i, A! I. O# V/ D, F5 B        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
4 a  ~; w% P5 [& q; T) X0 [5 c- u! k/ r  ^8 ]+ `+ X- X9 p
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
/ `+ R5 P7 _- X, W8 N+ |& U6 [        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
' x" v( S* U$ U' [                QueueFlush();# |, r4 X0 @# m2 X) R
        }9 e8 ?  g$ x- {/ p" D$ V
7 A. I1 p" K, x- F( f( Q
        while( dwLength-- ) {
8 |3 u9 K6 g! X! k" C" G) `                writetime = (DWORD)elapsed_time;
, [9 v7 ~# ~5 E6 r
) b/ H( u0 Q! F1 f6 E/ a                while( GetQueue( writetime, q ) ) {  A  z. x! O/ B6 k( Z( U
                        WriteProcess( q.addr, q.data );( ?$ w5 @2 w; h, S1 Y
                }
7 [5 y; b0 m9 [7 t( |. k- F$ G( D
4 h. d) X( q; p6 z) y                while( GetExQueue( writetime, q ) ) {
1 \3 V" H0 P% \! }0 v                        WriteExProcess( q.addr, q.data );
) E" M/ [5 Q& r( w                }
! l7 Y9 m7 r0 U* f) D: L- i+ V# l
4 L4 X7 P; \3 V0 }! y" f                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! E7 d' t6 c2 q) X
                output = 0;% e+ V2 `, e0 E( ~. o6 |
                output += internal.Process( 0 )*vol[0];
5 V" j, b! ?' L2 ^3 g  C                output += internal.Process( 1 )*vol[1];
4 C0 ]2 m, A. i/ p2 \, P5 H# O                output += internal.Process( 2 )*vol[2];
; m) M& k$ y  n9 Z                output += internal.Process( 3 )*vol[3];
: G2 x3 h$ ]2 J! e. W% T                output += internal.Process( 4 )*vol[4];
" E3 Q7 v2 A. `3 y. C. c" D5 E" l5 t1 w1 Y4 C9 C2 h. p
                if( exsound_select & 0x01 ) {2 }- c. x& l3 F/ G) q
                        output += vrc6.Process( 0 )*vol[5];9 [8 v6 ]' [4 r0 t* s& P
                        output += vrc6.Process( 1 )*vol[6];' c# d6 d5 h4 A0 v; Z2 g, {
                        output += vrc6.Process( 2 )*vol[7];
7 x% m4 O+ G4 ]6 [                }( A0 Q3 C$ T0 `4 {
                if( exsound_select & 0x02 ) {/ c3 Z$ Z5 R- u* j
                        output += vrc7.Process( 0 )*vol[8];
6 l. @. c# D$ b; j% u1 c& r' @1 t  }                }
/ _) p- E: [2 g1 b                if( exsound_select & 0x04 ) {
( A3 X+ V$ l/ G2 H$ Z                        output += fds.Process( 0 )*vol[9];9 r8 L9 y; N0 G% j6 L0 y: f
                }
- \& _9 f: }2 F4 m. s                if( exsound_select & 0x08 ) {' P# L) g% X( @& ]- x  k
                        output += mmc5.Process( 0 )*vol[10];
- Z8 f) l3 v& _. v                        output += mmc5.Process( 1 )*vol[11];
  g. G. a9 L& `* i7 X3 Q+ H                        output += mmc5.Process( 2 )*vol[12];
3 V7 k, ?! @) s                }
, @5 ~* h# ]- r, F* a# t4 [" C/ y5 P                if( exsound_select & 0x10 ) {
8 p8 t. n5 ]! |2 M9 D                        output += n106.Process( 0 )*vol[13];5 C) [6 }$ m; \+ g) m
                        output += n106.Process( 1 )*vol[14];
! {) y3 O" {( W8 Z, Q" I                        output += n106.Process( 2 )*vol[15];
, x0 w5 `3 B& V  |# v                        output += n106.Process( 3 )*vol[16];
7 X$ D* B( ?7 M4 ^+ A8 c% m/ a$ `* e                        output += n106.Process( 4 )*vol[17];
$ @& N0 Q4 u# d# O3 O7 i                        output += n106.Process( 5 )*vol[18];' s1 P! K' j) |/ k, O% y$ h7 `. p
                        output += n106.Process( 6 )*vol[19];3 U  q' c& Z* [! b* F8 ^+ q7 Q4 x5 g" r: z
                        output += n106.Process( 7 )*vol[20];
3 C+ ?# x( g8 x3 @3 S- V+ ^; D/ Q4 R                }; F) ], u1 L* F- s7 F0 H
                if( exsound_select & 0x20 ) {* W0 l# b, _2 F4 k9 L
                        fme7.Process( 3 );        // Envelope & Noise5 N* ~1 K. I; M! r. w: p& [( S
                        output += fme7.Process( 0 )*vol[21];
" G% k4 U1 t3 [. x! O  t                        output += fme7.Process( 1 )*vol[22];6 T0 j3 i. H8 ^  c0 U& X' n
                        output += fme7.Process( 2 )*vol[23];9 w* X7 Y" E: u) T5 k+ ^
                }
: W, N9 @  Z0 }$ j' f
, B8 }: x* d( @( n: x* @                output >>= 8;
; b* z4 \' J% A, W4 A4 r$ m6 t8 p* W, ^: |
                if( nFilterType == 1 ) {
8 k0 c( Y' F7 s5 S, Q                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)" r/ p+ G. z, d, [
                        output = (lowpass_filter[0]+output)/2;7 f. ]( Z% D, C9 Z4 h. Q4 v' l$ L
                        lowpass_filter[0] = output;% n" K+ I8 q6 F/ }4 w
                } else if( nFilterType == 2 ) {' X# q4 J9 n! H
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 j- V% Q) _- N2 O! W, E
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- S1 c+ A) U  f                        lowpass_filter[1] = lowpass_filter[0];% y1 k; H3 m3 t
                        lowpass_filter[0] = output;, ]0 I$ f9 A4 S5 o/ L
                } else if( nFilterType == 3 ) {
% J) I- h7 i. {5 z                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
+ E; F7 L" ?6 S3 j7 t                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* c5 a3 O$ N1 H+ d9 t
                        lowpass_filter[2] = lowpass_filter[1];
& _9 o  p  M& V: [9 D* l0 y                        lowpass_filter[1] = lowpass_filter[0];6 o0 Q! z9 w6 Z" e! Z7 F4 |
                        lowpass_filter[0] = output;
9 F9 X% o/ V( {5 J                } else if( nFilterType == 4 ) {" J- {9 a9 B% z% j' L
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
; }! Y# h! h" e7 n5 r, p" C3 V( Z                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  s% o2 k3 t% `" n$ I% Z
                        lowpass_filter[1] = lowpass_filter[0];
) o8 W$ t- z% s, }' z% m                        lowpass_filter[0] = output;& V( n- o. \( M  z
                }# l% h2 x  |  I. @1 L; K

5 H" Z; S" c1 `#if        0! {' M# j1 W$ S8 m$ b4 F$ Z  I
                // DC惉暘偺僇僢僩& o9 o' M( m8 H
                {$ R0 n# a+ `& w$ l* T
                static double ave = 0.0, max=0.0, min=0.0;
. V3 ~1 w( {& I$ |! D9 Q  w3 ?                double delta;6 L, x# r2 M: s  g) Y! |) ?& V
                delta = (max-min)/32768.0;
6 |3 e. y3 g9 o5 `" M                max -= delta;0 _( q7 E9 _4 s2 |) \* Q! e
                min += delta;# w' |; ]& Q& u1 n. D8 L2 e: ~
                if( output > max ) max = output;
( m# m  W. X0 M                if( output < min ) min = output;
7 l& a, L1 T8 ^$ y  K8 j* M                ave -= ave/1024.0;
" I# a2 e( l3 H+ P: Y# q$ h& H                ave += (max+min)/2048.0;
. K6 @  Q# e& P9 n/ A* M. A0 r                output -= (INT)ave;1 H& c( m( ]; b) s7 ?
                }/ x% x: Q/ Q( w9 T- Y
#endif
0 |/ w% v' W* X& D#if        1
' ^. f' k3 D. o+ _# \5 e9 n                // DC惉暘偺僇僢僩(HPF TEST)
  I9 x  I% \. s                {: Q; k, L  n; b# |8 w
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- V" P9 A5 m& r, m$ ^; y% L# R
                static        double        cutofftemp = (2.0*3.141592653579*40.0);/ @, j9 b5 w' y# N! g
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
% {* p' s% C0 [; G: V                static        double        tmp = 0.0;  L: `" M& c, p% K7 n. j
                double        in, out;( B7 P  R- b3 Q; ^/ [3 Y% p- V- y

% D$ b1 e/ T2 }" _8 u                in = (double)output;
2 ^8 a! r- K  N1 e  J, a; O2 e, U0 S; g                out = (in - tmp);
, p0 S( W; p4 X                tmp = tmp + cutoff * out;
: G: C; H$ @9 ]7 k
; F; _2 Y% F% G/ ?* S; R) K( O                output = (INT)out;
( l4 k# n/ ~& R                }
9 B# h4 h# b) S#endif
& f5 R- t. X8 C1 e8 w4 f#if        09 w% ^. x' J' g3 v" u9 Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)! W3 c; c$ Z. u' h: O4 F
                {1 P6 K- P9 q# W6 l9 H  `" C
                INT        diff = abs(output-last_data);
) ~1 I8 n: x; Q6 G- H! p5 \                if( diff > 0x4000 ) {
2 \4 u5 o0 o3 P/ R                        output /= 4;1 {  d( |* C: g
                } else
5 T9 u/ f8 ^% V) b. Y0 [% g, K                if( diff > 0x3000 ) {  e/ @# T! \1 p8 o& q( n& P& X0 k
                        output /= 3;
- Z5 P3 u+ @0 {* U, P  I# W$ j' s  g                } else$ u0 D* t! |/ U* W" F
                if( diff > 0x2000 ) {  h& D# N8 k* k( G' ~5 Y/ P# `  m1 T
                        output /= 2;
; @! Q9 J4 Z* D3 o* H/ C9 e* e                }
, \! w  R( p* u. D                last_data = output;  T! v# Y: M; q/ L$ z2 Z
                }) w$ _- \+ \' V7 r; P
#endif
  j1 |* N' l& S$ k2 W                // Limit
$ A, [/ `' a( ]' `) h+ D. P                if( output > 0x7FFF ) {) R; p0 `, b. E: Z0 C0 @2 w. [' {
                        output = 0x7FFF;8 D3 ~" a8 t/ j
                } else if( output < -0x8000 ) {( x, r) X: A/ C3 V: J- r% r' [$ X
                        output = -0x8000;. I! j' H' [* Y; t
                }
* s2 O) e2 v0 r" Q* j
+ e3 V2 w5 F9 G                if( nBits != 8 ) {% D" H2 G, P* f7 O$ P
                        *(SHORT*)lpBuffer = (SHORT)output;
  ?7 v. g5 w. r2 ^                        lpBuffer += sizeof(SHORT);! r2 j0 s* p* E6 A6 U
                } else {7 Y" j' S% e$ v( R2 V0 [
                        *lpBuffer++ = (output>>8)^0x80;) m; `1 j& J4 o4 u
                }
, G4 u. U; q; R- G: \" K
7 d2 `/ P; U6 {8 e% A' \; A                if( nCcount < 0x0100 )3 Y) ]# h) q' l- [; m2 ^" U
                        pSoundBuf[nCcount++] = (SHORT)output;
* `  S7 ~6 ]4 _1 |4 D- B- x! W# g  U/ ~
//                elapsedtime += cycle_rate;# E3 c5 \& U5 g9 A1 U8 T/ `
                elapsed_time += cycle_rate;! u% c( J% }1 J4 V  t& {
        }
, x5 t  J( O& @4 @" n2 g  b6 z$ b: y) U) a* r- y
#if        1
, v, f7 L( \& s( P2 r1 ~0 R/ x        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
7 U) m: ^; j( f                elapsed_time = nes->cpu->GetTotalCycles();
8 N$ U& X; a5 t        }& d: L/ W9 |4 `" x8 @$ k
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
% O2 ?& G& b$ i4 g. |( `                elapsed_time = nes->cpu->GetTotalCycles();
/ O4 n# Q% G1 U1 v4 n        }
# A2 l; m& ^% G* D#else- ~* C  r6 `& ~4 w- E
        elapsed_time = nes->cpu->GetTotalCycles();* k5 `2 G8 k% [- }; F- E2 }
#endif: G7 O: s/ v/ i
}
8 @8 l4 X& R5 X& G. Q0 g/ v3 U) }, K( W  f' Z$ [, m% ]3 O
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
% ~% `  A1 w; S3 wINT        APU::GetChannelFrequency( INT no )  v* U2 Y$ d# ]9 P5 k; i
{# T  u! Q5 g. ^+ W& p) k
        if( !m_bMute[0] )
5 @7 @. ^3 |3 p) @( L* \" ^; o                return        0;
1 r3 w& u! T) ~" ^$ \, O/ j. y* {$ G  J$ C! p. ?/ ]# D
        // Internal: {$ a$ m3 a7 z# r& O" p
        if( no < 5 ) {
) B1 f/ [! U( R" R, |3 q                return        m_bMute[no+1]?internal.GetFreq( no ):0;
/ G- u' c: A" k- [8 l        }
' z6 u- J3 M% J# G( t  C& S        // VRC6
( ~/ }9 Y. P  h; \1 R% o/ c! ^- I        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {  w$ F9 H9 }- y! n" z4 M
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;/ [8 Z; o0 R1 S6 p/ Y
        }7 E8 R6 o$ f( V6 C
        // FDS5 ?  K  b' A+ i5 \: U
        if( (exsound_select & 0x04) && no == 0x300 ) {5 w9 `" h2 }9 H* U, w
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- x! S. [0 P& `% G+ K        }
) U, s& e- |. H8 g2 U2 q        // MMC5
% ~" I5 m) k5 f! {9 k* H$ s% M        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {3 Y& `) J$ a  T/ h8 z+ ~" l
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 e+ m3 P! b7 A. E
        }. F% W* E2 U( ^! `( d. m: ?5 w5 q
        // N106, O, d4 o, H" \" [" y* Q& D% p9 J
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 E1 T: V. y* L) p/ \: G& n
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 k0 Q2 z$ S9 x* \+ a$ H5 [        }0 |7 E$ }/ c4 M6 N, l6 t3 r* z
        // FME7+ c6 k6 b7 @3 e3 F! b. u
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {/ Q2 q" o& Q1 H8 r
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;: ^: Z/ D. Q7 A( o. V9 Y- y: |, Y
        }" r# f$ N- e/ X7 g2 k
        // VRC70 T2 j4 L. r+ x  H. z2 B; d
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
( x, n: ^5 m- c8 ~/ l                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;7 f  }2 G6 J2 X7 b* E
        }
  Z$ D3 I; _4 F# X        return        0;- ^) I" A( D! [1 Y
}* D/ v, f8 Z/ w! }! g7 E' F

9 Z8 ^- t9 v5 x: z; A// State Save/Load2 Q7 [! o+ w" w, {
void        APU::SaveState( LPBYTE p )
5 b0 m4 e7 S7 L8 _3 N( j. ^{
$ t7 ?, f' j9 k; Z) \* [#ifdef        _DEBUG
0 X( O' R& P7 e, s/ jLPBYTE        pold = p;
# {+ T2 L3 l' Y* u' L" z( ?# t#endif& T5 W1 M( P$ E
9 M: X  _$ w& K1 m7 x. H0 n& ^
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! R# L; z; u$ w$ o5 N# f        QueueFlush();
4 ?0 A; X" W* ]  b! _1 o+ w
2 W! K7 E7 e. ^! }( j& R        internal.SaveState( p );8 `2 O: T6 _; k! g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: i' {; t4 I7 g( r, c
& B* H; D8 w  a        // VRC6) a. v6 k* V! }% y1 Z, }
        if( exsound_select & 0x01 ) {% u8 ?) P# C) U4 ^
                vrc6.SaveState( p );; F7 J0 x+ v; G5 U$ l' L" W; u( B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 U' T4 E' W. ?8 M+ ^8 f" G        }$ G) U4 E. `7 V7 q2 f" f# x) d4 Q
        // VRC7 (not support)' _( Z2 c$ ]& a6 ?" x- L
        if( exsound_select & 0x02 ) {
2 A1 }9 S% Y" E                vrc7.SaveState( p );
/ Q6 n- H3 V% y! R8 N% j                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 L0 e6 H8 ]6 b) k* h" [; E        }( b3 `2 r% x& Y2 l# R3 O
        // FDS2 a. v3 k5 t, s3 l3 p7 ^# z7 \
        if( exsound_select & 0x04 ) {. P1 k( }! G6 W+ s3 R% _
                fds.SaveState( p );+ |# E, b" t2 W" g. D3 Y3 V
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- d2 C  W. @9 c& F" C
        }
% J% F$ ~( l+ @7 M' o        // MMC5
8 i  ^/ z6 ~+ g8 |( N        if( exsound_select & 0x08 ) {& x, r2 k6 H' G
                mmc5.SaveState( p );! r; C8 X7 D0 a
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: D% I* r0 x$ v6 Z) @& ]: _  V' H        }/ F: n; a$ b+ ^! D
        // N106% e# E& S6 V1 d# s: i7 Z4 O
        if( exsound_select & 0x10 ) {
- D" Z* y1 W% C% S& u8 @4 Q" j% @) p                n106.SaveState( p );" }: \" B8 k9 a1 t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* w: H2 `1 x; {0 E6 c        }% t$ }9 Y# Z$ s  q" x3 N
        // FME7
# ]( Q8 g, |: ~1 w) d# J        if( exsound_select & 0x20 ) {, L* f2 F4 L3 U$ t* v% K
                fme7.SaveState( p );
6 W8 u& d7 r( \+ H$ k* e+ D                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
1 _9 \; o) }& P4 J' c7 N! E4 _        }' i3 v" D8 W2 [0 T# |# ?
' g& v  l2 ~5 T3 K
#ifdef        _DEBUG
+ T* y- x6 w4 K" HDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
1 E) Q( d6 q1 b#endif
' j, b( f0 M+ N' ~}
7 v& j6 p% ^3 ~9 [( V& _9 h" g2 U* Q0 V! V: X4 f# [
void        APU::LoadState( LPBYTE p )
- Q, c& J5 w1 D! h9 `; n{
+ U8 |- T& t3 N8 ]        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 n: P: t8 C7 Z        QueueClear();* L" q& @3 f3 _$ E5 H
" b" B4 ~: m; L, \& c
        internal.LoadState( p );
6 b5 V9 q) Y7 ^& L9 z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) z" S6 S1 T0 M8 Q9 w; S" t: B0 `% z$ W" ]! M8 ~( C
        // VRC6
. t* ]. d" o; O& [8 J8 S, U        if( exsound_select & 0x01 ) {4 d# V* D; Y/ }, m
                vrc6.LoadState( p );
, `9 A; L) q! s! o: [# S- V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 w1 }, s: U1 M
        }, ]+ o% B. Z: S6 b: F3 ?" J% D/ A' v
        // VRC7 (not support), w. j. D5 Y5 x% r( j/ H
        if( exsound_select & 0x02 ) {
" X: D( Z! O; y4 i. _& u                vrc7.LoadState( p );
4 s7 b: D. Z! a0 B, |* A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; a* U/ t! T+ |6 d4 W9 B  N
        }
, _8 O& [; A% n: g- q4 f: M1 e        // FDS
( K8 y) s3 B3 g$ ~1 J5 B+ u" w        if( exsound_select & 0x04 ) {
+ Q3 S& B  B+ r0 z                fds.LoadState( p );4 y: m0 B7 Z+ J1 E. e/ \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 D6 ^1 ?, f1 h3 m  j
        }8 T1 E# G7 v7 g8 f5 x# ~; E
        // MMC50 ^0 {9 S0 A+ y3 ^3 P& `5 u
        if( exsound_select & 0x08 ) {& M  \, A* v4 O9 i, Q% l
                mmc5.LoadState( p );
( h, Q5 w5 N' E, G+ l) j6 ?% V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' t& U7 \" f0 i/ J9 n, d
        }; Y0 J4 C- k* W& M% j6 X# L- T
        // N106' ?, s% _7 e' u0 E7 T8 D" R) j
        if( exsound_select & 0x10 ) {
7 \3 R  c4 g! X3 ~7 u                n106.LoadState( p );
' ]6 W0 N% @9 n6 _$ C                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* x+ |' M( l% Q5 ?( T7 ]. e, V9 T        }( `6 H  j1 b8 \; W  ]
        // FME7
* ?: m4 F( V2 x5 T( O        if( exsound_select & 0x20 ) {3 W7 q; x  o4 L+ B/ N$ P4 P. u4 ~
                fme7.LoadState( p );
4 Z; \* s4 _8 f                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 Q. d" ^4 ~) g/ |; V        }9 Y: ~* Q1 @0 l
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, s' p5 A6 I  U2 k  z4 x可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。% w, K8 M3 \2 Q! f
感激不尽~~
8 H5 h5 r4 ], j8 @9 W! T- F
恩 我對模擬器不是很有研究,9 O, D% A8 c0 O6 p6 t
雖然要了解源碼內容,可能不是很困難,# X8 Y& X8 }6 W' Q( \" n
不過還是要花時間,個人目前蠻忙碌的。7 Z  H- M% ~' D" e

3 o% N- ?1 a. l. }7 R) A5 ?給你一個朋友的MSN,你可以跟他討論看看,
, c, I) ~% {' N; `: j' y他本身是程式設計師,也對FC模擬器很有興趣。
( h" H$ q$ a3 f2 E* J/ O2 G) r
6 u& q& h, x+ K( i/ S. t% Q- kMSN我就PM到你的信箱了。
) h( t. n0 J1 J7 p1 E! n  v
0 x' K1 C  J* N  e希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 : m8 n" a  i7 F' B* N! Q0 e. d1 B
呵…… 谢过团长大人~~
0 k! F% a  h5 B$ J4 b* X  P
) ]; ]+ l1 a2 j& V
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
6 d4 X$ `$ p- l# v7 g团长的朋友都是神,那团长就是神的boss。
2 D' n2 l: Z4 D7 `
哈 不敢當,我只是個平凡人,
/ j* T4 m: X- y. Y: @. ]* j要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: P8 E, \& Z; m7 q4 N9 D
ZYH( u+ L8 C6 N7 |- f4 J4 M! F/ g
QQ:414734306, P" \6 Y* Y2 F; K
Mail:zyh-01@126.com
5 m8 }0 `4 ~% Z8 H9 N+ S0 c5 s* V7 }* |; J
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 k7 ?/ o3 K0 N! U  e再次对团长大人和悠悠哥的无私帮助表示感谢~~
3 v, q6 d& g3 f% e
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-26 19:58 , Processed in 1.120117 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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