EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# i/ M* c" Z( D& g% d% I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, U, {$ @$ W# |
这里有相应的模拟器源码,就当送给大侠了~~# a  Q0 A: E! }2 r
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
& A5 \( C; _5 J' t- p/ h能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ Z$ j, u  p' X0 _5 ?: Q2 @$ i楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( K8 Y, h" b' Z7 ?9 W9 z) Y+ {
这里有相应的模拟器源码,就当送给大侠 ...
+ T+ o( s$ f+ x
聲音部分(Audoi Process Unit = APU):# F1 S! N: U  e: f* E' U2 o
.\NES\APU.cpp
8 \  M# a/ b( p% `  |" O2 B.\NES\APU.h+ D; p$ I6 ^& L' P/ k* T& Z
6 N7 I9 m5 b1 V
; I* O8 D7 I( w/ ^, n
影像處理部份(Picture Processing Unit = PPU):# M4 ^3 Y- U' ^) V
.\NES\PPU.cpp3 ?- n& w& \) Z2 n+ x
.\NES\PPU.h
9 ~( o, |6 p' z9 `. _8 D9 Y7 t: p
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
! Z1 e7 v( n& d( Y$ R# q( a(由于很多专用术语和算法机理都不明白,所以看不大懂……)
, V" r3 u2 B  E" y0 w- w( m//////////////////////////////////////////////////////////////////////////
; o5 k& Q' c6 M7 q//                                                                      //; J) F( o  ]+ X/ _3 I
//      NES APU core                                                    //
3 U. t# [  o* y: @4 z//                                                           Norix      //, h% x3 P2 D: B- e
//                                               written     2002/06/27 //) X2 C5 q. N9 T& i7 v$ M. \
//                                               last modify ----/--/-- //
' ^7 [( t( l$ I2 a+ d9 `//////////////////////////////////////////////////////////////////////////
: I, D  P/ l4 ]$ v# c#include "DebugOut.h"
. m  e0 v; o# K. f#include "App.h"
! c4 |0 s2 \' D6 k& K) A, U( |#include "Config.h"
8 D/ ]; e4 J% ^5 E4 `$ J4 @) w/ h8 f0 z- a- W+ I; N) a$ V
#include "nes.h"3 m& D% @7 J/ L: m
#include "mmu.h"  n$ W0 R# u  w- t# s
#include "cpu.h"# S: X: F# @1 o# w& s" g' S
#include "ppu.h"
8 B, Y1 |# m5 N7 L' _#include "rom.h"$ B0 J2 F: r# m- a% G( J
#include "apu.h"* h) o+ ~+ \! U+ }: V
2 n6 G2 G2 E% k& o! Q
// Volume adjust  }5 o' W, K/ C& V! M" m
// Internal sounds( T% Y: |0 [! e9 A
#define        RECTANGLE_VOL        (0x0F0)
) v, K4 B( a/ h2 Q& z( `* b# P6 t$ O#define        TRIANGLE_VOL        (0x130)
/ C/ ~; ]! G6 I#define        NOISE_VOL        (0x0C0)# e9 M3 A7 @9 P9 \" i2 |# y" ^: s
#define        DPCM_VOL        (0x0F0)/ v2 P% Q4 U' ?# b/ R" V/ o0 E$ x
// Extra sounds
2 H) m  c, ~# q+ J, r# u8 |#define        VRC6_VOL        (0x0F0)$ w7 @8 C: l. t; x% [( w
#define        VRC7_VOL        (0x130)% f0 T7 L& B' o: R# U; h
#define        FDS_VOL                (0x0F0)
$ E6 D4 j4 B4 V, s& @4 n* ~#define        MMC5_VOL        (0x0F0)
. S9 _' \* M& I/ E/ _& n1 ?8 i#define        N106_VOL        (0x088)
, m5 _0 Y9 \$ I& r#define        FME7_VOL        (0x130)
* k2 [; M5 c. A0 _1 c
0 |! D+ d. i1 u, h% Y5 y- tAPU::APU( NES* parent ): Y3 a5 |( t2 q$ j1 p: C5 h, i+ f/ u
{
) r+ c$ Y7 d6 {8 x: W        exsound_select = 0;
4 R& v6 x) `% [; P! N0 [  \; T: B" ~% `( f& {9 `
        nes = parent;& w' h( Z2 N0 b; T7 p- \
        internal.SetParent( parent );6 D  K8 r4 o- j$ J" Y
2 z7 G" d. h. l; ]( n. ?
        last_data = last_diff = 0;
! \7 |6 K) c# u- @0 j8 {* w" c6 m& o
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
& n3 u/ B: ^( s8 s! H
: z2 h0 k! D$ X- g5 x        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& Z. p( r7 g" _1 Q6 ^9 J        ZEROMEMORY( &queue, sizeof(queue) );
: k  `# q% ?0 h0 V5 R1 {        ZEROMEMORY( &exqueue, sizeof(exqueue) );( r3 y' ], H( s( H+ ?6 l
6 B$ {& B7 \8 H; y$ x
        for( INT i = 0; i < 16; i++ ) {2 e, u, [  Q) Z3 Y+ s9 x$ I
                m_bMute = TRUE;
5 y( [/ O# k, `* D! G        }+ Y, M, J" O- Y9 i3 y: z
}
/ y; w' e4 E- Z: X
$ x- z8 k. j& a0 BAPU::~APU()
8 ]1 z3 x# n7 l* @& O8 u{
, N  v+ @" A' a' }& y  y/ c}
& L: |. g6 L' v( S: Q4 _( V6 H; t$ L% j- v
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
( ?% r$ a- u  U" a7 ^9 z{
; y' r0 H# `0 f2 m2 A: o" d        queue.data[queue.wrptr].time = writetime;
2 B6 R% o0 N' T* U& j( d6 t; y+ i        queue.data[queue.wrptr].addr = addr;
/ j( K* @9 e+ f) |% Z        queue.data[queue.wrptr].data = data;) m" m2 {3 W9 a7 t
        queue.wrptr++;4 A8 l& b5 `- X
        queue.wrptr&=QUEUE_LENGTH-1;
8 s8 z) N, B: c: G        if( queue.wrptr == queue.rdptr ) {& R9 g  y4 a2 W) i$ v' Z. M" W6 d9 R
                DEBUGOUT( "queue overflow.\n" );
. F4 b) }- u" J" S        }
9 o$ \+ u+ I1 f0 ?4 R, \6 J}& k3 Q7 ^" g$ F' G0 M
$ N* b7 v1 b: |" i0 C) ~5 C3 Z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& `5 p. z! r( D& W9 `{
0 C, u" u8 l" c% ]/ y        if( queue.wrptr == queue.rdptr ) {& V8 r- u, I% E
                return        FALSE;3 I, g2 B6 s$ E8 b1 {
        }
0 a) a$ U& @4 q1 W+ L8 x8 h        if( queue.data[queue.rdptr].time <= writetime ) {
/ ~8 V+ |' h! R7 k$ z% J7 S$ M                ret = queue.data[queue.rdptr];/ R9 X. C  F/ t) D' a) f0 s
                queue.rdptr++;" J4 M. [5 _' ~& H  M( @
                queue.rdptr&=QUEUE_LENGTH-1;
$ s3 U* s% ~* G* Y6 i; e1 u                return        TRUE;
. ~8 g, p0 r2 [! ^9 k+ o% o        }$ T, y3 k6 V9 b1 O/ d6 n, W1 T
        return        FALSE;
- ~# E9 Y! L+ g; ]/ ~}
) k0 F% w7 b$ \
) k; {+ _! o: Z5 Rvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )8 p& C! F0 y+ y
{: N$ s7 z* [4 l- ?1 [1 I) G/ X3 E
        exqueue.data[exqueue.wrptr].time = writetime;5 O( P: z2 v. ]- ?( G' C9 B& C* ]
        exqueue.data[exqueue.wrptr].addr = addr;5 v7 w# \$ ?( a3 N6 [3 G
        exqueue.data[exqueue.wrptr].data = data;
9 D6 H/ s( e% ?! `9 c# m        exqueue.wrptr++;, N- p! t, \5 v  J( G, W
        exqueue.wrptr&=QUEUE_LENGTH-1;
# u: M4 j! s- o" Y1 H        if( exqueue.wrptr == exqueue.rdptr ) {2 v8 b+ {5 i/ h: q* n, C  k# O5 t
                DEBUGOUT( "exqueue overflow.\n" );; R" X# X3 _+ P5 D. f
        }6 O# v0 R) i) Q; t1 z5 j
}: u- F- i8 `- Z3 m4 b

; ?3 d; Y4 y  E$ M+ K$ eBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 g# x6 D, d1 E- r% ^{
( I4 ~2 z7 K6 n7 y* F        if( exqueue.wrptr == exqueue.rdptr ) {& f6 @" ]$ H3 e) c$ T: X: C3 V
                return        FALSE;
: ?  K, J) r# k5 ^: y  O. ~        }% F# Q( O& I1 f& @! |* I  ]
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
) D9 l2 Z5 P0 _  Y: S; e' {  s                ret = exqueue.data[exqueue.rdptr];
  R7 [6 L! |+ S7 W' b                exqueue.rdptr++;' ]$ H( I. H3 l( ~
                exqueue.rdptr&=QUEUE_LENGTH-1;
# x( \# P) S( L' l& D- Z                return        TRUE;
; H% E0 ?  ?% \2 I+ o6 f- |; E6 U; d        }
' n. q0 C! V7 E2 M# S0 H8 I        return        FALSE;
( C' o0 m8 E0 [6 `* O5 P# t; `2 \}5 |# l  A' Z" p$ X' W4 o
# d% y- x8 S0 c5 i  s
void        APU::QueueClear()
7 m/ t3 t% l& r3 s. ^{# y3 N7 n( ~+ {2 v, _6 O+ A
        ZEROMEMORY( &queue, sizeof(queue) );
. Q% r. ~0 r7 Z        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ L7 T0 p1 i% K& z- L
}- c* x( |0 N4 r# m) V

) J/ h2 A6 R4 t6 x5 s/ {, ~! k7 c$ |void        APU::QueueFlush()
% F" |' Q6 e! t# Z5 s7 Q+ F1 r/ \7 h{; _2 g  W, u6 f
        while( queue.wrptr != queue.rdptr ) {
4 x: U2 o9 ?' u$ N4 w- t                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
4 i% B6 T, g5 T/ S9 E8 r                queue.rdptr++;
; _0 n0 F( f: G+ t& c                queue.rdptr&=QUEUE_LENGTH-1;
3 K& G+ i( z3 ?        }6 E2 o/ B2 E, r+ \: F2 A7 T
' r( `; i5 }6 O2 ~* s
        while( exqueue.wrptr != exqueue.rdptr ) {
9 Z- p9 N4 r2 I  \; ]. i4 J                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
% f4 \5 s& I( z. q6 q                exqueue.rdptr++;
# o! r: }# z) {6 `4 ]8 ]                exqueue.rdptr&=QUEUE_LENGTH-1;. f+ Z/ h, E( ]8 l- l
        }
2 ^; u; \& z  b6 v, G- n  H}
7 y% L2 W9 c$ |. e7 a! u" I
9 Y9 J% d. D% |8 _$ E1 ~' c" d$ nvoid        APU::SoundSetup()
/ W+ k  ]: Z0 m( ^. @{
+ e8 E' N& K# j/ f( {        FLOAT        fClock = nes->nescfg->CpuClock;
- a$ P1 ~, ^0 e0 c        INT        nRate = (INT)Config.sound.nRate;
1 l. _# ]  G0 A) C        internal.Setup( fClock, nRate );
. H. }2 e& J. o$ ^$ x        vrc6.Setup( fClock, nRate );
* c! J  f0 j9 u0 Q3 K        vrc7.Setup( fClock, nRate );5 w/ m+ ]4 o% l) d! d
        mmc5.Setup( fClock, nRate );
# U1 X% ^( F* S! m* a2 m        fds.Setup ( fClock, nRate );
3 }$ y, u% u, k! y0 G% p9 k        n106.Setup( fClock, nRate );, |) _& E5 ?1 P. Z$ ?4 M, {8 D
        fme7.Setup( fClock, nRate );; e5 B- ^8 F3 Z* x
}# V3 Y- U7 R' p3 a0 E

8 H6 [' r, L. v: Avoid        APU::Reset()
7 G7 Q' g' W; I+ l% m! z{4 ~! _* L' K) S; u
        ZEROMEMORY( &queue, sizeof(queue) );
3 ^* I, y! f+ y  b  I1 ^$ e! [        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 b& A- n8 M# v6 a7 R9 A
1 m8 ]" c8 B% j6 T! @; u8 ^* ?        elapsed_time = 0;; n3 l3 \: M; Q  b- R- y- a
& q) M/ d% j+ O
        FLOAT        fClock = nes->nescfg->CpuClock;" Y% k4 Z$ v3 [) R
        INT        nRate = (INT)Config.sound.nRate;
2 z0 f5 ]4 z- Y( g        internal.Reset( fClock, nRate );
& ^$ }: G. \/ E! d+ P2 {) Q2 U- s( W        vrc6.Reset( fClock, nRate );
1 F2 ?) p* ^6 ]) `( q  h% L. Q: n        vrc7.Reset( fClock, nRate );) U7 O4 Y: P7 o
        mmc5.Reset( fClock, nRate );$ b: d0 H, l( k) \
        fds.Reset ( fClock, nRate );$ {8 M4 w' _5 C7 H
        n106.Reset( fClock, nRate );) E3 Y4 H5 f* \
        fme7.Reset( fClock, nRate );
- r* R* C7 h) K3 g: u, v* @. P9 Q4 u; c- Q% F
        SoundSetup();2 x3 |! G) ~; ?/ H8 F
}  L, n4 ~; P+ g7 k+ `2 O( @

& W* L, S$ Y* Dvoid        APU::SelectExSound( BYTE data )2 g# z6 V0 r  h% p4 ?# ]5 a
{+ X7 F: b" j1 S8 P! G/ ~' `
        exsound_select = data;7 @, l; C. A# k! I. D$ S5 ]
}
! {, Z& G4 a: m1 f; p3 z
' x5 V8 h9 k9 i4 L& l' }BYTE        APU::Read( WORD addr )# X. Z, `# q* S2 V" T9 W0 ?8 o9 `
{9 K3 G8 s' U6 v  z9 [: |- j* L! i
        return        internal.SyncRead( addr );
) _& f- Q) W* \$ l' g}4 C3 O9 h& j. J* b
) w- p1 ?7 [" G7 O1 I1 I" J3 f4 ^7 S
void        APU::Write( WORD addr, BYTE data )
$ \. G$ |+ L! g: B) L* o' U{; z1 g& [0 a5 r- u
        // $4018偼VirtuaNES屌桳億乕僩5 o0 X; v, i" E8 S# k' G- ?
        if( addr >= 0x4000 && addr <= 0x401F ) {0 H+ C% ]. r1 Z, S* ^/ c
                internal.SyncWrite( addr, data );/ u0 o( e0 y' f9 J& g- P
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' g# \! x! r# x% [! F6 ~. n4 i  Z        }
- _3 k' ]3 u; z! Z5 ]9 S8 k( G* z}
3 p5 K& \/ U4 `
! t5 l9 N9 _( d* R6 PBYTE        APU::ExRead( WORD addr ): Y" p4 V/ R+ k5 W* j* H
{7 V& B, y( q" w5 F
BYTE        data = 0;3 p+ @5 M% |* O: ]# I, m: U

, M: M$ a) S% T! r2 q) `        if( exsound_select & 0x10 ) {1 d6 T5 G8 j$ J* A. d
                if( addr == 0x4800 ) {* |2 G' ]9 f$ }) m. Q3 i  e
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
% \" t  G' J" x2 d4 H+ k: Q                }5 }1 V) Q* ^* ^6 m
        }# @( S% L2 l3 d
        if( exsound_select & 0x04 ) {
( [2 o$ I$ E$ [) M& n                if( addr >= 0x4040 && addr < 0x4100 ) {
$ x( a- b/ k% f5 D/ p; P) }' g                        data = fds.SyncRead( addr );
2 G8 a+ ?0 r0 z" V. }; _. E, Q7 {7 w                }
2 C0 o" f- w# n' E0 }        }
; Y! Q& f6 O; N        if( exsound_select & 0x08 ) {% q0 e  a' Z, z+ Y- q5 s: Z5 h5 B2 b6 ^+ y
                if( addr >= 0x5000 && addr <= 0x5015 ) {6 r5 Y& W7 R4 S
                        data = mmc5.SyncRead( addr );
- p, o5 O  \* t1 i- b& I4 Y! }  S                }- `# r, y2 H& o+ ]% M
        }
( T4 g: f4 y( k4 a% G; e5 F) [; z$ {6 S1 g6 y( P! Y
        return        data;
& ^& R/ a' T; t, _}6 U% C/ d' R% I# G3 Q' {5 P" b1 m! [
0 z+ z3 y2 x( X5 ^
void        APU::ExWrite( WORD addr, BYTE data )
5 K' s& S4 F2 }# e5 p) j# o0 C' d. h* X{
5 B. \' K9 S$ m0 \& b8 |        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );6 v7 Q( r/ A) x! e

# f1 m2 R- L3 S  B0 E2 n! u, q# C        if( exsound_select & 0x04 ) {# c" \3 V4 J# U0 A
                if( addr >= 0x4040 && addr < 0x4100 ) {, U2 ^5 N% |- x  G* m
                        fds.SyncWrite( addr, data );, n" c/ J& m0 m( p
                }
: C! B' ~2 d- \        }
* H% @  ]6 I. y) e' h8 t$ d+ e
1 B" Y) i9 y$ J8 |# ]        if( exsound_select & 0x08 ) {
' C+ p; Q' S0 _0 }2 c                if( addr >= 0x5000 && addr <= 0x5015 ) {
" Q* B: {3 U6 r  ^/ Z9 b                        mmc5.SyncWrite( addr, data );
. A" }+ }( h& D8 m" i                }0 G0 N: T; j& I9 }+ E* v- l5 |/ o
        }+ ?1 R, `, O* o3 d) s' Q! ]8 x  Z
}
2 _6 H2 n/ {7 P1 O0 }) s6 Z# ^
: b1 \: L* B+ j! \7 k3 t# lvoid        APU::Sync()9 `+ m; M" f# J# g/ {0 k3 G
{
. d# N- u# V5 L) B! U! h% v}8 V; f$ [! P! O) P! \

% _2 I; ^$ E! y+ g9 Ovoid        APU::SyncDPCM( INT cycles )4 ^8 |; o# A2 u" i4 a& P! ]' F
{5 S% [* l' w# ?
        internal.Sync( cycles );
3 p* h$ s* U& a/ R0 z
/ F$ y* j, A  c% k% u        if( exsound_select & 0x04 ) {
& ~7 R6 ^& G7 }7 M7 L/ C                fds.Sync( cycles );
  c& B$ D' V% R. Z0 j, k3 e# }        }; L  ]0 e; s; b; x( c1 q+ V9 I4 U& L
        if( exsound_select & 0x08 ) {' F" h3 s! F3 S) k
                mmc5.Sync( cycles );
- j, ]5 t" c) Y3 C        }
3 v( s$ A9 I' K6 u9 f, O}3 z! h& \! M# S; s0 `& K1 p# k5 O
0 B: j: C/ @) y8 u; A. g
void        APU::WriteProcess( WORD addr, BYTE data )
# V/ H) I+ z# U9 y{$ d! y) N2 O- Z6 B
        // $4018偼VirtuaNES屌桳億乕僩
1 a1 Y, p  y) y( _1 N; u/ t        if( addr >= 0x4000 && addr <= 0x401F ) {$ U$ a: B8 X* f0 f7 }/ I$ Q
                internal.Write( addr, data );
% |- O$ n6 w$ B1 D+ H        }
- G/ }" s$ C% H) x}1 V' C. q  p+ B! p. b! I
% j0 R# P$ p! k3 G) g
void        APU::WriteExProcess( WORD addr, BYTE data )
3 H0 c! `- G0 Y! Q3 m" K6 }3 ?{: X: q8 g' q5 R
        if( exsound_select & 0x01 ) {
' W/ x% W7 X/ V$ ]& Q8 w2 d                vrc6.Write( addr, data );/ m- e+ X' {- _
        }
. Z; y9 f2 |; ~2 M) }6 q        if( exsound_select & 0x02 ) {) h* }/ B% S9 f# J7 C( h% y* O7 X
                vrc7.Write( addr, data );
, c. V: |7 P# P  N0 z        }
! q3 Z0 i: R: {0 ]% O        if( exsound_select & 0x04 ) {
$ |/ x2 p- {' e8 w                fds.Write( addr, data );( n" B' d8 r2 S, P) X6 v
        }
6 D1 y0 }& R+ d) E' I; t        if( exsound_select & 0x08 ) {
5 V1 F: ?( q1 u                mmc5.Write( addr, data );% Q- V& e+ P0 i! R# ]8 r* \2 a( F* K
        }
  v2 b! g  {- d- X. ^0 {        if( exsound_select & 0x10 ) {
" M* D1 u, j! @# U% B. H                if( addr == 0x0000 ) {- P$ S" [: R. Q7 ]0 d
                        BYTE        dummy = n106.Read( addr );
4 t& A; t  X1 b8 X                } else {% {2 u! Y( ]6 \& F: p
                        n106.Write( addr, data );; x7 }3 F& G3 K3 z5 f' m2 v$ a$ l
                }
* b0 a" I3 Y: j9 {        }
( P! z9 O+ v6 N# }  l2 l        if( exsound_select & 0x20 ) {  K) K8 R  G% g; ^, Z
                fme7.Write( addr, data );
- v# ~$ X# w2 I% D1 y        }
# {* i, w  k, Q2 Q1 X}
! j+ a4 \/ l. T: ?' c4 z4 I+ H8 R8 N" O: z, }4 Y" ?
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )) W, P# W8 |( E# s
{
' L* z! `/ ]8 r& J, S$ F8 p; s) _INT        nBits = Config.sound.nBits;/ b1 N' X2 d" A  Y1 M1 D
DWORD        dwLength = dwSize / (nBits/8);- A1 i  Z+ X8 v, Y) L' {$ u" L1 M
INT        output;
5 b% h9 k) _. ~8 W" gQUEUEDATA q;- l. [& A! h6 X% T& P: w  d
DWORD        writetime;
  V8 _8 J8 Q0 _- f) R
