EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ c5 n  ~! t5 `0 a1 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
/ Y5 h9 x3 i1 J5 C7 Q' u这里有相应的模拟器源码,就当送给大侠了~~6 L: E0 e* r& x% d4 L' n9 [
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 f6 h' o7 U- c能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 V! N% e, m8 z2 P  J% ~& I楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, P. ~1 _% V8 U1 E* m
这里有相应的模拟器源码,就当送给大侠 ...

& X8 j( L: t' \1 H- [聲音部分(Audoi Process Unit = APU):% ~6 ]0 d+ O- k" L) F( }& x
.\NES\APU.cpp; B3 o, ~5 [8 K3 @. y' \" u$ S$ Q( s% r
.\NES\APU.h+ K$ }' N8 A+ M! |% z
6 F" S* b8 e3 N. v

  W8 g1 V  W6 C影像處理部份(Picture Processing Unit = PPU):
6 w" F6 A3 _/ n+ P& M( X1 Z.\NES\PPU.cpp1 F( w* ?, e5 {! k
.\NES\PPU.h; m3 ?. [6 d" _* x& o% _
0 _0 B% v9 j1 o/ F
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:( Q- a# }6 h! D% [  d8 S! ]$ B& p9 ^
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
& U# }9 r! z& ~8 ~+ y% k# N//////////////////////////////////////////////////////////////////////////5 G8 N5 x7 C) f
//                                                                      //
/ ?/ u) f' z! k& h5 n//      NES APU core                                                    //# B/ l0 d  K7 j) y
//                                                           Norix      //
( o  w! k! p; c' ]( h2 ~' k//                                               written     2002/06/27 //
1 n% ], l9 f, r4 Y3 o$ x//                                               last modify ----/--/-- //- |, N$ k" l  B8 K& ^& L) |* b
//////////////////////////////////////////////////////////////////////////+ X* J. @& F0 z" l, u8 x' d+ ~# J
#include "DebugOut.h"  n8 v  F# Y4 e# `! a: a' W
#include "App.h"
# g6 |7 W  @; J#include "Config.h"/ Q) s+ k' M6 l# }1 E& E; e1 [

