EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 d0 q8 l* ?' S( i" @, g' ^+ r楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ j$ m8 N2 i$ r  q* f0 d5 f9 _
这里有相应的模拟器源码,就当送给大侠了~~  f% w3 }) b6 E% u- u5 W. v( K7 C! n
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
! R" |; t; N% M0 n1 P& y能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 `/ q9 q+ A% P- D1 K6 {  y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: q3 d- H; i6 X这里有相应的模拟器源码,就当送给大侠 ...

, B1 C: A8 Y, I7 h+ [, u. y5 c+ N+ f聲音部分(Audoi Process Unit = APU):
1 ]" t" w: g) N' M$ E& p( v' O# H  J. U.\NES\APU.cpp
6 f# K' b# g  U$ q.\NES\APU.h* ?# R, A; d- a
) Q) {$ g- f4 a5 O3 H' G
' X8 \$ F% r7 O$ L
影像處理部份(Picture Processing Unit = PPU):
' _6 K6 f1 @, R# X2 J% g.\NES\PPU.cpp3 L3 m- B( r7 F7 h. G) C2 e
.\NES\PPU.h9 G7 {5 x5 H4 ~' E8 ^
# ?$ R6 f  P' g8 p2 o
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
& W' E5 h+ E2 r9 Y(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 Y8 Z. s  {- Z, m) q
//////////////////////////////////////////////////////////////////////////; }. {$ ?; ?6 s8 i: Y9 ^
//                                                                      //
/ R- @1 @! S: H% {9 r//      NES APU core                                                    //
0 s# U$ h1 P5 m//                                                           Norix      //) l# r" b( P' a, m% i" d
//                                               written     2002/06/27 //; ]) P; ]  z, R2 p% {- j: f
//                                               last modify ----/--/-- //4 i" C0 v- R, J# c5 o' u
//////////////////////////////////////////////////////////////////////////" k3 F( Z3 X4 G4 B+ o" f4 z5 n
#include "DebugOut.h"
4 E0 y$ S: K% b6 e7 [/ A#include "App.h"
, W0 E; I, B! }, W#include "Config.h"
( t; ^9 B4 W  X0 q4 G$ \
# E  |, T/ v4 z#include "nes.h"1 J: t! \* X# C9 _* k3 y' j
#include "mmu.h"
" j% C3 p7 M" v5 ^; V) V% [& u, p#include "cpu.h"
. O9 o- m+ N4 a% ?#include "ppu.h". l$ F0 |- w# ]: n5 B. o
#include "rom.h"+ p- [* C; w0 I
#include "apu.h"; K4 m, z4 h, P, k+ w8 j% z% M, y
9 V6 Q# c1 n" M8 R) K1 x4 |
// Volume adjust4 x2 x4 F( j! G
// Internal sounds# F. s, ^  B- F$ m+ g' v5 f
#define        RECTANGLE_VOL        (0x0F0)
7 a7 d7 k5 D( \6 Z" b* g6 T#define        TRIANGLE_VOL        (0x130)- _2 E" x& Y/ z* g6 Y8 l6 y1 g
#define        NOISE_VOL        (0x0C0)
9 w* V' m* ?1 t4 B. P#define        DPCM_VOL        (0x0F0)1 x: t6 `. _* l( T, [- S
// Extra sounds
+ l  L  X* k- {- n9 e2 f: B#define        VRC6_VOL        (0x0F0)4 y" s9 [) _9 s7 G
#define        VRC7_VOL        (0x130)8 E2 {6 m0 L: B+ y9 V( f
#define        FDS_VOL                (0x0F0)  S: ?4 A2 j3 q% b
#define        MMC5_VOL        (0x0F0)6 H7 v$ W$ m0 g1 J2 b
#define        N106_VOL        (0x088)
) D, G: H9 Y8 ]: f#define        FME7_VOL        (0x130)3 A! d1 q2 |" E: \- `5 B; K* l9 R

. ]6 b. Y: [+ EAPU::APU( NES* parent )1 X0 o: k* Q0 @, i& ]/ P
{8 v* w; \7 i" q
        exsound_select = 0;
) L. @: A; M1 k' J+ {) Q
# {- F% t4 q1 |0 ?% t1 a        nes = parent;1 x4 H1 A8 B; D: w' \: Z
        internal.SetParent( parent );0 s) [0 f# l1 a* V' V$ x. L
+ c) H+ r7 H, r( ?$ z9 C
        last_data = last_diff = 0;
; U2 u% a3 [5 p: B$ E) r) }* b2 i  h4 O
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 k3 d  B& `, J6 O( S% i' j& O$ p5 V2 h8 B9 ^- r) d/ d; W
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );2 W+ [- A9 e4 D" {: h
        ZEROMEMORY( &queue, sizeof(queue) );+ N9 E4 ]. c2 i$ a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ B  _3 ^. K* l8 L& V+ H5 e
3 ]4 Y. [4 t4 h+ j/ L9 D! A& n/ `
        for( INT i = 0; i < 16; i++ ) {
+ [$ N2 H2 q& q* N0 T5 z                m_bMute = TRUE;
: u$ |1 f. `5 ~, I7 U# y& h        }0 n3 j/ n% h2 J% I+ b' A- g
}& g- H# U$ k- \7 [% K
" p. R0 p1 W, \+ i; Y4 t# w
APU::~APU()
4 {' o* x2 q; Q9 R{; }/ o$ c( j$ s# S0 X8 K
}
) [# b1 I+ \- n" U2 o9 G! m9 m1 I, x, H, n. a3 l5 H
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )) S4 o4 s7 M: H7 q' U
{
* s0 a$ Y* Q, Q' }; O! j        queue.data[queue.wrptr].time = writetime;3 ^1 X9 f  x8 l$ r9 ^- g
        queue.data[queue.wrptr].addr = addr;
* J3 w+ x5 Q7 |; w        queue.data[queue.wrptr].data = data;6 Z% t# }8 ~: |& G
        queue.wrptr++;1 @" \; G  i# l# A  y
        queue.wrptr&=QUEUE_LENGTH-1;
8 ?1 o, a% F) Q& H        if( queue.wrptr == queue.rdptr ) {
1 B3 E; g8 t' n% h* H  P  k                DEBUGOUT( "queue overflow.\n" );
+ I8 X% b; y4 V! s6 Y        }0 S2 B% f/ q: I) P+ O
}) l% H! R4 d0 k- W8 _/ c

  y9 P# g1 f' i) O" HBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
+ M' o' E1 S6 a{- _' Q3 u* x& I- x9 l8 S! T. U
        if( queue.wrptr == queue.rdptr ) {
( C" O$ J$ S* y8 c. B! y4 _                return        FALSE;; u$ ^* _: ?$ r
        }# f5 B! h* Q$ g8 V) M! Y& T2 K/ T
        if( queue.data[queue.rdptr].time <= writetime ) {" C1 a; T- k* Y2 m
                ret = queue.data[queue.rdptr];
3 i( s% K. V7 N                queue.rdptr++;" X6 l, n, H3 c; e3 y+ L5 X& u) d5 L
                queue.rdptr&=QUEUE_LENGTH-1;
& u# ^1 }9 N" o* n                return        TRUE;- s" D. a  }5 o! N( W& s
        }
, A) w) _  `6 b, w9 M! z        return        FALSE;6 h4 c; O4 V0 {- X) _
}/ ?4 a8 S  ^1 ]- Q. [+ V: e

4 Y* B+ i3 ~9 y0 K+ }void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ V" E: R% \2 H1 `( W
{: d1 P# d; N5 H3 M
        exqueue.data[exqueue.wrptr].time = writetime;
( Y+ B; e4 P& c) D4 b4 M        exqueue.data[exqueue.wrptr].addr = addr;2 |' A; B8 `" h" v  r! H
        exqueue.data[exqueue.wrptr].data = data;* o  |% e* H2 ~+ \( `; t! \
        exqueue.wrptr++;
/ p" L; _; K* i4 E" o/ `4 J. ?        exqueue.wrptr&=QUEUE_LENGTH-1;' t; l% s2 R5 P, I$ M6 m" S2 A
        if( exqueue.wrptr == exqueue.rdptr ) {
" h  P2 s% s, ?                DEBUGOUT( "exqueue overflow.\n" );
9 w- m3 X# K5 G. J" r        }
8 D! w3 H6 S+ g7 K}
  \" @& w; }  Z
# c" F1 Q' d. T; tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
8 Y. E- o" j: g9 y{8 u. \! ~1 N. R' W5 n+ c
        if( exqueue.wrptr == exqueue.rdptr ) {9 |  h4 p$ {( v# X& d6 M
                return        FALSE;
% l$ D1 v% N! H2 |        }4 H4 j( M0 y7 O
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' n! c4 \6 x1 `! _
                ret = exqueue.data[exqueue.rdptr];) g; l; {9 r+ {% r( }/ }
                exqueue.rdptr++;/ b7 |0 d0 w/ B+ c( K4 s- Q
                exqueue.rdptr&=QUEUE_LENGTH-1;4 f) K! S% W0 u, C- h9 }
                return        TRUE;
% G/ a. i8 E6 u% r. H1 N& C        }
1 G; s( F' j2 e% X& I- y        return        FALSE;3 u) _% i) I" I$ s2 k! F& n
}6 b1 g! L; S+ M( b$ x
; W/ q) E$ h+ ]  \5 Z0 a0 l
void        APU::QueueClear()
+ S: b9 w2 V) I5 G{
' A5 g7 E; ?2 B$ U/ |% w        ZEROMEMORY( &queue, sizeof(queue) );
/ e: l6 _. [! |  \' O- p        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& t& X' D  [# p1 a- I; I) k' ~- U5 j}
5 R! a' ?# R% j* k5 }( H. T! j, R- E6 j7 d+ e
void        APU::QueueFlush()- p+ n9 t7 |5 _+ |
{
2 w9 k1 k; ^1 B& M4 t        while( queue.wrptr != queue.rdptr ) {
$ l7 L! R# F* n: H                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );0 e% M+ {4 b4 t$ D. [7 q% t- C$ @
                queue.rdptr++;) C6 M! P  e. [' ~
                queue.rdptr&=QUEUE_LENGTH-1;. {3 A6 n7 K7 `1 v& w1 D# N. q
        }
7 j3 H1 v% X! [4 n
/ x( d9 R0 W5 j# m/ F* r) `        while( exqueue.wrptr != exqueue.rdptr ) {
3 ^& n! E" P& `6 V                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 q* a3 E+ f: i
                exqueue.rdptr++;+ t; ~+ N2 l  c4 J( p
                exqueue.rdptr&=QUEUE_LENGTH-1;
* Q* }$ d4 [" U9 ]: y9 w" }8 e  Z% V        }
8 l! E2 ~) r( ^) m6 [% l}
' }  _, @, d4 E8 [& r
* h2 Z5 ]6 ~" T% |* [void        APU::SoundSetup()+ O: Q* ^8 t$ n9 l
{
/ h$ e: h9 J2 B( [        FLOAT        fClock = nes->nescfg->CpuClock;0 z0 f' w" {5 H; k5 ]! {
        INT        nRate = (INT)Config.sound.nRate;! R+ B4 ]- X8 A5 p+ K0 S$ A. Y
        internal.Setup( fClock, nRate );
9 p) z- y) Y: B) V$ C* X6 t        vrc6.Setup( fClock, nRate );/ H% P6 I7 B8 z& @  b
        vrc7.Setup( fClock, nRate );
* D) N3 `  H( G' b        mmc5.Setup( fClock, nRate );5 t3 ^" ^! w  \( c# E
        fds.Setup ( fClock, nRate );" d- u1 [) N4 K; X: u1 G6 p! P
        n106.Setup( fClock, nRate );2 h$ M" P* `, M4 W0 x% P* r
        fme7.Setup( fClock, nRate );
, O( d! y# T# S+ G$ G( K, T}/ e5 M1 f1 K7 N0 Z( ~
1 N" }& V0 @# Z5 k4 ?7 ?
void        APU::Reset(); D" m0 C2 v& w. V2 }0 F
{
% M: M/ A% U+ {        ZEROMEMORY( &queue, sizeof(queue) );
+ q& h3 G/ @& D: o7 T) c9 }6 |9 p        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' q2 q) G+ v9 c7 T, Q
/ _% q* x  h/ i6 ~, S" W        elapsed_time = 0;: D, I( b4 C3 \3 D' T/ Y. Q. d

2 F- h  N; q: Y4 ~* Q- `) p        FLOAT        fClock = nes->nescfg->CpuClock;
3 G6 o2 m: q+ `! d        INT        nRate = (INT)Config.sound.nRate;
: o( ^6 O8 S' q/ R        internal.Reset( fClock, nRate );: Z- g8 i2 Y# P5 z. y0 E
        vrc6.Reset( fClock, nRate );/ x/ ]9 s1 W) R+ ~% _, r+ Z
        vrc7.Reset( fClock, nRate );4 l, }, ^6 n0 Z3 b9 J8 d( ?
        mmc5.Reset( fClock, nRate );
* D3 ~  H+ M8 L3 D* Z        fds.Reset ( fClock, nRate );
' F' f9 x, |' i) ^; R; V# n        n106.Reset( fClock, nRate );% T! [8 [2 h& f7 O$ ^+ V
        fme7.Reset( fClock, nRate );
" ^1 N& L* ^( @  z: q, U4 I  P
$ s8 c1 i) `2 c" o$ W+ }  @        SoundSetup();
. h, D  R$ Y( a/ F}; g' U( Z3 D! x: ?6 |% C. }: u. g* w
4 C! g8 |% ^, b/ l9 m1 ^( G
void        APU::SelectExSound( BYTE data )
" U) \* Q  l- [{
5 S' \3 M) ~8 T  I, f# c# l6 {        exsound_select = data;' P- e' p% j' t# t2 ~, u1 F" j% x8 m" Y
}+ F5 T( j8 V* ]
$ X. F* u7 n3 V
BYTE        APU::Read( WORD addr )9 j( u4 }4 \4 |! @7 h
{8 u) ^1 I3 [$ K3 x
        return        internal.SyncRead( addr );! N4 p0 w4 l: L  i8 O
}3 Q) ?2 N  m* r  U
" q) x% o! A% c# n; S9 P8 b
void        APU::Write( WORD addr, BYTE data )1 a, ^5 o# @# A1 E
{
6 |$ w! ?* Z( n8 A8 W- c% ?( ?' }3 G        // $4018偼VirtuaNES屌桳億乕僩; Q% A, I/ B- s( X: a" T$ r% L
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 B: Q! F- L" y: L+ R' v                internal.SyncWrite( addr, data );- d8 k* _5 N4 q  d, b' a5 K4 r
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 ], U) t3 i2 O9 e" z
        }
" \, i5 B8 G7 d7 F8 E}
5 D* f7 f; g% D, e) p( Y0 c( E  M. J4 P1 D2 x' N( q& c
BYTE        APU::ExRead( WORD addr )$ ?: A% W; |/ C: p( I5 p, t
{+ Y6 e1 w% ^) }' F% h
BYTE        data = 0;
$ v6 Q% _5 E, U' v' R4 l. x# X
; H- V, _3 ]3 U        if( exsound_select & 0x10 ) {# E; t/ ]: J! e& e  a
                if( addr == 0x4800 ) {
; N6 G; G0 ^5 Z" T+ W: {                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- d# Y) L- m8 t; ~3 \7 Y
                }( V) y( ^/ X4 A
        }
- ]& B. k5 h% n( {6 e0 L9 |        if( exsound_select & 0x04 ) {1 h8 m; L. \6 f% N% d, ^
                if( addr >= 0x4040 && addr < 0x4100 ) {4 ]3 p2 [3 Q8 Z) R+ W6 S9 w
                        data = fds.SyncRead( addr );
. _: e( w3 x) }: e2 D+ o( e! Q                }4 A$ M, T" r7 W, H$ {% m6 |3 b3 ]
        }
7 Y+ Q$ w  x: E" c, [8 Q        if( exsound_select & 0x08 ) {3 ]! I: m' S! ~- k- w/ m& M
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- e3 H+ ~3 L7 C+ F                        data = mmc5.SyncRead( addr );9 b# n8 w6 e: Q0 q& j# i' U
                }/ o. o9 J$ C, W
        }
! M/ o) f  r, r# y( S  }' i3 z& G& F, \; ^/ u# z8 w
        return        data;
5 |( ?& {: T# y1 O, U6 ]}- A! ]% R# A- }' W
' [9 C  w3 L9 ^
void        APU::ExWrite( WORD addr, BYTE data )1 ~1 f9 x2 w  V
{4 K1 p. L1 p0 I, y
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
- _1 c2 L9 Z$ E9 I3 Y6 C% s5 V
/ Q, D) ]- t" _' I4 y( c" x        if( exsound_select & 0x04 ) {7 }4 S' U& i, l( H- z3 o+ @
                if( addr >= 0x4040 && addr < 0x4100 ) {1 A  A- M- V# S2 P: L; I. L
                        fds.SyncWrite( addr, data );
0 ]# G( \, H2 ~- C! p& z                }9 k! K9 b* i- e7 }" P
        }+ |- y1 }) X- L5 Q$ h7 v6 e0 p
8 U, K( m# \# [4 s+ m  }# ~
        if( exsound_select & 0x08 ) {
( I0 e! C) }! ?0 }: n9 z% Y                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 ]$ z5 ?" E( U; f# q                        mmc5.SyncWrite( addr, data );
5 s- x; q" I7 U+ n6 y3 W/ Z                }
4 m' u, A! J+ ~* Q, g* Q        }
/ ]! s) P& v& L: J, M1 S  ]}
, K- U+ T: `1 g7 h" r6 t! J
- u7 x+ d6 g5 E7 R* kvoid        APU::Sync()+ u. V* _3 Z* v9 U' ~1 X
{% Q8 V. t7 C" E! e& H9 X
}
; u) L/ T3 U' i" T! B' b- H: ?. z+ D0 ?8 K& W4 o2 O" r
void        APU::SyncDPCM( INT cycles ): K3 D  i9 t* a, H
{" T2 }% b2 Z: W6 E* O
        internal.Sync( cycles );! I7 T' N4 k" i6 L" U8 V

) S+ A; w9 ~9 s5 _+ i! J5 x2 _        if( exsound_select & 0x04 ) {4 l7 P1 w0 T" B3 G1 _
                fds.Sync( cycles );8 d2 [, ~$ P5 n6 F3 v% D
        }4 U3 f% }. l% ~. O9 y; T+ ]
        if( exsound_select & 0x08 ) {( T: V+ K$ T" Z. j% S2 `# I) B: h
                mmc5.Sync( cycles );
* v8 E: d. s- r/ n0 ]( C  d: }        }6 i0 |) [' G' E. q: L- I
}6 r& g  G. z3 P0 k

