EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ ^- L+ M4 H3 N( M- r4 `/ M
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: X0 f/ j+ S* Y) \
这里有相应的模拟器源码,就当送给大侠了~~: K3 Z2 u8 \  h9 x# J: _) p6 Y3 l
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 t  a6 O0 X5 s) Z  Q5 a
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  y4 i# ]( ]1 r+ a! d4 a; w# D  l" w+ P
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: h- K6 @  y8 j) f2 r
这里有相应的模拟器源码,就当送给大侠 ...
7 w" g3 v' i4 K9 Y$ P5 d
聲音部分(Audoi Process Unit = APU):
! [& }* p- H. n; `  u2 V: x0 g& E.\NES\APU.cpp
& G' o' a, n1 v+ g, h.\NES\APU.h4 V1 H- i8 n% G; w4 Z: O2 ]
2 ^& u% X: L: u  u. u0 v4 _

& ^8 o* C5 g# N: P9 z: i影像處理部份(Picture Processing Unit = PPU):
7 x% ^/ ]* \5 l8 ].\NES\PPU.cpp
( h# Y+ i! y4 c8 X1 E, u! w.\NES\PPU.h
. N6 f, X9 L0 q, D: ?/ u
: [0 r, x6 R% {/ b如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 {5 q3 _5 |# V- O/ L
(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 |: ]! {  e- O8 v
//////////////////////////////////////////////////////////////////////////
, A+ P* Q& }2 a: ?//                                                                      //6 ?& ?) S) _' ~# x- x6 J2 N
//      NES APU core                                                    //; u4 d# _' S2 ]8 ~. A  ~# l
//                                                           Norix      //
3 D, s* R' M, D; `: P//                                               written     2002/06/27 //+ y- h6 Q: t: v) o  L
//                                               last modify ----/--/-- //
2 ?, I. K9 S! b% a. p+ ~//////////////////////////////////////////////////////////////////////////6 l1 m% ]8 a' m* e
#include "DebugOut.h"
1 Z& J0 C+ S; h. G#include "App.h"
6 H+ L7 A9 W; n( g#include "Config.h"
! p" l% K- w( l4 f, D0 g" Y5 R1 }. k* W
#include "nes.h"
! Q! t. r. b3 P5 b4 h#include "mmu.h"
$ H% w% d2 R" K0 {#include "cpu.h"6 r6 {/ Y% G# c2 ]( U5 ]1 X
#include "ppu.h"
2 h$ E& Q5 B; o  r, r7 ?+ K8 x6 n0 U#include "rom.h"' W3 y) v) e+ T' g7 y& c3 I
#include "apu.h"2 C3 u3 s4 N4 @' s  ~

# p0 R3 n4 u, ^7 P" \// Volume adjust) L. d, t. M" c8 ^
// Internal sounds
, h/ j) d! r3 d6 `1 O- B; \#define        RECTANGLE_VOL        (0x0F0)
- b: u. K& s* F+ H+ P0 e) I#define        TRIANGLE_VOL        (0x130)4 Q, O$ W4 p8 c/ K7 U2 G4 y* m' N
#define        NOISE_VOL        (0x0C0)
$ k7 z) A; J; |% ?#define        DPCM_VOL        (0x0F0)+ ~, N6 z. G7 [3 p4 i
// Extra sounds
+ Y2 u* s/ B3 q- N#define        VRC6_VOL        (0x0F0)
, |  A/ {" r" Q9 R( W7 _8 t; {3 z#define        VRC7_VOL        (0x130)
" U8 [# `# D) q5 K9 {4 ]#define        FDS_VOL                (0x0F0)
/ e& O+ k. Z3 R* I3 w7 G, x#define        MMC5_VOL        (0x0F0): ]5 L% e: }# N) O5 ]# F
#define        N106_VOL        (0x088)! h: Y. G0 l3 L7 _) w1 b6 \  X
#define        FME7_VOL        (0x130)
) `! q3 l2 |+ Q4 j5 W! b; O- [7 {7 S7 o
APU::APU( NES* parent )
( D2 l# h8 q+ F3 z) T2 y{
5 F* l0 H4 O+ r% n( Z# v) J. f% p        exsound_select = 0;/ B% r2 `( h3 o9 W2 _
- S" D8 c& F3 _! V& h1 D
        nes = parent;9 G) S1 y3 h( @: |
        internal.SetParent( parent );7 ?) ?& ~% U  F. U  o7 S

: W# D3 o: w# c* Q' n" N, Q        last_data = last_diff = 0;  S! I2 M; ]/ B& Z' [

3 C) ~  _8 U: X2 \        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );" U2 N5 f' n# b/ D" p9 }, J' {* o
9 V8 [* p! M' v  a% S5 G
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );4 o: g) k" a: o. b
        ZEROMEMORY( &queue, sizeof(queue) );) a% F( q2 b+ @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ ~1 f+ G6 t5 B, @

1 C, C- S5 e! ]9 |6 B        for( INT i = 0; i < 16; i++ ) {
; @2 P# g% A7 w                m_bMute = TRUE;
/ y, P, T' W9 R4 u( y9 j        }$ H3 p* q' `0 M+ V4 M' J5 N
}
5 B1 T. r- i3 C& Y3 t
5 r% R3 Q! v7 _. wAPU::~APU()
- q2 ]! |: T( R3 G& S{& H  U" j1 G/ R7 D; t6 g+ z
}; V. Q$ O( ?: N1 U* O$ t
/ P  q/ V) W, {# p, h3 E# A! \6 B
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
" q- }* |1 w6 W" P: b{
) [; S( h9 _' {        queue.data[queue.wrptr].time = writetime;3 B. x( ^% y' e! a5 P( C
        queue.data[queue.wrptr].addr = addr;
* D# s. @$ D" m* k        queue.data[queue.wrptr].data = data;
2 ?$ r, R  \* S  L& M- E7 q, {        queue.wrptr++;
4 s% `' Z; R" s        queue.wrptr&=QUEUE_LENGTH-1;
. p5 j1 }" U8 Q! b        if( queue.wrptr == queue.rdptr ) {1 M) n* v% l9 f$ h
                DEBUGOUT( "queue overflow.\n" );
