EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 K' u5 Z7 o7 R. z6 U! t  H楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 t) I7 D0 y/ Q* q$ ~9 X0 p, b这里有相应的模拟器源码,就当送给大侠了~~% r% M9 V9 }1 C' L7 W4 [' |3 R
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 G: y/ B8 X+ `( g* _
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 r2 W' w, I8 K& i' \楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
0 \9 f" s$ P" ~$ Q8 ?; g! O/ p4 f6 T这里有相应的模拟器源码,就当送给大侠 ...
- w" b  S* T( a6 ]7 f' ?
聲音部分(Audoi Process Unit = APU):
" @) m* {9 M" h' q$ |.\NES\APU.cpp
) |1 s" C1 P- Y* H.\NES\APU.h, V$ j5 {# A2 V; ]

4 u2 N' P2 U8 \$ U* S' Z
; A; Z3 @) R/ u' a, [' f7 U影像處理部份(Picture Processing Unit = PPU):
3 ]8 D' W5 a: M.\NES\PPU.cpp
) u4 c7 R$ R0 `  d$ F' M5 E.\NES\PPU.h8 u8 _: ^' F( r2 E0 q. u

% t" i; K. \& a: r$ v" U: X8 a如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
  V; v& _, R* a& k4 u( T(由于很多专用术语和算法机理都不明白,所以看不大懂……)
' f* g0 O0 J1 [1 B8 |2 P//////////////////////////////////////////////////////////////////////////1 _+ {# q7 ^0 ^  A6 B
//                                                                      //: G  e, e5 Y7 x7 N- g3 V
//      NES APU core                                                    //: \1 W8 g# }3 W# c, M9 e
//                                                           Norix      //
* i+ @, L7 M" e) L6 C5 i//                                               written     2002/06/27 //( F1 x# P) u" B: p+ @
//                                               last modify ----/--/-- //
! d4 i7 ]/ D; ?5 g) l//////////////////////////////////////////////////////////////////////////
0 Z! d( e# T/ _2 A0 S; Q1 y. M#include "DebugOut.h"
! Q* j; f2 t. Y; t' w#include "App.h"
& W6 U3 o, S7 U/ W6 h# l#include "Config.h"
6 h9 s; `! b4 D! Z1 j, Q7 |- J1 x* n$ ?" ?( N( e9 `9 X
#include "nes.h"
0 v& J$ }- B: ~, h/ ~#include "mmu.h": u& O2 C% y0 E- t
#include "cpu.h"
8 i6 S. J: I* h* ?#include "ppu.h"
+ Z; ^* C' Z8 s8 Z+ H#include "rom.h"3 \1 u) r7 U) \$ R8 Y$ |7 ]# c; j1 p
#include "apu.h"" b. Z1 K. s" ~% f/ D

7 F* U, F4 N4 E+ |1 x' W$ {// Volume adjust" H5 V6 k  H% i' d' @7 S8 G2 N" y
// Internal sounds  C1 r6 p% S% M6 R# i
#define        RECTANGLE_VOL        (0x0F0)
0 o. J2 X8 {2 ^7 E8 `' w#define        TRIANGLE_VOL        (0x130)  c' U3 z4 l$ k9 \: z- @
#define        NOISE_VOL        (0x0C0)% z+ O7 L# x! v- q' S5 J
#define        DPCM_VOL        (0x0F0)
7 v1 `. {+ N4 o: B7 b0 ?& A// Extra sounds
  F5 I2 @. a( G7 i#define        VRC6_VOL        (0x0F0)
0 {$ _0 j$ X9 c2 F  l6 K#define        VRC7_VOL        (0x130)
: a) V. y! F2 s5 e#define        FDS_VOL                (0x0F0)
8 k# b8 T0 ]+ ?  s+ z( \6 S6 T5 Y#define        MMC5_VOL        (0x0F0)2 ]; _- g- R  M  x; V$ F5 e
#define        N106_VOL        (0x088)) u9 z+ c, X; w4 N" c+ y5 v+ z
#define        FME7_VOL        (0x130)
/ K" ]  n2 ?6 }* Q5 n. H0 A! w. |5 |3 k; j5 K( m$ t
APU::APU( NES* parent )
* z" D2 e* i6 _4 V+ x{
, c" o, K" H4 f: o1 c- Y/ }: H& K        exsound_select = 0;  X8 W9 |+ U1 w8 m2 [4 Y

* M$ i' _7 K; T1 X3 H1 L! V/ k        nes = parent;
, B+ t% g( _2 ]- q% A8 I        internal.SetParent( parent );' o% U* L) X+ C8 J3 I4 f0 _6 C

. N: M- M( h$ o" M% `- r        last_data = last_diff = 0;
9 i2 D. L; L7 X  M0 \6 L# {) I2 p' ^/ m2 O, }8 E
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
7 M0 y" H# _7 A9 q2 C5 U: i
% |( V4 y( Q' O! m  T1 z& E& S& l( B        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );! X$ v" i* l  G+ K( ?! U$ P
        ZEROMEMORY( &queue, sizeof(queue) );
) Y% ?2 `5 F% D5 O7 @$ `        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) {+ X1 j0 g, p( X9 [$ [% i$ W
% O% u' m$ G% z6 x4 M        for( INT i = 0; i < 16; i++ ) {+ J6 |1 ?1 e& z# x
                m_bMute = TRUE;# w9 ]: U4 D* ~- A8 }
        }, Y! H4 ^2 o3 f! g
}
; {$ T$ I9 E% H3 _+ d
, |+ c* p" _/ j, G0 ]APU::~APU()* m7 L4 M% i& {' P; ^: l0 h
{3 c" C. c# N  o3 R' P
}* C$ l# J: B* o) o" _  ~$ s) P$ N
, a2 |( i; f: |& @* ?
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ j* P* s) ^- ]/ e; x9 l" q! `{
5 A" I$ ^" H) @5 f        queue.data[queue.wrptr].time = writetime;
( M8 w& i* \( C2 y        queue.data[queue.wrptr].addr = addr;
/ n+ G+ }* y7 X! ?        queue.data[queue.wrptr].data = data;( T" _* g) ]; m* L, l
        queue.wrptr++;
% a" C, J8 f6 [; I8 ?4 v        queue.wrptr&=QUEUE_LENGTH-1;  O4 J1 g2 {6 M
        if( queue.wrptr == queue.rdptr ) {. @% z+ T6 C# n8 [: y& r! c5 z
                DEBUGOUT( "queue overflow.\n" );
! d8 j2 u/ G, B! F+ l( o        }) O+ n( G% y2 }4 l- r7 W: U: n
}
/ z/ R7 y: |; m" k2 Q) i" q  Z/ ~6 e/ R; u/ c
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: r+ F- B' [0 }* x{! J5 e( p- N, D$ v3 w' o
        if( queue.wrptr == queue.rdptr ) {
/ d) _) V1 S" A2 m                return        FALSE;6 ]2 `. h& ]$ _/ k" S4 v+ B- f$ k
        }
9 v# G/ B' K( g1 r! n: j        if( queue.data[queue.rdptr].time <= writetime ) {
+ c; ]$ m, k3 b: u1 m! k. g5 a                ret = queue.data[queue.rdptr];
8 e/ v# X4 W7 M                queue.rdptr++;
- k) e3 I. s3 c9 P( S6 x0 E                queue.rdptr&=QUEUE_LENGTH-1;. V2 y. n1 E+ ~* B& L
                return        TRUE;% U* |. P. T. l2 s, S+ u8 V; f
        }1 Q' i  C" J, h9 D
        return        FALSE;* @4 ]4 ^$ Q, k" @5 B$ x
}; P" ~' y7 l! L, V+ `% U% w2 H

! X% ]/ m' M) c2 [void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 s) j( H5 V" X6 }( I* R) P# Q{" s! |7 Y% u( E3 z- d- D5 O. B
        exqueue.data[exqueue.wrptr].time = writetime;1 [4 Q* B/ d4 W5 t. D1 w/ L) T
        exqueue.data[exqueue.wrptr].addr = addr;( b& j" Q0 J2 B9 ?2 F  Z2 q
        exqueue.data[exqueue.wrptr].data = data;
9 R: M, b% h4 d3 r+ `6 g) B: M        exqueue.wrptr++;
$ u) C6 M0 r4 |0 _- V        exqueue.wrptr&=QUEUE_LENGTH-1;
/ P0 r8 k" h/ ~, h  G4 U; a        if( exqueue.wrptr == exqueue.rdptr ) {. @  X* S6 ^" z$ k. R3 ~
                DEBUGOUT( "exqueue overflow.\n" );9 X. W0 ~! O3 `+ Q* m4 [
        }8 ?: p- @4 s, |! P( s
}
/ k4 n/ Z, q7 O1 P' y; V( e2 u( H  [7 m' F
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )3 [6 W% o7 S" V( ~2 A' S
{
9 [* y8 Q. m, S5 T        if( exqueue.wrptr == exqueue.rdptr ) {
* n6 J/ Z) J7 g; a- C                return        FALSE;  m: h! b: G; _, G
        }
% d2 f3 s1 j9 T1 J1 V        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
: H& @  s7 y; f8 G8 H                ret = exqueue.data[exqueue.rdptr];/ R' ^4 T  l7 P; h0 A% T* u
                exqueue.rdptr++;8 ?) @; k# ]* I; Q8 F  \! Q
                exqueue.rdptr&=QUEUE_LENGTH-1;" i$ A" q* j& }/ u
                return        TRUE;
