EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 O, F3 P( S0 D! Z9 J3 S楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  Y- f; I2 D; |8 Q这里有相应的模拟器源码,就当送给大侠了~~/ V" c" I" M" Y7 A" N4 ~" c/ q
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ' @" ?6 p3 w% u3 \( C* O
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 z/ O# ?5 g  |0 v( s" k
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. q+ {5 A6 Y. s3 ?5 C* C; l7 G这里有相应的模拟器源码,就当送给大侠 ...

; T) P5 o' C5 `% J: R) c5 s4 k聲音部分(Audoi Process Unit = APU):1 S0 K3 z' M! L% ]; e" ?1 B! F
.\NES\APU.cpp% h- L! ^8 l' ^3 W. J; ~9 q: e5 q1 A
.\NES\APU.h
! t$ }1 U- n+ {. t
& H& g" O, f* a0 _7 `# [0 X) w- c' J4 J
影像處理部份(Picture Processing Unit = PPU):
% G* Q- ~8 F/ L.\NES\PPU.cpp, H# z4 h; s: G' t
.\NES\PPU.h
9 W, O0 p1 a. U- d
& e7 N- l! T5 ~% f如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:3 l0 z& w; Z, X; |: W, t) p
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
3 ^3 S! Y# i$ D$ D//////////////////////////////////////////////////////////////////////////
* k2 G$ c5 n4 W//                                                                      //
. F$ e+ T% Y7 v. S3 P7 x//      NES APU core                                                    //
  n) `) F( h8 H2 d$ E! v2 Z//                                                           Norix      //6 @( ^0 _" P: X3 w, l
//                                               written     2002/06/27 //: L+ V3 f$ t* F1 o7 H
//                                               last modify ----/--/-- //
& Z% A7 Y  e3 P% o8 k# @, }//////////////////////////////////////////////////////////////////////////
6 ]  T( R& o+ C& x#include "DebugOut.h", ?4 f9 L( h" y* E+ \; l& y
#include "App.h"
9 E# Z% i6 [% A4 ^7 g#include "Config.h"
" l- |% w& }( B$ q3 j  Z: G( o+ d9 R
#include "nes.h"/ c$ _, Z5 Q) E2 d) _- L: d  k
#include "mmu.h"
+ O9 F8 q6 y0 A4 D8 f$ N, [6 H#include "cpu.h") G& U6 Q0 V5 b1 m$ k  G
#include "ppu.h") b4 l9 @" D5 u5 S$ O0 l) H& N
#include "rom.h"4 n4 H4 O# E& P  z: ?0 i6 Q
#include "apu.h": _' H- [) N* n) m" U4 e
" g3 T" T9 ]/ x. @+ u5 x: Z
// Volume adjust
: d( r& k* o8 C2 `// Internal sounds
3 p* y. B, R+ x( F& Q, ]4 `4 ^! d#define        RECTANGLE_VOL        (0x0F0)+ D! }- u6 J5 d% d: |) h- ?
#define        TRIANGLE_VOL        (0x130)! B* I& S9 m$ p: U" O- x4 s
#define        NOISE_VOL        (0x0C0)
. b7 g, s2 \% s* Q#define        DPCM_VOL        (0x0F0)
' \  h+ s& F7 s5 B: ]. F// Extra sounds
) S; n1 g$ _1 |#define        VRC6_VOL        (0x0F0)
" d0 u$ I% W+ `4 B# l#define        VRC7_VOL        (0x130)
& l0 a( |  [% s$ L4 \. m# j; R( R#define        FDS_VOL                (0x0F0)- @. Y" }2 I6 A
#define        MMC5_VOL        (0x0F0)
# y" x! ?# w* ~8 j! P#define        N106_VOL        (0x088): J& J& C+ [9 A% I
#define        FME7_VOL        (0x130)) V: B2 ~) C- ]

- [& N8 A+ J8 f4 K. uAPU::APU( NES* parent )3 ^' J5 ?3 C) S. g
{2 _; n; t9 z2 d7 v2 G7 y* F# u
        exsound_select = 0;
* F$ C0 |: M& d; k& J- J
' m' _3 L- F3 g% E9 C        nes = parent;/ j: C3 W3 f" Y: r4 }. }
        internal.SetParent( parent );
4 ]6 ]5 W7 X& a) v2 a% [6 D  i8 r" T) h9 U
        last_data = last_diff = 0;- r1 h& y* U; h3 F8 e, ?) @
" i8 ?8 [0 b$ r$ T. N
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
2 {; A# H& J1 F! i, P7 _0 c4 ~0 @! ]4 H% t. i& g1 \; x+ X
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );/ ^# A3 f2 a) s0 H4 u5 p
        ZEROMEMORY( &queue, sizeof(queue) );, v7 X- P0 g; I
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; A  L2 o8 W* t% J- p( [$ l& T3 q. x! J  J3 K
        for( INT i = 0; i < 16; i++ ) {5 @/ S2 u! M2 V
                m_bMute = TRUE;- i4 Q! b1 R% W
        }
- R) c* D) i, e9 S}: K0 q' P0 K& ]% i3 k2 d% j; [

) |. m- J& L9 Z) cAPU::~APU()
& W* c& b& ?9 h5 ?! i" B{
0 b% d4 M/ ]' ^( z& y+ A" c}3 k7 q$ Y8 p6 Z! i3 A( W

