EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ n6 Q) @. Q; @  Q/ ]1 n  z+ E楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 O4 |9 Q. {7 x7 t这里有相应的模拟器源码,就当送给大侠了~~
- \2 V: x; P3 p4 q8 `/ b- ohttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : A2 L) x: f0 T
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& d1 M8 W2 q- _楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~6 N- h1 x* C) ^) v9 W2 D) X
这里有相应的模拟器源码,就当送给大侠 ...
* N% G* V2 t' L1 {3 {
聲音部分(Audoi Process Unit = APU):
. j: D# c. k/ ^- y2 [.\NES\APU.cpp
- f; i- |5 `: y$ ^! j8 @( Z0 p.\NES\APU.h( o& x! W* N. K4 @

1 n, f: k' p  u; J0 G# C7 ?+ W1 n* c# }- O' x# M" d  `
影像處理部份(Picture Processing Unit = PPU):
' t* c) Q( J# K0 _.\NES\PPU.cpp
: w0 y% {+ d1 U5 [.\NES\PPU.h: y! \/ W/ {3 F0 F3 ?: u3 w
: l% P! ~: W3 J7 m3 j
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:* x) D/ D# B- H5 Y' C
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
+ Q* `% _" e+ z4 w//////////////////////////////////////////////////////////////////////////% X+ U3 S' E; ]& V) Q' O& Z& d
//                                                                      //2 p+ V" l& W; L% p: e
//      NES APU core                                                    //
3 F$ ^. P/ T% }" x  @//                                                           Norix      //, {+ r7 T0 R& p2 l
//                                               written     2002/06/27 //& k' [5 g6 h0 R& E. e
//                                               last modify ----/--/-- //7 n+ B& F" G4 Q, T9 V& g& Z! K
//////////////////////////////////////////////////////////////////////////) w; ?7 x9 Q! j. ?$ g$ I
#include "DebugOut.h"
6 D* L& e, H/ v3 k6 \# R#include "App.h"
. [+ C8 P" w2 [3 x. P/ {0 n, U: W$ {5 B#include "Config.h": w% u9 i2 d6 j0 a

. Z" t( Z# j8 b0 i1 r; i; ?#include "nes.h"
2 O$ s2 _/ a8 x. g1 r! _#include "mmu.h") T6 s/ W5 F+ c1 D, L% i- E
#include "cpu.h"
0 P. \; u+ o; K- G* n#include "ppu.h"
( z7 q- I0 \4 Y+ \- J! R#include "rom.h"2 k# c3 S4 Y0 ?
#include "apu.h"
5 T; J5 [0 ]) x# a8 ]$ T# n1 E2 L
# l( x% C; o9 X6 V, n5 P# a// Volume adjust
. }0 I# ^+ q/ M4 ]# q// Internal sounds5 p# }3 r. b- Y: g- |6 X6 V
#define        RECTANGLE_VOL        (0x0F0)* J! o6 ^  r. t0 a
#define        TRIANGLE_VOL        (0x130)1 F# A. u- A6 ^. |
#define        NOISE_VOL        (0x0C0)
$ I8 I5 T" W& B: P% R+ j/ g#define        DPCM_VOL        (0x0F0)
+ Z( P+ Y' D( l' G6 y' s// Extra sounds* {6 h2 `5 Q: B8 `/ b& l
#define        VRC6_VOL        (0x0F0)# k3 j( w  w% L8 U8 ~
#define        VRC7_VOL        (0x130)) R( y! b8 d) Q( E7 Z9 J
#define        FDS_VOL                (0x0F0)+ z7 l) U& y- S! d  c& ]
#define        MMC5_VOL        (0x0F0)
( \6 \7 E% g/ s; y#define        N106_VOL        (0x088)( l0 a) r) r# S* v! Y
#define        FME7_VOL        (0x130)( O4 x  u/ t6 _- B+ }3 J* f
) C% @3 }$ M9 T' r3 B$ M, q
APU::APU( NES* parent )
6 n# N: k  O' F2 i+ I+ W" C{% g$ q* P5 ?  w/ `
        exsound_select = 0;
/ R. z& C5 R0 |" m) v* |7 \5 I
        nes = parent;5 {! v% ^" R, k+ `  @: P% i3 M
        internal.SetParent( parent );# K) o8 ~% ^3 u" p2 O( l: o4 m6 Q4 N
0 M, q  w2 p# ~, L! b) p
        last_data = last_diff = 0;2 A7 Q- f5 k+ l: [

/ A0 \* g& M, \. r* Y        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( h9 C; g3 x) Q3 R* W3 z) H
5 U% a4 n1 P0 C: A2 j! w
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' O/ z2 d+ ~9 \/ y; X, @, U7 a
        ZEROMEMORY( &queue, sizeof(queue) );/ k- R# E: C9 v3 H; A$ {; T/ I
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& ?/ X5 P& Z& B  t* B& t
# ~* C5 \, h& J; w" q8 F        for( INT i = 0; i < 16; i++ ) {- w* K' L( v; j* J+ J9 ^& |' \
                m_bMute = TRUE;
7 E3 r/ T) a$ j( e        }
1 Y3 j% o; b3 |* ?4 b' o}
  t& y' J: O" q( z$ c0 Q# [2 U, g* U" q) e8 R
APU::~APU()
! x7 o- R% a3 z! }9 X* {+ }{% t3 L$ q9 |. f' i
}
& }2 r0 Q! g5 G* }+ a. l; I% o+ M$ _# b8 `
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )# [/ F5 G* f1 N( ]( ?' u, j6 c
{
' d' }' u  }) j/ {' O        queue.data[queue.wrptr].time = writetime;
! z% h" j" C4 A1 H, l        queue.data[queue.wrptr].addr = addr;6 r4 g; ^/ B: @
        queue.data[queue.wrptr].data = data;
" b( J8 g, e. N( H        queue.wrptr++;
/ p8 S! C7 U+ `0 C' @        queue.wrptr&=QUEUE_LENGTH-1;! h% s5 _; v: `% {6 w% Q
        if( queue.wrptr == queue.rdptr ) {. L1 \5 S9 m$ |! v( U
                DEBUGOUT( "queue overflow.\n" );
; R( d* x0 t3 F& R5 u. g        }/ \9 R& P3 l' D5 E* @$ r# l
}8 o2 ]; t2 r  m  _

$ f" S" K, ~0 ?9 ?4 f. hBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )6 k+ ~3 F3 X% o0 d
{
3 d! x/ T: l! q        if( queue.wrptr == queue.rdptr ) {
- k- S. k% p5 G: q                return        FALSE;& \5 G7 [* E, e  x* {! x2 ~
        }
& m. E! W( X- i; \8 a        if( queue.data[queue.rdptr].time <= writetime ) {
. l9 l% F) p4 F6 ]8 [8 M1 W5 `                ret = queue.data[queue.rdptr];" I( U0 W  f+ l( @0 L2 N5 |/ T6 v3 L- Q
                queue.rdptr++;  O' g" N: A5 }6 h) L0 d
                queue.rdptr&=QUEUE_LENGTH-1;
! S& M8 e: r9 \, N: k! @) M                return        TRUE;) Z( U1 a3 b7 C; h
        }
7 ^7 I! h9 w0 t9 [: J7 h/ x) H        return        FALSE;* v& p* s2 N0 v1 h
}5 m& T2 Z/ M; H, v7 M- e

. ^& H% b1 ?3 ~5 `void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
3 ~" W$ A7 o5 n- K{
4 R- w) t# u- p        exqueue.data[exqueue.wrptr].time = writetime;
1 ]# \8 i' g# T& k0 s, P& F        exqueue.data[exqueue.wrptr].addr = addr;6 g+ U1 A4 y4 `% `9 Z) Z$ O' L" d
        exqueue.data[exqueue.wrptr].data = data;
/ M& v. J" P: V) X) u9 P        exqueue.wrptr++;
+ w6 E& C2 t' _' ]5 Q        exqueue.wrptr&=QUEUE_LENGTH-1;! g0 a$ ]9 |% c, ]
        if( exqueue.wrptr == exqueue.rdptr ) {
- O/ C% j8 W! Q" J+ x8 w+ N                DEBUGOUT( "exqueue overflow.\n" );
. u! S& d, w0 y6 _. {' E, t        }
- K6 q1 m# m/ T9 i& W}$ B% f  c$ \) J8 F

( Y) T/ G3 e0 C6 o. tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )3 ^  U' O4 m$ z3 d! m
{
4 Q6 F# G6 U6 N  ?        if( exqueue.wrptr == exqueue.rdptr ) {' W9 \+ a5 P/ U+ X- W* x( c# s
                return        FALSE;
4 M* g0 m6 o- @, ?( H/ U# C        }
) y. f; _& m, H8 u        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 Z. N. ?- a3 ?& T                ret = exqueue.data[exqueue.rdptr];( t7 w. o* N5 }! t- x9 H+ x
                exqueue.rdptr++;
5 X$ R4 x3 |. N+ n5 k& t& p% q# E& t                exqueue.rdptr&=QUEUE_LENGTH-1;; v$ S1 w* J& p7 V- f
                return        TRUE;
& G2 E" h& z9 ?; ?* N* G        }
; O" m- x& J* ]" N+ f4 a        return        FALSE;; {* T0 v( {. ]3 S8 x
}" s9 D, X& @5 y+ W3 [5 [0 p* Y
8 J0 c. w8 \  q4 ]  |, _
void        APU::QueueClear()7 z0 q% M, y1 d9 u/ w
{
3 @* m5 B0 Z' f        ZEROMEMORY( &queue, sizeof(queue) );- R% S; a6 }* T# w9 \/ D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) T/ L/ m( r) V" }, Z* u  c}) x! k3 B* S( b  Q. c

' w9 s! G6 R$ I/ `void        APU::QueueFlush()
9 H2 A1 E* R$ M  ^{
/ u1 t: Z4 X- M; J) c5 C$ D& x        while( queue.wrptr != queue.rdptr ) {
2 s: B- r: b$ Z0 U6 g) d5 x# I. ]                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );  O8 b' W/ u5 \( J; k% f' D
                queue.rdptr++;
' O: V7 b) n/ f' z                queue.rdptr&=QUEUE_LENGTH-1;% u0 h4 o5 S/ t, x2 e2 X1 d
        }0 c  s& O% h) K

4 }- ?; \- E: Y$ g        while( exqueue.wrptr != exqueue.rdptr ) {
6 T1 U5 h/ r5 A; Z, I' n! }                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );4 ]; p- |- Q7 p3 l" z
                exqueue.rdptr++;
$ v- S7 _' A6 g  X7 O. v  w" z/ r& j                exqueue.rdptr&=QUEUE_LENGTH-1;! y: U( E7 ~& f) M
        }