4 ?8 x5 D/ b/ R# W3 ?2 L( ]        }  M' j+ Y3 q0 @9 q, k" A+ z
        return        FALSE;
0 {  `3 v% I) }' v5 S& {$ D}
/ {- y7 \% C: B! D: d- f: n/ K$ }: i
void        APU::QueueClear()# D2 ~- n6 i- L+ H& I
{
8 Y* T) B- A6 Y: b# }) X        ZEROMEMORY( &queue, sizeof(queue) );$ ]3 H( K8 L' _3 u2 H
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- N3 V& z" f9 \$ A+ d3 b1 D+ X
}3 a% ?. ^9 N0 ^) r5 x" C: f; K
9 D6 D, L+ f* g3 P9 ?$ V0 Q# x# H: j
void        APU::QueueFlush()9 A& O7 F, a9 y+ ~/ _: O! Z9 ?0 W- R4 G
{! C. Q' T" a, b4 l- _" ?
        while( queue.wrptr != queue.rdptr ) {5 d/ n6 W8 B8 `. J5 P7 F8 v
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 G: w7 @$ f! U
                queue.rdptr++;5 v9 a6 X9 j2 w
                queue.rdptr&=QUEUE_LENGTH-1;: d2 z8 N, ~* X& d( y9 A% G
        }
+ q) N& k; g/ |
! f2 f; O& ?; a5 U% I- E- p        while( exqueue.wrptr != exqueue.rdptr ) {
! R3 C% ~8 P2 H: L: v                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );! y6 {, `* {. Z8 w
                exqueue.rdptr++;( Z. R/ n5 C" N, `7 A3 w
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 h2 K! I; a8 }' c' X4 J( `/ C+ d        }% R! t1 t( C9 ~; L" t! e
}
" _) Q: {2 ?/ N8 B' \
* k. S( A& V& k; N  n9 L; n+ D* x( lvoid        APU::SoundSetup()2 q- w0 P6 g7 h
{
' t: P( ?! \# ^6 v: v, a% T, m/ L        FLOAT        fClock = nes->nescfg->CpuClock;& P1 h8 K" x$ ]! Y
        INT        nRate = (INT)Config.sound.nRate;" |& K2 R1 D" ?& e* d
        internal.Setup( fClock, nRate );
5 s2 ~+ L3 R- W5 g        vrc6.Setup( fClock, nRate );# Z* Q2 L7 W9 s
        vrc7.Setup( fClock, nRate );
* h. v7 m0 `" ?7 m        mmc5.Setup( fClock, nRate );# n/ J6 l% B. i8 R1 |4 ~
        fds.Setup ( fClock, nRate );4 I6 E  m8 P  R" f* k' H; R
        n106.Setup( fClock, nRate );* ]( }( ^& P. N1 Z
        fme7.Setup( fClock, nRate );5 P' h) t+ C& \5 d* N) E
}
6 ~6 S7 S" l8 U/ F
* _7 H; A1 x# jvoid        APU::Reset()
2 e+ Q$ Q  k5 s( N{
- T. Q  }; L( S+ g. c2 |# _6 u        ZEROMEMORY( &queue, sizeof(queue) );# N) J0 e  ^4 `7 S
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 Q; r. B+ P4 E' l* Y! x

! z3 `- B; F( c        elapsed_time = 0;& y! W! v* l; `* g
& ?8 s* j5 C1 V
        FLOAT        fClock = nes->nescfg->CpuClock;
/ s5 I' S8 _8 T        INT        nRate = (INT)Config.sound.nRate;, w. T  o( d5 w1 A+ M
        internal.Reset( fClock, nRate );) ^2 W! W! c2 G3 k' t9 d. H
        vrc6.Reset( fClock, nRate );0 Y$ `1 g. I+ h) s8 Y
        vrc7.Reset( fClock, nRate );
0 o" z+ J  s# S7 i4 A        mmc5.Reset( fClock, nRate );8 p7 c$ ?& a8 D; F. F) G
        fds.Reset ( fClock, nRate );. C/ X7 u* r' U8 U$ u( x
        n106.Reset( fClock, nRate );, E! Y% M7 j2 b0 y% p3 h8 {0 U
        fme7.Reset( fClock, nRate );" y$ {: Q' s6 L+ r8 l

% ]5 H- H( l. e  `( \        SoundSetup();
: D5 \$ C+ T; t4 Q% J  V6 \}) Y% ^% d% l# }

