EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ O# v9 E3 i; U6 z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. R1 ~( F% [% Z# D$ S8 l7 g这里有相应的模拟器源码,就当送给大侠了~~5 J$ M3 D0 T1 M4 o( y
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 9 K, x6 j8 D7 ^- J& i
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。) U8 t1 X' V6 A6 B0 t* G
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 p$ I) ?( e, `9 [0 X这里有相应的模拟器源码,就当送给大侠 ...

5 o6 N4 b$ u. I; F' c+ g聲音部分(Audoi Process Unit = APU):
% E5 E! k" m9 j3 \& d! |3 l0 g) }.\NES\APU.cpp
" P7 s/ i: y7 h2 j, x' i.\NES\APU.h
+ M9 @8 @: [7 U8 F; N% w7 g& d. @! \

( G) U  `( ~1 r影像處理部份(Picture Processing Unit = PPU):: {7 @. O1 g# N7 u7 w
.\NES\PPU.cpp
  }$ l" V1 q1 {4 r' M.\NES\PPU.h: W. m9 G6 ^: m1 j+ {8 V" _) q

% P4 a1 r; K5 q. Q- }* P7 O# b如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* H+ y5 [# M/ i, _/ Z# \& A/ V1 Z(由于很多专用术语和算法机理都不明白,所以看不大懂……)
* T- T3 `8 c/ y' y+ W4 {8 L//////////////////////////////////////////////////////////////////////////
$ D9 h' C& C: u9 N: N+ K//                                                                      //
3 D, I& r' B5 e2 X0 p& v6 X//      NES APU core                                                    //. R( R# b1 J$ r
//                                                           Norix      //- K& F+ ]3 O) H1 g
//                                               written     2002/06/27 //2 _) k* q! g8 `+ @6 T$ W$ m
//                                               last modify ----/--/-- //  s/ H3 g6 Y- x0 L/ N# D+ n
//////////////////////////////////////////////////////////////////////////
2 H2 F) z! q+ I& i#include "DebugOut.h"
* h+ h4 i' X: J4 H* ^5 q#include "App.h"
  H3 |' q5 n# l$ W1 [3 h#include "Config.h"  ^+ x) z9 Q+ W7 s
! h* D2 K, n& Q, \: k
#include "nes.h"
+ A' B& E' k) E% m5 T$ [#include "mmu.h"
1 @. O& ~& g: C  K5 T3 h" I/ m#include "cpu.h"
" A0 f) y2 W+ U5 l9 t#include "ppu.h"
7 t" C/ t# o( l' A, _' J0 z#include "rom.h"
& b( T# J; ?7 c! L' t: \#include "apu.h"2 ~+ F+ R' G) N9 n$ O4 H
8 H3 p/ K; F8 Q/ _9 z
// Volume adjust) [( G7 F; Y+ ^! y
// Internal sounds& {: c0 x" Y' }- G& ?# ?% n
#define        RECTANGLE_VOL        (0x0F0)
) d% b  ~) o7 R7 V#define        TRIANGLE_VOL        (0x130)! `. e8 y$ B, L' T: x6 v0 \
#define        NOISE_VOL        (0x0C0)2 t5 X) J8 z/ Z% m
#define        DPCM_VOL        (0x0F0): j- D+ H5 _- J6 u! a
// Extra sounds& P6 l# B! S9 }7 i
#define        VRC6_VOL        (0x0F0)
# s! b$ h$ [- G. t3 G#define        VRC7_VOL        (0x130)5 M$ C  Z3 Y, t3 b
#define        FDS_VOL                (0x0F0)
7 U8 o# d$ y' j4 G  P! l#define        MMC5_VOL        (0x0F0)$ D" R7 a+ v, @* P0 P% C! f
#define        N106_VOL        (0x088)$ E5 B- D5 v. u- Y3 g  U4 x
#define        FME7_VOL        (0x130)
" c) _2 _4 N/ z8 \' i4 g- M, u- d* b# I, ]6 `, X: j- l' ^
APU::APU( NES* parent )) Q# Z# R$ s. Q! V6 {" }9 y
{. x  m' L( v2 }
        exsound_select = 0;  y- U+ D8 |/ ?2 N: T& P
  q+ X5 M5 p( Q) Z* {6 f
        nes = parent;' V( V. r1 Z( i
        internal.SetParent( parent );
% N  @, z. q* a5 x
$ z& `9 B! ?" I  }        last_data = last_diff = 0;
5 m0 }5 V, q+ J: J8 T& w! a8 [1 o3 W& a- f
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );# q# Q- y  x% I3 v" n& P
. h4 U6 p/ W1 C4 {- X) y& N+ q$ O
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );; e! V- L# V9 S- j% D; j0 l
        ZEROMEMORY( &queue, sizeof(queue) );
7 u+ h) F; q$ `: u' Z. U& Y' o        ZEROMEMORY( &exqueue, sizeof(exqueue) );  m; ?( A+ O# s0 \
& v7 Z% K% V4 z  S, Z# X
        for( INT i = 0; i < 16; i++ ) {
+ o- I6 b/ }4 H2 l5 J/ J4 P                m_bMute = TRUE;* u9 R8 R7 f$ E# F; |9 F+ P
        }
9 f6 G8 T/ P! Z+ @% C2 B  C. A+ P}
  F! M9 S1 s2 s7 `0 w+ I, D3 n
* E7 Y. i! {+ V3 I' w: Z& ZAPU::~APU()
8 f) v  m" l$ O6 p, d{
7 U( ?- G" J; b# M; o, F}
. y* M1 |7 n2 _  V% F9 z( l* |+ h+ W0 E/ e2 B+ P7 \+ ^) z/ C
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' v# D: V9 J0 L9 \2 p# c8 v; P{( F9 P% {( S& Q0 \
        queue.data[queue.wrptr].time = writetime;
) G) E8 q: Q; a. r7 F        queue.data[queue.wrptr].addr = addr;
, a* w) a& q% `% r+ @        queue.data[queue.wrptr].data = data;
& f( W5 n$ I) f1 {* f6 [* @        queue.wrptr++;& ]* R' s0 r' I/ Y, f) R. ]2 |+ K
        queue.wrptr&=QUEUE_LENGTH-1;
