EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 y% K/ w7 Z* |% c4 A9 F, ~0 [楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( d9 }$ j4 ^- \$ n+ Q
这里有相应的模拟器源码,就当送给大侠了~~% Z) G& ^" W% N5 K( f/ W
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
1 @* Z# l, J; ?% j0 _2 N4 L能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. q9 E+ Q# |5 c, M. d3 W1 N
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( P6 z- b  z; a' t: F8 m7 `这里有相应的模拟器源码,就当送给大侠 ...

2 z2 J) ~: f: ~聲音部分(Audoi Process Unit = APU):
* g* {: U, N9 x+ @.\NES\APU.cpp
, T- r) \0 A1 x3 T6 B.\NES\APU.h0 i3 ?8 e  [, s$ q. d% Q
& {8 c9 E* M# I& m( k

% h5 p2 `$ g: G4 I, [6 d影像處理部份(Picture Processing Unit = PPU):
' n9 a7 }8 h  N3 ?1 t5 Q  N.\NES\PPU.cpp+ N7 e4 N3 ?" ?3 U
.\NES\PPU.h
& s1 x: K! L& l3 ]
: j( k- ]* v# v0 a9 Q) s如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 ~0 j/ R2 w8 T(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 R# m; _& c, _& E5 @/ I9 ^//////////////////////////////////////////////////////////////////////////2 Q& c( U9 N4 Z% }9 F
//                                                                      //1 r0 I1 T2 Q* {( E- n/ A
//      NES APU core                                                    //
; b: G3 ^7 ?8 F8 X( L) I//                                                           Norix      //3 O  u8 I* ~5 C4 C( d2 g
//                                               written     2002/06/27 //
, D5 X2 ?* A( E' F# E9 ~" v* O//                                               last modify ----/--/-- //
4 G$ u# |, P' Q! \8 D- s& t* w# q//////////////////////////////////////////////////////////////////////////: H1 h- h/ u2 X- V% Q- m4 G
#include "DebugOut.h"
; f8 N  y" O- |& Q#include "App.h"
) Q2 j4 q( l4 Y7 Q* f#include "Config.h"
: X( Q7 b) t9 q8 m, b( |
" ^# `5 R  |7 |& \: P#include "nes.h"
4 n6 t$ J8 U9 u& w7 `, n#include "mmu.h"
  Q% X2 I& o1 j#include "cpu.h"" }6 k  m7 i* `% f
#include "ppu.h"( p+ d) z  o$ W, H2 Y6 T( b( W9 \! [* B. G
#include "rom.h"
5 G  I$ z, n- q3 ^' B9 ~#include "apu.h"
% J8 `7 f% M% B$ V9 ?+ [0 R& N2 `8 k
// Volume adjust
- s9 C) y4 [+ e" x; X. N; p* k$ W// Internal sounds
  j: i8 o9 A! D+ W#define        RECTANGLE_VOL        (0x0F0); o' h9 _# S! g1 n* x
#define        TRIANGLE_VOL        (0x130)" Q" q5 G% F  |6 |
#define        NOISE_VOL        (0x0C0)
6 \) T9 ~! T5 j- L/ H#define        DPCM_VOL        (0x0F0)! F* w. o/ D  Y9 a! P1 N9 ~1 _
// Extra sounds+ a0 e  w# a* J. x
#define        VRC6_VOL        (0x0F0)
/ ?( v/ t( Q4 F* g% R#define        VRC7_VOL        (0x130)5 u5 x: F' ]+ p+ E; D3 [
#define        FDS_VOL                (0x0F0)" t/ {' K5 A) X' k
#define        MMC5_VOL        (0x0F0)3 b& U& @5 c2 U; u
#define        N106_VOL        (0x088)
9 F4 m+ D) X' |$ w8 G#define        FME7_VOL        (0x130)( P* p. C' x2 w+ G$ I6 {' w

0 G3 `6 ?4 H) m% Q1 |. k& u) \APU::APU( NES* parent )
$ v# D/ R8 v( v' a" r{2 z  }3 m, L8 N; Y
        exsound_select = 0;: l: n, G: _' u

1 `* K  l5 I9 Z3 @1 h; S7 D# @% a        nes = parent;
1 w$ M5 G, E6 D/ R) {7 Y9 R% s        internal.SetParent( parent );
$ @+ }( r" h/ G/ `' ]
% Q  Y2 b: P2 K  L/ w- @# ]5 Y        last_data = last_diff = 0;
" \4 r. B" F  F$ ]; M7 x
7 W" m' p8 [; m8 E" C- t& m+ y- c        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
/ m! R; h7 w+ P4 w8 m" S; N5 t$ {& t
$ H0 _$ y% `* h. U+ h( q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( g. l$ _" n4 @) q! }1 n" O
        ZEROMEMORY( &queue, sizeof(queue) );
1 I7 K. u6 }) ?# y, n        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 ^" I- R+ \1 j0 e6 I
; W9 N6 @4 i+ S
        for( INT i = 0; i < 16; i++ ) {
6 E$ b! r# I& [/ @  {5 r                m_bMute = TRUE;
2 ^4 k+ ~. b1 V) n! i/ \        }
& {( X3 F9 T0 p0 i7 J}
3 v4 D3 ?5 p2 I3 Z$ f8 K' z4 L. E1 M, N- V# a
APU::~APU()
/ K2 o; P+ _* {" L" Q: q{$ V$ L% ~" L6 G- b( A, K
}
/ B5 l# x8 x5 q0 f& h! f, S; c# v5 C5 L$ U% p* E: a$ h
void        APU::SetQueue( INT writetime, WORD addr, BYTE data ): E% u7 j0 k, \2 N
{
. R5 i6 U8 ]3 Y% |$ ]# F        queue.data[queue.wrptr].time = writetime;6 f8 R& `: t' N
        queue.data[queue.wrptr].addr = addr;1 ~  V: ?: d: S
        queue.data[queue.wrptr].data = data;
, r$ i- y4 B0 q  `3 Z" g* w6 V        queue.wrptr++;' l, o  p9 W$ H/ S* W9 B  m" C
        queue.wrptr&=QUEUE_LENGTH-1;
9 w, W3 |2 l. s- W* h        if( queue.wrptr == queue.rdptr ) {
- x" c' I6 d1 i9 J, o                DEBUGOUT( "queue overflow.\n" );+ M! |* u. k6 g. v' g
        }8 P" [8 m' r. P
}
) _5 |. j! r6 a, m- ]. a/ f
1 N& `# M; _9 r, J2 {( ?- qBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )- A! y+ ]  ]3 z% P  ^4 }8 T% ]$ ?# d
{
1 r. b: `+ [6 ?/ `7 G0 w1 q        if( queue.wrptr == queue.rdptr ) {
+ ^: m- R: q( h: ]                return        FALSE;9 P' `3 W  |6 G" w
        }
! E6 \) o8 T; r9 @! J* F7 u6 x9 ]# U        if( queue.data[queue.rdptr].time <= writetime ) {
* |0 ], v. \2 a$ T8 i                ret = queue.data[queue.rdptr];
( j; ^0 v  C4 P" j; y                queue.rdptr++;! X) U7 r" M0 R. N: M) [
                queue.rdptr&=QUEUE_LENGTH-1;$ a9 \, X  n; d5 P7 F9 R" U0 r1 |
                return        TRUE;; ^3 E7 V& m/ d3 {1 Q' U3 ?4 b
        }
' H! c: n( p  ~  z+ Z8 u5 X! K        return        FALSE;- b) A! k, Z  \2 {
}! s; A0 N* s9 V8 C) j8 A

