EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
  x- V8 D5 x0 x% S1 m5 q& c+ i1 qPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 T2 ?$ v: s" w, B5 B, ]
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; ]  [  [+ R$ n) o& d* d
这里有相应的模拟器源码,就当送给大侠了~~
0 `2 J, z; X$ C$ g! F0 ?* v. khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 a5 [, _* g; N能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。7 g$ C# d- }5 }1 W2 F
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; L0 o8 E5 u$ x7 a' ^; Q这里有相应的模拟器源码,就当送给大侠 ...

4 o9 Q, \" w1 z+ e5 M7 ?聲音部分(Audoi Process Unit = APU):" u, E8 e1 {* P5 O1 B6 O% p
.\NES\APU.cpp
  p' K7 J. f3 T: {" F5 }$ U.\NES\APU.h
. ~" U, j9 }$ P+ x/ k* K$ }% x4 O* m2 ~% W

6 h" ~- a* Z! W' f影像處理部份(Picture Processing Unit = PPU):; Y7 q) D" l" e
.\NES\PPU.cpp
6 T4 G2 J9 i8 r) K1 h0 r.\NES\PPU.h. N/ b) p9 e# Y. n- J; E
! B  T& K- w7 }5 F- ~
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:! r' K6 T0 c" B+ \! L
(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 _0 ?( I2 M' `- ?5 y, K3 h4 N
//////////////////////////////////////////////////////////////////////////2 N8 D2 Q: ]; a: v# D
//                                                                      //' ~! t/ H6 |7 c6 e3 z
//      NES APU core                                                    //6 I% }: i2 D7 j9 _
//                                                           Norix      //
1 j+ X8 c1 @) Z6 g% E! n9 q: r//                                               written     2002/06/27 //
' D0 Z6 t2 z* q" n0 h) t//                                               last modify ----/--/-- //+ i8 ]* e! b/ L( f! ?
//////////////////////////////////////////////////////////////////////////
& x$ l6 o. v( H) _2 R) U6 T#include "DebugOut.h"% X; T( e" d; s3 O5 F0 S
#include "App.h"
# k" O4 c8 i7 F9 ]#include "Config.h"7 M+ U: J; ~/ L4 {# X7 D
* P, |) Z/ C; O: Y% l! l
#include "nes.h"$ H  D) Q! L$ ?' e8 S& y
#include "mmu.h"# u& Q* r, G/ Q
#include "cpu.h"
) q. e* N! v% J. ~- e/ _2 o/ j) K% p# r#include "ppu.h"
  l; O- {$ J; q! \9 G#include "rom.h"
4 S9 G! T5 A5 @9 x#include "apu.h". M* D7 X- d: e4 l1 F# O- S8 X

5 I  E5 \. @' n' e# K9 [8 m// Volume adjust
2 n6 c7 a8 J3 h+ F& k0 _7 R7 _// Internal sounds, j- e2 Q/ R3 \1 M+ v; ?: p
#define        RECTANGLE_VOL        (0x0F0)
7 q) w* G4 K2 h8 H#define        TRIANGLE_VOL        (0x130)$ y$ J  S5 K6 \$ n" Q$ E6 x' U
#define        NOISE_VOL        (0x0C0)
/ C1 A/ h6 |6 i% x1 l1 C#define        DPCM_VOL        (0x0F0)
7 q- T' }! l% S8 ?  G  h' Q: U// Extra sounds5 r% A: ^6 o9 Q7 ^0 Q" z3 S! C
#define        VRC6_VOL        (0x0F0)( {( b( v' {, ]+ `' X2 q/ _) R3 m
#define        VRC7_VOL        (0x130)
( L. a! U7 {: O) K9 K" [#define        FDS_VOL                (0x0F0); L& [0 a$ t1 J6 w) q, B% _
#define        MMC5_VOL        (0x0F0); e$ ~" p& j- q+ P
#define        N106_VOL        (0x088)
! q6 z5 C& C5 c3 U  Y3 ?, o6 x0 @#define        FME7_VOL        (0x130)
- w; \! U' i' ~4 R7 p8 F: q
4 U9 u; w1 k" Q- y0 Z# k8 vAPU::APU( NES* parent )
; q5 y3 f+ @: F2 C% H9 k{
5 D4 N, r+ p6 n  @1 `3 v        exsound_select = 0;
$ ]8 j/ x, F0 l$ m# d
  P' C6 j) B2 X# \& x9 G        nes = parent;
* R4 C/ y" Q: P1 G: ?! I& U9 F" h: M        internal.SetParent( parent );
) T% P* V2 L% ^' r) S% P  J# q5 s% w& a8 y. k" Y* m4 L+ e
        last_data = last_diff = 0;: O. S8 s" b! @( U5 Z2 M
9 o' N2 X+ a( S% X: D) C
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );6 P* r+ F" s! K1 z) ^
6 \  @$ s. Y+ J' ~: R4 y
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
5 m/ g2 T) h. d3 }9 s, n, w        ZEROMEMORY( &queue, sizeof(queue) );
4 C2 X) N, F& S& @  t) c& G1 f        ZEROMEMORY( &exqueue, sizeof(exqueue) );) @  l0 D( E6 R2 a) b0 r  t( v2 y* J

5 C5 P( g1 |2 p4 r        for( INT i = 0; i < 16; i++ ) {' k  p, ]% C( n* \/ Z$ ^( O
                m_bMute = TRUE;9 h7 Z; X0 Z/ I* C! e' G  O. o
        }
! k6 u5 C! |/ k5 b8 X1 V' W}
" J# U0 @# I7 P3 S% D% W- @7 i9 S( M3 z7 H. J5 [4 E
APU::~APU()) o) H* P7 w0 w7 p: D9 D( w6 R
{) o5 P7 S) x2 t, ?! ]0 d* |, k9 r
}' I! ?8 C6 z- g- z/ b! Z: |: g

2 {* V% d  P. P9 J. w# @# Mvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) C/ f* ]! w5 ]( q7 g{2 P! W* p6 j! k6 L4 W/ e
        queue.data[queue.wrptr].time = writetime;
$ V5 P6 X' Q7 n$ b7 l0 _3 V# v4 \        queue.data[queue.wrptr].addr = addr;/ ?: E( a% d+ `* _
        queue.data[queue.wrptr].data = data;
& R& _( e  G3 `3 T9 f$ N        queue.wrptr++;
: f( M+ m. }. B4 u& }; k8 V- I        queue.wrptr&=QUEUE_LENGTH-1;
' ]: R0 R" k' v; k7 u        if( queue.wrptr == queue.rdptr ) {
! b8 d4 q  I& Y5 T6 {  t                DEBUGOUT( "queue overflow.\n" );# E8 B  N( b: N
        }
; |) W, e$ l# G}5 J0 U' l  ]2 y. V. _
6 R7 @) ^$ `# {4 a
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) X; I; G1 T9 A6 S* w$ S9 J
{2 e# C% l- {; t# ^4 _0 t2 t
        if( queue.wrptr == queue.rdptr ) {
5 o  m$ B. {7 p4 n2 y" L! a                return        FALSE;
3 M& {9 s5 R. f: R9 {        }' d+ {) F- P# \  N9 {
        if( queue.data[queue.rdptr].time <= writetime ) {
0 X: c. x, a  j! p+ e4 I# n) s8 h                ret = queue.data[queue.rdptr];
  J3 e7 T- U" ^8 X0 C% b& a                queue.rdptr++;  S* e) A: }& t' x6 D
                queue.rdptr&=QUEUE_LENGTH-1;
  }' `! L2 Z' c5 r                return        TRUE;, \: p& L' w  k' F" J
        }2 q* w8 `+ y7 K5 `- w; e
        return        FALSE;
; A2 r2 ~2 p5 K2 f/ \0 n}( t2 j8 Z+ r/ n- g* `- y2 L, p" F  P

4 I* I2 M% ?- o7 `& c% Q1 Tvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ). {' F7 u3 p: B
{( B0 l" L: r- `0 t  g' m/ ?9 h
        exqueue.data[exqueue.wrptr].time = writetime;# D1 D; g0 C% L$ L2 x- d. e
        exqueue.data[exqueue.wrptr].addr = addr;
6 ?/ ]" N9 m) e( s& e2 L        exqueue.data[exqueue.wrptr].data = data;
. d  S+ W+ V2 d, x: j        exqueue.wrptr++;
) v: d3 x9 r; o1 l$ E0 R; ?        exqueue.wrptr&=QUEUE_LENGTH-1;, @1 }, }) N  S% W  z2 I; W
        if( exqueue.wrptr == exqueue.rdptr ) {) R2 S6 _8 A* M0 N$ _* i
                DEBUGOUT( "exqueue overflow.\n" );" C5 y% ]- s! X  e  T) {( h
        }
7 [7 i5 g+ Y  L+ H) h# L# t}, b+ [2 c; h8 K2 b% G5 t$ j

  r2 q7 x$ f' \. RBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* X5 ?& Z3 l1 h2 a
{; V+ j; I6 t/ R8 k
        if( exqueue.wrptr == exqueue.rdptr ) {: v9 C" c1 M6 f+ u
                return        FALSE;5 d5 P8 G' t4 V7 C$ x
        }
$ A( R! A/ A. p! C. S        if( exqueue.data[exqueue.rdptr].time <= writetime ) {( [- h) p- M6 P2 a0 ?4 N) G
                ret = exqueue.data[exqueue.rdptr];7 O3 i; E6 y# w' S, @
                exqueue.rdptr++;- [/ X9 z; v+ f$ V# n7 V" E
                exqueue.rdptr&=QUEUE_LENGTH-1;( o6 y1 g2 h1 S/ D% j$ D3 B
                return        TRUE;5 E/ Y( }: H& e7 p
        }2 \7 u# b9 U' r8 m
        return        FALSE;
0 E6 e' Y/ h  F" p  u) x, }}
+ ^6 g% @2 H& i: z1 z
$ ]" `8 T( y0 T$ O* t9 j+ \void        APU::QueueClear()& k/ s4 s4 @3 f9 c/ v% R+ A
{4 B( O- ?. ^6 T9 T$ Z
        ZEROMEMORY( &queue, sizeof(queue) );7 A3 z& K4 A% l) T5 ]' _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 m2 c% c6 [2 s$ v* e}7 `: y3 R" e1 T! {1 s

+ L8 \( q% Z5 S$ M4 xvoid        APU::QueueFlush(). C) W2 p5 V) J" g9 f; g) Q
{
' P( z. P6 S$ ]        while( queue.wrptr != queue.rdptr ) {
# _% _1 }. L9 [; e9 |4 I                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
. d; F- P# |2 T# [* N* k) N                queue.rdptr++;
1 }2 [& z6 ?% Z- l                queue.rdptr&=QUEUE_LENGTH-1;0 D! E  l3 g6 s
        }
2 u/ X) w2 W5 l; M+ C: ?/ n; z2 G3 ?# ~
        while( exqueue.wrptr != exqueue.rdptr ) {* ]( G  C. m8 O6 d) [0 }
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
0 _7 C" `0 |* P, [8 Z8 j/ ?2 \4 w. t                exqueue.rdptr++;
5 {+ W1 c$ w3 C& w                exqueue.rdptr&=QUEUE_LENGTH-1;! X6 B* g* K  U
        }$ V. p! c; {. l7 P; F1 k
}6 [8 [7 [/ R' ^" X) o; j5 Z

$ v' s8 w& {! V0 Gvoid        APU::SoundSetup()8 y: ^6 M. r, U) V3 t
{( V( J! |& l8 f9 E, r7 ^
        FLOAT        fClock = nes->nescfg->CpuClock;# v5 j( j' A5 m
        INT        nRate = (INT)Config.sound.nRate;! J3 m, L9 _; R; ?
        internal.Setup( fClock, nRate );
/ f- e' a- m4 j* N        vrc6.Setup( fClock, nRate );
$ T' C" g! r  R6 O& i. l+ X        vrc7.Setup( fClock, nRate );+ j) t! Z/ w! `+ D6 L( [
        mmc5.Setup( fClock, nRate );" p+ |) v$ c( m# b5 q% [
        fds.Setup ( fClock, nRate );
4 [6 Q, e; N" I+ _. y        n106.Setup( fClock, nRate );
- k' F% l7 \1 T" D( t, U        fme7.Setup( fClock, nRate );8 m; s$ e& S/ n* W$ n4 f
}1 a. W* ?2 b* l" h( f
; O. Y3 x) G' i8 y/ N1 l$ v
void        APU::Reset()! S8 b3 p  j9 l  e& Q' ?0 k5 N
{
5 U: N6 V2 y7 {# E! [- |1 Z        ZEROMEMORY( &queue, sizeof(queue) );
7 j0 h, w  M0 ?% R& a        ZEROMEMORY( &exqueue, sizeof(exqueue) );" S  M! l0 }, e7 I" p
9 y' X& z, W" n4 R# l% Z4 j7 G1 ]4 P
        elapsed_time = 0;  e7 |' j+ y" k5 v3 e+ @$ S& w9 I8 v
  S9 G5 z9 ~5 C8 @8 N8 t$ `
        FLOAT        fClock = nes->nescfg->CpuClock;$ z2 y: W8 f2 ], ]) a6 v+ X& }) \
        INT        nRate = (INT)Config.sound.nRate;6 e# f8 M  o  I3 t: T! B$ f' a
        internal.Reset( fClock, nRate );6 W7 t: S' v) D( v5 y1 a
        vrc6.Reset( fClock, nRate );
+ Z' S6 P+ W8 Q3 f) g# d8 P. ^7 ~        vrc7.Reset( fClock, nRate );
! j$ E( M% n8 g) E" W        mmc5.Reset( fClock, nRate );
6 B7 n5 Q  M& \8 b6 t# _        fds.Reset ( fClock, nRate );
% ?9 A5 G0 w; t! y% O0 m0 H        n106.Reset( fClock, nRate );7 }' {0 R/ ?& U
        fme7.Reset( fClock, nRate );
: }* O# o3 P2 W- a" \! g" C! d! t
        SoundSetup();
' N! j. c: {! S: n* H4 v}
5 H- k2 Y* @& m& U' Q& ^; v+ r# [
* q! {- e& s7 e! g3 H' Qvoid        APU::SelectExSound( BYTE data )
$ c) s5 o5 w) x% s) i3 J{/ A( o# n, Y$ k
        exsound_select = data;0 R$ c* m( y1 U7 D! H* P, w% z
}+ M: D- d! E* ^+ M5 A" K# w

# g& x2 b, R) A" t# J& u0 FBYTE        APU::Read( WORD addr )
8 L8 ~1 B# u) M7 H{3 b- n* I) ^0 T5 L8 W
        return        internal.SyncRead( addr );
- n! k0 e+ T9 y9 W+ g" E9 X5 |# {}
- k! o0 `" |: R/ A' M8 d) K9 r2 U; p8 i& Z3 Z
void        APU::Write( WORD addr, BYTE data )/ O( E* H; M9 N2 e* l1 q  a; E
{! s& Z2 S- A+ H
        // $4018偼VirtuaNES屌桳億乕僩
) R1 ~; M+ v" \" j        if( addr >= 0x4000 && addr <= 0x401F ) {
+ ^: Z9 y$ z1 E" n+ l& B                internal.SyncWrite( addr, data );2 S4 N7 z$ s- P* q. a+ q8 k
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 ?3 h. I' Q; a7 m        }
% V" l) R6 c' u+ |% t- O9 L}
7 O" O+ [1 [; {2 A
3 j, v: P6 O4 |$ H& hBYTE        APU::ExRead( WORD addr )# V! U0 R( Z7 D. |/ \- p
{
# a9 K: c+ i& U" pBYTE        data = 0;
/ y/ @/ g; {0 P0 P4 {+ m
8 x8 U. r( N- f0 x  c        if( exsound_select & 0x10 ) {
1 ?5 ^+ f- A$ }+ W& g                if( addr == 0x4800 ) {
, J% @$ V/ k7 I( o! {7 H                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 Y: p2 g; z8 j. g. S0 \( ?                }6 K3 a5 v: q2 Q
        }
' S  K4 N2 |/ `3 W" ]        if( exsound_select & 0x04 ) {9 B2 _! h3 Q( |/ H& ^0 w" x
                if( addr >= 0x4040 && addr < 0x4100 ) {
8 [" y! a% Y1 {6 k6 g+ b                        data = fds.SyncRead( addr );
8 k0 k, J0 L5 d( P. }                }
4 V: {% I9 _" U# A3 T3 Y7 _# i. ~( I        }
4 o7 I$ Z' t4 q# H; z% e8 W        if( exsound_select & 0x08 ) {
5 d1 ]1 I) d' `$ O- k                if( addr >= 0x5000 && addr <= 0x5015 ) {* R0 }2 W* g9 B* J7 I$ w: T
                        data = mmc5.SyncRead( addr );5 {# [5 E5 H: R! k7 l
                }5 t& _  l  M2 R$ E5 \8 b8 U
        }
* T" n( s3 k' G' ?: u
; h- G; Y$ P. `6 M+ o# W) B* v        return        data;# Q1 w& |  ?( [8 z; H
}
7 J; M9 ?  W7 \+ I7 |
4 G3 F* h: p* Z- J2 e, Uvoid        APU::ExWrite( WORD addr, BYTE data )% x" _. M: s& E+ K* d8 L% ~& p- d% d
{6 Y3 X0 m5 a  F  `8 i7 i- Z4 k" _
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# X) o: v" y& M) v9 t) ]+ c: W, w$ G& B4 w& W
        if( exsound_select & 0x04 ) {
0 T& L2 W& F3 Q! ?                if( addr >= 0x4040 && addr < 0x4100 ) {
5 V5 Q' E5 H* {9 `. C6 ]                        fds.SyncWrite( addr, data );
5 _: s& v& N) ~5 w& i                }. l0 b4 z" _  H8 p" d; q! s1 }* @
        }& F# Q2 Q9 U8 Z* z- p# o3 J
+ [3 b" f* R9 R. |+ [
        if( exsound_select & 0x08 ) {& f8 J9 n1 y2 F6 p# b
                if( addr >= 0x5000 && addr <= 0x5015 ) {5 P0 V! K4 S! E; b* x9 l
                        mmc5.SyncWrite( addr, data );' ?$ d$ Z2 n$ {# Q: f$ _* a, p5 ^1 _
                }
6 N% w  B% o% d# Q! N) n        }* i) ?5 E: O/ r8 f  `( s
}
& K! b0 A/ H- g2 T# x3 z# F* N3 x
; s2 i% B; s( [, |/ k  avoid        APU::Sync()" e* ?4 [! a' A3 i$ o  R$ z
{
5 z+ i$ V3 Q& f5 g) v}
3 H0 s$ _; P+ }( }* J% ]/ O5 ~4 H! O  {; c- [# m7 x
void        APU::SyncDPCM( INT cycles ), _/ `. f8 X( {1 a* `0 j" p
{9 S, H3 ?! g+ B7 F$ p
        internal.Sync( cycles );2 y' ]7 _' f$ |/ c( f4 o. b
. Q5 j0 y: d! p. [6 c
        if( exsound_select & 0x04 ) {
: `. J! K! X+ E& E' A- t( }                fds.Sync( cycles );8 V* Y4 Y5 o) Z! R$ l+ M
        }
. K- {1 c  R) A; Z, Y        if( exsound_select & 0x08 ) {/ w; h3 U+ m! b  G
                mmc5.Sync( cycles );/ R9 ]9 h8 y( f( n' J
        }
8 z' j8 f: U9 D: l}
. F9 p) x$ \8 a" H8 H( E
: S, @& J) A; h2 U! I6 I( Z! G: avoid        APU::WriteProcess( WORD addr, BYTE data ). Z7 }) A8 k( V
{- x& f7 h6 P* m* o
        // $4018偼VirtuaNES屌桳億乕僩
5 V- _# t( j1 P/ B  n        if( addr >= 0x4000 && addr <= 0x401F ) {; [& w% Y. y3 B- x
                internal.Write( addr, data );& P" ]2 i: L9 d+ D" e, o/ `1 m
        }  |* j8 z8 G8 c* Z  q
}6 k: s2 ]# T$ I, C/ c
  a# V4 q6 H( S- a
void        APU::WriteExProcess( WORD addr, BYTE data )+ e0 z: m7 H' Y
{/ E9 p) z7 v# B3 e3 T
        if( exsound_select & 0x01 ) {$ p9 Z- w- k8 [& [- f
                vrc6.Write( addr, data );5 y! ?  S3 W% M0 |3 Y2 U) [2 X
        }9 P% s$ F7 `& [: S/ z% d* B
        if( exsound_select & 0x02 ) {
3 {7 S  H8 m: a" y$ ~8 a                vrc7.Write( addr, data );
, X4 {' ?* }- E3 m( U) A1 p  [        }- H! ]5 H1 x' \2 T7 r1 f
        if( exsound_select & 0x04 ) {: X# Q4 _. E; g- ?' J! P7 j9 i, U- c, b
                fds.Write( addr, data );
4 j) I8 ?% V; _3 ~9 l* V5 e        }
% l+ j& p: U% i$ M5 T        if( exsound_select & 0x08 ) {0 y! [, k+ j! f5 B# O) u3 ~
                mmc5.Write( addr, data );
' d8 |! |4 W& t: Q        }3 {3 A3 i" t0 r4 V
        if( exsound_select & 0x10 ) {
9 @/ X2 D2 K" @                if( addr == 0x0000 ) {
" P% @) x# G5 ^6 @5 K( ^$ E                        BYTE        dummy = n106.Read( addr );
2 Y6 F! y; U8 R$ r. p7 F+ d8 Q( X7 G                } else {
! f& Z4 ~/ ^8 J' f; |                        n106.Write( addr, data );
. H! r1 O9 A- ]) k: H                }* l2 K) e2 I9 h* V; ~- W
        }" _5 i7 ?3 ]7 o# q4 o* f
        if( exsound_select & 0x20 ) {- Y# D2 W+ S0 s2 F( y
                fme7.Write( addr, data );9 g4 Q4 x/ D$ g0 o6 A( }
        }
" t) K' y. D6 h; O; ]7 j}3 U% o6 o9 m; g8 L

7 X. ?, ~2 ?9 [7 x& {void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 l* I$ v5 z# J) n* `, q$ k3 @
{
' @* e7 k9 b3 j, K+ X/ AINT        nBits = Config.sound.nBits;
% M7 M# N- i  T* tDWORD        dwLength = dwSize / (nBits/8);
. T! h3 C6 `/ R- XINT        output;
% h$ }' ~( w* R3 a; X% ]QUEUEDATA q;
& v7 k/ l2 Y- t4 d9 j( KDWORD        writetime;: h$ N' L2 J4 z1 m* W+ E/ d2 T2 `. ~
' ~! C8 M. U' Y: [
LPSHORT        pSoundBuf = m_SoundBuffer;1 u  U9 e. Q% C( F# K
INT        nCcount = 0;
/ X0 a9 @1 S. ~6 K
; I! w0 }' a! o% H6 aINT        nFilterType = Config.sound.nFilterType;, ~' ~% ~- p) M. @

/ l, I+ Q0 P; }- e0 M2 Y        if( !Config.sound.bEnable ) {
  }, y# D! L/ R4 ?0 m/ `" h                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );& p. ?' c0 e- F5 J% k  D
                return;
' W. G9 Z9 ~1 B" _+ o        }+ X4 X2 K6 ^, k" i. J! B" ~
5 _3 b. h+ _0 o) f# t" M
        // Volume setup
0 l$ w$ D0 \6 ^/ Z$ U- }2 m' q        //  0:Master
9 p" d( p! f- ?3 e! Z        //  1:Rectangle 12 E" {0 ~2 O: L6 `
        //  2:Rectangle 2. \: e! k4 a: d
        //  3:Triangle
; [: J' H  Q, y$ Z        //  4:Noise9 e. f% F8 q7 R6 x& {4 I
        //  5:DPCM
/ u% B8 }) x4 n- u  `+ h        //  6:VRC6# l4 C% ~5 ^* `; O: P/ P
        //  7:VRC71 L8 l# z, m2 r
        //  8:FDS: y1 y1 P$ c: R+ c/ L
        //  9:MMC5
% j5 U0 |, t% m' y        // 10:N106& u  L4 T, P) Y# k4 u9 F, }
        // 11:FME7
' w; p, M1 }  Z" i0 ^8 ?7 @+ n        INT        vol[24];
: g! i% W4 u7 \1 h& [, {& j        BOOL*        bMute = m_bMute;9 F1 q. S+ i% M
        SHORT*        nVolume = Config.sound.nVolume;
) u# h) Z8 Y  `) S5 Z( p( p1 @9 J
1 x0 M  a6 ^- W2 T9 |2 b$ P7 J        INT        nMasterVolume = bMute[0]?nVolume[0]:0;, H# m* T! k& L
, R6 R. I5 w, u+ J7 u
        // Internal
% ]4 H, K0 M' X8 R' ?2 O        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;* W+ E, g: T7 X6 U
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 Z% @0 t: {. P, x) J+ B        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 _! n7 T4 k9 Z( S: Z( |  S
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
8 g* t" P3 g0 `* H        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
( v7 A* D& R  ]1 N0 x8 y
! U: u2 \! \/ \! m, B        // VRC6
' x/ x* O4 N  l% i        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- l5 r5 _: T/ `  O8 r        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;' R0 g  m5 `4 C! P  ?: c7 p  c6 a: X
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( ~/ k" T1 x5 u. _+ Y

  l! `) x' J/ @9 ^1 Y        // VRC7* F/ ?! j" e6 K6 i! Q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
4 M, n, X7 F, Z9 i" [2 G8 Q
7 P) Z4 {+ r1 Z        // FDS
6 w! `$ X# p) g' Z4 S) x, E& S2 w: o        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;9 \4 L! w7 ~$ l3 {4 `
# E- e$ ?0 g" e: k" y; Y( `
        // MMC5* b0 X2 v5 j/ q7 s; i
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 Y5 V$ m/ C) U$ C0 @7 j# k
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. J7 H- H/ x0 a* ~( U
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" r+ P4 v: G# r0 f4 w  w7 @1 O4 S: X$ r% D; k( |: E5 N7 G* o& L
        // N106
' e; |) v8 {+ B) {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 o+ B, k! H5 a        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 ?! T7 C) [  g' f+ ^- ^( ?, N* d% J
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 [5 f/ M# D9 I* ~3 M0 a        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& m) {% e6 k' t1 T        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  _2 V6 J: l9 r5 R# a+ E& V1 S
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 W' u: o8 B2 J" T
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 d- \( n3 s3 ?3 F- c0 j, u/ ^6 H        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# k3 g  i! h6 y! r
4 r. b7 K. D, \9 \) m
        // FME72 ~# G( e. `( W/ N: M1 E' W
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# D% ^: n5 j% W8 E$ O
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" w& I$ v: u2 @) @5 ?
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( v% q) W! e) F1 N3 ^) F2 s: r
% t( t; K% A" d' j4 X2 ^7 S0 `6 b
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 J9 ]! B! k5 G! o6 T1 p' A
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
4 }# Y: v, u. q# n4 V$ W  {) @2 B8 b+ G6 t  }$ v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟$ S" @9 U1 ~8 S/ I- K: s: ~/ q
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
! p( H3 N+ S" f& O, l$ C/ l                QueueFlush();
) G. q$ k) B8 t4 z        }
; G' Z$ X- y* b! D# z, Z
6 h" H# y4 i8 s: G" o        while( dwLength-- ) {5 b0 }' m( U8 g$ F( N
                writetime = (DWORD)elapsed_time;
! U) @/ K  ]. U: N$ m1 K2 m
3 y8 ^, k+ t: C7 ~/ M2 i7 ]( b) x                while( GetQueue( writetime, q ) ) {
! B& m1 p& Q: S0 x4 z                        WriteProcess( q.addr, q.data );. Z$ t7 h) D& ?3 ]7 q
                }3 P" D4 W. Z% B! V5 b3 V

' J+ Q5 U0 E2 X) @3 C7 M) \. l. V                while( GetExQueue( writetime, q ) ) {0 C; E. A2 t& [
                        WriteExProcess( q.addr, q.data );
9 O9 M/ v: w9 o                }
; q6 V) R: z# _% ~0 ]
( ?# C5 r- E- k/ L# v                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 N1 @& q5 A6 o  a) N1 X6 L" m! ~
                output = 0;3 D4 z1 F- o* v. U6 h4 I
                output += internal.Process( 0 )*vol[0];* n( ?# {2 T: U. s' j& ~9 N( ?
                output += internal.Process( 1 )*vol[1];5 }' I, q1 d! B- e8 X
                output += internal.Process( 2 )*vol[2];! c  [% G& ]2 @1 H
                output += internal.Process( 3 )*vol[3];
, [+ `* P. G7 H                output += internal.Process( 4 )*vol[4];  U% v% ~4 B! [4 u4 ?8 C9 m

0 k( C# ~6 `2 z6 s2 ]" y                if( exsound_select & 0x01 ) {
& i2 k  k1 Z' E2 [" i. K3 Q                        output += vrc6.Process( 0 )*vol[5];+ d" r/ b9 c5 X8 k1 J  H% B  }
                        output += vrc6.Process( 1 )*vol[6];5 n( J9 D* f3 A; k
                        output += vrc6.Process( 2 )*vol[7];
- G# @5 K7 O$ i% p8 V6 X                }$ k! M. Z  z0 |7 N5 F
                if( exsound_select & 0x02 ) {
& y6 I1 {: _1 {) ]8 Q                        output += vrc7.Process( 0 )*vol[8];4 s7 r6 f5 x1 H; \8 h/ k! C
                }
' P. x# u8 @% U. h; i                if( exsound_select & 0x04 ) {1 h/ Y0 v( n; k! K. _! r+ H
                        output += fds.Process( 0 )*vol[9];& s) U0 A5 S: a/ |: v1 T3 [0 [
                }
8 c# K4 I# b4 h( u8 n1 z                if( exsound_select & 0x08 ) {
4 I/ \7 K5 O2 S: P                        output += mmc5.Process( 0 )*vol[10];+ O9 ~; G: ~& w" v$ ?7 u" Q
                        output += mmc5.Process( 1 )*vol[11];. P- P2 r" w& U5 E. u. Y3 g
                        output += mmc5.Process( 2 )*vol[12];- U- B: l: ]: y, T' F  u
                }
/ X$ {% h  w) v. i" i                if( exsound_select & 0x10 ) {7 _" }" c! m! {  n
                        output += n106.Process( 0 )*vol[13];
. a* z) I8 R/ E* O& w                        output += n106.Process( 1 )*vol[14];
( N( o0 J9 b8 S                        output += n106.Process( 2 )*vol[15];
' g- m0 [9 S- T1 G                        output += n106.Process( 3 )*vol[16];
' q, m% k; R  v3 \                        output += n106.Process( 4 )*vol[17];0 V. f3 g( _3 I! X- ~9 z3 x
                        output += n106.Process( 5 )*vol[18];6 R1 [1 L; J' ?. c& ^
                        output += n106.Process( 6 )*vol[19];
! `( E- A; t% J/ `# u+ c                        output += n106.Process( 7 )*vol[20];- B9 I2 i5 b: c. W7 D
                }- H1 i8 q* }6 b6 k
                if( exsound_select & 0x20 ) {- m+ W' `4 ~4 t; _; u
                        fme7.Process( 3 );        // Envelope & Noise
& U9 C" \7 z/ k9 J                        output += fme7.Process( 0 )*vol[21];6 }; d  @  M9 J5 S7 X2 G, _& T6 V
                        output += fme7.Process( 1 )*vol[22];
" f; t$ q" f4 k  Y8 L1 B; U; Z/ I5 A                        output += fme7.Process( 2 )*vol[23];$ |% Q! |7 n- s9 _) v6 p, J2 ^
                }
# L; w  L; K# t  x0 o" v; b: m9 K1 f* \7 h
                output >>= 8;' ?2 P! L: z& `1 h6 b+ z; |/ C
3 t+ ^3 `+ e2 n; a/ W3 B! c
                if( nFilterType == 1 ) {
9 k$ m& u/ x0 Q6 h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)0 f" p. ]' Y# P( N7 s6 H) N3 Y
                        output = (lowpass_filter[0]+output)/2;/ P! ?( y" V2 t
                        lowpass_filter[0] = output;
& u. Y7 S# f" |* I% e                } else if( nFilterType == 2 ) {
; [1 `3 |1 I8 P6 _6 ?( I                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
+ R* l. |: N4 N4 g' Y6 @                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 `! b$ ~& A& n: B5 K                        lowpass_filter[1] = lowpass_filter[0];
5 q* S$ [- }* i7 C                        lowpass_filter[0] = output;
* w2 |: y% v' g  _                } else if( nFilterType == 3 ) {
% A, h- U- e3 r! J                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' c; q8 g3 x$ S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! O4 ?" C- I. `: U* J9 X9 Q
                        lowpass_filter[2] = lowpass_filter[1];8 h) o) X1 N; L2 r) `! @
                        lowpass_filter[1] = lowpass_filter[0];, r6 Z) r0 ^6 {+ y+ L( z/ d
                        lowpass_filter[0] = output;
9 P& H& B2 ~" L$ G                } else if( nFilterType == 4 ) {
/ o$ v3 C3 v' C' k                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)2 w( Z7 z" c- I& _
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ L3 Z/ O, G4 }  }! a5 r0 e/ U                        lowpass_filter[1] = lowpass_filter[0];
! N% o# D, p/ I3 g: C& {# I                        lowpass_filter[0] = output;6 ~! V( l4 h) p6 s8 u
                }
' m$ ]- V6 P; m4 C9 S9 `( X/ ~: q+ ?* Q
#if        0
3 v0 K; \. ?/ J% G/ z+ J                // DC惉暘偺僇僢僩' H; c- y8 W- ~+ E9 y/ |# i
                {* g( W' Z7 b2 l  a2 W
                static double ave = 0.0, max=0.0, min=0.0;8 K# j; f9 R- f
                double delta;% Y3 D5 N* ]5 b
                delta = (max-min)/32768.0;; k/ G+ q4 N. B
                max -= delta;' n/ e. M( n( @% ]' U( E
                min += delta;, z" L& a3 R# ], ?! h. A
                if( output > max ) max = output;+ ?# E6 H8 Q7 w- h( O/ z8 h( k% q0 r
                if( output < min ) min = output;
4 r0 v3 W* p. Z- B/ D0 r- h+ w8 }3 j                ave -= ave/1024.0;7 B$ Q1 F- m$ O! ^1 i% O
                ave += (max+min)/2048.0;
7 g; W6 S& p; }& O' }                output -= (INT)ave;$ u7 x2 Z/ p: Z9 n. F% e( s- r% I
                }
+ P8 A  Q: w" b* R; T#endif
, o; `, }9 j. l! @. X( A#if        18 d; A* i6 }: H; E* Y% e- k
                // DC惉暘偺僇僢僩(HPF TEST)
; o% O" Y% a  o: Z5 m; R3 _6 C                {9 ?0 D. H* c' }8 j
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! p0 v! _  b  D% X" P- `, f  O                static        double        cutofftemp = (2.0*3.141592653579*40.0);  M% \& [/ h* |! W
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
3 V9 q8 X$ _* S6 Y                static        double        tmp = 0.0;
2 h7 }! W% g" u* m1 a, H6 l- V                double        in, out;7 p0 {$ g2 c& u9 l4 X5 f- ?

3 l0 w8 M5 w3 U$ q) [                in = (double)output;# Y" R. b8 f* p( Z* k; ?
                out = (in - tmp);
2 G2 o' f5 j4 r' X9 r7 w6 k3 }  D                tmp = tmp + cutoff * out;
0 H  G( w. \. Y8 i% q* @
, a) W  o+ r5 v& W                output = (INT)out;" d9 g$ w9 [( N. e
                }) n. g# B. ~! A
#endif# ^9 |, i0 w" z% b  u( v: N" n
#if        0' T& Q9 \" H0 I- z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)$ U; R, G) w! |7 z; s* A
                {3 A7 Y- G# B+ v) S: Y, [
                INT        diff = abs(output-last_data);7 V6 G% i  |3 I
                if( diff > 0x4000 ) {
% f; h8 @# K, B/ V                        output /= 4;: i! b1 E! \& E0 r1 V" O9 ~; d
                } else
* k& w* z, C/ v2 `+ F( Y# \                if( diff > 0x3000 ) {
6 J) i; a6 y* H- |2 j                        output /= 3;
# S: N" @% [# g* M8 ^' ^                } else
! t9 v/ d: ], P4 l" L! _                if( diff > 0x2000 ) {
/ `& P& `5 U8 N' P( O% h                        output /= 2;
. o) `) {" J7 [; H3 O: ?                }0 B& {6 g' b1 q* E. e/ I1 `  L
                last_data = output;" q3 Q+ P  Y# g* ^# C
                }6 K$ L% F2 }" C* i4 N. Z