& M) b$ J6 z* ?* H' n, t( C0 S! ~        if( queue.wrptr == queue.rdptr ) {* D/ J$ r/ C# v- K! y+ h
                DEBUGOUT( "queue overflow.\n" );' F: u5 H+ I; V  Q2 q, }4 @9 O& P
        }6 G- [  a0 Z% X, t* S, a, E3 T
}- @3 V" j6 Z3 l0 g( l. M
5 h. J! O. j8 j( z/ K% }5 {
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
2 g7 O( S, p5 l) W{
  l3 p; t% |1 |) ~9 b$ W        if( queue.wrptr == queue.rdptr ) {4 ^6 G+ a* x" m7 e" a5 x' T" \3 p
                return        FALSE;
2 Y  y* O+ }6 q' T% ?' h; Y        }+ J# k3 l" l! |' _6 D8 G# }
        if( queue.data[queue.rdptr].time <= writetime ) {
7 d0 `* @6 F0 q/ h; J% \, B                ret = queue.data[queue.rdptr];+ V/ @+ k* B0 d& f0 J! g1 q
                queue.rdptr++;
1 H& x- i0 x% {) T                queue.rdptr&=QUEUE_LENGTH-1;* R1 n/ N/ v# p
                return        TRUE;" r8 y' o% r+ s* n
        }
' r, J6 V& X; J1 l& T/ y% N        return        FALSE;) i- i7 Q% S0 p" O- N) G: S
}
8 @, m" x  x9 \
5 C! R) E9 P1 G) T* M# evoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ n: R5 J  z* Q* \) x6 Y{
1 C3 S: H6 j5 X! l        exqueue.data[exqueue.wrptr].time = writetime;
+ n6 E2 A$ U5 b1 s        exqueue.data[exqueue.wrptr].addr = addr;8 ~$ y9 P2 E! B3 F/ o% V" q
        exqueue.data[exqueue.wrptr].data = data;
/ t% I  c, U0 Z/ P        exqueue.wrptr++;
7 s- A  m2 r) a9 e/ {        exqueue.wrptr&=QUEUE_LENGTH-1;) K1 ^8 W  n4 g0 P
        if( exqueue.wrptr == exqueue.rdptr ) {( k. x. I# R! o0 s9 T$ r2 h
                DEBUGOUT( "exqueue overflow.\n" );
7 P/ w* P1 m! J; Z9 U/ ?; Y& w* [        }
4 a- o$ c$ e  O0 G6 F; ~2 W$ x  c}& S8 a' F( v7 U- G

/ _+ ^! X2 b9 D/ i$ _  cBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
" o# U% u( T5 N* J# `- |8 l{7 P5 _& Z$ K9 F6 T5 p/ N) m
        if( exqueue.wrptr == exqueue.rdptr ) {
' x" p& @5 G, Q" I3 ^# |9 j                return        FALSE;* O6 E) p8 c# n/ V. b6 Y
        }- h( a/ w# c  b3 F# j8 v  k& D
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
# L' L; L4 A% P; H                ret = exqueue.data[exqueue.rdptr];
/ p) ~9 f& R3 i2 o- f                exqueue.rdptr++;8 v! C1 h1 L, F: O: B3 e5 R
                exqueue.rdptr&=QUEUE_LENGTH-1;; o+ G% [) }$ K$ V# c
                return        TRUE;
, U" L7 \# Y" D# B0 |! b* Y, {        }
+ f7 f! h. U  |6 W! G; \        return        FALSE;
- v! u+ |4 i2 L, @3 |2 N}5 e* k! ]( V6 x% U3 ~
7 e# N, `5 k/ h; O2 E. K" B2 P
void        APU::QueueClear(); Q. Z9 v: U0 r$ w2 W
{. t: w% X# B, [# F  j
        ZEROMEMORY( &queue, sizeof(queue) );7 S$ ]- n9 ^5 _  {  \* G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! S& S  R) q& c, u' T1 G
}+ a) ]4 G3 o0 f, U

2 g4 e6 \3 K! _. n: \+ V% avoid        APU::QueueFlush()4 T! g! C/ v' h. p/ v
{
! |2 ~; ^: l4 g: v        while( queue.wrptr != queue.rdptr ) {
" _; E8 K8 t; j/ a1 }1 K: q                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
' P8 S. o! m- f* g- i; ^                queue.rdptr++;
; H" `6 A3 e3 u! I; D                queue.rdptr&=QUEUE_LENGTH-1;; K- D# p4 v1 p6 S" [6 |* f% |
        }& q" q0 @9 I: a9 r1 p% v/ ?: ~

0 i6 |7 r* W' o* s        while( exqueue.wrptr != exqueue.rdptr ) {
$ X- c+ K3 R# F( V; K8 d                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
' }* R" T4 }( W& `. M/ o2 L9 V                exqueue.rdptr++;
# ]+ }% B0 l( c" Q+ P8 t" `                exqueue.rdptr&=QUEUE_LENGTH-1;
) B0 G: |1 z. b7 V  X2 n0 e        }( o7 v! t  r0 o/ B" |1 e" j# d6 E& t
}. l5 x5 G9 X1 M# g3 [: p/ u. V
+ a$ o1 s6 }: G
void        APU::SoundSetup(). C& D# p) O8 j/ q
{
1 T* A3 y# n( Q6 g        FLOAT        fClock = nes->nescfg->CpuClock;9 C) s; E3 R. g0 _
        INT        nRate = (INT)Config.sound.nRate;
' M% Y: H* W7 V# D5 R        internal.Setup( fClock, nRate );. C2 p, z& m# d# n/ y
        vrc6.Setup( fClock, nRate );6 x; N; }5 g3 I* o
        vrc7.Setup( fClock, nRate );
