EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
- D; q- M/ L: f楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: `* e: D6 u, [* J! m这里有相应的模拟器源码,就当送给大侠了~~/ _  i" ?9 D. o; F! i/ x. `
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# M/ H" ~  A: S+ _1 Y& Z能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 ]% s3 b: V& ]% f" w
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& O& Q- H: h, u$ O/ ?6 W这里有相应的模拟器源码,就当送给大侠 ...

2 U( q, E2 B- Y2 j! ^( n聲音部分(Audoi Process Unit = APU):) T1 m% @. d" f
.\NES\APU.cpp9 }* e8 i8 R6 y3 W
.\NES\APU.h
- V  M/ k; D0 y+ A
3 g$ R! c* i. @+ d- m" L
7 k# P0 y1 ]) R# {2 [) C, D影像處理部份(Picture Processing Unit = PPU):5 `. a/ j$ L) D7 j  `2 q. P
.\NES\PPU.cpp
2 c9 ]& X& R& \3 x.\NES\PPU.h
7 q$ w1 L7 X% ?' O& Q; C- u$ S
& ^1 F( z/ ]( [! V% y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
, C% w% }0 z6 @5 [( h+ x" Y(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ ^9 f3 p) s9 V9 f
//////////////////////////////////////////////////////////////////////////
! A+ M' ]- X2 V$ d! G3 ^7 G//                                                                      //- c1 l2 f- a/ l: P. t
//      NES APU core                                                    //  |4 x; |. M0 }3 O6 Z- g. J8 C
//                                                           Norix      //
3 o  l8 t9 V- C9 F; k0 C//                                               written     2002/06/27 //
: y- o- B' G$ A& p7 \//                                               last modify ----/--/-- //1 o; H8 v8 }) A" ]. ]* G
//////////////////////////////////////////////////////////////////////////* s  r) E4 h8 j5 C: i) V: d
#include "DebugOut.h"6 m6 f7 S/ X! L  n" r' V
#include "App.h"
+ Y% v* E- O4 }( w, E#include "Config.h"
# y9 X: a5 I* `- I, r( g3 c2 G# X- B* \  d/ G- P' p
#include "nes.h"
, h* N% v; m+ R" _6 Y" C. e#include "mmu.h"
( @. ^- H* o! B, x0 D#include "cpu.h"
) b! @% P' u( B: G/ f8 Y" s3 P) [+ f#include "ppu.h"6 H8 t  X3 H1 e2 v
#include "rom.h"! Y) D2 B# d+ ^
#include "apu.h"& A1 N& K4 h  j! g" X  j$ n, g
/ Q; ^& w( O# Z2 A) J- F+ I
// Volume adjust4 v( P  d. o. H7 O0 _! g& p4 t
// Internal sounds
: V" h; D3 }2 u' D$ o, f/ a! v#define        RECTANGLE_VOL        (0x0F0)
% E, A- W9 A5 H* V$ U#define        TRIANGLE_VOL        (0x130)3 f1 l2 n1 d' A
#define        NOISE_VOL        (0x0C0)6 K" v) p5 G1 B2 C; O7 @: S
#define        DPCM_VOL        (0x0F0)
, M1 Z9 x8 R/ q6 p& |% z+ E9 y// Extra sounds2 [9 w6 v3 d, i! D6 v8 t* c
#define        VRC6_VOL        (0x0F0)
; {$ C1 q9 ]) r9 h2 ]#define        VRC7_VOL        (0x130)
) ^7 n: ~8 I$ P% \/ ]: B) z* B. h#define        FDS_VOL                (0x0F0). y5 M, }+ A# P% Y5 e% [  u
#define        MMC5_VOL        (0x0F0)6 }2 M5 s4 _0 s* D
#define        N106_VOL        (0x088)# b4 P) B7 B$ m0 k8 B! N) P- U
#define        FME7_VOL        (0x130)
$ S9 r4 a" x# [/ j( y5 U5 o5 Q4 L, Z7 ?
APU::APU( NES* parent )
5 ]% K# E4 a6 A  C{( h: W+ z- }7 \" ^
        exsound_select = 0;. E) I7 h" f" K( O+ b1 M' |6 J0 z3 |
3 [8 u, Q# ~/ ~; W) P) x
        nes = parent;, a' S% Y, o7 b4 J+ _9 F
        internal.SetParent( parent );: |# y. p3 u: ^# D

- `) k1 m# N' j7 C        last_data = last_diff = 0;, Q& m5 d5 Q, M; y
/ P) K9 Z( X& U
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' @% M, l5 A* [! s4 J; K
4 N( J* m4 C0 X3 e  [( F        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: K' o! k! N$ Q, i; d7 `- l0 I/ q        ZEROMEMORY( &queue, sizeof(queue) );
, c0 |7 W5 M/ D( ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );; F+ K* n' b0 j8 b. s" q7 Y

. f! J# o) L6 h8 f. `; w2 z        for( INT i = 0; i < 16; i++ ) {
' z4 k2 R: j6 W                m_bMute = TRUE;
. a8 N  A. i6 t9 S1 ]0 H7 j        }8 a0 Y2 x; I. O$ k
}
  l4 ?( I: {6 O5 P
: G. m, X6 J6 q8 M& |) u% q* e, e7 [- kAPU::~APU()# H; K& o. B5 J, I5 R# g0 [5 U
{3 ]7 D) l1 y; w
}. _: `  I6 L5 t& V, D! r, O
8 x- o3 [" z7 J* w' z5 S6 h
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& p" g9 y! H- J7 q8 g4 [/ s+ E; `{; ~2 \1 W5 @/ v! o3 I/ z: e6 z
        queue.data[queue.wrptr].time = writetime;
. q' ~) c% ^- l2 X        queue.data[queue.wrptr].addr = addr;
9 o4 Z! D: q3 A7 d7 d        queue.data[queue.wrptr].data = data;$ o# V6 D" z! E: g6 }: Q9 J* _& V: E
        queue.wrptr++;
0 f. ]8 G( |2 T( [/ e" N- |        queue.wrptr&=QUEUE_LENGTH-1;* H* A# A' N4 I! @; N3 ~5 R: q# P
        if( queue.wrptr == queue.rdptr ) {, J! R( n+ e7 j! c$ ~
                DEBUGOUT( "queue overflow.\n" );3 I) i2 m9 E! \8 [% u) C; N
        }
3 Q  @  d( }+ Q# z4 h}
( N6 H' o4 l( T; V* y! [0 l, x! U) o3 Y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) O+ H) a' e4 v' t. s
{  s+ a$ q' E2 ^7 i2 ^* O) w
        if( queue.wrptr == queue.rdptr ) {) J. n3 l7 j0 Q0 u7 k4 P/ e4 w7 l# `& ]
                return        FALSE;- s- E" w* S3 a% A$ g) Q/ C$ n2 F
        }
$ I, h& z* g- s- N% S( |        if( queue.data[queue.rdptr].time <= writetime ) {& T2 y+ }% N6 }2 `( I8 h
                ret = queue.data[queue.rdptr];
) o- ^! D! w5 w: Z  h) M                queue.rdptr++;
4 ?7 f8 Z: V; `                queue.rdptr&=QUEUE_LENGTH-1;. b3 E7 P5 W  u3 m# L4 w
                return        TRUE;0 V" k3 n6 ]! \& E
        }
0 u6 }* r- a* ]4 Z  l        return        FALSE;& Q+ x0 l5 `+ r+ s' @: Z  x
}
' n4 H! o" X' g  l. B9 _
2 U0 O; U6 c$ A" y3 y0 o5 zvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )7 j* H- ?0 i- v1 b" q  d* r* l% Q
{
: X1 m& C9 i$ G5 B( U1 K  F4 K8 {        exqueue.data[exqueue.wrptr].time = writetime;" p/ F# D. g+ P- x! H5 [1 K
        exqueue.data[exqueue.wrptr].addr = addr;5 }1 h- c0 E  K, Y
        exqueue.data[exqueue.wrptr].data = data;2 q% ]* d- M% y# T" z5 o7 b1 v
        exqueue.wrptr++;1 Q4 _" U. j* U, F
        exqueue.wrptr&=QUEUE_LENGTH-1;
4 T! [+ e- E5 V3 ~! {5 m        if( exqueue.wrptr == exqueue.rdptr ) {: l# J  ~: K/ t$ V9 `( A
                DEBUGOUT( "exqueue overflow.\n" );
! U4 N( a( F0 P  b0 e# B        }
6 V' m6 o# ]7 B7 P$ S}
- f3 U3 U! n2 s/ M+ F6 ]% h2 }# K* Y. _: M' {7 s, b; Q9 i" z
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' Y3 I6 `0 U; i+ Z. K( E{
$ V+ G+ M( S7 m) A: x# W        if( exqueue.wrptr == exqueue.rdptr ) {
) r9 ~  w+ x' p$ i, e! t                return        FALSE;: }4 ?! `3 N; a
        }4 Y" u& f) s" M( D; h
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
: J( ]2 S! }$ C+ _                ret = exqueue.data[exqueue.rdptr];
+ [( h: u% o( a8 b                exqueue.rdptr++;6 }2 L! I5 F" H* o7 h7 E# _
                exqueue.rdptr&=QUEUE_LENGTH-1;
$ s  z% F8 |4 C6 ?/ s                return        TRUE;9 U; ~- Q( a* M) E
        }
1 X! y4 @0 O: l3 t! F/ F        return        FALSE;- P  W3 G( p/ M& K2 K
}* S  J: I8 G& H( L8 a
; c. ~5 y7 A6 ?  ]2 x
void        APU::QueueClear()
" E* X6 T+ W9 D# `3 J$ y* ^& i0 M{. H' N# j8 e! f! t' _& E* Z
        ZEROMEMORY( &queue, sizeof(queue) );# s- u' t3 J7 W; L* Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. J& [. s$ o! m6 Z$ Z8 g9 R' O4 l+ p
}
2 V( i! Q# U* `( t/ D3 o8 p; d
/ b+ }. v) ^+ F0 q" _  w5 Yvoid        APU::QueueFlush()
: b: ?* A9 T. ]( g- H7 Y{/ H* V0 o$ e7 r- t, m2 ]6 d6 q. m
        while( queue.wrptr != queue.rdptr ) {0 T& l; N) a  G/ Y
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );! z' V# \* N5 d8 y
                queue.rdptr++;8 H5 p& Q5 ~& P8 ^
                queue.rdptr&=QUEUE_LENGTH-1;" P; `, e! O: A4 `% [  u# s0 m
        }) I& Z/ ^: j' F) t* U4 L

