EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" s, a$ n, Y, s$ j
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 C2 U/ N( z3 f这里有相应的模拟器源码,就当送给大侠了~~
$ ~+ k; T2 c: E; s' x: w  e4 ?7 ]http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
. m8 r; t0 u+ T9 x. o/ [能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 y: i4 e/ x1 s1 S$ l
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
4 L1 |  B2 a. J5 [& A# V这里有相应的模拟器源码,就当送给大侠 ...
" a9 j. n+ W5 J# a6 [3 F  G+ s/ P" b. M
聲音部分(Audoi Process Unit = APU):. p$ \2 a( S: V
.\NES\APU.cpp$ p! v2 k; h# E6 g
.\NES\APU.h
) y2 b, {" }0 ]- j+ t
5 R: ~7 a/ m6 _3 Z7 I  m' X1 c2 v- S- ~# O  `' S' S
影像處理部份(Picture Processing Unit = PPU):
" c: d, A2 I+ T2 @& ^! F5 [3 }.\NES\PPU.cpp
0 h9 Z/ s" X8 G& a# [. h.\NES\PPU.h
, Y+ g1 r2 D# F+ F5 E% R" @: u" j5 L7 e
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。& |. Q4 k) j4 b: H' ]9 m
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:8 E  O# _+ M2 h! e8 x% n* _* U
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% H! a  R& w4 V! U# B2 E//////////////////////////////////////////////////////////////////////////
( d. @0 V- Z+ a& U//                                                                      //  ^! `* {4 V) q  M
//      NES APU core                                                    //4 `- W/ X3 J$ f6 @, z/ u8 P1 r  M" {
//                                                           Norix      //" Z: x. A8 Q! g# F: {  O
//                                               written     2002/06/27 //
1 a& Z! G7 {5 |6 _( z//                                               last modify ----/--/-- //9 ~$ c8 W1 t+ C8 T, Q# `
//////////////////////////////////////////////////////////////////////////
: |$ ]& f) m' k1 \$ O# u! P#include "DebugOut.h"
% a. ?: V9 J& L: i% `- a, b( j9 g# ~#include "App.h"
) n( `: k. \3 n# r7 T: `#include "Config.h"9 c+ h' I6 i; q  D

4 V5 x$ x3 v& i: N6 P  e; Y+ n5 C#include "nes.h"
. J- H. O9 g1 ^' M5 M. B  ?#include "mmu.h"
, ?& B. J7 i* e, J9 U: s" k, ]#include "cpu.h"
% t2 B# H. |" O. W#include "ppu.h"5 g: p& ~6 U1 @: V: s$ n) n
#include "rom.h"
8 q2 x+ M# K! M( w0 y: g" v#include "apu.h"
: _9 H' W/ K0 S4 y4 K
0 K3 W& o+ W& V% T6 x. x// Volume adjust$ H$ _7 m+ ?  t' e
// Internal sounds
) \( ~% k$ d" t$ q; |  d#define        RECTANGLE_VOL        (0x0F0)3 H8 V$ ]# ~( @+ i, [) F2 k$ W+ l
#define        TRIANGLE_VOL        (0x130)+ z6 k1 a- \& ~; {4 ?& t" V
#define        NOISE_VOL        (0x0C0)
% r2 n1 ^- M6 m: c#define        DPCM_VOL        (0x0F0)
. h# B+ `. J6 f/ ?/ `+ `% F7 W// Extra sounds6 j* ^7 D/ H# \
#define        VRC6_VOL        (0x0F0)9 ^  G& d; P" R2 S
#define        VRC7_VOL        (0x130)$ t) P3 l# ^! j& D/ B: l. {
#define        FDS_VOL                (0x0F0)6 O- |# z, N0 {& W- ]& [/ p
#define        MMC5_VOL        (0x0F0)% I& {9 M0 H8 Z& W' C2 R
#define        N106_VOL        (0x088)" w- ~# X' a/ [) X1 X4 B
#define        FME7_VOL        (0x130)5 L) C8 Q9 _, s! t# d

) w7 r& c" ~6 lAPU::APU( NES* parent )& T' G: B9 y; z9 f( a- q, k
{( s8 T% ^0 l+ k* N& l% r* w* n
        exsound_select = 0;& u* }/ H+ U9 s9 s4 X
6 Y- h" H" X2 p. K* y. N
        nes = parent;
5 J3 }( X) |# h' \        internal.SetParent( parent );
# V* s% X/ N* y  s7 \3 Y7 ]/ p- \. k
/ r, Q1 x+ n. \5 \, H; X( h        last_data = last_diff = 0;* k1 x  ]! O3 m* \
% u, T/ g" i4 A6 h0 o
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
0 a- `! A# }) @, a
7 m  c4 J. E+ g5 n6 b/ v1 o7 u) T        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );& ^$ C! r: U! P; I2 r2 i
        ZEROMEMORY( &queue, sizeof(queue) );
# a# z- z3 |* E4 p, `- }5 E/ `        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 h' X( {9 B( J) x+ K) q4 Y" x

/ f) Q$ I" ?  d' h! ^        for( INT i = 0; i < 16; i++ ) {
! {6 K% g! s5 X/ a! T3 N1 n                m_bMute = TRUE;
5 k) x/ o; [* i        }
6 F7 n+ p3 Q1 M6 j8 u$ t. H}
' t3 O# }9 Z0 ~: E* {; L. e- H9 t2 \% ~" i; L6 b9 ~
APU::~APU()% C( H) U  [) ?, b- j) u0 t! u
{
( B: k- E  |/ g9 B3 i* c}
- }7 z( Y4 d# c) R( m4 d6 x
3 q9 M" g: X: F  v8 V! J" A1 evoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
7 X5 ^& y7 ~( q{
7 J* T8 x) b+ c* H; X3 X        queue.data[queue.wrptr].time = writetime;
' _  R9 |9 ~7 {) X7 E1 H        queue.data[queue.wrptr].addr = addr;
7 [( p8 `- F7 @0 A# r" t3 ]        queue.data[queue.wrptr].data = data;
/ ^5 \0 P* B9 z$ t8 g: ]( Z9 U; G        queue.wrptr++;7 Y% Z' x  s4 ^7 S( f  E3 V0 V
        queue.wrptr&=QUEUE_LENGTH-1;
0 Q: ^( Q. V2 ~: s2 F- F/ ?        if( queue.wrptr == queue.rdptr ) {
1 v7 B; _  Q, M5 I( A7 F                DEBUGOUT( "queue overflow.\n" );5 g) Y: @1 }  J
        }* X& ^; `6 A# V4 q# V0 a; B5 c2 J
}
, ^+ k% u) d% E* \0 B0 e" A. D6 l; l6 `
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
4 {# D+ ^. K& Q: l8 G{
6 e3 _7 g+ q6 `  c1 n        if( queue.wrptr == queue.rdptr ) {" K* @8 R# Z2 s: ]' G$ C
                return        FALSE;
$ j* p8 k2 }( r( P! I7 z7 P7 l7 _* W8 I        }/ R$ `- t8 \# Y5 `4 t1 A
        if( queue.data[queue.rdptr].time <= writetime ) {4 n& L1 [/ z1 m" ^, n
                ret = queue.data[queue.rdptr];/ S# N2 E! T0 D* g
                queue.rdptr++;
+ r! z6 H' o! Z  m$ v6 j: ^) ?' z                queue.rdptr&=QUEUE_LENGTH-1;
. [5 J# Y. N7 T                return        TRUE;9 `9 I; K% l8 ~# v9 |+ V
        }
3 ?3 D' _+ e5 n8 ~+ \        return        FALSE;. O9 l. B) N3 R
}5 e5 ^" u7 S* P- ?5 [4 p

& S1 F  o+ A4 i+ H) A0 \void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
& h) J3 h: A% z- W{
- j. K' q4 Y9 X/ ]        exqueue.data[exqueue.wrptr].time = writetime;
3 L8 k  L; m% l9 s' c( ~# W        exqueue.data[exqueue.wrptr].addr = addr;
6 w' t, t. l7 K# n+ T        exqueue.data[exqueue.wrptr].data = data;$ ?9 |7 ~# W3 m# f
        exqueue.wrptr++;0 t5 p+ Q3 Y8 V4 I7 L
        exqueue.wrptr&=QUEUE_LENGTH-1;9 X+ Y8 y5 ]. u! l  E
        if( exqueue.wrptr == exqueue.rdptr ) {5 Z% G. v6 y) h) _$ A
                DEBUGOUT( "exqueue overflow.\n" );
6 L6 d/ L+ C0 @( `6 h$ o        }* E' g# g9 |% A" @( M8 _
}
$ p) Y" C8 r9 ]6 W5 I
! y3 |2 P/ I9 x# X: G' \BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 u8 }# b4 @8 [{
( |9 J4 o  [' w  c: ?. Z        if( exqueue.wrptr == exqueue.rdptr ) {) p$ C6 y  S4 I$ O8 c- _6 ^3 J
                return        FALSE;7 Y0 `7 S! {9 o; j6 f
        }$ ?: G2 r6 s( m. Q; z( [* h
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
9 A: m, M2 Y; J2 A7 [* c% {. v; o                ret = exqueue.data[exqueue.rdptr];
7 W6 h9 K3 H$ {3 C' w$ V                exqueue.rdptr++;
3 H+ {- G5 M( A, s6 |                exqueue.rdptr&=QUEUE_LENGTH-1;
' K- N& {% F1 h3 B0 v: V( z* U                return        TRUE;7 _( N& l5 y: d* V! [( H* B
        }1 r' P+ }5 d# U& _
        return        FALSE;
: T. B( Z/ z) b6 Y}6 G2 L- I( S# p& x  ^$ `

' C' P/ ~' [8 g' m1 A: w  J7 P. fvoid        APU::QueueClear()) {" g# }% p, l0 [# ?+ U2 w* [% X
{$ S1 i5 ]$ j& B% X9 c, _
        ZEROMEMORY( &queue, sizeof(queue) );
2 z4 M  P6 x7 N  v2 M2 Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ r- ^$ u0 \3 Z0 p
}
" `* P* u1 G' G5 h- R7 Y
6 q# t& B  O6 Z- ]0 _void        APU::QueueFlush()- Z- R" u& K, f
{) i' b& g8 }3 `, I% P, H1 n  J
        while( queue.wrptr != queue.rdptr ) {
+ A7 G2 U' y7 E* z* o8 f6 ]$ W' Q                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );3 v0 W; h, L, H! F
                queue.rdptr++;
8 x- }+ g5 l) o- X  m! W( J                queue.rdptr&=QUEUE_LENGTH-1;# a6 n& p3 j  A
        }. [8 x% y$ Q! l8 y" T5 O

' N' Z' ]4 a, v  N. M4 G, Q        while( exqueue.wrptr != exqueue.rdptr ) {
/ D% f+ A8 F) z5 k! z$ ?* _8 _+ {                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );- C3 Y, r4 I5 n8 N5 e- ^2 j. }2 r
                exqueue.rdptr++;
4 N) X! }8 z$ N# Z  b5 Z                exqueue.rdptr&=QUEUE_LENGTH-1;
+ b, R  v" `6 I5 I9 B' ~; [        }
" C! O" |) W- A. M5 a# J5 d}7 K1 m4 U( V/ R% l

6 q0 u, h4 w3 R9 {, y5 W+ |4 o% Yvoid        APU::SoundSetup()0 }0 g7 j! u3 e$ ^" X' E! A/ U. y
{
; y* S( o# C5 O        FLOAT        fClock = nes->nescfg->CpuClock;
4 i1 ]8 [6 b; R        INT        nRate = (INT)Config.sound.nRate;: C7 L( `. Z, C! e5 @" X$ X
        internal.Setup( fClock, nRate );  S( K2 m8 [% k  y
        vrc6.Setup( fClock, nRate );
4 x$ u# L7 Y3 q$ A* Y; y        vrc7.Setup( fClock, nRate );
% d: q: V/ a- ]6 M        mmc5.Setup( fClock, nRate );5 T8 B( ~' G4 D
        fds.Setup ( fClock, nRate );* G+ a9 ^# Z4 r2 M1 c/ T5 I
        n106.Setup( fClock, nRate );
1 x2 l* [3 C) g3 ^, K        fme7.Setup( fClock, nRate );; a% e* m" }& z3 \
}0 y' ^4 K* J" s4 X1 e* I9 A1 w

: I8 U) H; k; i1 e' \. C7 jvoid        APU::Reset()
5 G, u3 d; }4 `% \{9 u2 I$ N" ^; R* A- `+ F2 m
        ZEROMEMORY( &queue, sizeof(queue) );! d: A- A! l( C; l" C
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 a0 ?; D. L! C, Z# M) A1 [; P
$ C% E9 g8 p& u1 O) }8 L3 V
        elapsed_time = 0;
* i5 Z5 n' f% o: ]9 l: p# N0 |. G  k0 c( |) a# `3 S
        FLOAT        fClock = nes->nescfg->CpuClock;
! X. ?; q) V! I% B( @, b: r        INT        nRate = (INT)Config.sound.nRate;
2 p1 Y* R$ S; H/ T" _        internal.Reset( fClock, nRate );  D, N4 E- u7 J
        vrc6.Reset( fClock, nRate );8 L! T8 a7 h3 o! ~8 L! q
        vrc7.Reset( fClock, nRate );, z' M# g+ C" M( ^  P0 r4 Z
        mmc5.Reset( fClock, nRate );
1 \, P, T1 M. M. g# B0 N3 o" V        fds.Reset ( fClock, nRate );
) j4 }1 A1 \7 c0 p  C! X) t        n106.Reset( fClock, nRate );
& u1 V; M1 w% ~9 w" G9 w: f3 Z        fme7.Reset( fClock, nRate );  o  b- {: y# t" d0 J5 X1 `3 B% ^5 D

! ]$ ?3 Z! ^$ J, w" ?% E# P        SoundSetup();
9 {3 i9 A3 s- y$ j$ h5 g. ?! i}- p9 ~: }7 z* G% N4 u6 D

9 _! a: a8 r; i- ~# xvoid        APU::SelectExSound( BYTE data )7 ^: o) O  A% J6 n* i$ R5 b0 j
{+ Q/ Z! O9 N* H
        exsound_select = data;
$ o# g0 m; f; V5 t}
. v# M4 F$ T! y7 W0 ~
. a2 f4 C+ ]" w1 w+ [BYTE        APU::Read( WORD addr )
5 \/ p; Y8 v# X. C- O8 e{2 d; g8 t) F7 R( j% u' ?/ s( ~
        return        internal.SyncRead( addr );+ F7 X# }4 Z  |2 I
}5 M+ `1 k8 A( i4 e1 v) S4 E' {8 \: z

% @' v) \+ F( e, n3 gvoid        APU::Write( WORD addr, BYTE data )
* W; l4 J9 R9 L% v" A4 k, f- w{  r0 }6 i" {) R: e* K' d
        // $4018偼VirtuaNES屌桳億乕僩0 c3 v. Z/ e. J
        if( addr >= 0x4000 && addr <= 0x401F ) {: z! f( R5 O% t
                internal.SyncWrite( addr, data );& ?8 h5 g1 [5 _5 N3 B+ e) j4 G8 z' L
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );( r0 i" i/ n7 A, A1 t% [
        }
& B9 X8 X1 L7 c) O0 _}( B4 i0 g- E. C4 t% l" h2 B8 j

, R" C8 Z# f. D( IBYTE        APU::ExRead( WORD addr )
3 m. D! R1 \2 Z, _3 d5 @4 i- u{5 N) T  o# B' ]) l. [8 H+ H8 ~
BYTE        data = 0;* q+ v) \6 e  r; l" }  z$ ?
0 f3 a  @0 Z# B/ D8 m
        if( exsound_select & 0x10 ) {  O; A; O- G- I# Y3 ~! ?( T
                if( addr == 0x4800 ) {
! N! d+ D% S9 A6 ?: G" b9 e  y                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 W7 |& r' i% o3 F+ R) x
                }4 f" I2 ^5 b$ U$ _. @
        }8 @$ X4 d+ U8 n. Z3 }
        if( exsound_select & 0x04 ) {/ g7 z6 c" l6 M. r
                if( addr >= 0x4040 && addr < 0x4100 ) {
) N% e0 U6 H8 h) m* L& ~                        data = fds.SyncRead( addr );
  {2 I! E" @) K7 V, j                }
. U* t( U  n8 K8 t        }  t+ _- m' K5 c. o0 o" `6 k5 M$ _
        if( exsound_select & 0x08 ) {
  G  M! a, l+ G. ^! n6 `                if( addr >= 0x5000 && addr <= 0x5015 ) {1 X( U! S3 `" w. w  o4 `! K
                        data = mmc5.SyncRead( addr );5 I" h: ]/ c4 I4 Y. c: E0 R. w
                }
% m, i9 R' C7 |% Y8 D' k- O        }
5 g7 R! j. K7 h* f2 y, r# v
+ [- X! s0 O/ ^2 h        return        data;
) Q, @# b0 {: X}
* I3 l" `% F( O# X& J& Z
0 m5 q! j- K/ ^% n2 C+ {void        APU::ExWrite( WORD addr, BYTE data )
9 v/ C) {! O) f  \& ]. B{- [  E8 f: V( g: o6 L0 ]5 H; l3 b
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );/ ~2 ^9 s3 e! j* g. q7 V# _

# {3 g& j* ^6 U5 u# v' I9 R        if( exsound_select & 0x04 ) {
4 t/ k& Z$ o- Y                if( addr >= 0x4040 && addr < 0x4100 ) {
/ Z# _3 z/ y7 C. o0 K2 Q                        fds.SyncWrite( addr, data );
% n# J8 @/ L2 C3 g$ A) @9 }' A% _0 Y                }
! f: }. {8 U5 l& `        }  A# D1 U6 S9 ~
& o2 I4 }2 m# `& j, Q1 a# G$ I
        if( exsound_select & 0x08 ) {
* e  w. E# u/ w5 d. V  H# {                if( addr >= 0x5000 && addr <= 0x5015 ) {$ ]- J: q' f: X0 ^) a: |
                        mmc5.SyncWrite( addr, data );9 f; z2 y" _' C/ C$ o3 Z
                }9 I& p8 I* J% Y! ^" U
        }+ ^/ h5 X! Y5 a0 _6 y( X! g
}) C) H2 W/ g; f0 y' }7 \
$ _% h( |& }3 H. r$ e& V
void        APU::Sync()* k- ^9 R% G8 T4 ^: k5 [
{1 a0 Q3 _1 h) W, j9 Z! K
}
% h' Z) q9 x7 o8 X) U
7 Q4 ~2 [* ^0 C. g9 E/ Uvoid        APU::SyncDPCM( INT cycles )
) }2 Z1 f: m1 V# A  [- z6 j& x7 n{
2 q, a% L4 T* G7 ]2 s4 `3 X: Z        internal.Sync( cycles );
# a# p, p# w: M5 A9 S0 C- Q' Q" j1 `8 K, B; O. T7 M
        if( exsound_select & 0x04 ) {/ I  Z) P' A$ y% Y. Z; R( ]
                fds.Sync( cycles );
