EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 S8 M6 I4 |; B0 L2 m楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) f: P/ Z/ r2 J" e) f这里有相应的模拟器源码,就当送给大侠了~~
/ C7 C7 q! C4 u& H. Dhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
. o0 c  j$ [6 X2 n3 P; l9 k能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* r# Z( d1 Z, |4 w楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: x2 E8 s7 H- m3 F- u
这里有相应的模拟器源码,就当送给大侠 ...
( E( F$ t  |. M% t) M
聲音部分(Audoi Process Unit = APU):5 |, |% }2 ^! O
.\NES\APU.cpp
7 h5 J! L, j9 K" }7 E: W! V5 b.\NES\APU.h) E/ o9 ?2 G- p, U* w

- W9 A0 I1 c$ w& r9 r% h/ }; C2 n9 w2 \5 q, V0 ^% v
影像處理部份(Picture Processing Unit = PPU):: Y+ \1 g: V2 B2 u
.\NES\PPU.cpp2 d, G, f: P# F8 L7 \
.\NES\PPU.h$ s5 I" W& c5 j2 ]
2 l% {# P. w# z+ ~
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:3 c) a  Z! n: X# }: L' f* f* k
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 U' P9 O& ?/ i% g//////////////////////////////////////////////////////////////////////////
% b: H- s/ |8 ~  }//                                                                      //, ]" s2 Z# B9 d1 h4 B1 n
//      NES APU core                                                    //& H: Y9 F0 U) Y) h) {
//                                                           Norix      //+ h  J% U9 u8 H2 R2 E
//                                               written     2002/06/27 //4 y' E# I& C4 q, X5 ~0 z, `
//                                               last modify ----/--/-- //
0 @- V; R# e4 G! S- w//////////////////////////////////////////////////////////////////////////7 ~8 Z- K% m! S: ^
#include "DebugOut.h"
& I# g& G5 y+ F#include "App.h"
" M1 I8 I- u' ?7 z) a  f$ a; P#include "Config.h"
1 R" A' ]# q  Z! Q$ `5 W& C4 ^9 T
. M5 [% s" v. B#include "nes.h"9 q3 N/ ^9 \9 N
#include "mmu.h"
9 U6 {: v$ k' t& Q3 z#include "cpu.h"6 w9 E& r2 ?5 }. b+ L- [0 d% ?
#include "ppu.h"- j0 X5 o" M+ o7 ?
#include "rom.h"4 ?9 d& ~- C' A( P6 `% Q
#include "apu.h"6 l, ^$ Z# D' {4 c
) C* f+ O) w5 \: `9 H9 P4 T: H  C4 M
// Volume adjust
: E+ @5 f. A. I2 a' c/ o) W7 @// Internal sounds& g' l! ]6 [( S  z$ E
#define        RECTANGLE_VOL        (0x0F0)
9 i3 G/ y, l7 M0 M$ w#define        TRIANGLE_VOL        (0x130)
. I. l1 e7 M. i; K# c& V8 J#define        NOISE_VOL        (0x0C0)
5 r5 r" @9 v9 V+ O- J' K, y#define        DPCM_VOL        (0x0F0)
/ p+ U9 U  w- B// Extra sounds1 ^2 k  T% D' a
#define        VRC6_VOL        (0x0F0)- n9 H# J4 K. P" K7 Y6 V8 e# Q/ A3 p
#define        VRC7_VOL        (0x130)5 U: e) R6 p$ {* j! E
#define        FDS_VOL                (0x0F0)
) P+ Y7 o2 R% V# K+ g8 P3 U#define        MMC5_VOL        (0x0F0)
. @8 h" v+ ]) r- V  e#define        N106_VOL        (0x088)) h8 C. G2 a* V
#define        FME7_VOL        (0x130)
1 N6 o% b1 K5 Q  ^! J" U7 C8 c4 W# ~% y4 y
APU::APU( NES* parent ), C. `/ k  I1 T% G! s+ K. K
{5 w7 V1 h: _, _
        exsound_select = 0;
6 E4 T2 l: f3 `9 |  o' ^2 l) V7 k" `4 G
        nes = parent;* O8 C" I! D0 ~( n2 W
        internal.SetParent( parent );3 D4 t3 }( F7 I2 ~9 ^

' y. ]; z( o. Z3 k/ j2 q# Z        last_data = last_diff = 0;
( D! e5 @  R3 Z5 t9 s. N* e  l4 Y3 B" q: x& i
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
  M8 r4 s6 C7 e- j6 @0 ?; a8 z, ~+ O9 ]" M- ~
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
6 a5 |2 m. |. \2 [        ZEROMEMORY( &queue, sizeof(queue) );
+ m  D8 h5 j4 b8 S0 E% v( @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ K- d: k- v1 D; Z5 N/ R. h% ^; r
+ O  E0 N6 B1 r: e9 z2 M        for( INT i = 0; i < 16; i++ ) {
! K5 a: I! N/ Z- \3 D4 Z                m_bMute = TRUE;% V0 N5 q; C( Z) i- n# u) f
        }& w2 t5 W, y& m: g! l( v
}* [/ R* x7 s4 K& Z4 k( x

3 |& N( U% O6 R3 wAPU::~APU()
2 j& H6 V  I3 i: H& L{
: P. p$ S- d7 h$ l0 \* W}
8 B5 ^0 @2 k( p
5 R: k1 l) ]4 d/ p+ b3 _8 k. lvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
. ^! O! R" F0 D1 _% C+ S{
3 n) `9 i. I' N, y        queue.data[queue.wrptr].time = writetime;
5 U5 }2 i) U' Z$ K, d" O        queue.data[queue.wrptr].addr = addr;
+ u' F+ J0 M; f+ ?        queue.data[queue.wrptr].data = data;
, l  n9 P1 Q7 i. {/ ~        queue.wrptr++;! C, \3 k5 h+ ^1 g$ d! N+ m% i/ L
        queue.wrptr&=QUEUE_LENGTH-1;
; O  |% ~" E% i  A. D8 j        if( queue.wrptr == queue.rdptr ) {
% `( M2 I6 ~& C' |" T% Y5 n4 a7 e# h6 ~                DEBUGOUT( "queue overflow.\n" );; E6 g. ~2 z# ?  B
        }) I$ I$ _3 u9 v4 n& ~  V
}
/ y4 s# |9 @, X  S, K" L& `7 d' X/ n6 b
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
! B6 Q( S4 {1 A, d; A! L. ~: f{" k! p+ t' ?; c
        if( queue.wrptr == queue.rdptr ) {, C  u8 H4 j: |4 ?9 c6 a
                return        FALSE;' Z. N/ o; l+ P# |( C% ?  o  u
        }
& ?! y" t1 m/ ]/ W+ P3 D. Q        if( queue.data[queue.rdptr].time <= writetime ) {
  ~9 x" a4 ?; O1 v* Z( h& ?                ret = queue.data[queue.rdptr];
$ R2 q; B7 r% [5 L                queue.rdptr++;
. p% d+ c* [8 l                queue.rdptr&=QUEUE_LENGTH-1;4 M1 [3 F' Q6 f3 s! D, r6 [
                return        TRUE;
5 `; R  D  p+ z) @0 Z' u5 D        }
; L/ ?7 O" f! ^- I: W- w# k3 D) o        return        FALSE;
* ^2 m: G6 T0 s7 o8 i. X) `$ ~}
) q: M, n; a/ ~- x9 e" M" M  W# Z8 f5 {4 `2 T0 f% o
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 p0 p5 Y% h+ u; T7 l{  d) c9 A; q& k; U0 [* V# e
        exqueue.data[exqueue.wrptr].time = writetime;
7 t' ~) n9 J! M' p7 E/ _! D        exqueue.data[exqueue.wrptr].addr = addr;
$ q2 o3 I6 @; @# `        exqueue.data[exqueue.wrptr].data = data;- q- e# S8 i+ b: u0 X- {& r' |
        exqueue.wrptr++;
8 Q& b" u5 W' N0 O" K        exqueue.wrptr&=QUEUE_LENGTH-1;2 K9 n0 y) Y( J! [8 P; p
        if( exqueue.wrptr == exqueue.rdptr ) {
4 W' O9 u; K( u( l/ k( h                DEBUGOUT( "exqueue overflow.\n" );# g. }: s1 Q0 ?
        }3 T. H; A, v' M, L. Z
}
4 ^" x1 Z# h# D9 _& E& ?# ^
: }: w6 H3 _4 y0 G7 S* q- @BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' q: Q2 a; G% ~+ B{% |+ O6 ~2 j9 A& G
        if( exqueue.wrptr == exqueue.rdptr ) {
# f! Q4 V( ?% }4 Q! \                return        FALSE;/ u1 `  r& R( }" m' r  Q. P  e
        }7 \# ^9 t6 A9 A* d2 u
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& I; `% z$ |7 V+ e7 Q. j( P* Q
                ret = exqueue.data[exqueue.rdptr];
0 t# g) r. V' q/ m: o! j                exqueue.rdptr++;/ T- g- @9 x# P+ Q$ D' F9 ^. C
                exqueue.rdptr&=QUEUE_LENGTH-1;
: U( a+ Y5 S: Q% d                return        TRUE;) {) i4 Q  E: v) }5 |
        }4 N7 n) W( @, y5 N
        return        FALSE;
/ N6 M, q1 V2 S7 b: R- R" W1 V7 t}7 y% l* q( V) [# _3 g

! W# D+ w" ^# }- h( R2 bvoid        APU::QueueClear()
+ R0 E, v6 J2 K: W' }{
3 e+ y- C/ o7 U' S0 d! v! r# M8 s! C        ZEROMEMORY( &queue, sizeof(queue) );3 L+ \: W; F9 g1 o9 ]+ ?& n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ u; Y3 C: r( M8 C, S9 |0 @}' `( F8 a$ x" ^4 v3 R* I: O

8 ^: ]( q' D6 j: e% Cvoid        APU::QueueFlush()) X% x/ K& ]% d. F; P
{
8 a2 _3 ?6 t0 U6 a$ N, z; g5 J% P* R        while( queue.wrptr != queue.rdptr ) {0 C( O3 t; O% h( v0 `
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* E4 R! O  P" k6 L% V; M' T                queue.rdptr++;$ r4 @2 @  f3 y9 h5 n; R4 i
                queue.rdptr&=QUEUE_LENGTH-1;
" k! C  C. Y# c5 q7 `2 I9 {        }
. ^3 S% N0 [4 @4 Y: w
, n: E7 c6 F" m6 C        while( exqueue.wrptr != exqueue.rdptr ) {  K7 {$ v) `; o
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 `: ~! I. W/ ?7 E, S; q# _
                exqueue.rdptr++;
) O. Q. z  A* ?' x" T; a                exqueue.rdptr&=QUEUE_LENGTH-1;" I( X' W! b' W
        }/ ~* Q+ S* K6 b4 N
}
# {3 f  G6 x% \3 C4 }6 J8 f0 |
5 s$ |/ w0 T( r) ^6 d3 F3 L* kvoid        APU::SoundSetup()
5 V) q6 ]3 {1 o: m% f0 l( Y: i8 F{9 m& M7 K' j  b2 f% H- ], c0 B8 M
        FLOAT        fClock = nes->nescfg->CpuClock;
! Y5 ?! H8 A; L        INT        nRate = (INT)Config.sound.nRate;" H' W' P9 J$ e: j% D5 k2 L
        internal.Setup( fClock, nRate );
* N, {- Z* F% j3 \4 A2 ]        vrc6.Setup( fClock, nRate );0 X' q6 g5 T( s" g
        vrc7.Setup( fClock, nRate );/ V, Y* J4 Q0 ?% Y
        mmc5.Setup( fClock, nRate );
) p) K4 C" H6 u% u; l. r        fds.Setup ( fClock, nRate );
, i% j- k7 K0 ^  ^        n106.Setup( fClock, nRate );  l' L& O% R( `+ \
        fme7.Setup( fClock, nRate );
' s2 O& x$ G9 Q0 {( B  {}
& F! O3 U2 F1 ]: |0 r
9 w7 O9 {, M9 d' I6 q4 G+ yvoid        APU::Reset()
4 _/ h" v" A* s2 \2 f! d{
! b9 Y) B6 u# }        ZEROMEMORY( &queue, sizeof(queue) );9 }( T, d1 o1 y6 @% y5 T  v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% h' X) Z  N3 m: |0 C, {( d, O4 {8 Q; n: ?2 b
        elapsed_time = 0;$ O) @- A& C# n2 A6 G
, Q  C, @, ~; g' i2 D
        FLOAT        fClock = nes->nescfg->CpuClock;
1 f0 `& {; X* x+ w        INT        nRate = (INT)Config.sound.nRate;8 \3 U. Z) Q* Y% e- |- P% H
        internal.Reset( fClock, nRate );
' E" Y6 b: p# K# G2 `; b2 I9 t        vrc6.Reset( fClock, nRate );: U( M8 j* P* q3 J6 x$ `, ^( a
        vrc7.Reset( fClock, nRate );
3 y' I# ~, a8 b- Y, n0 \( [        mmc5.Reset( fClock, nRate );, V) r5 O! w+ V
        fds.Reset ( fClock, nRate );
, L  P' B8 `/ g& A        n106.Reset( fClock, nRate );% `! P% c1 s! d- x/ `: l
        fme7.Reset( fClock, nRate );$ P# C$ S4 b4 M3 @$ m# |9 {
( H/ S' B" q$ b; v5 g( K% \, S' m
        SoundSetup();% M+ [7 H4 s: O  |
}$ u6 h8 @" b, b; k( ]$ B
' e: ~5 S! L+ ^9 p5 M* D
void        APU::SelectExSound( BYTE data )
  x( U0 u8 w: O) E& y( L$ p6 t8 p{$ @+ M  T1 {, V5 E$ T5 ?0 m
        exsound_select = data;& |4 V' x- Z, O5 |/ l1 d( u
}
0 c% t8 \$ k% }% \' h# _8 l1 o* ~9 u0 ^8 c5 P' T+ R5 G" j" ^
BYTE        APU::Read( WORD addr ): d/ K* t; P9 g- a
{& D+ Y# \" }  S" O. J
        return        internal.SyncRead( addr );& Q( @9 O* D* l. s, m- u
}  V: f- i. z4 U0 r

6 M+ j# ?0 S% b4 Qvoid        APU::Write( WORD addr, BYTE data )8 x. P) r8 G# q. Q9 O" d% W  c
{
: q; ^" z. x" m8 E! y9 Q        // $4018偼VirtuaNES屌桳億乕僩* @% b) C, Z, `' u
        if( addr >= 0x4000 && addr <= 0x401F ) {
: N0 Z. o7 X" W0 ?  ]                internal.SyncWrite( addr, data );' @/ U$ c- |+ c  q
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );6 d* t. [* V2 m* S" w
        }# E, d8 O" `2 O6 H
}' A7 e! S8 ?- Z2 L  m

/ _( }$ A9 p: k9 E: U" }# JBYTE        APU::ExRead( WORD addr )
  c, v( J* F/ _  u{1 ?; }5 E8 L. s: l
BYTE        data = 0;
8 I5 F; X5 ^# `0 S( V1 A' E- q% R# ^* G6 y# k% R+ k
        if( exsound_select & 0x10 ) {
1 \' X$ Z5 b8 h0 [$ p                if( addr == 0x4800 ) {, x2 R: S" Q7 c# s9 [' r" x* z
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: s/ p. I& c8 \8 \5 ]5 C$ ?
                }9 T; W; V% O3 y4 z" M4 s! z
        }! x+ ~* U" O9 l8 W
        if( exsound_select & 0x04 ) {; e) I; i* P6 [+ \1 Z+ p% P$ e
                if( addr >= 0x4040 && addr < 0x4100 ) {( L- d) y/ h6 |( g- `5 I
                        data = fds.SyncRead( addr );
+ y. |+ b) ?, J                }
. @- c& A; ^4 B5 J6 Z4 Z        }
- f4 o5 X  w7 m! F        if( exsound_select & 0x08 ) {# d. F( d" S/ k* a+ h0 m
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 e9 x$ c4 @- C
                        data = mmc5.SyncRead( addr );
0 u3 [9 x( |6 ?7 C: p6 J                }
  ?( A! i2 u- d        }
& y5 p9 H& ?4 Q: R# a3 J7 w, a5 K$ z5 g+ A8 Q
        return        data;
/ I& w# K5 h: i0 }}
3 J0 x- c& u5 H1 Z' G2 |( v
& U8 U4 R+ i, q" i8 T' g9 ^* Dvoid        APU::ExWrite( WORD addr, BYTE data )
3 n) L% \% J3 k1 ~{# m$ e; {# A( p! ~9 Q
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
: C9 e* D: k5 i4 x  I9 N# F7 ~6 o- {
* T9 S. F5 b! V' F        if( exsound_select & 0x04 ) {( y$ d4 t5 S& Q; g+ p* |
                if( addr >= 0x4040 && addr < 0x4100 ) {
8 T% i3 Z2 U. `2 m2 _) f) m5 L                        fds.SyncWrite( addr, data );
; p0 s+ a5 U& }! a) E+ }                }
: y8 l2 r, ^- l0 o        }
3 D  U1 J5 B7 a' a; W# \6 {/ l5 k
/ q2 P9 K7 Z8 v; Y/ q        if( exsound_select & 0x08 ) {! a% e! d/ j8 @3 E
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- C5 K( ~. |: v/ L. v7 a                        mmc5.SyncWrite( addr, data );# k2 u% a$ n9 N2 f' ^  [
                }3 I' t$ N6 a! M; a1 S$ B; u+ P
        }
! R2 ~% H7 n: ^}
% x) M0 u  Q" Q
, h* u/ R6 k6 rvoid        APU::Sync()6 Z! ~) v* \7 k7 f! {# ^* p
{3 M% v% B- L) V8 H+ w1 Z( N% a
}4 e0 x. Q- h* V& B$ d

" y8 F3 U& w5 |. ]' M9 D: gvoid        APU::SyncDPCM( INT cycles )8 x! I: E! r7 e; @$ y
{# T. M0 l+ _* O. z& J9 f2 [9 T
        internal.Sync( cycles );; F* d" f# d) r3 t
' ?8 x* S6 F( ?
        if( exsound_select & 0x04 ) {
( x1 G' A& p. _7 l! z) U                fds.Sync( cycles );3 B# T. N, d% E& A. u/ x/ L
        }
! X, a" w$ M+ a4 M        if( exsound_select & 0x08 ) {9 x$ S0 m# E5 m- N8 R3 Y" |$ d! y
                mmc5.Sync( cycles );+ P& W3 G1 x9 H* V2 J1 h+ u
        }6 d) S4 G: M- E
}8 M1 r( Z# M, t/ ~) F0 R  R# {" G# ]

( n. v& Z0 ^7 F1 {void        APU::WriteProcess( WORD addr, BYTE data ). y$ q7 a* F& C  m( P
{, ^0 G# |0 e7 a5 M
        // $4018偼VirtuaNES屌桳億乕僩& U2 y4 F# ^9 i2 y
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 `% r$ v) W8 a4 D: Y                internal.Write( addr, data );0 V0 t6 p2 M( k' V6 a6 l
        }
" f1 k" f, Q- e}
( a# Y$ |0 n+ F- f9 M7 y0 ^' F- x* O2 V9 K" h
void        APU::WriteExProcess( WORD addr, BYTE data )
& _+ K* n0 B9 f. p" h% ]{
2 a$ K4 E) h; G% }% I        if( exsound_select & 0x01 ) {
" k5 L& b" {6 G/ K                vrc6.Write( addr, data );
0 ~$ B1 K5 o3 B9 H7 q        }
. n4 `5 I( ^9 ]- ]3 \        if( exsound_select & 0x02 ) {  o2 q( G/ s6 r; Q0 y% Y" g
                vrc7.Write( addr, data );
# f- A0 a4 m! Q( w" d' {        }
- Z6 K( @, H; O0 ]  \6 o5 x        if( exsound_select & 0x04 ) {/ m% o( U! E% L& L; f, a3 L7 s# W
                fds.Write( addr, data );# z! a' h) Z5 Z. r% y
        }$ J0 s; h0 T6 v( e6 T- _
        if( exsound_select & 0x08 ) {
; Q- B6 {4 _" f: w: f                mmc5.Write( addr, data );
) ^" r, \$ t( \  p0 O7 `        }1 {- {$ v/ z3 L8 k
        if( exsound_select & 0x10 ) {
- S6 z8 k) Z$ Y- p  I                if( addr == 0x0000 ) {; o  e9 K, p# U! I. O8 P0 f" W' Y
                        BYTE        dummy = n106.Read( addr );
$ v7 Z5 W/ M/ v" v3 ]                } else {6 _  s# V& f+ N5 j2 A9 f
                        n106.Write( addr, data );$ d6 O- n5 [& Z. ~9 A2 f
                }/ E$ M# D& t8 P. Y/ }
        }
8 K7 G, ^- `) i- ~2 Q! d& [  e        if( exsound_select & 0x20 ) {* g5 d8 ]" N) y, U' R
                fme7.Write( addr, data );' \8 [, G- u  y! [9 c! A- ~' L) M
        }/ M0 B2 z) e' h
}
! \6 o, T$ c) G
8 z/ j* a0 f0 G' `5 i* Rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ ?! ^" V1 [/ s3 P3 p" {
{
* \  E  O0 B9 s* fINT        nBits = Config.sound.nBits;9 o% }# A9 p9 m1 Z7 N
DWORD        dwLength = dwSize / (nBits/8);
. i+ {5 F" g& \: iINT        output;- x9 ^# Q: N& d
QUEUEDATA q;
8 E. G: ~- ?  ?1 LDWORD        writetime;6 m7 i' E- |8 A2 r

, }. a4 N5 g% x  Z" L6 LLPSHORT        pSoundBuf = m_SoundBuffer;
9 Z8 Y& q# ^- {INT        nCcount = 0;
. A" }0 u6 |  o, y1 h% D" f. {- a, e/ W9 `; M
INT        nFilterType = Config.sound.nFilterType;0 f- F; i7 f! Y' X

. @1 i; P: d: O4 U6 ?- F- C$ P        if( !Config.sound.bEnable ) {
/ G3 V: n. f* d* W                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
( B$ X% h$ n2 _9 T1 L) i' D" g$ }                return;6 z3 l* ?. d1 x: C9 j' E# ^  m
        }
  ?$ U. r" @* m( p8 U: e1 r) J) X0 Z5 k, T% l- S
        // Volume setup
4 ^3 [! d$ R0 D4 O        //  0:Master6 p0 ?( V* i% k6 F* N
        //  1:Rectangle 1
  h7 m' g1 P' t9 l        //  2:Rectangle 22 ?+ Y9 w: P2 q* ?, j+ w; v
        //  3:Triangle+ v, B5 |1 l& ~2 p! Y
        //  4:Noise
1 |7 d7 v! E. ]6 F' i4 R$ l9 \        //  5:DPCM6 d0 v; Y2 j& s4 l
        //  6:VRC6' e7 A4 u6 x9 m! r
        //  7:VRC79 u3 x+ t  Y6 Q
        //  8:FDS
3 V; o9 a+ K% O: p4 b        //  9:MMC59 g0 F: l' E4 _; |6 \
        // 10:N106
0 L( _) _! C' C; Q        // 11:FME7
; d  e# M  g( q1 A* w: {) w        INT        vol[24];& x8 }5 e2 R' _+ e* _# E5 y2 E
        BOOL*        bMute = m_bMute;& T8 w6 v, v8 _: }
        SHORT*        nVolume = Config.sound.nVolume;
+ l1 _$ }% o2 }; [7 x% O# O! n  n1 E+ |& f9 y  |1 \( A
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
0 D3 ], }( m9 U2 k9 M; f/ Q2 Y+ A. x# e5 M- \0 b
        // Internal0 q; M! e) W% N2 J5 V8 D
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;6 q2 [1 n2 ^9 B" u# Q; i) J
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# {. `+ _& H- J/ a4 N% y& H
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;' _$ b6 B* H* t6 t3 t
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ ]! e! e) n4 Z: j" I+ B
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;6 d) _7 @7 E0 d% M8 G. E
9 F8 s! q+ K8 b% _
        // VRC6! D, ^. ^8 z* m1 _: S
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% L. B6 d! F9 B        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 H+ J9 M, b0 n        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  L( y" T( T/ m. B7 t
7 y* g& o# l* ]1 A5 Y8 |+ M
        // VRC7
9 w0 k, \1 [7 W. n& F# F        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 Z6 f4 b" D7 o  |3 _

, w: c! ^# P0 J/ q        // FDS
. u# H6 ?9 C2 T& Q3 k* Y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
' }, T, X" E6 f0 \
0 a0 Y8 D+ |7 ?6 J) y, Q/ n        // MMC5, \2 I2 R# e7 `7 q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 w: J' c4 I3 W6 A/ N, y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 c$ a- S, G1 S* p# _
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: j, S0 |! m0 ?% X/ S7 r, U) R: p, O+ f
        // N1067 s* Q$ s9 u- R, w8 y( g3 {6 [( u
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, ~0 [0 Z( ]6 [9 g- N) B: s
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 u. N. g4 W0 A/ A' O2 `7 n: X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 C8 W1 P/ F$ u+ D        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 G$ I7 x1 x% C7 l$ z
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 w' b- Q5 f6 s" Z) e% l
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* X% D( O2 c0 ?+ u
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, y# }. v" V* z0 Z, I: b        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 \% o- ]( a9 h8 G1 p' ^, {

# t  R* i3 \/ }: A( c8 }' Z        // FME7" j5 Z7 U+ ]: {( X
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 ^+ O9 b; l7 X        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- G2 ~% g% q+ O  _8 U        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 `8 m' Z# M  i, ?, v
( r1 B+ ~/ l. [+ b/ ?
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;5 T1 w* Y7 _: Q9 w1 p/ O5 U3 C
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 b9 j6 v' [9 h' z- g5 v3 u6 n+ Q: n) E' p" h- \3 S$ N
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
  G6 f( m$ I8 m        if( elapsed_time > nes->cpu->GetTotalCycles() ) {" J  @6 W5 N& B! L# B9 J6 s! Z, [
                QueueFlush();% N' J- e# I7 x4 t' Q3 w3 M% u
        }
8 `$ p/ I5 [9 S. O& Y; I* k( h* C1 p$ ]" a
        while( dwLength-- ) {7 r# M1 X' ]! a6 v" T
                writetime = (DWORD)elapsed_time;. g7 y6 |4 C4 r/ r( G4 ^0 Y% m% Z

% B# o  ^# d; g, r  q) V% v! {) n                while( GetQueue( writetime, q ) ) {
# V/ N. L" d8 z: `6 p                        WriteProcess( q.addr, q.data );
" J* J' K/ l8 V# d6 g                }; T# L2 J, h% a) V& p+ W% k6 y* u

( q4 [3 S/ @* v8 q                while( GetExQueue( writetime, q ) ) {
* i* n/ _  L; @# l% C                        WriteExProcess( q.addr, q.data );
% n4 B4 V" `1 M& k6 E" t                }( H5 H/ D) |: d3 [% E8 y+ s
) [1 _( i* l0 ]
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 t7 N, f9 N0 j2 G
                output = 0;
$ R' _% s4 R2 \: `4 J( f                output += internal.Process( 0 )*vol[0];3 }  r/ z9 z6 g5 j: v. ]
                output += internal.Process( 1 )*vol[1];+ }+ s- W2 V4 S" q5 m
                output += internal.Process( 2 )*vol[2];1 A% D6 Q/ C" ^! _
                output += internal.Process( 3 )*vol[3];
/ l. C6 \" k# v+ b6 S, F                output += internal.Process( 4 )*vol[4];  E  a+ B) p+ [* W
7 S1 E& [. L3 d, o1 B2 n4 Z
                if( exsound_select & 0x01 ) {+ d6 [) r$ W! U( B$ i; L' c- p
                        output += vrc6.Process( 0 )*vol[5];
, C' i! H4 N  q, o; w! x1 h6 y, Z, D% V                        output += vrc6.Process( 1 )*vol[6];
. B2 x' T; a  M  i, i$ g& a* o                        output += vrc6.Process( 2 )*vol[7];
* @+ o3 t+ [) q4 S: S; U1 Y                }% U" f' f" f! y: S
                if( exsound_select & 0x02 ) {
$ a( P4 r. j* ^                        output += vrc7.Process( 0 )*vol[8];1 M: x. L4 V2 E( Y" F# I/ @6 L7 Z
                }1 s& S; J7 J9 e* f0 r* P; F1 |
                if( exsound_select & 0x04 ) {
- n& ]) y% o. _' }; P                        output += fds.Process( 0 )*vol[9];
+ H  O% `$ g, R7 h                }- q( h8 U$ d: J9 M
                if( exsound_select & 0x08 ) {1 l' T- l3 z* e" c3 H
                        output += mmc5.Process( 0 )*vol[10];
0 w+ R7 J) A! Y. k  u# b" X3 D                        output += mmc5.Process( 1 )*vol[11];
1 d* }; q9 u+ E( U- p                        output += mmc5.Process( 2 )*vol[12];( F5 l0 b8 G1 K! B# T
                }7 z0 X0 ~- E% b6 w
                if( exsound_select & 0x10 ) {; L  K5 g; o8 D/ i
                        output += n106.Process( 0 )*vol[13];2 }0 g' P; d8 m2 M
                        output += n106.Process( 1 )*vol[14];# A' l( m, S3 `9 v  z
                        output += n106.Process( 2 )*vol[15];
8 I' ^. {. Q' h" G2 }                        output += n106.Process( 3 )*vol[16];% S+ p2 H/ ]4 x5 N+ q
                        output += n106.Process( 4 )*vol[17];
+ L& s6 S4 F% ~4 U4 i! \5 s5 u8 d                        output += n106.Process( 5 )*vol[18];
( w6 e, b5 q+ P* l                        output += n106.Process( 6 )*vol[19];2 {  r" Z6 \: f, x6 ?5 t
                        output += n106.Process( 7 )*vol[20];7 |% J; W+ Q, n( y7 B- B6 w' a
                }
1 l) G! h* ]1 ]/ Z                if( exsound_select & 0x20 ) {
+ R- ^% g2 C: P! W/ D5 s, j                        fme7.Process( 3 );        // Envelope & Noise
+ m. ~/ b6 K( l# q                        output += fme7.Process( 0 )*vol[21];) O3 q% L% V2 D$ i4 Q, b5 Y
                        output += fme7.Process( 1 )*vol[22];
8 x- C) K" @3 n" ~3 b/ V                        output += fme7.Process( 2 )*vol[23];
) r* N( o$ P/ K/ r7 _0 q: W/ h) h! c                }. L, T; T4 h8 _
; |8 F7 O) @1 j# b
                output >>= 8;
0 \7 P, w  n7 z8 K( n7 i- @; Z; l6 O& N1 [; K
                if( nFilterType == 1 ) {
, a# m' l' ^9 n. m' r; i" s0 k                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 k& x7 d7 \2 Q# f# ]3 h$ M: Z
                        output = (lowpass_filter[0]+output)/2;" B' T$ y7 v; _# I
                        lowpass_filter[0] = output;
9 e; U& i- k3 e; Y$ f0 I8 m6 C4 K                } else if( nFilterType == 2 ) {
$ W2 n. f! s: V7 Q                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 \  e% s8 ~# f/ P
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;/ `4 O. H) d# L. T, i' ~. T0 u
                        lowpass_filter[1] = lowpass_filter[0];
1 V# k1 ?! }" s* H1 |                        lowpass_filter[0] = output;
0 ^! p9 G, a; ^& s                } else if( nFilterType == 3 ) {
  m5 @5 g3 F) l1 n; m9 Y4 h; n                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2), `0 O: Q6 B% Q& i* u
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;- ?( c  p7 E" o, p2 C5 j5 b, F
                        lowpass_filter[2] = lowpass_filter[1];
2 w% X& m, h4 k+ y: G& e                        lowpass_filter[1] = lowpass_filter[0];
/ n+ Q' V6 v" B$ M& i                        lowpass_filter[0] = output;
0 N+ N' g! l* ^) q2 R                } else if( nFilterType == 4 ) {, g8 a3 ~; S1 L( A0 S
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), u8 \" ]+ B: z9 |, b/ @  l8 p
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
! E* h% u' r: i. d$ C& q0 r6 o2 n                        lowpass_filter[1] = lowpass_filter[0];$ Z5 j$ Z9 ?: U
                        lowpass_filter[0] = output;/ z# d2 O, j) \% q$ I/ F& F
                }! j. k6 }2 Y* I: H- S

; q$ f4 \+ q3 b3 I( h#if        0+ s* X- @$ F0 F: x  ~* P8 L
                // DC惉暘偺僇僢僩% l- [' H% ~6 y* U0 q
                {
, @: i6 l7 K8 C: E0 E9 ]( k                static double ave = 0.0, max=0.0, min=0.0;  h2 Q' l4 Y% ^1 w
                double delta;
- v/ a, a9 H3 j: T8 Y/ U                delta = (max-min)/32768.0;( y0 S* a8 y; L, i$ M. @' q
                max -= delta;& u; Z* w, }8 W: K
                min += delta;" t0 V$ W0 H5 s0 |+ p
                if( output > max ) max = output;5 a8 u4 ?) S- ~, a5 Y
                if( output < min ) min = output;5 K( `$ g: r6 R" K+ s
                ave -= ave/1024.0;
; [/ G$ f# m% x  }7 K                ave += (max+min)/2048.0;
' s) F; @6 P7 h. r4 L( S                output -= (INT)ave;
! z# }1 V3 `5 s4 t/ }8 u% W/ v                }2 j& N4 z+ l( x% a+ `3 ?' e
#endif* g( t2 H% T2 D) U) `
#if        1, `; V' f* ^9 k+ V3 t9 e. J
                // DC惉暘偺僇僢僩(HPF TEST)5 R$ k  L% E' o
                {, ]: j# v& p7 }+ {* ^) N6 U
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. m5 g* s/ |! R! l                static        double        cutofftemp = (2.0*3.141592653579*40.0);: u% x) m' T. l( y. F5 c$ V0 W7 O
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 H4 o. }# O/ K% I# P                static        double        tmp = 0.0;, _  f2 a! c4 x! H& ^
                double        in, out;
) Q! W4 u  N6 M! M- H: \3 y9 @6 M
" O- W. }4 l1 N7 T5 z' B                in = (double)output;
  S* @- |* n2 ]                out = (in - tmp);
; ^6 I  Y0 v9 Z" S; g                tmp = tmp + cutoff * out;4 b1 Q8 k5 T3 |" ^

% Y% ]9 V, ~" J3 O                output = (INT)out;
  g- E* v9 Z+ k                }
/ i. I; f# ^( A5 c8 \3 ?#endif/ _3 R1 P. U5 w/ _! h
#if        0
8 c8 a0 L6 `6 i4 c                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)/ l) D& T. m. Q2 I2 q  H
                {
" ^3 s6 w% s7 E                INT        diff = abs(output-last_data);7 K+ d' a1 A& d$ ?# {
                if( diff > 0x4000 ) {
0 E8 e8 E+ I+ K( \2 o4 y, L$ h                        output /= 4;: ^# B7 C6 Q$ c+ X% R1 }8 {
                } else 8 \) V0 Z  Y9 o8 x$ ]6 P0 s; d# N
                if( diff > 0x3000 ) {
- k1 d1 ?; ^& x- w+ @, ?9 ^                        output /= 3;$ g$ k: y3 M8 _4 t' V7 b+ \
                } else
( |" B' J7 y, r* w2 f. ?                if( diff > 0x2000 ) {# j( e; n2 _! }' p$ o3 a# A8 G. C& c
                        output /= 2;
  V, Z, H* _5 w, {, O" K                }) F! l* L3 v  t+ ^" ?
                last_data = output;! U, n2 g" U& }6 `
                }; a6 e4 h* ?& ^& D( X8 [
#endif
; {0 p; A; s2 I( p. ?6 O" z" f                // Limit& w3 z2 @; P' N1 @* d: K: ~
                if( output > 0x7FFF ) {) {' R9 J+ A& X5 M3 H$ O# l
                        output = 0x7FFF;6 m; M4 `: h" x; y0 h6 o
                } else if( output < -0x8000 ) {
6 p$ f8 n9 j0 B7 J5 F: I# |! l                        output = -0x8000;) l, N- m/ S  R0 D
                }: U1 k' B: W, D

8 z1 o3 M- P/ _3 h/ `9 b                if( nBits != 8 ) {6 C( u. U$ K- B( x
                        *(SHORT*)lpBuffer = (SHORT)output;  ^4 m: ~, c+ D$ {* X8 L9 j" q* f
                        lpBuffer += sizeof(SHORT);9 L* M* |( t" D+ l0 S
                } else {
! q! P' v+ I( w# e7 \                        *lpBuffer++ = (output>>8)^0x80;
" n( Y  o* G- K' N  c' j5 z6 Q- t                }2 B# y( F# t) q% r, ?) x5 r
2 L" }! X. X6 |1 W! W# d
                if( nCcount < 0x0100 )
4 s9 E9 m. S# X7 F                        pSoundBuf[nCcount++] = (SHORT)output;
2 G$ A3 ~  y* G3 \+ G4 M
6 j" z5 E* ~( [! e//                elapsedtime += cycle_rate;% K' g" l9 E( W' w! x& R0 I
                elapsed_time += cycle_rate;
/ H0 C4 S  u* T- [, x& L        }
& I1 a$ U7 X/ i- i- v9 Z) q& S' J" p% S! T  X
#if        1
  \$ L6 X( i1 r! M3 G1 p        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {/ C: w9 w2 r! Y4 P; |2 I
                elapsed_time = nes->cpu->GetTotalCycles();
$ _! O: _7 p# u* @9 X+ E        }
% r7 D# ~, K: m+ i9 p        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {- f7 n, z+ d: X; T9 o
                elapsed_time = nes->cpu->GetTotalCycles();3 `7 B; o) p! y, `, O. k# ^, ~
        }1 n  N' `- A( n8 n
#else/ d- P) I9 u* B9 u( ?
        elapsed_time = nes->cpu->GetTotalCycles();
- g2 b9 b, _; A) C* z' Z. z#endif
& F: z7 f- ]  l5 v9 L8 J7 h}, Q. S& K6 [9 x9 T
  \, ^' K& o  P9 O
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 c2 N! J4 q1 {1 E8 N% u% v5 l
INT        APU::GetChannelFrequency( INT no )) c) K$ ?- I2 z" j, ~
{
7 s; o/ p# D( ^  q8 G1 c        if( !m_bMute[0] )/ H; J8 k% E4 v+ c; R! ~
                return        0;( p4 A7 l! U4 q4 X% Q
6 s3 {; N8 i# W, Y
        // Internal
; a0 X; r. }* o, S8 ~- `        if( no < 5 ) {
/ G5 G* C" d0 `, _, S/ c                return        m_bMute[no+1]?internal.GetFreq( no ):0;
! L" ?0 s0 M+ s' X        }
  ~* M! d. u3 C5 h        // VRC6
: C; _* E2 Z6 n- b2 r- h( P; }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 |3 ]7 k4 I' B% r2 K5 U                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ T0 i! @" v8 `  D) z# F* L
        }
* h* ^0 M% p/ ]# A        // FDS
. j, h4 w0 X' k1 h        if( (exsound_select & 0x04) && no == 0x300 ) {; k) h2 G' }2 ~+ o1 b2 Y) b
                return        m_bMute[6]?fds.GetFreq( 0 ):0;& g5 g! E; i/ Q1 {6 L. m+ T
        }
9 ^# ]0 V+ D. w3 \1 d* \        // MMC5$ F! A- K9 `: k
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
  ?4 s! h$ {6 O/ ?                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;# i* h2 t9 ]9 D' }
        }
# X; D9 d  }, `        // N106+ F% z& F5 Q; D9 W6 K
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
8 L5 i  g4 n6 Q6 u                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;& ^6 E6 _5 V% H4 G# Z" V' S; w
        }
* ]4 m; c7 D1 O" T, P        // FME7. X0 ?9 h5 n$ v9 d
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {! e! Y5 Z( o8 C- ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;& E# q& Y$ x, b4 V. S  @
        }! F$ S. o. D# d' ^
        // VRC7
- `3 y2 x6 j& |* r0 U1 }5 n+ v. N        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ l. }  x5 q9 F- D) q                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;) v* B) T- p8 ]) S
        }
# c. c- ^1 u% Q4 [/ w        return        0;8 t, c. I" l5 a- t5 A5 i3 p
}
/ G: X- q9 d5 m
3 w' q9 ^9 I$ _; R& f// State Save/Load
4 m; I) _8 T- N' }% P5 ^$ _3 l1 ovoid        APU::SaveState( LPBYTE p )+ V& l& {" [3 o" p' Z- w8 u. n
{
: `1 \2 ?% O6 [1 ~- W#ifdef        _DEBUG! o) E8 }7 C& y5 ]" y
LPBYTE        pold = p;
: E- d2 N( X" _. ]#endif
( }/ V( z+ B- X8 [2 v; a* x$ D3 L
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
$ Z: e5 ~; s- d        QueueFlush();
8 N; K1 U, j7 g- |# b6 N+ S9 G9 x
        internal.SaveState( p );5 j7 y' Z. C! J, g! n
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding- ]/ A  D8 R, q7 Z7 s5 b

& A; }( i( X% F9 b  C7 Z        // VRC6
2 [7 x, s! f4 d4 o' P8 E        if( exsound_select & 0x01 ) {8 m" Y+ f9 ~) W  m/ U+ L1 @5 ?
                vrc6.SaveState( p );
- y3 i5 S) s/ e. F                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
6 ]5 j3 ?0 j* _2 W        }. U, B2 s& E% y7 F
        // VRC7 (not support)! W. @* _1 ^0 X6 h$ W# l( h
        if( exsound_select & 0x02 ) {
4 X) j1 S0 s! Z                vrc7.SaveState( p );
6 ?9 }+ O( v, \2 l+ W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding0 i0 B9 h+ G1 F7 a4 w
        }
/ A/ d4 d0 K; w# p        // FDS
, p& w+ F( [9 @/ R* z# Y4 k        if( exsound_select & 0x04 ) {$ b2 S$ d: P) g8 Y2 u' x
                fds.SaveState( p );2 h1 T* P/ O* P; A8 K8 M
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' T( Y( g# z/ y. x3 X3 l
        }7 I- n2 \, }# Q+ K' A' `4 l5 z# a
        // MMC5
( q$ u8 n  m& ^" I, i3 Y        if( exsound_select & 0x08 ) {! V$ |4 ?1 D7 Z
                mmc5.SaveState( p );
0 U( i0 ^. G9 R6 i0 W1 d9 s                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 {2 v# c5 u9 M0 i4 P: `
        }
+ Q( y% b. X6 f1 U2 U9 Q2 ?        // N106
  `. @# u7 t/ k. A2 Y        if( exsound_select & 0x10 ) {) h9 \/ i% A! P3 i$ n! |
                n106.SaveState( p );4 ]+ E4 Z; N! N& S: N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. N" Q: h  H3 h, q8 k: i+ T
        }
4 k1 T0 y1 w9 _( E8 u$ d        // FME7
* T3 b6 @& m. t        if( exsound_select & 0x20 ) {
4 y# H4 j& `- h: M: M                fme7.SaveState( p );6 N6 O" E3 i* q" G  M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ p# c0 D7 I6 f  h  @
        }
6 `0 r6 j( r& ^1 T4 N& }9 J2 X' O* `, x' @: L
#ifdef        _DEBUG
2 T! u: {8 a9 J! M1 CDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );/ O& y& Q0 L& E0 B  z
#endif
4 f9 D! D& c; C. L0 r' T$ F}: i+ ^, I- n) c* i' x1 R
3 l/ o) o8 `& V
void        APU::LoadState( LPBYTE p )5 Y/ b( k/ w8 L: F; i& ?3 J" [
{  H+ k( w& g! y* }: U
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡" K$ `( |5 Y" j; H% k! W
        QueueClear();' i  X  m3 I8 E' ~3 b/ P: {
) B, U! M4 x" F# q# T$ z  j) e
        internal.LoadState( p );8 e2 c2 u- v; l( H, ]
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" T5 i- Z$ T' P; S8 U) O
# `$ @  ?" ^* M* L5 E        // VRC69 |( ?2 H$ J9 {3 I$ f+ R
        if( exsound_select & 0x01 ) {
& t0 G4 J+ a/ h% k4 z                vrc6.LoadState( p );9 u) _, J4 n4 n# _) |1 o5 Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ f' g1 w2 V1 D& c3 s        }
' y8 B7 a) T$ x. P; E7 ^3 o6 H        // VRC7 (not support)
/ w& X$ l; l" x! G8 K" g        if( exsound_select & 0x02 ) {8 H4 A& F* B: D. T; A9 D% s
                vrc7.LoadState( p );
" I1 i& s  K+ g+ g                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 N0 @! J; e9 h, S6 x
        }
* v$ j1 L- z4 u3 y, W: r- @        // FDS
7 X7 H' {# S! ]7 G        if( exsound_select & 0x04 ) {! |* l$ f/ E2 H7 e
                fds.LoadState( p );
4 o# ^! R  k5 Q$ ]                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 e2 v7 r  N: u% w2 S        }
: z8 g# V# L: }  |        // MMC55 t& l+ [: v1 v- E& W
        if( exsound_select & 0x08 ) {' l' y/ `/ y/ X! C1 L
                mmc5.LoadState( p );
4 x3 F5 C+ `2 `5 O# k& Q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 ^4 U0 \7 z5 j( M
        }- }' M5 [$ b& b$ y
        // N106
* `4 \0 G, M% S! d3 S1 R% W        if( exsound_select & 0x10 ) {
! ^& x. }* x' t* z, ^                n106.LoadState( p );
* ^4 a* T; P) h, h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 q! q2 l4 x- C/ g3 {5 Y% |9 h        }+ {; P( |! ~# f- n. F$ \
        // FME7
7 ?+ A: T3 v% D9 m        if( exsound_select & 0x20 ) {: U5 ~& \% `4 h  Q
                fme7.LoadState( p );
; F9 L% Y$ |. u                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; \, |7 f8 m, s( D% a% O        }
, ?) {9 ^( M% e- y' ~! n4 Q) ?1 l& a}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; A; L! j; ^0 f7 d8 A( U0 }  e
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
$ g) L4 `7 u. K/ d7 p0 f+ w. D感激不尽~~

: d  n! G- v7 o$ i" b$ V恩 我對模擬器不是很有研究,: d0 h7 f, v. t* M( ^  ?* }
雖然要了解源碼內容,可能不是很困難,, ]1 ^, x& p% E$ O( t  g6 V% V
不過還是要花時間,個人目前蠻忙碌的。. ]" C* I5 v+ d
* @$ \4 {7 t" ~8 E1 p6 }$ i$ Y; p
給你一個朋友的MSN,你可以跟他討論看看,
* q) D. ?& J' i: ?3 h他本身是程式設計師,也對FC模擬器很有興趣。
5 b$ C, K% F4 W# T7 t4 @0 `) v$ S3 M& `% {
MSN我就PM到你的信箱了。
$ T2 P% Q! Z/ S7 T, B- V% c- B% S% j6 E% O8 n1 @
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# G; |9 s9 K7 U呵…… 谢过团长大人~~
2 P9 R- U& X- E, h# w
7 _) `& J- Q/ p! L) a
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# L3 B0 y: e6 K2 S, u团长的朋友都是神,那团长就是神的boss。
6 s1 L4 H! p6 U1 d
哈 不敢當,我只是個平凡人,! g  c, m: O& x) i2 p3 J
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 z- b' h& O: a$ L. ?" S/ _ZYH
" N! P6 ]7 S* A. JQQ:414734306  s, k* p4 k. \4 H' u
Mail:zyh-01@126.com0 K: y( J$ U5 b0 \7 A

! ~) Z/ ^: f2 w4 u/ G6 y2 r他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 + p* T( j8 S  p
再次对团长大人和悠悠哥的无私帮助表示感谢~~
/ I) u) b" X% T
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 09:22 , Processed in 1.077149 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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