9 l& U; B& N  c+ q8 rvoid        APU::SelectExSound( BYTE data )- z/ U1 T3 D  }' K  l' T/ d' _
{8 I3 G4 N: B2 y8 ?1 l. a) w  K/ M% P
        exsound_select = data;
  U3 E  e( T8 X! T+ j7 A, Z}$ T4 A  }+ r/ x7 h1 u5 Y

( T3 `( u& d7 R% J, G7 hBYTE        APU::Read( WORD addr )
+ X0 T: g. u- j8 X{
/ l# R4 b  v& c) W        return        internal.SyncRead( addr );
% U5 J/ ^9 w$ z8 C1 E, Z# U8 ^}
  H) r0 J' h* T2 l; [! r, U, Y. A& G$ Z* Z% g
void        APU::Write( WORD addr, BYTE data )
$ R2 @/ O, e) z4 _{
1 T  P# d5 F, h+ v& _        // $4018偼VirtuaNES屌桳億乕僩; I7 B; A' ?% ^/ e9 x) d, s: P, m
        if( addr >= 0x4000 && addr <= 0x401F ) {
0 \/ a/ ^% l$ H1 s. {                internal.SyncWrite( addr, data );
& u$ ?, s9 J( |- z8 `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
* o- m+ E1 A! G+ _        }9 S8 e4 K7 G1 ?  b' i; ~* O, J4 T
}: f! f( e* r) z$ G5 S6 I- O/ m" |* ^
3 q. Y+ p6 d3 j  K- }' _- |8 g
BYTE        APU::ExRead( WORD addr )& y+ ?) P1 c  [7 l) Y
{
; a9 \; B& J4 y8 `6 n- J# qBYTE        data = 0;
, l+ [2 X, U. ~; ~" C% d( e4 b  V- y- u6 T) o
        if( exsound_select & 0x10 ) {$ B7 Z9 u; H4 L8 y) B
                if( addr == 0x4800 ) {3 ]+ m0 ]% E- V! ~" o: B! T
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 I) _1 m: V2 S                }, V1 v7 O! r8 @
        }
7 U( ]( G( k1 R$ @7 I8 E        if( exsound_select & 0x04 ) {6 v0 X, M/ o! ?+ b% U; p
                if( addr >= 0x4040 && addr < 0x4100 ) {
% ^2 f. s& r) B: t* h                        data = fds.SyncRead( addr );
0 D) c! e  A$ R8 b4 F                }
& d" [, b9 ?+ @6 C  s2 X$ S% z  N        }; d! _' O0 _. T1 q
        if( exsound_select & 0x08 ) {
' e& |% p7 H( L& M7 r0 H% {+ J8 u                if( addr >= 0x5000 && addr <= 0x5015 ) {, q" |$ z2 h" h$ J% k1 C0 r- O
                        data = mmc5.SyncRead( addr );7 I- U$ @/ |/ Q: S7 F1 D1 a
                }' I) T- u$ Z" M8 A4 |+ Z; [9 _
        }9 P6 M" |: x9 @$ j& `

1 Z/ c& x  s# [9 C, b        return        data;2 s+ ]. m% i' i* A; X1 t
}
! ~' s  ^' P* N7 c
! n5 `, R0 c( Zvoid        APU::ExWrite( WORD addr, BYTE data ). ]- w' v1 ?  o* c* z# c. R5 ]
{# d* F* r+ C8 Z- c
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );0 {8 E% l$ @! x# y. y3 \# T8 U

1 Q8 y0 d$ k! z% x0 K- u2 t        if( exsound_select & 0x04 ) {
; R' m6 i4 A4 c4 \5 W4 l                if( addr >= 0x4040 && addr < 0x4100 ) {) s9 r. u& Q% u5 y
                        fds.SyncWrite( addr, data );
6 s1 ~# y/ O6 Q+ h8 t/ x* B* D' f                }$ @& Y  j1 t# B' c3 `$ z
        }
