EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 z$ [3 h7 ]1 w/ o0 c
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: f1 o! s+ [4 n8 u8 r
这里有相应的模拟器源码,就当送给大侠了~~# U( K$ k* \8 B3 Y" Q/ {
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
' S1 x/ d, l  {8 v能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 u* W# D# L- c2 z8 Y" I7 W% Q/ B9 E楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  r  E) L8 d. u) L9 ]这里有相应的模拟器源码,就当送给大侠 ...

7 L, Z  H( ~9 X4 x% S聲音部分(Audoi Process Unit = APU):: l4 _, d( l! o0 G) R; z- X
.\NES\APU.cpp
6 k2 l2 g6 C/ u; o.\NES\APU.h
% ?$ {$ p( i2 q- K% J9 |
. h! x' v# `! u: S$ a9 R( o- z
, x  X( L) l  B% D9 w影像處理部份(Picture Processing Unit = PPU):5 A& e1 @0 h  }8 L7 i2 q
.\NES\PPU.cpp6 q9 Z; J6 e+ x4 m) g7 B
.\NES\PPU.h
3 L( p, `/ W: h; e; H, X- f9 E" G( p# q5 i* y# p5 @
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* u, J4 J  B8 K3 U5 f(由于很多专用术语和算法机理都不明白,所以看不大懂……)
3 r% W: m  ?4 q) q6 {  L+ V//////////////////////////////////////////////////////////////////////////$ `* {2 ~: s9 R1 `
//                                                                      //- y) O6 e1 K' P
//      NES APU core                                                    //4 ]3 V7 y0 ]& p' c& w, D
//                                                           Norix      //
9 }3 x3 l7 H0 Q0 l) t6 ~+ _//                                               written     2002/06/27 //
$ m: `; {( u9 T+ E//                                               last modify ----/--/-- //
& N# V: r+ g+ _  ~//////////////////////////////////////////////////////////////////////////) T; W* O) P) `2 Y; E
#include "DebugOut.h"
( M1 p6 G. U8 M- L& s* }# ~* z#include "App.h"0 D0 o0 Q8 S# d4 c; ~; b. d7 Y
#include "Config.h"7 O& l( F8 U  B8 Z% b3 e+ p; T

8 T8 n+ c" T' q) _& l#include "nes.h"
8 r8 F7 X2 T6 P/ ?( K/ d% ^' R#include "mmu.h"$ K2 |" O/ Z7 @, c
#include "cpu.h"7 U: L, n) d: f$ o5 l$ h
#include "ppu.h"+ H, Q1 n, j3 o$ D0 M
#include "rom.h"6 `( T+ Z4 @3 ]- s
#include "apu.h"( w0 R- X, ^, b# r4 A

% d( B5 w$ ~3 |) \: }% e// Volume adjust
( f. ]$ i, K- |+ Y* I// Internal sounds
+ J6 Y: K: Q! T& ]8 l#define        RECTANGLE_VOL        (0x0F0)# q" g# t0 c" w/ J7 |# m: l1 i
#define        TRIANGLE_VOL        (0x130)
' v- S5 C% O% `! u& k# G. ^. j#define        NOISE_VOL        (0x0C0)0 i% m+ h& x' _9 j8 I
#define        DPCM_VOL        (0x0F0)" [3 n! g: a8 p' n1 \% y0 U1 X; @1 f
// Extra sounds- k2 [/ j4 I; @" c
#define        VRC6_VOL        (0x0F0)
' e9 Y0 X2 u6 d2 i#define        VRC7_VOL        (0x130)
1 e. N* B- S6 I9 L. x' a' H' T#define        FDS_VOL                (0x0F0)
0 V4 r. q/ N7 C& C+ y#define        MMC5_VOL        (0x0F0)
- ^1 l6 q/ n$ S( s#define        N106_VOL        (0x088)
. y  E6 C8 X5 ]4 L& T( m/ V#define        FME7_VOL        (0x130)
, a9 Y  `3 A+ W" k% i; P9 L, u. S& O( f' v* n. d6 `
APU::APU( NES* parent )
& H% P' {/ Y) s. o% A4 R* H9 l{0 T$ G# R% G3 c" e9 B
        exsound_select = 0;! t' }/ O1 S- i! g2 r: }% `

5 S! c6 g: P" p2 d: l        nes = parent;
% K+ p8 i4 l0 o9 D4 z/ w3 d1 \        internal.SetParent( parent );, a( I% j/ A- Z, }" \& {& Y3 p# g4 @
6 R7 \& w  v  {! q
        last_data = last_diff = 0;
/ y0 s6 \+ A8 C  P! Y$ I* d- I
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );* ?- h) f0 y3 y$ N9 H% h

- p% t" m, Z  l0 g' u; `        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );* h8 U4 n6 A/ ?9 T% S; U
        ZEROMEMORY( &queue, sizeof(queue) );. t9 g/ I+ b" }6 o) {" c1 I5 q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );" ]7 A2 P. w2 W: ?9 h4 d  r

5 M6 _5 _: |8 t* m& p# k        for( INT i = 0; i < 16; i++ ) {9 I0 b/ y  e6 j4 ~0 U+ b4 y3 w
                m_bMute = TRUE;
5 y; E# D6 d" Z9 X+ n        }
$ `$ t/ t8 Y$ A3 [+ x}
8 \3 g  J* }4 U+ {+ F  o; r2 A: F. q% ^2 f/ n' S) B+ w
APU::~APU()
2 x5 w( M( L0 m* X: ?; u{
" w% h( C( C4 S* S1 a/ A}9 _( i, c. W- h! p* E. T9 y

+ m  J+ h! l% V' [2 m! kvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )+ i2 w& b* C8 D% ^6 B0 G  x
{
( i5 ~  b" u3 D  G3 M$ t; z# _        queue.data[queue.wrptr].time = writetime;
5 E5 ]! M2 g5 N: ~" @( X0 c        queue.data[queue.wrptr].addr = addr;
6 ~" f- {- a% r* e8 ?- _        queue.data[queue.wrptr].data = data;. L% Z* h+ y6 O9 P: G
        queue.wrptr++;7 S5 K- s; J$ t* t4 M
        queue.wrptr&=QUEUE_LENGTH-1;
6 h' J- `# U$ z5 h. g, h        if( queue.wrptr == queue.rdptr ) {
3 _' t1 c9 K8 c, c+ \. J( X                DEBUGOUT( "queue overflow.\n" );/ V* c" M! A/ }0 F
        }
' K1 Q9 D; n' t}
* l$ d- B, ?! Q" [; C1 s
9 S; o# D/ [0 d9 j! ZBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 y/ g! Q9 p2 x
{3 |: c  `6 z5 g4 s1 [
        if( queue.wrptr == queue.rdptr ) {5 s; K& R( q. t
                return        FALSE;
, Q, m3 W" e% i5 c9 Z) t( k, T        }  x6 W( m, [2 Q; H9 ~* M* q
        if( queue.data[queue.rdptr].time <= writetime ) {
. ^  G0 \# c" p" x5 r" L7 [                ret = queue.data[queue.rdptr];3 z# g. @3 B  f" L
                queue.rdptr++;  |, A2 Q" Y9 X/ A" `. Q8 c6 A9 |
                queue.rdptr&=QUEUE_LENGTH-1;9 E2 _- ]# k8 j' @% h. x. j
                return        TRUE;
4 n1 n; W+ B7 y1 J1 J0 {4 f        }
; w! Y$ z8 m" g/ `        return        FALSE;
% o# a9 W# Z2 w& c6 ~}7 H5 b, r/ |/ ]0 T

( y! I1 A" o0 {. [# a- J5 bvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )$ u. [& w! `" l
{
+ ?5 y* @! z+ I        exqueue.data[exqueue.wrptr].time = writetime;
! i$ M$ ~2 s$ o/ H# N/ H" |5 ^- [        exqueue.data[exqueue.wrptr].addr = addr;2 p. Y" O$ Q) ~  O0 l& ^
        exqueue.data[exqueue.wrptr].data = data;8 S  {# G3 t  V2 l: u, r
        exqueue.wrptr++;2 n( Q3 D! L: ~- A, t5 U* t
        exqueue.wrptr&=QUEUE_LENGTH-1;
0 Y, X& v0 A7 Q: I  q, P# F        if( exqueue.wrptr == exqueue.rdptr ) {7 V( o, s1 e- c' I. S' g- }
                DEBUGOUT( "exqueue overflow.\n" );/ H' M1 i/ P+ F2 M9 t
        }
. n5 x- a  k% p}
9 ~, t# a( Q; ^+ O  }; F. s& u% p  {  d% X$ Z4 t; g  W
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ): E5 B. m/ F: J4 ?
{
( t2 M' y" M8 }; Q        if( exqueue.wrptr == exqueue.rdptr ) {
) b- w# _- K' L8 w                return        FALSE;8 f$ G; Z* I9 E3 m. e' |" i  S
        }
6 h8 {' S& ^% n7 [        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; q- N9 J/ V* g; P* L. R1 b
                ret = exqueue.data[exqueue.rdptr];: P- r. j- y. e5 s2 o
                exqueue.rdptr++;4 R9 y! ?3 q, x
                exqueue.rdptr&=QUEUE_LENGTH-1;
( s/ m8 w  a0 _- h0 l# l                return        TRUE;
$ J/ E' {" z1 p( @# B- N        }! i/ T7 c; Y# w
        return        FALSE;
  D6 w5 {' B- b  H) W}% Z+ N5 {' U4 S) g$ }$ k

+ @. c, h" V" O9 P' P" N0 wvoid        APU::QueueClear()/ f, F$ K2 K0 S8 r$ T! w6 h/ d
{
8 ~$ b' a$ C% I, v6 d        ZEROMEMORY( &queue, sizeof(queue) );; @  C9 ]: G. r+ `
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, S* t: o- |) j. z/ A' w
}
. f0 Y, X. o, u8 N' L1 ?5 u  m) o3 ?5 W4 ^- q
void        APU::QueueFlush()) V7 [8 L- s/ m) u2 V6 p
{/ H: b( p# a! D/ t* R5 K6 k8 G
        while( queue.wrptr != queue.rdptr ) {9 P5 ]$ s% ~8 @+ G8 s. y6 S3 J2 }
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
2 C5 d. Z* Q5 I' t" e* c+ B                queue.rdptr++;, _' k/ t) @/ q; Z. A" O
                queue.rdptr&=QUEUE_LENGTH-1;2 S; t8 t4 x8 e5 s! {
        }* E; r, S% N5 j
! m1 |0 W4 K! q3 f9 C, Y) n$ i" o/ S
        while( exqueue.wrptr != exqueue.rdptr ) {
  h5 N; X: @9 r+ m                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );4 g! ?, L9 k# b) h3 `- ]
                exqueue.rdptr++;
% T' p/ g" |9 s& p/ G( r- w9 G                exqueue.rdptr&=QUEUE_LENGTH-1;
. @0 ?( X! h8 f% P0 E        }
  `. t. q( j. Q5 T7 F}7 n' ]( p% d& V1 n, ~3 W7 ?

9 V+ R6 A0 N5 R  {) o( e/ ^- mvoid        APU::SoundSetup()
# H* q, k, D+ ^9 s{1 i+ B. F! W# h+ T$ O7 m) O3 w  S
        FLOAT        fClock = nes->nescfg->CpuClock;
3 O7 n+ O" k  B' M5 Z        INT        nRate = (INT)Config.sound.nRate;
' l( A0 Z) E+ j: P. z/ w        internal.Setup( fClock, nRate );2 \1 @' D) w8 k# z
        vrc6.Setup( fClock, nRate );
0 _! U7 p9 W9 \# R        vrc7.Setup( fClock, nRate );
: T) ?/ }7 n2 G3 [        mmc5.Setup( fClock, nRate );
; u) T" N- p0 G+ y/ y& x, @        fds.Setup ( fClock, nRate );( V, t1 N4 [* r0 r6 [. R
        n106.Setup( fClock, nRate );3 t0 d, B) F" R. g( U
        fme7.Setup( fClock, nRate );2 V( L9 `/ n5 x
}: S0 I$ @/ t8 f, ]2 Q! F. |/ b
: t# N. n" K2 W" o8 {5 ^9 u! j
void        APU::Reset()2 E' l- t3 ^8 C! d" D9 ]* I' q/ g
{
; M+ i8 _. G+ G2 g  r        ZEROMEMORY( &queue, sizeof(queue) );* ^6 N( e( V! d! f# Z* k
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 d9 Y# v! `; R: G6 }7 {; Z
% l/ a2 `9 Z# J( t3 A
        elapsed_time = 0;
& L" f6 L' Z, @! J# ~4 Y; d+ }$ f6 m9 F0 k- d) \  u0 x9 h; U
        FLOAT        fClock = nes->nescfg->CpuClock;3 g; E- U5 l4 n
        INT        nRate = (INT)Config.sound.nRate;
* Y9 _" X! h# g# {        internal.Reset( fClock, nRate );# k+ r$ ^) B2 n& u! z( }5 E
        vrc6.Reset( fClock, nRate );  c2 _9 \7 E: ^0 o7 i- |' R% K; V
        vrc7.Reset( fClock, nRate );" ]( e" U; H, @
        mmc5.Reset( fClock, nRate );! X, p5 d3 v$ |' [" K; |, D9 _( z* M, T
        fds.Reset ( fClock, nRate );; V# Y2 e1 @2 r: B2 v1 o8 N3 W
        n106.Reset( fClock, nRate );
1 T7 {+ ^( q/ }. x; \; B6 S" R        fme7.Reset( fClock, nRate );
/ M3 M7 v( S+ ^2 p; p" b' x8 ?' @
3 k! k+ v" [8 I+ P0 q) U        SoundSetup();
& B- _" ^) b; w9 |  ]+ E9 E) m}/ O" J$ s( {# c& g+ B3 V3 `

8 A0 m4 M* m6 V4 Evoid        APU::SelectExSound( BYTE data )$ X/ s0 j+ n- c
{# O3 ~- E7 R7 [4 M1 G
        exsound_select = data;
' F" F/ k  `( O+ P; |8 Z}7 Q8 t( s$ {" [' h+ G1 e$ Z6 j3 [
/ u' @( z; G' z( l7 t$ z
BYTE        APU::Read( WORD addr )
$ m2 F2 q* g/ b9 a( |' c0 V{
- J$ g$ R' N1 c4 Q! H0 W        return        internal.SyncRead( addr );
% U5 r$ z. E  ]8 k0 P}, ]1 e+ f1 g- j: V8 I8 i4 {
8 h1 q$ I5 [  J& r% n: m
void        APU::Write( WORD addr, BYTE data )1 v/ K' O- {7 c1 u) i0 p, \
{% B0 e* a" `+ K: `& H
        // $4018偼VirtuaNES屌桳億乕僩; ~/ l( L- T9 t3 \7 m, s( F" [: O  L! Y; Z
        if( addr >= 0x4000 && addr <= 0x401F ) {! g' H# ?, k  \9 Q0 b
                internal.SyncWrite( addr, data );* N* @. Y$ L# W8 q1 Z) j" C
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );& e& d! W+ ]4 O# U* m
        }
! z, |0 ]$ q0 u" ?}
* Q9 D, T* n, }$ q
! X" c' a, h: h: ?3 E2 p& IBYTE        APU::ExRead( WORD addr )) Q5 U) R5 O2 {
{" ^  @8 M- x# W
BYTE        data = 0;9 t( i$ ^5 w0 s# J; }+ y; h

2 Y( q! p/ n: ?9 d) Y/ x        if( exsound_select & 0x10 ) {
+ ]8 ^' W- C. }" p                if( addr == 0x4800 ) {- j! x$ `2 a) i% b5 s" R" H
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
9 p) ]) u7 r, Q0 H) S. F# M                }6 q& I7 C! |* Z* ]' D
        }
