EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 \0 a% t- P$ M2 m楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- ^6 L$ ?$ [! O/ F9 F
这里有相应的模拟器源码,就当送给大侠了~~
7 q$ `1 R+ H5 ~http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( k0 O' p8 l/ ?( {能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 o9 Z: G# ]0 b- }$ z1 H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 A4 r/ L, a3 x% w
这里有相应的模拟器源码,就当送给大侠 ...

& x$ i/ m  o! l- Z聲音部分(Audoi Process Unit = APU):
7 K9 z" }8 E; w4 o1 n8 Z6 E.\NES\APU.cpp
8 s; n& p) ~4 o3 V' B' n2 S! U.\NES\APU.h; ?9 x, T/ v% t) @. F
0 t0 p. u$ S  V; T1 Q' o

$ E+ ^/ l: u6 q# I影像處理部份(Picture Processing Unit = PPU):/ Y. r9 w( l/ H7 k! m$ D; h$ o
.\NES\PPU.cpp
, i: \7 W* y) N2 r6 ?& \* ].\NES\PPU.h& [1 [% X8 b3 `$ \+ m' E
' n- `7 b5 \, f' ~6 a' y8 K7 F
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  x  y; A+ C3 C
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ @+ R4 o' d. g6 c4 B! y: L
//////////////////////////////////////////////////////////////////////////
  Z8 q7 C6 z1 I- y. L//                                                                      //# v% ]0 v. q9 e. L* e7 `
//      NES APU core                                                    //
0 W1 a+ w) j" J1 A; v  t//                                                           Norix      //
* r/ P; }* s" _; {2 e6 I& c% X  F//                                               written     2002/06/27 //) L3 j* v1 h8 [
//                                               last modify ----/--/-- //# `- F4 l$ p  Y: x8 x' B
//////////////////////////////////////////////////////////////////////////
/ c* w! R+ j- i#include "DebugOut.h"
& x" s0 l" j5 N+ }3 K" {#include "App.h"1 \. I$ v" w6 A+ }9 Z3 R
#include "Config.h"1 N) B8 ~7 j$ L1 }5 ~7 n) H! m

" F4 L$ m* ~9 a* f#include "nes.h"+ E3 s0 P" R! O2 O
#include "mmu.h"7 X: K0 Q, w! G  m# t! N
#include "cpu.h"
) |; i% I, H. M#include "ppu.h"# }& M& E5 ?  p8 e7 x6 O* D
#include "rom.h"
. _+ _# K: Q0 I( Q#include "apu.h"
0 u0 w. F' d( W' g  {" M9 r$ Q, i& i
, X0 [0 d! A: o// Volume adjust
: x" l( [9 f3 L, g// Internal sounds& j5 s6 n/ v3 s  n& a9 L
#define        RECTANGLE_VOL        (0x0F0)* A1 z' e  A. s6 F2 x4 E- `. {: d& ]. Y
#define        TRIANGLE_VOL        (0x130)% D% r3 h9 X- `' V. E
#define        NOISE_VOL        (0x0C0)
* C* d5 a" a* e* |7 R9 y# m+ h* G#define        DPCM_VOL        (0x0F0); j+ y2 e7 W0 d: o# Q( T1 @/ v2 a. t
// Extra sounds
/ h7 b$ g( m9 m, ~7 o#define        VRC6_VOL        (0x0F0)$ T$ |' D3 \# t) ]* ?
#define        VRC7_VOL        (0x130)
3 }  z; R: y; v6 D$ W#define        FDS_VOL                (0x0F0)
* h3 C. @! d% R* ]4 h#define        MMC5_VOL        (0x0F0)0 b2 c3 w3 y" K  i8 L4 W1 @
#define        N106_VOL        (0x088)
6 Y) C$ G1 P; D#define        FME7_VOL        (0x130)
& c6 N1 o/ r0 ~- w  t
' D) U6 S  |5 F7 d' K3 vAPU::APU( NES* parent ), U& @. ?/ c) }% U4 s( L
{/ F! X' L% t6 L/ i( z) [! y
        exsound_select = 0;
/ Y1 \! Y# [/ i8 g8 C4 Q( O; Z4 ~
9 E, \' M1 e1 z2 i  F5 v7 h        nes = parent;' I( N- d2 b1 C4 T' k% L' w* W
        internal.SetParent( parent );5 p0 d! }$ U# _/ U4 _) B

6 r" M; z4 h  I        last_data = last_diff = 0;
+ }8 u! R( a2 h) M" Z$ Z7 Y# \* j6 W
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 e& O* ~& L* l

' `% \/ w  ]7 ]& r6 `5 u        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' `+ r6 S* f3 f( L' w0 m5 k
        ZEROMEMORY( &queue, sizeof(queue) );
( F# F! }/ W/ m" ~& f6 r        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ j& d! D4 C  T: V7 ?8 I/ k+ Q
; I; L+ @; r) L. Y
        for( INT i = 0; i < 16; i++ ) {% \5 \; f+ q* R5 V
                m_bMute = TRUE;
$ K" b5 n& Q) W4 V% a* t        }! V, A- x' X  S: P7 z) z3 ]
}1 C9 F& s6 K+ d9 N- `

8 \! S% Z, Z8 C3 tAPU::~APU()
* T+ d' R0 G, L8 Y% e/ x{
/ f- |8 s' i5 i% K1 C, U}
' v( \3 e6 v2 `. Z6 p% B0 N2 u' y, I  W) X1 a; L% V
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )! f/ g; l, _* i7 C- m
{
9 r, R; Z1 ]. x* I; q        queue.data[queue.wrptr].time = writetime;
- C% L' b; C/ ~        queue.data[queue.wrptr].addr = addr;
2 Y4 ?. R7 f1 S5 B9 F- b6 F        queue.data[queue.wrptr].data = data;+ S# X+ J% j. L% D2 H& E* t) s, z
        queue.wrptr++;
