EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) I) K8 C/ U  k5 M' |+ d楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 _1 L% x- \+ ?4 C+ r& l这里有相应的模拟器源码,就当送给大侠了~~0 I, Q( L* c/ [( N  f
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 . T2 C, \5 `* y1 `% Q" i
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! n4 F* Q& n. H& v3 C& d0 z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: z! a9 u, H$ p/ W3 C: M- Y
这里有相应的模拟器源码,就当送给大侠 ...
/ m0 F( M! k9 v7 g* l
聲音部分(Audoi Process Unit = APU):
+ X% Y4 D# z( l7 U% a2 n6 o.\NES\APU.cpp2 L, ?; ~, N, h- R
.\NES\APU.h
  z) S+ a4 C: h; f1 s5 M
, `. H" d* E6 ^7 A+ P
. h7 E; U' @- j3 `4 k影像處理部份(Picture Processing Unit = PPU):1 {1 o3 b0 q4 q2 T! c# h, A- x
.\NES\PPU.cpp
- l- x/ U7 A0 e! g3 f# w.\NES\PPU.h; Q1 ^$ d/ t& z8 A; C

0 i- @  {( t4 X" t如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
8 c/ S1 B$ E# u& i$ x3 |(由于很多专用术语和算法机理都不明白,所以看不大懂……)
" {: d- K" l9 t  `8 s//////////////////////////////////////////////////////////////////////////
+ A9 U1 ^: Y2 `. N. v0 A* w' V//                                                                      //) |* w9 ~% ]6 g9 V+ d9 F9 d" T1 ^
//      NES APU core                                                    //6 Z8 S9 L6 l; k8 \* r+ k
//                                                           Norix      //
7 t% f$ S! K! Q  T//                                               written     2002/06/27 /// [6 _1 z" p$ q. D
//                                               last modify ----/--/-- //9 }" H- i% Z* F) d' ?+ ~0 l
//////////////////////////////////////////////////////////////////////////4 E3 \" a1 L6 K: v; F; T+ R
#include "DebugOut.h"+ @2 z# o- y1 L; h$ R/ N8 v
#include "App.h", U- G- q" w5 x
#include "Config.h"
, s0 w4 M2 l' W6 A) z. ~8 @/ b% C: t% e4 k0 s
#include "nes.h"  F/ Z# [+ }1 z9 U7 h: d% u, N9 L- w
#include "mmu.h"
8 v8 N* ~( U+ P) O' s0 ?! O  v#include "cpu.h"
, F' e. y  Z. l/ N2 O#include "ppu.h"
8 Y- W- M6 |" ~% t8 |* s% {#include "rom.h", I" W# k+ e, }8 O+ Z
#include "apu.h"# J/ U3 e( k7 K) y; L) ^
; M4 N8 a' ]* u, ]7 ]6 Z& e! `
// Volume adjust
& ~7 @2 b9 g# m+ i! ~// Internal sounds5 p, _* w* q. R( E4 b; l4 q
#define        RECTANGLE_VOL        (0x0F0)
# U6 @6 M0 D; p. S#define        TRIANGLE_VOL        (0x130)9 q/ c# `8 [7 A, ~+ j
#define        NOISE_VOL        (0x0C0), S+ y( T8 H8 m+ t
#define        DPCM_VOL        (0x0F0)
( s$ b( K# i; z, p// Extra sounds
% y" w+ a- e# S#define        VRC6_VOL        (0x0F0)
  `2 O" s7 |) r& X! e4 u#define        VRC7_VOL        (0x130)4 o& d: g: t$ k: S# o
#define        FDS_VOL                (0x0F0)4 w0 ^9 Y3 \7 [$ i1 w
#define        MMC5_VOL        (0x0F0)
+ c4 M: p( B! ~2 u% E  g: l#define        N106_VOL        (0x088)7 C; f4 f2 d3 `$ A# t% G
#define        FME7_VOL        (0x130)
5 K) a! n1 x' I( w3 X5 C3 i+ _0 c
! E1 {" c% T- G# ?APU::APU( NES* parent )
0 R9 ?4 x) M! j. \) M. g; W( B$ b{% C) ?- r3 X/ l1 g- k0 c8 M
        exsound_select = 0;
7 S4 ^  Y6 @' }
/ U( v! x* N. M9 L4 ^$ w, j        nes = parent;5 J+ @" p: K7 r8 n# F9 x6 B5 g
        internal.SetParent( parent );1 N1 \2 d: T; `/ R& t

" l' X( F: O5 P! Z        last_data = last_diff = 0;
4 k! c. j6 ^4 }! ^# T) V9 e9 C: p
. f3 e3 z, U& M) e: X( z        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
! ?6 O& l8 H+ f  Z& R$ L3 j7 p! ]3 F% E, b/ }: l
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 U2 V% S3 v8 l0 O8 A! V        ZEROMEMORY( &queue, sizeof(queue) );
7 s$ c  r: T" V        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 b. H% G1 @& H/ a& M3 n) c0 p
5 M( p: o/ M( Z+ s        for( INT i = 0; i < 16; i++ ) {
4 a. t* ]) o& ]7 L( R* @                m_bMute = TRUE;% {( s8 ^" Z9 R8 q' C. P9 S
        }
" G, v' f! o  p- ]3 C. r/ W}. b) G3 ~- R( e' S
/ j, i( G: p. x
APU::~APU()
/ r/ a9 E: ~4 `+ i; b* ]  p{
  R3 A$ X9 o- h5 K5 d' s3 v}- _' }  d3 O( T1 A" u+ R. `' u
- H$ A- ?7 a- ], l7 V, f3 N7 [" P1 r
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
1 @0 v  M- k9 m  R7 W{9 h/ F# [8 Y' _3 x
        queue.data[queue.wrptr].time = writetime;
& x9 l! Q( n2 r" M$ w        queue.data[queue.wrptr].addr = addr;. Z3 e$ b; t, _7 o) H6 U' x7 q9 [9 T
        queue.data[queue.wrptr].data = data;
8 Q: D3 O+ N7 ?        queue.wrptr++;
3 l3 o/ e3 Z7 F% h$ c# T& Y        queue.wrptr&=QUEUE_LENGTH-1;
' V' A7 \! B4 u+ r) E+ d* \9 b2 g        if( queue.wrptr == queue.rdptr ) {
3 t4 X' \, {; d" w                DEBUGOUT( "queue overflow.\n" );
3 S/ d, T! {. k, T- [, ]        }9 W) B  V; O6 H1 s2 w3 ]5 _
}
' u; {- w6 w, L% y+ S0 P( i2 s7 Y
4 n2 G( c; z; m7 nBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ); o2 b2 c/ j  h5 h5 N
{0 X6 u0 e$ w$ N  T* {% H2 U
        if( queue.wrptr == queue.rdptr ) {
8 u  r6 _# B% T* g  n% |                return        FALSE;  ]% e$ U# D( ~, B
        }
3 n, [# w2 k6 |9 L/ f        if( queue.data[queue.rdptr].time <= writetime ) {
% a4 n" i5 s4 B                ret = queue.data[queue.rdptr];- S* N% ^8 C3 {- D8 s' Z. Q( q' I
                queue.rdptr++;
: E5 T. G; D/ z2 \+ z9 w( S* m                queue.rdptr&=QUEUE_LENGTH-1;- E5 t: d& G5 [- I
                return        TRUE;; o1 X+ I6 m' g8 b0 g8 T4 c
        }
7 u6 w9 u, z% C% r        return        FALSE;
- s6 Q0 B: j+ S* v7 H}. Y) Y* ~2 w, W: Z  u4 }
# A# ^7 W; m6 x# D
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ): |2 T# D  ?4 ]$ G) p0 d
{
( Y9 ]' q% z# u' U$ {8 H        exqueue.data[exqueue.wrptr].time = writetime;
9 R* ~) q9 M% U+ O        exqueue.data[exqueue.wrptr].addr = addr;
, G0 Y+ e1 r/ k: s( L        exqueue.data[exqueue.wrptr].data = data;# o/ X! q( A* Y7 q" R7 N- I/ {
        exqueue.wrptr++;
% C0 J/ l* H; H- z% j2 H        exqueue.wrptr&=QUEUE_LENGTH-1;
! }, Z3 I! Y. [        if( exqueue.wrptr == exqueue.rdptr ) {, V. I' G! |* k' u" z& M* I) a' [
                DEBUGOUT( "exqueue overflow.\n" );9 H( ]' W3 I3 \
        }% W! `/ C; ^3 }9 |7 @: [
}
' l& [3 R4 T7 {* x8 D% q* K4 e; q
$ b4 v; y& j0 e- v* U, HBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )1 Z5 |! e  ?. Q  B
{
" u1 K" x' u; B        if( exqueue.wrptr == exqueue.rdptr ) {
; K7 ]9 ^7 M5 e( ?% e                return        FALSE;$ @3 v; K8 c/ n. j3 ]  I" W- u- w
        }8 y, z, `) _+ ?: ~: J+ ^& ]
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! y2 J1 R0 }: i9 @                ret = exqueue.data[exqueue.rdptr];
$ @+ f! c/ X1 n7 \* m* `                exqueue.rdptr++;8 }: j! K# _) p& J8 X2 {9 F' _
                exqueue.rdptr&=QUEUE_LENGTH-1;
; L# ~* e' ~: o! I                return        TRUE;/ s! ~1 u! P  }3 }& w& {5 H
        }4 J5 \. J/ a- E- J
        return        FALSE;$ `) H9 c2 g& o- Q
}8 ?; M) s2 {5 Z, I0 B) u
- b- {9 a  h" }
void        APU::QueueClear()
7 u2 z% _+ X8 a( A{  g' s; ~" T8 C& l
        ZEROMEMORY( &queue, sizeof(queue) );
7 `  \, g) [/ J5 x+ C" c2 J        ZEROMEMORY( &exqueue, sizeof(exqueue) );' E' u% u6 k$ ~# L% X" c6 N
}
. ~; y5 n6 @" P7 g6 t8 f4 M4 d
" X' X2 F/ Y# Xvoid        APU::QueueFlush(): A- I3 m2 v; o6 F* S; D) ^
{5 G) J/ ]: o" `3 n  v
        while( queue.wrptr != queue.rdptr ) {
( ^4 S/ U+ m8 T' b& t                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
4 c' V% R. H5 \                queue.rdptr++;
% `0 e  [* j4 J2 _                queue.rdptr&=QUEUE_LENGTH-1;
( c% G" P8 w. m. \* y5 V        }1 z" y" e# f. o  M# w1 e

# c" x# C" G( K6 H" I  W" g        while( exqueue.wrptr != exqueue.rdptr ) {; t, R- _, a$ O+ J7 [6 X: h
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
; B; M2 L: d( d1 G4 Z' i                exqueue.rdptr++;
- d% e. Z$ X; {3 d1 [0 u                exqueue.rdptr&=QUEUE_LENGTH-1;" ^, @+ q# `( F: ]
        }
/ _1 s2 D1 `& K}" A9 I  C+ Z& i& J5 X1 j
4 H! R( W, X, }& a8 W
void        APU::SoundSetup()
* J- p- K5 u* n7 t% u* {{2 W$ R: |: S6 `; e4 V
        FLOAT        fClock = nes->nescfg->CpuClock;
1 M: X& W- A  T% x1 N8 w# l        INT        nRate = (INT)Config.sound.nRate;+ Z  y* _% a3 a6 F. P  ?0 v! Q9 X) ?
        internal.Setup( fClock, nRate );4 ]! {  a- A( u7 L/ m, p: w) S6 l' I- t
        vrc6.Setup( fClock, nRate );. n9 A4 Y+ C& j, c* Z' ~  N
        vrc7.Setup( fClock, nRate );
0 B% d5 I" w* Y' V( Y        mmc5.Setup( fClock, nRate );
$ Q2 h  X  p; k# ~+ d        fds.Setup ( fClock, nRate );
- K: C$ _2 x0 k& A1 I- h        n106.Setup( fClock, nRate );- F" y1 T1 U7 w" ]( z7 t
        fme7.Setup( fClock, nRate );) V, U4 X9 X) R6 X8 N, e5 _9 S
}6 ?3 ?' {# d+ r" {9 Z

