EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?  {5 Y! o" Y( t% @% m! T3 Z
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ h# ?/ J5 I  N楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! e; x3 F- c0 G  \这里有相应的模拟器源码,就当送给大侠了~~1 V! c  c- z! h4 E. o2 @& J% J, g
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% K' @  o+ a5 }6 _8 Z9 I' A能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ s7 F6 Y8 w7 @% x3 K) ^
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 y  @1 |) S. N4 D
这里有相应的模拟器源码,就当送给大侠 ...

, \; c# E; s/ S  z8 q+ m聲音部分(Audoi Process Unit = APU):9 Z" @2 ?8 H' N2 R, ~. P8 [: P7 u7 Y
.\NES\APU.cpp: A5 ?+ C1 q! s: O4 N7 z( y. J/ z
.\NES\APU.h& Y, K( T* S* h# X1 y4 `% k
6 G3 y8 o% I5 |1 u
9 |- z3 ]- G& C: C) g
影像處理部份(Picture Processing Unit = PPU):+ L% ~) x% d' l4 g2 {
.\NES\PPU.cpp4 R* A. [6 Y: P
.\NES\PPU.h
- W3 j" T8 N6 B) r  _, P
4 ?" ]+ P* t% b8 P如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:6 y' s2 M* ^5 k4 H  M
(由于很多专用术语和算法机理都不明白,所以看不大懂……)' U$ N7 z2 w, a* a) {( X
//////////////////////////////////////////////////////////////////////////# W" y2 R# r/ B2 H8 K, v% o
//                                                                      //, g$ O5 G, W0 K! Z3 l
//      NES APU core                                                    /// \5 }. e- I  X% H5 y  ^; b
//                                                           Norix      //
+ _$ ~$ y  i) w( i& l4 A3 o//                                               written     2002/06/27 //1 B2 y7 G) X3 M! D
//                                               last modify ----/--/-- //& R* b# `; M2 z; C: e# D" {2 m
//////////////////////////////////////////////////////////////////////////) i, K  C2 A7 {
#include "DebugOut.h"* o- p4 Q) i7 g$ L1 ?, ~8 b5 ^, E
#include "App.h"
) z6 t# n! Y1 x. z( u, {, ]. j#include "Config.h"2 R$ u9 \  z) [' }2 u
4 Y6 y3 q) e5 h0 W! @7 r
#include "nes.h"' t& h  \$ n9 K4 R9 h5 z
#include "mmu.h"1 `9 |7 O6 `  B) d
#include "cpu.h"
& [% V7 {6 z0 Y! t7 u- D" L#include "ppu.h"
) M3 r$ U# L2 V) m& ~2 L#include "rom.h"2 _7 \, _" Y: k# {
#include "apu.h"( a: o! F% O4 [6 @7 N! S/ @

; O$ M4 d9 J" A1 i0 h// Volume adjust
/ A- J( m3 J( k# g7 l( c+ }// Internal sounds' D0 M: V. [' R5 i# X& w7 o
#define        RECTANGLE_VOL        (0x0F0)4 o% n& R' A9 L* N% K; {* G* ^
#define        TRIANGLE_VOL        (0x130)
* N2 F4 L6 Z! g8 v! z) L#define        NOISE_VOL        (0x0C0)
" u, F5 ]# v' [2 \#define        DPCM_VOL        (0x0F0)! G/ u( x3 ^0 k/ o" v1 _
// Extra sounds9 V* S3 x) l; e6 R
#define        VRC6_VOL        (0x0F0)
+ P& [% {5 u* b2 k% H; v  L#define        VRC7_VOL        (0x130)1 [$ v( D2 S/ {
#define        FDS_VOL                (0x0F0)( V$ I6 m+ z* U! Z7 u& e4 m
#define        MMC5_VOL        (0x0F0)  v1 X6 n7 H9 o! D, n" L5 @
#define        N106_VOL        (0x088); X; j  d/ [7 a. C* ~6 l
#define        FME7_VOL        (0x130)
% Y, q3 a8 t" }
8 v) N" V, v: g4 XAPU::APU( NES* parent )
, i3 _9 q) a! T{+ Q! E8 x; Q6 q& o% [
        exsound_select = 0;, K- j+ G2 p2 q5 q. F. u
) f" V' X/ K& O7 g7 l4 d
        nes = parent;
7 [. j$ F, f! ]1 P4 |        internal.SetParent( parent );
3 O7 J; V5 ?: V9 e% R
9 g* s- G3 L2 G8 \# @2 k        last_data = last_diff = 0;
4 w2 A! R& N% d- {6 z" Y; v9 N- ]
) g: y! F5 d. Q6 w5 \- T' J        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 P- k, T! h  R4 l- S& Y
5 k8 n# L& z* V% K& E2 u
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
1 l7 s7 p9 a- R: P        ZEROMEMORY( &queue, sizeof(queue) );" Q& r( s4 {- R+ z+ {3 J) M  M9 ~! V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ Y" d3 j* \) x; b8 b* x: v* j! S; J& e" ^2 V& @5 X
        for( INT i = 0; i < 16; i++ ) {6 r5 P  ^3 ^3 T5 v% L
                m_bMute = TRUE;# ]9 q! n! A7 C) y. E8 G0 e
        }
3 d9 m. e) e6 o' Z9 p! n}
# K! O) F1 j+ E- r) k. ]" y# b/ d9 e. }* ^: ]. b
APU::~APU()2 `8 n  h0 q! I/ x" \$ r
{
2 o$ m( a9 P2 d: B}, |1 w8 U5 b# U  ~* r0 B# D/ y

; S8 B; v2 N8 V7 s0 i/ x/ \void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
* _8 H& A, W  ~0 M4 R# I6 o{
; |  O/ u% O3 n        queue.data[queue.wrptr].time = writetime;; h  L7 r# s& Y4 d4 |
        queue.data[queue.wrptr].addr = addr;6 ^0 r2 E& ~# F$ k" G8 U' n) @2 D
        queue.data[queue.wrptr].data = data;9 L: s. _! t( u  z' I
        queue.wrptr++;
) f% _% Q4 q* e3 ^* w  c2 ?        queue.wrptr&=QUEUE_LENGTH-1;, `3 z4 W0 H) D7 u- A6 X
        if( queue.wrptr == queue.rdptr ) {  b6 x/ {) O) l( h
                DEBUGOUT( "queue overflow.\n" );" `$ r4 U$ O9 p" k+ b
        }) w/ M9 t+ a8 G, J/ t8 L% B3 ^' ~
}1 Q# N# O$ e& ^- ]9 P) [/ T+ M, Z8 l
; b9 I  }  o8 m2 M7 e2 u% ^2 F
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )( g' Z7 F# L- L: V
{
) c4 ]# j- \( L  A        if( queue.wrptr == queue.rdptr ) {
% k0 R' E( j9 D5 {  y! y3 r                return        FALSE;1 w+ \4 v0 V4 ~& [  v: Q0 t9 l
        }
