EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ N8 y9 y4 E% r% y, |楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& U# V; g7 b8 _# c# z+ E, Q% `/ H8 u这里有相应的模拟器源码,就当送给大侠了~~' l& B7 M) |1 W9 P9 d
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 % V" r8 l; z  p* V/ V
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 l4 h' R; C5 |6 o0 g( ?
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) A* }* w! D; r) W: F5 B3 W这里有相应的模拟器源码,就当送给大侠 ...
, X' |1 O% M& M# X
聲音部分(Audoi Process Unit = APU):
8 T. h! m1 p$ B( O% G" c.\NES\APU.cpp+ |3 M; O8 W" ~0 n3 ^, R5 M
.\NES\APU.h
: s, k: a! y2 F+ S* i
9 H2 L: A/ \! ]- i3 I: C" k
; D4 u5 a7 \3 {* q影像處理部份(Picture Processing Unit = PPU):0 Q# ^6 S  e- B# [4 G5 v
.\NES\PPU.cpp. P' X6 b' z6 E, P' @' k1 v
.\NES\PPU.h0 y, M& Q& ~( l/ `
* w0 {. E% B5 B- t0 {4 L$ q: h
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
8 r8 h. j3 N* Z  |: p! G, w( W感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:5 }' u% J4 H% ~1 ~# X% s
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ L" n/ M; c0 s
//////////////////////////////////////////////////////////////////////////
4 R& E# i' a1 C0 n) s//                                                                      //
! u6 Z& r) M& d" q- @, n//      NES APU core                                                    //# v+ K( t2 ]/ y, f
//                                                           Norix      /// J, z( J2 t7 }' G- ]  W
//                                               written     2002/06/27 /// J: `5 X: F9 ]
//                                               last modify ----/--/-- //
, q3 `6 W3 p$ e& y/ R//////////////////////////////////////////////////////////////////////////( G& s1 u% H& o
#include "DebugOut.h"/ q% z3 C3 R7 e& c/ j) a
#include "App.h"
8 d! D1 ?9 w( G( @#include "Config.h"
4 S8 B# F% }2 L# i  X# G
- i6 \( @2 n4 \) Y: h  K# `#include "nes.h": `# Z; n7 R, A! Z
#include "mmu.h"1 E0 Q( G* N" B- O7 s8 I
#include "cpu.h"6 P( O0 R4 B$ S( e6 s1 l9 o
#include "ppu.h"
. @2 j) v+ y$ t1 ?( A#include "rom.h"( J" y6 U+ J9 y. z
#include "apu.h"
/ O* G# w1 }  n
  {6 p$ h, W  b' T// Volume adjust) {3 P1 {# D$ d; _
// Internal sounds
8 w% ]2 j( ?+ q9 p#define        RECTANGLE_VOL        (0x0F0)+ d+ E  b( s! U6 l3 V- w( V4 P
#define        TRIANGLE_VOL        (0x130)
2 n) `/ }5 _1 |4 l#define        NOISE_VOL        (0x0C0)
: c3 r3 T2 [( P( S$ k#define        DPCM_VOL        (0x0F0): i8 o3 _& T9 ^
// Extra sounds+ u8 h" L4 h3 Z5 u; o( U1 t' O5 l
#define        VRC6_VOL        (0x0F0)0 D& u& U6 }5 O7 H, i0 ?$ Z+ }
#define        VRC7_VOL        (0x130)
& r+ q$ z. ]$ Z: x) a1 Z#define        FDS_VOL                (0x0F0)4 K5 }% m2 D2 U8 Y* O( i
#define        MMC5_VOL        (0x0F0)
- d  l. V' J+ J5 |#define        N106_VOL        (0x088)
9 j+ n" L' b" P  ~8 u; q#define        FME7_VOL        (0x130)* i( z. k0 c5 \! Z4 G2 G! l* S
6 l. M; L5 ^+ U
APU::APU( NES* parent )' M5 E4 c; G  ~0 _
{
5 U  x0 `, ]/ Q3 r        exsound_select = 0;' x8 T! B1 \+ [6 y6 g; G9 ?# t
$ U* g! A$ b0 I0 R3 i+ |* m
        nes = parent;3 g3 c7 V7 t3 i: Y7 x
        internal.SetParent( parent );2 K9 i$ z  ]! V6 [0 @5 H3 l+ f
! s2 t& c% ]. H, d
        last_data = last_diff = 0;
4 u0 i! e  e; ~' ^" \4 O1 K2 a* f( |
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 c# F: S& A' Z" V1 |

