EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 Z0 g( r6 Q1 v+ z7 G0 E
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 d5 k8 w2 _* j这里有相应的模拟器源码,就当送给大侠了~~# N( [* \) T; n  z3 N0 N, I
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * G1 g; o2 x. j) J. [7 R/ W
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 U4 R3 [* }5 {# Y0 o) Y0 ^6 V楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& U' _9 n2 h# O8 w. F
这里有相应的模拟器源码,就当送给大侠 ...

1 B0 E. C; Y1 |+ m% w聲音部分(Audoi Process Unit = APU):; ]& `' j& _$ c) q# e( d
.\NES\APU.cpp
4 x  Z( r+ P+ [9 f- X& p" i$ }.\NES\APU.h7 }% j; K9 x, ]" y$ H( `- f* Y

( D7 a! y( H; z7 ~# B* W& @" [
0 S# u/ F: w6 V6 G; k8 f影像處理部份(Picture Processing Unit = PPU):' J2 s2 w( M+ h+ K+ X! U; m; @
.\NES\PPU.cpp
/ t: l7 M( J  c7 }( V% }& \) u.\NES\PPU.h
6 H8 j9 Z1 ?( Z# B
5 l6 Q. b4 D+ C8 [0 N4 i7 L; z" p) S9 C如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
4 m0 c- o7 P9 m(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 `" X6 m# v* o) l% W8 Y//////////////////////////////////////////////////////////////////////////
, i1 N% `" n4 n; }7 E2 Y+ r3 C//                                                                      //
3 Z# y: n# d& c* Q+ Q/ E//      NES APU core                                                    //
+ s% v* D6 I4 i2 }9 E//                                                           Norix      //
6 g0 f7 X1 F* z/ r5 C//                                               written     2002/06/27 //
' G3 Z" v# R' b- c) g//                                               last modify ----/--/-- //; N1 Y( H1 y, d5 z2 ^4 z
//////////////////////////////////////////////////////////////////////////
0 @5 }) }$ M% `$ V#include "DebugOut.h"
2 S  Z1 T6 S* d- y7 n. S# B#include "App.h"; X0 t$ s' X) `- L% f& z4 P2 |8 ~
#include "Config.h"
$ `3 V; i: R6 D  E, f6 X1 g: ^, \( P3 u5 j
#include "nes.h"; b( I$ F' [6 ~  x0 T
#include "mmu.h"
* |. t9 Y! f4 w) m9 O8 u#include "cpu.h"# r' ?' F* Q+ I" o7 q
#include "ppu.h"4 P5 B$ P% r3 K8 J
#include "rom.h"# Y  x' N2 J3 ~5 r6 n" y0 K3 A
#include "apu.h"
, I. Y" F. S8 ]/ o! u
) ?) X+ y9 l3 U4 c& H# R// Volume adjust9 w2 ^/ n1 l& @. P7 V! P4 w
// Internal sounds
+ D& S( x7 G1 s4 s3 [3 \% K#define        RECTANGLE_VOL        (0x0F0)
$ P& I8 P2 g4 R9 a. x0 l$ \#define        TRIANGLE_VOL        (0x130)
! [" Y6 B' m: O( E#define        NOISE_VOL        (0x0C0)# a+ n8 @: ^4 L$ Z5 R$ h  h% b! A
#define        DPCM_VOL        (0x0F0)
  O# u# Y2 ?3 E% }// Extra sounds
4 @& U( u, J1 i* q) H* ?' u: u#define        VRC6_VOL        (0x0F0). G( r$ i; [- H/ B* G" C8 o
#define        VRC7_VOL        (0x130)9 J2 ^9 V( a) v, ^1 p
#define        FDS_VOL                (0x0F0)
' R' G( H! v7 p. N/ [; k. D' |1 n#define        MMC5_VOL        (0x0F0)6 F4 `9 |+ d6 X( q5 c
#define        N106_VOL        (0x088)
2 ?: Q8 o+ z" n9 [4 U#define        FME7_VOL        (0x130)
2 u9 y" [0 ^, z2 H, O+ k% \* x2 q0 H5 ~& m1 ^& T5 _! p9 Z" F
APU::APU( NES* parent )
- I/ O& ]5 Z+ s5 [( k0 N{0 D( J  o( {+ E% D
        exsound_select = 0;8 I, r7 j  i" F2 X
. m) G3 r( P0 A. ?0 U5 t) m
        nes = parent;
5 t, C) ^* x+ H  s, L0 e, j        internal.SetParent( parent );
' J6 X  }9 f6 u. r8 f1 R& ?' R- u; Q5 q/ A& R
        last_data = last_diff = 0;
6 s6 A5 Y& B) D' r9 q0 S5 @3 u; l- H. @! B7 L7 |
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 D; [6 \7 C& K. k5 h

  P* C5 Z6 {  Q, J        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
% a# w& V- Z2 s9 O0 S0 q        ZEROMEMORY( &queue, sizeof(queue) );
9 k$ s& L$ ?) W6 L9 z' m        ZEROMEMORY( &exqueue, sizeof(exqueue) );! V5 }) _. M+ ~# _: r4 B3 p
6 c5 v( z; p3 R1 [& p& N0 z
        for( INT i = 0; i < 16; i++ ) {
+ ]2 @1 A8 W& ]                m_bMute = TRUE;4 W1 ^1 o5 _9 E7 X: j6 |1 S
        }
( d( V# @7 J7 J8 }- v' }}
7 r/ j+ `5 b* R' [" ~: v( n" {
$ W& x1 ~0 a3 q1 l4 ?& vAPU::~APU()
0 R9 T$ G$ r7 N- \$ |{1 w8 t6 V+ B. Z7 w7 d
}
! F! x+ I( W, _2 b
+ l4 T" n' C% X' s- fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) N: ^) O1 o' w+ N! F3 n{+ Z% E# S) |' S, u$ }( t' d
        queue.data[queue.wrptr].time = writetime;
5 \" B( u6 q& z        queue.data[queue.wrptr].addr = addr;
, b" h* [% n5 x9 s        queue.data[queue.wrptr].data = data;
9 R, {! K$ Q/ v- Z' A        queue.wrptr++;
7 k* i# G" M$ ?5 B( `( U5 j        queue.wrptr&=QUEUE_LENGTH-1;6 g) n: c; r, d; o
        if( queue.wrptr == queue.rdptr ) {
- j8 j" J4 d+ ?' D, C                DEBUGOUT( "queue overflow.\n" );- v& u1 L) @. K/ V4 X% a, n7 Q
        }
6 L( D1 [. H) k}
' C# m- Y% x7 a9 x
- F6 K: L+ i$ J# PBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
' x2 J: |) G* B2 r- Y" S$ M9 y5 M{
0 N: [/ ?' r' X        if( queue.wrptr == queue.rdptr ) {
+ D6 `2 C- @3 v                return        FALSE;: Y7 Q  l% O# D) j1 f
        }  j- e! H$ v4 G% C4 o
        if( queue.data[queue.rdptr].time <= writetime ) {/ J! F! ?: _: o. w$ g7 v
                ret = queue.data[queue.rdptr];! @: B0 }# A# N1 S+ c5 W2 q& r
                queue.rdptr++;/ m6 Z: H/ k% N) ?  w6 [
                queue.rdptr&=QUEUE_LENGTH-1;: A+ V' G3 Q% Z2 c5 k% b
                return        TRUE;
/ U2 s& n( G: |/ }( I7 \        }$ a/ U* ~* Y6 |- }& H# X
        return        FALSE;
) v. P: S: X7 d! C. u5 O/ |  p}
1 F+ @* r% w, Z7 y; K: W! G+ F( m# F) `# b! p8 A8 h, j: O. U
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )* @, D' z+ n5 m5 F
{2 V! n2 f" k" w# f4 X
        exqueue.data[exqueue.wrptr].time = writetime;$ y0 h! S( r( k: z8 y
        exqueue.data[exqueue.wrptr].addr = addr;2 s- d" ^4 F9 [9 q/ d& J
        exqueue.data[exqueue.wrptr].data = data;
4 L: m/ P5 B: T3 R) w0 X        exqueue.wrptr++;
/ B0 q) g6 t' e2 Q3 G3 l. u) y        exqueue.wrptr&=QUEUE_LENGTH-1;% s4 |9 l1 D; `7 L) R0 K
        if( exqueue.wrptr == exqueue.rdptr ) {9 g, b4 t, R# {# v7 w
                DEBUGOUT( "exqueue overflow.\n" );& O& g, A' U" l
        }
. v- n' l2 q& f- w}  P8 n% }( s0 e# D2 [. T

7 X: L& S1 F: Q1 Q5 {. X9 qBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ), b+ M5 m  `$ K/ I3 U2 V
{' J0 `8 N& `3 ~
        if( exqueue.wrptr == exqueue.rdptr ) {
2 W* c& n1 {0 C6 ~, _                return        FALSE;; @4 A' N  \2 e' I6 V; f# b3 q
        }
8 w$ F/ D3 A# w: ^        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% B8 G5 [0 @9 g7 n8 ~, T
                ret = exqueue.data[exqueue.rdptr];* G6 E0 Q! q2 K
                exqueue.rdptr++;
. f, V- v! F7 P4 l) d6 s6 U                exqueue.rdptr&=QUEUE_LENGTH-1;% y& B- ?5 T+ H1 \5 t. j
                return        TRUE;
! c" E* X# _- l6 h: E        }. k( F7 M* g9 ^3 C- o
        return        FALSE;
9 P- A& N& M: M* u}4 c# P; t- T# h  l$ g( f
/ S: U( _5 v5 J4 U" E. K* O; ]
void        APU::QueueClear()
# F/ q! a6 e6 r9 l' F* p{, C$ d$ [+ d' f" E/ Y; K
        ZEROMEMORY( &queue, sizeof(queue) );' m9 Z7 ]( Q" [) @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( Z0 Z4 P9 k) y& B
}7 X0 S8 S' q. M, s8 U

, d9 s# G! v# D! rvoid        APU::QueueFlush()" {& z4 u- F# N$ Q9 x9 o5 F
{# M! T2 M3 H5 q7 E% ~* c
        while( queue.wrptr != queue.rdptr ) {6 I; ]) Y5 k  G# @  I
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) Y: j4 M7 J, s0 k" j3 Y0 `- g
                queue.rdptr++;5 d8 ]5 j( [9 ]4 G
                queue.rdptr&=QUEUE_LENGTH-1;# ^! J! j7 k7 j; `" k7 r
        }
" P" ^7 [' E* Q/ s5 o: U; l2 C* C! A- h% j
        while( exqueue.wrptr != exqueue.rdptr ) {
2 m" z9 h6 h6 J9 W- g: x                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );  x; W  ^4 |0 V; Q: {
                exqueue.rdptr++;
6 _; u! W) `# ^4 M5 j                exqueue.rdptr&=QUEUE_LENGTH-1;
& j: D0 [8 `6 y( [% X( K* M        }2 X( w! B" ~4 n3 N
}/ P7 g) @  d' q4 x" u( S8 [

3 v- Y1 W2 p# I* Ovoid        APU::SoundSetup()
( F% g' I) d! a7 M* F{
- s9 E0 O* X; D7 R1 T/ L8 j        FLOAT        fClock = nes->nescfg->CpuClock;$ P$ g1 o; g, ?8 N- K
        INT        nRate = (INT)Config.sound.nRate;# g; p" a* x* O; ]( E
        internal.Setup( fClock, nRate );* c: S! A' @5 e# P( s6 |
        vrc6.Setup( fClock, nRate );
9 O& L4 n% M; G8 M$ \        vrc7.Setup( fClock, nRate );
' `+ h) q% g8 K: T7 i        mmc5.Setup( fClock, nRate );2 ?  T/ S. e+ \7 G( [  C  C( |- O
        fds.Setup ( fClock, nRate );
: d+ c  `% W$ M0 g6 D$ K% C        n106.Setup( fClock, nRate );# X) G$ K  s! r. y( E
        fme7.Setup( fClock, nRate );9 g' j- [6 o; u% |/ m; J6 w
}; ?% Y1 q/ j4 Q1 _; \* S

8 x8 R8 I5 o$ vvoid        APU::Reset()  f+ y0 S4 w7 E1 P" a
{
1 c  i9 ^7 j3 Y. ?. Y( H' Z6 u        ZEROMEMORY( &queue, sizeof(queue) );
& W- \+ n) _1 ~- H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ D; i1 `; j6 \6 r  p1 ]. z  Z- v3 J, |. S; u* @
        elapsed_time = 0;
* b& c% I& H2 B( X  {; r0 d( J1 o
        FLOAT        fClock = nes->nescfg->CpuClock;+ S8 P! t, L+ u* W# ?$ o
        INT        nRate = (INT)Config.sound.nRate;+ X% E4 |( g9 g5 {5 n( O$ W7 k
        internal.Reset( fClock, nRate );2 h/ {% b/ G1 K4 R
        vrc6.Reset( fClock, nRate );
- o: t& z5 |( h# t. t7 F* z        vrc7.Reset( fClock, nRate );& R& Z/ [- K) d# S2 S
        mmc5.Reset( fClock, nRate );& Q; L1 y" x5 b$ W
        fds.Reset ( fClock, nRate );
( l0 e+ L: q" _        n106.Reset( fClock, nRate );' g, A; t$ A, d& N/ I. W
        fme7.Reset( fClock, nRate );
3 [- ~$ g, k9 [5 Z9 j- b# B# z5 p) J6 b4 o: s8 W* j
        SoundSetup();
' i0 a: Z1 x$ e4 \% Z! x& g& k1 ^% b}' g$ E$ r- j% u. Q
9 w) j+ y. k8 C8 w* [/ ^
void        APU::SelectExSound( BYTE data )5 [  u* B. J6 b) X8 k5 A& F
{
# F- a3 e% {( m; r        exsound_select = data;. k% k4 d$ v( \
}9 T" l! i7 h9 \1 `" r

$ R* z6 b7 x% u+ eBYTE        APU::Read( WORD addr )
4 Z/ {; c3 [  G$ B) C1 e) t0 G& V{
( M& E' y! u5 [) ~        return        internal.SyncRead( addr );6 B4 _; p8 ~7 B) R
}/ ?$ z7 E/ c+ I, @, G8 }
5 O0 k  h/ J9 ?: Q( k+ c7 n5 ~4 q
void        APU::Write( WORD addr, BYTE data )2 _2 v) `; @( N0 q/ A2 E  a7 Z5 i
{- P7 o  T* i' _* A
        // $4018偼VirtuaNES屌桳億乕僩- y1 S. m, F* h, X6 i$ \- L. B3 U$ Y" W
        if( addr >= 0x4000 && addr <= 0x401F ) {
* B9 m; t7 S3 f/ q                internal.SyncWrite( addr, data );
9 c0 B- o, @9 {$ D8 T, L* z8 d                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
* A" q: f0 R" i9 X  w. ~3 i        }
- Y0 l1 y' F, X. }# p& ]- x2 t& `. ^, a}
; s- P. u1 X: U
4 f6 f4 J! f! W% C$ u  |; `BYTE        APU::ExRead( WORD addr )
1 b$ ^$ u! |" F0 j9 n2 O1 m' Z{
8 F- |3 Q3 u4 R; [' T/ {BYTE        data = 0;$ U$ M- Y2 R/ _6 \/ {( e- G; }# m
. ~& H+ u! q4 t' I5 U5 J  _
        if( exsound_select & 0x10 ) {0 d2 z8 O( k& ]0 W7 C! b
                if( addr == 0x4800 ) {
; O; p* z. ], W: f" D# L7 E# l                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 x. ^+ j' ?3 h- m3 Q4 U! C' H                }
8 O+ M3 l. x( b$ V        }: C0 B, U, j- L' Q0 o4 ^& {
        if( exsound_select & 0x04 ) {
3 b3 e' S+ b8 \4 D# z% B! d( A                if( addr >= 0x4040 && addr < 0x4100 ) {
8 \8 {6 G6 z+ ^" s                        data = fds.SyncRead( addr );
7 ~3 {3 P# z: u) x( c& ?' E                }
* Y: _4 \/ `9 H        }' P: F; ?/ o% B6 T' k
        if( exsound_select & 0x08 ) {
9 ?+ T7 P4 P- I9 T6 q) S                if( addr >= 0x5000 && addr <= 0x5015 ) {2 z. l8 V4 {  v  @
                        data = mmc5.SyncRead( addr );/ u4 b" }) o% [6 s& R% Y! J. ]
                }
. `2 B$ W, z' x  |" I' l        }! U2 J" G  k, h; f6 X: Y6 B% ^
; H5 @9 x4 K6 s# H: U) P
        return        data;$ L& N  ?, s$ z% R) w; R
}2 Z$ e8 h$ n+ ~9 O7 j$ |1 t, Q( l

" p4 t" u+ Q8 |/ pvoid        APU::ExWrite( WORD addr, BYTE data )
0 I+ `% U" U* e) v4 K, B8 @8 P/ ?{$ S! E6 A3 g& O: b- S1 ?
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& d$ Q4 l/ J5 f! Y8 M  L6 p$ U0 D2 T# E; ?! C: ]2 m
        if( exsound_select & 0x04 ) {
% s) D. `, P, g; f                if( addr >= 0x4040 && addr < 0x4100 ) {4 S3 W, r  t/ {
                        fds.SyncWrite( addr, data );
: [& o- a3 X) a8 J6 P                }
* ?7 G! R! @& r/ s3 R, j        }
' ?" u( l2 _; G1 {# J1 D' |0 k; j8 o( |' ?& l1 K2 E8 _4 f
        if( exsound_select & 0x08 ) {' ^' N! w5 ]% H! E
                if( addr >= 0x5000 && addr <= 0x5015 ) {; N% ~1 q" O- f2 d/ `1 e  ~
                        mmc5.SyncWrite( addr, data );
( i+ O& Q" B  Y! l: R                }
. b0 {) H; d2 ]6 W        }
7 M9 {0 w9 q  X; n8 B) E- L}$ i6 g. @5 `6 G! G; G+ A; q% a
6 R9 e' r2 P( o/ Q* V6 o
void        APU::Sync()
( s4 m; G% N) s{
9 z5 c" M; I" z7 K; O7 g}1 H* O4 t+ u9 }# z

' x+ Q. w  [$ l1 y; Bvoid        APU::SyncDPCM( INT cycles )5 o2 y! B0 \$ C5 ^. h  E
{
+ b. o+ t% ]5 C; a# K5 m0 i1 v        internal.Sync( cycles );
  \# R+ r' w5 F4 s
. C* A, z* ^' q3 e. T; `7 K8 ^        if( exsound_select & 0x04 ) {
( }' Z  P- C# v                fds.Sync( cycles );; k; q& l% a% ^2 y! U& ^% H7 k: {$ l: e
        }9 |* w0 E6 y. b( G
        if( exsound_select & 0x08 ) {6 }: ]+ y: ~: ?4 C3 Z# Q+ t
                mmc5.Sync( cycles );+ H6 F: ~* o9 A9 D4 Z! {) Z
        }8 R( ]( X* O0 u7 F% L
}* k8 L0 m! {" u) ~
# l0 Z) H& Y) ]9 u4 _
void        APU::WriteProcess( WORD addr, BYTE data )7 Q. r8 R) V2 v! b, T) {  H9 F
{2 {5 H. F2 Q  d5 N4 f
        // $4018偼VirtuaNES屌桳億乕僩& k; q4 M4 D: G& m# ^' V
        if( addr >= 0x4000 && addr <= 0x401F ) {% H; U  \4 O/ I# v
                internal.Write( addr, data );: ~- V1 p$ v- |$ M% u7 `' t
        }) t' ]) T; ]: f4 c
}
9 Y+ i; b. J+ s4 T7 q. A+ q$ P; L; N* l1 M1 d
void        APU::WriteExProcess( WORD addr, BYTE data )4 z3 D4 r2 S& K3 H3 s2 \
{; c* M2 S: f5 A. @, [  J
        if( exsound_select & 0x01 ) {
6 b$ `# s3 e& V3 D+ K3 M                vrc6.Write( addr, data );6 E: x) k3 W, N! u
        }
9 q1 g, o1 I6 B) G; [# c- L        if( exsound_select & 0x02 ) {
% a6 J) y+ z" A' c' J- X( z; ?: i/ _% _8 L                vrc7.Write( addr, data );8 e4 l& I, K, R/ ^3 B+ y( k
        }
; a5 }  ~' j( x6 B) {9 q# }8 e        if( exsound_select & 0x04 ) {
0 @* d7 N$ T  W% B. t" E1 O) G" F                fds.Write( addr, data );
# c1 w3 ~  s; F        }! R2 t( t+ k; D. @
        if( exsound_select & 0x08 ) {: g, F( R* g* V0 l# b  L4 d
                mmc5.Write( addr, data );5 |; Z0 Y) i& v$ y
        }
2 `( b0 ?/ m- k, R* D. ~0 d        if( exsound_select & 0x10 ) {
% C! z4 P; H4 f+ q( r* I                if( addr == 0x0000 ) {
$ v( N# R7 ?8 t3 E) P                        BYTE        dummy = n106.Read( addr );" b# a3 I3 ?( p' p) t! m
                } else {' O' A9 O' f& P
                        n106.Write( addr, data );
/ J, q0 p9 ?) u* V, {3 m5 j                }
# j6 p8 z5 _9 W  a% `4 U+ \' v9 g        }
3 @3 L; j  \* s7 S        if( exsound_select & 0x20 ) {& I; Y0 z) t; O$ D: H8 y
                fme7.Write( addr, data );
3 h; {( ^, L- ?        }6 @; U$ D/ X9 q, Z6 Z# S% f  f' h
}
# M/ f, W! Z0 t# f
$ Y- j0 @8 |, w1 @. `void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 n3 T% I. x9 i5 i0 E
{
- ]5 J  F: C5 P% ~, c: K9 W: N; E4 _INT        nBits = Config.sound.nBits;
# j7 o* a1 S" n2 f4 E* |DWORD        dwLength = dwSize / (nBits/8);( W( T. M5 r. s$ Z2 W' |$ L4 u
INT        output;% C" F* V# j8 z. y9 |
QUEUEDATA q;
( V0 J: \* O  e2 @  ]7 l  @9 BDWORD        writetime;
; U7 i% B0 ?# }& v( z
/ |6 }% C6 Q! I  J7 Q' \% m# o- RLPSHORT        pSoundBuf = m_SoundBuffer;+ E$ K/ [& h, {, V. U% d8 D
INT        nCcount = 0;& w: s* k. a! _0 I( u2 y
1 `8 l1 Y& z+ i) [; _5 c
INT        nFilterType = Config.sound.nFilterType;9 E1 p9 X5 B1 J. |4 Y8 Z
/ l; h: b7 O& s6 v( m* ?
        if( !Config.sound.bEnable ) {
9 d; b  x( Z$ Z: v  V5 o8 B4 y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
0 W8 |# T5 Y1 S. U' D                return;
9 F8 U( c8 L, X7 c        }
8 X3 H$ S; t( v1 Z) N2 |  |  U. ~0 V- @  Q
        // Volume setup
3 N& R$ [+ [0 K& \        //  0:Master$ D% D7 R4 h. c, ~  x
        //  1:Rectangle 14 s# |! t6 H6 E/ u: T1 x3 D
        //  2:Rectangle 2$ e3 P" V# k$ {8 Z1 [; e
        //  3:Triangle
  |' f! r" s3 X0 I' s7 p- |        //  4:Noise
1 _' ]% I2 a) U7 M        //  5:DPCM4 @' Q( n( k% m) p
        //  6:VRC6
/ M( M& ?) x0 {2 v        //  7:VRC76 ^9 n' P, G# a2 ?
        //  8:FDS
' B8 D. L$ V+ N7 f, T* u4 R        //  9:MMC5' p) {7 a9 F8 s' L3 y, Y; g
        // 10:N1060 f& B) A/ M& `. t3 _
        // 11:FME7
1 K5 b# i# U% ~; Y" d" K        INT        vol[24];
3 o$ |  K7 f" ?6 B, x3 ]7 {9 q        BOOL*        bMute = m_bMute;
, ^7 o9 l& c) a        SHORT*        nVolume = Config.sound.nVolume;) k5 R% t1 v! X' B& U+ n
2 w9 F: s% B8 f, {' R0 a& F
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; k. t' p: Z. _6 r* k& }( C% K

& b/ Q( h: }2 A        // Internal% f. @7 b3 d0 t/ w) x
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 l2 S- o: }* p7 B' L+ H
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 t. t) N% R: @- J
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
% v' z" O& g* S5 Z7 T, o& z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
! I3 \; w) g! v: U+ m7 P3 o        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
; s4 W: k0 q+ d  [& k8 V1 W+ Y) C6 Z, |; s
        // VRC67 @7 s3 O* }8 d! |$ ?; V
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 y# N) A/ ^9 _4 {) f$ n, T* X- w        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% T% ]) h# V+ @9 r- s  j        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* U, Q) h  u+ k8 b. r; A# h7 H
2 Y) {' U( t  a; R+ x8 I0 l        // VRC7  r. n/ e- A! Q4 x7 \9 W5 ]- L" V- g
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
1 M" K6 x# }% |7 g' {) w( T
9 }8 B+ k' C& C8 k4 s' t# J        // FDS
4 s' h. X% e+ \/ j        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: ?1 \5 E, d; ~$ D8 ]( l1 N' A9 ]1 `: j' s  v9 Q) J+ u, b& S; a& K
        // MMC5
, U/ |: I' c: \" ^3 _" _0 Q        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 G: u3 [* Z  d. b; ^
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" Y, K4 s6 Y# x: f( z" G
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ ~* N. F0 v5 j( e

0 s5 B% `& w3 M# r3 P  h        // N106
, k0 P* g5 ]+ c" K/ D        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& s8 u. }8 U9 q6 Z/ `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 l$ H! X1 S) G4 W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  M( `8 V  d) G7 V4 O, o' U1 Q        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" p7 w2 Y4 Q. w. }7 a- g, j7 X. a7 o        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  U6 F  B' p& ]; M. I4 n
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 D. m. n( A0 V1 M7 p/ O8 n
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# j; Z2 @. V9 Y. m. F; T6 X
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ `8 _& z2 L8 d, _
- f) b1 u9 K2 C8 r( i* }& ^        // FME73 i# F! F0 y3 e' L, ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" i3 K, j  s* G" N4 C        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, Y0 }% \+ I; n# m) ]% v2 {
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 \) ^0 T: L3 d$ C+ ?' f; `9 @
0 ?$ o" E. `- L- k) F//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 H$ E, F( X; [! [) y  I& A7 R, v
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;! \7 V" Q0 a0 [) y% [

# w* a5 G# M. D/ h- O  X        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% `9 x2 `& ]( }+ |( u# |        if( elapsed_time > nes->cpu->GetTotalCycles() ) {, c0 F" G$ G5 A! C) X% K' G# `
                QueueFlush();
+ n+ a! e8 E+ B        }
% K/ U! ?- j' x- ?9 b* d: m9 [
        while( dwLength-- ) {- @$ n8 _* o8 [% Q. G
                writetime = (DWORD)elapsed_time;8 I- c. e' j7 H. _% _

7 J4 P) r' q6 o3 C5 {$ ]                while( GetQueue( writetime, q ) ) {
" [; B  Q3 C2 B+ n' \/ |                        WriteProcess( q.addr, q.data );2 J2 P" I7 B) l
                }  n& \1 E, q4 ~1 d" i; [6 I

$ [# D& `( j6 n0 N( N7 E                while( GetExQueue( writetime, q ) ) {7 c$ J% ]2 z6 C% i  a
                        WriteExProcess( q.addr, q.data );
- T* c8 |' b8 y/ j& G, g                }9 }( y" h, Z/ b9 w; R& C8 ~
1 N* z* j- G( f: N- v
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" @( C' A( h4 y
                output = 0;
" b- Z, R6 z( F/ n. O: R                output += internal.Process( 0 )*vol[0];
) X0 X- f- _; U% ~                output += internal.Process( 1 )*vol[1];7 C  h  ]3 B  N; x! ?8 L5 P1 J; H) o
                output += internal.Process( 2 )*vol[2];) ?( i+ _8 ^: R4 l- B* O
                output += internal.Process( 3 )*vol[3];$ m4 y5 w6 Z2 f5 v3 Z! S
                output += internal.Process( 4 )*vol[4];
0 W/ w7 h; }) B$ p7 Z* T5 Y& ]8 j* e% {  @
                if( exsound_select & 0x01 ) {
" ~( F7 z+ [3 s/ w- N0 t                        output += vrc6.Process( 0 )*vol[5];4 P% w2 P5 u& R8 n9 }
                        output += vrc6.Process( 1 )*vol[6];4 I/ `( q; {% G4 A: s
                        output += vrc6.Process( 2 )*vol[7];" R; C! e8 m4 L
                }
! S, {0 {( o! Z* h( h7 n! s5 y1 o' e                if( exsound_select & 0x02 ) {
  [# S) N: E3 y) {5 {# H( {: F3 M$ f% P                        output += vrc7.Process( 0 )*vol[8];* n" R1 [6 R( s
                }& O: j# S9 ?5 R7 g
                if( exsound_select & 0x04 ) {
0 ?: k$ e) j5 m                        output += fds.Process( 0 )*vol[9];+ g! \$ {) j6 D/ k
                }' K5 r4 N/ e& ~5 j/ q( l( I& p
                if( exsound_select & 0x08 ) {% |: I+ I$ p; h0 o1 f
                        output += mmc5.Process( 0 )*vol[10];/ P+ x( d5 M$ m* }2 W' P" E
                        output += mmc5.Process( 1 )*vol[11];- h% s! [7 H( W" ~* C1 e
                        output += mmc5.Process( 2 )*vol[12];% y2 U0 e% V4 |% Y
                }
' C+ V3 L, u% z, R( |6 |% D" \                if( exsound_select & 0x10 ) {' w# f( e% k/ D9 p$ P* q
                        output += n106.Process( 0 )*vol[13];
9 q. A  V* X) L4 s# Q                        output += n106.Process( 1 )*vol[14];$ y8 r( O4 z# L7 s% X" t
                        output += n106.Process( 2 )*vol[15];
# Y7 ]  h7 m7 z8 B. r                        output += n106.Process( 3 )*vol[16];
6 \; G6 |6 O6 J' }                        output += n106.Process( 4 )*vol[17];2 |. o* {& f  I/ N
                        output += n106.Process( 5 )*vol[18];' s7 D+ s" P% `# [2 |4 l
                        output += n106.Process( 6 )*vol[19];8 U$ o" N* l. p5 b4 q& i3 _% T( i
                        output += n106.Process( 7 )*vol[20];2 R7 w6 y: n+ o, }
                }
# y% [4 V, M0 x" ]                if( exsound_select & 0x20 ) {* r1 ^! D+ d: F7 {8 V- K" J6 C
                        fme7.Process( 3 );        // Envelope & Noise
* k0 V  q9 @( x( h2 x0 @7 b                        output += fme7.Process( 0 )*vol[21];+ ^2 P. O( \; p
                        output += fme7.Process( 1 )*vol[22];
* p; f6 c* V. u2 \& _                        output += fme7.Process( 2 )*vol[23];
$ e$ `( d; E' E1 `/ F  S                }  B5 `( _1 a2 {, j
2 N0 L* Z1 r9 m. }+ f5 j) ~
                output >>= 8;; r3 P+ f5 J$ J: z) y# v" l

; p8 M2 G+ ^' V                if( nFilterType == 1 ) {9 t* {5 q1 @+ ^% J- c% H
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
0 h) R. C% s1 @* j% ?7 G* w# X: W4 W- y                        output = (lowpass_filter[0]+output)/2;
) e9 F% ~1 h5 g* q) a& o& A                        lowpass_filter[0] = output;7 o- K# f, V, p# Y) N& _# L8 F6 J& d
                } else if( nFilterType == 2 ) {5 ^9 z. u2 z1 I8 O; u
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)' Z+ H1 i5 z' \8 ]0 o
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 O( D& _; d& ^+ n; O
                        lowpass_filter[1] = lowpass_filter[0];
9 R' B$ y0 T, D3 ^( }                        lowpass_filter[0] = output;; ?# L! ^( b+ b8 f5 V
                } else if( nFilterType == 3 ) {1 f" V2 E6 Q" d% B! r9 ~% A5 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% k' e4 b+ z! k. k( X" H                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
2 E1 j* m* V; u# |) r                        lowpass_filter[2] = lowpass_filter[1];
% H* ]! a6 Y) C9 |% ~+ W: h- J                        lowpass_filter[1] = lowpass_filter[0];" P$ W8 c& X# K; }1 V) \/ s
                        lowpass_filter[0] = output;
) t/ K$ Q4 |/ S) K9 Y                } else if( nFilterType == 4 ) {% X& e0 O4 h8 J! ^  c' `
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
3 }5 {  o# Y2 o' o* ?3 F                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ b5 A* B8 k7 W# A: Y+ [- N6 w' `                        lowpass_filter[1] = lowpass_filter[0];. P" y8 j5 Q2 \
                        lowpass_filter[0] = output;/ m+ I' M  n- o8 s7 M! j1 n
                }& U* K( o, N5 r: v) E5 ]- [
1 d& m: ^7 I. Q0 r% f" V
#if        0+ |* s! ]2 \7 [- {
                // DC惉暘偺僇僢僩
  G7 h; y) K; q  a                {
# H4 ~0 \  \# T  f& Z                static double ave = 0.0, max=0.0, min=0.0;
% `  b& e. ?4 V8 z                double delta;
) ^6 v8 ~6 C% d3 [  S                delta = (max-min)/32768.0;. u4 f8 e3 Q7 I8 n2 ]- R2 O
                max -= delta;
  s' L% t8 _0 ~8 I( J0 B                min += delta;) g$ j% P0 C9 Q
                if( output > max ) max = output;
* L% q, \. U) q" o& r) N. W! T                if( output < min ) min = output;* D, o+ h8 F# Y# E
                ave -= ave/1024.0;
( \% V: L6 k5 B; t$ n; f                ave += (max+min)/2048.0;
5 ?; ^8 r' @. P" b$ `8 C1 u                output -= (INT)ave;8 X" H2 D" F( l  w9 R6 E5 C7 ~
                }7 M- g% ]" B$ a4 E
#endif
- f& u6 J+ r8 D! I" e#if        1& _9 C: c+ t3 l
                // DC惉暘偺僇僢僩(HPF TEST)9 ^3 D9 z: f0 Q3 D2 F0 U) o
                {
" c4 z& I* i+ i6 P//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);! r/ X: I- z1 U1 {; `% d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 `+ p4 I2 t7 B, m                double        cutoff = cutofftemp/(double)Config.sound.nRate;
- r( m* u9 L5 D; e" K                static        double        tmp = 0.0;
  |" r! t3 c; W7 |0 u. ]9 Q* V                double        in, out;3 I! z) a  P. D
0 _; k2 M/ ]3 T6 F) J' f
                in = (double)output;( k. i7 T0 t, D+ G: G: g# H
                out = (in - tmp);0 S8 E: a0 u: f+ }* X: O, p8 L
                tmp = tmp + cutoff * out;; T! I% L7 j$ P& B6 s% }* i: q

- c' I# I8 A4 D9 _* A                output = (INT)out;! H- d7 O5 K. x* }
                }
$ U& ]0 T4 c( T  F- L7 z#endif
5 K/ g' A. F- _! `0 j#if        0  N% ^! n! B; e5 _# R
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 I1 N6 A( L8 ~8 K+ \
                {* ]) k5 M* G' V) M
                INT        diff = abs(output-last_data);/ T# V7 q$ T. k9 i3 W' W
                if( diff > 0x4000 ) {/ x3 _. M  H6 [
                        output /= 4;; r4 o, l: e/ B# G( R7 Q; n3 X- B. f
                } else 6 x+ I5 {- i, h% ^0 \! r7 M; g
                if( diff > 0x3000 ) {
8 I! z( k# E9 D1 T# i# i  p                        output /= 3;. l% Y5 v! g' \3 z5 _* ~) ]5 `: J& ^
                } else
' \3 t9 w6 \( J                if( diff > 0x2000 ) {6 w. z4 t* d6 p" z2 J- e2 K  h/ R
                        output /= 2;' k$ \+ T$ _; D0 e' a1 \  v
                }
6 K; K5 i9 ?' s& f                last_data = output;8 Y7 \; M" o. r# h1 c$ p  i
                }. s4 {  G0 k( E
#endif
3 L6 Y5 s" h- `- f                // Limit
( `6 o  ^/ O2 u( L3 E                if( output > 0x7FFF ) {( C. C0 ~  P4 S1 `8 Z. Z4 K
                        output = 0x7FFF;, }/ ?* u( X. i+ v# F+ ^* r5 t. J) v) W
                } else if( output < -0x8000 ) {
9 {% U: p/ y$ T% D  a! Q                        output = -0x8000;& z" l* I+ A) ~- a, U6 h, \9 n7 {* \
                }: ~& q* L0 ]/ r
0 k* _) L* x+ T; r+ |
                if( nBits != 8 ) {7 v  X* y( F! M% p' b+ P
                        *(SHORT*)lpBuffer = (SHORT)output;( y9 A: f' n. X
                        lpBuffer += sizeof(SHORT);& h% t: m! }2 l8 L3 y) k
                } else {/ z- s5 _, Z9 [* o# v0 I5 m
                        *lpBuffer++ = (output>>8)^0x80;
8 S8 q8 Z# _9 h' P2 K& A1 b$ E                }
( U- h# m" V: A  ]# L) |! v6 I3 ?$ \% O" x; [/ c/ s
                if( nCcount < 0x0100 ): f' V2 r8 C  u+ ^2 Z% M
                        pSoundBuf[nCcount++] = (SHORT)output;$ S  N! v" y( \2 O- ?
. V: ^  @& r0 W, a0 {: o
//                elapsedtime += cycle_rate;) Y9 \  O1 F  z) q: f9 p
                elapsed_time += cycle_rate;
) v0 z' |4 n8 l" U+ v/ W6 [        }
% M, `, X. b3 T. O) ?3 {: g1 z4 Y# c( V) X" z: f% F' Q
#if        1
, z/ Z6 ]& `7 x: N* v+ O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 M; p5 @; O) b                elapsed_time = nes->cpu->GetTotalCycles();. S. _9 P/ Q0 z- |9 L
        }
! d/ ~7 i  Z2 N4 _        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
8 c8 A6 f6 y7 M! d+ A5 T$ S                elapsed_time = nes->cpu->GetTotalCycles();
; I3 H, d2 R$ Z$ @# d4 o) w        }
& Q+ ?; q+ z& |#else
! J9 Q2 `/ K% i& N        elapsed_time = nes->cpu->GetTotalCycles();! ^+ b0 R' K+ Q. t5 R
#endif
0 ~0 p+ `3 {6 W1 j}
2 h8 _( x) P: |. q9 {9 Q
0 z& R8 s- D+ S' V/ M# Z( {5 y  }, L// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  T! _* Y, P+ J: \; a: W3 L
INT        APU::GetChannelFrequency( INT no )9 l6 z6 R* c9 [" F; t% K% O9 M
{
5 y' O5 o4 T3 o+ Z, r, w& s        if( !m_bMute[0] )
( ^' O/ E( m/ E$ W                return        0;
: }$ E' V( U$ ]: }! Y, c
, l( F- e( {; [+ q        // Internal4 L1 c( l( P( t9 s: k6 q* M
        if( no < 5 ) {
8 A9 l9 @( }- C- _, z% H3 K& _                return        m_bMute[no+1]?internal.GetFreq( no ):0;
* C* n" C- z' b9 w        }' ~0 ?$ f( S: w, K9 h
        // VRC61 h  Q6 o" D9 k: G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
4 B0 ~' a0 {3 x  f$ u/ u                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 n% W$ `" K, E& H
        }
! b* o/ a  }) W# i8 N! @  r7 n1 H- ~        // FDS* i- Z, L4 L7 Z' _# k" j
        if( (exsound_select & 0x04) && no == 0x300 ) {3 }. J: E6 d0 e9 A. L, e, n
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
  O& b- }2 q5 x' p        }- q( [  O7 _2 N1 s
        // MMC5
/ Y8 p& L1 q& K; P9 Z$ |! @- Z        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
' N' X- x9 d( @& B1 P                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;) {" Y8 I" Y  [& E; M: R- c4 Z
        }
% q9 F2 f' n! U) g        // N1065 o8 b& ?" Y5 q9 D% s; J- _
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: I* ^% e- m9 r% K# q& ^
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ O6 y* s% ?: s3 s4 O, t- l1 R
        }
7 J7 b. {+ _: x1 u1 y        // FME7
9 a7 V) z' F0 M) T7 Q3 H        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {' |$ |8 g- L& n" Q
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
" R- h( Y( t8 B! U        }
# T- U2 ]( w- z" j        // VRC7
# d3 Q: u& S+ m        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {) e- L4 M7 E) `
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;4 y- ^$ v6 S% W: N. d
        }
% L0 Z0 X- l( I9 _0 k% x        return        0;
4 }# F$ [6 m' @2 o  T% D: [}5 X$ H% J, t/ j/ `# h4 A* ]
1 r7 q1 a0 z  u: M) [
// State Save/Load3 R" ]  o- c) P
void        APU::SaveState( LPBYTE p )$ _; A$ h& T. A# l7 A3 v
{
; r! G  Q- N' E: k' j#ifdef        _DEBUG
: F5 ^1 ]" W/ f% tLPBYTE        pold = p;( U6 F4 N, S3 h, [2 |/ J# a) B
#endif  S3 G2 m' q/ i1 C! E

8 l8 b4 R+ v. u# D1 q& `3 l- o        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 b3 v) E; c7 N5 Y6 `$ |: M, y
        QueueFlush();5 @; _; H4 ?) {

7 m. ]6 }/ O. `% }( {        internal.SaveState( p );& s- H( ?+ B8 I7 {. a
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 y- `8 D6 o6 T. g5 u0 R: i. u; a# h8 p" z: V+ B( e% l
        // VRC6
+ t2 w$ ]4 N$ `% M1 r6 D        if( exsound_select & 0x01 ) {
- R* l/ K4 M' A. q( x$ x  t                vrc6.SaveState( p );
$ P$ I- ^/ B/ I9 r8 D: Y" q                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: d* B  S# U% g
        }
8 G8 J' d5 I2 Q6 }9 S        // VRC7 (not support)
& M- }, S7 u' z3 `4 l        if( exsound_select & 0x02 ) {
+ {! i- u# K3 U                vrc7.SaveState( p );) g6 q9 w; ?6 l- Y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( v% V+ F1 l$ S9 r6 d: y% ?0 d& a' Q5 ~        }
7 n9 I4 t, r5 R4 G6 o$ B  L* v        // FDS. _6 o- N! N- m" `* U* ~; @
        if( exsound_select & 0x04 ) {
' V1 e1 ]% r( e& }% r% g, Q                fds.SaveState( p );
4 M- s) c; Z0 V; n                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 ^8 H% \+ b. ?) k8 N" N9 Y  O) P
        }$ K' m( W* s; \+ ?* ^8 R4 G
        // MMC5. k# n7 T! S, t% x) R
        if( exsound_select & 0x08 ) {! i& v' b( `* b4 C; ]& j8 ~" [
                mmc5.SaveState( p );& _3 b2 x  g. {! X/ d% @! R$ O! W3 D
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% U3 ?! J8 O9 J# t4 b* W0 E9 z- g
        }7 j& w; j3 O' s% `# e8 X# f
        // N106
+ s$ H& F" v! P        if( exsound_select & 0x10 ) {
" N# Q- O/ P! }9 V0 h                n106.SaveState( p );
& Y$ z; J# d% z- ?! g( G6 r                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ }; L0 ?4 A6 Q! Y
        }
% c5 l0 N1 s; V) ?) C: c" V        // FME7
/ b4 a. P( D9 Z& a1 T( L; g2 K        if( exsound_select & 0x20 ) {/ A" u4 W5 ?$ Q; P7 Y
                fme7.SaveState( p );6 o5 O' [% N! ^8 L$ Y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) q7 Q/ \3 i* G  F3 D& n
        }  C2 ^; y6 @; V5 z4 Q) i/ W: u

. `/ J4 d( x, p* j#ifdef        _DEBUG$ b% t/ M4 h, [
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 R) ]1 s0 D: ?! c2 w) T9 n3 l
#endif" E9 Y; T+ Z3 ]8 W9 M' _# t
}
0 Y- ]; ^0 j# k7 f: [6 t0 j, H/ D7 p, x) o
void        APU::LoadState( LPBYTE p )
3 p4 A+ O7 p# Y' l% I  _{
0 h* R! l" \8 v5 V8 x( L        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! R% d9 F# \( F6 n+ n        QueueClear();  y( U2 w% D" j

! A3 x5 d; l8 i" r3 O6 J        internal.LoadState( p );
/ F4 N+ Z) w+ ~2 g4 V+ t; o        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 s8 x, d8 m& Q* c4 Q+ ]6 r2 c- _& [  I9 T$ A
        // VRC6
% g! k. O/ c! _2 H        if( exsound_select & 0x01 ) {
+ l" p1 w. l3 ~- e1 D6 W- G                vrc6.LoadState( p );
& n. Y2 f9 _/ Z9 L9 v7 ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
# ~0 A' U: z8 Y( }5 |5 W        }; Y' @' J" k& _/ {& ~
        // VRC7 (not support)0 o* z8 a7 P2 C0 Q3 Y7 E$ [
        if( exsound_select & 0x02 ) {& X2 |9 S6 D2 M: h, {: b3 S
                vrc7.LoadState( p );$ K1 G6 c0 B" \& T- E! A+ q0 j7 C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
6 \0 [% P% h1 s, V5 E* y        }2 }# I2 ?) U" a3 R8 {' {0 R
        // FDS
0 S8 E$ M2 l# j/ f& N9 t( }# G; g        if( exsound_select & 0x04 ) {! M; Y. t% a$ {8 ]5 _  Z
                fds.LoadState( p );
8 ~) r0 x6 B% w! b' Z2 u9 A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ @9 t! r7 L% E! m: v; ~        }
; P# F5 }6 a) ]        // MMC5
' H! }+ o  O: S- [% D2 m1 e        if( exsound_select & 0x08 ) {/ E' x* |2 w: T9 S- [
                mmc5.LoadState( p );% O3 V. q- p2 D2 o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 `2 x. _6 ?+ s7 a! J        }
4 d6 p8 M; R# C        // N106+ d4 i* ^$ w3 A
        if( exsound_select & 0x10 ) {
- R! s9 e4 i$ e8 _                n106.LoadState( p );
! y5 q1 f' ?* G/ `5 e( v: \: |- F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* }' f" F2 R) V        }! n- W' l3 c" N" M+ q
        // FME78 a1 {$ d0 c, i5 f3 |0 j
        if( exsound_select & 0x20 ) {$ h- U1 n" x+ i
                fme7.LoadState( p );
! S  z6 x! X4 R                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; n4 ?% ~: o  r! r5 Z- j' |, O  w5 g1 q
        }
- E7 c1 s1 l. C7 k5 f' v0 d3 Q' G}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, z' N  p. P! r9 }  I6 k7 T% H可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 ?0 i( R/ D/ W, `
感激不尽~~

3 }% y8 {' z9 H: F) O! T: P+ r恩 我對模擬器不是很有研究,  n6 G) I( c2 I$ i5 p
雖然要了解源碼內容,可能不是很困難,
7 w) |% X5 b' e) n" p0 s: h不過還是要花時間,個人目前蠻忙碌的。9 O7 O$ Z2 u1 S! ~
5 C: v0 N3 J  c, b2 Q3 b7 N! ]7 U
給你一個朋友的MSN,你可以跟他討論看看,9 a* I" N% G4 ]2 Z) d( ?3 P
他本身是程式設計師,也對FC模擬器很有興趣。7 L/ k( u+ m0 B+ e' c

) d5 N5 |+ _$ D1 f, J8 }+ ]. hMSN我就PM到你的信箱了。! g3 B1 e) q9 |9 B- M- [
. f' a4 l9 G, G% e' X) S- T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ! [0 h2 r1 M# d! \+ Z% O, O
呵…… 谢过团长大人~~
% _2 L; M! I: V: |. p$ Y! E

% i4 c2 P& |4 Z  E6 B+ n: X4 O2 n哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 8 `4 A7 X) `3 x6 g
团长的朋友都是神,那团长就是神的boss。

; E" l( r' \  S( I7 W哈 不敢當,我只是個平凡人,. b6 z' M; q( Y) ?! M# [% p
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
& _5 j! V5 S1 N4 P3 i- NZYH
8 t& A2 V: p3 d5 ?  O4 ~" U& O- s9 AQQ:4147343068 q3 a7 U' k, Y, \- b1 B
Mail:zyh-01@126.com0 D9 J; g  U& b

' ?/ X; d5 E9 D9 w他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
% p) ?6 u4 |, j( C8 v0 X$ ?1 r再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ Q; w; B* y' v+ Y
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-23 19:23 , Processed in 1.101562 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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