+ }6 v* e0 Q( Q5 N9 T& m* f        }
2 K- }: w1 g. c1 ?$ {, i}
" R0 Z& U2 V2 k9 _6 L. \* ]3 C( F
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
4 o& V, `3 A; }2 s0 }* M{' h% {4 ]  ^# l2 |
        if( queue.wrptr == queue.rdptr ) {7 H& B  k8 P; M7 R  s7 P
                return        FALSE;0 H" u! @( y# d# Q5 f
        }1 i' z) p/ z3 N: ?# Q* T: ^
        if( queue.data[queue.rdptr].time <= writetime ) {* n9 y# e! |7 `1 J: X1 B* Z
                ret = queue.data[queue.rdptr];0 U% [" P# C) J2 g6 J2 \; w! t! ]
                queue.rdptr++;
' f) q0 l, H9 }* _( P: z                queue.rdptr&=QUEUE_LENGTH-1;
1 D; ?# o% p/ z- d2 l) d                return        TRUE;
1 y' k& |1 N6 ^1 }1 g' n, e        }
7 U  i+ v3 t3 @6 J        return        FALSE;
$ g3 X9 t8 q0 w& Z+ }1 w6 d; I- L}6 [9 i% X( o/ n7 }0 D
5 T: {. @, K4 x8 y! }" S/ e1 ^. G8 p% P
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
3 j+ _' ~  E) w# a{
5 [% n. O: q2 X6 s. b        exqueue.data[exqueue.wrptr].time = writetime;. z. Y8 p& H2 z  o, N0 j
        exqueue.data[exqueue.wrptr].addr = addr;
% I* W1 L: f# _7 N  G        exqueue.data[exqueue.wrptr].data = data;
6 j" M/ f# X% v8 |* j- ?        exqueue.wrptr++;" g7 N# r% `" b& Y$ f) e5 \
        exqueue.wrptr&=QUEUE_LENGTH-1;
4 n2 S6 v: o" I; O0 D        if( exqueue.wrptr == exqueue.rdptr ) {8 }# q# H' \9 S
                DEBUGOUT( "exqueue overflow.\n" );1 _& E8 T4 Q, g/ {
        }- l/ U- E- e) N- P/ o& }* w
}
- j+ A3 q+ c0 L; E9 P% |
' g& Q; \+ O8 s# g, GBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 F" {( d/ O+ H) q; F3 k{
3 D4 q3 M6 i: \; x- ?9 m, ~7 c0 ~        if( exqueue.wrptr == exqueue.rdptr ) {
( {6 L8 z3 X5 K- |' Q# O* {                return        FALSE;: Q( P$ a! C" e* L& D( r
        }1 Q% M4 D# k4 E: U2 t, S3 \
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* L/ h) A" T4 m: u
                ret = exqueue.data[exqueue.rdptr];$ y9 F1 y  R! Z0 ?) B2 J3 d
                exqueue.rdptr++;/ r8 k+ R+ a1 F3 B" Y. x& G
                exqueue.rdptr&=QUEUE_LENGTH-1;
/ V5 Z; I9 t6 i5 p                return        TRUE;/ T) e. v9 \2 x5 j
        }0 e1 o# v) B- I  b( @5 V
        return        FALSE;
' N7 s2 |. m6 R2 A6 Q7 |}
! |7 R+ Q, C% G3 \$ J% @+ h1 N7 _8 u/ u1 h5 r& P
void        APU::QueueClear()
! x! F6 u; |8 O, y- w7 ]{7 }% C; E6 `2 o% `/ F+ Q8 a( o
        ZEROMEMORY( &queue, sizeof(queue) );
$ F! p1 t+ ?' m3 {7 }        ZEROMEMORY( &exqueue, sizeof(exqueue) );! |6 B) E5 z# i* h0 P: s
}, W3 Y! X. H! y: m

