EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?4 \- s7 V5 E: s4 k  n' N8 C
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; s7 q/ C3 M3 r: Q% j! ^楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, c. W& e! t% J5 [& H
这里有相应的模拟器源码,就当送给大侠了~~
8 K; ]: p; L: v4 B8 l& |$ hhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
5 M: R) p4 S8 P) j) h' v8 g0 o) G; C% `, x能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% w( a/ `4 @9 \  {! i楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: {( h3 u! \6 Q% c9 F
这里有相应的模拟器源码,就当送给大侠 ...

( N& A/ j" {1 Z' P, }聲音部分(Audoi Process Unit = APU):( E# {8 H9 J" \
.\NES\APU.cpp
3 ^2 r% |( [& g6 M& P  [6 O.\NES\APU.h
& P" k8 `  Z" x/ Y  K: B
$ @+ B8 Z6 \' S, n8 d* v4 g; z" J) a' e6 w- p7 K/ K# z
影像處理部份(Picture Processing Unit = PPU):
0 ]' O) o- O* q- @/ A. f- `3 T.\NES\PPU.cpp/ `9 c" l* d2 M1 g2 |* ]1 t7 Q0 K
.\NES\PPU.h
/ a2 M( h% x2 b% h6 s& n! s# n
7 C- T9 E. q5 E如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:# W, Y8 \  t: b. w& B) r
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
8 d3 m7 I, Q6 g" O$ s//////////////////////////////////////////////////////////////////////////! m8 f5 K$ M- x9 E* k+ ~
//                                                                      //- b! h5 G# r& M8 J/ K5 W4 f4 O
//      NES APU core                                                    //. B2 x. e( q" _
//                                                           Norix      //
6 G/ n7 Z$ R$ {1 F) b! d//                                               written     2002/06/27 //. D& H+ E0 J7 s. o
//                                               last modify ----/--/-- /// q# l/ E4 I! W& f
//////////////////////////////////////////////////////////////////////////, B  X2 Z( n4 C2 Q4 L3 d. }5 E" {
#include "DebugOut.h"
3 s3 F2 t0 I: T8 o! ]) y7 _& x5 J#include "App.h"% k3 n: y- |# U9 Z
#include "Config.h"2 i+ _7 Y! L& S6 _$ n5 ]5 R
+ C: ^$ k- z. C6 Y
#include "nes.h"
1 \/ @; y; \0 w) R$ T#include "mmu.h"( s& f* R, Z8 S# V, |8 W& q7 `
#include "cpu.h"* a$ m/ g  ]# `
#include "ppu.h"& Z5 o5 f8 I6 N7 D% ], I
#include "rom.h"
1 o8 {/ [9 ^9 K7 V, y#include "apu.h"# p  Z! B  ~( ~" P: Z  Y

2 u" Z3 v5 p; f' Z7 K/ v: ]// Volume adjust
% r  _4 j" _" X- q: ~" R% u7 R6 D3 S// Internal sounds
3 P4 Z- u9 Z7 Z+ V#define        RECTANGLE_VOL        (0x0F0)
6 V* O: x2 ]5 P$ z9 ]#define        TRIANGLE_VOL        (0x130)
) Q/ |8 y0 j! W1 |#define        NOISE_VOL        (0x0C0)1 F& o- t$ o1 Z+ y6 q- b
#define        DPCM_VOL        (0x0F0)
% `4 v& i' a5 Z1 u* f5 _; r1 P6 J// Extra sounds4 r- k; |0 o# G2 e# \
#define        VRC6_VOL        (0x0F0)1 e  L! m: Z/ G5 Q7 p, j
#define        VRC7_VOL        (0x130)% @9 [0 S4 y! f8 \& u
#define        FDS_VOL                (0x0F0)
" K0 n$ C3 Z, U#define        MMC5_VOL        (0x0F0)( U$ H# h# z3 D- X; {; B" {3 o
#define        N106_VOL        (0x088)
" {3 Y; C! ]; M+ n#define        FME7_VOL        (0x130)- @" Q* E8 z+ S" D

& `: t( K! s! o. ?# N& DAPU::APU( NES* parent )9 J6 ]$ J" J3 a8 w8 x
{3 ~1 Z8 _" }; [2 A0 _
        exsound_select = 0;" w! m0 v  H- E  n- }& m) C1 z
- p7 {2 G$ m$ U7 I5 t2 r
        nes = parent;
) e  X/ e, m/ E7 J        internal.SetParent( parent );9 V- Q; h3 q# H2 b( X4 D8 k) ]
+ W( ^9 I- B" S* ^7 Y: [! {/ e
        last_data = last_diff = 0;! W: O; x  t6 V, d/ _
5 K$ `5 L( ?, i% U
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' ?& C- Z  B' R. d$ k/ {4 m' U1 o* o' t7 _' {: g
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 X) T, Z  B) T2 L* y
        ZEROMEMORY( &queue, sizeof(queue) );
' b4 K9 \) b5 u9 [- u( V9 H0 l        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 o* t) k: a; w/ C0 j' d! q4 e* I
0 F7 s+ `8 V$ |7 c
        for( INT i = 0; i < 16; i++ ) {  y4 H) i3 s, a# \
                m_bMute = TRUE;
: ^; L/ I3 i! }" l: }        }, x4 X; C" _( `& c3 v
}2 d, p6 N' F  S  O1 D
/ n& X# f$ D" {$ v6 X  R
APU::~APU()
2 l6 k  z; L( C% Z* ^( m/ a& h) ^{( P& n- ?' h  }
}
) n. U# `* \* T+ t# J
8 e  ~& x1 J6 F0 k8 Z3 wvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
7 j& b( H; F6 {5 h0 w& H{( `8 D! H- G2 a# M( A" I
        queue.data[queue.wrptr].time = writetime;
& i' O7 \$ w, F1 ^& P        queue.data[queue.wrptr].addr = addr;9 v  X% e' \/ P  L1 n: o9 ~0 V
        queue.data[queue.wrptr].data = data;6 K( @2 y# v8 p. Q
        queue.wrptr++;* M5 F) t1 R% j' p9 U  r4 s
        queue.wrptr&=QUEUE_LENGTH-1;
) K0 a! H+ C2 K. N) N. B        if( queue.wrptr == queue.rdptr ) {: o/ ^/ |5 R( K( Z
                DEBUGOUT( "queue overflow.\n" );3 `. _9 r0 b0 T$ g/ L* c
        }' h& F. ?0 G) T# Y& ~& ~
}
. Q4 P- l/ w- G+ g
! ?7 @3 k' H' eBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )4 `& m) y) M- w8 y% e& t
{6 B2 K0 `" R# P, t" h/ ^8 F& C: d
        if( queue.wrptr == queue.rdptr ) {
( z1 L% I" a2 W& [0 C" B+ T( ]                return        FALSE;
" K8 D: }) m9 v9 @" [7 |& r+ _# t        }! h' v& ]6 r2 Z; y" C9 j, H2 a6 p, a* U
        if( queue.data[queue.rdptr].time <= writetime ) {4 ~  F) E0 s9 q2 W/ j; {: }. X
                ret = queue.data[queue.rdptr];$ x  L' _* F0 d4 C" }6 t
                queue.rdptr++;
- Z1 a  K3 q5 V                queue.rdptr&=QUEUE_LENGTH-1;  I2 f9 \. J8 z6 o, y# t
                return        TRUE;
. O: t% i- R0 Q9 C# N" l        }* @! z0 t* x/ f  L
        return        FALSE;
% x0 G* R7 M) E% j8 L}
7 U( ~; t, e4 @; T9 ?
2 d. Z; f8 c! v" M4 Y' w+ }( yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ). @5 g1 j& {3 E  M1 Z" `' G
{5 |* d& s+ X1 ]5 V9 D: e
        exqueue.data[exqueue.wrptr].time = writetime;
0 y- w# n3 ^* K; f1 b% p        exqueue.data[exqueue.wrptr].addr = addr;
$ {4 F0 s8 Q. f! l$ \( _8 m+ v        exqueue.data[exqueue.wrptr].data = data;. r7 n; H  W( A2 @, [
        exqueue.wrptr++;7 o+ P9 s! q+ M
        exqueue.wrptr&=QUEUE_LENGTH-1;7 j: |( }3 W* F1 R3 p- x
        if( exqueue.wrptr == exqueue.rdptr ) {0 N' _( X' g: S- L) D
                DEBUGOUT( "exqueue overflow.\n" );
! T  U8 {: X. s! k7 F* \2 C        }: n1 }: v$ j4 k5 F9 Y3 w7 X+ B9 _+ G
}
/ t: C# t) n% ^( `# Y/ Y+ _/ z% s6 j" j, P2 |5 G
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' ]+ Z9 u: U0 c& s0 m, ]: i{$ _  ^/ [0 E% r  C
        if( exqueue.wrptr == exqueue.rdptr ) {
& ^3 n( G7 h( P5 X" D& l) Q+ }                return        FALSE;7 N6 x' U+ h6 {
        }
% u0 z, |9 y) W& c        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: o$ S, D0 n" w8 |
                ret = exqueue.data[exqueue.rdptr];
* w8 U8 J' A1 }: c* h                exqueue.rdptr++;
: {7 V# A" Q; l8 T3 R- D) d% r; W                exqueue.rdptr&=QUEUE_LENGTH-1;8 k0 P# V$ J' P" G! ^
                return        TRUE;
& h9 ~, e; w, O* S& Y        }
+ m6 q* X' H3 ?" o! n/ E        return        FALSE;4 w* \4 ]4 A& R; M
}: d$ Q5 R2 W; `9 |) G' l) n

( D0 ~2 }' _1 M* z% ~void        APU::QueueClear()
+ `% w( j5 F( H- b, V+ M{
' T4 I  K( Y* S        ZEROMEMORY( &queue, sizeof(queue) );
3 K8 g5 x+ m4 x/ v9 N1 w' N        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* [/ X  j9 }" i! y& ~- t}
2 A8 _, w7 G8 o9 r- g
( i2 s8 d# t. a. v4 D, |2 z+ Y2 wvoid        APU::QueueFlush()) p) w" a. H2 M7 a, E$ _5 s
{
. Q) Y/ n7 v! }6 o1 B        while( queue.wrptr != queue.rdptr ) {4 o' v/ u+ u- P7 ]. [9 i* a* u
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) v5 M: \$ p  w8 m; V6 J4 d. b
                queue.rdptr++;
# O; ^9 ?. L$ E  e9 F& V; P                queue.rdptr&=QUEUE_LENGTH-1;6 R0 V6 V6 u; _$ v
        }4 P) w& r% n6 C) d0 v" L

  I9 c  ^7 p, G. L( L7 d        while( exqueue.wrptr != exqueue.rdptr ) {/ V- V+ i$ B. N6 q+ c7 A2 b
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );* ]8 S; l) ~0 v: X( O0 F
                exqueue.rdptr++;
8 w4 P9 d3 R# g$ J' D; [                exqueue.rdptr&=QUEUE_LENGTH-1;1 w, U  a" O8 v
        }
$ v: q0 z5 E" u. B+ `) l}* {/ a' d  ]& P' r0 w$ ~* p

4 y3 g3 e. \, l+ kvoid        APU::SoundSetup()
, ~. |" t! [. `3 p4 Z{8 a( S1 d% u- N% B6 q$ ~
        FLOAT        fClock = nes->nescfg->CpuClock;
* z$ m  ^! v" y# F7 w        INT        nRate = (INT)Config.sound.nRate;
3 J) ?6 ^" S% p" T0 g0 S        internal.Setup( fClock, nRate );
) T, C3 Y4 M$ L4 J: A0 }) N        vrc6.Setup( fClock, nRate );
% h" ^+ Y0 k' O* Z$ o        vrc7.Setup( fClock, nRate );! c8 X  l. }  s* p
        mmc5.Setup( fClock, nRate );' R+ W& h. C0 v- v9 r3 ]
        fds.Setup ( fClock, nRate );
! g% z+ W% @8 W9 a0 F& M/ a        n106.Setup( fClock, nRate );
8 U# l/ ?: o8 t6 B! X5 O        fme7.Setup( fClock, nRate );
8 y! |' v+ r/ H/ ~}
/ g7 D5 }( {5 Y+ c4 f/ f' ~9 _  g4 J7 y* s/ M0 t& ?2 T( y5 _: d
void        APU::Reset()% |. A) ~7 d& S! {8 d# {& e
{
  `* E; s) n. r$ r0 E+ {        ZEROMEMORY( &queue, sizeof(queue) );
, v0 l5 G+ @8 I9 r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ H, q) M' M2 O5 Y! x# {9 x! P) E" I) p- v+ s: P$ r5 L
        elapsed_time = 0;  m4 Z0 W1 u- {0 a
9 h* c, e9 }9 r9 g9 l
        FLOAT        fClock = nes->nescfg->CpuClock;
+ N  K7 U0 {' Q        INT        nRate = (INT)Config.sound.nRate;* K3 L2 Q! J# `+ R3 J+ c6 t+ e! E
        internal.Reset( fClock, nRate );
4 m- a$ S6 ]- B% V# y/ r6 [- J        vrc6.Reset( fClock, nRate );
" t" e7 Z+ t) w# ~9 x        vrc7.Reset( fClock, nRate );8 V5 u1 c4 l3 |3 D4 ]
        mmc5.Reset( fClock, nRate );
( L& h, O2 o2 g( q& T2 ~7 X- N        fds.Reset ( fClock, nRate );* \( z  Q' H9 v4 F0 b( i
        n106.Reset( fClock, nRate );
: I) b7 ?2 ?3 z        fme7.Reset( fClock, nRate );( @3 Q: F$ n: E
, I3 g/ Q. B+ q" t
        SoundSetup();
  F9 Y" l0 y# s4 p}
: C8 X9 T2 A% j% d* }" V( n, `# d
3 m5 B9 I* V& D. T0 h. M9 C; qvoid        APU::SelectExSound( BYTE data )  x- i5 ?! X1 x& X$ l- Y- c
{
% v8 g6 y* l& Q5 r% I& _6 |4 N: ^" J        exsound_select = data;& R5 s6 w9 N' A1 J, |* \9 s
}$ z3 b: K( T8 _( _( Y. g

, n$ [* A$ h$ `" _8 \: `4 U: r# QBYTE        APU::Read( WORD addr )
  m% e" v2 l& q9 U7 d0 `( U{- f0 n- t+ P2 Z. T: C) m
        return        internal.SyncRead( addr );$ c1 P3 S  ~6 `! R; Z! s
}3 a% E5 J- @& J7 A3 n  M
" P8 j. `8 a$ `* W1 W, c
void        APU::Write( WORD addr, BYTE data )
! \9 E  h: I; g. f& [{
7 M  A" Z/ F  h- ?4 B. c        // $4018偼VirtuaNES屌桳億乕僩
7 s1 x% c0 B. F  }4 V# V0 f        if( addr >= 0x4000 && addr <= 0x401F ) {% H$ K7 O( S' b1 f! n
                internal.SyncWrite( addr, data );
; f* }2 r% ?+ O8 N5 ^                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% `4 ^' s! t  Z/ r- q2 ^  w        }
1 e5 z( s- e0 a}
* a) O8 e: U4 \# w; }5 Q" [9 ?& N1 x8 Q
BYTE        APU::ExRead( WORD addr )2 x& L5 Y& ]( S1 A  q5 c
{( p' j6 @9 s! `$ d2 O, I% v4 x) k  {- i
BYTE        data = 0;9 C' V* E/ d& G/ g; a

1 ^2 m! ~1 ^. |        if( exsound_select & 0x10 ) {$ n  ]# R, Z5 U- Q7 N! [0 Q3 W+ B
                if( addr == 0x4800 ) {* j1 T# @) H3 ]* g6 f4 z6 {# K! v
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );2 T# w, M% e$ |( s/ Y; ?
                }: [) v. S6 k2 s! r! v
        }
( t# |/ f1 N: f, ^$ g  F1 }        if( exsound_select & 0x04 ) {
1 T  T* C+ M- A6 C* M5 ?& h+ S6 p                if( addr >= 0x4040 && addr < 0x4100 ) {
: t1 ~7 B2 }0 [' g                        data = fds.SyncRead( addr );
# v* m1 k5 ^: K% D1 ^  p; J. F$ J                }
% d" E. Z# f# |; j9 v6 @* q        }, a. T; d$ q" z: [, G# b% T9 g$ C
        if( exsound_select & 0x08 ) {) V; f& d: N1 P- P! q
                if( addr >= 0x5000 && addr <= 0x5015 ) {
& ]& B8 x: W- c' {! a4 U* H+ ^+ X                        data = mmc5.SyncRead( addr );
- }( x+ w' @& W( I8 ~" n6 n. M1 Z0 S& Y                }
& P- [2 s; G# z" r& r) H        }3 [9 R  i4 k$ \" [7 M
# k& Y; D' e4 @* }* N2 v. Q0 V
        return        data;4 b2 g& k% D% e' A- q
}: }8 o% ?9 H* n& ]8 h% ^. O* |) ]
$ t; `4 F8 H4 r4 N" K
void        APU::ExWrite( WORD addr, BYTE data )
$ {) ?5 c$ r; }7 n2 Z2 U' K" v{! @  b* A5 ?. C, A
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );* {4 c6 H* ~" M( T0 h, `

5 h9 f( R3 W2 D0 F0 b* L        if( exsound_select & 0x04 ) {
. I: Q' E# n* }, \. d1 t0 N                if( addr >= 0x4040 && addr < 0x4100 ) {) u% y3 U% N6 |! r; d9 |
                        fds.SyncWrite( addr, data );6 Y5 K$ f& d0 M3 B# ?, |) L8 z# g
                }, C; q6 j/ M  o' b2 g
        }- E: a6 `  u* O9 G8 e* x- E

8 I, p- V: g& _1 J7 n        if( exsound_select & 0x08 ) {9 |& `' ~5 D; m# H: P' C# K
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" z4 V% A9 f/ T1 u/ G                        mmc5.SyncWrite( addr, data );
5 N4 Y2 Y- Q9 n! N4 e% s# z& H* V5 |6 F                }" d; J6 Q  S9 [9 v4 s7 B( f
        }
' i6 p% Z9 N, X  Z}9 X% R4 b! B- C; Z" w1 ]' s8 _$ U

2 K4 o! h! v, g# f+ V& Mvoid        APU::Sync()
$ l% w$ h- ~% Q% j# R{
7 K( E+ `8 T2 K2 t/ H% ~" g" v}
8 K. K/ O8 z  e7 I/ G
% x/ T$ Z- d  T( T8 zvoid        APU::SyncDPCM( INT cycles )5 C# C$ b+ B  I* [$ E" Y. O
{3 F4 H2 L' p+ {; O4 V; O
        internal.Sync( cycles );
7 [+ N: s- h; y6 r/ v: I7 l
4 x) D: ]* W0 D! k1 l2 Z% o        if( exsound_select & 0x04 ) {5 p9 A1 @. u7 y8 X* ?2 z
                fds.Sync( cycles );6 a5 g( p! U3 t7 C( r
        }
( W* `6 r. I! V3 h* t" f; p        if( exsound_select & 0x08 ) {
6 Q  S/ S+ L" _1 ?8 ~/ g                mmc5.Sync( cycles );
# o/ U' Y7 W! D7 i' e$ H: H        }
5 r6 ^& i) E% v; V9 q  a3 r}
$ W# v* u/ \6 ~/ F" K% k% m$ K
% ~; H& t' V1 I3 I. Yvoid        APU::WriteProcess( WORD addr, BYTE data )
3 W/ h% L7 I( G{1 \! S: K: X( j0 f6 O, h" G& i
        // $4018偼VirtuaNES屌桳億乕僩, D+ r- k0 `/ B# D/ c
        if( addr >= 0x4000 && addr <= 0x401F ) {9 p! A! I/ g& J# J3 p5 Z
                internal.Write( addr, data );2 z( Y% b5 M% Y+ Y
        }
6 P. I3 N! k/ A- X- l2 j! b- Y, I}
( p3 q1 P3 ^+ G6 I
( [  `; ?, S. X- b9 kvoid        APU::WriteExProcess( WORD addr, BYTE data )
( X2 @& J7 X5 V5 l0 F{
! I; f" m+ S' a: S  T        if( exsound_select & 0x01 ) {/ ], B! h" }. O: U4 _8 h0 E; K
                vrc6.Write( addr, data );# p1 g4 f6 D4 C$ x5 r, S
        }
4 A9 Q  G/ p. h7 n' n1 l2 K        if( exsound_select & 0x02 ) {8 v' d. H% L) ?8 K% [: J" ~
                vrc7.Write( addr, data );
) [. T5 j1 h9 l+ M! V# ]9 Q% {2 V2 R        }5 H$ Q1 Y) |# H. h5 H
        if( exsound_select & 0x04 ) {
: I% c( Q. J8 `                fds.Write( addr, data );/ S4 D9 @5 g/ l
        }
2 D. u) C0 i. ]  ~8 F0 [% v/ n        if( exsound_select & 0x08 ) {
# v0 S; V% h$ O                mmc5.Write( addr, data );
- E0 v4 h4 g# D% Y        }; q) w. }; p8 H: O
        if( exsound_select & 0x10 ) {
& w2 s6 Z( c6 g8 s2 ~2 Q5 f2 [                if( addr == 0x0000 ) {
% X: M. o" c% v) ^9 X  k                        BYTE        dummy = n106.Read( addr );# a3 j( P9 s2 O) E2 h
                } else {  H; m4 [0 b. m( ~
                        n106.Write( addr, data );
2 m' P0 ]2 A# O                }
+ N! `$ q: j3 c+ R        }
, Q9 z' q( K+ i5 |- L% `8 a) R        if( exsound_select & 0x20 ) {
; ^6 V/ a, V8 b3 v                fme7.Write( addr, data );& O, Q! s* m! q7 v; q
        }
1 B, o" O( ^$ w, ?8 B- J) O. t}
* Y# J& W) ^4 O6 T; j. F0 K3 k9 q4 @( k8 I9 Q8 T- Q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
; \% Y3 N3 Y7 p8 h1 `{- ^  Z5 I/ J3 q: U$ Q
INT        nBits = Config.sound.nBits;9 a  S7 G$ O- D
DWORD        dwLength = dwSize / (nBits/8);  f9 a$ I) V! I: F& u$ J
INT        output;
6 v. S5 g  v* gQUEUEDATA q;
4 o& i& O$ {2 k2 O% x+ qDWORD        writetime;
4 B" L% i$ q9 B" a! Y8 T6 u
2 f8 y4 a6 Z) x# \. A( W4 eLPSHORT        pSoundBuf = m_SoundBuffer;
! V7 z2 F2 k& M1 LINT        nCcount = 0;' Z( f- [( N. ]+ [3 ~. _
# P& w& x8 n: b- B. `
INT        nFilterType = Config.sound.nFilterType;- ^$ ]: K& H/ W6 ?+ k* ^

! H8 e8 s" `- A3 h3 H& m        if( !Config.sound.bEnable ) {
3 q8 d# a. m8 e  M( x! E                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
  ~' l/ K' P! i, [                return;( Z9 ]) q4 @6 C, R6 h0 g1 s( S
        }% s) b# G7 E2 e) U: x* I

1 |; ~! b6 D( A1 _9 ]3 r        // Volume setup% s/ H) |) p# A% K
        //  0:Master
" m6 s, E$ ~5 Q- ?, p# e) W        //  1:Rectangle 1  \# o" R5 P9 G, I
        //  2:Rectangle 23 y: M( m2 }. [5 U; g! C$ P' ]2 O
        //  3:Triangle, L% p) C( O6 s6 ]
        //  4:Noise$ y9 p* O% A  i* n( Y8 C
        //  5:DPCM
, E% r7 j9 T" B: X0 K4 C+ F        //  6:VRC6
2 C  `9 h2 `. r. \+ e; M2 b        //  7:VRC7
# e' i' k0 R+ p) ^& c, I        //  8:FDS; q$ j! c% C6 N$ h  N9 J
        //  9:MMC5
+ H3 Y# |0 q/ k0 v2 F2 M! h: A        // 10:N106
. O8 _* ]4 _- o& i        // 11:FME7
4 j! }& H- z8 P( g2 Z        INT        vol[24];2 |; b) A/ i8 h8 z# J! O- F
        BOOL*        bMute = m_bMute;
" V" R; l: H  b9 h% k        SHORT*        nVolume = Config.sound.nVolume;
$ \& Y7 U- [* W2 s+ G* i/ c. f& o# c. L$ {
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
, c" q  T) l: T+ g8 Q9 }
0 l# |, p4 y' j8 B' j        // Internal  g; j0 {" {% S3 O' W) B
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
" t, U. ^7 e& O1 t        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
$ V0 J& P) J- D1 G        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, q) u+ e  f8 N" x0 c        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;8 z! V4 l3 G) t2 b' W' g
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 M/ i+ e' H7 L8 Y5 ~+ N+ y8 Z9 E
- |) e$ d8 ]# M2 j% m        // VRC6- d. x( F  \! H9 m, s
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: v  X( e: V1 J7 Q$ Z0 y( s2 U9 t: Y, t        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& }# o- o' q4 Z# Z" h        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 W$ b) ~+ N8 X  S
, [9 w$ s1 y/ r2 |& F5 m6 N
        // VRC7, Q1 X4 k; x* @/ [. Z
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
6 V1 J- }2 [6 s# w; L1 A% m
  X/ t0 M5 p8 z6 h. h; }+ \        // FDS
' `4 ~+ e! g2 O7 p4 Y( W+ r        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
! N- i2 Z; p) a0 t! q
1 q0 J* A% S' Q1 N  h  U        // MMC5
9 T, M, e! e6 d4 W/ u  ^: r5 e        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- ]: Z/ a8 {% T& |& }  N
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% h4 c* |& M% B        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 r  O5 J1 a/ `9 ~" ]
4 x6 u) i) q0 j3 m2 t7 l% f        // N106; a  |6 J: O; w8 u+ c  \
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 t* A" K2 u1 t! {) E0 Q        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 T; ]& L1 X1 a9 J0 J' n        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, J2 G% l' o  w8 I* R        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! V' K& d) \; u. X        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& X' B/ i" U9 s8 C        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( s6 A' H3 }0 r3 H" Z# R  c" N        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ o8 }: E5 `5 A) q0 ]4 U2 A
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% u" [; P0 v- ~6 g5 W- @- w1 B6 I

1 A. ]- [! t. ~4 w' E        // FME7
/ J# k  O! m! p        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 Z" [2 D' Z# F/ e, y' v7 `0 y+ ?        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 J$ N+ R8 u$ t3 I& y        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 S3 Z% ?; D  }
/ C2 ~5 u( V9 R) r5 R
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
# n0 d! L2 j0 o        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 U* O9 i/ Z; M5 ?. A: B8 |2 w8 r0 S

# F5 ]+ [+ F: M$ D4 }8 L* |        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 |& N4 l! r) g. @' f' Q1 g4 p
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* W  ~- ~+ c# c4 d8 ?
                QueueFlush();
8 d0 g' e6 P, O$ J- m- }        }
! Z! y. x+ T2 {+ x
; U" \6 L3 K3 }5 D& e3 [        while( dwLength-- ) {
3 [/ Q! k# }% i; @" y/ x6 Y6 ^) c                writetime = (DWORD)elapsed_time;% ~8 R0 ?* B/ H$ b  T2 s% R2 T
+ ?- U7 Q1 q0 J' p
                while( GetQueue( writetime, q ) ) {
6 D, R& C- f- Q' A4 I                        WriteProcess( q.addr, q.data );9 u4 k& H$ E- |$ A  E. O
                }
% F, y8 `! g3 T) L1 |+ f8 d, `% k  r+ X' M/ _$ Y
                while( GetExQueue( writetime, q ) ) {/ t! ]2 |( s. z' Q5 h
                        WriteExProcess( q.addr, q.data );
& P, R: y( v5 ]                }, x% O3 @& U. Z: t
* Z( A) b) ]; T- `, x
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 V5 R4 m! P% w" C$ K' r
                output = 0;* z3 v  P- n0 @: k* H1 G
                output += internal.Process( 0 )*vol[0];
0 v2 i/ H! \' C8 M: b* g4 b                output += internal.Process( 1 )*vol[1];
4 |& b) O: N! L' H                output += internal.Process( 2 )*vol[2];
8 b& O: G( d. j* ~' M3 f                output += internal.Process( 3 )*vol[3];
% n) F3 q# H4 f2 V+ ?# X1 b                output += internal.Process( 4 )*vol[4];2 t0 Y5 z& q0 ]$ b. i# ^  ^1 p
0 A& \7 h( Z% }$ [! G: q
                if( exsound_select & 0x01 ) {
& N. P; b9 f. \1 p                        output += vrc6.Process( 0 )*vol[5];' x  G, f" H) N$ c* c0 H+ R) o4 m
                        output += vrc6.Process( 1 )*vol[6];
$ w0 ~+ u1 @4 W8 L7 a$ I* X) l, a                        output += vrc6.Process( 2 )*vol[7];
0 }( p5 f' ~3 y7 m; @2 X9 r                }4 J3 y" [7 f* m" c( b
                if( exsound_select & 0x02 ) {
( x. G8 j0 q$ {5 x: e! q, R                        output += vrc7.Process( 0 )*vol[8];
; W- H* y, Q* ~0 W: p9 c; _3 E% d, `                }* F/ u# r/ o  s9 w: G. G' `* l! m1 U
                if( exsound_select & 0x04 ) {
2 j2 [( m1 L  C" P) ?9 h; E7 v% s                        output += fds.Process( 0 )*vol[9];
; ^3 c" S5 }( H- q8 E0 m6 u9 e9 R' S                }
6 s) Y0 v+ v; @  h2 V                if( exsound_select & 0x08 ) {$ U% e) l, {- H
                        output += mmc5.Process( 0 )*vol[10];- }5 U, m$ k( [) t! i3 l/ D% y; w! B
                        output += mmc5.Process( 1 )*vol[11];
  [6 G$ r" N  y1 C8 H5 C                        output += mmc5.Process( 2 )*vol[12];
7 i& a0 \7 ~$ b; a% ?9 `" g                }# r, x2 ?4 i3 l
                if( exsound_select & 0x10 ) {8 E" h5 D; q. g4 C* ]2 z
                        output += n106.Process( 0 )*vol[13];- L5 ^" F% M; f" D# r$ `" A  x! o
                        output += n106.Process( 1 )*vol[14];  u* L3 W4 ~- Q
                        output += n106.Process( 2 )*vol[15];
% c5 b3 d% K* `6 U7 C* F                        output += n106.Process( 3 )*vol[16];
3 ?! \% Y; D+ F! }                        output += n106.Process( 4 )*vol[17];# d( f- N1 c$ u/ K7 W3 Y+ u- h$ R
                        output += n106.Process( 5 )*vol[18];/ L% y  }9 [6 b$ v* G% ]
                        output += n106.Process( 6 )*vol[19];# Z# u- j5 z3 q8 K
                        output += n106.Process( 7 )*vol[20];( @# k- Y* k; z1 a" N  i( k
                }
4 f1 G) |1 Z) U, I                if( exsound_select & 0x20 ) {
5 [% W8 Q7 F! K, k2 u1 _$ }% ]                        fme7.Process( 3 );        // Envelope & Noise
5 n; g" @1 p, M% R8 f0 ]                        output += fme7.Process( 0 )*vol[21];
: i% V* G; a7 S. l2 m' S* O2 U' E                        output += fme7.Process( 1 )*vol[22];/ H3 H/ _$ r) H, n# ?5 E
                        output += fme7.Process( 2 )*vol[23];/ r0 j" V6 Y: k( }: b
                }+ H2 t# M; k$ Y' F' L3 B* P) o7 C% q! |

' S; Y  Y6 Y8 Z+ ~9 E+ \                output >>= 8;- F( L% W8 t1 o% z+ q, r7 `

" ~$ u5 M7 [! {/ X3 Z: a; _5 C                if( nFilterType == 1 ) {
( r, }1 W7 }, T" d+ B7 Q( z                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
( D4 l# \: l+ @, E0 t9 Y2 ]; \                        output = (lowpass_filter[0]+output)/2;( D7 ?4 w9 m% L- U% v5 r0 N
                        lowpass_filter[0] = output;
5 S6 u0 c/ f) m! x1 a                } else if( nFilterType == 2 ) {7 ]% M( d3 F2 {0 n; ]7 K, C
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 |$ o" M, }2 e1 O+ o% G4 A. z
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
( I2 K. d7 |! ^, E" k9 Q) M4 ~$ v                        lowpass_filter[1] = lowpass_filter[0];
, \6 B. o! d. D( T                        lowpass_filter[0] = output;9 L" |& F: G7 P) |; G
                } else if( nFilterType == 3 ) {
9 v' v) n; A6 J% m; h                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
, u; M# t: o1 U! b                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) R# W& Y; H5 Z# h1 }7 w, |  r+ R
                        lowpass_filter[2] = lowpass_filter[1];
1 Z4 K% v6 M5 P- u, W! I                        lowpass_filter[1] = lowpass_filter[0];
+ i/ v; w/ \- {& n8 {8 ~                        lowpass_filter[0] = output;
) h9 m- A: o& ~" T# m9 Q# |! @                } else if( nFilterType == 4 ) {
- e! Q( t3 I3 }. g2 r: R$ q                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)/ d* ^& |. P6 E5 B
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  h. q  B2 h0 K+ C# Q6 Q
                        lowpass_filter[1] = lowpass_filter[0];+ E2 b  Z5 n( s  y
                        lowpass_filter[0] = output;$ m" ?: C9 a# F/ V4 w+ @0 Y
                }
' ~9 t: i/ I$ D' o# `( L, i6 v$ a8 J1 x
( w. v# L0 H/ U9 m#if        0
6 U* K3 r) R6 ?0 S                // DC惉暘偺僇僢僩% D# [0 B1 U4 w7 j
                {
9 `  f; d( V, q                static double ave = 0.0, max=0.0, min=0.0;# \  t% w) F( G0 ]2 V
                double delta;" k3 R9 h. ^; {2 W: p; N
                delta = (max-min)/32768.0;/ ]7 w2 I: D+ q" y/ c
                max -= delta;/ i0 u, I: M# w0 O0 d! z9 A. m; ^
                min += delta;
; `+ L7 H5 |8 o0 p& P. a                if( output > max ) max = output;
- c, t- r$ I1 B                if( output < min ) min = output;" A5 c# J% C2 W7 x! Q/ [
                ave -= ave/1024.0;
1 f2 z8 S* @' b" Y5 n                ave += (max+min)/2048.0;
- O7 B& S5 m& N                output -= (INT)ave;: @5 N- w! i' e, I
                }+ m# L" q8 a) T' B
#endif
7 \) Y8 a! \0 L#if        1
: s# {9 k2 z1 i+ x                // DC惉暘偺僇僢僩(HPF TEST)  h6 X9 a3 o" K8 ?
                {
( d# g  {6 c1 T$ x9 [+ m' k9 E" {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 e1 q8 K5 o4 j1 U( F9 T                static        double        cutofftemp = (2.0*3.141592653579*40.0);
+ K0 W8 \7 [8 I* t* d5 A; t: E                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ A! N5 Y' m, H1 ]9 }0 E                static        double        tmp = 0.0;/ d0 R& w- `) V: a, d; d3 k! P
                double        in, out;
. d. u" ?. T; Q' T/ {. e2 H) J) w% T) F+ @. y
                in = (double)output;5 P7 y7 U: e# _# q2 x, S
                out = (in - tmp);
- e2 @3 V) g5 ^* Y0 y% O. e                tmp = tmp + cutoff * out;) ^+ t; B' G6 W- W6 R  N# Q
2 w" T' w# ^; u
                output = (INT)out;
/ c; b. @# @, v                }
& i8 A# Y, z9 J" K# C3 V#endif
; }- L3 j0 I5 N9 n; q: h9 B+ A#if        05 o/ e  Y) ^1 J& g. e9 l  |
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
6 }7 ^  m4 h$ d6 s2 K                {
, `0 L3 I# I2 U( N                INT        diff = abs(output-last_data);
* G8 \+ {2 I  C6 D; C                if( diff > 0x4000 ) {7 A8 Y" _% H# n
                        output /= 4;# i" d1 k2 Y. R' k7 r8 T5 V
                } else
1 ?! S) U9 m- c, L3 G& ]) p% P                if( diff > 0x3000 ) {
+ @" |. x8 D! ]5 h* V+ I                        output /= 3;. C" d3 I" y+ J6 X3 e
                } else' t  K5 u+ A5 b7 f4 p- w
                if( diff > 0x2000 ) {
( w7 C4 V  @/ `% x                        output /= 2;
: \' p: b& [1 v0 X" c7 N$ ~& I                }
! A- q, G8 |/ o2 N) i                last_data = output;; o  E3 p0 V+ D1 ]0 _1 c/ W
                }" ]9 G; c9 q! a" D% d
#endif
+ p/ ~  k. x1 O* W                // Limit
/ G* t- y' [/ W" y1 }( t4 ~                if( output > 0x7FFF ) {
2 W' h3 ~, M; p' J                        output = 0x7FFF;
" E, p7 b  {( M6 ~, n# A                } else if( output < -0x8000 ) {3 u. u& V# K* L# ?
                        output = -0x8000;2 u6 b* v( {+ E# U
                }+ r& G$ s# }  q, o2 F7 }. @
, r3 c1 ~: X) O" J/ U% G
                if( nBits != 8 ) {
; v/ I% `& R: J0 t& |" [                        *(SHORT*)lpBuffer = (SHORT)output;$ z  F; W! L4 T
                        lpBuffer += sizeof(SHORT);
- x9 D6 J( Z$ [$ F6 c) q; k! S                } else {
+ A/ R+ \: R. F  c                        *lpBuffer++ = (output>>8)^0x80;
2 _' \( h! I, J" e" i                }! E6 {7 i( e! _# u! b

. @# W" D* J3 Y# r                if( nCcount < 0x0100 )
# X( Z+ `' v2 r2 R0 q7 B/ H                        pSoundBuf[nCcount++] = (SHORT)output;
2 h0 f2 q" K* ]- i# ^/ u0 B; Q2 r: C5 j: S1 ~5 B
//                elapsedtime += cycle_rate;+ Z: ^: l" J* q: n
                elapsed_time += cycle_rate;
( t! f* z% j* e        }
. r! z0 ]: x0 ^, x0 u, C1 B: ~& Q% |* |
#if        1
: ^! \$ N' }: W. i- }* A9 W9 O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {0 y: h' w1 f( d% r
                elapsed_time = nes->cpu->GetTotalCycles();
; Z* N8 Z& w) i6 b" D0 ~" q- Z        }
8 t+ L$ A/ o; G, e' r6 s+ }$ D% P. M: f        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 m- c8 U2 ~  n/ W1 s                elapsed_time = nes->cpu->GetTotalCycles();+ i" v( L4 i7 s6 H" h) y4 F3 w% a
        }
* l) J' D9 H! y; w, f" T; t#else& B# a( k2 K5 C2 y% p
        elapsed_time = nes->cpu->GetTotalCycles();
