EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 Q' q- s6 E# W' o* S7 I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' O3 i' b, v6 F) a+ s% @, v这里有相应的模拟器源码,就当送给大侠了~~
4 M+ K' W7 R8 S; X! z6 Rhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 T2 V+ [+ ?# B- {能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! H7 N7 j0 A; R& a3 w% b' b
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
2 x5 b3 }+ F  e- v这里有相应的模拟器源码,就当送给大侠 ...

, g' [* u- [/ a- m8 D5 w" o聲音部分(Audoi Process Unit = APU):' \* J: o% Q6 Q: D! ?" V. \
.\NES\APU.cpp( H* M" O1 }! h; U
.\NES\APU.h+ D8 ^4 p6 @- u* v- _

9 q% h! k, e5 t6 x# g, i! ^- _( m/ P  ^$ K8 O, f
影像處理部份(Picture Processing Unit = PPU):& H! a( ]8 P% `. B: X! ?" ]
.\NES\PPU.cpp9 b# B8 O7 E& [
.\NES\PPU.h
% z% ]0 Q. x0 e9 s
5 x3 {8 e' w- Y) \# t/ x; z如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  X; i& v5 \; C- v9 @
(由于很多专用术语和算法机理都不明白,所以看不大懂……)) b* Q2 \0 a7 h1 y; x
//////////////////////////////////////////////////////////////////////////
1 ^+ T: I, ^  d8 Z( _//                                                                      //9 Q* G. g: o/ H. s/ v) p8 v
//      NES APU core                                                    //
- \6 j# Z- j# H$ X6 f, J# L& v//                                                           Norix      //
; w7 e% k, z2 Q$ Z" k4 I7 q//                                               written     2002/06/27 //0 _4 h% `  X3 w
//                                               last modify ----/--/-- //
( B2 w& S5 s6 W6 j# W! Y! O//////////////////////////////////////////////////////////////////////////+ F* n( r3 `/ \; M
#include "DebugOut.h"
4 m6 A, ^7 o4 Q5 c#include "App.h"
6 ~- i% `1 f7 @7 i* J#include "Config.h"
" C! ]/ c% \- T* p! p2 `5 B2 ?( }2 M; N- O) T# v
#include "nes.h"# D0 B- T% J+ t6 E9 W& I
#include "mmu.h"8 D7 t! h2 Z0 L* Q$ D
#include "cpu.h"/ ]( j6 |, Z3 `; T& ~/ {
#include "ppu.h"7 [- a, ?! S& q: P4 \- d" l
#include "rom.h"
. ~) S5 R& S$ a. B6 A% k#include "apu.h"
+ A* W) G4 G9 j+ w- v0 Z1 C+ G. x4 T) J
// Volume adjust
3 v% f1 S2 F' T3 I// Internal sounds7 H# V! i& m' f& f9 r5 y
#define        RECTANGLE_VOL        (0x0F0)
  H- d$ e5 U% K, F) w# M6 N# e#define        TRIANGLE_VOL        (0x130)