; }* \3 n' S- K" a        if( exsound_select & 0x04 ) {
+ R4 r1 C0 T" Q! {' D                if( addr >= 0x4040 && addr < 0x4100 ) {
0 H- {+ l- j- F                        data = fds.SyncRead( addr );
9 x7 C0 D6 |) B$ n& }                }
/ i* V% i" i" n9 j5 R# J        }
7 X' I/ W* v! B' A4 J        if( exsound_select & 0x08 ) {
4 l1 m( c% ]. W+ S6 Z                if( addr >= 0x5000 && addr <= 0x5015 ) {
. Q) u0 L% E$ w                        data = mmc5.SyncRead( addr );9 D$ t" U5 c. [5 S6 K' Z
                }7 s# A1 G2 V& ?, u/ h
        }
) R- W1 ?7 i! H; W& u: B8 _6 ^+ G. R% {7 l' M) }
        return        data;
) f9 W! |, J0 Y" O1 U' x# |}, u; Y  L: b$ p) ?, v  T6 Q! {

' }" q! P+ K/ O% k8 v) M4 }5 jvoid        APU::ExWrite( WORD addr, BYTE data )
) g. @8 k. u) K1 t+ m. ^{
$ P; S% `. s' Q        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );! B4 b( H( }- X9 _5 k; T) R  D, y

/ |7 i7 I( U" P: P: F9 \' j- E        if( exsound_select & 0x04 ) {
# u% K, `4 v+ z+ I4 E. R* i7 _, n( C                if( addr >= 0x4040 && addr < 0x4100 ) {
& ~, a5 d) b# N; h) b5 w5 @                        fds.SyncWrite( addr, data );
& w3 H8 [+ V2 K$ O4 ?# Q! P. b                }5 w/ k" `/ `- S1 O
        }
: U4 r! i2 Y% F! O4 t! G5 ~
; s7 \! z6 a+ @9 A5 U/ [) O1 C* x        if( exsound_select & 0x08 ) {3 ?/ j% C. h8 C6 n; [
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 w8 l8 @# Q  H+ G; e% H4 Y                        mmc5.SyncWrite( addr, data );/ x5 J; m0 m' b% k* a
                }
# t; L# P. a- C, a        }1 Y/ W. Q% _, m- V- Q: w3 S6 Q
}
9 I: ^/ n. k2 U1 d+ ~) z$ [/ ?  l  D% q) J1 b
void        APU::Sync(); j* B6 J+ g8 ]7 w: _' X# y& @
{
, O# X% J/ x8 p  i% h* n% R+ F* P/ R. S}
; _  f: D9 w/ ?9 Z( D& G
; H( o2 u( M, ~) \! ~0 o9 \void        APU::SyncDPCM( INT cycles )
/ s: v3 E4 x, y) m4 ]4 m{2 [2 C$ O  J, V5 ], E* F) G
        internal.Sync( cycles );7 J% ^; E5 X% \: Z+ |

% ~) Y: h8 i& S+ v% Q6 D        if( exsound_select & 0x04 ) {
. h' B" Y" c3 i3 ^  Q6 F/ w                fds.Sync( cycles );) H$ z# x) o: v$ D# t& C; i
        }
