EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ O+ c2 C# z6 \  z! m! C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' q$ ^' L' G+ n( Y  G1 b9 U这里有相应的模拟器源码,就当送给大侠了~~
# J, @" ]2 p! J) O* p# H7 vhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- K9 }  H; _2 q能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; v) J% Q, y; h0 Y9 a  C2 P& z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& P+ w$ k9 f* ]6 A/ X+ T这里有相应的模拟器源码,就当送给大侠 ...

+ c+ H% L  }" I# M8 z聲音部分(Audoi Process Unit = APU):
) v- H! Y7 s- ~.\NES\APU.cpp' Z+ k; J8 W/ [# T8 _
.\NES\APU.h
# N% R, n) ^3 @( ^7 t1 z1 u& ]0 A
( R5 N7 ^5 I! `0 A
影像處理部份(Picture Processing Unit = PPU):
: e' \6 }! o+ U3 |.\NES\PPU.cpp
$ |% p( u  ]1 E" E& }.\NES\PPU.h
7 A& I8 P5 r* R# Q; M  j0 S! ?, a8 h( t2 `
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
2 T) |% x) n3 W& A; x9 G5 R% ~* i5 ^感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
% I4 b5 }$ P2 t; `0 O# d(由于很多专用术语和算法机理都不明白,所以看不大懂……)
8 T5 t3 F9 @% L  D/ b//////////////////////////////////////////////////////////////////////////
( v  c  z: t7 w/ W//                                                                      //
6 U6 @% _' M, w" a2 ]//      NES APU core                                                    //$ K2 W* c# \( ^# W- ]% ?
//                                                           Norix      //4 V% ?: y: X* }( L6 y
//                                               written     2002/06/27 //
  H; Y0 @3 V4 ?/ z9 C  O7 }//                                               last modify ----/--/-- //+ r1 {1 f1 R! O9 c7 V0 f. d5 |5 F! R
//////////////////////////////////////////////////////////////////////////6 J$ w, W* w8 q/ B: R# y* g
#include "DebugOut.h"
5 u2 z* W- A( p% Z#include "App.h"; k+ a- V: y# Z4 G1 @' B
#include "Config.h"
' X9 r  e5 m! k7 M& u1 H0 w9 W8 `3 J7 g4 W8 t
#include "nes.h"
: I- U0 ^& C* f4 c# P2 r/ A#include "mmu.h") ^% f, h1 T. T
#include "cpu.h"
* ]. I7 G: u% S8 m#include "ppu.h"
! l' v) q9 j  x2 W! l#include "rom.h"
; ]7 L' \% k" u0 W& B* l# z#include "apu.h"
5 P$ t! L. u6 Z. U5 X8 R3 J0 e% B) U/ n% G' Q
// Volume adjust9 N" R# z+ s4 V+ j
// Internal sounds
8 n! l+ \! `: N#define        RECTANGLE_VOL        (0x0F0)+ n, u- S; j7 M5 q5 u1 n. u& t
#define        TRIANGLE_VOL        (0x130)' O  a: ~. f% ]  j- _( t# [  m# n
#define        NOISE_VOL        (0x0C0)0 I6 ~" ~: X- @: t3 t1 t. k" o
#define        DPCM_VOL        (0x0F0)
1 V3 `1 |: ]' C// Extra sounds
& G9 l& y4 b: U9 d#define        VRC6_VOL        (0x0F0): g/ |  M* i! d1 s& p: i
#define        VRC7_VOL        (0x130)
: Z7 d9 ]: t$ f! h  n#define        FDS_VOL                (0x0F0)& s5 t4 [" r! j% y. Z  A
#define        MMC5_VOL        (0x0F0)5 @5 l5 W2 @2 @) K: z
#define        N106_VOL        (0x088)
( v  Z1 a* e' v5 @" E  B9 g#define        FME7_VOL        (0x130)( K. q+ e9 z0 \* m
1 x% H" y7 e: U
APU::APU( NES* parent )
+ i: B# s9 h) r/ W  ?9 X) X{: V$ N) G% k8 c$ V8 @
        exsound_select = 0;' [' i3 _0 \* f* ?5 k3 E1 z
+ i( z2 V; F5 _7 I7 A! q
        nes = parent;
8 U4 P3 ]5 N. [0 h, j. f( P) ^        internal.SetParent( parent );
" c7 G3 B' {1 d! z9 e* G5 ]- V5 s4 x* F8 ]. k
        last_data = last_diff = 0;& e6 W, y5 F! E' i0 I9 _2 p; Z: U, D

' N: S3 \, U& p, n& l: A& z        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) n. ^; R' F- y& c1 {, k9 B

3 M4 A. n2 n5 N% ~& A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );* E8 o, f" y0 y+ M5 x3 z% g
        ZEROMEMORY( &queue, sizeof(queue) );
, q. T0 G$ c9 }$ R9 I0 J9 B% M        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 v3 s  k1 E  B* t) n( z

& @  m- i* p9 }* C% l, c4 }& ~        for( INT i = 0; i < 16; i++ ) {& e( P* ]0 n* u7 j8 u: O
                m_bMute = TRUE;
3 K7 H' |; ~$ B# f        }# N$ A/ j3 s! \& V/ ]
}8 |1 t- Z/ E( f' ?

) @" \, [" [- n3 G% w* O) M* tAPU::~APU()' g1 T. `- r" p$ T: h
{
) Z* }% G( U8 l) F7 o}
" e; |2 u0 {9 h1 m4 }  N. p( H  U. L/ @$ R
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )6 F' V! z8 t6 ]$ l0 d
{
8 Q8 P& f. u" y1 K: V( {        queue.data[queue.wrptr].time = writetime;
2 J" A/ T, A3 C1 z        queue.data[queue.wrptr].addr = addr;0 y9 M4 }: J' T5 ]
        queue.data[queue.wrptr].data = data;% a* _, F  ?; f  I' z
        queue.wrptr++;6 ?7 Q6 K( @, ^* }9 }# S
        queue.wrptr&=QUEUE_LENGTH-1;( [* Y5 H3 \# G* w* J; n: Z6 {
        if( queue.wrptr == queue.rdptr ) {# s" t" q( v9 P
                DEBUGOUT( "queue overflow.\n" );
' o) w: p$ E% j; T4 I        }& `% e/ @3 K* x) W8 ^
}
+ {8 T! z, A: S2 i4 ~4 `8 s. z. T5 k0 E, N7 \
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )3 T4 g) Q- z2 r) d+ m$ N
{9 |* e. I; e' |5 H. H! a/ w- \0 L
        if( queue.wrptr == queue.rdptr ) {
6 O! v4 G+ @8 A7 _# l& g                return        FALSE;
; p) y) g4 \) [7 O$ Y* `( b% h        }# O4 x! Q. w+ e4 H
        if( queue.data[queue.rdptr].time <= writetime ) {
* R+ x" R% p6 F# K                ret = queue.data[queue.rdptr];/ c% h6 e% j# {( F8 V
                queue.rdptr++;
0 z  d) l( P, [% \                queue.rdptr&=QUEUE_LENGTH-1;+ V6 [0 h. m) Q, H7 b8 v, W
                return        TRUE;
. J% x/ n8 l& p7 p# P; W* d4 s        }( r- e' G: _$ `5 i: G
        return        FALSE;7 l( G; T7 K! ]3 w  e) L
}9 O( q  p5 S/ M& a+ s7 }3 U7 N
" r& d' j6 _% s
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
# r, |& G& W7 ^  H7 L{4 [7 t% X" Q% V6 l) D0 A4 i5 W
        exqueue.data[exqueue.wrptr].time = writetime;
* V3 N! _  ^" b( ]& Z, e        exqueue.data[exqueue.wrptr].addr = addr;3 n- ~9 U  E3 U6 I* h! y% x
        exqueue.data[exqueue.wrptr].data = data;* d. s4 F- h2 v
        exqueue.wrptr++;/ `% }( L6 U' v# k' y: f
        exqueue.wrptr&=QUEUE_LENGTH-1;
' D" ?, W: O, r0 v% e9 k0 N        if( exqueue.wrptr == exqueue.rdptr ) {; y1 A/ b$ J( j: s
                DEBUGOUT( "exqueue overflow.\n" );3 }* e1 y# ^5 s, r
        }
7 a% C$ u- a; c6 t7 W; o}
4 J, T( h. T7 x( d8 M2 l% ^2 s# _$ A( B( E
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
+ h- W$ V4 B4 f0 w+ |% {. s{0 W( X/ h, l; `' a
        if( exqueue.wrptr == exqueue.rdptr ) {, ]$ B1 s. ?; Q2 Y4 L% _5 k
                return        FALSE;% q; `; h( p4 \2 L0 C% [
        }& ~2 @4 p) _$ _" I' l
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
) i1 R# s( A% `/ u) Z* t                ret = exqueue.data[exqueue.rdptr];
7 \( Z. H3 a# k& o5 z2 Z                exqueue.rdptr++;
  D7 e; L2 o; Q: l4 [& r                exqueue.rdptr&=QUEUE_LENGTH-1;
0 q6 s6 P3 Z7 m* q                return        TRUE;) }8 }4 L. H" D" |
        }
