EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。( ~2 i; T! I5 D; t6 p3 O0 P/ G
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ l. U! J3 C- h: ?( }' N6 ~% `% m这里有相应的模拟器源码,就当送给大侠了~~
: q) O* B9 e5 E1 d7 W6 n, y4 I8 Zhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
$ ?6 L) }2 A7 |% E能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. w, b1 c+ e) B* V4 [
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* `& l/ u( }- S2 k这里有相应的模拟器源码,就当送给大侠 ...
- q& E4 C( A$ O
聲音部分(Audoi Process Unit = APU):  \' Y# e" y) P. L4 @/ `
.\NES\APU.cpp" ^8 e( A" h$ m2 ?( ]( ?1 i3 _9 t
.\NES\APU.h
1 L: Q8 A% }" R4 s" p0 C, C& ]: @# D( q7 L; _

( u9 w. X' o. L. [! z影像處理部份(Picture Processing Unit = PPU):9 x$ g! B" N6 Z' g5 T0 _
.\NES\PPU.cpp2 g2 l, o, Q& e! B7 W$ w
.\NES\PPU.h
7 G/ [: m- Q$ D, J* ?4 D1 s9 Z$ w( N& j
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
8 e+ G! l- [% k' l! ?( g4 X8 r# b(由于很多专用术语和算法机理都不明白,所以看不大懂……): c7 d( P  S) w6 ]; H; v
//////////////////////////////////////////////////////////////////////////" T! W; {: b) J0 g  R4 ^, a
//                                                                      //
5 P2 Z* j3 @; {9 A, @//      NES APU core                                                    //; u8 A8 i6 d: E, M, x
//                                                           Norix      //
0 V  P) t5 d5 N# `  P6 }: q3 Q//                                               written     2002/06/27 //2 E( {# S7 R& F( |" z' J3 \1 ^$ S
//                                               last modify ----/--/-- //- k" Y, h4 x# x
//////////////////////////////////////////////////////////////////////////
) F& m2 r. v0 e, l2 z( I% R#include "DebugOut.h"
* |9 B' e5 {# |* l0 y/ b9 l* y#include "App.h"
# m4 z! n/ q- I#include "Config.h"
% M) |, j1 ^# o3 Z! a  E- @: x; j8 m; A, i/ c6 D' |: C2 D
#include "nes.h"4 {- k; M- l# P7 D
#include "mmu.h"  I! G+ x0 S1 j+ j
#include "cpu.h". H( o$ P" a- m4 Z
#include "ppu.h"
# o' o9 q  K! Q- y#include "rom.h"
' }2 O( f& |- ?0 Y( d2 T#include "apu.h"( x: t  k0 F  m. ]" E% t& P
( ~) m# t) G( G+ F
// Volume adjust
! Y! H0 [9 ]5 g4 J6 e7 c// Internal sounds' t2 p) f' W' R4 D
#define        RECTANGLE_VOL        (0x0F0)$ p( q$ \' u1 y, s8 z8 A
#define        TRIANGLE_VOL        (0x130)
; }6 F% e. p& {/ _% c2 w. Z) `#define        NOISE_VOL        (0x0C0)9 n/ u' k4 k& c. L* \
#define        DPCM_VOL        (0x0F0)
4 A  h  t/ Z. r4 V3 ?& Y7 `// Extra sounds. D# ^- d0 d% g- A7 Q% ?
#define        VRC6_VOL        (0x0F0)
3 N2 T! t$ r2 l- |. i8 S+ x#define        VRC7_VOL        (0x130)
3 h8 D6 {& r4 x( u#define        FDS_VOL                (0x0F0)
7 d8 y6 c* f% O: {$ X: Z. `" Z* ]#define        MMC5_VOL        (0x0F0)& I1 m# ?  }& q7 Z
#define        N106_VOL        (0x088)/ T& k/ A4 A6 j! f1 z. n
#define        FME7_VOL        (0x130)
1 O& p& j& Y" d. i8 {" i7 P! ^$ c& W& X; [$ |
APU::APU( NES* parent )
7 W0 ^% F7 W% ?" I$ c* A{
$ t  ~. u) z9 R2 A, [- J        exsound_select = 0;
! `5 `& v9 w' p' p$ d4 f2 |# T6 @- T, t4 l
        nes = parent;) E% R+ d/ i4 F9 u2 O1 K' Z
        internal.SetParent( parent );! A, |/ h/ U. t: y, X

5 a( Y; x! I* [        last_data = last_diff = 0;7 m# E; m2 }' J7 r

1 ?) J1 [3 M8 P- a& E" j        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
, [" |) _" `7 {. G7 v1 d
6 G' m% H1 a2 Q2 S        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; g7 Q4 s5 f9 t- |        ZEROMEMORY( &queue, sizeof(queue) );
3 ~+ X" t8 H) |0 I) T; D; E. s        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 P2 C; Y+ W9 r& L6 c; M

5 E- `" ]( e. d0 z% f2 s        for( INT i = 0; i < 16; i++ ) {% i9 l6 @: F6 T0 B8 J7 i
                m_bMute = TRUE;* J2 s# |2 U. h2 d! i/ V
        }4 h, E" D# m( d
}, n; B. }2 V6 I: u  [6 L- E
$ a5 F3 j. ^4 h3 ~! @
APU::~APU()  e( S1 C/ w3 _
{. A7 K+ y) O& ~1 b, B% f
}4 m8 z: h* d6 `# P5 _7 m4 z9 x6 d

6 N/ \: B, l$ ?9 k/ j  pvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data ): ?' w- Q/ r7 Q7 W5 O+ i6 x
{
8 ~+ J+ `9 H$ ?2 s        queue.data[queue.wrptr].time = writetime;
2 h! i1 s8 S7 F) z+ K# m1 o        queue.data[queue.wrptr].addr = addr;; t# }, a4 V0 W: s4 a" X) i
        queue.data[queue.wrptr].data = data;
( z8 Z9 M$ L8 X4 X5 }2 @        queue.wrptr++;5 T4 x) C0 p6 `; H
        queue.wrptr&=QUEUE_LENGTH-1;5 C: g# O3 b/ Q- i% C
        if( queue.wrptr == queue.rdptr ) {
" V. M" H5 G. g& C# k                DEBUGOUT( "queue overflow.\n" );5 ]+ A2 B4 C8 X/ F5 F
        }& b/ t* k  o4 h2 `' ?
}
) U. S: T/ ]1 B5 c  @" r0 c" J. E% x9 y0 f- Q1 z7 j  N# Q6 S
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
/ |4 |4 b: @3 H{/ ^6 p2 Z; _& B; Z# E
        if( queue.wrptr == queue.rdptr ) {
) f  H; Q" U6 _4 ?4 W% Y7 ]( H                return        FALSE;
. {8 e8 k* q' Z8 ~3 q/ M5 E        }) N+ n2 V) }( ?9 J) l
        if( queue.data[queue.rdptr].time <= writetime ) {* D6 Y! h, n2 J
                ret = queue.data[queue.rdptr];/ r9 G5 a+ f+ f/ A5 F1 N; {
                queue.rdptr++;
/ d) f/ d  q" _" {; ]) z  Q                queue.rdptr&=QUEUE_LENGTH-1;
7 K% k1 j, W! u* y% Y9 c  d8 d, `- X                return        TRUE;
- F/ A6 F! |) L' v/ }        }
1 ?* n, L6 @7 F        return        FALSE;
. f) p! }' a/ E- b5 C( F}  `4 i6 l7 b% U& d& {% f+ K6 q* D

" H: V8 p8 |& j  d8 Kvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ): x+ e/ B7 A' b: _
{
' r8 P% i" E5 W0 Z$ O% M* [        exqueue.data[exqueue.wrptr].time = writetime;
7 J/ R- D4 c# y. v. S        exqueue.data[exqueue.wrptr].addr = addr;) p; G$ e) p' G
        exqueue.data[exqueue.wrptr].data = data;* l4 C2 N: ~/ e
        exqueue.wrptr++;3 g1 B# J  n+ s$ b9 ?4 z
        exqueue.wrptr&=QUEUE_LENGTH-1;
. p4 ]& q2 \0 Q4 w3 F        if( exqueue.wrptr == exqueue.rdptr ) {7 R5 M! Q1 N! T. z
                DEBUGOUT( "exqueue overflow.\n" );; _2 L/ N9 ?* _" L. {$ c% r0 L
        }- q& j( p9 }5 M2 v6 ~
}
; B9 U: T9 X% x* j. s, H% n' n2 K# D
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )) S( ~8 O7 x8 I+ X& l+ \7 {
{$ X' \- ~: X" I" _1 y  N0 _$ N
        if( exqueue.wrptr == exqueue.rdptr ) {
- B  P* ?  ^  r9 Z2 z, P. A5 r* w                return        FALSE;$ i/ Y& Q4 A: @) W
        }9 ]- d) r# i3 s* E' {: e( [
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* q0 L, j+ e' T
                ret = exqueue.data[exqueue.rdptr];
