EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。7 _+ U6 s1 B# [0 G/ ?
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
4 y, s' I" @# O3 @3 s这里有相应的模拟器源码,就当送给大侠了~~
' }8 R* ^; _* M) y: }3 i% p; lhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 B$ _6 V. D7 N  _
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* i$ @. I3 N: P; P. U( |8 j7 ^1 S& W: t; W楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& p+ B" o! H) z8 ^* O这里有相应的模拟器源码,就当送给大侠 ...
5 [3 o( l. n) B" B* ]
聲音部分(Audoi Process Unit = APU):- f  y+ _8 P. C" v6 u5 O
.\NES\APU.cpp
1 i$ k3 I" k: G# p+ Q5 S.\NES\APU.h
. r; E4 @) Y5 D3 V' Q
: d- A1 U$ u3 {$ N$ x
* T# s6 L/ o+ o! d4 `- R影像處理部份(Picture Processing Unit = PPU):
4 g8 y* p. ^) ^. ~/ y! c( ]8 X.\NES\PPU.cpp6 C4 H. Y8 j0 k0 V. n4 }* W. w
.\NES\PPU.h7 B2 H) `( p: F4 E4 Z- P

( a4 o! ?4 O0 X& X如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:) s, G9 \! ~' _3 r- R  c: q
(由于很多专用术语和算法机理都不明白,所以看不大懂……)# H, |/ {+ y: P' T7 ?
//////////////////////////////////////////////////////////////////////////
: v/ f1 v; K/ i2 |- ^//                                                                      //  G9 F8 ~2 x+ b* P: s1 K! E
//      NES APU core                                                    //  \9 x' i* k- E* v5 q  b$ M+ q; o& Z
//                                                           Norix      //
' g% v8 k3 H9 g0 r  j7 f4 J1 h//                                               written     2002/06/27 //
  B' W" v, a6 ?& k9 f//                                               last modify ----/--/-- //
3 P; E) k! }: M$ C/ ^/ @6 D//////////////////////////////////////////////////////////////////////////
- E6 K: E- x6 s$ R% H. E- _0 \#include "DebugOut.h"3 {0 ]# w. W! T4 U
#include "App.h"3 y# J- g$ m9 O. U/ {7 M
#include "Config.h"
) ~, y5 Z4 E% M
: M/ c- C- K& D! ^7 C#include "nes.h": I. T/ J5 b* k: Q( z, o
#include "mmu.h"
9 C1 w/ ?- J2 f8 b5 C% i& k( D# q#include "cpu.h"
8 c1 Y. o7 M- s* E5 {#include "ppu.h"
# d% V' x- l; g/ [6 j#include "rom.h"/ {/ r2 T0 [* m  ~9 a( Q
#include "apu.h"2 W( h. F/ Z  O, H( |3 t+ p
# h3 e6 s( f( Q# J
// Volume adjust
* s0 @" T* |- V( l3 y. @9 A2 ]( B// Internal sounds2 P: @* A1 @; h/ z( j. U6 V
#define        RECTANGLE_VOL        (0x0F0)/ M1 D& A+ |& E* G
#define        TRIANGLE_VOL        (0x130)
6 i( O' A7 r# |6 K0 g4 H7 t, @& u#define        NOISE_VOL        (0x0C0)
# W4 n; h) C7 d) I; v#define        DPCM_VOL        (0x0F0)
5 E, \( l1 ^* w9 L! a& k// Extra sounds* _* D, a( G& w4 E' ^
#define        VRC6_VOL        (0x0F0)
; s/ P% H9 w5 a, e8 ^. I#define        VRC7_VOL        (0x130)
( q4 A7 w5 C' X6 {. {3 `5 d#define        FDS_VOL                (0x0F0)' V' Q& Y/ @) N9 z
#define        MMC5_VOL        (0x0F0)
9 j1 M- u+ A' Q) V, L! L#define        N106_VOL        (0x088)
' v' E3 ~# l$ ^. m9 G8 A#define        FME7_VOL        (0x130)) ]! C1 M& A1 W. _% `0 G) w& N& e
6 \' n* e! J" B# c; v4 h
APU::APU( NES* parent )1 r2 q+ Q. o2 _( Q7 r* C/ X, ?6 }
{' v9 I$ X0 V9 x. ]' r3 O& w: E) M/ _
        exsound_select = 0;8 L& L7 J" d4 f% g) G! n! ~! ~
  l, b+ o$ T3 U
        nes = parent;