. |; V! y" w6 r% K7 C: O7 K#include "nes.h"
2 B; y* l) W6 y* s- A2 r#include "mmu.h"
: a, k5 U. B+ p! g2 e& l#include "cpu.h"
+ [& z: z5 O) b( f  H: @$ n#include "ppu.h"8 B/ v  F7 H  e7 p; B
#include "rom.h"" ^$ O: j% ~: A+ c9 \3 C
#include "apu.h"! c/ _5 w2 `$ M$ n

! U' g) {: }% J9 g// Volume adjust* d4 l: B' Y0 C% I0 d0 k5 s
// Internal sounds3 H5 F0 h" C( U: P
#define        RECTANGLE_VOL        (0x0F0)
: s' c- P  R$ |- u7 a0 M7 z% w#define        TRIANGLE_VOL        (0x130)
! H- R6 d- G+ F: |+ b#define        NOISE_VOL        (0x0C0)( o' F7 W; _& u3 `# f; H
#define        DPCM_VOL        (0x0F0)  P. u) u; j+ y& i2 \# y' j, ]' W+ ?
// Extra sounds% a; R: {) l6 F: \% I% l' L1 ~
#define        VRC6_VOL        (0x0F0)8 T- [# n. [1 L* h
#define        VRC7_VOL        (0x130)
0 k6 w- g) e  w. V8 F; I#define        FDS_VOL                (0x0F0)4 R2 n- I# Y6 f
#define        MMC5_VOL        (0x0F0)
0 C( M5 E4 l0 R& v#define        N106_VOL        (0x088)
. C  O, x9 X0 K#define        FME7_VOL        (0x130)
" X1 d  d- I& ]' s2 {/ c
# }$ s* w/ `  F6 P8 {) xAPU::APU( NES* parent )% T- a6 {+ I; \! P( }3 {. e
{* ?9 _. m% l( E: E
        exsound_select = 0;
& Q, M7 C  n* j; h# Y3 P: o% m/ f( o+ B  P$ y' E
        nes = parent;
& O" K: l2 h9 H; f: G! R$ [% A        internal.SetParent( parent );9 N, `* c: |4 e/ r
7 }- R2 p/ @7 I5 D$ }
        last_data = last_diff = 0;
2 j* y3 G1 |% X! `) a) v# k4 A* M0 k$ `4 j: G, X
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( N+ i1 h, o7 r: J3 d
; c0 U/ h5 @( [4 P2 c  t
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
! @0 |3 Q0 s7 J5 R/ |" y! V        ZEROMEMORY( &queue, sizeof(queue) );
1 w1 `+ B% A/ w7 a: ], J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) H% Q# M( X& }# D! L( I1 S5 u  ^( S* V4 b5 O. {$ [
        for( INT i = 0; i < 16; i++ ) {
9 o* s$ g* T$ p9 q* G0 l8 z                m_bMute = TRUE;0 V( M) c9 k5 g6 V& s" t2 T( D( u
        }
7 s% i, R9 [) V+ Y2 m2 i}0 P" _2 x+ g* S8 z$ u9 Q

' y- S2 Q9 s' _& L/ C. vAPU::~APU()2 k' |+ X, O6 V
{
3 `4 L" I) X3 H1 _: N+ ?; e# Y2 V( w}
% n* a8 H+ z6 K- b& j7 P' e+ o/ c4 F' l; u" R% O- h8 e4 B
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )% a( ~( v2 k. }3 C: y% E
{
! T0 g0 p3 `+ r* u2 h- y1 {        queue.data[queue.wrptr].time = writetime;
2 u% I( C. I5 M0 o7 f7 s0 P        queue.data[queue.wrptr].addr = addr;
+ w' H; k. D1 R% U$ ?        queue.data[queue.wrptr].data = data;( G) f# J" q2 k3 l$ l4 l
        queue.wrptr++;
' K# l0 B1 x: U        queue.wrptr&=QUEUE_LENGTH-1;
- L/ _2 b$ Z4 P- `, }6 ~9 n- b- f        if( queue.wrptr == queue.rdptr ) {; |# {3 }: k' d# I! c* ^
                DEBUGOUT( "queue overflow.\n" );
! }1 r2 e& X7 f# a) @& J        }9 |$ _( \+ D  e! g
}
: [, r+ E. {9 ~& Y& j; N  E0 {/ O
, i$ W. F* R' wBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* r0 `9 j/ }) u% N# }5 h  h& i; @{
! m) G4 O6 Y9 a! Q9 g; F# E; y# n0 a        if( queue.wrptr == queue.rdptr ) {3 O( A5 _, O# @& C
                return        FALSE;/ [4 u) ?  Q9 w  ^5 w
        }
9 @1 C0 ~( H; A- u2 o        if( queue.data[queue.rdptr].time <= writetime ) {
8 @, D  R( p' f  G9 \' M6 [1 X* e                ret = queue.data[queue.rdptr];$ v: m- E4 h; |% _2 c1 `
                queue.rdptr++;
. J3 M/ q( B: c$ h                queue.rdptr&=QUEUE_LENGTH-1;6 g5 ~7 f, R" g* O- w
                return        TRUE;
( r9 ]& m3 D5 ]5 D, o1 W        }
7 g' t! ^6 ]! d7 ~& i        return        FALSE;
1 Z- X! x! }' M& v7 j* R  j7 H}
' k4 y# Y# h- S; ?9 Z3 g7 B7 \9 x# d2 d, V0 ?5 I
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
, B# f- `3 {# ~- `$ S+ j" [. q) _3 K{" k6 \: d7 N# `, l) ]7 F  A
        exqueue.data[exqueue.wrptr].time = writetime;
" p. p- }0 |. \& f/ }$ j) I        exqueue.data[exqueue.wrptr].addr = addr;* Z! c8 \# C: q0 H( d
        exqueue.data[exqueue.wrptr].data = data;
" P. F2 X' u$ E  h/ J4 ~        exqueue.wrptr++;
6 |( `0 X1 X9 U' i$ M6 W# W        exqueue.wrptr&=QUEUE_LENGTH-1;
1 i8 ~2 S& E9 ?# Z6 j2 ^4 T        if( exqueue.wrptr == exqueue.rdptr ) {3 A- `' _1 J: v" \% \
                DEBUGOUT( "exqueue overflow.\n" );
/ _6 x5 d/ A; A- B; w) V) V        }$ B7 \3 A! x! h- l+ d9 @
}
% l8 R4 |+ r0 k5 ?/ T# W4 H
- B0 n% _( Y% z0 v/ e  J# r$ B! w. WBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ): v7 [8 T, j- k7 C0 R
{
3 e7 L' ~7 D  l        if( exqueue.wrptr == exqueue.rdptr ) {
8 C0 l& ]" Q7 j6 p  M2 p                return        FALSE;8 D; O8 w, ~: c& r
        }, Q' y0 g: d  s5 I* {. B
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
" d' Z2 j, s+ x+ C                ret = exqueue.data[exqueue.rdptr];
8 I% a# |  A5 k2 B& I& B) d                exqueue.rdptr++;$ X! Y' H% m: b0 A
                exqueue.rdptr&=QUEUE_LENGTH-1;
( u& [; `( e: f5 s. @, o/ m                return        TRUE;
$ c# y/ n9 X0 i; }        }8 b, q$ l6 _  i; M
        return        FALSE;! h6 C: `' J. x7 _
}
- e+ Q& q% Q9 O  E2 |2 Y) j0 [) z( l6 e- i9 R; m# b3 {, V
void        APU::QueueClear()
) t2 c4 L  Q7 i& z{6 s% T+ O7 R5 g, d7 ?! z. y' ]
        ZEROMEMORY( &queue, sizeof(queue) );$ g2 O* P$ t$ X6 m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, ~+ x' W( L: i/ B. [7 }
}
- D9 [2 w+ o% u' l3 e) k
  K( k& G  R6 m3 t* z6 k- Bvoid        APU::QueueFlush()5 Z8 J. x0 j' t% b3 X' c0 r% l
{
$ k9 ~1 j. t& x& L        while( queue.wrptr != queue.rdptr ) {
4 Y3 ~: [  ~! [! l# v; Y. [                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
3 M6 Q0 i. r. I: _) m: f+ j                queue.rdptr++;: E0 N% l) \( O- I
                queue.rdptr&=QUEUE_LENGTH-1;
& Z" l7 a+ W7 p; M( h        }
$ x. w1 l/ E( ~
( h; B* H8 C# ]  q. E* |4 ^0 Y- U" W        while( exqueue.wrptr != exqueue.rdptr ) {( |- N( a. d; L0 O% {
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );# Q0 r* q* q3 O* `6 G
                exqueue.rdptr++;
; y) I! ~" l! Q/ F' C& C, H0 d                exqueue.rdptr&=QUEUE_LENGTH-1;  ~4 [3 O# r" B- t; p" M: S9 S
        }
% O3 L; W: i& n9 J8 b" a}) D: T; O2 x1 i. V3 U

5 i5 S* b3 U2 X% d5 _7 F2 Kvoid        APU::SoundSetup()2 {  P4 g) X: d8 ?4 i* t. _
{
$ ?$ j9 a: ]1 n. e& E5 x        FLOAT        fClock = nes->nescfg->CpuClock;6 C, E5 l2 o5 ^3 `; P
        INT        nRate = (INT)Config.sound.nRate;
5 R* j6 a5 z* c/ d0 M& k3 N        internal.Setup( fClock, nRate );3 ^& ~1 U4 V1 v: R; V
        vrc6.Setup( fClock, nRate );
  v3 Y/ W$ u' J1 t0 x        vrc7.Setup( fClock, nRate );
+ ?0 i4 f- {: Y  L$ m$ C& b% y        mmc5.Setup( fClock, nRate );* s( |8 {4 E# D( [3 {: P- k( d5 B
        fds.Setup ( fClock, nRate );1 K3 l9 a9 W/ \8 I1 V
        n106.Setup( fClock, nRate );0 K: a/ I: ?- d1 P* `7 X$ P
        fme7.Setup( fClock, nRate );4 H' Z6 F- M( _9 G& F
}( X9 v# l$ i7 p

! {. `" W5 c  p" Q. ~void        APU::Reset()
% ~% @) V) D( q) U) f{; _& E* d% E% L; r3 r3 c
        ZEROMEMORY( &queue, sizeof(queue) );
8 q9 @0 {' a1 F; n        ZEROMEMORY( &exqueue, sizeof(exqueue) );- ?; L* s$ P6 Y& W% p

9 B0 A# w, n9 Q& [& F        elapsed_time = 0;( h) ~8 @) ^1 M' r

: H2 _- ^8 i8 _3 P        FLOAT        fClock = nes->nescfg->CpuClock;# v$ ]# `7 U7 H2 l* t- P
        INT        nRate = (INT)Config.sound.nRate;
* z& F0 i2 F% k# G0 V' D% K& L        internal.Reset( fClock, nRate );; A. h" k/ g7 z* [7 v9 ~' A0 ]
        vrc6.Reset( fClock, nRate );/ d/ b$ I2 [( [+ t4 j" C
        vrc7.Reset( fClock, nRate );" @3 }1 @8 E# h, f
        mmc5.Reset( fClock, nRate );
/ o" E' M, O5 `/ v' j, a        fds.Reset ( fClock, nRate );; |7 p1 R  ]& l
        n106.Reset( fClock, nRate );/ S. N% ~1 i& ^4 T
        fme7.Reset( fClock, nRate );
: _. W/ G. w; @1 ^  Z1 I7 f
& X) T% I9 s! h# L        SoundSetup();, \  Z- v2 T( ~: @; ~, I
}/ ^; m  y2 n2 a; S' g$ I$ Q+ X2 H

( e$ J) O/ L& C# J( o9 e7 Qvoid        APU::SelectExSound( BYTE data )
* n2 ]& m) \* c4 u* ]2 N{! }7 L% Q  @' \8 j6 O/ _, L
        exsound_select = data;
" c% r; o, x9 u& m}
  {& O- s( D2 j: E1 F. x: J5 ]: ?
, I& h! m: \1 _( oBYTE        APU::Read( WORD addr )* }" w8 ?) e% k+ L" T0 A9 l& r
{
% a+ p8 d& y* l$ p5 p1 q$ }        return        internal.SyncRead( addr );
# }# x& t  k3 z( N( c. G}
: r8 T7 Z" k; Y3 T1 ]3 p5 u+ P6 U$ q1 |9 u6 e/ Y: x
void        APU::Write( WORD addr, BYTE data )
0 M$ {3 Q% a; k( V+ z1 F{
8 V; }# H2 B+ l        // $4018偼VirtuaNES屌桳億乕僩6 @: h- m& c+ v' L3 N+ ?
        if( addr >= 0x4000 && addr <= 0x401F ) {6 D( Z' l# l4 a, D; F4 b
                internal.SyncWrite( addr, data );( c2 N+ z! n# p  m/ N
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
+ I0 k# q" A9 y4 q# o+ k        }6 D3 F: G! Y) O3 d/ g
}+ Z5 \# l/ n; {2 P2 o- O
, z" @" i% f2 g9 \3 V8 Q7 }
BYTE        APU::ExRead( WORD addr )
4 ^3 [0 `3 K6 K7 E) n$ Y# I: A{& w8 m0 Q9 D6 l  F: {5 P# y0 J
BYTE        data = 0;. A/ h' B. D4 A  r  Q6 z

0 f' q3 x) T+ o( N        if( exsound_select & 0x10 ) {
# v' i& @0 _9 U2 {                if( addr == 0x4800 ) {* ^- a) |( x2 ~# p+ c8 P
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! D& ^7 i7 v" U" |
                }
" B: {; P  N+ j: J- E        }
, p3 a1 z" m5 \6 Y3 C0 U" Z5 M        if( exsound_select & 0x04 ) {
7 b3 O$ d3 n  E$ v, `( l9 R                if( addr >= 0x4040 && addr < 0x4100 ) {' P, F& G0 Z- N, j; q5 L
                        data = fds.SyncRead( addr );! K- x# d; B! i& a& @1 e8 @' a
                }; C1 ?4 ]' g2 C' R0 a5 J/ P, d: r$ r
        }
2 y9 @: S; w! y; e; U3 ~        if( exsound_select & 0x08 ) {
2 }2 G* E+ v7 h; x8 x                if( addr >= 0x5000 && addr <= 0x5015 ) {5 ?/ u- y7 \1 h3 Z, v& i
                        data = mmc5.SyncRead( addr );. N1 `" `& B5 D5 t. J) ~3 D
                }
/ w# y' v& @, B8 I; J        }
; T" w3 k0 F7 f7 W# Q8 t' v6 z$ \* o  f1 V- h
        return        data;
* y5 v! I3 L: H% @}
5 e9 W: Z. A9 K7 `+ j* V4 d' e$ F9 Q4 \, P$ z/ C! x, V0 z
void        APU::ExWrite( WORD addr, BYTE data )
, q0 [6 g  C1 `* Y! `) O  }{6 S; F) `1 Y$ `. K/ R7 r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );8 {( c! e: b$ n; K1 s
  W9 J7 j3 e. R- _. P% L, o
        if( exsound_select & 0x04 ) {
4 w, q& N$ }( i6 R+ y# u/ L                if( addr >= 0x4040 && addr < 0x4100 ) {) I+ r: M  J. }( I' F6 S
                        fds.SyncWrite( addr, data );6 \+ P9 l9 w0 F& O
                }
6 \) Q9 o5 N+ l) z        }. H$ p! E' i- M- q

- @8 E  f5 t2 O' _2 I! t        if( exsound_select & 0x08 ) {
. s7 ~/ d; Z. ~/ P. u$ d                if( addr >= 0x5000 && addr <= 0x5015 ) {) |# V- i! K/ a* g
                        mmc5.SyncWrite( addr, data );, d  U, G) Q1 V7 k
                }. ]3 E! n4 J" Y% L, f4 T
        }" ^+ `4 I. ~' F  g& W/ Z% `
}
& j8 T2 Q0 s5 c9 I2 Z6 D7 g6 ]' W/ u! G+ H" O, s1 [
void        APU::Sync()
+ P# L  v* E8 ~. |' [9 Z$ b3 ]{
+ O3 d  Y$ N! U" D" v. z}
# Z' l" |+ L. s3 \+ o: P4 c
8 k! C7 w" R* h: pvoid        APU::SyncDPCM( INT cycles )
) `- Z% r. n" c, [& d# j{
1 ?4 |0 {. {2 Y! j( ]. V8 I        internal.Sync( cycles );' D7 _" R1 w; E! b& h, \3 G: @
0 P+ n% c" p1 t" N" x3 r" Q8 S6 v
        if( exsound_select & 0x04 ) {2 x- x7 |- R* D/ n6 [
                fds.Sync( cycles );
' L% F% p  u! H        }
+ }3 j0 c5 i/ s  K  T  W        if( exsound_select & 0x08 ) {
; U  {; _$ K5 Y' \                mmc5.Sync( cycles );$ T+ K  g! R, ~: ?8 I
        }# a" p! Q- w) ?) J4 w! {  M; @
}
! R6 `0 I" b' ^) `
: g( N: e/ E5 j8 i+ M) Y  ?4 ~3 y. mvoid        APU::WriteProcess( WORD addr, BYTE data )' [2 e6 E+ y1 I6 k
{$ V2 }4 ]- X8 Z/ k6 a
        // $4018偼VirtuaNES屌桳億乕僩' `4 y& \0 M9 a" [' \7 S1 U
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 ]1 S% D2 X& J5 A8 G                internal.Write( addr, data );
! D3 U- b; S. j) m* n) T        }6 V( _+ f. Q; C" t; v
}
$ C7 h+ D5 g$ J+ W  ^: L% |7 @# K: U3 n  I+ J$ f% H' w7 {
void        APU::WriteExProcess( WORD addr, BYTE data )2 X# [* {- j8 x! }+ a$ x: x6 n
{
" _! K# m/ ?7 v5 y& J$ U  p        if( exsound_select & 0x01 ) {
  a% g, f, R/ c8 o1 g                vrc6.Write( addr, data );% S+ e7 j6 {; d9 e0 o& t
        }
5 @2 @6 ]3 u5 {# U9 b1 O& Q9 \        if( exsound_select & 0x02 ) {# H: C: N: \9 C2 `) v+ {
                vrc7.Write( addr, data );
; E2 X: x4 M- k) I, w$ p3 ]" [        }* }3 q4 h  j7 Z: ?8 g# z
        if( exsound_select & 0x04 ) {7 _, a) A2 B  u
                fds.Write( addr, data );- e0 @9 w. k  Z( X
        }4 o# e& R9 ?2 Z* c* e
        if( exsound_select & 0x08 ) {
: T* H- p7 q$ t" U6 @& d& s3 @                mmc5.Write( addr, data );
! T9 X2 L" e- |: s& @6 |        }
$ M( V5 p! W& r! r5 M3 v! t        if( exsound_select & 0x10 ) {! Q& S! v+ S* c$ k- b+ Q. q- @
                if( addr == 0x0000 ) {! x+ Y0 a& c7 @7 p4 A  ~
                        BYTE        dummy = n106.Read( addr );9 Y  f; b! h9 {" {" c: K/ R( Q
                } else {. z  j) k% z+ s/ b
                        n106.Write( addr, data );
0 p# }" k- t* e: n                }
+ s7 i' a9 z. R5 T5 L        }
0 H' `* X$ Q% O* |3 m; c# y        if( exsound_select & 0x20 ) {
& J( u3 _) l) r  I6 B: \2 v                fme7.Write( addr, data );; M; S, L% L3 A$ O: U( s
        }: j4 K- K9 ]" A; C
}
. C8 ^( x8 r) f
- S: t3 v$ \. O, F% x" v" c' Zvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 P: N4 U6 x; b
{/ ]+ Q' o/ S  [# {1 y- T. g! E; N
INT        nBits = Config.sound.nBits;
& Q- X% ^1 D+ r  s; J/ IDWORD        dwLength = dwSize / (nBits/8);
0 U3 J& P2 a0 X, M* p9 @INT        output;
3 ~& w  H6 c5 B& ]! P) fQUEUEDATA q;' p* Y2 Q3 K1 H+ J3 Z7 h/ R
DWORD        writetime;
" _8 }9 J0 }7 ^  P. ?
, X! ]4 h( {0 J& W9 D3 A0 }LPSHORT        pSoundBuf = m_SoundBuffer;; T5 V7 {& x, S, l  i' [, T
INT        nCcount = 0;
0 v7 x7 n# n, s1 h2 q
. a" V/ }1 ^% c% _) b; MINT        nFilterType = Config.sound.nFilterType;
. J- I, U9 f/ h1 |8 b3 V3 K
, Y5 s$ _, v9 m        if( !Config.sound.bEnable ) {
/ V5 A* l: x5 Z6 v                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
; J2 _  v; u+ s% O* S: g% A. x                return;
/ R$ i3 w2 Y  N6 \) M: k! q        }1 G. e5 T& y/ _0 e+ [5 o
. O& @3 u- G  e  @: ?" A
        // Volume setup/ w# M3 D/ O& }" ?7 z* I
        //  0:Master
$ _1 G1 ^* c% Z1 i" a1 Z8 u3 S        //  1:Rectangle 1$ i! ?$ W# d$ U% t
        //  2:Rectangle 2
+ |4 X3 `& \* e" k        //  3:Triangle$ h) G4 A2 Z" b
        //  4:Noise( `4 `* r8 x7 O' q
        //  5:DPCM
; u$ s1 ]- ~. u2 s+ A# H        //  6:VRC6: s/ M6 [, c' Y& Y% j2 c
        //  7:VRC73 _$ G0 r7 |$ z; A8 U* k0 P3 J
        //  8:FDS
$ ^+ J5 Y1 _% z" ^, T- U% `% _3 ]/ A8 |        //  9:MMC5+ h$ E! }' c7 `/ m0 _
        // 10:N106
( F: \: V+ \, T* P9 C# M  f        // 11:FME7
+ B8 T1 x+ K5 K8 k% D: B- |, X: n6 l% B        INT        vol[24];
8 s2 q) r, e, X        BOOL*        bMute = m_bMute;
6 J, i; c) ^+ y% d5 S) a" M/ F        SHORT*        nVolume = Config.sound.nVolume;
- ]" l% {3 e, [$ X; m
. |: x9 `5 H% q* m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;' N' V. A, V2 x2 R- d# S- _

9 C- T: J% ]7 T5 v' x3 x        // Internal
1 \+ t7 C( {4 e. k        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 [6 g: n5 P  j3 x2 R1 w        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 c8 l& _) w" F+ i. _" @- n0 ~1 [        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 u5 B, T# a1 w: Q
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;( D/ _+ z2 \9 x; }6 o  H6 B  m
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ }# U3 s" K' J
7 Z1 @- k- |- p/ P! L* e        // VRC65 a  `6 J% v+ k( D. x9 K7 X1 r
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 C6 h4 y, j" y9 m
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ U8 e, }" C$ f5 @2 o) E        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ N# r/ i; U! ]5 ]  h- d" ?
- T3 Z3 {- }6 R* K; W2 V( g; J        // VRC7
. Z  K" `! z- d4 h) `7 |' K9 j+ x1 s        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;3 ~7 [# Z( N0 N5 }) R. `3 H9 \* Z2 i
9 S/ h: z3 u+ R$ b/ T; r
        // FDS
- ]4 W( E* c; s2 ]7 f6 W        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;* v, f9 m: p; u+ F3 k" W* L8 w; k5 Z

