EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 T" O4 e* s4 `8 @1 Q% |
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 I* }5 t8 f# H: v+ L* a$ `, v
这里有相应的模拟器源码,就当送给大侠了~~
( F& G) x+ {9 r& h4 mhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 & f& g9 l, J6 ^. c& [) U
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, o: z! i4 F9 }$ X
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 X/ C, z9 a) J5 z这里有相应的模拟器源码,就当送给大侠 ...

/ u( M3 V: V+ T# K1 J$ {聲音部分(Audoi Process Unit = APU):( R3 x7 A  K9 |6 G; u7 d: r
.\NES\APU.cpp
% `! c( A0 g& m9 H5 O) K.\NES\APU.h/ a, g3 T4 b, d9 f- x8 N

+ B. h" U8 k. ], U% U9 L. `* B. N. R3 ]& d& ^) d- T) m
影像處理部份(Picture Processing Unit = PPU):3 n, o' P# T: e* T4 B. X1 [* h
.\NES\PPU.cpp
% P7 I) e' s$ a' w2 K, o& l.\NES\PPU.h
- d( H. J; }% K1 u- p# h3 M; t+ a5 i, t
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  @& J+ k9 E7 U# D" Q( o# ]# s
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
9 a- W7 b7 U* ?! B% c6 t/////////////////////////////////////////////////////////////////////////// Q. Y' t% X$ L, W6 ~6 b
//                                                                      //1 ^+ [$ ?& P( \" l0 I: W
//      NES APU core                                                    //. [3 X5 M% Q4 P  i; _9 @8 A
//                                                           Norix      //
( U; @5 l7 Q8 m5 }, V* M% ?& Z//                                               written     2002/06/27 //5 h/ F& @! u  }; g8 N" g4 ]! c
//                                               last modify ----/--/-- //
8 ^5 A2 t5 l& f. o//////////////////////////////////////////////////////////////////////////
2 x( L* t( I+ C: Y. I6 y#include "DebugOut.h"
- R( b6 w/ E0 _0 \9 M  z+ B- R#include "App.h"1 _) P9 d% l6 {7 Q
#include "Config.h"6 h7 w# N( ^3 c; `1 S& {
( v- F9 Z' u" m7 G2 F1 H
#include "nes.h"1 r* J2 R% ?& h% d* }+ N$ _( Z0 k
#include "mmu.h"- Y7 o( t0 h5 S& D; U: z
#include "cpu.h"
. Q+ [2 w" U3 [  \5 g! M  I7 t7 `#include "ppu.h"# O7 d$ M8 B" I9 _
#include "rom.h"
$ Y- X& ?: ?% Z% C#include "apu.h"
. M( e2 o+ J, T: p# U; }; w  `( ^; p
3 A* [8 E6 n# ]7 i, I4 g  `6 h// Volume adjust
# g0 E# I* J) Y( d// Internal sounds7 e8 K  u2 T) X# l6 K
#define        RECTANGLE_VOL        (0x0F0)9 `6 r. H5 g/ @) A9 ~4 G: P, [
#define        TRIANGLE_VOL        (0x130)
5 a5 G8 M4 A: }/ w#define        NOISE_VOL        (0x0C0)
7 ^; `6 O' S3 K: B7 b#define        DPCM_VOL        (0x0F0)9 Z% y  @/ W3 D& q* d) l7 s
// Extra sounds; [. M4 P: ?) U! v7 C+ O% B1 |# }
#define        VRC6_VOL        (0x0F0)
5 P; j. T* N% Z$ ?: d8 n#define        VRC7_VOL        (0x130)
% |; T0 b0 \$ k9 h8 f* ?#define        FDS_VOL                (0x0F0)* U& F+ E) U+ R; l: p! m  C
#define        MMC5_VOL        (0x0F0)
/ H3 ~, [5 H/ w  O9 m+ P$ H#define        N106_VOL        (0x088)
7 t1 H  z# F' I#define        FME7_VOL        (0x130)
( E& t- x% ^. ^! H
+ @2 `& D1 L1 Y; P5 eAPU::APU( NES* parent )$ t$ U7 S+ s! @' b' a8 _: u7 r+ L
{
! @, k/ t: q. r) b& }0 u. w        exsound_select = 0;; c% D- f2 S  n2 Q8 h7 q& b
3 p; _2 N3 C' c; n5 `* O- u
        nes = parent;
; x% G* y1 h' B% W7 w        internal.SetParent( parent );
& `* [+ Z9 M- w7 _: O6 E- y7 i' B0 j! l# b" A" s0 R; @
        last_data = last_diff = 0;
4 ^5 G! [  }! V! x, j5 v" C0 ^) ~( H: a' ]
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
8 y) S# q% q7 K$ j8 ]5 f: z  ?7 b, K  n
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: U6 C/ K- _  E1 B4 x. {0 c        ZEROMEMORY( &queue, sizeof(queue) );
1 M! g: r6 M8 {1 h        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, u. b# d! F4 A" g* Y5 \, M+ k: Q' Y/ A: S6 l6 f% }6 `
        for( INT i = 0; i < 16; i++ ) {# x$ d* h' t2 V) e1 h
                m_bMute = TRUE;
0 l6 k# D, H% K8 a% I" w1 @        }! Y5 s; T" v9 g; a" |
}, c6 N4 l$ R- H4 g3 y  W3 d
+ T' S/ Z) R! w$ J! ?5 O& Q
APU::~APU()
- G; q: \+ Q: Y8 N1 X2 H8 T/ K/ ?{9 P! D5 f9 Z6 X1 t6 |- T
}
% I0 X5 c4 Z5 v3 ]& H; g
- ?0 }: M- I% Fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
8 U( W. [5 [! A  D) X: t/ v{
/ _3 v! Z! A8 J6 A+ _) o; W        queue.data[queue.wrptr].time = writetime;0 Y. z* C& V  X, k( F" B% Z5 Y5 S
        queue.data[queue.wrptr].addr = addr;
* g% }3 l# S8 n4 w        queue.data[queue.wrptr].data = data;
4 b5 L" V& R! z6 P        queue.wrptr++;+ T2 u/ b, x- j  o+ a/ n7 E
        queue.wrptr&=QUEUE_LENGTH-1;
5 M! P: h" e7 V        if( queue.wrptr == queue.rdptr ) {
( `% Y) i' E5 E                DEBUGOUT( "queue overflow.\n" );( X* q$ W  z& y0 ~2 \9 G* `. V
        }# m. h7 w/ ^; b, P
}
) D) q7 m) t9 N% f$ P3 n" }: J! n/ a1 ?/ I) ?
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
6 f) e* p) H/ |0 N# T{
- x1 h# Q* [. C: q        if( queue.wrptr == queue.rdptr ) {
( S0 _, b5 E+ [1 ?& h                return        FALSE;
; z# G1 y4 f& ~2 Q, K; M        }
: `; L' I. M. u4 p) G! W( d  O9 f        if( queue.data[queue.rdptr].time <= writetime ) {2 p  `# W8 i6 F5 ?7 M: o
                ret = queue.data[queue.rdptr];
0 X# F% x, L0 I- `( |0 S1 Z                queue.rdptr++;
5 F" L. ?- ^4 `5 h                queue.rdptr&=QUEUE_LENGTH-1;0 Z' O" Z8 O$ M. ]
                return        TRUE;
& W) x% Y7 H, n        }9 g" Z6 a( w1 t( E* Z" P
        return        FALSE;
