EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# G0 [; G- `" K1 Q, V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 T6 G/ B$ a+ Q+ B) F; {2 a( R
这里有相应的模拟器源码,就当送给大侠了~~
7 B( |; o1 Q& ahttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% Y$ \# t3 q# T* i9 Q. h  p能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& h. x" A2 D( w7 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- W8 l/ {+ S; p; @& \' [. y
这里有相应的模拟器源码,就当送给大侠 ...

6 u+ o* @4 z) z7 W6 w  @* a! I聲音部分(Audoi Process Unit = APU):' l5 w! G; B, {& J. l( W7 H
.\NES\APU.cpp4 M2 x, d& `0 ]) @, N+ m7 {, q
.\NES\APU.h. t; E/ u3 ^( _: j, Y( K! D
5 j# S8 G( a, l( Z$ A$ N9 G5 `. H
* o' @' ~. N8 w0 M5 T0 q; V
影像處理部份(Picture Processing Unit = PPU):
( ~" S- D; S- p1 s3 S9 [& B% c' i9 |.\NES\PPU.cpp1 A* B7 M$ U: v; X; ]9 B
.\NES\PPU.h# J' p. O+ a  ^- C
+ X7 k9 X: n/ {: y4 a
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: M! m, m$ `. F3 d5 W$ _7 t5 p9 d) A
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:: b5 @! }+ k8 T0 z# Y0 ?
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ G: O& m# r3 P5 y
//////////////////////////////////////////////////////////////////////////
& s0 n# i3 I: ~6 i! w6 ~//                                                                      //
* ^/ Q0 u$ ^/ Q' t0 O//      NES APU core                                                    //
  d" P* i  P; Z$ P//                                                           Norix      //% ~# H& J% U: x
//                                               written     2002/06/27 //
& L- ^: s  i! d' x//                                               last modify ----/--/-- //% [) b5 f/ e" @% Z8 B, C# N  s5 z1 m
//////////////////////////////////////////////////////////////////////////
, D# V0 [1 {- [4 ?, v. N" t#include "DebugOut.h"7 e5 z, _5 R7 C! i# ^* `% _2 n
#include "App.h"
7 u: i" L  L$ w! Y2 D#include "Config.h"0 v( k7 Z7 t5 v8 B

' L( k8 l' R) S' T# C#include "nes.h"5 g' Q& \0 i7 H! ^- u& ?$ V
#include "mmu.h"3 J% r8 |# B3 E- ^5 b/ N6 w6 }
#include "cpu.h"
. q. P/ ?; V1 i#include "ppu.h"- A# T  C( w0 T$ G  L
#include "rom.h"
  c4 I" B2 \# |7 w/ \( g+ ]3 z* k#include "apu.h"/ ]8 H4 E1 z' J5 a# e% v6 c

+ q# c! a: q6 ^; @; M// Volume adjust
% `2 B) `+ Q+ u+ \/ y// Internal sounds
) h# ?' }3 j) D1 b7 s#define        RECTANGLE_VOL        (0x0F0)
- A: f4 T& E' c" M* P  [#define        TRIANGLE_VOL        (0x130)3 |$ c7 d$ ^# t) N8 p2 V
#define        NOISE_VOL        (0x0C0)
+ l' q+ m. p. F, E2 I#define        DPCM_VOL        (0x0F0)' l$ r+ u5 i. T! z! \
// Extra sounds
+ ]# S9 Y  l1 f- |' h#define        VRC6_VOL        (0x0F0)
* f5 ?) C' Z0 R" J1 s#define        VRC7_VOL        (0x130)
& ]7 q4 Y: Q' ]5 Q5 Q# ?" ], N#define        FDS_VOL                (0x0F0)
" B) e) [' m9 K9 q" L#define        MMC5_VOL        (0x0F0)
, X8 o& [% C4 g  G* a! f#define        N106_VOL        (0x088)% \0 z9 \2 v( h! ?- c5 ?
#define        FME7_VOL        (0x130)7 f' V, w3 {; T: d" i, V
) ~! l+ r* T0 d8 h* ?# ^( w) U
APU::APU( NES* parent )
% T1 ^" d* x/ h0 g2 d* f% G{
2 q3 s/ @1 G. _  q        exsound_select = 0;- Y3 \$ v: b* \

4 `% t+ o" X- C0 m        nes = parent;6 A  O3 e) i$ q6 n6 K
        internal.SetParent( parent );5 U# R8 }! Z( C+ W& T

7 j. N0 O% A6 Y9 V3 l- X- H        last_data = last_diff = 0;
) \+ N0 ?- F% f9 g4 E4 G9 G$ ]( v0 I5 ~2 W2 t  V* ~0 e
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
: s5 L$ {, ]: {7 i$ b% l# r& f' N" m$ s: ~  K) G
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ e9 t' ~9 d, A  t% b
        ZEROMEMORY( &queue, sizeof(queue) );
4 I/ C( M% m$ D( w% W) ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );. j9 ^5 o# W2 N' l

! J. J6 Y, c' ^; D. r1 V5 O4 Y        for( INT i = 0; i < 16; i++ ) {  n" E1 E3 L9 D; v0 q2 W; X8 F$ P
                m_bMute = TRUE;6 z, P+ ]- L7 W( d$ m' }! S
        }
( \* w0 D9 o4 W. i/ F4 _  I}
* a8 D( G/ J/ X6 V
! S% {$ c+ |; W7 BAPU::~APU()
( w4 V6 f3 f6 B+ [0 {{
9 P7 T5 |$ ]8 D8 N8 q/ s6 m0 Q}
0 t9 Q. D+ u! W/ Z: L( C
% c- J- d, p) `void        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 N# L% \; m% {) j
{8 G5 E, }" i9 q  }
        queue.data[queue.wrptr].time = writetime;
6 V+ e4 ]5 ~9 X, y$ L* _$ F        queue.data[queue.wrptr].addr = addr;
4 @7 i: \. A' W: [        queue.data[queue.wrptr].data = data;# Q; J8 U8 ?( d% X/ w+ w
        queue.wrptr++;& p) \( W+ V: h! A: C) _
        queue.wrptr&=QUEUE_LENGTH-1;