, O7 @1 D  |1 ?: y) Xvoid        APU::QueueFlush()
* W: N# d1 |% L9 v- i' ?7 b{
( w$ `( u3 B$ J* [6 F        while( queue.wrptr != queue.rdptr ) {
/ D$ H( c  @9 I5 a& c6 C                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );6 D; Y' \- {/ ]/ E
                queue.rdptr++;- L3 Q. [" R& x
                queue.rdptr&=QUEUE_LENGTH-1;
7 h# b6 ^, D0 |4 r7 _9 T        }
- N9 P0 f% d, A0 V( @$ H; u# T/ R% x4 H! J( G) d! E4 q1 Z) ~" S
        while( exqueue.wrptr != exqueue.rdptr ) {! `: n9 W  \9 x  R: V' s6 B6 ?
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );8 Y) ~/ O, \, M. f2 ^: ]
                exqueue.rdptr++;
) G: D1 X! n$ y0 {+ T( I4 _                exqueue.rdptr&=QUEUE_LENGTH-1;
9 i+ a# Q/ L" L- g8 @8 m        }
- o, E% F% W: q9 {$ C}( f: D0 d6 t- C
) J, [$ r0 j2 h2 `8 r
void        APU::SoundSetup()3 n5 V* {! R/ [+ U+ `; F
{
/ T9 p' ?# ~. t" w        FLOAT        fClock = nes->nescfg->CpuClock;
& |9 M6 ~1 L* d  `: p3 l+ v/ F        INT        nRate = (INT)Config.sound.nRate;
' F, Q8 m  W$ d        internal.Setup( fClock, nRate );
$ _( ?/ i$ W/ Z8 D9 Z$ m        vrc6.Setup( fClock, nRate );' b9 x* Z* ?. i. }0 N
        vrc7.Setup( fClock, nRate );8 ?. |- h: D- a7 V
        mmc5.Setup( fClock, nRate );8 w5 L5 m  ?& }* k  p" j4 \2 r6 G
        fds.Setup ( fClock, nRate );5 {3 V/ ]$ `6 V4 R2 o  h
        n106.Setup( fClock, nRate );
/ c! P/ p$ r; b# o        fme7.Setup( fClock, nRate );0 Z% ?$ O% N$ c6 O4 m
}: T+ j4 n- J% Q6 v6 m

6 F$ i. r* J. }7 e$ m; g3 J5 Tvoid        APU::Reset()
% P6 J3 Y4 j5 e: Y; X! N{
$ u" K+ H% s. @& ^2 d' |+ E# ?        ZEROMEMORY( &queue, sizeof(queue) );( K8 M  ~0 a; O+ H: }' z1 E
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  h( C: Y3 G* R7 [' C

3 p  a0 n# I7 I. k( d. x# x( C        elapsed_time = 0;2 J( S4 Q+ h+ P$ P" q0 @  T1 @

( Y# ~" p6 K& ]        FLOAT        fClock = nes->nescfg->CpuClock;
6 F5 |, u2 ]) ]' T" v        INT        nRate = (INT)Config.sound.nRate;
& z  |. O+ |$ F& m        internal.Reset( fClock, nRate );9 J. H: G" P5 z+ W( \$ f
        vrc6.Reset( fClock, nRate );1 L1 w  P& K  U3 A2 L
        vrc7.Reset( fClock, nRate );
/ @; q# |2 z  E% r2 ^9 b. V' X        mmc5.Reset( fClock, nRate );
! ~0 y" [, |7 b% }        fds.Reset ( fClock, nRate );
! R3 X. ^5 c2 E( L+ X8 H9 c        n106.Reset( fClock, nRate );1 g* X0 }# ]2 ^! j% O# Q
        fme7.Reset( fClock, nRate );# L# o7 F+ q0 x8 [/ ^7 z) v0 P

. V7 l. p! t# F( C7 }: D& W: {# T        SoundSetup();
& p8 @/ c, [, d* y/ m. l) `}
: O& o) w) C1 Y1 Y* P$ ^
  b; p3 x. m, t' ]* Vvoid        APU::SelectExSound( BYTE data )5 t, r8 J: c6 B' b5 p+ P5 R
{* T# J3 F% ]; t1 N
        exsound_select = data;! G6 H0 C5 k3 D: y
}# `! C/ P2 G" Z( g* [5 _2 v

  w; D( G4 W/ v. ~0 y1 l" iBYTE        APU::Read( WORD addr )
+ U6 D& k0 C# p# d* J6 {{% K5 H  }3 y3 Y, f% V
        return        internal.SyncRead( addr );: S3 T" C/ f+ }8 E
}
9 {" Q; a* `  @3 Y4 |
! y9 O, n+ ^( pvoid        APU::Write( WORD addr, BYTE data )
7 d& L4 C. J' V2 N8 p* I{
4 K) Y( O( z" s. j$ V5 I8 e3 [2 Y        // $4018偼VirtuaNES屌桳億乕僩2 g. Y1 Q! w  p$ d2 z5 ]- j# f5 w) U
        if( addr >= 0x4000 && addr <= 0x401F ) {
' t/ \( C9 M! g6 r                internal.SyncWrite( addr, data );; M" E7 C( n0 z
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );8 N% v7 y% _, I
        }; S+ w( f; `: J% I% l0 W
}/ O+ ^" [3 t3 @& T  B2 u7 T' k
; X8 y$ w1 i) f  J  ?. _* s2 ?6 T
BYTE        APU::ExRead( WORD addr )
; f4 `7 N$ ]) W& }2 y5 c0 {" S{
# D7 h1 k) M3 P/ w, B8 C9 CBYTE        data = 0;/ F5 z) b: O4 n8 q

1 G# V+ V! ?  |9 i* o        if( exsound_select & 0x10 ) {$ o: g4 ]0 `2 O+ b& J' J8 K8 v
                if( addr == 0x4800 ) {$ f4 {8 v# i# I" h
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 @/ N  h; v4 F* z( e6 f$ E" @
                }
6 N* W3 }2 B6 [9 @# Y7 ]8 m        }
4 d' e8 _1 X0 h; [7 A        if( exsound_select & 0x04 ) {& R, K( h/ ]! N/ g0 {
                if( addr >= 0x4040 && addr < 0x4100 ) {
& H4 w9 t3 K1 {6 N                        data = fds.SyncRead( addr );
4 C9 i1 h! r" Y9 _9 j" _$ G; M                }2 }5 z  w, p, s6 P3 G
        }$ e0 Y: i3 V+ g# r7 G
        if( exsound_select & 0x08 ) {6 d: |0 f, P3 Y: I4 _% g: l
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' D0 H% i. U* B5 K3 W4 t& H                        data = mmc5.SyncRead( addr );
) |# q' _( Q8 j; o$ T0 ~* X                }
! L, }$ ?) Z* S. ~$ `        }
' r4 E, C% Y" W, r) v7 b) k
2 O6 l; z& |: x8 G/ u) `& V        return        data;- i9 ?+ W) _4 n/ u: p" m5 R
}6 R9 i+ C( T) G" X: d' Q9 l, t7 n

" R% d$ N* O  P% Tvoid        APU::ExWrite( WORD addr, BYTE data )
& ~9 r, c6 F; k7 W{/ f# C" Z* w. p% a# |4 R# L
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
/ G+ e6 H4 [" z& t" {
6 ^& J5 l( L  K+ c$ o2 n- j        if( exsound_select & 0x04 ) {
2 Y+ P4 Z. B+ N, A& [                if( addr >= 0x4040 && addr < 0x4100 ) {
+ ^9 A/ Y3 E2 `2 Q1 W0 i/ d                        fds.SyncWrite( addr, data );: k2 b/ q- t* a; n. Q. k; U4 T! i% Y
                }
' v7 Q: Q+ F1 e* z0 Q        }& c5 K3 t; z" W- g
4 t* j7 ~8 S- w! e& k0 I( f* C
        if( exsound_select & 0x08 ) {# t; Z% ]: i6 g5 `
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ Y/ w, X3 m( i% i  }                        mmc5.SyncWrite( addr, data );* p3 `) m: B9 _3 ~( H
                }  R. k4 J( a  N; _1 N/ U" d5 f% g
        }
3 W& \: O- s- E% R}3 S6 ^6 T" Y: G: V- z: L
; ^1 o: F. y4 _" _% L
void        APU::Sync()/ o! {/ U/ P, |
{" l- f. L0 W+ t" ]% H4 ?  Z0 f
}
, h4 ^- P+ w% q6 u
* O0 W) H8 f4 g, ~* qvoid        APU::SyncDPCM( INT cycles )8 |- P, W- E4 J" I( k
{+ [4 |" V9 B7 L2 v* l( ^  {
        internal.Sync( cycles );: T7 \, J& n; }/ i5 Y- Z

2 m% y( j4 A/ a% A7 v5 A        if( exsound_select & 0x04 ) {0 z+ X- a2 H0 n) V1 t# L: _/ a" I
                fds.Sync( cycles );
6 `6 S$ b; q$ M        }
6 p( N: s7 k4 v        if( exsound_select & 0x08 ) {- h: z1 N' B5 @3 G4 o6 S
                mmc5.Sync( cycles );# _+ N& F) |6 [
        }
: z, D2 T# z# _( t5 N5 r1 ]0 E" S; n8 E; f}
5 z3 c8 P$ k& \5 \, a) d4 I
( B  Y1 X4 s0 P: wvoid        APU::WriteProcess( WORD addr, BYTE data )) r! @: g, U8 D8 k, g2 i. ~
{
7 `, M; D- g" x$ R        // $4018偼VirtuaNES屌桳億乕僩
7 N. |& a; X8 {# ^5 `* M6 v4 u        if( addr >= 0x4000 && addr <= 0x401F ) {
( e! E! f& w/ A4 w" _3 d3 q, q                internal.Write( addr, data );. y' N+ `- a. F  L4 i
        }+ z& J( e% N9 ]: d
}
9 K- ^0 m1 @9 ^4 V
- [6 l+ f  K" T% nvoid        APU::WriteExProcess( WORD addr, BYTE data )( a) y1 Q8 b- ^- R7 ~2 J, {% X
{4 u+ ]) `6 F) `/ P
        if( exsound_select & 0x01 ) {+ ~) l- V0 a" \
                vrc6.Write( addr, data );
. L, y2 T+ q8 x  q# E2 p3 S        }' J1 D* Y" b$ t0 y" v) x) E
        if( exsound_select & 0x02 ) {
) j: b" G. ~0 _9 C1 [                vrc7.Write( addr, data );7 C9 g+ R5 [9 g& k! T
        }/ y$ I8 g! l0 F" p) W+ B
        if( exsound_select & 0x04 ) {
" g1 S- ^7 j) S8 F+ X! Q% B                fds.Write( addr, data );; }* |7 J) j0 W5 |& ~
        }
! _8 c; Q. H3 B$ b0 r, o$ A- a8 _! v        if( exsound_select & 0x08 ) {2 v; C& @. L8 R
                mmc5.Write( addr, data );
* w  f! s& d4 c& t        }( m% Q+ o) x9 y. k9 Z
        if( exsound_select & 0x10 ) {: U5 s6 M1 r5 u% R1 {
                if( addr == 0x0000 ) {: o& A, X; ~) A5 m8 F; @, I( h
                        BYTE        dummy = n106.Read( addr );6 b( t; f; O6 k0 z! ~7 |
                } else {
/ C* }9 z/ x: Y                        n106.Write( addr, data );
6 |: R% e. s! ]  K: x, l2 |& i                }
3 h. y9 u* H* A0 Q  e1 N# M3 C7 s        }
' }6 }( |) Q+ K; [- |7 h. G        if( exsound_select & 0x20 ) {
" @6 Z8 T, P1 s& `! N. T                fme7.Write( addr, data );: ~, s; V% i  o, B0 s
        }
4 e4 F8 o- w* M1 v5 {8 D4 r}
; ]; P+ z. S1 J* l0 u
! Y/ M/ S7 E: uvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
4 P/ Y3 p# a4 G{
8 p( O% ^* z6 s( W' U" M. |3 R$ ]INT        nBits = Config.sound.nBits;6 A1 T1 t1 p" O2 [0 v/ {( z/ m, I
DWORD        dwLength = dwSize / (nBits/8);
5 l0 W4 T0 _% v" YINT        output;
4 b5 U' R7 q* k$ i6 c. I0 E, ~QUEUEDATA q;" N9 J% [6 |. j3 r5 E5 N) \! v% |0 T  W
DWORD        writetime;
3 j1 L- N( D3 H& I. j4 u9 {' P. n4 y( r0 X
LPSHORT        pSoundBuf = m_SoundBuffer;+ M) a+ X1 I1 b: \  p8 f, M
INT        nCcount = 0;
* R0 R# x. r* p  O/ Y6 x- s2 a
" f8 D' N0 o* T- aINT        nFilterType = Config.sound.nFilterType;
- P1 t# Z; l( ~" J4 k/ K1 X, W8 x6 C
        if( !Config.sound.bEnable ) {! H  b. ]; w! l( `; _# @& J# F
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
/ b5 X5 d0 e7 {# l$ |                return;
) }9 S) d% H8 I$ O! e5 S' D        }
2 g% Q! G/ }8 Q+ T0 I
- }6 R; n- u! U) z5 `        // Volume setup
4 g: X+ l5 _9 o, K  K: N        //  0:Master
$ m0 r) [' {& B* u        //  1:Rectangle 15 @0 J9 ^; k( f! a3 s" T
        //  2:Rectangle 24 V1 @, k- \+ Y% W5 P) F9 |
        //  3:Triangle' Z7 `. c" ?  n5 k$ A; u' L
        //  4:Noise
% p/ d% i" t) ?$ r$ o+ U        //  5:DPCM
8 b) E  L8 X7 v9 Z% A9 A% E6 S        //  6:VRC61 G5 {! D) S9 `0 l5 l
        //  7:VRC7
6 x0 A" m5 t0 j% w" o2 ]! ^3 q        //  8:FDS
. Y! h7 p1 P$ l& e; t1 [/ `- X        //  9:MMC5
  R* q3 N4 H9 L- V- A        // 10:N106
6 l/ r& K3 e( M) o* g        // 11:FME7
2 i6 Q  O: M9 Y1 I) O" O1 I4 R        INT        vol[24];
9 G0 C0 k, Q$ S: w% _4 g8 r" N# S% y        BOOL*        bMute = m_bMute;
* i% s% t; f! m        SHORT*        nVolume = Config.sound.nVolume;
7 S# e! ^5 `! N; t6 V3 e
% U  Z& {: t% i6 ]  z4 Z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
5 R  F; S; J. x. n% ^$ G+ f) P5 V" r3 M' K3 U2 U* b7 u/ \9 W
        // Internal
6 z0 F9 X, M  K+ Z        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
1 j& Z. I! Y4 z4 {% P        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;% H  F+ k1 \7 j+ k
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: O) e, A. M, ?' `        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
9 t2 k+ b4 N: L$ R        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
3 c5 Z! V: `: V% Z( `& w; e
" J6 ~+ C" ]! z/ T, }        // VRC6
( i, v8 |* ]9 ^, t        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) l+ X4 F! j2 Q0 J# m/ q+ S! b
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, }: ?% [% o( B/ X        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 ^0 r$ D0 K( s5 d* }" _3 U' K0 H/ T6 L% d3 F
        // VRC7
! u7 f& H3 X& A4 p5 E* D8 P" U        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; }7 D: I+ A3 {- D/ N3 R9 I- o' p

* F* D  a' d! G) n" Q9 }        // FDS' k' I9 e  e, h7 l6 ~
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
6 N" z7 q7 x: j2 U. c  N( Z# a* L- ^6 a' Q3 m7 M
        // MMC5) J+ ]; `6 K* _& s+ ^8 [
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ g+ Q8 o. ~3 V        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* S+ E. R" [1 e! J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! ~& T0 h( w4 ^) I
& z% v  o$ t! [1 M/ d
        // N106; o* X- @" M2 ~( b- m
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( d- \1 I6 K; p' r
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' P" h# r3 [) S, p, j% x        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( v: |# M4 D  ~5 T6 I/ l! l0 U( t4 N        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! I1 j+ t( Y4 {4 L        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  b7 X5 ]+ a( l/ T) ~5 Z' X
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ p) Q6 m5 t9 d' E9 M0 |        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  A4 d* A) E. z8 t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 ]2 s+ q' A0 g( R6 K" C

+ M! e7 D0 O; ~/ q        // FME7
. \# `( }# X# z9 a* V        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 l, p  ?, y. d        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  y5 V; e9 Z* @. z/ q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 J+ @/ _4 {* C( X! a2 l
/ w6 @2 \4 z! l# H
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;/ q4 F4 q' v. d- J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
  H. U; w, o' ^! s7 c6 }
1 e8 n7 D* q) Z3 L. F        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 a! }6 i6 |9 y5 i        if( elapsed_time > nes->cpu->GetTotalCycles() ) {2 _7 {( z* ]# W4 [) M( d
                QueueFlush();6 o( b- G; f# Y/ s3 @/ K
        }
; C8 T1 h6 O0 ~, U( a7 i
" d) h6 B- f# m# u+ n: R        while( dwLength-- ) {  H) `) R: }* G& S/ F% h
                writetime = (DWORD)elapsed_time;) _# k8 ^; Y/ N# p: C
# B  d$ q1 M3 j0 k/ j/ J* a
                while( GetQueue( writetime, q ) ) {
) Z. Y" ?$ h  H; K                        WriteProcess( q.addr, q.data );" q! |5 ^/ c  C, R% a3 `
                }
1 ], x" |/ x. E5 s+ P& T! L( b
; l8 u8 Q- I9 Y7 W1 A1 ~                while( GetExQueue( writetime, q ) ) {2 i0 T; u4 L7 b8 v! |! S  B
                        WriteExProcess( q.addr, q.data );
) h7 G3 V$ {  j- J8 ]. ^: ^                }
. m. a  A& }  h4 d" w. w! I* P6 d1 l# L
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME72 a) M  E" e1 R) ^6 b
                output = 0;
) V4 I: \* j, e2 f* g+ j% s3 u' T                output += internal.Process( 0 )*vol[0];
+ N6 @5 \1 [% Q( d. m                output += internal.Process( 1 )*vol[1];1 Y! @" Z# q' t; D+ R2 j
                output += internal.Process( 2 )*vol[2];% |" M5 N- D4 }$ g6 g
                output += internal.Process( 3 )*vol[3];
% Q2 a) w' g* j                output += internal.Process( 4 )*vol[4];5 _% N) H  o% E+ C& L) N' z
# v- O9 q& z6 ^0 f& J/ x* B
                if( exsound_select & 0x01 ) {; J' J! x. ^& J/ U
                        output += vrc6.Process( 0 )*vol[5];
. z; B& V: N5 \! O" Z                        output += vrc6.Process( 1 )*vol[6];6 }6 i# M' i4 i( `$ d
                        output += vrc6.Process( 2 )*vol[7];
  O! z9 y7 B. U! n                }" k9 }8 P/ C; F7 A% W, S
                if( exsound_select & 0x02 ) {
1 q' V* ^; p9 m  O& i7 r+ r                        output += vrc7.Process( 0 )*vol[8];: m# |- c8 h9 ]" _) q' j) ?) C
                }8 C  |; R2 D# T' O; o# V0 }* q/ j
                if( exsound_select & 0x04 ) {; n# W5 Y$ t. u4 \
                        output += fds.Process( 0 )*vol[9];& w# F4 m8 O& Q$ W3 f
                }; j3 m8 O- H; U! j, |; Z" l: V
                if( exsound_select & 0x08 ) {
8 L' N: V; W9 I4 S                        output += mmc5.Process( 0 )*vol[10];% x8 A3 n/ l4 E
                        output += mmc5.Process( 1 )*vol[11];0 k0 L" W7 ^6 a7 m/ @: O/ ~% P
                        output += mmc5.Process( 2 )*vol[12];
) F( ?! u1 J! o- x                }
" i8 }( m" G# O( R% l' B                if( exsound_select & 0x10 ) {
5 D: m1 g8 g+ T- C; |$ J                        output += n106.Process( 0 )*vol[13];8 |3 h: ]. g- ~$ N; [
                        output += n106.Process( 1 )*vol[14];
3 S# K) ^$ e6 s3 Q                        output += n106.Process( 2 )*vol[15];6 Q6 z2 B$ z; s9 [$ W5 m
                        output += n106.Process( 3 )*vol[16];% S  e9 p' h- e+ Y: c
                        output += n106.Process( 4 )*vol[17];
# i0 a! E% N/ |( r                        output += n106.Process( 5 )*vol[18];
/ F1 g9 U6 j9 m; B$ _1 V* r                        output += n106.Process( 6 )*vol[19];
5 o) c3 _8 J. K' Z1 T                        output += n106.Process( 7 )*vol[20];
! b: F+ n) `) P! B                }. J/ ]1 k; U* [" f- X1 g( `
                if( exsound_select & 0x20 ) {/ t& d4 z7 [% r' M
                        fme7.Process( 3 );        // Envelope & Noise
5 C" h: i: C- z                        output += fme7.Process( 0 )*vol[21];( m) D  z2 T, v4 g- q( w$ [
                        output += fme7.Process( 1 )*vol[22];
$ M8 K1 t/ P( i$ V2 r7 H                        output += fme7.Process( 2 )*vol[23];& b7 S! L5 A4 P- h
                }" c# O4 E# ]+ K6 m8 X! J# S( Y
9 d1 I5 w- L4 g' d
                output >>= 8;0 {" u/ _9 b4 r) ]3 e  r

9 }4 l+ e0 g0 a. U                if( nFilterType == 1 ) {
: o' l2 D# C+ K' h8 U3 p4 s7 D( n                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
# J( j% ?" q) f! r2 |                        output = (lowpass_filter[0]+output)/2;
3 h* Z2 E/ Y2 J% \: a6 M3 M                        lowpass_filter[0] = output;7 N) \& |+ ~4 c9 w% z' y; e$ o
                } else if( nFilterType == 2 ) {
; A+ b, e9 y2 \3 K; W9 h! m! L5 K                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)& U, M/ z$ {+ l' ~1 \5 e
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;+ j( l7 G! `- t% u0 T8 V) M
                        lowpass_filter[1] = lowpass_filter[0];" g* C4 [4 \7 }7 {. n. H
                        lowpass_filter[0] = output;  L' P$ D' U) \$ n/ V% ]% G
                } else if( nFilterType == 3 ) {9 u: h% ^) Y) |, @
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
9 i7 ]9 f1 c4 F3 M0 J: e# M                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 S* O+ P* F$ ~                        lowpass_filter[2] = lowpass_filter[1];
) g6 e+ [4 V5 M! K$ B1 Q                        lowpass_filter[1] = lowpass_filter[0];/ a- N' t3 V; h$ `3 X7 [
                        lowpass_filter[0] = output;8 R' r* n5 g" ~1 h
                } else if( nFilterType == 4 ) {" S8 v/ I& o4 i: o# B% I+ x" P
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
5 u' {5 F2 ]: ?) {) S* S. S                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 i# D. F) K% d                        lowpass_filter[1] = lowpass_filter[0];2 H4 Q0 j2 w8 ?- w5 E* C! ^
                        lowpass_filter[0] = output;0 Q) u( f& L, k
                }) Q: Q5 f5 j3 B* N: \

. {$ o; E4 L1 ?  o9 C#if        0
: e* |" y+ l1 \* s9 d                // DC惉暘偺僇僢僩
/ |) i/ y$ p4 C3 v                {
8 B% ]7 G( ~) i' O                static double ave = 0.0, max=0.0, min=0.0;0 v1 ^# [5 K3 M+ a4 i. E6 t3 ^+ V
                double delta;
# X+ N. l' K+ ?' d. t6 `! ]                delta = (max-min)/32768.0;0 p0 T. c) k; W! ?; c) Z
                max -= delta;# N; J) T/ e+ z
                min += delta;1 K* ]5 s9 `3 {. \" x8 R) T/ k
                if( output > max ) max = output;4 q# Z7 l+ R5 {: W- k  U
                if( output < min ) min = output;
& x2 K' _) _7 M. ?                ave -= ave/1024.0;* E, X  L; a- ~
                ave += (max+min)/2048.0;8 P, g7 }, _2 H
                output -= (INT)ave;$ H& T5 i1 C* i3 L) h
                }
" l- T. a% N8 u& [) n#endif
- r0 {/ E7 Q8 E" z6 b' {#if        1
# K5 k9 @$ V) c3 s$ y" q                // DC惉暘偺僇僢僩(HPF TEST)
# \/ N2 L9 A& \1 A4 N                {
8 e6 k# D5 C6 W) Y0 p4 g% }" O# @//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 ]. W+ [2 B0 j+ t3 K# R
                static        double        cutofftemp = (2.0*3.141592653579*40.0);' j( d  a) w6 L  t  h% S. U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;9 k* L( O8 `( q& q2 C, m) D
                static        double        tmp = 0.0;% Y# w& V, u% u; X8 C
                double        in, out;8 t! `0 v; W/ F' Y' L! r0 D; V; Y
! W  M: m- G! }
                in = (double)output;5 V; Y* W+ q. P1 w7 ~! I
                out = (in - tmp);+ d" m+ S* l. I4 \. V1 `
                tmp = tmp + cutoff * out;
7 @! P7 o" J6 K1 b1 n0 ?+ w2 Y* V6 G" F1 S+ p
                output = (INT)out;% R' l) t. Q7 H
                }
+ I, ~. B* u* A% e) `$ C#endif
$ m+ j9 e. e* F+ C) ^#if        0$ A/ x" ^0 N4 T& B
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
& H3 h) j  f% ]. U8 W% A0 e; C" k+ C2 ]                {3 o- e2 a; j/ y& W* @' I  B
                INT        diff = abs(output-last_data);
9 G- ~" h1 v. `1 Y7 U                if( diff > 0x4000 ) {
+ Q/ p) @6 b2 v! f6 p6 z0 Y                        output /= 4;( O1 k' c  ]0 T2 w* ]
                } else / e( B* Y! K( h, @3 h2 @" h
                if( diff > 0x3000 ) {
# _* }/ B: U' e, s1 F- E' o                        output /= 3;
. ~2 @$ g, J2 f                } else# o: ~$ s& K; _7 }. I
                if( diff > 0x2000 ) {! a, m& m( {5 f0 \! M$ U4 v
                        output /= 2;
- w$ L. S. H& W) c/ ^$ X) t                }
# y# x! C; \. o0 z$ \! L                last_data = output;8 n# u6 y# W1 w
                }. s2 ~. k9 @9 u7 F$ T& u* p+ U
#endif
* S! G' b, h; {+ F) [+ _                // Limit
1 X) [: d4 K* n                if( output > 0x7FFF ) {1 V6 X, x% y; S# K2 t
                        output = 0x7FFF;
* l& x2 K$ A2 n" [- m                } else if( output < -0x8000 ) {& k- M( p% G% S/ f, E
                        output = -0x8000;
9 S: ]3 ~* R) c                }
& O2 f4 {" k; O
9 z! ]. U# _( p( u+ G) Q: v4 ^( X  `                if( nBits != 8 ) {. @6 Q0 F  j: _& D! P7 o
                        *(SHORT*)lpBuffer = (SHORT)output;
2 B. E1 U/ l  R$ l$ ^+ V                        lpBuffer += sizeof(SHORT);
& m. t0 `$ ?3 M                } else {+ q& v$ J( n6 p" R
                        *lpBuffer++ = (output>>8)^0x80;
" O) P. Y* n6 b! ^/ I8 y: Z                }$ n/ U' h0 H; S) ~- i! T

/ x8 O( e, N# [' o1 i                if( nCcount < 0x0100 )
4 \: q* A1 E5 Z# G- B5 A) F- n                        pSoundBuf[nCcount++] = (SHORT)output;
; i' x& b  N% \8 V; l5 C" `! v  Q+ X2 _- y2 Z
//                elapsedtime += cycle_rate;
  w- ^7 c5 z) B& k1 S                elapsed_time += cycle_rate;' W+ }; y1 ]6 s# Y
        }" V& n/ c2 f" u  J0 Z/ A- L

) b4 W3 i, S) n' Z; R% h6 Q# W#if        1( M6 v: p6 g7 u  T- X
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
2 I) ~3 K0 n1 D8 M) Z, ^                elapsed_time = nes->cpu->GetTotalCycles();
( z, E4 d9 s: V* y        }; w% h) u& Y+ e# g, ~$ d" @) W
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {5 o6 M3 m* P& X% L+ s' T$ C
                elapsed_time = nes->cpu->GetTotalCycles();
1 x2 C6 |% G- r8 D8 Q        }
  W( _* I$ y6 j( ?+ Z+ X' j) ]  `#else
1 ]9 e$ I; v1 f7 u0 G  y        elapsed_time = nes->cpu->GetTotalCycles();6 g1 W. C* g$ Q$ M5 c
#endif( f+ n1 t7 v' `) x) F& A
}( _" F0 z. \( ~3 J  i. K
: |+ ?, D. k' P4 C0 ^/ J% g  ~
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)1 ?, C  ]: r' t- v+ E
INT        APU::GetChannelFrequency( INT no ), }" O) h( P4 n4 \
{
3 ^" ~; d. X1 c( a& t        if( !m_bMute[0] )! u% r9 l( E- i- N
                return        0;
