EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. a" `; E1 p. s* e7 v4 A9 s楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 e0 l, Z! {1 x3 ]9 Y  U这里有相应的模拟器源码,就当送给大侠了~~
) i' M& i( J. Y  H( r1 Uhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 / y( V' s+ p6 S* |# y; K# G; h
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。) L4 q" w9 H. _
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( Q' x+ x7 J6 a/ ^* I/ N: w& f这里有相应的模拟器源码,就当送给大侠 ...

; x9 L1 v& k" D2 n4 d6 C& B聲音部分(Audoi Process Unit = APU):5 w4 [1 O" q% b/ B" x% N0 h
.\NES\APU.cpp4 ]% S" W& U: L
.\NES\APU.h
7 `* x8 e' Y7 N' z4 [2 V0 M  W: N9 N2 O, f

5 |2 c& X# o: U2 q4 ~0 U影像處理部份(Picture Processing Unit = PPU):3 q9 @+ F% k2 f
.\NES\PPU.cpp
- k5 R; a/ t  a; c% h.\NES\PPU.h
3 E8 t: c4 |  R3 ^+ j+ Z
4 R. N- V5 h, ~$ {& h4 y/ _如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 u0 a/ Q6 ^6 ~$ q" x& k
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 c" w! P* h9 P4 i4 Q/ [
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ ]  u4 i3 r+ [, m$ c: o
//////////////////////////////////////////////////////////////////////////; F: r" U" U; h- G/ V7 F; u
//                                                                      //
0 O7 c$ _; B+ d, y+ o2 l& M//      NES APU core                                                    //
5 Z2 w! _; q" D5 f//                                                           Norix      //$ a2 m5 _! L: h
//                                               written     2002/06/27 //* c9 I- P8 U3 q8 G3 i
//                                               last modify ----/--/-- //7 p0 H6 {; W! z
//////////////////////////////////////////////////////////////////////////
* x; l3 m7 a3 w; x5 X9 T#include "DebugOut.h"% i. g- j1 o0 H7 f* o
#include "App.h"
# R6 d$ O! g/ L7 e( p: Y- v#include "Config.h"" i9 R6 d# {* p

) T+ Z$ M! }" o' ^2 |( Q  p#include "nes.h"
8 `9 x# n9 b0 F6 D$ A#include "mmu.h"4 C" U' g  x" H( F) Y% q
#include "cpu.h"* c5 j- W3 x- q' d; i6 }4 E1 J
#include "ppu.h"- [5 I2 K9 k/ f2 D/ q, H( u% l) g2 _
#include "rom.h"8 Z' }: X9 G0 C- F; P' k
#include "apu.h"7 ]! z8 W0 j' f' m
: q1 j7 M4 [6 e- ]1 ^) B
// Volume adjust
# g- `& g$ W+ {// Internal sounds3 O" v. z% h6 M9 g7 a6 y
#define        RECTANGLE_VOL        (0x0F0)
+ N7 ^8 z7 o) K- s7 O% x#define        TRIANGLE_VOL        (0x130)
% Y3 M4 R2 |% r: x; b5 O#define        NOISE_VOL        (0x0C0)3 \9 K: G* [) F
#define        DPCM_VOL        (0x0F0)
. y. f2 d; h& a  O0 B* D- f// Extra sounds
+ N8 d$ O8 e) }9 I: j# _#define        VRC6_VOL        (0x0F0)3 \# Z/ |! N' m8 P, ~* ~
#define        VRC7_VOL        (0x130)
: o+ c8 }, M: q% Q4 `  t! {8 _#define        FDS_VOL                (0x0F0)
. C, k( b  g7 T& t2 e) x0 ^+ l#define        MMC5_VOL        (0x0F0)
1 M0 [! f  Z9 {#define        N106_VOL        (0x088); x% i# n' M' K" ^7 H! k
#define        FME7_VOL        (0x130)
4 P: ~3 P$ u6 m7 ]! G. B# J0 }7 q/ ]* b8 g" |6 m6 m- Y
APU::APU( NES* parent ), A# D% {. B6 D
{
3 q) {. L: C: ~* I. J& s2 N        exsound_select = 0;
& }/ R2 i$ i9 r( r- \9 a4 i1 w6 {7 K. b0 x( {& z
        nes = parent;* M; f: N/ }8 b* S
        internal.SetParent( parent );
9 ~9 N, n' M# t6 u0 a: z6 {, K. h2 Q) n& F" w
        last_data = last_diff = 0;& Y% R# O  A3 j3 Q

0 Y! X8 y% n) ~        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 r, Y4 y- e3 U0 Y: S  f9 D9 |. q- Y; ]" X2 L2 s
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 f+ W+ B+ g# {; y. u5 C+ z  q9 K) V        ZEROMEMORY( &queue, sizeof(queue) );+ d* }- ]& a8 H* v
        ZEROMEMORY( &exqueue, sizeof(exqueue) );% s5 v, X' i/ J% B6 ~5 [4 u+ l/ _

3 O6 r6 Z% s, U- C        for( INT i = 0; i < 16; i++ ) {
2 g2 i' c% P) K% |$ J# q6 E- E                m_bMute = TRUE;2 C7 b! m: b) h6 @0 x# \
        }
' A) T7 f& Z3 P, L  [}
" {) a9 D" c( b. y# _# `- P9 Y3 |
APU::~APU()
. q5 P( J4 }  I{; A' z/ F* P" |- K/ D# B
}2 p  n9 I( l4 b/ {. }

6 W/ P9 T* a4 Z0 }. T" }void        APU::SetQueue( INT writetime, WORD addr, BYTE data ). @3 K. t1 E% O( X1 v- O% y
{" G- N8 _: I8 U% X& d
        queue.data[queue.wrptr].time = writetime;; t# ~7 ]! A( T( D1 w$ E  I' n
        queue.data[queue.wrptr].addr = addr;; d3 u9 w! I' b. a+ x5 R; E  o
        queue.data[queue.wrptr].data = data;; ^8 [$ B( q; l% L8 f, v2 ^
        queue.wrptr++;
1 q+ s; k6 l+ {; t% v& u5 q        queue.wrptr&=QUEUE_LENGTH-1;
5 F7 s- M/ o& y# U! w: }        if( queue.wrptr == queue.rdptr ) {
; \7 F& y3 l9 c                DEBUGOUT( "queue overflow.\n" );/ ^3 _4 W+ N* {8 y* \4 Q+ x# D# h
        }
9 v/ x! w* j/ o9 d6 K: E}
: k4 p: _  n7 q/ i. E2 A" v4 t1 S* e+ Q/ ]2 `' _
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
4 U& Z5 p2 K3 P; \: }) V{( @' M  S, k6 L3 r( Z4 Z
        if( queue.wrptr == queue.rdptr ) {
: T3 N+ j- ?! w6 o- r+ W5 N                return        FALSE;
# I  a6 u- b( P+ u7 b        }
2 D; B# q) u. g* G5 M        if( queue.data[queue.rdptr].time <= writetime ) {
; [# p- U2 I: V0 l                ret = queue.data[queue.rdptr];
: J( O, }& Z4 n5 K: Q1 ^                queue.rdptr++;9 c- D: ~; [- @# l9 s* N. b5 k7 u
                queue.rdptr&=QUEUE_LENGTH-1;
: ?' s; Y' G9 h2 J) h                return        TRUE;6 b4 f) S5 I; h/ }
        }
+ h" `/ e5 |+ v        return        FALSE;  B, q- ?& U# U: X3 K
}& D, U2 u% F3 B0 L$ i* z5 Y
* `/ c8 s: I8 M' ]
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )6 F: |: w" }# Q3 Y
{; Q9 I! A. ?. l% c; I, p: _  @
        exqueue.data[exqueue.wrptr].time = writetime;2 L0 I, G/ ^, o2 m
        exqueue.data[exqueue.wrptr].addr = addr;
& S4 P1 ^; M2 D. K        exqueue.data[exqueue.wrptr].data = data;$ i4 `1 ~1 O( T5 i9 j6 f) V
        exqueue.wrptr++;
8 N, u& b: u! p. M+ [        exqueue.wrptr&=QUEUE_LENGTH-1;
' A2 y5 a. G% w! o2 a        if( exqueue.wrptr == exqueue.rdptr ) {  c) [0 H+ D, x+ c- P
                DEBUGOUT( "exqueue overflow.\n" );% p+ s+ T0 X0 B- C5 \/ h  M
        }5 u5 A( D& m2 `* `- Y, Z
}7 p; s1 q3 n* L  e9 b3 G& r) N, o
. E" w6 @9 ?9 v: m
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )/ A) ?8 c# g; j  V
{
# w( U4 w/ D) v9 A        if( exqueue.wrptr == exqueue.rdptr ) {
# G. T* \, L+ W" u) l                return        FALSE;  Q) B6 r. y6 Z9 Y3 O/ S- v
        }
