EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 u9 {6 S9 X; u8 @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~6 F: C3 H) f% {
这里有相应的模拟器源码,就当送给大侠了~~( p2 U! U) ?. a/ }$ A6 }
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 , C2 u$ m8 O( d' z- y
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) i# o5 p- O1 j楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' V8 `) B9 e) T* f0 d这里有相应的模拟器源码,就当送给大侠 ...

# Y  i4 E$ S7 F5 n# i! f; ]聲音部分(Audoi Process Unit = APU):% ^% f! W5 J4 |$ h! y9 u/ p  {
.\NES\APU.cpp, x& K3 g. z9 d6 W! R
.\NES\APU.h- n& A3 z5 O& y; ~1 a9 b
) g( [( x6 t* v/ L7 c
% c9 i6 c: s2 G
影像處理部份(Picture Processing Unit = PPU):0 b+ u) B& d) E* a
.\NES\PPU.cpp
! ^. \% t, Q2 C. |.\NES\PPU.h
3 v3 Q) L6 I- J: t2 T0 R" I' o3 ?- m1 k# Z
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:6 h0 \. u4 b. U% x
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
1 ~# T  |( S6 X& Y: {//////////////////////////////////////////////////////////////////////////
6 Q& i) R. T8 c! c/ C9 B/ ]//                                                                      //) ?+ @8 c, {1 {* E3 i- Y. E* H4 f
//      NES APU core                                                    //; d0 Q5 ?' m$ Q  m$ Y7 r' a1 @
//                                                           Norix      //
8 G6 Q- F* s+ q( Z//                                               written     2002/06/27 //
+ M1 w$ z; n( F. {. A# H//                                               last modify ----/--/-- //6 `6 H: r3 _8 ^5 G9 d
//////////////////////////////////////////////////////////////////////////" h- t4 T/ Y5 T
#include "DebugOut.h"
% [8 h- u! r# Z5 x0 A4 Q0 U. e#include "App.h"# ^$ N; |# M+ s
#include "Config.h"# p. A# d5 |/ S0 {$ p& T# K7 p

) o' E0 L. ]7 C& [#include "nes.h"5 N* l8 h. `1 l+ B/ v3 D5 t3 }
#include "mmu.h"" ^9 _4 Z/ O* H+ S+ v1 p
#include "cpu.h"6 c5 g7 a* p" R3 C( S! w
#include "ppu.h"! g. }; l) ?) ]* X& }- n
#include "rom.h"7 O! Y1 [2 U) A# s
#include "apu.h"$ e& b* Z; f+ ~4 y; ~, A8 a
  a: P9 w' s# S0 E; E
// Volume adjust
- ^4 T# k/ w0 a" Q6 e( w$ e// Internal sounds& v7 K: @) R8 y
#define        RECTANGLE_VOL        (0x0F0)
- D5 t. ], t9 B- F3 `  @#define        TRIANGLE_VOL        (0x130)
. p7 ]* x& t( q# y- @7 W  S#define        NOISE_VOL        (0x0C0)
9 v1 a) M: I8 T; l0 B* x5 D7 n#define        DPCM_VOL        (0x0F0)) x- G7 o) Q, }- b% O0 h
// Extra sounds* z  A& b$ g! L) ~$ j( j
#define        VRC6_VOL        (0x0F0)
8 k5 o8 z2 u+ U+ }#define        VRC7_VOL        (0x130)
4 W4 c+ `0 d% U& T4 d+ B1 G9 v#define        FDS_VOL                (0x0F0)
  x7 c0 P9 c3 s4 X7 B#define        MMC5_VOL        (0x0F0)# R! Q& |/ f  C
#define        N106_VOL        (0x088)
+ S4 H4 e& k4 T6 P2 N7 r#define        FME7_VOL        (0x130)- H# b$ {8 M4 a. y% x& s* ^

) I' x6 x- U$ J3 M% mAPU::APU( NES* parent )7 K* e4 l" A) r. K% j' f6 K7 x
{
' P  y9 O0 J7 a& l/ K  s4 A        exsound_select = 0;
. l5 e/ V' {+ ?2 ?5 ]- S4 X  x4 `; L: Q( m1 H
        nes = parent;) r1 ^2 s4 X+ J$ y
        internal.SetParent( parent );
' p8 [! ^3 R" V, w1 k6 _" x; U1 ^+ B4 B5 Z5 Y3 a# Q/ ?9 y; g
        last_data = last_diff = 0;
2 ]' H( K$ c! t1 |1 M( G- m" A8 b' B  y7 i: D0 u* H
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( b3 _5 y( |  r! b6 n/ I8 |0 D) C
! m2 c! ^! b( t2 n
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );5 s" W" E$ m0 Q3 {: F
        ZEROMEMORY( &queue, sizeof(queue) );) m0 `2 y  n- Y' @/ _0 l( _( |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 D  h7 G' Y% B4 L" ~
. ]" l1 D# G% K; F: @        for( INT i = 0; i < 16; i++ ) {9 u7 L' y; v0 z- {$ y% ]3 x
                m_bMute = TRUE;
$ p4 L1 A8 N* D2 j) G# \        }+ Z6 r) k3 X* W8 `
}7 O3 X0 r0 o6 |7 b& R, F) R# K

& K$ y( F, X% sAPU::~APU()
! c. \9 L3 I: x6 s5 C. e6 ]{- _) S3 X+ S2 D  H& [2 s
}* d- G$ t7 x* o/ e6 i

