EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。( _; I$ c3 l: q9 }. c- p0 e) k
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ I: y4 b8 U8 n8 K
这里有相应的模拟器源码,就当送给大侠了~~+ I* o$ H' s7 v+ L( b
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; }9 i4 z1 }- k  D: F7 D3 G
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. g# x9 i2 {3 p' k) y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ U, l; _% Y  J/ Z8 b1 Y/ V这里有相应的模拟器源码,就当送给大侠 ...
" ?9 v" T) u, W  n2 l! B
聲音部分(Audoi Process Unit = APU):' c  Z7 L- {' W) V1 X3 @5 @
.\NES\APU.cpp
0 v# t% X/ u8 P) V. d" J0 Y.\NES\APU.h% N0 n) U4 M, b4 ?
; ~( a1 G7 o' _. G3 K; E- N
  s5 Z1 a! T! H* {; j' a3 \7 ]
影像處理部份(Picture Processing Unit = PPU):, D* x% L8 z, Y! Y3 z' Y$ M
.\NES\PPU.cpp$ J7 W1 }+ B& E' j! o$ t  H
.\NES\PPU.h
' B& E. _: ~; C8 G; ]: T9 i2 F5 T
* k( w' [& W) ^* D# k* J如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:7 w" A4 T- R/ H5 |) H  C6 [* S5 f
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
8 s, g  h' j+ O7 d//////////////////////////////////////////////////////////////////////////2 h2 D! V) C# b8 Q5 ~
//                                                                      //! W* E, l; I: J) g( ^
//      NES APU core                                                    //; \# y- |1 [+ R, q7 f4 R9 G
//                                                           Norix      //
' i; z9 q" M" `- z, y/ N+ o//                                               written     2002/06/27 //  F3 q9 b$ z+ |' m0 \, ]
//                                               last modify ----/--/-- //6 A) M" A2 g& u
//////////////////////////////////////////////////////////////////////////
$ {% G  \! Z/ Q4 o) x# I: M4 L1 ~, p#include "DebugOut.h"
8 A* @& p- j  S7 z0 c6 A#include "App.h"6 r' U3 B7 ~& e( ?6 I
#include "Config.h"
0 l5 g8 r7 o( s1 u
7 ?5 T5 s1 r& R9 ^( ?. j#include "nes.h"
+ g9 h6 x5 k. k% b#include "mmu.h"" @+ a( }! c4 W' a
#include "cpu.h"; m5 A0 i9 |+ N0 J3 T8 E4 m9 V
#include "ppu.h"+ _! N! t2 O9 S& a3 h! f
#include "rom.h"1 a7 L$ T1 ]+ ~" d7 v0 N
#include "apu.h"9 w$ @1 ~( `) ?! [
/ \6 n" S- [( A& Z
// Volume adjust
) F$ D8 I4 I; \! [7 `+ t8 f) R9 P6 A// Internal sounds
% Z' l, o, }% B, }. z: V2 Q#define        RECTANGLE_VOL        (0x0F0)
  `. S$ w; l  H, U- l4 x- a* P#define        TRIANGLE_VOL        (0x130)
+ v0 T0 r  N+ N% X) }#define        NOISE_VOL        (0x0C0)
$ ?4 B, e' @% q* k* ^' j3 r#define        DPCM_VOL        (0x0F0)& g7 Y6 V3 Z( A% s! R+ J4 a  n! B' N
// Extra sounds
% O7 @9 ~/ X" j; g7 U. d#define        VRC6_VOL        (0x0F0)
6 Z0 T7 s5 ]4 i! k: j#define        VRC7_VOL        (0x130)6 X( i8 d! P8 G. [$ W, L% t$ C7 N1 W( B
#define        FDS_VOL                (0x0F0)
; b$ p9 B5 L: [( e( P+ R#define        MMC5_VOL        (0x0F0)# Q8 p# Y$ |1 }9 _$ `( m2 B
#define        N106_VOL        (0x088)
/ k6 p% Q# g  r#define        FME7_VOL        (0x130)
5 |- f- {6 o! r" b% ?. T6 N, Q( P  d6 W" ?% @  R$ g
APU::APU( NES* parent )
  g! o3 y5 T5 V& X! d; Y{
: `5 ^! a: ]4 l( V        exsound_select = 0;! s' j2 G9 B" z1 t6 d
4 B: ~0 E4 H5 F; \( p. s
        nes = parent;
  C/ x1 Z7 x( F% i        internal.SetParent( parent );$ b6 p$ M# q; {+ p
& m1 X/ I$ m+ v, B, r5 G+ O( R4 ]6 @
        last_data = last_diff = 0;# x/ G8 h' G$ `' \( ~- e& Q: `
9 ?1 e  L/ D" z3 \+ F
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );% t, l! C' V% R2 G- c# Z$ c5 B
& e" Y. W% W0 |* u9 X8 I" u; E
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );$ z8 w; @" D; v0 i+ L) d
        ZEROMEMORY( &queue, sizeof(queue) );
0 X  f! W  m$ ]1 |4 \1 j% Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );* I/ j9 _% ?3 f5 h" x

# ~; V+ w  [3 a. r# ?6 F! Q        for( INT i = 0; i < 16; i++ ) {: w6 s$ T9 p5 D1 Z, _6 \
                m_bMute = TRUE;
3 d' b. I/ ?% J1 n        }
- ^3 w6 q7 D' A$ m: f2 W1 C}  M- i0 Z* j% {0 @- C
1 g/ B) Z# i, d  [" b) n& u' }
APU::~APU()0 H3 P+ P) l4 l7 T
{
0 C. t& G' i  o+ I& ^}
5 j2 S" j8 ]4 I: R* A
  k# T, e, U0 n2 g. ?/ @1 fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' W& Y' Z( v! C0 o1 h6 ~/ N9 X{
: x! ]/ N% K  M8 l) K1 Q        queue.data[queue.wrptr].time = writetime;
8 X* y; N0 h* I' e) Y- r        queue.data[queue.wrptr].addr = addr;
" Y3 N2 Q8 d; m7 F- u( e        queue.data[queue.wrptr].data = data;
; ^& ~! d$ [6 v4 V; T) b2 K        queue.wrptr++;
( j; v6 u. }4 N        queue.wrptr&=QUEUE_LENGTH-1;
& X) u- |" A8 p& ^0 T! z( C. }        if( queue.wrptr == queue.rdptr ) {4 ]; h, E% Q3 K, o$ g
                DEBUGOUT( "queue overflow.\n" );