#endif
7 A/ r0 p$ h  t6 d8 U$ G; s1 t/ d                // Limit
+ K+ @2 n( [* c0 T$ H$ C  H                if( output > 0x7FFF ) {6 \8 g: s: V& [& G$ C0 j! h
                        output = 0x7FFF;- _; C5 V- ?! a( K5 \5 c. ^
                } else if( output < -0x8000 ) {8 p! v. l" {" A# ~& P
                        output = -0x8000;% }8 O3 e1 U, q; k
                }
6 j) Z9 A! v* n; {. }7 L. R. A$ E6 }2 [
                if( nBits != 8 ) {
  M! \0 q* O' c5 m8 S) `                        *(SHORT*)lpBuffer = (SHORT)output;% Y( y7 Z/ Q0 j: [" C
                        lpBuffer += sizeof(SHORT);
6 N/ u/ N- d, k# b3 r; c7 W                } else {  K0 c" ~) b( x, D% J1 k
                        *lpBuffer++ = (output>>8)^0x80;
) K, T. H& x& P* U                }
9 g( D+ h  u" G& w6 W: a
6 v4 P  V" z5 L                if( nCcount < 0x0100 ). R( i3 S0 R& a/ o
                        pSoundBuf[nCcount++] = (SHORT)output;
, S( D; s( X; I
8 d4 h6 z6 C/ n  Y) W//                elapsedtime += cycle_rate;
& H3 T# b& J* g7 S- U! j# V                elapsed_time += cycle_rate;
: D( U* X+ `* b( r! {  }/ g        }) A/ ]7 ^0 g7 n% O
" J0 X  m  W4 @: k$ K& T$ N, f
#if        1
/ l4 z. n8 s$ z$ j: J' h        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
5 Y$ L. p( ?1 f- z                elapsed_time = nes->cpu->GetTotalCycles();
- Y# S) m5 e' ]( V2 o        }' ]8 f! g+ t# r4 \
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
% Y% [3 i: C9 g% X+ X; z                elapsed_time = nes->cpu->GetTotalCycles();
+ }- @+ F" X5 o+ \        }
+ a/ i5 P# _& H0 [1 s5 z#else
. h5 z  ]* x" v. [/ V9 v        elapsed_time = nes->cpu->GetTotalCycles();
0 `- Q5 c/ ^* |, \6 H' V+ Y8 v& x#endif8 F; ^3 a4 s+ e* C3 W; _0 O* w
}; B6 x3 Y( u* R: D4 b
9 k, M6 p- X5 j* e+ R5 e- \" L0 O' x
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)3 w- x5 C" R$ l: i" e2 I; N9 x
INT        APU::GetChannelFrequency( INT no )
2 a$ u; X3 s' P& a  w0 T; z{
7 b' Z8 |) o/ R% ?, w2 X& F/ V        if( !m_bMute[0] )
, t( C# M3 [7 w, \                return        0;
6 N( Y5 E8 |% c1 t3 H- p4 N( @6 ]3 p- U
        // Internal
& Q* p! M' s4 c        if( no < 5 ) {
# \7 p: W* ]$ O! m! j8 o" F                return        m_bMute[no+1]?internal.GetFreq( no ):0;* R) H* q5 w1 T; P5 {
        }
/ S7 [6 P6 i$ g' t0 f/ P9 `) [        // VRC6
! V/ A& `8 P! w* h) Y2 c+ [        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ w/ Y2 h% m- Y7 k                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) w7 g, z8 \) [: o, T# P
        }0 ~. j& M& o9 y& L3 H
        // FDS- r/ _  f0 g# ~! p9 C
        if( (exsound_select & 0x04) && no == 0x300 ) {
& [' S2 L: U" h4 k  f+ _7 u                return        m_bMute[6]?fds.GetFreq( 0 ):0;; `1 X! A$ z* u
        }
& P3 j* h$ o9 ^4 N" v- I        // MMC5- N& V+ Z, e/ o' ]: A
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
3 Q$ W3 |- g0 g& |                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;! B3 e# a/ {  A. j
        }3 V3 t2 B4 f% h; T& p! O) C$ a" H2 i
        // N106
! e3 I6 C5 m1 g6 J2 X        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {8 H/ x2 |8 _0 p' V" w
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
4 f, Q4 |$ y, D$ J# B; B- ?        }$ u* j# H5 l0 u. ~
        // FME7. B1 k4 G9 ]9 T1 Z. A" I3 {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {1 x9 O" H! ^1 o! t1 e# I
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' C' C$ W# V+ O4 Y& H        }
5 e0 Z! l, D. o        // VRC7+ @9 t! g! J" ^8 T- {6 y" ?
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {* K  B/ f# D7 d3 j$ p5 e0 C- t
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ L6 F, @7 Y  G
        }/ `4 W% i/ X9 L/ c4 p
        return        0;
1 o# `2 l& R4 n3 G}0 U) C" _  O* y( d- N8 X( X1 q
* M1 p& l7 ~, t& y1 n- l' W7 O: W
// State Save/Load. D" E4 C8 I! Q( ~
void        APU::SaveState( LPBYTE p )6 c5 u0 |: M1 F: a' K& n3 H" k, i
{
- p. ^$ p) X/ y% \0 w#ifdef        _DEBUG
, \# r" J6 b* NLPBYTE        pold = p;7 L- ~  [+ I+ [6 i9 n2 }
#endif6 A4 N# D# C: _/ o  L) t5 E6 C

, a0 m4 k5 H1 v6 @( K( ~        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- f7 s+ R. B; s! q, D& L) ]
        QueueFlush();/ I+ x3 i5 f5 \0 b( O: X

( L8 G# c9 ]; l+ x        internal.SaveState( p );
2 Z+ Q* A: _2 U4 d" y' O% j1 w        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. s$ |5 J+ d! D" L  _% n( T. F
4 g; y5 j+ K# Z5 ~7 G4 v        // VRC6
7 a, ^. C: O0 ~2 u" f8 x+ K        if( exsound_select & 0x01 ) {" N4 T. m2 r" C8 B& W
                vrc6.SaveState( p );( J/ x; Z# _2 A+ |6 m: Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 D+ w) d% `/ k8 h9 }! o+ ]4 z        }* G1 _3 T: E: s% s' ^" x
        // VRC7 (not support)
; V$ ]3 m& q, [- ~0 W9 e# k        if( exsound_select & 0x02 ) {
7 i! `3 ~4 N+ @* p% k                vrc7.SaveState( p );6 T# o- J8 Z  I" @& w
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ n( u! I2 u, X3 g1 `
        }- d: ^/ D( P! P& c, z1 N' L2 E- X- `
        // FDS, S( D. B9 M) e8 V* ^$ x
        if( exsound_select & 0x04 ) {1 _& E' E0 v. t* I! @
                fds.SaveState( p );  N9 [1 w1 N6 Q2 {9 ~) z/ o4 U
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding; o$ e. @/ V* H
        }& U8 C& L1 P. V1 f8 j3 U9 i
        // MMC5
$ |  T) D/ l1 s        if( exsound_select & 0x08 ) {3 i; {8 f5 T6 r% I, i8 p+ N+ ]4 ?
                mmc5.SaveState( p );
+ R  f7 i& H1 M* H  j                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 W  e! U0 ?% @1 V2 W( ^: H- J" i        }! n% V5 ~; l# s0 }7 o
        // N106
7 T  i8 H1 E! @/ q) }( o2 a        if( exsound_select & 0x10 ) {
8 n- M& k* c( q3 Y  y) h( m                n106.SaveState( p );
4 I' j, ]$ J  i3 d( w                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
9 K( ~; c' i5 `2 ~! n3 j        }! o: i4 u6 `( N
        // FME7) z/ A; a; v6 j4 d
        if( exsound_select & 0x20 ) {
7 v6 M( y# D3 P, g: r4 N                fme7.SaveState( p );
& t% O, [* a! C* m. }  z                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# ?+ C7 R1 R4 W1 U, P& D$ y        }4 {' e- }* v+ }, M
3 y0 l. b4 N4 S+ S2 V
#ifdef        _DEBUG8 ^: J' X8 P0 ]  t* J, n' q8 t
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );/ [9 @/ f3 M/ V+ o
#endif: o! ^6 X* t" U/ }' R0 U/ b5 ?
}; E; W  X, N6 I- A# I, _# x9 c" d8 F
! k; N$ C3 u) W- |6 x) V7 F' u2 {
void        APU::LoadState( LPBYTE p )/ L7 C% {+ {- H5 G+ ?
{
1 B* Z8 V8 R8 d        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
, r* d. N" s3 b" `        QueueClear();* U% T8 H6 q+ o9 ^( I
2 W2 {0 D3 D' S/ ?1 g* h5 w# n
        internal.LoadState( p );, c( x0 J6 `# ~0 E6 I
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ N1 ]) L9 X/ a* y- l
9 p0 H( s8 ?! p        // VRC6
5 n) Q# }  T; N        if( exsound_select & 0x01 ) {# J+ ?9 D' K2 h
                vrc6.LoadState( p );
( M" G* o/ Q9 n& |* T                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, L0 v) n) [+ i* {" f
        }
! S% k8 o- g6 r; p/ F: @" `4 K& p        // VRC7 (not support)/ i! h9 x% D0 G; J) P3 }3 K$ \; T8 `
        if( exsound_select & 0x02 ) {
# |! r9 s; h( l7 z                vrc7.LoadState( p );
4 k8 d( s2 h4 N( h, \0 G                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. L/ q/ j& b, ?' C& S/ p; j        }9 g& z3 p5 y7 t0 f- a9 L* g- L
        // FDS8 a; Y  r& Z0 u2 O3 N
        if( exsound_select & 0x04 ) {
+ A4 T5 o8 r2 M! t: Y$ p# C& Y                fds.LoadState( p );
6 L6 @$ h' H! q' b                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# n1 ~/ u& R0 h4 e0 H9 S! `8 I. `6 ^1 h
        }
, b4 q! \# l. f% z        // MMC5
- j3 U$ K# w- e. {2 j: S7 w        if( exsound_select & 0x08 ) {# P4 m/ @1 @* i* i' f% h+ B
                mmc5.LoadState( p );
; S; Y3 [6 c* h$ \+ Z3 g                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
% U* ~0 G2 u5 C7 t) _2 T+ @        }
0 `; j$ ^( e/ J7 f7 |! D' H) I! @8 w        // N106
' e" S' o! @* _7 K& }) X5 d        if( exsound_select & 0x10 ) {# F. [% p; A0 P# J
                n106.LoadState( p );( P1 o1 J. a* k2 d0 c1 ^' M  t" O
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding" `) M  o$ N2 z; ^: {
        }+ z( g8 L  c% Y9 H
        // FME7
8 K! ]4 e: j5 X- s; G$ e        if( exsound_select & 0x20 ) {
. J: [0 s4 B, ^& d7 N                fme7.LoadState( p );. _6 K- m+ o. P3 O5 u# d4 Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 B8 {( @6 r( v
        }
* ^. ?4 ?; {" c6 R# R' l}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 q; L$ K7 q" _6 ^/ V% F2 Z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! g8 j2 I4 `$ r+ m3 P5 K
感激不尽~~
) ~1 E1 u1 k4 m" V' ?" |6 ~
恩 我對模擬器不是很有研究,
. F" _  b% U6 I/ b6 w6 B  ~雖然要了解源碼內容,可能不是很困難,/ |0 |! z' L+ _9 a
不過還是要花時間,個人目前蠻忙碌的。) e. \$ [/ ^; D7 N% p3 u

4 `# F6 t1 K; ~給你一個朋友的MSN,你可以跟他討論看看,  u4 M" s; z% M3 v$ T$ [0 F
他本身是程式設計師,也對FC模擬器很有興趣。
% T, C1 X: _3 \: R+ w4 A' i9 S9 _0 d. j3 ?5 i
MSN我就PM到你的信箱了。
2 \! [' k. B' H2 v# N8 [1 v* K
, h  P" ]) ~4 [希望你能有所得。

该用户从未签到

 楼主| 发表于 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 l# n  G% z5 M: `) y. w$ g% R7 Z呵…… 谢过团长大人~~

# n4 N* {! I$ ~
1 \/ ?4 e6 Z# u2 _哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ' o6 t8 R( l, q. c5 l
团长的朋友都是神,那团长就是神的boss。
+ G: S3 ^, D* X% p# ]3 D
哈 不敢當,我只是個平凡人,! O" l  l8 Z3 @( s& s0 Q# k
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  w9 }# K; Q4 f) C' z1 i2 g& u8 r
ZYH3 X/ {) `3 k" m/ I, Q6 ]; K' ^
QQ:414734306: r! S0 v' w( b' Z
Mail:zyh-01@126.com
4 U- A5 _8 f) B
5 h3 n' n5 J+ ~他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 " \6 ]! S/ r& ^
再次对团长大人和悠悠哥的无私帮助表示感谢~~
% p$ f5 L' @* B5 R  e( {% H
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 15:05 , Processed in 1.062500 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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