EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 m* t9 F8 D6 x9 z+ ^楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
: ~. d6 {% _9 y( S( h  i这里有相应的模拟器源码,就当送给大侠了~~
. g$ [" q2 k! W2 b1 V- Y$ }http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 / Y) T3 d; L' N- V
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% G% \7 K/ @6 a4 z8 R3 `% A2 u6 O楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 S' x9 _. E3 w5 _! x这里有相应的模拟器源码,就当送给大侠 ...
7 h: a, a5 z, x- f. H+ ~
聲音部分(Audoi Process Unit = APU):7 p; U  F: g3 k0 t! _& F
.\NES\APU.cpp1 s# x( _# p- e- W
.\NES\APU.h
/ Y5 s- m8 S# g* u5 V  |$ M: r8 e
2 }* Z9 j# h0 D! j3 g3 o6 p; K* I, r. e% T8 w  ?' v
影像處理部份(Picture Processing Unit = PPU):# u3 V' x9 I- R7 \( u/ `% R
.\NES\PPU.cpp
- }/ Y7 G" S1 ^! T' s' Z.\NES\PPU.h# ]# n7 \  ~9 J5 g
. c' d$ F- Y7 A) n( t! r- x
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:* j' g; G2 r; y6 e
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 H$ {  ]" B/ f4 W  [1 L
//////////////////////////////////////////////////////////////////////////
6 {) I6 T% l/ v/ b//                                                                      //
) h  s7 W/ O# `* w9 I//      NES APU core                                                    //7 m4 H: W: A% V7 |
//                                                           Norix      //6 k4 u' P' K' B6 Y' ^% H& @
//                                               written     2002/06/27 //# k' ~! w: P" P/ Y
//                                               last modify ----/--/-- //
* y% t, Q# `4 b9 [//////////////////////////////////////////////////////////////////////////
0 a* A' [1 c% {3 d9 i6 S; N8 k#include "DebugOut.h"; `6 u" ?. M! L4 @
#include "App.h"
7 p4 w, Z# L) b" K5 Z#include "Config.h"! z% |/ N9 {- Z6 S

, C; c* i5 W* G  i. t, L( c#include "nes.h"
% k5 w' F6 L3 X#include "mmu.h"; \+ l7 J3 y5 h  V: m
#include "cpu.h"
. y5 t7 Q( D) u+ f  B" ^#include "ppu.h"0 O! }- c3 i. W
#include "rom.h"6 P" a3 [1 q& S7 m: P* a
#include "apu.h"
" m( O) r# F% _1 M1 O
: `+ k/ N( a" W1 ^8 w// Volume adjust% \9 E4 \) q4 M
// Internal sounds
8 x- M. s& Y9 |: I: V# v#define        RECTANGLE_VOL        (0x0F0)7 R5 _- y! P2 v( b
#define        TRIANGLE_VOL        (0x130)# L9 l# F: I' y/ I$ s9 G
#define        NOISE_VOL        (0x0C0)
% t2 [2 F$ J% t7 e* h# i+ B#define        DPCM_VOL        (0x0F0)
9 l3 y) x- P) l% C1 _( x// Extra sounds
- ~# |) }7 z* K% ^8 C8 [* }  g9 s#define        VRC6_VOL        (0x0F0)
& l& }. W  A6 W% U' H3 p& [#define        VRC7_VOL        (0x130)
( ^1 e% N8 \+ j8 R#define        FDS_VOL                (0x0F0)% q8 _/ i  A: d6 _$ z
#define        MMC5_VOL        (0x0F0): Q" v1 {) i/ h, y
#define        N106_VOL        (0x088)
7 f* W+ b' N) m+ h$ C#define        FME7_VOL        (0x130)
" A% u. F6 H7 q8 y
: o; }. A2 P9 X  i2 ~" UAPU::APU( NES* parent )
# h/ W! I# o+ H' n4 o$ k{
6 g, o# N8 Q# L( L8 p' M# [% B        exsound_select = 0;
$ t5 z" }: N9 S$ t5 ^4 {  l2 R9 d: I7 ^
        nes = parent;) b( o# e, r" r' d7 {& w3 w( x# I
        internal.SetParent( parent );$ u! B. C0 t0 q, I" H0 ~5 O: `# Q

* X2 q& e* H6 i& T        last_data = last_diff = 0;4 R2 N: Z' G$ n9 J" q; y; {, m

3 a9 X9 b0 z# x: p& ^7 S4 y        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
: p/ q8 g! y( \
/ F) Y3 ~( O4 C, c        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
9 n& X, V. b  U/ O& |& i        ZEROMEMORY( &queue, sizeof(queue) );' S: ?. d. Z# d: `% G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 I/ M0 q+ t* x+ h4 }) _" ?, h
1 N1 w% X$ f) ]- c  C" a  n
        for( INT i = 0; i < 16; i++ ) {
( j& G5 N: F; S9 t( K/ u                m_bMute = TRUE;+ h: L9 d1 Q  c9 R
        }
: o! G% A, Q7 J4 m' m}
+ `1 W% v6 b" C% F* h  F# Z- \5 K) d9 v( Q7 w" w
APU::~APU(); |5 e( H3 C$ n1 f
{, j9 d2 B8 t8 O; }
}
) A" \" t3 {$ k  A, [
: b* `! I# P6 B' fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) {; Y8 V7 \; i9 _{
& R) z' E) J& B, u  Z1 F        queue.data[queue.wrptr].time = writetime;' b/ p  F5 t0 d
        queue.data[queue.wrptr].addr = addr;
$ [( F; T: G+ S3 Y0 R) w# t2 W        queue.data[queue.wrptr].data = data;
4 u: D: V4 _; l- u& x$ W        queue.wrptr++;( W! t. j7 l8 i  _
        queue.wrptr&=QUEUE_LENGTH-1;
7 o% [% {' J' R) T        if( queue.wrptr == queue.rdptr ) {
# k8 k( a2 r  \8 J                DEBUGOUT( "queue overflow.\n" );
* a; D! s* r6 s7 p2 y% D        }, h% e8 E  `8 V" a0 W$ x2 W/ q+ P
}# [1 R1 G, b/ G3 V0 L

& }: P+ F7 w/ c/ v: H7 A9 }$ m6 H) r2 ^BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )# w1 Q) z! w' ]  M. a, t, a* e
{' V4 T! j. G& h# n" B$ ]- v# D
        if( queue.wrptr == queue.rdptr ) {- q8 ?( n. d- ^0 W, q
                return        FALSE;
# A. k" N' D: k2 j        }
( K* U0 C) n) K2 h" Z* R        if( queue.data[queue.rdptr].time <= writetime ) {
3 e, H* t3 \- [& b! q                ret = queue.data[queue.rdptr];
! @4 Y  o  O' }9 n1 I6 `                queue.rdptr++;
2 r% b7 j% M* n% g5 T4 P                queue.rdptr&=QUEUE_LENGTH-1;' d8 A5 h3 `% P5 W/ |) c1 R2 B
                return        TRUE;" @9 i7 [- t* X5 ?% i
        }
! A; |  D% q+ Q* }        return        FALSE;
4 @3 o5 X  M4 P2 _}
' S* j$ N" {$ r3 M5 v
4 D  l! d8 {. e1 |& m1 Wvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: p5 Y. n: D) {4 o: P- X{
8 o2 f% c% G2 V        exqueue.data[exqueue.wrptr].time = writetime;
3 s1 g3 r) J# f1 X        exqueue.data[exqueue.wrptr].addr = addr;
8 l5 g( n2 y/ ]1 g# m% K7 G        exqueue.data[exqueue.wrptr].data = data;2 B  V  O. j; ?, N( g
        exqueue.wrptr++;1 u' \0 V' v. K! P
        exqueue.wrptr&=QUEUE_LENGTH-1;- [0 ^; [6 w, `3 g0 h6 i2 V
        if( exqueue.wrptr == exqueue.rdptr ) {
6 j# i. Q3 ~1 C( x                DEBUGOUT( "exqueue overflow.\n" );
- V7 j2 Z. ^' H- D: i& D        }
0 p2 w) S% J0 `, X! N' M}- b; i3 {, n- q6 n4 J
# h7 w. H) h4 f9 Q4 b
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
) C! A/ D. |, t. u% L% L: i9 G{: V1 U/ ^( e+ @
        if( exqueue.wrptr == exqueue.rdptr ) {, v" t! _8 _7 ?* d2 C
                return        FALSE;
2 j* @" Z5 n  K" p# z        }
  `' S7 O, x4 o# a        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 |, A% K# ]5 X3 ~. N2 X/ K% P
                ret = exqueue.data[exqueue.rdptr];
8 v8 w- I5 d, y, y2 B4 [: L                exqueue.rdptr++;
& D+ ^+ i' w$ D. U- [- `                exqueue.rdptr&=QUEUE_LENGTH-1;
5 p) _/ r0 L* n/ O                return        TRUE;
6 r- X$ i* X1 F+ e: }        }
/ m( J' H/ N, @1 u/ k# m6 Z        return        FALSE;! x7 `) V* X' k% _4 K9 O8 c5 y
}
$ V' B* h2 B* ?, T/ V. t# g( X9 E3 M+ b: C
void        APU::QueueClear()
& g1 m6 L1 T2 I+ K8 I{+ p9 ?6 O, B/ c1 ~/ @9 ^" E) B% u; R
        ZEROMEMORY( &queue, sizeof(queue) );
) i+ q% [; @4 U6 n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 Y( r! Q( Y% {5 \' x9 G}
6 w( x# ?! {1 _" I' `5 n8 Z% N" y* z. \3 C6 s
void        APU::QueueFlush()
- l& b$ K" R% \, B5 k4 D{( K5 k7 l5 q0 I. W4 U
        while( queue.wrptr != queue.rdptr ) {
' q: x! J" B9 W; `+ D5 \, [% F                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* W6 g, t' A( W* M0 Y                queue.rdptr++;
: q; f! l- a4 w/ k8 J) r: G/ c                queue.rdptr&=QUEUE_LENGTH-1;2 u. ~; F* b* f1 z
        }
/ {- J# V3 A+ x7 S3 _; z5 I5 i3 o' |- U( _+ y0 @
        while( exqueue.wrptr != exqueue.rdptr ) {+ x& P% A0 F4 f! ~2 g0 v" c; i
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
# P0 X8 q7 n3 A! Z1 z                exqueue.rdptr++;& N9 i6 h5 w' t1 E1 l( x& p
                exqueue.rdptr&=QUEUE_LENGTH-1;
, D# {( @8 V. n! @% }1 q" r        }  k9 e3 k7 P3 n  C
}4 `* b, x2 A( v; @) ~6 {

7 |4 D3 R% k* P& Avoid        APU::SoundSetup()# }, p* j0 D- l) N8 i8 _
{9 ~8 y- W6 ^; }/ Q
        FLOAT        fClock = nes->nescfg->CpuClock;' q3 e) w- }3 N- G- w
        INT        nRate = (INT)Config.sound.nRate;' t' O  f; Z/ s! _# C
        internal.Setup( fClock, nRate );
6 A( H  G% U& a' v        vrc6.Setup( fClock, nRate );3 W& h& Y! t! K- \1 \
        vrc7.Setup( fClock, nRate );
, ^, b) V1 q. ]5 m8 r4 R        mmc5.Setup( fClock, nRate );
  T6 O) e& \9 ~7 ]- U$ I; ?3 K# c# B1 l, I        fds.Setup ( fClock, nRate );
8 E( e" `; q  {; ?2 G* F! x        n106.Setup( fClock, nRate );
7 K  }  x7 s- Z5 W* A) |        fme7.Setup( fClock, nRate );% z1 h/ l2 J( i
}
: T6 P) P, ]/ n* k0 n% @: }( T9 `7 K1 J
void        APU::Reset()
3 T) `4 E# l; {8 f{
0 @8 T' o' f2 J6 j; b& p        ZEROMEMORY( &queue, sizeof(queue) );
/ L5 H2 z2 g6 \' ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( ^* N- c+ \5 }5 j% w8 w
6 C  i3 }- q3 H5 k        elapsed_time = 0;
* ]# A0 u( k; `1 L5 I7 e$ [4 v7 k2 K9 j. u: y6 G; ~  a6 [7 s
        FLOAT        fClock = nes->nescfg->CpuClock;
; W/ S1 P8 H/ v/ y# N; k        INT        nRate = (INT)Config.sound.nRate;% X' o/ ]  W/ `. a9 Z( e
        internal.Reset( fClock, nRate );
& R  j# w0 P: k8 V        vrc6.Reset( fClock, nRate );3 t% e$ h9 C: r9 ~3 B% i
        vrc7.Reset( fClock, nRate );9 m5 J) W$ A1 q+ E7 L+ S
        mmc5.Reset( fClock, nRate );/ c8 U" G9 E% d. Z
        fds.Reset ( fClock, nRate );) L( Y2 T' n, R1 [; L5 {
        n106.Reset( fClock, nRate );
  _" n9 t/ V5 q! A9 M        fme7.Reset( fClock, nRate );# W1 o0 f: _- w
/ ]5 y% ~8 q* L. A3 A+ u9 }- S8 B, l% S; I2 a
        SoundSetup();3 L4 ^3 n) d! y4 Z! A
}
1 z' e5 Y4 k* O2 n$ g$ Q$ V" @) y. g5 p1 t
void        APU::SelectExSound( BYTE data )
1 s) h( i! C2 P: D{
; p; i* c1 R4 ?4 Q        exsound_select = data;
  ]$ v" h# a9 w3 V3 R8 m}$ I$ x1 H/ n3 p8 i& Y. k

; f1 K& E6 @# ~5 P% JBYTE        APU::Read( WORD addr )8 [0 g2 s/ J" O
{
* p9 @4 k( U2 j( f( z6 J2 l6 x% t        return        internal.SyncRead( addr );
/ k  }# H2 T+ A6 u}( L$ [- D# Z+ E1 M. z

- [8 f! Q' c3 o/ ^& ]9 F3 Pvoid        APU::Write( WORD addr, BYTE data )
/ f7 w/ N& f- t5 `{) [9 A3 _+ j2 ~$ Y" b" A* |5 c3 {
        // $4018偼VirtuaNES屌桳億乕僩
4 N5 l) c) D; }- l        if( addr >= 0x4000 && addr <= 0x401F ) {) Q, Z! }1 I2 u  K+ s9 R
                internal.SyncWrite( addr, data );# n: K2 L7 U3 G' }5 n
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# m, B* f: W. i; T+ N6 S* _        }
0 T3 e% x4 x1 J, X$ X  i}& ^$ h& c5 t% s! A. d& d
; j, F5 u$ Y2 `! S5 l
BYTE        APU::ExRead( WORD addr )! Q8 k9 V* i0 c/ ?1 l/ q
{4 H9 t! U& Y8 v/ `2 t
BYTE        data = 0;
$ A# F! Q% Z, O7 i& D7 a5 ~
" x5 @8 q* o: H: b: A' s        if( exsound_select & 0x10 ) {8 m( z5 x4 ~  Z' T. `( u
                if( addr == 0x4800 ) {4 X" E9 R* P& w' i0 z) e' p0 g
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. ^, C# z" S/ n) T1 O                }* l5 j0 X) o( r# |! G: k4 F
        }
! a9 Y6 }' \! u* ]% u$ D        if( exsound_select & 0x04 ) {5 q: f2 ?9 J; _3 C
                if( addr >= 0x4040 && addr < 0x4100 ) {
5 T+ w. ?) r8 Y6 i* ~8 X. e+ Z% O                        data = fds.SyncRead( addr );- {" Y1 `2 M, T  ?' s* D
                }9 y( r( T) u% c5 N0 F4 K. O- L  @
        }6 i; m3 v7 j7 b% w
        if( exsound_select & 0x08 ) {
* p$ O$ I1 ?  T9 A                if( addr >= 0x5000 && addr <= 0x5015 ) {9 m8 H9 [2 T/ ]/ g/ |9 W1 s
                        data = mmc5.SyncRead( addr );
/ u. G4 N  K' u; |! v' j                }; ?) N0 Y0 z/ E
        }( P0 L/ M6 s( s! J3 J# h) X( e4 }

8 J) |4 L$ O4 _7 G5 [        return        data;* C2 J& b  [! L, \! i
}
& e  Y) N; }& ^* `( }+ @8 Y
+ r1 q! W+ |6 r/ b! }, f5 Q9 cvoid        APU::ExWrite( WORD addr, BYTE data )
* c& l4 K' Z. m7 V* ?{2 x# @! B6 \) `/ Z: o0 [7 R
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& o' W& s, |5 Y& X7 O$ G1 _$ f) w2 C' W  P. E0 F6 G
        if( exsound_select & 0x04 ) {
, {  v$ s% p4 ], I, g) A8 A  Y                if( addr >= 0x4040 && addr < 0x4100 ) {; J9 b; Q$ u' Y" U2 p! l) e/ M5 ^
                        fds.SyncWrite( addr, data );* D4 U5 D( c7 T; S
                }
& s, A: O: g$ _9 U5 I; Q& m4 z        }! X5 a: ^3 J8 d

" k+ Z/ j$ q' ?- S) K8 z! v        if( exsound_select & 0x08 ) {1 a' n9 A! t* a7 N. l
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ \& {  e  {- h* t6 L
                        mmc5.SyncWrite( addr, data );# a& \/ R; {, u, d; e/ [
                }- w5 m- h8 M8 [- @$ _$ m* W  H
        }
9 g3 |0 S0 }& Y) N! ]}# M3 W7 [+ U- Z/ G! }
& G3 k3 x, [9 C
void        APU::Sync(); P& l5 e- d7 z9 B4 V
{
( K" F* i7 e; N! ]0 }5 m, H}, Q2 @# Y% [9 ~: Z

/ E: [. Q+ {' f0 Pvoid        APU::SyncDPCM( INT cycles )
" Y2 Q" K2 u3 \7 D$ V9 W. P{0 p4 Q* Y7 \$ b9 \
        internal.Sync( cycles );1 T  |3 y+ H; r/ b& K; t- V
  _% E1 Z, w3 Q9 v7 I  G4 Q
        if( exsound_select & 0x04 ) {- f4 i3 N& B1 k  n7 |
                fds.Sync( cycles );
1 D4 `  z5 ^$ X        }
. w  L6 q# Q* t2 m' s        if( exsound_select & 0x08 ) {
2 g% A' N5 a, L) i% l5 }                mmc5.Sync( cycles );6 J4 ~0 l' A- o4 L' X) a  K1 h, b
        }
) O% n& }" ]; r1 S% x/ I7 c! {}
) u* X- e1 [* f3 p! n; h& n5 l; Z+ R( q; w) E
void        APU::WriteProcess( WORD addr, BYTE data )2 Q9 N/ d. L) e$ E3 B
{1 Y0 C4 B, |1 r6 e) p4 }  U9 v. q# z8 R
        // $4018偼VirtuaNES屌桳億乕僩
2 P* w$ @7 j. r) U: Y        if( addr >= 0x4000 && addr <= 0x401F ) {
6 Z! C$ p$ d3 E5 l                internal.Write( addr, data );
4 j$ E: m  i: C! s% z4 X: u        }
4 g; W) I) Q. c; L}
- h/ M% }" d  ~+ W3 v' a
7 _  }. g) J1 }6 \6 t8 `$ ^' bvoid        APU::WriteExProcess( WORD addr, BYTE data )
; b+ j0 V, D# q& ?7 w{7 ^! `- g( o! s% }
        if( exsound_select & 0x01 ) {
) a( Z; X1 Q* e                vrc6.Write( addr, data );
" a# {# Z8 c' w: Z9 }: j        }
& P% l" m9 X) i! a        if( exsound_select & 0x02 ) {
8 r! @$ X' o2 d0 C7 L5 p% D                vrc7.Write( addr, data );
2 r$ I7 f/ V6 |" t$ O' |' Y        }8 m' n. o( ~" U
        if( exsound_select & 0x04 ) {/ y$ Y: n  S) d
                fds.Write( addr, data );
9 `+ j3 C3 y& a) R        }; q+ r" i' c3 j; I& u
        if( exsound_select & 0x08 ) {
& b2 o6 c7 I- J1 ~# Q- A& Q                mmc5.Write( addr, data );8 [$ q, k: R7 v: U/ w+ D
        }. e7 k0 D2 a# D* d3 ?4 ^2 n. H
        if( exsound_select & 0x10 ) {
) ]  ~; s6 `' g+ j2 L                if( addr == 0x0000 ) {  u9 ?- T$ Q  j
                        BYTE        dummy = n106.Read( addr );/ ?+ V  u0 I! I5 q) I" t/ s$ t
                } else {; W: `. C0 D7 P$ k
                        n106.Write( addr, data );0 v3 m1 O( ~; y* Y
                }
, w; _' j$ K2 h; m        }
4 Q0 {: X" Z- d( Y1 q- }        if( exsound_select & 0x20 ) {
/ U; E1 k/ s; E: Z0 t8 ~! c                fme7.Write( addr, data );
( i# k+ L# f1 X& ]' Z1 b: u- d+ X2 F# i        }
7 V8 s$ y: n2 y1 v& R* W2 J}
4 p7 \5 ]! s" w; [+ x4 ^2 Y+ o# g! [
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
4 j; P' ]$ J& k6 S: T{
7 N- {5 W6 `2 E2 |INT        nBits = Config.sound.nBits;& @7 a" S2 p9 L9 d$ V' K
DWORD        dwLength = dwSize / (nBits/8);9 P" ^7 ]; P1 d% C4 L% K9 e
INT        output;
, M* E0 G8 N- u) k/ u1 JQUEUEDATA q;' \3 \0 x7 B: [# B0 f6 \9 Y( d. W
DWORD        writetime;
% ~/ M  e  y+ Z( @# c  @3 [2 H& H/ C' \8 J' X3 ]- `6 M: h! \
LPSHORT        pSoundBuf = m_SoundBuffer;8 {- a1 e6 }* d! U* A7 _: v
INT        nCcount = 0;  s  Z4 r0 ]$ s5 P" s' G2 c

8 d5 d- s' _  ?$ x9 M4 r3 x' vINT        nFilterType = Config.sound.nFilterType;  n* I$ v& W3 ], Z+ ~/ d7 m8 [2 _

/ @; l5 m4 B! @- i* A        if( !Config.sound.bEnable ) {
' i+ c1 N5 G3 J                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
; l  ?# [7 O' |2 F" X3 t                return;
/ j3 o5 ^5 B8 o9 k8 |5 D( w: r7 h        }
+ F0 @+ x" H& y, e' ^$ d, ]% q3 _" z; |3 X" B" q5 k8 _
        // Volume setup
; u  w0 ]. O+ ]7 g, g( ^        //  0:Master( n% |& b. Y1 Y  k( i% V
        //  1:Rectangle 1
, x* u4 q! \' S3 i% c* G* D        //  2:Rectangle 2
$ Z  A+ v4 Z5 Z4 E9 _) f        //  3:Triangle
1 `3 X" \# g6 d: R        //  4:Noise
( a5 l! g& h# @  Q" t2 t9 n5 L        //  5:DPCM2 Z+ h% @; i( u% n4 b
        //  6:VRC6
" t& U1 d( g) J+ |        //  7:VRC7
. J6 z7 }" \. {- e' O3 h0 Z& l        //  8:FDS
# ^! l7 d  n4 Z  U        //  9:MMC5: ^" W3 ]/ r/ [! G
        // 10:N106
: x, W4 }) z5 f% H- x. v4 d9 y+ h        // 11:FME7; N5 V1 V& E/ A7 F7 ^
        INT        vol[24];6 l5 X$ R8 I  u
        BOOL*        bMute = m_bMute;
7 @$ I% u- w0 N, l% j7 k8 l        SHORT*        nVolume = Config.sound.nVolume;& w3 T+ a5 o' x+ l$ u5 }/ ?; M. p; u) O
: h$ }7 J' m5 Q3 S: D8 L
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" U  A- v; v) X' m% s/ w* B( q% i
6 |$ H. v  B% i, n* G, ^3 M
        // Internal
1 Z0 b. Z& X. M/ G        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;- s8 y/ }. n  K$ H3 j& B
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;. f/ [% i2 o# h& O: ]# M
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;9 O6 L8 A3 W: _, u( D( n
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' D% X; K6 u% ]- U( a6 I* r        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 D! ?" G: x) m0 [4 G- C2 K6 q
( m! O6 X+ ]" |& @0 V  {9 ^5 C: h& e
        // VRC6
! A$ O4 O# I, G. Q( r        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 Q7 b" l- n0 |. [0 p  h  Y  i6 g
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# z7 N1 j( t0 ]/ }8 j
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" \, [5 c9 V2 V& X

! J3 t/ Q7 B) @9 n        // VRC7" Q& Q  e! u7 D0 n
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 b0 W& A4 G( k: h& E# h) k; d

2 n/ _( s8 A, P$ k        // FDS; A* U# q" [, Z8 S4 r; b, W$ i
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
! ~% R! }. Y8 G7 u5 ~% K$ S" q/ k& Q' z) P) Z' ?) r/ S3 x: P+ W
        // MMC5! h/ \1 }# G8 Q; u
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* e7 \% C$ `4 l$ }0 B( _! m        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 M! @  E6 f1 Y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 v# i, V& ?7 i6 l

" |9 T# X' u, c. [* O! S        // N106
8 i9 a* X) a/ {( W3 Y  z        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ S+ d8 c) ~3 \, v# c6 C8 _: Y+ }
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 J: B, T0 e4 U* ], v8 f4 s
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 [' \: N$ L; y+ W* W: E/ }
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: s, L+ k- ]9 h! o/ Q9 E
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 A' X! g+ _' n) i& d! @; N% k: V6 e        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 k5 m) [4 {$ |1 i. f# K        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 z( l0 t4 ]% s6 p  [1 c  t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 r% j& o& ?6 o2 g- Y7 V6 i  j# p: i. i$ m
        // FME7$ Q" m* R6 s  i4 G: Y7 M( z
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& k+ @& O% X4 C7 T! Q: }, i        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: {, D% q4 B  J, o1 k) B5 V        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 o0 Y1 T/ G! Y- E2 f# z2 H9 N* J. S! a: v" z, D5 N5 W
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" g; \* X. W# c. Y
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
" K/ P7 \/ g# V
4 L. c- B! m/ g/ N* K( k        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
) M% f) @2 D) S# [1 _5 _        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) s3 f" O# B# N/ n. I: v
                QueueFlush();
( ]* U4 K& ~3 |4 u+ `8 |        }2 i$ T" H1 x# u6 `
' y3 ~& e& W  q' M$ n( z
        while( dwLength-- ) {8 M! t* @2 X5 m  a
                writetime = (DWORD)elapsed_time;4 w) @' L5 C: }; {. u% y( \! q

/ D9 l  E# f8 F3 V9 e                while( GetQueue( writetime, q ) ) {" q# a; i: h% b) ?6 I, _6 u
                        WriteProcess( q.addr, q.data );
8 t8 L' d1 z4 I3 C. \  x5 _                }: z, J# r* _" [% b; \" x
; [1 B# X+ a# m5 U, l1 O# k
                while( GetExQueue( writetime, q ) ) {
  y6 B: b! i- h; ^: U                        WriteExProcess( q.addr, q.data );
2 ~! W$ n7 C4 E                }
: }+ l$ w6 i6 z: ]; S5 K3 H/ O1 O
5 N0 c8 @9 _+ {" m                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
* O1 s& d: R* k0 F3 M$ {6 z3 C  _+ }                output = 0;
- ]1 D" w7 q+ P) f& i6 v                output += internal.Process( 0 )*vol[0];
* W2 t) I; p. g. L2 \% w% F- r( h                output += internal.Process( 1 )*vol[1];
! Z* X8 G2 i/ ]: }                output += internal.Process( 2 )*vol[2];
& _' C, r' L. i$ Q9 _' v                output += internal.Process( 3 )*vol[3];
$ ?) O6 n+ w' R7 I5 ]                output += internal.Process( 4 )*vol[4];" o  h9 Z* X3 j% d3 s+ \
; X2 h8 F- l, z% _, Q' [2 ]. e
                if( exsound_select & 0x01 ) {5 P# P  a0 x: e
                        output += vrc6.Process( 0 )*vol[5];
3 s1 H+ n) h8 @0 \' {/ v                        output += vrc6.Process( 1 )*vol[6];
5 V9 M" @1 ^4 M& v$ a5 ~                        output += vrc6.Process( 2 )*vol[7];
, e. j, G/ u0 c/ O                }' V) N7 O( ^! a! x% k
                if( exsound_select & 0x02 ) {
9 u+ h- w1 l0 Z' c0 t7 s. ?  Q                        output += vrc7.Process( 0 )*vol[8];9 O5 @  p! H% c3 Y8 A1 D
                }1 i2 N  w4 Q$ a( N. L# ?7 K9 Y
                if( exsound_select & 0x04 ) {- g& l% E; w4 x) \
                        output += fds.Process( 0 )*vol[9];6 t9 {3 F4 r9 E" i4 M" [
                }
* G' L, S5 }5 m- U9 I$ U7 k                if( exsound_select & 0x08 ) {3 o2 t7 v! P+ _2 F5 |" H
                        output += mmc5.Process( 0 )*vol[10];. X+ h  \# H8 l# @. W
                        output += mmc5.Process( 1 )*vol[11];. ?3 q+ D: ?2 s  q7 L- [: F
                        output += mmc5.Process( 2 )*vol[12];/ ?( T$ w: t7 M0 X1 w
                }- z4 E- A5 M+ n4 s2 _/ D  f
                if( exsound_select & 0x10 ) {2 H8 Y3 a( K' P/ y5 z
                        output += n106.Process( 0 )*vol[13];
( m: B* |* r" f5 w* E                        output += n106.Process( 1 )*vol[14];1 s7 n7 H$ @4 @: F0 _4 g. t
                        output += n106.Process( 2 )*vol[15];
& m$ I( o- H# {4 X9 C* p9 [0 H2 t4 ]                        output += n106.Process( 3 )*vol[16];7 `& F5 J# e# B7 f
                        output += n106.Process( 4 )*vol[17];
0 S* G* X# I3 ?0 n- _) T                        output += n106.Process( 5 )*vol[18];# o6 `- n6 b$ A# {
                        output += n106.Process( 6 )*vol[19];' T% ]! ]* u8 p$ y4 i0 n& ~( B, G
                        output += n106.Process( 7 )*vol[20];3 |8 \6 I8 ], l4 |
                }3 N( h5 B. w1 O7 G: h! `- d) ]) Z+ \
                if( exsound_select & 0x20 ) {0 C- G5 `6 k: }! A' U' d. W
                        fme7.Process( 3 );        // Envelope & Noise
/ U) D7 f- o* N7 q" d$ I                        output += fme7.Process( 0 )*vol[21];
' N/ R+ `0 c1 y$ ~5 E, \                        output += fme7.Process( 1 )*vol[22];
( p+ y) V: E- K4 g& K                        output += fme7.Process( 2 )*vol[23];
) ]1 n/ k) d5 J' L: d# @* M4 l                }
" h; @# T7 [( a( p
* C8 S+ f) T9 q                output >>= 8;
# T+ u1 |! I3 n  D& K. e: ^  A' r' I; j- A
                if( nFilterType == 1 ) {, x, o0 Q7 x- u& B; R+ l
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
) v/ S  ^5 I8 }% K9 {                        output = (lowpass_filter[0]+output)/2;8 r. ?* |0 p; h( ^5 `: {- E5 x4 X
                        lowpass_filter[0] = output;" I# z; B: l9 l1 |/ Y+ Z1 @
                } else if( nFilterType == 2 ) {
) V" N" E% E% Y5 j                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)! r, b5 {4 @1 m% `2 S7 }/ M7 }
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
9 z. J3 Z) E) j9 |: {                        lowpass_filter[1] = lowpass_filter[0];1 Q+ q* Y" P0 V' [! t6 S
                        lowpass_filter[0] = output;
  ~) [) ^1 O& V8 A5 R3 `& ]' F                } else if( nFilterType == 3 ) {" q9 ]$ L; N) A. h& k5 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% ]; A1 u; {: Q$ g7 l                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
* }: v  l3 k8 q. ~4 F                        lowpass_filter[2] = lowpass_filter[1];# t: X; ^. o6 Z
                        lowpass_filter[1] = lowpass_filter[0];/ ~9 n& d& ^4 l% {' ]2 U) T$ h9 R2 f
                        lowpass_filter[0] = output;
% p! B; r9 g7 w: F* N                } else if( nFilterType == 4 ) {
& B% i0 |# h8 {, V9 O                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 P$ p1 r, c. y* ]0 L0 I                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 q9 v4 s* l" R0 F: `! s                        lowpass_filter[1] = lowpass_filter[0];+ y5 v' p: [2 R. |
                        lowpass_filter[0] = output;5 q8 A& I. Y9 }
                }$ W/ k: A0 y" ?' d" ~3 V