9 v1 e+ h8 n6 S        }7 M( ^! ]- z: A7 W
}
, O: x4 V# G& B5 R: k1 O- a4 R; G7 @
6 m' p9 S3 P# F* @- s! J# Q, PBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )4 P$ X! W7 N, {9 u( g
{
; n" T! e8 m! V" V! D% N, Z        if( queue.wrptr == queue.rdptr ) {9 r+ \+ F4 k! I7 I5 C) P
                return        FALSE;
: ~& X9 F8 s: M, c% A' Q2 A        }
( f) l9 S6 T( ?! \6 ^- G% |+ i        if( queue.data[queue.rdptr].time <= writetime ) {
5 d6 f' H; k0 \' o% _                ret = queue.data[queue.rdptr];
; V8 E) }3 ~* }! ~                queue.rdptr++;9 k* ~# I; m" w7 z0 d# @
                queue.rdptr&=QUEUE_LENGTH-1;
# p: z: h+ Z7 M; e                return        TRUE;% c% }. }' N) U- E; M3 H8 j1 l: \
        }
! `) t/ S, m7 L+ W/ D        return        FALSE;
( X2 d7 s7 k' s4 M$ X- X}' R5 Z) a  p) g- t# [

/ x. d! K: i8 {7 O+ kvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  d$ w* y9 A( }- O7 y
{
" B: g: I% d7 G. g  Z+ P5 y( v        exqueue.data[exqueue.wrptr].time = writetime;, h& r' Y2 K5 `% s
        exqueue.data[exqueue.wrptr].addr = addr;- Q7 p2 z* E" P# B' Y
        exqueue.data[exqueue.wrptr].data = data;4 U1 O) \) x/ C" w
        exqueue.wrptr++;8 G% U# r3 i+ k4 S
        exqueue.wrptr&=QUEUE_LENGTH-1;
6 P; \4 C: o, G6 O! [! V        if( exqueue.wrptr == exqueue.rdptr ) {
& c- J4 `" f+ A& o2 y+ K                DEBUGOUT( "exqueue overflow.\n" );! z0 }% C6 ?. t5 q: Z4 J. @
        }
$ \+ M. d4 f3 K) J5 j}, k$ v. \0 M1 p- Y

- f7 L$ ?, t8 ^4 \/ i( y% h) fBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 u* O" Z% F( G! o. ]- p4 ]{
/ L! C3 `$ ?5 S% x6 r1 t7 d        if( exqueue.wrptr == exqueue.rdptr ) {( p: L0 i: f- S8 R8 U6 P
                return        FALSE;* U+ Q8 e9 Q4 m& v  V8 a! {7 H! E
        }6 w4 h2 ^4 C4 a+ O
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ F+ @4 u) w! ?. S/ y  _
                ret = exqueue.data[exqueue.rdptr];
3 E" w) }1 D0 c9 e                exqueue.rdptr++;
" {: p3 ]: ^% K" z7 H3 X! ?                exqueue.rdptr&=QUEUE_LENGTH-1;  E( a* b8 X! p7 S) H1 R
                return        TRUE;
2 C; e, o% k; {" p5 {        }
8 Q2 ?4 y* J  s" r; G* b        return        FALSE;: y4 t9 f/ b# [: b( W
}
5 h4 A0 |5 W# O
9 f" |( C8 p1 A  \  D4 B  A1 dvoid        APU::QueueClear()
! _" A4 i* G! o$ O. y' _& v) M{
3 x& S3 q- m$ n/ f' g        ZEROMEMORY( &queue, sizeof(queue) );
, C5 X7 H1 B; f/ J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; V8 q5 J& J, Q' b}5 D: C4 E  F$ c; ]- z9 L/ a2 x4 u
6 k! q% m$ p( F, V- ~5 B
void        APU::QueueFlush()# P2 d# X6 J5 V" f, ~4 X0 f+ l
{  F4 T- w" C7 B2 ]# R
        while( queue.wrptr != queue.rdptr ) {
6 |" y7 f$ o8 \8 a4 O1 v                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );7 ~! }; t% g) o0 `0 ~/ t# j
                queue.rdptr++;
- a1 h- T! L( w  b0 h$ n                queue.rdptr&=QUEUE_LENGTH-1;
  w& _$ a  v1 u' R+ c1 j: d8 [+ A        }9 k6 v, v6 d0 U# X0 C- G  r

( y* J" z* d1 I0 Z        while( exqueue.wrptr != exqueue.rdptr ) {
4 a! }, }4 R7 I, C9 {+ u                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. z4 X! |" w( P
                exqueue.rdptr++;
6 a& |. O4 L% J" @5 k5 C                exqueue.rdptr&=QUEUE_LENGTH-1;
# m* A# |* n: T" s; t0 M- |        }' w9 V7 B( _( y0 ?+ |' H& t
}3 a- N) P/ t0 a% ?/ s* v. c0 S4 Q

6 v: x* p9 N) ]2 n. xvoid        APU::SoundSetup()7 m3 q1 z$ N9 Q4 R+ `# b
{8 @, i; Q. f1 Z$ b3 _# q& ]( V
        FLOAT        fClock = nes->nescfg->CpuClock;. N) i& T" T9 O, g  b* x
        INT        nRate = (INT)Config.sound.nRate;
6 ~6 H7 t1 j. I1 |% X        internal.Setup( fClock, nRate );4 v5 z8 U  U3 f, [+ t* C8 V
        vrc6.Setup( fClock, nRate );; P( s# @9 Y- D+ T  \  d; l
        vrc7.Setup( fClock, nRate );$ i- T4 P  g/ O2 f. z7 O
        mmc5.Setup( fClock, nRate );7 r# d+ x* q8 s0 I5 l# B& p
        fds.Setup ( fClock, nRate );
: T, _0 D4 W# F3 R# S% I! d( k        n106.Setup( fClock, nRate );
8 U4 y( Q' O( B0 c/ y2 H8 w0 X        fme7.Setup( fClock, nRate );
# v1 n+ L* S6 N' Q$ `1 P}
) c, V3 l# G1 w
! C; _3 D6 F' z2 \void        APU::Reset(): e% ~+ f, H. p  N  ?8 k, s$ h
{
1 L2 R+ ]1 W" V        ZEROMEMORY( &queue, sizeof(queue) );: y# b, O! \; {  G; f& N3 C/ m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# r+ O% H5 g. K" B% _. }$ G& g! U1 A5 C6 f- i/ o4 Q
        elapsed_time = 0;. g0 ?: G& g) h4 D4 e5 T

