EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
: F& L0 a+ Z- P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. |/ t( O1 S7 R) Y$ F$ d1 s3 j$ `
这里有相应的模拟器源码,就当送给大侠了~~- j8 P. d$ o( `3 Y* O
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- b5 S$ R$ p$ B, j能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 f* i/ p9 m4 ~楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
- d6 t4 n+ g; h6 n1 i( F- f7 ?0 a0 D这里有相应的模拟器源码,就当送给大侠 ...
% f/ I6 t; ?4 G% y4 i2 e& d
聲音部分(Audoi Process Unit = APU):
. U. ?% P# |3 h7 W, F0 T.\NES\APU.cpp
, f, t% @* B. E! n) i8 Z.\NES\APU.h! V& J* X+ q6 X) `* F

6 c( X, Z& u+ s9 f+ {8 f, k) }% c6 p; v/ `3 f- e, v$ t9 ^
影像處理部份(Picture Processing Unit = PPU):
8 n/ a+ [& S3 p5 a; n0 M  k.\NES\PPU.cpp
7 m7 |0 p; m. W) w; I+ j.\NES\PPU.h
3 r) `4 l% f$ W7 z
6 ]" e5 B- x8 N0 |如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:+ A6 `# K* k2 z5 A- J
(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 r" ~8 A% h0 V* ]; n' \
//////////////////////////////////////////////////////////////////////////
3 T0 [, @0 E3 I- x* y. ^. t1 a//                                                                      //0 j/ }% K  d, ^5 B: n. J
//      NES APU core                                                    //0 Z; I3 J$ p% U6 e7 ^5 ~
//                                                           Norix      //
$ \" e1 ?+ V% ~$ o6 U' h, ~2 ?//                                               written     2002/06/27 //
7 ?7 b: r# N, E. H, N//                                               last modify ----/--/-- //
' ~0 F) [' R$ t/ U4 P//////////////////////////////////////////////////////////////////////////" s9 m5 a7 V2 A4 u% s& `4 o
#include "DebugOut.h". z; _) W% D+ m( ^$ i2 F9 u2 z
#include "App.h"( T9 |" q& i3 V  y5 C- L& e0 i0 p6 ]$ z
#include "Config.h"" M1 S+ ]) L! }  h

7 ?- D0 Z3 V4 @4 I" A% t1 l#include "nes.h"
+ Q: f' m! ^2 F! C0 J1 S* K+ l# h: `#include "mmu.h"6 A1 u$ V3 Z& W" X+ n$ C! M
#include "cpu.h"4 C$ t. [) P) f
#include "ppu.h"
" _  o& p' e) Z- r1 z% B) U- T, z#include "rom.h"3 l4 V& Z  a. T$ h) U, P2 l4 c# J7 b: F! ~
#include "apu.h"
' F8 |1 S% j7 v. a% V0 k$ p; x5 |/ J* a' v% m$ B  ?7 a) T
// Volume adjust
* \/ z6 Q6 I3 _& R" t// Internal sounds9 E1 Y! J0 b; a% E2 r, i# J
#define        RECTANGLE_VOL        (0x0F0)* U9 l3 C9 F! Y
#define        TRIANGLE_VOL        (0x130)) f# ]$ P, p; Z
#define        NOISE_VOL        (0x0C0)9 c. t, w' H5 ^7 |0 M7 i
#define        DPCM_VOL        (0x0F0). E+ X/ s' ]  n4 ^7 v
// Extra sounds
" T% h9 o5 ^$ ?( I/ r, v$ |! @, C. M#define        VRC6_VOL        (0x0F0)- G$ H1 M. c8 h$ |9 o
#define        VRC7_VOL        (0x130)
5 a; m& @4 F6 v, P' M/ ?1 |( m* ^#define        FDS_VOL                (0x0F0)$ k- M* y- P  _9 m
#define        MMC5_VOL        (0x0F0)
; U2 I6 s  D# i- t#define        N106_VOL        (0x088)4 i6 F( E7 k8 w2 J& V
#define        FME7_VOL        (0x130). Y* L% }2 T  A  E* \* P  l- e
( h" Q, T( d, f6 b/ u. d6 A; P
APU::APU( NES* parent )
! d9 h0 t3 M& a! I$ O5 S% w{
3 |  O9 `8 g3 e3 [$ F" l        exsound_select = 0;
+ s2 w; P3 p* P  i9 s7 l
% u4 y. s& k# @        nes = parent;7 C7 u8 f8 |  K0 A, y9 t& G6 c; S
        internal.SetParent( parent );
, O) Y$ M- o7 G
1 c; Z1 J+ G$ U2 i2 ]        last_data = last_diff = 0;
( l2 {  d* n6 g6 f+ y
" Z+ W1 s- p  ?/ u; T        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );. u  E, X( h9 W( R. C

. P* P" t8 _, r6 m' z        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 i5 A8 A: [: K8 s" c7 h
        ZEROMEMORY( &queue, sizeof(queue) );
7 e: ~* ]( m+ {# c' E( H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 F3 k* @8 y' W* V. K5 U0 d* j% S1 M2 A% Q. Z6 ?4 [# j+ T8 x
        for( INT i = 0; i < 16; i++ ) {! n5 v" b/ ^3 s
                m_bMute = TRUE;0 {) S# e- {+ U! I3 V
        }" B8 o" K1 ?. ?9 g6 i5 x$ D7 @/ p
}
8 D8 H" o5 s4 N1 c$ w7 v0 F( V# V, v4 t
APU::~APU()  m/ v, O/ @( f. A
{
' V! ]0 _: O( G7 S$ G( F; Y' T- E  `; b}1 |' _0 [1 \! b) B7 e. r- x, {" n) b
$ K3 \8 m8 `9 v- O
void        APU::SetQueue( INT writetime, WORD addr, BYTE data ), N$ T- ?( m3 A
{* B# G6 E/ n9 x; n% F  }/ `
        queue.data[queue.wrptr].time = writetime;3 ]& p" u3 z, P& n
        queue.data[queue.wrptr].addr = addr;! ~3 _: y0 H' k' _
        queue.data[queue.wrptr].data = data;5 o4 d9 D; v+ n/ U
        queue.wrptr++;
9 f) d3 N' U* O0 A7 U/ ?6 C        queue.wrptr&=QUEUE_LENGTH-1;
2 Z, ?  s8 J( E$ k        if( queue.wrptr == queue.rdptr ) {. X- ^9 `9 i5 B6 y+ s1 J
                DEBUGOUT( "queue overflow.\n" );( b3 C3 }0 v$ i
        }
9 H& Z% W5 `1 B" I}
8 A. ^" r4 [3 W1 ~! N
9 Q" ~( j$ L% I' ?BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 J7 h& u" b, }6 E: x6 v
{
. _; r& ?& |+ {: @        if( queue.wrptr == queue.rdptr ) {% {% [8 Q+ _  r( o
                return        FALSE;
# |% p) B5 H- {        }- _% k2 M1 f3 w" z& b! d
        if( queue.data[queue.rdptr].time <= writetime ) {4 v5 s6 U; j: S( A3 v; e( P
                ret = queue.data[queue.rdptr];
! p) H$ B( r. K) Y  M, e                queue.rdptr++;8 |- M% e6 Q5 S! B! Z
                queue.rdptr&=QUEUE_LENGTH-1;
  M, n/ {! s4 n, l+ h                return        TRUE;. }$ {7 {3 C3 H0 ^" @5 j
        }
" j9 I7 f  N& j  e1 K% [( }* Q        return        FALSE;2 c- t  f# Z5 ?4 {7 H$ I
}2 E) w% ]$ R  t3 L8 I7 x& |! }6 q# q

  m6 `& {' b" b8 {# svoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )0 ?, A. j; {  h% a4 k& z  Y! C( _
{! i& s  R6 D" H2 ?, T
        exqueue.data[exqueue.wrptr].time = writetime;
/ m5 a. s1 }% q8 \5 P9 \5 }        exqueue.data[exqueue.wrptr].addr = addr;* S0 i) L1 D* O- e, B
        exqueue.data[exqueue.wrptr].data = data;
) k7 Q! T. }2 c9 ]        exqueue.wrptr++;
5 {8 ~  v5 f3 s: ]1 I0 E8 b        exqueue.wrptr&=QUEUE_LENGTH-1;
5 d3 ~6 n# Z. B        if( exqueue.wrptr == exqueue.rdptr ) {* i, }+ r) {+ a3 x
                DEBUGOUT( "exqueue overflow.\n" );
6 I+ s; ?5 D; l' V4 c# ^        }! h4 o& I- X7 F" {/ @, \
}
  D, m& m2 I4 @# {3 R5 e) ]8 q$ V  \4 T
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  V; h$ q0 R2 a( B& m6 J* U
{( t. v+ I" L9 Q: V
        if( exqueue.wrptr == exqueue.rdptr ) {" Z8 h8 w/ b( Z  }; w8 a/ X2 i
                return        FALSE;/ n/ `: ~  U  j5 R9 ~
        }
4 N$ q  U) C" [$ ^, t1 T        if( exqueue.data[exqueue.rdptr].time <= writetime ) {. l3 r" Z, q  e" f6 I% M: l7 ?( ~/ b
                ret = exqueue.data[exqueue.rdptr];" t2 @8 N7 L4 e) ]: N
                exqueue.rdptr++;
& G/ ]9 N6 x* s  _$ `                exqueue.rdptr&=QUEUE_LENGTH-1;
8 |2 U; R, ]! O1 V                return        TRUE;4 _. c& V  ]9 U/ q: N
        }; e+ A$ o! h) h0 t
        return        FALSE;
! t9 R2 J) j! W* B: c3 \4 C}6 c4 m+ n& S2 y; x/ J4 j% L
& i5 q) l3 a( j0 e; e/ o$ M; ]# j
void        APU::QueueClear()
  H$ u/ t7 X  m) |$ K( `{5 G% I' T% Q1 q5 l% _
        ZEROMEMORY( &queue, sizeof(queue) );, G5 h! L- i! ]4 R% C+ v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 h( L/ P' t6 I: p3 Y}
. f! k9 X* T% |4 L: R4 d& A6 x2 H6 G
void        APU::QueueFlush()
! a, s6 n  Y% Z7 q7 N# _{% a6 h9 D9 _& ?8 [. K1 t& t' P
        while( queue.wrptr != queue.rdptr ) {
1 b* h! i+ n; ]! \                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" E* H6 X# ?& y; M' |+ y6 ^4 @                queue.rdptr++;9 d6 D0 ]. c% y8 n
                queue.rdptr&=QUEUE_LENGTH-1;
+ r$ r3 c7 a2 S. v( D4 a        }
* M! I  g2 `* g4 @# i. K! ?8 t& j- O( U5 R. J4 G
        while( exqueue.wrptr != exqueue.rdptr ) {
; k" Y7 C/ [- K# _                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
0 Z: G6 x0 ?; J9 Z! A& Y                exqueue.rdptr++;
, \+ K* {. c6 x, L: j                exqueue.rdptr&=QUEUE_LENGTH-1;7 E# |7 M' }" \
        }
) n, N1 M; h7 u4 w% p}1 v: ^( P8 s& @4 o

0 f3 F: i- H5 ^, Ovoid        APU::SoundSetup()$ o4 |& m& o# Y* |
{  ?6 _0 i; E3 q6 }2 b1 Z: N% X5 s
        FLOAT        fClock = nes->nescfg->CpuClock;
! k2 v  n; @2 {' A        INT        nRate = (INT)Config.sound.nRate;
( t4 L# l6 Q. Y* ~3 n        internal.Setup( fClock, nRate );
( C& e  ~' n: z        vrc6.Setup( fClock, nRate );
* p5 \' t2 j/ f! X0 [9 j        vrc7.Setup( fClock, nRate );2 a6 b: d- ]: t7 w
        mmc5.Setup( fClock, nRate );
9 J! u: G% J+ _) S: f; g! p        fds.Setup ( fClock, nRate );
! @4 y& Z/ b9 [) \& v* B: o        n106.Setup( fClock, nRate );) c1 y( W& ^4 i" i3 k
        fme7.Setup( fClock, nRate );
" }- e' T' m* y6 }$ U}9 n1 A  f1 g5 d
7 d1 X) q  P8 t# W7 m, c
void        APU::Reset()
& P" B) R' ^9 c/ Q5 M$ `3 d{
" R. v( q" h, {8 ]3 f# {        ZEROMEMORY( &queue, sizeof(queue) );4 ]8 ?8 c! r' O0 t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% i- r: {$ w+ b2 X( Y; X, E: X
4 Q' ~  ^5 ?' n# I4 D# f( V        elapsed_time = 0;& _7 W* d; N( p& D  l# \  S8 a/ Q; X

& b$ l" {9 F. ~- B2 V* x        FLOAT        fClock = nes->nescfg->CpuClock;
# a$ f7 ]9 R! N7 i7 L* E        INT        nRate = (INT)Config.sound.nRate;0 {) Q) q4 B6 J- Y9 J' T
        internal.Reset( fClock, nRate );# j3 V1 Z% i; t( \% Q
        vrc6.Reset( fClock, nRate );
% V0 K! n* ~( b( P        vrc7.Reset( fClock, nRate );* b/ C/ ?/ R! L9 x
        mmc5.Reset( fClock, nRate );  K7 H. w/ ^: @- R$ s) ]
        fds.Reset ( fClock, nRate );
# O# B, a% `& X        n106.Reset( fClock, nRate );0 r# S" f& h6 h7 B* g3 P9 j5 N
        fme7.Reset( fClock, nRate );' w$ L* Q% t9 S. F
) [" E6 c7 n" Z4 u- a) L, h
        SoundSetup();
% p/ S# R- ]6 @9 m0 N5 @}8 M4 u' |5 b7 y( ~( ?5 p

+ X2 r* U  M, Z- z. g! ]4 p' avoid        APU::SelectExSound( BYTE data )) i$ e8 I# N7 M: B2 [. r6 v% ?
{
- p. {, o( z, ~0 r* x9 y, P6 }        exsound_select = data;
' C7 A  F2 m9 ?}( [% ~% O) u+ B9 `  v4 R
. _. g! a) z' w" n
BYTE        APU::Read( WORD addr )) c' r1 X! \5 R) P6 a% ?7 C: x
{
& N1 U. `  ~. Y        return        internal.SyncRead( addr );
3 l9 b7 h% x' n' s& A  m}
& Q* \  c" \6 ]0 o6 M6 y+ @6 n# p8 R9 F3 U
void        APU::Write( WORD addr, BYTE data )0 j% {  V) ?" r# {3 ~0 L2 D3 _! q- E
{" d# j  O1 Y, j
        // $4018偼VirtuaNES屌桳億乕僩' d$ |) T! B0 n% y
        if( addr >= 0x4000 && addr <= 0x401F ) {! _' {  i4 |5 ?
                internal.SyncWrite( addr, data );
. Z8 p# S0 d0 R, S) U2 Y2 {1 ?' ~. v                SetQueue( nes->cpu->GetTotalCycles(), addr, data );# `. m1 q7 M/ y" L) P/ M9 ~
        }
, ^5 @5 @& H( w}) C) E$ E4 |" B8 M$ R* r; ~  a

3 B4 t  O; T# G; I3 J, R3 K5 i( qBYTE        APU::ExRead( WORD addr )
: u: y: L, x' O2 y* S/ P5 m{5 `* J6 c  n1 a2 X: F8 s& y2 ]  j
BYTE        data = 0;4 u* L' [: K/ t. g3 `

; i2 E3 l) Y/ v        if( exsound_select & 0x10 ) {
3 {- K  X0 _3 b3 E  o                if( addr == 0x4800 ) {
# k  h6 C9 F! X" y                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );# ~8 ]" A- a3 A% ]
                }# B) y4 {$ ?6 i
        }4 P" h5 p% k7 X$ s5 B& Y
        if( exsound_select & 0x04 ) {# J) F# @1 H3 [# Q2 o  C% j
                if( addr >= 0x4040 && addr < 0x4100 ) {7 a) c' c& n; d9 m
                        data = fds.SyncRead( addr );
% h$ l. C6 Z3 N7 m2 ]$ b                }
: z7 w" [; G; g# m& h( W6 ]        }
- v' @3 e; B0 e        if( exsound_select & 0x08 ) {, m  i( B$ E+ D" f9 V
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" r' J9 W3 G" Q4 q# Y                        data = mmc5.SyncRead( addr );
$ ^8 s6 A9 n3 d* ^3 S! a6 [. ~. o# ~                }9 N3 K- B0 U: _9 Z
        }6 e1 U. p1 e9 ?+ U' ]% `
  e8 [9 M9 G$ e
        return        data;" v6 ~8 y7 j; o4 O3 A2 K( \, Z
}
0 F) Y' x  v7 b, S1 ]8 ]) q1 L2 p0 Z" L9 ~& d, ]3 A( p. T$ j3 d
void        APU::ExWrite( WORD addr, BYTE data )
3 f7 ]) n% p8 e+ o* B5 w{! G2 d7 t# a8 u
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
/ m  {+ k" @/ d5 ~6 i
5 G) D- F" B9 }        if( exsound_select & 0x04 ) {
0 u0 j+ {% ]) r( z                if( addr >= 0x4040 && addr < 0x4100 ) {  ]6 m/ U3 v9 j, v% {
                        fds.SyncWrite( addr, data );8 L4 M9 G* m- a$ a
                }' M; ]5 z1 ]( N# b" M
        }. r5 g& ^; a/ E4 J2 B+ k! z

  S9 _# S; Q- ]: H% i- C        if( exsound_select & 0x08 ) {6 i( ^# n3 O. K* T
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' S. e& y- F* Y8 e4 i. V% F                        mmc5.SyncWrite( addr, data );
2 j( [; p6 O7 q% |) @                }
* n7 k( U+ J, ~) f" W        }' B8 }# v  a: N/ z6 w8 A# i
}( B2 r: \: y4 {/ y/ T5 P7 R

+ E. q5 F- \$ B# y2 h1 \4 @, ~void        APU::Sync()
* G* z8 V3 t- q6 f{6 {8 U! t; K  V1 D9 W$ V' H- N9 d
}0 X2 V- z9 y  e7 ^+ \# q) h
( Z1 A3 b5 D7 o5 O, L3 W0 Y1 G
void        APU::SyncDPCM( INT cycles )) [2 [/ k4 L& I& a, K/ w
{9 G9 H& S: [' x6 S
        internal.Sync( cycles );5 v* f& |3 V1 _
' L( L0 W% K# q: e/ O$ _
        if( exsound_select & 0x04 ) {4 R- z2 r1 b' L' B* m
                fds.Sync( cycles );. k5 ^9 a0 O# y( x/ t' ^
        }
: C4 a8 E- B5 B        if( exsound_select & 0x08 ) {. |6 _' o2 t3 ^; m1 G( d6 v
                mmc5.Sync( cycles );# @( n' ]4 S; o1 o% w# ^
        }8 q5 c& D' Z  F! n2 u% C! y
}
) r1 B0 Q6 m' f- y$ E
& n3 j, t, n( p' nvoid        APU::WriteProcess( WORD addr, BYTE data )
* O- I6 A  y1 I& r' J" c{+ I1 J8 B. E! ?1 p) K1 w, L* x
        // $4018偼VirtuaNES屌桳億乕僩
5 F4 I, x, u9 ~- k        if( addr >= 0x4000 && addr <= 0x401F ) {' T% l* L/ s( L# j
                internal.Write( addr, data );
, A$ D* b# u# D# o% K& D' S        }
5 O* X1 a2 D4 }* x' c}
( g6 f9 l' [/ Y* X& i5 A' z
4 m) B6 S: n% Z6 S( l0 o" O9 Rvoid        APU::WriteExProcess( WORD addr, BYTE data )1 I* u, h* O0 Z5 s  b
{7 c. q1 L6 Z- U1 `
        if( exsound_select & 0x01 ) {  v; e7 \# {; _6 c1 W) V( L
                vrc6.Write( addr, data );2 F2 R) N% `  S+ p
        }
+ L" I: |. J( b1 D5 X& |        if( exsound_select & 0x02 ) {. a- L, t! p2 }
                vrc7.Write( addr, data );
7 s( |  Z& V3 e) k# V        }
& m% Y1 a  a  A, b        if( exsound_select & 0x04 ) {6 f; B& F9 Y) b& {3 s( i" E
                fds.Write( addr, data );8 ~/ i2 b" E( t
        }0 \6 G6 s! m4 d' r$ M
        if( exsound_select & 0x08 ) {6 y5 t: _( [' d/ l( y. R
                mmc5.Write( addr, data );
+ b! n, j/ Y( G$ q/ @! M        }
/ v% z5 k# ?! V. ~5 D9 O+ {( \2 A3 ]        if( exsound_select & 0x10 ) {! p1 n' N( A( v- a2 W4 P
                if( addr == 0x0000 ) {: a- u" Z& X4 S& i& _% X: k0 A
                        BYTE        dummy = n106.Read( addr );
1 d& G4 _: y0 E                } else {
! k% k8 C* V: B                        n106.Write( addr, data );
8 T6 E! b5 [, Y2 Y                }0 @- s# r) _' |
        }
* |+ f$ _3 \. M  L5 V        if( exsound_select & 0x20 ) {
7 Z2 g% [% k0 R0 \+ c7 d                fme7.Write( addr, data );! y) U8 k6 @, a, L
        }& \4 P' p( O# V$ I) B+ B& Y
}. o7 h3 _# x- E& ?2 W
  |; m. m4 n! U1 L% R: p3 X9 A2 P
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )8 h& Q9 s- a9 Z7 ~7 |
{+ c. r0 A+ ]3 _7 W
INT        nBits = Config.sound.nBits;
/ E1 m& z! Q9 U* x2 z- n9 sDWORD        dwLength = dwSize / (nBits/8);- `1 i% `" w! y
INT        output;
0 V+ T$ ~) k' Z; g& R/ eQUEUEDATA q;
* ]3 g$ O% }& i, h+ [# ?, DDWORD        writetime;# l# x9 L# X: n/ e0 j' q( m, S/ ]7 r
3 l$ |+ m& N, [7 \$ E
LPSHORT        pSoundBuf = m_SoundBuffer;  ~" a5 S& Z- z% i! V  `& Y9 G
INT        nCcount = 0;
* }$ O5 A( f3 }* J
. k  F0 ^; }* G5 k1 w4 t6 yINT        nFilterType = Config.sound.nFilterType;9 B* G0 H1 W9 W* B4 \7 {" j
7 |7 G& p% F( ?! ?
        if( !Config.sound.bEnable ) {
! n  r4 @. d% t5 b% F, p' l% Y# h                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 r* m1 g9 D5 k8 T0 `/ |
                return;# @9 h# B2 Y; p1 P  C9 I3 B9 t
        }1 P- W1 l3 F1 ?- h/ C$ F/ m; q" l

4 a5 @) q+ M8 X& {! v, G& k        // Volume setup6 o' j7 Y, H( y% W- z8 E
        //  0:Master
; \/ `: D/ |6 P$ l, y/ U  k        //  1:Rectangle 1; J  ^7 c: Z) \+ ~" M9 F
        //  2:Rectangle 2/ [% i% Y/ s  J5 O* i
        //  3:Triangle
: c$ j0 P' w2 x. U4 M; T        //  4:Noise
5 K$ b0 v$ ?7 x* _/ t        //  5:DPCM2 z2 l$ O5 ^/ B$ @  V; r) E
        //  6:VRC68 l' T/ h, ?6 D) s& h% s
        //  7:VRC7
$ H" L& L3 o! g$ I        //  8:FDS
6 {( j8 b' C8 f3 k1 ?$ n3 f        //  9:MMC5( T: b9 ]1 B: q9 g/ j
        // 10:N106+ F( ]7 o4 _3 w0 b
        // 11:FME7
. G* [& Z2 g& Q" U# m        INT        vol[24];* `3 U/ `9 x7 K+ Q
        BOOL*        bMute = m_bMute;
" o6 n: U3 f, _. w7 O7 e, a, f1 b        SHORT*        nVolume = Config.sound.nVolume;% I( r3 a; _0 M1 _+ C$ l2 C
% @. ^2 V* n7 M, }% E' d
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
5 J# z$ Z! P+ u* n" A5 [
0 }5 A( v1 r$ D2 e2 O- ~3 h        // Internal
  f8 a# k* h- X        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
% ^0 V9 ~) |7 m! D+ T        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;- P1 @) b1 L0 o. M* {! x; b
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- ?3 w2 a  V. I
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
) R+ V1 y/ ~3 M$ u7 z7 Y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& \4 d1 W! {# z' H1 _* Y

  V6 M: O9 a* p- Z! o0 }        // VRC6
0 U+ {! q6 g" a        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;' |  R$ M3 T( G1 e5 N
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 q5 m! b7 ~9 B        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& O/ ]) y/ d8 T5 ]$ u1 Y) ~

+ G# O% o) ~* P! e        // VRC72 m. O  {: g  j1 W" c; o0 r
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- a; j% G' y, z
# @7 Q) Z$ {. w4 H6 b" n        // FDS
, E4 |3 v" L2 J; P8 ~% n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
% o2 F( p3 `  p/ O# y, {8 b6 L5 ^. O0 r
        // MMC5
  L" q# e$ ]; ~1 U: w: q5 E( [% O        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& u, D& w: L4 F" q
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 H6 h% r. z4 L8 _' c/ Z  ^7 D        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: D( S, E8 B! T, z4 t! _$ w: R( u3 N
        // N106) Z) ]7 Z! r3 V: {
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 X% q8 Y* h: h        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( Y5 w1 C9 L$ N( e+ _2 G$ ^
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 |: b8 z! x8 R: ~/ R) b' H, L$ @
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& q6 L5 z- Y* o* y3 L7 k: {9 i        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" @& c0 u- h9 g
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ {; }9 p; P: J
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 c& F6 B% Y2 K  e* K! o7 Z4 n# K
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 i8 p# n4 F8 f: Y7 H6 r. H2 R5 p' ^/ y- B4 J5 }
        // FME7
+ |9 T" |! F* k9 p  B  |6 J5 y, l        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( ]- P- a4 o" [5 G
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  q: s/ D* S- Z4 P; D& Z        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% |) M. o+ A2 Q) m9 t  B$ Y! f, W
, w( W1 o6 O9 E( E! v//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
; q) `1 ]- v0 E2 ?& x, ~: E9 ^        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; F  n( T2 V" Y* B3 h; [3 T! p- B3 R  R% S0 ~
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟1 B0 r+ ]! _$ R% F  o# _
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* L  s, x- [( U/ L1 Y( n$ m$ p, b/ u
                QueueFlush();
8 Z2 `  L' f! |+ B  M        }5 C4 s" G# p7 E: D1 Z0 ?; J

6 ]* }3 b7 v5 X3 Q2 l' O        while( dwLength-- ) {1 C. A9 m, g' c" A& E2 q9 K. `6 `
                writetime = (DWORD)elapsed_time;
% h- `% y  y; a
$ f$ U0 U5 B! O                while( GetQueue( writetime, q ) ) {
4 f- L- m) S  X5 Z% @& e% g                        WriteProcess( q.addr, q.data );
8 ?* s9 ]" ?& {- \, U# P" _8 ?                }
4 P; a5 }$ s- `4 ?8 ~; D7 r' P0 N+ l" Z' C2 z7 m! K; Q
                while( GetExQueue( writetime, q ) ) {
5 |. R8 N. e/ ?6 Q. `! U4 q$ A- a- q                        WriteExProcess( q.addr, q.data );
: V0 W* L$ J2 L) h6 C) x, h                }
$ t* N+ d, P9 c; E/ y
! W- q/ k$ Y3 w7 ^; i5 R- P                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! u" u. C9 H! x$ S4 a4 x3 v
                output = 0;4 s; ]5 z8 k; Q
                output += internal.Process( 0 )*vol[0];
$ l( U! {* i& f0 z' Q# b( R                output += internal.Process( 1 )*vol[1];, e7 v1 G/ E$ C' d
                output += internal.Process( 2 )*vol[2];
/ p) H( Z5 }& p; y# l                output += internal.Process( 3 )*vol[3];& R3 y$ |# b5 J5 r( i
                output += internal.Process( 4 )*vol[4];
) [6 ^2 W$ [% e/ q+ I( }
$ M6 p' S+ ?9 M8 n: q- _3 w8 w                if( exsound_select & 0x01 ) {
: |! E& C. F0 [2 c1 U0 n                        output += vrc6.Process( 0 )*vol[5];* `3 Y! \$ u  R; l) {9 S
                        output += vrc6.Process( 1 )*vol[6];  A6 j0 `8 C. \
                        output += vrc6.Process( 2 )*vol[7];
, g" u' K8 S  ^, n) {, ]; j% b                }8 f) K: f# s2 a; _9 M  r5 d4 F
                if( exsound_select & 0x02 ) {
1 {1 z5 @+ e: @. ]5 I3 t& q/ `                        output += vrc7.Process( 0 )*vol[8];
4 o8 t3 z7 V3 g: x5 i                }
  ~9 B# ^; e* U& Y4 e3 G                if( exsound_select & 0x04 ) {
2 J7 h* _, q# V" w- c                        output += fds.Process( 0 )*vol[9];
- a! D5 t8 q6 q4 Q                }
$ W0 T- F8 C( |- K5 e                if( exsound_select & 0x08 ) {
  V. j# V% x6 A6 s- J                        output += mmc5.Process( 0 )*vol[10];
* K6 L7 g6 r' O& C5 s% \                        output += mmc5.Process( 1 )*vol[11];
( y/ i7 ?# H( k                        output += mmc5.Process( 2 )*vol[12];
: F5 v8 `- d  F* H# e                }
/ e( Y/ D) C. M0 R/ l7 ]: k5 P                if( exsound_select & 0x10 ) {$ X( ~: x/ c' i# d% S) C
                        output += n106.Process( 0 )*vol[13];
4 ]# f4 F1 n, ~" B) `, {0 e* X4 Q                        output += n106.Process( 1 )*vol[14];
5 \% w7 J+ x$ S% \. r  I                        output += n106.Process( 2 )*vol[15];
  K7 w+ W; V& }5 P5 K$ }                        output += n106.Process( 3 )*vol[16];
0 I& }! {2 c; V4 t1 X  X. s3 G                        output += n106.Process( 4 )*vol[17];
9 t$ ?6 @8 l4 A! W. ~: |! v' p                        output += n106.Process( 5 )*vol[18];
1 U* j& a# a0 ^                        output += n106.Process( 6 )*vol[19];
) M. X0 n3 j* x8 t4 E7 b! |. k                        output += n106.Process( 7 )*vol[20];
2 y9 H5 e% D$ B! q                }! K6 \1 N$ t* @4 F. m& @
                if( exsound_select & 0x20 ) {
) K+ r9 n- Y0 `4 \- u4 N                        fme7.Process( 3 );        // Envelope & Noise2 Z, n+ X2 U) Z
                        output += fme7.Process( 0 )*vol[21];
* u  T& X, E" i2 L                        output += fme7.Process( 1 )*vol[22];/ Q5 S! E, t6 Z' s8 d% r" K! n
                        output += fme7.Process( 2 )*vol[23];
% p, Y7 G3 ]- a3 P                }
. y) a. c- |! c1 D0 e
9 @, t; M  y8 Y' A. J/ z' E0 G                output >>= 8;* F2 q  Q7 v1 G# \6 }3 r/ {

/ g( @$ J2 G8 e' V- k6 M  p                if( nFilterType == 1 ) {
8 a1 L9 x. H- {8 }2 S7 p' n                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 P( j1 f0 \; D0 F5 U
                        output = (lowpass_filter[0]+output)/2;2 t' {0 l* x' p4 ?
                        lowpass_filter[0] = output;
7 W" O, H, `2 T6 {: e. f( }                } else if( nFilterType == 2 ) {
7 g5 I1 ?% J! k4 X$ h                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 j) w3 e9 d! H                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
4 F7 Z9 J; k7 _  j) l9 X4 l! U                        lowpass_filter[1] = lowpass_filter[0];) B4 j* q5 I6 X( ]' T. s
                        lowpass_filter[0] = output;9 {2 Y) W1 Z. W& \- q- A
                } else if( nFilterType == 3 ) {
4 t' J3 V$ W+ f  L; W9 W                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 P* t; r# ?, O) z/ e8 k7 ]8 O
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 k+ t. d- b7 I) g( u' M                        lowpass_filter[2] = lowpass_filter[1];  Q2 g# [% P- n  v* G
                        lowpass_filter[1] = lowpass_filter[0];
! V8 j& r# N: F3 s                        lowpass_filter[0] = output;( [; L, i! N5 P3 @3 A* @
                } else if( nFilterType == 4 ) {# P1 G! j! U3 N6 t. [& ^/ O
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)8 z# r# \- ^4 t* u3 [' \+ F
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;! W) u/ U9 Q# k6 N! z
                        lowpass_filter[1] = lowpass_filter[0];
) C; F9 [9 \6 T/ ^; U3 [3 A/ p                        lowpass_filter[0] = output;
% I* K0 ]; J4 }                }
2 ^( c  [' P3 w) Q# r& e# i1 S" {+ }0 T- J7 g
#if        0
9 {% f( }) v2 \  R  I! X8 N+ j$ |  c                // DC惉暘偺僇僢僩9 b4 g! u/ I/ E1 D+ _$ j& @
                {
4 f: x, Q# b, A2 ~# Z1 V                static double ave = 0.0, max=0.0, min=0.0;
0 |- u' R) r  ^" v                double delta;
% k0 y; F9 O; X' I5 R; w) z                delta = (max-min)/32768.0;
% G- N- `3 a* \7 w$ r                max -= delta;% Q$ i0 M2 L0 Z3 O& o9 B- X
                min += delta;7 p( \3 b4 c& ^4 M: F3 _: m. Y
                if( output > max ) max = output;
5 H8 i% g3 w0 F; }5 m' |& D. q                if( output < min ) min = output;+ a/ {! U, {# \5 {/ L" r
                ave -= ave/1024.0;+ E0 J+ W) {: V6 ~, [
                ave += (max+min)/2048.0;
* K' m* E6 o# g+ i4 P: @                output -= (INT)ave;
# l4 o6 v& {6 w8 s0 q0 b                }0 f" [9 }! ?1 V: F9 R
#endif
4 c2 h' w: c4 }% H. Q6 r2 T! u$ `#if        1
8 [8 J1 R, N$ h5 p4 z+ [. R4 l                // DC惉暘偺僇僢僩(HPF TEST). I, N. K4 _9 l
                {# f7 v! t% d4 L  g6 `% }+ J0 c
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 Q& ?( W, o! _) }5 I+ @# R                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 f3 N; g  o5 e, V                double        cutoff = cutofftemp/(double)Config.sound.nRate;
& d* u, o9 i# i6 K9 C. P1 p                static        double        tmp = 0.0;
& A% ~  g1 n# w' x                double        in, out;
) I6 u- J9 C+ t5 S9 l: E2 h/ B! I2 d. }) q) H( q7 @" i8 H# D: i
                in = (double)output;( k6 h  M$ q$ {4 e
                out = (in - tmp);
. \# i- K; ~4 B) w' g                tmp = tmp + cutoff * out;
* f1 b) w9 L; F# Y/ D! m) e+ N
# C" n3 f1 G, `8 l! y                output = (INT)out;
6 N6 @% v9 i- G4 d* ^9 _                }- T. A1 P9 O/ F5 d
#endif
% M$ g* y' F0 Z#if        0# B: |, I$ |; Y' V$ L0 o' v
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
3 Z5 D. h1 b: F4 t7 g+ ~: i* j' ?                {
- S7 j1 K9 L+ _" P, U8 J( m' W                INT        diff = abs(output-last_data);+ B8 w0 T7 B! l4 |2 b7 Z1 r
                if( diff > 0x4000 ) {
# V0 Q4 H& M: K0 @  z                        output /= 4;
4 J5 }: u4 q8 D% H  ]5 p+ C4 G3 ^                } else ) R3 Z5 G: m6 S0 n/ w$ i9 Y1 H4 c5 p# u
                if( diff > 0x3000 ) {$ ^' r% U! e+ v! K0 v! m
                        output /= 3;
2 \5 J/ z" O' {# B& g                } else
9 s; z5 X4 U8 D, j1 b; d' U                if( diff > 0x2000 ) {
+ s: K, O# c7 [; e% }# d" P% c                        output /= 2;
+ Y7 D1 Z$ s& W! g9 \& D  `2 D                }/ n  t5 J: f' U  X( O! j! ?% C
                last_data = output;/ q3 F: C8 N# t% k  C
                }
* H! l) P. y% l. U2 n3 p0 o#endif6 ~0 e, B% F( e' ?' y' _* L+ h
                // Limit' Y) Y. u; E8 @- R2 `# B* @
                if( output > 0x7FFF ) {
7 M; s  C" r; c) c, R  `                        output = 0x7FFF;( Q. d+ @2 ?" M) T8 P
                } else if( output < -0x8000 ) {
4 X" Y- r5 K: E0 E8 W  _0 V                        output = -0x8000;
& S8 O3 W* b0 e; l; _                }. }. v" q# ~; J: x