7 |- O& }- y$ Q) e4 G, ^7 Z* }! U        return        FALSE;! p$ m5 h6 ^+ [4 e
}8 ~) ~- \4 T. u  j# n  t1 A& T

# t( H# E; {- F# p' L5 ?# yvoid        APU::QueueClear()
, I6 V3 _: R# q4 o' o/ V/ {0 s{
( K" J7 b3 e+ Z9 w$ L, B( K0 r        ZEROMEMORY( &queue, sizeof(queue) );
2 c5 }9 `9 t9 y4 P7 v& X/ o) k        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, M2 t6 C0 V) ]5 J}
$ }$ I/ }2 q7 Q
5 v) b" q8 v+ B  W  ~/ j* x) Kvoid        APU::QueueFlush()) n' j8 g) _3 C( B' `4 {1 R! d
{
& g3 y- q& d5 s5 J        while( queue.wrptr != queue.rdptr ) {% g( {1 k5 A! j5 J
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ @$ K# H6 n' a. H                queue.rdptr++;( D# Y" W5 O9 ?; o! T" N' `
                queue.rdptr&=QUEUE_LENGTH-1;# f' W/ Z7 F( H. b0 o
        }& S. b  }" I2 I

( }0 M. Z/ I2 U        while( exqueue.wrptr != exqueue.rdptr ) {
4 u" i6 u  h0 L5 M# K+ L                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 ]* y% e" t$ C8 g$ s9 ~
                exqueue.rdptr++;. ?' O) K+ x3 n
                exqueue.rdptr&=QUEUE_LENGTH-1;: F5 d" K+ n' q& J3 Z
        }
4 i1 q# q3 ?  U3 v' I}
$ K2 B% N0 l: H1 i0 \2 ], F, m8 u9 B# `( W7 k( l) }# E
void        APU::SoundSetup()# ]. r# {) i( c( u6 T
{  I. h! T! |5 v! U2 ]4 b- {
        FLOAT        fClock = nes->nescfg->CpuClock;; \$ }, e5 l7 D. s; t
        INT        nRate = (INT)Config.sound.nRate;6 A+ l& O  d, W9 w/ S
        internal.Setup( fClock, nRate );
$ s' @3 }# v% ?6 z4 l        vrc6.Setup( fClock, nRate );: K+ z# h3 ], @% K
        vrc7.Setup( fClock, nRate );/ l" k1 n5 P; L$ G
        mmc5.Setup( fClock, nRate );
' K, l8 y) G7 L  z& k) A        fds.Setup ( fClock, nRate );
- S% p* n5 q3 l# t8 Y. e* Y8 t        n106.Setup( fClock, nRate );, s2 M+ F3 y! P
        fme7.Setup( fClock, nRate );
) ~" h$ C- b" `( ?5 y}
: x- E' {9 w* c  t* v0 @4 z8 `
5 e. }. T$ M/ ?( qvoid        APU::Reset()# X) v: G0 c: B. e. ~! p5 J
{
$ u* u3 f" ^3 A7 \        ZEROMEMORY( &queue, sizeof(queue) );9 c" M! \' y- k3 v) u
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- p  d: R# G: Z' G, z7 e. D
! T. r4 \7 d  V: {1 L  h+ o
        elapsed_time = 0;
: x: {: E& X/ o% B6 m
9 D) e  m) _. Y& z8 S; ~        FLOAT        fClock = nes->nescfg->CpuClock;# Z% E. _5 [4 Y9 r  ~4 c" c* e
        INT        nRate = (INT)Config.sound.nRate;8 d% ^( y0 a8 i8 m
        internal.Reset( fClock, nRate );8 c* C+ ^( i- B2 r& j% O5 b
        vrc6.Reset( fClock, nRate );1 v6 Z9 q+ T! U2 h; \5 f
        vrc7.Reset( fClock, nRate );) O; _& F0 O8 r& k* W  E
        mmc5.Reset( fClock, nRate );
% S; A3 K7 f5 B        fds.Reset ( fClock, nRate );7 \) P2 M: V% v- ]# r7 j4 T
        n106.Reset( fClock, nRate );
$ A7 ]% k, Y9 i: D% y2 H( N' f; C        fme7.Reset( fClock, nRate );% J& i1 C6 L. ^3 E4 k% s) B) h
# Q, g. O# X# D( [- P) n0 ~
        SoundSetup();' G3 q. N( J" M" J
}
9 V; Q: `( e2 a8 {. E+ E& f- ~+ L# C1 E# I$ J8 i
void        APU::SelectExSound( BYTE data )
! e. q' s7 N6 @+ v" O, {; n{  U" \" G8 z( `5 m. A. C3 [
        exsound_select = data;3 P' N# M- O- h5 O$ V2 }: l/ o
}# y3 A+ [5 U4 x9 _: K  c1 C
5 u! y- [% A% x6 l/ _! }6 F3 A9 b
BYTE        APU::Read( WORD addr )
% C. Q" ]+ Z' S- x# @{5 q# L) n9 B- C/ ~/ b! ]
        return        internal.SyncRead( addr );
