EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 v1 i2 I& [$ t; J5 V楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" F  H& J- h4 P( [& a这里有相应的模拟器源码,就当送给大侠了~~- |+ q4 s7 {& t& b2 B7 {
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
1 Q0 b& t% U' j9 u) H, i% R能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. f. ]' X7 Y5 |; r楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# Q1 J! C* ?! V4 z( o0 B4 d5 [
这里有相应的模拟器源码,就当送给大侠 ...

$ P% b: N; }% \# _9 G3 K: h聲音部分(Audoi Process Unit = APU):
* N5 _2 {7 B% p, s- H1 A' o, s* f0 G.\NES\APU.cpp
& T! s" d* S7 h4 m  @4 N0 |.\NES\APU.h
& ?( L" K, }, B5 o8 @' p, W8 g. Z
1 i( x  ?8 u6 N3 T) s* [/ k) k7 h5 s) ^7 u
影像處理部份(Picture Processing Unit = PPU):6 k5 _1 Q; {( `& H+ p$ C
.\NES\PPU.cpp' t8 r! F& D9 w. J" ?
.\NES\PPU.h
8 m# @( f: E, g6 r6 e, s
/ w' Z% Q0 m; W* J/ k7 k0 ^; z' T/ i如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
8 b! `5 ^% G) p+ [(由于很多专用术语和算法机理都不明白,所以看不大懂……)& H4 L, j* [# A  O+ e, {
//////////////////////////////////////////////////////////////////////////; C+ k+ k( D$ y% @  K
//                                                                      //
# m3 x$ |- n1 N//      NES APU core                                                    //: U8 n% p( g. `8 f0 @; v  y( l! z
//                                                           Norix      //- |' w( X' u; S% c: Y* K4 G5 n
//                                               written     2002/06/27 //! Y9 E5 v$ U; `9 s
//                                               last modify ----/--/-- //
8 E& F. y% R  Y+ S+ u; N//////////////////////////////////////////////////////////////////////////, v. V3 t5 B" s* Q% D) l; W6 F
#include "DebugOut.h"! b! _: h; @- X/ I" g7 a6 J
#include "App.h"
" `1 H. z: q3 ?' M- \! S- h0 A' d#include "Config.h"
4 q- O) n9 h9 |5 f- x! G
; A  d6 v; C6 J- [+ ^# s$ [. s' a#include "nes.h"
$ R  s' ~: F% z- [#include "mmu.h"
- P5 [# [. e5 [1 j: F: }( N; Z: y, L#include "cpu.h"
8 t6 c6 k; l+ i! d& ~% a#include "ppu.h"6 s; E" k( `$ ^3 z( l6 I+ p* Y+ T3 ?
#include "rom.h") j' y' g& d( C6 u$ ~
#include "apu.h"
8 i) K/ z- d2 C$ |
' g3 p. C( Y1 \+ N# U* u8 m, ~// Volume adjust
7 P3 Q0 w' H: Z7 h  {, t- I// Internal sounds
. W  R, G; h- x/ A#define        RECTANGLE_VOL        (0x0F0)  D# l; X: T, y% t
#define        TRIANGLE_VOL        (0x130)
* K$ R$ ^3 d0 f/ k  @4 X#define        NOISE_VOL        (0x0C0)
( Y) e* ^4 G0 }0 ?# M+ H#define        DPCM_VOL        (0x0F0)
4 l; D% H) b  S3 e# U  A2 W# a9 k% a// Extra sounds. G9 W7 M+ D- w0 U" W( C
#define        VRC6_VOL        (0x0F0)7 p: K0 T. V( F; k) ]
#define        VRC7_VOL        (0x130)/ T: d) Z' d! S% ^
#define        FDS_VOL                (0x0F0)" o+ S- U5 }* w1 t5 P; i4 X
#define        MMC5_VOL        (0x0F0)2 j6 v6 l) R) [+ m' U
#define        N106_VOL        (0x088)( [( q# z3 ^$ K% Q' B7 o. p
#define        FME7_VOL        (0x130)
' F0 Q; a* G+ _* g$ u" @4 y: k9 S
) v7 V  h+ a! d: G; dAPU::APU( NES* parent )# K& k' h* |( @1 a! W# H+ t) \9 l
{: y4 G( Q+ |$ k+ N, s
        exsound_select = 0;
" h& a* M5 ?  Y
2 p  I+ @$ g" q9 l; x, I        nes = parent;
3 ~# T% {7 R1 k4 M- T  Z        internal.SetParent( parent );( p' l2 P6 }" x5 N
8 i9 M9 i& Z# g- e: U
        last_data = last_diff = 0;
- Y5 Q7 x% l$ o( B: O" r  p/ ^# U1 [2 z) U% \
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
7 H6 @, m8 S! f- K: b7 t
8 f; ^* q+ C3 A3 A5 i7 o        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; b4 @, T8 X  x" E- a1 d        ZEROMEMORY( &queue, sizeof(queue) );9 H( h* ~' N) t) q: v, r6 Q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* S% Z# y1 J2 c1 Y# D5 v9 p
+ b  J4 q, M* z0 r# ~* X# [        for( INT i = 0; i < 16; i++ ) {  G$ j% D+ q6 m$ ~
                m_bMute = TRUE;7 [+ h: w$ Z; d4 U* R
        }- _) n! c' n" r( l8 _! F. Q
}
( O& c2 ^1 i' [( ?
$ r1 r+ n; ^% j1 @# x0 aAPU::~APU()
1 c6 E" D3 l) W4 f( x{0 y# Q% c4 F* k( T% O0 ^
}+ P$ A  X6 ^( M

9 M; c, k  T7 l2 @void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
6 }/ Q* D- Y& p2 A* h7 J4 `{( Q( A& w7 }* R" `2 {
        queue.data[queue.wrptr].time = writetime;
# A/ v' B' ~8 [- I" y. U        queue.data[queue.wrptr].addr = addr;2 C$ g' ^8 H: N: w' b% {7 z
        queue.data[queue.wrptr].data = data;
7 m& Z" L7 H4 o        queue.wrptr++;: P. }, v* G# @1 j) a& b# f
        queue.wrptr&=QUEUE_LENGTH-1;
/ t6 D8 h! `& v, G        if( queue.wrptr == queue.rdptr ) {2 c+ N  C8 H$ l7 u
                DEBUGOUT( "queue overflow.\n" );
" x$ i) E1 T* p; w5 W        }+ ]' w' J& v  d" b% R" C
}
- w- w* u- I4 z. U" [" @; z* A( n+ d4 l4 ?# Y; D& s& n
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
$ n1 b# i# Q0 i{
+ W+ P% {  ?( J        if( queue.wrptr == queue.rdptr ) {
: Q) j9 p, B4 Z4 {' {! y2 n; L* X                return        FALSE;2 W2 q" L$ v7 ^8 D" @1 p2 [1 j
        }) W2 Q! l  B6 b6 n7 W& \: t$ P
        if( queue.data[queue.rdptr].time <= writetime ) {8 _( f0 k/ [& s; e' K+ v
                ret = queue.data[queue.rdptr];: f, x4 U* x* m* u6 `' O) Z
                queue.rdptr++;9 n3 u5 f% Z4 A0 }) H% V
                queue.rdptr&=QUEUE_LENGTH-1;  M3 }8 @# L9 S( k3 r) L! `, O
                return        TRUE;
