EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* |2 p0 ]6 h+ c/ D5 t: F楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 Q# Q/ P( i0 S/ K; t: I6 l
这里有相应的模拟器源码,就当送给大侠了~~/ P3 z6 N. l  }* d  E
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 _2 s9 j9 R( I) R/ T) a
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' F1 |% k" M% r2 f3 z' Z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; m( a2 J4 Q) i' P- k  ], `这里有相应的模拟器源码,就当送给大侠 ...

9 n: Z: [* z) p' c聲音部分(Audoi Process Unit = APU):) j0 Q* n. P, G; A0 u
.\NES\APU.cpp
- |  G9 c) G  ]( p' V2 Y: Q' Z.\NES\APU.h. Q. {8 [( C; R% J; A1 G: p+ G# |
* ~  Y+ k/ r4 v# h; H

" N! Y; _/ o( l9 t  M5 o# o7 z  U影像處理部份(Picture Processing Unit = PPU):5 S+ y( O, I- Q/ i* w& s) Q- J
.\NES\PPU.cpp2 ^3 Y, W' t  ~* f
.\NES\PPU.h3 _) s1 K7 w1 \' F+ t0 m, d# y

# c6 i2 c* p5 v+ w# c3 o- j  U0 d如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 c* b4 q: {3 E2 G, V+ F/ V6 y(由于很多专用术语和算法机理都不明白,所以看不大懂……)
' L  d: U8 V/ b. A5 P6 m& _9 p//////////////////////////////////////////////////////////////////////////5 \3 g6 S0 s# T% i0 c$ \. _
//                                                                      //; O# O( |9 P: l
//      NES APU core                                                    //
& e+ B- ]7 P" u. U1 I8 a) L& h) @//                                                           Norix      //
, E2 \- `' ^- U6 u7 s//                                               written     2002/06/27 //
9 X$ i0 A( W8 U1 M) p" z//                                               last modify ----/--/-- //* o# u( F( I. a' ~9 Y9 y: Q
//////////////////////////////////////////////////////////////////////////
) h0 n& m7 r; o+ Z#include "DebugOut.h"7 @& o; ?& }& ]
#include "App.h"6 _+ W. L! D& I/ ~! B1 N9 x  h$ V
#include "Config.h"; F% p- h5 X. V' m" ?" u3 a* R7 S

2 N2 C8 r: E) J% d0 H#include "nes.h"
' p! T* Q4 ~8 l- Q) Q#include "mmu.h"
" ]6 o2 M# i( A#include "cpu.h"
4 Y4 a" c0 \" r8 U  j#include "ppu.h"6 }' e0 ?. R5 ?
#include "rom.h") S! B( ~. Z% i* `4 x
#include "apu.h"
2 W1 h5 ]; Z' ]# G# @9 o; s, ~
, T, ?1 U( F4 ^3 a( C1 l6 Y// Volume adjust
3 s# ?9 L$ D2 h) ]$ C! U// Internal sounds
3 r) |0 I9 G3 a#define        RECTANGLE_VOL        (0x0F0)/ B! [) @( x# F$ H( A* y
#define        TRIANGLE_VOL        (0x130)
& X) @: [4 p" T% B, m#define        NOISE_VOL        (0x0C0)+ y' D6 j3 K/ O) U7 g
#define        DPCM_VOL        (0x0F0)9 v6 H7 ^; G% p! y* z" d, o
// Extra sounds( D+ G% Z9 ^* N( F+ H* o0 S- @
#define        VRC6_VOL        (0x0F0)
) P  k& u$ O5 b  D" d/ \. U#define        VRC7_VOL        (0x130)
( _  E5 q' R9 [8 d4 Y#define        FDS_VOL                (0x0F0)
9 D1 b" X6 `# g; I; u8 x% ?#define        MMC5_VOL        (0x0F0)
' S1 W7 c' t9 n, c& |3 G#define        N106_VOL        (0x088)1 p0 K8 O1 X8 u5 }, y1 A
#define        FME7_VOL        (0x130); A# p- Y4 k  ~/ Z
) @5 N3 D0 g$ m8 c
APU::APU( NES* parent )) Q) y! L2 o- N3 U5 @" E2 X
{
3 D2 [* s2 i& e# j  k        exsound_select = 0;
- }' F6 [0 c# r- ]& u; {( T9 I$ D* S) f1 j; C
        nes = parent;9 C3 S% Z  D0 l6 a! T/ k
        internal.SetParent( parent );
! l* G0 ]1 d- A. K3 o0 o8 Y
% v# M) V6 T) c6 n# B2 p( J4 Q        last_data = last_diff = 0;
+ \1 ~0 m& ~) z; m! y
# b6 u$ |& Y% x6 W        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 [1 Q( h1 |; v& A- q5 F; v  _
8 }9 \# |- e9 K
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# }8 R- u. `6 y+ C1 y( O- i+ i        ZEROMEMORY( &queue, sizeof(queue) );
/ U2 h- P% O! g. }7 W4 R2 t, a- N        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ A4 S1 r) B- W. ^: v' f9 Z

- u2 {1 o1 ?) q9 z        for( INT i = 0; i < 16; i++ ) {
1 A( }! H  c: `                m_bMute = TRUE;
: a" s( K% [6 x. t; H( |        }" G* }( D: k; ]! V
}3 b% F  q1 ~7 @0 K- N7 H) f0 w
! K/ o2 F9 r4 E- C2 t( _  Y
APU::~APU()
8 i+ i9 y) _- U9 _. E9 e& h5 J{- Q7 G. t% F4 H7 Y
}
2 l, V& G/ N8 ]" u9 q
" Y% R3 v% c0 q9 O% _5 O  lvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )$ M- p1 H2 w1 P6 P% w  N& W
{
3 o$ W. v3 B# D( [        queue.data[queue.wrptr].time = writetime;8 R) R: O) v3 d$ h0 S* A) z7 Y( M
        queue.data[queue.wrptr].addr = addr;1 w# _- m1 b  W' Y: L
        queue.data[queue.wrptr].data = data;4 H4 i9 M, ~$ f7 N5 v* p, E* C
        queue.wrptr++;
3 \) E5 ~) B; |8 v: V" z: I        queue.wrptr&=QUEUE_LENGTH-1;3 V& q, G& i$ T* r
        if( queue.wrptr == queue.rdptr ) {, }1 ]# D$ \5 @
                DEBUGOUT( "queue overflow.\n" );
! X- `& l0 I7 R" j. Z: i        }. [4 u0 w: E  K, z8 _
}
# y" j! k. E& s" c& R5 K" Q. n0 {5 ~4 v5 _5 C8 k$ i
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
8 k- I" P, ]( V  v7 p; r6 b3 _{/ w) T$ @5 r8 f! t
        if( queue.wrptr == queue.rdptr ) {
2 l) e, p% A" J7 X) J5 C& N9 l+ c8 _                return        FALSE;2 ^- l: @7 Q9 h$ h& v
        }
