EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( I% q0 R1 c7 |( [6 l楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! T  f' ]1 l; J0 k7 g- C% _这里有相应的模拟器源码,就当送给大侠了~~; Y# j% {8 g8 V
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
) t7 D; j- B: s+ t% o6 r能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ F: Y2 a3 H  W4 y4 [5 c楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; I* w3 _" u* b! J6 k! ^
这里有相应的模拟器源码,就当送给大侠 ...
+ h# b! j( w9 c3 g9 d% Y
聲音部分(Audoi Process Unit = APU):1 y1 P' X3 M+ N! Q7 c
.\NES\APU.cpp& m3 i% I# B- R1 _$ Z! H& X
.\NES\APU.h9 K, h" @+ I; F' r( S$ a1 S  d

8 r( u' N3 q# ?& z. ~0 `# K8 p  l- r/ _& P9 D  ~" \& z
影像處理部份(Picture Processing Unit = PPU):
( m, }7 r% ]% ~% Q0 y.\NES\PPU.cpp
$ l" g; W7 f# x( w, Z+ O.\NES\PPU.h
6 H3 p* @, R/ p3 ]6 _7 Y$ p
$ Z+ {2 }! W+ ~+ z. m如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:' l$ M+ W. h+ \( v
(由于很多专用术语和算法机理都不明白,所以看不大懂……)* n' G( |3 d  c8 c5 B8 m
//////////////////////////////////////////////////////////////////////////
8 a7 ^+ Z9 m, o- v; l4 X//                                                                      //
( P) E' |' a- |$ j9 J7 Y' l//      NES APU core                                                    //
( I: N4 b! e8 A4 y4 X/ R6 e9 ~( ]//                                                           Norix      //( o- F% R7 ?4 D
//                                               written     2002/06/27 //
3 w) U& A/ H. c$ L9 K4 {//                                               last modify ----/--/-- //
8 R( o" r% R' w+ b9 v//////////////////////////////////////////////////////////////////////////
& \9 t9 K. {% Z$ `; r/ ~6 ^#include "DebugOut.h"
2 F6 J( ~- t+ n1 h7 H& Q/ g#include "App.h"
* U5 y4 j/ g4 q& x& R5 p5 `#include "Config.h"6 I! ]- v1 d6 ~6 |7 K

# }, R& r4 o0 z2 g) I1 H#include "nes.h"
8 x/ n5 v. A3 V# _: x#include "mmu.h"' j, o$ L  O0 f9 Z; U* n8 q8 R6 N
#include "cpu.h"
& Z5 S) T, X8 s( s" D0 K- e" s, O#include "ppu.h"
- k# W5 d/ }9 v- ]#include "rom.h"
# K: B! ?% F/ W* b$ _#include "apu.h"
; j- J" ?+ h9 N3 S- U
! c7 `2 W( t8 f// Volume adjust5 h, h! H+ }( D( O) P' r
// Internal sounds
6 b: j# P5 {# y9 @! `4 P#define        RECTANGLE_VOL        (0x0F0)0 v" {% _0 `! a; E
#define        TRIANGLE_VOL        (0x130)& t- R" p1 K% R; e, j
#define        NOISE_VOL        (0x0C0)' b; h# D: P( h! N  j
#define        DPCM_VOL        (0x0F0)4 o# O) @. V7 o; {8 H* @
// Extra sounds
7 k2 y' a: D: G! w#define        VRC6_VOL        (0x0F0)- P) K/ O% Q9 c, f' n. s
#define        VRC7_VOL        (0x130)
. t  Q3 c+ [2 W/ P#define        FDS_VOL                (0x0F0): c4 j+ M3 w4 y, b
#define        MMC5_VOL        (0x0F0)
) T: |. {' \1 y9 Z, Y#define        N106_VOL        (0x088)% O7 k( a- ~, o4 s* a" U, R" [9 J
#define        FME7_VOL        (0x130)
. F, D0 k/ R: V4 Q# z7 C) B* e8 n; z$ H  d/ E( `5 J
APU::APU( NES* parent )
  C6 `8 L, U7 p1 c{, Y; ~: f. B! u0 z# J' x8 e5 q6 B
        exsound_select = 0;; a. G# E+ h, B1 |% H
6 [2 i1 b! W. }- Y+ O
        nes = parent;7 V* K4 @$ v5 W! a9 Z/ R  t
        internal.SetParent( parent );! r& A1 c& \3 v! A+ }2 y/ y

% y( F# L# i0 r        last_data = last_diff = 0;
. O0 O' V" k# A6 v; L  P
- l. {1 v$ g# F$ b        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
6 Q& [1 K4 C( P6 J2 x9 J9 M" d' L: s$ `) Y) C
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 z4 J% Y. S% {7 v4 B% J* c! n. M
        ZEROMEMORY( &queue, sizeof(queue) );
! i# I( B' d2 v/ E% X3 C        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ u! F7 ]1 |# a7 n: V$ S* A( Z  J. N5 G- D/ n
        for( INT i = 0; i < 16; i++ ) {- @  y, q; v# U# d9 a
                m_bMute = TRUE;) z6 r7 N$ U6 f; R
        }
5 c/ H/ g3 m9 |9 X+ |* u* |0 Y/ t}3 P# Q! v* h' p+ I
5 `- h) ]) f9 v; r1 k( V- U/ e
APU::~APU()
! |  p' [* c  \3 Y( H{7 z  F/ E4 G+ a6 A' \: r. J
}
* r1 f9 F. f1 R: [" y, W0 Z
+ {0 O$ R3 k/ |+ t5 |7 F* zvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data ), O7 Q. j0 v* d" b1 F
{
- }) y% u0 H. S/ T2 K" `" T        queue.data[queue.wrptr].time = writetime;8 @! @0 ]- w( s  q0 g* O& L3 D6 W
        queue.data[queue.wrptr].addr = addr;
$ f6 P1 n6 [7 P! u9 b9 p" Z        queue.data[queue.wrptr].data = data;$ d* Z* N" o) M! A
        queue.wrptr++;; J; h/ y% T; z3 F+ J
        queue.wrptr&=QUEUE_LENGTH-1;0 q3 D$ a, z2 Z2 [
        if( queue.wrptr == queue.rdptr ) {
( k' K& b2 e) g, z" t: j                DEBUGOUT( "queue overflow.\n" );7 g# u* [! s& H, Z0 L: T
        }: e  T6 }; m2 m5 G
}$ w0 K: B4 d6 S7 ^1 r7 o" h8 l
4 d1 O5 ]2 {& S9 q, G
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ [1 @: ~5 {! q6 q* [" o8 p* G4 l8 W
{; d6 \' _( v8 E- F3 v
        if( queue.wrptr == queue.rdptr ) {  [5 b! s- X& q" {- A
                return        FALSE;! n( L$ }( V5 m2 l' F& j/ O7 ~
        }0 ?( M* c$ Y, z  Y
        if( queue.data[queue.rdptr].time <= writetime ) {4 I6 W# [6 s1 s7 P# @8 Z
                ret = queue.data[queue.rdptr];
" Q4 {( C* ]4 ]6 I" Y                queue.rdptr++;
' n/ X; M! O6 w$ q  ]+ i                queue.rdptr&=QUEUE_LENGTH-1;+ O7 C: I3 [9 ^' V. {+ C
                return        TRUE;
7 j0 R: {& u0 G2 f        }/ Z& r: b3 D# k: F( K, ]1 M) @2 m
        return        FALSE;
. H1 ~: a8 z$ Q: h4 M0 D}7 S$ |/ }/ [/ W  [' {/ V

) g& T& P# e4 ?* d6 Y5 e/ ?! \9 Fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 J4 P9 G. w* P/ o$ A9 ~{. z+ ~6 B3 j/ A7 Z9 C4 O
        exqueue.data[exqueue.wrptr].time = writetime;
, t' b0 M) m! T3 G, U8 W' U0 r        exqueue.data[exqueue.wrptr].addr = addr;9 h! L2 ]. g, W
        exqueue.data[exqueue.wrptr].data = data;% s7 X9 H4 J3 V- I4 Q
        exqueue.wrptr++;6 n  W. e+ {9 g, ]# j
        exqueue.wrptr&=QUEUE_LENGTH-1;  x$ V4 m( z$ p$ T7 e
        if( exqueue.wrptr == exqueue.rdptr ) {+ ~9 \5 z( S+ E5 i- W' B0 m
                DEBUGOUT( "exqueue overflow.\n" );: i4 x. z3 y' _" K2 y# j0 a
        }; V% ~+ S$ W3 m! f8 g
}$ s6 O3 g5 @' P" ^- r0 h% y  J
1 r0 s6 g; E$ v- t- Z) H+ t
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )3 z. {* k5 z. @7 O8 c& \6 r0 j
{
; K- }: p7 X1 n  Q3 m8 m        if( exqueue.wrptr == exqueue.rdptr ) {
0 t4 w9 j( H( k3 {, ~- j0 `1 W                return        FALSE;
3 l9 z5 S# w, [        }
) Q( J- {: b; Q0 f' L4 ^. A, E        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; ]& g, ]" c+ A3 K
                ret = exqueue.data[exqueue.rdptr];
2 a; K; |# m: w/ k* z6 C# c                exqueue.rdptr++;% Q. ^6 [* x- P7 _
                exqueue.rdptr&=QUEUE_LENGTH-1;" W  f7 f$ @* n8 ~' ?# R& E7 w, G
                return        TRUE;
0 z# Q) D; N5 }        }7 T; n+ H' G8 N) D3 }- U) S
        return        FALSE;% R) }5 ~" U: x' l2 {, M
}
/ L! G5 G' m, o  G( W8 H5 C9 _# L  p
void        APU::QueueClear()
3 ?, T' m3 U1 g7 X/ ]{
5 J# N: {6 E% e2 i        ZEROMEMORY( &queue, sizeof(queue) );
! Y5 C! C' E6 k5 U, g! H$ F        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 ~6 B3 D) g$ k! m" W0 ~; C  a
}& R7 e$ @1 \+ V9 M4 Q/ t/ D6 C

) s  j* d6 y7 @. c7 y# i# Wvoid        APU::QueueFlush()# r' X1 {% v  r- X3 Q3 J6 H( I. I
{- B& D! F; ?" }5 k) E$ L6 s4 B
        while( queue.wrptr != queue.rdptr ) {
) \3 s, t1 b0 j+ H                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& U) [: _. i2 R6 m
                queue.rdptr++;- w0 C; y! r8 k( ?4 H% z! o8 B
                queue.rdptr&=QUEUE_LENGTH-1;1 ]1 o9 j9 F' H/ Q7 H
        }
/ v2 |% [, h! C$ K0 b9 N. U6 {5 T1 N6 D5 k
        while( exqueue.wrptr != exqueue.rdptr ) {8 e7 G& J$ H7 T6 ~1 x3 z6 O) [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );; v; t) H/ E; h  G* z
                exqueue.rdptr++;/ y5 X( r6 |% E& D  R" D+ z/ F, n
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 _4 R% y  G! O7 j        }
6 L0 H5 ^2 p* d0 R}
3 O. {/ f. B# |' H4 f8 a0 Q* c8 G( K( s8 N
void        APU::SoundSetup()
/ M" ?2 }) C5 c( ~0 |{
" _: e$ m! c8 s4 }/ O0 u        FLOAT        fClock = nes->nescfg->CpuClock;
. t4 m' e# Q+ r3 g        INT        nRate = (INT)Config.sound.nRate;
# Y' l0 n1 n9 K" G        internal.Setup( fClock, nRate );
9 v" J2 i, E) a; T2 \. U$ F        vrc6.Setup( fClock, nRate );
5 w0 K5 \/ j: Z7 B; B" G        vrc7.Setup( fClock, nRate );: u" P) ?: l( u/ U8 D
        mmc5.Setup( fClock, nRate );' T2 ]3 P. T; b: F1 e3 O1 E
        fds.Setup ( fClock, nRate );2 M$ V7 k6 r- E$ w8 L
        n106.Setup( fClock, nRate );7 T0 p4 E4 I0 Y: P$ O4 M6 V- H
        fme7.Setup( fClock, nRate );
  z, |# o4 |9 R* o* @  b' j}
5 |& o! a' M) h% |
- a8 Y/ X5 Q, _& ~2 Mvoid        APU::Reset()3 F1 I- k0 {, C( w
{6 m. `# Y! k* v. z) y* \+ r
        ZEROMEMORY( &queue, sizeof(queue) );
0 }7 l4 e& O2 z, T        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 b- ]% A4 Y) k9 Y+ M; h" P
; q0 n/ M* y# j3 a( z        elapsed_time = 0;2 d; Y' `/ T. N' g, r! e

8 G/ m3 u3 N% x: c        FLOAT        fClock = nes->nescfg->CpuClock;; c4 U+ j5 w# b8 r5 B
        INT        nRate = (INT)Config.sound.nRate;* P/ n. P- s( Q# K8 G" A) o: z
        internal.Reset( fClock, nRate );
8 ?9 C, a+ @8 ^6 H        vrc6.Reset( fClock, nRate );
# D% y; F( Q0 M/ U& T) K        vrc7.Reset( fClock, nRate );
. [" _- Y: u# o7 F" V3 U        mmc5.Reset( fClock, nRate );! u& W  }9 @# F+ g# e) T& \% S$ W7 e
        fds.Reset ( fClock, nRate );6 v+ w+ W) z, l
        n106.Reset( fClock, nRate );; y' z3 z# P: a
        fme7.Reset( fClock, nRate );9 R6 [4 U% I. Z

8 T% c2 m9 L- Q& u+ M: {( G        SoundSetup();
- m7 x9 ?- L# G+ v5 }6 t+ {}
* t: c- y: v/ [6 f& c5 ]3 ~/ O4 N9 K
void        APU::SelectExSound( BYTE data )5 }: j7 B6 z+ E; V# M& `( q# U: a$ @4 S
{
0 H4 s' [! j, z3 t        exsound_select = data;  W4 `# Z3 C  S
}7 g2 I/ v# T/ q) R$ y( S1 D
; P4 e4 Z* j) F2 A* F
BYTE        APU::Read( WORD addr )" b" [7 }. k: x9 N  x2 D( E
{
  X, J; I# B; X' d: a        return        internal.SyncRead( addr );
/ l; y" a9 {. K( E, D& K8 H}
) x- b! ^4 `/ `5 o$ p4 W
; {  A& @3 Q& |) p- P  Xvoid        APU::Write( WORD addr, BYTE data )
- K6 F9 U! f4 [{
. R8 M5 l, L% y% A, Y        // $4018偼VirtuaNES屌桳億乕僩
" X$ U' [" [- `- D; s% W        if( addr >= 0x4000 && addr <= 0x401F ) {
6 x" X3 M' K! x& l/ Y                internal.SyncWrite( addr, data );% U/ y/ H! U9 a; d
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 l9 F$ }/ V$ S3 x% U8 \
        }, N4 S# I. H: w8 Y8 D
}
& v2 v. Y8 a) g" h6 ~7 ~; y4 W% f7 s3 F1 _  n- G' H8 n. b. h
BYTE        APU::ExRead( WORD addr )5 L, G1 M, ~/ I6 B+ }
{
9 Y2 d& Q- ]# M7 d& E& ]% t4 wBYTE        data = 0;
# ]; U; g# ?5 W  B8 K, B/ r: c) F7 j/ j% [+ ~& w% }8 y
        if( exsound_select & 0x10 ) {
# n$ Y& w0 C1 x                if( addr == 0x4800 ) {# O) _, k: s) D9 n  }" \/ ]
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );9 i/ I& O# R" B! `  s
                }
  `5 z7 z  l$ i        }
: ~+ A4 i$ D' v        if( exsound_select & 0x04 ) {1 W" }3 w& U2 b9 m
                if( addr >= 0x4040 && addr < 0x4100 ) {& m, F; |& L9 H% p$ m$ b
                        data = fds.SyncRead( addr );  ~( ]( I! |3 o
                }
+ ^1 ?( a$ A1 D! G! x& u        }
  e; s8 I& c: e2 s2 y4 Y  d        if( exsound_select & 0x08 ) {4 s; U7 d7 O# j$ a/ Q1 q# }9 K
                if( addr >= 0x5000 && addr <= 0x5015 ) {/ ?1 C6 o1 U0 N) L
                        data = mmc5.SyncRead( addr );9 A1 o( q  Q, U: A9 R5 m' i7 M$ V% e, |
                }
5 ~+ z0 ~* D6 A2 S2 c$ A        }9 K! D: `& y- G- K/ B
( Z: W$ R. V8 q4 E3 ?% Q/ Z
        return        data;  _6 o, N; I) @1 ]; i
}: u: k# S% \& A, d2 s
/ w# r% V6 V4 q. i% W2 r
void        APU::ExWrite( WORD addr, BYTE data ). [  ~& q! X% T) J
{2 U+ B: O- k4 A/ O5 w: v* S, u
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );. h+ e! S& s& f

* O# r9 H, Q4 l9 O! X  O        if( exsound_select & 0x04 ) {
# [7 v# q1 j$ K1 O6 w# A+ {3 ?                if( addr >= 0x4040 && addr < 0x4100 ) {
* {- V  g" A2 r- F( H; q/ Y                        fds.SyncWrite( addr, data );
/ x( u8 c: Q& b# k* e                }& v3 j) y1 D) [- V
        }% G" y* o  ]4 V+ L; f/ v
9 K8 T% u) ~2 D6 \2 [( V( ]& q$ T
        if( exsound_select & 0x08 ) {7 R- B4 y4 x$ T, M' Y  f) f
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# P9 f+ P& H: @0 N: U* G                        mmc5.SyncWrite( addr, data );9 _: C7 A) j2 W  I* r, W
                }
% i! g  v7 n- `9 J- i# \5 W& y4 E        }- [! }2 U: D; J; o: Z3 x& f: j
}
! V1 N7 e8 K! n6 {& N6 b' R. M& r; I& o
void        APU::Sync()
& ]* l' `( v" V9 E  z) T{
  V% e* m$ O1 m2 _}
" q: P# ?, t. K! Z$ w6 E5 F5 p5 H+ F+ M3 O% n. S/ s
void        APU::SyncDPCM( INT cycles )
+ b) b/ W% P: A' D{
2 k! z) X* a' V0 s& G) }. G' @5 B        internal.Sync( cycles );* x( E1 t, Q; A# b+ H, Y5 }9 a6 s
9 F) |( B" H- O1 Z
        if( exsound_select & 0x04 ) {1 T: W$ T+ C$ Z/ g1 J
                fds.Sync( cycles );+ L4 H/ {+ }3 n: ~
        }
. I7 ~4 ?. J5 G4 [, M/ q        if( exsound_select & 0x08 ) {
0 R/ g! a+ }2 p3 A                mmc5.Sync( cycles );- L  [, G5 a" u# {
        }
/ s$ F  H2 ]" x8 m- c8 }}- i8 a- M, V! R4 W- s+ L
- o. ]5 t3 n% E- q
void        APU::WriteProcess( WORD addr, BYTE data )5 Q9 K: S. B( S. ~' \6 Z
{
! a% ^; M7 T( l* K) u0 U        // $4018偼VirtuaNES屌桳億乕僩
! F' q6 \% T( ^, d2 Z. [        if( addr >= 0x4000 && addr <= 0x401F ) {
) b5 J, F2 w+ D; {; Q' z# Q; v                internal.Write( addr, data );6 A0 `* j, ^) _( T% r7 g2 @8 q7 O
        }
. `& E) |1 V+ a! F* |}& \' ]. z5 ?) Z7 v
( i6 x5 A5 R" ^: a
void        APU::WriteExProcess( WORD addr, BYTE data )& l1 R/ U7 Y$ P/ o
{
# _/ K! \/ |$ m( D8 ]        if( exsound_select & 0x01 ) {  e+ {* ]- P/ R1 |$ l
                vrc6.Write( addr, data );+ z+ A* N( `8 W# t* I
        }
' [5 ?. f, u. s9 `7 a+ o/ j        if( exsound_select & 0x02 ) {- h& I4 H& m# q; k0 w0 |# O
                vrc7.Write( addr, data );
0 U) g. ^; S$ B/ l/ e        }
* `1 m+ g6 V9 e8 U% p. S        if( exsound_select & 0x04 ) {- u- @1 L8 A9 b2 w- H2 c0 [
                fds.Write( addr, data );5 x- x% b  q) |: c! f
        }# r0 x- w( X7 S! f/ D. V( A
        if( exsound_select & 0x08 ) {
) t1 s$ V2 [1 Q. H$ k" ]                mmc5.Write( addr, data );
$ U, ^) B7 d; P  H! A        }
) @9 V* U2 L! B% `        if( exsound_select & 0x10 ) {- }' a2 u% o3 [) m9 @
                if( addr == 0x0000 ) {2 Z( A  C) A$ p0 d
                        BYTE        dummy = n106.Read( addr );
) f8 G+ }) U: o( t5 `' s' S7 y$ n                } else {2 `9 i& |- [0 o+ Z- F/ H$ E
                        n106.Write( addr, data );
3 @4 c% _' V9 T4 O* I                }; y; s7 l& ^! t- C: i. F* \/ D3 b2 [$ \
        }1 O) C/ d" C& o
        if( exsound_select & 0x20 ) {$ b/ Y* R* D* _" z) M
                fme7.Write( addr, data );
( W9 o" j8 D+ `2 q$ @8 P6 h        }- I7 S3 v" C9 x$ c! \! O
}
, V0 E. p2 Y6 ~( R! }3 U1 Y/ C- b" ^8 q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ f8 [% ]" y: Y! m$ v* Y6 z; @/ N1 y# m
{) k  Z7 J7 a; Z  b' A3 d4 Q6 J% r8 U0 O
INT        nBits = Config.sound.nBits;
4 q, L! a6 Y# B% }7 M7 ~, lDWORD        dwLength = dwSize / (nBits/8);3 `' ]( g1 ^) x" T
INT        output;0 C2 O6 K( |! ^
QUEUEDATA q;! X! y9 ~, P3 G9 }' z
DWORD        writetime;
/ Q; E* o* A7 y* e9 S# _7 [, K' E5 E4 \! O0 b8 U
LPSHORT        pSoundBuf = m_SoundBuffer;0 t8 C* L/ n  _
INT        nCcount = 0;- N% i; R" J4 Q+ F" X5 H! ?' R* y

5 p  M: f% \* C% IINT        nFilterType = Config.sound.nFilterType;& N( P2 G- N2 Z' K* F
9 h8 Z6 z( Q- z
        if( !Config.sound.bEnable ) {
# l  P5 G( {' o4 V2 R* q  H7 p                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );. L7 ^5 A  L* \6 L- c
                return;
+ S  t( w1 T( V- A% z: q) u; X        }
3 E4 K# K; K# v. s* K
! E3 F9 r! K5 k        // Volume setup6 o+ f/ U4 N. [" P# \9 p) u
        //  0:Master& O$ V9 _5 @4 L8 m( h( p! w. t
        //  1:Rectangle 1
/ Q4 @& p( j3 L        //  2:Rectangle 2
1 \; d- h( W! h        //  3:Triangle
/ ]) Y3 ?: q1 b. w/ s        //  4:Noise& h: E0 @- ?$ _0 w% Y9 _
        //  5:DPCM9 l. @; h2 w5 ?. S9 T. L- y/ M/ r. H
        //  6:VRC6
! c  o  j1 Q& h- j        //  7:VRC7: Q3 G# ?1 h! P
        //  8:FDS2 l- ^$ F; ?' h2 C/ q8 v
        //  9:MMC55 z+ z. a$ ^: i" ~  v1 W; f/ ^6 e
        // 10:N106
, Q* ^, q. U! N+ D1 E) l5 f        // 11:FME7- z5 s) l$ P% |, Q8 E
        INT        vol[24];
: ~3 f1 ]; z% L- ?+ R        BOOL*        bMute = m_bMute;& j, K! g: G" [9 w/ c
        SHORT*        nVolume = Config.sound.nVolume;0 Z7 b1 Q7 R7 d7 |0 M0 d* ^! F# Q4 f

* A6 R. ]) D- q# ^! L! R        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
/ i- ^" |1 z7 {- G
8 }& R; B8 N. \" w        // Internal
" p: A; w) [6 L& F' }9 ?        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;6 v; q) B$ f9 u. D( ?7 W% W" h
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;9 m% G  n' ?- F4 o
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
4 I# e7 D+ M+ @" j& K( L1 v        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
; J, L( p* b- m3 D4 C6 c; I; h        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;- H. L# P3 ?% {+ r* I/ `
; j, n- A+ b6 T( h& V4 @
        // VRC6. L. H5 b& M% t6 X0 F9 ?! G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ |: @  v1 n7 B+ p# O& Z2 J, j        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( X$ \0 N: D; D  _* N; ^2 h! I
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 X7 \1 L1 D: t7 G* x+ r: B1 E3 K
- Y, M! ?) E$ N+ X5 b  ]
        // VRC7
9 P. |! ]/ o# G$ H* Q* x8 j4 z+ M        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 @8 C# M% H( }7 I' d+ ^
1 _5 y7 P7 g8 W$ z8 m7 w) n; f) Q
        // FDS
! |% q7 I- |& ]( [        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 x; t& b) ]  ^6 C% Y% O
/ }$ P/ P1 z/ c( p- I% S% W1 d$ G
        // MMC5
0 {; S8 i; Z. g$ u* H7 L5 I        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: v* G( O+ V8 Q; v4 \1 H
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ T9 L, @+ V& [4 {0 C- l
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 u/ I: O1 A0 R0 t+ k
4 ?/ y* p0 o2 i' r
        // N106! I. F5 t1 \. s
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: e) I# d  O8 R% N+ {8 F+ i        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; r' a; |2 w. {3 ^+ G        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ U+ S& E# V: w& }
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! N. M7 u4 O) g9 L& D4 O2 q
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& f2 }5 N+ c! e% k8 b5 R
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ h$ T) F9 B& h  B        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' w6 t4 G  P: ^0 j        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. N* Q/ E' s; k) W$ d& q7 |

% L# F# A0 l# B+ y3 o        // FME7" L4 u0 \" w0 X
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; c" Y% U& V  V1 M  m' f% {1 s! G
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 B- ^6 U9 s3 A
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 T4 U# @( I  ~2 `! N' J0 R
% h% X" X8 T# W; f* o//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 i! T  V4 o5 \- l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ X0 @% C5 [3 d( N# p  e) u
, }5 _7 l, [" |, o        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟* D( |" x8 D" x. ]: @- p7 `
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
1 F( [# e" H! C+ K                QueueFlush();
$ G/ B9 X; n+ Z- z' o7 ]8 X        }
5 c9 g* z& v& R6 v& E8 |& H) ]& i7 ^& q1 ~0 W1 m
        while( dwLength-- ) {
( I: \1 B! I7 q8 G; J                writetime = (DWORD)elapsed_time;
. l, {" M5 e" {1 ]
- A- _4 q3 k1 R1 _: \  {# ^                while( GetQueue( writetime, q ) ) {
- N4 {; z5 z, T                        WriteProcess( q.addr, q.data );
0 i* |$ @+ _5 z                }
& T  A1 M4 ~) m( [# Q  }/ P  \2 e$ J0 M/ R, }2 X! x* J; J2 h
                while( GetExQueue( writetime, q ) ) {
: G' l& H' I) O; [' J6 Y- k                        WriteExProcess( q.addr, q.data );6 W# P0 i# U& @, A
                }
) d8 J5 P* _8 {" Y' t
4 i: T7 I% @8 m/ d! ]5 b& s2 d! r                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME75 U! b8 A# `: m, W- [. I7 ^
                output = 0;
7 p2 }6 i+ G2 |8 Y                output += internal.Process( 0 )*vol[0];% H/ w+ w2 w5 j4 l/ y
                output += internal.Process( 1 )*vol[1];
8 `9 ^. E' x8 c1 T4 X, a2 f! r5 \                output += internal.Process( 2 )*vol[2];
( _# r0 n, x- b' l; z4 s& W% \                output += internal.Process( 3 )*vol[3];( T, r" u' B* E% n& ^' t
                output += internal.Process( 4 )*vol[4];% X9 Z6 @' E. }3 S! @. I
  Y1 y5 T! b9 f  r/ ]0 P7 [' D
                if( exsound_select & 0x01 ) {
* M! q% J( W( ]) m* U5 i5 N                        output += vrc6.Process( 0 )*vol[5];
3 i) ]! q- Y0 O                        output += vrc6.Process( 1 )*vol[6];
# A+ b$ I5 N1 ]. [                        output += vrc6.Process( 2 )*vol[7];$ H, a( @, P+ t
                }
! S* ?0 c% W% i                if( exsound_select & 0x02 ) {: I) b$ i3 j) X: ^! {9 L: O
                        output += vrc7.Process( 0 )*vol[8];
7 Z- D3 [5 W. ~* ?2 l5 b* w                }
9 i! C( x  i  _% }7 @6 ?* D                if( exsound_select & 0x04 ) {/ ~" K5 B' a+ }9 `& f: |" g" G; _. v0 X
                        output += fds.Process( 0 )*vol[9];
% g' |* z3 C0 ~' k9 I0 I                }' U' ~9 G# ?5 V  }" i, c- w
                if( exsound_select & 0x08 ) {
- t9 J' r  U5 d                        output += mmc5.Process( 0 )*vol[10];
+ x5 A  M& o7 P5 o1 s, H: s                        output += mmc5.Process( 1 )*vol[11];
' X6 F& z0 j; N6 K                        output += mmc5.Process( 2 )*vol[12];" P8 T6 X! i3 T4 ]
                }
' u3 x8 _% C* v, y- S2 O% e+ V, I' d0 W                if( exsound_select & 0x10 ) {8 I/ g9 N" E( e( O
                        output += n106.Process( 0 )*vol[13];
6 w& K4 B7 ]5 I, y# z: O# F                        output += n106.Process( 1 )*vol[14];/ I- c0 B' o, k. S/ p  e
                        output += n106.Process( 2 )*vol[15];
" {1 Q8 A' y2 e2 h6 l                        output += n106.Process( 3 )*vol[16];
/ u2 e8 v! m  D                        output += n106.Process( 4 )*vol[17];
+ B% q: W3 D/ j7 _                        output += n106.Process( 5 )*vol[18];2 Z$ d" ^; P' M! M
                        output += n106.Process( 6 )*vol[19];4 A; s) x) _3 t" D$ `; F
                        output += n106.Process( 7 )*vol[20];0 a! V& V0 ~  W0 X& x
                }
3 E# F' _+ x5 |& J                if( exsound_select & 0x20 ) {
3 `! F" K. X3 \: A                        fme7.Process( 3 );        // Envelope & Noise
0 s1 x: w  v0 ?* p8 F2 J                        output += fme7.Process( 0 )*vol[21];
2 H( }! c( N8 e* d  p' r                        output += fme7.Process( 1 )*vol[22];( D4 t+ W/ C% B1 ~
                        output += fme7.Process( 2 )*vol[23];- n& O- ~. D3 H, Y. f
                }
5 V: o+ N5 w: K6 \2 Z6 B0 z2 o: @7 S% `: x4 i
                output >>= 8;9 }4 t; |* O  {" U3 W6 S! U4 U

1 z, |9 J. y6 t# @( g, n                if( nFilterType == 1 ) {& E1 I" `+ F& a! L3 l
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 p  s! a0 d+ B5 g, U4 K                        output = (lowpass_filter[0]+output)/2;
( m% ~* ~/ N4 m( h' r# P                        lowpass_filter[0] = output;3 C2 W) o, T1 f" S6 d0 O4 D" |9 l
                } else if( nFilterType == 2 ) {
# a8 a( e  s* v( }                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
+ i+ G3 }* V! m  J                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
& L5 W" _. j9 q" s                        lowpass_filter[1] = lowpass_filter[0];0 w% p& Z7 W# t( {1 T3 \/ d2 q
                        lowpass_filter[0] = output;
/ t' P, @9 O  i! g8 ~# o; V                } else if( nFilterType == 3 ) {% @0 B- B' a7 t; R  e
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
! w: I5 |4 I- J' c2 T* s                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; H! b' N3 K2 Y  \                        lowpass_filter[2] = lowpass_filter[1];7 U$ f6 f; c' m* A2 Q- o; p1 a
                        lowpass_filter[1] = lowpass_filter[0];
7 `# Z2 G; w' ~- H                        lowpass_filter[0] = output;
# \1 d9 C% Q1 J6 a: j7 H                } else if( nFilterType == 4 ) {3 f1 v% _& }' D% {  Y% w
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 i  }2 u% O' E1 ^
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;; z+ U# r6 J6 L: o9 Z$ K  i
                        lowpass_filter[1] = lowpass_filter[0];
  c) V8 {/ |9 V8 c% K9 [) ]                        lowpass_filter[0] = output;6 G$ w: D1 W. ~3 m# z6 X: w" n8 t
                }
+ P, m5 k8 p8 o+ y: J9 P  Y( r" _  R- k( d
#if        0
0 o1 V! s; |1 ~. I' s                // DC惉暘偺僇僢僩
( O+ v  ?, n( A* ?                {9 h& \0 R" S7 ^+ H% U* o1 D
                static double ave = 0.0, max=0.0, min=0.0;
( C& t0 ~( N8 e: r                double delta;
2 A/ F# E" A, c$ u1 m) n& n                delta = (max-min)/32768.0;
$ \% r; x. b# J6 v                max -= delta;
  A1 Y1 n4 M- o                min += delta;$ A) c; j0 m; c+ d
                if( output > max ) max = output;9 Y5 N0 \6 N" D0 q! x
                if( output < min ) min = output;: T; {/ ]: ~: s1 Z, G
                ave -= ave/1024.0;4 [* u% ?, ]8 {0 n
                ave += (max+min)/2048.0;
5 o6 D) Y; S# n' }. H) b5 M                output -= (INT)ave;
$ ?$ J$ c  _  G# v# V; n                }
( Q% E1 y( S5 t$ V#endif
$ P# s/ `# s9 B" y/ p2 D: w2 t#if        1& y6 I7 O7 _; J  w% q
                // DC惉暘偺僇僢僩(HPF TEST)! a  t* W7 N+ N8 G$ }
                {
. K, x- b4 c, r& V* q. J4 R//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 S- F( y, ^0 T3 ~3 d# h                static        double        cutofftemp = (2.0*3.141592653579*40.0);5 ^+ a" _# X% G( P6 {
                double        cutoff = cutofftemp/(double)Config.sound.nRate;: q7 _8 Q8 ^3 M) Z
                static        double        tmp = 0.0;" W/ |, B+ k9 s, M
                double        in, out;
2 Q$ N! J3 G: E2 Z: b
! h7 g  W% [$ i# h                in = (double)output;
- Y4 O& T" A0 G- R- R; U                out = (in - tmp);; W+ u' f; R" O8 T
                tmp = tmp + cutoff * out;4 t3 L8 Z+ t" ^
6 e/ U" Z" J) d, k/ Y+ y9 ~2 d
                output = (INT)out;
$ V( H; V! k0 z+ P, r! m/ F                }; Q, V* ?9 m1 B2 y
#endif& {# I7 p; q# d6 U
#if        0
- h  D3 X6 e, O! C                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST); M. j4 ~1 e2 u: O
                {$ J. A2 V# o6 A$ P
                INT        diff = abs(output-last_data);
* b; n/ ?+ |6 F! w1 j, i                if( diff > 0x4000 ) {" l( I3 d5 a. h  E( \' L
                        output /= 4;
! c% I2 e8 {2 K) s8 E) P- c# I7 H                } else
; N/ a; s& c- ]' k) W                if( diff > 0x3000 ) {, y# f. B5 U6 `2 c. d
                        output /= 3;
) n8 x7 x- w, ^' g- y                } else
  K' V+ X, }7 o& i                if( diff > 0x2000 ) {
' }" _7 w+ G0 K1 H3 X2 I( c                        output /= 2;  ^- X" j& a0 `
                }7 _( a) b: L& b% n$ n4 `! }. Z
                last_data = output;
2 N! j& o/ w; c, K" o8 z! Q                }; k4 s4 N* t$ @/ F$ W3 _
#endif+ P' L- `1 x! D
                // Limit" v) n3 \) s2 y
                if( output > 0x7FFF ) {8 ~3 T8 U1 x9 P+ Z- A3 ~
                        output = 0x7FFF;
. q" x8 T: J* `+ f7 ~: j, |                } else if( output < -0x8000 ) {/ H! k1 ]) w) y7 I
                        output = -0x8000;
! O" B" a/ V+ O8 Q                }
1 M9 a. J% ?# _, x1 ]) b/ s
$ ^8 s0 u( P, u1 D                if( nBits != 8 ) {* k# Q3 y. c$ P3 ], A7 _9 g2 b
                        *(SHORT*)lpBuffer = (SHORT)output;6 _: b0 e' i2 P' _
                        lpBuffer += sizeof(SHORT);( s: h2 A: V  N8 b1 d* l) I7 p
                } else {8 f% Y% L" ~; {0 H- y
                        *lpBuffer++ = (output>>8)^0x80;$ r; q% X0 U4 d* }0 c8 k) R
                }
5 k$ _  G* O$ _- t! T7 b5 K; t" I* v0 C. M3 s
                if( nCcount < 0x0100 )
, j5 `3 r4 i, R! y2 J/ X* R# X                        pSoundBuf[nCcount++] = (SHORT)output;
* k- O1 @3 C2 z1 F! O7 m7 n6 N3 L' E. l6 ^% @: }- {6 F% T
//                elapsedtime += cycle_rate;5 q& ^1 t8 p6 o# x3 i& j
                elapsed_time += cycle_rate;+ K- x# I7 U0 |7 }  e1 ^
        }
! t" @  N# Z- h( m- X" F" i! l' ?
0 e/ n0 Y8 t) w#if        1$ D/ D% U9 t/ ?- L1 ~
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
" ?1 ^, ~/ v& T! q& x3 w2 r                elapsed_time = nes->cpu->GetTotalCycles();& H! F4 Y5 P& e( B9 `) l
        }