* T( Z# J# ]3 ?" k6 l$ h4 N3 X$ m% }, p7 Q9 `# r; G) L8 D( `! w
        if( exsound_select & 0x08 ) {
4 {8 B. w- \5 x, U" S% k" w                if( addr >= 0x5000 && addr <= 0x5015 ) {
% R. k5 b- E8 ~7 G$ b+ G                        mmc5.SyncWrite( addr, data );
1 i6 G2 Y5 c/ j/ l: d                }
/ |& `; ^# d" T- w        }1 O$ D; M# V6 J7 v# A
}0 i+ v8 q' I* z
6 I. J. t; g4 a8 ?
void        APU::Sync()$ \7 W+ l, B  @4 ^
{# T! U& v% h" L5 Y
}
7 F1 f3 A3 O4 R- A7 E$ e0 l2 j: J2 t! d, u- C% R/ I2 i! J
void        APU::SyncDPCM( INT cycles )! ^  U/ Q. `7 ?; t
{
3 C! o2 W; h/ P        internal.Sync( cycles );
; |  A; G6 E! ]) k
5 p6 G: r* K5 o% O& q        if( exsound_select & 0x04 ) {& l. |: G; ~1 o" B
                fds.Sync( cycles );
' A5 n" q5 G" b  E" I        }5 }% ^4 T% @# v# b" d8 c
        if( exsound_select & 0x08 ) {
  A! B9 c: p2 [" o+ ]                mmc5.Sync( cycles );
: M- F5 [9 _1 r! T! ?        }
+ v9 h6 ]! G6 \; i! x- S7 K}3 Z0 X: y8 d$ T( k3 r
$ r) m8 n. i. e" i2 Y4 ^7 R" k
void        APU::WriteProcess( WORD addr, BYTE data )8 |6 V0 m$ D! V  e" P' h
{
4 p- W5 n1 K- E% s  @! f        // $4018偼VirtuaNES屌桳億乕僩2 z9 v! b- I! R2 v4 a: i! ]
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 J  s. ?* q. q- ~) V                internal.Write( addr, data );1 @& v0 n1 I: c2 y% j* ~4 A
        }
  m$ @+ [+ Y, F1 g. l}
9 f! w5 B( x9 n- x! u$ u2 r- _
9 s3 P- x! L# `! Z$ K) Pvoid        APU::WriteExProcess( WORD addr, BYTE data )$ M/ x% o: i$ I% V1 @& n& W
{3 I, \9 y7 o% W0 d
        if( exsound_select & 0x01 ) {
# f8 [$ a9 q. p/ K                vrc6.Write( addr, data );
3 Z. a" s1 d& I% r        }
! L9 r2 Y" r( h9 h* b# ~* C        if( exsound_select & 0x02 ) {
7 K5 Y- G. D; j: Q                vrc7.Write( addr, data );/ K. X* q7 g1 [! ]/ r  D- B8 o
        }* [7 c" h) v' f2 p. x; G, h
        if( exsound_select & 0x04 ) {: d  m# V$ D6 z
                fds.Write( addr, data );
" ^: \! u6 J7 j, G6 l2 V        }
" Z6 ^. \: _5 a0 {9 Q        if( exsound_select & 0x08 ) {
5 g! K/ u! Q: E, @) W" n                mmc5.Write( addr, data );) X9 E. d# T/ w% e9 S0 g
        }
; T6 e1 c% G" n  t        if( exsound_select & 0x10 ) {9 e2 s# k  H7 m$ h) [- d
                if( addr == 0x0000 ) {0 x- [! v3 A9 O! V5 i: X
                        BYTE        dummy = n106.Read( addr );  J6 P- \7 G7 F* }# M
                } else {
. n! E: C) Z( i$ X4 j* y# U& D* ]) P- H+ q                        n106.Write( addr, data );' D( M: r, f/ G5 H# |. Y( o
                }$ w8 q* V  t! I6 v0 [# q! b: R
        }
5 C, e# D" j  h" a6 U# X# ]" c        if( exsound_select & 0x20 ) {$ W6 H; ]3 l# H9 A+ e4 p4 P
                fme7.Write( addr, data );3 o! D- q& ?7 c! L( b" |, Y
        }$ P# f: J$ e9 g) j5 Q* p: N% G
}4 r- h2 v: f" X4 t
8 Z( M# Q  y; r9 n7 T# `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 X4 j# Y4 u" E8 c# h9 W  E{
1 [/ F3 |+ o& g7 }" fINT        nBits = Config.sound.nBits;
/ U8 u  h' Q3 s( ^! Y4 z% `: ADWORD        dwLength = dwSize / (nBits/8);3 |" C6 O" S7 r& f* |; c
INT        output;
1 D& B, W; W, \$ g. JQUEUEDATA q;' l. v5 _* q. H, H9 _
DWORD        writetime;
# A$ K0 s" p6 n
7 ?/ T" [9 i# w8 c; g3 vLPSHORT        pSoundBuf = m_SoundBuffer;
0 g# D. Z3 D" H1 tINT        nCcount = 0;
2 w9 N& H9 v% F' H; O* y! Q8 M+ J1 [
INT        nFilterType = Config.sound.nFilterType;4 ~' M. O, m2 v, e+ ^. g

* P4 Q2 q, w9 \$ q        if( !Config.sound.bEnable ) {
9 k% ~: r+ U+ g7 f% a                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
% |9 H/ x1 U$ g2 C                return;! r! e5 B4 A2 L: w8 G
        }
9 ?' E, ?; @/ a2 m$ K0 T( [7 l9 n. Y6 W8 E5 o) t% S8 u) G
        // Volume setup. ]! C& `! n$ k! x) b
        //  0:Master
5 n# ~( [- w& e3 I        //  1:Rectangle 1
/ e" P2 e0 L  \* b  [( ~        //  2:Rectangle 22 `% I. H, J0 H1 R; a
        //  3:Triangle' |4 {9 ^% D4 z; Z  A0 J
        //  4:Noise. V. N0 G; D" u" _& @2 P
        //  5:DPCM
; e. q  C; `" j3 [        //  6:VRC6# W9 b5 Z& m7 F$ K; v
        //  7:VRC7( g& e, T) m  ?$ ]. i. `1 _, U! X" `
        //  8:FDS
4 ]8 ~$ x1 x0 M# C5 m2 Q6 q        //  9:MMC5
/ ]+ M. Q& O) y! H* B+ V$ J        // 10:N106
6 R- ^. L& n2 \) f$ y% ~9 P$ y        // 11:FME7% c& n4 y0 C! Z" ]8 z+ N" k
        INT        vol[24];
1 F. W) b) ?' g        BOOL*        bMute = m_bMute;4 m! Q8 W9 @1 p1 `* L. J
        SHORT*        nVolume = Config.sound.nVolume;
