EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. ~, S2 \! k9 k3 B楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
/ S  A. z; T& E/ ?. f这里有相应的模拟器源码,就当送给大侠了~~
( l1 {& \. v( F' Chttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
$ i6 s/ d# v6 z) L5 T, _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
: `+ A' j+ a- m( N, Q! K/ q楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, |) i9 B# A7 X! h$ ?这里有相应的模拟器源码,就当送给大侠 ...

0 O" y1 O% q7 Q; c/ U' O/ K聲音部分(Audoi Process Unit = APU):9 ~3 L6 Y  a5 B7 q: l
.\NES\APU.cpp
6 a) E7 D3 Y( x' q) i.\NES\APU.h3 W. G- ~! P- G: Z2 U$ d) t  j: l
! G' n0 W2 T- r& t
, M8 k4 F/ c* B' A. Y
影像處理部份(Picture Processing Unit = PPU):
/ [$ S; B& C, C  @3 v4 `.\NES\PPU.cpp
( r4 m3 F. J% ~0 l" l.\NES\PPU.h3 _2 m- S" C/ N" D

5 x4 `: l5 o* @6 ^% [3 s$ G  D/ x如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:- C1 S, x. l9 k
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ k% [4 Q' U6 ^" d! D
//////////////////////////////////////////////////////////////////////////1 Q7 V: i+ I. ~8 V" d, t
//                                                                      //
6 v9 T& W6 y4 |0 `2 Y7 A//      NES APU core                                                    //. b/ b9 W0 t( V# U0 j% X5 W
//                                                           Norix      //
1 o$ s9 ]- a+ m2 y6 F//                                               written     2002/06/27 //& U3 {4 s4 }1 b4 i+ W2 c; B
//                                               last modify ----/--/-- //
* P9 k4 j& f8 U6 W/ [( o0 I5 a+ M- p//////////////////////////////////////////////////////////////////////////! }1 j- s" X5 l
#include "DebugOut.h"/ _) O  x5 k8 a
#include "App.h"
' |, R5 U- s3 X#include "Config.h"% s- U$ F) j) ]! u" O( t) j9 _# B

9 Z$ H8 ?6 L: @/ l9 r; p" V. d#include "nes.h"
  e# Z  l2 |; n# a/ w& T) G( |, F#include "mmu.h"5 ~* T8 z5 J% X& `) I1 a
#include "cpu.h"
* T9 T/ W& Y( `#include "ppu.h"8 g. C7 e/ A% E
#include "rom.h"# d- W, M  Y1 H& A* h+ ~# v
#include "apu.h"3 [! k) k: M- Q7 R# j

5 J! h% I. x$ d// Volume adjust
' B- Y8 N! a8 y// Internal sounds
, R* T4 Z" U' D# ~#define        RECTANGLE_VOL        (0x0F0). d. \. @5 w$ z) F: r4 c
#define        TRIANGLE_VOL        (0x130)
# I; ~1 C& @8 ~# M4 T#define        NOISE_VOL        (0x0C0)) {$ g7 Y& k. y9 \4 R0 p
#define        DPCM_VOL        (0x0F0). u; Q- u9 _) I
// Extra sounds' v- i8 Q5 E3 ]
#define        VRC6_VOL        (0x0F0), M# n+ x3 L9 j4 s- r& t4 o: I
#define        VRC7_VOL        (0x130)
% V) N  Y7 h  L. h& Q5 t2 ]#define        FDS_VOL                (0x0F0)
" q8 M' G( m5 V9 ~' b9 H#define        MMC5_VOL        (0x0F0)6 i# y) ~& P3 N0 x% C7 F$ D
#define        N106_VOL        (0x088)$ ~, A0 \7 W# ^9 M) J) A' z
#define        FME7_VOL        (0x130)
4 {; l& C+ |  k4 T% }7 b3 k; l, P: ^: b
APU::APU( NES* parent )
8 i; h! _3 U+ A- x) {{) N' k4 o) t. d4 ~, W
        exsound_select = 0;
1 q  z3 ]! y: v: }: V- o+ }, g. I3 v* G8 n! r$ s# ^
        nes = parent;
* d9 |7 T+ g9 D! Y, y6 }6 u$ c- g        internal.SetParent( parent );/ a3 W/ X" c. q0 y' p/ R

/ z$ i# k7 \4 N/ s9 _& z% |: ~        last_data = last_diff = 0;
# M5 _$ j7 j) ^% P* m8 l
# F/ F9 k/ ?% P6 E+ P) P- J4 u1 I        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( X9 g4 r! {" S! a3 v$ B
" u6 M! @/ e8 l! |
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
  B3 {: ]8 m9 o4 `- P        ZEROMEMORY( &queue, sizeof(queue) );* q6 i! ^1 Z# |6 @% O# |5 O' ^
        ZEROMEMORY( &exqueue, sizeof(exqueue) );% i2 x: o& ]6 _
+ k) Y, Z: U7 {' z2 v6 B
        for( INT i = 0; i < 16; i++ ) {6 ~1 w1 {5 R+ h2 K! G9 z4 T8 ]
                m_bMute = TRUE;/ i. H1 H+ h( n" Q+ @
        }
9 {0 |- N& H; L4 n+ d5 X}
; ?( {% F9 q5 i+ d0 t4 }3 N8 L: A% r- m0 K& @
APU::~APU()" x( }/ M2 B& R9 F) x9 J
{
: F; x0 j% ]$ R. n0 }$ |. j7 |}' U0 T! t3 o" j3 w6 Q  T
! p, ]# z0 H0 @4 ~
void        APU::SetQueue( INT writetime, WORD addr, BYTE data ): ?1 y9 g- d; q4 ~# d
{
+ b; T. F, Q, }8 Z" |6 d0 f4 [        queue.data[queue.wrptr].time = writetime;
0 |  m, v; @5 f. u' ~; H        queue.data[queue.wrptr].addr = addr;
& q6 R6 z; t' Q) J4 L        queue.data[queue.wrptr].data = data;
: Y# B/ R, [, ^) V        queue.wrptr++;, V" F$ v" \6 D! a2 }
        queue.wrptr&=QUEUE_LENGTH-1;* b. ]' u3 @" ~% ~4 m  Z" o
        if( queue.wrptr == queue.rdptr ) {8 D8 H; ]. S% S% o, L: F
                DEBUGOUT( "queue overflow.\n" );6 ]+ a* G& p0 E0 Z  P
        }5 l: K: ]/ v& Z$ z- `5 z" R
}
  o5 I6 I, C3 g* ]- I: J2 R9 ~! j- T' W# ]4 x. k
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- e, d7 N2 v" y3 l{  N" Z( E* y; [8 T
        if( queue.wrptr == queue.rdptr ) {/ O6 P2 N- @6 Z: C0 m4 B
                return        FALSE;9 [. i. v$ g- N2 a
        }
# a6 F2 t3 x) y& t2 X" [" k        if( queue.data[queue.rdptr].time <= writetime ) {
1 V0 _: k3 d+ H( l7 m                ret = queue.data[queue.rdptr];
; h7 z4 u) k  d1 s5 Q+ m+ r                queue.rdptr++;% {/ a  [& v  f4 _$ j) c7 y6 T
                queue.rdptr&=QUEUE_LENGTH-1;& P# j( w1 X9 W% j) ^" v
                return        TRUE;0 m( |& k, ^+ ]2 L5 _# O/ t3 d0 M
        }; `+ o& V! k1 l" h' g% k: \
        return        FALSE;
