EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?. n" x1 o# f* p# {* ?2 \9 k- I0 z
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! ^+ F1 D( `3 L5 h8 t3 F2 x8 H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: v8 {1 N: ~4 {9 H6 S! p/ x6 N% l这里有相应的模拟器源码,就当送给大侠了~~1 i7 q* P. h: B* C2 O; U6 y: ?
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
' Z4 d1 |" i6 h, B  O能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。4 `6 c" ]* t; [! V! k' w
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( O, T' V+ O: c8 g# w1 O' m1 j
这里有相应的模拟器源码,就当送给大侠 ...

# F( j* G" C6 j) l$ l0 W聲音部分(Audoi Process Unit = APU):7 n7 T/ q) I6 I% I$ X- ?. R
.\NES\APU.cpp
5 ?1 L, x" Q- Q$ V3 B2 z6 U.\NES\APU.h. E  i8 \4 T& J- v8 \4 T2 X
7 l+ }2 M0 A" |" O; `2 }3 e

. \- |/ f1 a' }$ X# z影像處理部份(Picture Processing Unit = PPU):
+ i9 u7 N( [; O% @+ N# o.\NES\PPU.cpp' A* d% [5 ?- y/ \' z
.\NES\PPU.h& l9 S, u# N5 K. x$ C. y
. e! @! Q+ n7 I. O6 d5 k
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; m1 o6 F5 L& X, l
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; }2 J. y$ E( `, `//////////////////////////////////////////////////////////////////////////; Q+ Q1 `4 L; e5 c4 r& a
//                                                                      //
7 I: H" c4 a; g; n: m' ^2 h3 }//      NES APU core                                                    //7 i' M2 _* L- N! k, C2 U0 l* w
//                                                           Norix      //
% ?& ~" [/ O9 F% ^+ ]+ X3 P//                                               written     2002/06/27 //
3 P4 \7 `8 G( O$ O! p9 l//                                               last modify ----/--/-- //
5 _' c% G) ]/ X. Z  c//////////////////////////////////////////////////////////////////////////( z' }7 F; P( R. ?
#include "DebugOut.h"
- m# q0 E  ^/ s6 b#include "App.h"
3 z9 v; C1 C: A9 S% X#include "Config.h"* Y3 \( }: r9 c. x. e

4 I/ H* B0 N! w2 j+ h4 `- f; A#include "nes.h"7 H; ~: Q0 d2 v
#include "mmu.h"
! K$ S/ V! ]. K; V$ @" l8 N, q  `6 p#include "cpu.h"' j" v& I# v% M
#include "ppu.h"
. M( G- j7 N$ x0 \9 D1 |5 V#include "rom.h"
  R% S$ K. i& i& q#include "apu.h"
5 O% P7 w% }! R! z! y
) G, D. V) ]# j: H" z7 i) s5 D// Volume adjust
% G0 t, Y+ T( p( l( ]- f// Internal sounds
7 M4 I: \$ F  e* I- x0 s#define        RECTANGLE_VOL        (0x0F0)
6 C& w1 T7 D) x2 c1 }/ v#define        TRIANGLE_VOL        (0x130)8 @. H4 S8 N- s  x. B
#define        NOISE_VOL        (0x0C0)
' V6 b# q5 y) e. c4 l  v, Q2 i#define        DPCM_VOL        (0x0F0)
7 }0 D2 s2 C3 T. [, N* X/ k// Extra sounds
7 }3 v/ f. [+ }0 m/ C% O0 N2 f#define        VRC6_VOL        (0x0F0)
+ y: b' B8 ~; `& p3 O#define        VRC7_VOL        (0x130)2 z+ k3 z8 L" y. c1 G5 i
#define        FDS_VOL                (0x0F0)" F! o! A% v0 v3 }9 A1 z0 w* ~
#define        MMC5_VOL        (0x0F0)) h/ `/ B- \2 j* f# H0 q3 f9 I
#define        N106_VOL        (0x088)
) r. F0 N# f+ t0 |% T#define        FME7_VOL        (0x130)
" ?$ q7 A9 p4 d' w1 H3 g2 w) W, `) @6 w2 D% X
APU::APU( NES* parent )  B) H3 P, M! P% r% t/ D
{8 c& @5 l; R6 ~2 ?( K, H- z
        exsound_select = 0;9 ~( A7 E: p# c) n0 F

3 ?" b5 P8 ~* X        nes = parent;
0 ^# g0 U6 c  b: B        internal.SetParent( parent );
1 \2 \* E% V& O/ W, [$ K9 S9 C0 X
3 c8 a, H- v' \0 O' u0 y& m        last_data = last_diff = 0;+ l% a+ ^( ?" s$ `  {# t& K

* P7 P$ l: ^- t/ A" T4 f  u        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
2 j! q3 D/ v: @' ^
( l- {! P+ p7 F( r( L, V( B0 f        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
! p% x$ N5 i5 d2 R0 c0 ~% @# B        ZEROMEMORY( &queue, sizeof(queue) );
& z8 a3 R# `1 ]& r  q        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 B3 k& p; E8 S2 A) u9 {
  M3 `: E4 F% G, Q# [$ p
        for( INT i = 0; i < 16; i++ ) {
8 [- h( G: ~9 D' ?# ]. J! {+ `/ T                m_bMute = TRUE;+ h! ~+ r, \. M  ^1 n+ Z
        }
) {7 ~% M  \& b+ z}! {3 V+ {& d6 J- M. Z

# ^" ~0 `: T, @$ MAPU::~APU()0 a0 S) x. m4 S' X; }
{
, Z6 Y0 s8 P9 W" x( e$ d}
' c; O; r$ w7 m2 e
9 G0 j6 k5 ?8 E, Q+ ]void        APU::SetQueue( INT writetime, WORD addr, BYTE data )$ z0 c2 I9 h6 }6 L- q% M8 d! e
{& b- n  s$ H* ?4 n
        queue.data[queue.wrptr].time = writetime;
- ^' G' u2 C& ^4 i. m& b        queue.data[queue.wrptr].addr = addr;
7 M) {' I  H' y* S        queue.data[queue.wrptr].data = data;
; G! q- l1 G/ @$ B+ S3 m        queue.wrptr++;" m7 ?- ^4 [7 I1 J
        queue.wrptr&=QUEUE_LENGTH-1;
/ o+ @* [1 A- y; ^        if( queue.wrptr == queue.rdptr ) {- H# c: S" K0 [
                DEBUGOUT( "queue overflow.\n" );
! G1 Y& C6 w' K% Q' k        }+ G1 A2 p, ^6 U: j( t( F
}" M) o" e! H& n4 p
! r; |7 b; ?- {, k, B# m
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
" @% S& Q% L2 z0 F/ t5 M{
# r: K7 h6 {7 }( b7 O! s$ D        if( queue.wrptr == queue.rdptr ) {
3 a9 m& G8 N' k1 I1 f5 L9 E                return        FALSE;/ X) v. [) ^  w- B
        }2 g* e# J/ y% S6 b
        if( queue.data[queue.rdptr].time <= writetime ) {
% }/ J: k! t0 U% q6 G- T) f, }                ret = queue.data[queue.rdptr];1 S! `) n5 p, O- D
                queue.rdptr++;7 V) ]" m7 }; h* U7 }3 Z% s; O$ z
                queue.rdptr&=QUEUE_LENGTH-1;
: m' h* [4 f5 x& V2 _                return        TRUE;9 r1 g+ w5 m5 c1 U7 n& \; X5 }
        }
* V# z$ t/ c& e/ ?5 {9 m        return        FALSE;
( r4 T- X! p( V- L$ J/ h& C; U}, ~' _$ a- q% o, q

! l7 Y1 w& s' _( e+ E9 U3 pvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ H  K' G5 {* \  p- v{
% {6 ^! R6 K6 I- Z        exqueue.data[exqueue.wrptr].time = writetime;2 E9 K6 q4 c" X: G# V1 O9 e
        exqueue.data[exqueue.wrptr].addr = addr;8 z2 `) ~4 a% H( c8 u$ p) L9 A
        exqueue.data[exqueue.wrptr].data = data;9 H$ x  b+ `* T' _; g
        exqueue.wrptr++;
! \4 ~5 a0 j& C        exqueue.wrptr&=QUEUE_LENGTH-1;* C4 A: X' [0 F9 h! J
        if( exqueue.wrptr == exqueue.rdptr ) {+ h& Z. e7 u3 D4 G4 q! q0 A' C# d( Y
                DEBUGOUT( "exqueue overflow.\n" );/ @7 W# g( Z: @
        }/ ?# M8 M: \2 X" b# R( \
}* `; l& x% F  q2 d1 l. S

, u% w3 a- E9 Z8 l' tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
4 w' S6 L3 V1 V* F+ q( q& }: {{, f8 k: T+ y5 G- _# g+ z
        if( exqueue.wrptr == exqueue.rdptr ) {
1 R1 l, k7 c. ]$ \2 v- g                return        FALSE;
1 R1 Z+ c) i6 k  v1 t5 I4 n/ L        }
& {7 C- P' o8 J* Y$ Y        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- |9 N) Z4 r+ b$ k2 {9 [/ Z
                ret = exqueue.data[exqueue.rdptr];
9 M. X2 A. T1 U( l* {: E                exqueue.rdptr++;: l4 s0 u0 `) g$ W) Q/ W
                exqueue.rdptr&=QUEUE_LENGTH-1;
* d, p. P$ i! A/ E1 c                return        TRUE;+ Z7 z, G; }( _: \# C  }
        }
0 O* J2 t9 k" X* e        return        FALSE;/ x+ X5 g0 v6 H" E
}
6 {# i) p1 M0 ~! O
4 K/ v+ ^: X) @5 u3 I4 _5 m1 Jvoid        APU::QueueClear()4 R0 Z4 I  Z$ v0 |
{
5 O, j2 \9 b# i        ZEROMEMORY( &queue, sizeof(queue) );
/ C) a. m; U5 m4 C' Q- J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 l0 H  b  H1 E' o4 W}
0 {5 N: g6 e% @2 {) V' Y
1 s: y% i. a' W  j/ ^+ q( Evoid        APU::QueueFlush()
! F3 m% I7 F0 T0 X{9 e- E+ h( j6 D
        while( queue.wrptr != queue.rdptr ) {
& R$ j# A1 [$ s8 Q/ z0 g+ D9 P                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ b& |7 m, c, E9 a2 i4 N7 E. U  C
                queue.rdptr++;4 [$ Z8 @2 v! O( h1 B( R; ?, r7 x, b; i
                queue.rdptr&=QUEUE_LENGTH-1;
1 \* ?- |# F( |9 w- B; u        }
$ b7 i8 _$ Z* ^: A: N) Z
* v1 M5 |8 ~$ q) q6 A        while( exqueue.wrptr != exqueue.rdptr ) {; ], h/ R& R# t3 j7 c8 w
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 U: x, C3 ]3 \/ d) `                exqueue.rdptr++;. o/ V+ E7 |' n* k
                exqueue.rdptr&=QUEUE_LENGTH-1;
* [0 i% u* t( n% P        }" R! G, g  r  t$ |2 A* h
}
2 @' e( j! l8 J# E& |
# Q" i5 D) q  f" }$ t, c& Evoid        APU::SoundSetup()8 i- T0 C: Y! T
{4 O6 F& X2 {  t( @$ E
        FLOAT        fClock = nes->nescfg->CpuClock;7 I* n1 E* @0 l+ {9 C
        INT        nRate = (INT)Config.sound.nRate;
$ ~) b5 ]% K+ w) N" j& h        internal.Setup( fClock, nRate );4 \, ~- [; S$ c$ a) g
        vrc6.Setup( fClock, nRate );
8 s1 P& @, h" u3 X, [  M' c        vrc7.Setup( fClock, nRate );+ @' \: S" O& X
        mmc5.Setup( fClock, nRate );
$ Q0 m" k6 g; M* B* x" ?        fds.Setup ( fClock, nRate );. H2 k! I5 a9 s& h& S* |
        n106.Setup( fClock, nRate );9 e4 Z+ n9 @/ w: y- s$ @3 }; d
        fme7.Setup( fClock, nRate );# k; K; o2 p# ~9 f9 ?  U
}& ~  k; L5 g. Q4 Y3 Y# o% o1 a

8 Z  }5 `1 `8 L) l1 y  X( ~void        APU::Reset()
% Q% u: c6 F& E8 T3 [3 F7 b{
7 u" i8 S5 K1 Z& Q) f        ZEROMEMORY( &queue, sizeof(queue) );
  f. D$ z- z- ]+ a        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  v7 R* x' I: I% z! |  w( S. f; z" b3 q, @! C4 a, z1 A4 V
        elapsed_time = 0;2 m7 E3 M6 _4 x0 W: q! o

+ g+ O5 j  S, l7 x( Y4 F        FLOAT        fClock = nes->nescfg->CpuClock;) m1 x: o4 A7 O# r1 M: [
        INT        nRate = (INT)Config.sound.nRate;9 P( g  C9 a$ q
        internal.Reset( fClock, nRate );- S+ m1 B; G- W9 n7 f
        vrc6.Reset( fClock, nRate );
# E( y  w- Y# Z; s. G        vrc7.Reset( fClock, nRate );
4 ?% U- E# S* D- A        mmc5.Reset( fClock, nRate );
( ]4 w7 C/ X' n  {7 Q$ z3 q        fds.Reset ( fClock, nRate );
' W  B2 L$ L% P* D" K+ V        n106.Reset( fClock, nRate );+ C! c" J2 n- B% N8 Y
        fme7.Reset( fClock, nRate );
" A# y0 `2 G1 h. Q" C; h! c, ?! a7 l
) M$ P/ v1 u$ \3 J, i+ N/ s5 e9 p        SoundSetup();7 q; n$ a, O" K8 s5 ]3 @0 R6 K3 t
}
6 B, d3 {1 e  c
3 d5 F: ^4 @0 k9 I: r9 c: Vvoid        APU::SelectExSound( BYTE data )9 S' @- q8 x6 b
{# ^# a! ~2 c! O2 J
        exsound_select = data;: J/ m3 }) A; p: c( |/ T( Z" w; {; K" H
}
3 r9 o! R  n$ F7 d4 J* W. N1 N; E3 [# G
BYTE        APU::Read( WORD addr )+ O' O0 ?8 i" W) c$ L4 \9 ?
{
& W1 J3 ?) F6 x+ m8 Q; U        return        internal.SyncRead( addr );
& n$ Z9 q2 T2 ?1 L5 p. q}
: F; Y/ ~% B% \8 [
4 X+ |- V* x$ L* w0 A0 Evoid        APU::Write( WORD addr, BYTE data )
" F6 [3 U! y: ~; a" }3 X; G{
+ {7 g3 q5 b' q  X) P! p2 h        // $4018偼VirtuaNES屌桳億乕僩5 F. i/ f6 m5 d% _
        if( addr >= 0x4000 && addr <= 0x401F ) {
& P; P1 f6 N/ j                internal.SyncWrite( addr, data );! ?8 C0 D/ ~% l9 u5 a& G
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );# k7 F& ]8 m0 g: s
        }2 O! {# U; V& a* _
}
" i% L( ^4 m  p1 ]2 i3 `# v7 i1 z6 ^) _) o- o
BYTE        APU::ExRead( WORD addr )
' }( c7 M- _1 n& @0 u{2 }, X) f9 L' ~$ @/ l
BYTE        data = 0;
0 \0 p5 C. `* W- I! I9 }- V+ U3 u
        if( exsound_select & 0x10 ) {
9 B$ h! ~8 X# N7 R  q2 R5 x! v8 h                if( addr == 0x4800 ) {, `9 }0 [8 N! z2 J
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, S$ [0 f7 s/ e: l) |5 O$ ]! ]                }& c- G) |  i  b6 C, U* u
        }
, t( A6 b, }' u$ q0 u        if( exsound_select & 0x04 ) {, ], `( Z# b0 |+ n0 f) a* p: y3 D2 [: @
                if( addr >= 0x4040 && addr < 0x4100 ) {
; l/ y+ q, M# _3 u" N- R                        data = fds.SyncRead( addr );2 t" A- V) q9 A- [  P
                }- j( }& |$ ?: Y4 }3 s& K
        }
+ E! B% s1 m( @' l: h- O. g        if( exsound_select & 0x08 ) {
# G, o  {' w7 ?: J9 k( v                if( addr >= 0x5000 && addr <= 0x5015 ) {2 W8 R$ F0 v9 R, {* ], R
                        data = mmc5.SyncRead( addr );4 ^$ ^- g  M" \& t" A
                }% a5 Q# Y" H+ {+ K
        }
# y1 n: Y$ r5 Y- x! A7 [9 j* \) n. g2 J, U3 \3 h' g2 F
        return        data;
( i5 P8 ^" g' E$ h( B}) P8 L9 d) Z. _3 A3 P. r: C
: Z4 `, D9 }; v$ B
void        APU::ExWrite( WORD addr, BYTE data )/ T- w+ N/ l! G- b4 j
{! D; ^+ T- \7 P& D$ N/ B/ q
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
% E/ I% B7 I" E
4 n) S% q9 A& I, m5 V        if( exsound_select & 0x04 ) {
) R& M) h# \! C- d* Z0 o                if( addr >= 0x4040 && addr < 0x4100 ) {( _3 [" H. S( e6 w
                        fds.SyncWrite( addr, data );9 \7 o2 ~9 M- R' B0 T! u
                }0 ~- B' K4 f- e0 S+ y6 L
        }
: ]7 \2 b7 f8 [! j9 b  ?
+ a( C6 D0 ]$ |1 G  R! j7 I        if( exsound_select & 0x08 ) {2 F' m6 D/ ~/ S9 e& U2 O- i
                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 @1 y4 [0 T$ h; X1 h! r                        mmc5.SyncWrite( addr, data );' E3 e' \0 v& [# k# x' J
                }
5 B% d5 |5 m/ L+ \, _        }) S* \2 G! B* a5 c
}
1 j1 }* B7 o6 U& n: H4 W# l7 D# p" y0 F2 {% S: g
void        APU::Sync()
% [$ m* J/ O) d1 _{
+ H+ H$ V$ v' s! [: V}
' V8 R; J: ^! C3 C9 E: u
0 S* K, U0 j6 P% rvoid        APU::SyncDPCM( INT cycles )
: D- G' T" m' X9 i* }. E$ u{% c. _7 A2 `' u9 r' O2 \; c* T' i$ S
        internal.Sync( cycles );+ n9 d" n6 w3 Z
) g; L5 H" L9 A
        if( exsound_select & 0x04 ) {
6 |# ~$ E: i2 ?1 z, A' m                fds.Sync( cycles );6 I! `7 b: J. K+ y
        }# g$ M8 m' n  D) ?5 g" B5 z
        if( exsound_select & 0x08 ) {
' _8 |. w( s$ K1 b                mmc5.Sync( cycles );7 c( Q; \0 B% G
        }4 y: ~  D6 n4 R" u; `# r" G1 I
}4 m; {5 B( J0 e8 e3 E. i
# x) n/ q0 y" y
void        APU::WriteProcess( WORD addr, BYTE data )/ y0 V7 D% K7 G5 @' a; d
{* K4 i0 t" \; l1 l: n; F
        // $4018偼VirtuaNES屌桳億乕僩( @2 p6 X% Y: k8 y
        if( addr >= 0x4000 && addr <= 0x401F ) {5 V4 O1 D7 h+ N/ y
                internal.Write( addr, data );' [. n  z" P) \8 w$ V2 t! k
        }
. [: d+ h6 `6 ^5 r) N}3 M7 H, v! G+ ^& t' q7 G
9 }3 @- P' c: O: w/ Z
void        APU::WriteExProcess( WORD addr, BYTE data )& V5 M4 O' C- h9 h7 u4 a
{
% w, U' d+ q, _4 A4 l/ q        if( exsound_select & 0x01 ) {( S9 N* T* G4 \# w& b4 \
                vrc6.Write( addr, data );% P' K4 X/ F, Z( J
        }3 p, {' \& F& s  [4 A' F9 g
        if( exsound_select & 0x02 ) {
9 h" g8 H& V+ t6 m5 p1 H  W/ \                vrc7.Write( addr, data );7 y) U+ S- U0 S: A2 p8 r! u
        }& ~6 I" u! g# T& [0 D' Y
        if( exsound_select & 0x04 ) {7 F# J7 r+ f5 z  g/ P; ^# p
                fds.Write( addr, data );6 \! w' p8 a& B/ n
        }
: V8 B4 ]1 Y- ]) S5 {" t# h        if( exsound_select & 0x08 ) {
, ~7 |5 l7 E2 X. a# G                mmc5.Write( addr, data );2 \: e1 c9 S( \; L5 h+ U& C
        }
* ]5 m6 _3 }7 w: T" I. P        if( exsound_select & 0x10 ) {
* B( f! X  c7 i                if( addr == 0x0000 ) {8 ?. `# x4 o$ J: O* U8 Q: s4 G& V4 X
                        BYTE        dummy = n106.Read( addr );" o& T2 B5 D8 z0 v) w4 r
                } else {$ n' ]8 G5 p0 a$ \
                        n106.Write( addr, data );
5 I, U" F; Y& F. N3 m4 ]                }
+ i' M$ _# o4 A9 s7 \  Y' \- v" {        }
( ]5 i) ^; V. ~5 q7 l        if( exsound_select & 0x20 ) {6 ^' a/ Y+ B; M7 Y, U  w
                fme7.Write( addr, data );
$ ~- O1 \: t3 n0 a  Z9 N        }
( }! e- `4 b3 ?" c}, _+ Y' g$ U1 @0 D4 a- j& N1 |

% l9 T% a$ q- K( i' n6 ivoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ U7 E6 _( |+ H  D{
  e( b; ]+ j% ?INT        nBits = Config.sound.nBits;
; U: d% \5 q4 A) n; z7 J7 ODWORD        dwLength = dwSize / (nBits/8);
; U5 N; |3 v+ DINT        output;
" S, a9 p3 ?. y3 [$ s6 K$ LQUEUEDATA q;. X1 w, r( z: G
DWORD        writetime;$ o+ \# F: u" u/ K4 [

8 B& P% x8 _8 z" d3 rLPSHORT        pSoundBuf = m_SoundBuffer;$ d6 m) N. C( |7 f; e1 H" Z
INT        nCcount = 0;
3 Z; B  [9 ?  v' L+ g8 i2 ]# n: v% z1 I% _% A0 ?
INT        nFilterType = Config.sound.nFilterType;
: ?2 c) @8 S9 D6 q% a: D# a
7 v3 h4 r& Z: Q2 l& z9 ^& d' m5 @/ j        if( !Config.sound.bEnable ) {/ r+ L4 ]1 ?  K9 p
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
- C' [7 C4 s, x5 C                return;
0 C* u' C2 _- h0 Q- }+ z$ q4 B, ]        }5 v# y" L3 C  z) e. ^
% m+ E, I5 t6 F. u
        // Volume setup
6 G4 d) e3 G4 T+ n6 [4 Q/ ]/ T        //  0:Master
, \+ _, n- @% K) r3 m        //  1:Rectangle 1
0 u+ z6 m7 l4 @. {, D3 h        //  2:Rectangle 2
9 a, x" r' g7 x$ [        //  3:Triangle
: L* u7 I/ Y$ _1 j; j        //  4:Noise' r0 J( o( T( ^6 U: T/ m
        //  5:DPCM9 G. E7 Z& \4 a2 u6 X
        //  6:VRC61 z0 ]) Y* Y. |0 O, H2 K/ m- ^
        //  7:VRC7
6 S3 x# y0 x4 Z5 h1 ]        //  8:FDS
% W$ z' C) N& _' f  i1 n; Q, W% m        //  9:MMC50 G+ X( v3 `2 I1 o- F9 i3 i
        // 10:N106! U, I# {5 N9 c5 \
        // 11:FME7
9 l( A/ ~8 {6 s6 J        INT        vol[24];
' J( c7 p8 o% E3 c        BOOL*        bMute = m_bMute;
, U% d- E! D( W        SHORT*        nVolume = Config.sound.nVolume;4 p6 k6 Z: @& @. b% C
6 [1 b2 C5 @  z2 d9 p, |
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;, {) G& e( E2 ~% ~  |2 I
4 N  _$ t( |$ T; Y
        // Internal+ ]) J" l+ `5 K# d+ z
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
. i$ f$ W% |  \* i- |- ^# u        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
2 T% c2 f+ M& |9 \        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
$ x6 e6 p, |, X  y, t/ I8 p9 O        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;! K/ M& j/ Z0 z) W
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ c+ T- C2 ~3 b! Y; g5 m

' A$ U$ c" \& Z' |: z, r$ u        // VRC62 }7 x; g) d* o. m; N
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  F  \# B# i2 a0 i& C$ K
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# K+ [$ ~* n. j. k( b4 }2 y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ a( ?) D( o) y' l) h; w3 u

" G& ~6 _& x! n: T6 C' }        // VRC7
. g  |# k5 S$ e7 Y! i        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
) f; B# }) A9 h' J+ G; U
% F' p/ E, b# t9 ?        // FDS4 @' |- G8 |! r: t; q  c
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;- H& z9 F& a, h' C& x( o

, W# i) B0 Y: J; l# e! A8 v3 }( e        // MMC5; f: A4 a* @) D% m
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" s/ i; U, E, G7 {' f# C) Z        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 ^6 m- m1 r  F5 Q- {; ~9 ]. y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 @. ?) p, k& a& _2 [9 B: J% A! r& N
        // N106% J9 S, K! U# x- R* g- E3 a; Q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 C8 i( g1 ~% E, r6 i
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! u4 _- u' o  o        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 N2 y1 n2 g/ K' F$ j& Y        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 z* |, z) w/ m: o& D        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 i8 U6 b  a# O) c$ M( s        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" B) r0 ]/ ^3 u
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  M" t( \6 G: [        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% d$ f0 i. ]" {; G% T
+ O& |& y: S/ W( s/ B7 b" q
        // FME7
4 t" I, \, R# y  S. g, R        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 E/ }0 n2 y4 L9 u1 M        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 M# d' y( Z7 T- A+ T( U: }  N
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" i3 n* k/ W# T% x( b: I$ G5 K7 @0 A8 C% l  {& u6 D
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& ^( z" F( J) V) r% {5 Q- m        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;9 o8 M2 \9 X3 q5 ^3 ^
4 Q9 {0 T" i3 k
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 Y+ J% c( i  `. o- e* c
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {5 o8 u- _4 e; y0 j
                QueueFlush();4 n7 h( w# H" F" u
        }
2 }" h( b- N, w+ s
4 I7 M' X- e# q4 y$ s        while( dwLength-- ) {! L+ Z/ s; ^$ Q2 Z) K8 B9 z' T  l
                writetime = (DWORD)elapsed_time;
( \% }* L% r" @3 e5 ]2 Z- [
: r, d8 [4 D- ?. e" G% @6 z" M                while( GetQueue( writetime, q ) ) {/ E& o( F4 j% W* `
                        WriteProcess( q.addr, q.data );) E4 {3 d+ s* i6 B9 M
                }/ G& R& X, c  N% i" w) P

' a' C4 [; }- r/ U3 r                while( GetExQueue( writetime, q ) ) {3 S" U6 a: ]5 D8 ^+ }
                        WriteExProcess( q.addr, q.data );* u% l/ N, x' U# P$ `
                }1 G" ^8 q% Q, Z) ^# P. B2 h

5 j$ @* ?8 Q  ?! K5 k                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" d; o/ y( k$ S* k2 I! y$ @3 P
                output = 0;+ p: ^: @1 q9 h) i
                output += internal.Process( 0 )*vol[0];* R4 }0 U4 N  f$ h
                output += internal.Process( 1 )*vol[1];
4 T1 f& F7 v- m                output += internal.Process( 2 )*vol[2];
( l6 i+ {9 K' R( y- d; C                output += internal.Process( 3 )*vol[3];
% l0 `6 q8 k9 z& D$ c; `                output += internal.Process( 4 )*vol[4];
% S: E" v9 z/ E  c$ F. s6 |& @
                if( exsound_select & 0x01 ) {* N, i" D8 [  H  S+ d
                        output += vrc6.Process( 0 )*vol[5];) |9 \6 u& r5 E/ K
                        output += vrc6.Process( 1 )*vol[6];) ]6 H) Q& c/ T: j
                        output += vrc6.Process( 2 )*vol[7];
9 S, s- a! B' }- R5 G                }
; V" Q4 Q+ g; Z5 b5 l6 x                if( exsound_select & 0x02 ) {
7 a. P( x" I. h" d1 D                        output += vrc7.Process( 0 )*vol[8];, S4 r& T/ d7 a" C( H
                }+ ~) S8 k9 t4 R- {6 q
                if( exsound_select & 0x04 ) {
7 n. h; Z8 i) U8 u- B                        output += fds.Process( 0 )*vol[9];
9 F- ^! c: J  s                }
1 l, }2 _3 A  l* O                if( exsound_select & 0x08 ) {, N; d. O3 L2 O7 A3 v4 M
                        output += mmc5.Process( 0 )*vol[10];9 e/ y: q" Z/ N0 y. s. s
                        output += mmc5.Process( 1 )*vol[11];
. X5 x" I% Q9 _( ~! n, d6 R                        output += mmc5.Process( 2 )*vol[12];" z3 `. ^* t, g9 P5 h$ L2 ^
                }7 R) F4 K" q3 z: q; ~
                if( exsound_select & 0x10 ) {! Z  I# H6 J/ H# V- q
                        output += n106.Process( 0 )*vol[13];5 j: l( n6 p6 y0 C2 c2 y/ }
                        output += n106.Process( 1 )*vol[14];) V6 g' v! J7 Q
                        output += n106.Process( 2 )*vol[15];
" \1 u, L  G" K                        output += n106.Process( 3 )*vol[16];
+ U, @1 m* W* `/ [! M; b' {, U$ a: Q                        output += n106.Process( 4 )*vol[17];3 z7 E7 }, \' ^
                        output += n106.Process( 5 )*vol[18];9 s$ K7 x6 g& |) Z2 _
                        output += n106.Process( 6 )*vol[19];8 D" c7 @" r% V
                        output += n106.Process( 7 )*vol[20];  S9 K* n5 u3 ?/ b9 I
                }) C/ ~- q* V6 m9 u4 L4 g- O1 o* |" ?
                if( exsound_select & 0x20 ) {
1 u  y: {; _7 R+ U                        fme7.Process( 3 );        // Envelope & Noise  f+ }0 \3 q, Y; o! @
                        output += fme7.Process( 0 )*vol[21];2 m# E, y$ }/ t/ a
                        output += fme7.Process( 1 )*vol[22];
' E* k( y5 Y0 A- f                        output += fme7.Process( 2 )*vol[23];% C( P8 R4 |; g9 O! k
                }
4 u& g* @' x& l8 ?5 a7 x* n6 y* c0 H- i7 O+ E9 {! p
                output >>= 8;1 s- q8 D+ ~: _

6 u+ P5 Y* D8 N' Q% ^                if( nFilterType == 1 ) {  l6 Q+ i4 u7 b$ V: T
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ c/ {! E, N' N) i5 ~
                        output = (lowpass_filter[0]+output)/2;
6 [: R+ c: I& _$ {4 c" i                        lowpass_filter[0] = output;# P. G5 h' o/ E2 x* R* E
                } else if( nFilterType == 2 ) {* b3 {; J+ j3 g9 @, E3 p& r
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 h( v: L% l8 R5 U                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: x8 d- `# J3 L5 H                        lowpass_filter[1] = lowpass_filter[0];
$ p  }  }* ^+ I* @+ d                        lowpass_filter[0] = output;$ B5 ^( m( J7 T$ y
                } else if( nFilterType == 3 ) {
' m: e, [$ r1 ~* p7 }                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 _; W2 @0 h, u/ M# B" f5 z
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; x3 X8 r2 n8 [: w5 e) q: e( F$ R* s                        lowpass_filter[2] = lowpass_filter[1];! Y; i5 v2 |6 j# B" b1 F. i
                        lowpass_filter[1] = lowpass_filter[0];& p& A% v3 U) i
                        lowpass_filter[0] = output;  }9 P2 j6 b5 ^- o# x6 H
                } else if( nFilterType == 4 ) {& T  B0 F) {. u( B2 K9 F# C
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  C* L  {3 g$ U9 [1 @                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
' T6 f" [: O, i- w3 d8 g                        lowpass_filter[1] = lowpass_filter[0];
6 V/ ^! x3 ~3 q8 H1 r1 n, B                        lowpass_filter[0] = output;1 m1 c# e) Y$ G1 s' }! A
                }% ]# i" e$ m. U6 [0 g0 z/ V

) S! P- l6 \% F* t/ a6 }; P#if        0
- H6 H/ y+ }% T6 ]! t! q                // DC惉暘偺僇僢僩
5 {& s/ W8 k; G) k                {
4 v+ l% c. P' u) Z/ w                static double ave = 0.0, max=0.0, min=0.0;! z' ~8 }0 O! N, {; O
                double delta;0 J+ W4 l. y9 @. j; x
                delta = (max-min)/32768.0;! h! a* _; O  s3 V2 y, z
                max -= delta;# k2 x; F9 P1 O/ m
                min += delta;
' |* E  g$ L% A                if( output > max ) max = output;' v$ j; b* A  g1 f; Q
                if( output < min ) min = output;1 b$ T8 b1 Z( i( ]# o
                ave -= ave/1024.0;: K% M" d- F: c) P) ~" g
                ave += (max+min)/2048.0;( w8 @, u* T) p1 s, Y
                output -= (INT)ave;5 Y5 O3 A# }2 k* l
                }
; Z$ Y, Y8 P2 N; X( g) Q$ c$ ?; [#endif
& p' d5 G4 |* h' |( u#if        12 P6 x/ G) \1 i$ @4 s0 f
                // DC惉暘偺僇僢僩(HPF TEST)
: U% E/ q& C. i) Z2 A/ A+ j, d                {; i5 B) n+ H" Q) r' x5 P
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% N6 k% O" e* A$ Y8 j
                static        double        cutofftemp = (2.0*3.141592653579*40.0);& ]; \. [) y6 Y
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ x/ T2 A' N0 [* @; A3 v5 x! f                static        double        tmp = 0.0;3 ~7 M0 C8 `0 p- A+ q! ~8 `
                double        in, out;
8 m& e8 C+ q6 h3 r$ O# R* C9 I, j; [: H# K/ ~1 [  e9 I% L$ `" T
                in = (double)output;3 f5 z1 C& u9 z$ e/ B! w, K
                out = (in - tmp);
! a" E* h* _! V' x4 J/ F                tmp = tmp + cutoff * out;
, [' h* q8 a  D8 J! u4 p0 D2 \
  ]7 d% [. r' `                output = (INT)out;
: }  N7 R6 g$ [' Q' ?                }
3 q, P8 _; u; r1 a$ B- _6 b! u#endif( k1 w8 f! [1 m4 b6 l
#if        0
. Z) P% z! Z8 m) F1 x) u/ }# t) d                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 d% V8 V  G$ f
                {
" K5 w" q" r7 k* l                INT        diff = abs(output-last_data);
2 |1 T# _3 k  k. C                if( diff > 0x4000 ) {3 H8 ^. h' Q! c
                        output /= 4;+ a4 J0 O8 G7 c0 r; F4 G4 N
                } else
5 M( t  a& z, w                if( diff > 0x3000 ) {
3 m0 x# j) @3 W. y, F" }$ r                        output /= 3;& S% B4 s9 J! g; M
                } else$ ]1 e4 w! H  w/ U1 ^
                if( diff > 0x2000 ) {
  ^3 e8 }" R' }) [                        output /= 2;  C! s* B) m! e
                }/ ?  y1 W' T* j! d7 J1 A/ x
                last_data = output;1 W5 c& D4 H  }7 j4 z4 j5 z* d
                }
4 p: C9 W- {8 _" r) N3 b- y#endif4 V4 b1 b0 b, i2 I8 G/ Q; l" u
                // Limit. j* L4 R9 ^! m( _. I  u% J2 _. Y/ ~
                if( output > 0x7FFF ) {
8 r& R" h/ F0 |                        output = 0x7FFF;
) l( q5 \6 ~- T, q) v                } else if( output < -0x8000 ) {
! B6 v* J5 P" e, X& ?7 v3 d2 f                        output = -0x8000;- l) _9 }2 Y8 }: {
                }7 N) x' Q+ [+ _& x9 L+ X
8 ], ~2 C# G, A' e" E
                if( nBits != 8 ) {
1 ?& r4 B8 A9 y# a                        *(SHORT*)lpBuffer = (SHORT)output;
1 k, X5 q# ^$ }2 }2 e/ ^& O% {                        lpBuffer += sizeof(SHORT);- R% _+ X' A* d
                } else {
7 S  w- i6 r5 w* L  d% Y                        *lpBuffer++ = (output>>8)^0x80;
5 x3 c1 o' `! A                }) o" k' P, D; Z7 t- o" d# o

/ ~3 `/ ~: i7 p1 F# @5 Q4 d                if( nCcount < 0x0100 ). B- z2 W/ G7 F. V6 o  d$ N
                        pSoundBuf[nCcount++] = (SHORT)output;5 Q- W7 v6 ]9 J* W2 G
" K' e& O) f: H6 Q* V. a
//                elapsedtime += cycle_rate;5 n0 w' _5 P0 c, P  j
                elapsed_time += cycle_rate;, G% U5 p5 [$ b+ B. K  Y
        }  K4 e% q4 e6 W6 I. c7 E5 n9 h: d6 \
7 J' H3 S. C1 s
#if        1% l$ T  v8 r- |
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
4 `4 I- x) W4 S, V                elapsed_time = nes->cpu->GetTotalCycles();
' B3 U5 v, f( w: @8 }2 A        }- m/ g8 t0 p/ y+ k* o5 [
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ D# R2 ?( ^! c6 `" T; c5 j+ j
                elapsed_time = nes->cpu->GetTotalCycles();" |3 `) O, i0 V9 x
        }+ @" j$ K1 B! B2 {& @7 w1 @$ r
#else
* Y( h! g" ~/ i: L2 h6 S        elapsed_time = nes->cpu->GetTotalCycles();
7 |* a" z" F0 o7 y4 G#endif
: E" D* p9 a. X& R! _% v}
3 Y3 S5 g! l; j4 C2 T! M5 w; {' P/ W8 X9 N, P7 ], I7 L4 J
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ e( z3 x) J3 sINT        APU::GetChannelFrequency( INT no )
  H8 N) [2 H7 T* g; a{, v* R% ?2 `- X. g) H
        if( !m_bMute[0] )
. X+ F* C+ a9 Q# s* {                return        0;; T. h# B. x& L! Z# d

. w  m8 u& A4 `/ f4 @' h        // Internal
+ G  s! J- }7 _; L        if( no < 5 ) {
( ~+ k" X8 P# M: B                return        m_bMute[no+1]?internal.GetFreq( no ):0;7 V0 r' S$ A3 E' H- A3 C2 j4 }
        }! Y+ |" ^* W# |% s/ g) b; Q
        // VRC6; p1 C1 j" \" i! `: o" D7 C
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {! @% K2 p. |7 H$ f
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
* @8 A8 s8 j& C6 \  O        }
. q! a9 c8 x/ y3 d2 A        // FDS
! \5 s' C0 s1 p1 m& P! |        if( (exsound_select & 0x04) && no == 0x300 ) {$ V0 g7 A, i" i5 _' u, G! U
                return        m_bMute[6]?fds.GetFreq( 0 ):0;% c+ R! F: j( h5 }
        }
0 h9 i3 d) X; b- h. i' [* Z        // MMC5
$ p9 K* V. }2 Q; D' \        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {/ n  }9 q0 t, K6 v9 f
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 e. f) A: j* l/ ]- K: E        }; C7 p3 w8 H0 ]( h
        // N106
; @/ r3 r, q) ^& g, p7 {: x        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- f) ~" o& _# v7 Y6 M! D                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; X2 X0 f) k% _3 q  z1 K
        }
1 k& ?, O. H0 {3 a4 o# _/ H4 n        // FME7; f: c4 ~& B1 U3 k
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {& g3 h  {: S( y
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;  p9 m7 e( l/ ^6 Z2 ^- @
        }
/ J8 T9 n; [1 ?/ Y6 a8 q        // VRC7
$ u" K/ T! x- U5 ^        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: d: h% b: a2 Z7 u8 J0 [: K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 C5 J" H/ Q2 N( Q: Q8 g        }
4 A7 C9 d% I6 i8 k0 l; H7 C; u        return        0;9 G* F6 M3 h# Z2 i2 R. L9 ~9 N/ u
}6 K3 ?- K8 S) ?: [% ^
- G- \+ S/ d. }! h2 F. a; w7 A
// State Save/Load  |5 d; q0 f% ^* g' a: g1 u5 F
void        APU::SaveState( LPBYTE p )
1 V/ N2 N5 e. v( @0 O4 w{- q6 x$ Y" Q0 c
#ifdef        _DEBUG
; x: l/ j! t' W: @! I$ G4 nLPBYTE        pold = p;! A; Y/ ]( S: F9 J
#endif
# d; R( b$ [" ~$ K& r+ G2 [& {4 ]( _7 B# J# J$ N
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 x' f+ {% L( C& L7 [7 [4 D
        QueueFlush();
- H+ k# }$ m5 f8 T) K3 L3 N2 a+ G9 p3 ~; G9 O: [  M* h" d( B7 M
        internal.SaveState( p );
! r( p& |4 f; h7 x& I        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) _, u/ P: \7 J7 J$ V( o, \0 O$ q
% M8 W9 Q/ y/ d6 E1 ^# C+ _
        // VRC6
, K/ K) V( ^- H/ B. v        if( exsound_select & 0x01 ) {
5 I) m3 k& }' \; L                vrc6.SaveState( p );
! x3 c/ v3 ?6 Z% u- k1 Q! O                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ h& R+ P. B3 O  s        }
) }& ^, _0 l2 f2 C        // VRC7 (not support)7 l2 h6 u$ W+ ?1 _* E
        if( exsound_select & 0x02 ) {6 i0 [) i( L! J+ Y0 a6 Z4 x6 z7 v
                vrc7.SaveState( p );) B4 B3 U& y5 j
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) n1 ?3 H8 @0 ]( t4 m+ _) J8 p9 s
        }4 d! ]6 o7 z+ Q
        // FDS  l* p6 f6 t8 p. t" E2 ~
        if( exsound_select & 0x04 ) {/ n) B, j) \9 z1 J0 E# Q
                fds.SaveState( p );
' m4 c' ?: W, {, d7 {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' V8 o& A" G6 n1 d        }0 L* |$ A+ o  P/ V
        // MMC5! S6 |" X* S/ p- ?4 i8 Z9 P
        if( exsound_select & 0x08 ) {
: l( G/ |9 c: w6 o5 S  m7 r1 R                mmc5.SaveState( p );- `. V+ o0 r% Z" o$ n* d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding- h# y% C+ W  d
        }: T: i( g9 u' G: |7 l& k
        // N106
5 c: m% z+ e! X2 z1 F        if( exsound_select & 0x10 ) {
3 m4 s8 F. z: H( K                n106.SaveState( p );
( q% [- j6 u+ F  t, @3 s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% L% |2 q0 x  |1 M        }
8 @  [. m1 U9 ?        // FME7
7 ~1 o! k8 Y; w7 n        if( exsound_select & 0x20 ) {5 j2 k( Y, H( k7 o
                fme7.SaveState( p );2 v1 L/ P" `! v% T
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 g6 z4 a4 f+ v, y9 ^. X        }
" ^7 e; c9 W8 u8 {- G. u; ?( k
1 A( s0 v* F8 L9 W: ~" n# j#ifdef        _DEBUG
( t, Y# h3 H3 }: b( q9 r1 I1 A# c+ J, PDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );/ O+ J& w- y9 s  ~
#endif& L& U8 `' l: F0 ^
}& A% a3 L8 ?9 ~4 T: P2 {* V$ X. j

9 B. @3 }$ h: c1 w+ c$ J+ F  gvoid        APU::LoadState( LPBYTE p )
  a6 m# D8 l) b% S0 `+ f( @{
5 _2 g+ S( `8 X6 e        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
5 d: @! f* s; N. ~        QueueClear();2 e$ H" F5 z  }/ Y( o) ^0 R
; ?  r# ^: o" W0 K9 X
        internal.LoadState( p );
# p8 u# c" ?  G- Y( ?- ~3 e' g- Z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ K* ?1 |( N. e1 K: R" h4 o* D3 l: C
  ?+ A0 ~0 G1 H# Q  K        // VRC6/ P5 R; |0 P1 ]9 z6 E; \6 m
        if( exsound_select & 0x01 ) {
: A6 b& ?) V+ W) W$ x                vrc6.LoadState( p );9 T) J; q0 A; b
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! `1 p: l/ V! w        }) a9 ^8 Z8 z4 f. n( K1 i  s: O
        // VRC7 (not support)6 U% M$ [+ u# r, J. u. _" T
        if( exsound_select & 0x02 ) {
; a- t7 j& `& A$ f% E) i                vrc7.LoadState( p );* H9 y8 `9 J' ~! H9 y' C& t( E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 Y4 s% f: v1 T8 V: N
        }
9 f  }/ C$ f. t( O, {3 m4 M5 o        // FDS
, g4 J9 ?9 r& \1 H        if( exsound_select & 0x04 ) {
$ D; t% V! f; l0 C                fds.LoadState( p );, [0 }* P# }9 l# E, n9 C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 D" t, ~/ R  A
        }
! i$ Z/ K, Y4 a. e0 r# m, H        // MMC5
) q. c. ]) n  u: J; I        if( exsound_select & 0x08 ) {' e! R, C* z# j0 D
                mmc5.LoadState( p );' A' O# {) y0 j# n2 n/ }$ f  Q% F
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* G! ~; J' n3 l- h
        }
+ i2 l# b+ ]+ u        // N106* z6 T7 Z# A9 h2 \. B* |
        if( exsound_select & 0x10 ) {3 ]: v. W5 ?3 ?; ~4 \
                n106.LoadState( p );
$ _( m0 s% w& b3 r" |                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 s1 v1 l3 x# n- H
        }
- P' X  V6 c# }" V4 ~, x        // FME7  z+ G( b- L2 R5 W& p# _2 b* \
        if( exsound_select & 0x20 ) {
  U) {( N  N9 s6 o4 G1 e0 T                fme7.LoadState( p );8 v9 Z5 C% W) k& n7 ^2 L) H- Y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 B7 n, X+ L/ ~$ ?        }! P8 d$ L3 P  F7 z- Q
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
- d1 B  b0 A6 r" p可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。$ {* o, l! A1 \8 C8 r1 d2 l
感激不尽~~
  l: g1 B5 z% m, a. @. r
恩 我對模擬器不是很有研究,! P' D. b' g& E5 M
雖然要了解源碼內容,可能不是很困難,& G4 B+ Y" b$ z! q- P9 |+ J7 a
不過還是要花時間,個人目前蠻忙碌的。
2 w! T) ]# K$ ^! L- m. l
% _4 w4 P1 H/ a) G8 @3 o6 ~# t給你一個朋友的MSN,你可以跟他討論看看,7 r4 S2 q+ v6 w
他本身是程式設計師,也對FC模擬器很有興趣。* E" ?- ]' E+ ?# U
2 ^5 y7 {% e7 R, F; ?
MSN我就PM到你的信箱了。) R" V0 N1 N% j" f- X
3 N8 E& v1 S8 F
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
3 V. N' U' V% c; L( _  j! y呵…… 谢过团长大人~~

% M9 F; w- K! s3 D% \$ }% Q% t: s" O! W1 S% Q
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
1 M4 N+ l3 ]; O5 H  \3 f团长的朋友都是神,那团长就是神的boss。
1 w( n7 m4 n4 v+ g) q) O+ ~: P& u
哈 不敢當,我只是個平凡人,
! Z( {; `  a2 D0 T; n. y8 ]要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
4 g6 D) v+ S2 o8 E  H0 sZYH. h' x  S. e% ^4 X4 u3 b7 D
QQ:414734306  M& i0 k, U# G4 {7 c  K! v
Mail:zyh-01@126.com" R: j- f( N- m) l  V9 h/ \5 w' \7 r

% }3 K$ e- w+ W5 s) n7 U他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
" ^9 Y2 B; W9 X6 j8 s' J再次对团长大人和悠悠哥的无私帮助表示感谢~~

4 ?% Q, _+ F7 `% i* H! Z' W不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-22 18:28 , Processed in 1.111328 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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