EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
) x& z8 q3 L& r2 `. X8 i/ ZPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ d* `, i7 F2 s8 l5 m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* W0 r7 K, Y- w+ R: T这里有相应的模拟器源码,就当送给大侠了~~6 U. @4 l2 B; b! O, d8 t" X0 M
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
0 Z4 h$ Z( u1 I3 J3 ?* B( p能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" n5 d, Y( l" v
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 \# z. b! s5 M2 T2 G! J8 a" X: U这里有相应的模拟器源码,就当送给大侠 ...

2 O0 O2 x/ x' B4 P% R8 `聲音部分(Audoi Process Unit = APU):
3 D! u; \! j  v7 N1 `( m' N.\NES\APU.cpp
( G- a1 [( [6 w.\NES\APU.h
6 z- {# x. ^0 l/ h% @! [" W
3 H- T! m! x8 J+ U6 L- M# F( a1 h
$ I, A( H$ \6 v" [/ Q1 H6 I影像處理部份(Picture Processing Unit = PPU):# z$ V& F; l6 {3 G) `
.\NES\PPU.cpp
5 h, t3 N* f! r  }.\NES\PPU.h8 q; m1 h0 ~0 `* i
" |) S2 b5 a. v3 H5 h
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
. L+ e6 b' z% D7 X(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ O! Y& l- ^4 G7 F
//////////////////////////////////////////////////////////////////////////
7 y# W  S% c* O* b+ A7 L( q//                                                                      //! v! Y; ?5 f  |$ K+ Q
//      NES APU core                                                    //  v7 }3 s5 k" T  ~# B+ s7 M% V
//                                                           Norix      //
3 d& p/ x& I, o9 ]4 m+ b//                                               written     2002/06/27 //
+ {+ I3 s# u2 j4 P% p) \: j8 P//                                               last modify ----/--/-- //5 y4 t3 {9 a, \2 y4 D  T
//////////////////////////////////////////////////////////////////////////
4 p' n; h4 @5 E. c; [#include "DebugOut.h"
* S4 d8 X- Y; u2 A#include "App.h"
. r4 Z& @) h+ G, q* E#include "Config.h"
* Z5 K7 U, s& @7 v4 d& b1 g2 h8 T
#include "nes.h"
# v/ P6 _+ h" w& i#include "mmu.h". W/ I0 l3 ]- ~5 ^
#include "cpu.h"
' j4 C2 m. C  L3 S' N#include "ppu.h"$ r4 Q& `6 T+ W8 D2 |
#include "rom.h"4 s6 b2 @( c, S  Z+ X
#include "apu.h"4 a3 v; G' C. `3 V' f
, B0 H! K# ~4 ?; P5 I, m# \
// Volume adjust
" e/ u* j4 \  e% B0 }. f9 ~$ j/ }9 K// Internal sounds& o. B4 X) ]& T+ L6 e; o$ c
#define        RECTANGLE_VOL        (0x0F0)2 \9 L9 I2 s( ?, x) j) k
#define        TRIANGLE_VOL        (0x130)9 u* Z  Q2 K& |
#define        NOISE_VOL        (0x0C0)
) H  q$ \! H: w- X2 i9 p, \' @#define        DPCM_VOL        (0x0F0)$ }8 ~$ A2 H1 E& V, @; _; S3 O+ @
// Extra sounds. I1 j( h' e' J6 A
#define        VRC6_VOL        (0x0F0)3 A& i% F) p. `3 @" Y
#define        VRC7_VOL        (0x130)
3 {1 Y$ l/ R" A; a+ B#define        FDS_VOL                (0x0F0)
8 \6 i% c5 X; K#define        MMC5_VOL        (0x0F0)
8 J( X( f; {+ G: O#define        N106_VOL        (0x088)
& N* A& h9 Z( `" D#define        FME7_VOL        (0x130)
) B; v0 X; j; n3 N. @
$ G% }! B2 V  b- K6 z: ?, nAPU::APU( NES* parent )4 N! v% e7 s- p5 E8 o+ S) X
{
$ x  |0 e  a* o& |! S        exsound_select = 0;
- v9 U0 A/ e4 V4 ]- O( b$ Q2 s4 ^
        nes = parent;
/ I' N) k. e8 Q/ l& _. \        internal.SetParent( parent );( G- [: j& O) K8 V2 y1 v7 \/ _; P

* ]& V! x7 K7 a        last_data = last_diff = 0;& ^" G2 i# v* j. ~7 J7 |. ~, A. V

# K+ z& {% W* @$ D- d        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 n2 d, H: M6 F$ O
' m( p7 A, f2 }, f% F  j
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
$ q4 H: }; ~" ?5 l8 i# b        ZEROMEMORY( &queue, sizeof(queue) );
7 d. i$ E) J1 _; p, E# B        ZEROMEMORY( &exqueue, sizeof(exqueue) );, n2 |! S2 h* D" {) r8 G/ q2 Q
7 d" D/ K- {- C$ t1 r- i
        for( INT i = 0; i < 16; i++ ) {
- {  ?7 G1 i. S; q                m_bMute = TRUE;1 B% m  I- d0 f8 ~2 b' S5 ^
        }) p' O# V# M' t) h( a
}" }2 e7 N5 B" h) C4 Z  Z0 n% g( S
* M' B/ ?) `3 S9 [8 y! W
APU::~APU()
5 m' W; Y1 |' i2 j{
# R- V, f" T+ N}
$ Q9 l; ~6 e/ ]: E9 G' O' ]% e: T. H* v# r7 m( ~1 k
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )8 L6 P6 f% c3 Q4 @
{
9 V, B' f  w7 M' v) N, X        queue.data[queue.wrptr].time = writetime;2 m& n% s4 Q! V* ]
        queue.data[queue.wrptr].addr = addr;2 m; ^. D) P+ w9 W3 }
        queue.data[queue.wrptr].data = data;
3 d# ^/ ?3 m2 h; c9 O, F$ G        queue.wrptr++;# }7 Q, M7 U1 d3 k! e( Q- I7 `
        queue.wrptr&=QUEUE_LENGTH-1;
# S( ^& H. P% g1 i        if( queue.wrptr == queue.rdptr ) {& H1 \3 J0 `; S4 q0 y; D% O9 }# Q
                DEBUGOUT( "queue overflow.\n" );
& m. z) _7 n$ l/ {+ B4 }        }
7 Z4 \" [, N! [- F3 ]}# P  u- ~5 J% |: |# I
$ U' [/ e$ u) b& l4 R9 P. g
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) ]8 N- V6 s+ z2 e1 E/ I
{
" ^& R/ O+ R( Z& Q$ @        if( queue.wrptr == queue.rdptr ) {8 @6 S" n, x/ M9 d2 S9 {
                return        FALSE;1 }+ z8 f5 x) f* R1 Z
        }5 m! q, A2 X( R& b* f! d
        if( queue.data[queue.rdptr].time <= writetime ) {4 D6 F7 y" E& Y! L! X& r
                ret = queue.data[queue.rdptr];
9 f) Y% g4 V; l9 _0 |+ B; u                queue.rdptr++;9 h* d5 `; B3 K6 a5 v0 z
                queue.rdptr&=QUEUE_LENGTH-1;: \8 h1 h* j' z" A1 I5 {
                return        TRUE;
) n0 s$ v% m' ]$ t) ?- V        }
/ d& b; x+ H" r, ~, a" X  V        return        FALSE;
, e8 u; @& z! r. ?, ?# _( u" n}! o8 I" y. s# c, |. q
8 u- \" h9 U4 J
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )5 U+ m& Q6 J, U5 q
{
9 m* N: b8 l0 @" a4 Q0 e$ l& o, a        exqueue.data[exqueue.wrptr].time = writetime;
* m3 M& Z) U- |        exqueue.data[exqueue.wrptr].addr = addr;
  s- a6 K3 u; j0 L% a        exqueue.data[exqueue.wrptr].data = data;' G8 ]# X) s  t: r' r6 |) L
        exqueue.wrptr++;
3 g$ k& }% u+ e& c$ e        exqueue.wrptr&=QUEUE_LENGTH-1;/ b) P% W) e% _# j% @
        if( exqueue.wrptr == exqueue.rdptr ) {, l' |! ^# g2 {& M& Z
                DEBUGOUT( "exqueue overflow.\n" );& G# w- F4 h! k  ~$ p
        }
2 F) R0 V  i8 X6 e# ?* Z6 J9 S}1 J2 y" M* s% F# c! y/ P8 [

# J+ [# q7 H$ R& g) EBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
$ k: L- S) D, E, {; M& H{) h1 i7 x) p& h" v6 ?7 R& ?
        if( exqueue.wrptr == exqueue.rdptr ) {
" M2 J1 F- s" \% k9 Z9 D" Z                return        FALSE;
# E! L3 W( u7 z/ ?: P8 Y$ A        }) I+ A, _( Q  {& U$ l9 \" A
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {" ~* k( Y8 `# j7 G
                ret = exqueue.data[exqueue.rdptr];6 Y) }! \9 R8 [; E4 c0 D7 i6 z$ L8 V( ~$ M
                exqueue.rdptr++;  p4 ?. k% U- V( n% h  i+ s* ]
                exqueue.rdptr&=QUEUE_LENGTH-1;
6 _6 h+ p2 T) g) c                return        TRUE;' i2 E' W+ C" M2 ?3 U
        }8 Q) L8 O; c; {6 _- W- i& j3 J
        return        FALSE;! Z8 f4 U3 S* D* C$ A. u
}4 A: R% y0 v6 ^) O! `4 J3 _

4 f3 y$ v0 F  z8 R3 ]& rvoid        APU::QueueClear()  {! e* R2 z8 Q8 B( A8 X7 k& k
{
& a# _9 _9 W- S" B1 C  j: W- Z        ZEROMEMORY( &queue, sizeof(queue) );
. i8 b4 L6 j6 d* Z        ZEROMEMORY( &exqueue, sizeof(exqueue) );, j$ y- P5 h. M6 H. w9 @" c5 `; h
}( i3 `) o! @' Z: B7 j
, K2 x: A3 `$ C9 |) T9 j
void        APU::QueueFlush()3 x3 u# T$ F! y4 c
{
5 F7 c+ I/ x; U& [5 d/ @. V        while( queue.wrptr != queue.rdptr ) {1 q7 m0 H& O2 [: i5 a0 C
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 N6 k2 z' y) ~4 U: R9 }4 U
                queue.rdptr++;6 J' V( o/ x8 u5 k7 V+ n/ B
                queue.rdptr&=QUEUE_LENGTH-1;
! e, a0 [/ S$ _1 N        }! {7 `2 t' G) _" C! i3 J! J3 [% P

! v1 I8 l$ m1 K& J/ d$ G        while( exqueue.wrptr != exqueue.rdptr ) {
3 G) s1 ~/ e% u# {  q" x- c. i                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
! e* k2 d: D4 w& C+ X4 F7 G$ v                exqueue.rdptr++;
/ N  \7 L, `. O; u3 d                exqueue.rdptr&=QUEUE_LENGTH-1;
7 d# Q6 H' n2 |. ~8 S        }4 L* B7 ?0 ]0 t: x
}2 `. f- D8 G  X6 |. E4 }

) M, \2 u) y5 g0 t2 cvoid        APU::SoundSetup(): v" b' u+ n' [9 L$ b
{
$ q: n1 H  E4 F; m6 o# [% `3 m. k* Q        FLOAT        fClock = nes->nescfg->CpuClock;7 A4 h' [5 L5 `6 ^( V1 z
        INT        nRate = (INT)Config.sound.nRate;! g6 b$ y" S( Q/ z- V4 H
        internal.Setup( fClock, nRate );
' R) {, L) W: Q        vrc6.Setup( fClock, nRate );
0 ^7 ?& t& g5 i0 |- C        vrc7.Setup( fClock, nRate );% a7 m) u! Y( v) n/ k- @6 K
        mmc5.Setup( fClock, nRate );  d4 |0 s" o5 G# G; h; c- `
        fds.Setup ( fClock, nRate );
4 t' M0 [8 H  e2 ?( W) |9 ~        n106.Setup( fClock, nRate );
- V  O, w1 J1 N! M9 _  X, L6 {; f: A        fme7.Setup( fClock, nRate );6 Y7 @4 @; m( J$ v  U
}
; W% [8 D' J  x( c: @! r7 z8 e( K% O' Q/ D- D
void        APU::Reset()
6 ~5 ^; k5 q1 ?- k. H+ r{8 M/ l- S! L: @. S  Y" k4 E
        ZEROMEMORY( &queue, sizeof(queue) );7 I: s5 l5 S* W9 k: Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 K0 m, |4 _# G+ T; H7 v( |1 q, y0 U" E! p% o% z
        elapsed_time = 0;% |. A. {2 h) R, y. e$ X6 b; V$ I; V

2 K7 u& v1 e  h) @. W        FLOAT        fClock = nes->nescfg->CpuClock;; q7 ]$ [$ A2 {
        INT        nRate = (INT)Config.sound.nRate;
, h, k6 l' t) k: W: ]        internal.Reset( fClock, nRate );3 B( ]+ s1 o  A# k, x
        vrc6.Reset( fClock, nRate );
9 X) L+ b8 {- p) R' i2 P# o* z        vrc7.Reset( fClock, nRate );& h' ]1 |* l( U+ E
        mmc5.Reset( fClock, nRate );
6 f* M3 ^5 q2 t        fds.Reset ( fClock, nRate );" }- B' X& M; a+ f
        n106.Reset( fClock, nRate );
6 H5 k4 N! A- s" Q        fme7.Reset( fClock, nRate );7 x+ @: {( s5 j! P/ V
! e5 M& o8 r& _! C  I) v% o1 R
        SoundSetup();
3 Z/ n* U1 b1 l" r/ d}) @! c  h6 Z* v, x9 C

) p4 U  r. R* r3 cvoid        APU::SelectExSound( BYTE data )
6 W7 w( A$ k5 ?0 d  k) I{0 I! W: ]5 S) X" x7 e( z
        exsound_select = data;5 K( v, s( T4 @  v  V
}
4 h7 L) J( {4 l$ u4 R
4 I, E' l: p2 WBYTE        APU::Read( WORD addr )5 g3 w! j! v( i( T! \8 i. c
{9 U  O: r$ |$ o) Z
        return        internal.SyncRead( addr );$ w: ^% }! t/ L+ h
}' x; Z3 o7 e. ~7 W' k
6 Z; U  L1 ]+ ~3 ?! g
void        APU::Write( WORD addr, BYTE data )
3 ^) J" n% T# d9 X# N/ G! i5 x6 P{+ F  A+ y; X4 B8 V  E$ K
        // $4018偼VirtuaNES屌桳億乕僩
