EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 y0 d: B; ?! h/ `0 W) G' S楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 `% T6 B7 I7 h$ r
这里有相应的模拟器源码,就当送给大侠了~~
8 ]: M  V5 Z8 G# o" Y  E( k/ Q7 Fhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" T+ k  ^+ n2 C能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) n& u7 F  i# D楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 P4 i. {; d8 n
这里有相应的模拟器源码,就当送给大侠 ...

5 A) x3 \9 S( \# S% D  n; }聲音部分(Audoi Process Unit = APU):( a( b- p( J; @9 S+ g" c
.\NES\APU.cpp8 w8 f4 ~/ q; c7 ^5 L
.\NES\APU.h9 i7 n2 I6 E; @' b: k; r- {
) X' B8 T! [+ [  G. q6 M
5 G; s# U* T; w# v6 B0 _
影像處理部份(Picture Processing Unit = PPU):* J) s6 \5 n% \
.\NES\PPU.cpp
6 k; g. l6 c1 c4 H: @  Z0 j.\NES\PPU.h* d' o2 F7 m8 }; V  d8 ^
1 J& d; _+ Y5 @6 q" q. s
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。3 s0 U' E8 \( j# T8 l
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:4 v7 L8 z) ?" G' c6 B
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
, a% _1 n& g0 d/ `//////////////////////////////////////////////////////////////////////////# N7 I/ [7 I' e1 ]
//                                                                      //; Q2 r5 X6 X) y: \# q3 j- N
//      NES APU core                                                    //- t- e2 k/ k5 h# J
//                                                           Norix      //
* O* z# C7 N# Q; m$ \2 c2 w  f//                                               written     2002/06/27 //2 K" B! V1 n5 f% M
//                                               last modify ----/--/-- //
4 b) u0 K" s+ z9 O. T, W, k//////////////////////////////////////////////////////////////////////////+ g" C  Q& a: A5 I  ?0 t
#include "DebugOut.h"
( v6 ?( T; ^  `' g8 ?9 s" u: c  H#include "App.h"
; K& h' a. L# l- |$ V#include "Config.h": N6 D( v. q: g2 t: u. [