/ m6 V2 C% ~2 o& T. R4 I8 N! j" r                if( nBits != 8 ) {
+ C1 ]( V7 S0 \7 ^4 e- Z                        *(SHORT*)lpBuffer = (SHORT)output;. d  R, ]! ~( C* d: U6 l3 B
                        lpBuffer += sizeof(SHORT);. o7 c4 Y$ |/ g9 C& ~' G* b$ q
                } else {
" ?2 O  b6 h6 a6 T6 e% K. u6 E                        *lpBuffer++ = (output>>8)^0x80;& L( s' K9 W* d; D) C2 V
                }: D- [. f- R) O2 {

7 p3 z5 g& [: n/ e! Z& C" _                if( nCcount < 0x0100 )9 _- l6 q1 f) [$ z
                        pSoundBuf[nCcount++] = (SHORT)output;
, e9 ^8 D6 S: y/ n  g- D/ n. \3 F; P# {" Z( |( S" |
//                elapsedtime += cycle_rate;1 M( r9 \$ }! B7 ~+ Q& c' e1 S
                elapsed_time += cycle_rate;2 J& o. m& w5 Y% H
        }) D* x  _$ t  M" t9 b8 F) ]

; m/ Z3 l9 F- M' J. c7 w#if        1- Z, t5 d6 D3 @3 R  v* \# e
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, o" V! w0 G6 D! |" E
                elapsed_time = nes->cpu->GetTotalCycles();
