EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?9 H+ e& v- t1 r* k, k8 p% B( m$ m
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; }* K4 d( r  v4 E, U
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
- c' r/ D$ x: ]! U/ k( u. M这里有相应的模拟器源码,就当送给大侠了~~$ V6 ^+ d& n/ T1 s8 y/ |% G
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 G: _  ^3 m( N6 F: d% W! q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, _& l6 H) k  G% M5 w楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ |7 f' v) d/ c$ k5 R- D这里有相应的模拟器源码,就当送给大侠 ...

# d" F# J$ g2 C. o0 Y# ]% A聲音部分(Audoi Process Unit = APU):8 P; k$ L) k+ [: h8 U" X7 B
.\NES\APU.cpp
  h! |9 X5 X# Y) q" ]2 \& K! X.\NES\APU.h, U; A: [) g" E% M* k+ Z' P) `

6 e, o9 C- x( W. y8 p4 M/ G
' r" l" y" S; X6 O5 [9 C" i/ u影像處理部份(Picture Processing Unit = PPU):' S) n7 g/ k3 F' @* d7 K1 N
.\NES\PPU.cpp4 [# p3 k9 ]3 d' Y( i0 B
.\NES\PPU.h
" H/ R0 i+ A/ N* x; G
" f- |1 q( c& }8 p6 T如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
1 Y( g2 s4 g. K- f(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 K/ G$ F) K7 K! F8 {" D( F) B
//////////////////////////////////////////////////////////////////////////( J9 p# O( T; V( W/ C6 ]
//                                                                      //4 J6 k" E9 K! k; o
//      NES APU core                                                    //* G+ V- E- y! T6 I& P* v& S
//                                                           Norix      //: C  x7 F& \5 n0 R% Z% p! ~
//                                               written     2002/06/27 //% e2 ]& ^6 l. j! N- r/ H/ |7 O
//                                               last modify ----/--/-- //
! L3 M5 \9 o" z0 x0 @//////////////////////////////////////////////////////////////////////////
* l6 @, d; i& `# Z#include "DebugOut.h"6 ^0 D/ @" I8 ^" A7 o
#include "App.h"
- n4 T5 ^7 ?% D+ m2 Y8 L+ `#include "Config.h"
5 h1 W8 r5 Z7 ^
5 z$ e. c4 f$ [7 Y#include "nes.h"9 }7 z8 b' \, o1 D2 K
#include "mmu.h") s( }5 G( v" T$ ~
#include "cpu.h"
9 d" V" P4 `: m6 {. n+ p: l0 a#include "ppu.h"
! ~- f4 f% [5 @4 q* O7 o1 V" O#include "rom.h"$ I; @& s- |2 W% m- U+ P* W
#include "apu.h"7 r! u. G7 U3 N* C: X9 l
) o! e) |3 S$ B$ F1 `% }
// Volume adjust
& ~: @% a8 A0 _9 g) [! k$ c// Internal sounds
1 S+ f$ d- E$ i: [! I#define        RECTANGLE_VOL        (0x0F0)
3 `; y" Y, Q3 C3 Q! @#define        TRIANGLE_VOL        (0x130)
7 @1 n' ~& P# f) L5 r  L( V#define        NOISE_VOL        (0x0C0)3 P2 ?+ `) E: a& [! K4 Y
#define        DPCM_VOL        (0x0F0)  ^5 G+ Q  ^' |3 ~* h! |, _
// Extra sounds1 A0 a" \8 k8 `/ e- x/ f- [3 R0 j+ \
#define        VRC6_VOL        (0x0F0)0 [- {4 o1 k8 `3 ~9 S2 M
#define        VRC7_VOL        (0x130)  B/ Q; `- e. V* U' B! A% r
#define        FDS_VOL                (0x0F0)
" _, I0 q# t: b4 b#define        MMC5_VOL        (0x0F0); n# ~& w  X% V0 N% G7 t, j: a% g
#define        N106_VOL        (0x088)
5 Z% o. u8 N3 l$ \6 N#define        FME7_VOL        (0x130)
! a" D4 y# K- `5 X* I1 P+ p+ d4 |+ U* v/ P0 p
APU::APU( NES* parent )
) v7 n% T. U( \- v{
  g1 R% E' u5 @4 L        exsound_select = 0;9 b- t' P1 M% t$ q# n3 v9 u

9 w6 Q' K( a1 k1 U' K' T, o        nes = parent;1 j8 {. w* R  C! ^5 }1 e) ^1 l* ]
        internal.SetParent( parent );
- K% V+ C& x+ w$ @$ _2 y' n, O4 P2 p5 V! V' q
        last_data = last_diff = 0;
3 K9 N5 Q8 {( T" A6 F+ U/ ~" t
. a! a& g0 _! y: Z# j        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ g: J4 o. L& h/ I( _

( {7 Z) I& f. N% r  n2 N  N7 r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 B( ?/ y* }0 K( B4 V# ?7 Z6 y
        ZEROMEMORY( &queue, sizeof(queue) );2 {( k- w5 u: ?* j! `( o, l& T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* [: g+ w7 d: M% h9 |# _

1 r& J; Q3 H/ a4 k; Z% H* B  \( z! E        for( INT i = 0; i < 16; i++ ) {
5 p9 x- P) N' r1 H. l; l6 H4 o                m_bMute = TRUE;3 ], c( C2 g) i9 Y
        }
  h1 B4 G4 ]+ e}' ^5 S* O, x# Z  S  f! f; P; ^
( l/ r, M5 h1 N5 {3 J
APU::~APU(). D5 U4 B6 ]+ x% V+ d3 j( ^0 T
{' y8 R! d3 N; F" T4 n4 j
}, ^6 l0 L, C) e8 l3 ]

  B1 f+ ^* k' R2 c2 n( L" x" rvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& \" A0 U2 D" W{
; J$ p% C- l1 m& ^        queue.data[queue.wrptr].time = writetime;% M5 W" V) z/ R% H9 }
        queue.data[queue.wrptr].addr = addr;! B( q/ H: Y( b' n6 f/ h/ K' D
        queue.data[queue.wrptr].data = data;2 Q* U- r. M4 B" U
        queue.wrptr++;" W# X3 g% n5 j; ^! u' ]6 W
        queue.wrptr&=QUEUE_LENGTH-1;
5 k6 p% Y' P( u. M' R2 \" D# N        if( queue.wrptr == queue.rdptr ) {
5 E" a( b% D2 ?- ]                DEBUGOUT( "queue overflow.\n" );
, ~2 Q( \4 Z9 c# V2 L        }2 l5 s8 F0 Q6 i& v+ m( `% e( u" K
}
2 f) |5 I! e  D2 H
5 J0 P0 d- ?# J" {& gBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ), @; |7 s' W. d
{6 Q" _! ?% b, R9 p3 k% g" X/ x9 T
        if( queue.wrptr == queue.rdptr ) {
% n/ C( C2 u4 T. p0 I  r                return        FALSE;0 C  q" |2 ?/ J: ^0 D
        }
! j) l" p3 }# v: W, H; Q) L        if( queue.data[queue.rdptr].time <= writetime ) {
8 f. @. y! A+ s+ O( r                ret = queue.data[queue.rdptr];
5 ]2 |/ w% V* ?/ v$ h: p7 r3 n7 v                queue.rdptr++;
3 ]( F* V' F. B0 h2 M5 ?                queue.rdptr&=QUEUE_LENGTH-1;
1 n$ Z$ X( M$ e4 Y! w                return        TRUE;6 ?1 b6 ~# G- f* B* f3 n
        }
* j  p6 c1 M& M' _: C8 Z# v1 p) [& s        return        FALSE;
8 \- b" f# x- _- ?6 u}
1 o: g% D( H$ e5 L6 {& I# G& g3 `+ x1 v+ j. \0 C
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
- j5 }9 I7 N, e{
9 e9 i4 }" R$ k% A4 C* u( Q        exqueue.data[exqueue.wrptr].time = writetime;) C7 y/ ~, I4 D2 C! ^8 s: a
        exqueue.data[exqueue.wrptr].addr = addr;
4 y2 v/ d5 f  W) Q: F. y" u        exqueue.data[exqueue.wrptr].data = data;
$ |+ C* h) y: l2 i        exqueue.wrptr++;
: f& u  @+ v1 V) F+ G        exqueue.wrptr&=QUEUE_LENGTH-1;" I3 R$ L" W% G
        if( exqueue.wrptr == exqueue.rdptr ) {
2 ]2 ~0 g. s- A# M  m                DEBUGOUT( "exqueue overflow.\n" );
$ h7 _% E8 \! X  [7 S+ A/ Q1 ?        }! I9 c& a4 v0 }7 f
}
& s* g' X- d8 n+ I% p9 ^
$ ?: M. z! b3 |4 S/ B/ p8 `! EBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
& Y) l! E7 n. x{
, D- ~6 n) G& E* b' }        if( exqueue.wrptr == exqueue.rdptr ) {
, i: j% f* @9 S- ~* B4 c- t$ B                return        FALSE;2 H2 _: {. O2 n2 x" i3 m0 p
        }3 \" w7 B) z- ]1 i# R! `" `
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
. [7 k  _* p  m; H- h                ret = exqueue.data[exqueue.rdptr];" o' x' s' s" ~- A0 U/ B$ M
                exqueue.rdptr++;& V8 s' _' N- v+ a8 |
                exqueue.rdptr&=QUEUE_LENGTH-1;8 N) W7 `4 P1 }5 ~# m4 d4 l
                return        TRUE;
' k' L0 ^3 O9 s2 g7 f        }
$ p1 F) |7 a/ \  X) q0 M3 l2 j        return        FALSE;
4 V( n$ n9 [, p  l* k}! f. T& {5 ]0 J; x7 `5 m

0 M" X) o4 z3 |+ s4 R8 Q! rvoid        APU::QueueClear()( r# c' G- j9 `6 F* c+ g
{4 l/ p3 U' B8 h- q+ u# n
        ZEROMEMORY( &queue, sizeof(queue) );- d& _6 E5 q7 l9 `; O9 ]; T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 ^8 H- D/ \1 ]1 H/ r}; A) h* P8 b8 l$ r$ a

) Z1 ~9 E% U2 r: ~  x  l( e& S- @void        APU::QueueFlush()
- J% {2 p0 H0 w3 g+ X{
! u% ^0 h3 n) c9 `% x7 c3 o* G        while( queue.wrptr != queue.rdptr ) {
9 _& g! |8 k- t# t& Q. {+ T& E  B                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; D: S; h( _. I1 X* U' ]                queue.rdptr++;
/ m# I" z0 k8 c, m# H9 I  G                queue.rdptr&=QUEUE_LENGTH-1;: h+ G3 t! A4 F8 p# l9 E
        }
: k) |1 j: z! y# l! |5 V
& {$ G3 a. e$ d! N- ~        while( exqueue.wrptr != exqueue.rdptr ) {, a& f9 |4 Z* K1 A# O( t6 s
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 t" r% L8 X2 l2 x  N1 o/ y, T                exqueue.rdptr++;
8 }8 W( ^# D3 g$ C# x8 G                exqueue.rdptr&=QUEUE_LENGTH-1;' a# d5 t, `" d0 ~1 Z3 {
        }
% L3 r( @9 n1 a' \}
5 t+ a0 ?" E  J' y. D; p- L! A7 v. \4 y) K: h
void        APU::SoundSetup()
$ [6 Y1 s( v% ]{
( N4 K5 j5 W. P$ h% e1 D" z1 u        FLOAT        fClock = nes->nescfg->CpuClock;' \! B2 e/ e& b  H$ s+ G# Z
        INT        nRate = (INT)Config.sound.nRate;9 f% m: {9 u3 M" M2 V5 l
        internal.Setup( fClock, nRate );( J: F! j& h+ U7 P9 v
        vrc6.Setup( fClock, nRate );/ E: V' F5 P1 t7 i+ Y
        vrc7.Setup( fClock, nRate );, L+ }9 ^$ h& L
        mmc5.Setup( fClock, nRate );
* B2 I0 W) w* Z        fds.Setup ( fClock, nRate );; l: e# A( d& y, Y
        n106.Setup( fClock, nRate );
1 {0 f! g3 O/ f9 @        fme7.Setup( fClock, nRate );% I. Y% z1 j5 C1 D8 c) V
}0 {+ ?- Y& n9 X! R: U; [5 R5 a4 ?
$ X, [) Y. F: |' [! T6 f+ d
void        APU::Reset()* e$ C7 W- k! G$ ^. J
{3 w' M9 |( V+ N9 ]9 ?9 ]' z9 j
        ZEROMEMORY( &queue, sizeof(queue) );
% }% L5 K: \5 q3 W7 z% k! O5 H2 m; ^        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 v) }8 D& n, I: C% d8 q, h7 n1 m0 T7 C& h( c. D
        elapsed_time = 0;
& C7 q8 a8 B6 Y8 x! L' W  x7 f
( N: j9 D3 d' T" J& u8 U* w        FLOAT        fClock = nes->nescfg->CpuClock;% O0 w9 M; w1 G, T
        INT        nRate = (INT)Config.sound.nRate;
' F1 _1 Z9 l. A& Y6 k0 |        internal.Reset( fClock, nRate );( Z" G3 m# @! `' k' _8 j9 e( @4 D
        vrc6.Reset( fClock, nRate );" m0 n/ _, w& Z8 A
        vrc7.Reset( fClock, nRate );/ f7 E$ W5 d$ m( o0 v9 f+ M2 h$ B. d$ r' \
        mmc5.Reset( fClock, nRate );
( j! A* t$ H8 Z        fds.Reset ( fClock, nRate );
6 O3 ~  n/ C% r8 d( F( M4 l( f        n106.Reset( fClock, nRate );; b" z- R: m  k+ m  N8 x% m% \
        fme7.Reset( fClock, nRate );  T# V* f$ u# ]' w+ v

7 R1 ~6 i5 P" T        SoundSetup();
5 j* C' _& e% S0 k- p}6 [9 q9 [' [$ k2 q1 v
  ]0 t/ Z% N; y+ v
void        APU::SelectExSound( BYTE data )2 v$ e- I% D3 B( k
{8 W* t6 G7 c( P# a1 e# l3 {8 m
        exsound_select = data;
. h3 n4 x( v8 j6 R' P6 x4 t3 O}
1 n* M4 q1 H) J1 T& h& y1 D: \4 W5 Y( V( k( X) d8 H/ L
BYTE        APU::Read( WORD addr )
8 D/ j$ X8 i' t  `{
+ k2 u+ K; Q( P6 r0 T        return        internal.SyncRead( addr );. S* M. B/ u8 i9 x! x& c+ S
}7 S  _! r+ O8 w7 e9 l( q+ M3 H4 o' j

8 `! ?7 `' T1 f3 Rvoid        APU::Write( WORD addr, BYTE data )3 g$ `7 C  x- L$ X( y: _
{3 _9 p: w# e1 E+ Q% ]- ]
        // $4018偼VirtuaNES屌桳億乕僩% \' d/ y) X- S* K* W
        if( addr >= 0x4000 && addr <= 0x401F ) {
- }  u, S1 F" h$ w& O( C5 K" h                internal.SyncWrite( addr, data );
# G( Z8 _: `9 }! K5 N7 x5 }, d+ h                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 m; ]4 l5 ?' [* c
        }
  \# h6 `4 Y2 @% X6 q: o( F}
# s6 m% Y: U% x7 ^) n7 y4 N2 Y( \( ~$ s& ?
BYTE        APU::ExRead( WORD addr )5 p& N6 n: L/ }/ W: d/ T
{
  {  F0 i! i! G& zBYTE        data = 0;0 q* }! V& Q# I+ f

7 e+ c* \  o' b, V' w        if( exsound_select & 0x10 ) {
4 d8 u, r9 u3 Q9 u                if( addr == 0x4800 ) {; n& K" N" [- {2 f
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- m8 }: a% D  a6 K; b8 o* ~1 F" v
                }
5 K. a: B. o1 J+ Q* J9 P% ~$ j        }
/ V5 V( ^& F3 L" `9 g        if( exsound_select & 0x04 ) {& v( l7 m6 x- w# b+ A
                if( addr >= 0x4040 && addr < 0x4100 ) {$ k* [7 A, ]) b' R+ P& _
                        data = fds.SyncRead( addr );
( Y( Q$ E4 h# h# D$ e                }
/ z' ^2 N0 j! r8 o        }9 `' r7 ~- z$ ?# h) q, I4 S$ M
        if( exsound_select & 0x08 ) {
; ^2 b" f% G7 |6 x                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 C! S2 g( G& t9 l& j$ ^4 `9 Q  i                        data = mmc5.SyncRead( addr );$ a( \. Y" }4 l( I- v0 }% S$ |
                }
3 y) C! }: l  o& I0 s' a        }4 V( ~6 G  q2 O. V! t) ?/ L
# V  T" b. I8 B
        return        data;
# ^+ Q% u. i5 S6 }4 N! l2 ]; e}
. x6 P8 U1 l+ o, d4 O  I
/ S& s; H/ O0 I2 k. \$ Hvoid        APU::ExWrite( WORD addr, BYTE data )
8 v* E+ ]% S) c. ?5 X{
3 c2 z7 }; m7 S6 l0 |6 Q" T1 ^        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" G0 t# t* x: d* k& G; w8 ^7 q0 R% R3 T" ^' E! C' ^5 ^, a  |
        if( exsound_select & 0x04 ) {3 G1 L: ]! D5 O3 ~
                if( addr >= 0x4040 && addr < 0x4100 ) {( q. `4 ^, Y0 P6 ^  v+ _
                        fds.SyncWrite( addr, data );
+ |2 r8 l( [2 n. u" W: W                }$ z( w( v; I: _9 i9 f# _" _* v" h6 G
        }, H, k& g: W2 {, L7 p

- X) Y, A% f1 q2 O- f        if( exsound_select & 0x08 ) {
% m. W" v2 h( ^# A7 N, ]                if( addr >= 0x5000 && addr <= 0x5015 ) {+ f. m/ ~" }. g/ E/ C# ^+ B) B
                        mmc5.SyncWrite( addr, data );
+ Q4 ^4 ]0 ?* E/ D2 N                }: w6 b& g- m: d( ?' {& G( U
        }/ w! n$ Z% r9 N; n+ L2 q; }
}
9 W. j$ G) w9 A3 J- y6 L
' X) e2 y8 h$ \/ q! Qvoid        APU::Sync()
' m5 m" _4 O7 h/ m. `{
, y# y8 t9 }8 a* H}1 ~  c' X# R2 ?
" ~) u" O; r5 s. y* U) |
void        APU::SyncDPCM( INT cycles )$ }2 N) G1 x8 F/ Z% a6 v
{
" {5 g  i, M' V0 r        internal.Sync( cycles );: F; x$ K( _8 ~6 W& N+ p$ J. \

' X% j8 i+ s9 X, K$ T        if( exsound_select & 0x04 ) {
- b- e1 w% M4 W; _/ G3 k: B                fds.Sync( cycles );! v% h9 z% `9 x: o2 C) j  ?8 ?3 u: ^/ @' b
        }
* R, D; o1 ?$ Y) B0 S        if( exsound_select & 0x08 ) {
# k5 u) k7 z; t& {: D                mmc5.Sync( cycles );
. C  _: g5 h) |& R        }
% J" W- B$ j8 b) P' E}" f7 H1 d$ p* F5 m% t  F
. j* A0 r) D# `- f- ~9 l
void        APU::WriteProcess( WORD addr, BYTE data )
1 C5 b" F7 q1 T6 i2 p2 u{; N  g0 Z3 Z1 H
        // $4018偼VirtuaNES屌桳億乕僩1 }3 }  d/ i) }9 n
        if( addr >= 0x4000 && addr <= 0x401F ) {
- i( o3 o2 l' t& l' b3 ^  S$ @& ^                internal.Write( addr, data );
' K$ Z2 \2 k! [        }1 c0 h5 T4 r2 h% v- F' p2 C
}! j* u, p1 G  c$ e' w

1 h: v! `! M* Z& b, H& Ovoid        APU::WriteExProcess( WORD addr, BYTE data )
  `& h* F" Z4 H" w7 U- ~( z: d6 n) T{
# o0 G& S: Z3 l( }0 j9 e) A        if( exsound_select & 0x01 ) {/ |1 p( c, H/ H8 O) @: _- N
                vrc6.Write( addr, data );
( h" I0 ?' M  d        }
' H. v1 ^, `7 V; g# Z        if( exsound_select & 0x02 ) {
$ L, J* o9 l% [6 F: e: u  c* X                vrc7.Write( addr, data );
9 L8 F; P" ], s8 {# B9 N* x        }9 a  }1 W2 N/ }2 }. K" h7 K1 D
        if( exsound_select & 0x04 ) {$ H& E9 r: X8 \. [4 T
                fds.Write( addr, data );
7 s2 u6 i* w# ?8 s8 Q1 s) Z        }
0 w! X2 T1 b  C! ~4 G" r" c  [        if( exsound_select & 0x08 ) {
+ o/ a& O, c# A  w                mmc5.Write( addr, data );
+ o6 F, c9 h4 k6 K: ]# N/ L9 R# c        }
6 ~3 P( G. }" K        if( exsound_select & 0x10 ) {8 G/ i! n4 x+ Z2 {; r6 ^
                if( addr == 0x0000 ) {! T- Z) Q* H" ?! b
                        BYTE        dummy = n106.Read( addr );. h3 z/ Y5 X4 o( X! B. g' U
                } else {
4 w3 z; U1 e' j4 L( U" ~4 T$ ?# B                        n106.Write( addr, data );
1 r) `+ A+ j3 e& i* }! D$ M+ i                }4 d* a' X5 {8 h
        }
. ?  P# G9 E8 Y9 u  f. T% w        if( exsound_select & 0x20 ) {! k' a- h5 s. e' C3 r$ H
                fme7.Write( addr, data );2 l2 n: `2 }: n
        }
' P* f" \5 I4 a: F}1 L1 t# i& \+ \0 {

% L4 I) h8 u/ E# n+ wvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 z6 }6 ]5 q2 X0 m3 [{! Q2 Q7 D. E( P; F( R7 F. K
INT        nBits = Config.sound.nBits;
! f" Z& d6 N. V7 DDWORD        dwLength = dwSize / (nBits/8);6 l( X. \) W% f5 T$ o. v
INT        output;
4 w" j0 I% f; P9 {0 I/ {" [QUEUEDATA q;, e4 l4 X: Z# W. e8 {' ^
DWORD        writetime;3 x& e, D9 _$ n1 H* Y/ L0 J) N

# @2 k# q, `) E: c7 |. bLPSHORT        pSoundBuf = m_SoundBuffer;
; @! W# N* t# r3 J& B1 \5 t" bINT        nCcount = 0;6 W0 _% G- ?( b( U8 V
4 Y' ^$ l4 g' m/ P9 E( G( u* i
INT        nFilterType = Config.sound.nFilterType;
1 `0 H" z4 d# y" f8 B+ r) ~& N, |+ `2 P2 w8 f4 |8 `3 g1 `
        if( !Config.sound.bEnable ) {
! q7 g  g6 m6 f6 \1 `+ k  r* F5 v" c                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );) n9 [0 f( h* J8 R
                return;
1 F$ D* p3 I/ F        }
: V  h, w5 |4 \: D* p! S! N' c8 f: m" D: r* V2 y  A, N
        // Volume setup( J+ M- s3 g  _* P% ?5 K
        //  0:Master
/ @; w& j0 ?6 u2 E9 t- u6 W        //  1:Rectangle 1
' b0 r) ~# L) x8 @& X        //  2:Rectangle 2' f, L1 s, `6 L+ d1 G
        //  3:Triangle
. ?5 U4 J6 O2 p        //  4:Noise
; N; }, p! {2 f# R, m' X        //  5:DPCM. W! s2 \1 T( }) G8 [
        //  6:VRC6  E7 N$ S; t. b- k3 `9 [+ t2 m
        //  7:VRC7
- L! W( m* ?& v        //  8:FDS
7 l! ?& R7 k) u! q        //  9:MMC5
$ ^6 K9 o+ |" K6 @) R- L' K        // 10:N106
% P. @2 f2 y6 j: t5 y        // 11:FME7
+ N) Z7 A7 X8 ?3 k2 E" a        INT        vol[24];+ X6 t, [; ]. ^) p$ U
        BOOL*        bMute = m_bMute;& |4 n: V% G# e3 x; u9 C3 ^, Y
        SHORT*        nVolume = Config.sound.nVolume;
9 d) g+ p; ^* J# c3 N. i6 Z+ i# r( e8 Y+ }9 c8 I
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  p) m# n& ]4 B9 M$ G' y" x! N

, p! l/ O0 T% V& B( i' x        // Internal, k- E" I2 j  p* o) A, D
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 X- _, I/ p# l. j1 \; f
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* ?$ N, g+ l/ H5 y% Y( R        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;2 }3 \0 R: v1 O
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
& ^0 F# y# o$ i        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; q+ O" F8 \- I9 A( X3 x7 J* H
. I+ |3 b& @7 f$ r' P$ k! v" b4 {
        // VRC60 n5 \9 I- H% g
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; f% o- h& g3 H) N0 F( Y; [0 D        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ ~; C0 B% E( X7 L$ P% @3 l! m
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) ~& x" Z" x( i$ U
6 U/ V  k: ^3 A# M
        // VRC7! K: v1 U# g7 j4 C
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. R0 Y8 C4 t9 T8 M! `

0 H! R. \# k+ q! |7 Q        // FDS3 V6 F- q+ v, M5 v
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;8 O2 b2 p& K& }' j8 T2 W: o& g- X" K

  f7 `  N% \$ W- z7 \        // MMC5
/ j& H# ]8 P$ y: f        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 {2 u& S* w. j. O9 Y
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- l" Y4 Z; }5 ]        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! {# K7 \- l0 I2 H
, _' w8 b3 a& r+ i5 p        // N106* x6 K5 ~( I( h+ G+ R  |! p; X
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' |# i! E" o& [5 U
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 F8 m$ p- {5 W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" f' K" Q5 U: c, V; Y        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 j2 s0 f* M9 o6 C, F/ U# a' p
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  W0 p! M. L, _( J. X        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 p3 W# T7 l( b1 ~
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& _' O7 v& D# k( Z4 h3 g: i        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 w" C4 Y3 y1 ?( \! O* K

1 r2 r& A+ [7 h5 w4 I5 H) w0 O        // FME76 X( I' A) |! o' M6 P' W
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ ~8 j9 l. P8 _/ V* c+ \' x, Q
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  z0 m' ~0 X, |/ {) A$ M* p        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ X6 f) M3 m- N
# J7 a, t* R1 b/ R7 i//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
! h, {- Q* _: P, R- |3 ?        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 Y: ~" B" A" O
# A/ K9 s! M. l+ C! @$ C) r% M        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 Q( s6 q6 ]' G% d4 G/ ~* u! x7 Y        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
$ J2 J7 m* @5 v# B                QueueFlush();. \3 S+ i" v/ O1 o2 W" D4 u# B
        }& u0 f. R/ i9 S; F

" M/ ~: }4 y; l1 X: N. o8 `        while( dwLength-- ) {7 |3 Z* F1 ^9 O' K
                writetime = (DWORD)elapsed_time;5 g+ m/ p* G! ]' ]
. I# \9 t8 ~1 a( f
                while( GetQueue( writetime, q ) ) {( T+ @& B' N, v! [# p4 y' G
                        WriteProcess( q.addr, q.data );
. F  k9 [2 e% ^1 D! X5 v6 [9 a                }5 J" C+ ]2 }& e, `3 k

) P  v( f- @7 @                while( GetExQueue( writetime, q ) ) {
8 |3 x4 S# s) c, ^$ I                        WriteExProcess( q.addr, q.data );* c0 P8 f) O5 z
                }
0 O1 W  [& d  A6 w6 b
5 s4 B! ^+ `9 x& f7 d; A- Q                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ X* s1 i! Z# l1 e" G, G                output = 0;
/ `  \. _4 ?0 W/ G0 [                output += internal.Process( 0 )*vol[0];
5 E  ]( [/ B7 e                output += internal.Process( 1 )*vol[1];% \. i' ~( J5 F6 ~) @
                output += internal.Process( 2 )*vol[2];
" u3 s' Y! u' }! n9 Z8 R5 ^1 R8 h6 H                output += internal.Process( 3 )*vol[3];
9 I6 W1 @# {9 ^* c& l0 f- c/ {                output += internal.Process( 4 )*vol[4];+ Z/ t2 O8 U5 A! H- J
- d- }: V0 D5 h
                if( exsound_select & 0x01 ) {
9 L/ _, U9 ]' G% D                        output += vrc6.Process( 0 )*vol[5];  h, L7 h6 o* D5 n9 ~& }
                        output += vrc6.Process( 1 )*vol[6];* x- [' s5 ?6 |' b
                        output += vrc6.Process( 2 )*vol[7];* G) {9 a0 W2 J! i; a
                }
7 A7 ^- ]  t9 p& b  b6 q; Z                if( exsound_select & 0x02 ) {
$ k# ~% I8 N) j2 V8 f                        output += vrc7.Process( 0 )*vol[8];) x' }& ^( L, K
                }
+ Y! z9 w0 V5 a+ e! `4 u                if( exsound_select & 0x04 ) {, O) a* m' }! B' Y
                        output += fds.Process( 0 )*vol[9];
. w5 s! a. v' B                }% T& N! M/ B" j- Y0 v2 ^" Z
                if( exsound_select & 0x08 ) {, e3 l4 o: u7 d/ A7 h! u7 C
                        output += mmc5.Process( 0 )*vol[10];/ Z" a4 g$ n2 |  v% ]
                        output += mmc5.Process( 1 )*vol[11];6 Y' n; K9 M5 O" ^6 n* ^) C
                        output += mmc5.Process( 2 )*vol[12];+ x8 T" h0 z- o2 N
                }# z4 \! }$ r: l0 ?
                if( exsound_select & 0x10 ) {
" y6 ^  b. ], a* o( q9 f' u                        output += n106.Process( 0 )*vol[13];
& h5 R- _) V3 ^8 A: s                        output += n106.Process( 1 )*vol[14];
8 t8 q1 m6 ?* Z/ k: n                        output += n106.Process( 2 )*vol[15];0 ^* `" F& H( g' }5 s
                        output += n106.Process( 3 )*vol[16];
% N) _0 ?* Y6 }                        output += n106.Process( 4 )*vol[17];
$ ?9 A; z3 @7 W                        output += n106.Process( 5 )*vol[18];# N5 o3 F/ o; l: |1 F7 {5 k
                        output += n106.Process( 6 )*vol[19];4 ?, q& n1 o$ ^* W
                        output += n106.Process( 7 )*vol[20];2 r& N& ^5 P. j3 l6 f
                }/ R: `  m8 _* F
                if( exsound_select & 0x20 ) {
8 l4 P' S1 N  q# g9 x8 w1 O                        fme7.Process( 3 );        // Envelope & Noise
3 h! K" {% e. [8 m                        output += fme7.Process( 0 )*vol[21];
; L7 Z4 ]8 T+ m3 [. T1 `$ |                        output += fme7.Process( 1 )*vol[22];
, [% a# f6 z: Z& z& Q                        output += fme7.Process( 2 )*vol[23];2 g* \7 n4 s$ x& G- D  K
                }
+ c! m1 I: `5 c. P  T6 |/ ~  _3 c
& ?* H9 I; v3 u3 ~. x                output >>= 8;
% ?( V% [- ~! b7 c) F: u. B( U+ {, C$ O( U& z5 o& o
                if( nFilterType == 1 ) {% I- q5 O$ V# N, M
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& e" g9 j' f: \- a3 {+ ^6 e
                        output = (lowpass_filter[0]+output)/2;
% ^: c8 r: g- f8 c1 t# w5 H- z                        lowpass_filter[0] = output;
- {0 P( z% o$ o; ~  N! m. c! a3 _                } else if( nFilterType == 2 ) {
" L7 ^" y% e- R/ G6 a/ k                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 K3 v- m- b1 L+ q9 u                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; L4 q3 f- G" D" ~
                        lowpass_filter[1] = lowpass_filter[0];% z7 ~; G( J' m5 A% h  ^
                        lowpass_filter[0] = output;
9 _( E$ F1 R) o3 H                } else if( nFilterType == 3 ) {: H6 }  C6 e( m! l8 B8 L; e/ D- z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
. P% N+ f* Z- f( B/ M1 U" r$ F                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
( H/ Z, J; @6 k+ t- t. C( e                        lowpass_filter[2] = lowpass_filter[1];
0 F  x8 s* V% Y6 v; r                        lowpass_filter[1] = lowpass_filter[0];. Q. f0 h7 f0 \$ [/ T# v
                        lowpass_filter[0] = output;
3 x8 F0 y$ G/ B- @  L/ _9 p) u                } else if( nFilterType == 4 ) {# K" T: p* g5 o1 ^& @# _
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)4 u3 o  x& j1 T! k* C
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
7 Q3 k4 t4 r: J( m                        lowpass_filter[1] = lowpass_filter[0];
  [: U; I4 [+ E; \                        lowpass_filter[0] = output;
# L9 r. i3 `" H7 o8 {                }
' v/ A) l# u) r/ g3 L. T+ Q# g  i4 f# l$ x9 {5 P
#if        0
2 F- s( C2 z8 C7 o/ f                // DC惉暘偺僇僢僩4 l* u* U% p( ]8 C
                {3 s* ]; k$ c; d
                static double ave = 0.0, max=0.0, min=0.0;( e1 t& C: U- ~4 C0 {: v( M
                double delta;! ^5 ~: x; Q# M9 O6 e, L  W6 i% l
                delta = (max-min)/32768.0;
" t) r5 U# b  C! I1 \  E                max -= delta;
* d" [: [: p6 }; L. i( s! f                min += delta;
# i5 h2 X* D) @6 K6 v# _5 t/ J6 \                if( output > max ) max = output;; K' F0 l2 d  M6 z5 a
                if( output < min ) min = output;
% y6 e' g6 _5 w# i# ?                ave -= ave/1024.0;
# Z1 g% _& }/ I# A                ave += (max+min)/2048.0;- y3 Y7 W9 n( v
                output -= (INT)ave;1 d" ]% a' m2 T4 G
                }. W) \3 r* _/ `; h/ L3 `
#endif  q7 B' }( o4 I' Z
#if        1
4 Q+ L1 a  D) n: E# \+ P; n                // DC惉暘偺僇僢僩(HPF TEST)1 w7 ?( C. `. p+ U5 e
                {: {' e. B3 ^* H! p; w5 o  k, }% N/ x
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 V# \2 t6 [2 Q- g                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 r, a1 G. B+ M                double        cutoff = cutofftemp/(double)Config.sound.nRate;
! y+ P* O0 F: K$ q8 X5 h5 D                static        double        tmp = 0.0;' ^$ e( u4 _. I/ E7 @
                double        in, out;
4 u0 Q3 V; U: D  X8 c. L
* s$ r# u" e0 ~" w                in = (double)output;
/ K0 h; I- l, U3 L; K                out = (in - tmp);
1 n% m# G9 w' I5 O; U                tmp = tmp + cutoff * out;
* \# X9 l( u/ M3 u  O; M
5 J7 p- \# l6 G  O. q' s                output = (INT)out;" K4 x- a3 D, J6 k1 x
                }
# `, v" r* _/ N& n: T/ J- o9 I$ y#endif
, ?# X) x% r. M; p! Y& U0 \#if        0) X! [0 t1 k2 Q6 O1 q) |+ s
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ d7 M3 o6 e! ^/ Y9 q- Q% j                {
) E( |6 v& b3 ~! f3 }# u                INT        diff = abs(output-last_data);8 `. _7 `" O% \, W
                if( diff > 0x4000 ) {
9 u% ~# _$ n7 P/ f                        output /= 4;
6 D$ S3 s4 Y2 r4 r$ W- l                } else # R2 l% U. p4 T/ f( v$ |
                if( diff > 0x3000 ) {
' h4 A% J9 r6 G7 x( R9 C% k/ z                        output /= 3;
' y: N0 R3 ]; K) |7 l' Q3 z$ r, z                } else
. r. e* X1 k! o5 k& s- x* D7 H                if( diff > 0x2000 ) {. O( c& O; t/ U$ U
                        output /= 2;
8 z+ R9 `' y4 Y                }1 W$ f7 O, p, B4 C% I. A8 f
                last_data = output;
1 h$ g( C$ D$ T. x' S  I) T                }
3 v2 i1 i% ~& }: D#endif* R4 F, O' J1 ?& n( L
                // Limit
$ l( K+ I1 d+ N! S% O6 g+ A                if( output > 0x7FFF ) {
1 O, G7 L& i  u" o9 k! O                        output = 0x7FFF;
- x# @- @4 b% ]9 v6 V# f; P                } else if( output < -0x8000 ) {
4 c# l2 [0 L1 W4 w7 H' m6 q  u                        output = -0x8000;5 [4 q) o" j* r5 I* J! m$ B: t
                }
5 r1 ~# S; w7 t" {7 \: H3 R$ |# `$ ~- C7 A( z
                if( nBits != 8 ) {0 b3 i& A$ j8 L9 B2 v
                        *(SHORT*)lpBuffer = (SHORT)output;% @: @1 W( ]  i2 Y, h
                        lpBuffer += sizeof(SHORT);
' x! B4 ^0 p  Y3 w3 D! @  M                } else {, H( q: J2 ]1 y! f2 C
                        *lpBuffer++ = (output>>8)^0x80;
# l8 t' L1 t0 ?& |% V                }
! G! l, d9 I+ g. H( Y9 g
( _+ P+ U2 {+ ~: y; s; ~                if( nCcount < 0x0100 )
+ [( c! b+ _5 L% u7 f6 \3 b                        pSoundBuf[nCcount++] = (SHORT)output;
9 }- g' I+ X" u! l1 f5 ^% J
- ?' Z/ n9 r) J3 Y+ J3 k0 J' I//                elapsedtime += cycle_rate;
8 c4 U, n. g) z) ^5 j8 J6 z+ a                elapsed_time += cycle_rate;) o  ~/ z/ L1 i; G* b( A1 C
        }, r! Z4 [+ {) Z5 ?/ H% ^

( j: ?) \( N1 I$ B#if        1  ^, v  A" x; r) N$ J5 }
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: B# d5 O6 W! A/ U2 d: u
                elapsed_time = nes->cpu->GetTotalCycles();
: \9 a2 @3 y0 |- f        }2 Z0 K$ K2 s0 A; B. |% l! R4 _
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 y; z8 O" a- q& A+ a                elapsed_time = nes->cpu->GetTotalCycles();
2 X0 x* E4 ]% i% A& G( ?: h, g9 B        }
" O( n" x: }. D#else& S9 d/ N8 R$ y5 o. j% r  O
        elapsed_time = nes->cpu->GetTotalCycles();7 C% q& k- e8 l. c5 H+ P5 M
#endif
  P7 z  d3 x/ `6 L3 ?}
& T( _) h0 I( Y* R8 x. [) h6 V5 L/ }$ f' j; O. l
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' j8 x0 u3 ~4 @6 N; E- j
INT        APU::GetChannelFrequency( INT no )
% V& M2 O+ w/ {! t9 [/ B/ I0 E{
, m- u$ i2 i; e8 i2 R# Y! u0 U        if( !m_bMute[0] )
8 @* ^( f& h& M- r1 d- y. F                return        0;
; o4 N+ J  c: j( k3 @: I8 j7 Q! q- B! }5 z  o
        // Internal
# K  c9 I" D1 K9 O% q; z        if( no < 5 ) {$ @5 n& q' I3 v% x; K
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
5 @# `; p4 S$ k6 [1 X9 A2 {) _        }
/ G3 y' [" I2 f7 ]! h1 W        // VRC6
' a6 i) N8 i+ c7 h+ E        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  ^' M6 @" w- T$ s6 F9 X                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 t9 m; W+ V  H2 [  l( ^8 h) ]: z4 x        }+ O% d  m$ m3 R: w2 W' ^- V$ v* s! H7 B
        // FDS
3 }/ X4 ~3 g5 k  [. k        if( (exsound_select & 0x04) && no == 0x300 ) {# }, r8 [. ?( d
                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 t7 }, i" _+ e# ^5 M
        }! d- d$ x0 V' M/ ^4 b
        // MMC5
2 R+ E) Y. _& \" ?3 q$ l        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# s/ p/ P( Q+ p1 D7 d4 w7 M                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" \  y- S- }" j6 q' a/ V1 R
        }
4 d& Z/ v$ D0 o( X" ]( P  U        // N106
4 _/ L( c% w) J1 o$ w- y0 R        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 K6 J. W& ^4 X3 J/ B7 S% Y
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ x  d, ^: }* f# J$ R. K
        }
; M# e0 I" i8 A% E- a1 G        // FME7! B. B; I0 l7 E3 S8 D! K) N
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {" A9 K/ P, ^8 Z2 |" F( r4 ~- l4 z( D
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
$ z& e; w' ]& b/ {        }
8 ?6 o- N) W! s' {, X        // VRC7
2 c! x& T4 y1 \$ Y        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ l$ Z" Y2 u) ^9 s% w                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
+ \8 Q. E) S! n6 ]# x1 o: |0 T        }
. B3 E# m4 L) O2 n2 S$ t9 B        return        0;
8 T7 b; s. p) y9 O: l}3 j! j. [8 j# j; [0 s4 E
7 Z6 W& K% A5 r" T! N/ y5 J
// State Save/Load
) q2 ^1 [- `4 S0 h7 }void        APU::SaveState( LPBYTE p )
7 B+ Y1 K/ q+ e9 H{( d4 e" o6 t) B, i
#ifdef        _DEBUG
, P: j3 Z0 e( `0 {9 j* s* @$ iLPBYTE        pold = p;
, S/ @8 P( `8 A. |, M) ]#endif/ J0 S: H! u' b. y/ m) u0 ?0 q* C1 s4 M
( x# U& c4 B0 R5 I
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞* O5 E/ Q2 }( Y/ T! I7 W
        QueueFlush();; {  Z2 D! s# b9 e
0 Y, P& Y, s4 y/ V
        internal.SaveState( p );+ R, G: B( t% l3 A! u) i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ I) V5 j* V. Y7 P7 `/ S  x2 M  m  ^! T" ~/ e- P
        // VRC6
' n# ~& m1 J7 x/ d! j+ n        if( exsound_select & 0x01 ) {" H% [, c9 r) `" {
                vrc6.SaveState( p );' p2 Z% m. [7 r7 x0 |& R& z# F
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! \% x3 U) S& I0 L$ f; U        }
+ b& m& M. E3 B& n1 ?; E/ p; ^        // VRC7 (not support)3 f) ]+ J3 O* a% V, h1 a
        if( exsound_select & 0x02 ) {- W, ?: V  o- [$ c
                vrc7.SaveState( p );
7 r! w* w3 ^5 f% L                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 V" A1 B: i( u        }
& [. r+ j7 A& j4 a; `        // FDS
7 r$ [3 F/ f- B2 o+ ?- J        if( exsound_select & 0x04 ) {, I* e( O/ z: e, G) a9 f6 w! e# F
                fds.SaveState( p );4 D" J' i' s' X0 ?5 ~/ m/ y' Z7 y' Z. Q
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! C" O- c+ p" }7 m$ P( ]% Z7 ~4 Q) a
        }
/ a4 a2 L# T( x$ I) w5 ^9 l( O        // MMC58 v+ L4 V9 @/ W/ E/ e
        if( exsound_select & 0x08 ) {
" ^5 |5 a, x2 g, g' m                mmc5.SaveState( p );
, q0 S* e9 f; X4 |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  R0 q2 z; t8 q3 i' i+ {+ |        }4 F7 R; J# j$ _* G
        // N106
- i5 y7 M! i7 h2 B        if( exsound_select & 0x10 ) {
1 v! L! ]+ b4 v                n106.SaveState( p );, r; p; h0 D/ m# s
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ R+ D8 h( U% ]  U2 w# X, J0 b        }
( h4 W3 ^, p4 E" E" J        // FME7; F) S$ y* x) ]2 x  [- Q  g
        if( exsound_select & 0x20 ) {
; n, V4 U  f$ c: {2 h- ?: {                fme7.SaveState( p );
# q$ t  p5 o0 r; V                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 R/ g( W% c5 U* k# `  |        }- H6 L6 O" ?( d
4 M6 F# G7 h; R. c1 E/ I# ~
#ifdef        _DEBUG
8 p6 L' I( Y- EDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% i( c6 \  m; s+ u: P#endif
$ `: q4 H  D5 E/ D! E1 |}4 |% y5 e, b$ ]; ^3 `

$ r& m% b/ Z' I6 Uvoid        APU::LoadState( LPBYTE p )
' Q& f) E. t2 y- I{
1 I0 |, g' J! I+ K9 h0 T        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! c& g( P- d2 o2 s7 w+ L  ]        QueueClear();+ q5 j" s9 [# T' w; `" B

! o5 s! N$ S, G& i/ M        internal.LoadState( p );
5 ]9 {# S0 ?% ^# V        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  T3 X& R/ f6 w

5 d; a  A/ H' Y9 t: C        // VRC6
) j5 j" N- X2 x: x8 F        if( exsound_select & 0x01 ) {
9 T; H: w+ U3 v* b* U                vrc6.LoadState( p );
6 Y( {( _) v$ v5 h; ?! X* P: w8 B9 I                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; M: F% k% ?7 h" a. O7 d        }
' }# _& w% g; N2 y* g3 w        // VRC7 (not support)
4 P7 {5 t* }6 K4 U# X" V7 J; N' ?        if( exsound_select & 0x02 ) {5 x& Q* {& L5 C  F8 J1 w2 i4 S! n
                vrc7.LoadState( p );& P$ S1 X3 a: `6 W
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ Y# i4 T/ N% R8 ]4 m4 K/ j
        }
4 g' K6 P; S+ [        // FDS
4 Q0 _5 L6 f, o( W7 Q5 R8 N        if( exsound_select & 0x04 ) {
) q; k8 n* `# p$ b' H( F. N                fds.LoadState( p );4 a6 [/ W. \, e% f6 N0 l8 ?7 j
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ ]; `4 ^" F! }( \        }" ~- l) q) ^) w0 g
        // MMC5
' X( P( Y' X/ W1 _4 A        if( exsound_select & 0x08 ) {9 A4 F' O' }+ y1 c3 P+ d
                mmc5.LoadState( p );
) x' Q: G2 e/ m+ e                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. g' r1 `6 [! [) N        }  n) e: g& L- i3 {
        // N106  _% A" J$ n$ ]- |8 j
        if( exsound_select & 0x10 ) {' Q6 ]+ d- F; \, q( n) \' J
                n106.LoadState( p );
* c6 X6 v& o0 h3 N+ O                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* L1 Q: U' b* z0 F& M
        }. d) |/ _9 T& F9 j' r
        // FME76 H! L% E9 V' [6 n6 e; ?& w5 ]
        if( exsound_select & 0x20 ) {
$ Y: W5 Q+ g' U4 N$ s2 ^4 Y; X                fme7.LoadState( p );) w. t4 r6 E" V1 B8 @: H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 x7 C. z6 B& m; {0 d( F) Q, b        }% p# {- t% p5 L- t% R* J/ Y. b
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
: _& Z8 i  t. T5 K7 q& [- l2 ?可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' y0 Q4 v  I$ s4 ~感激不尽~~
" a8 h) G: e# S
恩 我對模擬器不是很有研究,3 h$ L. r$ e& l* ~- q8 D5 J
雖然要了解源碼內容,可能不是很困難,, J& b% _& F' W+ G4 r5 {6 [
不過還是要花時間,個人目前蠻忙碌的。5 R2 {& d" y2 T! v+ b) \5 ^* A
3 i. j5 E6 U! n/ N) P1 U
給你一個朋友的MSN,你可以跟他討論看看,
4 b$ z$ H0 i$ D+ v7 x6 d& @他本身是程式設計師,也對FC模擬器很有興趣。
6 ~5 B: |0 l: ~8 G8 h' g, ~! Z1 a' R: W) A! Y
MSN我就PM到你的信箱了。+ f- _. Z7 b5 Y0 P

+ w: x9 G$ M7 D8 O6 u希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 & k  ], g3 b. l; v; ]. c+ B# Z
呵…… 谢过团长大人~~
) x% i6 J0 ]9 {. ?
- F2 B0 d5 L6 j$ c& Q+ |
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 3 t2 A4 M; h$ R# ~3 {% h+ t
团长的朋友都是神,那团长就是神的boss。

5 W( }* ~* w0 h哈 不敢當,我只是個平凡人,; [$ K! @, M% T  D+ x4 H+ G) l
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙9 ?2 m8 o: a8 D5 L/ n' q0 ]) c+ i
ZYH
4 U9 x1 ?( R2 }. J3 @- n. _QQ:414734306
. }9 G5 Z: J& M8 d1 x+ D4 OMail:zyh-01@126.com! f' x; r. E2 y4 l  k2 O# K2 u

9 O  r9 Q5 _$ v他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 ]4 C- m8 y7 o/ H/ J
再次对团长大人和悠悠哥的无私帮助表示感谢~~
% W. {1 J3 b# {
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-8 12:08 , Processed in 1.082031 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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