% r1 d+ [2 U5 r8 xvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )4 c" F# X. c/ ~3 Q3 u7 i
{
2 N$ I/ `- Q" `( g- S6 A        queue.data[queue.wrptr].time = writetime;* a4 [) x! `# g9 b7 n
        queue.data[queue.wrptr].addr = addr;
- L2 y% \( f+ K* S0 |3 s6 m* W) s        queue.data[queue.wrptr].data = data;, r0 d" y) I0 k: t6 _  `0 [/ D
        queue.wrptr++;
, e0 R: M0 j* K# S/ r8 o$ z4 [" |* C        queue.wrptr&=QUEUE_LENGTH-1;
; n( ?! F) i2 j  L        if( queue.wrptr == queue.rdptr ) {8 {' m5 ]1 n7 b5 D
                DEBUGOUT( "queue overflow.\n" );  t9 J# B# V/ b' V* g
        }
5 ?2 T1 Y" t$ Q  ]' @% E% I: }' a3 s}
$ T$ j/ o) k3 E- B/ B) C
6 S. q" \- o  wBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
% o  }/ c2 B5 \5 f{
; q0 i0 F8 @( k        if( queue.wrptr == queue.rdptr ) {/ D) \, n6 W8 X* Z6 C, B/ K2 y
                return        FALSE;
: F; o' j3 E( J) }' t        }
$ S0 [1 G9 j  {7 W0 i) }: u% Y5 f        if( queue.data[queue.rdptr].time <= writetime ) {% l. N, A( E4 p5 Y
                ret = queue.data[queue.rdptr];7 t3 C4 h2 i, O, p: \  D- r" q
                queue.rdptr++;% L) m( }6 s$ j* y& e- T" i
                queue.rdptr&=QUEUE_LENGTH-1;/ ?! Z- z( ~3 B% B
                return        TRUE;
% N% b( q2 f* Y6 \  a; z0 T        }
& C7 P1 A3 B4 F% d& N  j) z        return        FALSE;
# R& z, t4 ~% y# E8 G5 K3 Z! X/ d}- v$ O9 t0 D9 [3 Z; _# J
& |* H, P7 M$ S  Q/ q% B; Z
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )8 i+ s% Y( X" i5 o. ^  V! t+ |" C+ s) o
{
2 w/ L/ n1 f2 ]% }# B        exqueue.data[exqueue.wrptr].time = writetime;8 y: u# L# [1 m4 T# p; h# P5 U
        exqueue.data[exqueue.wrptr].addr = addr;
3 V6 l! E! S5 t1 s1 s+ g2 Q1 s+ D8 H! `        exqueue.data[exqueue.wrptr].data = data;
, n( b" }4 B  O; C        exqueue.wrptr++;0 V8 ^" i) n/ l4 e
        exqueue.wrptr&=QUEUE_LENGTH-1;
; O1 ]- H/ r( F. R2 N4 \        if( exqueue.wrptr == exqueue.rdptr ) {  P; K& e( Z' c. n! {4 }4 [
                DEBUGOUT( "exqueue overflow.\n" );4 `, B- O- z+ Z3 {2 p% {7 y& s
        }
6 L. Y9 d8 J* ^: ]7 c}4 V- d- r& ^# y  Q2 y

