EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; f8 y: B7 r! C- A; Z7 e1 s, T+ {楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 \7 O9 _) `1 j4 U
这里有相应的模拟器源码,就当送给大侠了~~& w8 R- X# P5 f' G
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 , m) N( g2 f# ^% z: `# G) x  O2 q/ e
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 a* A7 J- Y* a9 `9 V3 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 f/ n3 k& z* B6 ~$ W
这里有相应的模拟器源码,就当送给大侠 ...

2 h5 W' {/ }$ \( j* _- X聲音部分(Audoi Process Unit = APU):4 C; x- `. O9 \- e3 ?! Y
.\NES\APU.cpp5 Y" A; C1 C  |( b2 I2 ~, b+ b0 k" l$ B
.\NES\APU.h: {7 g5 ~) [9 T9 }
$ z  s0 ?0 p7 `: e( y
- y7 a; h& ]( n2 g- X6 n
影像處理部份(Picture Processing Unit = PPU):
8 n3 O, o# S, B) Y8 w, j! H.\NES\PPU.cpp" {# R3 T8 e- c; p- y, q4 J
.\NES\PPU.h
; V8 H: n5 c; {* `. Y" m1 G. _8 r" b0 {9 T7 T, p2 L, ^/ H0 }
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ N4 j+ U/ J: I$ k8 r+ c. ?- Y
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 i% Z% a# s- K( s" L% }* X(由于很多专用术语和算法机理都不明白,所以看不大懂……)
2 u/ [, J+ U4 T* T9 v4 S//////////////////////////////////////////////////////////////////////////
( y6 \0 [$ T' y) j//                                                                      //
0 h& }/ ?7 v3 c2 R4 s% y//      NES APU core                                                    //5 Q# n  x6 i6 T# i9 ^! V- |0 n
//                                                           Norix      //0 V3 u/ }! p  L: H; S* X( s/ K
//                                               written     2002/06/27 //9 A# O0 J5 Z7 ^
//                                               last modify ----/--/-- //4 V2 U  v# Q/ \& S+ K
//////////////////////////////////////////////////////////////////////////1 R* [8 v+ X  ~' s
#include "DebugOut.h"
0 f, b; S0 W9 h1 h#include "App.h"
; R  b4 O! G' k( i#include "Config.h"
2 L) u2 s* r' b# d! W
/ @2 c3 i( ^6 l#include "nes.h"$ n9 x* O3 R5 T( h. k, Z
#include "mmu.h"
1 g: c, a% V& Y#include "cpu.h"
) B$ j+ |# a; j2 M) Z#include "ppu.h"
1 V) C; K* _/ T. ^; [#include "rom.h"
. N; ]+ A2 Q9 \3 r8 ?( y' Q#include "apu.h"* r5 \$ j0 v6 z3 y" C+ C
! u7 H- o0 [3 l5 d/ k, _/ h
// Volume adjust
6 q0 v9 W1 v, L" B/ i9 f0 \// Internal sounds
9 l5 @/ X3 {9 P0 I* L#define        RECTANGLE_VOL        (0x0F0)
0 `/ F3 n$ g. H1 d#define        TRIANGLE_VOL        (0x130)/ u7 e- X5 r( r  m1 O4 n( v
#define        NOISE_VOL        (0x0C0)
  s. p5 f" y; p4 u- ^+ l#define        DPCM_VOL        (0x0F0)0 u: l- U6 ]/ k5 A; L3 e3 U
// Extra sounds
: W- F) m) X& D+ z#define        VRC6_VOL        (0x0F0)% E2 c3 L1 D  t
#define        VRC7_VOL        (0x130)
' _  B, `$ k4 c6 \7 p+ S* c* F#define        FDS_VOL                (0x0F0)# }% z$ U9 a3 b6 k7 Z; L% k' X/ {* R
#define        MMC5_VOL        (0x0F0)5 g- d$ ]. i. H7 ^# _6 P
#define        N106_VOL        (0x088)( N& r) ~! P% n1 ]1 E3 d8 v; Z
#define        FME7_VOL        (0x130); c5 }9 Q& S6 d! h. K8 g

- m. ~! ~2 n8 M: xAPU::APU( NES* parent )
. `1 \. U4 h4 s' O/ ]' X{
7 i  u% E( M3 y5 D- K9 c        exsound_select = 0;
/ L  n9 w; F5 g2 V( N9 Z8 A' ~2 I* k$ B2 ~1 b6 T: n" D
        nes = parent;) U* a% v5 H% C2 M  g2 R* ]
        internal.SetParent( parent );$ ~: t; {% z( W6 G: X! z5 y4 g

' p7 _* x% r$ ^9 }& c        last_data = last_diff = 0;3 `- A0 _6 v' _7 q+ a& N7 \
8 H. ~# K+ z+ }; w. t/ e" Q
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
+ u) T6 V5 a+ W8 d; w
! F5 f& k# x- h# g+ g( g        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# a' b. L& M; m7 T1 q. m; P        ZEROMEMORY( &queue, sizeof(queue) );
1 B: G8 [( z% x        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ y- T3 N  F" y1 n; J; S/ }
2 v/ _) f7 R4 ~- K1 j) @
        for( INT i = 0; i < 16; i++ ) {% O: W8 ~  p0 w* g
                m_bMute = TRUE;
: E2 L! @+ F* @" O" j8 k6 T( v        }
! T. q0 q& P! H" z7 f- h/ d}; z1 p( ^1 ?3 p, r9 \  j" B
0 M8 z  v: v* H8 d1 z. Z0 `! h
APU::~APU()
2 e, w  ~& z# B4 V9 m{5 H2 M& N0 [5 \  S
}6 d' w3 i$ n3 V" ^
0 K/ G  _; d  L+ g) w; C$ @9 r% P
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
3 Z  N& _: N: f+ X{
  w. n3 Z, E# \0 ?2 R        queue.data[queue.wrptr].time = writetime;. l. g( @! z: D% A1 b1 s4 U% n
        queue.data[queue.wrptr].addr = addr;) S3 N; u1 o7 L0 y# B
        queue.data[queue.wrptr].data = data;
1 ?1 X0 ~8 f8 e  P/ K9 o5 G) t% b        queue.wrptr++;
) e/ E. P5 c6 @$ T( E7 M/ z0 C5 ]6 Y        queue.wrptr&=QUEUE_LENGTH-1;
$ ~2 {9 P8 t5 H. \- C% B) s        if( queue.wrptr == queue.rdptr ) {
0 Y& P1 v% B% d6 G                DEBUGOUT( "queue overflow.\n" );
6 U# K& F* R3 O        }9 p- i/ g- n2 R& H8 E7 R4 t9 y
}
/ s  q9 B$ y, G0 n9 F8 x0 s
  L0 C, H0 I( \3 ABOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. P: j! D7 Q% ]{1 H% E9 v2 v. Y% s, y- N
        if( queue.wrptr == queue.rdptr ) {
" Y/ M0 Q( z8 z+ D                return        FALSE;
- m8 B/ A0 Z/ ~" e. r4 \9 j0 v. x9 e3 I        }
$ b" m* [& i: D: e. H* b        if( queue.data[queue.rdptr].time <= writetime ) {% k9 w8 ]% t0 w) M6 ?
                ret = queue.data[queue.rdptr];
: `3 ^) O5 V) h5 c2 v' k                queue.rdptr++;
2 x9 @2 ^2 S3 D2 M) ~                queue.rdptr&=QUEUE_LENGTH-1;) F' ^( B' p2 Z% S6 m
                return        TRUE;