0 b8 e7 T! s  u# u. \        if( exsound_select & 0x08 ) {7 z' c  T% `( a) r4 r1 l
                mmc5.Sync( cycles );
; h4 H% A! z1 }        }
3 y8 W. W& J! _# T7 D7 U4 }+ H% B# k% v}( p  R/ g! S* s

; V& Q3 u! U  c  lvoid        APU::WriteProcess( WORD addr, BYTE data )) V+ [) j( G4 n2 O# }
{
0 r* u8 B- k4 [3 v$ G4 A+ l8 b        // $4018偼VirtuaNES屌桳億乕僩" T2 l: E' m0 s
        if( addr >= 0x4000 && addr <= 0x401F ) {, e, P/ f" w& t, ?
                internal.Write( addr, data );/ x( G$ V0 V$ p
        }
; b/ ]( b5 P. _8 Y}! f  p# I/ E! B0 T

, x$ ]' W+ [) e/ B4 b) evoid        APU::WriteExProcess( WORD addr, BYTE data )1 Q* x# d4 f" Q" R5 K+ G) }
{
7 [+ X$ Y4 y9 I        if( exsound_select & 0x01 ) {
, ]" H" Z: ]. N# Q. R4 L# e                vrc6.Write( addr, data );  v" D: h2 x( {9 q$ H! T, N* W" O
        }
2 s  M" y- d# O5 w" L8 K+ O; i        if( exsound_select & 0x02 ) {. T7 P1 F9 t$ _8 v" X
                vrc7.Write( addr, data );/ P  ?8 i# V/ w4 Q
        }' e" K4 ]) d: @
        if( exsound_select & 0x04 ) {$ \: z7 n# `- g% i' |
                fds.Write( addr, data );* r5 j, @" Z# L( G# r% S
        }
7 Y" M- `& h) o  b# `        if( exsound_select & 0x08 ) {% V2 @. J9 r: E; ]$ J0 _3 v. a
                mmc5.Write( addr, data );" z$ x$ ^& }1 b; z! p, ~/ J
        }' H4 [8 I' e; G2 b/ A5 h1 h
        if( exsound_select & 0x10 ) {7 S! m0 ~$ {' m) m# r6 \# k
                if( addr == 0x0000 ) {
, ^7 K+ ^- M9 f' k: U                        BYTE        dummy = n106.Read( addr );) V$ m$ V6 t2 H$ \! N
                } else {! ^9 s" ~4 E$ ]4 `
                        n106.Write( addr, data );4 ~' R. h0 V& _
                }; g9 F# X  u) j$ n1 B7 }
        }4 D0 M) \5 }: `9 a4 g  z# b
        if( exsound_select & 0x20 ) {
6 e9 }& }  ~; n; |5 E7 |                fme7.Write( addr, data );
# [) W5 m/ S* l: Q" f% i        }
# }% N/ f0 Q5 }+ I}2 ^  ~  Z" V6 I9 J4 D5 ^% ?* f$ s5 n
- s$ R( q' n% Z+ C. H' y9 P
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
% ~2 Y; m1 ]# I& C' Z! M5 f{
& R% _$ {' l$ [  w! mINT        nBits = Config.sound.nBits;1 u% E& o2 o" e- S( m9 Q7 X+ _! T
DWORD        dwLength = dwSize / (nBits/8);# `( x- a0 `, e( l$ U3 {
INT        output;1 f$ I" `/ P3 Q6 {& `# f7 y; o: C9 b
QUEUEDATA q;
$ M4 D. ^# _8 |9 t2 l3 w- PDWORD        writetime;$ m$ R* G% P% K; h; q
! q! I  b$ U6 p7 K$ k0 b& a$ n
LPSHORT        pSoundBuf = m_SoundBuffer;" {# c5 j- r8 u: e/ h: L: I
INT        nCcount = 0;
1 g0 {3 n; n5 P# _$ O7 T; s7 E& Z$ k1 C) i: S6 \
INT        nFilterType = Config.sound.nFilterType;' |# F5 d5 i7 y8 W$ S; n

: d6 @4 w9 \: D/ s! {/ G        if( !Config.sound.bEnable ) {6 a4 Q* D6 c* w: p
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
1 q* O% \" B" c5 V+ V- w                return;/ E: @) |0 j4 x- i
        }) M. _3 E4 I. A
0 U: P2 H+ W8 q2 u  C
        // Volume setup
  H( M& ^8 E. |/ `        //  0:Master
# h' E8 a! Z1 @5 m# U' I" \        //  1:Rectangle 16 k4 c! |8 |7 W
        //  2:Rectangle 2
; O- E' Y( ^: G8 Y        //  3:Triangle
# a: k# z7 M+ c# ]# T3 [7 B        //  4:Noise
; A* E1 a9 f$ o1 Y        //  5:DPCM9 u! i5 L7 S/ b* _% L- X8 j
        //  6:VRC6& h! W; D/ x& _/ s
        //  7:VRC7) Q7 c1 R( g. h
        //  8:FDS
, ~' `1 Q; v& o        //  9:MMC5
( U8 @+ T, Z( B- g( }        // 10:N1069 `9 a$ P6 j7 a! p/ D( t
        // 11:FME7
) u- v( i6 G6 q0 r- P0 J        INT        vol[24];
% z8 o% l6 {0 t) I+ F" F* S+ ?        BOOL*        bMute = m_bMute;
: T6 z) [* e2 _% M3 w3 o1 }        SHORT*        nVolume = Config.sound.nVolume;
' |+ x0 S' S! o4 W8 t: a9 z
, U  V+ \7 j) U; ~$ A: v1 r. p        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
) Y& v. K6 f' m& H, B5 f2 S' P" q% k: v% |3 L1 J( S
        // Internal3 w2 @' m3 N" z, E
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
; w9 Q% E7 P0 k; i        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# E) A7 e8 X5 v4 H1 Q        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
! F' k, o2 f9 S        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ n; m' f+ q7 \
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 h- t& X+ M5 }$ j$ c1 t) x/ J  I$ O/ `& |! M
        // VRC64 t& @" `& Q3 z; D/ A
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% ?- c4 f9 P+ F  z6 w        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 A6 F" ?! O. f
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 w3 I3 b3 b* `/ @  J. Y0 @& r% g

8 R; L) T9 t, q  |9 }# c0 ~* `+ J! \        // VRC7" }" W3 N: K' b
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
4 n- K+ j9 X6 b& e5 o( D2 f* F8 z; K3 Z9 _  C
        // FDS
) E# S  Q: {' I8 d- o% Y; @3 d+ X        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;; N6 B5 y) N  f' r5 Z
# ?$ U( b' |$ q% V" n
        // MMC5& X8 Q5 v7 T% T. ~8 {
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 i9 Z" j8 V8 q3 }  @
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ ]2 L: S: e* o; S! q
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, |3 o+ r5 O' W$ q, Z" |5 T7 n( N0 _) W/ q; U7 r$ B3 @- ?
        // N106