8 u, Q' I& d" d        while( exqueue.wrptr != exqueue.rdptr ) {' N3 V+ t2 L6 H. W% @9 L- ]+ W" i  w
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );( V; S% r0 X3 t0 S7 R  r: w
                exqueue.rdptr++;- V' a0 t3 q4 [
                exqueue.rdptr&=QUEUE_LENGTH-1;
* x& `" O1 y0 v: j& l" {- `        }
" }* g* q0 M2 b! e' E$ b* e}  v5 c) t0 R* P. {, H3 g- _4 k* Q' P. w

* ?$ r3 g1 [; c- s. o3 Q" Avoid        APU::SoundSetup()/ ~* z1 C+ l# J1 Y; ]
{
2 G9 X* @& @) b- Z- n        FLOAT        fClock = nes->nescfg->CpuClock;
6 b# f. x% g, ]6 l        INT        nRate = (INT)Config.sound.nRate;
+ B3 R0 \1 W$ Q& w- q        internal.Setup( fClock, nRate );
0 {: f( L, H; V* \. T3 ?, W$ ?7 l$ ^        vrc6.Setup( fClock, nRate );0 ~8 X! v$ ]" \
        vrc7.Setup( fClock, nRate );  N6 k4 F- c  M# A  N8 ]* |
        mmc5.Setup( fClock, nRate );/ k  g! S5 n  {/ m: ?* K
        fds.Setup ( fClock, nRate );
( G2 s- J( d$ G: M! j        n106.Setup( fClock, nRate );& V% \: G: F0 a6 K& D
        fme7.Setup( fClock, nRate );
0 E& c1 d7 ]# H( \: N. I3 M$ V}2 X, @! s1 P& g  j8 V" I
+ Y. P3 S& Q5 `
void        APU::Reset()/ B- @2 j, E$ |" i
{# f) D# y4 A* S) l
        ZEROMEMORY( &queue, sizeof(queue) );
/ _* i! U0 A' H  L$ s+ {" f2 h- U        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 t( m* U% H* f+ J5 u5 Q8 D* F# |6 n* m- |& ?
        elapsed_time = 0;. N" H( [, K4 g' p0 t" Y

+ w- `9 Q! i; K+ W4 [        FLOAT        fClock = nes->nescfg->CpuClock;3 {( n- W: B& B6 d
        INT        nRate = (INT)Config.sound.nRate;( |" x$ e" j+ y% Y2 o0 ]
        internal.Reset( fClock, nRate );3 `3 U$ s2 S. w
        vrc6.Reset( fClock, nRate );! N" u7 {* V2 w, d9 k- w
        vrc7.Reset( fClock, nRate );
; Q; E( |4 V- F) N( U' R        mmc5.Reset( fClock, nRate );
: E& Z8 f6 `, f        fds.Reset ( fClock, nRate );" M. `" Z' |2 }) E. Y
        n106.Reset( fClock, nRate );
# p. v3 `8 Q" r) S        fme7.Reset( fClock, nRate );4 h3 a1 a' @! t1 I. n/ u) o

7 p9 n! B3 ~# Q8 N2 ~5 A8 k* l( Z3 q2 M        SoundSetup();9 `3 f5 b5 b1 i" z. D/ U# h
}
  [. \4 _, m' H& y. g7 l/ j" C
+ a  j% q+ {: e9 @void        APU::SelectExSound( BYTE data )
( l- e6 @( q; v( c, `" M{5 E7 N, ?+ s" d; Z: o
        exsound_select = data;- {1 F4 t5 Q1 N$ y; C* f) Z
}6 l; L0 U: r  h4 G1 i3 ~

( f" W) I8 R% U7 ^( C1 {. hBYTE        APU::Read( WORD addr )9 b7 J4 X9 ^8 }0 Z) k
{
2 h2 e, N4 t1 @        return        internal.SyncRead( addr );# W! g. c5 V8 c- ]6 |5 p$ s
}$ [+ g9 P6 K# |

* Y; D& r1 b# [. ^9 P# }. d; wvoid        APU::Write( WORD addr, BYTE data )/ l# I  V  Y4 P2 C/ [) p8 Z
{; C8 f- {6 e) W9 X4 n( k0 I; A
        // $4018偼VirtuaNES屌桳億乕僩
8 w+ j  s& }; f3 ~4 L. o( o4 r        if( addr >= 0x4000 && addr <= 0x401F ) {1 y1 ?$ K' o+ M" _3 q
                internal.SyncWrite( addr, data );; ?; V, W  J8 _9 b- g4 H5 k
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# v) e1 A; W' c; Z        }+ _& h. J: V2 s/ p# a* `' \2 K4 k
}
! U3 r8 ?: f! o! t" T: H* ~
6 _" F" s# R- gBYTE        APU::ExRead( WORD addr )
3 |( t) ]7 Z& u# D{
: s  M5 }( Z" z3 w% e  a- NBYTE        data = 0;$ U$ L# F. U) x8 C+ }8 v" E
/ m6 o: g8 i5 f& z
        if( exsound_select & 0x10 ) {; `$ X9 s2 P0 A7 i- }- [& j; N  C
                if( addr == 0x4800 ) {9 y3 [0 N. A% ?- {7 ^: f( c
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
& ~/ X" }! j" _# g9 c% n. l                }
. H& o8 t' C: l+ f+ Q        }
; D" W0 \4 A6 }/ h$ f2 E        if( exsound_select & 0x04 ) {
! Z2 x7 b+ I6 j. f* k6 x4 o                if( addr >= 0x4040 && addr < 0x4100 ) {
$ R( x4 o% H7 r, V, q: L                        data = fds.SyncRead( addr );5 ~+ w( a, c; Y7 ]: o
                }
. n( \. Z7 ], w5 M8 B: e* Y        }
, c  h* j' e) _2 h( f        if( exsound_select & 0x08 ) {1 ~8 t% K, a) o9 @. d9 V* ~3 x
                if( addr >= 0x5000 && addr <= 0x5015 ) {. r1 v# T( F/ L
                        data = mmc5.SyncRead( addr );
! G9 w; t& W9 s6 ~; y1 F                }
2 \, I* P! o1 Z$ A8 @: H        }
" L  i6 C% O5 v+ h9 @2 R" B/ V
& a4 l2 p7 H( V& m        return        data;
$ Z" u+ a2 T- c' T% G) ^}
9 Y' J" a5 C3 D7 h# N7 [) E
. J% ?: p; s, F5 M' ovoid        APU::ExWrite( WORD addr, BYTE data )
1 z& S8 F8 J4 B& g2 T7 Q+ p' y{
3 Z# l" s$ W1 w# y2 g% Z& [        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );* _1 r  }' ^, P: p8 E+ j4 E3 B
# p* x' N$ T9 R4 l; {( \! Z: l
        if( exsound_select & 0x04 ) {
/ z+ f% a9 p9 t7 Y7 C( L                if( addr >= 0x4040 && addr < 0x4100 ) {
6 l2 _$ Q& t7 o) y/ |1 l1 b' m                        fds.SyncWrite( addr, data );+ ~- Y) {# |# \) x/ D0 n7 {
                }
9 c  p; r& Z4 u7 g+ p7 Q        }
4 X4 y, a* E2 R' J  ?  U0 r
0 A7 Y  t1 K7 I6 @1 Z* s        if( exsound_select & 0x08 ) {
$ @9 R: A+ i" q, T4 }) J                if( addr >= 0x5000 && addr <= 0x5015 ) {
. s4 Q7 _+ J& ^5 S, D3 f* U2 e                        mmc5.SyncWrite( addr, data );
7 s, A4 l' d% E2 @# I/ B                }
% p& q' v# J$ l6 R        }. c4 Z' y. `' @5 |/ u/ `" W
}( \3 q% t: e. T7 \+ r0 i8 C& h
# Q; b* z4 E9 Y, H3 [5 Q
void        APU::Sync()
6 A2 g2 P* x4 A4 N% X{4 w0 ?3 N; G% q; p% N
}# i  Z& Z  p, k0 e  k
6 o9 f6 f; u1 o% }$ |4 @: I1 T: }) V
void        APU::SyncDPCM( INT cycles )7 E5 g# @0 ^0 E
{, j  `( @6 u% }  _
        internal.Sync( cycles );
& R" L. u# }9 n: R2 |, U! k9 N3 b# [6 J
        if( exsound_select & 0x04 ) {
2 ^7 ?; u; x$ [0 x! H/ {                fds.Sync( cycles );3 S5 [# e& f( p9 G( n6 u: N5 {
        }
/ ^1 w/ {+ }! k' F, S' d9 ^        if( exsound_select & 0x08 ) {
1 @0 j" c1 f3 h! y                mmc5.Sync( cycles );
5 N; x$ m5 v( h- n2 x. n. ?/ W        }+ O/ z" F' I$ f/ \
}2 {" s/ M7 i, w  i* L/ S# k. X
) g% m/ q6 q- x8 P: u# {4 Z% Y
void        APU::WriteProcess( WORD addr, BYTE data )7 D- z5 L! M" C$ `. g1 o" E6 u
{
6 {1 F3 f7 V5 A) @+ R- g        // $4018偼VirtuaNES屌桳億乕僩
, E3 u# }2 \( p- x, ?# q6 c        if( addr >= 0x4000 && addr <= 0x401F ) {0 n; q' E$ }# \; y) A
                internal.Write( addr, data );
0 \' g, A' `' Q- \        }2 _3 c4 ]: k7 U8 M2 ^; ~
}1 x: }* G( ?( ?- N: Q+ B# }
5 V  C6 }4 r6 D' v
void        APU::WriteExProcess( WORD addr, BYTE data ). c! z. e! D4 S5 M2 a
{2 X, r: b7 R1 q' Q$ W
        if( exsound_select & 0x01 ) {: H# a6 [! V) x- g# ]9 F2 j" K
                vrc6.Write( addr, data );
' t& ~+ [2 a% f- ~: a6 R' {: V0 n        }
7 P+ Y; R. {- [# M4 r        if( exsound_select & 0x02 ) {: F0 j$ T! ^1 |# D7 a- l8 F' c0 P
                vrc7.Write( addr, data );
( A0 r# O* c* D' c        }; n5 z4 I; d$ _. ~8 k' a+ Z* A! w
        if( exsound_select & 0x04 ) {- t2 \2 u& K, @/ V; H
                fds.Write( addr, data );
! W6 ]: q, e$ M" H' \( X! q        }/ F$ D! Z! C# |0 O: H9 _6 d
        if( exsound_select & 0x08 ) {* c( h$ r7 ?' A' j& G- v
                mmc5.Write( addr, data );) V9 k! i' ]$ K0 P1 u9 P
        }
1 d$ ^; W! k+ U  O1 E        if( exsound_select & 0x10 ) {8 d, e7 U. }( X- d. H  C& F
                if( addr == 0x0000 ) {/ e6 I% @. Q( J( ^9 o1 F
                        BYTE        dummy = n106.Read( addr );% ]: K2 W4 P$ b& b/ G
                } else {) q/ z% Q2 |8 W
                        n106.Write( addr, data );; w5 u' m# b; B
                }8 j. F1 |. c& }& s. X9 B' E$ x4 z1 I
        }
& V$ ]  m7 n% Z4 C        if( exsound_select & 0x20 ) {
2 a6 U, E6 k* u) W- Q3 B                fme7.Write( addr, data );
1 @$ E7 a5 Y4 X        }* u; K1 ^$ h8 u! S" g- T7 c
}
* ?, J0 n) J/ Q) N8 D- o8 T* ?' @; c& Q2 g& G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
8 a' ~; M( C/ z- u{
1 m2 O7 C5 M* J' a' L0 n6 AINT        nBits = Config.sound.nBits;
( ]$ g9 l2 a1 t8 k5 N' I/ E6 I1 W8 t; iDWORD        dwLength = dwSize / (nBits/8);1 Q) y) ~7 Y% {: S' P
INT        output;! R6 E7 ?- e/ ?  q
QUEUEDATA q;4 u2 G# x. U/ }
DWORD        writetime;
3 Y/ }$ w2 I3 ]  O* `! F+ p- o- Y0 S, c: m" d; ?3 z- r
LPSHORT        pSoundBuf = m_SoundBuffer;
+ g" P# Q4 g# g" b5 z/ A; A0 s% p, DINT        nCcount = 0;& o! ]$ \! Y  s" ]' W- s6 h/ w, _
0 u: r  e$ d2 D* N+ j1 t1 R
INT        nFilterType = Config.sound.nFilterType;
: W& f2 P$ A+ a0 {, f3 S7 n9 E/ j3 |- l
        if( !Config.sound.bEnable ) {
% ?6 S# o0 e+ \% B$ Y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# j" J9 \+ I! P! \4 F, H                return;
5 j/ ?6 A( t/ N" _% ]/ A* d        }% ~, {  h; [8 s! M4 f! B+ P4 z
9 x2 f% |1 M$ t0 }2 ?/ i
        // Volume setup
- l6 u9 Y5 k1 i5 H* J6 B% a, f7 p        //  0:Master
9 H1 J* l! @5 X& }- o) b        //  1:Rectangle 1% y, S: ?' b9 d2 O" E, S8 L$ N4 z
        //  2:Rectangle 2
" B* W+ R& F. b' W5 y5 }( X+ d+ Q9 _- m        //  3:Triangle- H; R  Y$ V$ k
        //  4:Noise) ?' X# o" j! l3 J; y2 b. W
        //  5:DPCM+ z, r2 S! `  }( V* y6 J9 `* @0 l
        //  6:VRC6
' }! B: p7 b/ w& q4 L+ n        //  7:VRC7/ I! H8 }' [2 W
        //  8:FDS$ f  l. D1 D7 p) J( a  D- }4 e
        //  9:MMC5# ?6 @1 g  T# J& G" d9 [2 z* D
        // 10:N1069 I& \* _* m  ]: A9 a" I) T0 i
        // 11:FME7- B% f5 T/ @8 |7 Q* u
        INT        vol[24];5 F7 ^6 D: h/ A% E8 w$ A: ?/ Z2 J& u
        BOOL*        bMute = m_bMute;
6 g2 E/ s6 |. N        SHORT*        nVolume = Config.sound.nVolume;5 R) A  a/ p5 ]" N* w, F% t
# G3 @1 ]9 K+ T- J( N- y' V) c5 \
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;3 t( z0 ?. |) T* v; t) A2 }% p

- l  Q4 Y6 v2 r5 R" D: p0 e6 R        // Internal5 H) L3 q; F: |* n& N5 r
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ E: J' g! z# Q! \# I
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 o7 t  o4 s! S8 E) t" z  m        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;* d9 v; `# W' o* q1 N+ A* ]
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
. q* k8 ]6 r' W2 V6 [# e* M7 R        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. ^9 R$ X' r9 a# x- N8 v9 Z% z# q1 p; r% S' i: \
        // VRC6: {* g2 f4 W3 v6 S& l3 {
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- ^, S' `4 ~, Z" l, e( _
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, _: I+ d' m+ x9 Y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! f, w1 Z4 V0 j. c5 P
2 L- h# k9 j4 A4 q        // VRC7
- k3 b* L' \" @# j8 v        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
5 q9 Y  [. M  @, ]1 R. B* @! e9 ~! b. {5 U  G! ~% ^
        // FDS
% r+ Q* i! _0 \# ?7 T1 t3 d        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
4 J( ~) J9 `% q% n' a. z3 H5 E# I# K3 M1 |- p+ Y0 x/ @
        // MMC5
5 O' s1 g6 ^; G        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) G$ F* A" W4 Q
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. Y$ M& H# c+ S" ]* B5 D& j9 z
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% i! D$ [7 S, O8 d& p# H. u7 `6 W; G9 T+ |* r0 m
        // N106- U. @0 R( `# t" l0 s; L) w$ A
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% T' [# H% `2 z. v) Y! {! K% F
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 U6 x, W5 `9 [
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 \3 k) x0 `: c' X        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, p+ A$ T, |7 L% d        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 `9 M- O5 ^- y3 E; s1 N! ]: X! w0 _        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 E& h4 X; t8 p. B* ~) Y* Y# ^9 q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 w, h' j' \) A+ S& `. X        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# A2 B7 j: M7 |

( \1 s8 S9 U# r; B0 r/ [7 W" a# P        // FME7/ e) R4 Y' g& V. A2 l, a
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ h. R& K4 q* ~/ O5 l$ U0 j
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 B% o' q0 v4 g8 ]        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 o/ s% l/ ~# u" ^% D2 p2 P/ Q3 X" q+ V4 d
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, M* H2 Q- n3 z; q
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* R% b2 k* q  x$ C0 U5 o4 o7 l7 E. m' V. r* Y* f2 O5 G
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
" l7 l/ b6 e. k7 J) u% r        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- S# N- D( M* y$ Q( u; ^  }7 c) `
                QueueFlush();  u- @, g* B) t  U) Z8 e0 G2 m
        }% D; q7 f" _- i" F% W( \
2 Z. o2 u: J+ o6 H' c( m9 H1 C" [
        while( dwLength-- ) {
) D0 U- Q( J4 \                writetime = (DWORD)elapsed_time;
/ P& @! _. B- d; i- v, Q. Z
# l6 R1 c5 L1 p5 Z                while( GetQueue( writetime, q ) ) {
% ]+ I$ @5 D+ u                        WriteProcess( q.addr, q.data );' v* ^. t! M! B: y
                }
3 [5 W! ?2 J5 u! \9 \4 a4 T9 [. Z& K) C3 _& Q( S
                while( GetExQueue( writetime, q ) ) {5 v! L& H: S, p! |. w
                        WriteExProcess( q.addr, q.data );
! ?$ f0 r7 Q( I' s3 C                }
1 ^( L% b+ k( t
# P% H3 P- O  d  v7 R. f+ K                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
# U4 F) G; E2 R                output = 0;
" c! ~, o( m$ d3 y% ^* U                output += internal.Process( 0 )*vol[0];
4 K% W7 }/ F3 b3 ^* f9 K; f                output += internal.Process( 1 )*vol[1];
+ _" q% O7 r" C2 g                output += internal.Process( 2 )*vol[2];) s' o7 V! {) B5 x8 P/ m
                output += internal.Process( 3 )*vol[3];
1 ~) x+ h+ e+ ]3 {6 ~                output += internal.Process( 4 )*vol[4];1 C$ r4 C" h' e

! A+ z3 q/ |7 G9 ?) y  h8 r7 M                if( exsound_select & 0x01 ) {4 x3 }: @  o' Y( A2 K
                        output += vrc6.Process( 0 )*vol[5];
( Y& _3 p) @; d                        output += vrc6.Process( 1 )*vol[6];  N  ?7 @3 E& ]2 N% |6 C# i
                        output += vrc6.Process( 2 )*vol[7];4 }- p; R! ~6 g5 L' j2 Y
                }% d* `: y7 y4 T* ~
                if( exsound_select & 0x02 ) {& I+ m% B7 z5 g) w/ K  w
                        output += vrc7.Process( 0 )*vol[8];1 C2 ^/ o% Z) L& R1 n/ X8 Y
                }
$ f3 R/ Z  R/ q) x3 r- B/ V                if( exsound_select & 0x04 ) {
$ b, j; }$ E) ?2 ~                        output += fds.Process( 0 )*vol[9];
9 t0 F) }& T3 ~                }0 c/ f6 l) g$ s* V7 u8 k7 N$ u
                if( exsound_select & 0x08 ) {
: k9 u% e) Y# `) v) [: s! K                        output += mmc5.Process( 0 )*vol[10];
+ G* |; ?& x* Z+ W0 x  z/ e                        output += mmc5.Process( 1 )*vol[11];
; S  h6 l  E9 Y                        output += mmc5.Process( 2 )*vol[12];: d: ]9 o) A% h& l# A: c
                }
