EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 i, i; P6 e5 }- I' P( D) z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! Z0 M3 F3 Y: U
这里有相应的模拟器源码,就当送给大侠了~~  _( Q& s/ Z' U4 ~/ u0 ~
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- _& o. @/ K0 E. L$ P" O能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  e  Z' e& L9 h; L
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' U6 E& I/ Q! B) g; h* `
这里有相应的模拟器源码,就当送给大侠 ...

! b! A. `! [2 c; j聲音部分(Audoi Process Unit = APU):0 K/ p1 F1 u8 V9 R6 m
.\NES\APU.cpp: `/ N3 H, m/ _  W' b: K" O
.\NES\APU.h
. B6 Q' ^+ j4 z- A
8 h# U0 e  [3 [/ N: c
# t4 m5 w9 B3 ]: g影像處理部份(Picture Processing Unit = PPU):* m% P9 N% E* d
.\NES\PPU.cpp
7 f% j4 c" z/ X.\NES\PPU.h
7 _2 W' Y+ ~: I' G/ Q
; o9 L5 Y6 l* j9 k( I如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ Z' D$ J# M. Q- ]$ i. a: v
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ Q0 e  y) I" Z: N& o
//////////////////////////////////////////////////////////////////////////
; b: m: N9 b. ~0 k//                                                                      //7 z2 C* O1 |/ A, a" m
//      NES APU core                                                    //
  a2 \! {2 U# T; \, _//                                                           Norix      //3 n& E% }! i# i
//                                               written     2002/06/27 //# [; Z0 }) Y0 Y  p9 h, d" X
//                                               last modify ----/--/-- //1 m2 \0 H: N/ c1 s* R
//////////////////////////////////////////////////////////////////////////
3 J' G0 a; p, w#include "DebugOut.h"% r9 i9 e8 V- M& j) s( X$ ~2 m
#include "App.h"
7 l& K* J* W; v0 F% i#include "Config.h") Y3 o5 e6 J5 v+ ?: [: w
( o% z3 n% T& \# ]5 R& l
#include "nes.h"7 v, a1 N6 l8 T3 {$ B4 V: M1 B
#include "mmu.h"
! U# N5 c- A6 S: k$ ]3 e" e6 n4 c6 S#include "cpu.h"
2 o4 |$ \; C# {. I9 z( D2 }3 V#include "ppu.h"
4 [( b% g& V) W4 T. D% F#include "rom.h"
% n: d. n+ F) S) B4 a) V#include "apu.h"  T. Q- V, O' `/ \3 p

  s5 {' u" ?2 Y7 ^3 }// Volume adjust
6 G2 g! X: ?; d1 r0 W// Internal sounds
  y$ _4 Q  b1 X#define        RECTANGLE_VOL        (0x0F0)
, ]3 A8 e! _8 w+ O$ k* T#define        TRIANGLE_VOL        (0x130)
/ l  W2 d- m7 e# u) m8 g6 R4 _9 `#define        NOISE_VOL        (0x0C0)
! \& v( h1 z+ [8 s7 Q" ]$ g#define        DPCM_VOL        (0x0F0)
) y2 p$ G/ [: F" [// Extra sounds9 t6 E# b/ {! Z1 P/ }/ \
#define        VRC6_VOL        (0x0F0)
! O. Q4 Q- p6 @6 P#define        VRC7_VOL        (0x130)
) J! N+ Z2 c7 x+ b9 s+ _  T#define        FDS_VOL                (0x0F0)* W% k7 Z% O6 j0 R/ C, b0 E
#define        MMC5_VOL        (0x0F0)9 q* _  n  T& T& h, C
#define        N106_VOL        (0x088)' `# X4 [8 J/ J9 g  l
#define        FME7_VOL        (0x130)
/ o" o9 o4 Z1 f% S0 [3 ]1 Q  [9 c9 w4 m0 F( _4 s
APU::APU( NES* parent )& b. Q, R3 K6 A# w" F1 l
{
) N* a& @3 L& R4 |$ p        exsound_select = 0;$ r" e6 Z4 E/ L3 [3 R9 ?

2 \  y0 i. D! c+ I' F4 P( R        nes = parent;
! T* K* j/ ^% h6 {7 R        internal.SetParent( parent );! l# _, |1 o* \* l, A& p& t

: {, J, A* l! o% b- o* H$ O        last_data = last_diff = 0;' \3 Y; D9 L+ r2 M1 }
6 s+ \1 V; x2 b, u) h/ B
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 R9 e' j/ v% V& n4 c. k) w5 U& \- x: Q) a1 Y
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
! a6 m% h" ~$ b        ZEROMEMORY( &queue, sizeof(queue) );- l5 s+ m7 Z( a& d! Z6 L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );# A/ D. h" u) O7 `1 H4 T

# D7 s, Z9 |* p" P  M0 \: n3 [4 T        for( INT i = 0; i < 16; i++ ) {
6 c; |  F6 i( e1 ]" u                m_bMute = TRUE;# C0 W4 `  E3 R3 {& n9 v
        }
0 `- Y) g8 b9 S- Z# U}% }/ W' }" I1 E* T& D0 R/ I
7 c/ L- O8 g8 F; J! _; h) G0 d
APU::~APU()+ H. _  t( ?2 R* l* v& n
{2 W. u1 M/ K$ ~, P- `7 T
}- z! P# d6 `4 h. R, ~- M

; y8 `4 i3 T* D& e& ?void        APU::SetQueue( INT writetime, WORD addr, BYTE data )8 m* F! b% |( y# T2 ^: u& q
{: g) A) _5 f5 N( ^& I- b
        queue.data[queue.wrptr].time = writetime;2 }% ^8 i# U5 Z) ~
        queue.data[queue.wrptr].addr = addr;
% \% _0 Y3 \" O; {        queue.data[queue.wrptr].data = data;3 W( a+ T. h" f# p4 i) x
        queue.wrptr++;
' D. G: @/ W* C/ D5 z        queue.wrptr&=QUEUE_LENGTH-1;: {: l" D# M8 z$ M! ]8 c" y# {
        if( queue.wrptr == queue.rdptr ) {# b, I* C* i" F5 G
                DEBUGOUT( "queue overflow.\n" );
2 U2 ^# x# ?$ h# {* C! K# P# q        }
% N; A( o1 F$ z* ]& i$ w2 w}
4 X# ?% K; r2 x$ H% ^& u, h* L0 P5 h7 P3 n: s7 ?9 g* h  m5 ^
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: n. a1 C6 T. M{
3 N# ?7 _* P, f; f$ {+ t3 ^0 b; v        if( queue.wrptr == queue.rdptr ) {- }. s! r7 e; R# Q2 V! i
                return        FALSE;
7 d0 f" T& E9 h7 i  ^% A& ~/ v        }
2 x3 }; y/ d& e1 \! _) S" _0 r- Q        if( queue.data[queue.rdptr].time <= writetime ) {4 D& K7 s; Y& z/ e" m
                ret = queue.data[queue.rdptr];
2 ^% m0 D- \* t) M4 g                queue.rdptr++;3 W6 S  B% [$ t' N* f3 `4 W
                queue.rdptr&=QUEUE_LENGTH-1;" b/ V+ t  t' @3 q0 q" I8 ^. g. J
                return        TRUE;5 O4 k8 D* i- A" [. V; x$ `/ D
        }' N& Q3 l5 T( O) [/ @* t5 i. C) m
        return        FALSE;