; f0 g) I+ R% I0 @* b        // MMC53 f  x& Y9 H1 [6 N' O6 S
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" W3 J) F% q3 p$ ?        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) a$ L- d+ ~* }$ ^1 \0 `/ s
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ G: L2 T8 |/ N  Q& C  g5 u
4 O; Z- b, D$ ]9 r3 p% [+ s& K
        // N106% X1 h; X$ v5 s4 D3 D0 {7 u& L' o( z
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) c  c0 ~2 j' o  A& r+ g6 A        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ t6 T. W% @8 W, H+ a7 J9 H0 d        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 i0 s9 S: y  j        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" J- ^9 O' |5 |) V
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& e$ c0 k; d) m/ \% I! Z1 Y        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 ]$ w) ?1 z! I" M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  ~' _5 p& b# M% c! C
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ~6 e1 k; C# ~9 \2 Z
  D% c7 O6 Y( m# T5 k0 r        // FME7
$ g9 m% q! p' i+ P2 p; z; z        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 J0 |2 @, C- `3 k
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 ^: b  U0 y& V9 ]        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# x7 L. d& Y0 d; E6 {) Z; G8 U* E) R' l* [) M
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& j: O5 j* P4 H/ V        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;- Q; p0 `7 h$ X: Z% i" M- \7 W

, D# g6 D8 t; j; O9 h8 J        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
& n9 f* f  H% `- x# G        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- M8 j& @9 {! {8 j3 ^3 d/ I8 ]
                QueueFlush();3 i: e5 L4 o; }" |4 W
        }