$ i3 R  r+ r; w1 ^7 V+ p; f4 r, ]#endif9 a1 K0 i: A+ I% ~5 Z
}
% l4 [. _- N7 s; N6 [
% d( t% \* m6 _8 q/ e4 [6 E// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  H. M. O# |- C% P0 v# P7 T8 c7 L
INT        APU::GetChannelFrequency( INT no )
- R, d; I3 x: L" R{  g9 P. G5 ~5 P& h4 C- M# R: {
        if( !m_bMute[0] )
: u3 D/ r) m. `; L; A- ~( g0 p                return        0;
( t) h0 O& H) H7 K( |+ [$ v/ N% N: f# k. @: q# S
        // Internal1 r$ Z7 R! K  X6 U0 p- X3 u& a* W
        if( no < 5 ) {
, w6 q$ L! b! K6 q                return        m_bMute[no+1]?internal.GetFreq( no ):0;$ l3 O/ s% n7 r' [5 e9 k
        }
+ }9 a' O/ V4 W4 U8 |) i( F% ~        // VRC6* ~4 m5 c/ [2 V# l; ]
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
5 v: J4 Y  z! }# {8 y8 l9 ~                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& v) C2 e3 k8 f$ D# D/ o7 r        }: k- U/ ?5 l6 M
        // FDS3 ]& |; E9 z! G0 `- |1 a9 n
        if( (exsound_select & 0x04) && no == 0x300 ) {
$ N. E* ?. V1 q' ]$ o+ v5 }                return        m_bMute[6]?fds.GetFreq( 0 ):0;
( }7 Z0 i2 E/ A* }; H        }
% m- o0 M8 V1 w; v3 {' z        // MMC5
- p7 _' h; {4 G1 k1 E        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {7 X9 a' R/ Q$ D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;$ s$ X0 R) R# F7 T1 z% ~
        }
* N( G: |5 `7 G        // N1060 e" c0 B; }$ }% Q- a& p; f
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
( U6 X5 U  F" T0 C9 N                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
9 l& `# ~' h, W& a/ w* N+ s        }
8 \4 O6 Y9 W( }) ]        // FME7
% r- p" Q& G0 b* Q# t9 R        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {$ c/ W' z$ D7 @: R# v' s
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
7 I0 a) J% a1 U% [/ @+ N6 W        }3 h! ?# s7 M+ ]1 @) n! j
        // VRC7
  d4 K( N' i9 O* N# v        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: G; h9 H7 X, W2 ^' p' x, W
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 p' Q. }/ b( R5 g6 G# j# n! t        }) v" Z, [3 Q0 H- s2 _
        return        0;- o3 O* r; X6 U* X6 j" w
}3 R- Y. \2 ^; j, O' l  p7 t
2 Y; @5 I2 T9 W# Q
// State Save/Load7 C! K* o( b  Y! l2 s/ v
void        APU::SaveState( LPBYTE p )
* ^8 A* m( B! s( }/ Y{
2 C8 w1 H; ]- x; k& D+ d# L- n- e#ifdef        _DEBUG
* u7 R" \4 V" x4 q! HLPBYTE        pold = p;
% ?; f. K! X% l#endif
6 \2 r$ y  w$ }; P: c8 h" R% U' B& I* p
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* @, G) a2 G1 ]        QueueFlush();
, u! l# Z: e! D7 @5 M
% d5 _7 x1 I. H- r/ N        internal.SaveState( p );" E& ~; `. G/ X/ L8 J5 x- a/ D
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 {" ]/ f: A- x: k; i
4 s: v: R6 J* g: T) U
        // VRC6& a+ G- r# A7 K4 D- e' z! }2 P- l
        if( exsound_select & 0x01 ) {. j  h. L/ L, T! h& C
                vrc6.SaveState( p );" t) _7 b% M! g/ K0 |' ?% R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( P, ]3 O+ j5 q' ~8 ]1 J6 a        }) T. d/ c* l5 Z) G) X
        // VRC7 (not support)
9 F8 V0 H# K! s, V( H        if( exsound_select & 0x02 ) {9 E7 v3 l- }) J3 {* I8 l
                vrc7.SaveState( p );3 w8 P4 `7 ]6 p8 s" k
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- v( O4 A' G% o/ y  I+ G  ~
        }
2 K$ u) E; D. \8 o6 M        // FDS
! V. F1 t% G5 X* h: j. O        if( exsound_select & 0x04 ) {9 ~; b4 @9 ^' E
                fds.SaveState( p );' v2 |0 l) A0 ^
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ \0 ^4 @1 T+ f
        }
( @8 A9 L. R' R" T  r# C# `        // MMC5% f- _9 S! T- U! h
        if( exsound_select & 0x08 ) {3 z' S" E- J3 K
                mmc5.SaveState( p );
7 z- P0 b0 |" C0 Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: B  N% F) T0 |/ y' w4 U
        }1 R) P: D- Z  _6 ~0 ?
        // N1067 M5 m& s% z* Z& J- `
        if( exsound_select & 0x10 ) {
5 |+ F: E5 p; s2 p% J5 ]* s                n106.SaveState( p );3 p% S- X4 ?, ^* W0 u1 n: e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 ?. G. r9 x2 E; ]2 F! H        }
% ^7 u  c. U( P0 v% I( s. i        // FME7
" F% |2 ?$ i+ }$ F        if( exsound_select & 0x20 ) {) Q! b& |1 P4 J7 u, ?" _  E
                fme7.SaveState( p );' z" C. w( w7 b
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding8 |6 n- A" h0 L5 M
        }
' p) G$ f6 A' `3 `+ |. I  h0 J
$ V% S+ J+ ~% f: ^9 p! I#ifdef        _DEBUG
: i7 t# P: I! @3 i# i, f4 p" NDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 O& b% W4 f- t* B7 m% W! ?- V& P" A
#endif% T$ K% |6 U; u3 L3 G
}) r7 X$ H, i0 b' f2 R" o

