EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) `0 f2 q6 H4 Q+ W) K; ]楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
4 @: s2 a' X8 Z1 q  `' W这里有相应的模拟器源码,就当送给大侠了~~1 v  U7 R0 ?  e* K
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 8 c, D  A9 J5 h
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. e5 \- c1 r/ `. R* M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, O& ^- r8 T! h) i$ z  b; I+ H这里有相应的模拟器源码,就当送给大侠 ...
' C& p+ }. F% @2 w# H1 U% f* m
聲音部分(Audoi Process Unit = APU):
2 M1 P! |% g3 |4 t4 J3 E* z9 i.\NES\APU.cpp6 z0 k. ]( [& N
.\NES\APU.h' w! C+ \/ H4 e% j0 [  A. W

# V1 ^5 \4 G- z% P1 G& T& ]6 U3 F; k
/ Y  ]( d2 x( B- @7 ~/ q+ ?影像處理部份(Picture Processing Unit = PPU):
7 ~) _+ o* _+ U4 R3 G+ J.\NES\PPU.cpp
4 N' I: I+ R* z$ G.\NES\PPU.h" w$ s! q5 J" n8 v  l* o
6 @' ~% r+ [8 X  l# f0 B& w- B" r
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
/ Z: ^% a; P; \(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 e; p0 i& g2 H$ R  f4 C
//////////////////////////////////////////////////////////////////////////" M4 A. n: J1 V3 i. Q
//                                                                      //8 {$ r0 E5 Y& I+ J) q2 r
//      NES APU core                                                    //
2 y# O. t8 w2 {1 a1 ~. `% Q//                                                           Norix      //
, l7 v& @9 J3 d! {; |8 @//                                               written     2002/06/27 //
8 H- j. ^4 U0 L' X2 e% j2 @) \//                                               last modify ----/--/-- //4 I6 t6 `% H: h3 ~; A8 |3 B
//////////////////////////////////////////////////////////////////////////
! |0 a% u( T* ]2 G: J: b6 V#include "DebugOut.h"( r0 t# `0 S) }& w+ N
#include "App.h"
9 J6 a0 f- L1 j" U% @6 {. s#include "Config.h"8 \5 N, X; e6 ?

1 p! }! N# S* e- s/ l8 x#include "nes.h"
8 t. k4 H- q/ d5 q  \#include "mmu.h"% w1 Z$ ^% M( Y. q5 n
#include "cpu.h"8 V+ x" R: E  j* a
#include "ppu.h"( C# K: @- e) X% |0 h
#include "rom.h"2 O* k. }# S. k2 v
#include "apu.h"
8 D# {0 j% C/ h7 [6 w& f
6 q: L: T; o: [- A; j// Volume adjust' I) J& y3 I  Q7 A1 I- {0 ^- t6 [
// Internal sounds
% o- Q! u0 X- y* C#define        RECTANGLE_VOL        (0x0F0)
/ T9 R+ k" f  `9 f/ ~; r* V8 b#define        TRIANGLE_VOL        (0x130)
5 P, a3 H$ S; Z) v2 B. l! V# K& b#define        NOISE_VOL        (0x0C0)$ c. a! v$ q2 \4 `# ~0 B
#define        DPCM_VOL        (0x0F0): C1 N6 W& W: o4 r# V/ i7 n* K2 _9 D
// Extra sounds
* ~- K$ p- \! h- L$ n0 C3 Y#define        VRC6_VOL        (0x0F0)
" }2 b1 o) b1 D: K# a7 d5 z#define        VRC7_VOL        (0x130)
# }0 o! ^4 _" s' g- O5 h#define        FDS_VOL                (0x0F0)/ K- u. p( d1 e1 }' H% e3 ]
#define        MMC5_VOL        (0x0F0)
  ^9 B/ F! l! y0 c#define        N106_VOL        (0x088)
: u0 `7 @" q4 H1 o#define        FME7_VOL        (0x130)
$ |% @5 c5 L4 o- }# [' U  R- Q. X  m! }3 C. e1 I
APU::APU( NES* parent )3 Z* W1 I% L6 c
{
; v  \" P/ a' b3 A        exsound_select = 0;; t- J, t, `0 {
' [+ K, I) O8 t6 Y
        nes = parent;) @7 f& m: M* r1 \
        internal.SetParent( parent );
5 I4 u$ h6 T' p7 ^' ~, \
5 A4 ?* d! l, `# z+ I) i, f: F6 m        last_data = last_diff = 0;0 ~) y& O* c3 F; B

1 J) i5 w$ R# F& J+ T3 h        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
6 L! y( B" N+ G+ E+ r; Q
! F, P) L' I9 e        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ O2 S" w0 U0 m" U2 |
        ZEROMEMORY( &queue, sizeof(queue) );3 Q7 W4 f. r. Z; X9 z, v; @5 _) Q/ }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. r& E/ z0 @5 K# n8 |
9 a/ e0 a/ _$ p9 E
        for( INT i = 0; i < 16; i++ ) {
! d$ N( [. P) _' `' }8 N; m" j                m_bMute = TRUE;
- U/ S2 o5 v. q; b: y2 u" h) [        }! z3 U7 G6 d* m+ B' Y8 ?: e1 c9 o
}
. E- x% Y3 x5 Z5 q% Y
1 [( J, A1 _1 Q5 F+ TAPU::~APU()0 H- o0 D$ H) U2 ]
{1 k% m* Y, h& \7 O+ v
}
; W9 D( J- c+ u  ~% Y( Q
* N( p& _1 z7 W* q0 }) R2 kvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 i6 A7 i/ i4 |1 _$ B5 C
{
0 \, e) ^2 e8 X$ m) O        queue.data[queue.wrptr].time = writetime;  `, h( S/ J- _
        queue.data[queue.wrptr].addr = addr;
% F1 B9 `" T: l+ j, M        queue.data[queue.wrptr].data = data;2 m, r7 d/ j) x0 |6 k2 Z+ I
        queue.wrptr++;