; x+ ]9 P0 l. o8 e& o$ s        }
: J& R3 C) s8 D! k9 P& b  t- f        if( exsound_select & 0x08 ) {
; v/ \4 I+ i9 q* T; W1 h) f: f                mmc5.Sync( cycles );
5 ?; D. J: I% O# A8 K1 z        }; X7 s. U+ B% K/ X
}
7 Z2 M' ~5 z% f: ], B4 ]0 Z; ]7 ^
" |7 D9 `3 x3 Z2 k' @6 |* K: Hvoid        APU::WriteProcess( WORD addr, BYTE data )0 V6 \5 P, t. v8 X1 ~# r1 [
{0 ]) C& `; {- Y$ y
        // $4018偼VirtuaNES屌桳億乕僩
% y- u0 P% c* K2 @        if( addr >= 0x4000 && addr <= 0x401F ) {
1 F' ~. E/ E5 l" D- h9 B. H                internal.Write( addr, data );0 ]/ G; E) B% `+ N% D
        }
7 F/ x+ g" ?4 l6 E" O5 o; R' `}9 Q: h* ~9 J/ ^7 Y  K# R: A  Z
. c- y$ O; n" J7 B) V4 P
void        APU::WriteExProcess( WORD addr, BYTE data )
  |4 W" ]- x6 A9 j1 _2 d{8 u0 a1 D/ l+ G8 l
        if( exsound_select & 0x01 ) {! V/ I. \# [2 p  l
                vrc6.Write( addr, data );. I! q8 y. Y& z$ x" Q! _
        }