. [0 Q' w1 F: }! ~        internal.SetParent( parent );
- z) l0 X8 \2 [9 a- H0 L1 |$ s: y$ \
        last_data = last_diff = 0;, a% F6 |2 e4 e* O
5 ^: U8 B6 a4 P# H! J- i
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 i* n" A. w( e3 p& z
0 _6 w" t" F0 B: A2 d3 l* R
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 f4 U' @6 b9 P- u0 m
        ZEROMEMORY( &queue, sizeof(queue) );
( `" K9 s& z$ t- k# ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 L; g( P9 B5 P! |$ e. ^. z; t* ^7 t
) J! y; Y( B! N: ?4 _
        for( INT i = 0; i < 16; i++ ) {
1 E9 P5 \' ?' H( U0 |                m_bMute = TRUE;
" m% G! I- x" C0 Y        }
( G5 r' c8 {/ J- r4 l) u3 I}
% d4 }1 n: W9 K, r+ e+ K3 k
: D) \) w5 o+ }( O% z9 y* E% O, r4 zAPU::~APU(): `6 n1 n1 I' e) U+ A* x; [
{
/ ^2 q# H2 V- G: d& K}3 l  a% B6 K/ W0 S7 N% C  o

" J5 w- O8 n) t! C% I1 u3 }void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 q! h& [' F7 A) s
{
: n/ q; S$ o4 C, ^        queue.data[queue.wrptr].time = writetime;
& b1 u7 q0 x# k9 {5 Y' L1 t% N        queue.data[queue.wrptr].addr = addr;
/ j& c& B9 F: V7 k" F        queue.data[queue.wrptr].data = data;
# ]" \. W3 a8 X- [8 h9 g* z        queue.wrptr++;/ }% S4 P4 E  v7 T) p7 v
        queue.wrptr&=QUEUE_LENGTH-1;
0 B6 d* g3 x) O/ J4 ^        if( queue.wrptr == queue.rdptr ) {
: P. d* D& Z  u$ A% M. h/ J: g                DEBUGOUT( "queue overflow.\n" );
" I" u7 r& l* y        }
/ e6 }% C1 U  K2 Q5 r+ n8 j}
' g' Y( V/ y6 n  k  d# d' Y5 o- I, o; ]7 c, u) a' ?, |! ~6 d
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* \. s( @% e# Y! a$ D{
2 S# P3 r6 B. W: X% P        if( queue.wrptr == queue.rdptr ) {
9 B/ Y8 h" q" `, A5 ]# l) r9 A6 Z                return        FALSE;1 l6 r+ h/ s3 A& t0 r/ e
        }  R$ Z6 P6 L8 P! a) I* h" @8 v3 J
        if( queue.data[queue.rdptr].time <= writetime ) {+ ]& q( a1 o: ~( s; M6 r; l
                ret = queue.data[queue.rdptr];  h! B# w4 I( ~7 A: ]' b
                queue.rdptr++;
& w8 F$ X/ [7 v, u& ^4 b1 x# C                queue.rdptr&=QUEUE_LENGTH-1;
3 P; {' z( T/ L* i) ^! U) U4 ?                return        TRUE;! \: j2 q5 E0 r1 c
        }& m9 c  N/ g4 [/ Y* P, L
        return        FALSE;
5 w' O- \& G4 [. Y8 \}8 S( [. K; `  U$ {8 L" c

3 W: Q6 S: J, a/ L6 jvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: ~8 Q0 T0 x. G  I{
* e( D) c% S2 m6 X: G; Z/ f        exqueue.data[exqueue.wrptr].time = writetime;) g7 M3 D4 [1 Z9 |2 a; q2 B
        exqueue.data[exqueue.wrptr].addr = addr;
& W0 u6 t! R7 J7 T- ?. s& Q# x        exqueue.data[exqueue.wrptr].data = data;
, z  S5 ]% F5 P        exqueue.wrptr++;
5 |) e: N) @9 L) b        exqueue.wrptr&=QUEUE_LENGTH-1;' c: p4 w$ k2 `) k- N7 ]
        if( exqueue.wrptr == exqueue.rdptr ) {7 i  ?. F" H. z
                DEBUGOUT( "exqueue overflow.\n" );
) @' J' _$ l" \' T: T: \; q' e        }6 W5 j0 G! H9 c' {9 Q9 w1 w  ]
}
: E$ A& Z) i8 s# r. o2 h2 o' F0 Z. q: J0 G* E: j6 J
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )+ n- T1 ^  T, M6 M* }
{! x0 t8 |6 W8 T3 j. E+ }
        if( exqueue.wrptr == exqueue.rdptr ) {! k. k  N% x3 C1 U5 o4 U/ c0 b
                return        FALSE;) ^8 @0 p" u0 n( T' C
        }
% f2 c; f( R- ~, x; q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
& F7 T4 k, B( n( ^& J                ret = exqueue.data[exqueue.rdptr];# t  ?  M0 K/ `; Z9 {$ Y
                exqueue.rdptr++;+ B* X# b7 F0 P
                exqueue.rdptr&=QUEUE_LENGTH-1;1 x! g7 ^) K3 @. g2 k, W
                return        TRUE;
. j  e) i  X4 k' S" b( B6 @        }0 q; t3 F/ t2 U( L. R1 g: [
        return        FALSE;+ w, k% X' c; Z+ h
}
  Y& i; u+ q( t- O, H5 m6 U% a" Y& |4 j; A! z& U5 g+ \
void        APU::QueueClear()
/ J2 T7 w8 ]! K0 R4 P{
( a8 P! Z' ]/ e' a7 v7 U% Q        ZEROMEMORY( &queue, sizeof(queue) );# a/ L3 m2 E2 K  t! [! s
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 u8 h& f# v3 R) Z9 {' k9 f2 k
}$ ]5 w* D- N! `: T2 _+ q
* T7 G7 F! A" ?/ x
void        APU::QueueFlush()6 {; |6 c7 u$ l
{
% t7 F5 Z8 I, `4 R        while( queue.wrptr != queue.rdptr ) {
; x% @& {- [) d& x  t: ~6 k                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );/ N/ O: B% ~" W- ]3 F8 J0 ^
                queue.rdptr++;' B3 C4 P, t( t8 A8 p
                queue.rdptr&=QUEUE_LENGTH-1;' D( H6 h* Z" t! y3 Q
        }+ e- u" F5 ], Z. ^/ P% K& w
. p6 \! Z" X# m, C& T' ~3 i
        while( exqueue.wrptr != exqueue.rdptr ) {& h/ t! k2 k& q  f+ b- P2 [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );+ t. a. l) x  [' |, n# [% A
                exqueue.rdptr++;/ N' c8 v$ }- {
                exqueue.rdptr&=QUEUE_LENGTH-1;* u$ d- E; U* S- F5 r  D3 a9 m
        }, M; _0 x- L% M7 d: N1 d8 t$ p5 }
}! I5 F. h& P5 o$ r- a- Q
# I' e, y: _7 @# P$ J# S: p. ]
void        APU::SoundSetup()
2 G; j. d5 _& W8 k{3 X% }# r6 Q. C% ]9 T" h* Q
        FLOAT        fClock = nes->nescfg->CpuClock;
  A; ~1 a' L. `9 {, g) x3 c        INT        nRate = (INT)Config.sound.nRate;, p( v5 H! f7 q9 ]# l7 e: w: `3 ]+ j
        internal.Setup( fClock, nRate );5 h( i1 P8 p2 n5 C6 W' p
        vrc6.Setup( fClock, nRate );, _0 U' ~7 d* n$ Z4 T6 R
        vrc7.Setup( fClock, nRate );
3 ?: k6 V0 ~) Q2 T6 O7 f. Z. q        mmc5.Setup( fClock, nRate );
% E3 z- v3 h0 j& s8 i6 w* b" V        fds.Setup ( fClock, nRate );  U1 h. K! d# S; Z8 }! q& J
        n106.Setup( fClock, nRate );- x" I% ^6 n. Y6 N
        fme7.Setup( fClock, nRate );! V# j6 ^- X& h9 I) I% ]' V
}6 o) r" h. A( H7 w( {3 m
4 C: g! a2 E% N- _( \
void        APU::Reset()
0 x2 t* w4 q' o. v! |! f$ J4 R1 P{$ [& L! A# W+ O& A& j5 J$ M
        ZEROMEMORY( &queue, sizeof(queue) );  G+ @  k4 `! n5 s
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, s. t/ k6 |4 n4 j' w5 U. O" K3 i. l& R+ Q! X6 P- e
        elapsed_time = 0;; K/ [8 `, N' h8 \' F5 L# r

$ [- w5 }6 }8 P/ H        FLOAT        fClock = nes->nescfg->CpuClock;" K  o  g1 {* b# [
        INT        nRate = (INT)Config.sound.nRate;