# Q' }5 b# Z' V3 W$ r" d4 S6 U        if( queue.wrptr == queue.rdptr ) {
' C$ o' _/ W4 B                DEBUGOUT( "queue overflow.\n" );
) ~- R' E( ~7 n* h0 q) C        }
. O" @# I2 D- d% A0 R}
4 X' ?$ U* H6 _' W' E
! L! O1 E7 {8 O! p* lBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
( E  W0 ^, _; `# v{& o% J- x$ _# |2 q) T# ~( @
        if( queue.wrptr == queue.rdptr ) {8 a+ }4 ^  m6 ]( c+ z3 Q; i6 p/ H
                return        FALSE;
% Y0 O. }) d9 h& _, d* ~; k        }
3 W2 M5 `  s: l4 A  I: ?0 I        if( queue.data[queue.rdptr].time <= writetime ) {' a1 _! L- N8 T% Y% C5 j
                ret = queue.data[queue.rdptr];4 p8 G* q+ X! A0 A- `; w
                queue.rdptr++;1 A9 O! s) }) v$ d
                queue.rdptr&=QUEUE_LENGTH-1;8 c5 [0 `+ h, a0 P
                return        TRUE;
* s& \( I' L- `; Z        }
" `% A2 k/ r/ q: s7 a# f& V% F        return        FALSE;6 L( Q) o* ^, \$ u  J
}
  f0 Z/ p( o4 h) F# f8 t
: A0 f2 i! d+ |: ^$ @void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )- [2 |: p( _; c( u6 Y
{
0 R2 j$ ~4 D' U        exqueue.data[exqueue.wrptr].time = writetime;
$ Q5 J" z) h; _6 Z  I        exqueue.data[exqueue.wrptr].addr = addr;" l4 x+ y7 p9 r* S! U8 S
        exqueue.data[exqueue.wrptr].data = data;
& ]7 x8 X2 {# B4 u& ]. ]; c6 g        exqueue.wrptr++;
7 E& e# Q& t- v! L6 _. T        exqueue.wrptr&=QUEUE_LENGTH-1;5 p. @" Z3 |# @  V' Q+ J0 g: w
        if( exqueue.wrptr == exqueue.rdptr ) {
/ t: c$ y+ a7 Z! |3 k3 W# u' H# W9 W0 A                DEBUGOUT( "exqueue overflow.\n" );5 H: E! E7 V* i' j1 X7 M( }
        }8 T! P" S6 z1 O$ l0 v
}
' N# @; y: J6 ~7 [7 D
/ C  i- |$ N- J1 A  G* GBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! z; A* l* }( E9 z{( Y: L6 E2 {1 B0 o% t: c
        if( exqueue.wrptr == exqueue.rdptr ) {
- w: N1 {. }3 R                return        FALSE;
# b* f8 z) O. [0 T; O6 @        }- t, [$ s/ U# y% m9 D2 }
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; G* L8 q, i' _3 u
                ret = exqueue.data[exqueue.rdptr];
" X4 i$ [7 o& N                exqueue.rdptr++;
" H+ G9 a) S5 C9 c$ l6 q                exqueue.rdptr&=QUEUE_LENGTH-1;
, y( h$ o; I- p5 F9 W! e                return        TRUE;
1 [5 A) Q* |6 V8 S! ^) V        }
; m% v" p) V. x& k/ t1 U: K        return        FALSE;- {: S. d- X( J& u( i9 X
}
6 g4 g4 h/ S/ k8 \, j8 R) K) e8 m8 |
void        APU::QueueClear()
- L- ~( H% G1 r$ f7 e. U{5 C3 L8 ^- I! `% [
        ZEROMEMORY( &queue, sizeof(queue) );5 W3 C; d+ X4 d6 ]; r" f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ }! ]. v- g4 [/ [5 c
}
  C9 [, m) M3 f5 ?7 P; i6 c& I1 B  W4 \
void        APU::QueueFlush()
' Z1 J4 l: ^3 r2 w  f& V{1 _7 h5 e' t: r7 a) ?0 \8 Z) |
        while( queue.wrptr != queue.rdptr ) {
4 p# n% z/ A$ d0 Z% u  C                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ u( }# p: i) Z
                queue.rdptr++;
0 p* c9 g9 [' U9 ~                queue.rdptr&=QUEUE_LENGTH-1;
( C2 T# k! ^9 N1 O        }
! m  }7 i! `1 f$ R% F: n
; A# K# W7 x% ~        while( exqueue.wrptr != exqueue.rdptr ) {4 Q8 a3 \/ d- T) O  [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 `) O% w( o" A( W0 G4 r- F                exqueue.rdptr++;
7 B) {; N' k* r& }                exqueue.rdptr&=QUEUE_LENGTH-1;$ p" Z2 i0 _3 e5 a0 q# W
        }7 K5 }3 Z' \* j! L9 a
}
; U8 \( Y& I2 T* ?
) F; R* c* s' S2 U# _6 F: G6 ovoid        APU::SoundSetup()
$ p  Q: O3 m( R  O{* n, `$ h. ~" K% I. s1 B! M
        FLOAT        fClock = nes->nescfg->CpuClock;
$ F: ^% t1 A' h        INT        nRate = (INT)Config.sound.nRate;& |: r6 C0 @) {- C: X; ?. ]! h
        internal.Setup( fClock, nRate );
9 {1 ^, [( D: k" ?! `        vrc6.Setup( fClock, nRate );7 G/ x+ G' h: `/ E7 q; q
        vrc7.Setup( fClock, nRate );
! N# L; s* d- a        mmc5.Setup( fClock, nRate );
+ a( H9 N0 v  `1 t$ ?        fds.Setup ( fClock, nRate );( V3 y$ T# R' s2 k
        n106.Setup( fClock, nRate );1 [- o" a* k. ^* `$ ?0 W
        fme7.Setup( fClock, nRate );& w* W* F3 A/ _# v# c
}% `/ i! ~3 [& _5 @! ^

6 r7 s) E, e7 H8 Nvoid        APU::Reset()
" \) d) @& Z2 w, W9 A# q% X{0 S, _* p2 @4 K( h  x- R, K; w
        ZEROMEMORY( &queue, sizeof(queue) );" n, v6 N: K  C
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 @& ]" s7 `! B0 ]
- M4 K& o5 Q0 E        elapsed_time = 0;! V) w6 U( C  X* @. S
) u1 U( R' D5 {2 R! e
        FLOAT        fClock = nes->nescfg->CpuClock;, s, P0 R5 h$ v" d
        INT        nRate = (INT)Config.sound.nRate;. L. |2 M- p3 \
        internal.Reset( fClock, nRate );
1 i# e8 r, s6 a) N7 t        vrc6.Reset( fClock, nRate );
( @: v9 g" ?8 p+ R5 y3 U        vrc7.Reset( fClock, nRate );
* l* ^5 h' y. R( ~2 R/ [        mmc5.Reset( fClock, nRate );
) _; w2 Q0 ]& c        fds.Reset ( fClock, nRate );
4 _" r9 E. X7 i* E  t1 k. b7 f        n106.Reset( fClock, nRate );2 Z+ f! p4 n. a! R* H- A* Y
        fme7.Reset( fClock, nRate );, k! Z; p  R+ a1 i# u

6 t5 |+ ~9 {3 U5 w        SoundSetup();1 Z5 Q5 F. G7 C& i# u
}
) e3 w; \4 {) D$ }$ i- q+ u( [) P; S7 y7 p. w: z& j+ [
void        APU::SelectExSound( BYTE data )* Q4 @6 w# A2 V2 ?  v( L- C1 }
{
$ b' F6 W" A& C3 d0 c8 r  D; A        exsound_select = data;
8 P, v, p; o" M# o$ z- L}- k/ {* |. P4 B* U. Z; k4 `
' o! @  o5 o2 T4 V) e! Q$ I, j
BYTE        APU::Read( WORD addr )
# S3 E7 W; ^* `7 x{
- a4 \# I9 M0 ~1 I9 F. ^. u        return        internal.SyncRead( addr );, I" M' `' R  u: u
}5 }3 `! z3 ?5 m

5 m2 T0 I3 D% H9 d, ^void        APU::Write( WORD addr, BYTE data ). T$ u$ A8 u& \2 n* k8 W0 n) j
{
: \4 q, _* f2 R# m" X3 T) U9 e* G' I$ _& I        // $4018偼VirtuaNES屌桳億乕僩1 i; U* u0 o& t- Z% P, O
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 j& Q, F1 ]  i+ B1 ]                internal.SyncWrite( addr, data );
& F- Z. x% H/ v) @4 w3 B/ N                SetQueue( nes->cpu->GetTotalCycles(), addr, data );, U. ^) |# u% W+ P  Y0 `
        }! a5 b! e3 |# J+ Y+ U5 O
}: Z# B9 o% b: x* V& ?

$ Z) }( K+ v& k  I/ vBYTE        APU::ExRead( WORD addr )
* b- B  t# I; U: n/ c: y8 `{7 `- a0 E( P8 d* U  k) ]
BYTE        data = 0;
9 F5 `2 t% u) A' o/ Q$ x- `4 p' o5 T  M1 H- C- ~$ U9 n) i
        if( exsound_select & 0x10 ) {8 U# f) k0 h1 a
                if( addr == 0x4800 ) {
: V/ F. Z: }* q" P                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! a% y" ]: e7 k$ P% P5 s' k/ ?
                }8 w+ e: G( q0 T; i
        }) [1 ?. m3 c% F
        if( exsound_select & 0x04 ) {3 |$ E6 T- Y- e: H, q7 I1 Z' D" t
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 ^" P, N/ c) O$ ]0 L* G                        data = fds.SyncRead( addr );
8 v; D7 L  j* l/ s5 W, U2 \                }
/ q* e# G2 S4 f6 l6 x) p        }
& g4 @" E( P4 I" o7 D' A2 D        if( exsound_select & 0x08 ) {
) R* q  S. W  ?* U                if( addr >= 0x5000 && addr <= 0x5015 ) {: n+ j) N  Z& i: z0 Z6 H, ~
                        data = mmc5.SyncRead( addr );
