EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! b- }( E* J1 K9 j, A0 E$ c/ s6 q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 p, r0 _* Y; d! H5 y; r4 j/ l这里有相应的模拟器源码,就当送给大侠了~~
% Q- P8 m4 p5 x* T! U2 t* F# u2 ghttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 L; ~8 D6 V2 S8 G
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ p9 _5 z- f) n& u/ H7 Q: Z, `5 }楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& E% j8 U+ N+ s5 E这里有相应的模拟器源码,就当送给大侠 ...

. I9 ~2 n7 [& Z. g! h' ~# v聲音部分(Audoi Process Unit = APU):
+ N0 K' B' b/ h.\NES\APU.cpp
9 Y  e" }+ Z0 K. L.\NES\APU.h: g0 X9 [( p0 C" }5 A/ w. g) q

/ R! y' c! y, T0 _7 {  P' K. \& ~' G2 F+ M
影像處理部份(Picture Processing Unit = PPU):
1 [, M: u. s+ n: L.\NES\PPU.cpp
! Z5 \7 c2 @: I1 J, j' _.\NES\PPU.h
" y4 I7 v) `, R  U5 E4 X; Y" k) A/ X0 L) i
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  D- k' A& S0 U  ?
(由于很多专用术语和算法机理都不明白,所以看不大懂……)9 H1 @4 M6 \# y/ ^) q; q  V
//////////////////////////////////////////////////////////////////////////9 s! p+ z; ?8 l: O# h+ e3 \
//                                                                      //
8 L! e. _$ [1 t3 A- A. m* N  e' N( Z% Q//      NES APU core                                                    //
8 |6 Z: c+ t2 B8 F6 d& c# Q//                                                           Norix      //
5 L2 l( M( B8 J- t% u9 }" m//                                               written     2002/06/27 //9 I% r# T/ S9 p, U5 s, G
//                                               last modify ----/--/-- //
0 Q; X! `: Q' @7 f4 T- u+ F: Z6 @: h//////////////////////////////////////////////////////////////////////////. p4 M5 Y- @1 |- k6 Y; D
#include "DebugOut.h"
* s1 n* ?* @# p+ K#include "App.h"
4 i% v5 {- E, Z! S) c#include "Config.h"1 b, T  ^2 [4 \, `, l; q! R

% f7 ?. J3 I, f; |' T#include "nes.h"
& M2 Q: M3 T% [" v/ \6 A* Z#include "mmu.h", {6 s/ C3 {3 o! i, a( E
#include "cpu.h"
1 g" P4 ^* M) o9 J" ~* y$ z: n( A# s#include "ppu.h"
- t+ j/ {* i  a3 X8 A/ x#include "rom.h"
8 W# v" o! j% T0 N" v#include "apu.h"$ h0 H# K, B4 Q: W$ Z+ ~

% j  r2 S+ e/ ~# P// Volume adjust
" {. V, a+ ~. W0 P$ v! [// Internal sounds2 s. n7 ]% a/ _  w
#define        RECTANGLE_VOL        (0x0F0)2 m7 d  Y) O: g( J; M- y6 X, `
#define        TRIANGLE_VOL        (0x130)5 }( b; i! E+ X& [
#define        NOISE_VOL        (0x0C0)
0 U1 `. i% W) q  X: ~  O7 }4 N#define        DPCM_VOL        (0x0F0)  w+ Q8 H, _" }6 }/ ]( K
// Extra sounds# t" N+ m- A; \1 M& H0 @5 e
#define        VRC6_VOL        (0x0F0)
2 A. k% R+ m) [+ p- L% Q2 s; k#define        VRC7_VOL        (0x130): o) z  A# J# d. K5 |
#define        FDS_VOL                (0x0F0): u4 r& }+ v# _  k( N
#define        MMC5_VOL        (0x0F0)4 L$ }9 x5 e2 \6 [1 m
#define        N106_VOL        (0x088)
  v# D# y* y9 `- O8 e#define        FME7_VOL        (0x130)
4 X" [, k( {9 E6 h1 X1 y, a" t! W) G) C
APU::APU( NES* parent )- a8 A9 r% Z/ M$ C# S" o
{. I  s; w( d+ |
        exsound_select = 0;8 }+ Y( l- l+ v! U. U0 p

5 D# u& j! A; H: Z/ r+ X2 y        nes = parent;
" P9 |( U4 q) q( q4 U        internal.SetParent( parent );
; P" e" n* K7 P# `8 i0 B) F- u: C; C9 Z* A) m  o& Z
        last_data = last_diff = 0;7 O; k; e3 k3 q1 B: Y$ T
( n/ R/ r6 R6 `. L- f& r
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
# \( _, j" |  N5 `- M! e! u5 r
( v* J  H) I8 ~/ Z        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );: j7 [& q) M! w$ l8 U8 d
        ZEROMEMORY( &queue, sizeof(queue) );
) V/ P6 K9 }1 ]" i  m: F' ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 h  D; W! ~/ Z7 C& I# P% J+ u, g" M3 `# |* ?5 P6 m* ~) p) Q
        for( INT i = 0; i < 16; i++ ) {
% @' k1 m& i6 G" B. ?3 b& ]                m_bMute = TRUE;6 w' ]2 }4 U, {1 F
        }
2 g) N& T  |, y6 N! m! N; ?}
- W5 ~) ^$ Y; K9 r8 S) z
/ Y& j; p' z0 D5 m, I" @0 g  LAPU::~APU()& h2 ?' f% g8 l, g/ W( e" J/ ^
{& d& U5 q- [# h% X
}
; C6 x5 U- U7 ^3 {
2 ~* v/ x9 U, f6 Q8 [" H& Y! @void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
" M8 p7 k% |+ g{
7 _2 b( v7 T' B8 s+ p, g        queue.data[queue.wrptr].time = writetime;
) e, K" b1 z6 a& T' L2 L. _        queue.data[queue.wrptr].addr = addr;
- b/ }" g* \; t, s3 f3 [6 W7 |        queue.data[queue.wrptr].data = data;
3 G, c3 i  k$ U5 D$ c$ l        queue.wrptr++;
  U  n- o$ n# D1 D        queue.wrptr&=QUEUE_LENGTH-1;
! D  A, L7 }. M+ i) L2 @        if( queue.wrptr == queue.rdptr ) {
5 G, m( x+ d' X' {" \6 \                DEBUGOUT( "queue overflow.\n" );
3 h+ e! V7 U5 v/ |/ g! p3 t        }5 e1 u3 B$ ^# Z+ A$ R# H
}
! Z. t$ F6 h& L
8 I+ I: o& c. R) PBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
% P- ?* ]' r! [; U7 o, x* N& q6 O9 S{
! F/ O) I& b8 T( S% H0 F5 e        if( queue.wrptr == queue.rdptr ) {: l1 o+ C0 Z; O
                return        FALSE;4 Z" F# _. X4 `% V
        }
8 A8 A7 G" J2 p) S5 f        if( queue.data[queue.rdptr].time <= writetime ) {
+ B  Y: [) x( `7 D2 }                ret = queue.data[queue.rdptr];
# I0 h1 G3 s4 I4 O" ^, f. ^" p                queue.rdptr++;1 S* `# I; D( [: N
                queue.rdptr&=QUEUE_LENGTH-1;( o& I! ?4 g7 S' h' K2 B+ K* E0 w
                return        TRUE;: \8 @! J2 }+ x2 w
        }
+ N: y2 D' M3 z* ~: f! C* y        return        FALSE;
, s# A% f( k- c  Z2 a4 \0 Y}2 }9 T% N" W. K3 K2 @5 l

) e* }' c6 ~5 F7 fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
" T( z2 d7 u% y6 s$ o  z8 t{
; b) q6 Q8 d2 m! L        exqueue.data[exqueue.wrptr].time = writetime;
* U. z! J: O$ o  y# J& v        exqueue.data[exqueue.wrptr].addr = addr;
( F& |. w$ p$ p# W4 X/ u  h        exqueue.data[exqueue.wrptr].data = data;( I' t; t9 w# \! c4 q
        exqueue.wrptr++;
6 [1 j! b6 \4 b* `9 f2 @5 d        exqueue.wrptr&=QUEUE_LENGTH-1;
4 e' E9 [1 v6 v5 E) ]# K, W: N        if( exqueue.wrptr == exqueue.rdptr ) {
3 R, Z$ P+ E( F. m0 G                DEBUGOUT( "exqueue overflow.\n" );% i! E" ?& q! v* o; z% V- z, ]
        }
6 `# ]! R7 b2 K9 ~) d; w}# X% v. r/ G: @& D# D# J3 O

3 @. v* G7 J# \BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 _, W% Y0 a: j" @9 t0 Q
{
0 X) l8 T' m9 f$ K0 O9 v- ^        if( exqueue.wrptr == exqueue.rdptr ) {2 U6 U( ]% Y- h# h8 \% T% z
                return        FALSE;# t- W- T5 W/ t3 i4 `& ^
        }
% H2 [' K9 q" p' x        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: h, X6 j; I% `/ b
                ret = exqueue.data[exqueue.rdptr];
0 i% A( m9 r( F+ |  `3 ^9 m* D                exqueue.rdptr++;; M) K  r( `# G* d4 R+ W+ y
                exqueue.rdptr&=QUEUE_LENGTH-1;
' j. u1 Z; p/ L# o, X8 h& R2 x                return        TRUE;
+ K0 \2 w3 W/ @. i# x) ]- w        }4 m$ `! p9 x0 `% x
        return        FALSE;
8 x9 k) q$ g- m1 d+ M+ s}
) R9 ]7 Q$ u; ~; B$ X
) J- d4 \, }3 E" f2 ^( z' D$ \void        APU::QueueClear()( p% S& f2 s' L* Y' q
{) K# Z- ~, e& J! z7 c0 D
        ZEROMEMORY( &queue, sizeof(queue) );" K" `) y# K" d" ?
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 Z4 Q! S! k! }, o}9 n( w4 j8 |/ g8 P$ w: E

% N/ E9 n  M/ t! |void        APU::QueueFlush()
) ]* M) A% I" X! B{
4 N& O/ V* a  d6 f6 a        while( queue.wrptr != queue.rdptr ) {" e5 Z6 U& x1 b3 Z7 E
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
' i( `5 q2 J5 O0 c0 R, i$ B! `9 \                queue.rdptr++;$ D9 _, I9 h4 Z* x
                queue.rdptr&=QUEUE_LENGTH-1;
- l8 a" w, {7 s3 F4 S        }; |1 _1 _$ p( `( B: P

0 R4 \: d$ d0 K% g        while( exqueue.wrptr != exqueue.rdptr ) {/ o- a3 }3 k1 \" j
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
' t( d- O  Q8 Q5 n                exqueue.rdptr++;
$ V: z8 }  e. R+ T' w                exqueue.rdptr&=QUEUE_LENGTH-1;
& n2 E7 g- g5 K        }
" C1 X% l- e8 Z- `* a, p}
' f1 e4 q. j& [/ Z& ~6 \
+ z9 z2 _3 s% R; R" `( Mvoid        APU::SoundSetup()
9 E/ t  S* x$ Y" F) w6 r{8 a1 Q+ x; ~3 x
        FLOAT        fClock = nes->nescfg->CpuClock;+ w) w5 A- `9 R/ k# b  g
        INT        nRate = (INT)Config.sound.nRate;
; v9 ]1 ?4 l# e) e) Q1 M0 Z        internal.Setup( fClock, nRate );0 Y8 k/ B" L, ~6 U1 c9 r
        vrc6.Setup( fClock, nRate );
' [% V/ s( n. E; z6 f( I; Q        vrc7.Setup( fClock, nRate );: x, X% X5 ~) h: q( {/ }
        mmc5.Setup( fClock, nRate );5 z+ `: M2 Q* j6 M5 ?9 z& ^( I
        fds.Setup ( fClock, nRate );7 k# v0 R# l- a7 x# P! @
        n106.Setup( fClock, nRate );! f( X0 ?% o: `
        fme7.Setup( fClock, nRate );7 g8 H5 x% z; [  [6 n
}0 l6 }! @7 \) w5 y0 X8 ]
' x5 g1 h2 I$ b
void        APU::Reset(). Y1 ?0 z9 H" p. n8 g5 [
{" o/ b! P) H( g5 A# ~, A
        ZEROMEMORY( &queue, sizeof(queue) );
8 R, f3 Y; r% I6 q9 P: y        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# w# B5 o, Y3 t4 U" {- G2 X: K
1 R# |' j% B$ a: _: j! K) n        elapsed_time = 0;7 }7 u% ~: ~2 j0 h  D8 M6 f
% Z& Z0 g+ z" x" Q. L1 m: V
        FLOAT        fClock = nes->nescfg->CpuClock;) m4 a5 K  S) b, `8 J4 ~: H
        INT        nRate = (INT)Config.sound.nRate;
! E. L5 x- D, S9 w0 ?8 _        internal.Reset( fClock, nRate );, @" C: b7 u7 y, F5 S% T
        vrc6.Reset( fClock, nRate );8 `" o8 l6 @3 J0 l2 Y4 b9 G
        vrc7.Reset( fClock, nRate );
- _  p  n2 G5 r, H# G2 @5 v        mmc5.Reset( fClock, nRate );8 [  _3 P; n' j1 K8 g
        fds.Reset ( fClock, nRate );
! m/ k" ~2 O  e2 q1 o! s2 A        n106.Reset( fClock, nRate );9 m+ Y( A$ v! i' I1 ~5 }' X  k9 l- P/ I
        fme7.Reset( fClock, nRate );
- @& U) x) D; e% |8 _
% L' F) q5 K5 p0 M9 l  u        SoundSetup();7 _) N$ A; A3 G. p  g1 w$ v
}; s& D  }. t' S) i+ n
- B* \& f$ S2 Q( p. |4 ]' u
void        APU::SelectExSound( BYTE data )4 [- L/ e# f1 v
{) ]: W/ t0 ?# ]0 {1 c' q
        exsound_select = data;$ G# {( c/ B/ v6 }+ @
}
: A' D: Q$ K/ G) G/ F5 D5 C# @$ D; U" e
BYTE        APU::Read( WORD addr )' Q8 J, e: ?# D4 R7 c7 _1 t: W
{4 ^  m) y* I- C) h
        return        internal.SyncRead( addr );
* g4 ^$ M; [* Z}
0 I  A( A8 g" x' Z8 ]0 r1 r; D* G
3 X' N/ y. y- @, ?9 a, evoid        APU::Write( WORD addr, BYTE data )7 J+ k) q  \: O' P% `
{
2 t- b( b2 h* {  }4 o        // $4018偼VirtuaNES屌桳億乕僩$ V' Q# q7 k/ G* }/ g
        if( addr >= 0x4000 && addr <= 0x401F ) {; [, l: `9 |* y, k
                internal.SyncWrite( addr, data );: K5 K7 p. v0 I  P( m
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 @4 i# E6 \! t# [
        }7 Z2 i. a1 w3 z0 e/ s
}
- s$ `6 ^- |. C% j7 M! P' P3 q) o' V" O2 X: W" W' D
BYTE        APU::ExRead( WORD addr )
$ l5 |) s  W1 i# h0 z" V1 J{8 ?; L/ W) m+ P* \* ^+ i
BYTE        data = 0;
# X- T: m5 `' K! {, \' i6 P: \& q
1 I- Q0 b5 m9 V! S2 }- A        if( exsound_select & 0x10 ) {+ p! j, m' V3 E6 u5 n4 S
                if( addr == 0x4800 ) {1 a4 Y7 N( M+ z* H0 U
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );7 a. g8 ]  C/ K
                }
5 `; S% B8 g1 @; _, J        }
9 w; n$ @, c8 r6 b0 i7 _3 N' s        if( exsound_select & 0x04 ) {
' K; U$ a# g" k) @/ V8 `7 a                if( addr >= 0x4040 && addr < 0x4100 ) {; w6 Z$ E3 T1 I, X  m( u( y! d
                        data = fds.SyncRead( addr );
/ k( s& M  D+ e# y                }
; k7 y, h( f* j& Y- v1 e& h        }
$ t8 X( _9 l) I: ^( g        if( exsound_select & 0x08 ) {% `: Q/ A7 ]" A' W
                if( addr >= 0x5000 && addr <= 0x5015 ) {1 z  @/ {4 r7 R9 n8 w
                        data = mmc5.SyncRead( addr );
- B& W5 W; m* [1 ]4 k                }
3 B$ j. N" r" F        }
4 }6 O) J. Q3 E5 ^' n: c% [8 Z" D. ~6 R/ j) E( O$ I
        return        data;
# [8 t" R3 ^, t8 x}3 A$ `/ P5 n. e0 b& q4 N

2 m) J) e9 J5 y# E9 j+ ]void        APU::ExWrite( WORD addr, BYTE data )" d4 ]5 S$ ?* W3 K/ N
{
5 b5 K7 z9 j% K8 f! L9 R        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );0 ]/ D8 v' a+ \% k, {# G$ l9 d

' d* \9 I6 ^% j" C& b        if( exsound_select & 0x04 ) {- ~  ~- v; q, G/ Y2 Z* q0 h
                if( addr >= 0x4040 && addr < 0x4100 ) {  u2 Q5 c4 G% y1 P% E5 f7 b9 @
                        fds.SyncWrite( addr, data );
; S' n5 s# g9 P# N1 U0 r5 ]' O                }
7 e7 w" `7 s) i$ {/ A3 @7 m        }' O* k. D4 Y4 \) Y4 l( @) c: z4 M; \; l

* |7 C3 U: H0 M$ u- Z7 s        if( exsound_select & 0x08 ) {6 y/ g( C* |" i& ]  S2 ?' |/ X2 d
                if( addr >= 0x5000 && addr <= 0x5015 ) {  ~0 S( ]# j- `/ C  L$ W% G
                        mmc5.SyncWrite( addr, data );
6 k! ^6 c$ s9 x' w                }
! ]+ _* r' ?0 q- z        }
+ J; |! Z2 {# O& c}
8 O5 ?! s; Y! ?3 G  U/ \  k9 L- m, C1 W
void        APU::Sync()
$ \; {+ I5 O# ]/ l  \{
. P, J( X! ?, r! v. E6 r" x! C}  {( E4 _$ m2 u. N8 h$ e
% r1 C4 c: z8 g* a: ~# n
void        APU::SyncDPCM( INT cycles )" j( f+ G4 i' ~. }) J  @
{6 E$ A% T  B: C( b! p- J) }
        internal.Sync( cycles );* M' u1 Q* ]! E7 L# i. Z
/ |! a; V  B+ g/ g
        if( exsound_select & 0x04 ) {
5 p3 F0 K  B' f6 R                fds.Sync( cycles );
  ]! Z" l9 K7 q! e" Q. p. I; Y0 D: H        }
& O* x+ f* Y$ T2 x        if( exsound_select & 0x08 ) {
* S  D3 y' M$ [0 Q0 p# D                mmc5.Sync( cycles );, Q* e/ i; }0 W0 K
        }: w1 ?* ^# K+ N
}
! }8 Q! q3 }, h" t; B# c: _5 Y
& O( l! a% [; D1 H& Yvoid        APU::WriteProcess( WORD addr, BYTE data )
9 x& ]/ l/ y% X5 x" Q4 {{
0 [4 ^7 n7 n0 v% U8 K- Q        // $4018偼VirtuaNES屌桳億乕僩6 I4 L( _9 W. G" F5 a( b/ C
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 u" Z* o7 c& N. \- R# K                internal.Write( addr, data );
+ }+ S: W$ G" X; O        }
% S6 G+ g* t6 d4 D" k8 r1 I}
2 f( i2 N  @" _8 N7 p
3 Q8 d" {! d' o0 s' x) R2 D% Lvoid        APU::WriteExProcess( WORD addr, BYTE data )7 }' m2 F; h/ f2 }% H- @. x, p
{% b  w1 V& _7 |0 {! J& k' t
        if( exsound_select & 0x01 ) {
$ S6 z. u3 \) _8 x3 N: w* ~                vrc6.Write( addr, data );- F5 k- `8 A) W# ^, }- v, f. Y& d
        }! v. t. j* @3 A6 q& X, M  J
        if( exsound_select & 0x02 ) {5 ?' S3 l8 w! `
                vrc7.Write( addr, data );
6 O$ K" N1 S; o/ m        }' T( X# m& u8 I9 F7 D
        if( exsound_select & 0x04 ) {
2 q& }" Z' W6 W$ V6 ]5 r                fds.Write( addr, data );: n7 v# V1 D& O8 K1 _
        }3 Q; m; ^' Y% d( t0 V
        if( exsound_select & 0x08 ) {
1 @% D& {4 O! G                mmc5.Write( addr, data );$ p! \; a* A3 I- {) l
        }6 k" g" \* y! z; k6 X0 K
        if( exsound_select & 0x10 ) {
, {/ V4 F5 K4 n- X7 v$ @1 H' c/ u$ w                if( addr == 0x0000 ) {  Z. C+ @+ u3 E1 Q' ?
                        BYTE        dummy = n106.Read( addr );; @7 i+ u* k+ I5 [: v8 O$ W6 K- }
                } else {& _- c6 S. e7 c3 ]6 E/ b
                        n106.Write( addr, data );
6 m! m$ t4 Z5 K: E1 ~                }8 P% {9 J3 ?0 i& M, a
        }
4 o( B" N. I, V8 {5 Z7 \- H. Q9 V) j        if( exsound_select & 0x20 ) {7 i( [6 ~6 v7 g
                fme7.Write( addr, data );  a4 S1 }8 D7 I9 t% N
        }
* @& V* u& {- N( C5 m$ A5 Y}# C- v7 i. M; I9 ^$ Y. B
: i; c: X  @9 O5 i% U; A' v# C
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ ?. ]. @2 `! H) X( A( |{
. b/ o7 [3 ^# |% H9 _' y4 \INT        nBits = Config.sound.nBits;
$ q5 J/ l* d6 \) m9 uDWORD        dwLength = dwSize / (nBits/8);" ?! k  X7 f2 p, s
INT        output;( o8 @  V: ]: |! S$ ^" c7 r$ ~+ Z
QUEUEDATA q;
7 O$ Y7 [9 V( d1 d# Q; fDWORD        writetime;
8 L3 b; n1 {/ `2 ~. l* w$ N
+ J0 P: O4 E# p, f/ VLPSHORT        pSoundBuf = m_SoundBuffer;
4 {/ N, M: h) s+ [* n, iINT        nCcount = 0;8 i+ ^/ x7 v  y2 s& x4 A3 ^, w
& }4 n+ x- J; }+ x& _4 m
INT        nFilterType = Config.sound.nFilterType;
! J# J  a$ S) d/ C* J: R  D0 r" L
: C% z0 f, b' a$ @        if( !Config.sound.bEnable ) {1 A3 \# l7 Y1 n/ ?
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );' j* R) \* u7 N  v# ^) s' |
                return;
2 e. g+ ?" o1 m        }
! M7 E* [& H# A" m; U& n& o2 d+ j0 U" F) ?! e  _. z6 h! c
        // Volume setup" t# L! `7 w( L$ x0 P
        //  0:Master
7 ^$ e5 |7 l6 z        //  1:Rectangle 1
' _& T- A$ k) n        //  2:Rectangle 28 z0 s/ h8 b, ]1 t! M3 F
        //  3:Triangle
; P+ M0 x$ C8 `' `, t" o        //  4:Noise
! Z) w7 _% K9 ~1 ]  H2 e3 o! u        //  5:DPCM9 ^. L1 j" E5 ~9 ^& b
        //  6:VRC6
6 ?: Y& `5 h6 G" W# G4 A        //  7:VRC7
7 D0 j# ^# i/ D5 d6 Y3 q- ~. |        //  8:FDS
; B, v- U  }. d3 w9 r2 A        //  9:MMC54 [. \* l3 s$ j" \; B" d0 Z3 `( U
        // 10:N106
* i) W( S1 A# `        // 11:FME7
* L# B+ u  ~! c9 f5 @6 X* v        INT        vol[24];1 J6 }6 I. {0 l0 y* g: f( t
        BOOL*        bMute = m_bMute;
1 l0 E/ |& u8 }' ]' B. Y: }& Z        SHORT*        nVolume = Config.sound.nVolume;
, y+ p& o' a0 t' O
  d& W9 k$ {7 c" h* r6 L" P% |* K        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
( ^& Y6 A" A" R# T9 s6 C+ {, m& `' a/ T7 }
        // Internal2 Z2 p: j7 e1 W  }' z: N
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 z& t1 u/ E3 U3 T  F        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ k& x5 b0 K5 c8 D4 Z        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
9 P* b7 l' `, B2 m& O; Q% O        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 l# X" _+ U2 P3 [( B6 x" A
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;8 B, X9 f% |: K4 e) k- W$ c

4 |+ R$ }% z. r" F        // VRC6# I6 ~% h1 J+ }0 r
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: e1 ~7 ]* v9 A. U
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# D; N0 X( b3 d        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 {3 M! C5 B& M3 Q
0 E! A3 }) i! b. f' `5 |/ o
        // VRC7
8 |, U( t& \2 k        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;7 P0 y4 R+ F2 I7 M

, L+ z; D6 W* d4 M8 p$ F1 r        // FDS( W: g+ ], R* ]: o! Y/ v/ `
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;6 r( y1 d( T% u% h. T: Q5 E
1 Y6 o1 K, j+ X; d7 _1 h9 V
        // MMC5
! Z- s% r/ `8 V+ |5 x; x% r- f        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 b- W7 M; |& r5 z7 S        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' O- K) l: p3 f6 I        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' _$ t6 o% C& k. Y' t. M4 R) g9 @* J) Z4 c
        // N106" s$ s# j1 m  j) K# E# U+ k4 x0 e  ~
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! \& {: ]/ }: Q- |        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; y& D! Z, p5 M  W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( ~3 F* @0 ~- Q. T4 m# n& A) @
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ b! I8 i% {5 o6 q        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' i3 W( ?/ w8 E8 a- Q  l) |6 _% D        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 w1 v' N2 R# |9 [) z. ]4 Q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 N; L5 I' c3 n! `+ l4 j7 {4 _
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 l3 Z6 _  w2 X5 _+ _
3 s5 @* l6 n& ]; r. y
        // FME7
6 O3 b% |$ Q1 O5 T. [: f8 D9 L        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 S2 r$ T" t+ j; g/ ~' G6 O" e        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ t, g: p6 m$ M8 ~& D' M        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ `) G# W; w1 \# t: ]- G- A9 M8 ]' n  v0 N  p2 Z, U
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;/ M4 ^6 V) @; T8 [7 R# t0 M
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# z# u2 Q- M& ]) e) P7 e4 _
( t2 T8 c0 M5 n8 ^
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& q, e% a" h- v
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
; ?! U7 a; K1 Q, z. B( |% C                QueueFlush();" F! ]6 Y) ]0 I8 s/ E6 Q3 O/ W
        }
- I  o0 U; P$ U$ Y, {3 t) k3 t* d2 U" |% X; F
        while( dwLength-- ) {
& Y; Y1 d- K. ?1 r$ ]                writetime = (DWORD)elapsed_time;& L5 E4 ]! s/ L" [& y
4 k+ A8 Q5 G3 ^, h
                while( GetQueue( writetime, q ) ) {
/ ?1 _9 |( f1 T7 X' X                        WriteProcess( q.addr, q.data );! K) k. c. R8 h+ b
                }
+ \! z' |4 }) h( Y$ Y* ]5 w  `- s- s# a5 b, \- v- j  S* b- l& O  M
                while( GetExQueue( writetime, q ) ) {4 `$ Q( q6 f9 i
                        WriteExProcess( q.addr, q.data );0 [! s3 {3 E; ?! H  i2 ]
                }
4 S3 ]# I8 q* v! \+ M9 ?
" p5 Y, R% g1 g8 I' N                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
% I  E* X4 O+ _                output = 0;
; s( m9 g3 J, ~" j' f0 z                output += internal.Process( 0 )*vol[0];. P5 J% @7 u) f2 p
                output += internal.Process( 1 )*vol[1];
& w1 A9 q& k0 l/ e+ N, i6 I                output += internal.Process( 2 )*vol[2];/ X2 Y5 M, @! Y  e9 F! H( W
                output += internal.Process( 3 )*vol[3];
7 Y3 A/ P. o) f" [                output += internal.Process( 4 )*vol[4];
- b. o7 b- S6 G# v) I' _8 N2 I2 F- c! _) {* n
                if( exsound_select & 0x01 ) {2 g5 r& Y6 G( e) Z1 s' {1 g) N
                        output += vrc6.Process( 0 )*vol[5];' \, W7 B* ~* n( W  v1 n
                        output += vrc6.Process( 1 )*vol[6];/ o1 h+ J6 _2 w, g. L% }
                        output += vrc6.Process( 2 )*vol[7];
3 A: [& R' S3 R+ f& r! F                }# r! |( Z& |6 G
                if( exsound_select & 0x02 ) {
1 a+ {( m0 x- c5 P" v+ T                        output += vrc7.Process( 0 )*vol[8];
5 L1 K' M: `* R- {. M                }
. D4 h: L1 T9 }; x' q: g                if( exsound_select & 0x04 ) {& Z7 z! T& q* v/ R/ c' J
                        output += fds.Process( 0 )*vol[9];! V5 E7 Q4 m6 S: D$ Q' r; t$ v+ l7 c
                }
9 I6 k2 I7 E8 a6 r; d                if( exsound_select & 0x08 ) {" m: |% v* a) k  j: @
                        output += mmc5.Process( 0 )*vol[10];
  y' f2 Q7 L( i( b                        output += mmc5.Process( 1 )*vol[11];
1 q) h! X9 T; f+ W( K                        output += mmc5.Process( 2 )*vol[12];
4 ^$ G, B: X' w. o- q5 P) }                }; g2 y' i8 h+ ^$ ]
                if( exsound_select & 0x10 ) {: s1 V# B+ \8 ~* x/ c3 }
                        output += n106.Process( 0 )*vol[13];& ?6 O9 `. F, m0 {4 h
                        output += n106.Process( 1 )*vol[14];
8 a! K+ }( j5 L: Z2 W" V7 |                        output += n106.Process( 2 )*vol[15];
3 z7 A" Z# }$ v- P' d                        output += n106.Process( 3 )*vol[16];
" \$ w& G3 C/ E5 F                        output += n106.Process( 4 )*vol[17];, \' n, j4 B* a2 M$ `) u: t
                        output += n106.Process( 5 )*vol[18];
' J# S8 J# ]: ~                        output += n106.Process( 6 )*vol[19];( w5 L. \' V) d  F
                        output += n106.Process( 7 )*vol[20];: y! t7 u% K0 _$ F
                }4 n% S# i( n4 B0 q
                if( exsound_select & 0x20 ) {
0 V: n# _3 }* a' ~3 h+ G                        fme7.Process( 3 );        // Envelope & Noise1 X0 d6 J: [# m! @5 k+ H$ z9 Z! f
                        output += fme7.Process( 0 )*vol[21];
0 e' i& q+ g4 a6 d, T- v                        output += fme7.Process( 1 )*vol[22];: l( t' _0 u% L' w" N6 A. L5 k
                        output += fme7.Process( 2 )*vol[23];" {' @6 d1 s9 z+ E& i+ N8 P/ `2 C1 m9 |
                }! O5 g% C3 q3 m3 T) r
- [6 b3 c  H! e( x/ H+ j' I, ?7 l. c
                output >>= 8;" Z! w6 y5 F; u* ?; J. N, [

* D8 A5 F, h8 o4 p- h5 L                if( nFilterType == 1 ) {
$ N; ?9 P2 S6 a" W/ }                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 B( }( e  y1 Q3 L
                        output = (lowpass_filter[0]+output)/2;
+ U/ y  A' q$ L& Q1 k                        lowpass_filter[0] = output;
+ {5 i% J" E- T: p1 W                } else if( nFilterType == 2 ) {. L; g( v1 ^9 e6 R8 [) d
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
* f  ^! Z+ H) {" H5 \* m3 o; l                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* S; v! x9 ?% u. g: N
                        lowpass_filter[1] = lowpass_filter[0];' C5 M* I" P  S( v; l
                        lowpass_filter[0] = output;
9 n% b1 R' q+ R+ y& q  x                } else if( nFilterType == 3 ) {
" j) b; c- c8 X0 X0 H5 a                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
5 I  q. {, L" u2 K8 S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
3 p* u7 R: B2 S. p                        lowpass_filter[2] = lowpass_filter[1];6 T# @6 _7 _  _) ]
                        lowpass_filter[1] = lowpass_filter[0];
( ~! |2 H5 z$ f/ T: y) F                        lowpass_filter[0] = output;
3 n( o2 P1 o5 U/ Z" r8 B                } else if( nFilterType == 4 ) {
4 ^9 H( k4 E0 g5 c& e8 H# {                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)7 `" C$ D+ D  X- V1 l
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( T: ], o( ~6 M. k                        lowpass_filter[1] = lowpass_filter[0];" w1 Z# `5 [! O5 E6 M
                        lowpass_filter[0] = output;+ y$ C' E* W5 }' U( ?$ X
                }( e+ Q. Z; j; G1 H% k0 S7 q

# d" B0 k- G% f2 x; ?#if        0
$ a$ a* ^' \' \2 q) I                // DC惉暘偺僇僢僩
( t; d4 I1 y, o( r                {2 R2 W. V% T4 ?" f  v; A% h# G
                static double ave = 0.0, max=0.0, min=0.0;1 X; e9 U: K7 v
                double delta;7 D" A. i) x' l2 H" {
                delta = (max-min)/32768.0;
) v; H" F$ q4 x  A4 E0 g4 ~, t! n/ y                max -= delta;
/ d( T6 e( v9 X6 i  `$ j; b( u                min += delta;
, @/ ~6 y1 O! }! ~  P                if( output > max ) max = output;
. Z$ ^1 v% X( [                if( output < min ) min = output;
, e) ^& V  ?! n6 \/ G2 }                ave -= ave/1024.0;8 |1 |3 s8 v0 n3 Z* |4 ^
                ave += (max+min)/2048.0;& f" e$ {# }/ X7 w4 r& J4 B
                output -= (INT)ave;
' ~, T) i! a' b( Z# j                }
! I% i  t- X/ e1 O#endif$ M3 W  [+ X2 ?3 p2 F
#if        18 Z% R& o9 Z6 J8 y% ~/ V: n
                // DC惉暘偺僇僢僩(HPF TEST)9 J- k" \/ v" ~- E# K
                {
; y0 W& Y* H, M2 V; b//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);+ Q5 V& x: V) {5 v
                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 G0 N, e* D) b" J7 n, j3 d$ ^- Z
                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 B( }2 |2 o  L! K- W2 d
                static        double        tmp = 0.0;- o+ r0 A' {$ I
                double        in, out;
5 m& Q+ q% h0 E- l/ w0 ~* D7 _! C4 }" ~4 V1 x/ a/ u
                in = (double)output;
2 h; T# ~* \& h, F( N9 P) h1 M                out = (in - tmp);
4 A# a9 @/ D2 s; D                tmp = tmp + cutoff * out;
9 q0 M$ A' t9 N5 F: j4 P; S$ V; J8 h8 B* W
                output = (INT)out;
1 M) ^% O5 X& l) Z5 {# A9 t1 ^                }  S6 o% b% |/ I, B& [% ]
#endif
8 {$ K& Y# j* P6 d, Q* S% o. ]  t  Y- |#if        0
& Y8 ~" c- ^1 q" K2 q* @                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)# U; Q2 _8 g! k4 ~1 w. t
                {
4 I0 ~1 ?- |/ ]9 }) v                INT        diff = abs(output-last_data);
* {2 b8 S; ?# _                if( diff > 0x4000 ) {1 Q- Z' {! ^- o
                        output /= 4;& v7 t0 X! Q' q# @
                } else . u- Z2 H$ O: y4 S
                if( diff > 0x3000 ) {
0 ]4 x" v8 y) Z' e" c                        output /= 3;; ^5 W$ E1 j( n) }# w4 d% r. x
                } else
/ l; g- O" K, r  J4 F# a6 s                if( diff > 0x2000 ) {
% ]' D* P3 K6 y- M                        output /= 2;; M1 `. c3 p+ v- [
                }
- Z% k; M, r- D8 G, Y. v                last_data = output;" T7 A. K+ J. {$ b
                }/ d7 a$ h2 F, |8 |. q) Z
#endif7 X  R' F5 ^3 ~5 M* }, v
                // Limit5 ^# Q( r7 x7 Q6 w; k
                if( output > 0x7FFF ) {
) L( _$ E5 j4 @6 [) S* k% T                        output = 0x7FFF;
$ R! e6 z# l1 X( ], H  v                } else if( output < -0x8000 ) {# H% J% y* }: \$ ]# u2 I3 [
                        output = -0x8000;
2 L4 k. [9 h/ J8 T( g3 M                }
" m/ V6 y0 _5 o  a3 g! U# [1 y$ H( p/ U4 }8 T
                if( nBits != 8 ) {
/ p: l/ \6 u! D* H                        *(SHORT*)lpBuffer = (SHORT)output;
! A- Q: @* S$ G: T                        lpBuffer += sizeof(SHORT);4 _$ y& f0 C) r* z; l; S5 @
                } else {
* V* z& z3 }5 q' g# m1 s                        *lpBuffer++ = (output>>8)^0x80;' A# R5 k: g* G( ?; O: j
                }
. n. S' D$ P: z  o0 w1 Z  I% {) J
                if( nCcount < 0x0100 )% Q! S. K9 q- _3 C9 _/ W# v
                        pSoundBuf[nCcount++] = (SHORT)output;
3 }2 [2 o" I! O  U; f: T  D7 M7 P$ i9 v  K+ z
//                elapsedtime += cycle_rate;4 E; j8 K2 ^$ h2 S+ Y1 M3 S4 D
                elapsed_time += cycle_rate;
, a! }2 Z8 p) V4 Q/ [/ b        }  }; ~3 ]% r1 A# D
1 k: f' E  ]: L+ Z! {
#if        1! T  @/ ~+ V- X
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {) m1 H2 f! \) u+ D8 s
                elapsed_time = nes->cpu->GetTotalCycles();
8 J( Z5 g* r1 D        }% l% n8 y0 m2 ?
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {. k+ O( P9 [: b
                elapsed_time = nes->cpu->GetTotalCycles();. F1 v4 U4 `# u9 S8 e3 b
        }
$ B( ]9 r. x5 v4 [#else$ Z& r! c2 r+ \/ L
        elapsed_time = nes->cpu->GetTotalCycles();+ n, O# e- s/ M% Y2 A
#endif
% O" ]3 R4 T0 N}
. |- ]  _) B5 p
3 L9 A' ~* I+ a0 E( Q+ `* u. E// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 \5 V  g0 s' Z6 u1 |1 b
INT        APU::GetChannelFrequency( INT no )
' p- \1 x  a) t) `- r6 `{
  I& E3 C8 i$ M+ P6 x* n& \- I0 D        if( !m_bMute[0] )* g9 V' _3 ]$ d: f' j
                return        0;% d! J9 M% Q( f7 e8 @( g7 }
# d7 g$ i& d7 U( A% K- ?2 {* c
        // Internal, L7 o: X" m9 g3 N% [
        if( no < 5 ) {
0 i5 X$ S5 C3 j; `* N/ h                return        m_bMute[no+1]?internal.GetFreq( no ):0;) V% Z# j( I0 v2 u
        }
7 ]$ S( _1 G) W; ]/ p        // VRC6( K* }8 [# s& f5 w! \
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {. v( I1 a  g/ M$ a9 j
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;" y; N/ Q% N6 g0 w9 u
        }
, L! J/ j4 _1 S# Y" `, i/ M        // FDS; c& i/ D0 }! i7 e, B
        if( (exsound_select & 0x04) && no == 0x300 ) {
! S( P+ f1 ~9 {5 T, z5 h                return        m_bMute[6]?fds.GetFreq( 0 ):0;
4 t$ N7 s8 l5 ]/ ]8 r/ @0 v        }
" @0 I, K: V! d- m# h( Z+ b. ]0 @6 R        // MMC5$ b4 k- C/ L' t- x
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, W- f% q# U( J' z+ o1 _                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" }) w+ G$ g4 T& J' k5 J) M
        }
/ Z' e9 ]8 {" W$ Z7 a$ t        // N106) D2 Y5 d! U7 H% o5 a  k; `, A
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {" k4 R! P5 I* K4 P' a3 s( U
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;! Q( u) q0 y% N8 P& e) j
        }' u) o& X% J. h5 X
        // FME7& _" \) @5 Q; H' L* Y) ?
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 N3 Z) n3 J: i/ D# m  H1 i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
+ W; g9 F" v  @4 I& R% p        }/ y- w% u+ c& N3 Y1 z. J
        // VRC7
/ m* `3 M  d- Q" C        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 H8 Z' v8 [$ s) y                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
. C$ @( V5 o0 @& L4 g3 }        }0 C/ i0 u9 Y: @7 E+ l1 H8 @1 v
        return        0;5 F! t% G# M7 i0 h
}- |* F  G7 M* s3 {4 r6 M

& N1 Y( [  D4 O+ `; X0 j! d" v9 x6 V4 C// State Save/Load
& k: i( F' v8 H% H2 e$ kvoid        APU::SaveState( LPBYTE p )& z8 n$ Q' J2 q: k/ G$ o
{
1 c8 l. |7 \0 v: N#ifdef        _DEBUG) J: A# D+ M9 w
LPBYTE        pold = p;! q, \! B2 N- z: L$ h
#endif* C1 s# @# z4 N. t" g; E

1 y( Y0 T5 \. Y/ l4 I+ P& Y        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
. A' Z5 y4 d) |4 l" J        QueueFlush();5 D; d1 T# E! X; G/ D
$ a( M0 D) k7 H1 E
        internal.SaveState( p );6 v/ A8 r: h- M& u8 O% D
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- y# W9 ?- y6 q1 t, `& T7 o" Z+ r, p4 v) f4 d
        // VRC6! b3 r, ~+ U) m! ?  f. E* b
        if( exsound_select & 0x01 ) {
; }2 `# q- [; Z3 ]                vrc6.SaveState( p );
% N7 H3 q' E2 }  Q' Q% z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- r' z- E  V3 ^6 j. v; f        }. T7 O9 \' |0 K/ N5 X# T: r; R( N
        // VRC7 (not support)
1 v% l; c; X) I8 z/ e  F7 x; F( s: i        if( exsound_select & 0x02 ) {3 S- v8 W% v; [5 m0 y
                vrc7.SaveState( p );
% l, \. ~8 b% x+ {' Z6 h# s! y$ Y% q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" D2 }+ J  z: [0 z* f8 s
        }- H* V+ }# g# k7 m: G7 e- ?. G
        // FDS8 F3 k$ b# w. |4 r9 L
        if( exsound_select & 0x04 ) {
' A; Z" P' o1 n" Z7 l                fds.SaveState( p );9 }) a& k0 L) h4 m4 [7 S& ~
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 M& Z! E% |2 A0 s9 w1 A
        }7 ]( R; J3 X7 l- m0 O; d+ d
        // MMC5- ?2 ]. ?1 ~- r7 J
        if( exsound_select & 0x08 ) {' e3 f& O! L& O, v5 N
                mmc5.SaveState( p );
: e" t, p# R5 f4 N+ ?' b. i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! M* i, m# G5 ?* o1 x        }
5 S: R7 i5 Z4 n        // N106
" p$ d8 \5 L+ N8 r  {5 ~3 |3 a        if( exsound_select & 0x10 ) {
& M  Y" i. Q  s& ]- k$ i                n106.SaveState( p );
! D' J# U( {; x+ n" T! r) L                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% T6 i0 L- ~- `0 B% z
        }7 y$ |4 S* t: J" j. j" Y
        // FME73 }  y  E! b& V
        if( exsound_select & 0x20 ) {; C# J/ y' `7 d3 {
                fme7.SaveState( p );
( t/ A5 _1 |. M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, Z* [+ G+ M2 y! P9 i& h        }/ r8 s1 {/ P/ F% U
9 u; F1 c# I: w. [+ L
#ifdef        _DEBUG8 T9 j7 H& O6 y6 I. _  G! {
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 w! s5 N1 F0 f, O#endif
3 |& J! E$ J% z% C6 H4 g}
! J2 C. Q- q9 @( |( G
6 W( u1 B5 a! S  L9 x1 o6 Uvoid        APU::LoadState( LPBYTE p )
6 P" k5 @: z0 C3 A8 F{! D, ], C" {' P, B; Z: E/ H' P
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡8 b& {% u! t. @/ R' ?' }  g
        QueueClear();
# T. h0 f' t  B4 |% f: L* Q" r5 T) l
        internal.LoadState( p );. d$ z; A  w4 |* t( {
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: \! }0 O1 h6 d6 p5 q) x  R) a- P2 P; A8 z; Y, o
        // VRC65 W& G( R% h6 b9 E
        if( exsound_select & 0x01 ) {2 O$ b. W; _' J; C) x8 S1 ^8 P' K
                vrc6.LoadState( p );' b0 Z- L$ o9 O4 b8 ~- Q" U
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% W; C& {+ i, j5 w5 F* y        }
) x" G2 f  ]8 g( W8 C        // VRC7 (not support)/ R# V2 _$ Y) d5 ]7 I2 t
        if( exsound_select & 0x02 ) {
. B& |0 S' f1 }$ i6 C  Z- `                vrc7.LoadState( p );  D2 v# f8 p6 y  t
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  M; o! V! t/ w& B  k
        }
- h" Q* S% m$ ]" r8 g        // FDS
+ g7 d9 O0 v+ Q        if( exsound_select & 0x04 ) {/ Z% I% S+ \& b3 J0 a
                fds.LoadState( p );2 X8 |4 V7 N$ K* \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 w- l; D- q& j) V. P  M$ f        }! ~" X# ^/ o9 u% p
        // MMC5
8 a" A2 A1 Q! c) u6 _: c* ~1 ~        if( exsound_select & 0x08 ) {+ v( l3 l5 s. v& G: E, }0 R3 P
                mmc5.LoadState( p );
5 r1 ?3 s; u0 @1 z7 [& D  G                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 y, S6 E! h: B, g6 G' z* I        }
/ w" W# R0 s4 _0 y2 J" P        // N106
* V! d. K9 H0 r/ O        if( exsound_select & 0x10 ) {0 s) H" J; `  c+ n
                n106.LoadState( p );4 e2 U  H) k; I
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 E' C1 |: s' k3 v9 L
        }) Q- L- p2 u  k+ i- T! A. Y
        // FME7
' ~# h- F3 ~; u& V& n        if( exsound_select & 0x20 ) {
6 [0 C, S0 R/ b  [5 u                fme7.LoadState( p );9 j7 v: M* u& \; O
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, d: F7 H1 J4 O  ]' ^: }6 }        }
' ~! i' m! a9 K* e# E2 v}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 S! P4 g! R$ z1 w' y6 j& z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 Z( d( K( P- d5 k, P" S- n2 r
感激不尽~~

* J6 m" a( W3 _+ v恩 我對模擬器不是很有研究,$ E# z0 y1 R0 N; s8 A
雖然要了解源碼內容,可能不是很困難,2 m3 _+ x. t# G
不過還是要花時間,個人目前蠻忙碌的。
# i% {, G! J; z5 a2 K% T5 b6 D# g  }: u" @
給你一個朋友的MSN,你可以跟他討論看看,
3 }% \1 w! _5 O. X# k, a* W他本身是程式設計師,也對FC模擬器很有興趣。) T9 j* v8 T1 l( ~5 V

0 _3 Y  P2 a/ g# O1 TMSN我就PM到你的信箱了。" j5 q( w) H# t! {
- r6 Q- N: p& O, c; ]  `% N' M0 N) }, M
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
- A# G. u9 ~6 Q3 x呵…… 谢过团长大人~~

/ A6 _. A* z- J* [7 t  `3 L( ?* h" M0 I. z) `" c+ T9 l% ^- L9 x
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
, Y; x7 x% w0 Y8 _7 C; B团长的朋友都是神,那团长就是神的boss。
. F0 R* N# s# m+ e% r
哈 不敢當,我只是個平凡人,1 {& P6 V9 U0 c: l
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) \' G2 O2 z! s6 e4 fZYH3 T% J6 o( f& L6 U: l
QQ:414734306
6 [; ]- m; i) d5 Q0 H6 }/ EMail:zyh-01@126.com
; J; E) h- q5 ~
. L3 K# S. H: Y: s, x他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表   S9 V$ A! j* |0 x" F; b/ o& }7 p# S
再次对团长大人和悠悠哥的无私帮助表示感谢~~
) E5 F% a" S& v% |* }
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-27 22:40 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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