+ a% E" h- d4 A% }  fvoid        APU::WriteProcess( WORD addr, BYTE data )
! }  Z! y/ U0 J0 v{  ~, Z) Y8 Y; w) i, V0 o7 r' p
        // $4018偼VirtuaNES屌桳億乕僩
* }# Z  S* Z1 c4 k7 U        if( addr >= 0x4000 && addr <= 0x401F ) {4 t/ Y4 U) P6 K1 m/ v3 r- g# B
                internal.Write( addr, data );2 b- I8 G" k/ F) q
        }
! y! k4 g7 x# h0 ?. E$ a' T}
. k& y% y: [# P6 A) `% i* `7 d
4 g; M, c; n+ z3 x* ^0 G( hvoid        APU::WriteExProcess( WORD addr, BYTE data )
" X4 a2 a& D" p: ?( G9 {, Q" ?{4 y. ^; a2 X4 R
        if( exsound_select & 0x01 ) {
. @4 S  D/ n3 ]4 z6 M; _7 s                vrc6.Write( addr, data );* G9 l' J$ [0 o- S4 y9 v
        }" C4 [7 u) f( S) J" Y
        if( exsound_select & 0x02 ) {
& E$ u6 ]8 N6 u; v" [3 X                vrc7.Write( addr, data );9 c) h8 y- H: d$ W" I6 U. k) r8 j* t8 C
        }( O8 i9 R! S# N/ E, Q$ y: X! d
        if( exsound_select & 0x04 ) {
0 G; t- T- U8 h" ~, f; i                fds.Write( addr, data );
. W) v+ P( h  v        }; P: p: l( p0 W9 Z! F' P
        if( exsound_select & 0x08 ) {
$ c! p; |( }) ]% V; H                mmc5.Write( addr, data );
* |8 y5 e- c3 d! v' J        }
; o% B) m; g3 F% t! C4 P  ]        if( exsound_select & 0x10 ) {# Q; X' Q, N5 _) F7 P* O! n
                if( addr == 0x0000 ) {
" ?& r, V$ z1 k& l                        BYTE        dummy = n106.Read( addr );4 O& ~2 g( X8 \! v
                } else {2 j+ ?# }# {% j# q/ i! [6 ^. u  e
                        n106.Write( addr, data );0 B& q! D( A2 I  m/ i- c8 g# y+ R
                }
" @. y! M, {* n$ Z! u1 u; ^        }0 Q: C0 {+ n7 F3 Q" x
        if( exsound_select & 0x20 ) {
+ H; {* Q5 Y% C& Y. v, Y                fme7.Write( addr, data );- F7 c; S0 g+ q8 l, r, W7 J
        }: R, @: b- n/ l% M9 t' U# ^
}
4 X0 q3 [' J4 [, B5 R8 U1 t8 n; t4 v, G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 e- x* x' m: a3 y{
! ]4 q. e6 h8 E* T9 xINT        nBits = Config.sound.nBits;( \' L  K1 O4 F& U2 z% p, G- e
DWORD        dwLength = dwSize / (nBits/8);
- B' F  R8 H& G1 }INT        output;' X) Y# h3 _/ A
QUEUEDATA q;, I4 F& [7 Y# V% x2 u
DWORD        writetime;
5 F% m4 M& d& A$ Q% x8 C
8 [1 d0 l" Y" }: zLPSHORT        pSoundBuf = m_SoundBuffer;
( d$ w* L5 H7 ~; V) _INT        nCcount = 0;, x: t" [( ]$ q+ [# g7 [& G

5 B+ p# A# q8 Y) e- z. LINT        nFilterType = Config.sound.nFilterType;2 F+ }( ]3 f. V0 H  V- ]

# z4 ~, |: \1 V3 R/ D0 g+ K! l        if( !Config.sound.bEnable ) {. o3 R, d2 u& ^  @. K
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );. p" z6 L6 M$ ], X
                return;
% L/ R3 o0 a, N        }
' w1 j5 y+ v+ {8 t9 Q$ R" G, C5 t3 H
        // Volume setup
( B+ s: g. `. }! `$ r% ~        //  0:Master$ B/ g/ m# N# g; o6 y- B+ Y6 Q: T
        //  1:Rectangle 1
% n4 Z0 N: A  i0 h$ z! E7 P        //  2:Rectangle 2
+ ], I8 L  o2 J: A2 d. c        //  3:Triangle3 c: ?( f# Z. @7 ?" K
        //  4:Noise9 @- V) g0 E$ O# J6 d! ?! S
        //  5:DPCM
. E; J; y% Q9 o        //  6:VRC69 R  }. i& A5 W9 h, s. E' P2 X
        //  7:VRC70 A' ^; I6 o+ K0 E! R4 `* i. i
        //  8:FDS
% T+ \: d" x( t# f8 x4 L& Y        //  9:MMC5' X6 v+ [$ k: \" m- p+ D) D
        // 10:N106
! W% S) x4 x& x9 O4 [( D* }        // 11:FME76 I; K0 G7 r  l: a$ l
        INT        vol[24];) Y. k. W( C2 w6 O
        BOOL*        bMute = m_bMute;9 S* o3 C% M4 C7 m  X; x& {+ U
        SHORT*        nVolume = Config.sound.nVolume;
" l7 n, N. P3 C( a- e# d6 Q  l/ R* n
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;) m4 h  F; f/ p* a. ~: h# ~1 Z* u

6 ]$ t8 U0 |; p% k! k        // Internal
0 H6 o" W7 \$ ]0 B1 n        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;- U- L8 S: O9 p, D
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
) a2 `' ?" z9 d0 ?/ [        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
/ m! O/ d( K. w( f8 {1 e( ?# P6 O        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
" ~7 x7 q( ?4 r: S" c: H        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  n& M# K6 p2 E( N5 m0 D
/ n2 @$ y  G% f( a
        // VRC6
/ y3 B9 z/ m; y6 X  U2 r  z7 A2 j. P! A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, F. t2 c7 y  V) B! D$ U4 A
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 l9 Y! b9 U+ m3 o" u3 H
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 M" k0 z# ~# S1 f1 c& f$ E, }& u+ R5 A) ]
        // VRC70 @7 B9 d3 G9 ^- g+ q9 r
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;' ]6 v2 l; l! }3 r4 [
0 w, N9 E+ g- Q- I7 [  x8 X
        // FDS
5 f  g+ ?9 e& M5 |$ P" h9 C) h" q: [        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;) ]: z/ D4 [" D% ^  B

: {8 ~3 T8 G3 K        // MMC5
2 l; Y: Z8 i" _        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 L6 @! z2 L' q; x9 l9 k( r        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 Y2 C" u: M' `! j; Z6 {  l
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 g& V: b  W4 A, Y5 o; x9 A

. l) Q/ ^- O9 P' O3 |3 N        // N106$ l, N% `; W2 m5 o5 {# l( l4 Q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ w+ g: x, y& \1 E4 g* e        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ^8 R4 R' p, t7 E. \/ Z: e
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 k" I+ u: ^+ R, ^8 P
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, q# w- ]* l8 o
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: y) }5 n: C/ t8 U- L, y% G        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ ^0 D8 `' r7 \& w0 K) o
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 m+ q0 o5 h1 f2 g6 s/ [; G, a
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ K3 {  B2 f5 ^; R
6 C$ h' H8 J5 ]
        // FME7! x7 E3 U) ?) w5 S! `9 y8 ~: X
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- Y6 ~- V3 l0 B9 B4 g6 q0 B        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  ~, ^7 p/ y' r5 b
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  ]- L1 A5 n) H. ]; ?1 f+ t5 W9 V+ r0 Y3 _
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;# o+ D/ b% h* _$ Q7 N* q9 W
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;- t# K8 |  B0 N+ L
. i0 Q: R5 P+ V- N9 T
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. F) S/ ~( f) I/ v, t# P* ^5 q+ _
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {5 G+ t4 v! ]) w
                QueueFlush();