- F+ v) N' ?2 R% y8 j- C6 h4 J        }
* ?4 \6 q0 t0 w' r4 N        return        FALSE;
/ W( X, U9 m: y9 O& e7 h* X5 O% z; M}* o, {4 B& v2 h4 X, J

1 E8 m) q% y, ?, D  K6 A9 a" xvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )' P7 C0 C% N2 |5 o+ v; L: t7 B
{
& O& Z+ w/ W" P5 V( \: s3 W. l        exqueue.data[exqueue.wrptr].time = writetime;
# H, N$ _: ^1 [4 Z7 g9 Q: V7 I$ E6 I        exqueue.data[exqueue.wrptr].addr = addr;+ h! v  C3 e: p1 M
        exqueue.data[exqueue.wrptr].data = data;
; s3 W8 m6 c1 {3 w, j. a        exqueue.wrptr++;
4 I% Z5 d; F/ v( \        exqueue.wrptr&=QUEUE_LENGTH-1;
2 A3 u. g2 X3 T* v: ^6 ^- W1 ]        if( exqueue.wrptr == exqueue.rdptr ) {
+ z& X5 ]/ x$ V, x! d& ?                DEBUGOUT( "exqueue overflow.\n" );: ~( b3 B/ ~8 u5 t5 ]1 y9 l
        }
" D6 c9 S9 v" a. X6 G1 e}$ Y0 A9 d) k4 p$ T+ T7 U
: t0 t, p9 y/ U& W+ ?$ j5 L: j
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
% {$ _1 ?- G$ t$ R! B1 X5 |9 _{
6 E* a( a# Z8 R) }        if( exqueue.wrptr == exqueue.rdptr ) {3 h$ X* O$ l% d0 Q% p! {
                return        FALSE;
, j: T( v5 Y  v3 ?9 m- m+ V        }
& Z; x3 [. C7 i        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! R2 E3 V- k% d% |7 D                ret = exqueue.data[exqueue.rdptr];  B( s; o8 F' r
                exqueue.rdptr++;
( _# k; c2 l( X- [                exqueue.rdptr&=QUEUE_LENGTH-1;7 ]5 H6 F* d# d' L
                return        TRUE;
& \. T0 s' `! Z, U, B( H4 [# a        }
4 Q) F- b5 s( z9 M9 K0 s        return        FALSE;
( C/ m( H; k' V0 O: ]: S: y}
9 `" W' V( k# I9 N
6 _" D. q- h5 [2 ivoid        APU::QueueClear()
# S* G8 y1 d+ C; V3 H/ `{+ q1 ^) E) E- F% g3 I' p
        ZEROMEMORY( &queue, sizeof(queue) );
6 Q/ P+ f1 Y: L: s1 U. M        ZEROMEMORY( &exqueue, sizeof(exqueue) );& m" g0 r! Z6 p4 H! R) ~+ n$ b; n
}
- p( ?0 K1 K9 {1 U0 u8 U$ D+ k" X. w- x' Y
void        APU::QueueFlush()- E0 U; Y7 B- u$ g7 g. `
{- W$ _9 p% r* m8 o" r- C
        while( queue.wrptr != queue.rdptr ) {
" N. ?  o  q& j6 n6 u                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
+ R8 P* K* f4 O+ G9 _                queue.rdptr++;
! j' L7 u. X; j                queue.rdptr&=QUEUE_LENGTH-1;! M/ `: }4 V( e7 I2 J% R
        }
# P3 t# r& m: s: Q' B
% g3 q  y8 V8 N* `        while( exqueue.wrptr != exqueue.rdptr ) {$ D$ J1 _  N  t5 Q6 H2 m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
1 E# \. d$ x5 e: j9 `+ G9 g                exqueue.rdptr++;7 ^# d$ {: L$ q; m7 r+ k0 j2 b. v+ P
                exqueue.rdptr&=QUEUE_LENGTH-1;' J5 f1 Z. y# g' i
        }  N1 x* t. N3 h
}
3 P' z1 [' a# j0 B) q2 e6 d, m+ B( \# e1 t9 z0 V- M, D! k
void        APU::SoundSetup()) \1 W1 h0 Z: \( d' t
{: i. i/ r* S, N  I& ~
        FLOAT        fClock = nes->nescfg->CpuClock;0 U2 g1 p, k& o" J
        INT        nRate = (INT)Config.sound.nRate;  w  X8 e' X/ {7 ^$ N0 k+ ]+ ^) r! x; Q
        internal.Setup( fClock, nRate );
% ~* h9 `& @8 i4 K4 A, R. n        vrc6.Setup( fClock, nRate );7 F- x6 A$ S! M# @4 S) d- @3 d( C
        vrc7.Setup( fClock, nRate );
4 X, L/ F2 J# Y        mmc5.Setup( fClock, nRate );# A# A# b% v9 q# {
        fds.Setup ( fClock, nRate );: x/ W2 y# c2 z% x3 J  g" q
        n106.Setup( fClock, nRate );% J1 u& o6 N* K& [% D# [- X6 H
        fme7.Setup( fClock, nRate );0 E" k5 v) K; c0 F% x
}
# S3 i- T( s7 s; e
$ W* ~" n, c* v  ?void        APU::Reset()
  I  i& ]7 @9 ^* M{
: h8 q! Q; @$ ~        ZEROMEMORY( &queue, sizeof(queue) );
! S; T- y2 O0 z3 V9 d% m6 q% |, I- ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 b2 G3 m1 ]( _1 @' a1 H2 V/ w

0 `! R4 y. n3 E# d3 {        elapsed_time = 0;
" x% X/ f1 x/ T$ b0 k
" m; d* _: q( u" [  D7 O# z, W        FLOAT        fClock = nes->nescfg->CpuClock;/ @" c* ~$ j( ^( U# S1 J( V
        INT        nRate = (INT)Config.sound.nRate;0 n: i/ _# q. P% P" U- a. ^
        internal.Reset( fClock, nRate );
0 I3 N5 ^. K! X" D. t; Y, O0 }        vrc6.Reset( fClock, nRate );# @+ W$ y# |! ^& c- @4 b
        vrc7.Reset( fClock, nRate );' ~3 O' x4 `5 M* `) ?
        mmc5.Reset( fClock, nRate );" d0 I9 z' M: ^# W
        fds.Reset ( fClock, nRate );; h! }3 U# @9 f) t. \7 A# F
        n106.Reset( fClock, nRate );
! |' D+ ]* ~; u# {* r        fme7.Reset( fClock, nRate );
& B/ e- \4 f" u) h) ?0 z" K. x" x% i/ l7 h
        SoundSetup();
2 l: T1 m3 ?' n' O0 a}5 o7 p: H5 V9 g: c" H, h

& a# ]. l8 [. Q' x" Cvoid        APU::SelectExSound( BYTE data )
$ D% {; e/ |3 y. S  ]- e) n{
" r1 f; e1 U4 B! H" u+ g: i        exsound_select = data;: G6 \3 w1 s) z# o- i
}
, \- X: y- T& m! |9 W& m3 n0 |+ h; o+ X
5 `" I7 r$ d* wBYTE        APU::Read( WORD addr )( q/ {  }+ E" R2 W7 D+ `1 S0 a+ b+ `
{' z4 S  z! }3 r; p  f5 }: t
        return        internal.SyncRead( addr );
9 `6 b/ M5 u+ P' d}# o! W7 U7 B; b0 k1 V9 K
1 t) p! p' Z0 d4 I3 ^
void        APU::Write( WORD addr, BYTE data )9 O, H! n5 O: f- d1 u" ?
{
( y! Q4 }! ?3 G; ]0 @, I        // $4018偼VirtuaNES屌桳億乕僩2 B# A8 [  T' b0 p' Q
        if( addr >= 0x4000 && addr <= 0x401F ) {
7 H/ C3 }  z+ ?0 A$ B0 Q: n+ S1 w                internal.SyncWrite( addr, data );
4 O5 t' _8 c( o" w                SetQueue( nes->cpu->GetTotalCycles(), addr, data );+ @( e" F. J0 v6 g& N4 s
        }
