EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* E/ q5 c; E7 w" a6 _- _, I楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' S& O' ?* T% C
这里有相应的模拟器源码,就当送给大侠了~~+ \6 C- l, ?" {; H* ?: H
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * w5 a% W: m6 q/ W' C  g) I4 d
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 z' S4 g! M# h8 n, n楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 c0 ?2 Z0 `- |3 p这里有相应的模拟器源码,就当送给大侠 ...

0 X1 `  X+ s* f; b+ v9 U  q聲音部分(Audoi Process Unit = APU):
2 J! r  P7 c- j! z; t/ e.\NES\APU.cpp
# b& @: H' t7 c( S.\NES\APU.h
9 P8 O* O* K7 H  K
; C7 n2 ]) `3 n: E7 y. R# h7 P4 o& @2 O# K+ k8 l, w9 L1 r
影像處理部份(Picture Processing Unit = PPU):0 s; s+ d$ m0 ?" U2 `
.\NES\PPU.cpp5 \+ p" w) c  o! F
.\NES\PPU.h7 X0 Z; x, H) D. i7 G* Y

, Z# g) _! O  q" K- b如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
9 @% K4 T3 ]. l" Y) e(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 T1 @2 ]# m3 |2 k5 n/ r% J  R
//////////////////////////////////////////////////////////////////////////: H2 y# C6 N3 @2 V; G, z9 ^* e7 B5 u+ r8 h
//                                                                      //  C$ I. Z& f3 Q& f
//      NES APU core                                                    //
7 B) K3 `& b' J4 f5 S+ r//                                                           Norix      //
) ~, G- Z0 Y8 P/ c( v' y6 e//                                               written     2002/06/27 //. Y9 ?4 K6 V" V
//                                               last modify ----/--/-- //5 U' y! B0 Z( s' ^4 s9 p
//////////////////////////////////////////////////////////////////////////! n, l4 N0 Z( ^0 E( A: t' S
#include "DebugOut.h"% O2 A7 N" [! R
#include "App.h"
* e: T7 _6 |" h0 p3 y! u6 Y#include "Config.h"
& G8 e  w8 j4 l
) n0 S+ h; {4 E/ a' v#include "nes.h"
4 Z% d4 e, m  V: o5 u1 V. V#include "mmu.h"
2 c0 K: H* U+ J7 P/ E6 q#include "cpu.h"
8 X  v! G( k/ Q# G6 z5 ?3 J#include "ppu.h"  k1 j+ I- P9 {0 D8 O
#include "rom.h"
1 o9 k0 O5 z, V8 l#include "apu.h"
" \% T0 C' k  t* }* l$ P  Y9 {5 c% T. l$ q) o. d9 h, P  ?
// Volume adjust+ N$ a9 F$ T3 v
// Internal sounds
3 U6 O" e! l  N, c  t8 i#define        RECTANGLE_VOL        (0x0F0)
7 g; I& \& e; i) q7 n#define        TRIANGLE_VOL        (0x130)
$ S* s* Z2 P: H& ?- Q#define        NOISE_VOL        (0x0C0)" U0 s; M) e0 ]2 s+ e0 K
#define        DPCM_VOL        (0x0F0)
0 S0 p; W' K$ o) s1 h0 P% k// Extra sounds
* s' V* \- W! p) l#define        VRC6_VOL        (0x0F0)) |# N, o, P$ \. i# c
#define        VRC7_VOL        (0x130)
) ~7 _, d8 P4 p/ b& l' I$ U#define        FDS_VOL                (0x0F0)0 X1 _  b3 c9 |* A1 R3 W- g6 z
#define        MMC5_VOL        (0x0F0)" B' E1 ?/ a1 Q; g
#define        N106_VOL        (0x088)
7 o& @" Z* A3 f9 w' Q( t! L#define        FME7_VOL        (0x130), ~- Y4 {3 I$ e7 {  A7 \$ `
# b' r7 R" q9 m! t: \2 H. T( ?( i
APU::APU( NES* parent )! m3 e; ^# _' K! v  @* ]9 Z! W, B
{, f/ ^( T4 J* p: O( v
        exsound_select = 0;# ]8 K$ L! T; k
3 L  F! E+ s6 }- z8 m
        nes = parent;* a9 }/ _* c9 t4 K$ W
        internal.SetParent( parent );
: y% t7 }+ u' ^1 n
7 v- a" |, p8 C: x        last_data = last_diff = 0;/ _( ?8 L8 {* Q* i3 _) L5 P; }( E2 {

! d, l5 m: i1 h        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );& x* x2 F5 V1 \
6 `# M1 l; x/ s
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );% y1 n1 l7 b! [
        ZEROMEMORY( &queue, sizeof(queue) );
7 p8 i: \3 z; T3 I        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 a% P; }4 a7 s, ^+ g

7 o: h1 D/ F, }# l0 X        for( INT i = 0; i < 16; i++ ) {
" U6 ?) a; D, n3 T                m_bMute = TRUE;
* A3 V/ u% i5 Y        }
, f4 X! J: J- K, U3 m: V}' N; O( e; D' ~5 o
) l0 r$ {$ m1 [/ [4 y5 c
APU::~APU()
+ U. r- E4 N3 P4 j3 B{
* ^0 i& S% \2 w9 ^" @}
: T3 H& V% P" M; \9 i! X) t
: P; A, }( Y( o6 h2 x9 ^2 Lvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )% \. z$ J' I7 [
{5 @0 N% y6 u  J: `7 O1 c+ m, e5 J
        queue.data[queue.wrptr].time = writetime;
, j( x- e2 m' g$ I3 [: b        queue.data[queue.wrptr].addr = addr;( t, Z$ ^# q% b2 J7 _
        queue.data[queue.wrptr].data = data;% p9 l' L* n* ?8 `$ Q+ N
        queue.wrptr++;
* B! ?1 t; V' _4 l3 ~        queue.wrptr&=QUEUE_LENGTH-1;" m- @# B' p! g6 S8 [1 z! ^
        if( queue.wrptr == queue.rdptr ) {6 {  a- I- k6 l& }4 i' h
                DEBUGOUT( "queue overflow.\n" );1 m" b3 `! m) \! o( H) A, o
        }9 x) E% ?% p. b; e9 P
}7 \' V" M! l1 f5 d+ m) ^