! B9 z6 a/ n6 C+ j8 @$ _        if( queue.data[queue.rdptr].time <= writetime ) {
2 W! R! S' |& z* T, ~( b; \                ret = queue.data[queue.rdptr];% f8 m- ?0 h/ U! J8 L  }' N8 ~
                queue.rdptr++;) z( B( ^' I: |7 G# P  f' f
                queue.rdptr&=QUEUE_LENGTH-1;: I/ h6 B) Y' x* w& y
                return        TRUE;
3 ?: k0 h  h) G* _7 @        }
6 o/ ~6 e7 |1 v' C; Y        return        FALSE;1 a9 ?: _! p$ Y' ~& {/ t
}
# ~9 o) a2 m6 w0 h% E" I
: @' P; ]' d% C5 s$ |  Q. V8 Gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 {; v/ K9 r, _1 A/ d$ q  d' H
{
  P8 V' Y$ t0 B, x: [0 [2 [0 }: e        exqueue.data[exqueue.wrptr].time = writetime;
+ f  f& h5 v( w! X) f- z        exqueue.data[exqueue.wrptr].addr = addr;
3 D2 S7 m8 D& z  c# o2 e        exqueue.data[exqueue.wrptr].data = data;) r) N/ ?8 H* Z% @
        exqueue.wrptr++;
; U. c% x2 D, |, v$ R4 z        exqueue.wrptr&=QUEUE_LENGTH-1;
2 w' S: m7 h" I        if( exqueue.wrptr == exqueue.rdptr ) {% @3 h" Q1 y* _# C  g5 K
                DEBUGOUT( "exqueue overflow.\n" );
; s; l$ J4 C' j9 R$ E" n6 _        }
, D8 h- w4 _( o9 m}
! ?* L2 H( I; v7 o+ ~/ f' q( c, L4 E/ c0 L+ p: a. {% e* J( n
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 s3 d6 O) B+ }$ D  L  y{1 u5 O7 i- q* v! `# m$ Y0 }2 v
        if( exqueue.wrptr == exqueue.rdptr ) {* q' N' K# D# G
                return        FALSE;
9 P/ Y5 T8 k5 z        }
5 X0 Q7 p8 b$ V. p% R" o, j# `7 c" Z        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
/ P. f$ H* B4 A# Q! m- J9 p                ret = exqueue.data[exqueue.rdptr];
+ e7 G/ E" _* U2 O$ u9 V  U# }! O                exqueue.rdptr++;
" W* N4 u( N1 H% C/ ]0 ~4 T                exqueue.rdptr&=QUEUE_LENGTH-1;7 J3 d* j3 p$ T- s( i# C- P' [
                return        TRUE;9 ]6 h% y" G; r. d# M% O6 G/ e1 b
        }" o+ U& S* ~  R2 W8 C& a
        return        FALSE;/ H% K: ^: F4 }: y
}+ z! M8 t) c* |0 J' u! G
. ^5 {+ F: c8 T7 y/ Q. z6 Z
void        APU::QueueClear()
$ n6 |+ n$ i: r% m{
2 p# r2 H7 X# M4 d8 e        ZEROMEMORY( &queue, sizeof(queue) );$ u9 c5 m2 ^; d: E( e3 O
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# u* M# E% e) Z3 \% u: Q}: N1 t# u" r! W. U2 K2 ~
, L/ `; B0 [8 G1 y' t
void        APU::QueueFlush()
; z1 h- d! y; g{2 \7 K) G4 N+ B0 R& a" Q% Q
        while( queue.wrptr != queue.rdptr ) {
# T" x7 K" m1 v* D- e                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* x! Z. u; n+ @3 u( ]5 j                queue.rdptr++;
6 c4 A4 k1 P% v& z1 K                queue.rdptr&=QUEUE_LENGTH-1;5 l0 t1 {* F5 S& U, H/ d
        }
) W' h3 x6 I4 x! e: q2 r. @- |7 \& P2 n& f
        while( exqueue.wrptr != exqueue.rdptr ) {" C, E5 N9 G, v" ?' m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
3 _6 j$ Z- L  ]2 D6 M, P) f$ d                exqueue.rdptr++;
, U% s5 R+ q& ^5 o$ R                exqueue.rdptr&=QUEUE_LENGTH-1;  J" T$ W3 S! c& F: a
        }2 q$ y$ W( E' I6 Z7 n# S7 s
}
0 u% O1 Z' \+ g5 h" s* _- R( y
0 C: f7 g# u2 a2 Cvoid        APU::SoundSetup()
) m; {1 V9 U; v# \1 |{4 |7 g5 Z+ X7 Y, r  o9 ?, O
        FLOAT        fClock = nes->nescfg->CpuClock;
# }( G+ o# X; T  ]) r        INT        nRate = (INT)Config.sound.nRate;
  q6 n: `6 X5 v( m) U        internal.Setup( fClock, nRate );2 m9 |# R1 _3 K) ?3 C8 W
        vrc6.Setup( fClock, nRate );* s- l2 t+ b7 C# F! @" Q2 W( {
        vrc7.Setup( fClock, nRate );
' G; |# @+ \% ]  |7 T        mmc5.Setup( fClock, nRate );
: F5 j& O( \# c4 p3 K        fds.Setup ( fClock, nRate );
  D, R4 c4 v5 }        n106.Setup( fClock, nRate );
8 S' h2 B* r5 {! O6 d5 z        fme7.Setup( fClock, nRate );2 D7 [4 N6 o0 Y! F2 \5 g
}: C- u4 w# l& s1 d4 H
( T7 r6 K0 e1 _: q4 F
void        APU::Reset()
+ w1 Z6 {7 e3 C* p{. m9 c6 `# J1 @) ^2 A# g5 u& A
        ZEROMEMORY( &queue, sizeof(queue) );9 Y0 X/ _5 P+ J  w' }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );; m' h, N1 @# U4 `- \; o

5 t/ X7 _; ?" W2 O! c. {( m! s9 e& l  n        elapsed_time = 0;
7 T$ d2 c; R: C9 W& J) h2 _5 r6 ]# E( I5 {" S" c
        FLOAT        fClock = nes->nescfg->CpuClock;
& `+ T$ q. o. l9 k1 \        INT        nRate = (INT)Config.sound.nRate;
  d4 m4 ?& e  O2 i        internal.Reset( fClock, nRate );
/ p+ U+ @7 m4 h8 A5 w) y6 y        vrc6.Reset( fClock, nRate );
; A" B! D5 `% e' V. ~% j8 s        vrc7.Reset( fClock, nRate );) O, C& A, X) c+ A
        mmc5.Reset( fClock, nRate );6 h4 b9 T8 l* h4 `
        fds.Reset ( fClock, nRate );# Q" `5 m% o6 F, X
        n106.Reset( fClock, nRate );
; ]9 l9 Y# ?4 ^4 q# K1 w" V) \        fme7.Reset( fClock, nRate );7 @% |% u7 R5 q$ M. [& G$ E

& V& ^, V1 S2 ^, t3 e        SoundSetup();& ]8 R7 g& G3 R5 T. c- b; ?1 g
}) w/ n4 p! k0 u, Q( e. Q

* C' B9 f4 m  l8 {! O' Gvoid        APU::SelectExSound( BYTE data )  j9 }: w8 l/ k( m: `  [: R
{9 }. K9 C( W, X: z; f/ H
        exsound_select = data;/ E  D( g- L) u4 b$ h3 M  w
}0 T) Y, w9 W+ F" ?/ u
' y' ^. v' G6 R0 y8 [
BYTE        APU::Read( WORD addr )" j$ h$ C0 X: M
{2 H$ @9 ^/ r9 b; {" l
        return        internal.SyncRead( addr );
; `2 s6 @2 q7 R" m- j}
, h+ J! h: O) E0 V
' y( }0 d( H3 `( F/ W" }void        APU::Write( WORD addr, BYTE data )
; e7 o  ]3 V6 a) e9 a{
" |/ R8 _3 x, n" w        // $4018偼VirtuaNES屌桳億乕僩
0 |6 V5 k- ^: D% z4 ]7 j        if( addr >= 0x4000 && addr <= 0x401F ) {
" L, G* _1 L  s! p3 j5 Y                internal.SyncWrite( addr, data );
. Q/ T- |7 k- L5 `# ], R4 n9 Q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );: Y8 m& m' f# H
        }
+ S: h6 ^  |# f" g8 p8 N}9 f( ]* u( f5 ^  z

* f  q1 [. {6 t7 F. v( ?6 t% wBYTE        APU::ExRead( WORD addr )$ Q% z4 C3 Q1 @$ W& {: a# K
{8 |/ }# i% g) y4 n
BYTE        data = 0;
1 w& u& e. o/ k. e. H
( {+ K! @: O: E) z3 h        if( exsound_select & 0x10 ) {+ y4 _' B8 D! I+ v& |, r
                if( addr == 0x4800 ) {
! o) z+ W( C$ z+ }                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );9 U! a7 U8 H' z) I8 W/ @
                }
7 \2 A  ~" z2 y, X        }7 O7 M! s0 u+ q1 g  w2 p3 q1 A& x
        if( exsound_select & 0x04 ) {/ E: {- p% G, j+ i+ t
                if( addr >= 0x4040 && addr < 0x4100 ) {
. Q" o& h4 z. }% n. e0 I9 i                        data = fds.SyncRead( addr );$ K2 h$ I$ O9 Y' F% p
                }$ W+ _; N( G. |+ u( T
        }+ w0 {4 }0 N( A) a) m; n
        if( exsound_select & 0x08 ) {
2 Y; M" n5 ~5 S" L- G                if( addr >= 0x5000 && addr <= 0x5015 ) {: V/ v& @( s1 M+ B* e9 G3 U
                        data = mmc5.SyncRead( addr );# _* \3 p* H8 x' P$ |0 ?
                }) ~$ A, f5 P  z. d' _" \0 a& a
        }; [& @- U& c( d' \) x4 s3 u" O
& q3 n% H6 q% U  x- z& K. h0 e
        return        data;! |, Y) A0 m' c: M: ?! z0 w
}+ h! C5 R; h* V, r8 p  o* A

$ c* M# S8 V  b  M/ t# B$ Pvoid        APU::ExWrite( WORD addr, BYTE data )* D) b( ^$ H) H
{
" P3 A) k& g' Y! P        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, I) F9 d; u7 U+ C
$ e3 d  G2 M3 R4 J        if( exsound_select & 0x04 ) {
% H7 u! }) w1 b7 l                if( addr >= 0x4040 && addr < 0x4100 ) {
0 U$ h  x+ ?2 B9 H9 l* T                        fds.SyncWrite( addr, data );
6 x; v4 P0 m, a8 y( j                }
. R8 ^% U9 H6 g9 Z0 a( V        }
% [5 [# g" f( s6 }
' D% \) c( }& S5 Q4 b2 c$ R        if( exsound_select & 0x08 ) {
% [0 s! z/ L( R" E; I) v, l2 ^                if( addr >= 0x5000 && addr <= 0x5015 ) {
" ~5 z$ T/ Z! u  d" x2 |: P                        mmc5.SyncWrite( addr, data );2 i/ L$ ?# `5 e- F; n. b. x
                }& k* h6 C8 s& r* W
        }  F+ K" j- e6 m4 H- n* r% H
}3 g% z$ W6 H4 c/ e9 c
9 F# V5 _% c2 J1 Y8 L. k# J+ V
void        APU::Sync()
" A' h& _& u: k1 ]{+ l) C5 F6 _+ _; \- r' d: T" v' L/ R
}7 e' l" Z. P' R+ {1 X9 T& P) J