8 J: G( }" }1 x* f" b# ]void        APU::LoadState( LPBYTE p )$ `9 U# l7 O0 J$ m# [
{  w3 U8 p6 p( R9 B  p; N5 ^
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
5 D+ S$ l% l7 r: R4 o( i; t  L        QueueClear();
; ^  \0 W1 {2 v# j* i) s) R
& |5 w& |8 S; a# ^3 u        internal.LoadState( p );1 G+ L8 v9 E% w# [- X5 P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 {$ T% h+ D' p! _9 M
3 w: q$ r- F# l0 n        // VRC6
6 [6 N3 F' H. r        if( exsound_select & 0x01 ) {/ P+ i9 @" c- A9 H8 R. }6 T
                vrc6.LoadState( p );
& x* z" S3 I# }9 [2 D9 `: l, L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding- s0 R+ U9 X; m* ^
        }
& [1 `1 {: j) m9 _/ E        // VRC7 (not support)1 u$ u- Y8 F6 L+ K3 E1 ?- _9 W1 O
        if( exsound_select & 0x02 ) {
4 m* i0 d& }9 Y# v: i6 F  ]                vrc7.LoadState( p );/ ~) n# _/ ~8 l6 e& L8 M6 P
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! Y$ C6 k3 ?# |6 H
        }
9 j8 m3 k, c+ ^0 a5 p0 A& E' s        // FDS
! a& `0 i+ ^! r. b9 a        if( exsound_select & 0x04 ) {
& i; d5 R, ^9 {$ _7 c- c/ m                fds.LoadState( p );
* \* e1 g! A3 n; m# S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* J1 G. T' S( Y  w+ s
        }
) ?/ G  v" q6 ?/ g6 q6 }& F' E        // MMC5
# H$ q4 I6 t3 m3 A0 {) q; m5 A        if( exsound_select & 0x08 ) {
- ?6 C6 w* e( G0 R; }: ~                mmc5.LoadState( p );
9 @8 }8 K1 l) c# l! s# e, i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! h) g* E8 X: f7 {  r% Z) a# _        }
" D( x4 H- x2 E6 Y' B$ X        // N1060 s! c: V/ K3 J+ Y# {4 B: \0 L' M
        if( exsound_select & 0x10 ) {
- ^7 d% s- f( O# H  z                n106.LoadState( p );: \3 Q) n7 }+ B* R8 y# T
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
) Q, X  s. T) Z3 D6 R4 v( j# `        }
) y/ O/ g* K# E3 m* C        // FME7
/ ^# \) V& `- Z5 T/ m$ q        if( exsound_select & 0x20 ) {. O( S+ k. {$ x9 ]( ]' p
                fme7.LoadState( p );6 t0 _0 s9 z# P* `+ [* Y# A: ]6 i( H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" W9 D; R' _; j6 t9 Z
        }
5 m% B8 Y- U6 L  j7 a+ V}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ V7 e8 F) N- X# [$ C可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 K: z6 f; j) ^
感激不尽~~