* [. C) v4 q7 d& qBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 Q5 U& s# |2 w* S' n
{
, H0 L0 B: f6 w        if( exqueue.wrptr == exqueue.rdptr ) {
' u: H, h! v+ o+ d: J8 B                return        FALSE;2 [% u+ ?: }" A3 B% Y: m* y$ ]7 O) u
        }
2 y* d. K2 g  l0 t        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& r7 |' d$ }4 o, R$ M
                ret = exqueue.data[exqueue.rdptr];3 s  [2 f8 o! {4 _
                exqueue.rdptr++;
! |, g* s4 f  @# }3 H  M* j                exqueue.rdptr&=QUEUE_LENGTH-1;
6 i' n8 ~1 p& o4 I; y2 o( h& _                return        TRUE;4 L* e+ h. R$ ~5 b4 r
        }8 R9 x& N- ~% O- m
        return        FALSE;. I, e5 b# W. B$ M9 V
}
$ I2 @% c7 [, E" ~* K. Z9 z9 n4 z, N, }
void        APU::QueueClear()0 Q0 Q; |; ~+ p  n! q, V
{
" p1 j2 g2 c6 U! @        ZEROMEMORY( &queue, sizeof(queue) );6 i2 H. l2 t5 x0 g- Q5 t" C/ p
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- e0 d. A3 P% U2 c1 P
}- l2 H8 s( T; a" K" S0 D. q. H

3 R2 T9 Y! @7 Q$ k& Nvoid        APU::QueueFlush()+ _% u) ^& M- j& v7 R$ o
{
8 n( K( w! _* ?4 R/ c+ r2 d0 n        while( queue.wrptr != queue.rdptr ) {
$ m: G  t' k: I' z* x6 n- Y                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ ?- c8 [  i+ W% o: A: t3 j' e! J, A                queue.rdptr++;
( P- y, r" M( h* u7 P. ]4 V. F% }                queue.rdptr&=QUEUE_LENGTH-1;
; d5 c, ^" I% Q  Q! \        }
  _8 u, b$ p4 ^' m& e, ^  X. f6 `( ~- k
        while( exqueue.wrptr != exqueue.rdptr ) {
1 I' c( p- B6 L, [. C/ q                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 K9 G8 b% b3 W( p8 ~8 [
                exqueue.rdptr++;' |. `7 o  w  m* n2 b7 ~
                exqueue.rdptr&=QUEUE_LENGTH-1;& j, Y# l# f. h6 }
        }' O; Y# J" L; [) W! M7 `
}
! @3 K2 t! v0 i  @+ M4 k8 n" ~# [3 X5 J! H3 P5 n: U. |
void        APU::SoundSetup()
9 y3 K8 R& p4 e. ~' z2 d$ w{% A; H+ ]: N- ?& M" f
        FLOAT        fClock = nes->nescfg->CpuClock;
$ R: ]# b2 d" @        INT        nRate = (INT)Config.sound.nRate;
! I* \5 I! q4 `0 P1 B        internal.Setup( fClock, nRate );; d: \6 h! r0 }, G
        vrc6.Setup( fClock, nRate );
% f& K- v& _' j' ^  N* f        vrc7.Setup( fClock, nRate );1 U, O/ I# u# Y) I" n$ [
        mmc5.Setup( fClock, nRate );
- J$ o: C( j' K, d        fds.Setup ( fClock, nRate );4 p1 l- T% D+ T$ d
        n106.Setup( fClock, nRate );3 q) Y( Z. F! V2 f9 i6 n9 X; N- `: X. v+ b
        fme7.Setup( fClock, nRate );7 g1 P* r0 Y. m$ f% ]# W
}3 {0 h* Z7 u4 {1 w
2 A, p+ Q$ y% W) F4 u
void        APU::Reset()1 N: E# }7 k2 Y+ w. Z
{
( w" K1 Q7 Z* i' H9 F) J" R# h( d# e        ZEROMEMORY( &queue, sizeof(queue) );9 n8 ~8 E$ n0 P. V0 h5 o, T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 c/ ~, A& `9 a6 P2 m6 W
: m. j/ Y* A0 U0 z        elapsed_time = 0;  {# c& \3 F5 U9 B& D9 G) Z4 |
6 I; E5 f+ N/ V5 J
        FLOAT        fClock = nes->nescfg->CpuClock;6 L1 V& H4 J6 n2 X* k* F8 g
        INT        nRate = (INT)Config.sound.nRate;6 i! B# L* ^8 H) M2 i" L( C
        internal.Reset( fClock, nRate );
3 b1 Z: ~* J$ Z( I& r# P+ C' K        vrc6.Reset( fClock, nRate );
; V5 M8 Z8 b# ~' u/ q# f        vrc7.Reset( fClock, nRate );
8 z, G! u1 |4 e2 n        mmc5.Reset( fClock, nRate );. O7 U6 ~5 B* W9 V( O! B
        fds.Reset ( fClock, nRate );
4 h! w9 {8 P0 P3 a  x        n106.Reset( fClock, nRate );
) j; p; m# p' d" X9 ]- s$ H5 m- V        fme7.Reset( fClock, nRate );* Z. H0 |. }4 j+ D0 ]
' ^% R; N) [& w
        SoundSetup();
) f( a) @( f1 ^) C/ k+ P}+ T  Z: x, f& U" n; w5 t/ V. q
  M& C1 y) D7 s# P& x, R
void        APU::SelectExSound( BYTE data )
) K( G1 M5 z4 R" W# V8 I; ]" |{
* U& t# I% W, {, [: g& B        exsound_select = data;
3 @- G/ M2 e- E}! s9 Q9 i) J& U! [( j* V9 g

) L, |) T. t8 S* l. p( ~+ ]BYTE        APU::Read( WORD addr )& G/ s& w0 {- q' q. R+ J1 M
{
) W) j9 U4 }; C3 U* b0 s        return        internal.SyncRead( addr );8 g8 ^, T. \7 @' H5 W
}/ V5 T; `! X- F0 H+ J
7 i, k/ G1 P' E
void        APU::Write( WORD addr, BYTE data )
% }9 g; q' L0 r/ Z5 T{
3 m% `: n# n5 N4 P* t4 y2 Q; s        // $4018偼VirtuaNES屌桳億乕僩/ b4 v! X% C3 y$ c& |4 _5 Y
        if( addr >= 0x4000 && addr <= 0x401F ) {% k* S- z5 p$ N! r/ |) y
                internal.SyncWrite( addr, data );) x/ w3 N- e; u. }0 W
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 J/ a7 {7 ~  q0 |( B( d* w2 t
        }1 D& g' y0 [1 u% l! e9 P
}
9 Y1 N- N+ j3 c' G2 ^
9 W: W/ z$ u$ ?BYTE        APU::ExRead( WORD addr )
4 O6 W3 t. h2 M' w! E7 P- H{
$ W1 z3 M" Z$ U, |& q& P9 k7 T4 SBYTE        data = 0;
3 [0 G/ h) P/ p9 ?! }( {4 i7 ]% `! }
' i' Y3 V& P9 a! {        if( exsound_select & 0x10 ) {
" @7 N* Z) z/ n. x# A  w2 S" u4 [                if( addr == 0x4800 ) {$ u0 c3 h! T" a9 r& o. r: J  {' M
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 X! O: d4 Q' o- K) u/ }
                }7 h7 x% B3 ~" H$ {  \6 @3 m3 ~* Y
        }
) S9 B5 T7 A! c2 X, G  L, b  K  u( i% m        if( exsound_select & 0x04 ) {& I- t' A$ `5 V7 t* A) v  m
                if( addr >= 0x4040 && addr < 0x4100 ) {( a/ q6 P" j8 X9 q" t; Q) m
                        data = fds.SyncRead( addr );
/ k$ a) q& o$ v6 o" i                }
7 ?  i8 S, ]3 j, h& q2 _7 W        }
9 L% x' V0 D2 H* p; t9 `$ \        if( exsound_select & 0x08 ) {4 [* r+ j! j- [, j5 ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {6 A+ }6 _! m( r) c2 c) t
                        data = mmc5.SyncRead( addr );$ b; q, S' a" x8 D) Z: z& f
                }: w/ c- Y; m* [+ x+ y* {$ P. x
        }
4 o( ~  ]. m2 V, X9 h  n4 J2 [5 l; C1 \0 ^% J  f
        return        data;# f7 z( X7 y$ \  |5 X4 A0 P/ W
}
6 c7 g. }9 |% d4 \7 \7 C5 o' N2 {" p; Z/ _, H3 j( g$ A
void        APU::ExWrite( WORD addr, BYTE data )* ~4 r: ?. [% B, S: i
{/ M' M$ u" A# }2 J! F. C
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );. c* d0 S" ^4 Q3 E0 y0 |& T
9 v; X/ ?- T; Z. D9 b3 O/ I6 c
        if( exsound_select & 0x04 ) {8 B5 l. |4 b& v# b( L) L( `% w
                if( addr >= 0x4040 && addr < 0x4100 ) {  [7 D3 N+ `- @4 Z# }5 e
                        fds.SyncWrite( addr, data );7 ?" d3 h* C$ p) l
                }
# L: U8 h" z* p) ?+ V  T1 s        }, l1 o4 t, S/ t4 s7 K
# V4 f/ U  Z; I! U/ |4 y0 \4 ]
        if( exsound_select & 0x08 ) {
- s9 N# N4 r" @  D, I$ S( X8 p( z                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 y0 y8 M  r  `9 E( d                        mmc5.SyncWrite( addr, data );7 l' w2 _: B8 i) T6 l
                }! T  u; u1 t1 V! m) R, k
        }
; U- `* H+ `( y: T, w+ H  i* G5 H}7 @- M. K& _/ X" c# e

5 ~; _: e, i( |+ Qvoid        APU::Sync()
4 M  L( s& U! \, @/ M7 A{5 t2 @3 E3 b5 s+ L
}( z6 m4 n6 H+ [& `* q6 {% Z" m

' g# z- A7 n% k4 V8 Dvoid        APU::SyncDPCM( INT cycles )
+ o$ v1 j% L/ ^* i' I3 ~{; S1 F: N3 j, z
        internal.Sync( cycles );
! [" Y) ~* n+ _" \7 e1 r3 ~  {
& g- K8 X- ~( |  p+ K        if( exsound_select & 0x04 ) {
$ P) O* W  e/ I& N. A                fds.Sync( cycles );
! i* J) k! r1 F1 A; l        }, o) i+ \  k$ U- P/ e: I
        if( exsound_select & 0x08 ) {2 J$ {, I! s# B) Q: T) E) d3 e
                mmc5.Sync( cycles );* k( |6 b  N3 }; v6 q- `& C
        }
, _; \9 {! g7 x" P  T& Y}6 P: T$ g+ y- I+ S9 g: f9 \/ |# X  a
4 j1 r4 A: S; a+ [: k* u
void        APU::WriteProcess( WORD addr, BYTE data )4 m. |1 W! o) C- V1 o
{
6 z" U0 q0 T) n/ l0 i7 ]4 L        // $4018偼VirtuaNES屌桳億乕僩. }! m; f( s  b. x% {
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 J% [* j. ?7 k: K                internal.Write( addr, data );- e% a. s7 X' G2 S# l. @+ H" `9 M
        }1 N$ c! K! t- X5 ~  C; O
}1 d4 x: q( i* u- }) L# i8 ?

$ H( k2 M; w% j1 |" Cvoid        APU::WriteExProcess( WORD addr, BYTE data )
- m: N- H3 h$ h{! }! d# H. N: p4 h& s
        if( exsound_select & 0x01 ) {
! e1 [+ R8 S  e0 b% ^                vrc6.Write( addr, data );, O# l- v9 E6 j) k& j! B9 v
        }# @; v! K3 |0 v5 g
        if( exsound_select & 0x02 ) {
2 T0 }/ v. }" T8 k* G  O                vrc7.Write( addr, data );6 S: w: u: H  q6 ^* G
        }
% C* a, C) U+ G( ^: p8 M: d, ~+ [        if( exsound_select & 0x04 ) {9 `) r# ~. X4 m0 d7 x0 e$ R4 C! K' L
                fds.Write( addr, data );
9 X( F6 n- z' X4 \        }
/ c5 C. K- c% G, t3 l% I( z# O, `9 z. S( g9 ~        if( exsound_select & 0x08 ) {2 i3 D1 Y5 @! n. _! b* B
                mmc5.Write( addr, data );
) I* B5 h$ t4 B$ F        }
9 D2 {, X, K& l; w8 s; M$ K+ ?  J4 r        if( exsound_select & 0x10 ) {* D; G. ~% l' \* ~
                if( addr == 0x0000 ) {* }1 H1 f1 j! X  C& [" Z& ^3 q
                        BYTE        dummy = n106.Read( addr );7 I) g" _9 ]- p% w. T) c1 f
                } else {
5 x. O, c$ I2 G, }6 _' y3 e, ?+ q                        n106.Write( addr, data );5 W6 F. p4 V( q  `& |
                }! m& ]/ c, \( {- t3 D
        }
1 ^: ^2 U& F: ~. G# R8 P( q; i        if( exsound_select & 0x20 ) {
. Z) q2 |4 f+ B2 H" N                fme7.Write( addr, data );2 M% P4 U0 m! d4 {/ [% v
        }
3 _5 k/ O% _  c) e) l$ H}
$ e' \+ X2 g/ ^- X  q) o# g
5 q5 w6 J" J/ Vvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 i/ P: j& G( w% n8 p, v{
3 a4 Y4 T9 O+ |3 L! ^INT        nBits = Config.sound.nBits;
- q1 e' Q9 R& l8 I% tDWORD        dwLength = dwSize / (nBits/8);
+ x& o8 d0 X& w. {- p) BINT        output;. l5 O+ M# E$ ?. a. T9 o. p
QUEUEDATA q;
, d" k, f" O$ O0 bDWORD        writetime;
% I: T+ [8 ~: H
; P6 \3 A+ i& h) t' SLPSHORT        pSoundBuf = m_SoundBuffer;- E2 g( \8 F6 ?9 f
INT        nCcount = 0;; F! R" h! |# |  ?2 ~

0 r+ Q% R5 P' K6 S: MINT        nFilterType = Config.sound.nFilterType;
  c8 b5 f  o; R* w! U; N% A$ O$ B- A6 _
        if( !Config.sound.bEnable ) {9 |  ^* U' S' T
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 [8 v2 L4 e' V3 a
                return;
& }+ o; l& D! @# T$ o        }
6 ^2 Y. n; X/ K2 N5 l; U) U* k% e! n' [' Q8 J& u8 Q
        // Volume setup! ]6 Z! O4 r, u  `
        //  0:Master6 U. x5 k7 f- `  C5 S% i
        //  1:Rectangle 15 Q  I3 f8 ]8 q' X! ]
        //  2:Rectangle 26 R: Q( C4 E" [9 X
        //  3:Triangle; j" c% X6 j2 s
        //  4:Noise6 E. x# T, {$ u) J5 p6 C. ~( [
        //  5:DPCM
- U+ N' }5 K. H- V2 ^        //  6:VRC62 T5 b2 ?  g; Z& ]
        //  7:VRC7
( b; j; K. X& Q9 T# ?        //  8:FDS7 r9 y! @  I$ B0 z0 i
        //  9:MMC5
& g- Z4 k/ g) i# }& i+ ]1 F" h        // 10:N106
; X& q- L3 m8 h4 ]5 B) n- C% z        // 11:FME7
& i2 N* e5 D  C. p8 y        INT        vol[24];
* Q: v8 J- v  }  y/ p        BOOL*        bMute = m_bMute;
: G  h+ l: M4 R        SHORT*        nVolume = Config.sound.nVolume;
0 A2 F1 S0 Z) _7 F- B# k
+ `) L3 S, h3 e" n        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- s% u! w# o( [2 C6 j( Q9 y0 F, q' ~
        // Internal1 b* V* V- S4 d- W' L
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;5 q) P/ v: d1 m" u8 K; x: c# a; x
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;4 Q* F8 x, q* q) g
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 H" Q& g0 T$ J        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;3 V6 f% `& S. ~/ _! F& X
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 u4 ?4 Z* f. I- j
; p+ K6 F+ d, o. z) _0 S) r6 R        // VRC6+ R5 {9 w& X) |( C/ P+ C
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 b: ~) d( e' V* y, D; u        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 x5 k7 g- @" [# a4 i. N# v( m        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 S' M( E0 J) E; }6 [! p# E, l
5 F; t3 S, H# c( B: Y3 J& ]        // VRC7# ~, Q! V) S. C# ~( m7 c
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
; L, k4 d  g( F; h; ^
4 v, u/ i4 S! r        // FDS. z. r6 e7 c1 k: P/ M1 ]
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;7 Q6 e0 F, }! L6 o6 }% g: U8 j