0 I) q+ P5 x) z% KLPSHORT        pSoundBuf = m_SoundBuffer;/ G% w! C/ G( ], H
INT        nCcount = 0;, c2 Q, Z# L4 z9 R& \  v3 R
+ X8 W7 k  B# r) @/ @4 C
INT        nFilterType = Config.sound.nFilterType;7 O5 u6 u5 X  R+ S! O4 F. y

& G  i9 ?- n& W1 e5 ]        if( !Config.sound.bEnable ) {
' V$ U% W0 @6 f% a) }1 c                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# P+ k  `+ A  U% k' D3 U7 ^8 T                return;7 K6 L$ V/ D3 V6 i& e6 z7 W" }
        }+ a0 E1 ^6 [$ m8 O4 Z2 M" |

. _3 p# g# v$ A' w  O. w        // Volume setup
* g5 d; t% l5 B5 g# _. N        //  0:Master2 }! m2 j6 c: q, R* v- f
        //  1:Rectangle 1& E# y- y& g' }3 M, H5 i
        //  2:Rectangle 2) q: O& V: ?' j2 l& i8 b
        //  3:Triangle8 x  w  O" \0 m* i( L
        //  4:Noise4 j& n& G. }8 ?2 I; ^/ r$ ~% I
        //  5:DPCM' p2 e8 a: S3 Y
        //  6:VRC6
2 ~6 v6 d8 f* B( b# y2 ?        //  7:VRC7" L+ y/ R4 e* Q. t8 R& l6 _$ `2 Q
        //  8:FDS
- g5 t7 T! G1 P% M& l        //  9:MMC5% }/ D3 F+ ]/ h3 F' c! R
        // 10:N106
! r% g2 f1 ]5 q        // 11:FME7
8 u9 {/ M, a, e% f. c" D- S, ]/ X        INT        vol[24];
: i( F& Z4 K# k: p        BOOL*        bMute = m_bMute;
+ j; o! t- ?, l; [$ c2 L        SHORT*        nVolume = Config.sound.nVolume;9 j3 f5 v; B. Z# N3 p, Q
3 a6 y2 _2 }; U: o0 `2 g% |8 R6 X
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
! g+ D8 L# L* h/ B$ b1 f7 \
6 i- I9 f$ ?: y  P) U, j: L        // Internal$ f3 |  b* w& S; ^
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& g5 m5 j9 b; ?5 v; ^; P
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;) L# J$ b, A: ^, b1 l$ {
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
; U: F" m( ?2 \+ ~        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;) R. Q. C$ [% n7 M
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. I& x  N: a+ c! z2 n1 D
. U1 `/ V" L( H; ]+ K        // VRC6. Z7 H& u6 o! u, Y9 I2 J
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ ]( n4 g" Z" f! m8 Y: y. F" o        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 x/ R. W3 J7 _+ w7 \3 N/ H
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 B5 ?3 i5 r" q. C6 j; v% {
3 [% h" z2 z1 t8 B        // VRC7
7 H& I7 N( p" f  I+ ^$ Z, m        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
; s" `$ Y4 K, |# ?. k; @( ^. ~2 S+ M
        // FDS$ [: T( W8 |4 T; C3 ?) Z" G6 |4 m  c
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
; S) @% @& Z( f7 A# L/ u. n& d3 o: t8 J& x1 a+ h
        // MMC5
7 P9 V+ G/ T4 P  q* y5 t        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) r& p. B% V* ?
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! n  s& A  {5 E/ t  b6 Y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# [' i4 i4 x9 p( d- v/ d3 M: r' l3 g2 E( m; V' z
        // N1065 r# C; l( w9 i( X
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" ]" I2 s$ m3 j        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. y& C' E7 z# X( X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, h8 }" y: c" y" x( Z; G$ E) i. F+ S        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 s3 v; O3 h, p+ K4 q        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& o; H* y6 ?( _" F( q4 t. f" V        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 I9 O2 v' f9 [) c% ^        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! \# n3 [) M% D+ J+ x0 A- l  Y
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 R8 U) Q& v& U% y
7 o! T, b$ N2 q! B        // FME7# o* \% d4 T" w$ ~/ ?  Y3 p
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 o2 D4 t  Y9 D# |0 S' b4 i$ V3 M9 a        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 x, }- D& }8 T! \5 i+ ^" }
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 G$ W/ c. {6 ]" x3 r- b+ {- d  h  p1 B7 C  t0 {) |' s
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;5 r, _1 \8 F$ B- C8 A1 i
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 J% }( P0 h+ {# m$ |" {% e: X  }8 I, I4 X
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟) n/ a/ w# G# H2 e- M
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
. [8 t+ ^  H4 W5 \& x                QueueFlush();9 x' ^% F4 N0 Z, ^  o! ^8 X
        }+ }% F, q, X, ]2 h3 Z
2 |7 _# W8 F% \, _4 p  M
        while( dwLength-- ) {
8 e& n4 i' n; a* k                writetime = (DWORD)elapsed_time;5 @, K+ P1 C% ~5 ]
" y9 N! _- y8 W! _7 A
                while( GetQueue( writetime, q ) ) {; c& G; d% N' v8 D( F3 ~9 p9 P
                        WriteProcess( q.addr, q.data );" z* V3 v8 ]" O  ]3 W$ u7 N
                }( N7 M" M7 F  Z. i/ L/ Y* C
9 @7 P. U) x; Z
                while( GetExQueue( writetime, q ) ) {
# A5 w7 C8 ?- ?/ \% ~$ f                        WriteExProcess( q.addr, q.data );
* l& o, N4 Q3 H/ @. h. Q1 x                }" t9 v5 g, p, d
- j2 |+ T" o1 o9 B; m
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! b. ^+ r$ o" w
                output = 0;
5 \& f: a: b( o4 a                output += internal.Process( 0 )*vol[0];
9 i* J$ ^5 @9 Y/ S3 ^" A5 y                output += internal.Process( 1 )*vol[1];5 O$ P: v. h" u. L* S5 }
                output += internal.Process( 2 )*vol[2];1 A' S5 s* ?( z
                output += internal.Process( 3 )*vol[3];7 B1 o' S2 \, D+ C1 X. \
                output += internal.Process( 4 )*vol[4];
0 d4 |9 ?& `* E+ p4 f2 |
6 Q5 J8 H- f/ R                if( exsound_select & 0x01 ) {
  C6 q, R$ L% ^; U1 k                        output += vrc6.Process( 0 )*vol[5];
% ~: s0 n# R) x7 C" ^1 m. {                        output += vrc6.Process( 1 )*vol[6];# [9 i1 k* \7 V' `& \1 }
                        output += vrc6.Process( 2 )*vol[7];! a- ^( Y5 J0 b8 U' v5 V! D  e
                }
7 [& m5 v1 t1 s3 B- I! |+ S                if( exsound_select & 0x02 ) {
; R1 Z( H( i( X9 n8 y& l                        output += vrc7.Process( 0 )*vol[8];1 ?. Z8 U: J& g  n
                }& `6 d) T3 q6 ?+ g4 [) D
                if( exsound_select & 0x04 ) {
" i  n/ Z. o$ u- U- H1 M* P) q; F                        output += fds.Process( 0 )*vol[9];, y, d/ z( ^1 p1 k  x! Q" Y
                }
0 H4 i! P$ ?# j# b                if( exsound_select & 0x08 ) {
* N$ T) f% E" r% v                        output += mmc5.Process( 0 )*vol[10];$ T7 l$ F+ |6 ~5 f& V; p! c8 W( F
                        output += mmc5.Process( 1 )*vol[11];* {6 M" s/ E3 W! g  L0 Z: ?2 ?
                        output += mmc5.Process( 2 )*vol[12];; k$ l# r) a% i% A1 t
                }
: O$ c0 q6 B- j. ^* f+ o                if( exsound_select & 0x10 ) {6 O( F7 H" f* K
                        output += n106.Process( 0 )*vol[13];
6 X; W9 r0 S8 A- [& g" z; {) W                        output += n106.Process( 1 )*vol[14];
2 t; _7 \; ]) |6 J                        output += n106.Process( 2 )*vol[15];- p& W- x" M1 l! v
                        output += n106.Process( 3 )*vol[16];; I0 W! a) j- [; Z. `
                        output += n106.Process( 4 )*vol[17];9 y$ D2 B1 d0 b8 r
                        output += n106.Process( 5 )*vol[18];! Z% S4 C9 B! U5 ]" D" u
                        output += n106.Process( 6 )*vol[19];6 W2 v- j4 ?4 T2 h& {6 a
                        output += n106.Process( 7 )*vol[20];
# w9 U0 |% u/ z5 W. l* u- n9 T                }
1 l5 h5 V. h- x/ D, [5 Q" S# \, @                if( exsound_select & 0x20 ) {8 Y' L7 ]" K1 e* X3 H& F; Z
                        fme7.Process( 3 );        // Envelope & Noise
5 A, X0 v# R& _" Z; n( }" ]                        output += fme7.Process( 0 )*vol[21];
1 }$ h/ W/ t" q& F                        output += fme7.Process( 1 )*vol[22];: C. V- x9 T6 Q8 r$ Y9 H
                        output += fme7.Process( 2 )*vol[23];/ q0 ^' `/ g" ?5 ]: W
                }5 I& @4 _' q0 L( D0 I
4 [6 H4 A/ K. [$ ]6 P, B
                output >>= 8;
- _' c' @. Y/ z0 O
6 \+ o) k7 [: P' e) e                if( nFilterType == 1 ) {/ ^. n0 K% `1 p! `
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
+ P4 v3 [3 Y4 ]$ r                        output = (lowpass_filter[0]+output)/2;
  ]8 h9 N$ O2 o1 H" z3 I7 x+ c* u                        lowpass_filter[0] = output;. p, w+ t8 x* f8 a1 N( R/ K
                } else if( nFilterType == 2 ) {
* Q4 C) W( q5 ^& U$ ~2 O                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 c/ P2 D" g" m. t                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! b: K' U# Q* H8 Y; ?% g                        lowpass_filter[1] = lowpass_filter[0];
9 g6 Y: g+ @4 l! {3 ^3 Q+ C                        lowpass_filter[0] = output;0 ?% x# ?, w4 V( _' Z. ~
                } else if( nFilterType == 3 ) {' c' }8 m1 L% Z; ~
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
4 O: Z. w1 b. C1 T4 ]( b$ A/ `: `                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
* X' z, q5 I" z. U                        lowpass_filter[2] = lowpass_filter[1];- V+ r& n/ s* ]
                        lowpass_filter[1] = lowpass_filter[0];
4 V* v. i$ \9 H; l, U5 `9 U                        lowpass_filter[0] = output;- L3 }0 o' X* {6 b3 C) `
                } else if( nFilterType == 4 ) {% [' E9 t* g$ F& r! f
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
0 x* F' B6 N4 i6 s7 m! d                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
' v; L2 b, v1 p                        lowpass_filter[1] = lowpass_filter[0];: ]" K% o+ t* e, U+ q8 j& [) n$ C
                        lowpass_filter[0] = output;
; ^3 X# Q8 p$ E$ @                }; q7 Y, K2 J; h2 P

: x, z  v! m1 Z9 r. M/ r#if        0+ I+ y! e( V; [; V% J, {
                // DC惉暘偺僇僢僩
/ k6 g1 Q+ _( c' ~8 Q* C                {4 ]* j, b% V, S% T, }: j
                static double ave = 0.0, max=0.0, min=0.0;' Q0 A" H; }0 A' ^" J
                double delta;
6 U5 G, Y- N* \& ^) u$ g, I# _. U/ i                delta = (max-min)/32768.0;
2 t- W1 ~* Y. {7 |- s8 J                max -= delta;8 F5 w. s. I" A
                min += delta;4 G% t! l' m7 ], ]* ^
                if( output > max ) max = output;
$ x" o6 M0 m/ h' |1 ]$ s) d" V7 c3 W                if( output < min ) min = output;5 \0 e& d6 p8 f  B
                ave -= ave/1024.0;: g: Q; ?1 h. D% G
                ave += (max+min)/2048.0;! C9 }3 U0 D: {( G2 v# N
                output -= (INT)ave;
) y4 s  n. z  t% z, z% c                }
* q. _: C4 |3 J0 ?#endif
2 H2 e' `/ G9 T#if        1
: `3 e- I! ^$ L. f: ]$ w! V                // DC惉暘偺僇僢僩(HPF TEST)
# f* d+ T& G2 o0 W                {- r9 c) E) b! _0 ^* S( _2 Y
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% D8 y+ C, u- v8 B
                static        double        cutofftemp = (2.0*3.141592653579*40.0);( v8 q  a2 _8 o9 D
                double        cutoff = cutofftemp/(double)Config.sound.nRate;7 l8 S- j3 W8 W$ P! x6 c
                static        double        tmp = 0.0;1 h' b2 Z; @; L1 Z  V
                double        in, out;5 Y; |; p9 N% [3 G# X& L+ Q3 C

" ]5 C3 B8 W! S7 m7 T                in = (double)output;' P8 u7 U7 S: X
                out = (in - tmp);
+ L% ?% C3 e  h, M. b, v                tmp = tmp + cutoff * out;
/ F9 O! L8 [' u% q' `' W( r4 t& w, U3 o
                output = (INT)out;
* g( z9 T+ l' u% n; ^0 r, T0 ~* L) ?, |                }
; Q( i5 j; o% `6 `, \0 s#endif1 \1 j/ ~0 B$ O- a, \
#if        0  r. K7 Z7 O) Q3 c3 u! O9 f
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* F$ c6 T- D  `- K; ~& H                {" Z& i5 b4 c, \% n
                INT        diff = abs(output-last_data);1 `( {7 s% _( `/ t
                if( diff > 0x4000 ) {& r6 I! ?$ R! D9 o, h- `! K
                        output /= 4;+ B6 H9 N6 z6 Q( Y2 p
                } else
. @& ~+ j/ ]1 S. c. Y; g# i( s0 w9 B                if( diff > 0x3000 ) {
& ?4 `$ \/ ^3 R% i3 D. `7 C                        output /= 3;
% P, Z; R( Y3 o! Y: g3 ^* p0 c( ^                } else
! m8 T! a/ V$ j3 b- k                if( diff > 0x2000 ) {5 m  M% T  ~0 K" P& ~. Q
                        output /= 2;6 O" I9 U9 ~  W7 V4 m2 d
                }
$ L$ t" F! j0 o; Z. A& p                last_data = output;2 G& `- O$ Q" ]' Z% e4 q: y
                }
' Q- q2 ~( r: O* T: `/ [#endif6 W0 l7 Y6 s4 X0 e4 t5 E! W7 c
                // Limit
% G, D* K# S2 x' a: P6 j: n                if( output > 0x7FFF ) {
5 _( y) |- D0 D( k9 @                        output = 0x7FFF;. F$ U; i0 S4 _
                } else if( output < -0x8000 ) {5 y* E% T) L2 D- p
                        output = -0x8000;- w: I7 p! S( x5 q; y/ T
                }
0 L. Y; G! N, G. N4 H  I) j! @: ^  Y/ a6 i
                if( nBits != 8 ) {
8 i" m$ ?# d' q( O                        *(SHORT*)lpBuffer = (SHORT)output;
( p* x6 Z8 M+ D+ g' E                        lpBuffer += sizeof(SHORT);; L8 z, b+ t! ~# ~
                } else {9 B- L$ P& m  g; J! a3 y4 l
                        *lpBuffer++ = (output>>8)^0x80;5 ]! E. n2 P0 b/ I/ g
                }4 b$ E- w- Q/ h- R  a

0 f& v& `# W% y0 [                if( nCcount < 0x0100 )4 _$ p+ y1 V8 n
                        pSoundBuf[nCcount++] = (SHORT)output;( K7 k, i$ G/ o, O/ h. F

% W" m; m7 l7 K5 T4 g8 N//                elapsedtime += cycle_rate;, `  [, z' r- R9 n0 Z" |
                elapsed_time += cycle_rate;
6 Y. ~5 x5 T1 D# b# \        }
( ^% ?6 l& g% y0 h' t' _7 U5 k6 v1 x
#if        1. d+ x* l; a. [- _) l4 |: C! M8 N/ V
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% K5 S) B7 q  I6 c7 i* X2 ]9 [                elapsed_time = nes->cpu->GetTotalCycles();
  D' r: w- v2 m& {        }
6 }. U" G% j/ A: V6 y7 Y+ m        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# Z. k* g: }2 t+ N$ d- E
                elapsed_time = nes->cpu->GetTotalCycles();( ]( q* f" o* s2 t1 h
        }. d  V7 f0 q( [) p7 X, ~7 y! w
#else
9 t/ l" W' X5 |        elapsed_time = nes->cpu->GetTotalCycles();: y) k7 i( p8 L. B$ k1 N
#endif% M& d/ J! E* o- N4 U% ?6 `0 O
}
+ c, k9 K& w$ d( P8 K' |9 V7 `1 h4 I/ o( ^, k. ~  C7 g& F9 e
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)2 h- A; S: i3 p, a6 K) a
INT        APU::GetChannelFrequency( INT no )! Y3 w* w, N, w1 Y* j7 c
{
, G  q0 c$ N- y+ E: O; a        if( !m_bMute[0] )
* R. c$ F+ \4 [/ ?$ Y2 C+ a" R                return        0;
/ ~8 m3 V5 }. D9 X  N: y8 ]4 q" N* D+ V
        // Internal& o3 }" ]& F. ]. B
        if( no < 5 ) {0 {+ Y9 E% ^- S  v1 i
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- H+ U" ]9 n* D/ S) l        }
# `- P7 [+ u' ?        // VRC66 E" \$ u5 r4 ^8 N
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {3 E; E* T( Z4 S! R  F/ k: e5 j
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# h) d5 h7 H& I( I4 A1 Q" T
        }; |- L5 x1 {! c
        // FDS. M. l' F/ O4 J1 y
        if( (exsound_select & 0x04) && no == 0x300 ) {8 \' b+ B) H+ a2 A7 Y. r" K
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
! }7 b, Q, W  n        }  s2 ~+ S% w& W6 Z5 X+ U
        // MMC5
2 q* q3 W( G) v! d7 t& n, Y. ]        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {9 |/ [! b  @8 s' w6 `" J4 y* |
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
4 \# s. r& |& f; A        }7 C9 j/ s5 J' g1 b1 h: P
        // N106
* y. z0 q* D) y) ]9 K  K        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
. N+ f, N2 e- ^1 m' s; f( |! m" t                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
; K$ \' B' N" l4 H% a2 l        }) F5 G% k( t; v* i/ D1 w
        // FME79 P7 [" M) V, U7 p7 n0 h. ^- ]; Z+ x( d
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 _( }6 R0 r2 p2 I% A$ L' a/ v# h                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;: C2 e+ z/ G% B( j- [# ~
        }
0 E0 n) q2 u! z1 r: Z+ G$ T        // VRC7: z+ Z5 w; G7 ?+ E1 U9 n3 c+ w
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {3 Z0 n& W: {7 C  Q' C) J
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;7 P6 a! t8 |3 q9 n0 M# h4 x
        }
, z/ m! y6 ^* C6 j  H% V        return        0;& d, i5 Y& O( b$ r% @9 ~
}
* x5 |# Y2 y+ O
) H3 N. H7 E# d- H7 {# a6 l// State Save/Load# @' o# `9 l; I$ K* n4 }
void        APU::SaveState( LPBYTE p )
4 I+ U" t2 l0 i( w1 S1 S  r1 I{
' R  W" J/ ]7 I8 |#ifdef        _DEBUG* p- l; [  D% r, ^
LPBYTE        pold = p;; _$ z3 j& P1 v/ Q9 A
#endif
6 R6 M4 B/ M% b5 x' i
/ e& F% G) b/ c( l& g5 d  u# k& {  m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞# N5 b  b7 }, `+ y* q$ Y
        QueueFlush();
% e' f, ~: y6 |) y+ B+ e) i! @6 r. ?0 L3 [. Z
        internal.SaveState( p );
, R- v% w1 X( Q! R        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# }% N  F' c5 @1 D6 c4 J* D
( Z8 j$ O1 I; J' f7 m        // VRC6
6 y" e5 W/ c- i& x+ v( p$ F+ d' M        if( exsound_select & 0x01 ) {
; Q9 V$ r" ~, J3 G9 J% ]                vrc6.SaveState( p );
% C( U! n- J. m/ P3 v$ J& T/ S$ J- R                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 M5 @: Y. @% G        }$ ]- R1 I/ j' Z
        // VRC7 (not support)' z3 {6 n9 x, H" E; V9 |
        if( exsound_select & 0x02 ) {
( p9 |: N% a4 \: P% j, d                vrc7.SaveState( p );
2 P3 K# e% h9 m9 J& j                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 f: g& l; w+ u! q        }
8 j! b3 U  K! I; P+ S& s9 B" }        // FDS  a$ l( Q, [+ A0 W# m
        if( exsound_select & 0x04 ) {
6 i: v2 O" S6 V5 ~, q7 V                fds.SaveState( p );
, Q2 x; M  \5 L* K                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 v$ Y0 T: z$ x" p) |1 ~1 I
        }, W& }: G; A( K0 B( h
        // MMC5
& m( ^5 s( t4 F- s% _' V4 \        if( exsound_select & 0x08 ) {0 ^! s" T% W9 m7 j5 p1 h
                mmc5.SaveState( p );
4 L. ]% z2 R  T: v                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( T$ m4 T- a, i! @1 l/ l        }$ J1 \0 l0 M6 s; T% J5 B
        // N106  F3 e& D9 o( t- q% u" m
        if( exsound_select & 0x10 ) {4 @, F+ [6 I) W& l1 |+ S
                n106.SaveState( p );
3 b5 s% J/ a+ i( _                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; b( B0 t& U( m- L! A
        }
( h3 M+ W! [, ~! a' \* p        // FME73 z6 d8 v8 F7 R! R  Y
        if( exsound_select & 0x20 ) {$ \% e  W# @4 M- b2 m
                fme7.SaveState( p );
0 K4 ^" m4 ?$ e                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' J8 @' l4 e% B" M  T
        }
2 h% x; R" L2 D" ]
, J7 L  E2 }3 J. y: T: `#ifdef        _DEBUG4 u0 Y; W% T& U* Y
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ h5 \- h) J) i#endif; G( i$ T+ W% F* R9 w; k
}
  H0 w9 g$ i/ @) a; Z+ e4 W- y
' q: T% G$ Z' e# }1 j$ _! }# X0 _void        APU::LoadState( LPBYTE p )
% F0 A  }/ m, O2 M. h  w2 X' U# O{
6 S$ g8 S2 j2 K9 g        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. q' Q$ N' z2 ?) A. R7 v1 w6 k7 v5 Z        QueueClear();
$ ~9 F; N7 _4 G- j" D2 ^9 m
& a2 h' u) ?& C        internal.LoadState( p );! K  \( _9 s3 I* o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 e8 I8 a* P4 @2 a0 J& s/ e! j
/ @; T. |, ?7 H$ B' F4 Y
        // VRC63 k4 L$ t( p  q2 j
        if( exsound_select & 0x01 ) {
% m5 H/ |4 J$ f                vrc6.LoadState( p );/ q, P- Y2 E2 q2 o. c! ~' Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: o1 k- C. W  a& s1 M3 l        }
" @# A9 O6 V7 h/ u        // VRC7 (not support)4 y& G2 ?1 D: B  G4 C
        if( exsound_select & 0x02 ) {
+ ^- Y, i2 Z" f* D7 G                vrc7.LoadState( p );
/ I' K" r& F/ l9 H" F& L+ Q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! ~' J- M, e; V9 C        }' r# }" g: e. J) w1 q
        // FDS1 C! K/ n5 w1 b" p6 F
        if( exsound_select & 0x04 ) {" I6 q* H4 J+ D' X: S3 `' \
                fds.LoadState( p );, H8 H0 G4 D) I& h1 R* U
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" I& g4 l) |; t) ]% D        }
& n# Z3 g. u7 _3 b        // MMC5
: \$ v  v; B8 o. G. l, G1 ^1 r: M        if( exsound_select & 0x08 ) {
. N+ k8 w8 G7 @7 [                mmc5.LoadState( p );
* {; l2 n) F4 @% |2 D                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, p& Z7 J' D8 I( y% E
        }
6 _; K$ Z- k: E  r        // N106' E  @! _' F( U7 O. N) }; v
        if( exsound_select & 0x10 ) {
( q6 u, T) h: b( L. ?                n106.LoadState( p );$ e: s0 G& ?2 _2 y& A' c: X  z1 N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! d3 u0 H; f9 y/ B2 z        }
: Y( F# w) T4 ?1 H$ f0 }; Y( z        // FME7
4 l+ Y/ p. p% z9 z1 d- _* s4 B        if( exsound_select & 0x20 ) {
% p5 D. c& a  q. c. |  L! B                fme7.LoadState( p );
/ O* H$ |2 X  _2 D* ^: g0 f' o! ^! Q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ m: B: \; N1 \/ B
        }  t$ D* o" w$ n8 y1 z
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
+ M1 s8 ~$ `9 K; t可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* M& w0 Y) p, a2 t
感激不尽~~

" w9 t* q+ X  F6 p- [# `恩 我對模擬器不是很有研究,0 X5 n: L: l) ?# y6 U& ~3 |
雖然要了解源碼內容,可能不是很困難,
( Q' R. P: D& W  n0 S不過還是要花時間,個人目前蠻忙碌的。+ F: e! t9 S. Q8 Q* p1 G5 C
9 `1 O; E; @1 T
給你一個朋友的MSN,你可以跟他討論看看,
  w4 W% X* c/ a他本身是程式設計師,也對FC模擬器很有興趣。6 ~7 l3 d  Q7 N
* H2 N2 Z; f, F& S0 O. c6 D
MSN我就PM到你的信箱了。, d) y, D4 @, f
  R/ m, h6 P9 J9 O7 j5 N6 w
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 & z0 @* i$ [+ A, C# w
呵…… 谢过团长大人~~
5 j: @2 v" |3 \. L8 a# [3 ^

2 T2 j) \4 k: Z: z% e9 w- T哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
. z7 ?. v; U$ Z: n, M团长的朋友都是神,那团长就是神的boss。

: H1 E/ J3 E6 [& j1 ?) F哈 不敢當,我只是個平凡人,
* q* O9 h- {7 z" ^8 |$ s7 K' X+ w要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙% g. Q' ^, Z- z7 M
ZYH
' F& }, H& W& T/ AQQ:414734306
' Z! d' K. m8 Y# {1 f9 ~3 L0 jMail:zyh-01@126.com
0 ]1 ~% e9 E/ b2 l/ s9 u/ Z( \1 `! [( V3 l
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 : ^  m: c7 @3 u5 J1 F7 N( G0 v$ |7 }$ j
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ x. d1 T% a; K
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-8 16:43 , Processed in 1.116211 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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