$ }$ s9 U9 R/ `4 S, k" m: l        queue.wrptr&=QUEUE_LENGTH-1;" ?8 ~! S% R8 z% t- c9 D
        if( queue.wrptr == queue.rdptr ) {! w1 p3 K4 E- V( [$ h) `) ]: S
                DEBUGOUT( "queue overflow.\n" );- _0 p- `# G4 ~  i, Z
        }
6 A0 N9 a4 {' O: A/ b, ~}9 a, S5 i, S- u% }, L. k
  J; M/ ]! z2 e+ N+ g# o) B+ C
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
2 m7 N* F& `7 E) \; N{, E) A$ R& k; E+ \* N- q. M
        if( queue.wrptr == queue.rdptr ) {- D+ F  }' m3 @% H$ h9 z. [
                return        FALSE;/ R" f: g- E3 m- x$ a; S8 I
        }
3 q, q5 \  v6 a( Y1 R" E( S3 l        if( queue.data[queue.rdptr].time <= writetime ) {7 Q- [+ J) Q7 F5 i
                ret = queue.data[queue.rdptr];* I$ @' p% u1 y. @4 ^# G* }
                queue.rdptr++;. [7 j7 R  H' X" v3 @% P7 U- n
                queue.rdptr&=QUEUE_LENGTH-1;( X. @6 |0 ^/ D3 ~; G: m
                return        TRUE;
, n5 N) H& C$ m( Y        }
0 S7 N- w" [# x% n2 R' S        return        FALSE;
) j: t; O, N8 p5 s* ~  p}8 ]% n, N1 T' o% r7 k4 P/ ]/ w

  m' N+ Y% q1 U7 ?  qvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 T& d1 w/ k$ @/ L) ]8 h
{
+ C, g; e8 v) ]7 V6 y$ u& d6 V4 p! Q' ?: ?        exqueue.data[exqueue.wrptr].time = writetime;5 l3 n; g- B) \* R/ W8 s
        exqueue.data[exqueue.wrptr].addr = addr;
8 g2 W8 G; K, d& I        exqueue.data[exqueue.wrptr].data = data;
" t' z- z/ ]( M        exqueue.wrptr++;
, T' f5 p3 j& f6 i) T        exqueue.wrptr&=QUEUE_LENGTH-1;
% E! S- v# l1 _' o/ p" X* K        if( exqueue.wrptr == exqueue.rdptr ) {2 K5 X* {' i8 @: `' R' v  ~
                DEBUGOUT( "exqueue overflow.\n" );
& w& s! u: Z4 N2 F+ ^        }
" r4 M5 N5 N+ P" u+ x: J" V' e* U}
4 j7 x5 N, Q+ y- h. r
+ n6 b! {6 u  I2 qBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ): q! V; i" H& ?9 g
{
4 F( \$ l* h0 F9 {% Q* }        if( exqueue.wrptr == exqueue.rdptr ) {5 _- d; w7 }2 U' O3 h& ~- ?
                return        FALSE;5 o& C' X+ Q3 Q5 C
        }
. M) Q. [) x) I  ]        if( exqueue.data[exqueue.rdptr].time <= writetime ) {3 O& d; o/ X0 p" ]0 M
                ret = exqueue.data[exqueue.rdptr];
, Q% X8 U6 Q0 @$ u5 x                exqueue.rdptr++;  P# v, A# o& U: S# F- q9 Q
                exqueue.rdptr&=QUEUE_LENGTH-1;0 w( ], q& }" H+ A0 e: r* h1 q! r
                return        TRUE;
* R) [& e, j6 }/ h/ x  w        }
4 a% q+ p4 o9 k4 R$ O        return        FALSE;+ b: _, n5 Z2 d: t3 [& b) j
}
5 p' ^* [) J$ ^% W: Y5 F' o0 e$ d  r# @4 C" T
void        APU::QueueClear()
" _1 }3 z- U7 R' o- }{( I) i1 m1 s3 B+ M4 ^; Y
        ZEROMEMORY( &queue, sizeof(queue) );
% H+ z8 E4 b% r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' O. O0 S! f: F. T& ^8 A}
( f2 r7 E) f) U0 v% S. X3 t  B" Z/ T- t( G  Y8 o
void        APU::QueueFlush()
4 l2 `& x2 `7 L% U5 L{
+ ]" T8 _8 P% I        while( queue.wrptr != queue.rdptr ) {* ]* p! f3 W2 s4 [" _4 N5 S
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
0 T, j5 G, o6 V& J) \4 Z% r                queue.rdptr++;
5 r, Z# c! ?4 \9 f3 v                queue.rdptr&=QUEUE_LENGTH-1;
* A* U/ W/ j5 D        }
5 D( b* V; `7 I& D% @; k) H& `9 E' r1 k4 _
        while( exqueue.wrptr != exqueue.rdptr ) {
* ~2 o. R2 R, i2 F/ t                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
& L. U* [4 T7 m$ }" h8 T                exqueue.rdptr++;
& `" r: s5 j: w5 {                exqueue.rdptr&=QUEUE_LENGTH-1;( Z5 z% x+ ^0 e! O  I
        }
, h3 D: g3 n. K0 D}' V/ P/ N8 `, S; v4 @& t& X' a

; y& d$ q3 q* U. N6 }: Qvoid        APU::SoundSetup()2 `. r; w0 O, f- x1 j5 ?
{& j; F- u+ j& A% b. d
        FLOAT        fClock = nes->nescfg->CpuClock;
/ Y, s/ L1 c( o7 ~1 m7 S        INT        nRate = (INT)Config.sound.nRate;" k% I6 a) X: y/ E* j$ N* q
        internal.Setup( fClock, nRate );9 H* A) X1 u# o5 O2 [0 @3 @" K( g$ B
        vrc6.Setup( fClock, nRate );
2 {5 @& u' P( R6 A        vrc7.Setup( fClock, nRate );6 u7 V( b- T9 {4 _* Z/ j) b* E+ ]( Y
        mmc5.Setup( fClock, nRate );* z, i$ k  ]" {4 w) B. [
        fds.Setup ( fClock, nRate );0 G& m* n3 ^/ F
        n106.Setup( fClock, nRate );- W5 {% S0 s  _1 Z9 z) {. t
        fme7.Setup( fClock, nRate );
. t' b( ~. l1 c}2 ^7 U5 f: O- R

: d, C6 Y4 z4 w7 T: mvoid        APU::Reset()  i  F7 ?( _" U( ]' c
{- L6 F* V' M. f3 Y, E/ y) a9 t  S
        ZEROMEMORY( &queue, sizeof(queue) );
2 c* [0 q1 c0 D% S  r        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 I6 n8 Y+ ]9 @& G% l
; D  S# t+ i( X& I+ p8 p2 {, a9 Y
        elapsed_time = 0;: k1 f. P% M4 d
5 z3 i2 {. k- C) Q
        FLOAT        fClock = nes->nescfg->CpuClock;
/ t2 A' `% S. ?+ p        INT        nRate = (INT)Config.sound.nRate;
7 }9 H1 s, W; n3 r/ |, v$ ?# w        internal.Reset( fClock, nRate );
2 e* Q. C; G0 x7 }, h" p8 P' R        vrc6.Reset( fClock, nRate );: h. |! i/ d# c; c: O( f
        vrc7.Reset( fClock, nRate );