0 `3 Q# z9 a2 }. B- B, O        if( exqueue.data[exqueue.rdptr].time <= writetime ) {( K6 B# ~  p9 y9 [  u
                ret = exqueue.data[exqueue.rdptr];
% A$ E& X0 R0 T% f                exqueue.rdptr++;8 K+ `( y" P# Q3 f0 D2 B6 O
                exqueue.rdptr&=QUEUE_LENGTH-1;
" f8 y0 u, R/ M' f6 g+ l                return        TRUE;
, E1 W& s! e; D8 A! q0 d        }
4 q: k+ e$ l( z% S& @        return        FALSE;
+ |" B" G/ i1 z! W2 \2 p}
% {& y" k$ N2 [; u
% _* ?+ Z; a. H2 M6 g2 kvoid        APU::QueueClear()8 e8 j/ W5 a0 |; n+ o& {$ Q6 }
{
7 J; F" |6 c9 L7 e1 g! u6 i        ZEROMEMORY( &queue, sizeof(queue) );: L% \* B* ?1 j) u) A0 f. z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 B8 f2 \8 \: n# Y4 G3 S/ T}
+ I7 {6 i$ m! f4 U6 b; R
8 c, U' n+ J* V& B8 j% o9 \void        APU::QueueFlush()) Z6 w/ X$ s* W# b
{
) U" h' y2 \4 o) X        while( queue.wrptr != queue.rdptr ) {( Q7 W6 ?1 k$ C3 n1 s
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 C* ^5 N' U7 _, g5 \  @5 N
                queue.rdptr++;4 d" y; q1 _  }$ U9 N
                queue.rdptr&=QUEUE_LENGTH-1;
6 N" _: }* ?3 e0 @. G$ L# S% c        }
' @' r5 K, c' \5 ]0 c, n/ s8 E  T  @& V1 U
        while( exqueue.wrptr != exqueue.rdptr ) {! K4 J. `8 h% o
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
3 M8 W: R1 ]; z# }                exqueue.rdptr++;, Y; r; s0 a- @% W# W
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 u! y; c; Z, G5 k2 U        }' H5 Z9 ^) Q( J; ]$ h
}. x5 i) ^8 j0 G$ B* ?, |
) g7 O& ]1 {+ m6 L- I' T/ v
void        APU::SoundSetup()
; V8 |- ?3 X4 s$ r{
4 ^3 v+ c4 ~* e2 C8 J5 v        FLOAT        fClock = nes->nescfg->CpuClock;
& ~6 C' j. n# ?, A9 A6 z        INT        nRate = (INT)Config.sound.nRate;. P0 ?$ ]+ A) E1 U' C, m% K
        internal.Setup( fClock, nRate );
. S' M* H' u7 O3 s+ O, R; d8 E        vrc6.Setup( fClock, nRate );
0 k1 O+ y0 I& m) z+ R! C) o- x        vrc7.Setup( fClock, nRate );
; T  F) ~; T7 K7 D% z- ~        mmc5.Setup( fClock, nRate );' L) a# v$ k7 Q: y) h! ?. q' X
        fds.Setup ( fClock, nRate );. A' R1 H; |8 k/ Z; y
        n106.Setup( fClock, nRate );
+ V' `, k& r4 I1 J' F/ x        fme7.Setup( fClock, nRate );4 a: E! ?' Q$ U6 n0 A' A( {" ~
}. j: P1 A' e" T

. v$ b+ C# q+ Ivoid        APU::Reset()8 o* t9 f6 g0 b8 P: q$ u" @1 T7 X1 \
{; p6 h# s, g2 {, M
        ZEROMEMORY( &queue, sizeof(queue) );( G" t' T1 V6 }/ E# p' a" }8 h& j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ H  s  X9 U2 S5 m0 \8 w9 v& p/ [5 F2 I/ x# h) w0 g  Z
        elapsed_time = 0;
* v2 l, \. Z5 b1 T, N, \% S9 T! [/ [8 J/ j
        FLOAT        fClock = nes->nescfg->CpuClock;0 O( Z" K. [. w. l
        INT        nRate = (INT)Config.sound.nRate;
4 P1 Q$ y: o; @7 {        internal.Reset( fClock, nRate );
: T, w( W; E7 {6 E! @        vrc6.Reset( fClock, nRate );
+ k( b; M0 B/ u        vrc7.Reset( fClock, nRate );
0 h5 e, W3 O, l( B) }( S        mmc5.Reset( fClock, nRate );# T4 p- K9 P. S# E0 {1 ^
        fds.Reset ( fClock, nRate );' S2 C7 ?% [9 K/ s! ^/ m' c# [' T
        n106.Reset( fClock, nRate );
  x, [) c  w* `- |7 {  m+ K        fme7.Reset( fClock, nRate );, z9 C9 l6 e1 C  K+ t
4 z) A% p  @" }
        SoundSetup();6 o/ v6 \+ ^% v9 ?4 P
}/ h! o8 r7 t. l# m2 W

/ Q- R9 d# I7 r! }void        APU::SelectExSound( BYTE data )) b# Z6 x6 }6 E* G( A! B. y
{
) e. i2 p' B$ w+ L$ k6 P( o# B        exsound_select = data;
; S$ |  K  y& ~5 g  I}, i; B  ^2 `$ X  b6 i/ D
: W: X+ a4 Z3 p1 W
BYTE        APU::Read( WORD addr )
9 D: c' w- L" v. |6 u1 ]9 [& x" f{
- y4 T! I( T1 a8 }) b6 M        return        internal.SyncRead( addr );
- r+ Y3 j9 k0 U}
: Z2 U3 X% s2 C+ U1 f+ v$ H% |$ Q
" |1 j: J/ \+ u% ?+ u' }$ z0 rvoid        APU::Write( WORD addr, BYTE data )* s( D& m# ?( |0 s
{7 R2 H1 `! F$ R2 p: \' ?: ~, E
        // $4018偼VirtuaNES屌桳億乕僩* Z  I* D. d. ~; ~- P3 H
        if( addr >= 0x4000 && addr <= 0x401F ) {
* }# I, @2 t1 q% R$ E# |2 F/ B                internal.SyncWrite( addr, data );. o1 ]. q# D% T% [! @3 a& ~
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
" {* w8 ^+ ~2 z. }7 P" K        }) c, J1 Q1 |! P2 ~0 e- W
}' B" y7 s# h# s3 d
& B% X" f3 P4 `0 @" z
BYTE        APU::ExRead( WORD addr )
9 j( u8 J2 o9 z{$ O3 l4 ~, ^2 y
BYTE        data = 0;9 a" l$ {2 s# _6 f6 H; n# u
/ F/ `1 t; e  k2 _. r  V
        if( exsound_select & 0x10 ) {
: T- C2 K1 |  ~. E' W                if( addr == 0x4800 ) {  v+ c6 ?  {' p5 |
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );- X4 Z; m; n. h  ]
                }
4 O$ N) o8 S$ M6 Q# e        }- b. y  z% z/ T" x+ S7 k
        if( exsound_select & 0x04 ) {
+ O( S( `: ~9 y' J6 M3 l+ n* J( _                if( addr >= 0x4040 && addr < 0x4100 ) {$ |, A/ P4 Y- a' L2 H
                        data = fds.SyncRead( addr );# \* K& `2 ~  }$ u
                }9 |% ~% A; p: O# h7 k% e5 W. T
        }& `( f3 i7 @, K+ P6 O4 g
        if( exsound_select & 0x08 ) {
" n9 P' V+ Z0 G% r% D                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ {/ c( s0 K" {8 l; ^                        data = mmc5.SyncRead( addr );+ ^& Y9 _0 S5 g& |
                }
9 K) G, l3 X# G  d        }
' o' v3 q3 f) r! G
% t  c* u# O9 u! c" C        return        data;4 [1 `+ k% f' x
}
6 g' {( b9 \5 Y3 D4 ^2 |9 H+ H
0 ~& y+ `/ l" c7 j6 b% w& Bvoid        APU::ExWrite( WORD addr, BYTE data )
5 \- k  A6 a! x0 L* {3 I{
/ W; I) v) A/ i  E1 d3 `( G        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
4 A2 E, ~" \- x, T' g: c
5 @4 }! I5 n, T1 h: g        if( exsound_select & 0x04 ) {
2 |' l; |) ]: n" H+ t$ E                if( addr >= 0x4040 && addr < 0x4100 ) {" |, e2 @* T* F" ~3 Q2 }! r# u
                        fds.SyncWrite( addr, data );4 o: [$ N+ N" X8 M! U, I* N9 W
                }
* g2 W) [2 W% j, n+ P- l( b        }
6 y) t1 Q" j& L1 h4 ]3 F
6 C% t) A8 L# ]8 ^, P        if( exsound_select & 0x08 ) {6 X' d5 ~, S: N: F
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 G& y6 C3 m, G4 v                        mmc5.SyncWrite( addr, data );
2 C! I2 P, O" A) r                }
1 W; D% N0 ]" n: h        }7 q. ^9 P/ V, b" L, y
}0 S4 H9 l& j! J8 h) |. i
* R! w  i$ |# r
void        APU::Sync()2 P9 M8 I4 ~( R) g/ x; J1 }; d4 T
{
3 |( r8 n0 I# b; H}/ o; h. o0 w2 a
6 K8 k' U* A+ {5 V
void        APU::SyncDPCM( INT cycles )
/ g- C, m2 ?& l1 I, n{
0 c' N1 j0 S& |2 w. T4 b        internal.Sync( cycles );) }- H" d9 \4 E9 p- C
7 \: }2 _) q; S
        if( exsound_select & 0x04 ) {& q: b6 w1 ]. @- i. Q3 ^
                fds.Sync( cycles );  G) R4 f( A$ P6 S# l$ p6 E
        }! u) i7 t% w3 S7 x2 K" G
        if( exsound_select & 0x08 ) {
- u9 b# J* _. p8 v6 c                mmc5.Sync( cycles );
/ V$ v+ _! i5 i- q/ a  X        }
7 g  W. V% V+ o1 _0 U6 L! v}$ V6 p. _5 t2 V( t

% I4 N9 Y  \: r# w1 [+ z' Mvoid        APU::WriteProcess( WORD addr, BYTE data )
* v# d! j( P* ?0 |{
* e) d% w& I7 W1 R# B  ~        // $4018偼VirtuaNES屌桳億乕僩
) K0 k7 U# P! @7 b        if( addr >= 0x4000 && addr <= 0x401F ) {
4 z5 L. ?8 ]/ Z. x. e! E                internal.Write( addr, data );
6 A5 V) ?, D6 ^$ C8 z        }9 ~( _- h0 [4 m; e$ w
}
5 F" D2 `, J% C* N; Q9 @+ O- w9 }/ D0 B3 X2 p- ?$ W
void        APU::WriteExProcess( WORD addr, BYTE data )
1 U" b' ?' O; Y; b7 U7 J{: M* ?, n0 L  `/ ~1 N8 h. A, K0 e6 x
        if( exsound_select & 0x01 ) {
- c- M" q0 `/ O                vrc6.Write( addr, data );9 D/ m1 Z) j8 P. G+ q
        }
1 l5 q; G( D, M        if( exsound_select & 0x02 ) {
3 M0 c+ e! G* s                vrc7.Write( addr, data );+ Q- z- m1 R3 f
        }) k; `$ a# V" S' |1 j
        if( exsound_select & 0x04 ) {
" O) L5 \% M: @6 [: s/ m, D                fds.Write( addr, data );$ e) f: e1 E% V0 z* L% C
        }' `' d) j! s; k% c  P% R
        if( exsound_select & 0x08 ) {
8 S. [$ p. E5 R+ H! d6 N8 R& @                mmc5.Write( addr, data );# P2 \: R$ ~% e& j* R
        }+ J) G( B2 I4 p! J# W
        if( exsound_select & 0x10 ) {# ~2 h. |9 X6 k# x+ x6 m6 f7 k. L: h
                if( addr == 0x0000 ) {
' M7 _8 d- f0 J0 P                        BYTE        dummy = n106.Read( addr );
% z8 {: x9 v* A8 G                } else {
0 f/ p- S6 e% T" |0 K1 }% E                        n106.Write( addr, data );/ j4 _) c0 s9 p7 g5 w; N
                }
2 w- E" [9 @. f3 G  w1 n/ G4 z        }" S6 y$ `. }/ q% h
        if( exsound_select & 0x20 ) {
% w4 i& O4 o, ^3 \4 c4 L+ [, R                fme7.Write( addr, data );
3 `3 R% S3 h* G        }, j  e, H0 r1 {
}" h; |5 v8 L8 s! v

9 ^; O' X' v' H2 D- gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
2 B! [9 T2 ^' u6 H& h5 F) Q: q8 l{/ K. a- e8 r# i2 _  r; J% ?
INT        nBits = Config.sound.nBits;) v) |- T5 i9 i' R
DWORD        dwLength = dwSize / (nBits/8);
: D9 T  K! }% j' N4 vINT        output;5 v1 n. D, b- r* H2 F
QUEUEDATA q;8 ?! `; {8 T% I9 {$ j: p9 r" W
DWORD        writetime;/ {; X$ P( V0 C
6 R* m2 U4 O* H( U) l( U: o/ M; L
LPSHORT        pSoundBuf = m_SoundBuffer;
9 z) ~" T5 h; H: A; y) a# PINT        nCcount = 0;
8 q' Y- v) Y( g: z8 A/ ^4 f9 q" D5 ]6 E& s, c
INT        nFilterType = Config.sound.nFilterType;5 j6 u5 N2 E6 O$ X) a
3 c5 e- k" W+ ?: X3 @* O
        if( !Config.sound.bEnable ) {5 P0 e% }6 k, j( q( C" G
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );. G; r( s5 L& H0 Y0 k
                return;
" v$ e8 Y8 Y2 A) \( I' p        }
, X5 v, s# @. m+ I9 Y! a5 R, _- _+ p( c5 a$ X/ R# d
        // Volume setup0 O- D9 o! S6 r, h% p1 d$ l8 r* J- O
        //  0:Master6 P; m- o  L' h7 [& p4 r% _' y) c
        //  1:Rectangle 1
$ `/ X' m( j  Q7 m  `! v+ X3 `        //  2:Rectangle 2
3 d) F3 v2 ^( M- E, E1 W        //  3:Triangle  \* r. V6 ]5 n: ^  ~! p6 H0 W8 A) `
        //  4:Noise
$ ~% p% Y- P; Z* c        //  5:DPCM
5 k! n  \1 [2 M8 A* `        //  6:VRC6
5 }1 \# u3 m3 x% l/ i        //  7:VRC7
% V1 ^+ O' T5 M# U$ p7 _# ^1 a9 w        //  8:FDS5 K: f% t% b9 Z' ]9 j- h% d
        //  9:MMC50 Z! e% |) x; H: R$ O" I
        // 10:N106& f7 P; u2 D" j
        // 11:FME7
& ?3 a1 k$ |7 i' z5 [. C        INT        vol[24];
" S" Z7 ^5 m0 y4 `6 y) J$ U7 ^        BOOL*        bMute = m_bMute;' Q: z! Z# ^! a' e! v8 H5 [
        SHORT*        nVolume = Config.sound.nVolume;
; M* z3 F* J5 n  Z, P. Q% i) w( y7 N3 B% S6 ]1 W
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
. O4 x8 A/ o$ A+ P5 l6 j" [" `0 l# ~% F1 @- e; _' W
        // Internal( Q% }' u) p0 }+ T# Q1 D8 t' I
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( N8 e5 p+ b% @" K        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;3 I; [' N3 q4 }( ^, S
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;. Z6 Y9 ~% E5 d4 a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ Q; t: S: i7 P; G* ?3 _
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
- x1 |% p2 K$ o/ c6 B
8 t  P6 V0 U( V7 v        // VRC6% n, H. H8 \/ F: Z: T) p; G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, U. s4 c5 r: R& A! U        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 y. O3 h& e0 H% b3 ^4 t) R
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 f( d% l; i, [4 I/ D9 n& K+ X8 R+ p

7 Z/ ^! [, l4 @        // VRC7  U" z: C1 _( i( \* C
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 ~/ E2 w1 A/ f
6 q3 B( p4 ^3 k0 _1 G
        // FDS
5 d. p/ P# P/ L! L% a        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
/ z5 @2 t' H5 Y$ u3 R9 E9 U" k
+ H- M8 P% k& B+ ^7 X. W* }( C        // MMC5! L2 c$ d( f+ T5 g1 K/ C" K3 R
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" A: y/ i5 F3 p8 K+ c. I3 E; C; Q+ i        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; v- j, x8 Z" `" t" A' M        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! X1 o' h/ g8 T0 o

* V" J' U9 ~( g3 b- T7 P$ h: K. \        // N1064 p3 A( |7 ^: p: b8 Q; m7 H
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ ^) D$ f7 z7 x8 f. P4 b
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 {; o# M" F, L+ r% p: d        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* n4 T; l9 S7 S& X
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 ]1 O& m  @7 U/ Q' U' O
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 E% s1 q% i1 e+ ~: p! Z        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# }. Q2 D& M1 q# t: s% v' K1 T        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- [8 L! M( ]( I1 I5 B
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 |9 j4 L( ?, G0 G7 v+ V+ G2 d$ o

; S1 z- G/ w+ D! `) u        // FME7
/ s0 I/ s% Y1 b$ H        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* L9 f0 W0 q' n, F        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! ~" s; F5 n( a! C0 g0 c5 u9 J        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 Q9 n( l! v+ Y% C" o& b( V9 [$ y4 O' I& o  D9 ~+ a
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" P7 n7 U4 f8 _0 l" k8 @% }/ Y- Y9 p
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 u/ z; D' h, B, _  {; ]

1 m% z  n9 b. u. B/ M; Q: L        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
6 _. [+ C, w5 c5 p( L; x+ }        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
/ _5 p$ Y, A  B7 K5 [                QueueFlush();
& i# B4 D; Z& k' e' t        }0 `. b0 F; ^$ P% e/ t9 w6 l

  ~/ Q. v) |0 l% m5 \- r0 c$ z" `( J        while( dwLength-- ) {8 l6 @( m: R: Y" M- s# k; s
                writetime = (DWORD)elapsed_time;