; H7 w0 }' ^6 _. E1 E3 X; cvoid        APU::SyncDPCM( INT cycles ), l+ }- U0 N5 M* m0 p8 B. `1 O
{
6 ^4 g* V9 e3 P        internal.Sync( cycles );
- g. ]( w" O0 z& M. x2 m* Y. v' P2 g: o5 u0 n
        if( exsound_select & 0x04 ) {5 b3 F% G" Q( F
                fds.Sync( cycles );
# V( D' K! |0 a- ~7 ^        }, I( X) N$ S6 R- T! G  V  a4 F- P
        if( exsound_select & 0x08 ) {  t, B* }, A3 H0 I
                mmc5.Sync( cycles );  Z% j9 g* {+ P  ?1 v  d
        }- ?+ ?3 a& w3 ]7 @2 I& t
}
- a6 g  Y5 a5 f* m$ G1 J( b
- ^! I" z9 D% X2 o% A+ rvoid        APU::WriteProcess( WORD addr, BYTE data )
% j& A" R5 m2 A% i' ^7 F4 H: {{
8 g! k0 x8 B3 l4 ~( ]        // $4018偼VirtuaNES屌桳億乕僩- ^8 l$ Q6 z; G' s' `7 V
        if( addr >= 0x4000 && addr <= 0x401F ) {& J) I! N' W& U& q5 ^5 w9 n5 q
                internal.Write( addr, data );
' M- Q$ G$ W% d# o5 Q        }/ d7 @7 Y0 ~& b: f) D  ]# [
}
+ {  v( V+ \9 j: L) U; s. n0 m/ ?' ~" @) D/ d3 n" h; z6 m
void        APU::WriteExProcess( WORD addr, BYTE data )" r% v) W. I: h7 `2 I$ W( C
{
& K" S3 B. C- J6 }! R3 P$ |        if( exsound_select & 0x01 ) {) Z( v' k" F. E7 j% w' R1 z- R3 k
                vrc6.Write( addr, data );( A, \3 I. T$ a& x) s
        }! @# e( b& ]9 o& C
        if( exsound_select & 0x02 ) {& `9 d& B' B, P! G3 [
                vrc7.Write( addr, data );
& g2 m0 m. ~0 N/ a        }
& ]6 V; e$ j4 f) i5 I" E        if( exsound_select & 0x04 ) {/ j' q7 C5 |  P6 I! d$ ?
                fds.Write( addr, data );+ `- Y7 d9 f# L+ y- B0 h
        }
- D* D1 m3 _5 d2 o; k9 K4 s: G        if( exsound_select & 0x08 ) {" ^% e, o* a( U1 h1 I
                mmc5.Write( addr, data );
7 e8 W$ Q9 Q5 X$ X        }
2 Y$ p- P1 \3 u. `" a* s        if( exsound_select & 0x10 ) {4 ?3 W. E0 t2 G! n5 d+ g# J
                if( addr == 0x0000 ) {
- a+ Z9 v7 w$ c/ p                        BYTE        dummy = n106.Read( addr );
: ?! i5 [. B/ b. f- f+ m4 I                } else {* _. v$ b) Y' V) [: c
                        n106.Write( addr, data );
6 i+ Z: Y! N' W6 Q- {; c" d                }5 Q, k+ O9 h' W5 @+ V+ ^
        }- A( D; x6 M) f1 y+ w, B* y
        if( exsound_select & 0x20 ) {
( F8 l  F9 Y1 d) ^3 k; l( v                fme7.Write( addr, data );; P# f8 C3 N- D* G  ~
        }
6 A; G% E% f$ o8 H& O}; L" {$ G) f3 d: d
3 l& {3 e, I: g8 ]
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ E3 T/ g4 V2 F7 U1 J8 Z0 q{
1 h5 W& O0 V; E( oINT        nBits = Config.sound.nBits;
9 h2 _: H' _2 b1 jDWORD        dwLength = dwSize / (nBits/8);/ i$ j, u  }2 k3 r
INT        output;* R3 v0 r& N% P7 S+ ]2 i) g! {  Z
QUEUEDATA q;3 K' q% v/ U  u8 f$ G, O* X
DWORD        writetime;
1 s5 P2 |" {' b' k9 _, n$ C/ D
- r2 t7 y4 q1 w; MLPSHORT        pSoundBuf = m_SoundBuffer;
0 @' K2 }: l' U6 BINT        nCcount = 0;
) F; b- X/ W6 r0 _3 J
3 a6 S- Q& x1 iINT        nFilterType = Config.sound.nFilterType;& B; m" L2 j8 `7 M

8 i. F/ m: m  P( H7 i        if( !Config.sound.bEnable ) {
$ D! k* D% b& S: x" g' N6 }                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
! [+ d. c: G% J5 |' p+ \3 q                return;2 A. V% v6 O  h7 m0 k5 }8 g
        }2 R6 s& L4 |0 T7 z. Z2 c( ?
. g0 t1 c9 S5 M$ S! n: t
        // Volume setup, u$ \6 }- `' A1 O# t9 z, w
        //  0:Master
2 n# [9 s1 {6 I  E( B        //  1:Rectangle 1* v  K- P' _6 Z  w1 |
        //  2:Rectangle 2
- r$ t  ^' S0 F/ B- [        //  3:Triangle
1 D- W& P$ S8 A7 M! Z0 ^2 r7 m        //  4:Noise- A7 [4 Q( l2 B2 u
        //  5:DPCM" l( ~4 ]* ^* V2 r* i, Y; y' a
        //  6:VRC6
, o8 O6 E0 M  s8 q% F5 H# E        //  7:VRC7
( i2 t' Y/ U, H        //  8:FDS
! m$ N) [* m4 z9 p) X+ ?# ~% v        //  9:MMC5
. ]: h. s3 S$ J6 j! J- w        // 10:N106
" J, V! W' [4 w; |        // 11:FME7
$ G) z9 F1 ~0 \/ W/ _0 s        INT        vol[24];7 o- |% f; t3 x. v4 c
        BOOL*        bMute = m_bMute;* l( B  N; y, r" k, i$ n4 _- l; m
        SHORT*        nVolume = Config.sound.nVolume;& M/ f0 e4 ]' |( m6 ^
, Q7 j# o1 k4 E5 A
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 G4 \: N& V; e! G, i

; f  O* ?8 P9 g4 U. L0 c        // Internal  x" A* f- {6 A7 ?: K: \7 y
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
. V! D. u: s9 g& W8 S. g( b        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
- m( I7 W: ^6 ^$ L        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: G! L; y- p$ H" s. J. n& ~        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
0 k  O2 I* c  O        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;3 L/ U3 i! v5 Z6 q2 u3 H

/ i- D( A" A6 T1 G. N5 {/ ?        // VRC6. B  k% l; B+ r3 {
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ Y; D# B2 m4 `$ a  J
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( r# _8 S+ g) f! C* T9 ?) X( _1 C& Q' g        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- t# i* G! H2 c. X! r' H5 |1 D9 k6 }  M% W2 ?) W6 S
        // VRC7
# E/ m$ f* T1 V" U7 L! }) l        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
% ^' l' d* H9 Q; e' U, v' Y
1 `2 O7 f0 ?& p* I, y$ _        // FDS
3 ?6 X" c" a% l, S( w        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;  [3 a- t) q8 A

; S6 [0 p1 z/ }( F" m5 n        // MMC5
: u7 K9 q( H# w; b  M0 E& K        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ R4 P* `% S; s+ j/ F3 t" Q' C        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 {; S8 w# _# L- l        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# P0 Y; |& T# X' a$ B4 b
$ r" z. {) h" ~7 r" [4 Y4 W9 ?
        // N106
4 O  H& \) i1 w$ _& y        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 W1 \4 Y" }& [( k* m& R
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 d4 i8 C+ h% _# \9 ~5 X
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 n) C) G% K9 C" g
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% J0 R0 Z  P. v, C
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 K# _, \% k# |0 w+ @        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( h7 }: Y9 H- \+ g
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. l$ g( {2 R! j& i3 f        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( n; i/ p$ b  U' i' `: z

# k( k5 h2 o  \, U* |        // FME7
. w( E- j* t% \$ V4 n$ ]        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: E+ t6 J3 L' c6 |, o6 D
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  j% k( ?: [/ o0 y7 ]4 V        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 v. Y8 s# t3 ^" z' J" ^! S- \$ a9 q: b
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" @0 @8 X9 [% y" q% z  l$ \
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 u4 a+ w" }; T6 t
: D& L1 G: Y, J  Y; p2 [5 f" y. P2 F
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟% W( C" |7 h; T+ k- k. {. ^% F
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- s! C" c) Z$ C5 Y5 ?  g, n
                QueueFlush();
# M/ |: Q, `0 M2 U9 p0 B, n        }+ K/ i+ B2 f% V0 U! _6 L

9 p9 i) B& r' K# H* e/ `' N        while( dwLength-- ) {! L; ]. W& }7 w+ W' E; I5 S0 n6 r- f
                writetime = (DWORD)elapsed_time;
! e. q3 a1 J; F$ h) N5 V! p4 w- r4 W) n9 }
                while( GetQueue( writetime, q ) ) {) Z) ]( y; G7 F/ H( m
                        WriteProcess( q.addr, q.data );
, u4 B. h  a1 s+ e3 T0 m                }. w1 ~% V2 Z  Z" V* e. n7 l

$ G. ^7 o* D, {$ ?4 V3 h                while( GetExQueue( writetime, q ) ) {
% x4 f& ?. {) F) s, n# \9 l                        WriteExProcess( q.addr, q.data );" G2 R6 ^! q9 z9 f  E% K$ ~. U
                }
; s# r: Z2 [+ s$ ~. ?3 q$ y5 L* l( |, a" u% W4 D  N+ B: ]' z
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
/ d/ r" [5 S$ _) s2 u, \                output = 0;
# e' ?, G  H2 M. ?2 l                output += internal.Process( 0 )*vol[0];
+ }! {3 f- g% }9 B- Y8 J                output += internal.Process( 1 )*vol[1];
7 h8 v* P- ^  P8 \+ D( u4 d8 b                output += internal.Process( 2 )*vol[2];# m# e% w4 T0 q2 p3 O& m
                output += internal.Process( 3 )*vol[3];' N- l/ [0 ^) D' F
                output += internal.Process( 4 )*vol[4];
. _  P  I3 W) E* N+ \. z: ?7 j7 y
                if( exsound_select & 0x01 ) {
" {' s+ q2 R1 i1 W+ z                        output += vrc6.Process( 0 )*vol[5];
, w6 A, C# P% |! I                        output += vrc6.Process( 1 )*vol[6];# }2 U# E2 Q2 f2 A& x2 o3 w. x4 z
                        output += vrc6.Process( 2 )*vol[7];% b2 B7 ~, c+ C. h9 M/ l
                }
