EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 D4 ~  E: O: b4 y9 k, B; e楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, q# T- U6 M3 E
这里有相应的模拟器源码,就当送给大侠了~~% e0 m1 I5 O% r2 D$ t6 y4 e
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 2 e8 X8 b! d$ M2 j% J0 |
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 G, D" m- \2 D- c0 T5 b9 [楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 T3 Q" X3 N5 `3 l# H9 B9 K' v4 Z
这里有相应的模拟器源码,就当送给大侠 ...
3 ^5 I; L: a# ]& O- g
聲音部分(Audoi Process Unit = APU):
- t' N& \* l; f( e- Z; s7 X* w.\NES\APU.cpp
: D8 M( @7 L6 K8 o' f7 D.\NES\APU.h
+ V- Z: G+ x  S- \. N6 D& Z/ G# H& i  ]
' y3 V$ C4 q; s4 {1 r' P% N+ X  j  V
6 W- I8 ?/ V6 z2 o影像處理部份(Picture Processing Unit = PPU):
3 U' u5 {# ?7 D.\NES\PPU.cpp
' h4 j4 k, B0 ^& b4 T2 v$ r8 l.\NES\PPU.h
7 U' D. i3 ~# U4 l' K
% x8 I6 \! _$ ?& I4 v# D如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* {" W- @- _# S(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) y: i0 A2 r0 i: i7 X//////////////////////////////////////////////////////////////////////////
# P  }6 {; A' D/ [! h# J( I4 \& I//                                                                      //. O! A+ i' \) q% C* g! {
//      NES APU core                                                    //
# H2 K& A) W9 u, y; i4 c//                                                           Norix      //
7 o; h3 V7 _% W+ ?4 [9 _//                                               written     2002/06/27 //
! o4 @+ j- }) h! r5 A" W//                                               last modify ----/--/-- //
5 f! `) w) D- E) S//////////////////////////////////////////////////////////////////////////
# @  U& ^7 i, ^) w# L, Y! O#include "DebugOut.h"# M. ]. j6 g5 `2 d+ e7 @
#include "App.h"
. J# \- j2 ^& h2 r% u; p#include "Config.h", F. Y3 w  \% E; |+ r$ T

  @  @% o! k+ ^#include "nes.h"
6 a" g1 `" ?% N& W% B/ |#include "mmu.h"3 C+ X4 x) Y/ A  w
#include "cpu.h"
0 H; x2 |7 r! j#include "ppu.h"
- @" v% c+ v( @+ L$ s#include "rom.h"
5 w% v, [! D3 E: `$ O" P#include "apu.h"
" P- p6 W; i6 R4 b7 W% L) i) U. h. p2 S: P! P1 k" z  i
// Volume adjust. j: N4 p+ k* q% I% D
// Internal sounds
; J0 `/ F8 \' r7 x#define        RECTANGLE_VOL        (0x0F0)" W- q; f. Y: m- t$ i8 B5 D
#define        TRIANGLE_VOL        (0x130)0 T* ]! ~/ S/ y. x, ~. ]
#define        NOISE_VOL        (0x0C0)4 `( {. n0 d/ }$ A' W
#define        DPCM_VOL        (0x0F0)# c# J! x/ a6 I& F4 i2 h
// Extra sounds6 Q* k% |0 a7 f2 c
#define        VRC6_VOL        (0x0F0)
7 n; p" q6 S. I# V2 {#define        VRC7_VOL        (0x130)
! ], k' [3 u. e# l- ?: D$ s#define        FDS_VOL                (0x0F0)+ k, ^  t7 l) y+ o
#define        MMC5_VOL        (0x0F0)2 \! v/ a5 l; h
#define        N106_VOL        (0x088)2 a; r. d9 i8 U4 z% L9 L$ u
#define        FME7_VOL        (0x130)
$ N, j1 t# J$ I3 F! X
6 y8 ^/ U8 H9 W2 HAPU::APU( NES* parent )9 h; ~" O6 p4 o* N8 I
{
) ^% r4 _# j8 E3 l( E* T( o        exsound_select = 0;
/ h1 o5 a  y6 _& l4 t1 S8 ]( \- O* f, I9 d
        nes = parent;' P7 |0 s$ L+ h- i, _/ ^4 t
        internal.SetParent( parent );
4 z# o6 Y  m) P- m+ X
! l% M- D9 ?  x        last_data = last_diff = 0;& K4 ~" |$ y* }3 `8 |
7 Y7 J( Q9 H' [' {1 K. S
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! A( V: P" L; q+ @, }/ J+ D# H6 {
. k: V* `- R1 m2 t* [, r
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
% c# Z0 m' p" c( X        ZEROMEMORY( &queue, sizeof(queue) );
5 Z+ v9 r0 I5 z        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 V1 U8 D3 ~4 A
# ]- K  ~, ?- p. e( c. m
        for( INT i = 0; i < 16; i++ ) {3 ]& E/ P$ X+ T! Q" u! K* W+ ]# w
                m_bMute = TRUE;
) T2 ~  k% ?+ x+ r9 Y1 V        }" o$ K, I. O3 {8 b* Z
}
( D* h$ K1 v1 Y, O
" U$ ?: {& P, F, `0 P4 ]APU::~APU()5 a  Z& H7 ^# t3 d% D3 {! ?- ~) O
{3 z( t- U) P$ ~4 e* t) S. u
}
4 }; H/ n# M) I/ |* `& F# m4 `
! f; v* @  I  W9 evoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
" E" B+ Z- y$ Z4 I{6 T4 g- F; p  S7 n7 o$ X
        queue.data[queue.wrptr].time = writetime;  f# Z& z' q* l; n+ D. [, q
        queue.data[queue.wrptr].addr = addr;
! {$ O7 D1 S5 @4 c0 r5 v- a- W0 X        queue.data[queue.wrptr].data = data;0 y% I; Q- J. ]* m
        queue.wrptr++;
9 ]8 Q( x( R+ U        queue.wrptr&=QUEUE_LENGTH-1;
; V& @+ J+ n/ U8 I" D& n5 H# |0 @+ O        if( queue.wrptr == queue.rdptr ) {
& ~- A5 Z; s- r: R! O+ F+ R                DEBUGOUT( "queue overflow.\n" );$ }% ?0 _1 c5 a- N. T6 `: y4 Q
        }$ F1 x, y* G# ?8 h
}
9 P; v0 k, |+ ^) h. o+ x( F. P" l( g5 x
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  T0 k4 g% ?( g8 W3 A: o{
& i" @8 _. p+ J( F! ?. y. B        if( queue.wrptr == queue.rdptr ) {9 T, v+ U! m! P
                return        FALSE;8 G8 K' L9 ~# S& T+ j" k
        }
6 ]2 H0 `+ v% m* n        if( queue.data[queue.rdptr].time <= writetime ) {
/ n0 V7 \$ |4 v                ret = queue.data[queue.rdptr];
! b5 f4 c" e% H' K4 A( J                queue.rdptr++;8 n$ U9 E6 I& C- L1 \0 a
                queue.rdptr&=QUEUE_LENGTH-1;8 Z- ]8 f8 W6 l
                return        TRUE;8 y( b5 e0 N3 ~) }& @  u
        }
