EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
- P( d6 p, y" w' ]+ ?" mPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 o3 f5 Z# ~' N) Q/ Y" q# M, K, K
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% z5 D: i" y) ?! V3 l这里有相应的模拟器源码,就当送给大侠了~~2 i0 j3 U+ G2 E5 R5 v
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
+ u; }! s* c" {& ^. F+ {2 H能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, S$ _# q5 Z( ~楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( u6 m* N. n" J, [, y这里有相应的模拟器源码,就当送给大侠 ...

: y2 x$ c- `+ G  D聲音部分(Audoi Process Unit = APU):  u: S/ Y: i9 q: w7 H
.\NES\APU.cpp% H! J' f) w# W4 a* O! E! Z
.\NES\APU.h( ]5 \/ Q: o7 e# P( B3 q

' }8 @) h) ^# j( b. |
# P  o- v- J2 ?& E  I5 b0 C影像處理部份(Picture Processing Unit = PPU):
* V6 i1 E) R5 @0 e; j7 X0 k% t1 \.\NES\PPU.cpp' G. c/ c; Y, p
.\NES\PPU.h
9 N$ P; Y/ L0 s" r3 E7 i
0 g6 m; y& @9 Q3 N+ s如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
/ I6 ?' u' x. E. q( a/ |0 d  l(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) T1 U( M  l5 @: n//////////////////////////////////////////////////////////////////////////
" t! z9 D: A$ f& Z, o7 s* _- S, ^//                                                                      //
: K/ Y2 s  d0 w% z+ H; X//      NES APU core                                                    //
1 _" I$ ^3 ~8 d! v1 \2 y//                                                           Norix      //' Q. j4 d6 r: X; ^5 d
//                                               written     2002/06/27 //& m" f# z2 G4 E9 M
//                                               last modify ----/--/-- //
0 l4 }! A1 h- B. f9 Y8 W, J6 s//////////////////////////////////////////////////////////////////////////
7 |/ j9 [5 X( d, l- ^/ v#include "DebugOut.h"
/ Y/ f' D% A4 {  t# V$ t1 a#include "App.h"
! W6 x" U8 D9 l8 b) w! C#include "Config.h"9 z: _% [1 y8 D8 K4 |2 b

8 ^0 \9 N$ m! e6 Y/ m#include "nes.h"
" V2 A! d4 K! T% u/ p) L" `#include "mmu.h"
1 `- X/ S+ l. H#include "cpu.h"
  W, y" C8 F4 B# ?+ H#include "ppu.h"
# B9 S" @; |  R#include "rom.h"! M7 S" }, K6 B9 h! q, l
#include "apu.h"
' P, D5 d3 z/ H% M$ C, Y1 q' d
5 \# r1 T4 u9 N" Z* b' o// Volume adjust
$ u; y; h% w( ]// Internal sounds
) X2 D  L% M1 s#define        RECTANGLE_VOL        (0x0F0)
  a' ]" \: [& e6 W. @#define        TRIANGLE_VOL        (0x130)* e5 C( w7 {4 T) U0 y
#define        NOISE_VOL        (0x0C0)) s& U$ a' F$ m' s
#define        DPCM_VOL        (0x0F0)" ^6 B$ Y4 h& Z7 Q! Z; G* m
// Extra sounds9 ~8 M( B( j2 v& p7 n& z- d
#define        VRC6_VOL        (0x0F0)+ y' s; @9 d) e* t2 Z/ K- G
#define        VRC7_VOL        (0x130)
4 C6 L% F4 i5 ~- Q. ]( r6 g2 Q#define        FDS_VOL                (0x0F0)$ Z5 m& E; \/ J1 v1 I/ x: j5 r
#define        MMC5_VOL        (0x0F0)5 M# @0 n9 v" a7 Q  {
#define        N106_VOL        (0x088)( k* A, Q. ^1 E5 d7 j
#define        FME7_VOL        (0x130)
9 ^& ]& X0 w" |
) _1 r3 D+ c1 @0 yAPU::APU( NES* parent )4 u0 {; D* ~! }9 l( e
{" w  L, K$ J7 d3 R& v7 u
        exsound_select = 0;7 Z4 F& M2 x6 k4 Y7 C2 ]. B
" Z0 P( R! o  T4 y" h" Z7 d
        nes = parent;3 p, u7 N: n/ G* v9 q- j
        internal.SetParent( parent );
, c; S' q8 j, b2 X: g
4 S+ o, a; K$ a. [        last_data = last_diff = 0;( S3 A& Q. [; _9 R$ l
$ c4 p. B+ y* Z9 S  c
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
( g: x  x& `9 Z' f4 v: @
% t5 D1 D3 J  S- z        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );; F& `. T0 `) p0 Z# x! q. n
        ZEROMEMORY( &queue, sizeof(queue) );
2 c/ k* H. o2 g6 t$ H; }        ZEROMEMORY( &exqueue, sizeof(exqueue) );# `6 O# z9 i4 R2 B

' @! b$ u- I) S1 w' n$ o  A        for( INT i = 0; i < 16; i++ ) {
4 X/ g; C" n8 L# ~- c$ Z2 X                m_bMute = TRUE;7 Z% B, k* n  L% @/ P
        }4 o; p. k0 I0 n& f+ f
}8 }) o( H3 |+ d; c* S, B! O
  s. `" d6 r6 [* U" B7 F+ c
APU::~APU()
: f5 _6 H+ F  t5 v' }( H3 r{+ @' L5 P2 w" V' `5 S3 i6 c; j
}! ?& P7 B% L5 R4 K0 E