7 G  \' U3 O; O# e}
0 |( m* A+ L# ^3 ^+ @5 w8 Z+ V" P8 N( G5 N4 e
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; `/ n' a- W) x{0 z, g, g# E4 {  K- [2 C
        exqueue.data[exqueue.wrptr].time = writetime;
3 L, t# E- \; u+ h4 p        exqueue.data[exqueue.wrptr].addr = addr;
& b) O/ D6 u5 U5 E9 l% V0 u% g* T        exqueue.data[exqueue.wrptr].data = data;! r; R$ f) H( P' ]* c
        exqueue.wrptr++;" o3 ]3 U0 N; r9 {
        exqueue.wrptr&=QUEUE_LENGTH-1;
7 Z  U+ k7 O* `. X8 S$ w* i        if( exqueue.wrptr == exqueue.rdptr ) {3 Y! n6 J1 J* X3 _$ z% z9 p+ T
                DEBUGOUT( "exqueue overflow.\n" );! E" ]3 _8 t5 S4 }. U4 `
        }* [( F2 W- R' p! `* @
}
! G4 H6 r' i  y0 y# A) O
5 N8 l8 w4 D! Q2 l( J, |BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
0 R; \2 f6 f' [# U  P{( e, T7 S7 ~* g1 z* s% m
        if( exqueue.wrptr == exqueue.rdptr ) {4 Q6 A7 l. {+ X: V+ g& b0 d% W
                return        FALSE;" i- Y8 W1 X  [4 i+ ^6 o( Y
        }
: v6 X! F  r' a8 R        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 t. B# J; V' n& q: W4 t: g* r                ret = exqueue.data[exqueue.rdptr];
5 K7 Z* |0 u" Y) J: o6 r                exqueue.rdptr++;
* Z1 _) u3 {; a( {, L: d( O& f: `                exqueue.rdptr&=QUEUE_LENGTH-1;
" i/ h* J3 _1 _' ^  j                return        TRUE;/ E1 i, Z. M( S- O! F+ h
        }* D7 [8 M+ ?3 U0 t1 P
        return        FALSE;, \) f6 |4 L, a4 |( q! l
}, U5 \/ ~8 h6 }0 B! [
) x% f* Z& K# n/ p: r
void        APU::QueueClear()9 g- ~; K% o% c" y1 H
{
+ J( b) M, o5 F. z4 o        ZEROMEMORY( &queue, sizeof(queue) );+ \- @2 U$ ?6 m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( B$ ^) r- M4 R4 Y; s$ r: L7 S8 H}$ t3 Q: P- |6 e0 V0 \8 k" J

& h5 p, `0 r  vvoid        APU::QueueFlush()& P4 _  h- d, y9 s6 n& v
{
$ g- e) P/ u3 S& y+ r6 q        while( queue.wrptr != queue.rdptr ) {& M/ s# O% c4 r8 Y
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );8 C/ S( F/ |: y8 I$ u) p
                queue.rdptr++;
) |7 Y# }' [8 E4 i                queue.rdptr&=QUEUE_LENGTH-1;
$ n9 z6 H. N0 d0 b/ _        }7 L' ^5 h0 I4 a( @

' D9 e" X* }2 i2 _# r! u, \        while( exqueue.wrptr != exqueue.rdptr ) {. y1 t8 I3 ~1 c! h
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ `% G0 `; f- ~. y' b6 \+ a1 S                exqueue.rdptr++;( q9 s& S4 P5 M
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 T" k& @; |( J% Z7 e2 f6 B4 v/ T        }! m3 L( {8 L- d+ U/ C: J( T
}
- a/ a+ f% j5 b* [
. A  Z3 q* R, V4 c* c$ l% [0 svoid        APU::SoundSetup()
$ R; Q1 {7 n% m{
' L8 E7 C+ v0 m* @# U. M        FLOAT        fClock = nes->nescfg->CpuClock;
+ N  S! l3 ^+ [- {& `        INT        nRate = (INT)Config.sound.nRate;
. h& z6 P$ z2 W, e9 B        internal.Setup( fClock, nRate );
: [& u1 U7 z+ I9 w- T2 S        vrc6.Setup( fClock, nRate );
$ |% w: Q0 }* w  D: ^8 O9 [        vrc7.Setup( fClock, nRate );
' n0 C, @/ [" J- Z  b        mmc5.Setup( fClock, nRate );( ]7 q" P2 _6 F3 L
        fds.Setup ( fClock, nRate );; N4 z  H, O$ X8 }
        n106.Setup( fClock, nRate );
: c* I* @) J+ K8 v/ q9 Q+ {        fme7.Setup( fClock, nRate );) K7 N/ b, b$ B' v7 L+ b0 _
}0 H. l: B% Q" F$ u* H5 r* u
, x" N. b( C/ I; E5 z
void        APU::Reset()! X# t# M  [9 B2 B  d5 S, ~4 {' y
{( {3 b0 e$ S  Y6 p) m9 ], K, z0 E
        ZEROMEMORY( &queue, sizeof(queue) );8 k8 G% K$ U- h6 |! C# k9 a  ?) P
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, r: ]; I0 F: x) W/ K1 z& v7 l
        elapsed_time = 0;
, F' k- s0 [  O8 z. X
  C6 f8 v# s* S( L  E/ P$ r  W  V        FLOAT        fClock = nes->nescfg->CpuClock;
% E! A% l8 R/ _% a        INT        nRate = (INT)Config.sound.nRate;
1 ?1 _1 d! P2 G8 Z        internal.Reset( fClock, nRate );
2 C7 G# t9 o; \; \( ]9 M1 J( h: q        vrc6.Reset( fClock, nRate );. ]$ s  O5 u" m8 _" C. @5 o5 K9 w1 N! p( a
        vrc7.Reset( fClock, nRate );8 @7 F+ \" b7 [. [/ O" M0 e$ Z1 `
        mmc5.Reset( fClock, nRate );/ M: Q1 e2 V* F/ }7 W8 {& ^
        fds.Reset ( fClock, nRate );( q7 m2 |1 x% Z, p: b' ?3 d
        n106.Reset( fClock, nRate );
: x, ?; r$ t& Y7 C" X1 p5 }        fme7.Reset( fClock, nRate );' V, Y: e0 I8 e2 D9 z6 d$ }& P
  l- `8 M# s9 ]4 C! O8 D( e4 B
        SoundSetup();
$ w' \+ |* a6 [; L( ]$ `2 F& S}& a0 E9 G/ h, Y- G& o
0 h& |, P6 N4 e3 z
void        APU::SelectExSound( BYTE data )
" P  j9 H4 f* f3 ?* `{
$ z$ R9 p6 a( q$ Q* o        exsound_select = data;+ A" F: X( h9 E1 A9 J
}% y& Q+ S% p- X1 @4 \' _$ {( z

) \  U, F" g" d# G1 \BYTE        APU::Read( WORD addr )) J6 `# e% U" _% P5 R
{
. L# o; H  s- T        return        internal.SyncRead( addr );
" `& G2 H2 v2 C# P9 @}
, g9 {3 z  ~: f5 b) `+ f! J
( t% g( {" q- b& ~8 Hvoid        APU::Write( WORD addr, BYTE data )$ E6 [! V; c: H( I$ b5 |
{
, c. A' n) P9 S$ O) j% g& T        // $4018偼VirtuaNES屌桳億乕僩/ r3 g% g8 A2 Q1 k# l4 B" Z. c5 ]
        if( addr >= 0x4000 && addr <= 0x401F ) {- i2 r% J) O' T6 E$ P% k  }5 X: B
                internal.SyncWrite( addr, data );! N# P) b, Z& W" L7 l' g
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
) d4 T2 N5 B5 J8 \) d0 d        }
2 r( s% {( A; t, R1 y}
) k! a. Q; i* h! ~! t' K
8 b7 O; I( }1 a5 N& e+ r- xBYTE        APU::ExRead( WORD addr )! ~9 R$ \: c+ Y" X
{8 F6 v: c9 L0 h" x# X
BYTE        data = 0;
/ o3 F, E( e6 P9 n; Z+ p
8 p2 t9 l* j' A& r        if( exsound_select & 0x10 ) {
' V2 Y/ j4 E, K# f& w( x' E- Q                if( addr == 0x4800 ) {) }% L9 @6 v- c2 e
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, [- z, i" |: j5 S7 |( w- ?                }; W# |8 F- n; b; U8 N5 ~
        }
9 X; x* h# k, r, y, x$ @        if( exsound_select & 0x04 ) {) S  w, r  S! a6 H
                if( addr >= 0x4040 && addr < 0x4100 ) {  p- U7 b4 E- {3 N' O
                        data = fds.SyncRead( addr );; S1 f6 ?1 ~  F) o& c. `
                }# o2 O0 E; O# Z  q9 B, l) x
        }
5 w) ~0 E5 q  C4 M" y0 y* s9 t        if( exsound_select & 0x08 ) {, u7 d' u+ [: A! L* y8 i
                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 n- s- `8 h+ \0 J5 u                        data = mmc5.SyncRead( addr );
; L" I$ e' f- y                }& d8 \  v2 z9 \5 k- y+ v
        }
  V+ M0 C* z. u; i
! F8 N4 t2 u1 ~( E" \8 k        return        data;
4 c1 R7 D" T$ x3 m6 C$ ]}; R" b4 p- s6 {. `2 o- x! Y
. u9 M4 `* ^, t7 \. b
void        APU::ExWrite( WORD addr, BYTE data )& j* y% m# x' M/ g
{
8 G# E, @/ g- K, `6 s$ j1 d        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
  X. I: D" L( Y2 d% c% y: k
- F5 ^( y% T& y- W$ @        if( exsound_select & 0x04 ) {
' d, d/ K# H2 J% f& |( l7 \' @) o* F                if( addr >= 0x4040 && addr < 0x4100 ) {+ U+ L$ v4 l/ V4 g) c7 f
                        fds.SyncWrite( addr, data );
# f4 T+ O- x& _" p                }
% B! x3 y( ~: R3 ~1 f        }1 l: }) _& b7 W; V0 X
, }2 F: o- @7 N$ w, w2 @5 e+ _' E8 f
        if( exsound_select & 0x08 ) {+ J! R+ h( P7 T; k
                if( addr >= 0x5000 && addr <= 0x5015 ) {% W/ h6 Q) ^4 i% m$ o, e) ~, g
                        mmc5.SyncWrite( addr, data );9 u) Z! J* ]0 C: c
                }
* d; |4 }" l/ b        }8 d3 {$ l; g% `
}
. Y- d8 n4 Q0 z8 {3 l/ n6 K
+ j) H: v2 L* h( G* E8 R) t8 cvoid        APU::Sync()- a3 E  g/ j( K
{0 o5 z) D; c; w# w6 L/ [
}
" S( E* w- Z0 o8 p" _9 }: q! |" ]% p
  D/ F$ k/ `# B' c) I% z9 lvoid        APU::SyncDPCM( INT cycles )
+ L/ Z8 v# B) B. b# `9 \{( I0 x! [5 `& `) \7 D. \# `
        internal.Sync( cycles );
% D* a4 D: S: \/ O- N$ V, b. u. X
- f' r4 q2 Y  D7 y# [        if( exsound_select & 0x04 ) {% H& W% K. E  m2 s0 k
                fds.Sync( cycles );
6 M2 g- g5 ]/ o0 b        }, t7 l$ w6 I/ k, u
        if( exsound_select & 0x08 ) {, Q4 q, o) Q, P3 q
                mmc5.Sync( cycles );
6 n* Z9 L& q  ^$ U, ^, ]. J' z        }7 q) W0 f2 x" Y, @
}5 {) n8 I( C& t1 Z8 }" k0 a6 o& M