. x7 o' g* E/ ^                }
# L8 U9 A3 c6 g0 H        }4 r" N' N. S. r% K, ?/ @

: _0 z" F$ K) ~        return        data;
: `1 ]/ E7 Q5 Z! }8 B}% C: D  a) L# _" f; z! Q9 ]
, R5 K! Y/ C9 K- N4 c/ A
void        APU::ExWrite( WORD addr, BYTE data )# u: S+ U1 ^# ]4 ~6 \8 ^. p$ l, E
{
/ V7 ?6 G+ ?3 P+ R2 ?$ _9 ~        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );) A. {. T$ i1 u$ l
9 y& \' t- k$ f- J2 C$ {: \, z
        if( exsound_select & 0x04 ) {4 X5 w* o  k# E) z
                if( addr >= 0x4040 && addr < 0x4100 ) {/ P  n. \8 ~% [& z2 w9 v. C
                        fds.SyncWrite( addr, data );
5 w7 N6 J  q: s% Y$ |* N/ x                }
. o" g" H! g2 z3 h; i5 n+ t, I        }" y* K, v- D( {4 M* v. L" e

  Z1 |4 d2 a4 l. g3 j( ^        if( exsound_select & 0x08 ) {4 m7 V/ X6 u/ D! S
                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 r  t5 X- |( s# }: Z; _  n( N                        mmc5.SyncWrite( addr, data );8 S7 K0 ]5 I( Q- Y/ B
                }* N( ^) V$ a# t7 L7 W
        }' x# E1 D- ^1 U9 z, [
}
; [  w: J- m3 U
2 S7 x: U% b4 v0 ~void        APU::Sync()5 T2 J) u; m4 Y) W  A; q0 o8 s
{
5 Z, G+ u* ]0 d8 |+ W0 Q}
- }/ R0 x4 W, C4 j# v# ?2 T3 f3 |# I1 _9 B% V9 R' S
void        APU::SyncDPCM( INT cycles )! Z& x5 }' K2 h4 W: ]7 S
{
8 O- q$ b( H0 ]* N" B. d        internal.Sync( cycles );
) X& L9 j1 f4 E+ t5 ~* v) `! k8 L4 j% H
        if( exsound_select & 0x04 ) {
7 |1 c7 k  p" j0 x/ }                fds.Sync( cycles );) \' H' n: E/ e* E3 @& e& Q/ M- l7 n
        }5 B+ {! d7 f) Y+ c6 n  c% s  X& O
        if( exsound_select & 0x08 ) {
( m; f9 j4 [* N% M                mmc5.Sync( cycles );
& V, G0 I( ]* ]! L$ t" }8 U7 }        }  Q4 G. E+ \" u! Q  L
}
: {4 K7 j  e+ F7 O. o7 }9 x" B7 g$ j
* F4 V2 ^3 n  r5 P- Jvoid        APU::WriteProcess( WORD addr, BYTE data )
0 Q! p# E  r6 R; y9 U- z{
: C3 t9 \& }/ ]6 y7 P6 l4 W1 \7 {        // $4018偼VirtuaNES屌桳億乕僩
) A8 h% y) S* V        if( addr >= 0x4000 && addr <= 0x401F ) {
3 O. q2 a1 T7 y: y8 w$ n6 G; P$ L! E                internal.Write( addr, data );
3 ]! L+ f, U6 V) Z! K        }+ o1 N2 H) y9 I) e0 k- q4 }4 Z
}
- M/ m  b; h' K* I! S
  {5 O( m# t. R8 E# ivoid        APU::WriteExProcess( WORD addr, BYTE data )
# F3 a& d4 \3 }8 g6 ^{7 W! ~( j# Z+ `3 g/ a1 }6 I
        if( exsound_select & 0x01 ) {
/ y; Y: a% S4 x; i& X                vrc6.Write( addr, data );3 a% @6 @& U  f# e8 T
        }
! N4 O! X# u( W        if( exsound_select & 0x02 ) {
2 M. h/ x: `( q) v9 {7 u                vrc7.Write( addr, data );
) j; ^* J/ F5 f        }: k( E) j( M8 g& _1 n
        if( exsound_select & 0x04 ) {
0 n  }5 h7 ^' @8 {6 ?* H                fds.Write( addr, data );
  \7 ^2 C/ i1 w: f        }! l2 X% K8 E: i8 P( F$ T
        if( exsound_select & 0x08 ) {
8 S; z. y/ b& o  m8 Z                mmc5.Write( addr, data );
% N. v/ z; V! k5 i6 ?  t$ k+ ^$ h        }4 [7 \& |$ g& b6 T* s
        if( exsound_select & 0x10 ) {& L5 A2 }1 H, c* I
                if( addr == 0x0000 ) {7 l. f; V5 R* H8 a3 B
                        BYTE        dummy = n106.Read( addr );
. y9 D* O  h1 }9 v9 `) {& u                } else {+ _5 v, d4 c9 l
                        n106.Write( addr, data );- f9 W8 V4 Y9 }2 ~0 [
                }
; }5 W* n% e* H5 N* N4 k. U4 l) U9 W        }
7 E3 n! e( l3 n        if( exsound_select & 0x20 ) {
% b8 w3 e  i$ y- c2 e% N                fme7.Write( addr, data );
' F6 i3 @' O9 U! A) S6 w% w        }! R( q4 i" i0 f- P  t6 W- q6 t! J8 Q5 B
}$ u. Q0 }( |7 ~& R" C

  d1 k. N/ ~: l5 G0 D2 Z* N  Evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), l4 B  K% U9 O, P
{9 r5 D5 J0 R- Q, U7 j" T3 [
INT        nBits = Config.sound.nBits;
; k/ K  ?5 N" A% q  ~: iDWORD        dwLength = dwSize / (nBits/8);
& U0 k: L- s: D& a  A1 j: \INT        output;
) z7 @1 m; O- v% w2 d3 s$ KQUEUEDATA q;. y) q  I$ h7 d! `+ _; ~3 C9 s4 f8 z8 J
DWORD        writetime;
: `) ~* _0 p* j9 V- d0 u& R# W6 W3 d! _4 }' ?+ Q6 |
LPSHORT        pSoundBuf = m_SoundBuffer;
6 \: F0 t0 t8 M. K) AINT        nCcount = 0;
3 J& `6 c* i& C& E$ o: w9 _* |% }
# I4 Y9 |1 Z) M9 A! WINT        nFilterType = Config.sound.nFilterType;' w. S4 s3 j1 G- c
8 J: \- J9 ?; O% D, J. T
        if( !Config.sound.bEnable ) {
$ T6 h/ X; a* H8 T                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );) ]- R: }$ P! ?0 O% i4 c; c3 g
                return;
  b3 a$ Q) C9 A1 i5 b" f8 k        }
  j/ E# w. D; L/ c9 e9 D
3 H; l4 v, A. d        // Volume setup
/ w" q0 k+ C, ]. {; Q        //  0:Master
' Z6 [8 ~; u: g# g' ]! J        //  1:Rectangle 1
7 K, b8 S3 `3 i$ I& @        //  2:Rectangle 2% f0 J. |5 L$ Z5 `3 S" i; R" Y# V2 ]
        //  3:Triangle