6 S) d2 h/ |: G5 ]( U        if( exsound_select & 0x02 ) {
# u! z) x4 o% Z- \+ T: E                vrc7.Write( addr, data );  S9 I& _; m1 M; p) V
        }+ |; P# A! g& p, g9 |9 Z# L$ g
        if( exsound_select & 0x04 ) {+ N) t4 M* R. t& t
                fds.Write( addr, data );
9 s- H9 i$ u4 _+ t        }: u3 X: n$ K1 L' ]) \9 h
        if( exsound_select & 0x08 ) {
8 a7 F: E9 ?& \1 K( J                mmc5.Write( addr, data );/ N+ \7 `. l5 T: x8 g2 Y
        }
/ u( g  Y0 a" I4 J- v1 _/ U, i% M: h8 H        if( exsound_select & 0x10 ) {9 X, D; g" K8 ~- g9 v  _' w
                if( addr == 0x0000 ) {
) y4 A! \: D* B4 H                        BYTE        dummy = n106.Read( addr );
8 f4 t1 R4 F% _, P: L                } else {$ ?6 j' W) ^2 A% `
                        n106.Write( addr, data );4 g& {; j( C+ d( c; e
                }! M! G3 d; z5 z8 B& F* B* X
        }9 s0 k6 _2 t" R1 f. c. F
        if( exsound_select & 0x20 ) {% u. Q# |+ S0 L
                fme7.Write( addr, data );
) D+ D, Q' F6 I- g2 m  T1 x( F        }
' w; F8 M& W+ W) s7 G( N}
1 z( Q6 o2 F7 U& I: y$ l4 z3 w0 i/ V. y0 s% {
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& B0 O7 [4 x, b/ g: r: I{7 e- u! L9 U  O3 v; i) E$ c# [' q
INT        nBits = Config.sound.nBits;
5 P2 X+ X9 B7 K2 P$ M2 x- @DWORD        dwLength = dwSize / (nBits/8);
( i) ?* j: p: M+ ZINT        output;. O( r0 H' _' r3 s  M
QUEUEDATA q;- Y$ w8 L! l0 {, x% Z( f
DWORD        writetime;
+ B/ R) M) T, s" v5 y# W  M
7 C5 h" N& T" }: c# LLPSHORT        pSoundBuf = m_SoundBuffer;
5 t1 o1 x6 [. l& ?INT        nCcount = 0;
8 o$ ]; F& P! b/ {; ?, r1 H& r0 H9 K5 P. V6 q6 k6 d, u
INT        nFilterType = Config.sound.nFilterType;- l1 \2 ?' J/ ~- G& x$ @
  i9 F, G/ ^9 J, e$ B
        if( !Config.sound.bEnable ) {5 `! A  m+ l; a
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );% z+ F" ?, _, Z+ `6 n8 r* t
                return;
! ^# ~( o% e9 n% _% s        }% ]6 R: |7 V  ?' e; b+ ^
* ^! E5 ]4 A1 n- A& K- P$ H
        // Volume setup' L! m8 p/ r6 Q8 t0 ]% |  d7 Y
        //  0:Master
3 [4 Y& |  P8 {. I8 I- w        //  1:Rectangle 1
  x' ^7 c1 ?) Y- l/ d# n        //  2:Rectangle 2
' h. b- a6 ?! ?8 A        //  3:Triangle- B! d/ z+ n: V' E% c
        //  4:Noise
% p1 a9 t. u7 H- [5 |        //  5:DPCM
* z6 b5 ?0 S4 y" _2 X        //  6:VRC61 z, c9 ?: m9 E; B* X* z5 J
        //  7:VRC7& v2 r( |% d/ [( N; r* L3 B# K
        //  8:FDS' G' M6 }* [0 s- Y2 m9 K8 }6 L
        //  9:MMC5$ Q# ?2 K" g. O5 i
        // 10:N106
* i9 \' I- t/ `- ~        // 11:FME7  i( h7 H# }. y/ X+ k
        INT        vol[24];1 t# M5 Y7 F  v/ f6 I
        BOOL*        bMute = m_bMute;
3 W( v6 N* a$ S! |7 Y% ^2 |" V        SHORT*        nVolume = Config.sound.nVolume;9 T, m  S! {" g; h! A% M8 W

3 P, n0 q, I& n" S! ^" y7 R. L        INT        nMasterVolume = bMute[0]?nVolume[0]:0;0 e  Y; Q' i; J/ n1 x
9 d9 C) {: o! k  |- B; d5 ^/ {
        // Internal% C) X7 |; K0 ~) p4 W* g
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& R0 H" G; ~/ }% i
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
9 {3 r# {) A' n% Y5 h: ^: e7 V2 C        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
% y0 e4 C/ p( G9 u7 z0 ~        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;- C4 z4 h' U- ~1 U; o& S9 q2 o
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ n: E6 {2 c) }- _0 I5 R8 H2 W9 r# j
        // VRC6. n4 R, D7 h) G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* _% W/ B) t, R0 u# H9 ?% E, R  }        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, e) Z6 c( f4 Q% P7 b5 }$ z        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& P# J7 p3 S$ B, F
7 X/ e& W3 y9 S
        // VRC7( c1 R/ J' @5 f& x5 N8 d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;9 i# H) V9 r7 I8 ^* r& f: @9 E
' _; y' k: r% j2 M& N& P
        // FDS
0 N! j5 L! n. H# J9 u4 X        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: {. i2 I4 r5 k9 p% h
5 }& ]1 ~% f4 t  b& _  S/ J        // MMC5
1 Y6 a8 V; ]# }        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ J3 {& S0 o# v; N3 i) Q" |        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 ]- P0 G+ U: L3 h6 O, H        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 q3 U9 z' y; z7 ^; t" T- H* K/ l) h, {
        // N106
) g- c# b# ^- q: J0 q2 [7 s        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 ^! Y- q3 ?$ L+ S, U* v1 H3 `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- E5 H5 W+ n2 e, k
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 A$ q) g% O4 v! l8 ^
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 t$ ?% N: G) Y5 N( u' P
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# f2 L% E/ y2 _- d
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! H  o2 U; A# N- F& r9 z        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ w$ ]6 X$ s3 o* p. o0 `8 |3 L& T
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 S( J" G8 ?0 i0 N* {" `# i6 V
0 Y  `- A% Y5 `/ ?4 Y        // FME7# _" |7 q0 u4 `( t  X/ Q; `
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( u2 ?# V* _( q% t' V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 Q% U; z* g' ]$ M- c8 y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: M8 W# l; s1 ~# {
  A3 @, ^( g+ c" m" H- w//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
6 J! j- x" J! B& R; N9 H1 p% x        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. U& l+ O, |9 G4 C/ U5 N, X! \2 y5 s# D4 i$ |3 T
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟7 G) t' C2 ~% J8 N
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {+ a. M# ]6 Q; ~3 d2 V
                QueueFlush();
- {6 V! k: y( A, x7 ]) C        }
! N& t- u. d, u1 [
: Q  U0 V) R( C, i9 G) m" b        while( dwLength-- ) {' v( s! i) n) _; A
                writetime = (DWORD)elapsed_time;
& p+ ]9 Z& T. V% V& Q; {; V2 ]+ x5 O# S- e- F4 b' M( _
                while( GetQueue( writetime, q ) ) {
2 `) w. h* `6 n                        WriteProcess( q.addr, q.data );' v! d& T6 k2 _& W/ x) `7 ?
                }
1 h7 n% C  B* b  i7 U, A! f8 }3 E: U5 E* M* e7 |' |; Q2 B' {6 b
                while( GetExQueue( writetime, q ) ) {
( {; _; H" [- ^' P$ {; t                        WriteExProcess( q.addr, q.data );! b3 r; C# x& x, y5 n
                }" P$ n" u" x3 t. p1 X. C/ N9 c
& s- U: e# @$ f3 Z# C3 c$ \# j4 P5 `
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
! J: N, U$ N% p. \                output = 0;0 h- \$ O0 }* n6 j; o- z2 L
                output += internal.Process( 0 )*vol[0];) F+ n$ z' A  V' q. M! A+ P
                output += internal.Process( 1 )*vol[1];
& G2 ?" G0 n  Z) ^- a" s1 \* p                output += internal.Process( 2 )*vol[2];+ `* C. r* [4 j" ]" q9 |
                output += internal.Process( 3 )*vol[3];
7 r3 y2 M. V' Y1 F; q                output += internal.Process( 4 )*vol[4];1 h9 M  Z! G3 _* y1 o2 G3 v
5 `0 Z5 S' D( d
                if( exsound_select & 0x01 ) {
+ J( Q& Z. v* W) W: ]; D                        output += vrc6.Process( 0 )*vol[5];+ w+ E/ p5 u# a4 z
                        output += vrc6.Process( 1 )*vol[6];
8 M9 }8 V8 H) S, M2 ^+ ?8 k) e                        output += vrc6.Process( 2 )*vol[7];* G4 _$ m; p, O  I8 T
                }3 o8 q, m  N! q# E% v
                if( exsound_select & 0x02 ) {
* s% t6 D/ z0 l7 h5 k                        output += vrc7.Process( 0 )*vol[8];* y/ Y4 j& K8 d: j
                }
& v8 V! K' }9 M5 ^* p9 F+ e                if( exsound_select & 0x04 ) {' d# x. T. c/ L- z. }9 @
                        output += fds.Process( 0 )*vol[9];
5 v. }* a8 p- l  g                }
5 q( M8 x  }/ j+ O1 z3 X                if( exsound_select & 0x08 ) {
! C, V, v0 J. ?3 t* X7 C* e3 p7 [                        output += mmc5.Process( 0 )*vol[10];
5 ?4 t, j4 s* t3 S                        output += mmc5.Process( 1 )*vol[11];. D, u% J% i6 H  p0 k5 g
                        output += mmc5.Process( 2 )*vol[12];
. u- y5 a. ~& j5 S5 ~6 [                }# y8 a1 `$ ^4 R  o1 B0 f, n$ R& z
                if( exsound_select & 0x10 ) {
1 |, E9 F* n; T" W( c( s  Y                        output += n106.Process( 0 )*vol[13];( P* \- G: L) k* X5 U# k3 N
                        output += n106.Process( 1 )*vol[14];& p- Z% k% j5 A- f# u( @
                        output += n106.Process( 2 )*vol[15];
, o, C1 f/ S+ j; ^7 P/ b                        output += n106.Process( 3 )*vol[16];  v6 q+ t; P3 x$ S! f: X
                        output += n106.Process( 4 )*vol[17];3 t/ h8 d( x; y% o4 c
                        output += n106.Process( 5 )*vol[18];
0 Y2 |3 h: ?( @8 |. U# N3 m4 ?                        output += n106.Process( 6 )*vol[19];  X9 p4 e( T' K- P7 _2 x
                        output += n106.Process( 7 )*vol[20];* h, |/ J- A* r4 P: P
                }
3 f. F* h9 [7 z+ }# \6 D                if( exsound_select & 0x20 ) {9 u& {- ^( I2 {: Z: U
                        fme7.Process( 3 );        // Envelope & Noise6 F  U! K" m1 O% V
                        output += fme7.Process( 0 )*vol[21];
  u" B+ _! t0 b% a  _3 Z                        output += fme7.Process( 1 )*vol[22];
. P6 E: E; `5 ^0 T                        output += fme7.Process( 2 )*vol[23];
" i! U& y6 O: O) C3 R3 G& e0 g! D                }, l! h' q2 j% [' W- ^( |0 x

* F* A7 q- E' q8 l$ c1 L                output >>= 8;3 Y  Y7 b( _& |3 F
' B% w4 }1 {& k3 U: A2 Z
                if( nFilterType == 1 ) {* E* r0 d9 u+ Q
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 e0 l1 a$ R' f) d$ [1 Y/ W                        output = (lowpass_filter[0]+output)/2;
+ i0 l6 s3 A9 c3 \  W4 b2 J                        lowpass_filter[0] = output;
  [2 G% i+ h/ ~8 f% c0 X                } else if( nFilterType == 2 ) {
# L3 H" c) h/ D                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)' @( w* q: b0 o8 L: R4 J
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;/ j0 ]  w. A- @. @/ |' k
                        lowpass_filter[1] = lowpass_filter[0];& w) @7 |3 |/ ~- q9 B/ ]1 d& `& n
                        lowpass_filter[0] = output;
* }0 F# ^8 S$ H% n1 d4 `2 r                } else if( nFilterType == 3 ) {0 d0 i1 y% N: ?, H
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 b" V0 C& o( z: e. f& Y6 `
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
: @! U# ^# @( M/ _                        lowpass_filter[2] = lowpass_filter[1];0 b% G! h9 G6 M- H, r1 v2 w
                        lowpass_filter[1] = lowpass_filter[0];8 z, Z; q9 e" G- H9 l
                        lowpass_filter[0] = output;
; b) Z( a6 u$ V! C$ n  Q5 b8 @                } else if( nFilterType == 4 ) {8 @1 |5 T- |) n& i6 G
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)3 l# J1 F& x3 r$ J$ A! _
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
: j' c( R- u2 ]4 V1 d                        lowpass_filter[1] = lowpass_filter[0];
7 v; J; ]: _) f2 L! H% R                        lowpass_filter[0] = output;- P* a. d. O" l4 l1 N5 A
                }