% j( n- D# H; M, g        // MMC5* e9 l  E2 ^; @+ Q4 I2 Q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 h1 [2 n! j! N7 k$ x& _% u. j
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 R& }9 l; `+ m% n2 Z* {
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# z5 |7 ^" F! ^! _/ ?! Y
1 t+ e9 r6 r% `, J3 D
        // N106
2 Q* {, q, H% L" a        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( ^; g( P% G( X8 _
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 X6 g8 p! `# s9 P
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 k& e1 J% P" _" c$ I7 z) t3 y+ A
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 k+ t  C% b; O' k1 Z. J4 Y
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ I" t: |8 d, K7 h% B$ l7 G6 q4 x        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% n, E4 q; S3 B* n3 C$ U) o$ M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) |# F5 X" O: Q" F+ }0 M
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% W& T4 M$ m; V  C' e1 K% d7 P! F5 y  Q* i( l! |
        // FME70 y7 |. q6 X, s+ ^
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ s  ?" f( m' e7 S# ?
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ g4 ^) H; B: |2 H! `, b
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; M( O$ H2 p, A# n7 P; H$ R9 E2 |
3 R9 w. d8 E  e) t1 F//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ [: j" o! P$ Q8 C/ _/ N        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 A' g  {& z0 W1 q6 l) W! R7 K; {% l* I
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ J% E8 ~3 C- X- U$ I        if( elapsed_time > nes->cpu->GetTotalCycles() ) {& L, a9 D3 b  w: H% G2 A
                QueueFlush();- ?! r: n4 Q0 S; Z1 ?- z
        }
9 y+ s! v0 t# G4 f0 P$ W% [. B+ z) f$ N5 f$ h. K* P! q
        while( dwLength-- ) {
( G2 C1 a- O) X, ]! U% |! M* z                writetime = (DWORD)elapsed_time;
8 G  J/ C; c2 M. p4 C9 G' [" m5 Q: P
                while( GetQueue( writetime, q ) ) {
2 x) ~, s/ @' A6 R# m1 X( `                        WriteProcess( q.addr, q.data );
" p! K% ~: E1 z: H                }0 r! ~8 ?+ f1 Z& g9 O( z- J
; L" B9 B0 ~8 A. _9 R* G: D( x
                while( GetExQueue( writetime, q ) ) {
; p' j7 Y+ j3 `" c0 e7 x- W' p                        WriteExProcess( q.addr, q.data );
, V) w0 }1 `. P                }
1 v0 B; P' x: C- X3 g$ U0 L8 Q" f1 h; {+ Y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME75 ^# Y! Y/ t$ m8 x! i* A
                output = 0;# N* W7 O. j+ \3 C' D
                output += internal.Process( 0 )*vol[0];6 g0 u2 W3 Z0 D8 V! a3 m
                output += internal.Process( 1 )*vol[1];
3 p' q7 v' q3 S& I2 J; X) N9 Z                output += internal.Process( 2 )*vol[2];1 O$ ]! P& c0 H! }
                output += internal.Process( 3 )*vol[3];
8 ~* s5 k1 y. h1 U9 s                output += internal.Process( 4 )*vol[4];6 \5 a  `! R' i" Y
  ~, }8 I) y( ]
                if( exsound_select & 0x01 ) {
( x- ~7 ^  D, z& l                        output += vrc6.Process( 0 )*vol[5];
7 K! f- d, j) @; V" d2 j. ^                        output += vrc6.Process( 1 )*vol[6];
+ x6 U; N2 M8 X  r                        output += vrc6.Process( 2 )*vol[7];
) Y, X& H& z' v' Z                }; Y" I" t" @- X) g' j
                if( exsound_select & 0x02 ) {
% [0 T8 p; l' Y& {7 i; C3 @                        output += vrc7.Process( 0 )*vol[8];
' e1 {* ~9 U) V7 f. G! Q4 E                }
# l! c& C  y) C7 m8 S                if( exsound_select & 0x04 ) {
: Z' v, P, S3 X8 H8 ]                        output += fds.Process( 0 )*vol[9];1 v$ U0 k3 @) o
                }
+ {3 F4 |" {* }: x7 q; W1 |# R                if( exsound_select & 0x08 ) {' w7 x: `8 U# z0 a! G& s: g
                        output += mmc5.Process( 0 )*vol[10];
" s1 z' g# k6 K% j" i/ v                        output += mmc5.Process( 1 )*vol[11];' G; z7 ]$ E9 o* O7 j
                        output += mmc5.Process( 2 )*vol[12];4 Q+ x) h7 L' R) o
                }3 v- ]* u, i4 l& A" M
                if( exsound_select & 0x10 ) {" P  [: T, r4 N, E: X' v
                        output += n106.Process( 0 )*vol[13];
0 T5 `! h* b6 C" {% S4 e                        output += n106.Process( 1 )*vol[14];6 U. _7 f& e& e1 D8 y  H; r
                        output += n106.Process( 2 )*vol[15];- s! c. q) n& r2 k. f, K" {
                        output += n106.Process( 3 )*vol[16];
" a, ]' s/ E4 I: P: F; W2 ]8 N  g                        output += n106.Process( 4 )*vol[17];
, E( I- D. a0 C3 m8 F( _7 r                        output += n106.Process( 5 )*vol[18];2 k( p. z  g  F3 I
                        output += n106.Process( 6 )*vol[19];
: P: @$ \# ^- K                        output += n106.Process( 7 )*vol[20];" }8 n6 [& Q: q+ t
                }6 u( L+ j& m8 b; t% B7 c0 c. b
                if( exsound_select & 0x20 ) {6 l9 K6 K* I' Z( |9 X
                        fme7.Process( 3 );        // Envelope & Noise
% e/ `4 c& n8 O* r0 H0 r: K) ^) _2 V                        output += fme7.Process( 0 )*vol[21];' U. U' n& e( V9 B  _
                        output += fme7.Process( 1 )*vol[22];9 U, K; q7 y' v, D) _, i* j
                        output += fme7.Process( 2 )*vol[23];  r0 ^+ q& \1 b- l! h
                }" v- j) o  w! q$ s! {4 p
  \0 r. A7 \9 ?) q9 m: k1 R
                output >>= 8;: x4 C/ w0 R2 ^4 l& a+ _5 l