( c8 r, S( _6 G7 r7 Avoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 m# U' s$ c) M4 e% d1 f
{
" t' V3 m: L3 c' X. r7 r" y6 b        queue.data[queue.wrptr].time = writetime;& a0 f. S# `3 r# H  m. P
        queue.data[queue.wrptr].addr = addr;
6 I2 u. i# g' a0 p: r        queue.data[queue.wrptr].data = data;5 [$ s: @" X) f- U
        queue.wrptr++;5 u. N. S  I% v% c# p1 @! o4 l5 w
        queue.wrptr&=QUEUE_LENGTH-1;( ~' q/ ?0 e$ Y/ r, V: @3 q
        if( queue.wrptr == queue.rdptr ) {1 p5 a9 p  ?' C- Q( `  W% w) i
                DEBUGOUT( "queue overflow.\n" );
% R, a& U& ]! r+ B; A) P. G        }  }  i0 g2 {" ^1 R# `' b, O
}
! n6 e2 D4 X  {) X3 A' {$ m5 x
0 q& }9 O2 X' aBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )$ M/ u2 h# u$ g7 |
{( z9 M" O9 L/ W) @, y" h2 d" C7 H* S
        if( queue.wrptr == queue.rdptr ) {" W3 g5 U, h( _2 ~& U  Q" q# s/ `
                return        FALSE;
$ v: x! m  z) y1 {6 q7 i        }0 b5 u' m; e0 G# K/ o! ]% @
        if( queue.data[queue.rdptr].time <= writetime ) {2 K2 F. ]. y" ]! y# z
                ret = queue.data[queue.rdptr];+ J* U" b' {- g
                queue.rdptr++;1 Z  s& R8 a2 C, L- r- b/ V3 w
                queue.rdptr&=QUEUE_LENGTH-1;
( d& {$ V: G: |, q: m                return        TRUE;/ V: {# f; r5 z& u8 s8 b1 U2 A/ ~# {
        }
1 G: @7 z; _6 x8 N2 r. G        return        FALSE;5 G0 W3 K" u2 P& e8 ?( [% y
}
3 [9 b2 I  c& L6 I0 B1 v: J% R8 W) L6 S4 n# c' |( c
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )1 _2 \1 `1 ^: K3 Y5 v  N' t
{; d3 N* G5 z' e6 }2 {
        exqueue.data[exqueue.wrptr].time = writetime;  e% q1 ^% ^& [4 S
        exqueue.data[exqueue.wrptr].addr = addr;
7 h) b; ?8 V2 O# G& }        exqueue.data[exqueue.wrptr].data = data;* P& v: M/ O3 p! \5 u; i
        exqueue.wrptr++;
: a+ a, G2 T3 `, U8 w# h        exqueue.wrptr&=QUEUE_LENGTH-1;, w! a6 h' Z( Q1 i
        if( exqueue.wrptr == exqueue.rdptr ) {2 ?0 t0 O8 w5 Y" x' H
                DEBUGOUT( "exqueue overflow.\n" );
3 n! f2 m* q1 f  t$ A0 R        }
- a0 @1 F) k4 |( X6 d}9 B* R/ O8 X% w. a

4 F& K3 ^' F* b  t! p9 Z! a2 [7 vBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )' \9 g$ h( Q: }+ k1 w1 c
{
/ n7 u% d! s. i2 ?        if( exqueue.wrptr == exqueue.rdptr ) {
. b$ S) R% j! I9 @                return        FALSE;
- T+ ^; g+ C, z) K3 N# S1 r        }
: V  `7 h& @, ]9 ~        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% d, J7 `1 n3 ~5 d
                ret = exqueue.data[exqueue.rdptr];
$ z- l( W% p$ [                exqueue.rdptr++;
! o  R8 y6 k6 B9 n0 }* r2 @                exqueue.rdptr&=QUEUE_LENGTH-1;
3 Y' V( g% `# M2 ^) g  I2 D: ]                return        TRUE;
& `! M. C( F0 U. c: W        }
3 {7 H! }. R8 z! |/ I        return        FALSE;
. Z# r) [6 m+ |8 i" k; c: ?}1 H: U3 @, N. S8 `# X6 ?
, ^; V4 ~3 o& G8 r8 m
void        APU::QueueClear()
3 q" z2 t) e1 q, f: b) h2 m{8 ]  K* L+ Z# L/ v5 a; {; `* t, j. k( L
        ZEROMEMORY( &queue, sizeof(queue) );
+ C3 G  Q$ d' Y6 b0 ~7 ?0 L# z& Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );; A8 A4 K1 y' _" Y5 k$ C
}
$ a' Z; {0 E1 V# y; p+ ]( u: G
( l$ j- O- H! m. e* xvoid        APU::QueueFlush()
$ C; l7 m8 e: N+ w6 X. h+ K, n' z) m{, n6 A8 T0 m. }. e. c5 C8 _
        while( queue.wrptr != queue.rdptr ) {; n* o8 G& z% y2 `1 `9 F' e
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
# X' w% N' Z& y1 {8 g# k                queue.rdptr++;& x8 D) R, {* m! I7 M# x7 P: N" I% g0 f
                queue.rdptr&=QUEUE_LENGTH-1;
+ f1 t5 |: ?+ H5 X' z' o9 o        }
( y' `4 P! b* U& c; v0 R: y- j$ C  A& K8 A: t+ j) G) V! a
        while( exqueue.wrptr != exqueue.rdptr ) {+ `$ v; E5 D" U7 V+ H1 y$ i. I& N
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( G: i+ o& r+ v( L0 j* I1 O! [                exqueue.rdptr++;: M$ r5 _, {$ h$ y0 h5 X
                exqueue.rdptr&=QUEUE_LENGTH-1;9 Z6 R- i' L+ f: l. }. r: \: H6 U$ I
        }
4 U  ~5 h6 p4 T/ t. M. t}
9 k; c6 @+ S  W: C6 v9 A" T# X$ o) k, S
void        APU::SoundSetup()
5 s9 _# U% k2 [" D9 i. _2 S; ~{
( W6 H! a" e5 d# f: x- R        FLOAT        fClock = nes->nescfg->CpuClock;
; j9 b1 [. I9 G+ H0 I. U0 ^7 r        INT        nRate = (INT)Config.sound.nRate;3 Q( R' f. E$ e, d4 j* E  q
        internal.Setup( fClock, nRate );/ x# `- K: r. X0 K1 b) ^' H
        vrc6.Setup( fClock, nRate );
+ V& q( f  @5 `% }        vrc7.Setup( fClock, nRate );
2 A/ D" B' L, E& h) M        mmc5.Setup( fClock, nRate );
6 ~2 E) _% o9 O8 y: i        fds.Setup ( fClock, nRate );
. \+ _) c1 v/ C- c/ P; e3 x2 U        n106.Setup( fClock, nRate );8 Z4 ~! @! [5 f- \( {
        fme7.Setup( fClock, nRate );) |7 r# [- ^+ B; m2 X& M
}
1 M) [  S3 k) p8 l6 _& l; r$ c, j! D% _& u) E. N& W
void        APU::Reset()* l+ [5 p# z9 l
{0 ], M1 J. u% B, U& r* ~8 }
        ZEROMEMORY( &queue, sizeof(queue) );
0 o# f0 B2 {% ^" l3 P        ZEROMEMORY( &exqueue, sizeof(exqueue) );( c1 j0 W  a9 B/ a' H7 N- l6 E

& H- Q; K1 O, R! P        elapsed_time = 0;
, J1 ^* i/ v1 v3 o& f8 |3 Z
" K7 ~; `0 F. L% B0 `1 y) C4 O. x        FLOAT        fClock = nes->nescfg->CpuClock;
& N* k7 ?4 Z# \7 Y        INT        nRate = (INT)Config.sound.nRate;3 F0 c! b+ m7 Y4 I- ^+ l
        internal.Reset( fClock, nRate );" W% E! b. ~' n
        vrc6.Reset( fClock, nRate );
5 u6 N& W1 f0 b5 b        vrc7.Reset( fClock, nRate );( q6 L" V, Z8 N3 H
        mmc5.Reset( fClock, nRate );- P: }4 F, T6 }* B
        fds.Reset ( fClock, nRate );
8 Y; X! ~7 w9 \4 g( C: W6 @        n106.Reset( fClock, nRate );
% K& }3 {; ?. @: z( Q8 F% s        fme7.Reset( fClock, nRate );
  V0 ^9 |8 U7 C) `6 C% D6 ]. B& a$ S' O6 [/ j" R
        SoundSetup();
  g* n2 F+ a" C# p+ ^}- d" g1 v) h7 Y0 _& ]

0 M8 o  T; ^" ^4 fvoid        APU::SelectExSound( BYTE data )' Y5 b1 ^# C. H- R
{+ m/ m- L2 i- x+ e8 J7 w* I
        exsound_select = data;1 l$ ^$ j4 z7 h" X
}
" j. N0 x. J7 Y* X- c+ `% L
# R- H5 C2 Y. e* f# r( W; G+ W6 uBYTE        APU::Read( WORD addr )7 l! T" \% d) G1 T% R
{0 `! p4 ?8 f) w
        return        internal.SyncRead( addr );
) W6 A5 A" ^7 `, J, e}
, F% w+ w! l0 k9 R2 L, V
8 ?# H$ r: A) ~; D: D+ n/ F8 ^( _: u/ l: zvoid        APU::Write( WORD addr, BYTE data ). A: I+ A6 f5 L9 _* A% t1 A# W
{+ f) F/ e! H4 z. y2 P0 V8 Q1 P% ?
        // $4018偼VirtuaNES屌桳億乕僩5 f& [; n& d4 d; G
        if( addr >= 0x4000 && addr <= 0x401F ) {6 b( G' o0 z+ H
                internal.SyncWrite( addr, data );
% i9 I, s; |' S% ?                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& N* A% ]3 @: H4 A: Z- u; ?- ^
        }1 `( `6 R1 H( C3 N( c1 j: l
}
" y3 Z2 g. s  }
! w4 l2 p2 o, e+ B  T. _$ b; wBYTE        APU::ExRead( WORD addr )
; X# V% n  q. K8 b5 R2 z7 B{. `+ l/ |/ D# X8 f
BYTE        data = 0;1 R  q' n" ?% y# }
$ ^: }2 q! F: ~" F) _
        if( exsound_select & 0x10 ) {$ @  f" l! _* t- K! S3 E! n- k# t  Y
                if( addr == 0x4800 ) {; `4 G$ m9 _  e9 ~
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: Y2 Q$ D: [+ f0 J! d6 ^5 }
                }5 I' I; V/ k% M7 {0 s2 X
        }9 C* p' s8 P/ A7 N# T; L+ H
        if( exsound_select & 0x04 ) {
0 f% F  B6 |4 x5 \" Q: R6 k7 N                if( addr >= 0x4040 && addr < 0x4100 ) {( g- T8 j% C9 }  J0 v+ ~! @
                        data = fds.SyncRead( addr );
3 b+ P& ], j$ @/ r                }& c# B( ~1 n3 f5 B& T
        }) R# @  n+ B! x0 o. Y5 ]6 G5 q0 y
        if( exsound_select & 0x08 ) {/ U9 o. e2 u3 B7 ~8 ~) O. ~5 R
                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 c% k# l0 V" K  @+ G8 |                        data = mmc5.SyncRead( addr );
" K  _" N7 h2 A: W6 e) A! |; k2 L                }8 K) S. h" D' h
        }
& V4 m3 J9 x+ ?8 q: }% k, x' z$ I1 y$ I8 E1 e
        return        data;1 C. t+ t: Z" f4 b
}
/ h9 d- j: r2 R( B6 e4 V
$ Q! ?5 [: t0 c$ X1 ^& Qvoid        APU::ExWrite( WORD addr, BYTE data )- b1 C5 B9 W  N0 _# ]
{  p/ f3 Y; c& m/ a' ]' K" A  b
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );4 W( n# P' k( n; ^3 x; u

: W. \; e& [3 U/ G) M& Y9 G, G        if( exsound_select & 0x04 ) {5 y3 H' h0 `, R! b! ]& h
                if( addr >= 0x4040 && addr < 0x4100 ) {( d5 L5 r1 t5 [6 C# Y. z7 V0 b8 }
                        fds.SyncWrite( addr, data );
' g1 ]; l0 g. V* O! \. Q' s7 f2 E                }
+ D$ ]: V7 y- ]0 |        }# F$ x7 M$ V6 T9 b' g

$ I& N8 O2 ], o( Z2 S5 Y8 L        if( exsound_select & 0x08 ) {7 `7 L0 D0 K  a* w/ T6 U& p4 g
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ I( @. f% L% [' g6 Z
                        mmc5.SyncWrite( addr, data );# d% t' _1 L% M+ E6 P$ n2 n
                }& u/ }$ ^6 t2 L) f$ m" D2 M( H. R0 R; o' M
        }0 F6 q( U2 Q& [
}+ `6 W& I" u* |2 T

3 ?1 f7 h; L, X# Nvoid        APU::Sync(), l1 ^6 o4 k5 E1 N
{
1 w7 x1 j; @* z4 f5 |6 `6 K}7 F* [9 |, _  V* b7 A: a

( d, V$ h8 E- j5 |( j% q/ s" z. E: }void        APU::SyncDPCM( INT cycles )
4 M$ B* L8 F! }0 A6 F% Y' t{
& j0 `* N) P6 |        internal.Sync( cycles );
- u# {, [9 }# Y
/ o& w( i9 y9 K# O8 C        if( exsound_select & 0x04 ) {) {. n; M7 J$ x
                fds.Sync( cycles );6 K& ]( K6 T9 m( u/ d1 u7 Y& K0 [( ]
        }
4 |" c/ q; \$ L5 G2 d        if( exsound_select & 0x08 ) {
1 g- S3 ~- Q0 Z. [6 O3 h5 c3 g                mmc5.Sync( cycles );5 q3 a* b/ C/ ~( H7 ^
        }: M/ m% [. x& @  W
}
! k9 p5 m& Q4 o4 `
" T2 i  w: z. p2 x3 Yvoid        APU::WriteProcess( WORD addr, BYTE data )
! L( o: M" ^/ l) c: ]" R{
! d$ a) {. p+ k$ Y- P+ B        // $4018偼VirtuaNES屌桳億乕僩/ x3 Q, N( P8 o& U  ~* R' q
        if( addr >= 0x4000 && addr <= 0x401F ) {) M: U) G0 p* G
                internal.Write( addr, data );
# |0 W- I+ ?: K% u0 v, J0 n1 Z        }2 t* d5 `$ `7 J4 `/ D
}
; S% U' m, @& B
9 u: ^1 r& A1 f% e8 d3 [void        APU::WriteExProcess( WORD addr, BYTE data )2 _6 {9 ?0 x) v
{
+ E7 M1 E) ?. e: ~8 X6 p        if( exsound_select & 0x01 ) {, G2 f! h' E6 N+ k  y) s$ C
                vrc6.Write( addr, data );8 \6 s) t2 a7 ^. [( p- T
        }. `7 ?; m3 B, k$ f* Q" z
        if( exsound_select & 0x02 ) {. ?* m7 j9 L  ^4 |
                vrc7.Write( addr, data );
( ?+ @6 w7 \" B7 i- s" f        }
& v% r7 }4 |% i9 E- K. s8 V        if( exsound_select & 0x04 ) {
- [; k2 [1 ~$ ]$ s) [                fds.Write( addr, data );1 i) T# ?9 d2 Q  t) K* j! T- `& O
        }6 o2 y3 t( i' i1 @/ w
        if( exsound_select & 0x08 ) {* G0 V! I; q4 q. d: w+ D
                mmc5.Write( addr, data );% ~( F- H- L) u
        }
, N- U: E5 z! f# R' @4 V        if( exsound_select & 0x10 ) {
+ A; c  F2 f% R2 m# Q                if( addr == 0x0000 ) {3 o3 X& @) Z# F/ h  B
                        BYTE        dummy = n106.Read( addr );% s* W0 x4 v- n
                } else {
$ ^* J* q  o$ \0 [                        n106.Write( addr, data );
0 d0 g$ B6 x, @4 g( A' r                }2 |( S2 s' p* h% _
        }
9 i8 M% h1 @' I7 s        if( exsound_select & 0x20 ) {
! r* v% u5 A8 l- p; f& u# I                fme7.Write( addr, data );$ R) {8 R7 n  v7 g6 G! m
        }* `' M! f  o  O( Q) g1 D" M
}% Z, s$ \( I7 n) N* p) X. B
" i9 s- x) @' f6 v
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ P- B, m/ T3 y/ l3 }; e{
* e: Y/ v( [0 v& O: a( cINT        nBits = Config.sound.nBits;
5 t( k" U5 d5 ~4 c# PDWORD        dwLength = dwSize / (nBits/8);
( r# X' x6 P* ?" m& ^3 oINT        output;9 u2 y0 Y/ T$ N  V: w
QUEUEDATA q;! O) A7 x5 E* G' K: ]3 \" k) d
DWORD        writetime;
; X* J* S$ q( E+ N3 O3 T( Z
7 p* ^, E# P+ {- Q) bLPSHORT        pSoundBuf = m_SoundBuffer;
0 v+ U* F: m% }" y# {: _INT        nCcount = 0;0 o5 _2 Z. m# z. {. D" m
1 ~9 ^5 M/ V: Y' b
INT        nFilterType = Config.sound.nFilterType;
8 \" I0 F4 K7 U! v+ q; g& J$ l1 z3 Z# D
        if( !Config.sound.bEnable ) {
" n- C8 T' P) }/ {8 C                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
& K9 G2 ^  q5 o                return;- k9 i0 p( c( w- e5 V, o
        }8 F' a/ g; b# B3 s# B
9 E( l- }0 Z7 F& f$ {/ k1 x
        // Volume setup
. O9 Y5 q$ ]% {        //  0:Master" E. \+ v- l& e  ?/ }! I8 t3 R4 z. R
        //  1:Rectangle 1/ v8 t$ d4 ]0 g; }  p& q
        //  2:Rectangle 2  @2 _" b' A& d6 t+ y
        //  3:Triangle0 i$ z* [4 u7 S) M' d
        //  4:Noise: n8 r% F9 c0 p% F+ G  U4 d* D/ R
        //  5:DPCM
* s( s2 I, F+ H+ B$ b# |3 P! v        //  6:VRC6$ c3 P0 E0 L- ?* X5 i9 e0 T6 U
        //  7:VRC74 d( {. z0 e$ {0 ]$ W  P
        //  8:FDS/ [9 ^! T5 M! x' g6 W- l) b
        //  9:MMC5% {/ i$ S) _; x& E
        // 10:N106  M; |6 q$ m  m" j7 U
        // 11:FME7
3 v5 t) }' q. T/ S- b, M        INT        vol[24];9 |* L* b, G' Y) c
        BOOL*        bMute = m_bMute;
2 T, L( Y9 |- {' Y8 R  f8 E        SHORT*        nVolume = Config.sound.nVolume;
, ?1 y8 t" h" `$ I! i& _
; N! v5 |4 J: r, \& F        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# i  u  R) v, I' O$ {6 q
: `6 v: P; P2 z" a5 \
        // Internal' O8 y7 ]0 F, p" ?- N: D4 T
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;5 \9 U/ m. V# Q* i6 n) s+ \
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;3 R! C9 i. R: H/ {
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;& T) c4 h* |7 G  j1 l
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
$ K4 o3 c9 w  p        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; Z9 B! N0 e! a: @1 y

6 A' f; E. u/ e        // VRC69 O' h  E) ?( g& `' q( k
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& L5 a2 b+ y2 s" K( u        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 N( N$ C! |3 F        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ t. x' A% n( k# G( j
2 I6 c3 O6 f* t- b        // VRC7
5 J5 f+ {: }0 P# k  v0 W        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; y  b5 w+ }% I3 x6 H
# T; p( b0 p% |
        // FDS3 a0 n! T- X+ J  F& X
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;2 Z( L8 _' }- ^1 W9 ^6 G

6 i2 _+ {1 W5 p6 f        // MMC5
/ N2 ~- }  O, ]0 ^        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. o. G# n( c- f' h* S
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 Y1 k) ~5 g5 z( O        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" E7 @) o+ C9 b- r
' ^' \; p) x6 ]/ X1 S        // N1066 Z" }3 J8 [! V8 E8 e4 j2 x
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 H& r$ H) k  t2 M3 C
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& y8 I7 h: z6 l! ]! z        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 F- \+ E' K2 [1 q1 ^! C
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- |+ B, ]0 e( U/ ?$ N        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) {3 j* {6 W2 c: a
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) E( D. b0 {7 P! }        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% t. m! o5 O. @$ i) I& I
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; s! I! o6 P! \; v0 D: @+ Y
/ J$ L9 v5 J4 {        // FME7# @+ a1 w: i; L0 s5 c+ Q7 ]) u# J
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 p6 ^6 [% v: E& S0 c2 p
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 z( F) L8 m% r2 `+ {9 p% R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- v) e9 |2 H1 {; E- i! E; c
$ ^: h% c- y1 m5 z, l) Z//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;5 j" D0 U  w! i  O8 |8 F
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
, H  O) p( N# N6 N1 @6 `* b1 W) D
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ x# c  Q" ?/ a/ x; x! \, D# b
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ x4 d0 x. z/ X2 @) A                QueueFlush();
, j5 T1 @$ p+ o6 x$ |: c        }
7 `" j/ x9 T. i0 ]( Z
; R+ T. {' P9 g6 x        while( dwLength-- ) {
9 Q2 j0 @% H& c" |  K                writetime = (DWORD)elapsed_time;
3 m) E' P. }6 A' t9 G  K& D6 J
& _+ j' n; H: O% p                while( GetQueue( writetime, q ) ) {
# v6 X9 T1 s, V5 \& B                        WriteProcess( q.addr, q.data );4 _8 b; U2 I" J4 F/ k0 @$ S
                }
1 \9 o$ C/ M" f& }7 i0 ?- k8 f- U" E$ f0 Y1 S. ^7 E7 f
                while( GetExQueue( writetime, q ) ) {
: b' x; i. E3 y+ M2 Q, ~                        WriteExProcess( q.addr, q.data );
$ i3 k8 |1 \$ m; _% v# L8 B                }' j! c7 h  r9 w  `) Q& h
, ?4 ]9 m$ p6 ~3 |/ d
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
8 A9 s" o% m9 m% I* V                output = 0;
0 d) ?1 _; o& @4 W! k                output += internal.Process( 0 )*vol[0];
, W9 S9 J8 K: U! A- T6 U8 W6 J6 n$ i                output += internal.Process( 1 )*vol[1];/ M' ?& _- o% ]5 F% h
                output += internal.Process( 2 )*vol[2];
