EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ B. P  j' o' \6 |3 I* V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. G0 \& _" V  ~+ @6 L# Z. p: o: ^
这里有相应的模拟器源码,就当送给大侠了~~
! e1 p% k/ n! Q8 D% Khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 h9 f2 p) _1 U1 B
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 ?7 B; p. e5 W" t2 X/ c5 x# f* X* f楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 W; b5 i5 m. T
这里有相应的模拟器源码,就当送给大侠 ...

; D  }+ u& ~9 x. M/ d2 G聲音部分(Audoi Process Unit = APU):7 O" a  S- i5 k! I' U/ b" _
.\NES\APU.cpp! |. V' ~# q# H7 c% @
.\NES\APU.h0 S. k- A5 {, x

2 @  p% o! d7 d7 S( A! s. O6 A) _& e' b% q. T+ w( Q* n( g% }0 M
影像處理部份(Picture Processing Unit = PPU):! _- G7 D$ b9 e* c- S- _
.\NES\PPU.cpp
2 ^* Z2 n& \; ?$ F7 G' k2 Q.\NES\PPU.h6 O1 i1 w' r5 P5 d) d3 Z
1 V3 ?/ Y) S. Q) ~. x& P# [/ a
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 C, u: G7 S9 T; Q5 v(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 k# G0 P4 m! P: k* c5 `//////////////////////////////////////////////////////////////////////////
; ~/ Y6 |4 Q& E) _//                                                                      //$ Z0 Z2 R3 \$ p) ]5 Y
//      NES APU core                                                    //3 i6 M1 u) W( @5 a& K) @6 ^
//                                                           Norix      //7 @4 g* G0 `% W7 M/ G, S  D2 r
//                                               written     2002/06/27 //3 ~% y0 u: B+ k0 Q
//                                               last modify ----/--/-- //
3 N% r3 d/ s( y* @4 S//////////////////////////////////////////////////////////////////////////! Y, f7 r9 W% Y2 }3 ?. p
#include "DebugOut.h"
) S9 i/ G/ f* Y0 \#include "App.h"( Y; n" k0 |8 J* I: y+ v+ W
#include "Config.h"* n1 L" {' `5 h
* ~- U/ v& b, {- c4 Q
#include "nes.h"( Q  _! l) t) S' ]' W" a, G
#include "mmu.h"
' \" L" e& h9 q$ r( e#include "cpu.h"
+ U/ X) }6 {+ W. K9 K  M. v) V6 Z* [6 x#include "ppu.h"! p5 a2 Y% S- @+ p  d
#include "rom.h"5 ]7 q' _- ~+ j
#include "apu.h"- k1 x/ z# v% j* l9 }5 E5 p, O9 ?
  ]5 U+ R( o) |/ O6 O5 ?
// Volume adjust9 @7 Q0 @# l3 w" F
// Internal sounds8 d& [% k& i& q6 |- r& m' }( o: j
#define        RECTANGLE_VOL        (0x0F0)
' z5 t/ E% b. k8 R  s#define        TRIANGLE_VOL        (0x130)
5 j$ f  V; k2 X+ J& D5 k#define        NOISE_VOL        (0x0C0)
& D0 F. H8 q+ ]) Y; z#define        DPCM_VOL        (0x0F0)
7 ?: \. z$ A. h! |, M: [" r// Extra sounds
; l/ w! y  p/ U/ c( Q, E2 o#define        VRC6_VOL        (0x0F0)4 u* W6 ?( f& j
#define        VRC7_VOL        (0x130); [) y# y3 q' K5 s' `, m+ W4 j
#define        FDS_VOL                (0x0F0)
3 i7 C: q0 P% h% L7 Q! u( F#define        MMC5_VOL        (0x0F0)- G% T6 i% @# X0 q, w+ ~7 Q( }
#define        N106_VOL        (0x088)  Q- s9 p% z% @
#define        FME7_VOL        (0x130)
+ u% ]/ c1 ~) h. T, j7 O9 D: Y2 W" ?: I/ i" j: g# u7 p: c
APU::APU( NES* parent )2 {# b) `, P9 p2 R( v
{
6 J6 I) D  K! `# i        exsound_select = 0;
4 [: s$ V0 H4 J% [6 K0 H$ e9 Q( u- m- I/ R# h
        nes = parent;, S+ l  g! \# K& q# q1 k! D3 m
        internal.SetParent( parent );
3 d/ H5 r+ F9 M$ Y8 T. `; I, `" i, r" W; y. D& m# w- m' h
        last_data = last_diff = 0;3 B4 z, `+ i% y5 S& Y$ ^
+ e: h8 y0 z2 C: r$ a
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
8 \, Z! V# m& l, z' r) T. d; Y9 u7 u4 ^
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );9 O& ]) ]7 O; `. r+ E& f. l
        ZEROMEMORY( &queue, sizeof(queue) );
' Q7 Q# H# H5 N! ^( U* a: F        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; b$ p" v7 i& q7 n% S" k) _$ m6 z# c" N
        for( INT i = 0; i < 16; i++ ) {
3 M& L( l8 \4 T. K3 P$ B- |8 S) v  n                m_bMute = TRUE;
+ J$ G9 v8 a' T( ^3 b/ P        }
7 Q0 @" z6 {: h2 h' `}4 ]" h8 I# i% b$ F

+ X; j; C$ {7 ~$ c. H4 oAPU::~APU()$ \' |# U  i& \  E* O) Y6 [# X/ \
{
0 `0 [' x" g; f/ E  i. R/ _8 n}6 \- s- b* p  C9 T' l/ T3 n; t, p
" g5 @. L5 a5 O9 [" f9 J( A0 t
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 ^4 F- z4 x* h
{: `% E! m& M% ^3 l# N% g* r- {3 c& O
        queue.data[queue.wrptr].time = writetime;; m. |3 }; \3 z) z+ F
        queue.data[queue.wrptr].addr = addr;1 \" D# c" N. v  K0 z* r# a' p
        queue.data[queue.wrptr].data = data;6 Y# f) V; s' y8 x. b7 d
        queue.wrptr++;' @$ E$ T  z! f/ U/ |( E9 R
        queue.wrptr&=QUEUE_LENGTH-1;