9 S2 r3 A1 n: y  s% N9 b
                if( nFilterType == 1 ) {
+ R  n4 \3 m3 e! c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), o. p7 |% Y- ?6 c: h, q& Q
                        output = (lowpass_filter[0]+output)/2;2 e5 o% T" R. M1 o7 Q! o
                        lowpass_filter[0] = output;
$ ]/ `- ]/ @. r+ D0 A                } else if( nFilterType == 2 ) {
+ H# W* x- T4 y! P                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)  W+ \4 s. U- V) O" B
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;) B5 G+ T# @* _) Q- q# O
                        lowpass_filter[1] = lowpass_filter[0];1 z! ]! r/ `: L5 u3 \  R/ U
                        lowpass_filter[0] = output;
2 }; W. D, P: D7 S+ e                } else if( nFilterType == 3 ) {2 \4 V; n4 }( D
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
& Y1 k3 A+ Y" u5 F' a                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 p3 q# Z% s( d
                        lowpass_filter[2] = lowpass_filter[1];8 E/ D% M  p8 }( y$ X  Y* A: H8 h+ B- }
                        lowpass_filter[1] = lowpass_filter[0];7 f$ g4 I5 J! l
                        lowpass_filter[0] = output;' n- q/ V& }; X* b0 z' ?7 }
                } else if( nFilterType == 4 ) {
3 ?* Y$ Q- F1 z, X# p                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 W3 H7 z4 t+ U                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;, ~) t; b3 l  z; P- Y1 S! C
                        lowpass_filter[1] = lowpass_filter[0];
( S, H2 F3 {; `  J9 C! M* X                        lowpass_filter[0] = output;: f) h" ?5 Y- V# P5 I( O+ Y# L" P
                }
9 B; m: \# r+ A6 W& D  s7 l, h% \% e0 L* r2 N
#if        09 S  i8 l' r: c
                // DC惉暘偺僇僢僩
- Z4 u( O; m: c; X" J$ S$ r                {
* z! B1 ~' ^7 i) M% i3 z                static double ave = 0.0, max=0.0, min=0.0;, Y/ R& x/ X! x9 i8 t5 N! D
                double delta;: J$ }% |  e5 d- K' T& |
                delta = (max-min)/32768.0;( G+ v, V; [$ F! T" K$ {
                max -= delta;
1 L/ k5 Z( f& A* T( X                min += delta;
2 a' r: }$ R* H1 ~4 c/ k                if( output > max ) max = output;
9 q% I) N) \% S& K/ P1 T' J" @                if( output < min ) min = output;
2 A" H! m6 E) H  F7 U# j( {# x                ave -= ave/1024.0;5 {* g4 W* I- U9 z, @5 W
                ave += (max+min)/2048.0;* f% p+ N8 t  L
                output -= (INT)ave;
, j& \; K9 e) h, [, h  d7 z                }
+ i: `$ V# n" N% x7 v# U3 G#endif/ f& o; F% u; V0 V: P9 O! v
#if        1
# x3 w# i  J% }0 k! U/ |7 u                // DC惉暘偺僇僢僩(HPF TEST)! N/ e" A0 S4 k) v7 S6 Y# x/ \9 e
                {: {, f. k  l, B- @
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);2 U0 ?( e  T# ^2 i- i' Z
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
, o/ k$ M: r: s" P  D! I                double        cutoff = cutofftemp/(double)Config.sound.nRate;& c$ S  r2 B3 r. i
                static        double        tmp = 0.0;" U/ d1 r4 p" q. F+ V
                double        in, out;
+ O' [+ @: I$ }* T3 R
8 R4 K% l% v7 u                in = (double)output;* m; a! P+ ?; o. v) K' ]
                out = (in - tmp);
, T$ k: X* N1 \7 w                tmp = tmp + cutoff * out;: o$ N2 ]6 ]$ i1 _6 d3 ^! c
* L8 _! x6 x& H+ s. T+ I
                output = (INT)out;) q3 w- G, c5 g6 B" |2 o2 a
                }# u: s2 [1 M( R