6 q5 g" Q. V' D6 ]: Z4 c#if        0$ a4 a& s& r$ K
                // DC惉暘偺僇僢僩
; }' O% _4 L1 C. a/ X: B                {& p+ p) D% h: V" d9 O: F
                static double ave = 0.0, max=0.0, min=0.0;
- ^- ~6 ^6 X" E0 A5 Z: M                double delta;* F) `2 S$ W8 F1 F# y. n, B
                delta = (max-min)/32768.0;
( z& @  B- I2 f7 ?  K- X( F                max -= delta;
1 {  Z. O, z- F9 R$ d                min += delta;
9 \* O; u) h. t- o                if( output > max ) max = output;5 |6 z2 _% }4 X8 c# E
                if( output < min ) min = output;' p/ H8 Y0 _0 e+ M5 K4 f
                ave -= ave/1024.0;/ n2 K7 B0 v& ~) @2 w. p
                ave += (max+min)/2048.0;; U6 a( `, n# u- o: c# D
                output -= (INT)ave;& K# Y  U' a4 N4 S; K4 _' V
                }
1 y% D6 I# o  g) \: a#endif8 k: ?- L1 ~7 m% N3 |
#if        1
9 D4 K: I4 `# _: L                // DC惉暘偺僇僢僩(HPF TEST)7 b, i$ ]( U6 @8 H# m2 n
                {
) U7 L; _" Y1 C, x! e6 C6 H//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& }0 x$ e+ `# |& I2 F8 J' e4 j4 C                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 R& W" n- M0 ?% c                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, Z, A  s+ A. \  I# L3 ?: @                static        double        tmp = 0.0;
# a/ J7 X1 n) w7 z. ^; g. v8 E  B                double        in, out;
1 O6 ?( i+ m5 z+ R6 O9 x8 V8 ~7 r1 v1 R2 V6 N5 u5 ?! z( ?! V
                in = (double)output;
" |  `5 G* H4 {& T/ ~- S                out = (in - tmp);+ s7 _. O  M4 N7 ^2 J( e9 E) a7 ^
                tmp = tmp + cutoff * out;
6 l6 S7 m$ U9 I. K. n; R- |, w. X
                output = (INT)out;3 ^2 @% X! ?9 p# L4 m1 z7 M
                }8 G1 j6 \3 i8 L# ^' @
#endif
) D: C8 m) J! L#if        0% R- K9 F; M. y7 g* i9 e' ~7 i9 u
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
! A5 d3 z) ?. P                {* W2 |' n, j9 K0 O, k
                INT        diff = abs(output-last_data);
. p$ J+ w1 X" s0 G/ K                if( diff > 0x4000 ) {
4 r5 V9 t7 L" g" r. k* T% f                        output /= 4;4 C1 f& V/ r( a! ^5 p7 A" F' P
                } else . N! r1 u  b6 v. U" O7 Z
                if( diff > 0x3000 ) {  K. I! g+ ]  `# S* j
                        output /= 3;5 P2 z; ]+ P1 W& n5 \) F9 X
                } else1 }5 c' D; L: _6 W9 p, u
                if( diff > 0x2000 ) {
7 z: \' h: w3 m: P/ l4 k/ j/ s                        output /= 2;; ?6 D! j  ^3 N- i
                }' I& b! M" f: ^  ]) C
                last_data = output;
6 e6 d% U' e$ L; N% ~; B                }; [7 }" y& H; O1 F# f% o. \0 H7 m/ j
#endif
6 n! L5 X/ t. w. t8 ]8 }( g                // Limit& v$ n$ O$ _/ g- u3 ~# L6 h
                if( output > 0x7FFF ) {
: i- Y) R% N: U4 |# g                        output = 0x7FFF;! O' j' [3 m6 q5 n, ~8 Y
                } else if( output < -0x8000 ) {) T5 @2 d: _: ?8 r9 A; c
                        output = -0x8000;  V1 Q* u/ g1 v( b& u: x
                }" S/ K; ~; D+ ^4 u; n0 D. n
1 z- f( A4 B; h" c- m8 u* X
                if( nBits != 8 ) {) u0 i4 {8 e5 B( U
                        *(SHORT*)lpBuffer = (SHORT)output;
* R" `$ R  a# f( H/ l# T2 `5 ~5 \, I                        lpBuffer += sizeof(SHORT);
! m' Y. {+ ~6 W1 D7 m( e' t0 m                } else {
: r2 [2 k* i( y4 M( L9 Z5 O  |                        *lpBuffer++ = (output>>8)^0x80;
; h1 b+ d& l2 ^; h2 \                }
; z, W* E3 ^4 u" ]& O2 m8 g! k9 m/ H2 w9 n4 T. m: I+ u
                if( nCcount < 0x0100 )
+ @' `8 a% M5 x: @, r3 O1 M; q                        pSoundBuf[nCcount++] = (SHORT)output;
6 @5 Q- ]( o3 i9 d4 U# ~
( o) h% A$ u+ x4 f0 `8 D( C//                elapsedtime += cycle_rate;
! M/ j5 A6 g  o* w" e4 U                elapsed_time += cycle_rate;
. E+ I# _: r. c4 P$ i0 X, j        }0 L5 H9 `7 p/ z$ p5 }' e6 ?  S

2 k% D/ u, C: {) Z! g! z: s#if        1
2 v- G$ r7 w; b* _' G0 G, y        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {  \+ y3 ~( z% K) |3 u* }4 V
                elapsed_time = nes->cpu->GetTotalCycles();8 U4 v, }( ~" r, Y0 C
        }
' S$ ]1 A! K) F0 O' I% p. M        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {, P4 p: k" h$ z
                elapsed_time = nes->cpu->GetTotalCycles();
; B2 q& }, x2 R        }! X: L- m4 r- ]! A3 S
#else$ \9 N- Y* F! W  y1 b* _
        elapsed_time = nes->cpu->GetTotalCycles();