* K; T5 M0 H" J6 Q* ?5 C        if( queue.wrptr == queue.rdptr ) {
0 d, D+ f8 ^& Y5 M% G                DEBUGOUT( "queue overflow.\n" );* V/ i$ \# r0 y' H% b
        }& j6 e; }* S* D; t# ~1 Y
}5 A) }" l& I/ w7 [) H' \! P
; L- C$ j7 [. ?% _4 Y2 t
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )$ n; R- w  ]8 i( F- }; c* I! ~' `
{
1 |* g( I' j& d, x7 }        if( queue.wrptr == queue.rdptr ) {
6 o( _# W3 o8 N  X, X                return        FALSE;' R- X& Z  w6 U" S' L
        }
! |2 W5 B5 R! s; n$ t& H        if( queue.data[queue.rdptr].time <= writetime ) {
' K# T. t& u8 B5 z                ret = queue.data[queue.rdptr];
: @! u' B: ?$ V1 w                queue.rdptr++;
2 E' ?" U% W# Z% _                queue.rdptr&=QUEUE_LENGTH-1;# b$ ?8 t; i! b9 @
                return        TRUE;9 }$ B/ `$ b5 e- U9 E9 P' P
        }
' @6 t+ g1 t6 ]2 f        return        FALSE;
2 T1 o# l0 K0 V; O+ D" j}
1 h/ D0 O1 e4 I3 f. N% s( ^6 A* ]/ x. @5 a) O7 p7 X7 U+ O. r
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 h4 s0 E8 P$ B. r( {& k: P: G* J
{
  f9 I4 d4 p! ^1 z        exqueue.data[exqueue.wrptr].time = writetime;1 t9 a% C) [5 a1 {3 [
        exqueue.data[exqueue.wrptr].addr = addr;5 N! b( P0 E2 [6 p+ f3 \% s; i
        exqueue.data[exqueue.wrptr].data = data;+ E2 T8 L! M) f2 H8 @2 ~. `
        exqueue.wrptr++;, z/ l' ]/ ~+ C3 ]( e: F* U, H
        exqueue.wrptr&=QUEUE_LENGTH-1;
, [) m; u9 ~# m/ Q  G        if( exqueue.wrptr == exqueue.rdptr ) {
; X% C# N" W7 K) D: i0 @                DEBUGOUT( "exqueue overflow.\n" );4 P( d- f2 c! ?- s& M4 X; T5 F- ^
        }0 `" [2 w7 M2 r  H
}, s* U2 j2 y0 N! s6 J) v7 N- O
. v* ]. x4 F* T" I- p% D  l/ l
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ), d9 M" J# F9 W5 `: ^, H! O
{% s8 u: w% L+ c, }+ t
        if( exqueue.wrptr == exqueue.rdptr ) {
- ?! J! a) e  \* a                return        FALSE;! \$ A. w- P! R. H& l7 J
        }
5 J3 c1 s, X7 j7 C0 R        if( exqueue.data[exqueue.rdptr].time <= writetime ) {9 e' k' f+ K; u9 U4 |
                ret = exqueue.data[exqueue.rdptr];
$ S; A' h0 u" A, m! g+ U. D8 |                exqueue.rdptr++;
0 [# K# w# n7 _2 }4 ~                exqueue.rdptr&=QUEUE_LENGTH-1;; I: y  t  U6 H, X1 j/ m
                return        TRUE;# @/ \2 f: W0 N( z1 z: E6 J' N
        }
& d  l1 Z7 M5 W( z/ s        return        FALSE;  @2 k2 a+ F% f$ K
}
1 ?' e" ?+ |9 F$ S: S9 F) F
! _+ E% g$ i* t* B% j1 qvoid        APU::QueueClear()
9 Z- e0 f. u/ U- p2 L: S2 B{
$ I% q( v4 Q6 r7 l6 T9 W4 ^& K( f        ZEROMEMORY( &queue, sizeof(queue) );
7 u+ Y; X- g% ^; {# K. @/ I0 k8 J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- A2 I5 x9 ]2 Q2 m7 w}
' k$ j/ b6 }5 U2 o, G
/ ~. Y) R; Q8 w1 F+ P9 A7 tvoid        APU::QueueFlush()/ X  ~1 k8 I. X) N; M% }( _
{
6 c7 ]- Q" e; c7 B1 p' o5 `6 H        while( queue.wrptr != queue.rdptr ) {
+ N0 ]" i/ `8 X7 L* ?: O, @, g                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" ]3 G8 n) b0 j                queue.rdptr++;. l5 O" u: E: Y5 ?% |  c5 J
                queue.rdptr&=QUEUE_LENGTH-1;' ?4 p: b$ _; O: f
        }
' q, C( Q8 y9 x% Y
/ @! d3 b/ H, E  u        while( exqueue.wrptr != exqueue.rdptr ) {
) t8 f+ x: A0 g. k" ]3 v                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 Z- c. V+ b- P! P; s& v* b                exqueue.rdptr++;
6 Z* U3 M5 H# Y                exqueue.rdptr&=QUEUE_LENGTH-1;; n" L8 K5 X! M# p( E  K  M0 n
        }
! L! I9 B6 L1 k7 T}
! [4 }% |: A# i
+ l. l5 ]7 [0 Tvoid        APU::SoundSetup(), U& |9 i! Y3 F* f, Y0 U1 ?
{
" e7 f: a7 ]3 r' I' T" |, i- i        FLOAT        fClock = nes->nescfg->CpuClock;
0 O& u+ R! W  H1 O7 e9 }        INT        nRate = (INT)Config.sound.nRate;+ j, q4 b+ t9 s! \% A. I  o
        internal.Setup( fClock, nRate );8 b) @6 R. L% L6 n8 E
        vrc6.Setup( fClock, nRate );
% J4 o& [  A" D        vrc7.Setup( fClock, nRate );
! U6 u- s- V8 F9 ?        mmc5.Setup( fClock, nRate );
) _: g! R: J; S$ q$ \) `        fds.Setup ( fClock, nRate );
% f. v4 a5 g; {% G* |7 F! @        n106.Setup( fClock, nRate );
: N6 @" Y" q+ T/ c0 |; |- _7 A" b" r        fme7.Setup( fClock, nRate );# h5 A8 |2 ]/ G3 z% p
}* V" N5 P. z* T+ n. V

- `" y+ d: Y" C8 {1 k) }void        APU::Reset(); E* ]$ |# p/ |. A5 p" t
{1 k. K  }$ Y$ c  ~) Q' L5 v1 n
        ZEROMEMORY( &queue, sizeof(queue) );4 i1 F) j5 `5 j5 `4 I8 j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );" d) c/ N# K2 y

