EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& ]4 R# q" P4 c  \1 @
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 _5 ^. u6 ]- D- ?3 F0 I& `& R2 T
这里有相应的模拟器源码,就当送给大侠了~~- D/ q2 R3 f; Q" I
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( T" k2 v; a% y7 _  I' G能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" c  E7 j! e8 V' u
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) X4 O+ {7 u& v3 C( H' t
这里有相应的模拟器源码,就当送给大侠 ...
- q8 E+ P- h5 l$ Y0 ~; a
聲音部分(Audoi Process Unit = APU):
+ ~% k4 B1 |( {( W  W# A. Z, k.\NES\APU.cpp
1 b: |7 _" Q' g" N( \.\NES\APU.h
9 p' F% n& J; F1 V: E
0 M) h. M7 |1 R2 x+ v/ _. ~3 C$ d: |( u8 I/ I
影像處理部份(Picture Processing Unit = PPU):5 X; j4 }) s9 J
.\NES\PPU.cpp
7 h2 ~  E4 i2 A$ w, r% I  Y$ M8 y.\NES\PPU.h6 D% B4 O! M3 s4 i/ C9 l

$ `# J$ U$ R5 k/ u/ q: l如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
$ l2 Y% A( O, v/ E0 i# S# ^8 U0 _6 U3 q! {(由于很多专用术语和算法机理都不明白,所以看不大懂……)4 ], g+ n9 I& I( x) J2 a4 q: b8 _
//////////////////////////////////////////////////////////////////////////5 B4 Q1 @; D( `# D8 m9 M. |
//                                                                      //, n) P& g% O4 q7 \1 W
//      NES APU core                                                    //0 j2 i( n0 @0 ]( A- E" E
//                                                           Norix      //
0 O+ q5 I+ J7 g# G& [//                                               written     2002/06/27 //: S+ t# p( z. s9 C) {$ U7 D4 _9 Q1 D
//                                               last modify ----/--/-- //
9 n2 u' p/ h/ n- I( I' s( D//////////////////////////////////////////////////////////////////////////
2 a# S6 a# w9 ?; U6 U/ Q" C$ b#include "DebugOut.h"
9 ]  Z( o) H# B* v. Y9 I#include "App.h"
' O5 q5 N  e9 q( |9 |7 X; |6 a#include "Config.h"7 ~* t  y+ [* K5 _% }0 |
" H, k6 V$ E, m1 r" }  B, z) V9 d
#include "nes.h"
! ^7 T9 E6 l+ a' J; ?#include "mmu.h"5 ]7 Q% T/ u3 n% Z; t: e
#include "cpu.h"3 u* c3 Z* ]9 {7 z4 x
#include "ppu.h". Y# S5 o  J* q" ^* m
#include "rom.h"
! B5 Q' g& d/ J- {9 \#include "apu.h"8 C! R4 p6 p) {! N9 N
2 b) W$ |! d% c; j
// Volume adjust7 ^. z7 O! U+ N0 p
// Internal sounds
+ C1 X' u' W  J#define        RECTANGLE_VOL        (0x0F0)
0 m0 b* v* R; |5 i7 @$ v# J#define        TRIANGLE_VOL        (0x130)8 [; {% R! ]9 T; x
#define        NOISE_VOL        (0x0C0)
$ W- V+ W; D  ?0 W: U3 g#define        DPCM_VOL        (0x0F0)
) g$ {4 z5 \+ I% M// Extra sounds
( i) |8 J6 Q  ~1 A8 M#define        VRC6_VOL        (0x0F0)) N3 b+ g) z' s2 G# d/ j! |+ W: z
#define        VRC7_VOL        (0x130)$ D4 @7 Y% {6 a$ o
#define        FDS_VOL                (0x0F0)4 x. i$ G9 U5 V/ l! L- ]9 D
#define        MMC5_VOL        (0x0F0)
! a( T8 i2 W3 [2 B5 K6 s6 Z% I/ i#define        N106_VOL        (0x088); j4 R0 c  ?* O% l: f0 U8 C
#define        FME7_VOL        (0x130)
8 ?3 t. v' L. o$ m% [
) Q# h, \+ o( R1 nAPU::APU( NES* parent )/ V1 a+ r# m2 u, N& f( X8 @4 \* J
{
9 |# c4 s9 ]% d' ~7 F2 s        exsound_select = 0;( k# `' C' a  _. L
% K6 F, x) P6 I( }$ b4 Y2 s0 F
        nes = parent;2 }6 R; Q3 q2 h9 N: e% j+ [  `/ |- w
        internal.SetParent( parent );
: I5 r- s8 W. N8 [* x; G1 o2 j* x
6 b# x# I/ g6 ~" ^; y& j$ m        last_data = last_diff = 0;
) C$ Q0 K3 r4 H; x; O1 i2 F6 n5 d* ]+ {
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );5 f# V; D8 z7 R3 c& D4 Z8 Z/ m

# g" P9 Z: f- f# L6 o; `        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );. S/ X2 J4 s/ O' x* H" i+ i: A
        ZEROMEMORY( &queue, sizeof(queue) );
+ g! M- `0 E' ~! v% C5 a$ |3 w6 A        ZEROMEMORY( &exqueue, sizeof(exqueue) );
8 d' b3 ^& @: G
* @& Z: t  s( S. M" Z/ @7 T4 A2 k% B        for( INT i = 0; i < 16; i++ ) {
  v* o4 @5 U8 O1 I7 h6 n* V5 |: D( X                m_bMute = TRUE;
1 ^1 ]" F" V' L* n" u        }9 S, u% u- [' r! {5 Y6 W* g
}
$ h& o2 @& O) ?* h" q' Q2 K& Q6 [% i& t; [0 G" g; `
APU::~APU()
  l- ?. \' c1 {1 g) x{
  p( A* o2 i+ u; ]/ K. \1 H% ~$ u. ~0 X6 p}