% g" l9 F" h) X7 I+ yvoid        APU::Reset()" R1 h* z4 G- l7 W& c
{/ ^8 N& `* S6 H0 v  k' A
        ZEROMEMORY( &queue, sizeof(queue) );- A- C# v! C/ u; m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; C4 `4 f* ~. g% I' V1 P$ i
, ?" z: X8 ^' y% v        elapsed_time = 0;2 q5 t  w2 @) G' m/ g" A
3 f0 |9 E, ]0 K4 @  D, I
        FLOAT        fClock = nes->nescfg->CpuClock;
  w8 B3 }$ ]7 N6 b# Z# M        INT        nRate = (INT)Config.sound.nRate;
1 b. m% D( s/ @% E# z8 E        internal.Reset( fClock, nRate );3 j9 Q$ S$ G  p& \  m9 Q
        vrc6.Reset( fClock, nRate );
/ F1 _9 E, T' I( t: X' [        vrc7.Reset( fClock, nRate );
0 }1 q7 `2 P% |( n; H1 s$ ^        mmc5.Reset( fClock, nRate );# s" h  p5 ~* Y4 S6 P
        fds.Reset ( fClock, nRate );7 G2 q. n- E) r; |- t
        n106.Reset( fClock, nRate );
5 ~. r8 e6 G1 N/ E: f        fme7.Reset( fClock, nRate );
  q5 f( I  _& V! |
1 M4 M  |, L% o, |2 E/ {8 z        SoundSetup();
( N" k6 @) O% p, p}3 m; f, G1 f4 u8 y* q4 }- o/ z

( H) k% m* t$ f2 b" x: \void        APU::SelectExSound( BYTE data )
$ S* [( g1 N% B, s  i{
) P0 d+ _/ d% g. E5 _' A        exsound_select = data;" v! B/ T) o; s) r! ^
}: B! D) R2 P" `: C
) D- X& N, a+ t( d3 k/ E' m
BYTE        APU::Read( WORD addr )
" G$ Q8 U; g( a7 B8 r$ t{6 u  B' _2 _& v$ F
        return        internal.SyncRead( addr );6 {/ }. w  Q1 }1 G9 e6 F
}
' ^  @- f# j( B# W* e9 k2 s/ o# g( |5 U# [+ `$ J' `$ T, C
void        APU::Write( WORD addr, BYTE data )5 F$ D+ b" G& B. h# q
{- n3 S/ N: C* n+ C( r3 l
        // $4018偼VirtuaNES屌桳億乕僩! n( t6 `8 _; ?* B  N
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 _  n* K2 O" j8 M, U  k) i                internal.SyncWrite( addr, data );
3 B- c" s6 o8 P, t                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% v7 _5 J% M7 B" j
        }
