EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 U/ p1 r& N) g* W3 x楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; X1 j/ N* j) q
这里有相应的模拟器源码,就当送给大侠了~~3 K# I( P0 j: x, m
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 p. ^1 I  ~1 b7 {/ y5 |, R. Y7 Z; B
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 Z$ h4 a5 c6 s. r: Q3 I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  c& }8 S* Q5 h3 G! M, E. O
这里有相应的模拟器源码,就当送给大侠 ...
$ h! e6 ^  U( f5 O9 L) S
聲音部分(Audoi Process Unit = APU):
$ B" o; n' B! f# U" T. J$ J0 i.\NES\APU.cpp
% G# a! o. q" H) i4 z.\NES\APU.h! W% h. ]! T2 C8 S
" i# @1 ^7 U% v6 |7 A1 ~" F, d  I

' E2 E1 L# a, c; x* Y2 P影像處理部份(Picture Processing Unit = PPU):) S: p7 J! `) J, [  E6 i
.\NES\PPU.cpp
) T+ x- ]5 W' w, F9 G) N.\NES\PPU.h& S3 N5 H4 T2 r3 E) T$ |9 S
8 P7 g- r# @3 ]8 i- R" J4 Q; Z
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 I& h' E$ Y. q9 o+ ]# U感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 n3 Z5 A% _( {, x5 Z, E
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ l$ l# r* V) U4 Y; O9 M
//////////////////////////////////////////////////////////////////////////+ N) }2 t- q% y, T8 E
//                                                                      //
4 F: ?1 ~$ [* C% c9 }//      NES APU core                                                    //
/ y$ d( \- P/ |& Z//                                                           Norix      //" o  S3 Q8 i1 k" a9 C/ v
//                                               written     2002/06/27 //
1 d; B) b& \/ ^//                                               last modify ----/--/-- //
( _  @& k# q, x8 S  I  f! Z7 t//////////////////////////////////////////////////////////////////////////- D) f$ f) |4 h5 d
#include "DebugOut.h"
) ~. ]# V6 z4 _5 q# ^/ }0 E$ R$ z& L#include "App.h"
6 S8 k" }2 ]1 Q5 m" K8 C; _#include "Config.h"" o0 J% f" B# C5 v/ D

