EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 s4 Y/ Y# C$ i& q7 m1 d9 P
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 x, {4 ?0 {3 [2 g) e1 U这里有相应的模拟器源码,就当送给大侠了~~- o8 y+ N# y" V' Y
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
$ @1 ~  M* ^  ]6 E  W能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, X) H3 \  Y' Z" X
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' [$ B2 w1 v" {5 u( A: b" I6 p
这里有相应的模拟器源码,就当送给大侠 ...

: K! |' H# d7 {  j4 i9 D聲音部分(Audoi Process Unit = APU):. |- H8 |' A0 h9 Y6 M9 i7 v; R
.\NES\APU.cpp2 P; O4 s  l" y/ i$ g- @
.\NES\APU.h- J% N$ j0 W  q, Y* Y. [
: n1 ], Z# R' H8 h$ [+ I( O( S
5 \: W* O9 M8 G& o
影像處理部份(Picture Processing Unit = PPU):
2 Q- E& f% f6 z7 y) C# `) b.\NES\PPU.cpp
2 ]. V$ ]" h- }4 w6 f; K.\NES\PPU.h' g$ y/ O" p) J0 f

" A$ `* g* Z6 c1 y- V如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:4 s9 A5 {3 W; g5 {8 x2 J$ I" ^! f
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) a, a$ p, N4 d2 H7 q5 e/ z//////////////////////////////////////////////////////////////////////////
/ I, L* s( i* y$ ^0 ^//                                                                      /// b0 m% w; H. `7 ]% R$ l$ q# C  u
//      NES APU core                                                    //' k! y( w" e7 f' Z1 H) j8 }  ]
//                                                           Norix      //& E" `% K! f" w
//                                               written     2002/06/27 //
" ^+ t; O) s. c1 t3 S1 ]6 Q* t//                                               last modify ----/--/-- //
; F' q9 H5 j$ h5 j( [//////////////////////////////////////////////////////////////////////////. ^( M) R7 w( P
#include "DebugOut.h"6 N0 @) K  V& k! V
#include "App.h"! @; N# Y4 p: G6 _. ]; Y2 b
#include "Config.h"" p& U, |/ F, F' B" C
9 S5 E. a; P. O3 \& c  U* R
#include "nes.h"! L8 X  E+ D; h- A6 u
#include "mmu.h"* x9 K7 J0 J4 x- y
#include "cpu.h", H7 _! y9 N' d, U9 c4 s  p
#include "ppu.h"* }' y  c  ~% {) D' f; L
#include "rom.h"/ f) _7 @0 C: o' x4 W" T" g" o
#include "apu.h"
% @" K$ i) ?  P  J4 W$ h: {, @- j8 c6 I+ P2 B- S9 I7 B3 N$ ?6 [, L  x
// Volume adjust
. e1 h8 ?  @; w) r( N// Internal sounds
2 g9 R8 g1 G2 s% T2 T#define        RECTANGLE_VOL        (0x0F0)
7 u( K& M6 s. U- p, l#define        TRIANGLE_VOL        (0x130)' F' [1 d" k7 e5 V+ v
#define        NOISE_VOL        (0x0C0)7 A6 J- `' }( C; x
#define        DPCM_VOL        (0x0F0)" }+ v8 W; I) |4 _" D3 L% e' i
// Extra sounds
4 h0 r% g# G: U- S' `- [0 J#define        VRC6_VOL        (0x0F0)
+ l" b( C# y. ^& A' J, ]# A0 v) o' S#define        VRC7_VOL        (0x130)- ], r& D7 {3 w( p) t6 S
#define        FDS_VOL                (0x0F0)
5 j# E* K# @" [; a" R- u9 S6 h#define        MMC5_VOL        (0x0F0)
& r. G3 z" Z9 V6 t#define        N106_VOL        (0x088)
" |% m+ s$ p0 |6 e+ A#define        FME7_VOL        (0x130)
: F1 ]$ F) B1 U* X
) p3 i6 e0 C$ \; P$ eAPU::APU( NES* parent )
, L4 y# Y9 A8 ]. _{) a& d5 g$ B0 \; Z" t9 p
        exsound_select = 0;