% q8 [4 ]+ T) I" u1 v/ Z7 Y9 Q0 D8 y( ]1 X; l. e9 F
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 u5 i! d# ]" k. D  O+ e( |1 j
{
4 R/ W! x, Q' C        queue.data[queue.wrptr].time = writetime;
! E1 ~2 _. [2 E/ u# a9 _2 U        queue.data[queue.wrptr].addr = addr;
! B! K. }" ~  Y5 L! E        queue.data[queue.wrptr].data = data;  Q- o' [% d: V  m6 {( {
        queue.wrptr++;
# x# [0 K- Q, y        queue.wrptr&=QUEUE_LENGTH-1;
- z4 }) W+ F5 o        if( queue.wrptr == queue.rdptr ) {
1 T# C- f" _$ k2 H4 \+ E0 ]( |6 d                DEBUGOUT( "queue overflow.\n" );& ^2 _* u; M. i& m7 ^( K4 c8 q
        }  P9 B# M; h* Z; }9 p
}
0 P8 d7 w6 r# B  p3 o0 _
4 [4 r7 Y2 i4 e5 _BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
/ I4 Z5 Y' [7 l( L- p/ R{
: |& B  l9 \, O/ n        if( queue.wrptr == queue.rdptr ) {6 f1 n8 H/ ~' o2 f7 a7 [" x% \8 ~
                return        FALSE;
9 \6 v# J% w/ p" D        }% Z% ^2 u5 l8 V. Y- j
        if( queue.data[queue.rdptr].time <= writetime ) {
: p$ F4 u9 S& i2 I0 J                ret = queue.data[queue.rdptr];- [2 B. y& S# t4 t, x& ]; p
                queue.rdptr++;4 y- a; T& L  z7 Y! K
                queue.rdptr&=QUEUE_LENGTH-1;6 g# x' u! T8 a9 k
                return        TRUE;6 _6 p4 m5 @( I' \& u& s; u1 G: z
        }: }. p; i4 i- I9 ]
        return        FALSE;" H' [" y0 F/ v5 s
}
  D* F7 }- R- Z( d* Z9 q1 w% N7 j6 \# `1 s" l4 H4 n5 H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
+ Z  `! K. [  z0 ]  c- D3 B{% t/ N+ x5 K; y. h* `
        exqueue.data[exqueue.wrptr].time = writetime;
/ l7 R" {) x2 E+ E9 ]        exqueue.data[exqueue.wrptr].addr = addr;
1 W  V" r$ M* ]% g& d2 J        exqueue.data[exqueue.wrptr].data = data;8 S0 o& I4 s; W: f6 x( d, k
        exqueue.wrptr++;1 ?  R/ b# R; q. {2 T
        exqueue.wrptr&=QUEUE_LENGTH-1;4 n1 n7 A9 ~! H* H  M
        if( exqueue.wrptr == exqueue.rdptr ) {/ c% ]  X- b. S7 C3 q
                DEBUGOUT( "exqueue overflow.\n" );+ G7 k/ a( d9 f& H
        }
( i. G- T. ^* A8 B}
! l1 N5 J5 `  A/ L. b" n% F2 Z& n3 c7 R, i
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* y. o/ k* P* |, F3 t5 Y$ Z
{
) A: ~$ ?/ b! B! o        if( exqueue.wrptr == exqueue.rdptr ) {( ^5 C/ e0 V+ Q9 X* S
                return        FALSE;
+ k. P+ `2 |/ S6 D3 D- I. A8 C        }, }! ?, }0 z* s
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {7 Y* g  s6 m! j5 }1 B# H
                ret = exqueue.data[exqueue.rdptr];; Y' C/ q4 _( F( i: t
                exqueue.rdptr++;1 }  k- L. u! {) S# L; [2 P7 F
                exqueue.rdptr&=QUEUE_LENGTH-1;
" n" X0 `( d9 C2 V                return        TRUE;( p. E4 r9 h# I) _/ H5 O$ x
        }
1 @( G. ~) F/ s5 Y' @1 W+ Z        return        FALSE;
# g" g) O5 l8 A8 ~+ V6 r# R}
/ ^. H( P7 F& {' M6 z
+ j" Y* k0 J. n. r" o8 cvoid        APU::QueueClear()
" l8 X; y0 {6 o) M+ r{
/ \8 [: ~5 C: w- T5 G# E        ZEROMEMORY( &queue, sizeof(queue) );
. j" e$ m8 o: Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ t. W! j+ ?0 Y( C% b. T
}
* Y/ e- A% A' e- ~1 h
( i$ }; ?% s( A1 b& g7 e6 w9 e& p' ~4 }void        APU::QueueFlush()8 E6 w1 Y) N, _( U" o
{. G& Z6 G+ W. F  c! z- E4 W- Y
        while( queue.wrptr != queue.rdptr ) {
( d4 w# C! O( y: C* Z: ]: g                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );" l$ q) w2 O1 h( U
                queue.rdptr++;9 K( B6 w, o) V# x% I
                queue.rdptr&=QUEUE_LENGTH-1;
8 Z& |9 Z* f, H6 y/ K1 N% K$ |( J        }
, U* C/ d" s6 d! Z6 r0 I9 e7 u* ~: A' s! ]9 i) J
        while( exqueue.wrptr != exqueue.rdptr ) {
9 f- k' @; I: L7 Q4 ]1 t( `                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 _8 ^" D. k; C                exqueue.rdptr++;# p/ _+ N) f! o( J
                exqueue.rdptr&=QUEUE_LENGTH-1;8 c2 i) G- _2 Q+ X
        }% V! U2 Q2 w. P, T: @/ ^
}# x/ \; I# `! c4 L, k

