EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?( w) k3 L) L$ W/ V8 P3 |( r+ A# N
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. I1 j5 p8 v! c4 j
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 O( Q# I! Z* u* o1 a这里有相应的模拟器源码,就当送给大侠了~~
0 Y0 _8 Z$ y  O+ P7 _http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% H$ q8 q' h. P; L, _3 _' B" Q% }能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 i; J  o9 g# |4 X楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~6 T7 o1 ~) \7 h1 C) J
这里有相应的模拟器源码,就当送给大侠 ...

% X! C+ P  P. B) q% N. ^' r; l聲音部分(Audoi Process Unit = APU):
0 ?# P7 q' T) t3 Y$ v8 B4 h.\NES\APU.cpp
4 W' @% p& \, u% T.\NES\APU.h
  _, k+ O' i+ b2 B, U: _9 K
9 S+ a2 D# D$ j5 K  g7 \9 F
& Y7 T( k6 [, T, w影像處理部份(Picture Processing Unit = PPU):0 Y. m* G; C. z+ _, a
.\NES\PPU.cpp
: h0 }7 Y" z1 A.\NES\PPU.h$ G5 J3 q) {: ^8 g# j
- T" E0 q* l  E
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 B. e, U% e0 w! Z8 G" G
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ t; l8 v% z$ w" E9 w* {9 e
//////////////////////////////////////////////////////////////////////////
1 P; p( j8 m. T8 |: O7 }* e//                                                                      //( ]7 _  m2 ]9 f; ^7 h% }
//      NES APU core                                                    //
& W8 R" i" @, U/ A  h' k6 H//                                                           Norix      //
5 x" f$ l4 _( T' ]+ v//                                               written     2002/06/27 //5 q: R5 D9 t* K: Z, _. f
//                                               last modify ----/--/-- //: D: o- Z0 c2 F) Y! Y7 b' w
//////////////////////////////////////////////////////////////////////////  l1 q: H0 t8 m
#include "DebugOut.h"
' c% A- j8 N& V9 t: Q; V) p4 B/ u#include "App.h"2 B/ g. I# F  x* O, Q; h* X( L! l7 b
#include "Config.h". Y+ m' S5 M3 g+ {3 o5 i6 }& A

) }1 J6 B- \+ J0 ^, ^. Z#include "nes.h"7 |! O. G' Z5 a, o3 C/ y) y# `
#include "mmu.h"$ i; S/ c8 q, ?5 E- E4 X
#include "cpu.h": g: e9 Q1 f, q& o5 J5 ~6 s
#include "ppu.h"# {; X% o- P  Y
#include "rom.h"# m  [# v6 J' G. o
#include "apu.h"; I3 o& U8 u' t+ {( Y/ D

% D: ]. c# U7 b9 k: O2 h// Volume adjust
! v5 J; m) J$ L1 H// Internal sounds* Q% z4 t" B8 p! }+ V
#define        RECTANGLE_VOL        (0x0F0)
; `7 P% b0 H  x( i! o* g* J! p' }#define        TRIANGLE_VOL        (0x130)' {2 c( W3 |8 a, V
#define        NOISE_VOL        (0x0C0)
3 g" R1 p& i1 p5 d% C#define        DPCM_VOL        (0x0F0)3 F, }! s6 C! |+ l8 O
// Extra sounds1 x6 F0 I8 d8 P" p6 N0 b' G5 t
#define        VRC6_VOL        (0x0F0)
/ Q: {* K0 ~: S! `2 R8 Z: B8 p#define        VRC7_VOL        (0x130)
$ o1 T1 Q$ D6 ]" b0 ?#define        FDS_VOL                (0x0F0)3 |! K5 }* y& N2 z2 _
#define        MMC5_VOL        (0x0F0)" x, A# Z! W+ k8 A0 e1 j
#define        N106_VOL        (0x088)
8 ]0 U% D" @' @$ T& m8 q' C1 \  w#define        FME7_VOL        (0x130)5 C3 r5 Q6 e! A% @) t# F
' f4 d5 y3 q; e- g
APU::APU( NES* parent )
- s7 M$ L4 N6 J/ f5 |: o{" C4 N5 R$ M3 Y  P( m2 |( C* [; z1 o
        exsound_select = 0;/ Z. E2 \: a9 f5 N! e
) Y7 ^$ d3 c% j6 G
        nes = parent;$ l5 Q1 q% i0 a, ~" E
        internal.SetParent( parent );
1 T' x) f% I% L; K3 ]  v9 d7 {  l4 u8 t. w
        last_data = last_diff = 0;
4 q# @+ Q: N& D9 I7 ~8 Y$ C
, T) T# |0 {" n  R' |        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' r' H% Q: M$ g4 x9 D5 s" a" U/ j6 G3 \! W
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, ?- p8 E# _( J# |  p& d0 @
        ZEROMEMORY( &queue, sizeof(queue) );
- M' x, o; e) J/ z/ a4 O0 Y* s5 ^        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ w/ n" R0 u- R6 w  r# N

! b# Z6 C  b% K% u$ e4 }1 q        for( INT i = 0; i < 16; i++ ) {
  O/ q) J8 `/ Z9 C1 h+ h                m_bMute = TRUE;& Q$ J. f% g* X5 m
        }
4 Q% k- G' I' _; @0 t( C}
' V4 y- r( Z( ^$ k0 v0 N* f" T$ |3 b3 G
APU::~APU()7 A$ V; h$ `7 J9 |: p
{
/ C* C) k1 n. |+ O& k}
, f+ Y) B. w3 [) X: ^, b3 d6 A
4 R- u" q) I5 o8 Ovoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 O1 o0 b7 H2 P. ]+ a5 W+ S
{
3 Y9 S- _) v; W! S+ z3 K        queue.data[queue.wrptr].time = writetime;
4 X* z6 W9 v5 H7 k% B; R        queue.data[queue.wrptr].addr = addr;+ v& Q* f1 q' Z$ ]6 E
        queue.data[queue.wrptr].data = data;