4 d* V5 l5 P* l1 R3 y, I}
4 Q; H( J! H# E" ^! x0 J% f; \$ P6 m4 t' n
BYTE        APU::ExRead( WORD addr )
7 U1 e6 f5 `* ]& }2 ]{* L& \% Z, P" \/ h) [
BYTE        data = 0;
7 A: A* P' t# v% h9 N4 K, |( e) N$ ?6 Q, b% j, K0 R/ W  [
        if( exsound_select & 0x10 ) {9 @# |/ t' Y, `0 n$ I  n  t
                if( addr == 0x4800 ) {/ k1 x% c, a" O9 A8 v, Q3 a
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
* d1 ^& m- Z2 h: |( u' N                }
# O3 {; K. p2 |, O+ t: T5 S& `        }+ l' i/ ^) e, ~8 n, b* v
        if( exsound_select & 0x04 ) {
7 @9 e* Y0 H# E* Z& K! F5 L. l                if( addr >= 0x4040 && addr < 0x4100 ) {
. ]; D' W3 u: t8 g' W0 J                        data = fds.SyncRead( addr );
/ y& }' g4 |2 U7 M1 P                }2 g  o6 B8 N/ K: Y1 E
        }
( q" [6 a6 H; a        if( exsound_select & 0x08 ) {
% g8 ], ?# k# q2 c" c' n- ]                if( addr >= 0x5000 && addr <= 0x5015 ) {
& R. C" z  e( f8 C/ d, r# {                        data = mmc5.SyncRead( addr );
( u( X% I; O9 N: j. y2 R# o/ `  J                }
$ W9 ?" P) k8 S) l. G# z$ a# x        }1 O7 x* w& T2 r

4 r  w. p9 X0 \# X6 b4 Y        return        data;8 l, S0 _! r& y3 |" m2 w9 |
}
4 V0 `$ T: l' Z! d( L0 f) C. q. Z9 k; ?/ S; U5 }* X' b
void        APU::ExWrite( WORD addr, BYTE data )
" u3 C( N1 z" b, m% A8 z1 G4 Z, p2 S$ r{9 p* C. @4 o+ B4 f) T1 r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
' K) G7 i, R. z- _! ?+ F+ a6 r; J* ^$ Q8 q9 |
        if( exsound_select & 0x04 ) {
4 \1 \! F! h! f3 k9 b& L; G( }' q  L                if( addr >= 0x4040 && addr < 0x4100 ) {
6 c9 P3 \' W0 M) ?6 i! S                        fds.SyncWrite( addr, data );8 Y5 @; o+ \1 Q9 f) |2 `
                }* r9 D3 d. J6 V8 m
        }& b  p. V, Q( D
/ M' J: G0 N: i1 ]
        if( exsound_select & 0x08 ) {1 }- L! I! z, c7 u
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# M# S% W9 {0 @3 B3 h                        mmc5.SyncWrite( addr, data );, W5 c; j& f, w$ X% E
                }1 ]* Q. p/ c# R1 x
        }
