EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* w3 v6 o. l- F
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# a& ~6 Q* t) c+ S: t& _
这里有相应的模拟器源码,就当送给大侠了~~0 w; ]. y5 R8 W4 {
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% F& _# R/ V7 e5 F; h, f能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' j5 x/ r5 H, y% w& \" u& M  M
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
4 f+ ?/ O  K1 q: \这里有相应的模拟器源码,就当送给大侠 ...

% |! w% c( v* k聲音部分(Audoi Process Unit = APU):( {1 y( S+ o) k( p3 T7 v. p1 F
.\NES\APU.cpp- V$ j8 a1 Y1 o( }$ w
.\NES\APU.h2 {- `9 j4 @4 a# M9 \1 \
, \# b* c& _  |
9 g. U0 J" `& J
影像處理部份(Picture Processing Unit = PPU):3 F# u8 L! \% X$ m& u
.\NES\PPU.cpp) V: g* O7 h3 f: Q$ Q
.\NES\PPU.h
5 z6 R% A/ X) e/ c6 [* h( W; Q" F" o5 S2 X
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
, v, @1 c1 C: v3 J. C(由于很多专用术语和算法机理都不明白,所以看不大懂……)( l- G% M, s! b
//////////////////////////////////////////////////////////////////////////
+ l! i% Q5 E6 n" n# W//                                                                      //
( N0 e/ r1 {( i! G//      NES APU core                                                    //# B& P  K( p3 e8 t
//                                                           Norix      //
, m8 ]  h4 i7 @1 }" }//                                               written     2002/06/27 //
1 L1 T/ H. E; V- `7 l//                                               last modify ----/--/-- //
* O/ j1 e: ~. Y5 Z$ Q! V8 `. u3 m% b//////////////////////////////////////////////////////////////////////////8 `$ P# q; K3 U6 r: g2 O
#include "DebugOut.h"
6 ~, F8 m2 o3 F" Z1 R; B& {#include "App.h"
) S3 f( z, Y0 g: ^& Q3 c#include "Config.h"# [* W7 }+ n. N! j% y  q
) M' n! k1 S$ U# a3 A( m) P
#include "nes.h"( o' _$ F! y/ i2 s
#include "mmu.h"+ p3 n% N1 M2 L% O2 x- j, {4 o  W
#include "cpu.h"2 _" N/ p6 H* e  c# H  `9 h
#include "ppu.h"
+ X& H' d+ \2 I: F#include "rom.h"; W' q9 ~0 ?% l4 C9 ~
#include "apu.h"5 w; T3 Q( W  b  d: m  ?4 G) ~2 {% p
# k: q+ e) B9 d7 ~& V; R. k
// Volume adjust
# ~5 {& _# i. C7 O// Internal sounds4 k) }# A' U, a# F9 F
#define        RECTANGLE_VOL        (0x0F0)* V( Z& T1 s: }, x/ h
#define        TRIANGLE_VOL        (0x130)% o; Y9 R# w  i: C( `
#define        NOISE_VOL        (0x0C0)
( Y9 h0 v% x/ H% n#define        DPCM_VOL        (0x0F0)
# q# U" }. u! D" e. a/ A; T// Extra sounds
2 U# t( b$ r4 Z, E# {#define        VRC6_VOL        (0x0F0)$ b0 D+ I( }4 y& Q$ M, {" o
#define        VRC7_VOL        (0x130)* Y6 g9 p$ G3 p. u2 K( {+ I8 Z
#define        FDS_VOL                (0x0F0)! {7 S' t4 h4 n7 h& B
#define        MMC5_VOL        (0x0F0)4 y/ d7 M0 d$ m1 o! c
#define        N106_VOL        (0x088)1 y  f' |( [5 S' ~% J! O4 [, z
#define        FME7_VOL        (0x130)7 M2 x4 S4 `$ x* O9 @, ]- b+ l

4 b, V% x+ t7 T' m5 B- GAPU::APU( NES* parent )4 s  P( W7 O) x; q7 @
{7 |" C% S% R  k
        exsound_select = 0;
+ q; I) [: o5 t5 N; f9 ~. E  m' r3 e- [( H
        nes = parent;+ K; V% o, d# Z, d/ Q. k
        internal.SetParent( parent );
, c: R2 v- B- X8 y, `5 [2 w- U/ v* a8 ~7 U& ]7 m) I; C/ j
        last_data = last_diff = 0;
( B6 @8 Q7 |$ T& U7 B0 I5 b4 Y
8 C/ S% k# D9 f& x- P1 U        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );" [! f& T) U! V7 T5 Q& X. B& s
' H, D0 J' T8 _8 x" O8 N
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- _. q0 B2 X# t% T# F        ZEROMEMORY( &queue, sizeof(queue) );
! q/ w" }* X# P7 N  N2 U4 d        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: u7 w- n, \! y. W+ }' a3 d  |6 [- ~
        for( INT i = 0; i < 16; i++ ) {# A; F$ r+ W7 l4 V+ B) c
                m_bMute = TRUE;
7 ?, s: m. s  ?9 W/ V  r        }+ ?* G) b" b: y; N- d! G
}
: [% a: J( k5 k! u( c% {3 ]; ^1 i  @0 t+ N5 t  \& O
APU::~APU()* g8 w1 J) O, H/ m
{
: ^+ T! k: W9 V9 D2 Q}
+ s% z8 `3 z: {  v4 ?4 Q2 d6 h' o& [- O2 q$ Y$ F" h
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ ^+ s! @  P4 o. G# u( a  @5 O  b/ G{
6 B5 v* F& P1 D  l3 [        queue.data[queue.wrptr].time = writetime;
6 z' H, N6 {; Q6 p6 g        queue.data[queue.wrptr].addr = addr;
; d3 ~5 h' h5 }  o4 f* _4 H        queue.data[queue.wrptr].data = data;7 h- d  ]8 ~' h! X6 }
        queue.wrptr++;9 j5 y! P# h( w5 G, w
        queue.wrptr&=QUEUE_LENGTH-1;2 E) ~! D! s" \# \) X* D7 C
        if( queue.wrptr == queue.rdptr ) {2 d7 H" J# J0 P3 s1 P' E7 H0 K3 ^/ D
                DEBUGOUT( "queue overflow.\n" );
, z  u! E; p6 N$ J/ m        }5 B" M; L8 |5 W# U1 D' h. T
}
3 Y; T' A: h' j) A) s
: b2 R5 Z2 o& h* n% N, x$ jBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
) x2 y& b! j8 j{) u- L; y, u, y" H+ ?/ {
        if( queue.wrptr == queue.rdptr ) {' y6 x8 z, _% V; h
                return        FALSE;: M9 @, F* {7 |1 R; R: ]5 f5 q& ]
        }/ {: W* b' U) D5 X- j  G, g( |0 L
        if( queue.data[queue.rdptr].time <= writetime ) {
5 o  @4 Q1 J7 h: I1 M+ `- D) h                ret = queue.data[queue.rdptr];* H0 A  ?5 [* Y$ ^
                queue.rdptr++;
2 E$ N: d6 d6 z& M) k. d                queue.rdptr&=QUEUE_LENGTH-1;2 V' [  {8 p3 Z+ t: R& f
                return        TRUE;5 o& r6 O, f4 u1 w
        }
( m1 P; Z% r+ ~" `: a        return        FALSE;; E; U+ D# E% j: `2 P
}7 O6 R/ ~- j- }
; S5 n) T6 j& I8 I9 j1 T
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
# {: n' B1 d5 M. r{
4 ~6 y+ O3 v! A4 a        exqueue.data[exqueue.wrptr].time = writetime;  H( }0 l8 s2 `2 X/ v' S9 }1 G
        exqueue.data[exqueue.wrptr].addr = addr;
/ A8 M+ M* `% j1 O        exqueue.data[exqueue.wrptr].data = data;
( D2 \( m, ?1 E6 n3 |5 T        exqueue.wrptr++;
- a+ W! V6 [/ ]0 k& Z9 `        exqueue.wrptr&=QUEUE_LENGTH-1;+ L1 k0 ], }2 L" O4 D6 x0 l
        if( exqueue.wrptr == exqueue.rdptr ) {* N0 Y$ O5 }: q3 F& h& l1 ^
                DEBUGOUT( "exqueue overflow.\n" );" i5 b3 [; z0 {3 p) ?1 U; O
        }
3 _1 f4 `  h$ O}
& i; h) z/ m4 Q5 D. L* A) `
# I, G) A2 Z1 \+ IBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )8 H+ C9 y. k/ M# D7 B8 j& U
{2 l; [3 m/ n+ d+ Y: C* c
        if( exqueue.wrptr == exqueue.rdptr ) {
% E5 ?* _2 P- n' Y: \" ?7 a                return        FALSE;
' T: ^% |# a: |! p3 c4 `2 n! E        }
9 _* O$ t* ]2 i        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
" Y  \1 b8 O1 Z5 s1 z% R                ret = exqueue.data[exqueue.rdptr];
0 S8 e" l1 }6 T2 }                exqueue.rdptr++;# i+ l7 l0 B6 m7 t
                exqueue.rdptr&=QUEUE_LENGTH-1;
) s; b) r$ a9 A8 y$ m# b) M                return        TRUE;# G) @5 f& w4 Y4 B5 U* B* I
        }8 L+ h" ]; e( S# |% p3 _
        return        FALSE;