/ F* _/ a, Q4 J! S9 f8 s. @        }3 `, p0 B5 k7 m; \

! Y, o9 K) [3 {. P+ K4 s        while( dwLength-- ) {( D6 t* w* r" k+ t6 M2 R
                writetime = (DWORD)elapsed_time;
0 h) |' a: L# i) Z( B
3 m  O; |- a! l$ o6 h                while( GetQueue( writetime, q ) ) {+ z8 c  S  S" v( s" `( I' a- Z! b
                        WriteProcess( q.addr, q.data );: Z. q  L' b8 A: I+ H
                }# k  G6 q) J* e) ~
1 s2 j$ y6 b2 K( X4 m; i
                while( GetExQueue( writetime, q ) ) {+ M, n; }5 {* z, F
                        WriteExProcess( q.addr, q.data );2 j& E9 ~  @9 I1 s  w
                }
8 a: ^. _/ j4 ~% b7 A+ P' a! }# S: W4 {! T) x
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- R* t; m. n2 B! e7 \/ X
                output = 0;
/ z- C- Q( |$ r( A5 c  @                output += internal.Process( 0 )*vol[0];2 Y9 G2 @  i; a( H6 B) p
                output += internal.Process( 1 )*vol[1];
0 K* M' P! `/ k) }# J                output += internal.Process( 2 )*vol[2];
% M+ I) S; K; W' j                output += internal.Process( 3 )*vol[3];
/ S' h: }+ ?/ U                output += internal.Process( 4 )*vol[4];
& g% R! [. a! [$ C, \4 I$ `& V0 m% I8 C- f! v- x4 z
                if( exsound_select & 0x01 ) {5 _; R% o& H* d# g+ I  p" A
                        output += vrc6.Process( 0 )*vol[5];
/ h% g% D$ k( k* b6 J5 m$ B' t$ C                        output += vrc6.Process( 1 )*vol[6];0 a; T9 M% ], p8 e& f3 F4 \
                        output += vrc6.Process( 2 )*vol[7];( a( }) ?2 S' J1 o% B; w" t* G, M" \3 F
                }, V& K2 t. g! f
                if( exsound_select & 0x02 ) {; S* _6 _: q0 J" C  s
                        output += vrc7.Process( 0 )*vol[8];
" k: E; D# A! d: a8 v3 F) f* p                }. ~1 X& Z7 x3 x! T3 ~
                if( exsound_select & 0x04 ) {
# O& a$ d* d( J( \4 }% [0 V. I& t$ b                        output += fds.Process( 0 )*vol[9];) [4 y' _0 S4 a  Z" Y
                }7 }; k* k, p7 K# V& i* ?8 `# i
                if( exsound_select & 0x08 ) {+ ^+ S9 X# h& e7 M' M. C' ]! P9 T
                        output += mmc5.Process( 0 )*vol[10];
2 Z0 l* V: |# Z0 u" `, O% k2 {  n                        output += mmc5.Process( 1 )*vol[11];
+ Q. ~! ]! y# z4 c% x                        output += mmc5.Process( 2 )*vol[12];1 e/ X; l4 p( k0 q
                }
7 n! o. I, P$ q: ^                if( exsound_select & 0x10 ) {. A  k# W6 L& ^
                        output += n106.Process( 0 )*vol[13];9 k' B! _& Z+ w' B3 x
                        output += n106.Process( 1 )*vol[14];
% k! |3 C$ [; Y4 f. N. _$ s% m                        output += n106.Process( 2 )*vol[15];+ T* T0 b7 w/ z: k5 a6 |" f* ^
                        output += n106.Process( 3 )*vol[16];8 ?) k! y3 o6 m1 A1 A2 a
                        output += n106.Process( 4 )*vol[17];* U: g0 |2 B( j2 \
                        output += n106.Process( 5 )*vol[18];2 A% C7 H0 G; {# X" A1 B- z
                        output += n106.Process( 6 )*vol[19];
9 r7 p  N; A% f% f/ Z% g* a9 i                        output += n106.Process( 7 )*vol[20];, F6 Z3 I1 M! k
                }
8 G4 X& d0 c# K                if( exsound_select & 0x20 ) {- C% v+ G+ u% D- D8 g
                        fme7.Process( 3 );        // Envelope & Noise# U1 R* y6 L2 m1 G
                        output += fme7.Process( 0 )*vol[21];) _7 o9 q  Z, {9 M
                        output += fme7.Process( 1 )*vol[22];+ J5 K- O1 y) m# N) z  w
                        output += fme7.Process( 2 )*vol[23];
/ z9 _, F0 ^& U# X% F5 o! y2 T                }
- M/ O+ P& t0 G& }2 s) G
4 I/ b* t4 ]6 {2 o$ H( h9 c. @7 k                output >>= 8;" h4 c% L7 J! ?6 G8 V
* N6 n* @& m* p
                if( nFilterType == 1 ) {$ U' L! @! X& O* }
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* P4 t7 j7 P+ V( L6 _                        output = (lowpass_filter[0]+output)/2;4 ]  h6 D8 n% ]- a% x
                        lowpass_filter[0] = output;
! W- y& a' O; {/ z" }                } else if( nFilterType == 2 ) {
2 r1 L) S9 ?& @8 X. x  I                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1): F' k! \, L4 Z2 N( W; e
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;, u- y, g& J( J. R
                        lowpass_filter[1] = lowpass_filter[0];& o. n4 O6 k- K% F4 r
                        lowpass_filter[0] = output;( s: B4 H. M! @) j& N4 G+ m
                } else if( nFilterType == 3 ) {
# R  ~% T, x4 k" M) \( M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
7 `+ u3 U; J4 |' ^: s                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) Z6 x+ T+ U, i. B
                        lowpass_filter[2] = lowpass_filter[1];8 f3 \, C. m0 {3 P; j; w: d
                        lowpass_filter[1] = lowpass_filter[0];+ Y5 T3 W* m' {  n: T3 W9 W
                        lowpass_filter[0] = output;
& o! y) K4 G$ }: p1 y6 W                } else if( nFilterType == 4 ) {; T" B, k' }8 m. x$ q4 j% b
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)9 l4 U3 U: ]$ C- g" f7 f0 }  O
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 E. a8 C* h& z/ B# m                        lowpass_filter[1] = lowpass_filter[0];
7 Z  w/ ]9 Q/ H* x0 ^/ ?                        lowpass_filter[0] = output;
3 T+ a( j$ s. H) I                }& i1 z' U8 j. H7 U  p

# c# x# C8 W8 K- h0 e" Y#if        0
/ F3 i4 ?7 D' h% Y7 K                // DC惉暘偺僇僢僩! J) H: z; d8 A( D
                {7 v. k, s- q8 I- t
                static double ave = 0.0, max=0.0, min=0.0;; ~7 D7 u- |$ \7 U, _: N# }
                double delta;
4 n/ R8 K0 K  {' z, B+ k+ Z                delta = (max-min)/32768.0;
( |0 |' ^) P% E, `' ~) H' A: c/ X9 v                max -= delta;" Z. W8 C% K6 D9 h/ \% b$ I
                min += delta;
) W0 h9 a$ C# z  R# u! D                if( output > max ) max = output;' d7 {2 }: L- P0 J! j% h
                if( output < min ) min = output;
8 j! B( g" `4 a3 k+ o                ave -= ave/1024.0;
% ~% }3 Q" O4 Q2 C- u0 \2 G                ave += (max+min)/2048.0;
) \' d' |2 j# T- C7 K7 ]0 d8 X                output -= (INT)ave;' z& e* B2 t* F& f
                }) D/ I' V4 T8 s' F% {
#endif) j, S2 y6 U) R1 P
#if        1
) }! Z2 c7 H% d9 j  H7 u                // DC惉暘偺僇僢僩(HPF TEST)6 B- ?% Y$ E2 A# O
                {
3 P) V3 ~- _0 b/ Q3 j1 Y; C//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 Y- H1 y# ~9 @7 ]+ f2 V                static        double        cutofftemp = (2.0*3.141592653579*40.0);2 I4 M+ @/ g! d( ~+ e* y
                double        cutoff = cutofftemp/(double)Config.sound.nRate;6 a  f& B5 @/ E/ g+ }
                static        double        tmp = 0.0;