, {8 J+ `% J0 Y/ ]8 C                output += internal.Process( 3 )*vol[3];  c* d5 Y6 I6 Y8 s
                output += internal.Process( 4 )*vol[4];1 F, l! z- }5 w* L* g8 X

9 l2 d9 m' r! L2 ^8 z. Y                if( exsound_select & 0x01 ) {
: j; b2 v' L% U- W8 _                        output += vrc6.Process( 0 )*vol[5];* r2 O) a3 ?+ d, H0 @
                        output += vrc6.Process( 1 )*vol[6];  }, {/ }5 [0 ~1 l$ E
                        output += vrc6.Process( 2 )*vol[7];
, g5 G; _1 I0 M6 V' q                }
9 D8 {  }2 T$ j- D  r8 M                if( exsound_select & 0x02 ) {3 l% z) m+ F" ~. o/ F$ y! ~
                        output += vrc7.Process( 0 )*vol[8];
3 W5 S7 n+ H- M3 p% f" Y. c4 y, a                }
+ j( J" Y5 e+ Z) @4 S0 ^' @. C                if( exsound_select & 0x04 ) {
" j. k& w( [! v4 E! p$ y; F6 ^, f: I                        output += fds.Process( 0 )*vol[9];" z+ S3 t/ p, ~  r0 K4 A& K
                }! j7 }  y2 v% f+ c0 k9 @
                if( exsound_select & 0x08 ) {3 p$ [/ ]( L( e( W) Z( V) k$ y
                        output += mmc5.Process( 0 )*vol[10];
7 A4 y) G# k& x( K                        output += mmc5.Process( 1 )*vol[11];; n/ M& v5 ^$ H0 m9 H; Q4 f  V
                        output += mmc5.Process( 2 )*vol[12];4 F8 b8 A8 D5 ?3 r8 o  _* x( y
                }
" w8 O  k  R$ K: l8 N  D                if( exsound_select & 0x10 ) {( \. x( Z) |/ P0 M
                        output += n106.Process( 0 )*vol[13];
  Y8 n! e6 C  o                        output += n106.Process( 1 )*vol[14];) W& M. u& @. s+ k
                        output += n106.Process( 2 )*vol[15];% Z/ _9 @4 y1 ^: T
                        output += n106.Process( 3 )*vol[16];
6 K  M2 i( F& \. j, K2 A$ {                        output += n106.Process( 4 )*vol[17];
, I8 J! K7 Z* x6 q! w( e/ V                        output += n106.Process( 5 )*vol[18];- V4 b2 C3 K1 @
                        output += n106.Process( 6 )*vol[19];, H9 l! j" P4 |) {8 w# ~  w$ B
                        output += n106.Process( 7 )*vol[20];
6 R/ G% z& w7 Y' w* {$ ~                }$ b* _3 r7 ~/ o3 q/ V
                if( exsound_select & 0x20 ) {
4 W& E2 J# }# V. r+ [                        fme7.Process( 3 );        // Envelope & Noise9 }+ X7 d0 Q) i" h7 n% C, r
                        output += fme7.Process( 0 )*vol[21];
3 s; Z5 a& V% W                        output += fme7.Process( 1 )*vol[22];  `, Z4 ?! D- x$ \. e, m1 I
                        output += fme7.Process( 2 )*vol[23];
% R5 C6 [: e1 J' D& Y                }- c0 @+ T! D0 A7 R; b7 o
# p) {, R: b7 v, n: |$ B' C% H/ B
                output >>= 8;. h% ^6 e# a, h% W4 T

; r  s8 H5 |5 c5 L                if( nFilterType == 1 ) {
# z1 Y. n% P2 n; D                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* u9 \# J5 |% b. v  g! z                        output = (lowpass_filter[0]+output)/2;$ e' ?) ]. c( {. c3 \
                        lowpass_filter[0] = output;
6 b. Q4 I+ `' G# E& b                } else if( nFilterType == 2 ) {6 i" s* J9 O% D" {# e
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 q5 p7 ?8 Y2 ]3 v0 k                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
/ G* [  n; ~: f; ]                        lowpass_filter[1] = lowpass_filter[0];
7 c  R% a* k5 r                        lowpass_filter[0] = output;! ~; `$ H& b" m2 D4 ^# v
                } else if( nFilterType == 3 ) {
$ x" s$ Y) f0 ]3 l* H. b                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* w, G6 J3 Y5 i; N7 k                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;4 P* h/ C! Z+ A- X
                        lowpass_filter[2] = lowpass_filter[1];
/ z. J: t! m3 V$ E' w                        lowpass_filter[1] = lowpass_filter[0];+ l: p  H. p; f4 W- j' z3 o! N
                        lowpass_filter[0] = output;0 w% i; C3 N0 L" g
                } else if( nFilterType == 4 ) {
% H' X8 J6 a  I& m: N                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! C4 O( ~; d; W# r  D  E) d                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;0 E, b/ o) D* u7 S9 ]( ~
                        lowpass_filter[1] = lowpass_filter[0];, U# Q. f3 U9 d5 G9 \
                        lowpass_filter[0] = output;, C+ j( B$ E3 T- Z0 T8 d! D
                }/ R# c) q) H4 ]" I* m
2 a; g5 y8 f  h; A+ i
#if        01 j, p8 A$ g: R
                // DC惉暘偺僇僢僩
' b* b/ ^- |9 ]; f                {; f) t5 F( w) l5 T1 l* b
                static double ave = 0.0, max=0.0, min=0.0;
/ x0 w: Z& q1 m5 b) Q$ g                double delta;
, \/ V8 B/ K2 d+ p# @! ]( @# ~6 q. ~                delta = (max-min)/32768.0;$ \- A+ k0 P6 b: f; a% G# k' {
                max -= delta;
3 Q8 H5 l6 O6 w# Z9 ]- E2 R                min += delta;
; ~4 T9 k  s& {# c) ~+ X+ K                if( output > max ) max = output;; d# h( U/ ~! l1 T* k1 l0 p4 [; m) l
                if( output < min ) min = output;
5 Y* C1 q4 k8 r  n( X/ K3 H4 X- G- [                ave -= ave/1024.0;' i/ T$ ^* V9 N3 E1 j$ i* _
                ave += (max+min)/2048.0;
$ e5 S% k& V* \9 B! S2 ?4 l                output -= (INT)ave;' Q5 i  u. V' y& X9 T; Z" O
                }
4 n, z+ @8 [' _+ \#endif* d3 c7 h7 B! V# W# e3 B/ [
#if        1
  W( D1 q8 G; n! B                // DC惉暘偺僇僢僩(HPF TEST): A$ q1 T5 j' S( x* c1 X4 p; r
                {& |& _: k4 U- U' [; F
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! z; m" E' w, f% I                static        double        cutofftemp = (2.0*3.141592653579*40.0);
, u5 p! @( ~* [                double        cutoff = cutofftemp/(double)Config.sound.nRate;
. r, `' z; z& W( C                static        double        tmp = 0.0;
& k4 t* |3 A+ X/ e                double        in, out;
) u% r/ b$ Z& h9 M3 b0 s. j
( l4 O: G0 w4 r7 r" a. N                in = (double)output;; {& P1 Z" G/ E
                out = (in - tmp);9 }4 V3 A4 `2 ~/ V- P8 ?9 z
                tmp = tmp + cutoff * out;% D- n/ y% ]( H/ H% K" E

: H- `( j% ?  J+ j0 z                output = (INT)out;7 p- \) Q. C+ T* ?% n  _8 w
                }" p6 O4 n) d  A$ t: M& P
#endif/ N& o% r' x8 m) V' A
#if        04 t+ O! ^/ B& d& l; X6 q* z& E
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* t  r3 n/ O. D# f) o
                {
! {4 T8 C" \/ L4 L                INT        diff = abs(output-last_data);. X6 J, c7 R7 n% ~9 e" n" |
                if( diff > 0x4000 ) {
$ ~# \  L8 D( L/ b                        output /= 4;* r7 `" ]+ Y7 Z% b
                } else
  t' e/ a* o3 D1 B8 T) M" ^0 o                if( diff > 0x3000 ) {
5 @& v1 s7 T6 \; m                        output /= 3;
, y; L" x& T- |, k0 [1 C* m                } else, u9 i9 U7 S- r. R
                if( diff > 0x2000 ) {
6 d3 W9 W$ b9 `) P( d% l- H1 |                        output /= 2;
$ J( D) J8 R  b# ]; @& F. l                }( `% f! h; S+ f+ \; q- q
                last_data = output;$ b7 `+ r3 ]2 a( I. L$ M
                }
, U2 I) o1 l5 \3 e- r, Q/ |, Z#endif5 X( M4 J1 c2 W6 ?6 l- w6 Y7 i
                // Limit
3 Q: _" h) V5 ~5 Y* C" U; L                if( output > 0x7FFF ) {
! S/ V& r. O9 d2 X" X                        output = 0x7FFF;
0 l4 A3 h4 V: x                } else if( output < -0x8000 ) {
( N1 H; N; q3 ~+ v$ K                        output = -0x8000;
! }: t. D& V( ~( Q                }, p2 u3 ^6 E6 w: d  N: J
, Q# ^, M$ U% o+ v! R4 B- h
                if( nBits != 8 ) {
0 B, Q4 _; D4 G: d# A% i- ]                        *(SHORT*)lpBuffer = (SHORT)output;
/ @( q. B- y4 F' i                        lpBuffer += sizeof(SHORT);: q6 j- n; l; q" `4 U
                } else {
* T9 {" g& F6 H% ]. L8 H% _                        *lpBuffer++ = (output>>8)^0x80;
; |# e' @/ ]; b1 M, R                }
3 v4 G0 s. c0 r2 V5 ^, J+ g2 j5 C1 s0 |$ d( z1 g
                if( nCcount < 0x0100 )8 }$ K6 U6 |1 ?- @; Q! v* @) V
                        pSoundBuf[nCcount++] = (SHORT)output;
, F" p& P5 w% n0 u. F
: ^# W) H  I$ k# z! J/ l//                elapsedtime += cycle_rate;& o/ L7 v, O# `: p9 z0 m8 X
                elapsed_time += cycle_rate;5 N7 E# K  q* \8 \
        }# i  \( d+ J/ x0 K8 z

% G1 G- T. _+ M! Y* M9 }: `#if        1- p1 m' @: o* F
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {7 w0 i5 m# {# R* Y, m, u9 u( H
                elapsed_time = nes->cpu->GetTotalCycles();5 `# D* r7 m; }0 @1 u' t( k- A
        }2 `% q8 n! e) y( H- G' E: {
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 [/ X" |  n) d                elapsed_time = nes->cpu->GetTotalCycles();
1 m8 s) m7 G; \9 y        }
4 I; ~- h1 X& u% Z6 x# t; N' C#else" s. F6 S8 H! h
        elapsed_time = nes->cpu->GetTotalCycles();: N+ C6 u# U0 z) x! p
#endif
- E2 S% L! J+ ?8 \  k* R}2 ^- Q" O7 Q2 o' ?5 [  W

  Z1 b8 D( F5 R" a7 ~1 R// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
; M& L6 F. J) a! BINT        APU::GetChannelFrequency( INT no )4 s: G( o  D) P; \, Q# O8 X
{
9 j3 }1 B& d# _" U. b# D        if( !m_bMute[0] )
8 ~# c% d% Z0 m9 S& ^$ P                return        0;6 _5 r6 U) W4 [" ^0 H- I! g) r

0 ?: t7 r4 d* P% P        // Internal" o( |4 y, X* o2 X) E  z# n
        if( no < 5 ) {; J7 D4 w- o8 [6 Q9 M" n, l
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 `. o0 x) n8 d2 o" z        }
% }9 F2 T* o6 i" j8 m) a# X6 D        // VRC6
: t; l! N, ^+ i2 s) B9 \        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' o% Q% x, s% ^/ s                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
' u9 [, L/ x6 A        }
+ W3 T' S, U4 s        // FDS$ Z. b7 G: ]: w- M0 j
        if( (exsound_select & 0x04) && no == 0x300 ) {( \5 G, k5 j6 v
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
! o7 h5 T! w3 p* [7 ?        }
& B: j" J* t$ T5 P; ~* b        // MMC5
5 [: Q& y! P1 l" L8 E0 C7 @. q        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
+ z: u, n( ~) o' n$ z                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;9 D; u; S: ?' [8 Y
        }
1 {. [0 m7 y8 b6 E5 n  }* \        // N106
; a& K3 p  ~/ d/ ?        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 b5 k$ s9 |9 Z* W/ d, x; x& ]
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# X6 T( `- T5 m, _( C* b        }1 x# n" c, y$ ]  F+ M+ J
        // FME7" @& V, G; \; N% V* O0 _. K# s
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {; L5 q6 f& W6 {1 p6 l) Y2 P9 _- l
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 k8 m& a: t! `        }
8 m/ h3 u. f! N' v+ Q2 c        // VRC7
, Y* W/ m% T; L& t. P7 {4 P        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
$ b3 x$ j4 J4 R  A" `2 t- S                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
0 ~' U) q& F- Y$ g5 b& t        }
/ H5 H9 W, b1 N$ N* W        return        0;, U6 h6 j, I/ ^$ y+ f+ k
}2 n  ?7 Y4 e7 A# D/ s/ ^+ O5 [  g3 G3 E

; ^5 {4 S- v4 F& j// State Save/Load1 p4 W, Q* N- G& b1 Y% l9 c+ s
void        APU::SaveState( LPBYTE p )/ I/ d0 V. _7 L! i( }: g
{5 L5 I: Q6 Z4 L: y
#ifdef        _DEBUG, d& F" h! V7 n  n& N; q, u
LPBYTE        pold = p;
. b6 h0 H( V: U0 s: t: X0 A) }#endif9 B) m) {3 g. S. Z8 y0 ~) d" P+ ?

& U* Y  y5 s3 r5 S7 R3 t6 r# ]        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞# Q* J0 j1 i$ o+ R; P3 p
        QueueFlush();- p- ^; F2 L9 s# G' u% ~/ p# U

% }1 k) W* j1 V% H6 w) r" U! x        internal.SaveState( p );
; {8 K3 l4 T1 J+ ]        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ P: F! Y2 g" D6 B  b& k% y& A( J7 v; N( `8 b+ N1 |9 y3 V9 E
        // VRC6
0 I  ]7 }! g3 N* ~, Q& U        if( exsound_select & 0x01 ) {
1 q: r  `: c8 Q/ Y3 {5 ^4 d" }. N                vrc6.SaveState( p );
2 V8 u+ {  ^+ O( q4 G0 i  Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 u5 R7 `& E: `0 G) N/ k  `* ^1 u        }5 w% C- h7 t  I' U
        // VRC7 (not support)+ H1 @& v" T4 X* S
        if( exsound_select & 0x02 ) {/ K+ W' J' Q: o
                vrc7.SaveState( p );0 O) T$ z) S# m* U( }
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
9 @8 ^% _4 D/ i" o        }1 t5 S( h& s5 c
        // FDS
; v7 ~) K" [) B) c        if( exsound_select & 0x04 ) {
; R8 e% f' ?; ?5 x- f                fds.SaveState( p );% ~6 u0 C9 q* k/ Q. y9 x
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" q1 E' j5 O9 m2 s5 C5 V        }+ b' G; @$ l& D- J" R/ @$ h: M- ~* K
        // MMC57 G+ N# ], A6 Q  Z$ M
        if( exsound_select & 0x08 ) {
9 ?8 U, Y# k& D, c+ U- H                mmc5.SaveState( p );0 a3 k7 R0 x; e" ?6 L1 W. t
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
, W8 ]  Y* g* M# j) W2 i        }0 x% ~8 ]. ~* B  r" `
        // N1067 T- @7 c' G- R0 G1 ]
        if( exsound_select & 0x10 ) {
) h& U4 _+ q# J  w( b& L) s9 b3 R                n106.SaveState( p );5 A- f9 z) |2 Q! U. i8 S" A
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, Z- E# o% G: V. t2 j9 t8 B
        }+ d; x( A9 w% W% N( n) ]: q0 k( O
        // FME7
1 `8 ]% i; q6 d: W        if( exsound_select & 0x20 ) {
  d( C2 J2 P5 x2 k$ [                fme7.SaveState( p );4 |  a, V( ^; o( `
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 e: C; n- ~0 g
        }0 b! @! q7 z& @) r
  u+ \7 H" L  F: Y) x7 |# n) D
