EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 J3 q0 ^1 }" v8 H1 @0 ~9 T楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) N* i: z( M4 y" b& ^* q1 o
这里有相应的模拟器源码,就当送给大侠了~~( Z" I9 e! j7 O) \( s
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 v; ~9 ]( n  [, J+ H( U3 e
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ i3 i7 v9 Z7 t# i5 |3 O! o楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) A. R8 N9 |0 N0 e: S这里有相应的模拟器源码,就当送给大侠 ...

" d4 z3 i( p  _# w& H; E聲音部分(Audoi Process Unit = APU):% k: v# A7 I0 [6 e. Z
.\NES\APU.cpp
) d1 \& e1 P' _( q2 h* b. l1 s/ C.\NES\APU.h3 R2 c. E& s; o* E! \* D4 e) S! ?
- A7 b5 \, v2 x: ^# e
* K' V5 |; C8 a  h' {
影像處理部份(Picture Processing Unit = PPU):
9 `% j0 w9 r! F.\NES\PPU.cpp
  a# P8 I! O, S7 A% M/ n0 X9 j.\NES\PPU.h
* S, a& o$ B; Q" @0 a2 L  M. |' r! r% J# Q3 B2 V7 c
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
& m5 E1 `7 u# `" E' Q, {) Z(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 \8 n/ h5 j' [" ]5 {4 F' K
//////////////////////////////////////////////////////////////////////////
8 Y, O% q( j4 y+ D  ]//                                                                      //0 u6 J4 A) Q" d# L7 \
//      NES APU core                                                    //# r# @3 H5 Y' w0 s+ f
//                                                           Norix      //
  ?, w0 w2 a% p3 v4 u5 I//                                               written     2002/06/27 //; Z5 A) c  v( G- I9 ^
//                                               last modify ----/--/-- //
4 D% l4 _5 h" o) S& U9 b6 p% e//////////////////////////////////////////////////////////////////////////
! g1 o: e. l/ `0 p3 i) H6 V#include "DebugOut.h"
/ g& l7 P* L1 S0 \- S  t#include "App.h"
  G6 @- u, s0 X7 h#include "Config.h"$ C" O$ J$ }& p/ Y. n

% Z. l. k2 y8 S0 r: K. O, j#include "nes.h"
, I0 J1 W9 t5 b$ U5 u2 R#include "mmu.h"; w( r9 y+ n9 L+ b5 W( a
#include "cpu.h"
$ a, u7 r& N$ P( g9 x. s- _& p#include "ppu.h"
5 E& d7 F4 P5 \: s#include "rom.h"4 T! V# k5 b; x; G* z' Z% D
#include "apu.h": {2 w8 {' l  z+ s" h0 V' P2 [) [

0 [# }6 x' n! p6 x) w' D4 f// Volume adjust9 K; R7 W; G3 o% a( Q
// Internal sounds
2 R( U. w' V) m- |#define        RECTANGLE_VOL        (0x0F0)
" A2 L+ ?: q) ?4 w1 e( e! p4 j#define        TRIANGLE_VOL        (0x130)
3 m1 `) p" C! t& w#define        NOISE_VOL        (0x0C0)
5 r6 Q4 [/ S/ x0 `, O- D) ]#define        DPCM_VOL        (0x0F0)7 t/ C* I7 z6 q1 z! Q- \7 {3 E
// Extra sounds+ {7 b) Y6 |  F  \7 Y, g! @
#define        VRC6_VOL        (0x0F0)0 j1 y# [$ D$ r7 E  Q# _# b
#define        VRC7_VOL        (0x130)
0 `  w( O- [# A; `#define        FDS_VOL                (0x0F0)4 p4 C9 n9 U4 z% N. [
#define        MMC5_VOL        (0x0F0)0 U; m" i* g7 j8 H1 ^7 W
#define        N106_VOL        (0x088)
8 ]. S# E2 ^% u0 L3 K4 D#define        FME7_VOL        (0x130)' v4 H. N. g1 s' H( U9 K
- I5 N  Y% Z$ Y$ i
APU::APU( NES* parent )$ i1 c7 H8 `- ~2 Q1 m6 Y/ \
{; @( S2 y8 @9 _# M& X9 G7 N
        exsound_select = 0;
7 Y3 r% ^' H# b; p* z" G, x& R
8 N, }$ {, c$ I        nes = parent;+ i5 C$ \7 v, x
        internal.SetParent( parent );8 B) H7 Y8 G7 ?& O

$ T$ V  J) r6 f3 _7 _        last_data = last_diff = 0;. S. Z- y; S/ X/ U) P; }& r
' h/ z/ r# L0 n( Z$ s; s
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! J! F( U; A+ s; Q& m

0 T/ [) P- M: u7 G$ ^        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- O  h- ~# ^; A4 a: m        ZEROMEMORY( &queue, sizeof(queue) );
! [: A) Z" E& P- _8 O( ?  U( ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ U/ {6 J% j" x" L2 p' R  C

* s% G! Y, Q, X7 {8 J        for( INT i = 0; i < 16; i++ ) {
9 N. V! h- D' M( Y* e$ n( H                m_bMute = TRUE;
' |& A* M: f- o3 m8 d5 \, C        }7 F. o. q2 Q& I
}, [: J: M2 R7 k& G5 N

( u8 ]1 ]- T! M# O, WAPU::~APU()
2 M9 k; D3 p) B; D! a6 O7 J* l{
+ E+ v% g* P' z! s}( L6 b# E" c1 n' \% ]% {
; _) Y) Z8 R  h+ T+ p, @
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )  ^& ]/ c5 `9 i2 O3 f3 ~. e8 a
{! }* q# _* b# a7 P
        queue.data[queue.wrptr].time = writetime;- }& z# U$ w' {7 A7 ?( {; D
        queue.data[queue.wrptr].addr = addr;
" _: S) P% k% Z. g$ K' @2 d        queue.data[queue.wrptr].data = data;' v+ f- l8 Q/ z* N
        queue.wrptr++;1 G3 ]8 T; j1 ~2 Z/ \
        queue.wrptr&=QUEUE_LENGTH-1;
8 t/ A7 y/ L( G0 X        if( queue.wrptr == queue.rdptr ) {
! w* u  ?  z) ~8 t8 s* x! y' ^                DEBUGOUT( "queue overflow.\n" );& E8 I$ k$ C, k; L2 g* Y
        }
: a  D0 I1 d5 b3 I& e; U+ n4 h}. f* s$ T1 V0 C5 N( _# Q

, j. u1 A- J/ O6 v9 o2 K# i6 s2 [BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* c. v5 e! Q9 k% d' ?
{
  \& w4 H' e' S        if( queue.wrptr == queue.rdptr ) {
! b, m3 F4 E# f4 y# L) y                return        FALSE;' }! v6 @+ g/ |" G. ?9 q/ c6 q4 N" m
        }
0 i9 U# A: o/ V        if( queue.data[queue.rdptr].time <= writetime ) {1 O, Z& E! `. [4 z: W. h: S+ l
                ret = queue.data[queue.rdptr];2 d  M- O3 M8 W) D8 N, ^7 n- M
                queue.rdptr++;
& S" ~5 W# z( n% t                queue.rdptr&=QUEUE_LENGTH-1;
8 t* {% y& b$ X7 m4 W                return        TRUE;. E1 M5 j. a% V8 t4 s2 r8 w; j( i. B
        }
8 Y6 p  G: x2 C5 R9 m; p        return        FALSE;
9 i. N9 J/ G/ Q) L% t}% `/ s( U0 T) t$ v$ W3 E# F' b
* ^% I( S# \5 L! l0 E0 b
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )7 }5 w5 q, Y; A" T
{& g7 i4 Q" w2 o+ e0 C2 k
        exqueue.data[exqueue.wrptr].time = writetime;" A1 @" {3 W, _7 F
        exqueue.data[exqueue.wrptr].addr = addr;9 G7 c2 z! a$ z, `( V2 O
        exqueue.data[exqueue.wrptr].data = data;8 `1 W' t0 ^' ^, N
        exqueue.wrptr++;6 z1 }7 T, G  T( p# o7 z0 F+ W
        exqueue.wrptr&=QUEUE_LENGTH-1;) ~. \, M6 B5 C/ t/ p' L! H
        if( exqueue.wrptr == exqueue.rdptr ) {0 p6 S0 R  e( `5 x, m
                DEBUGOUT( "exqueue overflow.\n" );
+ q) ?" k) r1 Y        }
& Z; h8 L. R1 @. d; i}, u2 ~& }5 Z4 n+ Z- F

) R6 A# r% h2 u5 G! J% N4 r) X4 IBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )4 p( P  N- K  V' w" n7 M- A
{
% f1 t) P8 J  \( s& v3 G, N        if( exqueue.wrptr == exqueue.rdptr ) {0 \9 o- }' [# g1 Y3 v/ Z. \. V2 [+ W
                return        FALSE;* |0 j( k# o2 _% N9 p# U# A/ k# {
        }* B9 R  m/ R# ?6 e; B6 I. V. O, ^
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
8 z: h" T- c5 F4 r                ret = exqueue.data[exqueue.rdptr];
  i! l4 g1 w9 d. W# \5 O) z6 c  C                exqueue.rdptr++;3 D' y; v, G6 m2 T
                exqueue.rdptr&=QUEUE_LENGTH-1;- S5 k" t9 S- i* u
                return        TRUE;% \; U- m+ i* K
        }
