EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 s4 p- c5 T" l' H/ H" V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! z% R# j9 }! L0 f9 W
这里有相应的模拟器源码,就当送给大侠了~~
7 k9 f7 g  \# O% a* i6 Q5 X$ `http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( G2 w  {- z9 u# D能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 U/ y' ^9 {- Y! m* y; Q) r楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# _  C" w0 }4 ?, ~% P: B这里有相应的模拟器源码,就当送给大侠 ...
/ ]1 m% o; f3 B1 q: p
聲音部分(Audoi Process Unit = APU):
0 r  k" c% o8 h. m.\NES\APU.cpp7 X9 g( Q7 V) }8 N0 Q
.\NES\APU.h
1 y) N. D# h6 [8 J9 p7 B0 _# u% H# d

$ k, L! I9 i9 z; k# j影像處理部份(Picture Processing Unit = PPU):/ m( b4 L# ~) ?- m
.\NES\PPU.cpp+ [0 {$ b3 Y# K3 K# L0 E/ g4 }) X
.\NES\PPU.h$ s+ {7 G# c( r3 {  d2 o3 h

: E- c: {! A: J( U' n; \: U如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 z0 {- r5 K" i  ^
(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 \6 e8 P: y4 F5 h5 V) N
//////////////////////////////////////////////////////////////////////////
3 X, d/ m6 B( ]4 D//                                                                      //
6 D& k7 T% M/ Z2 _$ a$ U//      NES APU core                                                    //
( \: U2 k' P- J//                                                           Norix      //3 p' W0 Y% G* M
//                                               written     2002/06/27 //) y- B" n& n7 [  i3 i; @
//                                               last modify ----/--/-- //: ?# f! P9 e# m* X7 l! Z
//////////////////////////////////////////////////////////////////////////! C0 B6 H% \( R2 f# F+ t: B5 b- x
#include "DebugOut.h"2 Y. s/ q$ o' ~, A
#include "App.h"8 U6 t, ]( s( S  B/ |' ^
#include "Config.h"1 N( V% M4 f" @9 V. C+ x
8 K' `' p8 B) F) T
#include "nes.h"
6 ?- S7 V" ]+ {" l6 q#include "mmu.h"
& B7 k4 c2 j' P#include "cpu.h"* a; m- m* `+ o7 P
#include "ppu.h"& X% b4 w( r3 J& M; Q# J- J& y! R( b( I
#include "rom.h"7 E0 I$ R# X" {4 L+ R  g
#include "apu.h"
' @* I8 m; b3 T* K7 l
2 }/ ?$ R0 i3 \/ ?// Volume adjust
8 [2 o+ l- C2 m, p- i5 b* C# ~. l// Internal sounds
" D/ k* Y% E5 Z2 E#define        RECTANGLE_VOL        (0x0F0)- W. ~( K. M6 R: [4 P" m
#define        TRIANGLE_VOL        (0x130)# r, {4 b$ d" E# W; Y: l5 n
#define        NOISE_VOL        (0x0C0)! ]3 A# ~0 f1 |; q1 {
#define        DPCM_VOL        (0x0F0)
0 c: m; A. ^! n/ Z1 T/ N$ N% s// Extra sounds
, c; U. g7 w3 U6 T1 }1 O% p5 T#define        VRC6_VOL        (0x0F0)
. O2 S, e8 N3 I8 U) d- {#define        VRC7_VOL        (0x130)
) I6 r' a' Z8 H$ l#define        FDS_VOL                (0x0F0)
% U6 \% p! `% t" ]- ^#define        MMC5_VOL        (0x0F0)
8 q$ S1 H+ x: s6 \( X2 m# [#define        N106_VOL        (0x088)9 H* ?$ y: ?; K8 z6 s
#define        FME7_VOL        (0x130)
5 ]6 a% C& D  N
: _8 H, W" r# c' w1 n6 X( gAPU::APU( NES* parent )# I8 i. L2 ~* _2 H; W4 @) a
{
6 ~  H6 v* Q, T9 Q, ^        exsound_select = 0;, N: w3 u  W; W: C; {
+ C9 K: m- H1 d" g' G4 R8 m, r
        nes = parent;
4 c2 K# J8 Q0 A1 W        internal.SetParent( parent );
% n# Y) O" M8 h9 G7 X  C
9 Z; ?* W# [$ z% f2 ~        last_data = last_diff = 0;
9 k7 X3 S6 @6 h9 V/ R- R# V% z. ~  l2 O5 H
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
! N% j) R1 O0 L8 a( v. c0 b& h2 }2 }8 B4 c
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );9 K% f# r9 }6 H% _, D* Q
        ZEROMEMORY( &queue, sizeof(queue) );
1 D' _) ?' h6 `  D$ ~, q: n9 o+ l8 b        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 Q7 a! o% F8 f6 L4 R0 p0 e" }& I6 W6 o

4 ]% q9 ?6 Q5 K/ J# h% Q* t        for( INT i = 0; i < 16; i++ ) {
' F6 I" j& i  @+ ^                m_bMute = TRUE;
1 r, W1 Z! Q: l        }* O9 ^2 I0 l6 b* _3 J
}, o5 j7 i) @2 b" a$ D