4 b9 B; g$ H  G, q9 f3 @#include "nes.h"
% _! m4 |3 w! m: |+ P#include "mmu.h"
  D, [0 \/ n* b#include "cpu.h"
. z) ?- |+ o$ D6 ^9 i0 G( X/ Z#include "ppu.h"
, H, i# p6 W2 G" |#include "rom.h"
" n5 v3 v4 X% H/ t  C. ~#include "apu.h"$ W' j' r* t4 t  {" Z+ p
  c8 m0 t2 Z$ B+ L9 |  Q* a/ E
// Volume adjust
1 s0 F  p$ @  V# ?// Internal sounds$ H/ h( d4 p3 Q" d. P# T2 h& P8 p8 y
#define        RECTANGLE_VOL        (0x0F0)6 ]( z) ^- I. y7 q4 P3 x, H, y% f4 o, _
#define        TRIANGLE_VOL        (0x130)7 W/ C: E1 P3 [7 [; R# ?2 N; a( e
#define        NOISE_VOL        (0x0C0)
7 e- m7 w7 x) C" s4 O! i#define        DPCM_VOL        (0x0F0)
- s( I, s6 S+ c// Extra sounds
4 Q0 k* j0 ~5 `0 Q# ?7 e( |#define        VRC6_VOL        (0x0F0)
; k0 `$ r* W" {0 Y  r2 i#define        VRC7_VOL        (0x130)* P* r% y  V, U0 O1 E
#define        FDS_VOL                (0x0F0)" n& X3 P/ V" h
#define        MMC5_VOL        (0x0F0)
1 H  Z0 S0 m/ n. `5 l#define        N106_VOL        (0x088)/ \! [/ p- k6 M: U$ C/ p
#define        FME7_VOL        (0x130)
& i, K! j- ]0 R6 Q4 T0 ?
# g9 I# ^- u- h' t4 FAPU::APU( NES* parent )2 E0 x. H5 r2 n/ j1 b: W, Z1 X
{
8 V! H$ V( X! ?9 E        exsound_select = 0;7 p# X7 d3 b1 r# Q. I! `! x

/ U' h5 `- P% O% ^6 Q: N        nes = parent;7 H; A& @7 [3 Z) X
        internal.SetParent( parent );8 R, G+ g4 i$ g# Q6 l' [+ l4 }
& P7 E: X, E6 ^* B5 N" ^3 J
        last_data = last_diff = 0;: C4 u& l: |% M0 s) {" n7 j' u

3 W& E3 n- K* s. d4 [        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );' H( k$ n& m' ~# o: l5 p( R
6 F1 ]6 _) y8 _
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# T" w4 w, @% x/ `' p( c- o) Q        ZEROMEMORY( &queue, sizeof(queue) );
- f3 h9 K' c- m4 @7 I# @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# H- q0 g+ [7 X4 j& A) _. f: \; N9 k* d- d
        for( INT i = 0; i < 16; i++ ) {" b  B. f9 L5 ]8 T% |
                m_bMute = TRUE;
( I! B6 O% G5 s0 x5 i        }7 J+ z9 t1 _8 s4 o. ?. u& Y
}( t5 ~4 O* F+ k4 r+ l0 c: B! p
2 F7 D- X, j9 n0 \9 K
APU::~APU()
* z5 L! M6 c3 V( Y. a! w& S{! s9 K5 p' x% D
}
% P! i* }& ?  X+ x/ C  q  _1 ^4 d% y" \6 l% w$ t+ v5 C
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: k* O6 j: p5 W+ t( U& Q{  \. T7 U* `# `4 a9 P9 f4 y
        queue.data[queue.wrptr].time = writetime;
- b. R0 [3 D( i! [* y& \        queue.data[queue.wrptr].addr = addr;4 [: s- a4 `2 I& U; P
        queue.data[queue.wrptr].data = data;
9 i( \. v+ g+ W" B2 I% \- q5 k8 _        queue.wrptr++;1 G8 O/ h! F" ]. H4 S( _
        queue.wrptr&=QUEUE_LENGTH-1;# C9 r! j" U) [, |0 z- \) b* R
        if( queue.wrptr == queue.rdptr ) {
  l. o4 `9 }1 ?                DEBUGOUT( "queue overflow.\n" );6 J  i; p: z8 P7 r' y. M! ^
        }
: B! u: P% f! }& F* I5 ?}
' R: v5 m3 F; T9 Z3 Q6 p( ~  d! _! t* H8 N
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
0 R4 _2 Q4 V' z4 ^6 K, l{( h. O: W9 f* A/ z
        if( queue.wrptr == queue.rdptr ) {5 Q% o* T" W& O. ~( G9 x8 M
                return        FALSE;5 n# x& B3 D1 q
        }
0 k4 {! t! I1 ]( w) D5 L: i! r        if( queue.data[queue.rdptr].time <= writetime ) {' a$ V: n/ o8 J- C
                ret = queue.data[queue.rdptr];
: W+ M6 l$ C2 D8 m! Y) B                queue.rdptr++;; l, c1 v7 l2 t6 L
                queue.rdptr&=QUEUE_LENGTH-1;
* a: p' g  K8 l" K# [                return        TRUE;- L6 I# F& f& O2 u
        }
$ G5 e6 n7 a4 v3 ^        return        FALSE;
6 d4 h( F: j' V# P- Z}1 n* f) ^% L! }4 R9 J5 `- {) F

8 O5 ]( x& ]; B. ~! s" Z# f5 mvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ E9 m* ^( S2 a7 K, e0 L( r{5 l2 ~8 q! ^& J- G% Y/ s0 \: `$ i
        exqueue.data[exqueue.wrptr].time = writetime;1 Q2 t9 S; y# z) y& c
        exqueue.data[exqueue.wrptr].addr = addr;$ p3 {1 @2 L. W, P) O
        exqueue.data[exqueue.wrptr].data = data;$ O: t3 ?0 k3 B- V( H! S$ Y5 \1 h$ m
        exqueue.wrptr++;
4 C% M6 n5 K- b        exqueue.wrptr&=QUEUE_LENGTH-1;
! i7 |* Z% m( l" g7 m5 Q        if( exqueue.wrptr == exqueue.rdptr ) {
3 n4 u/ [  {3 z& k+ F: v                DEBUGOUT( "exqueue overflow.\n" );+ w2 ?6 [+ K2 {" _3 v0 h
        }
6 [- S: B! n1 D' Y7 f. u/ ]}
. L/ l/ H. y! P0 {
( n$ ?# v* D9 p' QBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )7 H" t  J% r1 P1 Q1 T0 i
{
( r6 m5 R+ J6 G7 F) M$ E$ [/ F        if( exqueue.wrptr == exqueue.rdptr ) {
$ d& G8 b( X  ~, K5 ~& J                return        FALSE;
7 l; \+ m- t4 F; e5 b! m, {9 U& P        }1 n/ N  V& K  A
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
5 P3 n# Q7 j! b" y3 t                ret = exqueue.data[exqueue.rdptr];4 x/ _% e; t" p) R' `3 z0 b
                exqueue.rdptr++;+ `4 W* Z! r7 V! Q) U, |
                exqueue.rdptr&=QUEUE_LENGTH-1;' e- F% o+ d. \7 ?
                return        TRUE;: q; i# z  Q% G, X9 _6 o$ D2 D
        }# U* m2 p" E2 G2 [+ c  |$ E
        return        FALSE;
( F9 I* M* S1 k- @, t! B" n}
/ L8 Q' V* h- M* P- w7 B- m5 ^% @9 a; n- o" o" L7 Q3 O
void        APU::QueueClear()9 Y: }( g" _* }1 G" i, F5 t/ f
{% R7 p( W5 X+ `/ U' L  A
        ZEROMEMORY( &queue, sizeof(queue) );
8 [/ y. k1 ~: [$ L        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; c4 U. U- C6 |0 b}
! l7 p: Q# J9 G* q1 Z7 T0 Y( G" W- l, s  c. |' c
void        APU::QueueFlush()
4 e, h$ J& N% S7 ]; u{# R8 ?' V7 S; H1 s. u' d; |, S7 w
        while( queue.wrptr != queue.rdptr ) {
/ L6 `: n6 p! S$ r9 f0 D5 u                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) a9 Y2 |7 c+ q! M* H0 r2 o
                queue.rdptr++;
) D' Q! O% b' j                queue.rdptr&=QUEUE_LENGTH-1;
- z3 t3 H' e. Q0 e* s0 y0 o+ n# C        }  F5 @9 y: C/ k3 l" l
+ y  \$ Y$ g5 h" F" s3 a
        while( exqueue.wrptr != exqueue.rdptr ) {
' D6 Y  x% G. [& ?# A! }& n                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: U- d, x3 H* ?! \# \
                exqueue.rdptr++;
" G. f8 l# o* h% h3 H+ Q                exqueue.rdptr&=QUEUE_LENGTH-1;7 \" h& d8 ^: D& @
        }+ \+ c& a( C$ o1 G) K' M" [
}
% W' i& |7 L: ?, q, B
. K7 i3 s) k4 J) s7 ]2 T- Q8 |void        APU::SoundSetup()
% u/ u, h, e: T3 v& C& y5 {3 M{
) T3 T* L7 k! g' ^! |* D        FLOAT        fClock = nes->nescfg->CpuClock;3 }9 E" V* ~) v( i- x+ u" z1 Q! x  T
        INT        nRate = (INT)Config.sound.nRate;
- Z! ^, T' k/ h! X4 V: X" L, r        internal.Setup( fClock, nRate );4 G3 j. a; e! j7 G$ P1 h- U
        vrc6.Setup( fClock, nRate );7 d% I( l# X4 F) {
        vrc7.Setup( fClock, nRate );/ T9 ]: K- Q% y4 D
        mmc5.Setup( fClock, nRate );
6 B- R/ w( K4 e( I/ S        fds.Setup ( fClock, nRate );" u2 n- ~. [( r
        n106.Setup( fClock, nRate );
  l( \7 w& p/ q" w) D$ m- _9 g& C        fme7.Setup( fClock, nRate );
( J$ g' d. f$ K7 z7 _}4 c) v- h- Y9 h. w0 `5 A9 l& ]

" e6 `! M3 z7 P' X$ C& n' F- d) K4 Y+ t9 rvoid        APU::Reset()' H8 z. [$ }) \0 j5 ~& |
{; ^) @1 E2 F- e% D6 Z0 Z" `! s3 g
        ZEROMEMORY( &queue, sizeof(queue) );; W+ [0 ?1 b- v2 t% f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 |2 j, Q4 j6 Z! G$ L. ~

0 W: E8 ]* t+ h; Y  s' [        elapsed_time = 0;
# J' a$ F& `" D- d
. ]9 W7 F5 _; s7 u# h        FLOAT        fClock = nes->nescfg->CpuClock;
" ^! V9 Y4 G! d0 y& G# T        INT        nRate = (INT)Config.sound.nRate;) b+ [* \7 S6 t% ]/ [2 r
        internal.Reset( fClock, nRate );/ |* x+ h8 _( j3 u4 i2 K) t. ]
        vrc6.Reset( fClock, nRate );
1 d; [( G) T% w1 k2 W/ |6 V# _2 ^        vrc7.Reset( fClock, nRate );
+ l( B* `. ]' Z( Z- }4 d        mmc5.Reset( fClock, nRate );/ A; v! T$ X5 I6 y1 Q& p
        fds.Reset ( fClock, nRate );7 H; z9 Y) [2 o! O( I. d
        n106.Reset( fClock, nRate );
8 T' T  H1 O% H- s6 @        fme7.Reset( fClock, nRate );
3 ?, ]' m! V8 [0 w6 _5 ]: _, f3 x* t% N8 Y1 {
        SoundSetup();
# @# Q# _( \2 u! e9 M3 H5 d}
# c& B8 b. ]7 L. W: K8 S& o  W! ~; U$ P
void        APU::SelectExSound( BYTE data )
, {9 ~, h2 A6 k7 a1 V" D{
) H4 R- `) J5 Y; K; a8 T8 B/ M        exsound_select = data;& Z1 C) U. e/ h# Q( l
}
: ]: |0 ^7 C- ]5 g$ u
& w2 N! t, p* i- H  y) _BYTE        APU::Read( WORD addr )
" o2 k$ Y- M$ ~{2 _- P7 s/ q& i
        return        internal.SyncRead( addr );$ g, u+ r! v; g) ]5 c. _
}5 u, W; c( ^5 [0 R

3 G+ a5 |4 e5 z' P% Jvoid        APU::Write( WORD addr, BYTE data )5 E% L! S6 n2 H' N" d5 V
{
) l& W0 y: j8 V/ Z% o- E' r  ~        // $4018偼VirtuaNES屌桳億乕僩
' N8 m- |1 h. ?; W        if( addr >= 0x4000 && addr <= 0x401F ) {% C$ ~0 @; P2 _% B
                internal.SyncWrite( addr, data );
& D+ ^" ^( m! }; r                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 o7 `" E! h- C+ c' y# f3 b
        }
3 T( N0 y% t. O6 g8 I$ r3 n- m+ F}
0 S- P9 L, A& K4 S( a3 u5 @2 ?
, V1 d0 V1 c  G* K/ rBYTE        APU::ExRead( WORD addr )
) X7 g( e  b& z0 e{
+ \& e9 Y! G0 h" L7 b2 p1 o- SBYTE        data = 0;: k7 R; n2 }: T7 _/ {7 x" B; J1 @* R
  T9 x0 Y! C  P& H
        if( exsound_select & 0x10 ) {5 U8 ]+ I$ n' [% @# j
                if( addr == 0x4800 ) {
! i: u0 A" S0 B                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 ^5 v6 d+ U; N- k                }1 |3 b3 j. W+ D& @% G' A6 J
        }# m# l6 U8 w- _
        if( exsound_select & 0x04 ) {
) m8 o3 \( k8 Z3 K' x+ y* B                if( addr >= 0x4040 && addr < 0x4100 ) {
& ]0 ^, U. e& h                        data = fds.SyncRead( addr );
% a8 }. a" Q6 v* u                }
+ K: a8 C9 m* `0 k3 t; f2 n& H2 j        }4 ~+ O7 p0 a2 U, e% e
        if( exsound_select & 0x08 ) {1 [  I- _/ @; l' D4 |4 N$ ^: Q/ g
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, F: c; [( w7 A0 `( Q3 m% B                        data = mmc5.SyncRead( addr );
7 Z) W6 q' q  p6 y- j. I! X                }
$ s/ N5 |* H6 U% O' B        }
; {3 }  |4 ~) V3 G) L7 m
6 N# {) ]/ d" i: V2 N$ O3 X3 ^+ W        return        data;( Q* d1 Y8 Q% E6 X  M3 Y) V# A
}7 f- t/ g4 v1 }" U/ [  `
8 s" L/ z! s9 A8 R1 C2 Y( b
void        APU::ExWrite( WORD addr, BYTE data )
" u; C- g- C/ C. @3 k# L* a{
) H; _! v1 E6 T. X6 j; R        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 c1 W9 P5 P/ p% L; M& r: W  x$ R0 n) S1 |
        if( exsound_select & 0x04 ) {: E; D/ }2 M+ q  S' \2 m2 w. v1 T7 h
                if( addr >= 0x4040 && addr < 0x4100 ) {
$ ^- j% z* ~# z6 W! J                        fds.SyncWrite( addr, data );/ v1 v! {; o5 w# l6 A; Z
                }  W# ]) L: U8 {6 m' x6 K% W
        }
% V; i' o6 r' @( ^0 b+ w4 P/ w& \1 d8 B7 Y
        if( exsound_select & 0x08 ) {* E; W8 s& U! R& V; {; W: ]. J5 U
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' y0 B: W  k8 o3 X0 U' l6 Z                        mmc5.SyncWrite( addr, data );- {4 ^- `* v. M0 h: `3 [8 c
                }
0 o- S& w) M" k/ g: N) Z# S9 V        }. I, q# q% s- I6 x3 Z7 F$ K8 p
}
; r( r( \4 C4 [7 Y# ^0 h/ w4 I6 f6 Y; i) w0 q
void        APU::Sync()
/ v( m/ t; s7 l- r. I4 R{
7 ?, U( q2 J( m, ]) h}! e! z8 m) q2 u, t0 e9 m) p- j% o/ b
1 k; r8 O) y) }- H: S4 i1 _' z
void        APU::SyncDPCM( INT cycles )  O- G) X. R( m
{2 D- `0 l0 ]. ?" b, B/ S
        internal.Sync( cycles );
& C6 J: j( P$ S# F
9 N4 e' m( q0 T0 t. d        if( exsound_select & 0x04 ) {6 ?& X3 ~. a2 b; t* G5 |
                fds.Sync( cycles );3 V: I" ], Z) p8 P% I' ~
        }/ x8 A; Y" m# k
        if( exsound_select & 0x08 ) {, k, n7 Q9 d* j# n
                mmc5.Sync( cycles );
/ J5 {. e( y7 _* f" Y! d" Q        }2 e9 ^% l" u  C7 T
}
( C; Z! k8 C; y/ X
4 Z) H+ A8 E, a5 E) ~5 tvoid        APU::WriteProcess( WORD addr, BYTE data )
4 l# ~* A: \* n8 w" M5 y) s! Q{
' m8 q- B+ t/ T, X( Y4 J1 P3 G        // $4018偼VirtuaNES屌桳億乕僩3 ]2 M* G) Z" j3 n9 t) {) A' j
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 [. y1 M4 ?+ s7 O* i, m; |  }# f$ A                internal.Write( addr, data );
2 V0 b, ~4 r, b        }
" v+ Y$ E6 x& b( D7 s( v}: A8 S1 E$ v3 H+ m! q, S' I

0 C2 P3 C9 \* x! Avoid        APU::WriteExProcess( WORD addr, BYTE data )8 u$ P, y# H% }) o, @
{
4 K6 O. S/ u% m2 t        if( exsound_select & 0x01 ) {
0 y4 Y9 j1 b" `" Y# U                vrc6.Write( addr, data );
6 {0 D! W. w7 C        }
0 ]$ w- O, W/ ?3 Y        if( exsound_select & 0x02 ) {
& X6 a' \  G* j" A4 j2 I+ A                vrc7.Write( addr, data );
0 ~6 P, i/ |% t! ~, C" s        }
! l5 G, _8 I2 P: }        if( exsound_select & 0x04 ) {& l3 t6 C$ d' W. }$ z# W% @  f
                fds.Write( addr, data );; ]& p# Z8 d1 t  S8 O- S% I, n
        }3 L& B0 g( d- r4 ~, }4 X
        if( exsound_select & 0x08 ) {( |4 q6 s3 b7 o" [9 `
                mmc5.Write( addr, data );
8 l8 E' J- N- Z4 \8 Q        }8 O6 J, ?$ m8 E0 ^- R7 s1 P+ G
        if( exsound_select & 0x10 ) {( M# P1 @. A6 R# k7 [9 I: B  K
                if( addr == 0x0000 ) {
- j) c! Q- e$ f                        BYTE        dummy = n106.Read( addr );' {& w8 z' W2 |- |4 V# e. q
                } else {
/ b4 C  g3 B: K, g) K* g* G) I                        n106.Write( addr, data );! S6 l2 q0 }0 B' `7 P, g
                }