( r8 T2 N. w4 O3 V* z1 Y9 y        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 E! ~0 i$ ]: N! _+ w        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ G  c8 v8 E' x2 \; l1 x* Q  Y        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ B8 e/ i- y( u# ^3 r, q: c
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 n! B5 m8 O0 R6 r2 @$ J( B
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 g% G7 U  l1 E: ~2 }
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 A8 K6 x: {6 C( d
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* N: u# T# Y) M3 O' b
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' C1 R' q$ ^, r( y5 v9 a" x' N4 Z2 h; l' y
        // FME7
# y  q) P0 L, z% T9 |& Q1 u        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( R+ a2 E- e% `6 G1 r, a
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% A% K; D8 a' V5 w: @; B
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 B6 Q) r1 l. Q
5 [' x* |2 |; A# A
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;# `7 u0 @# ^& f5 \) p- v
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;! S) A7 L0 W4 |% M7 [

, Z3 \# _2 s% ]/ }- W        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
: ~+ ~  u/ x  t( J0 z7 N        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
) R( i$ w9 d1 C- r- H, j" u                QueueFlush();% u& ]+ v5 a9 y; s' P
        }7 p3 e7 N2 I( ~" r% {
+ I1 {) U! ^5 I$ d
        while( dwLength-- ) {; D  h3 F# S% a2 D9 n) R, M
                writetime = (DWORD)elapsed_time;6 V; [! X7 X- n4 i0 V
: G, C2 {$ n( G' [; X; \
                while( GetQueue( writetime, q ) ) {
; d" j2 G& T  X; I; `) E                        WriteProcess( q.addr, q.data );* j5 k1 `; ^" E: @
                }7 d3 w/ _( R0 G0 v4 F6 z

7 F* I$ l* S$ S! Q. c# w  ^# P" E                while( GetExQueue( writetime, q ) ) {% c7 [" p7 Q" L0 u' n
                        WriteExProcess( q.addr, q.data );
4 W0 |" c5 N3 W4 z& D/ q                }
' }, G- m2 {% |, k) ?( m9 i1 j9 I$ Y) o# o; a2 k
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 E4 |2 R! ^) J
                output = 0;3 E/ p8 [; y+ _, [1 }/ x1 I! e4 v. |
                output += internal.Process( 0 )*vol[0];
. Q5 @0 j) |4 `9 k. h                output += internal.Process( 1 )*vol[1];9 f3 E: X$ ?; o" s, s2 v% {& `7 Y9 Y
                output += internal.Process( 2 )*vol[2];
; `0 a/ g. _; N, C                output += internal.Process( 3 )*vol[3];
  q  X+ N& U6 x: s- ^7 ?5 U: C! \9 X8 M; ^                output += internal.Process( 4 )*vol[4];) t9 a4 {" ~# |9 ]0 e7 r3 r
( g+ c  |" l6 D  n8 G
                if( exsound_select & 0x01 ) {8 n9 O% b2 k( b7 O' I/ j7 P" \+ `
                        output += vrc6.Process( 0 )*vol[5];% E) n  b' M- |) |. h5 h
                        output += vrc6.Process( 1 )*vol[6];9 A2 D, c4 u  x8 a
                        output += vrc6.Process( 2 )*vol[7];
! x" @: \8 k6 I1 I5 B3 i                }9 d# S/ h1 [" M4 s; {- Z: s. F
                if( exsound_select & 0x02 ) {
" d/ {3 W% w4 b2 A+ v- U" z& S                        output += vrc7.Process( 0 )*vol[8];6 x$ b. w8 }7 F, f8 b
                }) c5 S0 X/ z) S% \8 ?( r/ T
                if( exsound_select & 0x04 ) {7 ~" L, v2 {% j; {; w3 W" I
                        output += fds.Process( 0 )*vol[9];  X/ K& F. ^% I" e* ]% i
                }
7 Z5 z" I+ {( G" v% |4 v3 `, t                if( exsound_select & 0x08 ) {1 L9 y& H' O% `+ s5 `
                        output += mmc5.Process( 0 )*vol[10];. M- [3 |9 D6 {# z0 o/ g8 U
                        output += mmc5.Process( 1 )*vol[11];
2 T: {$ a' a/ S7 T                        output += mmc5.Process( 2 )*vol[12];' E0 J& l8 K! `' j- o  `" g  A" C
                }  j8 u, O3 h+ y1 Z& `
                if( exsound_select & 0x10 ) {/ J, u7 }- F! O9 H1 g
                        output += n106.Process( 0 )*vol[13];- N$ d: d! y) i4 `  {. b
                        output += n106.Process( 1 )*vol[14];# s! w8 q8 z) w! b$ S2 a" ~: ?8 {
                        output += n106.Process( 2 )*vol[15];
& w2 d, i  S5 H6 d' C( I6 t. D                        output += n106.Process( 3 )*vol[16];- x0 H- g+ H) M/ f/ R0 i( x
                        output += n106.Process( 4 )*vol[17];. K9 C! _* A% E' ]; |& ?
                        output += n106.Process( 5 )*vol[18];& S0 R& q1 y5 x
                        output += n106.Process( 6 )*vol[19];% }. V# A5 P# p) l$ t& |% ]5 H
                        output += n106.Process( 7 )*vol[20];
- T- p5 A; A4 a2 C                }
6 S0 h- F& \; [& ^# R                if( exsound_select & 0x20 ) {4 F% p/ j1 J( |) [, k# p+ G( @
                        fme7.Process( 3 );        // Envelope & Noise
+ F' w$ h, [$ I# P' G                        output += fme7.Process( 0 )*vol[21];
' ^2 P/ t2 ?8 H! A" \0 k* p4 M                        output += fme7.Process( 1 )*vol[22];
& p( t1 W" Q( a$ X                        output += fme7.Process( 2 )*vol[23];
+ ~. Q+ C+ @7 N$ m- c$ I                }
9 L# X7 v$ ^0 J/ U, V) l5 q0 y$ [7 X3 i: x* W
                output >>= 8;
6 F0 B  T1 s4 f! G0 q
1 ]- y* _$ I' O6 n: k2 c( N                if( nFilterType == 1 ) {
9 w9 n' b3 Z" \( K% l                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)  q: s# B4 [4 h. U" R, p1 W) w2 T
                        output = (lowpass_filter[0]+output)/2;% U4 H* u1 U8 y/ Z9 Y2 G/ x$ ?9 ^
                        lowpass_filter[0] = output;% w. P3 Q2 A3 d/ q# w
                } else if( nFilterType == 2 ) {1 u0 z$ g5 {  V* L* [( Q& ^! m5 r
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 n; y+ G* E0 g
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;2 _0 V# a+ V9 T. \5 W
                        lowpass_filter[1] = lowpass_filter[0];
" @9 G( d, t# ?6 \! u, {1 ^                        lowpass_filter[0] = output;
6 V2 Q/ V% u$ C+ a; }$ e" V* P                } else if( nFilterType == 3 ) {
$ H1 @& K8 b9 W* M7 @                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* _9 ~0 A# `! Q% ^3 z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;  s; q5 i& X8 |
                        lowpass_filter[2] = lowpass_filter[1];
6 a# ]. N$ H8 w" c3 {) u* D                        lowpass_filter[1] = lowpass_filter[0];
( t& ^% |( ^! l) s$ t7 I- l: k                        lowpass_filter[0] = output;; y7 B9 m, g0 s  v3 m  m+ k
                } else if( nFilterType == 4 ) {
' I- u: C, s0 _( T                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% v0 ?1 r; |: C1 G) x  B1 w, m4 l, l
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;* P+ P' K% w1 w0 ?* }: `) i/ r; p  l7 ^
                        lowpass_filter[1] = lowpass_filter[0];
% w  r" l: h1 |& Q                        lowpass_filter[0] = output;" H/ a" T# q: B" L; L) l) z: T
                }% C- {+ Z  O! `4 g- `1 T
1 l' i! X5 ^. x: t. p' K
#if        0
9 j2 }6 I! E  C5 y                // DC惉暘偺僇僢僩
4 {8 v: r  J! }: \0 I' F                {
4 ]9 I4 T2 p, n# I                static double ave = 0.0, max=0.0, min=0.0;0 a: j, p& S, T7 \9 s$ \
                double delta;- O* ]. o* W  W- ^
                delta = (max-min)/32768.0;/ _$ b* A# g5 H5 P! [1 V% Q* ?
                max -= delta;# ]5 P2 B; p7 r& C9 r
                min += delta;3 s9 R# A9 T" [5 F! _) b
                if( output > max ) max = output;: N; k. Y7 o* m( Y& C4 \8 L
                if( output < min ) min = output;
! e5 @, b" v6 I! j                ave -= ave/1024.0;8 z2 |, f& z6 ~- b& ?
                ave += (max+min)/2048.0;! V, y, j) C" X' }7 V& D9 x4 Q% o6 d
                output -= (INT)ave;
9 x; }  W/ {0 R) U                }
' q4 }  A( a7 M5 ]7 S1 f# u#endif3 w8 ~3 L& f7 H: m; [6 A! `! L
#if        1
, X* e/ a  E, S) X9 {9 c& P; E                // DC惉暘偺僇僢僩(HPF TEST)# c: w' \6 d- w& A* i, n
                {
+ x! w: M: L8 O0 n/ {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
: K( ]- v6 r8 ^" N9 ~% l                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) D8 p7 W* R: v8 I                double        cutoff = cutofftemp/(double)Config.sound.nRate;
) S6 A2 D( f) e8 C                static        double        tmp = 0.0;
% ~3 ?. p! R3 B0 N$ w0 M                double        in, out;0 G- d1 ?( k- O$ B% }# |7 {
! D7 R6 q4 K) O2 X5 ]9 c
                in = (double)output;) Z( Y# Q: d0 |; c; [' N( _3 }+ H
                out = (in - tmp);1 ~* ?% ~+ r+ `9 x+ s
                tmp = tmp + cutoff * out;
- N( M8 ~) V% ], t4 K" A% p) `7 [5 u0 V* }+ J. }0 R0 l
                output = (INT)out;4 ?$ b  r: N1 j% L' u& G# ^6 {. P: I
                }