# u3 u: K% a- \9 \* x; r        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ F0 E8 i) I+ v6 T1 V( i( g7 W/ V
                elapsed_time = nes->cpu->GetTotalCycles();: R4 z4 W1 f/ D2 g5 ]0 O" Q$ p* Q
        }
: x; |" _1 d* s#else# z1 R- R4 k& Y# o0 s' L5 {; V
        elapsed_time = nes->cpu->GetTotalCycles();8 P7 q& ?" c! F
#endif
% p" a& B- J8 u+ R}: z1 R5 l* i9 @% s/ X* @* Y

& i7 |$ q0 U7 y3 w# M. Z2 O// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)4 |. p1 X, ~( f7 H9 v
INT        APU::GetChannelFrequency( INT no )
2 ~; M* B( g: g7 a{
. s7 F! O( i! \" L0 [        if( !m_bMute[0] )2 p3 n" J0 Q- ?) G
                return        0;
: t1 w  E) `3 c" n; [
6 {/ w8 x& V; z' l9 q. V        // Internal( b1 Q6 ^9 k* O  n. y; Q6 E9 m
        if( no < 5 ) {
& d* K7 E0 H8 Y3 \" F' L                return        m_bMute[no+1]?internal.GetFreq( no ):0;6 y# a& ?7 I) X( F4 ]" p  _  l" n
        }
( T- r" @; f# V& D- t( I( N        // VRC6
# b) J% J' e# v' c0 z) `        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ O3 r+ O# |( B  o1 m# }: H                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
; M; H7 e8 k+ a6 p+ |! V9 S        }
* a8 u. d! Z) K. O* J        // FDS
' W' H& h+ u4 {2 u: B        if( (exsound_select & 0x04) && no == 0x300 ) {
4 \6 I9 u  R0 r6 L$ y' {" D                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 m  a6 V( a) a9 H2 v8 G
        }6 g! R6 h' J: D' _# d- \$ a. m
        // MMC5) g, ?( s; B- B4 O
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {3 G+ L# T9 o( b0 [4 K3 F/ h8 G
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
5 ~; @$ B4 w8 F6 I3 Y        }
* t7 Q, M; B9 U; z" W  b        // N1068 Z  Z% n+ x% y0 p% |
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
& G# ?8 c* j2 w( L2 S                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* w& u' m. S* V5 V% n        }
- p$ D. B5 q0 |        // FME77 F* P7 y+ j  ^) k4 B& M- @6 b
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
4 [2 {: V; L7 m# g) m" E- X                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;/ C& n  Q/ ?8 X1 S
        }% \% j* P/ Z& Y4 S' `: s. c
        // VRC7
- T  X; m. }* Z+ g  N& D        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 c4 y. B. [) V. ^# W: y" P" N                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
" P$ x* C5 v8 W" Z& q, Y: o        }
; @2 @5 |& D3 ~' [# q        return        0;
7 O, `$ X9 T6 l% H+ Y  P8 f}9 x, ?& e" Z# P

+ B1 Q% [( Q: L' Q! {6 E// State Save/Load
) w! Y1 J' w3 \! s- F' l; _void        APU::SaveState( LPBYTE p )
, ^* D* i" t; o4 ?{
* L/ Z4 n, X$ X- `* `8 b1 v#ifdef        _DEBUG0 `) ?5 }* \8 D$ ~; ]# V# E5 q( N* z
LPBYTE        pold = p;/ o7 a  c1 H+ y
#endif
0 ^" L. f/ L' \) |* g+ b
% K" k' B4 i9 D* Y/ X7 V; l        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, |# T- v7 c. P# E  D
        QueueFlush();6 P$ z) O5 A) r+ q& g7 x2 m# V