0 ]- l3 w  [( P% p  \  P; |" L# M
4 ^1 F! v2 i, _& i4 U        while( dwLength-- ) {6 m1 B% `' C3 ]2 X+ \
                writetime = (DWORD)elapsed_time;/ l3 `9 ?3 _" G. I2 R' W2 n" S( O7 q/ m

1 d# H! b& N; O8 u3 Q; s. p7 E                while( GetQueue( writetime, q ) ) {  E$ T" e. p' d+ h+ @8 A) L$ [- d* v
                        WriteProcess( q.addr, q.data );
9 Y# r( G3 S' X) D" [- Q" p7 }                }/ M" ?$ s. D  B% @  ^

% K: }3 T4 V% @, `                while( GetExQueue( writetime, q ) ) {
! I% ?1 ]8 n! _                        WriteExProcess( q.addr, q.data );; A* x' y6 K1 S" g. I8 j/ N+ d: f
                }* w: U; v8 J7 l7 q# P$ ?
9 l6 N$ ?8 `) A+ g* U) B
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
) x! ~* Z5 }  S7 S1 l' A                output = 0;* r( Q% S( E9 r) H& t* S+ q
                output += internal.Process( 0 )*vol[0];( w  V0 ~# r! t0 ]; ^
                output += internal.Process( 1 )*vol[1];  [9 s- u* }" b) R( F/ V8 i
                output += internal.Process( 2 )*vol[2];" Z9 g# J  f6 q; F" U
                output += internal.Process( 3 )*vol[3];, }: c% k3 r  ^
                output += internal.Process( 4 )*vol[4];2 g) N- I  U0 i