2 `; m0 G- h7 n% L6 e- }        if( queue.data[queue.rdptr].time <= writetime ) {
9 v( o: `& l$ w4 i/ w6 X6 `' X# [% v                ret = queue.data[queue.rdptr];
# k4 y' l" s! `+ u  t/ H1 V; J                queue.rdptr++;
: I% }% U6 X4 J9 ~1 A                queue.rdptr&=QUEUE_LENGTH-1;' |, Z" ~0 p) `+ [; t
                return        TRUE;
% v+ w2 N4 Q8 E  V( N5 t1 j% V5 v6 {        }0 w; P! y8 c, \, d% j% v' W
        return        FALSE;5 P/ C$ k! J1 p, w, q) z* |0 @# `
}
' W! A1 r' P+ R. d% [/ |; u* a' p- Q( ~) E% S% w! b" j- w
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ): U! j' f$ j2 w9 m; Z) h! J  |4 E4 @
{5 ]8 u7 W. l0 o* ~% n
        exqueue.data[exqueue.wrptr].time = writetime;: t! k2 E  g% e( k, C; c
        exqueue.data[exqueue.wrptr].addr = addr;
9 H5 q! ~+ U- e$ J* ~$ K7 a        exqueue.data[exqueue.wrptr].data = data;  l6 E" x- G8 b  ?6 S2 R
        exqueue.wrptr++;
/ y6 _9 V3 F9 M+ p' Z        exqueue.wrptr&=QUEUE_LENGTH-1;/ K0 Z% b6 f4 c8 @2 ~
        if( exqueue.wrptr == exqueue.rdptr ) {0 s8 i' z/ y6 c3 A2 }, R; @
                DEBUGOUT( "exqueue overflow.\n" );+ n# V9 y, l) d3 K7 f# s" T  h# X8 n
        }0 I5 d  P7 D1 G
}7 l" Y) Q! c& l9 ~1 s

" c8 h& Y" q: b) D! |- pBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 t: K7 |" T1 D' R+ T, Q{. f& X5 I* f% H5 Y, U9 o9 R
        if( exqueue.wrptr == exqueue.rdptr ) {. d/ i! b9 u& R  Y9 w- a. k
                return        FALSE;8 P+ t. H7 g! K7 E$ s
        }. a+ Q% O& Q- I
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
7 ^0 r& R6 |* R+ ~$ R                ret = exqueue.data[exqueue.rdptr];
5 [! p5 u9 j& d1 J$ y* N1 M4 F; ]# P                exqueue.rdptr++;
) `* P% S& E: \' {                exqueue.rdptr&=QUEUE_LENGTH-1;, G- @% ], p) |; O, z1 K
                return        TRUE;
4 k+ x% P' e. i6 a1 O) p: [( y        }
) c; F$ \' v3 W  g: U        return        FALSE;" X) ~9 Y# y% `1 Z( Z; U* b- `; e
}
2 K* X4 M0 h. p! C4 H+ I% j. h7 K- v& ]# y
void        APU::QueueClear()
# _' ?' C& f  X. `{
7 C' T8 O. E1 K5 C1 N+ n* ]        ZEROMEMORY( &queue, sizeof(queue) );3 ~. {& g. D5 h* I) x8 _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: A3 E. D$ A' N3 f' U  S, Z
}
5 X8 G3 n* Z* B5 J% _
: c6 H% ]# B0 C8 ?& q( qvoid        APU::QueueFlush()
! ^8 t7 y" i2 x+ B{9 Z1 h9 x* I: |4 x  m5 }5 n* K2 j# c
        while( queue.wrptr != queue.rdptr ) {
, \1 I; i5 W) ]# X2 u. X* g                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# N4 A- S, E0 W7 P( Y
                queue.rdptr++;% X' [3 V! i4 {8 y/ u! [' e
                queue.rdptr&=QUEUE_LENGTH-1;
; r& j4 e9 ~5 a0 j/ ~        }
0 p3 e2 P# S* N( y) O
0 F" K+ w* O4 {9 K4 e( ~! e$ t2 B6 g        while( exqueue.wrptr != exqueue.rdptr ) {% ~5 V. {  O- w8 |0 Z# \% ^! w
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
& S1 U- a3 m7 I                exqueue.rdptr++;: E0 R8 }: R5 O$ L0 R( O
                exqueue.rdptr&=QUEUE_LENGTH-1;% r! t1 b# X: X4 V3 f
        }6 a" `" ?7 z- Z* p! F
}5 g; Q  e; T4 e* o4 v- Q. s3 p
+ v3 A. b3 w3 D7 u5 U) R
void        APU::SoundSetup()
0 v2 J, k/ _' ]9 Z/ L{+ u" O( P' h4 g/ H0 ~2 s
        FLOAT        fClock = nes->nescfg->CpuClock;6 A$ w! @4 a, ~! ~
        INT        nRate = (INT)Config.sound.nRate;/ Y+ {- V; D" {' \
        internal.Setup( fClock, nRate );
/ y2 c" b$ S' m+ J6 k2 g        vrc6.Setup( fClock, nRate );3 d' d8 z2 A# T$ s; z
        vrc7.Setup( fClock, nRate );
9 Y) f/ ~/ B+ E2 o3 C3 k% x1 o6 v        mmc5.Setup( fClock, nRate );! W) ^* @5 M% g2 u* c1 Z  K
        fds.Setup ( fClock, nRate );* O! f3 u, A+ d% p
        n106.Setup( fClock, nRate );8 C9 C- ?7 I* G; x4 K! ~  d4 c0 f
        fme7.Setup( fClock, nRate );; @( F% a- v. P! M8 s
}2 R8 \; s/ {( e
' H* T6 E9 l; b- Y7 r5 u* j
void        APU::Reset()( r% e  |1 D; U) Z; N
{* T/ _$ D  S  b8 B2 v" Q
        ZEROMEMORY( &queue, sizeof(queue) );
& J& s, n) C4 D) ~" r# c& U        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# M3 k4 K! E( D- h' W. ^. M% o7 U7 Q! v9 z
        elapsed_time = 0;
- p- m( i& ]1 O  ?: K
: U0 N3 j6 V. A; ]) h, B$ k        FLOAT        fClock = nes->nescfg->CpuClock;
# i+ \. y1 Q: r; E$ e1 j# x        INT        nRate = (INT)Config.sound.nRate;& H/ H: @* F' R" p
        internal.Reset( fClock, nRate );