( V' q4 C0 K! l- y#endif+ C( r2 B: O9 F! d& P7 [
#if        0
& h: E$ |. q+ Q- S. s; |1 S                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST). [; ?' P9 P. ?2 a7 l
                {$ w. d* A6 q; X  ?1 `$ ]  R% Z
                INT        diff = abs(output-last_data);
( B; b& }- P+ O                if( diff > 0x4000 ) {
1 }- K# B6 R( P; L8 w                        output /= 4;
1 |, P  q; Z3 h7 a7 w                } else 9 V7 ~. ?! @# G/ N2 i
                if( diff > 0x3000 ) {. d* A; ^# m; _" l6 t; h3 q
                        output /= 3;
- Z4 ?( q/ b" |1 j7 l                } else
& t, Q' r6 g$ i, k! l                if( diff > 0x2000 ) {
& g1 w. `# C3 n$ O8 ]' F& k                        output /= 2;) g, C+ @" F; Q* E/ c" R
                }
% t, a" J3 |, g8 |, \+ B                last_data = output;3 [* O5 |2 N: w/ r; ^4 M
                }
7 W2 c/ b2 @3 w' Q7 P" ?#endif
, @& `( U5 o9 }$ F& L2 i# t" o                // Limit
- W' e. l( s! N! ?4 V                if( output > 0x7FFF ) {( {1 h% q- _* |. ^$ Q& {- a. }! j$ b
                        output = 0x7FFF;3 n5 k8 K$ o1 H
                } else if( output < -0x8000 ) {% c" P$ O0 B* W, @( P, F5 i7 K
                        output = -0x8000;
5 N# A' k$ s, x                }
1 q( K- Q. @. P! g
/ t' ^: d# x; {& M# M/ I, i6 o                if( nBits != 8 ) {
1 W) F& o1 ?. u3 C; S8 [: _                        *(SHORT*)lpBuffer = (SHORT)output;
+ d9 g9 c6 Z/ x, Q9 Q2 X( Z, f: r                        lpBuffer += sizeof(SHORT);+ X0 D$ M  P! }3 O5 A6 |: Z' o! q* d
                } else {
: s% D) d0 Q9 Y- j5 G6 {# o                        *lpBuffer++ = (output>>8)^0x80;
/ X: y( a) t0 n& K7 f                }
% f( \+ o" B; ~& ^+ v+ B
8 y# l1 Z. h6 S- e1 C9 x. K4 o                if( nCcount < 0x0100 )  d4 b2 ^1 Y0 X4 e; {8 F1 ?! ?. {
                        pSoundBuf[nCcount++] = (SHORT)output;
4 M5 W6 p, y, E* C  d
; A; w" Y5 t& F' [6 @# ^//                elapsedtime += cycle_rate;
* b0 y! r/ l9 n0 F$ G) d$ {) k                elapsed_time += cycle_rate;
* J% P7 z) w% Y! W) v5 q; D        }
. y. t% ^) y/ D8 L7 v, N2 Z8 [  V: S
#if        1
& p! Z5 G- e9 j1 ]% k9 N        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
: M" h0 g: O, z                elapsed_time = nes->cpu->GetTotalCycles();
; U# i' ?8 z  |( e" w. k7 c. E- L        }( y% l: Q0 ?9 [! n7 X$ h/ ^
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
, o: P+ j) }/ P7 C! h1 {                elapsed_time = nes->cpu->GetTotalCycles();/ K/ y6 z( ]5 F- P( t, H$ v
        }
6 q) s& [' ^) k#else  j) e% G/ G' Z3 ~1 c
        elapsed_time = nes->cpu->GetTotalCycles();$ _5 u8 S( H8 y, Q- y! \* N0 p
#endif
; L# X6 b( A& L% m. j( ?' i}
. \) A/ }7 n/ g9 D$ I# m) B* x  Q+ x$ l& d9 u$ [# \( t4 L, K
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
( S2 d( I8 [5 @$ w- ^INT        APU::GetChannelFrequency( INT no )
' {1 ?5 ^- s  d7 G+ G2 i- N{. s$ M. H8 O9 \& ?9 |6 r
        if( !m_bMute[0] )% ]# P$ l8 v9 `. J! k% c
                return        0;