: b; n- H) D) t6 E# D" T                if( exsound_select & 0x02 ) {$ w0 m) m2 @* j: v( }% _
                        output += vrc7.Process( 0 )*vol[8];1 P+ h: d3 W: N0 X' M9 N
                }& ?' Q; M, o5 f2 d. Z; Z# X& X
                if( exsound_select & 0x04 ) {
% v: O1 x' ^3 I                        output += fds.Process( 0 )*vol[9];. p' q9 ]( w3 f8 `0 \  ]7 x# q
                }
4 B; \- X; `% k4 D+ m# d. q( N' E! s                if( exsound_select & 0x08 ) {
) N# d* E0 \: q1 C5 x; ~# y                        output += mmc5.Process( 0 )*vol[10];- P1 I) g. T, J! l. x* \
                        output += mmc5.Process( 1 )*vol[11];
+ _( R! a) J1 y3 ~                        output += mmc5.Process( 2 )*vol[12];$ U# ^1 H8 ]) _( c9 \7 i. z
                }1 y+ y4 x2 f* c5 {
                if( exsound_select & 0x10 ) {
% w! c2 c; P& A9 p                        output += n106.Process( 0 )*vol[13];
. t$ h* `5 L7 r  a  l- A                        output += n106.Process( 1 )*vol[14];6 T1 X2 c) {7 t9 c* D+ [  ]/ W3 S
                        output += n106.Process( 2 )*vol[15];
( W* K! @" ]0 s3 u8 D0 Z$ Z; n                        output += n106.Process( 3 )*vol[16];
& K) @' N; {% s* [                        output += n106.Process( 4 )*vol[17];
3 ]4 U, }0 W& S+ q) Z& q                        output += n106.Process( 5 )*vol[18];
( J9 j1 O% ?$ m% ?" \/ p                        output += n106.Process( 6 )*vol[19];
# v, X* ~; d% V7 F0 }  _                        output += n106.Process( 7 )*vol[20];* C  y; G  O  t8 {2 w7 o% l% G
                }
3 K& a+ I& u  @+ s" E* N0 A                if( exsound_select & 0x20 ) {
' W2 b& ^3 }: ?2 o6 q: }) f                        fme7.Process( 3 );        // Envelope & Noise
$ W' A; f# m+ E9 _7 T                        output += fme7.Process( 0 )*vol[21];4 j* `9 L& ]7 v3 h
                        output += fme7.Process( 1 )*vol[22];- j3 C- U7 L" }7 X2 S7 y7 [  X
                        output += fme7.Process( 2 )*vol[23];) k( a) M" `' F4 d7 s" b7 |
                }! ~- t7 {: y; V" u% h6 V" G& W

- ]$ P+ g. N; i% R# ^: ~# q( z                output >>= 8;
0 v; L$ f. S: P' F  M/ i  J8 U- V. s' a3 x) ]6 ^5 K. G6 }
                if( nFilterType == 1 ) {
, A  V( Z& u9 x) Z, ?6 z                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)2 x6 ~6 R% C$ Q' ?6 @# v
                        output = (lowpass_filter[0]+output)/2;