1 f8 X5 I" d9 h: J# M; Y2 z% n8 `! G# x/ M9 Y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- E, z  x3 l+ Z! n$ L! Y
3 y8 Q/ N0 z( U7 O% z2 M/ w# O
        // Internal* P, ^4 U0 f! N0 x! w
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; |2 H! e& F3 X- Z4 [6 U
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 M% o1 |3 H1 }+ {
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, O4 I7 V( T7 ^$ M0 c: V0 z" R; q! z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 m4 |# B* ?* w  I% \3 F( `2 o        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! B: \2 x6 s/ p4 }. X4 `& |2 p5 m$ u4 I2 `" @& k, G6 \" c
        // VRC6" V; D. f* g' ~
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) z/ s5 z8 ?3 I. f4 D4 l        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, X2 B1 l  g8 M7 w5 T4 c8 P        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 `! ]* ^, d" f

, H/ B% E( N. B( @( P% f% U7 ?        // VRC7% \0 t, ~/ m0 V& n1 {/ i
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;7 e3 I6 x1 X! p2 }1 [) W

+ I. D3 J- f7 Y6 h# n; C- Z6 I        // FDS# q1 B, a/ J5 H: @! ]% Y* T3 P9 S4 s
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
/ _% T- z) e  P( c/ y9 H7 |% N' m# b/ ~* ^& Y' h6 L* z4 j6 I9 |6 }
        // MMC54 |, B! P( a2 P. [/ v7 g( T1 I
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ i+ ~7 c: b5 r% I( n
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% S9 I3 i9 H+ ]- x7 b3 G1 @        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* O: ~: c- B. T5 Y, _# ^9 G% i7 C( _2 s- W8 f
        // N106
8 E* ^; I+ v6 c/ ?' w        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# ^) Q1 f7 R! I- J5 M+ ]9 C; i: u0 }        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- @$ X; K8 I5 f/ J6 a
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* S2 @2 ~$ v" v. G% K- g        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. L/ E* q" a. P. R, m; {2 A3 x8 _" J        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- r9 ]8 F/ c$ S0 L& X) k        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 a6 c% D' U- \' J: b/ q, x        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 [. T% m4 f  O7 O' |
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ]8 f1 h3 Y3 `1 v
5 {+ v- b0 E0 T1 z9 v
        // FME75 b5 k9 Z& s" E$ d1 a5 `
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 j" H! {5 ^, j
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 A# Z* v2 O& b$ L% w/ _# O5 ^, i
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 h0 z& H# `; c& A: Q5 e8 m- _, }' P; c( |7 `% a% ~/ ]! J
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 ?( q. M  g' D
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* d8 U9 V: l- }* K/ b) d, h8 r/ J* K
% D1 l+ v4 \0 n( n# o# a8 D        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟, F1 v8 E0 Q0 L' @2 [6 D, {2 q6 ]. L
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {1 ]" M/ q! i0 k0 s: h5 L0 @& k
                QueueFlush();) ~8 e) a0 j+ W9 e! y2 Z
        }1 k* h& a2 ~1 W

# H1 a+ d, }* a  E: R( I# d        while( dwLength-- ) {
0 Z9 O2 m( B; i. _4 p! h' u                writetime = (DWORD)elapsed_time;% ?4 u/ w/ S0 _8 R5 L
. ~! h( x( V! E0 t5 f. a- i0 A
                while( GetQueue( writetime, q ) ) {
- M  m9 ^8 a  R' K% P                        WriteProcess( q.addr, q.data );
. V% Q% H. t+ S5 z% G3 R                }+ @1 O0 W5 ?; x
; I/ @- v! u9 R! X4 f# w9 \
                while( GetExQueue( writetime, q ) ) {
- [2 D1 m! s! M1 U1 ~! U                        WriteExProcess( q.addr, q.data );9 Z% t5 e" q) l* r# Z
                }0 l# k3 r% X  L. n* ~

/ X  d  b7 P( t5 m8 u                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7: |. E3 c, c! `! C2 S
                output = 0;2 \# p2 t. v# P; |6 {
                output += internal.Process( 0 )*vol[0];( l; l- y% Q% ?& L8 R
                output += internal.Process( 1 )*vol[1];
$ [& z4 m) r) ?8 u& Y                output += internal.Process( 2 )*vol[2];* H: y7 R$ E3 [: E8 [/ T5 g$ m7 r
                output += internal.Process( 3 )*vol[3];
) v$ ]5 K# F9 h5 i' E                output += internal.Process( 4 )*vol[4];
1 J: o# r' o6 M2 j8 [9 i) m# Q) p$ w- C( t
                if( exsound_select & 0x01 ) {
- x) v0 R0 A* R8 b- W8 g                        output += vrc6.Process( 0 )*vol[5];
  u- z$ o/ Z3 G3 V                        output += vrc6.Process( 1 )*vol[6];" }' v+ x" u6 \( j% b% D; V9 H
                        output += vrc6.Process( 2 )*vol[7];: _) q( v% k8 X( n# [" I' Z9 Y/ P/ L
                }
# Q3 n, n+ T+ z1 N6 r1 l4 }/ n                if( exsound_select & 0x02 ) {9 U# b" c/ Y3 m- r; Z6 r  x
                        output += vrc7.Process( 0 )*vol[8];# H) V2 X8 V. H1 f% W
                }
6 T% a$ R  g7 r0 o                if( exsound_select & 0x04 ) {  z  G9 k7 r% D2 w" G7 R5 ~; j
                        output += fds.Process( 0 )*vol[9];
, H( [  A+ D# E$ `9 P$ E( a  a  v+ E                }
9 ^5 _: b! T: Q/ o9 }# A0 q                if( exsound_select & 0x08 ) {
) [3 g. S9 A3 ^+ a) o: ]! c3 A& a* n                        output += mmc5.Process( 0 )*vol[10];8 c6 q4 t- g  }
                        output += mmc5.Process( 1 )*vol[11];
" Z, ]2 L6 l) {4 c1 `1 x% C' h! R( ]                        output += mmc5.Process( 2 )*vol[12];7 z5 t2 N7 a1 w: [; [
                }