( E% d% J# U1 o' D* Y& Q0 O7 O/ o" D" `9 t$ j( R% M
#if        0
+ k& p# P! \. z0 g# g                // DC惉暘偺僇僢僩( c5 `' L: N( g; [  @. W+ ]
                {
6 @3 f" Z% N" C1 h                static double ave = 0.0, max=0.0, min=0.0;4 C" X( \7 x9 L) c0 C  c" ?1 ?
                double delta;: r4 T5 [9 y, [! h$ b8 A
                delta = (max-min)/32768.0;
/ ?/ i. g+ S% k  q7 A                max -= delta;  ?5 ^0 m9 P( @! j8 U
                min += delta;
" y" x4 _% m: Q3 X$ x7 }                if( output > max ) max = output;
+ ~6 _+ M7 g2 a* D4 I. Q" T                if( output < min ) min = output;
# y/ K: T8 h. l* l$ ]. v4 m+ E                ave -= ave/1024.0;& O9 A3 Q  N3 ?/ s, U
                ave += (max+min)/2048.0;
1 v9 k- \4 Q4 k6 s$ |; E                output -= (INT)ave;
; m" W8 f1 V/ ?8 `  m                }
1 K& {8 q$ Y" T' e8 A: _#endif1 c/ U3 p0 v9 W. _1 i8 C
#if        1
0 z# d" n5 N' K- C/ n: k                // DC惉暘偺僇僢僩(HPF TEST)
# B, ^. H' J% l( w# I( B                {
' U  @# M( ]& A( D$ g! Q* b% X1 `+ ^4 S//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! f: J; {2 D' X. q- l! f                static        double        cutofftemp = (2.0*3.141592653579*40.0);
; \; S7 x# W  V& Z                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, T  b- w- I+ F" x                static        double        tmp = 0.0;
; h, \; O* t9 U# G, r                double        in, out;
' h( ^7 S$ a' m) ]
. b1 K) n" X4 V+ E                in = (double)output;5 u9 L+ q4 ^5 x
                out = (in - tmp);5 i# F$ {* {! [8 Z: c" x& ]
                tmp = tmp + cutoff * out;
1 G* B/ G$ r" n6 T3 ^7 v8 X- W2 t( ~$ l9 Q
                output = (INT)out;
! y# Q% |; s4 Y$ \8 c1 a+ G: `                }
& U0 z' L' h9 B. w! L#endif
& E2 c" Y; L( `, H# B#if        0
0 q8 a4 D& y: i6 I                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)' r4 ]( y3 ]6 e( o) k/ S
                {. @) K  k4 D) |4 p" p7 u+ ?
                INT        diff = abs(output-last_data);
