EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  E; P, |4 D3 h+ B楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" w2 t4 T9 L, }$ O8 A, I  g
这里有相应的模拟器源码,就当送给大侠了~~
- G7 m' i: j! P8 k, z+ Nhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 9 V5 h9 ]0 C6 J8 [0 o
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& c4 ]$ i- L6 h楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  C. l' p( E3 q- P" \4 ~这里有相应的模拟器源码,就当送给大侠 ...
1 v  }5 f; {7 Q  ]. d
聲音部分(Audoi Process Unit = APU):
7 q0 k/ p3 [: o  Y, @) Y( q.\NES\APU.cpp' _( e! |& V9 Y4 h, ?
.\NES\APU.h' D+ b. y: d* k, ]( l

, d& x: t& y. p
& `7 T/ r; q; T+ ^5 n影像處理部份(Picture Processing Unit = PPU):
2 W2 v7 d4 C' G" d.\NES\PPU.cpp
3 W& W& `7 t- B! C& C.\NES\PPU.h
6 ?7 K$ s3 R' {. S% a0 T
. |; p5 C9 }8 k5 k如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。7 J/ i% J, _  q/ t! G9 m7 K+ y
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
6 L2 |9 w& Y4 S3 @7 _9 I9 o(由于很多专用术语和算法机理都不明白,所以看不大懂……)
# c1 p/ N( {0 t0 ]# j: x- A//////////////////////////////////////////////////////////////////////////
9 i3 d5 x6 @$ |9 \( k- p7 |2 i//                                                                      //5 E# f1 n* i9 d
//      NES APU core                                                    //
1 n! j8 A: u  {7 ]//                                                           Norix      //
9 E. G( S  M2 ?2 n//                                               written     2002/06/27 //# j- ?# T$ Z, ?+ c/ f5 T
//                                               last modify ----/--/-- //: U. C- P# i/ b
//////////////////////////////////////////////////////////////////////////
$ G& R# n. J( X2 C& b" i#include "DebugOut.h") d1 r, J6 C' H
#include "App.h"
2 d+ `: h$ [8 i#include "Config.h"
/ K3 r5 `) A5 O# p5 U6 p+ ~8 I& T
#include "nes.h"
+ Q) s8 J( a7 j. P" R#include "mmu.h"! ?6 }, ^1 Q( i, p. R# T" X( ]( X
#include "cpu.h") f& |7 @+ H- m
#include "ppu.h"# h! b, a9 w% V) B0 a) h  v6 k
#include "rom.h"( j  t7 I/ Z1 _' `: H5 y
#include "apu.h"
" L9 m! X5 E" Q) v$ n( c
# R7 C9 g7 b/ w, H: O7 B5 J% k// Volume adjust
/ M5 s3 T5 |: A$ z1 C, ^3 P// Internal sounds
: M1 r8 w1 Z% n#define        RECTANGLE_VOL        (0x0F0)) W, g; w" |/ `  f9 B
#define        TRIANGLE_VOL        (0x130)
/ b# n+ }9 F7 b9 h& Y#define        NOISE_VOL        (0x0C0)
" }, F0 g8 H; |7 I# E#define        DPCM_VOL        (0x0F0); [8 u$ B# L: J: P' r1 s
// Extra sounds
0 I7 V! h; R$ e8 K#define        VRC6_VOL        (0x0F0)) g9 R8 [( C- K) G& Z
#define        VRC7_VOL        (0x130)
2 Q& ~( H' x" }. U7 x#define        FDS_VOL                (0x0F0)
  S+ n; @/ n( u#define        MMC5_VOL        (0x0F0)1 U" ~+ W& l0 o; h. m; b
#define        N106_VOL        (0x088)
( K& f! Z- Z: `+ J#define        FME7_VOL        (0x130)
/ I9 ~& v& O/ v1 j/ B" j3 W, m7 r2 T9 v) w( O4 F( J
APU::APU( NES* parent )
6 ]$ z) M0 L( p+ Q{
2 ~) s- K  v# o# P) w8 Q( v. n        exsound_select = 0;4 m( ?) l$ n% \( z* C# x" \8 H+ c7 m

$ ?: U& o1 H  q        nes = parent;
5 g' V1 R: T- D3 S        internal.SetParent( parent );5 e: c8 J) k9 _5 p  T
$ j* e$ y: C9 ]. Z
        last_data = last_diff = 0;8 m4 v) O2 d7 y4 Y% o
6 L; Z8 g: K; V1 {3 U6 {
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
: L- A$ G, R9 w* T; K# y. e/ k' z4 x6 l6 X0 Q0 s1 `6 I
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
5 J: Q  Z) @# F! c1 U$ [0 Y" q        ZEROMEMORY( &queue, sizeof(queue) );
* e" V* T8 v. i0 o* j        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: b, t1 l, z) V/ m. v2 b& \
3 d, |6 c. c1 O+ U: ]! w+ b5 b        for( INT i = 0; i < 16; i++ ) {( j# ~' M, F" M8 x
                m_bMute = TRUE;
  s( l  E9 X1 ^* F7 l        }: a. ?2 P0 }/ l/ T
}+ \5 V2 i  q! ?  j: p; K+ s

: G& b8 a. l  O" jAPU::~APU()
, ]/ [) J" R/ }; W: m% l{
6 I2 ^, K# m4 Z' r, C9 Y. P}
. l% `/ I0 a8 Z
: X" e9 z/ k) V$ h* b" K9 Uvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 T7 E2 c: H8 }/ J3 q/ R7 J$ R' T* W' t& ?
{
" i' L; [  L( d8 z! `# t        queue.data[queue.wrptr].time = writetime;1 Z" d4 w1 g3 q$ N% d
        queue.data[queue.wrptr].addr = addr;
. x" e$ o3 U  n. d, Z        queue.data[queue.wrptr].data = data;
4 T: a& U3 X' }        queue.wrptr++;
2 k5 n% {! M! }/ w* N; L/ z$ q        queue.wrptr&=QUEUE_LENGTH-1;0 r8 S, U, B5 M- E
        if( queue.wrptr == queue.rdptr ) {  d, J% s$ B9 }0 Y1 h6 F
                DEBUGOUT( "queue overflow.\n" );
: e0 e: ]* ?& ^& C        }
* V% W1 M1 r, D' X- O}
  @' L+ o" m$ I/ U: G" f+ [) C- v$ n- a$ I! U
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
4 h6 U' q& [! O9 m. r{
: W& |3 _4 p$ |* X        if( queue.wrptr == queue.rdptr ) {
1 p) o4 |9 m' ~% _. l' ~                return        FALSE;5 Z3 H  n9 i& Z) h  `0 x8 K6 @& s* t. P
        }
6 p1 E, `7 e4 _. y# ~1 \        if( queue.data[queue.rdptr].time <= writetime ) {/ F4 R$ v# a3 a- [2 a; v
                ret = queue.data[queue.rdptr];