* ~2 P- a3 F- ?                if( exsound_select & 0x10 ) {# L- `3 w7 y2 O7 B; i- W2 _* y
                        output += n106.Process( 0 )*vol[13];
" t1 G+ b6 q: a; G4 T                        output += n106.Process( 1 )*vol[14];
. d" c3 Y. f0 K# r                        output += n106.Process( 2 )*vol[15];
0 d* z- J- o! J                        output += n106.Process( 3 )*vol[16];/ f. ]( L6 Y9 o# X; D$ M, w+ W: i) N
                        output += n106.Process( 4 )*vol[17];6 {% y( ~: }7 @/ }3 u9 C
                        output += n106.Process( 5 )*vol[18];* t2 _& G' H, A+ |8 S, `
                        output += n106.Process( 6 )*vol[19];- h" E% l" \: L- [3 s* ?6 E1 c0 C+ C: C8 t
                        output += n106.Process( 7 )*vol[20];
5 [/ ~3 z9 Y- B. a                }3 u4 R, f% }1 u1 A: Z( H8 b
                if( exsound_select & 0x20 ) {. O! W# l' G1 a* ^) ^$ b
                        fme7.Process( 3 );        // Envelope & Noise
) t+ i+ _5 p! n8 Z0 m4 N- P                        output += fme7.Process( 0 )*vol[21];
0 Q) y, v( h& b% I0 i                        output += fme7.Process( 1 )*vol[22];
4 B' r. y5 T' K2 ^                        output += fme7.Process( 2 )*vol[23];& r6 ?6 [# f7 w9 F
                }: f! c2 M; \" L4 l$ F
5 n; p" J% e9 g. n
                output >>= 8;* V' V( i% E6 W
& Q% p; {5 S5 B3 f7 ~; q; Y1 e
                if( nFilterType == 1 ) {
& o. \. \% ]3 [: h) S! g) i- n, J                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
8 ^5 L3 X8 H& D                        output = (lowpass_filter[0]+output)/2;
6 I. s) B4 q7 V- [, g                        lowpass_filter[0] = output;
' b! H1 [" A% t                } else if( nFilterType == 2 ) {
2 i- w$ R7 x. D                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
; |5 B) A. x1 y# \  l6 D                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
% G  f1 d2 D2 E& N6 [; n: {                        lowpass_filter[1] = lowpass_filter[0];
8 k% |7 q  b! c/ D* a1 F: P4 ?                        lowpass_filter[0] = output;$ k% a+ k+ I' l6 \3 D
                } else if( nFilterType == 3 ) {
+ `3 t. ~; Z8 u4 c/ ^                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
" ]2 d2 I+ ~+ [2 q                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;; r/ M. ]0 `$ _1 O7 }
                        lowpass_filter[2] = lowpass_filter[1];
5 k& h: d6 c. c5 u& F0 C  ~6 h- B5 g                        lowpass_filter[1] = lowpass_filter[0];
* ^) @3 S$ k4 P. z! T                        lowpass_filter[0] = output;8 q# D5 x" x% q5 z0 Q
                } else if( nFilterType == 4 ) {
; `) r) ~' q  _0 j' c                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% k/ c! x" R; p2 v
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;5 X  ]. _" `! _
                        lowpass_filter[1] = lowpass_filter[0];* Z" o8 A* g7 s3 j2 n
                        lowpass_filter[0] = output;
" K  M. H5 X1 w1 ^& b                }
. v* J, n0 B6 f, |9 k! ?. K- G3 N6 |) y: T
#if        0
2 R, M: l7 M  c. L# g- u3 g                // DC惉暘偺僇僢僩7 c1 @( K# v' r6 v4 Z- i: A
                {' Z' c0 H" |- ~+ D
                static double ave = 0.0, max=0.0, min=0.0;* p* K' X1 R1 l3 H8 k; S4 y
                double delta;) _6 ~1 L9 u0 n/ U+ ?5 z3 I
                delta = (max-min)/32768.0;
" \  c* J8 O* g6 X                max -= delta;
% D4 l% L& s+ D3 P2 `% \8 U                min += delta;& s! k" d. [& j; H( d
                if( output > max ) max = output;" B" T& q0 X; E+ t) W
                if( output < min ) min = output;
2 a( o  B5 N( N) g4 g                ave -= ave/1024.0;5 R, Z7 P* M+ U$ d) X9 ?7 o5 `, n
                ave += (max+min)/2048.0;1 C) N6 A* g7 P+ p2 ?
                output -= (INT)ave;