0 b% n: J7 z$ l- h                if( exsound_select & 0x01 ) {9 L9 n, m% F/ d
                        output += vrc6.Process( 0 )*vol[5];. c/ b' P: S3 C! u0 Z2 g# m
                        output += vrc6.Process( 1 )*vol[6];
7 K& v" b# e' z! x                        output += vrc6.Process( 2 )*vol[7];
7 _5 W  L/ A4 O8 V* d6 F$ V+ Y                }& g& a! h. U7 i2 [9 E- T
                if( exsound_select & 0x02 ) {
1 ], K3 B3 u0 o, ^                        output += vrc7.Process( 0 )*vol[8];. R/ U0 ?$ X% y) U- l) R% {' h% w' `
                }
" p( X7 u2 k" x: T' Y                if( exsound_select & 0x04 ) {6 n: q5 Y7 E& ^# ^% g. N
                        output += fds.Process( 0 )*vol[9];
; X/ ~8 K1 Z& e3 v8 A                }  G0 v8 p5 [! e! K* ?
                if( exsound_select & 0x08 ) {
3 o3 \0 @. G# w0 r5 R7 A6 k                        output += mmc5.Process( 0 )*vol[10];
. k/ h6 p+ s; }$ ~' j8 A1 s4 k  d                        output += mmc5.Process( 1 )*vol[11];/ h1 |" L4 |# f( B8 [- x
                        output += mmc5.Process( 2 )*vol[12];; z- i* Q3 V3 ~+ V6 l* k
                }* E# Z- J7 t- C* B& j% R
                if( exsound_select & 0x10 ) {
8 w' m; I, R2 g- q1 a1 i                        output += n106.Process( 0 )*vol[13];
  R8 y+ z9 @2 u1 M                        output += n106.Process( 1 )*vol[14];
5 w3 W  k3 e: F3 |) K                        output += n106.Process( 2 )*vol[15];
; p+ [& H' o- t# M& C1 F                        output += n106.Process( 3 )*vol[16];
& v9 X' W: [7 N; j- O$ K3 A                        output += n106.Process( 4 )*vol[17];! E) A" m4 i8 N0 k, G
                        output += n106.Process( 5 )*vol[18];
& {, O* c& i/ q$ M                        output += n106.Process( 6 )*vol[19];
! N4 R- L+ t, A+ X2 M                        output += n106.Process( 7 )*vol[20];
' R% n0 m( {; j                }
. c3 E- V. r# d) Q7 l7 F                if( exsound_select & 0x20 ) {9 ~# O% m8 t% i5 i
                        fme7.Process( 3 );        // Envelope & Noise* S* r' M0 |7 r# [& _
                        output += fme7.Process( 0 )*vol[21];: s3 u. C+ t% S& p+ _% u
                        output += fme7.Process( 1 )*vol[22];8 V' p) Z3 m, M% O& @# R* d- u
                        output += fme7.Process( 2 )*vol[23];
" Y/ F7 ]4 i* m2 ~                }
5 q* d& X. i6 _  s( O! X1 q7 a% K, s+ l8 _) R. O5 D
                output >>= 8;( g0 a. [5 l# b7 \* u9 X$ j! p
# V5 D9 p: g3 H, \8 [9 Q9 t
                if( nFilterType == 1 ) {
( P: E+ }* O  t4 y2 u                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
" Z+ k  J4 Q7 q                        output = (lowpass_filter[0]+output)/2;: F" h. Z' d4 q
                        lowpass_filter[0] = output;
+ U" i1 |+ a  C                } else if( nFilterType == 2 ) {
+ ~  [8 a3 j( c1 Z                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
& F) ~" D  o0 |: t1 z" ?6 |                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 S6 W' X; e5 C1 [& W
                        lowpass_filter[1] = lowpass_filter[0];& f# T7 m9 _8 e
                        lowpass_filter[0] = output;; ?( g2 E9 c! z7 k3 `% V
                } else if( nFilterType == 3 ) {
' ?2 }1 n; G7 s, J                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)* d- h* [8 F$ I* ]9 A, w
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 Y# Q( M& a3 h( H
                        lowpass_filter[2] = lowpass_filter[1];
9 X. z- \- v, ]& s                        lowpass_filter[1] = lowpass_filter[0];
* H' V% \6 p0 }, t- P$ _                        lowpass_filter[0] = output;5 R6 o1 E# w& E# x. `( }
                } else if( nFilterType == 4 ) {! K4 E* ]1 Z, B% s
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)" {; I# P; I# Q  w8 P
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
# j+ b; m3 n+ M% v; l                        lowpass_filter[1] = lowpass_filter[0];
/ ]4 p9 R7 M! f# t                        lowpass_filter[0] = output;
. r1 o  z$ J- Z" X9 A" m/ s8 }                }
9 k5 m2 d- @5 [; `9 A# M+ D( w4 k5 {2 y. K' S: w
#if        0
/ _' \/ ^, }) M. c0 l                // DC惉暘偺僇僢僩/ r3 |  P5 w3 w1 l& a1 D! @, K
                {; Z( j2 J! y1 H- f( z5 S5 y& o
                static double ave = 0.0, max=0.0, min=0.0;
- J# Q) I4 a# U1 W! S/ L) C                double delta;! ?2 s, M# [: g% Y
                delta = (max-min)/32768.0;# d6 C6 ?- `1 g! _5 c& A' ~/ A
                max -= delta;
: E- G) d  y- o9 [3 S! U: e                min += delta;8 }3 O' i3 l' ^
                if( output > max ) max = output;/ n5 l% P+ w4 z) ^( f
                if( output < min ) min = output;& d' A6 C% i- Q3 r- N+ Y
                ave -= ave/1024.0;
# L+ l2 u1 q9 x7 @                ave += (max+min)/2048.0;
$ }  N; W" @  T9 z5 Z                output -= (INT)ave;/ \' t+ a$ q) t, `
                }3 w4 J. N0 r5 m1 i0 R3 ]
