EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* T# n+ u0 V3 I) O8 i. A' H. ^: m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ v( ~! Y$ _$ i- Y! n; g这里有相应的模拟器源码,就当送给大侠了~~  }0 _4 ?+ z! N) D+ B5 m
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
1 Q; }' q" ]( g- Q8 n能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! n: h! h* n$ p) ~8 T0 k4 p3 D$ k
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& `7 y4 |) a+ f# H! X这里有相应的模拟器源码,就当送给大侠 ...

$ R$ _+ K- O2 `# k  p7 T/ k4 I+ P' J2 n聲音部分(Audoi Process Unit = APU):
/ f) }1 ~8 o8 C3 {) [  w' f1 S.\NES\APU.cpp
) ~* r$ ?* m% O.\NES\APU.h
7 W! j* j+ @+ ?, j+ f0 m. ~/ c5 t1 l9 S- V$ E- k/ ]
, B  s' x% M) s4 T5 N4 ]4 w
影像處理部份(Picture Processing Unit = PPU):
/ \. s7 C" A9 ^.\NES\PPU.cpp
9 b" h& A/ H* L.\NES\PPU.h+ p7 b; ?# m5 \% J/ f
$ H5 }0 _4 y8 k2 ^% z1 I! ?
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。3 O7 ?6 v* z9 G( A5 N7 Q% d4 k
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
# z# V" y+ {' p% G4 G+ v' J' v(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; G6 }$ R0 t! w1 D, O. C//////////////////////////////////////////////////////////////////////////
! O8 D$ a% I+ q" T  [//                                                                      //
1 Z7 H7 o( A) x+ u4 j0 X8 o//      NES APU core                                                    //
# N; R* b7 d; E  P) \//                                                           Norix      //
. o) _- e4 P' b) O3 w% X3 z//                                               written     2002/06/27 //7 X8 v# z( d/ p  ^
//                                               last modify ----/--/-- //4 x4 H& Z  _. p; V5 b
//////////////////////////////////////////////////////////////////////////
2 C/ s! |, T: ]' V1 \' N5 M* H#include "DebugOut.h"  H3 O/ H( ^# o
#include "App.h"
; t& K2 ?3 s4 s! p# E#include "Config.h"
; Q$ f: E" c$ K2 y7 \: T9 q2 h  ?6 f8 I) r
#include "nes.h": q& b  R# P3 Z5 u; G- p5 T
#include "mmu.h"
& ^) D+ N' Z' W2 @. ?" ~" R#include "cpu.h"9 T; p* S  I$ _$ E: d' a9 V
#include "ppu.h"
% `6 ^4 h. d% a9 L% c, O# c#include "rom.h"4 c* [/ u5 z3 h: _/ g0 i
#include "apu.h") `1 j' C$ F; S1 m7 x0 `8 ], e

& a8 g. U; \. c; i% D7 A// Volume adjust
5 c3 v4 g0 x2 h// Internal sounds
3 y% Y+ X/ c. H+ g( k" ^#define        RECTANGLE_VOL        (0x0F0)
; {' u0 W% @' J3 X6 V3 p#define        TRIANGLE_VOL        (0x130)7 m- w5 j! T8 d4 C3 I+ [
#define        NOISE_VOL        (0x0C0)" Y  y$ d+ @+ ?$ `$ _
#define        DPCM_VOL        (0x0F0)
* J& n* J4 A$ q  ]5 d// Extra sounds, `- v" x  R1 Q" Q
#define        VRC6_VOL        (0x0F0)
. q/ d& _3 `% v$ w#define        VRC7_VOL        (0x130), m, T& A7 r. ^
#define        FDS_VOL                (0x0F0)( l/ ^) \# K! j6 h, J
#define        MMC5_VOL        (0x0F0)5 }; L" J0 U& e/ q/ W2 J
#define        N106_VOL        (0x088)2 x$ s# G) s6 A6 d6 g+ W' G
#define        FME7_VOL        (0x130)
: p7 B" z: r3 T' W
$ F! l9 p) O9 b5 J, D( {- e7 ?APU::APU( NES* parent )
  I: f; N- s8 H) \+ x  c: H) x  B{+ Y! l( v- d: H/ R1 \9 T
        exsound_select = 0;& k  m; o. h; G% N7 M. A4 ~
( j, E" e! s5 B2 M" L" P, h1 X
        nes = parent;8 ~& W6 q1 ^# ^% C- T8 ^; F
        internal.SetParent( parent );
1 f! r5 U. d( r6 @  @. k
0 e8 V' `1 V6 }5 a6 k1 ~+ l+ y2 a        last_data = last_diff = 0;; F. t  z" g* W  {

# S' E3 T# J; i  @        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );  q6 ~; a& X1 b5 a& ~$ J

5 t5 K  w- s. [+ n' e; w. |6 C        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
3 O; L* o0 \; {/ y1 y        ZEROMEMORY( &queue, sizeof(queue) );
* i5 U% Z/ ]4 ~2 `) o2 a3 i( p        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 N: s0 t& E! J* e) D( J
4 p* O: D+ p$ A# c9 Q
        for( INT i = 0; i < 16; i++ ) {( I. ?3 Z8 ]8 K' e- Z9 I. ?4 l0 W0 T
                m_bMute = TRUE;* Y7 y) p# f5 M- M  U8 q
        }
( p: u6 O' f# s! j" y3 ^}
/ P3 y: [+ I5 v% {, a8 ?- B2 n3 K, v" [" T1 A' O4 q
APU::~APU()0 a5 a$ H- @/ Y4 |
{8 o  M4 k8 J6 ?, M1 x9 v
}
6 U' ?9 T: [. E, d5 w* [$ r3 K+ h- L0 C* i
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
7 q7 c4 [! ?" Y. B3 T{
; Y9 j* x# O5 A5 o* O        queue.data[queue.wrptr].time = writetime;
* y1 w. u7 q# Q* Y' [6 p/ i( k        queue.data[queue.wrptr].addr = addr;
2 f) a0 i: ^2 X% r- h, R        queue.data[queue.wrptr].data = data;# @; c4 s/ U! Y0 U3 W
        queue.wrptr++;
3 i) K. Y1 Z$ i% g7 E6 ~" |2 A        queue.wrptr&=QUEUE_LENGTH-1;
$ _) T+ G+ I6 q" A0 F2 f; \        if( queue.wrptr == queue.rdptr ) {  t9 S7 n! z; v, d0 N
                DEBUGOUT( "queue overflow.\n" );6 q3 U7 D+ n  ]8 g
        }) v1 A+ ^: A' r. z
}
" t2 z. @' Q0 `2 u; B8 q
+ w% ?1 {; Q+ X2 r) yBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ), o: `% {' G2 A4 Y  B/ t
{
, G, r) ]' u' b4 w        if( queue.wrptr == queue.rdptr ) {
' B* f' D2 G2 t  t. W$ ^                return        FALSE;9 n6 m4 ~, Q% @8 H8 v: ]7 Z
        }
  G' r8 T# ^: b8 R: s7 Z( `% d6 H        if( queue.data[queue.rdptr].time <= writetime ) {/ Y; g; Y1 \5 {) y& s
                ret = queue.data[queue.rdptr];0 X$ S" D/ g/ N& f% w4 N" P+ |
                queue.rdptr++;
" m+ Q6 j* Z' h                queue.rdptr&=QUEUE_LENGTH-1;3 t/ O; R! l# c8 d; a* I
                return        TRUE;8 A% E! f, R: l# o0 E0 x
        }