; o. v5 P. v2 ^, vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
" X2 y5 Z# G. q2 z/ J{: Z, S5 L3 }' A# E5 `3 Q: R8 S/ G0 M
        exqueue.data[exqueue.wrptr].time = writetime;) L( l' {! z* h/ c
        exqueue.data[exqueue.wrptr].addr = addr;- h) X. s+ K# J2 m' J! |9 G( U, \
        exqueue.data[exqueue.wrptr].data = data;  P" `# O8 G& S, a6 S' u+ Z
        exqueue.wrptr++;
/ n4 ]3 V$ {% K& v: ?        exqueue.wrptr&=QUEUE_LENGTH-1;  A- X3 H0 j1 i' c# Z* X% a
        if( exqueue.wrptr == exqueue.rdptr ) {
  [6 \/ S1 B' w! ~8 u                DEBUGOUT( "exqueue overflow.\n" );
. V% b( Y- ?1 ~7 N  r        }
! Y! _  G" l8 }}  ^5 x; L2 M# j: v+ N5 v2 j
  B6 S3 @$ D+ y$ Y& _4 u* d
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
; U* w  g$ ^+ m: V: X: k6 _! O{
# I$ m4 c0 Q$ V3 Z: D, S- ?        if( exqueue.wrptr == exqueue.rdptr ) {$ r4 J% g$ p0 b, M. n0 w6 r8 o/ k
                return        FALSE;
- |. r1 p  ]3 Q2 C/ `0 |+ ~" n3 A3 S        }& K' }% M; n- _( Z
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) q" N  k5 d5 m9 N( q% \
                ret = exqueue.data[exqueue.rdptr];, G( \/ y, x6 h( `) W, [6 N7 H
                exqueue.rdptr++;- T- W6 m* z* p' H% E$ H
                exqueue.rdptr&=QUEUE_LENGTH-1;) o% X& i; v5 D* j2 W
                return        TRUE;% l# v0 ^) \& k2 H- l$ T
        }7 j# R3 \" D4 C7 Z- |' P' b3 V
        return        FALSE;
. G* \# H) W6 t0 U, B" X}
3 S1 a4 p8 u% k; M
/ I2 _( y: V6 K; q$ x) @2 ?4 G' Pvoid        APU::QueueClear()7 q; r! m. R: z! n) M5 k
{
5 h6 k1 ]# u7 g: s4 q! r8 y0 {- y        ZEROMEMORY( &queue, sizeof(queue) );
6 o8 T; L# }, U% G        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 E) h6 D. i! p}0 p: k* n; ]# F5 l
' M3 N5 b* J0 r& g$ Z
void        APU::QueueFlush()2 \  H" T4 n# T  m. H2 p; R
{
" {* f/ l$ G7 v& ^& j4 [0 R        while( queue.wrptr != queue.rdptr ) {0 \6 a8 E8 @1 [3 D
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );! Q% M+ S8 J$ a& g9 }9 t4 C
                queue.rdptr++;
8 A. q; }3 U" t: `1 |; G4 i                queue.rdptr&=QUEUE_LENGTH-1;
4 G7 H+ ^6 q" x' ?7 J* [3 B        }
2 M4 d% t( J8 K8 Q" h3 t; L! q: f/ F* ]# s; h7 G  T4 o
        while( exqueue.wrptr != exqueue.rdptr ) {2 P* N" ^6 C& Q) F; t: k8 S1 y% O
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 m6 o% G# N! ^0 @9 z2 A% C
                exqueue.rdptr++;
7 U  f7 L. J1 K# O6 F* G* t                exqueue.rdptr&=QUEUE_LENGTH-1;8 \4 H- ^9 x9 x+ E! l
        }
( A! B0 K( }# N$ c, ]}# Z* z1 d9 {) ~6 [. W. o
; z, g6 N2 Y) z8 n+ @/ U$ M
void        APU::SoundSetup()
' a# C% x/ ~" |1 p# |{
4 ]$ m7 C- }7 w5 M        FLOAT        fClock = nes->nescfg->CpuClock;! J4 s1 B0 n5 G2 Y/ ?* x
        INT        nRate = (INT)Config.sound.nRate;