$ K3 {8 S2 J- V& Z8 G        if( addr >= 0x4000 && addr <= 0x401F ) {
' j& k3 G4 |& d) ^( T9 g                internal.SyncWrite( addr, data );
( ]) L# ?( P  x- H0 F                SetQueue( nes->cpu->GetTotalCycles(), addr, data );! p7 m5 _1 ?+ B5 E9 `* ^2 b, ^
        }
2 ~  R9 U( P( J( n}
7 t, D8 F% v1 g/ N% \% _8 w3 P8 \5 u" N) U9 Y
BYTE        APU::ExRead( WORD addr )
1 R. b5 b8 D  [7 h- P* X{- j5 ^1 Y! D3 N& M- e( p4 d+ _- |1 o
BYTE        data = 0;
8 F( c4 {: B' O, T7 w
$ ?5 i; Z6 `2 @) F0 a        if( exsound_select & 0x10 ) {
- ^" b2 G6 P$ ~6 l8 w( T                if( addr == 0x4800 ) {
0 o: o1 Y, w9 Q  m                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* g$ w$ E% M! s: N# s
                }- d; s! h0 v" H+ F
        }
! q. H. _8 b8 C/ q( u/ G        if( exsound_select & 0x04 ) {5 y+ `1 c1 z& s) h
                if( addr >= 0x4040 && addr < 0x4100 ) {
4 Q9 ]" ?5 |3 [" w1 M; n                        data = fds.SyncRead( addr );' o9 N- V7 a4 m$ S
                }
" `! Z0 ~0 n! }        }
2 n/ x/ n' q# i- v; e        if( exsound_select & 0x08 ) {" l+ v: c2 a( V8 f
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 [+ f$ h3 e' p! R* t                        data = mmc5.SyncRead( addr );; f1 _5 F' }3 J3 O# z3 b" @: e
                }
, z6 n3 Q4 I$ @+ c' _        }
+ g* h* j, j$ y( o. L* r* X" t; \- c/ G* H) ?; y
        return        data;: }  @8 `( T; L! J* w
}
- @: k: q3 _6 h4 L' z. A& R9 W1 D5 T0 N
void        APU::ExWrite( WORD addr, BYTE data )8 w) d8 y7 ?$ L! J
{
" \: ~1 h) I( X# Z! k: F# _' D) d$ b: v        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
. z- b. g% N* |8 J& D/ p! i4 W
1 H' D$ K8 ~/ [) a: `( Y        if( exsound_select & 0x04 ) {
& L1 g# U, t7 }5 h( ~  Q                if( addr >= 0x4040 && addr < 0x4100 ) {4 f) J! x& j2 x; e& ?& |
                        fds.SyncWrite( addr, data );4 v- D; E& F% B9 H% d
                }( q% \. p: p% p( M' I# B7 F
        }
7 f0 n' u" A+ f, h' {' Y3 L  A% i7 M" g& |( A( t7 E' `
        if( exsound_select & 0x08 ) {
# q( `1 w% l  V) B0 U8 s- H                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 |5 P& t6 R3 e; s* i9 q- K: ^                        mmc5.SyncWrite( addr, data );% h2 V. h3 @& T& h5 a
                }
1 d1 ~: d) n- s4 Y  U. i$ c) n- p        }
% h2 v! h, m7 A6 S- R8 B% ~}
- ?. o2 w$ R  N0 Z. D  C3 l; E! D4 `) `: z3 d' T
void        APU::Sync()
) q3 t( ]) ?1 W3 ], V: i{/ {7 |7 P2 S& m1 L- L; K4 E
}
- G& G$ {* u. Y9 D
* s) q6 F  v* f; Y9 a* M* gvoid        APU::SyncDPCM( INT cycles )
0 l+ h3 v: n) j8 ]3 K{
$ ~- F, n6 k8 n: v        internal.Sync( cycles );
2 [- _) s1 v& y, `# @2 \% b) K/ ^
        if( exsound_select & 0x04 ) {5 G4 Y2 N3 z  `& U6 s4 {
                fds.Sync( cycles );8 k& j' z) f# S5 u7 R; ~
        }2 t! @) [3 p; _( P7 k8 K: }0 S
        if( exsound_select & 0x08 ) {
0 k' b8 C5 }7 p+ l$ D# I                mmc5.Sync( cycles );
3 z+ R7 H% p0 n7 K        }
6 |0 l* B) H' u  m: s: i9 V4 _6 ^- X5 |}4 R4 g/ e% b. X( C. M  y4 \
: ?  q! N" b& W, B
void        APU::WriteProcess( WORD addr, BYTE data ). L- Z0 U: d# u; @6 J
{) ^, f1 E- v6 g& A, x8 W
        // $4018偼VirtuaNES屌桳億乕僩