# b- w! l7 Z: Y1 R- w+ [                        lowpass_filter[0] = output;* B# i+ j, L5 y4 v* i. x( ^
                } else if( nFilterType == 2 ) {3 X* Z: z# ^6 m4 X" O
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)8 P- F3 [: @% k
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;. O; W' r/ K- n
                        lowpass_filter[1] = lowpass_filter[0];' V/ ]; }8 f! E( V
                        lowpass_filter[0] = output;: Z9 @8 y$ @8 Z: N
                } else if( nFilterType == 3 ) {# _% S6 ^7 z" r" j+ o
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 M: E+ c- k' c1 |. j. k9 k                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 q1 ]. x. C' ]! Z- t                        lowpass_filter[2] = lowpass_filter[1];8 [" _. o- e5 W2 z: x
                        lowpass_filter[1] = lowpass_filter[0];
! j) L3 d$ s9 D8 ~                        lowpass_filter[0] = output;8 F# z6 O& L4 M; X* _: y+ D9 \; L
                } else if( nFilterType == 4 ) {
& U$ X6 G  s1 ^/ [7 O; ^                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
5 W. A- I9 l( y) O) G% n                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;0 c4 v0 K# E. ?' ]: T6 y% u- q
                        lowpass_filter[1] = lowpass_filter[0];
+ U! E+ p% [: v4 Q. ~  b( l! H                        lowpass_filter[0] = output;& n8 B* z* L7 Q  Y3 A) p) I$ F) t
                }7 c0 S9 s7 v1 M: [/ q# g% P
3 _/ C& Z! s5 F3 m$ w( a3 J* B
#if        0
3 r6 I- D/ C8 F% V& y                // DC惉暘偺僇僢僩( F! @# R  N- t. Q& r
                {6 `4 o* }0 P3 R- M' u1 M
                static double ave = 0.0, max=0.0, min=0.0;1 l$ B4 o0 u$ v9 g; J# r. W
                double delta;
  i0 o& U; _6 `( P                delta = (max-min)/32768.0;
! S, ^; e. _8 a: o                max -= delta;
" A5 Q5 S. z# y( w% z! X* g                min += delta;
8 Y$ v) P5 R( |% m0 C                if( output > max ) max = output;
* {' I1 U# w! {5 N* j, {% m& T                if( output < min ) min = output;' W! p# n  p3 V  h; Y7 T1 u" ]7 v
                ave -= ave/1024.0;
: ?/ b4 B/ p, Y* H; t                ave += (max+min)/2048.0;
# }0 v3 w1 \9 u. F                output -= (INT)ave;
) z3 ?/ ~  n; e4 x* i" \% E                }% H: d6 Y8 k( L1 @3 h& i
#endif
0 [+ o' ]) ?- ]* F6 t- G#if        17 \1 ?( h2 p, v( \* V9 @& _
                // DC惉暘偺僇僢僩(HPF TEST)# X* ]* K8 k5 K; E6 e- \8 I
                {
1 ^3 ?6 S6 ^0 e, }8 r) ]! d8 D: K//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
# I6 \' x( b$ W" y+ @, L: _( f' S                static        double        cutofftemp = (2.0*3.141592653579*40.0);
! b# x, Y7 I+ z0 z$ \. O% {$ w' `8 o                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, Z8 z9 P  L: m0 ?9 T9 A                static        double        tmp = 0.0;
6 r0 R2 [3 t: j. `! `5 m                double        in, out;
5 g; i1 b  R' h; M: G6 J. A
& u! ~) B4 l. r$ D% L                in = (double)output;- Q  X: Y/ m7 k/ j
                out = (in - tmp);2 e6 h. j' A! r  n  U4 s
                tmp = tmp + cutoff * out;
1 A3 }0 |/ i* C$ K9 F; a+ I4 t/ `- s) ~9 `
                output = (INT)out;4 w: M9 V3 k4 w; p
                }
  U2 c: Y+ H  H#endif. _: e# g7 ^' N  R8 k% c1 Z, ~
#if        0
! Z5 v- S; r0 _0 R/ z                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST). B: m5 I  X( O; o2 S
                {
% r1 w( ^: d0 N% i  y                INT        diff = abs(output-last_data);. y$ w5 F# X  N2 v
                if( diff > 0x4000 ) {
7 B* L; o1 N5 o* x; c8 p: V                        output /= 4;5 {2 g. q7 z) @2 h
                } else   K# O- r3 t5 \1 P; E! C6 o0 D9 d
                if( diff > 0x3000 ) {5 i- O# n' x" @& F  V
                        output /= 3;3 r" A/ _, z/ R5 E2 k7 L
                } else
+ L# L4 b& U7 E2 O2 D                if( diff > 0x2000 ) {
- r) T5 n" `' k. U, y3 ]$ y                        output /= 2;
4 Y; W0 v: M/ m; S: F! m% m; u                }- g$ ]' s8 ^4 t9 i" l) E
                last_data = output;: J, Y5 R: P3 s5 c$ q8 S; n
                }
