EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?8 s3 [9 ^' F, E: b, Y. {8 w
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" P/ i  w. {$ V# ^# B/ ^楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; G9 {4 |& a, q这里有相应的模拟器源码,就当送给大侠了~~
! ]4 @6 p  }: b% X5 Vhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 . q1 T0 ?# G3 u+ D& @2 _; M
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. d9 U8 J6 G/ v5 w# h, s3 ^$ W
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- `3 L9 F. R# [. U3 Z
这里有相应的模拟器源码,就当送给大侠 ...
* d' C2 k4 O* `; s" _" m' L6 Y
聲音部分(Audoi Process Unit = APU):
) w" f# y  \2 ?1 }' V( Q3 ]& i.\NES\APU.cpp$ w# }# A2 e1 u* |
.\NES\APU.h; e+ u& G; Y, }2 A

" y( [8 ?7 o$ E' h/ B" T+ h. A8 L" a: w, b& a
影像處理部份(Picture Processing Unit = PPU):. S% O1 a& w* k9 X  V3 o
.\NES\PPU.cpp7 T( Q/ Q# v1 c! z% w
.\NES\PPU.h  i9 }- A: _8 _8 o6 I
8 V" t& @4 j# O, G
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。. W6 ^6 ?1 L1 s6 h' c- t: D: I
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
4 j$ d4 m0 h1 J+ T! h(由于很多专用术语和算法机理都不明白,所以看不大懂……)- _6 ?( |: ?  v  t3 s  q
//////////////////////////////////////////////////////////////////////////5 R  g* H8 \- j! b
//                                                                      //+ h/ k: i2 D2 K8 h2 F2 a
//      NES APU core                                                    //- h- o$ D  y/ Y% Z
//                                                           Norix      //( p! R0 O# C3 G4 ]9 [
//                                               written     2002/06/27 //7 s+ C. P" t$ S8 p2 Q: A9 _2 `$ ^
//                                               last modify ----/--/-- //
# H9 n, L" l: }7 o& R//////////////////////////////////////////////////////////////////////////& t/ \: r& S, J) T8 T5 P( C' x( r
#include "DebugOut.h"
, G$ H8 S( `+ V3 w9 S#include "App.h"7 X5 m- K) L+ V# C
#include "Config.h"
- G& l$ t2 \! `  D8 n5 o' S9 i6 t( P& f4 |3 |, N. _8 |7 P% ?% ~$ v0 ?
#include "nes.h", T2 h" ]$ q' C: j
#include "mmu.h"
; z7 p# h7 R5 e" K2 h) e3 ?# Q#include "cpu.h"
& I, _& R: x! f8 z8 F1 Z5 R6 d#include "ppu.h"
$ J8 g" s" Q/ j: }# W7 E#include "rom.h", T' ]( |- V# C1 |- v5 s
#include "apu.h"
# g' |/ j4 u2 J3 J3 @
) G5 p" Y: _5 X! t' D3 A// Volume adjust! a( f  T4 H0 Y
// Internal sounds3 d2 i5 V8 V4 E9 [' s: O8 h
#define        RECTANGLE_VOL        (0x0F0)4 F5 `5 J; Q# [7 l3 H$ J
#define        TRIANGLE_VOL        (0x130). q. ~/ n" ?8 j. y
#define        NOISE_VOL        (0x0C0)
7 L1 @# `& E' d8 O0 `  w6 J6 J#define        DPCM_VOL        (0x0F0)( c9 t6 G- L% P# l7 A( P2 M1 _
// Extra sounds
8 h0 b0 k+ q# l2 w; [. C#define        VRC6_VOL        (0x0F0)
( H; k# X& ~0 Z9 f2 d#define        VRC7_VOL        (0x130)# l0 H; t( w; C+ N/ o
#define        FDS_VOL                (0x0F0)0 Z6 K; c! A3 D9 j2 W$ ]1 Q
#define        MMC5_VOL        (0x0F0)
5 I% ~; A, M4 \* J& p#define        N106_VOL        (0x088)
( }/ S5 |' o& Q7 A9 o#define        FME7_VOL        (0x130); c4 h9 _9 V/ W" m9 P9 t

- i* q1 @5 [  h- o* o" XAPU::APU( NES* parent )
2 ~8 t5 }! r4 r. h: y! {! B- r3 D{
: j8 ?# L: D' _6 D4 K        exsound_select = 0;6 p% C3 a( s) e" [- z& O
% h, s3 Z; K( u- d3 M/ H4 R
        nes = parent;
6 c5 V  b) r+ v        internal.SetParent( parent );# l: g! Y7 \; L* r

- R* T0 P7 N$ h: B. n" s6 |3 G        last_data = last_diff = 0;
: e; I' k! B% w# ~: h0 B; `+ Z/ ^) h. p
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
  }# J, C1 i0 }8 K
( D. @+ L" m9 q1 v' h7 M        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, N1 O% n8 ?' S- L
        ZEROMEMORY( &queue, sizeof(queue) );
/ Q8 ~3 x0 N6 C4 `6 y; ~        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 l2 R3 i5 h3 U/ u, d. ~- U
! L0 a  ~7 @1 Q. M        for( INT i = 0; i < 16; i++ ) {5 |4 S2 o6 {% I4 I$ u( h9 \
                m_bMute = TRUE;- X8 p  V2 W9 [. ~+ I: G
        }, I4 f+ z* f5 \+ ?/ e% \0 p
}, t; S6 V/ _5 x. ]/ v* b
" r, r0 A5 c! M& M4 R8 l- n
APU::~APU()
  l: m* b5 ]9 |6 n  A) @; A{/ D$ n. [) C( ?# z5 ~. O
}
% n1 G; S* p6 Y* O8 W2 {. s
' E+ |* G% W: b1 A/ Gvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )1 R9 n9 P; [7 q& c8 K& H7 B/ [
{
9 \$ D+ i' e7 [        queue.data[queue.wrptr].time = writetime;
$ ]3 E1 p& w/ r9 Q        queue.data[queue.wrptr].addr = addr;' B& t) s+ X7 B
        queue.data[queue.wrptr].data = data;
4 ^4 y2 z* H, p  K$ W1 b0 g- a0 @        queue.wrptr++;
" B; j6 S3 d1 ?# P3 j6 V! ~2 c        queue.wrptr&=QUEUE_LENGTH-1;
; r5 a4 W- L1 Q" m        if( queue.wrptr == queue.rdptr ) {
. {2 s8 i4 }; t  ~$ H% o                DEBUGOUT( "queue overflow.\n" );
' c. ^% T( M0 A# @  U" @        }
. d0 I+ C$ G% z% q! z}5 h9 x. K  H' P9 I8 D

2 b3 k# }6 h" E5 _9 j: ?3 IBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
( G/ F6 U# |0 p( u: S3 H) g{
4 @' T5 N( ^; k, c, ]0 [4 _3 P        if( queue.wrptr == queue.rdptr ) {3 ~' U. U$ R% ^# T9 R
                return        FALSE;
: ]$ f/ \9 _4 G$ [, N4 u        }
; ?' [2 G- I, M6 l+ s. \! K        if( queue.data[queue.rdptr].time <= writetime ) {. R$ B/ v  p7 Y/ S. z  R
                ret = queue.data[queue.rdptr];4 p* M$ E! `6 p$ L$ n" K
                queue.rdptr++;
# v% |: b  g8 w3 x9 O: |1 F4 ]                queue.rdptr&=QUEUE_LENGTH-1;8 k: x& v' ]6 |! [6 q1 s
                return        TRUE;0 V+ r; F, x/ {
        }
. d5 N* t5 y# ~1 l- f        return        FALSE;9 D9 Q9 X2 Y7 X. [
}9 R1 ^3 n  y' a3 g

; c0 S! r  |: j! v+ `- r' b- ovoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: K* t; k3 I3 Z% g{! `- w1 G' `4 s6 X9 L
        exqueue.data[exqueue.wrptr].time = writetime;' {( h0 G. p5 Y  @& w
        exqueue.data[exqueue.wrptr].addr = addr;
" P3 r2 j9 k5 X% @! L" {; I. t/ P        exqueue.data[exqueue.wrptr].data = data;* u5 f' q2 ^, E% s3 e, i7 R" A  O
        exqueue.wrptr++;
4 W, M8 h0 w  i8 y        exqueue.wrptr&=QUEUE_LENGTH-1;
" {- `8 P7 t& B        if( exqueue.wrptr == exqueue.rdptr ) {
( b- v8 _4 v/ M. G- i4 r6 G                DEBUGOUT( "exqueue overflow.\n" );
/ w6 h9 [  D% @2 \* y: B! R2 Q/ g        }
8 w+ y) @: k5 ?: O7 q2 J  Q2 k}
9 G( p0 _' Z! |2 K# t1 j' M; V1 B2 L0 C: q2 m6 ?' j6 o
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
  b8 m6 S# i+ D' x% I. e{
/ t5 q1 C- g, k1 G8 t        if( exqueue.wrptr == exqueue.rdptr ) {0 J" m1 ]/ O2 _$ F$ z+ x
                return        FALSE;
- u7 Q5 _/ E: p9 I        }
1 T3 Z$ a3 N& g% R* ?+ `        if( exqueue.data[exqueue.rdptr].time <= writetime ) {5 G3 f# C/ d0 o7 p
                ret = exqueue.data[exqueue.rdptr];7 i; |6 P  h* r
                exqueue.rdptr++;. O# E7 h' T0 E
                exqueue.rdptr&=QUEUE_LENGTH-1;4 [7 `, T0 r2 U( V: t. S5 i
                return        TRUE;
; H! w! H) S# W        }
) v- y* T2 P5 l7 ]        return        FALSE;
+ H* a0 z" W' o% b) R}' h5 c7 \2 I: @. K- @
; g$ z: Q3 E4 p' _% U
void        APU::QueueClear()$ t9 X3 ~- e0 f2 u
{  W9 Y+ ~" P$ [, r: c* j
        ZEROMEMORY( &queue, sizeof(queue) );
8 X9 a8 ~( \0 _2 v8 v* Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );, w4 x- X! V% s4 Z5 l2 C, ^
}2 V; S) A  r1 ?( q5 Q

' Y: A- j% V  |( s) F+ Yvoid        APU::QueueFlush()
# Q$ m* o9 t" T3 l{# e3 g8 {: A& ~+ Q, |7 D2 q/ m: D
        while( queue.wrptr != queue.rdptr ) {
1 y: s, j! N# w) ~4 o4 }/ G                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& p" C9 R: ?- B  D& ]$ ]1 v
                queue.rdptr++;; p% X# N3 O- m! i: X+ s
                queue.rdptr&=QUEUE_LENGTH-1;( B- K& e8 N3 O2 P! y: ]. I
        }
7 c( x3 f* c' q+ {/ G8 r( }: w$ r/ I' M4 u9 J% ~$ f# ?
        while( exqueue.wrptr != exqueue.rdptr ) {1 k9 E" i  ?9 ~) O7 J* [0 c
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
' U2 O, t3 a# A; I0 ]' J( h                exqueue.rdptr++;
. m7 k8 ^! \$ l& T: T                exqueue.rdptr&=QUEUE_LENGTH-1;5 V/ O( r! h, a
        }) @! t; o  N: _1 |! p0 K) n
}' P( f% X5 V. U( ^& n

8 I, O! M6 H9 F) J5 C4 S! c; Pvoid        APU::SoundSetup()
2 C3 ~3 v4 }6 d7 ?* j( B$ I0 ~{
- U: l* Y- `4 s- q0 ?5 T, ]' }; ]        FLOAT        fClock = nes->nescfg->CpuClock;
1 Z) |$ N- K; M4 p        INT        nRate = (INT)Config.sound.nRate;" x0 K' C3 E2 o) H4 {) @! o
        internal.Setup( fClock, nRate );) x# w: v1 }2 }/ M% _" X# K3 Y
        vrc6.Setup( fClock, nRate );+ m* {4 H6 `& [% ?5 [
        vrc7.Setup( fClock, nRate );
: O+ J6 g; b4 R; e; n        mmc5.Setup( fClock, nRate );
; o" Q  V5 P6 {5 M1 i' j' t, c4 C        fds.Setup ( fClock, nRate );4 s: Y+ H4 I2 F1 B- g& c
        n106.Setup( fClock, nRate );
8 d- A( B) n3 v2 |$ ^        fme7.Setup( fClock, nRate );& s6 g9 v  ^: l( M
}
4 x+ x- F. }1 N! B+ J6 h0 X& {: H" q! N* W% m% ]6 Z
void        APU::Reset()
/ I: ]4 n& a% r2 m9 X{" I7 e# j: ]0 F# Z( _5 T; z  L
        ZEROMEMORY( &queue, sizeof(queue) );
) h) K" X) u$ H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# P- K" G! @) _- M1 d' M
; }; b5 E$ P! [1 `( v" L        elapsed_time = 0;
% |0 V$ |" B- y3 a! A/ W
5 ^( A: E( z3 x$ c1 `        FLOAT        fClock = nes->nescfg->CpuClock;1 H4 k( v7 d# ~5 n5 _
        INT        nRate = (INT)Config.sound.nRate;* k2 w; r, w0 ^
        internal.Reset( fClock, nRate );
5 y% b8 H, t+ t! [& V% Y        vrc6.Reset( fClock, nRate );8 b. \, z6 P4 [2 [6 j$ J
        vrc7.Reset( fClock, nRate );% v. Y' r2 m8 ]" @3 R5 r; p
        mmc5.Reset( fClock, nRate );( `6 ?4 g& C0 a
        fds.Reset ( fClock, nRate );! F! ~: F2 w9 E1 K
        n106.Reset( fClock, nRate );+ u3 b* L2 m! J7 G
        fme7.Reset( fClock, nRate );
& I6 V% b: S. K0 {
0 c5 b* I" C  c9 q  T        SoundSetup();) f2 r. @# ?9 Q9 Y4 G8 _; l3 n
}( @, H7 d. X: [, R. s5 t
4 K" l6 a- u" f0 [. U9 o
void        APU::SelectExSound( BYTE data ); U! Q) v* q9 T! K8 e
{" ]3 f* w  b" ~% X& e
        exsound_select = data;
# ~7 Z) y( y  w! J% c}
5 R. n% n/ h! A, q0 I  h" X7 N9 a  d1 X
BYTE        APU::Read( WORD addr )
# x& |  D$ z& |6 M2 {+ W- U{8 q7 }) A9 `! n
        return        internal.SyncRead( addr );
3 E9 \. N! y9 i) p& G& n6 i0 g}7 o  U1 E# }4 O7 V

% `' u6 G( m* ?% P3 Yvoid        APU::Write( WORD addr, BYTE data )* `' \, M9 E( V  X5 Z3 T' ^
{* G$ `. m; {* E* q3 Y9 u: D
        // $4018偼VirtuaNES屌桳億乕僩
' J  I+ C& @: h        if( addr >= 0x4000 && addr <= 0x401F ) {: g9 K6 b/ |0 h
                internal.SyncWrite( addr, data );
8 M7 L8 |% n! z                SetQueue( nes->cpu->GetTotalCycles(), addr, data );, E2 s$ g/ F  ^' H$ J% d2 R6 O( `& K
        }" r/ O3 i  t9 `$ G( l! ]
}
! c9 |1 y) Z# U& g' b3 e- [+ P* r& @( @/ E8 q" l+ I; d: p
BYTE        APU::ExRead( WORD addr )) C* V; w3 X# Z; X4 E3 {; K
{! `# A. M" _9 J, `6 ~
BYTE        data = 0;
, b  `5 s" l, p0 H
5 W+ H, Z" y! f        if( exsound_select & 0x10 ) {
5 l' G# r) a* s- J" U                if( addr == 0x4800 ) {1 a8 D" C7 b6 I7 E
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
# T; C2 L: J  P                }
' E* t1 m9 A0 n' t( v4 v        }
& x* v+ v+ e$ ]" {1 f9 L' s        if( exsound_select & 0x04 ) {7 c0 G8 R+ V7 K, g* M# p- Q  `( `  R
                if( addr >= 0x4040 && addr < 0x4100 ) {
; W" Z4 d4 ?4 J' l* X7 y                        data = fds.SyncRead( addr );
- M/ M3 y/ w! f3 @+ t                }
. \- R) m" S& N        }
) x) _) X) ~; K' w9 |5 @8 f        if( exsound_select & 0x08 ) {
7 z+ c: b2 B/ e& w                if( addr >= 0x5000 && addr <= 0x5015 ) {% F3 _9 I$ u/ b' |/ k+ l  g
                        data = mmc5.SyncRead( addr );
( a* @# @6 l! M1 D, C: S" l                }
6 ]9 c% }0 ~2 K' {6 b  r        }
1 Y& J0 D/ N1 U' ~
! [' \7 S" v- F% w5 M) _        return        data;# L( z6 h. ^. s+ g9 d
}  X! D4 e" m5 E$ U+ J$ @$ L

  s' h/ v  L4 _void        APU::ExWrite( WORD addr, BYTE data )/ L7 d! [2 O: ^5 E* U" g
{5 i& d% @8 |, t
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, c) H1 z4 I  I! C! Y) o6 Y! X! T2 L4 w% Y
        if( exsound_select & 0x04 ) {
* m  _. t4 j" V* A/ T$ d8 N                if( addr >= 0x4040 && addr < 0x4100 ) {
5 K. V1 @: Q9 m3 D4 c* H                        fds.SyncWrite( addr, data );. `4 e. }; a6 ?3 Z5 k
                }  Y* l9 @7 m8 j
        }