#endif
5 U0 F! q5 i8 ?0 J3 d1 J#if        0
" O& X' U1 |; G                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
! d& \3 d% e' g5 T4 R                {
$ Q# H9 \8 i* X" P8 S( G                INT        diff = abs(output-last_data);) e% d$ g' L& j" i
                if( diff > 0x4000 ) {
9 [. e/ D( Y. H' ]0 L; ]                        output /= 4;
# p  d) K) G$ C2 j0 d: q8 y                } else : o7 h# q; ~- C
                if( diff > 0x3000 ) {
; |% k& ]& t9 i2 O1 z: C* _7 [) l                        output /= 3;+ D  X, U4 ^# _  |' V! l
                } else* e! n) a+ X9 x0 a2 d+ _5 ^
                if( diff > 0x2000 ) {
1 u4 k, `6 R' T6 ~6 o, d                        output /= 2;
1 n& K5 r. Q5 M- Y7 y, R                }" T) N( ~0 J. f1 q. O
                last_data = output;
- l" @* ~4 J# K0 d& y) i' h                }3 X1 d- C0 t2 q% N" q
#endif
5 v' D* i" _' v  D                // Limit, \3 ^% f7 |6 `2 V0 q5 c, t
                if( output > 0x7FFF ) {1 S% y, c! e) s  [
                        output = 0x7FFF;
# K/ D9 A4 ?, c( u: S; h$ O2 v                } else if( output < -0x8000 ) {7 r; s3 Z3 @& ?
                        output = -0x8000;
# t& I4 v% Z- \                }
: @! D0 s. h% p  H
- G5 ~* V) }6 l/ i                if( nBits != 8 ) {
6 E. H1 z5 F! W                        *(SHORT*)lpBuffer = (SHORT)output;
1 R) v5 L. Q! L( F% ^4 Z                        lpBuffer += sizeof(SHORT);: L& j( S, R* T
                } else {
! }, v0 |8 @- ?/ j2 }/ L+ x                        *lpBuffer++ = (output>>8)^0x80;
+ h, O4 h5 a. z- C  r                }/ I0 {5 Z+ v+ Y0 M, e1 ?
- r; `! M1 Q! ?. F# x: v+ |2 N
                if( nCcount < 0x0100 )
6 K5 V$ M1 B0 d- _1 @                        pSoundBuf[nCcount++] = (SHORT)output;  J8 ^8 ~' H# M: X+ E5 ?5 k

0 t7 O$ G; V& |% Z# P9 S$ F//                elapsedtime += cycle_rate;' R8 @4 x# M/ e- v. j
                elapsed_time += cycle_rate;- ?4 F" Z& l/ [" \- U0 _1 m4 H# |3 t6 U$ E
        }
( v, g( g1 Y3 x, Q
4 }7 U+ v6 W- w7 h2 v, C7 [#if        1$ {* ?; w  `/ M0 x& u) m
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {1 K. `, j- E- n" G
                elapsed_time = nes->cpu->GetTotalCycles();% M5 g# v6 |: r
        }
2 V$ T1 M( d( g$ \3 v1 U* e% F$ O        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& ~' E# {+ ^, K" `  Y
                elapsed_time = nes->cpu->GetTotalCycles();" ~9 o2 T& \6 _( q: q# |
        }' M/ N& |  y9 C! O