% z+ B0 c  E0 e3 P        }/ F/ K3 C; e2 n- |! C
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 \( a+ w/ O% x6 W
                elapsed_time = nes->cpu->GetTotalCycles();
( i& f* f$ T) F! E1 D  h% h        }' y! a9 B2 s1 Q4 q: a
#else2 ^; s7 P3 i3 w; [
        elapsed_time = nes->cpu->GetTotalCycles();
9 R3 }. r0 o9 ^0 n/ b% O, p$ L#endif6 d6 \: J! q7 ]' w# U
}
3 n4 [8 R6 a9 U+ q. t2 S4 B2 l
6 f5 j- @  V6 z0 j// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)$ t# R/ j0 q8 N9 q- P1 U* g
INT        APU::GetChannelFrequency( INT no )
5 ?8 }! D% Q! n0 o{) z' ^; \6 F; m) A, H8 \
        if( !m_bMute[0] )5 ?8 p5 J2 ]- K8 ~
                return        0;) h  _" M, ]2 w* S" }; ?
+ V, f9 f( @! F5 z, q# \$ I% @
        // Internal! ]& U9 O0 b. U' V# P
        if( no < 5 ) {
. R# h! q, s" i4 q                return        m_bMute[no+1]?internal.GetFreq( no ):0;. ^: P9 L8 a% ~' i0 k8 I
        }
( G" d9 P7 v4 Z( [  ~        // VRC6
: B1 J; o7 V( V1 J$ M        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! A  @& D, a. |: }" [                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;' Y% v7 R: o' _+ J( i- u
        }
( `8 v3 l2 u3 s  h/ w        // FDS6 w' W. S- Y$ X6 V8 N4 ^( g
        if( (exsound_select & 0x04) && no == 0x300 ) {$ e* r6 O) [4 T- g
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- ^6 U8 Y% g' ?- m+ T& s        }: x; ~) M" J; \
        // MMC52 {# F+ l3 c  t
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
% l9 G3 k) K# e) H0 |" Q+ n1 d                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;# T5 q0 V6 u7 ]( w+ r2 c% R
        }5 }% @, z6 ^* a' m' a
        // N106
' x) c9 j, |2 F3 K; u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {0 I0 d9 ^# R' _- u9 V3 o
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
2 f6 G( o9 h: S4 T  o- ~5 i        }
  P% u, S6 {' e  e* l* i4 E# n& @        // FME7
+ ~6 `1 Z' }; x* `1 A* F7 }  e7 r2 T        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
* a& d7 Y/ I5 s8 v$ M" \, e* D                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
- P/ p8 W) Y7 f        }
5 Z* _- @; ?: E        // VRC70 I0 r. h" l. G6 |# K* w
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# o4 Z7 N0 R# ~5 {  Q
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;% K/ N# h+ U/ @% H: c% a& {( V
        }