5 b' ?, [6 T' @) b: Avoid        APU::SoundSetup()! c+ K$ `5 M2 h+ G# v! v
{
$ g( J4 C  q+ f4 S& H! r        FLOAT        fClock = nes->nescfg->CpuClock;
) N- {/ c( B# \0 v$ f        INT        nRate = (INT)Config.sound.nRate;
8 t* b1 k6 ]0 e5 o+ Y        internal.Setup( fClock, nRate );, _  s+ @$ _; _% ?. t- h+ x
        vrc6.Setup( fClock, nRate );  D& w9 o/ ?* U/ @+ I
        vrc7.Setup( fClock, nRate );' [7 g- G+ `9 |, W) r! r
        mmc5.Setup( fClock, nRate );
  K9 M# o( X( I8 J' N4 _% J7 \        fds.Setup ( fClock, nRate );7 V& r9 x' N9 M9 @6 ?: b
        n106.Setup( fClock, nRate );& `! D7 a4 D- C. h. k
        fme7.Setup( fClock, nRate );0 h5 }! Y$ |! e" E1 E0 w
}
9 e' a# o$ _) x$ M: ^. q" h' T; W7 i% C6 ^7 Z
void        APU::Reset()
  ^+ A/ z; h6 h% b( R% O, N* I) X* u; S{
1 D: w( h. l6 i/ a        ZEROMEMORY( &queue, sizeof(queue) );& G0 r0 ]( X! Y. b5 s7 O4 B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, S% G# t1 o5 k4 c+ Y* \; M
) |) x# B. d- E" D; U! \
        elapsed_time = 0;
1 O9 w3 Q/ |, y$ R
( ^+ D$ m- [- d* x& `! a+ z& C        FLOAT        fClock = nes->nescfg->CpuClock;+ H/ p( y0 q6 C4 E# h8 y
        INT        nRate = (INT)Config.sound.nRate;7 D; W: y2 D7 T9 `4 @
        internal.Reset( fClock, nRate );0 f" Z8 ?$ A( x; S( a8 i( @
        vrc6.Reset( fClock, nRate );; r9 G& ~% e1 R+ G4 z( @" v4 N
        vrc7.Reset( fClock, nRate );- r; z! _8 e4 @( Y
        mmc5.Reset( fClock, nRate );
2 \7 Q7 i# o+ j* q        fds.Reset ( fClock, nRate );* D- Z# N2 B5 c7 U5 V+ z- k
        n106.Reset( fClock, nRate );/ b+ \  a# A9 w$ ^3 K
        fme7.Reset( fClock, nRate );
; g8 S! y! {( p8 O- p7 O% X
& G4 c! [* x7 r6 p" _* n" P" |8 ^        SoundSetup();
* l4 [1 K+ ~& I8 t+ l3 f% F9 P+ i}1 |9 f$ k0 [# E) D+ F/ H1 Q
! [5 t" q1 q7 }$ n* H% A
void        APU::SelectExSound( BYTE data )
# T9 B; A4 n0 F, q% M3 o) d! y- w& z{
5 {! j1 L% b; Q' D        exsound_select = data;# M8 u5 J" X1 M# s3 G+ d! V  c9 w+ M
}
6 z& B/ w8 I/ ]. W0 c+ I1 k" z- K. m9 d: U1 v! z+ `; s) c
BYTE        APU::Read( WORD addr )6 f  W- y4 \* ?: a  }3 `; ~
{$ i; w2 s% v- X8 ^& ~
        return        internal.SyncRead( addr );
; z% g1 ~  [& s$ b. e2 n$ v6 D+ k}
5 H6 ?! H0 {$ L5 _/ I: }' d! J
) U) P6 N$ _% @0 o+ Avoid        APU::Write( WORD addr, BYTE data )
# n) z: R" d& z% \{
2 L* p8 B" B0 V. T: m+ v1 o% T        // $4018偼VirtuaNES屌桳億乕僩- b; ~8 d, L: s7 e. X& z
        if( addr >= 0x4000 && addr <= 0x401F ) {5 }: E& c1 X7 B4 k1 _
                internal.SyncWrite( addr, data );8 |% M" n7 \" n/ q' i: G! d& a
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );7 v8 v, J( g0 C6 X% j0 j6 o
        }
) `. t& T3 A; ?9 L* T/ q}5 C: R+ h4 X# J* `
9 m# h. n) Q2 s% K9 D+ {: P
BYTE        APU::ExRead( WORD addr )
2 u/ m1 y7 ?  r$ ]; M* S! E+ M{" }- X6 p* ~3 f$ Q
BYTE        data = 0;# Z' v: b) a' |: T, m4 J5 C
6 `8 E- Y; H/ I8 K! ~$ U
        if( exsound_select & 0x10 ) {+ Y7 n) c" E$ |: o3 Y
                if( addr == 0x4800 ) {
1 v9 e( U, S; q; y                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, N( N3 f% O/ J% A- B
                }5 ^$ m4 i; c6 r1 a: r
        }! z, R7 o% X$ _4 o
        if( exsound_select & 0x04 ) {# K. d' Y) D. ]+ L6 b
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 F% ?! b0 F( _4 v9 i                        data = fds.SyncRead( addr );
2 y7 c! L9 m5 Z2 T8 D7 ?                }+ F7 _4 j% D0 }9 @3 C* D& a5 p1 j
        }; D% f5 k  x/ I- t; j" R+ D+ ~
        if( exsound_select & 0x08 ) {
& T5 v, L- Q" v+ S- ^                if( addr >= 0x5000 && addr <= 0x5015 ) {/ \* G. S  i9 o6 _; T. I
                        data = mmc5.SyncRead( addr );
3 \) i# N, w' z9 G5 C, H                }
0 U. Y# |0 c. I6 {* @6 b/ J: q        }: w. Q+ {6 q$ H1 X8 ?3 R2 M* B1 J- t
3 r+ e5 L/ Q& y0 z, ]8 P# `
        return        data;  I8 k  P8 H& U9 b, D
}
3 b" ~1 v7 }+ E
# ?& _( C$ |) C, n* |' z6 zvoid        APU::ExWrite( WORD addr, BYTE data )- w, D( \. E$ d
{9 I6 |) P5 p0 R4 o( h* x: h
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
3 A0 B% I! t6 ?! X9 f) z' q; u$ q8 D; T: |) A. u6 S8 a9 h
        if( exsound_select & 0x04 ) {9 h9 b" f/ B' l/ ]" J
                if( addr >= 0x4040 && addr < 0x4100 ) {1 e" e6 S/ E  t# t. K$ y$ M  ?
                        fds.SyncWrite( addr, data );
4 R* e$ f& l5 e' ?; y8 e: F& s5 y& i) P                }8 W$ ?! H3 |1 k& y; D
        }
9 i5 s2 T! o3 b! o8 ^! }; ?/ v* {! X' T; P
        if( exsound_select & 0x08 ) {
8 V& q" K1 _5 ~7 }) t: {                if( addr >= 0x5000 && addr <= 0x5015 ) {+ O3 c/ N# _" W
                        mmc5.SyncWrite( addr, data );7 Y2 g, \5 [2 v; W" ]
                }0 m5 x$ u5 C* u# ]6 b& F9 Z. S
        }
5 l% G, ^8 X* ~8 T6 Z}0 Q9 B$ z# v0 o5 Z6 l5 N! N  Q
' A& J* R( {1 f& n" H3 R
void        APU::Sync()
5 Q/ w5 I# e# ?8 J2 q{
% o  i- |# i/ @8 ?}
; r& C" S- R6 s' b: H& F  g! g% t* I, U5 N8 a! P4 S
void        APU::SyncDPCM( INT cycles )
% Z* F/ K" z8 m9 v! T2 a( u{3 v& C, d+ k& f7 ~3 u' D. |0 T
        internal.Sync( cycles );" N) g3 N7 H: U% V/ X