7 A* L6 A' z/ Z3 ~5 z* [0 V        vrc6.Reset( fClock, nRate );( b$ C5 ?: r* S4 Y- W
        vrc7.Reset( fClock, nRate );
; @" d5 @" T9 ]; X) Q4 h7 J        mmc5.Reset( fClock, nRate );
, x# X6 Z- K% u  Q8 c' E, p$ q! h        fds.Reset ( fClock, nRate );( D% D- c6 R4 E0 i* ^3 _7 `
        n106.Reset( fClock, nRate );, o0 b- |7 t0 m; c) t$ A- w% F
        fme7.Reset( fClock, nRate );
: R# {* w9 H/ S3 M& V; r: W) Z; b+ N- |5 J
        SoundSetup();7 k+ u6 s' G" o* ~) Q9 Z
}
6 ^, ]: p  Y* U2 H$ v# Z0 u0 o. g9 a/ P1 P/ [2 J
void        APU::SelectExSound( BYTE data ), [1 ]* W' [8 X- ]9 h- x* W5 e
{% F" ], M+ H5 ?: Q
        exsound_select = data;8 r/ N' ~7 p0 D/ A. k8 o+ P
}% b6 m. P2 Q5 Y! g7 T# k
; ?6 R7 o% u. Y' h# h) ^6 f
BYTE        APU::Read( WORD addr )" N1 J2 Y" r4 i- f, M3 g* F
{
6 o  T, a7 d& g        return        internal.SyncRead( addr );) k* R& E3 E( t" q7 q* r: L
}7 K7 O/ h7 F! r" m5 B4 s

, l- ]! R8 K+ [! l' Avoid        APU::Write( WORD addr, BYTE data )- J( C# U( q1 D- c& J
{
+ M5 A+ ~# i; Z1 E' k5 L5 I        // $4018偼VirtuaNES屌桳億乕僩. X" f0 R+ ^. i8 u
        if( addr >= 0x4000 && addr <= 0x401F ) {
! i7 Q% ?) a) S3 ^1 Y* K7 E# X                internal.SyncWrite( addr, data );
) D6 M+ {! [0 p0 }: {                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
4 i7 b# \/ ]3 W% M; B        }
- k' h5 |) j9 @) {+ v' d9 p8 |}. l4 U! z) a/ Q: M+ O) C
% C2 o6 ?/ L) ~9 Q3 N" `7 {; C
BYTE        APU::ExRead( WORD addr )
( E" V& `( B' g  Y{/ T. l) l3 g% @( R2 W/ N. a8 H* H
BYTE        data = 0;: g/ o0 N9 m7 w, j
# P4 N# Y9 `6 V4 y
        if( exsound_select & 0x10 ) {
& _# r2 N9 s$ K4 L/ n0 ^                if( addr == 0x4800 ) {
) S! n* B* ?2 c/ b+ ?  U0 Z6 N                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ T# T# i. n2 s2 s
                }; G6 g3 W$ r: R1 ^( i8 b
        }  @, C$ ?$ v- z" g# k
        if( exsound_select & 0x04 ) {
9 x4 U) N9 t8 @, z; h2 @% p# d4 o                if( addr >= 0x4040 && addr < 0x4100 ) {7 S) `( o& p* Z( n6 m, R
                        data = fds.SyncRead( addr );7 n: g+ _5 @) [
                }
3 i: L5 g. Y$ j+ B" L) x        }  r8 L' g3 g, U0 m8 J/ @% |, }
        if( exsound_select & 0x08 ) {1 ~- G0 j+ A3 }! P$ `, @
                if( addr >= 0x5000 && addr <= 0x5015 ) {
. U5 v. w# `- h$ y; J                        data = mmc5.SyncRead( addr );
( f4 a! ^0 E) h+ |* h                }9 I# Y# {1 I4 ^* |
        }
