EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
+ d/ R% W9 f2 n6 S6 U+ APS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ ~$ M) C- x) f, m/ }楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 e3 e& }: \  z5 h7 S+ T! L9 l2 v7 [) g( |, i这里有相应的模拟器源码,就当送给大侠了~~
2 I/ k( Z, E9 t9 c$ X9 b4 P9 ahttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 . r" c, _* v- |3 t5 }2 K
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 `9 t! G0 |6 ~6 n4 v6 \1 D
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( n+ B# w3 T1 i$ n; l! B
这里有相应的模拟器源码,就当送给大侠 ...
" w5 ?6 o8 j% Y3 a: k3 a; L/ B
聲音部分(Audoi Process Unit = APU):2 ?/ p# ~1 B: L5 O3 B4 t% y4 F$ n
.\NES\APU.cpp( n4 K$ e& x! b6 C) O
.\NES\APU.h
8 Y  w9 Z2 j1 n  F
* C& Z6 H$ A6 e' r5 M( E
7 {0 N+ A3 I8 ~/ p影像處理部份(Picture Processing Unit = PPU):
7 D/ G0 m3 x% ]+ L.\NES\PPU.cpp
+ P7 j1 ]# V7 d. D: I.\NES\PPU.h
* f4 s5 m+ X1 ?5 {& L% l  N4 A& ]0 u
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 L  W3 a  R+ m(由于很多专用术语和算法机理都不明白,所以看不大懂……)  c7 l4 x) {8 T- J
//////////////////////////////////////////////////////////////////////////
/ Z; D: ^% {/ j1 m2 P//                                                                      //1 |3 l0 O6 z3 F' f, Z6 v1 |, f8 U
//      NES APU core                                                    //
6 S, N2 a9 J7 @, g% @9 I//                                                           Norix      //
3 z; P& u0 u, F. q4 J- g( J6 B' H//                                               written     2002/06/27 //, f8 T3 S+ A! [: J; L+ \
//                                               last modify ----/--/-- //
. \% K" A7 w* D7 U, Q2 r) K//////////////////////////////////////////////////////////////////////////$ T6 W0 }/ V. t! F4 d7 ]& w
#include "DebugOut.h"
2 u$ _1 M5 d; e' g0 @; S5 b#include "App.h"
. q& a: e$ ~7 ~+ B, m0 ?/ ?. }#include "Config.h"
3 _* O. d0 K5 d9 o  l
6 P) }6 Z- `6 k" G- P# [4 I#include "nes.h"! a" T9 P. I* ^3 y. W! [
#include "mmu.h"' G7 o! g2 Z7 o9 T2 k
#include "cpu.h"
" O  ]5 ~6 ^8 K0 G* D#include "ppu.h"
; P( Z. y5 z' b7 b, S#include "rom.h"
$ G  w3 e$ L# U: W* {#include "apu.h"
9 D3 s# v0 _2 a# Z# o6 U% q/ W% y* ]; c% v0 W
// Volume adjust; B) _. e' V2 e2 b
// Internal sounds- F6 V7 N3 }# G. L4 j. f/ `0 U* f
#define        RECTANGLE_VOL        (0x0F0)1 a% f6 q( i6 W; j
#define        TRIANGLE_VOL        (0x130)
2 K% R( P5 z- {5 r1 [- J) ?; k#define        NOISE_VOL        (0x0C0)
0 \9 Z/ o" z% H6 X' w& O+ R0 J#define        DPCM_VOL        (0x0F0)
' w" a* N% G" s9 x0 |" g// Extra sounds) E( A/ I, F; v7 s' W3 D
#define        VRC6_VOL        (0x0F0)
/ z; B: H3 M: V  O8 Y#define        VRC7_VOL        (0x130)
) q; S! f  o5 C6 K" ]  |- ^#define        FDS_VOL                (0x0F0)- ?, ]- K4 I$ ^; v3 i+ W
#define        MMC5_VOL        (0x0F0)9 E( b3 G3 Y/ \# D$ v5 }6 D' ~
#define        N106_VOL        (0x088)) e, _/ X! v- q/ d
#define        FME7_VOL        (0x130)4 ]4 G: ~; B8 ~- a$ `
! M7 V1 Y3 n. t  @
APU::APU( NES* parent ): z: N& k9 K( d; R' n
{
: d4 k  q% ?; F  Z1 l9 E        exsound_select = 0;# I& l- [* e/ V- v& D: ^! J. g
1 U; D2 J" Y5 U
        nes = parent;
+ }; Z7 m8 {! _9 T6 F# o$ b        internal.SetParent( parent );
2 N- J8 C$ W/ c
. u5 f' P3 K  h1 m9 u        last_data = last_diff = 0;3 X# D% R2 l$ Q' t

3 k4 d& K+ Y- E( u$ u- e* N        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
% b8 H/ S: o$ z& E
- Y' u2 Y8 O6 |        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# V" P$ g- j+ p0 @  N; z        ZEROMEMORY( &queue, sizeof(queue) );8 ~! {5 f9 |* i: u; V. m& I
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. J0 h+ `: ~- j) i' g1 Y* z& E$ s; A  m
        for( INT i = 0; i < 16; i++ ) {
7 t# V) [" T" B' v& \, h                m_bMute = TRUE;
, B8 O( v; P) Y8 ^: K) p' V        }! i/ t6 w3 ^8 Y) a# U* G; K3 V
}& M/ [* c' E* U9 a1 L% ]- a& O' p

5 V  Y6 F9 ~( L/ I( }  ~APU::~APU()' c3 _: ^6 ?3 i& e  D
{/ E9 @% K+ A, g# J
}6 \1 b/ H$ j- b* x# Q& E
1 r( L! E- Q' x' F7 I
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )7 S' ]: b  k; t7 z! s8 E. U
{
  a1 E: a4 t6 s* t' y        queue.data[queue.wrptr].time = writetime;
. ^$ q4 R8 Z" K3 d        queue.data[queue.wrptr].addr = addr;* m; ?$ F  Z) g" N! Q
        queue.data[queue.wrptr].data = data;" g( n6 I) y+ T) W
        queue.wrptr++;+ E; x- `3 P. I2 B
        queue.wrptr&=QUEUE_LENGTH-1;
7 F) z. W( v9 v8 Q9 E        if( queue.wrptr == queue.rdptr ) {7 G" D! c( y0 |0 W1 u6 F3 k
                DEBUGOUT( "queue overflow.\n" );1 a& l7 N8 w: r8 n2 D
        }$ q; F! u2 ^  i9 x6 P  I) p
}
9 ^7 h2 S2 I1 A1 g# d, h2 S, K- @: J8 C% X
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
( G* M/ N4 D4 O% k{) a8 E: |) b5 S) R2 _
        if( queue.wrptr == queue.rdptr ) {
, b  y: w- Y- I% [$ A                return        FALSE;5 a, m* b4 i' Z5 b; V9 m
        }
2 |: A$ R' B1 w9 T        if( queue.data[queue.rdptr].time <= writetime ) {/ \- M3 L* }5 S' J
                ret = queue.data[queue.rdptr];
# a' h7 m1 y$ l8 s8 Z                queue.rdptr++;9 \+ x4 Y7 H8 F! V3 t% K
                queue.rdptr&=QUEUE_LENGTH-1;
2 U% H9 T; V# b; \& N; K                return        TRUE;% Y% {/ b  a8 S. l. n- j$ R- k9 J
        }
/ |" d1 ?; M! ]3 Y4 j- R- @7 w. i0 `        return        FALSE;
+ ]. h, h4 _! Q; K9 i; [# [( ^}% \( Z# q, R# ?; I  S) M& r* ~
7 p) c. }* D( n0 Y
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  C2 G3 m; y- F" s' M1 o
{
9 G; [) w9 l$ P; S) u! O" o+ s        exqueue.data[exqueue.wrptr].time = writetime;
& K9 h$ X+ p5 W* ~0 J; U' z) H        exqueue.data[exqueue.wrptr].addr = addr;
; s8 L  P4 Q+ i. M& H        exqueue.data[exqueue.wrptr].data = data;
( [* G1 _5 b5 _( J/ Q4 z        exqueue.wrptr++;& Z: Z" V% h0 x5 i( e# j3 X
        exqueue.wrptr&=QUEUE_LENGTH-1;
3 t! s. X; k; }        if( exqueue.wrptr == exqueue.rdptr ) {
+ P4 P2 d$ E2 E* X5 s                DEBUGOUT( "exqueue overflow.\n" );
+ I, i8 m' Y; k        }
. X; Q! q+ q5 h/ a9 M}
9 Q5 {0 \) E4 k& h! z+ e
6 `, p0 ^! p* G1 X$ h- fBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )3 G( u8 q7 K$ ?% Y7 w
{
# P! U6 T. j/ i0 l2 P5 w        if( exqueue.wrptr == exqueue.rdptr ) {
: x6 B5 l0 i, o, }8 o% f                return        FALSE;9 L8 K6 N8 c6 c% ?6 r( i! L
        }
7 W9 {" z( |  K        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 b, a( I* Y6 G                ret = exqueue.data[exqueue.rdptr];( @, n: f; C( g$ F; }0 x
                exqueue.rdptr++;
. z1 W5 h* P# ?: a3 ^) R                exqueue.rdptr&=QUEUE_LENGTH-1;
9 L; E5 S/ I. F: A; T                return        TRUE;* C- \% w# K: S
        }; _) g" I- u  L3 ^
        return        FALSE;
: V; `, W) ]0 \! B* R}1 s1 {8 b1 n3 n+ }1 }
; p1 @. T. y4 w0 b6 v* T& Q3 X
void        APU::QueueClear()0 s( e  j$ x0 D) n5 r* F' O
{
6 x! `; y. E0 c8 w: w* l% G        ZEROMEMORY( &queue, sizeof(queue) );
5 Z& o3 L! g4 G  U0 e9 y4 m        ZEROMEMORY( &exqueue, sizeof(exqueue) );. t4 p. t+ K1 F4 f
}
/ i* s( c" b- i% ?( ^% c
( x+ @! [6 a* n6 i2 w7 e; S2 Gvoid        APU::QueueFlush()
4 ?" M  S* t6 B6 R: _9 P# b{9 v9 o# E9 n+ h5 n4 @
        while( queue.wrptr != queue.rdptr ) {
5 ?' G: _6 `' M8 \/ n# }+ ?. f                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );4 Y- Y0 ^2 f4 I: O0 E
                queue.rdptr++;2 t0 w/ D3 t) S  G( X* r9 ^
                queue.rdptr&=QUEUE_LENGTH-1;4 _5 p, Q' v- k
        }
/ l$ {5 E! l+ ~4 V' c/ Z3 Y6 K/ p( t. a: Q
        while( exqueue.wrptr != exqueue.rdptr ) {$ o7 O; s6 Y, ]) Z4 Z3 w% S4 _
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 A) U0 ?/ c2 @- @) B* @                exqueue.rdptr++;+ y7 s. v" Q# Y& K: g% H( y
                exqueue.rdptr&=QUEUE_LENGTH-1;