5 ^6 z, n$ C) w% I. G        queue.wrptr++;
0 l: ?9 E1 ~( m$ [/ q0 G6 M( M; b; ]        queue.wrptr&=QUEUE_LENGTH-1;/ S2 o7 W$ d1 ?& t, S1 O0 Q: g( ~
        if( queue.wrptr == queue.rdptr ) {
# C. C/ m' G3 C; E( O                DEBUGOUT( "queue overflow.\n" );
+ e# }6 ]" r$ U# ]6 Y1 f' S        }
5 F% |1 h8 d5 C}8 G4 e8 I+ `, G6 r; h

0 e# M4 K& l# z0 {! p  H1 n8 _) pBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )3 P& T# j- N! o+ E1 `0 L
{
! n3 l* A9 [: h1 V( Q* a        if( queue.wrptr == queue.rdptr ) {
( Q8 T3 u4 ?+ W2 o                return        FALSE;
" I( A$ v+ b6 A" n4 C$ a" o/ d2 `# Q        }, u6 L+ a/ _- ^5 S; ]
        if( queue.data[queue.rdptr].time <= writetime ) {; @& ?6 C9 D7 |: h& e
                ret = queue.data[queue.rdptr];1 X3 n! n! W; f
                queue.rdptr++;/ c) l1 J, Q5 h6 Y  ?
                queue.rdptr&=QUEUE_LENGTH-1;
; X6 B% |2 J; y# b9 h* i                return        TRUE;
2 q. A, e1 X9 k. @8 t/ d# \        }
8 S9 S6 u; f% h$ U! v, D2 p# U        return        FALSE;
/ I2 n; ^0 w4 u+ U" ?) |}
8 V$ X7 i5 F, C
4 |2 i3 _9 p- Vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
0 l9 W- ~: W* \3 G( M. T{9 X" O8 w) H/ r/ x9 ?* o; I# J2 V
        exqueue.data[exqueue.wrptr].time = writetime;
4 c8 v1 o; p1 f3 C/ T        exqueue.data[exqueue.wrptr].addr = addr;% F  y( a1 T" d3 x
        exqueue.data[exqueue.wrptr].data = data;
3 _# d7 \3 a4 C0 @8 g6 X7 g  e        exqueue.wrptr++;
+ ]0 r: h0 f4 O3 R1 x        exqueue.wrptr&=QUEUE_LENGTH-1;
- }  L+ J& ?  s  r9 T0 O2 u        if( exqueue.wrptr == exqueue.rdptr ) {
0 S' k$ w" `* Q  |: o                DEBUGOUT( "exqueue overflow.\n" );3 a6 K+ e, s8 j
        }4 t/ `4 w" k, d% y
}* ~- D7 }4 \+ w. R

# O/ A$ J3 Y2 iBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )( q8 F% b7 `$ L& g  ?! Z9 d+ _
{
" l' K# Q: T8 P        if( exqueue.wrptr == exqueue.rdptr ) {
5 b( b* }" L0 M) L1 @# h                return        FALSE;0 L( Z6 @( Q( w
        }
: b) p% k9 x) V* L6 n% {# F: `; B        if( exqueue.data[exqueue.rdptr].time <= writetime ) {6 J% I. @% U' A( G$ k
                ret = exqueue.data[exqueue.rdptr];4 W, Y" x( S' g& s% ]
                exqueue.rdptr++;
9 w. Q' h9 j/ E) V$ a4 o1 }* H; C                exqueue.rdptr&=QUEUE_LENGTH-1;$ t: L6 U0 B( p: v" E+ B) y. Y* W$ ~
                return        TRUE;6 d; U/ a* Q5 i4 f/ J
        }3 O4 W  Y4 c; x6 a
        return        FALSE;& |4 M. Q2 m" M* p# ~
}" M7 U( {" Q. h+ c. ?) _" K

+ \2 ?4 S5 F2 S6 V. uvoid        APU::QueueClear()8 U% G0 z5 y9 Q, m
{4 G" V/ S# Y# C& o% p  @: K
        ZEROMEMORY( &queue, sizeof(queue) );! |9 v7 ~4 B! K* E- {" @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  K1 N$ t& N6 G* }
}
+ X" W: v( w# p& b4 t' \8 d, n) R) O0 B
void        APU::QueueFlush()% {  w1 H0 `' Q
{
9 s; d3 `3 m* K+ O        while( queue.wrptr != queue.rdptr ) {
" C/ {- ~( O. v1 w! ~                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
9 L4 j7 t2 L  C& |  D8 V                queue.rdptr++;. _8 D8 a5 S" K3 D
                queue.rdptr&=QUEUE_LENGTH-1;4 |% z7 B7 `3 }5 @! L& g% {
        }" F4 h$ i. S9 V0 u

9 l+ j6 P( F  z$ g# W( D. r  t        while( exqueue.wrptr != exqueue.rdptr ) {
& X8 i- F6 I, Y" F  ?8 a4 k. ^                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 Q9 h1 e: a" d( d. ^$ \& [
                exqueue.rdptr++;8 _0 s, n# A+ y! h( i, D
                exqueue.rdptr&=QUEUE_LENGTH-1;
  Y2 f, e4 ~+ H2 o2 H  K* d6 p" J% c. V' `        }0 a, ~- ^' _9 S8 D* r
}: [: h/ K4 M3 G; R3 @$ L2 o

% H" J! ^2 R* ~8 Qvoid        APU::SoundSetup()
1 r7 @4 _4 q& L) A' V{) d4 d. R  A6 u7 B& K3 L+ X! t
        FLOAT        fClock = nes->nescfg->CpuClock;
* u  O/ O  o+ C: c$ U3 |        INT        nRate = (INT)Config.sound.nRate;
& V( {) [3 ]" ~        internal.Setup( fClock, nRate );
, v6 P: a, p9 Q/ x        vrc6.Setup( fClock, nRate );
+ M( S& k6 Z! c% R1 O% \        vrc7.Setup( fClock, nRate );# z8 s! L' ]8 L; D; D% K
        mmc5.Setup( fClock, nRate );9 |# Q+ L5 E& ]3 H3 J% E3 V
        fds.Setup ( fClock, nRate );8 [) c( a7 q5 f' t4 u
        n106.Setup( fClock, nRate );; p' \& Z' [) J3 W
        fme7.Setup( fClock, nRate );1 l/ K4 Q$ m; K0 O% u/ y4 c7 p
}# O' E6 \, c8 N7 b  f; O

2 E5 ]/ p0 W( Y% `7 z$ o4 `void        APU::Reset()9 a/ |3 [7 `6 |- B6 T; O
{
/ l% j/ W: j7 o/ o$ ?5 B; N        ZEROMEMORY( &queue, sizeof(queue) );+ y+ S! k' s6 ?5 s" j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 E6 Y3 w3 i. W% {: C

) D. d' n; N+ y        elapsed_time = 0;
) }2 T% L, w8 _8 v0 k
7 Y* ^9 w3 k2 j" {( {        FLOAT        fClock = nes->nescfg->CpuClock;
2 `/ J) W# `7 l* H        INT        nRate = (INT)Config.sound.nRate;/ ?# Y& r0 \+ _3 m5 c/ ~
        internal.Reset( fClock, nRate );# \; K, A1 {' J  n% t" M
        vrc6.Reset( fClock, nRate );& w  E& E) [; |5 s
        vrc7.Reset( fClock, nRate );
8 g: m" _& @0 V" I4 X+ b* I5 e        mmc5.Reset( fClock, nRate );" W  e# X/ w6 h
        fds.Reset ( fClock, nRate );2 d7 W6 c( E) c) U9 N
        n106.Reset( fClock, nRate );
" \2 k: b+ L2 ]8 {6 @, W0 v8 w2 _  c        fme7.Reset( fClock, nRate );/ z% Y8 Y6 c/ m5 D  F. [8 e1 e

  b2 o2 E7 D+ W5 Q        SoundSetup();
. a  M0 W3 h6 s# y( |}$ C% w! b7 v! k) ^" O" H

1 {4 p6 u, l" Y# C: kvoid        APU::SelectExSound( BYTE data )
6 m, G0 k  W; M" @  o{
0 J. v6 J0 Q6 q+ J$ ]. J, A  B% y- k7 o$ y& e        exsound_select = data;8 z% k9 t3 Z  R/ n0 i* H3 F' [
}
, T+ T8 J$ v$ L. z) ?+ P
/ M( c# y" `+ |: hBYTE        APU::Read( WORD addr )
; l/ R/ }  Q7 Q9 E" [% F% z{0 m( u8 [) a2 D2 c; X
        return        internal.SyncRead( addr );. L7 C/ o; C$ r( t1 W4 W
}
& G6 A/ y0 N& N! O1 O9 o& F4 \2 R* H0 o* S+ j8 j+ G
void        APU::Write( WORD addr, BYTE data )- @6 ]/ ?& T* m
{
4 S+ h9 N: \" K% ^8 m        // $4018偼VirtuaNES屌桳億乕僩3 u" `; f: x" c$ @- X$ }
        if( addr >= 0x4000 && addr <= 0x401F ) {8 v" J9 ^! d9 h8 ~% b0 ]
                internal.SyncWrite( addr, data );
- I9 R; f  F  e% v  u& I- @1 y* u                SetQueue( nes->cpu->GetTotalCycles(), addr, data );6 u! n; s" e, j3 L4 C/ B* A4 l
        }: `, p% ]' U) X/ y. _
}
  |% x' {# }& a4 {% L6 E. n4 D
8 ]- H) m, C4 r# R! Z/ [BYTE        APU::ExRead( WORD addr )
* S0 g# }( D6 D  e# Z1 q' `{% {. u6 x/ t. N+ E8 Z
BYTE        data = 0;! ?3 ~" X$ d2 S6 X5 \6 s% {/ x3 j

7 U" [7 ^# K8 h6 P# @        if( exsound_select & 0x10 ) {
1 B9 y9 d2 s1 O" p- T0 @  }                if( addr == 0x4800 ) {
% ]$ }5 q9 K, P) k                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 n# A% k2 ], \$ w) }
                }2 p' Y! w' |% G7 P9 g
        }