7 X1 f1 j( f( l. ~2 i; L$ I/ S0 p        return        0;6 v. I1 u1 N' L( U- S' i$ l$ P
}: I; u8 t: p' Q, W: O1 `$ V: A6 ]. w/ g
! N% c3 |! N- @. W* X* x6 z
// State Save/Load
; C* G7 b9 v/ _! lvoid        APU::SaveState( LPBYTE p )
  j/ h/ E, }! ^3 _{
: C7 v: P' T6 a#ifdef        _DEBUG
' Z  b, R) A3 rLPBYTE        pold = p;: y- ~: I2 J0 ~$ [
#endif
# v0 s9 [+ k) X% R
/ y5 s5 a% B* e) y8 ]8 j        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞/ Q* ]; U( Y' ?3 ~, r- W2 U
        QueueFlush();9 d( @  @6 h) m* e% z5 G
7 A' N' C) w( S' T  U
        internal.SaveState( p );  E7 t+ o& x$ `+ L/ o0 U# ]- L! P# ~# V
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding- f9 o) b9 d# l' `" F8 w. {
% v& j+ z/ [' O9 Z/ y8 t$ R3 b
        // VRC6. r# u& h9 Z. h/ }6 r" @
        if( exsound_select & 0x01 ) {/ g, f" N3 b& A# s' g) |2 v
                vrc6.SaveState( p );6 S/ t3 T$ m4 N. e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 f2 M7 T( o0 k  s3 K0 W2 C9 |% P        }
. s9 m5 j2 ^2 ?  ~! }& s0 ~        // VRC7 (not support)) D" U5 E' I& m( U+ n
        if( exsound_select & 0x02 ) {0 M% S0 H) E  E! T2 m0 p
                vrc7.SaveState( p );: s; v  }0 Q  L* i* @6 A$ m! ^" @
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 m: z* b5 o  e0 d7 ~: U+ Q' y
        }