5 a7 I3 t& K: q3 h. T6 T+ I                if( diff > 0x4000 ) {! r2 ~, M( S; _
                        output /= 4;
* M! q9 j5 O0 C, \) G                } else
* F  s0 Z0 F- _/ i- E0 l                if( diff > 0x3000 ) {+ H4 l  Z) O: T  L  W9 [
                        output /= 3;: r% M; Q: o  S% O& A
                } else$ z8 e; A8 r: g5 L7 [
                if( diff > 0x2000 ) {
+ e/ b+ X1 Y* Q: B8 L4 `) d                        output /= 2;
( a& E+ h* N/ j# d* T( `% B5 C- A" t                }+ s3 Y/ G) T7 z& b" @! e3 ]  w
                last_data = output;
* Y, i6 f+ D8 |4 G                }6 x7 o5 W" x6 k2 L' t9 l  m) s
#endif! R2 V9 e% H8 {  ?. O
                // Limit
4 n1 Z* n( e" v$ B1 s- N; r                if( output > 0x7FFF ) {
3 S, i( d/ {- z9 E! s/ D3 y                        output = 0x7FFF;
9 ]2 ^; b1 R5 a# f                } else if( output < -0x8000 ) {2 F+ {+ o( r& L, b2 _
                        output = -0x8000;5 A2 \) _4 ]2 ~8 \
                }
