EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" u4 s0 V0 G% K6 T$ N  y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 [  u0 e3 Z; c这里有相应的模拟器源码,就当送给大侠了~~2 T: L0 A' h& U: M* k4 a; v
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 2 X8 c! H4 [' [' l+ p5 }( Z* y; E
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 P. e, w2 B% T1 t6 _! @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; o( w/ C! V4 O+ s/ L& Z) F这里有相应的模拟器源码,就当送给大侠 ...
6 q% ^% T6 z6 {/ s# _
聲音部分(Audoi Process Unit = APU):) r5 I: h1 h* b. z/ h* L8 U
.\NES\APU.cpp
4 h2 R$ n! }% S; `, ]! M.\NES\APU.h* y5 }# H, O+ W. U
- c1 N1 U" u: s7 Z+ q+ K# I

8 X6 l; E" F, [/ q影像處理部份(Picture Processing Unit = PPU):
2 g$ O% W5 _' d- P5 Q.\NES\PPU.cpp# P" w& Z, W6 m3 c
.\NES\PPU.h
  Y% \$ s0 V, p; `* k/ |" ]+ k. j4 Y' M4 M
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, {! X1 y; Q# I% Q  a8 ?$ F
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 _- H% W* i& V$ m4 s, [2 |- s( A(由于很多专用术语和算法机理都不明白,所以看不大懂……)
/ `2 l, y$ N+ z3 u2 u2 Q! C//////////////////////////////////////////////////////////////////////////
# ]. u8 P7 |) [1 Q) }) b//                                                                      //
1 f7 b# D2 b" Q8 U9 C/ M# l( T//      NES APU core                                                    //6 d" ?# A- ~* R+ g0 p: H# U
//                                                           Norix      //  L4 H' u( Q  ^& w
//                                               written     2002/06/27 //: J3 X5 X3 @4 L) n9 S" E
//                                               last modify ----/--/-- //
0 d) k- K* P. v# ?//////////////////////////////////////////////////////////////////////////+ ]0 k, L: S. A7 L
#include "DebugOut.h"
: V; e2 B: `- C7 c; D- [#include "App.h"
5 C5 }% C8 Y  C* i#include "Config.h"1 D: c& k. f; w& a2 y
% K) f3 @. R; A' n' m$ u
#include "nes.h"
3 {  G7 ?& }! o( z" s+ K4 P% n#include "mmu.h"* u/ [* ?' P/ q1 o% g+ U$ W, t0 p
#include "cpu.h"
3 t1 d" z4 a; p! q2 X; V6 R! G. B#include "ppu.h"
5 X( ~7 P( _" p$ \1 h#include "rom.h"/ k6 [! @4 Z1 L' \. H
#include "apu.h". z6 r6 P! u' H

2 p2 W' X* r6 g1 K, u: Y7 j// Volume adjust$ g: C+ t0 a* c  F) I# t
// Internal sounds
* }/ A- `6 ~: ?8 [/ i7 u#define        RECTANGLE_VOL        (0x0F0)) p& ~& H! e6 t' v; u0 o3 j! e
#define        TRIANGLE_VOL        (0x130)
7 i2 n+ R4 ?' r: g( R, b9 J, }) f#define        NOISE_VOL        (0x0C0)
' G1 f) x9 t4 _& F#define        DPCM_VOL        (0x0F0); c" O9 @: R# _+ \
// Extra sounds* x" M/ N! ?; p3 f, H" d
#define        VRC6_VOL        (0x0F0); A) i5 w6 A& {4 a" X: A
#define        VRC7_VOL        (0x130)7 P! p: x& @: o9 `
#define        FDS_VOL                (0x0F0)
: a, O& y3 a9 Q" S#define        MMC5_VOL        (0x0F0)3 o; r; x5 g, |1 [( c% l5 X3 w
#define        N106_VOL        (0x088)7 y" g4 h2 i% M! n% M4 L9 I# k4 s
#define        FME7_VOL        (0x130)+ D& F  d( S# e7 L

$ P; P9 v5 G6 pAPU::APU( NES* parent )
4 K% J; S6 b: H& L- I- T- k{
$ |5 e4 q; Q: J/ S1 S        exsound_select = 0;
! V) y% n2 I6 ^4 D1 w. [  Q, ]
, X# ~6 ]3 o, Y2 _6 ?+ O2 w% |0 ~        nes = parent;/ h" W1 h6 W1 i8 R
        internal.SetParent( parent );
5 [& H5 w( h% P& Y+ I/ e  |3 Y/ i+ a0 ^+ r* p% F) f
        last_data = last_diff = 0;  ~5 {7 ?4 q$ p% t1 S* p: g! f
8 r. x0 k; t- E$ [( n1 E3 c4 g' ^
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! \' s( I7 r- C" g% y7 M9 ~3 S

- K8 V8 ]$ z' C$ r: N8 e' ~        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );2 S) ]1 _1 h' y. y3 K# ^' M
        ZEROMEMORY( &queue, sizeof(queue) );( j( w! I. V* o0 |: E
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& i; [% @3 z$ y

" [" L: ]* S) y! U2 U% K        for( INT i = 0; i < 16; i++ ) {
( b3 l$ [0 l$ |8 B  w$ @                m_bMute = TRUE;. p# \( ]$ C4 u# W3 r. z  \
        }
. Q+ H7 P$ r8 D}
; N7 w( [% ~' ]* U! L; Z1 J0 u& D$ v( `4 S8 X6 Z
APU::~APU()- M3 ~  b" k) \! N1 x
{$ \5 w+ P# n% g/ f2 C* G
}
4 D4 Y! g2 ]7 V, c# S- P% ?( D% B! A# q
& ?; g7 ?% z+ ?void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: o" u( S& X  v  x1 t: l' B1 a5 ^{
* l3 \5 C8 d& Z        queue.data[queue.wrptr].time = writetime;$ r8 B8 Z% D3 X3 _) T! Y0 k/ @
        queue.data[queue.wrptr].addr = addr;
8 \8 D3 y* H% L/ F7 n) z        queue.data[queue.wrptr].data = data;
& x5 k: q. h! m& o8 G) k        queue.wrptr++;
- x$ V" d8 r* c! n+ L# ~        queue.wrptr&=QUEUE_LENGTH-1;$ |' b+ u/ f; y# m+ }' C
        if( queue.wrptr == queue.rdptr ) {
9 G% H* {% B# |  [                DEBUGOUT( "queue overflow.\n" );$ T; w3 F. N7 n. q( P* ^, J
        }! Z% u/ W* G! e% o
}) S) p7 s  l! ?: W5 z

# c8 x/ f& q7 J3 K4 xBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
) ?1 q- G. [) O+ V* s2 s{% Z% W8 W; [9 t. t
        if( queue.wrptr == queue.rdptr ) {+ z9 n+ y8 O2 {: B, \% W9 W7 Y
                return        FALSE;. w' }$ @0 i( o5 a
        }8 P0 z; b2 `" d3 T
        if( queue.data[queue.rdptr].time <= writetime ) {
& e. C: k" m. t, R  Z                ret = queue.data[queue.rdptr];: G  q2 E# l% R8 I( Y# d# ]
                queue.rdptr++;
" Y% D- v3 w6 H: J2 k                queue.rdptr&=QUEUE_LENGTH-1;
! A4 }0 Z0 d  L* ~/ ^                return        TRUE;/ i# g9 x* b! l/ A, E
        }+ i2 @3 a. X( y; }& T
        return        FALSE;
, S* |2 r0 B5 |- Z: g- d7 S8 K}
: @. n) [! p" a& H) q
( Z5 C' O+ f# I* t5 r  ^  Kvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )& y0 W9 y5 n; k+ ~' Z) ]$ l
{
# Y5 }8 }  y* G8 D        exqueue.data[exqueue.wrptr].time = writetime;
! E4 O+ J0 b/ ^. e! k2 R5 I        exqueue.data[exqueue.wrptr].addr = addr;+ B. A4 M/ h, _% {( }8 m# X) n
        exqueue.data[exqueue.wrptr].data = data;
& V; l4 ~5 Q6 D( G        exqueue.wrptr++;0 q3 g& B6 x- r1 Y
        exqueue.wrptr&=QUEUE_LENGTH-1;& S0 @. H- N) `, z9 U5 K
        if( exqueue.wrptr == exqueue.rdptr ) {. T. l2 H/ J+ [, g
                DEBUGOUT( "exqueue overflow.\n" );0 T0 g7 m- f% b/ b
        }
" v. s- ]2 C  o) H$ B}* `0 I- Y( c" z* ]% [1 l2 K
% P: j" I5 g6 b
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )0 E7 ^3 U5 `$ ~. n: Q& ^8 i
{9 ~* c; p- J2 W( m. x6 l: p" e
        if( exqueue.wrptr == exqueue.rdptr ) {
; ~0 s+ X+ Q3 i                return        FALSE;
* p, R& j! Y6 I! m" U        }9 l4 h1 G9 H+ ?7 E" ]' C
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 P# c9 j# {6 ^9 R# V
                ret = exqueue.data[exqueue.rdptr];
+ n1 n# `& y6 {* G8 w) V# J                exqueue.rdptr++;
' i: d' x  X7 }3 g/ i1 q$ g7 C                exqueue.rdptr&=QUEUE_LENGTH-1;4 y/ {; S9 a/ T. K" I; K0 ~" _
                return        TRUE;
8 q8 J8 g, G) V6 E. A7 u        }
2 ~+ Z1 E! o# L, ~! }4 H. [# C        return        FALSE;
7 q  [* u$ E" T) _5 }9 f}+ W* H2 `: Z! U. O8 t' |! W
$ q. n- Q) a! R8 H1 `
void        APU::QueueClear(); m3 X! D/ @& q& }  \* f9 f4 P
{
8 _9 V: b0 _0 g( l- ^        ZEROMEMORY( &queue, sizeof(queue) );  B! P+ v) i* T/ j) A8 [- U. d4 l$ v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, j' h  }, F# c; _% s8 ^3 S}2 v. D& r+ x" v% `1 s" Y
+ x/ I! g; d5 r8 l& ^
void        APU::QueueFlush()
. Y6 r4 U7 M5 ~6 O& h. a0 N{
) g$ g+ Z: y4 n6 E$ t# d/ @. W* k; E        while( queue.wrptr != queue.rdptr ) {9 E$ m8 n6 S1 i2 N4 h  G( H
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );* e9 M# f8 Y* l# ^# i5 N+ a
                queue.rdptr++;
2 B$ S" o; U- P. D+ \  w5 M& ?$ O6 \7 p                queue.rdptr&=QUEUE_LENGTH-1;7 \$ L/ @% u$ ?1 k; T( r
        }