" Q4 u+ h; y' P8 [}& z8 _3 H; j" m9 a2 S
5 S5 ?) d9 ~3 s/ c
BYTE        APU::ExRead( WORD addr ), n  z# x8 M' \; r+ e
{0 a" e7 R2 t2 |, J  b7 E9 G
BYTE        data = 0;5 C  o7 y& s( b) G

4 T4 k4 Z6 w( }  X0 Y) Z% p9 a; p        if( exsound_select & 0x10 ) {
' x8 z2 [5 B, x& y                if( addr == 0x4800 ) {8 N6 \, O0 J7 X, f' }
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
# ^8 C: V& c$ z( J" }/ v                }1 B4 [% U" e. m4 I" S
        }# t: g* x+ O. L5 o) s
        if( exsound_select & 0x04 ) {
4 I$ G* u( j& f3 l, {' E6 x                if( addr >= 0x4040 && addr < 0x4100 ) {
; p' p" A) v% _! c                        data = fds.SyncRead( addr );
( C6 j0 F/ f( |) A. b# T8 e                }; ~8 a7 L- {# \  T. T
        }
! L/ q9 @, L4 ^        if( exsound_select & 0x08 ) {
( r# }+ j/ q, I3 h6 W4 T1 [7 w                if( addr >= 0x5000 && addr <= 0x5015 ) {" D' j! R$ W1 `. ~' n8 C3 Y/ @3 n* W
                        data = mmc5.SyncRead( addr );3 @1 @! S. W& V4 G4 S  E6 g
                }
5 U# P' W+ J" O) s4 Y' B+ W/ D* h        }
+ M9 t& d. s4 j' z. c% j4 f# O* y: p) b7 G7 I4 j$ @3 G4 O: R, F9 o* x
        return        data;
7 i  n. o$ P& J/ w: m}8 F& h9 `! u8 N" p0 s5 N
* C# |; w% r1 @/ t& Q7 l
void        APU::ExWrite( WORD addr, BYTE data )" D4 }, M. k6 N3 T4 Y) X3 n4 l
{: E6 V/ U3 o2 N- Q8 x: e# J
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
+ j/ e- J1 @/ L6 Z7 w, ]& q9 ]. K/ H3 q6 c. |2 M
        if( exsound_select & 0x04 ) {
8 h, n( H; `& Q$ Q* _- T1 t                if( addr >= 0x4040 && addr < 0x4100 ) {8 [$ C6 ?* {. T: K% q2 o
                        fds.SyncWrite( addr, data );' X& j/ L7 i3 O3 H' W/ d: n
                }
' b, m: E- l; K& l5 f) T& b        }
& Q0 R" u8 ^: t0 C$ S. p& n6 m' [0 B9 ]: X9 U5 A& `$ f
        if( exsound_select & 0x08 ) {7 k; O8 ^! D9 d1 n4 H  n& b* r( C1 N
                if( addr >= 0x5000 && addr <= 0x5015 ) {! n9 E; J6 h1 C! u8 [
                        mmc5.SyncWrite( addr, data );0 F% J7 l: A6 P3 ]" C6 v; k& u# a
                }
2 \4 [, d$ J# Z* K" [: t" }        }
- V1 V* U9 x2 w* K0 n9 o# W6 w}
. k7 O# ], o8 r; X! [8 G" U7 e9 R1 d" N2 W1 x
void        APU::Sync()
: \: v1 E# V+ Z) J{
* T/ w8 D2 w, x: Y9 C; `}
' |4 q7 n7 a5 f3 j
; w  r1 i3 t$ H) v/ ~void        APU::SyncDPCM( INT cycles )
/ `+ f8 j% [( G{2 w# X& z/ g7 Q* s1 T
        internal.Sync( cycles );* ^  @/ v1 f( c4 J

; e( Y9 E9 Q8 |: G/ H6 d( z, @  {" M        if( exsound_select & 0x04 ) {
' P4 N- p& E0 b5 W" |0 k  T                fds.Sync( cycles );' F* u6 _( P, r, J& ^4 B4 v2 I& `
        }/ S8 }( O4 N) _. O# O
        if( exsound_select & 0x08 ) {
/ \4 p8 f$ `2 z3 v$ _( q                mmc5.Sync( cycles );
# F2 M" \2 L( D, ?* ]* @        }. ]' A" I7 p, f, q  e
}
& f9 h$ x/ i0 v5 m* D, K+ N  C; N" ?1 q5 u# g# K, [2 @
void        APU::WriteProcess( WORD addr, BYTE data )5 {% `- m1 S, X1 D/ X- n: k# D
{1 t1 \& {/ q) }" Q
        // $4018偼VirtuaNES屌桳億乕僩9 X8 T" b; R2 h4 t* x
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 m& N) g% \7 s& s7 z; {3 b                internal.Write( addr, data );/ {* M( B3 \0 r$ u. S. _
        }* m3 \# d! f& B$ ?/ |9 Y
}
  |- S; G2 w2 X  ^, I0 \/ A: r! z
void        APU::WriteExProcess( WORD addr, BYTE data )" l/ S& U- X( i/ e
{
" b* [- {3 X+ U& O0 l& t        if( exsound_select & 0x01 ) {! ?7 C! V6 C+ f' n' e
                vrc6.Write( addr, data );* g  d, Z# t$ Q
        }
  t- R. \+ i1 F: x& i        if( exsound_select & 0x02 ) {- V6 }0 r5 f# o0 H: v3 k0 _3 c) C
                vrc7.Write( addr, data );
) n7 F, O- B6 [3 _; }3 a3 j5 n$ c6 g( }        }7 ?4 Z. g# D; f$ [& D
        if( exsound_select & 0x04 ) {- X) W1 R1 ^, U- u% P6 I. R
                fds.Write( addr, data );; y" s' {/ a* `  O& r
        }; d# \1 J% ^! O6 ~
        if( exsound_select & 0x08 ) {; l0 y- [/ z+ K9 X" @
                mmc5.Write( addr, data );( C% d* A2 m4 W% S' `  ~$ m* R
        }
5 f9 S/ L9 r" w, I        if( exsound_select & 0x10 ) {* u* v7 c9 p; \4 v+ \
                if( addr == 0x0000 ) {8 v7 ]2 ?( u/ g6 @; r
                        BYTE        dummy = n106.Read( addr );
) b% H$ p! D- E, X                } else {
( Z; K" P" n. p( \2 `                        n106.Write( addr, data );
, I: S5 ]7 f# m& k" I6 ]- T                }
% q  B" I) f3 u8 O! Z: D" h        }
( P. W1 I" A! p/ t* ?, F3 J        if( exsound_select & 0x20 ) {2 Y$ [, z' o2 D. R8 h
                fme7.Write( addr, data );
2 {3 E% [3 ]# S" I$ j        }$ m1 B" d9 C' l& ?/ r
}
9 b' \% r& ~  ]- n, q& h8 u, M, B: r4 Y3 q9 m
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
% {+ N* j& D) I5 ^( u{
/ Q; A0 Z( r5 q9 Y- |INT        nBits = Config.sound.nBits;" k% Y& F* F$ @
DWORD        dwLength = dwSize / (nBits/8);
' R2 R! A; R& V6 y- GINT        output;
3 |2 o: E& f% y6 Z) i2 TQUEUEDATA q;
2 x% J) r+ J% U% fDWORD        writetime;
% X" }" h0 l- Z( G& l
3 Y2 U9 H8 X8 |0 O& `/ A6 bLPSHORT        pSoundBuf = m_SoundBuffer;
# M4 q" G  [' y# J3 P4 EINT        nCcount = 0;% f% I  k2 m; o9 ]

2 v5 q0 ~1 V6 H7 V! E' ZINT        nFilterType = Config.sound.nFilterType;5 f% g6 k2 H1 F0 ], A
+ p. E8 j/ l- N& V" y
        if( !Config.sound.bEnable ) {
# F0 p, D) S  p; b$ f                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
! X3 M* e1 X' \8 T2 O. |                return;) y" V% A$ d: v" V0 }: A! Q
        }
- c# Z# |" \% g5 H# q3 h
" \7 Q, s2 h5 D5 h' G4 y. {" V5 ~" N. q        // Volume setup
9 Q- I3 p  h- t  V, f  J        //  0:Master
2 Z) m" b2 W% H( }" i: I        //  1:Rectangle 15 y2 g1 V' u  K. R
        //  2:Rectangle 2! I7 Y4 P+ r5 a, Z; k* `
        //  3:Triangle
3 ?9 L; b: ~+ z        //  4:Noise
, {* e9 U) b$ L$ E% j" ^* q% Y        //  5:DPCM& \; t  M/ f0 E! \7 o4 k/ i% b& {
        //  6:VRC6# V) t3 D  W6 \/ e
        //  7:VRC7
# |: Z$ G3 i# x4 h" o$ v6 F        //  8:FDS1 v2 D$ k" O9 q) }8 E0 H
        //  9:MMC5, x' c" l0 u7 Q+ c/ J  v& w9 `+ X! |
        // 10:N106( b) s& H9 p# L$ U3 A7 s
        // 11:FME7' _2 y; m# v5 r8 ]- G3 o: N( o
        INT        vol[24];- Z' r+ d+ T8 j4 m, }/ }. O8 C! m
        BOOL*        bMute = m_bMute;
/ Y3 o+ M. d# f3 U        SHORT*        nVolume = Config.sound.nVolume;
1 A6 l1 r1 e) r5 v8 \
; F; {( J) x8 Q( I- X; v5 @1 i        INT        nMasterVolume = bMute[0]?nVolume[0]:0;+ m4 p& \( }! h; b' |5 X3 C( ]
+ s- A1 A' G6 C3 w
        // Internal' L) y' V4 o! W8 ]" @
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
  i+ E% O: M- N! h; S5 |! m; C9 E        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 z1 z" [2 y) Y; \6 @  ^& g- j        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 ^; t  z% D7 ~7 w  Z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;! k* g! r% ^3 M) g- @
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;1 V( }# J% }2 y- F. G' J

+ t  J+ |& w/ @! h9 p        // VRC6
: h6 \+ K/ b% v6 H/ l9 C        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& L+ z6 G0 g+ ^$ b/ U8 K8 [
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& A& q9 z: r$ k
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ I8 h( i4 S1 k" h% D+ I! S+ V

  k" f8 j! |2 l5 |4 @        // VRC7) T8 E8 L" B6 T
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ D& s& h9 A7 v6 K9 f
8 l0 M% q$ H. _# a. E
        // FDS
. R  u# x% s7 y  d' M        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
! Q$ _  T. V" I* p
5 ]3 T# M, u3 U1 w" W( }* x% D        // MMC5
& o1 z: x) ^. W: r        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 [: m$ p, u: e+ h  |2 I
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) i+ j% M- y' J; I0 T6 U
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, Y! r2 ]' G2 R* A4 p% M/ B

: x$ D0 r+ u$ r; m2 `  y  }' \: b        // N106
1 \, g% F- J( G; _: R3 y- \  S" W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 ]( Z+ V, s" J/ Y4 {        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  ^: Z: A6 U, K5 S+ o5 i0 J* v        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 v4 b! _3 h5 N8 m, n        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  x$ Y: M! F4 @$ x4 G- c( h# X
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& `. P( y% J0 v& N6 X) K        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 W: Q2 ]$ I) \. d$ T: x* U
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 W4 R* u  E5 J4 `# ~5 t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# v4 e( k8 p5 U5 l: s9 Z# T; F

; C+ n, E$ {& H+ w; D+ d: l        // FME7
6 H2 z$ s2 K* U- h7 l6 ^* ~5 k* g        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 `9 p  [, y7 @4 g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# f- x( `) x1 ^9 r5 x3 ?
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' ]9 g$ P$ l- Q: L' i

  J, j# j' A; h; x& x: g1 i//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;) v+ c3 Z$ j' x: f" @/ [+ J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 c: k8 D$ u& a: C! Z! z5 v- g5 g

& G6 t" I$ M4 q3 @* ^: ], K        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
, L: i& I' n! Y        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
2 Y; s+ D* t- O, D! {% `                QueueFlush();
9 d, L  T% }+ p. F) N# P  I4 U3 i        }) c. V: K7 j9 f$ N/ _' `
" Y, R4 }9 m/ ^' I
        while( dwLength-- ) {
2 i2 y8 ?0 r# E8 S' m                writetime = (DWORD)elapsed_time;
9 _+ {& c# n# e% c  S' p! D9 _1 ?6 W8 A* D; _
                while( GetQueue( writetime, q ) ) {* M. F; N, F4 ?8 h4 P4 i* [3 ~
                        WriteProcess( q.addr, q.data );" f+ `& h6 q% B" _
                }1 [4 y% [0 N' ]" M& x; M& R5 Q, \
* r8 j: K5 ~5 S' y
                while( GetExQueue( writetime, q ) ) {0 z) P# R: s5 P5 \
                        WriteExProcess( q.addr, q.data );9 S  ^' Y. a7 u9 c8 c( ?: x1 f
                }
) Q, H) S; R& q/ L* z
" G+ C! Q5 A2 k                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7( t7 f3 }6 \4 `
                output = 0;
/ v8 m: h+ b3 T! h! r                output += internal.Process( 0 )*vol[0];8 Y) k6 m! B% h( ^& e' v  i
                output += internal.Process( 1 )*vol[1];
. e$ `6 s; u1 X- e                output += internal.Process( 2 )*vol[2];9 u* `# U  m6 Q
                output += internal.Process( 3 )*vol[3];" g* \& u2 D) n# Z0 T1 _0 u
                output += internal.Process( 4 )*vol[4];( n& d0 A7 `( V3 M" M0 a0 c
5 I: s4 v. @/ u8 `; \& ?
                if( exsound_select & 0x01 ) {$ K! s! P: Z9 O! a+ u. c) h
                        output += vrc6.Process( 0 )*vol[5];5 b2 w0 I2 {3 O! {
                        output += vrc6.Process( 1 )*vol[6];3 Q, o" Y8 A' {$ `8 _8 v# S2 s0 I
                        output += vrc6.Process( 2 )*vol[7];
; l+ s; Y  s% u                }# ~6 r. |+ z/ k6 Y# Y, ^- R
                if( exsound_select & 0x02 ) {
% R! y6 i3 g" T                        output += vrc7.Process( 0 )*vol[8];8 q7 v4 t8 v, Q) W! h
                }
6 S6 E  u2 o) M3 Z; K6 o                if( exsound_select & 0x04 ) {
. L6 N' d1 W; T! Q                        output += fds.Process( 0 )*vol[9];
* P$ x# L! z! t4 r% e! {  D' a  P                }7 e% G) ^) i1 ]3 V' G+ s7 Y* g
                if( exsound_select & 0x08 ) {
* z$ l0 n6 k5 Y0 H, Z9 O# W, l( d3 H                        output += mmc5.Process( 0 )*vol[10];! y, b( M9 {9 W. |# e
                        output += mmc5.Process( 1 )*vol[11];
. X7 b( Z: X; E" ?( i/ H                        output += mmc5.Process( 2 )*vol[12];: g0 J+ c7 ]# Z: o8 f
                }
6 y: m' M- l: Q' v0 P% F+ c6 ]                if( exsound_select & 0x10 ) {
1 T- v; W0 v0 W8 o! e- [                        output += n106.Process( 0 )*vol[13];
2 v/ A3 F% m& i+ F! m) T2 X) x2 d9 i                        output += n106.Process( 1 )*vol[14];
5 v/ |3 Z% r  g7 Q6 {                        output += n106.Process( 2 )*vol[15];
. T7 I. K, \  q$ u- L- w                        output += n106.Process( 3 )*vol[16];& j( Z* Y6 ^2 S
                        output += n106.Process( 4 )*vol[17];
- W5 J& ?  G) E; |                        output += n106.Process( 5 )*vol[18];
, k1 r0 \+ r1 z- U: C7 |                        output += n106.Process( 6 )*vol[19];; v8 C4 V& a$ k  H, W
                        output += n106.Process( 7 )*vol[20];2 a  Z# \# L' b: c
                }4 i3 R( P9 h! c3 X6 N3 o" K
                if( exsound_select & 0x20 ) {2 ^" L% i3 z; _' W! M1 e
                        fme7.Process( 3 );        // Envelope & Noise( Y5 V: {% U# n5 c) i+ l. M; O. j
                        output += fme7.Process( 0 )*vol[21];
. U7 G  M, W8 [                        output += fme7.Process( 1 )*vol[22];
% G( i, D* X3 O( R  v                        output += fme7.Process( 2 )*vol[23];
5 x, j" g; g$ D) d5 ^                }6 h$ C5 P3 M# S" L- O3 H& o
2 s+ H; b; d- Y; Q. `  _9 A
                output >>= 8;
8 y! f+ d: H' R6 L2 W0 x5 |* u: l& S0 n
                if( nFilterType == 1 ) {% s# ^( z4 D& A
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, w( N. [( z/ _1 Z                        output = (lowpass_filter[0]+output)/2;: [! @) [  \5 r$ N, Y
                        lowpass_filter[0] = output;/ B$ {8 z% @4 m; O* D% w; c
                } else if( nFilterType == 2 ) {# Z3 ?/ H! B0 W3 n
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 u! T% a5 y2 p  q) `                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
* s6 \  d" v+ e                        lowpass_filter[1] = lowpass_filter[0];
& L9 o! E. f, g, r# d: U# {/ w& n) X                        lowpass_filter[0] = output;" }& ?8 D7 B. f0 Z# ]6 |
                } else if( nFilterType == 3 ) {7 W+ i' C; _$ h- ~- @+ k' X! a
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)" J3 e7 H% h0 X/ C# G
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
( Q" R  ]0 \2 e: t                        lowpass_filter[2] = lowpass_filter[1];3 U7 w/ C8 c) ?! ]7 `
                        lowpass_filter[1] = lowpass_filter[0];- y) r* _7 g9 P$ Z) M# y* q
                        lowpass_filter[0] = output;
4 R# v; r7 ?: M$ i6 V                } else if( nFilterType == 4 ) {
1 P; }! ~. L# Z                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- a2 E8 i3 x! ^3 ^  Z: D                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;* K$ y: e3 o9 N/ j7 ?+ ]
                        lowpass_filter[1] = lowpass_filter[0];
+ ^3 K. ^& f9 {* {' D3 f  v                        lowpass_filter[0] = output;. ?  [1 z3 H) x/ O4 E; P9 k
                }
8 d8 \3 [% ~  z; I7 R8 W0 ^; b: e0 m; ~5 |% j
#if        00 G8 {  n  `0 w3 a5 }9 U6 N
                // DC惉暘偺僇僢僩, z- o5 i9 v2 ?: Z# C8 ^+ W
                {$ R! N6 g$ p6 X! {) M" m4 W7 q
                static double ave = 0.0, max=0.0, min=0.0;1 F) l- ^( a9 {( G
                double delta;4 w9 ^& V+ ]7 u' d
                delta = (max-min)/32768.0;3 n8 U9 ^4 q" t  @( p- Q9 c- G- U
                max -= delta;" F) q7 {2 K. U. j
                min += delta;' b8 @# j; s- G/ t: s; d, T8 t
                if( output > max ) max = output;: T5 m0 s4 l. ]
                if( output < min ) min = output;
# F0 i, I1 k/ U. Z                ave -= ave/1024.0;3 b- [9 ~3 Q* w% l
                ave += (max+min)/2048.0;6 f0 a# B( r0 z( ]  s5 d% K/ S. @
                output -= (INT)ave;  v1 X4 F2 }' @  Y4 l2 _* |# Y
                }/ o' m: E( @0 l( ]
#endif
, g9 r, K, R+ H2 P8 [0 g#if        1
1 M6 K1 Q  ~9 L: p. i' j5 y! I                // DC惉暘偺僇僢僩(HPF TEST)5 B; y7 f  E9 O( w1 M9 }  z5 M
                {
8 B; V& E+ ^% X# K% \: r4 W//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- Y) ?, \5 o/ g# O7 Y. O3 p1 ^- c
                static        double        cutofftemp = (2.0*3.141592653579*40.0);" r8 y3 f, g$ x7 [& J7 j
                double        cutoff = cutofftemp/(double)Config.sound.nRate;( t9 S9 w% K# _1 T* P& ]- R
                static        double        tmp = 0.0;# A, X, D' ~3 w8 w6 Q
                double        in, out;0 O4 }9 m. J, G6 P7 @( v
) Y9 c7 y8 _' l7 L
                in = (double)output;
2 i) N2 N" C8 Y8 f; l  L  ?                out = (in - tmp);
0 v$ g' d! A! W% f$ D- {7 L. q9 j* s                tmp = tmp + cutoff * out;
: v9 J$ A' ]1 ^9 V$ X  I2 ]+ f3 C4 M5 T. V6 i
                output = (INT)out;" y( X8 a7 k) L  U. x- ^) n
                }
: W  e$ W. V0 f) W( G#endif) {/ j+ O8 e$ x& g
#if        0% [& T! K2 q& ?$ M
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
1 l# J5 ]* ^# @# q) q6 h$ D* R9 W                {- ^; i! o$ l5 B7 W  W
                INT        diff = abs(output-last_data);4 P$ s5 w% k! c) X
                if( diff > 0x4000 ) {+ `' B2 s, t2 k# F
                        output /= 4;, }: w1 K. ~1 ~' H- g
                } else
& I1 _7 g' p6 t2 ], v9 l5 S                if( diff > 0x3000 ) {
3 ]7 V; m* _% B6 H$ z  b" |; M                        output /= 3;
0 a% Z$ O% v: |  p$ J, x# G                } else: x7 t& \- s9 K+ a
                if( diff > 0x2000 ) {
; l7 n( Q8 q/ Y, `3 v' f                        output /= 2;2 ]+ ]# A+ m/ y0 A
                }
. K& s! ]* P  X2 M, m                last_data = output;
. A, K! `5 h2 o" \  d, {                }
/ s) ^/ U8 u: s  W3 M#endif
  n6 {2 p1 W! n, ?* q4 d5 i                // Limit
- s& G3 d, [5 F+ k& A2 |8 i* E                if( output > 0x7FFF ) {
) I: P3 x( ~$ X4 U+ g) L& J0 I                        output = 0x7FFF;1 N1 }) c+ K' }! T
                } else if( output < -0x8000 ) {) z9 p0 }% [( U4 `' X& K% m9 N1 L9 }4 {
                        output = -0x8000;
0 \" B8 W8 H& l5 d                }
2 @  R  l7 i  e. }- k6 j/ r; t) x5 E) ~/ C" h0 ^' R3 A, c
                if( nBits != 8 ) {
7 y5 L! e4 P5 [% W0 c  u( u                        *(SHORT*)lpBuffer = (SHORT)output;2 J- ~; |+ T9 f" [+ {% n9 g# Q) r" E
                        lpBuffer += sizeof(SHORT);& n  V0 D1 x1 G% X, g
                } else {
2 X6 {: v: C# @: [                        *lpBuffer++ = (output>>8)^0x80;4 _7 a# b$ C  {- _& o" A, g
                }/ @. |" d( w$ g! M2 T1 s9 }

& k- Y2 c. {* O$ A* t8 y2 P                if( nCcount < 0x0100 )
3 z/ B- `' _# B3 g1 k2 M                        pSoundBuf[nCcount++] = (SHORT)output;
3 F5 @. u. u4 k' R5 T7 h: A7 c+ V
: {: R  M2 t/ K* T: ^1 p# i7 \//                elapsedtime += cycle_rate;
) a/ b0 _+ {! ^6 o6 L  e# X                elapsed_time += cycle_rate;
$ [4 n$ z9 y; }) q" y# i1 Y        }
: v% l. n+ B! S7 U6 U
2 B, i* g: }* B. {5 O0 N2 y- H#if        1
8 w# Y4 B- R3 P8 `        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 \* o) \, X1 z3 J                elapsed_time = nes->cpu->GetTotalCycles();# K  s8 R8 `5 C$ @( d8 S" M$ c
        }
' D; X9 P% e( N9 I; Y% D7 E* L        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 A# l5 B5 u; V/ n2 |2 r6 Z9 z8 |                elapsed_time = nes->cpu->GetTotalCycles();
9 ~- u8 g6 `3 c8 S' u        }# @5 i$ a6 h: J' m
#else& a7 A; V$ h' L/ E$ b
        elapsed_time = nes->cpu->GetTotalCycles();
3 G0 i0 j' z' G" r#endif
+ E- Q) k1 g& K& }2 n}0 ]5 W. u5 b9 J. U
# ?/ z. P0 z  {! |5 {, A
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 |  l- b0 E, D7 k6 V! s% p: jINT        APU::GetChannelFrequency( INT no )# ~9 i* o# G- G( I1 t
{
' J: A1 C" m& c& t7 \1 {        if( !m_bMute[0] )5 }; w% E* R) S; M' b1 r; c! F
                return        0;
; t" K' y7 p" m. M- B" t2 V# T6 N
        // Internal$ A. r9 p" z- T# M4 ^6 Q) K
        if( no < 5 ) {; U4 y5 K" v  w0 O0 G
                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ D; ~0 l+ V/ L7 C4 T  N
        }& l1 j8 \2 b6 ]
        // VRC6
. ]9 c5 j8 }- z& e# C1 I& E        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
) I9 e  R5 @" p& b, U                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% ~$ B" p4 t# }( S' K, i
        }
1 \/ o6 A: c" g+ Y! z# r2 S        // FDS
9 I6 ^1 a5 i7 h1 U; Y( f6 b: v        if( (exsound_select & 0x04) && no == 0x300 ) {
; j- Z. K; F" C2 a) V% W4 {                return        m_bMute[6]?fds.GetFreq( 0 ):0;& j% \* b0 A; Y, s& F6 I3 M& M; u
        }7 `5 p  ~; a* ?" _. Y# g
        // MMC5
8 t! S- q) _# a: m" H        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 j! k% H9 [0 M1 t6 r) _
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
  H' o0 ?! R% `+ `6 L9 n        }
; K7 p) p6 k2 [4 J' O1 w$ S5 u        // N106
; [0 z" {  {! u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: }0 G. F0 `0 I# h9 L
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;( _- |4 c/ N' _" ~
        }9 _3 S9 P7 C" y
        // FME7
/ H" D5 g7 C7 f9 _( {        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
5 R9 G- o" y* U* {8 h2 x                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) w3 i: s  k/ _
        }0 ]( v! w* V9 x* N& ^6 x2 Q. k
        // VRC7( n1 R- V! u6 N0 w4 J
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {3 |( U  g% T% ]" ~
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;5 v" x0 [9 z% Y
        }
3 ]3 y, E. i1 u! b" U0 }        return        0;9 Q" L. X6 A2 M' [& w
}
% n/ v/ e! i1 a9 ]6 m
! ]" h+ b, B/ U! }// State Save/Load7 T1 ^4 r; ~" x# y" W& P# j
void        APU::SaveState( LPBYTE p )
. f8 ?) b* {5 _" S6 q" ]" `{5 C: V& D7 R/ |: N
#ifdef        _DEBUG. S! [6 E7 ?/ s& {& {+ W
LPBYTE        pold = p;: H. W1 q2 \6 O  ]  U( Y
#endif
# k& o! \& S9 x3 S2 J( E" L5 Q* ]8 I  U1 h% D5 ^% M
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞9 ^7 E3 X& z7 U1 s6 t5 H
        QueueFlush();. s( Y; J  `- U+ {5 s

. P: W. g$ [7 T( r        internal.SaveState( p );
. N$ U7 d1 g3 u; |8 V5 S: @, f        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( c6 t/ s+ E; e0 [0 ^1 g' k

& c. i8 f8 P  a7 d9 ~- _        // VRC6
: p, J) u! q, M8 J: O        if( exsound_select & 0x01 ) {  r. z9 Q' ~# J' @, h
                vrc6.SaveState( p );. e8 E1 ^: ?6 ]6 ^3 ~+ K! r) G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
8 L: r; s. P9 E        }
1 ]! o. F' Y, q. g/ I        // VRC7 (not support)1 o' _- K2 r9 x& w
        if( exsound_select & 0x02 ) {& ]* W1 x! f& a
                vrc7.SaveState( p );  y/ z' L% y$ [# g% _
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* m/ ^4 C# c- s% A$ \* f        }7 F& ?5 H/ y# z6 Q9 v& p9 Y
        // FDS
+ b7 a5 Y) o/ f" G# ?! J        if( exsound_select & 0x04 ) {7 G3 F3 R) ~+ [6 D! z% Q- v
                fds.SaveState( p );
* v3 }; ~! A, M+ v# }( c% b                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ P( ?7 C1 s+ r/ M0 X
        }! g/ R  m8 b$ L* q" }2 v* k
        // MMC5
$ v3 L$ C/ u9 y3 M  ?5 v        if( exsound_select & 0x08 ) {; t2 a8 ^$ _; F" f% q1 }# ^, Y
                mmc5.SaveState( p );. E: O2 z$ c# `) |& P9 W# R, y, t
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% }2 s& N, c- [% C: d/ p+ A
        }
* m8 _' v) U9 v- a. F        // N106
6 ?7 x0 B) K! @5 ^        if( exsound_select & 0x10 ) {6 o: \0 I( l+ \3 ?: q" L6 \1 H
                n106.SaveState( p );* o) w7 k. S- L! r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ V6 ^9 u8 H7 l! {% c* t+ p- N( I
        }
7 `# r) x) b" x+ `        // FME71 \+ a2 v( h' [& F
        if( exsound_select & 0x20 ) {
, {% B' c& w' P3 c$ x7 X/ F                fme7.SaveState( p );
! D0 h. H9 x) a2 U                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 C/ z  a3 a0 ~. \3 H, N% K
        }3 p8 K5 o8 p. U# K1 }
: e( K7 X+ t1 E& R# P( _/ P
#ifdef        _DEBUG
; P# `' h, h3 G% f+ |6 u: H! j) @/ XDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
: {# U, R! ?# }5 |- M, K8 \) h( O#endif
% b- g: D# r1 b& D, a# }: e}
% \& _1 w; f5 n- M* k0 w3 R6 K) g1 r1 N7 C$ z/ V
void        APU::LoadState( LPBYTE p )
+ l: b% g% n! ]4 t{2 V! O0 v* t% U5 n1 b/ ]
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 [8 {! C" K  E3 N! Y, b        QueueClear();
% r4 W# i1 `. L+ [6 V, Z
  W6 I$ v5 l( t; v        internal.LoadState( p );
. u. R! L% f) C6 R% q4 P) b        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) ?! W" N9 C$ h+ r1 Y$ o- H
" _6 L2 q/ i! X% F- m        // VRC6
, i9 Q0 k2 w5 L        if( exsound_select & 0x01 ) {
' r5 |+ }$ f5 ]                vrc6.LoadState( p );
  r9 _) }. ~1 x+ G                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! I% ^6 }8 c; _, x9 ?        }; K5 m$ x1 c) E% C
        // VRC7 (not support)
6 E% ]$ ?, \* L/ V/ m        if( exsound_select & 0x02 ) {
( c+ d: `0 Z+ d                vrc7.LoadState( p );& C$ u9 @. t6 l! H9 j" B+ W
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding8 M; k- p( E' P4 W+ |, y
        }3 [7 H+ b2 `5 f4 q2 u- i! o
        // FDS
2 ~+ [9 N2 h$ e# h        if( exsound_select & 0x04 ) {5 T7 [5 s$ M  G# {. q& ]  A
                fds.LoadState( p );
7 ]; G2 s" _# J2 T4 ]                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 k# d9 d" X% O3 R6 v+ m
        }
; z5 S! k* T" X# M- w        // MMC5
- G$ Y- B6 T& T2 H8 a  M1 v8 q& ]: N        if( exsound_select & 0x08 ) {" J" N9 K* S' R
                mmc5.LoadState( p );  K$ m. B, O7 C
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% k( x8 k1 \& I/ Q9 U
        }
/ m: M, t2 z+ e2 p+ A7 y% K        // N106# m8 f' _4 W3 C5 ]# M8 p+ W, o1 s
        if( exsound_select & 0x10 ) {
) T1 P5 o1 b# H8 z                n106.LoadState( p );/ j" {" F: G, s2 r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; l1 s) I: E  e  s1 c
        }9 P6 f9 y  o' \% |$ F% H, R
        // FME7
% d3 r! E2 X' D1 ~4 {        if( exsound_select & 0x20 ) {1 {- c) f7 Q% @
                fme7.LoadState( p );
  S8 s7 f$ z/ b9 j                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) E" F" a; X4 T" E- d6 {        }' W& |! O7 H5 D/ h
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
$ H5 c+ I! R) [' n, f9 L8 i可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。+ ]& q% ?; {. z$ z* u* C
感激不尽~~

" C# _1 j& \/ |$ q恩 我對模擬器不是很有研究,
8 ?& |- J$ a" x$ }$ p( t/ i雖然要了解源碼內容,可能不是很困難,
7 I# s; S! ?5 r不過還是要花時間,個人目前蠻忙碌的。
; o& h5 ?7 }1 p# `( ?% q
5 u/ K. u* y3 ?$ {( s2 @, P* N給你一個朋友的MSN,你可以跟他討論看看,
" L: c# Q& |1 ]/ ^) E% h他本身是程式設計師,也對FC模擬器很有興趣。6 q, [- d+ y5 l; a- D# x: |

4 E& {2 N) P& E0 F; LMSN我就PM到你的信箱了。
3 d) [- X2 w) i6 M7 J
5 L' B7 {9 b% c. I6 ~+ x: L希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
& Z3 N: M2 M9 |# K" ?' D8 t呵…… 谢过团长大人~~
+ Y. H$ X& K9 T* g2 m

0 S. O" E: W. L5 d7 [  H$ U哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 n$ i! j" B: X: ^  S0 g5 z! N
团长的朋友都是神,那团长就是神的boss。
8 Z1 a. P: z% `" ]5 M$ K8 a3 |
哈 不敢當,我只是個平凡人,0 {" H! x$ c/ x$ W
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ X! q$ j8 f( W4 `* @9 i" j; E4 TZYH0 U4 Y) m% D/ L5 L& w
QQ:414734306
4 ?& F7 \0 b! f2 Z) L. Q0 E8 RMail:zyh-01@126.com
0 z) b4 R' d. E# c# @; Z- w' d+ o; q" @2 R) T8 q3 @
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 , A& I% j5 [: G# U' R; d8 h  V
再次对团长大人和悠悠哥的无私帮助表示感谢~~
# B7 |5 P7 s, |& ^
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-12 05:37 , Processed in 1.136719 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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