( e- a% q  M* h8 t5 e% Y$ [4 N}
7 t# ?8 Q9 v7 W6 Z5 V& ~) u6 J6 W
0 Q' ?+ J% S7 bvoid        APU::Sync()
3 L! B8 `& S5 [2 A- w{6 D5 e9 w; R3 h" f
}
6 T% h/ R9 E" q! a# I% M1 Y* ~; X+ Z" p3 ?, G( o+ F4 w
void        APU::SyncDPCM( INT cycles ), T7 t! s! K! z4 e" R
{. _4 ~3 B( I9 w2 M
        internal.Sync( cycles );. o* Z% h- g1 `2 J6 {" A
) Q4 z9 T) S1 Q) U6 o/ z
        if( exsound_select & 0x04 ) {
& D/ G  [3 p2 y                fds.Sync( cycles );
0 \# s/ g1 l0 l, Q8 J( Q  L" R5 [        }  ?) V# k$ K: q' C7 p
        if( exsound_select & 0x08 ) {
& t6 Z4 y" ~! m! O: T1 T3 m7 d9 f                mmc5.Sync( cycles );& \7 R" ~6 h7 N8 E! q
        }; a" e% v3 ^: \- s; Y
}. C+ a3 s5 E, D. r3 O- y. s+ T5 ]

# D1 E" ^5 }" L5 y( x$ Uvoid        APU::WriteProcess( WORD addr, BYTE data )
5 e+ _! N4 w' A7 b+ A4 B{
  i* J# ~' ?% Y* c& m        // $4018偼VirtuaNES屌桳億乕僩. W! |7 x& }- ~8 ^9 e# t4 Y  i: M
        if( addr >= 0x4000 && addr <= 0x401F ) {; ^4 \5 v- \8 x" b$ Z* s
                internal.Write( addr, data );& h5 L$ L) d, r* I: [+ v! R7 b
        }( J1 N) s) E& e3 J5 K
}
9 L: u9 u  D) `1 ?0 h2 g! X3 T3 s& I! r$ ]5 d- h: @. P
void        APU::WriteExProcess( WORD addr, BYTE data )% \. M. R: Q* X4 t- V/ x
{
( H7 r$ t" N4 x        if( exsound_select & 0x01 ) {* f  q; c# a1 z) j( Z8 Q) Y0 p, i
                vrc6.Write( addr, data );
2 d3 J; \. H5 f$ D! F+ Z; G4 V        }
. ?* ^1 {! c3 I) C" C; o        if( exsound_select & 0x02 ) {% A1 [7 _( E! c; i7 F# J( V
                vrc7.Write( addr, data );
4 R5 ?' F; x9 I6 s. q6 i        }% \9 q  p& A) x- Z  a
        if( exsound_select & 0x04 ) {
0 ^; ~; s4 F/ |+ b6 e                fds.Write( addr, data );
' J/ E/ g; _" H8 Z7 b. y; @( \. @        }
) T7 i1 ]4 j( Q8 K9 u) L+ O        if( exsound_select & 0x08 ) {% S4 s/ D2 y0 H
                mmc5.Write( addr, data );
1 h. J) p& @8 ?& F0 m. w# @& f        }0 ~5 v8 ]7 H4 r$ v2 O+ J8 ~
        if( exsound_select & 0x10 ) {
) K  e& Q4 G" Z& K* ~6 b2 p6 A: {1 y                if( addr == 0x0000 ) {& Y5 U- k" z% B* s" D
                        BYTE        dummy = n106.Read( addr );, I8 F/ k! H6 r$ T7 f8 v/ I2 I4 d4 p
                } else {1 j+ F8 b$ G9 T8 l; {! q  Y9 ~
                        n106.Write( addr, data );
$ K5 h* K- ~! u5 a4 @" Y' t; T                }1 a1 w& J9 Z1 f/ c6 }( G
        }
) u, I8 l8 i" d8 f+ V        if( exsound_select & 0x20 ) {
* G8 W, O) |/ m* W0 n0 z                fme7.Write( addr, data );
/ K" C0 ^* l  ^8 i        }
, c0 |2 {0 }$ C/ r6 X) y8 v}, m2 Y: }/ ]* j

& w+ i, v! U- Y- b8 ]void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )& v8 |5 e7 D8 M: F
{4 ~* j' A7 @, |$ i3 v* t
INT        nBits = Config.sound.nBits;
" A+ V9 O3 T3 h# o- f' hDWORD        dwLength = dwSize / (nBits/8);1 P1 i# s' U1 {
INT        output;
  C8 b0 Y) H# W8 |* @0 r- @QUEUEDATA q;
" _1 ^0 l+ D& [. p7 DDWORD        writetime;
- `& h% F. t: R
* P& |) c) h. d6 Q* s9 M" OLPSHORT        pSoundBuf = m_SoundBuffer;/ h( a4 v5 }2 P
INT        nCcount = 0;
9 h9 e5 `2 h- o' @* Q: ^# \$ G/ y  G! a/ ~
INT        nFilterType = Config.sound.nFilterType;
9 F/ A' \  y! h) q1 q9 C. V
' [$ q- Q7 V- Q- q$ C        if( !Config.sound.bEnable ) {1 B1 X, R5 x" X% |2 w
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
8 d& ?9 w2 v+ c* n                return;& L2 m% g* t. q, h/ a
        }
8 F' J7 X7 z# E) U
. p3 t* R: ~/ D0 p) F1 d3 j        // Volume setup
4 Y- J) |; {7 E6 f- u: K        //  0:Master
2 }' {1 ?# M/ Q" v        //  1:Rectangle 1
5 u3 {$ o% ^# H, E        //  2:Rectangle 2
- v/ D9 z+ Q% T9 w/ t. Y, D& E$ V        //  3:Triangle
7 S% t6 c3 A/ _* p9 a& `        //  4:Noise# _& `5 Q" D9 q; P; X8 B
        //  5:DPCM