1 \# ?6 \6 s1 _1 c# c- Z: Z, [        // FDS8 \8 L& k! a$ p7 D# A5 H! q
        if( exsound_select & 0x04 ) {; r) p( L( M4 m" [- V
                fds.SaveState( p );( i# x9 ^5 N1 c6 R- `9 e2 M) y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 w# A, j, q4 s2 S' o. b        }0 R1 d- ~+ J  G3 \- z# j; L
        // MMC59 N" J# P; R1 u8 V8 v+ Z& h
        if( exsound_select & 0x08 ) {
# H, P( G) [5 j6 q, H                mmc5.SaveState( p );9 g6 `% ?1 m( Q$ F: ^2 ?) \
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 [. W0 p6 ~' o- k2 }        }/ ]- O9 D% B% }0 T( U1 q
        // N106- Q( b9 b8 S- n
        if( exsound_select & 0x10 ) {* T- [/ N+ J7 o7 W+ c
                n106.SaveState( p );" D# O- V. R( e9 ?+ P
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% d8 W+ U, O, N8 ?
        }# `. {* Z  U' z6 j- P7 e8 D
        // FME7
4 G0 \4 N7 @, u        if( exsound_select & 0x20 ) {- ^7 e. ?( X/ _8 d7 E- j' |/ j
                fme7.SaveState( p );4 O0 p9 g( T0 ]; q) S& v/ \1 j: J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! W# m- m! J) W: Z        }
! _& g( ]4 T! }3 E0 _/ n! q7 G7 {, V4 t% b( }& F* g# d1 V
#ifdef        _DEBUG
1 W. B* s0 V; `) V& ?$ B8 UDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" y9 X4 _5 l: C% [1 ?  ^#endif
' z% O8 W9 k+ F% u}
4 g5 L; F9 |9 B
3 i! k) D; w! E9 L% ?5 x1 T5 D+ `void        APU::LoadState( LPBYTE p )
$ p" O+ I: F3 A& {) T{# {: ]: ]. U- h  K% I; h8 c% Y: K
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' T- w4 w: o$ D" O6 H2 m. p
        QueueClear();
4 E' {: b7 H' o& K( d8 h; b, h. t6 {* Z/ k
        internal.LoadState( p );
* v  C! |6 k1 y& q* ~        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- s$ Q4 S8 K. D& l' N3 C% x% Z2 G0 K1 u9 A
        // VRC6
' Z  r7 V) e% I5 o        if( exsound_select & 0x01 ) {
4 b1 a( N  q! R3 {1 {5 J5 @                vrc6.LoadState( p );
3 l* M% ]5 x4 ?$ B9 r  j/ ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ p6 `6 R, W/ y' b- P# d; i' I
        }" H* `, D) R. c* ?4 k  Q- l
        // VRC7 (not support)+ ^% G3 T# B1 ]# U" D
        if( exsound_select & 0x02 ) {/ H; n2 k2 B' l; E! C! R- D
                vrc7.LoadState( p );( G" j( O5 P% t  n3 ?( d
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: y7 G* E5 L0 K4 y3 W        }( s# D! a/ i- T& `
        // FDS# B  J9 o; y& q  E: \9 U  {
        if( exsound_select & 0x04 ) {. e! x$ P9 M: _5 L' R% G- i
                fds.LoadState( p );$ @2 S0 E% G- T8 u
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' V2 ^; u, Y  u+ f) @
        }8 H' V4 k7 K# h( E! s% Q
        // MMC54 @2 L  F7 s% y; ]7 h3 q( I
        if( exsound_select & 0x08 ) {
# _4 P  l# }) h7 q, M: T                mmc5.LoadState( p );
: J8 K) k1 Y1 V& G                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. h- i; Y/ N( r" A
        }
5 w: Y: V6 J2 y  N        // N106
% j. @. ]6 {$ t4 d        if( exsound_select & 0x10 ) {  p! Q# D1 e' G0 [" `* H9 |
                n106.LoadState( p );
* i( B% E5 z) y! A7 ~# r                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 {1 \% `7 I5 U3 C, f  t8 a
        }
0 a; B+ z7 E. E# b7 t        // FME7
, s% e  J8 a4 K$ k, Z! y  N+ M        if( exsound_select & 0x20 ) {
- r6 _4 z0 V4 e' E  ?& H                fme7.LoadState( p );
6 J  X9 a8 j! w                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ @3 P' M+ P( D        }% B5 p' S+ a! Y) }+ n) f. N
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
. u' N: ^. G1 I+ O+ e可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, a: V6 T2 V, K! z& L/ Y3 R感激不尽~~

1 U4 f  P/ {9 H- J  I恩 我對模擬器不是很有研究,
7 U4 v  j( v8 x: g! {3 n雖然要了解源碼內容,可能不是很困難,0 v2 U/ `! X" H  R; q- {) b
不過還是要花時間,個人目前蠻忙碌的。" M3 I8 p) m5 X1 W5 U+ E& q: j
7 S! j5 r$ o2 D( _
給你一個朋友的MSN,你可以跟他討論看看,
/ f0 @  J) Q- B他本身是程式設計師,也對FC模擬器很有興趣。
$ {$ ?+ v1 r7 G3 c  E/ Z. U* ^3 V! B7 w
MSN我就PM到你的信箱了。# q, M% Q, C/ B7 s

8 ^4 K$ ]( H; e' M希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ e( `, P9 f' D7 o
呵…… 谢过团长大人~~

' ?* ~) g( V/ H1 x0 G+ e7 I$ Y& H$ d" U/ J3 h- D
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
: y! T: o4 F. `& x: U$ W4 O7 U4 j9 y团长的朋友都是神,那团长就是神的boss。
. u  o8 k# t0 l2 s; A
哈 不敢當,我只是個平凡人,
4 |& p- x+ B2 @7 P9 r要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& L' t! E8 F4 g3 R) x
ZYH  J, }5 `, b+ B$ v; @5 J0 \7 K- R! O0 F
QQ:414734306
5 R# ]( C. y. A1 d/ E4 xMail:zyh-01@126.com; T2 y! Y) R/ U3 B. G/ ?
# j2 S0 g# O2 g. a0 G5 ^$ L5 Q
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . [8 G  V( l; B' }) Q' Z4 E, T
再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ v( I6 `7 A8 \$ I不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-19 13:55 , Processed in 1.120117 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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