# h' O) G9 ]  Q( g2 X# k2 n% c#endif
  Q. w. m/ `( n, M}, ^" L. U2 x# h) H# w! \
2 s# n9 \* {/ s
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡), y% _; H$ P5 q  B( u
INT        APU::GetChannelFrequency( INT no )6 V' ^- D7 V: i
{
0 U1 X8 M% b* R, f) Z! D' T4 v        if( !m_bMute[0] )
- }2 O9 M( W0 @; N2 X8 m. {                return        0;
4 m' t/ @$ a6 s5 d/ ~7 [5 q1 H" L) u' Y% P/ i+ b
        // Internal  D, R! r8 z+ ~4 ~
        if( no < 5 ) {# l- |  h# n9 n1 V
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
. O7 z& X7 _1 e. a( B4 C' h        }/ `7 O4 y. h$ \/ T* h% h
        // VRC67 n4 R( O' R9 Z$ g' p( v3 p2 y
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ b3 }3 Y7 t" D. G' Q! r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
! \' `; J+ T/ w1 S  H        }* Z9 p1 m, W) f& ~' M0 x
        // FDS
' r% W& J# I. h        if( (exsound_select & 0x04) && no == 0x300 ) {
2 v3 O% V# |; r1 X, D                return        m_bMute[6]?fds.GetFreq( 0 ):0;( M; q# J& R9 _8 Q# e2 l0 q
        }