9 w" g+ V+ Y1 ]  Gvoid        APU::WriteProcess( WORD addr, BYTE data )! d4 g: Y% ]; D/ }
{: @; t4 o# c2 Q+ R3 g; Y( Q. r
        // $4018偼VirtuaNES屌桳億乕僩
8 _* p/ o' R# Y8 d% y' {: x        if( addr >= 0x4000 && addr <= 0x401F ) {8 ^6 _! Y$ [: M8 n' J$ u
                internal.Write( addr, data );5 K% w% j# H' `
        }
, D2 C, M  A/ L5 M- [/ G$ L}
  k/ {3 W) r6 {$ Z! e0 Y3 w
5 S  g" k% p' _5 m) D* Avoid        APU::WriteExProcess( WORD addr, BYTE data )0 e6 a. B/ r' Y2 H- R
{
7 C: Z. A& @, W: K8 U" ?9 Q        if( exsound_select & 0x01 ) {
2 K0 }% l2 h! ?% T                vrc6.Write( addr, data );7 |5 ^) Z% v' W$ g0 W
        }
- q+ ]" U: m$ r; ?        if( exsound_select & 0x02 ) {
2 l1 Y; k  G+ k                vrc7.Write( addr, data );9 j7 }, O6 Y1 j' `
        }) \2 T, \9 ~4 L- H! A
        if( exsound_select & 0x04 ) {
4 S% C% u& k5 g8 E* j                fds.Write( addr, data );
; v5 C6 C# c' o6 D3 s+ Z        }* f4 G0 Y: a/ k' z( k4 h
        if( exsound_select & 0x08 ) {
4 m  |( n/ R$ b1 T* j0 k1 o9 s, J                mmc5.Write( addr, data );
$ k8 }* ?( S* |! j$ z" W3 A' M        }2 `; F- ~' }! x% t5 U
        if( exsound_select & 0x10 ) {
$ i  e; L% L2 v3 t" S# B$ X! ?                if( addr == 0x0000 ) {
+ l6 i# A/ x4 `/ Q3 }                        BYTE        dummy = n106.Read( addr );3 b3 ^0 p% M& O. m. Q; l
                } else {
% f6 K# y& D0 \, @# Y. P                        n106.Write( addr, data );* j! \6 z- \$ M( n! J
                }
# C# A% M; p( j4 v, x        }
; ?% V' O) A4 K' E  Y        if( exsound_select & 0x20 ) {4 I7 s3 b" Y$ V
                fme7.Write( addr, data );& z9 q; S/ t2 q1 E7 r3 v
        }
1 D# g+ d0 M6 t$ _& h' B6 P* ^# |}5 H) c* e% I+ j+ ?' A
/ v% C0 f" C& @3 E. k3 O, g) F1 ~
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
1 j% l2 {6 G# b  l( e{0 Z' ?9 t' {8 I' z5 t. U. P! M
INT        nBits = Config.sound.nBits;# @: D5 ~4 U( A5 V8 A- f
DWORD        dwLength = dwSize / (nBits/8);9 [/ ?! s& s$ B& ~% j) j. l" h, D& r
INT        output;( Q& [6 k3 s' R* a  }6 i
QUEUEDATA q;
, x7 A& q1 g4 L1 hDWORD        writetime;
& P& [1 p5 x6 @" s" \7 T1 w' V
. l  e  N5 s7 _: q% \: E. Q+ K% DLPSHORT        pSoundBuf = m_SoundBuffer;) L9 r6 F4 b' q% E" ]* w
INT        nCcount = 0;
% `- C3 c; X% A2 x
. @3 C; B7 {8 S- V5 a6 u4 GINT        nFilterType = Config.sound.nFilterType;
1 r$ r- d7 e& {" b" P8 B5 b) h" D; p6 E8 J
        if( !Config.sound.bEnable ) {
# h& ~+ C+ t. p9 t- ?* R" c: {                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );, m6 u: ^% A9 X4 N2 I2 R
                return;
; G" C  N1 b, _& u( A) a; s' u        }
. r  n% a% L  [. J' o8 A' R5 d) e& H; J
        // Volume setup
0 X% m" g: J" G' ?+ P* h8 Q        //  0:Master, C/ s( {5 _! T+ {
        //  1:Rectangle 1, v8 ?: K; Z: K. X
        //  2:Rectangle 2" _/ ~9 T3 \7 [! L6 i* i4 [
        //  3:Triangle+ E( l* o& c4 a0 j8 d
        //  4:Noise+ G0 H/ h' T+ f: b
        //  5:DPCM& d+ z9 Z$ h) _( W  V
        //  6:VRC6. R# R8 V: H& X2 B+ J* {$ K
        //  7:VRC7
* W1 Y1 {* ]+ l% X' ]        //  8:FDS
( ~% }0 r3 i* [% R6 m6 ]        //  9:MMC5, ]7 Y- k& Z) ^7 W
        // 10:N106+ `' }6 k/ F9 Z4 o! E" S
        // 11:FME7
- T1 B! \/ s" ]        INT        vol[24];
7 @" A+ T: p: @8 v! x' s' X7 \        BOOL*        bMute = m_bMute;: q/ h0 J5 q. m- G# K" H9 _9 n
        SHORT*        nVolume = Config.sound.nVolume;" |: [! v  ]! i

4 V. _. f7 @4 @8 n        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' _1 X8 ~, S) h
$ `" L0 S2 F& b        // Internal0 p5 A6 a$ e' v* }' j1 f- h
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;) Q# k. k" q* a: C8 ]2 w
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
% O& U2 q. m1 y+ A        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 V( n- _0 N) Z( S3 ^# m
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 g( t/ h4 [9 V# M6 v! ~
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' i) d* l( T, ^/ {  |! K2 V6 q
        // VRC6
" d4 Z7 \* H" r0 \2 Z3 R5 ?+ C        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ P- W! c% ?' V# Z$ n0 w. V
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 D9 a: [/ G7 O/ T1 U4 r7 {* j
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; w( z, Q' e! e( T: W( A0 ?. U; r- T& ]3 z; [! P. \  v, G/ X
        // VRC76 \2 Y$ J8 z; V; L
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;! ?/ h8 _" t1 y, i) j1 Q
. X2 r  h2 [) A
        // FDS
) V8 V' Q) |4 \( i6 K: e        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;: n! b) l: n* p, C
) p' A, c( k' p" F' F& d2 a8 A
        // MMC5
  U& V" v2 ^, C6 Z6 U/ S        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ U5 v- s4 S  H# w        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( ^' b1 ^0 [2 Y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) e7 _& K; f5 P  z- a3 B, |+ |) f
        // N106
# S( p, H& \, y$ m' W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- s: {" R+ E/ b' j; h2 m        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! {- V7 C: P' k        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* r: n% |. ~( d0 A2 [; y        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  X0 Y' [+ k' c+ \
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; o/ ^4 G& B8 `0 q$ R3 [
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( w- M/ w* h8 g7 Q: l
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) f6 {9 ]" K2 G
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# T2 P; r/ a0 p! F! H1 `+ J  K: {- B
        // FME7
5 i9 R, C0 M7 h8 X        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* _$ m7 L( Y7 u& M. g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! C7 j& V; r: d& U8 d5 e- ?
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 @5 w& ]% {3 |3 O- @
2 e$ i! ]! C: f2 Y7 k1 W1 Q//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 o$ Q' t* {& I3 |( ?1 ^
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 V* e9 N' W/ h+ D9 d1 J
6 ?  |% i7 M- z1 v        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟2 z% Y# ]- j: T; W
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {; |/ [( @4 g: k
                QueueFlush();
5 b6 \& [* H  y) ]        }# N& l3 F# b- }! o, r
$ E! p& C8 k7 i* O; S
        while( dwLength-- ) {
! b2 J& a3 k: s4 J# _: r( R                writetime = (DWORD)elapsed_time;
+ E+ s" w  Q5 V: _$ E, d2 U
- r* L5 g+ G8 Q8 Y) i- D$ c3 V& z                while( GetQueue( writetime, q ) ) {+ ^. d3 H9 O  L6 o
                        WriteProcess( q.addr, q.data );5 V* T; q* Q/ g1 Y
                }+ n' Z% X5 _: S1 y% i) t( }
. ^% p7 q, [. b: j4 ~3 F) x
                while( GetExQueue( writetime, q ) ) {2 R* t4 z" \$ e9 m8 Z2 A
                        WriteExProcess( q.addr, q.data );9 j# H) \8 r) b$ X$ x5 W
                }
7 ?0 ?' V2 o6 ~" m! z1 R3 @: F' u3 G9 y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 W0 e5 J3 o- ]# u/ g. ^                output = 0;
% B2 h7 u0 q* f8 i# w# J9 ?- s! v                output += internal.Process( 0 )*vol[0];( `' E1 S' R* c& ~
                output += internal.Process( 1 )*vol[1];
1 ?9 {6 R+ X# w                output += internal.Process( 2 )*vol[2];
. N6 r+ r: w! f9 E: J5 }& {                output += internal.Process( 3 )*vol[3];
2 i$ c8 o, M; U- s1 A! C: S                output += internal.Process( 4 )*vol[4];
/ ^" D5 u4 u+ }. H$ H) R* `7 _6 [3 ]  p9 L9 V
                if( exsound_select & 0x01 ) {
) Z! ?' |. G( Y5 n% l                        output += vrc6.Process( 0 )*vol[5];6 l3 |9 Q9 v9 W' b, m) v. S
                        output += vrc6.Process( 1 )*vol[6];
; O& X5 r& B. W. b, g% g0 V                        output += vrc6.Process( 2 )*vol[7];
, ^  e: l7 @6 B4 N  P% B0 A7 n                }/ |% `! @0 n# t3 g! A& A% i3 G
                if( exsound_select & 0x02 ) {* M6 ~9 W8 l0 ?7 r# {" q
                        output += vrc7.Process( 0 )*vol[8];7 d7 e  z1 P" i9 N% J6 ^
                }1 d+ B# N9 b7 t! f
                if( exsound_select & 0x04 ) {7 R3 |5 J2 h2 J: g
                        output += fds.Process( 0 )*vol[9];
8 S1 W0 t/ z- v  b$ V7 K5 B                }
( t7 D* ?9 n" C/ [  O- P                if( exsound_select & 0x08 ) {
- a3 y! I. j! `8 e/ N: A                        output += mmc5.Process( 0 )*vol[10];9 }, m7 |& o$ M# q# n) L
                        output += mmc5.Process( 1 )*vol[11];8 `2 L0 r* s+ W. L3 V
                        output += mmc5.Process( 2 )*vol[12];
/ V& X, }' c" B. A* f$ q! b                }
3 j5 a$ ?' V+ ^7 K                if( exsound_select & 0x10 ) {% z' Q# z0 [9 E2 B4 ~6 L
                        output += n106.Process( 0 )*vol[13];. v+ y3 O4 m: y7 a3 X$ w/ p! O( R
                        output += n106.Process( 1 )*vol[14];7 J2 p- r3 C/ M. B% o, Z
                        output += n106.Process( 2 )*vol[15];* W  h: H! P7 u3 v& r
                        output += n106.Process( 3 )*vol[16];
. m) J9 O: }# Z                        output += n106.Process( 4 )*vol[17];
+ j; d8 R) g  j4 v0 \" D                        output += n106.Process( 5 )*vol[18];, J( j0 T# L! V
                        output += n106.Process( 6 )*vol[19];- ~+ _% m# b0 G
                        output += n106.Process( 7 )*vol[20];
3 a7 M2 X8 B! x8 e                }
+ ]" g* H- K# ]3 [1 G                if( exsound_select & 0x20 ) {5 [/ T8 c$ a, Z: _; [; ?: u
                        fme7.Process( 3 );        // Envelope & Noise' w' R4 Z: }4 W9 }
                        output += fme7.Process( 0 )*vol[21];
4 T. p: N% q# }# z8 A                        output += fme7.Process( 1 )*vol[22];: w$ u9 I8 J! f: X
                        output += fme7.Process( 2 )*vol[23];9 l$ i1 h+ L% f; F3 W* n0 o( U
                }- P) L6 H" b4 [" a  t
- X6 Q# A" O+ E3 Q/ m  J* W
                output >>= 8;: F0 \6 D6 |; a" t1 H
5 B2 M2 I- t0 F' q9 O* Z
                if( nFilterType == 1 ) {
/ \9 R1 z9 s: L0 @, _3 n7 ~                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), T, h& R+ ~" i. m2 W- O
                        output = (lowpass_filter[0]+output)/2;
- z7 B/ s1 C3 Y- e2 Y4 R3 _7 d, G                        lowpass_filter[0] = output;
/ T* g, C* A! Y                } else if( nFilterType == 2 ) {
; h4 ]+ x4 `- K6 Y: B                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)# U, x6 m- G( u! I  w" s* g
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
, {' `& T/ z8 Z& V1 G                        lowpass_filter[1] = lowpass_filter[0];
/ n3 b2 J1 Y9 m9 [, k( `  {                        lowpass_filter[0] = output;
8 @  ?$ h8 d  I% Y. v                } else if( nFilterType == 3 ) {4 u5 t# T& N5 u: `, }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 D/ t, n# e$ _- Y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" Q- x# `- X/ S; p. K# o( C                        lowpass_filter[2] = lowpass_filter[1];% U" ?$ Z! {/ H. w, X, Z
                        lowpass_filter[1] = lowpass_filter[0];
' d9 s% b: i* o- c' E( {8 E                        lowpass_filter[0] = output;
5 g/ l& {0 q7 c3 j9 Q" r- Y8 V                } else if( nFilterType == 4 ) {7 I- `* o" f2 b0 L! |; z- N9 U
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* x5 o) y# ]; L8 h* w/ _  O                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;7 j) y/ R& X* Z5 ?$ \2 b# K+ Z0 c
                        lowpass_filter[1] = lowpass_filter[0];
, l/ ^) L1 W* N% F4 G0 c) o2 E# i9 ~# w                        lowpass_filter[0] = output;
& S5 S9 I+ n$ N7 C  C' ^' g0 F                }- j3 x* Q6 Z% E. D- [9 @
7 L8 Q# M6 t$ y1 F* h, N
#if        00 U9 d; ~  B7 K1 r
                // DC惉暘偺僇僢僩. E& J) ]" k$ ^+ q8 {$ z, g
                {
/ }" d+ k( B$ g" [                static double ave = 0.0, max=0.0, min=0.0;
! l- o6 @* ~* q                double delta;7 u9 Z3 u# b  i, _8 b- V4 E
                delta = (max-min)/32768.0;& n4 f" ^5 r7 H: H" ?
                max -= delta;! e& c" Z0 X0 A1 g8 Y. ~- o9 J5 U
                min += delta;7 }- ~; D. O+ d& U' e  w
                if( output > max ) max = output;/ j: \, {2 n. x8 j
                if( output < min ) min = output;
+ s5 j1 _; ?4 P8 M1 U. @4 z                ave -= ave/1024.0;" L. P) m  J* k8 O
                ave += (max+min)/2048.0;
% J7 L0 F( [* I                output -= (INT)ave;" X) s  P5 A& y) N/ g1 X5 A
                }
" d- G8 Z8 E3 A% @" _3 q#endif
% Z' B5 v) N# B& J' v#if        1! |# [* `9 g! n: w3 @
                // DC惉暘偺僇僢僩(HPF TEST)9 m2 d5 Y. G* y5 \! F( Y# T
                {7 l3 E5 w& q# b" d, b' B  I
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);; [  K+ O. D8 K5 |0 y
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) k# m9 `# d& k. N. `0 j                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# U* P$ x: f  J  [  _2 O" _6 q                static        double        tmp = 0.0;
4 ^9 C/ `1 d- `7 Z                double        in, out;- ?- C% C0 ~/ o4 Q: L

! Y  V# D' `0 `. n8 c8 {! t                in = (double)output;! C( s$ u# N, G7 c) y6 R
                out = (in - tmp);0 V. L% c) `5 u8 }
                tmp = tmp + cutoff * out;) P0 d7 z2 V, d# Y: V! n2 I' K

% G/ c9 ]' v1 [                output = (INT)out;
0 h# M  {* K& [8 b& b3 X                }; n8 M( T$ u- q) ]+ o
#endif
) f6 l+ `' k0 k7 a! a/ l1 \#if        0
/ R5 \; o/ w3 K# r+ x; _' H                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
/ k! X8 k8 T* f4 a( N" y) U! w( V1 k                {. f. [1 Y9 L1 R- r- Y* m" k9 q( q
                INT        diff = abs(output-last_data);
! N+ ^: }3 ^6 g6 _* c                if( diff > 0x4000 ) {, n7 H# r" I, }0 l
                        output /= 4;' b/ |' j2 |5 T; {' q6 y
                } else 0 i8 C" X- Y4 j  P. u
                if( diff > 0x3000 ) {! E% w0 l, d3 M; g% O! ]
                        output /= 3;" W8 s0 J4 t: w
                } else
0 i2 Z7 I; A7 d! _2 J5 y9 z                if( diff > 0x2000 ) {' O( U. _; m- b/ w0 W4 n  l
                        output /= 2;) i) _0 T( T8 g9 q+ ]! D' `+ l# @
                }
" X% @, s! N# P( n7 f/ X                last_data = output;
# Z7 R' G& j6 ?5 }. c/ [; n8 h                }& v: |# y; n$ v3 d
#endif
+ }" H; a( @, M! S" n                // Limit8 G% w  y* t, s/ R( A$ x
                if( output > 0x7FFF ) {2 r; g7 T4 \$ U/ C
                        output = 0x7FFF;1 P5 I% ^, {. y+ j# D1 K, G, l
                } else if( output < -0x8000 ) {: R8 w: F; r$ N6 V. c4 _# C
                        output = -0x8000;
' A: n" y6 K1 [: y$ y# o- i/ }) v                }
( m1 Y# G$ ?% E+ p) r( m4 Y' }9 A9 D4 F, |) ]; ^
                if( nBits != 8 ) {
' \/ Y  `- n  I& B1 a                        *(SHORT*)lpBuffer = (SHORT)output;9 }: ?* o8 x# g2 s2 w# a
                        lpBuffer += sizeof(SHORT);' H2 I( [9 H% e: F% j7 Q. X( ]& S
                } else {2 Y$ R% ^  ?7 l: J
                        *lpBuffer++ = (output>>8)^0x80;
; @: N7 f; e& g& V. X. P, w3 I                }
" O5 b4 k% y/ N$ j6 ^. Y' i4 f) Z! y* g
                if( nCcount < 0x0100 )( }& z/ r" j" i8 o
                        pSoundBuf[nCcount++] = (SHORT)output;! w+ L9 `( N/ D- f8 D

( Y9 n9 h2 O  I//                elapsedtime += cycle_rate;3 e2 @4 E: b3 x) J9 ]) ]
                elapsed_time += cycle_rate;
- Z# }7 B& N; Q& R; g6 D% A3 v        }$ j3 T* r4 T7 O9 ], A% X

# L; \. i6 k' ?) [5 c# m- [#if        16 |& l3 }$ i6 o, q( l
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {/ t& r0 i' p) S1 P# _) S
                elapsed_time = nes->cpu->GetTotalCycles();9 C0 [/ D1 a/ ]% y
        }
" ~1 `8 z1 X- ]5 q        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
4 H7 j) B" f' q" ^, R                elapsed_time = nes->cpu->GetTotalCycles();
' W/ C" J/ Y/ C0 q2 S        }" J9 }2 U* V6 B, |
#else+ A( P  Z: G2 v4 c# }# s
        elapsed_time = nes->cpu->GetTotalCycles();
; J; Z5 K0 j5 P5 l# p  L9 k1 e#endif' c3 z8 A3 P9 q8 Q8 M$ z
}
  H- Y% g2 b; y5 n
, h# T# D  U' g! I& F// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)) d: u1 Q- ]* U# C: j2 @* M" X3 m
INT        APU::GetChannelFrequency( INT no )5 U1 G4 B. q+ v0 d4 w
{. t% ^7 w$ B+ b
        if( !m_bMute[0] )
  d2 J- O7 t5 L. z  X                return        0;
/ Z- W( p" o( h. @8 z, ^5 O$ n0 z" Y: t# S4 C) S7 t6 ~6 t2 A
        // Internal
4 x; x8 I5 n5 W5 n        if( no < 5 ) {+ I6 B! G& d0 O4 o, M! S
                return        m_bMute[no+1]?internal.GetFreq( no ):0;- B; a/ o/ f, n3 {  ]2 [
        }5 h" c+ W- w/ S* o' |* G% W& k
        // VRC6
0 u; P) T5 p& i" i0 |& F/ L) e        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
: \, G% o  b* b0 A( G                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;( Y6 U; C1 l9 M& N2 |
        }# N4 M' S" G  S
        // FDS$ k7 o; x0 R9 _; m; y2 f
        if( (exsound_select & 0x04) && no == 0x300 ) {* l5 M) m4 L/ B1 a' Z" i- g5 P
                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 _' i' B: \$ J8 V9 ]8 i2 G1 ~
        }
$ q8 Z' I0 f- D# W1 J& C        // MMC53 T1 F: c% R5 Q+ k2 c/ q4 f% W
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
8 U1 M/ {- h; O. ^& s9 S  E  O                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 y7 s  u: E. W' E! B
        }
, D- h* w6 v6 F# t        // N106$ R" ~' ]' o4 h
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  {2 F) v) C" W3 G8 N7 Y  \# v
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
8 ~) F) t; o) |  E* {        }' O2 h" f4 o5 g2 {. @
        // FME7
* x: q' q1 u# h4 `  z        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
% H  a1 `; I2 [0 W' \                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;% v0 B7 [* K$ R; B
        }
3 R, {" K, _) Q  @7 c5 X+ P        // VRC72 I# Y1 k/ R$ b
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {1 ^8 A1 u; i& V
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 u/ K0 }' R+ M, d        }, z7 z( U$ o: M
        return        0;8 }$ k4 ]7 k5 ^
}
& C1 @6 U, k* d; d) ?+ c' g( X3 z, z7 I& q7 T- g* W
// State Save/Load
0 ~0 V5 b$ |7 avoid        APU::SaveState( LPBYTE p )
7 N1 r7 I$ x6 Q  m{% R8 }" O6 u. E) x0 }" c3 m
#ifdef        _DEBUG2 m9 S# H5 Y/ h% ^# U$ K/ Y
LPBYTE        pold = p;7 j0 M/ P4 E/ e  m
#endif2 ]& Q& n& m6 K: @) F' w

/ _2 q: o5 _) p: Y0 t3 U' Y: T        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& s: O" G& I9 M0 L" W        QueueFlush();3 v) C# X* K; K) ~9 q
: C0 n6 @) E7 z" O
        internal.SaveState( p );. v0 s5 ^) }; J3 M8 l. o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' {+ W& y$ P7 t& T; H- W) [$ H
2 H$ M' P. [( _, ~& _0 I) U        // VRC6
3 f, z- i; L0 W6 J- _5 R        if( exsound_select & 0x01 ) {7 S& L$ u6 N# a- U# j
                vrc6.SaveState( p );+ N' n7 X% l  O& A! D6 b- w
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! G; }% v# D+ v2 J+ y        }
: g) K6 O. a/ u0 ^$ m# h        // VRC7 (not support)
: x1 C5 _  t4 G- j+ o        if( exsound_select & 0x02 ) {( o3 m% f6 n: l
                vrc7.SaveState( p );* Y4 L1 D9 B& f# A* y7 q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 Q, o5 ?% a. e  b$ V8 V: ^$ k        }7 k: J' S% |2 Q/ E3 A
        // FDS( ~; f$ G8 _( j4 {
        if( exsound_select & 0x04 ) {) H- K1 b/ X% t$ T3 j  Q
                fds.SaveState( p );- ]+ ?4 w, I3 n5 N+ O9 P& U/ E
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, v0 h' I- B" S8 u        }5 ?$ h1 x% `9 T% I" a& c
        // MMC5
8 C7 N, l) F+ k7 |6 s        if( exsound_select & 0x08 ) {
" P6 B. G# l' t% f, j                mmc5.SaveState( p );
$ y: N+ n6 e/ L6 v5 A0 E5 a                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
3 N) U- O# l2 N& [9 @        }3 Z, Z8 l& z9 c" h
        // N106/ i6 r. u+ b# Q4 y, T( W
        if( exsound_select & 0x10 ) {9 g/ Z3 j* q0 R' _
                n106.SaveState( p );4 B/ h" l- m, Q) @8 p
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 C3 u  _/ @/ Z' G5 o
        }7 ~+ @! ]2 x) K: h1 m
        // FME7