0 Y9 t) Y& E+ K% o}* a( j! }$ n$ u6 v! K# I" @' ?2 ^
; J7 r3 w  R# d' K& C, T
void        APU::SoundSetup()0 M, S: O9 u* G8 t- O! q' J
{+ @- X' X9 h1 a8 W
        FLOAT        fClock = nes->nescfg->CpuClock;
: P5 J2 M0 @  p+ q( o/ I5 X        INT        nRate = (INT)Config.sound.nRate;
& J# x# u( ^4 W) l+ H        internal.Setup( fClock, nRate );
# e9 S! C" L9 F        vrc6.Setup( fClock, nRate );
5 F8 B' S4 F! T2 N( N+ R# k        vrc7.Setup( fClock, nRate );
0 R6 y, z0 H. `7 e; j5 d        mmc5.Setup( fClock, nRate );7 Q$ [$ {- R. k+ B7 L
        fds.Setup ( fClock, nRate );4 P  D0 a' j7 q5 k
        n106.Setup( fClock, nRate );9 t( `( F( U' h) f* I
        fme7.Setup( fClock, nRate );
* C/ V5 }: r! `7 |3 V, F}
! w0 m9 h; \6 d6 Z
+ A# A+ X9 ^2 u+ k" C' r* u; Svoid        APU::Reset()* W+ ~8 N$ p7 r$ G
{
$ w4 y% S4 W: v3 f. |! h        ZEROMEMORY( &queue, sizeof(queue) );1 O8 g& W( ^! i2 s* |) O3 n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 r5 n) q7 T; s2 ?8 \+ b6 \

) F8 ^; B. {: R* A) A3 l        elapsed_time = 0;1 h) ^$ n1 C9 e" F7 v# `

# ~& R( R. E  T5 c3 B4 v        FLOAT        fClock = nes->nescfg->CpuClock;7 w- F  T9 W/ Y
        INT        nRate = (INT)Config.sound.nRate;
: l9 ~) e6 U0 `. T        internal.Reset( fClock, nRate );
0 U+ c: `" J" V/ C        vrc6.Reset( fClock, nRate );( @  ?% n' }" T, e  ^
        vrc7.Reset( fClock, nRate );2 b5 s6 P# w8 a$ e( l) B4 U* x: W
        mmc5.Reset( fClock, nRate );
# X3 F) ]2 G7 L0 V  \        fds.Reset ( fClock, nRate );
2 ~, V# Z. u0 G' E+ g  Q        n106.Reset( fClock, nRate );
% E# Z5 k  n* M. ]        fme7.Reset( fClock, nRate );! V0 @" a2 y' C4 X& I
6 G' u# _$ r5 H+ t  @$ x
        SoundSetup();% ^  x+ y. ^" M4 f, S* z4 F
}
& r( i9 ?. C' ]  a3 h
6 Z7 f3 a' P& d, V. z( {: w$ fvoid        APU::SelectExSound( BYTE data ); L7 m. Y$ R+ _2 {2 V+ j) D8 T
{
+ l: }1 Y/ M5 |+ w0 V( a        exsound_select = data;0 o' l. S) v* ]5 p. M- {
}- h& N* i0 X4 l
' O  T% ^' k0 j1 j7 D7 x# J
BYTE        APU::Read( WORD addr )" I* X, \9 K4 H
{; r7 ?2 c+ Q9 Q
        return        internal.SyncRead( addr );, _/ q3 ]( j2 O5 q
}
9 |' a2 x1 k: \- x- v. r) e& p' g: \. [7 I: O
void        APU::Write( WORD addr, BYTE data )
. m- m5 p' ?7 Y+ N; A{' t6 R3 O( i" l7 A3 }7 o, J- b2 x1 `
        // $4018偼VirtuaNES屌桳億乕僩
8 h: P7 W% c- T% T' @4 b        if( addr >= 0x4000 && addr <= 0x401F ) {8 w1 h% n3 V, N& p: N
                internal.SyncWrite( addr, data );
4 {8 H# }& v- g0 R5 F5 q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
5 h7 J; F# I) C% y4 i        }
" \* o+ M# F1 k$ R' d3 y}* Z2 y$ L& B" S4 b0 D9 P

3 }* ?9 V7 R$ z6 X5 ^) {7 BBYTE        APU::ExRead( WORD addr )! d$ B: \! j7 P5 {
{
9 N7 u, P5 ?2 r( M- I/ cBYTE        data = 0;% F. w: l8 E* t( o1 Q+ M1 z. N' Q

: Q5 I2 Z- F8 X; t+ F. ]5 j        if( exsound_select & 0x10 ) {6 w4 G. {. c3 K) M
                if( addr == 0x4800 ) {
" O0 _7 N: ^0 M, F                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& ^& K( f5 Y$ O+ H" a
                }2 r8 Z# S: s; m6 j
        }/ }! B3 z8 C( J$ x% g! l# R
        if( exsound_select & 0x04 ) {3 k, }1 L% s" A, B8 i/ Y
                if( addr >= 0x4040 && addr < 0x4100 ) {
) D' e8 ^  T" N9 F1 K7 C# [                        data = fds.SyncRead( addr );- ]4 R  x6 M' f) v1 X) _+ @  a. g
                }
6 g$ v6 ]8 P8 _8 k        }
# p; r/ c4 k9 Z$ p) z# S        if( exsound_select & 0x08 ) {
4 P- Y4 l! [4 i  c' W: |) @7 R                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 _: B8 n7 [8 v" y! E* o                        data = mmc5.SyncRead( addr );
# T" g! c& X5 }2 V. n; a                }1 ?8 e+ P  J" I( a' w
        }
' s! [  f* R9 I* K  F
  [$ _. G. e/ I8 T+ Z( b& H        return        data;
! y3 O4 d2 L" @3 k3 j}
% V' \- T; @% o1 |7 m% f6 S* F$ J4 j: K' N% m
void        APU::ExWrite( WORD addr, BYTE data )
6 {# [) `' k5 s+ F& U{/ t4 i! D" P$ X. C; Q  b& f5 g
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );' M" V" ^' D6 }7 d0 w' u
1 o! I3 f3 ?8 \; D) [% m
        if( exsound_select & 0x04 ) {9 B! S" {5 z. E2 N, V$ b
                if( addr >= 0x4040 && addr < 0x4100 ) {- O+ ^' _, I7 @0 T
                        fds.SyncWrite( addr, data );* L3 _% ^- U0 Z! O0 R, d+ W1 V; ~- s
                }2 }* X7 t; T* A5 p5 r+ o
        }! C8 |5 b& [9 z& S" I0 O! L
5 o: e. X% Q* A9 `9 q
        if( exsound_select & 0x08 ) {
6 s0 L' ~% I3 z1 P3 `4 R                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 P) |5 s, h& O                        mmc5.SyncWrite( addr, data );& M' }5 g  K; i3 R3 }
                }0 |0 ^& e  P' @/ i- e7 V
        }, s; Z* G5 Q# }- {
}
& ~6 a) r# B; ?& Q- v6 C+ Z( P0 |9 K2 t9 F) O
void        APU::Sync(): `* Q' n1 @0 k$ E# _) X9 g
{
; k* c* Y& j5 S5 k3 a8 x/ N5 G2 m}% s6 E' U4 a$ p# t

! `9 {9 _0 m# G/ F3 G0 T3 avoid        APU::SyncDPCM( INT cycles )* \3 Z' l) j+ }* V" a; e8 \" B
{
8 I" ~2 I) m9 m% |* ~1 t$ H: H& {        internal.Sync( cycles );
+ m, R6 d; f, E  C& o% F) ?0 y* ?% l9 z% W' w- f% d; l
        if( exsound_select & 0x04 ) {
7 g/ n  [7 y; O1 U& E8 h                fds.Sync( cycles );9 {6 B1 t6 H% O/ C$ @6 x3 D
        }
( J6 J2 J6 _  E/ c        if( exsound_select & 0x08 ) {
3 b2 t4 J) _3 J$ n1 `9 a" K  O                mmc5.Sync( cycles );7 `5 I8 j/ V# Z  A1 A
        }1 h  a3 K' W+ s* C0 G
}( y! I$ D" I  o% A; P/ w7 ]. W5 k8 T) f$ D
/ I0 S- D- M" L
void        APU::WriteProcess( WORD addr, BYTE data )
1 h. A7 H2 ?/ L{! R( V7 l/ q3 q+ F7 ]( t# A% n1 ?
        // $4018偼VirtuaNES屌桳億乕僩& i3 n: V$ k! g- S+ X' n
        if( addr >= 0x4000 && addr <= 0x401F ) {& k  ~. C' i" e/ a  V3 ^
                internal.Write( addr, data );
0 @. g4 ~  w2 V7 G        }
3 @$ W  Q- D2 \, u- ]}
- E" g& @6 s* w/ B7 J3 [7 d
/ m7 n* I0 T7 I6 \void        APU::WriteExProcess( WORD addr, BYTE data ), y. f, F" b; a% I! F: s
{( U1 G! [+ v3 f2 i
        if( exsound_select & 0x01 ) {
$ ^$ a$ U5 i2 O( `1 `6 O2 |0 n4 F                vrc6.Write( addr, data );/ n" i) ~; e5 O4 d/ Y6 q  F
        }! `6 q, k8 A. k7 }
        if( exsound_select & 0x02 ) {
" X) v/ v0 d+ T$ v                vrc7.Write( addr, data );/ C+ D$ f" y1 y; h4 q. f. P" Z
        }; Q+ y( j4 f. g* X6 h
        if( exsound_select & 0x04 ) {7 c5 s* U. n! u- n
                fds.Write( addr, data );/ Y9 L: j  i$ d, Z' @! _& M
        }9 h' X4 L$ r, J% ?( b( H) @
        if( exsound_select & 0x08 ) {: M; S1 l9 `& @; i
                mmc5.Write( addr, data );
3 V4 f. H6 O8 O7 M5 T6 X! D        }
5 q. i" h1 N8 c$ v$ X/ _        if( exsound_select & 0x10 ) {
7 p0 }4 p  x/ r5 J+ O. w; w                if( addr == 0x0000 ) {
- T/ _) H6 _0 @) H' N                        BYTE        dummy = n106.Read( addr );
! A8 y0 `) w! d- S! i                } else {5 W" O- x! G7 T) w4 C- J
                        n106.Write( addr, data );) [* M- A, |: U+ ~* R
                }$ R+ a+ q% V6 u7 N9 a+ ]: f/ H: N
        }# J% w0 z8 k$ o2 ~! f
        if( exsound_select & 0x20 ) {
2 }! z; [0 G& c. O+ D5 y: F8 F9 w+ R3 P                fme7.Write( addr, data );
9 [$ d/ M" y1 U* s        }
1 D. g( j$ }& }& I* ^6 d! |3 L}
0 o5 C6 ?# m7 x6 K: o) J/ J; @  [' l& B! Y& Q, o9 q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ): g9 t$ G8 M* m4 J4 f( h
{3 c/ ~; n5 P- U* D! U. a! U
INT        nBits = Config.sound.nBits;
3 i, d. }+ C! ]8 U" S, BDWORD        dwLength = dwSize / (nBits/8);
6 n$ a: Z: j' a) gINT        output;! [9 b6 J' ]7 K$ z5 L$ r' x
QUEUEDATA q;% m4 `# H- I7 u- I
DWORD        writetime;
9 W9 x3 G+ Z# W% Y* o9 r, N' g( v5 K
LPSHORT        pSoundBuf = m_SoundBuffer;8 D2 D2 b( c3 }/ x8 Z
INT        nCcount = 0;: F# f. R( @) g) H

. F8 ~3 c& T7 k( B- sINT        nFilterType = Config.sound.nFilterType;+ {  k" L' ?& ?6 `5 P% r
  m1 Q4 s) K5 z2 w
        if( !Config.sound.bEnable ) {
6 R& ]5 y* O: O; w$ F; Q4 h1 X                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
& G% R5 W( Y2 _& V+ A# u! j4 Z                return;
6 Y+ Q2 M# f; C8 k        }
' O6 v8 L8 t. y* _/ _- z. x7 v8 a. y% d3 \# M
        // Volume setup% n8 n' E+ h6 o  W/ L4 b' m
        //  0:Master
' \5 Y* H6 U: K0 s/ [( }7 K        //  1:Rectangle 1& o% Z4 F0 q  U' T" Q$ h" s" D
        //  2:Rectangle 22 J8 |7 v: c6 `& c5 e; v
        //  3:Triangle
, q* Y! }+ F4 M        //  4:Noise
: Y6 X: V( |' O        //  5:DPCM
1 _' ]$ L$ o1 t0 [( l6 A        //  6:VRC6
$ ^- w. F1 \$ L1 K' ^& F4 g; ?        //  7:VRC7
/ J8 I2 Q5 u7 m! R: b        //  8:FDS* L2 c6 V7 y( v  Y; h8 G& p
        //  9:MMC54 v) \% r9 a9 Y) b. q: B, |4 c
        // 10:N106
, i* w& C' m; p/ b        // 11:FME7, o6 r# O, W% d, A
        INT        vol[24];9 s% V# Z& F& }- D4 `; R' k
        BOOL*        bMute = m_bMute;# u  c9 U7 ?/ e2 G5 J# x& ~
        SHORT*        nVolume = Config.sound.nVolume;
8 ]- X+ _' |- D) E) b' K
7 [% u8 J; O3 u6 |3 N& m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
; O8 P4 Y: Q  K* h- ^$ Y2 ]$ P# D# g  E
        // Internal2 p1 i: ]" t0 z- {2 H
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
" a! K8 ^' x8 w  o        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& v0 z( ]# ~: f: v5 j: d        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;! j; Y% ]( i6 p. m4 S, u
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' i# I0 u  |8 o' i* g: m
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;% W  e+ t* m7 l  S  M+ o5 G3 Z$ E

% M& x7 }2 ]7 e* \        // VRC6
9 n  g- C% N  @; u& U  B  g& H) a% \        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 F# m' i8 R; z: N% |
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( a: U9 V: p5 n4 I7 O* |7 O
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. M' b0 E. I, W& F, U, X
4 `8 ~5 ~% ^3 j; J
        // VRC75 n: @) v6 v4 L1 C
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;6 W$ i5 j) s6 O( `# W5 A0 j

, i# s5 x; U4 P4 X        // FDS
2 Y: V. U0 V5 q        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 c, N# r- O  D5 L
9 f" H1 [; r) {: ~& `- k
        // MMC5
0 i% C4 C6 [5 S! R        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ ^9 o' R1 ]# t3 j2 a' Z$ b8 M3 r
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 x, ]- b1 I+ R7 x2 E: X
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# G& ]/ {& |1 k- j/ p/ x( n* J; t9 \2 B) e- Q  p" U  K
        // N106* A$ n! W7 y# G& j
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; l. o) S$ I, }& w/ y" e        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 y* ]7 p$ g; A' M
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: O- W4 ]4 `2 W        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 E5 z) J' S7 Y        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# P1 `; P: Z) _7 B        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. F+ }. ?* p2 E7 p. v6 l$ a
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% G# n2 i7 h9 U4 e8 \1 o  @
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: H/ P) C3 }3 m! s3 j& I

