EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ B+ l$ d8 P9 }6 t楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 s- j7 O. y0 A, {4 P# ]
这里有相应的模拟器源码,就当送给大侠了~~2 x+ X7 D+ G8 _" C9 j
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 m, e; x( O" g2 _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' H% E" H* M. i: P3 p
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  ^& N; R( c% S0 c0 F$ [这里有相应的模拟器源码,就当送给大侠 ...

2 h" F' b4 v! s- A聲音部分(Audoi Process Unit = APU):
  o8 t' E6 e7 b9 X6 \.\NES\APU.cpp; s# H) m6 \& s) Y' A9 \2 a, W
.\NES\APU.h% U3 Q& l# V( [7 M5 u

" S* W% J. C* L" H+ i2 H/ m3 }( z; X6 \3 W9 j  w/ w% b% @
影像處理部份(Picture Processing Unit = PPU):: X6 z4 q4 A  u
.\NES\PPU.cpp0 `) y+ w+ b8 k6 k/ Y, u' H
.\NES\PPU.h& c& @; U. d* D- h8 F' |

* v. _2 d# f/ I如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:* k" S/ ?  D  G5 C+ w0 v
(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 f, ]5 g$ \5 }' t, E
//////////////////////////////////////////////////////////////////////////6 t) `6 x' i4 W# A1 n8 X9 w5 P
//                                                                      //! N/ q% p6 l( e: `3 ]" K
//      NES APU core                                                    //
6 ~5 e; E( g" _, M+ T( C//                                                           Norix      //) |' `8 H4 p) J1 W% b9 L! i8 ~8 ]
//                                               written     2002/06/27 //
, c# f$ l9 E/ b# E  m* I! [# J//                                               last modify ----/--/-- //
; D/ d& e  X) x; `) ~2 `! C# b//////////////////////////////////////////////////////////////////////////
' o: O9 S+ H$ c3 {#include "DebugOut.h"$ p# w9 ^) o0 B0 L1 ]. u2 y
#include "App.h"
1 N6 t% Y! ?- c#include "Config.h". f# }$ x) Z/ A$ D
3 C6 T4 C! k* p- U
#include "nes.h"( h4 R. `2 n, }$ m4 q$ U) M6 A- J
#include "mmu.h"
2 g5 B4 T/ n, H. P2 r#include "cpu.h"
, ~# o0 z8 I1 N& v! i$ D! a#include "ppu.h"4 b: Y& o$ ]8 N/ q1 q$ t  p
#include "rom.h"0 b, d( T3 g5 q3 O  |& F
#include "apu.h"! h3 O4 o5 {2 B+ j) h% {5 b  h

' T/ z' K0 e. {$ i& T// Volume adjust
, {0 t* m/ T; W! k+ C' a* Q// Internal sounds
( V9 h$ F$ r. L. D#define        RECTANGLE_VOL        (0x0F0): j$ C" N: ?$ T) N, T
#define        TRIANGLE_VOL        (0x130)
; o/ y/ W3 G" `2 J3 G9 D9 `#define        NOISE_VOL        (0x0C0)
# n$ w/ y1 J- A, m/ D#define        DPCM_VOL        (0x0F0)
9 z8 q6 \9 \( J+ T8 L: i; `// Extra sounds
6 i. q- Z9 s3 d2 i' i; `+ [#define        VRC6_VOL        (0x0F0)' [# F1 L8 v! g
#define        VRC7_VOL        (0x130)
$ t$ l1 c; f+ W# Y. z0 e" I#define        FDS_VOL                (0x0F0)
/ L& m0 W2 a" z#define        MMC5_VOL        (0x0F0)) l, [8 `2 {6 {' |* F! e: w
#define        N106_VOL        (0x088)
* R# N$ I6 b$ d& b( w$ ~& G4 g3 Q#define        FME7_VOL        (0x130)0 X! S1 i( U  l1 U/ E
/ T1 |% S# e3 Y8 {$ M
APU::APU( NES* parent )
5 x2 K, p2 F& ^; e" m' t& e. y! ~{
- i. w7 Y7 e( M2 N8 [; j$ `: D# k; H: C        exsound_select = 0;
; g+ S! r7 y/ S# u. N0 @% K4 l! x/ c3 l" |! |
        nes = parent;1 e: O8 t7 {' m, v
        internal.SetParent( parent );
) ~8 `. C5 T7 ^/ q" R: C; `$ }. k' a  h9 s, `
        last_data = last_diff = 0;/ g( g* {* u: N$ [/ S4 j
/ e8 v3 |* U# i7 [
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );5 r/ }7 N' x. Y. m- l. u& B3 r

6 n3 x4 b. V3 b& G        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );: y8 w) [, Q2 V% s
        ZEROMEMORY( &queue, sizeof(queue) );
# ]4 U2 g& H& m( _+ R" N7 y        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 L6 @/ h( g. o7 ?  h
& ^2 |7 R% @9 Z8 L3 l/ t, m
        for( INT i = 0; i < 16; i++ ) {5 @( {+ {* B4 U: G* m
                m_bMute = TRUE;# P/ W# ^# e/ B0 W+ ~0 a
        }
. U% R* x3 ^$ s6 |8 H0 q}/ b! ]7 j8 k) b9 G" g
3 J& `+ Y+ R6 P, ]1 h2 T
APU::~APU()
0 b6 }2 o- T- t% d$ X{+ u7 l$ H3 G9 ~( b" |. E) w( W
}
8 m' r: x0 h8 [& ~2 S1 a9 X7 ?. H& L. N! k
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
3 p1 x) K+ s( I! _{; K0 e) a* \2 x+ y
        queue.data[queue.wrptr].time = writetime;: n0 T* t* o6 r4 }1 h
        queue.data[queue.wrptr].addr = addr;/ V+ X/ a2 r; A
        queue.data[queue.wrptr].data = data;! A% m, \1 o6 H4 H6 P. Z" E
        queue.wrptr++;# S( j5 J3 W0 m$ M' C1 E! v
        queue.wrptr&=QUEUE_LENGTH-1;2 ^* C! c5 i( @8 s
        if( queue.wrptr == queue.rdptr ) {; V: M" [8 Y0 y: q  p: u3 v* C
                DEBUGOUT( "queue overflow.\n" );! |9 T3 n& v; _* t- f
        }
8 s2 V/ s- Z- E# w0 F* f}6 K0 F8 f8 M- }& n0 o  u
  |$ b+ X9 w/ u: P: v
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
6 Y9 P5 c2 ]9 o. F{9 ?( j8 G4 A2 J% `
        if( queue.wrptr == queue.rdptr ) {
5 [+ ]  J5 a0 |- G7 v' \                return        FALSE;" P, ~' L% K1 R4 z: D
        }
7 ?6 i4 C. N! R3 q) _9 b: O. b        if( queue.data[queue.rdptr].time <= writetime ) {
! I, R# y: P$ A2 Z' D* h) _! h( v                ret = queue.data[queue.rdptr];
+ _* n% v/ p, E3 c9 a0 U$ w                queue.rdptr++;( L0 C0 F# F" g0 g, u- b
                queue.rdptr&=QUEUE_LENGTH-1;
$ {  i/ c% Z: n8 Q0 i                return        TRUE;
: F# \# `( r! I: ]+ `4 n5 T2 t        }
1 q0 E) @* E0 H0 K        return        FALSE;
- S! k. _9 x3 w) T6 q4 g}
1 r3 l0 b: [; e3 B# Z
0 R7 C6 y  e# l5 J) H0 Hvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 _, x; G7 i3 f2 h' }; ]4 L; F) m{
' u  V0 n' j5 E& Y& Y1 L$ @/ n        exqueue.data[exqueue.wrptr].time = writetime;9 ?; b5 r0 @* D; q4 l
        exqueue.data[exqueue.wrptr].addr = addr;' i8 J1 G1 P& c5 D
        exqueue.data[exqueue.wrptr].data = data;, L* e& J+ ?" ]1 |. P0 T# g2 ~
        exqueue.wrptr++;2 [( e1 l" V$ w" n; j+ {8 k
        exqueue.wrptr&=QUEUE_LENGTH-1;
  L# n3 @" H1 m( [' E6 R% P        if( exqueue.wrptr == exqueue.rdptr ) {' h: k! t0 P7 O1 C; b  o
                DEBUGOUT( "exqueue overflow.\n" );/ m. j. k$ k* j1 w5 h+ F( ~% ~$ E6 |! z
        }( J# G2 T0 g. W& I. g# u  @
}, f2 ]  ^: E/ P  h. Q
  d! \6 o& Z/ [
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. v. `+ k& S: p0 }{
- a$ E; r. \7 y5 k- C$ @        if( exqueue.wrptr == exqueue.rdptr ) {
/ _: ]3 x* E0 V. D% f- f& o                return        FALSE;
4 f4 s/ X4 ~# R6 m1 N+ |# s        }
* j. a( a6 Z! Z0 {% o3 r        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
- p' r- K0 `0 W' K                ret = exqueue.data[exqueue.rdptr];3 J- _3 V' y: h+ v: B3 o  M
                exqueue.rdptr++;
! `5 q+ k7 s3 B2 n8 Q                exqueue.rdptr&=QUEUE_LENGTH-1;9 _. L+ L* n% G7 [* @- y
                return        TRUE;
4 E9 A; j/ _2 ~& j2 e        }
% H6 |; @* i1 B2 Q) W9 t$ A        return        FALSE;
; s0 ~7 U9 Y+ M}* d3 q( ~( r8 a2 U8 Y3 m4 M+ H$ W
$ R+ N8 r% R( H6 p0 X. }
void        APU::QueueClear()9 U( g) [0 y8 ^
{3 K; h& Q+ _" ?6 i
        ZEROMEMORY( &queue, sizeof(queue) );
. W* ^# S/ `* W0 ^2 I; |6 ?) d        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ y$ A9 l6 S3 }2 }4 s3 x  a% v; E}. D8 {1 c( {" _: f& U9 H0 y
" R3 w$ u7 A* o
void        APU::QueueFlush()4 P0 U) D* A! X+ \9 ]
{; a  M/ |0 \, X# L% x* I& }- z
        while( queue.wrptr != queue.rdptr ) {' @* G+ q" _$ }; ~& v
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 \5 [$ `$ U% \& G0 u# t$ {/ r
                queue.rdptr++;
. h# e4 w% B* V# Y7 }6 |                queue.rdptr&=QUEUE_LENGTH-1;9 B2 u! o# f9 `2 a% [, d( G0 |
        }4 f* z6 N$ ^: K$ O1 `6 d
7 y. k1 [3 Q5 U, k+ ?: t2 x
        while( exqueue.wrptr != exqueue.rdptr ) {
6 t  i& @0 A' D; D* u% v0 U  M                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );& T, F" Y5 a8 J8 f% Y
                exqueue.rdptr++;3 j4 I& j& X7 F; ]/ F: i
                exqueue.rdptr&=QUEUE_LENGTH-1;
: e  }& B  c5 }( o) ?3 |        }5 t- j* W9 r7 }% G' ^3 m1 v
}$ V" I3 O6 E1 C+ @5 b

, w  Y* W- t0 O7 m  g' uvoid        APU::SoundSetup()
$ I) q5 ?1 e- y{( t5 C1 e; x4 g
        FLOAT        fClock = nes->nescfg->CpuClock;
7 U* |2 V1 E8 X        INT        nRate = (INT)Config.sound.nRate;, b" e  ~1 g/ u
        internal.Setup( fClock, nRate );" X/ _6 p8 |4 P# r
        vrc6.Setup( fClock, nRate );
+ L1 }% l  C% m' ?) [        vrc7.Setup( fClock, nRate );5 y0 U, I0 ^, q) q! ]
        mmc5.Setup( fClock, nRate );
/ J& o4 M2 G+ e% Y4 p        fds.Setup ( fClock, nRate );7 M# Z4 c. ~" b4 O
        n106.Setup( fClock, nRate );
% M- }9 f7 I& s  M8 W7 ]        fme7.Setup( fClock, nRate );9 w. |3 r6 h( Q
}
/ {$ i. y9 v, ~) Y5 l; w0 t
; [; r) Z8 X5 P. _5 n4 v, L* x, ^: ~void        APU::Reset()
4 w/ G9 ^' [# R, u8 J; j2 I, [) H: ^{
- I5 b; S* C9 L5 U  t' c% T        ZEROMEMORY( &queue, sizeof(queue) );; G; A0 t1 {5 k/ ]$ q0 L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( z6 M# Q3 }" B+ x7 y6 {

1 U+ ~5 T! |3 A  C. a" X7 q- ~- d        elapsed_time = 0;
/ ^, Z9 d! g0 }4 ^  \3 [  q. K% N8 t2 J! W# E2 X% ^
        FLOAT        fClock = nes->nescfg->CpuClock;
% ^" ~. G# T$ H        INT        nRate = (INT)Config.sound.nRate;
* T" b8 u( L* j# B1 I/ e% W$ s' Z        internal.Reset( fClock, nRate );
: ?5 j* \( \3 O$ m        vrc6.Reset( fClock, nRate );
# W) v: i. y  v7 p0 P        vrc7.Reset( fClock, nRate );
# }9 D2 x) q3 O7 {1 F! t8 @        mmc5.Reset( fClock, nRate );
, K6 v! y( g, {% W5 W1 O. v" c9 f        fds.Reset ( fClock, nRate );4 g' Q" d$ u3 P
        n106.Reset( fClock, nRate );
9 E: `- D, }$ A. Z/ U9 l; {        fme7.Reset( fClock, nRate );6 i8 d2 l8 |; ~

0 s. c$ D$ `- J! y4 o        SoundSetup();2 y" o2 ^5 }& b: g4 ?8 x
}" [$ Z5 d9 ^; n; X0 c( N. G
- u3 W0 u( q& L+ ]6 a
void        APU::SelectExSound( BYTE data )
6 D' i4 M% t1 q1 G{
$ E: J0 U7 b# J% ]+ R% J' V. s        exsound_select = data;
' M3 l8 x" w5 ^/ d1 p4 ]7 K! d}$ [0 a; N7 I: s2 P7 ^
  |, L# z/ A- T+ h8 P$ Q0 Z
BYTE        APU::Read( WORD addr )
* D* B( R$ ^- @{
# P) |0 `# v* ~& ?        return        internal.SyncRead( addr );
7 x5 R9 w  D4 V% x& ^}7 r9 T% Q2 C0 v
$ T4 ^3 P/ @$ I6 L4 L
void        APU::Write( WORD addr, BYTE data )* x/ P* I) m# b/ s9 m
{9 A/ Y. j: G8 m7 K% S
        // $4018偼VirtuaNES屌桳億乕僩: L" w) j. H6 H! N8 X& i
        if( addr >= 0x4000 && addr <= 0x401F ) {
- I: f3 i! w& {5 G& ?                internal.SyncWrite( addr, data );
! _: b! W: J1 z% }7 ]2 q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );  s, [3 ?% e4 C% [- ~( P
        }- M3 q- Y3 g0 w+ b* e  ]( @
}! @" v8 I& x. _0 s& S

- h+ t& F) O- d1 r( e$ bBYTE        APU::ExRead( WORD addr )- t5 N1 {  F7 y% K
{3 N% ]$ b( S& }$ l' J$ h
BYTE        data = 0;
& C& ?  N1 }% i8 C
9 Z# C2 g+ E% q$ Y7 y  t        if( exsound_select & 0x10 ) {
* b' Y* J( H# v  V- M% |: I                if( addr == 0x4800 ) {8 A/ s$ J. {8 u$ i; }
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, Q6 Q% Z$ i; @& u                }  v$ `" E% q- M# F9 y
        }
3 v5 D- x0 g% N5 p        if( exsound_select & 0x04 ) {0 Q8 N  n# H" p. D' U; f0 n
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 I/ C. D! M' Z7 Y3 w8 `1 e- _( A( |                        data = fds.SyncRead( addr );1 Z* F! l9 B$ t# ^) T; C
                }- I; \1 X3 i- l( w( B
        }
1 z7 p2 _- Q! d" q3 r3 G        if( exsound_select & 0x08 ) {; F  h5 V& N1 c1 ]* z1 S* z5 U; k
                if( addr >= 0x5000 && addr <= 0x5015 ) {: E- ]* c2 B+ [+ _6 q* v1 a
                        data = mmc5.SyncRead( addr );
4 I  g5 z# S/ M0 d  s/ s+ w4 Y9 S                }
0 x) U" @% r# q( r        }
( p3 E" g3 `- g. b( `5 i) H9 Y2 J5 H8 H9 b$ ^$ n) S
        return        data;
% k! _0 B2 h- @% g}
3 k6 {, T5 F& u* ~3 J9 z3 G% o
4 J4 F' _# A7 S; `8 m5 R% Q* F* pvoid        APU::ExWrite( WORD addr, BYTE data )
; M8 }- N, x! d3 V{
& Y+ z6 m9 d0 H        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; |6 D4 v* `: r; p- \0 q# W, B% F2 q3 a
        if( exsound_select & 0x04 ) {6 k$ D- ^3 c" D  V: {" G( K# a
                if( addr >= 0x4040 && addr < 0x4100 ) {: R: r' }& c. ?1 h# o' U& U
                        fds.SyncWrite( addr, data );3 P* j. G- B/ s  v& [$ r) z
                }
7 K7 Y- j2 R3 X8 a; ]        }
: J# K; `- j0 Q: Q; k
3 }; Y9 K- n' P# N8 c3 ^- n* I        if( exsound_select & 0x08 ) {0 [5 Q+ [2 a  w; s/ E8 r
                if( addr >= 0x5000 && addr <= 0x5015 ) {# z, r9 o' Y. B, V. l- N7 x
                        mmc5.SyncWrite( addr, data );
  {& s$ q: ?$ z6 f/ C! Z                }
3 r) a$ G9 D: K9 |  N2 |        }) C8 l0 r$ _8 ]% Z/ ^8 x! W, S7 G
}
4 k  M+ ]  h3 Y# s- V: }
1 l+ N1 }* w7 T. G1 U5 I7 Y  d" Pvoid        APU::Sync()
  [+ J& z. t7 q5 k. Y) Y4 x3 ^3 H& E{
' u5 z& v9 Y2 P$ \% U- j3 X}8 f5 k& P$ m! y9 f9 s

, e% B: u8 `2 K. y$ p. [4 ^; xvoid        APU::SyncDPCM( INT cycles )7 j# ]" j: f' K- _5 _. R3 i
{
0 t3 b0 ^' C2 Z$ ~; g# u) K        internal.Sync( cycles );
! x$ K' s9 n* H& e; d) o
' a* J$ K* p9 z" P6 ~  x        if( exsound_select & 0x04 ) {+ ~2 R; }; Q4 I5 r5 w2 S
                fds.Sync( cycles );
) n# b7 m! _" v' Y        }2 O* d- ~& d0 t  }  {0 ?
        if( exsound_select & 0x08 ) {& C& K8 j6 U3 Q8 R6 v
                mmc5.Sync( cycles );, S$ }' i8 d0 q1 m& ~
        }) V, ?6 _8 f0 \, ]+ [& e
}# v) J4 c$ U3 X/ f' F

% |$ s# u* `6 lvoid        APU::WriteProcess( WORD addr, BYTE data )
8 d# |/ l  m$ S6 g1 p/ ]" s5 F{
  }" ~8 l2 _7 R& N& _        // $4018偼VirtuaNES屌桳億乕僩
$ P" U& R+ N4 J$ P% k- H9 G        if( addr >= 0x4000 && addr <= 0x401F ) {
' n7 P& O8 |* y% E5 B+ U                internal.Write( addr, data );3 G% z4 y+ P$ C( ]! }4 o6 L7 `
        }
5 c( j* p# M; Z}/ C9 c: Q7 r- V* s. H( p# H

% O6 U3 l" H7 K' z/ w0 fvoid        APU::WriteExProcess( WORD addr, BYTE data )
: F! G0 [, s" j8 g+ t* k% ~{, D% G# h* O  \: \$ \3 I
        if( exsound_select & 0x01 ) {
6 j/ U5 Z% [/ t# C! ]4 N; Q9 l                vrc6.Write( addr, data );
2 U4 _- Q0 |; M+ N" O  ~        }
% P  f' ^; k9 U! B8 a& C) G( `        if( exsound_select & 0x02 ) {8 G, T. |# w# I' B% j+ t3 c0 k
                vrc7.Write( addr, data );4 e2 s( _5 M: Q- [/ t6 h2 {8 r
        }
- _2 P8 w7 Z$ n        if( exsound_select & 0x04 ) {; E1 E! {" u2 n: W3 J
                fds.Write( addr, data );
2 z8 C  M( o& r: E5 R        }% B) W3 R' `9 E# f
        if( exsound_select & 0x08 ) {3 N2 q. M( k$ N  x8 T8 H0 a4 v  H
                mmc5.Write( addr, data );
/ j1 a' |* ~! `& ]1 v( f        }+ |" |. x1 A4 n' f& |0 ?8 K
        if( exsound_select & 0x10 ) {
5 R  f* K) K  |  N: s: _7 o                if( addr == 0x0000 ) {
- W$ x3 K9 b0 ]; A6 Q# J$ w9 Z6 [                        BYTE        dummy = n106.Read( addr );3 k& x) U  l0 g# M$ b1 a; ]
                } else {. [( \* j& G* ?8 E
                        n106.Write( addr, data );
, Q* ]3 I3 J4 a3 p( s                }
. \9 O6 m5 l1 A7 Q7 y        }
0 B% ?! j; r% G) Q/ J        if( exsound_select & 0x20 ) {, @5 W# P! G; Z) V3 p
                fme7.Write( addr, data );- S2 b3 t, d2 z1 _
        }
4 d* D9 v( _. |, q}1 V4 G$ b0 R! r6 T3 \0 |' y+ \

" V4 N0 |$ S7 F- A( C, Yvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
4 r' P1 d7 |9 E; l, g{
% Y) `1 y* t% C1 G0 r; I# kINT        nBits = Config.sound.nBits;
, r9 B0 V+ y# D' y# V: o# ]! D7 V: xDWORD        dwLength = dwSize / (nBits/8);. G  s* P6 Y/ v
INT        output;
  `. V8 \* k$ jQUEUEDATA q;
5 I" _  f* ^- \# j( hDWORD        writetime;' P0 K. T' K& L2 d: |
' W: U0 w" f+ u7 Z& E  s2 C( D
LPSHORT        pSoundBuf = m_SoundBuffer;
: Q; |  B: b- }- a6 yINT        nCcount = 0;! e; ~4 y9 C- ^( i* K8 c5 U

; Z) G2 D- h1 l; D5 w' YINT        nFilterType = Config.sound.nFilterType;
1 l1 n4 G; Z/ ?/ q
$ j& v  q3 u* ]9 w' d        if( !Config.sound.bEnable ) {
- Y/ W; H5 \! O! m                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );& S) b- ~4 S2 Z5 O+ T
                return;
4 R2 F& T6 k. T0 l. b+ I  C7 l' v        }% ]) m1 ^. j9 q3 b3 Z7 t/ R, q

- t" w0 P9 h- ]        // Volume setup
" f. |  Z- F% B        //  0:Master8 d1 M# l5 |$ x" r* H: @. z
        //  1:Rectangle 1% E: F# E4 h8 m
        //  2:Rectangle 2
# U: [: M$ z/ ~5 P3 ]# y        //  3:Triangle% q# O- c+ ~. T0 f: E
        //  4:Noise
5 D3 D1 M+ l' p  V) L        //  5:DPCM! I% e. W" W; [* Y# h# \' {
        //  6:VRC6
2 J- G0 F- s! I( F/ M- x. w        //  7:VRC7
/ d4 H) n1 c. S1 M        //  8:FDS
+ R  ?8 `/ A- L6 S# w5 k& f0 E        //  9:MMC58 s/ m& K& V$ `  p; g
        // 10:N1067 N, d6 |( r5 G2 M% P. c. t7 i9 f4 U+ B
        // 11:FME7* |) x- {; l8 D0 o* p
        INT        vol[24];4 f: P7 \1 m8 N6 d
        BOOL*        bMute = m_bMute;
9 a/ U. @7 q8 O8 B        SHORT*        nVolume = Config.sound.nVolume;
6 c( e% t) j6 Y( h1 c
; J: \) ~0 j( k+ K% y0 I        INT        nMasterVolume = bMute[0]?nVolume[0]:0;7 B: x# b% {: Q- y# {

' z/ q3 |7 ]* o6 b$ I: r        // Internal
8 L: j5 Y& R- K# g! T7 X        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; p! ~# S: v7 R6 N
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;: x, d0 {' g5 N; T# ^
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;7 ]1 B2 z. G* O  }6 f2 ^  V
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
( C5 k5 c# n9 I6 R" ?        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
+ i/ {" x* ]6 M$ T
* W# V# I) |$ D/ y9 D  u3 |9 p; w        // VRC62 `# v* `% }$ m3 B
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: @* k6 M5 L3 H; F
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% Y! b: v4 Z$ [; a
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# N; H& X1 E3 Q( z  M' O
; _, ~  ?8 ^; r) B5 _8 o  E+ [        // VRC7+ z1 {% ^+ o( ]7 e7 t3 O! L) U+ E
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 G( r! j$ t% W
: Y0 Z/ q$ O+ N4 W. _" f        // FDS
, t( J- G" V$ T8 O        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
5 s) Q! w+ b6 p# F# w, {2 ?" f6 x" r2 E; ^" \% m: O
        // MMC5
2 M% W; N; O& n  B0 J3 c        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' X. J/ g3 t+ W6 b% J        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 F9 j7 R: }! e3 f' y, i8 |        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 l2 c4 H" K$ `" Q% r6 p/ ]* m
4 T0 L7 C( F, s5 n7 ^; x& K9 H1 _+ \
        // N106
" ~5 r! E( @. X+ J        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) |* ]7 _; |* z8 y. X- B
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! G. m6 O) K$ u" w  T4 f* p! S        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 [; f# U+ l# \3 k) a: b$ W1 R) Y        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- F% q* ~8 @5 ^1 `' h) ?# s1 {        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" \* Z. s  o7 K3 ^8 ], |0 e
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! R0 Z7 G) H) c0 D6 d3 N4 h
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 H6 g# o1 F& D6 L        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, u% r( U/ L) ?$ J

7 [7 U6 E+ d0 ], @        // FME77 S6 m0 O, h" U( c5 ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# N5 z5 m, W% d( g* J        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! B, }. |/ j; s/ R        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 r; W4 K. Y8 C) V: g# c3 r+ \9 T  s( B  K' o) ^
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ H2 v6 I$ A0 ?* I        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: B7 P; H3 `" l) [, k

5 x- v+ a% _8 }$ r6 n& d" c        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
( y: i: E) ]& V4 \+ F        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* w' G9 A5 t5 i# U  h
                QueueFlush();
" ~  e- v+ N5 ]        }8 `& X+ g  I1 D
( \/ t) {! |5 ]  C$ n( ]
        while( dwLength-- ) {  P' l, {( D) {4 [4 {# ~
                writetime = (DWORD)elapsed_time;( K$ w/ N9 @# |; ~2 c

$ F6 w5 ~( w( ?, Z  `* L! w. W* S1 Z                while( GetQueue( writetime, q ) ) {& I6 o. ^3 x& u2 V3 Z6 q3 D5 n
                        WriteProcess( q.addr, q.data );4 V. l0 R3 v& J; [
                }
9 }) }3 v* E3 R# v' n
, _1 I" B  v4 j& n& d3 l; j, S' {                while( GetExQueue( writetime, q ) ) {8 w$ F5 O/ F% X' l$ M2 [
                        WriteExProcess( q.addr, q.data );
- I2 X" n! M+ Z' k                }
% ^) Q/ k0 V* p$ _, g( M' V* s7 i& ~/ {9 Z' C* P" U9 ~1 }* N" f
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME70 B9 o: H& Q! a! p
                output = 0;
% B4 j! r. g+ K8 X# x" }6 I2 G8 ~$ a                output += internal.Process( 0 )*vol[0];7 x! Z% Q' `3 N! S# k
                output += internal.Process( 1 )*vol[1];/ Q* e. ^( m1 [9 u: y: [! j1 L
                output += internal.Process( 2 )*vol[2];' V6 z9 R# i$ G% p# ]
                output += internal.Process( 3 )*vol[3];
+ C) G* x7 G5 s- W6 Q$ J                output += internal.Process( 4 )*vol[4];/ K+ y: Z0 [3 F8 z% h0 l. |
5 {( p% U  m0 S  @$ z
                if( exsound_select & 0x01 ) {; G6 q  w: U  P. ]4 e3 z
                        output += vrc6.Process( 0 )*vol[5];! |4 U+ d! C& r- n1 p& r
                        output += vrc6.Process( 1 )*vol[6];
6 n8 V4 n0 T6 p* B$ p# A$ k                        output += vrc6.Process( 2 )*vol[7];
5 ~# E7 f$ |; A: E! B                }$ {7 x" X0 F1 x; O& R
                if( exsound_select & 0x02 ) {' R# J9 e2 Y4 j8 D) @
                        output += vrc7.Process( 0 )*vol[8];- y( h: {$ Z( Q7 o& M9 H
                }" G; L+ B+ M( N& V/ `
                if( exsound_select & 0x04 ) {
0 N3 x, g* `9 F0 Y6 Y                        output += fds.Process( 0 )*vol[9];
# B; c% i8 V2 v2 Y* \                }
3 O: D2 a" e( d7 v4 W8 v  u; {1 L                if( exsound_select & 0x08 ) {
( C1 q5 N5 V) I' p4 ?6 x9 i, F: y                        output += mmc5.Process( 0 )*vol[10];7 k, m$ G4 p6 M$ Z& g$ O/ ]; r, G8 s
                        output += mmc5.Process( 1 )*vol[11];" `! S! J0 S; U
                        output += mmc5.Process( 2 )*vol[12];
6 \$ \3 M5 B+ |, o  f; v                }, @: j: O7 A7 ]: m7 b' n) q
                if( exsound_select & 0x10 ) {
5 C. a( ~. Q& a3 e                        output += n106.Process( 0 )*vol[13];& k! q2 J3 G) @! I
                        output += n106.Process( 1 )*vol[14];) p2 x7 J+ e  E* a( r0 }
                        output += n106.Process( 2 )*vol[15];
4 p# l/ ~  x1 Z) K" O1 B                        output += n106.Process( 3 )*vol[16];
; }; I! Y" Z+ H9 p8 P                        output += n106.Process( 4 )*vol[17];6 s5 Q! V5 y6 h9 [: b% l  d# ]
                        output += n106.Process( 5 )*vol[18];
! f' ~' l5 g- h# Z% \( o                        output += n106.Process( 6 )*vol[19];$ G4 c6 D% W8 t# w. r6 T
                        output += n106.Process( 7 )*vol[20];
' I; L( ~$ F& P                }
/ ]' Y0 R8 a4 v3 j+ J  @! |9 j                if( exsound_select & 0x20 ) {6 j2 q( a5 B" m  Z& ]: x5 S1 K
                        fme7.Process( 3 );        // Envelope & Noise
* B7 j# v8 a+ S                        output += fme7.Process( 0 )*vol[21];
( v- m4 H3 u+ u0 K3 ?, e, c                        output += fme7.Process( 1 )*vol[22];
$ D4 u) I* T# _+ [% w3 ?                        output += fme7.Process( 2 )*vol[23];
- M" g7 H$ h/ |0 H. y; Z* q: I                }
/ M, m3 ?' L" H# A. \) c9 y( z0 P  r  A  P
                output >>= 8;
8 C! L4 c. F9 O- ~8 N8 @" H& Z" A+ I/ \( }. M$ c& w' A
                if( nFilterType == 1 ) {: P- w! o, t, E- y9 g
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 m; D& @4 L$ j% o% z
                        output = (lowpass_filter[0]+output)/2;
% a" w- B* C* u& r8 E                        lowpass_filter[0] = output;; ?) k* s: r6 i% g" J
                } else if( nFilterType == 2 ) {
! _6 i6 p+ q6 o+ ~; ]. e                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 T6 Q; d8 P9 A5 o2 v8 x2 g
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;5 s+ m: R& @+ O& V4 p
                        lowpass_filter[1] = lowpass_filter[0];1 o  y! E; [1 \4 k- d1 \
                        lowpass_filter[0] = output;
, k8 j: J2 y* t/ x                } else if( nFilterType == 3 ) {% y, E. \1 Z: I
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)7 U) L! x0 a2 X' [3 q8 ?
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
/ G% b# ~/ ?' ^7 ]6 I% W                        lowpass_filter[2] = lowpass_filter[1];& T2 T/ S5 n* T- w: f3 E. q# }6 J
                        lowpass_filter[1] = lowpass_filter[0];* d' [" W2 ~6 H# l/ F% W" L! O
                        lowpass_filter[0] = output;
; Y$ a$ A6 }- y! R- J$ l                } else if( nFilterType == 4 ) {2 k/ @- J0 i5 J" F& D2 {+ |9 k9 T
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& h0 c  T9 Q# G5 n5 y# x$ V! Z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;& L% T' \! q2 I" C2 P$ m
                        lowpass_filter[1] = lowpass_filter[0];$ j8 e: i+ {1 ^3 N
                        lowpass_filter[0] = output;! l! l8 P" Q: N
                }, U1 d' T% J: `! z3 D' p! ]
0 {# G0 J/ ]5 H2 t5 E0 y! l3 ~
#if        0
6 G1 M5 N! P# y% ]                // DC惉暘偺僇僢僩* Z+ J) S" J7 O  d
                {
; h* q9 `7 y# P8 P                static double ave = 0.0, max=0.0, min=0.0;
( q$ [; h! D8 a2 ^4 y4 h4 \                double delta;
& f: C5 _  i4 h* P' g* R/ U% |; |                delta = (max-min)/32768.0;: U9 T9 Y# J  n( m
                max -= delta;& T, U2 B1 h1 Z' W0 E% p
                min += delta;
6 _8 T. [( h3 U) L( Q                if( output > max ) max = output;
" y: ^, x. P/ T% J$ g                if( output < min ) min = output;2 h% p& ^  W" E* h, X; [% b
                ave -= ave/1024.0;
/ [, G1 Y% {+ S$ b* a$ Y; w                ave += (max+min)/2048.0;
6 h. |, Q7 Z- t# [+ V                output -= (INT)ave;
6 H, R& N0 V7 U/ D) N                }9 h. R+ R) `9 W* k- M) ~
#endif2 ^3 B' f: G. C9 P$ ?% R: R
#if        13 y; ~; Z: G8 P9 [7 r1 M
                // DC惉暘偺僇僢僩(HPF TEST)3 {/ W' c. r1 }5 b
                {
* k! I) R: Q( e$ x4 B% @8 X! B//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);, R2 K/ w5 k+ I, a+ d. Y: c
                static        double        cutofftemp = (2.0*3.141592653579*40.0);; i+ \; o# D# J3 ^
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
! S% y$ P2 R! ^! e8 C0 A                static        double        tmp = 0.0;. D) O0 ?# R' g+ t9 }, W+ n) N( _4 Q
                double        in, out;; C* k! V% f" J0 @/ D: d7 P! t

+ Y8 A* [( x* C/ s6 N/ I0 \# O                in = (double)output;
" ^3 u' r% b% b, j                out = (in - tmp);
0 `) v$ |: E  a9 n' q: w0 p. i                tmp = tmp + cutoff * out;
0 p# a) u% Y/ l7 v( g1 W4 @7 @3 o3 r
                output = (INT)out;! {( p; v) l( r' V+ ]4 X# `  x! i
                }
  }$ d- z$ K& Y0 l#endif
+ W5 X: s# ]" d#if        0: K5 a) \6 p2 a( z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' K( U2 C( I8 s  o: m' a( v: M                {
9 U3 X' K$ [: C, B1 P/ ~                INT        diff = abs(output-last_data);- I% {  N) t6 R1 O; i
                if( diff > 0x4000 ) {% h* T( P* v4 ^: h7 `# T  J
                        output /= 4;; s, L# }4 @+ y5 h7 `2 N- C1 \% a
                } else
! Y5 D  [  o* P9 ^                if( diff > 0x3000 ) {, O: l: Y  K) z/ @
                        output /= 3;
. Q. ?9 {( }/ \$ P& E                } else# V" H3 h3 ^5 H7 {/ m) W
                if( diff > 0x2000 ) {- \1 g1 g% t9 R* |9 P9 m: V7 L; F
                        output /= 2;) F" R; x" u; V6 Z# A( Z! @
                }  N% t- v- e/ g! z! g' T0 l
                last_data = output;1 V( H- }6 W/ b. q1 Z; B
                }
" `* f0 n; j/ T" _- V# L#endif, Y9 Q8 q, W' v* O# {$ s
                // Limit
3 U; y0 Q7 e" c9 n! ^! `( x                if( output > 0x7FFF ) {
% Z% r1 ^( w9 j7 a& Q4 l/ ?' g                        output = 0x7FFF;
5 C* s, P* f% ?7 L( Y* w                } else if( output < -0x8000 ) {) G8 s1 N4 M6 I
                        output = -0x8000;
" L; \, v# p  C$ ^                }
( Q' W! p- Z7 Q9 Z4 ~, N0 L" A9 S8 z8 L! ^( }# s0 @8 q
                if( nBits != 8 ) {
% k7 a$ K: g: O) A2 v( O$ f                        *(SHORT*)lpBuffer = (SHORT)output;) H$ w2 P4 j1 a! J& K( w$ R( F
                        lpBuffer += sizeof(SHORT);
' _& ]) {/ d+ z2 U- V                } else {( k. n; @. M1 k4 Y5 O
                        *lpBuffer++ = (output>>8)^0x80;  [6 y* S9 t5 t5 U& a2 _
                }' R( R$ b" q1 s( m
5 t" J. g: k1 \" G* Z- T
                if( nCcount < 0x0100 )
6 o: S+ U3 h, }" J! M                        pSoundBuf[nCcount++] = (SHORT)output;
$ t2 F6 W0 u7 ?: x. [8 M2 B2 {- Q0 c! A- c, H! \" J, b
//                elapsedtime += cycle_rate;
/ q6 b& }7 b/ w, x: J) K# R5 l7 b8 T                elapsed_time += cycle_rate;# I! O) a0 p( W4 T  W3 f
        }! [- q. n2 E5 p' L4 j- y

' g3 b/ ]& E# f' e. F- A% q#if        1
) A! O# l9 Z9 h# _0 t  @        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
, w4 o) _& o% N) b  y                elapsed_time = nes->cpu->GetTotalCycles();  k- i% a* ?" f, u. _* C
        }
+ N$ o4 S9 C) q9 M- r" O        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 ^8 }9 e/ L2 B* L4 R2 G9 i
                elapsed_time = nes->cpu->GetTotalCycles();, d0 G% f: x0 w( C) M
        }
/ v( ~% ^6 M6 B% L& O#else. M# ]+ U$ E( R& U
        elapsed_time = nes->cpu->GetTotalCycles();! }7 j/ N: u0 {8 O
#endif
/ A/ S& c' [" X- F$ |}
: K4 Y# ^% a6 {# k1 x! N0 s2 G, w# t6 d% T* Q$ {2 R1 ]8 R7 i& t( b# w
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)# W  x) {2 l" J5 y* |$ G
INT        APU::GetChannelFrequency( INT no )
4 s6 Y  `8 ?7 O8 h# x{/ U7 e2 p: P' |0 ^+ B
        if( !m_bMute[0] )
! z/ A& H. [5 l                return        0;8 s, k: B' V8 `) u( j6 ~; D& w

. _' T) Y2 ~- t* B1 v        // Internal  M" Y2 B5 f. X" Z# ]7 j: W
        if( no < 5 ) {* O7 G  R5 }8 T$ r
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
5 z% Q0 T. X9 e/ A$ v% Z/ {: r. z        }
! L& Z' w% t; ?# E; n$ e        // VRC6% q+ Y/ D2 U9 o+ w3 J7 A) O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ t  f; v) _3 w. C# i( j8 _                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
2 h7 v- E8 f2 V& r/ d$ A1 j8 `        }
& a: M8 R3 ~3 L% |        // FDS
7 P2 b$ ^4 s& C& y3 e3 b        if( (exsound_select & 0x04) && no == 0x300 ) {9 e2 |# o% [7 H" q
                return        m_bMute[6]?fds.GetFreq( 0 ):0;' A# O$ p5 Z8 _, ]% L# N9 g: \- m( x
        }7 m! E9 f: e7 e4 T+ h" z" `8 d1 ~
        // MMC5
7 L7 ^5 X  I, X0 |1 \* m" j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {, @8 l% W: |4 a+ {7 J6 @
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 S, O, y7 c; @& _2 G" }, ]
        }
; z' i" i' n. {; ~4 ]: h- U& b        // N106
( E+ o5 V3 ?% O1 w. n        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 s2 T5 w5 Y# f- X. h* O2 |                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
5 l* f; q  W. z2 i' T8 A        }
5 C- J6 b; j! s6 ]# w; a! ~4 H        // FME7# U: d3 s/ @/ _% z" n, j% I
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 T0 i7 f7 p% z& M$ T. Z  q  R5 O
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& T& G6 x% [' H4 b1 I, I- ]        }. B' z% A2 B; h* s$ s3 |
        // VRC7
1 l! p. [6 q% y* s* z0 j7 g        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ i/ `+ C& Z! o8 \- z, \. R                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;% J" i" R" g, B* F1 F
        }
# k$ Z, p9 ]5 R" y        return        0;" i- N4 S& p$ v- H0 \
}% v( M+ f# A, N; c

6 O6 u. B# X0 y// State Save/Load: i6 j" V( ^0 T. Y
void        APU::SaveState( LPBYTE p )5 a- i. \/ I1 u9 U9 H
{0 p/ u  b+ j9 P& N
#ifdef        _DEBUG- d% q2 q9 J4 {
LPBYTE        pold = p;5 _# i! q0 V# a& t, f
#endif
7 I/ V) D0 y* @" ~5 m
& m/ m2 ^& u5 K/ g# a3 [: c% m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- K2 Z( M6 y! D" L* l
        QueueFlush();
+ P5 [: }  E$ s6 f, H, B; j3 L* t5 l: w
1 V. [( Z* m+ B! r& X        internal.SaveState( p );
  J1 n; ?: z. j2 [        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 o; N; @' O8 a' M& X4 R: t# E, S$ X/ w0 g/ Q- D% Y
        // VRC6
. l2 v7 m. y. R        if( exsound_select & 0x01 ) {: u9 h" ^4 {- _" J
                vrc6.SaveState( p );; O- o" A5 l# H. ~, X2 @+ H: w
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 W3 Y% N- c7 T3 M& z7 z9 ?7 S
        }
! s  n! K$ [! D4 Q1 a        // VRC7 (not support)
3 H' v3 F3 `& a# Q2 h( k1 F' Q2 i7 F        if( exsound_select & 0x02 ) {3 _" I/ d2 G% p8 {
                vrc7.SaveState( p );
- d" x6 n. j% Y/ [+ [  N! \                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! E; K& _, N0 C, _+ M) J        }
  O! w$ x% E4 |        // FDS
8 a: y8 r: o+ p        if( exsound_select & 0x04 ) {. r& h0 j; s) @1 f! [+ S3 z: t1 c
                fds.SaveState( p );
6 \5 m, @: v) u  f                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 ~8 K! T3 y( U0 m3 ]0 i
        }
# g2 @! I; b8 k( w" H4 A        // MMC5
8 s! X" q) K* R4 F5 N( f2 p, B& m/ L        if( exsound_select & 0x08 ) {
/ }! l) Y$ E8 i$ ^  D0 Q6 {                mmc5.SaveState( p );& W5 ~1 c. `$ x1 d6 N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding0 I3 @2 J( x. b! m: C
        }$ @4 F& s! T: P  V5 X
        // N1069 F2 I: a7 x4 E6 N8 h6 `
        if( exsound_select & 0x10 ) {- t7 ^& F1 U) [5 L- q
                n106.SaveState( p );
/ e) L8 @  l: E' f8 M+ x$ C) M1 n                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 V. \' |8 e# w& I; J
        }4 k# k7 I; V, Y. `0 W8 o( Q
        // FME7# E% D5 g8 p$ J  k' D
        if( exsound_select & 0x20 ) {; u9 U0 N% Z' g  x3 {. a4 i; n" f$ v! x
                fme7.SaveState( p );" C* S( |7 o& y& ?1 F+ {9 n2 |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 ~. G  d/ W" h$ a: K        }1 Q) }2 a- N$ F) x8 V- L- M- K

- Y+ R  {7 e& M" `+ k& c* j#ifdef        _DEBUG
& E$ w- d2 i; B; E( [4 `; ZDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 F# j9 G/ A5 n, ~/ n9 h) V, b9 k& r
#endif
& L* m; d* Z; K8 v7 D. n* ^}1 r" g% ]3 o, B0 e  a6 M

  y% M3 Z: x$ o* U, nvoid        APU::LoadState( LPBYTE p )
6 {. o2 h! E9 B/ E) t{
  U4 Q0 L7 r( _1 C4 y4 ~2 z8 z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' q! r* C7 O/ b( }7 w8 F  g
        QueueClear();! O/ W" ]2 s& j$ X, s- ]* R. t6 k$ a0 G

& H& l& P7 M7 B" d5 R8 Z        internal.LoadState( p );1 G. R3 r* e, N$ O7 e+ ]! r; n
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; u" f' o" E, J+ Z

, o' L' R9 i" t5 ]  J        // VRC60 w, H+ s3 T7 i/ P: T% H
        if( exsound_select & 0x01 ) {; U7 C+ t9 r4 j& Z6 L) S
                vrc6.LoadState( p );
  w" ^0 a" `# X: w7 `3 ~                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 H9 q/ y$ P  c6 Y' }        }& f6 o/ t4 g  M0 M: N
        // VRC7 (not support)" A) ]: A" U' l2 o7 X8 z. X
        if( exsound_select & 0x02 ) {* f$ p5 I4 s0 P8 i
                vrc7.LoadState( p );( m1 H  |( W3 k* n) O+ h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' G  Y$ h6 [, P( l' R* m! P, J        }: ^6 c0 M$ u/ E
        // FDS
; m7 C+ y) w8 G# Y5 m        if( exsound_select & 0x04 ) {9 n6 L4 b, [9 J. G9 @* H2 G
                fds.LoadState( p );0 i& K/ V- V1 k$ }$ w- }& d
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 T" g: s3 s* m& K! M, B4 o) l1 ~        }8 T$ o; k4 [$ b' {
        // MMC5
" o) M$ L7 `2 J' m7 o: P        if( exsound_select & 0x08 ) {$ U4 ^7 {, D2 }3 x. `2 ^
                mmc5.LoadState( p );! g' y! z  M% u4 \( m+ ^# v% \% u$ ]
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. w$ L# w- b) f3 j9 \8 k0 P
        }
% E  J3 J$ c7 L! U) `9 l' p3 `        // N106
, {" Q+ Q5 t# D5 U) [0 o1 ^        if( exsound_select & 0x10 ) {( M1 ]* d& G: V/ G7 W* O& b0 P8 @
                n106.LoadState( p );. S; c7 z5 ~: e; c2 y
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, l# t0 }  \( d        }
8 c0 I- I! ^  z- j( }' f        // FME7. x% j9 ~9 U: w% O5 D: @3 X. O
        if( exsound_select & 0x20 ) {6 O/ O3 x+ z/ S
                fme7.LoadState( p );. p* h8 q1 h, H1 K
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; j* P$ {: C9 q" h% }' @$ ~, W        }
# W2 Z9 v9 b# g* _: l6 t6 u9 y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 @2 a7 A0 \  q8 q: f可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。+ N* I. @, |) s6 _. X6 |- i
感激不尽~~
9 Z8 {7 B: W; g. J3 w: o' \
恩 我對模擬器不是很有研究,% y0 J9 ^0 p* i+ z* M+ h, z
雖然要了解源碼內容,可能不是很困難,
$ A2 f9 Z8 t- O6 t4 g不過還是要花時間,個人目前蠻忙碌的。& i  j5 O. p  o9 ?% n5 o- o
1 I6 m9 v7 V$ Y
給你一個朋友的MSN,你可以跟他討論看看,
3 ~; w( X6 d2 r  O" S0 I7 ~他本身是程式設計師,也對FC模擬器很有興趣。, l4 F3 p! x1 @1 A  Y8 c' H
$ e/ d* X4 X' s" S3 o5 t
MSN我就PM到你的信箱了。
. m' x! L4 X4 O2 @4 n! O, J! D# {; ~" ~6 k" L" ~+ [) D
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
: K$ U$ v$ q8 a  J/ Q( l呵…… 谢过团长大人~~

3 R1 V# ~2 A9 f' |# p2 m. N6 t8 X$ L2 [; z
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & B' \: a: o1 m! ?1 c+ X  p
团长的朋友都是神,那团长就是神的boss。
/ M+ f7 r! a. J$ h$ e
哈 不敢當,我只是個平凡人,
8 a# w) u8 ?  e& Z; x: I* t. ^. G% ^要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! {: p+ o! k0 `5 M" |
ZYH/ ?4 H& v4 @2 h+ b. `, t
QQ:414734306
; H& h+ q( {% C, VMail:zyh-01@126.com
& V2 k  `  f0 y  n9 y
: H/ C3 H, t! @# z  l% S: G他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ; b6 ^# k4 J$ a6 c
再次对团长大人和悠悠哥的无私帮助表示感谢~~

4 P0 }  m+ H5 z1 U不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-31 03:13 , Processed in 1.076171 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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