7 E/ M: F9 ~" A        internal.Reset( fClock, nRate );0 u6 j" ~9 U' l
        vrc6.Reset( fClock, nRate );
/ v' P5 m. X& ^        vrc7.Reset( fClock, nRate );6 g2 M! h/ A# |. y. C* v8 A
        mmc5.Reset( fClock, nRate );
2 D" I; q" Y  h9 x/ o        fds.Reset ( fClock, nRate );
+ ?+ C- V  n3 a9 n4 V        n106.Reset( fClock, nRate );
$ ^( I+ l. u1 x( x5 I' [* p        fme7.Reset( fClock, nRate );+ o2 x, w$ o2 y- G- y, M

: ~5 z9 i$ C4 a. Q5 b5 a4 e. X        SoundSetup();
3 m' l4 [8 f! l9 s/ Y}
% q  L) S" B+ J8 a3 O
( J! F; F, o* _/ J( _/ v& ovoid        APU::SelectExSound( BYTE data )
& w: Z4 _$ F( W{1 L0 W# J# _" |3 P9 ]3 t
        exsound_select = data;
- a; _, s# K. b2 G; b0 ]. z}
* b8 }+ ^5 G' d7 S6 a
$ z2 B. A7 N0 S) A2 Y: [+ c  nBYTE        APU::Read( WORD addr ); H- r+ s7 D0 X/ w; q
{) A# L2 e. R2 V( u4 m9 R
        return        internal.SyncRead( addr );. n5 f1 {- P9 o9 f& X
}
9 w& t! i$ D: J9 s! |4 \
1 _8 {6 E) x1 o- z. w# i8 Qvoid        APU::Write( WORD addr, BYTE data )9 W, a% h4 W$ J# c4 a" V$ J0 g
{; Y0 y0 _$ t" ~$ v
        // $4018偼VirtuaNES屌桳億乕僩
9 L; n' w' u8 u9 f: u/ L        if( addr >= 0x4000 && addr <= 0x401F ) {
: S- U4 Q; K/ N3 \' Y" l                internal.SyncWrite( addr, data );8 Y# D! u2 Z% Z9 o: d- v
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
6 {3 B/ H( U1 Y1 ]1 F        }
5 }5 Q  a4 Q% G}. J3 |+ J+ O3 A2 ?; M% S
1 t, [3 `; d: C1 ~4 C9 i
BYTE        APU::ExRead( WORD addr )
* @. o4 w/ s$ M; ~! k{
6 L" a, p  |2 hBYTE        data = 0;( l  m5 O; {: K% B3 I$ z/ Z9 u

2 w2 B& H! k" T8 Q- a        if( exsound_select & 0x10 ) {# s0 n: \3 v1 L8 f
                if( addr == 0x4800 ) {
8 D! H) t" A6 M) v& `) g                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ h' v" k! g. r7 U  G" e7 L
                }) w! D0 e: n7 s% _: e
        }, L# O3 A* k: }. D
        if( exsound_select & 0x04 ) {( N% Z! i3 F4 g- h
                if( addr >= 0x4040 && addr < 0x4100 ) {
( y1 U+ P( y9 c, U( }$ C                        data = fds.SyncRead( addr );
" p8 V6 c! |2 c5 l0 @( ?                }8 D0 J: Q" L5 e  I( A5 I' z
        }
; t' x" [, _$ A# w! C        if( exsound_select & 0x08 ) {
3 T2 ]! Q# d! n( C, C' Z5 j                if( addr >= 0x5000 && addr <= 0x5015 ) {
: |! J2 R9 Q3 t- ~7 r+ j                        data = mmc5.SyncRead( addr );( W* G+ z- k$ i: D$ y
                }0 _: o4 C5 }& K/ r7 M* _
        }4 \- ]- d- _3 y/ V- W- @
  R4 l- f1 ~8 a+ T- ]( J; A
        return        data;0 e, l! s. V3 L" u2 R
}
9 H# e6 j; o) k7 v+ x  p2 C9 v( ~/ f% T* j, H. y
void        APU::ExWrite( WORD addr, BYTE data )9 \. [7 q- v0 v  t' }" Y
{; r" q2 o* T7 C. b3 R# C4 A) c: Z  H
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 A+ y  H9 B( [3 i( h3 r  o1 G1 W  `  b7 q1 m8 o0 A. b
        if( exsound_select & 0x04 ) {. t  ~, ?* c% N4 }5 O" B8 G
                if( addr >= 0x4040 && addr < 0x4100 ) {
; f/ C0 v) Q0 L; v7 B                        fds.SyncWrite( addr, data );9 e/ _. n8 m" P2 ?$ ^
                }
$ b- Y% l( ]: A0 |# C! N        }+ Q5 g  q. G/ V$ g1 k

8 G; [8 {4 R+ ^: p& \        if( exsound_select & 0x08 ) {, V* S' K7 ]' J, F
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ M* K" k. w8 X5 z! j& ?! C                        mmc5.SyncWrite( addr, data );+ w. b6 q, A5 o/ h* h
                }4 s1 ~* m; Y/ l) I
        }
- A# Q# K) H8 ?. A: U" a}
  p: P  M4 ~. B! H7 P5 ?2 G' \2 Q. a8 p" w; ?  L
void        APU::Sync()
6 F, [# y% L- l- ^. T{
7 B. _. u& B% {* J4 z}3 @" H0 f: `  H4 p0 `
: g( I! t; w# C' R0 p7 u- W, C
void        APU::SyncDPCM( INT cycles )
2 R  g. _5 Q$ y  Z, ]{
/ B1 x, E: F1 i        internal.Sync( cycles );
6 m" q1 Z. D! G6 k7 ~" n4 R7 k$ f, t7 x8 ^  R8 s1 a( z
        if( exsound_select & 0x04 ) {& r4 \: V! O7 Q5 {
                fds.Sync( cycles );
. A' `4 S& N) p        }
5 R% @! {7 C; s0 t9 o' {2 E2 f        if( exsound_select & 0x08 ) {
) J# |* a! ?4 M  d$ m# u                mmc5.Sync( cycles );. U1 ^+ G+ e4 B; x' J1 y- r9 H
        }& S( c4 V- J, D2 i# t
}) H) k7 b; ~; z) b# ?0 ?

