EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: f1 e3 H' R2 o. R3 Z4 J
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 w9 b  ?& b* r, ^. V5 V6 a
这里有相应的模拟器源码,就当送给大侠了~~& D- s, w% i$ j& v7 n) X
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 t" [! o' f0 K# h  L$ y能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 f* O1 x/ j, [) M, D  q& L楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 X1 }8 S* B# Q& d2 x: b# ?
这里有相应的模拟器源码,就当送给大侠 ...

3 Y* u# P6 [* i# A( l聲音部分(Audoi Process Unit = APU):2 K8 D: J! C& c5 v& h
.\NES\APU.cpp, L: N: T8 Z. D) y& Q
.\NES\APU.h$ P  y( e3 i: k- t$ V
* s3 I) c: G; i5 r- M. O+ H! h, P
" a7 N) m  {4 f
影像處理部份(Picture Processing Unit = PPU):
  X- {: N2 h8 l% v# S+ h  Q/ R% X.\NES\PPU.cpp
$ ~8 B, y% A  Y/ m.\NES\PPU.h( J& z, u2 h5 Z* T& t
* |" W- {- B* x5 \0 A' L" Y. O* J) A
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:8 J- N2 U; B4 k- l; F) S
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) c, W/ b2 b; ~3 ^# }' P" m: u* o! y//////////////////////////////////////////////////////////////////////////
( V8 c. f+ v5 z) S9 [" w5 V9 f//                                                                      //$ _6 \- a6 i& |0 f. N' c
//      NES APU core                                                    //: o8 G5 n3 d/ g) g/ R+ `
//                                                           Norix      //
+ f( f+ O  R4 J; U5 J# l//                                               written     2002/06/27 //& l. j, ]0 n5 U; ]& J& ?
//                                               last modify ----/--/-- //& H1 T4 S; @2 `
//////////////////////////////////////////////////////////////////////////
* ]. H( ]* ^% O  l7 Y3 I3 E#include "DebugOut.h"" ?! _) n' I; h  [4 h
#include "App.h"
6 A# E9 V. B! R9 `0 x#include "Config.h"! w0 C0 [4 Z0 x* p, f1 P( O9 I- u8 l
7 R1 x1 v9 g( W" ^" K
#include "nes.h"
) V  D) N8 V- V- B; |#include "mmu.h"0 _+ |' `. L$ A4 D/ M
#include "cpu.h"
  p) I8 |4 g6 H8 [. r: G! t, _#include "ppu.h"! C( u; H+ O; M- o& v4 `
#include "rom.h", s5 x) v* \+ {& b) V& d& J
#include "apu.h"5 @' k( e- j# G2 I& I, x5 u' y

: h, F; g* _! u7 U: p' G// Volume adjust
/ |# K  y) \( J. m- b& T// Internal sounds- _* a8 e8 n' I2 V: g/ V" D
#define        RECTANGLE_VOL        (0x0F0)7 p: D# N1 D, X) C& D' R, E
#define        TRIANGLE_VOL        (0x130)
5 x4 k1 Z9 D9 h- f#define        NOISE_VOL        (0x0C0)
  ~$ O$ A& M* j2 |9 t6 u#define        DPCM_VOL        (0x0F0)
: I8 _) i& Y2 O2 @5 z# w7 K! E) L# x// Extra sounds  E( h' x- B, w) ~4 S
#define        VRC6_VOL        (0x0F0)
. a1 d. t5 K' k# r9 t7 j#define        VRC7_VOL        (0x130)
4 Z! V" P) L- R9 o+ \#define        FDS_VOL                (0x0F0)
1 n. v6 R, Y# I$ W( H  ~6 e& M0 b#define        MMC5_VOL        (0x0F0)8 L: |& Y9 ^# Z7 U; s# r4 V0 l
#define        N106_VOL        (0x088)0 P) ^& Z! @8 f+ V+ q8 _. y
#define        FME7_VOL        (0x130)* [' s2 I: v. _' S5 T3 w! G
  r6 j; A4 d# y
APU::APU( NES* parent ). Q- V/ e; R% ^3 i. V
{) i8 [# J8 u, `  C8 Y
        exsound_select = 0;7 }4 P7 u0 G$ j$ z( S7 X7 f# e
; q) f' x: z5 Y
        nes = parent;
0 V+ @* o) f0 a8 z1 ?1 g        internal.SetParent( parent );' l4 u$ [5 U- Y1 x/ a2 H* ~
+ }4 l3 ~, S7 O& Y3 Q! L5 D$ l
        last_data = last_diff = 0;
- ?' O- z; Q1 p8 A) d4 T# a0 Z! V  p& a9 O
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );, i2 @3 H2 o* B0 t0 B
/ R4 a' Y& D/ l; u
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );8 m) i( C) D; S5 F6 j' X5 o
        ZEROMEMORY( &queue, sizeof(queue) );
& l0 L0 K# {+ s& w, R2 P        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* w; a; A- w  v0 J" d1 ?7 w( L, I2 T
. r4 c. C! K9 G2 |& k: {+ Z        for( INT i = 0; i < 16; i++ ) {
7 y* `& w0 B5 H1 i9 {8 X% k                m_bMute = TRUE;
" c% i/ W, @6 N        }! ^; X  @9 ^* p0 {, e
}" R' i6 W' w$ C- i% c' A
" g1 R5 h) S8 y6 j' ^. ]/ r
APU::~APU()
5 u7 G! g+ r- r# s# ], @{% z/ `" Z' {2 \% I* _6 Q' N
}
9 B/ Z# G( C! Y. A2 }: Q% P
* A  V2 i% R% H6 C* I, ^void        APU::SetQueue( INT writetime, WORD addr, BYTE data )1 s, J) i  S& N6 {; h, C" e
{
' u0 x% ^$ ?/ x2 f1 J        queue.data[queue.wrptr].time = writetime;' t& g' o$ ?$ R' H( Z1 d9 L6 Z3 \
        queue.data[queue.wrptr].addr = addr;
5 M3 E) i  z) o( s$ @$ |7 e        queue.data[queue.wrptr].data = data;( e  m* Z9 |$ F4 r5 z
        queue.wrptr++;) z& A+ r6 S9 h- V
        queue.wrptr&=QUEUE_LENGTH-1;5 Q! [: E4 K5 m1 K, X
        if( queue.wrptr == queue.rdptr ) {7 Z) F0 L9 }. ~  i, m# l
                DEBUGOUT( "queue overflow.\n" );
! t# A. I5 ?' E        }
! M5 S  p6 |+ x5 h) {0 U+ [}
" u* p2 E& ?) C, S# G) P7 r' z5 H5 u& c: j
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )2 J! a9 J4 K+ j
{
" q/ o9 m1 V/ A0 p        if( queue.wrptr == queue.rdptr ) {
" r/ e7 r" b2 F4 ~- G                return        FALSE;6 D# |, G: R6 ^2 H7 J8 w, v
        }6 P" X* {, N7 B+ i; P
        if( queue.data[queue.rdptr].time <= writetime ) {) \+ c& y6 r# i  e3 }1 r, e8 {7 m
                ret = queue.data[queue.rdptr];
! c7 ^+ m/ d, f' I( S7 N                queue.rdptr++;4 E7 d7 Y0 l; C  B$ N
                queue.rdptr&=QUEUE_LENGTH-1;6 ^3 Z5 X4 v/ f
                return        TRUE;
! c  Z2 }. b2 p. Z        }5 A0 G" R! l2 i
        return        FALSE;