" H: h- ~! e7 ^  ]- z}$ S& e/ H3 S# C7 A- A% z

8 l: K2 w/ v+ L: d/ rvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
( C( U9 T, e, [- b) Z; l8 l{$ [' g! a3 n- z* _
        exqueue.data[exqueue.wrptr].time = writetime;. \8 O1 K1 g, g* z
        exqueue.data[exqueue.wrptr].addr = addr;. u! a6 |; y' q7 n2 b
        exqueue.data[exqueue.wrptr].data = data;
/ `( C% F3 L( j+ I; ?) r& c! S/ V        exqueue.wrptr++;
; P4 |. \) Q, N8 ?" d9 A0 x        exqueue.wrptr&=QUEUE_LENGTH-1;$ v% A4 _  y( D2 G: u6 S
        if( exqueue.wrptr == exqueue.rdptr ) {
7 n8 N9 X4 g3 R2 r# X' F                DEBUGOUT( "exqueue overflow.\n" );
8 U( _  z+ G( X) q) F" U        }
# s" S1 t& G+ ^9 W2 Q3 p}
8 f' b% B/ n. B7 {+ K/ N1 X2 D7 }& k3 D8 Y, }4 h7 d
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )0 I1 ]0 l$ N6 K- `: [
{
' p; x- `6 p# p8 e" U        if( exqueue.wrptr == exqueue.rdptr ) {" @" q8 u3 X" a, K% _
                return        FALSE;% M2 n# n' p) l8 O  P! i
        }& z6 _. a3 v8 j( [/ u2 B( x9 \8 R
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {8 v! X( `9 G6 z; a
                ret = exqueue.data[exqueue.rdptr];% J# F0 j, z9 `- W
                exqueue.rdptr++;
1 I, U8 _. j) C( O% {                exqueue.rdptr&=QUEUE_LENGTH-1;
$ c, y, V( }! d. \! F2 }+ n4 e                return        TRUE;
4 p" l. H( [" ]% u6 x# g8 W- n        }
% p) `1 A! H( m; g8 V6 ^        return        FALSE;
4 d+ S; ], a8 a}
4 A' ]6 s. p- Y( K# M/ u2 e$ B" u5 D+ C1 n9 `
void        APU::QueueClear()+ X  E+ b3 |% i8 v% o
{7 X6 E% {* r$ h. x+ M$ V& w4 {
        ZEROMEMORY( &queue, sizeof(queue) );
+ b* c& `! ]5 H0 z3 k  D3 v        ZEROMEMORY( &exqueue, sizeof(exqueue) );- G7 C2 q% A. F3 _
}
! \/ h& x7 E" M/ M
$ g" U  U1 e4 `& m# Z% N$ s; ]void        APU::QueueFlush()$ Q. e8 w9 F. @& I$ q  I; L8 M
{7 F( U/ e; v+ U$ @: ^3 |4 ?1 |/ I
        while( queue.wrptr != queue.rdptr ) {' }. B! x  ?) c, d7 \8 W
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 F, g- K: m1 V                queue.rdptr++;
8 x  B! u/ k) I' R3 q5 S8 o# P, r                queue.rdptr&=QUEUE_LENGTH-1;
+ a- ^7 i/ l6 f: P3 k0 n        }& _8 L* Q0 K0 ~  q  s9 x4 M5 K5 k3 V

# ?- W5 _: M# n/ S5 a        while( exqueue.wrptr != exqueue.rdptr ) {: V6 I' \. X& L* Q, ?
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );( P" b% g6 h) I" ]2 m
                exqueue.rdptr++;
; }; z# {7 ~8 \' f2 B' n1 x0 {1 r  y                exqueue.rdptr&=QUEUE_LENGTH-1;
% O% I, }; b2 x# m& x. m        }7 f8 f6 g5 h( {% v& N+ F* P
}
" C  _1 T/ L9 N1 x
& q/ P4 g! s- N; S4 h: K1 lvoid        APU::SoundSetup()' Y0 Z! A2 r1 [0 k/ E* V# s/ s- a
{) Y* N: X1 q8 x# i* O8 j
        FLOAT        fClock = nes->nescfg->CpuClock;
0 x" F8 I( Z! N0 i9 k2 O        INT        nRate = (INT)Config.sound.nRate;( F  ?8 K0 w! |7 m$ i
        internal.Setup( fClock, nRate );
- \7 M3 g1 z3 ?# A        vrc6.Setup( fClock, nRate );* t8 i6 l7 ^) b" _: ~
        vrc7.Setup( fClock, nRate );
+ \+ s$ t  b; z        mmc5.Setup( fClock, nRate );
6 P: V  R% f; W0 H6 t* X        fds.Setup ( fClock, nRate );6 v7 _" g0 j, D$ |3 S% _  r
        n106.Setup( fClock, nRate );
3 q0 W& r9 Y" K8 S4 Y- g        fme7.Setup( fClock, nRate );9 ^6 \2 `$ K! h
}
3 Z# l& a2 ~( H* F1 Y5 w. o1 y4 b, a3 Q2 ]0 Y% D
void        APU::Reset()
9 E, E' f+ [- v+ w! h1 F, ^* d9 v{7 h) Z2 @$ J7 w
        ZEROMEMORY( &queue, sizeof(queue) );: c2 G( F/ k5 L& F( n% G. n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 ^# Q. \* ^: A/ v" S( I0 ]. J3 v* B4 k. a- ?  t; {
        elapsed_time = 0;
+ }9 M; I3 ?- u# v/ g- N( l1 {% G# t# i; Q" Q. a- V0 Q
        FLOAT        fClock = nes->nescfg->CpuClock;
. c5 P8 k3 Z4 a3 z0 I. v! E9 B$ o        INT        nRate = (INT)Config.sound.nRate;
/ r! b, z$ H  q        internal.Reset( fClock, nRate );
1 }; c4 |. c  q$ D        vrc6.Reset( fClock, nRate );( [' T# j7 x% I
        vrc7.Reset( fClock, nRate );
5 T+ D: T2 w3 z& R- h  G. Y  k1 C4 r( x2 Z        mmc5.Reset( fClock, nRate );
8 j6 g6 s4 M' L/ S$ U6 o        fds.Reset ( fClock, nRate );0 t6 _, S% z( ^8 k# N% B7 ?
        n106.Reset( fClock, nRate );
( S- u* _& S# q- F        fme7.Reset( fClock, nRate );$ u" d$ @0 d/ a% C$ f! A$ F; h
6 d) {; }0 {3 x% i4 g9 g
        SoundSetup();8 u3 ]0 x) g! `* }0 m5 p
}
2 R( G, F% {. I$ A4 |# y9 p
% t: u5 t8 M3 F6 ~+ u3 Nvoid        APU::SelectExSound( BYTE data )
7 n. H% c) h! Z* E) O2 @! B* m{
' Q5 Y. v. s! b, G5 Q* U( k% e        exsound_select = data;: X) K( {5 t; u+ w, O6 ]3 W% ~7 {
}7 g/ t: L7 N/ A+ X! c
. {* Z2 K8 h+ d+ V$ e: T
BYTE        APU::Read( WORD addr )
) h7 g4 a, l; @6 i{+ Y0 p: u8 y2 u5 R* T
        return        internal.SyncRead( addr );) P& [2 l  S5 b% R/ q
}
, D' I- e% W3 M, Y! \
0 b8 C" O7 N: W; O" mvoid        APU::Write( WORD addr, BYTE data )6 }+ U9 u* C$ z% b+ e% u) u
{
& N2 F3 H. l  q: `. ]9 S        // $4018偼VirtuaNES屌桳億乕僩
* w! o# f; e2 e8 m  S2 @* D        if( addr >= 0x4000 && addr <= 0x401F ) {6 M5 c. a0 D/ k4 N1 I, [5 U9 k$ I
                internal.SyncWrite( addr, data );
3 ?3 z# V( o( {                SetQueue( nes->cpu->GetTotalCycles(), addr, data );  S6 ?  ^4 f& L
        }6 J5 n  H3 f" _5 t
}
# |7 c/ j. s, N
8 V' h4 K5 U( j3 n8 i, xBYTE        APU::ExRead( WORD addr ); |" w5 M9 I' i& t' k) b7 C
{
8 L1 P/ P. L  }5 \  QBYTE        data = 0;
; ~; ~" f+ J, _
. K/ O7 G+ s6 C        if( exsound_select & 0x10 ) {7 Q4 _$ t/ E0 Z$ K. I; n& p7 J
                if( addr == 0x4800 ) {
3 J3 t; r) D% ~3 _/ M$ G( m, f                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. R! B( s" s' h' [& g8 @+ A                }
2 U  s/ c( A1 i2 q9 }# o) A2 W        }$ y% A. g9 ]  e1 R5 u* H& E
        if( exsound_select & 0x04 ) {
: `$ N+ a5 O* N/ f! m! y                if( addr >= 0x4040 && addr < 0x4100 ) {
0 P- ]7 j- Z5 }                        data = fds.SyncRead( addr );
5 J  p! [$ ]7 x                }
) s; t0 W9 ^8 S        }1 s5 j# U! e! F3 t7 \
        if( exsound_select & 0x08 ) {6 o1 \! C3 Q6 a: I, g4 q! o( k
                if( addr >= 0x5000 && addr <= 0x5015 ) {& N' _% a) U2 |) u( _; q; c
                        data = mmc5.SyncRead( addr );+ g1 a6 O3 D% B2 N$ v
                }
+ p0 Z/ ~4 {; m; a& Z3 o6 a        }
% t. C1 V1 X( T1 A* `) H2 _1 m) l5 v: m: v
        return        data;
. `0 u9 I) W+ r2 Z& d}
: j- Z' Q% `* B7 u$ K0 ^
) P- _) W6 V. {" \/ f9 D% ^void        APU::ExWrite( WORD addr, BYTE data )
7 h2 B: |; B9 `{8 |8 D( S5 @: ^8 h! X( l
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 W; Q* `8 C* r# K

4 r6 S3 w- s: Q5 n/ t        if( exsound_select & 0x04 ) {
4 v7 m- x0 g; G9 c% c: l, }                if( addr >= 0x4040 && addr < 0x4100 ) {! B  E4 I6 ]5 C
                        fds.SyncWrite( addr, data );1 T1 K+ q1 c0 w; G" I" s$ D
                }) ?" |- ^9 Z6 M" u6 y+ a8 ^! r7 R& N, r
        }
: X- e- h, H) u# v# S5 u' p- }. O$ L: V* L! V7 l8 x) h8 O
        if( exsound_select & 0x08 ) {5 e! f& R! R) ?
                if( addr >= 0x5000 && addr <= 0x5015 ) {8 F0 q- ]/ ^* ?6 D. @
                        mmc5.SyncWrite( addr, data );
" w) I. H: \  a; J# ^& {9 M                }2 m' M4 V+ ]/ ]! U1 {
        }
( |/ F. J" b) ]( @* _& V}6 Z: ]0 m5 Y6 f+ [' a7 ~

9 o- A/ r" \& @$ r' t0 a) K( A6 ~$ Fvoid        APU::Sync()  V: p6 h+ x2 _5 L6 P
{
& a# W  D' x* x# Y0 c: s}
. l1 h+ U* i( O' v
7 G/ {7 s( O3 ]' y& svoid        APU::SyncDPCM( INT cycles )
/ a( ^1 ~1 C5 F6 f{/ E8 S0 e  o, ?' C
        internal.Sync( cycles );" {7 G) V5 W8 Z$ C2 p- C
2 i3 J% ~' R% U& C% }
        if( exsound_select & 0x04 ) {, s% X$ I* c8 |1 y+ }. w% f6 B: z
                fds.Sync( cycles );" s* \4 t" ?7 U- Z
        }
9 m3 R$ N- s& f        if( exsound_select & 0x08 ) {
6 S, W% J$ r% k) F' c                mmc5.Sync( cycles );
3 U3 _9 F6 p: `# x        }, a- _8 L/ R' m+ H
}
: h( o& i6 ~. r4 K9 w! M/ j( e0 Q4 O) C2 n3 l2 o& d$ E: D7 ^9 e  T
void        APU::WriteProcess( WORD addr, BYTE data )
- D2 n" j* r- X8 |" h; e{$ Y3 Y- `/ ^4 o9 W: E
        // $4018偼VirtuaNES屌桳億乕僩! @9 U. M* o& g8 B9 a
        if( addr >= 0x4000 && addr <= 0x401F ) {
( U3 H1 T' L9 Z" g7 V( [                internal.Write( addr, data );
1 }( r; k* n2 Z1 k3 G        }4 r( e) a6 Y; K, u) m; V4 o) u
}
' A& X. J) D8 Z4 I
4 A' W- o; K; Y' `3 }0 @: uvoid        APU::WriteExProcess( WORD addr, BYTE data )) Y. s8 A  u& p; N" I: h9 x
{  V0 ^$ S) F# w- ~: [
        if( exsound_select & 0x01 ) {; k+ Q. D( W0 A! g" a1 K
                vrc6.Write( addr, data );
0 A8 ~4 j: V4 K6 R$ i' y- k  n        }% w$ E6 Z8 _( b
        if( exsound_select & 0x02 ) {# q2 S0 b) k, ^# F
                vrc7.Write( addr, data );
9 l. c: e6 k5 o4 g1 h        }1 ~0 q' n8 J* w, o/ K
        if( exsound_select & 0x04 ) {
# U/ g; a) t3 c* m                fds.Write( addr, data );
/ g/ V8 w2 L* q3 I- \  B        }
, X1 d  {# m, [- y# d: G+ F        if( exsound_select & 0x08 ) {
# y) d! U$ `! M5 N" B2 C+ h3 W                mmc5.Write( addr, data );$ K9 J! w! D- a- O4 m, }  y6 y) R
        }
8 G) C8 o* p7 [8 Y) |) w        if( exsound_select & 0x10 ) {' x, u4 }8 b( {
                if( addr == 0x0000 ) {! S: S# H5 f4 v6 v
                        BYTE        dummy = n106.Read( addr );
4 c2 j3 |8 ^$ u) h2 G7 k                } else {1 z& P  c/ Q; g: w8 _
                        n106.Write( addr, data );
& @9 K9 J9 \7 Z                }; E$ U+ [5 @+ ~9 C" k  ~! y
        }
! I! M' f) E8 ?- @( A; q        if( exsound_select & 0x20 ) {! q, x: W3 t: L$ z
                fme7.Write( addr, data );
  ]8 @( p0 ~0 {) l+ h        }1 b$ y" k' B  N8 z& o7 H
}) S( F; Z5 G( w0 T
; M# U" S" N3 r  i7 n
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 @) K% ]' C. A- c. a/ @9 a* T
{' ?& H0 `6 v7 R8 q! o9 i
INT        nBits = Config.sound.nBits;
3 Z% c" d2 f) \  `, N/ w" vDWORD        dwLength = dwSize / (nBits/8);- J0 m+ \4 W. q
INT        output;- r( o9 Y& P  e/ D2 F
QUEUEDATA q;& N6 X) G6 J0 n% P/ \4 U. e$ v
DWORD        writetime;
: x' r0 W- N6 B, D$ g7 p9 l! j# L+ I+ P( n( e# i5 M: g  x
LPSHORT        pSoundBuf = m_SoundBuffer;
# ^4 F1 X* f/ k' }& oINT        nCcount = 0;
) W: b4 G- H1 X+ }. G# V, ^# n( d, ^8 X5 J- \" v
INT        nFilterType = Config.sound.nFilterType;8 U$ T' l$ v/ [$ N, L( K' }" W% b+ o
! F0 A. F" m4 ~' Y! w
        if( !Config.sound.bEnable ) {
  h8 v# k4 U6 i: |+ G. G  K                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
/ }" L8 w) n% ^* R9 I! _                return;
6 Z! ]. D% c7 U  n0 }+ W) R        }
2 U+ J/ V2 B* o  s" b, X0 x6 u; k7 P# @$ |, i5 s, s3 h; s* q3 O
        // Volume setup