/ a- m  L% N( }% E        return        FALSE;' u2 n* L, q: ?$ ]
}
' {% p7 k. N: K9 ]- T
( q. I7 {* b2 {. qvoid        APU::QueueClear()
- m4 b: A1 x5 P5 `  t1 g{
1 u( Y$ a1 f8 X7 l! I& d+ E        ZEROMEMORY( &queue, sizeof(queue) );# H9 p4 a0 e5 D- u, n/ B: Q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( j/ I5 y& R. i: r) }& x+ m! X6 B
}
; Y+ {7 ]  ?1 y2 I' E, x  t) M8 W+ g9 R# H, i
void        APU::QueueFlush()
3 V6 V9 N# v) E{4 P% ]6 q% ^# j# p/ \5 U& z3 O4 k
        while( queue.wrptr != queue.rdptr ) {
2 h# \0 @: t1 B6 q: r# i# V5 ?4 m                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; l5 P" c, k4 t0 P/ G                queue.rdptr++;
7 m# W3 f, k* b' w                queue.rdptr&=QUEUE_LENGTH-1;9 K) P. x4 a0 L# _" @0 ?
        }
1 {4 j8 R( ]# s! U, t/ W
. h: Y+ h6 u6 W: u1 K$ N) X) j" ~6 z        while( exqueue.wrptr != exqueue.rdptr ) {* X# `3 ~$ L! v' m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
% n! E* O7 i7 c* Z# n0 ^" W                exqueue.rdptr++;
( Z* q4 x; {0 X% g3 h0 u! a                exqueue.rdptr&=QUEUE_LENGTH-1;4 x( d0 e2 o% n# _. J) }2 w
        }2 L6 @$ B. a; b  ^" n% G! t
}
4 X0 d3 S9 T. b' P  N
6 g' U" V- z- Y; ?void        APU::SoundSetup()
# O! e( J% m5 a, n/ L" A+ t% G{
- u, P) i8 v0 \        FLOAT        fClock = nes->nescfg->CpuClock;
# t  [4 W  S" h8 |0 ]+ X8 n* U        INT        nRate = (INT)Config.sound.nRate;
9 \6 p4 v+ x6 F. Y2 }, f8 V9 @# A        internal.Setup( fClock, nRate );
4 s/ h# V4 [0 _        vrc6.Setup( fClock, nRate );
) e- T( V7 b' `7 d7 E4 J% n# _9 {9 G        vrc7.Setup( fClock, nRate );$ Y' w/ X6 }2 A: E! x' I" S0 l
        mmc5.Setup( fClock, nRate );
5 x; _3 u) g; k& M0 L0 |' F6 u: J        fds.Setup ( fClock, nRate );# o5 A9 C: I/ O1 J3 |2 w
        n106.Setup( fClock, nRate );
4 ?* V4 v# c4 z' }1 Q        fme7.Setup( fClock, nRate );/ Q2 c% j" z4 i1 K2 ~
}  E" y* h6 k1 a# D; P