. K2 X* z. x3 a8 D# O9 V! ?" X3 R        mmc5.Reset( fClock, nRate );4 K* {4 j6 P1 o& ~0 K" T! N2 T
        fds.Reset ( fClock, nRate );
% p$ R5 r5 I2 Z* t! d5 z% J        n106.Reset( fClock, nRate );
- S4 C# A) r. e1 @0 Q/ v6 s( |        fme7.Reset( fClock, nRate );( J  m( o$ b3 H, d. m" _$ E+ L, Q0 Y
: J! y( q& h9 B) J# |+ [
        SoundSetup();7 Z  v" U* L  K/ d( H/ R2 T
}
9 U- m0 J9 ^& ], e9 }
: c* W' {% D; P5 f- N* t( Wvoid        APU::SelectExSound( BYTE data )
& d7 m; V) B& {$ O! |# Y( J0 i{
7 S# Q- V8 n% m        exsound_select = data;5 ]* {" Q! B1 |7 J( e9 z# p5 J
}
& p- j0 F; i0 D9 t
9 D4 ~7 i6 z1 oBYTE        APU::Read( WORD addr )
6 i) e1 ]3 [8 U4 g, i9 o7 G' u{
) E3 }7 _; i; t        return        internal.SyncRead( addr );
4 A; }$ S7 }6 x. `: ^- d}8 u6 z; a! e1 L7 r' Z
) m/ {+ i5 ?6 _7 _# k" c' b
void        APU::Write( WORD addr, BYTE data )
7 B  [. x0 M: Z{8 T. [" G9 f8 b, L% [0 B
        // $4018偼VirtuaNES屌桳億乕僩7 d% i# @; \  J
        if( addr >= 0x4000 && addr <= 0x401F ) {& T& L% R, e( `( b9 H& P
                internal.SyncWrite( addr, data );
) U# ]6 o5 {  u6 J, J2 O                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
1 W+ w6 k5 V( p3 `2 a& i  Q  {        }
/ P" O" m. t. ]" \7 P- \5 h}7 }, X3 L- u8 g, B6 M

9 K' @! B& Q1 yBYTE        APU::ExRead( WORD addr )
7 z, `. O, k& E" X{( O5 ~. L! J! e( z
BYTE        data = 0;
0 ?. I% H  @& @
! H/ D4 k, U% _) |* ]8 _        if( exsound_select & 0x10 ) {
! x: W/ F$ O( j8 L0 k& L% P3 W9 O                if( addr == 0x4800 ) {/ U) \/ F5 z) k
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
% m; ^8 P; ], V5 p# b                }2 F( M; e6 P- ~  f% A1 T- L1 f
        }% T( e8 r! b3 ]7 e
        if( exsound_select & 0x04 ) {
2 g% `* r2 Z- x2 V7 D4 c: _                if( addr >= 0x4040 && addr < 0x4100 ) {% W& P# g+ D/ k4 F/ M
                        data = fds.SyncRead( addr );6 L1 ^0 h# j$ I$ E
                }
" M- Y7 J+ n/ w6 i        }
: i- M1 U- Y- _$ O        if( exsound_select & 0x08 ) {5 P  y. m' G8 R7 g% m& T
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 T+ Y$ O5 p* O! k
                        data = mmc5.SyncRead( addr );2 r# m3 b6 B3 @$ ?3 ]
                }
6 b, ~! N8 f3 J7 v) p3 @        }; S( r: ^; K  Q# ^$ y" e/ d0 T

! H, L$ L0 E# Z        return        data;1 A. k" |# q( r
}
. L: y) ]! k; q$ t' Q% j! M
5 F: d5 L# i: }& q: G7 s, Avoid        APU::ExWrite( WORD addr, BYTE data )( |4 |) _$ D1 I' Z7 {% F
{- o/ h6 x) ^. q% E: M8 N. A. s
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
/ N; ]) a4 s+ G& R1 O" |7 I+ P5 \4 }; i: @
        if( exsound_select & 0x04 ) {, }2 t; ?% }& R$ |; x; T
                if( addr >= 0x4040 && addr < 0x4100 ) {
1 ?7 U5 l8 T' c6 w4 p) A+ m* Y                        fds.SyncWrite( addr, data );
. T9 S3 s2 h3 E                }
4 i- h! p0 M8 ]2 c        }
8 I& P3 m4 V9 A5 E$ u; C! U4 t( F- Q$ X6 A
        if( exsound_select & 0x08 ) {% m- A& l+ g3 F* }
                if( addr >= 0x5000 && addr <= 0x5015 ) {- M3 k. s: L+ p
                        mmc5.SyncWrite( addr, data );
6 U. ^! q+ x  S' b' B5 i& }8 x  {                }( U: A3 x# R% G9 I, p8 c
        }
4 D& e9 }7 U( i2 v) v4 Z}
+ F* {, f! }0 J& ]0 X$ {2 ^" }
4 r' ?$ \. ^9 j$ g" Hvoid        APU::Sync()
. x  E" r* u# i% |+ C# N+ h+ {" ~{6 o: D5 ?( @+ ~
}
/ c* o1 H& M! [# d5 g& y# F
) T8 {4 w9 ?- t% Y# z. T! c0 l0 Tvoid        APU::SyncDPCM( INT cycles )
; m2 p# f. ?1 @& S: I5 a{9 S6 p% g/ v' v! w. U9 M
        internal.Sync( cycles );+ d8 f; c" V- b3 V$ [0 e

. X" j, W* C; u& T$ ]2 H        if( exsound_select & 0x04 ) {
0 K. Y! e6 X/ |& N                fds.Sync( cycles );
! E/ S5 T. B; U9 o4 e. v        }
9 |4 _9 j0 x) J5 {0 w        if( exsound_select & 0x08 ) {
6 w  T1 F3 z- U$ b7 d                mmc5.Sync( cycles );
: ?% p: ~4 b1 i" L4 ~        }  p2 }8 g, q% k- m
}
- |/ `* S; C+ O  _+ E( ^
' A3 k4 A+ M' ?. J% u- kvoid        APU::WriteProcess( WORD addr, BYTE data ): E! l# C5 w) D% Y2 x! \
{
) b- ^( A  F; G7 E        // $4018偼VirtuaNES屌桳億乕僩/ X. \' s* Z8 }8 U' H3 A( T5 h
        if( addr >= 0x4000 && addr <= 0x401F ) {3 m0 T$ ~( w0 q! U
                internal.Write( addr, data );% b- F' Z6 k9 V1 B0 B9 p3 X
        }
4 ~4 U, x) X0 a- }}
6 e1 J, j/ G! p! U9 L4 ]# s9 {. _4 U1 \3 D: ]0 D8 e  s
void        APU::WriteExProcess( WORD addr, BYTE data )
* I3 j7 r4 ?( e0 J{
5 ^; G, n" r) y        if( exsound_select & 0x01 ) {  L* a9 p1 b9 G7 p$ J) H
                vrc6.Write( addr, data );
3 E- J- T- L' Y2 o9 \& t$ Y        }0 k0 N& c& D6 U! i8 h9 G
        if( exsound_select & 0x02 ) {3 C% K: @1 H' j+ S9 r
                vrc7.Write( addr, data );
. y8 R. `0 P2 A4 N1 ~        }& F1 L! e& Q0 H2 e7 b; }, K
        if( exsound_select & 0x04 ) {
+ g. w) k' W1 e. t/ q- F                fds.Write( addr, data );
, [; p, h3 U( \. V" L2 c7 G6 S        }% ^, e2 {# ]% [- B" M
        if( exsound_select & 0x08 ) {
% D! o1 g; y+ ]3 O- g6 p1 ?                mmc5.Write( addr, data );& w/ q) x7 w) R
        }
- f/ B% t# \+ S3 J, j- G        if( exsound_select & 0x10 ) {
& F( a9 S7 u6 D& I8 l' ]4 y                if( addr == 0x0000 ) {, w, y, [. @" l/ C( q+ z+ I
                        BYTE        dummy = n106.Read( addr );- t/ e. M3 i7 {8 \1 f1 g8 b
                } else {
3 ^8 L% o+ m6 i+ y. d. q                        n106.Write( addr, data );
7 P$ L# T1 b# [& v- s                }
8 p7 t: Q' W( q        }
; d' D7 w. H* i  h        if( exsound_select & 0x20 ) {6 V4 |! B( a' y/ e1 m
                fme7.Write( addr, data );
# p1 @8 X5 k& ?$ w" J        }
: [" L$ x" K/ R6 T$ ~}
, G2 `8 A) o9 T) s3 b3 G
; H  [7 ?6 O" z; W3 S* U! avoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
! ~  W/ L# ~! s: A- h: Q{" X+ A1 t) V2 L) d) p+ n: k+ m1 w
INT        nBits = Config.sound.nBits;+ q* `* }5 n4 [2 p, g
DWORD        dwLength = dwSize / (nBits/8);+ T  q2 z4 {3 H2 _( n
INT        output;6 s$ X9 E5 z) k7 k& r
QUEUEDATA q;
  z; m- x6 Q5 d5 ?% iDWORD        writetime;3 s( G7 e2 w8 f) ?

! |* f2 W4 {. p. d6 dLPSHORT        pSoundBuf = m_SoundBuffer;0 ~+ ~! l6 Z( q# O4 w
INT        nCcount = 0;
( t6 H- E: ~: ^+ i9 T8 Z* J" S% f  Z/ m/ F* r% j% {. T
INT        nFilterType = Config.sound.nFilterType;4 Q6 r& Z/ q2 y# S

& \5 m6 \( S2 t3 s$ A( p        if( !Config.sound.bEnable ) {
! b* ~7 d" l1 i. D$ ~( V8 F" u. s                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
- I7 ?* }6 z8 r) L5 @                return;7 X- q, g  F3 t6 j, a  p( K
        }
% @8 p. ?0 X) o
2 G; |) f( D: k! R5 }) C        // Volume setup# T: t4 z: y/ B- i3 d# b. ^
        //  0:Master+ W5 p* R9 R+ I& F! ^5 n1 a6 N
        //  1:Rectangle 1! N4 `) _0 j# f7 E) V5 s  Y
        //  2:Rectangle 2
  L0 b0 g5 o% ~4 u8 ]        //  3:Triangle; f$ L1 [. M& q, a
        //  4:Noise