" _8 N: z  o, C& I7 C/ M8 ^        if( exsound_select & 0x04 ) {8 n; d7 `$ S) B& J: j- w
                if( addr >= 0x4040 && addr < 0x4100 ) {2 `0 f8 b0 N( R; N- Z7 {  I
                        data = fds.SyncRead( addr );
  V( U. x5 z+ k3 u9 _) K5 L                }) D7 X6 h) J! n" B( h- m
        }! _  X  [/ a6 s* O! [% J% g$ r' y* B2 s9 r
        if( exsound_select & 0x08 ) {, }! U* ~  b+ q3 r
                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 j, P7 ~0 [2 w                        data = mmc5.SyncRead( addr );! H( Q, ^5 g; @9 S8 \( A
                }6 M* g1 i( G% }/ _6 B& @
        }
. D6 J+ s' r2 [/ V4 C5 b& k* D# w
: q; A' o3 y# ^4 E- t/ s; A) \7 ~) b        return        data;
. b: P2 `% D9 W4 O1 l}
* l  w9 J9 j0 K; S* h/ ?
' y$ q6 E* z# S; {3 p* O) Kvoid        APU::ExWrite( WORD addr, BYTE data )
: [7 f3 P3 W! Z{7 |0 Q% O( U+ f" n/ H" R: r" P' I4 h; d
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
$ X9 }# W5 c' u3 p+ _+ L" D3 Y/ i
. U9 a' Z* X% d1 P4 d8 p: f8 O        if( exsound_select & 0x04 ) {
% U" k8 ^8 u0 E                if( addr >= 0x4040 && addr < 0x4100 ) {
  e2 E. U' i8 \                        fds.SyncWrite( addr, data );0 }  A% A, q6 W2 W2 ]% ~
                }& `5 M; Q) O' y5 Y+ Y$ V9 X
        }
! T8 Y# ]: X% S7 v
, ?5 O: E5 h, c( o: T        if( exsound_select & 0x08 ) {% D% O& l9 l3 l% \$ @
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ a9 W% e2 L1 r) t) p. S                        mmc5.SyncWrite( addr, data );/ U+ M7 h9 v$ J' I- L& u7 v4 E
                }
5 I, U8 Z1 ~+ s- U  `1 G        }. E' C8 P! g+ B
}2 h- {, J) E! a8 g  K
2 S" H, j; A! {4 b8 u0 Z# q
void        APU::Sync()
# O  u5 Q( L# @# @{
0 S7 }2 M  e: w' G+ b# f1 \9 }# v}
+ A% x- Q3 |8 @6 u2 U' V/ d- ]. g4 J! O* I7 q/ @
void        APU::SyncDPCM( INT cycles )* ?" z. a; Q) f( S$ @- ~  h1 g
{5 U2 p4 A* N$ Q
        internal.Sync( cycles );, f" d% s7 ^$ e4 u6 I% j- i* b. r

" P7 Z$ a2 ?! l4 w        if( exsound_select & 0x04 ) {+ m" B/ Y4 x" s
                fds.Sync( cycles );1 M) E9 f) [- ?/ z4 f: ~* @
        }