4 f1 t8 {5 t) c
1 F' U8 C! Z" U- v" o        if( exsound_select & 0x08 ) {& ^9 P: Q' Y  Y+ j) Y7 |& O
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* D/ n5 b: I5 A! G% ?                        mmc5.SyncWrite( addr, data );
7 Y0 y- z' L% Z; s' E1 b0 i                }
$ C& O; y& \; {1 C' Z' o2 T9 Q        }
! t$ R+ z/ ~2 R. k$ m- d) t}
$ e0 h; ^  e; l/ j4 t/ e7 S: x( \- e3 V( [( K
void        APU::Sync(); f" u: j6 p# A/ T9 z
{
( W  l' H& o) j5 L! D}
0 {2 ^+ H1 I6 c# a% a9 O) l; V
4 q6 z, g9 Q, ]void        APU::SyncDPCM( INT cycles )
. B# [8 r: n- o, a9 h+ B3 |{
; s' C( \  O+ v# i5 E2 }        internal.Sync( cycles );
& D; \0 \$ R6 C2 Z' }9 a4 U" @$ [+ K9 W" `( j
        if( exsound_select & 0x04 ) {
# q* K" d3 {; ^# c. \8 \- `# D                fds.Sync( cycles );; M/ I1 Y- l5 `8 _) E' [
        }( _5 m' m! p: x
        if( exsound_select & 0x08 ) {: K7 f$ r) L. P, l% A
                mmc5.Sync( cycles );( E! L' ~% N6 b" @
        }- n) @+ ~( W. {2 V
}
, n; m+ m5 H$ u; T, p0 P4 U4 I6 a1 i  d  ^; G6 ^
void        APU::WriteProcess( WORD addr, BYTE data )9 V2 w- c8 k& A8 j/ d
{$ e! s1 j/ E2 K; W8 k& d2 b9 I
        // $4018偼VirtuaNES屌桳億乕僩+ T; \6 _' j9 q( ?9 u2 M8 D& ^, Q: z- {
        if( addr >= 0x4000 && addr <= 0x401F ) {( V* s1 O9 Y4 q; o- p& q) v, R1 }
                internal.Write( addr, data );. ]2 V, L3 @' a* g
        }
4 N8 J3 |" g3 C, N2 W$ L# ], U}" W$ E2 a0 T9 ]/ W

5 R6 u8 p; S$ G* J0 ]  G' ?# kvoid        APU::WriteExProcess( WORD addr, BYTE data )
  E" l+ W  S) N( I! C4 ]{
+ m! X. U, L- d$ u* m4 E9 Q! Q        if( exsound_select & 0x01 ) {
; _- [7 a$ K7 q# u9 z' w. n' S                vrc6.Write( addr, data );
* t# E' m7 ~, A" L0 l. P# H        }
9 B  j5 c4 y  M% S5 |        if( exsound_select & 0x02 ) {5 m% s# G7 E3 N- k; L8 s. ]
                vrc7.Write( addr, data );# z" r; v% E% }- e
        }! Y) W. ?% E. @: J; m# S+ p
        if( exsound_select & 0x04 ) {
) d; q2 X% k7 X$ z                fds.Write( addr, data );
1 o& G; z- H4 e% a' \        }5 N7 ?. Q+ z6 {- s# U# ^  G) h
        if( exsound_select & 0x08 ) {+ O- d* a! U- G) R
                mmc5.Write( addr, data );6 D/ q2 L& b6 ~+ j+ G) {4 l
        }# g; J, O1 w. `& H- W
        if( exsound_select & 0x10 ) {
: c+ H5 y9 ]% K& N                if( addr == 0x0000 ) {2 q4 g0 a& k4 \# h5 O
                        BYTE        dummy = n106.Read( addr );
0 m. C! m( F! h$ Z6 c                } else {! X7 k( h: B$ N7 _* _' S
                        n106.Write( addr, data );
! ~# m# U0 N. m* U                }
+ i, {! L' J# @6 L5 v3 M2 I- c8 i        }
) F; O: @& Z/ V9 d& M        if( exsound_select & 0x20 ) {
* @  {4 K; ^, K1 a- G$ Z                fme7.Write( addr, data );
* j8 W; d  R3 M        }
' ?/ r0 W$ J$ G( H. m}, s% U" y/ B7 c) l: a$ A6 Z# S, u! ?
, l4 A1 P  B* x5 y/ s3 z
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
" Y8 @$ R9 t$ G{
# {4 {" X" n5 I& U4 n9 [' fINT        nBits = Config.sound.nBits;* d9 k9 M: F# D% }" x' M
DWORD        dwLength = dwSize / (nBits/8);
) i/ b! w6 {, i  |' Y9 PINT        output;, k' V8 E7 p6 C- p& f: P
QUEUEDATA q;/ Y# j# \+ ~! p' x. H  n
DWORD        writetime;
* S' P. a! x+ P, y1 z0 O: f& G4 o4 K8 [& F
LPSHORT        pSoundBuf = m_SoundBuffer;" e6 S" d( N! S: h% K( ?' h5 A
INT        nCcount = 0;* y2 L0 C: ?, H5 m3 ?% m+ C

) ]) a& _: u; Z* ^* SINT        nFilterType = Config.sound.nFilterType;! s: j! t  Y( q+ t
' p& [+ N" r& }3 Q
        if( !Config.sound.bEnable ) {
. h1 {* ?- s: C: m' L* F* Q                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, i# _- w  ?7 X& q                return;
- j$ [- u% B. Q8 _: A. K2 k        }" G* _4 k" h, }6 J9 x

; X; @4 K  Y/ }        // Volume setup: G* g7 }$ r/ D/ p* G: c
        //  0:Master( R5 o3 d) l2 s8 t
        //  1:Rectangle 1  D9 @: X% s3 ]  V7 e! B5 G
        //  2:Rectangle 2
1 b( U7 H2 I2 Q        //  3:Triangle
: z+ z( ^) p5 |6 g5 K        //  4:Noise" H8 U; f; {. B, v; ]- J* F
        //  5:DPCM/ p; _, U: x* p+ x  a( W1 K* ]
        //  6:VRC69 H( N. K6 Q3 L4 p
        //  7:VRC7  E1 K9 U: o' L- h8 r5 C
        //  8:FDS
7 @  n' l. C- {* f$ Z        //  9:MMC5
* ^) I7 C. @# S: m0 F        // 10:N106
' _' o9 q: n& p8 E: R' w% F        // 11:FME7
  b( P6 S" D8 w  ^$ o; c        INT        vol[24];
+ l, C* ~2 B7 r        BOOL*        bMute = m_bMute;
# A: G% R5 b" X) P  Z* M        SHORT*        nVolume = Config.sound.nVolume;+ q7 W+ z0 j5 E9 Z5 b, Q& K; m$ E  Z
* d0 A& ^: `6 _* Y  X+ @( N" j
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
4 W+ L/ B$ e9 J; G# _8 C5 v. v5 U4 Y9 I! |
        // Internal
  V7 z; a0 V0 R3 X        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
$ r) J& I, Q+ y! A        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; L3 ~8 S' N% d
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
6 i$ Y- y9 F/ ?        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' U, H5 g( u* B! Q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;/ b. x& v0 t! z, E

) @0 n$ r4 v' c  r) [6 d% |        // VRC6! s9 c# L# [; A) @% s
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: Z  F( _2 T- j" m! O* }
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, p5 A! ~+ D. Y2 C" M  r/ x
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 r* T) G& s- g- e6 l( O, a5 F
5 n5 L# H6 a) a7 B6 ]& K, F
        // VRC7
; q/ `; x; l7 c% ]! x) ~0 x+ R* Q        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% e/ e' M3 R9 V2 U2 q2 k8 Z
: A- S+ O4 }: I4 z/ |' J8 i& H
        // FDS: }0 @2 C6 o4 I3 l
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
; `, a' {0 J$ ^$ e3 U. N' p6 B6 ~  U% j/ ~7 m
        // MMC5
  O' Y8 U1 ?! r+ v( i3 X        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ v' T2 _! l# K" t, Z& ^( {
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 P4 k9 V+ P5 a) M- t; k2 {0 j
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# f6 Q7 c8 V) b- W/ P, n- Y  n1 B3 D" w
        // N106' ?( Q, T0 |7 Y' n( y
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( E# H* c- M8 L6 k: d9 ?0 W$ `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  L/ L8 ^1 t! h$ ~. n
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 R7 C+ C4 F' D, G, V, y( u; z
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. N/ ]. A. f' v2 ^
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  [$ {7 H+ g% P9 F0 I5 {4 @
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* _' Y1 @  U3 y4 a$ P
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 D/ ?; c, r" D8 }* u( m- }2 R
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' S# q/ k/ S" s( v
: O0 [* P$ h  {4 W7 `# |5 u/ O! \        // FME7! t0 O; L0 ^! ~$ U: {: Y+ o
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  u/ P4 j4 U9 A4 e8 u# x: I
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ F, s' r, L3 w( Y( k
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ H5 E' c: R& W9 }# _% H! ^
5 ]. F5 `. y" U# O( t  q
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
8 }+ k( n& `- f! x# O8 v        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ ]+ Z, r$ }/ M' J- Q8 }3 q' L) q9 k$ T$ [8 G
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟0 S& ?/ z" p1 e
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {4 h, a( A! f( G) F5 E
                QueueFlush();' [. H  M9 G2 A2 }& c
        }- G6 g9 Q( G+ z* H. ?

: }5 I, ~' H+ y        while( dwLength-- ) {3 o, _3 u9 F' N! z8 e
                writetime = (DWORD)elapsed_time;% c6 `5 O1 E( _4 C/ r( J7 X! _

% Q( t3 c1 q  r' [                while( GetQueue( writetime, q ) ) {
" f+ s# W/ W  U% {                        WriteProcess( q.addr, q.data );
, Q7 m7 f& v( S$ w                }/ n, c& \' A/ q5 p+ N
) S5 l9 z& u- P7 ^- q, V/ _
                while( GetExQueue( writetime, q ) ) {
7 K) {+ {$ s# Y6 n                        WriteExProcess( q.addr, q.data );- M# g4 F: B+ B' i6 Q% E$ M! k2 m
                }
+ n# F/ h# \) x' ~( C* W% T# X) G4 J& d
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
' p: _  F4 V2 x# v                output = 0;5 g3 U2 q8 U9 W  X; U- n
                output += internal.Process( 0 )*vol[0];
1 J* [' z/ O- t9 V1 Q$ v                output += internal.Process( 1 )*vol[1];
. l7 P- N) F; a/ K7 d# P                output += internal.Process( 2 )*vol[2];  L) |) d' t7 t% l+ _, a
                output += internal.Process( 3 )*vol[3];
. ]% S( W% n7 p) g. @* U                output += internal.Process( 4 )*vol[4];
) y! c1 z  {/ B& e5 Y, ~7 R$ s) ~  [; f+ d
                if( exsound_select & 0x01 ) {6 y6 d( h; [7 t! O3 }/ |/ f) G! V
                        output += vrc6.Process( 0 )*vol[5];; S% S: ?; S% y
                        output += vrc6.Process( 1 )*vol[6];2 B) P5 S! V5 N( b" F$ a* v. u8 k/ n/ {7 J! z
                        output += vrc6.Process( 2 )*vol[7];
' H5 \1 r1 b: e  d% {1 {; {                }
( W2 a1 T9 [  W6 F! ]                if( exsound_select & 0x02 ) {
( r0 S+ c3 ]5 z( C$ P5 ]7 |                        output += vrc7.Process( 0 )*vol[8];7 f. r5 S4 \( Y% Y, t1 v9 q5 {
                }
- L; x4 v+ F  }' \1 f: B% p( O- a% a                if( exsound_select & 0x04 ) {" i/ Y1 j/ E  ~. G# ^) F3 z8 F$ U
                        output += fds.Process( 0 )*vol[9];
$ p6 {7 v+ ?6 Z" S( n1 J                }
# F3 [# E, i  k9 Z, H                if( exsound_select & 0x08 ) {
" X  n# \" b! Q- y0 u8 G. t                        output += mmc5.Process( 0 )*vol[10];
: ^( @) e/ w1 Y6 h: o! F; ~                        output += mmc5.Process( 1 )*vol[11];
8 |- _+ t( W$ d% e                        output += mmc5.Process( 2 )*vol[12];; z6 P' X7 y* R) f: q5 C3 G( y
                }
9 C6 z4 M* u- i  A# }" S% f                if( exsound_select & 0x10 ) {6 f  x1 q- {; t+ S4 G
                        output += n106.Process( 0 )*vol[13];
$ t$ v% \- P. W! N8 b4 X* R' d                        output += n106.Process( 1 )*vol[14];1 C2 n2 F% Q  d  V
                        output += n106.Process( 2 )*vol[15];5 Y5 ?$ g, c0 F
                        output += n106.Process( 3 )*vol[16];
& a0 c. j) X9 E' j                        output += n106.Process( 4 )*vol[17];
. j/ H! x+ Y7 L! U+ ]* V                        output += n106.Process( 5 )*vol[18];
$ m7 V% P0 e# B# V, K+ q                        output += n106.Process( 6 )*vol[19];3 h; P; A9 P7 L- ]# Y( R( x
                        output += n106.Process( 7 )*vol[20];1 x5 F* I' C4 C+ Z: Z* q5 z4 W
                }
4 G& l: j$ l+ k8 d0 U: V1 q) H                if( exsound_select & 0x20 ) {' l( a$ B; ^; j3 j7 C
                        fme7.Process( 3 );        // Envelope & Noise9 T# U" d' O' N, p- |" @" x' {' x
                        output += fme7.Process( 0 )*vol[21];
7 G, x9 f  e4 s. d4 Z                        output += fme7.Process( 1 )*vol[22];/ c) c6 H( B. q) M
                        output += fme7.Process( 2 )*vol[23];; ^6 k: t5 m0 M' y8 _
                }
9 F+ I' p4 i* M/ b+ i: j* M8 p6 I% n2 \/ K! v+ x8 ~
                output >>= 8;
/ X, h$ n8 D6 A9 _( F3 |4 A2 B1 @* U9 Y4 X( e. x0 Q  C, w) R
                if( nFilterType == 1 ) {% [& E# n5 s1 n! L
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: s* {( g. M6 I                        output = (lowpass_filter[0]+output)/2;' [  x7 U2 O% K7 i8 U/ h2 `
                        lowpass_filter[0] = output;* R* R. n5 v8 ~# h
                } else if( nFilterType == 2 ) {
& l' {! W  g, w8 V" F% [% ^                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 c( p( D( I) P' c6 F                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
9 i+ K/ C) J8 U; s                        lowpass_filter[1] = lowpass_filter[0];
' U' b5 i1 H( \1 ?  E$ \  h* y6 H                        lowpass_filter[0] = output;$ L5 I( E: F+ p) C3 ~5 z
                } else if( nFilterType == 3 ) {
7 o2 s% k4 i# w                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ |* f* V8 M4 [6 x! Z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;& @; Z0 [( D) {' \! B; e# k& p6 O  a8 `
                        lowpass_filter[2] = lowpass_filter[1];
8 X6 I$ \" K! q                        lowpass_filter[1] = lowpass_filter[0];
0 Z2 y8 J' K4 b" e8 @5 X                        lowpass_filter[0] = output;9 F8 E& D* y* p! r! U$ Q
                } else if( nFilterType == 4 ) {
2 ~8 F0 [4 q- X/ {/ W" w; y                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& s4 u# C, x. Z; M) E, R
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;/ F. h# W' B* h9 C- B
                        lowpass_filter[1] = lowpass_filter[0];. l# Q5 a9 v- w* b
                        lowpass_filter[0] = output;
7 |3 B: K" I+ F& q; \, A                }
' k* Q4 [: f$ F) s1 V% X* H0 k
#if        0
- t, a% b5 I2 n9 x: R8 {3 x                // DC惉暘偺僇僢僩
- ?& t: j2 J' v4 e0 e" a                {: |) z( _- g; H+ S1 h- b
                static double ave = 0.0, max=0.0, min=0.0;
. g, O: @% L! @9 G) K/ g                double delta;- \, {( d* d) @9 I+ a: N5 W
                delta = (max-min)/32768.0;
9 m& o6 K& _1 a: X                max -= delta;( E% Z( \* N9 \2 F' c
                min += delta;
1 {' y+ k; ^% r( H! d" P. D                if( output > max ) max = output;# c( V) z& A6 U# {" q- h, u0 q
                if( output < min ) min = output;2 Q. j- l2 N. y# ]  B
                ave -= ave/1024.0;
' K( ^) l' x# }& R: S7 w                ave += (max+min)/2048.0;( f1 H0 W+ W% c# N1 n9 Y2 s) q
                output -= (INT)ave;
5 N1 d" z* z+ E) j9 k, G0 p                }
' ^+ D2 R# I. ?( ?9 A#endif7 E9 S, S8 _, U( V- e% {; k
#if        1
. g8 D9 X7 A6 n                // DC惉暘偺僇僢僩(HPF TEST)% m" Q7 [8 _- f! t! U
                {$ l; V) W" @7 `7 S
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 ^, X, l; U( Y9 R
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 o. z5 o- @. k. G                double        cutoff = cutofftemp/(double)Config.sound.nRate;5 o3 w7 {2 w! v
                static        double        tmp = 0.0;. L! q0 l% D1 k( J. ~4 H3 I
                double        in, out;
9 u- {' n$ |% j1 j1 K( ?6 ?$ x/ ?) y8 Z/ s
                in = (double)output;5 c$ z/ H' Z2 u' S
                out = (in - tmp);2 s! E5 E4 z  ~
                tmp = tmp + cutoff * out;
" t/ Q% g4 D# f6 c: k# @6 t/ I0 a1 }
                output = (INT)out;
: W/ D) R- O: `* G9 H3 s                }
2 a, h) ?: I- }5 F4 d7 X#endif. H* ^, Z" V" m5 E$ |. s& Z, J
#if        0% r0 u3 V0 x# m  I5 Z+ z9 h8 L0 R
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)$ H- L( G+ q) P3 w1 l1 k
                {' n7 @3 B2 Q; x* u% E9 r
                INT        diff = abs(output-last_data);6 L3 c7 @7 \, X
                if( diff > 0x4000 ) {
5 P* j" O# }) X7 I# ]                        output /= 4;3 p1 x: `" M+ e) o0 ~# ?/ f: z
                } else : O! c; t6 E0 a$ k/ d
                if( diff > 0x3000 ) {, i$ j5 j' x- `: b4 C
                        output /= 3;
- W& J6 e7 I4 Q6 v+ @$ f1 x/ y! s                } else$ Q* z* B6 o$ n0 d, U, p" K; d
                if( diff > 0x2000 ) {  L6 K& M- }. c
                        output /= 2;8 c2 E7 S( V  x
                }1 n' c: ]; Q3 Q% G6 g
                last_data = output;8 W+ C- O% ?4 Y
                }
7 P/ @6 f$ _( l( C- M9 a#endif
! G! v$ |( h! k                // Limit% f, Q: |0 `1 d0 ?! F7 m2 m4 i4 }
                if( output > 0x7FFF ) {7 o: l9 u1 F% G* \" ~
                        output = 0x7FFF;
( s. D+ |% _8 z                } else if( output < -0x8000 ) {: w# j6 Z7 O3 b+ }; {
                        output = -0x8000;" C/ D! G* d' A- p; S$ ?. A  B+ [
                }) [' f; n* \# q) `. I3 F

9 L; F9 n4 `6 l5 A5 \                if( nBits != 8 ) {
3 O, z+ @8 k: `5 R$ ]  }                        *(SHORT*)lpBuffer = (SHORT)output;- X2 S/ [$ c2 h( F/ X
                        lpBuffer += sizeof(SHORT);
0 L% [& \: @. V5 k2 P+ N6 ^                } else {# k+ {- f" F' V$ x; A+ w9 b
                        *lpBuffer++ = (output>>8)^0x80;
1 j% i) \! @6 }: ^& k6 A                }; A3 L: u- B2 u" ~- K# D

: G; \- y! f/ d6 \7 m( ^                if( nCcount < 0x0100 )
3 s: I& W: g! E+ B  g: |! X  X' y                        pSoundBuf[nCcount++] = (SHORT)output;; D2 e9 }6 L8 r$ l
  S- d" e3 |& z4 u( z' a3 [! d1 t
//                elapsedtime += cycle_rate;
+ }) d2 Q9 w1 _" w* l$ a2 b( J                elapsed_time += cycle_rate;
* _8 K# V+ e. Y% h: `, M        }8 C9 {/ v; |/ R' G0 v* _9 p
- j4 X% O* R; Z: t# s5 Y; w) m
#if        1& l8 B  w2 V, ]1 Y
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
6 P/ I; t3 ^. K" ]8 B9 K2 o, r                elapsed_time = nes->cpu->GetTotalCycles();3 }0 ?7 x4 W" u1 b& \
        }/ Z6 B- J$ D$ L' _9 k5 M
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ L5 w7 r/ ^/ l8 l  w+ Z
                elapsed_time = nes->cpu->GetTotalCycles();0 T/ L1 {) M" L0 G
        }& I  j+ a" `5 P3 x) a2 W3 Y% D1 j
#else
; r' v, D& e9 W        elapsed_time = nes->cpu->GetTotalCycles();
# [- n/ [& z) T* n/ |$ K& E/ D#endif& N0 _; I/ \+ V  ]* |
}0 d5 d5 O) l* p
& i/ L$ P: p, ?5 d0 A9 z
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
8 o, k, R* T$ K+ ZINT        APU::GetChannelFrequency( INT no ), |* U' K! J$ d) v
{
! |' f  |, C- o) U" x2 h: n4 }        if( !m_bMute[0] )
( h# w, ]6 w1 @                return        0;
7 X  F, s2 n0 O" ~6 |7 V5 v
5 h8 c( c1 Y  h        // Internal- L; k. t1 N; g( \) C; L3 h
        if( no < 5 ) {3 G$ a) C, W4 s3 _
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
' Y8 k4 K. ~, z( |4 A& O0 P        }' B0 e4 R* y, ]7 b3 ]
        // VRC6
. A* n$ |6 L6 n% y: X8 [        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
# u) K  t! F6 X" T0 x                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
5 Z. X0 O( D. O6 Z- O7 t        }
+ ]4 }* f1 z( ?        // FDS" i" B  _0 X: [6 ?; ]
        if( (exsound_select & 0x04) && no == 0x300 ) {8 s2 c) J: N" g% t2 H" P( Q) ?% i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# Q+ A, x7 Q8 \* x1 T( F2 ~
        }' b8 ^- ?0 A+ B3 i
        // MMC5
8 B" ~) h+ P9 i3 O% }0 p- N% f" |        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {! z0 K, h9 r* F& W: h
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
0 s9 b: g6 x( K) g) O        }
) C' q5 q5 m4 ~  @7 P        // N106
1 U; y. w1 L* j! Q7 E2 a4 ]4 I        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 {, V( ?8 d% F3 B' }) n                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 C& K% T2 s  G  y2 ?. \
        }8 b; ~7 Q) ?- |8 M2 v; d" i! u( v
        // FME7
* ^- b% U' H- K4 _$ o* t1 a7 A; C        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {- H1 B) S2 ]; `3 B
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
- a( O, N" W+ F* z5 H0 ]0 W        }
: p# t1 Q; D% S+ q        // VRC7
4 @. t- q8 R) Q) F5 k1 [" W        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {8 Y# I6 Q+ `* M' t
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 o7 o5 A; E/ v2 M7 q+ ]3 ~' `
        }
( Q% c6 R. r( h8 K! K* I0 p        return        0;9 O; u0 d7 b' b" T4 Z
}  V8 I: _  d. w: G1 N% t
+ T- u7 b- Q7 g! ]% a$ Q
// State Save/Load
0 w7 p2 \, Z& jvoid        APU::SaveState( LPBYTE p ). H1 Q7 G' `; c4 z0 G$ ]* m
{/ L' d# @# B% K6 s3 D& Y- c+ m
#ifdef        _DEBUG% r. e% @. U$ v6 S: p" h% A2 `
LPBYTE        pold = p;
% C; ?" H* P: `6 a7 H#endif* y( g' X6 @' `- j
, M2 [0 Z, f9 \4 ]7 K9 `- q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
" j( \+ t, x: @5 t" P; D' s        QueueFlush();
: M1 j& ?; O. Z9 q0 k0 g  }, V" K0 _$ w7 S) x
        internal.SaveState( p );+ P) L2 ~  |( a! X. h9 q* t& Z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 J$ `4 x2 A5 \' M* j0 k/ [- y
! I+ ^% O+ Y# J) i        // VRC6, x# U+ M0 F" R# n
        if( exsound_select & 0x01 ) {
; I8 L# p7 W# k% Y$ e- ^% x! O                vrc6.SaveState( p );8 r9 f1 d# z* l% d, Q* B2 m
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 Y9 K5 x. n" q) l  Z/ T+ e1 V. N! L
        }/ ~/ K3 ]  b! ~; H
        // VRC7 (not support)7 S* Q# i6 M1 D% T3 M: _
        if( exsound_select & 0x02 ) {0 K  d- {( P. y& j; R  J1 Y
                vrc7.SaveState( p );9 V! h" |- R4 V9 t; z( |! B( q% X
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 T1 F" V# \' z' l: K; x5 o4 `
        }
1 j5 H; J7 ]# ]3 `) T0 N0 E4 H        // FDS
4 H3 ^0 E# L5 X& W: [6 h9 K        if( exsound_select & 0x04 ) {
; J  ]! U# W) }1 Y' K& p                fds.SaveState( p );
& k- u* Q; U5 X4 A9 b5 p% m7 B% X                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! t5 ~: h8 t* X, }# U* ~
        }
) v" ]/ U5 T0 v3 |  P4 u3 J) t4 _        // MMC5
+ I$ k* B" E! z% [+ |        if( exsound_select & 0x08 ) {3 |6 M" c- n* V& |9 }% d. ?
                mmc5.SaveState( p );6 f% G. N% Y# Y  O5 S2 [* r
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 [$ U) e3 {2 q; ^( R        }
6 N1 R4 t/ D4 P# i: C. a, S0 g, L        // N106
4 C* y- ]) k; s$ H        if( exsound_select & 0x10 ) {6 S7 c2 f, Q- I! u( q( ]
                n106.SaveState( p );
' _9 u! P2 s7 s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding$ P6 `5 }3 R& K3 G7 [
        }
0 O4 Q6 }4 g/ w4 W  S4 r& K        // FME7
. f: ~" |5 X1 U2 O: v        if( exsound_select & 0x20 ) {0 P6 `" w1 {% S3 V2 k4 c* {" D7 T
                fme7.SaveState( p );  Y+ L; o, _1 O: D% m: i! n) y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( s; v; T6 }$ D. R! e+ J7 p7 X        }2 y$ D5 E9 g% N; ?0 B" Z+ O
8 P$ Y8 d1 R2 `% a5 y7 N3 L- y
#ifdef        _DEBUG
; t. S# X. b) ]1 h7 B- RDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );; C7 n" P/ C5 |) e1 C  q! _
#endif
$ R3 @2 ?- d: l5 ~}
( }& `+ J: r' b# _) F; N3 Y& C! u$ u' T8 N7 V1 ^
void        APU::LoadState( LPBYTE p )3 n9 x" r" L- J$ F. W7 K
{- v7 j! q5 F: }$ M
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ o4 H) ?. B) g+ Q7 p: H9 \
        QueueClear();! }5 ^' T8 I# u1 H9 K
& [, y9 j5 k6 W2 i( [
        internal.LoadState( p );6 y$ K1 h  O& }( A# L0 L9 l
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 c8 z/ |' F0 b$ T  ?: Z" B+ d" n5 @2 F) `. w9 r2 d- Z/ k
        // VRC6
1 p4 @& g0 W4 r- Q+ x: |; T- l6 L        if( exsound_select & 0x01 ) {: ?  X; D, K% A# w* X3 Y
                vrc6.LoadState( p );
! G- E5 B  a" S                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 J9 v- Y3 `) b  p; k        }
3 c8 C8 s1 O5 C* M" k        // VRC7 (not support)
0 s$ n, z$ d. N3 B7 e        if( exsound_select & 0x02 ) {
8 o. t% ]) t3 P# E/ D& y2 ^& q( H                vrc7.LoadState( p );
- U* M4 _& K7 R+ E  X% a                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 }( H" j: a, s+ _: r
        }5 v' }- ^6 H6 z/ |2 m
        // FDS7 k/ I  O/ V% F4 O$ g. R& M: W
        if( exsound_select & 0x04 ) {: [# ?" p. y3 ^
                fds.LoadState( p );
# @) z( ~7 O: c5 ?# U                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) P. {7 }! r+ K- u8 R        }
) V2 i9 H8 `% `/ U; [2 z        // MMC5% n8 B; w* ^* T1 s
        if( exsound_select & 0x08 ) {
8 M0 B% t* _9 w: I/ f$ X' f5 W' Y                mmc5.LoadState( p );
/ s2 F1 L, }+ G( D+ q+ x                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# @" s! }1 O- W- [3 u/ A3 ^; c/ y
        }
5 {% d: m- F) Z0 |        // N106; S! g% h( o4 W7 w! _/ e( r
        if( exsound_select & 0x10 ) {0 \; V( L; @' J. M; S
                n106.LoadState( p );; b5 k1 x4 u+ |. v# a3 c5 f+ N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" P2 f2 x: j" I5 Z8 D5 C        }
1 V5 d& N. p. @) p) Z$ ]6 J0 f- k        // FME78 N' X2 A) t6 _2 [* h' H8 c# Q
        if( exsound_select & 0x20 ) {5 G( Y, k. s  X5 s0 B* U' R- T( U
                fme7.LoadState( p );$ c; g' D4 q: y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 w" h( C0 |* K; R        }: O7 |/ B, x0 G
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
1 h6 m* G$ d3 ?9 m$ G& h可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' b$ O! z( c6 d0 J7 [感激不尽~~
4 u  x4 e! z, u3 p& r
恩 我對模擬器不是很有研究,& a7 U' O) Y' L
雖然要了解源碼內容,可能不是很困難,
! Q) h; M# c1 l& N不過還是要花時間,個人目前蠻忙碌的。8 o% u7 N/ l  Y9 b8 M: _
0 ]4 L. N1 {2 u+ e6 `
給你一個朋友的MSN,你可以跟他討論看看,8 Y2 S# N5 }3 f' f, W4 g3 ^
他本身是程式設計師,也對FC模擬器很有興趣。
* J. K8 h  Q. \
4 c( n; d3 O! p8 gMSN我就PM到你的信箱了。5 e: ~8 N4 _4 c

1 Q, |9 f" \: P& h6 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 发表
; d4 z" m. {( ]9 \- B呵…… 谢过团长大人~~

$ Q8 H# Q3 {4 V( V+ q6 B: J, G; A1 I& T( n8 n/ F
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ B$ F% {% q3 i/ O) G团长的朋友都是神,那团长就是神的boss。

' u" X; k* c4 g; D' c! u" Q" S# D哈 不敢當,我只是個平凡人,7 ~$ @$ ]6 i, [& `
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 B  S# K0 Z2 g! a/ r. u; mZYH$ k% Y# O" t* k* A$ m
QQ:414734306) X% g. U3 `2 M  C# y
Mail:zyh-01@126.com
) T+ L- F* h( d( b3 R+ I
1 u, e! K6 @  E* e5 ^$ u, x  w0 R6 A% V他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 x4 L6 B/ ?0 ?4 S9 |+ @再次对团长大人和悠悠哥的无私帮助表示感谢~~
9 l# z1 Z% y- G/ C! F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-7 21:09 , Processed in 1.076171 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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