# a& z0 Y% {% u* ]; @" m, [void        APU::Reset()$ C. ~7 o; ]1 `) j$ A
{
* E9 {) o' Y# e, u        ZEROMEMORY( &queue, sizeof(queue) );
: h* ~7 M2 L& X$ O1 e        ZEROMEMORY( &exqueue, sizeof(exqueue) );- _# i  J* ]) Z+ k5 `

; s0 |) D# ~8 i! k( V        elapsed_time = 0;
6 ^  [  [$ @8 f
2 M$ f* p3 b. v% s8 f" @        FLOAT        fClock = nes->nescfg->CpuClock;
2 i- C8 s$ G+ A  ^) n4 @# A        INT        nRate = (INT)Config.sound.nRate;- w! s" i% w9 V# X* J
        internal.Reset( fClock, nRate );
) W+ G; k( w% P$ h        vrc6.Reset( fClock, nRate );
' K% \; r9 w0 @5 T$ \5 o        vrc7.Reset( fClock, nRate );( M$ g' X$ I2 n5 T6 E9 ^8 Z
        mmc5.Reset( fClock, nRate );
! G2 }# g% E+ a- z        fds.Reset ( fClock, nRate );
9 g) i! @5 K0 h# i- w5 w9 k! I        n106.Reset( fClock, nRate );
3 w2 [" F3 c" I" N$ _. Q) k* v" r        fme7.Reset( fClock, nRate );
- \# q) B; V7 ]6 X
/ J/ J" F0 k9 [* n7 k        SoundSetup();$ |( B$ ?/ q+ S: e
}
# D) p/ ^- A- ~# Q$ E) A
3 u6 ]! K- Y* T7 E) Bvoid        APU::SelectExSound( BYTE data )( K- q4 ]' U2 t: Y! m
{
6 o% V, j# r. J7 V- G$ c( Y        exsound_select = data;3 d4 ~: r6 H3 ]8 K
}
+ Q5 z; L# x% B) g- ^' i9 b1 o: E" p9 ~2 g- O
BYTE        APU::Read( WORD addr )( _8 T# S. p5 j/ N9 B7 B
{
- G* x+ p% S8 |( N1 y  ?        return        internal.SyncRead( addr );
# C+ I( W! l! T5 ^" t8 K2 `5 w- O}
: y4 l( z# G4 O3 K) i" W2 R" H8 u) X2 \# p7 }
void        APU::Write( WORD addr, BYTE data )
. L& q- k* b4 \/ c5 `( [{
8 |# ?; a5 e% U7 H, k# y        // $4018偼VirtuaNES屌桳億乕僩# v7 x9 l. J8 `. E7 J: u$ s1 C
        if( addr >= 0x4000 && addr <= 0x401F ) {
: T, d& O. p$ Z  Q                internal.SyncWrite( addr, data );) `/ P6 d) H2 H6 n9 b) }* _
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
8 {" o5 [* ~% E; j1 j        }
2 ?8 s! l$ N1 B- X* `* Y}# e5 F+ d! n' q. J5 P

2 n3 |" f  E9 W$ eBYTE        APU::ExRead( WORD addr )5 P8 l6 w6 M6 M3 ~( o
{5 x3 c/ P; z7 I1 ?
BYTE        data = 0;7 D; f. k6 g* Z- w# Z

3 S- I. Q, c) @# b* C8 Q        if( exsound_select & 0x10 ) {
8 ?, H$ P8 N; Y1 j) H% N                if( addr == 0x4800 ) {3 \- Y0 R( t1 ?9 x3 ]- t( {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );3 ?" S! v+ P" i- V3 Z
                }
4 M' x' W( R1 \3 h4 P        }
  t# ]; h6 m+ H        if( exsound_select & 0x04 ) {
- r3 W1 R. A! d1 W- q  Y; k                if( addr >= 0x4040 && addr < 0x4100 ) {: e' y0 o" j7 f" n' o. H
                        data = fds.SyncRead( addr );: U: z0 m3 U- F( g( a
                }
) G: G2 \; ]3 ^1 C5 M7 Z        }3 Y: x* ?+ A& N. j
        if( exsound_select & 0x08 ) {
% C2 G, }+ U- H' `- Y& P% a                if( addr >= 0x5000 && addr <= 0x5015 ) {8 S9 S. y; \) x
                        data = mmc5.SyncRead( addr );
- C- a- J* i2 n& t, y: A                }; y! K& @/ o; Z  ]* F" r. G. F
        }: L  r- l% a- ]! I$ t) ]1 s
1 a& O( ]0 Q3 `) x- _* [
        return        data;- N8 k" ]; R- x
}
/ L0 _8 _  o7 w, Z6 o
8 K$ |0 E( D/ Z# a( avoid        APU::ExWrite( WORD addr, BYTE data )% @  `+ U8 t: ?- v% `
{' V5 y# z6 `2 S8 X4 d
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );  v4 ^4 O) B8 B
% r( `+ `( i! X6 o. x5 w, G
        if( exsound_select & 0x04 ) {/ b# z2 I) P7 s& e9 B9 N$ H) x
                if( addr >= 0x4040 && addr < 0x4100 ) {- ?9 x$ i: ]6 d# z! ]" Q/ g. }
                        fds.SyncWrite( addr, data );9 {( S) K8 Q) |
                }
% ]+ G) G" v7 |        }
! c  ~$ a* j2 M7 B
; ^+ W  f+ d. L2 B- }7 F. p        if( exsound_select & 0x08 ) {2 v0 I- P9 j1 p4 w, a) l
                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 ]) j+ Y8 G6 m5 f) d/ Q, t                        mmc5.SyncWrite( addr, data );  y' s9 |8 x# v! H  @- K- ]  L9 j
                }
' `% M* W) o$ g+ ?, F) z, w% g        }
( q1 U7 r) h' ^. g: }}8 `; Q" u9 e$ ^1 @% H