. i* g& a. [2 K  T- V; }APU::~APU()7 J; V& H6 ?" h( B6 ^3 J
{" C& d0 h: B/ k0 a
}" u4 @0 a. P& r/ }1 ]
& r6 a$ T' G" z5 h2 F" b
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
2 ^2 @/ [  B4 T  w: s& c{2 P/ \# k+ O+ T6 A; b1 ^
        queue.data[queue.wrptr].time = writetime;4 M* ]% g, C% q9 E2 `
        queue.data[queue.wrptr].addr = addr;
' K4 ~- B2 r5 z) }+ @4 J: E        queue.data[queue.wrptr].data = data;
* x, _$ V) N. q0 }6 D: j        queue.wrptr++;9 k* V/ B6 C3 o! ^/ ^; _+ O
        queue.wrptr&=QUEUE_LENGTH-1;
; R$ t* F  i0 f) g! L, \        if( queue.wrptr == queue.rdptr ) {5 p/ M3 C7 c/ T: R
                DEBUGOUT( "queue overflow.\n" );
9 |+ u& x8 X4 e( [0 y" P        }
" F- L) n$ y2 v6 G}) }8 r( a& W3 v) A0 X
1 P3 ]3 S6 }+ r( J% f
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )3 I! D& Z' O( H
{
5 X/ F' J) o5 ]. w7 |- s+ u        if( queue.wrptr == queue.rdptr ) {: |+ j4 Y' C4 u
                return        FALSE;, W+ T- F. F3 R; [- @  A
        }  t( L4 `1 f. B8 F4 C
        if( queue.data[queue.rdptr].time <= writetime ) {& Z3 c* K3 |; i1 ~
                ret = queue.data[queue.rdptr];6 {( }& |2 W( |" J( W7 ^9 \& V
                queue.rdptr++;
. ?7 C+ Y/ w& N" j3 v  n                queue.rdptr&=QUEUE_LENGTH-1;. R0 @1 S" Y% x3 @! D: V
                return        TRUE;! B( r; g7 P/ }+ p
        }
; k, Z. l) r, V& C        return        FALSE;& H7 K2 j* n! b$ Q: b$ _0 _3 L
}* ?9 e" p, @: g5 E% I% A( H  M
9 a4 U8 _4 A6 j& K; j
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 G0 u7 Q) y3 w; ^# h{! l$ F* R2 L! q, S. E8 a. K
        exqueue.data[exqueue.wrptr].time = writetime;# X! y4 m0 B7 E, N* u
        exqueue.data[exqueue.wrptr].addr = addr;
+ t2 t% v/ ]7 U6 a+ [        exqueue.data[exqueue.wrptr].data = data;3 f% H% w2 d8 [. J% u
        exqueue.wrptr++;' A  e! z% e! k) Z/ l
        exqueue.wrptr&=QUEUE_LENGTH-1;
& n7 O) X6 U: J, _6 u        if( exqueue.wrptr == exqueue.rdptr ) {: g' g) J3 @5 [" B8 l
                DEBUGOUT( "exqueue overflow.\n" );
/ V: Z. a) s. N0 s        }
7 K/ K# C2 Q4 L- b}7 U  ~8 I9 L* G  A9 B

: C2 `7 i3 n! a1 I3 `7 RBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
1 f8 G( y, S! g3 I4 Z8 @{  e9 V* J* q; g7 ]0 ~
        if( exqueue.wrptr == exqueue.rdptr ) {
! M% l$ r- V4 p) j4 e                return        FALSE;+ p3 D4 C8 o. H
        }, K3 E5 A+ f. C/ [
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
2 F, \, R# G$ L* a% Z' j/ ]# ]4 \                ret = exqueue.data[exqueue.rdptr];
3 ~! ^  n1 l7 ^+ W- C. c  p                exqueue.rdptr++;
) s/ m( q' q1 E: }                exqueue.rdptr&=QUEUE_LENGTH-1;
* j, H4 B* J$ a                return        TRUE;5 c: _% v: R! C3 [" Y
        }
& x$ E. u7 o5 g3 s$ }        return        FALSE;- r& g. f& T3 S+ ^+ }
}
! G5 ]  X/ ]0 p/ B! J& ]* S4 y. O+ B: v% u
void        APU::QueueClear()
) U" r! S4 j8 z, ^3 ~{, T+ @+ m1 _# _0 d
        ZEROMEMORY( &queue, sizeof(queue) );
: B* \+ R9 k/ G        ZEROMEMORY( &exqueue, sizeof(exqueue) );, S, i8 |( ]7 ^/ l5 p& X1 i6 u9 ?
}
# O8 u, y2 l! b+ E' B1 {5 C+ n* s5 D5 W, i+ [1 N2 X3 L# c  ]/ R2 p
void        APU::QueueFlush()
. Z' D+ D! n9 Y% R{
0 L( M" m6 |/ L; F; D. M0 _; c        while( queue.wrptr != queue.rdptr ) {- [# S, Y" U) H7 v5 a
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: L" J; t* C* c! o+ T$ v7 l& q  o                queue.rdptr++;
& V2 k( n- @6 n4 s0 Z" e                queue.rdptr&=QUEUE_LENGTH-1;% h/ p# f) f& e; \: ?
        }% m6 F) X' \+ }6 G3 B2 J

- n! w" ~0 T8 @: y, k8 e" _  y        while( exqueue.wrptr != exqueue.rdptr ) {
1 N1 f, A/ _7 t5 k4 O                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
% U/ W9 e& \& q" {                exqueue.rdptr++;1 X5 u) n. E) m/ @  n1 m4 o( _
                exqueue.rdptr&=QUEUE_LENGTH-1;3 B2 n! @9 `' V" m3 T2 P
        }
9 I0 Y2 ]; x/ ~- u5 n. E7 x+ X}
; n$ y" M6 t: T& E9 x
! }5 t! p4 ^; s7 E) ovoid        APU::SoundSetup()
0 R# f) l2 x9 S0 z, O  a- D8 W! t{
3 B7 @5 V$ _6 X) W' G: U) J        FLOAT        fClock = nes->nescfg->CpuClock;
8 s+ d* ]; ?9 F6 Y# i        INT        nRate = (INT)Config.sound.nRate;
! F* _' L+ @. x1 n  g& [        internal.Setup( fClock, nRate );/ T/ T8 ?( w) N) k# E1 I
        vrc6.Setup( fClock, nRate );
/ y& X$ O% D8 J  a9 o# `# R        vrc7.Setup( fClock, nRate );
8 H  v. b' L6 \1 v        mmc5.Setup( fClock, nRate );
/ e. t( n% B! K# r% |% G1 `% a$ k        fds.Setup ( fClock, nRate );8 x  R$ ?9 b5 P
        n106.Setup( fClock, nRate );
' f" L3 F: g6 z        fme7.Setup( fClock, nRate );
; {' ~: D1 a) K: L}, c3 Z1 j) _# f$ S; a
. q- u/ u, F, W# r( ^
void        APU::Reset()% a- a( W( t: b, A3 T
{
% m- E  w' `, C7 }9 f% O6 @        ZEROMEMORY( &queue, sizeof(queue) );4 f0 i' \) N: M2 p
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! W  e+ F2 _; u" Y1 R# b5 a" Z6 L& v/ O  i
        elapsed_time = 0;
) J4 i* s( R2 M9 y+ p& i! [3 h' D  ^/ W
        FLOAT        fClock = nes->nescfg->CpuClock;
0 A. r5 Y7 G* s- Q4 U        INT        nRate = (INT)Config.sound.nRate;; e. L6 a; x+ ]- }% G- U( M
        internal.Reset( fClock, nRate );
: m/ N) ~  U8 O, u        vrc6.Reset( fClock, nRate );" x; u$ ^' i1 |% y& J# i
        vrc7.Reset( fClock, nRate );. E1 W2 H$ H7 G
        mmc5.Reset( fClock, nRate );0 P$ z1 D4 O3 k: p1 Y' y2 s
        fds.Reset ( fClock, nRate );$ ?. }. V2 d+ C1 G& W
        n106.Reset( fClock, nRate );' [: J  ?1 S8 v; P2 K! D
        fme7.Reset( fClock, nRate );3 M8 T' F& L' p6 J7 D- _* i1 |$ ]

  \3 d+ i0 ?! I- ~; P        SoundSetup();
. q2 W7 q6 b6 K+ y}
; R+ ]) S, |' B7 I3 r0 i  V; ^. T* Z9 i0 g6 I, Q
void        APU::SelectExSound( BYTE data )
5 }/ q8 D. K6 E$ o# e{1 S9 d8 z8 f, n4 v* d& ?# x% F
        exsound_select = data;
  z7 f5 ~( X9 x. f}