2 V4 t0 L3 D2 [% S0 {1 e, H' b        // MMC5
' r0 I8 G1 P" U/ a        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {( f# S- A( u4 G  w' p2 S
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: {) @0 F. t5 }        }
# g7 L8 \' ~& `  j' E' T$ }        // N106# i7 h& O  U. R" C% x& M! e. {
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {/ @# g' k  q1 ^  t0 v
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
) \1 R5 I( ~/ d+ n" c        }6 x0 F/ C* @- ~6 u! y0 w
        // FME7
* l8 k% j$ V8 t8 Z( H/ w: f+ ]        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {( N' }) s( k; k/ ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 L2 Z3 f+ D7 B$ n        }, Z9 U! M8 a, X1 }8 X  P
        // VRC7) N! [0 x8 Q$ K( ]
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ B5 d6 k' b6 A9 _7 E. {                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. @/ Y2 |6 k- ]( R
        }
; A' E/ n* `# Y        return        0;
! t$ i# c+ Z: N  R( v}
9 w* B, L; Y6 c+ g
) h$ ]5 m5 L$ C0 v( Z2 O// State Save/Load
9 V, I8 w. w$ D' G! Lvoid        APU::SaveState( LPBYTE p )
$ @7 k7 q$ D) D* n{1 R6 G$ S- v) C3 o$ }2 ^9 B, N, U0 ?
#ifdef        _DEBUG6 t, ^- Z- D( Y5 t) _' r* E
LPBYTE        pold = p;
5 f$ ^. V2 Z0 e7 @. w: f9 v#endif0 M0 G# x! T2 @
* [: }! `- f6 H, u
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞( }3 A  `" t& p* D6 p
        QueueFlush();
