EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?% U7 j% U; Y' J+ i/ v" y+ M
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 s# |; H$ a3 m4 q6 F# A
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 |* G/ P2 _, [" X9 Z0 k3 ^5 W7 A
这里有相应的模拟器源码,就当送给大侠了~~3 e* S% O# E1 U5 s; E2 w- {- Y
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
$ D6 N% d- v# R. w, |- i能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: r6 n  w5 N9 V5 t; \( x, l
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& M( ^+ e1 Z% A- Y1 X这里有相应的模拟器源码,就当送给大侠 ...

1 y  f4 k) f) y聲音部分(Audoi Process Unit = APU):5 j  g9 g6 f2 x  N  m9 `* b
.\NES\APU.cpp
$ {$ o4 Z8 j: O. ?0 l.\NES\APU.h
* b8 w" r( E- H# r0 G0 r+ k
0 K, h0 G  a9 M4 F
9 p. }0 b" Q( [8 r2 O  c影像處理部份(Picture Processing Unit = PPU):
; X" p9 u9 y. {! U1 j0 ~.\NES\PPU.cpp! B4 r6 D! a; m0 |
.\NES\PPU.h
* b* L) T1 ]+ l4 k) v7 o) s; e5 B& i) _. O  r( O# n* f
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:% Y  u2 l9 F8 x) L
(由于很多专用术语和算法机理都不明白,所以看不大懂……)9 E% p" p, G/ S- n' K1 D
//////////////////////////////////////////////////////////////////////////
! q' v4 m! ~5 Y) a//                                                                      //
+ R, ^: d% g* |//      NES APU core                                                    //
5 P1 H5 c+ N' j. Y% S( y//                                                           Norix      //& i# t5 s+ t8 R7 \8 ?; `9 p
//                                               written     2002/06/27 //
, _8 Z: ?4 {/ {# l//                                               last modify ----/--/-- //5 ^6 z* U# E  H, N
//////////////////////////////////////////////////////////////////////////
1 ?) k. ~; |+ c$ ?8 n0 K#include "DebugOut.h"
( ]/ B3 p  M+ I" L#include "App.h"( R9 r, {1 |8 B. @1 f5 p* o
#include "Config.h"
- D! {: E( r* P) q9 n7 ]4 p; V# e9 L$ ]0 [' o2 w: V, ~  s
#include "nes.h", J; V# ?! W$ T) y  e
#include "mmu.h"
. C& N: i0 O, X/ A$ v/ B$ w- [+ p#include "cpu.h"6 X' z* B/ O5 g$ E9 O, S
#include "ppu.h", I$ v. t5 l. x% h$ }5 x" ^
#include "rom.h"4 ~7 x) M6 o" ]/ B5 _5 p
#include "apu.h", S; X+ m% P: w# d5 U
7 R/ M! d6 M$ I$ Q4 ^4 K! S$ t* |
// Volume adjust
! w0 o2 H/ {$ o+ r// Internal sounds
6 \$ p; f! e& ]4 ^2 q" v1 i#define        RECTANGLE_VOL        (0x0F0)
5 ^% z; L. V, H2 }( j1 B#define        TRIANGLE_VOL        (0x130)9 T7 Q$ x& D5 b$ X
#define        NOISE_VOL        (0x0C0). O7 z/ E5 D6 ?- Y, c- @) x
#define        DPCM_VOL        (0x0F0)
7 r9 r) E/ P" c8 u; t7 `! u// Extra sounds8 f5 J. o% q  O
#define        VRC6_VOL        (0x0F0)
" Q7 G2 c3 J: q% o& A/ ]( h#define        VRC7_VOL        (0x130); X# w( T$ l! |& e
#define        FDS_VOL                (0x0F0)
! ~! }2 s6 M4 M. t#define        MMC5_VOL        (0x0F0)6 a4 I8 @$ X6 c( v+ |$ ?
#define        N106_VOL        (0x088)
$ R# i+ h' `  w3 S# n# O. _& K( [#define        FME7_VOL        (0x130)& Q' X$ c* p$ g+ h( x  N- E
: j  P9 @- I$ R
APU::APU( NES* parent ), W, \: P6 F. Y8 x
{
+ L3 Z4 p# }$ m* [        exsound_select = 0;! e- M3 ?8 H% t: _& Y
( X) P0 _* O# a& r
        nes = parent;, ~7 E  H) K5 a- r/ D
        internal.SetParent( parent );
- h' L) r) n( I0 X- b
% G& ^: V) z5 o! U4 C' c        last_data = last_diff = 0;0 h5 l4 Y5 E- O3 k7 Q
, b3 U% M0 s* x, q* J. K& B1 b% }1 L
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! z9 j" L, ^3 v" k3 D" v
" ~8 {7 D8 q* D  B3 s7 H
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
3 M% ]# Y+ H1 e5 Z7 B        ZEROMEMORY( &queue, sizeof(queue) );! }" y) {% h. S1 ?" n6 |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 S5 r, U# {* g/ Z, i; x" G! k. c# X1 Z$ @9 N- t
        for( INT i = 0; i < 16; i++ ) {
$ C2 x( M+ D, n7 ]" Y                m_bMute = TRUE;2 h; {+ a5 K6 ]3 r
        }