& W$ T3 K6 K4 d! n2 ?4 N2 t
4 f( X% [* q/ ]6 qBYTE        APU::Read( WORD addr )
  x1 e' |+ V; Q  R; y& i; e{  C. P7 Q: W! x" \" F6 F+ _0 W
        return        internal.SyncRead( addr );
0 r6 L; t7 ^* W# c4 Z" k* I% S4 N% Q}
# z6 s; B  U& Q( A/ J8 v) |# W( n8 @$ T- n6 U
void        APU::Write( WORD addr, BYTE data )
: r0 z! E' x' V5 U, ^  }{
/ j4 a) ?1 [: c3 \% n) a        // $4018偼VirtuaNES屌桳億乕僩# ^# W- C) b6 A' p  n
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 t) e8 D* ~7 A: Q+ s8 N. S                internal.SyncWrite( addr, data );
% a; Z" E6 j6 d9 C                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
4 R! }( A9 N+ S8 ?3 [8 N/ I9 J  J        }7 S; _9 s0 U2 `/ q( H" Z
}
$ V, x. s! y; H5 j9 s% |  \, i6 E- ?. D3 O  F# l3 w# A
BYTE        APU::ExRead( WORD addr )9 c+ X$ t" B3 u5 x  ~
{& ~" h7 w5 y/ j# J( R% ?
BYTE        data = 0;3 p, r; l# Y4 \3 p" q; d

5 g. i3 v  F  @        if( exsound_select & 0x10 ) {
( T4 [% r; H0 ?& |- H$ Q- u5 v& Y  m                if( addr == 0x4800 ) {, ]5 r- Y0 S$ q
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
! n) t9 D7 r1 V7 z. _! t                }. L, U% W$ T- d4 N3 y8 M) ^
        }
5 t' i9 x5 l- _0 S9 o        if( exsound_select & 0x04 ) {
9 \, o2 Z- [4 D4 R7 K7 J' L! s                if( addr >= 0x4040 && addr < 0x4100 ) {3 O0 c( L5 i: ?0 k' P1 _# e8 C
                        data = fds.SyncRead( addr );
% l) f7 ^5 p; ?% v$ V5 }+ Z1 W                }
& l* [& H5 n" i  e, D        }
" K6 a9 [! m/ S1 M, V# N        if( exsound_select & 0x08 ) {+ V( l/ v4 x0 W: P
                if( addr >= 0x5000 && addr <= 0x5015 ) {# |' G% j( v# }' v0 t) K3 r
                        data = mmc5.SyncRead( addr );
9 ^9 h* p) b6 o4 j, Y                }
7 x' G6 g0 k8 S0 s        }# M& K9 h/ B) b" N# S
9 K  _" H1 w* E, ~
        return        data;) }6 I; s5 @2 q8 e
}
! T' e5 V: C! ?2 ]5 z6 p
9 u9 R  C6 G; @5 X4 x; c- a8 tvoid        APU::ExWrite( WORD addr, BYTE data ), ]2 y; m. r7 Q
{5 k1 s- }% K0 y% D
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 X$ n: B* [2 p1 m

$ Q# e% F2 c# B' W! c        if( exsound_select & 0x04 ) {
9 X% |8 S. x. o1 N                if( addr >= 0x4040 && addr < 0x4100 ) {: h9 G' T0 E6 ?+ T! G
                        fds.SyncWrite( addr, data );/ J2 S# `1 G4 p1 b- }" \6 U
                }) q+ w& v, u9 s2 q) u
        }