# V& `$ }% n. k1 ~
3 p" I+ y, D# I  u& |/ R% X                while( GetQueue( writetime, q ) ) {
- V+ O$ |/ y& Y' a6 z; G3 v. S                        WriteProcess( q.addr, q.data );
7 @/ b3 A+ r7 ^1 V* D/ f6 T                }: W" x1 l) G% s8 @) |/ ~. ^

% U; F" O- e1 `( N& r* y                while( GetExQueue( writetime, q ) ) {
4 P% y& z( @. C! J& H6 S! i                        WriteExProcess( q.addr, q.data );8 U  b/ W4 n9 ?2 g( j& f( v
                }% Z( I4 v( [) W, d# |$ r7 ^
- T# q3 \0 A4 W! f
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" D9 H" r. b$ A5 _( ~                output = 0;
( v' X5 B! r& R9 D8 B' c, a                output += internal.Process( 0 )*vol[0];
8 j) k( d6 M3 g0 c- q                output += internal.Process( 1 )*vol[1];
0 d" s( O* i' X0 {$ O5 o, p                output += internal.Process( 2 )*vol[2];9 e" L' S; X  E9 R; K+ N
                output += internal.Process( 3 )*vol[3];
/ z$ l5 D1 w! I" j* V: `                output += internal.Process( 4 )*vol[4];$ x3 h+ |6 ~& ~/ }( x2 [3 M

3 n4 }- w; G% M                if( exsound_select & 0x01 ) {# W% e8 N9 v7 {5 j! \
                        output += vrc6.Process( 0 )*vol[5];
, N. u4 [' @& Q                        output += vrc6.Process( 1 )*vol[6];9 P3 P# W  z6 l) U# q6 X
                        output += vrc6.Process( 2 )*vol[7];* H8 o' k% x7 x$ z, X3 K
                }% ~# H' y2 |0 ]% B
                if( exsound_select & 0x02 ) {
- b9 X& f, }1 q                        output += vrc7.Process( 0 )*vol[8];
7 T7 c' c1 E  `5 D4 f                }
& ^+ x" ~1 }3 P                if( exsound_select & 0x04 ) {
2 O! P6 E2 p/ O- }3 @9 m4 j+ V                        output += fds.Process( 0 )*vol[9];: X6 x* \, ]4 G
                }7 \3 X8 q8 t$ f* D5 O% q
                if( exsound_select & 0x08 ) {
' k5 I# ^3 o1 z                        output += mmc5.Process( 0 )*vol[10];
7 }/ L- x: I+ o6 F7 T                        output += mmc5.Process( 1 )*vol[11];
0 _% |- E& K! A; d# ?7 z, ]                        output += mmc5.Process( 2 )*vol[12];
9 ]- f) i, [) j% r- Q0 N                }
, }- D. ?; Y, m$ K- u                if( exsound_select & 0x10 ) {
3 k& F; v: o0 V                        output += n106.Process( 0 )*vol[13];& A/ }& z7 w" k0 v2 `$ l
                        output += n106.Process( 1 )*vol[14];