4 e) u* A% A; U6 M' q/ X. |4 o7 |. c& y
        internal.SaveState( p );
. X3 A3 z7 E5 y0 r5 g5 E* |  O        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# I5 ^- d! B7 G! v5 j1 l
! `; k" l. T! q- P5 E* c9 @        // VRC6
6 }: j, c  |% r3 ^: g& t8 k0 c        if( exsound_select & 0x01 ) {
  t% H" h' d7 r! N9 t! M5 w& e* D9 q                vrc6.SaveState( p );' w8 N; f5 _& C6 t' T7 j2 t
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ I/ U1 d) Z, D5 t- y+ q
        }
) w9 B" i6 p! w; F! U. O" h        // VRC7 (not support)" V  h! k8 [# ~5 [& D& ]
        if( exsound_select & 0x02 ) {7 |8 D, j: c. ]. e2 N& r
                vrc7.SaveState( p );
/ Q" R# D3 X0 `2 O6 S1 ^+ X' i                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, Z# \/ [% U1 N8 M! Y
        }# m/ j+ I/ `: J4 I
        // FDS2 ^/ K3 {2 g/ W3 `
        if( exsound_select & 0x04 ) {
, \' S" q1 {3 u  M                fds.SaveState( p );
' A0 V4 F, L* ?                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ u: H2 I1 y- Z# Q: l" z& M9 K1 m1 o, q        }
: ~4 j  Q. c* k" M7 q        // MMC5
5 \# p; d. {6 o$ J        if( exsound_select & 0x08 ) {
2 T& ^& ?  ^; G- ^9 J6 u                mmc5.SaveState( p );
6 [- I: r7 j2 Y' B' I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' @7 o2 B  ^. x- K9 @+ m  s1 L$ A
        }# C- {3 ]' S+ q
        // N106
/ f2 [5 S! H7 Y7 C5 Y5 C        if( exsound_select & 0x10 ) {
1 f( G6 {+ I8 y) W                n106.SaveState( p );5 J/ |; z' `* P: ~2 m: ~
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: {( f3 D$ W, j; m: n        }) B1 b! R- `! E& q9 c) K
        // FME7
+ ?$ L- i8 j2 F5 s        if( exsound_select & 0x20 ) {- x' [0 C0 d0 ]& I4 k7 h1 J, ~
                fme7.SaveState( p );
6 [7 y+ {; {4 G3 A                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 v7 q: k4 w( G0 Y$ X
        }
$ r; @& W! y1 i6 _* s  ^! \  b' S! Q7 F3 }; g; v
#ifdef        _DEBUG4 Q5 Q+ W7 Y9 a# p" I
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );8 j; U' G* H0 E' m0 S
#endif
* S7 W, w. w5 [$ [4 o; r" v}
  B' W: C% G7 A; ]* C
# c! o5 l/ K8 T5 ]+ U- kvoid        APU::LoadState( LPBYTE p )
: {9 B! J1 B" q, Q' c$ c1 q' T4 s{2 A4 ]8 R; N+ O) P0 N! S
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% b* v6 M. a# K; ?1 ]* T        QueueClear();
2 y% S6 U# K7 _) O' c* g1 }0 l" o% [* Z
        internal.LoadState( p );
2 w$ L$ `3 A4 j$ b2 c% i( Z9 G9 b        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 i6 Q9 j9 o6 s7 h; {) y1 m
  m7 W% \9 y  \        // VRC6: F3 h# z2 q5 O" B, S/ ~1 Z5 p
        if( exsound_select & 0x01 ) {
4 x8 q5 a1 J4 g8 L! u                vrc6.LoadState( p );
' l8 y6 A4 N7 [5 ]$ y                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, y" v/ |! P- N        }6 }/ [/ w# d0 q8 S. U
        // VRC7 (not support)8 v. ~2 X6 ^* v, S  V  t6 V
        if( exsound_select & 0x02 ) {
1 X  y( C2 A) x$ Y" ?                vrc7.LoadState( p );8 V! N0 x* n# `; F. p$ E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- O8 A% ?3 s( P5 L7 _
        }/ k4 N6 @# A( o/ l" d" A( B
        // FDS3 _( m! \2 R8 }6 u; g4 t) `
        if( exsound_select & 0x04 ) {
( ^1 t8 \  i# [" d. ?) P5 ~                fds.LoadState( p );7 w  T7 \* i7 e
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 p3 S0 G5 w. D) u        }- E; ~( a$ }( X* ^) K! H, }
        // MMC5
( V6 o' @( w5 Q$ n; A0 s. J6 i        if( exsound_select & 0x08 ) {  F3 S5 X+ {* ]# ]/ D
                mmc5.LoadState( p );
7 M8 }' `! {1 }# E- W                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& l! [& Q8 a9 ^+ Q2 X1 M        }
$ f0 l8 N2 T" W) C        // N1063 s4 z: f# U  J6 K- g
        if( exsound_select & 0x10 ) {# g# O. j5 c$ a! _. `) R6 z
                n106.LoadState( p );' K: c' H% ^9 A
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 h9 E3 c! }: [! Q' C% x        }
. j* m. I8 W$ l: d; m" e% t( D        // FME7) U7 L1 {  y0 G% Z1 r
        if( exsound_select & 0x20 ) {, |* ^* u% R9 e' V
                fme7.LoadState( p );
$ k- \) f: ~% c5 y0 l& m                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- j7 `3 Q( L( A) q$ r        }
4 O4 H# n. M5 v+ f# X( P}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& _7 K: }% ^/ i5 e7 h. u1 \可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- `  l. s3 H. \
感激不尽~~
  K9 X$ D, X8 v) x' P1 q
恩 我對模擬器不是很有研究,5 W# h: D" B8 r' P: y
雖然要了解源碼內容,可能不是很困難,$ [8 H- ~  b7 Y. d0 E
不過還是要花時間,個人目前蠻忙碌的。
: y) X. ]/ `; m2 w5 p- ~0 o& n) s0 [3 L( Y# X" b
給你一個朋友的MSN,你可以跟他討論看看,
' ?) B- `( B$ k- `2 I0 p0 Y他本身是程式設計師,也對FC模擬器很有興趣。
5 ?( M+ g3 N7 @8 h# d3 C, c7 E( R6 G9 N8 a7 U0 V) `
MSN我就PM到你的信箱了。
+ s) ?9 U: p! ]: H4 O, Z! M9 ~# E
# c! a, z, I4 W' C# s希望你能有所得。

该用户从未签到

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

签到天数: 80 天

[LV.6]常住居民II

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

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
! \8 E0 ~; ~5 ~! D' l6 `呵…… 谢过团长大人~~

8 D" x* W6 u* Z# Q3 r7 i! c) I4 m5 ^. d4 B& }1 H
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
" q( Y4 V+ x% W团长的朋友都是神,那团长就是神的boss。
" }) H5 K% f6 L* V: h$ ~" p3 b+ x
哈 不敢當,我只是個平凡人,0 g' E  k( D( h. D9 L7 j
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
* ]/ s3 e$ Q$ O% HZYH
6 g* w# |9 D" tQQ:414734306
2 n/ T: f$ H4 }% S0 kMail:zyh-01@126.com! d# H) s: `" K3 {" }( n$ K) W
# D1 S( p" S9 u2 ~) [( z( f
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 6 y1 d1 S) h4 _; Y+ N  K
再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 a  k5 u0 d/ L5 {
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-5 13:29 , Processed in 1.103515 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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