EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. R; {- Z9 j% s) T2 I# g
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# e/ V/ E; [( r% [# U0 M7 q这里有相应的模拟器源码,就当送给大侠了~~8 p7 m: b# n9 q. h" P) n" D# i- z
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
. M# w+ n( A4 n, S; G, f* [( @能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 q. ?- k% l. P* p. p& g" b
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: R! ^' H4 P3 ~; S! J* _+ B/ `1 @- v7 c
这里有相应的模拟器源码,就当送给大侠 ...

% T0 l4 V! x, Z' F7 I聲音部分(Audoi Process Unit = APU):0 a; m7 M2 c/ L( g, y
.\NES\APU.cpp
+ l& j" v) J, S* |( V.\NES\APU.h
3 u3 Y/ ], A' c. p# h9 ]' |0 _8 f- r. i/ H, P- c

$ c- _- P4 n# p# P2 U. G影像處理部份(Picture Processing Unit = PPU):. F3 y) k5 `# R1 N; R
.\NES\PPU.cpp
1 Q: m, e8 n- R3 ~7 p0 D0 M.\NES\PPU.h
, B. B' ]2 e% s; C- l
8 |% w- c( j- U& f+ j7 c8 t7 m如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ M. C% F, c" u7 B. ~
(由于很多专用术语和算法机理都不明白,所以看不大懂……)& z  Y' I! K3 Y" p2 e
//////////////////////////////////////////////////////////////////////////; f9 C7 b. @. z5 k
//                                                                      //1 c8 I) ?$ ^9 I2 ?- e- E& y1 ?' E# R
//      NES APU core                                                    //) N! }+ q6 ?0 {
//                                                           Norix      //
$ O& g& R; H( u; E+ f//                                               written     2002/06/27 //
6 {- ^% d  _, D. J3 K//                                               last modify ----/--/-- //
3 T' J7 n! L# _/ a3 P//////////////////////////////////////////////////////////////////////////& i) t$ t# r" X- M# R; K- [
#include "DebugOut.h"
& Z+ V- Q8 q4 E/ @% h* q#include "App.h"
4 a4 q% f) k5 m& ^# E#include "Config.h"
5 \+ Q  _. W# p( S$ @! M+ V& R% ?9 h4 G
#include "nes.h": @# E2 s- c  e$ h
#include "mmu.h"
* Y! z: p: r/ _; w% T7 T8 x% a; _5 v#include "cpu.h"
; K3 z1 D) K% x* D1 F1 X5 W. v9 ~#include "ppu.h"
) [4 |0 A! u# N& }( c#include "rom.h"5 g' i+ D' I( |; d
#include "apu.h"
; c( e9 `& n! m5 {' `7 A2 n! W/ J6 L# g- j8 e6 \7 p. z
// Volume adjust& f2 g* O8 y/ q6 e5 O
// Internal sounds
( {' [. g; V! M% t: F' M#define        RECTANGLE_VOL        (0x0F0)# h5 X4 p% J; y2 ^. @' z& z4 A
#define        TRIANGLE_VOL        (0x130)
2 d, I5 p0 d: U. U" u' F#define        NOISE_VOL        (0x0C0)
/ j  x/ F( \4 @#define        DPCM_VOL        (0x0F0)
6 T8 ]) |, l- P// Extra sounds) C, H7 X( M9 f' a9 l
#define        VRC6_VOL        (0x0F0)
2 T, A! ]' y9 Z, i1 A$ `7 w#define        VRC7_VOL        (0x130)
; D( {% n6 J0 E1 U; Z) ^; X, @6 h' ~#define        FDS_VOL                (0x0F0)* P$ n2 ~# ?; }9 v
#define        MMC5_VOL        (0x0F0)* G  }$ _. S8 z% r3 _2 ~: G
#define        N106_VOL        (0x088)
/ Z4 |- z' u& M) g5 r" s" o' K7 D5 i#define        FME7_VOL        (0x130)( D/ X! S* Z5 @' T, j
, S/ P1 w4 u& }0 P; p
APU::APU( NES* parent )
& G2 t: s7 ~1 }8 _& h2 K# }{
" W" a. w3 G5 A2 V* [# p        exsound_select = 0;
0 i. H, R0 S$ J% K, I1 U! |
2 n$ C: b* J: z0 e        nes = parent;
/ Q' @( C9 k; Y# s: \* Q2 F        internal.SetParent( parent );
: o5 z0 j- r8 {* ?+ Z% H5 t$ k; B# A) y9 m: s' y% E
        last_data = last_diff = 0;
. n6 I1 i$ |0 [' b+ E6 o% R6 y/ M. R* e' Y- V" K" H5 |
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );% a  C1 \5 g# W

2 s3 Y; |  K+ V/ A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );- q' K& X4 B" `4 w4 s" w
        ZEROMEMORY( &queue, sizeof(queue) );
( L) q1 F9 j7 l5 ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* {$ e2 l* w. E9 @% x% t$ r& Z. r5 P. P, n+ x
        for( INT i = 0; i < 16; i++ ) {3 O: O5 m, N" z: T( Q1 [
                m_bMute = TRUE;, D4 x; X. X2 |
        }
8 V; W  _+ h& \% S  J: w2 z}
2 B% }$ P3 ?7 W# E3 Z/ X9 U0 E: ]: P. ]4 X  A' m5 O6 v$ k+ r% |1 A2 ]; Q
APU::~APU()
, t) M, Z3 \/ P) Q& a9 A' T{$ z! O, p: H7 q9 s/ Y/ c
}
4 l* \8 @4 P. Y' z3 x0 S5 W) T# f% V9 ^9 H9 G8 M
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )" c. n* `" p1 y0 I( m
{
! H1 J) i" R+ n6 ?1 ]        queue.data[queue.wrptr].time = writetime;3 b7 W. H, t" p) S- `7 d' n
        queue.data[queue.wrptr].addr = addr;. }( ~. l' o# X& H
        queue.data[queue.wrptr].data = data;7 G3 \1 D( v; N, a
        queue.wrptr++;% N/ r; z/ Z, ^2 v- R
        queue.wrptr&=QUEUE_LENGTH-1;( ^# E9 N5 z' n. V+ Y. i% M0 ^
        if( queue.wrptr == queue.rdptr ) {; @5 D5 X: Q# c$ v2 d
                DEBUGOUT( "queue overflow.\n" );' x& Z! K  G9 s' Q2 x
        }/ U: b1 Y8 i3 P
}! v0 F5 p/ W% T1 g- c
" `& D7 z# Z/ _9 s4 X) M3 J
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 t$ q1 u1 T4 d( r+ `, }
{
2 S$ R( s1 ]( J  K8 w& m+ y8 f, Y        if( queue.wrptr == queue.rdptr ) {
& b# \3 g- X8 Z7 ^, |8 Q! P                return        FALSE;
9 \* M4 I; @9 z1 Z        }
# A' E6 B0 D2 m1 g        if( queue.data[queue.rdptr].time <= writetime ) {/ Y+ S# q; ]% u3 y/ A7 x
                ret = queue.data[queue.rdptr];) F) {2 q% G/ i0 v% y
                queue.rdptr++;
/ R; O- B2 q: U/ `* K2 C1 Q' w                queue.rdptr&=QUEUE_LENGTH-1;/ V; b5 z  b* W+ [- w
                return        TRUE;0 D$ Y! L4 ?) u0 }
        }1 R6 X! C1 J0 {6 w) |3 i
        return        FALSE;/ W9 h+ c- b! O$ {  i8 P! }
}
/ X& C( s3 E& r8 a$ J* |1 |" w) Q1 {
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
/ J2 [! _- [0 Q" u{& e2 K" ~$ T# \. U" Z# N: _# o  Q
        exqueue.data[exqueue.wrptr].time = writetime;
, t( e  ^/ |0 h" D: j8 U4 E0 d        exqueue.data[exqueue.wrptr].addr = addr;
. t6 R( `, p6 d; w( P9 s        exqueue.data[exqueue.wrptr].data = data;* V9 W/ h/ I6 @# x1 @
        exqueue.wrptr++;5 E" O' D/ Q, i  _1 c* j0 r* X
        exqueue.wrptr&=QUEUE_LENGTH-1;1 ]8 V6 d: w) |6 V0 F
        if( exqueue.wrptr == exqueue.rdptr ) {, x5 v; ?- V/ ^5 I
                DEBUGOUT( "exqueue overflow.\n" );) ~6 c/ u' ~; H, Q* {& f
        }1 P/ }. o; F$ [
}
* V. x  K# r  a; Y& U6 w
  r+ Z. s+ F, E8 I) _BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 c1 \) [7 j0 \0 U4 U, e
{  i& ?' p3 s) S, W9 {2 @6 M
        if( exqueue.wrptr == exqueue.rdptr ) {1 f  E9 ]5 S1 ]  ]9 {& R* r, L
                return        FALSE;
0 l% j  d' R3 b5 p; {! E( r! H        }' s0 f' f! G" Q5 O3 K5 J- C# F" H5 ^
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {2 ]4 o$ V, c% \
                ret = exqueue.data[exqueue.rdptr];* G1 c2 q  N* M
                exqueue.rdptr++;% n/ J3 P) z& m7 E
                exqueue.rdptr&=QUEUE_LENGTH-1;# v$ F# Q4 U8 o  }
                return        TRUE;. O+ f5 W& ^) _2 T% M. Z* ~
        }# G& K& b2 ^+ F* k' r! [7 L
        return        FALSE;/ f: f4 E% S. F+ ?0 \! S* q
}) p& n1 |. Y5 S& L9 L3 @* h+ F1 o8 m

9 O, {7 z, p% u2 U6 k  hvoid        APU::QueueClear()
0 T, M/ Y. x3 k. Q0 q& b{
. c2 v, T* t/ c+ y9 C. n% L6 P        ZEROMEMORY( &queue, sizeof(queue) );
  O9 z# U) c: U        ZEROMEMORY( &exqueue, sizeof(exqueue) );! |" ]+ l0 q0 B
}% p/ i1 k! i' `' Z+ \0 O; w

5 Z% E0 L  B  N; g- Z' J" M4 o$ N& c. Q/ tvoid        APU::QueueFlush()/ C; s8 r2 R: O$ ?$ t
{
# e1 P( Z- F4 y2 L        while( queue.wrptr != queue.rdptr ) {
; U- l# R8 U: M                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );" ~3 x. g* x0 V! o% S6 O6 N$ E
                queue.rdptr++;9 A) b# L- h+ o3 U: I) K, v
                queue.rdptr&=QUEUE_LENGTH-1;3 r" h0 g& v: u7 A. d% d
        }3 w+ D2 Q* ^5 g

; _9 e" j( O2 K& g1 e        while( exqueue.wrptr != exqueue.rdptr ) {
( W8 I2 w2 m: @6 a                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );4 S7 l% j, V5 x% g% X4 G
                exqueue.rdptr++;/ q/ O, b7 r( A+ a; M3 _. J6 G1 Z0 ?
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 P& o# C& U. K+ l# W1 `# d        }
* |" e) H% u' M3 l}
7 [1 d, V* K  d2 q8 ?: s, `, h
% T' i4 u0 V# P! I% Yvoid        APU::SoundSetup()
( c" m. P2 h) Y2 \2 s* ]9 J{
- c: T; f- Y2 d& M% h% J. T        FLOAT        fClock = nes->nescfg->CpuClock;6 n/ x( U2 T) P( r0 [$ C
        INT        nRate = (INT)Config.sound.nRate;
/ n5 h1 t5 A4 j1 a8 t( k& R        internal.Setup( fClock, nRate );2 x5 _$ }6 m3 j
        vrc6.Setup( fClock, nRate );
% u9 \3 B2 R$ l- I        vrc7.Setup( fClock, nRate );
5 k$ `  o; s1 w( E        mmc5.Setup( fClock, nRate );3 q' i( v" }5 l! N
        fds.Setup ( fClock, nRate );
7 C/ Z+ }1 t' p4 p4 m        n106.Setup( fClock, nRate );0 x; i' t  @0 Y
        fme7.Setup( fClock, nRate );
* g5 P- O' t7 _* i0 S}
) o, F6 ]9 c+ o; M: X' |' C. F! ~, C7 S+ O3 p
void        APU::Reset()
; |. t3 i2 ~% e# O1 O' j2 a{
  E) V- F- Z/ i( n- _- ]2 N, g        ZEROMEMORY( &queue, sizeof(queue) );+ N! t# C' L' _  Q! i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' F& i5 h6 P4 y) m/ J/ u; b8 s8 z' O: N( f
        elapsed_time = 0;
4 @* X1 W. r$ R# R% n/ k1 r" F8 h% p# }: l) n
        FLOAT        fClock = nes->nescfg->CpuClock;
% [! u" d+ u( M+ W        INT        nRate = (INT)Config.sound.nRate;% }& s6 ]: V9 k& i% [
        internal.Reset( fClock, nRate );3 y( y7 r& g, e4 b
        vrc6.Reset( fClock, nRate );8 `+ u0 B3 F$ D, G
        vrc7.Reset( fClock, nRate );
3 f2 C$ Y0 ^4 \7 f, [- v3 i        mmc5.Reset( fClock, nRate );
% P( Y. T3 @9 b7 p' O" A* y        fds.Reset ( fClock, nRate );
8 b# Z4 ~" Z9 F# D  w% C$ G/ W( ?        n106.Reset( fClock, nRate );( G- O& s' _3 G) M; R
        fme7.Reset( fClock, nRate );
2 |) N! h$ j8 N! s( }
1 z$ ]6 O7 ^3 D" C- i6 B6 i/ i        SoundSetup();6 j' l- y% W: [. ]# K
}
) n7 G& Q" H7 l  Q% O) W7 }2 x- e
& v% r" J9 K& ~void        APU::SelectExSound( BYTE data )
) Q  e& B3 M0 Y7 j! f{! c5 q  {: Q! N/ N
        exsound_select = data;
3 r) ^3 H6 g6 ~8 g: X}8 W: \$ i: W! K
% u5 p  C2 Y4 ]8 P5 {5 A
BYTE        APU::Read( WORD addr )
, U0 m+ C7 V! M  Q+ B, Z$ [8 _{
" R9 F6 e: i) e* w* y        return        internal.SyncRead( addr );8 L# F" t! E) `) g+ E/ a
}: A" B8 t6 `7 ]2 |$ E! s- @
$ m& k9 P/ O. b7 X! \5 z
void        APU::Write( WORD addr, BYTE data ); ~9 U% ]% G9 h6 S) t+ A
{
! [& d( S% w0 V& W        // $4018偼VirtuaNES屌桳億乕僩
- S7 U: P7 W- s' q0 x1 B- t" q! g        if( addr >= 0x4000 && addr <= 0x401F ) {* q) l, U* J+ t
                internal.SyncWrite( addr, data );
: n% b" H8 f. C# v! q' ]1 ^6 z                SetQueue( nes->cpu->GetTotalCycles(), addr, data );) D/ b6 Q; b, [0 H  O3 z/ P
        }/ `1 ^. m4 q4 e  O9 Y, M
}
( |9 O7 W, r6 W6 H# W- {2 n  G' B- n' X( ~& A+ a+ M
BYTE        APU::ExRead( WORD addr )* B! P! E! l/ Q7 U1 V# ]- |
{7 @1 u: G$ k0 S
BYTE        data = 0;9 X# `! S( O2 C7 m4 ]% x

) z) @2 F" F2 s        if( exsound_select & 0x10 ) {* g; r3 {7 ?! A3 ~
                if( addr == 0x4800 ) {
9 w' R; X+ h+ _- z) J" U                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
% J' l: e6 t9 F; Y& v  p! b1 ]) d                }5 [/ ]7 b2 C& m
        }
! \& J' Z) o6 Y; D2 C7 Q        if( exsound_select & 0x04 ) {
. t$ ]7 n) d0 \4 C: h                if( addr >= 0x4040 && addr < 0x4100 ) {
9 S0 H3 ]' N/ q' m- N" |                        data = fds.SyncRead( addr );
# S; i% R( [# x6 {* G( a! B# P7 Y" Y                }
0 V. P5 O2 X9 i, B8 k& {8 K2 u) X! e        }' z- q. h9 v* \  x; L. o
        if( exsound_select & 0x08 ) {9 {, g7 K0 j  D8 A, L$ U
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' O- a2 r( A8 h4 M                        data = mmc5.SyncRead( addr );
3 m  [, _8 n2 O% R5 i4 m                }- `  {' d1 l& H5 t
        }
0 D9 P- f( I/ B! n/ W$ x9 ~
5 a) M: G: b! i. U        return        data;
0 G1 c# y: O% ^}$ M* T% ]2 l, m
% M/ j% y) P+ G( C2 |8 C$ d; \) }+ X
void        APU::ExWrite( WORD addr, BYTE data )
  z: Z5 u6 t8 n{' j. a" ~! u( Y
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 \! h6 {: J/ P7 }. c" n; m- n; Z( S. e+ P+ k  @' ?
        if( exsound_select & 0x04 ) {
6 c2 ^4 J6 l8 \: N1 f1 o                if( addr >= 0x4040 && addr < 0x4100 ) {
' {( [* b7 }. O& r7 G, V3 Y3 f% \                        fds.SyncWrite( addr, data );& G0 I. [9 i. H
                }  y6 g' [& Y1 T
        }/ W0 w7 X* E7 h, A. ~+ j/ @

+ L4 f# y0 S" k! Z1 g" z+ m        if( exsound_select & 0x08 ) {
) I% }  E3 o' K7 g0 W# M4 s# F# \                if( addr >= 0x5000 && addr <= 0x5015 ) {1 ~$ T( `3 K8 m5 a9 p7 L5 P
                        mmc5.SyncWrite( addr, data );5 l. c" v0 `2 n! a
                }1 h( T6 l& h* c% [% @
        }% q- c8 C9 t$ j# C1 R
}3 @( B: k( J9 Y
6 m+ O1 u/ I0 b$ |  h  F3 X; X% f* A
void        APU::Sync()5 L4 G3 A+ ?8 y- u+ L+ S& t9 V
{. h  k* C. c0 Z& g/ ^6 H6 f
}
0 F& P! W8 i8 K
/ q. q. p( S  v3 y1 N: D2 [$ n0 Q8 j/ Pvoid        APU::SyncDPCM( INT cycles )
2 `+ }1 j% w* I* [: Z1 C{; u( o0 }) A2 N& L, u" n
        internal.Sync( cycles );
; @- f9 S) b; r! o
9 m5 r+ x& o2 c' @6 j$ B4 M        if( exsound_select & 0x04 ) {8 o8 J( M2 x) z
                fds.Sync( cycles );
7 C: {/ [9 d; M  ~: c        }1 {1 Z, G( t" s5 j( J1 J) p9 Y
        if( exsound_select & 0x08 ) {3 }: D* C1 K/ m3 ]0 _' X/ d2 N! P
                mmc5.Sync( cycles );& d2 K( z8 O0 x, [' [( M
        }
# ]/ P% c& o$ U5 A* y' O( y- l}  i+ e- w' z) d: U4 \0 Z% D4 U

. Q( M& w6 S' I7 B  pvoid        APU::WriteProcess( WORD addr, BYTE data )" E  q4 i: D8 [! V+ p4 c8 C
{- D3 V, |7 c3 d( z; @) s6 E
        // $4018偼VirtuaNES屌桳億乕僩' K, i  \. ?. y; Q
        if( addr >= 0x4000 && addr <= 0x401F ) {
; b1 [! d& m* v/ o2 `  m( k+ Y                internal.Write( addr, data );4 k5 Y$ F- G: I& T
        }7 C: |$ x6 |# d* e
}, O) y0 ~9 t3 V2 T/ x

# u2 X- z, ~' @; N+ g+ wvoid        APU::WriteExProcess( WORD addr, BYTE data )
0 o0 Y. g+ G/ a9 U6 U1 w{
+ u9 J4 y6 O$ z        if( exsound_select & 0x01 ) {
* o" m+ {/ h. V2 a; E7 t* n                vrc6.Write( addr, data );+ D6 j. g! o( r) z2 G) B6 F
        }! c  m( f3 T/ P! a3 Q
        if( exsound_select & 0x02 ) {
; [  \1 o3 P* X$ D" M                vrc7.Write( addr, data );* n* _9 Q, Z9 g' @1 c1 c: c
        }- ^) x8 ]" _. u+ w6 V
        if( exsound_select & 0x04 ) {
' i' [. U+ Y  }. H7 ?8 d7 h8 H8 Y                fds.Write( addr, data );
4 ^9 Y. I! w$ N+ s; h& I: ^4 Z        }# [7 Z4 o: @# N% h* k+ B$ p
        if( exsound_select & 0x08 ) {$ r! J; {, w8 b0 [% t5 Z
                mmc5.Write( addr, data );
/ R2 @* [1 H4 n! q        }
" Y/ @! o( ~( }5 X9 d        if( exsound_select & 0x10 ) {3 A$ q: s5 |$ t5 F7 R
                if( addr == 0x0000 ) {3 A6 M5 p8 n: Y' H1 ~
                        BYTE        dummy = n106.Read( addr );
/ @' P  a$ f5 F# X3 }) k! o                } else {
! E2 S+ ^! V' d8 D! O" R                        n106.Write( addr, data );
' D4 F) T. O' z# H# C) u2 a5 f                }' J& @3 j4 D3 E0 l1 G! Z& m
        }
0 X/ i4 V  ?1 z. a( E        if( exsound_select & 0x20 ) {
) h( x' \" S) T: @: d                fme7.Write( addr, data );
& c9 P0 ]8 }/ ~# z% X# S        }
1 R4 }! g# D8 K- ?9 P( U}" g! Z5 e$ a: g! O

0 @" v0 y; A1 w: h3 Pvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ); {0 A& _( V4 q$ C, S- b
{
3 w2 y% @9 Z2 ?4 N2 T' ~  zINT        nBits = Config.sound.nBits;% j3 ]) _# Z) w4 Q
DWORD        dwLength = dwSize / (nBits/8);  ~4 m# \% d2 s1 O7 M2 t
INT        output;
3 c$ W1 d& k3 dQUEUEDATA q;3 ~+ r9 L, z7 J+ }* ~& v7 |
DWORD        writetime;
/ Q" D2 M3 I( v2 T+ ]; c! ^: z) F- a" U0 y+ b$ X* G7 r% ?. _
LPSHORT        pSoundBuf = m_SoundBuffer;
7 x0 v) r$ L7 u3 d  sINT        nCcount = 0;
: ?& O/ j/ m* @6 Q: x! ?$ F" T6 ~3 g
) r- p( j% `4 V' D* n' S8 J. }! DINT        nFilterType = Config.sound.nFilterType;$ f7 n+ l0 ]' x6 a9 H) ^, J3 n

$ ?+ X3 B/ g3 Z        if( !Config.sound.bEnable ) {- O3 A& Q; [- \3 P4 j& O
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* ^" I! c$ H3 s5 q' n' [" O                return;
' a; {+ f* ?5 u6 |. I# A$ H! a        }# k  D- B* Z. g! x
5 G5 |! t$ V+ k0 B: ]8 {" }. {
        // Volume setup+ J9 k/ V/ A8 A' ?
        //  0:Master
6 _  n' T, o  `7 \4 v2 `; @        //  1:Rectangle 1
0 p$ I9 b9 N8 j        //  2:Rectangle 2% L" J+ z7 C& A, @
        //  3:Triangle
6 J: G: ?+ H, X4 J$ I! z        //  4:Noise9 M1 \" [+ f7 |  [: R5 }
        //  5:DPCM
* m- e& `$ S5 ]7 C: I' z, N( n        //  6:VRC6. u( \; E: J3 t; u2 _# u
        //  7:VRC7
3 z& Q1 v$ c, ^% v& s        //  8:FDS! ]! H: _8 J, I% C
        //  9:MMC5
6 M1 W$ k, H; p7 m; m! k        // 10:N106) E; ^2 ]: o  W' w
        // 11:FME72 Y: \9 g" `& t3 m: G
        INT        vol[24];
$ e4 B, D; z. v1 R7 l6 J        BOOL*        bMute = m_bMute;7 B0 s, z1 {0 t0 d0 o  j
        SHORT*        nVolume = Config.sound.nVolume;, Y3 M* o# \6 r
! M- u, ]% o6 B
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
4 p& Z1 Z0 e$ {( h7 s: a6 e6 U% P5 c1 a. v8 i0 W3 i+ Q
        // Internal+ m0 l; R0 `% v" W2 X& G9 w
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* m: }. H9 ]+ Y  }; _. a8 y        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;2 ~  g) ^6 j3 k  T3 q5 l+ S1 b4 G, x: p
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
1 h# X7 ]; ^) P! X! K        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
9 c9 _+ t9 n0 s: T2 _        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;/ }6 d, a) V7 M5 {

6 G5 F* R' @- b* }) |+ u! f        // VRC6
0 x; l+ O& g* W' T  L        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: \( R0 Y: k: ?6 ]: K: k! Q
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 w- s; `- j; J1 T. z! F
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ T2 \, t' Z5 m( O5 U0 ?; g
& o# `4 z2 @. e0 Y! ?; I, y        // VRC7
7 R4 ?$ e% c4 C3 [# P8 n        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;# J4 t1 F7 {( Y/ Z9 i5 v4 @" f

- H" Q& [* W* ?9 |        // FDS! J2 `1 c/ [  C6 U+ c+ V
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;" y+ l7 T! q7 B) I1 i
: t  h! }) ]4 a% H% j9 _0 b; ]
        // MMC52 g9 u: U& y8 c( p
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 ?. G* Z0 d& G& N& z        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! E) z) r- p! C
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. P& L# g/ I& v( `+ f$ c4 @' k8 t9 Z
        // N106* F+ |, D% k. p, C2 {+ G
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- P5 J2 R8 z; R
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 c! l: K% x; V+ l* {- q8 G        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- \" X% G6 M" @( t/ F
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& {3 n8 w+ e9 |        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 T. x: E2 s$ B$ Q& a6 q: `* [        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* \6 ?! ]' R9 j* d. Q% r: P2 n
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- p8 q7 l& ^6 k1 e& l; ]* N        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! D* R0 u5 k3 k' ~* Z
; k3 [$ S6 ^  }/ O  j0 E        // FME7
( O. `. v% V! M+ z. @        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 h3 a" {5 ?2 y2 `        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 \1 l5 b4 `/ n        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- ?  e! g+ ~" N9 S/ V( o2 Z# Z& W$ v4 u- {9 y6 I* b0 d
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 f& v9 y, h# o  p) ^        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: ]1 J4 R; i5 `# k6 I$ D! w
: m  D. n: G& d, z; [7 q2 v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟2 C! t) m7 |$ {* c9 ~+ D4 D' G% o8 [
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: E" O& P  q! R$ k  O. G
                QueueFlush();2 w: E' B0 d3 Q9 \5 p
        }) n/ G% e+ l1 H
/ u! w/ l: M( ~2 U8 E
        while( dwLength-- ) {5 m9 h% B. S$ a6 t
                writetime = (DWORD)elapsed_time;
( d& o  _; y/ j7 H) E- r$ V
: X3 y* X+ f6 N/ N; Y0 J# N7 N, b; d                while( GetQueue( writetime, q ) ) {! K; Z! A$ Y0 ~: I8 o6 y
                        WriteProcess( q.addr, q.data );2 u5 r! w" j" V2 u0 P$ X3 U
                }, X! C0 @" T2 E( G

: ?8 w4 c2 [1 ]                while( GetExQueue( writetime, q ) ) {' F$ ?. `, g/ t6 T: h
                        WriteExProcess( q.addr, q.data );9 G4 _! m9 y3 F1 g" f
                }
5 d, w# p) h2 s1 I+ b
1 l8 x& r% d) i% V                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
1 L4 a; X9 r: _) m3 B3 c                output = 0;
' X; q! k7 L9 k; n, {: B                output += internal.Process( 0 )*vol[0];) m0 z- z6 d: X" p/ B) w
                output += internal.Process( 1 )*vol[1];5 p: A7 ~) l3 \  v" J* E  t
                output += internal.Process( 2 )*vol[2];+ T) U4 [) ^( X4 R
                output += internal.Process( 3 )*vol[3];
' k! @1 D5 H' P                output += internal.Process( 4 )*vol[4];; F3 E( W& P  j, o+ B, i1 K; A
) k% s, |& \+ |; S; @
                if( exsound_select & 0x01 ) {
9 z, Y$ I" c/ R$ L, Q% f                        output += vrc6.Process( 0 )*vol[5];
: O4 F: F( {4 `: F7 ^1 {                        output += vrc6.Process( 1 )*vol[6];
4 A' g  L- S1 U( `9 `) A                        output += vrc6.Process( 2 )*vol[7];
4 H7 i' C/ p5 V' K1 m- U                }! V9 s8 G7 s. _' Z4 l
                if( exsound_select & 0x02 ) {
. Y6 h- s# U8 }0 n                        output += vrc7.Process( 0 )*vol[8];0 u4 V! b' b) @+ Z5 [  J& j5 w; P
                }, l3 {# s2 A* a1 y, W4 _& l0 l, \
                if( exsound_select & 0x04 ) {
: s0 l+ s3 V! }5 m: e' h, K                        output += fds.Process( 0 )*vol[9];
- {6 x: z6 o  R/ `2 z4 ~, j                }
1 B9 w' R) h# v) m                if( exsound_select & 0x08 ) {8 K; ~5 x" G: b2 f1 a& k
                        output += mmc5.Process( 0 )*vol[10];6 r6 v. e& y1 u
                        output += mmc5.Process( 1 )*vol[11];
( `7 p) T3 l& C$ f$ t                        output += mmc5.Process( 2 )*vol[12];
! [; U% v( R( ~( A/ H3 I0 T                }& ?& N# i! U1 X$ {9 B) c
                if( exsound_select & 0x10 ) {
' d: ]2 d+ V, l6 i2 `                        output += n106.Process( 0 )*vol[13];
% K9 R. j2 K- S" N5 W7 g) M. A% S                        output += n106.Process( 1 )*vol[14];+ }  x5 p& B# h' A+ |( s
                        output += n106.Process( 2 )*vol[15];! U! z) g' t" B- N
                        output += n106.Process( 3 )*vol[16];5 w( L! ?7 q" B& y% a& \3 f& p
                        output += n106.Process( 4 )*vol[17];0 ~4 [# ^; Q3 y8 i; |5 o
                        output += n106.Process( 5 )*vol[18];3 r9 [! |5 I, S& h
                        output += n106.Process( 6 )*vol[19];
% I- G6 e, o0 E  {$ d0 H' S- ~, R& q                        output += n106.Process( 7 )*vol[20];
% E: O) ^# H: T1 K6 R( i3 R2 L/ t) D, h                }
7 E) y) u1 m  z# D                if( exsound_select & 0x20 ) {
, f) Y! y8 ]. ?1 z3 S6 D8 ?                        fme7.Process( 3 );        // Envelope & Noise* H" ^7 w' y6 @2 d5 t# O
                        output += fme7.Process( 0 )*vol[21];* ?: A- V7 {9 r
                        output += fme7.Process( 1 )*vol[22];
% X4 S, \/ Y1 U: ]1 y' q3 b                        output += fme7.Process( 2 )*vol[23];
6 m  `  p2 R4 `7 `+ P/ }1 l! x4 J- d                }4 u; `# K! L. a3 D" y
7 `& u3 O% l" z4 K% w' D6 H
                output >>= 8;# R0 H5 S, P4 I( _& f2 y
) v. D* l# O$ [8 L3 _: l" E' }% U
                if( nFilterType == 1 ) {
9 i; n3 x  d, h$ c% |                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 `. ~* W: _$ k& |
                        output = (lowpass_filter[0]+output)/2;0 Z. ]3 x; D3 e# U
                        lowpass_filter[0] = output;% F% f  R# ?/ \+ Z
                } else if( nFilterType == 2 ) {; p3 T( {, H; e' Z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
9 G. i1 g5 f) T# b) q0 b                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ S+ Z4 e' T! F) o                        lowpass_filter[1] = lowpass_filter[0];
6 `: P! ~  p' Q' S) I                        lowpass_filter[0] = output;* N+ V2 U! {: q2 o- C2 e
                } else if( nFilterType == 3 ) {
9 C( ?' X7 h% g" t                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 G; V& y& c$ a1 c                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; t- @9 M) m. W. ]+ I8 R                        lowpass_filter[2] = lowpass_filter[1];$ n) v6 g* c/ w2 l; ^+ t( v
                        lowpass_filter[1] = lowpass_filter[0];
0 B5 v- E1 `: W6 d8 j6 G5 f. z                        lowpass_filter[0] = output;
. N: n5 e5 f, A' Y& ?# h                } else if( nFilterType == 4 ) {8 I& T: g7 v7 S2 q
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 W2 {( @& ?; B* F& c  W/ E                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;, K9 s2 n  j5 l- O5 S  A2 v
                        lowpass_filter[1] = lowpass_filter[0];6 c7 ~" o- J$ o
                        lowpass_filter[0] = output;  i- }! N! G* B, B9 q
                }0 y: V9 u, m. b; s0 s
, ?. B* D( X: ^& l7 C0 H* p8 P9 T0 D; R- m
#if        01 U$ L8 u* F) _
                // DC惉暘偺僇僢僩
; m1 t% H9 g0 Z  }6 w                {6 z& U; k$ Z$ c
                static double ave = 0.0, max=0.0, min=0.0;8 ~' H2 H5 G3 _% D$ F
                double delta;0 A3 ]5 l% @7 B- u3 q; L
                delta = (max-min)/32768.0;
8 M( K, i4 F; H4 Q5 w: }! T                max -= delta;
  }5 N+ A1 J$ ^' H                min += delta;) I- g, c6 k8 h* k  p% q
                if( output > max ) max = output;8 K6 P( _/ S- F
                if( output < min ) min = output;2 o+ ~# @9 [( X* N
                ave -= ave/1024.0;
' F( W5 g/ G8 H2 v' ^                ave += (max+min)/2048.0;
" X/ m& O3 \: q5 {3 k8 G: O% t                output -= (INT)ave;2 j, j9 @& t( m: z
                }
8 b% Y# I6 ^  ]* l- F( t, b& \#endif* m- O& G- T6 y0 [, y9 f- R: B" e
#if        13 e) A7 h2 o) {0 h' x2 U# p4 ~
                // DC惉暘偺僇僢僩(HPF TEST)
4 \  ?- z0 s6 C3 F                {
2 ^& T. R" j7 n' W8 j2 C3 n# Q' _7 W  j1 d//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 t. k) T3 c# V$ V' Q- h                static        double        cutofftemp = (2.0*3.141592653579*40.0);+ w* f( V& e: l% V3 w+ v) _- F) H
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
* H: i0 o  p; g$ q3 V1 O4 V/ f: ?( T                static        double        tmp = 0.0;7 z5 y$ H6 v2 }2 Q
                double        in, out;
, B9 ]& E; i2 o6 x- \4 E6 Z2 i$ V
0 ^% O# l* |5 E- |6 j                in = (double)output;
! K0 Y0 }" k3 b( u0 I                out = (in - tmp);
& t- H6 j/ b1 ?                tmp = tmp + cutoff * out;( ?' m: b0 p- r" S  V
7 t  |2 g, n4 e2 c. O9 A  }
                output = (INT)out;