9 [9 _9 e* p; b% a; J& c        FLOAT        fClock = nes->nescfg->CpuClock;+ I; X$ T- b0 A0 V; B5 G
        INT        nRate = (INT)Config.sound.nRate;8 M, k1 ?- }0 I0 {9 f) s
        internal.Reset( fClock, nRate );
2 L. B  b; q! S( R- Z6 |        vrc6.Reset( fClock, nRate );
0 F9 x$ i% [! j1 @. K8 R        vrc7.Reset( fClock, nRate );- T' Q# `' ^0 I0 n7 h: b5 L
        mmc5.Reset( fClock, nRate );
- t+ Z" h* m9 x& r        fds.Reset ( fClock, nRate );
! y/ \8 `9 p- \3 l' a7 `        n106.Reset( fClock, nRate );
5 N& i/ B& ?# S% T        fme7.Reset( fClock, nRate );
, N/ j+ h- g- z5 ]! n+ R/ K
6 R8 i) ~& S- d$ B' I. J& ]1 `1 ?7 C        SoundSetup();
* y% E. b7 H7 d6 I& b3 K7 Z6 I}/ |8 e' f5 D% J1 E& t

* ~/ g- z* v  @0 K/ [void        APU::SelectExSound( BYTE data )
6 u% V  C, {: R6 y* {{: f3 k% Q4 @+ f& y' `$ F1 J0 O; f- A2 j/ A
        exsound_select = data;+ ^- P! y7 B* c4 F5 L) i0 [
}! M! S: N# J  E6 c# R1 O( H
/ K$ ~' \/ w/ _! `
BYTE        APU::Read( WORD addr )
0 U. }* W; V$ {# ^; I{0 n  _0 j  G( H! ?3 ]$ P6 K
        return        internal.SyncRead( addr );
, o, D/ U- N8 }( J* V}3 e; @5 G( x# B: }. ^( b

$ \; d2 Q, I" evoid        APU::Write( WORD addr, BYTE data )! A: e  ~/ B6 h, `- W
{
; z: G, P' o5 ?/ ?2 N; @% V5 T5 I  x& _        // $4018偼VirtuaNES屌桳億乕僩
+ h/ e4 Z' p0 c0 B1 T7 E        if( addr >= 0x4000 && addr <= 0x401F ) {' |, l5 ^& E* ~% L* C8 A
                internal.SyncWrite( addr, data );
- G2 V4 y7 E9 f" x- B9 f# ]3 e                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 Q; N$ b4 a& W2 n
        }
: w) `, o* I7 w7 q3 B}* O! x4 |* K& q: N6 Z0 f
% a, ^  U0 f$ h
BYTE        APU::ExRead( WORD addr )" A  W! F( a! R% i/ B  [
{8 p0 `3 W/ [- T3 m/ p
BYTE        data = 0;
4 i* \% H, z9 G
. t( `# b- {" j2 ]1 L& L        if( exsound_select & 0x10 ) {
; d( M  S& ?) c7 ~# q, Z                if( addr == 0x4800 ) {8 z4 Y- p$ u9 s- r  I$ v# G. [* ]
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );3 u: J8 }2 i) n0 y$ t
                }
& k8 S7 ?5 I3 o2 g" l. W6 C2 g        }6 x1 s: e; ?5 p# X6 m" {) a8 s) e
        if( exsound_select & 0x04 ) {
) [0 D0 h, Q$ q- K0 N: x1 X                if( addr >= 0x4040 && addr < 0x4100 ) {5 Z3 X7 u0 b% p/ G8 I. K. o) T
                        data = fds.SyncRead( addr );/ V; ]# y' j3 N& b1 W8 }
                }
# g% p9 P3 x# n        }
5 g: A) f1 M3 A9 S        if( exsound_select & 0x08 ) {7 L7 j# e; Q5 B2 R# }" o- N. X
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 w2 o  u. e: J+ Q3 a0 x' t
                        data = mmc5.SyncRead( addr );
& V  Y" x; D* O5 W  |! N                }) S" G9 E* e; d. }
        }
) w4 g: M, x. d! H% Q  v" W# w2 H/ F* I" d  O
        return        data;
4 E1 e7 C  A- B- Y( D1 [}! f6 L3 j% Y! \# B, B& p; W

+ o; W8 z& K' V# d/ evoid        APU::ExWrite( WORD addr, BYTE data )
; S& R7 Q" I0 g$ g9 m* _; C( x' f5 D; M+ A{
. B4 N( A, x( b( Z- K& g        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
! }# O9 A7 @/ d# ~: g  `
+ ~! I8 `& U8 C4 B4 L; l1 A        if( exsound_select & 0x04 ) {" R5 }* l! \* e9 ^" H& {
                if( addr >= 0x4040 && addr < 0x4100 ) {
! b- n  u+ S, q( w: j4 t                        fds.SyncWrite( addr, data );! B& }  d0 S! h. u8 k" x
                }
# Q" ?  v, J+ d4 ?7 J5 x        }0 f! I' E7 Q8 {& p7 O+ u! K

5 p& J6 `8 Z% E  }        if( exsound_select & 0x08 ) {" [6 h' o8 l4 c& Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {9 I, k  s4 ^: k: N8 n! ?
                        mmc5.SyncWrite( addr, data );1 C6 v+ ]* `5 k1 ?/ d$ @1 c
                }
: o1 m, y8 O* |" y; N        }  `4 }3 q# F; ^+ b2 P
}
9 Q# m6 F8 F2 ~8 \4 J% v* o& O  }1 `$ {* h
void        APU::Sync()
- k6 S# J! s0 C7 \7 H{2 G4 u, T# O) r7 O. a
}
5 R+ \( I, M( i$ o6 w& Z  h) O' c, K( A
void        APU::SyncDPCM( INT cycles )
" ^/ D. R7 U% U+ {/ y{3 }0 T; R' _7 ~& Z8 b8 b# j- ]
        internal.Sync( cycles );5 C* t- f" n7 s! ]
! f1 R5 u1 w4 E5 Q" {& \- F
        if( exsound_select & 0x04 ) {
# B  s2 ]$ _9 F8 _9 K# S7 i                fds.Sync( cycles );  E5 ~$ d, o  ]6 a
        }3 E4 E. T! F* q0 e
        if( exsound_select & 0x08 ) {
8 J* f# Q9 D' D6 K6 H                mmc5.Sync( cycles );
$ U8 [& j5 X! {# B- Y        }
+ Q* U: ?: }: f! A: F% ]# }1 t# I}
- h; f5 E% U3 O  p0 t
8 ]1 q- D- W7 Q+ Y, Hvoid        APU::WriteProcess( WORD addr, BYTE data )
% }. C9 a  ^$ t. z( z9 x{
; ?2 O; S- P) r        // $4018偼VirtuaNES屌桳億乕僩- z$ g1 `) V- Y% t! M2 p5 k6 {
        if( addr >= 0x4000 && addr <= 0x401F ) {
& t+ a: b0 v! N$ F+ ^8 s" t8 y                internal.Write( addr, data );1 F1 J- L8 n9 K# j" [
        }" f: D/ ]. f0 S% a' F
}$ N; p6 i# Y0 }) T

* p* J4 o% P( Z* }. `- e- Tvoid        APU::WriteExProcess( WORD addr, BYTE data )6 W5 [% ?6 P+ c! [: L' N0 `1 F
{
  `! R; p# R9 e* e  i9 x& {4 @        if( exsound_select & 0x01 ) {, P9 V+ q2 A( v8 }: u
                vrc6.Write( addr, data );
9 ]' F. M8 m) |' [! U        }
9 a* X- Z* l5 S4 c$ `9 t) k2 ^        if( exsound_select & 0x02 ) {
$ [8 t% X1 s3 R& l                vrc7.Write( addr, data );
, M% R, O" F( c: Q5 v( m        }
6 V) j; e5 n" t  k7 B        if( exsound_select & 0x04 ) {
. V" l, m" o; n                fds.Write( addr, data );
8 i3 m* e: ]- E6 R" Q8 x. c3 y% a  C. }        }
. R9 Z3 n8 a- N' y9 v0 T        if( exsound_select & 0x08 ) {
9 M" a4 I* L0 b# r; e# o                mmc5.Write( addr, data );+ x; N+ q/ Y2 O! Q+ K+ u
        }