8 g+ v6 ?4 e/ w$ |                }
; D% Q  u3 ^, ?( s1 u, i! b/ i#endif
) s. ~4 N/ \3 X$ u' r5 t#if        1
) x. ^! D2 W! l1 g                // DC惉暘偺僇僢僩(HPF TEST)
( |- i! A' h$ f2 c% z) J& J                {( k2 \; F' C8 T6 h  T& g3 C
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);7 K. x9 k( c& p0 u8 K1 j: [3 O
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
2 i: _- a+ ^: z& q9 x- b2 ?                double        cutoff = cutofftemp/(double)Config.sound.nRate;" h+ L2 _8 b0 [  [( T
                static        double        tmp = 0.0;
1 T/ C1 \1 v- S! F6 q                double        in, out;
- J! i. ^( G2 K5 Z2 e  Z  ~4 y. k) Z4 \2 J. F1 v
                in = (double)output;
/ I4 f4 x7 w- b6 d                out = (in - tmp);
1 x3 ^4 s' }: }6 k  ?) v! z8 ~' ~                tmp = tmp + cutoff * out;) {! S6 k" r0 r/ A0 b  D

3 G! [, \. |( D2 n* `1 h                output = (INT)out;
% w+ k! ?- B7 w1 s, Y$ K                }
& u+ `) K, y% |0 V- d3 y! v#endif
% r3 `2 e# S5 U: E: c. x. Q" _#if        05 a5 u/ L  I' f" A/ `2 R
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
1 I1 H8 r+ m4 o/ S                {& V3 g+ @" t# m  B5 \$ d8 R
                INT        diff = abs(output-last_data);9 v8 ]" i" R7 w0 c
                if( diff > 0x4000 ) {
! r6 y- X5 W( l                        output /= 4;/ g; S( g9 A; C% }7 g$ {' j  f
                } else
: C7 B: S3 l7 v- `                if( diff > 0x3000 ) {
$ O7 F% \+ M/ J- m" X                        output /= 3;4 h$ l/ ~: N* L6 [4 `: _- c5 W; r
                } else/ W; M4 ]. j* K+ e
                if( diff > 0x2000 ) {( [3 c" v2 L2 @% T7 H
                        output /= 2;
% q! ?: p, o! @- e8 F* m                }
  L+ e3 q# g2 W4 L; B. X1 n. `                last_data = output;
" ^( f$ s6 L- s                }, {" V+ H7 ]4 s7 b4 r! v6 z
#endif, ?9 B( N" }$ u% u/ L1 L
                // Limit
( _0 z% J2 i' {4 r" F  M0 v9 {" K                if( output > 0x7FFF ) {+ u0 S  z" t' B$ }3 F
                        output = 0x7FFF;# r3 r5 c1 m5 e* J, B% s
                } else if( output < -0x8000 ) {
' p2 _( m0 L3 I                        output = -0x8000;
2 u* ~/ R0 n; _" m( j/ d, {7 F6 m- p4 b                }
1 r# X1 Y9 n% s, E  w% P
- t% Z1 E# V+ g9 `: B+ t) H0 O                if( nBits != 8 ) {
/ o6 @8 Z) `$ t+ n5 V6 x                        *(SHORT*)lpBuffer = (SHORT)output;
- j* S# W# ~" Q" i; m' d3 F                        lpBuffer += sizeof(SHORT);
9 @% k/ A* k0 V% s) s$ J& ?1 u                } else {* a6 u" _1 B) J( N
                        *lpBuffer++ = (output>>8)^0x80;
7 e  ?7 K2 l8 o1 A                }  M" j, a3 }0 d/ L/ B
, M$ p! Q$ j7 U; @7 s- }9 T
                if( nCcount < 0x0100 ), n* S6 X: k  i" L
                        pSoundBuf[nCcount++] = (SHORT)output;% P" N& X# F: M+ h8 @
) A! ^8 e" q+ K8 \) C( a5 j/ }
//                elapsedtime += cycle_rate;
, G/ E# Z/ w$ }7 t6 v8 x" X# X                elapsed_time += cycle_rate;
1 G7 }9 [8 i8 A# a+ j* X        }
9 n: v8 U: h) G3 k5 m
# ]0 ~4 I/ g3 D* K- K4 |: C#if        1
- ?" z' m) A1 \7 Z$ A! `# B6 Y1 x        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {( y; X/ E. b- h& Q5 a7 a, G- X
                elapsed_time = nes->cpu->GetTotalCycles();, y. B- y/ g# d! L& J
        }  V; {1 I7 ~# {5 _! ^% \# u
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {, S# R) ~1 ]/ m4 c$ C3 q
                elapsed_time = nes->cpu->GetTotalCycles();
' \) }+ z0 x5 `  V8 t        }2 g- g8 |9 E  h( R$ F
#else9 e& [+ Q. M. n& j- N
        elapsed_time = nes->cpu->GetTotalCycles();
+ w/ `8 t* a$ R$ f( B#endif- y/ _1 N2 i+ F& U& c) ]0 w
}
( s. c! _$ [$ |1 E3 I
0 v6 z6 T4 E( @0 T% M* ]4 m& p// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)" R0 m6 \9 s3 y
INT        APU::GetChannelFrequency( INT no )( B3 v2 O: j9 m$ x8 M0 f1 A- ?  Q
{
( n) E4 A3 [! n) Z0 H2 T1 ^: p        if( !m_bMute[0] )! g, j8 J6 z: A% ?$ k( o
                return        0;7 v; o# O8 E( D& C

* e  i) F6 W8 `: J, _  s1 S  n        // Internal
7 m5 x& W7 E: M- `        if( no < 5 ) {
9 a3 H* _& H+ k( X. P                return        m_bMute[no+1]?internal.GetFreq( no ):0;
3 P; T8 z& S  P( b& y        }
6 F. E5 c. C( \; `6 O( a4 z        // VRC6
! t1 X( |. R) r% c+ _' i$ Q! @6 z        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {* J" I, b2 l$ Z+ ^; z2 g" u+ D$ G
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;- l) V8 A& B4 L  V7 F% J* Y; R+ P
        }; K3 b8 @" @& g' Y. _
        // FDS
- u4 q3 U3 v& v. ]$ f" n/ Y        if( (exsound_select & 0x04) && no == 0x300 ) {3 o: ]4 }2 y5 W( \) A3 p$ `% e
                return        m_bMute[6]?fds.GetFreq( 0 ):0;0 x+ m4 S7 d1 E+ s& @2 `
        }# Q6 m, P' n  ]6 b* L. n3 ~* N
        // MMC5
1 h+ ~6 F! P7 l        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {. }9 h4 b0 [  w, e' ?
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 N! w) U. @- G1 E9 a- s; l/ E
        }) v+ v* F! P4 @
        // N106
' u  w- K  {, ~( ]6 W9 u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {/ n4 n4 e: I' h; F
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: X+ k9 J* k0 M4 n3 L
        }
) c. {) @* b, f' R1 z        // FME7, c# V0 K  o( K+ _) z  M8 _# ^
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
* L+ w& O& j  l2 I, P* T$ z                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;1 r0 N3 Z6 T9 A, t
        }' u! v% i: c. @% N) g) s' c; I
        // VRC7
$ L' }& @  V5 }4 z+ o  {( Y, B        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 Q7 A* A5 o4 ]' k, d' ?" z
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
/ ]% r& F! t8 L) J) r  t* U( ]        }
4 x4 h3 Q. U% d% _: K8 B/ s        return        0;9 v; O6 z/ d) O  ?. N
}
+ }2 v+ a$ \  }3 d. {, y4 i$ O
& ^6 V  `0 {1 B% b$ y2 i// State Save/Load
. j) v- w2 c- |+ M+ Avoid        APU::SaveState( LPBYTE p )
6 z4 U& x2 ]' ^9 z{* ]! Y) c, a" [8 ^6 w6 O2 j
#ifdef        _DEBUG
/ W0 |6 t9 I& K3 H: L: z4 N! [% [LPBYTE        pold = p;
: l  s& Q% o  B# y4 g/ D- k#endif5 v4 P( w  |$ H6 P3 E; P

8 J; \" n3 J) x! B: a2 m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! O5 a/ d# |; {5 t; x- G1 X        QueueFlush();3 y2 p9 M) m, n" r2 `7 g3 ]: A
/ F5 y1 c, w0 o7 O7 @! a
        internal.SaveState( p );
6 j3 I5 n0 Z' `, ^/ ^. ?$ S$ Z. u# c        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  A7 S; Z/ y4 M' n+ E+ X
9 Y$ [0 n7 n" @" \
        // VRC6
7 n6 V9 {+ b% b% d: \/ f        if( exsound_select & 0x01 ) {
% n9 H& _2 d* C7 E; \. ]1 [$ t                vrc6.SaveState( p );
* W2 q% ?/ p3 q, O7 w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 ~8 S; Q1 L* j; B8 k- }
        }; a% p: |! \5 f4 {# x# e0 a
        // VRC7 (not support)
6 F/ P1 ?6 l; B6 @( O        if( exsound_select & 0x02 ) {
* e0 o8 S5 X$ s$ U2 h                vrc7.SaveState( p );! U7 Z2 B/ i8 I% T! G( C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- O" R. ?, [. [( Q8 o; p
        }0 _6 F; w7 m0 @% P7 Y& k, s7 ^
        // FDS
/ }& L# Z# n; z" Z+ L' F        if( exsound_select & 0x04 ) {* k$ I) l  p0 t% B7 X# U
                fds.SaveState( p );
' i: P. r: |1 c" ]. f3 H                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& u' a, E7 i: _/ v8 U0 q" b
        }
7 y) U- E& w$ Q! X( E6 O        // MMC5
% O( D( e' x6 u& y2 a. j, f1 X        if( exsound_select & 0x08 ) {: Z# m  T5 j9 U/ w4 s7 H: B
                mmc5.SaveState( p );
  C3 U. B4 F% C# h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' K  y, ?- o/ @* W# B# x' y" ?- G        }
% s2 i& {" [5 k. m  j: m        // N106% O& ^2 {  p# l5 @. H
        if( exsound_select & 0x10 ) {
; X4 {2 M1 M* ~4 W+ p& }                n106.SaveState( p );
* Y& L- i& Y, ?" {. `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 ^( w* Q4 A/ g/ v: a7 e        }
$ G0 q$ a1 _+ T# |        // FME7/ h- s$ Q& B% \' Q7 r
        if( exsound_select & 0x20 ) {
6 G1 O/ A& s% z& C$ P2 H/ R# q$ U                fme7.SaveState( p );- y! W( N8 t5 t- H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) S+ i6 \" F3 d
        }
7 e2 S6 |1 S6 t- Z6 }6 F) D. g% N0 a# ]. D6 P
#ifdef        _DEBUG$ K0 N" l- S( r% q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );. f/ \3 t$ b# W: C
#endif
% f0 t& k1 L8 I5 B5 w/ u, e- I}9 m  Y) C: m/ ]# O% j
) |5 `- a% g' e& `: e% W2 S. y
void        APU::LoadState( LPBYTE p )6 B; n* L+ j  K! C4 G
{; R" M! H8 n* I3 r3 a& \
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡6 E. C" B: q6 e5 x
        QueueClear();/ T9 k* [- I! Q, d7 |7 F9 R

) k; M& d' D3 C2 B        internal.LoadState( p );
* R5 B9 k: W. |; }        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: k; ~: q9 Z4 f
+ b+ Y& l- ^- D+ \8 Z- t        // VRC6/ q" E. y% I# A8 h* a4 d6 C- L( W
        if( exsound_select & 0x01 ) {3 x8 b; b& ?4 b! `
                vrc6.LoadState( p );0 E1 }2 g( U3 h' B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. o& J. X2 ~' z& X+ [
        }
2 w& E2 s! S4 C        // VRC7 (not support)
: s% N0 {0 t$ M- s6 W        if( exsound_select & 0x02 ) {8 ?; Y7 ~$ m# G( V6 d* S$ x& M) ?  i
                vrc7.LoadState( p );+ _) H! P( n1 C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
9 y) T( `4 ?4 D. r6 x2 A        }( w. v( H2 E$ T
        // FDS
7 f) @0 L" C0 m7 a- r( Y+ p        if( exsound_select & 0x04 ) {
) y. z8 ]4 h0 C3 f3 _                fds.LoadState( p );
" b1 J, S. J1 E3 d& J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) T; z2 x. j  Y  C4 ~- u        }
- w7 h* t) m9 O7 j        // MMC5
! k5 a( c3 Q. X5 H. }, t; D( J7 @) b        if( exsound_select & 0x08 ) {
9 F$ A8 V0 X& E4 i                mmc5.LoadState( p );& r$ M6 g. {, G
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, Q, s) G7 V" O* G& T! N
        }4 r6 }* j9 M# ^/ l  p/ @  u0 H
        // N106