% K6 o  s8 d9 b" Q6 E) C8 h                }5 T0 _  A/ ~( I# m
#endif4 f- a* r# S' l: d8 z
#if        0
* n6 u0 \6 a" _                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
1 s& J+ f0 y/ Y# ~4 ?8 ]% }                {" b* T1 r( z6 V* q! H
                INT        diff = abs(output-last_data);* v. H1 g7 F2 A5 T3 v( _! B' M$ u
                if( diff > 0x4000 ) {0 k; j$ h# j9 }( J$ {. u4 p
                        output /= 4;& Z& A: F( d8 m7 V: t$ D
                } else - o) S/ W! \1 |1 m+ N2 ^+ ]
                if( diff > 0x3000 ) {
  S- @' b. d0 j. Q5 g* x9 t. n7 u                        output /= 3;
4 G1 z; ^: L. u                } else
' X3 _9 a4 Q; z                if( diff > 0x2000 ) {; [8 A$ @0 I# W/ x9 _
                        output /= 2;
5 F! v. Z* x- ~$ `! u8 _                }
' e+ M  H7 |7 M# Q2 `                last_data = output;
, E# ~; H6 n- y- d                }
" t5 J% J+ ^8 v$ ]% z#endif
1 j  H' Q, ~! g: E) z                // Limit3 b+ H/ {5 |: N9 M
                if( output > 0x7FFF ) {5 @, h+ m, p1 K! J0 S9 v0 s/ r7 Z
                        output = 0x7FFF;
+ P6 c, p& L, r                } else if( output < -0x8000 ) {
2 J* s& C0 C3 l# x6 {                        output = -0x8000;
' r/ l0 J6 a$ z5 a# [                }
4 c0 s3 E# [4 U' h
6 E; Y+ {' I/ v. T( _$ q                if( nBits != 8 ) {
4 w: Q3 b6 e4 T% G4 _& v8 n                        *(SHORT*)lpBuffer = (SHORT)output;
; n6 u% q) ]5 k& t. ^8 Z  i                        lpBuffer += sizeof(SHORT);3 C" T/ X/ B& U- E. I
                } else {; ?. C; q' L* P6 ?* ~
                        *lpBuffer++ = (output>>8)^0x80;
( g5 O  f% N* u                }* T% Z  t0 ?8 Z+ O/ m" \
* P$ w. g! m4 W2 o/ u3 Z
                if( nCcount < 0x0100 )
) P& |4 X0 _1 t) d% b3 H                        pSoundBuf[nCcount++] = (SHORT)output;
3 U5 H; e! C4 g: S5 u6 u  j- m6 b  s8 W. ^
//                elapsedtime += cycle_rate;
: ?& C4 a; e' F' S; m; D                elapsed_time += cycle_rate;" {) E+ p2 p/ {9 z9 x! x
        }