$ Q3 B% c/ @1 i+ I! T        queue.wrptr&=QUEUE_LENGTH-1;
1 Z* `# S; e3 w. K        if( queue.wrptr == queue.rdptr ) {
/ k& h# `" X6 Z) i                DEBUGOUT( "queue overflow.\n" );( L& K) b7 ]9 D8 j9 X. i  X
        }9 V8 l8 N0 G4 U+ x7 \( B3 P0 [
}
8 @8 n2 a% Z! {8 e: C1 m8 {6 P. U% |9 [! X: p, ^; Y9 @
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ E' _. R- t5 c2 K
{! M6 d  G! A5 _, d! k
        if( queue.wrptr == queue.rdptr ) {
0 n* Q8 @6 L7 Q2 @8 q5 P9 g! r1 @                return        FALSE;
, w! ^2 i# M' l        }5 k) ?3 a4 R! h9 x% Z* j3 Z
        if( queue.data[queue.rdptr].time <= writetime ) {: [, j# _/ h; E6 y8 s
                ret = queue.data[queue.rdptr];
4 ^  {* W# Y9 a4 m/ f  T                queue.rdptr++;
  b: w% j- t- X8 N: q# B                queue.rdptr&=QUEUE_LENGTH-1;
7 ]5 K7 f+ |- _$ j: h, H                return        TRUE;
- m( H: u( L) V: X  ^/ _' F        }
7 X2 ]4 _! e0 ], S8 }/ a        return        FALSE;8 _' o- x1 C# t- E% ~$ U2 C7 Q* _
}
# l% l4 M. v! Z
/ g) K/ T& `- R0 d, }/ |# Hvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )5 w) K# k' M+ V- R! g! Y
{5 P1 F, _" [& _& U' m
        exqueue.data[exqueue.wrptr].time = writetime;" A' R1 z3 F$ d/ p% ]2 ^
        exqueue.data[exqueue.wrptr].addr = addr;
' ~6 }0 m2 H0 M8 x) e        exqueue.data[exqueue.wrptr].data = data;. ?( A* H) [* P# c7 |( f- z+ b
        exqueue.wrptr++;
: G7 M% V& n% q1 E" M& G        exqueue.wrptr&=QUEUE_LENGTH-1;
- X* e6 Q. Q$ Z3 z4 _! Y2 p& D        if( exqueue.wrptr == exqueue.rdptr ) {$ Y3 M' t4 O5 F7 m8 J! D
                DEBUGOUT( "exqueue overflow.\n" );
7 k6 f. z: q* r# e/ I( l0 C        }7 J5 J. t7 _+ E! F3 `
}
$ S2 r' @- ]/ C4 x% }: F) w! G* g5 ?1 _8 H
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
: Z9 J' m: [" I- v7 N{! H$ G8 `  z; N' h5 |
        if( exqueue.wrptr == exqueue.rdptr ) {* q* e, e' O9 J5 J( |: e# d4 H
                return        FALSE;1 U* F4 }1 {3 j4 Q
        }
" y3 n; V9 j; c# G2 l& g% m        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
4 x) O8 V1 T7 _- s- Z4 f9 y* W                ret = exqueue.data[exqueue.rdptr];. Y1 E4 T' B. t4 {2 g0 Y) z
                exqueue.rdptr++;
# E. d$ F  @2 n1 h0 ]- J                exqueue.rdptr&=QUEUE_LENGTH-1;
. f8 h; A7 `4 s% D. e4 _                return        TRUE;
) d, M2 h4 w% G2 L" I+ A5 z) f        }
4 o1 t) i! F6 i( @0 e& n& P' C        return        FALSE;, F$ g  ]' [: b4 E7 ?( J$ r
}
. @) G( E' ^0 o2 o% o
& V- T* k+ y6 F% L% Ivoid        APU::QueueClear()
+ S) q! a; s6 b: R& t{# W. _" o2 y+ o; N3 [6 G
        ZEROMEMORY( &queue, sizeof(queue) );! W2 U* W% j1 Q- \
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  m. w) m( e" u) t1 y) ]
}
6 A6 h3 ]; Y; V/ q4 X6 n# {( a& _# h$ l: B! Q; x3 j! {
void        APU::QueueFlush()
8 M8 d. r1 D6 P) @{
  T7 ?; Y! S( t+ A- k7 k        while( queue.wrptr != queue.rdptr ) {
% Y1 g7 i" p3 n  T; A                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
) ^- ]) k" `7 L                queue.rdptr++;7 @; h+ a5 h7 P) O  [$ K
                queue.rdptr&=QUEUE_LENGTH-1;
  g0 I3 E# b0 e        }
3 `. |* ~, {8 V+ G  r) e- [, C) y( p. E% G6 A: _
        while( exqueue.wrptr != exqueue.rdptr ) {
+ S' s/ n( @) O8 ^/ p; Q5 _7 Z2 H5 O                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 G$ L, K" f4 O1 z+ C                exqueue.rdptr++;3 L2 J2 Z" n8 i( y5 E7 t
                exqueue.rdptr&=QUEUE_LENGTH-1;. \' z" Y$ C1 J! A7 T
        }6 i( O( z3 ?. t( S" }/ P! m6 L
}
. N/ s0 n! t7 l( w5 g/ V7 ^" R) p  |" H4 F: W- t: D
void        APU::SoundSetup()& x" c# |' E7 ^! G. n2 d
{
2 D$ [1 b  x2 x! _        FLOAT        fClock = nes->nescfg->CpuClock;
+ L/ t) k( v3 |0 }! Z, [6 x( s        INT        nRate = (INT)Config.sound.nRate;
& v& E8 D8 i( f5 u' R' S        internal.Setup( fClock, nRate );
$ n7 S* F# S! Z8 f; g# y        vrc6.Setup( fClock, nRate );" E9 H( b1 M& r8 C7 P
        vrc7.Setup( fClock, nRate );
9 U- ^# X* N6 h6 `9 V        mmc5.Setup( fClock, nRate );8 d( ~8 Z$ S1 Q( S$ }6 Y
        fds.Setup ( fClock, nRate );
6 P0 V% x8 a. x) w1 |% Z        n106.Setup( fClock, nRate );  y: S; Q3 a: D- [; C; G. Y
        fme7.Setup( fClock, nRate );) l5 l5 E1 N" ~* W
}
' e' o6 J  k! H; g6 Z4 a
( T% `! Z' p& w" p/ Kvoid        APU::Reset()
0 q6 W/ D# s2 g& z# Y. Y" C{
6 b1 P* m. I7 K. R8 K& \        ZEROMEMORY( &queue, sizeof(queue) );
9 Z. k5 `) ~8 ^% U0 u! W        ZEROMEMORY( &exqueue, sizeof(exqueue) );* W9 Q$ A2 @, I7 {+ H6 ?& |( [

* L% v& k0 o5 d8 D        elapsed_time = 0;5 |* \/ `: g/ c9 }
  s6 j& m/ P9 b
        FLOAT        fClock = nes->nescfg->CpuClock;& N1 E& l4 f* x1 {
        INT        nRate = (INT)Config.sound.nRate;$ Z; T8 O0 G* }" F1 y
        internal.Reset( fClock, nRate );% V9 _/ C+ V6 |
        vrc6.Reset( fClock, nRate );3 [& d" F% ~/ M: d- ^
        vrc7.Reset( fClock, nRate );( n: ]0 H2 f" g# `0 L
        mmc5.Reset( fClock, nRate );
+ _5 z1 ?$ Y" N        fds.Reset ( fClock, nRate );
* w1 W2 O2 G4 [        n106.Reset( fClock, nRate );& r; P; j& P4 w
        fme7.Reset( fClock, nRate );# c) }3 A/ ]2 i( v. F1 T
% H' x5 L% r- d: S0 d: ~
        SoundSetup();
  U% l; M- @4 x! h9 W  D+ }}9 O3 b* z$ ~+ M* P6 F

# w: x9 y  N' Bvoid        APU::SelectExSound( BYTE data )
9 [& Y/ p0 G( w, V  F( k" o. K1 @{! H$ i8 U3 r+ C! J0 P/ q' n: R
        exsound_select = data;
' K3 g) {9 Z: s- v" n, x% M. S$ a}
: ^. O9 @, C  `: X3 f/ O% I* A: J8 z
BYTE        APU::Read( WORD addr )6 [' s1 n$ I1 I+ Y6 `
{
9 H4 ^$ T/ ]' B. {: Y% z        return        internal.SyncRead( addr );8 ?- a- f+ Z3 l2 X
}
. L, o) S2 s# G4 L$ y
/ [$ c6 s1 |/ i- Y" r2 W' mvoid        APU::Write( WORD addr, BYTE data )
! ]- [& u+ t' t8 g% `0 E{# W* k, S; n! A$ o1 J. ]
        // $4018偼VirtuaNES屌桳億乕僩8 u8 R, ^/ l7 @% g8 C2 e9 ]1 t
        if( addr >= 0x4000 && addr <= 0x401F ) {
. I; }. e' h' n. ~& `                internal.SyncWrite( addr, data );4 N/ A- ?& q0 l, h1 y- G
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
. H) R- B! X3 `        }! F3 b9 L: t$ {
}
# Q9 l0 L+ h! k  I5 d& H3 a& g4 G0 |$ A: F8 X2 {8 _
BYTE        APU::ExRead( WORD addr )3 Y! s5 [9 g/ x+ B" p% [
{+ R; Q* V1 k% E/ Z
BYTE        data = 0;
( Q9 a0 ^2 u( T. c! e6 W6 z/ h- R+ J/ c0 @
        if( exsound_select & 0x10 ) {# x4 F0 W/ Z7 d: R, X6 f
                if( addr == 0x4800 ) {
& O& Q- G, T# p6 p+ }) n9 o1 T8 C                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& S) n5 S2 V/ A- Y7 x
                }
1 [4 i' {: x$ _; I        }6 _9 R4 o$ }  B4 ]
        if( exsound_select & 0x04 ) {6 m5 R  W% l" @( ]1 o2 w1 \- @5 r+ N
                if( addr >= 0x4040 && addr < 0x4100 ) {
4 N4 k. ?: x. G4 Y: C. a. K# m                        data = fds.SyncRead( addr );! z! ]# o2 h2 |1 }- n( F6 x0 l
                }
0 M& q. P1 f& i$ V, }5 b        }
8 |6 d& A/ q8 x        if( exsound_select & 0x08 ) {
, \& Y3 {6 w/ h* N1 I- A                if( addr >= 0x5000 && addr <= 0x5015 ) {
; K+ g% E* \# y5 }9 U1 _                        data = mmc5.SyncRead( addr );
& C, G4 t/ h3 `                }0 w! F9 {- L! D  U! X
        }9 X' o9 d5 @+ t
4 I7 @5 O0 W: V) x
        return        data;
6 F' W7 Q0 O' K/ \: f- i" }}5 r# u% Z; {/ g- [+ S

: C! ]5 D* `% ]- K8 @" D6 `, fvoid        APU::ExWrite( WORD addr, BYTE data )7 H: q/ m7 R( N0 z
{
9 ]7 `2 Z* E( B4 u4 e: T8 l, E( }        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
! J& ?" `  J2 d; s
0 }; O2 p& S1 Y6 I6 D+ ], F! T        if( exsound_select & 0x04 ) {' E6 O8 y2 W! @* l. X
                if( addr >= 0x4040 && addr < 0x4100 ) {1 @+ \4 B+ Y/ N3 p& r
                        fds.SyncWrite( addr, data );
1 e. ?& I' i; k1 |% `+ [/ n, j7 F                }
# H4 D+ z* ]4 P* c3 e7 x, [% J        }8 u  [; @1 Q  C0 D
5 }3 Y6 e9 y' o0 s
        if( exsound_select & 0x08 ) {
- M& F3 _6 Z9 u4 x2 M- m                if( addr >= 0x5000 && addr <= 0x5015 ) {4 D8 d+ I( [( C; Z5 I, n* R& W
                        mmc5.SyncWrite( addr, data );
, H* F2 ?# K$ g9 W! [) F/ y; Y4 y                }  p, Q9 J( K5 W& N: K# y
        }+ I2 @. z7 O, {/ b; `# P7 e
}3 H+ P$ \5 e& w7 H7 ^

7 X  |2 _# o( F$ a1 b; G/ `, a7 evoid        APU::Sync()
! v8 a, V$ K  L9 s9 a5 t{
" a( \8 @( i3 d& N. u; C! L5 f& ?0 w  V}. _) R8 b, D- b2 y* T
2 ^# F* f. q( E' p. O) N& K' g# U4 I
void        APU::SyncDPCM( INT cycles )
$ A2 I6 R4 f+ z; v+ _8 P{5 L$ i+ {5 `8 U7 i9 N$ j3 w
        internal.Sync( cycles );
1 U9 J1 U0 P3 q; _
0 ]# H% g7 i; d5 o  L8 y8 q        if( exsound_select & 0x04 ) {& H" e1 y6 J. N
                fds.Sync( cycles );
& X3 y' B% p2 S( }        }! n+ a4 Z' {  C. ?
        if( exsound_select & 0x08 ) {
$ F" I' a6 j6 g                mmc5.Sync( cycles );, u8 ^4 X9 ^+ y' ?$ F
        }% Y. |9 ?1 v  C6 ?! f
}
/ U- U9 e' e4 P- p1 ^9 Z8 b' ]! k: p5 }: Y3 U
void        APU::WriteProcess( WORD addr, BYTE data )
6 Z# }+ [3 E0 `. h0 Z! R{2 I3 d0 j1 h& N
        // $4018偼VirtuaNES屌桳億乕僩: r9 W9 p1 z+ E6 O* d
        if( addr >= 0x4000 && addr <= 0x401F ) {' I% g, e; P5 o5 \& t$ ?
                internal.Write( addr, data );
% h7 U% l9 Z6 E$ V# I0 ]) r        }
1 m% p: c* D2 t! N) k  q1 J}
& _2 _) c8 x- J0 M5 D2 P6 f9 P3 n! m: n: ~( w1 m' _
void        APU::WriteExProcess( WORD addr, BYTE data )4 }5 @7 E% W* [* z( q; `
{4 @8 t( F9 T8 L0 b
        if( exsound_select & 0x01 ) {, O. @; v$ ?, v# q4 i3 x  h
                vrc6.Write( addr, data );
3 \0 {/ n9 ]" P) }7 x  l% P        }
8 y+ A! @, ?' f5 t# ]! h9 q        if( exsound_select & 0x02 ) {
$ e4 j! b3 R3 i/ V! d                vrc7.Write( addr, data );, Q; [$ f6 R& t2 H2 \
        }
1 |7 s( u' k  _3 O) c: q+ O1 t        if( exsound_select & 0x04 ) {6 S- d* H  w0 m: g/ m; ~
                fds.Write( addr, data );
0 _2 S) [7 i% j9 n; a' b% U- ^        }
. U0 [7 D& ?6 b* q3 o6 T        if( exsound_select & 0x08 ) {( e0 g$ X8 [0 ?* @7 y" Y. ^& \
                mmc5.Write( addr, data );
; N3 ]* n" Z& s2 p& H/ \        }3 u5 w# t, V" Z+ v2 n
        if( exsound_select & 0x10 ) {
- @" q* ]" f" ~& r9 l4 n  ]                if( addr == 0x0000 ) {+ [- o% h9 \2 h% G9 J8 C
                        BYTE        dummy = n106.Read( addr );7 U. M9 Y( I* A! |# Q
                } else {
9 P5 u1 Z! \, ^                        n106.Write( addr, data );
: o+ C: W& P1 j- I; |0 X& C; n# v                }
3 g, q$ E7 J( E* t2 s        }
) ~+ i2 W0 p. |! H1 k6 n; E2 A, f        if( exsound_select & 0x20 ) {( _' Y: J, C6 ^5 m
                fme7.Write( addr, data );4 D1 [# V; ]8 o( J
        }& P# d) e+ f0 O, K5 o0 @! o2 g
}* d* C/ K: {( H* C' H; r( i
# o: h" o: x% `4 G/ o- m) d) J
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ s) \2 d/ H, B' i9 l  B{
* y( Q" o1 \2 }. |5 K5 XINT        nBits = Config.sound.nBits;- r# c! }1 ?6 T8 L! n
DWORD        dwLength = dwSize / (nBits/8);
1 r. d6 C) a; }! @* d0 bINT        output;
9 ?3 X  q) f1 F" v- Q3 X; rQUEUEDATA q;/ N1 r$ g; x# i3 J% ]! p
DWORD        writetime;; ]/ x, W8 Y8 b. a% {

" {6 Q# c. D' W5 F, P4 k& _! NLPSHORT        pSoundBuf = m_SoundBuffer;
( f2 M2 o. [* i' X! J4 v9 zINT        nCcount = 0;
" j( \- D( D% G9 I/ u8 g8 y! M% H2 o! q4 w9 \' p% `$ `3 @
INT        nFilterType = Config.sound.nFilterType;
" G" ^, h2 t: K7 W& T- v* M: G  H2 E+ _( U4 A
        if( !Config.sound.bEnable ) {
7 H, i& m& F1 B                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, \8 T1 M$ L6 _8 c                return;
9 I" ~, `- V; b        }' c* B0 R# C3 e0 g1 i2 K
* e8 c( [; g- N2 K
        // Volume setup
7 L* l5 e. E) J9 n' a8 w3 B        //  0:Master
8 l9 `  o4 l0 x2 |6 C+ O        //  1:Rectangle 1
1 s1 i8 X% s2 m# [9 v        //  2:Rectangle 2" H. J; u3 e+ }
        //  3:Triangle
  i$ G# t  e1 Q$ t        //  4:Noise
& g; F  v$ O, ~. [- r        //  5:DPCM
% \5 I. Q- l+ y1 r/ e        //  6:VRC6* A& V4 T* S- r9 F
        //  7:VRC7
8 M% I! ]( y7 L7 }0 o* ?        //  8:FDS
- \4 B: b# f! U4 J        //  9:MMC5
# e, d9 R+ k# S" k        // 10:N106
! e6 ^+ b4 Q9 k# r  X5 ^        // 11:FME7$ ?+ P4 D& y3 T5 ^' z4 r7 Y
        INT        vol[24];) g# |8 a% Z0 w( O
        BOOL*        bMute = m_bMute;+ J7 P' N7 j' i5 @$ t
        SHORT*        nVolume = Config.sound.nVolume;9 H! w# y- d' F* b# `/ J
# g; \- w' |0 g9 P6 H" {$ C
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
  {1 ]* Z6 m" U0 D* }( I
, ?+ A% Q& \$ `3 k; Q. L        // Internal
4 x9 D+ L% ~/ R" W7 n        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;+ D/ f# h$ o4 D' H0 ]! L& T
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# \8 Z! [0 r# H8 A( q8 A! t" T        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
  t% ~8 ?1 N8 v- o# H0 g0 E        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: f0 Y( i0 R+ Z5 x        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. n" H. N. F+ D) q
2 {' \' q/ F, d3 x( @' V        // VRC68 K, X* ^) ], K" l% b& y
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 k6 ^  y- g! z        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ W0 r  c; M$ @) w) y' M        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ c! N' ~! \9 o0 {1 o
2 D" r. E0 Y1 [8 k        // VRC7
- Q4 y1 c; I  U, M        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, X7 b) ]$ ?$ v7 a( w
# D- q5 ?" t5 t# m! i        // FDS6 Q( d1 t1 h. d# w7 w: M; y( N+ H8 }
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;0 V' s! }, h% y) A6 O

$ l: `( o# T) @# o        // MMC5* U/ s! `) s$ k& ]2 a; j$ L
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  R/ }/ @2 k" A: W/ R/ B
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: U% \; r# P' U
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 k0 \& k9 ~5 c6 N. B. |" v
1 N, _" t, [( q( x! l& d        // N106  O, J8 |  a. I1 Z
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  L" y/ A! z6 t) O, J! P& O
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ f" `: ?& J; H: _. V, v; _
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! N0 y, t5 e* ^$ c  E  U
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 x5 a( |0 M; ?0 F- A3 a6 B9 A
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  E  _2 E! g7 ^& w3 j6 i. P7 ~/ T        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 c- r- I2 U, H$ `3 l        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! O- ?- Y7 [) A
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* W* R" J$ t7 |  S* m

+ s, p" v& f- J, {4 V        // FME7
: b$ v, G* C2 p        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ `- @$ y& [/ u$ _' w! Z        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 |; |, h$ k3 U9 e/ p  W        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! N! Q7 R# y' U8 }

) ]' @" Q2 x# C: a//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
0 n+ p2 |# W2 D' y6 @' I        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
% t2 b9 `# u9 c- F1 y; U4 ^4 s- d" o6 }& ]/ G$ V$ D5 x
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' }& L! h$ Y2 ^7 L        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
. ~- N8 U4 @* [+ L0 L                QueueFlush();
) l- @) ^; |! N- V8 t- O        }
- k) G7 N5 ?& \7 [3 W6 W$ N2 ^9 J( V# W; [( Z* [( z( \  E
        while( dwLength-- ) {/ E& |  |/ p: d* |( z
                writetime = (DWORD)elapsed_time;
+ L: `9 |4 R  Q: n+ i( J5 T% Z& z" t
* H* P2 r0 a0 X; Z8 f                while( GetQueue( writetime, q ) ) {, C; g2 M4 `, J& m
                        WriteProcess( q.addr, q.data );
0 [# \- W5 W. B. {7 _                }1 @; t. {- w* ]! _

  N4 ~4 k7 I8 ?+ u( g& X                while( GetExQueue( writetime, q ) ) {' e0 y' V0 m' P8 r- ^: j
                        WriteExProcess( q.addr, q.data );
& P! u7 Y0 k/ j+ p& W% a9 [* ?! s                }& R4 A# e. s- o. x$ T7 w. C9 W
2 @0 e5 |8 Z' |4 ]
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 d0 Y  o1 {: W. b, D; I/ H; T                output = 0;" N5 _  w" ?  T7 P" P( @$ T1 g5 w
                output += internal.Process( 0 )*vol[0];
0 G6 b6 A, o5 R$ g# ^& b; @                output += internal.Process( 1 )*vol[1];
6 h7 U. Q- ?% F1 e/ R$ Q' Y                output += internal.Process( 2 )*vol[2];
8 e# W  I0 S; [7 p                output += internal.Process( 3 )*vol[3];$ ~( L% Q. K0 s6 |6 ~
                output += internal.Process( 4 )*vol[4];8 Y* [" h4 F( V9 P8 i2 T

  @$ D; ?; J- E/ i6 p7 u                if( exsound_select & 0x01 ) {
) D1 y. c8 K, W8 f( X% U# e) N! d                        output += vrc6.Process( 0 )*vol[5];
; p! L  x! \8 h/ [, x% m                        output += vrc6.Process( 1 )*vol[6];$ p% ?8 }- C  A- l) q+ M
                        output += vrc6.Process( 2 )*vol[7];
& a; Q: h# f( w/ |                }
0 T! x4 H2 Q' i3 v! E! z7 y                if( exsound_select & 0x02 ) {
8 t( d3 A5 |6 C7 [                        output += vrc7.Process( 0 )*vol[8];& F: d2 k, b1 `: Q
                }
) @! Q, i, `2 N! {! q2 o7 a& Z2 P                if( exsound_select & 0x04 ) {
0 b3 P/ d1 E5 t* o. h! h* Q                        output += fds.Process( 0 )*vol[9];
  p7 J$ n: R* o% F. X+ B                }
0 w* M3 G3 b4 o; d" i, n                if( exsound_select & 0x08 ) {
3 o" K, Y% Q2 D- t5 Y                        output += mmc5.Process( 0 )*vol[10];
+ I) H0 @- i1 j$ i' b  u$ \$ B% t# ~                        output += mmc5.Process( 1 )*vol[11];
' t) Q, i( G9 X) H, H" B$ Q/ x# y                        output += mmc5.Process( 2 )*vol[12];
2 z- o( G7 P& N3 z  u                }
4 v. y; o1 O# F& A/ o1 J                if( exsound_select & 0x10 ) {
# R& C; W7 a9 x- q                        output += n106.Process( 0 )*vol[13];
: L( X+ V2 S# \9 J                        output += n106.Process( 1 )*vol[14];
- N' q- N+ W4 z, I' ^0 K& D9 i0 \                        output += n106.Process( 2 )*vol[15];1 \0 N* \$ r: Y- F) O9 y
                        output += n106.Process( 3 )*vol[16];5 D1 Q2 O) `8 o- y3 ~! Q" U, Y- Z
                        output += n106.Process( 4 )*vol[17];, |4 s7 [  O  Z  z6 q9 g; E
                        output += n106.Process( 5 )*vol[18];: t$ r) D& d; j  l
                        output += n106.Process( 6 )*vol[19];' Q) s' S# I0 t) K
                        output += n106.Process( 7 )*vol[20];# @1 T, c( U. n$ z7 w% W
                }
5 V# s! j. b2 _                if( exsound_select & 0x20 ) {
8 Z$ A. V6 B* f, z                        fme7.Process( 3 );        // Envelope & Noise
' M3 M) x  U. ?! _4 C" @. p                        output += fme7.Process( 0 )*vol[21];
9 D8 [0 A% c' g: v                        output += fme7.Process( 1 )*vol[22];
9 {5 j7 E+ q: a3 u" r! q                        output += fme7.Process( 2 )*vol[23];% u8 N0 l3 Z5 N  v0 H
                }
& Y; u9 W& P& J$ ?7 A; o) H5 W- O4 C2 h2 O
                output >>= 8;7 P0 O$ d% O" p. e) P1 I

3 Z7 O2 z( w" w+ j7 Z3 D                if( nFilterType == 1 ) {
) v4 ]' w/ u- L) }# ~1 g3 f& o                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ d: H6 a  B3 a: l/ y) H) m2 c% \
                        output = (lowpass_filter[0]+output)/2;, u2 g' F; z! s5 D6 o
                        lowpass_filter[0] = output;
6 _6 t7 O$ N% P7 ?+ @+ i                } else if( nFilterType == 2 ) {
$ O; D# N0 C3 \( S7 [  |8 m$ j6 p, p                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
# `# P+ a+ p' j3 \2 O                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
3 [4 t9 ~% v( g8 r8 v0 i" k                        lowpass_filter[1] = lowpass_filter[0];
0 g5 s$ D7 _6 f; V$ H* l0 O& r                        lowpass_filter[0] = output;
4 l5 m3 _. g  g; }# w3 L3 f                } else if( nFilterType == 3 ) {# Y2 ?: s6 D* l
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ F- G  ?$ F  r0 C3 o  N# J6 |2 e0 @7 Q
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ @" U, ~1 c+ F+ d* d* ^6 r
                        lowpass_filter[2] = lowpass_filter[1];8 G1 _3 Y. b6 D4 @
                        lowpass_filter[1] = lowpass_filter[0];
+ d$ |, r+ z) n4 w7 P" ?                        lowpass_filter[0] = output;
+ {; b: ^" Q; s$ s5 }; J+ _! y                } else if( nFilterType == 4 ) {* q/ n$ ?2 [0 p( z- b
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 L: I/ m0 N( y9 x* }  b5 _$ H# Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( L7 ~; s1 W2 e1 h
                        lowpass_filter[1] = lowpass_filter[0];& |  S# a4 }% V' H; d
                        lowpass_filter[0] = output;; d5 }, p0 L* i) ^1 I: }* H
                }) G9 h) }& E- c: X2 U3 ~
% f4 x" b4 H5 v, R4 D
#if        0
/ F2 L9 s( n$ g+ h                // DC惉暘偺僇僢僩  D6 h2 _2 {1 I8 s/ W/ U4 P
                {
0 Z' V4 h" a; ~3 ?+ B8 M7 P- }  [7 m                static double ave = 0.0, max=0.0, min=0.0;
2 P3 G7 B8 e# {* ^- g                double delta;/ Z6 R% Q0 v+ G* \% Q9 c1 m
                delta = (max-min)/32768.0;
6 `% D. z' e2 A! X3 u' p( y: l                max -= delta;- P9 }7 d5 L! R2 Q8 `
                min += delta;
( t+ I8 ~/ r6 e                if( output > max ) max = output;$ P. P2 o. e1 m. I# E
                if( output < min ) min = output;9 p- t8 x+ j# Y; S  Z8 h
                ave -= ave/1024.0;9 _1 L. M3 \0 c$ W& e; V6 ~
                ave += (max+min)/2048.0;
  w5 R, j  M0 q" n' i" U# D                output -= (INT)ave;- @. T& P! A: `3 G( h! w& p
                }
# B) E. ?, V( G0 ?#endif$ o3 l! @( d0 A* d( K/ y0 z
#if        1! k( H6 u: g. f5 x; X8 i
                // DC惉暘偺僇僢僩(HPF TEST)7 f  a! J4 M! r) q+ s' W
                {
$ P( [5 V+ f0 G0 t  {' A7 Y//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& B0 L  N: O, w; [1 J                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 l; p  C0 m8 K' D0 p
                double        cutoff = cutofftemp/(double)Config.sound.nRate;$ t' M% m4 x5 L) \
                static        double        tmp = 0.0;
' Z: `" Q( d5 C                double        in, out;+ s7 V- F2 H: Q7 h/ `4 `, z

1 R) M8 u9 z$ ~7 ^9 [, \                in = (double)output;
5 ^" o' H3 K+ L# B8 f                out = (in - tmp);
- Y# G% j, A( ?5 I                tmp = tmp + cutoff * out;
: j& K; J* t0 w6 t/ t1 K' a% B3 g" B+ u  V) Y  C
                output = (INT)out;
+ m+ t' Q3 r; L, b1 q                }' U0 g! f* x8 f1 {4 h0 r; s
#endif& D; s2 B  f' Q" ?
#if        0
, t) {4 b- O/ ?4 }                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
! |* ~; ?% P$ K0 g                {
6 N( u8 w2 b; Z                INT        diff = abs(output-last_data);( M1 V" D; p  l, v: p! k6 _
                if( diff > 0x4000 ) {
) M) ]" \/ l$ s1 H: u                        output /= 4;7 n: [2 c* m* N/ W
                } else 2 }8 ^9 I1 @6 C2 j" V/ G
                if( diff > 0x3000 ) {
3 y! U' s7 |7 _& o; k) D+ @                        output /= 3;  T, S, c# q2 D$ _
                } else
) a5 ^$ H+ V; S' r                if( diff > 0x2000 ) {
( {& x0 P$ E6 \) z                        output /= 2;
$ `' |9 p, ^' x4 l8 j                }2 o$ M' e7 X3 {3 o) D
                last_data = output;% c2 d6 [) F/ o* G9 r4 X. q
                }& @: P9 _: j6 _& Z- P& Y
#endif
: E; u6 B  Y! v" [. @                // Limit# Q- \7 Q' j8 f! J
                if( output > 0x7FFF ) {
0 |0 Q6 H6 j. _$ a! |6 w                        output = 0x7FFF;, W6 i  {3 l1 k3 m- }8 H, Y" x
                } else if( output < -0x8000 ) {8 F- a) [6 Q4 x# V0 J; P# D
                        output = -0x8000;
" e* m6 X1 `$ m                }
$ R' j9 A: N# v% _* p; n( B, B6 p2 {8 |; t
                if( nBits != 8 ) {0 v+ q' b3 P, j# y
                        *(SHORT*)lpBuffer = (SHORT)output;
& ?8 e# y1 y: I1 o, O* f7 w: Q                        lpBuffer += sizeof(SHORT);( R/ l  O. `. C' a( [* s" ~
                } else {
+ P: @; t, k. P6 i8 T) _* \                        *lpBuffer++ = (output>>8)^0x80;% ~* ~3 Y6 ~  O( r
                }$ G: @* \& _) q' v- P" X

3 G5 L: c7 S' G                if( nCcount < 0x0100 )0 h% i+ s; @& P
                        pSoundBuf[nCcount++] = (SHORT)output;
/ ?' K6 H3 ]( @0 p. `0 b
9 E* n6 S6 d6 s0 h* M" j//                elapsedtime += cycle_rate;
2 S$ V: f+ u  c/ w  Q( E" R+ n                elapsed_time += cycle_rate;
* z( H+ ]0 e9 @& d0 z4 [        }
' T6 k4 V* L" g4 S! n4 e. g6 K4 l  w6 \, B7 I& D3 i
#if        18 F0 S# a* l2 {; q1 j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {( L) w, z6 i; v  X# J0 L* [( b
                elapsed_time = nes->cpu->GetTotalCycles();
+ S0 a- @4 {$ F# z/ N/ C: ?        }
4 B- T6 [6 Q5 S1 g. o; {0 W( H        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {% T7 f# [9 p- k2 l3 M
                elapsed_time = nes->cpu->GetTotalCycles();9 o- T; j6 S# [0 ~) Y
        }
. m  g3 j0 h8 I" W7 s9 r#else  g8 M6 U' t$ r, K0 w
        elapsed_time = nes->cpu->GetTotalCycles();- j0 Q+ I7 X, M
#endif/ z# a) n0 F# x0 S
}
- F5 F6 b! f) w/ f0 y4 c, U4 S8 E  r* X8 E* P2 z: J
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 G9 P5 g" ?, w) r' G4 ]9 pINT        APU::GetChannelFrequency( INT no )
6 \4 D7 H% p3 l- @4 j0 D{
; s7 [# W1 f8 @" C% U        if( !m_bMute[0] ): `" W  ?) k9 \6 a0 c
                return        0;
+ ~3 `. b6 v% P
5 Z8 Z, r& ]& @7 o7 h        // Internal6 Y3 }& g8 i& g, l7 l6 f/ `" v2 P$ U1 b
        if( no < 5 ) {
6 W/ X- p. U- \+ H( @  C7 \                return        m_bMute[no+1]?internal.GetFreq( no ):0;9 `" j$ J; F% H& M) I$ K
        }
: Y3 m/ N1 q& h0 ?% f/ _        // VRC6, Z( d% x( L6 j' m( }
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {8 e0 |7 b6 \8 h8 A; \
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
, o5 W2 E$ `& A0 e        }
4 s% {6 }/ b( c        // FDS
) l7 o( o( Z3 c1 w+ [        if( (exsound_select & 0x04) && no == 0x300 ) {
4 q  P' g# L% p' `3 o                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 [# l" {. V4 X8 I; m        }
& n. l, T! r7 C4 z# ]1 U        // MMC5
. ]+ u$ z; m8 A2 a& S        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
1 i6 r) u- B! m1 q4 X& U                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: k- i  T- k+ [- ^, F& v        }
; p; ?" m6 c1 Z7 y2 H7 P        // N106
$ j  `8 q3 W& T2 O# s& F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
) k$ V6 C7 T/ u                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: {& \$ e, p2 a6 s, a! m. H
        }3 w/ f- E& U- M3 @7 Q( e! \2 }; w" H
        // FME7$ `4 J# \  d, m* ^& _1 f4 h0 R
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
+ T9 m9 z9 l5 k# I+ ~) I                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;6 A- B3 i1 @/ ]5 v4 }8 s) r7 N
        }
$ @/ m) ]; I* n        // VRC7
1 ]" F; [6 U/ I/ l        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 d. K3 y: `) ^! |+ k" S0 S                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;  \" u$ ~& ^" }9 C) O6 D
        }  p- u' y6 I, Q0 b; I' @# o: Y
        return        0;6 g5 ]- c. h7 m' I+ L
}
& F& j* s' W0 U7 x9 M) ^) u4 f; t* w* x! u2 n* v2 [" X
// State Save/Load
/ c* v% L0 A) z, @: `: evoid        APU::SaveState( LPBYTE p )
8 O" ?* I6 J( P: y0 b& i. j6 v{
  k9 G: p  P3 F8 B* D#ifdef        _DEBUG
' d/ B1 L0 Z% i7 eLPBYTE        pold = p;
: i- N/ ]: z: K% m- Q6 r#endif0 z9 l5 o: X3 A; g3 t' Q' Q' [6 g* v

* q) _6 [; J6 Q7 I. @  k$ s        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ ~0 \. A- M" G- g- f: j5 a
        QueueFlush();
7 y; R1 J! h% a# p2 D0 k" J. {+ A7 l0 C
        internal.SaveState( p );
" E# N/ I* _3 x" Q8 N2 v8 c$ f- v        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# D- x* e# W5 D# e  F' L7 w8 q, u! X' X
        // VRC68 H. Y1 p. X' G) N, }2 `
        if( exsound_select & 0x01 ) {
0 ?2 a1 Y% d) s/ _- z5 P                vrc6.SaveState( p );
# n6 f* H; w% X( z# D- Y; \                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( j( p/ I% g8 s: L: y+ B
        }7 i/ f0 F; m$ L8 L
        // VRC7 (not support)3 h$ l5 p* [- `2 ]/ _3 h( B* m
        if( exsound_select & 0x02 ) {
6 ]8 x& Z. W/ d& P  O/ M                vrc7.SaveState( p );
4 D9 `- R' {( Q# _$ R                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' ^) |. e4 t- o& P- [' @4 Q; s; s
        }
6 }. J4 ]. a# Y: F  q) c        // FDS& h2 Y7 L' y. i- ^9 Z, Y
        if( exsound_select & 0x04 ) {
% H- i( B3 O7 G; k! K9 {                fds.SaveState( p );+ Y+ K5 a9 f  |" ]
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& b; Q: ]6 J% D' V4 _( D        }4 }- o: m/ W" H' |% d! \
        // MMC5# Q2 G- A. ?+ O: I) z8 U5 i7 f
        if( exsound_select & 0x08 ) {) }& q2 Y. I/ m( _
                mmc5.SaveState( p );
& ~* k0 O3 G! T                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 E( k7 F+ L+ c# O  e2 X
        }6 Q# |* n) x* b  w' j# W; X7 B
        // N1061 S! T" H# q+ b) Y5 d4 W
        if( exsound_select & 0x10 ) {
6 c, n* F: m3 ^5 d% |! i                n106.SaveState( p );
! I( M9 r/ k9 s9 v- K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding" m9 a* Z  ^- ?
        }& a) |, J- a. a
        // FME74 ?2 ]; L1 _" D! \6 {+ e
        if( exsound_select & 0x20 ) {
8 q; D9 u0 l. y2 e8 m                fme7.SaveState( p );
! d* a$ M5 @, y0 @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' [' t9 y/ T  }% k7 j        }
; Q: A1 ]# U! V- e. m
; ?3 E* |- _+ r: K+ B8 [% q) T# Z#ifdef        _DEBUG
& J# k, Y7 S0 q% G) zDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );3 x1 V( N% H3 v* B( e& d: M
#endif/ Z  J2 ?8 r8 Y( K7 _% v
}  R3 G" _8 ^- q

+ e( V' e) @/ F* y0 V2 q1 l5 tvoid        APU::LoadState( LPBYTE p )2 X! t( @- l9 `) @
{
8 N4 f" y4 }# e6 ?# Q' a        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. |% H& d* e4 @& U8 t/ b        QueueClear();) x- `4 t, W4 X: x0 Z# U- e
7 l- y/ \) I% \$ \
        internal.LoadState( p );8 y, d7 N4 [+ v
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 g7 }  i+ F8 ~6 ~" f
8 f, f6 G2 k7 c7 q/ A% W
        // VRC6( ^; v/ _3 _* o0 k
        if( exsound_select & 0x01 ) {
, ^3 x$ t6 t9 Q' L6 E                vrc6.LoadState( p );* U1 d7 j0 X2 A* ^- C; b2 a
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 y5 y9 H/ f4 ^$ @) L
        }; Y3 p9 t/ T# F; K. u
        // VRC7 (not support)
  V: o, t$ x+ _+ t# V        if( exsound_select & 0x02 ) {
3 A$ Q8 K" T7 e- }0 r) l                vrc7.LoadState( p );
$ G+ d% V7 ]  ~# w) c" N. x: \                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: \* \' ]3 o# l8 V  e        }
/ Q7 B+ N/ F5 m$ I3 n. J- W        // FDS
! L  v: E4 h6 l2 O" t0 P; E( M        if( exsound_select & 0x04 ) {1 x+ y7 X1 {6 A3 A) A) a; j
                fds.LoadState( p );
4 O& F' v$ |, I7 B; j                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ f5 @; ^7 |* v0 t$ [7 z' I; j        }
4 u" g; j. P4 G' |        // MMC57 E0 w: l) ^/ ?4 [
        if( exsound_select & 0x08 ) {0 I9 K/ `4 @+ D0 Q" F- O
                mmc5.LoadState( p );, k( p" S: I3 \# u- Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 @$ T. K0 t( y3 r# ^7 t! n# M        }! @+ i1 `+ p6 Y4 O+ l, ^5 h
        // N106
, g/ f: h* e; ]' }& x        if( exsound_select & 0x10 ) {
: O/ T$ }5 J* \! h                n106.LoadState( p );
+ m( |' d( A' p1 f                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 g* X8 ^' s+ @5 ^
        }4 c7 o* m0 u9 N5 r
        // FME7
& Q' i8 {3 O$ _        if( exsound_select & 0x20 ) {
- ^3 z  x. T/ n. A                fme7.LoadState( p );2 t6 e% V1 k1 @; n" e& o5 k; W7 i5 w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ Q$ ]8 r* v/ \8 j0 x+ D
        }
! C8 Z! Y. f( y/ D3 r# {. F}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( S$ J3 G* S7 j$ \可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, k- Z4 _1 w6 Y' n/ c; }
感激不尽~~

% |$ I; n9 s% ~2 }- o- r9 o( c6 z恩 我對模擬器不是很有研究,$ N8 y( i! O/ y7 J
雖然要了解源碼內容,可能不是很困難,
3 \1 d0 Y1 L5 a& u不過還是要花時間,個人目前蠻忙碌的。7 M% Z2 ^- M! f- z% s! a
3 D5 }: q. W7 L# O% ^+ c- |
給你一個朋友的MSN,你可以跟他討論看看,
' ^+ k' [$ u/ U- x" F. [他本身是程式設計師,也對FC模擬器很有興趣。
) d+ Z: |$ O6 c6 h2 ?$ }+ A! ~( |7 N# H5 t
MSN我就PM到你的信箱了。
7 C# g7 @* d) ^: o- P, i8 x, I0 n' W. B. b& I3 V; k
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* q( E5 }5 q5 v& _6 h% }; d. h呵…… 谢过团长大人~~

0 v! q& ]6 X8 B
4 @5 {7 L/ X6 t2 b& Z+ }哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
* A! o2 L$ b- t6 t% T7 }/ [3 w: J( @团长的朋友都是神,那团长就是神的boss。
( r* Y1 x* A8 C" C. Q& T
哈 不敢當,我只是個平凡人,
0 U$ T' M# t9 [( y要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 W# M) v$ ]% W; xZYH
7 c' D1 ^1 r: J: C" j" fQQ:414734306
6 h- R4 a2 j; ]" m5 H% wMail:zyh-01@126.com3 w- [7 }5 T0 C

8 A- h0 u8 `- u2 S他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 B3 f- {5 T4 F) m" T$ m
再次对团长大人和悠悠哥的无私帮助表示感谢~~
- I9 B, R9 k$ r+ x5 C/ c$ k
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-10-27 08:42 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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