$ g8 y8 s# p7 D# T& X" N+ M                if( exsound_select & 0x10 ) {
  @! I- z  ]. t: `                        output += n106.Process( 0 )*vol[13];
3 B: g# e" [& Q; k                        output += n106.Process( 1 )*vol[14];5 G- E# D7 |, h& M, {6 _+ p
                        output += n106.Process( 2 )*vol[15];+ ~$ Y% c) h: h8 @, w
                        output += n106.Process( 3 )*vol[16];
7 o( Y1 m& J) t; z$ ?9 N5 G( C                        output += n106.Process( 4 )*vol[17];
+ r' ]+ k0 [4 O8 G                        output += n106.Process( 5 )*vol[18];
3 t& |+ d6 E4 k% p" I                        output += n106.Process( 6 )*vol[19];' H& d0 n0 k3 B6 l4 H  B/ j/ [
                        output += n106.Process( 7 )*vol[20];/ l; `6 P) Z# B& ~
                }
* p! C1 Q4 j5 u3 M; g" B                if( exsound_select & 0x20 ) {$ g+ y) p/ y+ Z6 L7 e
                        fme7.Process( 3 );        // Envelope & Noise
, M, V. Q. [0 P! p                        output += fme7.Process( 0 )*vol[21];
8 c% u4 w$ k' A4 ?) p( @/ N                        output += fme7.Process( 1 )*vol[22];
: {) W5 f! X9 ]' [* J                        output += fme7.Process( 2 )*vol[23];" @' Z! v/ `- _& \/ [
                }9 S3 g4 A( \6 {. {

& Q& |! ]3 J5 ]2 h+ y" J2 ?                output >>= 8;7 s& k: ~8 ]1 F" S- H  J
6 Y2 h: a0 `2 {5 [+ L; Z: n- X) ^
                if( nFilterType == 1 ) {# `) ]- d3 Q$ h7 Y  c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 j/ h: j5 `$ ~1 k8 Y% f& d; O
                        output = (lowpass_filter[0]+output)/2;7 _3 y6 H$ Z4 h6 S% p' U
                        lowpass_filter[0] = output;
% G$ S; s% v2 M                } else if( nFilterType == 2 ) {
- _2 E. ~/ |0 q2 ?& c% w                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ u5 ?; c6 \  R$ {# O* E
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;8 A& Q/ D# b( h# ~0 k7 _4 d
                        lowpass_filter[1] = lowpass_filter[0];8 ?  u' z% @* W7 Q1 C* E& C2 s
                        lowpass_filter[0] = output;
  R$ I/ O  T2 f0 l% u                } else if( nFilterType == 3 ) {
/ d7 a1 O. D4 v  A                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
( `# w/ K1 H1 H                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ ]! ?' {( c+ I
                        lowpass_filter[2] = lowpass_filter[1];
% Q$ u/ c/ {% A! G/ z                        lowpass_filter[1] = lowpass_filter[0];8 i) @5 |  x4 ^" _8 o. I% q, ^4 M
                        lowpass_filter[0] = output;
4 M, t  E& S* Y% x8 [& y/ f1 X" D                } else if( nFilterType == 4 ) {0 d# J6 o; I; a
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
2 y& Q' x: n  ?  w8 d$ [3 e  L2 s                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
, b, y- X0 G' {! J, b" w* r+ R8 U                        lowpass_filter[1] = lowpass_filter[0];
) _! |, `0 m! W; s9 t- D0 v  @) r  U                        lowpass_filter[0] = output;
+ P( C- @( z5 T* O                }
/ C3 d6 {0 }( S; P5 T* w4 N
( x$ X( D7 F$ R; X& R#if        0
- N/ \; o6 w- ^3 }                // DC惉暘偺僇僢僩/ }2 b* x  j6 G7 c/ @
                {6 `, z) W# G4 R: ~0 h  G- E" `
                static double ave = 0.0, max=0.0, min=0.0;
% H1 ]- T) z* U7 G2 T0 M                double delta;) j' g5 z% Z  Z: d
                delta = (max-min)/32768.0;
1 i* |4 i. \/ v, I7 o                max -= delta;: [0 v! M3 a/ b' J9 G6 y
                min += delta;
% a$ g6 m0 L0 D8 K                if( output > max ) max = output;2 K& `& A9 E" K) v7 N# U: ~
                if( output < min ) min = output;$ F5 O2 i! f& m. L  P
                ave -= ave/1024.0;
6 ^0 o1 g8 x2 k% K' V1 A                ave += (max+min)/2048.0;1 O4 ^- O+ U7 K3 n
                output -= (INT)ave;
* B0 ?1 w$ d5 G3 ~7 ]9 W                }
' I" B+ l5 P& @- T: K: o#endif
4 R' X. v' ~4 {, e6 }" Z#if        12 {9 ]1 v8 e# [: Q* I5 v/ K" r
                // DC惉暘偺僇僢僩(HPF TEST)% E! p4 G3 e1 K0 U0 M" @! J
                {; ?; o6 |, A2 _0 C& H% G1 P
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);$ _( G+ p0 I0 t8 X4 J6 [. ^, Y
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
8 f4 j6 L" O* V& M1 C                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# \) I4 F% N( I3 b9 c) J' V% t; j' c                static        double        tmp = 0.0;
& e- i/ D; p' ?/ S& ?                double        in, out;
& }1 x( q6 |/ j3 ^( ]" I
( `( [. q0 `4 p; x7 V8 ]1 |* g                in = (double)output;9 q- @0 O$ L* S* z, ^3 x
                out = (in - tmp);6 E  y8 ]6 n$ W  M* I5 \: w
                tmp = tmp + cutoff * out;
) K6 ]- k* c$ \: w$ G0 u: d3 ?
/ D  i( h! s2 ~; U7 U$ h8 j                output = (INT)out;* L! v- m. G+ i. E+ F; }
                }8 t* ~: X9 j/ X3 a3 W7 B
#endif
0 t  I! @" g6 T$ G* o/ M& @#if        03 s5 K7 l5 X5 D) p. t
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)! y. }6 {8 A$ D6 l
                {3 o6 W. e: s% D. Z
                INT        diff = abs(output-last_data);
) g7 Y, W& @2 j/ b- a                if( diff > 0x4000 ) {
. r3 W/ @; m0 z/ x                        output /= 4;
' l7 k1 \0 v% G- ]' }                } else : x0 f( P$ K+ c% N9 ?5 R: s" r
                if( diff > 0x3000 ) {! e3 F4 o) c  F2 y5 |" V
                        output /= 3;
2 ?2 z0 h  o, M% P, I) C                } else
0 |. Z  X9 m2 b7 W                if( diff > 0x2000 ) {3 ~6 Q, W0 y9 h' u; A0 {# }' }! S6 Z5 \
                        output /= 2;
7 W+ q# ~) K  ^9 H' E; T4 B                }  v4 V' n' _0 ~- P$ G7 U+ i
                last_data = output;
, G- r* b: X. M# C  I                }* {. b1 `% O0 E  @% W( R
#endif9 v! \. [% q8 }  F, y
                // Limit
, l1 q* I- v% G                if( output > 0x7FFF ) {
, K( t) c2 _' i+ P2 u* G9 V8 Y                        output = 0x7FFF;" g3 \/ x9 n7 D( l4 v0 m1 e( L/ J
                } else if( output < -0x8000 ) {, D, K% S% }, H0 H
                        output = -0x8000;
- `- U# q+ H- ]' a( i4 K                }
, d8 u( S" c3 `9 n5 E* {7 n0 b, E6 x2 k1 B! ~6 _0 l& G( @
                if( nBits != 8 ) {; i  s7 ~: K+ @4 p- ?
                        *(SHORT*)lpBuffer = (SHORT)output;3 Y9 s" v! L. [8 ?& C, h
                        lpBuffer += sizeof(SHORT);
% M, X- P0 _4 [- ]% O  h3 R+ J                } else {
" N4 Q3 V) h$ i! j6 c                        *lpBuffer++ = (output>>8)^0x80;
( s# g5 Q- e, _/ K/ r/ |                }
. P! J" j7 c7 p8 }3 }& ~; i+ e/ ?! Q
                if( nCcount < 0x0100 )
. A3 ^, ^- [2 c, F1 Z                        pSoundBuf[nCcount++] = (SHORT)output;
) ?/ Z' M$ g- X4 G9 d8 \
" y, T5 Q$ h8 V) j& v//                elapsedtime += cycle_rate;0 O$ n/ t* i0 K) X) g  Q
                elapsed_time += cycle_rate;
: a: \! p$ d( }, Q9 N0 `2 j$ Z/ y        }( f( X  k$ M  i& _

+ y; t3 v# U3 M$ R% S9 H7 ]3 }% a#if        1( v5 G- b3 u2 z" ^0 H, S
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {* g" S3 B1 e8 q! c2 ~" D( |4 f6 Y
                elapsed_time = nes->cpu->GetTotalCycles();
: m# D. L7 I" @6 P+ {) f2 Q7 s' [        }0 c: ~0 M$ ~7 J7 i; H
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {' ]" @4 T  _2 ^" j/ {2 c
                elapsed_time = nes->cpu->GetTotalCycles();* d; h* F! r2 Y9 ]
        }
2 l5 G& W' W" S6 z; r3 N# [#else2 D0 |: h% J7 ]3 M8 K, C
        elapsed_time = nes->cpu->GetTotalCycles();1 D1 v( E* {0 z% R" f. e
#endif
4 g3 f- W6 q/ M  }. P4 T}9 ^' y, ]+ U& C% T, _

3 g4 Z: i  T( F9 B1 b5 M% e  k5 T# B9 y// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)5 _' z0 s- }; u0 R! b" |, w
INT        APU::GetChannelFrequency( INT no )" q4 u4 C6 ]2 C5 s, P& w3 j
{, z( N' l$ O) I: t& `- j
        if( !m_bMute[0] )
5 `: o. C: P* v# F: Z                return        0;# E* c1 K2 V5 }3 _) T

0 }' O4 i# S( I3 K6 [0 H$ J$ \. A        // Internal
1 g& R8 \$ a1 x        if( no < 5 ) {( P  n: }2 X! }! P) I& Z
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
3 T1 ]! m1 K1 |5 q        }; m& A5 s# Y6 ]/ F4 O$ k6 P6 Y& T3 V
        // VRC6  x. K# K, r; N. g6 Y
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
( ]# R% b% ~" I) b( c2 e% J- t                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( h/ e$ V6 q6 @0 G        }
  z6 U5 K" @( K" ?$ z. d& b        // FDS) Z' U+ r( M, E7 ^2 [  x
        if( (exsound_select & 0x04) && no == 0x300 ) {4 m0 A0 M; [7 @1 C( W9 f
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
  Z6 ~; z, W0 c# c        }
0 ^$ D# e1 E: S% }5 X8 J        // MMC5
+ x  _5 |6 B; W        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
4 d$ E# T# i+ I! F3 b* n7 |/ t* n                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;# _  Y4 J' |+ E5 m. H% O" L  i3 t
        }
4 r: z2 b# j" Z! O* g        // N106
- [( G8 Q1 M1 s* [& }" d        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
6 M: _; o* A, `5 l* X- g, {                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# I; k, ]+ F* U5 D6 G$ g$ i        }" O! P9 v4 c/ z" L
        // FME7( v4 P; q/ }) i$ I$ m
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {3 d, V% ~2 b$ _1 [
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, i0 R/ f2 h) U9 s  ?) k
        }
9 z9 w$ ^& ]2 }* W  D# N7 P        // VRC7
+ I5 i' z) s) k# j$ ~& z7 H) u8 t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 C$ p  u0 `7 J4 Z; Q                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;$ ]4 a1 H/ A/ r' r  ~
        }
! V4 h: R2 t, g% ?8 \        return        0;9 u! o  x) L" }) u+ v5 K2 i
}
; s& U& g" j6 I8 Y8 u' U; N* Q9 \* r( o+ b+ H, Y; m# u
// State Save/Load7 `) {* D) N- q7 {( w; i4 t
void        APU::SaveState( LPBYTE p )
& R4 f% F$ s6 u+ ~. q$ K  ]{
& ^* j1 N( o$ _1 C- v5 V! Y#ifdef        _DEBUG
8 \: x9 N. d0 t0 x7 _LPBYTE        pold = p;5 T& ^0 ~$ c' X* }
#endif
4 ]8 }! F0 l  Z. j. p9 f  I
# W0 G* D* e- U# B9 Q        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
$ b) ?( U; O5 O/ g# @& o        QueueFlush();0 _& ^% L0 a1 ]

& X) ?  E6 m7 O        internal.SaveState( p );* N! O9 m. e; I5 S6 i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ L" g: @: [( g/ X; R2 c: M  K7 ?- G! U9 @  J
        // VRC6
8 z( T5 S1 c; n+ s# u# n9 m9 b        if( exsound_select & 0x01 ) {
0 h6 A( ?, y0 R6 E0 b, t" L                vrc6.SaveState( p );2 B, ^. t% ~& w. ~' z1 @# [1 n" t
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 k' {5 c! D1 w4 x6 A4 A        }) h1 e5 F" Q; q6 y- R  e( a9 y
        // VRC7 (not support): U8 l" p: K: f
        if( exsound_select & 0x02 ) {
( L9 m+ `! T  N5 r/ h) Y9 r$ Z                vrc7.SaveState( p );6 R# D* E. g1 |9 N
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: k$ [1 q2 ]1 t
        }
4 L) D+ y6 h9 i9 }4 H# a% r4 _0 F: {        // FDS
* V/ g4 c7 d1 u+ S( G7 s* h        if( exsound_select & 0x04 ) {' w' ^( i# R3 ]0 o0 C" u% j
                fds.SaveState( p );
) W2 t8 ?/ G- @1 }$ i                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* }5 B$ ~1 _2 ]1 t) ^        }
8 A7 Y1 P: a" f$ Y: x: N; m7 g" }        // MMC54 Y" V1 D: d! g) x
        if( exsound_select & 0x08 ) {  `0 e" i( N" [( z6 e8 c
                mmc5.SaveState( p );
2 t( G, A# [/ S$ C  _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& g4 u, |% ]% D% k. n
        }
( u7 Y; N8 x& z( N3 J% `7 t" \. O/ ]        // N1068 t: k, t, n5 ?: v2 y/ {
        if( exsound_select & 0x10 ) {6 N; e- g$ k' t8 p" A
                n106.SaveState( p );$ \: q: Y0 G- u- y( ]
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 j# J/ F: N7 a6 Z6 u- F# K        }
( O3 T4 u3 h4 U* A- @        // FME71 j1 q' |+ \5 \7 K3 O: k  c5 z9 \
        if( exsound_select & 0x20 ) {
. L! J' h$ J9 x                fme7.SaveState( p );
) D% j* n- z+ N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 ?' c+ W; K% |$ Q1 u& o+ b9 F1 M
        }, Q: }+ f3 F/ e0 |: P; a

/ J* X  ^" R. t  w: ~1 k9 x#ifdef        _DEBUG
' o/ Y! u3 O& z* a5 {" TDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
& ]; m- C) n# i$ Y- B) J# L! [. {#endif
. U! F, ]; ^& F3 _% u2 Q! l# A}
8 e  a! Y$ Q/ |& [" N
+ Q" ^: G# }6 S+ g" q! svoid        APU::LoadState( LPBYTE p )
& n, I  d) A2 ]3 f. l1 n{
' p: ~  z" a! K& M        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
6 d) j+ M7 N( `: E$ g5 ]6 B7 x, k        QueueClear();
' \8 j- J* {2 W7 }1 r/ T7 `, A3 M6 L0 F9 c
        internal.LoadState( p );" B! p9 U- l6 L# w- @$ r
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 |/ w9 _5 ^: j% c" R; M* T4 l- r7 ~  H. y$ G; f, P' b* I4 U
        // VRC6) K# ]! l& i( d/ m$ }, s
        if( exsound_select & 0x01 ) {; u. ]' i- g7 C3 ^. h4 D
                vrc6.LoadState( p );3 K: g$ b& N2 n6 {. D2 E) A/ E9 ]
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ p; B) R6 X  [" e2 }" f7 ]
        }
& \' `$ a. E3 p2 X1 x3 H- A) ~        // VRC7 (not support)/ F0 n9 ^% |) R
        if( exsound_select & 0x02 ) {
0 [; I9 z  B, m$ Y                vrc7.LoadState( p );
2 Y8 F1 C6 k: h- t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
9 ~' g2 o5 @& U        }
- A- U, e- \3 f( y        // FDS
) z6 y: O( J" T" X2 ?. p        if( exsound_select & 0x04 ) {5 h( D/ }- y8 l; g: C
                fds.LoadState( p );* u0 U: p; a' T2 M7 j! L
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
; Q* I! N" P7 z1 h8 W        }) m2 {: z* f/ `, D6 V- g
        // MMC5
$ Q$ k+ G4 P0 g( e        if( exsound_select & 0x08 ) {- d7 C; m# v+ A. e9 J0 ]
                mmc5.LoadState( p );
$ F$ W, u; C% O( z# Q( b0 v0 P                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 _! E3 c9 H' `0 \& W. u; j) l        }
+ d" z8 y+ @: _* Q4 T+ n        // N1065 r. }) I" b# U' r
        if( exsound_select & 0x10 ) {( S8 `8 W7 h& P; R  k( \( C
                n106.LoadState( p );3 o9 t- D) n5 L. L, i4 g" y
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& O" t" M4 i3 L
        }1 u. m& Z6 L, X2 C
        // FME7
' ]5 H2 t/ A' g6 a, c        if( exsound_select & 0x20 ) {
! b& [! F/ ^1 _* Q7 w  @                fme7.LoadState( p );( ]8 e# V. O" a9 {' S
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding% s! ]3 @. V/ z/ X7 R
        }6 J' u# P4 O4 ?$ B
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 T& \1 l, I% M  X7 @1 K& P) g2 o0 h可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 M+ M( g! ?: I% ?+ J
感激不尽~~

) W0 R  y! _3 t6 l* z* [% Q恩 我對模擬器不是很有研究,% B9 X6 m( C* q7 p! |" _
雖然要了解源碼內容,可能不是很困難,
/ T$ @8 s. w! L  ]6 J3 W7 O不過還是要花時間,個人目前蠻忙碌的。
+ \& T3 A( _8 e' H) }  E  V9 s3 T9 M, R$ v+ s; }
給你一個朋友的MSN,你可以跟他討論看看,, o1 {% ]* Y# L& D
他本身是程式設計師,也對FC模擬器很有興趣。
& f& W% I% L, _5 m5 E. [2 p3 ^6 f1 |8 f
MSN我就PM到你的信箱了。
7 n- c5 n% I8 G& X9 G' _% L0 |
$ }) ?2 V( C% E! 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 发表 7 j% H. }  _% O* L- J+ j
呵…… 谢过团长大人~~

+ d6 L" t2 ^2 _; C/ S
% V+ c% t0 P' f2 I" V; Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ Z3 G' X! b+ z  F! z团长的朋友都是神,那团长就是神的boss。
9 V9 m' a) n6 ?. d+ h" R* ~
哈 不敢當,我只是個平凡人,
2 w; O0 i, O, I8 Q. ~) t' p& @要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙6 }& V0 H5 a* K2 L5 U6 T5 M5 H
ZYH. G( E" I1 I5 C! B0 S
QQ:414734306
* Z0 t3 b9 \( c0 @9 v! P7 G. @0 d5 UMail:zyh-01@126.com, w; e  E  s, B# _2 L' {" }: I

, V9 D1 X6 t7 U他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ) K7 o8 G4 u  y8 R' h, E: a4 }
再次对团长大人和悠悠哥的无私帮助表示感谢~~
& s; Z* d; H& q* F4 Z2 f/ S
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-31 02:34 , Processed in 1.177735 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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