" U9 {4 R1 B) B; L, u: R}
0 W7 d" A4 i! w" D) u- y5 P! h! K1 c# R. v, z( S7 Y  i9 |
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% B! [( g) @; |: W# b$ z
{& u% W0 b0 w, A& g. j9 j
        exqueue.data[exqueue.wrptr].time = writetime;
+ I- O. e; G6 m5 D! Y$ f        exqueue.data[exqueue.wrptr].addr = addr;2 b" g2 F# b' C0 j# p) T$ W
        exqueue.data[exqueue.wrptr].data = data;8 R- P6 A* P: G3 C/ h
        exqueue.wrptr++;
; o# o; }7 j. Y3 h/ ^        exqueue.wrptr&=QUEUE_LENGTH-1;
/ d0 s7 J4 ~5 q( H$ P# k: f        if( exqueue.wrptr == exqueue.rdptr ) {
4 R! ]: A6 i- Z7 K& M. C' e                DEBUGOUT( "exqueue overflow.\n" );" Y3 t. c3 P0 ^6 ~3 P
        }
* H& T: E; @- B, g1 x}
( Q4 \& w: X) d. Q4 U$ S0 @/ K4 ^. J$ z$ A
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
% F+ i! P/ G" S5 s{: X! B! @. B  C- E
        if( exqueue.wrptr == exqueue.rdptr ) {
! h( t: r4 s' x                return        FALSE;3 R! V' {  R& H' i" d0 s) z2 m' a7 s( e. u
        }! ^4 t) C$ T8 w, C" B; Q
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% v% N! ^: V" n2 W$ R2 i
                ret = exqueue.data[exqueue.rdptr];
2 P& j1 U' t( ^                exqueue.rdptr++;
0 T$ Q# g" F7 ?# o" i9 z; I  G3 u                exqueue.rdptr&=QUEUE_LENGTH-1;
2 K$ l0 d8 m, M                return        TRUE;
( ]+ ?% ^$ e3 A7 ^        }8 G/ q9 a8 y" p  {5 D2 i
        return        FALSE;
7 Z6 B# f* F9 E2 t. r}& k# {' W9 v; U- h5 f0 p
" A0 s, G8 V' u2 u
void        APU::QueueClear()3 z# M9 \9 |  ^8 q* M
{  |! w. t7 l, x7 ?7 @% k
        ZEROMEMORY( &queue, sizeof(queue) );
" g5 e$ p$ z+ u" t$ L' B        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( h5 m& ^- @1 Q7 }  m}
' [3 C+ {+ _9 j7 y5 v6 @
9 L& w0 E7 s4 f# T- V; \void        APU::QueueFlush()
6 a1 y$ z/ W- I8 E7 t{8 t7 k; y0 Z" b6 b2 h/ x4 h' A
        while( queue.wrptr != queue.rdptr ) {1 ]. J( l+ h4 w  p, j3 R/ W% g
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ l* W- [0 a  T+ J
                queue.rdptr++;: l, d, a% z# c8 W8 x% p/ ]3 t
                queue.rdptr&=QUEUE_LENGTH-1;
2 y: d- c% J6 C" E+ c2 i# o& E; p  b        }
3 b7 d. c, f+ [( E' x+ X" t
" H9 J% d' P2 X  h( c2 W" A: B  l0 G        while( exqueue.wrptr != exqueue.rdptr ) {2 C* u* s  P* W  N% M" v( E
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" _/ ^0 d# H. d  i3 t, d8 m$ \
                exqueue.rdptr++;+ [3 v: x  {$ x+ n
                exqueue.rdptr&=QUEUE_LENGTH-1;
3 Q: I4 p1 N& Q# j/ I, p* s        }$ [+ i$ q* @+ W/ p$ p3 q$ m" ~/ {
}7 j& a* J/ G- N8 @# I; o
! i9 N+ a7 j( w+ l5 s
void        APU::SoundSetup()
6 ]9 N7 g( R: @# @" ^# c6 I5 z2 }{
  t' @' d4 f& L$ _' ~        FLOAT        fClock = nes->nescfg->CpuClock;1 Q7 T6 G$ g# H& M1 d/ p& O
        INT        nRate = (INT)Config.sound.nRate;7 ^: Y$ I2 O8 F
        internal.Setup( fClock, nRate );! i8 m& N. ^% T, r' [  k
        vrc6.Setup( fClock, nRate );
% S) v* I& ]( \+ n% K& J        vrc7.Setup( fClock, nRate );* k3 I% U: W/ D5 R$ q3 ?* O
        mmc5.Setup( fClock, nRate );1 e/ I4 C' t% u& G4 }- F8 _9 C
        fds.Setup ( fClock, nRate );
# I- P4 V" _; N) g4 A3 s( A        n106.Setup( fClock, nRate );
2 K$ w4 n& N' b        fme7.Setup( fClock, nRate );6 d  o7 a- `, A. O  ^+ i2 I
}& Q7 y, K- o# C$ S- k" d0 Z

  K. _2 D' G# R  s% Z7 B+ Y8 U, ?/ Ivoid        APU::Reset()9 M/ p7 \/ p( u5 a( p4 q
{
9 a8 W) v9 i# ~4 j        ZEROMEMORY( &queue, sizeof(queue) );; f( h" o" h# z1 F. r- o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 L+ o% Q& }  n/ o5 r+ x# g+ Y- F# Z5 a( c5 I
        elapsed_time = 0;: P# b6 U2 B0 P) A0 Z- ?

( O1 w4 Q. T( K" I5 G5 H; ?        FLOAT        fClock = nes->nescfg->CpuClock;
9 J: {# |: R6 T8 Z# {7 i        INT        nRate = (INT)Config.sound.nRate;6 [0 R! z+ a8 f! K1 W6 }. M
        internal.Reset( fClock, nRate );
- o- u: ]; y- y* a, l5 d        vrc6.Reset( fClock, nRate );
; e/ a4 D9 \7 a. v* @+ @& p* u        vrc7.Reset( fClock, nRate );
2 ?' F( i/ O) s+ e5 y        mmc5.Reset( fClock, nRate );
$ Q' j* t4 g/ q6 W$ q3 N5 }        fds.Reset ( fClock, nRate );0 M3 \; K0 M- x9 l' ]
        n106.Reset( fClock, nRate );& W+ b# T2 ^7 H5 P$ F4 R
        fme7.Reset( fClock, nRate );
, _6 k2 e. E  r( b, u6 }% B; i+ y4 X" x
        SoundSetup();
4 h1 K8 ]3 O8 F$ n9 z}
  Q6 N8 k7 A' q2 L  J: W: J' ^+ I% @; v" Z# m
void        APU::SelectExSound( BYTE data )
& [0 F8 C2 A5 W& ^6 Q8 m{9 L9 r" L2 K" R% W8 l( v
        exsound_select = data;, U1 B  q4 p$ u: F
}
' Y+ |; m& |* L: `" T5 D
1 v# e& K0 M: E8 K9 g; z& K) ZBYTE        APU::Read( WORD addr ). h$ e' O7 @) L" d
{7 N5 L4 f0 c) A$ n  |$ p) P% ^
        return        internal.SyncRead( addr );4 d9 ~& S3 g) E+ @7 B! Q
}9 e: k- E- d$ q- W% t+ B
0 ~: L# q; J' L- w* z
void        APU::Write( WORD addr, BYTE data )$ P3 R  l) N' A7 d: K5 Z/ u0 ~
{+ d3 d$ o1 D$ h5 @9 ~
        // $4018偼VirtuaNES屌桳億乕僩9 y% ^1 \# |; p' J6 X
        if( addr >= 0x4000 && addr <= 0x401F ) {/ W2 `) D. ^8 |6 o. M# b- ~
                internal.SyncWrite( addr, data );
5 ]5 K% _4 a+ m$ `. @1 `1 Q, Y. P                SetQueue( nes->cpu->GetTotalCycles(), addr, data );* S4 l. L0 V3 D3 |1 t6 T, s# {
        }
/ h. o  r) |5 {" V% ^}/ p/ }! x1 Z- f. S$ Q. G, r4 E
+ S/ U1 V, W$ D0 M5 h
BYTE        APU::ExRead( WORD addr )) D- i0 P5 {$ F! d$ H3 n5 N$ [- `
{  g5 I/ y8 q1 d" i8 d* U$ v* a7 y
BYTE        data = 0;
: A; E" D1 S5 ]% U
4 M9 R$ X9 ]. A( |+ H        if( exsound_select & 0x10 ) {
* f  b) Z& y" U: Q6 Y) ^+ o                if( addr == 0x4800 ) {, m* @9 W7 @) o5 P- o2 U
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
3 d- |0 I% f3 @                }- g1 L1 }) z! k
        }. d) [3 i5 b! g" I( [8 D
        if( exsound_select & 0x04 ) {- [/ B9 c! l6 h- [* V
                if( addr >= 0x4040 && addr < 0x4100 ) {8 Y6 U! M  F+ C7 q/ u
                        data = fds.SyncRead( addr );
* x: k9 q- K5 @! Q                }
" t6 Y8 {  L. J8 o        }
9 \. B0 E# r3 S; J5 M" ]1 n4 s        if( exsound_select & 0x08 ) {
- X8 J1 T$ b4 b% F& E- o2 b  y                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 S6 I2 a3 Y( k: F9 g. B- F                        data = mmc5.SyncRead( addr );' ^: G! K5 S2 C) X; C9 E* j
                }
7 h. c+ v% q( g$ C1 Y- @        }1 ?" G' r" s& C  O
( o1 A6 r3 ]6 b3 u3 U/ t
        return        data;" D( \% U9 |& y' m
}
7 a9 A2 h2 L: s# {/ G) m! D1 i
' u+ n' F# T- u* g) M. B& q5 Dvoid        APU::ExWrite( WORD addr, BYTE data )
% i6 X" |8 D3 h6 t3 {9 ^{0 L1 I1 P7 _0 }  w6 K- r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" w5 l' N1 a: k4 |# A- E, ^3 z& J; ]! p  ]- x) Z9 ]" H# ?  _& t
        if( exsound_select & 0x04 ) {; U9 G1 T7 z, i9 X; L
                if( addr >= 0x4040 && addr < 0x4100 ) {3 L' K: w: e+ V0 Q0 n
                        fds.SyncWrite( addr, data );
. `6 Y/ |3 u) `/ o/ M9 m                }9 e6 |3 l/ k, m* Z
        }; f4 P0 B% m2 k5 o1 n6 I0 G5 ]
% l! Y. X( ^* [# t, ~
        if( exsound_select & 0x08 ) {
1 r: s9 \4 x5 K5 P  c  w' c' I  D/ l                if( addr >= 0x5000 && addr <= 0x5015 ) {
! d6 J0 J+ j* T" @/ s                        mmc5.SyncWrite( addr, data );. u/ \- T/ l' P0 x! ~& g
                }
3 _6 n# m4 p# G4 z& J9 }        }
& C. o$ O9 ?4 I0 Y- K}, Q% |/ D; L- E" Q# E: a# G
0 f8 ]9 a2 [  t$ _0 x
void        APU::Sync()' W( Q5 L- l* i* ?4 }, E7 A
{/ q3 Z: {7 C- O' S# D$ ^
}
0 Z2 t) D) f4 q) J! l3 b: A( t" M6 G; I3 d$ m3 ]+ C9 w& O
void        APU::SyncDPCM( INT cycles )( k7 ~  z% P% o
{
% O' G4 n8 z4 r; a) H. O6 m$ E0 g        internal.Sync( cycles );
% U& C$ \' q7 E: R% ]% A# \0 E
/ N  N3 \! `/ e- L        if( exsound_select & 0x04 ) {
: p# w: z( |- ?3 @! C                fds.Sync( cycles );
9 g3 N& S& j) w: [        }/ ^' D. B) @9 z# J( V
        if( exsound_select & 0x08 ) {
* u' R0 k3 F' d& d  d4 P                mmc5.Sync( cycles );
. v4 E8 h  ?7 [2 m1 \: v        }+ K% M1 s/ ?" U4 N; k
}
0 r! P3 ^: m& N, Q/ N+ B: R( x  k/ d( x, x2 x: P4 U1 c, E0 R
void        APU::WriteProcess( WORD addr, BYTE data )5 ], R( M6 C& c9 j
{6 r9 F0 }: r4 x
        // $4018偼VirtuaNES屌桳億乕僩
! V/ o$ X4 z# e9 Z: |        if( addr >= 0x4000 && addr <= 0x401F ) {
" f+ q+ e9 \& L# [3 t                internal.Write( addr, data );
  @# P; @" k! ]1 C  u        }6 ]. e( h% k3 N7 p
}( [, s& i% P1 Q7 ?6 }9 D0 t5 Y$ m- u; X
7 n. q& a. N6 F
void        APU::WriteExProcess( WORD addr, BYTE data )
: f2 T2 V% v" @, N+ F' b{+ Z/ H% s) |7 Q
        if( exsound_select & 0x01 ) {( l* r6 ?' b' P/ {/ E( ]! O; U) `1 K
                vrc6.Write( addr, data );
$ i+ V" L" O! b7 V* J. P1 y        }
' K" {1 G- a' M, {+ ]        if( exsound_select & 0x02 ) {! m% w" D, H- s  l0 C2 E% f! a6 F' a! y
                vrc7.Write( addr, data );
* v7 ]2 g. g* s. S! N. p; M        }- F6 n0 ^7 T* {0 S2 v% v8 \* y
        if( exsound_select & 0x04 ) {
6 F$ [; J, v2 W" ~                fds.Write( addr, data );
7 @5 g6 y% E! Y0 E2 t2 [- C        }
9 H% d- B6 ?) W' i6 h1 E9 y$ P/ O        if( exsound_select & 0x08 ) {
  c3 G& x6 o- f+ `9 E0 k                mmc5.Write( addr, data );% A7 S  @- G- N) u
        }3 l6 L, Z# H! k% X
        if( exsound_select & 0x10 ) {. B4 X' o& p' _
                if( addr == 0x0000 ) {
( O0 H6 ^7 {" A2 e1 y0 n                        BYTE        dummy = n106.Read( addr );% p" ]' }# P% e: c9 Q
                } else {3 D$ H' ]# k' w) ]1 O; ^) \4 M. ]. w( s) I
                        n106.Write( addr, data );
, B0 a: I8 n# {                }
; e8 @6 t; c9 r* m0 |# S        }
5 [+ G) k5 T' j) T0 v/ F        if( exsound_select & 0x20 ) {
) M5 A+ N8 I/ O! ~0 P9 `4 }! R0 g                fme7.Write( addr, data );2 n/ V: d' H- O3 Q+ C" X
        }
1 I& V3 w+ i. e}
! r: i; X/ L5 n# p, k8 H% z
  e# R/ u$ U6 zvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). _* v& [. y& s4 z: _
{- ^1 t4 O' a, W2 `) m; V
INT        nBits = Config.sound.nBits;
( B3 b9 P, @7 a% T+ }DWORD        dwLength = dwSize / (nBits/8);8 I) ?+ _6 _/ Q- M6 A" l
INT        output;
* Q2 a. u7 l+ k/ E  J7 }QUEUEDATA q;
( M6 b: E% L9 c7 T/ IDWORD        writetime;3 C* }! D3 F1 [: {5 Z7 s

6 A( _$ z# {" D9 m. JLPSHORT        pSoundBuf = m_SoundBuffer;4 V9 J( S5 ~0 }6 }" H
INT        nCcount = 0;
" _6 N+ k$ d. _1 Q, ^! U. h
% Y/ q% o. c1 Z8 V9 _" ]. wINT        nFilterType = Config.sound.nFilterType;
! i0 @) Y0 i' X9 k; |- H2 ?) w7 s, s3 V; a3 D
        if( !Config.sound.bEnable ) {
4 n6 l% s- x, d4 d6 r. T: N                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
- Y0 g, K: G6 V, L8 @, y                return;
* D0 S% j# n! V; O        }( o8 S) p' F# E% ^. \( H' R

9 q3 a( V4 h9 h! K9 o0 `* j        // Volume setup
% t' n0 l7 t. O        //  0:Master
, n& O* g6 W+ u        //  1:Rectangle 1  F! L! g9 h: M- p' ?
        //  2:Rectangle 2$ f  d  n. d) e" B; _
        //  3:Triangle4 s0 W; v/ F; _
        //  4:Noise
( U# N* J! w0 f2 o1 l        //  5:DPCM
8 N% u$ a5 X$ C% c, f& s8 r        //  6:VRC6
- Q4 G, w4 S- ]! |+ s        //  7:VRC7
1 k2 C/ W) E7 {        //  8:FDS
' h. B  M) g# j5 l  Q0 e        //  9:MMC57 Q0 t6 [6 f- V* {4 D0 F  k: o- @
        // 10:N106
, n- L  \4 i$ X- j" q3 w! R3 F6 F        // 11:FME7
% m3 U+ ^, Q0 o5 P: S; R! [& W4 W* [        INT        vol[24];
9 ~0 f  p1 N( z2 Q  w/ l4 U        BOOL*        bMute = m_bMute;
2 |3 L' }% a* _" d" [. ?4 k        SHORT*        nVolume = Config.sound.nVolume;1 I# O$ }2 ?% @* k# k
8 x  Z; B& H' \9 `
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
8 ~5 {6 h: C/ h( W" M7 w/ h3 ]2 I7 p- N& e
        // Internal
9 C! C3 X) ^& Y- R$ B        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( q+ Z$ k7 W) j  K, C. H* I% L
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
- S$ E( @! K( E  W+ r        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
% u  S: h- b0 D: t  ^% @        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;$ i4 I) Z# Z+ R2 q2 [( N  l" y! C2 u
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, n% R. A3 b$ z  G8 j5 q

2 x* ]& Q& B: O) t% m: H        // VRC6
1 [. ^% B. s, H" z4 v) {1 d& n        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ {; [! U) H  j! [9 ~
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% `0 l6 i+ B  @" t) I+ ~% T
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ [( e8 I9 G2 T0 _
% }2 l& L0 d$ `: L4 ?. _        // VRC77 C$ c6 m7 E$ ~( I. t6 d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
6 G0 X) G9 S6 _. V1 q2 X! |* A) h$ C$ S, [0 Q0 }
        // FDS
5 _$ U8 b. J: e2 X        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
8 S: V: s8 Y$ L" J) S: Q4 L9 r5 W, p1 M- w! L1 c/ ]
        // MMC5
4 ~# B) q0 T! F- Q8 Q) g+ W        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 X/ s. N( A& u5 [8 s! a        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 @5 b% r4 b3 H: \" l# f. r8 t, @        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 t% Y" i' B6 H1 K* I
  S# V" o4 b, `5 z+ p* {5 u        // N106+ \) Q* e  e& z+ y$ M/ y# C
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& Q; `* X5 v3 p        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ w* K9 q$ \( ], s5 C& _4 D- {
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* g& r0 k0 E. I        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! t+ B- j( l3 }1 y3 V        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- @4 y5 \* [8 a/ o% r
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& Z# W' J; b% \/ ]/ z9 x4 Z2 b        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- l: ?7 f$ ]- ^+ Y" B( z( n) ]        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 s& e/ H" {% y. y: E1 {. ~
$ n) ?* |# M* d5 @+ j
        // FME7: n; X7 I6 I+ j
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 y" t, n! C. P: m& O7 p        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! x. f# M1 ?- @; y. J( A' |; c
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ G% ^+ o) J, ^+ F( y$ t% M( a8 a9 m0 s7 T( f! N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;  Y1 y. g0 [8 b
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;" S/ }9 [8 \5 S' k3 Y

' _7 y* O' ~/ V, H1 ~  c; r' s        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟2 r; h, e  G) B* f
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
/ P& m7 R, p; B) N, F7 Z                QueueFlush();
1 k& g7 I0 s( f- Y7 _0 h: u        }
: ~8 G/ M9 L7 t; Q) v' R2 F
7 B* r) J; s! \, _8 G  g. q        while( dwLength-- ) {% M/ D/ H1 c, z( d8 Q
                writetime = (DWORD)elapsed_time;) e( w  y2 T' b1 }: ^

, {' [: @* A! s$ F                while( GetQueue( writetime, q ) ) {
( [  I5 D! L1 A$ ~. d                        WriteProcess( q.addr, q.data );
$ |, u) T1 S3 c/ h/ h                }. r( J1 U; `4 b/ ]- q& @  P+ z
$ T( i* h1 K# h: Z) h* T2 g' d8 m* `. \) I
                while( GetExQueue( writetime, q ) ) {
! ]7 C* ^' ?( v# o  J3 P                        WriteExProcess( q.addr, q.data );, X! P1 C" [2 s9 u( _0 h: V( s" J
                }  C! n: E$ T. {9 Y, r/ U
' t' i2 ], O& a* b
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7( e4 J1 u2 B- ]2 ]
                output = 0;
2 r7 c/ g# u" N" l) R                output += internal.Process( 0 )*vol[0];2 \# d% I2 y* P! k
                output += internal.Process( 1 )*vol[1];: `2 X, m9 k/ s. ?8 {( d
                output += internal.Process( 2 )*vol[2];
1 y6 b: b; W3 A4 W/ ?* p' F9 p) y6 C                output += internal.Process( 3 )*vol[3];
3 ?% i& n6 d8 o, S: W1 H                output += internal.Process( 4 )*vol[4];7 ?# h0 _7 o% U% K$ k' }
- }; u# T5 \# T7 I
                if( exsound_select & 0x01 ) {
# i# o+ U8 K: `% @" s                        output += vrc6.Process( 0 )*vol[5];
) V3 Z1 X. q( X! l( F                        output += vrc6.Process( 1 )*vol[6];5 l9 K' P& [+ m
                        output += vrc6.Process( 2 )*vol[7];+ r; R2 Q: [3 d: t
                }
- T1 L% q! K. Q, H2 {6 g% _                if( exsound_select & 0x02 ) {/ e9 h* V: n/ a4 R
                        output += vrc7.Process( 0 )*vol[8];$ V+ v1 b* x" u0 V, e7 ?  c
                }2 |0 F; U, R/ l4 v
                if( exsound_select & 0x04 ) {
# i- J" @; W2 D# F3 S                        output += fds.Process( 0 )*vol[9];
3 g* w" H! J* Y5 w( v+ }                }, X. W! N: o& I- H  e+ `
                if( exsound_select & 0x08 ) {
0 a9 x; m" Z4 f( g* d7 y                        output += mmc5.Process( 0 )*vol[10];
9 q( l+ K5 @: s3 ]6 i- J                        output += mmc5.Process( 1 )*vol[11];
4 z! n9 I5 P7 V) r; x                        output += mmc5.Process( 2 )*vol[12];
# W  ?" L5 \" I# c0 u9 m                }& s; A: H/ `6 Q- U( K: w
                if( exsound_select & 0x10 ) {4 N! E' ^0 M7 f( Q1 h# R
                        output += n106.Process( 0 )*vol[13];2 p* y' K3 K! T5 C% g( ], I" d
                        output += n106.Process( 1 )*vol[14];1 M  o! D+ q$ M4 P8 B* A4 E
                        output += n106.Process( 2 )*vol[15];/ H5 F7 K0 K$ ]- D
                        output += n106.Process( 3 )*vol[16];$ ~% z; O, C. x  N! M
                        output += n106.Process( 4 )*vol[17];, a" s9 K( A+ ]7 _
                        output += n106.Process( 5 )*vol[18];( r1 P; L( ]) E+ \+ k0 ?  l8 f& O1 N
                        output += n106.Process( 6 )*vol[19];2 L( Y% e( j5 _7 F7 V
                        output += n106.Process( 7 )*vol[20];
+ z' O3 H9 ~- X1 d+ T3 \                }
& U' e; K/ F4 U                if( exsound_select & 0x20 ) {( M" U+ g3 B0 i" s( j  a0 R, g
                        fme7.Process( 3 );        // Envelope & Noise
2 r9 M8 F0 h3 M: ^) c                        output += fme7.Process( 0 )*vol[21];
& E# H' @, l* ~* C/ w/ j( J! b! m                        output += fme7.Process( 1 )*vol[22];
1 _6 E5 R" ~7 `7 F                        output += fme7.Process( 2 )*vol[23];! H9 I, @2 e( X$ l5 X$ x
                }
$ O: M1 Y0 q8 [. ]2 K: T6 _" f& p  R0 A  o; L) G* D9 ?
                output >>= 8;
$ a; V$ x, n9 u
  ?$ f0 @0 I2 i, y. a! n$ c! S/ t                if( nFilterType == 1 ) {& n9 u; h& O, b5 c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
) @; v( p+ a# G' q3 Q) F& C% x# F                        output = (lowpass_filter[0]+output)/2;
9 K3 s' v+ X; R8 n( O! s  X% }5 u                        lowpass_filter[0] = output;
9 b# ?4 b" n: o2 D3 \0 Y6 h                } else if( nFilterType == 2 ) {
* I$ e8 x% T. }1 ?+ y                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
# A/ w; n2 L' G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; _& {. g4 o% E* ]' }" l! b                        lowpass_filter[1] = lowpass_filter[0];% y# W, c; h3 J9 @' e0 x4 }
                        lowpass_filter[0] = output;2 H# O6 a& f+ W/ F6 G
                } else if( nFilterType == 3 ) {
) ?$ O8 C: R6 j$ ~                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)9 Q% m( U9 Z9 \
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 S8 }& ^( \. @0 b% [                        lowpass_filter[2] = lowpass_filter[1];
+ M& ?( {; i; b) w) B                        lowpass_filter[1] = lowpass_filter[0];+ J  ~" s9 U7 C
                        lowpass_filter[0] = output;" `* y: ~# E9 y2 N6 f
                } else if( nFilterType == 4 ) {
. a/ }% e/ F2 s, L0 ^$ {                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ a9 K" {+ @0 U1 }8 T/ k& k                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 r- M0 I# k; [0 A2 o8 _( r' q
                        lowpass_filter[1] = lowpass_filter[0];7 g! ~+ b/ d$ {9 ^2 x0 W8 \7 v2 n
                        lowpass_filter[0] = output;% y  S1 F0 |3 [6 Y4 p
                }+ a5 G  _% S1 O
# ?3 G6 M3 p- }
#if        0! o9 E3 |# f5 ^, a$ Y8 p. h
                // DC惉暘偺僇僢僩
$ X; Q# S, ?6 u. D: y* l2 J% j3 b                {
2 {3 X! m' `( y                static double ave = 0.0, max=0.0, min=0.0;: A" Y7 }$ y; {' |9 Y
                double delta;1 D) h" P! V+ a+ R" `+ Z
                delta = (max-min)/32768.0;, ?( t6 J2 L* A6 g- T$ B
                max -= delta;& K! p% `4 m+ {( A. f" i- i( N
                min += delta;( d4 Y5 r, F" R$ x+ B
                if( output > max ) max = output;
2 N! M1 x( G4 }& K  z) @                if( output < min ) min = output;. b0 }6 ~, U' t. V' o% `
                ave -= ave/1024.0;& a' H7 J8 p6 F* Y/ r
                ave += (max+min)/2048.0;7 a) f3 I" ?5 x
                output -= (INT)ave;- x6 W0 \# D. Q8 u
                }8 _& B9 T* h7 |( J8 x! s- M
#endif
2 h: k1 w1 F- D3 W#if        16 g1 Y; g/ R5 d% i1 v
                // DC惉暘偺僇僢僩(HPF TEST); y3 X* m& e2 }- s/ A1 {
                {; H" j% F6 I3 i) ?1 J* p; C
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" B# D) V6 h, H: a$ K2 s                static        double        cutofftemp = (2.0*3.141592653579*40.0);% K. G8 W* M, f- p; q* e$ [
                double        cutoff = cutofftemp/(double)Config.sound.nRate;  }6 `/ h' U" H2 i* ?9 @' Y
                static        double        tmp = 0.0;8 g' E& o8 N& T% R% M: M
                double        in, out;
. T$ S; F1 v: t- W2 ?- Y6 D$ X% R1 A2 ?  @" J
                in = (double)output;
: g# c" v3 r# _# u# Q9 q                out = (in - tmp);
( J- t0 [# s1 [                tmp = tmp + cutoff * out;) d9 z1 u$ [" Q

6 M7 l- o$ f6 X* s                output = (INT)out;
' _5 m7 K- K* @0 P% O6 a  R3 ~) {4 g                }
* u& Z8 S+ o2 }$ i9 ~#endif- G  A2 ^/ P, _& k( z) }( K) m
#if        00 U% m2 o: J- {* ?3 Z3 G: K" Q( {
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)8 o6 t3 d; Q, S+ j# |4 J7 y8 B
                {7 q/ v) g% Y: h
                INT        diff = abs(output-last_data);9 H; s4 N: e# Y: ~
                if( diff > 0x4000 ) {
  t( F8 m. S1 g4 ^$ T& H                        output /= 4;
7 K& P# U' b, d8 z- X, y+ u                } else ' U* [3 D, L0 B- r! b7 b5 u
                if( diff > 0x3000 ) {4 I3 c6 y/ X: F( W6 q
                        output /= 3;( A* |" ]4 g9 [, W# [
                } else5 U% `, z; q6 U# ~, ], F
                if( diff > 0x2000 ) {& t3 ^3 n( K0 _/ ]
                        output /= 2;" s) U0 R* A/ V
                }5 F1 L- ]) o. ?' E) G' K
                last_data = output;
2 l" H) i1 n& m) ?$ ^! h                }
; H, M- r2 h1 W#endif* }) S8 D( b# b- N4 r
                // Limit
" q; q) M4 I) w% _/ e$ i0 l                if( output > 0x7FFF ) {- C+ C2 F6 w1 {; ^. G
                        output = 0x7FFF;! }# C; x& o% J
                } else if( output < -0x8000 ) {
; M) {- N3 v4 N                        output = -0x8000;" Y! P; t+ |. i, f) }; k5 f0 {, q
                }
9 s. m0 ]2 _9 Y0 ]
- c8 ?+ \$ E6 |6 ?$ f                if( nBits != 8 ) {
; I: U/ d! s9 N: r) w                        *(SHORT*)lpBuffer = (SHORT)output;
7 H, _$ \3 A. N5 `                        lpBuffer += sizeof(SHORT);
! L: u% h  Z9 a                } else {
$ O& d1 a6 W4 o' {: Y6 f/ h% X3 ?                        *lpBuffer++ = (output>>8)^0x80;. D  x' K; f$ S
                }( m, V( C  O+ |+ W

3 L6 W+ O9 G* @3 t/ O# P: W9 B" q                if( nCcount < 0x0100 )
0 V  Z6 V) L3 N# S1 X* U                        pSoundBuf[nCcount++] = (SHORT)output;5 T4 f/ z/ W* d  j
# v8 a+ V: O) @8 a# E, l  V! A
//                elapsedtime += cycle_rate;$ j1 }+ T* q$ s- b
                elapsed_time += cycle_rate;
" B4 s. ~/ L, p5 e2 B7 {2 e) p) X        }
2 k# G+ W; q$ x) Z& r+ d4 y
  H- ?+ c' p/ P3 e2 h8 L& x9 w#if        1# `6 H% S1 ?& K5 Q
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 c$ x/ Q' }0 Q' L                elapsed_time = nes->cpu->GetTotalCycles();) ~5 L' g" N# y0 P# L
        }
* L* }" C$ i6 Z, j$ p+ f$ E. p        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ G6 r# a8 E: z8 U
                elapsed_time = nes->cpu->GetTotalCycles();
* U) }" n0 H. g+ V$ \        }
3 q8 f3 `) R- L8 \/ M- S; z#else
6 j3 @3 t/ g( m1 T8 F; [! Z        elapsed_time = nes->cpu->GetTotalCycles();3 ~3 I8 T( a$ M' x- C( l0 A
#endif0 M1 H$ x' x! i- N2 [7 y
}( O( A, ^* e, p, p7 n; v7 E) A

% ^& T7 S8 M% }7 B/ B0 y  s// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: `8 ^: D! b/ y6 }. HINT        APU::GetChannelFrequency( INT no )
' r' g3 T/ g4 n6 p) X" G6 O{
3 [" S" C: _) B6 ]  ~9 _        if( !m_bMute[0] )
- s/ O' v8 l' o1 F3 Q; O- J1 a                return        0;
( ]+ j& y8 F! F8 \& Z0 E8 x$ e2 h; [6 b' {4 w3 w
        // Internal4 \' n1 n+ e7 {8 V  Q0 f  t
        if( no < 5 ) {- U8 t. c8 b: }# P/ C- E* @
                return        m_bMute[no+1]?internal.GetFreq( no ):0;0 E- I1 ]( e; N& ?3 o
        }8 g: p/ F- D6 X' ]( t. y7 ?/ l) g. C
        // VRC6
) D, `$ E: q! E$ N+ K        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ {5 x" s. R+ o) y& k5 @8 t
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# `4 f+ i0 K& p& L. {0 Z* ^
        }; ^3 Z+ ^1 q1 E, y4 L" V0 ^
        // FDS0 a9 x/ I% r* d
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ }; E$ S, U8 O$ K' ~$ W                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: M& w4 ~- X, r  x        }# ^" g3 @/ D" d( W/ f
        // MMC5
, ~5 K- g5 d% l- D' d/ W/ x        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {6 V( U( |4 w) F3 Z
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;: A! \* N. y( F
        }
' M# \: @" }6 `! _3 x( D; X8 c        // N106$ s* }4 j4 g% s- \; G% H& B$ b
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {2 Q* Z5 z, S4 ?4 N
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ ]5 q% e# W. Q2 l# B
        }
% {. S' a0 _( D- u# h& y. _        // FME7
$ Y- U0 s5 i0 X3 b2 j$ _        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {& l" u# F8 Z4 _& H/ f, Q: I
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
, S  d4 g8 `% ~" A6 y        }
0 w; U- k& A) q* k        // VRC7: f; M! I. ^# q( B% i) s% r' ^
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {0 ^5 _, Y: n/ U' H, D
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. Z8 L% \8 V8 _
        }
0 P0 N; R. M9 [        return        0;
; K1 _0 ^# G! [: o4 ?2 T1 g9 T}' F: N$ _* f! t& X/ r9 v/ A1 B
. h& }" }+ i) L, m
// State Save/Load
, i* g$ w$ w- K: N$ ?void        APU::SaveState( LPBYTE p )$ I# b  y3 ], h+ y: V
{+ h% n6 y6 i7 V* M, D' \9 b  \+ L3 `
#ifdef        _DEBUG
9 O* n5 \; i% }) [/ oLPBYTE        pold = p;% Q7 N' r& V, |" p% ?; o
#endif: Z! ^# D4 n# Z  [. {0 r9 Y5 I" S

( T6 z) A3 ?! n4 F6 N        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; n- L8 A0 q/ _% T# Q* t% R; _
        QueueFlush();  P5 w) [$ J2 M* k4 N

2 i, \/ S* u8 X2 v        internal.SaveState( p );
  H& a3 Y8 e' r0 l* s        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( R* ?; m( R* f# v
' a+ E/ m9 @8 @* ]+ Z2 A$ g! y' F        // VRC6& R* F  z# I, d" F$ Z8 G2 O
        if( exsound_select & 0x01 ) {0 Q  f( m5 C, Y6 J8 H
                vrc6.SaveState( p );
+ [* v' P9 u0 q( t                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! o) q6 Q, m- _- y        }
, r# Y# {! q, w* C        // VRC7 (not support)
8 J5 g& E! G8 j5 O( @        if( exsound_select & 0x02 ) {
7 k: W( ~3 W, v4 w  ^/ E$ n$ \                vrc7.SaveState( p );
( ]; b3 t( r% G9 Y3 z/ X9 K                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
5 m/ q( C; q3 b  A6 ^7 q        }
2 e. v, |: A. J  R" H5 _+ K0 n9 C        // FDS' n* j2 {4 C. ^% i6 B3 S8 P) J
        if( exsound_select & 0x04 ) {! [3 b2 \. O- R4 f1 {
                fds.SaveState( p );
2 e; u  H4 H  {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# z' p1 d$ g% Y9 X6 m        }: C8 k: y5 R3 e9 d0 }
        // MMC5
9 C: R: e6 Y% t- L: U+ S        if( exsound_select & 0x08 ) {* y" t( W: [4 r9 S* x
                mmc5.SaveState( p );
' ]/ f' q* f4 I9 w9 Y* x/ G3 ^" Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 c6 ~2 n! J: _; \' Q% x5 h
        }
" Z1 d7 q8 @2 T- e9 f        // N106
" Y% m7 Z9 s0 T* j4 O" S        if( exsound_select & 0x10 ) {
; k9 `8 _4 _0 \( _                n106.SaveState( p );
2 A6 ^  R1 G2 P7 F( i                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 k4 z7 X4 d% l" p) B
        }
, ~6 W" B) H, O" V' r        // FME7  _+ e5 U! x! @" q
        if( exsound_select & 0x20 ) {7 V7 u- k5 s* y+ h. Y+ Y1 h0 V
                fme7.SaveState( p );: k9 y, j' h8 P4 ]" p! k+ P& P
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding( K3 D9 a$ m: \% r4 j; U6 s; O; y/ [5 @
        }2 h' [6 ~) N! ]: t

! _. X6 i  n0 w* V" [) b#ifdef        _DEBUG
& S" X# E2 Q( F' aDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 j; Z5 y$ c8 Z6 `: S# @
#endif% W! |/ H8 h$ \  l& \
}6 I$ ^, \: y7 F3 Y

3 `" N, f+ H8 e7 a9 mvoid        APU::LoadState( LPBYTE p )
: t; X6 R0 ^- Y: Z/ G8 L6 s' f{
  o, ]- w- R# x8 j$ O% e) g) e        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 e2 ~% r+ U) c% J        QueueClear();
( x  S% h2 a) ]4 c0 G1 |/ t- [4 _7 E1 {0 p  d4 T& C
        internal.LoadState( p );
$ W/ E# Y/ x5 q8 J1 _1 g' G. v: y# m        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 V+ }- A* M; b! J9 O1 i

0 K% L4 j/ A- o        // VRC6
0 ^0 C! F$ {2 |; q$ V8 W* W        if( exsound_select & 0x01 ) {
2 h8 f: G& E6 u" V# O3 c                vrc6.LoadState( p );  A. Q" X* c( [  s. X2 c# g7 x' [
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 m2 m' g; [* ?8 l
        }6 H2 D. Q. \/ Y* R
        // VRC7 (not support)5 L- _6 t, q! i9 H
        if( exsound_select & 0x02 ) {
  e" x; W5 @7 V) g( c) x4 N+ T                vrc7.LoadState( p );: J" g7 H" k  U9 M: N! j
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. f; Z0 a1 y3 k6 ^$ z" D        }
6 L  B6 [" t  A* B2 o% r        // FDS+ ]* J: U' a1 l! t7 g1 q+ d1 i
        if( exsound_select & 0x04 ) {0 a0 {+ U5 r- ?' u
                fds.LoadState( p );' V( J9 n& }1 Z0 }* A$ P, [/ y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 v# u! {4 A% F2 E/ z2 r7 }
        }
! I: J9 q. Z; L2 u  k1 U        // MMC5
) N3 N9 p) J. \1 B        if( exsound_select & 0x08 ) {
/ B. b9 \+ j' [% |: A                mmc5.LoadState( p );0 |' J6 B9 N7 s, R; V6 c" W5 b
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 M+ v1 Z, d- U8 g+ b0 K5 ~
        }/ O8 O% q; u( {+ Y
        // N106
8 q" y& e- L7 V$ F2 {9 @! M        if( exsound_select & 0x10 ) {
# s8 t# J: P" H; P- Q                n106.LoadState( p );
& g$ p6 T6 P9 O# c6 y; J( X! ]" D4 {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# A$ h6 L9 j0 T" ?' G4 T6 t* P
        }
; ^3 x! |! i' l0 X! _1 ~/ ?        // FME79 {4 z$ Y) g$ S. ]
        if( exsound_select & 0x20 ) {
0 x& C2 L* g2 _                fme7.LoadState( p );  c* c3 E) j% P3 W$ _( z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ ~+ }, h$ X( |; |6 G( w        }
4 C/ t  U9 q, L5 O}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
  u9 I( a' i+ t& g, E" {/ }可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. j. w- v- `% U9 F7 D0 W1 O感激不尽~~

* `. s& O7 A" x4 Z恩 我對模擬器不是很有研究,9 J+ `; L, K, P
雖然要了解源碼內容,可能不是很困難,
+ {* x7 }- C: D1 s. I不過還是要花時間,個人目前蠻忙碌的。
0 U5 \8 @/ b6 \' `) U9 s) D1 H* t5 _
給你一個朋友的MSN,你可以跟他討論看看,! K# ]  y3 p2 m  o
他本身是程式設計師,也對FC模擬器很有興趣。
$ M! t( C( e0 S/ F+ q6 O! Q# R( w4 Z8 [
; ^' c/ J* k6 ~0 Z$ N8 ?7 uMSN我就PM到你的信箱了。
* B  q1 d. Q& {2 Z+ o( O( t7 X; w( N4 V( f$ m, q5 }# B8 Q% u! n* f
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
$ Z# n: X- E( X2 J呵…… 谢过团长大人~~

3 r7 s! A) J. K7 e, H& |
+ P  }3 N, L( A哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 % o( z* M% G$ P4 q6 B; M
团长的朋友都是神,那团长就是神的boss。

% X' U5 |$ |7 I6 a哈 不敢當,我只是個平凡人,
% [, k2 `# Q0 Y1 D- s0 \要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
5 G. x  T% y( |# e- q' r) V) c  iZYH& g( F  ]" C. n" j1 |$ F# D
QQ:414734306+ d; N# U4 S6 E- o/ T
Mail:zyh-01@126.com4 C5 _0 o7 h, n- p. z* E5 h7 Q

8 n6 y7 H! E$ C# g, i# \8 C他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! ^/ _, ]0 D8 R! W, s1 E, S再次对团长大人和悠悠哥的无私帮助表示感谢~~
0 s6 f, K: Q3 p( B
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-9-15 06:41 , Processed in 1.165039 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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