# D6 N2 d! K( d% x( N4 h#endif8 w7 f) j9 N7 W3 D3 j7 s4 p
                // Limit
* K$ l8 r0 C7 a( K0 T4 n. v0 s                if( output > 0x7FFF ) {
3 c7 \" f% X* p% L2 F- E) \) s* }                        output = 0x7FFF;
( h' g2 ?3 ^7 ?& [( {                } else if( output < -0x8000 ) {
9 k' I# V. a1 S  x2 E                        output = -0x8000;3 Q/ j* \" {$ C5 `
                }
8 g  G" e/ ]! v& k* E" Y% V* A0 v2 A6 v: ^
                if( nBits != 8 ) {
$ h: d: Y2 U  O- D                        *(SHORT*)lpBuffer = (SHORT)output;6 p' A( n  f- P, d  t
                        lpBuffer += sizeof(SHORT);/ c- M; k8 a: w9 n# S, q. W8 V7 {# h
                } else {
" _& _: t( D, i5 p' m9 I                        *lpBuffer++ = (output>>8)^0x80;, P) G) k1 P; Y+ F4 o
                }
8 z! i$ \0 y8 ?  y. V% F& i1 f) w; Q+ ~5 g5 ^% y( b
                if( nCcount < 0x0100 )6 P% N- m1 G, {- A
                        pSoundBuf[nCcount++] = (SHORT)output;9 |+ R5 W7 h# F5 F

! v9 ]. v& i' n2 o//                elapsedtime += cycle_rate;1 W/ ]4 ?+ |* E# t  D
                elapsed_time += cycle_rate;
. E- d* S# O0 B' P/ t        }
. K+ C5 c' c5 a3 A- U( z8 w9 ^
( t" z* ]6 s9 U#if        1
) |! b* k- J% ~1 d        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {3 X7 o8 q3 _0 |" E- U: x
                elapsed_time = nes->cpu->GetTotalCycles();3 e' y# M3 H# |: L. X
        }
$ y1 ^$ D' ?. i* Z7 m$ |        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
# [7 |' d4 l( U& i+ V9 \. c, E6 a                elapsed_time = nes->cpu->GetTotalCycles();
+ u& \5 l. m1 T; s- u        }$ c2 b7 A( |) q" B3 Q  y  z
#else+ c5 C! M8 F5 y! H
        elapsed_time = nes->cpu->GetTotalCycles();" z8 F# _6 t# o- f. m& W. y
#endif
: v! V% h9 Z  q/ I2 f, A& @' W* t}% c( Y: r0 p# f6 G3 i
: w+ K3 [' s& d- p, n
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)& x8 v. B9 D, O
INT        APU::GetChannelFrequency( INT no )
7 B2 }1 I. ^$ u$ }. b{
+ g/ K* d) z3 t( E8 T1 N: U  I        if( !m_bMute[0] )
, ]7 q- [* Y* z$ N8 N" F: }9 U2 k                return        0;
0 V5 B- {9 }7 f7 G" y  t# e+ r" r  h$ Q( i
        // Internal3 c; n+ X6 J! J6 a* z$ `8 B
        if( no < 5 ) {1 o* Q' u- W0 V
                return        m_bMute[no+1]?internal.GetFreq( no ):0;: i0 q8 |9 V- b, k: x
        }
" y7 z! B- v2 i$ f! S$ E        // VRC6
+ A$ n/ F6 z$ {        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {3 O- I6 c3 M2 |5 F% D( ?& e, j. t
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
. g; ]4 s: r1 g5 }        }' W* P+ X' W8 Z
        // FDS& E# Z& @2 r5 l* Y3 U5 g5 O- p/ t
        if( (exsound_select & 0x04) && no == 0x300 ) {
0 L" R: K. n; w  Q: `9 y, n; b8 ]2 s                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 v6 m$ A7 \2 {! b
        }
- J- D" K5 n1 ~        // MMC5' G9 j/ G( `6 K5 q0 i' B
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {" J* ~* a3 Z8 I0 N) m
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;! L4 E- b% D/ E: F- ]
        }0 ~7 @8 z/ w  L6 Z
        // N106
7 c% f( e  ~6 k* [; f0 x+ |! r8 P        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- J: H" A' u& i# w" m8 U% C                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;1 ^( U( ?0 m0 @% F
        }2 y* V3 N9 R* r) r3 Z! X
        // FME7
, O" a2 n  `; E9 j5 b* I' e        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
; u4 A. }/ }4 O0 l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
( @' y0 J. P$ M# ]+ F9 }        }5 j5 s) w0 t2 Y) N! |( ^" P& E" O
        // VRC79 a+ R/ F; F1 Y4 ]& V
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {$ l) G. f3 O. l
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 \$ n. L( X6 T5 `        }- q' l2 R1 O# x) Y/ L
        return        0;; Y, m9 {5 D/ `# {2 O
}* w# ]4 O. S, ]! }0 ?/ }

8 s# h; }9 O% b4 d% Q5 Y) v9 a// State Save/Load' k, ?0 _  T; @/ c' g" D2 U7 t
void        APU::SaveState( LPBYTE p )
/ U1 R. v- R. z% G{
0 S# Y+ X, o' \& b' i#ifdef        _DEBUG
! {1 x7 m; J2 P7 }LPBYTE        pold = p;
( G3 ^" b0 n3 X3 l#endif. M& s% M  O- l

5 E4 k$ z% T+ T9 R: M" E! q        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
, o4 T1 O3 K/ A/ Y& M' J        QueueFlush();
6 I6 ^3 f, r4 e, C! `% D3 @* z, g( S# ?& x( y3 J" f
        internal.SaveState( p );+ {/ U" a( p/ A
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* H+ Y0 e6 P3 Z5 ]! j
7 r  A% }* ~& K- o# V        // VRC6  O/ s. u& G4 k" F1 j) [
        if( exsound_select & 0x01 ) {2 Z; C  v( q- f1 ^
                vrc6.SaveState( p );
) |3 _$ t0 i! }% v4 R* D                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
8 G- C  u: @' |+ z/ g8 \% E2 c        }
8 u3 a, o( _+ J        // VRC7 (not support)
! k. Z( b) J# k: H; v        if( exsound_select & 0x02 ) {
( p; D3 I$ q+ e! ?2 ?0 L: H$ v                vrc7.SaveState( p );& m* a" A: L8 O7 V9 |  k: y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, A& d5 F8 a1 E: L) R4 p( ]
        }
  n# K* a4 v. H        // FDS
( ?8 l- S9 n6 A# x        if( exsound_select & 0x04 ) {) A, ~( |6 F. j# |7 y
                fds.SaveState( p );
/ t% J' L1 b6 P  D' a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" w2 {0 C! a9 A- v+ r! J        }
8 U( ?: L& _8 t" F( {        // MMC5# Z( J. I3 U& q  e9 j7 k
        if( exsound_select & 0x08 ) {
) z6 l1 y5 i7 A' E/ J  p                mmc5.SaveState( p );
0 F" ]* i. }; [7 O0 R2 v                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( D7 j# d+ F, F% K  l        }  e1 W; G0 x0 @- A! L9 L
        // N106
; }1 R% q. i  l        if( exsound_select & 0x10 ) {, E8 i8 J% p# b- i0 e
                n106.SaveState( p );+ M; ^4 \$ k6 u0 Y  _2 a! l* P/ r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* n" D6 o3 q! m7 ^0 g: t
        }: \8 y* n3 m+ F% ^$ v$ J: V
        // FME7
6 E2 q: R7 m+ K/ t# S        if( exsound_select & 0x20 ) {
" _  T9 G, u$ Q" e8 a( e7 D                fme7.SaveState( p );
0 }' ?7 |! m# l( D4 X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# e5 H7 y9 g- D        }
, `; k1 H* `* D8 d6 U' a: O
; P/ o' F4 n/ l0 C" o#ifdef        _DEBUG2 j0 c  E% {$ C) B
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 [/ [( Q7 X! y" i! I% z! E#endif
6 v" A. P4 a2 A: o}7 S4 F* y* Q1 }
: |: F  l; Z- A! c" y
void        APU::LoadState( LPBYTE p )* D3 D3 q8 s2 l. e. p. ]
{
2 U$ Q% l- O( I        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ J/ Z7 F& A$ ?, N
        QueueClear();( b& G% S$ Y4 L. l, g! X

: e, r5 z, s- j9 f% X; `        internal.LoadState( p );
& \9 y: c- n! @7 ^0 F# s1 |7 K3 ]        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  Q; }( l3 i+ |) N4 M* c7 I; p. Y. ]  ?
        // VRC6
) c$ _7 b& W+ k: u- [. L1 o% U( o        if( exsound_select & 0x01 ) {7 Y' C) q3 j! [, U; r
                vrc6.LoadState( p );
0 O) Z! ~2 L$ s; T9 `  ]: G: r$ }9 L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
8 d$ l7 }1 n( B8 Q- ]( U8 I2 ^  x        }
6 O! c9 V$ p. S" |, V$ L/ F: y        // VRC7 (not support)0 R4 u& ^- V$ |! |5 J
        if( exsound_select & 0x02 ) {
4 J/ p) F9 v8 V& L( z! t                vrc7.LoadState( p );  \4 W" X! P- B0 U9 a$ y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 q+ {' Z4 p1 |) ~5 b- M; ^9 A        }! m2 G9 n/ F) A; W
        // FDS
8 h8 j( K8 w( h  h- @, h: o        if( exsound_select & 0x04 ) {/ X" E5 a3 ]' A
                fds.LoadState( p );
6 z; f$ O. f- ]  ]+ {" ?0 [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 v/ Z; T: X# C9 g# S
        }7 m2 c7 c( ~" |3 K' W4 x3 b
        // MMC5
6 i5 ]& P+ q$ C        if( exsound_select & 0x08 ) {0 m* w" `, Q0 s8 m( \" o. O
                mmc5.LoadState( p );
+ ~; G! X! l: J, c                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  A5 e; _8 \6 u3 m0 }        }& a0 @( A3 h8 \. n
        // N106
7 y" x* ]* |0 q5 I- {        if( exsound_select & 0x10 ) {
/ M- ~0 a9 {9 k0 g5 I/ Q                n106.LoadState( p );* y5 R2 B, e, ^  e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 G, \& S! J$ m1 l: v* b' h! g        }
3 ], ^; ^7 ]: l: {        // FME7
' U- t% E% X* Y# u        if( exsound_select & 0x20 ) {
' R5 V# L8 p5 N0 M                fme7.LoadState( p );8 z; B9 @6 ~" m
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  _0 V+ `' N( R5 p0 I6 ]: ^
        }
! ~5 T. i: ~8 x+ C# A& x( o}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
+ J8 \; D) ]! W7 x6 ~( y# q/ R可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
2 }9 D* {7 D( P7 L4 f感激不尽~~

( J9 I5 ^* O+ f6 c1 }! O' T9 M恩 我對模擬器不是很有研究,
, A- u& C7 h& X, f% o雖然要了解源碼內容,可能不是很困難,6 }6 u8 c# g3 Q$ O" h% g
不過還是要花時間,個人目前蠻忙碌的。
6 X: E' r6 k& e0 [. E# k1 w
+ W8 P5 l3 ~; b7 c1 m( W. i給你一個朋友的MSN,你可以跟他討論看看,
2 G# g6 Y/ U0 q5 B- x  I& I他本身是程式設計師,也對FC模擬器很有興趣。2 Y$ G+ \( g* N  A8 ^* s/ n

* L/ `3 ~- [) _$ y" oMSN我就PM到你的信箱了。
( u6 N3 n  b! U' b& {' Z: ^0 E' h  i) V  c" u% e8 o! S7 b4 s
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 e1 B# }  ~/ `6 f7 H呵…… 谢过团长大人~~

* B8 d# r# z  n. Y
& Y3 B9 q- T  D4 x: \/ k哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
, C4 p1 o' r) W7 @) @# Z( z" m团长的朋友都是神,那团长就是神的boss。

, S4 b& O5 N9 J; n/ n9 q6 Q  ?哈 不敢當,我只是個平凡人,
/ r/ Y- e' o/ J2 s  l& S要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
, ~% c6 s; J. v/ b# X0 ~$ H1 tZYH
; A5 D/ L& G. L! w8 ~4 H) dQQ:414734306
" N6 C7 m/ a* ~/ nMail:zyh-01@126.com
# i" K+ U2 [7 S+ G) O( i; o, S# b- _6 D
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 4 N% q3 o3 F$ p+ U
再次对团长大人和悠悠哥的无私帮助表示感谢~~

8 t/ q! q4 E# L; F' z  z, c: D不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-26 01:35 , Processed in 1.075196 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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