& _* y* I) Y+ i: U: Q( c! F2 ~0 x" o, r3 {+ J& T
                if( nBits != 8 ) {+ {; D) u+ S0 B; J
                        *(SHORT*)lpBuffer = (SHORT)output;
8 q) I5 Z8 o  i/ y                        lpBuffer += sizeof(SHORT);( Q$ a2 X) B  A) O. N, H' B2 H
                } else {+ D% [8 `. F/ ^) X" m' K
                        *lpBuffer++ = (output>>8)^0x80;4 L# M4 s! d- r' z
                }
& k! A2 h% k! R
) U8 g1 Z+ i  @  U                if( nCcount < 0x0100 )6 g1 v" K4 Y3 q, f
                        pSoundBuf[nCcount++] = (SHORT)output;9 q% o- A% \. n6 J! Y

5 U* J! i) o; T* K" E* H3 ^//                elapsedtime += cycle_rate;
0 K2 T% k' ], N$ |! S$ W                elapsed_time += cycle_rate;, X3 \$ H7 X6 u. i4 D8 _
        }. y2 K: e0 K' O' y3 a+ c) U
# w; c  O( r$ Q
#if        18 m9 I$ P. L$ a$ [  o
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
: c+ t/ z% z$ w1 F4 J1 t8 B. }$ e                elapsed_time = nes->cpu->GetTotalCycles();8 }; ]& L' ?) ?3 {- a4 X! F
        }$ l  O4 E$ p0 h, q' U9 a2 f4 n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
( q. `0 r7 ~+ i' @3 R5 @* S                elapsed_time = nes->cpu->GetTotalCycles();3 F: i# {8 N% e! s
        }
: Z- s- ?7 o# \) W6 z: c#else# F4 Q. F" |6 J0 K9 e9 J3 a( D
        elapsed_time = nes->cpu->GetTotalCycles();' z- \; |: F' U% H6 ~+ K) c