0 R4 J- m# M$ P, ]5 ^$ s        mmc5.Setup( fClock, nRate );
5 t5 |( n* K) d, ?+ j        fds.Setup ( fClock, nRate );7 H- P" }% L4 b0 q, o* }0 u
        n106.Setup( fClock, nRate );
) H; U9 F2 i, V: r        fme7.Setup( fClock, nRate );
- I9 z* t+ F5 y) J* M8 M* [9 \}
+ R; W; s+ k& A& w5 t1 c/ _" z5 ?1 X% C1 b* H5 `
void        APU::Reset()6 V' M$ H" G6 P, B: R: r# |; d
{
6 H; `0 H4 ]" H        ZEROMEMORY( &queue, sizeof(queue) );
& R# u$ ~9 Z5 i' Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 G* l  W$ d' c0 }! G) A+ g- O; ~
7 M* e' e/ C% U8 w2 o% z7 l
        elapsed_time = 0;  Y& e& T6 n1 e% y- q% T6 v! T. q

0 r/ v( ~7 G8 C+ T( `# u1 E        FLOAT        fClock = nes->nescfg->CpuClock;9 y; G6 J9 u/ G) n) Q
        INT        nRate = (INT)Config.sound.nRate;# I" w; F" @' T- I
        internal.Reset( fClock, nRate );
: d( r+ [; `: ?  y7 X; j% E        vrc6.Reset( fClock, nRate );
0 W; ^' X0 N" |% N1 z1 r- }% N  I        vrc7.Reset( fClock, nRate );. K, v( Z* ~% s. o" |( X: |
        mmc5.Reset( fClock, nRate );
+ i: k) l# J4 t( y" n        fds.Reset ( fClock, nRate );
  {4 d4 B( ?7 C0 E& \5 [) m% A7 `        n106.Reset( fClock, nRate );  I. c4 `, w5 _2 `8 j) r
        fme7.Reset( fClock, nRate );
  r- m6 I" _- h) ^. n2 j3 P0 V9 y# ~
        SoundSetup();
5 }5 C8 y. w% A}
8 p. }3 _% z5 s0 K( I+ B
1 o8 Z% {) D; r4 Y/ A) bvoid        APU::SelectExSound( BYTE data )9 R% \5 W. B# K& W3 @4 s1 m
{0 K) [% T0 Q% e/ e
        exsound_select = data;
( Y% \' d5 T' H7 I$ P}
2 Q% v% m# @$ p6 D$ w6 S
+ r" V: e  A: ]# LBYTE        APU::Read( WORD addr )
/ ]: ?6 B6 a* ^{
# x% l: n+ Z) {' ]* i) g        return        internal.SyncRead( addr );/ J9 g$ w; ?& ]3 N. b
}
. w" Q0 [4 f: M4 [) Z( ~: r2 n6 J% l: @; ]
void        APU::Write( WORD addr, BYTE data ): K4 l6 N# B4 {, ]) x( S
{$ |7 s4 Z) [3 \' [) K
        // $4018偼VirtuaNES屌桳億乕僩% x, g" X. U# t- e! U% `
        if( addr >= 0x4000 && addr <= 0x401F ) {
* s* k+ y# _' j; _6 S) s+ y                internal.SyncWrite( addr, data );
9 P: y9 D1 Y- X9 E% A) l( t                SetQueue( nes->cpu->GetTotalCycles(), addr, data );) h5 O; P$ A" E# l5 ~  R5 }( V
        }
* x9 H$ A+ O$ W9 {& k# x4 t6 E/ x}. L7 W4 [  d7 E7 \4 R- ]5 y

5 Q/ b! G  W; e: `( H. F$ [) \BYTE        APU::ExRead( WORD addr )
3 w; ]/ j" D) J{4 U5 r2 Z% O+ r& Y% z
BYTE        data = 0;0 M5 D! [  r4 t

+ B" ]9 P  h  _+ S        if( exsound_select & 0x10 ) {* h$ x* K' `; R; ^
                if( addr == 0x4800 ) {% e6 a& P- x  s6 Q* ]5 l) p/ F
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );4 O6 ~3 P0 j5 n; x* a) k  F/ X
                }
7 y6 u5 C, G5 g6 Y+ A" d& m5 A        }0 z  a* w3 |, W* |" o
        if( exsound_select & 0x04 ) {4 E+ }9 K& u; Q1 s8 Q
                if( addr >= 0x4040 && addr < 0x4100 ) {+ X2 j' Q) D7 r; h+ a  F5 h
                        data = fds.SyncRead( addr );" Z: l( v" G/ _- W
                }
+ K# H& i, o+ R( m        }
1 B- d9 a$ m& o5 r* s( A6 N        if( exsound_select & 0x08 ) {+ m2 N6 A& D, F' U/ Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ W' B8 ]+ Q: o' R7 c. Q                        data = mmc5.SyncRead( addr );
: A+ ], I4 l7 D8 `$ L+ K                }
: i; k4 P2 Q0 P0 g5 M+ Z        }
2 F# l# D- v7 ~4 m$ k3 ]
& T  t- d1 q6 x" b+ }) U        return        data;4 s, l8 u# K$ s  T7 K% L2 E! X
}6 @+ E. K# m  q% v. |1 _5 j

6 ~: }( v# c* i2 H9 W8 S% F7 V0 ~void        APU::ExWrite( WORD addr, BYTE data )
: e% Q3 x6 W3 l' G{
6 y+ o. \/ s4 K' N" @' r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );# Z$ K; q+ O( u
5 B  y8 d( O$ A3 Y. K; Y, m  P
        if( exsound_select & 0x04 ) {& @, b+ Z0 c  d: [! b+ B4 B  W9 f
                if( addr >= 0x4040 && addr < 0x4100 ) {0 y8 _: C+ j8 a, O% ~1 W, D
                        fds.SyncWrite( addr, data );+ t5 N' p* o1 s5 w" C2 u) s
                }
7 g* [0 a; p/ T. y% }' p/ W        }
1 v9 a7 J4 O2 Y3 f# J* Z
- x3 ~6 R1 R* R3 K! z% {6 P( k! m& c        if( exsound_select & 0x08 ) {+ V6 O) f- G' f' h8 e& V
                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ D8 T. a0 Z" H  N! J9 w/ ~7 V/ i                        mmc5.SyncWrite( addr, data );
% H' Y  G" e& ^2 E9 |/ [+ c                }( p- I' N& e. @7 q9 F
        }
1 U+ P# Z2 n+ u" _! Q2 K# g}8 v( {1 N# R# t1 ]: W8 o
( g: S& _: @5 {; u/ }
void        APU::Sync()+ z' @/ \9 f9 ~: T9 R) n9 c/ n8 G
{6 c: l7 e, {1 W6 o; c
}
& j) g3 ?9 u& b0 F7 w  k0 b, S& V# ^: P+ |9 i% H
void        APU::SyncDPCM( INT cycles )
0 Q6 P- b/ z5 z" T6 ~{
3 ]& s; R# S6 O9 d        internal.Sync( cycles );7 I# w3 N( n( X) i( ?8 `  u
/ T5 s; z2 K; J6 p
        if( exsound_select & 0x04 ) {8 p  v6 y# h- q; |8 X
                fds.Sync( cycles );) A' M% d7 @' \5 s9 Z% k
        }