# c8 w, W. |& `' e}
* m* F' n( z9 |2 L, n' P: Q( h
3 `- a- y& n$ c# E! Q3 [' o' Rvoid        APU::Write( WORD addr, BYTE data )  k0 H3 g; t; k/ K
{! N3 W, ]. H2 \& ~+ L
        // $4018偼VirtuaNES屌桳億乕僩
+ |" l. U7 e" v  M/ ^5 C        if( addr >= 0x4000 && addr <= 0x401F ) {
" B, m5 E* e) R, s6 d  d- p6 p                internal.SyncWrite( addr, data );8 b  K  F. Z& W) S( G* T
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 s# |! G) W# N6 l7 ~
        }; ~, R: z  v4 G) e
}0 x* X. _9 k' n

, E8 V1 H$ Z, A8 u# X8 T' n" XBYTE        APU::ExRead( WORD addr )
; Q1 h# O0 p& @/ O' |! i0 {{
  P2 z1 Y' l9 \BYTE        data = 0;
* f4 ~/ b: u: G' t0 f1 C- @6 s
* L" z/ }- N3 _, u5 H- B        if( exsound_select & 0x10 ) {6 I4 s8 p  B3 A; ~6 c
                if( addr == 0x4800 ) {
) q5 r2 m4 F6 T* X                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ e9 r+ I# V4 L  N/ H
                }
: z5 Y$ K' \# Y# u        }
. i) u; u0 h2 x3 L+ T" X8 s8 ?+ x        if( exsound_select & 0x04 ) {
6 C% R( M/ N# A7 u) m                if( addr >= 0x4040 && addr < 0x4100 ) {- ]: ^6 ?. ^+ h8 y0 n" m1 {
                        data = fds.SyncRead( addr );  @4 }& l$ O) D' r# r
                }
- h7 ?: ?# P4 J* u. K: b6 w2 [5 F5 ~        }* ]( l( S1 K5 M. L& [) d( h
        if( exsound_select & 0x08 ) {
2 R$ m0 J& _3 D2 V                if( addr >= 0x5000 && addr <= 0x5015 ) {$ E3 r/ w8 c  [! L. u( j* ]0 J
                        data = mmc5.SyncRead( addr );
$ K( q" J& k& t* m5 O# a, B' d2 {6 X                }7 h+ X- t  S3 c: X5 }
        }
/ z( |7 O6 A, l4 v% J5 {* |! E" f
        return        data;9 e; R6 d! W; d) J0 V9 C
}! j3 x) J) j: k$ f9 J

- s. D' o& w  |2 |& T! svoid        APU::ExWrite( WORD addr, BYTE data )  z- d- O  a0 T* x' `- @$ `% ]5 y
{
% g( n* }; u* p4 b1 i# @        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 H7 g. M( E) J
/ |( N6 e0 E! A* i; _        if( exsound_select & 0x04 ) {
5 c; v( T4 q( `+ I                if( addr >= 0x4040 && addr < 0x4100 ) {
6 F4 v: d8 z3 e6 H- U$ c                        fds.SyncWrite( addr, data );
0 J" i3 g, ~' D. S                }2 }0 I0 T3 g* t2 X1 @2 ^$ h
        }8 o! \5 h: ?3 b6 m) @8 v

: @  G2 ]! ?7 F* ^/ K: K6 q- E        if( exsound_select & 0x08 ) {
! G, N, ~: q. f" I+ r                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ L2 k7 F8 g8 X: ]) {! g                        mmc5.SyncWrite( addr, data );, p# j9 J" _( [+ M* }) T, z$ j
                }% N. X: r+ p, I- r
        }