, O7 s" Q/ H, l! d/ @. m5 C}
' b2 ]0 V+ @' P# B/ B
$ t& i% j+ v& B3 d% w- ]: Nvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: r! e% R, l. i, Z( t{1 ]6 Z/ H& R" Q( m$ @8 O' Y# L* c
        exqueue.data[exqueue.wrptr].time = writetime;" ~) T9 W* v% g1 J& `( s
        exqueue.data[exqueue.wrptr].addr = addr;! c# @& J8 T) X- i0 K8 e
        exqueue.data[exqueue.wrptr].data = data;, B% P% `8 Q% f% [8 h% G" f$ v
        exqueue.wrptr++;2 ]7 k9 a. p, Q, d3 G0 O1 p
        exqueue.wrptr&=QUEUE_LENGTH-1;
9 U+ z1 a: X' K: r( F8 H4 R) D, q        if( exqueue.wrptr == exqueue.rdptr ) {2 J# e$ y' i( s9 f4 e) u
                DEBUGOUT( "exqueue overflow.\n" );  b. I. P7 F4 k- `6 A1 F" t6 L% k
        }
# O1 r. K- E( D: i; |}3 J6 y8 r- }9 M0 n
! P1 D6 q0 s* ?' r! X
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 P2 z% g: @9 _- o
{
/ d4 s0 Z5 U( F: F& b        if( exqueue.wrptr == exqueue.rdptr ) {
. R, Z$ e, a8 G4 e# W! g# {                return        FALSE;
3 O8 a  r/ ?* s* p* A; F        }
- O' F) I6 h0 b) Z        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! y% k; n: R6 V. W. S                ret = exqueue.data[exqueue.rdptr];, u5 E) z) j4 s- C) F# {
                exqueue.rdptr++;% D! s+ \$ `7 ^2 j! \+ g& `
                exqueue.rdptr&=QUEUE_LENGTH-1;
. ]0 L* B" t% T! E0 d8 I) z                return        TRUE;5 w0 V1 M. b8 e+ i4 `  L' L
        }
( z. Z9 P. ~6 U; I  m2 U        return        FALSE;
4 Y( B7 \9 w% _  l! H}
$ r# e# b7 d7 @" A# ~
$ c( a- F0 I4 U2 E! D$ }3 ~void        APU::QueueClear()2 C6 f9 V( S9 w: k. G% ^! y, h4 j
{
, |8 _- b, ~' i! W0 a. e        ZEROMEMORY( &queue, sizeof(queue) );
6 M+ ]0 W; R& n7 L' e  v        ZEROMEMORY( &exqueue, sizeof(exqueue) );( @8 @0 P( D. s9 T: X' G8 |4 x
}
( _$ }% Q9 m) z7 {3 f% E5 k
/ V1 v5 W9 T1 O# }+ J: k9 Rvoid        APU::QueueFlush()
8 _; \, V! L6 m+ F5 }! U9 Q- t{
3 d2 k2 ]9 P- @) L        while( queue.wrptr != queue.rdptr ) {4 Q2 F+ {4 Z3 Q! \1 u
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 k$ a/ r) H/ q9 r, ~' Z: {: ]
                queue.rdptr++;
" }0 [9 {0 S2 M% ^& c! A                queue.rdptr&=QUEUE_LENGTH-1;: A, w6 z! E' c/ T( U! V
        }, m& a4 u' r2 _5 z; C6 a; G7 A
2 J$ t! V! K0 L" k4 {2 }1 G$ k% J; u
        while( exqueue.wrptr != exqueue.rdptr ) {5 v& b7 H4 g! N7 o
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );2 l6 i$ t9 j* \2 J6 u! C
                exqueue.rdptr++;
0 _& k9 A0 [$ y0 K. E& Q/ @                exqueue.rdptr&=QUEUE_LENGTH-1;7 _; R. F+ ^  C
        }
; `7 Q0 J- c+ L: K! V}
! |9 U9 L1 H3 m5 Q
* w: |1 V* c7 c1 Q; W1 s$ S% ^void        APU::SoundSetup()
4 @/ w7 ~3 o; p! `- V{  U7 D& M4 `% e  V' G  T% m
        FLOAT        fClock = nes->nescfg->CpuClock;, j3 o: e, z) s; B" ?2 f( u
        INT        nRate = (INT)Config.sound.nRate;
, h+ @/ v7 p+ k        internal.Setup( fClock, nRate );
+ {& P  M; {' g( m        vrc6.Setup( fClock, nRate );5 l) X( |6 I6 N2 o* F
        vrc7.Setup( fClock, nRate );
+ V) ]' `, j4 \- H7 _        mmc5.Setup( fClock, nRate );
( y: D  F0 h* y" \% i        fds.Setup ( fClock, nRate );0 g% d7 t3 z* g
        n106.Setup( fClock, nRate );
# U! {9 k9 N3 M* n  P3 L( m2 x        fme7.Setup( fClock, nRate );2 |( T# c& y0 u
}
' A) M2 ?; J1 r: W
4 r) r. K0 f! O2 q/ Jvoid        APU::Reset()
. k8 D/ Z1 D5 _+ N{6 D+ H) n5 T, o, d9 ~# R/ l& I% s# X
        ZEROMEMORY( &queue, sizeof(queue) );