* Z; Z3 p5 F, {) Y4 z        elapsed_time = 0;
1 H* s0 c+ g' {0 o3 u+ W; Y) S+ S! b6 d" {; e. r
        FLOAT        fClock = nes->nescfg->CpuClock;
: l* m1 s1 x: {( q1 t, a2 l) [        INT        nRate = (INT)Config.sound.nRate;' w8 Q, ~6 {9 h6 y( r4 u- R) v) ^
        internal.Reset( fClock, nRate );( I! E6 v9 |+ }6 ]
        vrc6.Reset( fClock, nRate );
( Y  |0 }& H/ `. f9 D        vrc7.Reset( fClock, nRate );
7 ~6 p! t* D" M8 B+ {4 ~        mmc5.Reset( fClock, nRate );: \( ?- @! ?3 B6 _) {
        fds.Reset ( fClock, nRate );
7 }. Z, `; r3 g- w8 b3 \% c& ^. X        n106.Reset( fClock, nRate );
. K: y/ B6 F8 W0 Y: i$ Z# A        fme7.Reset( fClock, nRate );
3 F) w/ H$ D" D3 P: B# Y* K8 J2 T, `) p; g
        SoundSetup();2 V; n" f, E1 t5 h5 ]' t) Q
}# ~. A* n* _( P( l

: }, O' I6 F4 O$ {* Y2 ^0 q9 G% Xvoid        APU::SelectExSound( BYTE data ); B3 m6 }) S3 ^- A" b
{, V# a* R( `/ u" n
        exsound_select = data;
  ~8 r, s# r2 z}
* [/ ?5 M& U! _) e" C' c  P! X- s: H  a% `6 q; M
BYTE        APU::Read( WORD addr )
& Y0 ]. x5 f1 v, j{
7 V) k& t" i* `8 f1 I        return        internal.SyncRead( addr );+ o& Q$ m! D: o
}
( G* K, N0 g6 ~* ^
: u1 ~8 y" n4 tvoid        APU::Write( WORD addr, BYTE data )
3 v2 \) c' l/ Q* {{* Y# @7 Z6 _8 i& b
        // $4018偼VirtuaNES屌桳億乕僩