- j: m3 V2 g5 r# b9 e5 R
7 U5 n% o* j: i        // Internal" C7 a: m3 ]. L4 Z0 p! d
        if( no < 5 ) {6 ?7 {# }4 g- W6 r
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
! V9 X9 O* ~1 v5 N( H        }2 \/ Z) b. T! g- M/ e3 L
        // VRC6
# k# }1 h) s7 t% D        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' q4 u6 D/ w6 v                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;* v& _6 D! e& a1 |
        }; J4 z2 _7 K" F5 ?3 t
        // FDS' _  t5 R7 L/ ^9 z2 b( G$ K5 [  I8 F
        if( (exsound_select & 0x04) && no == 0x300 ) {
! r& W* B! Y, P6 G7 H& x                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 ]' K6 K3 [" e4 u6 l; Y$ l6 ~) ?8 u
        }
! j" Y  ?( L& i! s$ ?. C( M        // MMC5
3 }% L! Z$ j' F* [: N6 V' g        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
7 z0 r' y, V0 B, F1 S( h4 N, ]                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ C3 {  i  T( u: ~) b
        }
% o0 z/ H0 N7 N& Q        // N106
! K+ {8 G# g: r& h# u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {! ~  l2 S2 {) V( I: F6 l
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
6 H6 }; E$ S' O/ Y1 s- o3 r( N3 s4 @% n        }! b  v- w& y( Z( ^
        // FME7: u# t- n( M8 Y  w
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 Z# F& r+ Y" d
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;  c* H/ v, m* Z/ s
        }. L1 T3 J# H& F. B9 R! B! o) z
        // VRC7! R" ~  ]( l. f4 ~/ ]
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" h: s6 @( G7 u% m0 a9 t2 B2 @1 c                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
" C& r4 O" ?: q* g0 R        }
9 N9 o* r* {& M4 D9 T/ @9 u        return        0;
+ L% Z- O# ~* @5 {, h}
" C4 \' O0 N/ x) E+ i! X
* y6 l% `$ E! m// State Save/Load- g, F$ g3 _' |' N
void        APU::SaveState( LPBYTE p )( X9 _5 I: i* }2 Q/ |( E7 f
{
0 E" D8 x8 @# o  O6 l#ifdef        _DEBUG# X7 C; f/ O4 A1 `
LPBYTE        pold = p;
2 |* f7 l9 c5 o" |% n#endif5 c3 p3 W8 @! |- f

1 ]$ X% h: u% c- I        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞* K2 E  ]2 a3 U; f. G
        QueueFlush();. ^4 s+ R3 w6 \