$ T2 E3 O, i* f3 K, p3 P. w) ^) W. m5 I                        output += n106.Process( 2 )*vol[15];
! d, w4 \: ]- s3 C- ~" h9 Z+ m                        output += n106.Process( 3 )*vol[16];
( f3 v+ V$ k- K# ^, [  c; Q) C* X                        output += n106.Process( 4 )*vol[17];" Q. {% |2 n7 Q5 }' ~( Y% G) W
                        output += n106.Process( 5 )*vol[18];1 V+ b1 F; U3 S0 e
                        output += n106.Process( 6 )*vol[19];
. e$ c" G1 V1 O; Q7 ^+ C" C                        output += n106.Process( 7 )*vol[20];
4 R6 R( }& u" A! @9 o1 w5 h4 N' C) S                }
: X8 Z( K- C4 A& R- Q. G                if( exsound_select & 0x20 ) {8 X: a# l3 V& A
                        fme7.Process( 3 );        // Envelope & Noise
7 o- F" J& \0 I4 l$ e7 h  b4 m                        output += fme7.Process( 0 )*vol[21];: J# h  T( A3 r- T6 o
                        output += fme7.Process( 1 )*vol[22];
" n- a, \5 H) V8 v% @% M                        output += fme7.Process( 2 )*vol[23];# d5 c. }' D+ m
                }
- o; z. U+ K5 `" `' L" Z/ b% L7 k4 M% f& G
                output >>= 8;
7 E8 O4 x  z& K8 {/ e" W8 b
% B# g6 X! Q- |4 @, {. F" Q8 P                if( nFilterType == 1 ) {4 L, Y  P% c5 Q5 i7 X7 P( B
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 N7 T( C% U2 L0 [/ E/ D1 G: q
                        output = (lowpass_filter[0]+output)/2;
8 o: o* R+ O# ]; ~                        lowpass_filter[0] = output;
0 w3 _. d: q+ j! l, S2 `                } else if( nFilterType == 2 ) {
4 Q( I' l2 {2 C! ^                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 {) ]# G; _5 Z                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 o. F0 M& |" z
                        lowpass_filter[1] = lowpass_filter[0];6 z) O7 ]1 M% O
                        lowpass_filter[0] = output;
& ~2 ^$ M2 |1 w' L: V  X6 `; R$ M                } else if( nFilterType == 3 ) {: A- \( a3 `- t8 D
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)2 n% F- u1 B4 j; L. C1 `
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
, O# E! f7 X* V0 P( c/ O, a                        lowpass_filter[2] = lowpass_filter[1];
% P6 W4 |" G) U+ @                        lowpass_filter[1] = lowpass_filter[0];5 p0 L2 Z' h: F5 D4 A
                        lowpass_filter[0] = output;
2 H& q: b' @+ d6 Y7 L+ o; p" ?                } else if( nFilterType == 4 ) {; H# S# W/ C& T/ ?4 L) `
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3): H5 I" Q5 s$ U: \6 ]
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
6 c% X9 P) ?9 J9 b1 X" D                        lowpass_filter[1] = lowpass_filter[0];3 k$ r. a: ?6 X8 ?. _% A/ I% q
                        lowpass_filter[0] = output;
7 Y& h9 _. H* l6 S# S                }
3 g$ X0 \1 j; V5 ~" g$ F  X$ }
$ ~% t; S/ T; J) v, m. W#if        0
& N. I# ^) n/ p; s6 T                // DC惉暘偺僇僢僩0 L. y$ f3 Q% a0 T' K
                {
* ]7 H& o5 n( r" q                static double ave = 0.0, max=0.0, min=0.0;
: e  V  o3 [5 o                double delta;
8 {$ H0 ^, S4 l6 ]                delta = (max-min)/32768.0;# M* s& [% Q+ n: e
                max -= delta;
6 h( b7 O4 }0 |7 R                min += delta;
8 n7 D& T! Y6 Z' a                if( output > max ) max = output;
7 U2 x% B3 m' c' E                if( output < min ) min = output;& L9 [# h; Z9 v/ O* d- k7 N0 V
                ave -= ave/1024.0;
, Z' Q. L2 c6 f- K; i# F                ave += (max+min)/2048.0;
: N' q  r6 S3 [2 c) T                output -= (INT)ave;
& B. \9 O: y9 d% a3 l                }  K' y6 f( G* Q" [  W! t' j
#endif
& R0 n5 i. V% h#if        19 ^2 o: d1 }4 f3 u; x
                // DC惉暘偺僇僢僩(HPF TEST)! h9 R9 I4 ?- }8 I
                {
& f9 B9 K9 y* N& O3 R0 Z//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
1 L8 B: O- S9 \7 {) e; G1 x                static        double        cutofftemp = (2.0*3.141592653579*40.0);
, x4 x2 Z; B( R                double        cutoff = cutofftemp/(double)Config.sound.nRate;6 U( [1 N( f" Y
                static        double        tmp = 0.0;3 ^# J) _6 t7 Z' K2 W
                double        in, out;' O, k4 {) U+ ?4 k, f
! ^) s% H8 f% Q9 \5 Y
                in = (double)output;7 t. E; H  `5 v: u
                out = (in - tmp);
+ d6 E1 y; k* I$ P. i8 P% I! b                tmp = tmp + cutoff * out;4 t# R5 [) D8 H6 W; H( e

& Y+ U% X( r, U6 X5 W                output = (INT)out;- N; `) D" Y  |/ o/ k
                }
/ o4 N5 r) w8 p, i  n! Y5 k#endif% r5 _7 j* @$ x7 E& C; p2 F  m5 }7 T3 {
#if        0
  G& M2 A4 l* q* ~                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)( G4 P, y( Y6 K
                {7 |2 J  L. Y0 k
                INT        diff = abs(output-last_data);/ n+ ?2 n, L! j! o& v* B
                if( diff > 0x4000 ) {
" g( t3 x: m8 B3 ^/ U% E: M. z                        output /= 4;
6 a( U; p6 k! d4 |4 D                } else " K! X" \9 h# \
                if( diff > 0x3000 ) {( i7 }: S3 }7 \/ @% ^
                        output /= 3;
& K+ D* U- v+ |: `# h) D                } else
2 G$ D" U6 f1 y                if( diff > 0x2000 ) {
. I! @: F# g8 K" I                        output /= 2;* r6 u/ `" g! @8 K  n# ~
                }4 _; w& A, |0 [) {; i3 _
                last_data = output;% F+ c7 Q5 A- s2 y# D/ ^! J' K
                }$ W# Z  h  g$ P+ n; S3 K- R
#endif
( Z1 z8 F# \  a$ [                // Limit
& ^: D. Q1 g5 {5 Z. s2 s" V% s8 z                if( output > 0x7FFF ) {. z3 m5 c8 e9 [( B' v" o: l
                        output = 0x7FFF;* ^. e- x5 p1 ~2 H7 V6 N; I: R1 J
                } else if( output < -0x8000 ) {. i2 W& A+ T4 v3 J
                        output = -0x8000;# T4 O2 @$ G4 z  v  i2 ~$ m- J. r( y8 d
                }( `& v5 U: ]! @- `
& V5 O; f- ?5 g: o6 @, M/ x
                if( nBits != 8 ) {& q: b1 p5 o) A1 Q7 n
                        *(SHORT*)lpBuffer = (SHORT)output;
6 M( ?4 T9 c* k: x: ^( H                        lpBuffer += sizeof(SHORT);
$ S2 h6 h+ _1 j) a$ g* T% U6 S( L                } else {" D2 I9 m# J9 [0 c
                        *lpBuffer++ = (output>>8)^0x80;' N" A; U. B! _0 V* K% N
                }$ c) m  r2 t9 ~$ M
1 m+ v+ Z0 d  y
                if( nCcount < 0x0100 )5 X! O* U2 p$ K' X4 h
                        pSoundBuf[nCcount++] = (SHORT)output;
& z+ }% E( M0 J  E& v& q8 o, {5 j: {9 h# H
//                elapsedtime += cycle_rate;6 F& `  v% r( E$ ^/ |2 q% b
                elapsed_time += cycle_rate;  ~4 P9 \+ y: \) }5 Z  K
        }
4 |* d0 B, d- T; O& q2 G' e$ m7 i9 \
#if        1; S" p$ Q8 ?3 j, ?! e( k, `
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ o% _  H8 G% d6 T& b5 `4 G6 z
                elapsed_time = nes->cpu->GetTotalCycles();
5 A. y; x  X+ {: V8 i        }
1 N+ R- J- u$ D        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {; H6 u1 f  {; h, y0 Q7 z4 f0 H
                elapsed_time = nes->cpu->GetTotalCycles();
# D) e6 w8 d5 G( W& k        }
- Q$ y9 g" `0 B$ \) P#else  D! J% c; B! X
        elapsed_time = nes->cpu->GetTotalCycles();
, i' a, `' [# ]2 F#endif
+ s2 ^& U* N) R/ O% k- V, X* L}
! H! H$ o7 g  M, R+ T9 k  W9 B# p/ t$ S! ]2 K
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
, M) F& K: a- \+ e% nINT        APU::GetChannelFrequency( INT no )
, c- v8 q1 E% s$ W{
' r8 |( f+ Z0 q3 ]2 g        if( !m_bMute[0] )4 B! }' L' x* l+ R  D
                return        0;# B4 V% ?" l5 l7 M, H5 K
8 S' n% i" I$ z- \& u3 r
        // Internal
9 P$ V$ g* }. F$ l  F; r        if( no < 5 ) {+ ^" v+ P3 W6 z* T
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
  U' j. L0 q, r4 T4 T        }$ t* I( `2 m6 B# ^
        // VRC6
$ i' r' \' E/ d9 u- Z1 i: K- d        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {# M( E) {3 \5 o
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;, X) k' M6 ?; z/ P+ j1 |" X
        }
, u: d1 }3 l, o        // FDS7 X. h( y# Y# L6 C1 X2 A7 R
        if( (exsound_select & 0x04) && no == 0x300 ) {$ F5 K5 a/ A/ u8 F
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ B2 m/ N( C) q: q6 Q1 a* w4 }        }- g6 Q  d, k- M# ]6 e. }6 ~; r
        // MMC5
4 N8 p7 b% q. d. L& z6 o0 c: N$ I' i        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {" n% Y6 ?+ }8 e% y) s" [4 s
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
' [/ ~: y; s/ V3 i& J: ?  G# w        }; |) F$ [  _. y1 _0 g$ p
        // N106
  j( O6 N4 h5 `        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 s4 K* U, G0 m# e! K2 W2 h) |                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
$ Z3 J5 O: t9 B# I" k; u7 r, c        }
$ ^1 x) w6 ~. h# h3 x0 G        // FME7
6 v2 y+ R3 |# D. R& w. _% E4 |/ h        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {: T* ?7 p1 _' j1 i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& o/ `& w+ @% ?        }5 e; h8 y; n' z) r( A' Z5 ]
        // VRC7
" F4 u4 g5 z% M! G& T3 x( [8 F8 c        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 L" v- Q+ q! U4 r0 K. ~7 f- V# s+ v- b                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;6 W/ u$ G9 c) e
        }/ j/ Z, \- E- s* Q3 v8 v& N/ A
        return        0;
+ ]' c( C9 L8 u5 ~4 ?6 U4 }}' d- W% R% L. K4 h/ x5 q
1 v$ l- v9 r7 G1 W$ Q! Z1 {- W7 X
// State Save/Load/ _& T9 H5 A5 q) Q" w0 }! W
void        APU::SaveState( LPBYTE p )
5 \( c, [: P1 q* \{: P8 n; t8 }/ Y8 t' f
#ifdef        _DEBUG
) l, d4 [1 k0 m0 q6 D$ ]LPBYTE        pold = p;& ]) i  U6 X; Y) z' V7 `3 E
#endif# Q$ T4 I1 t4 z, g0 ]