; Z7 B) P1 R- D7 ~. V. g* Z7 E0 g        if( exsound_select & 0x08 ) {& i1 W. i# B- H
                mmc5.Sync( cycles );9 ^' l2 E  f2 _% w, ~0 s" n
        }
9 j8 P$ ]4 e& h9 N6 J+ v" v( E0 s}
% K) ^% a% [5 B9 Z
  c# z1 A: l  V# E" Hvoid        APU::WriteProcess( WORD addr, BYTE data )
$ M. ~/ M2 q; Y1 J+ ~1 f; d+ t{3 Q5 c. u8 C  l
        // $4018偼VirtuaNES屌桳億乕僩9 J  x& M. S7 [! i% R, r
        if( addr >= 0x4000 && addr <= 0x401F ) {
( y4 n8 D: _; ]9 G* Y6 r2 K) e" L                internal.Write( addr, data );7 J+ a1 f/ [/ U/ n: H" C+ J5 I4 g
        }
  K$ Z" Z4 `0 Z' J}, |: c& V6 ~1 ?) Y
+ B' E' a( a9 S9 H; r
void        APU::WriteExProcess( WORD addr, BYTE data )
+ j& b/ Q0 \5 |. B{" Q: e+ O7 V$ S, i7 }8 f
        if( exsound_select & 0x01 ) {
1 S7 z7 a$ c6 I                vrc6.Write( addr, data );9 `& @8 [: y# M9 Z6 ^
        }0 v: X0 x: w  Q  v
        if( exsound_select & 0x02 ) {- {! f9 l( J0 K6 A7 O
                vrc7.Write( addr, data );+ o( ^, r- R% t! @6 y- E2 G
        }9 n+ T7 I$ |, }+ v4 A7 l. g
        if( exsound_select & 0x04 ) {
+ T; i/ N+ R  ?4 [) I  X                fds.Write( addr, data );- e# _: D! ]/ c& g& S  g, U
        }
2 O4 O- f$ t; X$ s        if( exsound_select & 0x08 ) {, ~# F4 }9 Z1 A( y8 x
                mmc5.Write( addr, data );
- }2 i8 m3 B4 |, }( m        }7 }# ]9 p9 O5 Y4 U2 u+ ?+ H& q
        if( exsound_select & 0x10 ) {
  a* b0 V# ~  g- {% L, U+ m/ Y                if( addr == 0x0000 ) {7 ~4 J# i$ v! E* _9 L. ^7 ]6 y
                        BYTE        dummy = n106.Read( addr );
" l8 M0 V6 Q' q8 o9 o& j$ e0 ?                } else {% W4 ~4 e0 y/ Z7 f3 c) F
                        n106.Write( addr, data );
/ e: _- v' {. k$ g                }
# K0 u. h4 x2 P3 k3 ]        }, c& d4 C5 w+ u) S9 J
        if( exsound_select & 0x20 ) {
  R! P9 y- I1 X' P# I5 s2 O" B                fme7.Write( addr, data );
. r+ n* c7 s5 ?$ r% {; p& k        }# P  M/ b' @$ R. d0 V& A" A& M
}+ q9 S- d4 N# A4 w" i1 E

$ X0 n  \) B+ W* ~5 wvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
3 m/ I) ]* U4 b8 Q$ H3 Z{. u9 {* l9 `0 U6 g' C; O
INT        nBits = Config.sound.nBits;
8 x6 b' W6 e4 HDWORD        dwLength = dwSize / (nBits/8);3 l5 k2 F0 A' a) ^9 I3 e' i
INT        output;, [% G3 b7 W0 `2 y) [' C
QUEUEDATA q;2 D  n% d: r* I! j% v: D3 h% l
DWORD        writetime;
$ x' o% a+ h9 X3 w, U6 R1 p8 b
/ S* R; N) M1 V# u& R; }$ ^LPSHORT        pSoundBuf = m_SoundBuffer;
9 |! o* q. e' @) z. J& SINT        nCcount = 0;% N: k& g6 s/ V3 S! `
, ?; ~( j2 v3 x1 m5 e
INT        nFilterType = Config.sound.nFilterType;
2 U* ~; M( Y+ J" ]0 e
! O+ H+ W  i" Q  V/ B! O- q        if( !Config.sound.bEnable ) {: {, D% H- d4 e' Y4 o& A
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 z) Y# f: S# q* O8 H" _1 O6 i6 e5 @                return;
8 m+ G1 b4 S' O% L$ F        }) p( Q8 h! {! G4 T. X

5 F# U' X# m( N) T- X        // Volume setup
  E+ J1 ^+ Y9 D; l, M        //  0:Master
! i2 ], e; E4 Q9 {- N' J        //  1:Rectangle 1+ ], p0 p( p/ O7 S' B# U
        //  2:Rectangle 2. P, n* `0 D* u+ E: z: e
        //  3:Triangle# x+ N$ Y( A8 a  l* Y
        //  4:Noise
2 U, X, P( w3 g        //  5:DPCM
8 M* M2 E; C5 P: y        //  6:VRC6
; G' E- K8 w4 c  D        //  7:VRC76 R8 @' g. j$ T/ k0 Y
        //  8:FDS0 q0 b3 Z4 \( g
        //  9:MMC5
/ I5 p* C. I2 f- Q4 q! }3 c( \        // 10:N106
2 ~5 F! @% h8 b* ?        // 11:FME7" H; v; U, W. b% V& W* v
        INT        vol[24];
/ k3 q7 @7 x9 W( ?; ~  {9 k  N        BOOL*        bMute = m_bMute;0 G. X; A, s8 p
        SHORT*        nVolume = Config.sound.nVolume;
/ ?2 e4 z9 V( n$ P
3 y! `  B; z( H, S  Q2 p& D        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
: M4 M: E- E7 z/ P1 c  f( k4 X. D2 G. I
        // Internal( h4 Z! s% @2 @' a
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
1 k, r  S( r$ m% Q  i9 S! r        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  k* d4 r5 P- U
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
1 Q, ]* L( _7 Q- B2 |! o3 c+ E5 Y0 F6 I        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 a; _( s/ [- t7 Z/ _; k4 }
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;8 x+ V0 O' I2 [0 _7 B
7 _  f3 o4 Z5 }0 w! q" S0 s: k
        // VRC6
4 |: m4 Y+ D/ {, d        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# @; ^- w) V8 V: P9 ^' w        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& c  A" t2 a+ @% K( {' x+ G        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 }( k, z$ ?# H6 K
, G" h- Z$ P# m! h5 q% X- a        // VRC7
" V7 d. V% c. Z. f, @        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
! D1 F- B! B# l- n1 j- m  s2 k4 w0 o/ S: N
        // FDS' ~% R5 A# A7 A2 W! s/ ]+ C
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;+ d( x/ x7 e- h6 o1 ]
$ H6 ^* T- N1 A! B% Q& C& g6 a2 t
        // MMC5
' @! u! N4 q) b# d: a0 j# s% U        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- R' x+ D% X2 j& N. R1 P/ k! D; t        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: a* V' f; z" a0 `+ m9 x9 q
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" V) f0 w4 \) P3 T1 M# ?7 n& G9 G4 r) E
        // N106
. r: q, i( H: b% w, ~! s% {4 F( e, r9 A2 z        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' j0 C9 ^4 w" K
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% D1 i3 @. ?2 t' R. b$ e. i! C; h7 n
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* h6 r/ p9 I- i4 N) n2 s7 O
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 o. i) T, ?3 y5 m
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' `, b( ~, U. D, ^7 h6 j# g
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 u( t+ x' {; W3 v' ^
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 S0 O, B3 Q) K: ]        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ B* V% y3 P# E

% e/ E9 v/ S8 L, S' w        // FME70 p; Q# V6 K) {& }2 }2 `5 y- v4 b
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 `) w* s$ ^4 @( G+ g4 {        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) A/ M4 N& v- C* I        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. q( y" `4 F8 S' R' O& e

$ f, ^) b0 _$ F3 s//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;. T) ]% X# r+ w+ O$ V! t% Q
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ z  w/ h' Z2 R* J/ f3 O8 f- Q4 |2 s# M3 B; A: n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
( w& L6 h' t/ I3 e3 x        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 P+ G/ K7 R# j2 ?* h. z! o
                QueueFlush();
% |( p3 d3 ~  t        }
" P: Z# [& A0 f! L  g. W
; b2 a; i# ~& S        while( dwLength-- ) {# }/ W, R4 u0 m; G7 N5 q# D9 n
                writetime = (DWORD)elapsed_time;* G; F! `: ?; a4 S3 Z) ~) K: [

9 k) d/ M4 D; u9 d. W/ V: P                while( GetQueue( writetime, q ) ) {
( w" v* F" q8 j! z) ^) F/ N. W" C                        WriteProcess( q.addr, q.data );9 k7 l5 c) _2 h. w5 [1 u( H
                }5 I$ p# X- _1 k6 W- _

/ z9 O, Y* F' ?5 g7 w  Z                while( GetExQueue( writetime, q ) ) {
% C6 \7 X( t( u/ S                        WriteExProcess( q.addr, q.data );/ L8 i9 m8 a/ m2 d( Z- ~
                }
3 i4 y% E2 O0 W) f9 d' ]6 D. w- z0 t6 W5 }
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# A; R& }" W! w7 P# r2 c
                output = 0;( @5 `: k5 _6 E. _$ J, M
                output += internal.Process( 0 )*vol[0];
9 s5 N# r; e& p1 g' |                output += internal.Process( 1 )*vol[1];
2 g0 M: H* @; R! E( A4 x. G                output += internal.Process( 2 )*vol[2];( P( M0 G* m+ D( K6 `" T* ?1 T* ^
                output += internal.Process( 3 )*vol[3];# ~: I2 B; N8 b( I
                output += internal.Process( 4 )*vol[4];
& }! \7 K- u3 U" j
3 p" i$ u# C: R/ g0 E  Y* T9 R                if( exsound_select & 0x01 ) {* i4 D, H3 \( G$ X$ l# E
                        output += vrc6.Process( 0 )*vol[5];
. m  X  `+ Y6 w# c                        output += vrc6.Process( 1 )*vol[6];
) H+ p( A% b9 {1 j# E                        output += vrc6.Process( 2 )*vol[7];% p, M) F" q3 v' [+ e9 H
                }
( h8 {+ s' s) t0 ~' B) I                if( exsound_select & 0x02 ) {0 n7 V7 h- I) T* E8 Z- C$ p" J
                        output += vrc7.Process( 0 )*vol[8];- ~+ B' i3 r0 F- p
                }  C1 y: N- L7 K# S4 S
                if( exsound_select & 0x04 ) {
! s; m: x  x$ c# L) B! e5 S                        output += fds.Process( 0 )*vol[9];8 e: G% O! D9 M1 W
                }! j3 Y, Q, [6 V4 K. M
                if( exsound_select & 0x08 ) {
: z3 q, v0 B- c+ R" _                        output += mmc5.Process( 0 )*vol[10];9 e* i  B/ U* C5 n4 V0 Q! {
                        output += mmc5.Process( 1 )*vol[11];' u* O. J' E- h; L9 g
                        output += mmc5.Process( 2 )*vol[12];
/ E4 U6 F& C$ N* D2 w                }- t: W( w$ u( t" C0 s0 I# s
                if( exsound_select & 0x10 ) {
1 z4 w1 V( `) n, p5 t                        output += n106.Process( 0 )*vol[13];, T$ z8 _) |: G) d
                        output += n106.Process( 1 )*vol[14];
9 F+ g, y) W" J# f) |) J2 `                        output += n106.Process( 2 )*vol[15];
6 i$ ~8 [8 o3 n( L9 x                        output += n106.Process( 3 )*vol[16];! T7 x0 r8 E1 t: l, F4 b
                        output += n106.Process( 4 )*vol[17];
* `1 S" _  c* k8 b9 i. P# q3 e6 O                        output += n106.Process( 5 )*vol[18];& W2 W: C. O* {; P) G/ y
                        output += n106.Process( 6 )*vol[19];
' P# u1 V" Q! l0 M* {# Y+ \; v1 R                        output += n106.Process( 7 )*vol[20];
/ W( z2 K) \1 ^9 n                }
& e' Y8 i' q9 F& y: y* w, J$ A                if( exsound_select & 0x20 ) {/ n- C/ ?6 U6 a6 q
                        fme7.Process( 3 );        // Envelope & Noise8 c9 |! T7 s" |' Y
                        output += fme7.Process( 0 )*vol[21];
  S7 Q% p8 \' P" v6 b* g; \                        output += fme7.Process( 1 )*vol[22];$ ^/ v% u& d; E8 \9 ?
                        output += fme7.Process( 2 )*vol[23];
( D, f8 U& c4 k$ V! h                }
  c; H: b% s7 c+ N7 @; f! }  f# h4 X, o& E. S# ^
                output >>= 8;/ |0 O9 S+ l. \

% E& v7 ]) G+ l% l                if( nFilterType == 1 ) {
) G/ f: k: {7 T& g, H8 Z                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* ^' D+ B& \& H3 V                        output = (lowpass_filter[0]+output)/2;  e8 m5 R2 H8 V3 `" v. w! |4 a$ s
                        lowpass_filter[0] = output;
; C! c/ u* z9 u6 |% D7 y# n9 ~                } else if( nFilterType == 2 ) {
0 R( G* @" @  w. H/ S                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 ~+ G. s0 a! }" A7 b: G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
) I; R8 Q; k: W) p# o                        lowpass_filter[1] = lowpass_filter[0];
8 M2 x, \# }% }5 S5 L! N9 c                        lowpass_filter[0] = output;
9 o- B. c9 X4 |3 {! Z* g' q1 m& n                } else if( nFilterType == 3 ) {
& p$ m( @* [, V: d7 y) v* _                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
( c7 a2 p, Q7 Z+ k$ m4 ?% T) L                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 h' q7 K3 k+ d& Q                        lowpass_filter[2] = lowpass_filter[1];
# w: y: q, E8 U$ s% K) z" V/ P* A                        lowpass_filter[1] = lowpass_filter[0];* }3 j7 ]  F, M8 J! P
                        lowpass_filter[0] = output;0 A; S; u& ?1 B! I5 {2 e
                } else if( nFilterType == 4 ) {
$ f  M- g* |+ }! Q. m6 ]                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); A( A  f  f) q) O; Y4 z8 d- f$ z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;5 z, P* Y2 P0 i* g6 K) u/ r. {
                        lowpass_filter[1] = lowpass_filter[0];3 E% W2 o# T- e1 \: Y" I7 X8 L
                        lowpass_filter[0] = output;- }2 D2 R) ^0 V0 r
                }: {7 l: i/ q; R# g* ^! v
. Q" s7 {& ^6 y$ F" y
#if        0; t" H  q( ~: j4 ]; L/ V
                // DC惉暘偺僇僢僩
& h9 J: b4 F; l! T                {* U/ R2 Z' `" R  `, V  S
                static double ave = 0.0, max=0.0, min=0.0;0 T+ u1 L4 Q' W% U  e
                double delta;
% A2 E& `! G$ K+ U1 R                delta = (max-min)/32768.0;
9 }6 K! G, ~6 e' j                max -= delta;; U# ~4 G: T/ f+ U( M; ~; V
                min += delta;
# W  |4 P2 V2 b: J                if( output > max ) max = output;
( c$ q1 p* O" ]- ]                if( output < min ) min = output;: V: `: d0 t' }
                ave -= ave/1024.0;" E& V1 [+ u6 d* t
                ave += (max+min)/2048.0;' l' s3 O* W/ j" d
                output -= (INT)ave;
4 X( k, k3 m8 G$ Q3 i                }# d' ^1 q6 A% I4 ]  I! M. L/ I
#endif
4 Q& n5 G; G# {9 _  b4 K) g#if        10 t# M, d9 l# i9 U- K0 a
                // DC惉暘偺僇僢僩(HPF TEST)$ N  b2 f% ~6 t
                {, k4 ~5 W$ I7 e! t
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 D7 Z) p! z* s' [& s4 `
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  x4 R" }" g1 B1 X3 e" e                double        cutoff = cutofftemp/(double)Config.sound.nRate;, C# U$ @  }/ @( h; o
                static        double        tmp = 0.0;6 |/ a. }- ?$ t7 |
                double        in, out;5 ?2 c' ?) c* k1 t$ N5 L

4 M, J# N$ V5 a% d  g; B, A% m                in = (double)output;
8 {% y$ W5 a2 X) |' A; N) V                out = (in - tmp);
6 B0 d+ U4 @* k8 l                tmp = tmp + cutoff * out;# s- {. L9 ^" t& p$ Z0 `

" x( q+ m* T/ }: m" @" T7 t5 O0 a                output = (INT)out;2 ^% c; S3 m3 a0 ]6 g+ j; f
                }
/ {8 Q3 `! f3 v7 h: P  ^  x#endif  C, L, w7 U0 u/ n! D0 T  u; v: A
#if        0
: q% f- a3 Q, `                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)! E2 u9 S8 u9 K5 O6 @
                {; L* n# }/ @& s" s9 X2 a
                INT        diff = abs(output-last_data);
: h$ \* a6 ^! z$ O                if( diff > 0x4000 ) {: r7 ^" F- R, F! x8 q
                        output /= 4;
+ [$ N8 n1 q; h, j% r; S& Z                } else
7 T, n  J) m' q/ i3 y+ ~. m# g                if( diff > 0x3000 ) {
- @4 M6 e/ K, g( X. v                        output /= 3;" L* Z* j  z" t3 G& O
                } else
" ~8 ?* @& T: B  j9 V# `                if( diff > 0x2000 ) {) z* k) l; G+ D
                        output /= 2;; a8 I0 |3 X. o: U% a7 j% Z
                }
# T+ `+ t  M8 m  S$ c% d& B" F                last_data = output;( `4 N- N' {, ]" K% ?
                }, y) k! {' G- q5 Y
#endif. U8 M* Y3 K" ?3 q8 |7 v
                // Limit
7 H6 `8 Z3 h- x9 F/ H0 F" p- ~                if( output > 0x7FFF ) {/ R$ U2 J# d- d# U5 Y* Q9 E! g
                        output = 0x7FFF;
* Y- \$ j/ q0 c3 a. D$ b: y1 S8 b8 u' W                } else if( output < -0x8000 ) {
9 W1 d+ K" l* |+ ?$ [0 A                        output = -0x8000;9 T4 O" R: ?1 X! J) t1 N
                }
2 f+ |/ d1 c) Q1 |4 E& D" L8 k$ F, M3 N4 O5 P0 k5 t
                if( nBits != 8 ) {
' Q& d& o* w* C. r: |                        *(SHORT*)lpBuffer = (SHORT)output;
; r7 c& w1 V' U( Q0 q                        lpBuffer += sizeof(SHORT);0 X! y4 E) m6 W/ ~9 ?  P4 {$ l, y
                } else {
6 s  i/ |( V6 l- R( ?. V+ E                        *lpBuffer++ = (output>>8)^0x80;
  e$ w+ M7 l1 L" D9 |                }' w' ^* A; }. D9 b, {' F+ i, |

; j& H) R+ N- u2 P$ T* q8 |; q, c8 q                if( nCcount < 0x0100 )
* i' k' ^! y5 ~8 ]% Y4 y7 K                        pSoundBuf[nCcount++] = (SHORT)output;. Q6 s" f4 e; Y  V# v

6 N3 O* d( r7 m! z% R//                elapsedtime += cycle_rate;0 C# ~, x: M5 v: [
                elapsed_time += cycle_rate;: Y( i" d/ k! F
        }
) }5 i* d% C  b: ]- ?0 _1 `  @/ J5 Y; @4 @/ D0 T& e
#if        14 {* i9 H/ l% m
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
! |, H. S! X  ]7 [6 z* r                elapsed_time = nes->cpu->GetTotalCycles();
1 _- N' C9 x) c% S5 |0 d- O. W9 l; K7 U5 u        }
: g8 C' T1 ^: S8 G        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
; k  m8 h. }9 F                elapsed_time = nes->cpu->GetTotalCycles();
( _* z* \' e5 t" l: h        }& ?' S# w; P" T
#else
' c' P" P* q8 C0 W( x& p) B; a        elapsed_time = nes->cpu->GetTotalCycles();
' U5 d8 v, M& p#endif6 l0 ^% g, M. u+ E4 u3 o/ g
}1 c1 ~, Q" h2 u$ t% L% y4 u
; A- q$ P3 w& R0 i+ P6 J9 ~
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)5 R$ M9 A- O, p4 p4 T5 J+ c
INT        APU::GetChannelFrequency( INT no ), w8 Q) ]% S8 W+ L. U
{
0 u2 |' y& B+ p/ n( I$ p        if( !m_bMute[0] )
/ a5 m/ O. B1 N. Q; n  B, j. ?- A                return        0;
0 k- |$ S# m. [) P+ ^, y( X# R! \! x' E' U8 P0 C, }
        // Internal* I* e! T5 d! |3 z& {, s
        if( no < 5 ) {
( k5 V& C$ M: y& B+ s                return        m_bMute[no+1]?internal.GetFreq( no ):0;
; n: {( Y8 S" j7 ]* y5 u        }5 H" c& W2 m- m! T
        // VRC6" t# w$ [$ r& J$ C* @
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {) w0 C) X& N% F! r# Q% i& C
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
2 B- h0 T7 s) n& B        }
$ Z2 c% t- @( y' M" k. V: b: ]  [        // FDS5 q9 z% Y+ t2 W
        if( (exsound_select & 0x04) && no == 0x300 ) {
8 ?# D$ X- H4 G2 \& K                return        m_bMute[6]?fds.GetFreq( 0 ):0;
2 J+ F1 l+ \% g" y        }2 g. @! G' W7 x3 T
        // MMC5! M- D- V2 ~4 r
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 y; F0 B. J5 q, b& L# D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
5 r+ U' A- D$ Q% k        }: i, H) Q1 ~  F: B
        // N1063 d/ G0 j) B5 |5 \$ n1 y; a% {% n
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 ]' \, I$ _/ D0 U  R                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" T- a8 |2 J0 z) G( z1 g: X        }& Q! W$ Q4 l  k& }0 m* i9 T
        // FME7
7 X, f4 K4 y! c: }/ Y5 x4 l        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
0 T6 Q) T# J% L" h7 P  }                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  b+ ^4 Z/ m5 S- ?( F  R3 ?# O# u        }8 J( |% F( ^$ Z7 ~
        // VRC70 R1 u0 x. c# d. \
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ _8 M' R- K" v1 b                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
3 T( d: h7 h5 z9 T, T+ Z4 J, g        }
8 U  F6 I0 b) d( i8 r$ I        return        0;( o* j7 _% W7 C; @) n  d& D
}
0 {# H" X# C- g- h: r6 r0 ]
  K% N9 G5 h5 U$ |* w; E2 j// State Save/Load
$ L" E; i- o& ?+ `% L0 M  j/ ~: mvoid        APU::SaveState( LPBYTE p )
' N; G$ w7 F) F# @  s6 w{
2 o0 W1 l6 W2 t2 A; P; T" |#ifdef        _DEBUG
  e9 t  O) v, n8 CLPBYTE        pold = p;
; s: T7 n4 z! }9 }: {  G#endif
/ ^/ y1 D/ t+ W6 }  Y; A  x; ?
) i* C/ h2 O& R8 z* b        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
, m: s5 g5 U, K8 a        QueueFlush();5 V  ~/ d5 J+ g' _( y0 _

+ |( U  K! _6 S5 e- S        internal.SaveState( p );) u) ^1 L0 `$ x" `7 l( s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding/ R+ \( ~4 X: E& d
* Z. o$ D. i* f8 Q' W
        // VRC64 M0 q# K  B1 X  L
        if( exsound_select & 0x01 ) {8 U. G' `5 L& g( W
                vrc6.SaveState( p );1 @* F9 n8 m: O$ P& Z9 ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% e* `9 R0 a1 I1 k" D# a        }( N" F% {7 B" m
        // VRC7 (not support)
% ]5 }& C1 h* ~( }" Z        if( exsound_select & 0x02 ) {9 |2 v( q- u/ t1 y% [+ L$ A. [! {
                vrc7.SaveState( p );
7 Q; W2 s3 U5 v* k. n; A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% l- b9 {- _' P. h
        }' i6 N! }( P$ l7 F+ P# d
        // FDS
$ r6 P# b6 l7 F* L        if( exsound_select & 0x04 ) {% `+ L3 `, c8 J" z( Y0 v
                fds.SaveState( p );
: W1 j/ ]% b  Z: U$ Q' s; F  J/ [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- h! s, u1 P* u/ t; c        }. A# Z7 |0 U2 ^5 O: F5 J& r
        // MMC5, Z+ X: g  M6 y/ d
        if( exsound_select & 0x08 ) {1 _, C2 I/ s8 O" }
                mmc5.SaveState( p );+ S, s6 e! t+ `+ I
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 L! N5 ~0 |5 ~6 t; j7 m7 p) Q        }
3 W: z% r& m$ x9 W" p* v- h        // N1063 d- a: X1 Y; b1 a* _
        if( exsound_select & 0x10 ) {$ J. d3 k2 P' h+ P: Z" F" a
                n106.SaveState( p );
+ p& [3 C) T' `9 s                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: D3 ]; \+ k  @
        }
) J. M* ?& W% P1 x' u        // FME72 \: ^& f6 p# H# S
        if( exsound_select & 0x20 ) {
7 v- ~  l) W1 P                fme7.SaveState( p );, v! n9 Z4 {; Z/ i
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: p( x& ~5 c. [% m0 B
        }
7 h8 u: [( z: y- w) P! C/ Y! q, w# t/ Z" m% m4 S( ]" R
#ifdef        _DEBUG
3 I: p2 n; Z+ b' m( LDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! F8 C/ s2 R+ ?: ~3 |#endif5 i4 W+ t, h- }: m# Q
}
9 a  K5 B+ G: g6 `# r/ S. D8 f1 D: T( `6 n/ x
void        APU::LoadState( LPBYTE p )
+ o: u' c4 M1 p5 \8 v{8 r2 R( j9 S' l* O  b
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 L# @$ A( k  `; j- c8 D; ~' W( E
        QueueClear();
. f% W& o/ h5 G# |& }
& S  \0 z% L! g0 _+ m9 \        internal.LoadState( p );1 _# O% D* ^+ q" I1 `
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding2 A" U1 E& l" m4 ]

) A2 E$ n) p8 G, k& U1 _        // VRC6
% C2 G1 o- J' j. f3 ~) |9 i+ {        if( exsound_select & 0x01 ) {) n4 }" }# n' P7 K! ]' ]; G) S
                vrc6.LoadState( p );
6 \% F" P* f4 x5 {' z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 T( K4 w- Y7 i# ]6 A7 T9 s' g
        }' ~( N4 {* k' L6 t: ]
        // VRC7 (not support)0 b0 F( c5 I0 S: G* X! u2 H6 W
        if( exsound_select & 0x02 ) {* Y& o$ p+ {! n6 q6 s9 y+ Q
                vrc7.LoadState( p );* {! V  \$ A2 n) l  c) M/ {
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. H1 z: X" l$ @* A  ^! ~
        }; H) Y, L- x' q& ?2 I
        // FDS
! Z- d' x, {( p* j; T& i        if( exsound_select & 0x04 ) {
2 O- w; I! H. G5 T5 o1 I# ~" I- ^                fds.LoadState( p );
) }2 q/ f1 i8 [& H9 }1 ]+ [9 T7 r# @/ M                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 g, M& f5 V3 i5 c
        }