6 x- Y/ V, \8 b  P4 CBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 q* e! L& e: s5 L/ a+ c4 V; }/ c
{
/ z( Q' L; _7 m" Q: X        if( queue.wrptr == queue.rdptr ) {' w' c5 _( g8 Q& F- q( i0 t. G
                return        FALSE;
( b  _% C* h1 \; w        }( T4 ?) b$ }5 J' W4 U; y( y
        if( queue.data[queue.rdptr].time <= writetime ) {
6 k5 N& Y/ D. j6 G3 |' q                ret = queue.data[queue.rdptr];
+ h3 U: g+ u3 k5 y" x) P1 }                queue.rdptr++;
% W8 v% I. R, g8 Y( F                queue.rdptr&=QUEUE_LENGTH-1;
8 U* x, e% w: y* K& S                return        TRUE;
' m1 t  U& g; K: P        }
/ e, s. p% H* `" k7 B" x        return        FALSE;, O5 }4 J* e5 D5 w; }/ K, M' ?3 l
}
0 b* t2 x  u4 q- `0 B
$ s  K3 }" `* h  J0 K; l! Avoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% w; o5 W) N! f8 a3 C2 l9 x
{
- e8 P* y0 B& ?2 \1 |        exqueue.data[exqueue.wrptr].time = writetime;
. G+ p" P1 Z( f        exqueue.data[exqueue.wrptr].addr = addr;
# u. d/ K: A9 y        exqueue.data[exqueue.wrptr].data = data;! z, R6 `4 [% g2 p9 }! l
        exqueue.wrptr++;- t3 s6 W2 \$ @& n
        exqueue.wrptr&=QUEUE_LENGTH-1;2 N" M, r4 i9 t! d+ M: \
        if( exqueue.wrptr == exqueue.rdptr ) {5 @3 ]. T0 s/ s
                DEBUGOUT( "exqueue overflow.\n" );
+ y  C$ m8 s) A% r% I3 j, \3 @        }
8 Q- m& j- ~  T1 ], k( ?$ r9 D}0 @2 u5 g" v9 }2 f6 T
3 \3 a  H9 l' E1 M* c6 Z
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )6 d# U  v9 N5 K) A1 y
{4 q1 v, l( k- m4 w0 g
        if( exqueue.wrptr == exqueue.rdptr ) {) k7 Q6 |3 E* U# _  h' u
                return        FALSE;* ~+ Y- @8 f4 L/ h9 r9 C& F3 U
        }) \2 N' f: f# N) v4 _+ ~1 H. z, H
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 ], S8 b+ o- N) S* D
                ret = exqueue.data[exqueue.rdptr];
% B6 F3 u+ s; Z0 p8 G& O                exqueue.rdptr++;- K/ _/ ?, X6 e; w
                exqueue.rdptr&=QUEUE_LENGTH-1;
  D7 K9 g. }% t5 W8 R0 O8 h                return        TRUE;
1 T$ V# A3 t( `) ?5 g3 {% }        }
2 z& u9 J6 q. a, M# \) c        return        FALSE;
, x2 n& p$ x* L4 a, [$ g}
1 E0 t1 U( u8 k1 q, E4 y: U+ F# N: f8 \5 K% X$ u2 ]3 s
void        APU::QueueClear()
, g3 ?) @+ [; P- U& A6 D9 G{
3 B9 \  |" r* \  _' _8 c( \6 I        ZEROMEMORY( &queue, sizeof(queue) );3 e7 f3 m2 c7 u! {( P  m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& A& @& K; |  ?+ K) C
}4 d+ |4 I+ ], }# A# ~5 I) Z4 ?
" @: v. M; l) F0 H9 r- z
void        APU::QueueFlush()/ m& d4 v1 h9 ?/ H4 f
{) q; S# H0 }5 p
        while( queue.wrptr != queue.rdptr ) {: y1 S& M4 v, |$ l( w
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );' t3 c2 l2 w! y; n, N
                queue.rdptr++;6 g+ ?3 p: T: I: K9 D) P
                queue.rdptr&=QUEUE_LENGTH-1;
& Q* @, K4 g) a  y* d4 s# N' `        }0 m3 c+ m6 b  O" _
% ~. ^2 J; T' E" y+ E' a8 e
        while( exqueue.wrptr != exqueue.rdptr ) {+ |4 Y  r5 k; z$ R# J
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );1 ?% ], w" b/ I
                exqueue.rdptr++;
  N+ A& K; o  }( g" r% ]0 n                exqueue.rdptr&=QUEUE_LENGTH-1;
# K4 f  H$ c, h* a& F/ D; {) A, t4 U        }
" t! [$ e. W, @! g( W}
! i. J0 C# J% a% ~4 p
9 D9 Q& f) o4 avoid        APU::SoundSetup()
! ^* t3 \. q$ X+ q, H" x3 n3 W{- i' y9 A8 l0 ~4 F) L2 H
        FLOAT        fClock = nes->nescfg->CpuClock;+ T! o" D5 j1 X$ t' K
        INT        nRate = (INT)Config.sound.nRate;  L! ~) ~( U/ E  j- x
        internal.Setup( fClock, nRate );6 J' }  H, ^% D& M9 P+ m" K3 p% [
        vrc6.Setup( fClock, nRate );
7 u8 M- o6 S* n* a  B# @. K0 R' I" A        vrc7.Setup( fClock, nRate );+ x+ c! u: U. e# t5 p6 j: x0 y- l
        mmc5.Setup( fClock, nRate );+ A" X3 y! g9 P, a
        fds.Setup ( fClock, nRate );
- w2 L7 s9 C1 g1 n2 H" l+ f! ]$ x        n106.Setup( fClock, nRate );
# W; h$ r/ T, u" T% }        fme7.Setup( fClock, nRate );+ ~1 F5 a+ u) e/ S
}; i. r' k! {4 x
8 x/ E3 r; G7 B- {  N: z7 q7 x* U
void        APU::Reset()
, t; k% u8 l9 i6 ^{+ |2 j' P. ?+ l
        ZEROMEMORY( &queue, sizeof(queue) );" l8 P/ e2 [+ B% ~7 o+ Q* S1 ?
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! j9 r0 s  M9 ]) p) x
/ ~  m0 q% y3 @! s) }* L
        elapsed_time = 0;