#endif# ^, p: q6 s( b+ }
#if        10 {, e! x( _5 H5 Q6 I' U
                // DC惉暘偺僇僢僩(HPF TEST)& `8 }' z. a( N: s& b0 ?0 E( B
                {3 L* }- j+ O6 [" O
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);/ k4 P( O" |: r) w7 x$ l+ P2 T4 d( [
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) G* E9 }$ R/ ~5 z' V# g                double        cutoff = cutofftemp/(double)Config.sound.nRate;
; G/ S: d: i2 h; Z8 Y2 }                static        double        tmp = 0.0;
9 U& H& o9 Q1 ?                double        in, out;
! W7 u+ B+ C4 s" ^
4 g; ~0 v9 p3 a5 q  ]: L2 a, C" B                in = (double)output;
  n' f) u5 a8 H. `# r                out = (in - tmp);. x* ~+ G8 g5 k: U: O! N& M, p8 A$ I6 ^3 q
                tmp = tmp + cutoff * out;
5 b% w* m# r9 y8 L1 [0 K  K
9 J! G/ O% M( ?( _9 d5 a5 t1 H  ~                output = (INT)out;
4 l* {! Q7 D' X                }& @( U; ]+ J" l( t) C# ^9 j
#endif3 H$ R* h. D) ~) o4 S3 x
#if        0/ h+ J  s; R, z( z* H0 V* L
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)0 X( Y: q1 r- [, r1 g( s. a
                {0 \; @; x1 T4 T  Q  t
                INT        diff = abs(output-last_data);
1 ?  C$ e% H5 G& s                if( diff > 0x4000 ) {7 L- g" D+ z  t2 x
                        output /= 4;
5 k* D5 w2 Z2 Q5 o& W5 s4 [                } else
* H$ Q( G1 [/ n                if( diff > 0x3000 ) {
4 K" b+ `* K7 U" n! K                        output /= 3;
, ^/ o/ o! b' x0 q0 o! f+ B# r. e                } else
, Z' n5 d' l5 {8 E                if( diff > 0x2000 ) {
1 H1 V: O3 l; ?& }9 L& d                        output /= 2;
+ T% D% b. [+ E, f) A: {                }% s% Z% |( y4 P% r' q: O  J9 I
                last_data = output;- L  D1 b- h4 N. b1 Z
                }- {0 u- i5 X4 j! L( @9 s! S
#endif  X/ M- o( y4 f- ~( p0 |
                // Limit% a. g' h3 H4 C( X1 N
                if( output > 0x7FFF ) {
4 T3 l7 ?  N) I7 e& h                        output = 0x7FFF;: ]  o1 D# ^2 e7 ?  \3 i9 C; V( c
                } else if( output < -0x8000 ) {
' \2 u3 V% @+ _- y* G, o. z                        output = -0x8000;
, x+ V1 x# ]4 `1 M                }( F7 _( P! d7 v. t# n, l) G  P/ G6 H: A
/ n0 R3 s* b7 c5 ]
                if( nBits != 8 ) {, F; f- o' x' t  |2 p
                        *(SHORT*)lpBuffer = (SHORT)output;- [+ x3 f. K) |0 J! ~) C2 d
                        lpBuffer += sizeof(SHORT);
' ^  ?9 ?5 [  X& E                } else {" B) U  ]( }+ ~3 _) }: H
                        *lpBuffer++ = (output>>8)^0x80;
9 J; v& T  \' F- @4 M                }  F/ @: r2 h+ E$ ~, [3 A

0 F: q- x+ k) I/ O0 ^: T, a                if( nCcount < 0x0100 )
7 D1 [% Z, |9 w; @, J0 f                        pSoundBuf[nCcount++] = (SHORT)output;+ t$ P' E- [) x4 f' w) |  l+ P4 B

8 E' c6 z- [$ X: `' j1 K5 A5 o  U//                elapsedtime += cycle_rate;
, m8 A: B! ~& @  h' {2 @3 ~$ {                elapsed_time += cycle_rate;9 l3 {2 K& e& M! L+ h5 R$ T
        }6 M, {; z+ C: k

6 l$ ]. Z7 j$ a" `3 J' ?; z) G0 _#if        1
5 ]6 d- u7 ^8 Y$ Y1 |6 w4 c        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {% [4 [% g5 ~, H9 v
                elapsed_time = nes->cpu->GetTotalCycles();) x/ V& z- ]& o. ]/ Z7 o2 b
        }" X' U* m( _  n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
8 s+ c; P: E" d& H# ~, y                elapsed_time = nes->cpu->GetTotalCycles();& o1 x, O* ~' v0 b+ N* i( s
        }& T& Q6 h; l$ g+ J
#else
$ w+ _8 N3 c1 K. {        elapsed_time = nes->cpu->GetTotalCycles();5 B2 K! p7 E/ U: D; q# ^! M/ B
#endif5 v. y" M. w5 d$ ]2 E  ]4 u
}
) \+ o. P6 k4 R/ ]
, j" [( T' k' h+ v// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
# _# S9 W- f% w3 {INT        APU::GetChannelFrequency( INT no )8 j- ]% R( |2 Y9 B2 v; Z' h
{
" v5 u# `8 d) y2 U6 V( B8 i" t' \+ {        if( !m_bMute[0] )) s9 x; g5 ?) C4 b
                return        0;
/ Y% E1 y0 a6 o: R- L
; o. Y* D/ e( z- \3 |        // Internal
, w' k4 A. z* t- {; T# E/ P4 v  v        if( no < 5 ) {# N" O: z" ~# g  U+ ^0 ~4 [; t
                return        m_bMute[no+1]?internal.GetFreq( no ):0;+ ^" g9 @/ K8 M6 t% X) S& J
        }
7 Q2 ~1 T7 k" A. Q4 @        // VRC6
0 g: ]  ?" `, ]8 @3 |9 n* D        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {1 C' s( y9 D0 u# c" f0 [
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
9 \' r& n2 P& q: }2 M/ b% A7 @        }: v$ U0 i2 m4 i8 z
        // FDS
, r  l/ w1 y$ t. B0 V8 `6 l1 v        if( (exsound_select & 0x04) && no == 0x300 ) {( |* k# |' U* o
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
2 d) p- ]8 \, K  K" B- h        }6 _1 k, E. v+ Z
        // MMC5
5 n# M# P0 d; `8 W" ^% r        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
) l. K8 M5 x# H3 P3 q6 g                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;( l' A0 M$ K; |# ^) w* w
        }
4 r6 D( b; e  O8 D, g0 S5 l! C        // N106+ H. U5 R% r% L1 w0 |7 s; c
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {/ h+ K8 S# ?; x
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
/ {& g' k# Z8 U( V: N  G7 W        }
. a8 t% p( R: D: i        // FME7
" X6 f. ]3 o( R2 r, m        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 Z2 n* M; S5 V9 {( H
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;+ P2 |! w0 N" \# K# T5 H- a
        }1 U! b' D. G" v" Q8 R9 z- A! Q
        // VRC7
6 ?6 t9 J4 U: P. k* j0 L  a        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
! Z0 Y$ }6 Q! z                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: W, w8 ?' }9 O# \! C        }
1 r$ g8 E+ m+ A7 {        return        0;
4 f- L$ _4 m) m3 q$ y. r}2 |: i! |1 w0 F2 j
& N) s$ N5 y: `/ K6 {0 m
// State Save/Load
2 }( p( r. M. K' z7 Tvoid        APU::SaveState( LPBYTE p )
. F! [+ g6 w! n- t' Z0 b{3 V4 ], N+ N) h. l8 n
#ifdef        _DEBUG6 u7 w) w5 ~( ]8 v0 u: M0 V7 b# r
LPBYTE        pold = p;
) E& y4 s0 K$ x0 r5 J: J8 X+ m#endif
- V- |) D9 d7 ?7 J  n  l: X
; K  ~2 o' X# E( u- b        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞4 w" Y3 K6 c4 Q5 \
        QueueFlush();
; g/ U- O  `+ r- ^1 Y4 Y6 P
9 {0 S8 R) U$ ]0 |+ }+ d4 u( D: r9 k        internal.SaveState( p );% i0 F  O# |5 `5 w1 h7 L, G
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 [0 c, ^( V, A' q* F( s7 t7 Z7 J* \
+ T7 V$ a$ t4 Y" C# j& Y0 ^& d        // VRC67 B2 W. v! h, W, B! x' y
        if( exsound_select & 0x01 ) {# h( e. h+ s: z4 F3 S, j
                vrc6.SaveState( p );: \9 w) g: i' y1 S# \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" d1 S' l) S8 S9 i5 F  V7 F
        }
, j, a0 y- ]& c% `' ?        // VRC7 (not support)
4 k( {$ l2 W) \        if( exsound_select & 0x02 ) {
5 ]7 M: O4 ~, a2 J                vrc7.SaveState( p );- L- r* L5 v6 t
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* }" X9 o+ X% c8 Y
        }8 H/ D# s1 R' U, q6 N! b1 u
        // FDS
( G* Q( U) k3 j; ?6 O# }+ [1 W$ D        if( exsound_select & 0x04 ) {4 V; Q, o3 z8 V* n) C' ]( |! {
                fds.SaveState( p );! [4 s9 P6 Q8 l9 K: K8 F1 H+ d, t# V. O
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 E  N# W7 i2 X1 s& \( G6 Y        }  m/ @* ~' v: Z# k7 O
        // MMC5: ]/ q" z: Q8 `2 K0 l+ q
        if( exsound_select & 0x08 ) {0 v5 ~* T7 w0 ?
                mmc5.SaveState( p );
3 C. ^& a3 q6 q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding) E  j5 \; Y2 j  M9 E; C
        }