* M: |8 A! ^" F/ p/ x        if( exsound_select & 0x08 ) {
; E- U8 S; u! p                mmc5.Sync( cycles );0 e: w) ~# F5 m8 q0 \6 p* q0 y
        }  L$ E0 ^. ^! Y4 y  L3 C
}2 h3 j/ K8 V6 |  z! c; i2 B  y) g7 n

$ l% l# B  Y* u( nvoid        APU::WriteProcess( WORD addr, BYTE data )
- G" ~# o. i0 y& j" b% i9 ^{
: z8 ]4 c. U; @6 H$ c# v        // $4018偼VirtuaNES屌桳億乕僩2 |" W. ~/ t7 C
        if( addr >= 0x4000 && addr <= 0x401F ) {4 y4 S! e8 f8 b8 Q
                internal.Write( addr, data );
& d7 U, Y& H  w  e! p        }
* U! n/ d6 O4 V/ F$ M}5 b$ F& w2 l9 s  {0 q) Q6 ?: {+ A
  w  V+ L0 `1 B2 G8 x( L" h
void        APU::WriteExProcess( WORD addr, BYTE data )
( G5 ~' D4 g& L7 y{. s  F+ y# Y  Q# r$ m1 a( G( N' c8 P
        if( exsound_select & 0x01 ) {3 R- F) n0 y& C! l  W  w" [' \6 m$ V
                vrc6.Write( addr, data );
- M8 M) o2 v# D, M        }
( b2 u! \; n; `. ^* y        if( exsound_select & 0x02 ) {+ D: Q' d" a( M. U( E! V5 ~
                vrc7.Write( addr, data );1 _" z; t0 l+ l4 R
        }2 u2 n4 W' h8 X. q8 f3 v/ P+ G8 w
        if( exsound_select & 0x04 ) {
0 ~! F# A( V! S8 B, L" a5 e                fds.Write( addr, data );9 U0 F4 r- O/ u, |8 n$ d) o
        }
9 k/ ?9 x* W0 U% ~- }6 {        if( exsound_select & 0x08 ) {4 H% M2 [; n6 H  V
                mmc5.Write( addr, data );
9 r4 N2 P! P) Q1 z0 z# l) V: R7 u        }
1 E% N6 s# w9 L  Q, I' g        if( exsound_select & 0x10 ) {
$ v* d" I; t- W% o& D1 [                if( addr == 0x0000 ) {4 w# T& C  O+ e- S
                        BYTE        dummy = n106.Read( addr );# O- L  b% f5 Z( ^+ ~
                } else {
1 ?1 i6 p6 ~! ^4 ^! u( r) a- f                        n106.Write( addr, data );
) t  x7 R+ K, g* D# j* Y                }
! `7 `" _# ]/ J+ x& I3 S        }
) Q: T9 L1 P; W( l# j3 O( R        if( exsound_select & 0x20 ) {
+ T  h6 I1 E1 ^$ Q' a$ w                fme7.Write( addr, data );- y* [0 Q  F. Y) B2 d  X; |" l- {5 W4 U
        }8 ~7 i0 Z  b9 Q9 N
}6 R& y% m- U8 O3 Q
0 V" e8 Z( c' ?" j0 ?; Q: c
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ o  u- l" }9 u" c$ ^{
7 J4 i7 |1 S6 v7 \. J( G: EINT        nBits = Config.sound.nBits;
# R0 S* m4 i: O' U6 H. tDWORD        dwLength = dwSize / (nBits/8);
* f: D, o( X) H1 g! H5 kINT        output;& N% y& C% y$ Y2 S. T  b7 @' V7 }
QUEUEDATA q;& C- e3 {# [/ |$ ]0 W& y
DWORD        writetime;
0 ?+ v9 a% Z% @9 Z( G& O" m$ L% b- I- B& d, S' Z2 e5 C- F; ?
LPSHORT        pSoundBuf = m_SoundBuffer;
* K2 _+ y! ~  M( |INT        nCcount = 0;+ B5 h  l5 s: o3 M8 T- }+ `8 R# g
% y/ |/ q, H) {
INT        nFilterType = Config.sound.nFilterType;  v& }8 n) N. Y4 J' j8 j' ^

) B4 @- |+ L' h1 f" ?. q        if( !Config.sound.bEnable ) {
. e9 E5 _) j! r                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
% K! M3 ^: s/ [$ r* r. J5 w7 H                return;( H" y/ U+ w' [1 p5 P9 P) `
        }
7 n& [. |* \4 Z7 @6 J8 I% b6 l( I& o- y- V% Z: c  ^4 }
        // Volume setup
! m+ @5 D. {* T$ i  E! B* v9 W        //  0:Master
9 q' o' z7 u) a0 h        //  1:Rectangle 17 U4 o6 N# c8 V* D' N) O
        //  2:Rectangle 2
8 Y! j! N* G: `9 O4 G9 P8 S        //  3:Triangle& G- t- G4 w9 x6 X' |
        //  4:Noise
, X2 C  `4 U1 P9 Q  Y( T) R        //  5:DPCM
" ]4 `8 S0 J# R& Y+ ]( f9 T( Y4 B8 C        //  6:VRC6
2 f/ `4 x6 d: i        //  7:VRC7
8 ^0 s9 v: t' j" x. c( h) Y        //  8:FDS
9 z( _5 S5 X# E: O/ R9 L& V9 |1 T0 q        //  9:MMC5. c/ y! \) B; V* u% S! D( U
        // 10:N106
( Z! w% z5 W5 F1 E" Y        // 11:FME7
, K7 y" C7 [8 ?' N2 H! @        INT        vol[24];
( l% F6 ~# Q5 V- b, J3 f" T7 |7 M# Q        BOOL*        bMute = m_bMute;
5 F; n, T9 X( ~        SHORT*        nVolume = Config.sound.nVolume;
6 ?6 b7 v5 \. y- S# d9 c) D
; D, X  U0 |( u4 o        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; j; @$ r% A8 G' W: w; a

/ L6 `+ Z9 g4 B" X  ]5 b+ _- m5 x+ {        // Internal% Q5 }4 W: f1 V8 A, U$ H
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
; b  G; v, d# ]8 ~        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
$ ^9 Q1 c  K4 \/ V7 C: K# U        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;; |1 L  m8 t! K& a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
! v! }8 i' j$ m/ m1 ?% [% Y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;/ y) w( P# X! a9 ?5 \
# _  l* G9 J5 J1 M
        // VRC68 E! w# Y: [6 z3 j6 ^# k% i2 i
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 ?. p9 q; `- `% p, i' I) I! M. [
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 }: K" ]5 ]; \' n, n0 R
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( y& V; m3 Q0 P' e8 m6 a# v
# S. Q  G  G# z+ D        // VRC77 U% q/ a4 s: q" M/ Z" A
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, J& `7 _  W* Z& T0 ^! a8 f! f! b" w/ k, c
        // FDS
6 Z. L/ ?. [8 O; A7 k        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;6 O: `, l; F4 g
0 m, O( Q6 W9 r% y; H/ Z3 d
        // MMC5
% b9 v6 G/ O" z, }& P' @6 i% g" W        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! f" x' P! m4 K, t& u
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 Q: P% w, \6 L" u" u/ N
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! U& n! s- H8 D! j8 L5 N/ F
5 e* S4 p, T4 e6 U5 K8 ]        // N106) f: p5 ?* V  d" a2 s& v/ Q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- W6 A* \" A+ \1 W0 h9 E
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 R/ }8 s( u" c* V! s% E3 E) K        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 p) q7 i9 y7 v
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& s3 j) a$ W# C( e  K! M
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% a& O1 j" ?  c        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 ]! r  V4 m0 [4 Z$ H, F& G4 f
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 I+ ]3 [2 a8 l+ E2 C9 b( ]& U" ^$ ^
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, Y: q. }2 a2 X$ U4 q

3 `) B" M+ Z4 a6 F- G& c        // FME75 r$ `+ l2 j2 M% C- G8 w2 M8 ~7 o
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 Z) O) o2 T* \: o* s        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* z6 I2 r' f8 R- c3 A        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) e5 l7 ~8 \3 |$ E' C: {/ q9 m
+ f3 M4 e' g5 Z9 f/ x
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
4 h/ F) L# t3 Q0 @        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
& B7 B: k" t* l+ |9 T. W
1 p  @7 t/ X6 ^: {4 k4 t$ c        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
) l( d* j; U; b" E! w1 V1 e        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
$ n. e0 P7 Z6 q$ b4 c                QueueFlush();9 ^/ F: o8 Z& x# F" R
        }