! e% L% D6 E% |4 B- H0 u        //  5:DPCM
' E3 Y) h3 b- T- U6 K) d6 X        //  6:VRC6
/ f5 h- J2 \# y) M% N        //  7:VRC7
9 _/ p! p! H1 H* q4 v        //  8:FDS3 s8 j3 |. G. M, H; l
        //  9:MMC5  c: w7 S1 c4 ?# v  R) ?( [
        // 10:N106: m. H4 X6 a  b6 H
        // 11:FME7. [& E* F1 l4 T3 |
        INT        vol[24];# U+ ^0 j- V  _' Z
        BOOL*        bMute = m_bMute;2 e4 z5 A) k( D( r, F% `
        SHORT*        nVolume = Config.sound.nVolume;
5 O) s- U9 x) W6 }' p5 ~5 b+ ~& l3 G; r
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" E8 i4 }* X" _$ A8 T5 q

9 A4 ?) p: |  o; \- i% z        // Internal
' j# Y& }6 I1 w) X1 w) z        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
6 I2 B" T0 n5 D# J& G: V, a        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;, e4 ?$ ^* A! U6 p
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
# y5 E, V% Q  ~        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
) ]# M' I3 b: N. \        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ i& b! I7 i1 B9 v2 |4 {, P& d0 a) O( c8 w, y
        // VRC67 s  F9 T2 |% V5 v" P4 I
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 S, ~* H' U2 U) \' u1 X
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 Y8 f: d( ?& F
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: B% s( k) }8 I- m% D6 ^/ [7 C6 K$ Y: [& Y$ i, D
        // VRC7' L6 {3 F! [+ k0 I" q5 I
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
" w: R- z1 c* b% r* z# I
- S) B0 w) c$ b6 }$ n: {) [        // FDS1 K. ]$ W" n; d: q9 B& f- _: U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 O9 c0 M: \- g$ L/ @% S' L5 T* N6 a+ U9 c
        // MMC5
; J" p$ W  x  n! |* F  O* H1 P0 E        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ F+ Y7 i, A6 C- J6 n        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- n! M3 Q8 Z/ L) a
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 O0 l+ a% z2 ]+ e  I& W1 O
8 G, `+ |' @! Z: q
        // N1065 {8 D% b8 |) ?
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* C1 A/ p3 G8 y2 \: `7 ~7 c        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" N3 V. V1 S, N( d  [
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 d3 R- W+ s! e; {7 G
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 |7 |& V3 }' c8 c; c5 {- X
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. O9 n* ^7 v$ x, x$ r% i        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ u. u) |0 H: N1 _# b* J        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 U" S+ P1 e  U* F+ X* s- Z) |$ U        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 r( n- V' @. \. B3 e7 P% h
0 H/ J) N6 L) m$ r8 t) N, i; {        // FME7
2 s$ E5 {; D; P. _$ y        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, h# {2 {/ E4 w! l  Y
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ P; i, l5 V& U% Y( j4 L' ?; r1 }6 ^        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 S* l1 C5 ]& O; W. O% ]3 r' _% Z
2 d2 _2 C/ b+ b7 q
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& ?! t. j4 n1 u# `$ ~        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
2 i$ r; ~' U& _2 b' }- _% J' V' S! L$ W7 }+ V" R- V
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟5 e  g+ t& }' l0 O
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
0 C/ k9 z, h' \$ ?9 j- w                QueueFlush();: C% \! Y# z2 v: D
        }