1 o1 {  Q( F' i% D5 M- o#include "nes.h"2 l. b; k# D, t& s8 C: k  H& V+ o$ A
#include "mmu.h"
. j4 a& ^# b- ?( ?; {' j8 X& T#include "cpu.h"9 |; z/ V; }- r) z% d5 x) W
#include "ppu.h"/ K* I% ]* b: o; Q( l- d
#include "rom.h"9 S5 m. Z' D( Z+ |5 h
#include "apu.h"
, r+ {& z; G3 s: X. D; [! H! M- k6 c2 f- r
// Volume adjust! Y9 m* \9 e  l; P+ Y( D& B
// Internal sounds, i- {' r, x$ F, z) A
#define        RECTANGLE_VOL        (0x0F0)
# ~- S' V  r% a9 G5 L* k  j#define        TRIANGLE_VOL        (0x130)
3 T/ b3 v/ |9 Q, h/ Y1 O& c1 I3 V#define        NOISE_VOL        (0x0C0)
2 {; S; N; i0 E$ j) [#define        DPCM_VOL        (0x0F0)2 t) r3 U( R/ Y' V8 b, d, F
// Extra sounds" ^$ x' y' r+ e' ?" w+ z* }
#define        VRC6_VOL        (0x0F0)
( t0 f8 F6 R( k+ }9 L7 l4 m#define        VRC7_VOL        (0x130)
' w- p0 y! U: p4 ]#define        FDS_VOL                (0x0F0)6 S# o5 G2 R6 C  J9 R2 \
#define        MMC5_VOL        (0x0F0)
2 w: H* |5 |  p" x- N/ {- v#define        N106_VOL        (0x088)
$ q* i8 }1 {1 ~8 S- K6 @#define        FME7_VOL        (0x130)/ G4 k1 u9 P; l+ L
  p; r7 e" `2 e3 j: F/ Q( R& x9 f! [
APU::APU( NES* parent )
0 J( s" ^+ ?3 Z, n8 s; N/ h{/ r# T& }8 A; \7 a5 E% M3 r0 I
        exsound_select = 0;
. K# W5 p% d4 Y% l) C- t& L
' I) `' n( V8 _* o( O        nes = parent;4 Q- ]6 Y; Q! t8 P
        internal.SetParent( parent );+ T8 s3 @) m% ^4 Q! H5 |. ?
9 v, q6 v! V0 a! S2 l: w9 Z( H- Q
        last_data = last_diff = 0;
, F6 T. V8 b7 _4 m
- p# ^# ?# J' @, ~        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
& {: w$ J! r/ }: O9 j9 h
: p9 e# M4 _$ E* {        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
$ k& |# T2 P6 }6 P: [9 N" v' R+ l        ZEROMEMORY( &queue, sizeof(queue) );) q2 J" {7 M* @3 K) Z. M: {9 D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- I  P* j. q* _+ W  G' M$ S- {7 _7 J% `8 [3 e
        for( INT i = 0; i < 16; i++ ) {# r2 W: D7 o1 Z; u, t, d
                m_bMute = TRUE;
4 F' P0 q6 ?5 M: Z        }
* S% O& J: s$ ~}
, m4 h6 A1 @+ q3 {' ?7 U6 G0 N- l* [6 _5 P8 n2 x
APU::~APU()- k% p; W, L: L9 P) c
{7 `7 g* x6 Y1 g! t, [
}% }  f2 L/ C6 `( B4 }2 _

; `; b3 u& O- fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
" ^3 V8 K  `) @2 f; f. h. J{
& V8 z* y; F; |4 E  |/ p- A7 a        queue.data[queue.wrptr].time = writetime;+ }  G8 @& o9 Y6 j3 K  B" y6 }
        queue.data[queue.wrptr].addr = addr;+ M9 V1 f1 x/ B1 ~
        queue.data[queue.wrptr].data = data;
3 F$ w8 r  ~( ]9 M6 J        queue.wrptr++;1 n$ b- I( L6 ~5 V& A: `0 w
        queue.wrptr&=QUEUE_LENGTH-1;
4 c) V  X0 ?7 f        if( queue.wrptr == queue.rdptr ) {. C6 U9 w' ?  R! M
                DEBUGOUT( "queue overflow.\n" );. ?& w8 x3 o- Y8 \7 R: }, J
        }
% ?8 [2 [* R$ l2 I/ v3 _}
  n3 V0 `# m& A, k, z' m2 q7 l: a9 m. [# u: {# `8 }% ^; @. @% j
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
) ]$ @" W+ C( \2 b0 P& r- u{
' n7 f4 B; z4 d8 n/ U" U1 _        if( queue.wrptr == queue.rdptr ) {
; ~2 c$ ~7 i+ W: H2 k5 H9 N                return        FALSE;
% E) z& q) k# ?3 ?3 [( D7 z! g/ f        }
* u( E. Q, {. B; Z: [- M        if( queue.data[queue.rdptr].time <= writetime ) {- {6 z& F: T' R1 R1 ]6 S) p* P
                ret = queue.data[queue.rdptr];6 g, x- h: N! R% S( `- Z* N' ^
                queue.rdptr++;& ~6 t$ L- [3 Q: j, w
                queue.rdptr&=QUEUE_LENGTH-1;) ~5 O' X0 r; o1 B$ v) C
                return        TRUE;
- J* n, x; m% P- D/ U; V) t5 T$ q        }* _* Z! d) L$ D6 O  o0 A; [
        return        FALSE;
! q- }8 w. b9 ^+ ]& `}! e9 s+ P8 }8 }0 _

5 W3 c  B8 H  A, d% yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
. x# k  E: a. z+ o5 ?{- }7 N5 a: ^, ?- ^) ~& @7 @
        exqueue.data[exqueue.wrptr].time = writetime;  [) t% r' `$ a) b) ^/ p6 y+ D
        exqueue.data[exqueue.wrptr].addr = addr;( R" v+ l& X0 C$ f. m/ y4 ~* ^( ]
        exqueue.data[exqueue.wrptr].data = data;" }9 i, g" p: ~6 \, \5 \0 l% g% N0 g* G
        exqueue.wrptr++;
+ D) U0 ?* ^6 V) v        exqueue.wrptr&=QUEUE_LENGTH-1;) `3 c# j5 _" W) e6 e; b, k$ M( q
        if( exqueue.wrptr == exqueue.rdptr ) {, D& A% ^1 r0 n
                DEBUGOUT( "exqueue overflow.\n" );
2 E7 c1 F. j% P+ u8 s( m. g        }) @8 Y! o2 z6 x! F" t- X
}
; B" V* }; ]' K0 z2 I- {+ B5 m& ^
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 \+ t3 _8 I2 m5 H{& k+ L$ t8 `" B3 e) w& E  P" s( @+ q6 N
        if( exqueue.wrptr == exqueue.rdptr ) {
8 @0 y8 ^+ h& u/ ?                return        FALSE;+ o6 m6 E7 x% i% m
        }- d& V- o4 m' w) W; S( V0 v  O" b
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
5 Q- ?" ]$ C' ^0 @7 v' q3 e: e$ {                ret = exqueue.data[exqueue.rdptr];" s* S1 a; |8 N; |0 \7 w. B
                exqueue.rdptr++;9 K) w5 D9 f8 t
                exqueue.rdptr&=QUEUE_LENGTH-1;- m$ k' v8 Y) M1 k1 @7 x7 W+ S
                return        TRUE;
; i: @1 H2 X% e& d7 f) D0 X        }
& G4 n1 c6 q: M, Z) ]: |        return        FALSE;
  u; P0 I6 \. w& s; p9 Y}
5 e. R/ E* q0 S2 U( A; R; e# g
9 P& E/ w) V% L% a  @void        APU::QueueClear()
  Y' ^5 h+ s2 f; z{# o& ]4 Q" X, q: q/ f% }
        ZEROMEMORY( &queue, sizeof(queue) );* o3 y+ R: }* _- r
        ZEROMEMORY( &exqueue, sizeof(exqueue) );' T0 w0 R& I9 ?9 I# e
}
; o7 D1 J! H1 ~1 \$ Z
' d+ f. [& r6 d' q; L2 L' evoid        APU::QueueFlush()
% W4 c* S+ [4 V6 S; q" N{
  E3 A8 Z3 O( H" P: i5 y4 i6 Z        while( queue.wrptr != queue.rdptr ) {
3 V( l6 p. h. i& O1 n- [                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );* \+ B) F- c6 m( ?; T/ f, Z
                queue.rdptr++;) ~$ ]' n2 m7 A$ R- N
                queue.rdptr&=QUEUE_LENGTH-1;5 R5 j2 `! [( L9 l, M  p
        }
  w3 k) B5 y" B& `' L. x2 W: j7 m( F
        while( exqueue.wrptr != exqueue.rdptr ) {" b) e" ?& m( D# `7 ~
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
  Q; E9 a' ]3 T7 |8 |7 R                exqueue.rdptr++;$ v7 A0 R0 i/ I! a) B
                exqueue.rdptr&=QUEUE_LENGTH-1;
$ }  s* b( z3 U: e9 j) ~4 J        }9 ^, d: t( A/ n
}9 u3 p4 d  U/ i$ r+ t% T, p
& z$ m& D4 K5 f- B& ]
void        APU::SoundSetup()' _2 w2 m$ x" i8 z: p) O; v3 I
{
; l7 a, r, `% E8 _9 y2 z7 R+ ?% r0 ?        FLOAT        fClock = nes->nescfg->CpuClock;
5 c7 ?/ f' m# e; T4 i        INT        nRate = (INT)Config.sound.nRate;
) e! r0 |. b% ^$ q2 G/ b- A        internal.Setup( fClock, nRate );: T0 o8 P5 @8 u
        vrc6.Setup( fClock, nRate );
; @) m6 L* w' ~, s4 M/ Y        vrc7.Setup( fClock, nRate );0 y6 J7 t7 j/ I" S' u
        mmc5.Setup( fClock, nRate );. w1 n& d) q4 r
        fds.Setup ( fClock, nRate );9 ~7 l& d- H  K! `4 e- V6 N9 T
        n106.Setup( fClock, nRate );; O3 {3 ]3 Q+ G  s* L8 y! L" P6 h
        fme7.Setup( fClock, nRate );
2 C1 N/ r  i4 ?5 S2 [9 v- {}
0 y5 c4 H2 i+ J
6 H9 K$ E( L3 y  I( \$ X" b' ovoid        APU::Reset()
8 f# {) f$ T- q9 g) Q{
4 N& \+ l* q" d8 A        ZEROMEMORY( &queue, sizeof(queue) );# A4 s7 g9 u# b  b0 e8 H+ T! c. i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* ?8 R% r$ P5 i! |0 H& K
2 M2 E# m3 f/ J7 }: M* H# ~
        elapsed_time = 0;
: T- u& ~  J' Q2 i. C
0 S1 d( S) i6 Q- Z4 ~        FLOAT        fClock = nes->nescfg->CpuClock;
0 K6 T/ v9 I4 f+ q8 ^9 J6 {        INT        nRate = (INT)Config.sound.nRate;
6 T% P# _9 w5 J        internal.Reset( fClock, nRate );
, G9 E" R' ~% `+ ~        vrc6.Reset( fClock, nRate );
9 i! ]0 i: S$ z2 c3 H0 N        vrc7.Reset( fClock, nRate );$ Q5 p. T2 `/ p' U
        mmc5.Reset( fClock, nRate );! @& L3 f: h9 O+ A! f% I
        fds.Reset ( fClock, nRate );
) T  n: _% v6 H/ `9 O3 n; G7 f, _        n106.Reset( fClock, nRate );
1 z! X, q6 z% s        fme7.Reset( fClock, nRate );8 e0 P, `- Z1 c1 X- Z
/ j5 h, d) N" ^3 r
        SoundSetup();
' Y% v9 m: H  R5 P. K  d}
% O" o5 Y0 j7 x
9 h3 Q2 a  U4 F/ t( q' U* t# M$ @4 Dvoid        APU::SelectExSound( BYTE data )0 u& s" K, A; ?  m
{
* p9 f/ f3 h% O7 ?( X        exsound_select = data;
& z. a( E6 Q* O0 n' g0 e}
' a) e( i9 {/ G1 |/ {2 ]) ]; M# O& |1 u* w% B6 P0 ^2 P
BYTE        APU::Read( WORD addr )$ c& [( |" {; ]  ^* N5 F9 P
{. O9 j! D% U/ o1 ?; P
        return        internal.SyncRead( addr );
+ b4 |, q9 W0 E( w0 m# S% |% x: G& _}
' L1 N/ k. h6 |( n. q
, `: [6 t" |+ y0 i) i  R1 \  Tvoid        APU::Write( WORD addr, BYTE data )
$ N# c4 `9 M4 g- o{4 U# p" [. k7 H# D8 t& H' z7 H" h5 |
        // $4018偼VirtuaNES屌桳億乕僩
/ e0 F* D& o0 q; Q        if( addr >= 0x4000 && addr <= 0x401F ) {
0 w/ m8 G: c3 W: a5 @- `! g9 \7 q7 R; Y                internal.SyncWrite( addr, data );
( U1 Y, k8 Y9 U( i# Y+ V                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
- T' {" `' t3 I0 N$ U/ h! @        }
  O2 A! i& V. ?) F6 m1 k( ~}. k6 H1 O* L% |, t  p6 z4 [1 {4 E
! D  i0 F7 f; ?8 R7 [
BYTE        APU::ExRead( WORD addr )" @1 M# {8 |) ?# E' z
{9 S6 l: C, ^# w! G3 e+ J+ o
BYTE        data = 0;
. X; ^7 C. I; S5 U& k# K5 Y' P; ?; W5 o  `7 f+ R8 c' c
        if( exsound_select & 0x10 ) {
' Q# T; w5 _2 F: ^# j                if( addr == 0x4800 ) {' r- O" Q1 s  |1 H, v" |
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 Y1 N/ I; E4 H, a# c9 a" ^                }
, X4 r; D- s5 C9 N3 R/ X        }
; c* _0 u1 }9 ?1 M        if( exsound_select & 0x04 ) {
. G7 Z3 A7 {& \                if( addr >= 0x4040 && addr < 0x4100 ) {
; |% m* C: @) U                        data = fds.SyncRead( addr );/ z4 U- B( f9 Q0 z% s/ G' l  P- J! t
                }1 W+ {# k0 z1 [( \; b
        }0 u6 t0 s# y  g  G
        if( exsound_select & 0x08 ) {5 @+ D8 {2 H, r' e/ g8 u
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ A( b2 p; f" [: L. n                        data = mmc5.SyncRead( addr );! [% y/ v' `0 g: l% q5 q$ T
                }8 O' O% _2 \' m5 M
        }1 S* K2 G: D  s) u& ?
! X5 }% X8 |: E* l' M7 H4 n
        return        data;
  }' b9 ]" {) ~8 P, G}# W" Y* y7 z8 k% y

' \: \2 d+ n& h& \  u# y% B* Avoid        APU::ExWrite( WORD addr, BYTE data )
1 h$ a( G& Y) J) Q5 C0 b  e{
4 C& y! w) J9 M9 d9 k        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
* N* q$ j. |9 |0 }, |' k/ L4 |5 w1 P9 C, S' ]
        if( exsound_select & 0x04 ) {
9 e: F5 I/ F2 g# g                if( addr >= 0x4040 && addr < 0x4100 ) {- F6 W* t" R0 }5 o9 A
                        fds.SyncWrite( addr, data );
8 O) @! b/ A( y# \                }
2 l4 r9 j' u$ c7 T' q9 b6 t* f        }
' ^  O6 Q6 k& E7 `1 e/ {. V9 F8 }/ g4 ^
        if( exsound_select & 0x08 ) {
/ r/ {$ q* D8 _                if( addr >= 0x5000 && addr <= 0x5015 ) {
4 Z- F$ L0 Y/ R- @8 b6 ]                        mmc5.SyncWrite( addr, data );9 C, I. S0 r  w: N5 Z
                }
; F6 b3 ~; g! d1 p% U        }- ^. w* Y* i+ L, o4 B- G
}
4 M; D3 @# K* R+ c0 h, ^# [5 {+ L3 \& J9 A3 v  f% [0 Z6 M
void        APU::Sync()9 Y5 T1 n( |: U' \) F9 q5 s  r
{% x, w- u; Y/ v$ V( A/ [! ~! b0 l
}/ ^4 ]* Q& O5 X* d
# d; i3 J9 u7 M. F& r7 F
void        APU::SyncDPCM( INT cycles ): m7 _/ {. P- C+ y' E4 z
{
3 ], g& j6 J& _$ E* S, d; @8 t        internal.Sync( cycles );  S2 U# D! m+ `8 X9 V5 I& X

8 @  P1 I7 @* o* @        if( exsound_select & 0x04 ) {
, e0 ?) @6 e& b2 R                fds.Sync( cycles );
9 ~/ m8 y+ o; H& T) a        }7 n3 a' [5 H* \( ]) u) q
        if( exsound_select & 0x08 ) {6 q% a, V. O, y2 D( n' [- O
                mmc5.Sync( cycles );
: O2 r' G4 q" D( k' L        }
+ x. }  L# ^( J" V% P% |}( o, N" O& N* I. W. \- D8 G

; J1 `+ K  T5 _( U' B) [void        APU::WriteProcess( WORD addr, BYTE data )
- v- y* Q+ i  n; ]( C1 x{$ W* Z  P3 r, K
        // $4018偼VirtuaNES屌桳億乕僩
: k# {+ E# o  A6 A8 M8 t8 `        if( addr >= 0x4000 && addr <= 0x401F ) {& |. l9 t$ Z- e: i! O$ {- Y
                internal.Write( addr, data );
$ f3 t/ u1 F. ]+ _, R" \! B        }
% @' {7 A  \* B7 ?}& l" Y; d' j' @4 _; _/ x# P

$ p( ]0 s% U  }& M8 rvoid        APU::WriteExProcess( WORD addr, BYTE data )
. v; B5 T# b0 P{3 z7 c1 P) X+ l8 a, F
        if( exsound_select & 0x01 ) {
) e& ~  J6 @' e5 r0 T( Z                vrc6.Write( addr, data );
0 z* K. O' f( M# |# u- e1 K        }
( p5 L4 i. w# @" |        if( exsound_select & 0x02 ) {
' J, c8 _& ]" K/ m3 \. C                vrc7.Write( addr, data );$ {2 J% n! V) |+ X# s! z
        }
4 m5 s0 Q% O) N+ d6 }: e; j        if( exsound_select & 0x04 ) {+ s( ^* |6 d0 F( l; c7 e
                fds.Write( addr, data );
( \1 p6 ], q2 }% m1 H' z        }6 S6 F* |; ?' I: q& Q8 p+ ^; T
        if( exsound_select & 0x08 ) {
# H, {/ N- @. [& M4 N- K                mmc5.Write( addr, data );
# \/ x  m8 f0 l$ Y+ f        }
  u; v) _' {" e8 h6 _( ^        if( exsound_select & 0x10 ) {
4 t  T+ z0 W2 _- [" K, O( {- ~4 V                if( addr == 0x0000 ) {
+ [  P4 H1 Y' H! w                        BYTE        dummy = n106.Read( addr );* j, y& z6 w, c
                } else {
$ l* q. X! v( q: ^/ l. J                        n106.Write( addr, data );+ c+ X; N& s/ s: A7 `+ d
                }+ x  o9 m" H4 R! i6 P# T0 o- f
        }
% u& W5 W' ~% |3 i: y& E        if( exsound_select & 0x20 ) {
+ p8 X* O  }1 S0 E) l% y) Y# [; q                fme7.Write( addr, data );8 r: Z9 R( ~' r8 }( O- f) t0 ^9 c$ q6 L
        }5 Q- L* h/ P8 b0 Z* l5 K1 {! H
}
9 @, c+ ?& B& P: H; i
8 w& W1 Y$ {. q- [8 kvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ }! M0 \+ O' B0 K* x% Y{
# q) _6 u, Y& ?# xINT        nBits = Config.sound.nBits;
  h: `4 \1 G" Y% E4 ^' e; sDWORD        dwLength = dwSize / (nBits/8);
0 }" M* e5 f9 h6 B, q2 jINT        output;
* r% x% F1 P4 v8 UQUEUEDATA q;- W# Y4 T+ p: y  B9 a
DWORD        writetime;
4 `% l5 R( b8 b" k6 L1 U0 r
* |0 U5 p; o8 q# q7 eLPSHORT        pSoundBuf = m_SoundBuffer;* j& B4 P( {2 z1 [
INT        nCcount = 0;: A5 O# q9 I  j2 l: W4 W
6 A  G! k5 K" d
INT        nFilterType = Config.sound.nFilterType;* x0 n5 M" }1 I) c; B8 H
2 C' z8 }+ l$ J, X
        if( !Config.sound.bEnable ) {6 o# k- _' P5 {% t: x% b
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
4 S: _: d/ s/ [& z& x5 d# W                return;
+ c0 h$ l9 |9 o+ g        }
/ G+ T$ ^6 Z7 |3 T0 ?( ^9 k. G9 V0 _. I0 r; s
        // Volume setup
' B8 s1 |$ _! F! L- K5 ]        //  0:Master
$ r; _( y* ~: U, f        //  1:Rectangle 1* @3 _% w$ u$ l
        //  2:Rectangle 2
4 f3 B0 m$ x$ m* V$ U        //  3:Triangle% L/ {2 e' |! k; N( I
        //  4:Noise  U; l6 r7 e# K3 m  I5 F
        //  5:DPCM
' I% K% n+ m, L4 [        //  6:VRC6
/ h* a+ E8 S: J. `) R+ i        //  7:VRC7
7 V9 c% }& n" q) y        //  8:FDS: n  K" l, L0 F9 O- A  B
        //  9:MMC5
" s  G8 \  ~3 S2 {. M        // 10:N1064 ^) ~6 D. s1 _6 w; K! ]
        // 11:FME7$ q( u9 k# q% e5 k! y
        INT        vol[24];" [4 j5 m$ k7 X+ y
        BOOL*        bMute = m_bMute;- G2 H: x1 i6 M' n* F* n9 A0 ]% @
        SHORT*        nVolume = Config.sound.nVolume;' K' Q4 k2 K% A

) I6 [9 b! H3 Q3 r8 U2 U3 n8 t        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 y9 H* B7 z& @6 h  r" Y0 C7 K
2 s/ x# X1 w( g% ^, u, ]0 T  T
        // Internal
1 j. ^" J1 z7 \% p1 S6 I        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;4 z" U, Y4 A" B3 Q! x" [0 x
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* \, o" D) x' n9 {; D; Y1 d  o        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, {; Y' G" a7 O0 Y        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 @9 E5 v! A/ k' K
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
( d% E& b% }) _$ y9 Q- t+ L4 u6 c. d' @
        // VRC63 L! K, k/ v0 n+ Y/ A8 r1 T9 L1 \
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( s- n- D4 d3 T- A& H" j        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 ~- ~( e: _. s+ ?        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ Y7 Y$ Q, q5 c9 U4 q, D9 o  f: }5 @
$ b  n* S, o* U' ]5 P        // VRC7# o, P- e* ^5 m
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
8 m; D' {, G1 v% u% E8 x) _% }1 j3 A, {! G' h4 r
        // FDS
! X3 `9 a% O% S0 ~& s$ R3 W$ j        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;- h8 j) F6 Q9 @; g8 X

! U. B1 o( }8 M5 x        // MMC5! r9 m0 W. z6 X6 p
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! {7 t) U9 i7 `4 ^7 K3 C0 y! R/ Q/ g3 E7 q        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" P% |3 P7 _: N5 \9 L& ~2 o        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! D/ u8 d( e# k2 H! f* G: l) t/ y% T
        // N106
7 ?* a  a3 x7 R        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# V- M5 e6 o2 v0 D4 s+ I1 E
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' L; ^% Y/ h5 |" T+ s$ k2 j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 s- L- Q+ g( m* @; \; H4 D& d3 x
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, \0 F* p+ K/ D( f7 m" G+ \        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 j: L0 r, e8 O3 \& q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 c; p* m" G) ]$ h' d        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' |+ G" |  o5 S        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 T3 Y* f9 j% i5 ]* u# k7 Y& l6 _- t. j" b# v, T, z
        // FME7
; N2 y! g1 E4 M' H" A        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- @  ]- ^$ g9 m8 i, C! E. @+ Q        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 U2 N* V% V% I2 A
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) Y8 y. {  A3 i" a; E
3 R9 T: i8 d4 f: w  l2 V//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 k8 W* z" w4 v/ y* o% E
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) c' A$ p  S! H) j* I6 t' F+ C
1 x- V- j: \+ V/ X( h+ c/ k        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟1 ^) w- `' [5 W6 a* n
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {; d! E( m" a5 c5 y
                QueueFlush();8 i' b3 s$ u; l
        }/ x' [6 l3 W+ `! H2 g2 h
+ [6 R& c5 H+ i; o. ]
        while( dwLength-- ) {
' I; l7 T; [; [( p5 m                writetime = (DWORD)elapsed_time;4 L0 d& W) L4 R: y, A3 t9 E9 g
" `0 r6 P7 l9 t
                while( GetQueue( writetime, q ) ) {- f5 `2 M+ d& n9 Z) |
                        WriteProcess( q.addr, q.data );
& ?% R5 q* L! C2 F) a& d                }
' q! M" _' I8 Q2 O3 c* ?/ P1 q" t
* D; E1 _6 F& ^, ~                while( GetExQueue( writetime, q ) ) {
1 T& T) L- B) l; o. }9 V& Q                        WriteExProcess( q.addr, q.data );
, n+ {( f1 M! p6 ?( O( I  m: g                }
9 f. ]8 O4 Y8 r8 {& z
" A: s5 k4 U  O. r( Z, y6 m$ o                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
( m, G% b6 }+ d2 b5 @; _; A                output = 0;; w) W% y* J' j" |
                output += internal.Process( 0 )*vol[0];
+ M8 A  w9 b1 r- F' C                output += internal.Process( 1 )*vol[1];
9 U! v5 w1 U8 q# B  v                output += internal.Process( 2 )*vol[2];
3 a7 |3 r$ {' t! b. J6 ]! ~                output += internal.Process( 3 )*vol[3];6 X$ J0 u. B9 o0 O% o
                output += internal.Process( 4 )*vol[4];
. b$ H% t3 @1 Q9 s" Q$ N, j: S1 n
7 {# l. `, P. j" C) z" j4 I                if( exsound_select & 0x01 ) {: F- ]6 z% {  a3 M: K3 R# A
                        output += vrc6.Process( 0 )*vol[5];5 v. y, G( x( F( ^( c+ |
                        output += vrc6.Process( 1 )*vol[6];, \2 J' q) ~! ~4 X. u. z  }
                        output += vrc6.Process( 2 )*vol[7];: Q2 H3 ?7 @5 o4 w( a# C/ @
                }' R4 g( ~: w6 @. t
                if( exsound_select & 0x02 ) {5 d( V7 L6 c8 G+ u% ~3 o  p; u" `
                        output += vrc7.Process( 0 )*vol[8];
. ~0 q2 o0 M7 G8 n/ o/ y                }
: M! Y& s  F0 w9 Q1 C  m+ V  n6 P                if( exsound_select & 0x04 ) {
' ^# ]! Z  `8 b                        output += fds.Process( 0 )*vol[9];
" v' ]7 g' N9 n/ w8 F2 l                }- @: j- U6 `9 ^  ?" ?
                if( exsound_select & 0x08 ) {8 B( N3 ^+ e# T
                        output += mmc5.Process( 0 )*vol[10];2 i0 Q3 X/ @1 ~2 U* Y  \2 V, F
                        output += mmc5.Process( 1 )*vol[11];( p, k! X$ Z. b+ a
                        output += mmc5.Process( 2 )*vol[12];# t0 f: H8 j" ~2 `3 P0 y7 A7 ?
                }
8 \; X' Y, K. s) B1 `& x7 s' ~                if( exsound_select & 0x10 ) {: s& u! P$ C& K& x
                        output += n106.Process( 0 )*vol[13];
0 _; Y5 t7 N1 N5 h                        output += n106.Process( 1 )*vol[14];
; }+ O& d% f. n6 H                        output += n106.Process( 2 )*vol[15];
2 S+ R  o6 M' K- t; O                        output += n106.Process( 3 )*vol[16];5 p8 c* G, `4 `; ]9 J8 ^  f
                        output += n106.Process( 4 )*vol[17];
" t. U* J0 A5 E$ A" g" y" Z" ^                        output += n106.Process( 5 )*vol[18];
& v. P  L, }7 Q3 z, R' l% i8 E                        output += n106.Process( 6 )*vol[19];5 v( j2 q: F5 q2 u
                        output += n106.Process( 7 )*vol[20];+ t4 z' i" R, c* {( R
                }, M+ P7 k4 w' N! G" g' B6 P
                if( exsound_select & 0x20 ) {! {; ?5 R) Y% S' E
                        fme7.Process( 3 );        // Envelope & Noise+ m! _3 M3 A0 f, }
                        output += fme7.Process( 0 )*vol[21];3 h; o* r" }1 b/ n
                        output += fme7.Process( 1 )*vol[22];. Z5 t: [+ V: P+ Z% P
                        output += fme7.Process( 2 )*vol[23];( e$ X, R9 S: x5 b4 v) k8 \/ N9 F
                }
$ Y5 A9 Z: @6 A( A
2 W" w# ~/ P! B                output >>= 8;
8 m8 s! q" x* X4 j! q
$ r7 R2 R1 X( n6 a; Y  b3 [                if( nFilterType == 1 ) {
& m  R& U) }- W6 b                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
# b/ U- R$ v# t$ J                        output = (lowpass_filter[0]+output)/2;* ?4 r# J( M3 F( {
                        lowpass_filter[0] = output;2 s3 a; u2 g) B6 W' G# j9 T
                } else if( nFilterType == 2 ) {
/ S$ f. K  d6 X. J' z2 Q- n                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 t" f% v5 m" Q% r3 Y/ v7 M
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
. C- W" \5 B& Y( ]$ {6 }                        lowpass_filter[1] = lowpass_filter[0];
+ w! b  K( O* b; X" x4 u3 ?                        lowpass_filter[0] = output;+ z1 B; n" f' J& P8 _# w
                } else if( nFilterType == 3 ) {7 {7 q$ n+ @' n4 N2 O3 e9 O
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)- L% `* z8 S' k. l; V
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;5 Y1 L+ }  R  r! V
                        lowpass_filter[2] = lowpass_filter[1];2 |5 i# _& E7 i5 `+ A, L
                        lowpass_filter[1] = lowpass_filter[0];
# l# E' `" }# P  ]' k                        lowpass_filter[0] = output;8 U  ?1 p  E; ~6 f2 V: S/ r
                } else if( nFilterType == 4 ) {. t+ C+ n' L6 K! U; D! v
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! m6 l/ A% o( j4 n& w6 ^                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
, f/ n$ W* x& q! O1 ]# |9 N3 u                        lowpass_filter[1] = lowpass_filter[0];  o+ m  w: T8 \4 s5 |# `7 ~7 L+ u/ L
                        lowpass_filter[0] = output;
  B" C5 q. e# n5 D8 O                }  U0 j9 `# i# f) R" l* i
) ?( B# W$ V" B9 {5 K
#if        07 G  L8 z& a) k+ Z5 |1 K3 u
                // DC惉暘偺僇僢僩
1 @; a9 U+ J$ j  ^8 h# S; J                {2 v9 L2 l( r- q2 z5 ]
                static double ave = 0.0, max=0.0, min=0.0;- T+ J; J2 V' ~  t3 l
                double delta;
. m  P2 Q4 Q9 h7 N$ B  v                delta = (max-min)/32768.0;% ?6 |7 s+ \8 J; |* j
                max -= delta;9 w+ P2 w4 L; A- H9 C; l0 f
                min += delta;3 A9 v, O8 d  n% `
                if( output > max ) max = output;' \& \- T' V" E3 L2 ?0 U# W  t! Z
                if( output < min ) min = output;( p- I" x& Q7 Y  ?
                ave -= ave/1024.0;
& i3 C- B9 S* F' B" E- w                ave += (max+min)/2048.0;
$ n0 k" {0 w; ~7 M1 u0 W                output -= (INT)ave;
( Z" N' y, a: t: u; O                }
2 L; T. x, \6 c% J7 Y* k#endif& \/ O; n' |$ k/ e
#if        1" o) M# e# E& J* x2 ^. N/ q$ ^
                // DC惉暘偺僇僢僩(HPF TEST)
4 C- f6 @9 n# q6 M9 {                {8 b) |0 `0 E( ^0 s- m& l- s3 N- l; t
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);" G- v3 a6 t% U, ?3 b" h
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
4 O' v  z: N- E4 U/ T                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ F& M) V* j" R( v1 g8 o9 v2 |                static        double        tmp = 0.0;/ W6 L1 M4 ]/ K1 p7 b
                double        in, out;1 p) f8 H; C* P9 Q; X2 q' S* V

$ [( J" e% `# m2 {/ H0 U% {* X                in = (double)output;
, E+ h% O  O# m8 o5 |+ c                out = (in - tmp);
5 t! h& }! ]. [: j* J0 V                tmp = tmp + cutoff * out;
5 Z3 A0 E6 ^+ Q; Y, B0 m; `+ Q, w) [2 z6 \% \! c
                output = (INT)out;
& T, b8 H: l" p' h; m% A4 d                }( Y1 h/ g' a/ A+ |1 S& b2 [
#endif
  i" O0 r' D9 }) [. Z#if        0" p( O, P- Q; t( }: _! ^9 R# X
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)& A( k& D3 z% \/ K) {4 P5 ?
                {. }  E" N5 P, H% v2 O  h) i1 H6 ~
                INT        diff = abs(output-last_data);' ?: K7 N. [: u. T
                if( diff > 0x4000 ) {
7 c' P9 d) f* I3 }( B# m5 ?                        output /= 4;
- ^6 ~2 J1 O6 L3 F: i' b. o/ ~                } else 9 g4 L7 o! F" d2 k
                if( diff > 0x3000 ) {7 K# T7 c6 V/ y3 C# N5 a0 j+ ?
                        output /= 3;# F1 B' x7 f6 z/ ^# O9 U! k( l8 R
                } else
, G; B2 y0 n5 Z; _( M; ?" F                if( diff > 0x2000 ) {
' j" g5 F# i. E                        output /= 2;3 h5 T; f! m7 Z1 H
                }$ I5 k2 g: S/ p! s0 F4 g0 Y
                last_data = output;
2 [+ z. v5 D7 Y; x$ T0 z! T* _                }4 V# ]. t8 s5 t2 c4 [
#endif( D9 B0 K0 I% U" ^
                // Limit
5 L% V8 H6 Q2 D- S- h! `1 t                if( output > 0x7FFF ) {; a0 |) F0 W! F- T( k
                        output = 0x7FFF;) Z8 F3 l9 I- F; `$ y( W6 x
                } else if( output < -0x8000 ) {0 b7 z8 Q: R" p5 N
                        output = -0x8000;
4 e8 ]- v8 y* R: M( U                }
$ S& y  O* R  g, C1 i) q
/ N* d5 j0 v4 q                if( nBits != 8 ) {
% ]0 T, D" R! |" S! p                        *(SHORT*)lpBuffer = (SHORT)output;% _) A5 n) m- T% j; L: e+ T
                        lpBuffer += sizeof(SHORT);: [# N6 e; ]1 G' j; d# T0 J7 g  C
                } else {
2 x+ v% ^8 ^" {% C- P5 D& A                        *lpBuffer++ = (output>>8)^0x80;
8 V9 d8 c2 X, B! c( S7 @                }8 Z$ V& i# |& T1 ]! \% X! f, r% w/ O
2 G2 q& a; R6 l4 p# k+ [9 ]
                if( nCcount < 0x0100 )
8 m# Q1 @* C; z' i7 Z( X                        pSoundBuf[nCcount++] = (SHORT)output;
9 \" g$ L' m9 j" _! t, D, L
  Z2 ~' J" D6 E1 Y1 a//                elapsedtime += cycle_rate;
. d; E4 a  Z- ~& M0 [, m- f8 C" f                elapsed_time += cycle_rate;
) ]  X. _/ |$ ^! U- e1 b+ A        }
7 g" `0 E& x, s) o6 z# O; p# e+ s% [, ^7 A8 J: Q& \
#if        1& ]1 Z6 l1 E  s9 g7 V' H$ [8 H- k) I
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ n; w& R. o7 Y3 e
                elapsed_time = nes->cpu->GetTotalCycles();) p$ k4 k4 T1 w" s$ |
        }
# v8 L0 ~- \; T! n        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 S/ J7 n% j: T# E9 J- N( w                elapsed_time = nes->cpu->GetTotalCycles();/ A/ H7 }# Z6 j; r/ Q8 L8 ?
        }9 d7 B' f! s6 Z# c/ k
#else
% Y9 r/ O( m7 M! c8 G! p        elapsed_time = nes->cpu->GetTotalCycles();
: e6 c) |$ g" F% ^1 {( d" p6 U7 ]# T#endif
! O, a0 S; {8 L7 [+ _# H+ c}) f  ^6 E$ B0 I% q. B% Y5 y9 @' x

$ r0 b( C) ^  `1 K  {// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 F2 k% L* Y8 F$ b' b5 gINT        APU::GetChannelFrequency( INT no )
3 f1 b8 n4 {* |+ F  m0 a{
( E+ l# i: S4 U; d- f9 T6 A& B        if( !m_bMute[0] )
+ H% h( c# V8 C. b3 G- U& }                return        0;
" e. `- I& g$ c  h8 ?6 A, Q: a1 N3 @  O2 |
        // Internal
' B) I. y/ w* d. L( R# |+ ^8 `9 r        if( no < 5 ) {8 Q9 }( K, n1 c  `
                return        m_bMute[no+1]?internal.GetFreq( no ):0;: T/ {, W5 k( _! m3 D% @* G5 c" P& c
        }
) h4 m3 c3 v/ T& ^% E' W        // VRC6
- W* ~) B/ r" _2 H5 N6 O        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ {8 ]! d' u' l$ z8 `+ k1 ^) M4 b
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
* P/ P3 g2 o9 d2 {. Q4 y: n& q        }. y; h- K  h3 ~: i1 q
        // FDS" }; w: H7 N$ x: \' u
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ z7 Y- v) N5 a: m) {8 X& Z; p                return        m_bMute[6]?fds.GetFreq( 0 ):0;
4 E; A5 J9 J# t: Y! Y8 H        }( Z7 B; ^. H7 f! P- O0 G) N% C! r
        // MMC52 z/ |* P& f0 F: R+ f
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {- {! c6 ^; v5 B) W3 ^. c
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 U# R$ E% p: q5 J! r0 ~3 t& P
        }
3 z& k0 g/ ]$ m" f1 X        // N106
! T! N1 q5 I7 n) B' n: X9 g        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {. M+ y6 R. \  x0 Z4 N
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 _# ~! S+ A$ S        }
6 N7 W" L$ l- M$ J9 j: Z7 H        // FME7
# r3 V1 O9 m7 t/ D+ N: n        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 F% H3 P0 b( [' W; F8 P                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' B, M* I( D& x  x        }% R. h2 G3 S  g& p/ T* t& h
        // VRC7
! [2 A- H/ w/ x  J2 Z* D6 z8 Z, C        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
1 R$ k+ }$ P! {                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;) D* U& K9 Z0 V3 t1 |2 o" t
        }' y  M5 g7 ]( W3 ]* e% Q2 Y2 u, E
        return        0;: V: K* [9 D/ r' W0 k
}
! t9 q8 b& m2 w5 r0 J/ S
" V8 v" y3 k/ q* ^// State Save/Load; o: @3 P7 e0 [8 ^
void        APU::SaveState( LPBYTE p )/ v& R4 D1 f$ o7 A/ Q
{
2 D* h) C8 z& M; ]/ o#ifdef        _DEBUG$ A$ F0 ~/ H+ [
LPBYTE        pold = p;5 o0 \7 T$ \6 t* ~7 |
#endif  o  @, ]5 `4 t' b+ s% N

! t$ }1 I0 H9 a  E* I2 B1 ^        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- I- h1 l6 c# X6 H3 _- D, ~        QueueFlush();. J7 t1 o2 V3 R6 v
" u* [8 X% m+ k+ p/ }' d
        internal.SaveState( p );
$ |6 A6 \+ e$ Z6 f! V. f  o: |4 `        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% J+ G( k4 F7 y
5 {1 G! j0 D6 z6 M9 D3 `" H
        // VRC6
* s9 q; f. J+ a: b        if( exsound_select & 0x01 ) {
5 D, ]/ V# o& X- }+ H9 I3 c6 |! F                vrc6.SaveState( p );8 t7 Z6 O. [% {  r( a9 L
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 B6 X3 u4 N* f# w) G" J9 f. k        }
( Y- V% [0 |, a1 X3 p        // VRC7 (not support)
# \- ?6 y+ b& q+ }2 w        if( exsound_select & 0x02 ) {! J, L. e. e6 k& p7 @9 M8 g
                vrc7.SaveState( p );; I+ n% D4 U) k% C2 t
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 R7 g" [' y  I$ m2 V0 B; m$ Z7 C& o- c
        }! g- o1 |, C/ W! f7 ~+ g* A0 T
        // FDS
, \5 Z7 ^6 v& X+ f" B' \8 M" E        if( exsound_select & 0x04 ) {4 L; L7 }/ C( z1 ~3 K
                fds.SaveState( p );
1 S. ~8 I  Y% K0 u( U$ E                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& }* k1 z4 @8 `3 i: r% F        }
. {" I" H7 u1 w  ]) q        // MMC5
6 j4 G. l6 G  P( [" \5 m        if( exsound_select & 0x08 ) {( F% f6 }& b+ Q. c3 \9 q
                mmc5.SaveState( p );
( W$ B1 T# r. y9 M5 G                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding+ d; }5 ?( c8 Q! `9 m# W1 O
        }" s2 |& r1 L3 u" B( d
        // N106
9 P. r( K6 P( K% Z  e; _        if( exsound_select & 0x10 ) {3 w; j0 O4 s9 q- N, @$ t
                n106.SaveState( p );
$ ?( y# ]7 y, S( \+ s& q6 a8 b9 x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! A  S( [( _* K- F( n/ o: k4 L; O        }
$ O! H, K/ i$ J/ F$ k- G# ^$ n4 i/ m        // FME77 c+ V& I0 n( v
        if( exsound_select & 0x20 ) {
$ F) _& r# a% ]! l3 X                fme7.SaveState( p );: K, t+ h) U; m  d" v  `9 e8 E
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' i1 V& e9 {4 q5 B8 m# h7 q$ Z
        }
6 {$ }* _5 e+ V& `" @/ @% L% @( [  _* Y+ e- p+ `9 {
#ifdef        _DEBUG0 I8 a# S5 y  h3 G
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
$ k% h. |& k9 E4 h$ `#endif: N& G" o, E( m  w
}
/ D! H* d  f5 i# v3 l5 ?! L
0 y: @( y8 O" l+ u3 ~5 ?- cvoid        APU::LoadState( LPBYTE p )
) c# i' l; P3 F{
$ E2 A4 D, D9 F+ N; Q% n$ T$ F        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
6 e' U' P: @6 w  y/ c  y" M        QueueClear();
' O" m' [" K1 E2 P1 Z3 j+ `, L' i7 ]& V& H* m; d; R2 V
        internal.LoadState( p );
3 D4 P$ M; t& b# m% x% `        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( g& F' x2 Z6 ^' G/ z/ A0 _. ]
& h5 B) g2 s( q. a1 J
        // VRC6
# u6 q# z) d& M) [0 S9 |% H        if( exsound_select & 0x01 ) {% w- p8 S* k9 t% x  P' ?
                vrc6.LoadState( p );
, P" Z) y# w$ c6 z- K                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" e9 p4 n+ `% J& d* H, \" Y$ |        }& q$ S/ T, N8 W0 D* H& d
        // VRC7 (not support)) u% U& T. ^) _! v4 V8 A
        if( exsound_select & 0x02 ) {
$ q, R& a7 S, L                vrc7.LoadState( p );: a, B# O) ]3 k, O: G/ Q. P
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. }( o- X" B: B9 z* q6 j. c        }
5 O. v0 y9 z4 y1 m8 V7 _        // FDS+ X9 y, j5 ]; {. f; m5 E' W0 b& ~
        if( exsound_select & 0x04 ) {# Z% D! N3 ?: R" M: I: i* v/ H
                fds.LoadState( p );
6 c, D6 F; S6 {2 c% y: H                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ Q4 |. w- D2 K$ K, J" X
        }
! t, d2 J. l( x        // MMC5! ]8 w! f' P4 W
        if( exsound_select & 0x08 ) {
/ J0 o5 ^& [0 \( g6 ]9 Z6 }                mmc5.LoadState( p );
0 a# \: e, P' a* P; M7 Y# S0 i' m6 m                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! G& X% j4 E# g( ?3 t/ t; n        }
5 d6 ]  a, P4 w* m        // N106
8 y  R; m, z( e$ ?: l. j& @        if( exsound_select & 0x10 ) {
2 n8 W5 Z7 x( v                n106.LoadState( p );. A! l; B6 N5 q( w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  n" V6 h$ {4 l2 ]3 f
        }8 v3 n/ R" I0 ]0 `+ S* O. C
        // FME7
6 g- e% h' x7 i; y        if( exsound_select & 0x20 ) {  N5 F9 p. T1 v" r) T2 c
                fme7.LoadState( p );
3 o0 F2 }3 d: y                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: a2 y* P1 C" K8 R        }4 Z$ _+ F! r/ h" \3 R- }
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; o! g$ q6 U. E  J7 d1 h* S
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
% s. X; V5 x  \6 J感激不尽~~
* ~$ k1 y1 a7 `
恩 我對模擬器不是很有研究,
1 |5 y# {9 v4 W( H3 V  o雖然要了解源碼內容,可能不是很困難,
& ]6 T& z1 P! O不過還是要花時間,個人目前蠻忙碌的。! R  y) E) ]) L/ G. a" n

( B% Z- Z1 {! O- e- @: j# i* T給你一個朋友的MSN,你可以跟他討論看看,  @' U) l/ y4 G* o
他本身是程式設計師,也對FC模擬器很有興趣。0 z% D" v" ]. K& ^9 r3 [) F4 v

, F3 d! T9 U9 G% w$ e& b% OMSN我就PM到你的信箱了。
' B0 i3 b4 c# w: G9 J$ }; ]! M# G% i  s* @
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 : z$ L4 X/ p* _9 K/ x8 P
呵…… 谢过团长大人~~

+ Z' \5 p2 C% i7 T
9 D& w8 }! B; j# \8 X# y哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 F: D- ^4 @. ~- S) z3 |0 ~, Z团长的朋友都是神,那团长就是神的boss。
- h, j, T! i+ ?' f, g6 r" O$ Q
哈 不敢當,我只是個平凡人,
) g5 [* e  ]7 }要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙8 F& i/ \5 f) J
ZYH
+ l% F6 X0 g0 J) ^8 b' y5 Y8 uQQ:414734306
9 z$ n, Y, s' ?4 SMail:zyh-01@126.com
$ }0 i+ V* r2 v0 d5 a6 M4 @+ ^! b  x8 s
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
/ }4 I: I+ k- U6 ]. G再次对团长大人和悠悠哥的无私帮助表示感谢~~
4 T" o% a2 `% J6 t, ]
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-3 23:14 , Processed in 1.098632 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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