9 W( X& j+ B/ h( a1 P% \& Xvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
4 q% N0 s1 h$ F; d% s( R{
* w9 R% B2 ]/ M  }  j& I        queue.data[queue.wrptr].time = writetime;$ @' }' [4 w' V. `) j+ H" j& y, F
        queue.data[queue.wrptr].addr = addr;1 w8 d& F6 _! P& x
        queue.data[queue.wrptr].data = data;
9 M6 q3 {7 Z5 J( x: @7 O) j1 w        queue.wrptr++;
: U# F& L. Q. b9 U0 l        queue.wrptr&=QUEUE_LENGTH-1;
7 P9 ?6 m. d4 [- M7 {        if( queue.wrptr == queue.rdptr ) {& u7 ^% [4 Q7 h% w
                DEBUGOUT( "queue overflow.\n" );3 p, [1 P; ~' A2 d; U
        }5 x# G: E! t6 H; x2 R! p8 ]
}
0 g  F* @% N, _3 m7 A' Y4 Q: {8 m( d6 n5 R$ @
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* e) c! {2 A8 e7 g: R; p{. O, c+ C1 v- Y- u4 s8 `+ k
        if( queue.wrptr == queue.rdptr ) {0 o4 y4 Q- ~: ^3 Y
                return        FALSE;2 N! v' ~) I1 E: |0 Q. [
        }5 \6 E2 r9 g+ F5 l0 ^0 \6 a$ I# s
        if( queue.data[queue.rdptr].time <= writetime ) {3 u; }2 J/ X) E+ g
                ret = queue.data[queue.rdptr];! u& R: Y( Z. f% [1 D$ h
                queue.rdptr++;
: u" W' l) q% s$ C+ C$ e/ i                queue.rdptr&=QUEUE_LENGTH-1;0 j8 h. {$ m, m- z3 E) @) K
                return        TRUE;
, B7 D) I3 d6 Z8 c        }
4 ?9 X" S/ e& E        return        FALSE;; e- d0 y( ~1 d4 q* ^
}: m6 J" K- l, E) u
5 V3 ^* b% @. G4 B6 o' ]. A
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
0 k. e9 J: @+ [; Z* r- T' y; S& A{
+ [: R. e; f4 H1 {( ^; n        exqueue.data[exqueue.wrptr].time = writetime;) D3 F. j* X, {0 U5 j4 a( t
        exqueue.data[exqueue.wrptr].addr = addr;% W* C1 P7 s" z8 r! t6 R( b
        exqueue.data[exqueue.wrptr].data = data;- c# r$ {  T& H  ~
        exqueue.wrptr++;
( m: o8 b9 B4 D" W1 d9 {7 G0 a        exqueue.wrptr&=QUEUE_LENGTH-1;
4 M; p% a! C0 G7 D        if( exqueue.wrptr == exqueue.rdptr ) {
, i3 S3 u  b: A9 o% n$ m                DEBUGOUT( "exqueue overflow.\n" );
' s( w! ?- {( a* d) E+ g        }
/ y4 I5 v2 i! p/ ~}4 P  ]0 d4 d  b: Z4 g( `3 V

# U! O! M$ m& X" R6 n( wBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' R2 ~$ d# ]3 M7 {; Y9 c2 s1 e8 U{
, S& _1 ~; j3 z1 Y" E# S( H        if( exqueue.wrptr == exqueue.rdptr ) {
# ^  V* `3 b* f( i4 B8 P  @                return        FALSE;
3 G# V' J" T8 ?5 [9 s        }% [3 n; @% C8 B
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
6 r5 h, Q6 s+ n' p7 `7 o                ret = exqueue.data[exqueue.rdptr];
( U/ J# z% C6 ?1 F1 X' h% e                exqueue.rdptr++;/ S7 N: e9 X0 Y- O! s
                exqueue.rdptr&=QUEUE_LENGTH-1;
: i* p5 G8 U: t" I0 ]; [$ ^, i                return        TRUE;
+ z( k: y+ N/ Y6 q) p2 A# E        }
  N. D; f. ]& a9 @# K4 a- M! p        return        FALSE;0 R7 }. y/ m6 W2 |: z4 s
}
4 A+ ~/ n7 K; k0 @' v  a2 @1 ^4 |9 I! b7 J' |! O! N# @$ w
void        APU::QueueClear()9 [! J2 ?( x  U
{5 ?7 o4 f- B( H8 o* {
        ZEROMEMORY( &queue, sizeof(queue) );
: G; R4 k& R9 o1 W, q' F. R6 a        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' A3 L1 I+ Z5 {}
" v$ Y1 M& \. Z! g0 ~6 @5 w& U' O* ^# b" B+ H8 m) Z) B
void        APU::QueueFlush()
8 @  ?+ w% x  F& K& L5 J0 i2 B8 O{
  {7 W) |( X. M& f7 @        while( queue.wrptr != queue.rdptr ) {
' i% ?& x5 a* S" w$ B" |  [                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
  L( {2 t6 M* n6 r! R                queue.rdptr++;. o0 M7 |& p1 _9 ]% ^
                queue.rdptr&=QUEUE_LENGTH-1;
( |/ l  m9 n' u+ e        }
  p9 L% k$ b; ?* _: }7 ^  H/ w$ L- N8 y+ C1 l  J. w2 Q& h
        while( exqueue.wrptr != exqueue.rdptr ) {7 V- {) b* t8 V9 e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );8 _7 w- V- @6 F; o+ r0 D- F5 Y+ f
                exqueue.rdptr++;
# {7 v9 P  z2 P                exqueue.rdptr&=QUEUE_LENGTH-1;
; ^8 T/ o# U+ |7 y5 R& K5 Q        }
; M. _; P; {- A: v) ]}! W3 ~: Q) Y9 Q) r
# C( h7 t# u) X1 I" x2 r
void        APU::SoundSetup()
5 F$ n& s: A0 P3 U2 A) `& W/ k% S{7 u7 b7 X, Y9 [  I1 O8 c% N. e
        FLOAT        fClock = nes->nescfg->CpuClock;7 u$ Y6 o$ x! j  U- w
        INT        nRate = (INT)Config.sound.nRate;
  u. ]3 Q, I( y* ]+ X; x  q4 p        internal.Setup( fClock, nRate );, M( c) D2 ?% }' M! h
        vrc6.Setup( fClock, nRate );
8 G7 x1 g7 _9 s+ Y        vrc7.Setup( fClock, nRate );: i5 ]+ ]! _- ?# {0 D$ w
        mmc5.Setup( fClock, nRate );2 @1 ^5 U2 a; @+ T) L% x$ S
        fds.Setup ( fClock, nRate );9 p# s$ g" m, e( Q: a7 X0 P3 {
        n106.Setup( fClock, nRate );
. ^8 l5 F* Y6 J, B7 Q" O) H. Y) L- H        fme7.Setup( fClock, nRate );
& A+ @8 E; K6 P( X1 U4 c}8 x8 @. ]# `1 |& \

0 w; U" J/ L7 Cvoid        APU::Reset()+ }9 A% Q) m0 V: ?5 \3 W8 e
{2 o2 t/ v- z- h' @
        ZEROMEMORY( &queue, sizeof(queue) );% i5 Q- a3 U. n( M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 d+ V, G2 g* `6 p
( b0 N; G# m* D
        elapsed_time = 0;
" D; Z. J' E* G8 d7 J; D7 h  C2 r; r
        FLOAT        fClock = nes->nescfg->CpuClock;
2 I1 y, T' a. q- v6 C        INT        nRate = (INT)Config.sound.nRate;
5 J* _! y3 t8 z        internal.Reset( fClock, nRate );: B; M  O0 Q$ w0 Q, T$ I" F
        vrc6.Reset( fClock, nRate );! `9 J" k" Z. i* G6 U9 r* G9 @3 F
        vrc7.Reset( fClock, nRate );
$ u- g/ ]/ N  [. v        mmc5.Reset( fClock, nRate );+ z  X# t, b: i! t
        fds.Reset ( fClock, nRate );
* C; T/ q2 R1 j( k4 O        n106.Reset( fClock, nRate );
+ W; J+ V4 _" m, R        fme7.Reset( fClock, nRate );4 e+ }4 B/ n- R4 j
7 ~' x9 P3 |" r. L
        SoundSetup();
- U' q  u& J( A0 R}5 d( n. d' b2 V* d1 _- o

* L9 t1 {$ t3 u' d9 `( ~void        APU::SelectExSound( BYTE data )
+ T$ q/ C, n: |# F& j8 K# ]% a{$ O8 K: K4 `) a
        exsound_select = data;2 S, ?# T+ c6 }
}$ E) E4 J2 m3 o! E6 v- _
1 i. D/ p  d6 j* Y  s
BYTE        APU::Read( WORD addr )6 Q. X" |' L; J/ X
{
5 B+ J0 o% ?& s1 ~, ~. }& u! L/ O/ g        return        internal.SyncRead( addr );
" i% F, _! D' X7 I}8 T& O* ?1 q. o2 \

# S1 t+ E) U) X4 n! `$ avoid        APU::Write( WORD addr, BYTE data )$ p7 a1 b( {( K, B+ |) ~
{
$ O- e! w6 W: O  a6 o/ \3 D        // $4018偼VirtuaNES屌桳億乕僩
5 Y+ V7 N9 e; d& v1 ~        if( addr >= 0x4000 && addr <= 0x401F ) {
4 h+ q9 {% v2 e9 z" b( O4 k                internal.SyncWrite( addr, data );, y5 ]2 d# U5 ?7 F# b; n: L% k
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
4 m* f$ w5 w9 \. r( Y        }% d* V$ t4 \# g# N3 Z
}. W- M% K2 ?- H& ^

% C, s( d( V4 i5 v8 F* [BYTE        APU::ExRead( WORD addr )) X8 _, v/ t: r8 [/ U
{+ r2 T$ x6 Q# i# n* \# ?+ w
BYTE        data = 0;) Q" z$ d) O/ e
3 \7 U. T5 ^$ Z  K4 ~) u/ i
        if( exsound_select & 0x10 ) {: \( u; x% ]+ T% U2 ]) M
                if( addr == 0x4800 ) {, t) Y2 y  G* d; [8 Y# k, h& H
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 G, ^1 E+ V8 Q2 H; f4 ~0 {5 X$ T
                }
/ _, U3 K% q7 V& w        }
  y7 G) A" K! `0 q- J        if( exsound_select & 0x04 ) {
5 l) R. z! u/ ^0 f6 a( y( m+ o                if( addr >= 0x4040 && addr < 0x4100 ) {- }7 a" l& f9 A
                        data = fds.SyncRead( addr );% J# }+ m0 o% A& k6 h
                }
8 @1 k6 M& @/ `2 L) J- G& V  v) j        }
! s1 q8 [# w% a: c; Z        if( exsound_select & 0x08 ) {5 u& J- `5 A8 }% _8 z
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 |( v( \- x& I" R8 \  i; H
                        data = mmc5.SyncRead( addr );
) c! [; K, l) V; `" z$ m                }# G5 E- s+ z& B6 k
        }- A9 c$ D1 \% ~* }# w8 v

% {  {; h; p1 C+ a8 F        return        data;, r* c0 b$ u! E
}# B& f% N' |7 V& [: I; k5 A
  @/ f3 ]; [& ?) q
void        APU::ExWrite( WORD addr, BYTE data )7 t: [  R4 V8 A! O! j6 i5 S
{( V6 v% p) e$ v' P2 [8 e1 E: ^
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );$ Q, V7 l7 f# N

7 `9 L5 }  }& C- b: G; y- L6 v6 `) q        if( exsound_select & 0x04 ) {
" ]" U& p( |5 [                if( addr >= 0x4040 && addr < 0x4100 ) {
$ `6 i3 F- M! E9 g0 G                        fds.SyncWrite( addr, data );
! j, B) E& p* ^! q* e6 d! }4 V                }
, ]; z4 \4 c8 W2 I        }
2 t& Z# q8 [0 @
9 Q1 W+ W1 z: Q- Z3 [6 [        if( exsound_select & 0x08 ) {  h  @! |( l# K4 d7 Y+ l8 L  W, l
                if( addr >= 0x5000 && addr <= 0x5015 ) {
) N0 K: m6 W* O( F+ e                        mmc5.SyncWrite( addr, data );
# ]3 x2 L" s, z4 N! z8 r3 }                }1 `  D2 Y0 I0 E6 q. Z
        }3 F/ E) T# W: G# b% r! T
}
& s3 S/ j0 j  v& |& {& {) q
/ I( n3 n* K5 U! Gvoid        APU::Sync()
4 \- o1 {8 t; A- P. r{! l5 M! s3 G! k$ M8 ^0 s/ x+ q
}
% N% H- n* u* N
. g# Z' S7 u# y% h2 Cvoid        APU::SyncDPCM( INT cycles )
# e6 r8 s' K7 e% x( X% `& k{/ Q5 c3 ?. t2 a7 ^/ V1 s3 m
        internal.Sync( cycles );& u, @; `/ K2 v# e! w6 o* X9 o3 ^
- j- }/ t' c( I! R. G9 m, O+ q* B
        if( exsound_select & 0x04 ) {
+ Q& J, y4 i1 \                fds.Sync( cycles );
4 M; C0 J( `! `        }# v$ ?1 u- a! Q4 r0 ]
        if( exsound_select & 0x08 ) {! r7 A4 p, N. ]! \) K* ~
                mmc5.Sync( cycles );
* {- K# w5 ?% @, Q        }
/ ]- [. [7 S& I9 f0 @}3 I9 o/ E) J/ Q+ I
- ?8 p5 N% A% F, b
void        APU::WriteProcess( WORD addr, BYTE data ). ]# h# F8 a, H' c& D
{/ Z$ m4 R) b7 }8 D
        // $4018偼VirtuaNES屌桳億乕僩
% U0 I  g! n0 ]9 Q' O  j6 ?        if( addr >= 0x4000 && addr <= 0x401F ) {
  Q) {& X7 H' R  ]                internal.Write( addr, data );! {/ K/ u7 X+ }6 V8 W: u" J
        }
, _1 e1 r2 J1 Z; f9 G! r+ K: h+ m+ \}! R! x2 D# E& p) `4 Z
8 x( J* ~6 k/ U. X5 X' E5 o
void        APU::WriteExProcess( WORD addr, BYTE data )& V% i6 S1 \* d$ @; ]
{
) I% Y' g; a  N0 X6 X        if( exsound_select & 0x01 ) {
) A) H% _' W9 N! g6 k1 e) w                vrc6.Write( addr, data );6 u! N0 \; p6 ?. X: I7 e9 r
        }$ C$ @6 B- I; w% F! n" [- y
        if( exsound_select & 0x02 ) {, e# m+ Z& w# _5 N) s/ F
                vrc7.Write( addr, data );
; k1 s) T. f7 K2 u' `" {* c. t        }
+ [6 P% S! J3 H" O* o% |        if( exsound_select & 0x04 ) {
  K6 @3 ?! q2 _3 n" v                fds.Write( addr, data );; \( ^6 H' C: {. K
        }
0 I% V$ S# ]7 p- U        if( exsound_select & 0x08 ) {
! x/ @% B& b  s9 |. T. B                mmc5.Write( addr, data );6 L( K; f1 E$ u2 j" P; S/ M
        }
0 Q. z$ E, v+ g# s1 [        if( exsound_select & 0x10 ) {+ r8 W9 U; t: K0 C! o
                if( addr == 0x0000 ) {
5 E1 r$ {# V/ |' g                        BYTE        dummy = n106.Read( addr );) D, _8 F0 y- r. F  v5 a
                } else {
  A- E: P7 j9 @; T. e, D) _                        n106.Write( addr, data );- G2 F$ p% d; f% q) \3 Y
                }' c) ?5 O; R* X+ l) ~6 V4 }4 b
        }9 Y, w7 V. |) g2 N2 r# f
        if( exsound_select & 0x20 ) {2 R2 U8 {2 O/ A7 R3 f5 b% g! C
                fme7.Write( addr, data );
6 S% |  M* N9 M) m' ^        }1 n& A: Z" J. z2 I
}/ Q" Q3 }  s9 @$ E
1 b4 x1 w5 U9 a6 x8 G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
. F6 x  R* k6 t, w- f2 O{5 I# s5 z* d$ P  _5 H7 D
INT        nBits = Config.sound.nBits;
3 O2 X; Q9 z1 Z! b; h8 [DWORD        dwLength = dwSize / (nBits/8);* N: D3 T! g( B( t
INT        output;
3 E0 x3 N) w* |) ~3 y( LQUEUEDATA q;
5 t  g9 ]1 B1 a$ T4 k% G6 c  mDWORD        writetime;
" k* W/ q) Y8 h; F) Y8 W9 d% H2 q8 G" Q7 B* W: n& S2 D" M
LPSHORT        pSoundBuf = m_SoundBuffer;
$ d7 W" M3 \% L9 F: h: xINT        nCcount = 0;
: C( g0 m3 }: j; f  M; B3 G+ `- ?0 Y! G2 w( v. m( I
INT        nFilterType = Config.sound.nFilterType;
% M1 t4 d+ N$ i/ f( o- V0 ~( V) W1 Y
        if( !Config.sound.bEnable ) {8 r* U# D& U8 p+ C
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
: x; z/ r& T9 w4 ?# r6 D5 ]% i( ?                return;8 n8 s* z; b' Q" N% H- o
        }) a8 M8 L# j/ v8 x: k! p3 Q

8 p5 J6 u* `( V( R        // Volume setup$ F  p2 \; [1 `  y/ U0 d; r7 m: z
        //  0:Master" I$ l, I! m! B$ b( h. T( P
        //  1:Rectangle 1# O9 d* G+ [6 u& G7 N1 F  {
        //  2:Rectangle 20 E$ M0 v* ~8 F2 w5 }6 J+ ^+ \
        //  3:Triangle2 F+ \8 e( t  T4 {4 ^# a% a) O
        //  4:Noise
0 J9 g& \1 w' |2 F' z        //  5:DPCM, x8 Q6 `5 u8 s3 N' @# j" V
        //  6:VRC6
: N( i! r3 Y  v" q        //  7:VRC7
) ?- r$ B& Z0 g- _' p        //  8:FDS" z4 {7 _! O! u% c4 b# j2 m1 n
        //  9:MMC5
; d+ E7 c# e% I6 J& y1 N        // 10:N106
5 y, s6 x/ A" q8 `+ U' F        // 11:FME7
# h8 _8 x8 M) C8 s) Y        INT        vol[24];
2 r9 S# l; c$ s/ B: B0 n        BOOL*        bMute = m_bMute;
0 I0 i+ g0 [, l) V0 x0 Z        SHORT*        nVolume = Config.sound.nVolume;0 @4 G+ O, e1 P) Q5 t

8 N) T* d* ^0 t  b& ?' A        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 N+ }0 ~: Y3 ?( C+ `; R) H! h

% k/ \- }4 Z2 m+ |. V4 m        // Internal
0 G' N' \4 O& a7 u        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
. v3 L9 L" s0 f. N; ~        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
% v; M2 m  \- G        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
" k8 d, `  G8 \% }$ y9 M        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' N2 U: ~4 y" Q3 K        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; H0 c/ ~. m1 A7 D

2 @3 s7 h& Q' c! d6 E        // VRC6' l6 D1 y; N; l
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 y# z1 j/ i  K5 |5 V
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, t! C; ~: W' v% e  Z2 A( ~  C( x        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 p3 }1 ]- S3 j' X+ [" J& |  o
5 e, e: i! b) l8 ?  q
        // VRC7
) X* j  w" u1 Q! Z. O9 u/ \/ {( F        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 `# P. _; b: r/ W

( e7 |9 {5 h) D/ s        // FDS6 s* U& z+ ]* ~% p3 k; P
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& u4 ]' Q5 b' g) r- x
9 x4 p" V, j: M% u        // MMC51 H6 S" x# Y) w0 W0 I
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 I. q, [& f! @/ I! L$ Y! T        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 B  M- \' u( z9 O        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  z/ }4 a7 ?8 l- u# ]3 Z1 D# e8 T
/ T5 w7 t; d+ N3 ?/ {        // N106
# |+ m9 x2 U3 x( B) M; _        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% ^& A7 h9 g5 X7 j: q        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. p4 H+ ?/ u+ Y0 Z9 r0 ?        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 _) I4 M7 t" p6 E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  m* @/ d1 Y! U, d7 u7 E
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 m6 T* `0 w, |3 Y# E7 c/ ]4 [
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. O6 c. |% [/ Z2 [$ T7 m/ Q$ x
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 a% e( h9 e5 D/ w; ^        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 E/ \) P- F# K% o
$ n6 K3 p) S# L5 h$ t! w
        // FME75 [% Z4 W2 e/ R( |0 m( v
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( S3 K* Q, ?3 w7 J6 U  U$ Z0 L
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 z) ?' Y4 V0 y7 z( T. {, O2 Z2 I# t
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; ?& x2 ~8 R  s) |# x
2 s, o; p: Q; v" b//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
) V! J! ?) g* G' [, Y) A3 i        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;( x# Q( S6 `3 w% A1 U' r, e$ C
3 R- M+ _! |. g) Q5 c; P, c
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟" |& _0 o. h* Q3 r1 H! {, I. S
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
" s3 A. u& L1 X9 ?" \                QueueFlush();
, B2 G* w/ g/ }        }
) G; r1 J* g7 |$ E& Q9 r) o- w0 J8 a, s! _$ }: d
        while( dwLength-- ) {* e/ H6 r8 b- G% u; Z7 S& g: w& u
                writetime = (DWORD)elapsed_time;# t' H) i# T: S; N9 ^
* r4 \5 R, W" q+ {) Z+ G
                while( GetQueue( writetime, q ) ) {
7 W: b% C$ J9 k* |' R- U                        WriteProcess( q.addr, q.data );
4 F/ _; m# c0 e5 A; K                }
2 t. S* g7 i: p5 ?+ W7 o5 t( }& d/ W3 [
                while( GetExQueue( writetime, q ) ) {) W9 T) u: s5 ?, x1 F: `7 X
                        WriteExProcess( q.addr, q.data );7 i( e$ D( P. q: J8 }
                }9 c6 o" a' h( W+ F& l, ]

1 M/ ?. g1 b- v0 n) R                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7; D) W/ V% I  b$ p: i
                output = 0;* d4 Y; a$ h( n. ~& }/ [# W
                output += internal.Process( 0 )*vol[0];
& w: K4 x' I7 D' c/ o0 n( ~! `! O                output += internal.Process( 1 )*vol[1];
/ C* {3 C( O" d, d' y  h; u9 f                output += internal.Process( 2 )*vol[2];
+ o0 h, F. ^" I' l- d5 V                output += internal.Process( 3 )*vol[3];
, A7 J3 m* N( e% h                output += internal.Process( 4 )*vol[4];/ |3 p% y+ i" J- N
# j( R; |# \* Q) D/ o8 M
                if( exsound_select & 0x01 ) {
+ r! v8 }3 ]+ J                        output += vrc6.Process( 0 )*vol[5];6 r6 F4 f6 m- T$ x
                        output += vrc6.Process( 1 )*vol[6];- H) r6 [3 m. P, P" x. W" z3 A* A+ f
                        output += vrc6.Process( 2 )*vol[7];
& W+ }- B0 Z, s9 O: s' F4 x                }- g1 N9 [0 r0 P
                if( exsound_select & 0x02 ) {# N9 I" ^- O' Y7 E- _
                        output += vrc7.Process( 0 )*vol[8];
- J: Y- K2 Z( [7 Y! J& R' f( s. I                }! N! x; a0 ?* L# T% h8 V/ c; K( N
                if( exsound_select & 0x04 ) {
$ g9 ?7 \6 d. V( w                        output += fds.Process( 0 )*vol[9];
3 N1 l7 x( M5 D                }/ q# w! }% j' O: L! U  [+ B! b
                if( exsound_select & 0x08 ) {
3 x# X) q8 Y; L' @" k                        output += mmc5.Process( 0 )*vol[10];- `+ j2 n5 _( Q2 ]3 @
                        output += mmc5.Process( 1 )*vol[11];, U, P# R# |1 a5 K5 x- R
                        output += mmc5.Process( 2 )*vol[12];
7 }" d' @- K4 t+ {                }
* K& g/ n* @- B; Q                if( exsound_select & 0x10 ) {
, j; q6 a, |0 r9 e: _  ~: }                        output += n106.Process( 0 )*vol[13];- _2 a* W7 b& [! m# Z
                        output += n106.Process( 1 )*vol[14];
' E: y( I3 B: q0 }* `8 m6 P                        output += n106.Process( 2 )*vol[15];3 T; m7 `) j# G4 K
                        output += n106.Process( 3 )*vol[16];3 t' |) k; m, E; R
                        output += n106.Process( 4 )*vol[17];
. v8 V+ \! f2 s! h% W* q                        output += n106.Process( 5 )*vol[18];# k3 z5 c! W3 X* q6 S* s
                        output += n106.Process( 6 )*vol[19];
6 h  o; Z% k1 s% J+ V6 D9 b                        output += n106.Process( 7 )*vol[20];" f% I: D" b! Y; B0 m
                }* Z2 g; ^: C' G) D2 W2 p% j+ U2 P
                if( exsound_select & 0x20 ) {
, I; S6 b0 ]; x" a0 c5 p3 W5 h' q" t                        fme7.Process( 3 );        // Envelope & Noise
. M1 i* ?8 ?1 y9 f6 E                        output += fme7.Process( 0 )*vol[21];
* \: P% p! _: c; B! n0 n: @                        output += fme7.Process( 1 )*vol[22];, S' Y+ J: t9 L) _* z
                        output += fme7.Process( 2 )*vol[23];% |$ f: u6 q' N' L3 t
                }3 {! u, i9 l4 m. u- g" A8 a
1 q( w$ C3 G# x3 w- w% U- c
                output >>= 8;
" [4 Q; Q& o: u  w; h2 n' ?
) a4 M$ T2 r! E' ^3 x                if( nFilterType == 1 ) {* |; F2 ]% k* F! g3 b! \
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
% p& A1 O7 @4 M7 C: Y                        output = (lowpass_filter[0]+output)/2;
/ j8 p* o* ?5 x7 o                        lowpass_filter[0] = output;
, Q" o, I! O; h1 h. M                } else if( nFilterType == 2 ) {0 S/ |& a- g+ n! Z- I9 E
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
& W% P6 t- U$ K4 j8 z                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! b2 D% v; h9 r4 h                        lowpass_filter[1] = lowpass_filter[0];/ A+ ?9 E( @, o, g, g) ?1 X3 K- t
                        lowpass_filter[0] = output;
6 _2 B0 K. c0 O. [# h/ S% h1 [+ m                } else if( nFilterType == 3 ) {! B# ^) J, t( o% |% ~5 R
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ \; }8 ~& H1 b0 \! i1 ]% p                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
: Y6 {2 ]7 n8 E- m% X+ V7 B                        lowpass_filter[2] = lowpass_filter[1];/ S/ f& ?7 ?: C8 v- l% E' {
                        lowpass_filter[1] = lowpass_filter[0];. X: z& J; D2 R- G
                        lowpass_filter[0] = output;
$ k; J) a, X) r                } else if( nFilterType == 4 ) {
1 Q% h) S# k3 Z                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)$ _4 _3 R* z" J' `. {
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 F0 y9 p9 H" s( D9 ?1 M                        lowpass_filter[1] = lowpass_filter[0];2 k6 J! i+ x0 k" u
                        lowpass_filter[0] = output;) h* g, k% }! y9 Z
                }
1 Y3 W4 V6 k8 Q% ~
% s! w6 K' V/ A0 U" A#if        0% k, X, q+ ]7 e' L
                // DC惉暘偺僇僢僩
, ~# `+ R; d: m6 J- c                {
& ]/ p7 A$ Z" s, K                static double ave = 0.0, max=0.0, min=0.0;" U$ C; f' @3 K: n: x; a
                double delta;