& T+ l9 [# g& D4 U+ G, `* Y3 F                exqueue.rdptr++;. P* _: |/ V% s4 C# T+ ]
                exqueue.rdptr&=QUEUE_LENGTH-1;
( c+ \* O: z. j" q+ Y+ C                return        TRUE;. z5 M! V9 j' u3 I/ x/ n" b
        }
9 F9 a# p  n& u7 m: k        return        FALSE;
2 r0 n& a+ \+ K8 Q/ `}
3 g5 Y8 U* r' E" ?
. q0 I' X, h( e  Mvoid        APU::QueueClear()
' _6 Q% Y; }4 M% I9 d, W: [{4 x: w) d( T% n( h! u
        ZEROMEMORY( &queue, sizeof(queue) );
8 Z7 x' k1 z5 [        ZEROMEMORY( &exqueue, sizeof(exqueue) );- a) A2 Y! H& q, r- Y
}) u6 r/ m3 G2 z) g& o6 N
) V4 W+ Y+ m# Y& _0 A
void        APU::QueueFlush()( k4 s" F$ b& G& C# u- o4 i
{
, Y- {# ~" }9 |' h1 {        while( queue.wrptr != queue.rdptr ) {
$ a% C& Y; h. _  x7 N" S2 C                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
- d& x/ a4 z' v* O7 P8 D                queue.rdptr++;* R# G% \% p9 o6 }% Z5 m
                queue.rdptr&=QUEUE_LENGTH-1;+ a4 x) l* G0 c9 U% A! }
        }
; u8 u2 |# F) k; \% n4 r: q: ?# H$ o: Q! F+ A& Q, X1 v
        while( exqueue.wrptr != exqueue.rdptr ) {
: E8 t" Q5 M, [                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );; |. z) P5 U8 ^3 J
                exqueue.rdptr++;( X( t7 t* H5 J/ C
                exqueue.rdptr&=QUEUE_LENGTH-1;* l3 b6 {. q2 o  M9 r) |$ i
        }
4 g& G- u/ Z8 N1 z}3 e, b9 W& ]' F- E: i2 B9 }
/ D) N* j& X! [8 T
void        APU::SoundSetup()3 B5 x1 r; b) A) R
{6 R4 u( X9 e5 |3 ^: O# l- O
        FLOAT        fClock = nes->nescfg->CpuClock;0 g# `1 z7 L  I$ U6 S
        INT        nRate = (INT)Config.sound.nRate;
- ?* B( U+ r; S% ~7 e8 j1 A/ V* }, L7 V        internal.Setup( fClock, nRate );
) k# O" q! }4 {$ e& y& |        vrc6.Setup( fClock, nRate );
' S) U7 V) j& t# |8 ^) M0 v" b        vrc7.Setup( fClock, nRate );
/ y" d. E0 k0 J; u( d        mmc5.Setup( fClock, nRate );" \4 W2 v3 \2 y2 I  f, l
        fds.Setup ( fClock, nRate );5 z' O- ~! }' L) s. {1 o" \. s1 `% E
        n106.Setup( fClock, nRate );
; D  d! A. q+ k! ^  ~5 W, \& w* _        fme7.Setup( fClock, nRate );& u6 K" a0 E8 B% z( h* k
}
2 d9 O* i5 D# ^% r
( b3 }+ n4 _$ R/ W/ ~void        APU::Reset()9 v0 w6 g( _4 l- [5 @
{
; t2 |) ]2 |2 _+ ^        ZEROMEMORY( &queue, sizeof(queue) );
" x9 Z( `2 b- L        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 n4 R3 w( d. Q9 P# ?$ V
9 T3 s3 M1 x' k$ {
        elapsed_time = 0;
2 T( W& t. R( y& \
  y$ b4 Y0 g, J9 g9 ]6 O        FLOAT        fClock = nes->nescfg->CpuClock;
( Q- g* r, q  Y. S7 M* Y/ _        INT        nRate = (INT)Config.sound.nRate;) d( e4 O/ A2 ~4 S
        internal.Reset( fClock, nRate );
! O; }$ [6 x1 B* r1 G7 F: m        vrc6.Reset( fClock, nRate );
/ j. {* a$ T% |- ~: p: n/ O3 r) s        vrc7.Reset( fClock, nRate );
" A3 G& M" y" p+ c0 t& ?  c8 N        mmc5.Reset( fClock, nRate );
+ r8 \( R+ k  q6 t        fds.Reset ( fClock, nRate );
0 K& d- {# |- [. ]. H- f2 F        n106.Reset( fClock, nRate );' R, ]+ X. d( z  J! R
        fme7.Reset( fClock, nRate );
* D; O3 b8 t5 N  Q2 [' L
5 J& Q8 a2 w4 ^/ ^+ f2 \        SoundSetup();' g7 W# ~5 `+ X- v* u) T
}
* T$ I# n* K7 c, X) ^6 _) C- H. V$ H
void        APU::SelectExSound( BYTE data )
  V6 t. T. V$ {6 N+ m$ s" G, O+ j{
8 u# n! O, ^% K* J7 g4 _3 V        exsound_select = data;
- t. s: p0 r2 C! {! ], ~}
6 E3 ^3 s1 o# J  g; P. M) v8 {
$ o8 S) k6 F9 R( K, YBYTE        APU::Read( WORD addr ): i1 B: B* O& O$ a$ N$ P0 Y
{4 k7 n# T8 }$ x  s' L
        return        internal.SyncRead( addr );
5 |* v# G! t* m* d9 m, \# N}
) J6 r; X. @; A6 p8 L, E
) `! Y  x0 D6 ]8 p( rvoid        APU::Write( WORD addr, BYTE data )8 a$ g$ z$ t5 @" b! j, K" p$ |; A
{1 _6 `, `0 f3 H  d& f
        // $4018偼VirtuaNES屌桳億乕僩
3 A: Z& c3 Q. G$ F( C2 v7 [        if( addr >= 0x4000 && addr <= 0x401F ) {
& ?- p1 ^4 W5 J/ S) A                internal.SyncWrite( addr, data );
  G* {8 ?" u5 x) v# [                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& N; u( F3 d3 W" z
        }
/ S1 k: k$ @, X+ K/ V# m) d}( b) k% q6 a6 J% J, u& T2 j
5 S6 k+ I) S: z# i% L5 }
BYTE        APU::ExRead( WORD addr )* Y7 Y4 [2 V5 s2 b$ G
{& Y5 D+ p- v8 b4 G  `  V
BYTE        data = 0;0 s; G' A" f; A8 a9 r% s8 e

& A3 T; L4 X; F7 w7 C        if( exsound_select & 0x10 ) {
, Q6 ~+ O. R- p7 w) s0 h                if( addr == 0x4800 ) {% x- ], q- c" N% X
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
: |& |* V9 W' P9 T                }
0 r% ?2 g' k9 y, y8 Y        }
# u. z8 O6 o( Y4 p8 N2 {4 B0 p        if( exsound_select & 0x04 ) {
$ A) D  F* W9 r/ C3 }; \# i  @                if( addr >= 0x4040 && addr < 0x4100 ) {" E7 _" Q( G3 j. Z) q
                        data = fds.SyncRead( addr );# l- h& K' v: C) v8 M
                }$ M0 _8 V# p. f; `& U$ J) f. K, m
        }; R- A; Z/ u" g2 _  f/ s1 i$ V
        if( exsound_select & 0x08 ) {2 X  k( O# k0 F2 n  D1 W
                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 R4 S4 a! W5 N- o2 X6 C7 |                        data = mmc5.SyncRead( addr );
/ k# t6 g) O( a  r1 |                }" K0 l5 Y5 m; c6 M" C
        }: r  D% \  @4 ?% u( j$ E

5 K6 f, y; O  A        return        data;0 u" c/ ~- Q" e: A4 ]8 l. ]
}
% |: t1 \) Z" Z* y- U5 d- h' f8 I, T6 d* f+ O, R! L
void        APU::ExWrite( WORD addr, BYTE data )) u* x. d' s, p, a: h2 o
{
8 c" I1 V" O* K9 H" |# I        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# D6 V8 l0 U8 G# `7 d4 ~# U: K* D! z$ d* Q9 w  Z
        if( exsound_select & 0x04 ) {
: `* x- p; u$ s1 [% R: V  S: Q                if( addr >= 0x4040 && addr < 0x4100 ) {
9 \5 u/ |; R4 l- L$ {                        fds.SyncWrite( addr, data );! o# ^0 e; z  @) q
                }& t6 i5 G/ h/ l0 B1 d' l
        }
+ ?" o# d9 {+ ~* k' _+ Q/ l  L+ I* Q$ d0 }- t
        if( exsound_select & 0x08 ) {9 `7 v4 P/ B0 ^# R' V
                if( addr >= 0x5000 && addr <= 0x5015 ) {
( d" L' M$ d$ ^4 `0 ^( K                        mmc5.SyncWrite( addr, data );4 g+ x0 C) x7 L+ U+ `
                }2 v6 y+ t% y6 l, B6 j& x5 d' b
        }( a8 Q, z+ q1 r5 }0 ^
}5 T6 ^" ~3 ~+ Q( y" \6 I6 i8 v

/ |$ r/ S% w' Q5 W( ^1 P5 X- avoid        APU::Sync()
1 u! V: p; f8 D9 M% w{
0 ]3 j$ E* m, L; N9 O}
6 J, l! k* i5 f5 c' ^. K* e- P7 q/ N9 f7 a; w: q$ m1 D
void        APU::SyncDPCM( INT cycles )
; O: c2 b- X) @9 ~! s- ?+ Q{& p( D( j9 P1 o8 n# U' E5 B
        internal.Sync( cycles );+ N& z& i8 A/ e# Q0 Y# H  p3 A2 S

, G) P- E1 Q. v. }* U. t        if( exsound_select & 0x04 ) {: s, S8 m) P; U7 b- o
                fds.Sync( cycles );
6 x. \. f0 }9 V$ O        }
1 ~: O$ d2 d0 m0 O1 |$ \        if( exsound_select & 0x08 ) {
/ g. m1 x4 D2 ?# V  V                mmc5.Sync( cycles );
: L8 d# s. c1 I; C. Z        }- e9 Z0 t( }0 q) N! i2 u
}
0 r* }3 @) N" s; P. u& p- |. k: h# |% A. `( e
void        APU::WriteProcess( WORD addr, BYTE data )- f$ D( q( Z5 ?3 P; V: {9 Q, }' W
{
8 m& u/ b/ C  j  @! P        // $4018偼VirtuaNES屌桳億乕僩
: l" D& Q* k" l        if( addr >= 0x4000 && addr <= 0x401F ) {3 @6 m+ a+ }6 v1 I5 b
                internal.Write( addr, data );" }) V5 @1 {7 J* W0 ^* w
        }' J- f9 k' j9 e! B. L
}
$ e0 M$ I" e1 j& \$ z# i
% v$ o* w. p. e" _void        APU::WriteExProcess( WORD addr, BYTE data )" S; t* G2 l/ ^' p
{% ^% ?7 v" `/ x! c  z5 }
        if( exsound_select & 0x01 ) {
$ `5 V& e! k4 h8 ?                vrc6.Write( addr, data );
9 c' ^; A- T# y* z7 X3 ]        }
6 ?% ~. Q  j% o9 b2 y' w% ~# Y* h        if( exsound_select & 0x02 ) {
* E4 E; t1 o8 E1 S: o2 M. m                vrc7.Write( addr, data );/ M9 Q. c# F' A+ S2 h
        }# [9 _% f$ @4 N) ^' x- w" S
        if( exsound_select & 0x04 ) {
% P9 K4 @; N) P+ I: k/ e$ H                fds.Write( addr, data );
5 j$ T  H3 P1 n6 H( s* \        }
) E/ r* V9 N' p/ t/ w5 i8 Q0 ~: C9 b        if( exsound_select & 0x08 ) {
1 x) R; H6 F" ^) z/ E3 B                mmc5.Write( addr, data );; H0 |5 q+ u$ g$ a, P" u
        }
+ T& Z. ?2 K% q- V: G# m1 _$ N8 w        if( exsound_select & 0x10 ) {
; p4 G6 M; E/ Z* n% u9 N( M                if( addr == 0x0000 ) {
1 l0 L) {. }% Z6 @* l5 \; _3 z                        BYTE        dummy = n106.Read( addr );
# N5 u% C: d# n4 `; [; Y. c4 D                } else {
' f; S( M+ j  A1 Y3 {0 Q* j                        n106.Write( addr, data );( U2 A& Y5 s8 k+ B* L7 Z$ q  F; w
                }
. D) b3 R! h: N: [5 k# d        }- L- \* N' _2 n5 p
        if( exsound_select & 0x20 ) {
( {' I4 D! ^2 m& f0 B8 |9 I                fme7.Write( addr, data );+ k3 ~+ X" p" g+ v
        }
( W( s% y, _6 T3 s" z  S}% V! }! S8 H$ D! ~. G
% w1 z" E5 Y2 }$ H. N3 h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )- A( m; {8 w% a0 _) {3 {" r8 ?
{# Z4 e" h! a, \; o2 Z6 k
INT        nBits = Config.sound.nBits;
% Y- V5 Z  Z/ ~* y  oDWORD        dwLength = dwSize / (nBits/8);
; V6 \# ?# ~; eINT        output;3 N/ n- _. a- V/ j& l. u; w, z. w: A
QUEUEDATA q;
5 Z( e2 K- u: |5 I+ sDWORD        writetime;
. ~  E  Q  v) `' ?
: c( W0 Q. f2 m; MLPSHORT        pSoundBuf = m_SoundBuffer;3 r* t6 v4 O/ z( \% t/ ?
INT        nCcount = 0;
: j# d9 C  ]- F/ j- [
6 I1 }2 ~9 I/ dINT        nFilterType = Config.sound.nFilterType;2 `6 q' M! N6 D# ?
4 W" ~- k' D- ^7 ~! R7 q6 d5 N7 `$ T. [
        if( !Config.sound.bEnable ) {- G  S& h$ b7 Y! u2 o( V
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );1 f9 A, x2 {4 ~$ c6 \+ b+ B5 Z
                return;2 B, ], Q' Q# T# T1 [
        }! S7 E* \$ ^$ Q& A" O

" }$ g5 d2 v- u+ P4 k7 ]# z+ G        // Volume setup
% t3 b5 L! D1 j: F4 V. F! o3 _        //  0:Master
* L2 z3 h. a3 u  p4 j3 d/ p        //  1:Rectangle 1. l! j3 }' |1 H' j
        //  2:Rectangle 26 g' Q* E' D+ c1 ~0 G# R3 l6 k
        //  3:Triangle
( W$ z$ L: H' ]* P' a& V% i        //  4:Noise
! q# ]6 r! u0 f1 R1 v        //  5:DPCM) f4 l% M7 Z' n  L" m3 |
        //  6:VRC6- F- d% ^( p$ s  m0 b; b6 P. e6 F7 u" |
        //  7:VRC7
1 i" m2 p- ^, }6 Z8 _        //  8:FDS; q* }# w# Y& X
        //  9:MMC5
2 j- t8 r$ f7 G2 S, \: ~- i        // 10:N106) f2 [  W% Q8 h- e) \1 X4 K
        // 11:FME7
5 |# }. ?$ i8 N. }( s        INT        vol[24];+ u: ]9 t. D; _  ~: y
        BOOL*        bMute = m_bMute;0 F5 m$ G  i: N  N. v
        SHORT*        nVolume = Config.sound.nVolume;
4 G& d6 S# p0 D1 y$ n0 w2 j: [7 J1 {+ W& ~$ o. O$ ^
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 J2 X* W0 L1 M: P5 e: n
4 i- y  h" t0 g+ \; p
        // Internal1 t" _% v4 a" n# w
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
) R/ {8 K0 C6 M# N5 B1 U( n        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ g3 G& ~) b9 O# T) r6 O        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 \* i6 e+ b' b$ ~# V: v
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 ^; g+ P+ w' D0 Y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
# V6 d  Y! X, d  N! t/ j* X2 c3 C% d4 @/ X) N2 p9 \
        // VRC6  T7 U9 S. B7 V$ D/ ~2 @; n4 z
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- g- |: r5 }' v) p
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* h( r5 ~. h. W/ p8 r        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 M1 t! ~4 \- B7 ]" p; |- g6 w2 z; Z5 b  n4 _6 N
        // VRC7# h0 {/ T/ a0 e
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
& S! [0 z, V7 q3 m
9 Y, W- ?. s$ ^' ^$ n/ m$ g  T1 o        // FDS
8 _8 h- z8 S2 p3 x+ `( z        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
9 g. X  G. I4 v2 P1 o/ Y, @' `, ]8 s7 O) X! ]& f
        // MMC5/ D" s' |( P$ n9 g: `4 k
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 }! S  |# f* H
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: M: S* M. y; Q$ ~3 E, O( {& E- ]5 @        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 w& m) m) g0 p/ o5 S
6 k% x! }5 M" _! c; [5 [) M1 a        // N106
( |4 O" q9 |# @5 X- N        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ q# x% U  _  c3 ]8 M        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ ?! q  ]9 J) p" N6 s3 a
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 B% N( V; L; x- t7 v0 v        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 t" g  W4 g, u$ p5 Y        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% E: S8 Z0 R7 J9 m' p
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) G* e5 O7 N$ {1 m6 q/ G9 q1 n
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 n5 \" a: Y( |3 d* l        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 y5 ~7 m2 m- E

, D; X8 q6 K* K7 m( D5 E3 e4 l        // FME7
; j# c2 d/ Q5 s; Y" A+ q        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 l  a: Q5 r; q8 p        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) ~6 z% A$ P2 }* Q' `
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( |, K6 ]- r) [: Q5 O* ?4 f* `* ?3 B% e4 p5 O
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
4 i0 o+ a* O# y8 [7 s        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;/ P! I" S- N9 D, Z

0 g, \( F5 P; n( x6 s: V8 q( D        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 X( e. y# g5 @
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
# T8 t8 ^0 k0 D  t3 \# Y                QueueFlush();: T3 |! {1 I! s# O% n
        }% J% Y1 P! V/ u8 a  ]) M; H

+ p& F6 p9 f/ B# j# q        while( dwLength-- ) {( i; X  ~! f: j+ @( |7 s
                writetime = (DWORD)elapsed_time;0 O8 b/ L5 J5 I3 L3 T
6 ?6 U8 m5 r5 \3 o
                while( GetQueue( writetime, q ) ) {
/ b9 j' w4 a3 C3 Q, E, d                        WriteProcess( q.addr, q.data );
6 n: u2 l" C% H( M" |1 P                }9 V2 z& {8 u1 ]4 m
9 o" X/ w5 n$ O: ^" w) U" h8 d
                while( GetExQueue( writetime, q ) ) {
7 p5 f  o. Z, p( y" y: h3 w                        WriteExProcess( q.addr, q.data );
) a: U& v! C6 h; Z  t& f                }
/ e3 O" ^8 M+ M  |( ~9 d1 u% H9 q; x2 s6 m9 i
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 C3 E& a1 [+ Z3 L+ t
                output = 0;' O* D. z: S8 e5 `
                output += internal.Process( 0 )*vol[0];
5 l% C" S6 ?8 D1 E8 C9 I/ R8 P. G% G                output += internal.Process( 1 )*vol[1];$ i7 F* E3 u- r, o9 F/ K: v/ P8 ^6 u* a& {" h
                output += internal.Process( 2 )*vol[2];5 f/ ]! W7 E/ P$ {
                output += internal.Process( 3 )*vol[3];
; E$ ?8 Y7 F$ n) @" t; |6 `                output += internal.Process( 4 )*vol[4];
8 B( F; r: x: h5 `  q$ y/ K7 j; m0 d' L8 k
                if( exsound_select & 0x01 ) {' I3 Z9 D6 `, V3 ^, F3 W( J& m
                        output += vrc6.Process( 0 )*vol[5];
& C$ r1 \. `. p6 k& c                        output += vrc6.Process( 1 )*vol[6];" \: z6 {5 B9 |- C3 O  W* v; v
                        output += vrc6.Process( 2 )*vol[7];  W* N  u* M" ]3 h
                }! b. C; C3 r2 E  W$ |2 x# T. l4 s
                if( exsound_select & 0x02 ) {3 l, {, e+ O* I- a
                        output += vrc7.Process( 0 )*vol[8];
! n; b$ C3 V& H                }
: ^# V/ S5 |3 r$ C$ \9 u) E                if( exsound_select & 0x04 ) {. D& N  s+ s( }" H
                        output += fds.Process( 0 )*vol[9];3 {, j6 G8 k0 o# X0 O6 |
                }
6 D  t2 I. j- U. k0 X7 ?# s                if( exsound_select & 0x08 ) {1 ^. m( e& i9 s( i2 A
                        output += mmc5.Process( 0 )*vol[10];
$ |4 _! K( X" b9 `: Z' P                        output += mmc5.Process( 1 )*vol[11];
# J  Y7 ^9 L0 X) v3 R                        output += mmc5.Process( 2 )*vol[12];% D3 X+ _" ^6 q
                }
7 H2 D3 t; J5 n- f2 J                if( exsound_select & 0x10 ) {6 r. a: @# g" h$ ^# a  m" Q
                        output += n106.Process( 0 )*vol[13];* a' {& ?6 U9 ~0 Y7 n; A  W
                        output += n106.Process( 1 )*vol[14];3 K8 O' A9 k, ^* ?, y7 z
                        output += n106.Process( 2 )*vol[15];
6 u8 T! [8 B4 @$ e% V5 M  K) r                        output += n106.Process( 3 )*vol[16];: p3 q3 Z2 [4 U
                        output += n106.Process( 4 )*vol[17];
8 Y0 a8 M. j1 `' q/ |$ J                        output += n106.Process( 5 )*vol[18];0 a$ E$ j. b, d, H" e. Q" q
                        output += n106.Process( 6 )*vol[19];
6 E' G/ E: x0 t* P$ o                        output += n106.Process( 7 )*vol[20];
' A) z9 v/ G& `                }
2 z% Z! U; T  }& N9 I                if( exsound_select & 0x20 ) {) I% T2 O" C5 X& B! S
                        fme7.Process( 3 );        // Envelope & Noise
6 E/ u1 c$ _* v% _3 f+ P! m                        output += fme7.Process( 0 )*vol[21];: o! ], F% [" b: O, t+ m
                        output += fme7.Process( 1 )*vol[22];
2 m* Y5 \0 e* E& P& F5 S4 v6 U* j                        output += fme7.Process( 2 )*vol[23];
5 y5 v" ~! P) g+ O! q                }
9 ?8 |" @0 H: r' k* k$ M3 z9 h' n8 C4 X9 \1 l' h: W8 _
                output >>= 8;( y4 [& `1 ~  [1 f

2 {# B# `; {3 F; E  G# A                if( nFilterType == 1 ) {" h1 c! Q+ h; U' D3 Y. k0 K
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)/ }0 F: k! r; d% Q
                        output = (lowpass_filter[0]+output)/2;
" f* w" V$ j* J9 R: E                        lowpass_filter[0] = output;* b) e8 j% X6 y8 k0 c8 s( ~
                } else if( nFilterType == 2 ) {
1 \) m+ T) h! }                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
* \% D! [9 I" z: X0 U                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# k) E, K$ _7 |% N, Z
                        lowpass_filter[1] = lowpass_filter[0];
' r+ z) n6 t3 U: ~/ ]% j1 T                        lowpass_filter[0] = output;
& `, [# S/ o' [  y3 b" e. l/ i5 m) E                } else if( nFilterType == 3 ) {
  Z; H7 E& G( W7 x$ z) G3 o) m, y                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
: O( O0 ]5 s9 c6 c                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* Y  @2 \& ?1 y2 z! J/ u
                        lowpass_filter[2] = lowpass_filter[1];
! I! P2 z, ^+ g  W                        lowpass_filter[1] = lowpass_filter[0];$ ^- g$ \( W* I; n4 D  @1 a
                        lowpass_filter[0] = output;* K# b8 q7 P5 d+ B, W% n2 y9 n
                } else if( nFilterType == 4 ) {4 f# ~6 Q6 Q9 p
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- S7 p# ~2 z: O0 g. |; g
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
) g' |* W; Q4 z) F3 b. L4 G                        lowpass_filter[1] = lowpass_filter[0];5 W1 M) |, V& H4 D( |* z
                        lowpass_filter[0] = output;
  g: Q- v+ ]( d5 P# i                }
( y) k* B2 _: v7 |$ b2 c' {; N
7 Z4 H% R; b' V1 t#if        0* u- E- j, P1 B# b& y
                // DC惉暘偺僇僢僩
  r  L3 Q' H; p1 e* C) V6 R  h" J; p5 M                {( p1 s7 A5 u. C0 p9 l* b
                static double ave = 0.0, max=0.0, min=0.0;
& s" h: I& G! e! d                double delta;  f! \  X2 l5 k; g) O
                delta = (max-min)/32768.0;; c6 h- E: d8 e2 Z5 K# }; b
                max -= delta;+ r) J) u$ w- S: U
                min += delta;( f( o0 y# v" ]( ~) Z/ C" k
                if( output > max ) max = output;( j# J9 F/ h; T. Z3 j, F6 O
                if( output < min ) min = output;: ~6 y4 W1 \  n0 v& Y- z8 o
                ave -= ave/1024.0;
6 L0 R3 B" E3 ?+ g* f( [                ave += (max+min)/2048.0;
& l: x3 `0 b4 }5 q6 v# I3 S                output -= (INT)ave;
3 Z' X4 {! j7 X- s7 X6 Z. e                }
! n% E9 }- L' f6 ]#endif
0 l  d3 q, ~3 I' `& R; `, D* z#if        1% Z! }' l: `  N8 h( n- ]* P
                // DC惉暘偺僇僢僩(HPF TEST)
. a- Q+ w- a. c6 d                {) U6 J8 l2 {' N- N/ \" I
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);" m0 x2 I+ W7 y
                static        double        cutofftemp = (2.0*3.141592653579*40.0);+ G$ d( g( y1 M
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
6 q5 c+ d" i* Z/ l2 R% _                static        double        tmp = 0.0;
2 f( t5 P0 m8 ]/ G                double        in, out;( f, Q8 A& M* q( w
2 m& n& u& d9 {3 a8 w
                in = (double)output;
! d8 y" f: r  J7 f$ q                out = (in - tmp);) {5 q2 i" F: l0 w( |% I
                tmp = tmp + cutoff * out;8 O6 {; i' V- F# }

: t' @- ~% \. C( s' ?4 R0 ?* V                output = (INT)out;
; Z# I( t3 i8 n" p, I                }5 ?+ r" l% D, u) }$ t  e& _
#endif
0 @0 k* a+ P, Q. N! y8 ^#if        0
5 D5 P  S4 E( ?2 Y( l                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
  v0 l- L* y* M2 E                {
5 F: _. L3 y0 y: l# R/ Z                INT        diff = abs(output-last_data);) q8 ^+ v8 ]& L5 Q
                if( diff > 0x4000 ) {; z( \  b1 q, X! M4 z/ m
                        output /= 4;  ^5 O. F/ C* Y8 q8 y" X  @
                } else $ R9 I! A: x& v) E4 }9 s1 z, ~
                if( diff > 0x3000 ) {
! C5 S6 D7 d& D2 g: ~( W" ^; K                        output /= 3;' ^, M6 m4 H1 q8 a9 N& \, c8 p
                } else8 c$ b  \6 J8 J& ?: y7 ~0 Y
                if( diff > 0x2000 ) {" d0 A% \% y5 h4 S
                        output /= 2;7 C* D8 J& e$ t7 o; G( h9 f( U- b
                }
8 U' X5 K4 _, q! e0 O8 b                last_data = output;) d3 [% P, O: `5 y5 z1 p
                }3 g, |; C- ^0 g! r( u" R$ h; {$ k* U
#endif
  X$ `. d0 t' t) E3 F" z+ E" m" ~( M                // Limit
- Y5 ]9 y7 q5 u% ?5 s& \  \                if( output > 0x7FFF ) {) ?) U( F+ N$ l2 u) p( M
                        output = 0x7FFF;: E( E1 j, I1 i* u
                } else if( output < -0x8000 ) {0 w8 X& v1 U: S& x
                        output = -0x8000;* H. u" ?0 I* f, }" w9 a
                }
' e& J9 _0 p- \- d7 ?5 X3 d$ b2 r. i
                if( nBits != 8 ) {7 y6 _' r& R$ Z5 q; a
                        *(SHORT*)lpBuffer = (SHORT)output;+ P8 m& z( g6 X& }" k! \- D
                        lpBuffer += sizeof(SHORT);$ }& a0 w7 t0 ^1 D8 W4 n
                } else {
6 r' Q5 n& Z& o. P$ r. ?$ Z                        *lpBuffer++ = (output>>8)^0x80;' F( {  s  m' P
                }
9 w" i8 B6 D; |0 ^
9 Z" m% \$ L4 E5 d# A; p. p                if( nCcount < 0x0100 )6 r8 h/ I/ l7 N9 Q
                        pSoundBuf[nCcount++] = (SHORT)output;" w( K! j5 z$ n9 a$ }" e

* q, i2 ]. }# T  Z+ u$ f0 W//                elapsedtime += cycle_rate;- k& G0 t% Q& h
                elapsed_time += cycle_rate;; I8 K! n) F7 i. W& Z& M
        }
0 D( }1 K6 P: T& J- x7 O5 c; {0 i% \/ N7 J' t% W1 D0 e9 J3 \; I
#if        1
5 t5 x5 e3 y$ C* K  {; h# R        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* e8 m5 `% d7 ?+ \5 o  k4 f' t                elapsed_time = nes->cpu->GetTotalCycles();
9 s. U, F0 \& n: u2 D        }" d3 I. x% a& k4 R( ~" l
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
# L& ?, k( p( e7 m                elapsed_time = nes->cpu->GetTotalCycles();
% q  N9 Q, [* l5 c/ d! C8 f        }
* g- P2 ~' [, g! n#else
3 f" ]9 [( ^. Q0 A/ w* ^        elapsed_time = nes->cpu->GetTotalCycles();
8 T: B) q. {* f#endif
8 r4 P; b1 H# k. X- {) s3 R2 s}
  |7 T: b) j$ T- B: c6 ]
