EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?5 g. c/ y. M4 i, L( p, h) r
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) N  Z8 y! Y# Q* T. j楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. _& d9 C; |( H+ [- \) w! G这里有相应的模拟器源码,就当送给大侠了~~
9 g  C: L9 F5 Y, C; s$ r; F5 Bhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
' W  U' @, d5 o" U能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 K* y' \, \: S. p, J+ ~* X楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. f4 @; T9 o. }. n2 P, P  P" M/ E这里有相应的模拟器源码,就当送给大侠 ...
# ^+ Y; |5 l$ x% n+ y, A
聲音部分(Audoi Process Unit = APU):4 ~0 g* Y1 @: h$ S9 v+ W- K
.\NES\APU.cpp6 w# \/ o7 [: G
.\NES\APU.h, x7 E( q$ D; C& Z

- J& t0 g" z( b8 h
* `- Z2 ~1 v1 J, r# J; W影像處理部份(Picture Processing Unit = PPU):+ b# e3 H/ R" Y; ]* ^( r
.\NES\PPU.cpp) X: U9 j/ H/ q
.\NES\PPU.h
4 b: L5 q: W/ v* h; E  [% c; g/ \+ r# O8 W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 J: J/ t) K; c( f/ z+ d(由于很多专用术语和算法机理都不明白,所以看不大懂……)
3 t' ~1 g" E& I. g6 h//////////////////////////////////////////////////////////////////////////2 \* M+ s: u( g& k. {6 h
//                                                                      //
+ E2 v/ B/ M# ?//      NES APU core                                                    //" l! f1 k' H5 J' @
//                                                           Norix      //2 E# l/ i0 }# Z
//                                               written     2002/06/27 //7 Q! z' t5 p- z* m
//                                               last modify ----/--/-- //* F1 R7 i6 W  n& d  y4 r/ E) C- E
//////////////////////////////////////////////////////////////////////////
  x9 s8 w. Q( Q4 N( D) Q#include "DebugOut.h"3 M* A$ d+ c. s
#include "App.h"
; a$ ?' b, j: I  [  k* j$ g#include "Config.h"/ M- U" j. o1 h1 d# ]

% f. g/ z7 H7 W* f8 v#include "nes.h"
% F6 d6 Y* \% n* b, P4 S3 s#include "mmu.h"7 S  r5 Y. y7 L! N
#include "cpu.h"
  m/ s, A) Q1 a. {, p1 A2 b#include "ppu.h"/ W. D, z0 X' `/ E" F
#include "rom.h"- o" e6 s) }# B1 ?4 l% u  d0 U3 p& s
#include "apu.h"
+ N. D* z  L' ^- N. ~  G; k) I0 Q
5 p( y0 y! n6 o// Volume adjust
% d: v  v' [9 F// Internal sounds+ i. O/ ~/ }& \) A
#define        RECTANGLE_VOL        (0x0F0)
$ t/ @+ V4 H" p+ k% i#define        TRIANGLE_VOL        (0x130)
# ?% P, `5 m) W( u#define        NOISE_VOL        (0x0C0)* h4 d0 ~6 v  A: U
#define        DPCM_VOL        (0x0F0)# [: H9 V4 F9 t. R
// Extra sounds: G( z* L; [/ T: c- c" v: B
#define        VRC6_VOL        (0x0F0)4 v2 p/ g  K# h9 \" `& L
#define        VRC7_VOL        (0x130)/ y! p6 \- N& M# n, Y0 u+ N& o
#define        FDS_VOL                (0x0F0)! V/ L9 E; L; D+ s& C
#define        MMC5_VOL        (0x0F0)
& ]4 S( J% l% P4 S/ ^# b5 R#define        N106_VOL        (0x088)
- R1 M' x' Q0 W" \+ x7 x/ z! U#define        FME7_VOL        (0x130)8 E; y8 q" I3 c7 y* Y
6 h( c, x  C+ @& {$ y0 t8 q
APU::APU( NES* parent )4 _. n; B, h; T5 {3 q: V
{
) w0 l9 N. F* e; \        exsound_select = 0;
* s  G( [: Z- g$ j' g  t9 n! J' D' F
        nes = parent;
# [  k( \1 D- T8 F  f4 L) o5 a8 ]        internal.SetParent( parent );! p. W6 z( J, J

4 R* M- a7 \: H" v, p        last_data = last_diff = 0;) @' t4 D" q1 i# E9 ~$ K7 Z* M! o
9 H& G  @. Z7 L* I. Y$ k
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );; T* u' x4 x' k7 t# G# n/ C

( v% u. z( F% u. V3 A% @1 F        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );& L  v( d; y( W* F5 q4 F/ Z" F9 j! y* d
        ZEROMEMORY( &queue, sizeof(queue) );
, X  }: ]' @# \5 }" q% n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ `- n: D% `  r0 w  D- d5 v/ Q9 \" @" z6 Q# h6 c- ^
        for( INT i = 0; i < 16; i++ ) {& L* `7 l0 y/ B- U& r0 V) x4 E) [) Z
                m_bMute = TRUE;
9 O* H+ l, O  e7 o2 k! }1 |, n9 Q        }+ ^! @/ }( `' y7 ~, Q6 Z( H; j
}
6 U% q+ }. c4 k6 n' Q3 a7 G0 K( r2 J' t) X9 y4 b9 U) U; b* t
APU::~APU()
$ j( S' ^* C9 H9 T# l{
" w! K5 }2 ]5 [' U' n}
/ x5 S# Q' i' k9 Q0 F! t9 G0 V
0 s$ S1 E/ O( ?8 V0 W$ bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& N+ Q7 M0 W0 R( T* f
{
- x4 j2 `# c: \        queue.data[queue.wrptr].time = writetime;
' W, Y1 T1 a* r" p% ~' `8 c        queue.data[queue.wrptr].addr = addr;7 b5 k+ z9 F" z) {1 b, f( w1 K) X
        queue.data[queue.wrptr].data = data;; }  K3 v4 O6 M
        queue.wrptr++;' Y( Y+ R( k, L/ s! I; v
        queue.wrptr&=QUEUE_LENGTH-1;! t: p0 a* `. F7 E+ Z
        if( queue.wrptr == queue.rdptr ) {
6 n! `* Y1 F2 C+ y% C, O                DEBUGOUT( "queue overflow.\n" );
! ^/ r! m( N, {        }
  W; D3 |: g) A- K2 W, m) m1 A}
: d" _9 t- B! r( l& W1 v+ p, s3 a5 `& h: |
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. h, s  w8 |! U0 c9 H, ]: C' f{9 O8 A  d( K# a( r4 i4 Z  X
        if( queue.wrptr == queue.rdptr ) {' J+ q5 x8 K9 y7 @2 b
                return        FALSE;
& K1 I$ j. ^6 q; N* n) T; w7 _! J        }
$ ?$ b' C. H4 D        if( queue.data[queue.rdptr].time <= writetime ) {; ]2 @4 ?/ W, k+ |# l% B7 b
                ret = queue.data[queue.rdptr];" D  z5 }5 w% V9 a' e3 I# K6 \
                queue.rdptr++;
: @+ l; a8 U* M                queue.rdptr&=QUEUE_LENGTH-1;
& t' z6 z1 ~, I7 G                return        TRUE;4 }/ z, k2 m: q5 |/ M! K- n
        }
# |( ]# C/ s- i3 Y5 o+ L3 n( x1 D        return        FALSE;
! I2 o% e+ c6 t6 e2 ~( \}% o. m5 q- c& f* V6 `

9 A# p% C- D0 `. H, V; Xvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
1 j* P1 p- F; F$ L/ F$ W{
2 `! N1 u, u; u; A. V1 D        exqueue.data[exqueue.wrptr].time = writetime;
: F- N7 H1 O/ Z' T! y; c0 Z7 F3 K        exqueue.data[exqueue.wrptr].addr = addr;% f) J1 h; c3 ~
        exqueue.data[exqueue.wrptr].data = data;
8 M: n" C; c# b        exqueue.wrptr++;9 K7 f$ J4 t& G/ Q: X+ H
        exqueue.wrptr&=QUEUE_LENGTH-1;
# i7 D& l* N1 @' i3 ~* G5 }' U' v        if( exqueue.wrptr == exqueue.rdptr ) {
5 Q' I9 _) R& I8 e9 _) w: C/ \* Y                DEBUGOUT( "exqueue overflow.\n" );' C, U! b7 }7 F" b8 U
        }
2 G. w8 C2 D+ O5 g/ Z}
, k3 b: K' f0 }3 `6 c( h0 H3 q; l3 m9 }' u8 a# W9 ^; W3 T
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )4 U) o% i  T1 w6 }& O: p
{5 ~. `4 s. d( L1 g8 F
        if( exqueue.wrptr == exqueue.rdptr ) {
* `" E9 d7 \6 w0 D: E9 Y! G% o                return        FALSE;
: N) O, ?* F! i7 G        }
7 C: D; j6 }' e9 k) H2 x        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
# f" D) E) E$ E' K* V5 x                ret = exqueue.data[exqueue.rdptr];
5 \& o* p! u5 Z8 D. L  F4 ?0 C6 U' a                exqueue.rdptr++;! j3 b: X) j% d% ]
                exqueue.rdptr&=QUEUE_LENGTH-1;