' Y3 u2 F! b; j5 }6 z) K* F6 p        }( v3 Q# M5 y. @5 X" G. ?  o. a% K
        if( exsound_select & 0x20 ) {0 r& ?2 P' q& E& K0 U& D
                fme7.Write( addr, data );
* p( v. b8 r, ~0 R6 a        }
9 ?$ q# L& h% `* I" l4 J}
) r% u. q+ \% C9 w- C+ g! Z9 D  u
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 ]; u+ Q- D7 T: e. T
{
% X8 S; f2 D4 J6 _7 I. z- eINT        nBits = Config.sound.nBits;
3 {# l) ~5 e- f# @, r9 \2 ADWORD        dwLength = dwSize / (nBits/8);
& L# }$ \+ i: T3 yINT        output;
7 I: I4 |* ?! v% uQUEUEDATA q;
6 t, w2 o, N; y6 c/ F2 PDWORD        writetime;9 A/ n  h5 U+ D

, v2 V/ X/ \1 r4 v- sLPSHORT        pSoundBuf = m_SoundBuffer;) G! {  `  o4 c4 |0 u* c% q
INT        nCcount = 0;
( s. M: }! D2 Z- W" B( U* u. T5 \* G0 o
INT        nFilterType = Config.sound.nFilterType;6 q; l! p/ z" h; u8 f0 a

3 E  H) V$ k! z$ j$ P# X, D: T+ I+ J7 Q        if( !Config.sound.bEnable ) {
6 i" W3 x: F: j* j: X( K! }" L                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# ?" d( [! C. ]4 z, I; A- A                return;8 g# A7 U7 v1 s2 v9 z
        }
6 H4 a. m. e. \. B+ G7 g, T- o# J2 F0 ?  Y! Q
        // Volume setup8 m# O9 F# G9 @; q7 t2 J9 Q
        //  0:Master5 G2 ]8 {9 N+ I0 c6 S: I4 j$ g
        //  1:Rectangle 12 G9 k/ }+ S. n# y' D, N0 l
        //  2:Rectangle 2
7 c2 c1 `0 H' ?- p        //  3:Triangle) f3 D$ I1 e# u$ A4 o9 C
        //  4:Noise2 T( ^' P8 W- Z5 t
        //  5:DPCM
2 P; t9 Z% L+ ?1 v6 R" k        //  6:VRC6! V3 _+ m4 u; D% g$ [* D
        //  7:VRC7& A0 n; B% A, S+ @* H
        //  8:FDS; e+ N: \. u# P' ?! x
        //  9:MMC53 O0 J- G; W0 h
        // 10:N1068 a- \* Q) @; |3 g* Y8 j
        // 11:FME7
6 u: Q) K; [: A0 o        INT        vol[24];
1 z, l: ?; d7 s8 C/ Q4 l$ ]        BOOL*        bMute = m_bMute;' e4 P6 P3 V. s! ~2 e8 k
        SHORT*        nVolume = Config.sound.nVolume;
' Q& q3 [- O9 C( ~  n" ~  g# V, t+ {7 H$ t8 b- u' g0 S6 y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
7 K; [5 h3 E' R/ K/ g5 }! A( O9 ]- X5 O! d6 ?& a
        // Internal
, L! Z$ h2 Y: q% M8 p        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
& ?% s. y2 A- |6 n1 R& U9 c& Z        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
( z7 z. Q& C. {  S  G0 W' M/ r        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
) C( m9 E0 l2 i9 F' I        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' |1 v; h+ ]5 u4 N$ n4 t* G) u        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
1 d$ @' L+ {4 Z% F, ]# k' A
8 C) z$ e$ h" {* H        // VRC6
# B+ G& j, f5 d6 g# m: w& w        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ W) Z1 X8 s0 Y1 P; o* T3 z& }9 L        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. K0 W" u8 I5 F0 }8 j; P) i        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' p+ ~. M3 [+ V6 b
8 q6 O9 d% C! U( U( T5 r        // VRC7
0 @" ^8 r5 n& ]. C1 C6 T        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;3 s/ w4 C; n7 k
/ E& y* b9 |5 E) w# }0 u8 R
        // FDS
9 P3 j. }, q$ k( n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
2 Y) w+ p, @- |; `9 @
6 D/ o# b, h$ r: A1 @        // MMC5, V9 n$ ^, T2 R7 k
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 T# u9 U  Y) K; R% y5 ~* D
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; \7 [" W  \' `% f+ B* \  q$ }( p        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- `$ n2 X9 t1 ]% D
* {* o, L8 l7 ^6 J9 q% ?5 @0 O0 ^        // N106
7 ^" t$ y9 @/ Z4 @8 I" p5 p" n5 {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 s- {, v9 |8 C) N* `% L* ?* `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! a5 S# t) G; b% K  F
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ K; g* h; ?" Y' j        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 x6 `! \/ o+ `7 m
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) Z" Z; B& d$ ^$ `
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 P7 d$ }& D0 M! v5 o
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 ?4 _& k* v+ l4 s8 r
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 j" E5 M9 q$ v& o7 f7 V, g  U  t9 t
        // FME78 E! [) z5 B, E2 a  }7 F+ k/ P
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ q# i0 T$ T  E  X7 C- `        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 ~2 F8 A: }4 E; a. p! y+ J
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& z4 k  a/ i( Y" K# Z+ R
# c2 B4 z. w4 j//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;* s2 s. E; E) l2 Q
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
: u0 [( \6 x5 u
  p. d8 M0 K  w5 P& C/ S        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- K! \7 X- I3 g0 m5 b" e- I        if( elapsed_time > nes->cpu->GetTotalCycles() ) {- n& U5 D/ ^. z) b1 t6 j3 k
                QueueFlush();7 I( K( w7 }+ k+ u% H! h$ S1 V
        }
8 t# a3 U" P$ V6 m/ S7 W  b  ^  l2 v" U1 I" G) ^6 i3 [; Z% y7 |! j
        while( dwLength-- ) {& I" i# @3 @7 B2 ]% ^8 i
                writetime = (DWORD)elapsed_time;
1 c/ L; V6 b" \9 N8 A5 q3 ]7 c6 H3 i  T; F8 c9 Q& ~6 [
                while( GetQueue( writetime, q ) ) {
: u$ s$ |' A! Z0 u& ~: U6 p: T- u% T                        WriteProcess( q.addr, q.data );; ?  W4 e4 @, ]; \$ a
                }- B' Y2 D* _1 c: U
! g/ F* v, K4 J, X% T2 r$ g8 b
                while( GetExQueue( writetime, q ) ) {2 ~; h, ~/ k" \( Y& f( J
                        WriteExProcess( q.addr, q.data );+ {6 T9 G0 p5 f" s! i. C
                }
/ x& h9 @0 g5 r. J$ J- o5 f4 v: h* `5 L! D2 a- v% N: L$ I
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
0 R" z& X; y1 ?# D  x! [. n                output = 0;
& m. `' R# z( x7 c, z                output += internal.Process( 0 )*vol[0];
+ l+ p7 [% F" _, _5 F                output += internal.Process( 1 )*vol[1];
2 \+ d! O; C- H, j) a, R( L4 w1 w# m# B                output += internal.Process( 2 )*vol[2];8 V4 a* y% q& L( P
                output += internal.Process( 3 )*vol[3];
3 Z! O6 `! w2 Q; w$ Z0 r                output += internal.Process( 4 )*vol[4];0 M" d" x2 u* I5 Y; Z& t7 R  }

2 t- H. N( U. n% x7 ]+ _+ ?                if( exsound_select & 0x01 ) {- r- C) A( S( ?4 t( r# Y1 s8 E! E
                        output += vrc6.Process( 0 )*vol[5];
+ t  C1 H$ o# |( G# D* e% f) u8 k                        output += vrc6.Process( 1 )*vol[6];2 w% |8 \2 |& |0 W: |$ A; k
                        output += vrc6.Process( 2 )*vol[7];
/ T* [1 Z& P& `" v/ p/ X                }& }. Y! M4 y/ s! K
                if( exsound_select & 0x02 ) {
" P! K3 P0 c# a                        output += vrc7.Process( 0 )*vol[8];
1 _. `/ t  W9 G  O' `                }( {, [. ?; X% ]4 M5 R$ X
                if( exsound_select & 0x04 ) {
0 L, U0 V/ F, L' [- L                        output += fds.Process( 0 )*vol[9];2 d9 Z% M0 S4 y5 a8 g7 r6 [
                }
2 c8 X7 t& m" `7 Z$ @                if( exsound_select & 0x08 ) {' \. y/ {" Q# ]5 `# R
                        output += mmc5.Process( 0 )*vol[10];* _2 j: _: e+ X! S- I
                        output += mmc5.Process( 1 )*vol[11];; ]8 [4 P3 t& e6 L/ k2 ~* }
                        output += mmc5.Process( 2 )*vol[12];
* I% k0 t, z4 q9 G                }
/ z- d/ ^& _& R& `* M( b1 p                if( exsound_select & 0x10 ) {, A# v+ k$ Z( Q, y: H' r
                        output += n106.Process( 0 )*vol[13];2 b; p( o7 y2 X+ D: x
                        output += n106.Process( 1 )*vol[14];
' k- L8 b/ Q6 q( m                        output += n106.Process( 2 )*vol[15];  W! a1 P! E5 G) ?6 w6 J- K
                        output += n106.Process( 3 )*vol[16];
' R& G# _! y4 f: U9 J: q                        output += n106.Process( 4 )*vol[17];
3 Z- Y1 A2 T" ]! O) K& J/ ?, e                        output += n106.Process( 5 )*vol[18];
( H: w$ F  L  I8 b, v3 b: A                        output += n106.Process( 6 )*vol[19];" Q; u4 |# F1 L. H; H  Y
                        output += n106.Process( 7 )*vol[20];- W, C) @3 j+ E! h
                }
7 |* P8 M/ d/ D3 Z' Y, |& N# f% c* w                if( exsound_select & 0x20 ) {; X/ D8 q" p2 E9 v5 o; m  h
                        fme7.Process( 3 );        // Envelope & Noise0 V. {0 c3 b% ?9 c/ ?  v+ i( o# {: H
                        output += fme7.Process( 0 )*vol[21];9 ], r$ t. H0 o9 o, t  r1 p  Z& Y
                        output += fme7.Process( 1 )*vol[22];
( e* F& n8 A  d                        output += fme7.Process( 2 )*vol[23];
4 @+ x1 ?7 u% D8 x5 z                }
( S7 i" x0 F- I* X  _  _# q; p( T" R' k0 `8 T' ?  Q
                output >>= 8;- H. x& a5 r$ S2 I

# L/ c; O7 y& X+ M% i                if( nFilterType == 1 ) {
5 g0 W' P* H! |5 i+ y* Q                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
6 Z9 \5 w. {/ d; K& ^0 k                        output = (lowpass_filter[0]+output)/2;1 q! q  `. M- C5 X1 {% E: l4 }
                        lowpass_filter[0] = output;
: B1 @9 E2 Q4 v& z2 r                } else if( nFilterType == 2 ) {
6 z: ]4 j, x1 t, _- v4 Y6 q                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 \- t( t" {" p3 F" _                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: f0 I  B! Y; E5 }                        lowpass_filter[1] = lowpass_filter[0];
) e1 F- W/ r3 d: _+ G. p( X                        lowpass_filter[0] = output;( W6 J6 E3 R( q4 Z- i1 M& b
                } else if( nFilterType == 3 ) {
& ?% n3 \2 W: U- `) T5 x0 {                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)8 y4 r( @; b" M
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
1 C. x1 [( o2 O; L+ n( Y- P                        lowpass_filter[2] = lowpass_filter[1];$ j5 e  }, A0 |! x  d! ?. D3 J
                        lowpass_filter[1] = lowpass_filter[0];
- L0 j% ]" m6 L/ h7 Q  r. l5 b- O                        lowpass_filter[0] = output;
- N' u5 i& q" _6 W: ]% s                } else if( nFilterType == 4 ) {4 V/ c7 \' c. p  a
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
( X( O5 a! g0 x                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 X2 [% R0 d& `5 O) j) a2 t
                        lowpass_filter[1] = lowpass_filter[0];; `+ }7 E$ m6 Y
                        lowpass_filter[0] = output;
" @9 J6 v1 C2 m! M7 V" t                }; x6 A1 o8 b6 m

$ e$ r! w, X* I" E5 U" A#if        0. P2 _7 k) ~/ H+ O" i
                // DC惉暘偺僇僢僩* p$ K! k4 t' o3 d5 h0 q
                {
) H2 P, u& i2 l9 |* W' V                static double ave = 0.0, max=0.0, min=0.0;
% T/ a  p) v4 m                double delta;
0 z( O9 {: w9 U, h5 ?/ ?$ k                delta = (max-min)/32768.0;9 s0 s: q: |7 Q/ a
                max -= delta;: M, J* ]/ O# v. k) {+ `
                min += delta;! G( L  h/ P8 L; }1 }/ B/ v
                if( output > max ) max = output;# q2 ], Q7 \; G3 ^# h. t8 u
                if( output < min ) min = output;
* w6 x6 F  ]# e$ N& l( q; {) p                ave -= ave/1024.0;% G, j, ?; r1 `2 N+ h
                ave += (max+min)/2048.0;
1 B" N: u9 u" d$ n* r                output -= (INT)ave;
4 k+ e2 O3 P  y; H2 J5 }0 \* V7 X                }
% {" m0 u3 Q0 D% j#endif
# H+ t/ P- v( B#if        1, l  {# t. w( {% d; f) X
                // DC惉暘偺僇僢僩(HPF TEST)8 P6 m5 [! @* j+ @
                {$ S7 J0 ^4 O5 u% W- P  [
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% D  x8 O+ L7 X$ Y4 D: @
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  L: w' D5 Q9 N* e                double        cutoff = cutofftemp/(double)Config.sound.nRate;
( T0 Y& [/ f0 @3 z# j: S& h                static        double        tmp = 0.0;
/ e$ U% M$ g' X! @0 m* I/ a                double        in, out;
: {; {" j. d; T+ @; v
8 n/ |& g1 k  _                in = (double)output;
4 M' o* F* f6 a  U% h4 {! P9 G: Z( r: H                out = (in - tmp);' i2 ~7 v  d; y3 f' o3 C' U
                tmp = tmp + cutoff * out;
" s, S9 j/ e3 b9 a
& y( e3 Y% a+ l* ~                output = (INT)out;
, r# n! L3 r  ]+ Y6 W                }
, A3 k+ W7 L0 ~5 Y#endif/ x* X+ @4 e+ B6 l  V! U
#if        0
+ r! L7 h2 ~5 {( M0 f: z                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 q# ?! ]: _  }& }. A+ Q, l
                {% `9 _5 N  H1 T& o
                INT        diff = abs(output-last_data);
) d2 B2 i4 v3 g                if( diff > 0x4000 ) {( |2 }# |2 ^+ K/ ?" x+ C; s
                        output /= 4;
' J/ @' O2 ]7 _6 Z4 O! T8 b                } else ' T6 ^/ J" M4 Z3 Y7 l2 [8 ^
                if( diff > 0x3000 ) {) o' @% m3 `4 m' S9 \
                        output /= 3;
- K" X' {! v' r) f* `7 V                } else7 X6 H% x  k1 z) c2 k- A0 u
                if( diff > 0x2000 ) {0 s. H+ L; _+ b# l
                        output /= 2;
3 V) J: f4 G5 c/ O                }
' V$ T& M% R$ ^- {+ z                last_data = output;$ J9 c; A2 \* A7 w1 u$ }8 ?& v, K
                }
" K' C+ J; }, X#endif
1 d# T4 J7 ?9 R' _  f0 \" L9 ]                // Limit
+ _# q! U  S% h                if( output > 0x7FFF ) {4 w6 t! l$ J$ |# N+ b8 M
                        output = 0x7FFF;* z. s# z/ K0 |- X- a9 k
                } else if( output < -0x8000 ) {
6 E, e! j4 W$ A: Z% g% _                        output = -0x8000;1 _) w2 o% l* U/ [; K5 o
                }2 S" w' A' K" n

! Q5 L! J0 S( ^+ C                if( nBits != 8 ) {
# X0 S# V/ |0 J& R* |5 {. c" h                        *(SHORT*)lpBuffer = (SHORT)output;5 m  w2 E  }7 x' ^7 b: H7 `, g
                        lpBuffer += sizeof(SHORT);- J- ~: |) o; J9 z5 {/ Y* N2 e5 j( m
                } else {
; @) f) S0 [* e% Y0 |4 t                        *lpBuffer++ = (output>>8)^0x80;* K1 `7 e  w" Y) j  E; u, {: G
                }
6 [' \" M# |/ {1 f( h6 S7 L: C8 d+ d3 C9 p* ~' h1 {
                if( nCcount < 0x0100 )
: o) B! L9 E9 L, E6 [* j                        pSoundBuf[nCcount++] = (SHORT)output;
2 u2 o* E. @- D8 X! F8 L' t; D- o. D" f$ k' m5 z2 C! {/ M- T) N2 |
//                elapsedtime += cycle_rate;
4 G) C7 k  }& G. H. R  c/ H1 b' t                elapsed_time += cycle_rate;
+ O: B, J; D( G% z* I        }
$ n" D( z% q0 y8 Z
/ ]1 P* r! L1 N4 m#if        1
# t% S$ {2 s5 K5 d        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* ?. `, a0 f+ k& z& E                elapsed_time = nes->cpu->GetTotalCycles();8 O, x) A1 N* h* Z
        }# _# V+ ~- q) B4 z$ A% B
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {9 Q" h) R5 \( l& e
                elapsed_time = nes->cpu->GetTotalCycles();6 m  z+ b, A: a. J1 O5 a& E/ |
        }
7 Z1 n0 z. n! L$ H' q# O. Z% V#else
$ |2 }) o2 |& X. Y- I) m; ^3 \        elapsed_time = nes->cpu->GetTotalCycles();4 w. W  F; C% ~9 c% a6 q
#endif
' T0 k5 w9 J: H}; K  C+ K4 x) [$ m
& r$ z( s) \1 D2 Q% [) v
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡). O4 ^+ [2 I% k7 l' V6 e, u
INT        APU::GetChannelFrequency( INT no ), X% z  O8 o/ K
{
8 P) |8 h/ }/ l8 u) B( n1 w        if( !m_bMute[0] )/ n5 \- L5 Z) A" W, R7 ^. o) N
                return        0;$ r: t' E3 q+ F1 v5 h

" |4 r" A5 h) c* f+ y  [; r1 l        // Internal$ s4 ?: s6 u- c1 e9 x( r2 |" o$ W
        if( no < 5 ) {
9 n. z& P! r# b/ O. n" e                return        m_bMute[no+1]?internal.GetFreq( no ):0;: s( j# @4 s. ~& O9 y4 P
        }
" Z# v6 d, ?! I9 M' k- m3 ?0 @! _        // VRC60 Q' J' u, S; S, D% z
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 J, x2 h0 f" A+ k4 R# Q                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;& }, g& d5 @* _. k6 [3 p/ d
        }8 w7 z8 ^& [4 A8 `) @9 X. q
        // FDS
. u$ x) \* M5 k) z        if( (exsound_select & 0x04) && no == 0x300 ) {- Y1 h6 s) t* p( q2 \% c! [# e
                return        m_bMute[6]?fds.GetFreq( 0 ):0;* A. H" @4 G+ E+ y7 x9 \9 D* R
        }
* w) D! M8 y9 w        // MMC5
2 T* r2 ?- j4 P, E        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 m( _" b1 h9 P5 `# z* f, `
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
1 [8 N; O" `* S/ h9 G: v. H, _        }
1 P7 C( K- D/ S' Q5 R8 t        // N106
: L3 D5 c+ p# G9 e: C$ g$ w" Z        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" o2 W9 t5 y! h+ k" k8 d$ H9 \- Z: g8 [9 n                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;* G* `, i# h& Q' e, \7 c  ~
        }
. P& v  @8 z- b. c        // FME7* ?( H5 q0 c3 k# [
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
- p0 J: p2 m3 g; ~9 f3 @                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;9 H0 v% `8 \1 r
        }
4 h7 ]) Z0 l* {. u1 ^4 C$ Y        // VRC7
9 g7 B# [! d5 t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ q; _2 |, o3 ]6 n6 l" z                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
, H6 ~$ H1 Q5 U* J/ T1 r        }' C- z. b: g  D" \) [* F
        return        0;( h$ `7 X" }8 |
}5 D, R  i7 w+ ^) }0 K* e% x

& [% J! P8 y( F- b9 |" W& N- a// State Save/Load! b/ h, i" O" S: t7 z
void        APU::SaveState( LPBYTE p )$ U$ C- S' I- l0 o8 t
{) i4 ^- t  M& U
#ifdef        _DEBUG0 t. S3 G& |8 B- M
LPBYTE        pold = p;! ^9 t( H; c+ W" q
#endif7 z8 C- B; x, c# G

7 u% N' G' ^4 t! K! g        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞7 @0 }( y) ?% y5 K" ?& }% f
        QueueFlush();( E$ z$ y7 _5 N. |) C
# D; w+ ?( h8 u! N) |
        internal.SaveState( p );
" Y( t6 T6 [; O' r' G        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 I( p! z) }4 t9 v( }% W$ E3 h
% M& Q# f) u  b" S; a& C- L        // VRC6
7 ^: {3 s# i, N" M        if( exsound_select & 0x01 ) {# F4 e5 M' n0 u" X7 o; H
                vrc6.SaveState( p );* e& i( C. H. Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: K( m2 H1 f/ v2 p% ?4 U
        }, a3 V# H' p& q8 k% p
        // VRC7 (not support)
  U+ q% b" {/ O3 t4 ?4 U        if( exsound_select & 0x02 ) {
( \8 m7 p. F. d) C/ d  M                vrc7.SaveState( p );6 n. u' ?0 L5 |) h& Y3 p# K
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ x  f) i+ X  o' B7 c$ R! ^        }
- a9 G0 I8 R0 z        // FDS
2 u2 l/ w& z; l; F        if( exsound_select & 0x04 ) {3 S2 ]  U7 b7 n; ?& m4 i9 }
                fds.SaveState( p );/ k3 `# k' o4 A4 h# W
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
: J# S& g( W3 o7 t        }9 e/ N$ t5 o& u7 V
        // MMC5
4 W$ |1 M$ \4 K        if( exsound_select & 0x08 ) {
* F6 ]% k) u' Y6 q0 L/ ^2 k( |                mmc5.SaveState( p );/ D! a4 C  T3 S# F5 Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding8 {, {7 E- d& g+ B' X  R
        }
, L0 |' q: t3 h2 G- G! l7 r( t; h        // N106* _. n0 _. u2 W" T2 N9 o
        if( exsound_select & 0x10 ) {# ~3 @4 n) o: J' _, c# Q7 z0 g
                n106.SaveState( p );! J$ u, `- L/ H
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" k2 ]. L, g1 i2 r" }( {8 Q8 B        }
; F0 h: V0 P* Z( K  Y1 Y: k* m        // FME7) z7 e/ m4 d7 I+ o$ F
        if( exsound_select & 0x20 ) {
% A0 c% R5 ^. ~& k                fme7.SaveState( p );
& j+ v+ l9 a" p; L% g                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 ^0 c8 c' U$ w: q3 I/ ~* c; ?
        }
1 _. o& P2 [% w% [
- g5 b$ t$ }2 R8 y0 p( |#ifdef        _DEBUG
3 K) i( m6 A0 u$ E$ T0 XDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ d' J5 \% w) Y#endif
; e: C7 u* N9 L! }) \7 y}
! M4 ^$ f- L0 h9 d6 s9 }; Z
& o# q- m' |& `0 f8 N7 Vvoid        APU::LoadState( LPBYTE p )) [& i& `# Z7 I* i: b: F4 U. [, [2 t
{! Z- o# C" U- v) R/ b
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! F7 X# l% E  S( J" e; I+ V' T        QueueClear();
- n' o& }" L8 z$ u+ H, J  n# U# H& O8 [
        internal.LoadState( p );
& P( o4 V( l4 n9 @' X: _: ?. m" C2 M0 Z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( B# o0 ?7 T1 }3 f6 i8 }/ }
  N. W- W: h5 X5 a. U, q8 _* Y1 W        // VRC6# A: d/ k  L( \. u# b( B! n
        if( exsound_select & 0x01 ) {+ W) |3 l. I6 Y: ]$ V# p! C9 J& `
                vrc6.LoadState( p );4 K1 `0 S. N- X! C
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 T$ ^! F- E' H0 M& Z9 l        }5 N( h; T+ m" a7 N  k( O8 f* ]! H
        // VRC7 (not support)
; x7 `/ Z* t! x9 T8 W        if( exsound_select & 0x02 ) {) i  g: T- \. q. r( s$ W
                vrc7.LoadState( p );
: k9 c4 \3 a" L6 P                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; K) D! Z0 ~3 @% J        }0 x, u$ K' N: O
        // FDS" v) D3 @, ~4 n! P. Y# |7 a- e
        if( exsound_select & 0x04 ) {
1 E$ K9 U' \* u3 _% a4 _* c                fds.LoadState( p );
  J' s. z$ C  B& ]                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- N$ p6 L- k' C; V7 M
        }5 C8 V9 d9 o  a) f
        // MMC57 `" O6 R3 M3 f6 {1 A2 T
        if( exsound_select & 0x08 ) {
* E% R, z4 o1 z& ]/ a                mmc5.LoadState( p );
6 d9 |* C) I( |+ p                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 U6 z, ]6 q+ f        }
1 r% s6 q, K! Y) B5 P; n! g        // N106
- ~% b" C8 A) l4 ^5 W/ D        if( exsound_select & 0x10 ) {' s* d0 M( M0 F! `% F. F1 x7 `  A
                n106.LoadState( p );
% Q" Q+ v; A# [6 \                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 d  p6 Q% y0 r
        }  }* M! t6 E6 |* q2 ^
        // FME7
1 \. T5 e7 p' Y8 x* _/ c/ G        if( exsound_select & 0x20 ) {( q4 ]. d0 y6 C) Q
                fme7.LoadState( p );
& y; i' p2 D3 _% Y0 ]                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* k" z8 y+ E) k& q# D; R0 J/ r
        }2 j; S% Y3 X$ ~/ ]* j
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ' D2 B( W% P( m% I. q& w0 \
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
+ q) G) L. ]& n0 o: o7 G' s感激不尽~~
& v! C0 b" l$ {1 K3 s: N! D3 ]
恩 我對模擬器不是很有研究,3 N, Q8 @0 K! Q& {9 Z
雖然要了解源碼內容,可能不是很困難,. ^! k2 G2 k: P( @- i0 n& ?9 g
不過還是要花時間,個人目前蠻忙碌的。& p: W& e! _; t/ u! t$ x
* z3 {( N- G$ t' N' V
給你一個朋友的MSN,你可以跟他討論看看,0 T" F+ D2 x6 c
他本身是程式設計師,也對FC模擬器很有興趣。
5 {; a3 P  r& a' z( c) t, Q6 s
/ q" t9 T# g' r6 C, H6 w4 l$ U* GMSN我就PM到你的信箱了。8 i& _$ A" p" u7 ^% t/ y8 {

( p& I- k8 }+ T! p. F希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
% G  X% o) r. P) n1 U呵…… 谢过团长大人~~

' _  ~( u! _. [, J
4 c& H* _  Z! G) h  Z) q哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
& n. `1 C4 l2 M0 N# ?% y0 Z6 u5 g团长的朋友都是神,那团长就是神的boss。
% e0 L! l2 }) X7 g+ ~5 p6 G
哈 不敢當,我只是個平凡人,
4 J5 @9 I" K  q* K3 a/ F/ ~要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙8 z; B9 x& ]9 j0 D# I
ZYH3 l* N  e9 h$ ^6 Y
QQ:414734306' [# O  p8 g: X
Mail:zyh-01@126.com
* X# _( E5 A! H) D
- O# y+ j/ F. y他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ O: v3 p8 B$ v) R0 e# K2 \( e; D$ _再次对团长大人和悠悠哥的无私帮助表示感谢~~
( j5 T4 D- \% V9 M
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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