% e: k8 P8 m) ]7 O3 V3 b1 T5 J) x        return        FALSE;
: x2 z* I: W" E& @}
9 b. P8 X9 H' }% y7 f1 I* R9 ]2 @& }' z1 _
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
0 p4 G# O0 Z; q$ y! }/ l{
9 e3 b# V! e" e6 y1 ^1 i        exqueue.data[exqueue.wrptr].time = writetime;
+ T  f8 j, [( C0 T        exqueue.data[exqueue.wrptr].addr = addr;7 S& u/ r4 {+ N# w( I9 y0 z  v
        exqueue.data[exqueue.wrptr].data = data;
' ]! N) j/ y- y        exqueue.wrptr++;8 x, F% A+ p7 g' `
        exqueue.wrptr&=QUEUE_LENGTH-1;( d' R; A& h7 j1 `
        if( exqueue.wrptr == exqueue.rdptr ) {
5 c  T6 c' \: {0 n; ]                DEBUGOUT( "exqueue overflow.\n" );5 D- g5 z  A  e/ u' }
        }9 t+ Z& s0 e% W
}
: n. C0 d* T7 c' J, q) [' p; H) O( u7 {; N. x% P
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )1 E1 Z) V4 v' \
{
0 P) ^" P' f& |        if( exqueue.wrptr == exqueue.rdptr ) {9 _; g6 b$ X( o5 v. k' N: n
                return        FALSE;