0 _7 R7 H# [3 h& Q
  U2 G4 E) M3 ^( i! E5 y; P        return        data;5 o5 Q1 W- E. |
}. [) {8 ^6 p" x
/ b" w+ C" b: ?, I$ C. f/ C6 l
void        APU::ExWrite( WORD addr, BYTE data )- ^+ l+ m0 C9 {' S6 ]
{
) [4 D1 k& e: X% |        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, e: V* w; l" |0 i# @! X! x1 H; n) ]5 @  c5 ?" D/ L
        if( exsound_select & 0x04 ) {- q/ B/ p( }1 G
                if( addr >= 0x4040 && addr < 0x4100 ) {& ]8 A0 `2 F5 |
                        fds.SyncWrite( addr, data );/ x: U, Z0 E- Z7 G- l: ^9 Z& ]8 {9 a
                }, S  [% s) G4 k
        }% w: m9 T3 \/ b% j! r9 B2 N$ W
$ C" L5 ~' k2 b" U5 \
        if( exsound_select & 0x08 ) {
' J$ r  a: k9 l! r3 B/ e/ f                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 z( E1 v  U' T% M  [* Y# I                        mmc5.SyncWrite( addr, data );
. ~: m% }: m3 j- \                }& x8 t) b  N4 U7 S  z% i' k2 y
        }
- s. J& y( ^2 w. l}
) c/ D) J, P5 ], t- v7 @& y3 O2 @' Z7 V) c! i: U# Q
void        APU::Sync()
/ n' I! c7 a7 C: y{" f' X6 P! s+ `
}
3 D- A. \% ?1 ]" a5 E3 x  s1 r. i
# E  v$ q4 J2 V- ovoid        APU::SyncDPCM( INT cycles )
$ W" w6 _8 `4 _9 M7 Q, K{( ^/ D% |6 N, B" K5 ?; h8 u
        internal.Sync( cycles );
5 F4 n$ M, v" q) ?6 b, @# G1 V  U3 A& H/ Y; H. H
        if( exsound_select & 0x04 ) {
- A$ i4 ^7 F% u6 ~( ?1 U                fds.Sync( cycles );
0 {3 ^- e* Y5 f7 T1 d% H$ t        }0 }( ?1 m0 W9 K' A7 u
        if( exsound_select & 0x08 ) {
) H8 M! j8 R) |/ q, h                mmc5.Sync( cycles );
/ d1 I0 g9 U8 W( n        }
5 F: g$ t! d1 a& M}* ]" [" V. ^4 x; X/ v+ w+ B
. z7 ~) r* r$ K% s: i$ }
void        APU::WriteProcess( WORD addr, BYTE data )
; n) X6 l9 H8 V6 o/ k, F* m{1 x3 P: {( Y, Y8 K1 p0 b  g: J3 x
        // $4018偼VirtuaNES屌桳億乕僩
" U4 Z: D9 o4 c$ R, u, f        if( addr >= 0x4000 && addr <= 0x401F ) {1 g6 `+ e, A* ^+ A5 ~- w
                internal.Write( addr, data );  H- Y' C+ e7 E; e/ G: p
        }
! ?' J& \  q3 F: C* E, ]}
9 N$ A" [& a3 A5 C7 {, _( \8 \2 y0 g$ ^' K
void        APU::WriteExProcess( WORD addr, BYTE data )$ K) ]( U# w9 u+ x. @
{, J! `+ I! r6 {; e2 T3 N
        if( exsound_select & 0x01 ) {
: B' T) ?3 r+ ?$ q0 t                vrc6.Write( addr, data );
: J' {$ m' X9 Q! [2 o% i        }. A" d, D% D6 ^% F2 [0 [; O; R
        if( exsound_select & 0x02 ) {7 n# {: \- g3 y; ]0 y$ T
                vrc7.Write( addr, data );
9 s0 Y9 I; z; ]# V* V- x7 |8 k) ~+ J! l        }% p9 B) b( M& d! n5 ~6 q( }
        if( exsound_select & 0x04 ) {
( j" ?1 ]- s9 q3 U                fds.Write( addr, data );
% [$ {! N( C1 ]+ J3 h& a" M        }
* j4 [( U/ w" |' _$ o8 N7 \        if( exsound_select & 0x08 ) {; O% z' U. ?  R/ @- X+ ^
                mmc5.Write( addr, data );
& ?- t/ c$ w: [( H: g        }# D( T7 e$ [+ z* `5 D+ e" b3 A
        if( exsound_select & 0x10 ) {$ u4 D  w* m, R7 U3 k5 V. i
                if( addr == 0x0000 ) {  o0 r4 @: L8 ^. t. Y
                        BYTE        dummy = n106.Read( addr );9 ^$ r! Q$ H5 X# H2 X/ Z
                } else {; s+ p; H0 V# m. g/ H/ h' l  F: L6 I3 ~
                        n106.Write( addr, data );7 E- ^" z# K# a: [% v( k/ b) }
                }6 S6 N/ V2 B3 v! x& |
        }- \+ d$ L/ Z7 n
        if( exsound_select & 0x20 ) {- `8 _5 Q- h$ ~9 G& d
                fme7.Write( addr, data );
: e) Q- p4 D! ?+ }2 w+ ?        }
# d% U; W5 I) k; n$ l% y" z4 J+ c3 _  U}
; `# R; U6 ]/ `2 g# W  Z7 {- N% N" ]) B( J$ g0 `& z! {
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 i) l0 V$ i" ]& W. [: [+ H{8 r9 i4 z% j* X8 J% d3 z- K. I
INT        nBits = Config.sound.nBits;: z! ~' v4 s5 [' s+ o9 |
DWORD        dwLength = dwSize / (nBits/8);
$ I3 H, x3 _7 Z! q% n/ q6 C7 RINT        output;% ?0 T7 t$ ^# t: L" t" D
QUEUEDATA q;
' b0 g: R5 f% Y. _2 Z. r' i) cDWORD        writetime;( J4 Z2 U, t, W
! s# I: d) G8 A, a, E
LPSHORT        pSoundBuf = m_SoundBuffer;
. J( I& A, I+ s; C6 [INT        nCcount = 0;
8 o) |8 n% e$ |6 ~& U7 Y
4 ~- Z2 W3 Y: }9 G$ F" wINT        nFilterType = Config.sound.nFilterType;& z7 S! Y- O; l
3 O, C% q+ a( `( y# h* J4 F/ i% l+ B6 N
        if( !Config.sound.bEnable ) {2 K" Y( }+ C  w/ {/ a1 V& P5 W
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 e; p1 _2 d( }9 M. N$ }. @7 t8 m1 v                return;
" [% i1 q5 d3 E        }
+ I8 K# _5 }* _5 O* b+ p* p% r$ a$ M
        // Volume setup* u0 K, V5 ?+ a& P
        //  0:Master
+ M, [. q/ t. p5 v3 A        //  1:Rectangle 1
: Q1 M& W0 Y+ a9 W& h. n3 q  `        //  2:Rectangle 2
3 u2 T. a% s" |7 a4 X5 {' Z, t; c        //  3:Triangle, h# W/ t% _' n8 J8 c% i
        //  4:Noise& k* c: g: ~2 W6 `
        //  5:DPCM* Y! u6 O) N- D0 c3 Z3 s
        //  6:VRC68 c* {2 B  {* i5 ^
        //  7:VRC7; ]1 _- a* P6 k( B
        //  8:FDS' Y. Q8 ?: z( D! L1 b- k7 v
        //  9:MMC5
3 }# D" \! z: R8 v+ y0 p        // 10:N106
' H! H/ Z! r- |1 `4 d& |        // 11:FME7
" q; I$ T, G  w( F& ?        INT        vol[24];( Z% P2 ]/ j' L' X9 e' @" d3 a/ m6 p) m( U
        BOOL*        bMute = m_bMute;& P/ ?+ r5 b( o  x0 u& V
        SHORT*        nVolume = Config.sound.nVolume;
) U# Q& Y0 ]2 t9 y. A
$ x1 V8 e' _3 x! _0 U        INT        nMasterVolume = bMute[0]?nVolume[0]:0;1 b! N8 g/ q! J3 T. W9 f

6 |) F/ s/ N% i+ p* K5 j        // Internal- \) O0 r! Q+ q! f, X% X# {  C5 @4 W
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ i1 R4 [& O( |9 u
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;/ b9 C, `% K0 g1 [# j' G5 J) q
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 e2 n  ^* K- H& S" c; v
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;# j. }- w0 |& \$ J
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' g& Y4 d9 s# I3 _, z. H
6 Z3 y' J6 ]- L8 a6 E1 c+ ~) a& x
        // VRC6
7 d( y0 \7 ^9 k* `        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) U; ?1 F3 R4 C) K! |+ |        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( A9 i2 w, z3 A8 B% A0 m1 L# I" _        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( S% L6 Z/ {; P. x! t. r% v
# U: c; k2 d! H. v        // VRC7
: P3 @$ H3 h4 X) G2 v        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. A7 @& d# E  j8 h  E7 A# v( C

2 t5 c$ R( F7 f$ n. l7 p7 h        // FDS
' N0 f% M; y% Z) A' P5 G        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& @7 U* ^" G/ a5 l6 p
2 o) x2 B( r( ?4 N5 e
        // MMC5
/ R' H6 t6 O7 ^9 y- @        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: J: }- F3 O3 q8 [. U- {  n- G  Z& g
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 _7 i" y# C. P2 ~% Z, s        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" `. K0 A- ]9 |0 y  W/ A

6 S9 a( e+ j& ~: [. j        // N106
4 v' O+ s+ U) ^# W$ {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- \3 L4 H, S% S: O9 M        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 w) z; E! {5 {$ s: ]        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  O7 w3 X! i3 ^. g3 E6 i        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 X- B3 s% X% X" k0 i7 b) T
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, ^- @0 c9 B) f& T1 B+ ]% Z! s1 Z        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 H" {7 U  _# t  S2 i        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 f' K1 E' w/ e        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& I7 w) q" a  h) X! u4 _6 }
# ]1 P4 S/ i7 V
        // FME7
8 M8 d* i& H7 N8 P        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ ]; y/ d6 _( P* a, j5 r; \& ~. H: `
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" |5 H$ m$ G3 O: k, @        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 n% K( {7 @6 y( z# N* w) C& l( d6 |2 E& [
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% l; [0 k- a! [6 l# C/ {        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;* v( v7 Y7 V2 `* a% T+ w$ ~  v- J$ B
1 i- V, k/ y- c) u
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 g# h8 d, U4 r        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
2 T% M3 ]7 K3 w                QueueFlush();
$ ]) G' w3 O; x        }9 D: f5 V: z( }3 i& Y2 n& A

9 ~+ ]+ G% a" d4 w( E8 C( D        while( dwLength-- ) {
  _6 |  O" I4 @3 p) L, Y) \  F                writetime = (DWORD)elapsed_time;, B1 B8 H  g8 I  Y7 j6 l