1 u/ z% `6 l8 j2 i! S' P6 |: {        // FME7# I$ q  X( L8 c: f. _  \; X' n
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) B/ h( s" C+ M' Q$ R
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 X  ~: F. ^6 m5 D, k- N        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 i3 U+ V. M! j  l9 K) \1 |4 C7 z8 G& A3 D
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
6 U: c8 T( f4 H" K8 x* k        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 F9 s+ S3 T' m9 E8 V9 u: ^+ \6 N% F" G1 @  v9 L
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
& ^& i  |  t) W6 P        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
8 F; H- K/ F0 M2 n2 t* i                QueueFlush();4 o4 E0 r- _# V& Z4 `
        }
8 t2 K4 C# m' S$ z. F
  ]3 \5 K' W( C4 F4 a4 ?9 v        while( dwLength-- ) {
9 W, |, k! R" x2 M/ p/ A0 y# r: k7 G                writetime = (DWORD)elapsed_time;
* [: a; u" h) @: z! |! }. T6 g* ^, e) h2 ^
                while( GetQueue( writetime, q ) ) {4 c$ y8 f' i& g+ k9 S) ]9 C
                        WriteProcess( q.addr, q.data );
/ {4 u: A) A8 _! S                }
8 T: G& b+ ^  w; U9 s- m) e! @5 O: p7 y4 s' I- G
                while( GetExQueue( writetime, q ) ) {+ g1 n9 M: H) h/ \8 f; f# E: }  b
                        WriteExProcess( q.addr, q.data );- T! _4 V. }, n  O/ z& i$ Y) H" p( e. ]
                }