/ n& k# H7 Z# a" u( _                double        in, out;+ ^( b; ]$ U9 |1 p3 ~. P
$ B2 ?8 n; E1 A7 I. C2 C
                in = (double)output;0 K" L) }/ d9 L
                out = (in - tmp);+ J4 M$ _4 q, }( L
                tmp = tmp + cutoff * out;
+ \8 `; U$ n# O9 F+ f: {# x0 t2 [9 t. N" G8 g
                output = (INT)out;
; }+ n" u5 F5 M2 L' s                }
0 I( q: a+ C# z( i; I9 {#endif; L* k& v  G/ e0 U0 F8 p; V
#if        0% m- o. v/ u  p
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)# }% B! y' L# J# `6 ?
                {
9 L. Y9 F  T$ \9 V                INT        diff = abs(output-last_data);
. n/ g4 [# A7 ^& S0 S+ D                if( diff > 0x4000 ) {$ g* _) v& _* E6 f! D6 M  `/ O' U
                        output /= 4;
2 r4 e9 Y8 M, B0 r# o                } else 2 l- |3 s: b% {
                if( diff > 0x3000 ) {
$ t( |7 r: w- U" z- h+ ^                        output /= 3;
' k9 O; M+ U. y( Y" s                } else& \+ ?  ]8 j6 ~" ^3 `1 h$ D
                if( diff > 0x2000 ) {
, _4 N3 C6 Z: r                        output /= 2;9 q. k  K% l: l6 ^: ~! V
                }+ ^+ ^. Y4 Z$ L2 t
                last_data = output;
! ^% i) n: @& K7 i! o/ A  \                }
4 j/ s7 L( Q# h( m% x: S#endif  }5 P4 G7 _: K- P3 Y9 g0 T/ e
                // Limit
' a9 K: s9 y! K- h( V: ~5 E$ Z( s                if( output > 0x7FFF ) {, ?" E; n1 o3 }$ |5 ~
                        output = 0x7FFF;
' p- o) g8 m* G- y( f                } else if( output < -0x8000 ) {" ~8 X8 Q3 i# p+ B: r2 d6 {0 u
                        output = -0x8000;8 U3 ~& C: U3 M8 ]+ T
                }
% E0 a/ r% m. m- k
$ x7 X7 \9 v3 w5 F, k, n1 @3 P& L                if( nBits != 8 ) {
2 O9 m& N  i) ]; \$ ?                        *(SHORT*)lpBuffer = (SHORT)output;
6 ~6 }/ ]/ C  Z- T. i) R                        lpBuffer += sizeof(SHORT);
1 T# h4 C7 `1 L0 F) Q+ t& `                } else {* G1 {# L4 {1 ~* q/ B9 ?
                        *lpBuffer++ = (output>>8)^0x80;# z5 `* q+ _2 }6 d/ t7 {* p
                }
) z8 w* H" E5 u7 `6 G! I1 N
+ j: L/ a" o+ L; W& @                if( nCcount < 0x0100 )
+ g7 G8 d( `) b( C# J. j                        pSoundBuf[nCcount++] = (SHORT)output;- F5 a( |8 o& l- s- d; Z- v7 W' d2 u; N

2 B+ P: G- H1 @) z8 F* d  g/ {//                elapsedtime += cycle_rate;
' o) {" G" A5 G7 S" a  [; X                elapsed_time += cycle_rate;
9 E- h2 S: u2 v& K; T) Q        }
# H+ I! u$ V: L4 Y+ f' t! B4 a6 P2 s. Z* u% b' G
#if        14 |; b* f, q- z) P, Q* R6 L9 C/ ?
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {) i" G3 p3 D# p2 l% j9 A# w4 P
                elapsed_time = nes->cpu->GetTotalCycles();
* F' x, `2 X" _# U        }
# I% F' L* B8 Y0 u2 U1 N1 Q. x7 U% u        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: H" x/ B7 Z% y5 [                elapsed_time = nes->cpu->GetTotalCycles();
  ~2 s7 d# e( M: I- Y) z0 A        }
  F2 ~8 N8 w' z1 ~/ ^#else
$ I8 c/ ~6 C' e; z: L( i' T& `        elapsed_time = nes->cpu->GetTotalCycles();
7 v5 _8 T9 K: V' [# d' `. A( W9 C#endif% H6 g  X$ r4 H" `( n
}
. Z9 s& I2 C, y* z) t$ @
( y4 S8 n. I8 j' P2 J// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)$ D$ f- A7 w, @5 _7 U& t- K
INT        APU::GetChannelFrequency( INT no )
1 G4 B6 ~. c: Q3 S{
: U) |2 p7 V" b        if( !m_bMute[0] )
* T  p6 j6 G6 H& A                return        0;( m9 D  p- j/ D2 K
0 E0 Q& B9 g! J' v( ?' D
        // Internal
$ r  [/ x8 h6 k        if( no < 5 ) {/ w  z/ B7 j( B+ c: |7 M
                return        m_bMute[no+1]?internal.GetFreq( no ):0;$ _! s5 v/ T# z: W/ x2 O
        }
$ x6 R% Q. k0 z: w/ u% A! C        // VRC6
3 q9 W- U* z/ ^4 W6 n4 R        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {& L& H, J" g# ^
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
3 ?3 g7 y& S, s' N6 Q) G; f        }
# U4 K' B  `) u2 T& `% L        // FDS
& s- g7 ~9 i% z/ J        if( (exsound_select & 0x04) && no == 0x300 ) {
5 u1 e5 r: H: R                return        m_bMute[6]?fds.GetFreq( 0 ):0;
& L( r; S* v# J) z/ v/ ^+ X6 i        }: V* o% a1 B- v7 E; _* `+ [
        // MMC58 i7 L) N6 k, P1 ^! Y/ }
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 N- J6 p6 e& O. ~                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% F% y9 X% x( w% g/ Z7 M
        }- D$ g  y: S" b2 b6 E, v4 C: x
        // N106
, P, v, U( d5 u# V, l9 ~; H        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
( G  q4 W" }, W, u1 y+ o4 [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ s, a) R  n1 p7 {2 n
        }
; M6 |, B8 l" s5 z3 h+ {+ q% J' h) g        // FME7
7 U+ z6 n8 d( K4 x# W3 J$ D/ i( R3 E        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* ]5 k5 u0 b. R( O1 `; R
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;7 k  ?! W- D# i# R$ X
        }2 L3 y9 d( ]0 t8 Q( V8 h# `, U3 M; m
        // VRC7
) P' U  _+ n9 R/ J        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {1 w/ o( L1 N$ Z+ T, {+ ]
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;# g- {+ ?0 Q* V+ Q: f# B7 h
        }( @" G$ l* T1 ?8 @' g# G" ^
        return        0;
2 z9 P, K, q; f5 S}
9 L) l( F9 J) {9 H
1 z/ q! {3 f& q$ r* }// State Save/Load
) w  [! M$ U6 {2 d, {* qvoid        APU::SaveState( LPBYTE p ), m. C, q. n: \: d2 q/ W
{
7 a, e' h1 v! d0 }6 b& K#ifdef        _DEBUG
  {* Q: Q! l" n. E7 VLPBYTE        pold = p;! k7 B8 A' I0 U- r/ F7 e% \7 ?2 v6 \
#endif3 R9 C9 b% X0 Y1 Q
  Q$ u: r! I& ]5 ^3 L" K
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞9 Z+ \- W$ \$ n+ T/ z; q
        QueueFlush();
$ b7 Q. M* [3 M0 l: b1 O, b  q
# k  k& g$ r" T+ P) Q7 c        internal.SaveState( p );
6 |8 a/ c& |) _. g; J$ _  d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  ]4 X" s  `' O
$ Y/ z+ u) k# T& m( G        // VRC63 e* C9 c( K+ u; v
        if( exsound_select & 0x01 ) {( W% f0 u7 `# `/ G
                vrc6.SaveState( p );
) Z  a$ U0 |3 y                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( x- |% g/ G, G  G) i0 c% f
        }
! c) j4 I& b% d9 ?6 J$ Q; P7 ^; T        // VRC7 (not support)
7 F1 v+ A0 }9 q        if( exsound_select & 0x02 ) {
* v6 s! ^5 Q9 k) O8 w; i# X                vrc7.SaveState( p );
4 t' ~/ V- R/ E; i8 D                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 p* e% |$ y% R/ `# w) A# w1 z        }
  m) T, N! V. Q5 v        // FDS
- o7 R7 h9 I1 S2 I* X        if( exsound_select & 0x04 ) {7 [3 b" A: ~& t9 P2 p0 _
                fds.SaveState( p );
( `6 E) t  Z4 Y' C                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: t4 l7 t6 j, V/ b2 R
        }
, A6 K5 Z* a6 h  L" b8 j1 ?        // MMC5
$ F- Y. d. _5 a        if( exsound_select & 0x08 ) {
3 e( ?: f! E) ^                mmc5.SaveState( p );
5 Q( y) T. v! D0 I# ~                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' ]: q% W% ]4 [8 W, v* e. t: J        }8 Y- D' K2 C( C- f6 t% B9 I! s
        // N106, r" v  a8 n+ F* F
        if( exsound_select & 0x10 ) {5 T/ x/ p' R- Q, {# h( P
                n106.SaveState( p );$ K+ ~! x3 p+ n0 S& [
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 ?6 B$ k- {. C3 Q$ G: f8 @        }
0 W& }" M$ t4 `# i# ?4 k! k        // FME7
2 d2 J1 t0 R8 L: i! l' w        if( exsound_select & 0x20 ) {  R8 s6 Y0 O0 _5 b) S" R
                fme7.SaveState( p );1 `; V. G) o$ _/ o7 {
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; q) o. D7 `/ O( {, G- _% m6 R% s1 f        }
( ?& J+ a! a0 i, A# W
& z# g% D6 S4 B" V* x- L7 r  m" O#ifdef        _DEBUG
4 A9 P! X, t! E6 HDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 Z. y! @% p+ v4 S! k) z" h#endif! T' a! b9 J  z. s% M; _( B' R
}
1 }0 }6 k4 M: {8 D, k' p- ~
) `! J" n3 J9 A$ I7 V, R; K  Mvoid        APU::LoadState( LPBYTE p )  b6 G9 q3 W* J! u1 K) e! Y2 v! V' @
{
5 U2 m( Y7 X+ j' H) d        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
: H- A: ?! U" [$ Y' P- K        QueueClear();3 B6 L0 q( H$ H, C6 \/ Z
0 g3 x8 E1 `  D" _2 ]% s
        internal.LoadState( p );
1 p3 t1 g* D2 n& x        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 `. T6 C: c# n, c
* Y; N3 N: t6 C9 N7 p4 c$ P* A
        // VRC6
2 ^3 P1 F2 x, v! q- u7 [        if( exsound_select & 0x01 ) {
+ I: G6 p9 J8 a* t. [/ F                vrc6.LoadState( p );
6 z) M& U/ H/ d' K                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 t$ O$ R1 G3 N, M
        }
( ^' q6 h' w* e        // VRC7 (not support)3 ~! T3 R5 b3 |8 A( H4 c
        if( exsound_select & 0x02 ) {
. \6 o- j- C2 l2 n6 Y) w                vrc7.LoadState( p );, a  |( Q# {) C8 b6 x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ O; v- q0 ^) S( F4 Y% U: a* S6 N        }
( @! A( |2 A' A5 h        // FDS3 A7 f% m$ r0 |) b4 @
        if( exsound_select & 0x04 ) {
1 g5 F% Q: k1 D2 d                fds.LoadState( p );( ?- C$ t& P# d3 ~9 x
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% Z2 _* f7 g  g        }
, Z2 ^( d( t/ e  @9 p9 g8 q! p        // MMC5
1 E8 C$ G$ n+ ^. ]* Q        if( exsound_select & 0x08 ) {& {7 }/ [8 Q# _0 @, F/ _# I
                mmc5.LoadState( p );4 Z& o5 u+ Q$ l) `
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 ^2 J% M/ M; h5 K        }2 A* k: V1 W) @% g. G7 k, V0 b
        // N106# o3 b' w8 i* a% V* N
        if( exsound_select & 0x10 ) {
7 J$ a: z% D5 N0 E! S                n106.LoadState( p );0 h' @) n) f' t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: e! W2 Z; z1 i* ^, v5 n& m        }: t3 ], ^/ c$ H4 H& I. }
        // FME7
( a4 q, N5 s% i1 ^$ x, {% u* X: Z1 |6 ]        if( exsound_select & 0x20 ) {
1 E! n1 s8 B- j( M                fme7.LoadState( p );
" P7 X7 Q* m: }; a8 @6 K" p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- U+ Z1 i+ K. x( z( u) }
        }+ E3 A! y# U5 k6 F3 B: L
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( r1 g4 b8 m; L. @" y2 V1 ^可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. k$ I3 J* B- _6 {4 Y" p感激不尽~~

: l3 d, U8 I: n  J) A$ H7 E$ Z恩 我對模擬器不是很有研究,
, ?3 e2 V( `+ _- g( P雖然要了解源碼內容,可能不是很困難,
3 c$ K( D7 T' g" L8 M1 y" {! A0 H不過還是要花時間,個人目前蠻忙碌的。+ S' [- e( V% X5 Z* n! j

. l, r8 m3 {: E* K6 F, Q給你一個朋友的MSN,你可以跟他討論看看,, s' m% f" L1 ~
他本身是程式設計師,也對FC模擬器很有興趣。/ A8 m, m/ A( E% R* Y* h

- L; L+ Q1 C; g9 C2 P: DMSN我就PM到你的信箱了。
7 w* A% W; l7 W/ q8 `, U. `  n4 n% M
8 Z# k4 J" H+ f1 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 发表
+ _  }8 Q1 N# k* T; u呵…… 谢过团长大人~~

: j, A' R% ~7 u6 O) N
5 g2 l" q& }) w哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
: `$ Q. N1 v7 \& B1 x团长的朋友都是神,那团长就是神的boss。
* i" Z; z* W1 S1 s; b4 x) ]
哈 不敢當,我只是個平凡人,5 Y# [( @2 Q4 n: K, k4 {9 M
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! s5 ]# l/ N7 J
ZYH0 @* E4 o& h. M: ~% j
QQ:4147343066 b/ R: A. a. o4 Y, h
Mail:zyh-01@126.com. u/ D$ Y, C; t5 U0 f! b+ o# r4 m

! Q' X. I, g; L; m' ~9 ]  D$ e他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
2 x0 K! a8 \' N6 Y再次对团长大人和悠悠哥的无私帮助表示感谢~~
' O3 j  g3 V( I$ K
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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