EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" `1 c2 i& b. M! W' v( D
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" u4 B% V8 D2 e+ J4 }这里有相应的模拟器源码,就当送给大侠了~~
8 P5 m+ }& n" X- p  t/ U( Z4 hhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
& t6 I) k. Z( w) z4 K& \能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ l& T7 O, y0 ~, {* _; ?楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~8 ]8 {# O( B9 l9 y! l7 Z0 V
这里有相应的模拟器源码,就当送给大侠 ...
* S8 x6 W# ^( b: J
聲音部分(Audoi Process Unit = APU):: W$ K5 ^/ h4 `/ i3 k7 @) c( H
.\NES\APU.cpp9 I2 Y4 r, @, U( \! }
.\NES\APU.h' \; s  }( _* x: @& a& |

  X" X0 O( z1 G$ j) J/ u- n; V& O. A. K
影像處理部份(Picture Processing Unit = PPU):
8 m: m, y# @9 ]* I! v5 W2 N.\NES\PPU.cpp
+ B" Y! q7 Z3 g2 d" f  p6 [1 L.\NES\PPU.h3 x* b2 o3 ?5 W- W& {; D2 e0 q

$ A. G  d; u% W  i- T如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:$ M) L2 P. _5 y( [# g
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
9 a3 ]) D+ e2 i1 E' U  l//////////////////////////////////////////////////////////////////////////
" m, W7 v) Y% ?# b' L  O3 l- z//                                                                      //
9 p  I: Q  `( R4 U+ K//      NES APU core                                                    //* U- o7 z6 i6 B/ `# H8 ]- a7 C
//                                                           Norix      //
5 |  i* A) J" T//                                               written     2002/06/27 //
' E6 ^* D4 U+ t- a, G//                                               last modify ----/--/-- //
; S3 n0 {, V% h//////////////////////////////////////////////////////////////////////////
# u4 G% e- e, }9 x' K# `#include "DebugOut.h") z$ D' k- H' t4 D: r3 B  K3 y
#include "App.h"
  L4 @' d- o8 f; @8 ~$ g1 e, R#include "Config.h"9 z3 [' F, c# N0 H* D
- D; I6 e; \$ B( D, v9 O
#include "nes.h"
3 H, s& f9 a2 a' m#include "mmu.h"
: O& e" v. W, `+ D3 B$ p" _& V#include "cpu.h"
+ W8 [' f7 @; t7 A8 g: V: y% ]#include "ppu.h"
" C/ s* X) n1 U2 P. \1 J#include "rom.h"
; _9 b' T8 P+ t6 V3 h: l0 ]#include "apu.h"
1 J2 B. E' ^' f( C0 V
/ O2 W7 d. Z  Z/ W7 x/ x2 V) K" }// Volume adjust- Q2 c! i8 s0 }- C7 _) y
// Internal sounds
- J9 S9 P# }- o, W6 \+ B$ N#define        RECTANGLE_VOL        (0x0F0)
3 \; r% x7 v7 P2 z2 D4 N$ f#define        TRIANGLE_VOL        (0x130)
& E2 U- S( b# G/ W+ {#define        NOISE_VOL        (0x0C0)  u. s% n: W; @, e9 d. [
#define        DPCM_VOL        (0x0F0)% P3 C$ K6 S( V$ I
// Extra sounds+ P0 N! a0 P9 B' W0 t9 t
#define        VRC6_VOL        (0x0F0)
: b4 _9 g2 N( J% _#define        VRC7_VOL        (0x130)
; Z4 p( Z: u2 ^0 v; ~. ^0 ]! L  C#define        FDS_VOL                (0x0F0)! u6 u" m9 }8 ~1 l' Q/ n( Q
#define        MMC5_VOL        (0x0F0)
, b& `7 i: M6 E0 D0 E& v#define        N106_VOL        (0x088)
! h3 C, C( \5 C0 d! ?, c#define        FME7_VOL        (0x130)
" n& K1 y4 J; u6 O: J* M  Z6 H% F1 u9 q) ?
APU::APU( NES* parent )
. B6 Q+ f2 F0 k! X0 W$ o{9 [. K' z; J% x2 T0 [5 u2 F
        exsound_select = 0;
5 q3 X' v+ K4 l$ m( W# E8 j0 ]/ k; W/ q" N
        nes = parent;
: n5 t# ^# ^7 _  h8 T* _3 k/ s        internal.SetParent( parent );
" L& d  o% b& M0 D
8 c( i' O7 A: O4 P        last_data = last_diff = 0;
2 y1 X, O- U- I8 I4 f* q, F
0 [8 P- t3 C+ @. I        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- n  m' |: a* d4 {- c" I9 p

% _1 z6 j9 Z0 h. k7 x7 ^, _$ T* m% `: Q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
) f9 ^* v; W3 @( R' X  ~% k        ZEROMEMORY( &queue, sizeof(queue) );
/ n1 d, G' T6 i8 M+ U        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 C1 M/ {! Z1 J& ~( |# U
7 K8 P7 B6 ]6 u9 i; V        for( INT i = 0; i < 16; i++ ) {8 d! k/ u' I  j9 a
                m_bMute = TRUE;
# h- g; |- V2 P. k        }
. ?* V9 G0 d( @& I}0 s9 w7 N& U8 O' e
. Y$ o9 L$ {# C# y$ j
APU::~APU()
7 [, W# w6 e1 [1 C{
  R/ }- p! L4 q4 {4 |+ w}  f  H. j3 |6 W4 M' ~/ s

  z) q$ w8 g$ C: B, D  m2 `2 m4 Qvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )) }: o' \3 \+ S6 P3 c4 m* C3 w: u0 t
{5 f0 {) j& E5 S2 S( N, Q' A& C
        queue.data[queue.wrptr].time = writetime;
( O4 Q( c! v; ^) ^        queue.data[queue.wrptr].addr = addr;
+ s6 s) r( j# o. I9 y        queue.data[queue.wrptr].data = data;  M: R3 x9 b/ Q8 H4 b- u
        queue.wrptr++;& P' T6 L$ P, {, m5 X) x: |
        queue.wrptr&=QUEUE_LENGTH-1;- `8 q- U. ?% }' K. L; Q1 g2 m
        if( queue.wrptr == queue.rdptr ) {
( ~- @8 W: H8 @                DEBUGOUT( "queue overflow.\n" );! ^7 I/ S+ b6 q& W* t$ e( E9 |
        }; P  A$ C- E$ B- k  E. C6 i, P
}
4 {2 S: F, Y, N8 u# H$ T1 |- T1 E* s$ q9 h6 x9 _
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )( t& u* J* a/ P( B5 c6 a* a
{
7 I2 s! h# u0 R( |0 w        if( queue.wrptr == queue.rdptr ) {3 x4 |" r! o/ L3 r& a: W' k
                return        FALSE;* S# y% K2 i4 K. q. I
        }
3 v9 m' Y5 X/ s$ a# O2 {        if( queue.data[queue.rdptr].time <= writetime ) {
  x; u8 \1 k+ E/ l( C0 l2 g                ret = queue.data[queue.rdptr];
' {4 J3 c7 m( y) [& X                queue.rdptr++;: i4 f& ~: H1 I/ }2 v8 c( }/ }
                queue.rdptr&=QUEUE_LENGTH-1;& a- O$ Z1 p3 G! r1 \! L1 S
                return        TRUE;& k5 N+ z# l# T- m9 v4 o* }" t1 X
        }
; I2 s+ L; e3 E9 ]2 f" M% f9 G  J        return        FALSE;
" }  E6 H  o6 T( ?3 m3 c}
- q- {" w# B' n% j3 W5 r0 V" K% I: E- d9 K0 P; T
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )- N# ]- F0 F, x
{, R. Y1 `/ T; h+ Q' F( V8 ~
        exqueue.data[exqueue.wrptr].time = writetime;- F4 m& ~8 o: u: K
        exqueue.data[exqueue.wrptr].addr = addr;
2 T% O$ i. d0 T4 j3 B        exqueue.data[exqueue.wrptr].data = data;. P  C( @; S5 X4 [
        exqueue.wrptr++;$ F: n3 V7 b2 y, a3 e! T
        exqueue.wrptr&=QUEUE_LENGTH-1;
2 h7 f: k: K6 l* M9 s7 F        if( exqueue.wrptr == exqueue.rdptr ) {
0 s; z) C% H+ L( l* c: o                DEBUGOUT( "exqueue overflow.\n" );
5 l% }  P* _- V3 R        }5 e& K# N& s& U
}# V9 D) W, E8 M

- l; |6 Q7 E1 C! Q! \4 N; P! PBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
# R: x% ~) t* M$ x* Y( v* ^2 C{
2 T. k; Q) M' @' K9 C+ c2 z% p        if( exqueue.wrptr == exqueue.rdptr ) {8 O$ ^- v1 R3 y- B2 i8 k
                return        FALSE;
. x& [7 H+ V  t! Q! Y        }. e/ P. {, D  ?* I6 E
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& y! c6 k) e+ @- E+ f
                ret = exqueue.data[exqueue.rdptr];
0 T+ M/ t& P4 t. }$ W6 t                exqueue.rdptr++;( d* y! i! @; ~: N7 x
                exqueue.rdptr&=QUEUE_LENGTH-1;6 T+ O$ U+ }/ o  G2 b0 U2 n8 K/ u9 g$ H
                return        TRUE;% r! @5 p  H  \. U* W
        }
- p4 @' S' `& A+ Q- }% b        return        FALSE;* }1 X# m7 _& F. |
}
- G/ v- m7 F! \) Q$ h
* l* G/ `& t# D" z4 J) Tvoid        APU::QueueClear(). F) U# b: D) \* E
{3 h) P5 b$ h3 D) d! P
        ZEROMEMORY( &queue, sizeof(queue) );
% q5 K; g6 V$ J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 e2 O  T2 c& P( I0 s+ |! _7 x}) H/ h+ e& w+ c* f

2 ?' C( K9 N* u; y  cvoid        APU::QueueFlush()! C) g" g- C9 O# k' F
{
/ k* S  y4 m2 Z) m  A        while( queue.wrptr != queue.rdptr ) {
1 e5 p* f  J! f. |                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ Q) N1 S! R7 X/ I& [                queue.rdptr++;
# K+ W5 M. k) U  a% t% ~                queue.rdptr&=QUEUE_LENGTH-1;
* O& |6 l9 I& m  {& g        }
9 ~9 X( y) g* Z5 p0 t* s4 P- h1 a: }& j- c  y6 ]
        while( exqueue.wrptr != exqueue.rdptr ) {
; u1 H5 R& Z: M+ }' f3 y                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );6 G7 S% I- V! U4 ?+ q3 q  ^3 F/ r
                exqueue.rdptr++;
" ], {/ Q( e" f7 Q4 R                exqueue.rdptr&=QUEUE_LENGTH-1;9 _# Y$ H* B' n: v/ W
        }
1 p- L! }+ i! j  K}; A8 b* O9 ?7 J% O( b

( U* j2 |7 T$ k: g/ B# q& Xvoid        APU::SoundSetup()
5 u5 l! v' b" n3 X7 ~; m. L{
% p2 |, ]* _0 l- n        FLOAT        fClock = nes->nescfg->CpuClock;
4 K+ L9 g% Y- Y2 Z/ L        INT        nRate = (INT)Config.sound.nRate;
$ a3 Y. J5 s1 `! Z- i2 Z        internal.Setup( fClock, nRate );0 G+ S9 U: y3 f1 U- R; Q
        vrc6.Setup( fClock, nRate );, `0 F" R/ b, S' z2 z4 [. u% w
        vrc7.Setup( fClock, nRate );  _# p( p! X% g) i
        mmc5.Setup( fClock, nRate );
% V2 I- _" k/ S2 x        fds.Setup ( fClock, nRate );
9 h7 m: }% r/ e5 y        n106.Setup( fClock, nRate );0 d% L! E6 M9 p
        fme7.Setup( fClock, nRate );
! v+ z6 J4 j/ z( c' S}. B* d/ |! B+ l! j/ d9 K0 u7 f

8 R) i6 Z, S+ O$ ?. Lvoid        APU::Reset()
; n1 e$ G  p/ |# K; A' d& v9 [, K{
' U+ u- M5 G. l" ]7 @) p6 k) V        ZEROMEMORY( &queue, sizeof(queue) );7 P0 L( V# u; H
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) _; w1 v' @& K( U

; u  {5 f5 m! I% e6 B* f. i        elapsed_time = 0;' `; ?$ X7 P# B, E3 ]

. q. s# n- I7 q1 q0 p9 R        FLOAT        fClock = nes->nescfg->CpuClock;, o9 c0 m$ k* r% W7 t- `  g% N: z
        INT        nRate = (INT)Config.sound.nRate;- t& p" f7 f/ t' Q, }
        internal.Reset( fClock, nRate );
# i# Y3 C% c% i: }8 x  j1 E' Z        vrc6.Reset( fClock, nRate );/ @9 Q- L0 X5 Q. E+ X
        vrc7.Reset( fClock, nRate );
' {2 l4 r( z9 L' ]' V" z/ Z+ a        mmc5.Reset( fClock, nRate );, `$ E8 z! z  x6 S; R+ T/ B
        fds.Reset ( fClock, nRate );
) }! Y% o0 g3 y% w        n106.Reset( fClock, nRate );
  Z& |; L5 B  Z# t( a        fme7.Reset( fClock, nRate );2 q9 N( _! m1 Y8 K! G- Q% k
/ [% j0 j0 @( x! X
        SoundSetup();
9 ?3 X* i3 _2 z# m# g- p}
4 a1 l( Z" c( i( R- x1 }; E0 \& ~% J
void        APU::SelectExSound( BYTE data )+ M/ j" _  B4 a% m2 m' R# y' i8 ~
{
1 \  L! c" l6 a- _, r% o2 d        exsound_select = data;
( f; c+ _  h/ r4 Y  J}
9 u  S4 A4 [- W1 L( N2 M5 ]6 g$ A) @+ O  f
BYTE        APU::Read( WORD addr )& A- _7 s" h# O2 W+ ^
{' ?6 O% K0 s, o+ N
        return        internal.SyncRead( addr );
: o1 P! K0 m$ D}
' C! i3 l3 X' U+ F; l4 Q4 n4 h' X; r8 j0 f! |. r
void        APU::Write( WORD addr, BYTE data )
1 S5 Z  U" W2 E$ M' W& A{
! n4 m8 b. f; X        // $4018偼VirtuaNES屌桳億乕僩
6 T4 J/ [- |$ d7 \9 S$ E        if( addr >= 0x4000 && addr <= 0x401F ) {
9 r# _  [6 u; n/ o% _- i                internal.SyncWrite( addr, data );
. |  m/ q  I1 T/ b3 i1 [9 w                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
0 L* R3 U5 r! {/ z/ h% {. J: a        }
; i9 i9 N) C- G}+ @& p, e# ]3 O# B: |  w
# J6 N  Y$ U. J, S7 L
BYTE        APU::ExRead( WORD addr )
; P, j8 J1 @7 H% F, A{
/ G- ]5 ^$ S3 p, H, J' }7 `BYTE        data = 0;9 P* m8 k( }& q! Y

' }- f# h/ c* n5 J' q        if( exsound_select & 0x10 ) {
7 o* q1 j7 C8 U                if( addr == 0x4800 ) {
2 ]' v8 j& P: h4 ^; v2 N                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
( ^( a1 g/ ]* C* k                }
4 W& ~3 P  K' L' T        }
* [7 M0 u' Q' k+ V, A        if( exsound_select & 0x04 ) {% E4 q. u: i1 G
                if( addr >= 0x4040 && addr < 0x4100 ) {# G: ^8 K, E9 ]8 u  H
                        data = fds.SyncRead( addr );5 V: D6 @) K2 Z( T4 d
                }
6 v9 K% I3 m0 u7 _) M* u0 I5 ^        }/ Q' n" g3 z' ~$ d8 q! [; k' f. s+ ^
        if( exsound_select & 0x08 ) {; F( ]- p2 |! m: b" ^6 g
                if( addr >= 0x5000 && addr <= 0x5015 ) {. C( Y7 b# u* v- Q/ B
                        data = mmc5.SyncRead( addr );7 r  l* i4 z7 K2 m4 U0 C
                }; |' H$ u0 }3 _! s/ A- O% f
        }
6 ?& d% ]" S- [, Z% C! F% q; @9 l
7 t9 Z  ?) p7 }6 q        return        data;
' {9 e* c  t& M& G: W9 ~& Q0 `/ i}
# w, X# H( `  e- v7 I
7 s5 e3 C- h& b3 I3 Nvoid        APU::ExWrite( WORD addr, BYTE data )
3 ]* ?: q( l; F6 T{' f% Q: i& Z' ?- r; C# y# g
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );# k' v3 V% f" S

( j& V. f/ t* h# a, O        if( exsound_select & 0x04 ) {
! }* ]# k' ]9 P2 M+ A- E: l                if( addr >= 0x4040 && addr < 0x4100 ) {, P4 i7 W: a4 x! T% O! p7 S
                        fds.SyncWrite( addr, data );
/ a6 k$ P, m9 z, P# q# w8 @+ Y                }1 J) q+ g% ]9 `) J/ U
        }3 c3 n% J  H8 Y; V7 ]. }1 b& G

3 t8 }8 `* Q) y" X) v; W        if( exsound_select & 0x08 ) {
4 K& M" M* k) Z' {                if( addr >= 0x5000 && addr <= 0x5015 ) {9 j! ?8 D: V3 k4 i
                        mmc5.SyncWrite( addr, data );
8 O9 s1 w7 d' k' m- d                }
$ E6 A2 z" k! }( U        }- k3 `. t: w- D* R0 t/ T
}
1 i& I5 K; }6 |2 {2 s1 w, ~; g4 ~. v! U/ {; W* i4 L) I
void        APU::Sync()
8 _( S7 I( H( K, T2 P8 ^{
3 y1 }, o$ t8 _}2 E9 N' k. J' W' s' P$ X2 G
+ B! C; D- |( E) d* @% n
void        APU::SyncDPCM( INT cycles )
  I# T8 v* R$ H1 d" g{, W) r( J5 V' J
        internal.Sync( cycles );- T; ^1 A: ]) v4 |
6 U' S, T6 _" H8 W
        if( exsound_select & 0x04 ) {
. r! \& q3 X' E  V7 D                fds.Sync( cycles );
+ w0 Q: N" h8 o: k  A' {6 ~) C: Q        }
* W/ J5 u  h9 K+ Y' [7 E, z        if( exsound_select & 0x08 ) {
, Y# I3 M( h$ q7 _+ z                mmc5.Sync( cycles );4 z$ j4 x# P3 T2 y2 Z2 {
        }( _  _" b+ a, i# b7 B
}; h( w( \' [& a1 Y9 O7 u" x

- q$ N' n; e- y+ W2 qvoid        APU::WriteProcess( WORD addr, BYTE data )# ?3 e5 f! \/ L7 w) D
{" l0 z5 {- |6 f) N  X2 O
        // $4018偼VirtuaNES屌桳億乕僩5 g3 j# F1 E6 \9 A9 Z8 _
        if( addr >= 0x4000 && addr <= 0x401F ) {0 j4 q) e6 T& d
                internal.Write( addr, data );. H* l8 r6 g- f& {. N
        }
* L1 Z( z+ q' v3 k8 \}+ A6 D: I; F# o2 a) g5 m$ u7 w

8 _6 O9 i, l0 q0 [; pvoid        APU::WriteExProcess( WORD addr, BYTE data )
$ I/ D: l. q7 b! x" W{
- n/ n  h6 r) O0 c: p) J! O        if( exsound_select & 0x01 ) {
5 W2 R0 s) a* F1 n+ \3 ^+ O                vrc6.Write( addr, data );7 Z% \. y0 Q9 d7 [* Z6 k
        }1 }/ j$ z' q& \3 r9 O% X  d9 d
        if( exsound_select & 0x02 ) {
+ O* o: T: T/ f5 t) j. m+ i                vrc7.Write( addr, data );
: {! M+ n5 ~+ _- x4 G- ?) a, H8 d        }
8 {5 S! |: j1 H) }; G2 `- [        if( exsound_select & 0x04 ) {
- t2 }* g8 u( _- r                fds.Write( addr, data );2 d# V! j/ Q4 B6 A) P  B
        }1 c7 m" @" S7 t* d. }% o# Z
        if( exsound_select & 0x08 ) {
7 v4 j8 P( c  F, `                mmc5.Write( addr, data );3 ]  a5 P$ @0 [1 V2 B/ `
        }3 g) x% V4 L8 a  f( B$ v# S8 I" h, ?
        if( exsound_select & 0x10 ) {
5 M: v' Z0 ]- t( l" |; v8 F) r8 o                if( addr == 0x0000 ) {
+ z; R: a2 Q) T: ]( y! u                        BYTE        dummy = n106.Read( addr );
7 m) t$ G/ N+ q2 j                } else {. D5 o6 `" Z' [/ C; _+ {! o
                        n106.Write( addr, data );
0 ^7 G! [0 R% k$ V                }) E7 J1 K2 p9 u3 ?! O7 W
        }: F$ j3 }# V3 q0 p
        if( exsound_select & 0x20 ) {* ]$ s, V, H5 L* X/ n
                fme7.Write( addr, data );0 X; t9 c# l' U$ M; a! `9 J
        }