/ C& v. E& M3 B3 z        ZEROMEMORY( &exqueue, sizeof(exqueue) );. I- v% l0 C, H1 b5 H: U# |1 e

0 \) C8 s7 l3 ?7 R        elapsed_time = 0;
$ D" `  U, v7 m: O: Z( T! b8 Q3 J3 v" k5 B! v. O
        FLOAT        fClock = nes->nescfg->CpuClock;
8 E7 {7 d0 U, P: Q: Y, B        INT        nRate = (INT)Config.sound.nRate;
5 J0 _; P" D3 y        internal.Reset( fClock, nRate );- x4 g0 c0 s: x* E6 D6 k/ X6 a
        vrc6.Reset( fClock, nRate );0 L0 E! w( W4 R2 u) a, n" o
        vrc7.Reset( fClock, nRate );
5 Z. E+ x; i* i7 D% D- R+ }        mmc5.Reset( fClock, nRate );
* d# ]7 U$ I0 b; L9 O8 e) Y6 Z) G        fds.Reset ( fClock, nRate );
) r2 ^& r& M! \9 z        n106.Reset( fClock, nRate );; O. U! p0 V5 O9 Y
        fme7.Reset( fClock, nRate );* a' x" u, s; V+ E& x! h5 {, S
2 l" s/ Y; r  C/ t' N" P
        SoundSetup();
  O, ^% S! K8 O; s2 A2 _}9 j8 i3 {- j4 o" W0 f7 Z, Z
4 G( n7 w8 i3 H, O
void        APU::SelectExSound( BYTE data )( O! w! p1 M9 g
{5 d" X4 k2 b& I$ d* J! ~9 D0 ]
        exsound_select = data;% S, B9 \4 g& g/ r9 A
}
- M5 j1 p1 D( N6 Y- B3 I! |* D" W" c; Q5 M
BYTE        APU::Read( WORD addr )( T9 h( p2 o, S7 r
{6 }0 }* p' X" v' `$ ?% S
        return        internal.SyncRead( addr );: i1 r- T5 s7 H" g
}0 a9 ?5 T8 [& L$ Q: ?9 o( z! t4 A

/ p: A3 v5 E$ @4 o% _void        APU::Write( WORD addr, BYTE data )" G7 f2 k4 |; _3 H/ R) o- F
{' U( W3 ?3 d: J2 ~
        // $4018偼VirtuaNES屌桳億乕僩
) o& C  ^. ?0 v; x1 I3 ]. A6 u        if( addr >= 0x4000 && addr <= 0x401F ) {
! P0 }" z, S6 v" P# \                internal.SyncWrite( addr, data );9 f; Z! |' m% E. Z2 f; ~1 v4 e
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
5 p( X1 W" G# U5 b! l2 ?5 a        }
# F9 Y. V! j: Z}
' ^& X" Z8 w+ N2 D6 d) k
5 S- p& {* c3 l  k& S$ B# TBYTE        APU::ExRead( WORD addr )
* @% a0 K  s* d4 ~{3 d+ d+ B* J, A: l$ A+ V. O: V
BYTE        data = 0;
' ~8 q1 ^6 a1 z0 i- H" Q5 f: t7 d9 M$ B6 d7 U* @
        if( exsound_select & 0x10 ) {
. k: J! w/ H( ~0 O                if( addr == 0x4800 ) {
! @) ^5 a) a+ S( j                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 ]6 s! P2 t! C5 i$ w+ S/ J+ i. h$ `
                }8 L. o6 ^8 T! ~/ d# f$ B( r2 C  [$ o
        }
% [) f" x0 q& x- ~        if( exsound_select & 0x04 ) {
4 `0 O' O* C( i3 _" h1 T                if( addr >= 0x4040 && addr < 0x4100 ) {0 k. K) d: e0 [
                        data = fds.SyncRead( addr );+ |/ {! T# ^' u5 O; v0 y0 J! Q" x5 v
                }; m6 [6 r; |( h3 h2 _3 x) o
        }
9 X5 }" [% `4 x3 K* r        if( exsound_select & 0x08 ) {% k1 w( f. t- o$ A7 r: G
                if( addr >= 0x5000 && addr <= 0x5015 ) {, ^9 o7 r& Q! [/ [: `1 G' i
                        data = mmc5.SyncRead( addr );3 c# U7 S% [( Z8 Y: f" G7 s7 P5 W
                }9 h+ w- _* w1 ]  `2 L! ^
        }
% E. T( k! Z4 B" b, _: }5 t2 F! x( g, A
  Q* P* y+ r. P5 Y" u: b3 x        return        data;2 ~' _3 E+ U7 W
}
$ n7 r, h& P3 D$ p8 K6 a+ d
2 i9 J& u* R) _- G. i- i& j: Kvoid        APU::ExWrite( WORD addr, BYTE data )
/ k+ j( \* i$ F6 f3 T" p# K/ \$ c{9 b, u& _9 @! O: C. u3 ^* ]- ]
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 R$ S0 h# R2 a; ?7 M8 K0 b8 [+ t; N6 w* L: J8 _  K1 ^
        if( exsound_select & 0x04 ) {
+ K. J: D( ~, l                if( addr >= 0x4040 && addr < 0x4100 ) {
& N2 Q' M; f* K3 [4 J% \4 m                        fds.SyncWrite( addr, data );, }  \0 q' W, P% K( l9 j5 f
                }2 e- ?/ o; |/ ]0 M3 z
        }
/ ?7 |' @  H7 N" \
9 t9 ]7 B$ s( a) O' E! R        if( exsound_select & 0x08 ) {
$ V, K4 [) k0 f. l1 g2 g                if( addr >= 0x5000 && addr <= 0x5015 ) {
# G; o  G: e; p- n& Z                        mmc5.SyncWrite( addr, data );
  ]/ X. R$ o% r) W3 I6 i1 A                }7 e: a. k$ m" P: f
        }
- h2 \: c1 ?0 p9 X) a2 U! G6 l0 S}
0 Q: w( g1 L- n! U4 J7 A
7 m: d; ]8 ~( Mvoid        APU::Sync()
+ c0 k7 p" k) E3 Z{
5 }; K, y5 o8 h* w; l% n8 V}
" p+ M% H4 j. P! A: F3 ?2 l- _* {. d9 u; V
void        APU::SyncDPCM( INT cycles )# @4 }1 q' H! B; j5 m% o
{1 ?! T" w7 y  S% d7 c7 m
        internal.Sync( cycles );
( g, h& K+ V& L) a2 z" b
$ [  R/ y+ ~5 P, H        if( exsound_select & 0x04 ) {
! l5 Q1 g: c; x, a$ U- U9 X3 i, B. V! O                fds.Sync( cycles );& n/ _7 F3 b5 T) B: _
        }
7 {2 E4 E  @: C- t. ~6 ?! m        if( exsound_select & 0x08 ) {" O! w8 h& t" C* f' ?; }) C
                mmc5.Sync( cycles );
& H5 q' T7 N: W, c" ]% ^        }) ?/ H3 ]. O) P2 F0 }3 x$ R
}- e; E' l' Z2 x1 Q" {
% Y) j+ |5 E2 k( ~5 }
void        APU::WriteProcess( WORD addr, BYTE data )
; k7 |2 t0 y, ]{
3 D' L; w. n" u        // $4018偼VirtuaNES屌桳億乕僩* `; ^$ G6 T" d8 M
        if( addr >= 0x4000 && addr <= 0x401F ) {  {) Y& ~% a: _3 K* K( H& H! y
                internal.Write( addr, data );
4 W* }: A: J% ^' r# Q        }8 Y. y1 k2 Y9 W! n# o
}9 F) u4 X: W$ A% ^$ L; A
" }* |$ @4 w/ r3 H
void        APU::WriteExProcess( WORD addr, BYTE data )
! ?" E: @" l  }3 e{
+ N& J/ B$ y+ z5 y, v$ `! J/ F        if( exsound_select & 0x01 ) {) p1 S: }- h1 b* Q& D/ R+ U) F
                vrc6.Write( addr, data );
; M+ i/ X4 }: i1 b; a) E" k' x        }2 P, s4 [0 z$ M) t3 a; F
        if( exsound_select & 0x02 ) {
5 s( w0 W! n% s) z/ T                vrc7.Write( addr, data );
. E" ^% u# S% |2 l4 h        }) @$ v& G) x2 C6 ^; W" O, v
        if( exsound_select & 0x04 ) {
3 l; y+ R+ O, [3 @* v6 t$ e0 p                fds.Write( addr, data );  R& K3 O$ G0 i2 m& A, [2 m
        }% ^7 p4 {1 N0 a6 [% e
        if( exsound_select & 0x08 ) {3 x. s# h; \" t2 ]
                mmc5.Write( addr, data );
0 {3 g6 B" |  T# U+ j8 _3 I# g9 M        }
; K2 l) I. e5 |& e2 k% A        if( exsound_select & 0x10 ) {3 i+ s5 V2 |( _+ }$ R
                if( addr == 0x0000 ) {
2 q1 _# ?) Z, g; g$ c3 a                        BYTE        dummy = n106.Read( addr );
" `5 Y) H7 z1 S: Y/ Y3 {# C                } else {
# ?. D8 \1 ^+ \6 N) g                        n106.Write( addr, data );8 c  U, |- o& y  c$ E; q1 e
                }
9 W9 w0 D  r* B' E3 J- m! p        }
: j# y( a5 L( G3 ]$ t. E0 C- x        if( exsound_select & 0x20 ) {4 P/ ^/ E8 g, k6 _% e/ p+ F- K
                fme7.Write( addr, data );1 M3 X. l& J4 m/ d7 |7 ^% B
        }
! d# `* x) H# M* h, t}$ ?& z' o2 h$ Q/ A; V2 G& L
$ n; L0 D3 P0 p
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 |7 y; b/ k  G% \6 i7 Z, O
{
3 U6 M+ k8 d/ WINT        nBits = Config.sound.nBits;
; B' s0 ^5 ?9 t% ~# ?# |4 SDWORD        dwLength = dwSize / (nBits/8);
; w% M: V' g6 fINT        output;
0 b1 w; r& T0 V+ y0 N0 x0 k7 c  ]; }7 ZQUEUEDATA q;
$ A. `& [% W; j9 V: N6 K3 NDWORD        writetime;
4 X, v5 _: M% D, B( A" E8 p# t5 }5 J! M
LPSHORT        pSoundBuf = m_SoundBuffer;: H, l* O- `$ F  m! b8 q* ]
INT        nCcount = 0;
1 I: p: @/ Z$ Q* h" x4 q
/ X) g& L, w( w1 L, R7 }1 vINT        nFilterType = Config.sound.nFilterType;+ k9 n! d/ J* J$ [, Y6 M' P+ x

# P+ V, Q, R* a. H        if( !Config.sound.bEnable ) {
" Q, X/ a  M% x  c1 t% K                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );& J% |3 c# m' |
                return;) h0 w: X3 o/ e% Y# Z3 n5 B
        }/ l( P6 r# q% R- v  q$ ~+ r

9 x4 _% a' W& Y. m5 @& O6 R        // Volume setup; {. ^. u9 r3 c: b3 e+ T' I) Q
        //  0:Master