' V' o2 |" t+ V& c$ b+ G/ v        if( addr >= 0x4000 && addr <= 0x401F ) {
0 J* i% l6 k) S                internal.Write( addr, data );
; I, u) L* V& f+ c9 ^9 `        }
/ K  T6 t6 o2 d$ ?! U  }; [}4 g" N0 b( A- ?4 O5 `/ O

* q) b. j. e$ u6 C! i9 V. Bvoid        APU::WriteExProcess( WORD addr, BYTE data )
9 ]' o# t8 V" P, _' _6 l{: {# @4 `/ e6 v/ s7 U
        if( exsound_select & 0x01 ) {( n/ D. j" J& t
                vrc6.Write( addr, data );9 V7 d. B/ j+ h' @9 g" I
        }
: O0 j. \$ ~  C  G) s4 M        if( exsound_select & 0x02 ) {, s; v& w! b5 a; o2 v
                vrc7.Write( addr, data );! K0 P& u& g2 L$ Y" {
        }) h( s' y2 C, `% k3 P
        if( exsound_select & 0x04 ) {
2 u, L: b% C/ c) B( }% o                fds.Write( addr, data );9 P" o( g1 W& G2 w# q4 t. ~+ t. _
        }
9 _+ o5 T% V# I, D/ m        if( exsound_select & 0x08 ) {, o+ s! G# p: S/ A/ e) Y0 e
                mmc5.Write( addr, data );% |, G: _& Q5 ~) `0 s( e6 k3 ]
        }
6 A. \# }2 r. E  j% Q) {/ C        if( exsound_select & 0x10 ) {
. ]$ F" p) B2 G  V4 d                if( addr == 0x0000 ) {
) ~  k; V' u: ?6 L$ n* s. I                        BYTE        dummy = n106.Read( addr );
) _; _4 P% w* l5 n  a, y                } else {( A8 b* Q9 H4 |! V+ L8 |4 @
                        n106.Write( addr, data );( b  y2 ]8 J, Y6 }# B, B, t2 n9 f( [
                }! U4 U+ V% A) a/ G* a7 P& w
        }
& j' n  G6 K8 t$ n        if( exsound_select & 0x20 ) {1 {' a8 r$ ]! k' E/ Z
                fme7.Write( addr, data );
* B0 S6 n3 m' m7 B        }
# \7 ~, L$ D6 x% m* S' F}
1 J, c9 ]/ p6 k, ?: O# J" l5 z/ h
3 ~1 T( w/ _! g" F! b' }' o; nvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
' \6 o4 `! r+ ^. L1 [9 _1 z{& a0 A& M( s  n! Z
INT        nBits = Config.sound.nBits;. \% f8 `" W4 W* M! D" q
DWORD        dwLength = dwSize / (nBits/8);  a  O7 h, q: w2 ?% Z- U+ t, M
INT        output;
: `4 e" V9 r+ |3 PQUEUEDATA q;
! w+ c) z7 {" q+ _* ?7 ZDWORD        writetime;1 w( b. W: }; J5 [+ |  z/ w

0 x( _! O0 y1 d6 Y' T2 g7 K. ]. }LPSHORT        pSoundBuf = m_SoundBuffer;
. o! U- y2 Y6 q5 pINT        nCcount = 0;2 O- x' `" K- `
+ x) W0 H! c& s( \8 Z
INT        nFilterType = Config.sound.nFilterType;4 p8 b' f. U! ]8 _9 h

6 D0 G9 K, d3 `: J        if( !Config.sound.bEnable ) {4 t9 s) n$ ^8 ^8 F* Q
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
! W4 W/ f1 T' Q" o                return;
- {' z+ D! e/ n1 \: o$ }+ }. P        }
3 ]8 S& K* ~- G
9 O2 G) w( H. J; x$ g3 q- @        // Volume setup! R. y6 A0 b) s2 N) a: [$ R) M
        //  0:Master
# D: y. Y# L% {" U' B        //  1:Rectangle 1
# N$ }9 C* O, B        //  2:Rectangle 22 H5 ?7 v1 R1 d0 w
        //  3:Triangle
& J; A( T) t* C2 _5 o/ Q) `        //  4:Noise9 W2 M' b# N7 n6 M) P/ X' p$ @
        //  5:DPCM
! M& `/ k! Q7 A# t: O5 [        //  6:VRC6" c9 {# ^" _: [% A0 D
        //  7:VRC7
2 d% G' G! T% Y7 _4 ]0 a        //  8:FDS
( e6 Q2 E! u& {" I+ i& |/ j9 H        //  9:MMC5
; X. x4 `( Z. p        // 10:N106
2 l' z7 b' D; M# k" x1 Y" T% X        // 11:FME7/ ?0 V$ O6 o* o' i" M- F
        INT        vol[24];0 @1 L6 b; ^& _) ]6 u2 \. Q" C
        BOOL*        bMute = m_bMute;5 N* e6 H/ e- F  Y' b, N
        SHORT*        nVolume = Config.sound.nVolume;
, y3 q. s# y8 w$ G( J8 t/ n, d7 d* G) S
; A$ ~% R" w2 u. Z5 g% L2 M/ z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
7 r8 K) V' h+ \/ f: j* @0 K) J: E; s- v  q( ?% [
        // Internal5 V, G6 O* A/ {& t3 P
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;- y- w3 m+ k" j2 s# y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
5 ?+ [. {8 t& |) e8 x9 g. ]6 u        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;' {* t0 ?3 |- p6 W5 }  R4 f) T
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
8 S7 x1 p$ c0 _        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
* D6 a3 n7 r' {% o
  ^  k4 ?! ?; [1 |- K& N4 K. v        // VRC6" U' `  ?; J+ R6 |+ o5 i1 Y, t
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% r9 v& O+ i  z5 i        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 W, j+ c0 V& _9 f
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; T. I9 n4 `% A# l% ]- L, j! x4 g0 X  d9 H) v5 g3 ^" @! q2 E/ u
        // VRC7( Q7 \$ u9 {; r6 j% ^+ d% e! A
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
6 I3 Q, }8 y2 c( X2 b3 V$ ?( [# E- t7 y( r* U" s& e8 @
        // FDS
; s0 l2 l% v* l6 f8 z6 Y4 n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ n, E( V6 ^/ x

$ o0 \6 s) W2 }! R( @; o8 u        // MMC5
/ Q! X8 U, Q. R4 \- n        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 Y0 T8 u' g3 [: q        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; e5 M/ P: f/ _) O+ q        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* n) \) ]3 ]; T3 }* X5 D. @- C6 T
; h& ~; c6 b. I7 [% Y2 u3 m        // N106! N* a2 s! A# K8 r9 Y$ p# p
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ P. V3 q2 C+ W; n
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) ?8 U4 W5 N! f% k. o        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" D; Q; w  g9 q) W' f6 j
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 Z9 L/ Z( T' O5 o% K; ^* ?; G2 a        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 C  B+ R$ y. ~        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! U6 @! G5 e' O6 V) v" @
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 b  b1 e1 ^* d! ^- c3 w        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  Z4 y6 V3 ?$ a. i$ o! S
2 [: k* g* x& O& m8 e- ]6 U3 d
        // FME7$ ]8 \8 B: z% \4 d% P/ W
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: s3 z$ [6 Y# O        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 p7 e- k; x- B/ T1 t
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 {5 C6 M4 H# _
$ [- }3 s# A* r4 c0 J//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
0 s/ A9 y* t' S+ z6 W9 I/ f        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) b( M9 u, a4 A! e1 h4 |
2 j1 M# I- z0 |: f0 i        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
$ U1 H! {/ J1 D' y& k; n3 L6 c4 x        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  H$ ]2 E* f% {: ^! t                QueueFlush();- A, o5 f8 m, z$ \. Z! k
        }2 `1 L) O, ~9 G# b$ o

5 m% C1 S1 v1 u1 Q2 i( @/ a        while( dwLength-- ) {
% b+ H/ J# d4 z. l                writetime = (DWORD)elapsed_time;3 _7 c8 r$ I6 D- F9 P+ i
+ j+ q: y  l5 A' M5 n
                while( GetQueue( writetime, q ) ) {! q/ D5 K( k, K  H' z% n$ l
                        WriteProcess( q.addr, q.data );* z0 \7 P+ `/ T+ r/ q
                }# u8 B( l; c9 D% K- A2 s

4 z+ K; f9 r6 I: o8 c1 U8 L: _                while( GetExQueue( writetime, q ) ) {  E( M, c  V0 [( f6 P6 Y, M9 d
                        WriteExProcess( q.addr, q.data );
; u& o: ]- _' o9 q- f) z4 P                }
; m# B8 f' D! B0 h: N; u6 \* W5 g  ]$ d) y4 F+ W! c. ?5 }
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7* d( F9 X; R, c, T' {
                output = 0;! B' z, s5 M' s9 r
                output += internal.Process( 0 )*vol[0];
  G2 Y- A$ m5 Y+ W+ d2 E                output += internal.Process( 1 )*vol[1];
- l3 K" x0 I: q/ ~                output += internal.Process( 2 )*vol[2];
' D5 p/ X! L4 H. ~6 S$ E% f                output += internal.Process( 3 )*vol[3];
2 y, P& B: Z4 v  |                output += internal.Process( 4 )*vol[4];! Y, P, h- H4 ^, D4 C

9 A* W7 m2 @! p- D) M0 Q                if( exsound_select & 0x01 ) {
# ~. _( s/ s, b5 d                        output += vrc6.Process( 0 )*vol[5];
5 V9 N5 f$ ?) f' b# b* u$ l# I                        output += vrc6.Process( 1 )*vol[6];
- J% l4 `* L  T1 m! J                        output += vrc6.Process( 2 )*vol[7];# u9 Q: j) l& c
                }* y- }  q0 U9 |( k! P: P" H9 {- a
                if( exsound_select & 0x02 ) {, m/ B- D' x, S9 D4 w
                        output += vrc7.Process( 0 )*vol[8];
( T% ?" }" F0 v8 V* {                }
& T$ K1 i2 l" f2 K/ |* Y2 r                if( exsound_select & 0x04 ) {: n( h% y/ R. j4 ~; f6 q) p( B
                        output += fds.Process( 0 )*vol[9];& u' S# Y4 t" Z/ N) K
                }
( }8 M3 k6 J5 Y' t( d                if( exsound_select & 0x08 ) {: M5 |- O/ Q+ G$ ~; v' ]; ^
                        output += mmc5.Process( 0 )*vol[10];8 @& L* L; u7 l# p
                        output += mmc5.Process( 1 )*vol[11];; x! s* @6 [8 q1 u! d: z/ O
                        output += mmc5.Process( 2 )*vol[12];3 {$ |7 }6 q7 t8 D7 w3 t% ?5 J0 X' `
                }
! D2 D4 v0 b: t" h. S: s2 n9 C& o                if( exsound_select & 0x10 ) {1 C7 q( E! L9 C% N
                        output += n106.Process( 0 )*vol[13];
. Z) T0 C  T' j7 s3 ?                        output += n106.Process( 1 )*vol[14];; I3 I7 q! P; {( |& j; I7 C# e/ s: K
                        output += n106.Process( 2 )*vol[15];& J3 |; @( R" P. D  W7 Y
                        output += n106.Process( 3 )*vol[16];
1 _$ S9 _* i8 k! |. x7 {3 J, f/ ~) B                        output += n106.Process( 4 )*vol[17];
8 ~( j( E2 w0 O8 }* Z2 p                        output += n106.Process( 5 )*vol[18];% v& l7 v* K# M8 C& v' N
                        output += n106.Process( 6 )*vol[19];# I+ C/ }8 x$ I  N1 _7 `
                        output += n106.Process( 7 )*vol[20];9 e: e0 K9 x7 f
                }4 A8 n7 h, X  V! X- H0 ^$ P( Z( X
                if( exsound_select & 0x20 ) {
" p5 ]3 i9 K, B7 \5 `* _9 m5 ^                        fme7.Process( 3 );        // Envelope & Noise
' j% d: N& e" c7 v' L                        output += fme7.Process( 0 )*vol[21];
' `9 D& `& ~- M+ h3 r                        output += fme7.Process( 1 )*vol[22];1 H8 n0 j4 F/ n: x3 C: l
                        output += fme7.Process( 2 )*vol[23];
0 C" k$ f3 `( h! J. @                }
5 v) _. n& k0 a2 K; k' |6 w$ J1 I5 P/ x! P! }
                output >>= 8;
# v  U/ j# L$ J' c4 l7 y
9 |& ^8 f; T; y# O                if( nFilterType == 1 ) {' Q+ p+ M6 e* }& @& m4 F
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 Q# ?7 p6 R# I. z$ Y: M
                        output = (lowpass_filter[0]+output)/2;0 ?" d2 `) h; J  a. O% d# W6 O3 L
                        lowpass_filter[0] = output;
6 v: }. t8 {) K/ J                } else if( nFilterType == 2 ) {
! n  X6 v) T; [$ G% I) X! i                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 O% e3 u9 y9 w3 u
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
' L; m' q5 a0 T# a$ y2 U! `: ~                        lowpass_filter[1] = lowpass_filter[0];
) z9 t& ^5 p# q% K: a% }                        lowpass_filter[0] = output;- j4 b* P' x/ S! Q: ?2 M
                } else if( nFilterType == 3 ) {
; I! T" r  B/ F/ W" ]1 j+ T                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 g7 Q7 j6 ?3 y( ^6 c3 ~% n9 B$ p
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) J, u6 ]" b5 c% r: g9 R$ s
                        lowpass_filter[2] = lowpass_filter[1];! \8 ?2 N  o$ c- Q9 f5 h
                        lowpass_filter[1] = lowpass_filter[0];4 x$ r8 n- o* R8 s4 T
                        lowpass_filter[0] = output;
9 N8 [, R, a, q6 _                } else if( nFilterType == 4 ) {% u$ n: {: j, r1 I8 {
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)( I/ O* X. o9 E' S) c7 \1 B  @
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;8 e6 H, U7 `# X. B
                        lowpass_filter[1] = lowpass_filter[0];
; H7 n6 u) A$ a( z( \0 f" y                        lowpass_filter[0] = output;: q7 `" P8 I+ K+ O; P
                }
6 e; H" O6 K/ r1 X) }8 H1 X1 j# l5 `- {3 D8 u5 {) H6 c7 ^
#if        0
$ B/ k% w- A8 T: H( X                // DC惉暘偺僇僢僩
, i- C1 d' i1 a/ h' A                {
/ u5 i6 l+ f5 o+ {                static double ave = 0.0, max=0.0, min=0.0;
* E- u5 M! n$ a7 W  d" h                double delta;( Q- n5 Z( |/ V; a8 p4 X
                delta = (max-min)/32768.0;
( K4 Y4 ^+ Y) E4 W' [% h                max -= delta;- p8 f7 J( K9 A1 P- {
                min += delta;
' R# y& t7 h8 [) e                if( output > max ) max = output;
# S4 b1 o4 D8 \$ [" N: e, E                if( output < min ) min = output;9 ~3 m5 l  {( S& N5 V# c3 y
                ave -= ave/1024.0;( Z1 x- m" H6 a# q# g% \
                ave += (max+min)/2048.0;# p. q( H6 T! ]- f
                output -= (INT)ave;. |) f% S- G8 Z8 t7 p: e3 K
                }
: g, w3 ~3 d' b% A5 q" Q' e! o#endif
& D! k2 _' e4 R5 U3 H' m+ K1 E" ?#if        1! B5 Z9 m9 S* F8 m
                // DC惉暘偺僇僢僩(HPF TEST)
: ^: g2 I$ w9 [  E                {
9 D, B/ C( H9 S* `8 e6 R' [' D  J  [//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. ~4 @6 p- t! {                static        double        cutofftemp = (2.0*3.141592653579*40.0);5 z1 ?( k  v& L' ]6 f: F. `  A
                double        cutoff = cutofftemp/(double)Config.sound.nRate;- `& `' I' k- M# o+ [: q
                static        double        tmp = 0.0;
6 C. E0 C; ~1 t' s* Q- H" k                double        in, out;
- y5 e. J$ C! u# P! T+ ]' w4 r& `1 L5 ~) V0 s+ b
                in = (double)output;- l7 W! f& w/ m+ t& h3 _4 ^4 b
                out = (in - tmp);5 f5 V! c  D9 o. m3 i
                tmp = tmp + cutoff * out;
+ \8 A. z. i9 S; I  d6 `7 A5 n; t) y9 z& ]; {% E
                output = (INT)out;
" H, w" p" y" L# z6 j                }
6 L( }( }, V5 d8 `) o! |% c0 ?  K#endif2 v; b- V8 W" ?4 P& q/ o
#if        0* ]  ]$ I9 c9 m4 _4 J& `) S+ R. ~
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 {# b2 h! z( n; C4 T. L
                {9 C: Y3 a( l" }. ]  @
                INT        diff = abs(output-last_data);5 J$ k+ {; t3 ^' r
                if( diff > 0x4000 ) {
( \! o+ m1 q5 I2 R- h2 d" @' ~$ x) e                        output /= 4;. P8 Z& b) V7 T# w% l% U
                } else
$ A6 _! Z( w5 M( X9 e  ?! W                if( diff > 0x3000 ) {
) S# Q- w# H* f                        output /= 3;
3 W9 m0 k. L6 e2 N                } else
$ V2 R/ p0 [' ~9 f                if( diff > 0x2000 ) {
: n& b0 r: [: l6 S/ h3 a                        output /= 2;1 A" x8 o, q+ f( {, {
                }
* u( \" N! J. v2 r  P                last_data = output;
$ v2 s1 K8 s' r9 g$ g& Z                }. P7 _3 L8 y$ b8 X4 G
#endif) q) F4 Q) O! P5 |5 U1 D3 N1 C
                // Limit9 H7 ]( }: }  t4 O4 Y5 W
                if( output > 0x7FFF ) {
6 t1 j- [# H' H7 t                        output = 0x7FFF;& H: r/ T0 D& H9 z" o3 t5 a
                } else if( output < -0x8000 ) {, i) ^) C2 P5 q* q6 M& b" r% ?! V
                        output = -0x8000;! ?; f, z  `8 J8 n( j
                }
, k2 ]  x! j% T% u2 t. x& F* b6 ^  F- u
                if( nBits != 8 ) {
8 o9 O/ B" h" j% s" o, n                        *(SHORT*)lpBuffer = (SHORT)output;
( `* F7 n! @/ h. z                        lpBuffer += sizeof(SHORT);
/ E2 L0 r$ c$ ^* @/ c5 ^: y                } else {
: R- V" ]5 f' b4 g                        *lpBuffer++ = (output>>8)^0x80;
" @% x. A" i7 h2 H6 O  E                }
6 v$ _* I* u1 {8 I/ R4 A; @+ u- S! _3 o, `# g: b9 r  B& d
                if( nCcount < 0x0100 )
7 r1 H! Q. H' e                        pSoundBuf[nCcount++] = (SHORT)output;
* I, I6 s. }8 Q2 U) o" n( y% z# D8 J8 N: d5 l
//                elapsedtime += cycle_rate;
$ t+ ?( q0 }$ M8 e                elapsed_time += cycle_rate;' a4 g+ l: ?& t4 f& D
        }
- v$ |% E5 n8 `* D. j7 c1 H/ Q0 z2 \' Y5 U' ~) {5 }! O
#if        11 A7 M7 o" {, K
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, _* q) T# ~9 m* L' Y* g
                elapsed_time = nes->cpu->GetTotalCycles();
, I; }8 z4 F4 M% `8 O" e        }
% l5 W  z* B, k# K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ y  f) h$ ]6 R- t; a0 i; w
                elapsed_time = nes->cpu->GetTotalCycles();
. h. c! m* f' @        }
7 N) H; j6 F$ _% _6 w  `4 a( T#else% i. n  Y; q* M+ f) G4 O9 T
        elapsed_time = nes->cpu->GetTotalCycles();
: p+ |7 g& p. X8 f$ K6 W4 s4 K3 G# E#endif
6 `5 s( m  |% H0 Y}# F8 k0 W/ f! v# c/ F7 I; U4 N

$ g3 L( S7 s( H7 c. ~// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
2 b% u' q+ G& U& a. `INT        APU::GetChannelFrequency( INT no ); N2 d4 X. g! ^7 C# @. \) t) C
{& _2 {; s) d  I: E
        if( !m_bMute[0] ), ]) k" H+ d* b- e* c( m/ e* X
                return        0;
9 X, ^. d8 b; l6 m/ m
* g+ ~( I" h7 k' o. ]$ p: Z  \0 q* @        // Internal
- F0 {$ ?9 k2 T, C        if( no < 5 ) {
5 k: K: }/ O; S0 k3 n                return        m_bMute[no+1]?internal.GetFreq( no ):0;  o3 h6 e, p; n, z# Y+ k
        }
5 E: @1 W5 G; ~1 v: j" I( V# v        // VRC6* L1 A) k: X9 [. V: e+ g
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {" d: Z  R1 u5 o" t$ X* Z% |0 D
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;' V) z  E) v6 M) h) [& m
        }
0 f- A* R: H+ V) P; p        // FDS- I7 `  t* T& F) t2 Y. J6 Q, A
        if( (exsound_select & 0x04) && no == 0x300 ) {7 {1 h1 e7 p- O# T; {
                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 ^5 T* \  k  S' S5 ]9 L6 V' w
        }7 ~4 q3 P' ^" [; f; h1 K. n
        // MMC5+ m: y$ ~: ~0 R4 |4 U3 d
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {+ P) `5 x1 P5 r
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
# v8 R1 c9 Y+ ~* q# C0 H0 u        }
4 p7 [- S6 z- K! z3 Q        // N1063 q$ A: {9 p* H2 f6 Y" F
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
  X' U4 n. r2 X/ V/ [3 E- I                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
; ]: s; W1 i% T- G$ k7 t        }
: g: `1 x+ _: V! N$ i/ W2 [        // FME7
2 g9 X9 \0 W) t, S        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* F/ M/ v5 f5 k' g
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 c* x, }1 o% V3 n$ z  I% Q        }& _. P! y8 [  X% f! j! I- }
        // VRC7
. l! |% K2 a& K% Q5 z& s1 h+ w        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {/ `6 q, ?/ r% _: M
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;/ C/ }* ~1 @, N8 c
        }
9 K% P0 U& B) ~. u  a        return        0;
1 h- j) R3 Q1 I# a9 D7 V}0 D: T+ O1 Q! O. \9 m0 w
" I* r6 A, K( a
// State Save/Load
# c% K" [# x' j' z+ Rvoid        APU::SaveState( LPBYTE p ): s" m9 O( }( V9 W# a; k2 g0 ]
{; \: w$ E8 @5 P. x+ z1 ?9 [
#ifdef        _DEBUG$ g) k9 `! S( ?# }
LPBYTE        pold = p;: F5 d9 R" G0 V; c* x- t
#endif+ s5 k% I% _( S+ u, b

2 [5 W$ f! j4 c  O; Z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, @7 T8 f& I- b8 E# r. t
        QueueFlush();! T. a2 C: I3 F& M7 X" `/ z

# E  C; U7 L" S' Q        internal.SaveState( p );7 [& O" v. x' |8 w8 V; s* j! W
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ g. i! E3 ]- l  g; n" N/ ~
2 V  v5 S5 z! P2 b
        // VRC6
8 i. t9 x' Q# q5 {        if( exsound_select & 0x01 ) {
0 S" r- s$ \  d3 {                vrc6.SaveState( p );
9 @& N2 s1 [6 Y  H4 G                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ U4 A% H9 `+ z' p; O$ u        }
  H- |: o- D) q9 Q- J        // VRC7 (not support)2 q( ?! b9 d$ Q9 e4 j3 F# D) k
        if( exsound_select & 0x02 ) {/ c) S3 Q0 K  I5 T6 h4 e0 }
                vrc7.SaveState( p );
8 }& k+ R9 [; z5 |# b2 J8 u6 j                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& Y& c$ ]7 [7 [. ]; ?5 D2 {        }
; l9 q9 |; M! M: P  M- Z  g( ~        // FDS
/ [0 F* i1 `7 f+ w$ C- T0 G4 }        if( exsound_select & 0x04 ) {
) v0 q6 F1 E7 l, B5 F- L7 z8 r7 W                fds.SaveState( p );
0 X; f, ]- F  q3 I/ ?3 i                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& n: S5 `  q+ z, ~' U        }
/ f$ x, K2 v+ ^0 n' d        // MMC5' {. F/ Z3 [: }9 W: W
        if( exsound_select & 0x08 ) {
2 ^5 o0 S1 z' N                mmc5.SaveState( p );
' b7 o! g; ^8 H- Y5 }5 c! [                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* q1 ?7 E/ O# @  J% x) x4 W- a
        }
4 @4 I  {* O) N" K9 f        // N106
& s- X  a* J3 J, S2 W        if( exsound_select & 0x10 ) {
$ s( p6 p0 V9 W. |, r( ]" q                n106.SaveState( p );
, @2 f0 W1 t! J, h& r' H# e3 `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 E. q* N3 R& Z7 ^
        }
: w0 N' T6 k& a' {# ^        // FME7
  j- a( |- e+ G% K8 d  c- C6 b        if( exsound_select & 0x20 ) {) u  I7 V% D  A0 {% s8 }  w
                fme7.SaveState( p );
! Q8 p- P7 {: X) i& [* i# _% g                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 k6 H& \. A1 e; a; P& e; C( X- v
        }# \3 `' a' }( c

, _% Q) C! l6 x  o9 n#ifdef        _DEBUG
4 g, U2 @7 L% X  R4 H# T* Q& f* iDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 D6 H, n  Q4 b1 e2 ~, ^
#endif
) ]/ C4 ^* I2 ]7 g7 Q}
$ M5 `4 S- N' K( u. S4 C  O6 `& f. j( w6 @* J: g, l, ?
void        APU::LoadState( LPBYTE p )
+ X! p  i$ A6 f{
" p. W9 W8 N) C        // 帪娫幉傪摨婜偝偣傞堊偵徚偡0 X8 @5 |1 E& X
        QueueClear();. t" V5 l, o+ `8 |; c7 C% |

+ S* u" l$ E1 r+ u        internal.LoadState( p );, O8 o+ y# P4 |: ?# V% R. g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) G1 I7 x) S! k! N' v5 z! e# U) `
8 X" G6 o, H  h        // VRC62 b  X0 F- i6 J0 k
        if( exsound_select & 0x01 ) {
2 t: T7 }- r  v                vrc6.LoadState( p );
- t3 W! T8 |4 t% ?  O; ^% @                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ C( {- F& T% {4 x
        }
) D# L: w1 }% g0 W' \, D+ _$ U        // VRC7 (not support)- a6 z8 i1 l. \# Q: @
        if( exsound_select & 0x02 ) {
4 k- I7 Q9 V1 `: ]                vrc7.LoadState( p );
8 r( \! E& k* I6 K8 g                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 t; X/ u) S* `" M  C* J        }# ~( `+ y+ Q" f2 ?# Y7 ]2 G
        // FDS, O4 ^9 F4 h5 {+ d( u5 e, r
        if( exsound_select & 0x04 ) {
* a" n; K3 G# S, e                fds.LoadState( p );
4 ]' N5 W7 R" Z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 `5 l8 a; Q3 G  [& @        }8 A- K4 K& ?; x
        // MMC53 I6 y) o  i; }. A3 R4 I6 V' `0 R
        if( exsound_select & 0x08 ) {+ D4 s2 x2 L* I6 C8 D
                mmc5.LoadState( p );
2 g7 F# ^  Z0 ~' |* Z) l# i3 c                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. [3 G! [5 o$ A; D. U
        }. r+ o: |/ c% {
        // N106
1 u7 g5 j. l& n9 }2 I5 F( e! ?/ [        if( exsound_select & 0x10 ) {; ?' H# O3 b! I; C2 h
                n106.LoadState( p );% G( T2 c3 h# Q" ~
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding- Z5 b/ z2 ]2 @% i7 L8 a4 I
        }
. U% H* e3 V1 S        // FME71 }- b% Q: t9 j0 k' J
        if( exsound_select & 0x20 ) {1 r1 U# y5 r2 L& ~, ^6 w, A& r
                fme7.LoadState( p );( [0 z: {* t8 o" s
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# U( i( }( c) H$ z* C- I
        }+ o; Z5 E% g0 E5 D( n7 q
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 6 O/ m( Y* S+ u  E
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: G6 ^- W* ?; q
感激不尽~~

4 R7 Z5 R8 F; l* \1 t恩 我對模擬器不是很有研究,6 ^9 b% ]1 T! u1 u7 E
雖然要了解源碼內容,可能不是很困難,  i; |. B% b5 m; Y. s; S: I
不過還是要花時間,個人目前蠻忙碌的。) n/ ?! Q2 h. r

+ Q; o. h6 z* ]- q/ \! f給你一個朋友的MSN,你可以跟他討論看看,
- G/ |- u6 z6 d# E' }他本身是程式設計師,也對FC模擬器很有興趣。4 ?* G7 U  a# E0 ?/ f2 b" n' D

) c$ [2 Y' {8 J7 x$ K9 k9 mMSN我就PM到你的信箱了。5 O& E5 Z8 x$ l6 t

) w4 a) b9 v. P* B$ {- R- X3 V希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
' e/ d' V: N; X/ G4 B呵…… 谢过团长大人~~

4 F2 d: q5 ^5 D2 n7 l% o8 b/ N* h3 |' e0 e6 N
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 / ^0 G. H- r: E- F8 i
团长的朋友都是神,那团长就是神的boss。

" }/ A! y. v* ]7 r1 ^" L! g哈 不敢當,我只是個平凡人,6 `( |; t6 ~9 e7 M1 e
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
' s6 c* i7 X1 @+ J; tZYH
6 a! f/ y* V, g9 w% gQQ:414734306% Y+ |9 p7 u. P# A
Mail:zyh-01@126.com
8 f: K* J6 P: I' f
9 z* C% K; A6 l他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 " v, [; C" [2 M+ G4 P9 |
再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 z" W3 \& \2 C8 r% |+ k
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-29 14:20 , Processed in 1.125977 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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