4 l' z0 h' ~1 m6 _; t- \        }
$ k4 F! v3 c3 I( Y5 L9 h        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, ?+ O, n! q; t- \! M$ \
                ret = exqueue.data[exqueue.rdptr];# V2 R* |& S+ r2 |! ]2 G' O
                exqueue.rdptr++;
  E0 U) X2 Y; A* ]: z1 e& H                exqueue.rdptr&=QUEUE_LENGTH-1;: T: o3 o/ J8 `& b: X
                return        TRUE;- y7 Q1 O) Q% \" s; y
        }! e4 J1 [  R% E. ?) x4 a6 R( b
        return        FALSE;
; u* H$ O6 O2 l, ]. d9 s: b# G- q  n1 ^8 f}
6 w8 _4 T* |+ ~
4 @# l' @3 T! x1 r3 ?3 ^" s$ ?void        APU::QueueClear()% `3 T: e& Y8 U  O5 O
{( Q0 X) D/ B0 {5 c4 a6 `' \
        ZEROMEMORY( &queue, sizeof(queue) );- g4 U* F; A9 I+ n  U$ O1 t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. ~7 q6 i" |! l: r0 ^' ]2 N( N
}
/ l0 }2 Q: _% ~. y6 u( v, l1 b+ I, m0 ?( G/ j
void        APU::QueueFlush()7 f* R% ?/ W" q: [# W* c
{
! K0 L& V+ x9 A5 t; }- f$ M        while( queue.wrptr != queue.rdptr ) {
4 L: o0 p4 A9 \! U( m. D                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );8 i5 P" L- Z2 \
                queue.rdptr++;- L4 h/ `$ b* ^0 V8 A" \* Q1 k
                queue.rdptr&=QUEUE_LENGTH-1;
! p& c( o! E3 t# l  Z$ q/ z! y9 N5 x        }5 N! T, \3 b: C3 e1 @, d" K  C, d  S; \

- S( t1 G! z' E- e5 }1 c6 u        while( exqueue.wrptr != exqueue.rdptr ) {4 q+ \4 v" I* h, l% T* d, A3 J
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
# G; B5 T' R$ N                exqueue.rdptr++;4 R4 o4 y: B3 r+ z
                exqueue.rdptr&=QUEUE_LENGTH-1;9 l6 h1 F) s1 A: S& @* N% W
        }8 h' v8 d8 I  f" U* R% A' u7 \6 y
}
  H- F9 Z1 {/ [/ l: l
. J* p  T$ h& I  ?8 u0 ]void        APU::SoundSetup()
7 o0 g( t; u% n* f) X3 c# T{
4 u) j6 j* u# d  `        FLOAT        fClock = nes->nescfg->CpuClock;. |7 K4 \5 Y" R8 P
        INT        nRate = (INT)Config.sound.nRate;% Y* y, A# ?# n6 ]
        internal.Setup( fClock, nRate );
7 C1 x' `. r! f+ h        vrc6.Setup( fClock, nRate );
. ?4 n) i: T+ n* W  A* L% J        vrc7.Setup( fClock, nRate );
+ H. e, \9 i& U$ F& |* d4 M        mmc5.Setup( fClock, nRate );
; h. j, a7 Z2 ]# b  s, C, _        fds.Setup ( fClock, nRate );" o$ _2 R- r; a; b; P  p; S2 O
        n106.Setup( fClock, nRate );/ U: H, y& Y) z) l  B9 b
        fme7.Setup( fClock, nRate );& L% _2 `! |5 i( w7 c/ t, d
}) k% ~: Q$ K1 G* p0 ?3 a0 n" c
0 y" Q/ J  _7 `) Q) ~* v
void        APU::Reset(). f. Y9 w% d/ @$ O3 y4 H9 D6 u
{
2 {" \, ?, Z8 }, V* c        ZEROMEMORY( &queue, sizeof(queue) );
' n1 r/ P) u- o        ZEROMEMORY( &exqueue, sizeof(exqueue) );
8 N  g. r5 S' R# `* K) w4 x
" M( `  t5 `- _0 M9 d. ?5 H2 o        elapsed_time = 0;- l1 Y2 j' t4 H; ~

6 o: s5 f9 c' A. z% o9 @        FLOAT        fClock = nes->nescfg->CpuClock;
7 T/ a6 W7 a/ a% q3 f% @8 Y' ?0 g        INT        nRate = (INT)Config.sound.nRate;
0 x0 u- Z0 V: T0 X& a: Y5 B" z        internal.Reset( fClock, nRate );
: R( [  ?0 r4 ?# I& w, g5 W% X2 L        vrc6.Reset( fClock, nRate );' v; ?8 K# s/ q5 \
        vrc7.Reset( fClock, nRate );, d  T7 p7 \4 Z9 r
        mmc5.Reset( fClock, nRate );
# c5 P) ~6 D+ A/ u# Y* N' k        fds.Reset ( fClock, nRate );+ U2 ^; t; R" ^& B/ C2 C
        n106.Reset( fClock, nRate );
( Q4 [- N  A2 Q0 W9 C        fme7.Reset( fClock, nRate );
- ^. x4 @" a* J% i# y. X
5 y% X% [! j* o9 k  i% m0 C  r& m: z        SoundSetup();: r- S2 O) M5 r; z( L6 T( H& H5 p
}
2 o) ~4 ]; m# b& @( X
5 O+ s, H( C& ovoid        APU::SelectExSound( BYTE data )# e& s) c( \7 S7 ]/ F) O
{: M* C% |! U2 V9 d
        exsound_select = data;  ]5 h7 ?; e" n
}  p# A( J+ V; Q8 ^$ @5 \
' f* e: e( {' K- K7 L" b
BYTE        APU::Read( WORD addr )
# a/ K! M  ~, E/ ^& ~6 s{
" Z9 U8 C/ ]. V' C3 |' j# W, B( I8 E        return        internal.SyncRead( addr );
8 h7 k$ N- Z, T6 i" m9 L% w}; T* G. p5 {- _# F8 Z  a

) Q8 @6 g6 ~) n! |$ A6 L/ z% j) _void        APU::Write( WORD addr, BYTE data )
* j7 E* J- r* i8 f$ m8 d4 P4 j{6 H* p1 v; W- C3 e
        // $4018偼VirtuaNES屌桳億乕僩" l. @7 J: V# c% ^# m% r! `" S  b
        if( addr >= 0x4000 && addr <= 0x401F ) {7 L' ]8 R, A/ T: e5 D7 j
                internal.SyncWrite( addr, data );
- w5 v2 S0 e6 n  g                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ L7 m) A4 ?% y# W        }
% {$ h  S: R4 T1 ~/ W3 Y}
0 D" n) I! x4 l, @6 y; W8 U
- v) Y5 C: ?- m* W- fBYTE        APU::ExRead( WORD addr )
0 p& G/ ]) D% |4 I7 x{! w. i2 J& t9 Z8 ^* y, q9 a$ Y
BYTE        data = 0;) k; u( E1 D1 b# t

" @0 z: B/ {. P: L/ s9 s  z        if( exsound_select & 0x10 ) {
1 N& P! b' {0 Q                if( addr == 0x4800 ) {
2 D+ u7 R) S% S" p! q9 C* h                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 |8 ]$ B! Y0 w  K) ]2 D5 _$ X                }
8 h# ~. h: p+ }. u" ]& ~1 O        }
' Y  ^; \" \  o5 t2 x! R1 `        if( exsound_select & 0x04 ) {
. d- u8 a$ \5 Q( o; _3 o# {  a                if( addr >= 0x4040 && addr < 0x4100 ) {
, {/ J! R- \  t9 ^# y: V                        data = fds.SyncRead( addr );; Z5 S+ x2 Y5 s- D
                }
0 a7 L& H  ~; Z9 ]        }) f1 m3 H8 A' @1 M% ?+ ^
        if( exsound_select & 0x08 ) {
% \+ z+ A5 \/ l9 i$ x$ E" |! I                if( addr >= 0x5000 && addr <= 0x5015 ) {, D% p/ g% d0 G8 b
                        data = mmc5.SyncRead( addr );
9 J5 C5 d$ i1 P4 A* M2 P% q                }
; N# k, J( a" w# B  e- G5 b        }
. ]6 W) j' c7 m. {, r5 a; l' a# ~
! x5 b+ Y# W9 R        return        data;8 Y" C1 y8 y, v# I- q( O! P2 N
}3 F+ C4 v# C( I/ o0 D
* S6 ]  P/ V7 a1 h, U
void        APU::ExWrite( WORD addr, BYTE data )3 @9 ]+ f* r2 `% ^8 X% g7 A# y) |
{
' j, |) h. s! o  x9 C# _        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( C+ r7 T! t& F3 l. l& u' Y. t; s& }
        if( exsound_select & 0x04 ) {
! p) w* i' g/ j9 y9 S                if( addr >= 0x4040 && addr < 0x4100 ) {
7 O6 d5 W5 T6 Y0 Z                        fds.SyncWrite( addr, data );
. `% `; [  v6 _4 l1 P                }7 X! _' _3 l: s
        }
/ i6 G; [8 I' i1 `! }
% ~% y+ n* m% w: ~5 q1 D: B- n        if( exsound_select & 0x08 ) {' q6 F4 W% T$ }) m2 I' ?6 V) m
                if( addr >= 0x5000 && addr <= 0x5015 ) {; i/ f2 V2 G' {* y
                        mmc5.SyncWrite( addr, data );
$ f0 a7 t  k1 L                }
7 J" g+ I* z. i4 d        }% y7 \6 ^7 P' s3 Y5 ^
}
, S  E) T/ [- H& b" Q$ Z( m
# c* K! Y3 i6 C* N/ evoid        APU::Sync()
' f( n5 H  a4 ~9 f9 Z. a{
1 `: p3 @( G0 J# O4 l. b}% G$ }: e% e4 d7 m. K7 d
3 \" @! @" o1 n
void        APU::SyncDPCM( INT cycles )
* P: i' C7 J! S2 u: F- t+ f4 g8 e8 _{9 z! r' [3 l: T$ r
        internal.Sync( cycles );
0 g  q$ A3 P% k# q8 X$ [6 i* ]) ~. g+ S: S6 }) w+ N. I: R$ ^
        if( exsound_select & 0x04 ) {
- u4 b# p" O$ d3 `                fds.Sync( cycles );7 n* U% t% \  a7 ]% H
        }+ U4 q0 l# L# t: e0 j+ e
        if( exsound_select & 0x08 ) {* y' d6 U, C; A9 g, Y) j
                mmc5.Sync( cycles );0 r- W+ l  v5 m6 M0 x
        }