+ A- X% C7 O. `, l3 S" g        //  1:Rectangle 1
4 _5 ^1 D$ m8 T( ^0 B) B$ k        //  2:Rectangle 2
# n& `( j3 n' H" `        //  3:Triangle
% `9 o( ?- N# Z. m% ~5 z        //  4:Noise' p" p$ Z: N- _$ H8 z
        //  5:DPCM$ y. _/ p$ \2 N8 k! l% F( a4 C
        //  6:VRC6
% x/ a4 H6 ^7 Y7 c        //  7:VRC7( w  c4 Q5 ^0 J/ p# G% V  Q: V
        //  8:FDS$ u. E: u  R6 d4 {( Q
        //  9:MMC55 W1 s  b2 q1 a. q- E, a5 y
        // 10:N1062 g( `% d) R8 m$ K
        // 11:FME7
) Z0 F2 P8 \+ ^3 R, D/ X& x+ W9 _        INT        vol[24];
, [/ m, k$ K( n, L. d        BOOL*        bMute = m_bMute;
8 w6 Y' [7 N- e. O# ?9 d, w" b        SHORT*        nVolume = Config.sound.nVolume;& J9 {6 C8 c& g; L
7 x( K9 M2 d5 Q, l
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;: r% A+ l0 P7 f# R) X" w
3 M. C  [% O1 p- s  K2 z" g
        // Internal
0 g/ M* H8 d5 V        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( w9 H/ o8 F. |  a0 {
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# q+ p( s7 V$ D; ?" P9 L: S4 A
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
. l0 d& ?& s8 k- ~" O3 N7 p$ ?4 R        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;" @* u6 R! |: P! z/ @
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;- n* J: x- L  M( [( c
! w, ?' Q) Z/ j( j' ^( w+ n% t
        // VRC6' s* y+ D9 Z6 B1 J: q
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 h/ G' |$ t6 ]. R0 U& V+ n/ D' @
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- z+ P2 N3 A7 f) q) c# F4 ?        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' Y5 k6 a1 ]1 M: y* k& X% E$ ~$ ?) B7 A# l( `
        // VRC7: C( S: K2 A' g- T* ?2 A% r
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;- J# S1 t& d. K# Z, Q" W5 {
! g2 o5 T- ?/ H" Y6 r
        // FDS; R( e, @+ u' [; S
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;* f& i6 `  X: w0 B
, I# X' M) c% Q& s" }
        // MMC5
& l' T- t- {7 U& A' k2 ~. ]        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! a3 ]( |6 O$ z5 E( B+ [/ r6 r6 j        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# c( c; K. q7 f! d. a: I- J0 R
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; D3 {1 |$ n# {3 y" p# g
7 ]" U4 r3 h6 m+ V7 }% s. K
        // N106
3 x, B, x0 Q/ g" p+ @( e" i5 _; g        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ q" ?; X  Y4 ^$ h+ _
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; F8 k  `% f4 A        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 l6 h* g' Y2 R/ l        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) h$ X1 l& l& X; p+ t        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 Y  g. `. F3 V  p1 P3 K! Q' K        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) [+ Q; k! l) y8 T) g/ ^        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ A/ n' d3 e1 t% G        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ F# R9 p, B0 s3 E1 r9 Q
( G. W/ K0 j! t6 @' g( }        // FME7/ [( V7 s6 q; E
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 F+ a8 M8 k. }5 G6 I        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) [; K& A  }+ h' f/ L# Z        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' C. e$ w% X& l" w

) ~: T+ ?5 I0 x/ N% ]. F//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 f- {" q) |' _3 [' l  |1 [        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
6 J) u2 T5 y9 D: y% A: t% ^7 F3 q/ O1 L) f  H+ D  \
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟$ I- T. j% E  J$ g% }; a$ x( H
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {! E) u9 I- C3 u; D8 z+ ]
                QueueFlush();