7 ^5 W" Y# H! \5 O% u                queue.rdptr++;
' i) r9 g* D6 y8 `" d% H3 p6 a( w6 ~                queue.rdptr&=QUEUE_LENGTH-1;* x& }, `$ g) l. [
                return        TRUE;
  Z5 t' U: K% J" }8 J. N3 B9 d        }
6 K8 x. @5 I* I        return        FALSE;
; z, U$ B! Q8 r9 A2 u7 O% W, _' c}. E9 _& B5 n" B+ i* E. R9 }

- F' {7 s2 d2 i" m, {4 M; Qvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ m3 y4 `# T& P7 j; v
{
5 n. O; z6 X+ H5 o        exqueue.data[exqueue.wrptr].time = writetime;8 I: `, P( m" V. \# x) p# W5 V/ e
        exqueue.data[exqueue.wrptr].addr = addr;+ f+ ^5 V# M- d" v
        exqueue.data[exqueue.wrptr].data = data;4 ~' P( @9 e' b/ r# K8 |) k5 \
        exqueue.wrptr++;; M, R) p2 d7 J" R% @
        exqueue.wrptr&=QUEUE_LENGTH-1;
8 B( ?+ c% i& j. k. j9 @5 z        if( exqueue.wrptr == exqueue.rdptr ) {; N2 \; W: Q( `3 n
                DEBUGOUT( "exqueue overflow.\n" );
) l8 M0 _6 z5 Z. T        }
2 z1 l6 X% s; H2 X" t/ }8 F}, d5 d7 {8 ~6 U' x
8 [" O/ {+ Y3 y4 c
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 l8 t4 f9 `  u' [! i{+ z! l4 V3 s, ~, X: Z
        if( exqueue.wrptr == exqueue.rdptr ) {9 f: N+ a, C: G. i; S' G
                return        FALSE;. H) f5 Q* E3 Q
        }/ t  D" ]3 d2 [; J
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
- v, |( h4 x% A3 C1 s3 T- S                ret = exqueue.data[exqueue.rdptr];
& M0 `! M: p; s* k$ H                exqueue.rdptr++;- r1 I8 O; w  |% v) J. @& Q  J
                exqueue.rdptr&=QUEUE_LENGTH-1;/ Z% p7 J$ Q5 V. ^2 j( @* a! h3 t
                return        TRUE;
. R  d. O5 }% @0 a) S8 L        }
3 x: r8 k. O9 Y' [9 \. l4 W* s        return        FALSE;0 {; {+ I$ e4 \. y% H) _1 _* K1 x. G
}. p4 e7 n! }# a. v, [+ m
/ l: I5 f: l. S) V9 \8 M& d; f
void        APU::QueueClear()
7 n2 T$ W  g1 [9 C) [0 N{
( t. _9 p' Q' D, ^6 n( Q2 @        ZEROMEMORY( &queue, sizeof(queue) );: a, U0 i5 a, \( _3 h
        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ l) t; ]8 X5 V( B
}
) U( S# m; k* L; C. ?# K6 {9 y; E9 ^8 g0 W
void        APU::QueueFlush()
  D$ d% m( B% Q2 U{. i6 }# @. U. V* s
        while( queue.wrptr != queue.rdptr ) {, a' U0 o. T& M7 A
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& W! p+ q: _! y8 \7 I. W$ F
                queue.rdptr++;
! w2 ?* ?" R, ]& n  U* d                queue.rdptr&=QUEUE_LENGTH-1;3 E( \- I. \  D0 p( e
        }
- u' T) }  g; k* ]! c" u
+ _* E, W! r" d7 }( c        while( exqueue.wrptr != exqueue.rdptr ) {! ^& e. k/ L# S0 x3 O7 ~1 @3 E
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
& K( _8 {# F  m. ^- o! |                exqueue.rdptr++;
9 S9 `7 W3 ^* u& k                exqueue.rdptr&=QUEUE_LENGTH-1;
) v( N/ [5 I( W. [7 K        }- q- u* f. |6 l7 Z, K
}& C( Z' X; `* ^/ o

* l7 h/ f. n$ k. z* l2 Qvoid        APU::SoundSetup()+ V) D7 t6 r2 r$ {: i3 L' I
{4 H& F, b5 I; P- K; W
        FLOAT        fClock = nes->nescfg->CpuClock;
, K( ^2 j7 H; u/ Y2 M. s        INT        nRate = (INT)Config.sound.nRate;/ |# k: ]+ [% t" U6 Q
        internal.Setup( fClock, nRate );  j$ J% Q" j2 m/ C
        vrc6.Setup( fClock, nRate );8 e$ X) p/ m, |9 k# f' T* w
        vrc7.Setup( fClock, nRate );" G/ {7 ]1 Z; ]+ l3 e
        mmc5.Setup( fClock, nRate );
; g" ?- @! @, n6 `/ p        fds.Setup ( fClock, nRate );
& a( y% r) Y8 Q% [+ |* v        n106.Setup( fClock, nRate );
7 n9 i$ a' ~' w2 Z0 S        fme7.Setup( fClock, nRate );
( r9 X( g; \4 Q2 t: e6 x}  Y& n. n( |/ ~8 v0 h

7 K2 O% X0 e. Y$ h+ gvoid        APU::Reset()$ h% B1 l7 D" ]. @
{
6 U& l+ F% S. M7 p        ZEROMEMORY( &queue, sizeof(queue) );2 z  h. B; |$ S1 i: l5 c# u
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 |) B+ X6 ^2 k& Y' [( i( S/ z
' I9 D1 y# B0 Z  b% \( |7 \# d7 d0 e
        elapsed_time = 0;& C$ o0 F2 C2 T  q* f
' t  d1 u8 @7 C1 O  q
        FLOAT        fClock = nes->nescfg->CpuClock;
! R4 Q5 x# W& U% J: f! p        INT        nRate = (INT)Config.sound.nRate;
4 X' H( j7 D+ A$ U        internal.Reset( fClock, nRate );
! R6 V( j% u6 ]        vrc6.Reset( fClock, nRate );4 t9 l+ K' M" ^1 D
        vrc7.Reset( fClock, nRate );
( s) F8 F2 V( d8 W+ D) i        mmc5.Reset( fClock, nRate );* v, Z. g: l( D; f& Q6 x3 R
        fds.Reset ( fClock, nRate );% v1 k9 o' h; N2 x3 u$ f3 H' L
        n106.Reset( fClock, nRate );: H! i; c+ l$ l, V1 x) t5 W
        fme7.Reset( fClock, nRate );1 K- j+ a* H, C9 g2 ~6 m: z
0 ~- |3 c* n4 e/ \
        SoundSetup();% ?, S7 f1 K8 N$ m! u: j% j
}
. t5 V; q7 u" T( u  L7 S
# [% ?" i( Z" Nvoid        APU::SelectExSound( BYTE data )
$ V  \5 f8 G3 S7 F{0 h. C& n1 g7 |( ]4 U$ ~4 H
        exsound_select = data;( o; Q. Q) i; ?
}# y- x+ |' }0 i& E* W

4 L; W, q0 D% u9 xBYTE        APU::Read( WORD addr )
/ j& u  }. s1 |$ @' w{
- `3 E  j1 m$ Z/ H2 S$ ]8 X        return        internal.SyncRead( addr );
8 U8 a2 n3 H& }0 X}: ~- _! n; ]! d7 p0 S1 p

: q) p# `% }# p8 U6 B% Bvoid        APU::Write( WORD addr, BYTE data )2 E3 |& J! [) `  S' P
{/ L! Y: E0 K, i+ c2 J- e
        // $4018偼VirtuaNES屌桳億乕僩
# L* V& t2 @% o5 l: b        if( addr >= 0x4000 && addr <= 0x401F ) {) ?- R8 Z0 Q. Q# ]6 f
                internal.SyncWrite( addr, data );" z' h' U5 R5 n" P+ M4 ~
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# [$ x/ ~" U/ A4 r: g        }
7 n9 H7 f# R% S7 }9 e2 q+ ]}
  L0 v1 D3 Z2 F. v+ ?3 r6 Q5 h3 f" U2 U; U+ U4 v! ~3 C5 g6 E
BYTE        APU::ExRead( WORD addr )
/ a8 s8 R& H# u{
, `# ^+ [4 Q5 W0 O& TBYTE        data = 0;
9 k" ?' p  X2 P( i3 R
2 c' e* x) s8 T0 {- U) [        if( exsound_select & 0x10 ) {
& _! A6 n& C- Z; f                if( addr == 0x4800 ) {
2 A: M1 R' T' q: A+ t% i# E! S                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: H) D! i4 U5 @% x  q+ ~9 S
                }
9 x! v+ r8 J. J' r        }6 v9 \; L' q- R; r/ J
        if( exsound_select & 0x04 ) {
8 W9 v+ M9 l( F  W9 I                if( addr >= 0x4040 && addr < 0x4100 ) {
  ~$ N5 U# u. L  n                        data = fds.SyncRead( addr );
1 O+ |, D9 D! g  r/ V                }8 _, T, m; e$ x
        }
* P) T: a9 m4 T        if( exsound_select & 0x08 ) {
  f- i$ c& R+ H( G: T4 @                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 t1 E! V8 W) w& e8 ~                        data = mmc5.SyncRead( addr );
' C& ?$ r; B' h- M7 ]                }* @& \( F% z3 [2 {
        }  \! a! S( o% G$ Q
( a) `# a) H3 E% o- J- J% n* m
        return        data;
4 C( R/ K4 e; z' D}& Q' |5 a! i. P: y5 i5 i8 |

1 x' V7 M1 F# D7 C2 c9 t  [void        APU::ExWrite( WORD addr, BYTE data )6 B3 |4 D# X1 l4 k
{
. p$ a: z. `: G        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );# F5 e% i. d# u  y
8 P0 k6 V- B8 e6 v. |" `
        if( exsound_select & 0x04 ) {  u& \2 |- j3 V' B
                if( addr >= 0x4040 && addr < 0x4100 ) {! _" ^4 a, A/ g7 y9 b
                        fds.SyncWrite( addr, data );
1 z' ^2 ~) E% h  a3 W                }) L# c/ F9 d, `* |
        }& i% k. K$ H2 Z% a2 O' _4 K/ z
! c( c( Z) ?! m
        if( exsound_select & 0x08 ) {
4 z+ I$ s, l3 K# h7 q7 A7 a                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 S8 `) i# n" s! L; w                        mmc5.SyncWrite( addr, data );
9 d! J0 `( u& W4 i/ c                }
5 b) A) s2 R0 Z6 H8 z8 P+ R        }# _1 V( l7 |4 y
}
4 B/ v8 ^3 }0 O% Q9 A$ y
. u4 g6 E% ]. |4 B- qvoid        APU::Sync()* d$ ]; A; g; I8 n5 P) G
{0 O$ K3 h; u% d5 g" @
}
' y/ @8 X2 D( K
& M4 ]0 K; k/ g5 X. \4 m- I# |void        APU::SyncDPCM( INT cycles )
  s, V7 E/ C! n. U{( ~+ ^9 W, \/ e
        internal.Sync( cycles );$ n7 K/ J3 e2 j, Y0 \
: m7 y9 X5 U  b/ C9 C6 D8 o
        if( exsound_select & 0x04 ) {
* D0 ~- t  K' F2 T, M& {6 v                fds.Sync( cycles );; ?/ x8 g6 a& q5 t1 }3 R! ^
        }
/ N  T  L: E- {; E        if( exsound_select & 0x08 ) {# }: T4 J8 K: ?) @$ b0 t0 Z
                mmc5.Sync( cycles );' s. o7 @: u; b& a) v! o, W
        }7 c+ q, E+ }' k7 \% [
}
& Q$ o4 m( [  r' @5 k( G- t( w1 z% Q' a
void        APU::WriteProcess( WORD addr, BYTE data )8 J/ H+ ]8 q- T8 W2 a9 Z6 r5 L, N
{1 Z$ k+ t% x1 D- ?% P& W6 ]
        // $4018偼VirtuaNES屌桳億乕僩" Y9 E2 z6 r5 {/ j; ~9 o
        if( addr >= 0x4000 && addr <= 0x401F ) {
$ _; l; d7 @# J3 G" U! {8 ^& k                internal.Write( addr, data );/ Y! C  K- e) D( f. ~8 s+ f
        }
0 H1 H, u+ b& W7 ^# R+ F}
# W0 f, y3 c- P2 Y# V
9 K: R8 t( Z3 C' k. uvoid        APU::WriteExProcess( WORD addr, BYTE data )
7 R  ]4 S. E2 z- R* i9 V{
4 ]. R/ {1 Y2 y" Q" U6 I        if( exsound_select & 0x01 ) {* L5 w" q& q: q  f  e( O
                vrc6.Write( addr, data );" Q# T) |9 g% Y1 ^5 E" H
        }0 M$ y, s2 k9 F' p% j2 y
        if( exsound_select & 0x02 ) {
5 h1 c0 u! T5 c6 A& N                vrc7.Write( addr, data );
7 m5 h3 I  {, H: {( Q        }
1 F7 \5 L, l- ]2 A* z        if( exsound_select & 0x04 ) {) B" H: C4 s- P) \, a+ F
                fds.Write( addr, data );
5 [& Q- y; |1 F; ~2 q        }8 N! G" G* m! x, K; N; ^- @
        if( exsound_select & 0x08 ) {: F8 \# [, e% d0 u+ |/ K  |2 c
                mmc5.Write( addr, data );
; K7 w  R! J5 t0 |1 t% A        }
3 s# [9 W/ N; r4 L8 z8 w9 f        if( exsound_select & 0x10 ) {+ q3 t; |1 l  b) Z8 E' m
                if( addr == 0x0000 ) {* A$ [. x9 W3 }+ ^
                        BYTE        dummy = n106.Read( addr );, [: b7 K4 b) ?+ L% U8 i% ?  s. }
                } else {/ P1 M) [9 g9 k7 M
                        n106.Write( addr, data );
+ `- w; E, c+ X% X# H                }7 Q5 a% {( q" p4 x" t
        }7 H# U; G) r7 ]- [" y% s# r3 I
        if( exsound_select & 0x20 ) {* ^1 L1 @5 I/ Y( m% |5 G
                fme7.Write( addr, data );: \' ^  @) h: [3 R! W) h
        }+ C; v4 }4 a2 W' N" q
}
, R% j# V) L. ~( x
2 z9 Y) C# U9 bvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )/ R" ~5 }7 d2 P! ]" [
{+ b1 t; d2 p. e* k9 d8 ]
INT        nBits = Config.sound.nBits;
( _+ g' P( z) Y4 `  ]DWORD        dwLength = dwSize / (nBits/8);
' ?0 |1 o4 i' t4 sINT        output;5 a1 ?4 I( X# @* v7 |1 P1 F, Q
QUEUEDATA q;
8 t& y  ?* K0 R6 u+ }# QDWORD        writetime;3 `: x' b5 q, y/ m
6 z: m6 h& y- j/ N4 a
LPSHORT        pSoundBuf = m_SoundBuffer;" r8 s0 Z/ m6 a# ]7 c9 R$ U8 R
INT        nCcount = 0;- H* E+ ]( }  |2 {9 D4 v; p

6 ^0 E4 c" |# ^' g% C/ N" rINT        nFilterType = Config.sound.nFilterType;5 z) g# t% E" W

6 j  L# |) s' v4 T# V/ b/ O        if( !Config.sound.bEnable ) {
  y+ O, `$ k8 }) }                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 Y8 n5 x9 E( E3 _. X4 l5 E, E6 m                return;( @/ ^  Y) A3 Q, V1 S2 N
        }
- `6 S) h  Q  v( [, o3 o' x6 f6 r" E  O  H8 [+ k9 a: o8 X
        // Volume setup
4 N! G  r2 m# s: c- f* m        //  0:Master* f  ^' W& W, V
        //  1:Rectangle 1
0 _  f. v4 m& y; }: @  D, B3 z3 {        //  2:Rectangle 2' r/ G0 m, [* A6 s( w
        //  3:Triangle
! @' N" b$ D5 d8 I5 F        //  4:Noise! k; F# L: t, ?" N7 n2 m9 K# [6 Y$ y. s
        //  5:DPCM
$ r0 ^$ H1 |# `4 P        //  6:VRC64 ^/ d% c, Q# o5 b" ]
        //  7:VRC7
7 E. `* A/ t7 ]        //  8:FDS4 S; ~3 [+ u9 I- o& ~; d+ X7 U
        //  9:MMC5% p6 P0 c. B7 }' y8 L' g* C% h
        // 10:N106
' X3 X2 }; h2 E        // 11:FME71 M1 R& J* L5 u& V
        INT        vol[24];; z; ?, D& Y- Q. \
        BOOL*        bMute = m_bMute;# C* q+ m3 C- ]1 P6 c2 S5 F" x; e! m
        SHORT*        nVolume = Config.sound.nVolume;; O$ Y7 Y6 i% e* k% A( w
# Q/ I' T. l- L4 J: z+ ]& t6 X8 [) s
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
6 F! s1 \& |0 _8 f7 N, h% j, c& ?, Q' K+ N3 M; [1 \# ?
        // Internal
, A" M% S' {0 o( z        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
- N4 @! F2 H. }2 Y        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
- W  h; G5 f2 F$ G+ }  z! z        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 m; y9 a* u+ |9 G
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
8 v+ r5 ]+ z, L- b4 I* w        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' Q* e: t* \" a! x, y

( I( E5 R' T. Q) ~8 t7 e        // VRC6
7 Q; r0 n- A6 H' u/ l; J1 b2 l        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% I" n1 j/ q  b$ o  t3 S3 M; s4 A! f        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# w6 E1 r0 h0 ~( S* k& z0 t        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& X( V; @% r. b9 l6 F: D# L& x# @7 \" d( F
        // VRC7
; `7 p4 C) G: j/ _; g  Z1 z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;6 {5 A1 F( _2 F7 L9 M2 l# X

' g( ^* V& a8 ~7 q        // FDS5 z5 s6 }' ^  ?
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
1 w. y: p! U5 M+ g' h( z( w  K6 f0 I
        // MMC5
' I& p, {9 {3 e: E        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 l0 r5 Q4 j; P6 u3 x6 D
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* {# n* h  o' N+ v* b6 ]1 D        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! D, Q, \; x9 n  S! q* f

. T; f1 g/ I! _* l2 j' V        // N106
3 E% H2 r& v) r9 w8 o: s$ a( w        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ l7 z2 [4 l7 N" E
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, n8 L) m7 t8 ]% }1 b
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 ^' W, a' ^) h; ~9 I
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 ], F/ u& A3 L  c1 B) {8 F) w        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 X  F/ B1 z. f) v( S        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* }- h( N: |: F9 g5 o& M0 S9 F
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" V* A" R. D! u        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# T$ W. m$ _, F" H# b) x+ ?* D
3 E/ g3 Z# v, M1 n        // FME7
6 w; Z0 l/ ^- @        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ G$ j5 Q, \* b
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" ~. w4 L; ?, p9 e, e        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 J1 l- G' ^+ j! D1 C4 p# E; h  H' [! u& N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 ~2 s1 T2 J! ~% j1 [4 Q9 x5 n        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. F* [1 f  m. n* `, I6 c8 f* @* K5 ?- y  m9 e( }
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
0 q, ~+ e/ d) ^        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
; F9 t& [5 u  f$ f; W                QueueFlush();
7 G( ], Z5 @" O2 h2 j        }8 u& P# ~$ ^2 b

- v8 y1 c- m4 k1 j. ?        while( dwLength-- ) {
& s2 D3 o7 E# q! b6 h4 d! j4 V7 Y                writetime = (DWORD)elapsed_time;
+ p  v; O! {; t; ?. y, Q! }
8 N' a- R( V- k# G8 V                while( GetQueue( writetime, q ) ) {
* k0 b% c9 r5 K% i; t# Z# y                        WriteProcess( q.addr, q.data );
: K3 F( X, H- ^! J                }% u) Z$ x) B2 k  z

. v7 w- W9 z5 p( D* l* ?                while( GetExQueue( writetime, q ) ) {7 y/ X, y( V3 o0 \  v
                        WriteExProcess( q.addr, q.data );2 P; `: W8 ]. O, J5 v
                }* N; o% J. g6 z; C3 q

, P3 X- }) K  ^' p) J9 _                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
! ?& z3 q5 \, X                output = 0;
- O6 J2 d* }9 F5 `' m  ]9 Y                output += internal.Process( 0 )*vol[0];
6 [' N; `% }+ E                output += internal.Process( 1 )*vol[1];* a9 ?% [) m- w4 |1 l
                output += internal.Process( 2 )*vol[2];
' |: Q0 d% H2 j9 H  K* I  t+ Y                output += internal.Process( 3 )*vol[3];
! U; G8 k3 j+ U* O1 d$ o) m$ Q                output += internal.Process( 4 )*vol[4];' S6 y- x5 m* i$ \
  y: d. F( k1 C, u9 U" v3 D
                if( exsound_select & 0x01 ) {
/ Y, J. j1 o& D- K                        output += vrc6.Process( 0 )*vol[5];
$ U+ B0 `: i1 d% q+ @2 m                        output += vrc6.Process( 1 )*vol[6];$ m" S7 A! u- N0 b
                        output += vrc6.Process( 2 )*vol[7];+ H0 U2 R, A6 [+ L) T, `% h$ @, K
                }
0 y: s6 T. n0 z4 V* F! T, u8 M                if( exsound_select & 0x02 ) {
, W* c  S7 P+ |- M' o                        output += vrc7.Process( 0 )*vol[8];: X( H. r7 D' N
                }
1 h9 H4 l; Q) Z. H8 q4 }                if( exsound_select & 0x04 ) {
0 C9 u1 h/ ^, `& }& F% F$ m4 J                        output += fds.Process( 0 )*vol[9];1 H' g+ ?2 x# ]+ z
                }! V5 T  H3 |  C& S; `! c
                if( exsound_select & 0x08 ) {
& J) L- e7 e% q! w1 ]                        output += mmc5.Process( 0 )*vol[10];  a' O" n9 C" u1 j5 ]6 F$ V
                        output += mmc5.Process( 1 )*vol[11];8 \. [& ?: q  d& h: W
                        output += mmc5.Process( 2 )*vol[12];7 G4 N- ]6 v& a: m4 k
                }
, J1 L2 k1 v+ D- e" D                if( exsound_select & 0x10 ) {
8 D7 J/ {* s, C                        output += n106.Process( 0 )*vol[13];6 R$ Y! r! D# \6 X' E/ g
                        output += n106.Process( 1 )*vol[14];3 u2 s+ c. u( a3 r* Z
                        output += n106.Process( 2 )*vol[15];
: E- P1 X$ a; Y" N- A# i! ^                        output += n106.Process( 3 )*vol[16];: c: P+ K/ z+ i* b) X
                        output += n106.Process( 4 )*vol[17];
( S3 D! C9 Z  l' K                        output += n106.Process( 5 )*vol[18];
8 Z4 E0 h- U7 w4 R1 ^8 h                        output += n106.Process( 6 )*vol[19];. z5 Q% K; U: ~$ R7 e4 T
                        output += n106.Process( 7 )*vol[20];' k9 P" ~; a2 [  B9 h
                }" c9 w( b" O1 R% N3 b
                if( exsound_select & 0x20 ) {4 h  T3 Z, @1 [( C$ v* m: M4 \, i4 j
                        fme7.Process( 3 );        // Envelope & Noise
, `/ u% f) E, ^+ ~: p! q                        output += fme7.Process( 0 )*vol[21];( C: S) `1 P9 B3 J
                        output += fme7.Process( 1 )*vol[22];2 Y# a; V) F8 B& g/ k: `
                        output += fme7.Process( 2 )*vol[23];
4 `* ~! j4 W$ I! T" _: t4 N                }5 D" Q0 q: h% y- {9 R

4 t) u0 Y4 v  t                output >>= 8;, |0 G- B/ c( v3 W* F
4 X9 R* u$ I+ ?/ u( \1 c  l- s
                if( nFilterType == 1 ) {
6 ?; L' J% o% k  x, S                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
- ?0 G8 A8 [1 ^, U& ], g                        output = (lowpass_filter[0]+output)/2;) W+ c$ |8 l2 `8 i' f6 U2 d6 \9 B. U
                        lowpass_filter[0] = output;" F' I1 r3 C9 T( @5 z9 l" P
                } else if( nFilterType == 2 ) {7 n- n# ?% s0 V+ m
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 D' f4 p! R& s3 Y" b
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;, R) S* U0 ?' G. y& R" {& o6 S
                        lowpass_filter[1] = lowpass_filter[0];
, g' a$ e' t5 p) Q* h' o2 V5 p                        lowpass_filter[0] = output;
, |/ P, ~+ m2 f# S& \3 T# G! n& W                } else if( nFilterType == 3 ) {
$ U0 a/ n# \9 x4 E4 W                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% L9 g' |& g* P: @2 L                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) e$ \6 K4 ]1 K2 z# g9 `+ A
                        lowpass_filter[2] = lowpass_filter[1];1 Q6 k9 ~) G& }) l
                        lowpass_filter[1] = lowpass_filter[0];
( L) ^& W1 E$ b$ }                        lowpass_filter[0] = output;
, Q! v/ s* z) w  p: G                } else if( nFilterType == 4 ) {
' x/ T+ ?9 q" O0 W2 R' g9 ]' \% H3 y& `                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
' n3 D6 R" ?+ n1 D' W                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;) k" u  K2 ~. a- \, }7 F0 u3 w
                        lowpass_filter[1] = lowpass_filter[0];
1 t1 E1 [3 M# f                        lowpass_filter[0] = output;8 W1 e4 u( k8 H, r- r6 V
                }
6 {5 j9 w) |" o3 c+ o
( V3 @: ?# w: a" e#if        0
/ [4 U, I0 s0 ~1 Z' ?: X                // DC惉暘偺僇僢僩* w' o; [6 ^0 g% A, ~3 L3 A
                {; W  T) r8 N9 L2 Y
                static double ave = 0.0, max=0.0, min=0.0;, j% b, f- W2 j; ~. A1 a/ J3 }  ]& W
                double delta;5 m! v) [3 f2 u0 z& L4 J
                delta = (max-min)/32768.0;* q6 R# J) @# j& x; C' I+ b, H! w
                max -= delta;" ?' Z1 m; E9 |' v# E. O0 G: V
                min += delta;+ \& [$ J& s5 Q" y; k
                if( output > max ) max = output;
8 [6 B5 F# _2 l+ Y- z# S                if( output < min ) min = output;% V* p! Y, j- U7 |9 a  F4 b
                ave -= ave/1024.0;5 m; A! Z. b- z* U! q
                ave += (max+min)/2048.0;
7 R# I) l2 D7 m$ S" G2 X                output -= (INT)ave;
" d- j6 L" v& ~1 j& w/ f: E                }
4 K8 u" D6 r5 {/ R" `#endif
* k; |, q7 C" K- J% R) m#if        10 m, H5 T4 @9 o3 J
                // DC惉暘偺僇僢僩(HPF TEST)1 G9 Y- k: Y' f& V8 H9 a
                {
% n% B# O* y4 h+ o& O//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- @" R- N$ Z9 [1 ]$ Y, M, `
                static        double        cutofftemp = (2.0*3.141592653579*40.0);: l: N9 A2 Z) s; Y7 ^$ R9 J
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
3 P" x  k6 l6 r8 _! ^9 O                static        double        tmp = 0.0;
. _5 h4 Q, s1 I  Z                double        in, out;
; h" R. [1 E$ n$ H3 K" p- g8 v/ F. E- N
                in = (double)output;
9 |3 e7 u: J. O% U/ m/ [) i4 h                out = (in - tmp);6 k8 C) |" h% r; R3 k
                tmp = tmp + cutoff * out;$ u) R1 k8 F4 B

# [# x% S, s; }: _& ^; Z4 l4 O                output = (INT)out;, a" i; B0 s$ p4 T3 S
                }
7 m1 t# B0 d4 Z8 T8 A: b#endif
7 k) R9 t. l# V* }& ^#if        0* \3 z7 }6 L' R  w3 b2 R
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)( X  X# O9 c4 a$ r
                {
' [& R+ l' t% D5 j$ J* w" X                INT        diff = abs(output-last_data);  H# ?( m. W* C$ m
                if( diff > 0x4000 ) {
* q# z6 N% _! L1 ?9 x2 L% e                        output /= 4;+ \' p. E( @! N- \5 R
                } else
) s0 y( w$ ?8 ?4 k6 ^7 C                if( diff > 0x3000 ) {' n! H+ K1 l$ p! t, e- y
                        output /= 3;' Q  o' N5 P8 C, t% v/ V1 Y
                } else
' F& Y% ]+ K4 d: G- z8 {- {                if( diff > 0x2000 ) {' |5 y" d) c- R+ R" |: U, z
                        output /= 2;! J* E7 q& |. W' M+ K
                }( x- Q1 ~' @: J$ \, D) k8 k3 U
                last_data = output;& v* I) C' Z# k+ O( n# L/ \7 Z- A
                }