# h3 r  o& ~* j& W( g7 Q7 {  _" v
                while( GetQueue( writetime, q ) ) {
6 z+ W  L) H: {3 u                        WriteProcess( q.addr, q.data );
1 F% r8 ]6 [) I9 P" L7 k                }
2 c3 t3 {: P9 Z
' Y) @2 U8 A# G. s' h4 T8 g1 }                while( GetExQueue( writetime, q ) ) {1 [. I* @, w  Y2 p
                        WriteExProcess( q.addr, q.data );" j2 R$ @  u. N7 u+ ]
                }
9 f' g! F* I: D" l$ g8 N+ h
8 \) p6 I: @& ^                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# ^: l* U& I9 A/ d2 g+ b8 P
                output = 0;: W) x2 B, v( |, x  n; k$ H( J
                output += internal.Process( 0 )*vol[0];
  ?% ^( q" f. Y* z, X5 N                output += internal.Process( 1 )*vol[1];
9 d* B" M6 o) h) v+ r: N! K                output += internal.Process( 2 )*vol[2];- s9 m# l6 E" e% ~" K
                output += internal.Process( 3 )*vol[3];
1 p* ~; e" M  E                output += internal.Process( 4 )*vol[4];
1 [& w3 o& b' a5 Q+ w
2 Z1 q/ j( ?- e) w' h6 S( x                if( exsound_select & 0x01 ) {
( p) q# \" |! G3 P" H. e# X                        output += vrc6.Process( 0 )*vol[5];
, B, i6 g4 Z; Y; Y                        output += vrc6.Process( 1 )*vol[6];2 y* c4 c; z% U( e
                        output += vrc6.Process( 2 )*vol[7];
! }. R& |# J9 o5 d$ W                }
$ H3 `. A, ~9 U6 @! \                if( exsound_select & 0x02 ) {
: F! ]0 ?, \/ L7 L% _* p* J                        output += vrc7.Process( 0 )*vol[8];) r0 ?5 s4 _& ]2 ~
                }
- R) I" x9 t5 ]3 A* o# n' @                if( exsound_select & 0x04 ) {3 `# M. F1 o8 N" a1 w! L5 H
                        output += fds.Process( 0 )*vol[9];
6 q9 H( u, Q9 V" y( c                }
! h, ~3 j# l# y2 Q) O; e                if( exsound_select & 0x08 ) {4 G0 L- J+ Q' H, F4 @
                        output += mmc5.Process( 0 )*vol[10];# p. @- a# _' ?- _! v6 [. A  s
                        output += mmc5.Process( 1 )*vol[11];
" T3 E$ f& q( q                        output += mmc5.Process( 2 )*vol[12];# p& w& {  w! h9 u* `# v
                }1 s3 R% K+ p3 z# Q/ K
                if( exsound_select & 0x10 ) {( c* m4 W% l* X$ ?6 t5 N3 r* N) c
                        output += n106.Process( 0 )*vol[13];, V$ f  u  d2 W# N. N" Z* e
                        output += n106.Process( 1 )*vol[14];- Q  H% q% p! E8 y
                        output += n106.Process( 2 )*vol[15];) I, \5 g) Y" W3 x
                        output += n106.Process( 3 )*vol[16];7 V( g( c4 P2 g" h' Y) P$ y7 k% N
                        output += n106.Process( 4 )*vol[17];' t- }5 l& [4 C6 U* f
                        output += n106.Process( 5 )*vol[18];! W, T7 `$ y; ]! H0 z! V) a: H
                        output += n106.Process( 6 )*vol[19];
6 v' W$ H: e, U' d, N  ~                        output += n106.Process( 7 )*vol[20];3 F0 s& Z8 j: n9 Z0 z
                }# N- Y/ G7 E7 q- u. }
                if( exsound_select & 0x20 ) {0 d# q- G/ s0 F1 d, v, \4 @5 k
                        fme7.Process( 3 );        // Envelope & Noise4 x) U+ S: e* v- g- Y7 P0 P
                        output += fme7.Process( 0 )*vol[21];
0 a0 N! ]! l; d, o% u9 k" g                        output += fme7.Process( 1 )*vol[22];
" p9 m! Z9 S3 H. L: f7 w. z9 P                        output += fme7.Process( 2 )*vol[23];* N& E, V8 |  }% ~. Z5 H5 m; Y
                }9 D6 x: P# U$ D2 z
; S3 g8 {& ]* C/ v, T" \
                output >>= 8;
0 }% B7 y; Q+ i4 a8 L
8 a* _' @. [6 g* n' B( T                if( nFilterType == 1 ) {
8 Y1 M' |9 D2 I7 Z4 i                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 q0 \& f2 F+ p* O( k
                        output = (lowpass_filter[0]+output)/2;7 B$ }0 f6 j0 q4 z  M
                        lowpass_filter[0] = output;9 N0 i5 E0 c/ r% K! }
                } else if( nFilterType == 2 ) {
5 A/ D3 J. ^1 Y                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
- q3 {  l4 ]/ W3 g* M                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
' F  Z" ~( E( z/ R9 n$ ?' e& M                        lowpass_filter[1] = lowpass_filter[0];
+ U- B8 d% c5 k- b6 r5 u1 w  j                        lowpass_filter[0] = output;
! U. d* U! v$ j# z6 Q! Q: {1 G8 Y                } else if( nFilterType == 3 ) {  c$ v) ~3 F- J
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); |- e+ u. N- c* k% h, K& r
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;8 s4 U3 S% W& K8 a! ^+ E% C7 W
                        lowpass_filter[2] = lowpass_filter[1];
: g% e8 i; p3 z1 e* M                        lowpass_filter[1] = lowpass_filter[0];
/ U; |, A: C! B+ p1 R                        lowpass_filter[0] = output;# o" n7 m1 @/ ]" }
                } else if( nFilterType == 4 ) {
; s% @% H! g# g                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- B, I+ |5 x: i/ t) I+ Q
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 g  X5 x; L2 B  t$ P
                        lowpass_filter[1] = lowpass_filter[0];6 u$ |5 X% ?1 |0 o3 F( V8 \6 Q
                        lowpass_filter[0] = output;, _/ l- i6 [# z/ t( a
                }
$ f& m6 G3 T' t" ~; d3 W1 h
9 k1 k9 A* Q, _' b. ^$ \) l) S#if        0( |& j  B* J% i5 i$ Q. D, U
                // DC惉暘偺僇僢僩! L# w0 S  D8 k# |1 m9 m1 r
                {8 j- B# Q: I6 k% {! y# q8 I) g
                static double ave = 0.0, max=0.0, min=0.0;
0 T2 C. d$ J6 e" u9 M$ g                double delta;5 O  Y8 P7 b% ?* ?, A$ V  D- O
                delta = (max-min)/32768.0;! F; s. v/ }' ?5 N7 L9 S
                max -= delta;" W$ x, M: N. i/ K& l& d
                min += delta;3 z) j' A2 h4 F( P. k$ a
                if( output > max ) max = output;
; U7 @: d0 Y: w. a- N                if( output < min ) min = output;- _* e. |5 D! Z& Z6 p) B8 }
                ave -= ave/1024.0;
0 U+ H1 W/ b8 B# @+ O! ?8 P                ave += (max+min)/2048.0;
& v3 w/ k3 E/ w8 Y- z; g/ b                output -= (INT)ave;
4 {' t/ c+ r) w$ [& m                }; D7 L0 j+ \1 ]. r7 l4 W! k: J
#endif
- H$ r  V0 b. R4 U0 P8 \0 {#if        1  D' ?. [. T( r1 w' [3 d
                // DC惉暘偺僇僢僩(HPF TEST)  B4 j5 c% M- @  v$ _* d
                {9 Y& F( a9 `) V* Z- W
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);$ D4 W: T: m( d) N7 [
                static        double        cutofftemp = (2.0*3.141592653579*40.0);% f# [& O6 P8 |
                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 p5 `. P/ {+ A; x& }, A: S
                static        double        tmp = 0.0;$ D) w; t# g6 Q7 O) [
                double        in, out;* c3 Y1 U+ t% r, ~4 n
3 ]0 E8 w* O1 B+ y6 O" ~
                in = (double)output;
; x( J8 Y. G6 _$ _, F0 g                out = (in - tmp);! a$ ]; ]" O+ W3 }, o% U: y
                tmp = tmp + cutoff * out;  A6 c+ y7 o3 V, T- w

2 G7 K7 j; u$ D0 y* j                output = (INT)out;. s$ J+ Y) [% e5 K
                }
$ c) G0 F2 t& {# B+ q/ a: ^#endif4 l- ]9 ?( Q( A( Z* Q) Q3 w
#if        0
- W" x! ]$ H/ [* q                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 E3 Y: {' k' R, d' ?) D
                {5 d- V# p' N' c
                INT        diff = abs(output-last_data);
4 H. z! l# z" l                if( diff > 0x4000 ) {
: D7 ~1 J$ m( C9 h                        output /= 4;
8 l' E/ k2 H! L/ n! J) ]9 q                } else
9 c- J! [, b$ I# w4 U" J, V                if( diff > 0x3000 ) {8 k- F3 D! D$ s! ?4 q' J
                        output /= 3;
1 ]) g+ `2 J0 r                } else
- @! O; [1 m! y5 P                if( diff > 0x2000 ) {
4 w  H- S' v2 t' q+ W8 Q5 }: x# F                        output /= 2;3 W' ?3 ?- d" G
                }* J3 q) a' Y: L- P: @: v- B1 o
                last_data = output;3 ?0 S0 V5 s" P; Y0 S
                }
' X* _1 y7 v2 y9 R+ J1 u/ _#endif, ~9 |1 z" h% Z8 G, P1 Y# J  T
                // Limit
, f% `( W# Z) o! S# L                if( output > 0x7FFF ) {& f9 X/ C$ s/ v" i
                        output = 0x7FFF;! i" [8 x8 Z% R# a7 \0 J+ w& C
                } else if( output < -0x8000 ) {, V6 \$ n  o: ~- D, K( ^8 [- w
                        output = -0x8000;
% E# Y- |( g( Z                }$ i8 R) O& |$ a+ U( S, p
% D4 W4 z2 e, ]* M2 K
                if( nBits != 8 ) {' l1 ?- p6 J% m1 @! f% ]
                        *(SHORT*)lpBuffer = (SHORT)output;; r' F/ \4 [4 q8 I% m
                        lpBuffer += sizeof(SHORT);
" u, }) y2 X/ z6 d- J                } else {  ~! q3 H8 v: x+ a" c6 N
                        *lpBuffer++ = (output>>8)^0x80;
- p$ \3 y$ ?. O" W; Y: z                }
3 `0 D  k  Q) L+ b: y/ M" a7 ^/ t
' R) ~+ h: u5 G9 v! |$ U' K                if( nCcount < 0x0100 )
9 O' f& x. L8 S                        pSoundBuf[nCcount++] = (SHORT)output;
+ w- r5 i* z0 y! D+ y$ d  U: q
7 O7 g9 \" n" K. D$ F//                elapsedtime += cycle_rate;
  N* V' T8 b6 c; P! Y                elapsed_time += cycle_rate;0 M) S! l9 w( B1 ?; c" t
        }" i( S- }- }: }1 Z2 e' E8 j