+ h. d8 C6 `# C% t3 O# R恩 我對模擬器不是很有研究,# b( w3 O# E! [0 v( p
雖然要了解源碼內容,可能不是很困難,1 \6 p0 {# A/ C: \0 t% C9 d3 ]
不過還是要花時間,個人目前蠻忙碌的。
2 n! P8 E) }$ h5 W& f  w7 X% a# L. T
給你一個朋友的MSN,你可以跟他討論看看,
/ D# J  Y: G: u% _4 N" j: Q% {2 |  @7 A他本身是程式設計師,也對FC模擬器很有興趣。) S/ G7 d7 k5 j2 d4 x7 a" M' ]

3 q7 {! u% ]7 i" J$ {( Z6 pMSN我就PM到你的信箱了。1 }, F1 U* a/ l$ O/ m( t; P4 f9 a: V

2 m, p/ X% a  C; u希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# f5 V- Q3 ]8 C; R+ p3 q5 l+ W' h/ K呵…… 谢过团长大人~~

5 J& n: S' C" J0 @2 N6 B/ `* q; G- t1 @
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
0 e: x* J+ A) m: M2 b+ t& F$ u团长的朋友都是神,那团长就是神的boss。

5 X7 {. M; e! Y9 ], z哈 不敢當,我只是個平凡人,
, d; W. Z- M0 ]  b' g; `3 t要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  g. _' D4 S* R, C5 L1 U
ZYH/ w- v& h6 M; S1 ?. w; D
QQ:414734306
4 m! V# ?: o# YMail:zyh-01@126.com/ {4 r- D3 e% Q' U, X
3 b/ X5 j' a( r2 o3 A
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . R# x1 U* H) B4 m9 Y9 f4 V
再次对团长大人和悠悠哥的无私帮助表示感谢~~

% R# h/ p0 I+ D% o4 O0 y" x不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-2-19 07:18 , Processed in 1.133789 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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