, `4 a" z: O' [        if( exsound_select & 0x20 ) {6 B" R8 ], t  b" T
                fme7.SaveState( p );
% a1 U0 ^. }1 W& Z" L) f4 t5 r                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; K1 B/ j8 Z+ l        }
3 O, J7 p" I/ I& h) N; {( a+ }3 L3 p  }% m$ u4 U1 V
#ifdef        _DEBUG
7 R; s3 z& r! G1 I' v2 g- IDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );( F2 s: I  x7 D  u* {/ d
#endif
5 n; P9 R; U3 @}
" @4 `5 ?9 }: ^% a' ~
* {* J3 }' h; V  ~: w7 Pvoid        APU::LoadState( LPBYTE p )/ A8 Q- P( V5 ~' X/ _" e5 v) E
{+ X# \# L: J' X% j. ~9 E
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 ]) ^0 W3 ~( U8 a4 o        QueueClear();6 J5 Y3 ~2 S( Q- \# i4 U" v% i* e2 Q
- o+ m) s) n* T3 `
        internal.LoadState( p );# X+ m- E+ V+ o3 f' ?
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding/ x: s% T9 V( q: ^4 b

6 ?: H& ]/ S+ m& R5 r+ C7 K4 {        // VRC6
4 K* |4 [% l3 G9 Y$ F" t7 _        if( exsound_select & 0x01 ) {
* I2 j4 V# ~$ K                vrc6.LoadState( p );. J9 x: `1 |0 U& @# A( X* ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
6 ^* s. F' F' Z0 {* {        }) R2 }) J4 A# {4 j
        // VRC7 (not support)