. N% Q% G$ U) Z8 B1 u( F        if( addr >= 0x4000 && addr <= 0x401F ) {3 M2 Q, n0 V9 X8 o2 Z' y/ \
                internal.SyncWrite( addr, data );! S3 ]; n3 p* o
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 e! l- I& u' Q        }
6 y% ^5 _* h  }3 [" `: c8 I+ P}
  d: L9 V2 z5 X" I
( }5 E) ^  O% v5 _5 tBYTE        APU::ExRead( WORD addr )
" d* x0 f3 \+ s1 V- n) Q! Q  u+ J$ \{1 `' B2 p$ L  f$ `6 W6 _6 P
BYTE        data = 0;
9 _3 ?- R" w- A6 i5 C; Q. f" c
8 V( W4 t) U5 u, x: p        if( exsound_select & 0x10 ) {+ `/ t% {5 c* e' ~% g7 I
                if( addr == 0x4800 ) {
+ E" H, {! Z1 _$ ?  U  m% ~0 N% c                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
6 C$ h  h. u) v                }% C, e& v9 _  _  V% J$ \
        }
1 Z; Y" K" q6 c. L/ `7 |        if( exsound_select & 0x04 ) {' @4 w+ W" o5 t1 w1 v
                if( addr >= 0x4040 && addr < 0x4100 ) {- `) S* n- X6 n
                        data = fds.SyncRead( addr );
9 x# T# [3 f! @0 m( a) h$ Y) u7 p                }" B  H+ l5 y& P* r8 E7 t' \  h
        }; Y1 T( d' p8 q. G  X
        if( exsound_select & 0x08 ) {- F4 P5 e/ ?! J9 X) R+ U
                if( addr >= 0x5000 && addr <= 0x5015 ) {
; P5 c& c* V4 s9 [7 ^# O- E; E2 O. \                        data = mmc5.SyncRead( addr );9 I* L: x: f/ U6 ^* a0 f0 j
                }
# D5 g0 {/ s' F4 m" m        }
8 l- V) b* N7 M/ x1 k4 w! z5 k4 Q% z' Q% y$ ~
        return        data;) w, r% K4 K% c  O; G; x
}
- N$ d; H1 l/ y4 M4 g4 C
/ P& b$ l% v% P0 ~# {( ivoid        APU::ExWrite( WORD addr, BYTE data )- g. N& I7 A( S3 }
{9 r* C2 T" [5 M! G% J) _
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" {5 P+ B' o) }1 t; r5 t  S$ f' X% g- f. C$ Z
        if( exsound_select & 0x04 ) {$ t) G4 K1 z8 I
                if( addr >= 0x4040 && addr < 0x4100 ) {4 L  A/ [5 R1 S. _" c- r
                        fds.SyncWrite( addr, data );
7 _5 n+ M& Z4 J, ]                }3 i$ C0 e2 h* ?& H7 ^
        }6 p5 T7 M' {4 t5 s- J
+ ^0 O0 O# V+ K
        if( exsound_select & 0x08 ) {! \/ r4 m- f  J/ Q* R/ D
                if( addr >= 0x5000 && addr <= 0x5015 ) {6 R" o/ l( E; E  M5 ~
                        mmc5.SyncWrite( addr, data );
" Z$ x( Z( K  A$ O                }
0 g' U: s, z8 m) W" u        }5 F, O* h$ _$ L2 N2 P/ _% Z( E
}- F/ Y6 X- A$ [9 v9 i2 x7 `

' Q, K! B0 C* p. Rvoid        APU::Sync()- C. |; G, a* f6 s
{" U4 r! x' U, [$ S$ h
}/ H# m6 ^1 i. I3 h# V

/ l3 @6 t' g1 T' \/ \void        APU::SyncDPCM( INT cycles )
# I( D  Z4 i! d* ]8 k8 d; y$ M8 G0 m- A{' [# N" ]( c7 [" x* ?  W, l
        internal.Sync( cycles );0 H: @( Z6 \8 k+ E/ T
+ I0 T! v( ~8 _
        if( exsound_select & 0x04 ) {3 k- F# J6 k' L1 b$ l4 I, W
                fds.Sync( cycles );6 O" I$ w! E$ J! l
        }
! U4 [7 \. ^8 T8 [) _$ p% V9 p. [, V        if( exsound_select & 0x08 ) {1 f+ L# e0 e% a' {$ v4 g" P$ c, r
                mmc5.Sync( cycles );' E2 F1 {. v5 h0 G
        }: o+ c4 Q5 y  q) U" Y
}5 s" G+ C2 s; Y1 y; ?1 {

/ x: {& G% {% d: s! x5 o; S: s. |. ovoid        APU::WriteProcess( WORD addr, BYTE data )
: j9 x) Z! D" m7 A# U" g{
7 J9 D2 a- L) Z  x* D$ F9 g        // $4018偼VirtuaNES屌桳億乕僩
4 `& b' g9 m* N& U' r+ \4 w( m8 s8 s        if( addr >= 0x4000 && addr <= 0x401F ) {
+ K" H1 h: ]- E                internal.Write( addr, data );
& [! W4 A% V* f3 S( f, w        }1 C9 D0 X* e. g% E6 _
}" o5 k" C0 Z; Q" ~# Y8 ]) K- ~

8 i. n3 ^: |% K9 v7 ^! nvoid        APU::WriteExProcess( WORD addr, BYTE data ); N: i# ^! r" Z' L8 x: @& L$ n6 Q
{: k1 l5 ]2 Y" T
        if( exsound_select & 0x01 ) {
2 u) l* v' M1 M) N3 k                vrc6.Write( addr, data );
6 p* z: O. V% U' i! A        }, k$ v+ E5 c% |+ V7 \
        if( exsound_select & 0x02 ) {6 f7 m  q) L" v5 X
                vrc7.Write( addr, data );/ p2 f. Q# T- H6 B- I& `% Z
        }
% i+ e1 W; T. S8 u; |+ P$ b        if( exsound_select & 0x04 ) {
5 D  r  X# p( r1 C                fds.Write( addr, data );9 e' c% F8 n$ }% t: ~  g1 A
        }+ P7 ~1 q* g3 x# H5 e
        if( exsound_select & 0x08 ) {2 I1 B0 U$ Z" b9 V6 Z( s/ G- g5 _
                mmc5.Write( addr, data );
! [6 Z5 ^# x$ y4 T; L* y5 X" d6 d/ t        }) a3 A4 j" o+ H
        if( exsound_select & 0x10 ) {
$ t) Y2 ?6 P% N% s5 ^8 k! ~4 M                if( addr == 0x0000 ) {
+ @" ^! Q/ l6 S8 M- E                        BYTE        dummy = n106.Read( addr );! a. r* M9 Z# E9 i. x2 z- O
                } else {
2 K0 j4 W/ u; B3 G. G8 Y& h3 c                        n106.Write( addr, data );6 d# J4 v! S* b- ^
                }
1 ^& ]8 P1 D' J6 p3 x: ^/ I. f) }        }; M* Z3 ]% }0 b+ ?$ K; w  s
        if( exsound_select & 0x20 ) {! P4 D, S) v+ T4 o; v6 X
                fme7.Write( addr, data );
$ w4 d$ d( K; R: A2 [5 O8 Y4 x        }  v1 J" i- }/ }' _
}+ Z# W2 G) W, d- S
& Z" c0 y" N% e' o2 ^* z
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )& g7 o) e: A# |, \
{2 \7 _8 y2 R* s$ G$ M
INT        nBits = Config.sound.nBits;
% Z" T; s6 l/ n- c7 i% iDWORD        dwLength = dwSize / (nBits/8);
: s7 O8 x% r8 b3 FINT        output;0 M/ s- b. @/ H# P! F( x7 ?
QUEUEDATA q;
( |( s% U( j" {/ v: ZDWORD        writetime;/ V3 o. Z! J1 A$ q6 a

- W' d" X4 p& g# I0 v8 V% Y7 @% |LPSHORT        pSoundBuf = m_SoundBuffer;
0 E3 V1 p4 K. MINT        nCcount = 0;
+ H1 x6 a! z1 J" C5 X0 K1 I
5 V0 V4 e% [1 S* T8 WINT        nFilterType = Config.sound.nFilterType;4 q) e& {5 i# x, B& o

: G# c6 g0 b5 G, y1 F: C+ j! U        if( !Config.sound.bEnable ) {$ ]8 B; w% A! }' `
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );0 r3 y2 Q! u& ?3 f
                return;/ d% B5 Z6 j0 O  x/ s2 C  I. `8 P
        }
2 Z9 S3 ?! }$ b+ a9 h/ _9 u9 H- x: e3 z/ l' x& \
        // Volume setup3 C# z: D  p$ @, J* X. C2 ?' x* S
        //  0:Master
+ G" B3 {. k$ ^0 C. k        //  1:Rectangle 1: i/ ~$ g2 \. t6 A7 I0 `
        //  2:Rectangle 2
6 M* L' h. ~7 C. X4 i        //  3:Triangle
% c! A5 F3 Z: h# _        //  4:Noise7 q/ l3 J8 g) |$ [, n: ?7 j
        //  5:DPCM" d# ]) V/ e- g  b: U
        //  6:VRC6& P! q7 q+ Z; H6 k: l$ d
        //  7:VRC7& t& x0 {: P8 V# F; V; A0 m
        //  8:FDS" Y' C8 I3 `; @& Y: ~' c
        //  9:MMC5/ P3 z2 p' e. H+ a) T
        // 10:N106
' K; i0 R; q9 K        // 11:FME7
/ }2 w) F/ ?  B9 h! x& X        INT        vol[24];7 v5 ~! ]6 d. y' L+ N& r4 y, D. M
        BOOL*        bMute = m_bMute;
7 h! h$ B8 C: N4 _        SHORT*        nVolume = Config.sound.nVolume;
! s7 _5 k$ j) h4 \0 y  L( X& N/ v* l9 Q5 n  z/ _- ]
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
% H, c8 ^3 @9 l* o; M" o9 K5 F& c5 O' v% [: @
        // Internal' Q  ~% X5 ~, Z
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 `8 g! z( M4 j, l0 t/ {        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
. W! S( J- T/ Q' @, I4 ?        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;9 U9 g8 O% @; U" _4 M$ N
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 E. m8 n1 m7 c        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 d2 v0 M8 A; Y. ~' c, I
! Y, P" y7 x! s$ s        // VRC6
3 F8 c4 m4 U: P        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 W& y0 c6 T3 W! Y4 u& h        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; i$ ]3 T. K0 _
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& d* w+ \. c" e
- B! \3 j9 W" N
        // VRC7
6 ]7 n/ p0 H) p. T8 k" [# D' U        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
! [9 _0 w& N% c  }1 h; B% K  W# c, G- a: w9 l: s( c, R
        // FDS
6 b! d) c6 j: V' h        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;3 Z' L$ T9 a# A# M/ w. e

$ Y; M* l' Y) l- P7 m- n        // MMC5: y! [. e; J7 \$ I6 y$ T
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' P9 @4 W: \* Y' k1 B2 X9 c( Y4 o
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, G* m% e+ {' W. A' [        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* i; ^6 z( s, W; M# w6 h) m9 J
4 V5 K2 A( F. E* d. H        // N106* O& ?9 J" Y; P5 [
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* I2 e( Z5 k1 a% c
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 U( ^* S7 u1 o' W  _        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- Y2 d: \3 J( `
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ k& p2 A8 }! Y5 X9 a
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 s& P3 ]8 n* _$ L+ l
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& H2 Y% c( ]5 I# o4 p* a        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) U& a. a" ~: A- g
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 B$ v$ V( E; M5 m& _, \0 u5 ?% \) L! r. ?9 [% i# m
        // FME7
5 F! B7 G3 `& d. W) |        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ E, A0 T9 |" R8 B* d# R
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) z" @# @' e: J, h6 l
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ Y' [# O9 g; u8 S9 ^$ E  B4 @
. K; S! z3 ]% r  j1 |//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;- D& o% Q: U% S% s5 i, y, H0 Y
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;; q/ ~5 ~( y. Y' q) u' Y3 Y$ X
# j- T2 I7 \# a
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. r  X' o2 j6 H) _
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
9 l  A- s$ X' p  K* ~                QueueFlush();
+ q  b, t; a" E- F5 r7 b        }5 ?+ Y- J3 }, i+ ~
& U3 u. W/ W8 S" i0 Q
        while( dwLength-- ) {; |, I# e4 V( f
                writetime = (DWORD)elapsed_time;
4 a  \! ~8 y! a
8 V) K/ L: d3 u# l" O                while( GetQueue( writetime, q ) ) {5 ?- _$ Q* b) d( r
                        WriteProcess( q.addr, q.data );
( T5 D- P5 `% ]8 N: x                }0 y( {$ o3 d0 o& w

( K4 j8 V- M* j; G  N                while( GetExQueue( writetime, q ) ) {
  L) c) X. j' L$ R, q$ r4 c" m7 J                        WriteExProcess( q.addr, q.data );. J8 m" U. j3 S
                }! i" y& j0 Y. z( h

0 w7 {- L  V8 |  l9 t$ J                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! ]& w$ K4 p$ j
                output = 0;5 |  B. ^' ]: s
                output += internal.Process( 0 )*vol[0];
, [$ b8 Q, j4 ~. [/ _" [$ ^                output += internal.Process( 1 )*vol[1];
* B9 ]4 }# m0 w7 J7 U" g5 \                output += internal.Process( 2 )*vol[2];) Z" S8 t+ y1 l8 H$ c
                output += internal.Process( 3 )*vol[3];
& v2 E# K2 y/ j& c2 T                output += internal.Process( 4 )*vol[4];; C8 u! t% l) F. O9 c* T) g' h! |1 c
/ M% P9 ?) R. [  b/ h
                if( exsound_select & 0x01 ) {& k+ u+ G) W& E" F6 {$ [
                        output += vrc6.Process( 0 )*vol[5];! n) `- }& U$ A" l$ s
                        output += vrc6.Process( 1 )*vol[6];0 K8 U/ m" q( q+ V
                        output += vrc6.Process( 2 )*vol[7];
  a5 N# N6 B! m5 K: b                }+ i' Q* t- o' P0 V# M& A+ [
                if( exsound_select & 0x02 ) {2 |1 D% j# \! M1 t/ w9 X- a
                        output += vrc7.Process( 0 )*vol[8];6 a3 K6 q/ P: y. R
                }& k, v( t- i2 l  @# D3 w5 v
                if( exsound_select & 0x04 ) {( t0 Z% V# y- H  P2 n+ p  e7 \. p
                        output += fds.Process( 0 )*vol[9];
7 j0 ]# M, D! |* Y7 P9 E                }/ E; r$ U' X! H4 A/ b; t
                if( exsound_select & 0x08 ) {# {' T# E: [, N2 Q* {
                        output += mmc5.Process( 0 )*vol[10];
2 Y; I; S8 G9 u- Z                        output += mmc5.Process( 1 )*vol[11];8 }8 z0 z1 O* Z+ `1 \
                        output += mmc5.Process( 2 )*vol[12];0 U$ e$ _4 V; ~' X5 f7 i
                }
  x- ^0 m8 N. v3 G+ P: L9 S, l                if( exsound_select & 0x10 ) {
( F8 Z/ Q  v7 h# p. m/ J7 p                        output += n106.Process( 0 )*vol[13];6 U! s7 X' `( `6 |
                        output += n106.Process( 1 )*vol[14];; l8 ~, b7 ^/ q7 w
                        output += n106.Process( 2 )*vol[15];' }1 y) \% u: m0 P6 j9 I7 t) Z
                        output += n106.Process( 3 )*vol[16];
/ P8 |6 ~0 Y# e1 f% L9 T3 j                        output += n106.Process( 4 )*vol[17];
  Q. Z5 N$ v8 v; {                        output += n106.Process( 5 )*vol[18];
9 f! B4 s% w( |% {                        output += n106.Process( 6 )*vol[19];3 c: U/ a/ W1 j$ d( T& X0 ^
                        output += n106.Process( 7 )*vol[20];' d. m4 }4 o, g7 w% ~. c
                }
8 f' P7 n( O: ^$ K2 a                if( exsound_select & 0x20 ) {6 e( R$ |, V; @% p+ R$ a$ ^
                        fme7.Process( 3 );        // Envelope & Noise
' t- V* Y- ^! c  q. `                        output += fme7.Process( 0 )*vol[21];- |# p! \9 I8 [- c7 q7 m) z
                        output += fme7.Process( 1 )*vol[22];
; P4 a6 |) _6 Y+ Q" E* g                        output += fme7.Process( 2 )*vol[23];
6 l; U; |9 h( o# Q: @: V4 Q                }) [0 O4 y; M- s, ?; D
- i0 |+ z( v1 R
                output >>= 8;; a" D* E" A) ]$ s! ^5 |

" s1 M* \6 \2 V( D9 M# }( L' N! A                if( nFilterType == 1 ) {; j- Y" c; y0 a$ R) A- O
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  T- C/ R9 H% e1 J
                        output = (lowpass_filter[0]+output)/2;( x7 i* {, c" [+ r( v3 }: {
                        lowpass_filter[0] = output;
. E1 z8 W' P0 y( C                } else if( nFilterType == 2 ) {
/ Z& ^% U" O) {( [5 K8 o                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 T6 u& _& }1 e$ J4 i                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
  v2 `& t% p* N* P/ ^                        lowpass_filter[1] = lowpass_filter[0];' H9 G, |$ h! |( }3 d; L7 x
                        lowpass_filter[0] = output;
& T3 t6 c3 m% T, V  `4 O# D+ Q$ e8 u                } else if( nFilterType == 3 ) {
* P6 q, C9 h+ c                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)* b% y8 P8 k; k, x
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
6 I$ a' L8 i0 u! h; S, Q/ K% t  J                        lowpass_filter[2] = lowpass_filter[1];7 {# z3 E+ ^: s; k/ k: G& T4 y5 i
                        lowpass_filter[1] = lowpass_filter[0];
: l2 X5 y& @0 L2 m% M+ s% N; ]3 g                        lowpass_filter[0] = output;* a, c: r( h# i" k
                } else if( nFilterType == 4 ) {
) r% r0 V4 N3 h) D3 b                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
7 P! ]+ n6 X. s4 x                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  a# ~1 R1 C# h: E! b
                        lowpass_filter[1] = lowpass_filter[0];
, H  F$ h7 @, J9 J4 Y                        lowpass_filter[0] = output;9 U2 A3 D% P& L) z/ ]7 x
                }) D) q) L7 v7 s8 U$ {+ ]/ }: `

9 G( Q( U! k4 \" v% T( i#if        09 c  ?; r$ t2 |# T  Q( d/ r
                // DC惉暘偺僇僢僩, f  l$ l+ c+ a+ m8 J/ \
                {2 z. G  g6 |/ B* y  i5 R0 g
                static double ave = 0.0, max=0.0, min=0.0;
1 Y" z8 w5 h5 I5 l  E/ T' |& F. b                double delta;# A7 g! h; W2 U
                delta = (max-min)/32768.0;, g# c- B  V* r/ a. m
                max -= delta;. {. z& Z' O9 I' L- f
                min += delta;
0 X3 _" O2 S' r; l+ R! k  Z( F8 ^                if( output > max ) max = output;1 S3 |9 V1 o; C0 r
                if( output < min ) min = output;
1 b  J/ j( z* m$ ~1 ]' k+ ^                ave -= ave/1024.0;
6 b' }- D; Y9 M2 X                ave += (max+min)/2048.0;
$ L2 e" o! h! f9 w& z6 Z; E$ B2 T                output -= (INT)ave;; a# j: s/ f' |
                }6 Z6 y: o  f6 _: Y
#endif4 L' i7 ^! h/ `
#if        1
# v* B  o2 }% j7 e  Q3 I8 [6 c                // DC惉暘偺僇僢僩(HPF TEST)
' V4 n2 T7 v" c6 V                {0 F$ L3 V" {) C( L! i4 [$ Y
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);) O+ i  {: T: Y
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
$ D. M- ^0 z) F/ w1 Z9 u                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 ?; u: R# K# T) q) Z* S+ \
                static        double        tmp = 0.0;0 U- C2 x0 v4 x+ a" w) ~3 B; b
                double        in, out;# O5 f5 ^" |8 N% K: Q