9 G& j' n6 Z1 z3 I6 `/ I#define        NOISE_VOL        (0x0C0)
" ?: j' `+ M+ C0 ^$ i6 L0 I#define        DPCM_VOL        (0x0F0)8 q6 d( _  \3 E2 i1 ^- @8 r
// Extra sounds3 P+ H( U& B* n
#define        VRC6_VOL        (0x0F0)
! \/ @9 c  R3 b* {+ |8 S#define        VRC7_VOL        (0x130)( v. g) g$ q& q' O) A) I
#define        FDS_VOL                (0x0F0)+ }7 \! T* n  w9 c) h" m+ s( d+ W
#define        MMC5_VOL        (0x0F0)
9 v" b, f: k! V: c# r: Y: v/ S#define        N106_VOL        (0x088)5 m7 W$ d% B* a/ J0 G
#define        FME7_VOL        (0x130)
0 e2 r* n' P% l! s0 H$ ~
7 g! X4 k8 h# Y- @APU::APU( NES* parent ): f* U$ `! O: t5 |: J% l( c
{; I$ V4 l7 R  o" N) p
        exsound_select = 0;
# m& F- b6 s+ e* ]" \, c; |0 q, s1 d. S* e3 h8 s
        nes = parent;
- b" g2 b  A$ f        internal.SetParent( parent );+ t5 N/ H" V1 v
& @& \9 r- L2 p4 S& t
        last_data = last_diff = 0;
6 h( w9 `% q7 L/ `' c+ V2 @) h& M) @5 s$ v. v
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
; `) V: W- l" L5 d' _. k  Y, R' k& Q( i! [+ c+ W2 ?
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( C6 Y" M+ }: g! G
        ZEROMEMORY( &queue, sizeof(queue) );
+ w. |# X; w! y& ]2 Q8 y        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) A0 f  Y! U4 ]* ~! d
$ T7 K" I' N# H& v3 j        for( INT i = 0; i < 16; i++ ) {6 M- O4 O9 p# P5 ]: |6 ?
                m_bMute = TRUE;
% @) V. T& @3 e2 b. {        }" |, ]) v# d' t4 G6 ~- U2 z
}
# r1 [* X. ], w) v6 u6 e2 k) {3 ?0 Y1 ]0 Z7 U) L
APU::~APU()5 m  d* }' g" ~
{" |. b! A6 a7 L8 ?
}
% [. t2 M7 K  r
6 I2 H8 `6 H/ f+ X: r# Kvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
! P) {# i9 @' H{- s+ k( a( V* C9 s: \+ N3 O: d. A
        queue.data[queue.wrptr].time = writetime;. s  j3 d5 ?: `) e7 M9 K
        queue.data[queue.wrptr].addr = addr;% _' Y4 w" ]8 }( \2 X( F* e
        queue.data[queue.wrptr].data = data;1 b6 K/ y, D: {  V5 {% b
        queue.wrptr++;
; A% t% H0 Y: A9 O' M        queue.wrptr&=QUEUE_LENGTH-1;
' G7 o: w( v% H& H: |        if( queue.wrptr == queue.rdptr ) {
8 m* j" ]8 M) T6 ?- I  Y3 V3 p$ J* Z  `                DEBUGOUT( "queue overflow.\n" );/ C7 B, R2 {6 c6 C, a
        }+ {; \3 D5 r: F
}  ]7 j/ u2 I2 E* k  v% Y3 }

- h# g$ f- g  SBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
" o+ V2 j7 L0 s3 D4 g" F{  w8 W( V$ w; f6 a
        if( queue.wrptr == queue.rdptr ) {
, t& b0 R- ^- F2 O' l4 S1 ~                return        FALSE;
/ J5 c/ I0 q% C' }1 F1 V9 |; R        }0 a, K" g% Q- R1 s+ l& Y7 \0 ^
        if( queue.data[queue.rdptr].time <= writetime ) {7 M; g! P% t1 @9 V
                ret = queue.data[queue.rdptr];# _; H  L/ K  y5 a3 i. u! b
                queue.rdptr++;
5 h+ M2 y  T' ^8 n; Z8 M' H                queue.rdptr&=QUEUE_LENGTH-1;+ ^. o& U' y( ?  W5 q5 u1 P6 e( O
                return        TRUE;; l3 f; @% t, k( n# P
        }
  v" U$ f- B+ J3 D8 ^8 w8 {  J% w        return        FALSE;6 T  L% S3 m! N5 F  ~3 `/ E9 A
}! U  ~" S( M' l& R; a# p3 x% H+ n: B

# I& n- m. }/ L6 Rvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )' @" R( q0 {" J# P* m
{( w# k7 e; {+ i+ @7 h, }3 `  E
        exqueue.data[exqueue.wrptr].time = writetime;) B; z/ o+ D" Y
        exqueue.data[exqueue.wrptr].addr = addr;( v- `: r+ f# G, [& y. f& w- C
        exqueue.data[exqueue.wrptr].data = data;7 ^; v( g7 F1 X: J' S
        exqueue.wrptr++;; w" N6 [8 w6 I7 T
        exqueue.wrptr&=QUEUE_LENGTH-1;- C3 u% n, k; J% v5 K+ _
        if( exqueue.wrptr == exqueue.rdptr ) {. S/ G( ?! N0 {; A  m. [# d
                DEBUGOUT( "exqueue overflow.\n" );4 p! C3 {8 Y! b% ]6 [
        }
/ J# }5 |5 M/ o6 |/ g/ O. p( ~}
( c" k# {8 {! d$ L$ q6 m; W& q: ?  p. i7 M9 G; @
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
% D% H0 i4 g4 y) W{
5 D3 q) z: i6 v        if( exqueue.wrptr == exqueue.rdptr ) {
& E8 j4 [/ n! J, N& r2 S8 F! F9 b                return        FALSE;
" s$ y* c9 E% g$ v7 \        }
$ e3 n) k$ Y! l4 j4 p        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
* p  n4 H5 N1 @9 ?. t$ h# u' k) i                ret = exqueue.data[exqueue.rdptr];
" H0 h0 l9 K/ F. Q                exqueue.rdptr++;- @4 G& @. y+ U! o2 p
                exqueue.rdptr&=QUEUE_LENGTH-1;
, N& \* r' ^: H' S9 d7 \8 t( {2 m                return        TRUE;+ S0 {( ^5 [$ v' p
        }
" P( c# v0 {; Z0 t. f, j9 m+ x2 O        return        FALSE;
# D: q+ H2 k* v( G/ o( A}
* T" V& O6 B8 m! Q2 N/ B+ }6 h7 v* w: ~8 r
void        APU::QueueClear()
( K5 \" e: ]- G, ~! f" b# j6 ?{5 x4 i, \' r+ M5 `4 \7 C1 \& F
        ZEROMEMORY( &queue, sizeof(queue) );
, c: D* s  A5 @1 d/ {! Y/ y: U        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 m0 ]; s  n( N+ `& C7 ?}/ T: b, V0 S% ?. d% y

3 s$ b* E* C% s% I( c2 Cvoid        APU::QueueFlush()' d5 ?! m* t" C: @0 i, ^
{6 A4 u* t7 r; F/ j4 m, r
        while( queue.wrptr != queue.rdptr ) {- Z5 J, o# H; m9 H. n( T
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
- A+ t# o; V, r7 H9 g. W$ b2 D                queue.rdptr++;
, \4 q  f; A  S+ V3 ?" }* y                queue.rdptr&=QUEUE_LENGTH-1;
4 |. {6 a' ^* q& n0 ?, G        }
# L' V5 B2 ?0 P  e. Q, y' H
, Y  Z3 n* K; H8 G# d& }- ]5 t        while( exqueue.wrptr != exqueue.rdptr ) {
5 w5 q2 W" Q8 ~* s0 a) f                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* K0 }" t/ e( A2 I/ o9 g, u* S                exqueue.rdptr++;
: O! f& ?& {: K6 h1 d                exqueue.rdptr&=QUEUE_LENGTH-1;: s9 j0 e6 W% z5 c5 k
        }7 f% F7 l  \8 G1 {4 s
}6 O, ^! {# {! _' |$ |, U' F3 j

) l7 C( s0 v. E  x# s6 gvoid        APU::SoundSetup()
% t- @: z+ n0 O# j% l4 v- \{+ C) @: ]. V6 M' w' G! v8 ]2 s1 Y
        FLOAT        fClock = nes->nescfg->CpuClock;
( D0 O; V7 T( X7 F2 o( }7 x        INT        nRate = (INT)Config.sound.nRate;
" F7 Q: O- e5 R% S5 r2 g" [! m        internal.Setup( fClock, nRate );0 q1 }! g; P4 \5 T7 ]2 W  d
        vrc6.Setup( fClock, nRate );
7 Y$ `2 a! S, n( k/ g6 Q        vrc7.Setup( fClock, nRate );
& e5 @# H5 O9 p# E        mmc5.Setup( fClock, nRate );6 U# I; W, t- \* D) M+ T1 \
        fds.Setup ( fClock, nRate );
2 S- K3 ^/ z, }& F6 D! q        n106.Setup( fClock, nRate );
7 [  V; H& k" C' j/ T        fme7.Setup( fClock, nRate );
/ `9 q& R5 }' [}3 `/ H5 t  y1 @

& P+ D% g. o5 b7 Fvoid        APU::Reset(); U5 v8 [. K4 B  x
{
! a4 w0 K" T8 X3 Y2 _+ N        ZEROMEMORY( &queue, sizeof(queue) );! J& {7 g9 i6 P) X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. z$ @8 S$ k& u" l/ s5 X* W6 N
. `9 y! \1 u# X9 t2 q
        elapsed_time = 0;% G) b7 B( {9 s* Y8 o. N
; c  _" B% \2 D" D
        FLOAT        fClock = nes->nescfg->CpuClock;
6 d' j1 B2 ]: O6 f* v2 m        INT        nRate = (INT)Config.sound.nRate;( e6 I: a1 z* q# E$ D
        internal.Reset( fClock, nRate );* U! e& k! c2 }7 O
        vrc6.Reset( fClock, nRate );+ o! a( m; p- i: k) M
        vrc7.Reset( fClock, nRate );
  t4 O2 E& g3 Y, `% I        mmc5.Reset( fClock, nRate );
2 S$ E+ h* r! X1 j, f        fds.Reset ( fClock, nRate );
8 c: V0 ~% |# h# G3 x* o( r/ F! J        n106.Reset( fClock, nRate );9 X2 l; D8 G- G: l
        fme7.Reset( fClock, nRate );# `; E( _, j. ^5 U. Q3 i
% ?/ h& q  ?; @! z, W
        SoundSetup();/ f- E% T7 t( R  Q* t8 H
}
2 C3 {+ y: H5 J  N1 m9 G( B7 J
' ]4 p4 Y+ R& ovoid        APU::SelectExSound( BYTE data )
9 N+ }$ f/ q" l1 F) H% u: x4 N5 y{! z5 z2 M% Z- o
        exsound_select = data;( @( G& i# o* Q- V* n
}
3 x, r8 F0 R- K6 R3 l5 G9 r0 k$ E6 Z
BYTE        APU::Read( WORD addr )$ Y8 V2 \. W1 O$ h! x
{
; a$ c: @( }1 d9 z        return        internal.SyncRead( addr );% ]2 }7 O7 i; c+ \) X" j3 A$ G1 }
}8 P# d, _/ ?( h- C

7 p) H4 i4 u6 v9 G0 `void        APU::Write( WORD addr, BYTE data )+ l7 E) g7 K- q4 U2 R. N' I5 C
{
- [6 Q9 g7 Q$ T        // $4018偼VirtuaNES屌桳億乕僩" e1 N) d( v7 U3 c# J! U$ Y1 L* @
        if( addr >= 0x4000 && addr <= 0x401F ) {/ _0 h% v0 s' {; A# h
                internal.SyncWrite( addr, data );
  {: I$ i! \% C4 w4 v- c9 I                SetQueue( nes->cpu->GetTotalCycles(), addr, data );' m( C4 b9 W! }  @9 T# ~
        }$ k6 L( X# s7 u( J" @3 y0 Q) \
}% b6 ~% r: ], O1 i7 R/ [  K

) e# z4 J1 ~% l8 K2 Y+ f- FBYTE        APU::ExRead( WORD addr )
0 z# n8 Z. d0 h9 S{
4 A$ J  G2 I: ?4 N' tBYTE        data = 0;+ k8 o+ O! f1 H6 h
6 t1 H' B' O+ s" W
        if( exsound_select & 0x10 ) {9 |0 y! T( _7 t/ X5 @- y+ K
                if( addr == 0x4800 ) {9 g1 f8 B* s7 Y$ Q
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
" u* @  }$ z  A. ]                }* O( X3 _3 \" r; K& l1 O
        }1 j" n5 D$ B. F: b3 T, H
        if( exsound_select & 0x04 ) {7 g! Q: {6 Z0 y# p
                if( addr >= 0x4040 && addr < 0x4100 ) {' S, L! m- y: t" ^: ], A6 D
                        data = fds.SyncRead( addr );5 ^: V$ K  q9 @" L/ O  i
                }
8 B. [9 ]2 O" s; T1 ^3 w6 k3 Y: L- J        }
) K1 b+ g& D; E9 B2 Z: u& [% }- [        if( exsound_select & 0x08 ) {9 B' i. D* W2 P: z
                if( addr >= 0x5000 && addr <= 0x5015 ) {& o9 u, A8 [& f, A& G
                        data = mmc5.SyncRead( addr );
0 J# m' C. X: P* L: l- C/ h                }' r4 K+ K. D; `
        }: F3 @- M2 F' G. K$ {
9 T. }& @. g, {2 p+ `6 R
        return        data;  p# P+ L9 z* {* k- F  A
}
* Q) z( `3 ?: v2 k* c4 s; ]- q) P& \7 J
! T* b& Q9 s2 A7 C" x  A! Ivoid        APU::ExWrite( WORD addr, BYTE data )
/ d. L- A3 s0 Z( l/ X) A9 [6 a3 v{
. t* N- {; E9 N9 \- E/ h        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& h' }0 Z( t1 j! g) h$ R- ?; f9 O/ X0 {% A2 t9 p" C2 }/ ]: [, D
        if( exsound_select & 0x04 ) {* O0 t$ G8 Z. b5 H2 w. l
                if( addr >= 0x4040 && addr < 0x4100 ) {
" z" K9 }: ^* J7 h, l; C                        fds.SyncWrite( addr, data );
2 P+ c7 ?# |0 U  q6 |) b$ j                }
) V, H" J% N+ R8 E/ _        }
! o! \! }0 B0 F+ L  O  d  ]% T7 k6 v0 }6 X
        if( exsound_select & 0x08 ) {6 s  }( b+ t% X( z, C! n5 R' B
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! q% w6 I7 o+ V) I8 P6 H/ h, }                        mmc5.SyncWrite( addr, data );" Y) o. c1 y! L, n6 W7 C. d! A9 ]
                }7 R6 R, p, v5 A: S9 Z5 V# F6 {
        }  y% m$ v% D' A$ @5 z# _
}
, Z+ [3 d0 k+ _5 H2 k
4 ^2 ^5 ^( x: q. t# _void        APU::Sync(). X! e2 w1 T% v0 T2 z# D
{% u- F( M2 W+ a( t  p# y( d0 N. k
}
; L. U  W! ?. `, r  V3 u
* e) [$ B& T. i' F2 @# _& Mvoid        APU::SyncDPCM( INT cycles )
+ H; N" E6 Q) {, B- j! a{' E' y( G+ Z( i0 x3 c" ^1 M
        internal.Sync( cycles );4 @* r  e6 M: {* e
1 b1 Z. J; T9 }" M, U
        if( exsound_select & 0x04 ) {
; Q, o: e! l# B5 t                fds.Sync( cycles );4 N) M/ b; Y! y  \3 k; X: J
        }
5 M# n3 n  T7 i& E        if( exsound_select & 0x08 ) {5 |3 W: Q4 B2 L9 @3 Q
                mmc5.Sync( cycles );$ V) A0 d, I3 b& Y' G4 j
        }
  x% e$ J: R% N" n}- f8 R# v5 i$ I+ p+ [/ d2 J+ q& x
/ S" Q4 i- ?( \- G1 N- L
void        APU::WriteProcess( WORD addr, BYTE data )
$ f9 T, c0 J- t- l+ U* b{
$ S: V; `( n1 b        // $4018偼VirtuaNES屌桳億乕僩
1 j, x0 b! E. a: U+ g; H        if( addr >= 0x4000 && addr <= 0x401F ) {8 C* ]# y2 }# Z6 R6 F
                internal.Write( addr, data );
3 y" z6 X' H! r3 l& n/ j8 C        }/ t1 k, S- ~4 y* T9 e
}
/ P( I' b3 p; C/ u9 K4 K# a
& d+ d% h) h/ yvoid        APU::WriteExProcess( WORD addr, BYTE data )
# b; g* b5 D8 T0 w6 ]  j{& m) C, v1 C4 \2 {  D( C
        if( exsound_select & 0x01 ) {
5 r. O1 b4 J) B" @                vrc6.Write( addr, data );
2 O! r3 F# a) V7 N8 o        }/ I9 p6 j, a$ B2 U7 C
        if( exsound_select & 0x02 ) {! U) Q; J+ r3 {( _( [9 |
                vrc7.Write( addr, data );
) `. `4 N8 U( ^3 @        }
& h6 q& J: t3 _) m' w0 {% @" {  j8 h        if( exsound_select & 0x04 ) {
8 L% D  n4 D0 t* i                fds.Write( addr, data );
# ~9 r/ n0 _: v  {; H1 K        }8 J' {1 X; o' \
        if( exsound_select & 0x08 ) {
& F, }! }& C8 U& J  Z                mmc5.Write( addr, data );
0 q& b3 [  g" a: e        }
7 D" k0 `( ^. r6 z7 H        if( exsound_select & 0x10 ) {& p; C' d6 G4 q. I
                if( addr == 0x0000 ) {
0 C) l) h3 r8 C! W5 {$ E. U$ G                        BYTE        dummy = n106.Read( addr );
# q: P  r& N# {* ^! w                } else {
3 G7 w' e) {/ ^: r) K8 u                        n106.Write( addr, data );
# k, I9 m1 ]4 g" u9 Z                }
/ n" z+ g4 t1 e( v        }
7 l8 Y8 g" _% [% B4 |5 L        if( exsound_select & 0x20 ) {2 B0 s) S( K! Q$ ]
                fme7.Write( addr, data );
* V; [0 B1 m& W9 [/ g        }* Z% P8 O* p8 O% E" ?7 p
}
, L) q$ T3 r; p. [' Y: e( k4 ~0 E6 t7 k( C
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 N9 j3 o' |# u" i' r: S5 h
{
; V. K& }% D( u6 u5 o! ^1 y! u, pINT        nBits = Config.sound.nBits;2 |' @$ B8 \7 l5 P6 a
DWORD        dwLength = dwSize / (nBits/8);
6 f. F2 d. q; z9 h7 I) }INT        output;
- \0 P8 c( d" P9 k" o2 VQUEUEDATA q;
6 q* p. m7 V+ d5 G; sDWORD        writetime;
& }# Q7 z& C3 C% u2 |- l& ]* u  v
8 u$ C& @# o8 T9 A  RLPSHORT        pSoundBuf = m_SoundBuffer;
( [: d" b& G: K  LINT        nCcount = 0;
/ w6 i" i3 y0 w' N4 ]. |# \4 _5 D+ G4 V
INT        nFilterType = Config.sound.nFilterType;
; r' [5 I  o2 S1 O9 N6 K; N
! N) T! D9 n2 h/ r" C        if( !Config.sound.bEnable ) {, R, t' e& p6 P/ x* e& ^
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ N+ }/ h1 p1 B; z
                return;
4 w; q1 e4 _+ T5 C( Q3 C        }+ A$ [# `6 n* R2 r1 o- J* E
3 r6 ]6 T) e# Y& l
        // Volume setup
$ @& o6 y- G& Q$ s2 U0 }        //  0:Master, q4 ]4 ^% G/ ^6 q: c/ L) `
        //  1:Rectangle 1. L' O; a5 P3 Z7 a6 {, f. k9 n1 ^
        //  2:Rectangle 2
/ `0 j9 R% W" _9 j, G: i        //  3:Triangle) z( t* P7 Z2 Z- @0 ]
        //  4:Noise
! y! g5 H$ t0 `        //  5:DPCM
: h  N( P9 I3 z/ _3 E5 F        //  6:VRC6
! }3 y( [9 ^9 z2 f" m! @        //  7:VRC7
" A; I# V% i- }( E& x3 C; H        //  8:FDS* \8 @8 H2 ^! Z8 }! Q5 V( r
        //  9:MMC5
0 s' U4 S# D' z        // 10:N106
4 S& x8 t* \# H: _6 w        // 11:FME7) U, S" s+ A, W3 t  L9 B, ]3 @
        INT        vol[24];- }8 n- r* e& X* Y% _  P& l
        BOOL*        bMute = m_bMute;. U$ T! J/ @2 W" [, b
        SHORT*        nVolume = Config.sound.nVolume;# _! e8 h* V$ p7 f, S5 C6 K

6 ^6 R" `5 Y, T! ^+ v- p! [        INT        nMasterVolume = bMute[0]?nVolume[0]:0;$ G, S0 F9 j7 D: ?' B3 _
+ K3 u9 f- q2 P4 ~9 b1 J  z- o6 n
        // Internal/ [( X" i+ v/ R9 n) ?5 U7 O& R
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
+ E1 S  q. i1 q0 `- V$ r        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
" ]( V, h, D3 S- J/ ~0 g        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 B" r' a2 x8 {& D" j: O        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;% R5 I6 n" j0 A, q5 D8 O; U; Y
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;/ ?+ v: `1 R0 `: P, g2 |
1 H: ~1 \$ |. l+ l5 B/ @. [; P4 o
        // VRC66 w, C% S) K9 O2 M  }  R
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 S- K6 E7 r6 ^# n4 d8 N7 R        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# Q' z; V; h7 C& h: i  S7 k
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: s4 u" t3 Y" Y! A: l+ E

4 C3 s% F7 n# h. W) s) ?        // VRC7
. f3 i# C5 n) ^        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
" t  [  K- O$ C: }2 q+ h5 `) J$ E: D- E! m
        // FDS
. l6 E8 L, m# h4 q  g* _8 _, U        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
8 S5 ~0 O9 W7 s% z: ]$ X. k, d* {& J* @
        // MMC5
  s: P! \- g; A+ @7 j        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 ]! H( A& X3 d" g, w        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 B' a, [% g1 n) |( q        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* J$ Z- L8 M) `) s  w( _# ?. K
        // N106. n' P5 |% Q" q5 S
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- Z0 x* g7 O* x$ [6 p
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; x" h  `. j) O. z& f        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; N: I$ X/ B% Y6 d! X& g
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# s5 e- {7 }4 ~3 q        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% T4 R( {( \* h' x( M# K! k% F, a
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! e1 H2 ]( J& C, ?9 j& \  C        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' s7 l0 \) E( M3 d
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 b5 q+ ^6 ~" X/ e
" o, h0 q+ f) F( ?! J5 f
        // FME7
0 G0 d+ L/ ]8 R5 P# `. [" F8 x8 i- L        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, M" [3 A$ w/ L        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 O& r. U; b: @" ^
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; p; ~( I: `% I3 ]7 @' f0 u' _# J4 Z; z+ H( @: ]
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, ~& V4 g. w5 Z) H( `% |
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;1 p: e2 @) B, F: J* [

4 r$ X% R0 j% L  b* R( w( V# R        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
6 p, j) {; v& g/ W7 O- M        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
1 m& s, C$ L1 i0 n                QueueFlush();. l7 ^& e2 i) Q# f* B7 Q
        }
0 _/ T6 K6 _5 `2 D( m$ j/ M, A' Z& V
        while( dwLength-- ) {
& T/ t$ @( V2 v% m  z                writetime = (DWORD)elapsed_time;7 o$ A) |# f* Z2 m0 E

# S) l9 Y3 f/ f                while( GetQueue( writetime, q ) ) {2 X$ U) q$ H$ m9 l0 H6 B  l  b2 l
                        WriteProcess( q.addr, q.data );0 t; P5 f5 n# w3 s, C* r6 {+ c; ~5 p
                }
7 z* ?  g* x/ n6 G" h$ {6 S
/ U! V9 U; y/ [; y6 I# }5 B                while( GetExQueue( writetime, q ) ) {, P' y/ X, q+ v' P, K, n  z/ o
                        WriteExProcess( q.addr, q.data );
+ a  X  o0 h, F# T3 W7 j                }$ y+ j& F3 h) M& g

% w+ I, m! N% U                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
. C% i' `0 z8 x$ x* o9 n; @( H5 }                output = 0;4 `/ E+ ^* U9 |: V0 J
                output += internal.Process( 0 )*vol[0];
3 |2 T6 H* _6 Z1 O$ q! j3 q                output += internal.Process( 1 )*vol[1];
! Z8 w; y; d- O  @6 n                output += internal.Process( 2 )*vol[2];# S/ d- P1 W1 k; J' l8 l. I1 o
                output += internal.Process( 3 )*vol[3];/ o8 F* A7 |# j$ V' O
                output += internal.Process( 4 )*vol[4];8 m7 {, u( ?0 h2 L3 x3 E( A
6 u+ [4 W! f9 C- B5 W! j7 X- L; [+ U' O
                if( exsound_select & 0x01 ) {9 Y5 n6 l& B4 ?* w; Y/ o
                        output += vrc6.Process( 0 )*vol[5];
8 H6 Y6 ~2 H" k2 R; m                        output += vrc6.Process( 1 )*vol[6];
: ^! m+ u: r1 X% O5 @                        output += vrc6.Process( 2 )*vol[7];+ Z3 g: K8 w4 r
                }0 z4 n6 Q+ F0 t3 n
                if( exsound_select & 0x02 ) {$ k: A$ O  [% F2 \# a2 f5 n1 C
                        output += vrc7.Process( 0 )*vol[8];
6 M- c8 x/ M: e' ~                }
/ q' ?4 M; Y6 E6 Y% o& c                if( exsound_select & 0x04 ) {
9 l$ g+ g" E# R4 v5 e                        output += fds.Process( 0 )*vol[9];
5 ~! c1 P3 A2 _* e' e                }) }5 a: E; f6 n% M& F6 z/ D/ V
                if( exsound_select & 0x08 ) {+ ~4 @% @! u$ i2 Z5 Z2 x6 w5 q7 O
                        output += mmc5.Process( 0 )*vol[10];
$ |, }: T5 P1 W7 X; ?                        output += mmc5.Process( 1 )*vol[11];
' L8 q2 j) P* g                        output += mmc5.Process( 2 )*vol[12];
1 V, U* _6 b7 |- b& ]  r8 K                }7 z) K& m: T7 L6 X8 j% n& _
                if( exsound_select & 0x10 ) {3 u2 l/ F3 ^+ V# T3 v, `' ?
                        output += n106.Process( 0 )*vol[13];
8 e  M: U7 L! p                        output += n106.Process( 1 )*vol[14];( p- U9 f  `' v  X8 n
                        output += n106.Process( 2 )*vol[15];3 `8 y1 H3 e& N4 N/ `; d
                        output += n106.Process( 3 )*vol[16];$ F2 T0 q3 f) K  i" x( j
                        output += n106.Process( 4 )*vol[17];' n* A" ~% `: q/ w1 N
                        output += n106.Process( 5 )*vol[18];
/ t4 r  V% v  Q* |7 |$ y7 o+ F                        output += n106.Process( 6 )*vol[19];
% D" C" a( q& F9 {* J7 H                        output += n106.Process( 7 )*vol[20];* b1 V( i% N5 E9 o0 a% ]! W, G+ @
                }
5 O& C7 m) f- n                if( exsound_select & 0x20 ) {
4 n& e8 {1 c& j: }9 J* d5 h                        fme7.Process( 3 );        // Envelope & Noise
. @; W1 g- @( s                        output += fme7.Process( 0 )*vol[21];
+ L2 i+ J2 H  K                        output += fme7.Process( 1 )*vol[22];; N4 \% {9 ], B
                        output += fme7.Process( 2 )*vol[23];9 D0 L/ N$ K2 M  _( b* Q
                }, R$ Q9 i% U9 M( I  b. v% F; q

( S$ P+ ~+ B$ I2 R3 c                output >>= 8;
$ d# O, F. J2 S
: B, H& D1 J' T! q$ P) E                if( nFilterType == 1 ) {
/ G' X3 ]( P4 b7 o* {5 F" p  @                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
+ c2 [4 V- U1 b                        output = (lowpass_filter[0]+output)/2;5 a& m' o' F8 d( ?* h+ |& o
                        lowpass_filter[0] = output;+ U5 F* p$ S  f; A3 Y
                } else if( nFilterType == 2 ) {
4 x3 `3 s. u+ Z( p- h                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 ^2 k6 N# U" }0 ]                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
3 c/ `9 W2 p- Y  H9 P  c' e$ R                        lowpass_filter[1] = lowpass_filter[0];
+ Y5 h$ |  J: Q5 C9 ^* _  r/ r                        lowpass_filter[0] = output;
& W, t* I# p. T, p- t                } else if( nFilterType == 3 ) {7 P1 G' g* t; p7 @& }& H4 Q
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 u4 r/ _" X; @3 X( M; n
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;/ q, O8 J. `) ^* K( O2 E
                        lowpass_filter[2] = lowpass_filter[1];
" i5 k  {3 S& V4 [                        lowpass_filter[1] = lowpass_filter[0];* O: T( u9 F' ]
                        lowpass_filter[0] = output;$ H1 L7 G% ^1 C, |* W) ~
                } else if( nFilterType == 4 ) {( T. F7 z4 Z- ~  x& x0 n4 |
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# ]/ |8 ?+ _' w% T
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
' Y3 I) x4 v% l- G                        lowpass_filter[1] = lowpass_filter[0];/ b0 u, M; p: P4 o7 s5 O
                        lowpass_filter[0] = output;
5 C5 f$ m* r: o6 a                }: y: q* g( C; i% d( P( X
# A: e8 i+ H1 v0 O: J) U' {5 X
#if        02 A6 v5 M+ `5 B4 \$ e7 J- l6 P
                // DC惉暘偺僇僢僩& d+ A* Z" N7 X5 u1 ?
                {6 o% p! Z# W. ^( q5 g6 I# w( [
                static double ave = 0.0, max=0.0, min=0.0;
/ a: J5 k, ?0 i5 `                double delta;9 ^/ n  A9 f3 h  i* R
                delta = (max-min)/32768.0;$ a! \* p) B- M% W4 q" u6 }7 B
                max -= delta;! x# \7 W8 J2 d) w2 E$ i
                min += delta;. f9 h+ M# Y; J
                if( output > max ) max = output;3 o, n7 ]+ ~' L. [' I9 A" G
                if( output < min ) min = output;
4 e. N, L5 Y. d; X# \) z                ave -= ave/1024.0;1 c8 s$ C6 y0 v: y
                ave += (max+min)/2048.0;
2 Y- J% S6 k; z, L+ ?                output -= (INT)ave;
' r# H. O% w/ b                }
( u3 `* t7 R: V  F#endif: q5 z4 Q; d9 k9 S2 X: E
#if        1
8 X# |0 g. i. s# }# W                // DC惉暘偺僇僢僩(HPF TEST)2 w; }7 `! @% `& K) H5 Z! }0 f) E+ e
                {0 o, o, g3 {# U( N# P5 q6 \
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);6 x+ o0 U3 r; q- h; M( n$ V0 N
                static        double        cutofftemp = (2.0*3.141592653579*40.0);6 b. E, o4 o) s+ Y8 t# d! N$ M" [
                double        cutoff = cutofftemp/(double)Config.sound.nRate;- {8 N6 D) K0 W6 v5 I# a) Y# x
                static        double        tmp = 0.0;
) \8 z2 Y* h4 e                double        in, out;# b7 z+ E: g7 P. V
3 w) t( g) B8 C) b
                in = (double)output;
% `' G- \7 G) E$ G                out = (in - tmp);
6 }, ^$ k9 d8 ^# s& `* G; r                tmp = tmp + cutoff * out;8 }' M) O. r- @
7 U, k) f3 }3 m) J2 ^2 V( K, k
                output = (INT)out;- M& I+ a( L, e0 r: _5 w" {7 l# b+ {9 b
                }
! |! ]! j/ c( a7 w#endif
, a$ j4 v& y% c/ Y  w#if        0
* S6 c  H/ R) v; \                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
7 j9 P: J8 w6 y) B. W1 l4 F                {
2 Q4 b' s! j+ `" N! p+ y% E9 R# D1 n                INT        diff = abs(output-last_data);. i# T) S) f5 [! R/ X
                if( diff > 0x4000 ) {
& j' m8 w) \. A4 j                        output /= 4;9 w' w9 w: T" n8 i
                } else # M* }6 k8 o9 m& `: y& l# [* T( w/ B
                if( diff > 0x3000 ) {
. x( N' c  ]' W; _1 T                        output /= 3;: |' |9 U( \% J+ `9 \7 ]
                } else
( X/ o% [, t! F0 e! X4 k* l- \                if( diff > 0x2000 ) {
( g, l! b/ P) |8 w                        output /= 2;
% d* t+ x( ?, k4 z( A/ Z' J                }0 ~$ \5 G" e0 Z" k
                last_data = output;, Y, s' d4 Y8 C8 c- X
                }
  r# a& O, \4 T2 ]0 I$ R#endif" A9 |# F" V' y1 d. M
                // Limit
9 z+ ]) S' M# h$ H                if( output > 0x7FFF ) {% ~% U9 K: M( g3 E
                        output = 0x7FFF;
7 D5 |# x( p) g3 J                } else if( output < -0x8000 ) {, U2 Q1 ^" o% Y5 W* A" f
                        output = -0x8000;3 p8 e' v& s( v
                }  \* p9 r. q6 }) \2 u3 l
; L3 O$ V4 l/ |+ _. a7 L! K
                if( nBits != 8 ) {
# _( |! }( a, i! w! g& M                        *(SHORT*)lpBuffer = (SHORT)output;$ I- `. S, D- i8 g
                        lpBuffer += sizeof(SHORT);1 _7 J& P) f4 S+ E; V+ C
                } else {+ H: t& d0 Y+ {( @( s! i9 w( F
                        *lpBuffer++ = (output>>8)^0x80;
  z4 b+ l; D* ^: x  I; `                }2 m/ z3 E* j2 X) W
) k6 U8 l3 c, E' O2 u
                if( nCcount < 0x0100 )
: L% P. d! Q  {! i3 d- L) \                        pSoundBuf[nCcount++] = (SHORT)output;
4 u' R1 O  ?6 b* w6 j; v: A7 y
/ k4 c; L+ l) S5 j//                elapsedtime += cycle_rate;
& u* [$ X6 |; {0 M" x5 W. n0 T                elapsed_time += cycle_rate;
6 g2 j! a' E- `- o- t        }
6 l) F0 Y2 @& W2 C0 ?
" e5 r4 s3 D1 ]2 d3 }5 T#if        15 R' d$ q+ a( H% ], g8 b
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
' @$ r- u) o  Q                elapsed_time = nes->cpu->GetTotalCycles();( R7 v0 N* d6 A4 N4 `2 M' b, G
        }
; }1 M* J3 O  `# t8 ~4 K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {- k8 I/ F- g6 ~
                elapsed_time = nes->cpu->GetTotalCycles();
' w6 `# a; u8 d/ N- _2 ?' E6 @8 }0 f1 m        }1 ]" q# M& g& W8 l4 e/ i
#else1 b/ _0 f7 Q* J; A7 X
        elapsed_time = nes->cpu->GetTotalCycles();
( D) O6 l  Z, }9 s9 T#endif7 N( V+ H+ N7 ^  l+ c( w9 ]
}
4 w( |2 w/ P! t  r+ r
- K; [& f  G& }) l) |// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. V3 R- J% ?1 P5 j' D% DINT        APU::GetChannelFrequency( INT no )& }% X+ y* R+ H5 e
{
! w. ?3 j6 N+ O6 K1 @8 S; }0 h        if( !m_bMute[0] )1 K4 C' I# X: Z7 T$ R
                return        0;
% I* A' z4 A; G% Q# P/ x
; d) Y0 s7 r# t        // Internal4 I: F* x# R+ ~
        if( no < 5 ) {
3 O' y# T  }8 v4 d                return        m_bMute[no+1]?internal.GetFreq( no ):0;
  C2 |7 V$ A3 X# c        }  y4 e& P; E' f4 z' z5 m% W
        // VRC6  \6 b1 a% B! C6 q2 m0 E, x
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {+ G1 m! K7 m5 ~( H8 F
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;0 ~$ |+ s, }# i* z! v* n# j
        }
3 d7 L! U5 V5 T+ h        // FDS# M2 i# o9 w- h- D+ Z9 a
        if( (exsound_select & 0x04) && no == 0x300 ) {, v1 E( [' E( i" {9 b" K( B
                return        m_bMute[6]?fds.GetFreq( 0 ):0;& J2 y0 ], G: F; U  @
        }; g' ~1 W0 q3 _
        // MMC5" A7 r$ B9 @) e4 ]3 D
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {" c0 n# }; S2 [7 D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 A, S: ]8 T) c* N, z; H5 @& c
        }9 _$ _' k/ n' T- M) u; A
        // N106$ Z$ L5 Q; i  }: V
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {0 B+ u, `! t3 A5 h& n( {
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
) d) u' }8 z+ c, x        }& T% U6 s" q- J9 \
        // FME7
+ B' ?& }8 _& m        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {1 e. p+ q' S+ e8 X
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
+ a; Q) ?6 ?' e- P  u        }4 l6 |8 W) m1 D
        // VRC7+ o7 A0 E2 ]( E0 c
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
' y" n9 {* g( h6 H7 Z% f                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
; P% @3 T$ r, [/ F  ^! @' R        }
3 e- M& k6 |. v  S* C8 \        return        0;6 l' F3 D& f& p3 o4 K
}
4 E# N  M+ |. B
. H, q% u* S' m// State Save/Load
% d1 i3 ^9 w  ~# |" A, }! o* O/ ivoid        APU::SaveState( LPBYTE p )9 h3 Z6 x2 X8 O$ d" J5 I1 }
{
+ u; \3 e: ^) ~1 R#ifdef        _DEBUG
6 n, d/ e: i  J4 R: r0 jLPBYTE        pold = p;
& Q& T* a* b: k( O" @( C#endif4 \- b" z" p. P5 E/ \% M, W  n

2 O' z! [9 \( I1 u  a8 c) X        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞0 X9 u* Q5 j3 @
        QueueFlush();
* n4 l/ l% J4 [  a; Y* A; a2 J# u5 ?, \9 l
        internal.SaveState( p );
9 x1 }0 M8 l: i7 N. H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 E+ X7 c: K. |" a( Y

" @7 @- i  g$ p$ m0 A        // VRC6
+ X1 u  Y- l- O8 k8 i/ Q4 m        if( exsound_select & 0x01 ) {
; g% C, Z8 G" j& _: x& s$ k2 {                vrc6.SaveState( p );
2 _5 _. R1 v& D* R                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' [( b/ s& |. A! _- \& N( Z/ t9 ]$ N        }
* m5 W- T  _$ l: t" s) [( E        // VRC7 (not support)0 d0 A& l; ~  t9 u0 {
        if( exsound_select & 0x02 ) {
5 ?5 M/ X8 ^2 ^" T0 }7 f                vrc7.SaveState( p );
$ v/ R9 [- M: n                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! H' E, ^7 M, D6 _        }; m9 l7 g) Q( u2 I7 Z& F! |
        // FDS3 V+ L2 X! O' I3 R6 _7 |( d
        if( exsound_select & 0x04 ) {% J" D, K% X9 [+ t5 C& |, P/ S
                fds.SaveState( p );. L& _3 N0 h& M0 m! C, C  C: F, U
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- v- p7 T9 ?1 v0 K7 ~) S( S5 ?        }8 |7 T1 J3 n5 c( C1 W# B, o# U, S
        // MMC5
/ H) Z1 T; p+ z. Z        if( exsound_select & 0x08 ) {5 p, c1 J# g4 n2 p* o- y
                mmc5.SaveState( p );2 Q. j- ?( a$ ^; p
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 O# S- y  s! [
        }+ \- X; _5 ]  g
        // N106
  V# E! K% n; |3 [        if( exsound_select & 0x10 ) {' b3 [9 Z5 n/ t7 S) y1 `
                n106.SaveState( p );
; m; e$ e* o6 Q, \( O                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ y; N) C& J7 h+ ^; m/ p! c        }
/ K2 n2 n3 v; m/ w5 h0 T4 _        // FME7$ \' S* w  K, J* N
        if( exsound_select & 0x20 ) {
9 t5 M- f+ E0 l& E) }; J) q; h) H. ]                fme7.SaveState( p );  |6 \, o4 D8 q7 \1 {
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 t/ [# [0 {1 A( n) b% X3 L
        }& E5 [' @) K; W* Q" M1 k
: h# P2 ~. J/ M5 t8 @6 u2 P* S
#ifdef        _DEBUG
* |. e1 \6 x; g0 P& z  _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );# ^5 ?5 J, n$ m) t/ P" R  d
#endif
7 l, j7 U) O3 I( p" D+ t}$ j4 N% T0 g2 x. y

0 Q) C+ a( \4 l; g) r$ _* a" ]void        APU::LoadState( LPBYTE p )( W6 @0 ]1 Y* ?7 I" M: e2 [" J5 S
{# S/ ~& ~" d# X9 y3 ]# [+ j% [
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 E6 Q7 E+ a5 U4 U6 g        QueueClear();
3 W! y# [( [1 B/ _, M% X
8 c* v# S0 y& m3 v+ }6 ^        internal.LoadState( p );
* ~* Z9 U. H" [1 V, a6 O        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" T# ?- \6 ]5 q! O3 R) E# P% n; k0 }  M) r4 I. \5 }
        // VRC6% M% A- i/ p- S* ?$ r$ J
        if( exsound_select & 0x01 ) {+ @3 x8 ?" j: e
                vrc6.LoadState( p );
' I0 N3 A, \4 q  o  W) h" H                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* _$ o0 X4 ]% F! Y3 h8 n2 x' v5 _$ Q
        }0 K1 P4 Y* ?* F0 {, y' q& s) l# C
        // VRC7 (not support)7 [7 i3 ?& E' e$ V+ [9 _% ~! n; a
        if( exsound_select & 0x02 ) {: [' D3 R+ U7 m$ g) W# X
                vrc7.LoadState( p );
* C9 D- C$ U' }  N; @1 _                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! F6 I5 Y& J* b6 [+ a
        }
5 h  i. m* E* M% X' t5 n( R; v2 s3 `        // FDS1 a5 W9 _, g0 d/ W+ ~/ X. D8 a/ }
        if( exsound_select & 0x04 ) {  i) e0 ^/ g6 [* `$ y" ~1 x
                fds.LoadState( p );' j, y% e1 a4 Y7 \" _
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 N: P, _% z5 e        }
. Z/ o- ^% D0 D8 R* \        // MMC5
; Z( m/ h; }2 h0 M% _7 W+ u        if( exsound_select & 0x08 ) {
  H* [) i3 W% U( N; ]                mmc5.LoadState( p );2 h' [9 t! p3 b& r; c9 m& e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 C# B& w) m4 L: q/ n+ {
        }/ w$ Y1 U' ?4 c1 t- f+ I5 I
        // N106* B2 E8 l! n* S3 x, e. X7 w
        if( exsound_select & 0x10 ) {
- R& l% X7 J6 o1 F+ D                n106.LoadState( p );( N' h( k2 W8 s" ~5 A- u7 V
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 G* f) F- a/ q  L. u& x
        }4 T# c4 w( h# L' s. E
        // FME7
6 j/ M4 z' c/ L5 _        if( exsound_select & 0x20 ) {; c" z3 R" T+ _9 b) Q
                fme7.LoadState( p );
: C0 p2 L9 i7 B& c' I                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 R  W" u7 K! N& c        }
0 ]' e3 J. h2 [}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ( o. E2 y. Y' z5 ]4 p
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& O: D0 ?5 n5 R% g  {4 v感激不尽~~

) q- Z! s- {; ~/ Q! i恩 我對模擬器不是很有研究,& t; ~7 X: Y" k0 Z. |: {0 T
雖然要了解源碼內容,可能不是很困難,
" v* {; M) |6 ~) H( c不過還是要花時間,個人目前蠻忙碌的。
7 ~* p& D* e+ q' f! P
1 A( j0 t% ?1 Y; R5 z  m) j4 [給你一個朋友的MSN,你可以跟他討論看看,
8 ?" a" R/ d0 S9 h% u6 ~他本身是程式設計師,也對FC模擬器很有興趣。
( a& b5 h* `' s& E2 W
$ z2 ]. B* W7 ]* J' t  _- t9 R4 UMSN我就PM到你的信箱了。
1 H' t  \' _7 i9 j8 K. ^1 _$ P+ y+ {, o4 J( b" l- i: T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 . r& w. w: ^' u1 V: @
呵…… 谢过团长大人~~

0 K, k  e" d) a# U9 I9 q( x: u2 O8 G" \
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! K0 d" X  T2 {) {' ?7 U( V团长的朋友都是神,那团长就是神的boss。
3 l; f( b; X5 r+ t& `2 j5 |  e) y) m
哈 不敢當,我只是個平凡人,' r6 s: z! G+ J; i2 ?
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
% V+ W8 f! o" ?6 RZYH; {! T$ ^' _; ~" s; E3 q& I
QQ:414734306
% C" g( {5 ^/ d! M6 D/ nMail:zyh-01@126.com
4 h. }. L6 ]3 `4 ~, h: m1 L8 x/ {$ A
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
' e' a$ i% {2 E; |' D% X再次对团长大人和悠悠哥的无私帮助表示感谢~~
& p9 i+ h2 J' P
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-10 11:19 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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