#else1 a; C5 h, ~7 n, z8 V1 k8 R
        elapsed_time = nes->cpu->GetTotalCycles();
: K7 L: ~* i0 [! [# ^  Z* I6 E3 C#endif; b, _( c" T. P# k" J* u# S" y, ?
}
4 B; a; h) p( R' Y$ w( b4 R# u$ S* o: v; o. A9 [
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 {4 x* H% c! a% X+ B# a; [7 fINT        APU::GetChannelFrequency( INT no )
: K; `7 y0 M. f; o9 f. S( x4 h4 a{& f- `1 T0 e1 t7 G: B
        if( !m_bMute[0] )
, E4 _2 g: v8 Q9 u; @, L# ~1 u' a                return        0;
! c2 j! _- U6 J3 U; P3 R7 H) r; F3 ]" X) z
        // Internal7 F. G5 W% Q9 f' B' Q6 `$ C
        if( no < 5 ) {
3 S8 R9 Y! K6 c- U4 U  V# T                return        m_bMute[no+1]?internal.GetFreq( no ):0;  Y# B$ q0 t( j4 G) u3 @
        }
& u% t, P" E# J* H' {3 \- [        // VRC6  S4 f9 g3 ]* K* P
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {+ n0 \' R$ d) J) w$ A% ^
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
2 M# g0 o3 P% t3 D# ~' w" M        }, f: G% O; o5 s8 _
        // FDS
1 @1 P4 [& d0 w/ ~        if( (exsound_select & 0x04) && no == 0x300 ) {
9 L! U. A8 g3 E$ L  l$ _                return        m_bMute[6]?fds.GetFreq( 0 ):0;. Y3 {4 v9 ^& A4 c
        }  W4 i. i% Q1 s2 p" E
        // MMC5
1 `/ r: g7 L) M# x2 O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {. l# ~4 M% f( Z0 ^1 F; _7 J, H4 @
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
8 `+ X) g" z5 ^/ T0 `" Q1 q4 }4 p        }
# B( ^' u( A) `& }5 s        // N106
9 F) P  ~, K; L$ s0 C        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' x+ w- Y: c+ ^& m  q- B. F, B                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;( H+ H2 N4 z+ D9 w4 c
        }+ {4 W( s; E- l
        // FME7
& U3 v# b: Z5 v: v( c        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
. y" P2 D: f" l& R! I                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;. }0 o7 I; P; }; p6 f% D
        }