3 B) x8 ^8 I; t6 ~7 d        //  6:VRC6
, |1 r( S5 K4 F9 O" Z5 l. M# }- A2 a        //  7:VRC75 j! }4 ?$ w4 r( |
        //  8:FDS
" z0 Z$ V* C% ~! q        //  9:MMC5# m% b$ a/ [) G' b: C9 i7 |
        // 10:N106
9 M* m+ W" f) Y        // 11:FME7
9 O4 g$ e1 r7 T5 i; e* B2 X9 G        INT        vol[24];
* F  s. U5 |" u) P        BOOL*        bMute = m_bMute;+ N% d" N+ Z" H; L, `* z# M- e
        SHORT*        nVolume = Config.sound.nVolume;
9 Y6 z6 U4 h, u- g. `- n1 b3 [' J: x( m5 s' v
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
9 d" }- p# b, P4 d7 U1 z% y. ^" H( Z$ P5 O1 R  n6 ]$ h$ {
        // Internal
4 Q# R1 {  U3 ]1 _" `        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: X* i$ T, z8 ]& A+ j
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 [. Y$ y8 k, X% D        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
+ [& C& Q- v0 _2 K  I        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;" ~+ T+ B; X8 R6 x  w
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 e6 Q8 t2 i% x3 @. B+ \6 J( e. S; U3 W$ d0 U
        // VRC64 R0 G$ M% x/ l( U: U% e
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; B* c) W4 X9 ~: d5 v
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 ], U9 i5 d# {' H. \/ u% r. D        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 o+ k1 O5 N" ~( V1 ]

4 f" J# ~3 T3 j( G# S0 |% Q        // VRC7& k% k. b0 I4 U/ ^5 [5 D  z, }
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% s, P  P8 I5 z& c7 Y, h# m  Y

5 g3 s: J4 S7 s: o# x        // FDS' t3 K+ H# u+ r# R0 ?) l
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;/ f7 P! q+ o1 x" A6 x5 Y8 m
& C: I4 p/ e. I. |2 U
        // MMC5+ T2 N; ?7 J9 `
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 [( U1 T& ~3 ?# i        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 x0 y3 J) J- {# J' G
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- ?6 A3 P1 J3 N# y  d! ~$ z) w' `! g0 W
        // N1060 D* X9 m/ h7 S8 A9 K
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 G: ~% G# A4 w/ N( D  n
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( [, }/ G  x( V" c        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; Q3 m, j- ~( X        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 z# ^7 ^! K. t2 o4 S
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 }4 ?' H& f  E9 Z        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 r% k$ f* [( A3 P, a3 U# c
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 Q0 J) d% k+ S" X) ?( @* Y
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) M0 g3 [3 P7 z" ]
, J% ^( r7 `% }- P. q5 [- v' T1 k        // FME7
( f; @: K  p+ q2 H        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: t# c5 Q- X5 R
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ Z( v! m, l. O2 H        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& \7 u) A4 _& i: m0 s+ h' D
" q" b# x# X6 A) J6 @, r) C
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;( C+ X% L; q- g% P0 M3 J9 X( _; a2 G
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 c7 X( f5 T9 T4 j6 ?. P
1 O4 R8 e; I# \! ~  q        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
6 x, A& w9 z4 Q! \        if( elapsed_time > nes->cpu->GetTotalCycles() ) {7 @) x, a5 X1 T! z" D- X
                QueueFlush();7 H5 h- @- ~5 A- C
        }
  i: u7 _' y$ c/ _( R% Z4 N& z6 T, r8 w1 }  u; N
        while( dwLength-- ) {
- D8 |( e5 {# `( D3 }9 Z: |* Y7 ?! W                writetime = (DWORD)elapsed_time;
7 g: m; o! P/ d/ P2 t
( w- A$ N" x" V/ D2 ?4 A, `                while( GetQueue( writetime, q ) ) {! v8 S9 c7 [) Z% ^( E& N2 V" N, [
                        WriteProcess( q.addr, q.data );
. m/ x6 c' O% W" Z# _4 Q6 E                }
9 y( l6 u1 ~2 b) _
& W- D$ y" ~5 Y                while( GetExQueue( writetime, q ) ) {+ ?: {% Z, V1 @- z4 D5 b
                        WriteExProcess( q.addr, q.data );
* l( {6 m& t4 M6 d( h& Y7 z  n                }3 m# M0 I( d7 A& ?

0 `) B* h( F/ ]- @" P                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
- Q2 ~: s, W6 Q/ U9 Z/ K                output = 0;7 b% y4 X, O! ^/ L' V4 W& J5 S
                output += internal.Process( 0 )*vol[0];7 X1 U; r- Y2 Q: _3 f* ?* \. q& X) \
                output += internal.Process( 1 )*vol[1];
: D! V, G) x8 w' Y2 a1 S                output += internal.Process( 2 )*vol[2];
3 H, e* ^* A2 d/ Z                output += internal.Process( 3 )*vol[3];4 g% ?# @2 a' ~! b3 L
                output += internal.Process( 4 )*vol[4];4 C( B  ]5 s: x* Q1 Y% K
" b& K0 y  o! O% y
                if( exsound_select & 0x01 ) {
( g/ v' {( M2 @3 N! }1 Z: n                        output += vrc6.Process( 0 )*vol[5];
& q* l, P2 A% |2 c; a$ w                        output += vrc6.Process( 1 )*vol[6];/ E% q. M. D" i7 x/ S+ Q; N
                        output += vrc6.Process( 2 )*vol[7];
1 m  P, F! J, x- c! L                }
$ w6 v# O6 d6 C                if( exsound_select & 0x02 ) {
, Z" Q. n% L- T6 @& N                        output += vrc7.Process( 0 )*vol[8];
4 W. d8 |  V) p8 ?+ l4 T                }. Y' q, y2 e/ `4 F' }; h* N* B
                if( exsound_select & 0x04 ) {3 Y! A5 n8 w- ^: l+ i% `; ]) ~
                        output += fds.Process( 0 )*vol[9];
8 o/ I. `- t  W( n) O. P' p5 U: f( R                }/ e" a& {1 |8 Z
                if( exsound_select & 0x08 ) {, f" T4 e) n- _2 i$ }
                        output += mmc5.Process( 0 )*vol[10];& D) P$ J7 t. |% m: D  j- [" p5 s
                        output += mmc5.Process( 1 )*vol[11];8 `7 V5 x# N0 V- c- c4 u* Z
                        output += mmc5.Process( 2 )*vol[12];
7 a/ W% n' v+ O& _                }/ Y& W0 U6 d* i2 D) s0 e
                if( exsound_select & 0x10 ) {
) @4 a5 d/ }, ^4 ~( A- N( ]3 m                        output += n106.Process( 0 )*vol[13];, b2 C" t& g: A  U) k
                        output += n106.Process( 1 )*vol[14];6 g7 Y) I8 ?# h
                        output += n106.Process( 2 )*vol[15];) i: L' X( U8 L* c, R% Y/ d0 N
                        output += n106.Process( 3 )*vol[16];
$ Z) k3 |6 e. W                        output += n106.Process( 4 )*vol[17];
0 V9 C$ {3 A% G( h; H                        output += n106.Process( 5 )*vol[18];- {* V9 G3 A' ?& U2 W" S$ y
                        output += n106.Process( 6 )*vol[19];
$ A6 ^8 o8 H' G& I: D                        output += n106.Process( 7 )*vol[20];
' h0 a' H) N) O! q                }
) L$ x8 D- R' k1 h6 \                if( exsound_select & 0x20 ) {$ A0 D8 }  A8 t1 [# j
                        fme7.Process( 3 );        // Envelope & Noise
6 P: Y# c# \1 H" N. y4 M                        output += fme7.Process( 0 )*vol[21];
' j# A0 Q  f$ [                        output += fme7.Process( 1 )*vol[22];! X, n% c5 X# l. [! U' l3 V8 K5 W
                        output += fme7.Process( 2 )*vol[23];8 r. ]! @8 p. _2 S3 V( R
                }
% t$ u& z* z0 ?& U  [- G! H; U. V4 Z- R' M; |5 \5 U
                output >>= 8;
2 t1 v* M+ V& I3 _& [) Z- F4 P9 N. E  p# s) p* \" b9 G* W
                if( nFilterType == 1 ) {( g; Y% f# r" ]/ k
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) R8 w+ U+ T* Q7 z, U
                        output = (lowpass_filter[0]+output)/2;! V* y# G* i2 ^' W/ R. T) l5 ]
                        lowpass_filter[0] = output;5 |& K) ~/ \. R" Z  r
                } else if( nFilterType == 2 ) {. D2 B# M- @; B; ^' C
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 y$ c  Z. b& e0 X1 M' C  O
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;5 q3 p+ p9 z5 ^8 |# Z# `' {& t
                        lowpass_filter[1] = lowpass_filter[0];3 \2 j- T) n/ v" X
                        lowpass_filter[0] = output;7 O2 ^, g) R" ~- X
                } else if( nFilterType == 3 ) {
( t: w5 ]& @. B  z$ L% d                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)7 N5 q/ x1 U, W" i3 n8 {, {* ~
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) y* A' n! t; ^! @; |7 I
                        lowpass_filter[2] = lowpass_filter[1];