5 C" ^7 r2 }! Gvoid        APU::WriteProcess( WORD addr, BYTE data )- `( l5 F' j8 j+ L; v
{1 ~" R5 N0 c1 W8 p+ [
        // $4018偼VirtuaNES屌桳億乕僩
  R0 e3 e3 F0 i$ P2 E3 R/ S        if( addr >= 0x4000 && addr <= 0x401F ) {) I) X" S) O+ ^! ~: h1 ]2 }
                internal.Write( addr, data );: Z. r+ N. y3 k* U! D8 ?
        }
6 k+ u& _; ^5 L) Y}7 i0 P% Z3 G8 K: q8 J# _! S& ^

, w+ n# e3 }1 T( f  G- ?% U7 uvoid        APU::WriteExProcess( WORD addr, BYTE data ); q) m& Q9 `" p: o
{
, J5 U! H( r/ i% b: h- y9 p        if( exsound_select & 0x01 ) {
, \" s. k/ Z, J) O, `0 x                vrc6.Write( addr, data );$ ?- w( t/ w  i6 b, o! b, U- |4 L. Q
        }' f9 l) N& c' |8 W" I
        if( exsound_select & 0x02 ) {6 y6 m: U7 C* A) @+ g
                vrc7.Write( addr, data );" Y& o6 u/ \7 s
        }
0 N/ a& J2 x2 [% ~/ b        if( exsound_select & 0x04 ) {
+ g7 J6 _- K( o                fds.Write( addr, data );$ p6 e$ k. d, b
        }
3 L# U+ J* s  @  Y' v        if( exsound_select & 0x08 ) {' @: d' a6 J+ s2 C0 q
                mmc5.Write( addr, data );
" g% t% y/ A& l8 X        }
$ u3 n- S: y1 F* n" S% K- s        if( exsound_select & 0x10 ) {
* W* ]( y6 L+ B                if( addr == 0x0000 ) {) V. i# f* @% p. a6 {. A
                        BYTE        dummy = n106.Read( addr );
1 n6 P3 r* H7 e1 N' d  U9 m, n( W                } else {* @$ U: o/ K2 P) o  H
                        n106.Write( addr, data );; b9 Z2 K' n$ W5 w3 P
                }
; a1 X' \; h3 g; T  c        }
3 m# x9 Q! _  G/ {0 E        if( exsound_select & 0x20 ) {
( N$ T' v- M$ M* f$ x, _                fme7.Write( addr, data );
8 C: U1 E' c, W, j; `; g        }8 a3 t! E; I/ l( \
}( y' |/ ~9 E- z+ f
- B3 Z4 F: k( y+ e8 g
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )0 D" B0 |$ l: u' D7 b- U4 N
{1 e+ K7 e' C2 s- d) z, m
INT        nBits = Config.sound.nBits;
; A! e& w( e+ g4 D% k9 pDWORD        dwLength = dwSize / (nBits/8);$ X  x- d0 [4 @# \" f7 p9 d
INT        output;
7 `( O2 ]* [  T1 h6 h* m, FQUEUEDATA q;. L; g) {+ {+ w6 H3 S) T" n2 L( f4 \
DWORD        writetime;3 m# m1 z/ s4 U3 _3 X, ?9 c
5 C' Z2 n- _7 J+ V$ J: r9 z) H
LPSHORT        pSoundBuf = m_SoundBuffer;
- x& h5 _: {1 `- i# U) f( w2 E5 U) _2 ZINT        nCcount = 0;. W( _+ B- e  T5 ?+ l, u' f

1 F# x& k- ]- q+ J! P4 g" i: V. EINT        nFilterType = Config.sound.nFilterType;
' [6 @! E! h( j
2 J  ?" q; y0 Q* Y* d6 D        if( !Config.sound.bEnable ) {7 p* \. _9 ^7 b& O1 Z
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
: O! Z/ w/ D4 f& R                return;
* \; d: @  j  I. L        }
, }, o. }. H/ u& L; O
9 M/ k' w& o8 C+ t* c2 \9 I        // Volume setup# p7 y' l2 B' Y4 B9 H1 M
        //  0:Master
" ~* R; s5 `9 Y% u- f! O) C        //  1:Rectangle 1
" z1 t, F* \( Y' E        //  2:Rectangle 2
2 z1 N" M  L' l. @; J        //  3:Triangle
8 i) R! a: H( G2 W        //  4:Noise
2 t& s9 q4 }+ P+ G2 q* b3 @        //  5:DPCM. ~" v6 q1 H5 }" F3 u
        //  6:VRC6  {) C# Z# S& a" p8 d$ U
        //  7:VRC7  W/ I: [: L5 C; k! m8 S& ~
        //  8:FDS
6 o' F3 l2 k; N8 d* [8 h        //  9:MMC5
7 [5 V; D7 R- }$ P. G; V- ]        // 10:N106+ t3 Q. N+ a( s4 A1 s% r
        // 11:FME7
& O4 J6 T" ?* q0 `4 F8 n        INT        vol[24];/ l- W! @8 e7 d  I) A3 J  }
        BOOL*        bMute = m_bMute;. q. q# G: P/ J5 X* ]
        SHORT*        nVolume = Config.sound.nVolume;8 A1 r- B) |2 r* V" r