" Q' S7 H' W% E2 I}1 f* w' r3 p+ q: b3 L3 U! j
) E1 v" `3 [6 K! C- n+ q" g0 u
void        APU::WriteProcess( WORD addr, BYTE data )2 |( q+ l9 p* l3 h2 r
{
2 G) o/ e3 c1 O* D8 m5 {        // $4018偼VirtuaNES屌桳億乕僩
4 ^7 d+ r3 i' m) r) |; A        if( addr >= 0x4000 && addr <= 0x401F ) {
7 ?# a- A8 R, \  {9 Q6 O                internal.Write( addr, data );
3 H6 ]3 W( g& W* [        }
) x8 j% y7 M! E, x. G! @}
4 Z+ y* {5 i7 Q4 h1 Y/ ~
$ k8 }6 \5 h. N. [. U2 Ivoid        APU::WriteExProcess( WORD addr, BYTE data )7 d" w/ O$ O9 ^' z& O5 D2 `
{* s& V& t6 x" }# T- j1 T
        if( exsound_select & 0x01 ) {
7 |$ D( \8 [+ Q# ~4 O/ E7 M                vrc6.Write( addr, data );
2 \/ l4 ]; {6 l2 j! K. J        }
/ \- g6 R2 I$ y/ _9 g6 Y        if( exsound_select & 0x02 ) {: {; ~7 k* Y3 O2 U
                vrc7.Write( addr, data );/ `& b; _+ T! n/ z" }
        }
) L: k. M: c+ R0 @        if( exsound_select & 0x04 ) {
) s: E7 y3 H5 s2 Q                fds.Write( addr, data );
7 q( V0 j6 L' o) J0 Y1 ?0 P& c  T        }' I1 A1 E( D8 v5 i. G* r) O) y# i
        if( exsound_select & 0x08 ) {
* V- r% @9 S0 O6 s( l( m" P$ k                mmc5.Write( addr, data );# g2 W" N0 o8 P  B! t: y' ]% U
        }4 I/ G" r# A8 r8 S. ^) D, ?# M
        if( exsound_select & 0x10 ) {
  k4 Q% O9 K8 [% [                if( addr == 0x0000 ) {( X1 P/ {. H2 z4 a# m
                        BYTE        dummy = n106.Read( addr );. d# }$ G: w( Q
                } else {
) v7 K% c' G$ x4 s; y% L                        n106.Write( addr, data );6 C1 b5 [+ P' N1 f* |6 u/ u* I
                }
4 |/ _5 j- d0 a7 S% e        }( y1 ~2 {3 n: i
        if( exsound_select & 0x20 ) {, g7 z  X. h' D' Z
                fme7.Write( addr, data );3 _3 M6 m$ ^  _! K
        }. v. {& b) c  Q" _+ P( n
}0 L! E3 m8 D; R
# ~  o0 m# H& y
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )' r# V; l* c1 i" s
{$ J; u! y, A" u1 \2 f9 H- i
INT        nBits = Config.sound.nBits;
% w& d7 {: b: Q7 f3 ^  K* y" i- xDWORD        dwLength = dwSize / (nBits/8);0 y5 \% a3 }: N/ }4 i  d
INT        output;
+ A, C/ K% N7 a  BQUEUEDATA q;
( J- {+ Y% x3 c, d5 SDWORD        writetime;
2 ^3 q9 P& L- e) `7 C. g7 B* w" X
4 y( y$ P! [$ s+ p3 Z: zLPSHORT        pSoundBuf = m_SoundBuffer;
* u  t5 {7 c) C  xINT        nCcount = 0;' Q' ?& k" r( m4 K
; D! v- b. `) @
INT        nFilterType = Config.sound.nFilterType;; k( r  e, ^# `7 p, w9 D  I

( O0 k' ?1 N( q9 d3 M  d        if( !Config.sound.bEnable ) {* J0 Z0 `$ e0 Q  J
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" E& f! g" }1 b2 Y6 l# h1 p( a                return;
8 n2 r! S. v+ d- P" z        }
9 \! O* u" v4 B# l
: B. L" t# k( n7 u1 K) B        // Volume setup9 C, m2 I0 ]& H5 c; B( J
        //  0:Master" g' w9 i- z$ |" o/ C% v
        //  1:Rectangle 16 G, m5 L# A$ l( ?3 D; U
        //  2:Rectangle 2+ _% k8 `* ~! E% W7 S- T3 R
        //  3:Triangle
) K8 I& h& k4 ^- @. @# z; R; ^% }        //  4:Noise
; d5 ?7 B* Z  t! Z+ e% b' i4 n) q        //  5:DPCM
, H" F- b/ t% U- h6 ]        //  6:VRC6
2 \! p) N2 V2 h* T9 \1 c        //  7:VRC7# b& B) t6 J8 [3 N1 d& [
        //  8:FDS
7 \- K3 ^" e" Z' f! T* G: S2 R        //  9:MMC5& c3 T! T# R* `, Q! D( ^: |# q; C
        // 10:N106
1 H- i5 |1 f! E. \( \7 f4 `; R4 J        // 11:FME7
1 [* h4 C0 @& z3 R* c; W) o' x- S1 N        INT        vol[24];" h" z/ a& _$ s6 C+ {/ j& J
        BOOL*        bMute = m_bMute;
0 _( g4 i$ Z1 P3 x3 r8 [        SHORT*        nVolume = Config.sound.nVolume;# X1 _' Z; g2 z  e9 W3 v

4 R4 V, f3 }7 C% M/ S/ x7 E        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
0 n% M# ~& V, c% [$ V5 w( H& R
' A- T7 K; o9 q        // Internal
; P# w1 a( G  g7 w1 W' `        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;6 D3 i1 y, ~* d; H, d  @6 z) n
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( A/ E4 u: Z" @( M' t2 d
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 s; E% A1 A6 s- U  o$ Y& U6 ?: D: b
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 a3 `3 d$ W3 k" j/ K
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;3 ?) R0 f! o! V$ J- A
$ j0 ~9 H" h6 ]' Y% j3 l
        // VRC62 C; m  e  u( O0 i) n6 {
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ ?/ k6 j5 h4 i' Y8 ?% W        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. q- V0 t% h3 w
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 r; A; Q. }0 x8 l+ j( F, ?" r) q# h( B  R$ b( N: y
        // VRC78 f5 h1 d& u$ z, y8 G0 C5 @
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; p0 d6 s( U* U& U! y& Z

' I$ Z  R/ o; g- K4 {        // FDS% P5 M5 X4 M2 ?( E) L8 k
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;' m: p6 W- T( G; l' ]
/ H' r  U! R! N0 u& I2 A6 f
        // MMC5
% l& v: F) U8 w6 R) x5 L        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  V' c3 O- U3 ~  y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 h% `3 S6 H# N) R* {4 V5 Q        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" b( R; S: |# S' ?/ G% v- \7 w# Z5 P- a
        // N106
* a2 r: O3 ]6 k$ A" L        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& A9 @7 j* W+ _) R; C, J9 p0 L
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* `8 y  {/ x; M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- `. l4 q, h& v; ]        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 {5 m1 z7 w* T+ L5 M4 w' O0 P
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 U: I8 w& }% t
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 s" ^. X% g3 w" c        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  C, s0 {9 O% @& X3 n: _. U4 K8 `
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 X2 d* r8 M; z; u
& j, p3 q  X9 ^/ A        // FME7
5 l& U$ v0 t; r2 [6 z2 D7 _        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 q4 j# j( Q- \% H1 {$ N3 X        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 C  |% V: W1 X3 ^8 e% z- M        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 @+ v$ V8 r$ }8 d( y

6 _2 w9 d3 M; I) A% L//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% {& \: E* I7 C9 s! {& P) ~0 q        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' j6 x/ u5 o, ?: V0 l( @0 Y" y0 b
5 v% r4 j& f9 f. a6 u6 |        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
2 v3 x" R& {- e        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
6 k! G1 a. ^+ e                QueueFlush();  F" H6 e7 `: t# W3 B3 [" D# o
        }
) k' e) }8 @# D9 ]: b: N& B
2 X  ~4 f0 c) ^; k        while( dwLength-- ) {8 f) n7 W% h! m8 ~) D
                writetime = (DWORD)elapsed_time;
3 V/ Z  q0 `4 z, ^1 Z/ _8 k" ]) g; }0 ^  c# L0 P. {2 Y
                while( GetQueue( writetime, q ) ) {
+ N2 j& e7 P1 K6 ^2 w+ Y                        WriteProcess( q.addr, q.data );
4 y$ A. p, n# X' q' B, L                }8 S* k7 l: z, u1 e, L

1 p9 U+ J# Y, M6 x& C                while( GetExQueue( writetime, q ) ) {- R5 p2 s2 Z: R4 n. x; S
                        WriteExProcess( q.addr, q.data );7 T) g$ z4 H  K6 t
                }
! x, u: ?  ]2 A+ @- u) F
. p! I: f3 R' q5 w9 R4 u8 S* _4 Y                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
0 a( K$ ]8 }8 D3 d- A2 ]* f/ k) f                output = 0;
4 `! y+ s$ l2 X                output += internal.Process( 0 )*vol[0];+ p0 J+ r# @3 R0 E( Q9 p: H
                output += internal.Process( 1 )*vol[1];3 _% R. B1 [# p: ^" D! o3 @
                output += internal.Process( 2 )*vol[2];
" |0 \+ j. ~# j6 h; z. _: E3 \                output += internal.Process( 3 )*vol[3];
; L- G- W0 V. ^+ b1 K/ c                output += internal.Process( 4 )*vol[4];( a  f' C& D8 o) Z0 d  B
& |+ N/ L0 V/ @) ~  }
                if( exsound_select & 0x01 ) {+ y3 k5 L5 G( y/ W' o, w
                        output += vrc6.Process( 0 )*vol[5];
% W* z6 h+ }- N5 c6 e6 _                        output += vrc6.Process( 1 )*vol[6];2 p6 [0 S$ P5 D
                        output += vrc6.Process( 2 )*vol[7];
/ c) V3 O* k- A                }
5 \0 x- p. F. o; \; K9 S; I% Y                if( exsound_select & 0x02 ) {
; x3 y5 l/ t; m! l# ?                        output += vrc7.Process( 0 )*vol[8];2 f3 w& l8 T: G& J
                }
) Z- O, {& Z9 T% B                if( exsound_select & 0x04 ) {) d& x1 V2 O1 ?) R4 c4 T* H
                        output += fds.Process( 0 )*vol[9];
) V8 }; \! V7 ~/ r( Z                }& I' d, |$ g  ]) P: d
                if( exsound_select & 0x08 ) {, N  m" q$ I' M! ~+ p0 Z
                        output += mmc5.Process( 0 )*vol[10];
$ }: T" `6 d" Z9 q4 L- k                        output += mmc5.Process( 1 )*vol[11];
' K, N$ j& h  K                        output += mmc5.Process( 2 )*vol[12];
1 ]- E$ y$ }3 U* Q% ^3 _                }
! Z9 o, f0 E0 Q/ g, X8 o                if( exsound_select & 0x10 ) {9 A: i; e: N! l- W
                        output += n106.Process( 0 )*vol[13];: i! ^3 s; {- T* v& m: f; c1 C
                        output += n106.Process( 1 )*vol[14];9 O, K9 f( q/ @
                        output += n106.Process( 2 )*vol[15];+ {. o" U2 _: u' P+ J2 y
                        output += n106.Process( 3 )*vol[16];
; Q7 c9 w: _$ X  p3 ^+ m- T                        output += n106.Process( 4 )*vol[17];
- g9 k% s! ?5 l# \4 _$ g" d                        output += n106.Process( 5 )*vol[18];6 I  R" V( `' q( Y7 a
                        output += n106.Process( 6 )*vol[19];
$ Y# ]+ A5 M2 v9 Y* N  x% W                        output += n106.Process( 7 )*vol[20];- r! L0 x# U& ]6 K: d
                }
9 Z7 U8 X) C! M; `                if( exsound_select & 0x20 ) {0 n  }, |4 |$ D! h& ~6 d. Y) Q
                        fme7.Process( 3 );        // Envelope & Noise. A/ Q: E6 n3 {% F3 v
                        output += fme7.Process( 0 )*vol[21];6 S2 X  C# b7 Y" K, n" P
                        output += fme7.Process( 1 )*vol[22];
2 Z7 @5 `* u1 R                        output += fme7.Process( 2 )*vol[23];
9 C& Q3 S0 [  D                }/ r7 e, K( ]1 j' R: u/ V. V

8 O! |7 R7 b- ?7 F$ K  ]; a                output >>= 8;
4 r% m" v5 p5 M! b2 W3 Y# A
- z4 n9 a: K' u                if( nFilterType == 1 ) {7 p* I# U8 J; p; j
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
! e9 Q4 S: X$ Q5 X7 E  K                        output = (lowpass_filter[0]+output)/2;
4 M& k0 e  K2 r, y  j                        lowpass_filter[0] = output;, Z0 A3 l: i, ]2 n' ~0 a
                } else if( nFilterType == 2 ) {
, H8 t) x0 h- S                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)4 S# G+ U! o5 M1 o2 q/ j, R
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- u  a: g1 J) x0 B4 p. g  d                        lowpass_filter[1] = lowpass_filter[0];
* J* D5 v4 a  B% o. l2 u. r                        lowpass_filter[0] = output;
- j: a0 }# F- B+ M  T4 [  U                } else if( nFilterType == 3 ) {' v$ e( `# }7 L8 |2 f: m
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 v1 \+ _) P3 }3 W                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
  \8 \8 o6 z& A2 y% c# c                        lowpass_filter[2] = lowpass_filter[1];0 e/ L' g9 G: M4 @; @
                        lowpass_filter[1] = lowpass_filter[0];