0 `" N. i; ?1 \( {% Z" f6 D        internal.SaveState( p );
. I. Z) e" i- P5 B3 X        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( {. s9 f) e! n$ ]" i4 d  i! p. [

+ \0 ]' Q5 g* C' U. Y" @. z        // VRC6
( n8 E0 W. B) Z' P        if( exsound_select & 0x01 ) {
9 c; |( T. C- ^  h: p                vrc6.SaveState( p );
2 u5 X5 X' H8 D/ E) ^# _$ I' {7 I                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, F( d9 Q8 ~, E1 }* j' x$ o- A) q1 d        }
/ S. ?% _+ n$ h! _2 B        // VRC7 (not support)' ]% R$ X4 }* R( r0 u+ v
        if( exsound_select & 0x02 ) {( b% o  ]7 p+ |/ C/ L3 I" K
                vrc7.SaveState( p );
7 I$ i$ W+ \! I6 f                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( B* T5 ~# n7 D5 F1 [: [1 [
        }
/ ^$ e" |  s# J; q4 \: G% e        // FDS
( e( |0 `. ~7 d* Y        if( exsound_select & 0x04 ) {; k/ x% Y& n' ^. n/ p' _* I5 R$ g
                fds.SaveState( p );
" y1 Y  ?& y) _& v" n+ y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 B/ ~4 P1 n) y        }
7 P) H, o1 A' W* ^4 y        // MMC53 g% r% m/ J+ F9 k. _& @& _/ o
        if( exsound_select & 0x08 ) {: G/ O  m. c4 R4 H4 V4 C  H
                mmc5.SaveState( p );
3 l! W' H9 f6 E0 _3 T& e                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: f* z* [) _- }; P8 Q6 ]) t        }
, o5 _! U% i) L1 |; t% |        // N106, @% w6 P2 m7 V$ h; K5 `$ r
        if( exsound_select & 0x10 ) {
+ k4 p0 ?' l+ w! {& t- r# n. ]" P                n106.SaveState( p );# F! z/ m7 K: C2 U& r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: X+ s# i8 [+ z' x0 R( s) u
        }