#ifdef        _DEBUG: P, |+ |8 t* C
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
# l% Q  m' ~) O8 p#endif
+ k1 }/ `/ Q- C, f, J2 ~2 c3 C}2 j* _$ v0 o5 }* E! q8 w
0 F' c6 v* m. |; `4 c- w5 I
void        APU::LoadState( LPBYTE p ). T' a4 p. O1 \3 K5 x' E
{
0 I% R- _( K7 o$ U( M1 C        // 帪娫幉傪摨婜偝偣傞堊偵徚偡% V- h7 u/ g4 |/ p. E$ w1 d
        QueueClear();: @+ Y0 t2 j5 s0 d) c" _4 z$ A& X

+ }8 P4 K4 [, b' {% B$ F        internal.LoadState( p );  A! F( m! Z: L8 v2 c; z; a
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! n: R' `; k$ I7 f' V, F+ c. k2 y% d* M& v5 P7 X, t
        // VRC62 ^7 O/ I5 M% E
        if( exsound_select & 0x01 ) {
; o/ k2 q& T+ {6 _- @% S                vrc6.LoadState( p );
/ ]0 q1 J7 M  }3 b- t( M                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) Y" l: t+ U  D* |
        }
% T% [. z3 S7 ^  ?+ s        // VRC7 (not support)
4 z8 H9 O  y* [; ~        if( exsound_select & 0x02 ) {
; e. X4 D- V0 b" A& I# S$ [( k8 g) ?                vrc7.LoadState( p );! _  K7 O. O4 r3 |2 u) e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ T# h. r4 h6 @' [        }3 s8 A  b2 v9 M( r; R  r
        // FDS0 P9 |& i% }5 J- L: E
        if( exsound_select & 0x04 ) {: f" L4 Q% N5 l, j' F7 e
                fds.LoadState( p );
3 s/ Q3 \8 x/ b& F) W                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 E8 y5 T, C) |) e# N% g        }
) z( J7 d& E( j        // MMC5
7 j& a) Q  P: S3 q0 `+ d        if( exsound_select & 0x08 ) {& T4 T9 t% r% C2 q8 r
                mmc5.LoadState( p );* W* `. n  o' z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ s) w, d) p9 _2 W; P        }$ {; D- ?$ Q. R$ g
        // N106
# t% j+ H3 Z* ~0 u9 m* y1 l9 [        if( exsound_select & 0x10 ) {
7 ?1 k' U8 k9 E, w                n106.LoadState( p );. J" h$ d6 l' Y  k
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 B( t* Q& l& V9 F# S        }9 X" b8 k0 B9 b- W: Y
        // FME7
! f8 `. }" d" k2 g8 L0 ?1 y+ o        if( exsound_select & 0x20 ) {
- {8 [: g6 [" ~# s2 v' \# ?                fme7.LoadState( p );8 |: C7 [5 Y9 S  o$ j# r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding% ?- r: Q( f& F, u/ j: I% y5 h
        }
2 e) q2 L: ?6 d: g* e: Z1 C}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( M4 k: _* W: f0 |可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 ~/ f. G, p3 w4 S7 P1 U6 ~
感激不尽~~

$ D. m+ I) h7 `4 a" w. I0 c恩 我對模擬器不是很有研究,
5 j3 W. [( j2 ~/ ~  o9 e雖然要了解源碼內容,可能不是很困難,
. K2 W7 U3 c: p+ o5 U不過還是要花時間,個人目前蠻忙碌的。
& k+ g$ Z/ ~+ L7 U; R3 Q8 S* U, P' D  J8 Y- e
給你一個朋友的MSN,你可以跟他討論看看,
1 U1 T% G& K7 ]2 Y. E他本身是程式設計師,也對FC模擬器很有興趣。4 C7 n: u0 Y6 I
2 q' \. |: m$ D: I! f
MSN我就PM到你的信箱了。
0 X6 M" N$ ^! E( h3 V& m1 U6 a" p' o  x5 D" W, g) d9 Q7 ^
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# U" k) H$ l8 a+ H5 ?4 L+ p呵…… 谢过团长大人~~

( j) k! f+ V; b6 B+ J2 U5 `! f  C* p/ o
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! ~8 {, o" u* Y4 r( C" k
团长的朋友都是神,那团长就是神的boss。
- g( ~) L2 Y$ d: B) F
哈 不敢當,我只是個平凡人,# u6 v; d/ h9 t, \0 t
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# I: T0 |: t8 @, }# DZYH/ d! O) m% v: x( M( s+ @5 K
QQ:414734306
$ l2 a3 j9 a! {0 }" kMail:zyh-01@126.com8 O8 E" |. a# R( k
) l! W9 C- R: O4 V9 q* c0 T/ H
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ) X+ T6 {4 _  J- _# a
再次对团长大人和悠悠哥的无私帮助表示感谢~~
# E1 g- ]9 C( ~1 y$ M/ t
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 12:51 , Processed in 1.170898 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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