! v% {, k5 Q3 n2 c% u" l/ ?& {                        lowpass_filter[0] = output;
+ D7 Q( z: n, O# [# E                } else if( nFilterType == 4 ) {
' c# O4 q# Z$ r& @% y! U                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
" h& @  I, p" Y6 j1 {                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
$ A8 G: x; u) Y9 |' A' M                        lowpass_filter[1] = lowpass_filter[0];
/ h0 k/ O3 C% V  v2 g                        lowpass_filter[0] = output;' I, f1 V% J' Q" K5 D- T$ [( B
                }1 F2 s# l5 q" \/ g! U' Q
5 ^( R4 u2 {: w3 h) t2 T/ i/ _
#if        0
5 K6 |, L; I+ X' a, E: M' i                // DC惉暘偺僇僢僩
7 q" W; W; F1 i; Q$ a                {: X/ e8 e4 Y2 b, |: y
                static double ave = 0.0, max=0.0, min=0.0;7 O! y/ k& N6 ^8 t. |# u
                double delta;- }4 W7 j) [2 H5 @+ [" }" w/ w3 \
                delta = (max-min)/32768.0;
1 u+ c6 H' }0 w2 E                max -= delta;5 N+ |, I) L. H: }/ o+ @0 U
                min += delta;
% f' q1 m, p( n' E8 C                if( output > max ) max = output;5 Y( I0 X: n0 C
                if( output < min ) min = output;% ]% [3 ?& D6 ~  |) I
                ave -= ave/1024.0;! m$ A, C1 f6 C
                ave += (max+min)/2048.0;
; r4 Z3 ?  \: H! `$ d' k- M, u                output -= (INT)ave;; b. V$ |0 Y/ u9 o" F+ V0 }% a
                }
0 g! ~4 G) ~) U* T$ i#endif
5 A4 j0 r/ Y* m% R$ ~#if        10 i* o& {. O8 w! M, z- V
                // DC惉暘偺僇僢僩(HPF TEST)
7 ?7 v. U1 D4 A" ]                {# k) t/ k4 U" r1 D( C2 D! m
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
, n* y3 Z+ d& _4 L" D0 h4 U                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( U  O9 @# u, q  V# l) \                double        cutoff = cutofftemp/(double)Config.sound.nRate;  r' I/ I2 Q1 @& i
                static        double        tmp = 0.0;/ O1 N1 C& B1 p4 Y$ y' [6 V
                double        in, out;& g8 Y) ?1 y8 V7 z: P% p
: V. a6 E9 b# f$ @8 j2 Q
                in = (double)output;
5 O7 i% k  J9 G. k) p                out = (in - tmp);% M9 T7 ]+ H& p- ^
                tmp = tmp + cutoff * out;9 M% _: y# ]" E6 Q8 Z

- b# J# h; `; H# V9 `3 H                output = (INT)out;
1 S7 i! ~: l. }3 G2 f: @: Y  n                }
# V1 {9 L9 D9 g7 w0 L% W. {, {#endif
4 n: D1 t7 H9 y: }#if        0) K5 X1 O4 G+ N0 {" G: d# Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' m+ l: h8 v. \- c! K- t                {
7 |0 ]6 t9 J  X% g                INT        diff = abs(output-last_data);! z% I  D# m; R2 C  s% z9 n
                if( diff > 0x4000 ) {
; O6 X- r2 x% P( f, V( x                        output /= 4;
  D: x+ n) W6 k2 ~                } else
2 D' c3 T: l9 ^                if( diff > 0x3000 ) {" S4 ?0 q8 C7 P- G' G
                        output /= 3;: z5 ?/ Z5 [3 |
                } else
, `$ x6 l0 g" z) x                if( diff > 0x2000 ) {
5 g  e9 G( G9 P4 h! A$ B                        output /= 2;
4 A) F; T/ X8 v* [6 A; o                }
/ b; u& u& _7 Q) D. ]  ^4 [1 A                last_data = output;: ?' V/ ~& \$ A5 m$ ]( M
                }
8 A# |( \) c1 G$ U* P#endif7 U, b* ?! Y5 N; a* c
                // Limit% W6 m' L: h: D/ _. f( |
                if( output > 0x7FFF ) {- m# G3 J8 j8 T
                        output = 0x7FFF;
% ^% l5 p4 ~  s3 Q; e                } else if( output < -0x8000 ) {
/ A' g! V7 i/ H! [2 c3 Y2 y. S  [, f                        output = -0x8000;
- G' P' S+ N* c; V3 K                }
- s  J# q! \& }
9 z0 [( S2 N3 n                if( nBits != 8 ) {
+ N- L- T7 J0 N2 B" q) ?                        *(SHORT*)lpBuffer = (SHORT)output;$ V. z* `- C0 C2 B9 e7 [1 r
                        lpBuffer += sizeof(SHORT);
( |- ~/ q9 T0 i( K8 b                } else {
/ c, ]& ?0 g8 `  \" D: |* M1 U' I                        *lpBuffer++ = (output>>8)^0x80;* |8 C$ ^* G3 R; ^- O
                }5 u) n* S: }5 K  a; ], z; T' S' n
! B  f! u" \( H
                if( nCcount < 0x0100 )
7 |5 `6 B+ a5 E' V& K                        pSoundBuf[nCcount++] = (SHORT)output;% p& D6 Q% \4 @
/ F( u5 t4 A% ?8 @$ J/ `0 f
//                elapsedtime += cycle_rate;$ V( S* I7 B5 K; `& b
                elapsed_time += cycle_rate;
6 Q0 y3 u0 j9 e3 h$ g; X( b' m        }0 l; B! h2 D% R7 W# e7 A5 F

5 u0 w% ^2 Z$ i#if        1$ r; ^; D% s+ @0 l; @1 K
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {% q* y6 F1 k6 Z+ S
                elapsed_time = nes->cpu->GetTotalCycles();3 I8 P9 g' ?0 Q; Y% _
        }* a+ [7 M" f! W5 W  P
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 Z; I" ^7 R5 _6 v9 s! h) c
                elapsed_time = nes->cpu->GetTotalCycles();
" i8 s8 l, i+ i2 m        }! [2 \9 Z7 E# I8 d
#else4 F3 G2 v' w! S4 i
        elapsed_time = nes->cpu->GetTotalCycles();
1 i4 L4 X& s" B# w1 @#endif
* [- D) {6 r  F) q$ n) m}
! Y! X5 W6 O/ x1 {; _$ b' P' ~% J) S2 Z! R& t3 [) C) w
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 @1 X! @, _2 G' C& v" nINT        APU::GetChannelFrequency( INT no )
) _8 o$ y5 }) [* R{
5 }7 ^: A) D& O( t. H5 X  S        if( !m_bMute[0] )
) J/ Z" M5 \8 J# A. t8 \0 i* C                return        0;
1 i/ g" ]7 Y, |% m2 D8 s8 w$ O3 a% V  R2 S
        // Internal