6 q& V+ x1 a+ f/ S& V
; T7 f( J4 A8 N        // Internal
  u2 U  D  \2 L# W        if( no < 5 ) {! f5 M  h- r, e4 o8 ?, j  V4 n2 c
                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ _+ A+ O3 Q4 |  M8 N" |; W6 C6 p) V
        }
- q7 b+ i) g. Y% `) W# Q  ]        // VRC6
4 U0 B; F" g+ K2 u# C5 o. N; h        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ |& i% f# @# X6 y0 Q1 ?* Y4 _) R                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 r' P: O3 L# p8 s  x/ S. p6 [. y0 _        }# g$ ^* B& ^1 ]- n: Z' f! E
        // FDS  D9 B5 m  v6 O# h
        if( (exsound_select & 0x04) && no == 0x300 ) {
7 ~/ u5 W4 n* q( r9 o( F                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% r/ k" J8 w; G' t        }
3 d1 P6 X; |0 ?6 @5 k2 V& ^        // MMC5; y) X5 o/ r) f7 J  E
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {, Q: l$ Q. E' }" U7 ^6 O
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; T0 ?- C9 L7 V+ b- m; o        }
+ G* X" z$ j( _% v9 H9 j# r        // N106+ }  |( Y, c- R, b+ k) c
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
* E1 T4 @( U# L                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
2 |" l1 ^5 n$ q! T6 }% M" ~        }5 r: O  R9 D7 u( ~+ U; F% ~
        // FME7
8 t& i6 m$ @' F: Q" \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
) U, E; Y$ K5 }. X: p, m7 K                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 ~3 O7 O. D$ ^7 r( w% w% o3 o        }4 E8 O& J! {% f0 z; l+ U
        // VRC7
6 W* d) i. R$ }/ p' S8 z# K        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {. A4 \) q! n2 g7 y7 U* L' E
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- ~1 v6 }' Z0 y, s) j        }
  S' c  S9 n% \        return        0;
* h4 \1 a3 q/ U. Q  z}+ Y1 W0 A3 I+ u+ s8 ?

3 o+ a! k6 G2 I9 b! e4 }! _! D/ @// State Save/Load  F3 j/ y2 \6 t, r1 ~8 `, i
void        APU::SaveState( LPBYTE p )! k/ h' `  z' Z* h1 F2 s( K1 z
{
. w6 g" R1 G- N: i& W) ?2 @#ifdef        _DEBUG
) A) m1 J2 b  ]4 zLPBYTE        pold = p;$ A% R( r. x2 j, ~) w2 H
#endif
: }5 W, _+ ]: C% M9 c  ]. i5 d
0 g, c% Q0 t$ \# K        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
6 B3 ~  y* Z1 V9 d2 ]" s        QueueFlush();
! g& Q7 @! s+ [# o6 r; M
5 }- J4 V2 x. O/ {  ?4 I; L        internal.SaveState( p );, s$ j! l/ _' ^; K+ ^$ V( k2 ~
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 O* O% V2 C( t4 l. w7 D
0 K) F2 H8 \1 V( V
        // VRC6& E) a# J; {  c, G
        if( exsound_select & 0x01 ) {1 W, ~% L, M$ P+ K; U1 w
                vrc6.SaveState( p );- P6 J. c4 Z+ A4 g, j. L
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& T1 u( C+ V; o, f& W- Y
        }) b- D) V( [! v3 M6 t( k# `
        // VRC7 (not support)
+ U$ [2 D1 f3 Y5 l) w        if( exsound_select & 0x02 ) {- s9 q; d  R" [: U% o
                vrc7.SaveState( p );1 ]8 H0 Q1 @3 X$ y' l1 a( j
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
5 f4 r! M) E/ \* D4 S. ]6 f2 a        }+ p0 W: z. L- S  u
        // FDS" d0 U4 W$ k% o9 o
        if( exsound_select & 0x04 ) {
$ {2 a9 H# X, o) K                fds.SaveState( p );
: z6 _& p6 U* V) A5 Q7 k                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding) z+ D- u4 D/ g' f; }& N6 V
        }4 U! O; H+ o) [  m
        // MMC5
6 A" y# {+ i+ K5 e! }* ^% o        if( exsound_select & 0x08 ) {
  s" X) A. n# c. q                mmc5.SaveState( p );
6 J9 M, M1 G/ Z" B9 J% E: U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" p+ n) \& q' N& \
        }8 n* e, g3 }) X4 Y
        // N106