: G  X2 L- @" y2 }; i5 S. N// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  a1 U1 _! L/ Q0 y; [; L8 f
INT        APU::GetChannelFrequency( INT no )
- ]% y6 S' z. r+ y* b1 O9 A{+ r8 O" z7 c2 g9 g) ]
        if( !m_bMute[0] )
5 F3 o+ x  `5 j1 Y0 u                return        0;( [3 ~1 y9 X' [

$ i9 h: H7 b) Q" {- H  M        // Internal
, E( S3 x$ z* ]: ?3 J        if( no < 5 ) {# M, z  W  ]# J7 L
                return        m_bMute[no+1]?internal.GetFreq( no ):0;9 C* H# \2 p# s# ?
        }7 B; U, Q( f, c0 |3 Q
        // VRC6' n% \7 d0 P* _- u, x* |
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
1 u+ S( K5 P* v  s% |: d! v7 t                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& M- w0 A' O/ j) q3 r        }: i! m; J; b$ p; Z  _- v1 T
        // FDS4 G, m6 h7 W$ g  K
        if( (exsound_select & 0x04) && no == 0x300 ) {3 G% n" Q7 H5 ^/ K1 n! V9 X
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ v" |8 }" n& T+ @  L8 S        }
! N  n/ N* \: h* _        // MMC5! T; i1 o/ m; f/ v( }
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; X- f# T5 K9 V/ f2 v4 g% e& I                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ |  R! m" h3 t6 @0 Y5 E6 S5 Y        }& r9 p  Z+ |+ g4 N
        // N1062 I! S. e! o* ?' r! {* g
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {, }: U, G( O: k1 X  r- P" ?% Q* h
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;2 L1 w3 x3 ~! Y$ i7 S1 k
        }  Y2 C6 ]5 F) m$ F) G( e3 q: c
        // FME7
( m& }0 I$ t" U( @, _: I        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
: B' ^5 ], i" E( y                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;5 c& ^2 ^9 Y) c) b! Y/ k
        }
- g' T1 r! n! t6 G, T0 @6 r        // VRC7
5 V" H  z. w0 c        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {- m& L! v5 {& I+ |) Q
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 x/ |) g2 w, I& t8 N        }
! M7 l: h& W$ g4 V        return        0;7 B8 u1 d! x- z0 j9 s' N$ t
}
0 {0 w) H* p/ ]8 |! B) H0 n/ n" T8 s( \, q8 M7 m: b0 W
// State Save/Load/ ]7 J. n) U  x) h
void        APU::SaveState( LPBYTE p )0 Q9 `2 H6 c+ Y* Z3 S. z
{, y6 V6 n+ C) {7 W  l1 U5 g  O, a
#ifdef        _DEBUG# _" @  l  }+ P0 p8 j1 O7 v( g; S
LPBYTE        pold = p;7 N0 Q6 C2 v$ B: d- n1 f
#endif
$ V  s+ f- {7 `1 N4 `
/ h* P$ B) `4 v) c5 Y$ E5 K        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
) y  l# e9 y3 ^, s+ Z$ D        QueueFlush();3 [- t+ d' A+ x' }- B4 v
, }, ~) T% r( j/ y. a  T  M
        internal.SaveState( p );# J- e3 x* ]; Z- w' p2 C1 H
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* o! v  C4 t; i6 s2 O5 @7 @7 }2 z# s9 b) g! M
        // VRC64 r4 s2 W, t* v2 @$ Z' x
        if( exsound_select & 0x01 ) {3 t. d$ Z+ T/ d6 F9 e; h$ D
                vrc6.SaveState( p );
1 W5 E/ Z* ^- r& v, }                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding- f1 w. E8 w# s+ e7 I7 }
        }3 K" `3 T# m) d
        // VRC7 (not support): e) l- d1 O" [' w' t) |; R
        if( exsound_select & 0x02 ) {
. l- T3 p/ j+ l& {5 \                vrc7.SaveState( p );+ I2 V# |8 C. O0 {0 Q! R
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- t& V1 E# w! ]. n: q8 d8 K$ J
        }: T! t+ ?% s. r4 r  @
        // FDS' w1 ]( R: ]9 |3 T
        if( exsound_select & 0x04 ) {
; w& [8 g" e8 M( Y1 F5 Z) `                fds.SaveState( p );% k$ Q7 L; V% M- f* Y* B
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 N+ F5 U1 J5 R9 ~5 L
        }! |" w$ M" C! o7 g0 Y( g7 j" ~
        // MMC5
$ X7 n2 h9 @3 {6 U- m        if( exsound_select & 0x08 ) {0 L# Q  E/ V1 t8 j* L7 e
                mmc5.SaveState( p );9 `+ B) \$ O3 i4 U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 r! Q% h- v2 _8 l9 G* g
        }4 G! Z2 j' g, u( q! t
        // N106
7 |/ ~& [* Z7 k/ C& g+ Z+ b5 Y        if( exsound_select & 0x10 ) {9 b9 @# ~8 ]$ R8 r; c( p% \- U
                n106.SaveState( p );( f2 W2 h( e6 ?! e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ w% _& E- h9 r) x' i# G9 g, D  I5 k1 s
        }8 n' @" l5 {$ w8 _! R, M& u
        // FME7
" V2 P' S! O- Q2 i4 N' e- U        if( exsound_select & 0x20 ) {% e& N6 M, z; X7 _, V
                fme7.SaveState( p );. n! g; z3 q- Q9 G, x6 Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- o% z% ?1 N! x$ r! [8 W8 Y
        }
8 `' E- @9 z8 k  K( ~0 C
. o2 N& p+ u! r#ifdef        _DEBUG
  H0 f" u1 ~, C# S4 M! {DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
# q) w" |% P5 u1 l( c6 D#endif
8 k4 i1 L8 ]! }' y2 J9 I  i}
* M( |9 P3 N- o% ]/ H3 O  I1 Z" j9 @; u* _) L
void        APU::LoadState( LPBYTE p )) d0 t3 }' o0 p* |5 n
{
- [" f* D7 d8 n; n        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
4 O$ B) _/ C! [# @' a: w5 S        QueueClear();
( M3 N/ i9 a  B: [6 l
. o4 T, A& I/ @5 N1 Y        internal.LoadState( p );
! v* ?6 d' F0 w        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 o/ P& g$ c6 \4 x2 A$ }7 h
* ]1 ?5 Q  i6 L6 d        // VRC6& o( y. {; ?" d% S/ @1 y- B" ]1 ~
        if( exsound_select & 0x01 ) {6 @& W$ E" d1 J0 \
                vrc6.LoadState( p );9 M6 U, R. Q+ O1 ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 W1 p% p9 L- @" C        }% p5 r, c# L5 Z$ x/ @
        // VRC7 (not support)
. j; P  s% w8 l" y        if( exsound_select & 0x02 ) {/ L# V4 M' S# _  r9 j
                vrc7.LoadState( p );
$ j) g0 ?; r0 s, t+ r& _1 y, B                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- v9 P8 I' w' i        }3 `5 ?- S, [9 k" x* Z2 C' Y
        // FDS
* L* L* f0 q5 N        if( exsound_select & 0x04 ) {9 w; w2 K) k/ I6 s
                fds.LoadState( p );
8 P: f) O3 q* F5 c: ]7 c                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 Z8 p- h1 u8 j' Y        }+ f8 t# C0 C# C! q3 E
        // MMC5( C4 {; s0 T" t) h/ s/ L. V8 T0 ]! h4 b
        if( exsound_select & 0x08 ) {
+ |  x9 E* l9 t; Z2 q0 P/ w0 j                mmc5.LoadState( p );  k. Y& K5 D1 E
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# _% t' x; j! ]; U( x
        }0 ?; l$ I# {7 }! g! J! u# w) r
        // N106% N* d2 v: f( a/ G
        if( exsound_select & 0x10 ) {
4 I+ z4 m/ n7 s0 T! S5 Y/ u9 e- |                n106.LoadState( p );
' Y4 p$ E9 S' U! K! J6 h4 s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 ]" g2 @( F5 X5 }8 `$ I        }
' S0 \: |+ S; M' W        // FME7
% q. \- ]6 @2 M- g% u% j' ~% D  C7 N2 R        if( exsound_select & 0x20 ) {
' L! B1 l5 w6 H                fme7.LoadState( p );
9 W  ~! {2 T2 l& Q# }0 \8 e                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. Z% ?! V/ A, C
        }3 [, e6 e9 H: X7 W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % c. Q" d# Y1 U0 \2 }' E+ |
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 F6 p. P0 `$ c+ J5 \, s  a感激不尽~~
6 x7 D8 q& L* L. y6 m' y, O
恩 我對模擬器不是很有研究,
+ R" @5 a, J: ?2 Q雖然要了解源碼內容,可能不是很困難,( U2 _0 c: A" B" M
不過還是要花時間,個人目前蠻忙碌的。) t% b* s" w1 l& p+ h2 h

$ B8 ]8 G# u' D' n* U% O2 E給你一個朋友的MSN,你可以跟他討論看看,1 H1 j$ a  k: A4 @& r$ `" y
他本身是程式設計師,也對FC模擬器很有興趣。
, _% u; g+ F: j- Y: r( U# j4 P" o+ C  q$ f! I5 f3 f1 a9 f
MSN我就PM到你的信箱了。6 z( P' E5 M3 j( I7 U
$ T* {) {1 Q$ _( 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 发表 ( m; i# t* }. N8 B
呵…… 谢过团长大人~~

' ~0 A- k6 I$ q+ C2 ^5 m( }+ ~8 L# ~# G* \" ]7 k3 F3 ~+ K
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 W: @! ?" w3 e3 A团长的朋友都是神,那团长就是神的boss。
) i: p, C3 G- u' U: z7 G2 g
哈 不敢當,我只是個平凡人,
6 b/ I2 e7 W( m$ I. J- {& K5 o要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" e: e( W! W* v/ yZYH
" K8 K& Y9 J% v; wQQ:414734306, c+ u- w1 i8 b8 o0 P
Mail:zyh-01@126.com7 H+ t* U: @9 L; t2 _& ]
# l8 H+ }3 w% z+ ], W, v5 N' j
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
2 K6 q" E. t! F' G再次对团长大人和悠悠哥的无私帮助表示感谢~~
, ~# U) o4 x" ~! A
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-7 21:57 , Processed in 1.083985 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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