, T& [0 q/ G( b        return        FALSE;
: O) g$ \% K$ }( f9 _}
9 s: ^0 L. o" l! H6 V; {' U
0 h8 }0 e2 V4 N8 H9 d" T/ ~0 `void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )6 C& R) I" J; d3 u" p
{8 G9 N9 U2 X) X, q6 \
        exqueue.data[exqueue.wrptr].time = writetime;& Y6 `4 }; a" G9 x  R3 b
        exqueue.data[exqueue.wrptr].addr = addr;
* D+ e; G+ V( E0 `" e9 d) M        exqueue.data[exqueue.wrptr].data = data;% A' A1 n. p4 l. U5 R5 y0 @- a
        exqueue.wrptr++;
: ~. W1 w2 q( H) w6 l        exqueue.wrptr&=QUEUE_LENGTH-1;
7 F8 }  F! t6 g1 j8 [7 r; `        if( exqueue.wrptr == exqueue.rdptr ) {
7 B2 C' z; J; l( g) y8 }                DEBUGOUT( "exqueue overflow.\n" );  G, I! z3 I' _- t! t' A. n/ \
        }- Q- e1 r. c* W- o' F" E* T. h5 n
}
1 B0 }# ^, J) K" r& `3 r9 g/ O. e: Z9 L* f# X! [1 r' V( p! c% j
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 Q) O8 x  b  ~8 O{1 @1 I9 I2 K2 h3 g3 x
        if( exqueue.wrptr == exqueue.rdptr ) {% C* V; Q0 u4 ]( G8 j
                return        FALSE;5 S4 n6 Q* O1 e' n# l
        }* f: [% B: z: h2 H
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* F8 \4 t: d7 _) L9 Q4 V8 z& Q
                ret = exqueue.data[exqueue.rdptr];1 t4 I! Q2 j1 k6 ]
                exqueue.rdptr++;
* T( |  U% u7 N! M0 t' B; Z                exqueue.rdptr&=QUEUE_LENGTH-1;
6 ~; m+ s& |. ], g% B5 b                return        TRUE;9 x* H& D: d' U. u: J
        }
( Q& Q0 `; g& g8 Q        return        FALSE;
8 q/ |) X! h2 h* V8 p}
/ F- R- x! e5 K# n6 |) J2 w6 z
) o, \# S4 R* Q, F5 |* G; Nvoid        APU::QueueClear()5 ^6 ^' S% w% ~1 x, i" Y4 g
{
# p" n5 k0 I0 X; R% _. W        ZEROMEMORY( &queue, sizeof(queue) );. i! Q+ d* k6 I  k1 Z% ?
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# c' l; P8 r4 i$ Y}
: m" \7 G% K0 B6 w6 U
$ y6 v9 {$ ?+ T3 P* d0 g) ]! v" lvoid        APU::QueueFlush()* c, E& |& z" v$ c5 T/ N7 r$ I
{
8 P1 Z7 J7 p7 P, B+ R        while( queue.wrptr != queue.rdptr ) {; s4 J, o. H* }+ C# a
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" J! P& _, W9 V" }6 T& g                queue.rdptr++;
4 K* d6 b4 V2 ?7 @% T6 F6 C4 U                queue.rdptr&=QUEUE_LENGTH-1;
3 a* Y* f- w) @  F        }
9 D0 Z& t" a% ^; F
* a8 P1 b- W5 y6 \. J        while( exqueue.wrptr != exqueue.rdptr ) {5 i7 m7 ?) c% j6 e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( J' \8 y* \5 G3 A                exqueue.rdptr++;
+ e1 g, @, a! F5 C5 |" ^                exqueue.rdptr&=QUEUE_LENGTH-1;
, V+ \$ J% g' |; S* c% r9 r$ P  s  u        }
8 `$ w8 q* b: g* _9 f}6 m/ x1 ~8 K; U5 e; E+ O8 W
+ b, k) P. n) `, K& M/ ^+ U& q8 R- {1 H
void        APU::SoundSetup()
! @5 E/ o0 v3 Z& l$ O! g{' P/ ?( D1 s1 X  W+ U0 ]
        FLOAT        fClock = nes->nescfg->CpuClock;4 Q* L1 e) A- W9 g6 g
        INT        nRate = (INT)Config.sound.nRate;0 ]) y8 q7 G  B3 T6 ^2 U
        internal.Setup( fClock, nRate );
" M9 z) Y8 V( e" I3 p        vrc6.Setup( fClock, nRate );) G7 A& Z" d* E9 v* W
        vrc7.Setup( fClock, nRate );
2 ~" Q# c/ p) s/ O! z! }        mmc5.Setup( fClock, nRate );1 D( P! S; m3 U9 J0 j& ?( Q
        fds.Setup ( fClock, nRate );  W$ f8 k$ B  g$ v. o& C
        n106.Setup( fClock, nRate );- w4 E; C( v0 Q) j/ Y+ ~( h) s* W' Z
        fme7.Setup( fClock, nRate );5 P2 l7 C2 |$ o2 O' T
}) O3 X; T' W/ m: m' U
% ?/ p4 x# M% q5 j3 I' [9 e
void        APU::Reset()
- `% E$ T; y0 E# k. K{
/ b& c* e% ^2 P: V9 b4 N        ZEROMEMORY( &queue, sizeof(queue) );9 t( n4 k, k( _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- X! a  h- N: I6 x- ~( A
6 q# o3 h: ]) g6 W  M- A7 a& x
        elapsed_time = 0;0 h) x( M- Y. P9 ?" }7 C5 E
- A; c1 [; O. t$ u7 }2 l
        FLOAT        fClock = nes->nescfg->CpuClock;; b! Y) X. g" m4 Y
        INT        nRate = (INT)Config.sound.nRate;
  Y: p) i) H' a9 m: N4 {2 R        internal.Reset( fClock, nRate );