( g1 F( M4 F" k/ T) g        // FME7
$ u7 L9 x+ P/ F6 t        if( exsound_select & 0x20 ) {
; e: Y6 ?( L9 k6 q                fme7.SaveState( p );4 F, D8 @5 Y& F$ S7 |, y5 j
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 ]8 w& _4 S/ E
        }9 h& i# o7 C( x4 c5 Y' t3 E) v

. v$ G) ?  i3 x& Q7 m% u#ifdef        _DEBUG% W6 F$ F: ]/ T0 f/ C3 r
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 [% L/ d( b$ D
#endif
+ ?6 p. }3 b5 A9 v  A! b3 d0 d}0 h( n" a9 `5 D7 E: V
2 r; f& z' E# B9 w0 K# y8 }+ d
void        APU::LoadState( LPBYTE p )
9 {. C: m* X) F, b7 ^{: D' N/ z$ n7 c; r) G& a
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡% h' z( i! g( ?0 `% F
        QueueClear();) p: n% p8 i5 ~  Q; L& {

; W) i% ~: |& B+ v7 ]5 N/ v% N        internal.LoadState( p );
6 ^4 S/ ^+ |+ i; s! P        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ W3 R8 K0 o9 V! J7 [+ O( M

5 D; J  N1 k" B5 E* c4 q# Q        // VRC6) N8 e3 }5 ^8 _1 p- `
        if( exsound_select & 0x01 ) {
: A1 q; H  H9 [. A                vrc6.LoadState( p );
! G# L! F0 {. V: u; b. Z! o, ~                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. u' z5 z4 S9 s
        }2 I; x" Z* J4 L+ D$ G) m2 s5 k
        // VRC7 (not support)
7 o3 ?9 }9 C8 W. M        if( exsound_select & 0x02 ) {
. s/ Y( d) `1 ?/ X, C                vrc7.LoadState( p );3 g/ ^( M% Z! Z: J7 s  `! B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! w+ M* d8 K& [$ n& N3 c: x. m
        }) R- `7 b1 ~6 K9 |$ }9 B6 Y
        // FDS! i8 R# }: I4 d1 ^' g# n$ P
        if( exsound_select & 0x04 ) {, b. w% x) k+ H3 q# Z
                fds.LoadState( p );
4 [$ n! @) s. X8 e' Q- l) d; _                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding) U- T6 b- n9 ^
        }! f) @1 k+ [3 z1 Y- [9 a
        // MMC5
$ f9 n$ m* M5 Z2 q% z3 B        if( exsound_select & 0x08 ) {
' q& G$ ?. e: [. x& D2 Z. o                mmc5.LoadState( p );
0 D& d: f; M& _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 R( x  N- F6 r4 I: a
        }
& C6 v: t: R% v8 y1 L        // N106/ y! r* M/ v" O
        if( exsound_select & 0x10 ) {: s# w5 ?8 D; a8 T
                n106.LoadState( p );, n6 A, t5 T$ h0 ]$ _
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% s6 c2 ]) ~0 A% u2 t9 x. L
        }
0 z0 L  ~, n. u- B        // FME75 l% L, L) z5 k# W$ h% x
        if( exsound_select & 0x20 ) {3 n+ `( M8 {; m/ ^. s( E, b1 p# W
                fme7.LoadState( p );
  X1 {/ p* s, v7 K+ U5 |                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) N8 Y( \% ?! H$ _' _9 V        }
* u* b8 P5 K" }8 R: M: R}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
. v4 {' s4 o' O2 D& u$ C  M可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: l+ R. J3 j! b  s1 O) W) s
感激不尽~~

$ L3 A" H. g1 r  G) P8 p3 k% a恩 我對模擬器不是很有研究,
4 f" S+ I7 ^6 {" X3 M) z雖然要了解源碼內容,可能不是很困難,
- x4 C  e: M) H3 D不過還是要花時間,個人目前蠻忙碌的。8 ?- S4 l) u5 \7 Y2 _

/ Y" A1 m8 S  L; Y+ J9 d給你一個朋友的MSN,你可以跟他討論看看,
* t3 j- d6 Q* E- T! K: J他本身是程式設計師,也對FC模擬器很有興趣。
' W( P9 [" A# N! S  m2 K# c& n5 o; T( c+ u! u
MSN我就PM到你的信箱了。( ?2 v3 f+ r4 p. G" d6 a
$ e/ Z' b" X  i( h
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# S+ e( J9 e7 `; {& c: Q呵…… 谢过团长大人~~

, X: A: J1 j! M6 ?
1 ^$ R- v0 _3 u4 ]2 {. @哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 3 |! r5 ^* x! {$ A$ @
团长的朋友都是神,那团长就是神的boss。

3 \& D7 b4 E2 J8 A; }哈 不敢當,我只是個平凡人,- B+ K, D$ I+ U( n- r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 y: [$ w; Z: @( T3 \( MZYH, A( q9 Z: A* S: d( y: y
QQ:414734306, H" c' ?5 ]6 W1 w
Mail:zyh-01@126.com
, T3 y' v; q" W& ~$ S3 I; u5 z/ |; q" g- f: z3 D6 y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . F: V( e% \9 X8 U* h$ ~+ o
再次对团长大人和悠悠哥的无私帮助表示感谢~~

3 i" I' a! y9 `# _5 @' k7 h不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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