& g9 w/ e7 Y% q' \8 P1 f        //  4:Noise" o, @4 M% c% d4 {
        //  5:DPCM2 c% m; o4 C  H, Z- w
        //  6:VRC6
3 x* B- n; }3 Q. N! M5 n9 o# W        //  7:VRC7
6 N/ i, w; Y8 _5 k3 \        //  8:FDS
& F) A. g* y* Q3 v% l# d        //  9:MMC55 Z5 W+ B) [7 t
        // 10:N106" ]/ }6 q) X) M2 `' C' w$ `
        // 11:FME7: `; }: Q& O, f
        INT        vol[24];
; m. a! Z+ X+ l/ [        BOOL*        bMute = m_bMute;' ?4 ~- [! H  A% [+ P3 s2 T
        SHORT*        nVolume = Config.sound.nVolume;
$ P! Y  ~! q: F) B
8 v! s, U1 g; P5 ?) O        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 Q1 _+ C/ o; a. l; Y

- u2 V, T" D$ S  X0 ?3 `        // Internal
" ?  ^. F/ O, L7 s        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 I8 F# [' b9 x* c, Z+ l$ S
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;* a$ x! X  i" [4 Q; u$ N3 c
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- B, M/ v$ v- B9 e# @; A) t
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
3 ]! q/ d9 I+ s        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! s; n# N, b1 @5 O% ~/ }- \  X: i5 v- ?% \% |8 o! X$ j8 W- _
        // VRC6