; i7 T4 \1 w3 u  D5 k                in = (double)output;
3 R7 I. V  h+ a, j( s7 L& ~4 D                out = (in - tmp);
) n' Q1 N6 I- J, O                tmp = tmp + cutoff * out;# ]/ d& w1 H: x; b7 b
" f" O5 N5 |( @8 a1 A
                output = (INT)out;
) m5 ]' Y: |8 S% ~7 C: G3 @& ]                }
* s# s- G+ ~5 s! x8 `$ d' n, |$ J#endif9 E7 }% U' z  S6 K" u
#if        0
6 O7 K# a' R% ~, q( d$ T                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
/ Y# I4 k& G1 p: T/ c3 }                {! S6 g+ f' U! L0 [: ?; ~0 J
                INT        diff = abs(output-last_data);
! G1 A! R: |' J- t                if( diff > 0x4000 ) {
8 E- n& _- H- Q1 p; v0 `' s* [                        output /= 4;% i% u, V4 D( k7 p1 I  g
                } else 0 N9 Z1 G8 z1 u, [! @  y4 C
                if( diff > 0x3000 ) {
$ X9 N% j7 M. J4 a0 g  m                        output /= 3;
% M" g+ G  s. d; I                } else* [! _9 l+ C0 R1 i6 o5 ?0 |' M) ^6 K; ]/ {
                if( diff > 0x2000 ) {) `1 c% b5 E6 |# {' _1 S# [
                        output /= 2;