+ j$ W, L" L/ [- g$ K' z" s( [# d0 S
        while( dwLength-- ) {7 ^. h3 c- p3 v6 B8 q2 ^% Y1 G" Q
                writetime = (DWORD)elapsed_time;& ?$ h* \5 L5 E3 v: G7 ]

) z, D+ ~9 u* U8 U8 K$ d- e                while( GetQueue( writetime, q ) ) {
4 f7 a( e2 S$ d. e  q# D                        WriteProcess( q.addr, q.data );
' X' Q8 ]2 c6 Z/ x% H, J4 r; v                }. b/ ^7 j5 F# q9 O/ v9 k" p; h
6 T5 s  h, ]8 L
                while( GetExQueue( writetime, q ) ) {
# ?- K8 d: x( H1 y/ r                        WriteExProcess( q.addr, q.data );, u( q# Q5 w# L/ O- E/ M* J8 A
                }6 b5 J. m: t+ D$ Y& Y( x

" O* H- t, u# [                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7( y* k4 A; R, M7 I
                output = 0;7 ?1 [$ C/ z7 l/ a! j
                output += internal.Process( 0 )*vol[0];: _; \* e& W' m- g! \. B2 M
                output += internal.Process( 1 )*vol[1];
4 H1 G2 m1 Y- g, `% G                output += internal.Process( 2 )*vol[2];
" I2 T* e4 F% m( U, w                output += internal.Process( 3 )*vol[3];! M5 k2 P( X& f* W; M
                output += internal.Process( 4 )*vol[4];
9 q2 A# t! X4 x. x3 ]: |) K9 I, F; i9 R: o/ }' e  z
                if( exsound_select & 0x01 ) {4 J0 S1 \) Z/ M  @# \
                        output += vrc6.Process( 0 )*vol[5];
( X4 e5 x5 t6 C: `+ b                        output += vrc6.Process( 1 )*vol[6];/ n- L( b; B8 w& I7 x4 |
                        output += vrc6.Process( 2 )*vol[7];
9 R8 A# U/ r! q                }
% @- c: G3 O5 J$ @7 M, R2 B0 {                if( exsound_select & 0x02 ) {
) D# J# n" ^& A4 r                        output += vrc7.Process( 0 )*vol[8];/ O7 x/ p# j; L/ x
                }; E1 A* j: l& Z( L3 k& X6 f
                if( exsound_select & 0x04 ) {# |: [# x6 f  m
                        output += fds.Process( 0 )*vol[9];
" S$ r1 X- K* x! m6 x6 d& x                }, b# F, U4 w: _$ v
                if( exsound_select & 0x08 ) {
3 n  F* A$ Q8 e4 p                        output += mmc5.Process( 0 )*vol[10];
& l; j" K# S7 G2 o3 O1 o4 p: i+ j5 ?, r                        output += mmc5.Process( 1 )*vol[11];
) W0 |2 @+ M, H                        output += mmc5.Process( 2 )*vol[12];
7 g# h8 K/ m. ~. o5 ?                }% H0 D* L- x1 H  q& j; t& t) q
                if( exsound_select & 0x10 ) {
1 B7 U+ H% a9 c/ O, d0 X! z                        output += n106.Process( 0 )*vol[13];( I; N7 q# r: ]/ t: A! @  L6 v
                        output += n106.Process( 1 )*vol[14];- {$ C) u2 w! f( ^, ^9 ?  m" M
                        output += n106.Process( 2 )*vol[15];, s( u+ V/ E- l7 ?
                        output += n106.Process( 3 )*vol[16];& s8 v2 ~, ?: {( |5 l* e4 D! p
                        output += n106.Process( 4 )*vol[17];
/ ?  b: ]1 t: H+ E0 b                        output += n106.Process( 5 )*vol[18];* J9 Q+ j6 D$ V$ T! C0 p4 E! z8 S
                        output += n106.Process( 6 )*vol[19];9 K1 u' l! A- E7 p) O
                        output += n106.Process( 7 )*vol[20];
, v0 r8 q0 E& k- J                }% d; h+ o6 C* W# I
                if( exsound_select & 0x20 ) {2 w8 t. Y' e0 x( L) {$ j* @! x
                        fme7.Process( 3 );        // Envelope & Noise% x7 R! R2 o: g6 e3 J" u+ d
                        output += fme7.Process( 0 )*vol[21];
, b7 m$ T0 V/ A* q' m( w                        output += fme7.Process( 1 )*vol[22];! h/ B% ?5 _- I- v2 v2 {
                        output += fme7.Process( 2 )*vol[23];0 a1 G1 |5 [' B7 N! W) i- _, t2 W) `
                }: q, c6 Q4 v0 Y/ p4 C& s
; \& e' U! `* f# S
                output >>= 8;
# x; N9 C" f% K: a+ Z" z$ `* I) _' Z; h
                if( nFilterType == 1 ) {
4 p) }4 x9 s2 ]* l% `8 k3 E                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& ]9 H( J) ^9 a& K, ~& }( F                        output = (lowpass_filter[0]+output)/2;  \- g7 K& E; z4 |6 V- f6 Z
                        lowpass_filter[0] = output;0 ?( B9 {3 p5 G' w# D
                } else if( nFilterType == 2 ) {$ B  i' E) l) j  i* X
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ x2 Z# H5 ]% b3 i5 a& E# Y
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
8 W8 A# ^8 }/ j, C- K* `/ w; A                        lowpass_filter[1] = lowpass_filter[0];5 l6 C4 ?- ]/ P1 `
                        lowpass_filter[0] = output;
- q0 _  m9 x( Q- m; o' |                } else if( nFilterType == 3 ) {9 @$ k: o- w' {6 ^6 U/ o$ x
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 t" Q. q8 B" F/ t& _. T* d                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
+ E& m3 ~' Y  N1 e                        lowpass_filter[2] = lowpass_filter[1];
0 E7 k/ @5 D, G: A/ s                        lowpass_filter[1] = lowpass_filter[0];
6 e! M: f) b7 h8 t, A/ \8 I+ v                        lowpass_filter[0] = output;5 j5 I3 }) Y& W! @9 A  N
                } else if( nFilterType == 4 ) {: q3 g( ~1 i) r
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# i+ j) L- J& @6 S% |+ H
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
: h7 p; C# h' ~" f) ?! M: I# o% p( ?                        lowpass_filter[1] = lowpass_filter[0];
- J+ C4 u4 u& x" A# ?! A7 e0 W9 }" ]                        lowpass_filter[0] = output;
& l3 x/ `0 s, r$ D# K; h, j9 [% R) ^                }
: V- x4 s" a( J0 h+ q
8 Q3 a# X; T6 H3 s% i: I" L#if        0) r1 x" T% ~: T! Q3 Y) V6 w
                // DC惉暘偺僇僢僩0 H, c* V3 U# d8 I! S
                {4 y' I# o& T- C3 v* O* w$ ]
                static double ave = 0.0, max=0.0, min=0.0;
) E: A7 ^) {& D                double delta;0 [6 X& k$ {$ D: u5 A) E
                delta = (max-min)/32768.0;
9 B6 h9 S2 B2 V) }. m9 b4 e                max -= delta;! O9 z# b+ Q# ~! w) f
                min += delta;
! `- L1 r! a( R) y                if( output > max ) max = output;
# y3 e, U! F. N/ j9 ~9 x                if( output < min ) min = output;
" s: t. [. X1 n  `1 A8 R9 v3 S3 W3 g4 n                ave -= ave/1024.0;4 y; k( v0 W7 Z0 Q2 g, a, x
                ave += (max+min)/2048.0;
. T; w8 A& N- m* Q                output -= (INT)ave;0 z( W4 _% ^  ]
                }3 l( n  B- G/ c; z' t7 s
#endif
' g5 u0 V4 g4 E- W  e5 m2 G#if        1
9 r1 ^! p4 ]8 M& F1 y! G0 P                // DC惉暘偺僇僢僩(HPF TEST)
+ g, g. q. M- D  Y                {
8 T3 U0 t$ h. O2 [0 Y" q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
4 Q* b, Z) ^+ k% I                static        double        cutofftemp = (2.0*3.141592653579*40.0);
! L5 K- a% b4 u3 |" y, \) t$ T                double        cutoff = cutofftemp/(double)Config.sound.nRate;
' C9 e! u& k" O6 ^' n                static        double        tmp = 0.0;: i. @4 ]4 b# F
                double        in, out;
: _$ q* {& T) q4 f- l  D
, t; k: t' Y" E! y                in = (double)output;
9 }5 d, V6 t5 i4 \. [2 ^                out = (in - tmp);- s& e+ v7 b1 |3 U5 y! r" U
                tmp = tmp + cutoff * out;
: x* L& q) m. q" C% g
$ K, k1 a- ~  m" ?0 T( Y1 y- V: Z- x8 X                output = (INT)out;
) Y! W, s- v) z/ j                }$ p/ F* A" w0 ~
#endif
6 W7 d, A$ y& v+ s#if        00 l3 S% @' I' d+ C! Y* H/ ~, e
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
4 P: S" E5 k/ M: p                {9 J2 b/ i6 \1 h- D
                INT        diff = abs(output-last_data);' b; F5 F  w3 _& G
                if( diff > 0x4000 ) {
. _1 s  b; r8 t; U- l4 c+ R                        output /= 4;+ }% L: g) f' v8 o/ c: b9 b
                } else ! o' m* e6 H9 d5 u4 @2 g+ C1 D
                if( diff > 0x3000 ) {; ?2 q) ~5 w0 |  q1 X; N
                        output /= 3;