+ C1 ~! |1 A; [        if( no < 5 ) {& X: D1 p0 _* E1 N( J# p8 c: n' c
                return        m_bMute[no+1]?internal.GetFreq( no ):0;$ z& \1 z" ~( ?) z& [' `$ \, G
        }
: A# c2 \* Z9 o3 Y$ D        // VRC6& t( h6 T2 h- P
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
( \. |4 U) Q$ p4 r9 v; K( t; @                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;8 k2 a8 C( T) s3 @: r
        }8 M, P2 Z" g' Q2 |3 y) t0 p
        // FDS" C# a  X4 }7 B9 V& M
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ i5 r% V# k( N                return        m_bMute[6]?fds.GetFreq( 0 ):0;8 E8 w6 P- C) Z9 y' a: n2 h1 O- o9 g
        }
5 Z' |, D6 J- d0 I( O* n% k: d        // MMC5
+ W# }/ q! T$ I4 z        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
: r4 H' W& ~% j8 B0 Q/ H! O1 M8 Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
8 k( e! w. X/ g+ C* K0 ^9 \- _6 G        }/ D  A5 H7 e9 T1 E8 L& V
        // N1060 i, f0 t; v- v& V
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 |" T4 ]! C! k" j                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;- g8 L4 ~7 C" V% ]- u3 ?) z  K/ Y
        }