! H6 `. p2 R3 f2 \; I$ a% p+ d! ~' L4 H! h. K! \
        nes = parent;
8 d3 O8 s  s" o; H. C        internal.SetParent( parent );7 A. W% o$ e* ^% q0 U

# G# L0 z. d- S2 F5 j7 y) f        last_data = last_diff = 0;& }' B& z( g0 F4 P
7 R2 \$ B9 c. H& h  V" }2 F
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 h; l) `' ^$ O5 i& ?8 C
+ h5 Y; \  I) C* ]$ Y7 ^3 `
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( n4 I- N2 m- F
        ZEROMEMORY( &queue, sizeof(queue) );
5 U% @: Y$ a, T6 w- I: |; f        ZEROMEMORY( &exqueue, sizeof(exqueue) );" Y' p5 b3 N  m/ f. W2 k& [
: _+ d' W( d0 M+ M) \( [/ K4 }- i
        for( INT i = 0; i < 16; i++ ) {
! P, w# e" O" X- i* e                m_bMute = TRUE;
, [# z2 y( ?4 E, r) |3 W/ [. f        }
! V- _" o! a, O5 X3 G) Y/ \9 @8 E}2 r9 i3 u- n' ~3 V- j

) J6 X, _: `- g4 g2 VAPU::~APU()
3 i! M( o1 v2 |2 f$ @( [{
' ~5 ~& c- G  g, k( i}5 C( }. u( a6 M5 m, u7 i2 K
) w* ?9 c4 }& w+ r
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
* _5 N3 y: C# C! R- {6 b% {' c{
- `! m* A- a1 ]! Y        queue.data[queue.wrptr].time = writetime;, C( s% R- d, Q$ \! \
        queue.data[queue.wrptr].addr = addr;$ K- t+ Q3 I- d3 E, p
        queue.data[queue.wrptr].data = data;
) k' |9 G/ `; [        queue.wrptr++;
8 ~9 z2 R' o2 @) R$ a        queue.wrptr&=QUEUE_LENGTH-1;
+ Q5 z; ]3 v3 P# D        if( queue.wrptr == queue.rdptr ) {
0 y  [, K& r- U                DEBUGOUT( "queue overflow.\n" );
8 }/ ~6 A+ v, b9 C( K# l        }
  B$ @9 T. U& n) e: Y2 W- Q$ `}
3 s( ]/ [9 ?; J1 O; x$ i& d
  Q5 H! j  \# H" W1 @9 LBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )" X7 y# ~/ V4 y; u4 ]& G7 c7 g
{8 `  o1 b& F  @
        if( queue.wrptr == queue.rdptr ) {
% f. a0 D, j$ j- j+ D4 j                return        FALSE;* b/ L# q% J: g$ K2 q
        }
+ O' R1 V' [) M( H" \7 E" h" V" ?        if( queue.data[queue.rdptr].time <= writetime ) {7 B0 T0 ?$ R; r; k1 u* |- I' U( L
                ret = queue.data[queue.rdptr];
8 G( E9 o2 Z( f& x- Z                queue.rdptr++;- r9 {. u) x% L# n8 j, O
                queue.rdptr&=QUEUE_LENGTH-1;
# b* W5 A' i, c0 Z                return        TRUE;- P& G) A* P7 M1 C+ B3 o0 ~8 K
        }6 d4 [$ u  s& L3 {
        return        FALSE;: d$ F- \" H; Q/ \
}; d9 `/ K4 \1 |$ J. J8 N0 h0 c

2 k% z) W# `3 B% fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ `3 B8 ?) B9 ]- Y) t{; F4 ]* c3 E; ^9 [
        exqueue.data[exqueue.wrptr].time = writetime;
& p4 P1 Z& K/ o( ?, B( u) Y        exqueue.data[exqueue.wrptr].addr = addr;
  [! ~8 v7 D2 r        exqueue.data[exqueue.wrptr].data = data;/ [5 @4 @: m9 |4 Q* `3 A
        exqueue.wrptr++;6 n5 j* h/ j9 ?  d) y
        exqueue.wrptr&=QUEUE_LENGTH-1;
4 k( H# ]2 P3 R" V8 v' f$ o        if( exqueue.wrptr == exqueue.rdptr ) {
8 Q6 `) w  r+ U. l# q+ b                DEBUGOUT( "exqueue overflow.\n" );
, Y0 D7 i2 O! X' K" w5 o( g* I3 v, d        }- U' J" v1 f7 B/ E3 I& O. T
}4 H4 T$ C9 S9 i* k! i* @
' J# C5 F, M# h/ c% a) V3 E
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
; h1 @+ y/ H2 }{
1 F( A+ V/ P  U9 \        if( exqueue.wrptr == exqueue.rdptr ) {
2 H$ v( |5 Z, [  W: h) p) o! C                return        FALSE;
/ D) ~. @. {. Y* @: ^  ^3 Z' g        }" \4 J% U; ^  k/ {% j9 m
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ U+ P) E  V2 o
                ret = exqueue.data[exqueue.rdptr];
: f7 h) b  E/ j" f: V& l6 j" [                exqueue.rdptr++;
5 c: j) Y( p% k, M                exqueue.rdptr&=QUEUE_LENGTH-1;
, P& c, ?9 W* @& T  N4 K/ _                return        TRUE;
$ h+ [1 m: b; m( [9 i        }
9 f- m* {% p7 E- J$ |6 T) |& P2 h        return        FALSE;
& C7 _& {/ i' a. h' W3 P* d}
7 B" d% P, O$ m0 t$ i7 O$ B6 F7 q2 X+ W+ b- i' _$ c* W7 ~2 v
void        APU::QueueClear()+ O! S9 c, h4 \3 }% D
{
& h. A5 Q0 u/ V/ J        ZEROMEMORY( &queue, sizeof(queue) );
& Y. g9 _7 b5 D& [        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 x/ H, J6 N) K: \2 K2 [
}
( X7 w& {1 L& w1 }/ T+ i
2 n- G- f) S7 O9 \; g* p8 Zvoid        APU::QueueFlush()
& s. a7 [8 }/ f6 d$ u! i% W. U{
; |* J- b) {; P) I7 P, ~9 H        while( queue.wrptr != queue.rdptr ) {
# u7 r. s) p& g; N8 Y                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: D4 R) {8 B5 Z8 T" r0 x                queue.rdptr++;
4 S" w: t0 C+ w2 A/ Z  d* z                queue.rdptr&=QUEUE_LENGTH-1;7 R& q; ]1 l, I
        }
6 j/ v" R4 a* Q% @- S; s
# U) b0 t! v& r% v: D5 z8 t4 P        while( exqueue.wrptr != exqueue.rdptr ) {: B( P) q! t# ]( A1 U
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: {* j: ^5 P4 O# k3 R7 i
                exqueue.rdptr++;1 S# F$ H+ B9 J$ n
                exqueue.rdptr&=QUEUE_LENGTH-1;! z! U: `5 S3 r" r
        }
$ j  O* G- v, W1 r}8 T! v5 e4 u- S! x8 n& m

/ X7 o( I' \# e( Mvoid        APU::SoundSetup()
: [7 p) Z. X/ [6 t* N0 {( H{
7 ]- g7 r8 H3 g        FLOAT        fClock = nes->nescfg->CpuClock;
( K( W5 j+ H. P9 ]        INT        nRate = (INT)Config.sound.nRate;. G0 e# E; h. m
        internal.Setup( fClock, nRate );
" M+ d9 R4 }0 `6 N# @) \+ y0 m        vrc6.Setup( fClock, nRate );
1 O7 N; ~& K2 n+ ~) R# ?        vrc7.Setup( fClock, nRate );. {. D) r: x) G1 Y$ L7 h
        mmc5.Setup( fClock, nRate );
7 k* ~3 c  U6 Y4 e+ k! o* A5 N+ r        fds.Setup ( fClock, nRate );
; n8 ~; i  G8 \3 e( w* L; C' W        n106.Setup( fClock, nRate );
5 n( H: X* \% ?; Z6 m6 C  O/ p+ ?        fme7.Setup( fClock, nRate );3 @# q# f: P& a
}
' Z- _$ K# @( |' R' E- o- S' t8 h! [# i1 D+ K
void        APU::Reset()
! b( e% u  m4 t) L( H/ Z{( z) p: {' r! c+ Z# C5 x
        ZEROMEMORY( &queue, sizeof(queue) );
- J$ W" v8 Q  y$ s, ^        ZEROMEMORY( &exqueue, sizeof(exqueue) );. }6 \5 ^0 \: [* c2 `. }3 M
8 B0 }4 e9 N9 _' }0 u" ^6 ?
        elapsed_time = 0;
# v1 Z! @0 V* i$ K
" U+ k, H+ }  u2 \5 q  }5 Y        FLOAT        fClock = nes->nescfg->CpuClock;) R6 i# x1 l6 `" T6 ]4 C# A+ N+ `  j+ q+ g
        INT        nRate = (INT)Config.sound.nRate;
# c% ]* T! \9 C  H9 ]) x$ j- ?        internal.Reset( fClock, nRate );
7 S# r! s7 m9 Z" j! I: [/ l. _        vrc6.Reset( fClock, nRate );
# W! d  y6 W- q' k( U+ o6 w        vrc7.Reset( fClock, nRate );
+ e+ F4 w* Y3 ^3 m7 `+ M        mmc5.Reset( fClock, nRate );' }/ j/ u( l2 i1 \4 a2 |- n% C
        fds.Reset ( fClock, nRate );
9 b% H( ~$ ]4 a! S; ?0 R! i        n106.Reset( fClock, nRate );; G! i7 n3 k: R& a' v' Q" B1 d
        fme7.Reset( fClock, nRate );! n3 X$ `4 x7 M1 H1 i
2 j( {) @8 ^8 ^; ?/ {5 r
        SoundSetup();  N, f/ t/ x4 [8 H/ Z
}' {+ E+ g) x6 k; q) v
2 u; T% }- m4 c  C; Y1 ^
void        APU::SelectExSound( BYTE data )9 c) C6 l8 Z! ~* h
{5 @/ M: O7 {6 r: {3 N
        exsound_select = data;
8 }; z. E1 }$ U' A7 R1 W}
: H; V: v/ D6 b% E/ h
$ R" N6 B5 d, }4 k4 ?BYTE        APU::Read( WORD addr )# G+ ~9 {0 K3 H! t$ B  i3 E7 c+ I
{
6 o9 Q4 u  `2 U        return        internal.SyncRead( addr );
9 P1 }  I/ `+ b8 [}
' j% v. q" p2 w; F" H8 v  g
) I" o: l4 L, [" O8 n7 ovoid        APU::Write( WORD addr, BYTE data )
2 ?9 X" g' ^# Q2 ]5 x6 ?{" o/ q! O7 ~  w/ `
        // $4018偼VirtuaNES屌桳億乕僩" X) g7 \1 o3 f3 T) ]  H1 T
        if( addr >= 0x4000 && addr <= 0x401F ) {# k5 w+ m- F0 q! _% ^
                internal.SyncWrite( addr, data );/ W2 r$ i* b" Q; q( D  r
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% \. f( k, o9 y
        }
( t1 X* g8 ], Z* a5 }! F) ~( v% W9 w}
/ j8 b4 j2 L! J3 C! n1 G' I9 O8 z; J) {3 L5 }2 P$ n
BYTE        APU::ExRead( WORD addr )4 B; B: n0 N; T% d6 t; k0 T1 e9 b
{
! B2 U5 C% X. }. DBYTE        data = 0;
! f) z; T! d$ c9 p9 H$ G1 H# b
6 w+ a% k: B2 G        if( exsound_select & 0x10 ) {
! G9 O8 Y7 E1 Y  x! N3 a' O! u                if( addr == 0x4800 ) {2 M+ O9 b5 s, e, X5 ]9 h; }7 s! G+ a
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ A* S+ B/ R# v1 O$ o4 a
                }
. z/ u; L4 ~% E7 ~4 ?* ~$ K+ F        }2 x) G# g1 y; V: h
        if( exsound_select & 0x04 ) {4 v- y2 x# M, I+ r9 t3 e  F1 O' g
                if( addr >= 0x4040 && addr < 0x4100 ) {6 y; @( r7 S4 i3 R  o; O, K1 Y
                        data = fds.SyncRead( addr );* d! }' f7 @) i
                }! i: z( }( ^6 ?7 g* J9 Z+ X0 f
        }
# k5 |7 C/ M& H, }  s1 w/ s        if( exsound_select & 0x08 ) {
% C* |4 q  C: o, h# [" B* y' \" `                if( addr >= 0x5000 && addr <= 0x5015 ) {# C( f8 Y* o% K4 H* L7 z
                        data = mmc5.SyncRead( addr );4 [. O) A& v4 c/ _. ?; M  R/ W2 D
                }9 a9 z! Y0 M0 `" y* Y- J) f
        }
% g" E- z% f) O5 d0 r4 W2 g  Y* [0 p4 D7 ]+ c) V  b3 C7 R
        return        data;
/ D! g: w7 G% [' }9 J( U% m! X, b}8 F/ H. {- W. P
+ s) w" S9 i5 H3 Q0 I9 _; P
void        APU::ExWrite( WORD addr, BYTE data )7 x  M- l/ r) A( N, q
{5 m9 Z5 x5 ~- D1 k9 c. z
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );" Q3 P8 ^& f  A2 d2 w* r. |5 \( Y

# w$ Q# Q- u4 R        if( exsound_select & 0x04 ) {
) Z+ O; P) N' |: Y5 o                if( addr >= 0x4040 && addr < 0x4100 ) {6 G. T( b6 g* F' T( N
                        fds.SyncWrite( addr, data );7 |: Q$ j; Y- M$ Z: F, k
                }
: p) A- Y6 _4 T# N% m% z        }4 s# z9 U1 C/ \" ]  y( Z& n3 y0 U
' G4 q) S( i$ t# D4 x# B
        if( exsound_select & 0x08 ) {. ^2 X+ w* {5 V) w2 V! w
                if( addr >= 0x5000 && addr <= 0x5015 ) {2 }# Y+ e+ q4 p' N$ n5 ~5 X) G
                        mmc5.SyncWrite( addr, data );/ j$ p8 F% J& B
                }
+ i- m5 B* C0 W6 W9 N        }
( C' }- b5 u& Q}) [8 X# z* |! P+ A( ^

# I: l) X5 c) @$ v5 ~void        APU::Sync(), D8 l! D- y/ w4 C! D8 F& C
{
+ B9 j* V* ]' e, @}# l" ?; C& r: P1 j
; E6 o3 _2 w/ R: [1 [  ~; c
void        APU::SyncDPCM( INT cycles )2 b, @1 n4 P- m7 L  ~5 u6 s
{
1 ^5 J6 \: \0 @5 Q" a        internal.Sync( cycles );
. ?' W. ]. S/ s5 L6 }9 C! [' [; X6 v; q" g# F
        if( exsound_select & 0x04 ) {
1 W  F8 f' h  [8 m5 u0 H7 Q0 I) l                fds.Sync( cycles );
! x& M1 m. J! {        }
9 D' t9 o2 t# E/ E        if( exsound_select & 0x08 ) {
, e7 e8 G( B, ^0 l7 Z                mmc5.Sync( cycles );
6 V5 }2 \' k  A3 }- |5 l0 e3 G        }/ h  U# p6 `7 N1 C- H
}, m9 u7 j! L3 T, r

# D) ^  f7 ~3 N/ ^$ {: x9 dvoid        APU::WriteProcess( WORD addr, BYTE data )
( o5 B4 V3 q& p+ I8 p{
( X. {8 M  L! ^5 Y' d. i        // $4018偼VirtuaNES屌桳億乕僩
' M; K; Z  C9 @2 W( N        if( addr >= 0x4000 && addr <= 0x401F ) {3 A$ m6 U" \  G
                internal.Write( addr, data );/ v" f/ w/ ]% c: ]
        }
9 ?- t0 w9 }4 [: c}; l5 E- |# h0 A

& a% y6 n; z* E$ n' J& @void        APU::WriteExProcess( WORD addr, BYTE data )) M4 B2 s9 @$ h: Y2 T/ r) `
{
5 K. h( o$ k6 A! s' K3 h" q, h        if( exsound_select & 0x01 ) {
% R0 G3 |/ S6 t, y                vrc6.Write( addr, data );" D& c. D% ^) S
        }
8 ^& H8 O8 r, h        if( exsound_select & 0x02 ) {
$ \8 g. E  p* E$ `+ P% l  l  x                vrc7.Write( addr, data );
6 S2 n& r$ g4 Z- j; q; l5 L        }
" _4 R' {8 s" c9 w        if( exsound_select & 0x04 ) {
& T' [6 L. U1 u5 H, s( k                fds.Write( addr, data );% G* T' O1 {: B9 o4 o) @
        }/ R+ I$ @: z- ]# o
        if( exsound_select & 0x08 ) {
8 F: |& l4 q# r  ?2 l' q6 o- m/ s                mmc5.Write( addr, data );8 @- R: B8 n5 `: C4 _
        }
& P. p- ~' z; y; D        if( exsound_select & 0x10 ) {0 H- Y/ l; n, n5 r" x
                if( addr == 0x0000 ) {  c) B" D, [( x3 d* q& @
                        BYTE        dummy = n106.Read( addr );+ m! J; [4 ]$ k2 {- @- A# }
                } else {* k. c' R7 O  ~, T9 Y" D% ]
                        n106.Write( addr, data );5 e1 w8 J8 M6 J! `0 G1 Y& o# s
                }
" Z9 L( R  w* a' l) y        }
3 S9 i( r" @0 E! o        if( exsound_select & 0x20 ) {( B) z" z) y. g7 z
                fme7.Write( addr, data );" ]! q' ]! k  h, |* C
        }
" k7 ]. F$ X2 R  P% n0 K" r}1 K! L3 [8 l2 g! a' M

9 O! v3 D( w, S) y. s" l8 ~5 lvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )0 p9 \/ x0 [8 J. q: t" [& y3 u
{
6 j2 V9 t& [2 Z# wINT        nBits = Config.sound.nBits;( h8 O; d  [( F7 Q
DWORD        dwLength = dwSize / (nBits/8);
+ q) L& q) w4 X4 \( T+ TINT        output;6 `. A! z5 P- ~- ~- x4 p/ ]& F3 x1 e+ k
QUEUEDATA q;
4 N7 M. T0 s$ x6 x9 h' QDWORD        writetime;
5 R! ]1 C: ]( v) e( T/ v2 Z6 g% g  y$ i  s# e9 }! N3 K  Z
LPSHORT        pSoundBuf = m_SoundBuffer;
! e* y* J8 s5 _# S  S; A! ~% OINT        nCcount = 0;4 R! j+ u. k' s( [' D; v" U
+ \5 m: L1 r: N9 w$ Z
INT        nFilterType = Config.sound.nFilterType;
3 E/ D. f7 ^, Z+ ~  f1 g% T0 ~; x, I1 e2 X9 u" N) t0 I
        if( !Config.sound.bEnable ) {4 X* S# ^/ `3 Z
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
$ }: I, W8 Q9 j8 c" t+ o                return;
8 z! _5 M" U( ^; o        }4 V8 Y. R9 D, y$ u2 i2 O2 o5 O

8 ]. B' e% H* E' U% B- e: c        // Volume setup/ s  Q" i: j  M; J, m
        //  0:Master6 y( C* l' b7 {! `6 k
        //  1:Rectangle 1
9 \& {* r5 H% O! [) a* G- p        //  2:Rectangle 25 o7 X) c- L$ N* e% `: E
        //  3:Triangle
2 V9 \' R+ b, ?( L& Z: ^        //  4:Noise
/ |" v2 j& d0 \, e1 S0 y        //  5:DPCM* p7 @# Z: X2 d
        //  6:VRC6- O/ s+ ~) c$ b/ l) H- x
        //  7:VRC7
  r; J8 P. n9 x1 A& t7 e4 Q        //  8:FDS
$ p, E2 A& }3 |( E' e7 h8 N/ N        //  9:MMC56 p7 i3 j+ I( Y5 |
        // 10:N106
3 p/ R$ C8 m4 U        // 11:FME7
2 V1 w- u& r9 V( A7 l        INT        vol[24];
' L- k7 I. g( n: i$ K, ^        BOOL*        bMute = m_bMute;% i7 [& G8 D/ v7 d! H0 ^; K: `; v
        SHORT*        nVolume = Config.sound.nVolume;
* X8 v/ \- w5 V6 H) ?# |1 }7 x. k
! |  U6 a- ?% I8 c        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
9 @7 j  q7 f8 H( x, Q
8 t* G4 C- g4 L+ k/ T        // Internal
2 _5 _2 q, s. ]7 r" Q8 @3 r        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ I4 a, _4 I7 R, k- G8 t% Z9 \2 m4 {
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
) k, v- m' R3 S6 I  j        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
6 o: h9 O/ A8 W* j- O. T! o        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;% l7 s: F. W* M) ?: g* j
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 }) E/ l% I5 B) e, J3 I; Q2 J* V: w+ U* V* O1 k7 P; I
        // VRC63 ]& M! L. O5 E& B& \& ]. |
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 i) w: e% ]- r9 h, ?
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 E# D' R/ e5 T$ m# P
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: O7 e: b0 H: s4 s' @  A  e

4 p# p1 O- F2 F7 M+ V* V1 U        // VRC7  [" Q; g4 R, E# q: `, b3 @
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 a7 [* G" S/ z4 O0 k5 A
9 n& Z) ^7 X5 `  v2 b: ~7 V
        // FDS* W6 f  B0 a3 t# o1 D
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ P) d4 a6 d" ]- ]9 [
6 i0 w, @; Y5 U6 m# d. T4 V9 v0 @8 n        // MMC5
8 j3 ~: |7 M3 @* _        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ n  @: v: c! M
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) b( f" {: q7 L# D        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 X6 U  P" e# v2 C, G, x& N% W5 s
9 V5 X3 X: d4 m" U$ X2 P' O9 c* _        // N106
  @. s/ x! B! a6 a- s        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ M6 `" v! L- U) ^
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ b4 E4 _; Z/ |0 Y+ c
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 b/ g) [$ I1 H8 U! O  X: `8 \9 k( r$ p
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 u' N. Q$ w' q. X. I" b) p
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ T( T0 ?- p6 D6 ^6 u# T        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 I# P" o( E0 @/ f5 T/ Y$ D, J        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, Y( }% U" l" k% s5 ^: ^: H
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# }9 E0 c+ f& T' w, G) ]  L4 P; m9 Q2 J7 x" f; R8 Y
        // FME7( {) J3 p: G2 X# \
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ P2 B) ]2 f9 o4 x/ H: z
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 }9 Y" ^5 r1 N
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ C! l0 e4 u7 d1 Q0 T6 H9 u6 l9 F0 s! y: s: P+ {
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;6 I+ L, g: t' }" X/ e8 F7 G
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;+ T; `( i7 Q8 A+ p' j
0 A1 }3 K" w, E, N
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- P: \; f7 L3 q! m& P- ~        if( elapsed_time > nes->cpu->GetTotalCycles() ) {% S7 S/ b/ _) u1 k3 z2 r9 R1 s/ }. e
                QueueFlush();
) G/ x, H2 e) [% Y+ O2 w        }
/ a& w+ Y7 R( V5 A9 f3 Q7 F, y9 K5 M) i# p" d& S* A7 W; G
        while( dwLength-- ) {) O! R: a# i2 f( Y! U9 U
                writetime = (DWORD)elapsed_time;
/ U9 @; v+ y' _, d) c, }
# t# n6 R1 b( m, F1 ^1 s  v                while( GetQueue( writetime, q ) ) {
" P0 I+ I& x' t                        WriteProcess( q.addr, q.data );7 R9 @- p8 b% _+ A
                }% e1 t. Q+ D! f0 ~
# ^& p, s# l4 f) r9 E
                while( GetExQueue( writetime, q ) ) {
: c- }6 q7 O- s* F! B$ r- P& N6 O                        WriteExProcess( q.addr, q.data );; {! N) c# c$ p/ I# T  o* b& k
                }6 B* o4 z/ n- z2 Y$ e

6 f$ h/ b' g( p9 t! g                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7& L, `8 R/ M: q2 |+ `3 M: }
                output = 0;! i% o; \) `0 e1 y5 Q
                output += internal.Process( 0 )*vol[0];
! w. u) S. r" {6 b$ S$ ~                output += internal.Process( 1 )*vol[1];- X& S' F, ~* U" M
                output += internal.Process( 2 )*vol[2];
* {7 w/ \4 f0 [                output += internal.Process( 3 )*vol[3];# Q7 E( H! O0 }7 Z
                output += internal.Process( 4 )*vol[4];
+ z4 Y7 k, c8 Q7 ~* |' r0 I% S2 g, j( G, |
                if( exsound_select & 0x01 ) {0 ]0 q  |1 p" l2 V% s" N
                        output += vrc6.Process( 0 )*vol[5];
6 a: }4 q3 B; b) C6 x+ g% r                        output += vrc6.Process( 1 )*vol[6];% l, h- A; i' N9 C
                        output += vrc6.Process( 2 )*vol[7];
" g$ |: s, o1 C+ D/ v2 s                }4 z2 p. o3 c' a* A
                if( exsound_select & 0x02 ) {
; c$ g6 ^; g4 t                        output += vrc7.Process( 0 )*vol[8];- ~% T, a  V. y# Q: d& d
                }
3 J* U9 F0 Q2 u5 Y                if( exsound_select & 0x04 ) {
9 t& A# ?7 q+ T6 J: V                        output += fds.Process( 0 )*vol[9];
9 |6 }: @- [1 Y1 J/ c( ~6 u                }
+ P/ F. G! L# b; K) n                if( exsound_select & 0x08 ) {0 W" l4 N7 O) e+ q: `
                        output += mmc5.Process( 0 )*vol[10];
+ b6 ~, |  ?- P2 x5 n                        output += mmc5.Process( 1 )*vol[11];
+ c" D6 l! M3 D  @  c. c* K3 P                        output += mmc5.Process( 2 )*vol[12];- A7 K' M( |! I1 ~5 h0 ~$ ]7 `
                }8 a& l& f& }9 a/ H, ]: l2 g
                if( exsound_select & 0x10 ) {
( ^; g' B; q7 ^( x3 s8 J  s                        output += n106.Process( 0 )*vol[13];
* w, f, [) W. `: C                        output += n106.Process( 1 )*vol[14];
7 W, ~+ X8 u/ L3 |9 v- b4 ^( K                        output += n106.Process( 2 )*vol[15];1 c5 [7 |2 w; [, a' T+ L# v
                        output += n106.Process( 3 )*vol[16];
( f4 R/ \) S0 p* `: Q% j2 ~                        output += n106.Process( 4 )*vol[17];6 N! M) x2 N( \
                        output += n106.Process( 5 )*vol[18];% T9 ~5 G3 R6 P& Y  Z  |, a
                        output += n106.Process( 6 )*vol[19];# k$ r; p2 m4 j0 [
                        output += n106.Process( 7 )*vol[20];- Y( V1 J% z' x, p; W% g) N
                }: H, {& B/ U: n! L* U
                if( exsound_select & 0x20 ) {
" M1 u) x# Y, C: K! y                        fme7.Process( 3 );        // Envelope & Noise
/ b/ h* s$ w4 r- o# m                        output += fme7.Process( 0 )*vol[21];! r! F3 B- i2 Y4 j4 N
                        output += fme7.Process( 1 )*vol[22];$ |- E% l6 H# \
                        output += fme7.Process( 2 )*vol[23];
0 K2 p' x& W8 Z7 ]4 ?                }
4 c9 ~. g2 \  _: Q) N; t' J
) c; f0 _  l4 h7 m- G$ P% G                output >>= 8;& r; p7 p& T, l; h
( y* Q! V! }& J7 T4 d
                if( nFilterType == 1 ) {: Y  K, q) O- }* f2 z8 `: S& D7 |
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
  Y' d! d8 V+ M$ t5 W+ O                        output = (lowpass_filter[0]+output)/2;$ J& l' a' v  ~' \3 Y: B" i1 W+ r2 o- ]
                        lowpass_filter[0] = output;) K1 ?; V: M4 v' v( \
                } else if( nFilterType == 2 ) {
- o; L6 a2 H6 s- Q                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
" R: W+ |; o; V* T/ i- W) q                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
9 T; a) x: [7 n7 P                        lowpass_filter[1] = lowpass_filter[0];( `: M* \/ u3 ^/ v
                        lowpass_filter[0] = output;" ]/ e) D7 H$ w6 N7 B# y. @( W
                } else if( nFilterType == 3 ) {) W5 P1 t  h$ y: @8 s) ^% p
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
: d" J' j; b! z0 J                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ o1 o( f: z+ E% q2 {" z" s
                        lowpass_filter[2] = lowpass_filter[1];& R8 x( U5 ~0 m
                        lowpass_filter[1] = lowpass_filter[0];- y( t4 P1 l5 @! u& v  A; W* ^
                        lowpass_filter[0] = output;" H! e, \, y4 w8 y
                } else if( nFilterType == 4 ) {
! B7 o( ]* t) I; k7 @                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
: N" V2 j5 V% H! m7 _6 P" i                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( j$ ~9 T% r3 b                        lowpass_filter[1] = lowpass_filter[0];
& f" f  _# r6 E) O4 ]6 y                        lowpass_filter[0] = output;
9 P6 h) x. E' y                }
: ~) F4 k9 |9 c4 V4 M6 L' E- p4 `$ r( ]% i: |' S$ u
#if        0
  `" z' Z7 L3 L5 D: b" n: P" ^                // DC惉暘偺僇僢僩
! P+ a1 S; M2 Q% y                {2 N9 z* {# [) s
                static double ave = 0.0, max=0.0, min=0.0;
! ~0 T. q  g1 W  t" `4 @& ?                double delta;
" i0 K" w1 o; @                delta = (max-min)/32768.0;
. h2 x+ n4 R9 W) T# y                max -= delta;
$ f% l8 l: m, a$ Q9 a2 A+ k                min += delta;1 q' @6 K* N! y3 T
                if( output > max ) max = output;