4 T  t9 r; B: P0 _7 s        }
! O4 i( w  j& v1 |  U; G8 ?        return        FALSE;  A  H" v' V4 ^) `- G  H& t! {, X
}+ j6 c- c& O5 G

  ?, Q* `  j3 ^( C- _void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
0 H) L0 }" `  V, [  g{$ m$ W9 G& t! Q) s7 J8 t6 Q, Q$ ^* Q6 z
        exqueue.data[exqueue.wrptr].time = writetime;
( K; @% f, E6 b9 {6 Y$ l        exqueue.data[exqueue.wrptr].addr = addr;# U- y; g  R+ @0 @" u
        exqueue.data[exqueue.wrptr].data = data;
8 x6 P7 I' `3 o* n! I7 j  `2 t4 p: k        exqueue.wrptr++;7 o* b6 I9 N- [- L3 k
        exqueue.wrptr&=QUEUE_LENGTH-1;
+ J) h! m" i- N& K2 c, g" l/ [! Z$ u& m        if( exqueue.wrptr == exqueue.rdptr ) {$ ~  Z! O% U3 ~
                DEBUGOUT( "exqueue overflow.\n" );
$ C& c- ?# g2 G9 |, G9 G        }4 l4 V- M  w+ [/ k" L8 H8 Z9 R
}
1 d% [" l/ n/ q
3 `7 G5 K% U2 Q# I7 }BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )- s( ]+ B) w% C1 ^
{
& S( p& O  F: A) U) C3 e5 U9 {        if( exqueue.wrptr == exqueue.rdptr ) {: y7 g8 T8 o3 p; d
                return        FALSE;
) c# V; @3 X  L# K- m5 c: u  D        }
" [7 [1 w2 `; k4 z        if( exqueue.data[exqueue.rdptr].time <= writetime ) {9 [9 y3 z; ?" \0 O# a5 V# u. i. I
                ret = exqueue.data[exqueue.rdptr];1 Y: ~" e, s# a, Z
                exqueue.rdptr++;
" M' e; \1 I# o                exqueue.rdptr&=QUEUE_LENGTH-1;1 D) T: s& r% E, w- Z6 T  p
                return        TRUE;/ q& e, i3 ]7 a. X# f8 W# [- j7 Q
        }0 `6 z1 \6 E& F9 j1 @
        return        FALSE;4 q  r5 T: a& u2 ]1 W
}. |, t2 l) ~0 Z  l
, ?$ w$ ^& D7 H; P
void        APU::QueueClear()
; X' n9 I6 m1 m- N{8 n: Z* v) D8 j) G* }1 w
        ZEROMEMORY( &queue, sizeof(queue) );% K/ @/ n- h" }  C$ `
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# B$ ~; ~, E" p; a}
# l/ m2 E) S+ x2 h/ @  i- v
  A' R2 [- ]$ }- I  T3 Wvoid        APU::QueueFlush()
$ f3 W4 T8 A1 m; u- b0 W! s{# N: i( \% `+ ~2 n
        while( queue.wrptr != queue.rdptr ) {
3 L% E4 v; R5 J4 n                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
3 E- G/ I* N$ W7 ^8 g# I% w5 V' b2 x                queue.rdptr++;# p/ e1 p3 u# t& E
                queue.rdptr&=QUEUE_LENGTH-1;
) }  P( {4 N' b1 j        }8 L' U1 H/ M! k1 T& S

+ p& T! k$ ?8 @% O+ N$ X0 v$ g1 F9 d( u8 J        while( exqueue.wrptr != exqueue.rdptr ) {
9 ~0 K: n, I/ ]% d0 v9 ?                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
1 {& j2 n0 h1 f- M- ?                exqueue.rdptr++;( n* [& x5 t9 ]
                exqueue.rdptr&=QUEUE_LENGTH-1;! L' t% @8 y8 z/ u1 s
        }6 U% U( u+ _/ r" J  r
}  e' a0 c& s" F. M; {2 k- [0 R
1 n% ?* s2 p* t$ \
void        APU::SoundSetup()
! v9 L7 L$ z" w7 d" x) C{) H8 U) H& l* i# K6 r
        FLOAT        fClock = nes->nescfg->CpuClock;; n/ u3 V7 s% ~# L2 [
        INT        nRate = (INT)Config.sound.nRate;/ ]. I' L- y- w0 O
        internal.Setup( fClock, nRate );4 @( I, f- R6 t# x& R' q: H- j" C- u
        vrc6.Setup( fClock, nRate );+ I5 b* G0 C7 q0 H4 X5 V
        vrc7.Setup( fClock, nRate );
# P0 [# V" A$ d8 Y# R0 `( }        mmc5.Setup( fClock, nRate );0 z* q0 g8 m* e" D  Y- N( X
        fds.Setup ( fClock, nRate );
3 ~, D3 X. l) `        n106.Setup( fClock, nRate );
% `1 T% g; ]' O+ p) [/ C* c7 d        fme7.Setup( fClock, nRate );# L; u' s/ C7 r7 k7 b7 W  U
}6 ^' t* I1 @9 _. p4 {% {+ k

9 t- M4 b( ]: H3 L  cvoid        APU::Reset()" f* Y& e) x+ `0 ]! i6 f
{" k# E5 q( X9 K
        ZEROMEMORY( &queue, sizeof(queue) );
, a+ h. W' a; m' Y5 M2 n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
9 O0 ]: j. Y( G( b  X+ A$ x, |' ?: l9 {' }* A  K# H
        elapsed_time = 0;7 t" R$ ?/ O9 q4 O# Q1 x$ x: c( u
7 c( E" M6 X6 \  {
        FLOAT        fClock = nes->nescfg->CpuClock;6 R: F& f; ^; F3 D& ]- V" q
        INT        nRate = (INT)Config.sound.nRate;0 e8 }% L6 f* a" C
        internal.Reset( fClock, nRate );8 p$ A5 o% A, I
        vrc6.Reset( fClock, nRate );
. k' s3 K  i% I; E; @8 ^  e# Q        vrc7.Reset( fClock, nRate );3 {! {) z( A& B  q
        mmc5.Reset( fClock, nRate );+ r9 K' F2 I4 z# A2 m
        fds.Reset ( fClock, nRate );
8 [0 [/ y  {) E- g. B9 L. H        n106.Reset( fClock, nRate );+ _' K! z1 p% ~3 V6 ?
        fme7.Reset( fClock, nRate );  ^7 ~) v9 G% X  x) Y

$ s, u0 Y' g% J  H9 c, @% F        SoundSetup();
1 ~$ a6 ~3 p; L- O1 _}$ l9 i+ \$ R" }

) ]/ A8 j9 v7 ]# Q+ T5 ^6 mvoid        APU::SelectExSound( BYTE data )  X/ {# w1 S7 b
{
" u0 Z. d1 V8 H9 D' x        exsound_select = data;
! W, H  r# g+ p' s}1 }" |2 U5 v- F. M

. x" A6 k) R" N8 O3 A, X& DBYTE        APU::Read( WORD addr )
/ ]. f2 v9 a) k$ t& ?{! q8 ?& W( m7 x
        return        internal.SyncRead( addr );
: [* B3 O4 Z" a. P$ O" S. }) k}
) I: O/ s) b& y1 o* Y1 G- \0 H! F, c0 ]+ T2 s
void        APU::Write( WORD addr, BYTE data ); f( O$ M! a* f, v: I# q
{
, ^9 ~1 L, ^. N- V1 f( q        // $4018偼VirtuaNES屌桳億乕僩
( s' E$ i, H4 @( b        if( addr >= 0x4000 && addr <= 0x401F ) {  r* p, k7 i+ L) w( Q" J
                internal.SyncWrite( addr, data );
9 e2 }( [8 R5 r7 g                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
- w# K7 G. n0 ^( q7 |( S  n$ \' m8 I        }* F) a: Y5 t" e6 y5 C
}
5 Q2 H( S& m% d$ G. H% _( q
' m3 D% r2 w$ q- q$ d: Z# jBYTE        APU::ExRead( WORD addr )
8 g# v1 w4 q9 w  m( A  n{/ |* f9 s, O* t8 p- q
BYTE        data = 0;
# F: C/ t' Q& R, N0 o1 r
( @3 u$ }$ f( {+ }        if( exsound_select & 0x10 ) {0 X7 X- J1 a0 T8 O$ m
                if( addr == 0x4800 ) {
8 n% n4 k2 d  j5 L7 V; u                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
- U+ h4 ~$ m+ ^0 p6 G9 M                }
6 {5 K: e: P! L5 ]- r6 h        }
+ n% W% a) R1 m+ U6 ?        if( exsound_select & 0x04 ) {, H+ m7 H( M9 }. u
                if( addr >= 0x4040 && addr < 0x4100 ) {
5 Q9 ?$ ~% }+ }5 z                        data = fds.SyncRead( addr );
& z, b3 l6 ^9 L* h# t+ f5 ~                }
0 F; ]( x+ P- x, H        }
/ z* j* B7 c/ d) X$ q: u        if( exsound_select & 0x08 ) {
9 T3 v$ |  F* |) p+ N                if( addr >= 0x5000 && addr <= 0x5015 ) {
. o) O, W9 \& T5 p, z7 V. A- _                        data = mmc5.SyncRead( addr );
  i6 T* ]* R5 H! ^8 l                }2 T+ `' f: A, J/ B5 _8 e9 S2 n, X
        }
7 ~' W1 |- F+ y* D+ J$ {, i' g4 W) _1 f/ l* I4 k: [" U/ P% |
        return        data;
% y" s# J# v+ S9 u}1 Q! P/ @) `0 A- x: H
: z- K' R0 S( Y6 m; j% Q8 V
void        APU::ExWrite( WORD addr, BYTE data )5 R/ ^# u) c" r* F
{9 b8 m5 D+ t7 y" k
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 X: z4 @5 A) C9 X1 G7 o8 v
; d8 A5 _8 ]2 q# b' X6 Y
        if( exsound_select & 0x04 ) {
8 l+ E  o5 u! c2 g7 u                if( addr >= 0x4040 && addr < 0x4100 ) {
, }% w! C! V, [2 c                        fds.SyncWrite( addr, data );
1 |5 u$ y& n- [) T5 m                }8 b5 E* n5 c) ?! B+ q2 G
        }0 Z$ G) c8 e/ d7 ]1 }% l/ }