/ Q  K$ h, u' F- ^. O
        if( exsound_select & 0x04 ) {
6 S5 U( K, m0 Z0 Z; ]# ^. u                fds.Sync( cycles );& W* }; D- L, I: A' L* f
        }
0 f- @1 A% ~5 o# x        if( exsound_select & 0x08 ) {
" Q: I, I/ p8 |$ K8 ~                mmc5.Sync( cycles );8 F+ R. v& c! j3 G
        }# m# d* ]5 ^+ e* X) K! p
}! l- X: ?5 L1 K' f0 ?! I- X

; ^% Y* y1 {8 \! \! ^- yvoid        APU::WriteProcess( WORD addr, BYTE data )
# Y) B+ O, j& W{
" a1 K. E% X; G& l        // $4018偼VirtuaNES屌桳億乕僩
9 i  Q; d0 c; O  U: G2 Q        if( addr >= 0x4000 && addr <= 0x401F ) {2 p- p5 r! ?( z& \* ?3 N1 x
                internal.Write( addr, data );
4 A7 {2 A' e0 S3 D; ?' x# [        }4 X. S8 E# ?4 j  e# `
}
6 l+ o, G8 ?1 i: X, r' U
; a5 _. x8 f9 g& ]void        APU::WriteExProcess( WORD addr, BYTE data )2 d1 H* C) I$ i% {0 z. q- ^
{- M' I0 k+ I5 A2 e4 l
        if( exsound_select & 0x01 ) {
$ x( w  y& R5 d7 N3 |                vrc6.Write( addr, data );$ L. z. r$ o0 v" ~, [) `
        }
, u/ o; G- Z2 D- R( ]3 {% L) l* ^  P        if( exsound_select & 0x02 ) {' u& U. L+ N$ Q* w3 J, g0 u
                vrc7.Write( addr, data );
) p3 ^3 n: O7 g        }
! n+ T: `/ u' I6 W% v        if( exsound_select & 0x04 ) {
9 T+ H# u  c2 B. f  g/ F                fds.Write( addr, data );
9 J  W( ?5 s4 y( i        }. f2 _0 Y, Y' O( c
        if( exsound_select & 0x08 ) {; y; l/ N5 j- @2 C1 j
                mmc5.Write( addr, data );3 Q& ~( I0 r+ c
        }
7 N& j4 a- h5 x+ }        if( exsound_select & 0x10 ) {& u* L+ v0 o) w; F  g; t+ k
                if( addr == 0x0000 ) {
" K$ m5 [. c4 U1 ]- c: m                        BYTE        dummy = n106.Read( addr );/ B- ?$ r: b5 P: @: y7 K4 O$ G9 ?9 H
                } else {$ X( ?0 B+ |9 O* Q* O: o
                        n106.Write( addr, data );
& T; T/ w- Y0 |3 h; i6 T# ]+ v                }
+ T! h2 f$ L1 r: K5 t% \0 V        }1 C4 G6 j3 m# G) D4 _
        if( exsound_select & 0x20 ) {. Z5 v+ R  O" T2 `3 M% K, L
                fme7.Write( addr, data );
! ?# L( U' V3 ?* H/ a$ O        }
$ R( s2 L, w' q}
% z2 q, t! a* E4 [
- c0 e/ A- N9 |3 k' Pvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 ]0 i6 e* I( i( V: n$ `{9 Y3 V  I1 U; s- f( {% G  P
INT        nBits = Config.sound.nBits;
$ Q. p, p+ H+ Y$ s; n, `DWORD        dwLength = dwSize / (nBits/8);- g" i( i( K; v7 x) O% H1 O
INT        output;& c1 B8 {6 t& w1 r
QUEUEDATA q;
' k& H$ I9 A7 _4 w- u/ a9 `DWORD        writetime;
# X# s& `( [1 a/ G4 |* @4 q7 Z) l! L4 F1 U
LPSHORT        pSoundBuf = m_SoundBuffer;& ^1 B1 n) R( N
INT        nCcount = 0;
$ _5 \6 p, K6 {$ Z% C
- k2 H6 H( o9 M2 s0 f; aINT        nFilterType = Config.sound.nFilterType;
0 m, [- P* d7 p) t* \
2 q. I) e6 `0 a6 `7 H4 F        if( !Config.sound.bEnable ) {4 A* o. o1 l0 m% J% G
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; c* |6 b" Y$ d6 a7 D, r
                return;
8 L( _: ~# m( L6 e7 l$ B' L8 T        }; K& }% }  k2 w: i4 E- h

4 P, Q! u; _7 |4 e4 u# u, H        // Volume setup
/ d$ i, C/ v! F/ o% I4 n. f. F/ M        //  0:Master3 R0 i: l, v1 Y
        //  1:Rectangle 1
4 H2 ]* B/ q) }4 s/ Y        //  2:Rectangle 22 @# Y( r2 V3 K/ G
        //  3:Triangle
8 b0 C. k' U! }: V        //  4:Noise9 x" B$ h/ _+ s+ l
        //  5:DPCM4 j/ N$ a6 ?7 k
        //  6:VRC60 d. H  T' M. |0 h' ~
        //  7:VRC7
0 ?0 t1 y1 V  T$ b        //  8:FDS- {( m- b/ O1 Y# r9 Q, J$ d
        //  9:MMC58 o4 [: F% P; n1 f3 S
        // 10:N106
3 V. m+ a3 Y3 f        // 11:FME7
" r: I& z2 _) g" e        INT        vol[24];
! t/ ^* ?# o9 V8 E0 M        BOOL*        bMute = m_bMute;. |0 B4 b$ u3 s3 E2 |
        SHORT*        nVolume = Config.sound.nVolume;
' d! _7 P  m4 A# y; H5 a1 {# U) p/ o* o9 T( s& J* f+ I
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;6 a0 B) ]3 r6 e. _! t, Q

2 S, \' V2 v. h! G" M5 `# F) B        // Internal% ]8 k9 U# o$ G! A0 f$ l, V9 B( Q
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
3 k4 ]  Y6 a6 T1 k8 T        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( j- }6 p/ Q* `3 F4 J
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
& L" b! C% ^: C+ X- h4 i* S6 h; w% z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' j7 Z: w- N; H: V% ~
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;) p% Z/ Q! t2 q9 L7 G% |
# Y; P  C+ x# p" B, M
        // VRC6: x7 K1 X+ F' J! P1 T3 I( U
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 r) V8 e5 i8 z
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" N3 |% m6 n% G$ t' d1 r* Z9 r! x
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' h3 C3 m* H% ^5 l7 u- ]- T* }) c: z  ?5 l
        // VRC7  j" \; Z" b- p8 B- n: `6 Z
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
! u4 R( m  e9 E
2 ]6 B6 W$ q4 a% D        // FDS
" L* }0 x5 I& f6 U        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
* V: T3 A/ _% _  V
4 w% S, S8 l) m- L& r! I( l7 }        // MMC55 J3 f/ U+ c6 y0 _4 s
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( p' P1 ^# Y; c" a& J9 _% c4 W        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 M( s- w8 Q9 i        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ c: j: H- ~, s8 Y. y  p
" [1 B& e3 D' Y0 q4 R
        // N1068 t5 M9 Z$ M, x0 U
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ]' I- ^0 m. M% l1 u) a- N
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* @$ w1 j" {, ^# t9 U, X& A        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  [( q. O& E1 A" ?) w( B( S
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- p; B0 l/ I  l$ e; z4 Z* A
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 U4 t  Y7 ~" B" v7 D
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 `. h" H0 B( x7 W
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! r, Z* v4 g6 K4 c2 U
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. D5 F; r! R: w# `4 r9 d* F+ C8 A7 z
        // FME7
9 O' a+ z0 \1 W: L& R7 V9 L        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 M8 C8 T! |4 ]7 x8 f+ r# `  p
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 r3 M+ e( C0 \0 |
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 N2 z! ?/ V& X* M" Y4 b! O
8 P! r8 {& D% L& L2 A6 B/ g9 u//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;: V8 P% e3 [% M+ I8 s6 K9 _0 C
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;. ~% |/ U2 v  A" D9 r; a+ |2 t' X
0 C: a. z9 O8 z! W" K8 }; u# O
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
* s% ~7 |# b( c4 l6 ^        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  O7 C4 v( U" L  B- I5 Y                QueueFlush();5 s2 `6 ^1 \$ T2 D- |2 g
        }
6 y1 @4 T% P$ i/ f3 T5 e' g5 x: \3 j  @) h3 ?/ f
        while( dwLength-- ) {$ u' [) O& K/ g8 K) g$ Y$ g! {
                writetime = (DWORD)elapsed_time;; T; u1 ]) C' k
7 i& s3 N# [, N1 ~
                while( GetQueue( writetime, q ) ) {4 Q+ r" K2 B: u$ F% W' `5 l  d
                        WriteProcess( q.addr, q.data );; g( p: w7 `! m
                }
' r7 X$ v; ^4 R$ |/ {8 r  `
1 @0 J" s7 |# e2 g6 ^8 t8 f5 [                while( GetExQueue( writetime, q ) ) {3 o/ t' O1 R: j# i
                        WriteExProcess( q.addr, q.data );
4 I  G* g5 Z7 M* q2 m+ D  c                }2 d' G% I) m% B$ s4 {; q, w
2 J% @3 |9 f& s+ v/ y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ e+ V9 \' Q2 q3 m1 p
                output = 0;9 u/ M' Y0 C; D' @" D* f- U
                output += internal.Process( 0 )*vol[0];- u# F; e! K/ f! J$ e
                output += internal.Process( 1 )*vol[1];) E# j5 L0 k8 |/ r) F( J# \
                output += internal.Process( 2 )*vol[2];
" A; u: x" y- N1 V& V                output += internal.Process( 3 )*vol[3];
! r, p1 P' G- G8 h                output += internal.Process( 4 )*vol[4];/ P; o2 A$ x6 _' a

- @3 v8 M  P9 W! R- f4 X  e                if( exsound_select & 0x01 ) {
- x8 N0 _8 H% s$ j% W3 ]  e4 T5 c                        output += vrc6.Process( 0 )*vol[5];1 i8 Y/ W% K% ?. W
                        output += vrc6.Process( 1 )*vol[6];# C& h' D( a- q$ X2 t
                        output += vrc6.Process( 2 )*vol[7];, Z/ m! x. v$ F! _) l% o
                }+ e4 G) {! r5 [7 b* @% {
                if( exsound_select & 0x02 ) {! |8 A% p% \. b6 o1 C! n! t
                        output += vrc7.Process( 0 )*vol[8];; k5 m* Y* e' v3 d# q
                }3 q3 I5 ^8 x! X% c$ N9 X# f1 v- y3 n
                if( exsound_select & 0x04 ) {
2 j% d6 z( r( s! _3 Q; B/ T                        output += fds.Process( 0 )*vol[9];
8 o( o* z" G/ f                }$ Y8 h3 M" S: U2 A# @
                if( exsound_select & 0x08 ) {4 k3 ]8 W  V' C2 U
                        output += mmc5.Process( 0 )*vol[10];
* R; J2 X4 S; l. g; Q0 X                        output += mmc5.Process( 1 )*vol[11];
: x: ^9 R$ f( Y/ c% V* a                        output += mmc5.Process( 2 )*vol[12];
! d) Q  H+ P! y                }
5 z* x% @2 @' g7 w                if( exsound_select & 0x10 ) {3 [8 K. e  M# j9 C% t' O
                        output += n106.Process( 0 )*vol[13];
4 s: I, e" g6 y: \% S9 p2 m3 {! r                        output += n106.Process( 1 )*vol[14];6 v8 X7 D6 e  S! D# @/ B, n
                        output += n106.Process( 2 )*vol[15];
0 O4 s1 S" D$ |7 }5 Z                        output += n106.Process( 3 )*vol[16];( Z# B8 V2 G/ e
                        output += n106.Process( 4 )*vol[17];' K1 \+ U% r2 J( P* X
                        output += n106.Process( 5 )*vol[18];
9 o  z/ ]8 X/ J3 g                        output += n106.Process( 6 )*vol[19];  _9 r. M, n# F' y
                        output += n106.Process( 7 )*vol[20];
% T, |4 ^5 N; `2 k                }
" A* Y1 L2 I1 J9 J6 H                if( exsound_select & 0x20 ) {
/ g" u0 x/ G5 f1 ~/ y                        fme7.Process( 3 );        // Envelope & Noise
. p+ |$ j6 _, w1 @/ Q/ T3 I                        output += fme7.Process( 0 )*vol[21];
2 F7 }$ j, l- h4 M. ?                        output += fme7.Process( 1 )*vol[22];( F! F5 o* Z3 o; |+ [. @
                        output += fme7.Process( 2 )*vol[23];8 O* T5 s. P/ d# ^+ s
                }, m; i/ n* A' S0 O+ _$ V

  y1 \( ~. m9 |                output >>= 8;
3 w1 J( a, b0 h8 {+ G3 S0 t: s! w( @  C
7 r$ H, H, ^- |, X7 ]. p                if( nFilterType == 1 ) {
: I7 `, f* E9 q1 I' l                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
% h. p* C! O. u$ v9 N                        output = (lowpass_filter[0]+output)/2;
' l7 \; |0 E! g& I* q                        lowpass_filter[0] = output;" I. C$ v5 M2 ^) o! i  P* [
                } else if( nFilterType == 2 ) {
+ r5 ?! r) b3 J9 S" D                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
8 }& B9 W) W5 ?. D1 l                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;! ?8 l% G! T, i5 H
                        lowpass_filter[1] = lowpass_filter[0];
/ i- I. q  `) r" z, r1 R; D                        lowpass_filter[0] = output;
% ^( x5 ^  N% U# @& [3 y% S' x                } else if( nFilterType == 3 ) {2 `- R1 t/ R' R  R. D
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
+ x9 o' r% _2 o6 B' ~. W. |9 ?                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 i% t! k* b" I1 q: n# U                        lowpass_filter[2] = lowpass_filter[1];/ i" D9 n+ \, _$ @$ d- X9 A
                        lowpass_filter[1] = lowpass_filter[0];* K! K. ^; j) g! q6 {
                        lowpass_filter[0] = output;3 s" y# L4 s0 i3 {. u
                } else if( nFilterType == 4 ) {
% O' E1 r4 {' r- i  [4 Q                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ R9 O. }9 I  t7 M                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* ?: X# n5 e% q6 P' r1 Y                        lowpass_filter[1] = lowpass_filter[0];. s$ b4 p& d9 m, m
                        lowpass_filter[0] = output;
/ Z+ }+ y# m1 F+ V5 `2 I                }
  S& v* J- o1 P  Q$ R
7 T! G" k% t+ v$ ]#if        0
9 C0 u% ~; T9 g4 t- f8 N                // DC惉暘偺僇僢僩
( [; {: z7 U, i: h. w/ q                {: {: s1 q, E# t
                static double ave = 0.0, max=0.0, min=0.0;
2 l, X0 r& r! g7 q5 S, ^                double delta;' ?: \+ g; Y! }  h6 C. X$ Z% y1 }) U
                delta = (max-min)/32768.0;
1 D; _. S2 Y9 {                max -= delta;0 J7 f1 b, m4 D. q1 E0 K
                min += delta;2 V. e4 z. q& @7 q, }, o3 s$ M
                if( output > max ) max = output;
; {/ l  w' G& J, r                if( output < min ) min = output;& ^) v; }+ |8 H$ O) t# M
                ave -= ave/1024.0;
" r. u! p0 S( z. C$ c3 `                ave += (max+min)/2048.0;6 V3 O5 c& N+ b( M$ y" p
                output -= (INT)ave;
0 H6 S  g8 p" h8 ^; T9 _, b) S                }1 U& T- i. B  V- G# L" s" y# F
#endif
# J  b, V: _5 M: A) x#if        1
$ K- H7 Q' Z/ z0 v' X7 u# @                // DC惉暘偺僇僢僩(HPF TEST)& F: `8 D0 Z( o9 Q' t3 s
                {
& ]$ L" W4 A1 ~! h; ^4 q# f) E$ ?$ ?//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
# F9 r+ X; ?: R5 r! O& x                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# \2 c8 A/ d- T3 N8 [8 U                double        cutoff = cutofftemp/(double)Config.sound.nRate;; _/ i& C2 y3 w* n; H8 ~5 V
                static        double        tmp = 0.0;
2 b% `+ V# a5 P* C3 T* F                double        in, out;
3 n; W  m( I/ [5 F; ]
, e4 S+ v0 u6 t6 w                in = (double)output;
  o1 X. A( G6 n1 _7 T                out = (in - tmp);
- b" E. G. d' w/ n+ I" K1 y) I                tmp = tmp + cutoff * out;6 s9 m( q7 x/ W" C# x, e
  r$ N# Y/ z! [: z
                output = (INT)out;. W+ h5 z- B) \3 V" m) a! o( {  y+ \
                }
8 d/ T: V! Q% c  s#endif
3 ?! }6 |* C: k: W#if        0
/ s- K+ K' h& {5 C, d                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 M- z+ w1 p2 V$ h' o3 N$ k# X1 \
                {
# Q" ^9 @6 m: z* @3 J2 ?8 y' Q                INT        diff = abs(output-last_data);
  [/ u" f  |8 i                if( diff > 0x4000 ) {' G3 R  h( g  y" r
                        output /= 4;3 U# q* i" g; _2 `+ m
                } else
4 M, b  _  }9 z/ B& F                if( diff > 0x3000 ) {9 E& c7 A8 Y) X& l
                        output /= 3;2 Y* U7 |9 ~8 e+ M
                } else
7 o6 i# G* J* `' I- R' S                if( diff > 0x2000 ) {+ R3 M0 o7 ~) p' u( O' j+ A
                        output /= 2;
% ?1 @4 e3 A+ k' m+ u% t                }
- x8 D1 h6 o" |                last_data = output;6 _' W. M2 Q+ H' g
                }
$ C8 _6 ?- ]  s#endif
: i) x' Y& T# x) f+ X$ i                // Limit' C& m- s# }. [, X/ g' J6 x
                if( output > 0x7FFF ) {; k- z* u5 `8 j& _( n" x
                        output = 0x7FFF;
% \# z  m7 F5 L& ?0 q                } else if( output < -0x8000 ) {
7 V0 g) ~: `3 ?& M/ H. d4 F                        output = -0x8000;7 H3 S4 T0 N1 }
                }