7 l$ D: T; C7 C- v+ g        if( exsound_select & 0x02 ) {
+ G; `( f- z  q/ ~                vrc7.LoadState( p );+ `8 p: z/ |- o- c5 f* }0 c! E& t
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; H* t) E- ~0 D  b  i: A8 U* H        }! J4 ~0 J) i) {8 J9 Z+ s
        // FDS
7 m" i; Z/ P* ]; ?' r0 Z" M        if( exsound_select & 0x04 ) {
7 t1 Q5 v8 _; T. D* r                fds.LoadState( p );
5 y* u  t1 K/ g) Z0 f7 O( B$ i# [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* b% m3 P% h/ s" Q: v: p
        }
* S" Q' ~; }2 O        // MMC5
; P2 `4 {# V: |6 M* g, V        if( exsound_select & 0x08 ) {
  z  P6 ~& R0 G; w% z: e7 q                mmc5.LoadState( p );, a" L  n& W; l6 K& D, O6 e7 v
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 R8 X# r5 _" @; p& }" [$ W! [        }( `0 f1 I0 E0 Q: t6 U2 r/ N
        // N106
& T2 u! L& k1 ]$ M, T" I        if( exsound_select & 0x10 ) {" D- t8 i, D9 Y* U$ Z1 w, Q
                n106.LoadState( p );8 p6 ~7 e; f3 T3 R! q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% a! b$ v! z3 b/ u9 d        }