1 _% t) e9 R7 r! d) G8 m) `2 X                        lowpass_filter[1] = lowpass_filter[0];6 @! X7 s2 r' N
                        lowpass_filter[0] = output;
4 o' j& v9 n8 h                } else if( nFilterType == 4 ) {
) K. ?/ F; T9 k& Z) x                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3): L! T1 v- W# f+ M
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;7 F' g3 D. V; H( ^0 I
                        lowpass_filter[1] = lowpass_filter[0];
) Q: Y! H( n. M. K# C5 }7 Z                        lowpass_filter[0] = output;
/ k5 |( p. w* |                }
$ I, u3 G  E, w; i. _
$ \( M2 z4 c) j4 I#if        0
" V( q  r0 r$ q& v2 B                // DC惉暘偺僇僢僩% P2 o6 [- e. g3 E
                {# \0 b3 T+ Z+ z( {- K, j3 b# r* f
                static double ave = 0.0, max=0.0, min=0.0;( r3 p& q8 \2 ^5 ^9 W& e  ]4 x
                double delta;3 \/ \! X0 z& f" Q- H2 n
                delta = (max-min)/32768.0;
. m, Q6 k' z0 A" K$ `" h                max -= delta;9 b$ |5 i/ b$ |7 s/ X
                min += delta;
4 H% `" ~5 Z5 w; \                if( output > max ) max = output;
. E. D: {$ V3 _  U                if( output < min ) min = output;; h3 p( i' V. B, E- z! x
                ave -= ave/1024.0;
  ~! [& ^) R% ]* U& Q8 q2 `$ ]                ave += (max+min)/2048.0;, r+ `' C1 [1 p; p0 y& \
                output -= (INT)ave;
3 n( ~$ m* R, ?; d3 K$ I) C0 O) x- O                }
3 J6 D- `( a! U" P: ]#endif
4 U# F1 s% U2 l5 s#if        1
8 _& R- }4 t5 W  Y6 a+ Z                // DC惉暘偺僇僢僩(HPF TEST)
. _7 M# O$ q+ S" _                {' |' v% C# V: @1 G& _' R# P: F) f
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ Q. m, G  X+ X, r( F  y$ O                static        double        cutofftemp = (2.0*3.141592653579*40.0);9 F- F' e; K- I2 u& z" u) p+ `
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
; d' s" X% s4 ^4 U! R                static        double        tmp = 0.0;6 M  D* U5 }8 W( H
                double        in, out;" V+ n7 @7 Q( }
2 V+ U" U! R) z+ j+ ?( J; z
                in = (double)output;
- ]4 k, q+ g5 E- h                out = (in - tmp);2 J5 _7 v4 A7 b+ {! B1 |
                tmp = tmp + cutoff * out;$ x) v/ v- ?3 \