8 i) @3 l# R+ r* B5 H: P: e% O4 G1 ]4 _; a% L
        while( dwLength-- ) {
  H6 Q$ k2 a' n7 k! {' B, F/ w                writetime = (DWORD)elapsed_time;  R2 r. X/ }' O" @6 D" C8 K

# F9 W; f, f) X3 m/ y4 d6 r                while( GetQueue( writetime, q ) ) {* x. V0 P: Q0 I
                        WriteProcess( q.addr, q.data );$ Z. `. c' V6 G5 z. |! b# z
                }& B9 m4 G: E. U  c" ~

- u' M. D/ t  a                while( GetExQueue( writetime, q ) ) {
, p2 [. w& B4 ^( \                        WriteExProcess( q.addr, q.data );
8 B6 U9 `3 n5 B# p; {  H( K                }
' N- X( j& n' a9 k: |4 [
' m/ S1 q3 X1 N/ W9 m                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 U  J  D- \/ c, w5 Z$ W4 l                output = 0;
' a$ _, V: A# u, X                output += internal.Process( 0 )*vol[0];, s1 P5 P5 A# ]6 l- Z7 W
                output += internal.Process( 1 )*vol[1];1 U8 Z. _) S/ r6 i( t& n/ ]* L1 P
                output += internal.Process( 2 )*vol[2];
* I7 G3 |0 j, V1 g0 I2 ^                output += internal.Process( 3 )*vol[3];* w* n1 e) K# @$ n2 @1 b5 j6 S
                output += internal.Process( 4 )*vol[4];9 g1 K6 G% N  t5 w4 D) d