8 w4 H4 o* Y) J0 W        vrc6.Reset( fClock, nRate );# c- {6 b- I& T. C$ b
        vrc7.Reset( fClock, nRate );0 ^/ w* k% H* s- Y- ?0 f
        mmc5.Reset( fClock, nRate );: t7 i1 A: b6 T( e# q4 l8 w) T
        fds.Reset ( fClock, nRate );) [$ a3 {4 n+ J& J9 j! Y
        n106.Reset( fClock, nRate );
$ M3 {6 ^3 u1 n. Z* r, \" O        fme7.Reset( fClock, nRate );
; u6 i& N' p2 F$ `# Q0 e6 p
- ]& G0 ]; s/ S' n5 Q        SoundSetup();
1 J( k  a# e5 N; |}
; _! m7 y  |5 U# x. t7 v9 f% N! e4 ]) P; D+ \8 k1 F% z# O) w
void        APU::SelectExSound( BYTE data )% m. U. o) y, d+ N# ~* k
{- s  Z* F* ?* b
        exsound_select = data;
4 |- [! p8 R4 T( g& _}5 w; f5 F; y& M6 s- O
: \& `# h7 f: N! f
BYTE        APU::Read( WORD addr ): g" b8 J5 j$ b7 C& i. q
{
5 l* ^% C4 u+ s( d# z" Z: V        return        internal.SyncRead( addr );/ J$ v: s) P: Y  P5 w
}1 E$ ?1 N0 e* C0 t2 ~% P
! T6 r. X! A& [+ T
void        APU::Write( WORD addr, BYTE data )
/ Z  [6 D9 e$ S. |{0 H+ g' P8 o8 M1 l
        // $4018偼VirtuaNES屌桳億乕僩
8 r* R# [4 B8 X6 ?        if( addr >= 0x4000 && addr <= 0x401F ) {
: Z6 |5 m. c) v% m* w                internal.SyncWrite( addr, data );
2 I2 m0 R8 J6 P: D  T% E                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- r. W; a* F4 q, C* u7 r% ~
        }
. f1 b! a  [5 S' v4 |8 U. X3 z4 }3 S$ u}
6 M# X. L2 ~# j
2 Y! W' F: ~% B& q( M2 R( iBYTE        APU::ExRead( WORD addr )
) a% x9 Z/ L0 M; M: H$ M6 k{
8 ~9 K  |' Z* w6 D) Q0 i- m5 PBYTE        data = 0;, A$ K; T/ x: l  n9 |; Z

* i! o/ g* w  i0 `! J        if( exsound_select & 0x10 ) {0 ]/ E2 G% |" w6 U
                if( addr == 0x4800 ) {
7 s' G0 s  \5 G                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );0 D9 u1 `: R5 u- W' T; T
                }  f2 y8 o( p: B* `
        }
, S2 o8 t8 _5 B' x9 k* F        if( exsound_select & 0x04 ) {- C  u" S8 p  ?8 @8 H# y4 Y2 f
                if( addr >= 0x4040 && addr < 0x4100 ) {& G) {* N" i6 d* [6 ?, @6 _' W0 S
                        data = fds.SyncRead( addr );
* U  a  m+ H3 V3 D6 ?; p3 I, b                }; G# {% R: o5 a* e, N9 Y1 H% M
        }
9 E% x3 d" x$ [3 R, {$ h% `+ x        if( exsound_select & 0x08 ) {
0 P9 S2 h; t  x; f                if( addr >= 0x5000 && addr <= 0x5015 ) {
: p* u: }- D, E                        data = mmc5.SyncRead( addr );
1 h9 S  @; r3 Y                }
! [7 N1 N7 S# k: L% L2 f5 C+ K        }
5 _; w$ n' n: S! Z  l: G8 ^* o0 y1 p6 F; \! S# b
        return        data;* r3 Y& P" O' m% x: U( S3 ~
}
3 [. h' @3 l* z2 y9 k/ I9 Z5 _; v
- n5 ?; J1 ?) M) }" m4 }% q  jvoid        APU::ExWrite( WORD addr, BYTE data )
# ]3 m. P/ l2 R" p$ T  k8 ?1 r  R{
. v$ c8 I+ M/ z3 ]& I' p* U+ u        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
3 p; l2 W* m' S, S1 V! R9 F. @# ]% S
$ ]% _; q5 a# m: `: Q3 E- l$ |        if( exsound_select & 0x04 ) {( |/ U% Q- C5 D7 p, Y. [
                if( addr >= 0x4040 && addr < 0x4100 ) {7 p/ L' g  t$ ], {
                        fds.SyncWrite( addr, data );5 b9 Q$ q1 R/ k9 e" w
                }' f- k5 K3 A& c
        }
  v* R0 R6 p0 ?. w. J
8 l! x6 Z+ W! y$ T* o2 ], L        if( exsound_select & 0x08 ) {
3 [9 F; l. K6 l" c0 M                if( addr >= 0x5000 && addr <= 0x5015 ) {+ I' n# V( G" P6 O( _5 }0 L  Y
                        mmc5.SyncWrite( addr, data );
8 B4 J& R, I# N1 T- C) \9 }                }6 h( X; ?1 K' y
        }1 K3 U# @) I2 ]" }8 `. V
}+ r* `, e+ }* h4 E/ m" D% |

9 h, }7 z3 T; s# E% Kvoid        APU::Sync()2 m2 I9 ~; [& y+ z. X
{( h' u. f0 Y! q  o- P
}
: Q+ e6 A. C; L, o) {1 q# A: V2 w: N" E5 T
void        APU::SyncDPCM( INT cycles )
: g# \" ~  \/ V$ I8 P{
& Y6 g9 k. W4 W1 F, A* [" s( F        internal.Sync( cycles );: {" B+ \0 ~/ _( J5 Y8 h, q" n
- Y5 ^. ?$ ~( z8 x
        if( exsound_select & 0x04 ) {
) {/ z2 A5 H1 `" P6 ?: q% |  J                fds.Sync( cycles );3 l4 P* F" s5 U' k, |3 U5 T2 p
        }