8 L: Q( B8 H' z                output = (INT)out;3 g% x3 i6 F1 S  i& f
                }+ `+ r% z# J- x4 \- M+ A
#endif
6 u* h- f, R/ \. e3 Z+ u#if        0
( o+ d' |8 p! ?- b" |7 X6 D                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* l- g* W0 g4 d6 {5 ?% i" p, ^* s/ `                {
$ l! ^+ q/ Q' [4 O5 q+ D7 {& q1 k, ^                INT        diff = abs(output-last_data);
: g* n4 b2 ~7 q- R+ [& F                if( diff > 0x4000 ) {
9 s, d" j3 P1 h1 H/ k) x: a5 |, A$ p! D                        output /= 4;
& _, p+ r. e- x9 \                } else ' A  t( ^8 d% j$ O& j1 T1 f3 J
                if( diff > 0x3000 ) {
: h* j6 X5 U0 d4 h* S5 k                        output /= 3;7 w+ F9 H8 [9 S
                } else  V' r- B% q6 |) j5 A+ g4 c' h- }# x5 T
                if( diff > 0x2000 ) {/ U$ z8 Y$ c% [6 b6 J
                        output /= 2;& n2 j" `2 y8 ~/ a6 g4 ~
                }
, Q# V" S3 T$ g+ l2 R: }                last_data = output;+ X3 Z9 b! C8 ]0 ~( z
                }7 ?2 z4 T% S- H; Z. R6 O1 p7 D
#endif
( X' \" ]6 x2 D' B! n                // Limit; W7 f4 L' c1 h7 v6 |/ w
                if( output > 0x7FFF ) {. w5 ~# }6 ~9 k: n: Q
                        output = 0x7FFF;
( O: f9 h9 s& M0 Z4 h7 j# |0 {                } else if( output < -0x8000 ) {
: e1 o# ~9 U# o  U" C+ R                        output = -0x8000;! _, x9 @. F! a
                }
  Q6 J- ~' [7 R$ n3 P) |
) M0 _. A( ~7 x                if( nBits != 8 ) {
' v0 Q  E2 [4 L6 p( w" z3 Y                        *(SHORT*)lpBuffer = (SHORT)output;
4 I. E- i" a! y1 K+ G                        lpBuffer += sizeof(SHORT);
, L4 a3 L2 J4 W6 L! v                } else {
$ p( e% |. Y9 }# e* T                        *lpBuffer++ = (output>>8)^0x80;1 a1 q7 R# Y1 j' _: j
                }+ ]3 a4 ^6 p! Z7 A; V; ~- _, L
8 n+ d. t& {( B5 ~( V) \3 T
                if( nCcount < 0x0100 )$ \4 e/ F2 L4 T' ]; V
                        pSoundBuf[nCcount++] = (SHORT)output;
3 W0 k+ y7 y- c8 t, ]' H, H6 a7 g$ A- q* g: @+ R6 t2 E/ p
//                elapsedtime += cycle_rate;/ f$ s  D# E, |( ~" S$ v* P
                elapsed_time += cycle_rate;3 G1 F9 t9 R8 X4 Q! s5 Z+ p
        }/ W1 X5 l5 J" f5 L) ?( ]" u

) B% _) }. i1 t4 g- N* V0 t. a#if        1% S' V' c0 o& c5 y; x. v* q) k
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
# B$ b/ b5 i. O3 j, f                elapsed_time = nes->cpu->GetTotalCycles();& K. k4 {. U  c3 K6 C
        }. i3 ~$ z- K( U: {6 m# Q
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
4 ^" g, T: W4 ?! Y' l                elapsed_time = nes->cpu->GetTotalCycles();; j* b2 J5 \9 O9 D
        }
2 `* `: L) i  l* k% m#else5 g# w. a2 d. R1 N
        elapsed_time = nes->cpu->GetTotalCycles();
- R& h* Y* L3 ?" d# h5 B#endif
4 \& r! |* z  p4 w( z}
1 n1 q. }; P/ h
) i- Q2 H9 k4 w- [  T/ ^// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- L3 U: Q5 {) xINT        APU::GetChannelFrequency( INT no )" f( b/ u. }; p5 i8 y
{
# R  I0 p3 Y6 b        if( !m_bMute[0] )
) W# l+ T/ J% B( s7 ~                return        0;! [* e2 Y& L  Z1 `, b
# J# b2 R4 {" l$ I7 d+ q) i: @) Q3 I
        // Internal5 G7 C! b8 A1 H( p2 {
        if( no < 5 ) {2 b, f$ n. i7 `
                return        m_bMute[no+1]?internal.GetFreq( no ):0;, ^, f; Q; H. s/ l; f
        }
  K) R- a4 U. Y" _. v$ U2 V        // VRC6" k# P$ E0 ~$ L7 E9 v7 A( ^
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
7 _6 s4 c8 g2 G9 I9 K8 y8 N! e                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
  U# _) A& ]0 v9 Z8 R        }
8 _0 }# r/ Q& m$ q        // FDS4 V5 ^7 m3 t% Z% B. R4 C. q% B
        if( (exsound_select & 0x04) && no == 0x300 ) {- q- h1 |( g: y# w2 }/ c! F- u
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 \" L, i& h, k6 U0 @: h' k        }) s) t6 O: E3 n( u- }  F  B* F4 E
        // MMC5
3 |6 Q% P2 X1 H- S* d$ W3 K4 R        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
7 n8 e$ u7 w' ^* w                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
6 P0 w3 f: J3 g5 i        }
" Z' Y( f- n0 D" [4 ~  O        // N106
' t6 W# w; p/ D' t9 z( d: e5 a! v! n        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* X# f) f+ X  B- R, U' q, B* [
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
$ L: p- q/ R5 }5 m% c        }, Y  ]4 N5 T6 w; T
        // FME7
0 P8 C3 k) j# o- E0 u        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
/ i+ R( Y" K. q  B0 w                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, T  t( V: a* z( x0 B+ [, M
        }3 }0 Y! M) J3 Y! h% h: _
        // VRC7$ c* \& t, D" h/ [! F( @, j1 |
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ a; F( W  f9 G: i% {' @$ E                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
. n+ o: j: E+ s! y5 Y' ~" P) ^5 f        }1 n; }* p* @3 ^* J
        return        0;
, V8 ?* z" Z2 K4 i! d- p}# g9 U' w2 K3 |& u% q3 P' _/ t# W

9 l) k& V$ r0 H( [. L7 P) i/ k; A; P8 K9 n// State Save/Load* w( V5 B) O! M
void        APU::SaveState( LPBYTE p )9 h$ A2 H3 X. M% J# Z0 t
{
/ r1 s6 n0 r+ z8 H. _#ifdef        _DEBUG$ u8 u1 b8 ^7 }. K
LPBYTE        pold = p;. `  C5 a# W( a6 ^- C/ v
#endif6 M/ K( v' C% e, h! C6 j- G) ~8 b
, Y) Q9 Y+ d' j( e  `$ c
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞. E4 o' V7 t! F- H% X! k, E/ O6 e
        QueueFlush();% S, M2 K7 w; Y

. Y, F3 o% m+ V1 z0 E* N        internal.SaveState( p );0 F1 V2 O# _3 @( k) c" \! G
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  g& a  d; t4 o: j
8 D9 n5 [$ _9 J8 _
        // VRC6
3 s+ x, i+ w* q9 b" \, R        if( exsound_select & 0x01 ) {* e+ U) n/ P$ b: e% y1 d7 v
                vrc6.SaveState( p );
  S6 Q4 t! S) K2 P* h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- l7 L/ d6 E- Q! M! ?, ]! }/ q        }