7 ]% S5 A9 i9 ]4 o( Z3 m
/ }9 {5 L- _0 }                if( nBits != 8 ) {# G8 P7 b! C8 V2 W, L. ]# U
                        *(SHORT*)lpBuffer = (SHORT)output;
; Z/ H' N/ ?. [0 l  M+ `* V- e                        lpBuffer += sizeof(SHORT);
' I, K9 ]$ z% e) M3 O- B" X                } else {
7 X; T1 G! Q5 d  u/ K  W+ F0 J                        *lpBuffer++ = (output>>8)^0x80;3 F6 G4 N2 a; u
                }
' _3 E# l" H! ]" X, G" L' w
% x7 m) q6 K, z0 z. }                if( nCcount < 0x0100 )# J/ c, Z3 Q9 k+ c' _
                        pSoundBuf[nCcount++] = (SHORT)output;
; B/ K0 ]4 m- r, P
3 \& z6 C# c+ z6 R5 A8 c//                elapsedtime += cycle_rate;2 h: X, d. N( F: B, Z: k! V) s
                elapsed_time += cycle_rate;, V4 \( C5 {4 d, m
        }
* ?0 c, c& u, h# u. [
- \: [+ z& X4 ]: `: `#if        18 z. s" V* f( |1 \# [: M; Y
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {' H+ A# N4 ~5 Y/ r4 ]
                elapsed_time = nes->cpu->GetTotalCycles();1 W$ T! I# Q; W2 k8 X- ?# B: ?
        }* y3 {* ~$ E0 x" V0 H' I3 d8 _0 y
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {" {* p) {; ~4 U
                elapsed_time = nes->cpu->GetTotalCycles();
$ N5 g7 m. |* P3 H3 l        }" o  i0 A1 x" Y; T2 k- p0 h5 d' Z
#else, F/ S$ ]8 W( T% t9 `
        elapsed_time = nes->cpu->GetTotalCycles();
" d0 T; h- a7 u#endif* B+ }1 H8 B3 k% j* ~
}9 w1 p( S4 `+ ]6 d$ O5 I

) K' l1 q' x, [3 I& i3 Y0 L, M// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)$ N, o6 e, {& r( \- n; q" A9 J
INT        APU::GetChannelFrequency( INT no )! S- w5 p4 h$ k( v/ `
{0 {. N' }9 }1 k$ O/ ~2 P8 R; p  ^
        if( !m_bMute[0] )) P+ l5 p( B/ F4 T1 j$ h
                return        0;
3 L8 ~8 N6 V1 }) Y
1 M% v9 r! ~  [3 B        // Internal
4 W/ e" q7 u" }) X6 b2 d        if( no < 5 ) {
. \7 f9 R' O! L, C) \/ y; A0 C                return        m_bMute[no+1]?internal.GetFreq( no ):0;$ }$ L+ K6 n8 j8 Q. k$ k
        }% E2 A5 E7 W, w5 d0 _. g7 U
        // VRC6
; H' M* w& A& `/ }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 W9 \- L- }0 X% y; s
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;; H2 c; E' Z) }. v) P) t
        }9 W8 y# i) t9 h
        // FDS0 M5 i. Z" U" _( a3 g
        if( (exsound_select & 0x04) && no == 0x300 ) {; Z. _: v, Z6 `2 f. O) B
                return        m_bMute[6]?fds.GetFreq( 0 ):0;  W" r0 I4 e; Q& @
        }
2 Z; }4 h3 V* C. N6 i        // MMC5
! T2 _0 b  R( \2 T        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {% S, S1 s3 v: p% \+ a0 q0 _4 [
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 p( `; Q3 e6 n; e) j( I
        }7 k( q& `6 `2 }+ y$ U; V& M! U, ?
        // N1069 r: {9 V0 X* y$ @) |/ W( F
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 j( l0 F4 b, I  W7 T0 F
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;4 z5 a- P& m7 @+ Z) L" [" Z) H
        }! w( u5 \- H. u& G' y
        // FME71 m: w/ [& u, q- Q& \
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) U' b; y. v3 {9 q3 e5 S5 \
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;+ i. h, W! C5 O( |+ n5 n+ P" }
        }1 I7 K* Q; }6 F1 `- A) f
        // VRC7( F% B, U1 s  k2 W6 p
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {6 N4 P6 h8 X& S5 @( K
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;) H! G$ p; x2 @: K" T+ s4 _
        }
$ k& V+ E5 U# ~% E3 q  M" A        return        0;6 j- O7 B/ }0 c
}0 ^) [$ b; J" {. X1 d/ `, X
9 ~8 ]& R* M- a. a6 a" C
// State Save/Load! f) a' L: n0 k& u, _
void        APU::SaveState( LPBYTE p )
+ K$ w" h6 Z, k. S{
+ c) l: @( r1 y( x! C#ifdef        _DEBUG
! R* Z' q) A) q) A, TLPBYTE        pold = p;8 H+ Y- S6 p' q
#endif1 B, k: ?, b* P. ?' C  }6 P# p

& q. V# f% l1 R  t0 X( w        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ M- T6 s: Z: w3 [  K; {
        QueueFlush();; L0 c0 u! K- {& j8 L$ r9 K
' O) R& I+ V: y  U
        internal.SaveState( p );4 {: S8 M" [5 y; i# t, b( v" X  P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) h4 V% z. g. v9 ]3 A3 i
) M6 n) D! j" m# u. v( ^& h9 S; Z
        // VRC6- A' d' e* Z/ g! d9 F
        if( exsound_select & 0x01 ) {
- M# b2 N) o4 y4 I) F" H, ]4 J* g                vrc6.SaveState( p );3 ~5 ^8 l( D; U# a0 T- H+ }
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 @# ?3 Y$ i! j; c6 {( c        }' a7 ~- k# ~- m2 ]6 X3 [: ]3 s
        // VRC7 (not support)) H/ O! h1 ]' _$ c! _
        if( exsound_select & 0x02 ) {
/ M. [' |  ?8 f) u: u                vrc7.SaveState( p );
+ q5 [/ @0 D! e( c, t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; p1 ]3 i, I& W$ K* ?9 k        }; I+ N/ ?" f3 l/ O8 S
        // FDS
6 D. `6 o" t$ W1 C6 H        if( exsound_select & 0x04 ) {& @& j" e% n5 B$ C
                fds.SaveState( p );
8 v: r1 i  l" N) A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 X; g% P9 H5 j& m# m" \
        }
, e  B! C. C2 T        // MMC5) u# A, Z- w4 R3 ~
        if( exsound_select & 0x08 ) {3 d+ @$ b4 `( M; j" V9 f
                mmc5.SaveState( p );9 v' _$ h+ v  t) m. w0 c# s* Q  w( u  x
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! M" J" [9 P0 f& R' L        }
0 }- K' T6 Y0 B" `) w        // N106
" j/ F. V, l: S: J/ v        if( exsound_select & 0x10 ) {
0 u8 T: |6 ]! u                n106.SaveState( p );
# y$ `/ y: e9 }$ u, ]                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# S# n+ F, o6 Y9 a0 c6 `4 j; N+ w        }
- k) h2 R: X$ k1 m        // FME7
9 G4 f9 y. @+ j. o0 ~  l9 J        if( exsound_select & 0x20 ) {7 P! \1 L5 r' @! O
                fme7.SaveState( p );. p* ]; b* G4 u- w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% x" i  `! F' l" B        }
7 m% j2 J0 O) z2 @8 L6 d3 _4 ~% G+ d
- T! g0 [, ~! a9 [1 b. L2 C+ d* I1 l#ifdef        _DEBUG; W$ \  q& H) R/ X( |3 z
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );# a% t( s# d6 y1 V: ?4 P: x
#endif
+ u+ f2 Q% k) U6 R7 ^( c}( j( h" V* k; o4 \! r

0 b$ e% B; z5 E" b2 U  ^void        APU::LoadState( LPBYTE p )
2 \$ {, i1 D5 r4 B0 g{7 p: |  l% o. x) a3 M. R* P: w5 e6 X
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡. v4 U6 C. _# ^, c# G+ J
        QueueClear();* f1 C- ~$ @% G( U

% X2 w. L0 B" ~% D: b6 r8 u0 @$ S( i, T        internal.LoadState( p );( F' T. z8 ~, C) U1 {7 X* g3 E0 y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, l. i+ _4 Z- u7 f3 Z/ I7 F# x
* C/ e6 `( ?- \/ n3 X        // VRC6
- W3 Z, o+ a$ Q& o/ y: C. |        if( exsound_select & 0x01 ) {# q, v; c1 T- N1 C
                vrc6.LoadState( p );
+ T4 P  \0 r3 z. C7 E9 E                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" K1 q( r% H2 @' V( Q6 r% O) R6 O# \4 Y
        }: m( u4 J* ?/ k9 K7 z- f! _, R% A
        // VRC7 (not support)
9 K) o/ K( K- `8 F% }6 L        if( exsound_select & 0x02 ) {
- u# t7 |8 p+ }: D                vrc7.LoadState( p );" [5 M- R1 c* j9 `& G. v5 S
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 b/ g( l# v6 }$ {& ]        }9 [! y# y$ C. u+ k" c
        // FDS
2 j+ `0 G" m5 ~) ~& Z- d        if( exsound_select & 0x04 ) {% N; ^- j& q: R+ d  r
                fds.LoadState( p );
4 b1 |5 ~% y$ j4 _" `                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 R* I- U* n2 t# `; N7 ^        }
) q. M, k% k- b! s7 L. A9 I        // MMC59 J5 P1 ]& g1 C
        if( exsound_select & 0x08 ) {
) h) u5 H+ X9 o4 k( c                mmc5.LoadState( p );; p& E: U) S( I) {( z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 x( ?+ b5 I0 k; u' ^* Y1 I; y
        }
+ Y* b+ E% m3 I# a% _        // N1065 Z' Y  r5 D% ?1 L- m- A
        if( exsound_select & 0x10 ) {
. I/ _! K1 |/ _. `: p5 n                n106.LoadState( p );# ^$ l7 j. J% n" ]4 K7 ]# j
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 d. y. i1 n; {/ O5 r. H6 l. r        }- Z& ]4 G6 X/ D4 J$ i
        // FME7
, h9 j# ~/ T8 v  H9 Q* L3 D9 P        if( exsound_select & 0x20 ) {7 B2 {5 B3 E4 K/ R/ K" L
                fme7.LoadState( p );  v. Q, B+ a5 I
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ I2 I" q+ A6 V3 l        }
. _- h0 \/ n* M6 E' O; e}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 Q8 `3 A) ~( K7 b1 \可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. A8 E/ \- o4 `+ K: D, g感激不尽~~

- e/ U3 n4 _" F+ q3 x' X) P恩 我對模擬器不是很有研究,8 M/ R4 v* u( Z! r9 [
雖然要了解源碼內容,可能不是很困難,
1 S2 ~  m5 ?$ ~) ~不過還是要花時間,個人目前蠻忙碌的。6 m, I* y$ ^4 I5 J

8 U( {  z* ~9 Z2 O給你一個朋友的MSN,你可以跟他討論看看,
+ E' G; O& `5 g, J  q" O% n% \0 T他本身是程式設計師,也對FC模擬器很有興趣。, C; E3 }0 F- L  {

" i* L2 P1 Q+ K' g/ i' |  fMSN我就PM到你的信箱了。
" T; ]& z# P: _0 s8 [7 d6 d2 w
8 x& [+ M3 I( d! S# ~希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ! D9 c5 f# t; m6 q# q
呵…… 谢过团长大人~~
, `  a7 \- H2 K- U" y4 J3 t3 k5 ~0 c

* h" e7 e! }* U6 t, k* [! H哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 7 i+ h) q  t2 M6 o$ [0 d3 K
团长的朋友都是神,那团长就是神的boss。

# P/ ~7 k0 r5 K' Q哈 不敢當,我只是個平凡人,5 G8 R8 ~9 J) \* X
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
2 [% X' L3 Y9 l0 M, I% wZYH$ E6 |. n" m/ @
QQ:4147343061 u! [# V) e) E5 ]+ A
Mail:zyh-01@126.com' f* _; I+ Q% P) c0 A, q2 g
% Z! B) t. y5 H# p  @
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 J% I) I; P% y1 g7 }0 o再次对团长大人和悠悠哥的无私帮助表示感谢~~
; j- ]! @0 V! Y5 D) v2 H# @
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-1 05:46 , Processed in 1.092774 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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