EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?# m" ?4 Y3 G+ [2 I
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 ], M. s" a8 F4 u% \- ]! R& x
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; }! p( f6 G/ U8 f这里有相应的模拟器源码,就当送给大侠了~~8 r, t: x/ H& \# T2 j# Z/ W
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" w- H6 b' h) m) d能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 E; i- ?- ?% ]楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 z7 u2 }' D# z9 E/ e  K
这里有相应的模拟器源码,就当送给大侠 ...
! d( W, w( q2 I7 I: k+ H
聲音部分(Audoi Process Unit = APU):
5 P+ i: `$ s) P* H.\NES\APU.cpp
! j! o: J0 I& G8 i, D! l.\NES\APU.h
! p5 A; @; x: j+ ]" h3 g
+ O. x3 w  X) Q: C" ?0 C$ {+ U) @0 v$ j0 {+ i
影像處理部份(Picture Processing Unit = PPU):! P; C( B5 P* {% _' Q2 c) T- i
.\NES\PPU.cpp
7 s3 `' x+ b. n. S0 b& V- H.\NES\PPU.h
7 D- T5 {' |# ?2 y
& s2 [" z/ Q5 M, P如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 h1 J" e; _+ p/ T# p  F6 Y6 a感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& K' K4 Z+ E2 `4 d' r
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 t) W; @9 X- L4 i- j//////////////////////////////////////////////////////////////////////////
: H. ^% e9 ]/ b* m9 B//                                                                      //
0 }* h" X0 C! l- C! x  K//      NES APU core                                                    //: b( c5 W! e2 w; r' Q! O
//                                                           Norix      //
3 _/ }% Z; y5 w  ]# w7 x" Q//                                               written     2002/06/27 //
$ M: u0 c/ _9 h( X  ]//                                               last modify ----/--/-- //* s9 `& W) ^3 }  B& G" [" t, j
//////////////////////////////////////////////////////////////////////////: o& b2 n2 [1 W$ B) `
#include "DebugOut.h"8 t+ _9 l; R+ m
#include "App.h"
1 O7 N3 f1 K: x#include "Config.h"
- `( l5 K* K6 B" [% N4 C  n
! L2 I, r7 c" A' m8 _' B$ X#include "nes.h"
/ Z/ X7 z2 a0 {- d. ^5 t! q#include "mmu.h"
0 m; F# \: }9 _+ g: ?7 Q' Y#include "cpu.h"$ T& h9 Y# \. s  m
#include "ppu.h"
, h: x, V3 J! v& h#include "rom.h"
; l2 c5 y/ D6 q6 G* x5 v#include "apu.h"5 v  E4 g4 y; t4 t8 p. A1 G8 e
5 }7 f/ Q+ D, V, s+ y% \6 O
// Volume adjust! s& u7 @6 r4 u1 G* T
// Internal sounds
- g# \0 G; s/ r  m  }#define        RECTANGLE_VOL        (0x0F0)1 F5 r  S4 P  U' c
#define        TRIANGLE_VOL        (0x130)
0 s. P( Y6 G, W#define        NOISE_VOL        (0x0C0)
- i9 `# ?  J2 w; c6 Z#define        DPCM_VOL        (0x0F0)
3 m2 W: y, ?" Z4 d// Extra sounds! a; Q0 ~, y4 l8 G: j* U
#define        VRC6_VOL        (0x0F0)
( |; M5 v2 s2 @: }, m) J! a#define        VRC7_VOL        (0x130). r5 a0 e% Q0 {2 }" [3 X
#define        FDS_VOL                (0x0F0)- n: \7 D2 J3 n5 O, c# P" o5 N' Y
#define        MMC5_VOL        (0x0F0)
7 L. z/ I' q7 H  r# c2 a& e/ {#define        N106_VOL        (0x088)
( u* ~- l2 z1 y3 C  n- [* a% t#define        FME7_VOL        (0x130)& D$ s) C; T; T1 D9 o+ U

1 E! V" v" d2 i, M# Z$ TAPU::APU( NES* parent )
" u6 x# T6 G4 l, |; D. ~/ [) e{& o+ H* a  }8 W2 N* P) ^, P
        exsound_select = 0;
. J) ^8 O9 [- P# O0 N( Y
5 G" G4 |& z  |/ c/ X  R        nes = parent;9 x& d/ Z  k8 k0 x. V
        internal.SetParent( parent );
: R% k; U0 v6 ~! n; @2 i1 Z3 d/ ?( I8 L) K6 Z' u3 O8 V
        last_data = last_diff = 0;
# \1 q, r' P: y' m, O! U  g! w, d& m. j' s) y2 c, B; x  K
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 k/ V: v4 Y7 U# `5 V6 O
" e. R0 S1 y6 y
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );" Q( ?% V" |6 g; _
        ZEROMEMORY( &queue, sizeof(queue) );& w% s% g# E$ |1 r$ r8 `" o1 ~2 J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) y- ]% V6 B1 N, m* A. h* ^% T8 R+ Z- O2 G' c8 J/ a; A9 ?  \! @
        for( INT i = 0; i < 16; i++ ) {# V, C* p1 e- \0 Y/ {
                m_bMute = TRUE;$ S* ?" P) T+ W
        }
( i; m2 w: r. F  y/ J, [! ^}
) n9 I1 S- ~6 s7 ~& R7 T' X8 r: [7 Z" T0 q  r  a8 @
APU::~APU()5 L0 p: K. O. S9 I/ a! l! [
{
; b6 t# y3 ~# J' y, R7 C}
' k2 ]) Q1 e8 G8 w; h- y' |# E& _# M/ R0 W1 B# R
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# ~7 R% L3 ^: w& k{
* z. D0 z1 ?! i9 p        queue.data[queue.wrptr].time = writetime;$ j4 g- ]$ U  O& K
        queue.data[queue.wrptr].addr = addr;
: E) v7 r6 Y0 d+ ?        queue.data[queue.wrptr].data = data;
5 A6 U! m* G1 c: n# J' ~% x# u! k& p        queue.wrptr++;  C. x6 a0 ?5 S8 E! l5 B/ k
        queue.wrptr&=QUEUE_LENGTH-1;( c. R. r0 H, ~7 X
        if( queue.wrptr == queue.rdptr ) {
0 ]" r3 L9 @& n0 s2 m! e5 l                DEBUGOUT( "queue overflow.\n" );
1 @; g6 J- _8 X; L9 v3 z        }
4 z; M$ S: [9 l8 a$ x; P}: }3 W* \, W) n6 Q6 p  h