& d, ^* ]9 g. w# L# d; k: z
        if( exsound_select & 0x08 ) {
$ ^" M9 O2 r) o. u5 c6 D                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 g: p9 W  a( j% U2 E                        mmc5.SyncWrite( addr, data );, }8 K" N! W! \+ Y$ H/ e: ?
                }
7 x1 _. Z1 w2 d$ K        }, Z% P$ y4 G" \+ S
}- p/ F3 G. Y0 Z
/ E. z! F6 s1 B1 ]' O7 g# T5 a: @
void        APU::Sync()
8 c9 {; g% `% \' G" {; q{
  l5 N+ o0 z( @$ F+ R}7 K7 x% _- e1 D/ m

7 r( X! u6 k! Evoid        APU::SyncDPCM( INT cycles )$ ~" E# S; y7 A
{  \, t3 f; G3 [  ^9 m) Y
        internal.Sync( cycles );
- m1 e8 S/ m5 c  w
# D. W1 V  n4 s0 e* ]6 U8 Z        if( exsound_select & 0x04 ) {' J/ {! V2 F! X) v3 X
                fds.Sync( cycles );5 r( K9 w) {  t
        }
) w9 _( |. P: w8 b/ p/ ]        if( exsound_select & 0x08 ) {
0 {( N8 g3 V! u8 m. r) I- d                mmc5.Sync( cycles );! G4 }1 z* w% M
        }8 J/ T/ ~3 p  D0 Y
}4 g8 Y2 m; b" j# F% M$ J) P2 Q

; T+ F# T$ N9 o! J& {% i3 a: n7 P9 Jvoid        APU::WriteProcess( WORD addr, BYTE data )
  T' ^# q6 W& k{
0 M. L* ?3 z7 l9 T+ {6 w        // $4018偼VirtuaNES屌桳億乕僩7 A% {; e$ |! E' \: U" ]7 _
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 s9 b8 p' b- S8 M                internal.Write( addr, data );+ s/ k  J0 \% p5 E0 [4 o8 u: i, s
        }- f) c% K0 d, b. _
}* x" H% h& {; }5 }, B
' [# l( t8 y4 g/ s2 B* ]
void        APU::WriteExProcess( WORD addr, BYTE data )1 k/ O! C5 O8 k, j5 t5 E3 v
{5 N  A4 a0 o) z# N3 Q6 v( q  z
        if( exsound_select & 0x01 ) {
2 q/ @& G" D% a. `- \                vrc6.Write( addr, data );
6 @2 j* h# y2 d& b        }
7 u6 @$ P7 F5 A* o        if( exsound_select & 0x02 ) {7 r7 |* @1 {* A2 L: |% }) u5 _
                vrc7.Write( addr, data );/ S% A5 D, C; w6 l* B# x$ x2 Z
        }