6 e/ M/ {; S- N: a/ [& N}, o, u6 S' d  `2 o8 r$ x3 O  F7 m
) L' Y; H' y5 O5 w; a
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )& I0 P% s7 [; G3 }1 V
{0 U) [# ~* I9 a4 e
INT        nBits = Config.sound.nBits;
4 h8 G" C" N, j6 oDWORD        dwLength = dwSize / (nBits/8);
4 J+ @/ X, a: k7 s/ rINT        output;1 Q9 C: e  y* j3 _
QUEUEDATA q;0 |( d' n7 T, s
DWORD        writetime;8 s8 Z' `) \" f8 g7 }8 q3 U

/ Q! H4 B$ V: C$ \6 jLPSHORT        pSoundBuf = m_SoundBuffer;
( A+ _# x2 n) u4 c$ E: Q& hINT        nCcount = 0;
' G5 ^, g6 f9 X
$ a3 m/ _: w: Q4 t5 q1 l6 N$ U+ QINT        nFilterType = Config.sound.nFilterType;4 K6 K$ h5 ]9 y. t7 L  N* y! U
6 _: g# k1 L! x: [. W7 m( A
        if( !Config.sound.bEnable ) {/ Q+ f" J8 _2 M; {
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );  j: F$ G8 S" c' E! N
                return;
+ g& {8 w( p. o1 b: Q0 d        }
' O8 ^- f4 I2 z; ]. ?/ {5 }8 n4 e8 ]6 w, ^2 {) J, Q. y
        // Volume setup) a* _/ o* C6 n" P" j+ @
        //  0:Master. _' q2 V- D7 H1 b
        //  1:Rectangle 1$ L) S% x* |# X8 U1 y
        //  2:Rectangle 2
2 \$ m. q* k- {: t, i        //  3:Triangle
" j, _7 Z* o1 m# _/ ^% p        //  4:Noise1 T3 V: [$ `9 O3 p9 _8 b  s
        //  5:DPCM- J4 @6 l* V, }' f
        //  6:VRC6
2 `, X0 O+ n6 F4 e/ I  g5 t        //  7:VRC7
" d; y; U/ S& z        //  8:FDS
* X  T8 H7 y; i! `7 S8 ?1 k4 m# O        //  9:MMC5+ ^' n8 x' X0 R* ?3 Z, u1 L
        // 10:N106
* @" C: B9 K. ~4 `        // 11:FME73 y, m" i5 w; j7 E3 h! |; Q  U8 ~
        INT        vol[24];  D; Y  Y$ H4 K/ a8 C5 J( @. {3 P
        BOOL*        bMute = m_bMute;- j6 O! f% [5 T+ q
        SHORT*        nVolume = Config.sound.nVolume;5 U) n- q0 I6 n1 F3 t: \) B
4 j+ q2 O  j0 V9 \. @- k! Q
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;0 a  \- {/ {+ e; W
) }* A9 M/ ~" i. N  m% _
        // Internal2 B( B1 J$ v4 \: H2 S
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;, X6 u4 n; Z9 |4 {
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;# ~. v: s1 T7 I
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;, z# I/ k# i& {( D/ a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 I. r" n" r7 V7 t8 H, x
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;% `5 b; g- q" L7 q, l* _0 ?
- y9 k9 w& J3 a
        // VRC6) j4 f5 n$ i& l7 \
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 c# ?1 h2 g3 w6 E6 ]( p        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- j$ l0 X' G, X        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 ~" f7 z3 ?- Y( n# P
; x! A, m8 ?; \! ~' G        // VRC7! Y- n5 G9 |& v" {6 w9 ~/ s
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 {7 W; I! o! u2 z- D2 T
" e; d# I  o: a; E; {$ A( ~        // FDS. N; w& @8 ^4 a: Q( J
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
  b* J  [; Z# U& m8 j0 X! t
  o& B( U( g0 e( F# a        // MMC5
& X; n; O. {8 a( D& `+ {" C        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, k1 z, j; l' x        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' l4 I0 d' ~+ T/ h" T+ X        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& y: c2 n  ]; P. J3 Z1 x, i% P- ]$ x  `& W6 u
        // N106$ T- `* D6 T( c0 u% ]: i# E) A
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ }# s& H5 O6 {* c. T8 ]        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, ^3 ]1 F8 x4 w        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' s( `8 `/ u) m$ ]7 w' H- ?; Z! S1 @# M
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 P. p/ m5 g" _        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- E9 q: I% L; X: o* V        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; E; M  K( L6 G/ P
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 g0 m3 d7 ], e; g* `        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- r! h! N( m- z* B1 w: T* K1 Q8 X, a5 M% J' G- u  c1 r/ ?
        // FME72 X& a* x' e' s
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 A/ J4 v$ u- R$ N0 e
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ j% h4 Y& a8 ~# X3 j1 @, V
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 y" X& f) j; ~
# I- Q7 c( H# u" w1 f
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
# a7 i% Z- `. Q: T        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) ]& \8 t* U+ h# U8 w
- T, r5 F: M0 |" b2 u        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟* h; ^: u1 ?$ k; E9 I! j0 z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
) l7 W2 X! u: b                QueueFlush();
8 M0 T- x& v2 J5 Z        }
7 i3 `% A" O- ]
: @, I) [  F* T0 {$ h2 i; Z+ O        while( dwLength-- ) {
# H3 X7 J3 `% q( e                writetime = (DWORD)elapsed_time;
) K% \4 i/ Y( X1 F; ?; }: g8 C4 T4 m8 j+ F0 C8 D! F7 z- v- s
                while( GetQueue( writetime, q ) ) {+ k% b: o3 d4 _
                        WriteProcess( q.addr, q.data );: N) a0 d$ g3 b3 E9 s8 B6 J' H1 C
                }