. i$ C& l* p- L9 J: W                return        TRUE;
5 m* k( g3 W+ m6 F        }
. r( u! @# B6 O, a- g- ^/ G+ V        return        FALSE;
/ w; k8 k. a2 X! e, X}( g: P* c% V% s  Y# t6 U

+ M0 i# N) x. S" _2 ]0 uvoid        APU::QueueClear()
9 _! m9 O1 _9 y8 z4 C. S{' {7 U& A0 R6 B# s3 X$ z
        ZEROMEMORY( &queue, sizeof(queue) );
' N  v- ~# o7 H        ZEROMEMORY( &exqueue, sizeof(exqueue) );) M3 I- C( p% r9 Y1 L
}
( r  i6 A, ~1 ?8 N) j1 A% ?, f' v, T8 \6 U: w* k% m
void        APU::QueueFlush()% T+ k" `# V  K% s- x+ l7 m7 `
{
) j! y( J3 S* H" h" E2 h        while( queue.wrptr != queue.rdptr ) {; f3 s. @5 e$ m& G3 H6 r$ q
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );! e, r8 z5 ~* j
                queue.rdptr++;
' x2 ]& b# e3 G; m& ]/ D0 b. l9 ]0 f                queue.rdptr&=QUEUE_LENGTH-1;
' ^/ X( H( g5 g8 `        }* I! e2 P! P( e) L- b2 ]
' F4 D9 V7 @( S( x% S0 E0 E# @
        while( exqueue.wrptr != exqueue.rdptr ) {
5 ~" j- n8 m/ |7 e# m                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ Z. D1 i  F  k# J+ U0 q+ S                exqueue.rdptr++;4 G* Z8 {/ c! Z4 B" [
                exqueue.rdptr&=QUEUE_LENGTH-1;
2 @( S4 F( b+ h1 a5 V/ ^0 L        }
( |" A! v4 W$ E5 S( B/ D}
2 v4 _  v2 b' W  _7 v5 [; r! |
" Y8 |5 q3 `5 ivoid        APU::SoundSetup()
; j2 c, }/ G2 N! \% {; A{5 y+ C; @. v, j# n
        FLOAT        fClock = nes->nescfg->CpuClock;
5 f  a3 \( P* A' b% w8 v* x" E( }        INT        nRate = (INT)Config.sound.nRate;  T: ]6 e8 G# E4 \1 Y  Z' K/ v
        internal.Setup( fClock, nRate );
8 i: U5 A+ V) {0 ^$ @2 {1 {        vrc6.Setup( fClock, nRate );
* ~3 q! s5 V4 D$ L' d1 v6 W+ Y        vrc7.Setup( fClock, nRate );
- J: p9 M! V! ^) j8 W# {* z: U+ ?        mmc5.Setup( fClock, nRate );0 X  A& q2 p4 a8 ]9 L) w
        fds.Setup ( fClock, nRate );' M! x5 k) v" _" o& `: V6 B3 N
        n106.Setup( fClock, nRate );
; E$ @% D  Q  t# |4 d. F        fme7.Setup( fClock, nRate );6 T  H' \/ d1 J
}
; i  ]3 I2 l  \% {% u' g
2 N( j; \* p- t4 Z" P2 \( R/ t3 N6 D! pvoid        APU::Reset()5 T. I$ Z: c. I% g" \) _# f; W3 g3 x
{
  q( R  R+ d/ P2 V        ZEROMEMORY( &queue, sizeof(queue) );0 @3 R  U$ }2 C, N3 a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ H* T; V- Y/ K0 f2 j# y! p; x5 i

) _) {- n+ p5 s        elapsed_time = 0;! l. Z: r0 {' x* S" L& Z$ h

% J4 U7 O2 k& j5 F+ A$ z        FLOAT        fClock = nes->nescfg->CpuClock;
4 X; e% |$ i* T4 U1 F' O7 K$ |! P. u        INT        nRate = (INT)Config.sound.nRate;
, U$ z6 U! k: B# _2 a* d- T        internal.Reset( fClock, nRate );
9 K7 M. w$ u: P0 i0 e        vrc6.Reset( fClock, nRate );8 v8 E, I' W# R  q" S
        vrc7.Reset( fClock, nRate );8 |4 f4 E( J" K# g5 S6 K1 o" v
        mmc5.Reset( fClock, nRate );: F: M+ g3 Q' j" r! G
        fds.Reset ( fClock, nRate );
, |2 I7 O( G6 {% r. X7 u( i1 |        n106.Reset( fClock, nRate );) {5 l* C& F- ^, Y% G6 _8 m
        fme7.Reset( fClock, nRate );* M8 G+ S+ w/ E: A' C: v

' u1 W' J" e; L; n5 \1 R$ J        SoundSetup();
# H5 F/ c# r- G" a1 y$ d. e}
) T. @2 O, K6 m; k: c
+ M- \" k7 B" H8 N( Ivoid        APU::SelectExSound( BYTE data ); H1 o7 D% z/ r& n. }' h. F$ [# e
{8 D! Z- k, o9 R7 b, I7 [7 ]& \8 @
        exsound_select = data;; u) Q& R& [; @0 e% ^  m/ m
}
9 @; k2 q0 b9 Y* s
5 X# z4 A- ~; Z; c) a4 S6 p' uBYTE        APU::Read( WORD addr )
& Y0 f5 R" i7 F1 m) P{' s3 @# f9 V, R# C- A! V, Q8 g2 B0 e
        return        internal.SyncRead( addr );0 y* O: u1 n6 e" [) O/ G; D
}, U7 C% U6 F( T1 t+ M' U/ ~

) l5 r6 a) N: h! g" p9 o0 kvoid        APU::Write( WORD addr, BYTE data )2 b5 E& L. U' V  j, y
{3 f4 s, y/ @4 ~* j9 i6 t) {1 Q0 e
        // $4018偼VirtuaNES屌桳億乕僩
" D0 O' M5 w7 L. g4 O9 ~        if( addr >= 0x4000 && addr <= 0x401F ) {
. L/ `7 R/ m. v) }; D, n                internal.SyncWrite( addr, data );
) c9 @6 h6 x9 m) c8 h3 Z2 c                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- v- p! T% l% d$ F/ s# A- T9 E
        }
4 }/ C  j3 Q) t- V}& G0 k' x: I. Z2 P& f  K/ _

' M3 R4 [$ U) P5 e: i+ yBYTE        APU::ExRead( WORD addr )
) b. x4 c# D+ J1 ?1 B{
/ k. w3 z0 i* j# a2 gBYTE        data = 0;
6 p6 O# U  G- q8 R1 l% F( ?- X7 q: d+ L: G# \( b' s
        if( exsound_select & 0x10 ) {3 G1 U0 F6 I/ Y/ k6 _5 j/ V
                if( addr == 0x4800 ) {1 F7 d! O0 d! D1 Y" M/ r8 G( ^% \
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
& p3 Y3 p- g& g6 E& A                }
* _: |1 M  ]: [* u        }
/ j, y: S5 j1 T! e        if( exsound_select & 0x04 ) {8 f" }' I. |+ Y& G% S- S. l
                if( addr >= 0x4040 && addr < 0x4100 ) {
) A# u. m# d2 V3 ]6 B: w                        data = fds.SyncRead( addr );
5 B2 v8 y4 F; K                }
$ f' ]7 s% `8 U  m        }
9 b- l& u/ j# _! P: |: d$ }        if( exsound_select & 0x08 ) {
8 ]+ s& i9 |7 o2 l  {# ?- Q' v& ~: z, s                if( addr >= 0x5000 && addr <= 0x5015 ) {. _4 V! m. Q- v$ P* v( Z
                        data = mmc5.SyncRead( addr );. l) @/ }; j2 d6 c# G) J- h
                }
. H: ]/ y9 @/ l        }
3 y; F6 F# f. A: {& h7 L2 H1 e' h$ U/ L0 O
        return        data;
2 q% x' V% @! a* K* _; E# n( u* j3 [}
, w4 }8 ?6 z+ R% K6 S3 d( m6 f' \: |# C
void        APU::ExWrite( WORD addr, BYTE data )
8 h( Z4 ^0 g' _& T2 |9 A* n{
: S( K& B  _$ {( r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );; m! W6 i: u" m, Y7 m8 s

+ z7 D9 y- l9 s        if( exsound_select & 0x04 ) {/ q8 m9 ?6 a$ v4 l
                if( addr >= 0x4040 && addr < 0x4100 ) {8 i- O! G3 C! z2 @$ i. x
                        fds.SyncWrite( addr, data );4 \/ P& _: g7 W3 F0 K: l  v+ O& }
                }
3 }6 ?8 |! N1 l. Y        }" \, X/ I" E* Q
$ [" O- a; ?8 o+ W+ R
        if( exsound_select & 0x08 ) {; Z9 d7 G0 B/ ~3 v7 j6 {7 `# E
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 z% _3 V! h6 S$ Q/ q. H* n- O                        mmc5.SyncWrite( addr, data );% [7 ]1 P( }" F$ d
                }
- G: z* F, u- r1 r- W        }) o: E; |, X0 O9 X; `  F( R, E
}7 F* F# O# m* _2 {3 S$ ?7 T

) ?% C9 ]. T, J! Y& N- i* {void        APU::Sync()' B+ G+ M$ e& T& z1 y
{
+ h8 S! O: q: K  x# l# Z" x. [}
! v( [. [7 S* E% n9 A) \6 @6 C- q6 N6 C
void        APU::SyncDPCM( INT cycles )" @) r9 b/ q& J  G; @! v8 a  g- L" o
{8 R2 y/ K: D8 s/ m
        internal.Sync( cycles );& w+ y" u- J0 n; w& j2 D9 U5 R
( D4 B1 U: H6 {1 `9 f" C0 h
        if( exsound_select & 0x04 ) {  \  @5 t* q$ e
                fds.Sync( cycles );& b: g' J, g  }" L; }
        }5 Q: ?+ D8 h% t2 t5 y* ^$ B0 ~4 [
        if( exsound_select & 0x08 ) {
$ j  s; W% n' J! J0 t4 H) ?! R& r4 v                mmc5.Sync( cycles );4 A! M& r, x) v: h
        }
- f" s3 K8 }' \. Y, X}0 |& c3 B. d( L' r3 g

: f2 K7 d8 ~9 N6 Z9 g3 Jvoid        APU::WriteProcess( WORD addr, BYTE data ), f5 Q0 `; e  Y
{' O4 h6 q( v- @- o  x5 w& N
        // $4018偼VirtuaNES屌桳億乕僩
7 s+ U& ^  m+ j1 r        if( addr >= 0x4000 && addr <= 0x401F ) {& ~/ w# b; C1 _: J( @  c
                internal.Write( addr, data );: N7 X; W8 E/ o
        }
# r* P" E/ k' V3 T5 K- w}
1 ?, \2 R, q; ^) b% A- T9 c, _$ o4 A/ _$ h
void        APU::WriteExProcess( WORD addr, BYTE data )! q, ?! ]9 m7 b$ ~7 `6 {  A- t( `. W
{6 \0 c; Q9 {+ W, N4 ?! Q0 D
        if( exsound_select & 0x01 ) {8 y1 O5 \! o2 {
                vrc6.Write( addr, data );
5 I0 A7 D8 ]6 Z- h1 f; \        }4 N( B3 \4 w2 H5 D. Y$ [( M& T
        if( exsound_select & 0x02 ) {) c  z- e/ K" {* z% ]6 f
                vrc7.Write( addr, data );+ t3 ?$ M2 c7 z
        }
% {6 b+ n  k; ~2 p7 G6 Y        if( exsound_select & 0x04 ) {* `& H5 l' e0 U" ?6 l, t: \1 h1 o
                fds.Write( addr, data );
2 U& P0 Q. {* Q6 @/ _' a        }4 g3 a3 \: c4 x) M
        if( exsound_select & 0x08 ) {
. D. i: C% r3 e4 b, X; m                mmc5.Write( addr, data );
" S% `' O) |, F. ~8 |# y' E        }+ a: o- N" D+ D+ V. L5 s2 E8 F9 u  H
        if( exsound_select & 0x10 ) {
3 c* w( w- J% {* H- l" V                if( addr == 0x0000 ) {% h; u( w- ~; j& x
                        BYTE        dummy = n106.Read( addr );4 d* ~( V& B; _; A! R% `
                } else {
' A5 w' P, z4 e! K1 [1 q                        n106.Write( addr, data );, `' J& N: o- t) h( |3 j! ~
                }, U1 Q2 n. r$ k- I! R% }8 S6 I
        }
3 m9 h( ]5 Q: `  |        if( exsound_select & 0x20 ) {
1 w# u! d9 H% a/ E                fme7.Write( addr, data );
9 B( o, @  y. f( M1 C7 T7 E        }$ X# Y  _! b6 i+ m' q
}# |6 X* V% s* y$ ~8 N6 y) Z# {
, ~% d1 L$ c+ S5 F
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
( H% Z+ j# b& M, ~7 c% o+ j3 I{
% d+ I0 b  \% A8 G2 u' o, rINT        nBits = Config.sound.nBits;
' l; D& S3 j6 _5 K6 ?DWORD        dwLength = dwSize / (nBits/8);3 c6 S4 t/ ?7 s5 N* A: ~
INT        output;
% |7 N/ ?% `' i* \7 \* kQUEUEDATA q;
1 X/ B! z& \, I0 `DWORD        writetime;- a+ p* z# Z/ F
( D6 M! U" J! X' J1 g
LPSHORT        pSoundBuf = m_SoundBuffer;# T6 r! m2 s7 ^1 T0 [5 A- t
INT        nCcount = 0;
% U/ G& v8 S5 \# X/ q$ c; X" I* k9 d3 t( A
INT        nFilterType = Config.sound.nFilterType;
1 L/ j2 |9 e) ?1 w
" W# l! }. f+ a. o; C" g6 l        if( !Config.sound.bEnable ) {9 Z& A, d/ z, t, @  P
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; G8 W+ n' S- h# \$ L; L! u( ~4 C% k
                return;# y1 N# |( j% o8 X
        }
5 M) k& e& o3 R9 ~" f) k9 u
( Y; f8 d1 e: K1 I0 r! @' }1 F% [        // Volume setup
/ B( i, a% h" c2 {0 u5 Y        //  0:Master! h, z# l( j5 |0 D) }
        //  1:Rectangle 1
4 \2 n! n3 _  y1 w0 `        //  2:Rectangle 2
" s, k4 M! m0 _. D6 z" B* g% r* G        //  3:Triangle1 s8 M5 Q) V' W0 ~
        //  4:Noise
- t+ l- f9 F- D# b. v        //  5:DPCM
1 a5 p; {- J, S  b  P        //  6:VRC6# {; j: J0 r& f5 P8 O' `' l
        //  7:VRC7
4 o3 C. s  g0 `2 |4 W& j+ I! ~        //  8:FDS
: v! W3 }9 P: C  K0 h/ ?* U9 V8 ?+ J        //  9:MMC5# L/ s( j& p# e& n& Y
        // 10:N106) v" m% `( P7 p* o$ o- r! m
        // 11:FME7
2 l. R- l6 Q4 z4 t9 w8 R7 R2 X& l        INT        vol[24];
1 L( v& a" ]# Z  T) _9 C9 ^. x        BOOL*        bMute = m_bMute;8 n' b% K& Y3 I+ _" B7 |- ~+ ?
        SHORT*        nVolume = Config.sound.nVolume;! }5 T/ B2 d9 R- H3 E! B

9 G' \% o5 R# [! z* _* {        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
: _  O; u/ `8 N5 k0 h1 `1 j) ~+ K8 x, u
        // Internal, _+ K! z/ |0 H3 N+ v3 s2 ?- @
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;6 S1 ?- |/ o& D* `* N! Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# R  C+ e; ]4 l4 J7 t        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;, ~0 V0 |: j( K$ U  _3 ?
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
( ?" z; Q, h' d: n7 ~6 v3 L0 ]  q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
+ C% o( |6 j6 b( w
7 S" e5 S. x# N1 F: t$ p% p0 v        // VRC6
8 C: T7 O' ]$ v- z( G8 y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 k  C# M5 e0 O' s' e2 Q( d
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 Z% m+ B# q9 l! j: h0 |9 u: H
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 n6 Y# s. a+ V  g. a8 D% M6 O

% X0 N4 s1 B; _; I; E4 [$ I3 F        // VRC7( K# C8 P; M( v% \' e$ N' s
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
1 R+ P: \3 X4 j  N+ t- e- N" Q) q9 g
        // FDS& O  x1 M: \. K4 q* I4 h' U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 x3 c" v  J8 E) s( y
" D9 P9 C  R- Y+ ]) c: ?        // MMC5! M4 R% }; c2 I+ Z7 e
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* Z1 X- A4 `' R. m        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% |+ S% l& n7 Y6 F6 F7 y2 f        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; Y, E! D4 v$ D& F) C8 T

, K, s* U" w8 Q: F$ Y  \        // N106* O8 @) T# M, ^+ M
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 h$ G# E' c, h" c        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# X; u* r& _( h5 x" U1 v  m+ Z7 f1 X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 W6 v( u1 F1 T: M        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 L" U' d& P8 r5 z        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( F+ y2 W7 A' h/ {1 X8 y3 J7 l8 q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% i6 ~9 Y- T. n5 A- d3 e. M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 F% x7 H+ p# P9 l' T5 n3 r        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! F: n3 l. Q( D: n& }* H4 D
& L7 k4 b, r1 b% p% Z. Q
        // FME7
. ~) I6 s2 Y0 J6 }1 `4 y$ a        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! [, S  b. C& u  S7 a" ]" a        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  q( f! n9 o5 n& o' N
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. Y. z/ f& Y/ v

2 S: j+ F, f* ?" ]//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
6 S# |; E0 G$ C        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;, K& }/ M) n6 I5 g6 s: V
' F$ }" D- t, _$ j) j$ b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟% T5 }! @, t6 f  o* i& w+ f' l! {
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {; t3 j# }2 M" c! L
                QueueFlush();
( P; _1 q" z1 v2 U# E        }
) l+ u: @3 J3 f0 i1 A/ [
! T: @0 r( K. e) s1 W0 g) z        while( dwLength-- ) {; h; L, W7 y6 O8 i7 w4 A5 d6 a
                writetime = (DWORD)elapsed_time;
  L3 {, U" Q: `: B5 z
: x' i" z# j9 Z0 \- e                while( GetQueue( writetime, q ) ) {
% {  S5 v2 M0 \& F6 T! |8 J                        WriteProcess( q.addr, q.data );/ p% H5 D: T8 O1 B
                }
0 U# u& R6 y/ |2 w) C6 c
8 H/ j+ W3 C6 }( H" j, R. z                while( GetExQueue( writetime, q ) ) {* H5 ]  i/ s" D0 `6 n: y* Y  ~( k
                        WriteExProcess( q.addr, q.data );
* J0 l' z( V  i' G- Q; |6 h) E2 C                }
- |1 h/ t9 t- p8 v1 b+ e% S1 T9 |  }) {7 `* e8 C1 d9 T
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
: L/ Z0 d, T% [( \) U- T                output = 0;
9 a- |( n2 t1 M6 @* L                output += internal.Process( 0 )*vol[0];8 {7 v. |* r) C
                output += internal.Process( 1 )*vol[1];
3 S  [% l5 K6 x. }, \' G                output += internal.Process( 2 )*vol[2];
. _, @8 B) _8 z* c3 d9 q$ M                output += internal.Process( 3 )*vol[3];% [" W2 q3 g, N  V. v5 O2 F6 \( ^
                output += internal.Process( 4 )*vol[4];1 J. M% \! J" _; \
# g! c% [# s; k% i9 c
                if( exsound_select & 0x01 ) {
* _% z3 T* _5 V  ]5 W5 l7 F                        output += vrc6.Process( 0 )*vol[5];
5 l# B" D0 D: U; i# X: u                        output += vrc6.Process( 1 )*vol[6];' \3 Q8 Z0 B8 b: E" j
                        output += vrc6.Process( 2 )*vol[7];5 R( l' f$ W$ p  c
                }
: V9 Z9 m9 p, ]6 R                if( exsound_select & 0x02 ) {! m6 F' e7 d5 H1 V) V
                        output += vrc7.Process( 0 )*vol[8];' X/ x6 Y" D' N, B
                }. Q/ w( R! G" k+ q! p* E
                if( exsound_select & 0x04 ) {$ b# d) B: V4 P4 T5 o1 s
                        output += fds.Process( 0 )*vol[9];
1 Y# }6 u# W3 ~/ @* z1 ^- O                }& o6 I+ D9 ]: x$ s& g- ~
                if( exsound_select & 0x08 ) {
! x% Z  S0 q: M$ z2 D# C                        output += mmc5.Process( 0 )*vol[10];1 W( c( e9 B1 d5 P+ Q
                        output += mmc5.Process( 1 )*vol[11];
+ J6 b: Q# a; Z' g9 z2 T                        output += mmc5.Process( 2 )*vol[12];  r6 S/ j! Y/ _# R
                }
6 G; Z6 H  f# K8 v; r' G                if( exsound_select & 0x10 ) {
' ]! o+ L* F+ r) e. z$ Y1 O                        output += n106.Process( 0 )*vol[13];& p7 n! A0 q; \5 h7 m! e
                        output += n106.Process( 1 )*vol[14];& i8 e4 x) N: _/ o4 K
                        output += n106.Process( 2 )*vol[15];& A3 l( g' i  l1 s5 j5 g
                        output += n106.Process( 3 )*vol[16];
& U5 K) r2 [9 d8 v; I8 [7 E                        output += n106.Process( 4 )*vol[17];
& R, B7 |* ~4 X+ \                        output += n106.Process( 5 )*vol[18];
- E  W$ t% ?/ _7 K4 g                        output += n106.Process( 6 )*vol[19];' ^0 _) ^/ K4 c/ q% i/ {
                        output += n106.Process( 7 )*vol[20];* C7 @7 b: q# N. F$ |: N
                }
( `- C9 b6 i& b; ]                if( exsound_select & 0x20 ) {
9 ^9 a! _8 b1 h4 L3 i                        fme7.Process( 3 );        // Envelope & Noise
5 J9 W0 I* b6 u0 D( K) I  k; ?7 {0 ]                        output += fme7.Process( 0 )*vol[21];
& V! D# P3 r9 g. h  a. |2 v. Q                        output += fme7.Process( 1 )*vol[22];
, D# h5 D: o2 F. D0 `7 ]* a                        output += fme7.Process( 2 )*vol[23];. g+ b. g2 |1 t. K9 I$ R
                }0 ^7 ~' m, x9 i; D# d
9 D- y# ]6 }" Q$ R5 X" B* s0 ~0 _
                output >>= 8;
. u2 g1 ?* j4 ~  |1 g" @* D- t! l( B  `2 e2 w
                if( nFilterType == 1 ) {& t# X, L5 n; l4 \, s9 @0 {" t. z7 b
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  Y8 k/ m0 }# R6 R& h4 D
                        output = (lowpass_filter[0]+output)/2;
% T  T4 d; |- h0 U/ J$ Y8 W9 V                        lowpass_filter[0] = output;
1 Z% r3 F, z1 @7 d4 k  W0 u                } else if( nFilterType == 2 ) {. n3 D; {6 b6 Z8 k2 b9 K( p. O
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
' q3 e% V9 A8 @& Y9 G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;/ u- {* z0 O6 G2 h
                        lowpass_filter[1] = lowpass_filter[0];& R" z( `# O+ M+ d5 w) |! B" R* I
                        lowpass_filter[0] = output;
8 k/ P% t$ V' C% i                } else if( nFilterType == 3 ) {
+ M& W& y: J! `5 e6 f$ X5 Y                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)# M' N5 D1 X* N. F3 c2 X
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;4 }# @$ j7 u) M+ [8 e8 U  l
                        lowpass_filter[2] = lowpass_filter[1];% r( f; f0 i* X/ ~0 A
                        lowpass_filter[1] = lowpass_filter[0];
( R8 T1 o3 b$ g" ^  a8 y                        lowpass_filter[0] = output;4 a3 a) l$ i, [& Q8 h6 q
                } else if( nFilterType == 4 ) {- ]1 [" i5 f9 L, [" B) V
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), b9 C# K5 Y1 p+ K2 R
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;5 G& q  o+ v' w
                        lowpass_filter[1] = lowpass_filter[0];6 f5 M  v7 \8 U
                        lowpass_filter[0] = output;) _; z% u4 E1 @/ S1 y) A& @
                }
+ B" Y: U  w% U7 r
/ m3 h  W; C/ k: b3 I#if        0
# A# h$ {2 U; b/ w8 x# z                // DC惉暘偺僇僢僩' ~9 [5 F3 P! `" p3 e( f' K/ z: |
                {
2 ?) d, F; N, Y6 P6 O) B2 t$ Z. |                static double ave = 0.0, max=0.0, min=0.0;
! a0 V8 }9 g4 K# U                double delta;
, N% p6 ^9 F  g- s$ W7 g                delta = (max-min)/32768.0;
0 i3 E& O7 r$ P" @" I) y7 I                max -= delta;$ G. l  m! Q2 B' s' p) c" k3 Z' V
                min += delta;
' v- s( R3 Z6 d1 X( G1 p                if( output > max ) max = output;% i8 _! M' V9 `: |) M& r1 H
                if( output < min ) min = output;
9 I' O' E. v* y& d5 q3 K! k                ave -= ave/1024.0;
# G. S) U# D2 b3 Z                ave += (max+min)/2048.0;& _1 _- p( ~: q" w* }
                output -= (INT)ave;
# m. ?- n/ z0 a8 [% O% a                }
) L4 c$ R/ l# e5 w#endif
0 W# z- x1 h# f2 H#if        1
0 z0 R* G2 I/ G& m' U6 v                // DC惉暘偺僇僢僩(HPF TEST)& [4 v1 `- K; q/ F  S
                {2 p3 o0 N2 U0 ]  h4 h2 F
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
9 g! [5 v/ I: F3 m                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 e# \7 _  \+ O) W' X' o                double        cutoff = cutofftemp/(double)Config.sound.nRate;  |* v, u+ t# ~0 g
                static        double        tmp = 0.0;
: ^# j& N% N/ \1 l" p  b, X                double        in, out;
4 A3 g( C7 N* b/ z+ D* F: x' \' U9 |6 t6 R. v5 O( D0 y4 J6 |4 y8 n
                in = (double)output;4 i6 L4 R3 |+ N0 H0 n
                out = (in - tmp);+ L# G' K9 q! V& R$ f
                tmp = tmp + cutoff * out;
" V3 r) [: l( `1 u+ u, G$ l1 m/ R! `& ]" C
                output = (INT)out;
+ }# p; l- B; Y                }; Z$ b/ @7 @; t% d6 r' H: H
#endif
5 D/ y3 @6 n. s#if        0
5 z: ^* D0 e! x0 W                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
- H: D; m$ r; [                {
& b+ n* L+ a1 q/ T; J                INT        diff = abs(output-last_data);- W0 J% `8 N5 L* u8 J, l$ A, v+ Z
                if( diff > 0x4000 ) {0 o4 n4 W' P' }9 F5 r& V
                        output /= 4;. [9 r  w3 H- {4 f9 k
                } else
/ u3 T9 K) F3 Q5 y; P                if( diff > 0x3000 ) {3 Q3 J6 t! J& H/ o! [5 g# Z
                        output /= 3;
6 b& w# z. h0 w. _2 U3 g3 H+ f                } else
/ C/ [, t! h' s                if( diff > 0x2000 ) {
' R( K2 @8 q* v- f" `                        output /= 2;7 N. V( P: a* m4 q1 g; u: @
                }# F# V( L( z" n' X1 c) H0 M, v
                last_data = output;
* I& \1 q: h, k4 h4 d: H; b                }
5 e9 a+ U1 H! B3 x9 e  h( R#endif* T4 P$ v+ U! F' N- `, s
                // Limit
( M7 M( l7 \& ^8 Y                if( output > 0x7FFF ) {5 T. ^# v( Z4 q- y
                        output = 0x7FFF;
! M1 c. c7 C. c3 [8 n% L                } else if( output < -0x8000 ) {4 G) N% A0 m* g" d5 R
                        output = -0x8000;
6 A0 O; c& X. R& ^# t* U                }) n# {# }5 r5 W! V( f* j
& z+ b" Y" z+ b1 k' u
                if( nBits != 8 ) {& a9 o5 t% f, F  k8 y# z. ~
                        *(SHORT*)lpBuffer = (SHORT)output;
, E/ J' d0 l, J! A) X$ U                        lpBuffer += sizeof(SHORT);' `' p$ o/ J% u: H
                } else {9 L' E; [/ n/ z
                        *lpBuffer++ = (output>>8)^0x80;. g, O  e8 o  W
                }
% R; D( i6 j9 \9 l* ~6 Z
% `* [8 x/ G1 Y                if( nCcount < 0x0100 )" e' H- {( q. L! }: z' w
                        pSoundBuf[nCcount++] = (SHORT)output;5 `2 t1 b8 s3 |/ ^' c1 y

  I8 q- R7 s4 N+ ]5 ]! k//                elapsedtime += cycle_rate;
' A, ^4 K6 ~. e9 C$ \+ m$ L                elapsed_time += cycle_rate;
5 q1 }2 j7 V9 W        }
& V! U' Q( C+ @! W1 ?) n. A$ J
! ]4 d4 R6 L7 C3 y1 ?#if        1) p8 u# F6 l- O
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {9 |0 H( P, L2 z, ?* ~
                elapsed_time = nes->cpu->GetTotalCycles();
2 @0 ]* Y. Y& L+ B9 n        }
* v; W! Y& e% C  ]" x        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
* ]$ V( {8 |' D+ ]& ~+ D- ]" J                elapsed_time = nes->cpu->GetTotalCycles();
- n4 G1 P3 r0 U7 Z        }
; T2 R  J+ q1 h- Q/ W1 \#else
0 z7 o- C+ [8 j- b1 {. S4 \        elapsed_time = nes->cpu->GetTotalCycles();8 d  r+ r3 n& ^' [& g. o
#endif
, w4 i* `. |; A  \* N}1 a+ k# J0 K8 ]7 q7 B4 j: I) Y
1 Y; X, A4 c. D' q7 I
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- G+ K/ Q1 o' s& uINT        APU::GetChannelFrequency( INT no ). p% I9 d/ @) c1 V- N# b. _$ p& g1 W
{+ f0 b8 ^; f0 ]" \
        if( !m_bMute[0] )3 f" B& I. m; ^# ?! S( A
                return        0;
/ ^0 L3 i+ f% V7 d* |/ J+ Y
2 I6 y% u( l! M6 v7 b8 a0 h        // Internal6 ?& p5 d7 v; b# M# x: t' ~+ Y4 e
        if( no < 5 ) {
- [1 o$ M5 z4 K# L& G7 S: h                return        m_bMute[no+1]?internal.GetFreq( no ):0;) |2 T( C! e! H6 v; ^
        }
, F  m6 _2 X) F$ K: V; G5 d        // VRC61 S) W" ~: G' s/ F) d
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  y0 H) G1 ^; M                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;, t+ |; U3 L0 U) i: E
        }, {' i4 h9 x9 R8 a  O
        // FDS
+ c5 r$ k' p' l0 I        if( (exsound_select & 0x04) && no == 0x300 ) {6 C$ q+ M) m' P% }6 ?. u5 ]
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
9 H: p8 z5 e( \8 N' S$ M& l- ^        }
- z8 s1 J/ F6 d& ~1 S* J        // MMC55 @5 U& z  ~; c' Q. @7 ^* K
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {! u1 i, i' [$ s0 t
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ @) i* M# G, \2 b- T4 \; }( \4 f        }, ]2 d- D8 v4 q8 L5 T
        // N1065 N" o% b; l. C; |" z3 Q
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: P  t# B, l3 P/ N3 g) C  |8 \" o
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
$ i! m+ l, D! D4 H, p3 w1 C        }% _, U* \3 _! Q3 z4 i6 }
        // FME7# l5 u+ \3 b8 n2 \3 E* {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {1 c7 y6 y4 a9 s% b
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
2 [) D9 T2 w# m) H# Q- _1 d2 b        }
: ^9 W; L  H# i* [/ T& [        // VRC7
  R5 |3 M. A8 I: d$ M7 [# S        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# T9 m2 n( E, C9 ^, {
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
# G/ O; R/ T/ C6 e, k        }) L" @2 o6 z5 G9 Q. ]+ U3 D
        return        0;7 K- a5 d0 z+ O5 {  W" T
}
! S1 o, i$ }; |  n
* K. e. U4 p  `0 D1 l! a// State Save/Load2 t: V, t9 l5 E$ K4 ]( q, U
void        APU::SaveState( LPBYTE p )- U$ f% ]) G' t& {. w! A
{
9 N2 J; Y  D' G/ [6 g+ S& Y#ifdef        _DEBUG; \8 s( s" A4 y. s; m2 ^' i
LPBYTE        pold = p;0 X; p$ L8 n5 Y4 S- V3 d. `
#endif" J7 C) ^, _$ |) e  ]# J

; a  C( o$ s8 f# N3 J: z$ l3 l        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
2 c3 N8 A/ i; V2 @, t        QueueFlush();
# I; \( {8 `2 q
$ [. i; M( v7 O/ K        internal.SaveState( p );* A* Y8 C9 `. H% i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ s, y( Q2 h& W* ]
" O; w% }  D1 l) G: g; n  E3 L        // VRC6/ p$ S( o  U( U! \
        if( exsound_select & 0x01 ) {5 \* f$ T! h8 L
                vrc6.SaveState( p );
( f# u; r& i' v9 v4 y2 ]                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( Q7 l/ {; [' r. I, Y* J! S: _: @
        }
4 h" w* ~, K# c4 Z, N; Q" C        // VRC7 (not support)
0 j* Y2 M8 y/ z        if( exsound_select & 0x02 ) {
# K; h9 M3 X% ~$ D' G. g- @                vrc7.SaveState( p );+ _+ D2 f6 h% d: X' E$ ?7 G( O" h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" i0 Q# u; n: J/ x3 W7 p        }
2 d& u0 J! }( |& r3 g        // FDS
# W: |: V! t* ^  J) K$ U        if( exsound_select & 0x04 ) {1 a3 T" |; O9 S6 x
                fds.SaveState( p );
8 l+ U% d& z! F' N# |: j+ v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 A4 V6 G& G/ K5 I7 K. p        }* v  z& h9 H3 n, `
        // MMC5* y1 `) t  E. ?' V! y
        if( exsound_select & 0x08 ) {
& j" |4 A. z7 b) y7 m, Z9 x                mmc5.SaveState( p );
0 U# u( s1 n9 j& b/ Q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ W) f. g. f' z: x5 {5 u& a        }% v5 _- ?/ {5 l
        // N106
, J$ N( T) G/ X4 H- J/ H        if( exsound_select & 0x10 ) {
6 b  S7 }' J) N. X; u                n106.SaveState( p );
( Y8 q9 r1 q; w- J5 ~6 d" W3 h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& G9 g7 Y( U$ g" x5 W' r  O
        }0 U' e" [9 b6 |; a0 t- v* ?
        // FME7
) P0 D. Z: X( \  }        if( exsound_select & 0x20 ) {
; ]1 L6 B% H% x8 i" @, U                fme7.SaveState( p );# L* X4 C/ p9 c+ C7 v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 O1 E0 X# d( p1 {
        }/ Q7 x1 f5 a$ h, V& D# H# B; i, n
# p  g) P$ e4 Z' v0 A
#ifdef        _DEBUG
2 B+ T) F" ~1 e) O$ aDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );. p. M8 z& R+ x* `! Q6 ]1 s1 ?
#endif8 c0 d! {3 h# D
}4 C8 n; _% ~" V# ^5 [) s- \. z
7 u0 d: j0 i) `2 ]1 y; `' B" T
void        APU::LoadState( LPBYTE p )
- \9 ]7 O' Q% y' o8 \& Y+ M' R- I{4 z) r* f) d9 v  n5 |- H1 h
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' r; @$ }  Y/ e( w, @
        QueueClear();
* k  Y% O5 W. B+ {% a$ [2 B+ x; Y6 P! m1 B8 W* `8 K6 w2 M
        internal.LoadState( p );# ~& \$ S; W0 Y) x& J
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 ]: H) g, a7 q
6 ^7 N5 z  t4 I! [        // VRC6
9 ?4 q: l- c$ l$ \        if( exsound_select & 0x01 ) {- ?' M# M3 ?4 F' n& o3 Z
                vrc6.LoadState( p );
" }! D5 c1 T& P7 V$ |% Y* s                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, h, b2 U) `) g+ ^. c3 P        }
+ Q9 z- B& @/ g; K: L& n        // VRC7 (not support), R0 w, c: i  O- \: ~0 w
        if( exsound_select & 0x02 ) {
. e3 s& t0 o6 {3 |$ u5 l                vrc7.LoadState( p );+ }) A+ m0 M5 {  k
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- q( `4 [6 T% Y/ r' U$ y
        }% N" d$ w% n* A2 N0 c5 W
        // FDS7 E; q9 V; {% W0 P6 e+ f
        if( exsound_select & 0x04 ) {8 `. z' {0 S; v- {
                fds.LoadState( p );( k7 ]0 S) l3 J
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 M) X& E0 |, L5 R% j
        }4 _) Y/ v& K, Q& S; B9 d2 z
        // MMC58 _/ b, c% M& J! V) h9 I2 I
        if( exsound_select & 0x08 ) {
7 X! m8 f, V! t9 J; C+ b: U9 B                mmc5.LoadState( p );
7 H  k8 Y( h$ @* n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; X% P( o. J9 G
        }# f) D# W# f9 F( d7 k
        // N106- l# [( S- N: X3 T% ?& s- m
        if( exsound_select & 0x10 ) {
  L- z* K+ s8 }6 _3 Y  V) a                n106.LoadState( p );
" K, J) }! g# W$ \0 ?% d1 U4 W                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: D2 ~0 `( o" a- r" F        }
1 B0 a1 _, U& _1 C        // FME72 x; t$ ~3 T" a# i8 T- L: \
        if( exsound_select & 0x20 ) {. ~( ?0 R5 g6 p3 p$ _- f+ j
                fme7.LoadState( p );$ N+ Q4 J7 J1 L6 j; v( x5 l8 X
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 \5 g: ^; x5 `& D5 E
        }
' W' Q* [6 @* ]}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
. T6 G# y, Q, j2 y3 U可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 b/ H0 {+ w- u( V* P5 Q& h感激不尽~~

. h9 k" K# ^# }* G2 F1 ~  N8 {9 n恩 我對模擬器不是很有研究,( V- q" b3 F' B" o$ t/ l7 m
雖然要了解源碼內容,可能不是很困難,
" J  B9 E; z) ]不過還是要花時間,個人目前蠻忙碌的。; v3 Z1 C) C/ g! h3 e# T) H( a3 S; h- D! m

- U  F- S& F. A4 S. y* K給你一個朋友的MSN,你可以跟他討論看看,
+ H; ^0 @! j" \他本身是程式設計師,也對FC模擬器很有興趣。9 @$ f8 `/ {$ u$ ^9 L/ P& y

- [5 e* z- _7 u3 v5 UMSN我就PM到你的信箱了。' L$ M' M  ]0 N

  \( T0 b: U  V4 w! ?! H希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 D7 n" |6 H/ Q) X! l( `' m# D1 ?呵…… 谢过团长大人~~
- I* }- b) ?  E, D5 e
+ v+ h+ s9 d/ l# m
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ ~& `& x& f3 U8 y  E团长的朋友都是神,那团长就是神的boss。

7 U# T( P4 G  I7 C0 G' t) c4 N哈 不敢當,我只是個平凡人,4 L" h/ a9 u" F' m1 {, K
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙" {% f, T/ ^2 B- `% I. t" \
ZYH& S5 o6 |, @# ?0 y" F7 R1 L# ~
QQ:414734306
" [- E  @# v& |3 g' o/ x! E! WMail:zyh-01@126.com
% W# J' h; q. \. u( \1 U
9 B) A# a( s# R; `他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
0 Y( m6 G- \$ t& _# `再次对团长大人和悠悠哥的无私帮助表示感谢~~

  J. ]# o5 w+ @# r( w不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-16 11:48 , Processed in 1.091797 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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