/ n9 `6 `6 `, e! H( l$ |        }
( E  E6 W+ r' t' m. f" M7 P4 m8 d) D5 U- Y' \+ _
        while( dwLength-- ) {; W" `& l& Z& T" [& Z2 Y
                writetime = (DWORD)elapsed_time;
* y( B0 }& Z! L. {8 Q9 r& p+ D" p! F# |
                while( GetQueue( writetime, q ) ) {6 r; c( [0 _$ P: }
                        WriteProcess( q.addr, q.data );, R& y  s# L# T+ z/ v. W8 }1 _
                }1 N& g' A7 h1 M# r- |; F# l, S

" C2 t" A5 k2 y0 K) ^2 |/ O                while( GetExQueue( writetime, q ) ) {5 U% E% V2 V" x* i% |2 v1 `
                        WriteExProcess( q.addr, q.data );, m) ?; S8 a1 V: U! ]
                }
* j2 j: u6 P/ s! G% z  i+ {& Z9 ^# e6 t9 Q3 i. E8 A
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 o. E0 S* I- R  _/ o
                output = 0;4 U* p; o2 \+ x$ ~7 i
                output += internal.Process( 0 )*vol[0];
7 ^, ~1 M; B" l; Q6 G0 k% f$ ?* ~$ I# H                output += internal.Process( 1 )*vol[1];
, e" o. ]0 y' v- c                output += internal.Process( 2 )*vol[2];% y  A. {  R9 d( @: I
                output += internal.Process( 3 )*vol[3];
' Z9 T) E% M4 q# ?5 v- X3 \. B                output += internal.Process( 4 )*vol[4];2 o# w2 x/ a6 x& K4 d; R. b3 v/ o

4 `4 N) m% d- R8 q1 m                if( exsound_select & 0x01 ) {4 O3 V/ K) {, ?2 |( Z+ p; D( Z& c
                        output += vrc6.Process( 0 )*vol[5];8 D0 D' l; E7 [' O# m! [' ?4 q
                        output += vrc6.Process( 1 )*vol[6];0 C+ o' s+ ]+ w8 z
                        output += vrc6.Process( 2 )*vol[7];' D3 g; V' x3 _" a0 |
                }
: T0 K% L% M3 P0 V) e7 ?                if( exsound_select & 0x02 ) {
- l9 _$ a" J4 b  [2 o- B& ^7 Y                        output += vrc7.Process( 0 )*vol[8];
# n% ?; a3 {0 W, L) O: h! F, z4 ]                }$ Z4 d3 w  @6 I4 C% L' X
                if( exsound_select & 0x04 ) {
3 R0 ~& i, @% s; ^1 u% j                        output += fds.Process( 0 )*vol[9];
2 I" y$ M, O3 H1 M' a' u8 t                }- F$ R9 b$ }* o
                if( exsound_select & 0x08 ) {
9 S7 F9 K/ G- v* p$ g. C9 }                        output += mmc5.Process( 0 )*vol[10];- T# Z. W5 ]) _
                        output += mmc5.Process( 1 )*vol[11];0 M, N! P5 G* `
                        output += mmc5.Process( 2 )*vol[12];0 P( h7 R# g4 \
                }  O+ q2 X+ F% z9 R
                if( exsound_select & 0x10 ) {
% {" r* G1 P  Z0 Q9 U                        output += n106.Process( 0 )*vol[13];
3 l- t3 P& g- i) ?' j8 r3 t                        output += n106.Process( 1 )*vol[14];
, J/ U4 j3 w/ B, \( {2 m                        output += n106.Process( 2 )*vol[15];
/ R' Q+ @' ?! w3 B' e& u                        output += n106.Process( 3 )*vol[16];& o4 H  B  k2 D+ |% ^( A! G
                        output += n106.Process( 4 )*vol[17];
) |; o* X8 J) I4 v( g; _5 r                        output += n106.Process( 5 )*vol[18];
) I( H7 X1 i( V                        output += n106.Process( 6 )*vol[19];
' b4 @, K8 Y7 t6 U                        output += n106.Process( 7 )*vol[20];: x4 e- X0 S0 g  f# Q# j3 V
                }
# x6 `8 x, r9 j1 T  _9 M; @                if( exsound_select & 0x20 ) {9 K9 V1 H0 R  F8 x- a. F; I* K
                        fme7.Process( 3 );        // Envelope & Noise
' ~, o' {) C1 s6 a, V5 n                        output += fme7.Process( 0 )*vol[21];: p0 J) J% R: |+ ]8 u9 L
                        output += fme7.Process( 1 )*vol[22];+ E( {& [. g; u2 m3 v- s2 ?
                        output += fme7.Process( 2 )*vol[23];5 P8 ^2 |, S* ?% v
                }
6 N: {: u& g0 x7 Q5 t0 X0 c! v$ u( g
                output >>= 8;
; d. T( J! @, [) r. `$ ^3 J- x$ G) Y5 e- T/ S
                if( nFilterType == 1 ) {, D2 u7 M; o8 D  V" O/ q
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)% G. a/ f* v& C  Q$ ^1 j
                        output = (lowpass_filter[0]+output)/2;
- S1 N/ {) E, h+ F9 T& S8 k$ }8 ]                        lowpass_filter[0] = output;
6 g/ x3 e& L- z: O; i9 K                } else if( nFilterType == 2 ) {) w! ?* P& e0 t- _. b) B
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 w0 v5 P0 D1 L! d4 u& O; i
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;) n2 y) C  |3 d: H; S& N; I
                        lowpass_filter[1] = lowpass_filter[0];: M( i! o3 F. J
                        lowpass_filter[0] = output;
' y9 z4 f- P  [: X                } else if( nFilterType == 3 ) {) x$ d/ f8 j. i
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 e! u& W+ v% d3 T9 s1 f+ F
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;6 Z0 ^) e7 m4 w: k
                        lowpass_filter[2] = lowpass_filter[1];7 I, w6 j7 Y# ~+ h( \
                        lowpass_filter[1] = lowpass_filter[0];
7 Y5 C3 F; |: F! T  n& U* [5 ^                        lowpass_filter[0] = output;; r4 q& u( J$ d& G1 f" {
                } else if( nFilterType == 4 ) {  k* \7 k7 o! S& o# J/ @
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& h) {) v) v8 n; ^                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;# t1 Q7 T6 \8 m1 Z
                        lowpass_filter[1] = lowpass_filter[0];0 y2 e8 \, W% M
                        lowpass_filter[0] = output;
' |2 p/ H4 t* i( x) \                }& C+ e- }( i5 ?
- S4 o' |. v6 C! g( n
#if        0
9 e, x' T+ c( u+ u+ r* a4 g                // DC惉暘偺僇僢僩: h  }  O* S! K' ^$ [3 A9 B
                {% t& K* }+ g* q" r" M6 K
                static double ave = 0.0, max=0.0, min=0.0;6 Z2 U& o5 I3 n- V5 o, q4 ~
                double delta;
1 i) C( q3 W) n$ n, m) E$ c" w- J                delta = (max-min)/32768.0;+ m' a1 E; _( E) i
                max -= delta;
; D$ ]0 Y% \- b! F2 G, z- t                min += delta;$ k5 H( s" X( n+ }
                if( output > max ) max = output;
' _' I- L0 J8 _% r! H; E" f7 i                if( output < min ) min = output;( g) y  z; t& m; ?, c, X9 d+ E% ~- s, N
                ave -= ave/1024.0;
- |9 i  E# F+ M5 J                ave += (max+min)/2048.0;
( k% p) g! ?0 f" c                output -= (INT)ave;$ g  U; S3 a* k, _) R9 W3 R& S( g) }
                }
. Z7 c$ }7 X- B: n#endif
: j( b7 t2 f. b; y2 x8 ?- G* c. h#if        1
5 k3 }1 N1 s9 }                // DC惉暘偺僇僢僩(HPF TEST)- m: \3 H/ B: m& S7 P5 L
                {0 h+ m+ _' ]; E; o+ R8 \0 X; e
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
% M/ P" I) ^: a( k/ n* V& V                static        double        cutofftemp = (2.0*3.141592653579*40.0);
, m1 |2 k& d8 t! i( N" t                double        cutoff = cutofftemp/(double)Config.sound.nRate;# t6 m3 n. V; F7 @
                static        double        tmp = 0.0;; c: l7 _6 Q- G! }
                double        in, out;7 u0 e! C; e4 X  Z1 T+ p
) Z8 {( j+ b- }9 o* f6 u, A
                in = (double)output;& H9 d4 W+ Q( e) c
                out = (in - tmp);; r2 J# k' V5 \4 Y4 B4 @
                tmp = tmp + cutoff * out;
+ y% U9 g) u- R. m
2 n- y/ L9 {: `( Z- Z( @) |                output = (INT)out;
3 Y1 q4 L. N& n                }
9 d: y1 K( O, J+ D#endif
$ p9 \; t# Y3 T1 W" L- ?" L& T) v#if        0
& V& d% V: u# M  Y# Y9 Y                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% H/ L! D* Z1 h8 E' O; i
                {
: E! I: C( i  U* Z. b4 }# H$ U( w                INT        diff = abs(output-last_data);, z+ g0 Q1 F' [, ^6 f' _9 n
                if( diff > 0x4000 ) {
. R5 {  C: w* M' W$ j/ b5 }) M1 F3 B                        output /= 4;
3 t) e) z6 e+ R4 ]) w" L. c                } else
0 _4 C% a8 B* ^; F/ s                if( diff > 0x3000 ) {
4 P1 N2 d% o5 W3 D                        output /= 3;
+ K3 i, J& s; ?                } else
6 k0 q( w& F; P' @. P                if( diff > 0x2000 ) {
$ o+ O$ H# T1 C                        output /= 2;
* K/ B" [' J4 \7 u                }; A& Q4 \( g% o1 N8 y
                last_data = output;
7 C; ?; M: R/ H6 r7 V" n' r                }
) R+ k- d0 U: m" j0 N- x0 v7 b#endif
2 i; v7 ^7 t( |5 m' h                // Limit
( K+ S6 b: k' I% W* |( e                if( output > 0x7FFF ) {
6 e( W8 b) o3 ]- M9 N                        output = 0x7FFF;
9 i0 X) m1 _; k                } else if( output < -0x8000 ) {
. k) {1 L6 x$ k! [% C3 [2 D% Z                        output = -0x8000;& U( {9 K- f' Y: _) o, K; J+ ?' T
                }
. {; w& @" C& z* @7 v4 A5 h  n0 y: S7 ]3 ?0 w4 a9 x1 k5 q
                if( nBits != 8 ) {( V7 u: c2 _. N$ B4 y) m! o2 c6 W
                        *(SHORT*)lpBuffer = (SHORT)output;0 Y! G; t3 {5 k: Q- Z
                        lpBuffer += sizeof(SHORT);
; m, Y6 T% f. d$ v3 R                } else {! @! \; O9 P# X# _
                        *lpBuffer++ = (output>>8)^0x80;
' u5 P6 n. I- R( L6 N3 \                }
( e2 l$ E2 |3 Z% M  j+ q( r# l1 u. o+ V  N) R  B: |5 \
                if( nCcount < 0x0100 )
2 c1 a6 y' q5 }* D9 N; N; j                        pSoundBuf[nCcount++] = (SHORT)output;3 o3 R2 w4 F+ H  R6 m% `+ q* i
8 S4 B5 e/ O" r# ]& J: V8 x
//                elapsedtime += cycle_rate;& y& |) S$ J( C/ q) J$ H  t6 r
                elapsed_time += cycle_rate;
: j& U" T) d" V  ^* f7 h0 E        }
' D) `# P9 q  J+ z2 [/ v, ~8 w( D% `5 ?" g- Y- p
#if        15 h1 h) }$ M! N4 O" n
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {5 n. j% ?& t- ?1 v$ m3 J" \8 p
                elapsed_time = nes->cpu->GetTotalCycles();
6 k1 g, l6 n8 m# o: Q) G- V% N        }5 \/ W; B" v- a9 @# n" r
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 h& M( ?; \* V  d+ \$ {
                elapsed_time = nes->cpu->GetTotalCycles();9 }0 [. m9 L5 `' Q
        }
0 d% l. D- p, ~  ~#else# I& c7 ^$ |7 M- I8 G% D
        elapsed_time = nes->cpu->GetTotalCycles();
- D3 k6 G( A% q#endif+ k: g+ i! T4 e9 B2 z# m! q
}& d( k1 D( y! T( P' p$ c  W
7 l- s  _$ q. g
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)3 `6 b% @' l& P; G; \
INT        APU::GetChannelFrequency( INT no )* C6 |/ z4 z, s5 P8 v0 K1 ^2 o/ U
{
8 n* Q. j) U' j% Y) @5 y/ x        if( !m_bMute[0] )
$ N9 m  @! A! A+ I% I$ H                return        0;0 w# c5 T8 t' L8 S0 ]! G

0 H/ S1 a* l6 g7 w1 @7 N        // Internal8 ]7 e# N7 }1 o8 i( ~# }
        if( no < 5 ) {
0 H3 x* \$ E) i; C. V  e" q                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( B( `, [+ _* H" _        }. L4 t5 Q, O( v$ e' S
        // VRC6
% M  M7 ^+ e2 N0 K4 |3 ?. Z        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" g% y# x2 }4 z$ \                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  I" c+ Y' q, J' T0 t
        }
  f; F$ J3 Z6 ^$ m6 y% V- h. _        // FDS  |3 Z5 R1 _: o& ~; U
        if( (exsound_select & 0x04) && no == 0x300 ) {
5 W$ G2 G# o/ e" y: q5 a6 \                return        m_bMute[6]?fds.GetFreq( 0 ):0;' ^3 }. j) E' V4 B
        }
& G9 |" X. d. f8 u        // MMC5
! M, z! Y' L6 y+ M. q( G        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {3 V1 ~. h2 I0 [, S3 f3 g
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;9 j1 T2 n) h" i
        }
5 n, f% W1 ]! r+ i        // N106
& K! f( O0 u! U9 {6 o" P% p8 e& B        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 c- U: W  s2 z( _$ [9 ~) K( y. j
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* ^) U5 b/ e( {& P4 u  n6 C        }
/ \5 ?7 [! A1 n5 P. w* ]4 K2 _        // FME7
; J) w3 i9 k7 l2 q& \  X7 ~        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 @: U4 N- m# ~3 I! \2 z2 R; N                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
( U; F- O% I3 `- g1 Q8 F, x8 j        }
# p6 g9 R1 {" A0 r' m        // VRC76 ~3 g; q$ i4 m
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! u: |' H. S, w4 x1 f$ H
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
! a$ |" [3 J. @3 g/ i        }
( m3 B5 ^) i% l* a& H" Z$ g& Y6 Q8 Q        return        0;" l0 A9 z: b2 ]/ t2 y0 c2 X+ P
}
) {- J& x9 b5 \* A7 P9 |5 Y! B+ q) s/ C
, O. j9 R" x' B% R$ |: n6 D2 [// State Save/Load5 s4 c9 C7 \1 c* g
void        APU::SaveState( LPBYTE p )& k4 s* z1 [8 C6 u9 E1 d7 S7 J' x
{
# ?: n5 H( {  C3 t#ifdef        _DEBUG1 Z! ]  Q1 h$ S
LPBYTE        pold = p;
- H: D# z$ D* R#endif
' ~7 T1 A5 u) U0 j0 v7 u/ L& H4 R5 k
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 k8 w8 G2 t! F5 w6 z, _+ f0 k
        QueueFlush();
. I; R+ {! V4 Z) B7 D" V6 @7 M: S$ v! D0 z, X: q$ S
        internal.SaveState( p );, G& A; m% T8 E( u- K
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 {% |1 G2 D+ M! l8 \1 p( K- {4 D3 c/ _2 _+ W: p) }7 h) w
        // VRC6) j- P, n: o+ ]+ y7 h! Q3 D  @" {
        if( exsound_select & 0x01 ) {
/ g, H9 j) }* q$ a$ o* `& i' z  {                vrc6.SaveState( p );; V# x; K2 O5 p  E1 R% `
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& C/ e4 ?2 b7 p9 _0 w        }8 C* k6 ?% o& S+ Q9 S* N) d3 c
        // VRC7 (not support)
  Z2 I8 c0 ]9 p% F, E- k" ]& ?/ A0 P& S        if( exsound_select & 0x02 ) {0 d* r" ]7 L' R3 V$ I
                vrc7.SaveState( p );
2 E! ^" y# A! ^. [5 M                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# O/ z( U) Y( `: K
        }
7 A7 B* }7 ^; O- ]5 X7 B. w1 b        // FDS
* o2 x" f4 s' R        if( exsound_select & 0x04 ) {% ^5 {8 f" s& L7 L0 d
                fds.SaveState( p );
% f4 [: s$ S" i                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- i6 f$ s. t6 u" c4 R3 o
        }
( v3 ]% P, ]0 P" q* C        // MMC50 b1 F& E! T1 q  V( K
        if( exsound_select & 0x08 ) {
) P; [1 y& T* I; D5 `* ]                mmc5.SaveState( p );
0 j2 Q+ H$ O: k0 t6 t$ R                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* e$ A2 w/ J! S1 `; ^' c        }
# H# a' r% [8 B/ R8 N- D6 K- ]7 N! z' l        // N106$ t5 u) m- I+ A* l$ v
        if( exsound_select & 0x10 ) {
5 y; x7 m( `3 q0 t( q+ {( U0 @                n106.SaveState( p );, P9 u' l0 t) B% c* S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 _1 Q* h7 l8 ^1 w        }
7 r7 _3 a- S) i" K        // FME7
$ _6 X: M2 {% b" G9 m) x  I        if( exsound_select & 0x20 ) {
% Q, o, U& g1 y# s' C+ J                fme7.SaveState( p );; ^2 G3 G* M( O" N& [" T8 C- D+ A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding8 z. ]9 q1 ]( r0 }. r+ R7 u! |
        }; _" N5 z, @% O3 \$ G
: d( ~% o! D( d4 y1 j% O
#ifdef        _DEBUG, e% w9 d: e8 Q! m, Y
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );+ x  t1 S3 C0 c3 E% m
#endif
8 ^- p7 I: i8 s2 B3 L( R: f* {}" a. W- K7 I7 a) W$ m( N
; ^0 y% a$ e  ?  m5 i
void        APU::LoadState( LPBYTE p )8 b, J: h0 L) F/ {3 C
{
$ |9 k& b' v0 h0 u" k! ^        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 J  l8 V  p- ^! ^! r        QueueClear();) |) H- b9 K8 K5 B- ~
5 x: a* e% v: L" o4 f& k% L5 f
        internal.LoadState( p );
" O0 z# x7 A( c+ x- z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 A5 W) g# T' v- C: V/ X

$ Y+ z- p, Q. X        // VRC6
# ?) ^! S/ A+ }. A! V' q        if( exsound_select & 0x01 ) {
. m8 E2 C7 l: R! `                vrc6.LoadState( p );5 z9 V7 g& E+ ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; S5 w2 K- b8 s8 f; r: N
        }
) P" P7 ?! S1 h$ u% [# w0 |        // VRC7 (not support)$ {( T6 V1 j* e5 N# b
        if( exsound_select & 0x02 ) {+ G3 R3 d% ^9 i6 d  d9 o: F
                vrc7.LoadState( p );
, a4 r" d% ]& u0 K! W! o3 h                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* A  o1 X3 y1 l* X; Y" g        }
7 o/ x% n- {9 N; V) j( s8 v        // FDS% }6 I" ~4 H$ B( ~$ T& d1 @9 [' q
        if( exsound_select & 0x04 ) {
2 A5 Z3 ]' Q' q- i, R, J( J, O6 p                fds.LoadState( p );
$ [+ z5 c3 v9 @+ @; K* L8 j% ^3 t                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 N0 ^0 ?7 A( O
        }
+ F% U' y2 [; o( t" h9 z        // MMC5
5 I, R6 ]( w0 `5 P8 t9 B) m9 |: E( W# P        if( exsound_select & 0x08 ) {
# r/ e3 x/ j1 g2 a8 ?. `3 v7 h' J                mmc5.LoadState( p );/ N8 o$ d5 J7 J* m* Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ ?4 b  {) @# D/ o; ^" A0 D9 x        }
5 T1 P8 I+ R) R        // N106
5 [4 ~2 M- h8 V2 B2 E        if( exsound_select & 0x10 ) {
; ?1 ]" ?. T& v3 N' z. O$ G1 H                n106.LoadState( p );
% x9 J! D- a/ p  `! Y7 w                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 g3 ?8 }- Z; B/ [0 d
        }
+ \  S0 o& L. t8 D$ m        // FME7
$ F$ g9 R: W2 u: Q' q" X+ U        if( exsound_select & 0x20 ) {; w; M% A- a. Y5 H
                fme7.LoadState( p );7 W: {- n( L# u/ ?: J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# c! p5 Y& ^* N& E0 {        }
" C& N2 {2 A# Y- d4 u" l) ?}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 Q7 V% X% s# @9 b; {2 |5 \: x
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ h# n" R6 K: f0 W
感激不尽~~

8 U. {8 e3 I, `1 r2 y5 {恩 我對模擬器不是很有研究,& n$ D4 M$ U& c$ d# e
雖然要了解源碼內容,可能不是很困難,( ^/ A( k9 C0 T+ f% b1 f
不過還是要花時間,個人目前蠻忙碌的。
, [* {) v; ?  R! f
% l, N: D& Z( @* y7 Q給你一個朋友的MSN,你可以跟他討論看看,% u3 P8 ^3 D& d3 {8 r% W3 [2 k
他本身是程式設計師,也對FC模擬器很有興趣。) u  ^! L: I/ d* [2 M5 a* J
* }" @$ N! C9 {
MSN我就PM到你的信箱了。
0 x" t" t7 B  a
5 U4 J  n  D, e+ ?; n' B, o# X希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
6 Z! F2 J# M( s- S呵…… 谢过团长大人~~

. Q" g2 O( H: H' Z% @, E& V& \4 f
  `- S: P, W4 @- k; _哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
5 m% B; I; t8 @" J2 d# h. F团长的朋友都是神,那团长就是神的boss。
- a8 B( S! \$ f. y$ @/ D0 ]  O
哈 不敢當,我只是個平凡人,3 D# w7 {) f) y  I! l
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ b; L" C, K: b0 {: s
ZYH
/ ]% k* H2 P  z+ ~2 D1 a$ yQQ:414734306
" I8 ?1 h- Y1 e# q. AMail:zyh-01@126.com) c" o& B  T0 I! X" O

% G/ o& `& U/ w4 Z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 4 ^% a7 s( _/ [) x9 Y+ a! V9 }
再次对团长大人和悠悠哥的无私帮助表示感谢~~
/ L. j! J( j6 y) k: e3 b. T
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-2 10:10 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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