9 N0 U0 s9 o* O        // N1063 h; E8 A8 O# K7 {2 B1 a
        if( exsound_select & 0x10 ) {
+ M* o5 g4 p) ~; [" P# {2 D                n106.SaveState( p );
/ }* R& P2 ~0 d- F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- i; g1 Q# Q( j' M. L0 E( ^) N" Y        }- o! s* ~1 s7 l5 x( p$ w
        // FME7% |3 B( U  J7 p8 J9 x
        if( exsound_select & 0x20 ) {
8 ^& \5 w( h' Y0 n8 f                fme7.SaveState( p );, p8 r9 m! c6 t6 ~. q4 @
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% A/ g1 x& m! w7 e9 g        }
' m( ~# Q/ c& ?- |
2 |7 k' w. T/ |' ]* A: I. c#ifdef        _DEBUG- W2 ?- B! H' m0 m2 \. L$ o& b
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );  h: w6 z3 @1 Z' J" Y$ n
#endif; V: Y+ ?7 a) L
}; G* M8 y' K; d( Q- W

8 I' o$ {0 V  l. w5 Jvoid        APU::LoadState( LPBYTE p )
& o2 F1 ~6 _& O' x* b. A8 m{
. X) B, ]& T) q% |        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! H6 t2 I1 P, \8 `4 K. X3 O
        QueueClear();# Z& c: w: `0 h$ w  i; |( N) }7 [' c/ S

/ _/ t# t1 F+ R* `* d        internal.LoadState( p );& d. U0 p3 k: k# l2 [
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, g4 o& r. K  }, K8 g! \) a4 d* h
        // VRC6  k$ v% Y  O% X7 \7 y9 n
        if( exsound_select & 0x01 ) {8 C$ I7 j! y+ M9 e
                vrc6.LoadState( p );
5 u: n, y' |. n* O+ j  p9 w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 f- ~( s( M- E8 j4 S/ M$ i# z        }2 N3 U: A1 n9 a3 V( L
        // VRC7 (not support)
% U  i& m4 ?& e! v! E7 {8 L. k% L. m        if( exsound_select & 0x02 ) {
$ U3 o" M+ o9 d0 d* Y                vrc7.LoadState( p );; A  I1 {; H$ b) y1 D. Y, E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 D8 `/ O+ }: F1 o* h1 H
        }% ?8 H+ N% Z1 H, R, P
        // FDS
8 s& i: W; H5 `" \        if( exsound_select & 0x04 ) {
7 ?# D+ j/ }' \8 h8 @                fds.LoadState( p );
1 K& y/ [5 U* V( ]* I( T5 ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 n2 e4 N  U" v$ K7 c        }% h) _# v% \* t" R3 @8 b7 G1 g
        // MMC57 [: T1 \. e: S' A
        if( exsound_select & 0x08 ) {
/ J9 V$ h' V5 D) Q1 t3 V3 y3 |                mmc5.LoadState( p );
8 ]( W' C) |* l+ q% p                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, }0 `' B4 w! W) J
        }
' v9 s2 Z; ^: a: Q        // N1063 ?7 m3 R4 c$ N* j
        if( exsound_select & 0x10 ) {
) F9 X& T8 ~# K; N/ [7 K                n106.LoadState( p );: M2 Z/ e2 z( ^/ J/ J. S% X
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& D5 q+ Q/ E2 Y3 ^4 g2 B1 Z
        }