3 u5 C, ~5 |$ `4 F8 ]8 D}
& R+ c4 z4 S4 b4 y+ r( ~/ P- G+ Y" d4 j9 z. f
APU::~APU()
0 A4 n9 |1 R6 H* U. n{( f+ d0 \# l5 Z2 b3 E& @5 x+ f
}  _- q, G7 y! Y, _# A4 }# h( `
. c6 L7 t5 H4 j! Y& W! D( I/ W1 c
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )9 L! h* m# `0 t7 E" J6 N1 Y+ s
{+ i" Q* h2 ^) u. m1 ^0 D1 ^
        queue.data[queue.wrptr].time = writetime;
3 c, V- \; R1 x. V: R/ }        queue.data[queue.wrptr].addr = addr;
; ]" ^( v* g% E; m5 D        queue.data[queue.wrptr].data = data;
' \1 y2 U% b4 ~- c; f        queue.wrptr++;
6 d7 e9 N- Y0 X        queue.wrptr&=QUEUE_LENGTH-1;, g* v" S9 m/ a) e" a+ z9 D
        if( queue.wrptr == queue.rdptr ) {$ S+ e7 g% n" _' g$ e3 n5 ]
                DEBUGOUT( "queue overflow.\n" );
$ [. k% x8 D, f+ j1 m7 r        }* `5 A. V6 k+ f1 h; V, Y6 z3 ], t
}
0 X& F- W- u0 e; o! z- S# D; S/ T. t+ F! b1 U" ?2 e
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
# T8 i" o9 I; r! S6 B6 H5 L{5 t, N# T* y; I0 J9 n, {( `" W
        if( queue.wrptr == queue.rdptr ) {2 i1 q* ?( b) u9 Q' z' m- h+ `
                return        FALSE;
3 u( d* v% F; @) M, l2 U8 W        }
9 [, y" ~6 ?3 ~( G. q. D  |+ ?        if( queue.data[queue.rdptr].time <= writetime ) {) k" P) i* B& v2 M% A
                ret = queue.data[queue.rdptr];! o$ t' J& g2 i& A* @5 g& p, u" `
                queue.rdptr++;
" u0 N' |0 r7 @! X: P  |3 Z                queue.rdptr&=QUEUE_LENGTH-1;
. M4 r3 t4 |* z1 n) h9 n( l2 r9 m, j                return        TRUE;! Y' I9 b3 g3 U" V. y+ S
        }
" |: Q0 u- Z# Q$ d( P% }; {$ E        return        FALSE;
( q6 z7 L9 q, k) f8 e: L4 P}- L4 \' B1 q* E2 v" y$ \
4 E6 l' r" f( Y& Q
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* Y9 M, B  w5 j& U* h# p4 l$ R{
4 F! T$ V$ S6 o, t        exqueue.data[exqueue.wrptr].time = writetime;
. D9 G( M6 z# P        exqueue.data[exqueue.wrptr].addr = addr;+ ]0 x& K% X5 q0 v. C3 c9 T
        exqueue.data[exqueue.wrptr].data = data;
& d: k; i5 C9 J# C; ~        exqueue.wrptr++;
' E& e0 D- o% H; ~" K9 J$ h        exqueue.wrptr&=QUEUE_LENGTH-1;
  U3 F' R- d5 E. ]: X1 _# ?" S        if( exqueue.wrptr == exqueue.rdptr ) {6 b  u( t0 U9 r6 L6 T+ S
                DEBUGOUT( "exqueue overflow.\n" );
5 C5 \- H  f$ m5 V- T        }
5 O/ J: J0 Q( Q) X  Y/ S+ w* ~}
0 x. ~. I( p4 P  s1 E+ m3 y. _! {" {0 j; ^% |8 T6 w- T
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
0 v7 [& W$ _2 X6 X. v: W; [{
# Y, O  w3 b9 t6 `  ~        if( exqueue.wrptr == exqueue.rdptr ) {
9 P! w- C: S; O                return        FALSE;/ P9 Y# c$ a4 s8 i
        }/ c3 L" h+ M" W# _+ j6 r6 T$ F
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
* q& d/ P8 j7 ~3 g                ret = exqueue.data[exqueue.rdptr];
! N- `. N' W4 w# v. s+ _                exqueue.rdptr++;
/ t+ F% e0 E9 P: \) L                exqueue.rdptr&=QUEUE_LENGTH-1;
$ v0 ?* ^' k3 C8 r6 n                return        TRUE;
# J" N" B; H5 r) d0 a. f        }+ X, R8 V% J' I& Z. b1 ?! g' w
        return        FALSE;
" O4 f& P" I5 b9 t+ B}
4 z7 h, q$ I& m9 r/ c+ S: z( d) J8 w
void        APU::QueueClear(), Y% k' i1 M* W( B0 z' l
{
9 t% g. W/ u' j% L9 ^        ZEROMEMORY( &queue, sizeof(queue) );
) k+ s1 G3 @* \1 b% s! F        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' o6 `5 x; Z1 G8 v* ^9 Q. r( W}7 N& S9 a8 ^) C* f* X3 r: q9 {3 x
0 B9 u0 y9 a% u6 ?  w
void        APU::QueueFlush()
, ?: l/ d  p  P{' g/ k. K. l; i2 X5 z' b- C
        while( queue.wrptr != queue.rdptr ) {
. X3 e$ @& h# }8 I                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );. q4 H, L5 v# i9 p
                queue.rdptr++;
" m5 [% J4 \) M5 P8 O2 |: [                queue.rdptr&=QUEUE_LENGTH-1;
4 H; N8 R+ n+ u/ \8 B1 e        }
' |3 ~* J+ E) X0 D
6 d; n: m6 `, A* r1 J: K1 R5 _        while( exqueue.wrptr != exqueue.rdptr ) {" P: f, j8 {  s% ~- M, w4 N! A
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );9 y1 z  u7 b5 P* {% {! {& {
                exqueue.rdptr++;
# {+ }% `  c# r+ F0 V4 y& _. P                exqueue.rdptr&=QUEUE_LENGTH-1;
. c- i8 ^3 O4 U) z8 G- z        }
3 }: X1 k* T3 q+ E}
3 U8 c: G1 ]# a9 V0 e
( c0 A% G) l& A- O( K1 p) e& s7 svoid        APU::SoundSetup()' q$ Z5 \% i+ n5 y; a
{
/ b/ F# p4 E! E7 g" X( y        FLOAT        fClock = nes->nescfg->CpuClock;
* M: |1 F1 y7 l) T% i4 }3 d% c        INT        nRate = (INT)Config.sound.nRate;
, m( w% i; j; a9 C  ^        internal.Setup( fClock, nRate );
: P1 O+ l: h, I0 F( t% o$ J        vrc6.Setup( fClock, nRate );
7 ~" k6 k. A$ m- T3 K. V/ h, d( E        vrc7.Setup( fClock, nRate );
. C6 |% a* O# l        mmc5.Setup( fClock, nRate );( q4 z! j1 M/ F: D. q7 \
        fds.Setup ( fClock, nRate );- K5 j2 W' i! J, f
        n106.Setup( fClock, nRate );# ^2 p; g- v/ e8 O& }* _5 l# e
        fme7.Setup( fClock, nRate );
! U7 U6 N$ |5 l" A/ f# Q8 Y; s}
) M4 m1 J: e; D3 ~" P: y
) ]$ a4 R$ q- M5 L: {void        APU::Reset()
- S: V! V7 J) i6 N0 f) g{
$ p  i+ @; e* e& U; S2 d        ZEROMEMORY( &queue, sizeof(queue) );
1 ~, M& n0 o0 O6 X/ O, s: ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. u4 ?: Z. j* _4 M. B( G* [6 f4 X5 X  T: l
        elapsed_time = 0;
' Z0 Y" E. M" I
. I, Y5 {; q1 A5 c: D        FLOAT        fClock = nes->nescfg->CpuClock;
. W6 @7 ~) w7 [- x7 \0 [        INT        nRate = (INT)Config.sound.nRate;
  y" J+ }2 `& ^1 _0 U1 R        internal.Reset( fClock, nRate );
5 Q5 Z0 n2 A! V; c* M/ x1 O        vrc6.Reset( fClock, nRate );
9 s2 e+ W) ~; c* P. S* d1 i        vrc7.Reset( fClock, nRate );1 P8 w, m5 I) r4 X$ [; i
        mmc5.Reset( fClock, nRate );
6 h6 w% S# I3 I        fds.Reset ( fClock, nRate );
& J; A9 C* Y% @4 S        n106.Reset( fClock, nRate );
8 D9 Q& l$ B6 ^7 t/ W4 X( w8 y        fme7.Reset( fClock, nRate );
# b+ u1 D6 e* V/ k5 E3 O9 n
  k5 K5 u1 V1 D. n$ C6 V        SoundSetup();
* q7 c9 z3 l2 t7 T}
! a; {: T$ p% p+ `  T) x& x; Y* a; G8 Q$ F* @
void        APU::SelectExSound( BYTE data )
2 O5 b( F/ I" t6 H/ U. R{
2 @) J! v$ ]* }        exsound_select = data;0 C* L5 Q) Z& X1 z5 I$ x$ x
}8 d; k7 L& G3 [( g) d' _

' N1 Z6 g9 d/ D& r- _9 v; e" e2 G, _BYTE        APU::Read( WORD addr )3 G, q9 ], o8 m" A  P+ q
{
8 ^$ R" \( p5 s0 x( z- A) w        return        internal.SyncRead( addr );# A5 h0 Z) X: {6 ?1 _- C7 [
}
+ l9 S7 \, O6 p4 r: ?0 o9 Q1 a
( y3 l$ `/ e  Zvoid        APU::Write( WORD addr, BYTE data )6 s# G& k& m1 U/ w
{
+ `# ^' i2 C5 D4 I, ?        // $4018偼VirtuaNES屌桳億乕僩
* w9 [/ C/ O/ p8 ]! w        if( addr >= 0x4000 && addr <= 0x401F ) {
) @+ J; a+ @0 N                internal.SyncWrite( addr, data );5 J! U9 s! {5 L. A3 k* N0 T
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- }% J& |% j, z) C- ~
        }5 v, |0 ~) R3 f( A$ K, X
}: z& w) e) z3 @5 ~, k8 y4 v

0 ~& a& L  [" g5 T; N8 @/ wBYTE        APU::ExRead( WORD addr )5 z- }' h$ E$ p0 A
{
9 k3 G7 q/ T4 D/ EBYTE        data = 0;
) V, c; H4 b7 h. \0 t8 D- ^7 X3 P. p! K' H$ M/ ^2 @
        if( exsound_select & 0x10 ) {
, t" Q3 d: V# ?! O9 s                if( addr == 0x4800 ) {
9 U: h  t" V8 A! x+ @* H* w                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) H2 Z1 g9 b% r1 |# P9 J( {                }
- u& r. b) e( J# m# a* v0 G        }( q2 s) N0 U; B! q* o
        if( exsound_select & 0x04 ) {
% l# I4 Q5 e# q8 V9 d! z                if( addr >= 0x4040 && addr < 0x4100 ) {
1 s) H! h- x' T) q* N                        data = fds.SyncRead( addr );, o' W  e- B7 s' s. r
                }
" G0 Y3 T. W9 x! n! t; ]+ o        }
. G0 d% l- f( O        if( exsound_select & 0x08 ) {# \& B' M6 {4 M9 b
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- c4 a" F# ?/ ?4 a3 t                        data = mmc5.SyncRead( addr );' I, [5 m( z; O' ^
                }$ q. x! u" ~* p& G8 f
        }
7 c& w( y1 F# k6 ?9 G  y& B4 V2 m$ p7 ~, \  ^# f
        return        data;  ?8 \$ y1 D$ G% t
}7 N9 n( i  r- v! \0 \" y# J" V, P: I
/ P3 Y+ u1 W* e  t, ^
void        APU::ExWrite( WORD addr, BYTE data )
' ~: M9 @+ e% t  o8 A7 Z{6 S1 K2 D1 Y& }" h6 m
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, b( `5 O0 h1 w8 R
$ U, ]9 e5 B- B$ O2 m  k9 m5 ^        if( exsound_select & 0x04 ) {0 c& I: d/ ]3 i, j
                if( addr >= 0x4040 && addr < 0x4100 ) {
; ~8 P7 r& q1 y                        fds.SyncWrite( addr, data );0 d1 W" }! p  y" Z+ T$ Q0 A1 {: @# A
                }
; E! Y5 k- ^5 _' Y% A        }5 }# z+ X" c8 R3 ]$ {" _$ L

% N& m* }+ k/ [; a+ x, g  w& e        if( exsound_select & 0x08 ) {
% @1 z, Q% q5 [4 @4 ~0 o. F, ?7 D                if( addr >= 0x5000 && addr <= 0x5015 ) {" ~$ m& ]( m7 U- e8 U) P
                        mmc5.SyncWrite( addr, data );
" J. s% V/ r& s: Q. H8 [                }- _7 `. `9 W( N+ B& A( @
        }1 U8 c/ l: ~, B' j6 p8 m
}8 {1 t$ W) L! a  |1 }& g
4 N, \  @% h& E; ]$ K1 @3 }8 w
void        APU::Sync()' T' F3 P& O  s" A: x
{3 b; W! j1 z$ R0 E5 p
}% _) y+ z+ Z, r

5 N  m$ `4 m* F1 S6 x9 o) Pvoid        APU::SyncDPCM( INT cycles )4 k& ~  Q7 T+ z3 _
{( H8 ?( b* \, Z5 F
        internal.Sync( cycles );
# A: H- A3 _& C/ X6 ~# L  E- v+ j6 [( F0 F" W' O) a. W
        if( exsound_select & 0x04 ) {
1 a# N0 g$ ?* |, W! L6 l                fds.Sync( cycles );9 D. V( U/ `1 C8 w
        }% l! t# A) W. J7 `. Q  \
        if( exsound_select & 0x08 ) {! @3 a5 j/ `) Q7 L
                mmc5.Sync( cycles );6 g* O+ _: i4 m3 ]& F( t
        }
! V& o# O; m0 ]1 o$ f: o! r6 p& o) C}, K. H* P! O& u5 o& B  i- h. n; P

0 H" F: Z. v4 x0 @void        APU::WriteProcess( WORD addr, BYTE data )5 U2 p6 l  B7 F, L5 V+ b  f! ^* O6 S
{" b8 P' V: _1 _8 f5 T
        // $4018偼VirtuaNES屌桳億乕僩  Q7 E' `- G3 k" F% z4 a
        if( addr >= 0x4000 && addr <= 0x401F ) {$ M7 z* t' ^2 a
                internal.Write( addr, data );* D" `" ~7 s: R. m/ T
        }, A1 @. S7 h- s7 ?
}
) Y  J0 ?9 C+ T! i) P. b- K. Z' _1 t1 r% T& X7 j
void        APU::WriteExProcess( WORD addr, BYTE data )
/ t& p8 _' k3 z{8 l# K- D! U' p" k
        if( exsound_select & 0x01 ) {8 h# a3 Z1 Z' W. F) D3 I3 m
                vrc6.Write( addr, data );
' w4 g# C6 B) H( [        }% v  A# J5 B% B! e
        if( exsound_select & 0x02 ) {
; Z# ^3 H/ ~* C7 x2 B+ L7 }                vrc7.Write( addr, data );
+ v8 C% R5 S" z3 r* N) v        }3 q5 N3 D' [9 [) E& k
        if( exsound_select & 0x04 ) {5 S' a1 _" c) [
                fds.Write( addr, data );
8 m+ G( a6 w* I        }; H0 a8 o; p5 [3 A  L
        if( exsound_select & 0x08 ) {
* b, y, W7 }' O& b# B                mmc5.Write( addr, data );6 ^% _5 j# p7 _. u$ `3 d: {
        }
$ O. ]$ b! Y( l7 ~, ]5 \  ]. R        if( exsound_select & 0x10 ) {# a- ^2 r( l0 R& @  t
                if( addr == 0x0000 ) {
  g  q) ], L! J, H" c/ w0 H                        BYTE        dummy = n106.Read( addr );% C. Y9 {" ?( }) \
                } else {* X# Z1 G0 k& \; }
                        n106.Write( addr, data );8 D" p$ }& g, b# a+ j6 l$ @+ ]/ p! Y
                }6 v! ~3 M5 L  E0 ^2 t! T+ N
        }
) S0 P9 A) W3 R  v  \        if( exsound_select & 0x20 ) {
% ~& T' r4 u. Y8 b6 z$ D                fme7.Write( addr, data );
& O* c% X, r5 y- K) r( f        }
/ \3 T) G# U, F# [}, Q; Q0 }2 q8 U; j
8 K) P5 P2 d1 x: M0 Z& g" V
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  C* c- _8 h2 S+ O9 P0 ~: {
{
9 d6 v4 o8 X9 I7 UINT        nBits = Config.sound.nBits;& o4 i( n6 Y# H4 j1 k
DWORD        dwLength = dwSize / (nBits/8);
& B* ?# T) N; f8 N: q& B( X; O% AINT        output;
3 G( i5 p) S/ l, Q' o) G+ h/ lQUEUEDATA q;- s! |- l6 t' j3 W# J+ ]- X4 B
DWORD        writetime;! h9 k& k% {- G/ W% j- G
# w5 ^/ K# m2 k& S: F& c1 c
LPSHORT        pSoundBuf = m_SoundBuffer;
5 t! F5 Y7 n8 n5 h/ ~INT        nCcount = 0;
& N" a3 x1 j0 a. T9 g0 J5 O* U, I5 o, f3 F- L# [7 _
INT        nFilterType = Config.sound.nFilterType;
+ ~0 j/ ^6 ^% S" k8 j+ c0 W) y9 ?6 W3 \4 Y' m
        if( !Config.sound.bEnable ) {
4 Y; _* M, ?: K1 @                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );5 l* [9 y1 q" i( M1 G' l1 t- x, @
                return;
/ T1 J; `9 p" I$ d  X        }$ i6 Y  {" W# f

. L3 A& I( R: a# C        // Volume setup
, \$ T. r( Z) A# y/ N% n, B        //  0:Master" y5 Z1 K. E7 P1 X, G; f* f; a
        //  1:Rectangle 1
9 r% Y4 p' k7 N6 H& k        //  2:Rectangle 2. ]9 p5 {! z, c
        //  3:Triangle
% h3 d+ P8 p3 Z/ o4 ?5 l        //  4:Noise
: O5 y. X- Y9 N0 _9 g- ]1 E3 `; ~        //  5:DPCM
* l2 [: ?' O3 u: l        //  6:VRC6! ~2 a% C; K$ W/ c9 M
        //  7:VRC7
; l( g% y4 n( Y        //  8:FDS; u5 m% X7 u2 m  L5 v6 q5 w3 x' l' X
        //  9:MMC5
; I* d, K. ~1 A( n' }2 M: o8 U        // 10:N106
/ ^" I3 g  h5 S# y( J* ?7 |- @        // 11:FME72 J% H2 ^  P: ^
        INT        vol[24];
0 W( X4 U( C6 }8 M        BOOL*        bMute = m_bMute;
! ], C1 A; |) v0 I" Q; S- R" G" P  e        SHORT*        nVolume = Config.sound.nVolume;
& W. f7 t) N2 J/ U. D) t) b/ W" C& a+ x& c2 _4 h9 E' o& r
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- r: n5 x+ b0 Y) O1 b, A' b
6 A3 r9 ^+ x+ Y        // Internal9 n* t5 D0 a2 [5 \
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 z! N3 O8 I- h8 g7 Y0 x" i# Y0 u0 Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
7 S* G4 ^) Z2 s" h        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
2 Z2 u( E3 \5 `" V3 R, h        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 U' J. E2 \, U( _; b        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) Y4 r  w) m6 w; I+ B
. w4 B: a; q$ E$ ~1 n, G        // VRC6& ?9 m1 V( h/ n) \3 {
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 C! e! z' s/ X9 C
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 H) ~- ]6 t7 X' w        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" r5 f6 ]) |/ j2 u7 `
6 Q. y. }( L/ \. J4 m
        // VRC7# S. t2 S" j- h* {& d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- ?# K% r; J: ?& ~
7 y7 R8 t, Z# v  ~0 L3 r        // FDS
! N+ E7 k% F& V+ `* Y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 B; E9 ~" j. ~7 \0 O# V1 M
* a  @4 N. k6 k0 w$ T2 Q4 w
        // MMC5& Z7 a3 g4 p# D5 q/ H
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ P+ h( D/ N' }$ `        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* T- S& ^& o6 o+ F0 O% L) ?1 r        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 [' w! D: t( E- ~

8 v/ n9 [4 Z5 M0 W9 a        // N106
" c/ t8 O' U& Q8 K/ d        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( s$ O3 G5 z2 ]0 B/ V3 j9 i+ G
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" g! [" Z4 l7 r: r* x( U        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 c8 ?3 x( Z( G  b( F1 y. W
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. b5 T) O, G3 b
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' b; b/ a0 g) U0 {' W  K' F& W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! ~# \: D* \. ~
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" a4 A" w5 b% C2 ^6 N1 \- _
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) w) U" }* N$ y) ^) t; P8 X3 w) C
$ n) X! |0 U# C! E# x% D        // FME7
' Q# A. X4 I0 |( W2 ~# g$ c( W$ Y        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 V  I/ c! ?$ x$ f4 @( l
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% O) V& }1 q& M5 p0 \
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 ]( {  @8 M+ N
! P: q$ E) p3 @9 W2 A8 N7 L: H//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
- Y3 D8 c" ?" p5 x8 z, y        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 t$ s0 F7 ?* C) w8 c7 [( I4 X- |8 E& ?1 I+ K; \# o
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟; O/ d3 Y' A) j. }% v6 G
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
( E" p  L1 B' }, _% a                QueueFlush();
# j# a2 q- `! c7 [( w$ i        }: E9 b  N8 v( p* }7 P6 L

, y; _; P" [' |2 H( _- n: ^1 A# K        while( dwLength-- ) {5 N2 ]" j5 ]$ ^( k: e) V9 O# R$ o0 b
                writetime = (DWORD)elapsed_time;' ~- D6 O) Y/ A; n
( z+ F9 b" _3 t5 v3 A
                while( GetQueue( writetime, q ) ) {, T2 r* _# d; @
                        WriteProcess( q.addr, q.data );
/ z* p4 b/ w' ~4 M# E                }1 l# k8 P. s: ]8 I2 L- T3 {
1 x/ A" S$ o+ O8 G3 S: F
                while( GetExQueue( writetime, q ) ) {
7 b( M" f+ e( q& x                        WriteExProcess( q.addr, q.data );
  ?( T9 \- h* z2 H- {                }* O) ^6 y, i# a- V9 l5 n2 C

" E# v# C+ T0 s8 N% i                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
, |  \7 x. Z/ N  p" B3 ]( l5 ]                output = 0;- Q% }# c6 j) J
                output += internal.Process( 0 )*vol[0];
- i) `8 |! O6 n$ x# P                output += internal.Process( 1 )*vol[1];, l) |4 R( k) R
                output += internal.Process( 2 )*vol[2];
- Z; K0 Y( }' M  \* e1 X2 E  A0 h5 q                output += internal.Process( 3 )*vol[3];# _0 F% G  E( v) _: }9 U2 w
                output += internal.Process( 4 )*vol[4];
) v! `0 M( j& K0 C
0 v% e8 E( d/ M2 B; `                if( exsound_select & 0x01 ) {
# q4 z# P  h" h) l7 |. T8 ?' S) Q' C                        output += vrc6.Process( 0 )*vol[5];
3 g, @9 E& x2 N3 T/ f4 P) N1 j: M                        output += vrc6.Process( 1 )*vol[6];) Z8 L2 t0 f+ o# d3 d) w$ d2 j# w
                        output += vrc6.Process( 2 )*vol[7];
+ G! W4 G( y# s/ T8 G                }' o& T9 k6 E. W. ~+ a
                if( exsound_select & 0x02 ) {
- J+ t# o3 }$ X                        output += vrc7.Process( 0 )*vol[8];
7 W3 j& R2 }5 E. O/ l                }
5 B: E3 @+ k3 v* M$ m/ P                if( exsound_select & 0x04 ) {
2 V: N& J  W1 G: ?                        output += fds.Process( 0 )*vol[9];; Y$ Y+ l& |/ j/ d/ L
                }
1 g5 B4 s" N3 N* [                if( exsound_select & 0x08 ) {9 \$ s' ^, E: u) X; O' p6 p  t
                        output += mmc5.Process( 0 )*vol[10];
, f! F+ a9 G( {) R                        output += mmc5.Process( 1 )*vol[11];
* j) M4 c7 u0 l! E. L8 D# N                        output += mmc5.Process( 2 )*vol[12];' Z5 F0 X( A' K) C
                }! Q0 z, v, S; j+ @3 i9 E. ]
                if( exsound_select & 0x10 ) {
3 ~- F# W5 `( E4 r0 I- f                        output += n106.Process( 0 )*vol[13];
, W8 w  `# ~. h4 n+ @. f% K2 I) E                        output += n106.Process( 1 )*vol[14];
- m# o4 i' T3 t+ C& b                        output += n106.Process( 2 )*vol[15];( e7 b7 j& K" o: F0 x1 Q. \
                        output += n106.Process( 3 )*vol[16];% a' ]* ^) c7 }  q) _$ \' W8 ]
                        output += n106.Process( 4 )*vol[17];9 G( U+ l& a( P+ R& d
                        output += n106.Process( 5 )*vol[18];: y. K7 \4 ^% X6 A
                        output += n106.Process( 6 )*vol[19];* w4 T0 k5 W" z: R
                        output += n106.Process( 7 )*vol[20];7 J6 H' h( l) |0 N" z5 s
                }
0 l* |/ d" H( K/ D. q. O                if( exsound_select & 0x20 ) {
  A) ?# J9 B, B! H$ R/ v                        fme7.Process( 3 );        // Envelope & Noise8 k$ x9 I' {3 p5 b7 Q: i" V
                        output += fme7.Process( 0 )*vol[21];" b8 h! x- T8 z+ i7 _' [+ k
                        output += fme7.Process( 1 )*vol[22];2 Q9 K1 W% ~  m  z& p
                        output += fme7.Process( 2 )*vol[23];4 M' P& h7 |' p8 V; Z1 L
                }
4 O; I' u8 Z/ L! n# S( C4 D4 V5 y, ~+ ]# q# l: D$ x/ Y
                output >>= 8;
+ ?, Q% T$ U/ w" `4 _3 _7 m. c; }4 ^/ s; P
                if( nFilterType == 1 ) {- l: ]: E3 E/ `) t' r/ `
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) w6 K3 ?+ u9 @8 J. r
                        output = (lowpass_filter[0]+output)/2;$ J6 t# T9 K$ V% K/ @* {& l! w
                        lowpass_filter[0] = output;
5 D; |4 V, j3 T1 E& {( f: E                } else if( nFilterType == 2 ) {8 i  W$ _5 _, E% O( n& T( c
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
. J: L( A" m9 h/ a  U- J# H8 f" W                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# _$ Q* P3 P7 x
                        lowpass_filter[1] = lowpass_filter[0];
" ~2 g/ F- z) ^! W0 w                        lowpass_filter[0] = output;& m) ]& d% Z5 k- ~- t. f
                } else if( nFilterType == 3 ) {
% L. ?0 T! B6 ]) S5 v3 g                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)3 P4 p) T. @8 ^: T" k
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! O4 E, Z& `+ f1 e  W7 L7 q
                        lowpass_filter[2] = lowpass_filter[1];' N& e, V2 r, _& X3 R6 O& T8 Z
                        lowpass_filter[1] = lowpass_filter[0];/ g0 V5 n4 D6 E! Q  m
                        lowpass_filter[0] = output;, O4 p3 q% _2 I6 S
                } else if( nFilterType == 4 ) {
6 ~7 ]6 ^9 J" r& N                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& i+ e: w1 m- i: r+ D, ]2 _" \                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
# X7 N+ S* `( u2 j! T: n% g% d                        lowpass_filter[1] = lowpass_filter[0];
8 \, ?& Z5 d; K6 n+ S+ T! k  }                        lowpass_filter[0] = output;0 k! v; i+ x$ l- L' m
                }$ }0 S8 g2 |' \( k2 G- d* T* J
4 t+ J; r  ~3 S' r) I; G* h6 O
#if        0
' ^( Q6 ^9 g2 O( ]2 h, ]& Q  e7 I                // DC惉暘偺僇僢僩
* p; ^$ [; a" _' e, E  j                {; B- e$ S5 s- X) V% R4 H
                static double ave = 0.0, max=0.0, min=0.0;
7 u1 n4 H0 Z3 }1 C% H4 x" @                double delta;
( K% `7 _+ \* C2 b                delta = (max-min)/32768.0;) R  W# v  a/ h  K  A
                max -= delta;
$ R! k0 \: A# {                min += delta;
; i) A& K) t8 ^0 G2 ?                if( output > max ) max = output;
) b6 F( I' e6 ^. x$ f' i3 p                if( output < min ) min = output;0 a6 ~; ~. R/ N5 N1 I' ^
                ave -= ave/1024.0;
2 X, G9 b2 b1 p                ave += (max+min)/2048.0;
: {5 F: s# r$ N  G! a1 @. o0 O                output -= (INT)ave;
6 a7 S. A0 P% X$ q" J                }
- N: s9 n/ h# |+ z3 S#endif& [* g( O# i( ?  P% a% p# R
#if        1/ Y, m4 Y9 B! h
                // DC惉暘偺僇僢僩(HPF TEST)3 G1 E4 Q: m* V
                {7 ]3 B' |# ~8 \' O9 o; K5 [' F
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 a( R) W# B7 |- k) i' b( e                static        double        cutofftemp = (2.0*3.141592653579*40.0);
! O3 R9 r" h# B0 V8 J                double        cutoff = cutofftemp/(double)Config.sound.nRate;
  W! O- Y/ w9 v) V, p! ~% }                static        double        tmp = 0.0;
" R$ v' M. U( S$ P2 T, [( Z                double        in, out;
. H7 P$ r+ O9 A; F+ t3 V/ M( t6 O5 a+ i4 Z& |9 Y" N. K
                in = (double)output;
3 |- P- m& e/ |4 ^$ M                out = (in - tmp);6 t( j) l, R9 n9 z! k7 m( H) a
                tmp = tmp + cutoff * out;0 u0 r. h3 }8 u0 J' _: {' X

- J! H. {$ _- u8 `# l: Y3 x                output = (INT)out;# x7 W+ \8 ^9 O/ j0 ^  S/ Q
                }# V# c& S# @% f( f7 V7 r* X4 Z. q5 S
#endif
7 E1 H5 |3 I) N& y# i3 A#if        0/ C& E2 l5 \7 l1 d+ M& m. f
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 |0 g) ^* h" }* c
                {. O/ q, D; ~% K  K5 N4 W. F
                INT        diff = abs(output-last_data);
* W, C# \, `+ a+ p$ y                if( diff > 0x4000 ) {7 B: e& P7 M8 M* X6 C
                        output /= 4;# ~' k# r% A; l3 D6 V* c* R
                } else
$ h% f7 w) v2 |: l) j5 f0 B                if( diff > 0x3000 ) {; X5 {; }7 [5 _8 t9 `* m! ?
                        output /= 3;9 z$ H/ R3 [$ T2 b1 \; Q/ u
                } else
/ ?0 c" A5 h* P% `2 V                if( diff > 0x2000 ) {  W! N. t$ Y5 n" K4 c
                        output /= 2;+ G9 A; X3 Y* ]1 k2 Y  U4 ]1 e
                }& X" r, N8 X2 Q
                last_data = output;
, F4 l/ C( {" f8 t) p6 }' c                }2 q/ @1 L) M/ W" r2 G5 A
#endif/ m( G* R( x, M8 e# x: x. ~
                // Limit8 k* N; D* }% n0 i' a+ b1 N! ]( A
                if( output > 0x7FFF ) {
$ T2 q7 k% ^9 h# [( r                        output = 0x7FFF;
( x3 V% k- @3 O8 B7 O6 n& p                } else if( output < -0x8000 ) {! q/ Z  {1 X; u7 ]
                        output = -0x8000;; `1 p( g; F2 X; L; Y$ W; J; O
                }! E9 h3 }8 f0 v& ^. ^: S+ f) [" c, f
( v5 _; F/ \$ ^
                if( nBits != 8 ) {' c8 Y  J. S$ k6 d, w2 {
                        *(SHORT*)lpBuffer = (SHORT)output;
( n" V1 V9 {% y* x; M% I2 Y                        lpBuffer += sizeof(SHORT);" \+ o, g  P' Y  S  e: l9 D4 C
                } else {) c  R1 w% R/ O- q2 R# W! c, @# f
                        *lpBuffer++ = (output>>8)^0x80;  j% A) `3 ~' |! t) s$ d
                }
; D4 g6 T: V  ?( t/ _% M, l: B
5 A, u; E# o; S, @                if( nCcount < 0x0100 )0 i; d  l& }% e/ a% k% D8 x' b
                        pSoundBuf[nCcount++] = (SHORT)output;
. D+ f4 l+ g/ [" r1 @$ g+ l; S9 E& v, @. h0 T6 K6 r% L7 C
//                elapsedtime += cycle_rate;8 Q$ f( E7 b$ J' P! V
                elapsed_time += cycle_rate;1 c4 i5 }) X! i) b4 p
        }
4 O, H7 M0 A: q. P- |9 [
' I2 ]4 a( v5 @7 d8 `3 l- T#if        1
( X+ C& H& O! b: ^# q6 v, `        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
- e4 m1 v8 @: ?/ U6 q                elapsed_time = nes->cpu->GetTotalCycles();
5 K) v6 Y! h9 _4 B: \# n9 K        }$ P) @# d9 z0 E1 L1 w
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 X: |, j1 T7 V+ {! p) {
                elapsed_time = nes->cpu->GetTotalCycles();
  e, E4 j9 u- ]3 k0 t5 E        }6 B) m0 F) z, M- ^- J5 n
#else
# I8 j% P$ K4 U; Q* o* d& @6 o        elapsed_time = nes->cpu->GetTotalCycles();* F; s; N- M5 N( j* B, i, c2 E
#endif. e0 \" M9 w4 z3 l
}* ?. b+ z' H: E: F1 N) }( d
2 q$ f, ]% K6 }3 u! s) @; h* Z8 U
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)% h3 h( t: D* A' F8 O- ?
INT        APU::GetChannelFrequency( INT no )8 [* B! [0 K$ g2 m# m4 C; ]
{+ e2 ?8 F" y9 C0 w
        if( !m_bMute[0] )# Y0 A1 H$ e0 @% F* f
                return        0;
: U" {6 ^- O+ Q. H
4 X% f. a# q4 ^( r9 g        // Internal$ T6 f% ], K; R" i
        if( no < 5 ) {4 E3 C6 u7 ~+ U7 k8 I
                return        m_bMute[no+1]?internal.GetFreq( no ):0;  r& i% G. I& z. z
        }
% k6 J6 F2 P+ k/ F        // VRC6
, i+ {5 X! @+ f7 v) C% l+ f        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! b3 y; \$ A% T; ]* i. V! \                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
  n# d4 ~. a+ r1 Y( x4 ?        }1 }& Y" R% f, g6 H& _! d( s
        // FDS' T# b3 h% h( n) L- P5 R& [
        if( (exsound_select & 0x04) && no == 0x300 ) {
- R/ _- u6 T  O% d) I; W                return        m_bMute[6]?fds.GetFreq( 0 ):0;: S3 w/ `# N- I  i
        }
7 E$ X/ K8 W9 \; q8 |        // MMC5/ O. W/ a3 o, v
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) G$ o$ J" ?: y5 P; I
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 c4 q  P3 P2 W' ~4 a& v
        }* S" S' H6 R0 U
        // N106
# v, h2 `( U- O+ F; z        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
: l1 ]3 r) }2 a+ ?7 O                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;) @7 W2 J. U) m, P# H$ K: S
        }1 |9 D+ ^" m" U2 j0 @' d
        // FME7* s5 s2 f; f+ E4 T
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# U% G8 P( N; q6 C" i) d                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;+ a2 q, m! J& D& n
        }( U: F. z3 D6 \4 r+ \/ C. h
        // VRC7
$ C! y# v% E! b. L. r        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" J. }: z1 w# h3 R( ]. S$ d, |& E                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
3 V2 M* ?  \1 i. W# Q/ Z( e        }
: \3 f2 F% ^8 G% m! G. M+ \# h: G        return        0;6 f. N0 t: Y% r( L1 A: O
}
* T- y) r. d/ o$ W2 g  k5 W4 t- d; ~  Z8 U! k8 C
// State Save/Load
4 g$ v$ A4 U. f9 G) C5 [7 @void        APU::SaveState( LPBYTE p )
+ v# q, A$ |3 P7 w{3 w0 `/ {% [6 [1 T7 S
#ifdef        _DEBUG
( B6 w( _; ?4 X  F9 Y" i3 |& ~LPBYTE        pold = p;* l8 l/ N8 Z  e" D
#endif$ ^2 ~! X- g" w$ ?& [

$ T1 s$ q" x; ^1 _3 j# t6 q        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞% v! F, s4 y$ X# l
        QueueFlush();
6 i+ @2 _5 L7 O8 }! t0 U; S, D
0 Q9 |* W0 ^' c! S        internal.SaveState( p );
, ^3 H( H! x$ ~/ E: m, d7 [        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 ?6 P, ]7 I3 G' i+ R
: k' a+ L( @# l2 ?& m& m        // VRC6. j4 D2 q# Z: S* ?
        if( exsound_select & 0x01 ) {6 ~% V) ?% P6 f6 W0 x, X1 h7 K$ [
                vrc6.SaveState( p );
. x1 s3 a1 Q5 ^/ }                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) j0 S/ U& B0 ]+ _4 G! d2 q2 C
        }' l  {1 G  ]( [$ n  ]# {
        // VRC7 (not support). a2 F5 B; a# p: z! t/ W
        if( exsound_select & 0x02 ) {
$ w9 |0 O6 k, h                vrc7.SaveState( p );2 P$ H6 }  K! k+ G1 n$ k+ c: c
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% h/ J' ]/ u8 q$ X% u        }5 a& Y$ w4 `# U( x' B- j5 O
        // FDS1 l2 u( k8 I, m- N' P
        if( exsound_select & 0x04 ) {
( T  Y1 A2 o+ g5 ~' p' q) u4 e                fds.SaveState( p );/ ~4 _+ ?" p5 n3 y2 p% |
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 z! W* @0 m0 h6 N. Z$ `
        }
$ K0 T! o" R6 N+ E        // MMC5
, e1 s9 m4 u  |2 m4 U- F9 ~        if( exsound_select & 0x08 ) {
4 _& j: b$ c! C2 ]+ M2 H                mmc5.SaveState( p );6 o" r% T9 P7 K7 B
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 q3 `) S# I  _        }
+ I; c! c( U5 G. O/ K. c6 d        // N106
" s& G/ I* J+ [* T* s* ]' x  m2 K        if( exsound_select & 0x10 ) {' [& t4 t/ Q7 ~/ F" |9 i( a
                n106.SaveState( p );% j1 ^7 r6 E7 l( U0 h
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 g! `0 _5 I% Q
        }. ~0 }& k7 h2 [# p9 g
        // FME7
; M. c3 ]" r$ ]        if( exsound_select & 0x20 ) {
+ f& f- h; [  K& r                fme7.SaveState( p );" }4 Y  Y! E& f% ?6 S; X6 @. S
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 o" |* B/ }2 U- \4 C
        }+ x4 a, H& ]1 C* s" C$ j8 u

  i1 j; s8 d9 d# D$ U#ifdef        _DEBUG1 h8 h  Z6 D7 u) G9 V  ~
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
( T4 W% [4 b+ _' r7 d- l4 y#endif
. w( I& |" y4 y% K}
$ u. ]% X  n9 M: v
1 y6 f4 s4 }" K. L: H  b! uvoid        APU::LoadState( LPBYTE p )
# b' y, M+ p' u& D3 @{
$ f* y4 {) r" X. v) a( K3 N- A. C        // 帪娫幉傪摨婜偝偣傞堊偵徚偡1 A) _5 _5 i+ a
        QueueClear();
% Y. ~9 w+ w: z- ~& v- N
. i( E7 f2 j' h: t3 U) d8 A        internal.LoadState( p );" q( w' n1 D1 |
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 l2 F/ n" x. S& T5 \6 \; r7 r/ T. A3 p: L, u# O1 t
        // VRC6
' [) @1 [/ u" R6 d. |' d+ ~        if( exsound_select & 0x01 ) {9 n% g, G, k: r- \5 G# m
                vrc6.LoadState( p );
2 N# x! j* h$ O7 x# C                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' L6 Y& f3 I* O7 Q) r' [
        }
7 x/ u6 `7 g5 o        // VRC7 (not support)
# ]' \# ^% D7 m& z0 w4 D% Y        if( exsound_select & 0x02 ) {
1 C( x* g9 A& S/ A) l0 Z                vrc7.LoadState( p );
  O% `" t) V) }  ?/ c* b" L                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 K$ @4 A7 D# ]2 g+ N3 U  \
        }9 B7 j  Y/ _8 n( v. G
        // FDS
6 y0 ~' S9 C" l        if( exsound_select & 0x04 ) {6 c* z" F* F6 }6 x2 E* L- z& Y
                fds.LoadState( p );
1 o! ?7 z; N& k. ?7 W6 S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 O% D! O( N' {; Y
        }% ]! Z. B+ b4 e
        // MMC5' S6 o: _1 i9 l* q, i( `# W
        if( exsound_select & 0x08 ) {
8 ~+ `4 x) Z. m9 a$ C! c0 T3 x& `                mmc5.LoadState( p );
/ Y6 Q  j2 w2 ?4 g: i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ g+ |2 t$ E8 X' w) W* u2 E
        }! Q6 X# g: s. y, t  w
        // N106
- j! ]. x1 t* O0 C        if( exsound_select & 0x10 ) {, f- A' _+ g. y$ W! i
                n106.LoadState( p );
7 s$ d6 X! m. B( @+ l( o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ p0 ]  m5 ~" `: Q
        }. |* e3 \1 |  R: T. \
        // FME7* Q3 @+ ~* y1 S) U+ Q! l
        if( exsound_select & 0x20 ) {
; ?! t; H1 L! N* x8 X                fme7.LoadState( p );9 a' E# p9 K4 w' r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 B( n( ~" x  S0 ^) n/ Y& ^        }- q+ ?, e( w0 F( ]5 _. |
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
+ t1 c0 E3 A6 Y. F( C' z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ Q( d: w) b( @  u' J* V
感激不尽~~

5 {. T7 U- i9 j* R恩 我對模擬器不是很有研究,. O9 b, U/ I& j
雖然要了解源碼內容,可能不是很困難,- V) ?3 ?9 X6 s4 ^* E* w
不過還是要花時間,個人目前蠻忙碌的。
1 h3 P, ~/ o% Q5 O- r. F6 f. {8 V- _. t& l4 i3 k8 d
給你一個朋友的MSN,你可以跟他討論看看,
  ?. q$ D& ^5 t# Q6 e% ?他本身是程式設計師,也對FC模擬器很有興趣。% ], R0 \$ _6 D& q

4 c8 H# j* J# D. bMSN我就PM到你的信箱了。) \$ O/ `: S. p6 f

, M. G0 p2 Q( V. Z4 w5 z希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
! u) J3 K( ^; ]. w9 `& r- c呵…… 谢过团长大人~~

4 c6 B. Y& ~5 m6 I. c) T
& f* f. E, N0 R4 h. U哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 L0 K4 H0 q9 J! M( k# |团长的朋友都是神,那团长就是神的boss。
- m7 j  Y" T: O6 t( }: x
哈 不敢當,我只是個平凡人,
0 T- s; v0 `) Q% h4 u/ T8 o+ v$ ^7 F要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: R/ _8 d: g8 Y1 r8 {1 ~
ZYH; @. v; L- N  E# z% J
QQ:4147343065 M% h6 E& ^: ?7 m
Mail:zyh-01@126.com
/ f3 Y% O' Q% B
+ h5 G. s1 q6 d2 q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 v- X5 y2 N, V$ v% P/ P% [
再次对团长大人和悠悠哥的无私帮助表示感谢~~

, D: w8 ^1 G4 H8 b& w不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 06:36 , Processed in 1.129882 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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