, n) E( X  S- R8 t8 ^, M  dvoid        APU::Sync()" D2 L5 O: o( d2 q
{
9 g# n8 T  @  W* L$ ]/ i}4 ~/ E: b. ?% i2 y7 U
3 S# r  N2 b. c9 j4 E8 o& ]2 c* u( j
void        APU::SyncDPCM( INT cycles )& W! K' x) U, U3 J& p, N- x" q
{& j7 e0 o; R. K7 Q8 p4 C, U4 u
        internal.Sync( cycles );0 @3 A1 S( {" m  M' ?
& V& ?# d8 ?+ _' e  O  S
        if( exsound_select & 0x04 ) {
6 R6 z" c# t, t/ o" y# J4 k  D                fds.Sync( cycles );
% C, W. I+ U! [6 u1 v" @. g- r  x        }
( ?! A9 H# F4 _' [5 W3 k9 P        if( exsound_select & 0x08 ) {  V+ T* f! J* e% B
                mmc5.Sync( cycles );( `" r: @. |" H/ q
        }) N: \# ]2 x/ ?, _2 D5 E' D
}3 P- F; h2 h: F7 a9 }

3 J4 h1 J5 _; z5 H; h5 O' K# |9 ]void        APU::WriteProcess( WORD addr, BYTE data )
2 p$ f' z; ^7 t( u{
& J3 b; g$ q- g/ l        // $4018偼VirtuaNES屌桳億乕僩
+ W2 l3 B. ]+ w. a- @        if( addr >= 0x4000 && addr <= 0x401F ) {
% X# R$ l) ]$ b                internal.Write( addr, data );
* r  s9 P" o, d% @9 b. J* |        }
) C" @; s2 s7 n3 _$ _}
. w5 u. u* O. o8 e' N0 L
4 h$ g- k3 B0 N, A8 E' H1 M7 p* Xvoid        APU::WriteExProcess( WORD addr, BYTE data )
' B0 u2 Q7 c; K0 m: n7 r{
  U8 I! Y7 C( M( ?; d        if( exsound_select & 0x01 ) {* I" b& G. i/ u) l! X3 Q% v
                vrc6.Write( addr, data );
: O  U" ^. [& p# A. g8 I        }
+ q) p+ F+ V, N# P9 \- g; p- U9 O: ~        if( exsound_select & 0x02 ) {" F+ y  ]. J' \  H# x
                vrc7.Write( addr, data );
; x$ V, F( U6 h# U& @        }$ V* @6 z+ B% ^& N7 f6 d* v
        if( exsound_select & 0x04 ) {: ^% y- [0 v- W5 z% t
                fds.Write( addr, data );& h( J  A2 o! P/ Z
        }5 O, Q  O% @8 Z; S7 _# a' w6 \
        if( exsound_select & 0x08 ) {
4 l# t& v/ [% c. E                mmc5.Write( addr, data );# X3 n9 |+ [6 p8 g" _8 G
        }
  M2 ?/ u, B: S, v" ^9 F9 y# E        if( exsound_select & 0x10 ) {$ K  Y! j" J( [- o
                if( addr == 0x0000 ) {4 f- M0 [+ T( b
                        BYTE        dummy = n106.Read( addr );  N5 H3 s2 Q3 b- m+ s- _. A. d# N
                } else {( i; X6 Z. }2 N8 ]4 w
                        n106.Write( addr, data );
; H+ o. G0 Q) x" [' @" q                }
, `# [( w' {# y8 }) t. W        }
5 Z; ^6 A6 [4 h2 [9 f        if( exsound_select & 0x20 ) {8 e" P( n2 z" p. }8 @5 A: x
                fme7.Write( addr, data );" V+ I: D+ c9 l
        }
( z8 ?& D5 f' u( A7 C  H}4 `7 D* j. l7 p# u
4 n! c2 i3 Z! X0 g9 s5 S& v
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )5 B( T3 I  R* T9 N
{" X" I$ t& T( d6 _3 u  ^
INT        nBits = Config.sound.nBits;: X0 T$ b6 d5 z( H. A1 S
DWORD        dwLength = dwSize / (nBits/8);0 |2 S. X2 K  i3 G: j
INT        output;3 f1 g, s$ \! E. C' N
QUEUEDATA q;3 g5 |# ?- E+ U1 m# @# f& z
DWORD        writetime;
7 ]* s# U7 R! T; `* p9 l% m, r* J/ z1 C* p- i2 Y
LPSHORT        pSoundBuf = m_SoundBuffer;
: X6 Q: R3 O  ?7 Z# f2 gINT        nCcount = 0;
! }% y% ^8 O% C
% _) l2 t6 |/ I7 V6 uINT        nFilterType = Config.sound.nFilterType;: j/ B& f; n% y

- L" h8 F) C& ^1 i2 h, [        if( !Config.sound.bEnable ) {( I% `9 k# T1 W0 l" _8 l2 v
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ M8 L- `! \5 [
                return;! C* W& p+ ]2 h4 l
        }' B, t, \  [9 Y% k: p8 A

- x9 v4 o2 o6 s        // Volume setup( J( Y4 @4 ~' _: `% i
        //  0:Master4 D# q, [5 Q* i- r+ ~5 L  d/ W
        //  1:Rectangle 1
4 m; z2 p8 Q) M* C8 n4 s* y        //  2:Rectangle 2
0 z* `# P9 W. z7 `! r        //  3:Triangle5 y0 s) q. l6 V- D& L( P
        //  4:Noise
( H! {" p  P7 G        //  5:DPCM
! m9 M1 Z; P& q: c' ~/ ~' @        //  6:VRC64 W6 s$ x7 B7 R$ T) R
        //  7:VRC7
: o! E) q6 f0 `' n& [        //  8:FDS2 [$ X( h( g& `6 N0 Q' n
        //  9:MMC5- o& X5 m1 t" b% @2 i: _3 P
        // 10:N106
7 ~5 a- H  n# G  w  v5 R1 {        // 11:FME7
3 H( y" ~: l- x8 T- S) d+ ~4 }        INT        vol[24];
- p( G: t$ j3 T9 N+ e5 m. b# g, b* H3 g        BOOL*        bMute = m_bMute;
& c; \- i2 M7 V  \        SHORT*        nVolume = Config.sound.nVolume;
; {  W( N7 Q: |% o2 O! x6 e1 C' g$ y; f  q9 e1 Y) V4 f
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  I( K& o/ V5 |

% g6 ?+ Y- |6 O& z        // Internal
! M# H2 B% B0 p7 t1 _2 d+ y0 M( q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 @( X9 p& K1 L$ U3 x# B0 ^        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;$ |9 N( o5 w0 s# J; O- Q$ \, l
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
7 Z9 D+ ^0 ]4 m$ O2 o, o# e        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;0 _/ M0 Z4 ^) k! `5 S7 Q- j+ X
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
  i! g1 E3 }. w5 O, t, Z# ]1 r9 d+ y$ Z& h: _- ?
        // VRC6
5 _% o  F+ K/ M1 Q) c9 g        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 {  Z' g1 `$ `3 x9 Y
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! h5 a, i" t+ }) p        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, y+ b  i' ~4 r! q% R

  m8 I# K9 F. L. B; d1 O9 X        // VRC7
3 l) s# y4 F- k6 p" m4 L8 L$ k; X4 m        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, V" k) q# V+ R/ R. A
" W' S7 Z( m0 U" f: T5 K5 I        // FDS
  O6 c/ B$ j3 t/ o/ p        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
' m- [) M0 z$ l# l2 U( U" \- s7 C2 [" G7 X% a
        // MMC5
  \" _7 K* O. h5 A        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 o) P# Q  J) z- _        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& m3 {5 N  }2 r! I+ F, h) h# j        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# Q% s1 Z- |: g: O. j$ _6 d7 ]

' Y" _( L- K! `# T7 d# \1 ~        // N106' X! Y2 D% k8 I  R2 y8 U* V% z; S
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# I! Y  J: m* x  T8 l% c        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 T+ [7 l7 C4 \( X% m0 f' z
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ d: A2 k9 L0 e: f& j# x
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ r% g% E, I& _9 E; x! j. }6 |
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 g/ }5 B8 r$ W        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! l5 B$ C9 v% Q3 l3 C; o
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- b/ E8 I+ A0 [  I" ~/ E        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' i6 A- q& L5 E4 f. b) B2 k* F4 H7 O2 }' B
        // FME7
% u$ h. r; G3 e" M/ Z        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# v( i6 V- z- m
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) J. Z9 K; |$ {( ?        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* B8 z2 I& }4 _. |
# [0 N; J# v' Z- L. I' r4 w
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" N9 I( _( \6 z2 T6 }0 s" p3 L9 V4 s* H
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;+ R+ i$ E4 [- u
  n) j2 q2 h7 R1 D* W, ]
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
2 k  `  ?* b0 u8 R' G8 t* u        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
/ R6 L/ J  f7 j/ |                QueueFlush();
. G" s' N2 n+ ^& w- X1 C* }        }0 Z& \9 b# A" [+ [1 w* E
5 O% r3 v2 N9 U# ?3 a! t
        while( dwLength-- ) {+ B1 S% v; ^# B* m8 q5 I
                writetime = (DWORD)elapsed_time;2 x% A9 b# A4 x
: ]! h: [1 F" [6 O( O2 }
                while( GetQueue( writetime, q ) ) {" @( h1 W9 Z4 l
                        WriteProcess( q.addr, q.data );
. N+ M' A( T" ~% c& t                }# s* Z& _$ `' n/ G- e6 `
* Y9 E- e& C- H3 ^. C
                while( GetExQueue( writetime, q ) ) {
: o  ~( f3 {) d. m1 h1 ^1 A$ z* p                        WriteExProcess( q.addr, q.data );+ d. ?0 I7 }! _  h# V3 f
                }
' |3 p1 H# f8 |: M% b) s% N) I: y* y% Y8 M) Z4 c  ~7 z1 O$ U6 w
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
( P+ ?, N. L7 _8 t                output = 0;7 A0 b4 G( Z) `; T# G/ v% |
                output += internal.Process( 0 )*vol[0];: c$ ~: H/ J- h* P1 X
                output += internal.Process( 1 )*vol[1];. O0 ?1 X/ V7 s! Y4 T. V$ t6 u
                output += internal.Process( 2 )*vol[2];
" v! v* T8 {8 O; t2 M( _% j                output += internal.Process( 3 )*vol[3];7 C6 d$ f+ |2 K% O% v2 l
                output += internal.Process( 4 )*vol[4];
- X" w! Q+ Y( f# Z! J
6 ], o# x. o5 q7 w4 _, R& S                if( exsound_select & 0x01 ) {* _$ _1 Y! x8 F- O; V) _
                        output += vrc6.Process( 0 )*vol[5];
( Y2 m/ f' ]6 y, s2 |+ a& t" S6 A                        output += vrc6.Process( 1 )*vol[6];
* W" v( X4 T3 _1 H                        output += vrc6.Process( 2 )*vol[7];; Z2 x( w  }4 i7 n' }- J
                }7 ^8 k4 T  ?1 H' E- ]4 g
                if( exsound_select & 0x02 ) {
5 i$ q; V: ]0 L, q                        output += vrc7.Process( 0 )*vol[8];3 ]! |+ D  }: a; m% |3 n) \
                }
& U# o4 @! p% W+ g- v& l% E                if( exsound_select & 0x04 ) {
* b: K; h8 v" b7 O  j: p                        output += fds.Process( 0 )*vol[9];! a% o1 h) L' X# o/ \" z
                }
1 c) B6 [" O+ t' J9 [8 C- ?                if( exsound_select & 0x08 ) {
2 J9 O6 m% G, H& r! J                        output += mmc5.Process( 0 )*vol[10];8 L: P" K  i# }! ?) f# e. \
                        output += mmc5.Process( 1 )*vol[11];8 \+ }" m) m$ W' M7 M1 U
                        output += mmc5.Process( 2 )*vol[12];8 u% n" T1 m6 N& r6 m
                }3 m; j, ^7 `0 l9 ]
                if( exsound_select & 0x10 ) {) P5 _8 n4 M/ D. J" K7 E) W
                        output += n106.Process( 0 )*vol[13];
% D4 m3 }2 E; I                        output += n106.Process( 1 )*vol[14];+ j6 e8 r' g; V7 g3 r' H2 \4 [
                        output += n106.Process( 2 )*vol[15];% L+ s  A) |/ }. Y
                        output += n106.Process( 3 )*vol[16];/ w1 a, k+ }3 c  p' O1 m5 R
                        output += n106.Process( 4 )*vol[17];: Y! g# c# N' X  j' i
                        output += n106.Process( 5 )*vol[18];2 V* S% n1 j. `- @2 R6 o5 M! G& b
                        output += n106.Process( 6 )*vol[19];
. h' y% c8 f# R: s6 R+ ^                        output += n106.Process( 7 )*vol[20];, J% A3 x2 l  a5 B
                }: Q" v/ t" G, J5 b9 n5 c
                if( exsound_select & 0x20 ) {6 R' o/ H, Y  d, T3 a7 Z* n
                        fme7.Process( 3 );        // Envelope & Noise+ Z. r! Z# B* V$ i7 C& R9 B
                        output += fme7.Process( 0 )*vol[21];
% }5 j2 `3 n' q7 L" f                        output += fme7.Process( 1 )*vol[22];6 o# i' ~8 J% f+ [. }6 m
                        output += fme7.Process( 2 )*vol[23];
: O/ C& p7 l( T6 H; d$ G8 N9 J                }& S* w, \" o" Y) [

  D: i# V* P# ^' }; n0 Z5 `) ^4 Y3 w                output >>= 8;
/ N6 W: x" |% x6 l' X! _# ~9 d/ ~3 n
8 f3 n) y  N8 y! z                if( nFilterType == 1 ) {
: ^# \0 x" R" }' K4 @% `/ c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)( N" e' J% V: ]! `( H* H2 H
                        output = (lowpass_filter[0]+output)/2;- a& ~6 @: S" `
                        lowpass_filter[0] = output;
' M) N4 h5 c. ?- h8 S% @                } else if( nFilterType == 2 ) {
" V* }. ?% y3 c( {* D4 H                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ h7 |. Z' p; y. N5 n' b+ |                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; k* v) l8 W. o
                        lowpass_filter[1] = lowpass_filter[0];$ Y7 h# c# Y/ H6 L% S/ O0 V& V
                        lowpass_filter[0] = output;
: B, P$ W/ j; [: G$ I% m                } else if( nFilterType == 3 ) {# K0 ~9 e) A2 h
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; _; u# t, f! A* J# F1 U- u+ z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 J. n; `" w  G! T                        lowpass_filter[2] = lowpass_filter[1];4 L  U4 l# z" X3 P$ r! S' F& T
                        lowpass_filter[1] = lowpass_filter[0];4 c( o6 G; u, J' V9 q& J
                        lowpass_filter[0] = output;
5 i" t. k, M3 J& V* h                } else if( nFilterType == 4 ) {
' N$ Y2 \. Y; |3 o/ ^& k  N- {8 Y; q0 ]# D                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
; b8 v0 G- j: n, {% x1 w                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
3 q% \2 r9 B# K; n                        lowpass_filter[1] = lowpass_filter[0];1 O: f( p, d1 g: P& z2 R8 T
                        lowpass_filter[0] = output;
) S, w% x/ q. W1 }, p                }" U, _8 n5 }1 }9 |( S7 B0 V
' M9 M' _% A7 Z3 ]
#if        0
) @% S) b, B6 }/ Z6 ]                // DC惉暘偺僇僢僩& y+ n( ~) s% w. j) K! _
                {
$ U5 C% }  i) U! ]                static double ave = 0.0, max=0.0, min=0.0;* s' p2 `( H; S  g) w( x
                double delta;
  J# L$ V! z' e, ^6 L- Y                delta = (max-min)/32768.0;6 ^6 u- |+ b1 M1 U/ p7 j
                max -= delta;5 B* [. y2 J1 `7 q6 d
                min += delta;
! y8 T+ u- {0 B/ i# e$ n/ B7 r2 d                if( output > max ) max = output;8 a' O& G0 t- u1 ]
                if( output < min ) min = output;
+ v5 X# C+ i) ?4 c                ave -= ave/1024.0;1 L1 e0 f6 N0 y! E$ o
                ave += (max+min)/2048.0;/ R8 ~& _& l& k* B
                output -= (INT)ave;; S4 I/ }" Q; Y- |( u) \. A
                }
2 h, Z5 I+ F9 M8 S. C; b#endif
- c& h+ f  k  h: B#if        1
8 L, x$ V+ K7 O( D& C# q% s                // DC惉暘偺僇僢僩(HPF TEST). b* f/ A9 P2 x# @
                {9 u6 B2 ^, a6 m
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);' [% Y8 u7 n! x& u
                static        double        cutofftemp = (2.0*3.141592653579*40.0);0 D: P. ~% D7 x
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
  ~7 a( M$ E; J7 Q) G2 ]                static        double        tmp = 0.0;
$ R: s" u, M& U0 A                double        in, out;+ U8 L( n( Q5 \. |) F" w
2 o' c8 r" H  {5 a/ C1 ?
                in = (double)output;
; \+ Y* D) w7 o7 l: `" V                out = (in - tmp);% R, E4 B. z  g: ^
                tmp = tmp + cutoff * out;9 Z5 q7 K# I; A" X9 Z
2 P5 I8 Q& W) t9 _" H4 l" X+ w
                output = (INT)out;
6 @# e0 q$ O9 Q7 D7 v                }/ {+ M& i' Y& k/ |
#endif6 t4 I5 D) {! E' z5 E9 E
#if        06 {" i, `# S) d- A1 Q
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
5 P8 f5 r" s, j                {
& L0 `1 W7 _" ?; j4 Q                INT        diff = abs(output-last_data);
2 t9 f( U. D# L5 y3 t2 l3 m                if( diff > 0x4000 ) {3 @' u2 v* J" S; t5 c
                        output /= 4;
( O, r8 P* n8 m% _& R( u                } else
$ T( k' M1 U9 N" f3 y. \3 p$ j0 T                if( diff > 0x3000 ) {
5 Y/ }8 k9 k2 P- @                        output /= 3;
7 ~% A) `0 R$ V* z( S& d8 r! d: I/ r                } else
( }( `1 e& @0 v' s                if( diff > 0x2000 ) {
6 c/ U, H. t1 |) ~0 T: h                        output /= 2;
4 j$ ?2 q! E" }8 v$ E1 i                }
/ y, g4 i0 A6 J5 Q% K                last_data = output;
& [: B8 X: M& g# o( U                }) A2 j0 _: v$ g9 ?1 V" E/ [
#endif3 k% R+ @' z! P/ r. s0 A6 O
                // Limit
* l: w/ o3 U: ~, J* h% D# N                if( output > 0x7FFF ) {' d. F: U; k! z" d- H# U4 ]
                        output = 0x7FFF;* |5 U2 O+ }# `, I
                } else if( output < -0x8000 ) {+ s& z4 W& g- C, ?; c# {; s
                        output = -0x8000;( \( ~5 M+ h9 y
                }
) Q. b- }! f( s- E- g
$ t, Q) q' g0 [1 H5 Q                if( nBits != 8 ) {8 }5 [: `8 z- ^( w! V  Q2 o
                        *(SHORT*)lpBuffer = (SHORT)output;
+ C5 e: u2 g$ h7 E                        lpBuffer += sizeof(SHORT);$ M- G/ ~# Y. N4 N# m' {
                } else {& }8 R7 y/ B( `: j9 W
                        *lpBuffer++ = (output>>8)^0x80;
5 [0 ~( K# C) y+ F1 s9 W4 T                }
- G1 c$ T* S1 J6 z6 j8 O4 z) K3 i0 \$ O' J' F5 u  B
                if( nCcount < 0x0100 )- d3 V6 G% ^( l! X8 d
                        pSoundBuf[nCcount++] = (SHORT)output;+ D! c" E( S+ F! }* Y- r; \6 H: ]
- r1 `8 }( {: c' p
//                elapsedtime += cycle_rate;3 c& c. M9 a, z1 I8 S2 l4 F
                elapsed_time += cycle_rate;# x: A* @0 v2 j1 w
        }
7 \. \; f. M/ B7 P' m, e
5 g4 {$ }0 A/ `% t9 C, G" U0 ?5 w#if        1/ s0 b7 g" i7 }; _+ d
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
. [1 |( p. {2 p( j' X                elapsed_time = nes->cpu->GetTotalCycles();
6 C- |3 i+ y1 h$ {0 E7 D        }
+ x3 p: Z% X! V5 U5 G, x        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
0 U; e8 ?. c& A' W3 l                elapsed_time = nes->cpu->GetTotalCycles();: Q& @; I2 s1 a$ f0 {# `
        }