#endif3 ~/ e4 g4 C& s" d  Y
}7 H, }  ^$ c# Z6 Y
  b9 i2 R/ }4 ^3 Z+ M# G0 C3 o
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)7 f1 M) M- A  P9 m3 j
INT        APU::GetChannelFrequency( INT no )* v/ d, K& X' t
{
/ j! V9 i, j( r, q/ w        if( !m_bMute[0] )+ g: v% H# m& a+ K% a: g
                return        0;
, C" f+ Y" [$ ?* p  k
+ m5 i! E3 i  h: ~+ A. f4 A        // Internal
( a4 b, M' U4 z# |" i' f9 }2 A        if( no < 5 ) {
0 v0 f) Y  X8 l: l                return        m_bMute[no+1]?internal.GetFreq( no ):0;
' {4 o0 t' U9 V7 A$ n. \, r% s/ A        }! o- J# u5 Z; M
        // VRC6
8 f  r( a: n$ u. y( ]1 g* u$ B! ~: g        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {* F" i. Z# }. ~+ \4 N3 H6 o; \3 E$ O; b
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% |1 `4 ~: y/ T$ M, W6 f* m        }
: ^, i3 f" n( E* E$ ]' `. c        // FDS1 Z, `" I( k' ^% l5 H
        if( (exsound_select & 0x04) && no == 0x300 ) {# }; |; u  A/ k1 J" `( K9 d  g
                return        m_bMute[6]?fds.GetFreq( 0 ):0;( k6 }  b* F$ l
        }3 J& S0 g4 J% e4 ~0 {' n( }
        // MMC5
( O- [9 D4 v; L7 |4 x$ V# c        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
5 R% h& v( {0 u2 W: M  v                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
4 E+ q, ]/ [1 [  a" |# T/ M2 \        }. _# o4 o, E7 b
        // N106* A, {8 |* [( z( f. W1 I& \
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
7 \- ~& _6 p. L' a" E# ~2 ?( R                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
& `" [% F' |8 U" O- R, H& ]- G        }) H. [& P5 z% w4 X" _
        // FME7
: ?; a) `9 a, N  F, s* S$ \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
: J$ u- |. O: y1 N3 D( J, o9 d3 T$ \                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
# ]( Z# q/ z/ O# I0 `        }* O; G! G- m% C: ^6 m
        // VRC7
4 ~, v+ v$ j9 J1 x4 A) ^        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ K' Z4 g1 J, O) a                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 r' v' x0 v6 k  G# I- K# x+ M        }2 A+ c. h! U$ O* _
        return        0;
) H6 k4 }; Z2 u. R" ^7 t}6 z# |& i5 b! K2 k
  I; F' [! Q$ s. d
// State Save/Load
, y0 _4 X: P9 `7 u# Xvoid        APU::SaveState( LPBYTE p )2 L8 n8 l& {, l9 p2 G& `
{
& A/ M1 n; j( U2 ]; x#ifdef        _DEBUG9 w) M( O. w* c7 P
LPBYTE        pold = p;6 N8 A/ m7 y& W1 M$ `' |- D+ c
#endif# R9 N2 v1 z6 `- M7 p; `8 D. x

1 [, J* }7 ]5 i7 o        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ q! v7 z# u  W4 [
        QueueFlush();
% J, ~+ ]$ j0 G+ Y+ y5 W# e9 s7 }+ n# c6 ~5 b8 Q8 i! Y: p
        internal.SaveState( p );
" @4 z5 {+ A! T% p9 |0 v        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, O) v! K4 t$ w( O% @6 b
+ X4 d. K6 d! @- L( f7 ]        // VRC6  L/ I. _* K6 V6 }: W
        if( exsound_select & 0x01 ) {
3 F( \5 a) E* a' ^                vrc6.SaveState( p );
7 Z" q; D( t# Y; R/ e7 C                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
# g6 U5 t$ Y! i7 Y& B        }( T# B" V+ F! `3 l1 D+ l! F
        // VRC7 (not support)
& }3 F, ?4 I/ `" G2 h        if( exsound_select & 0x02 ) {
0 d! N2 d. Q( T6 @                vrc7.SaveState( p );( U% S8 t1 X) l; U! p3 I
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; G9 W( W3 p9 e3 S% w        }( C/ {& g! x- L. h. f4 x. e
        // FDS
$ j1 _* \+ Q- N        if( exsound_select & 0x04 ) {! L, C3 g) W. ^. N/ E
                fds.SaveState( p );) H: {6 Z7 f# K8 E
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding  \3 o. t' D3 g* K8 G8 b
        }9 Q# B, ^# C* t) Z; h( K5 _
        // MMC58 J6 a$ [2 j0 O, k) d% O5 ~" t
        if( exsound_select & 0x08 ) {
1 E& i; \7 q0 U" l4 Z                mmc5.SaveState( p );$ c8 S. i* ]; v! }; F, T& I; a
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 a1 n- l2 A% }4 t# Z/ y: Z+ a        }+ k1 o8 |" ^8 }  Y- v( S8 ]2 t" E
        // N1064 K0 g* r) K) @7 i* f
        if( exsound_select & 0x10 ) {" q) U0 b5 [( W5 S) w2 L
                n106.SaveState( p );+ Q5 M3 Y  G- a3 p3 k
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  i8 i1 D6 \! d
        }9 o  w) A+ h" I' F4 @# }% |
        // FME71 x& `; L, u# L5 {* X! {
        if( exsound_select & 0x20 ) {
. Y" G$ Q8 o- g/ L( s1 @* D                fme7.SaveState( p );
! z% L/ _* M* U1 ]' |% P! G0 o, ~8 K" P                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 P& T1 h6 K: |  ?& ?: B( |" [
        }
. x: h* q4 o( w8 g
* p8 Y- U7 |2 g  E: X; E* M1 T#ifdef        _DEBUG  h" ]  {6 d2 k* V8 k
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 h4 g2 y+ q. Q- F% [0 a
#endif
+ f4 `$ t7 n1 Y$ s* J7 H# U}
/ m& r( X& M* x  t+ I
0 Z0 s" |& K& e5 x! N" S# L3 jvoid        APU::LoadState( LPBYTE p )2 d( k5 R4 [+ w$ G0 Y9 R& x
{% |* w( u! r. Z) m
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& i$ G9 J  ?4 p: \* t
        QueueClear();
3 q" u& v3 p2 n+ y: K1 J0 y) U$ p3 G( B! V. e
        internal.LoadState( p );7 k! b' t5 O: V6 b6 \7 b
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 R. T% I* u  t5 a! i4 M/ a0 J6 A& g5 R# ?. e+ D
        // VRC6
% D$ x+ ]2 f0 l1 Z+ ^# `1 w        if( exsound_select & 0x01 ) {  L1 f; G1 Y$ D! r$ q2 {! Y: J" m. R
                vrc6.LoadState( p );
' P$ N! L9 G' ^% R6 K2 ~) ]- U/ j- r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ V4 X& O5 y( {8 c$ L$ z: r% J
        }+ C' f+ q/ O0 D! J5 V
        // VRC7 (not support)6 I0 C( D2 q  I9 _3 x
        if( exsound_select & 0x02 ) {( a2 z0 y& ~6 y1 @" Q6 T
                vrc7.LoadState( p );5 \+ X- a0 A& K1 F* p
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 {0 L, z% Z. ~$ s$ L
        }
2 @; r* W4 R. D6 {- a5 j2 o        // FDS. q* j) y/ ~& C: I* O8 E/ `
        if( exsound_select & 0x04 ) {2 V  q: s% `' J# @8 O
                fds.LoadState( p );
$ J0 G5 j( S. F  [! a- l                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# Z. z5 h  e8 X' m9 e5 |        }! j- L" M  }8 u6 o; o
        // MMC5( @* Z; E0 v) F% [) C" {) J. T
        if( exsound_select & 0x08 ) {
! o7 S) q/ U8 f2 w& M( P) F                mmc5.LoadState( p );+ Z8 T- r# U5 I0 W
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; i3 n, g+ p9 z5 Y' S$ M        }
0 n) w: H) k& z' R; G: z& F" x        // N106
: W% \# |# x) K. [& {* P* ~) e        if( exsound_select & 0x10 ) {$ t5 r+ y; t1 Q
                n106.LoadState( p );
' @" f0 |% G+ ~4 D                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 p# H6 J8 {: m5 o' O! N1 f1 J        }
* ^1 j$ m- N# v6 U/ C        // FME7
9 r) J! u9 `7 ]' w7 J8 u        if( exsound_select & 0x20 ) {
/ N* x9 A( A/ J8 a  R- y0 |# t                fme7.LoadState( p );
$ r9 {6 X+ }8 o5 W, ~- z: T                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 ~% U/ b1 T! @7 W3 i( |        }& g- d9 @  m; b% }
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 m4 E, [- b4 Z- |$ f: m
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
0 n7 ^2 l/ [7 L# F3 ^感激不尽~~

- l! F% O. M3 }恩 我對模擬器不是很有研究,/ ^$ K3 x; K1 F
雖然要了解源碼內容,可能不是很困難,
; R/ }0 r# ^0 o  o不過還是要花時間,個人目前蠻忙碌的。
- I$ u% u, v8 k! D. C! \+ `
3 U. t) U: ?/ K* u+ t0 b/ z: s給你一個朋友的MSN,你可以跟他討論看看,
: @' V9 {0 U4 G他本身是程式設計師,也對FC模擬器很有興趣。: B# t8 v8 y! W' H  I' Z
: P! p  }7 m& K6 ?2 O0 m7 s
MSN我就PM到你的信箱了。
4 `% x" M) W9 P, I
3 D/ W7 B0 _- k/ _希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 d; k" ?9 M' S, h, L呵…… 谢过团长大人~~
( S, _1 {" }6 w1 H
* [: d, `. v0 a  f3 E
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , `4 ]/ P1 l. M2 L% {5 [) J+ N% ^0 @
团长的朋友都是神,那团长就是神的boss。

1 v3 f- }; b, S' Y/ Y# N3 G哈 不敢當,我只是個平凡人,8 B( N2 f5 k2 W" C& \
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
2 D: A4 d8 I4 Y( P2 G4 u6 TZYH% g  X3 B, d' C! A- E! z0 E( ~6 a
QQ:4147343062 Z& C/ o# N7 \6 M4 f; s+ l3 t
Mail:zyh-01@126.com
. a# R1 Z' `( l6 Y9 H6 j# _* l0 w" f% H+ w) O
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
5 N2 G* H; t0 n: j再次对团长大人和悠悠哥的无私帮助表示感谢~~
. s: j1 Z" M: k+ K$ b) J  n
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-27 10:21 , Processed in 1.120117 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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