- j5 C0 Q7 j- K7 o! ]}  t1 a9 i! c2 p4 m' _
4 A- h2 |0 f  ]! a* I
void        APU::QueueClear()
- K; W. ~; a3 W" s) r/ U{
5 c+ r# G; W0 S* M8 J8 C: L  @, k, b        ZEROMEMORY( &queue, sizeof(queue) );% K6 ?" H; r. z. X6 P! k% T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. d5 Q9 L0 z8 p. C}) z/ |" I& j& f
6 s* o& W! w; j# P+ Q" B4 M$ p( l+ b
void        APU::QueueFlush()8 B7 O# f, @' G+ Z1 J) _5 \
{
1 K, L. o+ D% L# q! L        while( queue.wrptr != queue.rdptr ) {
0 m% N. ?. _2 i: T                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
1 c: y0 M( Y, z! ~# e                queue.rdptr++;5 r. G; b) _" _% B' O
                queue.rdptr&=QUEUE_LENGTH-1;
4 W7 y  {3 `0 a, O* L# z- ~        }3 L/ ]0 v$ w8 q1 w" J: }
* u) U: a( @/ h* G" U9 w
        while( exqueue.wrptr != exqueue.rdptr ) {3 R$ `7 M+ H- z/ P! D+ i) L( u
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 w" A+ n8 F$ X4 }4 x& u: A+ f                exqueue.rdptr++;
5 r/ o0 t4 N7 ]0 L# D" v6 t                exqueue.rdptr&=QUEUE_LENGTH-1;1 R( n$ n* N: ]! |) m2 p
        }
' a7 m9 ]( B" r0 E5 L- z}
' g. S+ h9 M" g  m3 y7 Z( m( T+ M' [9 |5 R* t9 z
void        APU::SoundSetup()
% q+ H& M4 f4 f{
! G/ t  j6 A# c& J6 h- v        FLOAT        fClock = nes->nescfg->CpuClock;; c: S/ D& X, a' ?% I7 w$ {
        INT        nRate = (INT)Config.sound.nRate;8 }. ]2 |: ~% a( C' n+ l
        internal.Setup( fClock, nRate );
  f8 J# M- X5 ?* {        vrc6.Setup( fClock, nRate );6 G+ Y1 `- t  D2 ^
        vrc7.Setup( fClock, nRate );
' E# L0 C+ j" ^9 ^) e, ~0 ^& z        mmc5.Setup( fClock, nRate );3 z& p/ g" Z# W9 q
        fds.Setup ( fClock, nRate );" t: r8 x3 ]  N2 d, ]
        n106.Setup( fClock, nRate );
7 V. k! ]/ q2 z  L1 E5 g        fme7.Setup( fClock, nRate );
: y( j. S1 }# _6 m; ]% m}1 D6 t* [$ s6 W' ]; j5 Z) S
% G, E: n8 Q! E4 p6 T
void        APU::Reset()
* l/ v) B7 Q2 T0 w: v9 L) E{
! q! U- T; V. M5 d" L0 v        ZEROMEMORY( &queue, sizeof(queue) );5 O. t9 X9 f# G' @  j7 ?* q! r
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- F8 B: N7 T" e1 u+ g; P  X

* \. h9 J: c# v+ w, f4 A( u- U        elapsed_time = 0;7 l) ^4 n. @5 u- Y3 [0 f$ G
$ F" H  I9 w4 `
        FLOAT        fClock = nes->nescfg->CpuClock;- j, h: o5 `1 a! \' R: }, r' t
        INT        nRate = (INT)Config.sound.nRate;. B) B) V, ?9 S/ ~! _9 [6 A' Q
        internal.Reset( fClock, nRate );
6 e& V% }2 V6 Z/ |! y; `        vrc6.Reset( fClock, nRate );' E4 A( B4 w* V) m' `
        vrc7.Reset( fClock, nRate );) O' z2 u( C9 a8 {# x
        mmc5.Reset( fClock, nRate );* R* ]4 s( d' a  |0 \4 |1 U" l
        fds.Reset ( fClock, nRate );( n& S5 O: |8 {! n( Z4 c+ ?/ \! ]
        n106.Reset( fClock, nRate );
" O$ n  L# l. @1 K. M- Q& n5 x        fme7.Reset( fClock, nRate );
2 X  N1 u% m; E4 D' f# i; E4 O# V* o7 J3 J3 j& P- e4 c. V8 P
        SoundSetup();
& _( O3 p3 L0 h" ^( F) [# R5 v% `' W}9 t- u. ]5 d! N  B: C" e  o

' U! s4 M8 a) a$ O1 rvoid        APU::SelectExSound( BYTE data )) o% @7 _) x+ D3 E4 c* f# P
{% s7 d$ [% U& d6 e6 m- G
        exsound_select = data;  f* }* K9 r; t8 k7 n: F+ n) j* ?
}
6 A% B# s- Y- a/ t6 x
% I5 g; [; y$ ?* ~BYTE        APU::Read( WORD addr )+ j4 `( u5 v6 Y! w- ~/ f
{
$ a" v7 \1 I- z% N2 |        return        internal.SyncRead( addr );
; O/ M. e# x- d+ O# {' a}  t: B+ E! v  F8 o

, P8 E# r' f6 m- avoid        APU::Write( WORD addr, BYTE data )% \# l) J0 {# ^8 y! z5 [
{, }9 B+ @8 z6 e, d1 R
        // $4018偼VirtuaNES屌桳億乕僩
" a" L) x. V$ E" Y        if( addr >= 0x4000 && addr <= 0x401F ) {" W; d8 m' o$ s) b6 l  T7 q
                internal.SyncWrite( addr, data );
  q$ _$ b% \( F3 q. m! c+ \                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- w" K( @; L# Y& r; B, I4 m  [
        }
& N- P& x9 z% p$ M. K}
, k! C& e6 D4 Z7 k  N+ a5 s1 F& s* e7 d: I3 E
BYTE        APU::ExRead( WORD addr )6 L6 O( W2 Y2 g9 w! }
{
) |$ H2 u6 R4 oBYTE        data = 0;3 \7 i& X4 @6 N
6 g4 L3 D3 u9 K2 \+ b' b
        if( exsound_select & 0x10 ) {
1 f* v; _, S( H9 @! b                if( addr == 0x4800 ) {0 y7 b$ c9 M* Q4 ?& c8 `  _1 @+ b. j
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
9 q: M& {  h5 G& r' h4 p                }
4 v/ w7 i1 b% f        }  C" W' J% O  U6 `' L
        if( exsound_select & 0x04 ) {
9 h! _& q( A( H7 B2 ^4 R: r2 v                if( addr >= 0x4040 && addr < 0x4100 ) {9 |1 g& O6 ]8 ~6 Q/ |
                        data = fds.SyncRead( addr );
, e5 d# ], w/ [8 d) }; ~                }* b+ D7 B4 T/ U" _& {% M& r$ z) ~
        }
4 V2 v% w2 f& A( F8 c% @/ Z/ |        if( exsound_select & 0x08 ) {
4 K5 z2 w" i- V  p1 r                if( addr >= 0x5000 && addr <= 0x5015 ) {
: R7 Q7 S; k0 ~) N5 |+ N                        data = mmc5.SyncRead( addr );$ _8 \5 M3 X3 r: y8 q9 o
                }
2 g, C4 @1 s* F/ \! X$ ?        }' Z: e' p6 W' }1 F. f
( b% V5 X: S; F) W
        return        data;
& [  {7 k9 K6 z/ \5 Y3 d+ S5 l}
  r; D9 V+ v6 ~# C* [- W" {! h( |& M# N) `: ]; A
void        APU::ExWrite( WORD addr, BYTE data )
5 _& ~. r' `' F: v{  [" r7 C; e  A3 ?2 |) S! Q, L9 D
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
1 F1 L) S  k# @2 t4 Y
. |/ }+ ]% \1 w. ~' D% N* E2 ~        if( exsound_select & 0x04 ) {7 @2 A: J( W4 H6 e- l
                if( addr >= 0x4040 && addr < 0x4100 ) {6 k  E( Z' a0 ]. w
                        fds.SyncWrite( addr, data );
4 g& ~* P2 k, `5 ?) I+ D7 k4 O# l                }, ]4 \% |# f- {. _+ C, L
        }( z' ^3 X5 O; ]

+ o2 f$ |, y3 k) ^1 E" _' ]        if( exsound_select & 0x08 ) {% r& ~( q5 Q) Y2 x3 _; N% L! f3 T0 s
                if( addr >= 0x5000 && addr <= 0x5015 ) {3 T2 ^+ y8 a* ~. D! o  {" X
                        mmc5.SyncWrite( addr, data );& C# R$ p- P3 W) g7 `
                }
1 F& Z2 @. \. q        }
" f' m$ G( Z2 A; a4 D}
$ Z) x% c/ X9 d8 I2 L  g5 _
* M0 q8 {/ Y4 ]5 Q# D( qvoid        APU::Sync(): W6 w4 S- x3 [) O! o$ B  F
{
7 y4 @- Q; V2 \5 W, s' N& M}; T# `, @- Z: F" r; k' W
0 {$ Y0 g3 F$ E# n+ _- Q( B
void        APU::SyncDPCM( INT cycles )
$ O* m+ g' \: l* e{
2 ~) z! k8 p3 j, T        internal.Sync( cycles );
( A. t) D" }8 |* _" `
! q  x; e' {  D' k' h! E. B        if( exsound_select & 0x04 ) {& N* J+ b1 |8 d  r; x
                fds.Sync( cycles );
2 {7 R/ T  p0 `' \( Q        }4 |! R8 a: r3 I& _7 s% w# Z
        if( exsound_select & 0x08 ) {
" o2 }/ |8 p- L8 p+ r8 J2 f                mmc5.Sync( cycles );
& ^7 Q. P* o' P+ a- d7 |  u        }
! L; o" P6 B5 W$ D) @# f7 |7 k6 g}
/ W. f" {$ O. V+ d- y( p6 O" b' H8 N6 B
void        APU::WriteProcess( WORD addr, BYTE data )2 d  y5 X1 b. ?  z9 Z
{1 r; W8 m" |7 k/ `1 h" R# \
        // $4018偼VirtuaNES屌桳億乕僩( B" T. f5 j$ T& k
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 h# x6 R; d; A7 k                internal.Write( addr, data );
7 V. j8 `+ ]+ i8 J3 n3 v& n. S        }
- t6 {, a3 r. f1 b; w}& a" a1 Z" g: K, }, u: {

" {' p5 k( g( n; P7 d: `void        APU::WriteExProcess( WORD addr, BYTE data )# `" N# i4 |" [' a9 d
{
, @5 k0 c( k! A) }        if( exsound_select & 0x01 ) {
0 q. n. l3 n6 |( V. o                vrc6.Write( addr, data );
" D6 \0 b# Q+ E7 L        }. A; {' {! T+ u3 t/ T( ]' i) T
        if( exsound_select & 0x02 ) {2 H) R7 a% M# t1 D0 ]
                vrc7.Write( addr, data );
/ N3 g0 {, q. v' W: K8 L  Z        }
) ]& @+ m: }' X1 {* A        if( exsound_select & 0x04 ) {
7 z5 d: R1 [; v. |- h' Q' o4 A# Q                fds.Write( addr, data );" n6 R; c% c5 F+ i4 B3 S
        }4 _! P7 t1 C1 ~" V
        if( exsound_select & 0x08 ) {
) ~4 L  ?% y! ?  J% |' @. N% |                mmc5.Write( addr, data );2 e1 K/ C3 Y4 u& K! x, x
        }/ `5 ]" l( E* c5 A, y4 E
        if( exsound_select & 0x10 ) {
9 H! o$ |1 O: D5 r' k                if( addr == 0x0000 ) {2 S3 G% O# Q* @2 U( c& I2 i
                        BYTE        dummy = n106.Read( addr );
# {' |! }5 ^" N% f, Y: V0 [  Y                } else {
. J. \7 q( R! b0 _4 z4 u# R) K! c                        n106.Write( addr, data );# p8 T  G5 C$ X1 \# X9 O5 i, [3 |: x" d
                }3 Z$ f, S& T( Q" {5 }, x" o) t
        }4 H3 g: Z. A4 o5 W; F  y
        if( exsound_select & 0x20 ) {9 C; [# h. a8 {! V
                fme7.Write( addr, data );
! d% n7 k: I; R& M        }
9 c6 a6 A6 z1 H- E3 }}
4 V2 d6 Q: \1 [/ c8 N, }: v' i4 y$ u1 w% v8 C" ]; R7 F
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
6 z2 {& G) E7 g7 E/ l$ [# A{
9 X; O: g' u: _7 X) _$ W. mINT        nBits = Config.sound.nBits;0 U  n* j. e. W+ }
DWORD        dwLength = dwSize / (nBits/8);
0 @, X" L( ?8 b+ GINT        output;) _4 `. U5 w& f
QUEUEDATA q;
/ {7 y$ G8 B: K- N! v! f$ |DWORD        writetime;
; A" ]$ M! R" Q" w# M9 x% T* n
LPSHORT        pSoundBuf = m_SoundBuffer;
3 r0 P0 m4 t" d/ g- @7 m$ d4 O: X& LINT        nCcount = 0;7 k! x  n& b2 {& D, J' Q* ?! A

; T( s" f2 m7 o. C4 \  fINT        nFilterType = Config.sound.nFilterType;. b1 Y; M3 W6 y  S. h1 B+ F# n
+ Y9 |8 i/ n  d4 ~6 C
        if( !Config.sound.bEnable ) {
0 a" J: w3 U' m  v                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 u) Y$ t/ G( _8 @6 O5 `. y
                return;
# C# Q5 c2 j+ k9 E        }
/ E& |/ [7 Y. p: ^2 c7 B
) I. E4 f$ _. G9 f        // Volume setup
% a5 L& S. p4 w4 \! p* H2 ?        //  0:Master
. @7 b! y) Y1 w  s+ Y( `+ S        //  1:Rectangle 1$ A3 S" T: q: l9 r
        //  2:Rectangle 2' W0 d# X. K$ p6 t7 j# B4 K
        //  3:Triangle
" r5 ]6 I" d" I+ A: j        //  4:Noise# W) X) c* P7 O7 P1 B. L
        //  5:DPCM
" d5 J. A; h+ R& j7 q        //  6:VRC6
' T: }* a" B/ R5 ^1 V" p6 |1 ^4 c        //  7:VRC71 R) S" E: K0 J: K
        //  8:FDS
' P& z6 ^) ^5 c        //  9:MMC54 ~* f# J8 u7 Z3 Q: H
        // 10:N106
$ B- j4 j6 W9 W8 X8 q) X        // 11:FME7
9 r. F8 }: Y7 T* ~; s        INT        vol[24];
3 f7 ^  ~: Y7 R; z        BOOL*        bMute = m_bMute;0 R* z( n7 m4 ~# A& \6 _
        SHORT*        nVolume = Config.sound.nVolume;1 a5 E+ h4 k9 Y3 {
, `8 J) W$ n4 v8 h" G
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
& k! t5 M" a6 B( r$ N
0 I% g& x4 Y6 S) z) x: ?/ w# c        // Internal4 k, j  a. `2 l5 n4 U$ J
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
1 N4 G; G! q8 l0 f! j! v1 F        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  _" F+ H# i1 K0 a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
2 u0 n: C% F; _1 M        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;# ]1 i6 ]* S9 T
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' |) V- j: {' v) `& F% t

/ Z; y6 }- t. \# E+ n* m        // VRC6
. f* ^$ n9 E3 @3 b        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 s6 l) w+ V& Z$ _        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 q7 t5 u/ f3 [5 z( j        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% O9 W' i) B! P* J! V& {( s. [4 I/ j, ?7 F6 t8 \& @( Q
        // VRC7) \; }9 n4 S$ V8 S( H3 e
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
: q3 L6 k2 w# H+ j' }2 Y
( ?, I# U) Z+ ?- s        // FDS. n' y! q' q# t4 }5 k  r
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, S; n+ P  c  m  Q! A0 G2 W
. ^  r' D3 a* d6 A        // MMC5
; p" c9 Z. s& {% L        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 i0 H* k7 m/ _( U) e3 b0 S
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 ?. _3 s$ v# b4 ^
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" q6 I( m7 A$ W% A

7 P$ b, M" Y9 S$ E! t        // N1067 I  c& \( _- ?" b5 V! |1 q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 F$ A5 |( W* b* @7 k        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 o: {# s8 T1 m
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 F; r4 w$ V6 I, o
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" H% e. \2 B' h" i1 }; l        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) p5 A, ?* v& U! d2 G3 P2 F- v6 b8 P
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 ~5 N7 k" e3 G; x$ J
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: f5 s1 r% t& \. y. y) n
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; n0 P+ M" J. E/ C) e
! n7 j2 D/ U' O        // FME7
4 |* R' j2 B0 U" C5 o/ h        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 M9 f+ Y, K+ ^  a3 E6 T        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ S' h8 ?( F* v1 g        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, W  K7 \8 A+ F# ^+ X' m2 _# O3 N8 w0 k- m9 c
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
- h6 E8 N/ _0 x- Y        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) v0 D& \/ V( L+ b
3 X4 p4 M! @  m: S4 [4 x        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟8 A6 c1 Z, D4 T( [. Z* b0 \# w
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
$ L5 y+ [, L: Y8 t' o                QueueFlush();# s! C' a3 w6 [2 H  j# g6 e
        }0 u. l! G; i7 M
) o/ h2 m% Z; B9 t% @5 _
        while( dwLength-- ) {/ H, S( f) Q" r7 i! a
                writetime = (DWORD)elapsed_time;$ g. m$ H! a+ x' Q) X$ p

, g- D3 b% E* b8 m                while( GetQueue( writetime, q ) ) {% O. D1 o. e: G, v* ^. p1 }# ]$ D
                        WriteProcess( q.addr, q.data );
* q  F. @5 P8 p: d4 E                }: ~, _5 H! A- q$ i' L: x9 k
' Z$ y* S0 j, c# J
                while( GetExQueue( writetime, q ) ) {
% }! U, G7 e1 b9 B6 U' O0 N                        WriteExProcess( q.addr, q.data );" ]) |" d: m5 }7 C9 |7 s8 S0 F
                }
6 w3 I6 u) o" _1 O' }: u5 F8 b: Z2 M+ P1 h, _
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
8 l, v5 V  o& i9 J                output = 0;9 Z7 [# o  M; h! K4 W; a! E8 Q) V
                output += internal.Process( 0 )*vol[0];
1 E& Q: s4 z& J0 O4 V( D8 ?                output += internal.Process( 1 )*vol[1];* x% W, [) f$ n/ W3 R. c
                output += internal.Process( 2 )*vol[2];' B5 T) ^# `( P
                output += internal.Process( 3 )*vol[3];
& ?+ \" G, z7 r& ^$ Z/ h                output += internal.Process( 4 )*vol[4];
( [$ i# x3 g" V! S$ }0 }3 g$ Y  ?6 i3 i7 d7 G4 b! @
                if( exsound_select & 0x01 ) {
  W% s) e# K2 D6 ^2 M                        output += vrc6.Process( 0 )*vol[5];) c$ K9 Y- a1 G3 I
                        output += vrc6.Process( 1 )*vol[6];
0 N% T% N" F+ |9 N9 d                        output += vrc6.Process( 2 )*vol[7];; u- e& ]: [/ y) E# b
                }* R7 |9 n- x0 ]" k3 Q  G/ l
                if( exsound_select & 0x02 ) {
2 r% j: S* A/ d3 a% l% L' I# h0 y                        output += vrc7.Process( 0 )*vol[8];
& v: ^  L1 S* y6 @4 w: `1 A                }
" }7 k& \6 v$ H% y                if( exsound_select & 0x04 ) {
9 p; R2 D; R5 e, D                        output += fds.Process( 0 )*vol[9];: V* k+ k+ ~4 U5 _  v2 w% L
                }- N1 C( W9 \% z# o
                if( exsound_select & 0x08 ) {5 e6 e( R/ O1 J3 W
                        output += mmc5.Process( 0 )*vol[10];
* ?# f& ]  S# g. t6 ?8 p                        output += mmc5.Process( 1 )*vol[11];
* ^) C/ ]) R; z7 b8 |+ f                        output += mmc5.Process( 2 )*vol[12];
! S' P. D9 ^( k% F4 n                }
6 S* }, h5 G1 l9 L                if( exsound_select & 0x10 ) {) N7 {5 B  L( I, I: \" m, @* K
                        output += n106.Process( 0 )*vol[13];4 x+ c) C& T7 {2 K4 K
                        output += n106.Process( 1 )*vol[14];" R2 W8 \4 A: b8 R
                        output += n106.Process( 2 )*vol[15];8 ^# Q, L. C* H9 L+ e7 m
                        output += n106.Process( 3 )*vol[16];
  X2 b, {9 T; V2 J* _# p( `5 Y                        output += n106.Process( 4 )*vol[17];. u  e, E% u! m6 ^9 d
                        output += n106.Process( 5 )*vol[18];" n3 W+ r% Q# J
                        output += n106.Process( 6 )*vol[19];( g4 T& _1 }' d. S- R
                        output += n106.Process( 7 )*vol[20];
3 n* k; L% X0 u( L0 A- S3 x" x% P                }1 v& G0 q, W- G# ]9 X: r
                if( exsound_select & 0x20 ) {$ b" {+ L7 Z0 S* y5 k* T% E1 }& v; z
                        fme7.Process( 3 );        // Envelope & Noise
7 a5 u3 P* b( ]# O' `                        output += fme7.Process( 0 )*vol[21];
5 {1 U9 G3 O8 A: r. e. Q                        output += fme7.Process( 1 )*vol[22];+ C; f9 X- A+ x) l; L/ i1 F
                        output += fme7.Process( 2 )*vol[23];, u2 V. x8 A# S3 b: a$ d2 F
                }
( T7 g2 M9 b3 N9 B( i+ _$ g  Z7 p( W4 K  |
                output >>= 8;# P+ S9 s* \. y( I$ X6 ?

5 r6 t& K( ]5 K$ E( Z1 q+ W4 W                if( nFilterType == 1 ) {8 @4 T& [$ l& n0 W+ [; W3 b; h
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* k5 t( E; `" R! d" U# @                        output = (lowpass_filter[0]+output)/2;0 [& c1 ~( x; U8 F# y& G
                        lowpass_filter[0] = output;# F! P7 d0 z# S% Y- V9 j: A. C
                } else if( nFilterType == 2 ) {
( `: r' ?8 f7 U5 S                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)5 `& Y  r* ?. C3 M, c4 a
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
, V( d% C: H/ Q% ~/ u                        lowpass_filter[1] = lowpass_filter[0];
0 a  l* w! j& W8 R8 c                        lowpass_filter[0] = output;. v. w3 S5 h0 Y5 a9 v
                } else if( nFilterType == 3 ) {
8 Y0 e' t6 J/ o$ @* r                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
) E, @' ?9 M4 @  O( `( j  \2 v" o                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;4 r- E" A, _" J" Z+ b
                        lowpass_filter[2] = lowpass_filter[1];& s3 d& m& C0 ^: D9 W5 o" ?5 I( N
                        lowpass_filter[1] = lowpass_filter[0];
+ x, F/ `/ Z+ \6 h8 C% h/ E% A6 M                        lowpass_filter[0] = output;
1 A+ l' d6 l+ f% f, L% A# K                } else if( nFilterType == 4 ) {
7 M$ I& {8 A" a1 |/ s3 R                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)' {! t% ?  g7 I) B, S
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
/ h7 G" L/ L' y. ^* b: I                        lowpass_filter[1] = lowpass_filter[0];
6 D* K4 }, e& q- d4 `$ a- s                        lowpass_filter[0] = output;* |! |; @/ y0 D2 w3 X
                }0 {& ]0 T& ]; b: n! h- _3 c' p* N

# Q6 D6 b2 ^# M* A#if        0
  F8 \4 s% F! N& m7 L7 K1 n                // DC惉暘偺僇僢僩
7 j! D3 |6 {7 i2 M' C                {
4 @7 x8 {3 P. |) F, \0 U7 u) n( Y                static double ave = 0.0, max=0.0, min=0.0;
+ V* m" C7 |9 Y- G! D                double delta;6 `4 P: W8 ?8 H7 }3 V. i: M7 L
                delta = (max-min)/32768.0;! r. r$ W( {1 O! Y$ d
                max -= delta;
% O8 N9 ]/ d) D6 m& C5 o                min += delta;
* z  K% h, A7 }: q: d3 N* W                if( output > max ) max = output;
9 O6 Z8 c1 J6 z" b                if( output < min ) min = output;
+ B4 |" W9 A" g8 t( y; B                ave -= ave/1024.0;
* N+ E1 p  S* u* J' b8 [& D; U                ave += (max+min)/2048.0;  {/ }1 o" H3 C5 B- r" @8 B1 `" M  @; f
                output -= (INT)ave;$ P2 Q/ [+ O7 P
                }
& X6 F: ~0 ?# h4 j  M: G7 h: T$ N#endif7 `0 w  T* h9 B: U. A6 C
#if        1
* x- h1 b) Q  z" T                // DC惉暘偺僇僢僩(HPF TEST)
( a) }0 S2 P0 q# p                {5 f/ B$ r; L' Y/ L4 _5 i# ^" @& e
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
1 ~) d2 _) {5 Q8 \. i( S4 l                static        double        cutofftemp = (2.0*3.141592653579*40.0);( w1 i1 t$ w7 c
                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 y) |5 Y- T" h- w" j. B
                static        double        tmp = 0.0;$ w. w8 O' n3 l% x4 ~2 a
                double        in, out;
1 ?* u% u/ d/ _9 X1 [7 L% I( K1 d8 I; R% B+ m" l
                in = (double)output;
6 h1 w- q1 n% g1 n7 i( k                out = (in - tmp);: B: b. p$ L! g( s5 k
                tmp = tmp + cutoff * out;! Z. E, G& }" M; j
1 L4 a. Y# m3 u- M: p
                output = (INT)out;
1 ]; {3 y* q0 S* r: J                }
9 V) U, O2 W8 q; N! @% p) x#endif
: l) R! I* d! `1 V. u/ v#if        0
0 ~! h/ J6 w9 M: b' n2 V                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
& B4 ?; e+ {; U4 w! A                {. N8 g! A( \: T8 @, y: B$ L- Z
                INT        diff = abs(output-last_data);, [) g8 K' m2 r( T2 C
                if( diff > 0x4000 ) {
+ X. d$ K. ^9 g" q( m+ C( R+ R                        output /= 4;3 ]+ j  C9 E7 w: k
                } else " S* W" j; E: E& ^; [" r
                if( diff > 0x3000 ) {
$ s' A7 ^) l& n2 ~/ ?5 y                        output /= 3;
: e" G3 s9 n! i                } else% B9 w: ~: V' j
                if( diff > 0x2000 ) {' m* J2 D9 H! U2 N* w  K
                        output /= 2;8 e# [% }7 ~- _' Z4 c7 k: U! G
                }
. @) R: C1 y# s& a" B                last_data = output;, O" d8 n6 E) t" u9 \( ~! \
                }
- @, n% r6 ?+ M4 c#endif
* e3 A; D) G% w% V2 U                // Limit
  \3 f7 @$ u( B: J- V  M                if( output > 0x7FFF ) {
% E& m6 j8 F! ~                        output = 0x7FFF;
2 n) v5 c/ s- f0 f) q' Q                } else if( output < -0x8000 ) {
- A. C2 d% K4 Q5 c+ Z0 _3 d* h                        output = -0x8000;+ H, Z9 t% ~) ^, j. j) e1 o
                }+ t8 B- Z  Q3 |% P: Q5 E# C$ k
! e/ f/ q4 C$ g  S. D
                if( nBits != 8 ) {, l) ?6 C7 Y* \  R) b
                        *(SHORT*)lpBuffer = (SHORT)output;
% G3 d8 W+ V. [* N, k) K                        lpBuffer += sizeof(SHORT);" E8 P- p; r1 Z3 n0 y3 X6 V# U
                } else {/ t/ i5 C9 t4 m2 l. y, z) `
                        *lpBuffer++ = (output>>8)^0x80;
+ @& }0 f& s3 m" ]8 D1 W                }5 l, h8 r1 }) m5 w) o0 g
0 _; r+ s( P% P) x3 S: v2 F# G  K/ {5 r
                if( nCcount < 0x0100 )
0 k) x5 M" r7 o& J/ _: i- b                        pSoundBuf[nCcount++] = (SHORT)output;' y* L7 h3 \- D

2 u7 {4 d! t- [  U//                elapsedtime += cycle_rate;9 P5 f& g, c: y1 K
                elapsed_time += cycle_rate;+ ]  f% D! z% ~# @. Z9 j, k. }, A
        }
, H2 z; n, e2 @! [
6 I8 p% ~5 m9 W" i: o#if        1
- n9 n  @! E  Z- b        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ j) |+ ?9 E8 M0 s1 O8 d: {
                elapsed_time = nes->cpu->GetTotalCycles();# x1 p7 I) e4 m) I- Y' C! i
        }
2 D* Q% b. L- U1 }        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {" \) _* P; F7 {
                elapsed_time = nes->cpu->GetTotalCycles();
9 f, ]+ d2 k  d' Z# T        }' F- u% x8 x9 i( X" S0 D
#else4 ~$ Q! b  F9 T, @" g
        elapsed_time = nes->cpu->GetTotalCycles();
. C6 a% a& f. x* g3 X#endif* }/ x$ y7 F  `4 W- a9 q$ n* g
}
* H! M3 A2 B1 |+ P, r+ F$ E. I$ G" P" q, U0 K* z, g( j/ h
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 C2 S4 K2 m8 p: fINT        APU::GetChannelFrequency( INT no ). w8 M) o$ i  K. }6 |2 I7 H) E
{" T% P+ ?! V1 x1 w# G3 \/ A9 ~. s
        if( !m_bMute[0] )! s: v* \3 o0 E8 k- m
                return        0;: U$ X! k9 R( {7 {9 [  Q
! D' c  o8 |  G* m! i! f5 ?
        // Internal
/ P  M& u- B! X5 a! a        if( no < 5 ) {
% D* ^% z1 M$ q" a4 y  B1 f                return        m_bMute[no+1]?internal.GetFreq( no ):0;
: x- h$ h6 D3 p7 I% G# C! r        }& w8 F% Y* P( Q8 \7 v: h
        // VRC69 ?' A) D" c3 f2 I& n
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {2 Z8 v; p' x$ P) s' o
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
8 t3 R* ?1 c& q# q6 X( S# ]        }
+ c5 t- W# R8 W- X7 c        // FDS. g& v, h% f  ~) V, n$ F
        if( (exsound_select & 0x04) && no == 0x300 ) {
$ N3 H( s4 S" ~  a1 I                return        m_bMute[6]?fds.GetFreq( 0 ):0;
( V/ e: M% F- V) O2 h1 V        }
" b+ Y1 u% i2 L  s$ N% K6 Q7 i        // MMC5
; H8 m9 ^8 g8 j" B+ T* N! d& N        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
) G7 d& V; {, S2 w                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
4 B: ~& @" u4 N( @# P( r7 S        }
' Q0 s: }& m. U! u- A  W        // N106
' h% h+ x: D( E1 |+ s3 ^& U        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  b1 v$ J5 j- s* B
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ i( e9 T* e0 W5 z        }
( F/ S+ a& F& ~% C' {2 K6 B$ i4 Y        // FME7
% }' i' b* d. O6 ?: D6 p7 x        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# [0 ?) m4 ^4 R; U                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
! x  K9 Y1 B% I! r  i        }
$ s$ M$ I4 R0 N4 X# ~! O! b' _7 o        // VRC7  M: f, Z4 |) L- \% v+ L) A
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: t( r' P: }8 ^' p1 z; y0 g                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 u$ v8 H0 W4 V9 }
        }
( V8 x. b+ b: @& _, L& ~        return        0;
& W4 ~+ R4 r# p8 g. u# l  R  G( w}
+ _8 n, E1 P; x5 m) @( R' D0 e! n
// State Save/Load
6 b) v# Q; }, Evoid        APU::SaveState( LPBYTE p )2 N% h+ f( Y: I2 @$ L
{
) c$ {8 o' c7 Q- N; m2 ~4 h#ifdef        _DEBUG7 J6 [6 D6 Y; Z# ?6 a" @/ _2 t
LPBYTE        pold = p;
% q% X" Z/ V: Z7 f1 K' f+ D#endif
4 b; x' G: m+ M3 y1 j
" [6 R5 ?4 g7 L) n& V5 b        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
3 ^, E8 K5 ^" f& g( ?- u$ g        QueueFlush();) \) j' N; ~3 y4 H/ E6 }

. i* f1 B% k6 A        internal.SaveState( p );
, I/ d" l7 B8 Q        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: R( }# Q0 q' u( N. ]$ d5 _

5 u  G: v  j0 p- ]        // VRC6
& r0 P( l) Q4 L& p) f4 r        if( exsound_select & 0x01 ) {
( u) u" K0 @( h# y. B7 G. r& Q* S                vrc6.SaveState( p );% c( q6 Y4 G7 a! F' k# T+ j; @( `
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" k+ x" X3 o. B
        }- r8 M7 A4 _+ n$ h9 l
        // VRC7 (not support)
1 W2 m% h  M6 q( P: R: _  ]' \        if( exsound_select & 0x02 ) {: A0 f7 N  h: |5 |
                vrc7.SaveState( p );/ ?) Q1 k% U0 E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 Y  q: b9 [! F+ `
        }
1 w/ E$ S( j7 y* V        // FDS+ V0 I9 R5 v% K7 r) ~
        if( exsound_select & 0x04 ) {& r% V/ B- a% A% i/ R  h" |
                fds.SaveState( p );+ I8 F' X, |, i# }1 k
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ ~% k& k: |, m0 y6 A8 Z( J
        }9 h# \3 [: K# S9 W( R2 e; l9 k
        // MMC55 |4 J3 ]  {) }1 m) _8 v
        if( exsound_select & 0x08 ) {
6 |5 \- D& M$ z; N3 W% S& [                mmc5.SaveState( p );) o2 F, `$ b; Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding) v9 t  m7 o# L
        }
8 E3 Q3 w9 |" F  U- K        // N106
; K9 m( K) g4 c+ m7 d        if( exsound_select & 0x10 ) {6 [8 D' Y4 k9 L) J$ J, `
                n106.SaveState( p );! K6 b' W, {. i$ N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 u2 R# a& x3 ]; a7 N6 r9 E& U        }/ M% E: Z7 _# b" V
        // FME75 E+ G9 ^8 ^& G7 r1 h& e$ h% w
        if( exsound_select & 0x20 ) {3 O: D) d. I  v5 u) b
                fme7.SaveState( p );
# P! c, u8 `, J/ X4 P4 d                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# m7 v9 p  V/ y* Z- Y9 U7 P        }' {# L6 t$ \! @  G2 ~6 T) b/ H% E
' ?7 c1 a: {- f5 _. d4 Z6 ^/ }4 H' g
#ifdef        _DEBUG
# F1 Y( f+ k. O+ A0 M" B6 zDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );* J& T. a% T8 K5 U# v; C; c6 F
#endif# Q$ P6 y7 O2 E& I7 T
}. i6 Q# @7 a# p6 m) X2 `. M: L0 C8 u. u
' }4 X% G  w( r3 i$ d
void        APU::LoadState( LPBYTE p )' N" c3 x5 T; @3 o4 j5 l& T# s; I
{
1 n$ a. Z4 d! b% \        // 帪娫幉傪摨婜偝偣傞堊偵徚偡, n6 c. @9 T" F  z
        QueueClear();
; w1 s! {9 Y# }& W+ h6 p% K% X5 _8 I) W) `8 }+ Z  e+ H2 H: I3 z
        internal.LoadState( p );$ v# o. ]: `& m* f
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& S8 @- [+ y$ r: E- n
$ B& c/ m6 {/ x8 ~$ }5 k
        // VRC6% e# n. I4 b8 R, U
        if( exsound_select & 0x01 ) {
# k  m8 P/ P+ U3 n1 H5 L                vrc6.LoadState( p );
8 j  H  G/ s- S7 e9 f  m5 V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 V6 m% u% O0 b/ K% v        }
% u" k! k) w+ g- S        // VRC7 (not support)7 e) w8 r( e( [) Z
        if( exsound_select & 0x02 ) {
4 L  F% J$ R1 U8 Q/ T' \" y                vrc7.LoadState( p );
$ o9 W$ N& r( N' o+ q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  g+ m# ~) S$ z2 A7 [) S8 q
        }4 ^( m- L3 ?- j# q& A! @! V! f
        // FDS
4 \3 `( W3 A: B1 a* F        if( exsound_select & 0x04 ) {
7 S  m; L' q1 P                fds.LoadState( p );
+ D) H2 j; [- O- x, h                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 p/ }0 F1 G4 C- V" A
        }
% s! |3 w/ S1 @5 a        // MMC5
( S: _; B; z2 M2 @        if( exsound_select & 0x08 ) {
. d+ a; p& |  v% O0 F7 Q  t+ }                mmc5.LoadState( p );5 e) n4 M" Q1 a2 r
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. @) u6 {3 T6 D1 s2 q
        }
  Q, y) E2 v( v8 c$ N/ x        // N106
- [0 `" f+ F+ O2 [        if( exsound_select & 0x10 ) {. W9 v' o+ f" T" b7 z( v
                n106.LoadState( p );
) l1 H3 a$ R4 t0 H& b3 F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. x0 r$ c/ j* s: b1 ], i* l        }
. o9 r  ~) G3 O! E/ V        // FME7
" w( g8 Z+ R2 r        if( exsound_select & 0x20 ) {8 h+ }! z4 M7 G/ U# ^
                fme7.LoadState( p );5 z8 B1 b5 d' g$ L' R) \0 O3 X4 e
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 R0 B* z% n& P$ p3 n
        }
; g# {) n: f! C( a' m; x}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
+ I2 h( Y# W6 n. W8 o1 J可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。; E& a& T" C1 e7 j/ }! w6 g
感激不尽~~
5 T  _  ]" i: L$ x/ ]7 g
恩 我對模擬器不是很有研究,4 a7 C- N& Y. J" f- q1 O1 Q% w
雖然要了解源碼內容,可能不是很困難,% s& W# i3 I, Y- ~
不過還是要花時間,個人目前蠻忙碌的。
5 H9 E( I$ D# X1 D% L6 P$ q5 C; V5 X0 m/ O, N
給你一個朋友的MSN,你可以跟他討論看看,
# q- x9 w9 E! B2 N0 c2 z他本身是程式設計師,也對FC模擬器很有興趣。
2 f( A/ I! p7 n( p" C) Z9 j% S$ l# c( w4 R% y+ C  [9 I# f: |$ u
MSN我就PM到你的信箱了。
& J/ ?9 s% ~& M" {
, X# L  _1 g6 a$ K- m: l希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
0 E$ F* f! e. ^! g$ W; l$ k4 b呵…… 谢过团长大人~~
/ @$ }& y3 y0 e4 B2 o, U# a& N+ x
+ _9 H+ _8 a% W- z; o: q  w
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 c# z( z" E0 J  [6 q$ k( N: r
团长的朋友都是神,那团长就是神的boss。
7 k* D& L% L, v3 Z, s0 w" i
哈 不敢當,我只是個平凡人,0 |8 s% U% v$ h" y# ]( y
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
, w1 M: N3 }8 F/ Q; u* t* c5 ]ZYH' m2 }+ y* W% ^# k6 L: U
QQ:414734306
( ]$ j" B# {, j3 x5 D5 U% ]Mail:zyh-01@126.com
% c1 l4 k% l  v! c) Z7 Z/ }6 k+ |, w( ~. v
/ t% w' y( t6 R他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
, Q/ u' j: J: _1 o/ P) F% G4 l再次对团长大人和悠悠哥的无私帮助表示感谢~~
" U5 u# u5 U0 d1 @) V3 S/ D
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 03:41 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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