EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 w# F. s! J7 G6 _: H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& [! h! ?* U* m这里有相应的模拟器源码,就当送给大侠了~~
5 R: M$ R8 p* |# a8 C$ ohttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 l4 k8 [" p2 H% c* t, m' Q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' N" |; W: |! n7 _
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# _1 R! q0 |6 w# a. }1 b8 `
这里有相应的模拟器源码,就当送给大侠 ...
  E% V  W% G1 H! L) u4 ]. }: P
聲音部分(Audoi Process Unit = APU):
; l1 i9 c6 d. k  ?.\NES\APU.cpp: \0 t1 }3 u$ \
.\NES\APU.h
0 y2 M8 d( R) {1 w1 I4 t
$ \% ^& _+ V& I0 e' `* Q) J4 Y" z* Z
影像處理部份(Picture Processing Unit = PPU):
2 o4 c+ X" k7 {! M4 T.\NES\PPU.cpp
7 C, m4 w, l3 x( ^.\NES\PPU.h/ W# e: p* g' n7 v: e0 ?( Q

- r# B, F9 d5 \- p  l, D% J如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:8 d) n4 y, X/ }7 c" u$ `+ o; y- W
(由于很多专用术语和算法机理都不明白,所以看不大懂……)- x7 n, r% w. ~( X- [7 D+ z$ {
//////////////////////////////////////////////////////////////////////////
. V1 y0 d5 R, B: n& n//                                                                      //
- e4 Y) C# b/ N" [+ p2 H//      NES APU core                                                    //2 b# v* h0 D! k# p% |' U' c3 e
//                                                           Norix      //
) C) i$ C/ `7 \$ T* B$ ?% A//                                               written     2002/06/27 //5 ]* P' N4 X' P% x3 k
//                                               last modify ----/--/-- //8 Y' [5 g( O2 R8 D  {$ F9 J4 g
//////////////////////////////////////////////////////////////////////////0 G8 `2 b1 e0 k0 f
#include "DebugOut.h"* R" d4 b1 V1 g& ^3 T
#include "App.h": |! h- c3 s3 i. B; |; K# v- ^
#include "Config.h"2 P0 w+ |) Q/ K6 s  i" b. d
8 o: Z7 }1 X$ W2 ~4 _
#include "nes.h"
2 v8 e1 z3 N- c, c  m5 Q#include "mmu.h"
7 K- q) t2 Y( ~( q' Y; C#include "cpu.h"
2 h7 l. z; h% V#include "ppu.h"5 j4 E# ~8 `% T' @' P
#include "rom.h"- C, `: }  V0 f. u: [6 O
#include "apu.h"* X0 a. o: W% s
6 b+ X0 |- y7 C  r$ ^8 ~# I
// Volume adjust4 V5 z+ K2 P$ H  Z0 S; r
// Internal sounds
2 [: n; c3 L5 t#define        RECTANGLE_VOL        (0x0F0)! v" j: F$ w! z$ h- `
#define        TRIANGLE_VOL        (0x130)8 @6 H' o$ e4 S" _
#define        NOISE_VOL        (0x0C0)1 ?8 b6 h5 L9 |* E4 V' L
#define        DPCM_VOL        (0x0F0)
: r) h6 b" d6 C0 R' h2 a, O// Extra sounds/ J0 A2 s6 U4 B3 C5 G4 z, i' ~
#define        VRC6_VOL        (0x0F0)
2 d& U7 v( Z8 U2 P5 _5 n#define        VRC7_VOL        (0x130)
" F2 T/ c0 X3 D6 M3 i6 L* z5 B/ f#define        FDS_VOL                (0x0F0)
5 ^3 Y. C# f& r# Q2 o% I; Q% [#define        MMC5_VOL        (0x0F0)
$ J; R4 J: ]  i3 z& O#define        N106_VOL        (0x088)* N# y$ L: o- X7 Z
#define        FME7_VOL        (0x130)
1 }5 _2 H$ X1 Z  C# _3 p; p6 x8 G% ^* }6 V
APU::APU( NES* parent )6 L5 R; ^1 p  |' x) K+ o/ j
{
6 y1 ]' p; W6 h8 }) e        exsound_select = 0;; b, \9 R! e5 o4 |+ y

; A/ Z  b* f6 `2 J6 G        nes = parent;
" f1 j( U+ A" C9 N6 C, Y        internal.SetParent( parent );
8 Y* V+ [. {( ^. [
' Z& M# v. z% R9 q; b+ }. ?        last_data = last_diff = 0;
7 F1 ^9 a8 V! A
; [# w& p! I1 o& X9 q4 a        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
2 g+ G+ z/ _; P! _) l0 D( w; |1 y7 V' c$ N5 P% R  s
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: ~+ k2 d) J' }        ZEROMEMORY( &queue, sizeof(queue) );# w0 G* u/ V- W7 Q! J0 }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ W: g8 `( G: W5 q5 O7 [1 k
: p& T4 j4 L- j1 V1 Q
        for( INT i = 0; i < 16; i++ ) {5 ?' `0 q3 I% _) r+ u3 }  I  |
                m_bMute = TRUE;
& {8 k4 F7 v* \5 z* E# V8 T        }( `0 ]$ r/ w- [& o1 C4 l- W
}8 [2 d& [/ E& [
; B/ z5 @+ m( o  G0 X5 l
APU::~APU()
8 y8 g6 {+ _/ r/ O2 h{, T& e/ ]# G4 H& M5 q* F1 P  p
}
% l9 j! [8 ~) ]7 |9 u+ ?: A  ?' b- e) A' t
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )  A; L( K% p/ O- X* [, {
{
6 S, Z4 d, |) O1 R1 j7 t* i1 m' |        queue.data[queue.wrptr].time = writetime;
7 c6 s1 ^( R" k1 s/ m0 \9 K        queue.data[queue.wrptr].addr = addr;% K' q4 R. a! F) H
        queue.data[queue.wrptr].data = data;8 ]) f+ _6 V8 B5 ~
        queue.wrptr++;
) G( G9 M9 `, ]2 N        queue.wrptr&=QUEUE_LENGTH-1;
* l4 `- [9 I! ~. _+ D8 ?9 u$ [        if( queue.wrptr == queue.rdptr ) {
' D; T! N* C0 h* v* m                DEBUGOUT( "queue overflow.\n" );' a/ [+ g" S, h# }9 g' D) m" e' `; X4 G, q
        }
" ~1 J8 y, }, V9 z% r1 k/ ~) r}
# M* t$ r% }$ V# A0 f9 T: b
! E. A0 \. m" P; r' j; EBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )0 `! d. A4 V9 [- G# M
{) l$ d8 ]6 I  [4 N& t
        if( queue.wrptr == queue.rdptr ) {9 z$ o: o. Y  c$ ]0 Z/ z2 H# r4 g. i
                return        FALSE;
; O1 E& P& N$ d' e7 a& {1 K% J1 y        }, y4 @+ `; [/ b& }* B
        if( queue.data[queue.rdptr].time <= writetime ) {3 |* R- c( D8 @
                ret = queue.data[queue.rdptr];
- V6 e# K' g& D: U7 M3 V  G4 \+ \                queue.rdptr++;0 U3 X% n2 ?) I7 X5 H; i/ d  H6 b
                queue.rdptr&=QUEUE_LENGTH-1;! u2 G# X* L' T5 ?( E" t0 U
                return        TRUE;
$ A0 k) W9 z9 `& M        }7 R5 p3 Y4 u; w1 J% D' E* M0 C
        return        FALSE;
2 G6 r: H9 r" @}
, L4 n4 \: r' x9 }( b
, w0 E; h3 j' Y8 _+ ~& ]* u; Vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )$ A; q  F6 P4 j" J
{
% G8 G. ~' \: ]0 N3 t, a7 ?        exqueue.data[exqueue.wrptr].time = writetime;3 `: n% a7 e- Z  \7 T, B
        exqueue.data[exqueue.wrptr].addr = addr;
7 R6 L3 z! e' M+ f! d% u1 S, }6 J  D        exqueue.data[exqueue.wrptr].data = data;
, j7 r8 }* Y8 ^" P        exqueue.wrptr++;
7 ^- I' ?* E6 i4 j/ M        exqueue.wrptr&=QUEUE_LENGTH-1;6 `- M6 C6 [5 k  g# @% z7 T
        if( exqueue.wrptr == exqueue.rdptr ) {
% {' P7 X, E# @9 c" Z                DEBUGOUT( "exqueue overflow.\n" );
- d& S: u) g/ _* }        }
$ @5 Z9 C( m2 n8 h$ t' y0 }}
; b# i8 c6 D/ s( B$ c
& E6 h3 b) Z, B% G. ZBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
# w3 Y' t0 h8 a( ]{. ^# H  ?4 T% L1 Y
        if( exqueue.wrptr == exqueue.rdptr ) {
4 \# _' E* B, o# q6 v                return        FALSE;+ m. H  p  {1 G0 ~* y" V
        }0 u; J1 e, B4 @  X0 L, u
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( \' A3 U5 A4 ~6 ], Q! r                ret = exqueue.data[exqueue.rdptr];
4 ~- q& ~4 _2 f# x: ?                exqueue.rdptr++;
8 r8 i8 W( {& B# @$ w8 o+ d7 J                exqueue.rdptr&=QUEUE_LENGTH-1;
5 C- l. d6 B& ^: V. J8 w                return        TRUE;  O; z* x4 K! R8 b7 n
        }
% L0 ^; n. `1 J+ N6 T        return        FALSE;
3 L; e) i# x7 Q}3 R9 X6 `0 ^# |

9 E% @; A9 g6 R) D0 M+ L" ?9 b4 mvoid        APU::QueueClear()
: U1 z" z; u) P5 @{
- e2 `( v9 a) _& a3 K& x6 Z! h. H        ZEROMEMORY( &queue, sizeof(queue) );# b# Q+ N+ c0 W4 h6 Q* f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 X& t  d9 p6 V
}
4 L* m: `$ s) c$ ~; K$ ]5 p' m( h" U
void        APU::QueueFlush()# q$ `- }, k& ^8 X& D! S/ `6 q
{- Q' \" C% s' G; O' f2 I# w  t
        while( queue.wrptr != queue.rdptr ) {
4 y- I0 O2 a0 N% \# N9 `                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );8 C6 V/ E! {3 E1 x  i7 M1 F1 o; B
                queue.rdptr++;
% s8 I7 R# x- ]9 H; z) B                queue.rdptr&=QUEUE_LENGTH-1;3 d  |) B4 R2 a4 _
        }
/ s% ~* |+ f) V, Z  [
% Z4 }" O/ v) U: H# R* e, q        while( exqueue.wrptr != exqueue.rdptr ) {
/ t  v7 e# i% p: y; _- o9 m- J                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
. I- V% |) Z* s+ }4 H4 G                exqueue.rdptr++;
: T' k# c  ]; b) J9 N7 @* V                exqueue.rdptr&=QUEUE_LENGTH-1;
% h. B/ f4 j" H  f0 U; |0 R        }; A9 G% g. o0 z
}
5 }) e' I) `5 E6 w6 k
, R# ?9 D/ ]/ Bvoid        APU::SoundSetup(): F2 `( J& C" d. {# d* |  U
{9 N4 k& A, T  @* s9 x9 w# [
        FLOAT        fClock = nes->nescfg->CpuClock;, r  B7 S2 W( Q- R
        INT        nRate = (INT)Config.sound.nRate;: g* K8 \7 J" ]1 T# @5 W
        internal.Setup( fClock, nRate );( I: H! _) a  F; k' `' L
        vrc6.Setup( fClock, nRate );. o& `/ ~( y) I8 o' A+ Z$ A3 Q
        vrc7.Setup( fClock, nRate );
6 J$ n4 P! d  I8 k( R  C' V4 U4 {        mmc5.Setup( fClock, nRate );9 w0 h& u# g  Y6 i
        fds.Setup ( fClock, nRate );4 ]: N  G2 g9 U/ H
        n106.Setup( fClock, nRate );
: w8 c5 _+ ^$ Y# S1 w- u: ^% a5 K        fme7.Setup( fClock, nRate );5 @/ a% Q$ I2 b- M) n5 c
}! G! f# g+ c( l! w  Y$ K4 p6 C6 m
, w0 E/ M5 Z9 q/ x9 i0 D# X
void        APU::Reset()
+ l. Y0 w  @4 Y& W/ |{$ A2 g4 {% I0 K1 }! r! u$ I
        ZEROMEMORY( &queue, sizeof(queue) );/ E; d$ D- r* V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 c! S0 v3 c, _5 j$ L
2 r6 z/ ]1 `  W/ y# E$ ?$ U
        elapsed_time = 0;
8 \* r9 `$ m2 j; C) q4 H' p3 u8 n0 f/ v* P& i  g4 m" t
        FLOAT        fClock = nes->nescfg->CpuClock;
/ D+ ?: }/ ?6 f1 b% @* E% z2 [        INT        nRate = (INT)Config.sound.nRate;' n/ q1 J* Y+ ?4 x# H9 Z
        internal.Reset( fClock, nRate );
; b7 M; U( W- w+ h/ v- b8 L        vrc6.Reset( fClock, nRate );
/ p* ]2 c! ^. {7 C- T        vrc7.Reset( fClock, nRate );) L9 S  Z2 c( J& O
        mmc5.Reset( fClock, nRate );
9 Q9 I! H9 L6 Z; p8 I& @$ }5 i        fds.Reset ( fClock, nRate );0 O( v1 {' H8 z# L# M
        n106.Reset( fClock, nRate );
, a& O* |' [5 p6 N" d7 A        fme7.Reset( fClock, nRate );
( v* B/ ]; v- j/ O6 s
* L9 F, g! V) e" B, ~4 @        SoundSetup();
: w1 A, y; E  m) B; y4 Y}/ @7 r# L9 B) }  F% K
: J: G$ x# ~* B' ^2 [( X' R
void        APU::SelectExSound( BYTE data )8 C8 T  H0 G; N6 k0 E- q
{
7 k7 V5 @  z/ N        exsound_select = data;
3 O: z' ]$ @" b9 Y# ^: ^}
: ~9 O8 C' F9 s+ m1 r
2 e0 A" O. @6 }! s# ~% c5 N1 _! aBYTE        APU::Read( WORD addr )8 w; L- l- y2 I) _
{
( V* {8 k, ]  e: l3 |        return        internal.SyncRead( addr );! b6 Q! K) a. P0 }6 d/ u8 y
}
: u. N5 `" {- R. h! D/ X. u/ g
, y; N& y8 {" }# Y9 \void        APU::Write( WORD addr, BYTE data )0 M* [$ B( p, V
{) @% p2 h& c3 h' j) k; b
        // $4018偼VirtuaNES屌桳億乕僩
, t6 u  i3 L* K. t- Y        if( addr >= 0x4000 && addr <= 0x401F ) {" V/ a0 b% O, e! Q
                internal.SyncWrite( addr, data );
; H+ h8 n, E0 C$ B! s                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
% |$ p7 @0 r7 _8 ~2 y& H        }. i% ]: L' l+ }, r7 h  B
}
3 d/ y( @0 h1 ]/ `& ~
# Z+ X) Q) X  }- ~  OBYTE        APU::ExRead( WORD addr )
( i8 v# ~3 }6 v! ?{' z9 y6 w0 b7 t6 e
BYTE        data = 0;
$ L- z. r- x+ \- D2 `( T! z$ q) t" B. t9 S& q" S; G  `9 c
        if( exsound_select & 0x10 ) {
4 t! h9 x4 ^/ j, {                if( addr == 0x4800 ) {
& D/ |% S$ v  o" l( h" P: R) W                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) [- ]- X2 z: |( z/ l                }) m  l" g  o+ I( r$ [( B
        }' E$ O" A- a$ `% m; u
        if( exsound_select & 0x04 ) {
* Y' |$ S5 Q5 P$ N% P4 ~                if( addr >= 0x4040 && addr < 0x4100 ) {
+ }3 c" {& _7 j# ?+ N                        data = fds.SyncRead( addr );: A3 j4 a  |1 l6 r% f" ?. m# v: V' y
                }) S% @5 d# y+ K0 {3 U3 d
        }
- N% H5 P% r% N" b        if( exsound_select & 0x08 ) {
9 c" B5 F/ T0 `- Y! Y6 J$ k( a                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 W2 a2 ^5 @  X  A* r                        data = mmc5.SyncRead( addr );
; h* X% M; e+ o* P$ {+ |5 Q2 @/ w4 W3 Y                }
9 P" b; K/ C, X; v) G5 y        }5 \% L4 d8 U$ N/ k9 l
) Y$ @2 k: F+ h( V* N% Z; h
        return        data;
/ S* k9 {6 V, _' Q}
- t6 C" `) s, D
6 H) |2 x- H$ A8 y& ]& N& }. pvoid        APU::ExWrite( WORD addr, BYTE data )
1 ~* k0 r* q. R! D{, k: Y; g5 F" L; D: c
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );: E1 V% K; _7 ]; u/ e) T6 j
; j$ T, s& |$ Z% n/ j
        if( exsound_select & 0x04 ) {
/ Q6 d7 P* S. Y* t4 q5 ~                if( addr >= 0x4040 && addr < 0x4100 ) {
# Q9 U/ F0 i" N* v$ ^. Q                        fds.SyncWrite( addr, data );
4 u6 E! \0 }7 O. P: ^! G" N                }% r1 J1 W$ K1 t1 z, N
        }