. U, ?& o/ Q/ V  _  L! [% [) G                }
/ x. o3 c" B& O% i& j                last_data = output;
( q$ g5 R: I+ A( l- A. U& A6 @                }# E* |* R; u4 V
#endif
2 l/ `3 a; }' h, n( t7 ~                // Limit/ A( c+ c  }3 u( B" {
                if( output > 0x7FFF ) {
/ y) }. J8 L) `( ^+ d4 M6 @/ A; n                        output = 0x7FFF;
, ~7 n+ ?, h8 v* K                } else if( output < -0x8000 ) {. w# e$ c1 ^, [; D
                        output = -0x8000;, x; O6 _' I2 W6 }9 {6 J: Q" G
                }0 a( e. Y7 d4 b
5 i; X. E# N) c  u2 N/ s& b1 [8 e
                if( nBits != 8 ) {
) W, N# o# j( O" `, p                        *(SHORT*)lpBuffer = (SHORT)output;( d3 x# f* P" h5 c! Q1 T3 V
                        lpBuffer += sizeof(SHORT);# ^' k0 [$ ]1 ]7 \. {
                } else {/ D6 Z, s0 A: l- J% W
                        *lpBuffer++ = (output>>8)^0x80;7 L; W* K1 P. e
                }4 M" |7 h: W9 ^! r/ T
% _* U0 d( t# |, i
                if( nCcount < 0x0100 )% K+ Q- }; s% g  o: k' R
                        pSoundBuf[nCcount++] = (SHORT)output;& @) v  M; z) H* g9 H