9 [, C  ~" }8 X: ?, T) B! s        // FME71 @9 I4 O3 @8 a. g% G5 J2 r1 \+ ?
        if( exsound_select & 0x20 ) {
0 |0 H! f5 |# e* I7 B5 g( I                fme7.LoadState( p );
+ G( z$ F2 y3 J6 J) @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 {$ u1 x; g" _7 F! _1 E
        }1 u# [7 c. M" V0 W0 Q0 H
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% E% @" g# {4 ~4 }! _% e可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  ?+ G  h2 [+ d" j$ B' Y感激不尽~~
7 Q! K6 G3 \9 M9 }& s2 X& ^
恩 我對模擬器不是很有研究,6 E) h' K+ \3 h  s3 e4 J' f* g
雖然要了解源碼內容,可能不是很困難,
8 D' a) r( b/ s1 H6 ]: W不過還是要花時間,個人目前蠻忙碌的。: e( V4 g" p3 k! j5 v) U

/ ?5 B6 r: v4 C% e給你一個朋友的MSN,你可以跟他討論看看,4 c# o' j7 |- L9 B4 F; G
他本身是程式設計師,也對FC模擬器很有興趣。
& q& t9 y9 i. z
0 M/ \: F0 n7 |8 P# g# VMSN我就PM到你的信箱了。
7 b4 R! f+ @! u& B2 ?4 x' M8 q9 |7 n  F+ f/ S& p: L  Z5 L' J0 O1 P
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 & N  s0 c' M1 L8 b
呵…… 谢过团长大人~~

3 h* Y5 f7 \5 }0 z+ o7 B7 F$ @/ Y$ L: N
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
3 F" ?$ P' w; L; \团长的朋友都是神,那团长就是神的boss。

" B/ p8 i" s& ]! V2 W8 w1 \. q% x哈 不敢當,我只是個平凡人,# O( t6 h) ?. I0 p( P4 ?
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙6 Q; G# j! u4 F- q' a4 z; x, `  K$ w* X
ZYH, T. c% {' {- v6 I; \
QQ:4147343063 z7 X; ]9 z' q
Mail:zyh-01@126.com; t9 d3 X" }' H3 n: i' n! ?! H! C7 q8 @
! _" i1 A5 {2 t
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
  a$ j3 y3 }8 |  d  g再次对团长大人和悠悠哥的无私帮助表示感谢~~
5 c) x' B# c" }1 ]7 h8 j
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-16 15:48 , Processed in 1.098633 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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