& Z+ o7 ?& E  x& D, H/ [& R4 n# N& s4 e
        FLOAT        fClock = nes->nescfg->CpuClock;0 F" h& \) Y# U$ S% j& }& E2 G
        INT        nRate = (INT)Config.sound.nRate;
7 z9 g% t; n$ J; {5 |3 Q        internal.Reset( fClock, nRate );
4 p& m3 L( D+ C/ Q9 w3 {3 V5 n        vrc6.Reset( fClock, nRate );: O' t; Y& L" i& Z+ I
        vrc7.Reset( fClock, nRate );
% `, o1 F6 F0 j* l! S% }% {8 w        mmc5.Reset( fClock, nRate );
" e0 o; W6 s$ d% h& D! l        fds.Reset ( fClock, nRate );
& c7 {8 j' W/ U2 n        n106.Reset( fClock, nRate );3 I! {/ V0 w/ X( Z
        fme7.Reset( fClock, nRate );
) m( M7 u- ~6 S7 P
, d; z7 v% e/ W' c$ J$ e' C        SoundSetup();
( i  A0 R! A( k: u* V+ n. S) o6 |}/ V! y: u2 ]9 E  f# a" o

3 `. w$ \# B: L. i8 C2 ?  fvoid        APU::SelectExSound( BYTE data )
5 W8 l5 R5 ]0 \( c6 |{; S7 j3 o7 Z; h" `2 y
        exsound_select = data;  X6 X) w) \6 {5 @  ^7 G
}
0 M1 k6 |, k2 X" g4 v# b( O$ \5 l+ D3 P9 w: I5 Q* y+ Y" M
BYTE        APU::Read( WORD addr )" T  g$ F7 C/ w/ E. ?# }
{
5 `* f8 N; A+ Y4 H: _; u3 V        return        internal.SyncRead( addr );6 w* a3 y* A# Z; b9 `
}
) W3 _% d$ z0 f: `6 x: `5 x' Y/ B" R
void        APU::Write( WORD addr, BYTE data ), k9 A6 A& h& q) E* y+ l+ ]: k
{
( f7 j0 W$ T0 ]3 Z& a3 ]        // $4018偼VirtuaNES屌桳億乕僩
$ _+ P- I" I8 T( y/ z1 ~4 C8 w        if( addr >= 0x4000 && addr <= 0x401F ) {, `- K: ^+ X. d& l' \
                internal.SyncWrite( addr, data );