- z: \4 }- L9 B; c4 J5 \& W
$ y2 ^% M  F% O# i  R& ]        while( exqueue.wrptr != exqueue.rdptr ) {
( `+ C+ \7 C) a3 i* |                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
, A! o' X, c% {                exqueue.rdptr++;- G" C, s8 V. R0 s8 x2 q
                exqueue.rdptr&=QUEUE_LENGTH-1;
& s- m" @, }% G* q. F( |; {  B        }
1 V* R. S' ?0 B- i}
) C. L! S9 j# E2 s0 l, @! I! w; {+ G0 Y9 M1 @) B
void        APU::SoundSetup()
! _2 W$ R  u3 A4 V{
' U: @# w5 f! v5 G3 i0 ]        FLOAT        fClock = nes->nescfg->CpuClock;
1 {" W. S: ?$ u& {, B        INT        nRate = (INT)Config.sound.nRate;4 x2 I) r+ S3 V, b3 }: ]
        internal.Setup( fClock, nRate );
% w, [/ Z) z6 O& q, G& l        vrc6.Setup( fClock, nRate );
4 c6 a* r3 L2 B' z        vrc7.Setup( fClock, nRate );2 g9 e+ W7 R! @0 q) E, o; S
        mmc5.Setup( fClock, nRate );. M: x. h8 W% o: `% p0 N) B7 K
        fds.Setup ( fClock, nRate );