$ z! m4 M( D* S) N( r        internal.SaveState( p );
0 |: }6 W( M% Q        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 S* q2 c8 I. }
4 \# c0 B. Q' ]; U7 Q2 U3 A, ~. E        // VRC6. l. U8 Z0 t9 ~. s
        if( exsound_select & 0x01 ) {6 S: ^: G% l2 m3 b  v6 W# Z
                vrc6.SaveState( p );
7 n& u1 d. u5 Y8 z; t& w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 v: c" ^& Z7 H. W! Y
        }+ V7 X- ^" y/ G! E4 X' {
        // VRC7 (not support)' {% t/ J( R; _  ~- S/ M6 m0 l
        if( exsound_select & 0x02 ) {
# f" l$ J8 B+ ^6 l7 ?, T# r5 @                vrc7.SaveState( p );
+ e) a/ ~, J* e7 B9 ~3 i                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( K7 N, z  \# c
        }0 U  F, h, x- i4 f4 g5 A4 u
        // FDS
  ~0 Y8 ]3 X  C1 f/ C        if( exsound_select & 0x04 ) {
# T# V' @& [0 g* Q. ~* u                fds.SaveState( p );
8 {, u- t0 H  U' I, |* x  r! B' Z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* V8 B! C1 `5 l( K8 V
        }$ @) F4 h; p& D" m. m
        // MMC5
' Y2 P6 W" b) n0 h        if( exsound_select & 0x08 ) {
' c/ p4 t3 ?. s2 k8 |- _                mmc5.SaveState( p );
8 w6 i2 A' I( g; w( M$ f                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. B  y8 F. e9 ~; P" c9 z- j        }
2 ^, k9 r3 x6 p2 [2 h! {        // N1064 g+ d8 Q7 {% y$ G8 F& h( R
        if( exsound_select & 0x10 ) {
2 d8 `# q# R- p4 x2 R5 r- @( \                n106.SaveState( p );
! y5 m1 c2 w9 O5 e                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( \! E0 t- i& {! A* W  x! y% G3 c        }
  Q  L9 B% |5 A5 k1 K        // FME7
, t6 L: M0 w0 b" @        if( exsound_select & 0x20 ) {
  z' @. l/ x! |' ]+ h                fme7.SaveState( p );, A9 @) \1 U8 c8 i: ]" O
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) |' m, F$ V5 s" r1 Z- X! @# n8 R        }
: ~- [8 U$ z9 f$ n2 ?. }2 ?0 j* K( U# B
#ifdef        _DEBUG
# r5 s# {8 v+ UDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );1 B/ |7 o  @* I' A- m' L: ?
#endif
+ L' O0 |# D1 a/ H5 H0 D$ C! D}, K8 A! z& w$ W# {
' Z8 x6 j( _/ R& N3 j
void        APU::LoadState( LPBYTE p )0 ]% }2 [% R8 H
{
# Y7 D& ^  W; t4 j2 v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡; h3 t7 f* O6 r6 c
        QueueClear();' ?, P/ f' a- f

' ]- g& G. V# \7 j/ A6 c        internal.LoadState( p );/ \: C7 M8 i! j
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# t1 ^* E; o- G3 e- V! h% @. E: ^9 P* v4 X3 R, Y
        // VRC6
: c7 L& f; K  K2 L; `1 A        if( exsound_select & 0x01 ) {3 N! M, Q% {! v' X9 T
                vrc6.LoadState( p );
  y  }% D& l" E. C7 h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ j; s0 I; E4 S8 b3 L- p        }
5 W4 i* M4 G7 @* c! o3 h        // VRC7 (not support)
) B9 ?5 h- L' K3 H        if( exsound_select & 0x02 ) {
3 W+ b2 J' l6 t# M4 e% ~# w6 `                vrc7.LoadState( p );4 d, A* P7 Q5 W+ c: z& D2 N8 L
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 Y; t& `( b4 s4 x        }
8 ~0 a0 U8 G& l, [7 T  b% D" j        // FDS* [; K. F0 D! N/ n$ c" \
        if( exsound_select & 0x04 ) {
; l$ W, Z4 S0 Q: S; X                fds.LoadState( p );
) q0 c( b" B- V; L+ h3 {: |                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  m5 z0 w0 ?2 L, K! _5 L" x        }2 K+ ]; R3 ~  O+ M
        // MMC5' [6 F* H+ N3 ~. m, z! K
        if( exsound_select & 0x08 ) {
6 N9 ]0 M% p' R+ Z- U( c% `( m/ M! Z                mmc5.LoadState( p );
5 K! b& |$ O6 u( y8 ?5 I0 n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
" \0 i0 j" Y2 ?. N( t( f3 D        }; o8 \( E* H4 T3 [8 q& }/ e3 j0 a
        // N106) @1 d- A4 ]' y4 ^$ a6 R1 `# ^* i% I
        if( exsound_select & 0x10 ) {
- P7 H8 n- z' p8 S: ~9 u9 s                n106.LoadState( p );7 f4 A7 O1 U% Z- v& m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding3 z  q8 C: @6 d2 A9 Q
        }% ?. Q) o9 |7 A9 R2 u
        // FME7
6 ^; X7 c4 L1 F        if( exsound_select & 0x20 ) {
- H5 S2 {; `: B7 r: @! k5 O                fme7.LoadState( p );
' ^* R: ^$ R5 O" ~) a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: R# v' M, K+ |5 d+ r. z3 Q
        }
: R- F3 b, ^0 G3 B2 s: z; e' n}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
: t& a& s$ p/ P% m7 _0 N3 h可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 ~; \$ t$ w; U+ j+ t2 }" @" u- f感激不尽~~

  O2 ?5 ^; g+ `4 z! V6 |5 J恩 我對模擬器不是很有研究,- O; U4 h1 f- N4 {: s
雖然要了解源碼內容,可能不是很困難,
1 w' N1 N. F2 X, Q不過還是要花時間,個人目前蠻忙碌的。+ ?+ x* P8 e& I8 a- W$ g: a

9 p/ @5 ]$ v. G2 o1 {給你一個朋友的MSN,你可以跟他討論看看,
! k% P4 G& m4 l" c" `3 m他本身是程式設計師,也對FC模擬器很有興趣。  c1 R' e" |) B6 V

/ g3 c4 k# r% z" @% ~/ hMSN我就PM到你的信箱了。5 F2 N% E+ @; m, V& X
: n; A6 I% u/ T* K' 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 发表 5 R8 f, y: O* d2 M
呵…… 谢过团长大人~~

& ^% N( N/ L# @' \' l2 E8 p, Z9 M) P6 E$ t( M# E
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ) H0 w0 m; L" ~+ V
团长的朋友都是神,那团长就是神的boss。
: ?5 j  r) N: C, l9 {4 v, ^' ~' e+ o
哈 不敢當,我只是個平凡人,8 I+ B+ g$ v+ ^
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# C. S8 S) _: VZYH) i# |: [/ o( }% j) ^% k
QQ:414734306+ i7 l: n, I' a5 I7 x
Mail:zyh-01@126.com1 a2 V/ B3 e) f% I% ^6 A8 |+ u+ |
* |# n. j- H# w; O. g0 t0 R/ T
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 M; x- S9 p- O3 e. a6 ?$ E+ j( B再次对团长大人和悠悠哥的无私帮助表示感谢~~

) M3 j+ a, Y& D, V* ]不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-2 14:03 , Processed in 1.123047 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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