0 n: {! i1 i6 n* z9 q+ ~        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ g: a$ }) I) L/ f$ Y1 ~
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" q% [$ V- c. a        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  L. n- B5 |, n( p* Z  ]" q4 v  ~( N- g
# w- j' ]5 C" q' ~        // VRC7
- W3 Z0 W- N, u  [& _        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
# c) T# ^. E2 w4 d# A9 x2 M) W' b5 |7 I9 R8 I2 |8 S
        // FDS0 U4 ?: m* y8 X* K7 Y
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;2 G7 q* V8 v. h

: q% m7 p' E/ q2 p        // MMC5, e- P. F3 Q# S( ?7 h
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 `, q4 P* j3 t7 e9 h% _: k        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, [# Y' f: S  ]+ J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ Y3 C$ @+ W, Y  i3 w
+ R- p4 c  D" |; z. n
        // N106
9 }% ^( q! U/ v; {6 }+ b" V1 D        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) p; D; w/ Z& _. y        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ ~& r, t6 U1 l2 E, z
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' h7 A5 V5 E) y, x. o        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% {' x/ [( B- r0 L$ U' M
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- `* ?6 Y, ^/ d8 R/ o) L" W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: m1 M; o& q& ]/ ~2 N4 ]        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! g+ N( l2 o: ^! ?3 X/ s! W  W        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ w- a8 s% Z8 Q

5 {- t  x7 Q% J# F1 e1 K. V( l1 I1 a        // FME7
- R( D+ h0 v4 R. r% l7 {- ?6 u        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ }& i4 h' t- P
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 L. U: o  x8 i: f% W  D- r; b+ s
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ n0 Q3 ?! y6 g9 Z) b' Z$ w: z& _2 L
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
1 ~6 u% n, D$ c        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;  @% p5 G- K: O

/ @% y% A& `  @+ m& m. i3 m        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 u0 Y6 M" N$ R. Y4 a7 K        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- E  W& ^; M! w+ x; q
                QueueFlush();' `: T1 N2 ?& z: h. l2 o
        }" |) r9 E2 l" `9 E* |

# Q/ j8 g5 Z4 J+ \. ~! F. v- N% Q+ |        while( dwLength-- ) {
9 o1 A. W4 d0 ~: X# ~                writetime = (DWORD)elapsed_time;0 O8 y, ?1 x! N5 M7 W
) Y0 a- Z- N- u3 ~3 e6 V6 R0 a
                while( GetQueue( writetime, q ) ) {
( k/ R$ S( ?# W                        WriteProcess( q.addr, q.data );
8 ~& Y; i9 n' f                }( B6 p) m, i0 r/ }$ I# Y

, O: q& L( k8 \6 J                while( GetExQueue( writetime, q ) ) {0 ^! ~: S0 }9 S! j1 t2 ?  D
                        WriteExProcess( q.addr, q.data );$ O" O- l& x3 J& Y
                }  D8 f4 g1 z- o" v
. u$ R, o+ D: _/ ?% T8 {5 h. D" P
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7/ {/ u, m5 c) ]2 Z, S# u% _
                output = 0;
% s8 H% ~' A" v                output += internal.Process( 0 )*vol[0];
' ], B# P/ S$ v                output += internal.Process( 1 )*vol[1];
2 n  f' }( G3 u                output += internal.Process( 2 )*vol[2];
, y) Q3 e8 W) O/ ~, M                output += internal.Process( 3 )*vol[3];
7 M( z5 S$ Q' }, ~! G; M                output += internal.Process( 4 )*vol[4];
; d8 o( X6 A: i" _
. ~6 n0 E8 b" v, O                if( exsound_select & 0x01 ) {
+ u! |0 Y& w- G" D% i4 ?, e, b                        output += vrc6.Process( 0 )*vol[5];0 |4 ?( T, u  E* g4 o$ F) S8 R9 e
                        output += vrc6.Process( 1 )*vol[6];
3 Z" h- ~5 p, N1 b8 m. M- g                        output += vrc6.Process( 2 )*vol[7];
& Y9 H# N. L/ H2 h. Z                }
2 R( o2 I6 B/ N* Z7 P0 P                if( exsound_select & 0x02 ) {3 c/ l; l: e% S! ], F" C/ e
                        output += vrc7.Process( 0 )*vol[8];( \3 y9 {0 d6 y: w) o
                }
% `) B+ e7 P8 s* t  c' ?3 U* i                if( exsound_select & 0x04 ) {5 m6 u- s) @" r8 y  ]% _
                        output += fds.Process( 0 )*vol[9];& i. U* x# [& O$ x5 \8 d
                }
' z( l  s2 j( u1 B                if( exsound_select & 0x08 ) {
4 e4 z0 L* m9 m. U0 ]% ]' p                        output += mmc5.Process( 0 )*vol[10];
( ]8 @; X/ K0 b                        output += mmc5.Process( 1 )*vol[11];
/ g* b# B8 D* t9 M; C  s* o, R                        output += mmc5.Process( 2 )*vol[12];# P$ A4 C; J) k2 a# T: b2 U
                }