% O, a( Z+ t. t5 C6 Z3 |" U        }$ g5 o' |7 C7 G. K4 h$ B
}+ i3 i7 g4 e+ ?: h
- ]4 T4 V5 H7 ^# [
void        APU::SoundSetup()
' o2 r9 t+ ?% w+ U1 v* @{9 r4 q  t- O! `+ E6 }( c  R  e1 K) F5 h
        FLOAT        fClock = nes->nescfg->CpuClock;: G6 Q0 t3 p) }
        INT        nRate = (INT)Config.sound.nRate;
: u8 ~5 ~) c  f; e6 X/ w, _; l        internal.Setup( fClock, nRate );/ b! j* E9 ?5 {. \& n) d
        vrc6.Setup( fClock, nRate );
+ }- N. ^) _$ m" x1 h        vrc7.Setup( fClock, nRate );4 D4 x9 ]. h2 r! N
        mmc5.Setup( fClock, nRate );
- N& g. B3 b5 U+ h        fds.Setup ( fClock, nRate );* |# [5 ^3 J8 q1 c7 ~9 e! n
        n106.Setup( fClock, nRate );
2 m: l$ d" z7 f9 A4 _  ?        fme7.Setup( fClock, nRate );* i8 W: G) I) W$ I  w( o- Y4 N
}
3 h. q; C( C/ x4 h& {+ Z
8 ^  z/ i( H! d2 p2 @void        APU::Reset()& O1 Z5 n' |8 F
{7 A  E* Y- L0 t1 }9 B
        ZEROMEMORY( &queue, sizeof(queue) );
/ f8 M6 E$ Y& o( P; e        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 r( J2 t, C4 D" k6 G0 b; X# D' m, g
  S- C) M6 D# K3 n: K& K# a* e/ Z  }
        elapsed_time = 0;
5 \. [. T  w  b9 |, t
8 Y/ E( Y9 k5 |        FLOAT        fClock = nes->nescfg->CpuClock;8 d( p4 R8 G2 x" t
        INT        nRate = (INT)Config.sound.nRate;2 D# E: }. T+ V3 U) \& k; w
        internal.Reset( fClock, nRate );4 _. c5 Z3 V& k% Z4 U
        vrc6.Reset( fClock, nRate );7 V' ^7 u. h- K: a8 H  O
        vrc7.Reset( fClock, nRate );
* V, R! T/ `6 u& A3 p        mmc5.Reset( fClock, nRate );: P* H( s  _7 }- N1 q  ?& S8 k
        fds.Reset ( fClock, nRate );- p) h, a# p" ^3 ?* |
        n106.Reset( fClock, nRate );6 u" i, |! u# j: C. t
        fme7.Reset( fClock, nRate );
1 v% i# R. C7 \- d! E7 I! T
/ _% s4 ~% S5 N  Y5 b        SoundSetup();
, I" @  q$ D" `: ^* y( S" h' q# @}* H! ~3 W  X- F) U+ m

/ ~7 z4 u% X! O: C- `. K% w; s3 P2 Zvoid        APU::SelectExSound( BYTE data )
6 e9 }7 W8 U0 O/ b{
, [; G3 g$ x7 v' S, E        exsound_select = data;. Z- {  ?- k" s
}% M: Q* M) L/ n, y% z$ H
% b. [6 b9 S6 B6 H7 O' F# [
BYTE        APU::Read( WORD addr )
* \5 W% s5 T% c3 `6 y{& q7 G5 f$ ~5 J
        return        internal.SyncRead( addr );' \7 v' O4 C! J
}
; N# O+ _& |9 \8 n4 K. H5 i6 P! b% w# ^+ k3 d+ K  @( X
void        APU::Write( WORD addr, BYTE data )* Y1 W, C& L6 a0 C3 |/ Z
{9 u) p# {$ N- m! U3 A0 W
        // $4018偼VirtuaNES屌桳億乕僩" d! k4 L$ Y6 i) V$ g+ }! ?  L
        if( addr >= 0x4000 && addr <= 0x401F ) {1 X3 ]$ O& a3 {' R
                internal.SyncWrite( addr, data );
6 ?" u4 n+ J9 H2 ~3 o3 t% Z2 I                SetQueue( nes->cpu->GetTotalCycles(), addr, data );5 o. i$ d, ^9 J1 _( g
        }
- _0 `% k# R; Q! [: B}
: @, ^5 q: w% D$ k# ~8 i
  b; b8 R% r7 f7 H; [# k7 UBYTE        APU::ExRead( WORD addr )0 u/ ~8 {* S6 m- X' c  I
{
- S$ k- Z6 X+ }$ w1 GBYTE        data = 0;: h( e3 k3 |# h5 q5 V

8 r( S6 W4 N& B( V0 z( o; |        if( exsound_select & 0x10 ) {
& z4 r: e/ c* y) x( `* z                if( addr == 0x4800 ) {! r+ ^  Z- A$ e* D; q  p* R+ g
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. S6 T% e* p; p0 s. w8 t                }
- e2 r9 Z, E; M' f4 v. \        }. Y0 R' C9 z6 X* D! Q
        if( exsound_select & 0x04 ) {5 c7 n3 v$ p& C0 _) H5 [. R4 w0 ~; g7 ^% t" O
                if( addr >= 0x4040 && addr < 0x4100 ) {
* F9 [6 R: G1 _$ `6 _  Q0 S( C5 c                        data = fds.SyncRead( addr );
( Q9 n* u+ J, Q9 G+ ^- S3 r                }- `* t" z! r- _$ \- [3 t6 c" U
        }! p3 |. j  u" I; _9 P, n
        if( exsound_select & 0x08 ) {
5 \9 a) {$ }+ B$ a4 H' T                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ u8 \) R( _0 K; }4 m                        data = mmc5.SyncRead( addr );
  e; N* I7 B7 `5 U9 d2 s8 l                }5 S/ u1 S4 j( E
        }
$ A+ H; a7 D, K6 Z6 L5 d
% o# Y4 t8 L6 w# b) Y% G' a. E        return        data;! L- v. N; o6 n- s. ]3 |
}( x4 h. C- C# C4 M' u" J/ l. x1 a

: v0 r$ X8 n" b0 z) p" zvoid        APU::ExWrite( WORD addr, BYTE data )
4 ^' Z# M/ l8 y. u$ ]4 i{
7 n- ^4 k9 t" D5 G% Y9 O        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
+ X: ~) l# I% a0 }2 U! v
2 R* W3 H& v6 |  I" ?* U        if( exsound_select & 0x04 ) {
# Y0 k; w" T8 [/ P                if( addr >= 0x4040 && addr < 0x4100 ) {  f1 Y: z5 S: I8 P4 d8 t8 z
                        fds.SyncWrite( addr, data );0 ]) p' V6 _, \* [6 ~7 y& Y. e
                }, p/ s6 W: N- I
        }2 O. J8 Z6 O! i" w$ H! x. C' G2 A

, @5 A3 ~: q$ R- s5 R/ X$ z        if( exsound_select & 0x08 ) {: z4 b' f2 ~" k$ S% H/ X+ p
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 c) I! D( y7 x+ W) R
                        mmc5.SyncWrite( addr, data );
5 r$ b( p' b$ q1 t/ ?( w                }$ k' A$ H0 C# Z3 I% q
        }
1 U: q) N1 B$ P: N" a! W1 c) C}
2 n) k/ l8 F3 T" ~9 U" A! m0 l
9 [+ h% b9 Y! y; X5 ~$ Zvoid        APU::Sync()  B, O3 Y. n5 X1 A, @0 \
{' E6 S! U0 D  j; g; [* Q6 X
}; D# U+ T% B) y' O. X! O6 u

- R- w% N$ o: J( y# `+ B6 Y- qvoid        APU::SyncDPCM( INT cycles )% Q7 V: P& V2 |8 D: d
{) \1 h. N. U7 `; t, W
        internal.Sync( cycles );% B3 @5 N6 e" |* x

6 B' t0 l% U  t/ C        if( exsound_select & 0x04 ) {
( l6 {8 d% Q( P( \- }+ h" i                fds.Sync( cycles );
3 m4 n/ U) V, Y% L$ b# n/ k7 Z. N        }
8 L  u5 ~- S1 W9 N7 L' P        if( exsound_select & 0x08 ) {' I/ d- B1 }5 m6 @  P# d3 J4 A% F
                mmc5.Sync( cycles );
5 n. L& x; \( d& i* u0 x& F+ @        }
' o, p  ~8 }. \* f! E% F}
' b2 Z, f. f% [/ q) ^$ l& g# Z3 s4 _) C) M% c% n3 c: N9 }
void        APU::WriteProcess( WORD addr, BYTE data )
( Z* J* q# ~/ _6 l{
3 ?# y/ O$ g( y0 p7 ]4 ^- w  r        // $4018偼VirtuaNES屌桳億乕僩
7 ^" q# O- V3 @6 Q+ B% N        if( addr >= 0x4000 && addr <= 0x401F ) {7 J2 T, k" k: r9 o5 x6 R0 O
                internal.Write( addr, data );8 c2 R% ~6 j$ o) g
        }
4 D8 i: {$ F9 Y  E- p8 m0 Q}
8 X- m1 u# s  g4 p; ?! I! K( [. a) L/ b
void        APU::WriteExProcess( WORD addr, BYTE data )
5 z: m7 L) ~4 U" n. P9 i  Q4 `{+ Z% B* p' s( a8 b6 r& i! e
        if( exsound_select & 0x01 ) {. p% J4 b" S* C8 u: O3 P
                vrc6.Write( addr, data );
. E: e3 G( y6 d* y        }, B! q' A5 H& k* ]; M& u: n
        if( exsound_select & 0x02 ) {
3 Y9 r8 ^; F4 K; E) ]- C  @                vrc7.Write( addr, data );6 @% O; k% G4 ~8 [, @
        }
; ]/ ^3 I# [( a+ `2 Y7 q" J0 j        if( exsound_select & 0x04 ) {3 ]8 d0 j/ l& j6 ?! z2 {, m
                fds.Write( addr, data );
. E, c8 E1 O' z' J+ L) @: X, d        }
& U. c: @; C2 F& G2 v1 ?3 c; U2 h        if( exsound_select & 0x08 ) {
7 G4 Y- a9 y5 t: f$ u. Y2 N                mmc5.Write( addr, data );% H9 z4 H% X- g9 d5 x) [: N
        }
6 N- g0 G  z4 N8 J1 t0 f  n6 |        if( exsound_select & 0x10 ) {
2 t: e6 [1 l7 _: j; }                if( addr == 0x0000 ) {
, g2 g) R6 o$ F                        BYTE        dummy = n106.Read( addr );
+ }3 z) e' E) {2 f6 Y                } else {
9 I% i% b2 H" Q5 v+ b7 Q                        n106.Write( addr, data );
& R! I7 \% g2 ~2 S( N  w8 \& B                }7 r7 ^% B/ ]$ i" \, s
        }- {- V2 n4 k% t/ ~' u% h
        if( exsound_select & 0x20 ) {
# U; Z! f( H" y* _/ m/ t                fme7.Write( addr, data );0 q$ r( ]3 h, x) w3 X* w4 }
        }
7 Z  P2 |5 g6 v* s" H0 m+ ?}
2 r* _* r* ^) ^  o4 g) k% j* e
/ |- k3 t% i  L1 [void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). T* W' \* t7 E5 ]  O
{8 p- i5 U( m: Q/ W# s7 n
INT        nBits = Config.sound.nBits;
0 w+ S: M8 A5 {& R$ TDWORD        dwLength = dwSize / (nBits/8);
% G+ S2 g* q, @" m- `, s4 IINT        output;2 x) Z- V! b( ~5 Q9 f, {8 I  _. S5 s
QUEUEDATA q;8 N% ]5 E1 s2 _! `# x6 `6 F3 N* i
DWORD        writetime;
. y0 N1 o3 @# P. s+ r* w  M. p: X0 U; p" H' Z
LPSHORT        pSoundBuf = m_SoundBuffer;
" t+ _/ a' Q0 |3 F9 F! rINT        nCcount = 0;! n9 j9 n* E1 P" G3 W3 R# d

* D2 \" L1 x# S) q' }  @; W) LINT        nFilterType = Config.sound.nFilterType;
! C; X: I& I# D" F6 q
: J4 r# r; c& h% E1 I        if( !Config.sound.bEnable ) {
& k! K) q3 u2 P6 f) X                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );( \" ]% C& c0 }! P* x. d# N5 F5 S
                return;
& y1 p+ w! |4 e$ L, k; F        }0 E; V* t/ h; t$ [5 j& Y1 y

) Y* a% J+ |8 M" n& y        // Volume setup
& O9 D/ b1 u+ F        //  0:Master" a( w3 v( E( Q
        //  1:Rectangle 1$ [- S2 K9 d/ J% A4 t1 Z  n
        //  2:Rectangle 2
( ~% H0 }7 i, h! r# N        //  3:Triangle
* e+ l$ }$ P2 _3 o        //  4:Noise5 x1 m6 \: g9 {' K2 A
        //  5:DPCM
: B- U" l% X- T9 p- N4 N        //  6:VRC6
) |$ M8 A# f; @) y. l& [        //  7:VRC7: H. s3 @2 Y/ Q, W' X  _
        //  8:FDS
& e/ P0 w/ c6 e  [) d4 M; l7 Z2 y' K        //  9:MMC5) {' o; B* q' z% ^  J0 p
        // 10:N1065 R5 S) b/ v" R/ v& p
        // 11:FME7
$ a* R+ ~& L$ U, }: t* n5 s8 [        INT        vol[24];) ^$ H" O3 y  U8 c* l4 q
        BOOL*        bMute = m_bMute;: }( d0 D3 w6 P( Q* a9 K" H% e/ I- |
        SHORT*        nVolume = Config.sound.nVolume;
! M% o) ?5 |2 u! v0 X% O  @8 d
# O7 i: Z  w' W9 f7 U' x3 g        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ i/ ~. p$ {1 s/ {/ Z" u9 P9 v7 c' B- K0 d& f/ u- C5 ^
        // Internal# l- G# l: ?. [  C) S. Y
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
7 m, Z: K9 Y3 \! ]. c7 I        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( O, Q! Y* n4 \+ f) Q9 @* c
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
7 f( e& y$ a% z8 `: u        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
" t% E- i& Q, u% s        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
# O" d6 u$ I0 ?; f- _
# r1 _0 S! ^& E3 T- F        // VRC6- o+ y9 h& p6 W. G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  U" T  s' X- q, `
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 k/ y5 ?$ S5 K( U  v        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! A. a+ `* m: o) E/ _& ~
( e0 F1 y) t$ S, I% Y4 e
        // VRC7; P2 M3 d  [( t  F) s4 r
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 @- O, _# N8 R+ U- Z
# r  g% ^; f( l7 x* p        // FDS, D) x6 g- N6 E& y
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;: j! W) W8 b6 f" z, N6 O1 l" x

- h. i3 W% o" I: R9 [0 d& ^        // MMC56 Z0 E3 \  A  S% F( W) n
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. C1 a/ |9 f7 ~- X$ M+ u+ E
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 ^; ^) G0 C7 f
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  x1 P0 G! o- Z$ `. e5 _( V0 I3 Q9 d! s7 ~4 A( h
        // N106
( K% B' I/ X$ K, t        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, k3 K0 f' r' f5 f
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 O: W; l/ J5 r3 T0 }3 B        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 y3 K$ ?, X% o# S. ~# S        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ b8 m6 u: X* ~
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 l- H2 R  K" h8 y5 W2 r& d        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' J8 |4 e% k# |6 e: r* b
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 {2 T# F$ n/ K% V% s        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 [3 _  `9 U4 x' f/ B

1 M9 O5 n* e0 ^8 M5 ?        // FME7, i2 B& G2 D' k6 |$ }9 Y; \
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; v: G' U. O" r  g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. T2 D. F8 S6 J. p% T
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 p) h: G( x  G
- W, P3 `1 X! H; w
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
: A$ t/ S) R2 O+ c# x0 {% q" G- v        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;( P6 {0 {# r. {* p- \8 X3 H
0 Z, B+ X$ S) O" k4 J
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟* Y; I1 w6 P- Z! A! r
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {4 `, N  c3 n7 }1 e! }6 d$ ]! a
                QueueFlush();& ^9 l, H& z- ?# }( ?
        }& Y4 {; m+ {. X, N
, Q6 T+ Y) ]$ V  O: [/ f+ f
        while( dwLength-- ) {8 Q+ R/ s! O7 o
                writetime = (DWORD)elapsed_time;
6 q6 j; v, A0 T# {
) U7 Q& V1 [! w, {" N% Q4 ?                while( GetQueue( writetime, q ) ) {
5 N8 D) j6 G$ o1 M  F% s3 `" ?! ~                        WriteProcess( q.addr, q.data );. o" ?7 M) G0 D" J3 m: y3 h( D2 Y
                }
0 ~6 G- a! |  m7 |% c2 z( b$ e" j2 M' A7 G
                while( GetExQueue( writetime, q ) ) {
7 I. V3 n( V( e) ?5 R, P2 V                        WriteExProcess( q.addr, q.data );
, o! S! k& k; ^# @3 O) Y                }
* \4 W9 K; c0 `* q. y& z; Y2 p& q! F% ?1 c9 C/ j
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME70 ~/ E- F$ L, G0 m5 W9 t/ E% L
                output = 0;
1 }+ R3 _+ w4 s  m4 s                output += internal.Process( 0 )*vol[0];
6 |; [3 N$ B$ P5 v" g/ G$ [                output += internal.Process( 1 )*vol[1];# z8 K0 ]  W  u) K
                output += internal.Process( 2 )*vol[2];
/ Y, s( ?. g8 _                output += internal.Process( 3 )*vol[3];- q& V9 ?; I1 V$ T
                output += internal.Process( 4 )*vol[4];
+ r  [4 D. `9 e" \9 X# f( o! G
( f4 A, u7 t2 P' X. C% e                if( exsound_select & 0x01 ) {* J9 i- X1 h" G/ O7 h) {
                        output += vrc6.Process( 0 )*vol[5];
  i/ i/ X' A0 I3 {                        output += vrc6.Process( 1 )*vol[6];
7 f" P; W1 y. v' N8 n2 [& n                        output += vrc6.Process( 2 )*vol[7];9 N" t$ w3 N. J  M3 ^9 Q/ E
                }
+ Q/ |9 m5 H) R4 {  ]7 a- R                if( exsound_select & 0x02 ) {
4 O+ P0 P. S! F7 h* j                        output += vrc7.Process( 0 )*vol[8];# w" {) T9 z: d
                }# @( B* `# y* u
                if( exsound_select & 0x04 ) {
) o  V+ c' c# }                        output += fds.Process( 0 )*vol[9];
2 i1 q1 ?+ l. @5 [                }
! b8 H! g9 \6 O: \/ d                if( exsound_select & 0x08 ) {
' _, C; w* }/ p3 u9 m' D                        output += mmc5.Process( 0 )*vol[10];
, i# O8 `2 Z1 w2 ?% V" a                        output += mmc5.Process( 1 )*vol[11];
8 s+ f, y; f4 h, ~3 [                        output += mmc5.Process( 2 )*vol[12];! j- N( u: o9 A1 B/ D
                }6 h1 B0 F+ O( M0 n" |
                if( exsound_select & 0x10 ) {
7 W' C% P2 m3 H; [                        output += n106.Process( 0 )*vol[13];& |/ b6 ~( W; {" ~
                        output += n106.Process( 1 )*vol[14];* I1 e& o1 d. ]3 V+ C
                        output += n106.Process( 2 )*vol[15];
' a- i) k5 y1 [, ]& o" |                        output += n106.Process( 3 )*vol[16];
1 d& e& O; I  c$ k                        output += n106.Process( 4 )*vol[17];% C* {/ h* o$ p6 X4 n2 Z7 ?
                        output += n106.Process( 5 )*vol[18];
6 [- R  K# K2 \                        output += n106.Process( 6 )*vol[19];
$ @) G7 h# [# r: A% _4 I0 s                        output += n106.Process( 7 )*vol[20];4 U4 @* [0 E' T7 Y) t
                }
! w& ]4 e& Y! f$ Q                if( exsound_select & 0x20 ) {
; j  k: I& b' e7 _% E% @( z                        fme7.Process( 3 );        // Envelope & Noise
& ~8 B& }8 S& [3 m5 u9 R. m                        output += fme7.Process( 0 )*vol[21];1 e7 t  Y: {" X  Y' h/ @6 U2 B
                        output += fme7.Process( 1 )*vol[22];( P7 L9 R# x0 Y
                        output += fme7.Process( 2 )*vol[23];
0 ?1 B% J2 O* p                }
1 l$ w* r' |' M0 ~0 |/ I" `$ ?- k% |* M' L- U1 V
                output >>= 8;, E9 p' `- M1 o$ s
" l$ J) D  U- K! Y) Z2 [
                if( nFilterType == 1 ) {4 S; T8 V4 M. }- l
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
/ n5 `7 u. L1 c& j0 z# R, ~                        output = (lowpass_filter[0]+output)/2;; R, H/ Z# m8 |
                        lowpass_filter[0] = output;
# V* P& f' X4 w                } else if( nFilterType == 2 ) {1 N( ]3 ?" K7 h, Y7 F- z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1); X. G% ^7 K$ h- _. f& D1 X
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;1 G# D6 Y: A/ C4 g- s
                        lowpass_filter[1] = lowpass_filter[0];* t/ S# L( c# C9 Z% b3 H
                        lowpass_filter[0] = output;
! w9 U/ h% q( |" K                } else if( nFilterType == 3 ) {
0 Z; I6 C8 @" s! O6 ]1 t+ M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
! v4 ~: j1 G' ]* m2 ~                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 l+ D/ m9 Q, e  M" t( ]. Y                        lowpass_filter[2] = lowpass_filter[1];
0 Y4 J; H: A. |" R- L+ F$ a                        lowpass_filter[1] = lowpass_filter[0];- e/ q( c5 n5 y7 }) `
                        lowpass_filter[0] = output;
3 D' ~0 m/ q. X0 G+ e                } else if( nFilterType == 4 ) {* m5 Z5 q2 [* r% X# c1 J
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)$ j: U& ?3 w. _* J& x
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( x8 z* V9 U8 ]5 X$ O. p- Y
                        lowpass_filter[1] = lowpass_filter[0];( M" H# N- n) F& g( i% N: D) T3 _
                        lowpass_filter[0] = output;
( B6 @7 y- C7 p2 e5 O                }: \; ^. U; g  q8 }

# N4 G9 K. L. j- y+ [#if        0, S8 o$ w$ K5 J' \; V& R" b6 A
                // DC惉暘偺僇僢僩0 ^$ p/ w% H3 |7 P/ X/ B3 [
                {, B( X% {9 c5 r3 h6 g- f5 L8 c
                static double ave = 0.0, max=0.0, min=0.0;" L. F, [  C# X4 H" j( i& O
                double delta;
) {: }; c4 R6 M$ L) C                delta = (max-min)/32768.0;6 e! x8 v3 S- a
                max -= delta;7 @/ B/ t1 _7 \6 u
                min += delta;# h: h$ z" |/ p' t
                if( output > max ) max = output;7 z. j( V/ n" [9 H, }
                if( output < min ) min = output;
0 L, G+ N. b" e$ O                ave -= ave/1024.0;
! Q8 I5 W1 t* k, V  q; r3 L& N. E                ave += (max+min)/2048.0;
2 l0 ?& _, L) a& H5 L/ O' ^6 p$ @& x                output -= (INT)ave;- ]! m4 B- T" e
                }8 e" o: V0 N) n; F/ \) g
#endif8 \% V: i. g3 v& d
#if        1( t0 \% o$ x# L
                // DC惉暘偺僇僢僩(HPF TEST)2 C# r& x0 n! K
                {
: O4 `& n# `4 j6 E# W+ \//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
2 r& k" o6 E3 y8 P                static        double        cutofftemp = (2.0*3.141592653579*40.0);
. W$ a7 l' ^8 a$ z, }  }! P                double        cutoff = cutofftemp/(double)Config.sound.nRate;& A/ Q5 C9 E# n
                static        double        tmp = 0.0;& Z! O* Q. x+ D" n6 c- }& G' A
                double        in, out;
5 x' i# ]3 u3 h  f/ R) M
: }0 P4 L. D6 i( X2 m7 R                in = (double)output;
1 H+ T* z& Q6 t5 J" \& h6 R) K) o8 j* `* k                out = (in - tmp);
3 s( `  f7 Q$ J                tmp = tmp + cutoff * out;, M, [$ J. y5 M1 r4 X' J

4 E. R! A7 n8 D1 X" o                output = (INT)out;
6 p1 W+ w* W( _7 s                }1 l) P' z# L; |. c
#endif
) {7 k! |, `- w. D#if        0
: Q! K$ P/ k. v4 t9 q                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)+ Q1 x4 R1 \: h" y: j3 [
                {/ f% |" p7 T. q. v. f" k6 H
                INT        diff = abs(output-last_data);
. u( I$ ]8 l% j( t& w. z  O8 C                if( diff > 0x4000 ) {1 t9 ?/ H) v5 G! ^) @$ P, a
                        output /= 4;& U7 }9 {1 }- M: T
                } else
; s# i- b, R# d  X1 H9 y- r9 E                if( diff > 0x3000 ) {4 f1 e0 n9 p) C: M& `! n6 X% ?
                        output /= 3;; r' {8 i$ M- e4 T" X# V5 g" B0 W  d
                } else" j& T. Q0 v! @5 e' d% j
                if( diff > 0x2000 ) {6 Y2 B" A0 T3 I7 m1 M3 k0 X
                        output /= 2;
( o! [' c  @3 g" o                }
4 ~% Z4 P" J9 K" x8 Z6 `                last_data = output;( K8 r5 ^+ n2 s! M8 w
                }5 W, i1 k5 Z, \! n. P* i; E
#endif: R! U3 x# o; a9 B3 V
                // Limit& S3 a* D. ]; x- H, H
                if( output > 0x7FFF ) {4 S- ?, `% y' f* Z4 o2 A: p6 b
                        output = 0x7FFF;
* n6 H9 \1 y4 R" ]* O                } else if( output < -0x8000 ) {
5 h/ F- ?4 y% ?                        output = -0x8000;
0 I. y/ u% R+ U4 g7 A6 i8 N: a& t                }, z1 y; R" o8 `% {4 U( \

0 e* t& c; s5 X& r( x6 S                if( nBits != 8 ) {
2 c5 v- C4 R2 ^% ^. w                        *(SHORT*)lpBuffer = (SHORT)output;
; d; a2 s/ Y7 h+ A9 G5 t                        lpBuffer += sizeof(SHORT);
! E, l/ m! B6 x; E2 b                } else {3 t1 ~" w- r# a$ f
                        *lpBuffer++ = (output>>8)^0x80;' H' t. h. T% }& @& I
                }3 U% z. S; ^) z- H2 K

. r+ Z. q3 ]0 S3 i+ Q6 r8 m                if( nCcount < 0x0100 )
. ~: T/ r* W) U4 P5 _                        pSoundBuf[nCcount++] = (SHORT)output;
8 k* W) k' w- y" ~$ {2 K7 d# W  ?8 ^) H6 I: X7 b0 e* X
//                elapsedtime += cycle_rate;
7 D0 j3 m9 {$ A8 o                elapsed_time += cycle_rate;4 q  S( R" U/ F
        }. b" U/ l+ j2 A; Y7 f2 x% B5 P
0 \6 |4 P  L: q2 q6 B* k5 U9 x
#if        1$ C8 ~$ f6 d4 j6 H( v* K
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
5 g2 h5 F" s/ t0 ^- M5 y                elapsed_time = nes->cpu->GetTotalCycles();
6 b# N$ D3 j1 {6 {' k. N        }
. L5 ?* p# P- G6 {7 ]% T        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
2 L* T! u) i+ D                elapsed_time = nes->cpu->GetTotalCycles();
6 D/ ~; I0 V" A  A! \: \- U- y4 r        }
2 ]( A# J( x- a5 u9 _! M7 V% K#else
. A5 ^& z8 b" N- z        elapsed_time = nes->cpu->GetTotalCycles();
) d8 B( f, ~0 R; N/ {#endif/ o. R2 l. T- m5 \" y6 z
}
9 ~3 m! V1 X9 @$ Q. l. y2 X
, m  z) h5 b' E0 c7 F0 @+ w. X// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* i8 h+ r5 x5 N9 ~( [
INT        APU::GetChannelFrequency( INT no )
- E1 @! D; a/ _( |1 V7 E{
) [) P" [7 S. N$ p        if( !m_bMute[0] ); t( o$ i+ Q) _
                return        0;
1 W2 V' Y# o! }! L% m3 G
' M  @% s- w! ]8 N        // Internal
- u8 i$ a$ B" m$ }/ [        if( no < 5 ) {* T% v. d5 @1 g7 ^
                return        m_bMute[no+1]?internal.GetFreq( no ):0;; @8 i) p' J; x, F+ K3 f4 j/ f
        }
2 v3 Q. q2 \6 G1 Y7 J* L        // VRC68 I4 O  F8 u2 ]+ b
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
- x0 ]% f9 h4 J! l* y- U( o" w& o                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
+ B: f/ W4 ^4 F1 a' d        }
0 L: U$ l; A# O6 x        // FDS1 e5 Q* u: b0 _, P3 X
        if( (exsound_select & 0x04) && no == 0x300 ) {
5 L( \, y. O, O/ a                return        m_bMute[6]?fds.GetFreq( 0 ):0;
' X$ }" O* P* F3 B        }& D, [4 }# {- I) R
        // MMC5
- s. I3 L4 l0 E* A/ W9 h; c        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {4 S5 X: N( M- B! g
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 N( a3 e. D' Z0 [2 H/ f" `
        }
0 g& y& |$ j3 S        // N1060 ~. }3 F5 u& Y  J) t; N; P
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* P8 Z; V1 j& P2 d: F3 i3 c8 J
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 w( L' G5 }! Y9 L+ u
        }, P' P- k/ ?7 j) K* v5 ~
        // FME7
$ {7 K( L' _, x0 w+ ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
; r% t0 x9 j4 Z; j8 C( s                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;" O0 a$ ^( S7 o  b
        }6 n" e, ]1 B4 O9 U
        // VRC7
# N- C1 l: j; r# T/ z. k        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
7 Y+ l" I& F+ P6 D4 B4 H; R                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;3 f# M7 ^, b( E# y" W& e9 J6 m
        }4 X+ n. S1 g' }6 E
        return        0;
& z* s8 l) V9 u8 n1 z; r}
7 g3 C8 A) D) ^/ ]% E7 {/ J  D
) P6 J  i8 A4 s/ Y+ b2 X// State Save/Load, x1 F# C. l6 Z! ^
void        APU::SaveState( LPBYTE p ), I+ N9 }' P: L# p0 P
{% G( G+ M7 M' i) u% y
#ifdef        _DEBUG1 p! ?' j3 W" Q- D
LPBYTE        pold = p;
4 H' U! R' Q0 {" m$ \% F' l0 F- k#endif2 h& h* `0 C4 A# ]! M
+ X$ ~0 U% _7 }. w) u
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞" I2 w- c6 A9 `  h
        QueueFlush();
2 y5 U8 V2 g3 Z1 P7 V1 B( G* t: S
        internal.SaveState( p );3 b# v& V/ {6 |* O* h8 ?. E& W
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% j9 [) J: W$ h+ a5 |; D: S. T. Y; y1 I
  X# v9 r5 |0 X% B, F9 C, {, V
        // VRC6
4 F0 Y6 l. s" N3 n; u; V        if( exsound_select & 0x01 ) {5 F) z- [) V7 l4 w* e
                vrc6.SaveState( p );2 i4 h9 f+ ]4 U. ^- e' x
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( _$ \# T. @0 ~" E
        }1 X9 }& Y5 T( U* v7 \2 w) A
        // VRC7 (not support)
1 Z0 r5 A" q, r7 i0 ^% Q        if( exsound_select & 0x02 ) {$ |" w7 r0 S( d% a& a& S  l, N
                vrc7.SaveState( p );
+ I  E7 x  z2 b! t, F5 w, J                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- Y7 q' }- v; v7 C+ {5 ]" D
        }3 ]9 X' g: w) T, a% p& B
        // FDS
( I- [. {" ]. ]4 d& d        if( exsound_select & 0x04 ) {2 Z) k( R! ]; d6 Z
                fds.SaveState( p );
2 R& O0 b* Z3 B                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* \/ P; z2 B: J+ K5 W
        }
! R# M( b% e, g8 o" ~8 V0 V        // MMC5) \: a: J9 T- `4 C1 C
        if( exsound_select & 0x08 ) {
1 G, n2 k+ Y! u2 G4 f                mmc5.SaveState( p );
0 ~0 R* w7 R- v, i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ `' f2 l- M6 O3 u* Q1 A3 z        }
" ~! Q0 n0 H" V+ G1 F, ?        // N106& d, w/ `$ O0 p' K6 I  b( ?3 M
        if( exsound_select & 0x10 ) {( O8 o3 ^1 @: f; Z  }1 J- ?
                n106.SaveState( p );
  f3 Q0 `! {# U& g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( S3 N3 d% V, _1 M1 A        }
7 `7 T. {3 n8 a. D        // FME7
4 k) O* c/ g7 I- B' m  J        if( exsound_select & 0x20 ) {
: W5 n8 i" p- l                fme7.SaveState( p );
$ w+ ?) {  W. X9 e$ O0 P3 M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ i1 Q0 x$ n2 L2 T: \
        }" `$ E# q, P. b' ~( R+ X) T1 z
) [# x/ n; M& E6 Y  Q
#ifdef        _DEBUG* c6 ~/ ~$ o' t, K" [+ {' R
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" F  R+ V; r' \5 E" \# g& D#endif6 ^9 U2 N% n6 Z' j2 c" f) M
}4 G9 O( `% _2 l5 U  B$ f6 B

7 R! z( \4 ?1 D0 z) Nvoid        APU::LoadState( LPBYTE p )) J3 ^9 ^$ [; K# N! b
{
; S7 h, [- L3 _9 g  S        // 帪娫幉傪摨婜偝偣傞堊偵徚偡1 H3 z/ l6 t8 H, i6 H- m! X' C. F9 J
        QueueClear();
6 o  |/ _3 z% s6 R  s
3 ?2 i; k0 a2 I& I* w1 F        internal.LoadState( p );* C  I3 [0 o' E( g* J( m* \
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ s- X6 a8 C' n/ Q# ~) H# ^
9 E' b) Y  M) c        // VRC6" o8 t1 N: `* T( p6 n& H5 r# [
        if( exsound_select & 0x01 ) {2 c  |' T* b; b" z8 P! O( M
                vrc6.LoadState( p );: C; `! L" B: h; P. u& ~& b% A* i
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 z+ i3 D8 _1 s$ v1 X( M
        }" b+ `+ {& u$ f" @+ H+ x: E, d- h
        // VRC7 (not support)! X' f- k* r# c3 j
        if( exsound_select & 0x02 ) {
( ^; P' l, v* I7 I! z" b  r                vrc7.LoadState( p );2 g+ b, ~3 W* I6 o! M
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 S- L5 V+ P: n& a
        }( R# X/ {7 N+ L' o
        // FDS% B& n" d: R* l9 ]5 @
        if( exsound_select & 0x04 ) {
; s5 h' h+ N% S; v7 k' ?                fds.LoadState( p );
; l. Y- j! Z6 w/ H' r                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. R/ A/ H; `' o) I; h
        }& E. z! _" s4 Y4 L
        // MMC5
0 M8 t7 A% c( n        if( exsound_select & 0x08 ) {! G' N8 I1 |* M- q- x1 I, D' ]& d
                mmc5.LoadState( p );6 T0 O- B/ j1 |" y- L+ T
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 Z7 ~% _. \: R" |0 r" ~) |- U. s        }* n+ M, f2 O- P7 c
        // N106  g, H4 D6 |9 i; h
        if( exsound_select & 0x10 ) {
3 w& X0 H* W. w- x- S( u6 F) ^9 M                n106.LoadState( p );
9 Q7 q( d8 F3 [/ Z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, J; j- L% h& O5 X* p        }; v, I  Q, s6 n+ q; \4 C: P
        // FME7& v# T" }/ `, ]
        if( exsound_select & 0x20 ) {
6 L8 g. t, O) n8 _, S5 h                fme7.LoadState( p );2 v+ v7 n! a: M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& r9 F/ T/ F9 Q# V! N. s7 X4 l! n        }: F6 i1 w+ t2 v. N7 V( R
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表   m! A1 _" z- `) Z2 I
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。+ `% M6 f; h* I
感激不尽~~

9 Y$ D2 R/ w4 |/ S& _  l恩 我對模擬器不是很有研究,7 z8 v1 ?, F9 P& ~* F+ J
雖然要了解源碼內容,可能不是很困難,. d' a4 L' s( ?& d0 ^
不過還是要花時間,個人目前蠻忙碌的。2 @5 i" w$ r4 g8 H( `- t' K* r7 `3 K
7 ^0 m$ x  x- L
給你一個朋友的MSN,你可以跟他討論看看,9 F% U3 m6 j! a: I: ~/ P3 ~0 Z2 F# L
他本身是程式設計師,也對FC模擬器很有興趣。# {9 [/ x+ X) M$ y  q7 X- J
1 S. n: c4 \( t8 J& h
MSN我就PM到你的信箱了。9 \* t$ e. U0 y* A

' `6 e  r* ~/ K- T7 ?5 e希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 0 A; p* F( S9 }5 `6 z6 A$ L# m
呵…… 谢过团长大人~~
. V7 U% G, b3 d9 i8 d" K

+ a1 }( p8 z! R$ r7 _哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 " z3 }, j; `) o; k0 X6 V/ b" \
团长的朋友都是神,那团长就是神的boss。

# f0 m; O% o5 t0 n  y0 t1 F哈 不敢當,我只是個平凡人,
% j2 U1 f# s9 @. K要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
, g. U& {: M( A# I* mZYH. k5 _5 o' Z; Q: T
QQ:414734306/ m0 o9 a' Z) ?; U1 y7 R% _) L* D
Mail:zyh-01@126.com
; ~2 S$ C/ a; k5 k0 K7 k/ Y; A' ^3 o# |7 d2 z4 V
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ! v; d7 ]3 w3 K6 P
再次对团长大人和悠悠哥的无私帮助表示感谢~~

4 y3 D/ f4 `4 j6 o  p不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-16 02:08 , Processed in 1.083008 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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