! h6 b1 U/ F, w- B; y) D& H. x        n106.Setup( fClock, nRate );! I! S; d( l( n
        fme7.Setup( fClock, nRate );
+ V# ~+ E' w3 a; s4 a! D. \}
6 y; Q" t; l0 B' _  `+ M1 e( L
! w; X2 H3 \! g: H  yvoid        APU::Reset()
. k8 |2 f8 |' w{
, g; S$ x; D7 x6 a  P( g        ZEROMEMORY( &queue, sizeof(queue) );
& Z. r* G% a7 \        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- Q' ?, _2 _/ h6 |* N! K7 ^
8 g' ]; X1 q/ q% Q1 D6 Q0 y* P        elapsed_time = 0;$ F/ F0 w4 G0 R9 w2 n

# A, ^2 v- L$ E: L        FLOAT        fClock = nes->nescfg->CpuClock;. B% b! e8 O3 ^5 ?8 N6 m9 b. Z3 e
        INT        nRate = (INT)Config.sound.nRate;: a2 Z: n2 Q* ]2 q! |
        internal.Reset( fClock, nRate );
8 |( ~( q5 N2 S$ M" y2 G$ {        vrc6.Reset( fClock, nRate );
7 j$ J  a9 n8 e. H/ K5 W        vrc7.Reset( fClock, nRate );7 N, q/ w5 ?" y3 B6 T7 W
        mmc5.Reset( fClock, nRate );$ d) l: p0 Z" @; o
        fds.Reset ( fClock, nRate );
- q9 G4 j5 s4 M0 f( a" S' E4 I        n106.Reset( fClock, nRate );! ^8 K- R8 F- s. S. S* L0 E
        fme7.Reset( fClock, nRate );  j' x( J& }3 @2 C/ ~! S* r

: f1 k* l% ?& @5 x2 e, F. D, G        SoundSetup();
& Y0 t) f9 v) V( K8 N! K, {}& k9 u7 d" j: D, d
7 w6 O6 H' x/ e
void        APU::SelectExSound( BYTE data )
9 k7 A8 |; Z1 W. X9 H9 c{
9 o- f) V/ A2 p' v' g/ i: W        exsound_select = data;
) M" `) h8 y8 X/ j% w}
+ l& f+ D" F3 A( ~- [1 ~* R3 e# t$ n. }- y
BYTE        APU::Read( WORD addr )& ?$ S( v) V7 Y8 D  p& z
{
$ ]: w" l( ~3 J6 K  b        return        internal.SyncRead( addr );/ I+ |4 _( V/ \& l. [) o+ [
}' A% f2 D' Z9 H. `( O  l
, P0 D* w, j9 A) L2 S0 p& |
void        APU::Write( WORD addr, BYTE data )
* [+ P) k) n; O' T: D{6 [% [' @* K$ G
        // $4018偼VirtuaNES屌桳億乕僩( e- n. b* z( Q/ ]6 u
        if( addr >= 0x4000 && addr <= 0x401F ) {. _! A3 y; I3 y( L. l8 E
                internal.SyncWrite( addr, data );
% E4 L* l( p! I5 m                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 G6 a+ a; h/ z2 `        }
' U) }* E& j. ?2 P+ O2 s}, @$ z0 s! j, A0 G
  t3 B) }8 w- D, ~: k* ?' j  X