5 F/ d# {3 x+ x8 U        //  0:Master0 |( N% Q, p0 u% x; d
        //  1:Rectangle 1
) h( I3 R5 m0 m2 Q        //  2:Rectangle 2
* b) e. e6 _5 }. R! Z$ F        //  3:Triangle
( ?/ U1 I0 D5 Q  H& I# b! U        //  4:Noise
3 q4 \. i% Z: J5 c        //  5:DPCM3 b2 y) J0 j! o+ k. K
        //  6:VRC65 ~0 N/ ^4 Z6 i) o* V7 {  P7 t
        //  7:VRC7
! C1 u. H: W! {4 Q        //  8:FDS
' {8 N. e# ]0 {& K" Y" c7 P- n        //  9:MMC58 z( G- B% ^1 s" y% |  ]
        // 10:N106
' g1 L- b( j# E( {; w: x. {        // 11:FME76 A* B: O  z) W& e! Q
        INT        vol[24];
* K- @8 p" ?) }/ a9 b        BOOL*        bMute = m_bMute;0 ~% e% e. M4 v/ b$ D
        SHORT*        nVolume = Config.sound.nVolume;, u. L% Y3 n5 ?/ A1 X( A, Q  r6 ?  @+ v/ E
/ I9 w8 Q6 ?( ]! T  Q# C
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
2 n8 t  J) q: m# U9 V# k- Z7 L9 Y, o
1 _4 x1 J+ S4 T4 B7 ?  V        // Internal
( W; \% X& L2 c% M: e; b+ Q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;2 C+ t+ B+ s' r# M) t+ g* x
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
8 ]7 p; Y( K% Y; V3 P        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: A, L, V6 t; o/ y) @
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;/ t& q. ^7 L2 h5 u" d
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;4 h0 f- `: F) G% c& b0 z
, M! u5 V4 v' p+ F2 k2 b& S
        // VRC6
& v1 F4 D, _8 O        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 j- j) U/ k+ J) q/ ]% o( z3 j1 u
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# K+ ~- B) A) v* S9 n        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- S) R; P+ E0 X# d2 V0 s
; ?: @2 J" _, f% V$ D
        // VRC7: s3 y; e5 F4 B# U- Q. [
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
+ v7 A/ d8 O' }; u. a7 S, N5 z" |/ x+ k) ~* X3 K/ g
        // FDS
2 [9 S/ a6 y- q: j2 x, M/ x4 x3 c        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
6 b, L8 ^. G0 S& v3 R  S4 U
  W5 n0 G" n- ]* E0 M        // MMC57 J$ G% w& F+ z, \  t% [
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 q. R; G& u) @* f' W( }
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* _: I/ h; n/ G3 v- P% v. e& x
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ n# P4 G/ Z. B, S  r, q7 \8 ]( b/ ?& [8 C! w9 O: _2 b+ A7 [
        // N106* g9 D/ O) w1 V* _
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' n5 P' R( H* H- U9 H  V' q        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, l& L/ {3 ?# N( e& d6 s' O$ [3 O
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; ]4 e/ i! v" e' n" _7 x/ s* N
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ^  M" {% m- V$ f- O1 U& Z1 ^        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- V2 M" S5 D% W7 o
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; N6 I+ k- }' U        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* t* Q& n/ ~+ Y        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 n8 p' F. N7 c/ u! U( d' S- ?5 j0 V+ a$ ]% L
        // FME7+ _( ~5 A$ b+ T1 V& d
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% O. d7 r. y5 l, v! ]$ n        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& i: S8 ^% m$ [7 Q- ~3 l        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' Y/ `1 w1 z% Z' w; U) j  T, ~  S
  R4 ?% t, p& o
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
1 x% U/ N+ r- T! T& R% {        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
6 |( V6 v) h4 L( M- t, C! ]4 Y* I) \7 k) }% Z8 t& L  B/ x
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟6 C9 r' H9 D5 T: a
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' H3 e1 t7 u% F3 f: ]
                QueueFlush();