6 _! i% r, B$ k: A0 R
4 N( P7 R& X- ?' }3 s+ J( k6 K! p                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
1 ]5 U8 T( y' t2 K8 a                output = 0;
9 n8 H  y' c* R( w                output += internal.Process( 0 )*vol[0];
: p2 e1 U0 k$ u$ a" L                output += internal.Process( 1 )*vol[1];
, U  _% K8 }! Z) m; F6 g! t) J                output += internal.Process( 2 )*vol[2];! t1 m- `# A) K5 A& t9 V& b5 w" B/ c
                output += internal.Process( 3 )*vol[3];" {) n/ X( J% s
                output += internal.Process( 4 )*vol[4];  e8 r, j$ N& A& H% c
2 L% j, R; |' N3 f3 j" L" m
                if( exsound_select & 0x01 ) {) J( N  ?# Z- A& M' U+ ]
                        output += vrc6.Process( 0 )*vol[5];3 m+ h" v6 a# j8 Y& _* m
                        output += vrc6.Process( 1 )*vol[6];
4 F; Z& H9 x( _9 L6 [( h- f! A                        output += vrc6.Process( 2 )*vol[7];9 h; u4 ~+ ^3 _/ q
                }
$ }- ^6 X, g7 `  G+ D+ C) f                if( exsound_select & 0x02 ) {
  e1 P" M' s8 n* a                        output += vrc7.Process( 0 )*vol[8];
6 @; N1 m. D" z# v% J, L6 W                }
. V0 e: ], z; G; }( U                if( exsound_select & 0x04 ) {
+ l5 |/ t- X/ P% r1 q0 z                        output += fds.Process( 0 )*vol[9];
/ Z  j7 p6 [3 t. q                }+ e8 m& ^( {0 J0 {1 q
                if( exsound_select & 0x08 ) {2 K* i  u2 p; e
                        output += mmc5.Process( 0 )*vol[10];
, X! E) }! \8 L& r, \3 U                        output += mmc5.Process( 1 )*vol[11];
5 T) I- d* }. D/ Y2 t* c0 w                        output += mmc5.Process( 2 )*vol[12];
' z9 s1 D, ?! J, E7 Z9 S                }
7 D9 L: _, N4 b' D3 p; f* y- A                if( exsound_select & 0x10 ) {) k- W) |# ]# n2 R! _2 Q
                        output += n106.Process( 0 )*vol[13];' J" C9 q6 u: z, j
                        output += n106.Process( 1 )*vol[14];
! }9 Q; N# {. Z! w0 Y6 }, e! d9 |                        output += n106.Process( 2 )*vol[15];% n! B; A4 ?: P, `; [7 p3 b" |) B
                        output += n106.Process( 3 )*vol[16];" |# |8 a( a5 ~% C. ]! C4 h  q4 j
                        output += n106.Process( 4 )*vol[17];
( g* v% I' n' @0 c6 R% g; M                        output += n106.Process( 5 )*vol[18];
9 T1 X. Q0 O. b" b# l                        output += n106.Process( 6 )*vol[19];
  I& u% \( I4 e                        output += n106.Process( 7 )*vol[20];1 ~* f: t' ~, O! c
                }" K/ z2 T% ~1 n! m
                if( exsound_select & 0x20 ) {; p9 ~% A+ h  W
                        fme7.Process( 3 );        // Envelope & Noise; E( c9 L8 j( u0 H2 Z- U
                        output += fme7.Process( 0 )*vol[21];
: L) s! J. [- z7 b; n( U                        output += fme7.Process( 1 )*vol[22];+ i# g4 S& d2 ^! a2 b1 y
                        output += fme7.Process( 2 )*vol[23];
' `% k  u% N  ]                }
4 d" W0 O8 j! [& r+ U1 r, d) ]+ l$ R- R! F
                output >>= 8;" F# V' m4 H1 g' ~2 Z2 `, B

# t! m% x+ B8 p3 A' R                if( nFilterType == 1 ) {
- {% Q- o/ b/ T) @, }8 f/ `1 P                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)- O# S% _4 s1 z
                        output = (lowpass_filter[0]+output)/2;' @) H. b1 H* t  K- C
                        lowpass_filter[0] = output;) Q' x0 c+ X9 [* G  O1 B
                } else if( nFilterType == 2 ) {
7 y  p  B% e5 d- z( m8 T( r% x                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
6 U) A% B7 \5 N* y; J: S% P                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
( [% r) H) d  _' i                        lowpass_filter[1] = lowpass_filter[0];
/ S& w5 o$ Z9 @                        lowpass_filter[0] = output;% Y# {2 m/ J/ }- a! X) O# `- f
                } else if( nFilterType == 3 ) {
7 R9 ~) i! g) ^; m1 s7 U: j                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' p. K; p  ^7 i8 r                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;6 {" t( ?: Z' M) G) q3 V( _: Y
                        lowpass_filter[2] = lowpass_filter[1];/ i  b# m# A' p. L: @
                        lowpass_filter[1] = lowpass_filter[0];
: W1 E" ]3 |  F6 K1 Q                        lowpass_filter[0] = output;2 W+ a- s5 g5 \( Z8 U: ?' j  `* ]
                } else if( nFilterType == 4 ) {3 W: |# l; I" o* d7 P+ M
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 N' y. m9 Q0 Q2 j8 q  V5 p& V6 x                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
3 r& A5 Q$ \0 Q2 N                        lowpass_filter[1] = lowpass_filter[0];1 z& H& l. g: F( F: {2 f. a
                        lowpass_filter[0] = output;
% N5 ^% s: M3 c                }
. A2 ~% {; ~# P) I$ _* B
5 F1 w! C& u" O3 K8 J#if        0
3 `+ K% S( C, y7 V1 m                // DC惉暘偺僇僢僩& g1 b( F2 h; g- [1 {
                {2 \8 D# o! J- t' q
                static double ave = 0.0, max=0.0, min=0.0;3 R5 s% M- n' ]$ Z  u  |
                double delta;
+ Q- }  s, G& U! S# Y+ I                delta = (max-min)/32768.0;
9 A. J+ Z$ [. i                max -= delta;$ z/ @& W3 e; I% `! L7 |9 i5 a1 L
                min += delta;
4 w5 C( F9 K; Q9 C                if( output > max ) max = output;
! i. N" I* E3 C  A- n: o4 N                if( output < min ) min = output;7 h* _  l1 n! A! q4 J
                ave -= ave/1024.0;
7 {+ o$ f* Q9 D) i4 k                ave += (max+min)/2048.0;
( r; k" {2 f! ]# F                output -= (INT)ave;
3 O) s7 N# h" m$ R                }
8 h# n' \6 f/ F7 d: H8 p% a#endif
, z: B' r5 C( ~8 Q, R1 H( Y2 @% ^3 x#if        14 F5 e6 t- U5 K! m
                // DC惉暘偺僇僢僩(HPF TEST)
& j  n2 X  K; Y+ E6 Z  L" ^' Q                {
! h$ e/ J- P2 a2 v* ~//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 B. k6 V) Z9 n' Z$ j9 F, T' L8 z                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  U$ d4 ~, s% Z. _8 \                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 A2 _8 X' G9 D  B8 @                static        double        tmp = 0.0;
' o; p3 O+ k, Y: k# k                double        in, out;4 Z/ }- l" s5 I
( t2 c; k9 `# R% {- x9 x' U$ g
                in = (double)output;) e2 ^- n6 _. K9 a" T
                out = (in - tmp);
1 g8 R. B. ~. h$ J9 o                tmp = tmp + cutoff * out;
- H8 Y; R9 I+ T2 X+ Y6 a5 b/ d% d; l  y2 ]4 p
                output = (INT)out;
- v+ ?7 @% z2 a# z                }
( l6 B* K: ^- y' z7 A$ P#endif1 h% R4 p8 h0 G1 t
#if        09 T% L* \& g/ L) i! U: ?+ e
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)/ }% ~  I' }: f1 ?) M5 g5 ^- [- |; u
                {
1 Y2 ~4 s! y" Y0 F                INT        diff = abs(output-last_data);# {5 U3 q' d- r# D, ~
                if( diff > 0x4000 ) {
  K; r, m: I' ~5 Y& q& m                        output /= 4;
$ i" |  Z  L% n% A                } else 5 m7 J- a/ R6 k
                if( diff > 0x3000 ) {
! u! d( q1 e9 A" w: G                        output /= 3;+ n$ F. h+ Z$ |% u  w
                } else
, O! [3 q0 A5 |) D" f                if( diff > 0x2000 ) {# h7 R' f# R0 W- V5 o
                        output /= 2;9 q0 D% I* l( T. \/ g- k
                }
( @6 ^) H; i4 r* c6 s3 D+ h                last_data = output;
! q$ w# K7 [" \                }
6 `5 r3 b( f9 G! S- t#endif( X! V, Q) v8 I) `
                // Limit: \$ S- X$ g" C7 i  z
                if( output > 0x7FFF ) {- t6 Z3 C8 y* ^9 [2 ?
                        output = 0x7FFF;& i& ^- Y, p9 D8 Q: W
                } else if( output < -0x8000 ) {4 {3 q: I- h, S! A1 [& g, W
                        output = -0x8000;& n+ I9 V6 P2 T7 a: l" v
                }
! u. S# R; k- J( L, [, f' \4 w7 z
$ k% k7 }2 b. m8 G* w8 ]                if( nBits != 8 ) {' r7 x9 J5 Y3 _' B$ u
                        *(SHORT*)lpBuffer = (SHORT)output;
( o* b6 l' d$ M/ o( g. R  I# n                        lpBuffer += sizeof(SHORT);) A* M& w$ g$ r
                } else {4 s7 z* C. U( @0 S8 G1 M
                        *lpBuffer++ = (output>>8)^0x80;
. W. u9 j$ d3 R% @* x                }' F/ R) ^0 L7 D! l% ^

  T+ c, ~: p; ?+ K7 o  ^2 D- _                if( nCcount < 0x0100 )
2 h, V# T7 W5 w: {8 t                        pSoundBuf[nCcount++] = (SHORT)output;
. n' [: t/ i2 y) v5 [5 n  V3 ?  ]5 y7 M' ~9 r$ s- T
//                elapsedtime += cycle_rate;
# x/ W! V% K( W0 y1 b                elapsed_time += cycle_rate;$ j. |; h4 ~: l9 o  d# ?( L; A: _
        }
" a  P) Q4 l. N% i4 ]4 T$ e/ k0 J$ F# e
#if        19 K1 H: k" Q+ S, I2 s; W
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 h$ v3 I- c- l: i, I. k# V# Z6 F+ r                elapsed_time = nes->cpu->GetTotalCycles();3 E6 K  v) R, b6 h: T  C. A& O% W
        }& T- S# i& t$ L) D* c7 [
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {+ R+ r% M% \1 r& C. r
                elapsed_time = nes->cpu->GetTotalCycles();
8 J: @: Z6 p2 ~0 {0 U5 M9 |        }
! R4 O, u$ I/ r8 z" I% y5 O" @) R7 `#else9 t. ^( m6 ^4 b# v2 w
        elapsed_time = nes->cpu->GetTotalCycles();! p! K( L1 h( S: U3 k
#endif; m& B4 _: @; c* c; C
}! I- L7 E- W3 t. c. W+ p& H1 p

  ^7 |6 ]; U8 j// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
* l5 s; O9 ^" _, nINT        APU::GetChannelFrequency( INT no )9 a: Z; |( P  i7 c  @3 n) R4 N, G
{
5 D2 o* I2 v2 l9 s        if( !m_bMute[0] )! y( \9 A5 W% i
                return        0;& D' @/ c2 I4 c. {

  j+ N' F+ Q! L8 e; Q- i        // Internal7 s  L0 i, b  V7 ~" C
        if( no < 5 ) {
; ~9 n8 i9 W1 a( ^! e                return        m_bMute[no+1]?internal.GetFreq( no ):0;& L0 c! N/ u! t: `5 ?- S1 A8 _
        }- O' T! f' \# D, M* h, m* e- @
        // VRC6
2 a! L0 J+ g# N        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
: H" o7 m# Q* `: {* t( Z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) W. g/ T9 L; H& ~+ r& m
        }3 Q* H; N& y' v
        // FDS% M! C, t( d3 X
        if( (exsound_select & 0x04) && no == 0x300 ) {# E4 c$ @% h( H/ C) _
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# K  I$ ]. |/ W0 S0 Q2 H3 J* X3 p& h
        }2 @: j" [  T' |/ Q' ]
        // MMC50 G  z, n. C1 r$ G
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* ?2 J/ ^3 G3 G( p7 ^
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: Y- h' _6 Y: C3 K: }) }        }2 R& G0 ^* {; V6 \! k( k' F: N
        // N106
0 B4 m2 D# C: ]8 j! K4 R' g( W        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
$ O5 T; c" q, e0 j& F+ y$ F! O5 i                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" a; T& `. A& N$ W' K        }& ?" k! u3 |7 E4 T8 L8 ^
        // FME7
2 X$ s+ \: x+ K  b; v8 [        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
6 P9 W, A' Y/ @                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;5 G# Y- k4 M& @: d/ m/ q
        }
0 x6 E3 {" n+ _7 h        // VRC7
. k. L$ \2 b0 Z% p7 X* e; H        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {+ Y, H; s" h3 y' @
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. E# z6 i1 t/ o2 n% y
        }% @$ G0 |3 R, |# _% g/ {
        return        0;; d* q' b5 |/ t& M' ~3 H
}
4 k& s3 j/ t4 B$ T1 h
3 G9 Z) o1 ?9 |// State Save/Load
& c7 g: b9 r1 p7 M* w+ ~1 {- N2 [/ _void        APU::SaveState( LPBYTE p )
6 ~: H$ s3 }/ T) o# l{1 {! L% v. o. P' \; L
#ifdef        _DEBUG: w6 A# h4 g2 ?
LPBYTE        pold = p;
4 l# V0 w4 V( d$ [#endif
+ _/ j! o  c# ?% G1 ~- U% W$ p1 v  {& T2 t, c/ e
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
5 s  T, G  b8 u        QueueFlush();2 j- Y  k  v! `0 B3 y

6 ~) Q  n: Z8 e6 F# Y( l        internal.SaveState( p );
- ?  _& B( y$ e% n) [8 _        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& L" M9 u/ J% U! H& U2 z) y
+ m+ y8 R' p" ^7 K
        // VRC62 z( w5 m% O8 |/ H, x* g
        if( exsound_select & 0x01 ) {
* Y+ s* b, @7 b6 i8 T6 a                vrc6.SaveState( p );
: s7 H7 P( g  u0 C                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 X1 k6 V8 {, `1 ^, C
        }
( d! J) R1 H' g9 r$ C        // VRC7 (not support)3 @. n- m3 Y' i$ H7 _! ]1 `
        if( exsound_select & 0x02 ) {7 q( v4 k" L4 o9 ~! d- d
                vrc7.SaveState( p );. H( W1 \2 |" Z2 j+ [
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, L# F3 K+ ~8 d) i) S: O) R) Z: t0 r        }
/ `% L7 ~. R5 M        // FDS8 }: J+ X6 R3 n0 i
        if( exsound_select & 0x04 ) {
* u! ^: j- y) }7 v3 }7 x* _- v                fds.SaveState( p );
) o- m( E$ h3 q# w4 f! |4 ?                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 s6 G3 m: Q/ q
        }
, b7 U$ a' H& x        // MMC51 V3 d( j  u3 Y: L
        if( exsound_select & 0x08 ) {
  U6 Q; |/ l) Y6 J# z; ~" y                mmc5.SaveState( p );
# \0 z5 o. Q6 A- L                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. ~, Z8 l( y0 B  Y# \' u        }
1 X- R  o  W/ M" s3 U        // N106
$ A1 o4 N4 i( K0 U& F: L# e% Y        if( exsound_select & 0x10 ) {
; z6 W& R8 [& G' u7 h                n106.SaveState( p );( t8 |: }/ L0 I- B- S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* N3 v5 I8 x* M3 |        }2 j0 J' R' ~, R# K' ~5 j
        // FME7: z6 b2 C; G: _% r9 C
        if( exsound_select & 0x20 ) {3 `! U1 b" a& _# S( }( m( d
                fme7.SaveState( p );
5 H- g. @/ a# k7 v                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ G( D( E3 h- ~
        }
  E5 H0 v( e9 L" h
( I; Y) d! Q2 m3 T#ifdef        _DEBUG- m8 `% r* `- k- x9 k
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
1 }$ t6 @& W' k5 r#endif4 ~2 W7 h1 h, x3 W5 O
}
* k" C. T; d! U5 N1 k: U  S. L: i1 b4 X( u9 s8 p0 S5 Q5 |3 z/ O3 r
void        APU::LoadState( LPBYTE p ). w  ~( K) _7 p, [" F  n
{
' R* l+ b2 k+ v8 y7 a, G        // 帪娫幉傪摨婜偝偣傞堊偵徚偡. W: M. D, J  ?. v
        QueueClear();3 n  V# u# S% h$ M
2 `3 v" D- W& n
        internal.LoadState( p );  S7 R# ]. v3 Y& E7 z! ]
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 A5 u& J( {: q& l* t! ]$ n
5 `3 S8 ?# r8 I& D: j% O* X3 p9 z        // VRC6
: `3 x! h5 M' _        if( exsound_select & 0x01 ) {
1 a/ \3 \% W5 F2 `                vrc6.LoadState( p );
! @& r% S0 t: B" O) E                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, k' |6 Q- j) M! r5 Y: S9 M# [        }
/ u4 C% Z. ^; v( c6 T        // VRC7 (not support)
) s9 b: H) d5 f0 }4 N8 h; _        if( exsound_select & 0x02 ) {' k4 T% i  A7 v* F1 j) a/ J
                vrc7.LoadState( p );+ n3 ]! S6 k- l- U* Z: @
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& d% u2 c4 {3 J) {4 d; P        }
5 j2 p! r* C$ {6 H        // FDS/ N' G9 a* }, ]' q$ I! n/ E
        if( exsound_select & 0x04 ) {
& t% Q- s4 F2 V1 l( `/ p                fds.LoadState( p );8 g$ z; n& ]# b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 s/ q, Q) G; J9 e# O; O& ]' w        }1 r% G/ w/ d: Z* _# z
        // MMC5
3 m8 ~3 _8 O: k; x* s" x+ ]        if( exsound_select & 0x08 ) {) B! u0 v4 r4 [9 x7 A: Q: o" H
                mmc5.LoadState( p );9 d% w9 U; y0 {) h6 P# u
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 L3 V( a" R  h+ x  k        }# O$ w: ]) I; l$ {7 o" B
        // N106
4 a0 r2 _7 N9 P, n  ?        if( exsound_select & 0x10 ) {
  Y0 U" ^6 ~% u2 D- C7 l& t0 A                n106.LoadState( p );
5 N9 l0 n( E" o( h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, t' h4 m) C1 s% P& A
        }
  d0 L( o2 l# c8 Q4 i        // FME7
9 ^! f5 u' h+ E        if( exsound_select & 0x20 ) {
2 M& g: I- G: v! ?                fme7.LoadState( p );0 A7 a6 ]8 v2 [9 }& W' h0 J1 q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 m) X& [1 Y$ z8 K6 B9 E
        }
9 G! p8 E5 E! |; D6 O}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& `& b0 T* [2 k! D. ]可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。' P' E( ?! L2 y$ S  h8 r6 e+ I
感激不尽~~
# D, m) `' j8 p& p* o
恩 我對模擬器不是很有研究,
  }2 A0 \1 P& _* A9 k) @雖然要了解源碼內容,可能不是很困難,
8 W7 C5 q% R3 G1 k2 h# I, x- X不過還是要花時間,個人目前蠻忙碌的。% F- |* S0 ^7 g0 Q. n  U

" L. @7 B3 B! `) K8 K. ]- ]給你一個朋友的MSN,你可以跟他討論看看,
, s  ^* a- g0 V, [# f0 |% L$ S2 B3 b5 B他本身是程式設計師,也對FC模擬器很有興趣。
! |0 w: G7 y, p, O3 r
( \  D" V. ^' r" E& |, A+ IMSN我就PM到你的信箱了。* y6 Z2 ?' f' L

. F6 c) y% h2 }: @7 L希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 , O9 P2 |2 |- A
呵…… 谢过团长大人~~
+ N5 f( i9 t3 p% w1 o( R7 B

; i2 z/ o+ W/ j$ P. E2 e哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 # z8 R- f' F1 e
团长的朋友都是神,那团长就是神的boss。
$ [* |* f# E$ Y; G" G. [
哈 不敢當,我只是個平凡人,* z6 Z: L0 H% a+ ~0 ^. b
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ v! p" R$ d5 i% U: ?
ZYH2 V" A$ ^, Z# J: }
QQ:414734306
0 ^0 \. w* T1 F* z( nMail:zyh-01@126.com
7 o; R, T/ G: q/ D7 A4 g. S: z6 Z# e. M7 t4 X8 ]
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 j/ r* [: {1 [+ G. r& ~
再次对团长大人和悠悠哥的无私帮助表示感谢~~
% Y% I0 Z: k- |' U+ p. {6 B+ n7 G
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-5-19 17:24 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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