0 }8 y# C0 N0 i" g$ R1 D6 T/ Y% Y6 _* M8 ]0 U3 m5 _/ S7 b+ Y: i& x
        if( exsound_select & 0x08 ) {4 L2 I7 J2 a" W
                if( addr >= 0x5000 && addr <= 0x5015 ) {# u! D0 K6 w  D; {. O. K
                        mmc5.SyncWrite( addr, data );
5 [/ k1 [8 T1 P                }
- Y1 j& ?6 t& N; C        }" b) d/ o# a9 ?! T  L9 p- d
}
- G8 w! l+ [1 O' X! o) G' }1 h+ P; j/ f6 d3 [) q0 Q$ h- N
void        APU::Sync()
6 a, Q! b) B3 Y9 I, h{- |( @% f6 m; H- z# a  |  m
}
8 j/ a+ v# b, |2 I# G! A/ t, b! f$ n* x: o4 a. a4 {# W
void        APU::SyncDPCM( INT cycles )
( d0 E4 w! j0 V! o. A- N' Q{2 p2 b% Z5 F3 E# X
        internal.Sync( cycles );# A# @+ v7 q- b' s: {9 H$ x
- Z/ s2 E! O: J) _/ E
        if( exsound_select & 0x04 ) {
* A( I4 u/ q3 l                fds.Sync( cycles );
! M1 j! x: i7 i( Y3 o, \6 D        }0 T- {* Z& q, P9 ?$ Q
        if( exsound_select & 0x08 ) {: @  f# A0 |" e* ]7 W
                mmc5.Sync( cycles );
# U' E4 S6 Q9 H7 d% p" h& R( q        }
) A# [' Q: L3 S5 Y' \}
; [* C- q2 J# K5 Q0 g- ?- s( z$ q7 o9 Y" L5 A! S
void        APU::WriteProcess( WORD addr, BYTE data )7 L4 `" @, u! b
{7 @/ l( h& W' Q, f
        // $4018偼VirtuaNES屌桳億乕僩
/ M( V( T; j/ T/ x        if( addr >= 0x4000 && addr <= 0x401F ) {
& }+ X$ M, n. Y' e4 w                internal.Write( addr, data );9 T6 b2 D0 Q' z5 @. w/ z! _- V
        }
3 T$ s" b7 J2 R' V4 K}9 }+ Q- C$ v  I' }7 T5 R

4 }  Q8 y+ e/ _+ U# `: l% H5 W4 Uvoid        APU::WriteExProcess( WORD addr, BYTE data )
3 K4 z- U; ]) H& X0 c  J5 Q{1 Y; p! J1 Z4 R3 h2 N" X- b( p+ C
        if( exsound_select & 0x01 ) {% C& g, [$ J$ a) G; t4 [$ O
                vrc6.Write( addr, data );
7 j, C* F% F' `; T        }
4 v  k$ D' t5 H* p; R  T# f% s        if( exsound_select & 0x02 ) {
' s! m2 I$ N8 s8 J5 Q2 U3 X                vrc7.Write( addr, data );
' y7 P1 v1 h- E1 l6 v7 n& Z) p        }! H# Q; \6 E* u" W4 [$ U
        if( exsound_select & 0x04 ) {) A0 D6 J) M3 h
                fds.Write( addr, data );
+ P4 `" {# O8 C& |        }) R& K! m9 c' X2 B2 T8 K
        if( exsound_select & 0x08 ) {: B9 V( l9 I/ m; S
                mmc5.Write( addr, data );
7 ?. x' W9 ]3 o        }
+ Y4 U( H- w4 Q% i        if( exsound_select & 0x10 ) {" R# ^- q2 V5 S
                if( addr == 0x0000 ) {- N: x% N$ {  u
                        BYTE        dummy = n106.Read( addr );
9 I( a& r, @% t/ Q9 r                } else {
2 T# |  V5 ?* W* l                        n106.Write( addr, data );# t" ?# t! e" C3 e3 G: U
                }
% E4 X! \- k9 s3 b! |& D$ c        }
2 F6 K0 R* A' T0 m1 |! g/ s8 s        if( exsound_select & 0x20 ) {
3 y% D. [" L/ w% r                fme7.Write( addr, data );5 t+ |# Q4 A* `6 m' e
        }
. o& b! \" U9 H( l}
* H! o7 C7 ]4 {
) {* I! f5 Z# f: {& b( ~void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
# ^& I( k" R" N; M5 a{
% P0 `  `+ d( E! kINT        nBits = Config.sound.nBits;
+ S  S" `0 e; T# d8 g2 X; R/ uDWORD        dwLength = dwSize / (nBits/8);
! Q. z& q6 P' {# qINT        output;
5 r# |" `9 m( h+ N9 gQUEUEDATA q;/ ~: h6 N) [* C4 E& }
DWORD        writetime;. x4 ?+ i5 R* m) h
/ G( ?- U6 q8 I- i& b7 Q
LPSHORT        pSoundBuf = m_SoundBuffer;7 u3 a3 J$ l# w# o  ~
INT        nCcount = 0;
6 y: ?( y% t6 X' l" ^  X
, s" @+ X* `9 h4 K5 f4 l/ J7 tINT        nFilterType = Config.sound.nFilterType;# w" O  q8 I) ^! q* g8 e

7 K/ P8 [- R9 r$ s$ f        if( !Config.sound.bEnable ) {( ^$ S( w" A0 `1 D% Y- \$ ^
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 l/ C' Z/ {( {" N. l$ y1 i. u3 O; J
                return;
' `2 ^! M& f- [* @8 g+ G5 i        }  u% Q4 M- K9 v. |2 t. d

& R5 q9 g1 P+ g3 h        // Volume setup6 i; d7 H) e- r! l( s
        //  0:Master
+ t2 y  ~3 v" R8 M" ^5 s1 ?        //  1:Rectangle 15 l/ b* D" q- E. y" v
        //  2:Rectangle 2/ v9 t+ F7 J& V0 z5 E
        //  3:Triangle
# V2 f4 v8 k$ F) F# N. l2 ]        //  4:Noise
% U7 ^% L% F" j! g7 e! ^7 I        //  5:DPCM( v6 S+ [. M" d& G3 j( {
        //  6:VRC6
  Q# [" V( g; ^        //  7:VRC70 f1 d7 R# d+ t8 h
        //  8:FDS* ?& l6 j9 ]( @3 q* Z, ~! R, Q
        //  9:MMC54 \- e5 A2 [+ ^- M' M1 x) B
        // 10:N106
  h9 ^  v$ S+ m: W9 k+ B6 y        // 11:FME7
1 ?+ y. J7 ~* e" b        INT        vol[24];
# w( ?" u% G) P: L        BOOL*        bMute = m_bMute;
$ K! Z9 A( a7 k$ Y/ T        SHORT*        nVolume = Config.sound.nVolume;) q5 ?4 f0 X% O. I) }: |: O
3 P% q# h4 k4 E  ]4 X: W
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
) E! M5 T# c% f5 l
' d% }( ~! Y4 E2 Y: t        // Internal
. a- k' E# h8 U4 S/ L$ A6 q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 `' _. h# h% t6 X7 h
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 V- t; c% T+ d  Q        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
% `' L5 N! a+ k6 q        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
* }4 s5 j* N5 r        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
( I8 h6 Y+ j; n1 V/ ]1 g1 `
% _5 G$ F" H0 }/ P, @        // VRC67 N# n+ D/ ]" ]( w
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: g! l' C( _& I- X* |
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ B* w6 I; H% H* a* I/ X9 ^1 e2 h
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 u/ P7 S/ {* F( f
0 d. L: }! K2 k$ W1 H" ]        // VRC76 q; c- l# P' l6 ~  l
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
+ j1 t) s" h& T( q7 z/ }1 h* m
! B  H- T/ d) i/ A/ ?& M        // FDS
: q, q7 Z2 L7 A- ^        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
/ W0 J: G9 P/ y4 }% \1 @3 P
  e+ R2 R( f% K4 j" O        // MMC59 j/ b7 ]7 A  |4 E
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; O! z2 v: h( u# U' G
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- [, F  c5 e5 k
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) l+ ~1 @( C  J) x5 r4 ?8 U/ d
% H1 O: p) u8 ?( j        // N106
  A1 B' e, A! M( w$ p4 t. {/ O2 x        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 p3 b) t6 Y$ }' y
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. e3 R$ A6 O6 \/ u
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! b, z; [- R5 ~/ h$ E9 D  H& C/ ?
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 e9 M, F: V* e; d, k        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' i4 M; [- w' W( P        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 W5 Y  v# p/ X( T9 X+ M
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! L; M# `. h& n8 i! q7 O* U$ ?
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. I5 l0 y6 n+ O4 `! d' E5 q7 H# ?; ?( [7 S% V& c- L# H' s, r  ]& I4 E
        // FME7" \7 z1 I: q, z7 _, a+ b$ G5 o
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 |% X. H" a8 A/ t( g% M1 A        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  m# m: I5 [! x2 w
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 x. L) g5 J5 r0 V' H/ p) a  m
5 F( ~" s' d5 R  _% B& J
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
  P% o# [* i' C( B8 L' l: t, I        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
- j# n* \6 Z; a5 z: E8 i: U1 ?
9 }% H: ^5 _) L! X3 s* V        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟' ~  G3 ~9 a' h* [
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: C1 s- B! Q# u8 Z                QueueFlush();- }+ L' ]  t9 E
        }$ R3 ]' K' w1 |4 e# [& ~0 B1 x6 Z9 B
8 M2 R! x0 B) k& u' R
        while( dwLength-- ) {" @, O) u9 `! V: }5 R; Q
                writetime = (DWORD)elapsed_time;
% ^% x- o2 _  c0 |8 m+ t6 j2 m2 n, ?3 P3 v1 d, A6 h6 o1 V6 M
                while( GetQueue( writetime, q ) ) {6 Q: X# w+ d- F
                        WriteProcess( q.addr, q.data );
6 G+ e! y* b1 g                }$ a2 ^# R: }3 S6 h8 V

. K: |8 h& }) B- w/ Q% c                while( GetExQueue( writetime, q ) ) {" ^5 ^. T: o% e9 S/ J9 N
                        WriteExProcess( q.addr, q.data );7 A1 P8 R5 d+ e4 N9 f" y$ b: Y
                }
) H' L3 @, @; d9 r* _/ J
: n9 n3 Q) o3 X( g3 P6 s8 S                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
; y/ w1 c- J1 \4 a0 d                output = 0;3 Y+ V/ w0 a$ X; i( C6 R! U
                output += internal.Process( 0 )*vol[0];
! s, ^; i" M3 D. {. O                output += internal.Process( 1 )*vol[1];
0 H" H5 n1 }4 |( i6 Q                output += internal.Process( 2 )*vol[2];7 Y2 m9 H# l+ H3 E7 E+ I
                output += internal.Process( 3 )*vol[3];1 f! r$ L  d) C! f1 S
                output += internal.Process( 4 )*vol[4];
) ~0 E4 Q/ x" B% _2 L% ^- F& P) d# C+ l
                if( exsound_select & 0x01 ) {4 G  Y! t7 U7 c
                        output += vrc6.Process( 0 )*vol[5];* J, h/ n8 Y( F, A3 [
                        output += vrc6.Process( 1 )*vol[6];
1 `4 i/ o: A2 j" C! ?+ I" ?                        output += vrc6.Process( 2 )*vol[7];
9 L+ _+ G9 b3 x# _+ }+ ]  Z                }7 y. c; O! x0 r" e' d- a9 I6 ^
                if( exsound_select & 0x02 ) {
- D  n8 b5 X6 |                        output += vrc7.Process( 0 )*vol[8];
; B! [1 |' n* x8 {$ b/ J                }9 m- y& r) C5 x, @
                if( exsound_select & 0x04 ) {- ]0 [  M) x" D' n  y
                        output += fds.Process( 0 )*vol[9];  C' e- \# K4 t9 A
                }
8 p: e! p" [7 G( c& ?% ^3 o9 A3 ]# Q' [+ E                if( exsound_select & 0x08 ) {: @8 u9 h& }* P! H4 i$ j, F" ]
                        output += mmc5.Process( 0 )*vol[10];
+ n& H5 o) P: H. j$ @: j' g' v                        output += mmc5.Process( 1 )*vol[11];
, @1 M: [# h7 T" |6 H                        output += mmc5.Process( 2 )*vol[12];
0 Z3 d) j/ o* [                }4 J; [1 r% B% U) j
                if( exsound_select & 0x10 ) {) W+ `7 w1 X. r$ n, S2 n* }* G% o+ v
                        output += n106.Process( 0 )*vol[13];
+ a& @  r9 r- W& b- H4 O; u- v& }                        output += n106.Process( 1 )*vol[14];
. b4 N; D! w6 Q8 A& M% P                        output += n106.Process( 2 )*vol[15];$ ~% t% [& T& k# J) r' L5 l
                        output += n106.Process( 3 )*vol[16];5 R6 s: ]4 w- O+ v
                        output += n106.Process( 4 )*vol[17];' G$ h$ W- z( K
                        output += n106.Process( 5 )*vol[18];( t, u  V7 G3 }! d1 J  `( n: C, T& [
                        output += n106.Process( 6 )*vol[19];
& p. a  s/ i5 ~% E$ G$ U                        output += n106.Process( 7 )*vol[20];, y3 m8 F4 ^+ A1 `& {; ]6 W- U
                }( U1 l; G% E. Z; K& ]
                if( exsound_select & 0x20 ) {9 B" D0 `+ E! ?+ h. @# @
                        fme7.Process( 3 );        // Envelope & Noise
& k! v6 A/ H: a6 J" I3 e                        output += fme7.Process( 0 )*vol[21];
  B5 k& U+ l. ^                        output += fme7.Process( 1 )*vol[22];
) \, O2 Z) N9 ?, w9 I" n3 q+ T1 R                        output += fme7.Process( 2 )*vol[23];
0 H* _# Z) T$ m  G9 G( R                }
1 ~5 a) r3 H% K4 T" D  R! h2 @2 I. U6 B7 d4 |
                output >>= 8;, s. V: k% E9 J1 w8 e5 f
2 p, y; T, S- Q4 w
                if( nFilterType == 1 ) {0 |! }& a" @* x3 u5 M5 B1 V: G- _
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
9 C9 l+ J/ ^/ ?! C( R                        output = (lowpass_filter[0]+output)/2;6 W+ ?9 D6 D2 I3 a1 v
                        lowpass_filter[0] = output;
/ ?' R! M3 ]1 P/ `                } else if( nFilterType == 2 ) {
' o0 g# B: C0 V' r                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! f& u/ V) ~2 K* s                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;2 c) ]; a0 f* _% F. a0 O, S
                        lowpass_filter[1] = lowpass_filter[0];
; ]- C: _# I! C- ~% |* E                        lowpass_filter[0] = output;
! k5 m8 o% B1 r) ?: V- c9 D                } else if( nFilterType == 3 ) {8 b* C3 b7 L/ O5 v( C, e
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 s( M; |  h/ `. M
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;( i2 r5 Y& b2 v# i
                        lowpass_filter[2] = lowpass_filter[1];
4 M( a: `: o( h. B                        lowpass_filter[1] = lowpass_filter[0];% c5 l- e6 q  l) R* Z- r! V/ Z. y% d
                        lowpass_filter[0] = output;# l- U1 ]* j* k% P7 S# A* I, @  u
                } else if( nFilterType == 4 ) {6 s) s, e8 i1 [! v* I
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% x$ o2 u6 q' [. j
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
3 B6 i' A% w. O0 S8 J% f7 q9 Q                        lowpass_filter[1] = lowpass_filter[0];+ s/ w9 A' h, }0 J/ ?% m' r* L* Q
                        lowpass_filter[0] = output;5 O, `0 ]+ b0 O* ^5 t( g! ^
                }/ x! e+ b+ T! H7 |+ e! b, v9 `+ |+ u
3 t0 ~' |7 y2 k+ C4 h( R5 G2 N1 X$ u
#if        0
, v' C4 X# s$ l! p4 @7 J- G5 V                // DC惉暘偺僇僢僩1 c* {- p" M. d  w; Z# k
                {) I3 C- K8 ]# ?% A" r
                static double ave = 0.0, max=0.0, min=0.0;
6 B0 Q  c' M! X6 s" w( V# f                double delta;, ~% J  `  S% ], Q
                delta = (max-min)/32768.0;7 v: I" y; N* g5 M8 r9 F/ |
                max -= delta;
: x% k; x6 [. Z+ ?                min += delta;
- `% P3 U7 Z* i" S* @8 U3 [7 n1 \                if( output > max ) max = output;7 q* _/ G/ \* p/ ?
                if( output < min ) min = output;
0 z: H* ]9 X* y2 ]( T                ave -= ave/1024.0;
: T  K8 h1 R1 n' U; }' k% z                ave += (max+min)/2048.0;$ _5 S8 _+ }% {7 x5 V. A; r5 I
                output -= (INT)ave;+ s3 M" p9 f- E4 n2 N
                }
7 }5 c/ u2 s; a#endif. ?" |9 I: U4 P2 F8 X0 }$ P
#if        1: U! u# ]6 r, K, f! h
                // DC惉暘偺僇僢僩(HPF TEST), _: h! Z9 ~. e) B8 }
                {/ `' E1 g* F2 K/ j; |$ p/ {
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* o2 V' Y$ G' @, D
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
+ k8 T7 F& v! V# c                double        cutoff = cutofftemp/(double)Config.sound.nRate;1 Y  I- `+ M( ~
                static        double        tmp = 0.0;
3 y/ y  b6 Z7 @. Q7 k                double        in, out;
) U- m6 p" h  d; Q& \4 X# b: _, b; k
                in = (double)output;9 ~2 a8 y& H. U& ^+ J, q' b
                out = (in - tmp);
) v7 ~1 O$ y/ J0 Q4 {/ ~( S                tmp = tmp + cutoff * out;5 v9 @/ m1 n4 D5 A! X
" [* a; ]/ i& G% G7 A/ K
                output = (INT)out;
! N$ `3 Q: Z# d; ]) g& j3 I                }
; p' l9 s2 M6 Y! N  a#endif0 ^/ w! s. O/ b8 [4 j
#if        0
2 B  |& q7 G. |                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
; B7 U/ W% v# h: T+ |& I- c' V                {
5 R% ~. x% m1 U* P& }                INT        diff = abs(output-last_data);
( c& f+ F* x: O3 d3 H                if( diff > 0x4000 ) {
/ [- [1 L# K5 j                        output /= 4;+ E- N( T& q& L7 h) c
                } else $ R9 Z# v$ x% e4 A. d9 _4 s/ }% Q
                if( diff > 0x3000 ) {6 Q' O. W$ @  b6 ^' c1 @0 g
                        output /= 3;
4 l4 r! k" W- S0 ?                } else
2 M+ _; _9 P% d& z% W7 ]& @5 @( D7 s                if( diff > 0x2000 ) {$ z% x2 _' Y) q- ]! }0 [) x9 d4 d
                        output /= 2;! K  x' A2 c3 l, v
                }% n( X/ G1 \& O  e
                last_data = output;  o! Y& A6 L$ N5 P
                }* C2 Z9 {0 D& }: G5 u% {
#endif7 ]4 p1 k% o! ]
                // Limit8 u' B' u/ E, k* y) _+ {( P* G5 g
                if( output > 0x7FFF ) {+ x# E0 E2 u( U0 h) f9 ^
                        output = 0x7FFF;
* }8 l: x5 r- ~                } else if( output < -0x8000 ) {% e* o* T# o) b  J+ x7 ~
                        output = -0x8000;
: m- Q+ ~  i1 Z1 V                }; V3 r% j9 b( Y# o3 @, u& ?+ t# z

. T6 F3 L8 b/ s6 Z* U. w* k                if( nBits != 8 ) {
6 ~  s% d# \5 M5 M                        *(SHORT*)lpBuffer = (SHORT)output;3 c8 Q3 g  k" M1 ?4 n1 K" Y0 Z5 e
                        lpBuffer += sizeof(SHORT);
1 f! m) a, Y" r* `4 a5 E( y- e                } else {4 N$ |. K$ l9 u: I7 k% L
                        *lpBuffer++ = (output>>8)^0x80;2 x. D; O% ^4 _' `: ^" d1 i
                }9 m8 W9 ]& `  C* |( h% ~
' b0 C, c* m& v$ ?. D
                if( nCcount < 0x0100 )
, s' P. t( F# C9 V' E0 z  z. U                        pSoundBuf[nCcount++] = (SHORT)output;1 m$ c/ |! J4 l' ?' I' ^
# K/ e; F& y# A1 m' c- y; r( |! G; V
//                elapsedtime += cycle_rate;5 [$ ]% Z  Q% `# Z* p4 x
                elapsed_time += cycle_rate;/ w. O9 x/ J7 \# Q
        }