" N- s0 ~" n2 a$ @                if( output < min ) min = output;
3 w" o; p  X, }                ave -= ave/1024.0;
+ N9 ]0 a4 g/ o                ave += (max+min)/2048.0;
1 J5 c4 e- _2 V, r' W0 w" X$ R1 F! q                output -= (INT)ave;
+ ^1 L0 _, [/ t                }
4 Z. e8 P- z3 P( w& h3 Y#endif
3 x4 V% p# _1 p0 P#if        1
4 z1 T, `- o0 M$ e  ]8 `                // DC惉暘偺僇僢僩(HPF TEST)
; [# `; X4 _- d: C4 y9 F, ~                {; S* d8 Y2 Y) x: X6 \# P
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);" j+ h+ S/ s7 I# [3 I* j
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
6 a+ B3 F! Z  L, C- L                double        cutoff = cutofftemp/(double)Config.sound.nRate;! B* M5 p% J; T* M$ w( ~2 K
                static        double        tmp = 0.0;4 S9 j  `4 {% f. ?
                double        in, out;2 @- q2 `$ j8 i# i5 z, J

% d- P% ^8 E1 {9 m. |                in = (double)output;& ~  h1 x; v& g3 z" G+ [& j
                out = (in - tmp);% E* q0 }' z  o
                tmp = tmp + cutoff * out;
9 e9 C+ {1 d# U. M0 X/ m6 d  i4 ?9 _+ M, r
                output = (INT)out;( p$ i8 K9 @) F" q4 h
                }: b4 h" d; m) Q4 T
#endif
) j3 D# q9 L' Z) j#if        0# \, K) ~9 j6 L* Z* J( }7 @
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 Z7 C( B. v5 S' S
                {7 A6 O3 a; d& w$ |* W( a
                INT        diff = abs(output-last_data);, J4 p, L  M0 J
                if( diff > 0x4000 ) {& l: ~& |& G! e6 u2 ?
                        output /= 4;" U9 T2 {) d' P* a. c
                } else , U$ [3 c8 u& O* d! g, B+ `% Q
                if( diff > 0x3000 ) {0 b) g( P! ~& ~' @1 a7 d5 i$ X% X! f
                        output /= 3;4 j$ o$ v5 ]* [- H; d* P: @
                } else
7 r4 D  f: z. @3 L# J0 m. X% d                if( diff > 0x2000 ) {
5 k6 O8 e# X0 L3 E                        output /= 2;! S+ Z. u' ?1 e8 \
                }; W% X, C; x- e: |
                last_data = output;& {$ Y# W2 `1 ^8 r  N, R" u9 L
                }
+ U" }0 c" [( Z9 S8 I5 e#endif; m/ L1 E5 D% y' g! D  H" M
                // Limit
) d) o- W! m3 O( @! _$ b# s                if( output > 0x7FFF ) {* D; ^/ U$ A. ^# \
                        output = 0x7FFF;2 r( n; U1 Q4 Y+ |2 [* ^, n6 i
                } else if( output < -0x8000 ) {
3 r8 d* H3 X4 h, v& ]* L  h                        output = -0x8000;% v9 j) c4 v. a8 ?" v6 W
                }* S; H  r. U4 ^5 v
* b$ b+ ]0 s9 \
                if( nBits != 8 ) {) ^% ]$ R! B% @6 p' ~
                        *(SHORT*)lpBuffer = (SHORT)output;1 x! H2 V- Z# F" r1 U, F5 d
                        lpBuffer += sizeof(SHORT);
7 `0 o5 l) t% X$ r" E) k9 ^" c                } else {
; Q) M! Y1 ?- |, d6 I                        *lpBuffer++ = (output>>8)^0x80;' i* n( v7 m9 N; S9 n
                }: K' n1 Y0 u8 e" k9 a
% p! ~0 c$ [; }3 G$ P* t5 V; Y
                if( nCcount < 0x0100 )  u( {: ?! r* `# x
                        pSoundBuf[nCcount++] = (SHORT)output;
. J7 `7 R3 A# _2 U& R
9 O) V2 k1 q4 [" J( e. e//                elapsedtime += cycle_rate;& W( }3 f4 J+ |6 t9 w  u  V
                elapsed_time += cycle_rate;" h. m' Y$ I# D
        }
% @1 N( H: E8 Q; h, H: t, W, T
* `! H1 U0 d# t#if        1
+ j; E: u8 r' _$ v6 B+ V        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% W% M8 a) t4 w; Z) z' R                elapsed_time = nes->cpu->GetTotalCycles();0 O- M1 b2 S  B
        }; b' r. T; I/ C; i
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
, }9 I# f5 R* _$ D3 D                elapsed_time = nes->cpu->GetTotalCycles();
/ n2 k! Q4 F' a( z' ^        }, \' ^% [7 |$ ?2 n  r
#else, I$ e; S7 }% J+ u- G+ N: J
        elapsed_time = nes->cpu->GetTotalCycles();