; p, M3 v3 f0 F5 S                if( exsound_select & 0x10 ) {
# c. w7 B" y$ U- L1 J                        output += n106.Process( 0 )*vol[13];; v6 T% ~" R! A4 i
                        output += n106.Process( 1 )*vol[14];, F1 X3 O& u' n3 ^5 ~  H# z
                        output += n106.Process( 2 )*vol[15];* T; q/ U4 c* h% V
                        output += n106.Process( 3 )*vol[16];
" I, z. ^# }' L9 z. a                        output += n106.Process( 4 )*vol[17];
) `# T& C5 t' v. L& {: u                        output += n106.Process( 5 )*vol[18];! }4 I8 ^- J: q8 p( U
                        output += n106.Process( 6 )*vol[19];
9 s7 H8 `' X$ [2 x6 D& c                        output += n106.Process( 7 )*vol[20];
' \- M/ z- p5 o* `8 Y8 O                }  h; t* u4 H& g5 V
                if( exsound_select & 0x20 ) {$ |! h  h, y3 j
                        fme7.Process( 3 );        // Envelope & Noise! r5 @. U- Y# V- N& H! e" z, i4 l: ^0 S
                        output += fme7.Process( 0 )*vol[21];
5 {) V1 O7 z, V7 a# B3 P* h                        output += fme7.Process( 1 )*vol[22];9 E$ k7 T2 ]7 q, T& x6 D
                        output += fme7.Process( 2 )*vol[23];
- Y/ G6 o. s% I$ U' A( t: |, ]. q8 ^                }
& _8 u' R$ i  n& h; q0 U4 B3 h( q# J) E- b
                output >>= 8;
- ~2 D6 M: p" F2 G9 R
. H- ]7 N9 r& {+ y! A' E                if( nFilterType == 1 ) {
4 g3 P- @- ~4 y' x& E) v                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple): w7 N% f2 g, f& o- C
                        output = (lowpass_filter[0]+output)/2;
* e8 Y3 n* \( C8 D; b" A                        lowpass_filter[0] = output;7 C7 P0 K9 D/ h4 I
                } else if( nFilterType == 2 ) {; g* c$ h  }5 y$ F2 Z: |
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
3 @+ q, ?$ q0 B, ^                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# G3 V0 F: Q; C) z
                        lowpass_filter[1] = lowpass_filter[0];
/ `" G8 k3 }5 ]3 B- d% H                        lowpass_filter[0] = output;
, g( Q8 q) p( q- p* n                } else if( nFilterType == 3 ) {/ c* X9 ~+ I+ Z; Y. F6 K
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
, J( |8 T% Y' W; p$ h                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* a# f  \5 J3 ]/ K
                        lowpass_filter[2] = lowpass_filter[1];
, |- U3 I5 ?# g: H& a  o2 [/ B                        lowpass_filter[1] = lowpass_filter[0];$ h1 H; b2 W2 P2 o* ]9 R) \
                        lowpass_filter[0] = output;4 e9 b, l' s% s0 L4 R
                } else if( nFilterType == 4 ) {4 C: n$ o- o: {% n1 A' F! c/ o" d8 o2 C
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ g! W4 ]3 B' y% W2 L+ \+ _                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
9 C, p! o+ b( C4 M                        lowpass_filter[1] = lowpass_filter[0];0 L) ~" y  M6 p9 G2 s( r8 P- i
                        lowpass_filter[0] = output;
7 j6 O6 r3 }7 Q. b8 Q2 G; d                }
, I+ \5 ^5 T  T' o2 a' N  y" b7 ?2 l- C) a* a, M+ c; D
#if        0, M. O# x% p/ W0 P2 R; E! u/ Y$ ^
                // DC惉暘偺僇僢僩; e) V3 f$ E5 u
                {, E. q+ c& }6 V  j
                static double ave = 0.0, max=0.0, min=0.0;
! E" l7 s$ ]+ b3 Q; ~: r3 @) H- z                double delta;
$ E- L: |, _' j# X                delta = (max-min)/32768.0;7 `4 i& }0 L# |1 I
                max -= delta;
