EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
/ r$ f# ?$ {7 c& x3 r8 F& X$ ~PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) ~6 l1 ^) [2 {* ^8 Z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 o6 _4 [$ U9 s' L& F这里有相应的模拟器源码,就当送给大侠了~~  ^5 p/ Y8 M+ C
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# C4 `/ Y9 E2 [: g能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: i9 m) g1 N# w3 M+ G: Q) O8 y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; d1 ?6 W( E2 d这里有相应的模拟器源码,就当送给大侠 ...

/ D4 |- I" Y+ q: q+ Q聲音部分(Audoi Process Unit = APU):
- ]. o4 ^* P+ e) d7 ^8 U" i.\NES\APU.cpp& \! y: b! l% ~9 _
.\NES\APU.h) r8 D" x! K; P- T" f. h
, l0 Z7 ?# {- h8 |

" Z1 f8 [  A& W" r2 P1 c6 ^影像處理部份(Picture Processing Unit = PPU):: x* t- m; @- e0 j" V6 H
.\NES\PPU.cpp' Y$ X% L0 D, i8 |1 ], e
.\NES\PPU.h
) H* d9 C2 i9 D) t- A) j9 ]% `$ ^; |. v3 X& ~( Y% ~5 v* d) J0 r0 y
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ h8 S; B1 |9 T7 m2 Z/ @: K
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
1 z8 [7 P$ ^. Z3 |//////////////////////////////////////////////////////////////////////////
1 _5 U( Y, ~& a//                                                                      //- C% T' D5 X1 s( A
//      NES APU core                                                    //
, V* Z- N) O1 d' ?//                                                           Norix      //. W8 M4 Q: j+ S; @1 L6 ~$ h
//                                               written     2002/06/27 //
( @2 ^2 d  o* q. `0 a8 E; q# ^( k//                                               last modify ----/--/-- //" Q  \0 p1 R4 m3 d( K
//////////////////////////////////////////////////////////////////////////1 p" r% H1 v" v- Q6 T  ~! p/ d
#include "DebugOut.h"
7 F# d/ \/ m% g! y/ Q) C( H#include "App.h"$ u3 l6 W. O# ]1 ?3 X0 y+ L; I& y
#include "Config.h"3 }- u. z8 n! }- ~
8 `: K4 B3 q  ?3 L- @# l
#include "nes.h"3 \9 n  K5 y% U/ w2 _: K/ A
#include "mmu.h"
4 o% p( i4 |0 w/ m$ o0 d5 j) @#include "cpu.h"; n4 \% V- |+ u. }  F
#include "ppu.h"9 A' P- Y5 f& W8 _* o7 s
#include "rom.h"
2 E' _& f5 v' x: Z/ k#include "apu.h"3 F1 }/ D! C% W6 o$ H9 L1 c8 D

+ u: a9 [$ `* t, V% L) Y// Volume adjust8 L' [& S8 o- v& R
// Internal sounds. f2 O' x# U# C" K
#define        RECTANGLE_VOL        (0x0F0)4 X1 I. S) l9 M( J5 A
#define        TRIANGLE_VOL        (0x130)
. f! @8 k( D3 F( H( T# ^- K#define        NOISE_VOL        (0x0C0)
' d! a3 F% I! Y+ ]8 P( c) r#define        DPCM_VOL        (0x0F0)
8 t" F* p3 Q- g9 x+ c! Q" V// Extra sounds, ^2 x2 i  M0 D$ k: c
#define        VRC6_VOL        (0x0F0): f& i7 a; g) l$ ~
#define        VRC7_VOL        (0x130)
5 a' }" w" o; a+ F2 ~5 N" g#define        FDS_VOL                (0x0F0)
( [2 E! U! E' h' t& P#define        MMC5_VOL        (0x0F0)* L, s2 i* b& ?' S3 Q
#define        N106_VOL        (0x088). k& u7 B  ^5 k  o0 M
#define        FME7_VOL        (0x130)8 y1 I! i- i/ B8 B. z. S! j8 {

+ b8 M) P6 i4 R" z$ l% B/ ~APU::APU( NES* parent )0 u$ s0 }: _- I6 i8 M/ q  x9 R
{* S! U1 u8 Y) _' [
        exsound_select = 0;2 t# n( C7 n7 b
/ N8 A: o  J, ]% g: L0 E% F
        nes = parent;
. ~, W; C+ N4 V7 y# N) z9 P4 Q        internal.SetParent( parent );$ E  g( J# k: {+ c/ z$ G7 S" u
; e- H( J2 R; o' Z
        last_data = last_diff = 0;
3 b) i- K3 u  d7 T
0 {- A: B( A$ f6 c& W  M0 P        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- d: s+ `" d3 k* @/ d$ q4 w: ?

: ^3 |3 e/ a( B5 U! o& O- P        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );% t) O( u  [8 l1 S- ^
        ZEROMEMORY( &queue, sizeof(queue) );+ W* B3 P. f/ s  e* X/ _/ k
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 R8 Z9 u+ Z0 f! F
! U. E9 h( t6 g  ]) X+ [        for( INT i = 0; i < 16; i++ ) {
+ d" m! M; x( b( s  T% ^7 ^                m_bMute = TRUE;7 T- a' E: b. N& ^! a- ]
        }
( j3 N$ B) B7 w) \$ R" a0 l; k3 s; S; Q}' Y, o$ Z# N# N% G
, J' {. R; @! s! ?8 G
APU::~APU()/ _% r- s+ l7 Q  W/ ~; Y
{
0 L6 `7 Y7 C( K* y" L}
9 P5 w6 G+ J! b- |- C% ^. Z  y" O; u/ T) y8 y" x1 K
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )8 h, j3 t8 n9 b6 t$ |' |6 R
{3 h1 c* H3 a* Q9 q# c- d
        queue.data[queue.wrptr].time = writetime;
# b/ `9 l+ h" ?) G/ T) i        queue.data[queue.wrptr].addr = addr;; b$ D& W: c, _  w  A, l) O  }+ R, f
        queue.data[queue.wrptr].data = data;- C" J/ N2 ~1 `
        queue.wrptr++;
: t6 Q" C9 s( ~; k& ?( A$ ^        queue.wrptr&=QUEUE_LENGTH-1;' v. q1 P+ d% }7 e, N# E6 r: v
        if( queue.wrptr == queue.rdptr ) {
. E. L" D# ]; I7 J                DEBUGOUT( "queue overflow.\n" );
# w2 `. S3 C* O: u        }; ^1 ^5 W# Y; e2 q  _/ O* n9 `% M
}
3 \0 g* S9 L. X# o5 P# Q3 u0 Y' T0 ]! D" t
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
7 T, W7 b: J$ M: Y" y5 z1 L{2 l& B* y8 E; t
        if( queue.wrptr == queue.rdptr ) {
7 A% }( J0 s: i                return        FALSE;9 }  ?* Y+ L' S# h! p. A' o
        }; d! s2 `8 {+ N3 r
        if( queue.data[queue.rdptr].time <= writetime ) {6 _  F4 d( |9 s
                ret = queue.data[queue.rdptr];
7 l4 b) w# K  b/ y' V2 h' j7 a                queue.rdptr++;
( I! c& l3 Y2 ]' d" e% }7 r! N4 G                queue.rdptr&=QUEUE_LENGTH-1;
; {) [8 T2 a* G7 g0 h& X                return        TRUE;! o) ?) {2 V1 V5 V
        }9 x/ \. M  |. }3 E: q6 ^
        return        FALSE;" r6 P# z8 L+ V- w# u. k
}
5 S1 P6 Y. B  G+ l2 ?7 C+ T; {
# n- s/ g( w9 C3 b6 M+ gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )/ U+ K4 A9 ^( N, X. n- e
{9 b; P/ c/ _! U
        exqueue.data[exqueue.wrptr].time = writetime;
6 j: C( x4 k7 s7 o# K; E        exqueue.data[exqueue.wrptr].addr = addr;- S- s) @# I7 k9 ?, x7 k) V6 _% L6 C
        exqueue.data[exqueue.wrptr].data = data;$ c. Z1 a- C+ b" c2 E4 r' I
        exqueue.wrptr++;
, |6 j% O6 d3 B& Y        exqueue.wrptr&=QUEUE_LENGTH-1;% B5 J, a: g+ l
        if( exqueue.wrptr == exqueue.rdptr ) {5 U- K$ T8 c" ^' m: q
                DEBUGOUT( "exqueue overflow.\n" );
# G# y4 Z( u0 z5 D/ W" W$ c        }+ j, _) h; d7 M0 c- c
}
2 T9 O) p# j8 k2 M8 e
7 [# ?# F. ?/ {4 M9 rBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )0 \1 r- H: z8 X6 n' C5 k
{3 z2 R) D0 s1 P- g/ Q& ~
        if( exqueue.wrptr == exqueue.rdptr ) {
5 F( R- G/ G% t$ p6 G                return        FALSE;
- f" f  \. D: D$ }7 B0 ]0 K2 }. D        }% q$ d; T! ]/ |) d( G0 o3 m& w6 O
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
' O5 [5 @7 k" J! |: k3 k                ret = exqueue.data[exqueue.rdptr];
) I  T- ]' O1 p: r( I$ l8 S                exqueue.rdptr++;
' v9 y% w! b6 l+ v# {                exqueue.rdptr&=QUEUE_LENGTH-1;
3 t8 R! E( E5 Q' C9 z- p* x! M; [. C                return        TRUE;
  ~# h( r$ m- f7 |( J$ A$ M3 f        }
& E( h; O( V0 y6 |' V8 f' Z% ]) t        return        FALSE;
% J! T' q& [; i}# ?+ s2 g6 h9 H; U

3 g8 N+ [0 s" x7 S( a' H. ivoid        APU::QueueClear()
0 B$ S' e! r6 N{( W4 X' j! |3 a# p
        ZEROMEMORY( &queue, sizeof(queue) );
# n- D0 Y% m( P5 a, \        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 i3 _' o, G4 k/ `! a}* i5 c$ K( ?4 P8 u; }' f# I9 P" W
; N0 ]& S( `3 m
void        APU::QueueFlush()
2 F; n% S+ H( G9 c8 H' H8 F{$ C8 e! U! P% J
        while( queue.wrptr != queue.rdptr ) {+ P5 y9 ]5 R& ?; P) ~
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );. ~$ l9 v) {$ ^5 g
                queue.rdptr++;
  Q; o: a+ h* w% h  d2 _$ a% w                queue.rdptr&=QUEUE_LENGTH-1;
6 Q, U& ^/ b) d6 W5 S& E9 ^        }% F$ Q  f5 H. v9 L9 C" E1 v

: N+ H0 ^1 V, M3 ]) |1 S2 H! k        while( exqueue.wrptr != exqueue.rdptr ) {' ^% s# @  h8 a
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
) e( c8 [2 s" S8 x/ \                exqueue.rdptr++;7 b' x. }  ?- u$ \' S: \3 t
                exqueue.rdptr&=QUEUE_LENGTH-1;
' i! E( o; L- q0 h7 F        }( _) L  s5 D/ T% E; [) U- K! t# `
}
2 Y& ?  N% @$ V0 T
' E  O+ ?0 C  M  ?void        APU::SoundSetup()
- I% M  Y  d. d- b8 L7 |( k{
/ B4 Q7 T- i, t/ W9 h        FLOAT        fClock = nes->nescfg->CpuClock;
7 i5 k+ `& s( ?# a2 c. z  ?8 I        INT        nRate = (INT)Config.sound.nRate;& t. }5 @3 B& t" ]- E6 {) T
        internal.Setup( fClock, nRate );% o8 J" y( `- }# q9 W3 [/ _
        vrc6.Setup( fClock, nRate );4 v5 q4 V4 C$ G6 x1 o5 i
        vrc7.Setup( fClock, nRate );; O6 r5 w6 G4 A, c
        mmc5.Setup( fClock, nRate );% o: O' Y% s  B. N7 ~) g; q$ G# |
        fds.Setup ( fClock, nRate );1 C* K0 K) J8 g* I) T
        n106.Setup( fClock, nRate );; d5 C8 w; c/ ~! O5 o5 K( m$ B& K
        fme7.Setup( fClock, nRate );
8 Y$ G* J* {% q}
5 m$ n: h  g+ G; U* s# u- k& y8 k& q7 X0 `2 y
void        APU::Reset()+ j% z4 F: L; G. {9 g9 z2 j
{
7 @0 W9 j7 b9 r  Y4 Z% N/ f# x        ZEROMEMORY( &queue, sizeof(queue) );
# V5 X- U1 W6 Q6 p) S2 Z  u        ZEROMEMORY( &exqueue, sizeof(exqueue) );- e8 m) H4 {$ s) g- B
4 \' x/ u) b  y) O
        elapsed_time = 0;
. V5 l( Y; l* I  e1 B; ]: E( B/ F2 a# S4 L8 ]( Z
        FLOAT        fClock = nes->nescfg->CpuClock;. l5 j" o* e) p* `; Z$ ~$ g' }+ L
        INT        nRate = (INT)Config.sound.nRate;
6 z0 w  w0 R( A- v        internal.Reset( fClock, nRate );% J1 P0 k) a. h# V3 P5 h4 f" H
        vrc6.Reset( fClock, nRate );( H) H2 T: K' T4 V$ N
        vrc7.Reset( fClock, nRate );2 |$ m; {4 e/ R5 @
        mmc5.Reset( fClock, nRate );% j) A1 y  o. Z
        fds.Reset ( fClock, nRate );
& J3 A6 E' j( j9 m1 ]4 w        n106.Reset( fClock, nRate );% }" _( @! A( n
        fme7.Reset( fClock, nRate );! e5 \  l7 Q9 w6 W& O8 K1 V
' Q& b, D% A! f5 [/ a: o* h
        SoundSetup();
8 {' R9 v7 X& C: u0 u}( h6 K8 ]9 l6 N+ W& c" Q2 l. b

# N3 a6 @6 T. x+ W0 ^void        APU::SelectExSound( BYTE data )5 x! G+ j2 H1 h4 m
{: W6 k3 C. Z- E6 ?- Y; }+ S2 j  |5 `
        exsound_select = data;
1 J% ]" o9 d; z* q8 D}
% Q7 F4 s  s$ E+ U- J, `; Z) @8 F( X" E+ U
BYTE        APU::Read( WORD addr ); g4 P6 [5 s; a" {* l
{
' N) g1 ?" W% u0 E4 k, [7 f1 M        return        internal.SyncRead( addr );9 P; W( z2 H0 B. X
}4 w8 o# B$ T# a! ?+ J
/ k9 C9 H  N4 t" ^/ b: N  X5 |
void        APU::Write( WORD addr, BYTE data )
$ ~9 [0 P# F6 s7 j: j+ _7 p{& Y" g1 Z* T$ M' @, |  Y  Q
        // $4018偼VirtuaNES屌桳億乕僩7 m1 G. x4 Z4 e5 D. X# i$ D
        if( addr >= 0x4000 && addr <= 0x401F ) {- P# u% O  j+ D; P& W/ W  r( P2 c
                internal.SyncWrite( addr, data );! F3 r& l+ U7 Y: v
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& W. v* ]- k0 U& |
        }
$ Y) q2 R" h: U}
1 c' _  }: V+ |* u6 r1 w# w" U6 C& H5 V* k
BYTE        APU::ExRead( WORD addr )7 @% {5 ]  }8 x6 W( D
{
  u/ G7 A% }1 k2 K  U. LBYTE        data = 0;
2 N- l, z; ^# u" M+ J* ^2 E2 p# i8 o
        if( exsound_select & 0x10 ) {. M& ]# p" m) n1 M$ {# ?
                if( addr == 0x4800 ) {
! l; w( _/ w5 j( {2 K7 S& @! ?                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );# N/ x+ Z* r! Z
                }
9 V! i! A& v$ R0 B        }
# S4 T# K) d; g        if( exsound_select & 0x04 ) {; h6 r2 U$ D% H. p5 W1 m+ O
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 Y" B4 a) J6 Q                        data = fds.SyncRead( addr );
4 d2 c! Q9 X4 `" i6 L3 e                }
  T$ e) z- Q' c3 L: L+ g* |        }/ M% n2 n' T1 i) G) p
        if( exsound_select & 0x08 ) {! w% x0 D) H! u; }
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 k; R( ?6 B9 B
                        data = mmc5.SyncRead( addr );
$ O* r# i) Z8 d, e) w. M, s7 g                }9 Y" G! W" X$ w
        }
) m& H& Z: h; r' `8 Y
$ O; t% {! N5 Z/ j+ M  }' \        return        data;" ^- d7 O1 Z; G* A9 \6 q  m
}2 n; w* w: e* m! m& u! B, b) a& Y( g

" @3 o' i0 [* D7 Q4 Fvoid        APU::ExWrite( WORD addr, BYTE data )
: y1 I& E. }# Z" j$ b$ X4 K{9 o- l! ~  R, }% U9 s7 z' ^
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" R. Y* j/ X6 [) z0 Z/ n  ?5 ~, ]+ N( z& d' i" `  G5 G
        if( exsound_select & 0x04 ) {6 `! N: [, N+ d* O
                if( addr >= 0x4040 && addr < 0x4100 ) {0 R, r! Z& P% c5 r! H% `: e. w2 e
                        fds.SyncWrite( addr, data );7 K' u/ Z$ b+ u. R3 U
                }& f0 Y+ U4 J: O  E7 Z& k5 _7 p! k
        }
9 t6 g1 ?5 o  t& h2 V) {/ k5 Z. P, L* e
        if( exsound_select & 0x08 ) {
' p5 @- w( v  e# r7 w, I                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 ]( o. e% u  a                        mmc5.SyncWrite( addr, data );7 |8 l4 Q+ P: |0 ^. e3 Y1 x
                }
8 Z# i/ X1 p1 a( o        }: k$ h( t% K& r! B3 ]: V. l8 Q
}
7 z; \& h+ D; B+ ^4 D% t6 c! P
/ X$ H! p, K- P9 L6 b( e4 ~void        APU::Sync()
" y4 G" z1 n* m- e, c0 E{
; ^1 q, g# n' M9 }$ u: w2 S0 P6 `1 d$ [- w1 f}9 g+ s1 A* J/ a- c
& b4 }5 H4 O2 ?, a
void        APU::SyncDPCM( INT cycles )
0 P4 o1 j- ~2 M5 [6 N7 F& a5 n{
; N0 n: q: ?: Z( a4 V        internal.Sync( cycles );
8 G% ~3 V# ?: Z+ [3 W1 G- x+ H5 o" J6 Y' A& ~7 a9 C/ h
        if( exsound_select & 0x04 ) {. G- o6 T' y# Z% t$ z' J$ N
                fds.Sync( cycles );
; {  b' w0 B. s2 Y  {! ~& m, R7 C        }* W) T0 X4 E+ z4 t; t/ \; M, K
        if( exsound_select & 0x08 ) {5 |1 e+ I; |+ v3 r- Z$ H5 @# @
                mmc5.Sync( cycles );
7 _: {0 Y7 C8 D4 {" \1 n& ^        }
4 [+ u% E4 ^. K. ^5 q}
1 y+ f; B0 j% ~8 C* B9 Z7 V. v' H. |0 N0 h# v0 G! T6 R: y
void        APU::WriteProcess( WORD addr, BYTE data )/ X% i+ C! t+ A& H9 S+ y
{
$ Q' W' c# ?* S3 u9 z  |0 }        // $4018偼VirtuaNES屌桳億乕僩
" w0 L* A) M7 u/ B9 y7 m, t        if( addr >= 0x4000 && addr <= 0x401F ) {! r% Q- y; H" s2 Z& U3 h
                internal.Write( addr, data );% X. ?9 k2 V+ d9 s5 I( V7 _: e
        }
7 Y: A% F, ~4 o" t( }5 k}/ O* I7 c  H7 h$ T) E0 B
! [$ d9 N; R) ~* a* W' D" x7 U
void        APU::WriteExProcess( WORD addr, BYTE data )/ p) d; ~: B+ `1 `% v
{) l5 T' o# S5 k
        if( exsound_select & 0x01 ) {
  `( w5 C" q3 X2 Q+ B0 G                vrc6.Write( addr, data );
. {3 t! _5 x- c* k" u' n        }. q& ~' ~; N: D# k0 P2 C
        if( exsound_select & 0x02 ) {
8 J/ z8 y+ i& q* B0 s" L% G" \                vrc7.Write( addr, data );! A% o1 H: q, X- z  Q
        }! D4 B. F, W8 e' b) W6 ]
        if( exsound_select & 0x04 ) {; g! N' ]. I3 I3 K$ h3 D
                fds.Write( addr, data );
% ^+ l7 n( O* O1 f5 Q' J+ }        }+ Z  m  g/ \) w5 R& H, b
        if( exsound_select & 0x08 ) {2 p& P* y7 v9 \+ M1 H/ d+ t7 b
                mmc5.Write( addr, data );
- P! u# q0 D- m: \$ o6 z        }
0 H7 l* f$ q8 Z% N1 J# e        if( exsound_select & 0x10 ) {
3 k3 G0 k: g8 W) v3 O8 w; V: I                if( addr == 0x0000 ) {5 B8 ~4 s: E9 }) ^6 W. ^/ I
                        BYTE        dummy = n106.Read( addr );
5 ^( V  k0 o% ~7 }& Z                } else {: m- X! q  n+ X/ C* f8 }6 N8 E
                        n106.Write( addr, data );" r0 S, @, A0 A
                }
. g# {+ D/ z7 B2 w  c6 ?4 S% x% s        }
" R( o8 O/ P1 E4 o' Z        if( exsound_select & 0x20 ) {8 o; H+ O! `% T  f; d
                fme7.Write( addr, data );
2 K- r* \8 G; Y3 l# j        }# ~8 X1 }0 Z9 T  G
}% ?  b( f# @" c: ~# ?
2 {7 ]6 ]$ i) \2 L9 M& k  E, _
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& @6 e7 p+ d- ~' P, Z2 S{
8 k( N9 j  S- t0 ^' f- Y& P: L+ IINT        nBits = Config.sound.nBits;' r0 S/ N4 w6 h7 E" z2 i& R6 \
DWORD        dwLength = dwSize / (nBits/8);
9 A7 c: M# r2 K  y7 R% X9 A5 xINT        output;
$ q6 o2 W1 ~8 d) r1 O3 `8 pQUEUEDATA q;
# `- C4 U% X2 B6 e8 cDWORD        writetime;* l; o1 k* n( ~& C

( {2 c4 t. _8 f# K$ P7 SLPSHORT        pSoundBuf = m_SoundBuffer;$ \& }( i; I* z0 a$ o
INT        nCcount = 0;; _  E5 q2 H; C9 o

3 g/ z7 ]9 @4 oINT        nFilterType = Config.sound.nFilterType;
; {, g0 R8 A: L
' `; r$ ^8 g* O        if( !Config.sound.bEnable ) {9 i) X. b9 H) V  X1 a9 V/ k1 q1 m
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* {: y- f1 i  j                return;4 S/ k; E  i4 }( a
        }
8 h) ]  L2 A- i
" L. G8 s- Y: }/ d% r4 D+ @5 q        // Volume setup
" I/ w$ Y+ i6 t        //  0:Master& N0 y* A3 Y( y/ z' ~9 g
        //  1:Rectangle 1' E6 `  ]  C  \& [# p7 f5 L8 k
        //  2:Rectangle 2
9 a9 Q1 }9 R( E        //  3:Triangle
. S% a. u. A8 _1 Y$ b+ a        //  4:Noise9 O  J# A% k( Y
        //  5:DPCM) E; ~) l, ^+ n0 ?# j; q# q, Y' T
        //  6:VRC6
/ n4 L+ o( e3 Y+ ]  J        //  7:VRC7
3 o6 Z0 [& ~! k* C+ j5 l4 [        //  8:FDS1 U2 b7 l* N- k& d0 n3 X: H
        //  9:MMC5
/ X3 ~( G5 D( V+ a5 r        // 10:N106& @1 I- \$ x( P$ x
        // 11:FME73 Y) g3 v& |4 e! Z. Q2 A
        INT        vol[24];
' h* D' O8 r% f( m0 `. E0 k. y        BOOL*        bMute = m_bMute;& R% N0 }/ Q& F$ ]
        SHORT*        nVolume = Config.sound.nVolume;+ N7 b+ l$ @% B+ |: ?" \( e
" |" G3 _: ]; Q- ~& |
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ ?+ m% u- q" b3 A% P: t' m
' U( F; b; H+ Q  d- ]8 U: g3 P# k) j3 W        // Internal
! K9 _. h. X. k9 |' [" D        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& `2 y1 N' j; p3 v
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
! U5 B$ a3 j3 q- K  Y+ [9 _8 Z        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;% [# C( J1 x1 Y$ b, s1 H/ L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 P! C, \0 ~4 y8 A        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
; T; f# f* G# N! u  k! l& O: _
7 U8 @" N6 T( `4 P7 J        // VRC6" R4 E8 x, `6 i  i& D
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  \. _; `7 f& h1 D4 Q4 n! R$ Y        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% O8 O* z  T7 S, E* k
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# `- `3 @0 C3 g9 D+ G" J5 X0 c# A+ `" ?0 U5 h2 X1 n
        // VRC7  k, \: B. w8 H( c# Q: s8 V1 }: q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% ^1 y0 L8 P! ~! g, X' m4 n
' a) z2 Y5 Z8 z" S  F
        // FDS
1 c1 j3 o8 R7 [1 s# z( _$ w  E0 u        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
8 J/ R/ f6 y! \" J. b) D2 K
- b( s& h: l+ f. E$ i3 U) x        // MMC5" ^, Q' ~5 ^+ L& c' |
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  Q( f3 g2 O9 g& u* F" W; K  b3 s
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; h5 D4 R6 \/ P( P) {        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% H" w* K+ g. M! T

$ E) e# T* r$ m/ M/ i        // N1064 n8 n8 _! M2 w4 a9 R0 w. v
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! A( M4 v: @# o* t
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& l" S) I  _. |7 x% y$ \: x
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ H& R- r6 C$ [4 H
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; h4 w9 ]7 Z' P1 I% M7 h        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! u' _3 K0 a# @% ~7 b9 V2 S        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" E1 n% u3 |6 K        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 _7 x9 M6 r  m) i6 [% A0 g
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 a, L. {3 {6 V

( \5 _3 x9 K8 Z        // FME7! V; u! s" w. h# k+ e
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 I, W: e/ p% G
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( V- ~' m* z1 p( o( t" U( [+ a        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 z2 E9 ], m8 Y# s  \7 Z7 {

% W5 D7 v  V( p' A//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% b* ]0 B3 h6 @7 j7 O        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 }9 d) N9 ^6 K8 e2 q" m
7 o! {& Y" o% ^% ?: j# j        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 ?2 L- E& F) I        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: `3 F' G9 ^/ k" s6 T! K  G                QueueFlush();
6 a! h, _6 f/ U3 u8 C4 r+ I+ Y9 u        }3 m+ |" c0 u4 l& Q2 F
! m' r% g' c% `& I, o
        while( dwLength-- ) {
' o: ^; {1 o5 X$ B1 I                writetime = (DWORD)elapsed_time;
& }8 ?  }  C. Y2 p& N6 q1 A( [+ C/ I6 n9 b: {- @  {
                while( GetQueue( writetime, q ) ) {
0 y; a; I1 `- r' Q3 X                        WriteProcess( q.addr, q.data );
$ S3 C4 F+ A/ |& e+ P: q, k0 L                }' A( D7 s4 w$ F
' J3 a2 h1 G4 z$ Z8 u  Z( m" |: j
                while( GetExQueue( writetime, q ) ) {
% L6 l, y; u7 r; G                        WriteExProcess( q.addr, q.data );/ w( G2 ^0 B8 A7 }9 H8 M0 _
                }
; {9 j$ |7 T1 z3 j7 D8 L. `. {" ~5 D- M: B, T" E* @9 V8 L* s
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
9 A( t) O% E% v* }& ]0 d& j                output = 0;
" r7 X6 U# t8 ^2 _/ ?                output += internal.Process( 0 )*vol[0];' E: m  P# a, i  Y. S; i
                output += internal.Process( 1 )*vol[1];2 ~, a  @9 r) P' e7 y
                output += internal.Process( 2 )*vol[2];
5 Q: ]: Z" n* G2 f* `                output += internal.Process( 3 )*vol[3];% S! u" P% I2 i
                output += internal.Process( 4 )*vol[4];
8 f0 H( Q  j8 E$ ^1 T/ D$ z% {) I" W( i; C9 w& p- `: g
                if( exsound_select & 0x01 ) {8 S( n2 C/ o/ N
                        output += vrc6.Process( 0 )*vol[5];
8 P# I3 o9 a$ z1 ?$ _                        output += vrc6.Process( 1 )*vol[6];0 X  c8 H$ K; K6 H6 m8 f3 {
                        output += vrc6.Process( 2 )*vol[7];
" |* n- u: G8 u0 ~2 E                }
% h2 z+ r. @* O+ U                if( exsound_select & 0x02 ) {
) ~# N2 ?' g4 ^3 b. z; M6 A' J4 P                        output += vrc7.Process( 0 )*vol[8];
0 j3 d, h, u& o8 @                }( e% {$ M: H: u  N
                if( exsound_select & 0x04 ) {6 R1 t/ y- A, }4 V9 x
                        output += fds.Process( 0 )*vol[9];  F, N/ c/ I" Y' S
                }! u0 F  d8 g7 L
                if( exsound_select & 0x08 ) {
$ }9 C/ s  B" \% C9 E! C/ K                        output += mmc5.Process( 0 )*vol[10];( W5 g) p/ _1 g% W* ~$ Q, U
                        output += mmc5.Process( 1 )*vol[11];' y* S3 D+ U8 t! g5 }- `4 ~0 f  z  V+ g
                        output += mmc5.Process( 2 )*vol[12];, D% c6 K5 _! Q! P
                }0 V5 @4 Z! R* W6 U2 n: [
                if( exsound_select & 0x10 ) {  ]3 b$ ~& n! l! K. b! a
                        output += n106.Process( 0 )*vol[13];
# V- e6 t; h9 J0 g* ~                        output += n106.Process( 1 )*vol[14];
5 B0 I1 b3 K  K8 k! m  L6 T& T                        output += n106.Process( 2 )*vol[15];
  g, H2 ~& B/ h+ P0 L6 I                        output += n106.Process( 3 )*vol[16];: `- p# Y5 H* ^7 t# a/ Z
                        output += n106.Process( 4 )*vol[17];8 A- Y" b; n1 A5 ~
                        output += n106.Process( 5 )*vol[18];
8 K0 |3 [/ O2 L( S8 T, p; ~                        output += n106.Process( 6 )*vol[19];4 E. t$ Q  r% R  Q) ^; Q
                        output += n106.Process( 7 )*vol[20];# g" j; s6 _: `, W0 [
                }( Z' N! _( G, E  B
                if( exsound_select & 0x20 ) {
. W$ P) E" X4 N& O9 |                        fme7.Process( 3 );        // Envelope & Noise
* w* d1 N; R6 E& A6 \3 V$ l                        output += fme7.Process( 0 )*vol[21];" ~7 g5 u9 K: r& k" A: p& x% F6 z% {
                        output += fme7.Process( 1 )*vol[22];
: u4 w: I1 c. T! B% A2 f                        output += fme7.Process( 2 )*vol[23];0 g8 |; L* j& v
                }
( T9 f, w; f) O! c$ H6 a' @
. H+ I2 g2 i( d) u" ^6 u                output >>= 8;
7 f  a$ X( v" X  }; N7 y$ F
  Z% X% s% X* Y' S# k                if( nFilterType == 1 ) {' O/ i" X2 _# {7 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
9 V; e" J" K5 E  r" C                        output = (lowpass_filter[0]+output)/2;. z, I4 t3 N# ]8 R3 v5 N4 Z5 U2 G
                        lowpass_filter[0] = output;
3 N4 O& H" b$ _- s/ a+ t                } else if( nFilterType == 2 ) {
9 c) Q) L( m. x+ B8 y1 T1 F" E                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)5 ^4 S, U+ \. t0 e# u$ d
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
" h3 F6 a" R( A  a) \6 B                        lowpass_filter[1] = lowpass_filter[0];
, W: D" V4 \2 u7 @& X0 Y$ A                        lowpass_filter[0] = output;4 g" [- b4 `: f3 n9 z# [1 Z2 d
                } else if( nFilterType == 3 ) {
7 ?% N* J: `- m1 U# F6 r                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
8 U) ?/ C) g% s' N* u4 ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;5 l- R7 x% j" w
                        lowpass_filter[2] = lowpass_filter[1];8 T  @( ^+ B3 s, ?' B
                        lowpass_filter[1] = lowpass_filter[0];% t8 W' b" t# O
                        lowpass_filter[0] = output;: }6 ?3 X, l1 y1 P, z
                } else if( nFilterType == 4 ) {1 B! k- M/ j* v! v
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)9 t& A% T# o. Q; g& L. i% y/ h
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 j. X) P/ Y% J/ q& E  I                        lowpass_filter[1] = lowpass_filter[0];
* v. v* q- z' n* d; i8 Z% T                        lowpass_filter[0] = output;- I# S1 t; ^% X
                }8 i# D* O+ ~) h( r/ ^
+ S9 D! [; q3 A* x! ?% _
#if        0
* M$ Q. d/ p* |# u9 [/ Z                // DC惉暘偺僇僢僩/ h- m" F# l/ t  r8 J! r
                {* M3 ^+ b8 {3 @" I4 ]+ M1 e8 k
                static double ave = 0.0, max=0.0, min=0.0;
; B1 D; K9 r! n                double delta;% Z1 x) V8 @  C; R+ p2 L# y
                delta = (max-min)/32768.0;
. C, f. W0 w8 k- G                max -= delta;) w4 F3 c0 M$ J4 L
                min += delta;  r; b' d+ h, B& m8 ?4 p& d
                if( output > max ) max = output;0 o+ ?4 C0 S( q$ R, R) P& l
                if( output < min ) min = output;7 U) a# _" I, g4 Q" b
                ave -= ave/1024.0;
' F' z# T! t  X5 ]/ ]                ave += (max+min)/2048.0;
5 d$ ^. f  k, B% o+ d  K0 l+ R; D                output -= (INT)ave;
% P: D+ c8 R5 }; |) x3 A3 l                }$ d* o4 ^0 J. d4 K) Z+ z
#endif$ H. N0 s8 u- A; Q
#if        1
& V) V; L7 c2 u' c                // DC惉暘偺僇僢僩(HPF TEST)2 l3 [" m5 F- I+ k; W3 u9 y
                {
' r, s, o* o/ f, n. u6 \" ]! h0 D4 Y//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
1 Q8 G2 L9 [6 J1 M+ f                static        double        cutofftemp = (2.0*3.141592653579*40.0);, p! c9 C4 y3 M: V
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ j  T6 m. `0 h                static        double        tmp = 0.0;7 b9 U- v$ T' W' a+ a" M( K
                double        in, out;
" }  X0 D# Q8 g2 t3 e0 t; c( Z
1 l' T' `* M% u                in = (double)output;* W3 w( r& f! k, v$ W
                out = (in - tmp);
4 H3 f0 ?) ?  F5 o1 }3 Y3 O                tmp = tmp + cutoff * out;6 U$ f! M9 L; b9 f1 t. P3 O  g

/ q) X/ ~) j2 c0 I2 H1 G; y                output = (INT)out;0 I' t" q% z: \  E0 s; |, U' \+ J
                }
+ w6 K' c# i0 q; G0 n4 W#endif
, c4 w8 l2 }- C% @$ c#if        0. k0 E7 k4 w2 A$ Z2 j; X
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
8 `& b$ ^1 M; F5 i4 j                {
$ x" N  W8 _) O* ]! C# D                INT        diff = abs(output-last_data);: a: ?! ?3 J: K" V  N% R* c1 B! O
                if( diff > 0x4000 ) {
* f# N% {  R: t6 \& [! }                        output /= 4;) j) v8 P: U4 Y+ m- Y4 Y6 P/ ]
                } else ) ]" M# _7 Z+ F  v
                if( diff > 0x3000 ) {
4 K. \+ Z% k& i7 ]" {$ K8 Z( s                        output /= 3;
& ]4 S% i. R- _( s/ J9 u3 `                } else, f. k1 m9 G- D& N
                if( diff > 0x2000 ) {+ u! S3 M  q/ d! e: V5 a4 Z
                        output /= 2;* x6 ?( X" d* f$ Q
                }
% |6 D6 D8 k  D8 e  H2 I0 g                last_data = output;
$ s9 r1 H) \: j& k* E) e- y3 x                }
8 n+ Q# [/ ]/ K1 D  r#endif
! S" ~- D/ ~7 |7 v  I$ U% l                // Limit( T6 E) M0 h; v# G1 f
                if( output > 0x7FFF ) {7 }7 m2 `- W6 y7 K6 ~
                        output = 0x7FFF;; ~; h# }2 J5 [/ {0 X
                } else if( output < -0x8000 ) {9 h9 _  d: `+ s* }; y
                        output = -0x8000;
- w' B- O/ U! n4 s7 K                }
  F1 l9 G) |) a5 a. G/ v$ ^
  ]" G8 ?3 n8 V# M8 C9 V6 [6 E% P8 c6 R7 d                if( nBits != 8 ) {% P+ K8 U5 a. v  ]; A0 N, j- W
                        *(SHORT*)lpBuffer = (SHORT)output;
- c* }9 e, S, t# w                        lpBuffer += sizeof(SHORT);3 l9 q, A8 [4 P% C5 V) m6 g
                } else {
- a; A2 c: v$ R8 Z3 Y                        *lpBuffer++ = (output>>8)^0x80;
" D" y" [: w* O8 |8 F) {. R7 H0 E7 F                }8 }" i* Y& T4 V1 Y) E3 O. O
* {3 a; V  R/ G
                if( nCcount < 0x0100 )
1 e/ T6 D0 X, n& H                        pSoundBuf[nCcount++] = (SHORT)output;
$ K4 ]1 _6 K, H% X  P" d" @! A
//                elapsedtime += cycle_rate;& n$ y- a' J8 w& p
                elapsed_time += cycle_rate;9 h6 E% r  ]1 R1 h
        }" E+ l/ m2 l% {4 J
$ ]+ z$ x! U7 S9 v
#if        1& N) @2 |% Q! a
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {. V2 I& _4 v7 R" I
                elapsed_time = nes->cpu->GetTotalCycles();9 [( e6 e, \$ B5 M& k( K+ [6 W
        }
7 R+ V0 d& ]# l! Q6 J        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 U1 F6 n: V1 R6 T                elapsed_time = nes->cpu->GetTotalCycles();! I( H3 M7 J: K; Q4 g( @1 y; e
        }4 @" W4 s& H! d$ o; O7 e
#else
$ h1 r* I+ `, E; y, i        elapsed_time = nes->cpu->GetTotalCycles();$ Y+ w. f" J. B. C- L- _7 k
#endif  n+ G' |+ X# N5 S
}( Q& s: U/ P8 x5 r- R: n
5 i+ ^% ^1 K' \7 J7 j2 {
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  b! n8 Z5 m( {. n: R$ n$ i
INT        APU::GetChannelFrequency( INT no )
' x' B- W0 B( L: K" Q( U; @{7 W/ q$ C/ S' c) X, J2 @6 j
        if( !m_bMute[0] )
# q& T: C4 w( f: w, {                return        0;
. g2 t9 t. B' x5 o+ K, O# G; A, k2 m
9 C1 ~- H8 Q% C) I, L# i) V, g        // Internal
- K2 I8 w8 `& r( ~        if( no < 5 ) {
! i8 {. w" a  D% S* l5 p                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- o9 \. {+ o# u- s& Y, ]* h/ b        }1 S$ d( G/ c" n% N0 f9 i: d
        // VRC6% z' b7 H$ f# E
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {1 E& {% r( c8 m. R6 I4 c4 k$ h
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;+ ^( n1 G( a; x7 m
        }
3 N0 D+ f1 ]4 I        // FDS
" @2 ?0 r2 M% o+ f" P9 r8 e+ T        if( (exsound_select & 0x04) && no == 0x300 ) {( H/ I; |7 M0 {; G- p+ ^4 k6 \& M
                return        m_bMute[6]?fds.GetFreq( 0 ):0;! H2 B: x  Y' N4 t# O1 U! j2 H" p6 W5 {" U
        }
1 c- h) c7 \5 A' L& ]3 A4 O' o        // MMC5& F- I% L  M/ E! A# Z6 ?- E: ^( L
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {& g$ H+ _/ c6 d2 g
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 @5 c2 p2 G$ O& Z( r# i4 k4 F
        }/ H6 l' L) I" C* Z- U0 Y9 \7 p# _
        // N106
5 `' F- q- S) J* h7 _5 e+ P        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 P. E& W5 j3 [% m% T4 D) ]# t                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;3 R3 }/ Y" d; E  T# x& \
        }6 P9 j- |, Q( ]! z$ v. [
        // FME7
4 Y8 ]+ o* O( U! {+ E2 l        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
, f9 s% J' s1 |) h  {6 `1 g                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;* Y& D% f2 b3 u$ U/ M& ^) g0 K
        }
& y, ^$ u# O5 ~        // VRC7# }0 W7 s, N# X+ x3 t1 H4 j
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {/ G2 d% o, A% m  O
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;& Y3 Y! K& V! w8 H; b
        }
# I5 ?' J0 o8 E        return        0;
* ]1 Y& n: x( U- L; g}
. E, L9 t! @, J1 x4 r
3 s* [4 B5 }1 H' j! y# u' k// State Save/Load
3 U& Q3 c9 a# {9 @- J* j) Z3 i6 y0 G! Mvoid        APU::SaveState( LPBYTE p )+ E6 R" a- Q1 `& B0 w- L( j
{
( v" B/ K. ~9 Q( D7 N#ifdef        _DEBUG6 y1 M& P9 R* k; ?; y% o
LPBYTE        pold = p;
5 z! j8 P2 g( |+ w  x+ A, o#endif  S) u* L2 g2 k, [

% p( F# u, \$ V* @        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
6 H) @8 e' D& b        QueueFlush();
$ q) v2 {4 Q6 u) t5 a' `7 j; h( p2 }5 R* e
        internal.SaveState( p );, d* B  d9 H! ?
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ `1 e6 `" y; F" t! y# s* e8 X' n$ a, }
        // VRC6
4 u$ S0 @% r# G7 |7 |# Z        if( exsound_select & 0x01 ) {3 H: k: ~" x8 [) g& ~% w) z; _
                vrc6.SaveState( p );2 _% ?  Y" [1 [; U5 h6 M2 j+ m7 F1 G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ X& j6 l" K% `& C( r4 x+ v        }
+ A7 G$ f  ?8 G9 m( M/ P        // VRC7 (not support)0 H. \/ b/ z' I) u
        if( exsound_select & 0x02 ) {
) g! y- J& S0 }. _' e" b4 m                vrc7.SaveState( p );& k. a8 O4 e/ D/ {, Q- d9 B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! F% u) O5 J4 l" p* Y        }
: ?3 d' {2 S7 ]1 n: Y  A        // FDS6 L3 x& L/ O; v( H: O
        if( exsound_select & 0x04 ) {% ~2 v0 L% O4 {2 A# m3 x+ t5 `
                fds.SaveState( p );. v' a. E/ N/ r* D1 u, j
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: u- C# l; V9 s2 i! u+ V6 K        }  m3 ]' t, I4 ~. k
        // MMC5% i% g( ^' ~8 x
        if( exsound_select & 0x08 ) {
* q* c+ b$ t* I: ~- f4 |, {' |" F                mmc5.SaveState( p );
* s4 f% g: @7 w, P% Z8 V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  z2 d7 J( h. s' m4 n
        }
+ J' F! K" l1 @, z/ W& _        // N106
; \- q& K% g! l        if( exsound_select & 0x10 ) {  n( D! i+ i1 j! P, u! B
                n106.SaveState( p );
( q8 h+ w( K+ @" m, V, K5 [                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; D9 N) ^, L# @1 l
        }
3 i! k" V1 l+ c1 h& Q4 J9 T! N        // FME7
3 S1 O8 N" ?8 M! {5 j" T0 s1 f        if( exsound_select & 0x20 ) {
6 i& n" j7 f* X                fme7.SaveState( p );( e7 Z, \# J& Z8 i, F0 D, m
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ O& q$ Q2 q7 D% `9 C. f        }
: W4 N' k9 ]2 n5 J2 K$ J8 q; z. l* y/ C/ y# `' R
#ifdef        _DEBUG( y+ |+ L2 P$ K1 D
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" C  D  N, O( g6 _, B, o#endif2 Q5 g9 V- G3 z* K
}
1 R( u0 R( p' ?& k
8 G: `0 ]3 h4 b! `void        APU::LoadState( LPBYTE p )
- t+ ]+ ]7 d; V8 Z2 F% J{3 |4 a5 ^! Y! Y) P7 T* N7 p, U
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡4 [- h1 \' G3 P6 q7 m, `
        QueueClear();6 N# n) r; V) V7 s% M' S* [" c! E

: L$ ~6 T0 ?8 _3 P: t        internal.LoadState( p );
% P6 R- ~$ p+ B/ A- E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 d! V7 y' C' L5 Q9 F, t
0 n! r. |/ _/ C4 {        // VRC63 l1 M$ C  }3 T. r& b. X
        if( exsound_select & 0x01 ) {
4 s. C- i4 A1 N                vrc6.LoadState( p );
& O! s+ ]5 s$ D2 a" Q/ [                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding- q& o7 H! R/ G- d  w0 m; Y: k5 v
        }
( F, q: @2 N5 @        // VRC7 (not support)  g0 d( ?/ G$ v2 f% m8 p( x
        if( exsound_select & 0x02 ) {
2 G+ v" @2 y7 B& _# S' m! ?& C, _! G                vrc7.LoadState( p );
* L5 b% \3 S( T5 ]9 }                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: p7 h: g, t5 z, [+ C8 {        }
- ~, Q$ ?9 O! N9 ^# H; T, }        // FDS, Y- \. ]+ x0 |& G1 l2 _( ^
        if( exsound_select & 0x04 ) {* y$ t' ~, [0 M1 k- ?% H3 f, g4 J0 |0 [
                fds.LoadState( p );
9 g6 D" i$ o8 d                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# Y, \/ K1 z7 g4 }( z" ?' ?
        }
/ _$ v" ^# }" V: b% a        // MMC56 \5 w; l5 R, d
        if( exsound_select & 0x08 ) {: x0 R2 y8 q$ i
                mmc5.LoadState( p );
' f& W3 N# c5 |5 e! u+ B, d5 X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 f- I1 S: k( B5 v5 H# K- B
        }
3 g" A, {3 j0 w, r0 k* p+ J        // N106: `0 R1 R; F0 m
        if( exsound_select & 0x10 ) {# e# `; `% v, V1 E7 S5 y
                n106.LoadState( p );0 j9 k  J( Y8 F0 A! y" ^; C/ V
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 v, J4 Y/ u# I$ n        }
! V+ }) H2 _% p$ m; a/ b- @        // FME7
8 t# J0 m9 D0 f: y        if( exsound_select & 0x20 ) {* j% o; z% F3 a( k# ?$ M- ~
                fme7.LoadState( p );
& o( B" f5 M+ |% v# a" ?                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 J% p5 y* W( E1 s' h1 K8 ?
        }
# _9 j+ A4 T' h, g0 o}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 . h, f+ M1 _$ Q) M9 z# M  Z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, e: n& n# T' L4 }  `/ I4 P- r4 {
感激不尽~~
# I4 _" b4 o; N# r" l
恩 我對模擬器不是很有研究," E! S, u7 S9 H. P$ h
雖然要了解源碼內容,可能不是很困難,
5 d6 C7 \3 \1 j9 v9 Y3 r) Z2 h不過還是要花時間,個人目前蠻忙碌的。+ u2 M4 M! Z% U

, E7 D: }# m, G9 k& V給你一個朋友的MSN,你可以跟他討論看看,( y3 d, R2 z7 u0 n' m
他本身是程式設計師,也對FC模擬器很有興趣。: z4 g) {, N6 B8 {5 o; N3 E6 C

: ^. G4 D4 v6 Z) A! T- ~4 a- |MSN我就PM到你的信箱了。2 |( Z7 x+ Q+ w2 n6 P: W# U, {

5 O. Q' W- F. @2 O% ]* S% Y, 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 发表
4 K% ?) v$ C: P  D呵…… 谢过团长大人~~
4 n3 b9 Q9 Z2 B. K! M
% P  F, ^: o0 \  A0 w' R/ V
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 - }4 x8 O6 }* G3 j% f
团长的朋友都是神,那团长就是神的boss。
' N. R: }9 o) a
哈 不敢當,我只是個平凡人,
! ^. W' D2 _7 H4 ]要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
  W& c2 W. J, w# d7 J. b) t7 }- }ZYH- U0 f" `8 b4 \5 {$ P/ N4 f3 T- M
QQ:414734306
) t; i. l4 @' p/ Z/ z8 MMail:zyh-01@126.com' [( S( m+ K5 R4 q: o
: C! J3 b6 r0 ^( }: L. U. T
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
; J7 f% S6 W/ E7 Q3 @- z3 R再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ M7 Q3 t& L  V: Z% s+ ~& ?不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-28 06:10 , Processed in 1.094727 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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