7 Y6 A( r* {9 m8 S  m4 |6 a#endif
  k  s; h  W7 @) H0 n$ [}: l8 U5 _% O0 K( v7 A
" B9 u2 Z" V/ b9 h4 K
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
6 m# N* m( C, LINT        APU::GetChannelFrequency( INT no )" \  D( M9 W8 T
{
# C- `; {  P0 N) t( o        if( !m_bMute[0] )
. L* b6 s6 x- t! Z- X                return        0;! A# s0 g  n0 \

6 ^% `+ s9 P+ u8 S0 B$ ]        // Internal# U6 `7 e) H7 C% Z. W; n8 w/ N! c
        if( no < 5 ) {4 F% C& `3 ?9 r) o2 |  N
                return        m_bMute[no+1]?internal.GetFreq( no ):0;  N9 W; r2 t% a+ y2 U7 Z
        }: @3 c! D3 f' P9 M! l+ b3 D
        // VRC6
  w0 f- {0 O3 f7 N        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {  j$ p2 E; u: E) u/ m4 v# T9 r: N
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
- E) [2 P( ~9 I: i0 }% O( s2 H* U        }
' k( a) r8 ?: d) O' y5 c        // FDS( [, B8 l8 Y" j: k- H7 M2 H
        if( (exsound_select & 0x04) && no == 0x300 ) {
1 X. }! d/ W5 F( x                return        m_bMute[6]?fds.GetFreq( 0 ):0;
' A- P- I8 \" k- w+ O        }7 t3 B: K  H) K5 b
        // MMC5
% L$ J; K4 }! D# Z1 p" s' n# n) R        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {8 b( B1 P$ ~5 O( n/ q- d9 T$ P
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
$ `; K) {2 B* G) ~* ^        }8 ?1 w* R# h- @+ `2 V
        // N106
7 e0 K9 a! U; D, _% y8 {. F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
% M3 U. g4 L! l! v6 \$ h: ~9 k* f                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;  p; i: o. E6 _. k5 @- @5 \9 q3 Z( m3 v
        }+ X' M8 u% J% s9 U- @& W2 R+ z* `
        // FME7
4 ?0 g: Q& p5 w; I8 m! ~( ?& i2 \. D        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {8 r0 ?0 w5 w) c+ n( c+ B. i# Y
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;# i) }  m3 c5 M5 o' l3 J
        }5 M" A9 p( f7 j( x6 c
        // VRC7) Q* c9 p1 r' P& j
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
5 D+ G* ^! k: h7 j- F& H5 l0 X4 K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ {2 w' e/ [' d: g" W8 L1 w
        }, [/ y, [/ a+ v
        return        0;
6 l: w2 S5 Z/ ?. k6 \0 A  a}8 P% i$ S! I, s' X

  k: [/ w5 o4 N/ `  G// State Save/Load
* o: m% I9 w, z& d. s6 p( k! evoid        APU::SaveState( LPBYTE p )7 |! v+ C. C1 L2 @6 `/ J
{
2 y9 ]! w. C. {  x#ifdef        _DEBUG
4 O- Z6 q4 y& X) v4 ~: T6 b# ZLPBYTE        pold = p;
1 e! p1 C1 x6 N  O#endif
  i4 `9 t; |1 h# H4 q) b  J3 j7 Y4 \) Z! I/ W+ q) ]4 k
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞$ g* G0 ^9 C1 i# E7 O. V
        QueueFlush();1 D  v3 W' s: C5 t( p4 Q" C3 d7 c& f1 l

) l( _+ u# `- C: ~        internal.SaveState( p );- N% S8 f; b7 `: Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ E* E: i- V. a0 l" B6 w# n4 z0 K/ n
        // VRC6
  }: Z5 ^6 T0 W% w: W- g        if( exsound_select & 0x01 ) {
1 _2 J( k! ]: e$ ?* t                vrc6.SaveState( p );* M5 T: B" h' m* t
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 H" A* U! @7 l$ j
        }
, N: R5 I, q1 N( D; w        // VRC7 (not support)3 h) }4 W. w& L# O- U9 W
        if( exsound_select & 0x02 ) {
* i& g2 F* b2 J( c                vrc7.SaveState( p );. O! \( c% ^, {: q! @) r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 m( E& z2 p4 ^8 x9 t2 L$ T        }
) s+ m$ l+ w8 }+ ~% @* h        // FDS
- o4 ^6 D2 N2 E4 Q7 J        if( exsound_select & 0x04 ) {
& a7 s( [9 Y) p6 b                fds.SaveState( p );
0 j0 D. [2 T8 P) e3 I6 U* l: h: S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 m) X5 v+ S0 _9 B5 U" p7 U
        }. y# u" J* `+ y: D
        // MMC5
& }1 ?- f7 @) E3 p) K        if( exsound_select & 0x08 ) {
# v! X, O" Y* S* H& j, k; a0 t+ |                mmc5.SaveState( p );
6 Y% k% M. G# o2 b6 W1 m                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 F- C: w& x3 Y+ f4 u* t3 i5 a        }5 _* Z  J  v) t, e
        // N1069 }& e/ Q4 v2 F7 c7 t! a" `
        if( exsound_select & 0x10 ) {
( u7 S8 k! c( m7 X                n106.SaveState( p );
) U% i" @# e0 \% e                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, r) P/ h8 ?- J4 i3 Z3 e1 q
        }+ ^" ]7 a, o9 M8 W! t. C6 {' C( x  }
        // FME73 N  a1 i4 Q; k
        if( exsound_select & 0x20 ) {
6 L& ^) y' P. T0 q" M& j7 d$ w# f                fme7.SaveState( p );% N5 V" Z5 ?9 @9 x" \4 \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. y7 R4 O2 Q' b% ?3 |" W
        }
: i8 R& n8 Z  A! G3 _+ T- D7 z3 S, |; u0 |; q
#ifdef        _DEBUG
- q) Z6 Q0 b; `% E" w. T. b1 WDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 i5 t; F! f8 g2 w1 \
#endif
) B2 K; V2 ?# h2 V}* I; Y" ^9 [: A
$ T! a- P2 Z/ G
void        APU::LoadState( LPBYTE p )/ `1 @1 a5 s. r; g, N7 m; F
{
, ?( |! `9 d( v1 Y5 e" y1 o, E3 c        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
/ `" l5 s  ~  X6 `        QueueClear();
. n* _7 ^4 q9 h( T5 b
6 Z8 ]' Q- O  N3 K* D* B4 V        internal.LoadState( p );" f2 p0 S" }6 l5 d  ?
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- V6 w5 W* R7 e  B1 j( j
  J" v/ u% R/ S5 w$ Z9 d- N; ]$ t        // VRC67 f5 y' \5 ^0 ?+ b& C
        if( exsound_select & 0x01 ) {
5 k& N& G- b' V8 I4 D: O                vrc6.LoadState( p );6 y5 S! x* o- F7 Q/ C
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, V1 J# l8 w3 ^9 Z& U+ D$ ]
        }2 o4 o, _- X' n: D9 h
        // VRC7 (not support)
) s1 M% p4 ^: S9 N% M% k: T6 e        if( exsound_select & 0x02 ) {
! D1 ?3 n& y4 c( e( B; J0 U) B: V                vrc7.LoadState( p );, W0 y# a6 N8 x4 f% ^3 i
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, l% E9 c6 B6 B7 N* O7 O6 B  a+ Q
        }: w6 f; _0 \6 ~
        // FDS
1 Z; z8 y0 ?6 y        if( exsound_select & 0x04 ) {2 Z. D$ o! K- Z" g
                fds.LoadState( p );* [4 G( W/ v6 P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 C/ \9 r9 h1 A3 p) U9 r        }
4 ^2 S+ _4 v+ i5 U9 T1 V        // MMC5
/ ^+ G: {: G0 w        if( exsound_select & 0x08 ) {
# Y0 z( L, m3 u                mmc5.LoadState( p );
* Z4 U' r- p7 f# c- o$ F* s0 i* ^                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 `6 Y# G. K8 r6 m7 X7 Q- B5 J
        }# \/ s' W' L4 D$ S7 i
        // N106
# R1 v  {7 z" ~8 z: J$ w        if( exsound_select & 0x10 ) {& ?3 Y* u/ J% Q9 V
                n106.LoadState( p );" C) U; r# J+ e5 }+ }$ @- Z/ [* n2 Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 ^* k9 \, t, l! ~" @
        }  I. c% C; G2 t9 ?6 C* x
        // FME75 R: Y* f: ~- D
        if( exsound_select & 0x20 ) {4 T7 |( o/ I1 s0 ~$ ]6 _) ]2 N, P
                fme7.LoadState( p );
  P( `# B0 V4 k: ]( x& d. X  i                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 p0 ?+ y8 x* d1 _
        }
2 ]; @/ f" y/ e1 {' j. J3 O}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% P' b0 B& S3 N! a可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ P5 L0 T' q- P* x% p
感激不尽~~

! Q- d3 F7 e4 d+ R恩 我對模擬器不是很有研究,
0 d0 J/ r: ?# z7 `) t' c% k/ ^3 ]雖然要了解源碼內容,可能不是很困難,; |  _+ q$ |' c, i3 F" ]" Q# K4 j
不過還是要花時間,個人目前蠻忙碌的。
2 Q- _# T7 ]# c4 G& [7 W  a8 M
% `1 K7 n; r9 `- r) c- u- {& F3 c9 B給你一個朋友的MSN,你可以跟他討論看看,- v5 L+ e4 T9 F; p% f
他本身是程式設計師,也對FC模擬器很有興趣。; C( S; c! J& f  y
; z3 W7 z5 D5 c. o; L
MSN我就PM到你的信箱了。
4 }- W) e* |/ ]% [; q1 E: t2 I6 j9 `0 g$ K2 n
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# o- d7 R" l9 U# v2 d呵…… 谢过团长大人~~
+ A/ C0 r" i7 [- `  N9 t6 b
2 `% x" O( z  S3 s* ~
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 @5 T% i3 p1 I( p; e) v. r团长的朋友都是神,那团长就是神的boss。
7 w8 |7 }3 Q! _$ b/ k
哈 不敢當,我只是個平凡人,3 _/ ]* b  w5 g. Y2 M5 i( I  C
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
  L2 f, e) Z8 K6 y4 A5 _/ QZYH4 C# w' t* `' l5 I" T3 s5 `+ z
QQ:414734306
, W) k( u, h" J$ V  R) j7 V/ `Mail:zyh-01@126.com. H/ n8 v8 K3 V5 |/ S, Q0 I
9 s$ f, P, i' {  @4 T$ J, I7 j, h9 D
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! {5 a6 L/ V( |7 }6 H$ J4 t再次对团长大人和悠悠哥的无私帮助表示感谢~~

5 t5 R' ^9 q( B- N' [  x不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-1 12:31 , Processed in 1.092773 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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