* A+ e; ?, z' I
: c8 K& I& b" I' ?0 F% S5 r3 R#if        1
8 q1 i4 {& v- c& L1 ~& D4 m: T        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 O+ M- d; E$ S1 Y1 A  W) i                elapsed_time = nes->cpu->GetTotalCycles();( D# k7 @- u- H4 Q  H! E
        }/ _  @$ f8 N- [7 v+ n/ o' Q$ H8 w
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 `) d' [1 S" r0 p( j
                elapsed_time = nes->cpu->GetTotalCycles();; C: Q- I5 b! ?* w0 A7 x
        }
' j, Y; _9 A" f9 E6 Y; m#else
# w7 ]. g5 ~& K% z        elapsed_time = nes->cpu->GetTotalCycles();
. ]6 n) Z" ]" U#endif
7 i  }# ^/ q% w6 R: M# _$ z}' G# W0 A4 p1 H
- i& B) i2 F# r/ I- P" Q' S
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- Z) K% G5 {/ R$ I/ R) g" s, d; G) VINT        APU::GetChannelFrequency( INT no )+ A2 g0 Q! S+ _2 q9 Q- z' \. |  C
{* [2 A% m1 \+ @
        if( !m_bMute[0] )- G+ M0 Z4 ^( b$ ^
                return        0;
% U( q+ z% y" a( v- {) d$ C, H
8 K* j/ j+ R1 w* Y6 k8 Y        // Internal0 P' E1 |6 B* K( M( G9 Z
        if( no < 5 ) {
/ Z: O, q: _$ K                return        m_bMute[no+1]?internal.GetFreq( no ):0;
& R2 J( J- F# F8 B  S        }
& h' G; e% X/ x0 z6 q" C4 z, `        // VRC6
) K6 Z) j$ \, h, X: T        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  B; g( K9 ]7 l+ q& f. R$ o                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! ]# M3 ]2 A4 G$ i% P
        }/ `- z3 I* P) i7 [/ J' }- P2 K
        // FDS( d$ i, A, M3 p9 F: q
        if( (exsound_select & 0x04) && no == 0x300 ) {
  a' m+ J& n# t: h5 V, X% h8 a9 G                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; D, C, K- _  H+ K        }
3 ^; A5 A! |1 f0 E1 Y8 ~9 N# R6 c        // MMC5
4 L( r" B/ }! }; t. \        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {7 h4 `& R) u9 a! O
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;6 T& w' S, h+ r; c# u
        }