5 |) g2 s# F* M3 w& o9 t  _: E        if( exsound_select & 0x10 ) {4 ?& Y5 X* N  }2 \; u+ D& w) k+ _
                if( addr == 0x0000 ) {  s8 ]9 ]% Q7 c( o6 Y  K( O
                        BYTE        dummy = n106.Read( addr );3 ^8 V* d% L. t9 f% w
                } else {% [! I4 e1 h1 \* n4 g- j( o
                        n106.Write( addr, data );
, w  z8 d& U, o1 G# W                }
) T/ B: j! O9 W, d) H1 [( [        }6 V3 Q9 n/ @* @! o5 c/ ^
        if( exsound_select & 0x20 ) {
: W0 n: e% D7 `% [5 S4 p                fme7.Write( addr, data );
! `1 D" J& w  ]; B        }1 W+ p1 q, @; @" Z+ j! ^6 v1 x" H2 o
}
, ^) {  A9 [& p7 N8 A- H# d. C
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
8 g: g' z+ R' `# U) P{, F+ c7 L7 C9 e% |: r( Q% ?
INT        nBits = Config.sound.nBits;' N% }8 h/ w) c. q: t7 f6 q# O# l
DWORD        dwLength = dwSize / (nBits/8);
% ~: i& [1 A: ?" M+ P" @INT        output;
3 u! j6 {( U% d& |: MQUEUEDATA q;% r$ c4 ^$ `6 P! ^, Z  n* B, A
DWORD        writetime;
6 s( o' J  X6 Q4 N3 R: p- ?9 P0 ?4 \& F! L
LPSHORT        pSoundBuf = m_SoundBuffer;
( n( Z: j4 r  N) cINT        nCcount = 0;; @: ^: `6 K$ B2 I& l$ B8 g. Z7 L
$ ^2 j9 a7 r' F( U/ M
INT        nFilterType = Config.sound.nFilterType;0 {* R% d+ g' }+ q" k" U$ G1 |
% x3 p- q+ f# ~# R
        if( !Config.sound.bEnable ) {2 j& P3 _# q/ I( }% Z# N$ }
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* X1 N$ g. C7 o% L1 {. `" E" w7 d, ]  i                return;
7 G1 ~3 V, p: U' A0 J' N* p        }( d# g2 {4 ?2 O  E8 d
  i( n0 z: ]: M. O+ b8 L6 V  f8 a
        // Volume setup3 [7 ]0 X- y! e) T! o3 L, M8 i
        //  0:Master
1 x! |1 M+ J# d  E        //  1:Rectangle 1: k5 M  X. x7 |6 S
        //  2:Rectangle 2  E. W% x; z$ l. k2 X! C, z) M
        //  3:Triangle
+ S" Z5 `" _& {: ~* w  ^! M        //  4:Noise6 B# X4 a* L6 ~
        //  5:DPCM
/ V2 B! C$ I, \        //  6:VRC6+ `" E& }4 @9 h. e% I( ?& ]  o
        //  7:VRC71 w! l3 N0 U1 I
        //  8:FDS9 J7 X3 C4 M! E1 z& K
        //  9:MMC5
+ ^. w* z8 u# E3 i  M* M        // 10:N1063 F  L2 M. g: k# _2 m: a2 R: F+ |
        // 11:FME7
  d- q/ ]) i& ^8 _/ A: f        INT        vol[24];
9 C! I0 Z% x: s  S' b        BOOL*        bMute = m_bMute;
9 x# ]  u$ j* `        SHORT*        nVolume = Config.sound.nVolume;1 x' b& ?/ G8 L- S% F5 c

/ b' L8 [0 @, a0 Y5 v        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
1 P# L. D) M. ^2 W' I# Z3 G( V4 B8 {  h5 {; K; z) F
        // Internal
; ^9 L0 B! V) S! U  A0 X; p: k        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
& }3 t2 T* J; g        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;1 C2 V# v7 R# H5 D2 g
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
. W% h" r3 b  ^5 ^8 u( |        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;/ Q, W9 Q. U9 ?4 E& y% t
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  Y! i6 X3 u5 K2 R! A( e
' X+ ?' a1 k) C( y) e; d
        // VRC6, i' F, W) p/ t8 N) e
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 V. u' u% l1 R; [+ h  h
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  x' H3 z/ v/ t& a2 A        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( ~2 _& Y. |1 W2 w+ V& a, J  v" r, J$ s: r+ \6 D3 }- c
        // VRC7
2 P* W& F& [/ Q5 L( }        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
5 H3 p2 N& g) w& `( Q2 w9 V4 q  N
) @% C( o9 V* q# ?        // FDS& m$ v2 g3 ]) N& a. z) s
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;, b% P& s0 s7 ^! I, {1 B
7 z9 H$ V; Z' [3 v, D1 `1 y" v
        // MMC55 j1 G0 \6 V3 z6 Y9 \" L
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* r/ B; r: D, {* h7 i        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) \7 U& R3 J  k+ c9 f. M
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 [( e8 m9 e: G# ]
( z# Q+ ]% [' i) T  R        // N106# q7 w: v) R7 I
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ |; S/ Q$ @1 ]) w& M- _$ O1 [
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 L, G( g+ l# ^3 G        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: Y$ }; D4 t6 a/ I
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ [, K; O8 R/ S" e  O* O
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  }3 m/ Y5 L  L) O
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 @; @4 s6 |) a) _
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% `  V/ E+ w5 b1 y# |
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 L- T$ |8 I8 d- _- c7 D/ l
9 x- N( G: U% t
        // FME75 ^; R. G4 [3 x: d
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ G) A9 B3 t/ [" G
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 J- q* O5 K5 g8 R% f( w
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 b( E6 A1 y- T9 u1 m  T, h: s4 V8 N% x6 W1 p& d2 w8 D
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
* T  `6 b7 j& {" a+ h6 E        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 t; h6 h1 n  y/ m. }; R4 D

, ~- s: v7 v5 q( @9 j4 B9 n        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟; {1 A7 L. X7 [( M
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
9 l! `/ |0 Y* @* m& N9 M                QueueFlush();2 Z) i/ E  Q) U. k1 D8 R
        }0 U: w6 g4 A1 b/ c1 S% c" k0 G$ Q7 K

: B9 Y  u6 X& S( r4 }' r        while( dwLength-- ) {
2 h* P: d8 ^4 A" [: [7 r& c                writetime = (DWORD)elapsed_time;
; d8 H* z* O: j+ g- Q
% Q; V4 h9 h( D9 @1 J% {                while( GetQueue( writetime, q ) ) {
' l2 F3 Z) o: L/ u                        WriteProcess( q.addr, q.data );0 z, S* T/ _! \
                }, a) a3 e. J) X& d! W8 X- H; k5 f
* r" p# ~" i. a  t( ~% O$ W1 N4 [
                while( GetExQueue( writetime, q ) ) {( u' G2 K. v( ?. H1 O
                        WriteExProcess( q.addr, q.data );. @# G' |- J. e7 t" E5 W4 @# Z6 A
                }  Z7 B* \. E& F/ S( q

0 {/ p+ X2 E3 G& W                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- r1 Q, I, h, t1 {2 w1 k( i* E# o
                output = 0;
. }* h+ G9 a" c* Y& H  ], l                output += internal.Process( 0 )*vol[0];2 N0 E" \: R4 u7 }0 b$ g: N
                output += internal.Process( 1 )*vol[1];
5 }, R% ?( N" u                output += internal.Process( 2 )*vol[2];
" G) q& ^; ~# K6 ]! _/ a                output += internal.Process( 3 )*vol[3];
2 u- `" }" e6 T$ Y2 w. O( b                output += internal.Process( 4 )*vol[4];
1 K$ r5 p& f! i. A5 P+ r
1 W* l+ f7 R- o) Q. U                if( exsound_select & 0x01 ) {0 F0 S& ^# x" Y
                        output += vrc6.Process( 0 )*vol[5];- J* ~; ~( ^8 G9 t
                        output += vrc6.Process( 1 )*vol[6];
- m3 R# W2 m- J/ S. D2 i7 Y                        output += vrc6.Process( 2 )*vol[7];
; T! j# H- a: l5 e5 b0 H! K                }+ ^9 A7 G" Y' T0 z9 N
                if( exsound_select & 0x02 ) {; ]6 B" Y% p4 ]( D) U8 O& k! p) G
                        output += vrc7.Process( 0 )*vol[8];( u# y  l  Q# c6 @# p
                }- q+ e2 [7 o! P1 J
                if( exsound_select & 0x04 ) {4 J3 }" b$ P- e3 b% h
                        output += fds.Process( 0 )*vol[9];; @" N0 i! r: T, \; f) ^! e
                }
0 n6 ^7 |, e( O9 ]2 E                if( exsound_select & 0x08 ) {' M) k) ?( y: o( n: o
                        output += mmc5.Process( 0 )*vol[10];
3 ~9 `  B/ ^/ c                        output += mmc5.Process( 1 )*vol[11];9 V5 V* e3 T" T0 O
                        output += mmc5.Process( 2 )*vol[12];* {$ Z- }, }6 a- j. m  j3 J! F) {3 Q
                }- L/ y; b& b" U
                if( exsound_select & 0x10 ) {- R( W/ Q% h* L' O1 m' y9 z
                        output += n106.Process( 0 )*vol[13];
: X0 c2 \; d/ v1 h  b" g                        output += n106.Process( 1 )*vol[14];' [' s  m8 f9 Y% ^6 ?- i- y3 J
                        output += n106.Process( 2 )*vol[15];
8 P, Q4 a: y& y9 E& A) A                        output += n106.Process( 3 )*vol[16];
2 }9 c0 R6 z7 m* o                        output += n106.Process( 4 )*vol[17];
& N5 [1 J6 Y8 j                        output += n106.Process( 5 )*vol[18];) K, b/ I# ?" B& q
                        output += n106.Process( 6 )*vol[19];
( F, n8 ~( {9 m3 [2 Y                        output += n106.Process( 7 )*vol[20];
6 G( r6 R& o5 k7 [6 E( |8 ]5 c                }
" C, x5 b0 g; O# [# `                if( exsound_select & 0x20 ) {
7 q" x9 i% i/ O- _                        fme7.Process( 3 );        // Envelope & Noise; ^/ c8 V1 |! w! A& y
                        output += fme7.Process( 0 )*vol[21];
. V  G3 H: w# P. E                        output += fme7.Process( 1 )*vol[22];. L  ?1 y: S' n$ g1 B5 s) a
                        output += fme7.Process( 2 )*vol[23];
; G$ C6 @$ X) P' ?; J+ D                }
) z" T& |! D2 }# s6 [- f( `+ U! u: G4 N8 t
                output >>= 8;
' \8 B7 P- a; x4 w2 B" P! b# ~* `0 C+ h
                if( nFilterType == 1 ) {
( }& y& t, d5 Y5 Y  B6 h+ N                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)% s, [" N: Y, E/ o  j
                        output = (lowpass_filter[0]+output)/2;% J$ h! Y8 {0 w% t& k9 U( D$ F4 B
                        lowpass_filter[0] = output;
8 N7 h9 r; L  Y' v! K9 e' H                } else if( nFilterType == 2 ) {
0 Y9 o6 W" {; `0 l' p                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)5 @' O" h; q& _+ k
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 }1 \) g  v+ k$ U                        lowpass_filter[1] = lowpass_filter[0];! _% B7 f8 m% U3 j. {
                        lowpass_filter[0] = output;
2 z; q, X+ M3 c2 M5 t3 y1 ?5 n, _8 a                } else if( nFilterType == 3 ) {
% k! v. ?( d% C! g& N! L                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)* }; X4 S2 n" u; {
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
1 B3 E4 V9 }2 G2 W, I. a                        lowpass_filter[2] = lowpass_filter[1];
- m7 F+ i2 G, m' Y0 q1 f                        lowpass_filter[1] = lowpass_filter[0];
$ m4 y7 _  I$ R* K+ l                        lowpass_filter[0] = output;# q/ o5 G1 M+ {* ], b& P8 |. z
                } else if( nFilterType == 4 ) {
8 p* b7 W' k4 @2 Y                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ J. o* _( J1 [' A" b& t3 I                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;/ q( n- Q: S0 \, ]+ {+ D" i
                        lowpass_filter[1] = lowpass_filter[0];
) e; y5 h% Z! g4 c5 [+ N; ^" }& W' ]                        lowpass_filter[0] = output;
6 q: v4 ]4 Y% g7 ~! c! q; a  N                }
5 j: a$ r- U+ B. g2 b* k$ [6 U7 ?  t' L) s" m6 X/ ?
#if        0
* \+ u+ q! m8 T                // DC惉暘偺僇僢僩
& i0 q: S% a4 r9 O3 a# j- d! a  w                {. G. Q" O' l8 h* F/ W0 S6 M
                static double ave = 0.0, max=0.0, min=0.0;
$ _; p+ W2 b3 e# N& N5 b1 c                double delta;
5 Y3 f! W# K9 \: X                delta = (max-min)/32768.0;/ x8 h8 }  t! p+ S( h
                max -= delta;
  H# b. A: \4 w6 p                min += delta;' }0 J0 W  W2 t; _; i* D5 t: C: J
                if( output > max ) max = output;
2 s$ x$ \9 v5 S9 F$ R/ ^- d# P                if( output < min ) min = output;
: I% l# f, N' w4 ]* p  `6 g& A3 ]                ave -= ave/1024.0;
8 w8 P0 W- a* y6 O                ave += (max+min)/2048.0;
( V6 r9 g2 U2 X' H9 U                output -= (INT)ave;2 S7 L1 M/ _. w! p3 {  @5 j0 G
                }
$ k) g* Y0 ~, Z! Q. h0 w#endif3 ~- U' ~2 l- C
#if        1
! a" s- @3 ]1 l! S: q% u                // DC惉暘偺僇僢僩(HPF TEST)
% l7 r  q' }% Q5 d0 {                {' A$ K: y/ i" I" E8 J9 I
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
0 k+ O8 w6 ^8 g                static        double        cutofftemp = (2.0*3.141592653579*40.0);. T( v% `2 V: K7 d; x; J) F
                double        cutoff = cutofftemp/(double)Config.sound.nRate;* H4 O. x* ^0 m
                static        double        tmp = 0.0;
0 Q6 q# W! W+ y& f                double        in, out;" [: h' D+ I6 q0 h- o. Z3 k
2 n( |- c, }& j$ A
                in = (double)output;
) C* @( z# Z6 s4 j& M+ _                out = (in - tmp);
- f! @/ ~2 n$ H  C3 [! b% t/ o                tmp = tmp + cutoff * out;
& u: Q& ~: p  [+ u8 g- D9 |3 i& o
                output = (INT)out;
) b0 p  Q* C3 `$ N* r                }+ W4 Y+ G) a) F, I, x; U# I
#endif
; p) [! ]* u2 n! a* X$ n1 Z  @#if        0
7 y0 C& u. z+ W& R                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)' }! Y' N$ u5 t3 o: z9 T+ V
                {) f6 I0 J7 w5 J) G. w3 T0 d" w
                INT        diff = abs(output-last_data);
, Y: A& [  O" B- G5 H, p                if( diff > 0x4000 ) {1 j- d, v3 Q0 A
                        output /= 4;5 V" y' n4 d$ b! F+ y0 I
                } else * Z, G. y8 ?8 Z; v
                if( diff > 0x3000 ) {
6 F$ c! |% O& m5 L: t, T7 L" h                        output /= 3;# G5 h) _) {: a% Q# R
                } else
7 g3 H; [& l' Z+ g' k                if( diff > 0x2000 ) {) S- O+ r' K% V2 `4 K
                        output /= 2;8 G5 v( X! h* [: D
                }
- [6 {5 l% `: w- @( Y                last_data = output;- c4 H; j3 I; T
                }
# k3 \% L' ?& G, v7 r#endif
' u1 a6 L/ f9 c' s7 `* v. U                // Limit
  ?1 e$ b5 R' }* U                if( output > 0x7FFF ) {! V: @* F9 o- A
                        output = 0x7FFF;1 P# ~- l+ V. B- u; m: k2 K( _6 W
                } else if( output < -0x8000 ) {
( Z7 P# }& E& v- C' z                        output = -0x8000;
' o4 S6 p0 K6 Q/ e                }7 k, S. v. j1 v2 m$ Y2 W+ a* C
9 n# W' R  ?  X. r, c" A# q7 D3 `8 L
                if( nBits != 8 ) {
" N! a4 y' j; ~0 ]                        *(SHORT*)lpBuffer = (SHORT)output;8 H% O' @4 i/ Q& J2 a1 p
                        lpBuffer += sizeof(SHORT);
2 T* G& S0 F8 g+ a$ ?4 Z' V) I" f                } else {
3 S4 w* I) \. |7 ^" z- |5 y9 L7 N& E                        *lpBuffer++ = (output>>8)^0x80;' k, @0 S: X  ?- E7 Q
                }
- s" u, f* i2 @% X
/ M9 N9 P( S/ W! T4 u8 U4 A) g                if( nCcount < 0x0100 )
% p; _/ q8 I+ p4 S% R, u                        pSoundBuf[nCcount++] = (SHORT)output;
5 d) X% }/ z' n) ~  m" {- p3 V5 r* A; E5 R6 {5 M' B! G9 X8 G- k
//                elapsedtime += cycle_rate;
. W( |+ a$ Y9 ~. a                elapsed_time += cycle_rate;; B* b/ k& ~9 y$ I6 s' q$ n
        }" w/ A% s, S' s2 @) Y! M% |" ^

0 u6 Q- N: _( Z; y! q#if        1
4 m! u; x* X2 _5 |! S8 i4 s( c% N        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {0 T: h1 e& A: X, [( \+ M% U' D
                elapsed_time = nes->cpu->GetTotalCycles();* z! ~6 C7 ^+ B; f
        }
' Q/ Z5 z: |- a" @& W) W( ^        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
8 k' @0 M& s1 ~! F, D                elapsed_time = nes->cpu->GetTotalCycles();
, z3 H" [( n7 k        }
( \9 G: v' i. J6 i1 ?#else! i* e: B0 `( E, C/ l- w* K9 x5 ]
        elapsed_time = nes->cpu->GetTotalCycles();6 Q+ _9 h& A  H8 m: m
#endif# w- T/ Q) f- r
}3 _4 B  S" D. L" G- L, y0 L

' g- |. `9 A4 {5 i// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
, L0 L" Z7 J+ K  j& v7 }INT        APU::GetChannelFrequency( INT no )1 U" a& v$ b" W) O, z
{
  Z$ x, @! @5 @9 O' S# k: }        if( !m_bMute[0] )
) I2 ?; ^8 b' P6 _                return        0;. s; @0 G( s* H- G

4 w# p9 v" x- U        // Internal  n& W' `! t4 f! k& j' |8 R
        if( no < 5 ) {
" h0 Q( w. A5 i; G( r! h                return        m_bMute[no+1]?internal.GetFreq( no ):0;5 b( u, \- h# A  K3 Q6 s
        }
  W) ], N" e0 f# F, E. s" t$ u/ B        // VRC6
+ e) y' _2 B3 M2 i" K( l        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* r$ O3 V, _$ p! o" e& G2 N. o                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;5 e( n" Y% w# r, Y5 }0 I
        }+ s( @  m7 [$ Z+ X5 i" m+ d
        // FDS
8 o  m& k. s$ g        if( (exsound_select & 0x04) && no == 0x300 ) {* I8 \( e/ d4 o6 `8 u
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 q0 S1 g9 m$ V( w% @" `6 Y+ ]        }; W+ T( f6 C% W" h5 M0 p( F: R
        // MMC5! R( ?6 ]# I6 Y; \
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
% z7 H  b( x; p                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
5 p4 ~& C/ \; @( x3 v9 X        }
8 i. y5 [" g( ?3 ]        // N106
' i7 G* I0 T! a9 c' m        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {7 l3 p( W  h9 M) z& D
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
) a5 R, B5 T' l+ \- S3 k: n7 T        }
* H" T5 |" v, k) j  A7 A        // FME7
3 t2 u/ A# u( H        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {0 i- F( C, _6 i1 D! [4 y
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
6 L- t* u1 W# R4 s        }! _( M$ z9 J# Z$ B
        // VRC7
, z) c$ t, B/ `6 `3 p        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: i& I8 u' |6 {7 w& B3 W
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
# Z3 @' @4 y3 o! i% y/ d        }
1 P9 U3 a  V0 N+ n+ Y2 _        return        0;$ L1 K* W% X. d6 j) m
}$ A- z' v8 Y/ d# e

' S& g7 g4 |# g1 ]// State Save/Load' u! E. P/ {: k; ~3 H
void        APU::SaveState( LPBYTE p )3 v7 F2 L' N6 N: x- a& Z- s
{  {% \( v3 A1 {3 E* E4 `
#ifdef        _DEBUG
. Z2 \9 O  S* g: ~  }7 PLPBYTE        pold = p;
6 Q% h7 ?6 A$ E2 N9 c#endif
; i6 n6 i* n0 r$ i4 {, g
( ]: T3 N# J& i        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
1 n, _: ]# n# n, m/ D2 u        QueueFlush();+ l" }8 D/ N5 H# U2 X! j
1 d' u5 R+ R* K9 P, ^+ [
        internal.SaveState( p );
. g. l, D! h9 r2 ~3 v6 J( n7 F        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
1 C$ |+ I" x! S% c4 Z
3 p  F; G' w$ D+ I0 S* ?        // VRC6
% m# O. `3 p$ Y, y' k        if( exsound_select & 0x01 ) {
5 k# J! h4 K" [. ?                vrc6.SaveState( p );' e: n/ F( Z" e2 r  O0 V  m8 l9 B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& x) @4 U' l1 _7 u3 G. q        }4 q' P2 @: r" o3 t
        // VRC7 (not support): g8 ~* x! Q1 W5 R; m
        if( exsound_select & 0x02 ) {
3 C. a) f  I  k; W                vrc7.SaveState( p );. z1 Q; P. O1 H: `6 g* Q8 q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: T$ `0 S) ?1 x' @2 N0 v" v& C0 Q" O# X: @
        }! F0 a# z& h; g: \- _' N( l+ o
        // FDS
; G' J0 {( M; }8 P8 l! M        if( exsound_select & 0x04 ) {* p! j4 _( n+ d, l3 c1 A
                fds.SaveState( p );( s. X" O2 ~; K, N4 ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% r. t8 N; p. t6 x/ Y        }3 e9 c$ ~' [$ f, |
        // MMC5. X3 ^" l( P1 x
        if( exsound_select & 0x08 ) {
( R  f/ q  O2 B! m! V                mmc5.SaveState( p );3 h& d) O2 `. c1 H- @
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 I! p+ B. ?/ s2 {+ `1 c$ V! r! E, f        }7 \. D; c# Q! ^: Q. H" L
        // N106: G0 E8 d4 J% v2 J% B
        if( exsound_select & 0x10 ) {
  H$ X3 |; p4 t, l8 }1 c                n106.SaveState( p );
% |4 {5 v4 `$ C# N                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 \$ X4 @% O/ p5 i
        }: Q, h2 R( K( p0 }! {
        // FME7
. F6 T/ [6 k9 e  V7 V3 @        if( exsound_select & 0x20 ) {" q5 D# d0 ?, c9 m/ p" N
                fme7.SaveState( p );
9 m9 T$ e4 J: e  l" u, n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 ]: y% \: q' @8 s: ?& v: L* C
        }
. r; `, }# k2 U# d  l+ B
" U' X! x: H  c+ [7 q* N#ifdef        _DEBUG
7 h0 ~% W7 r; R5 eDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );3 R( Z+ b3 K8 A
#endif) |  M6 _1 Z& y% K0 I, w# a
}7 B$ U6 Q0 }+ W4 f
7 j1 }6 M# c; l* o; L' W* ^
void        APU::LoadState( LPBYTE p )
1 m  K5 {/ @0 W: u+ W{
0 z; i1 R! }- N/ M5 W. i, v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡% ^6 R9 w4 |1 l
        QueueClear();4 T! l- b7 e1 f% y6 N

9 b* n% p- Y& j6 f; u' A        internal.LoadState( p );- N2 M' N, o4 C" F
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: o  ?* A. X) d) b2 n5 c% w, _& B2 y9 ]8 h6 E4 ?/ ]# R
        // VRC65 s  m7 d* q2 q/ B! x
        if( exsound_select & 0x01 ) {7 n. Y: r( U. f% ?' [& A1 I
                vrc6.LoadState( p );% R( e6 O5 Z- ]5 N( p0 F6 c
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- c. F1 G$ P0 x% [; M3 m3 N        }
9 y; d8 e& _2 z' @- O        // VRC7 (not support)
2 T) W) A9 \& n4 d        if( exsound_select & 0x02 ) {* Q5 V; \, w+ o4 f* h! \1 l
                vrc7.LoadState( p );
6 ]$ u$ ?3 Z# }# t& t$ a                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; b% w; ]1 p+ X. K. W, p        }
% H5 q" \5 p) v4 F        // FDS8 A8 Z& u7 m) J+ X
        if( exsound_select & 0x04 ) {0 c  A8 s$ i6 p4 z1 @
                fds.LoadState( p );
, Z9 A8 ^  E. z9 m# V7 q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. \% B% D9 |1 l6 [" z1 z" m: }. r# G
        }  ^, l2 I: M3 d- S8 r
        // MMC5) Q/ f4 c( U2 {" m6 m- M
        if( exsound_select & 0x08 ) {7 I5 Y2 ]$ o0 G$ n6 g
                mmc5.LoadState( p );
6 {  P( D1 v  D0 V. a                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 Y; }6 Y* u: A
        }' X7 C( _- A. a' L) q7 W7 u
        // N106) p% R/ J( A/ @# W5 b  i/ S
        if( exsound_select & 0x10 ) {
0 I1 a* N8 Z7 B( `' I                n106.LoadState( p );
  g1 J; r/ ]( R5 y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 k5 l  i( b( R$ T% k* T- O        }
. j* ?$ n2 [( ?: k' j8 r4 A1 j        // FME78 u% R* }5 p# l0 ^" [
        if( exsound_select & 0x20 ) {, O1 [: T9 \* R: y" j$ y) W
                fme7.LoadState( p );
8 l# B5 `$ O& E                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 h; G, n. V. k. g7 f) f. x/ a        }
8 `2 a- J' g' l}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 x* w/ I# c: u  O  _' E# t& z4 p可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 d. k+ K; z, _8 Q) h. F( A
感激不尽~~
  i  L/ u: h9 S5 T& k; P
恩 我對模擬器不是很有研究,0 M; P& C; ?! h. {( ~2 H
雖然要了解源碼內容,可能不是很困難,
8 b3 m' ~+ j( x* d; z( B1 G不過還是要花時間,個人目前蠻忙碌的。( E$ c/ p  Y$ U( u  m1 c* Y- ]

# F7 P( c" L8 F0 `4 A給你一個朋友的MSN,你可以跟他討論看看,6 }  a4 c) ]& b
他本身是程式設計師,也對FC模擬器很有興趣。# L7 |5 ]3 Q  |' s9 k  f1 b6 u2 i9 p
! Z) L' ?4 U9 ?+ ]8 q# T; {
MSN我就PM到你的信箱了。9 o. l& }& q& w

0 ~% _* @% N4 }* _希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ T* r! ~' g- Z9 ^( B
呵…… 谢过团长大人~~

. \+ j# \2 _3 A
3 {* p7 W1 I) ?' ~哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 j0 z" V# c& ?) n
团长的朋友都是神,那团长就是神的boss。
7 Z6 c  W% E) q
哈 不敢當,我只是個平凡人,
: C! \$ q1 S7 r4 G$ F/ ]1 Q- K要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙7 X. ]% p& m0 j  |9 j; X
ZYH
9 U) s8 u- }. ]* gQQ:414734306; k" D/ W( Z6 k6 Y" ?. ?0 b( \  P
Mail:zyh-01@126.com
4 N5 ], E* n9 o- U) n$ v! x/ N) W: P3 O
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 l! E6 }+ ]$ w# r; t9 c# B/ w7 m
再次对团长大人和悠悠哥的无私帮助表示感谢~~
* e* K, i: C; R6 w) c
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-7-26 21:29 , Processed in 1.090820 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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