EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 P  a: H5 l3 c5 z2 A
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) L% j5 k4 o% q2 U1 e0 u- W, @; C这里有相应的模拟器源码,就当送给大侠了~~
& {! g5 M* T& ghttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # [$ {) V% c) }0 L2 L
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  L( Q0 W8 Z2 T楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( E4 u8 D: p- j7 G
这里有相应的模拟器源码,就当送给大侠 ...

( _- w7 ^) v3 _* w1 i# Z聲音部分(Audoi Process Unit = APU):
) |8 {' Y3 S2 g.\NES\APU.cpp
; `% ~7 C3 |& v2 l. L, ~: M.\NES\APU.h1 S9 u' T) M( r/ `* W
% l) i( {6 I2 z. G* d3 T
( j# v" x; C# g1 \" P; B) X
影像處理部份(Picture Processing Unit = PPU):
' g/ i' T* J& A.\NES\PPU.cpp  v+ Z: x1 M" u+ A( r. B2 I9 O7 f, b
.\NES\PPU.h
* N/ Q" U9 B, l2 f; b
9 ~/ B* b9 p5 n: I- \$ U如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:: f- |9 S: L5 ~) J7 k3 d
(由于很多专用术语和算法机理都不明白,所以看不大懂……)# m: c5 ?, X2 {( D. \
//////////////////////////////////////////////////////////////////////////  G; J9 P3 _# l$ v
//                                                                      //' e+ O9 l. C' J% r  a" W8 {5 h7 k
//      NES APU core                                                    //( K: |) o8 j% ^/ z: g4 [3 p5 ~
//                                                           Norix      //7 H# J# u0 |: o1 B6 r
//                                               written     2002/06/27 //. ~2 k# d# ?' s3 b) U
//                                               last modify ----/--/-- //5 P6 A$ C# k+ J
//////////////////////////////////////////////////////////////////////////
# V; k2 Z1 Y0 s7 ]5 ^#include "DebugOut.h"8 r$ s2 }3 F( B; s. _% I; E+ y
#include "App.h"( s3 O  G( ~; D5 k
#include "Config.h"4 ?6 f8 E4 h8 E4 _- P

8 n5 J; I. x) j2 g- R#include "nes.h"
4 S8 H; k7 M2 W" z3 Z% [#include "mmu.h". i. z& P6 r1 r. s
#include "cpu.h"3 b! ~. |3 b* H* E5 ^3 |" L
#include "ppu.h"7 }# I/ P$ a4 |( W
#include "rom.h"+ x# Z% X# i4 j- O8 T. Z
#include "apu.h"
# {  Z( y. a& O) l: t/ r7 {" d$ H
, _0 U1 {1 b$ s6 E2 |' T! U// Volume adjust- [( J4 |6 L# u) k/ G" W
// Internal sounds
9 Z5 M3 Z2 ]8 W2 l5 P#define        RECTANGLE_VOL        (0x0F0)3 A1 e& t" r" E3 f
#define        TRIANGLE_VOL        (0x130): ~. U* m4 c# S
#define        NOISE_VOL        (0x0C0)1 P0 [$ Q; j& F. S' f' b" ^
#define        DPCM_VOL        (0x0F0)9 O( w( I' g! \% a7 k* s7 p+ z
// Extra sounds$ N6 a8 T: K, h3 G
#define        VRC6_VOL        (0x0F0)6 ?4 _- [' M' e
#define        VRC7_VOL        (0x130)/ l# D% J8 @$ I  U/ j
#define        FDS_VOL                (0x0F0)& N4 B5 J2 I4 \" m( N. E
#define        MMC5_VOL        (0x0F0)
* z  f) q* s& d- E* v# v' B#define        N106_VOL        (0x088)
1 ^8 W! B' P; F( D: U#define        FME7_VOL        (0x130)$ ^1 [0 E% g* w( s) J

, ^- W% w) |% s# Y( [APU::APU( NES* parent )$ ~! T" X. \1 q, l+ `* Y
{
% V2 k: d- j6 Z* Q1 C( E" i        exsound_select = 0;
8 A1 }4 R) v4 D
. p) m4 _+ Y9 o& ]* |" v        nes = parent;
3 R& N: V! D/ ?$ Q        internal.SetParent( parent );
1 e  h/ x: e  Z" o# O7 Y% t5 ?% _2 i* @) L- o& G
        last_data = last_diff = 0;
' m7 H: g" b+ h! B* C* \
& V3 B; m' ^7 E5 A. {* _- P        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 ^- H9 T+ @6 q) O9 ~

% q; H0 X3 v  B5 y        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );1 a# F* w, f2 t+ J
        ZEROMEMORY( &queue, sizeof(queue) );