2 `% G7 A; {" h3 ]7 R$ ^- I) Q        if( exsound_select & 0x04 ) {
6 V$ J4 e9 Z" {* l) ?8 I+ C) x  ~                fds.Write( addr, data );
( h( c/ n' x$ J' Y        }
: l9 _; W4 D0 y- v: ^        if( exsound_select & 0x08 ) {
. Z& J+ _9 R! g; e6 }- `                mmc5.Write( addr, data );
6 A3 t; k; g6 g* L        }+ B' p2 |+ H$ U! Z# J! a- e9 x, Z0 f
        if( exsound_select & 0x10 ) {  _* ?  [. ]8 a2 l+ t
                if( addr == 0x0000 ) {) n+ T% A! c  W: g! w9 q
                        BYTE        dummy = n106.Read( addr );
/ \5 D: _4 u' c- v; ~# r! U                } else {
5 \; F0 \7 ^6 r7 F* p. m/ g                        n106.Write( addr, data );
  @8 {  R6 Y% N                }, W4 i0 p% v9 v: u- @8 {
        }
7 Y2 @1 p: I5 H( F        if( exsound_select & 0x20 ) {
6 l) J% w" f9 j! x7 s- k. {1 Y                fme7.Write( addr, data );
  ^$ w8 K" s, g4 m        }% ]' I7 v! M& [+ F" u  S
}
* w( s: H( P7 t$ A
& m  ~+ z  M. H# zvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ): ~& k" S+ A! h& ^
{
% l. C7 a! b. ]8 T. s4 BINT        nBits = Config.sound.nBits;  q; x5 W1 T( ~& e" {1 P
DWORD        dwLength = dwSize / (nBits/8);) ^$ h0 O# }" B: ~/ t- U/ o
INT        output;/ X) L+ j; ^* f. Y" M
QUEUEDATA q;4 \& J: n0 ?) q  v# b
DWORD        writetime;
/ M7 V% }4 Z1 [6 C
8 n! K9 H4 a7 P0 G: q: ?  TLPSHORT        pSoundBuf = m_SoundBuffer;
/ ^0 R; U9 |" a0 LINT        nCcount = 0;3 u7 y2 Z5 U! N9 Z2 T$ E
1 X: L% C7 M7 G/ c8 [
INT        nFilterType = Config.sound.nFilterType;
1 ?6 M: b  ]  m6 ]- _
& e" T# k/ W" s; F, B, O2 y        if( !Config.sound.bEnable ) {
) j* v3 R' k/ n. g8 b3 a                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );' c, j0 o* M4 s8 E: g& n* {
                return;
0 J; v3 f  T  D# a5 ~9 ~* {9 P        }, |) a; A' U5 a) G0 \- w

# @; @, p( n* G6 W# n2 p* j        // Volume setup. `3 {& [+ `- Q8 B
        //  0:Master' @7 `/ t4 l0 q6 j
        //  1:Rectangle 1
# i7 O' X: D, `/ T! e        //  2:Rectangle 2$ Q7 _2 e$ m) P/ r
        //  3:Triangle! m$ J: p$ [5 w# ?. D
        //  4:Noise
# s+ Y( q# x% r% g* f) S& T7 M* H# T% A        //  5:DPCM
% t& {4 z) J% g  f; y        //  6:VRC6
/ v* W; R5 M' {+ B9 E$ X: b6 g        //  7:VRC76 O+ _% S  J1 z+ J! X
        //  8:FDS6 S0 F+ |% q3 Z7 j: H% R9 \
        //  9:MMC5
* Q7 E/ i+ ^$ `& d7 g" H: N        // 10:N106, m( R' [! @0 B# j- _
        // 11:FME7) C# m4 p8 n; n
        INT        vol[24];1 ~6 [3 I2 J: |6 E: `1 G) W
        BOOL*        bMute = m_bMute;6 s5 n& Q: L6 _) ~4 ]
        SHORT*        nVolume = Config.sound.nVolume;