9 w4 u8 _  D1 {  l- V# G                } else
, G( A9 s/ o7 c, Q                if( diff > 0x2000 ) {) |$ N$ u9 i& `
                        output /= 2;7 ~0 H9 i: ?: _0 e
                }' o! ~9 f( s: m/ I, h' {' p! H+ Z
                last_data = output;
4 ]) ?8 j& A& C                }0 k0 ]$ H) k; X" C0 X% P
#endif" L9 L1 A; v) o- c; M9 q$ o
                // Limit2 r: v; O& o" p2 m! Y( U5 f* a
                if( output > 0x7FFF ) {# E- ^* ~' c* |1 n2 M  K
                        output = 0x7FFF;
5 o/ ]' E7 v* J8 J" |3 r* J                } else if( output < -0x8000 ) {
5 U7 Q' k0 L" C) {4 U" |* @" L                        output = -0x8000;5 D. N2 ^7 R1 }' s2 S: f# i
                }
$ f) \: u! g& V+ r7 v6 B$ c# I0 A, T: m3 W
                if( nBits != 8 ) {% z. S' l# p# k5 E. s) [
                        *(SHORT*)lpBuffer = (SHORT)output;* M# d' P4 o! V8 A1 V& g
                        lpBuffer += sizeof(SHORT);' b2 L: U  A" a. k
                } else {
; I8 }2 n. Y+ C' m" i3 s6 H                        *lpBuffer++ = (output>>8)^0x80;
' o1 {% x% }* W# c/ Z/ E                }4 E# R" [9 M) `. o6 [
$ D  k; X: i1 r+ d2 |
                if( nCcount < 0x0100 )2 D- m/ e, f' \  E( w; m0 {# _
                        pSoundBuf[nCcount++] = (SHORT)output;
1 U) C' m/ c0 b) Q
2 U( z7 e! S4 ~8 y//                elapsedtime += cycle_rate;
  i, R, G# }6 ]( `. S                elapsed_time += cycle_rate;* w  B9 B! n! S6 ]
        }
% d7 r1 B# u6 x% _1 V
( J$ M" B5 y0 H% F, \$ L#if        1- R8 y% Q9 y: p) `# v
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# @$ K. D6 S2 [( f: ~; s2 h1 G
                elapsed_time = nes->cpu->GetTotalCycles();2 ^. z0 P! b5 G* m0 `
        }
/ t, @  `2 _/ m( q        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {; r- R3 g9 V% t6 F6 l
                elapsed_time = nes->cpu->GetTotalCycles();  k  x2 q9 X  ~
        }4 i5 U, O7 S8 E; J: D1 c$ ^1 n
#else. \3 D: g( v( o% P
        elapsed_time = nes->cpu->GetTotalCycles();2 O% N& m3 [! f% [
#endif
( O3 W: [. q. _9 E}# e% |' i. K. R2 K0 n' ~3 M
5 H/ \; R  s7 J1 s# _
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 r# N% }  O) `! GINT        APU::GetChannelFrequency( INT no )
6 b/ [+ h, b: E1 E! c{
( ?: a+ G  f' \; M9 e/ i4 K        if( !m_bMute[0] )' K' h) E8 V- N" A* ?
                return        0;
0 ?2 M/ l& P& N+ m- Y5 [. i8 U0 P/ w" T0 W& t3 M' }
        // Internal
# g, N( ?* E( n# G5 I        if( no < 5 ) {
4 q+ P& y5 h- h2 G                return        m_bMute[no+1]?internal.GetFreq( no ):0;
$ U3 L. \6 Q3 p% N% L  |        }9 K0 g$ x- u; W: C3 C; ~& b
        // VRC6
4 S8 I: \3 b' b        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {8 b9 q) v: }8 v3 }. i2 _2 n) O! h3 h: V
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
" h' o0 I$ l* x. ^  Y        }
% N/ j/ o- e* h2 ?        // FDS
7 W" J! I  a, o" {        if( (exsound_select & 0x04) && no == 0x300 ) {) D. B1 k( W+ a
                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 G7 F; N8 K: e$ P4 @7 c# _
        }$ i6 l' }  ^( y: ^) H6 j( G
        // MMC5
) [% d* x0 W' |- |' g        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ c6 c$ T/ r/ s9 J7 [/ s                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;4 Q/ ?$ P6 C7 x) B# I2 e+ W
        }
0 M* Z2 n3 v9 V2 [/ {7 D        // N106
; m! r* ?8 {% g% t' G7 B4 }+ A9 z( f        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: }! e( e. I8 \4 ]: e
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;) K+ s( y( |3 m$ a& Y2 ^) z) Q/ D' z
        }( R# M7 Z* {' f$ w
        // FME7
6 p9 a) W7 o- K        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {/ X  i3 h2 y( q- K2 U: V
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;. F* `6 {* J0 U' U
        }
% H# {* N. y2 g- ~2 k        // VRC7
/ s! j5 V+ f, B( D' y9 A. W        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {5 S; D  k9 {5 T: I6 T8 J
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
! U" z) k$ Q7 n. v        }
, o- V; E" o8 i% x; w, x! u  ?        return        0;
+ N6 _8 C. F8 ^4 x# I' h; g}
' f4 f# L5 h; t$ K' r: F
% \/ Q$ g5 @; l4 l// State Save/Load
5 U/ J4 {4 h. b; ^( O# kvoid        APU::SaveState( LPBYTE p )) T: z+ N! @! Y6 u0 z
{! O) K4 O& z; [$ K3 Q; T& \
#ifdef        _DEBUG  E( C7 Z) C9 c& }; u  d# K
LPBYTE        pold = p;
2 B* t. A/ ?$ j5 C. }#endif+ b# Z7 p4 f) l  P- w1 Y( t; d8 U

: V8 V2 p5 ?1 [+ ~+ ?8 A* h        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- t  J- ?% u" G* O$ s9 L
        QueueFlush();
' `# H$ h5 d5 x7 @' B2 F' C$ Y* P' J* h: m: f
        internal.SaveState( p );" {  a8 h4 r9 x
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  D2 S( Q  i: t4 {3 E
# E1 l+ k, E. l: W) Z        // VRC6
' E9 v' _- s* q2 K$ c4 v2 I        if( exsound_select & 0x01 ) {9 `  f! T  L& i
                vrc6.SaveState( p );
' P) K9 I9 K( G9 b! g                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 C* ^+ G2 m  t  y        }
* Z: I1 l- K8 m        // VRC7 (not support)
" S6 W2 ~5 L. q; w: h2 E        if( exsound_select & 0x02 ) {
( k+ ~; A% |; }( o& q9 I                vrc7.SaveState( p );
4 N7 q" H1 X0 k6 V( c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! x: J( \$ n0 `  G8 G
        }, T: \! S# H7 c2 D
        // FDS9 O; V: [0 _% ]: T! t2 Y/ l
        if( exsound_select & 0x04 ) {
5 z" m" }7 H) h5 J$ ~& D2 _6 Z                fds.SaveState( p );4 X1 b: U# c* X8 e, r; H
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 l7 u+ g; l) W2 c; p
        }% d, x. [; |2 E$ `. g0 w3 }" m& j
        // MMC57 [* ^& t1 t+ s5 C4 a) f  f
        if( exsound_select & 0x08 ) {
' v" Y  D! s$ O2 c                mmc5.SaveState( p );
% g7 \! R+ G6 G9 \                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 Q" `# H9 [3 O" d1 a
        }: D& J  ?  D$ q3 R
        // N106
8 X+ ~' U' L) R2 A6 Y/ ?        if( exsound_select & 0x10 ) {" D8 l: m5 T2 U& q4 Z
                n106.SaveState( p );  f2 Y7 L: S8 Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% }$ H. ~8 u* i+ O3 w& d
        }! @2 @* T% k% s
        // FME77 @' \7 r& s7 [  X, }+ l
        if( exsound_select & 0x20 ) {3 T' b1 C, p% f4 U/ k% m! Q3 E
                fme7.SaveState( p );! a2 V* g+ L; f7 w3 Q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 g4 F5 Q& d( \) s- C; U2 e        }' U' q5 S7 X1 E6 m+ n- q
; @; p9 ^6 N% s& ?* \+ S
#ifdef        _DEBUG
, v2 Y, [3 a& J1 w0 i! [' [DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );0 \" ~9 z' W4 X; o& o4 g
#endif+ v3 `1 V6 m3 Q4 g) o' C
}6 V" f: ]0 t8 h

. b. K. D0 A# Q( b: Dvoid        APU::LoadState( LPBYTE p )
2 V; A0 e' g4 n  b/ u{/ s" n7 O6 C* M8 H
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
( Z- t4 @/ r. w3 |        QueueClear();
/ }, @2 g* S0 i4 [! P
. I# w; T$ W- s2 Z$ w- b; B3 d        internal.LoadState( p );/ v* @! c& Z3 {" u) G* \# T+ r
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) v1 a! N0 b; a; F3 L% @
3 m3 f7 G1 I# h" d, D' m5 V
        // VRC6
% B& ^/ D% R: m; H3 h5 i5 e% Z% U: E        if( exsound_select & 0x01 ) {
: C9 C  ]% {% y: T/ @                vrc6.LoadState( p );8 g) R9 D; t* {( s% d+ p$ ~0 Q$ Y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# i; T( M$ F& j- j
        }
' R- Z$ N0 Q, C/ U5 J5 f* _) k        // VRC7 (not support)
6 U5 S0 B! V. D5 D, h        if( exsound_select & 0x02 ) {
% E6 u& I1 }8 ]$ K3 W) e# z                vrc7.LoadState( p );
- h8 G6 ]8 V% [7 n( c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 v+ P; E6 H, s9 m. _/ q7 |( \
        }4 E0 u$ P5 |/ d: Z% S* p: c
        // FDS' v9 A8 Y8 B1 D' a( X0 I
        if( exsound_select & 0x04 ) {
& J7 N' Y; C3 u                fds.LoadState( p );
  X4 K0 y, A2 t7 ]% d                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. h# q! m2 O' M4 b/ P+ K6 d0 t
        }
9 U' F% r6 X, H5 e; q        // MMC5
, L) t" D$ d+ E7 o% ^0 D7 Y5 ?  B, w0 g        if( exsound_select & 0x08 ) {
* ?5 B  W+ J4 E" o# y* j4 |                mmc5.LoadState( p );/ L+ m2 f( Q0 c' ~2 G8 T2 i3 c$ v: d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 W3 f0 T+ Z& {2 D3 j
        }; |) ?( B. M6 v! i
        // N106
  R0 h1 }9 G- g5 `/ }        if( exsound_select & 0x10 ) {7 V! L- l! [+ R
                n106.LoadState( p );3 R  m9 n; W8 I3 D. b/ z& d8 @
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  h+ N# V: R: \& Y' g
        }
# K4 ?' ]' I) ?        // FME7
3 ], Q+ ~0 }# `/ ~6 \        if( exsound_select & 0x20 ) {2 S3 f9 i* |& p: M- Y; o/ K) p% ^7 m
                fme7.LoadState( p );
7 z+ \; A8 d' G7 K) B" X% g/ \                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- B9 C/ G7 v1 T% g+ m& a3 P: S        }- N" A" p! U+ f; b$ P
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 L, X' U2 R. L% ?可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
" p$ D* k* I; v. B; M3 l% N感激不尽~~
1 D& p2 g; A7 J/ L
恩 我對模擬器不是很有研究,5 _" c( }* a: c3 h$ j
雖然要了解源碼內容,可能不是很困難,
" e6 L0 z' W+ t: d. m- ~不過還是要花時間,個人目前蠻忙碌的。
8 u! T7 B7 E" j  p4 O
7 T3 C' G7 ^2 e/ F! E; m8 ]給你一個朋友的MSN,你可以跟他討論看看,
. g( m: z! @, n, \, E: V他本身是程式設計師,也對FC模擬器很有興趣。5 ~, I9 O3 B: {
2 T2 X1 H* V; r5 D* H! m
MSN我就PM到你的信箱了。3 N: L+ @5 W7 Z- B" V+ B) I/ w

5 B% m6 [& C# q希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' T, |1 {+ q2 f) p. V; [" E
呵…… 谢过团长大人~~
0 O5 S* B8 W# S7 ^) f9 T& N
- q  Z8 P6 {* s; s
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 $ P0 j+ y5 ~) G$ ^: u' E! @' U. m
团长的朋友都是神,那团长就是神的boss。
2 j: H+ S! j- ]( K4 p
哈 不敢當,我只是個平凡人,6 E# B! W* V9 Z$ T5 \% N
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
5 S$ y& n' _  `) }3 F# J! w8 OZYH
" m# k  G0 x7 C( b% ^: T+ BQQ:414734306
# e" }8 Y/ J4 Y8 ?9 {  D( DMail:zyh-01@126.com
8 u% _1 b8 L) t* P7 n- _/ d' s. _4 G9 Z- G5 y  I! x8 ~: o
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . I" d; U7 q3 e: G- {
再次对团长大人和悠悠哥的无私帮助表示感谢~~

1 O) Y) V0 V7 P9 v不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-26 00:54 , Processed in 1.111328 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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