/ G! a) G, ]/ s        // VRC75 L3 a) W1 ]; q5 f
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
; ^7 t! s! |  C3 F0 d* k# M) h                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 i3 H. G8 H, A/ s- O3 m
        }% \" X- d; J$ _( M- ^3 h7 V7 c# c
        return        0;9 D# p" {: @& F2 x5 U" f- v5 s
}+ c% |4 q7 B, n# O
5 S& R2 m/ L; R
// State Save/Load
( i. J, w9 e+ o& V8 cvoid        APU::SaveState( LPBYTE p )
+ ?& }" o0 b4 X8 |' `5 s' s{
5 v3 A) c* K( }+ v% }( m/ w9 m4 ^#ifdef        _DEBUG0 x  {3 D. Q3 G, ^6 H
LPBYTE        pold = p;3 @# b7 V! ]# v. F+ |
#endif; [# ^* V$ z) ]- Q! Z+ }

( Z& Z9 V' B, x' P" C        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞8 q+ f' {' s& H3 n% x( L( _& x
        QueueFlush();
: K. n, b5 `( {4 q: C  S, b. K9 A1 Y2 n
        internal.SaveState( p );
! o9 q! G* x( ^/ {0 H' H. J        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 d# b4 F* r  `" P( r& z; {- n

2 D2 S! {4 o9 Y" x, F" Z# s# c        // VRC6
0 v; B, n2 u; x9 D. s* c, H4 w        if( exsound_select & 0x01 ) {
) w" i! w. s3 |" w                vrc6.SaveState( p );
* D) G, a. j5 u# Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% W. F3 o+ A" e* g' |- h* ?/ s        }
+ t& z; Y5 u* b5 H0 k        // VRC7 (not support)* ~+ [6 C6 L, E/ u5 A5 l  s' |
        if( exsound_select & 0x02 ) {+ g- H( G( V+ u  j* S
                vrc7.SaveState( p );+ I: W7 |6 P4 C  ^( [. y( M4 C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) `* C9 I( T  J& O        }( L9 S$ Y8 Z( A1 e% h7 @/ e
        // FDS
. k1 S7 w% t% w: t        if( exsound_select & 0x04 ) {
$ Z7 {5 d- G2 `# _5 \9 S                fds.SaveState( p );
, v  r) h4 _3 _; ^; e: e  R                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  G" R* |& t) s4 a% S/ P        }
7 h& R  o! R# [! X: ]" d2 N/ q% `        // MMC5
! e. Q- o; h7 `$ k; w; o        if( exsound_select & 0x08 ) {6 G: F9 Q; B9 X" V- D& a) q
                mmc5.SaveState( p );
9 [: |$ @5 h3 x: a) m                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" M9 }' @5 a% G: b3 c' m
        }
; r! ^3 V* T% C' p        // N106
5 e1 q4 @/ }% e        if( exsound_select & 0x10 ) {  B8 M8 [  P& _/ X) S- |
                n106.SaveState( p );
# K$ u' A1 V, a$ K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 H8 N) \7 L% G1 Q0 C' t
        }
1 n: j5 {" Z) B  B2 e# E' Z        // FME7
$ {" M% @; X; u8 O5 i1 ?        if( exsound_select & 0x20 ) {8 M% p1 D1 i( t8 \2 W3 b
                fme7.SaveState( p );
6 a3 A& G) m9 L                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* t) R: y, }" c& D, {
        }
4 s9 \- v0 E" d- F- E- g  M0 E4 P
#ifdef        _DEBUG7 Z3 P; `$ x) j
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );1 v' e6 R% L# z, y2 b
#endif. t7 x4 H8 D5 m3 c$ F# `; i  S
}
+ L- V8 }! e( m/ `
& W+ r2 t% @9 [1 S4 E3 I" ?void        APU::LoadState( LPBYTE p )3 ^1 p# _  Q# F% f
{
+ Y9 u: e8 S+ h! b1 |# ?3 }        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! \- S$ B4 @5 V1 _8 \
        QueueClear();# ]& m6 Z+ i: p- P/ ]" F

% o& f2 m/ G0 I0 T6 X5 c3 D        internal.LoadState( p );7 D, v$ _6 ]) j4 C% c6 o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# c2 P  u0 ?+ _! n- H/ C
1 ]) B6 ]1 {' ^/ A9 I6 |8 J! N        // VRC6" s6 d* P# k+ c: d% W( A" v
        if( exsound_select & 0x01 ) {
# D6 ]7 |- ~$ S/ F                vrc6.LoadState( p );
. x& F, z% N- x                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, H8 P, o. ~3 T( C2 C" y0 V# A3 V. z9 ]        }, s* S* _, {) Y5 t
        // VRC7 (not support)$ I/ T0 i  F0 W* {
        if( exsound_select & 0x02 ) {" d5 Z3 x( m8 W# U* v( r
                vrc7.LoadState( p );  T* ]1 P$ ^# n( ]' a! y* ^0 z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ |& m# j; Y" u+ j# c& s5 o- x        }9 g* i. N1 _1 ^4 ~
        // FDS
7 A3 d: r) e) ]' Y) i4 c        if( exsound_select & 0x04 ) {
8 V& a) ]$ g5 ]) P' F6 z                fds.LoadState( p );
( Q( [* ]8 w3 @# X3 `' V9 t) V                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ _1 z! p& |' {+ V
        }
% ^/ \+ M) A  g4 M        // MMC5
$ b* ]$ t* Q; L. h/ B        if( exsound_select & 0x08 ) {
: H! C. C6 E5 P& N+ w$ h1 Z) z                mmc5.LoadState( p );0 `+ u- p. V# D0 C
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
% }7 ^; J  G( A! K1 W        }
( f$ c+ U- ]+ W, p$ M        // N1067 @$ D6 K, `' U$ u6 R4 N* |
        if( exsound_select & 0x10 ) {
1 I" X7 q4 _( i* L                n106.LoadState( p );
- g# h2 k* A* G0 v& M                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& v3 c4 w, o( P        }
1 [  {; i- [# z6 @        // FME7
) u$ m8 D: q% ~# [/ r) @' p4 n! u        if( exsound_select & 0x20 ) {
  g5 ~6 s- ?# M: ?                fme7.LoadState( p );
' S" m2 j2 }- d# h- }: i                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" u; L8 F' e6 ~9 N
        }, B* s- m7 f2 ^* @( X( o+ q
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 9 _# r0 S8 R4 H/ p
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
+ U& h1 A" z( I: f感激不尽~~
; O4 Z1 P6 B" g3 V. h; B
恩 我對模擬器不是很有研究,
$ }+ N& a- ~1 M5 l雖然要了解源碼內容,可能不是很困難,9 z$ B4 B# p* N* V
不過還是要花時間,個人目前蠻忙碌的。
0 Z! J, B' {: V8 _4 _6 B2 J2 I$ U- Y& f  ]/ f
給你一個朋友的MSN,你可以跟他討論看看,4 t7 v( w2 |  R+ ~1 [+ m
他本身是程式設計師,也對FC模擬器很有興趣。9 X; s" v1 Y4 `( _

1 Z* w+ ~0 }9 L0 J0 O- WMSN我就PM到你的信箱了。- n6 I0 u2 F4 ?" G
+ ], U3 h7 T) ], {0 C
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ i, ^+ R/ R+ {' \3 Q0 q" o
呵…… 谢过团长大人~~

) ~% R6 C1 E: B  v! @
7 p! \/ p& Q/ h, E* ]  f) h哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
6 o6 a4 O% `  y0 [5 ?% Z* l1 [& {团长的朋友都是神,那团长就是神的boss。

$ y* m. D9 Z* `9 j  [, B6 f哈 不敢當,我只是個平凡人,
! a2 T4 P4 a. R7 m7 M9 @1 f! S要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙8 T/ o7 O, ~# n# d3 J- P! c
ZYH2 C. B) P! y, ^( K7 C+ I
QQ:4147343066 i* ~. b/ H% ?" L2 T$ _0 D4 j# N
Mail:zyh-01@126.com
8 b- F+ b( ~7 a& p+ ?6 \( e
. M" ^' P% Z4 ~( x3 p! r他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 $ v7 p; s2 s! X  ]; ]2 W$ |7 c# k
再次对团长大人和悠悠哥的无私帮助表示感谢~~

% D6 T" D0 Z& x  V% ?. Z6 o不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-5 05:48 , Processed in 1.096680 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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