3 b1 h1 f! B+ T  I" j$ Y
% O  ~% |! \' L+ M/ q        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# p: A' v* Q( Y: ^' R

4 j6 w* e( L% q! `' d3 H        // Internal' b* m* D* [% w& \
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
0 q* ?! I9 J# V) B, w9 ?( ?- N        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* c2 n+ |: o$ V" e0 _        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;# A1 W1 W% x5 M" _1 ?  e
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
/ @' p0 O3 c. [3 S9 E        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' l* p9 ]: C. ]' R* L8 ^
) G- U% L( M$ l: y9 b+ M; A: o
        // VRC6: i$ z3 g/ \, U. c; R8 s: A4 Q
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 P  o- b( @% N
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. p0 Y1 r- a3 k! B4 Y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 I3 l4 m* u, O( p1 y3 D2 l1 _+ F% L) L/ E0 N% y
        // VRC7
, |0 {& y! m3 P) t        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  V( c" y( U/ K% V$ D- j; O9 y) u! ^5 N- A5 |0 ^% H, Q* {
        // FDS) F: b! c  ?* a( g: g. I9 P
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
4 G0 G! L' T$ L/ m) ~& N  o) d
        // MMC5
% V3 F2 x" Y$ @& T        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 q. b+ i4 d1 X. z1 s: t
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; P  A9 Z6 ~, r7 D0 i5 Y
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 s9 g! Z7 ?" k; `2 {8 }

* c( b0 p/ P) N* \1 ~. D) s, X        // N106
3 C% U7 k( @6 Y  E8 O8 i* r        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, W4 ?* n# p" L$ e) D/ E5 D
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# r" _; E/ X6 A5 I3 Z7 H0 u        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' b1 r$ ~( K. t! t) P        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 \. t; ]  N7 E) {( n        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 K) o- E" ~& j4 J. M5 ?9 F        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. d) L& W+ z- d1 c  d8 P        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, ^* `5 Y' V9 L. r5 k4 F        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' c* w1 F8 h5 e& g7 C" L1 a! R( m0 ~
& ^% m- R  M1 m4 ?: ^        // FME75 m0 F; Q) ~- [( W: f4 b4 V# `
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 ~- X# N, W- N0 ^2 S$ H: @
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  e& C: L( U4 s' ^: w# ?
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% a# Z5 @  t) q8 D, y6 N+ C) y" R/ q. v" ?
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" {& ?4 k9 e5 ?1 T2 X        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;9 A$ ^6 Q  d2 i9 \7 O) h$ R

- m- q" r/ p3 D7 x- f9 p. q# v        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
! h$ N5 D/ q1 y, O& V        if( elapsed_time > nes->cpu->GetTotalCycles() ) {& B+ L( s3 t- b3 D5 Z0 f
                QueueFlush();% ]5 k& d$ _- F
        }
& \( i! q0 R2 b  G( r9 _. Z3 \- @3 _% |  [* [% F0 ~
        while( dwLength-- ) {
- L$ I* h$ Z# ?6 ~3 D3 q9 m; w2 h                writetime = (DWORD)elapsed_time;
( {+ U, t* I. Q% C# |: S1 Y* i9 M: ^1 Z- D
                while( GetQueue( writetime, q ) ) {# d+ H. s( s7 b& Q6 ?" ]" t4 [
                        WriteProcess( q.addr, q.data );. w4 X; L  O  v( d1 Q- {
                }% w' t  i# Y% j+ o
5 h8 g/ `! w# q
                while( GetExQueue( writetime, q ) ) {4 e) s$ [4 U- {3 w7 {/ O/ V
                        WriteExProcess( q.addr, q.data );6 p3 |; c% _9 D5 [
                }1 |# e; h. Z$ @6 g: X4 U
' S4 b; E5 [2 d- N  w
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ [9 u5 Q* b6 Z. r                output = 0;
- P2 I+ n9 m8 Y' L) k                output += internal.Process( 0 )*vol[0];
& m+ Y8 x3 h+ \& P' g9 a  Y. b                output += internal.Process( 1 )*vol[1];+ P- m, W; P: S+ U9 K3 y
                output += internal.Process( 2 )*vol[2];/ x# R2 N$ ]7 P  Q  C+ r
                output += internal.Process( 3 )*vol[3];
- F7 D  ]& l- P0 k6 s7 r                output += internal.Process( 4 )*vol[4];
5 g' K# K' f2 v% p3 M
* U, Q' ^% \1 }1 M7 v1 T                if( exsound_select & 0x01 ) {. e7 o* ]# B5 w' u: `/ h! S
                        output += vrc6.Process( 0 )*vol[5];0 M/ N9 Z$ P1 `1 \4 p! C/ M
                        output += vrc6.Process( 1 )*vol[6];; c# y* G/ k( ^1 u% e" S
                        output += vrc6.Process( 2 )*vol[7];
3 l- Z) H2 T) o+ X' E                }
! C  P5 Q' G5 J6 ?; W                if( exsound_select & 0x02 ) {0 Q; `$ G% z5 {+ E3 Q8 D$ l" j
                        output += vrc7.Process( 0 )*vol[8];
; }2 n; V# n. i  w8 l+ M% O3 c% a                }( x5 h( u- S: C  g
                if( exsound_select & 0x04 ) {) }) B( w" p- z  G- Q- v
                        output += fds.Process( 0 )*vol[9];( ], X/ q  C  E3 K; j
                }
; v" `; m5 C3 u/ v                if( exsound_select & 0x08 ) {
0 w3 \/ Y/ K6 s' {                        output += mmc5.Process( 0 )*vol[10];) ~0 y* J. z. i
                        output += mmc5.Process( 1 )*vol[11];
" x: @+ l5 E, U, Y+ A' i4 c                        output += mmc5.Process( 2 )*vol[12];
0 h9 y2 ]6 H# q' {1 f! ~                }( p7 I# S8 ?  h( o
                if( exsound_select & 0x10 ) {
5 y9 f; j" e+ c" l                        output += n106.Process( 0 )*vol[13];; Q0 ^! s# K' x" S
                        output += n106.Process( 1 )*vol[14];
& k* V% I# r) A6 K$ y/ x6 |                        output += n106.Process( 2 )*vol[15];+ b: P$ N4 o- F, p0 x& Z& R9 Q$ q7 P
                        output += n106.Process( 3 )*vol[16];
, W6 \6 \7 o, a; P5 M                        output += n106.Process( 4 )*vol[17];: r1 U: p( B. i
                        output += n106.Process( 5 )*vol[18];- \; J1 e4 }' I  Y1 M  ~/ \
                        output += n106.Process( 6 )*vol[19];
: ^7 Y1 Z* @! Q' c4 C( t0 ^2 T- f                        output += n106.Process( 7 )*vol[20];
6 g5 G' I/ S/ e6 n8 [# Y                }$ c9 J2 H( T1 t# C5 g" R: f4 B
                if( exsound_select & 0x20 ) {, f& |3 n. O! q
                        fme7.Process( 3 );        // Envelope & Noise' A7 S5 v" Z3 G+ h* j" [
                        output += fme7.Process( 0 )*vol[21];
9 S4 T" J( _8 I                        output += fme7.Process( 1 )*vol[22];) ?$ P7 e6 Z+ e% ?* ]' c: _
                        output += fme7.Process( 2 )*vol[23];
, V7 f. I. c: J) t; j0 F                }
% A" i: F* d) S! o1 f; `% H0 J/ I% e. W
                output >>= 8;
! t+ ]2 a) N( ]3 X4 T% x
, N3 p; y. i# _2 c5 V- V                if( nFilterType == 1 ) {* S# @# N/ F+ M- c9 T+ S; F
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 z2 b: P' J5 w; f1 [5 i
                        output = (lowpass_filter[0]+output)/2;
3 _& s3 r- r- ]0 Y) S                        lowpass_filter[0] = output;
! q- z& y9 j" m2 d$ `8 c4 W                } else if( nFilterType == 2 ) {
; b% V( E  D2 L8 L                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! `/ C( u: }0 j                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;. v$ W( _( i  Y6 k/ Z
                        lowpass_filter[1] = lowpass_filter[0];
2 B' d- b# |1 m4 c1 _                        lowpass_filter[0] = output;2 P! F. V: G3 x5 i6 k3 C8 g( h
                } else if( nFilterType == 3 ) {
! d# K% f( W2 N# h' I+ m                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ v7 ^& T, j7 U% Y5 ~
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! U& P5 i2 V* w
                        lowpass_filter[2] = lowpass_filter[1];
2 }' H, _! T* B; C" L0 {' @                        lowpass_filter[1] = lowpass_filter[0];
0 |# q8 a# J) m  C- \                        lowpass_filter[0] = output;  `; c, A- Z$ y: l- a2 W
                } else if( nFilterType == 4 ) {+ C" f3 E4 h! v  L$ E6 j- o% u+ k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
3 H# q& {8 m* \& ~8 `  U0 I  S                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;# W/ q4 f& B0 c
                        lowpass_filter[1] = lowpass_filter[0];
  Z& {- r' \4 d( q                        lowpass_filter[0] = output;& v* E; v9 Q; s' m$ X3 H7 z
                }
6 w. E8 j7 \8 R4 D9 m. \4 r$ v+ Q* t& u/ T8 D' m' s1 r
#if        0, I% j& d( e4 S0 N
                // DC惉暘偺僇僢僩- D! U6 ~1 Z+ D. P. Y7 Q  m
                {$ p$ |& s$ [7 r7 X- e
                static double ave = 0.0, max=0.0, min=0.0;
, P# N/ C! S& T/ n                double delta;+ _/ u' u8 u( Q/ z
                delta = (max-min)/32768.0;
/ W; s2 |% l" K2 y                max -= delta;
  Z) p, v# o( d3 {; r5 X5 B                min += delta;
2 p- C$ c: W: J+ R, P" O                if( output > max ) max = output;
1 k0 r  `* |' \/ l( i1 R                if( output < min ) min = output;5 U6 v$ x+ u# W: J2 ]" i0 f0 ^4 g
                ave -= ave/1024.0;
, s: k/ i4 x; R1 S" d                ave += (max+min)/2048.0;
: j# `3 O+ s3 d1 i3 e1 I0 Z0 _. Q  B                output -= (INT)ave;; t' K# |. D3 u5 I* Z1 D7 ~
                }# ~3 L5 ~* V* d2 R) ~
#endif" t/ [6 z+ A1 w1 v+ g1 D; v
#if        17 d/ Y% }( Z- b; W5 I
                // DC惉暘偺僇僢僩(HPF TEST)2 M% A7 Q1 Z6 O3 T0 r; t5 N
                {
" w: V/ m0 ~- Z6 z" S$ {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);7 p) s4 P1 j& g! Q/ W4 f* `' e
                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 O+ E$ ?$ E( \* ^8 l$ T
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
2 f4 f9 d8 Y! @& w                static        double        tmp = 0.0;
) ?" o) @/ H, d                double        in, out;
( }5 F3 o1 C3 K. ~1 D0 n6 h+ s" b+ ^+ P; |, u4 \1 n) X
                in = (double)output;7 k7 H4 v$ v5 d3 P
                out = (in - tmp);
3 f$ {$ V0 l$ r; ]3 H0 W                tmp = tmp + cutoff * out;
; c4 Z* a5 g9 r' `8 i% x
6 Y! Y% \$ P, C' {7 ]                output = (INT)out;" R4 C1 d4 d, h) B4 y2 ?
                }
" t# [1 B. r! F6 K6 |#endif
2 j2 B- ]9 N2 r8 O#if        0
+ {5 A. v$ \+ m! H3 W1 K                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 g* X( y% @* {7 `- t- S; L( o
                {9 C* W- P0 D0 Q' N' i) N
                INT        diff = abs(output-last_data);: b. A0 P, ]- u/ i9 I3 A; p+ k9 ^
                if( diff > 0x4000 ) {+ n! _( o: e, O( I1 z* \
                        output /= 4;
  Y2 T. K" B5 v2 Z2 [3 h                } else $ E2 {$ W1 T0 k! ~" s- |3 B
                if( diff > 0x3000 ) {! M7 o) m; Y8 [6 }4 n% {, B
                        output /= 3;, Y6 H& W& n& b7 o! a0 Q
                } else' R/ M( G  O+ z1 m  b
                if( diff > 0x2000 ) {4 J! m* a7 f; S" Z1 v# X+ l
                        output /= 2;; |2 g+ l7 V, \3 s- ~3 A/ u
                }
& e  N9 |" P* A0 O                last_data = output;' n. _+ P; M" z1 t; \' Z* a/ r
                }' P% I- d2 G* h
#endif/ \5 m1 X9 `6 ~- d1 U2 l7 @
                // Limit; a6 Y: ?: X& G8 d2 R6 I
                if( output > 0x7FFF ) {/ G$ R6 I+ A) V8 y3 u
                        output = 0x7FFF;% V: [. l$ Y$ {) O
                } else if( output < -0x8000 ) {, m! L1 l2 G5 ^, x9 o5 P
                        output = -0x8000;
4 k/ m$ j4 G6 l0 T( E/ n9 x                }
' q: \: L8 t3 ~$ @  B+ {& s. ]' s2 V  K. n+ B) A  }
                if( nBits != 8 ) {, I9 A* S4 f# g5 |' ~" ?
                        *(SHORT*)lpBuffer = (SHORT)output;
% L3 r2 D: S" P  r                        lpBuffer += sizeof(SHORT);" }6 T2 Q6 p- }/ S3 C* K
                } else {$ |7 }& p2 }$ O+ m
                        *lpBuffer++ = (output>>8)^0x80;
0 i8 o% C' R! c  O                }0 f8 q+ W1 n1 b$ _: }5 B& H
( L' m0 R: ]. d( [* \, Z, \
                if( nCcount < 0x0100 )
7 [3 [0 F" Y3 y0 B- i! U( I3 U! o3 ~                        pSoundBuf[nCcount++] = (SHORT)output;* E: @9 d. `# i3 a( n
4 K; J) K3 i# B% L: _! x+ \2 F
//                elapsedtime += cycle_rate;
1 b1 M  Z; J; e& e; E                elapsed_time += cycle_rate;
' I$ w  c: L" {  P( u2 w        }
2 D  a/ w" H+ s* U, L: ?& @3 M; T+ Y7 _. A- q! V
#if        15 z* J( z2 U  Y- m
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ i3 p1 j0 ~' Y; X6 T. y2 @                elapsed_time = nes->cpu->GetTotalCycles();
) {, y$ n2 T* M# L0 M5 E: [        }/ W" p1 n  S  V! q* x
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ R' I6 `5 e4 \& I9 c, R9 j
                elapsed_time = nes->cpu->GetTotalCycles();9 j) [- L% i9 k! Q: Q/ R
        }( b1 V' b  B) Q2 M
#else7 E# x/ V$ D8 `4 p
        elapsed_time = nes->cpu->GetTotalCycles();
  o# ?  H2 W: h3 T$ A. Q* j2 d* D#endif" l2 x0 X. o: \! J
}
. X% E' Y  i: H' C1 _
$ [4 w* O2 c( h5 m9 D, @// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
( m7 r6 |0 ?+ X$ k# C7 CINT        APU::GetChannelFrequency( INT no )
# |$ m, K+ s2 X; n' Y' @5 i{
% R4 @8 ?8 O5 z0 K$ t9 B! V        if( !m_bMute[0] ), G  U. @  L/ Z3 w
                return        0;
9 i3 N# g( l! Y9 F2 I9 x
) A- Q7 x7 }  D- J& N        // Internal
3 O* y* C+ e" K$ P# M; Q        if( no < 5 ) {
5 G4 w* ^7 l) v. t' [                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- R; a" s7 G8 |! q( d        }# ]$ `4 I$ a  N$ D3 v
        // VRC6; J; `. \4 e! [# |' Q% m" V
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; y. {1 u) M3 X# Q; A5 M; c6 R  }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
7 Z$ Q1 W# V" F  a3 D        }
+ ^* z+ j2 p# a. o5 @0 F        // FDS5 o9 M: G( t/ P9 ]. |& e5 i$ j
        if( (exsound_select & 0x04) && no == 0x300 ) {7 c  Z- s7 N& r- P8 X9 k5 y. C
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
# W+ {/ ]5 }# \. X& ~+ Z7 ^2 t        }$ \3 ?  B5 t4 T! b$ o) K
        // MMC5
+ S0 |' R. n+ Z' S: z: r        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
8 H  o9 w, R* M8 D. z" q& F/ i                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;! A5 O8 o% @( a( W  i
        }
: p( q) W" P1 @0 c+ o  S/ A2 ~        // N106$ m" y+ I% C, x  w) l
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" C% Q$ k  u9 d1 o; D; O8 f: B. x3 n                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" `. y& l% n9 A/ {: ]        }) e3 M& f: D' b. r
        // FME72 O5 X9 k& w2 Y- i  ^2 l
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {# h" V0 R8 G* k: U
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! c/ [6 r. ~2 `6 b" l. T' E
        }0 \4 e# O* l: _5 J& @/ n! K* @5 f
        // VRC7
, U: k' n- `2 N, p$ X1 I% Y        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
2 c) k" X" s; r4 f                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
9 s9 d( ^% s; k. M4 F3 I! j- J        }0 P' x/ n* C7 M( }, ^
        return        0;
& q3 T2 e( u: S) R- L2 w}
2 \5 [( Y& B, H5 D% l6 m
4 L) ^3 _: d8 p0 f// State Save/Load+ ~+ @: E9 M1 v' r
void        APU::SaveState( LPBYTE p ). c/ ^% E% W2 k! u9 B1 J
{
# \( B4 E0 ^( J+ p  x* o#ifdef        _DEBUG" p5 R3 C% b5 C1 N# h$ e
LPBYTE        pold = p;
7 ]0 t3 A0 z) C9 A( q( Z: _#endif# |- O$ [( @! n' ]0 R3 r+ z' m

3 n4 r) H2 m  Y. s4 m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
0 h8 r5 w3 U2 I4 U+ B        QueueFlush();' s& Q! E0 B4 o
4 K! X& i$ m( t* I- |% s8 C: K
        internal.SaveState( p );( f1 H& {5 w1 ^$ K* C8 Y; W
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 W( i2 s4 z! L
+ o' t) k9 l% S" q! w  g4 K        // VRC6
* O$ v, m$ |8 a2 F. @  M- r        if( exsound_select & 0x01 ) {
, l- N# c1 [4 o& Y1 ?                vrc6.SaveState( p );
8 b+ q4 |1 m; [/ |; e9 k) N                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; k: c* ]1 s! D' {6 q0 x
        }
/ Q' V, }! L$ W  Q( o        // VRC7 (not support)
' ?( _/ t. r8 G( ]- b, `8 o2 j        if( exsound_select & 0x02 ) {
( D5 x$ R4 r1 j8 |6 [                vrc7.SaveState( p );* _( e+ J% x5 l( V9 J$ n
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 ~2 o& s- |5 h; N- h: H- v        }% b. t6 E; n8 f+ M. u( G
        // FDS: f4 D5 \+ N, e1 [- H5 Q  l$ `
        if( exsound_select & 0x04 ) {  x9 T8 i. H+ W8 N
                fds.SaveState( p );
3 e6 p6 H# w5 M6 J9 e5 W6 A1 M                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ M, t& I3 o. ^+ Z) x
        }" D3 ?) J! Y+ I) h  }$ w
        // MMC5
0 ]" M1 ]! P0 {( Q/ h4 `        if( exsound_select & 0x08 ) {* K2 F8 |! H: W4 d
                mmc5.SaveState( p );
4 G) E, C# @2 J% D                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& N1 }( N6 l/ a: M        }+ _4 ]+ G7 I/ }2 M9 |2 W5 m* V% H
        // N1068 E: f  Z! d- J( f9 c
        if( exsound_select & 0x10 ) {
8 W/ L' M# z4 A. B                n106.SaveState( p );6 p! S( D8 [' S& j# T
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" ?5 A& h8 \: [) m" T        }
" M+ W) w0 {- e0 \        // FME78 E) k: |4 h. y
        if( exsound_select & 0x20 ) {/ w% }8 ?0 b" y9 e* [! k
                fme7.SaveState( p );0 K* q: v4 ^+ R) @( d" ~# f8 m
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: |+ d2 I2 [) H$ Z) c        }
8 V' B- b- h. p" R( _8 c3 g
- M& Z! c4 F8 m  n( m. t0 U* u& [#ifdef        _DEBUG9 Y& t! `( a* v6 E; x
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
) `2 t3 c% g7 J0 E2 S#endif& k, n  @* R4 |6 \4 V' U# \
}
9 E* G6 Q0 {4 b+ x+ F  K  K
7 P- y# @. ?$ q' C9 evoid        APU::LoadState( LPBYTE p )0 ]) R) B" a; v, M
{2 O+ h! d2 A* I; \3 K$ s, }# E
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡+ x! R3 z2 c1 y6 X7 K3 M2 V
        QueueClear();( I$ D1 e' a! Z( s! Z5 r
9 u( ]$ B9 ?+ X* y# a, z9 G
        internal.LoadState( p );% V' N( o/ H1 a, y7 d8 M
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; P/ \0 x6 S) H- ^9 t" t8 q: T' a3 o0 I0 d' a2 P: H+ V7 ?
        // VRC6
& v: R, I4 v6 W; `) Z9 X4 x        if( exsound_select & 0x01 ) {
: F& z7 B: [7 T                vrc6.LoadState( p );: y& @: R4 E9 S) o) B+ i* h
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 F; O) {. l1 Q7 R
        }
9 m7 `/ n8 M1 p        // VRC7 (not support)
. x. |) E; T8 l        if( exsound_select & 0x02 ) {
, H0 b1 b0 r$ q5 G* p" y* k                vrc7.LoadState( p );
3 U6 M( n3 i5 U% N$ K                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) ], ^- ?8 d/ p! B! g* |( E        }
8 R5 o/ a# E, {2 h) i% y        // FDS8 K/ d) W6 J( p: e7 s
        if( exsound_select & 0x04 ) {
* E4 y, m" I. w/ m1 [* t! f                fds.LoadState( p );
2 B7 H( u! |3 H7 d& A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 J! ~  n- r* d0 q4 m        }
" M# t' p- t3 h) x# W: m/ ^        // MMC5; E) c6 {2 B& E8 c- F
        if( exsound_select & 0x08 ) {
3 y+ u( N; \1 N) P& M                mmc5.LoadState( p );
: v. x8 p9 `& ~2 t0 [* `) z8 {                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 t" n0 ]& X  G5 J* C+ e
        }
0 ~( W+ R& s* P4 ?/ s        // N106
& f3 B: @  Y! l% H- f3 g, \% n$ X        if( exsound_select & 0x10 ) {( H0 w: x  S) e  R5 m8 w% C
                n106.LoadState( p );
. p: R3 @0 b% ]1 A( |2 I                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& p2 A! u9 o* C" n# h        }
" V" W8 p2 {; ~, v, G9 d        // FME7
: @6 ^* z: h" e( Z* W4 M/ \        if( exsound_select & 0x20 ) {
# D4 v  m1 P, G$ b* ?+ G                fme7.LoadState( p );( @- \7 e9 d& W
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 n8 U# ?8 e" }' v& T
        }
* E* f; T" [. T2 u( [}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, L" E0 G% C) y+ @' C) B" J可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。  J+ ]! r0 Y# P1 {1 O' K5 |
感激不尽~~
+ o1 ]) o6 k3 @* s- p
恩 我對模擬器不是很有研究,
/ M1 f( U4 `- U7 I! s3 x  R雖然要了解源碼內容,可能不是很困難,* W: g7 `9 S4 B/ N' R* ^
不過還是要花時間,個人目前蠻忙碌的。
$ X2 x$ u3 K% Q
1 o3 t0 n5 }0 a, Q- k9 ]9 h9 U給你一個朋友的MSN,你可以跟他討論看看,
  i+ U' P3 u6 z他本身是程式設計師,也對FC模擬器很有興趣。
  n8 u, c0 w; A2 q' |. r$ m/ h# P( ]/ \, @
MSN我就PM到你的信箱了。
0 M5 Q7 F0 X( |& p/ m- a9 E$ x) k( [+ M4 U3 H( D8 I
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 / c0 j6 k  y% z, R  m& [" I
呵…… 谢过团长大人~~
+ S& d2 R& `1 ?5 ^( k) A6 e4 J& Y
. a( W: E9 U: F0 G" @% T/ `
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & L5 g0 g, ?4 d" v
团长的朋友都是神,那团长就是神的boss。
% @. N, s2 Z5 ^
哈 不敢當,我只是個平凡人,
* F. n# K* b0 u  H2 I. e要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙' m2 j: U* W( L* G2 H. J+ l& F; k
ZYH" S1 S& ?. D9 {9 v
QQ:4147343062 b7 h# a" s" `- W" L
Mail:zyh-01@126.com5 Z0 X! F1 d0 L4 l5 r- N

; m% j+ \  s" Z8 j% ^& o# u他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 : h5 [( i4 {* u
再次对团长大人和悠悠哥的无私帮助表示感谢~~
. w4 Q( f3 ]. |: Y9 ~1 ~5 _
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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