: O- I# q" u4 F$ Y. ]/ b( [, n* i
                while( GetExQueue( writetime, q ) ) {9 w7 e" y) E9 n$ B- O: p, F
                        WriteExProcess( q.addr, q.data );) c, l! {& l, o8 d% N
                }
1 I  E7 N+ s6 \- ~6 S' ?* o9 h0 o! r4 Q2 L- b+ D6 {" g
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 a1 [# |6 R3 k0 K1 z1 \& ?                output = 0;/ p+ ?- a; P5 P; h& e
                output += internal.Process( 0 )*vol[0];  i* i  U, e$ F  e, n# k) T
                output += internal.Process( 1 )*vol[1];" T, s7 T, [/ @  b5 P% V7 U0 ?1 z
                output += internal.Process( 2 )*vol[2];1 r+ G0 U1 [% b: P& K; Q' [
                output += internal.Process( 3 )*vol[3];- z6 M. I$ n* e: @2 C
                output += internal.Process( 4 )*vol[4];
! Y4 V* z( x" g, ]4 c8 x9 L; s! h, ?1 m8 a5 d
                if( exsound_select & 0x01 ) {
/ ~1 T. |- s2 I6 J# y3 O                        output += vrc6.Process( 0 )*vol[5];+ D0 n9 j% f/ b
                        output += vrc6.Process( 1 )*vol[6];! g! u9 U" p9 I6 {' A  x
                        output += vrc6.Process( 2 )*vol[7];7 W3 M  b0 f  N$ a
                }: T4 `1 y3 h$ n
                if( exsound_select & 0x02 ) {, ~, v* g6 D# ~  j' F1 X- u0 `* F; e; }
                        output += vrc7.Process( 0 )*vol[8];! C) v  Z/ N0 I
                }! Q- E% Q9 S& t! e( \
                if( exsound_select & 0x04 ) {
9 T. E# q' W- m% F: n- p                        output += fds.Process( 0 )*vol[9];4 }: @2 y1 F) x
                }
9 }5 S) A$ |3 R2 q* [1 I                if( exsound_select & 0x08 ) {  T0 q- g. b# @
                        output += mmc5.Process( 0 )*vol[10];2 ^+ b7 {4 |0 H# E5 f! T
                        output += mmc5.Process( 1 )*vol[11];' W! Y5 |; S+ K5 B5 U% l
                        output += mmc5.Process( 2 )*vol[12];
+ @  {! [& Q# A& h+ u                }
9 E; ?9 A) h3 u! }% m                if( exsound_select & 0x10 ) {
, T" q1 ]+ m$ b. Q; {' \                        output += n106.Process( 0 )*vol[13];
, x: x( }, b5 z7 L8 b                        output += n106.Process( 1 )*vol[14];
2 \; d3 I6 E8 L                        output += n106.Process( 2 )*vol[15];
6 y! N) K& ?) o. g$ n  m& Q8 V                        output += n106.Process( 3 )*vol[16];7 `2 L  ]* |* H  K# \" f
                        output += n106.Process( 4 )*vol[17];
. w3 F! q: g0 s6 X) _5 R" D                        output += n106.Process( 5 )*vol[18];
5 W3 ?- `3 D. Z- X- Y6 e                        output += n106.Process( 6 )*vol[19];1 G; h8 {* Q+ ~: {* u' q
                        output += n106.Process( 7 )*vol[20];5 [2 s: m% h/ w2 y* I  K) C6 i0 z: V
                }: n1 N4 n, g) Z4 ^3 Z0 M, P
                if( exsound_select & 0x20 ) {) ~: x# E# a, @( k, ?3 j3 u4 y1 G/ h
                        fme7.Process( 3 );        // Envelope & Noise
" Z7 K: }/ |* r# k7 ]: F                        output += fme7.Process( 0 )*vol[21];% d- x/ D+ y8 Z; m0 W3 {
                        output += fme7.Process( 1 )*vol[22];7 [" g+ B5 ]$ k9 e
                        output += fme7.Process( 2 )*vol[23];. E0 R9 i9 u! ?" q  q" I  j  ]
                }
) u- H6 G+ g7 G" a0 T0 Q1 Y2 l
" {1 {9 z& f: u' [                output >>= 8;1 U  e$ h0 T$ f+ U. Q7 L
) }% N% v6 a4 ~0 a3 r
                if( nFilterType == 1 ) {5 k2 U, G  \% z6 H+ L5 {2 D
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)% V9 z( F8 N, V2 u+ R  W0 A& H* e
                        output = (lowpass_filter[0]+output)/2;- I5 m- p+ x$ t
                        lowpass_filter[0] = output;: a5 E+ K& N4 m, z  k% {
                } else if( nFilterType == 2 ) {
# j. c. ?' f9 h  Q6 R7 z/ [7 `                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 }+ E  Z- e- H- o, u
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;, }- A9 i9 |3 K7 R0 a
                        lowpass_filter[1] = lowpass_filter[0];3 X" [) Z7 T7 j( t5 G  I- P
                        lowpass_filter[0] = output;
$ ?7 P; z0 A( \5 X                } else if( nFilterType == 3 ) {
" Q+ w3 W' l* I: [9 p                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 Y; n, A: `$ T9 Q% `4 P1 y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
. v: J5 L# g; U2 j- e7 L' V* o                        lowpass_filter[2] = lowpass_filter[1];
5 y" R" ?, R: ?" c# X! W                        lowpass_filter[1] = lowpass_filter[0];  R% K* D: c% j. C2 a: j
                        lowpass_filter[0] = output;+ v6 Q/ U; R8 Y  s8 y
                } else if( nFilterType == 4 ) {& j# n. ~3 ]" q( o2 }' V
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 p  h4 o8 Q" T. k9 n) l! B6 D                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;" p3 |* Z: ]. N! M: Q/ s& I
                        lowpass_filter[1] = lowpass_filter[0];
1 g2 [' `" d  z# V8 `6 k3 G                        lowpass_filter[0] = output;
- S( I: V. }/ W) N) |; S                }5 }0 H, a/ [* _- D7 \" d. }3 R
" k, R: G0 V# ^. d0 ^7 j" t3 }
#if        0* D' V) R# t+ L: @- f1 Z% r
                // DC惉暘偺僇僢僩