/ j2 F3 j  u/ A% ]4 T2 k                delta = (max-min)/32768.0;7 O5 p+ S8 s& F. A5 [
                max -= delta;; }0 x9 f; A4 |  w# t# h
                min += delta;
8 E; j8 u% X1 L  H2 d! m/ f                if( output > max ) max = output;4 _3 Y4 ?- s# ^. t" `* `. t6 c- E2 Y
                if( output < min ) min = output;
5 T2 t; S) A# o                ave -= ave/1024.0;
: K. A) |1 _& e                ave += (max+min)/2048.0;7 P+ u" ~% _: C5 w2 b. T, G! V
                output -= (INT)ave;
- v& v: d2 P# n4 E                }
+ h. t3 O# t$ W#endif
, {4 j* d. [( c+ l: W#if        1; ?* J; L1 c" A7 g4 d! o
                // DC惉暘偺僇僢僩(HPF TEST)3 L: t* `9 E2 n; o9 u
                {
5 k5 g1 i" p* I9 q6 E4 j! o9 x//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 a) y* ?; @0 |& q8 }/ _                static        double        cutofftemp = (2.0*3.141592653579*40.0);' g/ J% l9 U/ j4 D# u
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
* b* `% @7 `. S, ^# o                static        double        tmp = 0.0;
' @) k, `2 ]- V- u; \0 x                double        in, out;. F# F7 l9 |. m, J: v- ]5 v

9 W7 m2 j2 j7 E, a$ m9 E" ^/ X                in = (double)output;
4 @% ]5 h9 o4 \+ Y. G                out = (in - tmp);/ N: W" e# h5 W% q1 I4 `" m1 ?- f
                tmp = tmp + cutoff * out;
; d6 C* `% g8 @2 O  t1 r/ N
: o- |' K( J0 F1 {                output = (INT)out;
  W/ v  o7 u# D4 s                }
) c+ r: W: L0 ?  {5 P# i- U#endif
/ o8 \* p6 r2 D! t; J3 F! I- {#if        0
& \+ E1 U: V- i" t" Q, ~# m                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
2 K( b+ }) q! [5 |# i/ i9 x                {
. T7 H9 t& q9 e) j% Z  @8 K                INT        diff = abs(output-last_data);# u8 ~$ [2 C( q# s: g' [
                if( diff > 0x4000 ) {
. }: ^" {& `9 ^7 B1 {                        output /= 4;
$ L% j* L1 |% j' x, @  p5 {  {7 F                } else
) r- \& h/ u- p1 H                if( diff > 0x3000 ) {
6 C7 L  U- B2 s6 F* t9 M                        output /= 3;
# `3 e( H4 ~3 ]( [  V                } else
+ U% @* T2 x; \! u- F+ h                if( diff > 0x2000 ) {
* F) G$ t5 b6 p' b                        output /= 2;
3 \& V) Y4 I' j; n                }
: b1 q8 f" e; [& _* L) Z- v+ C                last_data = output;
: T+ V, G0 r+ j" ^2 w                }. {  U6 c% \* k
#endif7 a  G# T2 ?- B% e2 n
                // Limit" L" v  B! I+ `' t: r
                if( output > 0x7FFF ) {
0 T; a2 F5 _& J                        output = 0x7FFF;
  n! z3 K6 V2 m) C                } else if( output < -0x8000 ) {' s/ d7 z) y) t) Y* `
                        output = -0x8000;
8 ^. ~& X! h7 t$ [. O9 e9 E                }! r* P- n: p6 J6 @! p- _

0 v/ B% I# }/ c  c3 f9 ?% @                if( nBits != 8 ) {
2 _, C7 ~7 }' D  w                        *(SHORT*)lpBuffer = (SHORT)output;
7 {- ~! s2 T5 @; g  ]1 G: Q* ~                        lpBuffer += sizeof(SHORT);% T% X8 v! Z( k+ D
                } else {
3 b8 D5 T: h) T8 f1 |  w" ?9 Y                        *lpBuffer++ = (output>>8)^0x80;
$ S: |* g7 X3 ?) n                }/ v; j. E$ _; e4 M0 p& T* z
6 c  Z5 z8 r8 Z: G4 D) `
                if( nCcount < 0x0100 )3 b8 Z) |& s! |( b. z1 E$ _
                        pSoundBuf[nCcount++] = (SHORT)output;# S1 W# L  V' `5 U) W, x6 A