* X* u+ O# F5 B4 l' w) q
                if( exsound_select & 0x01 ) {9 c8 M6 {5 M0 o& P( a3 f
                        output += vrc6.Process( 0 )*vol[5];! k" k' C1 n4 M( z: n
                        output += vrc6.Process( 1 )*vol[6];2 q4 w. m! F0 d# b
                        output += vrc6.Process( 2 )*vol[7];/ y) P- B1 {( }% u! v
                }$ L% V# S6 J9 J/ s$ z
                if( exsound_select & 0x02 ) {" ~; Q0 o. \  _/ i5 q! ~
                        output += vrc7.Process( 0 )*vol[8];' y  s6 D' p5 u- p% q9 s* g0 |3 T6 T
                }
. x0 ]$ z+ V2 T* T/ h+ {% F6 e% g                if( exsound_select & 0x04 ) {* P! P1 n4 K6 p8 ~' W0 w* D
                        output += fds.Process( 0 )*vol[9];
6 X1 q  N' g" n+ T                }6 d3 d; H4 T4 K) {2 B
                if( exsound_select & 0x08 ) {
  H$ U7 I# R# A                        output += mmc5.Process( 0 )*vol[10];
$ a, e. k5 f# ^* A7 F" f4 F                        output += mmc5.Process( 1 )*vol[11];7 y& X  G# N7 c! W5 O. ]
                        output += mmc5.Process( 2 )*vol[12];. h. q* Q/ A& Q$ Z3 R4 G
                }
+ `7 J/ ?0 E  `8 {& C2 |                if( exsound_select & 0x10 ) {
8 r8 E0 h# {# x0 V% D                        output += n106.Process( 0 )*vol[13];
. i/ v  O5 d5 ~- @, h                        output += n106.Process( 1 )*vol[14];
) ~$ b7 j3 A9 X  o                        output += n106.Process( 2 )*vol[15];
' J* B# R" u5 a$ s) w% l                        output += n106.Process( 3 )*vol[16];7 M, E- X+ b, w/ G8 p9 P6 Y& D
                        output += n106.Process( 4 )*vol[17];0 T/ }4 t/ K7 N  n
                        output += n106.Process( 5 )*vol[18];( o! C3 K) \4 A
                        output += n106.Process( 6 )*vol[19];& Y5 V- L3 k8 _
                        output += n106.Process( 7 )*vol[20];" }' ?7 t& v' a# g
                }# \- \8 x+ }8 O
                if( exsound_select & 0x20 ) {
1 j) R; F9 O6 [: j. \                        fme7.Process( 3 );        // Envelope & Noise) k9 h6 ]7 z5 i# a
                        output += fme7.Process( 0 )*vol[21];
$ a# r* K0 A) I1 f4 f                        output += fme7.Process( 1 )*vol[22];
: ]: g) T  \# i% A* G$ [& e( \                        output += fme7.Process( 2 )*vol[23];
/ Y" |! h) a! T2 e( x" O; R& }                }* @6 B2 }! g) w8 o4 u& S7 ^
! C0 u' J5 m6 Q6 d! F
                output >>= 8;6 {" P; x; X- q

; A( i! L5 `: w                if( nFilterType == 1 ) {
7 p6 |2 d+ @9 j) J6 Y6 e                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)% o: @+ m: h. n- }
                        output = (lowpass_filter[0]+output)/2;
; t( l6 K/ C. l$ F1 y2 x3 R                        lowpass_filter[0] = output;
+ o) t8 u9 o$ }! G                } else if( nFilterType == 2 ) {8 x* \" e3 i9 [/ ?, X* A; K2 a! ~
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- `5 O! [" f. I/ p4 f
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;$ ]9 T, ^% F( c
                        lowpass_filter[1] = lowpass_filter[0];, I8 x9 p8 O' S* U5 [7 m
                        lowpass_filter[0] = output;/ E; g0 @' l+ [- U, H5 o# a
                } else if( nFilterType == 3 ) {" ~2 {* ~/ O3 ]; z# R
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)7 s1 b4 ?! e7 c- |; {( O
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;3 @" ~' g* t+ L  y
                        lowpass_filter[2] = lowpass_filter[1];
( Q6 ?2 N" ]. ~' {( C9 F7 X                        lowpass_filter[1] = lowpass_filter[0];
& [5 A# ^% j! T# `$ X$ N1 A                        lowpass_filter[0] = output;4 G. r5 Q$ w7 m, U
                } else if( nFilterType == 4 ) {
7 \* s/ |" h- ~/ G) |/ z0 G                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
% E/ b- W4 x; P                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
. t# g/ l* K' Q% ]1 J                        lowpass_filter[1] = lowpass_filter[0];
1 N/ f" C! ?4 }) }- v1 l                        lowpass_filter[0] = output;
5 |$ g( ]4 K; P; Z/ m' ]& A                }
; h: V5 P8 y8 \& t/ V
& w6 ^+ e! u! z* h#if        0
2 y- l9 Y- B) P% h6 C) ^' K                // DC惉暘偺僇僢僩
% n& u, M9 D; }+ n                {
$ U& i6 {  `( ?: x: _( l                static double ave = 0.0, max=0.0, min=0.0;
: M3 C, }* N# K- A                double delta;$ J+ \8 ?# O2 R) ]
                delta = (max-min)/32768.0;0 @- Z# g3 I9 M7 l3 }: x' i2 `
                max -= delta;
" m. v' C  X8 @6 [8 l! X$ E                min += delta;
* @% l2 u3 U4 W                if( output > max ) max = output;0 Q7 [  w7 o4 o
                if( output < min ) min = output;8 J7 z7 ~4 V3 k8 ]( y* j: B4 F/ ~
                ave -= ave/1024.0;# L# J! A6 f$ w6 x/ _0 g6 T! q
                ave += (max+min)/2048.0;6 `) |7 B6 y* {1 o& g" L
                output -= (INT)ave;
. J# L; M# N+ y0 T; w! v; Q                }- A+ n( m' s9 r0 O
#endif3 r, W& ~8 O! c. ?5 F. H9 j3 L
#if        1
6 Z9 ~' y. n5 O4 ^( G$ j                // DC惉暘偺僇僢僩(HPF TEST)9 s( _6 A: O2 }' Y' q  ^# b
                {% R2 j9 i4 D% R' Z
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% D" ~2 B" l/ Y9 l2 g, k
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( b  _) p$ t2 T4 S! G8 m& J6 q# H                double        cutoff = cutofftemp/(double)Config.sound.nRate;
9 m: Z/ F7 h+ ?# Q                static        double        tmp = 0.0;
8 _& k) B! v2 ~                double        in, out;
* y+ J8 g8 Y8 X! n3 a" [* C) B0 z) u
                in = (double)output;
. y- @0 y) R- z% ]8 g                out = (in - tmp);; [6 v) A9 l7 E% w6 u3 [
                tmp = tmp + cutoff * out;
+ x( \3 h8 |! p, D3 O- z; t
: Y  }: V- T: I7 V                output = (INT)out;  {% k4 a# [5 F6 L# J0 L. M
                }! C9 i9 S# Y, {) N( Y5 {  C! o
#endif7 \1 r3 y. ~* l, F$ J6 R6 J
#if        0/ F% z: R2 X; c8 s( f, L5 w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 o/ D" m" n, U) U5 W5 u5 d
                {
" n0 a; @* F0 k" _. A                INT        diff = abs(output-last_data);$ I; W. J" t8 E* J9 c% n! b7 x
                if( diff > 0x4000 ) {; j! t6 F, F9 @6 x$ ]
                        output /= 4;
( N$ b4 g# u. o" }. u- j                } else
2 Y# K4 s8 X9 J9 ^/ t                if( diff > 0x3000 ) {& ~& M8 q  V; F0 D
                        output /= 3;
0 N1 |' ?0 m7 |/ [6 ^. B& |, s/ D                } else6 z) y' n+ v9 `9 x
                if( diff > 0x2000 ) {
$ R  T  J* Y# i3 K2 L  C1 q( t+ a' N* S                        output /= 2;: T; z$ {5 X$ N: U; ]% T
                }
& L+ }  P7 w- M9 P, A6 U2 \                last_data = output;7 e2 R$ l- @& P2 C$ s9 Z
                }4 Y3 h1 p9 l5 D7 j- K
#endif
# k1 s0 e' q! s1 o1 }                // Limit, u: P0 e; L$ _- W
                if( output > 0x7FFF ) {
/ X( J7 @2 a6 p                        output = 0x7FFF;% o" \* L: ^  Y! X5 k+ C! O6 |
                } else if( output < -0x8000 ) {% P( P+ j1 v/ G- x0 K$ L3 C4 B
                        output = -0x8000;/ _. f0 m( {) m$ G/ y' ]5 h
                }
' |. r/ x3 G! b* s- \' L0 \- T$ F1 s6 t3 w1 f6 e" R; O
                if( nBits != 8 ) {
$ z5 D# @7 G/ e+ z3 W0 D: r                        *(SHORT*)lpBuffer = (SHORT)output;" n3 G  V1 I0 E2 M6 D
                        lpBuffer += sizeof(SHORT);$ g; L1 v- |6 L+ N  ~. n+ o6 X! x2 o
                } else {
4 ^- j4 g0 n( Y7 r" n/ B9 @                        *lpBuffer++ = (output>>8)^0x80;
# s, R* }* z3 _- A/ s                }
$ g3 @" G7 i1 h
5 A2 l* }, E! w2 ]' U) O                if( nCcount < 0x0100 )* Z2 z! W* D- _7 l, N# G
                        pSoundBuf[nCcount++] = (SHORT)output;* T3 P( h. {3 Y5 e  H6 S
1 A+ F; s; q& o, I, v0 @! A( ^. ^
//                elapsedtime += cycle_rate;$ s5 z$ a, ~( j" ]8 I" X$ s# U
                elapsed_time += cycle_rate;+ e/ J1 }& q: j1 B9 H/ Y* M; F
        }) ?' t& w7 V. X, p4 v; Y
: p8 z: C. T; M9 T
#if        1
# R# y: ~7 g5 @) v        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ S# {- Y( k% j  T  p# A
                elapsed_time = nes->cpu->GetTotalCycles();$ z2 W. M8 z9 @2 }" L; q: O
        }
  M3 Z+ [9 |5 ^: ]3 S        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
* i- o3 y, U7 Y8 S# v0 m0 k$ d                elapsed_time = nes->cpu->GetTotalCycles();# j4 j0 |5 w! S% {8 y/ o
        }
8 X* U- }. x1 S( z2 J2 a0 {#else
0 h% Y! }4 B: n' N4 j1 N& {+ H        elapsed_time = nes->cpu->GetTotalCycles();
, v$ v9 J7 l2 a5 r- |$ T0 \#endif, ^. c7 x5 ~$ B; z5 v6 T
}: T* O9 ^  |( S: h$ E$ D

, D# S( a5 I" L: M// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)5 K9 W9 \5 F0 a# b0 s
INT        APU::GetChannelFrequency( INT no )
/ @( l4 v1 o0 X) c* M{+ C, K! t' g8 i1 a- D
        if( !m_bMute[0] )
; d" `: W# g6 C) ]  s" j& ^& f! z5 b                return        0;' t5 R+ g8 c$ d* E1 ^, o

2 V5 i+ x: G3 f+ J6 G" i0 @        // Internal
& y( G9 G4 W' g: w        if( no < 5 ) {. ^. z9 H" g' A1 E9 H: q; `
                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 Z& y4 s* l& s% w! Z: P
        }1 i4 ]9 G2 [) x, Q/ G/ h
        // VRC6
+ ^4 \' W7 }0 A! E3 g% Q        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
# C( }. e; a! W! b/ K4 M- V0 d                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% D! B* X" }$ L        }  {4 [) w, X/ _' p. @
        // FDS' b3 h; W- _) s: g* W5 Z1 X6 g
        if( (exsound_select & 0x04) && no == 0x300 ) {
7 T7 v- y/ Y9 i                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ F) e5 M! I2 G" d) w0 W0 e) d        }4 O$ M& V# W3 ?  c
        // MMC5$ \0 B: z6 g% _
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* _* j' H+ d' z! c6 M/ p% t9 x
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
1 T  ]0 m0 `% M% v8 Z        }% ]  o* B# z, S
        // N106# N( X0 }/ `1 ]# M4 q0 W- ^0 _
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
# G  ^' o3 P% X# \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;& k/ F7 j5 H, X6 T- Z5 h
        }
9 V0 o* d5 ]) S& c. R% G        // FME7
0 {: ?$ i: K6 _# Y' B2 e) @        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 K2 j& F( u7 J2 f                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
4 k6 q8 R* b: H3 m; _        }
- ~7 R$ b) t6 s+ K" u4 ?! j( j. W8 \        // VRC7
' z" k1 ?- k8 |: m; Q6 E& a; ]        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 k1 ?; {5 S& y* a2 N                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;& q# N1 ^# m. @8 f* M
        }6 V7 y& P% i# c7 G3 i
        return        0;4 D6 ?3 M2 g+ q+ H9 S3 w
}, y$ X% }8 E2 U- T  Y- h9 r
) h/ t! t5 L) G9 ?
// State Save/Load% }* m  M# N1 g& q
void        APU::SaveState( LPBYTE p )
8 D4 n8 q1 a0 F{, p5 x5 P0 x- X8 m8 Q! k/ U
#ifdef        _DEBUG
: B% e4 n4 [1 m. X3 ^6 u# J+ ELPBYTE        pold = p;) N5 |( l! }. ^6 F& Z8 d  l
#endif
6 R0 ?8 }" d: G: X4 A# C& b
9 I$ C2 W% `, U# m/ L        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞8 a: u7 [; w  y
        QueueFlush();
4 h" d4 O  ]* D0 ?; @9 V3 H8 V; T$ e) }$ D" M! J' e
        internal.SaveState( p );1 J, G+ Q5 p" N3 @2 s: i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 _" C9 O+ X2 _  ?- k- W8 Z' i

" C4 K! p2 R  d) H+ ~1 x5 j        // VRC61 Y8 Z3 [0 X0 @# k8 r
        if( exsound_select & 0x01 ) {
+ h$ I* c) v, ^0 b' B                vrc6.SaveState( p );
5 C2 \; M; Y0 X4 e9 V) ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& |3 g8 a$ ]* ^
        }1 H4 t% U! N# w, Y1 l
        // VRC7 (not support)+ y) t; C" L* M6 q
        if( exsound_select & 0x02 ) {
5 Z9 [# k- _3 l                vrc7.SaveState( p );! k( n. N* B" x3 U  u. f1 U
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. K4 n1 W; Y, \        }
, R" f, H" W9 r        // FDS1 r7 R  H' w8 A+ \2 Z
        if( exsound_select & 0x04 ) {
1 p: {7 d% P7 `( `                fds.SaveState( p );
: N6 z9 O7 Z6 o; E                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 q2 J9 i. @+ M" v6 M
        }7 {0 K' Y" \6 M' v) p& b
        // MMC52 }4 k& A  \  u9 R! \
        if( exsound_select & 0x08 ) {) ~" v5 I8 j# z: J; Z
                mmc5.SaveState( p );
5 {8 P/ G, n, \- X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& c6 f! |* w6 l5 Y        }) [- I  ]; A/ Q9 d4 L. I: u
        // N106' n% h' l. A: Z+ f) O2 @- m
        if( exsound_select & 0x10 ) {
$ }0 v0 G+ C& `( p                n106.SaveState( p );
# z4 F1 o3 A3 a" j3 m                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: _' n* u" Q6 s  D/ x- p) b7 D7 J
        }
6 k) y. p3 v: L& x8 `9 C% E        // FME7
; u6 D6 u4 _8 p6 ]        if( exsound_select & 0x20 ) {
9 Y; p$ E6 J5 r0 M! v                fme7.SaveState( p );2 V! h$ W8 e. o" v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  A' d7 S$ r4 `- M$ |% f        }4 k1 B3 v" k- I% L
% G9 u9 `& c, ~
#ifdef        _DEBUG: `2 U" a+ i3 D$ ^9 O& `# _( j
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );2 |# B8 D9 [* M2 X
#endif
6 u( u# w  U( P  n5 R  H3 E}+ W/ U1 l) z) [0 Y

! N8 z& f# X6 O) |4 h7 ^- gvoid        APU::LoadState( LPBYTE p )
0 J5 A( s0 ^' ]4 K, _! _- E{
: j, |$ t9 J1 r" B& {+ z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
9 N/ S0 Q" G* m        QueueClear();9 a4 R  o  e3 D5 L1 k
2 D, I6 M8 C5 l4 e' D, s
        internal.LoadState( p );
' |& ^. Q* a  v7 u        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 a; m8 m" o/ X9 {

# y0 ^) a. d) Z0 c        // VRC6
8 l4 \$ M# ~% t! K        if( exsound_select & 0x01 ) {) E8 V1 J. B0 ?9 O( x
                vrc6.LoadState( p );
  P0 N- l7 I: G) Z9 \                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 Z2 r% u9 s$ Z. r
        }