& B$ W$ L; {+ {" g/ ~8 _1 q        // FME7, C# s4 t% Z  o7 J/ P5 x1 a' E
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# b( d+ e$ K6 s2 z                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;6 i6 k2 K* _" |: f: g
        }3 w' W9 C7 a  W$ F
        // VRC7
0 o: {  ^0 f9 e1 b7 }4 B" [        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
& J. R" Q& ?3 Z7 Y2 S9 ?# d7 Y                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;" a; S' B' `9 R; \
        }1 P7 A  {! J' ^  B* w
        return        0;
" |: q4 h6 z) l}
: k/ b0 V/ S. Q+ i  W, d( h
4 D2 c# P3 k6 Y. E: j1 L// State Save/Load5 y- j. ]  H! z7 [) \5 q. n
void        APU::SaveState( LPBYTE p )
& V( Q0 M5 r* M; {& r{# @+ ~9 a6 B! _6 x3 K
#ifdef        _DEBUG2 Q+ M8 z- ?( k7 x# w% D
LPBYTE        pold = p;
  Q; x+ p: c2 v/ D#endif
& D  K; i* |# r
1 P+ s1 j% F0 c! R: h0 B        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% T7 l3 h/ C2 S        QueueFlush();9 @; K1 [% P" l: R
; \& V* z' M' j. C2 E  F
        internal.SaveState( p );
* W# c: t$ g2 d1 Z% d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; b) p: Z; I) E, \2 r
* j0 r( C7 A, u
        // VRC6  `! O. y: y5 v/ q+ |' M) M( _6 W
        if( exsound_select & 0x01 ) {  C3 @  E4 C1 Y; V
                vrc6.SaveState( p );, ]+ R1 C) m  n) u
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 I" m/ d/ \1 R. j1 Z) v& _4 K2 @        }6 f- u$ M# K3 b& O1 `
        // VRC7 (not support)7 U, j7 d. q$ A, b- Z5 _  R
        if( exsound_select & 0x02 ) {
2 R6 H) d" W. U' F                vrc7.SaveState( p );
( l& h, Z5 E4 V# }. r* P                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 o. Z% @7 J1 ?9 w0 k& C' b# G
        }$ N& \6 x1 x/ B: Y
        // FDS
  {, }0 \+ N+ f4 ]4 {# `: v        if( exsound_select & 0x04 ) {
: a0 _/ {1 G/ |, [5 V                fds.SaveState( p );
& ?: s. y' Y  ~- R" s2 H3 G                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 h) B% I5 N8 `6 z
        }
/ [2 [, k0 m1 n* _        // MMC55 D6 T  R! E+ u
        if( exsound_select & 0x08 ) {7 P# g9 |3 I: Y' y
                mmc5.SaveState( p );
9 X3 O5 O1 J. v. m3 \4 ]                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 f2 H2 |. P' V7 \        }
1 M- r& z) M. {/ G! l9 i& _        // N106
/ R& B9 x- S2 l" A; C        if( exsound_select & 0x10 ) {& h) D7 R+ k  r& y4 O  K
                n106.SaveState( p );
5 w1 O8 L. ?! c; \4 e; Z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% G+ y2 M/ q% P" I! M        }' o- G- K9 y! ?$ i  R0 |
        // FME7- n& L& O1 G1 `& ]5 ^- R0 f
        if( exsound_select & 0x20 ) {* ^4 ^# G( `5 N* e; i( S
                fme7.SaveState( p );' {7 G9 ~+ G. n
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: c. `! W4 O! K6 }% l
        }
8 u' O; t3 N& L7 c& W! ], ?$ B; s: C4 X- Y3 `$ L& P
#ifdef        _DEBUG1 O+ G0 {: ~0 o) [9 l% {: w
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );/ T- G! j( O" \/ D6 A
#endif
: w# i1 f' |$ S; Q& f; {" j( g}
3 m4 C2 n, t3 X! _! I* K. A8 q" g
9 O# f& c& x2 I# X; K7 ~+ A1 G2 @void        APU::LoadState( LPBYTE p )9 l) A( U2 e% J2 e/ W9 p0 M' y: k- r
{
- i1 S9 |$ f1 P0 k        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
# Q9 f9 R+ ?! `        QueueClear();1 I$ g, o( B+ t! [( o$ j: ?
0 l3 b9 v2 y) c4 y$ W/ Q3 Q
        internal.LoadState( p );
+ @: |6 e" V0 {. A+ f6 ~! m        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: j5 m/ j6 z; Z2 s$ l2 |( t$ N# b% S& Y3 j5 T5 x
        // VRC6' V3 r. J4 O8 C# D
        if( exsound_select & 0x01 ) {
7 t3 r+ I* s$ ^6 \, m3 ?+ V+ }                vrc6.LoadState( p );& |+ U/ K8 t/ {3 m. u2 p
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& U$ Y6 }  m% w# u        }0 L/ U: O: k0 \4 z+ r* ?
        // VRC7 (not support)" W8 E; w$ t' A. M' s
        if( exsound_select & 0x02 ) {3 O9 C- ^- @' M
                vrc7.LoadState( p );. I9 U7 E! }- R' p& V+ ~
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% `0 U  T$ [/ P4 Y# M' E3 N
        }
3 \( ?" W2 {: u- `8 P) Z. j        // FDS
6 _$ O1 }$ d& B% t* s3 A. j        if( exsound_select & 0x04 ) {. X/ J! _) l( |) o3 e
                fds.LoadState( p );+ M; R5 }2 C5 J! j, Y, K
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 k- X) ]8 r7 t. H. w  e6 ^' \# \4 Q        }. K5 F/ b/ m9 |- S. W7 ^
        // MMC5. ~. d1 O% N/ V9 y) G! O9 Q* a
        if( exsound_select & 0x08 ) {
. _# p  f% b7 b7 e0 z' w2 @  p                mmc5.LoadState( p );
; ]# B, i, `; c& V" N6 a$ ^                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 \' w5 J" S; ?* X& x        }
4 @2 Q, q- u- I9 j        // N106
3 k- m( }- F8 w: D* F0 n        if( exsound_select & 0x10 ) {
3 E4 D! T. ^4 O) X* D% \$ f                n106.LoadState( p );# f( ]4 [0 Z0 |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 E! n" e, c: g# ^
        }