. ^# |4 u1 P! g# D        // FME7
1 _& B1 ]3 ^, ~# s3 l& D        if( exsound_select & 0x20 ) {
8 Z: E  ?6 I$ E, F1 f; B# {# z                fme7.LoadState( p );6 R" G4 a4 `2 `* x% h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 t& Q8 _) H/ r* W3 p2 a
        }
3 Y  Z! j9 m! T# _1 Z}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ I+ R7 ^5 K6 d  F- Q0 A可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 A( r# l) o3 ~1 k! S
感激不尽~~

5 d( J2 k/ j3 U6 l4 w3 |# R恩 我對模擬器不是很有研究,
$ Y* {  p; p5 U! Q. ?0 c雖然要了解源碼內容,可能不是很困難,
8 u! F4 H* j. a不過還是要花時間,個人目前蠻忙碌的。: l8 H: M, _6 p5 _9 B0 L9 G

1 p+ I2 d5 V7 s1 ^6 F給你一個朋友的MSN,你可以跟他討論看看,
0 Y6 G+ i5 }6 ~他本身是程式設計師,也對FC模擬器很有興趣。
* }7 C: F  A5 @! d% V* l) v! p9 K
5 I* a8 I6 X% i0 B  [! |MSN我就PM到你的信箱了。
( ^$ t9 K' `% ]
2 ]- |: v' E7 o8 |  o, T0 M希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 6 G3 t2 N2 P/ \2 G. I
呵…… 谢过团长大人~~

: b3 `7 p& p/ ~7 ^2 `4 g0 s4 j) R8 Y$ k& f
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# [0 K# Q$ o0 M团长的朋友都是神,那团长就是神的boss。
0 A1 I+ ?1 B( b8 V! \2 v0 Y* C
哈 不敢當,我只是個平凡人,
1 k# \- S) a$ R; @- ^2 u7 c要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# O. y1 V0 s. c) W$ R
ZYH
2 T5 }3 B9 a' }* A* Y4 MQQ:414734306
4 B$ D( j5 q: ?Mail:zyh-01@126.com- i  K* g  S7 k1 }0 s* q
0 q5 p. y. G& t( ]5 H
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) w) d( }& D& ]' b1 x8 D, w6 D再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ }0 a3 ?2 v5 l
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-5 22:31 , Processed in 1.090820 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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