% z4 E$ C' Z' _2 T- V        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞0 E! N6 t3 Z& c: K
        QueueFlush();& {% A& B& o! b+ B# h
# L+ i, e7 \% e) M2 V
        internal.SaveState( p );
5 s- K4 m' M- z+ d8 v, _$ `        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 j- H7 b: d# _" |% [. ?5 ^% n) N2 T+ M
        // VRC6
/ h* V% |! D+ _% ^( p        if( exsound_select & 0x01 ) {1 \7 f" k3 r6 o
                vrc6.SaveState( p );/ j# C2 v; \! X- N1 i6 T
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. b+ c0 l0 x$ N/ ~* J, P
        }6 T4 ?2 u$ k: S/ n8 W3 ^
        // VRC7 (not support)
% g1 O; f3 [1 O) S  t  H4 Y        if( exsound_select & 0x02 ) {
3 T. h$ W1 |$ J1 F                vrc7.SaveState( p );
, W( Z. V9 Q+ r0 p6 v) Q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( z2 ~( e4 a4 `: `7 J! J4 K; h; M
        }
, g0 J  V6 P: }, l        // FDS
" G6 B) L8 F* o8 K9 @        if( exsound_select & 0x04 ) {$ g, G6 D- j) }; B, J
                fds.SaveState( p );
" D9 p: y! Q# g: y1 g7 q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! k3 g  f2 a1 }: S9 ~  @
        }/ t7 |4 P% \4 a/ j
        // MMC5& S: @2 W4 U0 ~; w- r
        if( exsound_select & 0x08 ) {
& T6 k& F' L$ }1 C' W                mmc5.SaveState( p );. i8 C$ Q7 }; d0 ~8 ~5 L% q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding+ K; r2 m" Q8 f+ }3 h7 \; r
        }' A6 ?+ A) K+ `3 z
        // N106
4 @! |; y( n, X7 l: r/ g        if( exsound_select & 0x10 ) {
8 ~4 L" P0 `1 Z* t                n106.SaveState( p );
: z5 @+ p' m# G                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ k( Y+ ~* s8 k8 \8 _: l, Z  D        }
; D9 @- Z, e, g        // FME7: l$ u* E2 d' ?$ s! i; K
        if( exsound_select & 0x20 ) {
6 l" Z4 A9 [0 E0 H7 C5 K                fme7.SaveState( p );
8 _  e# ?" k% T) P0 P& D0 T- B# Y, p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# r* m% b9 S8 y( @        }
% M9 q; I: t8 j. s; [1 U
" L' z! G6 T0 X. Z( d5 I6 X#ifdef        _DEBUG
6 F# t. Y( Y' h3 P4 {; {' ~1 QDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 b4 s* `2 @. J$ \! Y% ?% `#endif9 A0 ^! C0 L) ~% @
}
. m# K& I2 r+ A0 y, O& }7 @* {3 _
" `. G& R/ T- k7 Y9 y) S/ X2 Gvoid        APU::LoadState( LPBYTE p ): j9 t2 N  L2 p  B5 [# Z  f
{
, L, \6 E# }4 ~9 s4 G        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 v0 o* e# ]$ |* F
        QueueClear();
+ e/ l+ [+ t, R! |9 F9 j# p/ P. \% G7 K: v7 E3 m  d' p& n
        internal.LoadState( p );
8 ^. u! f7 ^  Z; H) A' K! [4 T        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding' P1 j! }: u! l) c" R5 w" m
0 {+ T8 g* P9 n; S8 m4 P
        // VRC6
; e* Y: Q5 C3 ~% z% s/ [+ r        if( exsound_select & 0x01 ) {
# g8 `0 ~0 ~: X2 h                vrc6.LoadState( p );
- q: C! ?. L  G7 v0 N                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. z* ]! O# q0 E5 w/ q# t. p
        }: [: d" F# I. T7 j1 A: N
        // VRC7 (not support)
/ g! R8 O; V6 t4 a1 U        if( exsound_select & 0x02 ) {  k6 y/ L* U0 K$ G1 L7 l( d/ k- z
                vrc7.LoadState( p );3 H+ K9 H# m( h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" b8 a6 r4 G+ x, z) n- l/ e1 J$ p9 @
        }
3 {+ A5 U% A+ k3 U8 O( @  [) A        // FDS
2 F! ^2 u, a% p2 I9 I- k        if( exsound_select & 0x04 ) {
2 x2 h7 Q' P9 ~- i" i) [: b; B                fds.LoadState( p );
& y' X0 D- d5 S. F( W' x( m/ t7 B                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 ~3 u0 j0 N8 G2 ~        }, v. i0 p" s/ I3 Q9 @9 m. W
        // MMC5) I+ p  i+ x6 W8 R4 w
        if( exsound_select & 0x08 ) {
+ K3 L1 O5 U" [* u( |' A                mmc5.LoadState( p );0 T3 [. E# M  o) s) q% B
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 Z9 M! d4 u% ~& \4 c        }
+ w* d/ v1 @. V/ @8 m& c) |        // N106* G3 F/ t5 H; }1 m+ A# B
        if( exsound_select & 0x10 ) {
/ L( g. g7 F, B; }$ ]4 ~5 T2 i4 ]                n106.LoadState( p );
3 a' F- b, d% {/ B: I% m) w                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, `- W) s: l0 K$ W+ L
        }
3 C$ s  z, ?! Q+ Z        // FME77 l+ W$ Q: B, h. w1 |' j( B
        if( exsound_select & 0x20 ) {% e- K3 d; _& \3 C% p3 [
                fme7.LoadState( p );. M2 M5 B$ ]1 E3 s  y) P! o2 d
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 Z3 W; A) |; ]6 T0 x% n( U        }  `+ D, m, \* N: I) ^; w
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( D  C4 N( P" c& b  [( e6 j: F0 s可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. D% s0 C1 Q& ^感激不尽~~

  a: p7 w7 T/ u0 Q恩 我對模擬器不是很有研究,: C4 v4 A- V3 \9 ^: y' o
雖然要了解源碼內容,可能不是很困難,1 z5 M1 i4 A5 B& ^9 i3 O5 q  O9 j
不過還是要花時間,個人目前蠻忙碌的。6 H6 N: x3 P2 ^( i1 V8 |1 E+ Z

7 q( I" Q7 |( P" D4 w) R2 y( M給你一個朋友的MSN,你可以跟他討論看看,6 r, [% J' x# w
他本身是程式設計師,也對FC模擬器很有興趣。
0 {% I* S/ {6 ]" l
' J" p7 J% E4 F1 f( T* uMSN我就PM到你的信箱了。
9 b, v1 A# M- L: ?& o8 m  q$ W7 L  Y4 l5 n( ?, c9 r
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
: K& a1 m2 b4 x% m4 d) y3 m呵…… 谢过团长大人~~
6 p& ]6 |" S: U+ ]/ w8 ~0 s
7 ?3 m' L' V/ D! B1 V; _
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 ?% ?, R* [9 j: a& o7 B! Z4 B团长的朋友都是神,那团长就是神的boss。

! n) {$ f4 ~# k. O' b" W' |& u哈 不敢當,我只是個平凡人,' t1 \0 ~; B! Y# W9 g
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
6 X9 l0 Q/ B9 l8 GZYH2 V8 n2 N4 Y( _$ f1 e/ F, G
QQ:414734306+ O# `- x( W& F5 v9 p# N/ h
Mail:zyh-01@126.com
7 T4 u: c' f: F# q5 L# ?& Q+ o* \" ^+ }+ x  q3 i% S9 ]+ @
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 1 ^5 G4 v/ g- i' @( ?+ A; i
再次对团长大人和悠悠哥的无私帮助表示感谢~~
' E% E7 q6 D( ~  w7 H, E
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-28 19:13 , Processed in 1.120118 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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