5 A) X7 x7 O* Q2 Y! z4 ~        if( exsound_select & 0x08 ) {2 P; f& z4 @2 H8 n
                mmc5.Sync( cycles );0 c5 M( h1 ^  E5 b3 h
        }
4 p# t1 Q0 P; h; W+ D1 Y}% t$ @: K: O  R) T. W1 k1 H5 q

5 {( T, m) [' B! H" ~void        APU::WriteProcess( WORD addr, BYTE data )
$ D  D9 h; t0 Y  R, V{
- R/ k" b5 h1 {  k        // $4018偼VirtuaNES屌桳億乕僩) U! j9 H4 i. l& f. h' H! t6 s
        if( addr >= 0x4000 && addr <= 0x401F ) {) L# M2 U8 ?4 Q1 u5 V# x% _5 |
                internal.Write( addr, data );
& _0 C' o! [5 @1 i+ K0 p% M5 r        }
. X6 Y. X/ T9 o/ F# L3 B% a}
5 l% n5 U/ Q+ ^1 S% @! P* S( d3 g* u$ O: _) W
void        APU::WriteExProcess( WORD addr, BYTE data )5 P4 m& u- c6 C% b; a/ \0 Y& I
{: E: T+ t! l" j
        if( exsound_select & 0x01 ) {
7 L$ n5 O$ O. m% i* C5 a% R                vrc6.Write( addr, data );
6 G$ H6 N  T; G2 W        }2 j. e5 f! S6 B
        if( exsound_select & 0x02 ) {$ `& K: o, M; r4 J
                vrc7.Write( addr, data );3 z$ }' R& I& M) w8 m  ?4 S4 b
        }
$ S& M4 C( b: S        if( exsound_select & 0x04 ) {' E  @& j" A* {' N, U- y. t
                fds.Write( addr, data );( B$ v+ w3 A7 b5 j
        }; w1 Z$ A4 o8 X" O( i# g
        if( exsound_select & 0x08 ) {  Z8 x/ j0 b- L4 j; r
                mmc5.Write( addr, data );! _7 g1 t6 n0 |$ P' A
        }
/ k! N* H- Z- {  \        if( exsound_select & 0x10 ) {; @* b" K7 T3 }0 R3 }. B
                if( addr == 0x0000 ) {
, _3 G" b- x# N: L- \$ a% w                        BYTE        dummy = n106.Read( addr );
0 Y! b9 v* Y! H                } else {
8 x) B7 }; ~) B+ F' U% q( d                        n106.Write( addr, data );* {- g7 h. u* t7 Q1 l5 y$ h
                }
! l9 O. U) Q0 ~. H9 u, ]        }' ^, _" v2 H3 w8 v/ V
        if( exsound_select & 0x20 ) {5 d' _" X- Z" _% _
                fme7.Write( addr, data );* A: p. J( Z& T* M8 o, H
        }, o  x% b2 o$ K, s3 F
}7 Z" q0 `- T" X! \8 Y, V
  a; H, q& |2 _2 m$ C( S1 {
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )3 _& i" Z/ P8 e& |
{
2 x' T, [. [4 P9 x/ DINT        nBits = Config.sound.nBits;
0 v3 a# o) ^1 w& f2 rDWORD        dwLength = dwSize / (nBits/8);
3 t( |* Z, U2 y$ k8 `; D0 cINT        output;
: M2 p# j- b* H8 q9 rQUEUEDATA q;  @4 L# p, `: n" m+ N1 O
DWORD        writetime;
$ f3 G. ^( Z$ }2 K3 L& `$ L6 U- a: \
LPSHORT        pSoundBuf = m_SoundBuffer;
) b  x- Q2 |& k% c# p& z, \INT        nCcount = 0;5 S! V( D; n2 g5 o: N9 ]  w
3 a% h% P4 m; T. r- ]
INT        nFilterType = Config.sound.nFilterType;
1 z6 X) v% R+ d  y' d6 R% h+ H) e: q- k1 h- w
        if( !Config.sound.bEnable ) {
% b' [. h* h& r$ r/ E1 Q6 T! j                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );6 ~; U: F' }& K1 a1 x+ t; U" u
                return;
: p0 v/ S7 G5 B$ W        }' `- r) Z# Y6 p: H: B# w

  X6 [/ Y( G5 m        // Volume setup
  g, [! D! L: w( ?        //  0:Master
+ H( {) H* T9 {+ a        //  1:Rectangle 1! K$ ?6 n" }" q% e  n9 n( S
        //  2:Rectangle 2$ O& e' Q) U, Z) J) Q" h
        //  3:Triangle2 Y, {8 H- c) z. X( i
        //  4:Noise+ o5 e) d: n0 w) m/ |0 |* T
        //  5:DPCM
5 F: H& `' T. N% `2 e7 t        //  6:VRC65 ?! _/ J2 O2 |4 x7 g6 p
        //  7:VRC7
% ~5 i; N+ F. D' F( l# S' K        //  8:FDS
; @: w  ]4 C) s7 _        //  9:MMC5! O0 N4 Q  l- O5 w) \3 i
        // 10:N106
4 O; c2 r* H) {; s5 A2 \1 h' n1 @0 z        // 11:FME7" Y( m/ h) x8 o/ V- t" q+ w  O6 V& l
        INT        vol[24];; H) F3 J% r! r2 }" t
        BOOL*        bMute = m_bMute;# V: [: e- H# P0 _6 z/ m8 y) e
        SHORT*        nVolume = Config.sound.nVolume;
* ^* ]: {7 Y; u3 u6 c1 f2 F2 _
2 Z) `$ I5 P9 Z& |4 j, C1 y% B        INT        nMasterVolume = bMute[0]?nVolume[0]:0;1 ]- r4 e6 c4 t; Z- [; N( q6 I
2 R$ J$ e0 y7 l
        // Internal
3 E( b$ N5 Z  O1 V5 [8 [        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
6 @" j$ r, I' h        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;4 w& [1 @/ e. ]" }3 [; M$ \
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
  u9 I6 H9 e- l; `4 ^        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;9 W8 d9 G; h; z' M1 B" i6 g
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
9 E" r% J% `* q$ h/ A
6 t( \" u. C" l9 s9 H& V; Q6 `        // VRC6
& U7 z7 t2 c* v/ I, Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 \8 T& Q: j- ~1 P) x
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( d+ V; ]! R" {# N2 b+ @+ Z
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 n% q& `3 r  A' `( S+ m# A4 @4 h3 j  R; Y: x. G( W
        // VRC7
- c/ R; n8 @( @5 Y" u" ]7 v/ O        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;, z- C6 i2 F& D4 R5 g
' l1 _. s9 _" D/ Q4 A* W. ^
        // FDS
/ a/ p6 r1 Q* h5 a, [" m& Z1 b/ f2 B        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
) j* X0 }9 S" b6 `
) H7 g) T" H; K: ^# d# b$ E        // MMC5
; U* A2 ~7 Q8 t  c/ R        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" t' t6 g# c8 C' A: T' y8 H$ {! G
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. l$ Q) m* Q9 D+ `9 [
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 z# p2 J  q5 |2 H

* r! i4 S$ [: v; V5 j1 y. V2 }        // N106& S$ W8 X. `  t5 v9 N
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; U" u4 x5 ?4 ?; }/ r
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 }) K/ @# ^, x. z% J        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ q$ J$ s7 Q7 A7 b6 G
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 @' B( T7 q: u5 g, C# B* D& ^        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: e3 c5 e! B# j; t" @5 d1 u        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ V* g( |' e5 i6 _$ ~$ v
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ c2 H9 j) @4 w. I: S% B        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* Y8 i" Z* z2 L  R' ?) h

, e5 X# Y/ _6 w- a8 y" `( u, d6 m) Z        // FME7$ n# p8 Z  i- z3 a- O
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 |+ e$ e) \7 }7 \5 k        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 y3 g& Z5 j# K& y5 u- O4 Z, q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% Y% E8 x' l% d, z0 a7 u
( \5 ~+ P9 B7 N2 M- i+ o7 Z
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 S' x! b! p; p% s( l        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;6 m5 F! c0 M; I4 Z* s3 ?
/ w1 f1 R* c2 p* S4 T, _
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
# i5 E; t# z* G" Q3 f/ e        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' Q% |( h  S1 W
                QueueFlush();/ {0 p9 x: n2 d0 c6 ^% F- j; o# R
        }
6 |  v8 u, E  h1 Z8 U: a+ a" _  \( m& C: F: s! n
        while( dwLength-- ) {
" _$ g) N  d1 Q0 ?                writetime = (DWORD)elapsed_time;7 U" a1 U+ L  m! C
) j3 |( n4 N' a! |- D; {, [
                while( GetQueue( writetime, q ) ) {5 y( F7 s& ~! N% r
                        WriteProcess( q.addr, q.data );
8 d* B, @$ a; Y9 T                }2 d' i3 ^" |5 b+ o
9 O. @. y+ P& S" J
                while( GetExQueue( writetime, q ) ) {
& _% @$ I0 r! V7 ?. {! d+ l3 ^                        WriteExProcess( q.addr, q.data );
. _6 D8 }# c. \2 q7 B                }
0 A9 \/ o& e4 X7 O* |; h
( K- [1 ]' I  Q- o9 k( \& ?                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7  ^5 J1 c, w  R7 w& b, H
                output = 0;
+ P" p9 @( a1 W4 a8 M. Q9 V                output += internal.Process( 0 )*vol[0];
8 V8 o' P2 U# h& \                output += internal.Process( 1 )*vol[1];
2 @6 O. x) E) q) e. b9 h4 K2 {                output += internal.Process( 2 )*vol[2];
0 t. Y. y) M* s5 k) I6 `6 Z: u                output += internal.Process( 3 )*vol[3];- d( ~( @# q0 q, f
                output += internal.Process( 4 )*vol[4];3 `$ A" w) J4 c' |; n! Q1 B7 Q
: w- S3 R* p$ A0 |/ c. [
                if( exsound_select & 0x01 ) {
/ f0 |3 j5 S' D4 C+ J3 e! }- K                        output += vrc6.Process( 0 )*vol[5];
, ~4 a- W6 A/ ~+ T8 z$ j, n; M                        output += vrc6.Process( 1 )*vol[6];* O, I( g; R5 f) P( b* i% D
                        output += vrc6.Process( 2 )*vol[7];
1 Z  q0 O3 j$ a% A* A( L                }
# g  J1 m/ P! N& k                if( exsound_select & 0x02 ) {
# E" L" I! p+ [- h0 \/ Y                        output += vrc7.Process( 0 )*vol[8];
& |% _+ y4 K& L8 _# C                }
; A% {) m+ P! b; \# |                if( exsound_select & 0x04 ) {
( \& ?# S8 ]" K/ i& H4 h                        output += fds.Process( 0 )*vol[9];
7 F4 A' K& u4 t% A; k( A7 S, K- U                }
: o# o( w  O& k; R. _1 d- m, B. n                if( exsound_select & 0x08 ) {* \6 E; E+ s7 P( R5 c. N& U
                        output += mmc5.Process( 0 )*vol[10];
- m9 F* s! y! J2 R6 X3 Y3 H                        output += mmc5.Process( 1 )*vol[11];
# o6 a/ A5 e. V                        output += mmc5.Process( 2 )*vol[12];
* F. M/ ]' Z% F                }
! V3 L( R( Q& H( B                if( exsound_select & 0x10 ) {
0 B, S' a3 |- X# P' B2 [                        output += n106.Process( 0 )*vol[13];
8 M: \" W3 H  n+ y# ]. f, V: `1 c                        output += n106.Process( 1 )*vol[14];- L6 B  H3 x1 a* P
                        output += n106.Process( 2 )*vol[15];
! ~* @) k0 ]; M( b6 X( a5 f0 `                        output += n106.Process( 3 )*vol[16];
& R( V# s6 U. r8 ~1 \                        output += n106.Process( 4 )*vol[17];
7 D- V- F; ]* d                        output += n106.Process( 5 )*vol[18];( X( s% g8 a6 [. r+ L
                        output += n106.Process( 6 )*vol[19];
! M: d, E/ ^4 X                        output += n106.Process( 7 )*vol[20];! X( p. N" `3 d8 _
                }
+ y  m- r3 T# J1 _* N, x4 [2 |                if( exsound_select & 0x20 ) {
& j( d' W- L+ T% v2 Q/ P                        fme7.Process( 3 );        // Envelope & Noise# z. n- h1 m! ]" a
                        output += fme7.Process( 0 )*vol[21];
  u/ B5 C4 ?* e; u4 Y+ V* `                        output += fme7.Process( 1 )*vol[22];
& e8 ]2 `& G7 @8 q                        output += fme7.Process( 2 )*vol[23];4 B0 N$ J0 z+ I* u& M! W2 q  Y
                }7 o3 c- u1 ~. A* a1 C6 v' ~. H2 j4 B

( u/ @' \. \' L2 i                output >>= 8;. j: x! A' Z7 U, T0 I

8 `6 j6 B, K7 B8 T" g: m                if( nFilterType == 1 ) {
4 z( W( D$ |+ K, d7 F1 t4 S                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)- L' E# V9 N4 v& \6 j. S
                        output = (lowpass_filter[0]+output)/2;
& }4 n$ u, v# R) F                        lowpass_filter[0] = output;
2 V! m1 {! I; f  M                } else if( nFilterType == 2 ) {0 \1 b+ I, u) H7 z! L9 q! Y
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
, j2 G) Y6 j9 `, D; ~. |                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;5 X' d2 ~) \' @, F
                        lowpass_filter[1] = lowpass_filter[0];
+ H  B7 x$ k' X  k, P2 L! }                        lowpass_filter[0] = output;0 l9 W! A: [+ ?, L* Y+ D4 ~/ H; R
                } else if( nFilterType == 3 ) {
, H5 G4 R8 A) v" A$ M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
& |6 ?1 F4 E. [8 s0 m8 n) ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! j/ F0 S1 g/ [3 F7 s/ }
                        lowpass_filter[2] = lowpass_filter[1];5 S7 A7 B4 P6 [7 b2 h
                        lowpass_filter[1] = lowpass_filter[0];5 l+ A2 L& y6 d" m  X# H0 t0 F  m  a
                        lowpass_filter[0] = output;
% x6 S: ]3 I. e% \% y" c                } else if( nFilterType == 4 ) {
3 E3 F+ z3 _0 r( M. f& i                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
% c8 o! P$ e9 K4 W: t( u6 u" o                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* d" n- c1 p9 ?: x                        lowpass_filter[1] = lowpass_filter[0];
8 m( P+ T% }3 H1 e3 C2 T- I                        lowpass_filter[0] = output;
2 ]7 Q( Y7 O2 ~                }( \0 {' b: A* m7 E

1 k7 |  W. I  |5 K2 @, _0 ~# E#if        0
- F  e1 B! X4 I/ h, x                // DC惉暘偺僇僢僩2 n$ C; m3 ]7 q, j4 C) ]
                {
# _1 J0 P# S+ }                static double ave = 0.0, max=0.0, min=0.0;
2 J1 p! P4 M8 C: r                double delta;( ]2 b- {! N. m# o
                delta = (max-min)/32768.0;$ D* J% N+ z8 Z% K- T
                max -= delta;
/ ]6 M% `: c9 H9 f! X, e) ], ^                min += delta;
5 o! c1 ]7 W$ E+ ~                if( output > max ) max = output;2 I; g9 g$ s1 ]/ B" o) \
                if( output < min ) min = output;/ j% d1 z! X. N0 `
                ave -= ave/1024.0;1 L/ i  n5 M& d' ^
                ave += (max+min)/2048.0;
8 C# v& v  O+ t: f& q& c                output -= (INT)ave;0 A9 t5 d5 b3 s( n
                }/ X- `: w6 p: B6 D5 Q$ b# S* @5 i
#endif3 x$ h3 s; u6 P) p5 g
#if        1/ \  y1 O( c0 p) @) K9 x" e
                // DC惉暘偺僇僢僩(HPF TEST)0 m" e: f( J1 H1 x" |
                {0 V/ s6 N  S/ f6 y0 m4 h" Z
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
: m+ a) `0 k' V. r$ x                static        double        cutofftemp = (2.0*3.141592653579*40.0);  j8 Z3 Q, ?6 [% A. N; X
                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 @( m* k- @6 b& o9 |7 I
                static        double        tmp = 0.0;
3 n. a" C9 O! P) @0 T                double        in, out;7 S$ E2 E) {# S$ V, x  r2 t
2 a0 R( c5 @" h% J
                in = (double)output;/ H" k6 T0 F. @% @1 _$ c' y
                out = (in - tmp);
) C4 e; w( n- g6 X7 D- ?) _                tmp = tmp + cutoff * out;
$ W* }/ |! N7 i/ a
# ~0 {' X) m. z2 z                output = (INT)out;& L: R2 X/ H4 ^4 [3 g
                }7 Z) G0 ?- w, {- R+ k; g) [: Z
#endif3 f* j% d' [" i8 f" x
#if        0
4 F1 @! V) x3 T, c: E2 e                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
4 u3 N- R) k& n; S( ?' u                {
/ q" I9 b. Z) y& b; O9 x* l: r                INT        diff = abs(output-last_data);; C+ \8 M5 ?8 k  M" p
                if( diff > 0x4000 ) {' Q' }, I9 e: N# C) u, A
                        output /= 4;
( r/ \$ }1 A5 c* ?* R                } else : ]2 C9 ^; Q% ^; o
                if( diff > 0x3000 ) {" W2 \4 ^/ E7 b+ T3 Y& h  \
                        output /= 3;1 M$ r( ~5 X* p$ R; r
                } else3 @9 K7 A: D  X& }7 c7 q& t
                if( diff > 0x2000 ) {+ t% d. R' o7 q% r8 V0 i9 t
                        output /= 2;
, w% h* O9 f3 R' z                }
/ X1 ~/ |  y' B% T& C$ w                last_data = output;# U5 l3 C1 m# ?$ M# r4 S2 S
                }6 B! K6 n) z  k3 l0 s; {
#endif
2 ?/ I3 m! ~7 G( @                // Limit& ?1 a# B  }1 N% h* K( G
                if( output > 0x7FFF ) {
0 j' k: f* Y1 \; s) b5 R% G                        output = 0x7FFF;
/ D6 K: m& w5 U' X8 m                } else if( output < -0x8000 ) {
- E4 }# @8 W& P, a! b# [$ K' Q                        output = -0x8000;2 K9 z8 D% W8 v- J4 J% o3 z
                }
  E* G5 a8 G1 e! U/ u3 n- o& }4 k$ r) W
                if( nBits != 8 ) {
) x- E+ j6 E$ F                        *(SHORT*)lpBuffer = (SHORT)output;- i) e- ?& ]' {) S7 q
                        lpBuffer += sizeof(SHORT);
; Q0 Z. V9 j/ R& ^3 f4 z% b, P                } else {
+ V' c0 K- R" _4 g' t! ]                        *lpBuffer++ = (output>>8)^0x80;
8 Y0 N7 _$ w0 Y& G                }
& o: ]/ E7 K  X( {: y4 }1 h6 F* N- o
                if( nCcount < 0x0100 ); T& g+ s8 R1 X$ c8 L8 l2 ?) C
                        pSoundBuf[nCcount++] = (SHORT)output;, Z/ W- m, G, w