9 G( `* j& V  k- C2 L' W//                elapsedtime += cycle_rate;
8 W2 K# _$ o0 h                elapsed_time += cycle_rate;$ U( G) u/ M# G' f5 ?0 _1 }
        }
5 X* w: b7 M" v0 j' {% ?0 q1 x* r0 L. i9 B
#if        18 b+ u- [1 t( Y) C4 M/ j* Z/ j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 N5 V' _4 ~! f/ b/ C                elapsed_time = nes->cpu->GetTotalCycles();/ S- |5 K/ s0 p; A3 q8 a% D$ ^
        }
9 E$ f& U. L0 E* S2 o, n* ^        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: K; E5 a" u" n                elapsed_time = nes->cpu->GetTotalCycles();
1 Z1 @' A4 j: D; F! X9 P7 ?" B        }
4 W' C) u* J, z7 f$ Q7 r7 w; f#else
. P% J5 `4 L4 S5 C, e3 v& k+ R        elapsed_time = nes->cpu->GetTotalCycles();
* \* s0 J+ O$ m% }) U#endif
0 {/ s$ b3 f, b}
' p" S2 k: R0 }6 [1 K$ `( |
1 o* j3 I+ r: r1 l# _// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)" `& c& o2 K+ V% T* v0 |# b, }
INT        APU::GetChannelFrequency( INT no )
& }7 I( Q; @6 D; X8 g{) Y, J9 A- J& A
        if( !m_bMute[0] )0 C6 {8 X: ~3 f% j( G
                return        0;
0 L( Z) G1 ]3 k7 L5 E4 o4 o
4 H1 @0 x- Y: i6 K$ f        // Internal
9 O' K. X, g2 `% w& {. T% Z        if( no < 5 ) {7 n9 Y  ~) v1 k# a/ L
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
+ M4 E  b, ]- b% N- t        }
' i& p5 X9 ]$ U4 p& |+ I        // VRC65 Z4 |# d2 c9 @- j. _
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
4 o% u1 q) K0 ?' {                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
4 ^- ?. ^. B' X3 o0 R  J! s        }
2 ^4 ^# u2 e2 E# y        // FDS! d5 F0 ^. ?- R8 W  V7 O
        if( (exsound_select & 0x04) && no == 0x300 ) {' O3 J% X& Y7 S9 T) n
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% }4 W: _( {& N- J) K8 y7 j' Y        }$ z- q. G/ ?3 r8 R; I
        // MMC5
' j0 \7 {, h% G4 [6 N& ^        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {8 n$ y# N; S! k: N" e
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
* j/ A/ o! C9 t        }) H0 c, s# F1 z; H) m* L
        // N106