8 ~9 z! h6 ]4 m& j' _: k9 p- q# O        // FME7
9 a# X# c  @6 S0 c        if( exsound_select & 0x20 ) {
8 {! Q. @2 D  h* H6 ?                fme7.LoadState( p );
( L. s! q" m' p% Q% @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 z1 A; T: P; K6 R% W
        }
" H$ l# I' h! Q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, Q6 ]! D- g4 z2 k1 H可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。% R) O" J& K1 ^$ b
感激不尽~~

# [$ ~8 b$ ?+ f0 S, m恩 我對模擬器不是很有研究,
1 K" t, X# Z: F2 @" Y9 a4 d& D# p4 r雖然要了解源碼內容,可能不是很困難,
" M# p6 M5 N2 j" \: x" h不過還是要花時間,個人目前蠻忙碌的。; H* [# X9 E1 @  L* X

2 t0 Y/ Z* d2 t給你一個朋友的MSN,你可以跟他討論看看,
( y( v! [, f& s' |6 ^. G3 g他本身是程式設計師,也對FC模擬器很有興趣。7 ^2 a5 V! i4 [. d6 e
0 e7 y4 J9 {: d/ V
MSN我就PM到你的信箱了。
6 o7 A& E3 n0 s3 F: }! U; l* l% {! y6 z- W0 C4 j
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
1 S. T" X  S) k; K1 M呵…… 谢过团长大人~~
9 S  t. Q$ S! Y3 [; ]5 |1 A
) Y& L( \  S6 F4 {6 H7 I
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , z& ?2 Z0 h9 ~
团长的朋友都是神,那团长就是神的boss。

6 F# U3 c2 ?2 f( Z6 v哈 不敢當,我只是個平凡人,0 u* s2 X+ u" I* }  a7 U
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# m. V& X+ t% @9 FZYH
: @# T$ }- H& b% s' o7 _QQ:4147343068 k! Z, u  ?, A. x3 A: [2 t% X
Mail:zyh-01@126.com; Z6 D4 h+ s$ v  v0 ^
* i! x0 Q$ m3 X/ S, t+ }* z
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
/ m3 W  T" V. S4 u7 n* y再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 w4 y$ o; I: h$ C' t不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-3 02:51 , Processed in 1.097656 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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