EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 A: f1 Q9 l0 \% v9 [) B3 t0 G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) ^9 C4 S: ^3 F" i! p这里有相应的模拟器源码,就当送给大侠了~~
- w8 ?. t& e, p4 Chttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
$ S" k& V* l7 U能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ q0 k  t9 w- }! S: H" \楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ A/ m" U  r2 ^1 s! L+ `! V+ X. A
这里有相应的模拟器源码,就当送给大侠 ...
! k- k! E8 P- f& z
聲音部分(Audoi Process Unit = APU):
+ P- Z  K, B7 T7 j3 l0 k# J.\NES\APU.cpp
$ [4 M- _$ z2 D3 d* y.\NES\APU.h
" z2 Z% `6 F/ G, z1 X. i7 x% j+ k$ x% h. o: m$ }
' _. b) o; w5 P: R
影像處理部份(Picture Processing Unit = PPU):
+ B2 [. L* p) H1 h.\NES\PPU.cpp) i% w0 W+ N. ~0 V* y# p
.\NES\PPU.h
, ~/ D& D, S' z; x/ L1 |) i4 |' X! L; P" Y" H3 F
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 {- k5 f& c$ o  c% Q% T7 C# e! m(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 b) A0 e# w* N
//////////////////////////////////////////////////////////////////////////) h0 T8 D: ^7 n; \6 w* R2 A
//                                                                      //) ~8 T* y. f5 T7 a
//      NES APU core                                                    //5 f) k3 m+ B7 A
//                                                           Norix      //
, [2 p; D! t9 d5 D//                                               written     2002/06/27 //& B: K5 w: x2 x  N. t7 j) C
//                                               last modify ----/--/-- //% U# z! h8 l: S0 l) V- l
//////////////////////////////////////////////////////////////////////////
) c$ [  R2 S' S0 ~0 U2 `#include "DebugOut.h"+ ]4 }' p& g) a' T) i7 {
#include "App.h"5 G# F7 F) ?9 ~3 q, ]* M( Z; X
#include "Config.h"6 \8 {- r- S. |

/ {  K2 @+ ~* o' X3 U#include "nes.h"
5 O* f/ C1 w* C; Z3 ~#include "mmu.h"
- B3 N* m1 Y7 u+ x& K/ Q#include "cpu.h"
3 v  T4 m; j& P  ~5 y#include "ppu.h". W  w$ i3 N7 `- E8 A1 T/ \
#include "rom.h"3 Y; ?" A6 V; u. I" t# P
#include "apu.h"
- F1 J- T0 ~  F( N5 C9 z( r8 p- N1 r4 W  j4 v: Q! K
// Volume adjust
" x/ g4 j: a6 o0 H3 |! i- S// Internal sounds3 y1 Z' \. {( k; o
#define        RECTANGLE_VOL        (0x0F0)9 t' Y6 T" [& w1 \, z7 K& p
#define        TRIANGLE_VOL        (0x130)
0 }& v+ V/ u# i#define        NOISE_VOL        (0x0C0)
8 ~7 S9 T6 D. Q( N: C. s#define        DPCM_VOL        (0x0F0)
% k. `' q. T, q; q/ c// Extra sounds" w& F# [0 t; {' d- i; K; e5 r, \
#define        VRC6_VOL        (0x0F0)
6 C0 H+ T( c' f7 F#define        VRC7_VOL        (0x130)
7 I! L- |5 [9 d" V& G; P) o#define        FDS_VOL                (0x0F0)# S" \/ b1 S; t
#define        MMC5_VOL        (0x0F0)
- ^# K5 \& B1 h( z#define        N106_VOL        (0x088)0 K- m& r* C) H+ r7 c  |  g
#define        FME7_VOL        (0x130)/ W1 P7 B3 H8 z) L8 q& v6 w

9 Y! k  W0 x, T6 \APU::APU( NES* parent )
) w6 w$ ~9 ]" \, n, k, \{
* d& M9 k8 \# g1 ?/ Z8 ~* [        exsound_select = 0;
5 I# y! p" r) L3 H2 R
% S! X# b4 g2 z        nes = parent;" p" L8 q2 i# ^, z8 R& ^
        internal.SetParent( parent );
" N# M# v: R. W% _, J, h- G: K$ }6 B$ k: R, x; q! P) d
        last_data = last_diff = 0;
' O* q' m" n8 {, ?8 V  I5 S+ N
$ ^1 @" w' U7 ^; H, z. E* C% Q        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );9 d: h1 I1 s) F7 y

/ F$ T9 F- x- r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );" a4 |9 o' P& H3 d  ]8 p+ i% W3 I
        ZEROMEMORY( &queue, sizeof(queue) );
/ R& g6 h' P5 N: S# E* w6 \        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 G% s+ a' Z2 L- f* f" M

7 y2 `8 V% i% o6 L' Z        for( INT i = 0; i < 16; i++ ) {' L0 P" t- i% p
                m_bMute = TRUE;
) C  H1 f6 |6 q+ a8 k        }
( L) |( o/ O+ D! {% `$ t}) _) P$ m) o5 V/ h6 G) B% I6 V

8 m: N! n* n6 x8 BAPU::~APU()
( n' ?' `: p# g. \' V3 O: I4 p( z{
% T, X2 b0 V3 q+ [}6 N# `2 ^9 }' u
5 ^- _  v# Z! [- R/ k7 [& }- p
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
1 n. b; T+ L" Y  G# U7 N% K{
) n$ d6 @/ s2 O* x        queue.data[queue.wrptr].time = writetime;
3 k! n$ E: K1 `7 U        queue.data[queue.wrptr].addr = addr;
% z' r2 n, S2 k) q& a7 R$ @/ M( B        queue.data[queue.wrptr].data = data;
4 t) n: o/ r1 J        queue.wrptr++;
" D" W/ h8 t% h$ b( a        queue.wrptr&=QUEUE_LENGTH-1;
5 }  a% w7 q9 |( e" ?        if( queue.wrptr == queue.rdptr ) {
  C6 V1 K5 ~5 b' q2 u6 q6 N4 o4 f( v                DEBUGOUT( "queue overflow.\n" );. M4 o% X, }6 Z3 ?8 O9 U$ L8 N: t
        }6 p" I4 V, i& ?5 K) {( T
}
0 L: H# u  b, E( ~3 A- O3 _" n8 Z5 {
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) d1 G, @; t+ C6 m3 w# O  P
{
: U& h2 u! Y5 c2 c. a        if( queue.wrptr == queue.rdptr ) {5 ^3 m" e  w- S4 [7 y4 M/ }5 Y" y
                return        FALSE;& v( T- C. O, s9 j5 Z
        }
) W/ G# J# r6 T- A" o6 ~        if( queue.data[queue.rdptr].time <= writetime ) {
. g4 @8 _9 n0 S$ ^. ~" L; x+ b                ret = queue.data[queue.rdptr];
+ ]: r5 S2 f6 X, C                queue.rdptr++;
8 v% h6 P$ m1 X/ {( T4 v                queue.rdptr&=QUEUE_LENGTH-1;5 T! Z  t9 g" ~  x, m
                return        TRUE;
( a4 b; f% T- d4 h        }
- {, h- m; |- N. Y$ E. _* I( j, W        return        FALSE;
7 S) ?& Y/ j$ K  G' M}' F$ m5 u9 i) A- {) a
% C& G  f0 z( D% m: v
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
. r' x4 j' v/ R' S! m{" F) S( ~1 C3 z2 C: }
        exqueue.data[exqueue.wrptr].time = writetime;
% X8 ~2 |% f/ J4 s6 K% ?, E        exqueue.data[exqueue.wrptr].addr = addr;
: R& F$ X1 O8 \$ n; k! ?/ ]- Y        exqueue.data[exqueue.wrptr].data = data;  ^' r1 C9 W# b
        exqueue.wrptr++;
% X+ [9 n9 W3 |- ^3 N! i        exqueue.wrptr&=QUEUE_LENGTH-1;# E, H& p' H5 i' f' I" {0 }
        if( exqueue.wrptr == exqueue.rdptr ) {
  f: L9 i+ G+ Y( T# \7 V  a                DEBUGOUT( "exqueue overflow.\n" );! ]! W/ B+ S7 f3 z& t, I
        }. p- R; E9 n+ x: l
}8 L+ L! Q9 q6 J# o' |' l: p( F
5 j9 B& e) I: L$ H1 \
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
; G: E0 p* ?& x) Z5 ^5 D, R& t- v{
& {$ y7 _( M; c' Z. A$ M        if( exqueue.wrptr == exqueue.rdptr ) {
# m3 x- i, s( c                return        FALSE;
: j5 B/ i& y1 S1 z- l$ o' Y        }
9 l: g2 k; _  |& I        if( exqueue.data[exqueue.rdptr].time <= writetime ) {" @( E& W& i0 L& D5 p$ K* P
                ret = exqueue.data[exqueue.rdptr];
5 y0 x9 _8 @' |* z+ g: U3 I                exqueue.rdptr++;
* T. g, |- |$ `& @) G6 }: T                exqueue.rdptr&=QUEUE_LENGTH-1;& u6 B) g' I7 I% C! c, K4 h
                return        TRUE;/ W( H: @7 T2 R1 [: S( P7 F$ E7 c
        }
$ h- u9 \, p. ~- z. H* @) i        return        FALSE;
/ ~4 ^' k; Z- f) T) {}
* `1 B9 I8 e$ z: N. W+ M: R4 k; \& \! l& q
void        APU::QueueClear()- B9 `- \$ J- h5 d+ ~1 P
{9 x( O' p/ Q4 ^0 |; l
        ZEROMEMORY( &queue, sizeof(queue) );0 q+ e% l. m. b6 E8 d9 G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 G$ H* I/ d- l+ X- t}
/ [, T6 X; n' z5 h  n1 i8 ~0 T9 Z; Y( F$ ]+ a8 m4 X
void        APU::QueueFlush()% F8 B7 r8 ?7 k6 r' f) H8 n
{
5 x# V( R, x- D8 J3 f: M        while( queue.wrptr != queue.rdptr ) {) v; q, u" ]$ x% z& Z8 Z
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
3 w" g( c6 v+ _3 d3 G                queue.rdptr++;7 j* m" i4 K! \# }( _# ^# z; m7 L4 z
                queue.rdptr&=QUEUE_LENGTH-1;& M+ G# Z. G0 N' X- v* H5 f
        }$ A! ~! y* m+ t8 D3 Q

* U5 B; M. w6 F7 L8 g        while( exqueue.wrptr != exqueue.rdptr ) {
$ r1 Q& p. [: m                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 H6 k( }! I9 d$ N: P                exqueue.rdptr++;% C$ \0 C2 t0 \# l/ ~
                exqueue.rdptr&=QUEUE_LENGTH-1;- a3 }+ P0 x3 C" w
        }; k9 u% t" Y+ |3 Z' Y. `8 \! }+ z
}
9 e+ R8 t; M! ]: q- v" {
1 e. o. ~  o( ~1 w( b! u3 l$ vvoid        APU::SoundSetup()7 {$ D% H* ~1 h; l
{- H" c9 h- D# C1 _: ?
        FLOAT        fClock = nes->nescfg->CpuClock;6 k0 t+ c( x& h) ]5 y9 Q/ Z  a
        INT        nRate = (INT)Config.sound.nRate;
( h" t9 _7 @& m7 ~! G        internal.Setup( fClock, nRate );
! Q) @5 e& u. ]  }! ?  F# u; N        vrc6.Setup( fClock, nRate );2 q" H& E/ O" A" n
        vrc7.Setup( fClock, nRate );! w2 U  B5 Z/ J. \
        mmc5.Setup( fClock, nRate );) s. G  V9 n+ X1 t
        fds.Setup ( fClock, nRate );
- ^- l4 Q: Z: I- y$ P" ^! b9 f        n106.Setup( fClock, nRate );+ N' k# N- W  t, }8 f
        fme7.Setup( fClock, nRate );, w( E1 x, e/ `
}  y$ K/ A) i. n' s

  u# \& k1 J. ~) ~0 U8 lvoid        APU::Reset()8 M( [; r: L+ x" `: X' `7 X5 |& }: X
{* q+ a4 p6 W0 O* c0 d
        ZEROMEMORY( &queue, sizeof(queue) );7 v5 `5 A# S7 y* t0 p$ L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );# k9 h6 `5 m. ?( B2 e) r. o" k+ l

  x' s3 X. N+ w8 T$ [: [! ]. q        elapsed_time = 0;- S7 D) K' h& U
6 c" ^7 r/ y2 l  D' a
        FLOAT        fClock = nes->nescfg->CpuClock;
$ H; F# P' O$ O6 S        INT        nRate = (INT)Config.sound.nRate;
6 u0 u5 c" s. h9 J2 g. n% b        internal.Reset( fClock, nRate );
$ c4 I0 w/ z; E5 j. O8 d1 X9 I3 v( C        vrc6.Reset( fClock, nRate );
% T5 c2 C3 U5 l        vrc7.Reset( fClock, nRate );8 w  N& b& A. W. Z' X% M% {
        mmc5.Reset( fClock, nRate );
* u$ {! K) L8 h: [        fds.Reset ( fClock, nRate );6 P6 T& T( J, X
        n106.Reset( fClock, nRate );: A$ [9 b  {5 O5 ~* a9 P( {
        fme7.Reset( fClock, nRate );+ z  ^$ v5 H' O, z% C. P
* D8 C3 K  ?4 }( }8 A
        SoundSetup();- b3 C# y: }3 x; `2 t; @
}! x% l4 {% m# k3 n  S
% ^  E2 l% Z5 Q) W$ G
void        APU::SelectExSound( BYTE data )' n# }* m7 D6 d8 C
{
2 K7 y* ]  Q' @, W7 |% m" ~# J% ?5 x        exsound_select = data;9 f3 m8 m7 N7 J' ^) d
}, y( E& @4 U2 {; |9 l" [3 o" s
$ @- P, q: C; t0 c9 m7 p
BYTE        APU::Read( WORD addr )
* y+ ]) g7 q$ C. e{1 e5 D+ m' G' \; K
        return        internal.SyncRead( addr );
7 G- z' i0 I9 ~+ D0 h, g; W1 {}
( G1 M4 j- n' t( N$ c+ A% q  z
+ d. A! @9 Z, \* J5 Q7 svoid        APU::Write( WORD addr, BYTE data )5 C/ l9 p  U* W9 n# v& |
{
* O: I  X8 D, O2 [1 I        // $4018偼VirtuaNES屌桳億乕僩+ E$ b$ z, T) N: S2 }
        if( addr >= 0x4000 && addr <= 0x401F ) {* x% T  S5 N4 G) [
                internal.SyncWrite( addr, data );
& ~2 {0 I5 e6 L/ h& K0 z( u                SetQueue( nes->cpu->GetTotalCycles(), addr, data );: W- N. h7 ]6 l
        }
* h6 G, z1 m, N1 |% s}
. }4 E3 L, W2 `; U1 @. Z9 d1 [& ?; f" R% [2 \7 H6 z
BYTE        APU::ExRead( WORD addr )
: U6 h1 I! R2 S# g{0 G# g' S0 x/ Y0 ~, ^6 y
BYTE        data = 0;: V1 }0 c- L" Q( g
! \- _( v9 Q( c$ s# L' z
        if( exsound_select & 0x10 ) {5 S! W0 u% K* Z% C& F! I
                if( addr == 0x4800 ) {; ^7 b+ b4 S# c8 z% Q: t
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );4 c; |- Y* y: D. }! x, J
                }
: Z# i" t: H! g        }
! J0 }# I& F) J- v( @# E        if( exsound_select & 0x04 ) {
. }! U( O1 ]! J$ I% z2 `# l( F                if( addr >= 0x4040 && addr < 0x4100 ) {
- y% S0 J! h% r5 s7 e$ W/ G                        data = fds.SyncRead( addr );
! h8 O4 U" I& j) n! E& @: t4 \                }$ [7 J' k% W. V" U1 X% Y
        }" O/ G$ e( q- r5 {. j
        if( exsound_select & 0x08 ) {
! F9 @- M4 j8 Y" i                if( addr >= 0x5000 && addr <= 0x5015 ) {9 L0 C, U/ R5 z/ I  V7 `! @% @$ T9 A
                        data = mmc5.SyncRead( addr );
% ^' I# w( ~+ k! N                }& v6 ~, E3 ?# }
        }' \" G9 i2 Y; Z" j2 \+ o5 _
: p/ T" A. s6 _& x5 Z& @. O! I  h
        return        data;
0 H; T3 x8 Z( p1 ]}
. j! Z2 |0 N/ C1 l7 p
" |3 N& j2 g/ T: svoid        APU::ExWrite( WORD addr, BYTE data )' [4 _4 `7 w4 Q
{
! \! r# r$ w0 w1 {& A3 E        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );' i7 b$ [( n3 o$ k& p
7 A3 l, |0 s* Y+ e
        if( exsound_select & 0x04 ) {2 p2 g6 _+ t" F5 y5 P
                if( addr >= 0x4040 && addr < 0x4100 ) {
; z2 V! \+ b4 e- H- s                        fds.SyncWrite( addr, data );
0 n* y) r' o) L3 l' [2 o                }
& P6 [8 J0 R* P/ y! T/ B        }
- l- o+ w5 s& ?2 X0 e; P8 u2 a9 n8 m8 H$ s
        if( exsound_select & 0x08 ) {4 l. G$ i# a, M9 A. q
                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 l% Q- N  W. b, Z. D                        mmc5.SyncWrite( addr, data );
, h5 G* I7 H0 e. @; d( Q                }
) O2 k, Z: L1 T6 F, w7 D5 m        }1 L  A0 Y% M( T  n
}+ S& g$ H- I" V7 k
9 N2 [1 L" t+ b+ D* T1 N
void        APU::Sync()
8 q4 J9 ]0 F! z7 m{
. ]; Y* N# q$ S/ U}
. d" X' g. Z0 P: ~0 J  n& i5 z4 Q( l  i8 h* A
void        APU::SyncDPCM( INT cycles )
/ c; E  e# @/ ^( E' q{0 l3 V. _% v3 `9 F
        internal.Sync( cycles );
' Z3 Q9 l9 N, D7 i, l& i2 a8 i
+ X, }7 m) k/ G        if( exsound_select & 0x04 ) {
. O5 |9 Z+ \* r- t/ O: [% Z0 q3 A                fds.Sync( cycles );
; j) Y9 p1 t/ V: S& u        }
$ ~9 A- g. \2 E( r2 X9 {3 v        if( exsound_select & 0x08 ) {
" D" ]0 U; N0 D' G                mmc5.Sync( cycles );
5 A2 T9 i$ j1 k! }& U/ B1 O1 |0 ?2 J) W9 w        }- [$ J  {7 S# g) x; L
}) R) |! _% S" u! A5 F$ H- G
' ^/ Z6 \2 W+ H$ k
void        APU::WriteProcess( WORD addr, BYTE data )6 _: k0 G$ k8 H! y1 T; i0 W+ _3 @
{
! l5 ^+ h4 c$ Q2 i. a, q        // $4018偼VirtuaNES屌桳億乕僩9 n2 [7 o$ P; n5 {- U1 ~
        if( addr >= 0x4000 && addr <= 0x401F ) {& s$ u" `3 ~) Z2 a+ M, g; ~4 x
                internal.Write( addr, data );! J, r: \# E( X, p5 J
        }
  j) S( |' z! m- }7 I- k1 B: p6 M}
3 G9 P8 |+ I  j/ v
5 F1 u' x! w+ N- kvoid        APU::WriteExProcess( WORD addr, BYTE data )  r. i! T& i2 H" C' {/ T
{9 H! A6 x/ n. g) R+ B
        if( exsound_select & 0x01 ) {3 X. |* y  O& N5 N; b6 {# [
                vrc6.Write( addr, data );
" s$ s. K% u6 Y" R        }
% o0 ?* P$ u/ O; N+ y- F0 ~& ]        if( exsound_select & 0x02 ) {
1 m" l" q  @8 ]2 y8 t3 _# ]& X                vrc7.Write( addr, data );' ?. w/ {0 l8 P
        }, N& }( I9 J" [4 m" Q3 O
        if( exsound_select & 0x04 ) {
5 z( ]" {2 D7 B. l" Q                fds.Write( addr, data );
$ b7 I! a1 u/ p+ G        }
' w% [( h$ P" U8 M# Z3 M7 y* _        if( exsound_select & 0x08 ) {
) O; W$ y6 }: r4 ]                mmc5.Write( addr, data );
  S' p+ i9 R( ~& m& B9 X% L        }
; q2 p  ~3 r8 J        if( exsound_select & 0x10 ) {
) l! u/ k% d! f$ U                if( addr == 0x0000 ) {
0 T4 t6 L0 @" U( c6 D6 t                        BYTE        dummy = n106.Read( addr );
5 i$ z( o( Z6 W1 Z8 D. C                } else {
: r- l5 A' w7 i# ]; H# t                        n106.Write( addr, data );
1 y* P5 E* D9 M' ^: T5 s! z                }3 D/ r* I9 X  ]4 q
        }. k' V( u% V9 U  R8 Q( u' A/ v- f
        if( exsound_select & 0x20 ) {
$ P. @, m' d$ n% O                fme7.Write( addr, data );- h5 W$ Z/ I4 l& f# D0 M
        }9 i+ w% k/ k$ j$ w/ X" R& z
}
8 B1 H) `0 ]1 e" f1 N7 J
, P8 f- h/ W0 i" j0 b% |' q5 Cvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )5 n, K; [1 k" s7 s
{2 X- h6 I  F" M* U
INT        nBits = Config.sound.nBits;2 @$ V& J  ~- d) P( c4 V' d3 }
DWORD        dwLength = dwSize / (nBits/8);* q" t- q) X( X4 h6 b
INT        output;0 M- W( ?2 b& |( a5 h; H7 x
QUEUEDATA q;/ U3 v5 D( M% `! p
DWORD        writetime;) G/ M7 c1 e' t# U7 [. n9 X
1 E! n: D! ^- b$ F* ]4 F9 u$ ]
LPSHORT        pSoundBuf = m_SoundBuffer;
; H( D% b4 t- \: x. @+ jINT        nCcount = 0;6 ?3 i% i; n1 q1 t2 l5 {

6 H& G$ R" J9 b7 JINT        nFilterType = Config.sound.nFilterType;
/ J" n& G) F" n
- l! K+ x* v; d  b/ d# [' j        if( !Config.sound.bEnable ) {
- r( g: r3 `3 [( O( i1 L) K                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! T. y: {3 U( A' U
                return;
) A. r* |, [& T& d$ _, v1 D3 M        }
- z2 f* U  B( B( C/ z/ h
8 h9 p  |: C1 y# u0 J& q# k+ i        // Volume setup( z9 @+ W: g1 h& E. M2 l3 H
        //  0:Master
! B' n4 V5 R" }9 z  a        //  1:Rectangle 1& q9 P! y3 M* V3 C, Z. r* Q- Q6 s
        //  2:Rectangle 2
. k( o: \4 G& a1 i: h        //  3:Triangle
1 ~+ d! a3 m7 @0 v6 Y& Z        //  4:Noise
# i* ]9 D+ q( I# I        //  5:DPCM
, c/ R* C( Q" d, P        //  6:VRC6
6 \, r- p* N) e6 J        //  7:VRC7
% Q% d( V& h/ I+ C9 H' k        //  8:FDS
7 b. V% m' G8 t        //  9:MMC5$ v3 Q5 M3 `6 A! w
        // 10:N106
5 d/ o3 J* O3 G  m3 t( I# z* D        // 11:FME7
0 n) A, x" y. N5 L+ U3 {        INT        vol[24];1 L+ N# S7 C: k
        BOOL*        bMute = m_bMute;1 ^4 P; b( B7 V) Z( M
        SHORT*        nVolume = Config.sound.nVolume;
9 Q% d- |/ v2 d: h. [
2 R+ @6 W. Q/ F' S2 p& n4 F4 j9 V        INT        nMasterVolume = bMute[0]?nVolume[0]:0;5 \, A* L+ T2 p% |7 C7 v4 m3 g
  J5 r1 s+ h- e; Z
        // Internal3 q' W+ u) |0 K1 U# `9 `# j, X
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 x/ ?, W( I' l( j0 X6 v        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' S. K4 w+ b$ s% O        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
* u. q, @! K" {4 l2 t        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
& ?# }$ L6 h6 Z: ~: ~( [        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 H+ C6 f/ Q+ c# I
9 A  a' G3 l$ _, `0 ?& V8 v% I; n
        // VRC6
8 O1 k9 Q* \( k6 q+ V, A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 S" M3 E+ F, i: C2 Q' O! `# n
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 V5 U4 {1 e4 U: D
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 {/ {& o7 n+ C! s# h

9 T+ m) I9 ^7 A5 F6 ~+ q. @        // VRC7! K; ~5 v% ^5 V, w/ b4 w
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
8 {5 @; ~- T3 \4 j6 c+ ^) F8 Q& F3 w( R& D9 H# ]8 u
        // FDS$ E6 `0 I& S3 h7 h! u0 t8 Y0 }
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
2 d. c# q; a# ~6 Z5 h) _: A8 ]" ]  {$ C
        // MMC5
) ?; [5 ?4 S/ j! v        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% o4 o3 n* b& q6 H
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! f% R+ [; N, G) G        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& ?& \0 i+ o4 D" i, z/ |

. R! l3 q1 _! e) F# E        // N106; z# L, z8 I3 Z0 p$ _
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 ^6 L/ f% s  ^# e
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 T% K1 X  f8 F4 T! W# b        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, K. h- n) o' J0 H$ o, ?3 G# r! |
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 E( G5 F% B) I& f3 S5 r% I        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 i$ h4 Z* l- X5 g( }% L
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  r7 Y+ p: S' w" A% l9 c4 A        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ z: m  n8 W- K4 u0 K* G/ z
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 r8 f# U# e! ^( `) ?, q" Y
; x5 V) y* M6 }9 ?3 Q+ b( P- E
        // FME7
; ^2 X8 L- \' A4 F  s' E        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" s0 \+ T2 [# g/ P
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 u/ R: K. N" Q& N$ M/ ^5 e        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( n" z  |' h* O$ R5 m6 ]) ?) M
( H8 Z7 C+ U5 u* M. ^$ }- q  `//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;* l9 I  }# e" o5 s& ?" H& G
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: s' w: U, ]# R" e' x" c) A/ L* n

) |* `( `" A5 m        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟' {8 W+ w5 v5 S: }4 {* j
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {  g) y9 d4 l( B) a0 V+ N; o
                QueueFlush();
4 I  o  q  {. W1 e7 j* d. W6 O- G        }
4 J- h5 U/ t$ v) j% _" c/ A, t
/ G! F9 D1 K' K, K        while( dwLength-- ) {
  s2 C6 \( {8 P                writetime = (DWORD)elapsed_time;
) N$ A, a$ H5 |% n& x3 O& O
  ?; g4 S6 w+ U, @2 j& W# b                while( GetQueue( writetime, q ) ) {, G8 f8 T  q, K- d% [' D  o
                        WriteProcess( q.addr, q.data );
: S/ T  h; ^4 H                }
9 R; u, d* c4 ~' A; n# H, c$ u
" T: H6 ?5 s; t6 ?$ \                while( GetExQueue( writetime, q ) ) {; }& l7 c" M! P2 W' c! O
                        WriteExProcess( q.addr, q.data );
6 s0 z% M# x3 q/ v4 t. N                }
# I* n- q  f; z# L
& g' _; N" ?7 s0 V                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME70 v( z/ u. o$ ]
                output = 0;
: L5 x2 J: @1 ]8 Z8 v& l& e                output += internal.Process( 0 )*vol[0];
" \( ], K$ F7 S6 y2 g6 Z                output += internal.Process( 1 )*vol[1];
2 z) a8 C' ]# |                output += internal.Process( 2 )*vol[2];4 [) o! Z- h6 t( J: p& q# k5 `6 u  Q
                output += internal.Process( 3 )*vol[3];) w; O% ~+ e" c$ v
                output += internal.Process( 4 )*vol[4];
7 w1 C4 E" x# @5 @( f; Q, d( u4 e0 R! b/ ?, y2 q
                if( exsound_select & 0x01 ) {2 ~1 S3 W& `$ g$ v5 v9 r# q1 {
                        output += vrc6.Process( 0 )*vol[5];
7 P4 `0 g6 N& R2 Y+ r3 t) H1 n                        output += vrc6.Process( 1 )*vol[6];
' ~* j+ s9 V! T- P                        output += vrc6.Process( 2 )*vol[7];8 C. ~' p4 p/ a/ U- I: B
                }
) G9 R* i. m9 M% ?                if( exsound_select & 0x02 ) {( Y: z( d2 k9 G4 `
                        output += vrc7.Process( 0 )*vol[8];
& U* w3 O2 v% ]6 ^/ _$ k                }
) y( {9 ?$ I. N- i& R4 |! |                if( exsound_select & 0x04 ) {6 q$ U1 a8 {) y! w
                        output += fds.Process( 0 )*vol[9];& m1 f+ z. ~( e. [
                }
' y  B7 v9 ?- U                if( exsound_select & 0x08 ) {2 Z8 Y' K/ n- K7 Z, F, b
                        output += mmc5.Process( 0 )*vol[10];5 f3 ~  t5 e, E$ w' ]
                        output += mmc5.Process( 1 )*vol[11];
& b) \: P! o4 L; G  ?* L+ I( F  U                        output += mmc5.Process( 2 )*vol[12];% }3 C* v6 c& X
                }
3 O, n( F. b9 K& v* B5 A0 B5 x                if( exsound_select & 0x10 ) {
6 Q  q- ]* k4 Z6 _2 f  m3 m7 ]                        output += n106.Process( 0 )*vol[13];8 ]: B4 e  `9 m
                        output += n106.Process( 1 )*vol[14];
4 f6 ^8 s" R) Y0 W6 {* Z                        output += n106.Process( 2 )*vol[15];
9 l7 c, Y4 U) N: C" `8 w$ R                        output += n106.Process( 3 )*vol[16];* @: w4 \5 K( t6 ~% d
                        output += n106.Process( 4 )*vol[17];
1 V4 ~6 T7 r! t% Q& @- y3 C                        output += n106.Process( 5 )*vol[18];
5 J! q/ n* x2 k2 B+ ]& i                        output += n106.Process( 6 )*vol[19];) A7 i5 j' ?  O  C. ~
                        output += n106.Process( 7 )*vol[20];
4 ]* G: L! Y* `4 W8 ]) F) o% @                }5 r( l- X. U# O) H
                if( exsound_select & 0x20 ) {
  F" p* E7 [3 r$ w) N                        fme7.Process( 3 );        // Envelope & Noise
  m. v0 s/ S  T8 d& W& s* `                        output += fme7.Process( 0 )*vol[21];
; _! |' ^) U3 ~+ t                        output += fme7.Process( 1 )*vol[22];  J1 X" X% f: y+ s% R$ O. E
                        output += fme7.Process( 2 )*vol[23];
8 Z8 X( _1 Q6 L4 c5 Z1 Y. T                }
3 K: Z+ p/ |6 O  E- ^5 M4 a2 ~% \) D: j+ e
                output >>= 8;; E  E' L. ^1 [! B

1 P5 `  o; g  |, l8 f4 D2 ^2 [7 {                if( nFilterType == 1 ) {4 i. a: p0 x- q9 a5 I% }" h- n
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 u  o# _$ \5 a( n5 k* w! n/ Z                        output = (lowpass_filter[0]+output)/2;
. E, R8 \  N8 F$ @7 X                        lowpass_filter[0] = output;! m- q- A, w( W) E- T
                } else if( nFilterType == 2 ) {
$ M' W' \5 U  F                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ ^" ^9 g+ O* Y5 }                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
' @8 Q+ K9 [& m& Z5 w: q                        lowpass_filter[1] = lowpass_filter[0];
& l, i/ n; z. ~6 p+ H+ L; R! }                        lowpass_filter[0] = output;! ?0 a( `6 C! d9 k' s  p) j
                } else if( nFilterType == 3 ) {
" K' E! f& Z' ~" B' p* X                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
# w7 I! `* O1 J4 K                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! g) I; ]# K( I1 J! N
                        lowpass_filter[2] = lowpass_filter[1];! R( w( S! H& e: c$ h# g- K' ~
                        lowpass_filter[1] = lowpass_filter[0];. o) Z! O4 W" |
                        lowpass_filter[0] = output;4 m- f0 H" b: v# I5 V) U4 H  F( R
                } else if( nFilterType == 4 ) {) ?/ K) `% P8 V: W+ A. R
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  @4 u- l7 D; U9 }6 t& u                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
2 B2 H% o. x9 U" @8 N+ f                        lowpass_filter[1] = lowpass_filter[0];
3 y1 t( Q) @  |- Y  J0 n) h                        lowpass_filter[0] = output;
8 x7 K  W9 B8 Y9 T/ {6 \$ Z                }
% w! d" j+ Y' k+ S: Q) {1 C" R4 [7 N2 z( |9 M3 z& D; _2 P
#if        0
; @# b( I% q/ m                // DC惉暘偺僇僢僩
1 Z' K3 N( C  z  s                {* \6 ~3 f0 w4 H# ~# `5 C. n
                static double ave = 0.0, max=0.0, min=0.0;' n# P5 o2 \' v: ~% ~) P8 L
                double delta;! n6 O' b8 @1 K4 P
                delta = (max-min)/32768.0;
* v% x1 ~" |( c" U3 F2 ]                max -= delta;4 E* p, ^- n) U; O* E0 ~
                min += delta;8 i/ n3 W7 H) t" m& _! f
                if( output > max ) max = output;6 W9 H( N; g, z
                if( output < min ) min = output;4 [- S( U( t. v+ s
                ave -= ave/1024.0;
' h: P  h6 ^3 F                ave += (max+min)/2048.0;* S& G7 ?5 E8 a6 x3 m5 m! I1 _4 w
                output -= (INT)ave;
9 v, ~; c: O" o                }
- S3 P9 c- U) r, X6 ^8 Q#endif8 v0 _2 ]$ N+ A' R
#if        11 T$ r. Y, h( k7 f; P- p0 }
                // DC惉暘偺僇僢僩(HPF TEST)
0 T5 M4 I% ], Z3 M1 j! I                {5 K2 T( U  ^6 x9 u) o* M; V
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" O/ F6 E* s; M- |2 X1 c                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( j7 Z0 J4 E4 y                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ y% O" w1 {4 p* ~& B                static        double        tmp = 0.0;
" x1 n6 H# {1 K6 @# {: m/ u  W                double        in, out;
9 M" \0 p  k) Q% \% J, x5 N! [3 ~% z5 z
                in = (double)output;$ Q, V0 b3 @/ t# D  j0 v2 n  ~
                out = (in - tmp);
/ G$ b1 O$ A- U& X! y                tmp = tmp + cutoff * out;
& l8 O. C- @0 X0 |' g. o) K
) i6 s4 P* W5 i, {0 n  l                output = (INT)out;
/ Z% k4 d: ]' p                }
; K; D" b/ Q% v, ~#endif
% }, y. l! c' N5 i  D#if        0
6 ^; r# g- M: u4 C                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% x' f9 A. R/ W( Z5 U
                {  N" H3 ?) y& J$ ]# Y5 L
                INT        diff = abs(output-last_data);
( p% c* u$ C) O$ v/ D7 w                if( diff > 0x4000 ) {
- ]8 P0 i' i3 ^" T/ `                        output /= 4;( \% W. ~$ _! y8 W, M6 ~# q% H
                } else " a/ P/ J2 `1 w% M2 J  \
                if( diff > 0x3000 ) {/ _* A, D+ E$ Y, H
                        output /= 3;
( _" K* J" Q* G0 J7 z: x                } else
8 s  u5 H  V. P' Z( }6 d  c8 B                if( diff > 0x2000 ) {5 w9 o3 b; l0 U* X
                        output /= 2;
# L) s7 N4 v9 d6 s5 |; P                }& @1 J' d# N* }6 d" }  }) Q
                last_data = output;) B- R1 v, F) |* g* r6 ^. d
                }7 S3 z( v  F9 z- ~2 M( L
#endif
: g& E- I3 {3 p6 z/ p& G) r; F                // Limit3 f4 x" {0 c" p
                if( output > 0x7FFF ) {! }1 ]6 T0 k- m; P. B1 B( b1 l5 U
                        output = 0x7FFF;
9 p& ~$ s& K& q+ x7 q. V9 b6 j                } else if( output < -0x8000 ) {( w6 W  R: |  l) X" X
                        output = -0x8000;
! c5 Z2 y0 q3 s" L  f& S" k                }( q( M8 C6 S0 D. G# w7 w

/ K/ _- U, x! I3 Y+ Q                if( nBits != 8 ) {2 [0 q; v6 D/ I6 ~7 e7 X
                        *(SHORT*)lpBuffer = (SHORT)output;
. [, s1 T! ]% {" y# R7 p                        lpBuffer += sizeof(SHORT);6 ~: H2 w) W/ S
                } else {/ ^3 S9 X. x9 g
                        *lpBuffer++ = (output>>8)^0x80;
/ S& E; R- Z" N+ ^! ~' g                }7 S" C' r( j" m: s7 c' k

' q) N5 @% G9 ^( Z5 P                if( nCcount < 0x0100 )2 v* q" J; h; W# Z0 R( }2 q. C
                        pSoundBuf[nCcount++] = (SHORT)output;" h+ R+ l8 A, W$ r) }/ E* q/ E
3 I6 ~. I/ t7 W+ P
//                elapsedtime += cycle_rate;, {; c9 v" W6 W" e
                elapsed_time += cycle_rate;
& q' s/ C/ Y* r: k5 w1 H2 x        }& D* }& ~, B7 f3 n. ^) s3 O
( E5 f, q) p% M* B) A3 l& o
#if        1% B; I3 C( q! h# F3 D
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {0 P! X+ d' z, L
                elapsed_time = nes->cpu->GetTotalCycles();
# i2 M' s# e3 z8 x        }$ ~# c; B' i3 t0 ~8 q" o! ~$ n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
/ S) o  z+ N8 `! D! n) |+ |5 Q( w                elapsed_time = nes->cpu->GetTotalCycles();# K& u3 h* w( \0 H
        }6 r3 g4 P+ l& T% Q$ q
#else3 v/ `/ m) @' e2 T8 e1 a
        elapsed_time = nes->cpu->GetTotalCycles();6 {* y) W$ }- S; x7 J
#endif
3 k  Q* R) c" K+ E6 ]3 @6 ^}: i9 Z! J* v; V+ G
1 [/ P0 B7 R: B- Z
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡): V" U3 y- f, I2 \2 S7 e& F# K' j
INT        APU::GetChannelFrequency( INT no )
! J2 g; |' ^' x; F& @{3 `0 z: j( }2 ]$ h1 h' b
        if( !m_bMute[0] )
( Y) J1 G: E5 {  S8 E                return        0;9 _7 M0 u/ L4 E- @9 C
  Z/ P. f4 D# s! f
        // Internal- ^" C9 _8 d9 ~, Y* C' L0 |; \( n
        if( no < 5 ) {4 M) h1 A* O* Y) L! H
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
8 y' M* b( j# |4 `$ r* T        }
9 a6 M$ [1 J0 j+ ~5 j7 f% X        // VRC6
# L5 o) L7 C7 x        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {. R- p2 n9 D- f/ H& z
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
* n8 S. b2 i: n& x4 ^6 P8 d        }0 w7 C2 H3 o1 h3 U& l
        // FDS8 F* _! D! b9 B8 e& a' l6 w
        if( (exsound_select & 0x04) && no == 0x300 ) {
4 p) {9 x  V5 u& m                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 Q# e0 X9 a1 ~0 A4 B
        }
" t/ L  `" {. C3 j        // MMC5
* `' I" U/ @' W& C) n# t        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {# p/ Z4 O& Z# I  O
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
. x$ b+ q+ T* v& w6 Y; ?% F/ b        }/ @+ \3 k4 X, \" g+ v- C- {
        // N106
5 i/ ]) g# U: t) D2 B! o" X: z        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {# y) l( u# H0 S; g( _' F' i
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
8 r2 z- E- b# [& w7 {  V        }
! v2 [$ E0 S8 d% P; o5 W        // FME7
) g  |' J# {. J1 A        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {! Q+ S! m+ O5 B2 T& g8 X
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 U) O5 Q" x: `& T7 h7 y        }& W/ x  S4 Q, e
        // VRC7
" F5 g2 W+ q/ ~        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
8 ?) A- ?9 z5 R# t% i) O7 D/ C1 I' L$ `# D                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& I( Q( G( m5 i/ P" A        }: J3 b$ u7 m) w
        return        0;% c7 M, c  [, q: @. j
}
& D" t+ W8 }- W6 e2 V3 B* i% H, ]- L
// State Save/Load3 W  a) `# s& F
void        APU::SaveState( LPBYTE p )& b' }) O5 j, o8 t. I5 k
{
0 I9 C7 _8 N) v; x( H4 z: q#ifdef        _DEBUG
+ @( D* _& P0 z# M6 J$ QLPBYTE        pold = p;* k4 ?$ A4 L0 o
#endif1 m& }1 E! S' y  e+ Z" C2 W

5 H6 o4 s/ q% U2 p1 [        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! L7 D; [" q9 V$ [! `0 k8 [        QueueFlush();& ?: R  D0 J- L; ?2 x( @. n

# e5 p- L; Z  I, w" W, h8 s2 X        internal.SaveState( p );
, p" F1 g; v) I. F2 g        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  c/ n8 z4 Q. a2 U4 n* Z% i, ~* C5 }+ ^) ]6 j/ B9 w
        // VRC6
% m, v/ h5 z$ g) \$ N0 k3 w        if( exsound_select & 0x01 ) {
  Q# G5 H1 v, i0 Z! i                vrc6.SaveState( p );
. j' m2 M% q" g: b% L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ e/ q# b5 x% Y        }& C/ e1 E3 M+ O. i5 y' K' ?0 E  ~5 |
        // VRC7 (not support)
( K4 v) z) ?/ Q  F3 ~        if( exsound_select & 0x02 ) {, O9 E" H4 `) D- \4 M) E0 G: G
                vrc7.SaveState( p );- t' M' T# w% m- Z- P' m! x6 O1 j1 z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- J: J2 ~& G2 ]- g. A
        }8 U/ e% {5 S. @# P: ?7 r! L/ l
        // FDS: Z) p+ F7 p) i8 [- P- I1 h- L0 @
        if( exsound_select & 0x04 ) {
# S7 }: G8 ~; a                fds.SaveState( p );9 j2 d: w% S' }- E. T
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' M. v% s! O6 ^
        }: I$ S  R' Z3 ]2 m8 w
        // MMC5# X( A  Q& z8 n
        if( exsound_select & 0x08 ) {  l6 U/ G! y  t
                mmc5.SaveState( p );$ h# L, r1 C& R5 t4 f# K/ M/ z9 y' w
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; q  T. V) k1 [( @: ^& e        }
1 ~$ j9 p. L2 P        // N106
! c" R* S# W# Q3 e( v, W. e/ ?9 l0 C        if( exsound_select & 0x10 ) {% k9 s% j/ a2 Z/ R4 e! K
                n106.SaveState( p );  W. }5 ]+ Z/ C( t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding- v/ r% M3 V' _' H
        }
. d$ b4 f# Q! N* v! D; f7 _# O        // FME7& A+ ~1 r9 @6 i% Y3 S0 \
        if( exsound_select & 0x20 ) {* y% W, L9 v3 n3 T( x- ~. R" w
                fme7.SaveState( p );7 n* \$ Y% P5 X; p
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 `4 i/ P0 B8 D: B5 G; @        }
( E4 G+ n/ x8 L* G* ?- W/ P, K+ q' C- T, |
#ifdef        _DEBUG( {0 V; H3 r2 Q+ m
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 Z0 A' m: ?& P& k6 W9 x#endif) i4 O7 ~, G' y8 e
}
, F6 e, M) d3 T) C  Y4 Z0 X8 s8 Z4 E8 X, `% g, W
void        APU::LoadState( LPBYTE p )
- v1 }( |/ g: P/ \{
( {1 a: y2 [: ]8 _9 M: A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! O- v1 |8 `% y8 ?
        QueueClear();. @7 ^- v6 `9 v) X+ F

7 r$ E' Z/ M. R& U# f& L3 t        internal.LoadState( p );% F. b! z/ K2 I6 n7 ^
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 Z7 q' ?" t( @/ M/ z* O" z( a
) b1 D" q: L1 D. v        // VRC6
8 a$ s" A8 E- n2 q        if( exsound_select & 0x01 ) {& |+ o; K) o. `" M" Y9 V3 D6 b% q
                vrc6.LoadState( p );
8 y9 V# A  |! Q7 E, Z) u; w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 m- e0 ?3 G" ?
        }
7 S( N9 Y8 S" |$ g* R! I% c        // VRC7 (not support)+ V, G2 a8 Q6 t: l1 @$ M
        if( exsound_select & 0x02 ) {
# O2 \2 ^0 h9 e* ]# x4 O! Q                vrc7.LoadState( p );
9 L* E! ~; \/ Z- m4 S' A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 w1 j9 Z) @; s$ q$ f        }
  X- B: L7 K. o6 m* D8 S) L        // FDS
+ r; W/ O0 U" D- O0 x: f9 Z! ^        if( exsound_select & 0x04 ) {
4 P9 M) r+ X+ ]% f                fds.LoadState( p );6 e5 |- N( e. A- K
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% n) C6 G2 @8 p) F* K- D* \
        }
9 R0 a4 W2 M! d( j/ @2 O* I5 w        // MMC5: L7 e" Z( v  f) I8 m0 n" E' X
        if( exsound_select & 0x08 ) {
- s$ v% L: M+ T  |& _6 Z- e# ^                mmc5.LoadState( p );
4 V, `9 t- Q4 H; M  Z4 n1 M% {' i                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 F+ Z, N: S; D9 ^& c
        }
4 r  M7 o7 n" A3 |        // N106, @4 T. @0 b! }  K2 x( F
        if( exsound_select & 0x10 ) {
' I) X3 m% K) d: v5 \                n106.LoadState( p );
6 L$ Z2 p1 Y* J! P* a) u* {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 ^8 o, Y. y$ ?) w! b+ C: }! U# D
        }4 h2 @4 n' S" F  s( o
        // FME7: ^( s; P3 j7 R* z# Q
        if( exsound_select & 0x20 ) {3 ~% Y( ]  b0 \5 ~) h; U4 U, R& P
                fme7.LoadState( p );
" D$ s5 \* I* I6 s                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 t8 q8 z0 w" U- r, }6 l        }
% h! Y% h, C8 |" g% q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
- R8 o3 j! s! d可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
4 B( Q  A/ i0 {. M感激不尽~~

4 V7 D5 f. q. a& d- q/ l- j恩 我對模擬器不是很有研究,
$ }- G. p4 l& w7 @0 S2 I/ V0 m! @雖然要了解源碼內容,可能不是很困難,
3 |4 n, k- U+ j2 }: C6 r不過還是要花時間,個人目前蠻忙碌的。
- h$ P# S3 q* l3 f+ ?
5 _5 J+ ~+ a! I" f: ?給你一個朋友的MSN,你可以跟他討論看看,9 k! D, M* q) o2 o1 a; C
他本身是程式設計師,也對FC模擬器很有興趣。
( O0 Y/ o0 |$ l5 c" Y# L+ i% ^# A4 h( s1 |9 W/ @
MSN我就PM到你的信箱了。
+ z" \7 P, v1 ?
3 P" u; F/ z8 I7 E! p: q' L" I希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
/ U0 p0 W2 S" ]- i呵…… 谢过团长大人~~

/ f; U2 |( ?2 ^2 Q
; O* A3 M/ N  C& m0 V: p* F哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
8 }. _) ~1 F& i6 i5 u; M0 p- P& c团长的朋友都是神,那团长就是神的boss。

8 H# V9 |9 H6 L) o, |( N哈 不敢當,我只是個平凡人,, y4 G9 W4 V) Q, s5 _1 Z
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 a+ L; y! ]* z1 vZYH
  O* r7 f8 E% I( e5 dQQ:414734306
+ s  k- V( W3 g: ~6 jMail:zyh-01@126.com3 K* R9 u- K3 m$ z, C" F
+ `4 P3 B* S! X3 t( r
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
# ^* n8 t) f8 n, L; f/ L% E再次对团长大人和悠悠哥的无私帮助表示感谢~~
% `4 F* Y/ G2 n
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-7 17:49 , Processed in 1.090821 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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