' S7 m  H/ [  N% r' S5 w  [8 O& b        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 X. _! m3 Q4 C/ J9 j9 h3 {9 B1 m  D8 }$ u0 w
        for( INT i = 0; i < 16; i++ ) {
$ v( Y; i) d/ t- n, w1 z                m_bMute = TRUE;( A% C' S2 ^6 t5 V
        }
  D% t# E% J. S+ I5 f}$ D: j; Z$ p* r: e, {/ {) z+ l

# z- {% b* z' I2 \- b8 {, |APU::~APU()
4 k0 H* [7 x$ K: y{. E; H6 P2 R9 \/ N3 u
}
  A( `+ O9 }; c7 t/ x7 p7 r/ M( k, f! S; e3 ^8 `. f
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
( E2 u+ _9 b& y$ C{) k" f* Q% P$ A
        queue.data[queue.wrptr].time = writetime;
+ E. x' S% N3 w. b, n3 A% ~        queue.data[queue.wrptr].addr = addr;: g, |. E3 t( z+ [! j
        queue.data[queue.wrptr].data = data;4 g' v& \) K6 u# |
        queue.wrptr++;
/ E- Z7 l% o3 H        queue.wrptr&=QUEUE_LENGTH-1;
3 [% m5 m3 ^" R        if( queue.wrptr == queue.rdptr ) {
, ]% Q3 ^0 d- A! U8 y8 G: e                DEBUGOUT( "queue overflow.\n" );
6 r  Y3 l, h; f- A        }
2 G4 T; Y- E' V3 p}! b  w7 a9 c2 Y( I9 |& ], {
, a6 L* h* q( P6 ~* [2 ^
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. g1 U% ~% ]" t% N' g5 u5 X( W{
' _# V; }  c' {: `# ]        if( queue.wrptr == queue.rdptr ) {
9 @  q9 _* O. X! r. [                return        FALSE;- z$ U. \$ Y7 ]2 c8 |; @( P( e9 b" S
        }
- S' o' t: _0 t% ]% _2 d) O        if( queue.data[queue.rdptr].time <= writetime ) {% _2 L( [2 D- }
                ret = queue.data[queue.rdptr];4 P6 L/ e. Z. G
                queue.rdptr++;
+ R, R0 D" j7 p0 [& R5 J                queue.rdptr&=QUEUE_LENGTH-1;
8 K6 ?6 J8 ^9 n- i                return        TRUE;
9 I. g6 O  K' f) i        }
# S, O4 A* C* S        return        FALSE;
0 Q6 h) n* i: U}
6 l& R" U' A. O; `2 b' G+ C  {5 x- l( M, G% s. L$ i0 h
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! l# R7 u2 F5 B% D8 l( e
{
9 J* Q5 O0 M0 V; K' r: k8 l) P        exqueue.data[exqueue.wrptr].time = writetime;3 I% r# _4 F" I4 F& y
        exqueue.data[exqueue.wrptr].addr = addr;% r# J6 ]+ z0 n" |5 ^% H
        exqueue.data[exqueue.wrptr].data = data;
8 d3 H- Q1 @* @+ Q1 i6 y" A        exqueue.wrptr++;
4 [9 V; _3 m  V& L' B6 J4 A( N        exqueue.wrptr&=QUEUE_LENGTH-1;
, h6 J6 ~( w# z" i5 R& g+ [* w        if( exqueue.wrptr == exqueue.rdptr ) {, M/ R5 S* q. T7 J
                DEBUGOUT( "exqueue overflow.\n" );# T" m4 t* K4 d/ |: U3 J
        }' h4 h& K5 v3 Y. L% }# b% E  |
}
; d. W! E! Z1 M/ X2 S
! X! @' p. p% b2 y. p+ MBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ). z8 }. F% u! {' ?3 H1 V
{
- @' S$ W: e/ A        if( exqueue.wrptr == exqueue.rdptr ) {" ~0 C, m) {% w+ W
                return        FALSE;( y4 \/ I5 U3 ^9 m6 H8 g7 e, E0 s
        }
  U7 W% H5 A2 [8 Q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; a& H8 }* K5 d) C
                ret = exqueue.data[exqueue.rdptr];
% ]' t# h3 A7 {7 d  {* \1 z  m                exqueue.rdptr++;
& `1 f; R2 o* _( C% q/ ^                exqueue.rdptr&=QUEUE_LENGTH-1;8 Z0 v; z& K! }% P# A7 z! `* a
                return        TRUE;/ @# ~7 e& e% _$ f' R' [3 ~
        }
: w9 V+ ^# G8 q) ^2 X4 h        return        FALSE;
) J& T: B6 [$ l}
- e5 g& m4 J! L; K, k4 _' x4 _1 t$ m3 J# C* q7 O8 ?
void        APU::QueueClear()
" Z: `$ ?( {$ \% u; P{
: u! r4 ~, H: p0 _% [4 `' _        ZEROMEMORY( &queue, sizeof(queue) );
- U. y! v. L1 m0 S6 \        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 O7 Z0 O: g0 [1 i+ j4 W$ E+ ?}
& ~3 V+ }$ T8 d" `' V% P" n  h# D" X7 f6 l0 o1 M  V& T# F
void        APU::QueueFlush()" H$ X# }0 I% E  E1 K! r) D
{
5 c0 R4 \0 y, V- |        while( queue.wrptr != queue.rdptr ) {1 n- v6 Z+ [0 S5 o9 w  U1 L% o
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
( ^5 A" L# ^3 w+ ^  g6 D                queue.rdptr++;
! n1 N$ n7 ~4 C& s  s" {" Y                queue.rdptr&=QUEUE_LENGTH-1;
( H1 }3 C3 C: Y( G" t  ]; m3 \3 V) @        }7 y! D  t8 @3 q: Q) z( u

: C5 d8 X5 l' k8 Y1 N" G        while( exqueue.wrptr != exqueue.rdptr ) {( L! b7 ?. v8 e9 w
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: v' a" X7 r# H                exqueue.rdptr++;& T* q2 A9 W( v; E/ k4 i
                exqueue.rdptr&=QUEUE_LENGTH-1;4 {0 C- \4 V  }9 V* z
        }& t6 K4 m; J  ^. ?/ b
}
5 R9 L1 g" P( \1 a8 A  r) Q$ V# Z  X7 y
void        APU::SoundSetup()
4 @7 f& [- h# F( a{) B. T) k9 P% {; W  q3 O* Y+ T
        FLOAT        fClock = nes->nescfg->CpuClock;
8 }! B" t5 P4 j. N: U        INT        nRate = (INT)Config.sound.nRate;- \: g0 @; _0 G. G! q8 D) t0 y
        internal.Setup( fClock, nRate );4 n3 x3 G4 u9 w
        vrc6.Setup( fClock, nRate );$ o' a3 b0 ]" A. y# \' w0 ^
        vrc7.Setup( fClock, nRate );6 K- F) Q7 H( b0 `+ n( f
        mmc5.Setup( fClock, nRate );
& u% K, s, G& w2 F* p$ B$ I        fds.Setup ( fClock, nRate );
/ l9 F% w* z3 f+ K4 ?( V% `% j        n106.Setup( fClock, nRate );2 k, J; E( K: i: V) E' R$ R9 J  E
        fme7.Setup( fClock, nRate );
1 u' H8 A$ O, Z2 A}! W6 J9 s( \- h7 C, s" I
0 F# D9 ?- [8 J
void        APU::Reset()
6 l/ T# {7 F( W$ G9 n) g: ?{
* M4 N' \/ X6 h        ZEROMEMORY( &queue, sizeof(queue) );( ?0 L% a4 H; H% @4 x
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* w9 v/ }5 \4 n/ n! z/ t4 L
8 l# i) A! h% s9 Y7 L        elapsed_time = 0;# b2 j$ E5 C1 y. S$ ~# q8 E
+ D! _$ d# N  Y; v& }4 V* r8 ]2 S4 \
        FLOAT        fClock = nes->nescfg->CpuClock;
! A; |0 k. Z' I; M" ]4 ?7 ?        INT        nRate = (INT)Config.sound.nRate;4 \" z% ^5 l% `4 F2 Y7 o) |4 |
        internal.Reset( fClock, nRate );# ?, d7 ?* V0 b* K
        vrc6.Reset( fClock, nRate );
1 N. X$ P4 c$ i9 n$ v/ C        vrc7.Reset( fClock, nRate );
+ A7 n" C, J3 K! e( T        mmc5.Reset( fClock, nRate );
$ B7 L! i, A) M; t/ g6 G  n1 |+ c0 u; c        fds.Reset ( fClock, nRate );
- u6 f, V8 |, |1 ?, c) i1 i0 n' ]        n106.Reset( fClock, nRate );
( R7 {) ^6 `# A2 ^        fme7.Reset( fClock, nRate );: T2 f8 V+ R9 v! E. B  `
2 s7 P7 I# Q1 M( `* q# A: I
        SoundSetup();
. Q& X8 B9 |. A$ M5 t" k4 v}" u6 `0 v- |8 M

0 k% I* i+ U& E( s0 |' f. x: q, ?  G0 d3 kvoid        APU::SelectExSound( BYTE data )
5 y9 x2 r% R% m8 X  |5 P' \1 Y{
# \  d- A9 J1 N6 T0 l# ^        exsound_select = data;* k1 k4 J6 P3 o  ^$ X7 P; l
}
; E9 G) o6 o- w
# X# _# `( G# P7 hBYTE        APU::Read( WORD addr )9 g# J0 O; V: t% P+ z8 n
{- f& [% ?2 P) E9 j+ a
        return        internal.SyncRead( addr );
* R0 @4 i  g5 z6 e& {}
8 x, y- ]( X+ J) b& ?) a# J) s
5 Z* W* y' m9 c- kvoid        APU::Write( WORD addr, BYTE data )) @2 n, \2 G/ g3 z+ I- H
{1 M1 d4 X! o5 u6 t; A  s
        // $4018偼VirtuaNES屌桳億乕僩
4 ~# q* C8 K9 F5 E# K2 _6 b/ Z* }        if( addr >= 0x4000 && addr <= 0x401F ) {! H( f! ~, m4 L9 C7 P: U
                internal.SyncWrite( addr, data );
2 s- e2 V0 V3 s+ E                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& \0 u. Y5 S4 Z5 {1 u+ T1 z
        }
9 W( i3 a! N/ b. c}
% T! {" z4 K3 p- ~& t9 i8 \" P4 y4 y- `" z
BYTE        APU::ExRead( WORD addr )
7 O  j  \0 L. y4 ~6 R{4 i2 {/ j7 N& O0 H/ q
BYTE        data = 0;
1 T) O; Y8 P# v# y# |7 F5 b# t% A, x& @  {* h% R6 a# t
        if( exsound_select & 0x10 ) {$ z8 K7 j; m! W  P
                if( addr == 0x4800 ) {
8 i( J  o/ g# z                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 g4 Q5 c5 b. h
                }! a0 n  @* w4 }- E4 k: v
        }! E" E4 {. E$ {" n! C- L& {
        if( exsound_select & 0x04 ) {
4 ]0 ?2 \! w. D" u/ Q* W9 f) x                if( addr >= 0x4040 && addr < 0x4100 ) {
9 ?. O9 c/ M0 P                        data = fds.SyncRead( addr );
% d) }% z  J: \) ~: l- v$ Y                }
5 p2 p; w# P& [        }# e: r! X  F3 c1 |( s% \
        if( exsound_select & 0x08 ) {! R4 f( ~7 ~+ f6 {( v9 Z/ Q# h
                if( addr >= 0x5000 && addr <= 0x5015 ) {2 _; G7 d4 v1 U* N6 ^; F
                        data = mmc5.SyncRead( addr );0 J/ E* n. D5 g3 }* H$ @
                }0 V, t: \  g; ^/ z3 `; M. F# D) C4 g
        }8 o8 a) ?1 ~9 V$ L

- {7 c3 y" ~9 k9 a5 N- a! }9 M! W        return        data;' V# T$ c  n4 [% e* a6 R0 i
}
% X! F( X( E* l5 r( `4 L- ]+ j4 ^  ^& l; {' C
void        APU::ExWrite( WORD addr, BYTE data )
  a$ @5 c( M  @7 c2 T2 ], m5 j{; S) k$ Q0 W$ a
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );4 U5 i) E8 y: S6 A0 T9 `
. h" C1 {( W* K+ M
        if( exsound_select & 0x04 ) {8 j8 j% S7 S7 t* Y  n5 P( S4 M4 J% A
                if( addr >= 0x4040 && addr < 0x4100 ) {0 I% f$ J9 L7 Z$ ~% j
                        fds.SyncWrite( addr, data );
( w, G9 o" U, G8 g, L$ Z. A* j1 n                }
6 M2 T. \- ^3 w7 h2 N* \( K        }. N' Z; f- ?+ O& _: |
( W4 a) E) G7 G# z) w
        if( exsound_select & 0x08 ) {0 n  ]5 N5 \. u. x' v1 ~5 F+ a5 n
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ F" ?- l( C4 |, U1 O  s                        mmc5.SyncWrite( addr, data );& G9 h1 D  P# X" o; @
                }/ o" o% P+ x5 I' j0 x
        }
9 U6 F. @* R. V  Y" `+ K( S# f}
" ?! y8 G* Q% i; Y9 t. Y5 ]! A" y
- \9 }; `# }. S' @3 U; Ovoid        APU::Sync()" U- W3 |! {! B7 r" `
{( ^/ H5 K; m2 z# n% }( _
}* S9 u& t: l" C9 }- W4 p
. D+ e- t+ h# R4 V
void        APU::SyncDPCM( INT cycles ), F6 m% E" Y  k' t2 N* j5 ~* I
{0 C2 B+ ~' v/ Q7 W6 O
        internal.Sync( cycles );3 A" D/ T! t5 n- I/ a6 b$ c

& F; c( v* n; u' g2 i        if( exsound_select & 0x04 ) {' V6 o4 f& m3 I6 Q
                fds.Sync( cycles );: k4 \. Z  l( X, u% E
        }
1 q! P7 b+ ~4 z( D$ ]1 m        if( exsound_select & 0x08 ) {; F! I, ]) m* p. [/ M4 i) n
                mmc5.Sync( cycles );
) l, h0 Z2 s" ^; N* |        }
3 z3 S/ }, l9 X8 }: [7 \}
5 ~7 ^6 S7 G# `4 x  d8 b! @4 s
* O4 y% i! s9 |* Q! Z! wvoid        APU::WriteProcess( WORD addr, BYTE data )1 x+ s! j$ D% r2 C5 _3 x7 }2 D6 ?
{2 C, F' M9 C$ p; d; f( B
        // $4018偼VirtuaNES屌桳億乕僩
. G; a5 Q4 v% ]7 w( n& R7 f6 {8 Y        if( addr >= 0x4000 && addr <= 0x401F ) {5 p4 T" g4 W3 Z! y2 x. Y: i
                internal.Write( addr, data );3 `6 V/ W$ V! J/ J3 M5 c
        }/ A, q1 Q7 ]( j3 l
}& f4 O6 ~. \0 d! t

; q: S; O3 C( r' i1 V: h- B& Z/ Lvoid        APU::WriteExProcess( WORD addr, BYTE data )
8 ]( W& f. J% X8 f& V{
6 Z8 E3 Q) f+ A" J  X/ I& P        if( exsound_select & 0x01 ) {
3 }5 b$ X# i+ r5 R                vrc6.Write( addr, data );
2 C; {) y, z6 d! l        }( p. X- \3 Z- V3 Z: z, ^" j4 H
        if( exsound_select & 0x02 ) {
$ ~4 ~6 f8 X: R- A0 c# o/ O5 ^                vrc7.Write( addr, data );
# q" o; J" i- X; Q) t& e        }
/ {9 w/ j& @3 z# B7 V6 M) j        if( exsound_select & 0x04 ) {2 o# Z+ ?# s% O8 _' N5 `) v& y
                fds.Write( addr, data );6 |9 a2 z+ S2 v2 e5 ~2 `. E/ Q
        }
- C# Y1 R' _4 X& a0 j* R* g3 n, P        if( exsound_select & 0x08 ) {
7 Y' `4 q( ]$ w4 k$ `/ s% X                mmc5.Write( addr, data );: h! q- U  e. q0 [: u
        }1 A/ r9 j# O1 _: `
        if( exsound_select & 0x10 ) {
. X: R) \$ U# [! b9 ?% H                if( addr == 0x0000 ) {) e/ n+ f% K& c
                        BYTE        dummy = n106.Read( addr );9 M0 ]3 t# T9 W) S! D& V
                } else {
- z$ c7 h  {" T0 ~                        n106.Write( addr, data );. W0 p6 ]7 S9 Q4 N# r
                }
9 g! h/ e6 r8 q  X3 i! q        }1 ?7 l& O( `& o8 u3 D0 @/ P. n/ I
        if( exsound_select & 0x20 ) {
4 L8 c( M+ {( t2 v2 p/ X                fme7.Write( addr, data );
4 E& j$ W& O8 P8 d6 {; n        }
' _0 \3 Y+ K7 s}
  z& ^1 ]) n+ z- Z  t7 Z  W% J$ o* ^2 Z1 g  i" U$ b/ `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& q% f4 @! @5 p+ c% M{
+ Q5 }# w5 u0 v: e& K& H$ R3 r( SINT        nBits = Config.sound.nBits;2 r# L+ l0 ^1 B, c' R
DWORD        dwLength = dwSize / (nBits/8);7 p6 q, {' H5 u. |) B6 ?( H
INT        output;
5 n& l+ [. a7 O" AQUEUEDATA q;+ Y. t* Q5 \9 d! g. z# a
DWORD        writetime;" z# W. B+ n4 B1 T

& E5 |' K6 ?- lLPSHORT        pSoundBuf = m_SoundBuffer;
. w8 t" Z) r9 n" HINT        nCcount = 0;1 b" T* Y. h7 f& c! S

" H. E( Q* G/ D* DINT        nFilterType = Config.sound.nFilterType;0 O! l" c) u$ k; Z6 p1 }

4 ]! U; t. h. t8 ~        if( !Config.sound.bEnable ) {
1 [( f$ c- T# d" t, f2 A6 Q                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );1 Z/ p' [: Z7 y# ]
                return;& X# d- _' l) M+ t. o2 p9 |
        }0 w% a% B2 N7 ]6 f9 b' m: `' L
! _( t/ z- M3 R0 l0 ~9 ~
        // Volume setup& A9 ]& ~4 X* b
        //  0:Master  n; P' J; y+ y5 y) I
        //  1:Rectangle 1! a: S  F0 t2 @1 }( n
        //  2:Rectangle 2
. n& N7 A9 ^, E" }- F8 @2 R% s        //  3:Triangle
5 s( R+ F/ }$ r8 y4 ~  ^1 `1 g6 X        //  4:Noise
8 c! e* T4 l2 D' m/ d        //  5:DPCM
1 Q: O. H3 n2 Y$ J  t        //  6:VRC6/ M$ l0 y% S2 H: Q9 z# W
        //  7:VRC7& _" ]: ~5 S, ~/ E
        //  8:FDS
: {2 y$ A7 n0 ]" A# M2 j        //  9:MMC5
9 a* m- \- z" d" X2 L7 E        // 10:N1063 W, ~1 [( L! U) ?2 p( _6 W
        // 11:FME7
) t* }( d8 @3 J) K4 d        INT        vol[24];
, Q! z; V. Y1 D        BOOL*        bMute = m_bMute;) Q/ l4 y6 ]. w9 W& _+ S. {1 z3 D
        SHORT*        nVolume = Config.sound.nVolume;
- R$ j3 J# N7 h+ m" ?' E1 i3 T2 r$ T. K6 H9 s' p2 F- x0 _
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
/ `/ D% R: ^" S# k# U- q$ h! C" O; e( D" U, ]
        // Internal
( D% V4 V& u" m/ s0 F; M3 }        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
) b" `* B" E- M2 ?+ y$ d$ I        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
: }& W2 K3 O, M# C' m# R) [        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
9 K: n2 _" W  S& h# q2 A$ K# F4 \        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 m8 i8 p9 S5 j9 V, H3 g        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
" X4 _& \! g% O! w3 P1 q( j% h) Y- ^' X  l
        // VRC62 q: ]4 Y0 e& u2 c# L% w5 _( `+ h" U
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ V4 @) ]. X' F: |5 X; ]/ n        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 l2 }2 h, z' s+ m+ q
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 r: w( D5 @! K$ C# [2 g+ F! B
        // VRC7
# Y5 O% s8 W& ]3 M: I        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
: u2 g: i; X, g* F, f
! @4 ~  ~& q3 v        // FDS
! `. \7 x9 p  x* @# _* R5 C        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;% a" P) @- q3 K7 |
5 V4 Q) L) B' R1 P& A
        // MMC5. H9 X# `2 D& q& t: H. J$ i
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, r3 \6 o$ U# n* M6 r8 S; t& M; J        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ s8 R3 A/ m9 P" d
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( Y  t4 X; a8 x- z
5 t# X! o3 N3 I9 J6 I7 @: T        // N106+ P1 y4 u2 [3 o& m* e2 g3 I2 ~1 ~6 L* K2 S
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ G$ c7 I+ v" _( r' U
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& u) }% m* m: N
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( f- t. a+ z( `- c( B3 c
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 [  H5 r  C: U" h6 b% Z
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  \+ `+ v6 Y0 M" }# G
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. S: `: C- S  `8 e
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; \$ e! i; O0 o8 @6 y1 n! h) U5 G
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ O% B0 R, \! p6 v; o3 c
. \: T; e7 O9 t% q        // FME7; `( J  s! `6 L, j1 s' h% S; C
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ _/ t1 E7 l* Y        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* A: |0 J" ]  R$ a2 e
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 c8 n- G/ U' _1 `, B  A% j2 m# t" Y7 h: E' e* g5 B. j( P+ v
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 N, x/ n: z; `. b! C) Q) ~" j
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 R. z# ^$ ?. D8 j( v8 m" b8 T: I, L

. ^( b' M4 c7 [4 j7 {: y        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟( |. w$ ?9 ]" \9 K$ t- N, s9 K
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
1 f& E4 w; d$ M' F; d                QueueFlush();
9 o; v/ p; q, ]7 ]8 q) E9 [) d        }
7 u; [$ Z4 P: l# x8 R& r3 H' ~, {4 u5 n3 i0 i8 Z* Z- i
        while( dwLength-- ) {
4 d2 f6 V: ?5 |  R" R4 T                writetime = (DWORD)elapsed_time;
, \& {: w3 n8 j# F6 o6 w; n4 Y
. x8 r! v5 a% z/ g, W2 F                while( GetQueue( writetime, q ) ) {7 A, A7 T$ P$ e% V
                        WriteProcess( q.addr, q.data );/ [7 F. P( K. G( h* ^9 p
                }
7 T& Y% p9 |' ^' [. z' W. f  l0 p0 `/ \5 B( J3 K" F. H
                while( GetExQueue( writetime, q ) ) {5 N" B4 {; O. w) @& G% I3 f
                        WriteExProcess( q.addr, q.data );
$ j9 [+ S1 z  C4 P- {' l- I, }                }. z8 h0 l! h0 n3 Q8 T6 g3 c% X

$ m- R; s. C: r# P$ q                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME71 D2 Q# n4 |1 s6 ~
                output = 0;" l$ B) i& C$ y! |; A
                output += internal.Process( 0 )*vol[0];) n8 c! V' Y( W0 p
                output += internal.Process( 1 )*vol[1];
; M. A% K5 _  D% J% \                output += internal.Process( 2 )*vol[2];
+ d: l6 n# D, L                output += internal.Process( 3 )*vol[3];
) _( u8 Q, |1 z; A8 u2 `                output += internal.Process( 4 )*vol[4];
/ x9 K: Q! z5 W. T' y+ x! H' `* B3 \% B# }$ V0 b* a( Y: C& g
                if( exsound_select & 0x01 ) {1 H: A/ Z0 K6 n" E
                        output += vrc6.Process( 0 )*vol[5];& ^0 b$ \% h* K, w
                        output += vrc6.Process( 1 )*vol[6];
. H' Z$ F0 I: Y, h/ ]4 }                        output += vrc6.Process( 2 )*vol[7];! k8 H$ A% `, w% W5 s* k0 X
                }6 c: p3 v0 F4 g3 }7 X
                if( exsound_select & 0x02 ) {3 m6 l& r3 K  _( F9 E
                        output += vrc7.Process( 0 )*vol[8];
. \1 Z, \3 H/ D! j  m                }7 ~9 s. M$ T) x1 |% _* Z
                if( exsound_select & 0x04 ) {8 ]% ~5 g" B; y, j9 U4 q2 E  v( m  h
                        output += fds.Process( 0 )*vol[9];
; P. x2 e, e  A" E: Z                }! R) I4 V6 `/ y: D8 x
                if( exsound_select & 0x08 ) {2 R3 s2 c7 c- }! ]0 @# u; ?
                        output += mmc5.Process( 0 )*vol[10];( N  C0 O- z5 j% D4 A3 y4 b9 {
                        output += mmc5.Process( 1 )*vol[11];
% y- ~$ J6 {% p/ s7 }+ Z$ E; ^                        output += mmc5.Process( 2 )*vol[12];2 @. L5 X; j, x3 {4 t) U7 X
                }: M0 S& _! z, ^! T; n
                if( exsound_select & 0x10 ) {9 [/ U+ ~! ]! |& B
                        output += n106.Process( 0 )*vol[13];3 A# E+ Y5 n2 G
                        output += n106.Process( 1 )*vol[14];
& g( x7 x% ?2 f8 |+ b1 I, X                        output += n106.Process( 2 )*vol[15];
) p7 p) K* t3 w8 v- P                        output += n106.Process( 3 )*vol[16];
$ n1 o& O' F% W& `                        output += n106.Process( 4 )*vol[17];9 \. P+ V9 I# D& `! M7 W8 f. R
                        output += n106.Process( 5 )*vol[18];' Y! @. G* g% D  l2 W) |# m3 @
                        output += n106.Process( 6 )*vol[19];- c: u' Z4 b$ v  J& Z
                        output += n106.Process( 7 )*vol[20];6 q$ j; v1 F& R2 _) n9 p: C- S. T! w8 ~
                }& V- m7 s3 U* q5 D" ]3 S
                if( exsound_select & 0x20 ) {- m( f* E% S: W/ G( |# D
                        fme7.Process( 3 );        // Envelope & Noise  h4 Y5 X2 W0 y
                        output += fme7.Process( 0 )*vol[21];( `& i1 M: O. ~
                        output += fme7.Process( 1 )*vol[22];: _+ x: y' A6 _/ H1 M* P6 m
                        output += fme7.Process( 2 )*vol[23];. Q6 ^& ^1 \) J) h# A
                }( y6 ^- w( U2 e) Y' s
+ R4 F7 r8 J0 {$ i3 E1 m
                output >>= 8;) r/ ]6 A( [/ A! |6 V* v

8 G7 E% B' a/ N- n7 s+ M* Q                if( nFilterType == 1 ) {0 C0 T4 z+ f* c: q0 P/ s
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 j6 G# Z* h. q: B8 }0 d1 x
                        output = (lowpass_filter[0]+output)/2;4 C. x) o9 ?( O( p
                        lowpass_filter[0] = output;3 p4 H' c* u5 ]7 Z
                } else if( nFilterType == 2 ) {3 ^2 b5 z4 ?6 T  h- y( T- r
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)) f* ~5 r: s4 D6 ^* H( U7 H
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; |2 V3 v/ L# ], B+ S! A4 T                        lowpass_filter[1] = lowpass_filter[0];
/ q6 q: Z0 J! W. t; q4 x                        lowpass_filter[0] = output;
2 }8 o& h2 Z2 x8 W7 w) Z                } else if( nFilterType == 3 ) {0 w5 k9 J: y- X/ R# @
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)7 j- P7 ~! e4 B; b$ U- h9 ]
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 r( h& x# S) z( g4 L, }( r                        lowpass_filter[2] = lowpass_filter[1];; R4 p1 I4 _7 E+ {
                        lowpass_filter[1] = lowpass_filter[0];: u5 [; x6 I5 \" q! n* h( U
                        lowpass_filter[0] = output;
* J7 X) m2 C5 s1 q                } else if( nFilterType == 4 ) {
) h% D/ ^) X7 Y7 e4 M                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)" c! s- d! s! ~
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* z8 X& x. Z! B; F# u- Z! h                        lowpass_filter[1] = lowpass_filter[0];
: `! f/ ]! O# [' P                        lowpass_filter[0] = output;
  F" F7 O% o/ c' W  a# }( L. I                }
* X8 h9 a* w1 @
& [4 @( a. H3 \0 f#if        0
: q# w+ Z# F; _: L/ m                // DC惉暘偺僇僢僩2 f/ Z' i8 o  [) c" p
                {
/ f( p3 B) k( F% {6 Y# F                static double ave = 0.0, max=0.0, min=0.0;) T, ^8 a# B$ P0 ^
                double delta;0 m# x# O# p* l( d8 @: K% L
                delta = (max-min)/32768.0;
% Z# d6 {8 y3 r. e                max -= delta;
5 ~5 ~+ P0 O3 l: k4 ~                min += delta;5 C# P. W/ O0 W: C6 G6 X
                if( output > max ) max = output;
* Z) w! P/ W* z                if( output < min ) min = output;
) O3 q; }/ _7 n9 g) z                ave -= ave/1024.0;
" N2 u  W0 |; N; x* i( w( Q0 M                ave += (max+min)/2048.0;: _1 Q8 o& g& S+ G* ~
                output -= (INT)ave;; X  h2 a$ p2 Z& P
                }/ {3 K* x1 y: H" O
#endif; K. j- G: E9 x
#if        1
8 f$ y5 O- \3 V9 E                // DC惉暘偺僇僢僩(HPF TEST)" M# T; D3 @( m5 A; Y
                {- t$ Y4 H7 B; X0 \  q! H# L4 z
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);: ]" X$ o, f" S2 s6 L5 P
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# ]# _# N( {; R% E5 d: H9 ?                double        cutoff = cutofftemp/(double)Config.sound.nRate;
2 \" y7 b; a5 L9 ]* ^                static        double        tmp = 0.0;
$ T" D/ o, o3 x/ i7 U) O$ i: h$ S* Z                double        in, out;* J% i) g5 B" _& U  Y0 {

. u- ]3 U8 D7 L* n) w: ^3 |5 s% f                in = (double)output;
* `4 a1 a6 }$ W1 v/ g- a                out = (in - tmp);
% C$ p# g8 G# i) N                tmp = tmp + cutoff * out;
' A0 }/ t0 |' s  c3 N# b
8 J7 o! O1 V: b9 m7 m                output = (INT)out;0 C8 k# J+ ^3 }
                }& }5 s5 ?* p$ t4 o: G: l  y
#endif
$ _9 }% |+ l2 ^7 C' Z( }, t$ [#if        0& K' U" Q$ m, ]$ F" ?) x4 G6 r* |
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)! d. m$ Q9 R% `2 L( M
                {
+ k3 Z4 N8 a: a% @- ~                INT        diff = abs(output-last_data);; D" M$ U) y: c5 B/ n
                if( diff > 0x4000 ) {! V# ^5 @" A9 }- l4 s+ W
                        output /= 4;* Y" Q) n* M- X  C. |
                } else
# {. Y" U: k8 X" ]/ Q                if( diff > 0x3000 ) {
. \" y$ c- ?% Q2 z- w5 f+ h/ m2 `                        output /= 3;
$ T# q: f0 b/ G- o                } else1 W+ O' ~4 X$ J4 ?6 \- @3 i7 t
                if( diff > 0x2000 ) {8 l( ^& l+ H2 }9 U; E3 n
                        output /= 2;
5 b& f+ ~: D7 W* n: ^' h                }
5 d* U8 i- V* a. @                last_data = output;5 j8 c5 X8 Z. o' C) C! O' S
                }( t$ v* v. j* v! z. r
#endif
9 o7 n, e2 i, H0 Z: b                // Limit
" L: Z0 n3 _% `' \/ |                if( output > 0x7FFF ) {
, a! v9 O' c/ \3 x                        output = 0x7FFF;
$ z# O4 ?6 h' P, {9 W                } else if( output < -0x8000 ) {: C/ j0 o2 H2 o& R! o. h! c* H
                        output = -0x8000;1 v* X2 t7 b0 D" i1 [9 P+ r
                }
8 U) X; Q. h1 }% @% z; t  |: h, J7 \; _: v' X- H2 I  |
                if( nBits != 8 ) {
9 F1 X) p/ g. \- J0 l# {                        *(SHORT*)lpBuffer = (SHORT)output;# Q( _% S3 `' E" U( X7 n
                        lpBuffer += sizeof(SHORT);
- k% c6 M9 g9 N7 J  S$ D                } else {" b- s6 D6 Q& O  \1 d  }
                        *lpBuffer++ = (output>>8)^0x80;
# i1 h+ ]+ }! O; S. }                }
' a8 M: V) @" t- X8 W- m; i7 T: {7 S
                if( nCcount < 0x0100 )2 L& p  y# x3 C* L. a3 w
                        pSoundBuf[nCcount++] = (SHORT)output;
( E! x& O: U; @" |) ?5 l' E- l- k
* ~  ]& I+ P/ d//                elapsedtime += cycle_rate;
+ m' ]$ s9 _% A: S( K6 `# k                elapsed_time += cycle_rate;; \" h2 P5 X( Y7 j, [3 h
        }1 @# i) _1 a/ d: q% K
8 ^( T' f7 ?* l) `. |
#if        1
. n7 U4 Z7 Z5 T& D8 ?4 k+ Z8 i        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
- h+ P; d/ L  {7 w4 f8 N                elapsed_time = nes->cpu->GetTotalCycles();& S$ e8 o+ j6 n' ]4 p
        }
6 \) _$ |+ g5 P" R& G+ v' y2 O        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {, U5 D! @. f. {
                elapsed_time = nes->cpu->GetTotalCycles();+ [' X9 T/ u" Q2 v' n4 A4 f- o6 j
        }5 @, c+ {- P' l/ p. D2 f8 O( {
#else
+ o. ~: [1 Q* t/ N5 L        elapsed_time = nes->cpu->GetTotalCycles();
4 h: s4 @! L) `4 o+ L#endif
+ P/ S, l2 n" W) \3 Y! o) i}: F( W% A/ o/ |& K  E+ n
, }9 N1 H, ?; {! j+ A& O
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ O- ^* @, m" L$ O- g" kINT        APU::GetChannelFrequency( INT no )) \+ h1 ~1 S) K  u) `; P8 A; b
{6 I" q. N* p8 y4 d4 m; G0 D
        if( !m_bMute[0] )
  u7 g; o, p, u& f8 o, O: Q                return        0;. w( q* I! [) Z# y" M) ?1 I+ I
# S, x+ s5 @% C) k/ @9 x0 ?( v
        // Internal
: v; Z8 W; E6 h' \! C        if( no < 5 ) {' @: L' ?) c4 ]5 C6 Q
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
0 z6 C; N/ o& ]- Z. ~; Q        }+ _1 k. b/ G, L  [( ?0 E$ O1 P+ Y
        // VRC6* H! M3 o6 v7 a: K: d/ [
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
7 a4 d1 F: H4 _                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
, U+ w! ]& T0 c: Y( w1 m/ U        }
0 y' Q4 |% A+ j7 ~% T& ]        // FDS' H0 y+ V% N% T! U( ~4 Q3 s, V
        if( (exsound_select & 0x04) && no == 0x300 ) {. U& e0 j8 N8 q! `: P9 \
                return        m_bMute[6]?fds.GetFreq( 0 ):0;9 n( ]4 \0 }4 u; O
        }; D5 P( f" E$ {, Q& F0 G- ~/ b
        // MMC5: f  {( f# R/ e: G: r; _3 K# }
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
" E- H1 X. E/ @$ ^, {+ C                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;- e9 n/ ~% x1 d: Y- d% X8 b
        }3 |' f2 U2 h4 `5 E3 A
        // N106
: U, {/ Y2 j* D' T) R        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' C' V) j7 ^4 i: l3 o4 V                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 V+ g' B0 B# F) F+ `; p
        }
( I: ^+ Q& o) |3 B) L8 d        // FME7! @* v; g/ S: ]
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) W+ u& b" S1 W# k5 f# v5 |
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 b, L3 R& _1 ~9 V2 k        }  y2 k! L2 D8 s# O+ x
        // VRC75 C$ r. z4 T% P; S+ C
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {1 t& P# j. \8 q4 {; A+ P
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;( u5 K5 h/ G$ R' D: W. b
        }
6 w% O% I: A5 p) u, v- @( h        return        0;
7 c" |& `; s* ~" W* L. h}( y  r. l) o$ c, C1 ?8 N" ^

6 R% ~* `3 y7 k/ Y; v// State Save/Load
; a" C6 r. a; e3 ivoid        APU::SaveState( LPBYTE p )8 K' N, Z1 [' Z* u3 A5 b
{
4 R5 e$ j2 [( t% P7 y3 v) k+ P7 _#ifdef        _DEBUG
& C4 I# ?( c2 O9 u8 h% E# pLPBYTE        pold = p;5 Z0 D8 E; E2 X8 C( G2 ~9 ^
#endif
9 D2 P8 K( d9 J5 a
4 `% ?( ^. P4 s$ |$ t        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% ~' s! Z2 d  b! u: h: z( N# W        QueueFlush();( ]" ~- G$ h; j; s) w& D" X: N
% i% M7 ?; |1 Z% ]# N9 q, @' t& |1 ~1 C
        internal.SaveState( p );% \: J. o' s% Y* J
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' ~! b1 p& R1 N, _8 h$ T: m
7 @# B3 K. v) n+ |5 }4 N8 W1 B$ {        // VRC6+ r) x% g6 U% S  J
        if( exsound_select & 0x01 ) {1 i* R% L4 u8 h6 S# y
                vrc6.SaveState( p );
! `3 w& K2 O9 f- K- [                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" v4 m& X  L9 j+ R4 y' e0 i        }* ]( _5 r$ R6 T- f% O, ]- w% T7 I
        // VRC7 (not support)8 E, M2 ^6 i: D2 N/ @5 \2 x
        if( exsound_select & 0x02 ) {
5 }( T8 F* i0 `3 q$ |7 ]9 a                vrc7.SaveState( p );" {6 p' V! C4 z& e8 z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) C! ^( }; t8 v$ M  X- b
        }
0 [. p# ^3 C6 X4 t" y        // FDS5 ~% i% W6 A3 D, r' r' h
        if( exsound_select & 0x04 ) {
/ j; h5 w, ^4 }* A                fds.SaveState( p );5 A- T+ m& y' A$ V2 ]
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 g! i! d$ Y+ q: v: J
        }. l% G' z7 G3 L  `2 x
        // MMC5) B9 v: _+ y% a* `9 V+ [2 i
        if( exsound_select & 0x08 ) {
- t7 `; I4 E- M  S' z* F                mmc5.SaveState( p );
# d  i. _" C( y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. G; ^2 H! l( [7 X, A" M$ \
        }
$ a; f' P" _5 l        // N106
9 }% v( f& M$ `4 y' {+ P        if( exsound_select & 0x10 ) {, y, p# R* t" ?6 L1 c
                n106.SaveState( p );! G) F& ^* T6 w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; ~( Z+ x3 S$ i8 o( @
        }
2 m+ E2 f& K  |8 ~1 z        // FME7
! f( O3 H  X! c  C% `, {        if( exsound_select & 0x20 ) {* i, N0 X0 D6 _7 t# Y
                fme7.SaveState( p );" H8 B& x) T* G. F0 `3 q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 X( g6 W5 w$ d: s; M& S2 L
        }$ q/ e9 K2 ]. m2 z
; z# C4 Q" D% C; f9 ]0 H' Z
#ifdef        _DEBUG: h" w" \0 o. J( D, R
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 {( C, L# L6 I' S4 _
#endif
& J2 P- u1 Y+ G}" I' D) N# I" c3 f! h3 Y+ g2 W, V
1 s% k% M8 Z9 q" K& y
void        APU::LoadState( LPBYTE p )* r6 @% k; }. U
{
* e* X/ y  |  j6 ?        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
9 d' P6 i, ^: w; r8 ]' T/ W        QueueClear();( p/ L! i8 k$ w. d' A0 @' x

5 r# L+ A  X3 s9 H; I$ T" y" u' s5 o        internal.LoadState( p );
' J, {: P- X, a: n9 P        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. p2 j( ]0 |; V% M' y" ?& K, e- ~
* C" Y: L0 g* D5 @% {6 N
        // VRC6
+ T# h9 ~/ k1 Y) \7 E0 ^: r9 w" t        if( exsound_select & 0x01 ) {
5 [0 y1 |6 j9 y# C! O; j- e  s# a                vrc6.LoadState( p );
) G6 o& Q6 a* U( p                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 w2 a& y6 V7 K) Z+ f
        }- \/ ^9 D# @# @$ b6 N- r
        // VRC7 (not support)
# I4 j; a5 Z+ h0 Y/ E        if( exsound_select & 0x02 ) {
9 J7 M8 g8 _7 v' K4 {  I6 X                vrc7.LoadState( p );& ]4 ^* W2 K  v/ v
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% |  c" G: s1 ?9 S* @" p4 S6 F0 Y        }
" h2 c/ ~" B# B. X! U2 y$ `        // FDS* _' p0 ?. q% U: J* R8 p
        if( exsound_select & 0x04 ) {0 s* U+ Y! {5 Q5 Y2 X2 a1 z+ \
                fds.LoadState( p );
5 U. J3 J* P0 I$ ~( z. T/ P1 E9 B                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: ]! K3 e- U6 ?  A; H        }8 M) W- K' q5 V( ]5 S2 v9 [% ?/ a" O5 `
        // MMC55 o( O) k& }" v$ g) K5 ]
        if( exsound_select & 0x08 ) {
+ h, a. X$ Z3 D" \1 V  n; T                mmc5.LoadState( p );1 `4 p  N2 ~  @: T
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 }2 A. C1 f9 K" q
        }
+ V( J1 h  l. ?        // N1060 M9 X2 l8 I: S  \8 J
        if( exsound_select & 0x10 ) {+ B/ s/ L! a  n& c1 {* \
                n106.LoadState( p );
3 _  ^9 U# t+ Q  s/ Z! ?" X/ D                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 Y! I# J/ k4 M" @6 H3 A& O        }
2 j; d. M8 C) B/ C9 \        // FME79 s7 B2 W0 g5 I
        if( exsound_select & 0x20 ) {) n, {* n/ L) S" g1 g/ k
                fme7.LoadState( p );) D" m, d! u) |) o3 E) o7 @7 I
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 Y& r  ^& S4 T3 ?* k3 }7 R2 y        }
6 T- ^* a) I  A, n; w1 |; C}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 : O$ c0 T# t( Q$ j7 e& @3 T, @
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 \5 i! \0 `5 `. k/ z1 X
感激不尽~~

# y$ U. \: x" g恩 我對模擬器不是很有研究,4 p9 C* z  |1 _
雖然要了解源碼內容,可能不是很困難,
8 m! ]) _) ?$ q0 @" U3 _& A; q不過還是要花時間,個人目前蠻忙碌的。
* Q  K; E  y4 J: I  k  c! \3 O) X! g( Z$ {( Z) S( D$ I2 m
給你一個朋友的MSN,你可以跟他討論看看,/ C! w, p% o& p  [( m2 h" N
他本身是程式設計師,也對FC模擬器很有興趣。
3 G- u$ E9 ?6 ]7 [# J
' a; z5 P3 X) d+ b$ JMSN我就PM到你的信箱了。
1 r" Q/ v' a2 S3 Q- k% n3 d0 V) z% R; W/ w4 W3 Y: u4 W" T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
0 k7 [' S: Q% a# j9 z# ?: @呵…… 谢过团长大人~~

$ h( w4 l2 f$ H' R7 w8 W  a; O  d6 Q; {
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 J5 o- K; @( \; @团长的朋友都是神,那团长就是神的boss。
- o% h) Z- t4 N8 c- o2 W
哈 不敢當,我只是個平凡人,
; T4 D9 E7 g2 q; g0 R要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙" ~" H6 H, b$ j! E( E% m, ?
ZYH% P- H* f& ^7 B* t* x/ V
QQ:414734306/ N* v/ U+ X( }  m; H. D
Mail:zyh-01@126.com, E$ E9 @" B& h5 A- }+ D

% _: Q3 \* b" w! a  w他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ; w  i$ l" d; t0 b! m' P$ z
再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ R2 d' k$ g# @2 Y
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-14 06:43 , Processed in 1.123046 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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