( \# o) W: X/ p3 J6 c//                elapsedtime += cycle_rate;6 q% i6 z9 L; T  |" [
                elapsed_time += cycle_rate;8 {1 L( T, y9 x+ S$ a( ]
        }+ ]# I( T$ V9 m. [
& l6 j" m  ^. \8 Q- K5 C
#if        13 \* v! n6 ]0 k1 v  Y
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* z% q. l& i# f) M                elapsed_time = nes->cpu->GetTotalCycles();) i: o. L  E# Q0 r+ ]/ [+ m3 y) V
        }- l3 j  w% [8 J1 s+ F6 d
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
- x5 ~  q/ C* k4 u                elapsed_time = nes->cpu->GetTotalCycles();" i9 o7 O, g" g  T9 X; f
        }
6 I6 f$ I  [7 i% y7 E  S( @#else
: `# L/ z3 A4 t- x. ]; z/ t8 {        elapsed_time = nes->cpu->GetTotalCycles();
- R: x# |9 t& ]! g6 I#endif* f: |) M0 `: ~# Z7 _5 S5 D
}
5 E3 W8 M4 ]  O/ T* d$ S& _3 K: f3 P$ v
, Y$ U+ x8 q& _# Z; }# ^// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)" |1 n" `1 j9 }9 N; W0 c
INT        APU::GetChannelFrequency( INT no )
- C# X0 H" a* ]- v' v0 |9 Y0 K1 u{; Y, _+ O* ^9 ^9 \9 B
        if( !m_bMute[0] )