$ x7 o8 F' [$ u: O& e        // VRC7 (not support)/ y) k  r( l* F: q$ m
        if( exsound_select & 0x02 ) {7 O  S( I5 {# G, P" U
                vrc7.SaveState( p );0 v, l0 d5 v6 e& O. g1 g! O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
5 U7 F5 O& Y, w, ^! t        }
# F6 \6 d! j9 t        // FDS/ ~# F7 c: t$ a; L  f2 J+ ]% E
        if( exsound_select & 0x04 ) {8 A! J2 I3 i5 G, G6 p
                fds.SaveState( p );( J6 z( `" a: b9 V/ B/ A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. m3 R+ L" \9 d! \- a        }9 E# p/ B2 G7 s5 ]. D$ p
        // MMC5
* ]9 J( t' Y0 t! d6 H2 B        if( exsound_select & 0x08 ) {
  J+ r& _/ V" O                mmc5.SaveState( p );
9 S4 w0 ~1 G3 ^! k+ ~( F- T# l                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 p! G. S$ I5 u0 R7 Z9 J0 p' s        }
- [. U! |# N# \$ p        // N106: E% ?/ W* Q- H2 ~; K4 T2 L% {
        if( exsound_select & 0x10 ) {' O% T* o0 N, F1 S4 a9 z' W
                n106.SaveState( p );
' S4 P8 @0 l  A  f/ ]) |& Y+ m                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# Q# p! L: N6 ]) @- B        }" M8 a1 Y  O" D/ u/ ]1 c
        // FME7/ i! ~: S0 I9 O: P5 d% }. k  n) }
        if( exsound_select & 0x20 ) {" U! V3 ~7 [3 F7 t2 M; Y5 t
                fme7.SaveState( p );2 a% Y0 V) D  M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 j( l" U  h+ [/ K2 Y
        }
" y8 T# j6 \- }( n4 j
1 [8 o0 F9 i! e9 X* Z- a#ifdef        _DEBUG
5 F0 d( k2 l/ H& r% ]5 r2 k  rDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );* O6 C1 ~' W7 ~. c4 n
#endif" R, S/ v/ R$ k3 _2 L
}
; L7 M9 X+ J2 P' S$ X0 ]" N1 M- ]' ^- w9 B7 F* W2 d( d* X; R
void        APU::LoadState( LPBYTE p )
, p, J5 I, H, H" \8 H! e) N{4 b9 v- _  o4 X) H) I
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 `7 \: H# T; n4 z1 E+ U        QueueClear();0 D. g. w9 o" @1 ]
" a$ [" g. G1 w/ A% [
        internal.LoadState( p );
$ |6 E' L( I2 ]+ H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; C* O2 m. y: X4 X" C
( s7 i5 o6 g; ]/ m6 X$ @1 z0 Q        // VRC6- c4 g( m  D( Q6 C% R$ y. u; J# c
        if( exsound_select & 0x01 ) {5 q( b& y% E) t% I! A
                vrc6.LoadState( p );" E, L' q) F; p- h/ U; R& p
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 F% L5 ?: }1 r6 S$ X! Q+ a
        }
5 z7 X( T% p: c" M+ o7 v+ t9 Q        // VRC7 (not support)* z9 A0 ^4 E$ P8 a7 e) |
        if( exsound_select & 0x02 ) {
0 S; a& O" H' [. ]1 X' A) s& J* ?                vrc7.LoadState( p );7 I6 }, c" p3 `7 P  v& |2 F
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! V" n- x  a5 D: x8 C* a: T' C        }4 r" t% }# j$ `2 q6 o
        // FDS
$ I* a/ h' m' e4 T+ Y; c  c        if( exsound_select & 0x04 ) {
3 e; p- l: i( b# j! t                fds.LoadState( p );
! Z+ D2 e: x0 ^. L                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 D( \1 M+ `3 w5 z1 F, H3 o& B
        }
% S5 F% @' q; x8 \, k        // MMC5
  A# u4 M# P: g6 ^        if( exsound_select & 0x08 ) {1 S) h, T% J+ @) S. ?& E3 O' w
                mmc5.LoadState( p );
$ g* E  Q% Q  P! {) l2 ?) L6 u                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding0 O) g0 k4 C. O+ _- W4 n2 J( c
        }; D  E7 ^1 M0 |0 j: Z" }
        // N106" e9 `1 t' K7 ]( O3 E
        if( exsound_select & 0x10 ) {/ A$ K6 z9 r4 w
                n106.LoadState( p );% Q9 G( C6 o; x; E5 {' m8 l
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' x( A* C5 J( c; V        }
  K0 P5 ?; d' Q. D        // FME7
& `6 g8 O  p2 D* u        if( exsound_select & 0x20 ) {) J1 K. D; ~# l1 z; W6 p6 [2 y/ D
                fme7.LoadState( p );# M; l- e' v+ o/ K
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding, g. \1 b' h. t% x, Y8 `  A9 E" {
        }
7 b' B; a, b2 u: e' X}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 g  ~* ^7 H+ l可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 d- Q, R4 C+ c
感激不尽~~
! }+ q2 c7 Z+ z* e0 B+ S
恩 我對模擬器不是很有研究,
% q' j! t+ I! w. O" ?3 b* m# ]雖然要了解源碼內容,可能不是很困難,
# r# z* X5 Z0 P+ V" ~5 G不過還是要花時間,個人目前蠻忙碌的。
8 X) L0 }  h3 K- O( J
& |3 V# h% {2 z- C: d; }給你一個朋友的MSN,你可以跟他討論看看,
1 n: R) X1 P" R9 r  Z, M7 S他本身是程式設計師,也對FC模擬器很有興趣。; e! J& A" m+ g# e

+ \9 _2 W4 ~# t8 Y  k) lMSN我就PM到你的信箱了。
2 y7 t* S' v% ]6 l, |) b' }. z: U' a
希望你能有所得。

该用户从未签到

 楼主| 发表于 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; R/ v5 @2 a  a" R* j
呵…… 谢过团长大人~~
. I) C* X! N/ B# L

: x, U5 c, d- [7 c5 g) ]7 m哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! o( }2 d/ T) l  p' c% l" @团长的朋友都是神,那团长就是神的boss。

2 ^( z) R$ v" H哈 不敢當,我只是個平凡人,* @! \6 R8 L' y9 J" A+ L
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙; y! c. }4 ^0 u* y: N3 |
ZYH
& x2 \: V2 c8 X7 \QQ:414734306
5 g5 u" B' ^: J+ iMail:zyh-01@126.com( s$ Z4 D5 J( V$ ], }  h1 ?) E

. ^" `. F8 i$ P% d; ~6 q; Y他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ n0 k/ E# i) R* w再次对团长大人和悠悠哥的无私帮助表示感谢~~

% _8 D" t% L- [$ ~/ W! J不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 00:14 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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