# G! m. F  }  \4 W7 @' C#else# I6 F7 b) i- F
        elapsed_time = nes->cpu->GetTotalCycles();0 s, V2 ?( @/ G. d
#endif
! h5 V2 m' L6 z}! L- z$ U" Q2 s; |  @3 x, P+ f( f

5 V1 z: q+ {+ B3 ~, g( @// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)$ \& z4 w, i' a
INT        APU::GetChannelFrequency( INT no )
8 r! @, {' T7 l% ]9 D/ Q{
! V' X/ \! d2 {& g" ^' H4 r        if( !m_bMute[0] )0 f0 g4 x# h- n" S' }. M
                return        0;
  K7 S) m9 t0 h( C8 g% \; E* C3 r2 S0 g% [+ m( j
        // Internal
5 c/ G% x3 j$ E' i! K- f7 `/ Q; L        if( no < 5 ) {
: v% `+ F& e1 S$ }                return        m_bMute[no+1]?internal.GetFreq( no ):0;+ O, M( d5 @) R% p; T
        }
' e* l- `! }/ h/ V  V- C        // VRC6
- V! w# y" @" G" K2 i) @2 @5 }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* ?0 m( h# \8 C/ p* y8 b4 X5 ~" \                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
: w9 t: ^$ q6 S, k; Z5 O        }; c& e. ?2 L, u- `$ p% G$ f1 o
        // FDS2 F  N5 x; a, u+ G9 p4 M
        if( (exsound_select & 0x04) && no == 0x300 ) {5 F8 T- n+ j4 X- ?7 l
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
" ?* v) l* b3 Q0 z! R4 P5 a, B        }6 V& t. h) k* z# \
        // MMC5
: Z4 C, j; M9 Q7 e$ `5 n% b        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 X  {: M* N0 B1 M  C+ `                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;* j8 o/ C5 i- y! M
        }! w  M, \! @5 l& M2 e# W, z
        // N106% G9 b  z4 }( k) K$ w  v+ U
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  b* ^+ T0 N  K0 Q
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
. p, S0 B) x# }; m( g" P& B. u        }# o& @* [0 {3 g6 L8 f, P
        // FME7
$ k' J6 i' G) Z5 h; I        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
% F; r- _. W* z7 q                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;/ x" r# [" }7 N1 E4 s
        }
1 I! }( I2 P0 A& v' P8 n) x+ z8 g; y        // VRC76 |' `8 z4 Q0 t& J4 u( S
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' B4 D* t  @- s
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;& R/ M" i9 L4 W
        }
# S2 t% M# N) n' j9 ?! J        return        0;! n. n) y; y* N, x8 B
}! U  m4 L/ B5 V6 @# a0 m
; `. A: q' O+ ?; \% F" r
// State Save/Load- j! M8 P1 D; T% }2 b) C
void        APU::SaveState( LPBYTE p )- @# g- P- c# t: f
{0 V! j  D# w& e& F8 T! k
#ifdef        _DEBUG
# F6 @$ ]: M( o5 S, CLPBYTE        pold = p;: f2 @1 z4 _+ t2 y- Q( O# A& g: p) E; i
#endif
& W) r" X5 m- G' I7 u! O3 q9 x/ j* E8 ]0 M9 B
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞' S* o7 x% H! |$ w
        QueueFlush();
- m/ @! _$ N, Z! g: j! Z  G! E$ u1 H. T6 h
        internal.SaveState( p );  {: U( K# `/ o; R/ F
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 C0 Y9 J. ]! r2 D& x1 a

8 @9 S+ c4 ^: d6 g6 \3 ~* p1 H% F        // VRC6
$ c. M. z" j* v3 m& K' J) l$ |        if( exsound_select & 0x01 ) {
2 n% L4 k" E( x) W% }                vrc6.SaveState( p );
! k, E; l; e3 t- T0 B                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 D5 Z$ z# K+ q0 H/ d        }
2 z: \7 R) |7 R2 D- U/ z        // VRC7 (not support)
2 v4 T/ a$ c/ V! k9 ?        if( exsound_select & 0x02 ) {$ C( `( s+ B5 ?/ q% {
                vrc7.SaveState( p );" R. a# S9 D% _+ C  W
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 h, g2 d. F3 q0 m        }
4 R$ M7 S# [, t7 A* X        // FDS
% L. h3 w& [/ E3 R7 ?9 L        if( exsound_select & 0x04 ) {
  a3 d% S2 z9 P7 N2 B' L                fds.SaveState( p );
) m$ [) F2 u( }8 f, a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 @; j7 T- n. m$ \: A7 w  T
        }" K) T4 w- [* P) N! h! ]# u: l
        // MMC5( U0 O( R( r) m2 ]8 z/ J
        if( exsound_select & 0x08 ) {, K: ?! q6 g' k5 _3 z, ]) Z; `8 p
                mmc5.SaveState( p );
! E, X% T, U4 f8 a/ s1 D; }                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( Z4 `; v9 O8 o$ q& L: E0 q* h) W        }! m" s% I7 t5 k- l
        // N106" @: L# ], ~) ?  v
        if( exsound_select & 0x10 ) {
" y$ D; S  p# b9 k8 I& ?                n106.SaveState( p );
9 l$ O7 A2 [2 v$ n+ b' K- _                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding- Y+ Q7 w# \% P  s; ^
        }3 j! {5 `2 G. A( D
        // FME7
5 @" |4 g7 g8 L3 s2 c" r3 e# O        if( exsound_select & 0x20 ) {
! _6 D0 {  W6 O  e1 [3 w! X- {                fme7.SaveState( p );; Z  D2 l+ l( F; r  J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* f7 K6 w0 e% ^7 P        }
4 T* r5 e9 t! W( x4 ~. L
+ u* T( e5 J* C2 y" z- j+ {: O  ~#ifdef        _DEBUG& q7 f- ^7 |5 c; d
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
: u# R: W2 g8 z  k#endif
. ?3 y- f+ a5 J5 u  Q6 z6 \5 H}
- @6 i6 H3 J) c0 C9 P5 Y* s- y' K0 L
void        APU::LoadState( LPBYTE p )) @) n0 |8 Y- M9 `) S* c# ^. s! e
{
4 h9 J( [$ t  q' O0 M' l. N, A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡0 u$ W$ Q- t% j3 G/ W; K+ L" M" h
        QueueClear();2 h& J' W' x+ f6 M) Q' I
0 s  ]+ p1 D$ ^6 r3 g. t8 x' g5 b
        internal.LoadState( p );. n1 {+ P. q# R: e1 D
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( V/ V- Z* I4 _1 L. g/ L2 N  P0 x2 ]8 Q1 J( ^
        // VRC6
) ^0 I4 k- l' i# d6 [3 Q! k        if( exsound_select & 0x01 ) {5 R8 U3 ]7 n: j' S: u1 p: ]# y
                vrc6.LoadState( p );+ K. ^. Q% b( O# V$ r
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding7 a2 B9 ?- `( j& Q0 f2 ?
        }
* r0 m' ]8 E0 Q8 y6 q. [5 `        // VRC7 (not support); c# {  u& u/ K. b0 l% f0 k$ M
        if( exsound_select & 0x02 ) {
( _4 f' m- d# S( n; ]: Q! `3 |                vrc7.LoadState( p );
/ V  [9 q7 u) t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
6 A/ G8 a6 j# E6 _8 n        }5 r8 r$ E, [* j% P+ }$ w
        // FDS
) f* U$ S; f% t* W        if( exsound_select & 0x04 ) {
- W$ b$ w  ~" N                fds.LoadState( p );9 w3 N, _. h) u
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* B4 v) L0 r0 b% d        }
* K1 y9 M/ q! q3 `        // MMC5
& u6 w% U' f/ Q" ^        if( exsound_select & 0x08 ) {
. h$ ^( {) B/ C9 [                mmc5.LoadState( p );+ u( C0 o$ K2 ?. X0 [
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 x* ]- F5 x. T8 p+ b: D3 V' }
        }
2 s) a3 P, o; X) @' |$ i7 |1 O+ }( e. }        // N1060 ]; k/ {! s; W5 ]3 v2 p, B
        if( exsound_select & 0x10 ) {4 ?) |1 @  f  P/ Z  y) A9 @
                n106.LoadState( p );
# g# A$ N8 h! I) {: G3 g0 E                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& y8 ]9 Z1 t$ u% M8 u: U        }4 }2 s9 f" y3 i+ n
        // FME7
5 c7 `1 u- u( T; |* q: }        if( exsound_select & 0x20 ) {% ?2 F) _9 b, e2 G
                fme7.LoadState( p );; H* C# a- \6 J: a
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ J8 o% \0 l" s5 S        }
: N, l  g) Q8 X6 y% I}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 4 I% a2 K  W& d  Z$ u9 |3 k7 f1 ~
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
6 g7 x' Q- ?- q! i5 u# B( T感激不尽~~

( y. ^4 \  I$ V: w; d, }恩 我對模擬器不是很有研究,
/ \1 E3 u. v, T8 r' I* \& s" I雖然要了解源碼內容,可能不是很困難,1 }7 z% p1 Y" S
不過還是要花時間,個人目前蠻忙碌的。
: h9 t+ a7 s" j& D% B' l
5 `4 b1 c: P9 r- f給你一個朋友的MSN,你可以跟他討論看看,: ^. y/ g& T0 d+ ]! B, S
他本身是程式設計師,也對FC模擬器很有興趣。
; e7 O- `! Y. X2 v8 X
( ], j& F/ X( S+ O! NMSN我就PM到你的信箱了。
9 R& y. l, G# X7 x# n" ^  i. k: z
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ R7 G' B; e0 N3 w$ `& l
呵…… 谢过团长大人~~
  f* ^; F# w2 q, {2 m2 i) L4 r7 t4 e
/ K1 l/ L' n2 X. \5 p1 ]* e
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
7 n( r2 W/ t/ |2 E$ W+ \9 z; E( _+ M团长的朋友都是神,那团长就是神的boss。
* o# l1 v! S9 L8 j. A! E
哈 不敢當,我只是個平凡人,
0 W, p( `$ ^2 |) e要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 a0 L: s7 ~5 v( N3 u# HZYH6 H# g2 P; h0 F3 [2 g
QQ:414734306
1 I7 H8 Q0 n" i7 J% Y/ w( X  x; F# BMail:zyh-01@126.com* C. u4 r$ e/ d: P: I% s

5 ^' ]+ t# r. K9 a- W  t1 j' o他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ; o3 c9 `& J$ o
再次对团长大人和悠悠哥的无私帮助表示感谢~~

" ~! v0 s1 Y: n; A8 }不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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