5 k# O: B- r! r  g  v" M        // VRC7 (not support)( \$ W. d; L* }: f8 a
        if( exsound_select & 0x02 ) {5 C5 d5 ]% F5 }8 \
                vrc7.LoadState( p );
; h1 N1 `4 G8 W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 F, Y$ Z+ K4 O        }; @. @7 {% r" X. ?# f7 K
        // FDS
3 g* t: K% {& j9 B2 E        if( exsound_select & 0x04 ) {6 ]0 J" X( G0 `, r# S
                fds.LoadState( p );
! Q/ v: [- f: c% ^5 ~" {* Z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 e4 @& R# Z0 U% N# b. q
        }
( s* h: \2 I$ c/ l' G) w        // MMC58 P( f  G. I3 A  x* j+ {! r" ]
        if( exsound_select & 0x08 ) {1 M8 r3 n6 ]- g" K/ h
                mmc5.LoadState( p );1 x2 a$ [: D! U$ p- q. E
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  j, E, ]7 A$ J3 P7 E        }0 `  B5 M( u% ?2 u( g$ q
        // N106
' ?1 f' ^) k- S. Z! I# U' J        if( exsound_select & 0x10 ) {$ O/ b- K  h$ h
                n106.LoadState( p );( a4 W/ }3 x0 c- B+ Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; h4 Y2 z, l) L* w        }- G9 N  p; ~; h$ d% E4 V5 A
        // FME7  Y! x1 G" H/ \2 r$ o
        if( exsound_select & 0x20 ) {! U" A: T7 R- F2 ^+ C' r3 [
                fme7.LoadState( p );' z3 r, S; F' V! p$ V- i: h! ~
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 O6 o+ `8 _7 ^9 y* g        }
. x( C+ m0 w' k$ M}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& t- R* J9 J7 j  ]/ _1 X可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, `  a; x3 \! T0 G感激不尽~~

+ h, F5 `/ j1 l% g1 Z0 [% l恩 我對模擬器不是很有研究,* G" j& I0 I/ D! D; `# Z8 [
雖然要了解源碼內容,可能不是很困難,
9 y  N# k* h, z/ g8 M不過還是要花時間,個人目前蠻忙碌的。
3 K) T8 M1 s8 s* p% {9 m. \/ V/ n/ }3 G$ K
給你一個朋友的MSN,你可以跟他討論看看,
. L/ `# u- z6 V6 a7 Y, q& B他本身是程式設計師,也對FC模擬器很有興趣。
( \2 o1 |# |$ v2 y; }$ q8 v1 @8 d4 C  o: m- o
MSN我就PM到你的信箱了。
7 s/ g6 F' f- L( A- ^# @
) X3 g; F! Q% \6 Z* X& [% G希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
! k, l3 x8 _* [3 I+ R呵…… 谢过团长大人~~

' {; g# F& p: y+ Q
) M$ X7 X! G( z. _  p7 U( e8 a哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 . I4 P6 W% T7 m3 z  I+ S2 I* g7 q
团长的朋友都是神,那团长就是神的boss。
  ?5 i9 N& P: c' o1 z5 G. X! Y
哈 不敢當,我只是個平凡人,
: j5 h& a8 g* N- [" q: U5 C+ a% L要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
: v6 O0 L* z/ I1 N. b. Q( [ZYH
) J9 k4 c* G0 ]* zQQ:414734306& T9 o' s/ c! Y1 H7 [
Mail:zyh-01@126.com
4 L" u/ M2 K, O3 V" \5 g* [
0 E% z  b& a8 M+ r他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
4 ]- T: e9 s- q( H7 P3 h再次对团长大人和悠悠哥的无私帮助表示感谢~~
6 A! f  @1 N- W7 v+ f
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-3 13:48 , Processed in 1.062500 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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