- y+ S+ H# r- s
//                elapsedtime += cycle_rate;2 a$ Q$ Y, K. a2 H8 [0 \
                elapsed_time += cycle_rate;" V& \" I$ `0 f
        }+ }* \& Z: _  ~& g+ L

1 v( m  W% [* K! Y1 O5 ^1 Y#if        1& ?7 {9 Q. ~( e1 z! ]: e
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
1 F; J1 f" G% ^% ?; `1 c6 Z                elapsed_time = nes->cpu->GetTotalCycles();
) C5 W6 {( W: Z* @. U        }" i6 {' |: \9 G% W2 W9 ~
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
) b9 b8 i3 j/ A" r" N0 o                elapsed_time = nes->cpu->GetTotalCycles();" k. a" c1 b+ m* P) M8 {! ?' G# C5 f
        }
8 Z; \, v! L1 D- T  h5 I#else
" ~% C, N8 r$ c# l9 i# \. ?, `        elapsed_time = nes->cpu->GetTotalCycles();2 m4 D0 ~$ o% O/ L
#endif
- X4 y( x/ ]  \  {$ \7 x}
5 K0 ~# C, K: Z6 L5 U
9 y0 K( _8 p' F  W# b5 M  T// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: z7 Z. O: U5 V5 M' jINT        APU::GetChannelFrequency( INT no )$ ~* p! u) ^5 U& }
{( w3 Z( V0 l( ]: [: \- O6 F, S
        if( !m_bMute[0] )
+ V7 u: t4 |9 }& k% J* o) B                return        0;1 t! _/ v- b! P% J: z' ^) I
7 c0 |7 Q4 q$ F* c& l
        // Internal
* h7 E0 a/ p; H9 \9 |2 T        if( no < 5 ) {
! a, a# r1 U6 H, r                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 g1 _3 J( Y% I5 d( g' p, L+ J* }
        }# s( p8 g9 @% {3 k8 v. k! ^0 |
        // VRC6' G7 z/ J. z. `
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 C+ U; W) l; f* f% {" p$ x
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! ]) O  F0 x- W/ p4 J4 H: e7 d
        }
1 t& G) b  |: T7 u& s        // FDS0 a+ o. X- G: K6 i2 T
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ `/ t- u& g3 O! b5 a; ]/ }' g7 |                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- h5 P7 S2 e/ L7 w        }3 n, ?: O& w* X) d
        // MMC5
9 V( T# H& ]( Y  ^2 m) E' J        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {0 m4 N5 E8 f+ d( c8 `
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
# w) f  x" n8 g2 i7 W0 u4 i        }
5 N5 I5 l+ j; u- B8 d6 Q8 {- f) V        // N106
) r) l! J  T. R& ^; e+ H; y4 s$ b% E        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {+ B$ s, t3 o- m2 y- c/ c
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;6 S; @1 J- Y3 K  W1 Q
        }/ y: E: |+ C7 S: Z# c: V" n+ `" x
        // FME7
+ c. u' C" Q+ a3 @8 ^7 p        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  e% v% A+ y# k                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, H! V; U; q" U8 n5 N+ e
        }' x; e* P4 I7 a5 p7 K
        // VRC7- D+ l# e) K) c$ \
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
4 j. d8 A1 T* f/ ?" f                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 v: f. k; H6 w$ E        }
0 L; G; F) U' H3 _! t# h8 e        return        0;& ?& c" f' F" k+ E' ?8 {
}$ v" B1 I0 R' B+ R6 U
! t6 r: g# C+ L
// State Save/Load
$ }% R7 J0 {9 kvoid        APU::SaveState( LPBYTE p )& s% j8 i& h7 {/ W
{6 A# K+ P/ K' |+ D
#ifdef        _DEBUG
* c* ]' _; p! ~+ Z# m# P( I* l2 @LPBYTE        pold = p;1 v4 F8 _( r2 L1 o. O0 R
#endif; y4 }7 z9 h4 d7 ]
: O) c) Y' m- P' a$ @: |
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& k7 B+ N/ ^& l8 p9 `        QueueFlush();
  I2 I9 c/ Y, [* R
+ q/ T- m& _0 `, A# d, p0 |        internal.SaveState( p );/ d/ n; k) p, l3 @
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: u4 E- t# J. F