+ n5 e' B' I& @5 K: `7 F5 L' [$ W/ k. j3 ?2 p, j# w
#if        1
% Z  `6 p3 O/ n$ ?7 {6 @        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {  ~! `% U1 r' x8 R* h! J6 w
                elapsed_time = nes->cpu->GetTotalCycles();* m7 k" Q* ?+ G3 ~: k8 R. @
        }5 K8 f1 ^" U3 Y: B
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {1 R& o" @; @1 v+ o5 y$ U* e
                elapsed_time = nes->cpu->GetTotalCycles();
# `; Z  [2 i  x, P        }
0 m4 |$ C4 Y% B" g#else
9 O! `/ _" H+ M, P3 X/ e$ p        elapsed_time = nes->cpu->GetTotalCycles();3 O* G7 a! {. _8 f
#endif
5 n' B' L: Q; G) x! i}
5 T4 }7 k  p/ p0 C' d, Q* m' [0 J. }) w' ~! i8 j6 \
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! V; O* ^+ b( l6 b7 fINT        APU::GetChannelFrequency( INT no )* c4 [- j4 y, ~
{
$ ^" ^) {7 w8 m) Z        if( !m_bMute[0] )
0 g9 [0 a8 q4 d& O/ X' L6 Y                return        0;  t% ?  P( ^$ @  g$ w
# `1 D3 q3 S# Y- f7 m( f7 N
        // Internal
, U- z6 B3 H1 b        if( no < 5 ) {
( `  V3 m# {3 `! m5 l                return        m_bMute[no+1]?internal.GetFreq( no ):0;
6 {- ]9 s3 N$ t4 l2 \        }
) s; h( Z+ l7 p: |  k9 u        // VRC6
3 s0 f3 @8 U* x        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' W# c7 n5 U; s& L& i* G4 P% V                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
- Z0 v& t% p' e9 S) |" @& [        }
/ c0 L9 d; I4 L5 {* H        // FDS3 ^7 S% S4 Z9 M% ^1 Y
        if( (exsound_select & 0x04) && no == 0x300 ) {
3 D, n' v4 i. P) K8 D6 y                return        m_bMute[6]?fds.GetFreq( 0 ):0;, I% J1 _! h: l( z
        }
" i+ x0 ?( M0 h. z$ ~4 J" r: x2 m        // MMC50 X& {/ L3 j0 E+ A
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 A) r& h/ B2 b
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;+ `2 b" h8 I, g1 a. O/ [+ i
        }8 ^7 g$ V! g, D" `
        // N106( q0 G* H- E) J: ]' F  J9 g
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: W$ j! o' ?1 l4 t8 _5 s
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' I. M) t( u  t6 }; Q, j* y        }
8 K% s; o; R$ V' k+ c        // FME7
/ i7 R3 w- Y* p% @        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
4 o% x. _6 V! A8 w                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* j/ [% n/ Y) t5 z2 m5 c5 t        }
3 Y% Z5 \. `/ n        // VRC7
9 R# b1 r) ]9 A7 k2 v% Z! @: ~$ x' ^        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {% v/ _! \0 T; v. M! {$ D; C) A- b
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- G4 L$ x4 J. \: \        }8 w0 g& i# D, D) F& b3 L( g# E
        return        0;
# b- U( b) J1 i7 ^! U  i. ~% I: T}' p) `. G. i7 H5 }( O( @) L

1 f  H7 I( F) t+ P// State Save/Load
* X9 s2 U- w1 |6 F: S% ?# ivoid        APU::SaveState( LPBYTE p )
: _& z- e" T! z% ^$ Y7 Z3 O{
9 n: Z3 a) Y* o#ifdef        _DEBUG3 m) s2 \  K- a' k2 c
LPBYTE        pold = p;
0 s& I- Z! f9 z& a$ s& r#endif; B- M/ [- T' D. u2 W7 j; k

! D& Z+ D( r) u0 c7 B6 C        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
0 d- E" e# [  q' r0 R& k        QueueFlush();
4 @' L" `6 U& }6 D
9 k. P6 t5 C( J+ D! g9 P3 d  g* [        internal.SaveState( p );
! E; |! m! Q. {2 C# ?: {$ X        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ g: L, G6 }/ \/ ~) A9 {4 B! j
5 Z* t( E# Z7 |* `3 i" G& C. W        // VRC6( X$ [1 D- p! u
        if( exsound_select & 0x01 ) {
' x" O& T; ^( \# f3 A                vrc6.SaveState( p );
1 S+ B4 `, r- U, q) s  X                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, Y3 u; J' c8 \4 s" Q
        }, i# z9 f! P7 B; Z  e
        // VRC7 (not support)! m0 I5 V7 j, t8 S* T$ T/ S
        if( exsound_select & 0x02 ) {
  G& e8 X- e  C: I                vrc7.SaveState( p );3 ~6 j5 f& k. @, y1 ~
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& J+ c) ?9 g$ L3 u        }) D) p9 j  A2 E2 j! ~
        // FDS0 \5 [4 c" x: Q. x* o) q8 n
        if( exsound_select & 0x04 ) {% \- U  y6 e8 s0 ^) V% r
                fds.SaveState( p );
$ H  D! C1 m7 z  [1 C# M  k                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding  d' w% d$ r+ a% g& i' Y: x; t7 o3 G' {
        }- ]% }  X) T( {6 J: Q
        // MMC5
( F) X3 c7 M. B# s        if( exsound_select & 0x08 ) {  C' |6 r% _* }$ l% ]; ^
                mmc5.SaveState( p );
# X8 A5 K8 G' h* W, I8 P                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& Q) ], F/ W; |. s3 g' h
        }7 W6 j7 y2 E. y) x1 X/ s" ?
        // N1062 }' \  L! {7 Z' K
        if( exsound_select & 0x10 ) {
% L6 Z# ~  C8 q0 p8 w/ P                n106.SaveState( p );
- Z( }; l! |1 n( h# H% x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* b: p  y* n: ?$ F% t/ X! Y
        }
% H* H: p& q0 G/ }        // FME7# s9 b6 W& a8 w3 Q" Y6 g* C1 p
        if( exsound_select & 0x20 ) {2 l. R4 l, Y6 r; A! J& C
                fme7.SaveState( p );3 s# L* K9 y! _! N9 z- g( }( M7 |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 L$ J( I& l! z: g
        }
3 v2 U3 A0 w9 W+ f. A) V& h7 t' d3 I2 K# s( x* k* @' H  X" W
#ifdef        _DEBUG
5 w; b' Y6 f' c8 H) Q  {DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% ]! N; ^5 m2 V  P4 w% ?7 I#endif. Y7 Z' `+ M& L! b- f
}
  l8 m' i& j& `4 i1 h4 j: q, u& u! Q# W" A  [7 O5 q9 J
void        APU::LoadState( LPBYTE p )
2 X, W3 `) k& P5 w0 p3 U: j- b( N{: b0 Z( {- Q7 n0 R
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 B- a1 `& b5 K7 N
        QueueClear();
" s" Y/ ?' ~3 B' l8 r  X
& b! K! `) Q0 n: {3 R9 x        internal.LoadState( p );$ A. }& j) [  a3 q, U+ x
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& b+ r+ K, w8 s" s6 k* l5 D" F& {# D3 _6 m3 a# Y. u1 x% A
        // VRC6$ c  b8 d+ k) W9 [7 e$ N9 {9 s8 \
        if( exsound_select & 0x01 ) {
8 k& \4 r& f& g' O  o                vrc6.LoadState( p );& @0 W- N( D3 h
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' U9 @* B' b- U# x' H3 t6 P2 y0 d" s
        }
: ^; T; ^# k6 k        // VRC7 (not support): f6 z5 M  P( E# i- k+ {$ _4 l. H
        if( exsound_select & 0x02 ) {
4 S1 W8 t1 ]1 B1 j                vrc7.LoadState( p );  F% ^1 ~: R7 Z% n$ r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" A6 y' J0 g3 z) l, d( ]2 z
        }
) @. U8 d4 @; v8 l/ q        // FDS
! p7 N% N4 D6 o; T+ ]2 V5 d        if( exsound_select & 0x04 ) {7 }# w4 j8 T3 Y) P. L1 z
                fds.LoadState( p );
+ F+ r% a( s4 P                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, g; O# ~/ h" A6 n! R        }( N2 L* D. S2 [! X* o! H8 L3 _7 d( F- A
        // MMC5! I6 r% j  k: {
        if( exsound_select & 0x08 ) {
+ Z1 Q' p1 z& C2 P+ _+ A                mmc5.LoadState( p );# Y1 |' R5 a+ c9 r$ z2 V
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 L4 c9 A* ~" j' H
        }
: Y' T4 |: Q4 A+ `        // N1060 W4 f2 ?* x2 K7 C) ~; a
        if( exsound_select & 0x10 ) {
, ]! e$ w5 c/ P4 v+ O                n106.LoadState( p );
) W* B* p! D7 N8 O- c                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 l* g' C5 D" c! J
        }% |/ \& X2 L0 P! O! r; p; j
        // FME78 l  Y8 g( c: O, l2 _5 _
        if( exsound_select & 0x20 ) {
0 B3 y- u, r) d7 f% v3 p                fme7.LoadState( p );' w0 J0 z, {% P) z' R
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 C( @7 R# V; K( [( |
        }
- j" d- U3 |3 f}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ! G/ Q' [" p6 Y9 q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- N6 F5 `3 i" s, H4 A
感激不尽~~

+ c" c( z* V2 L% w' M( N恩 我對模擬器不是很有研究,+ O# U) V1 a! I0 \
雖然要了解源碼內容,可能不是很困難,
4 {% G& N8 c$ ?1 E# l1 t不過還是要花時間,個人目前蠻忙碌的。8 K; `- W( b3 ^- O
: `( E5 v$ ~, l. S. |$ c# n/ _
給你一個朋友的MSN,你可以跟他討論看看,
# Q5 D) ^: [- t, P+ Q他本身是程式設計師,也對FC模擬器很有興趣。; r3 B; P6 q1 T* |. {$ m" y

- b( M( ~  p9 Y! O% y" G1 ^MSN我就PM到你的信箱了。* N4 [, H" D2 j& B
. F3 d* Z* `: n+ D& A) T8 D& z* O% B
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 6 f* \4 J! s, h" e
呵…… 谢过团长大人~~

5 ]. x& J5 j  [- S- \) s1 C& O9 M6 b! {9 v2 r* W; M- ^. v3 w  ~
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
/ K. |8 p( Y9 k  Y4 `6 I3 I; e团长的朋友都是神,那团长就是神的boss。
8 ]* ]3 V) l( K& K% D
哈 不敢當,我只是個平凡人,
9 S3 B2 y. G: {* z3 S3 }: L* S# @要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙1 M0 v. o; Q- D$ Q3 L+ f3 J+ G2 A
ZYH
% h7 `# L% J/ _/ |) [7 \QQ:414734306
+ H; h2 ^; f! o7 ?7 _Mail:zyh-01@126.com
/ N% V2 P; g+ K1 y6 v9 f
% d- W- Q# i; B7 W他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 4 ~5 o4 h1 q! |' L/ o* E
再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ d% `- G9 M0 ]3 v+ X( X/ o不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-4-20 07:56 , Processed in 1.178711 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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