1 K' x5 q7 z5 i& y) W. s( P                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
. E8 n) V7 `/ J- |" P        }
& C1 _( ]1 s% p( T}
9 n2 F( N+ L  w- \3 u0 H; y
8 r4 G& ^+ i) B' mBYTE        APU::ExRead( WORD addr )) q0 _" s% U( ]  o4 F% ~/ {
{
0 U5 I$ L/ V* B0 mBYTE        data = 0;
% C6 l* V0 a$ W9 _8 @5 \. w' j" y- @3 m% y' y2 [4 ?' Y# h
        if( exsound_select & 0x10 ) {% Y& u5 A- |  L3 Y$ E) Z
                if( addr == 0x4800 ) {, u. w2 ], ]3 w" w  g1 q
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );3 {( l0 \) r5 d3 e" T: O$ D3 \. J
                }
" @3 f- i9 M' [* ?        }
/ v  F7 w! D; M' N        if( exsound_select & 0x04 ) {
; Y8 q- ?" t! d! e( R                if( addr >= 0x4040 && addr < 0x4100 ) {
: R* p1 v  X, U& x( F                        data = fds.SyncRead( addr );7 P; a$ I+ q( O5 ?, y
                }
( v) c% ?* l2 G, z4 v; e' H2 r        }
6 Q% e. P0 U3 p$ u* Y        if( exsound_select & 0x08 ) {( g$ @6 s/ m0 e1 M) g
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ D3 d  Z# {1 ]3 X/ r
                        data = mmc5.SyncRead( addr );
( D5 u/ s% l: W5 r9 e! Q                }" x/ Q* n! |4 p8 C7 D# a
        }
3 B: Z% {. [$ t1 e& y  H/ J, v1 o0 o& G
        return        data;
7 V) ?7 T+ h4 e" A8 q2 `5 r2 M}
1 `$ r, v. b! ~1 A5 }
/ f' F; b, U% a( xvoid        APU::ExWrite( WORD addr, BYTE data )  i" H; X8 u, d
{
% L' V/ K- L2 I, r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );. u) u. C, P2 r3 j
* `( s: T# B3 O9 Y" Z& K; s
        if( exsound_select & 0x04 ) {
' w% Z2 M# `% W& z+ V( N/ D                if( addr >= 0x4040 && addr < 0x4100 ) {
$ n* L0 n- @: G                        fds.SyncWrite( addr, data );
8 G  m3 W# _* `0 Z2 K                }4 b1 c& C- @3 |: Y% w5 Q9 f* n
        }
  [: N% B3 e; t5 {8 s! f* }6 J' G! ]: e$ L4 Y; M: |& o
        if( exsound_select & 0x08 ) {. g' B  V* B0 `
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ g5 b8 _9 y0 b3 |$ E                        mmc5.SyncWrite( addr, data );4 r1 z' _7 O5 t3 b7 l& x
                }
/ e& n$ X3 n, D) {/ i8 A7 E! j2 L: U        }! o" a0 q2 T$ m( s* d0 Y9 i
}, J6 F! q1 v: Y
3 E) ?$ S+ d/ ^$ M  M
void        APU::Sync()
. t& w$ F/ {4 g{
8 g  P! o2 Q+ P. F4 C3 u, G}" Z2 S; T4 d7 k2 D4 y( g2 g. E
7 u, I; ~2 E$ @( E
void        APU::SyncDPCM( INT cycles )- y- c4 l- Q3 C, Z5 d) b
{4 \* ]" t) L4 H0 R: ~% M
        internal.Sync( cycles );
2 S1 T7 n- l# ^2 U  \' S: O9 J5 }0 v) c
        if( exsound_select & 0x04 ) {, o4 ^4 w( F) Y! f
                fds.Sync( cycles );
5 M5 R0 W/ m- N7 e$ W- d" ]        }2 X" Q0 P% h- Z* [6 n3 ?; ?: G
        if( exsound_select & 0x08 ) {
% w! F$ v2 f0 A/ h( i* E9 D& J                mmc5.Sync( cycles );
( V2 c( [$ o: I! [* t+ y9 N        }# s7 S% E% D6 N0 ~) g1 o
}" b( Z3 q! b3 R" Q, n4 n, a
  w9 o7 t( b+ I8 v. l
void        APU::WriteProcess( WORD addr, BYTE data )
7 @' [, I5 S$ a* Z: x{( P* t! o5 F9 G" B
        // $4018偼VirtuaNES屌桳億乕僩% T: ^- g  j/ a, A* a' ?6 `( W& k
        if( addr >= 0x4000 && addr <= 0x401F ) {
) b9 f8 A1 l( j( Y# t1 P% h                internal.Write( addr, data );
2 d# i0 _( h6 P" @4 |& d( s9 k        }" q/ F" d5 W- I- ]. S; A
}
" Z" q1 e# p; _& c" G& N/ }8 j" [3 [1 ]  n& ]- t# n: B
void        APU::WriteExProcess( WORD addr, BYTE data )) y" w5 |; k; V, F( |# P8 e6 S7 ]
{1 K' F5 N! B( t0 `6 Z' |. d
        if( exsound_select & 0x01 ) {( Q* X/ n% _* Z( i. M8 U' E
                vrc6.Write( addr, data );' C# \5 Y9 D: K$ r1 ^) z
        }
, P( H' `' I# u- r        if( exsound_select & 0x02 ) {: o! S5 O$ r$ U" ?
                vrc7.Write( addr, data );- J$ r7 z/ {3 G9 ?2 `! c
        }5 C2 C" y$ f9 `2 u5 z% \4 ~
        if( exsound_select & 0x04 ) {' O% ~0 R- k% L
                fds.Write( addr, data );- B4 C% k" _& \% z  k" U
        }
. a% w) R( `# `7 |, H. B* Q5 }        if( exsound_select & 0x08 ) {
$ d' u# J% d+ M3 O% Y9 h                mmc5.Write( addr, data );( p; a# c9 a1 ]
        }
6 U1 |. E& i  m3 F" @. D        if( exsound_select & 0x10 ) {& _9 l  ^) k  s# G; H4 p
                if( addr == 0x0000 ) {
  j+ U" ~3 F+ \, z1 r: ^9 v                        BYTE        dummy = n106.Read( addr );+ h& r- e4 N* Q  q
                } else {4 r: L1 N. Z* t8 T4 j: A
                        n106.Write( addr, data );, R( d# l" p7 i
                }
  y  u3 s% g. z8 P$ U0 k, H        }2 j& h( x  I% J  x( O
        if( exsound_select & 0x20 ) {5 n; Y! @. q; ?9 X; \5 T$ @: X
                fme7.Write( addr, data );
; _. }, y) O& c        }
2 {9 t4 n- I# m8 _/ _% w}
! E$ n0 i. A2 L& `, T5 r
# \* X3 w1 u2 B4 D" |void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )/ e8 s" p, c; {- D  a+ ~
{. p( m! h6 |$ M1 V/ R
INT        nBits = Config.sound.nBits;+ L/ U" A. m  j* m) ?! a+ P! {
DWORD        dwLength = dwSize / (nBits/8);
9 y3 W# y- h# HINT        output;
9 S4 U7 x0 G9 Q/ H  P% f5 g; {" HQUEUEDATA q;
& a9 |( L' m. ^9 \DWORD        writetime;& X" o" F* D# k( {- F1 }# {

6 N2 Z' a! c( N! bLPSHORT        pSoundBuf = m_SoundBuffer;. X9 Q7 d! _: O( ]) Z
INT        nCcount = 0;
2 R' w2 F1 a5 p8 W1 s; F! f3 v
# p4 {8 C. j( e/ DINT        nFilterType = Config.sound.nFilterType;2 M" f. x/ I# t; F( t  V; e

' g2 Q* v  I9 t, T. U- V        if( !Config.sound.bEnable ) {
8 Y$ `+ ^$ Y) o% E# g4 k                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );9 }! b* T2 P7 X6 ?; \4 y
                return;
4 H9 y  _( D& o- z5 c2 @        }
2 v, D, g1 k' f  u4 ~8 _
; E, r3 O) y; E/ ?1 I  _        // Volume setup
. T, @( g; z5 T( n        //  0:Master
% `' ?, b8 f5 |9 e8 r% Z& T        //  1:Rectangle 16 G* W8 |* |+ g5 G. F- T
        //  2:Rectangle 2$ ?0 @$ L) e+ |
        //  3:Triangle
6 A7 r+ b, X" N0 J4 `8 b& k        //  4:Noise- F9 b% f. R0 j  B8 J; H9 y
        //  5:DPCM4 p% m4 \4 v# W/ Q
        //  6:VRC64 M$ ^6 x1 t& C  ~. q1 S
        //  7:VRC7
: l  |* B5 I; o8 S: H) Q! f        //  8:FDS7 C- C  t/ A, u
        //  9:MMC52 G7 i8 `; ~* X7 E
        // 10:N106. U3 C: m6 S- {! D$ j  g
        // 11:FME7
- w& {" Z8 S6 S) W. ^        INT        vol[24];
# E$ M9 d; E; o" [% U7 l/ L% `/ E* P        BOOL*        bMute = m_bMute;3 I! ~# R2 T! g+ W1 E! c
        SHORT*        nVolume = Config.sound.nVolume;$ X! o0 k; Y. w4 ~( H" @5 J

2 w+ G: @7 O& ~; ], F, i        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  R7 Q# w8 F; H4 F* }

$ S5 J. T" `; Q- n+ z$ ?* d        // Internal- }1 x3 s$ w' }1 |1 A, ~# Z! G7 {
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;. l" m5 c( q& }* C
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;. Q# U" ?7 D: z! Y" \, ^8 {
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;7 C# y+ J* @' @* ?% e# T1 p! @
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
* _5 E2 X( W1 ]: h1 u3 {        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  L* O& `8 W* Q3 X2 H4 `4 S8 e

* i% Y! j3 W6 A2 x$ H% N8 I* a$ W2 @, K        // VRC6# A# Q# ^1 k9 F5 N* d6 c0 w
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' X. x' Y) }1 g$ F        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 Y% C' N# f4 K. Q- s* B7 B$ d        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) m: w4 ^+ x3 q
0 n$ {! Z- A, c( t( n$ Y4 L
        // VRC7
2 ^4 M& I5 z/ S7 ?% y        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 g, A7 Q1 r' h% R1 x/ v! U* o4 I
+ [- q8 [3 R+ ^. W- g$ ^5 u+ p
        // FDS% J/ \# ~9 Y' b; I1 s3 o
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;# ^) U' k% D% M# t
0 W" w5 [3 n: c2 I% T
        // MMC5
* J( N7 W- F& C  u" v0 Z  p! f8 b        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' I6 \, E9 K6 U. T' C# q+ p- H        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( Y) Y2 t& k6 J5 E
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 N+ @+ l! w4 V9 w9 P  G- n* F

9 A- o2 `7 y8 @5 a3 L* Z  G0 c( {        // N106
( i  P+ R  [4 g) o3 ~        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( J4 y( \8 M% J7 C1 h" X: K        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: t4 c; l7 e9 r8 I5 i& U# |$ r. k        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& u+ m" Z% ]* X: W        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ P1 E' s$ p4 ?4 V9 g        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 L. L8 ]. b( E' F1 Z3 g: R
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# z: `# z- z% s* d        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 k0 f' Y% `1 x' x- c! }. U        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& z4 L, r8 r  h8 o; o: W- ?& l! `0 `4 l) S
        // FME76 K7 J2 P- I6 I  l. I, V
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* ~  A. N1 M+ W) [9 N        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  U4 U9 j+ a  S+ D+ O        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 w  C! j9 V; X+ Z2 \1 `  b/ _6 U! t+ w, Q' i
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 X5 l& h; k. C% ?4 ~7 e
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
% R. R- v9 u3 t0 s7 v3 Q' \' W. r, |0 @8 ^
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' z9 a: t9 V+ f& |9 }3 O        if( elapsed_time > nes->cpu->GetTotalCycles() ) {" A! P/ c0 V! P& n
                QueueFlush();
" {, @" \& c. E        }
5 d, Z; h) F) \6 p. ]* T# u, k" w/ W2 E
        while( dwLength-- ) {
+ O0 n4 a3 |& g: H                writetime = (DWORD)elapsed_time;
7 U+ x/ s; H; w9 Y
  |. q+ S" z9 j6 u9 G6 N/ P7 W                while( GetQueue( writetime, q ) ) {
; j& r! Q4 i- J* P7 b3 k% z                        WriteProcess( q.addr, q.data );
. J$ n- |3 h- d2 \3 w5 b                }
0 ~$ ~4 p+ K1 M( P1 t. U5 q- H: G5 R, n6 v) }: h: S
                while( GetExQueue( writetime, q ) ) {
" h4 g  X; u) t                        WriteExProcess( q.addr, q.data );
; _# ?& i' Q2 f! f, U                }
3 M7 Z% M- K& {; |$ @6 A+ Y' Y- a
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME76 Y( Y& I2 o8 E) d. N
                output = 0;+ g& x2 l9 }) U1 o+ s3 ^; F8 F) ~
                output += internal.Process( 0 )*vol[0];& L! D$ q. z8 i$ V; x- V9 ]
                output += internal.Process( 1 )*vol[1];
; v, }: _- {; o                output += internal.Process( 2 )*vol[2];1 v3 C4 X$ |1 n* N, Z% U
                output += internal.Process( 3 )*vol[3];- U! b6 u& i. [
                output += internal.Process( 4 )*vol[4];
7 [9 [1 M- N; W& }8 C; @6 ?( C+ v; V$ @+ f' \- n
                if( exsound_select & 0x01 ) {
6 H: r3 u  ^* A% b( v% \. \# x- _- v                        output += vrc6.Process( 0 )*vol[5];6 ^9 r* a  X. Z! u) m
                        output += vrc6.Process( 1 )*vol[6];, I! R, w- ]: G' c) O5 m
                        output += vrc6.Process( 2 )*vol[7];
4 ]$ N7 E- R+ J/ i0 ~0 @                }9 O% Q* I' }9 n, I, H" w
                if( exsound_select & 0x02 ) {
6 U1 K5 \; E0 s' t, }; d/ [                        output += vrc7.Process( 0 )*vol[8];  n2 Q7 C  z: a; r
                }
- ^2 ~. F6 Z$ Z; k/ }) b0 L" A                if( exsound_select & 0x04 ) {
. l7 O! g" R" f% I) n2 s                        output += fds.Process( 0 )*vol[9];' Y! a. _9 ^3 `0 P. t+ I
                }% z; J5 S: _/ X* N$ Z6 m
                if( exsound_select & 0x08 ) {
) z3 i* o$ P, j7 x  I$ O                        output += mmc5.Process( 0 )*vol[10];5 W+ I* U1 v2 ?
                        output += mmc5.Process( 1 )*vol[11];
% c7 g; j+ i$ P5 i                        output += mmc5.Process( 2 )*vol[12];* L- b4 W! j# N% t6 e4 ?; B1 v- A
                }8 c# Y7 w& t8 I8 i' V7 g
                if( exsound_select & 0x10 ) {+ }6 z( r. D1 x: M/ B" Q* I+ h6 d
                        output += n106.Process( 0 )*vol[13];
9 w, E; b0 w; c/ m: b! c  {                        output += n106.Process( 1 )*vol[14];3 Q% }( U1 K  S7 p  ^
                        output += n106.Process( 2 )*vol[15];! R: a0 q3 p8 d; \* L
                        output += n106.Process( 3 )*vol[16];" F# _9 D5 s! x7 i! A
                        output += n106.Process( 4 )*vol[17];6 H; T4 p1 _7 R+ E
                        output += n106.Process( 5 )*vol[18];
+ {6 h" j5 Y3 o3 o                        output += n106.Process( 6 )*vol[19];
9 \# a# N: Q/ \2 q: x                        output += n106.Process( 7 )*vol[20];
  _8 D7 c, v2 R; t1 N                }
. ^+ y8 H- f" ?3 w( Z                if( exsound_select & 0x20 ) {
: G4 p# Q( r% k                        fme7.Process( 3 );        // Envelope & Noise
  f+ u- O( M( I. j5 D                        output += fme7.Process( 0 )*vol[21];
6 B" F0 [* @1 u( g                        output += fme7.Process( 1 )*vol[22];
" W* p8 J8 S9 u5 j                        output += fme7.Process( 2 )*vol[23];
. X9 D' I0 ]+ _* X' H: {                }7 |2 ~. V8 s  O, I  n
9 C, Y1 s6 F$ y& C: V% L
                output >>= 8;
2 v# k8 i2 }4 R8 o+ D) ^- x& Y4 b8 {( f2 E  u6 H9 r, h% {; w
                if( nFilterType == 1 ) {, P9 v" N, G1 g  G6 P, A
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
9 D( ]5 Y  I3 U- J) f+ g1 c( C, z                        output = (lowpass_filter[0]+output)/2;9 l# ^3 I9 p% f( M9 }+ z) s
                        lowpass_filter[0] = output;$ t% l; y- s1 v8 p2 M0 t5 D
                } else if( nFilterType == 2 ) {* A$ \2 a- P( \. }9 z+ A
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)( f4 ^2 D' \. ~2 f
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ ~; v# t8 U, K/ l                        lowpass_filter[1] = lowpass_filter[0];
4 i4 ^: ?1 ^% Y; H, x2 U  @                        lowpass_filter[0] = output;
0 B6 T4 y% O; t$ a                } else if( nFilterType == 3 ) {
# k5 j$ I/ C5 ^& A                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2), p: H' L+ z9 k' s, I1 P! j
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;' R# j/ a6 R' {9 I  i) Z; _) M6 U
                        lowpass_filter[2] = lowpass_filter[1];
7 s2 d. c* \) K6 T$ D1 S                        lowpass_filter[1] = lowpass_filter[0];/ K/ H1 p/ n1 Q# u. a/ @
                        lowpass_filter[0] = output;* p* Q' i8 J- Z, J0 h4 |- y  \
                } else if( nFilterType == 4 ) {
! E8 W3 K# O9 J0 v$ {* c  A8 {5 N                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
  \* u7 X4 ]+ K$ W! s6 {& Y: I                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' X4 E3 \; k4 a% d" ]" ]% @  k7 t
                        lowpass_filter[1] = lowpass_filter[0];# b9 J3 b/ ]$ U; i8 f
                        lowpass_filter[0] = output;4 g7 d2 T" ]% {$ S! x7 \/ C
                }2 j8 f! T  v; ?' w! G% A# e7 {& u
- s7 F" K9 X6 s% S
#if        09 t  h, K% y$ k, D  M
                // DC惉暘偺僇僢僩' p! D' R( `  d2 K2 f# J5 N, F6 l
                {3 L0 W3 J/ c* t7 k- t* v
                static double ave = 0.0, max=0.0, min=0.0;  x" p2 ~2 [; d# L
                double delta;
# C, z1 j2 z& C' R$ V& D5 \1 i                delta = (max-min)/32768.0;  B2 _. [: {, Z
                max -= delta;
, R+ E$ X4 l/ s6 z                min += delta;
# Y0 u5 s% r2 ~0 G# e                if( output > max ) max = output;3 i8 j2 J6 |: ?4 N
                if( output < min ) min = output;
# i: d" Y& o5 @8 x1 K7 C& c                ave -= ave/1024.0;' [8 \$ _1 t# N" D! B$ D
                ave += (max+min)/2048.0;
# j) k' f5 d: T8 D                output -= (INT)ave;3 A: X- x$ Z% c$ v6 v
                }
9 i. u, R! c5 `  g#endif8 m1 }6 d7 Q* }' \- G9 ?7 Q$ [
#if        11 U0 t/ e4 V: G
                // DC惉暘偺僇僢僩(HPF TEST); H: F( d$ J9 U# u; H0 s- Q% b
                {
, m) q  O' a/ ?  r8 Z" ^//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" B6 Z$ a2 F: _' g                static        double        cutofftemp = (2.0*3.141592653579*40.0);
9 z; {' ^# c3 y" `! V$ H- e                double        cutoff = cutofftemp/(double)Config.sound.nRate;
  O) S" M! ], M4 n) K                static        double        tmp = 0.0;4 q& E; x7 B  E6 F1 w, A. ~8 l
                double        in, out;
6 `8 L# Y; v( V$ d/ ^4 }6 S& x
+ A- k9 J* P, t                in = (double)output;
  [. j0 L# w- L- O                out = (in - tmp);
5 y* V7 N! S: o7 ]6 [                tmp = tmp + cutoff * out;( X4 X! u3 [# U
" X4 }0 Q, f- D
                output = (INT)out;
& J2 N" n9 H* w- b                }# w" k7 V: @- B% `/ U3 R$ |
#endif" A* N6 S# L* l" [* }5 L: D2 T* F
#if        05 A: ^9 i2 q2 W. e3 \
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
6 Q' f" W! b$ G0 l                {
4 [( ?8 ?/ G% ^9 G8 W) [+ g& C                INT        diff = abs(output-last_data);) _5 [9 t5 W1 h' O7 F* j2 @) w
                if( diff > 0x4000 ) {6 X/ A8 j: k$ z
                        output /= 4;  M( ~1 V: W- G& J% a3 i0 E5 k4 F
                } else
- s+ m! r- d; {                if( diff > 0x3000 ) {
# X) h$ T+ ^9 f& ^                        output /= 3;
6 `) L5 ?$ P) E5 K6 P0 V                } else) N: w9 |6 g/ z9 e' v% ~/ j
                if( diff > 0x2000 ) {
+ b0 B3 t+ a( M2 @  R/ ~; E                        output /= 2;
" p2 R5 ?, H2 Z1 T. x                }
% y. W5 j4 b5 w+ U                last_data = output;( q  ?1 n6 g$ I/ y' _9 [
                }$ Z/ h2 O" C+ B* H
#endif8 A. ?" `, }0 W! x. Y- e) Z2 q% X/ `4 n
                // Limit. G$ g  @* F) B. V+ B1 e( w
                if( output > 0x7FFF ) {! Z0 n# H! R5 X2 @* Y1 w# U0 U
                        output = 0x7FFF;
6 v( a2 O% S! X7 B; L9 |5 c                } else if( output < -0x8000 ) {) s; q% O) f# N' X% s
                        output = -0x8000;
0 i0 a5 e3 N( q9 h' F+ P' g; B                }
" o5 C' w% e6 V, @: g
0 |1 Y7 k( F& v5 A                if( nBits != 8 ) {) w+ ]6 ]3 s- J* T' l$ n6 ~
                        *(SHORT*)lpBuffer = (SHORT)output;
* Q1 m1 U8 y4 @1 k2 s, M8 Z                        lpBuffer += sizeof(SHORT);; f  a( m8 `1 x0 U6 v" v
                } else {" ^& f% a1 \9 z( w
                        *lpBuffer++ = (output>>8)^0x80;
! K5 H2 N  X& G0 `1 A8 T5 e- e$ ]                }0 e+ q+ c- h0 X( A. n3 ]
+ ?# N, }) V: L1 C$ T; F
                if( nCcount < 0x0100 )
5 e/ p6 Y4 c& l5 i, k) J                        pSoundBuf[nCcount++] = (SHORT)output;) g! V* o$ O0 w9 I
: P! m- E8 y) A4 h
//                elapsedtime += cycle_rate;, G- ]; \5 S; r+ s' s5 W7 p
                elapsed_time += cycle_rate;# `( A0 ]7 x3 W: [
        }) V& o& S  d( V2 n* P* |& F

! `# U1 ~9 n: K# ^7 @+ _7 s#if        1
3 X  l- S5 l; P        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {- A5 f: Q+ e7 D
                elapsed_time = nes->cpu->GetTotalCycles();
/ B, s7 q0 u7 `' F        }
4 }% }: c- q& N7 @4 h* q        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 R. F6 U, S) S& I0 b& e
                elapsed_time = nes->cpu->GetTotalCycles();
2 ~% w2 |7 u. E0 v$ g2 C6 b        }
# [9 ^2 C2 M! |6 _! ~9 Y#else
3 H0 N+ O4 A* S' ]; Q- [0 |        elapsed_time = nes->cpu->GetTotalCycles();
. v4 G4 X0 N: q9 y$ O#endif! U" h. z% r8 X5 A% ]$ t, @
}8 Q/ P6 i# ?! P5 A
/ o2 `3 q# p! p$ V
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)) T6 |* u1 P2 Y
INT        APU::GetChannelFrequency( INT no )
( z/ F- b0 p/ |& {; \% V* u{
# |3 |1 i0 G6 h4 R        if( !m_bMute[0] )0 X  w9 u- i9 e$ }* Z1 p  S: D* g
                return        0;
" v( y6 a' ~3 k# \: r9 R
& e  H' Z- p0 ]2 A6 P5 r2 c        // Internal% r! L  J; R( R
        if( no < 5 ) {
! L' X, x% [. ?' Q                return        m_bMute[no+1]?internal.GetFreq( no ):0;: m( k6 |  N" v8 r* y
        }
" @, R+ I4 C) @$ i9 K% [$ N0 b( w        // VRC6
9 b: y5 r- n5 t        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {( |7 Z+ r  k4 ~# v% e- b& h9 Q! A
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
# C: p. s) y3 Z- P9 V        }7 I& i5 h) p9 Y# l1 f6 w& T
        // FDS
# U* i- D# e) c) J! E' T2 r5 W        if( (exsound_select & 0x04) && no == 0x300 ) {3 |/ J6 J5 b! n! V2 v1 r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
$ o5 L" h8 q; ?2 V2 ~4 P2 C        }
' _) _3 |# T$ W4 j$ f        // MMC5
" A+ ?! y- n$ V. v        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {/ l5 X4 t& G7 D2 B; q1 G
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;* W% \3 t/ {1 X- w. `2 Q$ V
        }
6 f6 E: ?: u+ o+ B- @        // N106
" f) B( U. m0 a8 S1 V8 u: u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
* J0 `3 Z9 n: o/ A: A( l7 i' z; @                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ l6 T+ I, A# d        }! Y1 P0 I" c+ ?7 U5 \' L" H# V
        // FME7* A3 p0 D" B7 q4 m8 i
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
& L- l, V* {& S% U- l2 s                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;0 I( y; K0 S9 W% I
        }
7 `, n- U% Y2 ?  v5 U( w" H        // VRC7
1 j! A& z; O4 J" F5 O! ]5 U6 E+ w        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
  x, x8 ]! i# d$ w                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
9 s7 D% ^  v: a2 J9 T        }8 M0 e1 z1 b( v2 l1 V. B
        return        0;7 a0 C" |( r5 A3 w0 {% p2 L" u- E
}. F5 C# x* C4 F( W* X+ D
* n5 a5 F0 ^  M( C
// State Save/Load
+ m( ~0 z# }/ B+ @* f. Xvoid        APU::SaveState( LPBYTE p )$ @+ |. H7 F) u/ k( f
{
5 `* \/ g! L$ A" h2 h7 u#ifdef        _DEBUG7 S: J% ?4 D* M4 A2 O. k7 B
LPBYTE        pold = p;7 r% J! |( N5 q' ?) L* |
#endif( X& v% s% p! ^: s& s" c

! M, a- o3 f' Q3 x; c- `$ [. H        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* b/ w$ x* |+ F$ c/ ~! T. X        QueueFlush();
' r. [7 o+ @7 w7 c, s% [4 I" m: r& G8 V! A  T! M" u+ E
        internal.SaveState( p );
& L" u6 Z1 E" e6 Q        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
% |% F3 w) \9 h) H3 y: W
/ g# w7 m7 `4 f        // VRC6# P- O0 o8 A7 ~$ W( F
        if( exsound_select & 0x01 ) {
" o$ w- W* l1 I                vrc6.SaveState( p );
4 t& o4 C7 X5 B  \/ c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% p- A( Y7 O; T
        }! a( T: p1 m( e: R3 n. D* k5 b( j
        // VRC7 (not support)
. Z2 |. G  f8 h( P# d        if( exsound_select & 0x02 ) {4 r3 n+ f5 F! C$ @. \
                vrc7.SaveState( p );
: o& D; O2 O  o) m5 I                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" D  Z+ p: Z) P9 x
        }5 V4 z/ Q8 N3 Z5 n, ?# V
        // FDS1 Y- v3 T6 _, u$ c' m- Q1 v+ ]
        if( exsound_select & 0x04 ) {
; W$ ~' R( d+ V3 U                fds.SaveState( p );4 ~- G) p# t4 b' ^) I: n; j
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: w0 X, `7 q# k        }1 s& \  k3 h. L
        // MMC5% c4 f# C: k5 ?+ J4 d6 t
        if( exsound_select & 0x08 ) {* z% m' _: f& I9 C) t
                mmc5.SaveState( p );# ^, F. U6 O9 t9 J# t
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
% J7 w- d) w7 n+ R* c" T2 w        }
2 Q6 x# Y8 m6 t7 ~3 U8 ~        // N1067 L) K! {7 \- j/ M) M, ^! [0 A
        if( exsound_select & 0x10 ) {
5 B" I+ o' b, b, I1 _: ?                n106.SaveState( p );
+ s. i# V2 T" A+ ?                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 S' O8 A4 ]1 o1 r
        }
/ J& g5 _. i+ \* E3 x$ Q' P        // FME7
7 l6 c. [/ ~' d; x. c  Y        if( exsound_select & 0x20 ) {( m" {! g" `' x: _3 R8 Z, }* g, ^
                fme7.SaveState( p );
! m, b" s, \+ t                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 `6 U. s9 r. J$ V- F2 ], \        }
/ U9 s7 H& q* x. m2 D: J% F/ u1 u& e: @1 ]" ?* T
#ifdef        _DEBUG* F1 ~$ m' C2 D; P! F, ^
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );: q% f" @4 n- o2 J; p+ ]8 G
#endif# y5 D& m5 B$ A9 w9 ^% N
}
' T" T9 s+ ?) G: Z6 p, Q3 o+ c; j, ?4 G, V  B1 l7 M
void        APU::LoadState( LPBYTE p )
5 t. o& Z8 o  C" T+ Z0 ~3 n/ K" s! D" B{
' L8 s2 H, D9 D3 u        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ T3 u+ _/ N- J
        QueueClear();  L4 k- R! ?" w* U7 b& Q
# ]2 Y/ @+ x8 r- O0 ^9 b7 k
        internal.LoadState( p );9 c. n3 `4 E9 L* d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' Y4 _5 t  L* z  @, A
; G  A4 b7 A$ ?        // VRC6
2 p6 t: J9 D  _; m        if( exsound_select & 0x01 ) {
7 H3 y8 X7 k9 w- \" g                vrc6.LoadState( p );
1 u8 a# _! q& ^7 @                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 B# w5 A7 a1 k9 L. f8 D2 e# w        }
% A8 N5 o% `- A& q9 q        // VRC7 (not support)/ ]$ }" r0 T. s# \6 k6 p
        if( exsound_select & 0x02 ) {! o" S) J6 t7 t
                vrc7.LoadState( p );+ Q5 X+ T% p% u: J# d
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ l4 u( @7 B3 ]7 F* k% U
        }, [, d7 T* X% K& ^" W; w8 M
        // FDS* Z( u. ]* L5 r* |) T, _* i
        if( exsound_select & 0x04 ) {; Q; {. e8 T4 V0 s9 R2 W; p& i/ E
                fds.LoadState( p );9 C3 E* S! v. W2 S) w9 m% V% [
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 \- O: A4 x. H        }& x' A1 M, t9 @
        // MMC5! ?+ C+ z% m3 M  z# }/ o
        if( exsound_select & 0x08 ) {
( E) \  f' a& t0 R7 E0 m                mmc5.LoadState( p );. \% T( u# A" U" N0 y8 e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 U- d- Y$ b3 C, S( p        }
6 T2 u4 ]* X( l) e9 M* k        // N106
% z1 ^( K+ B6 d        if( exsound_select & 0x10 ) {
: m+ B7 o5 [/ Y; W7 ?                n106.LoadState( p );# C- ]9 k3 W* Q. @! `7 H* C$ g
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ m  k9 q1 c, C3 P; Q6 h# P        }
" i6 d; M9 W6 H7 p3 s! ^5 t1 |# J        // FME7
$ x( \3 a9 ]( O/ @1 H( g        if( exsound_select & 0x20 ) {
3 z( r  b: {4 i) g/ \* N                fme7.LoadState( p );3 v+ G; w  G6 ^7 s& t, Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& E. w3 q+ `% o  B) q        }
3 [0 L( ^5 Q2 o) y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % ^7 o3 U9 ?5 v# G, N. j1 i
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
; x9 p+ |7 v3 {7 \感激不尽~~

" u- Y/ s% _5 h0 u- z: p恩 我對模擬器不是很有研究,
# r# A" G! o1 b$ C' C雖然要了解源碼內容,可能不是很困難,0 L3 ~, p: k1 \* L6 h- j$ [
不過還是要花時間,個人目前蠻忙碌的。
0 T2 _$ j( k6 F4 r8 Q4 k" T- }% l0 [+ x2 \5 c
給你一個朋友的MSN,你可以跟他討論看看,2 M/ Y6 f2 u) K7 Y' g3 K
他本身是程式設計師,也對FC模擬器很有興趣。/ |0 O- h! T% U8 E" c# |
& Q; d+ t" F. i3 D- @0 N
MSN我就PM到你的信箱了。. j7 H! K/ H$ X- Y; M; M
5 V* {; ?2 k, w7 ~
希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
8 l" v; d: d' e; D3 e呵…… 谢过团长大人~~

4 d' L$ R3 B( ^# ]7 D# O+ m$ ?6 y0 X/ m; |
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & a6 k5 R9 P$ W  w; P% f8 ?; G
团长的朋友都是神,那团长就是神的boss。
, w3 r. f: c& ~/ e2 n
哈 不敢當,我只是個平凡人,4 q* _. i' s% n, L5 N9 ^
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ N& o" C+ q& cZYH
. V, G! y; w: m1 o/ aQQ:414734306  A. i4 f. @- C$ p/ [
Mail:zyh-01@126.com
) M. S5 n- C( k/ X  s! E- v3 f  D7 T2 h0 W; U; P3 A
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 7 e3 L4 T- I3 a8 @# z$ D& ~+ N
再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 k, G- d% ^- b% W9 @* g不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-28 11:47 , Processed in 1.131836 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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