3 v) t; c$ M1 P+ q}- H) X4 E1 N: F! Y
! h: `- @" z9 v6 U. n, t
void        APU::Sync()
3 G* n, @7 k& f& j* S4 ?6 o( ~{( J4 p: Z5 t  i& W+ f& w4 v
}" k' `& F( G# i. X" l
: X8 _+ ~. {3 U4 ^
void        APU::SyncDPCM( INT cycles )
( C0 T& B- w/ F- n; y; o6 `- m  a3 P{
4 N. e- h; q+ ~3 I; y) V3 f        internal.Sync( cycles );* J& M4 v( K# ^2 K1 K( L4 T

) I7 O5 i2 J% |6 v' W        if( exsound_select & 0x04 ) {: |( `  m. a2 ]- g/ ]# D+ o7 B
                fds.Sync( cycles );3 ^8 [) p, C5 P+ L- X2 @) q+ w
        }0 S; J& t5 B2 }# M& t7 o( t5 ]7 y
        if( exsound_select & 0x08 ) {
3 F( `6 Z& T( B( ?                mmc5.Sync( cycles );$ a8 l0 D7 _; u+ w* y% p
        }5 _. M' S" o2 G+ X2 h- r- a! l3 S: O
}
$ y) T2 V, k1 s' r( ]. i( _8 U" p. K
! d2 M3 A$ d* y$ ~* }void        APU::WriteProcess( WORD addr, BYTE data )
# @. d! k: d, u6 ?2 e* K- O2 h{  t. i% e. Z8 ]; @6 R
        // $4018偼VirtuaNES屌桳億乕僩
$ b8 g' d6 Y! x: o/ {1 l* l        if( addr >= 0x4000 && addr <= 0x401F ) {
0 d: s2 \& q1 K0 I/ ]5 v- A                internal.Write( addr, data );6 e6 A: [' n) U. J; V& q$ u
        }) U% `% j2 H$ q9 u! x
}( Y% n3 y+ @* z
' N: \; P/ w- ?4 z" `# Q8 l& y
void        APU::WriteExProcess( WORD addr, BYTE data ); I1 [1 L% ?! L- ^7 @8 U
{
3 g3 Z/ A0 {, d6 H2 g$ r5 ]        if( exsound_select & 0x01 ) {
1 ]: \" z. u- ^                vrc6.Write( addr, data );
2 J# F* h9 E, H; B/ q( k5 f        }7 c! T/ y  X9 y+ F2 ], t
        if( exsound_select & 0x02 ) {& L7 E  K% z+ X) }
                vrc7.Write( addr, data );
1 x; z! |1 t5 S        }+ Y1 E" \4 ]5 W% O: y9 k
        if( exsound_select & 0x04 ) {' K9 m: }4 {* K- j
                fds.Write( addr, data );! U0 U# f& Y1 c5 N6 `' x0 U
        }! t1 R% H0 i9 a! ^! g
        if( exsound_select & 0x08 ) {
8 |) N) O- a' t8 S  m                mmc5.Write( addr, data );
, J! ~5 y- i: ]9 k        }6 ?3 O  w0 @. u% m
        if( exsound_select & 0x10 ) {; ~3 d! ?3 G" c
                if( addr == 0x0000 ) {2 q( d" ?, p) g9 n; _2 Q
                        BYTE        dummy = n106.Read( addr );
2 [) J9 ^, q% H7 G# @1 x! X1 P                } else {3 |* k4 m. U- `$ ^! v0 D7 }
                        n106.Write( addr, data );
- p0 m/ T: J5 W' S9 `6 ]                }
  k: G" ?( D# ?# S/ p        }
& w+ T0 c- ?6 T* S. S: ~/ t& O        if( exsound_select & 0x20 ) {% Q& ]5 s3 `& j2 u, G* b* e: \
                fme7.Write( addr, data );
! b# W# }5 q# x0 K: P& |: Q4 `        }
: z6 o7 `5 |# w" h5 z/ e- @}
: z0 Q, W2 p5 t7 S+ |* i! q2 ~8 P, B2 P3 {
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )) F" d& ~5 J' [5 R
{
; G* |& c8 M9 m. XINT        nBits = Config.sound.nBits;
% }4 E5 ~6 y, y' K1 B2 pDWORD        dwLength = dwSize / (nBits/8);
' x" K" b7 B, f$ WINT        output;, A8 z+ S8 |# d
QUEUEDATA q;* w2 P7 [( w1 ^, l! x! ?# C) @6 o
DWORD        writetime;- `8 o; y2 p! E8 m' a
: K! I& e5 T7 G9 {# Z. M) w
LPSHORT        pSoundBuf = m_SoundBuffer;
4 m' O. L7 O8 P7 m+ c; N* yINT        nCcount = 0;
( W# @! d( F0 M$ d, \/ E; G5 F; b  h' _
  n" h) R$ F* B+ D( a! pINT        nFilterType = Config.sound.nFilterType;( k' Z9 k8 U2 O7 z5 c" K; J

, k! r  v' a) y" d' t        if( !Config.sound.bEnable ) {
" o6 Y% |' F* ~+ K5 z                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; d1 `/ m( @5 k8 o% L" e+ q" C
                return;: Y' k/ E* v8 \+ i
        }
# R9 E1 H* G; X# V! _& Y0 u5 `0 j( \6 A% g2 I8 X; J6 |7 \
        // Volume setup
$ x, ]2 n! _) Z0 C6 T/ \        //  0:Master( \4 _( g8 I* b# C* m* N0 ~9 g% s
        //  1:Rectangle 1% t* x4 H& u% s9 u& b
        //  2:Rectangle 20 \4 {9 ?1 E& L: X9 G3 a1 g
        //  3:Triangle1 q0 s6 Q' k$ r' j* l3 B1 x
        //  4:Noise/ T  q1 ]+ U2 ^8 {
        //  5:DPCM
9 z5 ^3 z. {) h+ I' {6 |        //  6:VRC6/ y) A, d1 O4 l( C
        //  7:VRC7
- y0 F; G  o, C2 ?3 _        //  8:FDS
! F' b0 \& I5 w0 T- W3 _6 e        //  9:MMC5  a0 t# W, o7 v' X
        // 10:N106- Z1 }$ O1 A  X% |5 V) {+ ^
        // 11:FME7- B3 i  l5 x4 q+ D7 ^; z
        INT        vol[24];3 W- o( P! H0 s$ C% Z: l! \
        BOOL*        bMute = m_bMute;
2 `9 ^; ^5 r/ L( ^# \5 l* G/ ~# x        SHORT*        nVolume = Config.sound.nVolume;
  ?1 D, s" [7 n) `! O* [1 Z* Y! |0 g9 a+ d$ D' Q8 k
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
6 k/ c" i" Z& q. K. v- O" P- w: j; ?- N! ]/ _- z
        // Internal* N' K5 P: V; S
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 u5 |& Q( a& Z: U( ]8 O) S
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;" s' E4 d3 \! S$ _& n7 I9 t- k; _
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
- |, g1 {0 \" q5 x( l  [* c        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 q2 Y! L( n) {+ W' U, o        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& H( x& d: ~8 F; G
8 C" M& d* J4 J0 |1 }6 l        // VRC69 p& ]: X8 ?" L8 m; v9 `
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) d% K+ n! A: h' e0 h/ T        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 O1 L. \* S! ^- i        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! Y8 t) g! Q3 S2 c5 j; P. I+ g0 X- p( R( m
        // VRC7
/ V6 _2 p! R' b' k8 J: \        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;9 J1 S$ R4 y4 p  p  N+ B
; {6 d3 c; t4 X4 s6 ?
        // FDS, f3 ]; B7 ^/ u9 x+ p, z+ T/ |
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
7 Z+ U" c0 f* a3 U+ v+ F) ~7 [: z
3 O0 W, `. Q: p4 O9 p        // MMC55 m! m# W+ h' l, v, L( c7 E
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" l! f. ~/ N+ B  B9 w  F- x        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; L- I9 L. [2 C& Z9 N        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 W! P* Q5 [8 B& r
+ y5 I  v3 g1 o7 K5 U
        // N106
1 @% k" s3 w; [; ~* @+ m        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- G% V5 \- K/ q- m( P' S
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. i/ j, I" |( r8 k        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- h- ]: d# z3 i6 \% T3 u" Y8 ^        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( x) i, _$ s1 o9 c$ l3 O" r        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ [( ?: P6 q3 F" Y$ y& D
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 L2 F- ~0 V% P+ W- `. [; I/ e8 z  u# p5 Q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! i& m/ s. H3 ^% Z1 ^/ L        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 c9 C$ A" I$ @2 X" ^

9 d% s/ s4 {3 A3 N        // FME7
8 a- a: ^. N  t. z" N! l6 J        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 x9 J6 Q# T" k9 L. X$ H, o        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ q6 L" a5 _- U1 D* y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, w1 L  W, a2 N) ~; U' |" A( q+ Q; c6 ^  F
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;9 f% J6 h9 O' z, i1 ?; F
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;+ d, `$ G: F7 G& v" U2 V* s
' c" `2 t  Y) t
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟( \3 O: \8 y8 ~: c, E6 y
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {+ Z9 {1 Y: T; I6 a6 n) d1 q  d! i
                QueueFlush();' c# k5 U  U0 }5 a: ^2 R) b/ _
        }
+ B4 z- K7 l  u+ j: [" L0 z( a4 p1 f, l; t8 x0 a
        while( dwLength-- ) {
3 _+ {0 b6 I( @" W- D                writetime = (DWORD)elapsed_time;
* ~& Y* O1 r% [3 R+ x: L' i: {' }& R7 M5 |! J
                while( GetQueue( writetime, q ) ) {% |* S( N' o; j" x- w( M( s2 ?( H
                        WriteProcess( q.addr, q.data );
# W! c# K/ V. v1 K2 f1 A7 f1 z                }) L4 h  n4 U; i  l1 L: q8 I

2 b3 j- m$ Y# U5 h; Z                while( GetExQueue( writetime, q ) ) {
9 [2 ^; R" g1 f5 `+ {8 h                        WriteExProcess( q.addr, q.data );
) x$ @- c6 O4 y1 |8 \  T                }2 @7 i! q+ a. n, Y
) Z# i0 T. \4 o: O# W5 e# U
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 x% w9 @7 \  V$ v) K                output = 0;( [4 m9 s  D! p0 Z. R1 @
                output += internal.Process( 0 )*vol[0];8 ~3 K! a0 u$ y4 C
                output += internal.Process( 1 )*vol[1];
/ o' d3 w1 S5 _. W; k1 I                output += internal.Process( 2 )*vol[2];
0 H5 }, V6 D9 ?1 N5 R2 M                output += internal.Process( 3 )*vol[3];
; y( N. M2 o/ h2 |! z. W                output += internal.Process( 4 )*vol[4];. A8 X. d2 [3 |0 N' u) L# u
: Y9 `$ O( I  O
                if( exsound_select & 0x01 ) {: ^: y9 R' ?; S
                        output += vrc6.Process( 0 )*vol[5];! n2 l1 g; D; X3 x
                        output += vrc6.Process( 1 )*vol[6];
# X+ D3 S3 m, ^) V# N5 Y                        output += vrc6.Process( 2 )*vol[7];% j3 t3 v+ I( L. g9 Q, e) V
                }* C1 D: h1 G0 `1 c5 g! Y2 P
                if( exsound_select & 0x02 ) {
( d' \) P. T8 z; Q( Z. ?                        output += vrc7.Process( 0 )*vol[8];
2 t/ D9 s$ T1 {                }
' j; a, o" I  Q* i                if( exsound_select & 0x04 ) {
  r/ v8 D( Q- ?% a2 W+ x! g                        output += fds.Process( 0 )*vol[9];9 F: Z# E2 a) k# e9 `3 s8 N
                }% o. p" ]9 x5 V! E3 c3 A% \
                if( exsound_select & 0x08 ) {
6 _, }1 G" J, ~* I7 U" F* O, }                        output += mmc5.Process( 0 )*vol[10];
5 Q4 |0 l0 u; p6 O5 m                        output += mmc5.Process( 1 )*vol[11];' {8 V" u! ]1 {/ z! m/ m: M
                        output += mmc5.Process( 2 )*vol[12];
9 E5 _/ l4 ^0 m2 q9 ]1 V                }
% K( P: C1 w" v; ?2 f  Y9 G                if( exsound_select & 0x10 ) {1 S, g6 \  l5 }" {/ _' ^
                        output += n106.Process( 0 )*vol[13];( ]6 A, E2 P1 p1 V9 f
                        output += n106.Process( 1 )*vol[14];6 x4 R* |; P0 N7 c7 E! K
                        output += n106.Process( 2 )*vol[15];7 F$ j8 m  H/ a9 _7 x4 e6 I; B- X
                        output += n106.Process( 3 )*vol[16];
' r1 O4 a9 I8 ^' N2 |- L+ N; Q2 o                        output += n106.Process( 4 )*vol[17];
/ w5 `- k8 s  I: ~                        output += n106.Process( 5 )*vol[18];, u+ z( g6 E& W, x" A
                        output += n106.Process( 6 )*vol[19];
: M9 m' B" M; {3 h6 r                        output += n106.Process( 7 )*vol[20];
7 s/ Z- H- o0 m8 \) j- Z* x. j                }
, a. z1 D* O" \6 D% J7 |9 A+ B                if( exsound_select & 0x20 ) {9 P  L3 Z7 m  m2 o
                        fme7.Process( 3 );        // Envelope & Noise
6 a) B# j3 V6 J8 M                        output += fme7.Process( 0 )*vol[21];
8 `/ x6 L$ ?8 |                        output += fme7.Process( 1 )*vol[22];
3 f) d( }5 m6 p5 h$ {                        output += fme7.Process( 2 )*vol[23];$ U& m6 {# N2 x" D3 S1 H
                }
& A. j# N: B- ?$ j8 [* x7 f6 q1 Q  E% ~" T7 U$ b/ b
                output >>= 8;! k* d7 K, r$ l

8 K6 p' Y! d- P' D1 K$ W                if( nFilterType == 1 ) {
! D- n3 V: \1 Y# N                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
/ h4 f- S, R( A                        output = (lowpass_filter[0]+output)/2;7 @9 [+ n$ \6 j  u+ i& B8 V
                        lowpass_filter[0] = output;
# Q: `3 n2 n% s( J0 R- R" R# J# K                } else if( nFilterType == 2 ) {
/ y: Z( D! L9 n& {( o" A  D: ]                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 e- S, k" j0 z! _
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;  S( I1 r# P9 v8 t6 {/ N5 I- I9 X
                        lowpass_filter[1] = lowpass_filter[0];
! O" s# k: V: W4 P3 D                        lowpass_filter[0] = output;* `1 W) x0 \# T# X2 R$ A
                } else if( nFilterType == 3 ) {, `5 _& y1 H+ r6 a) m
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ e9 |* }+ W/ ]9 o                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
- h6 _3 w1 ^* h% N. w: B! H3 v: I                        lowpass_filter[2] = lowpass_filter[1];
& X/ ^: R$ e! M& z( y2 v* {4 A2 d                        lowpass_filter[1] = lowpass_filter[0];# B2 \+ i6 e& ^( @. G, Y
                        lowpass_filter[0] = output;
5 K0 [* u- C; C                } else if( nFilterType == 4 ) {
5 }( [* K) q0 }% f; D% w6 j# U/ p                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)$ ^" p& [- K! p2 w( [' r
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
' u) f- `9 q+ \* o' c6 y3 V                        lowpass_filter[1] = lowpass_filter[0];) f4 m$ s; J1 H0 R
                        lowpass_filter[0] = output;
7 Z  u( L% Z: L  O3 V! k5 f                }
, e: O  z- F' ^5 M* i4 g0 N% G( L% _
#if        0
; h* N* p4 S4 \- U7 L! x3 {$ l4 ^% ?                // DC惉暘偺僇僢僩
, j& p& b3 q5 U. Q( h) q7 m3 P                {. |- h3 T& f6 L0 p" g- a3 x
                static double ave = 0.0, max=0.0, min=0.0;
7 P: s% u( L) y; u                double delta;
  G  ~& A  p# L; u& d/ c                delta = (max-min)/32768.0;
3 x8 g2 X$ A( U* |. W/ K                max -= delta;2 V. t, l; a3 I$ Z; b; {4 ~
                min += delta;+ ^9 ~$ [5 l+ n7 X
                if( output > max ) max = output;6 ?- M& |6 O, a4 s9 u
                if( output < min ) min = output;
6 g8 Y' M$ l* y5 x- e                ave -= ave/1024.0;, d5 P0 ^# o, F. l* q
                ave += (max+min)/2048.0;( g. T2 M4 J/ I( A8 H
                output -= (INT)ave;& `: T; B+ l3 A% x" c9 I1 r
                }8 h9 q: x% R% p6 ~0 b7 y# ~
#endif
, R& T. V: v6 V0 r) f; @5 r#if        1
! ^2 `+ q" r) Y6 I1 g5 H6 m                // DC惉暘偺僇僢僩(HPF TEST)
* A/ D- Q4 U. U, n                {6 n0 h+ [* B% o' f  k+ |4 ~2 S8 Y$ f9 |
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- @. }6 i- ?1 l+ D% |8 `2 Z
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
8 Z& Q) j: m; v0 Q9 n* M% D! ]0 R0 K                double        cutoff = cutofftemp/(double)Config.sound.nRate;" \; l- a1 {; M4 t1 g* `- x
                static        double        tmp = 0.0;
& A( ?$ x) a# @1 \                double        in, out;
8 Z" h1 @, J( b% m4 R9 ~& l/ ]
. R' U3 D7 {+ `                in = (double)output;. t3 b0 f8 y/ M0 r/ f& m! u
                out = (in - tmp);4 b" C& x' m/ g6 q' G: u) z2 _
                tmp = tmp + cutoff * out;
# f% g/ O& ?+ Q* {% l
0 w% O5 I* e, I                output = (INT)out;5 u+ A$ ^) d: O7 Z$ u# `: b& x4 W6 D
                }
6 d: T) g& y# I#endif
; L8 F6 d  ~! ]6 t#if        0
! J9 ~3 z+ u8 {; |& \2 E* U+ Z                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST); W+ t6 ?  r2 ]0 c8 Q, |( }
                {
/ W. {& \0 c# ~                INT        diff = abs(output-last_data);
/ _9 u2 ^+ m2 `+ N$ `& {& n4 l                if( diff > 0x4000 ) {$ z' ?. y# c& i! l3 y& L
                        output /= 4;. Q: G9 L1 W5 v1 q' g$ x
                } else 2 K2 q+ u! M' c9 C6 s/ o
                if( diff > 0x3000 ) {6 o, g! c* \; w1 U7 e
                        output /= 3;3 s9 u- D* [, b$ T1 Y
                } else' v+ S/ F" `5 Y( j3 `$ W
                if( diff > 0x2000 ) {/ l/ P. b$ [! i) H
                        output /= 2;5 u) |4 p( M4 P; _; U( w0 s3 @! D2 j; {
                }, j2 n3 ~; @. W
                last_data = output;
' M$ ~6 ~: c# K4 g: |                }+ O" I" S6 q* z8 Z6 B
#endif
; \5 A  V4 {7 w  q                // Limit
* @' s, Z! U1 ~9 T9 x' C$ D                if( output > 0x7FFF ) {
9 s) N& R4 r) R7 [0 N6 E                        output = 0x7FFF;+ C+ p5 T; r+ X, j  C) A
                } else if( output < -0x8000 ) {
  l9 e) V9 t9 e, I7 l                        output = -0x8000;
: d% a4 K  L1 c$ V: d6 E                }9 L  d4 P) B( R  i. i5 J+ K+ R
+ K: [, V2 u. I$ C# \) L  j
                if( nBits != 8 ) {& B4 W$ M, U3 o! S0 e2 n: K7 [, Y; y# C
                        *(SHORT*)lpBuffer = (SHORT)output;& \* d7 F2 I$ X& K- r2 A
                        lpBuffer += sizeof(SHORT);
! m5 X( K. @1 G, ?2 J8 F: n                } else {9 z4 p' ~; z& E5 O5 M: F& h
                        *lpBuffer++ = (output>>8)^0x80;
0 e1 t2 R' z! ~" Y                }6 r2 e9 y8 @+ I5 h6 Q) D
) k$ m- f, a7 [3 ]5 ~( d
                if( nCcount < 0x0100 )7 g7 L$ f: z: G1 V9 l
                        pSoundBuf[nCcount++] = (SHORT)output;
6 [+ q& t8 _; H* w( U4 u6 B9 w( w5 p8 K/ k( g- Q: @4 g8 F
//                elapsedtime += cycle_rate;
4 L" K7 V# {  t: N+ \                elapsed_time += cycle_rate;0 e8 T: z, a. C
        }) x, u) v6 w9 G" L
1 ^/ U' x( x- Z4 p: I* X
#if        1
# a/ \2 U  n4 N. C        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
; h- Q, f: J, g. A0 Y3 U& b                elapsed_time = nes->cpu->GetTotalCycles();0 _: w4 i& O0 x7 K( [
        }
1 s' e  D7 _" W' J" H2 q* u& {- e0 ^        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
1 b+ n; u! T5 E6 X                elapsed_time = nes->cpu->GetTotalCycles();* s* G' _* M0 ?4 H9 j: X7 D" x1 K
        }
$ B! ]- y! B1 _) W' `#else2 Y( m0 ^) g2 n
        elapsed_time = nes->cpu->GetTotalCycles();, L$ A/ C$ E$ c3 W
#endif' V1 j4 @: k7 ^, W, G
}
$ r, v- O9 B1 o3 |. |3 j7 J# x* O$ Z& l) Q4 B# i* D
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
  f7 U' t9 `& c7 q3 \$ B0 uINT        APU::GetChannelFrequency( INT no )( P- f( b& i5 l2 O) o- Q
{
' v- B- j" \" D4 z# @        if( !m_bMute[0] )
( R+ Y9 n5 y! N, M8 c                return        0;" I& D/ b+ ~+ i6 o6 u: t

. o, W, N9 ]. n/ b$ I        // Internal8 N. z% g" W! z8 q3 n- b
        if( no < 5 ) {
0 ]0 S# _4 s$ D6 P$ Q                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( ~& ~3 |. ]. R- A$ P5 K- s        }
7 ~- R1 `0 P6 [' d4 c        // VRC6
& g2 _# n: W, l# m' d# l- |        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {) L7 l) V8 C- {8 `0 J6 i4 S
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
7 K" C/ F" W. r) x0 {        }
& c% J4 V' M' d. {$ Y# D6 N        // FDS- M! |! R3 L+ T- V+ j
        if( (exsound_select & 0x04) && no == 0x300 ) {9 g/ F  R' h4 l
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 v: f# U% g3 o$ B( k        }
6 _: H1 p" l$ ?. r        // MMC59 j/ [' b) V; t$ U/ t' J
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {! M9 X% ?5 G' }& X& r4 z' W
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;, M4 g% w5 v( M; x
        }
2 m) r6 }7 m1 y0 W. a6 G1 `        // N106
# @: ?- @2 v2 h        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- a# V1 p4 \" D- f* e9 z                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
1 b( L  W" G  S* _        }
, O; s* F* [/ I5 s8 B2 J+ s6 p        // FME7
6 i& q4 _  B) b; {1 d2 u& U' T0 n9 K        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
( B  v9 |/ B8 V6 A, g6 d                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
; ?* @  \+ @6 s# b2 ~        }; _. H, [4 b0 S8 ?; u
        // VRC7  V3 W) E' Q9 c' e: x. `
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
, e" N5 R' U$ I9 O6 K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;2 o( B4 E$ ^8 h' a1 R8 U7 `' B
        }- L0 P& \8 u2 G0 _; l0 m: _3 r
        return        0;
0 Z0 ]' m3 O  ?) V0 L}, ^6 k* j+ B- |; _. X: x

3 n* `: ]5 h. `0 @1 {// State Save/Load
. _. \1 ?9 v. _4 @void        APU::SaveState( LPBYTE p )" f0 U$ [4 t0 u% Z, X- z2 A( J" E
{7 h  F4 P/ }; ]* x) J9 P
#ifdef        _DEBUG
8 y+ T2 U3 U5 D) d' G: LLPBYTE        pold = p;
5 Q0 M; s+ X( D#endif. K+ K5 J4 ^* G& L! R

: \* v7 h3 i" g* r. Y+ W% Q        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
, r. x6 X) g; Z8 c5 h' o' U9 J        QueueFlush();: M" i5 j( q9 C4 D  B3 T- M0 v6 [
6 @, i6 h8 z1 e% M  \; e. s
        internal.SaveState( p );2 w& [) s0 w) M
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. C$ B* d; n1 |0 `
; G+ u* D! |: C1 C
        // VRC6
) ~4 ]8 D6 F( K$ U( R% t6 r6 X8 @        if( exsound_select & 0x01 ) {  b% s  D- o; u4 V2 @5 A% |
                vrc6.SaveState( p );
  m# v  B# h% ?0 u                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 _7 Z; q4 h# `- z9 g        }
# f; S9 p7 I) }6 \5 ]2 D2 r        // VRC7 (not support)
, c( Q1 l3 `5 p) p        if( exsound_select & 0x02 ) {
0 d: ?: }, E! a5 |5 r* t8 C                vrc7.SaveState( p );7 T2 A( g7 H6 w2 z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. O% l* q3 s- D% c2 s# T* b$ A1 O$ I
        }2 [& v+ @! M0 F0 W5 W
        // FDS/ i1 P: e9 x  U* Y! s% m& }) q: }
        if( exsound_select & 0x04 ) {
6 n/ [+ W; |3 ^$ I                fds.SaveState( p );
; U, H" K2 P3 \3 c) ~" J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 |# _7 l, M$ I  K1 D        }
) @* ?( t8 M; z1 ~0 i2 d9 ?        // MMC5
* T; N. k0 v: R! i, o/ W        if( exsound_select & 0x08 ) {0 n3 n& ]. H+ t3 A! J! H
                mmc5.SaveState( p );
* O. \! c- ?, n. p                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! B: o# Q$ S( x7 G        }
4 q- e' J. Z" G        // N106
" q6 k3 p! U, T+ }1 T        if( exsound_select & 0x10 ) {
, B7 h- z# I4 m- y& K7 H' Z' x                n106.SaveState( p );8 x! P# u2 ]& ~( U# m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* X1 U7 U* T/ Z, f; A+ {. j; |
        }1 g4 C! t0 I. b/ f# c( T- ?& m
        // FME7
6 V: S9 c% w  \6 L: t8 s        if( exsound_select & 0x20 ) {7 X6 i. v' }) ?% ^9 A) G( o" f. H
                fme7.SaveState( p );
8 \" T8 s/ O& j/ p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 m. @  v. n# n        }$ A$ l! E( K7 d* H& v

6 g3 y8 f9 S/ l! I& i( Z#ifdef        _DEBUG. \  U! d& f; W9 o7 N. H5 E( B
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
8 p# l# F2 n6 c4 x- [4 N9 @#endif
  t- f; C4 |9 p}+ j9 u0 u+ a! n6 r; V* c0 [. i

$ C( T0 _! I2 ~4 Y4 ~- Yvoid        APU::LoadState( LPBYTE p )' G% V. z- ]" V1 A( g4 o! |/ C
{
# T0 S2 }+ p! |8 |" r7 ^        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ J; u: E  T% P) I4 o        QueueClear();( I9 `# C+ j/ H, t9 Q
8 ~% o, ]6 M' Q* M+ x0 g
        internal.LoadState( p );7 h5 x  Q1 A4 k2 }7 ~5 r
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
% ~& p: D3 _8 J; s
; {8 v7 w( H4 X. s% C1 x" m        // VRC64 p7 v. Z1 m8 \% e' }/ t( Z
        if( exsound_select & 0x01 ) {
% G$ O8 [! K( G" T% M% q, {4 p- i                vrc6.LoadState( p );; ~; `& o" x$ g$ |9 c
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 z  ^$ R1 w4 h- N        }. q: z2 e3 U8 k6 B
        // VRC7 (not support)
0 Z, t( q5 k) @7 {! r        if( exsound_select & 0x02 ) {' h& C: D5 X7 V7 {$ F
                vrc7.LoadState( p );& a) d1 ^5 h% N1 Y& U
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% K9 A/ `3 B8 W. X- d5 }2 U* h) v* g, Q
        }+ T1 c; H/ X0 ?+ D
        // FDS8 q# ~4 U9 D8 I
        if( exsound_select & 0x04 ) {
0 \2 v; h- j8 [* f                fds.LoadState( p );) x. ]. f1 ?* p+ w( X, p7 w: t
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* d6 C! ]# S# j8 c        }1 K5 j% l! m) u% R1 \2 M5 M
        // MMC5! ^0 o! g2 [1 v# c7 ~' r6 F: }
        if( exsound_select & 0x08 ) {
- n6 w1 H5 S$ l# M' C, j- E                mmc5.LoadState( p );5 }% N0 e/ z2 u3 k( K" J; q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& i$ [1 f9 v, l$ h, E  U
        }
& f( g/ h% p& f! r8 \5 i        // N106
; G# y5 r* E( X& v. M; h        if( exsound_select & 0x10 ) {
0 o  {& Q, T# w                n106.LoadState( p );+ L# {' l1 `: A
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: [" H% f3 `% g) p+ _+ z        }
+ H7 a0 `$ u2 V- J' v9 ^: e6 `        // FME7
3 O5 x; F: l* _6 d        if( exsound_select & 0x20 ) {
' j9 ]( u2 h# J3 f7 e                fme7.LoadState( p );/ t, O; t! ~3 |' C. Z7 Q. A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ U7 d$ E. N* m0 N, f6 L        }0 p: p- l, @% @* ?" c0 ]% ~5 B6 ^! O% P
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
2 l2 C/ j9 z2 i& y8 }0 |0 b0 [可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 {* y5 _- R! w8 P% S感激不尽~~

6 y* ?9 X# g% Z% l* Q恩 我對模擬器不是很有研究,. `  ~$ r+ V; z9 ^8 q0 V: D
雖然要了解源碼內容,可能不是很困難,& V" h  Z, Y  |
不過還是要花時間,個人目前蠻忙碌的。
, x0 p9 i6 U7 A' q* S. X  o, o! _4 p! i% k/ \) l
給你一個朋友的MSN,你可以跟他討論看看,# r' o" ~& J1 l1 u1 d
他本身是程式設計師,也對FC模擬器很有興趣。
5 y+ S" X& U( a2 N' C5 R5 j. A- p  s/ G  i/ _, |
MSN我就PM到你的信箱了。" ~! O# H* p5 t$ f9 B& @

) ^* E0 f- A1 A7 x希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
" S0 R3 c" S% C4 F# s呵…… 谢过团长大人~~

/ v* f. ]* A8 G; m; R4 A: G/ V# k7 D1 w! P
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ L' W: K. a4 c& V  G( S3 @团长的朋友都是神,那团长就是神的boss。
% T0 `/ o! N/ c& t  Z% |% q" I
哈 不敢當,我只是個平凡人,7 J6 i/ u% ~6 L, K  r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; |3 Z, O. g. _0 T. j4 pZYH
- d- P' E$ K, }; K% j+ SQQ:414734306! q9 v. w( G# c- u* H: z/ r
Mail:zyh-01@126.com5 k2 V, t$ \6 n$ N1 z+ F! h
6 v& A. B8 D' ~2 K+ z3 W* I& z; L
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
$ Y$ Q# I: X, }$ n再次对团长大人和悠悠哥的无私帮助表示感谢~~

! c0 v1 M6 w+ k3 E9 N不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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