' m( w( ]- G1 e5 g6 G# mBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
/ y; ^+ S' g+ X* ~( h{+ r0 f. B8 v4 p2 G8 o$ C  B4 p
        if( queue.wrptr == queue.rdptr ) {
3 f! Y! ]* x; @: l: i! ~                return        FALSE;
$ o: R* A! ?3 \- w% R( d  d" c$ J        }
8 f% v; a( t: n. P        if( queue.data[queue.rdptr].time <= writetime ) {$ `) P& P: j3 t& T$ d% ^0 Q: J& F4 ^
                ret = queue.data[queue.rdptr];% w, ]! M$ d; ^9 l. V/ s9 G
                queue.rdptr++;0 J  u, N: I& `
                queue.rdptr&=QUEUE_LENGTH-1;# P7 @" {& W. E+ D
                return        TRUE;
3 ?3 A9 o) h: k8 T9 _+ b0 O% x3 i; D        }! i" q1 n6 p9 ?/ I
        return        FALSE;( {% `9 i: A3 c- P/ ?! q  d
}
" D- F/ `1 j" u+ o6 K
! |& b# T2 s$ P7 `void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
' o( ~' X, _( E: P6 _- R{0 x0 U" `0 _8 q1 R6 t1 F
        exqueue.data[exqueue.wrptr].time = writetime;3 B8 r3 }; a& x( k( z( n
        exqueue.data[exqueue.wrptr].addr = addr;2 v: j: K) p0 P1 D& z
        exqueue.data[exqueue.wrptr].data = data;) Q! T2 D! B( W2 J! H
        exqueue.wrptr++;# m! ^0 D: n1 s# c/ Y8 w- `
        exqueue.wrptr&=QUEUE_LENGTH-1;9 v, h2 j) Y  f3 x  U; h
        if( exqueue.wrptr == exqueue.rdptr ) {
$ \8 g$ P7 p, I                DEBUGOUT( "exqueue overflow.\n" );( l$ i6 n  Z& h. N3 B! a8 c
        }& n6 @0 U; ^& d& r
}$ t6 _4 H1 S9 g/ a4 |
- H# G7 W8 B( m  z
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 @: ~; T; d: ?- v- q9 c
{
5 e4 B& c) V9 S        if( exqueue.wrptr == exqueue.rdptr ) {
6 j+ {0 c: E( ]' g" ?  `; z1 M                return        FALSE;
7 Z" g* w9 V; }! S/ i! t: K        }3 Z5 ]6 v) D4 C9 `. r
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
  K6 O& T- k4 h, ~) {% k                ret = exqueue.data[exqueue.rdptr];0 K2 M. J; y* I
                exqueue.rdptr++;
* o, m  N+ L9 m6 v3 A: W% v                exqueue.rdptr&=QUEUE_LENGTH-1;4 ]* K. h5 i; M0 ~
                return        TRUE;* \; w: E, {6 z7 g# }
        }
$ K% G$ {  Q; `' f* L) D( h        return        FALSE;
1 E- M0 {, Y: o& L0 e( C" P+ T" b" P+ P}
& k. A; v9 V$ j$ f0 }) G
* X2 k+ o  l6 d% Z; D- D( U- Uvoid        APU::QueueClear()' d, k' u3 X8 I5 b/ ^9 D1 ?! W
{
! x+ a* x7 ?; P        ZEROMEMORY( &queue, sizeof(queue) );
/ W1 W! J" T" A& w: \5 j. s1 a. z        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, _2 ?4 X, K+ Z+ J5 B5 {6 X0 d}
& X6 C& v8 `2 G3 M
! m/ m0 \5 _4 |' b: S9 |* kvoid        APU::QueueFlush()
: ]& S( N2 v6 H/ |+ y: |/ f{
/ V% \1 v: q. S& d  A& g        while( queue.wrptr != queue.rdptr ) {) E. l8 D+ i* Z% I
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# K* S2 W# `: c/ A! s7 h8 [2 x; Y
                queue.rdptr++;
1 C0 C, M% ?; [. R0 p5 r+ h                queue.rdptr&=QUEUE_LENGTH-1;+ L* Y( s% I) e" d
        }
* H; X% z4 B' l! S7 [- M# C1 v. V; s" W2 Y1 d8 M" D( a
        while( exqueue.wrptr != exqueue.rdptr ) {  N. G! V& ~" `2 D9 Q% k4 z
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );  [5 H% j9 j. S7 [3 P, i
                exqueue.rdptr++;2 a* \5 g8 O" ]
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 b% _! l3 H4 \        }+ u4 N8 V3 `# \% X- m; e. F
}& q4 r8 {- j4 r0 f* f2 A7 X
) Q/ d! L8 n7 ^2 ]' }9 A
void        APU::SoundSetup()
# c' J7 @( @0 r  w# q% S2 `% k& a{
! |( \, n: P: `9 ]3 _4 `/ E( Y        FLOAT        fClock = nes->nescfg->CpuClock;
$ p1 m7 |" Y8 [        INT        nRate = (INT)Config.sound.nRate;
1 M: Q/ y2 l: @# g* ^        internal.Setup( fClock, nRate );
+ S( Z: w9 T" i5 I3 {        vrc6.Setup( fClock, nRate );6 L9 J, K( e, L( h8 A, |3 h" |2 K- `7 M4 ?
        vrc7.Setup( fClock, nRate );" `# E0 f3 s) D, R
        mmc5.Setup( fClock, nRate );
2 {( K4 w5 g' B# i2 F6 E- U        fds.Setup ( fClock, nRate );
4 d) n  k/ m# @; P2 c7 l4 `        n106.Setup( fClock, nRate );
. _% I. }. `( u' w        fme7.Setup( fClock, nRate );
4 F' y8 P4 H: o/ e0 m3 t}9 v" q5 a- z4 `
' ?8 E5 o; l: g4 H" t' V# s
void        APU::Reset()# _& ]3 z% a- l: A: f& g
{
) x  a8 Q1 f7 D; T5 K        ZEROMEMORY( &queue, sizeof(queue) );
2 e0 t4 G6 x$ V        ZEROMEMORY( &exqueue, sizeof(exqueue) );  ]0 e3 u2 r8 l3 c1 @* [& Y1 i

7 P5 g6 v- j; s5 ~9 @  n& b+ T, P        elapsed_time = 0;5 F$ g9 b* f: E6 K& O
, T9 E: r( z5 P* `* v
        FLOAT        fClock = nes->nescfg->CpuClock;
# \* ~) j1 _" I. R        INT        nRate = (INT)Config.sound.nRate;
5 y; a; x+ |8 N- p' e        internal.Reset( fClock, nRate );
( c& C, x6 j) h4 Z        vrc6.Reset( fClock, nRate );7 C; k& x! e/ S4 k6 K) L
        vrc7.Reset( fClock, nRate );  }! O  _% |+ O( d. q7 S
        mmc5.Reset( fClock, nRate );8 H% A( Q* ]# j, O8 w7 i  Q( o* y+ B: L
        fds.Reset ( fClock, nRate );
9 @% v) B, |  M  G        n106.Reset( fClock, nRate );6 g& Q9 ?- I/ `# n% w) \
        fme7.Reset( fClock, nRate );
5 g, C1 ]# Q! J( y# U' b
, J4 ?7 S& E! U& g1 w        SoundSetup();
1 T* p6 `; W6 J) @# c}
3 F7 d; X, S! G7 j% |3 k
+ `7 X; S# V1 ^* E8 hvoid        APU::SelectExSound( BYTE data )' P/ i1 _: x2 G: {. i  a
{* C- D/ C$ ?% o
        exsound_select = data;6 a( [* X% k6 P$ k! ^
}
' j& [# v$ q4 r. z! g9 U
/ K$ G/ S  s* v( |$ r% KBYTE        APU::Read( WORD addr )
7 Z  }, W6 o0 _; E- @9 }& }% r{
; t% a$ @- a0 K5 U) g& k        return        internal.SyncRead( addr );
! a9 U2 z& H& q0 F}
; Y% h! R" f+ n. ?3 C6 F* l4 l' u% i9 I; z3 Y, F
void        APU::Write( WORD addr, BYTE data )7 H/ a9 r% y' ^( b1 x
{" p5 n) u8 F/ [, Z' G
        // $4018偼VirtuaNES屌桳億乕僩- d  Y. ~3 a! O! M4 [
        if( addr >= 0x4000 && addr <= 0x401F ) {7 z6 ~# i' p% Y! w. D$ y
                internal.SyncWrite( addr, data );0 R1 J$ z, k: J/ z
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
. [0 D( @- K1 G# r  y        }
, m' r* \  N$ w9 w! `, D" Y}- i0 k9 ~* n, Y' H5 \& @# @& S
% p' w+ p9 V0 u6 t$ T9 p; `9 O
BYTE        APU::ExRead( WORD addr )
+ Y. F" }9 I0 K{
' b# H2 B: O6 Y6 X4 l2 k8 PBYTE        data = 0;
1 s: O% e! q0 F( n! e2 p
' p2 j( n6 J- Y        if( exsound_select & 0x10 ) {9 b# h3 V; J9 G& ?* \
                if( addr == 0x4800 ) {) f2 T* S* Y9 d9 M+ j( o
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );8 W) p; c9 Z1 g* p1 A2 w  i
                }* }2 z- B8 k; B8 X/ d0 T
        }# d: G' v; t" |" T! k; n! R  y" p+ F
        if( exsound_select & 0x04 ) {
% |' Y" W! `% \+ j0 w                if( addr >= 0x4040 && addr < 0x4100 ) {
4 l( n. A+ M/ ~3 z9 v                        data = fds.SyncRead( addr );/ x+ d* ?" T# m( m  O, }4 m
                }3 q5 _6 m3 X. H; ?+ E7 r' I) e
        }
# f. I1 x3 G1 ?' n( U5 v4 O7 _        if( exsound_select & 0x08 ) {" ]; n. A- I6 S6 U
                if( addr >= 0x5000 && addr <= 0x5015 ) {
) M. \% n2 ?. B6 r                        data = mmc5.SyncRead( addr );* Z: \( N3 D; r7 I& j0 p
                }3 D" Z5 I4 `- J9 ]) A' ]
        }
: ]; b/ k8 v6 }: I' U& K7 J1 z7 h- I8 d% |$ R% w6 t
        return        data;3 F" q8 ~0 s. P! f3 D2 l
}
  L7 A0 y0 F# S" Y% P
8 [1 q/ N) D7 f  X$ d* f4 kvoid        APU::ExWrite( WORD addr, BYTE data )
5 \, X& V; U; R{
5 ?1 R7 H7 Q, G* u        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );" t. w7 r6 n8 D5 N. g

( Q4 G4 ~0 v. j0 y: c7 b  m        if( exsound_select & 0x04 ) {
+ {7 A( _3 W2 ?0 _& m, K                if( addr >= 0x4040 && addr < 0x4100 ) {
: N# Z( {. p) T1 Q7 m6 g/ j                        fds.SyncWrite( addr, data );7 j3 j9 k7 X& B- `+ b. {0 j/ o
                }
9 N/ F% p( B0 N9 {  Y        }6 h7 V4 k& m- C" p. ]3 N

3 w9 w  @9 {; r, _+ r        if( exsound_select & 0x08 ) {1 U$ d: `+ G$ O; a! l
                if( addr >= 0x5000 && addr <= 0x5015 ) {. p5 a9 s# w1 f8 S  a7 n5 z
                        mmc5.SyncWrite( addr, data );2 m0 Q" h( m6 x! Y: j7 E  @) y
                }) G8 @- ~0 ~; H- [# s6 }, @- C. |' W
        }
: F9 O* ?7 j$ [, B  g- ^}
- @6 ~; L& C. A  Q, `' c
! _% w$ X- T0 z- M" ^void        APU::Sync()$ I4 w+ m- w6 ?" _- L
{7 T1 o! v6 b( d% u6 c
}2 x- Q; ^0 ~6 M

& L5 Z' J+ I& |& E! h% L6 Bvoid        APU::SyncDPCM( INT cycles )
% D5 L2 K' `4 ]" R{" ?7 `, d( d; w7 R
        internal.Sync( cycles );1 s/ b7 y9 q' Q* |( G/ n

" g% ?' z. n8 Q3 m' U        if( exsound_select & 0x04 ) {. C7 ]' U$ G* C
                fds.Sync( cycles );
, ^' u* M+ X% `* D        }2 f3 a  o1 V9 h% T+ z) Z7 a. L! S
        if( exsound_select & 0x08 ) {
+ i) i' l9 d% e) M7 [* v% Q                mmc5.Sync( cycles );
3 T7 N" z" E( U0 K9 |# ?0 J        }
: A" E: G  ~5 @+ c* a) n}
/ L8 ^' [! X& o4 A3 ~4 `  a/ f) o7 `4 @, f. Q
void        APU::WriteProcess( WORD addr, BYTE data )" E" v/ R/ z' B6 C
{
1 ~$ ]6 k% ]8 k0 x) I. k# g' [        // $4018偼VirtuaNES屌桳億乕僩/ F+ B& k+ }/ T
        if( addr >= 0x4000 && addr <= 0x401F ) {
; b' _$ l: L. C% c: v                internal.Write( addr, data );0 M% t8 K0 G& |% p
        }
9 }5 ^- n6 D  |}% y9 v- ~  q" ~7 a+ x5 ~
6 Y& k, H: z6 ~. u
void        APU::WriteExProcess( WORD addr, BYTE data )( ?1 [4 w9 p, O& K
{5 `2 \) s. v! Q" @. M
        if( exsound_select & 0x01 ) {( O( F, B1 _# g8 E, H) ]# Q
                vrc6.Write( addr, data );
$ g, X6 X) y3 t7 R! }1 ~, @        }
5 ~3 r$ Q" H& T- n        if( exsound_select & 0x02 ) {
" U' V8 o2 g0 p4 d# A4 O                vrc7.Write( addr, data );
# }* I$ s' Y7 u- n. W7 W6 U        }
) ?2 [, p, p* F* [0 ?. L) q& F        if( exsound_select & 0x04 ) {
9 R* p2 w- v" {2 V- g                fds.Write( addr, data );
/ Y! r0 E* w6 q2 t$ _! }        }
6 j! C' L4 A' }& J. V' }1 ~- m' q        if( exsound_select & 0x08 ) {0 d6 q# ^' |& I0 e6 h; q
                mmc5.Write( addr, data );7 u% ?& ]. y. z! H
        }6 b- R! v+ Q; J1 u: H* X
        if( exsound_select & 0x10 ) {
2 V' a8 a; y  o8 M( o+ P                if( addr == 0x0000 ) {
/ i) Q+ `& {; ?+ t* q" }' o                        BYTE        dummy = n106.Read( addr );# }0 F& H, g2 W/ b) I/ Z; y( i
                } else {
& u5 n4 X' H9 L6 |4 r2 g  }                        n106.Write( addr, data );
- c) C2 @8 A8 G. q                }2 A. N3 L' }4 F8 i1 H
        }
3 W/ h; r+ [/ Y! i        if( exsound_select & 0x20 ) {2 O# C& E0 H; }) k. R
                fme7.Write( addr, data );
% X3 |8 K# F4 l2 C9 K        }
, B5 h& {2 h5 h& t}' D" ?+ o$ N3 C8 _( O+ G, k4 {

8 h9 t  o2 K4 n, ?! Z1 ]+ b' Rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )- b& @  {% ^4 ]) i
{
0 T! {* G' i( F0 d" q* f0 L  w! ?INT        nBits = Config.sound.nBits;
8 J# y; _2 R/ }' f  l3 i& {' tDWORD        dwLength = dwSize / (nBits/8);
$ R% s+ a+ s, mINT        output;
1 o7 N. j# F- X; z3 HQUEUEDATA q;
9 ^5 J. Q2 v6 DDWORD        writetime;
( i2 C! P( J, Z. X. i1 |3 p; Z$ Q+ h% R3 d/ A, E" p+ N
LPSHORT        pSoundBuf = m_SoundBuffer;8 |# p& w  F9 D: Q
INT        nCcount = 0;
  R+ m7 F$ u" P+ Y1 C. d
4 r" Q0 t/ W+ F9 s6 D8 ^INT        nFilterType = Config.sound.nFilterType;
( p/ X1 u% Q6 I/ U1 q! H4 c6 _8 v/ v* n% j9 o" L& g
        if( !Config.sound.bEnable ) {
- c3 g3 X# n' v5 W                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 x  ^! o( n2 `4 f2 G& Z4 u2 ]                return;
: l9 h- h5 I. E/ A        }, `. S+ f1 |  H+ d
  e; ^* m" E5 E: l' Z+ S
        // Volume setup
6 H: m" v/ |8 K" f. U        //  0:Master: X, _* t& W2 x
        //  1:Rectangle 1* O! k8 E; T1 A/ u( d6 @0 C. d
        //  2:Rectangle 2
; L# O% z$ q* }; r7 M) K' [5 f6 H        //  3:Triangle3 \) x% x( J2 F3 z; r5 N7 w
        //  4:Noise
7 D: x% I3 k* {- L        //  5:DPCM
2 l0 b9 |0 ]# v4 G/ L7 L8 ]/ E        //  6:VRC6- q: {' i, _: \' N! C" a
        //  7:VRC7
2 `- g& C+ z. z' m: ?        //  8:FDS! c, ]! @' |6 F
        //  9:MMC5" U3 ?0 t; O! X2 u
        // 10:N106
  _2 J1 r! V- D        // 11:FME7& p2 ~+ J( z3 Q! C  T4 A
        INT        vol[24];
# [) s) v. S; |) l2 E        BOOL*        bMute = m_bMute;8 d2 o, M+ c) O+ E6 n
        SHORT*        nVolume = Config.sound.nVolume;
: N+ K  S7 w5 C$ w, M2 a: `, ~* M$ u0 U1 G& O, M
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 Y, D% d) z8 M/ B( y0 w9 ~

' F- J! q( c. ^) o6 e6 t' y        // Internal- f/ M: t' d; \
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
  j/ c( p) ~( E7 h$ Q        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# Y& [4 Y3 {5 Z/ x4 [0 j+ K) u
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;# W- r5 K% z9 U4 F) [! l# i: e
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;. Z( l! R' Z8 x$ |
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
8 g. z: E& ^' O& }/ K4 Z
0 k& g6 h' N6 E( @1 p        // VRC6
/ g1 W$ O& A* V" Q1 ?8 w        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 C8 z% y( G: Y' ]5 ~' M
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 F2 _5 e; v* m
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 _, n' s& b+ s6 E8 Z" X6 e) h" {- ?; e2 T$ ]5 ]1 ~7 V9 Y8 |3 h
        // VRC7
2 k% H% V& w6 m! z' B0 l. n  p5 C, G        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 a% f! p5 f6 T, S) ?
- y4 M; a# ?+ `. o3 k3 n9 J        // FDS: x$ H5 R3 F$ f7 X4 S- V  I
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ N( N: o  t' P# R! j) ^
) \: J5 R8 o) |( m+ Y' G
        // MMC5/ Z0 e8 B" N8 U5 a( ~9 m* \0 n
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' N! _( R- I  F5 P        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' f# p# j- m, x* R
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 p9 C& k  Q4 A; H' z' P
  ]' r7 H# I/ F- z% z  D9 p  P$ E3 e, y        // N106
2 b# k0 G, ~! n7 i' e- {- z        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& q7 P# T# K  I
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ E; y. [: p9 @0 E) U9 d( E        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& F, V( Z" ~7 |) T
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 h2 E8 Y  U/ F- ~        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 i4 s3 e4 f9 u0 d7 J) R        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) R/ h- W4 t) v0 l) Z
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- J/ K8 {% E5 c) H. \, e. Q        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- e5 x2 E- c" h5 S5 W/ A/ u
0 e, }. J0 a& U& R( Z4 Z# ?; M
        // FME71 Z1 l8 i# d' @
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' Q) v: [6 p  a1 E2 @+ n( b
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) o9 o3 u5 W8 s) D# v8 _: C: o- L
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! P5 {. M7 g8 Z5 r" }6 @3 V6 K

2 L3 o2 `$ j  e# Q$ n+ d+ `5 _$ m//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
; ?6 M7 g, @2 V        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
& N6 U5 D7 _& R4 C/ X, n2 L# [1 N/ B. M' n3 Q5 i! y
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
0 O; z- F; D3 `: R        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: k. K/ C/ J! e. b& n                QueueFlush();
2 t, d% c5 Y9 t8 u2 {  I6 }! U+ L: A        }
# f/ F% L7 j, N* w: N
. ~+ q1 s; F2 @8 f2 K        while( dwLength-- ) {
$ E# ^; O: P& U                writetime = (DWORD)elapsed_time;
& }- [* Z6 s: I$ w' D7 y6 N0 U
% o1 {' r9 b5 d" k+ d* E                while( GetQueue( writetime, q ) ) {
- q$ K2 q. P' v' z3 F. X; o                        WriteProcess( q.addr, q.data );
) o/ n. f7 J$ S6 s5 U: V: u$ F1 Q                }
/ ?& v$ i9 |( `% x. P! u# I
9 T" z' c" Y* F6 w" D, f/ [9 p4 c                while( GetExQueue( writetime, q ) ) {# w6 @0 J9 f$ c0 @( E
                        WriteExProcess( q.addr, q.data );% s: ?1 [1 Q6 a& w2 b9 U( _0 t" k
                }
' [% k( U5 A, ^, F5 u# y# R
5 x6 X2 v' W5 j. A                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7* L* k8 ?3 V/ R  r  @
                output = 0;( Z' s2 M1 l8 D' n
                output += internal.Process( 0 )*vol[0];
$ Q4 r# H1 ~0 ?9 w* B                output += internal.Process( 1 )*vol[1];
; F  P- i/ o+ q  ^& S. P; o9 U. j                output += internal.Process( 2 )*vol[2];
- b6 E' c5 d# b0 h                output += internal.Process( 3 )*vol[3];6 T/ m/ B, ^0 l! g# G
                output += internal.Process( 4 )*vol[4];0 F0 b) z7 p8 n; k) k$ R6 M8 H

3 ~9 }; j+ D: ^+ `) J                if( exsound_select & 0x01 ) {
: i( q; ?& N# c  v6 D& p8 \5 ?                        output += vrc6.Process( 0 )*vol[5];0 M1 s: R0 g+ r, ?) [7 O
                        output += vrc6.Process( 1 )*vol[6];) |7 `+ c# G2 p4 q( z
                        output += vrc6.Process( 2 )*vol[7];
& y8 q' c9 u+ r* L: i                }
7 j5 i4 L& ?+ v                if( exsound_select & 0x02 ) {: m- L% {- D& q" o( }& G+ a$ t3 D
                        output += vrc7.Process( 0 )*vol[8];
9 s: a; `1 J2 U6 q8 R  m                }/ L( e' O; X- _7 Z9 F1 x% o4 q
                if( exsound_select & 0x04 ) {* F1 i. ?2 ?, y" K
                        output += fds.Process( 0 )*vol[9];
5 D, i! x/ P  f% x. i2 \                }
' ^2 q9 u) l: L  w# w3 b% [                if( exsound_select & 0x08 ) {9 E  [3 k" o  ^# a2 D, Y
                        output += mmc5.Process( 0 )*vol[10];
' [" J0 p9 c7 C) d5 {9 I2 |                        output += mmc5.Process( 1 )*vol[11];
) a2 K0 }1 y" h5 G4 B                        output += mmc5.Process( 2 )*vol[12];
- ~8 J0 L7 B: b( f5 `/ t* y1 U                }
# e7 y) J" e( A" b/ g                if( exsound_select & 0x10 ) {
2 a3 ?9 P6 R# D; h2 l                        output += n106.Process( 0 )*vol[13];4 B1 E+ \) t8 \0 d: u5 @- q& G
                        output += n106.Process( 1 )*vol[14];+ g) h3 S( r: y% W/ _/ D5 a
                        output += n106.Process( 2 )*vol[15];
8 [5 ?# y) `) f% `1 e/ S                        output += n106.Process( 3 )*vol[16];
3 p: H6 I3 J- k. N7 V+ r2 t! L                        output += n106.Process( 4 )*vol[17];
2 b3 A  x& w6 W/ D2 N1 j5 U+ }1 @# u                        output += n106.Process( 5 )*vol[18];
) `: ]0 B% P/ r                        output += n106.Process( 6 )*vol[19];6 D- T$ x( @. f1 Q; w
                        output += n106.Process( 7 )*vol[20];! s: d5 ]) m# _) |1 ~' z  }1 G
                }2 |, ]+ {6 W5 Z6 ?. l& y4 Z+ K. |
                if( exsound_select & 0x20 ) {
( ~3 {1 W% |$ O1 k) z( G$ g, b9 R! ?2 ~                        fme7.Process( 3 );        // Envelope & Noise
& f3 m% Y/ R5 K/ P2 F2 D                        output += fme7.Process( 0 )*vol[21];" \* R5 `5 P2 F* |' p' \
                        output += fme7.Process( 1 )*vol[22];
- U  A  ]; Y; u                        output += fme7.Process( 2 )*vol[23];
* b1 \0 L' \( `) ~$ [- c- r# z' D                }
+ f& e3 U9 Y$ z( _% S$ V, f* X/ s7 J4 R  G+ X( x. c
                output >>= 8;
3 w% }, t, c- m7 P# q) k& W# k0 j5 J, N) A7 _, ]# X
                if( nFilterType == 1 ) {8 y% y1 X0 p  H. z& P7 ]; C" K5 I
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  C: q! b7 X$ |/ H
                        output = (lowpass_filter[0]+output)/2;) y( ?1 `1 D) V5 l
                        lowpass_filter[0] = output;; R. C. Y6 U+ Z% Z( K& X* C1 q
                } else if( nFilterType == 2 ) {
% G( x( |+ n2 O2 c' b                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)  b  f/ V3 U$ {6 D
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 l5 S/ g: Z: A# L+ H- w2 [                        lowpass_filter[1] = lowpass_filter[0];
% D4 T% t# Y) |0 Q* j) K( H                        lowpass_filter[0] = output;1 \8 A1 L& T8 v8 |9 Z* Y- j
                } else if( nFilterType == 3 ) {5 d" s1 h+ O/ Q9 g8 E( ?  V) U
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
9 Z7 h4 p- _9 k$ W% N5 O) ?9 _                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 z" X5 C9 L# v& }* w' O1 V  [                        lowpass_filter[2] = lowpass_filter[1];
& z, ?9 d6 Z' y9 {                        lowpass_filter[1] = lowpass_filter[0];' Q. Q- V; v8 o. @5 r
                        lowpass_filter[0] = output;
7 n1 l- l+ h1 ^: I* E$ N* y5 |+ |                } else if( nFilterType == 4 ) {
( u! ^/ \, Y/ G+ x; ^                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)/ G: _. `/ z' j0 j; j/ W6 o7 ^4 B2 u
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 U+ ^( ?( b* |* X
                        lowpass_filter[1] = lowpass_filter[0];
" F" k$ o( t$ k5 b) J% d                        lowpass_filter[0] = output;& ^% t8 b1 T2 M! t4 z3 D) H7 s) G
                }( |5 X' d2 \6 @3 J
  K$ [: R: f9 t3 f7 S
#if        0# [4 M7 B" N7 T4 c1 g, A  v
                // DC惉暘偺僇僢僩; e' y" h$ D& |6 n4 Z: T/ l
                {; K: q3 c- Z; g9 F" @
                static double ave = 0.0, max=0.0, min=0.0;
! I, n+ `! l2 _; @  x                double delta;! v2 [' h) _$ S, o
                delta = (max-min)/32768.0;
$ F7 D& B; o3 N. j9 p+ V$ J                max -= delta;/ U( B1 O% T3 P5 c  a- k8 Y
                min += delta;
$ T8 m9 D9 n8 a                if( output > max ) max = output;) s! [: C$ `) Y. r
                if( output < min ) min = output;; J+ @% H# ~! Y  n6 w, K
                ave -= ave/1024.0;
) W8 s) ^% D2 z2 |) ?( m8 w, C0 ]5 l9 }                ave += (max+min)/2048.0;! o" F# U' w8 _' y+ k
                output -= (INT)ave;
+ U# d3 s5 z7 J8 }" R  w                }
- E4 K+ p% Z( N. g#endif1 E' ]( v, o7 f
#if        1. E3 T0 o2 m, t9 S0 i
                // DC惉暘偺僇僢僩(HPF TEST)/ q# ]/ I: O1 O( x  p( p+ Y
                {% E' \$ C  j8 u$ e0 i9 L6 s% }) w8 g
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);6 z0 l& S# n$ ]. f0 L
                static        double        cutofftemp = (2.0*3.141592653579*40.0);: N# \) t9 k" O6 X( N
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
4 k- h+ ^3 e7 j7 E9 I5 H4 @$ D                static        double        tmp = 0.0;
/ r" E" c' ?( |! ~4 B3 U2 f+ c6 T                double        in, out;9 G* Z, p* f2 H0 `( B4 l: {

( R( G: U, |3 A3 @1 N                in = (double)output;. Q* p" L* {* l: B/ i$ l
                out = (in - tmp);4 Q& H* e% t. D7 o" E# S- g% a
                tmp = tmp + cutoff * out;
( ^& u+ Q: ~; ?8 I4 j' u# z
  ?/ D6 B& E9 K" g; `                output = (INT)out;1 q6 I" f' N2 X& h" g% f
                }7 ~5 n: R2 B- y" p. i* R( O5 P4 a
#endif
. m. O9 M/ A" }; v5 q5 L$ M#if        0
: t7 f: l2 S! E$ x                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
! d% w1 s, R; y4 T                {  r9 W% n$ E3 e# i# ]
                INT        diff = abs(output-last_data);
8 @  R* l' E/ |# K& e                if( diff > 0x4000 ) {+ n0 o: r, B, {/ y7 H/ P
                        output /= 4;
) O' [# g9 d9 O+ l5 g) O2 h& O                } else + ~! O- s' A8 `' A  Y5 \9 R% ]
                if( diff > 0x3000 ) {
; k; Z! c1 s+ v% I                        output /= 3;! P, i; M- E" b& ~; K# S& o7 \
                } else
  T) Q! S2 Z* Z                if( diff > 0x2000 ) {# ]6 h& k, O+ A" n  s
                        output /= 2;
) T/ @/ i4 g5 D# `; F. F                }
9 Y3 ]& U4 q9 U/ p8 g5 B/ J' L                last_data = output;
7 p, M7 l1 }) k2 \- L; [                }- m3 Q8 f. H+ M4 f+ H! D! k9 @0 O) t* p
#endif4 P3 l7 b  i4 `" H* V! r
                // Limit' y* ]5 g* C: Y2 ?; x" Z( u* v
                if( output > 0x7FFF ) {" [/ T/ m# x# x$ X& u) H
                        output = 0x7FFF;+ Q. H; r) i  z* K
                } else if( output < -0x8000 ) {
# s6 D$ Y9 l% D& ?1 D0 P' w                        output = -0x8000;
0 Y' b8 Z+ A! R# c/ f" q5 y                }, t6 n+ f+ F7 `+ A  v
9 ^. ~) k+ k7 V5 d
                if( nBits != 8 ) {
) d+ c+ P% s) `) I                        *(SHORT*)lpBuffer = (SHORT)output;7 |, S5 E% z4 V: B) G
                        lpBuffer += sizeof(SHORT);; v, [: ?$ B! _, f
                } else {! B  |/ j% y7 i5 O1 n3 D
                        *lpBuffer++ = (output>>8)^0x80;' ?# }, v2 I9 R# Y
                }; C- O0 R  t" {, O  Z" R

& x3 D+ ~: ^2 `& l6 ~                if( nCcount < 0x0100 )* B# X5 t: ]% X0 x! o
                        pSoundBuf[nCcount++] = (SHORT)output;: t1 M5 a$ D0 ~$ `8 |0 a/ J

( F1 r3 g7 U- o8 b//                elapsedtime += cycle_rate;+ L. ~7 j! t; L1 s% j/ R
                elapsed_time += cycle_rate;* o/ m' u; [  i; r6 F0 U
        }! l* m. Z9 @6 H
) b- q" u8 c4 `( W
#if        1
  V+ v2 R2 [* z- z) n$ r        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% s0 c3 C9 [  w7 t! I  H                elapsed_time = nes->cpu->GetTotalCycles();
$ V4 s( |* [+ Z" x( D% r        }1 u& Z; c0 {: k% `
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {( c3 p9 h( p8 T& c
                elapsed_time = nes->cpu->GetTotalCycles();7 Y$ f8 n, N, ~3 A
        }  g4 t; Z/ c& q8 ?% X, Z4 Y
#else
- l; ?( c- p, C: a7 |        elapsed_time = nes->cpu->GetTotalCycles();
& A, i+ Y% r6 f$ N9 [5 M$ P3 o: Q#endif, p9 z7 h6 }7 G# ^. u% W
}
0 `7 F. v3 Y- I. ^8 ?, {. l7 Q  h9 m; G* G
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' ?9 S  @/ w9 d5 O4 X; ^6 n4 o
INT        APU::GetChannelFrequency( INT no )! P* i& T' v( g* }$ N
{
+ L9 \& J/ g, O1 o6 G' ]* F        if( !m_bMute[0] ): z, T  Q% `. H- q, n! g$ ~$ Q
                return        0;
  f2 U# Z. j1 h  ~3 u6 ?+ N3 j- z( {
        // Internal5 D7 n$ t% L9 P$ i% |( i+ ?2 d8 B  n
        if( no < 5 ) {- O) N& O9 R, C; j. ?
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* x' k, `$ ^, b5 E) X        }
4 s- ]* N* @9 Z9 J4 }+ V        // VRC6% P" y: |( X3 F2 `: d; B5 |1 O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' l1 L$ g, w! B: P) H  J                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
; _' V; Y; N0 [2 x. a% t        }- ^' Q. m# {2 n! V9 q( ^
        // FDS4 l2 ^7 z1 I. N
        if( (exsound_select & 0x04) && no == 0x300 ) {: C* i$ @3 m5 g; r8 G6 n
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% J! F! \3 s& L        }7 i6 @4 F) N- C5 @8 B
        // MMC5* ]5 @; @& \& P9 Y2 u' q) N. K
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ @  F% v3 K9 f6 E  ~5 v$ p                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) p/ t' K/ N) \2 k6 @5 |! }% h; Y        }
2 i  i; b1 _$ z5 A7 d        // N1066 `  _2 p  n- ~5 g' ~
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {( h4 ^$ r/ R% K' m, Z$ Y
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;" `; G2 K" [5 a% t
        }
' H4 D5 r$ ~, M! ^' f        // FME72 c  }3 u! P2 D( r
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {4 L! s2 {3 W6 D3 {3 w! K) u
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
- ~) Q$ }* B% r2 Z  {; O        }
( R9 j  F' w$ j3 \/ _" a) V: c% i        // VRC7$ ~% H8 D& ^- E( l' O3 @, b; v: r) M
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {5 T, Z9 \% h; J
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* G5 ]( |, k, B, X
        }1 r7 a& T$ l2 s7 v' z
        return        0;# Q3 n4 N( A; G
}+ H+ Y: x& T2 V; o- f5 e) k

( c9 v% R" k) U* m1 K// State Save/Load8 J" P& W' z! n* _$ w
void        APU::SaveState( LPBYTE p )9 t, ]& G3 {: S0 Z: ^) M3 J# ?" P
{: g1 H1 t" Z1 _
#ifdef        _DEBUG3 J. \) J$ f% U. O$ j- y+ r
LPBYTE        pold = p;( T+ s- h- q2 j
#endif
1 N  ^* I3 W0 z# F& [, a3 ^6 @. Z- `1 T
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
1 T3 ]2 o9 V; W- ~. v: ?% ]        QueueFlush();: A% J* @% `( @* F; Y1 r; }
9 ^/ U1 l9 c0 L! G8 \1 l
        internal.SaveState( p );
( R; `% C$ Q6 ]& o; s6 p5 M0 n        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 z5 a. M3 a6 @

7 D( a8 _- F* ~6 H        // VRC6' T- w' B4 W: i& t( P- d1 F
        if( exsound_select & 0x01 ) {
, G3 ^* |% I" F" e) L3 t                vrc6.SaveState( p );% S, `- x+ B: K% j4 N: Z! x
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 K: z5 U6 B& i
        }  u+ g+ G9 }' s" u0 Q
        // VRC7 (not support), u4 m6 w2 Y5 i3 ^; C
        if( exsound_select & 0x02 ) {
% p8 `7 E4 C" D" @# M3 q0 m8 q# d. f9 N" m                vrc7.SaveState( p );
( D5 U8 y8 m) V4 v; u8 J. @! u                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% {9 s+ S. n8 C; f
        }
! n# A: J3 J/ N$ g$ D- ^0 y        // FDS
! A( r8 X8 t% a$ G2 z) X+ k        if( exsound_select & 0x04 ) {
2 T% i  `4 r" S# g) m                fds.SaveState( p );) j9 G( `2 `' g. g5 K( X
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' H. F: X9 n: h) p2 f: ?        }
. v9 v# ^1 z$ i1 S7 h( k" v        // MMC5( L( t7 |$ @5 T/ C$ {6 Z
        if( exsound_select & 0x08 ) {; d( ^. U( |* N6 R; z" {
                mmc5.SaveState( p );
* A5 a) B+ \% w) T                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# [3 @& S2 G$ i5 T2 r2 b
        }
# H  ~/ X, H0 Z' |. O. R3 \! C        // N106) T* A; |3 S7 |. z
        if( exsound_select & 0x10 ) {
3 e+ u- a% x2 O                n106.SaveState( p );3 J) q, b. X( b. L1 D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 I6 r6 b. v1 A/ g9 ^) ?( s% o        }
! |; k) z& |4 D        // FME7
. \  `6 n+ O5 c7 @5 m0 q! S        if( exsound_select & 0x20 ) {
5 n2 h7 K) F4 T                fme7.SaveState( p );+ s# i& u8 V6 ~. _% s
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) z5 ~3 _5 ?* w1 j& G1 X$ s
        }8 ~2 {6 o9 d8 @6 X; Y; I- U( d: I+ k
) G6 w8 o/ o! v' \1 q- K
#ifdef        _DEBUG  v3 O3 b! c3 J0 ?- a/ }
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ q: G6 K+ {0 x9 v! P+ Q#endif+ U$ D# N# v$ E9 J: Z8 m
}
0 q2 t7 A7 M2 l7 F( H) w
) ]1 W4 E, X, o" nvoid        APU::LoadState( LPBYTE p )
2 B0 b" T* p( w2 T{
: w- x# n" E4 B' W- }/ m& L        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
( z3 n  m8 C5 Y( n5 ~+ M        QueueClear();
* v8 q# a( I2 s* A+ k* d, q! h# ~1 Q' U# K0 U4 G7 x
        internal.LoadState( p );- H0 w( ^+ G! g# S/ E2 p  z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 ?2 z$ s0 e  [' R) ^( l; k

/ y9 {/ N: {2 @* Z        // VRC6
* D( m7 r% E  K  ^& _. F% o" x        if( exsound_select & 0x01 ) {
2 v1 ~2 V2 v# t5 Q                vrc6.LoadState( p );. c5 r8 Y- d3 l# d! a4 a5 r2 |& w
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% b4 ]- V& {' l9 m        }8 t! c! I8 }- @. G
        // VRC7 (not support)
; t2 ?& A' [: l+ y        if( exsound_select & 0x02 ) {
% \. t8 {% u- ^- c% W7 a                vrc7.LoadState( p );! x$ o; @2 F9 w  @
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ [, y# r/ i+ \- k) z. \' B# A( H
        }; W. [7 i) H) u0 l7 u
        // FDS% y, i# c/ F0 I9 P, {
        if( exsound_select & 0x04 ) {
! D* x  j" S% I# C& {6 H0 }5 ^6 J                fds.LoadState( p );
3 |0 J* o( i" O/ C  Q# e1 w                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 U) T4 \7 ?% B1 F% }
        }
& D' A# F: f3 d8 V. W* q        // MMC5
* I+ Z3 M+ A& d) C2 S9 ~5 }' D4 W        if( exsound_select & 0x08 ) {  k& ?+ W. a' m' i$ T; ?6 E
                mmc5.LoadState( p );
  R* z0 J( ]6 D! P! \                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 h9 w$ @! ~1 F/ ^, l        }
8 w  W, x& f' y- [+ T8 P# d2 @7 b        // N106
5 \2 [0 G  Q& |0 m8 v        if( exsound_select & 0x10 ) {- O2 \2 q3 Y9 \, B% m
                n106.LoadState( p );6 E' u2 n* \; V3 p1 c. N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ `  w0 }) Q( a, O8 l! i9 T" L
        }; g2 Z: }! @1 a' T( t
        // FME7+ {$ Q" I; M1 T" [: ^( H4 w
        if( exsound_select & 0x20 ) {7 d9 _- m# }2 d" U9 i
                fme7.LoadState( p );
6 b/ M# Q) U2 C& N/ P  D7 |/ U1 o9 U9 u, R* S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ P4 @9 N1 j/ ]" H. X& O
        }6 o1 a1 a  x' ~) d$ |+ q. r' u! M
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 2 h! F7 \7 p/ _- u. U
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
! b# m' a5 e) x4 E感激不尽~~

# o: t" N5 S- w恩 我對模擬器不是很有研究,
. ~9 P+ c; U0 R: s  Z) @雖然要了解源碼內容,可能不是很困難,6 W" X3 v& T. G/ V# i/ F$ Z
不過還是要花時間,個人目前蠻忙碌的。
9 g, O, ?( U2 |; L: \$ G
- C- [& x  L" R1 W) S! k5 d' Y給你一個朋友的MSN,你可以跟他討論看看,
( c) r0 Q8 `% M他本身是程式設計師,也對FC模擬器很有興趣。( K* Z; I/ j8 d! q
& s, @* z; j9 g" ]
MSN我就PM到你的信箱了。. I- o7 r* r5 j
9 {, }" V4 t9 s- p; c! k! T/ P- b
希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
! }, y  [: S) E8 V9 s呵…… 谢过团长大人~~

3 j2 v( {1 m. H2 H! V
$ P6 T, F' d( z7 W  c" o5 p哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
, Y2 f5 a* ^. g8 F4 O2 F/ K& `团长的朋友都是神,那团长就是神的boss。
1 n9 R9 {' h$ \# |
哈 不敢當,我只是個平凡人,' A: r* h* q8 V! ~
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ h* D  |  H( S2 ]
ZYH
" ]" Q2 g; o' _+ B/ P7 R+ e3 PQQ:414734306
( m! @6 u  T) ^6 w7 q1 VMail:zyh-01@126.com
% _( a1 d# m. U
4 j6 m3 \+ O1 W3 s( S0 g/ ?. a他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
. E- L7 T8 \: y( n" S  k再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ A, t3 Y6 X! g: `不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 16:05 , Processed in 1.088868 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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