! V3 W9 E+ b5 x3 |5 R3 `        if( exsound_select & 0x10 ) {
, A% ?( J" s; t& [, s- {# L                n106.SaveState( p );
1 p& L: B7 C+ D! }! i( j                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& {7 X% h7 `' B% j2 L  x
        }9 [; _+ Q* x' w% h& i
        // FME7) s( q2 o2 C& a- q8 }1 z4 z
        if( exsound_select & 0x20 ) {
, e* G/ @0 I: V$ _                fme7.SaveState( p );
. q8 k7 W( Z/ q: M: h, v                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( j! @4 M+ V7 p/ x        }2 G& G" h5 k/ p3 @/ g
+ T1 Q4 s) p7 _3 O
#ifdef        _DEBUG: g1 O$ P0 J8 D. h1 Q8 N
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% _7 g0 A, w% B- E1 F( o" P- E" ]#endif0 ]2 E# J( D* j
}
0 d( J+ K  p: ]0 _! {" }" d! a: ]
  n0 w! w. U0 ?3 `5 evoid        APU::LoadState( LPBYTE p )
0 F  E8 U( V  v- ]2 b& m1 a/ V{7 k/ Q$ H: \. a/ e2 i
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ m7 R, g# X* t5 |        QueueClear();
+ C& b" `* A* Z
, f- t( ]( _6 ?$ K7 G2 ?        internal.LoadState( p );
8 P1 S" B0 l4 h. I        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 F) r( y. ?4 S5 q7 A& [
7 [7 _0 V& j: S& e9 z4 X: _; q0 e
        // VRC6
  H' U7 y5 g: O' F- ~        if( exsound_select & 0x01 ) {
; U& T' m7 Y& g0 g3 H$ z$ |* N) A: T                vrc6.LoadState( p );
* z. B9 S- s0 |. |                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* b( H- F/ l$ N5 a
        }# x! U( {  |) G$ q
        // VRC7 (not support)
. K9 h3 ^! Y9 }4 _( M        if( exsound_select & 0x02 ) {; C% a7 [  l3 X6 a' ~* |
                vrc7.LoadState( p );8 `9 V5 P* m" y# B& U$ v
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 D  I! S8 M5 D6 O1 _2 m3 w& a0 W
        }$ m8 P6 v9 d- N3 O5 t
        // FDS
3 Q/ ]+ z/ p' b" b" F2 i, Y* z+ G        if( exsound_select & 0x04 ) {9 D  V% u1 E6 x" U( ]  y: ?
                fds.LoadState( p );* K7 @# g: r7 m. t5 ~5 q# p
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! i8 p1 Y# L1 t" T5 u  Y
        }% e. [/ a; W  R# q0 x+ q2 {
        // MMC5
7 N7 [! I( p1 w- x2 d        if( exsound_select & 0x08 ) {& [* Q0 Z& Q8 t- C- C: j2 w9 K. Z! G
                mmc5.LoadState( p );. |+ j! q) a( O+ E$ n: }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# F5 C- U; N6 ?, S9 ^3 {        }/ @2 m; k- v0 U$ z  J5 w+ ?. M
        // N106
- h8 G1 T) T6 \; I, d        if( exsound_select & 0x10 ) {' a6 r/ z  G* s" ~
                n106.LoadState( p );
, G1 e6 e1 `1 q  |; Y5 A                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; g. t& b& o3 B( h# O5 l        }
) h2 W1 J+ T5 k! J2 X0 h        // FME7
% o4 k+ Q- K' j% P        if( exsound_select & 0x20 ) {+ v! o+ K. S# n( ~. S, s
                fme7.LoadState( p );
" N. J+ J. O+ ~' p# C0 Q5 |' C                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 m3 ~8 p2 g% ^        }7 V# B: ]5 r+ [, T6 i' a
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
4 [2 u) K$ X  ^! ~  ?1 ^6 r' i+ b可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 k# S) D' p3 Q; }! v; z1 W感激不尽~~

# e$ K( z( |  v3 @4 Y$ Z恩 我對模擬器不是很有研究,
4 a) }) G3 m6 o, L4 }' }. L- H! m雖然要了解源碼內容,可能不是很困難,5 `- p$ @: a: |" E
不過還是要花時間,個人目前蠻忙碌的。
& P6 `$ ~% j( m0 p9 r  T4 r2 R. ^& Q7 ~
給你一個朋友的MSN,你可以跟他討論看看,5 Y$ I. k* F5 R0 x5 R( |/ Q; |8 T
他本身是程式設計師,也對FC模擬器很有興趣。: {. M" N( s- m; z
3 b6 y) j( @# ]" c/ Y$ g
MSN我就PM到你的信箱了。9 C0 W8 j% i  m7 p$ k; @, E

/ Q' G. r% k: w- e4 `% M& T希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 7 T/ H' ?! J( F! i- F' ]; g, C
呵…… 谢过团长大人~~
9 ]" W) g. V* S% V
& d" ]& K2 b: \- I: D
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 z  A% [/ `$ b" W% ?' L团长的朋友都是神,那团长就是神的boss。
5 D  l# @  `0 d  s; ]
哈 不敢當,我只是個平凡人,
" i0 W: N% K+ k  D2 y2 `2 x$ u要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) c3 B3 g. s1 \% Y; gZYH
" r+ ^2 q; y2 D0 KQQ:414734306
& v: f' \9 w) Z3 e- Y: v* y; P3 {Mail:zyh-01@126.com( x- ^: `7 \1 i
* p" t+ k9 ?4 _  X* C( ]* R
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 D3 e4 {5 N! \( o) ]/ k
再次对团长大人和悠悠哥的无私帮助表示感谢~~
, r" N8 g. H* j9 `) i
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-1-20 07:17 , Processed in 1.069336 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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