* c+ J) z8 ?+ B5 \        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {7 q+ O+ x8 L' g8 O/ ?
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
! b/ S$ R( ?  m! {7 H, g        }
& x" _" t9 ^" R8 r; O1 W        // FME7
1 w/ l) u& z7 ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {7 \" D7 o( g9 D
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
( k3 u2 n8 j3 p& }4 o        }
8 e+ Z) F  e- |6 N6 e        // VRC7* f1 L% r+ X- R! g. Q$ ]# [
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {2 y2 K( K+ A9 v  o
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; H5 T8 X# ~5 E% D0 H
        }
9 o! U' p) ~' |7 Y% ]" P        return        0;2 }/ t1 N7 Z: X8 t$ ]& u
}+ A, s3 ]  z# u1 Q
+ \: o' F! ^& @
// State Save/Load
; n% N( z  m+ gvoid        APU::SaveState( LPBYTE p )7 O& ^1 e+ w1 Z% V+ j4 M
{
; x0 D, w- H* T! R3 g8 p#ifdef        _DEBUG
& d$ G: J  T* S( s% gLPBYTE        pold = p;
% m/ r* Y( r5 T  {  g; N1 [7 \#endif& J7 t/ L/ G/ m

9 N  q( o7 {( ]0 G5 h1 f        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞! J3 `0 O4 M2 f# f% e1 u( p
        QueueFlush();
3 F; R/ N) ]4 q5 `) [4 W$ t
2 [1 k0 }0 T' z* a: V        internal.SaveState( p );
3 e. B$ R' Q6 W+ A        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 T! m5 Z9 e% ^6 |1 K
& Y! ^3 F( I% ~2 D        // VRC6
* Y! D2 O. t" H. ]$ C# w- r        if( exsound_select & 0x01 ) {, H) V: o# U# s# }8 h7 H1 ]
                vrc6.SaveState( p );8 m3 c; m8 }0 M' \% O$ W
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ l4 V# i2 `/ Q3 a7 [: q1 |1 T, x
        }
5 J# |6 v+ v9 t# d; F) \( n        // VRC7 (not support)
. O0 t& z$ C5 I& B        if( exsound_select & 0x02 ) {
# i3 s/ N  j4 `                vrc7.SaveState( p );
; X6 C% c4 p9 v4 b# F                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 B7 M5 `$ d* v+ C/ w  _3 g8 I        }+ i& F" L: s3 y
        // FDS1 `1 S" g' h+ O+ s4 O" R
        if( exsound_select & 0x04 ) {- D$ M; T0 V$ }: Q# v, z
                fds.SaveState( p );
" @, A& ?' R3 H5 u6 M                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ v% s) ~0 C) s0 @        }" t5 i* K! M, X) n! w# E2 H) a
        // MMC5
$ h9 G* e. t2 {/ b& ]- L        if( exsound_select & 0x08 ) {6 s$ k3 A) J/ }+ ]
                mmc5.SaveState( p );
$ p  w4 ]: d: w; `9 I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding+ Q+ w' j: W* p- t/ L: `3 `
        }
. N1 k6 q3 ~- I  Y        // N106
! {6 x7 b2 ^; H9 [! O# B        if( exsound_select & 0x10 ) {$ \/ Q& e  @( D6 Q$ L' R8 S" M
                n106.SaveState( p );
5 h( q' p  r# B& m3 m/ m% T4 C6 X                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( |( O% W# w3 e" k  H9 a
        }
7 o, |2 }( w0 ^# ~7 a9 c        // FME76 q% c5 y6 X2 v: z8 [3 D- X3 _4 [( E
        if( exsound_select & 0x20 ) {- j. \6 h" d  w6 o+ Y# Z9 S
                fme7.SaveState( p );
2 x& r0 C* |1 v1 f9 P' z" A0 J                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' S. P8 H* v/ B; d, y        }
7 H6 A' H  u- V6 Z  a
& g1 J4 I% [. e#ifdef        _DEBUG! T: n. L- ?* _8 u
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
. ]# X8 s0 }! c; N# X. [#endif/ S' u8 t, P9 H  }4 e& n
}
5 \3 P2 N, R  T; e% \( H/ r, s  k. c  Y3 ?, `
void        APU::LoadState( LPBYTE p )( n( H% v# U0 Q
{1 A( u3 W# ]2 @2 Z! q- W# _
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ L$ K3 c9 Y9 [; t& x7 ]. O5 {5 }+ E
        QueueClear();
. C+ u. _- R& g+ a+ ^2 R) S6 z9 g7 S+ g) u, K
        internal.LoadState( p );. I2 x! Z; Q9 H9 b( J' `% C
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ b% ~( t  |/ ?8 n( h2 V

  p' F$ z: n; Q/ n& s        // VRC6, }, U9 L8 U- G
        if( exsound_select & 0x01 ) {5 |% s- F+ \# m5 |2 x
                vrc6.LoadState( p );7 I# Z; g$ G0 K
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 t3 B7 I3 w, j! }/ E7 @% Q, m        }5 \4 m, Z) l1 W! U
        // VRC7 (not support)
0 H$ {- \8 m" r        if( exsound_select & 0x02 ) {
4 \$ J! r4 g" P( c. O. Y1 H% K                vrc7.LoadState( p );
7 |0 @, w2 f! `. R                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, R3 h( R% `. c        }' `4 H8 p, N& N' C, C# n
        // FDS5 [: K( q  f& _4 L+ b
        if( exsound_select & 0x04 ) {
0 y4 t8 e7 D* ]4 Z                fds.LoadState( p );! T7 z4 ]% f- r' Y) ^6 m9 C+ I
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. d+ [; y) j  w+ A+ m7 ]3 n, y
        }& a1 m* N- c0 R  \9 Q
        // MMC5
8 Z/ D% e" v& ?4 E$ G2 G2 C        if( exsound_select & 0x08 ) {3 ?2 M9 H$ p. ]' L
                mmc5.LoadState( p );
7 C4 ?6 f& G% E, B# V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
/ E6 s: s# L' b        }
% l8 V2 A2 a! `  @! L! J; \# u" {        // N1062 w3 f0 u& r# t+ }
        if( exsound_select & 0x10 ) {0 Z8 r/ O0 H" s+ [/ |4 L
                n106.LoadState( p );9 L7 e+ I; z, F* o( |* ?; r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& p' q3 z; e8 V, `* ~. l
        }
' p* e% I8 @% W0 s8 P        // FME7" }; b0 j4 o0 A( w7 U$ B0 y
        if( exsound_select & 0x20 ) {
! D: b1 G9 g1 h! N                fme7.LoadState( p );0 v% Y! w2 U( }* P1 [2 j7 a$ Z9 U; |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  g0 n+ o" |5 s! q9 N# x0 L5 ^
        }) o  B  z0 k0 i; s* U
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 # A4 L' V6 T/ n+ i
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。7 T7 R5 A7 L$ G
感激不尽~~
' o. s* Z2 m  i3 L+ j
恩 我對模擬器不是很有研究,& v' t# |1 U5 \+ [5 E/ U6 T4 u$ z
雖然要了解源碼內容,可能不是很困難,
/ U$ n  b- l! _6 l; M- Q不過還是要花時間,個人目前蠻忙碌的。. G. C9 o# }* m5 ]0 o0 d8 V8 h
* B; l. Q" |+ o; s0 H
給你一個朋友的MSN,你可以跟他討論看看,
  Y! }  c: [0 Q+ _5 L他本身是程式設計師,也對FC模擬器很有興趣。+ Z$ }' h3 [/ L9 b4 n7 U0 t8 v

& z  `  H6 r; z; UMSN我就PM到你的信箱了。
  ^* y4 ]0 W; p5 `* U
1 l6 G; u8 O: X% b* |7 V( @希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 5 [; t: Z  N% v7 ~( C
呵…… 谢过团长大人~~
# d6 V3 p9 U5 E( a1 c* X

/ \; C8 X  F, ~哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! p$ M$ {; n8 j% y/ r
团长的朋友都是神,那团长就是神的boss。
- `" H; `) W! g8 N
哈 不敢當,我只是個平凡人,6 Z; f! b$ |, G1 y
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙7 ~4 U, k# c+ n5 t+ O$ W
ZYH
) e1 S# q# J* V* TQQ:414734306
  a, [0 ?3 I8 e2 D5 YMail:zyh-01@126.com
1 T2 A) g0 d* [; w6 P( r) l# E
6 {" J9 E- w8 O9 _, J他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 + O5 f2 S0 h8 b2 {; n) z
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ c4 J2 R. K2 p9 P% J7 |7 H/ b8 v
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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