: D3 a. |; K6 ~                return        0;
. \5 Y8 M! E3 A& v
& M2 ?) D/ \8 B8 k        // Internal$ P' \8 O# [- I; O$ e+ w' r
        if( no < 5 ) {' B7 u/ G$ Z- D- G& t! S# a
                return        m_bMute[no+1]?internal.GetFreq( no ):0;% J! v% b- B+ g1 k+ ^
        }
5 T, t6 O2 J8 H+ e  `) ~  B        // VRC6
) |( p7 q" h" W; |, b        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
0 E8 l- O9 m" n  Q4 F                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ `1 b& ]$ U0 m' G' _! O
        }, a7 R) A  _6 l5 j+ Y6 d
        // FDS
9 j  c+ _" b4 P3 y        if( (exsound_select & 0x04) && no == 0x300 ) {
. x+ k& \8 Y3 q# a5 ^( F  w                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 j9 w, q! q4 K1 k5 y1 l* q* Y1 h$ _
        }
& x0 n, i. j! S        // MMC5/ {2 m( i' \7 i
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {  U2 k0 ^8 F$ [* _# r. {7 h
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 i2 ]& w  K# z; S- f
        }1 ~/ x3 f$ l# f) D" v& F
        // N106) I- \4 h- N' R! y; F: S# U
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {; s) {, F: S& [6 h; G: N/ N
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
) c! p: J2 `; t5 ^. h        }9 {% z/ o1 N+ {: S
        // FME7- s8 y3 U- \, j
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {; q# V) b" `& \, Z: b8 Z
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 y; ~/ w0 c8 s: `+ P! C        }
! d3 m& ~. H: h$ L; l- {: S        // VRC7
3 g# @( u! o' H( h1 \: R        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 @5 q8 N' G8 M2 {  w                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. Y; E3 o/ V$ D0 O* U1 o
        }( Q, j% S9 @! u" z
        return        0;4 j5 o8 H! V' U, t2 A) A* j
}
' R5 V1 x  S* p! z! H. K" C. C
- I9 f$ w/ x/ O/ n0 A1 ^& \// State Save/Load9 H& J3 e, {4 k6 r5 h! |# L
void        APU::SaveState( LPBYTE p )3 n' \3 Q& d% G/ y
{
2 A% B3 F6 M. ~. P#ifdef        _DEBUG+ t1 D% s/ L/ U- i% \
LPBYTE        pold = p;
* x( \2 M, J1 t5 }#endif8 l( w% F% P9 S. n6 A9 u  ~/ P6 H
# {7 |( K) ~$ k% b( S9 I
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
( D( E3 ^0 e3 E" l4 Y9 R; a8 Y( F        QueueFlush();. k( H; [- S0 @
& q! v# W6 J/ _# E
        internal.SaveState( p );7 r2 H1 F# c# \" o  P; B/ ~' m3 j& }3 _
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ [2 w9 O' A$ e: y
! {" {% j4 X0 j# D2 w        // VRC6  c1 ?8 l6 U+ ^6 f
        if( exsound_select & 0x01 ) {9 R* Q& L/ x$ @% x- N" N: z
                vrc6.SaveState( p );
) p. H% Z& y4 M2 r7 p. u! A) P' I                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ {/ H6 c' t5 M$ Y% o        }3 G  G7 B- A8 n* q! |" S
        // VRC7 (not support)  F8 ~2 u1 P! a; S8 H8 _/ b6 ?
        if( exsound_select & 0x02 ) {$ y/ Q! f( V: _7 p# a
                vrc7.SaveState( p );& k3 P2 y+ g- S1 {% ?: Q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' S5 k6 D( N) p& P1 k        }
& H/ _9 ?+ H" c        // FDS6 h1 a% p* z% x+ _  I* o
        if( exsound_select & 0x04 ) {/ _, K# |5 v; q. z0 B
                fds.SaveState( p );
* x( x# \$ F  Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. C; s, q3 H5 O0 `9 N4 V
        }