0 Z5 \+ }9 |. t( v" V# [        // VRC6
; F/ k  i2 c7 q' P1 ^  D& _0 R        if( exsound_select & 0x01 ) {
) W, }+ C1 M$ a3 ~/ o                vrc6.SaveState( p );
2 }) n6 ?. [4 L/ u" y4 g9 h2 T! j                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 R1 X. O0 z9 Q        }9 z4 {' x: P, z0 S/ T6 `
        // VRC7 (not support)
! u, i$ D: u1 S" `        if( exsound_select & 0x02 ) {
+ ~4 W; i' e- ]                vrc7.SaveState( p );
5 T/ K" L7 n. O9 N$ W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 m; E- O( B, }  r9 |3 l1 C        }
0 M$ T% i9 n$ p  S) c        // FDS
1 c0 S: V7 x% b        if( exsound_select & 0x04 ) {( B8 m, j! n% d( e
                fds.SaveState( p );
" v: t+ L1 c9 _0 Z% Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. @6 |3 b% t' m! t# c5 \
        }
6 G0 M; `: X  z        // MMC50 V5 s! G5 \" G+ h- i9 x( L* h
        if( exsound_select & 0x08 ) {; D$ C" H* ~% O( n9 E" X6 Z
                mmc5.SaveState( p );, F0 V: m) h4 ~; ~( q) e: f
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& q7 K3 t& T2 x: g
        }
( @& N, @8 h, t        // N1062 s- H! L5 k# c( e9 v
        if( exsound_select & 0x10 ) {
  b; @- G9 G, `  c* z8 W5 R                n106.SaveState( p );
: ^: p& n( m+ Z: ~1 m& N                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* H) n+ g+ Z, j$ j* i/ }/ `        }' x. E! J, c& C0 F/ a3 T& v
        // FME7
7 [: R. Z# ]; A7 O6 }0 V& }( B) N        if( exsound_select & 0x20 ) {/ _7 p" b2 k5 o4 B
                fme7.SaveState( p );* p0 _, C, c5 n0 u; i+ G8 T; D
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 [6 T' @7 M) Q; k        }
; G0 G2 [3 l3 S8 T- a# C% b, V; V$ X) ]6 ?, B7 o4 i
#ifdef        _DEBUG& R5 c! b8 k8 ?, `) j% w' E
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 J1 o5 s- \, z# g# g* o
#endif- d" g$ G8 y1 v. ?1 q8 S8 Q
}
( U( c1 R/ B4 F. s; k7 x8 f0 X5 Y/ e9 X5 D( w2 V
void        APU::LoadState( LPBYTE p )4 ?$ x) N  |+ C7 e  S& q
{7 J$ Z* W/ z& |9 K: V. x& \/ Q4 Z
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡) Z% _. k- ]  P9 a. q* j7 a# R
        QueueClear();
  y5 l# a6 ~; y4 x+ P* d
& e3 G6 [" s/ g1 B, p        internal.LoadState( p );
8 D; F1 f5 V9 ?7 f3 D5 g6 x        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 o* j1 J+ c1 d. c
- [0 c5 p# w- j( ]. A        // VRC67 ?( z# P" J$ c" \  b
        if( exsound_select & 0x01 ) {. j0 \9 ^9 Q; X( B2 N9 Z* L
                vrc6.LoadState( p );
# Z; L: V8 G9 e1 Q3 Q) h! M; j                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" @  u7 \6 Y$ ?! Z( h  D$ O        }, v; Y* @4 z& c) V
        // VRC7 (not support)
9 V$ ~' x$ C  ]3 S# K) a        if( exsound_select & 0x02 ) {. E1 r3 m2 n+ U
                vrc7.LoadState( p );; ~& T! G: s* b# d3 h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' W4 g. E; J" u& K4 C  W1 C
        }
7 Q$ H! v: b9 C: _' W7 T: s        // FDS) h- ?" a' e5 [) U
        if( exsound_select & 0x04 ) {$ l$ a+ p" n4 `! p! f
                fds.LoadState( p );
; f, r9 Q" L+ R  S! X3 V8 Y* N                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 _, K. z5 l+ n0 a
        }
2 }3 Q" f; y) B5 h        // MMC5
" p( G" u  d& M7 F# [: X3 K6 z        if( exsound_select & 0x08 ) {) b# z! @  C$ A+ t* G
                mmc5.LoadState( p );- w/ u1 ^, F! P, I$ q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. |( c1 ?& `  v* F9 D        }
! U" @8 y4 s0 r! a  \        // N106
; C, P' w+ m8 p& o- d& n) \- C        if( exsound_select & 0x10 ) {+ i5 a5 ?' ]$ Q
                n106.LoadState( p );1 @" `7 C( u  P3 C. J( y( l7 a
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 o/ c7 f# H4 r
        }- {$ Z6 K/ {$ y: j7 X1 j$ `. ~
        // FME7
4 `9 l" I; c! j. s% y6 G6 v0 k        if( exsound_select & 0x20 ) {0 q- h" k. t/ P/ ~- _0 V! F7 j
                fme7.LoadState( p );
  Q+ p5 y2 L# j' {                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 U3 n- D, @! w& z! O
        }
) D4 p' s8 R/ V9 m1 u$ I: H}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
) b! R3 u/ v1 m可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
# r- i+ g1 D1 b+ z: W* Y2 i5 l感激不尽~~
4 X7 w% p" K( c( I" ~7 E3 X! }- A
恩 我對模擬器不是很有研究,$ w) p: ^6 l' I: t3 ?$ o1 H+ A* h
雖然要了解源碼內容,可能不是很困難," |' H( w# s& Q# K
不過還是要花時間,個人目前蠻忙碌的。! T% D6 c7 m' r# C  Y
+ M! @4 m0 d4 n9 |0 v
給你一個朋友的MSN,你可以跟他討論看看,8 z7 u3 Z( [& G+ y. y% ^
他本身是程式設計師,也對FC模擬器很有興趣。" e3 M8 D) T4 V2 W

! }6 M$ [" E+ {; X" x8 z% `9 EMSN我就PM到你的信箱了。
3 ^; a$ }# Q2 w2 T+ t+ A
0 z% f: l3 |3 {9 h1 M7 F) D/ U9 C希望你能有所得。

该用户从未签到

 楼主| 发表于 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 @3 f. }0 R5 n! Q% B! c) n呵…… 谢过团长大人~~

/ }: j7 i4 I2 G4 x( w6 _" a7 H% }1 ?7 W
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 ~3 U3 n% h$ P4 Y% r9 l团长的朋友都是神,那团长就是神的boss。
+ P" S3 t3 N9 {7 m) Q7 r. y* G
哈 不敢當,我只是個平凡人,& ]" S1 c6 X; X* }5 j
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
2 j/ |- V4 C& _- t3 T2 iZYH$ T' I7 t/ c! S' L, w5 I; f
QQ:414734306
' z' c  \5 O/ ?  KMail:zyh-01@126.com
1 d0 n5 K8 J, m* j1 I( g8 z! L/ d  s: f4 D2 |
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ) q1 i: r$ t8 t- Q5 u6 ~
再次对团长大人和悠悠哥的无私帮助表示感谢~~
' l. E$ u$ m. {& v
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-14 01:02 , Processed in 1.127929 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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