/ o  a1 {3 a9 V. J8 R        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& O1 ~, Q# B% b* A6 ~# m% V        ZEROMEMORY( &queue, sizeof(queue) );# p. B/ M0 r0 f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 G4 h2 \; y" `
# g; C/ m3 Z% A2 Y$ I* q: E
        for( INT i = 0; i < 16; i++ ) {
8 Z4 V% s5 Q" c( V4 v) `7 j                m_bMute = TRUE;; H; Z+ Z! v2 R+ i  Y% G. ~
        }( J+ p$ c7 W, u8 \6 {& u
}" E8 W! C/ a$ u5 V, y! B
  K9 Y0 u2 K, h$ q6 W8 A
APU::~APU()+ g2 |0 j0 A6 C* I; {
{4 |# O6 d. j! x0 Z0 ^! _, p" ~% k$ E
}
( F0 p6 _2 u$ `2 J- {
9 {6 W# l/ T$ i8 P* mvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
, W% r5 g5 d  x4 ]& f. k{
) g$ d! \( ]2 t9 W" f: W" N        queue.data[queue.wrptr].time = writetime;  B& r: g, U4 a4 ~( r4 ]
        queue.data[queue.wrptr].addr = addr;: ?. x, `/ M9 {( q
        queue.data[queue.wrptr].data = data;
9 F: [, D5 I/ w: Q        queue.wrptr++;
* o) X* [4 k0 H        queue.wrptr&=QUEUE_LENGTH-1;4 \/ `" ]& g- C
        if( queue.wrptr == queue.rdptr ) {) G2 ]' E. v, L' {# m: {$ i
                DEBUGOUT( "queue overflow.\n" );' E5 U: a! p# ]
        }
# v! ?6 e6 a( r: q' a$ \}! v4 ^# a& d2 m9 V6 _

4 h8 u1 m, p7 R$ E4 `' a2 QBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
8 `# F% y8 n9 i$ S8 t  z  v{! R+ g& x1 K6 f4 G  H5 {0 V8 o
        if( queue.wrptr == queue.rdptr ) {# C' w7 V+ e: ^+ C1 w& z+ `# r9 A
                return        FALSE;1 \4 x6 P7 G( ~0 g( [1 E2 u4 w
        }
9 G, k0 p6 m. @( L1 x( N5 K" b        if( queue.data[queue.rdptr].time <= writetime ) {; ]& [5 B8 i+ Y  y
                ret = queue.data[queue.rdptr];
$ m7 ~1 ?+ N5 s, w* A                queue.rdptr++;, B8 a9 |; j2 a* b+ N- D
                queue.rdptr&=QUEUE_LENGTH-1;
  Z! |4 n! M% B3 G4 O! ^- q3 C: y. m! V                return        TRUE;
0 x7 v; k9 _  H' o- `        }
: [+ w) ?4 h0 }% M        return        FALSE;. E6 Z9 {$ f3 p2 p* ?% J
}5 a( F  ]. E& \! t4 j) {; O
" @9 Z5 J6 A" h1 y8 T- v
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ x. m/ K* J( |0 E$ W% Q  P. ?
{
- w. V" A: E- h6 [" O# D        exqueue.data[exqueue.wrptr].time = writetime;: R: T0 H7 Q+ X( u
        exqueue.data[exqueue.wrptr].addr = addr;+ X+ p& g3 }( R9 p
        exqueue.data[exqueue.wrptr].data = data;
7 L$ ^# L  P/ d1 y/ w        exqueue.wrptr++;
0 g- h, a; a4 t* z+ p        exqueue.wrptr&=QUEUE_LENGTH-1;
& Y4 P3 b9 e: d* P. Z  p6 k        if( exqueue.wrptr == exqueue.rdptr ) {
6 r- q+ {; Z' g* r                DEBUGOUT( "exqueue overflow.\n" );
0 A; N0 f7 B' Q1 |7 E! p# j1 Q        }7 H- d& _* O' {! ], _1 M1 a
}+ L/ }5 ~& v0 m' G7 b( C

; q( x+ o! a) Y6 J# M7 |BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 P5 @/ D% x$ l6 @3 M$ A  C! r{% H8 s( w8 i7 Y5 O& n
        if( exqueue.wrptr == exqueue.rdptr ) {! c% N+ m4 t# Y, T+ b. w$ w3 t
                return        FALSE;
2 A  v4 R1 @. V6 ]1 g! `: h        }
" X& n9 F" l7 Y        if( exqueue.data[exqueue.rdptr].time <= writetime ) {/ |9 s" J  j! F' ?
                ret = exqueue.data[exqueue.rdptr];
9 N/ M4 }9 _; l! u( z4 T7 P0 m                exqueue.rdptr++;6 [9 B6 v4 K' D0 n+ D
                exqueue.rdptr&=QUEUE_LENGTH-1;# G: O  S/ @, w2 I3 Y
                return        TRUE;4 E6 H( m1 l5 n+ |' c/ C( D/ C' A
        }1 T+ u$ d7 g2 ]. |
        return        FALSE;
# N" d! N7 s" ?}
% l, U, Y) e/ O. C* r% a6 m' a! x( c3 ]
void        APU::QueueClear(), o- Q$ V. ]% g- k2 d5 [8 S5 U) b! M
{0 i' ~$ o, ?: W
        ZEROMEMORY( &queue, sizeof(queue) );
, V# i8 Z7 L" ?$ |  H        ZEROMEMORY( &exqueue, sizeof(exqueue) );. U& I- L3 {" }( z
}
; x& {' }6 l  z( [8 n( t2 q  @- H4 M
void        APU::QueueFlush()7 j% l7 p& i- L+ V
{
4 ?2 F/ }$ \1 }" G7 }" s; A        while( queue.wrptr != queue.rdptr ) {
2 R5 H- X- ]& ~                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
- B4 B. W  e0 w  _! D& h+ @                queue.rdptr++;# x# v5 c6 o$ K" r3 Q( ^! F, I- e! c
                queue.rdptr&=QUEUE_LENGTH-1;
% w" \! K/ Z3 B/ E. M9 G. g        }! b; I* I% g* @5 ^8 B0 r
- B. j7 N' D  D- T! B
        while( exqueue.wrptr != exqueue.rdptr ) {# B9 x/ ]& S3 }: y/ o9 N/ t; X
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );2 Y. V* x. `0 {
                exqueue.rdptr++;8 l% j' ~1 v% O1 |* b5 M5 i/ b
                exqueue.rdptr&=QUEUE_LENGTH-1;
: ~8 N8 [) z" _- m- O8 Q. Q        }
: Q4 q; e* H: M% g5 Y1 y. D3 z}9 d6 S& T; N& ?7 S5 s# C5 d
: r. b& f, T% z; I6 S
void        APU::SoundSetup()/ y7 ~) r9 o& v6 a1 T
{, E& U4 O2 F! O
        FLOAT        fClock = nes->nescfg->CpuClock;% w% h# ]- E. y9 s
        INT        nRate = (INT)Config.sound.nRate;
, L. _9 [2 _' c& G' y7 i        internal.Setup( fClock, nRate );; z1 t8 l/ V, r6 I, Q0 t( J, E' _. B
        vrc6.Setup( fClock, nRate );
$ Z5 V* a" Q( m4 U        vrc7.Setup( fClock, nRate );
5 a5 L4 P8 {2 D- B        mmc5.Setup( fClock, nRate );0 |9 e. v! _) E0 K, a) b$ V
        fds.Setup ( fClock, nRate );/ e0 K  n0 n  N3 r) J
        n106.Setup( fClock, nRate );
0 x3 T( M* R; I! j9 p( `# A        fme7.Setup( fClock, nRate );
7 ?$ ~* d- z2 X}$ q8 h6 `( O" X" I% n+ Q. K. ?

6 B& s% ~% q( }8 d7 P+ nvoid        APU::Reset()6 m; ~1 {5 G7 N2 b3 n
{& Q5 D9 f  F! F* l- M/ B
        ZEROMEMORY( &queue, sizeof(queue) );
! j/ K3 _, Y* _$ l        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 q- {+ G+ x) Y1 A
# z5 w8 O( |3 y! X$ b* v2 s        elapsed_time = 0;
: O% n8 o9 \% _! f% c* D: u: T3 t' i  t3 d! i0 T' [
        FLOAT        fClock = nes->nescfg->CpuClock;6 @0 a+ X  M3 K! E4 I
        INT        nRate = (INT)Config.sound.nRate;3 ~! o9 s, v2 v
        internal.Reset( fClock, nRate );1 M# A, `9 [, v
        vrc6.Reset( fClock, nRate );
% x) L' L2 E. X        vrc7.Reset( fClock, nRate );
& Z8 g( C) {7 T$ e        mmc5.Reset( fClock, nRate );
1 j: Q+ t$ H/ }$ s* b8 V* I4 z        fds.Reset ( fClock, nRate );+ u( W- m5 x- w+ n& m: G
        n106.Reset( fClock, nRate );
* ?+ ?3 n( J; z9 o        fme7.Reset( fClock, nRate );
: _6 D  p( Y& E8 g$ K, g
. g3 z3 S! Z& U1 J7 X3 V& u* ]        SoundSetup();6 O; P& R2 [9 _) k0 ~7 e
}
8 o2 ^( r6 [( N' ], w5 D4 t
$ w  X. X3 e, B: q3 g7 ]void        APU::SelectExSound( BYTE data ). c! Z. V, w! e. B9 ~% v
{
/ a" F( Z; \* h- H# c7 o/ l8 y  A5 Q        exsound_select = data;# v  @" P+ U/ g1 w: m- ~* {. L
}# s6 p3 J: e" v

: D, ]& o# E3 [: CBYTE        APU::Read( WORD addr )9 w5 [$ R% t9 I* b; w+ V
{
: u7 L( I  M: O8 n" v9 ?2 X        return        internal.SyncRead( addr );
0 j1 w1 v: z$ {* w% G( ~}1 K8 Y7 w8 c4 C! n

/ c2 P! y* B+ [1 {0 Ovoid        APU::Write( WORD addr, BYTE data )
' P' o3 {& B6 q; s+ g7 k{
4 t: X* \4 s2 i7 m% u        // $4018偼VirtuaNES屌桳億乕僩& r8 M2 Y1 n1 K; a1 G& f
        if( addr >= 0x4000 && addr <= 0x401F ) {% u3 g% r) ?- l! {' x; q# s
                internal.SyncWrite( addr, data );
$ ]6 F' B. D/ Y                SetQueue( nes->cpu->GetTotalCycles(), addr, data );$ q* I1 f; ?; v' k7 F, M
        }
" n, p$ l* n+ ]' Q; d}
0 ^8 p: u5 Z" v( }$ [. [4 \) z" P, u6 Y* S# G4 H
BYTE        APU::ExRead( WORD addr )/ B3 O6 d! k: p+ D* ?) M
{! X6 G: G- c# I0 ]& c) k! [
BYTE        data = 0;% J4 Q! M4 Q' A# ^# D7 h
: N( J. s; a' B& T" o8 P1 O# [" A+ s
        if( exsound_select & 0x10 ) {
8 M3 f/ c4 E1 `7 x                if( addr == 0x4800 ) {
6 I. C1 M! I. \6 E% Z$ k                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
8 y2 O9 L' G) G- w0 v                }
6 j" Q3 f/ _, X6 n- K. z- o        }
) c; w- B! N$ K3 p( v+ M. c! }5 w        if( exsound_select & 0x04 ) {8 G3 x0 s4 O) ^( A9 V, z
                if( addr >= 0x4040 && addr < 0x4100 ) {
+ k1 {- Y0 E( \) ~  u, c+ _                        data = fds.SyncRead( addr );" p+ a3 H; |1 x. H( K/ P; t% s
                }7 x) d% j) _; p. ~
        }
( _3 y+ P$ @7 T) y        if( exsound_select & 0x08 ) {
8 i6 I2 _8 G9 K                if( addr >= 0x5000 && addr <= 0x5015 ) {
( l: h# z. d0 Q# q7 q                        data = mmc5.SyncRead( addr );) Z+ O, m' R+ J
                }
, C3 e( O3 f6 Z# b( U7 T        }1 o; t) d1 w, C" U6 i- ]
  o( u' F' U7 s
        return        data;
6 O+ ^- o& H* q+ v% E}
$ q& X' M( P/ G
, T* E% {- k2 G8 i' \8 A; J$ l; svoid        APU::ExWrite( WORD addr, BYTE data )/ k& P- T* P% M2 Q
{- b4 m  m7 `/ \1 G: y- _5 Z
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );/ e0 o" P1 r6 e: ^! F4 B* y& b8 s

. u: G( w. i: [- e3 o3 Q        if( exsound_select & 0x04 ) {3 w$ h# o' A% Z* C9 s
                if( addr >= 0x4040 && addr < 0x4100 ) {3 k' ?# k" Z) v4 [3 ^2 M+ V) G
                        fds.SyncWrite( addr, data );! l" Y" D- d. L1 y/ Z& P9 e
                }& j$ V9 q# h- z3 s
        }
* s, e0 s( k6 N& O% l1 |' h1 C  j5 ^7 T$ s0 R' O; K
        if( exsound_select & 0x08 ) {
5 K6 g4 A$ Z% [2 _                if( addr >= 0x5000 && addr <= 0x5015 ) {
' g" _, [+ u( k+ k' ]! P% R1 M                        mmc5.SyncWrite( addr, data );$ R. b, M) s+ C! _" q9 Z7 }
                }, k  I& \# ?6 K
        }
6 ?4 G0 u, H6 M$ G+ k}
3 L7 O* w& N8 V' C6 Z2 m' M" a
6 J& m0 v  h2 B. Q9 X) [- {7 @6 dvoid        APU::Sync()
+ X1 p0 r/ E1 q4 ?# S{
4 s; {; _# B. d}6 ^, c& O2 j; J" |+ l, ?( `

- `% U0 |% |0 Z2 cvoid        APU::SyncDPCM( INT cycles )
& n" _+ e8 N9 w0 d{
7 f6 Z  G& p" V) ^0 ?2 r        internal.Sync( cycles );) H4 q5 j/ Q2 e7 q

. z# a3 w/ d# @  L. a        if( exsound_select & 0x04 ) {0 t9 l% G" _6 z1 d/ ]; o
                fds.Sync( cycles );1 r8 l! o/ k, \' Z: d, G
        }
: n) L$ N6 t- d: f        if( exsound_select & 0x08 ) {  \/ _( y8 ?/ d3 \
                mmc5.Sync( cycles );
  H- K" e7 u  b9 v4 F* |        }
+ y' G; `) B* s( @5 E( s}! [* ^( \  O! N* t' v
1 O; @. @$ J' J% |  m2 E0 S
void        APU::WriteProcess( WORD addr, BYTE data )
' T8 w. `. l4 K8 Y{3 y, @: o" Z: P5 w7 @
        // $4018偼VirtuaNES屌桳億乕僩
) U4 R$ L% _9 L9 M        if( addr >= 0x4000 && addr <= 0x401F ) {
8 n8 b( m- f! W+ A/ Y) w1 [; Q3 @                internal.Write( addr, data );( J  j+ M- @4 G
        }+ p- o/ @- i& C8 w5 U2 d5 J7 Q
}2 f9 B( |1 E& l2 o% N8 Q5 i, ?; z

( a8 K1 k7 H" l+ g! Zvoid        APU::WriteExProcess( WORD addr, BYTE data )* g5 ^: n- Z$ A2 M, @7 E- W9 P
{3 v8 G$ b! j$ M
        if( exsound_select & 0x01 ) {0 L1 |  Q$ j* o
                vrc6.Write( addr, data );
! W6 i8 g. C$ _        }* w  R: i7 J4 b0 U
        if( exsound_select & 0x02 ) {+ V! a+ Q) L3 G3 T2 @% u! F( _& ]
                vrc7.Write( addr, data );
6 D) p% q" i: }7 j' H        }
9 u/ L* V& O  j( H        if( exsound_select & 0x04 ) {
9 G( i" ~0 B3 r2 W5 a1 k. X                fds.Write( addr, data );
' d, d" a( f( R1 h' S( d1 r        }; t! P! U4 E" V( f6 b2 t3 @
        if( exsound_select & 0x08 ) {
* b, s& F" w, E' Z3 n                mmc5.Write( addr, data );6 R2 Y  }) ?& V4 p3 g8 A2 D
        }; n# Y2 @1 b' J6 f
        if( exsound_select & 0x10 ) {
) g5 }7 M) {: S5 h, z6 c7 s' q                if( addr == 0x0000 ) {
6 |1 o- l: ?- \$ V. i; g0 y                        BYTE        dummy = n106.Read( addr );
  ~* c  i. G  y8 u4 P                } else {
; [% L( v3 C# d  e                        n106.Write( addr, data );7 D6 |3 \3 Y) t3 B$ R% x3 B
                }
/ P" N; u; t( y+ Q1 u( [        }* q6 T% q8 {5 f, z/ O/ {0 c
        if( exsound_select & 0x20 ) {1 r3 f+ t0 W% P9 N( d# V5 U3 N
                fme7.Write( addr, data );
) z' m9 g; H2 p" t) p        }
) A: L; x. ^9 I/ S}
! j$ \8 D+ t9 o" Q2 Q( ~+ R9 w# r* H# g% r( G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
  G! k, v, q+ d: T{( \- k2 j6 z* T( h8 I
INT        nBits = Config.sound.nBits;# y* W" ^& U3 u4 C8 `, V
DWORD        dwLength = dwSize / (nBits/8);
8 d+ n: |. _. B& UINT        output;
% j: b3 @* ^; j! ]QUEUEDATA q;
" I) t" B/ x7 A/ @& r( E7 CDWORD        writetime;' s( l; N& y: Z* i' L
$ M5 o: l9 p# e+ [: [( C* N
LPSHORT        pSoundBuf = m_SoundBuffer;) t! {6 b- a2 e5 `' r9 k
INT        nCcount = 0;
8 t& ?7 U2 t- ]& ^  ?7 f* L7 y7 `9 _
9 C% }) e' U, y2 H* K$ I2 kINT        nFilterType = Config.sound.nFilterType;2 z9 Z( J% u& K

/ H: D1 H( r" V+ |* p4 q  d4 A        if( !Config.sound.bEnable ) {
% X! `  ?7 f- u7 g) E                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
8 E7 U9 f6 [7 S4 x                return;
: L$ t% a4 b! P        }: T4 X5 h5 x! W- _/ u
% b, K: N3 s3 J1 o
        // Volume setup
$ P. E+ L; W3 x: ?        //  0:Master! _9 I  q6 u2 u$ y
        //  1:Rectangle 1
7 |6 D/ m7 ^. X) j# c; l        //  2:Rectangle 2
5 s, j  T; s. U! `( V) b4 t        //  3:Triangle0 B+ |6 L) U) s+ Z
        //  4:Noise
  a7 y, l6 Q8 f1 P( Y7 o        //  5:DPCM
) ?, q/ N! r' U) r0 o7 I        //  6:VRC6' t& X; M4 q; p
        //  7:VRC7' T6 ^1 L- X; x* f4 t0 J; q) I
        //  8:FDS  C/ k/ V( [9 r4 \- T1 h, F  ^
        //  9:MMC5' \9 p" e" m7 R9 m' u- E
        // 10:N106' d" [5 O3 }, z
        // 11:FME7( ?( R8 [) k/ J- {, R& m" Y- U8 p2 U/ N
        INT        vol[24];7 O( F% V; d3 \: e: e$ g
        BOOL*        bMute = m_bMute;! O! q( w6 k. r0 F0 e# f9 D6 z2 R! x
        SHORT*        nVolume = Config.sound.nVolume;3 a# N( F7 t  l2 |, S5 Z
1 F) i6 J2 _9 x+ u! G9 n
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- w/ x/ ]. L0 F0 X) c

: }  @1 I$ g) S( Z7 B. _1 b! ^        // Internal
0 T( y) w  L4 |$ o% A9 ~3 b        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* a3 W1 ?" _+ S) v! x2 e1 e        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
6 Q, j" c# {7 o7 k; S6 L        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ k( I; g! j% Z* H
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;) n) U2 \( ^  L
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
* f0 m+ i) ]3 O
3 M+ I% M: [' G/ d" y        // VRC6
* ~% a  S% i- {9 ]" [3 l- n        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  B5 @$ t' D) a$ k% x- e* `* n
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;' f, @& G- d5 Y/ [* _+ ~) g
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 y$ m( _6 K5 }+ I' l! ^
- P( s0 ^# e$ O: V6 |2 V+ M
        // VRC7+ X+ F6 m( x. y+ R1 D' g
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 L& F2 n6 k9 G; n$ G5 S! f
! e, K8 z) y! q3 w3 q        // FDS
$ F: D7 ~9 w- t" a# g% q  S/ J        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;6 R3 I2 @) q% V0 f
3 F0 M! H0 i: M  f" h  e' R0 Y
        // MMC5
& U1 v( H, H1 U3 N' r& C6 P        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, ?4 b$ a1 ]( V4 P* t        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- X6 D5 c7 U) Y, ^. ~2 N9 ?
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 @" g# d6 b1 |0 A: O& Q1 n
& m4 {+ Z9 I! J' U2 K9 A& G0 ^
        // N106* r. `$ s' d. G
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: h' \6 b9 B% U% K
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ {" J  n- h7 \0 n+ o. j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) }- e1 L' v1 n
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' F$ x! y3 U+ c+ M, I$ U. r
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; b$ l& G3 \# |9 s# ], X/ c5 W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 g& ~) O- p4 x9 w+ w# ^( n
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 }4 {& z/ s* ~7 A) M7 z2 B: S        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% n6 ^& d, \% C8 Z- @3 Z+ h- P
" h# x+ r  E* S0 C- V6 ]( A        // FME7/ H% l9 z4 y2 y$ s$ {
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 Y* ]# C2 ^7 {. {& K        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 t" b0 ^" O( c        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ W' z% Y8 _1 f2 `* k4 _$ S% F7 G8 }4 d% c( B6 B8 Z  X3 ]
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
1 [& X% t3 ~$ ]7 i7 K        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 q* ~8 t7 `) x! |3 i& g+ V) t& D1 |
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. {1 C& ]8 X/ a- n! [* @
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
6 p- z1 I8 r. o+ u- i                QueueFlush();# @' Y: l: C( L( f( H6 M
        }
7 Z2 C) t- g& H: S
4 l% f0 W5 z8 g" f        while( dwLength-- ) {' k" k1 G+ B' ^+ F! G/ \, \1 I
                writetime = (DWORD)elapsed_time;0 ?# j# l+ q8 Z9 }: O+ Y' P$ P  i

6 Z& m2 y- r3 r- @" P                while( GetQueue( writetime, q ) ) {- K% |' n% g$ a; i- [
                        WriteProcess( q.addr, q.data );1 G! e$ E% g7 ]  a& T: U
                }
4 g' ], p9 J% `6 j& f6 s
. q$ `  z, y# R3 E6 u2 ?4 \+ b, n                while( GetExQueue( writetime, q ) ) {$ x) `& p# C5 |
                        WriteExProcess( q.addr, q.data );& C' L- [4 d, h) q  p; O
                }
% F  i' O0 E+ w0 \) c
$ I% q9 g! Q! @0 C. {  q                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 ~- U' A- ^/ [4 }& x0 z
                output = 0;1 B! t3 X1 H: \; F4 @3 H2 N" {
                output += internal.Process( 0 )*vol[0];
  K% w, _6 w1 r) M1 p' ?' M                output += internal.Process( 1 )*vol[1];
! r& x5 o% h$ s- o! l3 G' E                output += internal.Process( 2 )*vol[2];, r2 ?2 c# }3 _6 s0 S7 v
                output += internal.Process( 3 )*vol[3];
5 [( W8 M" e; Y3 w  I( m. c, t% E1 h                output += internal.Process( 4 )*vol[4];
3 i) c+ |& x% W3 s- w8 i' v
) F+ x+ [" y3 w: h6 z7 [% l6 k) T                if( exsound_select & 0x01 ) {1 @& |0 U# z- z7 ]
                        output += vrc6.Process( 0 )*vol[5];
7 j9 H+ z" O5 z4 }                        output += vrc6.Process( 1 )*vol[6];
5 r) ~, \/ g8 d) c5 p7 e: u                        output += vrc6.Process( 2 )*vol[7];
# ^2 [, }  V# P7 Y, s& x1 L                }' w5 v9 G  V3 y
                if( exsound_select & 0x02 ) {) F% ]7 [8 V' j$ c1 U
                        output += vrc7.Process( 0 )*vol[8];8 z* W$ x6 ?( Y- v+ `
                }5 J5 }  z) g% p: U  G; l& @+ o
                if( exsound_select & 0x04 ) {* B+ U9 M+ v/ X) a* ~- j. @
                        output += fds.Process( 0 )*vol[9];* l, M1 ~) L" O2 ?
                }1 E$ V/ R( o5 X
                if( exsound_select & 0x08 ) {- N3 A8 k( l- a% W
                        output += mmc5.Process( 0 )*vol[10];5 A$ a2 X" L4 E4 N9 b
                        output += mmc5.Process( 1 )*vol[11];
% U8 ]) D& v( o9 T" _0 M" v                        output += mmc5.Process( 2 )*vol[12];
; G% R2 l! W- ?/ W" m( c* o2 t0 b                }& [, z" v' K% {9 q7 a* A; ~
                if( exsound_select & 0x10 ) {  c, `0 [! {6 f6 V
                        output += n106.Process( 0 )*vol[13];: i0 c) B# E( v$ _. X/ X/ h
                        output += n106.Process( 1 )*vol[14];5 H* @7 l0 w, v. k% U$ L
                        output += n106.Process( 2 )*vol[15];0 K$ P% C1 U* e7 N
                        output += n106.Process( 3 )*vol[16];& `% s" J! v* u$ @; G. Z, f
                        output += n106.Process( 4 )*vol[17];" t  S4 D9 m9 a* z. }5 P* B# d* S
                        output += n106.Process( 5 )*vol[18];  Z1 o5 L2 \: k$ n( e0 w& k& |' }5 v
                        output += n106.Process( 6 )*vol[19];: |. E4 Z" z6 A4 e/ k: b# J5 |% G
                        output += n106.Process( 7 )*vol[20];
' ^7 Q$ G! I( U0 E7 a                }- X: E* b& k# T0 z
                if( exsound_select & 0x20 ) {5 J1 G( ~1 d! q( m) f
                        fme7.Process( 3 );        // Envelope & Noise  U7 l+ r: C* x7 ^3 E# k
                        output += fme7.Process( 0 )*vol[21];
5 }; a  ]5 j! \$ E5 p# k9 o  d                        output += fme7.Process( 1 )*vol[22];$ a3 Y6 i% E0 _. d- c
                        output += fme7.Process( 2 )*vol[23];; `* q5 h/ N2 N# C0 ~
                }
, C% g" @) e' Y. v& B6 z& Q6 R  d: {, B7 D4 ^8 b; H- K
                output >>= 8;) J1 d6 g, k. N" F

4 j1 K( H& k8 o8 D                if( nFilterType == 1 ) {" e/ F" C6 d4 `: o: b# T; d9 o# w
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)+ ^. v, W2 [+ q, P7 _
                        output = (lowpass_filter[0]+output)/2;3 F3 U' X" |( u  f3 z$ z6 T# n
                        lowpass_filter[0] = output;  a" r& m8 f; q
                } else if( nFilterType == 2 ) {) z) Y; p, T) l- }8 [" r  t
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1): O3 P" H3 i  f! e# w- ]3 m# b
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
  N) O3 w! |) H8 C                        lowpass_filter[1] = lowpass_filter[0];1 V* `- u6 c$ j* s
                        lowpass_filter[0] = output;
/ w' v, v: k# f. r+ P                } else if( nFilterType == 3 ) {
  ]" w1 \7 i9 W/ R* _% V                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ e: a' B* P: ^# x0 z: [
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 ~8 q9 B  B( p                        lowpass_filter[2] = lowpass_filter[1];# r7 t6 V( [* x! y' u
                        lowpass_filter[1] = lowpass_filter[0];+ W% e+ O/ d4 W; S# M
                        lowpass_filter[0] = output;
4 j* v( {; p$ v6 D' _, ?                } else if( nFilterType == 4 ) {
( [$ Y! ~3 q3 w+ @                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
2 `+ B* w8 C( `" B% b                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
, d9 b3 m6 z. \                        lowpass_filter[1] = lowpass_filter[0];  V1 {! `$ |2 M# B3 ]/ F
                        lowpass_filter[0] = output;
0 x4 M3 ^2 p, p6 a9 s: P/ t; ]                }2 ~" `- g: u6 R7 D' E4 d
" \: z4 d+ z8 s1 n8 g4 ]. N
#if        08 Q* e, A. _" ]' r8 l  U
                // DC惉暘偺僇僢僩
/ q$ K$ ?* [( I( F+ ]                {
0 t2 {" a: S7 R                static double ave = 0.0, max=0.0, min=0.0;8 p# ~( A, ~" r/ u7 w' M
                double delta;
. L2 h, E% d6 I; G                delta = (max-min)/32768.0;* e9 g$ a  o, T  @, E# A
                max -= delta;
7 |0 @. b7 Z& p  G9 D# Z                min += delta;( ~, n9 y- T* g) ]- x9 ?/ A# }! p
                if( output > max ) max = output;
6 G% d5 X2 A9 Q' _                if( output < min ) min = output;
- [0 N3 }0 V; |; O: v                ave -= ave/1024.0;
/ S6 F1 |( N$ F  Z: ?$ C9 _3 o1 W                ave += (max+min)/2048.0;) ^7 K" T1 ?& a& @! T& J  `+ Z
                output -= (INT)ave;9 c3 |3 X2 V- P
                }
* l8 f( n, ^1 Q3 N4 g9 H#endif6 c# R- W& R5 X
#if        18 F6 ^$ J3 L: @! \6 o, ~0 X: }3 g# c
                // DC惉暘偺僇僢僩(HPF TEST)
) t5 b/ K( A6 T! U# b8 ?# R3 W& Z6 @                {
5 A/ f9 w8 l( S//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
/ j4 _( A% v+ y                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 Q/ E4 O2 y! ~& n                double        cutoff = cutofftemp/(double)Config.sound.nRate;
$ d: S6 A! y6 C1 `/ P                static        double        tmp = 0.0;6 u/ D1 r$ U- l6 t' X
                double        in, out;9 A) Y- i5 l" M6 y- r0 p$ l
3 S7 Q7 L% r3 s
                in = (double)output;- _2 F' V2 N4 n" e7 v+ b9 y! R
                out = (in - tmp);
, U( L& \5 K6 A# H# f* Y' @' I                tmp = tmp + cutoff * out;& i+ I; q- b; G4 K# r" h

0 W  U4 d6 y7 s. Q                output = (INT)out;6 |4 B9 x; s. ]: b( M: k$ ?" L$ d
                }- X0 z2 ?* z  D) Z' d$ A. y
#endif" T5 e; j! _  \3 v5 G
#if        0# k% y; o; T- c" K! a/ T. b  n
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)/ e/ V' H/ a, g! e1 g
                {
9 c5 h$ [2 R5 t3 l                INT        diff = abs(output-last_data);
0 |" Y6 E9 b' e2 d                if( diff > 0x4000 ) {2 Q2 i5 V  }; l
                        output /= 4;
( L/ O0 y; v$ A* _4 T, r                } else
" v" p; N6 R# u* ^" [8 B0 h$ y                if( diff > 0x3000 ) {
; j; k! |3 l5 ~7 \7 A; y5 ^* G                        output /= 3;
- o( P$ a. Z$ X) n# e                } else! l, o5 k& L. t8 k; f
                if( diff > 0x2000 ) {
' O" U! ?9 k+ X2 e                        output /= 2;
9 l# o. X* Q5 y- c                }6 F, R* V: y' N+ [
                last_data = output;# p( e1 c  ?, i3 K7 z
                }8 ~2 ?: ~! z( T- P6 w7 ~! a3 g
#endif4 `3 s# |: y. A
                // Limit
% }) Z7 ^. f) O4 G# ]  B0 [6 m                if( output > 0x7FFF ) {8 c5 Z  ]2 D0 f$ i' d/ c
                        output = 0x7FFF;
- L- K" x6 ~5 `3 W9 V6 G) m                } else if( output < -0x8000 ) {0 K' d4 L- M0 `- r( a) q
                        output = -0x8000;
) f: n4 X) r$ T5 k; t; ^                }) x% \& y  {, U- H, R
8 T- W' F; e  A2 Y/ W! ?, N" t+ l
                if( nBits != 8 ) {
! i/ e/ H2 v4 ?+ o                        *(SHORT*)lpBuffer = (SHORT)output;2 y; G; G8 J% ~1 _2 t* @
                        lpBuffer += sizeof(SHORT);
9 {9 _: U8 M( L                } else {. Z) m% l) e+ \# n8 W2 Q" O( s
                        *lpBuffer++ = (output>>8)^0x80;# h' W: z/ \0 z( p0 i
                }" x2 |9 g% w' M

6 c( _9 e6 y5 U, n. ~                if( nCcount < 0x0100 )% M" _' w6 F& i: F! P1 w& r* K
                        pSoundBuf[nCcount++] = (SHORT)output;0 G  b, i8 U- Z# z5 ]

/ D" C* G. |9 L2 ?1 g//                elapsedtime += cycle_rate;
* M, A$ p$ Z6 |/ A) S3 b0 R) h                elapsed_time += cycle_rate;
4 p7 y' P5 U: |- f" d1 k6 _) @        }) c& F* h$ z4 n8 B

- i/ E& O) j. Y; X* z$ c* {#if        1
% r! V4 ^5 j/ \( I$ x$ w9 o! n        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 t5 g2 G! I9 s/ `* [
                elapsed_time = nes->cpu->GetTotalCycles();8 }( y2 Q+ G  ^0 i5 h7 \5 {6 ]$ F
        }
2 d3 v2 d% ~) B+ ~( [4 b        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {1 h# e. m) N3 K# Z  f2 g6 v
                elapsed_time = nes->cpu->GetTotalCycles();6 H& [# {9 }. O- t3 M0 A! }) x: }/ u
        }
2 y+ H& k0 q# r% T3 H#else
- P1 v* `5 u* w: A1 \! }        elapsed_time = nes->cpu->GetTotalCycles();. [3 O3 v: y, ]- u8 y
#endif  u4 n$ `' m+ V( p/ q/ U6 I
}
4 z# h. l( f3 ^4 Q4 C9 N
9 H/ V* Y: p+ Y2 b2 _// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
' a8 H% k( U% v2 }; YINT        APU::GetChannelFrequency( INT no )/ m7 y$ V1 E1 V+ Y" V
{2 L3 D1 W. L& y. F  m
        if( !m_bMute[0] )
0 z4 U: t% }- g                return        0;
+ t- h6 `" t' T& G8 T- }* G5 [$ x+ ~% D5 e% \2 Q, r8 Q# b& I
        // Internal3 m% L0 x' \  ?6 C5 I+ r
        if( no < 5 ) {5 V5 W) x' i% h; P% F
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 T  }3 r" [' O9 e/ u: I! r/ J" H        }
0 u3 V3 a& n6 M7 d  e        // VRC6
3 Z/ I, `" j5 J7 B2 j        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! @9 T/ q0 j: m% e# y                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;. ~3 U5 u% l& [! {# H% Y
        }& c5 O9 S1 p5 o+ z  v0 N( P4 m9 X# \  F
        // FDS) e5 K9 V& w& }  J2 Z' p* `) K
        if( (exsound_select & 0x04) && no == 0x300 ) {
. e( C" d/ W9 F( R                return        m_bMute[6]?fds.GetFreq( 0 ):0;
1 m9 Z6 |+ V/ j  u3 d5 o        }
7 D/ G, t( p& J, i+ H+ K, ~7 w        // MMC5( v! ?# X; [# {( d) V! K9 q5 E. m
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {& S5 c/ y7 X7 e* X  R7 ~$ A
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;) K$ z& [" u5 U3 Q
        }1 Z/ d( z' x( H8 F% E+ C' U$ Z% F
        // N106( O5 z* F" H2 J* h
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {( {+ V# r. z3 l; d$ K0 w
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 |3 E0 N. h, D! S, E" n
        }
) E% f. _4 n; `( w+ ]8 H        // FME7% O( c$ y$ E  w1 Z6 s) K
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {8 c& X. v0 o- w6 k- i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
/ x1 P5 f* K, a        }$ ?  t/ y4 q% ?" S* `
        // VRC7
9 O3 D7 L, A" F1 d        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: p+ J8 L% A$ `
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;: i$ J' q6 N+ ^7 a; {7 a6 k
        }' L, E0 }/ Z; O; R' m
        return        0;8 n/ S8 g, E; h, A! C
}- c: f2 X) u6 a) k" H

! C7 z0 W5 t0 e% S// State Save/Load
8 L0 m+ J. x5 Tvoid        APU::SaveState( LPBYTE p )6 s8 a' {& l2 l7 J8 [/ ^
{
, C4 N( q, U9 O#ifdef        _DEBUG/ K% ~6 I7 Y+ n9 o9 d% t2 A( @( V
LPBYTE        pold = p;6 r, i) T; a" y. ~# \4 y
#endif
0 ?# ^. _! y' U9 T" N6 r+ k* s$ C" J# d
: \4 j, [6 c; j1 _        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* P% P. O& E' l; z1 j' ~1 O        QueueFlush();
  A  }  @0 u2 v. ^3 _
" N" d2 [& g3 m        internal.SaveState( p );
/ Y. M+ ^  o0 D6 j, b# |0 D  k2 j6 H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 {* n2 j$ E' ?" S! k
, X( b- s% R- w( }/ h
        // VRC64 p$ t  k4 H2 w8 n9 `2 K
        if( exsound_select & 0x01 ) {
8 Q# v! {: f% E, |$ d                vrc6.SaveState( p );- H) \; A4 |3 a& g- M
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 _; Y) b1 ^# Q; V) Y4 R& M1 [        }: e+ y# c9 n. m+ n+ V
        // VRC7 (not support)
9 p7 |. o0 u$ X5 B  N        if( exsound_select & 0x02 ) {
0 S: d; h8 u6 U0 b1 `1 C  R1 S                vrc7.SaveState( p );; e) V6 i5 q  H& p4 \
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 p7 G$ j2 ~- o5 Z
        }# |5 R! f6 c( ~3 ~6 w
        // FDS# n1 @4 r8 [8 a
        if( exsound_select & 0x04 ) {
" V. D; u& R8 g& T0 G                fds.SaveState( p );
0 J" ^! T4 B& x& P  B( y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! S% M+ E' B. q* s& O6 s4 X        }
/ N. Y& u& M! R6 ?/ z# u7 c. V3 c        // MMC5( O) ~0 D. b' c) y! V' N+ r8 {4 f
        if( exsound_select & 0x08 ) {
" |& t  L3 m9 I# F                mmc5.SaveState( p );3 M0 {6 h/ Q+ ]/ r8 N2 O4 |
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  X. b  j- [8 g* H  y" I3 n2 b
        }
7 S/ b8 o* ~. S0 M' f4 @        // N106
7 ^  W) ^, p, L+ s% Z$ v  @; r        if( exsound_select & 0x10 ) {
( _5 w- N/ n; s3 V4 a2 r7 h                n106.SaveState( p );* _) v( _& H: g& y0 N0 t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  w$ }, B9 t, k4 H/ E        }; w2 ?  k* a9 @: |2 k$ \
        // FME7
# D- P8 ]! Q9 s        if( exsound_select & 0x20 ) {
1 E3 w& L0 v0 A0 e  C; p. q                fme7.SaveState( p );; H4 T7 X, j% Y9 V6 @
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ U9 a" e. n4 Y        }
6 s4 F! D" B" P3 {' k6 M
( ]5 Q1 l  `% O#ifdef        _DEBUG: A' h* V  Y2 b5 h
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
+ V7 m$ z2 X) L* l' z1 f#endif
  G, j4 z# m4 m9 @0 |}
3 L; c+ J& Z+ C. Z7 w( A$ I5 B3 B  C$ a  Z2 W
void        APU::LoadState( LPBYTE p )
$ Z) E$ h" w$ R+ }2 G{) Z4 f5 t1 v/ A" Y8 e
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! ^# O1 ]% H9 v! C        QueueClear();  d$ l9 y6 S" @( X  S8 y; B
2 n0 @# V9 a! g6 W
        internal.LoadState( p );
: P( U) E' |. N. j. b        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, B5 D2 T' `1 i4 R
7 L% G. j, {7 o$ E' [
        // VRC6
& q% T0 M& G: y! j( k% N6 T        if( exsound_select & 0x01 ) {
2 |( S: o9 b* K                vrc6.LoadState( p );
/ w9 l; k/ D' [                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ X: b) T; d2 c' ~' N: h
        }# f9 F+ q* w$ e
        // VRC7 (not support)
2 H& j* x! q  ?# Y4 v+ [$ Y        if( exsound_select & 0x02 ) {
& W0 J$ p) D, W4 h% K' b+ u+ k                vrc7.LoadState( p );( \) a8 e1 q. X3 Q: j* c" ^' p: b
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! N4 Y- A$ R  y. U9 A: z9 \$ c
        }7 N* q. d( q  d' [* m, X9 r
        // FDS
; N9 Y/ Y6 Y# H3 G9 a+ \9 b7 u. ]        if( exsound_select & 0x04 ) {
5 w& g' J: i" @" b                fds.LoadState( p );0 M5 A/ _7 d  H. W" v* O% ^
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 K5 u6 k. K5 O7 z
        }
" R, I8 N8 h& h        // MMC51 v' n) Q& s1 w4 ~
        if( exsound_select & 0x08 ) {
1 [) @7 s) W% z$ n1 a5 C3 X! J                mmc5.LoadState( p );
/ z; F* i0 k# m, v3 g( I9 h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  S" n" `& Z2 R/ f1 m        }
& W* b% N" D& e2 z. Q" B        // N106
" e( S( K" _" @2 G, H        if( exsound_select & 0x10 ) {
* L0 N# p# }0 q; _. `3 T                n106.LoadState( p );
/ L$ A6 L/ B5 `0 m* E                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; t: B1 S4 W8 C0 ~, v& \! I' p
        }
$ |. v7 y, ]. c8 M        // FME74 B, ]) Q" k  U
        if( exsound_select & 0x20 ) {
+ S; o  k0 n; N* ?# N4 T                fme7.LoadState( p );( X" y+ W* }  A; e1 ~
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 x" c9 U4 \+ z3 {
        }
+ H: i1 C/ A4 W}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
6 v( A- a! a& ?% o; r3 v1 U$ @/ T可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
7 E; {) C( r- n4 c$ U3 U' i2 T感激不尽~~
8 Q. U2 j- r9 p5 D
恩 我對模擬器不是很有研究,
9 ]5 |4 C# t* ~* y/ r雖然要了解源碼內容,可能不是很困難,; i& x/ I8 P) z( \7 c$ N. L& K
不過還是要花時間,個人目前蠻忙碌的。' r# F, i$ Z) h& e. H& F/ V7 }6 X

; e9 I7 W$ T' S7 Y給你一個朋友的MSN,你可以跟他討論看看,
* `% @* L$ V8 v0 Z$ n- I3 H他本身是程式設計師,也對FC模擬器很有興趣。- J2 m7 {) g2 a- x( m6 C% B  W+ y
  ?" c, k2 c& N& Z( R
MSN我就PM到你的信箱了。' V, o4 l4 E) ]

+ i7 P6 x! v/ U9 M( j希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* x# m4 [$ w- O$ _. c, ~: r呵…… 谢过团长大人~~
1 y% m  i" Y; p+ r  D1 y
. {! Y7 J/ l& A" `& c  s
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
: a9 r7 ~% ]- A( z" u; C团长的朋友都是神,那团长就是神的boss。
6 Y$ k" d) |& w: Y5 ], e; C* g
哈 不敢當,我只是個平凡人,- f, S5 Y  S7 s5 X: B
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
% U5 B0 u+ P# u+ o8 {/ _ZYH
5 J9 A9 t2 ^- n5 _QQ:414734306
" V0 {2 D1 {/ E$ K2 {6 x6 I8 qMail:zyh-01@126.com
: t7 S3 w# g: ~3 w
- X- T" b3 o2 x: ]) C( D他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * G7 o9 X: b" P2 p$ z- P% [7 Y& j! W
再次对团长大人和悠悠哥的无私帮助表示感谢~~
- r# b; X- t7 c( ]
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-6 00:38 , Processed in 1.115235 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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