( q- O9 H* i& f& P! i        }
8 g* q2 H6 n% d8 ^9 c( S8 L; @3 p2 j2 C# m$ j' Z* J" Q& a. F
        while( dwLength-- ) {
! p, E, h5 D: v2 k* v: h                writetime = (DWORD)elapsed_time;, a4 k4 p( }* |: B9 R$ T- r% A6 q

) O7 T! A) F( G" W% J, {                while( GetQueue( writetime, q ) ) {4 A6 g. \  [1 k
                        WriteProcess( q.addr, q.data );: }$ ~# E2 j/ [: W* V( H4 ]& W
                }) x5 e, \, y, M. l
! [" q5 i' r7 u, {
                while( GetExQueue( writetime, q ) ) {7 ?& \7 u8 T$ o# l
                        WriteExProcess( q.addr, q.data );/ I5 S, |- W2 c
                }. b5 R9 Z3 \2 b. [/ ^0 q1 Q
0 G' k& D+ I1 M# q
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7* @- s" R- D4 T* _0 G
                output = 0;. |! Q1 g) d: J! j+ j9 @2 S7 k
                output += internal.Process( 0 )*vol[0];
+ ]! C) a( U% n( O) F6 i& S2 Y                output += internal.Process( 1 )*vol[1];
( G  i4 h- |+ V% _+ a6 K2 \  e; ]8 k                output += internal.Process( 2 )*vol[2];$ {2 p3 w- b( {. o
                output += internal.Process( 3 )*vol[3];
4 k& c7 L; Q9 u* p8 B                output += internal.Process( 4 )*vol[4];: i& H- m9 w+ [1 R' S
$ u* ^$ p! f8 S9 s- o
                if( exsound_select & 0x01 ) {& C- T2 `% y" V0 e1 o
                        output += vrc6.Process( 0 )*vol[5];
+ W$ T. ]1 m3 u1 {/ b+ P' }                        output += vrc6.Process( 1 )*vol[6];0 H% W0 q; _! |9 X1 ~( _" H, c
                        output += vrc6.Process( 2 )*vol[7];
' ], v% n5 B" J+ _) S9 D7 L6 ?                }
& h9 l  g' Z0 N4 c  R7 d                if( exsound_select & 0x02 ) {
' c( M+ e" g9 W                        output += vrc7.Process( 0 )*vol[8];. a* y  n/ f, U' s- u
                }
" R/ G- g8 w  g2 L- B: Z3 v* N                if( exsound_select & 0x04 ) {
9 |9 t0 |1 `+ r: P, U' |- _" p                        output += fds.Process( 0 )*vol[9];" [9 f8 }3 j% @" l+ ~
                }" E+ u7 {  H8 f0 o( [
                if( exsound_select & 0x08 ) {( {% |$ q4 m4 h0 }" X, ~
                        output += mmc5.Process( 0 )*vol[10];/ N! w6 Z  |* Z4 D5 W
                        output += mmc5.Process( 1 )*vol[11];
! O6 p+ P  Z& x6 e                        output += mmc5.Process( 2 )*vol[12];6 a! o% |/ |+ L/ ?1 T9 F3 U
                }, Q; o# W$ A. a/ X( j, k$ o
                if( exsound_select & 0x10 ) {! e* y4 |: C8 p
                        output += n106.Process( 0 )*vol[13];# q% g% N' F8 |9 U9 H- j7 E
                        output += n106.Process( 1 )*vol[14];1 n9 |' |1 \9 ?4 A5 n
                        output += n106.Process( 2 )*vol[15];
6 ?! O/ p4 `+ P, N& N- r6 z  J                        output += n106.Process( 3 )*vol[16];  H2 W* m4 `' g( f, v3 V
                        output += n106.Process( 4 )*vol[17];/ j& K5 J  ]; b) Y- P# K' M
                        output += n106.Process( 5 )*vol[18];
  ?. d4 m# E0 ~6 ^: S- O4 [                        output += n106.Process( 6 )*vol[19];& j- w/ |/ X: l- e1 t# S
                        output += n106.Process( 7 )*vol[20];
  b- A" H5 |% h5 U                }
& w& m! s6 N3 t                if( exsound_select & 0x20 ) {8 o* ?6 {  {  T  k$ N. E3 g
                        fme7.Process( 3 );        // Envelope & Noise- K; b3 @* K. i. X/ i
                        output += fme7.Process( 0 )*vol[21];' }  |  E; L& d- Q( F9 q
                        output += fme7.Process( 1 )*vol[22];* R- D8 x5 o# p: ^; L. {  K. S
                        output += fme7.Process( 2 )*vol[23];
  }( D# b, A' L6 D# y( M                }
* B: c4 p8 S2 I3 N7 A: F: K4 k/ |' G6 I) e
                output >>= 8;
7 k+ u, ~. z2 h) v
1 P6 r& E' N  C" j+ W2 r7 @                if( nFilterType == 1 ) {
+ R4 d5 v" }* K2 v+ ]                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)' F' O# k6 L4 X' {8 Q1 n+ P9 o
                        output = (lowpass_filter[0]+output)/2;' g" G0 e* |2 L2 ?2 `0 b7 D
                        lowpass_filter[0] = output;" N+ K$ r( V/ y7 z
                } else if( nFilterType == 2 ) {
4 z0 W. Z8 ^$ ~( Z0 G                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
: u. {; _& k' S9 u+ Y! m7 {% t                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! z, C% x8 @4 @$ p- A                        lowpass_filter[1] = lowpass_filter[0];+ q' \' Z5 u' _! o' l: o# a
                        lowpass_filter[0] = output;
) R4 z, u0 \! O% i) |6 w. o                } else if( nFilterType == 3 ) {
  g5 r' A- g- @" h                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 `- C9 [6 }+ t                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;8 }3 {- |( H1 T- w2 r! n
                        lowpass_filter[2] = lowpass_filter[1];( F. q6 z% a/ P
                        lowpass_filter[1] = lowpass_filter[0];
; h6 T4 Z( e5 ~' g                        lowpass_filter[0] = output;9 N& e4 g& e, L. X
                } else if( nFilterType == 4 ) {( \: f$ y4 A5 q7 Y9 t: P8 k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 h% k, s9 ]/ j- Q0 W
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 p0 y7 @1 n0 b2 u- l9 T$ h- t
                        lowpass_filter[1] = lowpass_filter[0];
6 I# l8 f7 R0 D) a                        lowpass_filter[0] = output;* a8 `# j0 y+ a6 s6 n1 G* o  G
                }9 I0 f' y4 t- ]+ F. R0 ]
7 S7 x5 K6 }* f' w$ M, `5 C
#if        0; x3 H/ K, j- `" c! N8 z- \  N
                // DC惉暘偺僇僢僩
: {" S7 F- d1 }1 G' g                {
' z+ r/ w2 H. @0 u; ^5 d                static double ave = 0.0, max=0.0, min=0.0;
! f$ A/ y1 K; W( Y0 d# R- M6 F& D                double delta;
, H1 N5 x" z- ?8 N9 m0 e, K; f                delta = (max-min)/32768.0;
' W: o1 J: a1 O* E4 `                max -= delta;
' z: t4 `% C# l0 }% L                min += delta;3 E9 k, ?; l6 [& Y8 p$ g/ K
                if( output > max ) max = output;
6 s; _. ~, i7 n/ L                if( output < min ) min = output;
+ ~+ \# o% U2 \7 F: `; F, F                ave -= ave/1024.0;
" D, E% L1 D" i) i8 ^3 m                ave += (max+min)/2048.0;7 |3 e( E# }7 c' e" K7 z
                output -= (INT)ave;
6 {( K! E/ X3 |8 S                }
9 N+ m6 P% d; P# q, u5 F#endif
8 U$ D/ t( }$ ]) d/ |# P  U% U( g#if        1+ r" f$ _# N8 R
                // DC惉暘偺僇僢僩(HPF TEST)  G4 z9 q( N4 Y+ y. {6 o, I
                {
  F/ N  f- x+ P//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
% [0 X, b4 T; \& A+ M6 {  N! d                static        double        cutofftemp = (2.0*3.141592653579*40.0);
1 S: S9 T4 U# Y5 t  @                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ ^/ a8 F9 B% V9 \. [, p                static        double        tmp = 0.0;
/ r6 V9 x; @0 {! Y/ `9 X                double        in, out;3 N% Y: u2 l- X3 ^: B; R0 H4 ?

3 b9 z% [8 ~( z& d. c9 d  o                in = (double)output;
3 H6 D4 ?$ w, P. [                out = (in - tmp);
% O1 y5 f& Z, t& ^6 {! L                tmp = tmp + cutoff * out;
) e  z0 H4 e" D4 B$ ?5 P. f! B9 I; t' `9 g  ~1 R
                output = (INT)out;
/ i$ ]8 a6 N% t% u                }8 g/ O/ f) f  [4 J) `0 O
#endif
7 I4 O, y! ?! y& U9 B#if        0# y2 g4 k" C! o- c! r3 g
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. j( Y$ ^- y6 m                {
: K' g# z6 N$ P, ]                INT        diff = abs(output-last_data);+ ^4 d0 m' g# ^# ^
                if( diff > 0x4000 ) {
0 ^* N. L+ d7 o/ W6 N                        output /= 4;! K2 ~9 h3 Z  ]. z9 F1 G
                } else   N7 a' \% Z  @4 \
                if( diff > 0x3000 ) {$ p& K. x! c8 m
                        output /= 3;
( K& X, D/ D/ M% |                } else
/ s( ], U8 g& P                if( diff > 0x2000 ) {% T6 U/ J! H; A# B, C* s
                        output /= 2;( A" m4 O& h! f1 X
                }; P3 p$ f. O9 E; i8 {
                last_data = output;' p0 C' W! H+ o" T0 G- m. r; u
                }
% z6 n2 g! e: ~1 Z4 u1 w# g( w: G#endif  p% O1 z& `/ w. j$ I- c0 t( I
                // Limit
% g9 X* l- _, r5 v* z7 F                if( output > 0x7FFF ) {
8 N  P5 w! @" Y; k4 h1 e                        output = 0x7FFF;  P- I7 W. h! ?
                } else if( output < -0x8000 ) {
  M5 Q' T  a- \. h# i, v( M                        output = -0x8000;
: U  P# ^& R/ y$ X3 w9 s  l                }& Q2 w5 M$ |/ u7 f

7 j9 s2 W$ w3 b2 A) i# Q* B                if( nBits != 8 ) {5 R; j" `; D" E6 ~- t0 ~
                        *(SHORT*)lpBuffer = (SHORT)output;) N! K6 R( T% d! T) Y2 [, j; A% I
                        lpBuffer += sizeof(SHORT);
# K8 Y1 C$ V& c* M                } else {! E5 p+ q6 {5 D/ |  d) j+ [
                        *lpBuffer++ = (output>>8)^0x80;3 A& |# O) f( P. n4 Q
                }
$ H' W$ U1 X$ W7 J9 Y6 b( |( s6 O' l0 o1 b7 l- s
                if( nCcount < 0x0100 )
3 v/ W9 g1 a$ B* _# C) d1 k8 I                        pSoundBuf[nCcount++] = (SHORT)output;
% F. s8 q- e% x9 F  B: R, X# `
) d+ s" ?8 T4 ?, D. R8 j, \//                elapsedtime += cycle_rate;5 C" f! x" l' m! C5 z% e/ A
                elapsed_time += cycle_rate;
" `. |7 T$ D  L" Y( }. G        }+ a" g+ b5 o$ i5 h+ H; ~
' C# L  z  b8 l2 Y7 X
#if        1
9 k( E6 P) M8 s1 f, Y% Y# ]% H        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
( S$ P6 X9 E3 ]+ K0 }' W                elapsed_time = nes->cpu->GetTotalCycles();
: x; y2 m% }1 V        }
9 h  O2 Y( J, O; N        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
7 @4 d0 J3 E/ \4 Q0 Q0 D                elapsed_time = nes->cpu->GetTotalCycles();
+ k! [( J3 }* ]7 \2 V0 d5 T4 ?) h        }
% E% p# P; s1 `: {, t) X1 K6 N4 A0 D#else" Z( Y. t. h9 F9 D
        elapsed_time = nes->cpu->GetTotalCycles();) V& E4 {6 s% @8 H5 e! p
#endif. v; n( u3 }9 A6 L
}
7 k4 E. l9 s* ^" H% R
2 g3 t$ \3 l8 G6 n// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
8 _& ]& R, L2 o" W" W* W% {3 FINT        APU::GetChannelFrequency( INT no )& g7 b: Y+ V" d  o
{
3 H. {1 b" k2 _$ J8 O% C        if( !m_bMute[0] )
6 t% s% O3 l$ I! B8 u                return        0;
1 B% T% f$ N9 {$ _
" S9 _' T6 Q2 `# j2 P        // Internal* z& T4 t5 P, T9 f; n
        if( no < 5 ) {' ~- m8 \( v8 f  U! p
                return        m_bMute[no+1]?internal.GetFreq( no ):0;( p3 m  x4 N' y1 f& M2 r
        }4 y6 Q8 L" z: Q
        // VRC6
1 I: _  [2 \2 n1 c+ k; d8 y        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; l: C( R* E+ J. Q
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( Q4 I" q7 f4 t2 u        }8 }3 Z& V; Z7 M7 A
        // FDS8 b# K* s7 p- e  t
        if( (exsound_select & 0x04) && no == 0x300 ) {4 L1 r3 v' z* r. X' |
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
& W2 ~- x6 m8 D* \        }
: |  T' B7 V" h        // MMC5
0 J; Y4 J9 @% S4 s        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {' N/ `( y' _1 y! L5 R5 U
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 {$ \, e! R+ ~6 O0 u2 w7 }: ^        }$ v* w: }3 V2 L# X
        // N106
9 N+ U* u; C' y. m# g        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
3 h0 L7 X2 Q, ~* l0 B0 D% I                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
4 x; T- G3 u" ~        }
" ~* L$ ]2 e3 x' c. w" Q        // FME7* o5 O' S  @* d; u! t5 P
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
/ l' r5 |8 a  o" l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, X9 W6 Q8 {3 Y" U3 i
        }
1 l' |( h# Y6 h0 j        // VRC7
' ]. D+ P+ R- p1 [6 x        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 Z7 s- C3 m1 Q0 w                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;8 O& U3 o4 @' H% M  \  u$ X+ `
        }* w" C+ T! a' f$ V9 P: c. G
        return        0;# U. B; x. j+ V& V% B1 @' ~7 R
}8 B" E6 @! Y8 E, N

5 {# g& b, M% ~* ]. v* A1 d- T1 u// State Save/Load
9 R! v8 }" k3 C' Z  l8 P' xvoid        APU::SaveState( LPBYTE p )
2 r; D1 i1 O+ A2 M: \{
3 q9 ~+ y8 m$ k, S5 x  p( ]+ X, Q# P#ifdef        _DEBUG9 @( L+ o( Y, z; t+ ~
LPBYTE        pold = p;
  k, T% o4 U& ~" a5 k: s+ y/ f, x6 G#endif5 k- t1 D0 L. ]

4 y% B! c+ o, `) I( H9 W' L        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
7 T5 {9 [" k; Q        QueueFlush();3 d: I6 q' J; m2 y: V
- y8 h( x- h- _8 Z
        internal.SaveState( p );
3 {# n3 _- H+ B3 n        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 W( c- d9 D) \

! ^! l( z: K/ F" D5 O1 W. a1 m        // VRC6& N8 d# q: |, A; {& f5 Z' `
        if( exsound_select & 0x01 ) {8 Y! F% `0 u) [5 f$ e. z+ T
                vrc6.SaveState( p );& R3 e8 ?: m  J. Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& p+ ~6 C0 r0 n) Q& _  j
        }( q2 u; R" p8 E( v& {
        // VRC7 (not support)
# p; i  n. Y8 ^; G; c        if( exsound_select & 0x02 ) {" V+ b' a4 s7 }* O5 X& C$ Q/ z
                vrc7.SaveState( p );3 b. T- _* u' `- D2 e3 ~
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) @! F, J( R; J4 Y) n$ W
        }* ~( x5 x8 t! s, j$ F4 S0 {
        // FDS
% z1 w8 {4 d! }& M' I0 {6 r* J7 R        if( exsound_select & 0x04 ) {( A/ x% p0 V; l5 @4 J0 A
                fds.SaveState( p );
7 T) L! r9 O; G6 u) u; j                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: `% n- a9 R7 u0 J
        }
+ \' a& v* j* B  C& z* ~        // MMC5
9 r! s+ Z8 H% v        if( exsound_select & 0x08 ) {5 Y4 k2 y$ s6 |/ j7 ^
                mmc5.SaveState( p );
8 z! {6 `: O0 l. y8 ~8 K7 M3 H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* j* Y* l5 y+ X/ |        }& e% ^+ e2 J7 F; v/ h
        // N106
  t; h0 i$ n1 C8 y0 P# m        if( exsound_select & 0x10 ) {
) P7 {! ]8 s9 H# ?                n106.SaveState( p );7 B1 e6 m" E# r0 Y0 p
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# H! N+ Y5 o" s: W. W2 Z
        }! ^3 ]: R- r/ p# k# T7 j. v
        // FME7
! \+ ?$ `/ R& q9 D        if( exsound_select & 0x20 ) {
; z9 i- M. T/ ?- G+ a0 {) v9 J/ C                fme7.SaveState( p );3 u3 G; M( V, B; v! P8 {; U
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' P8 A) T% C0 Q  R) N) T" H) N# ^/ h        }
2 j, u4 k& e" |2 o5 o
# g5 m0 |) T) i  h: E8 f, w* U4 l; w#ifdef        _DEBUG4 O- L" O3 m9 _/ }. e! B: H
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 |5 U" k3 z% {+ s) n+ k2 y8 M#endif8 B5 D) O, [- U( W8 E) H
}
' C/ c2 I5 A- X5 s. X) D8 Y6 I4 f0 M+ K" }" Y1 A
void        APU::LoadState( LPBYTE p )
6 o1 F' @5 L; p5 K. x9 @" L{! r% E1 l; |1 H& T3 k- H
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡2 V0 P8 L& u) s
        QueueClear();
3 o2 j; b: Q$ }1 {) y
# l9 g# t8 _1 C8 P8 P, I1 Y        internal.LoadState( p );( s+ I  o/ [+ @$ o0 C' O/ F5 s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
1 B* }& ^/ i% U$ O6 m
  H2 S& n% S: a) P, k        // VRC6: O" I0 C( a9 c7 J! y. y1 {* I& u
        if( exsound_select & 0x01 ) {2 @) M* K0 y7 I/ F' {7 U
                vrc6.LoadState( p );; f  ~" z2 A* [8 `
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' ^% y6 g$ E" R4 z1 N6 E3 w        }8 L4 X& G* z4 i4 E
        // VRC7 (not support)
; J4 |4 p( N+ L# l+ S. t8 N        if( exsound_select & 0x02 ) {
, |# i8 f- l6 ~% d% K! L3 W                vrc7.LoadState( p );0 M' x* P) @! e  O( j& f* A
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ }9 r5 x1 x. f
        }
& a. C7 x9 r4 w) C! _8 F. L        // FDS
1 j; M. z& t  |8 _* v# L& @        if( exsound_select & 0x04 ) {
+ y- c4 \& W8 x% m. o- i                fds.LoadState( p );
, Y' y8 E+ Y7 V3 z1 p" c, u8 k  j4 t( v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ B  R5 }4 T/ Z: f/ u- m
        }
/ [; H% X& ?( T        // MMC56 q( a" V4 `/ o6 N3 V
        if( exsound_select & 0x08 ) {
2 h5 g! S- x: F0 \                mmc5.LoadState( p );
# N- F2 y, j/ M" f2 J                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* ^4 E% k: u/ [. f6 w) h
        }2 O; u, p2 P! _1 Z' S
        // N106
4 }) K) _: Z) q) s+ Y        if( exsound_select & 0x10 ) {; Z, ?. {$ v# |, S  e( C
                n106.LoadState( p );
3 F+ D0 a" O3 }! s5 @! V                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 [" Z1 ]) X) Q+ \        }) m5 ~2 x" u+ \2 K
        // FME7