: j; X* B# U1 ~6 ~4 B" E( V                {
# C0 V2 h. k" w4 z+ B                static double ave = 0.0, max=0.0, min=0.0;+ i2 z5 l. X: V, I) ^" F8 b/ m) D$ n
                double delta;
# R; |8 U, I$ a6 y: t5 Q                delta = (max-min)/32768.0;
+ }( u) `. r) s                max -= delta;: H; }5 |, x/ M0 E& w5 e
                min += delta;
; _% @- I4 g' X8 ~  X9 j4 h+ s3 B! [                if( output > max ) max = output;
! |( u- `6 j& I7 I; B                if( output < min ) min = output;- j8 V8 Q5 I. `& ?5 d  q/ N
                ave -= ave/1024.0;% c0 g9 Q9 n5 x  R) ?2 s( v' f& L  r& }
                ave += (max+min)/2048.0;
* W" o& P& C/ O                output -= (INT)ave;
/ D: ]* @" n2 ?8 b3 {) I7 {                }
- R: w3 [: y$ H#endif
& r. j6 D  u1 W3 B4 W#if        17 x# }2 a) s0 G+ y* Y+ T
                // DC惉暘偺僇僢僩(HPF TEST). T7 c2 h- R9 E, q. A
                {
; u4 M! W8 f" `7 y" ]! n" s: C: A7 [% l//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! v$ u' i$ u+ u" C                static        double        cutofftemp = (2.0*3.141592653579*40.0);
+ C) x! C( q& @: n                double        cutoff = cutofftemp/(double)Config.sound.nRate;
) V6 a' K& y8 n+ O5 A                static        double        tmp = 0.0;
' }+ Y+ p8 z4 ^# D/ q7 ?, \  T, u1 d- H" ?                double        in, out;
7 U/ a$ z2 z; ?% n6 t1 {( F
+ J* c" f: g4 t8 S8 G! t* U                in = (double)output;
! t5 ]4 v8 T7 i( J" c                out = (in - tmp);7 _0 L# f) V7 p( s  O' X/ |/ }  U
                tmp = tmp + cutoff * out;
" ^$ Q0 P8 W% E% P) r8 Z3 X
  O, [& e) J0 I, L: C                output = (INT)out;1 v# R" V' ]: B1 W, ?
                }4 |# [; ~$ w/ E
#endif, p& l* J# W/ n5 w, o& ]
#if        0
  E& @, y, G3 i! N. l0 j/ N7 [                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
4 Z0 O" j; {, {                {
! p/ o* d, A7 g- j% c6 u  c& W- Y                INT        diff = abs(output-last_data);* P+ z' p4 J* h6 c
                if( diff > 0x4000 ) {
; I( |2 E) C$ `: D                        output /= 4;
- D1 D7 A3 X# K9 D                } else ' r8 x1 _2 K# _
                if( diff > 0x3000 ) {
1 T: T& Q. S5 S  U# q$ Y/ M                        output /= 3;
$ Y3 ]3 y# t9 z4 Q  K                } else; Y; \0 Z4 }; G' M' i2 A
                if( diff > 0x2000 ) {
' |$ M0 G9 ^, \. Y                        output /= 2;
/ g( L1 Y( x2 V7 @7 o/ U                }4 D, I) C) v) p# q
                last_data = output;+ W8 k. t- a8 M' X; K, I
                }# g* I& T; Y! h7 o4 M5 b. b
#endif
: y# y+ K* c9 Y3 W5 m$ s0 B                // Limit5 {  o! I" {, J! Q
                if( output > 0x7FFF ) {
3 _$ p7 G4 [8 d" R                        output = 0x7FFF;2 ]" O/ U' G, Z( _. D
                } else if( output < -0x8000 ) {
+ z% U/ s' v. Q; X  u8 q% g# ?                        output = -0x8000;  h) f$ N5 ^; f( Z5 z  @
                }  M" d7 q* j) \6 a- [. m. H, `' U

+ f7 G+ @& @4 L                if( nBits != 8 ) {
+ e" c. j. D8 a5 p3 v                        *(SHORT*)lpBuffer = (SHORT)output;" Z- C# g$ |( m
                        lpBuffer += sizeof(SHORT);
0 S8 u( e, M/ K4 s                } else {
+ A- q' C9 s! e0 l                        *lpBuffer++ = (output>>8)^0x80;
/ Q8 U4 z6 F( ~- f" m1 S$ X: C                }
$ s0 u3 S3 @1 f: J; a/ L# d2 \1 w. L5 \! ?; D% y& r9 D
                if( nCcount < 0x0100 )! N0 _1 n  ?% o9 i6 X4 Y1 f
                        pSoundBuf[nCcount++] = (SHORT)output;0 K+ t9 B: K% `6 R; [; t
7 z& e6 m# n/ A  `  c
//                elapsedtime += cycle_rate;
* O% b) C( f9 n9 d- w" I+ u9 p                elapsed_time += cycle_rate;
* E, c% Z3 _& \/ h- _2 `1 `- W        }& A0 Y3 e9 n7 }0 ~. G

6 o1 J) B/ @8 ?5 {- |#if        1* _9 Z2 T6 c9 d! i
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* v' J% ?% p6 y+ ^2 C                elapsed_time = nes->cpu->GetTotalCycles();
1 x" ^3 c* m! b1 V% ?        }3 z7 f( [, y5 M' x# T  f! o
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
0 Q- [; g! I; q+ [1 w6 u6 F                elapsed_time = nes->cpu->GetTotalCycles();
2 o  J6 G0 S, u5 F  V' D* p        }
$ `+ L/ ^1 ?: G  D. t& A#else
' f, z1 X$ ~' M5 K& P% D        elapsed_time = nes->cpu->GetTotalCycles();
8 O5 j' C- Y( G3 a2 O! @#endif
# e  u2 z- l- X+ W/ j}
9 `- R3 W% W* U0 ^- i: {( l+ m& Z8 T" T' j
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
' g9 \' ^0 ~$ B3 G, f+ uINT        APU::GetChannelFrequency( INT no )7 p: E; m$ N/ T# s9 \! G
{) ^! e% x. ~2 F# q; l
        if( !m_bMute[0] )
0 Y# P/ o0 Z9 E- W1 L8 D                return        0;
# q! S' s0 }+ m% x+ Y- }
4 S0 i- e! q& [2 b        // Internal
$ u$ G- X) J8 {5 l0 F+ P; L        if( no < 5 ) {
% Z/ Q' y* v" g. `9 v8 u                return        m_bMute[no+1]?internal.GetFreq( no ):0;% X0 G  {% I, i% [+ ^/ H& `
        }
- P8 a/ o( d: F        // VRC60 ^) a" K0 i3 G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
- F0 g; o$ m# \8 l: X: m! D: g0 W                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;7 L+ i' q$ @0 G1 f* y
        }
# Y' H; q$ u& S7 y: @+ y1 W' F        // FDS! \; d% K8 V- E/ L4 i' u
        if( (exsound_select & 0x04) && no == 0x300 ) {
" O8 T, z/ G! O2 }) ~                return        m_bMute[6]?fds.GetFreq( 0 ):0;, a3 H( O1 P: i3 I2 L7 n' j  F
        }
# ^2 |. \2 c) O+ I. L: A        // MMC5
8 A1 }* Z# Y! P. T" w- M+ O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {9 R- U! O0 M3 }. U
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;( l9 [' D! E; s' z. I( o
        }  q  T/ ^1 X& R( g2 s
        // N106
* }' ?* _3 b7 i9 {" B: }, _% b        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) c: w$ A7 u, o, b. m" V
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 `- m! C6 G) _6 x        }
0 d, W4 Z0 w* Y1 \        // FME7
9 }0 \" m$ n1 Y; t  u        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* L. \, @3 e( z8 s$ H0 ]' N$ \
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) \: U% C. w" B4 W
        }
) T5 W0 q" B# w: m  N3 U        // VRC7
7 G4 C3 U, d8 j1 a: Z$ N        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {; c9 Q; _( H0 o/ e# j
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 f! U" u  E3 V' f7 T        }
( I9 G- r5 r' K" V6 E        return        0;  |0 J* X3 B+ g5 _7 V+ h2 ~! e9 H
}) G9 e$ m2 t. \* [  a! c" S1 I

* a8 y. n2 G# W6 Z( H; F$ u! L// State Save/Load
' e2 b! ~/ r- Q! g  D; j7 vvoid        APU::SaveState( LPBYTE p )
, t! F9 a: F7 H8 G% p" s% \{+ R8 e9 n" ^+ }2 o, C! H3 D! _6 a
#ifdef        _DEBUG
; H! E( D/ `: }- v" ZLPBYTE        pold = p;  B/ H! {; S* E$ ~/ z1 z5 N
#endif+ S* B" {6 [2 M

' R7 _- z. h5 w        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞3 i+ g- _& P% d5 s$ B1 A& ]2 x
        QueueFlush();1 E" k/ {( B8 Q' ?) q* z* w

3 @7 \+ L1 T# P( |        internal.SaveState( p );  z: i& A) q) [5 i! I* x8 J
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ y, j* \  q0 Z* f- V! w; Y7 Z

* P6 t# B2 C% T( s        // VRC6
! f# @- s( C1 y  I9 h3 u2 h        if( exsound_select & 0x01 ) {8 I+ F5 N" f6 [& }
                vrc6.SaveState( p );: d4 M& i( T7 R  j3 R$ D- z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 P) `# ]3 F. _7 \) a  u# d
        }
) P# _( v7 X7 T1 a3 q        // VRC7 (not support)0 d) v& {6 ]% E3 e- l5 R$ h
        if( exsound_select & 0x02 ) {# P- r! h6 ^4 q' d7 F: c
                vrc7.SaveState( p );# }9 |' O5 t& @5 T, `8 x5 u
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 y6 x+ i1 ^/ B1 n/ u' c5 v' `
        }
) l* z% l/ V7 k; J6 u        // FDS
1 N, ?0 g& e0 v8 R        if( exsound_select & 0x04 ) {
" h. j$ B) q: L; Z1 F! }2 V1 H                fds.SaveState( p );
; r5 y: g1 R* e; u                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 K- O& H& Q8 O/ |7 E: ^% O/ ~4 r        }
/ o# e7 k  B1 X2 n% z9 G        // MMC5& |8 P! e, B/ m
        if( exsound_select & 0x08 ) {
! |) O9 ~- G8 y8 A7 x4 G8 Z                mmc5.SaveState( p );( h: Z* ]7 m1 h# E- [4 D
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: @$ \, L+ K9 o4 X% R
        }' M, H% M! _4 C+ e% n* p
        // N1061 V: g. ~* l2 I% d$ g( ?# Q
        if( exsound_select & 0x10 ) {/ y7 O9 N9 z4 {9 a: j; V
                n106.SaveState( p );
; }# m: [; N8 n3 n: f$ Z; Z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* M! F9 W$ h# l
        }) r0 G0 c; s& d# S# b8 M3 {8 W
        // FME7
% u# V3 B3 y" K, H: @, o        if( exsound_select & 0x20 ) {/ ^; T8 L; M0 X  d' ^/ W, k
                fme7.SaveState( p );
" |4 `' u8 D" t$ Q5 q& Z% r4 X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 R* d( W' M% W        }
$ Q: n6 ~0 M  ^4 A% U
9 W* W! k; f. V( @- ^6 H+ m#ifdef        _DEBUG
5 W$ D+ X' y2 ]# A1 `8 zDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );. d9 [  j; Y/ g# |$ A' e" H
#endif
& y6 y9 F6 d1 T+ H- }, I}
9 e% ^! {) j/ a4 A4 ]+ X2 F+ T% |  s" s7 s% Q5 r. B
void        APU::LoadState( LPBYTE p )
- E% a! o5 P' @2 O1 t4 |% r) g9 u{' _1 A/ \! q, z% {- m7 I6 K
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
- P  s1 k, V6 W& D& F. L7 Z+ m0 y1 X        QueueClear();
' Y- b) G8 e- M( @- T+ l" m4 s1 Y" l% S; U
        internal.LoadState( p );9 ~3 m' K7 Q& \5 M2 G% Z  B
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
- E9 x/ Q& a! i3 K( o
1 [" X6 F% S, q7 F( _        // VRC6$ [! O7 v' v) U9 c* E
        if( exsound_select & 0x01 ) {
# ]! j0 W! Z, n* r4 E7 e; L                vrc6.LoadState( p );
9 f* P' X) q8 w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  K; E1 A/ K: a- a        }
3 O. m; n$ i0 ?& ^; {# C        // VRC7 (not support)
# f  N( g; p: E2 Q* Q" h7 v4 D5 u        if( exsound_select & 0x02 ) {# y- r$ X. F! R; H7 E7 N7 N
                vrc7.LoadState( p );- X/ w% j8 [# x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# N1 v; `4 V/ i5 |! u& j5 J        }) ?* q% Z0 t" o4 p" a5 x/ o! B
        // FDS
$ e8 b* b; r1 i: l: @5 P% q        if( exsound_select & 0x04 ) {
+ W! c' V3 @! h5 k0 Q" v                fds.LoadState( p );
: v# O$ ~, o) S8 i! ^) o                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* ]/ \. T3 c3 F! P8 C& a
        }6 a8 ?4 {' I2 g. u* Y2 L9 B
        // MMC58 I; x! o- q! q' f8 P3 o' ?
        if( exsound_select & 0x08 ) {
& x# _" W8 q9 G4 e! I                mmc5.LoadState( p );$ P1 N7 E2 M2 L6 C
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, q! T5 Q- ~' Q, h2 \/ r
        }
3 M! O2 v; B* `/ P        // N106. m6 L3 v' F% V6 l- \: n
        if( exsound_select & 0x10 ) {
* R2 Y: ^! q' |                n106.LoadState( p );: a5 z/ W9 p" H. K4 }/ O- [
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 [2 R. C3 l) N0 E        }' [  _( E, o1 m% E
        // FME7
# X1 K9 f7 Y3 ]; E2 d6 L2 l- L( }        if( exsound_select & 0x20 ) {
; K4 K1 E' O. D; j7 V                fme7.LoadState( p );3 K( b$ |8 Y8 |9 s6 q3 E9 y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  u5 i9 B3 J- V+ _
        }& \, C& H7 Q* `7 R  P! W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % s( k4 L% l8 Q; h
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
) m, m( m1 A- w) E" D& \感激不尽~~
# }4 W5 A: e/ t4 r) Q
恩 我對模擬器不是很有研究," W, u, C* M1 J  c
雖然要了解源碼內容,可能不是很困難,
$ O5 E! y9 F3 p# l不過還是要花時間,個人目前蠻忙碌的。" y+ N* u, z# F5 U  E
3 _! }- W2 t* a( @0 T( O$ n
給你一個朋友的MSN,你可以跟他討論看看,
4 q+ F/ E0 S& y2 J% `" B他本身是程式設計師,也對FC模擬器很有興趣。; N# w! \5 S" G$ p0 m) t( |3 R

( t9 y8 t7 z) {0 e1 kMSN我就PM到你的信箱了。
, q# t9 j$ \: K" F; H1 w8 b
# N5 K# J0 |; l; {3 ?, I希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 2 W  m9 L- I# \; b
呵…… 谢过团长大人~~

1 ~; O, W$ K6 ?& m7 `) ~" i, D% {# a! `  M# d4 G
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 " j% y4 q) ~: W
团长的朋友都是神,那团长就是神的boss。
9 t, S( f; z- a+ x
哈 不敢當,我只是個平凡人,
( L# t4 p# O1 E% a6 N9 ?: W要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# l0 B% y4 x' N8 B; x8 ^0 T# u" N- NZYH
7 X+ t1 K7 L( X" c/ RQQ:4147343066 i! L! }( y- l5 r4 S" {: I1 R  I. N
Mail:zyh-01@126.com
9 E3 J% v6 d  x$ d9 M5 `4 Q
0 @: P& W! b# d* J6 o% V, Z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 m) ]* r- v. w# }, }7 d+ K/ J
再次对团长大人和悠悠哥的无私帮助表示感谢~~
4 a  L7 S- N- p
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-6-27 13:58 , Processed in 1.089844 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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