$ {  y9 j' q7 f2 H% D                min += delta;+ r( J2 s# ]2 E+ M
                if( output > max ) max = output;
4 w& G/ @3 e6 b2 _& r2 Q5 {& `# u                if( output < min ) min = output;
5 h9 j7 \$ Y6 l& q1 W; Q% q                ave -= ave/1024.0;  d& ~" u$ T# y# n1 k5 u7 x9 S
                ave += (max+min)/2048.0;
/ X2 w$ S: h: G& ~                output -= (INT)ave;9 l+ E% |, g- @* [
                }: J. l+ i! _; W0 ~' |" q
#endif2 p+ b2 N& D* v$ a9 A1 m/ D" G
#if        1
5 ]. E3 @% J4 _1 I3 b& H" f                // DC惉暘偺僇僢僩(HPF TEST)
8 d' g! B! I% G" R1 q! k$ d                {
  t. \+ s5 A+ Z$ v) A2 N# E- h//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. j$ f. p6 y2 {# ?0 W4 M0 x
                static        double        cutofftemp = (2.0*3.141592653579*40.0);" F1 B5 X5 }$ }3 a2 ~: I( a
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
% f; M# y, o! G                static        double        tmp = 0.0;
) g3 j5 D  {1 m4 K) x                double        in, out;% \' ]0 f8 n/ S  o( F

1 M* l" }0 J3 o2 ]  H. L                in = (double)output;
2 Z; N& H# e5 J. u# ^" L8 h                out = (in - tmp);3 ^  P# G/ l3 A$ M& C1 g; C
                tmp = tmp + cutoff * out;3 z6 y5 t( |, ?4 I

0 M, T( a6 P) }8 J7 Z6 p                output = (INT)out;
+ w( f/ z- q( B( M                }% J! f! a: r7 _9 [: F* s
#endif9 V5 `& r' y; K
#if        09 K. A. {3 {, C4 n5 q
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 l( x$ l; t. s' ]# x- C' e1 x
                {% u( {+ k$ R. I4 F3 M6 L6 ?2 L
                INT        diff = abs(output-last_data);/ e7 c, j  [7 y4 p" D
                if( diff > 0x4000 ) {
  p: m. R6 Y, z8 r/ q/ m                        output /= 4;" K" w! n1 ]( U
                } else
1 `. Y1 d0 u- m6 i& }; o                if( diff > 0x3000 ) {
4 ?$ \( S# M# Q. a9 i9 Q* ?. e; }                        output /= 3;
8 B8 _9 ~0 R+ S, J/ f% [8 O- K                } else; a4 x% c/ U% l
                if( diff > 0x2000 ) {
" m- p- p' K, w: I8 X                        output /= 2;6 V7 I+ D5 s+ x3 M& h! \# f: Q+ o, w
                }
5 r0 n, q  p6 K* ~6 @; X7 }                last_data = output;  h4 o" Z0 K% x+ P+ K+ f
                }/ ~  O: k2 Z6 v4 k6 e  ]
#endif
+ p6 `& r4 P& Y# @" O% m; G& _8 S  M                // Limit
  g: b6 V$ ?. V& I4 O! x: W                if( output > 0x7FFF ) {. e3 Z: m. I( X
                        output = 0x7FFF;6 A4 P& X8 ]. ?
                } else if( output < -0x8000 ) {
7 A5 H3 t5 L% O% H# j. [                        output = -0x8000;" }) h& Y) w5 ?0 V! ?, k
                }3 h% v% p0 I% A, @
+ E( _% @& g" i/ O$ g6 ^
                if( nBits != 8 ) {. M; s! A6 D6 }7 A. X
                        *(SHORT*)lpBuffer = (SHORT)output;, [0 q  z2 [# t. ~7 z) L
                        lpBuffer += sizeof(SHORT);  k3 a: z$ ]$ h0 M1 \+ C# E2 {
                } else {
6 H0 F: L% a" D! F' y* i+ h3 `                        *lpBuffer++ = (output>>8)^0x80;6 J/ {* b% S, p1 S
                }4 R1 [4 p: i; a( R! x
' S7 i  [% Y- k0 W9 |+ ]5 C6 y
                if( nCcount < 0x0100 )/ p& w; t# Q/ H+ k
                        pSoundBuf[nCcount++] = (SHORT)output;
7 {# L7 y% A1 [; c, q- o
, n9 ?& P% M5 D' l( W//                elapsedtime += cycle_rate;9 K" T# M+ c$ s. [7 D0 w
                elapsed_time += cycle_rate;6 g" z7 ?4 d/ _5 B
        }
% V# O3 {, n( P8 C9 u0 ^  S# L
+ ?, P9 a& `# l4 F: B#if        1
# H* K+ P# H- |, _) @' f' V        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ B+ }: \( ^# p6 R; m. H: ?                elapsed_time = nes->cpu->GetTotalCycles();
7 @- F5 \5 X) o. A8 R& ?6 X        }/ P1 Z: u, f( c* X4 @
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
! ?) Y6 P) b6 T6 @5 G/ w                elapsed_time = nes->cpu->GetTotalCycles();
) b4 c' j; _8 p        }9 E; N$ p9 p  u# T% @# E
#else! j# S( }, x) d; P" r/ ?. U9 I" \
        elapsed_time = nes->cpu->GetTotalCycles();% a5 I" Q! a; M0 E& v5 ^! n
#endif% f& h# H4 N+ r( g" E
}; d; }1 \: W- j- M: Y$ j

' C, B) u& U) ~0 d// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
) K1 T7 [, |  u, y8 zINT        APU::GetChannelFrequency( INT no )
( s& p, F! B/ }6 y8 b+ l4 x% M{
4 z* h* r, M* H- }8 L# A( z        if( !m_bMute[0] )9 M# _" q$ ?7 t5 o3 Y6 l8 p
                return        0;( T" B* C# ?* c- Z: [

- v$ e; R3 ?. w  b  h, V        // Internal0 z, `! p* w/ m$ f  x8 W3 ]
        if( no < 5 ) {
1 F: T' J7 P7 y( Q/ V3 `. l                return        m_bMute[no+1]?internal.GetFreq( no ):0;
: j; v+ n- O6 J) P4 T        }$ E3 ]$ ^, {3 N% ^' k- p
        // VRC6! N/ b# G5 l2 `$ L# F* Z" W
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
0 B: N, O" k) i) K2 k1 c& g$ T                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% N  p% q* i! H3 v" {8 Q: J
        }: W4 I# x( r' q
        // FDS0 A  @1 W  i0 y% M! y
        if( (exsound_select & 0x04) && no == 0x300 ) {
, ?0 h- n7 H5 _$ l" c! c4 ?6 d: J0 d1 W                return        m_bMute[6]?fds.GetFreq( 0 ):0;3 m1 t) g* E; Q
        }% O9 X; f$ K2 m# a% j
        // MMC5
5 Y' {  c3 ]$ t( y! B$ t        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
* {" k& J- @- Y2 B2 e4 x) ^                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 R' A8 a+ I/ n( g+ n% S  p0 y
        }* k! j* \1 M9 n/ Z6 h2 m5 b
        // N1065 L  u2 j( o. X/ ?2 {2 t# E
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
) O: Q: z1 `4 Y0 L/ N                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;' D* T" R$ x: g2 k& U4 I' Q4 P
        }' k$ e% P2 P# h9 Q) Q/ f
        // FME7
; ]% M8 p, i& b2 I# M        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {7 F0 S* G  U  M  o+ G* |
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
# Q. f8 V0 G- G0 i1 t  v9 q        }
: g* @& e" p) ?% ^        // VRC7% H3 B8 T4 D7 M) X0 s/ f9 N
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# u& f  H3 e) M+ W! y4 I+ G: Q
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
  l* {7 h- D8 l' h        }) w" ]5 L0 w. n2 w6 P1 D/ z  _
        return        0;
" D, O6 m! S/ D0 d}
! }; E) u0 {4 q. I: d: [) l
. ?+ B& ~* X7 Z/ \# G" z) ?3 n) Z* G// State Save/Load2 V( S$ G) [, I7 E
void        APU::SaveState( LPBYTE p )$ S! Z/ b  A  b
{: B, t5 C* q& x$ x. h8 V
#ifdef        _DEBUG
) n/ V# I: \8 m$ xLPBYTE        pold = p;
1 B5 ~" S6 O( b# P. L#endif
; B; i% P, o0 _2 l; Y# V2 X
$ f5 V3 [  ^  c8 N3 e% Q. f        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
; d, G; ]1 j, H/ ]$ J- R        QueueFlush();5 Q- z3 V" F/ S, g

) v# v2 g( ^4 Q& n* R- j5 a        internal.SaveState( p );
( k( C& v3 @* c( I* b        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; R! y/ R/ L- k6 K# o/ l& d7 n( M; Z' }# ~3 r- M6 n
        // VRC6
8 I$ o, P5 f3 I3 w        if( exsound_select & 0x01 ) {' p2 ]) f4 d. y7 T
                vrc6.SaveState( p );8 {3 H  R2 G! f
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( S) a! _2 J6 J# W        }
% _" V" o+ m: T1 r7 l1 v) Z9 D. O8 A        // VRC7 (not support)
0 L' n. |$ M& K3 m) R        if( exsound_select & 0x02 ) {  J! F1 ^9 t9 F) L
                vrc7.SaveState( p );* M# u" V1 z' C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, I: x# n4 {% X; g* w4 s
        }% [) O6 P; {+ V- @; A1 F
        // FDS7 N  K' o, @, r4 r) [
        if( exsound_select & 0x04 ) {- P5 I( D/ j) d4 S
                fds.SaveState( p );
* w; @. H' `! I6 g                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: c9 ]# ~0 x. j7 l: V) R        }* I' L# l0 S1 Y/ t; o  L
        // MMC5
% a  r6 ~8 X2 V6 A% E        if( exsound_select & 0x08 ) {
0 g) r; L5 Q, F0 P$ F* X4 r- e                mmc5.SaveState( p );$ ~: x, F0 Q6 e  q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding! a' Y- }8 _$ y' M4 G, r; ~
        }
( E) Y3 U( I( Q' k        // N1067 r1 Z5 Q+ m/ Z
        if( exsound_select & 0x10 ) {
$ U) l; v. d/ u# d, A" ]                n106.SaveState( p );
4 \: }% G& s, n                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, T+ h2 }# D2 r! _        }
. U  W! G4 m$ \8 s6 ^7 {# p9 l0 v        // FME7
( B7 P+ W3 n/ H8 C        if( exsound_select & 0x20 ) {
  B4 ~4 }+ P# |" m  Z                fme7.SaveState( p );; \! E7 P6 i( {/ x9 I: Y& |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! J6 j9 q/ y8 I  S* Y        }
- o$ X5 ?% N! @0 F" c5 D* `
9 ~6 u+ H6 I; x9 v+ s6 X  d#ifdef        _DEBUG
3 F% @$ ]# i& jDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
8 H5 A" ]; z+ ~5 F: v#endif
$ \2 b4 T( N2 U/ x}% _8 }7 A1 ?, b, t/ I9 `! q

. _& B5 Z# b2 `3 Cvoid        APU::LoadState( LPBYTE p ); S6 r- d- g. g5 ^  e
{
% }% _3 _, E. V2 k% `! F: T1 J( q" H        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
: j: |7 Z' `5 E+ ]* `        QueueClear();, ~2 l6 d# D$ k- X
  W  F- h5 ^; w+ z0 T. ~2 I
        internal.LoadState( p );
9 R4 ^. M2 ?3 j9 a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; d2 |' ?/ u# D) f0 s
+ S' p, u) g3 T5 f3 b        // VRC6) u- X3 G+ T1 \
        if( exsound_select & 0x01 ) {) H2 i/ [4 H2 S: v3 T; E# \
                vrc6.LoadState( p );
* }. u" z* M; C" ~) E                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
8 n) y4 U5 g, Q  e# L        }
, a+ }' o1 S/ E! C( s) W2 A        // VRC7 (not support)
5 p* Y, p  Q+ _/ ^: H        if( exsound_select & 0x02 ) {
6 R) E* H8 Y7 q/ k/ q5 W                vrc7.LoadState( p );
; t9 ]0 a2 I0 o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 [- A  f7 P8 G( p$ U1 M  y        }
* i$ }* ^; \/ g( g6 z/ t# t        // FDS
: A& ]) G: }4 T, W  ^+ K- g        if( exsound_select & 0x04 ) {. I9 ?1 r9 V( {. a
                fds.LoadState( p );
3 B2 G& l/ Y2 e4 ]" @* Q8 R8 g% Q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 ~; W) W) I% b7 Z        }
" ]' H) n' ~- U" G        // MMC5
# u$ q2 A; p9 N. y+ _9 C        if( exsound_select & 0x08 ) {
: U1 \, \% @0 a% l                mmc5.LoadState( p );3 U2 ]4 \6 ~3 s! l4 A  a
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, }5 ~$ s' q: \3 C  w
        }) o; u; b( ]) H: J4 i
        // N1063 b! A4 R5 w1 @1 u
        if( exsound_select & 0x10 ) {) t) O1 t( S! ]9 W
                n106.LoadState( p );
1 F2 {8 H5 H" S) R, c) f/ y( z/ U                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 Q7 f. U  R! b" N" `7 W. f: W
        }5 k  ~7 s) Q' @2 i% l# ]( x
        // FME7
# {( T( m. e' ]6 Z        if( exsound_select & 0x20 ) {- }1 T, O9 s8 V5 z  x' I: M
                fme7.LoadState( p );, h; _- E* V2 t" G. C. r; a
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 ]/ Z( J  p0 d  x/ W  g5 D: x, ^        }
6 B4 _4 u! E- j" [5 y* ~; G}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 # s6 N( ~0 |; ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 N' ?4 l# b2 W* t3 e
感激不尽~~
5 r% j3 e; }  R& F! ~
恩 我對模擬器不是很有研究,
5 B1 A( X5 @8 A9 d! {+ b- Y雖然要了解源碼內容,可能不是很困難,7 z( [1 g( D# S+ [$ j8 Z  m4 q, c( n
不過還是要花時間,個人目前蠻忙碌的。) c/ _, w4 F8 J1 h& e+ i9 q5 B; X
7 \# \( |$ e% c' Y+ b$ {
給你一個朋友的MSN,你可以跟他討論看看,
3 G7 @0 Q3 @* a* o3 J. ]他本身是程式設計師,也對FC模擬器很有興趣。
8 a# c. U. {6 @
6 b! P% F  j4 N# A- u2 X6 [7 \6 ZMSN我就PM到你的信箱了。. u) x0 J/ u6 N2 H

+ m; a2 z* q( C+ h* t0 X希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 M  u! S% g7 C! D0 z% y) V呵…… 谢过团长大人~~

1 z+ F0 \' w8 w9 S- D- ]* R7 Y' r5 S8 e; e* a  M" C+ N9 q- ^
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ' c+ [+ U2 _' `! ?. d4 G7 _% _
团长的朋友都是神,那团长就是神的boss。

9 M/ U+ r& R% F; z, h哈 不敢當,我只是個平凡人,8 M  J. {9 R1 k) O' R
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 k* ?+ B& {1 Q+ z! RZYH8 `  j6 {+ O" ~
QQ:414734306  i( Z7 Q: q; j/ \
Mail:zyh-01@126.com6 X2 X; Z6 h0 ~! i( t1 i

; G/ \# t% `; ~( K% ~/ h他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 7 B2 ?0 R# a* K9 G- Y! b: m( r
再次对团长大人和悠悠哥的无私帮助表示感谢~~

1 Y0 L* {' J. d& W. `' c/ ^/ @不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-2 01:22 , Processed in 1.077148 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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