- b' L& u8 j2 M, d1 f& ?8 B        // MMC5
7 u5 I; j+ r6 H& m" w7 w        if( exsound_select & 0x08 ) {
7 w8 q" M7 x5 [" B+ l. W) K                mmc5.LoadState( p );5 S. h* _8 f4 I% P
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  d$ V$ v/ \; S4 Q# B1 V' U  z        }
+ Y+ y" \6 \1 f5 Q* v3 e+ F        // N106
$ a2 J' I% S" J% ]        if( exsound_select & 0x10 ) {! a. L* t8 m  u$ M
                n106.LoadState( p );
: [. J$ c) X! B( y. ]                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' _& M9 k9 R3 c2 o
        }2 L$ @9 o( b* f2 m3 O
        // FME7! w- v" Y8 J5 O3 D$ _
        if( exsound_select & 0x20 ) {8 t" U& l/ K6 k
                fme7.LoadState( p );
' W: X% a2 l* p. |2 V8 k7 m                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ c) J; q) d9 ^; e! L- l8 A5 q        }4 T  ?1 v5 Z+ E. s; ]
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% f! Y! O. Z0 N& G/ h6 |- r5 ^可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
5 B4 h( Q# v4 m, }* }) m4 m4 c5 F感激不尽~~
' c- q- r9 j8 o" z: S  ?
恩 我對模擬器不是很有研究,7 o) @. q$ S4 d  u
雖然要了解源碼內容,可能不是很困難,
5 Y0 f" |2 n6 Z! I, x8 v不過還是要花時間,個人目前蠻忙碌的。( N$ H3 D3 F- t1 I! m
% o0 c7 p: b  T( I6 B0 W
給你一個朋友的MSN,你可以跟他討論看看,  t7 \$ I! d0 l2 C- O; Q4 w
他本身是程式設計師,也對FC模擬器很有興趣。8 w4 T, Q: S5 f/ H3 t8 u7 K
0 g4 q5 v3 [& o
MSN我就PM到你的信箱了。
; k, A6 f) a4 n1 |8 l7 E# u' `; z3 A. i2 G9 c) T. L
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
8 T* m; }0 ^. \) m/ X呵…… 谢过团长大人~~
- A% c+ W5 H- j8 Q7 j9 p' F

1 b  i$ I. u0 c' d: W; h% Z9 d哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 T9 A4 Z7 A% `, R5 [
团长的朋友都是神,那团长就是神的boss。
* H7 ^7 n  @* v+ f, I( b) y; \# F
哈 不敢當,我只是個平凡人,
+ ]  G/ g, a/ m( J- |要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; x4 p% ]6 R, @3 ^7 FZYH6 |% r/ k5 \$ _$ k; a$ `0 A2 }, c
QQ:414734306/ D1 v( O6 I0 L2 S  U
Mail:zyh-01@126.com
9 b2 B9 X& i& g# `7 k' A& {6 D& {1 A" `* ?( I
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) ?; |! b) l7 B再次对团长大人和悠悠哥的无私帮助表示感谢~~

: k1 \* ^5 l, Y# M  M! S不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-9-18 21:03 , Processed in 1.082031 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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