+ z  F4 _3 t6 {* q. b1 A6 u#endif
& e7 N7 f1 @& T: F6 q                // Limit
( Q; M& T, t3 p# c, l9 R6 ~                if( output > 0x7FFF ) {6 @& q0 }& {7 E: s  t
                        output = 0x7FFF;: T! @/ k& e' s6 w/ X- O
                } else if( output < -0x8000 ) {/ F! s  {, b* X0 n0 J* G. z
                        output = -0x8000;" H  Z3 M/ p( V* }, A* @7 b: }
                }0 n6 d' s/ n( x
+ u  D- U1 x# J
                if( nBits != 8 ) {
( T9 O- h, a% f$ ~/ C* C1 P                        *(SHORT*)lpBuffer = (SHORT)output;
$ q" Q! w0 P0 s" w1 }0 K                        lpBuffer += sizeof(SHORT);/ t- W& B3 }: z+ k! c, X  V
                } else {
" o* ]/ T) O% |' n1 t! [                        *lpBuffer++ = (output>>8)^0x80;
' m4 R# ^+ x( C/ k; `6 M( |0 I* ]# z7 d8 k                }/ B4 [9 U. M2 Q# j) l& Q/ m+ k) r
; b, U& S2 y4 a$ @5 C1 L2 n
                if( nCcount < 0x0100 )
) t+ T" Q  N* T3 W- f                        pSoundBuf[nCcount++] = (SHORT)output;, Z, C5 [$ e; ^/ \6 ]

8 K8 f) R9 Q7 S4 l2 e  m//                elapsedtime += cycle_rate;, I2 t% `6 F& ?+ p  [) F2 n
                elapsed_time += cycle_rate;
) S8 Q' n0 p+ W% {% s; x        }
+ e. ?6 s1 H1 L) o9 }5 G. e% Z5 Z. E( I$ f( {3 M( n+ K9 U
#if        1
% c( A9 d+ f% _        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ D, D/ R1 @3 W1 ]/ P& y" I                elapsed_time = nes->cpu->GetTotalCycles();
2 J: @. w& r8 Y. s        }
- b- u9 P; M. J1 \        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {% Y( x$ b5 ]* W" Y- y
                elapsed_time = nes->cpu->GetTotalCycles();. G' [% E* ^/ N2 |$ i. O4 E1 P
        }
4 \  O4 R/ h  H; K6 w7 @2 M#else
3 [6 K% x' L, I* [* g        elapsed_time = nes->cpu->GetTotalCycles();/ ~& v4 E& o5 ?
#endif
# V6 L/ r; H1 v' @# C}
( [5 ?5 c! a0 w
7 M1 A+ m! l7 D# U2 |- T! l8 a6 Y// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡), w  o7 Q' ^: j$ e6 a
INT        APU::GetChannelFrequency( INT no )6 Z% k# S5 i3 l2 R& A
{
/ {4 _4 Z* T! ^2 f        if( !m_bMute[0] )
6 G2 `( i: j/ l! k                return        0;: ^5 b7 i( t8 G5 q8 M
6 }  E, n' S$ y. b. J' b9 H: _8 L
        // Internal
- V* i( J8 S. W+ y1 i* o        if( no < 5 ) {
/ F; P% I9 q; P                return        m_bMute[no+1]?internal.GetFreq( no ):0;* f! X4 ]3 }6 N3 O, ?! s6 |  E) p* |
        }+ \, n5 y: ?; V
        // VRC6- w- O- }: A& h+ t# H" f: n
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {# ^9 [. H5 \+ O& O* L+ y
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! W6 N0 ~. P9 u4 R6 K6 W" U) g6 g5 W
        }
, v( o/ e6 N: J$ c        // FDS
( f1 F* z8 U: Q0 c        if( (exsound_select & 0x04) && no == 0x300 ) {
- g( }% a& \" z: T+ A                return        m_bMute[6]?fds.GetFreq( 0 ):0;
! d" L: I* h6 l4 Z/ y# y        }
  L) _4 ]! Y7 W  a0 v4 I$ D5 L9 c        // MMC54 E- Z, \& o0 d0 U, n* k
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, W; e8 o" n1 o3 N9 d: a                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;+ d$ W# ?- h- E2 p
        }4 L) e/ o- H7 E4 m
        // N106
% I+ V# }3 h% r! U        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {  ]3 J2 O3 B+ S9 ^. @
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* I  a4 D: W& r; x6 t4 V$ _" ]        }
1 K' K# a6 k3 b: T; K' e# Q        // FME7
$ r% U  h2 B- h0 x, _" b8 V9 J        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 w2 q& H! i* }                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;9 W7 j: D# ~- \$ l6 U/ k
        }
: W0 t/ x' Z; T( Y% N        // VRC79 X/ [; r- H) H4 Y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {9 h" i  d! W! W+ v$ L- E$ y4 T
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 @$ E0 B' U3 x
        }3 O  S! T4 O) ?0 p
        return        0;/ l+ ?" H& g, P. n+ ~0 i
}
1 v6 q, k4 i9 b. W& x
/ s. b' c" G! c  E! ?1 J) }// State Save/Load( u/ P, n1 A; p! _: ?# T
void        APU::SaveState( LPBYTE p )
/ K  J7 r/ A9 ~" M{. J' s+ F& |3 ^6 Z
#ifdef        _DEBUG
' V8 }0 W2 y3 U' R' H/ K5 aLPBYTE        pold = p;
* ~# c: R2 g7 g1 b% s5 ?" ^#endif2 Z, E' _. o4 ^& }- |

1 X) |# X% f6 H* A) f        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞" K0 K3 H* h7 M7 s
        QueueFlush();
! I1 V5 b0 k0 ^! S  d% k
7 F1 D7 j6 B9 s# b1 w8 \& m, R$ J  K3 z        internal.SaveState( p );
* q, V( }, y( r/ `3 F- l- l        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, }8 P+ I0 G* Y7 W; q- w  T" f& d2 p$ i- t- v
        // VRC6
( k& ^, K3 F: n) A# D& j4 ~/ I        if( exsound_select & 0x01 ) {8 x8 ]4 V  K* V8 o0 @
                vrc6.SaveState( p );, h1 O  U7 v4 {$ `1 w) F0 ~
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# [: K4 D! |7 Z: \
        }
/ O/ N5 s$ O9 U        // VRC7 (not support)
- K% T) W! S7 o1 x( K! z' k        if( exsound_select & 0x02 ) {
& H( D% o7 I# R  m" H7 u                vrc7.SaveState( p );. i% |1 N9 ~1 r1 ~
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( i4 h$ T6 ]5 k2 U9 v* H        }% Q. @- _' v8 F* C; d
        // FDS
; O# X' u) R3 I: f9 |        if( exsound_select & 0x04 ) {# v9 ]8 K: b" S3 l/ |& w: A! w
                fds.SaveState( p );
- h# ~: y+ e3 u! O* R. Y0 Z' O8 {' Z# k                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 l. Z( F" Y( o* l+ x        }
. a9 u/ i% @7 H6 s2 h% _        // MMC53 [+ W8 C. d2 Q/ x4 L
        if( exsound_select & 0x08 ) {
: `4 k# g1 @" D4 A+ a# j                mmc5.SaveState( p );
6 V/ S) |! d( Q9 K$ Q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 ~. |1 e  g" G5 K
        }2 |2 I9 j$ m4 Z' k# x+ ~9 }
        // N106! O) s" M: |. r, v& }- ?% j7 W
        if( exsound_select & 0x10 ) {5 c7 `1 N$ U7 |
                n106.SaveState( p );
( G" y  J) K! I4 a1 n; {. c                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, {0 Q3 w/ b4 C9 }) f9 ]$ r
        }
0 I- i" @. C4 e# o  s4 A        // FME7& ^5 J% f! R% L. g# L" O& b& j  @
        if( exsound_select & 0x20 ) {
! r0 s3 _' u  G                fme7.SaveState( p );* j; Q" j9 \2 y9 R# G- f% M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 Y1 B  J, U% V0 u8 V" e& [& M        }* a$ J0 B* G( w2 d9 d2 ]$ R

# v, U8 d/ ]) {% s7 z5 I9 {#ifdef        _DEBUG
+ C6 U1 w1 n. VDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );0 F. Y1 q2 a: [
#endif0 R$ U- K$ c3 Y$ v$ N
}
0 W, i: m, V9 l3 q% T5 V/ T4 z' ~- h1 @! Y2 P, L
void        APU::LoadState( LPBYTE p ), x3 q4 v1 m0 z" `% f3 i/ C* [
{9 k" K. m) o& I/ l* ]6 f0 _% \
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
2 @1 \% [$ z0 S# i/ K# M        QueueClear();
4 {$ y, v. \- N6 ^& A+ m) {
7 @8 Z" ~) e( |7 L3 \        internal.LoadState( p );; H% S5 q# R3 _# S9 ]5 i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 m2 T& M" T& }/ G- Q  L+ Q; v" Z) l" H' a8 c+ q% A' O! T
        // VRC6
0 o! }: p% G7 f2 s$ M9 h        if( exsound_select & 0x01 ) {
( ^8 i7 A2 E: r                vrc6.LoadState( p );( _7 M. T4 y% s& E; @" R- D
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( q" z' f% t( H& `$ Z/ B' u        }; p- M. }- S( r  W2 y2 w
        // VRC7 (not support)4 V8 _/ |! c  F- I+ u, a, _
        if( exsound_select & 0x02 ) {
% D9 V2 E% k0 b; U; ?  L7 W                vrc7.LoadState( p );+ W6 @" X& z. Y# a3 J  G, _( P& u
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- q! |& j+ X8 F2 m
        }
. c" o8 }: h3 L& h& W/ O, ^        // FDS# m! d7 ~- S( O8 P
        if( exsound_select & 0x04 ) {, ~- p# S5 p% R
                fds.LoadState( p );
( f9 v; G+ r+ j* B* {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 [: Y9 o4 G6 G  J& w( P4 |  y
        }
% N, p& k) I7 x5 Y6 x* Z- @; |        // MMC5
7 s; w+ S; h7 y) W        if( exsound_select & 0x08 ) {
! n& S0 v* _2 c# d' j) |* x                mmc5.LoadState( p );: R1 A6 S+ S( P8 l% Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' H2 M4 u( M1 K/ \* M        }
! `" D3 G# _. I  u' h        // N1062 Z8 W; j1 L3 G+ S( q6 h  C
        if( exsound_select & 0x10 ) {' ?8 a1 f& r; g* a4 c. D) l
                n106.LoadState( p );
' X0 p+ X9 u: P+ j. d1 ?5 P1 |                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% F" J/ P4 }! T9 @        }" p2 x! M% O0 o5 Z! V# ~$ H+ \% s  w1 Z
        // FME7/ q; k9 J6 x' E# n" L2 u5 A
        if( exsound_select & 0x20 ) {. L; B. t: Z5 }0 K* S6 U: G
                fme7.LoadState( p );
  u2 e& ^/ C( f' X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 J) |1 T4 f% `( f
        }
9 C% G. T; }  R9 Z2 b}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
# L7 @; P. M" m可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" Q( }# m1 B) S  B/ ^8 [6 O1 i+ }' A
感激不尽~~
" ]5 S7 k2 w5 N5 r
恩 我對模擬器不是很有研究,
, c8 [7 G. Z4 n2 U/ b, m雖然要了解源碼內容,可能不是很困難,
6 W: Y. t# z1 I1 M不過還是要花時間,個人目前蠻忙碌的。
) Y( y: N* H+ D( Z9 ~! k* M8 ~$ j( b3 w- R1 c6 H
給你一個朋友的MSN,你可以跟他討論看看,6 n  ]( Z( ?, B: j% n* }4 z
他本身是程式設計師,也對FC模擬器很有興趣。5 |( e+ w' n3 R" C6 j8 f& ~3 T

. r% w! B% |, }6 |( o* u2 oMSN我就PM到你的信箱了。
# U8 C) _; q3 O5 C3 p& H, n3 R7 [' S0 ]% T4 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 发表
. [- G8 F7 r# z7 F  Y1 L呵…… 谢过团长大人~~

8 _  }- J! _6 T7 u4 |" D* C0 @& `) \; ^- U
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 8 u6 G! m) P$ j2 x7 q
团长的朋友都是神,那团长就是神的boss。
. U: i; t- j& W( D( X
哈 不敢當,我只是個平凡人,
: o- c3 K/ b. Z$ w要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
/ D8 ?$ f( c+ Y% A( Z* iZYH
" J0 N$ S: ~; xQQ:414734306
' `4 f4 C+ F' e3 [Mail:zyh-01@126.com+ Q* b! q6 u- e* ~+ @
, r6 k# `' l( k6 B% m: |
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
# s% Y3 g1 d! g0 G' z  ~再次对团长大人和悠悠哥的无私帮助表示感谢~~

4 _+ B; c) @; E& L" @不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-6-10 03:50 , Processed in 1.089844 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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