1 `. Z7 g! U5 `& k3 }2 U8 @- G% L& C( c+ \
        if( exsound_select & 0x08 ) {/ r: b) |& F1 Y6 W0 w+ ?0 X
                if( addr >= 0x5000 && addr <= 0x5015 ) {
% n) z9 w: ^0 U1 }$ l  _                        mmc5.SyncWrite( addr, data );
: N& w7 @1 _1 ?* p                }
/ }/ F2 k0 w9 H8 E6 q( ?        }9 I+ m% H# p8 Z( D6 U0 g' B; _4 K
}
) ^3 Z& v& u8 ^9 E5 \
4 Q! p4 H( o3 ~, Z8 Zvoid        APU::Sync()  \( Q" Y0 T: V0 g; F
{8 ?& e2 V2 {4 k/ L0 b
}7 S0 k) ^3 _/ ~
! x) k! B4 g- q7 F3 \; o; I4 d
void        APU::SyncDPCM( INT cycles )7 U! H! I6 J/ J& w8 F5 |" l- ?4 C
{
" M6 I' E, G) e  r5 E* v2 J  S/ {4 g        internal.Sync( cycles );4 X( Y  P! B- V

& M8 E9 |( G5 |* U        if( exsound_select & 0x04 ) {$ Z. M6 ~+ i5 u+ p& {" Z2 P
                fds.Sync( cycles );+ T5 S4 S; [, n* L! s5 \
        }0 C( c+ k$ V4 w+ B( T
        if( exsound_select & 0x08 ) {7 I+ k, o  R3 ~& n2 |! a
                mmc5.Sync( cycles );$ r+ `. j' M9 b5 G6 Q! D$ H7 Z  m
        }
& x9 @+ x9 P5 b) ^* u}
1 X& m; ]5 Q1 M  O9 a: K: B+ n8 [: O' ^! b
void        APU::WriteProcess( WORD addr, BYTE data )  U  K, i5 c5 R6 _- Q* J
{6 m, D* b+ \" m" T6 g1 K: \* O
        // $4018偼VirtuaNES屌桳億乕僩
: p. y! t5 u) G6 O) \& U        if( addr >= 0x4000 && addr <= 0x401F ) {
" z& M" D) H' j6 V6 Q$ l                internal.Write( addr, data );1 _) h- s- W) y2 i/ M" P/ Z
        }% D; V& p; ?/ w* {! x$ [6 {
}# r# Z- r( Z! M, |0 `: r0 _5 G

, _. d% I! z( U9 bvoid        APU::WriteExProcess( WORD addr, BYTE data )
$ p& h  R4 @/ ~* Y! {0 C{
% g) }) O9 Y  n. i9 X        if( exsound_select & 0x01 ) {
& ?3 F) |$ z4 ?1 E8 @+ D                vrc6.Write( addr, data );
7 P  y8 ^& n3 n, p9 R# n        }* v' E# `4 G, P# I  e+ H+ z2 G
        if( exsound_select & 0x02 ) {
8 n! L  m1 ?* `! [- q  l, {                vrc7.Write( addr, data );
2 w% a4 W; t! v% k1 d" L3 r        }
/ V: h- J( ]- H' B/ b        if( exsound_select & 0x04 ) {
1 [+ Q# ^) J3 d3 K1 a" ?  H                fds.Write( addr, data );7 H" X, j5 m# @
        }
: r# f/ j% \7 A/ p' i" t% j- K        if( exsound_select & 0x08 ) {- F+ D) T( v* F- \+ I& p: ~& _
                mmc5.Write( addr, data );. M6 Q- p% |# }) S2 Y
        }
+ R1 y9 L9 v7 }0 d# }        if( exsound_select & 0x10 ) {8 B2 I' e& C  @# }
                if( addr == 0x0000 ) {
8 i1 \2 |. }+ G2 u& [: n                        BYTE        dummy = n106.Read( addr );" ]7 I& h' u1 \9 S* m# ?
                } else {
8 D& e1 i; t) f7 T( b. A* C                        n106.Write( addr, data );
( Y6 \, E0 {  n2 n" ^6 ]9 ~                }
; J1 l4 ?1 ]5 {9 }$ `        }' q3 X3 p  M3 T& x( P% B. d
        if( exsound_select & 0x20 ) {# @" B% ?3 Z! `
                fme7.Write( addr, data );/ l" r5 ^- H; P# E8 F) B5 j
        }) s4 h7 h- z  u! l% X/ Z0 x1 Y
}. |% M* B# j/ s5 w7 S" K8 w0 m

" m) w" k& {5 Y& j' [% d. X) ]% \: M  ovoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )" [4 e. X1 O9 L+ c( `0 E; w- q
{/ k* M8 T: ?2 M6 J5 h) X8 ~
INT        nBits = Config.sound.nBits;$ v  C' j7 N+ [. v
DWORD        dwLength = dwSize / (nBits/8);
) f% ^. f2 i& J1 XINT        output;
# p, V9 ?* k& {& b7 F, EQUEUEDATA q;
3 r0 Z1 A' e. b; iDWORD        writetime;
) z  v2 a3 O8 [# h% K' d7 q; `  X" ^' l$ y
LPSHORT        pSoundBuf = m_SoundBuffer;" u3 u# n% b& G
INT        nCcount = 0;) x( |6 }* J, ?+ L  M

" b# s* e; W$ B5 R" @6 c2 f+ }% ^INT        nFilterType = Config.sound.nFilterType;" I" W5 D5 ^7 v$ g: j+ k3 M

8 E: N+ V( D, |  W- j- k6 q        if( !Config.sound.bEnable ) {0 Z0 D/ J2 o) v" s7 z  h- a9 O
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 e/ h% O- ?, L3 V                return;! g7 R" d9 M- R( i! K# U" Y& L
        }, {* s& m4 @+ |( A* N
# W' Y! D% h5 s- q0 l
        // Volume setup
" S3 ?2 Y! O) m* ^. `, F' }9 S* i        //  0:Master
$ e) a! V, R3 |  m: N        //  1:Rectangle 1
; I2 d, g7 W- y/ x        //  2:Rectangle 2
3 M" [+ j8 ?" ?2 X# f! n        //  3:Triangle9 s' S2 ~; i/ w; n$ ^  r$ U1 o( ]
        //  4:Noise' g6 a9 c" A8 r  G
        //  5:DPCM
0 X, H5 n1 j5 e4 a/ Y8 w4 N% l        //  6:VRC6
5 ^; O' T6 }) \# |$ o! e        //  7:VRC7  F# ]2 V0 m7 F" C
        //  8:FDS( M9 p( J8 [) u( [) g2 L( F3 S
        //  9:MMC5
! W. z& Q# g- u" r        // 10:N106
+ Q+ H5 e& Z1 o+ X4 T) e# V        // 11:FME7
2 o* ]5 r" {# s: B, {        INT        vol[24];
3 u; e+ B( [" ^/ s$ l        BOOL*        bMute = m_bMute;
  e0 m6 R9 s' Z2 f) ^        SHORT*        nVolume = Config.sound.nVolume;" `2 f, u9 d7 N

8 ^2 y  Q) b( m3 q        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- @' y4 l* j) X! H% A, B9 F
% b  ~" R" u0 h& d( D# }
        // Internal
' m& ?: f7 Q& ?        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
. m5 D- W2 d# T% _        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
5 P$ e" O  A% u" r" W        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;& I, ]- V  C& u( l' \% E5 V
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;" L8 A7 Q, _# z; c$ V8 \% i
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 K1 w2 X8 r; b; y( {$ T: Q5 B: D4 b/ O( M; g3 t# E
        // VRC6
/ ?& {2 Z: j4 F# B8 Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 `9 g7 N: I; d0 e        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; G; D9 U4 y( u* O7 l- z        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 _" i. `3 S! ?
% o! \* n" G* c3 @* u        // VRC7) @" [, d$ i9 j4 n
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 R  O) E4 s" t& l! {8 `: ^  N- ?  M5 v# O
        // FDS
/ Z7 A& |4 C( ?+ f9 I0 N; h        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
1 t$ Q: I- Z8 W! t% n
' X3 m  I. Z$ n% b, v! k9 c        // MMC5
1 B0 d/ B: [: Z: D+ Y- z( Q        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 K7 k9 C( F8 M, f* F& b        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, i' x9 |! E( y  N/ z        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  A! @5 K, n" O: {3 e  j

8 C: D' s! o& W1 H. d9 x4 K! R        // N106) L! \5 s& {9 I% S9 B
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) @$ k# Y, M) U- e4 n& {        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 n  h+ e6 R$ y6 i1 j$ h9 K
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* D1 E6 i, |) |0 X
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 R9 I8 ^0 b6 @" R& M
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 Y( n( A" P$ ~5 l        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ \$ J% w/ ], h; a' u        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 e& |9 T) ~& q8 e6 Y
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 f' S# B& @/ C$ \; k+ L* S7 t$ o* z$ y
        // FME7
7 q3 ]. Y9 o1 z( E! h/ [) \        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( A* M9 [8 Z7 L- T
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, }# e% \4 _$ d0 k) z1 ~3 Z/ V        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& D8 ^/ p) K! Y- l6 A3 |% Y5 N" Z5 @% d% n8 ^
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 N  Z8 B3 C5 ]" B" d8 S
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;3 J/ f0 t& _! X2 v& J
/ ]4 P* \9 i5 ]$ C7 Q
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
" l; I+ U( K/ i" l. B        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  D9 w1 L; S  }* z, y                QueueFlush();
2 H0 D* G7 y0 r, Q: i6 l        }" u& ]0 o* V: c& T; [5 a) l7 `% o

, g+ S' w: G' g        while( dwLength-- ) {. E1 S. ~1 P" G+ i
                writetime = (DWORD)elapsed_time;
' X: A  \4 [* W& H& o" q  C1 u' s% v$ y' t9 B. I! ^& n
                while( GetQueue( writetime, q ) ) {; {7 K: o) x, {
                        WriteProcess( q.addr, q.data );# a; W4 m3 R; G; y# f# t! a
                }
+ d' X" L+ r9 r: j* Q& H8 o; z+ J' O' Y- }7 Q
                while( GetExQueue( writetime, q ) ) {
: [/ Z+ U5 e  V1 Y                        WriteExProcess( q.addr, q.data );
, D. t! c7 Q* W                }8 H0 X+ a  ~, Y7 y6 y

" u0 p8 P# P3 q1 M( f                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7% k* {) g' @" l! Q0 d
                output = 0;( W2 W! z2 w9 a& v2 N
                output += internal.Process( 0 )*vol[0];
$ V3 ?# ~* H/ m8 h! f; `                output += internal.Process( 1 )*vol[1];! m8 _  n, y& z) E4 n6 Y
                output += internal.Process( 2 )*vol[2];, T- E1 _; B; h, l  {
                output += internal.Process( 3 )*vol[3];
! k3 Q9 ^' E% M- R: [                output += internal.Process( 4 )*vol[4];
/ [$ ?7 i  k& G( ~* q6 I3 S+ e8 B- \. W6 k# {9 j' t8 `3 i
                if( exsound_select & 0x01 ) {# @) t% a% ]8 G4 o. a
                        output += vrc6.Process( 0 )*vol[5];8 t$ e, A( q- |9 T0 D' K7 \
                        output += vrc6.Process( 1 )*vol[6];4 e7 e! S$ w" R+ X& J$ a
                        output += vrc6.Process( 2 )*vol[7];
+ r" |1 k9 {3 o                }
" `0 Q, q- _0 }- G/ c7 W; h                if( exsound_select & 0x02 ) {
) |' j5 A8 C3 h5 r8 M8 I9 W0 X$ [                        output += vrc7.Process( 0 )*vol[8];! s0 d& [% W6 k8 Q: _) S3 a# i# A5 o
                }
. @8 C" e8 s0 ?                if( exsound_select & 0x04 ) {5 V3 }% t9 x: _/ D; c# @) ]
                        output += fds.Process( 0 )*vol[9];
# S3 v. b" t: C                }" s/ T6 b5 l; w; v: P& m. b
                if( exsound_select & 0x08 ) {* e) a2 ]' O8 v: i1 ~$ V
                        output += mmc5.Process( 0 )*vol[10];
) a/ W7 b8 g& v1 i8 }0 I                        output += mmc5.Process( 1 )*vol[11];
3 J3 h( z8 J8 d) F  s                        output += mmc5.Process( 2 )*vol[12];
* {7 q! r( `# X/ X" q                }
* Q, O# i. k4 R0 G2 ]" N) H                if( exsound_select & 0x10 ) {( `! g+ ?# G- X9 n" b5 t9 q8 s
                        output += n106.Process( 0 )*vol[13];& V  D9 m% {6 {5 s; \4 Y
                        output += n106.Process( 1 )*vol[14];+ a* ?4 }; Y% {- A- w% c4 Q1 R
                        output += n106.Process( 2 )*vol[15];+ r# _. y# s5 N$ w6 R' b; L
                        output += n106.Process( 3 )*vol[16];+ v9 t6 q4 w8 t% E' X
                        output += n106.Process( 4 )*vol[17];3 e# _( q7 e* i# @
                        output += n106.Process( 5 )*vol[18];
2 w. g; `) ?4 o8 C& i                        output += n106.Process( 6 )*vol[19];# h+ D8 l4 O3 t* d0 V+ v  S  Y# F+ Q
                        output += n106.Process( 7 )*vol[20];
+ t1 E/ A1 z0 q* c3 q                }* T5 [5 z  X1 p$ L3 a5 b
                if( exsound_select & 0x20 ) {
1 L/ L0 e+ w4 b3 E0 r% O                        fme7.Process( 3 );        // Envelope & Noise5 M! \3 p" f7 C
                        output += fme7.Process( 0 )*vol[21];
0 d) u. ~" ^& C# u                        output += fme7.Process( 1 )*vol[22];
+ j2 ]! d+ A) k. ~- s) i1 ?  \                        output += fme7.Process( 2 )*vol[23];( L  ^, r, s8 c: w9 N8 H
                }9 P1 D0 o( C0 }) W  I" E

" f  C6 ^% T6 J# v7 Y                output >>= 8;
$ o) D/ M% X; |9 F8 O
) n' y% R+ V, ^- g/ z                if( nFilterType == 1 ) {
3 v; k5 \) c- ?: w  m                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. C- B# g0 ^" D$ ?/ {                        output = (lowpass_filter[0]+output)/2;+ |$ Q/ s, m* z0 O( L, A7 d7 M7 f( O
                        lowpass_filter[0] = output;
4 d8 ~# o: {# ^% L& K) i                } else if( nFilterType == 2 ) {( b3 m7 u- L, p$ H" I) ]
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 D& ?- q" b# J$ a
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; Z% H" ]' n2 x
                        lowpass_filter[1] = lowpass_filter[0];% s  x+ r' n" f
                        lowpass_filter[0] = output;2 |! ~. D" P8 L9 q
                } else if( nFilterType == 3 ) {- X. i- l3 @: U6 v" R/ W, X- _& @- z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)/ q, F1 L# L$ T$ v* t. `4 h  \
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
  j* M0 r4 f6 B7 c  j5 \0 c                        lowpass_filter[2] = lowpass_filter[1];
5 g, O* b; ?% O- \( X; l6 L) [9 m                        lowpass_filter[1] = lowpass_filter[0];
- F# N$ ]' V: M; T( Y                        lowpass_filter[0] = output;0 S7 J# E6 ^3 q, ~3 d& l
                } else if( nFilterType == 4 ) {5 n) w1 f1 S. f3 E
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)$ q  j6 ^( i2 r, P# V7 b
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;. w, `) A) S/ r9 k4 Q7 M
                        lowpass_filter[1] = lowpass_filter[0];$ }: A) V# C$ P. g* X
                        lowpass_filter[0] = output;; N/ M: N- Q9 @! @" R! W
                }2 [+ X% k$ {1 H. L
3 T. r; G5 s9 W5 U
#if        0
: b# @0 F+ b+ i# V# z* D3 Q                // DC惉暘偺僇僢僩
7 [  A  Y/ e9 Z0 W0 b                {8 L6 }5 P# d6 E
                static double ave = 0.0, max=0.0, min=0.0;
* |0 p0 A$ ~! t1 y& ~! T                double delta;
* h  D7 _0 a6 n, w) Y* p7 P                delta = (max-min)/32768.0;
6 M) Y+ I0 \  x8 Q' k5 c                max -= delta;6 n" U  e& H( C
                min += delta;
& C( m2 c) {; l7 i                if( output > max ) max = output;
; h& d+ x2 A3 w( H+ E                if( output < min ) min = output;
2 g( L( l; s- ]0 z$ m; ^- h                ave -= ave/1024.0;: ?8 ^4 o- k* J
                ave += (max+min)/2048.0;9 m" C, L1 s) ~9 v; \. X3 a
                output -= (INT)ave;8 z; x7 a9 R/ w- }0 y6 S- a8 {- x
                }
) _* g, [7 P6 t% r* W#endif9 Q) o3 J* J: G! `7 @+ B: J8 ^7 O
#if        1/ R- }& ?& f- L# q! ]. p' t
                // DC惉暘偺僇僢僩(HPF TEST). H  w: X* ]$ ^2 L
                {
  y6 A9 [" q5 [; {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);5 o, j6 w4 X  ?1 M8 E1 A
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
* P- I2 o0 }# A0 C; [9 s; B- N                double        cutoff = cutofftemp/(double)Config.sound.nRate;7 C! ^8 c4 I0 N( {) z4 U
                static        double        tmp = 0.0;
6 d6 |  m, o4 q6 e/ x                double        in, out;
& S* G* N7 m8 p& f" c
' A$ q. U3 F+ P( M: e" g5 Y5 i                in = (double)output;% S1 F, b/ Z$ o/ K9 E5 X
                out = (in - tmp);/ b( e% h5 A% k) q" Q* m
                tmp = tmp + cutoff * out;. }" v) n6 U' k0 N
* k2 r. [0 f4 [
                output = (INT)out;
& k0 e' M: \/ `* Q# ^9 N                }
; j$ O) o& y: k# D3 o#endif! Z5 b2 O2 s9 b- p- |6 V
#if        0
1 d! f, r' a6 A" r                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)- Z/ y6 p$ O0 n  s, I6 n/ i3 F
                {
+ q$ f- W# q- e  I                INT        diff = abs(output-last_data);/ N# V  {& }3 x& h/ e1 |
                if( diff > 0x4000 ) {
; {5 U. `, p2 ]; x6 c) Z                        output /= 4;4 @, f9 M+ U5 [  i- B9 P$ j( B
                } else 4 R, }- E' W( e8 c1 a4 M2 b8 P
                if( diff > 0x3000 ) {
- S- Z; k) t+ ?  M* q/ u$ f8 K8 m                        output /= 3;: m8 V9 S2 {0 B9 D( G* A8 K. i( h
                } else2 i2 C0 o) x5 ~2 U4 X) g
                if( diff > 0x2000 ) {
" I$ d+ G# H6 B  D                        output /= 2;6 [& L9 C1 `2 G8 Z  T, O
                }8 Q1 y0 s  k1 F9 G7 Q- l
                last_data = output;& ?/ b- K3 i5 x# H( _2 M
                }
0 P/ D( a! E2 R( U; T2 M# f( p4 y#endif
3 N) H" x1 g% w" U1 x                // Limit2 S1 N! ?9 f; C1 K
                if( output > 0x7FFF ) {- C3 o# Y* I/ u
                        output = 0x7FFF;
' a' Q: _# h9 X: u; y9 \& ]. r                } else if( output < -0x8000 ) {; `# V8 U, t6 J3 a& J$ X
                        output = -0x8000;( ]3 o6 b( [4 |, L
                }% t" _& k6 A) C7 f' T
# C- g1 u" q  j
                if( nBits != 8 ) {
6 p% m- Y/ S1 j$ n& W+ C                        *(SHORT*)lpBuffer = (SHORT)output;. e  _  |' Q" N
                        lpBuffer += sizeof(SHORT);
/ }! S3 m: `3 {2 V& W( M( C                } else {
% f1 ~4 [  U, H2 @                        *lpBuffer++ = (output>>8)^0x80;
* Y# M& b; P/ Z$ R  _8 E                }- p& }( \* S! E. N. z; n5 Q6 z

, e2 ^4 {: Y! z1 U' h) G: j                if( nCcount < 0x0100 )
" b4 E& @# \- K+ j3 ~2 y( x2 w5 K                        pSoundBuf[nCcount++] = (SHORT)output;
( C* e) b: x- B9 c5 Q! k" Z- e/ {4 t5 i+ }/ M7 n) S6 X8 X
//                elapsedtime += cycle_rate;) z8 h% i' B6 J+ E# D
                elapsed_time += cycle_rate;  p) M; Z& @& {& l- E; v( G
        }$ l0 y# D% _0 T- Y

* n" r! v! O7 V#if        1
. T. [* G. B& b' Q        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {5 E9 y4 W+ C2 M" R& \; ?
                elapsed_time = nes->cpu->GetTotalCycles();+ _2 b( v0 V# V4 b
        }
! L& j  L1 b6 \, H2 w6 r2 I3 r. w* u6 t        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: Q( s. B9 c4 i3 G7 w: c                elapsed_time = nes->cpu->GetTotalCycles();7 ~1 E9 J5 W5 Z+ `7 r1 X8 N. K6 E
        }2 O% d4 |* F! E( I) s
#else) Z% c/ D: _7 y3 r5 t+ C$ ]
        elapsed_time = nes->cpu->GetTotalCycles();
$ p$ |- }4 V1 V: y; ~#endif
: l; [) {4 x! w( m}
: U; B8 R5 \) I) \; j4 r' f/ Q3 J5 [, }; q% e
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡); h: |* M/ O6 u6 x5 P  c! i4 A- o
INT        APU::GetChannelFrequency( INT no )+ K3 D4 N; I- S5 \) l# L
{( ^7 r  v9 T0 @9 @! S+ M
        if( !m_bMute[0] )1 e1 Q( m* T6 W0 g
                return        0;
2 x( N" |  O2 p6 S/ {% D$ z# f
* Z( W6 D1 G, L% D# Y        // Internal( ~; S+ _  i1 n' G
        if( no < 5 ) {3 ?. G  R. l5 N' f+ p
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
! t+ Q9 M' o- x  h: g& `( `        }
( {2 M# T$ g* W3 r        // VRC6
5 B) S6 |+ N/ m4 ^        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" g9 D3 x8 `1 c: |4 k4 Y( I                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! i; c, Z, S$ y' Z$ B
        }6 ]- k' s, e! b" N7 k: X
        // FDS2 S1 l; P3 p& ]
        if( (exsound_select & 0x04) && no == 0x300 ) {
: P. [# [, G! O                return        m_bMute[6]?fds.GetFreq( 0 ):0;
5 |! k7 s: ]+ v) ]0 L; ~! f% c        }
; N- ^( H' M1 {9 U        // MMC5
8 i8 ^2 d) I" D) v8 l! O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: B- i5 Q; ^7 T2 b' B8 U5 Q
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  b8 s+ E0 A" m
        }! m* p+ ^* ]+ u9 ^. D" Q
        // N106
' P8 r5 a* M1 b        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
/ l& `0 r7 l/ y6 x- P  ], e* w                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;6 ^3 L8 Y  h5 k4 `
        }
) r, j; W: G; _; k3 l        // FME7
+ D1 q: s, b- F" y; q& b1 x; _; |        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
- e9 X- c: B8 t                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  V1 N, S" \  O: H- d6 T        }% F; R! X7 `6 H/ d! V
        // VRC77 b* w" k7 P4 ~
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! y. h4 V4 m3 c
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 P7 t& A0 |; m/ b- X1 {, O        }
; u7 [# x- y2 {7 w4 W/ g; t0 p        return        0;
9 x2 o  w7 b; S: B. [}6 N0 f1 V# j: c" l- E
! _$ |; B: {; P. u
// State Save/Load7 n4 F4 {" W: g4 A0 n
void        APU::SaveState( LPBYTE p )0 @$ Q, Y' m+ w
{* |- F  l$ g* j
#ifdef        _DEBUG7 Q& a, b" G$ }- S9 {5 L+ x6 J
LPBYTE        pold = p;
* U' G) Z  x5 `% \: p#endif; ?  C: C& y4 u7 T0 V
7 N: v$ _* s! M+ ~0 [) G1 ?
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; ?! c8 N$ ?5 k
        QueueFlush();/ ?7 d7 ?  D0 Q  F1 l3 F/ a9 [
0 `2 d8 z3 ?6 g8 X* k1 ~5 q
        internal.SaveState( p );9 U" c  Z/ j, B' Z& B& d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding0 K  T' A6 k. y: h- }7 `& _% O, l

) w: P( z& V5 V: j7 A, X        // VRC6
9 `- ^7 z$ ^8 p  p9 D6 `! _        if( exsound_select & 0x01 ) {' W8 t! m) ?$ V! ~# A- ^2 _
                vrc6.SaveState( p );
4 A+ H8 y  C2 _  f7 |7 X* {! Q% \                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* W; ?1 p7 H) H( S
        }
" C/ n* [& ]* _# A  n- w        // VRC7 (not support)
+ @  `& H0 N# I5 r" @3 x        if( exsound_select & 0x02 ) {/ l8 u4 e: h( P: A
                vrc7.SaveState( p );
2 W* W$ ~/ P* o8 o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  y) `% t- n- H5 w
        }* `4 G% \2 H+ N* G
        // FDS, S9 P! K' R3 @; E; U! a) [7 V
        if( exsound_select & 0x04 ) {' _/ E. V2 e( y' P
                fds.SaveState( p );
( L# D: z0 Q* f5 R2 ^# l                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" ?/ L7 o, X7 H3 \        }
, `, h" ^4 a: ?4 N' O. b  T# J        // MMC5
8 v) _7 w/ @3 a- ?9 Z6 |/ R! y        if( exsound_select & 0x08 ) {9 `. k6 y! f; f  @3 z8 u
                mmc5.SaveState( p );8 F& B! y  y- J* t. I. B) g
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( v" Y( ^1 i% ?$ Q& H# f) E        }
& L; p) _- l# J6 z- f1 L        // N106) M+ Q  c- [! F, g- _- P2 `
        if( exsound_select & 0x10 ) {/ g% w5 C$ B* |
                n106.SaveState( p );" Y, r' Y' N) Z7 S  z- `" }! A" }
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 B3 t. `/ i" O1 j
        }$ W' {: I$ f! o5 q9 M% T! @3 z
        // FME78 ]/ y  a" I* J$ R6 {
        if( exsound_select & 0x20 ) {* O: f: n) |5 g6 b# V0 k! F( S
                fme7.SaveState( p );% b, X. D- ^2 O
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' E7 B, n1 ]3 Q% n, `1 r        }
/ {2 M6 w+ Z' _( R7 i5 q( g
# Q9 d1 z' v+ U, [#ifdef        _DEBUG' e$ z1 r) x& ^1 b+ j
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
' K. _+ C6 F! @' h: v# S% l& B1 [#endif; l  p) M% Y2 O% U! `  Q
}
0 y( m; p, U) w, {! b3 d! ~+ a9 O8 l6 L" s
void        APU::LoadState( LPBYTE p )* C; O! G( V& h
{
5 `* Y! q2 Y% q        // 帪娫幉傪摨婜偝偣傞堊偵徚偡% Q( s( T8 W) T# m& o* m
        QueueClear();4 P4 a( I$ ~4 {0 Y& n4 i7 ?4 K
  v( j) r) g, ^: [- B6 T- c
        internal.LoadState( p );! Z. ^, q+ V$ v7 H: a& Q7 ~
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" j1 p% ^' g3 T& [* ~) @  z6 E5 ~" c) n) o# i. t) K: J
        // VRC6; z( D- O9 f; ~* V
        if( exsound_select & 0x01 ) {
$ W) H- z! @2 a3 K+ I7 O5 o                vrc6.LoadState( p );
  o4 r6 d. ^3 p6 R; }$ q* c3 u                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' V  z# [$ a1 f3 L' C7 O, N) j, G
        }
* h0 U6 o, c8 B        // VRC7 (not support)% ~! C' h3 o) h3 d" T
        if( exsound_select & 0x02 ) {
6 M) D) b, N7 Z% d+ E                vrc7.LoadState( p );
% D; g  f4 E6 l! y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* X$ L  t' G7 \) B) X3 W/ H
        }9 t0 \" S! n! N% I: v" I
        // FDS4 l0 ?. b  O( b* z4 W8 w
        if( exsound_select & 0x04 ) {
2 W1 T0 n5 I) _; d2 Y                fds.LoadState( p );
7 c% v# E, K$ @: K3 E0 p  W: A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 A$ z" o# v8 Z0 `; Q% Q6 {4 X! [
        }
. |& Z2 D/ E1 D, z( e' Z        // MMC5" U4 m) \  ~" }1 b
        if( exsound_select & 0x08 ) {
6 ^6 x, `9 {" I7 H. s; v                mmc5.LoadState( p );
0 S4 b2 k6 z. @$ H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# U+ p  i' C) H2 A% \
        }: U" ^# ]. _5 \$ X: S, r9 q
        // N1067 K; T- o, F5 s+ Q
        if( exsound_select & 0x10 ) {
0 X: _/ S# E- F* `7 \+ u- s# D                n106.LoadState( p );- P8 \1 |2 n& W4 D: m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. ]8 z4 N/ U0 ?' P6 Z        }
7 H2 J; a  H. h  ^! M# P: e# O        // FME7. Y( F: Y/ z# Z. i0 ^4 ]! ?- @' }
        if( exsound_select & 0x20 ) {# i: [3 i! U) ?2 p
                fme7.LoadState( p );
6 P4 H# Q$ f& B$ X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% J7 D0 Z' }1 U3 @) w        }
" C+ ]- P0 E: U1 g}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 8 I$ J: i% g+ X, ?: p! w7 s6 |
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ G- t4 q! t4 H: k' g) g: e* s1 f
感激不尽~~
2 B$ V" W% `( w% n( n% n
恩 我對模擬器不是很有研究,
$ Z$ n9 v- A: _$ }7 P雖然要了解源碼內容,可能不是很困難,
. j9 t! u4 K: `4 Z! G: y( N不過還是要花時間,個人目前蠻忙碌的。
3 Q9 Q3 o& h) a6 B! i! p9 o4 Q( k" a7 I7 w
給你一個朋友的MSN,你可以跟他討論看看,
, T% E& m# ?  ?他本身是程式設計師,也對FC模擬器很有興趣。
) ]9 p" ?7 `2 Z3 X( Y
" _: a$ q4 L4 g; H1 @MSN我就PM到你的信箱了。/ r' J1 P  e# e  z% j

+ `2 d+ g" @) w; [3 c9 X; D希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 * R$ P6 `" i; B! f8 ]
呵…… 谢过团长大人~~
) Q) r9 N, m: `, x; F

1 m' [9 |3 a: p哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ H3 s! b+ ]6 d1 E, _# L4 K1 F团长的朋友都是神,那团长就是神的boss。

+ ^+ U  C" L0 I. A0 ^" c1 B1 F' e哈 不敢當,我只是個平凡人,
& Z) C; B! h/ q: N5 Z8 R4 U要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; }2 a8 t7 g* t' D: \0 HZYH5 g% J/ P/ c" m% p; y1 a' \' X
QQ:414734306! D/ g; ?5 {9 k
Mail:zyh-01@126.com/ O7 p- [; r3 w7 {* d7 y4 _
. p( l- b: z/ c% U. M5 ^
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 5 e0 _" w, t& I, ?) O8 K' W
再次对团长大人和悠悠哥的无私帮助表示感谢~~

# T; v9 d+ Y" I1 G, a( j7 Q# z9 s不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-8 09:46 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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