2 a$ H1 T, N( v3 L, r) Q" r5 ~        // N106+ t. E4 m* X4 f' R/ [8 d+ u9 r9 U
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {& V4 W7 R8 w$ |! F; X4 t9 S
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 I9 D3 \; R- ^& ]* b* C* B0 L
        }) I( _$ o8 K" z
        // FME78 W* @% Y3 l! b; G
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {. T" O$ `# i6 }+ j. W6 i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;" H% d9 \; Z1 A; V& P0 Q8 i/ j3 I; m1 @. @
        }
: p& e) b& u6 I# L$ r2 _        // VRC7
+ {' k: q0 [; g# P' F        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
8 o8 c, S: L+ K7 ^" e. V                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;' z, f0 E6 [5 E/ @8 V/ ~  c
        }1 X) j1 Q2 q3 [6 n: P+ z7 j( g
        return        0;# u& V+ d4 C3 \& ^; I/ ^5 t
}$ G3 u2 A3 f% K- j

( D$ k8 w( s3 k5 z0 M+ g+ j// State Save/Load
; e1 i( U) u' _- Evoid        APU::SaveState( LPBYTE p )
; s2 P7 K3 Z; _1 X5 {+ R{( F. l& z2 \' w) z: W) o
#ifdef        _DEBUG) v3 T( V( X# Z- `
LPBYTE        pold = p;
- E# j" S( e3 c" V4 x' @#endif# }" [. m6 O7 [: `. z2 e  J& ?
1 X8 n& v3 ]! q$ W1 M- P( u2 _/ Y6 R
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
2 P9 G1 ?2 O' o) M# ^9 X2 j        QueueFlush();8 Q8 S9 \7 ?/ W& Z$ t
( W7 {# L( X; }5 w7 Y% @7 O
        internal.SaveState( p );  j0 o2 q; E- W& M# ]+ q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 y6 I" _" J2 ~8 U$ B. ]

4 M7 S' ^) O5 d8 l; y4 q& q7 W$ B        // VRC6
, r9 \  j( [' m  c& p& v        if( exsound_select & 0x01 ) {5 {# _5 }) f3 X! C8 F5 m
                vrc6.SaveState( p );/ U, j! s3 Z. h. I: i: p
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; i/ Y" ]- [- l9 m: J
        }
6 \" V# `% A3 ~: V/ `; Q        // VRC7 (not support)
* c1 U0 z3 F6 J4 ~  U/ ~/ M; _        if( exsound_select & 0x02 ) {  @! }6 Y0 z$ W
                vrc7.SaveState( p );+ [" N9 v: Q3 G; S* e0 V
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: G( q9 b' {: ]" s
        }
  I+ M! N' b! N0 j8 X        // FDS% H- u7 D/ e7 o! B% e& \5 O
        if( exsound_select & 0x04 ) {0 `( l. i2 [1 ]! q. Y
                fds.SaveState( p );( r4 w0 G( r& f2 T' f9 O: ]# g
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# {2 X% v/ d( t5 B( z        }" ~1 v, X' c4 u0 Y
        // MMC55 e+ W  Y3 ^. a: G5 i
        if( exsound_select & 0x08 ) {6 e  X5 u: i* r+ w$ }3 ^
                mmc5.SaveState( p );
  {1 E) d$ e0 @7 h* \5 i, L                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 i, K1 x  q% L6 E% e  I8 s
        }! R; R$ s" K( ^3 G
        // N1067 Y) e$ X- \/ i7 j; y
        if( exsound_select & 0x10 ) {7 t& F; r+ ^; m& T1 D" D
                n106.SaveState( p );* m; F+ z$ V6 E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 z  |! ~$ t- J; V1 i
        }
; S3 p/ l7 c. ?        // FME77 W' C0 T( b1 b1 u# U+ J  _
        if( exsound_select & 0x20 ) {
* X% x' m% s* C& P  E. s                fme7.SaveState( p );9 d; p$ L. o: y9 v" q' s0 u! I3 F
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 |. O/ T- @( C( t0 `! j7 S        }& H  R0 b/ n+ J3 \

! u, |) m/ v& e4 @, D#ifdef        _DEBUG
; U9 u3 |' @+ J9 Y( X7 i4 M' ^% _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 A4 u& M) e% `: Y#endif1 y3 x5 X* v: [/ N; b
}" `3 l9 @) K- C* T; y* J9 o

9 h# w5 [+ m) a6 y% @: q& {. uvoid        APU::LoadState( LPBYTE p )
; i5 a7 `- O* ]0 B. t{  ~$ v4 J6 l  ]+ Z" O8 h" ^% |9 ^; Q
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
, ]* o3 P/ \3 {        QueueClear();
' y1 W% w2 j$ P$ m$ n' j; w0 [- w+ j4 x, b& P
        internal.LoadState( p );
1 L# w6 F7 H( Q+ H) ^        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* F0 W1 a# f/ q8 U, _0 }. ?9 @
3 I8 {, H* o) _        // VRC6  j6 f7 v" k% s, u
        if( exsound_select & 0x01 ) {
/ \' T, a* [/ h5 m4 ^6 D/ g                vrc6.LoadState( p );
; m8 [) W) j3 V% }) v' n/ e& n- {                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ l! r/ U! X: R! U6 G' G; F
        }
6 l, j. O0 c4 P/ l        // VRC7 (not support)" l+ F3 \3 n9 Y, i; Q3 b
        if( exsound_select & 0x02 ) {
3 H; F- ^+ }+ t2 U) |4 |( o9 d6 V                vrc7.LoadState( p );5 T3 X/ @  t4 }  }" @
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
  C) E/ ?5 U+ O3 n& z7 ?# I5 ^        }! G5 ]# d) W* `9 G( K; G, f
        // FDS
3 @1 D' h& ~* {- T$ s: ^+ M, K        if( exsound_select & 0x04 ) {
' p4 B8 T! t* q                fds.LoadState( p );
! @) M9 N" G9 ]4 K! m5 c                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! z! I7 `5 q* R0 U$ }* j/ p
        }+ C: m# x9 T! G  `
        // MMC5
9 r7 L2 ^" E- k& `        if( exsound_select & 0x08 ) {6 G% P( \: w# Y9 q( |4 O$ x  E
                mmc5.LoadState( p );; G: N/ f; s* I; V# |7 P& }) A
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, t. K4 }8 C7 x" k
        }
  |9 j9 C9 P% \; E1 Q3 ~8 w        // N106
7 q: _" p, v. u* S" W+ |/ N3 \1 W        if( exsound_select & 0x10 ) {
/ l& v  r$ L# `9 [, L                n106.LoadState( p );
9 g5 N, I" e& B% Y2 p% r: c                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* ^. e) s  ?- r5 Q
        }
5 F; g8 j; J4 x& S$ _3 X1 Y2 Q        // FME75 Z$ e- n3 g1 r! |5 q( e
        if( exsound_select & 0x20 ) {! S3 o% p8 }: s  j* Y" q' o- U
                fme7.LoadState( p );! X9 t9 k/ }1 u' v/ d
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ p& g( G1 o( D        }. F* l, ]- f+ b6 k( E! F; {
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 \  A8 {& I: A" p1 h可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
$ P/ B& \  `1 b$ B+ h感激不尽~~
, k0 B6 k4 a" T: p: F2 i/ V
恩 我對模擬器不是很有研究,
" c8 }: z6 L: E! V雖然要了解源碼內容,可能不是很困難,
' ?: T5 y+ o  K不過還是要花時間,個人目前蠻忙碌的。
- a# |/ ^* u/ |. i* c0 H
0 j- H; z: [* ~! `給你一個朋友的MSN,你可以跟他討論看看,
+ v( _( k; }* O& p* j$ \0 T. I他本身是程式設計師,也對FC模擬器很有興趣。
) d; @4 v8 y: r6 v
7 g7 h% j$ O8 G) ~+ ?MSN我就PM到你的信箱了。
$ ?' R2 j: z6 m. J1 }1 I
* r8 g+ `" X' K# E希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' w. a( }) z5 Y
呵…… 谢过团长大人~~

* E8 g# n/ U& Y% h0 R8 u
5 n& ]% ?! W$ g4 \哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 [) H  ]8 f) b
团长的朋友都是神,那团长就是神的boss。

/ T+ ^! a6 ?$ D! L0 Y# |; Y3 E哈 不敢當,我只是個平凡人,
( G6 C; r( r1 r5 K. P- ~! i要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙% [. l0 E0 O5 ?0 X  ~
ZYH6 f" S# B( u, k
QQ:414734306; m  x: ]3 @# G& T6 |
Mail:zyh-01@126.com
4 U7 L4 q4 Z  T) J0 h+ O( G- T+ ~4 V( S9 I9 \
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 " h4 S( W, n, O- y1 }
再次对团长大人和悠悠哥的无私帮助表示感谢~~
! {5 A8 A  i! c5 F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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