" s4 q4 d! ?: e9 K5 O- H& {5 H# p- K        // MMC5
6 `( ]3 n$ S( S: a0 e2 \        if( exsound_select & 0x08 ) {# R  t+ @* s2 K  a2 B' l! ~; ]9 f
                mmc5.SaveState( p );2 b& k+ ?, p$ a+ d# x, [  w
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: _$ d* ^. B/ k8 G1 }. K6 K$ h. |
        }
1 q7 K* [; ?! J7 v* O* I( t9 k        // N106
2 q8 Y" N# d/ |( C& v8 z  {8 H        if( exsound_select & 0x10 ) {* u/ o8 u) U1 W8 f  G  e' z; B
                n106.SaveState( p );
5 `7 {8 P' W  Q+ h. G                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 o7 ]$ R7 n0 u8 ^, W* o        }
- a: G8 ^: d8 _: v1 P% ]4 m* a* O        // FME7
, ^+ @2 B5 W/ m% s        if( exsound_select & 0x20 ) {
3 b( Q/ i- n9 b, o) l: N6 s                fme7.SaveState( p );/ S5 \/ h( q- F
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 T! v! S0 ^2 P5 z$ t4 X9 j- ]% Z        }, \6 r" A5 M+ ^1 ?3 E, i
/ N& ]8 b- @' K6 Z* K! u4 ]' j
#ifdef        _DEBUG- d  ]( [& F# ~0 J" q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );3 c+ Z& L5 H/ d( [& P0 w
#endif. K! Z! ]0 n& L- w
}
! @' e4 b* F9 V1 F: O6 c. w
, r  C; a8 x9 |) o# T8 yvoid        APU::LoadState( LPBYTE p )
- B+ r% b* [7 H% o( s{
: ]' w! m: Z, L) J        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
& [! W& G: y) [+ H+ ~        QueueClear();0 x* J" w" H0 `! |4 Q. V
& s% Y8 c6 @" O- C0 j
        internal.LoadState( p );
" d8 J. k3 }6 {) x" ?# |4 E3 J        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 p% r' A! z# h6 A" @; s5 W* ?; N* H) m) g# w3 A9 R
        // VRC6! u1 {# h! j3 P9 W+ `# v
        if( exsound_select & 0x01 ) {
% @* Q/ N; T( |' o# r                vrc6.LoadState( p );
" w) p- x7 r* s                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, y$ j9 F# W0 J7 }        }( {) I0 T  I) Y$ K& H6 ]
        // VRC7 (not support)/ c3 N( B5 t6 z$ B
        if( exsound_select & 0x02 ) {$ A/ g' T4 \9 I( _
                vrc7.LoadState( p );8 C* P: X8 W8 Q6 O$ u( P' F% Q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 N% |6 B& E8 b1 D4 _/ j6 {6 D        }  ~6 d/ J9 q# s. X
        // FDS, W) f: a9 O; K9 ?* f
        if( exsound_select & 0x04 ) {, @6 a( i8 U1 q* f
                fds.LoadState( p );5 q8 N4 F& }4 I. D6 }; u( u0 B# p) n
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! R" C9 ~6 L3 i
        }) ]6 L+ W% Q9 @; l1 c/ |. W
        // MMC5; R5 G" m1 ~9 g* `. `; ~) s
        if( exsound_select & 0x08 ) {
  q! K. _! E# E+ ?5 V5 V                mmc5.LoadState( p );# l7 D; @. S# C5 C
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& u( ^) ]" Q8 g) x5 v        }! V% k0 S' p6 |% H) [0 G
        // N106# l$ a: R6 Y6 m/ P: t
        if( exsound_select & 0x10 ) {
6 O: X2 E! d. \' {                n106.LoadState( p );
9 z1 {. E+ N! C  X                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) E' q8 ~; W: }
        }
8 |! I+ W* E% q8 r8 ^: q* z# p        // FME7
9 R/ J: a0 m  f$ W        if( exsound_select & 0x20 ) {2 G7 o) w; w) K5 x
                fme7.LoadState( p );& y9 d) U- E3 {
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# {7 M5 X! S* [1 ?4 n  K
        }
  e' `9 Z7 C# I  S$ A}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
# E6 q& ^. j' c0 d3 F5 z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
% ~1 L) U% y3 _- Y% m$ [2 u感激不尽~~

' c! w) A# [, ^" S恩 我對模擬器不是很有研究,0 Y# a: {* G7 i' I% ^: m; D0 U
雖然要了解源碼內容,可能不是很困難,$ _. i% v! K- A: K0 T3 z( `! s
不過還是要花時間,個人目前蠻忙碌的。
, ~0 ^- q  I' \+ \9 m0 |* M
- V3 j. X3 D. |# d# G  }  I給你一個朋友的MSN,你可以跟他討論看看,
) S! P' m/ C% d+ Y3 M他本身是程式設計師,也對FC模擬器很有興趣。6 T- v) g. e- ?3 C& i3 i1 X; u

/ I/ A% V% I2 c* D2 `MSN我就PM到你的信箱了。
3 H& j6 l: w+ O, M2 x& V7 v
# b1 @/ u/ d$ v* p7 i希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 2 o# ?0 {% F5 i
呵…… 谢过团长大人~~
: Z8 R* u. L* S8 G- {) a0 @. P
* M+ b% `# n8 p0 W' t. T
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 4 n) _. X6 E: [2 C- Z+ ^1 P
团长的朋友都是神,那团长就是神的boss。
+ |3 f& O& u  F1 U; }7 L
哈 不敢當,我只是個平凡人,
3 U7 n, W. @$ i* v" E1 D* c1 z! u要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! E; Y; M0 c( ~6 c1 E0 p
ZYH
* I7 d7 ^: K. A* Y, Y" d' G, JQQ:414734306
1 G( W  B/ p8 r' _. tMail:zyh-01@126.com
) n( E' W# D: P9 G4 x
6 b* t7 C5 y4 g% S4 K2 A他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * P6 ~- [' ], H1 B; L
再次对团长大人和悠悠哥的无私帮助表示感谢~~
! b  p- L; W! ~: U8 L& h/ m
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-3 04:31 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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