( w& W  f+ C5 o! ]
#if        1/ a/ T; b( F% t! p" w) B0 `
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ j( i5 J+ u* O' N                elapsed_time = nes->cpu->GetTotalCycles();
( }3 }- L4 x+ f1 |: V        }' V; O: j# T3 s
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {3 ^, T1 r  k% {. e+ E& X* \/ X9 q
                elapsed_time = nes->cpu->GetTotalCycles();
9 o1 h; K' t* _& G# D        }5 d6 n8 X! x7 k) ^) _0 G1 k
#else
6 b$ ]( L5 C7 X) L        elapsed_time = nes->cpu->GetTotalCycles();" E; o- W: A9 a, |8 z
#endif
: v, H5 M, f/ D! k}. z3 J3 M4 `+ I2 U. F! t

8 u( O4 G7 v* s0 p7 B+ C; c1 u// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' z/ N+ P- I. G+ G- v( t7 R
INT        APU::GetChannelFrequency( INT no )( m& ?( n" J3 D
{0 B- G  _' H4 l; R# L) D
        if( !m_bMute[0] )6 ?, P, O& ?, _
                return        0;
9 R7 ?2 l  m& s  M9 x  u" q! H, \8 U/ L. w, r
        // Internal
% |( v9 }. a* J        if( no < 5 ) {2 r' k! H) @4 d8 J9 V
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
$ D3 L; S" e5 ^+ ~6 ^: y        }3 P" m7 n% _9 ]" A8 T7 x5 V/ V
        // VRC6
  F0 [, Y& m0 a! S3 w2 O1 g# x        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ r6 O7 o' d, n: s6 e8 a; G                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
) r, n: h: G! a' P$ I        }8 `, F# u" W$ ^% d8 G7 b
        // FDS/ q8 i' b; B5 r" n1 V; V  o7 j4 A
        if( (exsound_select & 0x04) && no == 0x300 ) {
" m. [% B# M" y! X                return        m_bMute[6]?fds.GetFreq( 0 ):0;
" M$ g. {! P' l        }
/ v( _1 l% \" M0 R# M        // MMC55 \' N1 t$ _9 {  Z! M5 V
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {& l; c( ~- u! d. ?% Z" o+ A& V
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
* u, C/ K8 s8 {* `' i. K, s        }7 c; V0 A$ V# r* m! ^
        // N106
( Y' a+ U) f+ ^* d  R( L$ E+ B. X        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {4 `9 Q# N) }0 Z$ Q
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' e1 i, W8 B' C; [        }4 Y: D$ z& C9 M' C, W" s
        // FME7
8 R' n1 _4 m  f3 r4 Z( ?0 l! e2 j0 p* [        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 y3 o, s+ z3 Q                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
/ c- d4 s3 k# p1 [* L8 j$ P0 C        }
2 z& S5 K# m3 ?* `  ~7 B        // VRC7
: b  [/ y* _' `) \        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
8 m( J" s. ?* Z6 Z( P9 h) H                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* |) H) j6 }1 k
        }
/ i) \, E4 O1 a' D        return        0;9 O9 `* ~$ b' U: b8 G, y
}* O' R% z# C' A) z
$ c( C& z' B: Y( U' o$ L, {
// State Save/Load
' U( \) K+ S0 C) ?1 B2 ^: Vvoid        APU::SaveState( LPBYTE p )
& G" T, K# _  {" k2 ?2 A" S{
) P) e3 E' e) k! G#ifdef        _DEBUG( F+ I( \5 V$ _
LPBYTE        pold = p;
3 Z4 n- \8 a) x. K#endif
; A9 I; G0 D6 n- P# _! N  `$ A' J- Z, ]
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* V' l" j+ d, h) J        QueueFlush();
; _' P; `) }5 D0 k0 H! e2 p
& S* k. k, Z6 F1 V8 \- [+ |* H2 b% W        internal.SaveState( p );
; L9 Z6 C4 {# B& D        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 B/ O+ t- f" b7 o- _9 t. a* x! b* f, Z5 X3 i3 w
        // VRC68 Z+ h) ?- V! o8 I2 _0 S1 n# D
        if( exsound_select & 0x01 ) {
8 L- J# X& o8 \8 B                vrc6.SaveState( p );
4 G! S; x. P7 {! s- |( r# B                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  c; ?# K" u9 ]8 K( j        }
/ q, O5 c  F- n. L" Y        // VRC7 (not support)
3 c- r: |% ~( x' D/ D        if( exsound_select & 0x02 ) {; N4 E1 P; h2 w6 ?, x
                vrc7.SaveState( p );
+ d2 G( M8 w" E# [( o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 t, S7 F6 C1 z3 u
        }6 C! H( g' K4 t+ h% G
        // FDS
& v/ }$ U! V% j) J# I% Y- z        if( exsound_select & 0x04 ) {
/ I2 @/ A: z4 k% x                fds.SaveState( p );: g1 s# u8 C; d: @) y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 \% \. m. r* Q/ p6 Z: l
        }
, s. G/ Y5 C" r% @9 N  {: L" o        // MMC5
0 A1 ]" L' r( B* P        if( exsound_select & 0x08 ) {
1 j0 \" ?& n' Z% `, @1 T! R$ N                mmc5.SaveState( p );
& P& m2 u4 N3 U; [6 p; P                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 F, |" L2 h$ @, `7 q2 |  \& K1 Y; R& N
        }
. M( T. b% C7 W. ?2 D5 r; P        // N106
: ~4 K0 @9 h# l2 U, H        if( exsound_select & 0x10 ) {1 o: W0 h+ k1 r4 }( H
                n106.SaveState( p );: d& k: ^6 @" h  J. p3 W2 d
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: Q& X9 x' t4 V. l- ]
        }
% y  @( N' K# U2 }& W( i) ^2 l( C        // FME7
7 ^2 t$ V6 m* |/ H7 I& ^: S/ P        if( exsound_select & 0x20 ) {$ ?- ?( m2 r3 }) \. L) c
                fme7.SaveState( p );7 O: `3 W& q" u$ Q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% E) Z3 W7 f% d& m9 i' d" i        }
, C( G( g( u; k6 P5 C0 e3 A0 z  k; {# `; ~8 w
#ifdef        _DEBUG
" U3 T, F# R/ DDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 H% i6 t% C" A; k8 n' m  @' g2 t3 }
#endif
6 Y5 b( K. k: h" w7 Q- F}5 i& g6 `" b% u. q, v
( R6 E) S: A* b8 B0 J
void        APU::LoadState( LPBYTE p )
7 D& d8 k# Q$ D4 I0 k{+ R8 p' R/ {3 Q0 @% }9 a
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡/ J: k  g/ u9 c- ^( x8 F4 k! }
        QueueClear();- p0 a' d9 X% g+ ^7 O4 y

  j4 A" p# j' Q" E( Q- }        internal.LoadState( p );( ~/ S* ~$ |, P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 f7 ^1 \( H& S( M+ f8 Y% v- T) u

" I4 s# |. p: e        // VRC6
/ _3 P- g, Z" k2 W' m" N        if( exsound_select & 0x01 ) {
5 j) A$ t1 s1 M+ S( [3 C                vrc6.LoadState( p );
+ \% b3 ]: A( w' o2 O3 s9 m& X                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 D0 l/ X& M" r        }
% H; A# X3 K" B        // VRC7 (not support)  E& E( d- F9 b6 J# C0 H; p
        if( exsound_select & 0x02 ) {: p9 I  k. ?$ R) I2 B9 M; p) q7 I5 Z
                vrc7.LoadState( p );
; ^& y' Z2 O5 ^0 p' {  h1 {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* V: h9 f- Z- X8 Z* z' G: l) h        }9 n  ~& i! J0 O4 i8 `5 r
        // FDS" f$ o+ z' K+ I( a! M
        if( exsound_select & 0x04 ) {
& ?# ?3 O8 B" X  }                fds.LoadState( p );/ Z" B. q" s* A) U& ^, V! p
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding; @/ v0 B! U, P( u
        }+ H+ [9 j+ u; N' a- I
        // MMC5' e' l- E; u9 l& q
        if( exsound_select & 0x08 ) {
' S3 H& S& `( F8 f2 t; I4 N                mmc5.LoadState( p );% N# {. E: M) v4 V% S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' r0 j& c3 T8 K! ]% }
        }0 C% I, r- o; _/ J3 ^9 \7 O4 q
        // N106; e3 S& p9 Z2 f7 _2 l
        if( exsound_select & 0x10 ) {
1 I6 Q- i7 X4 O8 n* u                n106.LoadState( p );) d, f) n3 ?; V  a" Q  e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 d3 r3 t6 }; T& H0 k" k        }% ^% ^! ]8 V' W. I
        // FME77 j6 b$ d$ e& c' v( M( k
        if( exsound_select & 0x20 ) {0 T; o- C  g  a4 `5 U3 ^
                fme7.LoadState( p );
6 Z- {6 I8 h" ]                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ \7 y/ Z. j9 }' n        }+ `+ D6 k$ S' l6 m% K; D+ L
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 # h8 ]/ R' b! t0 ]/ a! |9 ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: {  x& c0 A0 x5 U# B/ _3 c; D感激不尽~~

7 w- d1 O$ A% b9 O; y8 c' C恩 我對模擬器不是很有研究,' J- g( L5 |( q& r- e
雖然要了解源碼內容,可能不是很困難,: r* `. ?4 y, i/ M7 ]- U
不過還是要花時間,個人目前蠻忙碌的。
" ?5 ], b$ l4 A5 f6 G8 n( I! v( z* S: L- ?6 u: b9 {2 e) q& t# X
給你一個朋友的MSN,你可以跟他討論看看,, p4 X8 g! V6 s' M% ?# b+ H3 X
他本身是程式設計師,也對FC模擬器很有興趣。
2 j2 U+ t( m. Q2 o) r- A3 g5 y9 C6 F9 v$ n. P
MSN我就PM到你的信箱了。
0 y6 X! q/ D: m. W- {. h& b- I: 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 发表
+ O# p9 w2 A" b* Q% g8 g呵…… 谢过团长大人~~
% @6 m$ j6 ^6 b# V1 c

& g/ y3 v: E' s8 E$ m2 r哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
- V; D+ d: H  s% a, y1 K  R: j团长的朋友都是神,那团长就是神的boss。
; V* G. ?1 H3 L+ l, b; I0 b
哈 不敢當,我只是個平凡人,
# ]* D* R4 z9 O要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# |6 ?+ R% Q2 p5 N) {
ZYH$ |3 g! Z' [5 F2 W1 K
QQ:414734306
6 l- _6 z* k* O3 ^/ s2 sMail:zyh-01@126.com% H7 B+ M6 b% ]% d  C
& o# O5 q' o7 {7 g2 E$ l0 ?
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ S: I# i( X* m. w& ]' B再次对团长大人和悠悠哥的无私帮助表示感谢~~
# a' Y% a3 Z) }8 A$ S" A
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-5 05:14 , Processed in 1.136719 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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