1 J, B! B8 V5 h        if( exsound_select & 0x10 ) {# p% o; r' k2 X  L
                n106.LoadState( p );
8 F3 I6 D* Y" ^( v  ?& [                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% A& ~5 p& L% K" e        }% {& s6 S% W7 \/ i( `
        // FME7! C8 f3 s1 b5 F. f
        if( exsound_select & 0x20 ) {
5 h$ J4 o, h' w8 [                fme7.LoadState( p );9 V" U0 V. _' n+ \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 w2 t' Y6 p' v+ X5 [        }: X& b: W( Z. D5 v( X2 Z
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
4 V, U- w  T6 P( Y4 F可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* V  x8 S! @# V
感激不尽~~

7 ?/ t! P+ b! X$ c. t+ [4 X* z  c1 [恩 我對模擬器不是很有研究,; _6 o2 Q7 h: g6 S" t. ?
雖然要了解源碼內容,可能不是很困難,% b4 f' r& t: o, ]8 ]
不過還是要花時間,個人目前蠻忙碌的。0 p4 d% N& v% m  Q% h- b
; {- r# u% u8 w
給你一個朋友的MSN,你可以跟他討論看看,
  B8 W) k6 ?4 M6 s  I他本身是程式設計師,也對FC模擬器很有興趣。8 b  Z3 b; i4 n

! o% j+ G! \8 tMSN我就PM到你的信箱了。
; |! M! R1 L% J- d- z; {' S" [# s' K3 D. 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 发表 0 d% ]$ x$ r% ?& R+ ]
呵…… 谢过团长大人~~

: E, E- n# t+ T8 L3 {' l
# u2 E/ f; i7 s哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
( c+ p  E/ z2 m( M: @6 n' h团长的朋友都是神,那团长就是神的boss。

) k8 `) l& W# \- g2 K3 }& d哈 不敢當,我只是個平凡人,
/ N. r6 Y0 C4 |5 B, u" Z要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 }/ C, G( ^/ C. WZYH
% X, r& }) U! \QQ:414734306  G3 @7 b+ i; I+ L6 P: i/ M
Mail:zyh-01@126.com: k$ [4 h8 d5 M  _. S1 p1 N$ ~

. R/ N$ D. i! {0 a他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
- r! p+ x. v$ ^/ U* b" ?再次对团长大人和悠悠哥的无私帮助表示感谢~~
' ?/ R0 L+ x9 v. @
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-1 13:54 , Processed in 1.104492 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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