+ ^* n3 _$ o. x6 e$ D% J( X, R- k        if( exsound_select & 0x20 ) {4 D* _! S4 Y, `0 }) L
                fme7.LoadState( p );. g$ c" z: q7 w  h) X- B
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% x( q0 j& N4 ?* V        }
3 k) E8 @! [6 H& J& O0 G2 a}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& q( k7 f4 s8 H, L9 E$ p0 {% V可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 O: u9 k; @% W! Z感激不尽~~

. K$ d% M) Q0 P恩 我對模擬器不是很有研究,2 w, k$ l& Y# g) j1 k6 l: ~: J5 ^
雖然要了解源碼內容,可能不是很困難,
2 E1 W1 O( v7 d9 q/ U4 x- r  x不過還是要花時間,個人目前蠻忙碌的。1 {/ l! e6 l3 s6 e7 K: `
1 Y( x: m+ }" b- i" R) c
給你一個朋友的MSN,你可以跟他討論看看,) O* d" Z* y' F' ~; s5 N8 H
他本身是程式設計師,也對FC模擬器很有興趣。' f4 v% U. u. f3 u2 q; F0 |$ u; k
. W$ c2 e. G& F' m2 N
MSN我就PM到你的信箱了。9 ^6 l% P/ i' c) R4 w

$ d3 F, H5 T/ q& |5 F希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 7 h* x) V. r4 O3 s
呵…… 谢过团长大人~~
( R  C( M! X# G" Z0 l. ^/ ^

% A0 R0 {/ C3 p3 B% r% O6 m3 o# Q: |哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 o  _4 h' d$ X1 |. k: H4 f* k团长的朋友都是神,那团长就是神的boss。

( j' J: O* h4 r* E. U哈 不敢當,我只是個平凡人,
8 j1 k. m$ e4 _' W: R. T% {要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& l. O" b& Q# T' j4 I" s
ZYH6 Q6 o& ^2 U( V7 h+ K+ u; o3 t. j
QQ:414734306+ o6 H% y& J) v# j* y
Mail:zyh-01@126.com
$ O2 R4 z# z9 N( k4 r. l: m5 X0 R: e
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 I! |5 z. R- Z. [, w4 |2 P, H
再次对团长大人和悠悠哥的无私帮助表示感谢~~
6 N8 [2 y4 V, G" n3 D) o1 ^% v# O
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-9 00:11 , Processed in 1.072265 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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