* Z& s- d1 ~( e) A. C5 f% k        internal.Setup( fClock, nRate );
/ U6 U% G3 z9 C8 h7 H        vrc6.Setup( fClock, nRate );
8 S" m0 ], c( A0 d. g        vrc7.Setup( fClock, nRate );
" F0 J& T- g' U2 V1 i3 M        mmc5.Setup( fClock, nRate );
2 {6 y- D% h) u( B        fds.Setup ( fClock, nRate );
5 @7 t, w8 D* W* Y3 C& _        n106.Setup( fClock, nRate );
* _  `- J9 ]" p& W9 ]) A        fme7.Setup( fClock, nRate );: p# h0 a9 i, u# s# m4 ]; p8 Y
}! w, W* f2 f% m% l' y
! m$ l) O5 k! i2 E, ^7 D7 Y2 l
void        APU::Reset()
9 {- W# ^7 G% G) O4 p{
! j2 W8 r& [0 w( U5 S# P" O        ZEROMEMORY( &queue, sizeof(queue) );- T1 e! E2 T! Q  n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, j4 ~& @4 T+ _# z: L. w+ u. D* _, y/ W) N/ p
        elapsed_time = 0;
# e" ~6 s. Z4 j" [5 ?  A
& }1 U+ P6 K6 y( s. r. b. c        FLOAT        fClock = nes->nescfg->CpuClock;) L/ u( r! P6 ~" n! c$ x
        INT        nRate = (INT)Config.sound.nRate;. c* W+ Q/ x/ G9 `. g
        internal.Reset( fClock, nRate );
7 }6 m4 [9 H& {. o- d/ A        vrc6.Reset( fClock, nRate );
. J- M5 d! b+ r+ C        vrc7.Reset( fClock, nRate );, {' r! j; E$ m- @$ |2 g1 \
        mmc5.Reset( fClock, nRate );
- g4 {0 K: o* @0 M: ?4 c) S        fds.Reset ( fClock, nRate );
; G; h! U6 `; s# E7 w7 `        n106.Reset( fClock, nRate );
. t- _* H& n, c        fme7.Reset( fClock, nRate );
# \9 I- A  [% C( Z/ G( b& N! }* z) R. b& A- L/ m! D1 H
        SoundSetup();3 @% Q. e0 l0 H
}
! g" G* ?0 A" p0 R3 {# v2 B! x! }/ p7 K, O( ~
void        APU::SelectExSound( BYTE data )7 Y1 d/ B. ~3 `" @4 w: e
{
( f8 L# K# a; \9 ]$ C  X        exsound_select = data;
/ w( Y" c6 ~, _1 [7 s/ p, R+ o+ H+ N}6 [1 d" K2 q- x

$ y( I2 M  u' T" Y% U- X. YBYTE        APU::Read( WORD addr )
0 N  A4 ?) Q9 Q8 Y{
5 `/ ?) e& s" Y" G9 w        return        internal.SyncRead( addr );8 O+ N. D5 h7 a
}2 V; S$ J  A- n' v' s5 x8 k

( D7 [# \  J% V( yvoid        APU::Write( WORD addr, BYTE data )" J9 O9 e6 m$ S' _3 [0 M
{
" z  [( |5 z2 z# C. T- T4 S        // $4018偼VirtuaNES屌桳億乕僩, X8 K3 c( f. w( i4 F* h
        if( addr >= 0x4000 && addr <= 0x401F ) {
0 r& t' l: q; N$ w0 D6 d4 b                internal.SyncWrite( addr, data );
' o7 `$ G. [& T# D7 t                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
- W/ Y* o2 z3 c% x        }
; e; g+ M* O- S: ^5 [5 _8 j+ C}
: F$ M! K* @( G5 O$ n8 V
4 Y" X4 Z8 D! m& dBYTE        APU::ExRead( WORD addr )
  @! y9 g) Z8 K$ G3 r' h{
7 l5 o, u5 G" v8 pBYTE        data = 0;
/ ^3 u' v6 [/ c2 q6 v* e2 z* o( X
7 l2 {& I* Q, k$ v& s/ k  y& U        if( exsound_select & 0x10 ) {; @7 }# T/ c+ p8 Z; |- T! D* \
                if( addr == 0x4800 ) {
4 Y# ^: R0 m1 o  a' N! _( G                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 w( |4 h6 @/ S1 F
                }
& h6 w$ Z# G" W2 _0 ]        }  W$ D7 F- a5 r5 Q% E$ @/ d
        if( exsound_select & 0x04 ) {
( ?. m7 a( N- @/ v  J* e& Y; v, H                if( addr >= 0x4040 && addr < 0x4100 ) {. ]! c5 c; A; o8 H! r9 A3 L
                        data = fds.SyncRead( addr );
: o, l/ `" M: Q7 W                }( Z" Z) w6 K& \: O- C- V
        }
8 h( W# J: w0 t9 Q* C4 S& `        if( exsound_select & 0x08 ) {
( @) Z; B4 Q9 s5 R8 I# S: a' G                if( addr >= 0x5000 && addr <= 0x5015 ) {9 w) A7 v2 S+ ^" C, H
                        data = mmc5.SyncRead( addr );( H" _9 y6 |: {/ U
                }& k% ~5 X6 |3 w+ w: D; c9 _5 z
        }
% M8 T6 `$ d# B! o4 a5 \
% R: \9 D1 G# X/ L1 k5 b- }6 ]1 F6 w! r        return        data;
4 f& O- n& R$ p- r+ e# G3 d}
* ]9 f6 ?2 ]  V. U  T
5 l. R. v, c+ |6 x  W  e" Hvoid        APU::ExWrite( WORD addr, BYTE data )
+ Q9 M2 Q/ x7 D; k1 s{
/ j1 W- |1 A, [        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );& n% s7 f' ~/ m4 _
+ H/ p: I3 c: }) o$ N. [
        if( exsound_select & 0x04 ) {
- Y8 z; U9 v& e& L6 y1 t$ f7 D                if( addr >= 0x4040 && addr < 0x4100 ) {: Q4 ^% m  B- H7 F/ D
                        fds.SyncWrite( addr, data );( W' K5 D& U- D3 p9 t! m: `2 O
                }
: _" i: D! k  ]! [, A$ Z        }
5 g& r8 [) x# @! q+ Y/ E- z3 N; y( ~2 B, Y) C- P4 w
        if( exsound_select & 0x08 ) {  |3 a' P6 u7 [8 Z% @2 A' K
                if( addr >= 0x5000 && addr <= 0x5015 ) {
; C- V" x. u; x* r! y3 M                        mmc5.SyncWrite( addr, data );+ X5 w. Y, W+ @! _7 n- R8 f( M
                }# m% m. R0 ?- p/ T2 o( a; o
        }7 V9 l) ~9 G# `  T
}
3 \8 j4 w1 @6 K- C8 P: {' ^/ x
( A) E$ ~: S  U) Dvoid        APU::Sync()
5 S% M7 S2 ?! v  s. E- _* M" |$ A{
! Q" W& P! M6 A; t' o, |}
# p5 e5 U3 S: d5 c8 J2 f9 d! U' h* Q) j( ?) e7 J
void        APU::SyncDPCM( INT cycles )
0 S3 m. G# J" N- N% V# ]1 ~  N6 U3 u{4 W4 e; [; z7 V4 ]0 }( o' ~- w' t) Y/ U
        internal.Sync( cycles );) x" y, _/ q* ~$ s" ~1 a

" t1 Q3 W( }. J+ v/ [        if( exsound_select & 0x04 ) {9 E1 Q' R( `$ ?! t' p: Q& x( }! Z
                fds.Sync( cycles );: t& d" v. U5 q0 H. T+ o( |4 b
        }/ E2 R% n4 u$ G
        if( exsound_select & 0x08 ) {
$ O0 Y0 B/ U/ ?/ c; e                mmc5.Sync( cycles );
9 x3 z$ c" f3 g6 S* I  T0 F$ t0 w        }
& e2 U( \8 N; a( b7 W% l}
. g! a7 n9 Y: F2 B' K$ ~2 O3 P! \, T) q( Q' t; t' F
void        APU::WriteProcess( WORD addr, BYTE data ), |3 D. K& E! a. k! _8 f
{
+ c; t6 v9 }' F. `+ C        // $4018偼VirtuaNES屌桳億乕僩
; g1 s: Y) w" C! n/ f3 s9 F8 G        if( addr >= 0x4000 && addr <= 0x401F ) {. B2 b& w  F" g, ~0 `4 g
                internal.Write( addr, data );' {* `* a* S4 A# R% Y
        }
( s: S  h' ^6 i}
# D5 ~  Q+ k; L1 W8 o! P% P% Z8 a' B6 u! T' o
void        APU::WriteExProcess( WORD addr, BYTE data )  j% R8 m+ f% |, I
{
$ T, u/ w* Y7 N& d        if( exsound_select & 0x01 ) {
7 G' B- p3 }) j; O7 k. u3 \( g                vrc6.Write( addr, data );5 }2 T+ Q. b: H, K8 ~+ e# S$ k
        }$ _8 z+ i" z6 o9 c
        if( exsound_select & 0x02 ) {
5 t. ^% f% _: \% G( K                vrc7.Write( addr, data );
: Z4 u( C1 c  [- G7 E        }% F1 P4 H; D2 _3 Y/ n3 ~
        if( exsound_select & 0x04 ) {
- W0 {" x: O) B8 I- |7 c                fds.Write( addr, data );
4 c- u: v# l5 E" g. V1 U        }
9 H! T- _7 |5 q  E; ^        if( exsound_select & 0x08 ) {, ], |5 C& b6 d/ Z2 p* ~7 f
                mmc5.Write( addr, data );
  m8 l; y9 i/ R. j+ |7 u% ?7 D        }
( {( g1 g# T" r, C9 V        if( exsound_select & 0x10 ) {* P! W  F- M% X0 a7 |& I6 O
                if( addr == 0x0000 ) {+ Z. \" f/ J3 _5 B/ |3 z) U
                        BYTE        dummy = n106.Read( addr );2 B6 y, f4 |8 `  R  Y" d* _
                } else {* p# b( Y7 V3 X( `6 m
                        n106.Write( addr, data );! @3 G& H5 p; q# f( @3 P$ Y
                }- N  V/ j2 v" G0 X2 _) ^4 q
        }- Z2 r/ v- N4 @. {4 l* u  Z
        if( exsound_select & 0x20 ) {
/ \8 b/ J" h& b2 G                fme7.Write( addr, data );
6 A: V' [2 X0 D* _! p+ f        }
+ `+ F  y4 ]' z, F0 E5 e9 z" K2 N}1 |+ q" d+ f6 x
8 D/ o1 i, Y6 T- c( L
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  Z+ \& y5 [& p2 _7 b  L
{
7 `9 E: Q9 j9 L1 |4 x( G9 e8 Q7 a! x% cINT        nBits = Config.sound.nBits;
5 [  ?8 C7 ^1 d! B" `2 C8 rDWORD        dwLength = dwSize / (nBits/8);  w6 t  Q, l* e5 ?6 m, u
INT        output;
+ J0 h" |" s, p1 yQUEUEDATA q;
9 C, t7 ^! {& w/ f# |$ IDWORD        writetime;& E+ x4 t/ e+ b8 [6 ^) s; X* f
: r! R( X+ E: @
LPSHORT        pSoundBuf = m_SoundBuffer;! y4 \4 v4 Z! b( J, e8 e' d
INT        nCcount = 0;
- D- {& z8 ]: Q' c; s9 {/ L/ A% H. a- \
# P# x/ s$ [# N# x+ C3 \INT        nFilterType = Config.sound.nFilterType;9 e& n& _/ i% f
$ {3 t# t" A4 Y9 [& x: N' G0 O% _
        if( !Config.sound.bEnable ) {
  @2 m! [2 y$ a) g- X                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ N$ T) O' R0 Q4 m
                return;8 L" u5 Z) d. |8 b) F
        }
; M' l) G% c8 U. C  Q
% B- W( W# M9 I" P5 @) H6 N2 l) s* v        // Volume setup
6 e" }# l' L5 T+ y* h) G# r        //  0:Master
3 @0 \: l, |% M; Q8 Q3 T' \+ V; w        //  1:Rectangle 1
# @1 i+ @" Q1 q0 F. k) t4 F        //  2:Rectangle 2% t& Y9 B$ W; Q# ~. X9 D
        //  3:Triangle
0 U6 |3 S' b% Y. V- q' }        //  4:Noise
5 \$ V) t' _+ k- }        //  5:DPCM
* V8 l& p: h9 e2 i' l        //  6:VRC66 y, P/ B) |8 S0 Z: c
        //  7:VRC7' R' z' {0 l2 Y8 `
        //  8:FDS
! f  b0 S4 \! W0 l) F+ b) V8 H4 Z        //  9:MMC5
1 }1 N% @8 v' D$ S        // 10:N106) J% r, m' i$ H! @3 r# a
        // 11:FME7# _+ G: W3 l& b. q" F
        INT        vol[24];
5 y+ v5 B4 `4 L5 Y        BOOL*        bMute = m_bMute;
: x0 t, S' \  \" Z        SHORT*        nVolume = Config.sound.nVolume;
9 ?2 q5 Q: Q9 p( i( T
5 H6 o9 ^% v+ _0 j        INT        nMasterVolume = bMute[0]?nVolume[0]:0;& [: I2 V* D1 u6 }. Y" b" }) P3 ~, K

6 @, I; Y( J" Q! R        // Internal
- Z2 y+ d1 U% C! X        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( B9 g! w! Y& F9 w
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;+ f* L! [, G9 v# [5 h7 g2 |2 N
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: O/ Z5 m' s% O        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 Z6 `$ A( `4 u* {
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;2 b, W( w) T: G* r
0 T+ W6 s/ S  Q2 d3 E/ b: z
        // VRC6
! ^" q1 B* {1 I6 x& C" j* [# L! ?        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 Y- @% J5 ~! B. k! L
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 {- Z6 @& G5 O. N2 g        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# d7 m2 V1 U( R9 ]0 I4 c% Y8 D# L( }: M0 x, G$ F$ a0 \
        // VRC7, }% d( p% L) X- P
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. D# X6 d0 i! P
0 u7 Q7 K7 U0 a% \2 [; a
        // FDS
! K0 q* e3 ?: `6 G1 N3 C        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;) ?+ Q; _; s7 g$ X6 T

$ ~$ b# d( K( K        // MMC56 P4 h: M, e' D# u. X! A& i
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 w# y3 C( Y) [9 @
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ `( j- c2 h( @: ^% ~$ W1 n' y. o        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; G9 G$ O0 K6 A, t8 O. `- k' A

) L7 J% w& }7 L  v9 X        // N106
3 L% U) y! Z* H: I% F' s4 {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, w+ n; N" r6 L
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. d, T! k! I2 ?) V* d        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; L) B) @& R* `( U        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ l$ T! R& C% O+ G
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 o% s$ t7 L0 f5 B+ L! W+ D
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 {$ s5 O$ i, x* F
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# y7 D7 k) k" x1 L        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ C' D  O; [0 y

. H, [9 o' e8 U* f- B0 I        // FME7: S% D# t* P' M- p9 f4 e% ^9 K
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 F# {- S2 Z) r7 l" u7 h
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 `# W! S" B: J* j7 E  l1 G/ M- Z4 X2 T
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 o3 f* ?# i. K

6 [7 c' k8 Q+ E% D  q" e//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% a9 m. m" \. C$ A        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
- B* N7 Y1 o6 {9 I( [/ I
; I/ a0 p  M: G# ^/ P1 R" n        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
) P9 R8 h" ?, z3 v        if( elapsed_time > nes->cpu->GetTotalCycles() ) {& ~/ ~4 A5 ~2 [. _+ S
                QueueFlush();
0 h: V3 D9 h& c! o! F7 u. b% w        }
% H. ]- }  v+ g# ?+ ~3 Q
2 j& c2 P7 R# G5 V4 O' e- ~) b        while( dwLength-- ) {# E3 V% F' D# d* u) X: q
                writetime = (DWORD)elapsed_time;6 r- b1 T  v, n/ b/ {' U5 R6 @# |

, s6 F6 ~0 |9 u# b                while( GetQueue( writetime, q ) ) {
0 m; ^- ^! b( o$ B4 N                        WriteProcess( q.addr, q.data );
5 `4 b9 l' n7 f) X9 j                }
4 ?8 j3 x! `) o; P. ]
) P3 w9 L: y: {9 z/ f                while( GetExQueue( writetime, q ) ) {( J$ d# I5 a9 u, c6 K
                        WriteExProcess( q.addr, q.data );7 G+ ~$ k3 J2 U2 F" v4 E
                }/ @. L. c+ ^+ h$ [( m
' q1 p6 X, e. l- k  g0 u
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 Y3 F! j  M  ]: ]) ^4 g* E$ p# E
                output = 0;1 J' o1 a' A* J( D$ e
                output += internal.Process( 0 )*vol[0];2 D5 ~1 C# D3 r5 N7 K
                output += internal.Process( 1 )*vol[1];
' D2 P/ W: x' h/ H# H                output += internal.Process( 2 )*vol[2];
1 F9 {$ J+ V; @$ f- n& p                output += internal.Process( 3 )*vol[3];  E- i8 A6 E. y8 E+ \( Q
                output += internal.Process( 4 )*vol[4];
- z7 {9 c+ q6 f6 \! p6 ^' F2 q' L0 e4 c+ T  m3 S. ?3 z% V# W) s
                if( exsound_select & 0x01 ) {
: m+ Z; r% J& g* R  U) ^! _                        output += vrc6.Process( 0 )*vol[5];; q9 u  _0 c! A6 F) I* S  t
                        output += vrc6.Process( 1 )*vol[6];8 S: V/ G0 d! m5 C2 Y
                        output += vrc6.Process( 2 )*vol[7];
5 z, q8 Q/ |8 l( @/ i9 H( n8 P                }
; S( ~: X; S! `$ {                if( exsound_select & 0x02 ) {! N0 s: G4 Q- k0 O
                        output += vrc7.Process( 0 )*vol[8];1 B6 z' F  A7 k1 Z. \
                }
; |8 P, S! P5 |0 ]! s) e: [                if( exsound_select & 0x04 ) {
3 v# y  K/ \% ~2 Y8 I% ~% \6 e                        output += fds.Process( 0 )*vol[9];2 X0 w' ?5 k. f
                }
7 n% r1 W  C: Y5 z$ x: v                if( exsound_select & 0x08 ) {
) r% }3 ]0 t6 Q                        output += mmc5.Process( 0 )*vol[10];
' B- j9 ?' d* X9 h, Q( j5 D5 o: W                        output += mmc5.Process( 1 )*vol[11];" P: C) c" z' l- D: \4 n
                        output += mmc5.Process( 2 )*vol[12];9 X) o9 e! D/ Y# Q1 y. _
                }
7 Q6 x# i9 T/ ~$ C                if( exsound_select & 0x10 ) {
, d. Z0 m/ E1 o3 @( D6 u' V                        output += n106.Process( 0 )*vol[13];
' E% F2 Z6 T- V: B4 i1 @                        output += n106.Process( 1 )*vol[14];8 K' R% }; [/ S/ {- S9 i9 j) k
                        output += n106.Process( 2 )*vol[15];& R. v3 B. z8 V* d
                        output += n106.Process( 3 )*vol[16];
. l8 J' G. A) R: w2 W9 I, f6 t9 P                        output += n106.Process( 4 )*vol[17];
5 A: U+ _- f8 l' N& d! h                        output += n106.Process( 5 )*vol[18];5 }* r/ E6 v4 }
                        output += n106.Process( 6 )*vol[19];
0 Q2 O2 \' d, h: h' R% J3 V' p& y4 F8 J                        output += n106.Process( 7 )*vol[20];
8 a/ G4 Q4 i/ J& w5 m9 ~  t                }" O1 D9 B2 h1 Y4 o" ^$ A1 g, d0 s
                if( exsound_select & 0x20 ) {5 o# L: a/ m/ P* n; w
                        fme7.Process( 3 );        // Envelope & Noise
. o7 w2 r1 F3 b! ~5 q* G                        output += fme7.Process( 0 )*vol[21];" I9 F3 {  W$ m# ~1 F* H! F( o
                        output += fme7.Process( 1 )*vol[22];
6 b' r5 w- z! c# v                        output += fme7.Process( 2 )*vol[23];
1 |% y4 n/ n& v) i                }0 q9 d% C3 }& {$ {' b( o

2 D1 ?( O) C- P7 {                output >>= 8;
# c- Q4 d+ x) H, |$ x4 J5 a
" l, o( h# a& l6 e+ H( E( }  q                if( nFilterType == 1 ) {6 f1 q5 F+ b" d, g( e  G3 h) v
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
) O; f! E( q* k% r/ c& S                        output = (lowpass_filter[0]+output)/2;
' o9 q) g5 o6 l7 l  y9 @4 Q                        lowpass_filter[0] = output;$ O- c, S& `5 A0 U- [9 o. H
                } else if( nFilterType == 2 ) {) U, s# C! A. t% h0 ^
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ N6 c7 K! \; X# f! f% h8 W# q
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# c: e1 z+ e- t0 q, H
                        lowpass_filter[1] = lowpass_filter[0];
4 J( A0 a, l) @. m8 @8 Q                        lowpass_filter[0] = output;
6 h* f" ?" j1 j# q) i                } else if( nFilterType == 3 ) {  d$ s8 R9 O- K3 C+ g1 j( f. o6 I
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
" t9 F- V  C' s: K  w4 `9 S- O                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;; D) ?9 b, d, J
                        lowpass_filter[2] = lowpass_filter[1];
5 K( q3 ]% n* U1 V- N                        lowpass_filter[1] = lowpass_filter[0];' G5 U8 `8 |6 ~1 h+ i# @5 B+ |0 T
                        lowpass_filter[0] = output;
6 e. Z0 E# t( o9 F4 S( k0 D* i- M0 b                } else if( nFilterType == 4 ) {" x  s9 v' \: P6 i: y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
0 G- X6 ]0 t+ L2 k0 H2 x                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
) |0 @0 ?" G* I, s, K" u+ p) j                        lowpass_filter[1] = lowpass_filter[0];
/ G8 p0 o; z8 t                        lowpass_filter[0] = output;" [6 Z( H( V: Z/ _6 |0 @( R
                }1 v& _# G$ V* E" L! b/ S; v

+ c; {6 ~' e0 z- ~6 X#if        0
. N: [2 x, D' [/ d/ \8 g                // DC惉暘偺僇僢僩. c2 E7 D+ P2 R/ m8 @) c0 x- L7 f
                {5 U  G4 g4 p: F- S& A  |0 R8 w
                static double ave = 0.0, max=0.0, min=0.0;
2 f2 V5 H) Y  C( v2 t  g                double delta;
/ Y; ]. @4 K& u1 }$ w% F. o# D                delta = (max-min)/32768.0;. v- b0 ]! {2 L+ m3 p9 v* D
                max -= delta;
$ _9 J$ T4 Y7 E9 U2 T/ c4 {2 \/ G                min += delta;
: k1 C) ^: y. F; U1 x                if( output > max ) max = output;: \( `2 |; x8 V; b5 Z
                if( output < min ) min = output;
6 D* r* |8 D- X                ave -= ave/1024.0;0 U: `% X/ O" D- D4 f2 S0 p
                ave += (max+min)/2048.0;
- [1 B( t7 q* n! v* l& G5 j& u5 E. X' `) H                output -= (INT)ave;. F1 l/ G! M3 C7 G/ _
                }; k) O8 V/ x/ ^/ f
#endif, ^: q3 O) r3 K/ t  H7 c2 X$ Y
#if        1
% n0 `( N, y+ @                // DC惉暘偺僇僢僩(HPF TEST)
# \- t6 }/ {7 L% d) r9 n                {+ O  W$ j% i( i) U! h
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& s# {3 k) K" S. _' x2 g8 U                static        double        cutofftemp = (2.0*3.141592653579*40.0);. x2 V5 x  N: m
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
4 t0 x+ w0 R' H; K/ V9 C                static        double        tmp = 0.0;9 ^9 f  t0 _3 Z2 M* m
                double        in, out;
, a4 ^% v7 g, F/ h' [( G' Y$ Q0 `8 J5 J  c
                in = (double)output;
" Z5 P' H1 P4 M! D9 s                out = (in - tmp);
& ?8 j" v: t  o7 v6 H                tmp = tmp + cutoff * out;
& G& J' A: j/ [" s$ H7 v1 x  c5 x7 [; I8 u9 o' R" e
                output = (INT)out;9 O, v) {2 ~4 f7 U1 H* z- t) t
                }+ x$ s. y6 r7 X3 _6 r5 X
#endif4 I5 G  _% O% O' G5 `, G
#if        0: T6 I# P0 [+ ^1 f. v
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* p1 K# f8 ~/ j+ V8 ?
                {
! p6 O4 `- b, g; e, q  \* T                INT        diff = abs(output-last_data);
, r" a1 c  e1 Z9 Y                if( diff > 0x4000 ) {* z/ X! y) e+ F8 W7 S
                        output /= 4;: w, e# c3 ~( Z) A9 n
                } else
  F5 f3 K: N5 B# _: p" c                if( diff > 0x3000 ) {
" _8 _9 I/ U' ]! v  G) D                        output /= 3;
2 X) z3 z; {2 x9 y3 e" r0 `                } else, \( H  ^" Z7 c2 K( T/ }
                if( diff > 0x2000 ) {$ t. v. \. s5 L3 K, I
                        output /= 2;
" x. C0 C/ G% H$ B                }6 @2 {' ]7 n2 {
                last_data = output;: p; }9 S6 h! b! ~6 h- N9 L
                }4 J, a- f# p4 A; q* R. h3 v  _8 H
#endif/ L: b2 f8 ]; M
                // Limit0 \6 }0 C. M# G0 e; J9 K
                if( output > 0x7FFF ) {/ `" K$ u" I& m3 @
                        output = 0x7FFF;3 l) i6 a' r( F1 `2 v# B
                } else if( output < -0x8000 ) {
, C. V0 }# V4 T! M- i9 v5 d                        output = -0x8000;% X' w* O! R7 y5 ]# @
                }
: W% E# L- @1 G# l4 p9 e) Q
3 q6 z' W2 f  }7 A5 ^# p                if( nBits != 8 ) {0 ?  _# W2 V8 ^
                        *(SHORT*)lpBuffer = (SHORT)output;
# S$ |1 j( u* d: h7 f% v                        lpBuffer += sizeof(SHORT);
( W7 @: L+ E& K& }/ K! V                } else {3 e9 o8 B. P3 h8 r* q, N+ ~
                        *lpBuffer++ = (output>>8)^0x80;1 ]& n+ Y+ Z0 K; Y0 n" F
                }8 K. j  N# o4 }- R& y& ?3 [0 a* q% I
7 @8 \6 [+ z9 ~8 C& `! ^9 b
                if( nCcount < 0x0100 )7 I5 w3 J% Q2 X( m
                        pSoundBuf[nCcount++] = (SHORT)output;" D# `7 E  d" _! D+ D

8 r9 K; g9 z/ _7 `0 W//                elapsedtime += cycle_rate;9 N, z( y3 M0 {+ X* f
                elapsed_time += cycle_rate;
1 d3 u- R  K3 f) `. g        }
# O1 E+ T1 v. X9 S, q  @% Y4 ]7 {/ j* \: Y
#if        1
" w  w% {  X/ {  h: q! m        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# @; Q4 Z! i/ k1 S9 v2 a, j; F
                elapsed_time = nes->cpu->GetTotalCycles();
' O3 ]. v2 {. Z4 s$ `, R        }
, G9 _  {7 N2 V! _. d7 i+ H) B        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
$ d7 n0 D) o% U4 c1 r6 {- t; d6 L                elapsed_time = nes->cpu->GetTotalCycles();  u( v9 m* ^5 g( k9 q
        }
( L+ ~' M5 [' u: C1 p* P* i1 Q#else
! Q5 G( k+ f4 d" j+ ]+ |        elapsed_time = nes->cpu->GetTotalCycles();3 Z7 h/ B4 y5 m+ }
#endif
, v& o7 n- Z& I# Q  F0 D( M}6 h9 J: D* O( l8 U* ]+ @$ D& a

3 K; V' \6 v# L- G' l$ W// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 w1 l/ K; {. C5 T" e" f' p# D8 ~+ K
INT        APU::GetChannelFrequency( INT no )5 z  f# |8 ]4 E5 r7 I8 w5 z" h: `
{
* T2 k# B0 |. j. V6 P, O        if( !m_bMute[0] )2 Y5 C# o6 B% q8 F/ T
                return        0;
; [; h1 M& g0 I- e' G4 G! V  i8 x4 i5 I7 m: d
        // Internal
  A  E; C+ p0 a5 J        if( no < 5 ) {
! C: z3 y1 Z' A5 ]. q# B                return        m_bMute[no+1]?internal.GetFreq( no ):0;
5 Z& N1 y- [; a7 y) c! M: U        }' w2 \) w  S5 V. r  q
        // VRC6; @* I7 j' @7 q/ b
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {1 M+ U6 V# S# R( q* E
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% o3 R1 e0 B' [0 X        }/ ?. k$ m3 D6 D/ {& z' G5 ~2 y4 \
        // FDS* C4 w8 W; V8 Y6 z/ p6 ^- i9 s
        if( (exsound_select & 0x04) && no == 0x300 ) {
& p: t+ B- a' A0 o, v  {, D. m3 e                return        m_bMute[6]?fds.GetFreq( 0 ):0;
1 N) _+ s( U  K* P" ], k6 Y& R        }7 f! H, Y! Y5 B. g& L" y, V- z
        // MMC5' `0 y# e# C% m: ~9 l3 ^
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ T; ?  q9 w5 s                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: W7 y. C! M/ R' D- n2 V/ x. _        }; j$ x/ X& h& d; p& G* U
        // N1060 O! d  U; C0 B0 O
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" R* G5 x9 R; b& b& L. V( J9 L                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;. q) j. K5 s- k+ q3 B2 X$ o
        }( m+ G0 Y1 P7 Q& B2 p
        // FME7
0 n+ Q2 Y2 l% Z7 B        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
0 X7 J% {0 J- \# I5 B                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
7 b7 K. T* s0 [, m        }* W- D' b* J; i) O# x
        // VRC72 [6 Z' N/ ~8 @$ d. I
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ m. y9 I3 }1 m: f                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;' z* [( X9 m8 N9 o0 w! B
        }# {. ^' m0 r7 f* |1 ^* ~
        return        0;0 O/ w9 j" x) K3 P9 D- q0 m+ E
}0 K4 H) Q" m! ?* ^, A% t' s

+ Z' [6 n9 T$ R9 @( T// State Save/Load
) G6 T5 ]2 N) Q2 p5 Bvoid        APU::SaveState( LPBYTE p )
3 T; b7 S9 d* j{( Q  |# I% {0 p/ a, |
#ifdef        _DEBUG1 a* d1 P4 @: [- A# D
LPBYTE        pold = p;
$ h  ?7 u* z4 N  s#endif1 e' u# Y# |! @+ }/ o. \
  @( S0 z" |! B4 C- h" e# F
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
6 X3 T, p$ E. E' o* ~7 e        QueueFlush();# X$ i' u4 j) L& ~% \+ ~  |" L# F5 `
6 }3 J; b% {9 h  M  ]! S
        internal.SaveState( p );
  ^9 M  S$ P1 c' \. Z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding# B, t" U$ F  z+ ?* X! m

1 ?) ?4 X. F. [        // VRC6
" |, o8 M% x& \$ a/ f- q$ h) j% {        if( exsound_select & 0x01 ) {0 M/ w1 l- U5 Z8 D. G: a
                vrc6.SaveState( p );
1 [& C- x4 L% G% i" _                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 s* y, G$ i: C9 ~/ g, `
        }6 X6 w! Z4 U7 j- t! y) S, J  E  c  g
        // VRC7 (not support)' [6 h+ b, K* @0 q; m* b9 ~, r
        if( exsound_select & 0x02 ) {
3 s* t1 Y0 t' N1 c% H' d                vrc7.SaveState( p );
! r. |$ s$ v5 h% S$ }3 _, y, {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) A3 p- [2 E- v4 t  D8 \
        }7 l2 ?/ O$ I9 s% R
        // FDS
, c, E9 W8 m/ X. `; W        if( exsound_select & 0x04 ) {: ~  r2 g8 s6 @- ]
                fds.SaveState( p );
9 }+ W( d, N5 u                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- z* e0 f; h& F( @1 d& L% A6 F        }
. X# p! ]2 _; W/ U8 n8 W  G* n        // MMC5' Z' u0 G' ^( ]1 F: h- p2 ]
        if( exsound_select & 0x08 ) {4 |9 n: g" F5 O9 W" }0 W
                mmc5.SaveState( p );$ ?4 P5 _1 n& c) T
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; Y2 o# x4 E( r: S  m- s* K
        }$ y( I, p; W4 Z
        // N106
% C9 @& D7 w6 W- O) T6 T        if( exsound_select & 0x10 ) {
$ w7 E# T5 r' h  A4 C# K# F                n106.SaveState( p );
" \+ R& P; I- t                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ r( F4 a% L) |        }: v: u5 U. B3 r- ?
        // FME7
( P$ Q- t1 x& I; S        if( exsound_select & 0x20 ) {* W' d/ y9 P" z
                fme7.SaveState( p );# r. t0 v3 ?% H- u
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 J8 x1 C# r2 U4 V" _+ s# o        }
' ]+ |8 m% b1 p; Z' }0 |+ F; j1 s3 _& u
#ifdef        _DEBUG+ s6 [. R3 b! `
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
; {# r4 h) C. ?; U#endif% d- d: H( M4 C( a# `/ o2 F
}
: D! S9 N) p  K. c/ E5 d
9 `# x; l6 T& L# o6 yvoid        APU::LoadState( LPBYTE p )
2 n: G" j" b9 ?& i$ @- w{0 F3 I9 u+ A8 S8 p- H! M" Q5 {
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
2 B/ h3 b9 H9 d6 w( c  l3 O        QueueClear();4 y, i4 |) C. J; L

( G; R0 V- x8 _+ J' Z+ z1 l: t        internal.LoadState( p );5 _8 r% n. ?% p9 u! p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  d. a0 w3 j# G% \, V3 s! k) Q- M
3 S7 r7 Y3 D) s) r3 {
        // VRC67 ~3 ~( B5 ?8 y! B) q! k7 I$ {
        if( exsound_select & 0x01 ) {+ ]( Y' B  k: A0 i/ ^5 ]6 d
                vrc6.LoadState( p );
! K, b- ?( A. [* M$ K0 u: B                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) W/ w# l* q2 ]
        }0 Y8 \) F6 Z$ g: {; y
        // VRC7 (not support)4 f* M+ u9 W  l  Z" U: a
        if( exsound_select & 0x02 ) {
% @! O7 s$ L9 a& ?! ?! r* x' R7 N' u                vrc7.LoadState( p );
/ G7 f8 }& R' _6 b/ P  Z+ p) b$ [                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: y5 J% j; Z: l. Y; i9 D2 ]! m: |
        }* w0 ^9 S$ a8 M- C  b1 U! z. w
        // FDS' j( n/ S3 ?. S1 o9 V& D- M
        if( exsound_select & 0x04 ) {
% {0 x! |& ^% [1 m9 ~' T                fds.LoadState( p );
* c1 k) u8 f2 I+ U                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 ^' u' i4 {0 g8 j. j6 l) k        }" o* |2 w* K$ [/ K
        // MMC5  g$ G4 O' ], ^" D7 ?/ z
        if( exsound_select & 0x08 ) {
* U# u3 v) m+ X8 u! j, j" J                mmc5.LoadState( p );! s  J4 L  M* }# g1 ?! v5 C6 |1 d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 o9 A7 f3 y: V        }
7 V9 n0 P' v7 J# p" D        // N106
; r$ H+ z2 ^/ A: T3 S, [7 l  b        if( exsound_select & 0x10 ) {
' o9 h# R1 S# V( y                n106.LoadState( p );
/ \$ w# c7 Y# G; v9 D  D' X0 m9 K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 q7 F; T7 f7 E8 u6 C+ S  [' P        }* e* }$ S6 c& i( u% x! a! W# N
        // FME7
6 Q4 g5 M4 S6 L9 V0 K( j; H        if( exsound_select & 0x20 ) {2 h: U6 T" z6 q6 y+ d
                fme7.LoadState( p );" W. a4 N1 S  T& x9 W7 X1 K
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- s% J& x: a3 Q1 W; C' C        }
1 g& C6 S; u! c2 m) q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& e4 c0 G) e( ^7 W6 z! z4 P( e. ?可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
% ]3 T, c1 a) e& Q0 {/ r) k感激不尽~~
+ L* x$ o3 B4 C$ W( C7 W
恩 我對模擬器不是很有研究,$ s9 G# ]4 ~" v2 W8 F& N# V# p
雖然要了解源碼內容,可能不是很困難,; K- R+ I( o6 [5 `/ ]( `4 D' l" {/ Q
不過還是要花時間,個人目前蠻忙碌的。
8 p0 ^4 E: Y" v. ^( q8 H/ j0 g& |2 c2 M% ~9 E
給你一個朋友的MSN,你可以跟他討論看看,  O+ l4 q2 s2 B
他本身是程式設計師,也對FC模擬器很有興趣。
, B  }1 d# p- X. G9 |* G
9 d& F( Z! p1 P) h6 z, m/ {MSN我就PM到你的信箱了。. w* e+ c8 z2 V; p8 F( F# M" y! [
4 O- X/ o# w, b+ e$ V; p/ r" D  R
希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
) s! J/ Q3 E, `呵…… 谢过团长大人~~

/ g3 V5 _. P3 e& S
& w  C) X6 F4 M+ v8 k6 R" Q哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 : A! p( |$ S# P/ X4 \3 L& I. j
团长的朋友都是神,那团长就是神的boss。
3 d# ?8 s, A+ t1 Y
哈 不敢當,我只是個平凡人,
0 Y9 [4 h- x% F% n) W$ Z% T& Q: I要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙, H9 `1 I3 k: O
ZYH" f5 C- J0 D1 X
QQ:4147343063 n" I4 t" F9 o
Mail:zyh-01@126.com3 J! i% x$ _; _: |
, [* v) q3 u: _3 t# y8 E
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
& r% v8 c; A) m! i/ H2 N再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 z2 L  V3 p$ S) u% C$ P7 q* q  C$ _) V不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-30 06:32 , Processed in 1.088868 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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