BYTE        APU::ExRead( WORD addr )
/ d6 g& [" ?" T4 l0 z{
8 g+ t# p6 L% p; o5 `BYTE        data = 0;2 H( o! _2 X- t4 G1 f3 y
: v2 g2 t& J9 c) d6 U
        if( exsound_select & 0x10 ) {
7 @/ [* l! A& u- n! M  y2 B                if( addr == 0x4800 ) {
& m; g$ I6 p+ X" m. C: S; U  N# H  P3 B. S" Z                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. V% j. r& K+ ^                }3 Y! T# ^' X* g- y4 X
        }
+ J6 D: c! U% }( v6 z$ K  j2 |  a        if( exsound_select & 0x04 ) {( ]1 B+ g& O- F( V
                if( addr >= 0x4040 && addr < 0x4100 ) {
" U" R1 D2 E7 A6 R                        data = fds.SyncRead( addr );$ A, o* G* D5 L: F9 ~
                }
# W$ q9 F4 v- a2 n" A        }2 I; T* T& O; f& Y8 _8 ?
        if( exsound_select & 0x08 ) {! r( J2 k/ d! v5 T) W/ |
                if( addr >= 0x5000 && addr <= 0x5015 ) {1 d0 o  t, F+ |! H: H0 l
                        data = mmc5.SyncRead( addr );
) T" M! R# `; J1 K: t+ n: x. ]! K3 {                }1 B% Y7 G8 ?2 i6 J0 t) r
        }4 ~, u5 \) ~6 h
& _( h8 F/ {; f. O
        return        data;
4 X  t0 l" {% Q) j; _2 {5 A2 ~}1 i0 F( O, n7 _9 ]/ v7 v

* W) J' y0 T: N" x% I* o5 v# zvoid        APU::ExWrite( WORD addr, BYTE data )  D8 N1 |* p0 [) J3 z2 R
{2 r5 v8 A# C" u9 F' G' _
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
' t; {: f- m8 x  f; b- ^( G
" k6 S2 t) t, {: Y$ F        if( exsound_select & 0x04 ) {
, B- J, F; k4 u8 z                if( addr >= 0x4040 && addr < 0x4100 ) {* C( m9 k8 L: s5 z+ L
                        fds.SyncWrite( addr, data );
- T6 s% @8 b2 {" _+ V/ n' \                }5 p: ^) c# j$ F3 M' n2 {
        }
4 e9 u+ K( @' {) \; Y3 Y. I# E2 ~' ~) H3 U2 B+ R
        if( exsound_select & 0x08 ) {% l3 p  j" F/ c8 ^" X- R
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 u- K0 b! \4 P1 B, @+ a" |: x
                        mmc5.SyncWrite( addr, data );
" ]7 r' W$ E. V2 V  v/ J                }6 S! y* K& G) V4 F
        }. s& C$ a, W$ f3 d1 w* l
}1 e" O5 c* ?- x

' Z+ Z' R8 Q' j) t' Fvoid        APU::Sync()
* m! p6 g: a4 j8 {  B0 j/ W{
; Q6 c8 a8 c1 x" L$ \& ?: l! e}, q  V9 G; d- d( I5 `" O
, F# s# C5 n, F' B$ z9 C5 V& F: i
void        APU::SyncDPCM( INT cycles ). q" i/ v# {1 |, b8 r
{
" A# L- N) l2 p. J' o        internal.Sync( cycles );. y+ X! V; E$ ^

+ I+ J: Z% }) t# i        if( exsound_select & 0x04 ) {
6 ?& s9 _  w( z/ |                fds.Sync( cycles );
2 Z8 }( N+ h& S        }# B0 b9 i* o1 @" z; {; S
        if( exsound_select & 0x08 ) {
+ k, S+ A, ^4 ?3 J" ]& i4 @* C0 ?/ g                mmc5.Sync( cycles );
' \0 s2 T+ |( W  w; U& u        }# R7 p2 W" {' c! Q2 D! z
}4 N+ Y4 C, `0 E0 n7 T8 O
9 A+ J7 Y5 G5 A7 I
void        APU::WriteProcess( WORD addr, BYTE data )
5 e2 w" n4 l7 D3 V: P9 m; m! Y{
0 J; d, o$ `/ `- v$ |        // $4018偼VirtuaNES屌桳億乕僩
4 U2 D5 M. J0 o/ i0 @3 s        if( addr >= 0x4000 && addr <= 0x401F ) {! o6 @3 X) q. x' p& M
                internal.Write( addr, data );5 Z, e% O! E0 ^& s# Q
        }
2 K! J8 y, p. _. X}
) G7 Z9 C' Z$ e# ]2 s5 u. ^1 {1 k2 Z, H, `
void        APU::WriteExProcess( WORD addr, BYTE data )
, F" t. M* P0 x; @{/ a& e& J' x% j9 r" q& [
        if( exsound_select & 0x01 ) {
0 t4 l5 C5 ~4 V2 S1 A+ h                vrc6.Write( addr, data );  x+ N0 e1 ~5 Q3 Q3 f% H4 Z
        }
3 y  b! p: `; Q% B        if( exsound_select & 0x02 ) {# l4 e2 O$ ]$ D9 N
                vrc7.Write( addr, data );
9 l" U: V1 E$ O5 v        }
" q$ K+ R* v* H; p: ]' j        if( exsound_select & 0x04 ) {
# {& T0 a' x9 M3 w  P2 ?: v0 v                fds.Write( addr, data );$ h/ W; G( W. |% }3 _
        }
/ X: ^; I+ d0 H1 o2 D        if( exsound_select & 0x08 ) {7 ?1 E2 ^/ ]2 W& R2 P% K- V
                mmc5.Write( addr, data );! I' ^2 r8 m7 |5 T. e
        }
3 u2 R* ]9 ], R, k! C6 a        if( exsound_select & 0x10 ) {
5 G/ m; U; d2 N! m4 ~" C! g+ ^                if( addr == 0x0000 ) {
- f3 b! w* U+ b5 k                        BYTE        dummy = n106.Read( addr );
* u; h. h! O6 H& y& Q                } else {
( q0 B, [& @/ P) ~, T                        n106.Write( addr, data );
( c6 |4 X9 r1 d$ R$ m                }6 P& b. u0 w# z; Y, k
        }) p/ f7 K6 a6 w. J) C
        if( exsound_select & 0x20 ) {$ w# h# V# ^# b7 |) l$ `, w
                fme7.Write( addr, data );
+ H8 b* u. F$ ^5 Q  r4 j3 y        }3 j0 {* p+ |: ]
}; G; B0 O4 Q- Q) @5 C6 W

7 X) N' x* }' U/ w# Nvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )5 ?2 j5 X2 Q: H) R* \: ?
{
: ~4 W% e  @$ X: T& [/ n8 b1 {- q& FINT        nBits = Config.sound.nBits;$ P8 P- @# Y% E' ]
DWORD        dwLength = dwSize / (nBits/8);) t) T9 V; [+ \$ e* h) H$ o
INT        output;' J7 [8 a! O0 [  u2 ~
QUEUEDATA q;
8 B* ~4 z$ A+ J' h8 tDWORD        writetime;6 U4 d8 f9 X3 m( S; x8 l! u6 }9 a
( ?& p- z) D6 c! Y, B
LPSHORT        pSoundBuf = m_SoundBuffer;
' B7 s7 k, {9 D7 d7 Q# K3 z5 UINT        nCcount = 0;
! z% e9 h7 H. F  e% G
5 _, k$ ^: o8 `4 ]: G, xINT        nFilterType = Config.sound.nFilterType;$ G& J* m* Y0 x- ~

6 g- s4 c. y4 R2 n6 m        if( !Config.sound.bEnable ) {3 f4 C+ n- g8 b0 Q
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 k- o" a) a; N# X9 x) V8 W: W
                return;
/ O$ I# O; [& t        }
; D6 \' ]2 s+ k$ I% m( g! S- T
0 g3 N* d- n/ {; s$ f) c        // Volume setup
. z/ P9 d4 B, f0 D        //  0:Master
* h( C* r& m, W1 J        //  1:Rectangle 1
  n9 F6 \, a: Q$ {' A: i        //  2:Rectangle 24 N1 b3 \: `; w" c5 ]6 R, h0 E+ d
        //  3:Triangle
& H) P5 c% M- P9 y        //  4:Noise1 F" F% b( Y! K: B
        //  5:DPCM* y0 ?, v( T6 w3 J+ a# S9 [9 h
        //  6:VRC60 u0 j  h5 M3 X- j
        //  7:VRC72 g+ W  ~3 E$ M1 p
        //  8:FDS  ~3 T) l7 g7 V/ A5 N* ]# K1 C
        //  9:MMC51 w9 C0 z; s* x- i  C
        // 10:N106
( ~; }5 ?& t& O( Q        // 11:FME7! ]7 @( X, e6 b( s$ s5 r9 [
        INT        vol[24];
' t& u% e. |6 z3 C' z7 r. k4 ?( E3 @0 }        BOOL*        bMute = m_bMute;5 s9 o5 M8 v! j# G
        SHORT*        nVolume = Config.sound.nVolume;
; P" G5 b9 r4 D( R7 r, i
' W, \; R7 ~) U$ ?$ j4 h/ h        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
! a- A: T, H/ n$ k
; _  m2 X- X! U& i. K3 J7 v; W        // Internal
2 h" X" s% J: J! a( _0 ~4 C9 b* G4 |1 s        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
$ E0 r2 E1 a5 ?9 c5 r( W" ^5 x* }        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; ]5 y( V8 u7 ?! [( D2 q; h' o
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;( R9 L+ o3 Z  a. q; |  Z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
& |+ u9 X5 f- Q5 c. c% K        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;! ?/ j! K* }- M" R
/ W0 f4 `* o& @
        // VRC6
% i! i! F1 f% i1 N        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" M; _( v0 \7 k6 i9 I2 R        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 L8 _2 P7 d% D
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& Q) d. s; \$ Q) ]8 A
) M) W0 S. b! V  v0 }; ~5 O) l
        // VRC7
# A; X* z5 ^' i        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;2 F) p$ h6 a" Z( b- \* u

" L/ y' J, K1 N. ~        // FDS1 M/ z" C% D) i" M8 V& Z3 A
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
5 C3 N* H/ h9 \" g! @$ f  i8 Q
: N5 f% v' a1 f2 }# H/ s0 k        // MMC5
9 Z" L4 o* g' c4 H0 D0 y        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% f' S/ n$ B( J% r* A' z: t8 ^+ ^
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ n  q4 v  w& j5 R/ l0 g  c& S        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' w! n6 @4 a- @, J0 M

( ^( y& L. F! |9 t6 Z' C        // N106+ V% T. z# A: Q" e
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( @; O/ }* c, |3 k1 C
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; n+ V$ h' u0 J- I; q$ O        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& q  `$ `. V4 f$ M3 h9 n/ O; |& F
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ s& x- `7 F  v5 U  H5 C# }5 K        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 X8 O  M1 q& G  P* J- w* \
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: c+ Z4 u' a8 q5 o7 Q5 @) D; ^        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) A* [: ]1 ^4 P6 P8 o3 S9 }: o
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) N; ?: R) M$ X$ f. n5 x- e7 H' l/ u$ b5 ~3 O" g  g( Y
        // FME7. W" ~; J2 I( o+ U& U
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 a4 l( |% ?; L, k
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- y2 A4 Z; Q; b* Q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& W2 _6 C! z# F: }, N  V8 k9 a  H
' I7 P& y: j6 ]1 N6 P//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
( \5 F  |: X' n        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
7 r: j( ^3 ]# `3 T( U1 z. o" l6 z2 V  R& C+ I
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. T$ s  a; n" Z) q
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
" k( g% m. [0 T! V( Z+ H                QueueFlush();
, Z& V4 `* A( l: ?8 H4 u6 f( ?        }: P  q. I. B! I

! B" w  j% D( `2 o+ ~% E( w        while( dwLength-- ) {0 c/ ]. O0 l' h. c; E9 k8 z8 ^5 z
                writetime = (DWORD)elapsed_time;
0 {8 o: C! n, y9 u" g$ [* H' ~) A: u
8 U! ]2 P& R# y  E) a                while( GetQueue( writetime, q ) ) {1 N& c' x& ]$ M# L
                        WriteProcess( q.addr, q.data );
- l6 j' s8 y; q% I                }4 s- k' ~# I/ }6 [$ b
# n- {: K& |. e6 F4 N  @
                while( GetExQueue( writetime, q ) ) {4 ?5 l0 P' ~& k: z* d4 c2 p
                        WriteExProcess( q.addr, q.data );- w% w0 H6 ]) f0 `8 H0 B4 N( J
                }: G; E- ?, z, ]: \( y- _1 r

8 p( o) v# q% \+ h) V+ @                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ |, d: y# J6 W& }& y
                output = 0;
- `' H4 j' m1 m" b5 U3 _* M                output += internal.Process( 0 )*vol[0];: d) A. \9 b0 D4 e: o& c; O
                output += internal.Process( 1 )*vol[1];
0 h" k8 x. A: N+ g! _0 U" G                output += internal.Process( 2 )*vol[2];
0 {/ L* s/ \' }" F5 v9 \+ s# ]                output += internal.Process( 3 )*vol[3];
% b0 P( i' w: Z8 f0 e3 A                output += internal.Process( 4 )*vol[4];5 r& f5 C+ N8 p0 y, Y  K7 X5 ~3 c
' Q8 H/ e5 M4 v0 L3 Y) Q& L; j
                if( exsound_select & 0x01 ) {
& ?+ b' y5 c$ A3 Y" e8 E                        output += vrc6.Process( 0 )*vol[5];8 @3 a4 Y4 t  \; v2 X- N; ]
                        output += vrc6.Process( 1 )*vol[6];# {. p& ]9 u. u( L) g: T1 H
                        output += vrc6.Process( 2 )*vol[7];; h4 N& V- s$ h& v
                }
. U: L: X: K3 g                if( exsound_select & 0x02 ) {8 E# m  |+ o3 {. I1 M) {
                        output += vrc7.Process( 0 )*vol[8];9 V- H* n6 J' h5 e6 q' t
                }' g- ]# {/ v7 w/ o
                if( exsound_select & 0x04 ) {* K/ `/ Z$ r" ^0 W; I/ z! W2 Q
                        output += fds.Process( 0 )*vol[9];
8 a; q1 R2 p% Q( G                }' ]' ~$ _( Q: {6 u9 H
                if( exsound_select & 0x08 ) {4 g* s% @; f; @3 [
                        output += mmc5.Process( 0 )*vol[10];9 N/ [3 U1 u! k9 X- u$ c0 X6 l9 G
                        output += mmc5.Process( 1 )*vol[11];
" V. v/ b2 w9 h5 L; i                        output += mmc5.Process( 2 )*vol[12];
4 w$ V& [) Y: u6 i' a* L                }
) Z- L# F0 a3 Q+ Q" _                if( exsound_select & 0x10 ) {0 f1 |8 @' {! i  o2 M0 W, B
                        output += n106.Process( 0 )*vol[13];* n  @3 p# ?# L1 q; t3 O
                        output += n106.Process( 1 )*vol[14];6 `1 p2 h, X( v- [
                        output += n106.Process( 2 )*vol[15];6 T; P% x0 H; Q2 e2 j* e% R& M5 t
                        output += n106.Process( 3 )*vol[16];
  ^+ H3 q7 b8 I7 m                        output += n106.Process( 4 )*vol[17];+ f, n; `& B! n7 m& v
                        output += n106.Process( 5 )*vol[18];- |5 d  y- s. I+ Z- D
                        output += n106.Process( 6 )*vol[19];
2 ?# V: [  ?! n6 J                        output += n106.Process( 7 )*vol[20];+ K% a+ \! U: H6 Z
                }# W9 z0 z- m' d1 N- C
                if( exsound_select & 0x20 ) {
1 x+ f- A% D1 M6 w" G9 v                        fme7.Process( 3 );        // Envelope & Noise
- _- U0 i8 l% m9 J/ f7 V                        output += fme7.Process( 0 )*vol[21];
+ @+ j" @3 C! l1 j/ C; t                        output += fme7.Process( 1 )*vol[22];
+ [* u# X0 d0 q+ p; Z' t                        output += fme7.Process( 2 )*vol[23];2 V( r* g& M5 ?* A9 U
                }2 W; L; r% c; i. E( s& V) E$ [
$ V! i% `! A( x: I" ?
                output >>= 8;# @* F+ J1 ]. i; l
" r# g; H: B! L# Y3 F9 o  e
                if( nFilterType == 1 ) {  P3 R8 ?: T" h- e( P6 P0 r+ m7 q
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
/ q# Y, x5 k; ^: Q5 C                        output = (lowpass_filter[0]+output)/2;" D6 a" s2 |( z
                        lowpass_filter[0] = output;% t  S8 Q( r8 P# k7 s" S
                } else if( nFilterType == 2 ) {
) @6 I% u- S% m/ ], a5 n( M2 N                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 ]+ ~4 ]6 x' r' W' f                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;* }" D& k! P) A3 D: X9 w4 _
                        lowpass_filter[1] = lowpass_filter[0];
# s0 @9 @) ?# n. b+ G                        lowpass_filter[0] = output;
/ |/ g8 n4 ~0 J2 ~  ~( I                } else if( nFilterType == 3 ) {
0 O* |* T* J6 j$ E7 B" Q' r  G                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
  R! S, E2 X# Q7 l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;. e9 h8 v& Q8 A8 s( E
                        lowpass_filter[2] = lowpass_filter[1];
- [5 w; K* [$ Q  ?. [. }. |% b                        lowpass_filter[1] = lowpass_filter[0];
6 ]* l% ]3 L  B                        lowpass_filter[0] = output;  K' j' `2 N+ s
                } else if( nFilterType == 4 ) {, F5 f$ O0 f8 d. c4 x
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* e" O$ A' `  j8 K                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;. t" S0 F- p& \% i
                        lowpass_filter[1] = lowpass_filter[0];
/ ~8 i0 B  x" X* l                        lowpass_filter[0] = output;
* U& S# s: ?1 @& F) U" q* U- H                }
6 P% [: f' Y' I3 T: `. m
; @0 a" h- T/ q. I#if        0* i8 Y- @1 F+ d
                // DC惉暘偺僇僢僩
: o+ F4 I. P+ g' h6 A3 Z                {
2 e. I: N) P9 g! M                static double ave = 0.0, max=0.0, min=0.0;" }4 H4 f8 \& ^% J4 ?7 x0 _
                double delta;7 N" |# Q% Y% d- W! \) Z5 y& Y5 K
                delta = (max-min)/32768.0;5 }; F1 G- p" B9 ~: H: M9 f
                max -= delta;) U1 }! ?% W% m! `7 z% x, F; K
                min += delta;% B) p" ~* [6 _2 N- t& A$ G8 P
                if( output > max ) max = output;
" j) P9 ~, P: N% ~1 K0 E/ h' ]                if( output < min ) min = output;- w3 Y- ?0 Y5 _  z: s/ s$ E
                ave -= ave/1024.0;$ k- A) s4 H2 m, a" D! v
                ave += (max+min)/2048.0;& K, A2 l- `. @6 F3 \% W
                output -= (INT)ave;5 [  [" F2 W4 X% O& l
                }
( Y# S2 _6 h" C# o* P7 b, E#endif: B* D0 ~# V" y% g" T: g
#if        1
0 @( ]( X5 m+ J% p                // DC惉暘偺僇僢僩(HPF TEST)
' E9 u( a0 Q6 V% j; ?7 N                {* H8 h0 m3 h* ~+ ~  v1 H
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
% H8 k7 a9 n) l& P                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 H: Y( M3 k' X$ {3 M2 F                double        cutoff = cutofftemp/(double)Config.sound.nRate;
7 }) J) O0 \9 T) r& ]                static        double        tmp = 0.0;
2 M$ Y; \& q! Y                double        in, out;
6 I7 y5 R9 o1 `1 u6 \/ r# }  N% x/ G) u  ]
                in = (double)output;" r! H, ?2 O$ e7 ^
                out = (in - tmp);
9 M0 }4 J$ n& t, R                tmp = tmp + cutoff * out;* e+ {2 T3 C8 }
3 W4 n6 r9 ~( i8 J% J
                output = (INT)out;
1 l) w% t+ y& _                }
! o/ c  \- c# c( h7 ]$ r7 a#endif" m, p- |  A9 K- W
#if        0
5 P! i5 Y3 a- t6 J- t  e& e9 a/ ]                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 j, c' J* L6 \) a6 f2 E  |: `% v
                {6 T2 |, ~0 @' @! V2 x' |
                INT        diff = abs(output-last_data);
/ M0 ^" `2 N3 a% N0 j6 ^                if( diff > 0x4000 ) {  F% K, B; j# o& L
                        output /= 4;6 N, y2 K4 h/ |
                } else
$ C5 J' O7 {5 n: c4 ]6 M' E                if( diff > 0x3000 ) {
) u' j7 c2 r: d8 a9 x                        output /= 3;* l; I3 E5 N* t7 I" b
                } else( y. S5 S/ s" O
                if( diff > 0x2000 ) {
+ |, S' W5 a1 c. ^8 x                        output /= 2;1 a3 N- F( o8 u5 V1 Y
                }& t, r9 y5 @5 h2 t% V
                last_data = output;
( Z: ^& l% C* a, Z, u                }4 Y* J: M8 m- \. Q$ B/ r% _+ M8 ^/ j
#endif
1 p: T& P7 w. h8 [( T4 r                // Limit* l2 @' f- N* {1 Z4 h4 ~* J
                if( output > 0x7FFF ) {3 p; o6 l0 l; o2 @+ P2 S+ W: }
                        output = 0x7FFF;
0 e! Q5 k8 s0 |* `4 X8 T* f                } else if( output < -0x8000 ) {
5 L6 o  d* Q. B: J8 t5 z1 T1 C                        output = -0x8000;2 x, Y$ I" @7 l6 K% J8 V
                }1 A4 ~; }/ V; g! f9 y

* o; Y4 v! l; }: ?1 @                if( nBits != 8 ) {
, [* w/ L5 {" J- o                        *(SHORT*)lpBuffer = (SHORT)output;
  }4 R! a1 W6 K. _9 Z7 p                        lpBuffer += sizeof(SHORT);
1 h9 Y8 ]* _  h. y- G9 y( T* A$ k                } else {
- K7 q. g7 l. a+ o& P9 f                        *lpBuffer++ = (output>>8)^0x80;
/ ^2 V3 X9 G& d9 a& \* N) `                }+ Q; E: }8 B# ^. A* y6 F3 D& F1 Y. v
' b. w4 q9 s" A$ ^. v
                if( nCcount < 0x0100 )
  R- O& F8 R& n! A" L# V                        pSoundBuf[nCcount++] = (SHORT)output;
! H, B5 {2 C: T3 K# f' D
. |. A7 ~' A+ f1 V//                elapsedtime += cycle_rate;
8 ]: r" b  @( @& a; {- j                elapsed_time += cycle_rate;  z* q5 |: }: g
        }( K, K9 w" ]5 b# h1 {% H7 O: S1 ]
# }- A, `1 ~4 Q7 O
#if        1
/ y2 h4 a1 h7 J+ f$ f! L, M        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
. Y. \% w7 J4 Q& x                elapsed_time = nes->cpu->GetTotalCycles();
0 s+ z, l0 Y& k        }5 D, _* `- ^; h8 d" }7 T
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. Y, _0 A1 ~+ u0 k. _; }: s                elapsed_time = nes->cpu->GetTotalCycles();" ]6 H# J4 b1 }- ~& D  y
        }1 Z% w# ^2 Z3 b3 N; E1 G7 ^& h
#else
3 S  B& Q1 x$ a5 P) i2 h        elapsed_time = nes->cpu->GetTotalCycles();5 p# G; Y1 P: O; d
#endif9 Y' Y: f* D0 [
}$ ]& P, R" C- V9 L& X) M; D

% r5 U( A" L! y, h// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)9 m5 @7 I/ G4 N
INT        APU::GetChannelFrequency( INT no )
0 z1 w# U# t, s) q{
2 X- y! i0 g0 C9 P2 j! w        if( !m_bMute[0] )
6 j4 w: c+ V* A$ |                return        0;
& b! {3 S1 h5 O: `, b" F5 W2 I) G! C5 X( R4 a
        // Internal, f6 N+ l# b! @7 o6 A1 ~
        if( no < 5 ) {6 F% a) `: [2 x" N
                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ {$ h" s3 p( f& ]9 n
        }
* l$ {2 j& H! G# M6 \; ?        // VRC6  L. W' @7 p% R0 M$ Y3 P1 H/ W! z
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 O1 e: m6 K. d- Y; a- e
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
8 M8 N) {5 q; `8 Y' Z5 q7 X        }
. M- S, g  |2 I- L* n        // FDS
# [5 K0 [0 K5 U6 h        if( (exsound_select & 0x04) && no == 0x300 ) {$ S- c0 a0 l& p& \
                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 y) ~" H" R0 I2 W, Z$ d
        }
- G& ]5 H  f6 k! \/ s# `        // MMC5
" @$ S4 K, [8 |% I% X' y; O+ ^        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, [% H/ U; f5 Z' H! ~# M                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 g: D  R9 \# A5 I. x
        }
" U% Z( l: m  q( H$ {% Q' A        // N106
$ ~1 K3 D, v* F; T        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {( S+ \& Z5 B8 x0 r; u- E2 p1 X/ r2 W
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;* q( c% f; ~! H% _, E
        }
1 L/ B: l& x- {3 w) D        // FME7
7 W5 y) J7 [6 N) ]+ c& L' b, F        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
& o- b* K2 k" T+ e4 E+ K8 F2 U1 u                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
, m: E0 V' |) V2 ^        }
0 q& ]4 G9 y0 h; d        // VRC75 I6 n1 ^! i7 i% X0 O# [$ z3 R  y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
% X; Q' ~- g: P5 ?' e                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
, O# B* \; j0 ?+ A. l4 C        }' Y# C" A7 w0 P4 r
        return        0;2 S/ Y1 R& d; `" t  M4 P
}
+ f& y9 Q, j" c3 S+ x$ H7 |5 `, L( B; l2 t4 D6 R
// State Save/Load
2 d9 e' B5 Q" h! V1 u3 ]8 pvoid        APU::SaveState( LPBYTE p )
* ^4 Q+ t/ E; I{- p- z: L  H3 b( @. l8 x. O! W+ u  U
#ifdef        _DEBUG4 X& h# J; b5 O  X$ S7 t+ N8 R
LPBYTE        pold = p;% M3 v3 u  P: y" M3 q$ E% I9 k" W
#endif
" p1 c8 J9 x' ?7 y% v8 F' }7 f0 n" A6 G. n
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞  Q% c- ?: B8 R8 Q9 L0 }
        QueueFlush();+ V7 @8 A) N2 c9 ]; v$ W# r
6 I; J( b# G3 ~. u: V  k
        internal.SaveState( p );" a8 c( i! L7 |1 g$ m
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) E2 x, q, M1 s# [0 h9 x3 o" H  ?: x9 i- z5 B6 U" t" M9 ], U
        // VRC6  x% b* B9 g) |6 S4 h
        if( exsound_select & 0x01 ) {
) H# B9 v: z. l& @                vrc6.SaveState( p );( [. D8 ]) |, E1 w2 Y: ]% s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- u* Z" ]* w% C/ _+ P2 \$ L4 u        }
* ~% |2 U- q1 A( b        // VRC7 (not support)' ^+ [% G& S- A5 Z: }8 Q
        if( exsound_select & 0x02 ) {
- i/ ~  {) {7 U' Z, a/ N" D- j                vrc7.SaveState( p );
2 _, w7 {% o( F! p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 E* n' l+ Z/ O1 S' O: W
        }. Y/ b3 @! `- l8 L, q" r
        // FDS
* V6 d- {6 D: W3 S7 x1 L9 w& i% I0 }1 b        if( exsound_select & 0x04 ) {  v! e, u* N# M
                fds.SaveState( p );  p3 h% Y( x, z1 P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! z: g* s2 U% K1 f/ \) F' y4 g        }
! `7 j) o9 @5 G( p. t& C        // MMC51 {5 e, l% N: [
        if( exsound_select & 0x08 ) {
/ T+ K- _& g  B1 i$ U                mmc5.SaveState( p );& C9 U# R$ J! O; x8 |
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 n3 P3 @6 t. k
        }5 A( f' Q' F) R% u
        // N1063 j& {8 M2 A' t0 r# ~4 }
        if( exsound_select & 0x10 ) {  s5 @+ S7 o) g3 r. Z
                n106.SaveState( p );$ J9 L8 @9 P. A# G0 _" d7 [$ ~
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& I& G  L1 x; }. L) T        }
3 H1 w- B/ ^: D' j        // FME7
) |' U. {! y$ H$ C: _+ x9 l        if( exsound_select & 0x20 ) {1 V  C% ?, Y/ r$ Z
                fme7.SaveState( p );8 w& _, k  k" u0 p9 y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  _: y+ X, h9 O/ |6 g1 c, j        }
1 k' f# {. w- U! c
& ?% G! e! a+ J, H! K( U/ k: G3 k9 X#ifdef        _DEBUG; d' H$ s) A" w% @) E9 f
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- m( R; _$ f( c3 }0 [5 L#endif
! h- i  [# F# V}- H4 E0 R2 x' P7 O4 s' _5 n8 v' S; h
6 Z' O% T% P3 `  C- I
void        APU::LoadState( LPBYTE p )/ {  J* F6 E0 n6 A( s. e; F
{" j, z7 e$ C5 U7 D3 E
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! B& [1 c- m5 L8 A5 ?: `& R        QueueClear();
& R- G: v( w2 j& I6 }0 \. ~8 j
4 O5 k/ G) s, {+ M" n/ s) _        internal.LoadState( p );
2 t% K( z" U' S5 k/ S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 ^( A4 m6 I8 L% C  X; T2 O9 S7 q

' Y! C9 b, W: W" r4 x- K        // VRC6
6 ^* L2 T/ [* k        if( exsound_select & 0x01 ) {5 x& u4 M* q! T( t$ g' `$ d
                vrc6.LoadState( p );
: `% _3 f4 _  o1 j                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& w: F% U, w* O! |- w0 s1 F        }
8 p  H& R. g9 }0 D; s8 }        // VRC7 (not support)7 U3 l: ]4 N7 W  _( |5 E9 U) o
        if( exsound_select & 0x02 ) {0 n$ {* j4 M  Q. k4 ]) z
                vrc7.LoadState( p );6 Q+ b6 S8 R5 f) Y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) X6 ^5 h+ }% q0 c        }) m$ t0 ^1 d) n: ^
        // FDS9 @% ~* D8 }4 |6 Y
        if( exsound_select & 0x04 ) {; d1 W% Y# }) h% w5 i: ]8 N
                fds.LoadState( p );
- J+ q/ @* u- k* i2 D: r                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 Y9 G5 X) r8 _- E+ {0 Z
        }
' s6 R' m. \9 {5 W/ a" i        // MMC5* M! O6 w9 H1 v5 C" y1 |
        if( exsound_select & 0x08 ) {
! K* H) d% J. l# X* R                mmc5.LoadState( p );
* ], Z$ P' c' u( V1 F% A1 j/ H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) k3 J+ P5 i; ^7 a        }
. @; h/ C5 K' x, l! S# f        // N1068 k! k( P4 G' d/ M
        if( exsound_select & 0x10 ) {
6 p2 a% X( x& I' k                n106.LoadState( p );
7 Y5 o# c; @- F* R( \                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* p2 W0 v% o  B0 C& G3 L* p3 _$ ^' X        }
: K' c3 U7 j4 W1 X. a% Z7 M1 ]1 s        // FME7
( B0 N. j4 w8 o, H$ e3 u        if( exsound_select & 0x20 ) {( q) g: g0 G7 g! ~- a- P
                fme7.LoadState( p );& U$ w" A/ k6 H1 u/ O
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ d; e' Y, N, I
        }, o3 |% J7 A3 @" l/ o! D/ s$ d2 N& w
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 6 w# i7 p! t1 o$ a
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! @' R) J6 a, g+ s: x: e7 n
感激不尽~~
) @5 o, A0 l% F4 ~; k
恩 我對模擬器不是很有研究," ?; i0 v/ Y' t% A* u
雖然要了解源碼內容,可能不是很困難,' _& g* W- @# C: B& \
不過還是要花時間,個人目前蠻忙碌的。* t; T4 g; g& D

1 F. {. G1 j/ f給你一個朋友的MSN,你可以跟他討論看看,& m3 Y6 Y$ }" Q9 E
他本身是程式設計師,也對FC模擬器很有興趣。, Z6 ]* z- n* G; t0 X

; `, }4 M" p8 _0 s9 i! y! xMSN我就PM到你的信箱了。0 q2 e$ X  U( q  ]0 r
. L* T! e. ^4 r9 I& p/ ~% y) \
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " j2 |( F# f/ r' M; a8 s
呵…… 谢过团长大人~~

2 N- x. |% Q( G# h1 n% @) w4 I
2 x) J; b3 V! r  o$ M9 Y- Q9 G+ S3 W哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
* @7 l) p7 s* ^$ j, r/ C/ i' e团长的朋友都是神,那团长就是神的boss。
! J' Z% i$ J$ a
哈 不敢當,我只是個平凡人,' }9 o: V1 k% h
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  p4 b/ r' ~6 e8 m. N
ZYH3 w# _7 V8 N9 o8 H
QQ:414734306  h1 j0 @, n0 m3 b. t1 \& X& b
Mail:zyh-01@126.com
. X0 z) G  x% u; J+ w# Y6 {+ Q. I
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
7 P/ C& V" V: ]$ U/ v) y) `再次对团长大人和悠悠哥的无私帮助表示感谢~~
5 \7 j* f( j8 I# W+ y) H3 n
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-1 11:07 , Processed in 1.066407 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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