% |  w, h, @; i9 F# [' D        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' N0 ^2 V! ~9 o- A3 v+ a. t8 ~
5 ]. N2 a) d" L. o, X  f  o7 U        // Internal, a1 c  T, G4 J" j, ~* j6 O
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 u$ a) {) W# j5 c
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
- Y1 f$ m& B4 c! s8 A% F        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;8 z4 Y0 U; ?- L8 a. M; t  s
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;$ D0 q% c$ b9 }
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
3 Y( t* n3 S* G6 t6 w  m1 K2 q9 e7 J2 C* c2 F+ q
        // VRC6/ S( g' t% X& o3 k
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  V7 }! T/ C5 P1 [$ d8 E# q
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 Y# U6 y- E8 k9 q  r        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ d- |, S, ?6 C; g7 Y+ k
6 t$ j' ^5 s5 C        // VRC7: t4 K+ w) V# Q0 O: N0 H
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ o( O6 w( }% `) @0 H8 R1 C+ _! `$ R6 a# D! z  k6 o2 P
        // FDS
' E- B( m( J: ?' t        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ f" l1 W, X2 V4 Y% t# ?6 F! D4 u: C, x2 [' _! T
        // MMC5& F. W* Q3 r* H1 K  b
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# O3 C/ f6 @3 J; i! ]" @  ^        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 d3 F% p& V( T  \
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 C& t5 k; k: ^5 s

" D6 A& ^9 k  S9 n/ P# |        // N106& N* i( y3 J$ o0 O7 K
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% Z  t6 c! W. C/ B        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! |3 t3 B1 ^# O0 V" F( C) ?        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% v+ P8 V/ O% `: n! \
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; N- W+ \' z  m) l& n# P
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 r8 p- O' O7 i% Y. H        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ `3 t1 w0 @! j2 c5 Z1 \        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" X- o% r, [3 e) s. C: s        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' p0 v, V8 J! j4 z4 R% d# \5 W* V/ n* N1 c, _5 `7 \8 D4 f
        // FME7& C. R/ _9 T" B9 h, ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ G4 n# X' z3 V+ a) d# K% n2 [4 L        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 v: d* b  W' J/ S+ x" @. s& E1 O
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" Q  \1 n7 [8 K5 _
  {* d' b  ?% m9 g//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
( \: E/ f7 J( v- r  |) W        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' T' U. B( t1 K, o+ V8 t3 Y+ y* ~# [
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟  D( O7 i! l. O( @; j' b/ b
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
# z0 h) P5 f0 M+ n& ~. y                QueueFlush();
7 i: P$ D4 W; s+ b        }
: P- R4 W" v: D' ?" \5 F$ ]) i/ ?" g+ `: M
        while( dwLength-- ) {
% Z$ E! s' b/ O2 P                writetime = (DWORD)elapsed_time;/ }' {* p  L7 i+ y, U6 R6 ]: G

* U9 l8 U& _+ b, v0 J/ _9 G$ O3 ^                while( GetQueue( writetime, q ) ) {/ q! S$ b0 B: Q7 m! ?1 g7 ~
                        WriteProcess( q.addr, q.data );6 E4 p7 E# L2 J& f0 ^  i+ T: h
                }9 ?: i% ]- {# T' |! f
3 [- H* z: g* }- W: M3 ^
                while( GetExQueue( writetime, q ) ) {
/ e/ p6 |8 s: r$ u% c7 n; d                        WriteExProcess( q.addr, q.data );
+ Y3 t* i- _# `8 j  {                }% R# v& Z1 |, ~' J6 B& J
" w- \. A) h4 {1 \& m
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ H4 s( T) m, \0 ^$ w9 U* J5 V" Y
                output = 0;
6 X) r" i% m1 ?# h$ w: c                output += internal.Process( 0 )*vol[0];
. I3 ~$ Q/ r6 l! u  W1 ]+ F                output += internal.Process( 1 )*vol[1];9 b8 Q, U, U9 N1 n
                output += internal.Process( 2 )*vol[2];
3 e, c# ~/ U+ @: {9 T$ C                output += internal.Process( 3 )*vol[3];
9 {0 c& ^/ C" K$ ]# c  F                output += internal.Process( 4 )*vol[4];. Q' Z4 y9 L0 U; j
' w6 g* m0 y9 `" e. M! E$ m
                if( exsound_select & 0x01 ) {# p: c0 _+ p# l, X
                        output += vrc6.Process( 0 )*vol[5];
: d) m# t4 t3 \9 A3 r" j                        output += vrc6.Process( 1 )*vol[6];
( J. |6 D& A! `! N( ~& u% R                        output += vrc6.Process( 2 )*vol[7];
- u( Q0 K! ]* U                }
! k4 s  i! m1 X6 M4 ~                if( exsound_select & 0x02 ) {
+ w5 q, w5 r6 O1 h4 ^; }                        output += vrc7.Process( 0 )*vol[8];$ R: A! U- e0 ^9 E, J6 z& u( H& V
                }
  z: N- u+ n: g/ M5 F" J3 t- T                if( exsound_select & 0x04 ) {! E7 V/ h& p( J( w' A+ n
                        output += fds.Process( 0 )*vol[9];- t% _  j9 W( ]4 k& a
                }
# m# ^& Q, B9 u2 i                if( exsound_select & 0x08 ) {" y* t# P; G7 r  a  N  k# U0 n
                        output += mmc5.Process( 0 )*vol[10];
2 Z; f* u; Y& w                        output += mmc5.Process( 1 )*vol[11];0 K1 t! B+ a5 W3 c% t
                        output += mmc5.Process( 2 )*vol[12];. S6 I6 w7 Z- v5 W4 ]9 q- [- E4 J
                }
( r6 X- k* Z3 [6 z( g) ~0 Q                if( exsound_select & 0x10 ) {
! V) G2 h# a+ R) k                        output += n106.Process( 0 )*vol[13];" h, T1 |' f# H- v: O
                        output += n106.Process( 1 )*vol[14];
0 Z. n; `' A! K- O                        output += n106.Process( 2 )*vol[15];
, W7 W4 V& g0 h" o0 q( R6 `                        output += n106.Process( 3 )*vol[16];7 N& v5 ^' o1 s2 Y
                        output += n106.Process( 4 )*vol[17];% q9 [- i9 D) V/ `
                        output += n106.Process( 5 )*vol[18];. j: x' \: m4 Q5 ~) l$ d
                        output += n106.Process( 6 )*vol[19];
% F5 K. s- ^) E3 t2 x                        output += n106.Process( 7 )*vol[20];7 G& h. |; J( g0 {& M4 ^
                }
* V) K: p8 K6 r0 M8 [                if( exsound_select & 0x20 ) {( r3 O; K. r; b: {. l; E
                        fme7.Process( 3 );        // Envelope & Noise9 Y3 b4 J+ k2 g1 R9 Q
                        output += fme7.Process( 0 )*vol[21];# @, D4 z: L* j% s0 ?" Z
                        output += fme7.Process( 1 )*vol[22];
% s6 h  L7 s8 N  ]0 A                        output += fme7.Process( 2 )*vol[23];
- M/ l( f7 [4 d, L                }
/ H! Z1 R3 k; ~2 c3 V" T0 Y2 q; |" `! r
                output >>= 8;/ U8 U& W  B& w2 z7 d. _- ~& {
+ {( j! _1 g* h* E  _
                if( nFilterType == 1 ) {" O1 P9 ^& `) m  X' k
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 Z3 U# {& k9 I& V+ U                        output = (lowpass_filter[0]+output)/2;
( |) P" S" E$ {( L- _                        lowpass_filter[0] = output;. k. k2 l( N: M- m: j1 m1 ^
                } else if( nFilterType == 2 ) {/ l0 w- V0 l+ `6 g+ N2 F9 U2 I( h
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 R. V6 `- {# H" w7 t0 M                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;( E: E, U1 V, L" d- T  m7 Q
                        lowpass_filter[1] = lowpass_filter[0];9 F. C5 P, y; H( p
                        lowpass_filter[0] = output;! v3 ~2 I- J$ ]' A6 B# x4 q& }
                } else if( nFilterType == 3 ) {- X7 B) c) ]- A! F' m# s" ~+ ~
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
: _8 d  G% [! y                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;% A+ {" N) N  b1 ]3 Z
                        lowpass_filter[2] = lowpass_filter[1];; m. d* [+ g" J# X6 D' z( X
                        lowpass_filter[1] = lowpass_filter[0];" |( f- V6 d; @  |7 X
                        lowpass_filter[0] = output;
+ \4 u2 u- g$ V9 G. O                } else if( nFilterType == 4 ) {
! O1 C( W1 T" K3 v8 d1 N% {% X                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& \: w$ }) |: S& r% b
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 d5 B4 i3 x6 H/ P                        lowpass_filter[1] = lowpass_filter[0];, X  n+ W( D* V) z5 y$ s9 E6 o
                        lowpass_filter[0] = output;0 G7 Y+ \; x& ~6 w  P
                }- |8 h& {1 O% r' q

  a& O) ^# z. o. z2 T* c#if        0
7 O! s) J5 a( t" _0 H: w0 D* u                // DC惉暘偺僇僢僩" P5 s& n! |3 E
                {! u+ l( n* E6 d, J  ]& ^  i! g+ q
                static double ave = 0.0, max=0.0, min=0.0;% X; z/ i, [" T: K7 L( G
                double delta;
/ A% Z8 w0 l) Q* h                delta = (max-min)/32768.0;
  l7 v- F* x1 Y! V                max -= delta;
' x1 B, x# _# L' s- S! c1 ^/ W                min += delta;. b' e- x$ o# e9 f$ ]
                if( output > max ) max = output;) z& C/ f0 i9 y- W* e- P8 E& ?
                if( output < min ) min = output;! U  M% j9 f; s- e* ], x$ ]" N% p) v
                ave -= ave/1024.0;. Q* X% B2 c+ B; f$ N0 D
                ave += (max+min)/2048.0;
- Z! G# S1 Z2 V. i                output -= (INT)ave;( z6 H) G/ f$ \# t/ `: L
                }
1 o4 U, e! d) l% {; H! q6 i: q#endif
& e9 s3 P% d# J#if        1
+ a9 M3 u' p, j1 o2 M                // DC惉暘偺僇僢僩(HPF TEST)4 ~" D+ Z- G) W& L3 u2 g: ~" u
                {
! J- u, Y$ l5 |1 b# I( ~+ B! ?  D//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);: Y1 M+ Z" ^, d# |8 d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  [1 e. V. O8 \- R' J                double        cutoff = cutofftemp/(double)Config.sound.nRate;" d3 \/ N4 ^; d- A2 n
                static        double        tmp = 0.0;4 A6 \/ j5 l& E7 V/ Y
                double        in, out;
, K# U5 q6 ^; ^" s3 v+ p
# k$ }% A2 Y6 F                in = (double)output;
3 R) Y! n" u9 |) F3 l8 r                out = (in - tmp);- k7 f* d1 q# j/ a& Q
                tmp = tmp + cutoff * out;
: U4 S- z$ K3 E$ s# s
4 `" }6 ^; w6 r6 U. x                output = (INT)out;
) W) [# q6 o! S% w; \! z                }
7 Y' Q/ }( }8 J  i5 {; R! S#endif! _) f2 {0 y9 o/ J
#if        07 [: n8 E, |, v3 C; L; S  x
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
% K) K' ?- C' x0 o                {
! u9 u8 p$ Q- w2 \2 l                INT        diff = abs(output-last_data);$ G/ g3 s1 F" K. G' u
                if( diff > 0x4000 ) {
3 K4 U* u0 J# e$ U1 e6 a) J" g3 M( H                        output /= 4;
/ s; t" y! b& H5 z- L' x3 u                } else 7 Y& D5 T1 A: K6 v
                if( diff > 0x3000 ) {
. E' @9 K4 ^: u1 h0 l$ M& o                        output /= 3;
! e1 Q) ^/ X8 L* g5 z                } else( p& M5 s! }8 ~  g" X! G
                if( diff > 0x2000 ) {
% F: g4 b7 D  [$ @+ ]. ?+ i# H; D                        output /= 2;% A# k/ F2 q+ c
                }
& D' a: j3 \1 _6 ~% B                last_data = output;3 a/ o1 V: w+ U& e( v: z8 u/ R
                }
  O/ ~# K( [0 H6 v: g/ B! s#endif! ^- M5 c5 F) {8 K7 I/ \
                // Limit1 ~; `2 R! l/ Z1 T* l
                if( output > 0x7FFF ) {9 X* Z- r, g% g, O
                        output = 0x7FFF;
, H8 T' |# A" @5 r1 m2 _                } else if( output < -0x8000 ) {" Q; G) p9 R5 K$ ?0 f/ i) k
                        output = -0x8000;+ Q( j% b8 V: s
                }
0 W, _; v1 V9 F0 @* d/ Y% j2 V
1 g0 U- S6 T. X( t8 j8 `                if( nBits != 8 ) {
1 |, j2 p9 O, c, Q                        *(SHORT*)lpBuffer = (SHORT)output;( b* ], B$ _4 }
                        lpBuffer += sizeof(SHORT);
8 I$ X% l: w1 V                } else {
: [4 M5 W9 x) F) }                        *lpBuffer++ = (output>>8)^0x80;5 I5 T1 m( i# i! f( t
                }6 J+ f1 h! @; K/ `: G1 ?6 D4 M

+ ^/ Z4 [: l  N, n& j0 |                if( nCcount < 0x0100 )
& d7 z9 |/ R2 t: H& H* ~" r2 w; g3 a! P7 o                        pSoundBuf[nCcount++] = (SHORT)output;
& A; _' l3 h2 S$ v2 s# `
) R; y5 b4 Q" p4 O+ l( S//                elapsedtime += cycle_rate;
. L2 \- ?$ P" s: g7 _- C5 y' W                elapsed_time += cycle_rate;
# N( C. I0 o( J* b        }
+ F2 g* U2 R1 J! B3 {
% b: n# E% R  b" Z#if        1
" J% o  _, {4 h; i! m3 v        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ P3 i" U" J( F; \1 b3 Q5 n. u" {
                elapsed_time = nes->cpu->GetTotalCycles();! j( N  e& b( b1 \0 a) H# e
        }. c, @  O# Q* Z+ ?+ S
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. Y  v) i( a3 b: w8 K0 Z/ y                elapsed_time = nes->cpu->GetTotalCycles();
' y( S- o, i, X) n; w        }& k& w+ @) @4 o2 ?! O1 m( D
#else  i8 @( v3 W6 ]+ M
        elapsed_time = nes->cpu->GetTotalCycles();
2 S- j) d$ h, Y#endif
( V! O& O; c6 U* z" ?}& Y0 {, c; ^& }7 d% y
$ b+ P$ R+ R" V
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
) d( r! M9 V9 ~/ V, _& aINT        APU::GetChannelFrequency( INT no )' b  C9 x5 L, E) @% y2 @
{
6 H5 A8 Y# d$ f/ j0 D1 a        if( !m_bMute[0] )5 ?2 V* s* }7 I% M- w+ I; t
                return        0;. V/ c) K% q# e  F

# Z* s% `2 k8 {* ~8 l        // Internal
% b8 @% c3 |7 Q3 M- u9 p        if( no < 5 ) {
. L: y. K/ c2 e* a$ X* k                return        m_bMute[no+1]?internal.GetFreq( no ):0;' ^6 G$ [/ g7 X1 C; y" U! {8 @/ B+ L
        }( h" ^# V: y. e+ P% X
        // VRC6
7 g+ F" s* [6 M5 D7 ]        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {: m9 B7 w" T+ ]  }
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
' Q5 d1 y) [$ w9 V, r( T        }; o9 y/ ^3 x% J1 ]4 @) ^, ~  u* |( K- M
        // FDS& Z$ {' O. ?. J$ R" T; j% }
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ g6 L% Z4 u- A. C$ O                return        m_bMute[6]?fds.GetFreq( 0 ):0;) F" n9 C0 `$ F6 E; ?
        }2 _1 V+ D0 S2 H
        // MMC5
/ L# r, Z8 F0 v# J$ S$ W  O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {8 T$ \7 B1 F: [. y! a' _
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;& N9 K8 u) n) U( i' W3 S
        }# ~! b0 X- }2 Y( O& h  t
        // N106
1 w1 \4 [3 \& M( [! ]' l. C        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {4 k: ~# E( y# i+ o6 w# H
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 `7 p' ^1 l3 D* Y: U1 r        }8 K# j% d* ~+ A/ p$ k
        // FME7; g1 C* W: g$ ~  z
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
% i  u- G) j1 Y) x3 B: Q, B                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! P* {# l- U4 Y- t) {/ Y: n: b
        }" W' i3 v; [6 K8 u( q/ X
        // VRC70 I3 \' u: G( n
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
; p7 ~9 ]) }7 B2 l& ]) E3 A+ }                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;! ~0 V* \! b( n  z% Q; {
        }. b# ~6 k7 \! s! G/ O
        return        0;" s8 N$ Y, Y1 c8 U7 H/ P
}; i4 s. g& \5 A/ A6 l" t7 _- q& Y
: H. w% ^' V$ B* y* y7 {" e9 G  m
// State Save/Load
! y, E$ m' u* [  r0 }* pvoid        APU::SaveState( LPBYTE p )" w0 W; A* R" s$ {' U6 ?
{
' R2 z; \; [# i& \) M: r5 O#ifdef        _DEBUG! n4 k; q8 @9 X6 k* |
LPBYTE        pold = p;6 @8 R6 {4 O) B
#endif
5 S3 c. j* x6 z% ]5 U, }$ [% W' b0 q% X
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
0 b8 [$ e) @7 h" t( s: {5 K        QueueFlush();
& ^( S$ Z: p5 _, X: r  T
1 r4 F# Z7 J( N        internal.SaveState( p );& G3 @! a7 S( }3 t
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ s4 |1 g* ~0 [  G3 p
) v; i: q- I7 S4 D
        // VRC6
* @, n4 u0 g+ X9 Q! |        if( exsound_select & 0x01 ) {
* i1 K& e  Q1 R- A+ T1 ^# o                vrc6.SaveState( p );
) N/ P; n0 U" z( }1 U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 o1 s* F% ~" A        }
. E) r- P' O% r$ z9 _# S2 [        // VRC7 (not support)7 n0 K0 }9 I* C/ V. T
        if( exsound_select & 0x02 ) {
+ g" x0 z2 o. T6 Z/ c6 ^                vrc7.SaveState( p );; n$ `( V5 T& l
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 C$ D0 V1 v# g3 p9 _7 u% S. B        }
( P2 l8 R4 l$ T, Z, O) p( o% U3 `        // FDS8 V7 A. q9 ~1 I
        if( exsound_select & 0x04 ) {
7 v3 [( D; K/ w$ E* b# o5 s                fds.SaveState( p );
9 J" N2 y: Q9 V1 X9 X9 m                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. Y& r) H. ^4 E& P, J4 q" T1 K
        }" e7 ^: j% U- e4 d( _* w
        // MMC5
* [6 B7 I/ @1 s, I        if( exsound_select & 0x08 ) {  B4 r8 W. j% G( H  P& I0 B. T
                mmc5.SaveState( p );, n: Q& q  c$ H
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; @! S% x* g- P2 x
        }7 |6 T! g4 o- D4 S; I* U" s
        // N106$ B% V. j. L# k8 s! [
        if( exsound_select & 0x10 ) {) V. J6 Q8 X8 q" n5 t' ?
                n106.SaveState( p );
( H$ M, j# @3 A                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) e3 R9 q! S+ V
        }
4 J* a; r5 X1 A6 I9 S" l% J        // FME7. f5 }( ^$ ]1 y
        if( exsound_select & 0x20 ) {0 a7 O, u' J/ e$ F; t( M
                fme7.SaveState( p );
4 n& B8 `0 j% q7 b' {$ n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 B: c# f6 z9 J        }+ O* }( @9 i# p/ J1 B9 [# Z

/ Z) f, ~5 C' b2 \#ifdef        _DEBUG2 ^" i; _7 ]. w, W1 K9 ~9 u5 v' t
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 }# H  _! X, @3 \9 }6 R
#endif+ [! t  H6 T' J, `# I; a) _: L7 x7 W$ X
}
: y; H3 `9 E/ M  h' j$ k4 y- M5 {1 b$ g) _1 c& i
void        APU::LoadState( LPBYTE p )
+ o, R/ o2 H" z0 O% T+ q' z{# \4 G2 ?, C1 A. k" F0 `, ]
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& u1 q5 ]; b6 G5 b$ w. t( C. J
        QueueClear();
: S' ^4 ^  x( V' p" _7 ?! h$ t. I% g! y3 m- M( n
        internal.LoadState( p );
1 R6 w! D- Q6 ~- U4 \, C( q: C; @        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( h. P" Z& [# I. g! {
5 i& s0 l  C* k6 G, _
        // VRC6' e: C) V& a& t8 W# s/ J, P
        if( exsound_select & 0x01 ) {
1 M. c0 o' B/ }: N) D                vrc6.LoadState( p );
  C2 @/ n4 z( b7 Z/ j$ G( L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* o0 ?' Y; D$ V/ K8 q/ t        }
9 ?( [3 J7 I9 L9 y' f9 b        // VRC7 (not support)
, u' j) E" i  s" p+ A6 f5 X- c        if( exsound_select & 0x02 ) {
1 H0 }' I5 H% o0 }                vrc7.LoadState( p );
- N" ?  a' X/ A, J2 J% B! W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: L1 ~+ T& j5 R0 X" A- }  j
        }5 i1 T' b( C9 P* a- H% V2 o4 K
        // FDS3 S" T& f5 m) b8 m+ p
        if( exsound_select & 0x04 ) {
- M3 Z2 C2 L  z& T* F) E* M$ b                fds.LoadState( p );3 h5 `& G/ W" k8 G. L
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
( C( f; t6 v# O/ i        }
4 X3 i* c3 M$ b. h  U$ |        // MMC51 [4 h) f- r* ]' t1 [
        if( exsound_select & 0x08 ) {) |4 N5 C/ N# |. B6 U$ i
                mmc5.LoadState( p );
- j# \8 U& i+ I+ Q8 n. t                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. K% F7 k, X' X$ T        }1 j; A2 S0 h6 |4 x! I7 i
        // N106
4 b0 E- ~, J# |1 k7 L        if( exsound_select & 0x10 ) {  {7 O' [+ [8 b1 Z
                n106.LoadState( p );
9 R1 C( O+ E: i                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' f: `; t4 {' G# I, r: |( X
        }: @8 E4 p& w5 z) z, d0 S/ F
        // FME71 N3 P, n+ \$ ~; j$ q/ v' [1 x7 @# g) q
        if( exsound_select & 0x20 ) {
% j9 O- }8 c" H8 F/ E  F' ]                fme7.LoadState( p );
5 o+ Q7 |/ c% j! X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" R. Y) x; p, ?/ M1 K
        }
5 E  k, U' d" e8 I$ X) T* f( z0 D}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
+ B8 n* ?! p) r/ t" t可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  G, O. g+ n7 l2 K感激不尽~~

( L7 M) K% A( L恩 我對模擬器不是很有研究,- ?/ Y4 u! V7 n3 @( z
雖然要了解源碼內容,可能不是很困難,6 ^- ~# T3 C9 J# x! d6 o# D
不過還是要花時間,個人目前蠻忙碌的。% {! h2 Z) F4 M! ^. d
8 f8 B# ^. Y) y0 z7 D/ n
給你一個朋友的MSN,你可以跟他討論看看,
/ T/ ?7 {6 w& K. O: e4 Z+ o他本身是程式設計師,也對FC模擬器很有興趣。. p5 @! L* [8 R1 e

( E1 i1 L! M: e& K- v: jMSN我就PM到你的信箱了。
  c4 L: s, z, S0 }
9 X( d" [$ W, [0 C/ e6 K希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* S, D- [- G1 K  t) Q1 H7 p2 G呵…… 谢过团长大人~~
% d% @5 ~5 l6 O. _; A

* L" A$ N$ Q. K8 f% ~3 B; f0 T哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ; k3 r  ]# w2 H7 p" j5 |* t% E
团长的朋友都是神,那团长就是神的boss。

4 X$ u9 p# a; Y2 ]. B哈 不敢當,我只是個平凡人,/ Z! S2 _6 `4 S, ?
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ d4 w! c8 N3 q5 O1 Y+ ]. v
ZYH
5 u# O) Z7 ?; {8 H4 P: jQQ:4147343061 {& h& H/ w; p4 z; R+ O* D* f
Mail:zyh-01@126.com
" [( x# i* h0 B9 S( |
$ y, v( P; F8 Z; w/ A0 w- P, K" Q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
% ^* t9 ]  [8 t; U7 O再次对团长大人和悠悠哥的无私帮助表示感谢~~
2 X, X' S% {4 V# C" o( m! v0 e
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 22:52 , Processed in 1.107422 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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