EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% M, r: [! {- h0 e! C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 m1 i$ f& H3 U, r( W/ b4 P
这里有相应的模拟器源码,就当送给大侠了~~
5 L' A; S. x) r$ [( t6 uhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 f8 L4 @4 ~9 O  c
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 ]# V- T+ q# P# L) ?; w$ }楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 W6 X, o( o/ E+ u' |这里有相应的模拟器源码,就当送给大侠 ...
; B0 h' T6 E- K! J3 `; t
聲音部分(Audoi Process Unit = APU):. X, Z8 z& D' J6 _% F
.\NES\APU.cpp  e) t  w: k; U/ T( X
.\NES\APU.h
5 Z) P3 v% U$ U7 ~2 B! n6 c2 n; w  Y7 U4 X! `- ^3 O0 i
; X% m! {8 K7 K* Q- e: A; u0 ^
影像處理部份(Picture Processing Unit = PPU):
# Y( ]7 I  X8 P% p- D5 S5 [.\NES\PPU.cpp' h) K& B& R0 w) [$ [. Q# M+ A9 X
.\NES\PPU.h+ t5 a4 u+ m2 Z$ M
5 v1 {: m7 Q! f" k
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
. s/ [! Y# z. j! ?1 A' a+ V1 k, G' w(由于很多专用术语和算法机理都不明白,所以看不大懂……)
* r$ M% X$ X. E! i* g//////////////////////////////////////////////////////////////////////////
' e- b5 g1 d4 f# O, I- H. N* s0 S//                                                                      //
' k7 c+ r- R# R  @9 |% o9 j//      NES APU core                                                    //+ p' g( r: ?* f* k; ?7 X
//                                                           Norix      //9 P# V/ T/ ], R- r9 m
//                                               written     2002/06/27 //
; q. k$ `) b. E+ _//                                               last modify ----/--/-- //2 T# A9 Z0 H3 U6 T5 a' \
//////////////////////////////////////////////////////////////////////////! y3 H/ c2 t" ^' k" V8 J3 `+ k' _3 z
#include "DebugOut.h"
( P8 j; F! x" {4 S2 B* H- D, }/ {9 I#include "App.h"
- F$ O0 j! A, }& e6 r3 D8 Q#include "Config.h"
, _: M. K; I, x0 o' |: ?! K$ y% J+ T2 l4 @
#include "nes.h"
$ s8 q3 H% d3 _% X5 T* u#include "mmu.h"' l3 K5 V  e( B# u( o
#include "cpu.h"7 w- U1 A: ]0 d" r, w7 I9 S
#include "ppu.h"
; C# @9 r6 o. d0 L7 L#include "rom.h"
/ \3 [7 u6 H; j) r- a) `#include "apu.h"# V# Q+ \- Y7 o3 y, }* K# x/ O

. r2 ?  j- \1 F7 g// Volume adjust
1 I4 E8 Q9 ~& F% a2 @- I// Internal sounds5 L. E; Y( Z) X# T# w. R5 |* Y
#define        RECTANGLE_VOL        (0x0F0)
- ]# U/ w# I% y4 ?& m5 t! l2 S#define        TRIANGLE_VOL        (0x130)
' ?7 Z$ {% v  m/ I/ }# Y6 J% @6 B4 j#define        NOISE_VOL        (0x0C0)
1 u) |0 X6 B, @  S) D9 h#define        DPCM_VOL        (0x0F0)# L: n  N1 L* L+ J9 ?, ^( g: Z
// Extra sounds
4 ^  r3 u5 {2 |% V#define        VRC6_VOL        (0x0F0)
) Z. n) o! z  }7 Q#define        VRC7_VOL        (0x130)0 ~/ @5 G, w4 X4 m9 ^
#define        FDS_VOL                (0x0F0)$ n) E+ T% o) M( H( h2 H3 ]
#define        MMC5_VOL        (0x0F0)6 Z, F4 w0 ^0 Q( y5 \( t9 J
#define        N106_VOL        (0x088)6 Z$ P7 S7 G& ~; p7 h! _5 m
#define        FME7_VOL        (0x130)9 J- j6 ]/ P' B1 j" J+ z
0 u( M0 ?( R7 [! n& |3 L
APU::APU( NES* parent ), ^" R8 ?" {" w9 H9 r$ p
{
+ T2 p& z- q5 B2 b( t. ?) G1 c        exsound_select = 0;$ z1 l( j2 |0 }8 d' t5 y! V/ t( N

' y, F9 v, k6 q- x9 k        nes = parent;
( z: p  m( H9 U4 _8 R5 _) l        internal.SetParent( parent );2 D  J* t9 `3 `6 O5 I3 \5 M

, w! a$ y; ^3 V' @8 E/ L  \        last_data = last_diff = 0;4 m- b* I) w( c- d- z8 Y; I

0 G, c$ W' \( y/ [$ u' c" C        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) P- Z0 a) T6 l9 s9 u  V7 S/ C
* J1 f( _9 s+ ?6 m
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- l5 T6 j% ^8 s9 f        ZEROMEMORY( &queue, sizeof(queue) );( `0 A5 w9 j( g; _9 _" N2 B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. Y( J, @$ n/ c" O

4 B$ d0 U, {& {4 ]2 a/ C3 m        for( INT i = 0; i < 16; i++ ) {
% o: z* B) T3 s) L( ~! S                m_bMute = TRUE;( {3 }- M2 Q4 p- |! e$ U$ s
        }
0 Y4 K8 V; a1 A2 S3 ^}
% u& |% E$ U8 ?8 q3 d7 L) Q
# T; H# B7 n4 G5 b' i: zAPU::~APU()9 Y/ |; I/ q8 P6 K- B6 G- D
{
  N# J7 a5 r% l9 H2 q! U}. ?& r  r( J; I) k4 l

4 j9 v4 A* e- f9 o+ T; Uvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
/ c6 q) y) C$ V% J+ m5 z1 N{3 ?' w: e' L0 s" J# a+ n9 A7 `" A
        queue.data[queue.wrptr].time = writetime;+ a' ^9 X) a* Y1 E/ ?# i2 Z
        queue.data[queue.wrptr].addr = addr;
- R9 [5 i0 J  _& C( m$ \( `        queue.data[queue.wrptr].data = data;
/ A' }: W( q& G2 G( z& ?        queue.wrptr++;6 L1 ^0 i- f$ |. C
        queue.wrptr&=QUEUE_LENGTH-1;  P3 w( O( U& Q1 ~$ p- |/ I$ l$ [
        if( queue.wrptr == queue.rdptr ) {) r1 h* ^; g8 L/ q
                DEBUGOUT( "queue overflow.\n" );
, Y8 U( d9 G, I        }  a5 U' V, r9 s/ K  q) L
}
1 E( ^0 w* S0 }: ^, B/ T
9 n' \6 W3 w: Z' O# {: a. DBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: s3 y. ?/ h, v2 B4 V$ A& T9 \- ^4 q{
% i% P' h/ }+ o0 S% g7 E( x        if( queue.wrptr == queue.rdptr ) {
" B7 A9 x$ b$ W$ a* `                return        FALSE;4 p" L! g# y1 H* @; I
        }2 v% L: T/ l  ^- V3 _( s9 k
        if( queue.data[queue.rdptr].time <= writetime ) {  ?) f- G0 N2 u; I. r
                ret = queue.data[queue.rdptr];
  c4 Z% {+ y0 G+ m3 {                queue.rdptr++;
9 D) w. L$ z. \0 i2 n. `                queue.rdptr&=QUEUE_LENGTH-1;
6 ~# h  t; G5 n" N# f                return        TRUE;
" v' p" r1 t7 Z% M* Y: h  H6 F        }
- S, X* X9 X2 M  V; q        return        FALSE;
6 A3 _% L0 s8 E' m}
5 }/ N  x: N4 U
6 }$ `4 l/ J4 P/ s. @9 dvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )6 `  X1 E4 W& z- S* t) T7 u
{
, u3 ]) W6 d1 d4 n        exqueue.data[exqueue.wrptr].time = writetime;
4 l1 ~; p8 C2 ]        exqueue.data[exqueue.wrptr].addr = addr;1 m! I( r- ~# `- |4 ]
        exqueue.data[exqueue.wrptr].data = data;
3 D. y( ]$ v2 n        exqueue.wrptr++;
  N/ a% R* d5 a        exqueue.wrptr&=QUEUE_LENGTH-1;; G  g# D* [2 e. D3 G
        if( exqueue.wrptr == exqueue.rdptr ) {
' {* L% \2 N0 \6 r) d) P                DEBUGOUT( "exqueue overflow.\n" );
  w3 i% w/ P, ?3 n, P" \8 b        }
, O& W: }; r5 ?% I}: ]3 ^2 E3 H% _) ~1 M3 D; [) L. }. L9 z

& s% B9 W; k6 w0 i/ v1 m4 T6 VBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
$ ^. L! w! a  U{' P: b  {+ s6 u) f0 C) z+ C
        if( exqueue.wrptr == exqueue.rdptr ) {
! W" C! z* D( p: s0 G1 @                return        FALSE;
/ {' j6 L4 G! f7 P        }9 I0 D3 I& Z3 f) B; W. \4 X- y
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {/ V  t$ `' A6 l
                ret = exqueue.data[exqueue.rdptr];+ x) y5 j: k4 x, c
                exqueue.rdptr++;& N& S6 V9 X7 x+ |5 n, B) B
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 B# E7 S/ ]( I' [1 Z                return        TRUE;0 _. p6 {# p3 X% o, u2 R7 k
        }, \3 ?8 X6 ?/ o! P' e. O
        return        FALSE;( o% Z) c8 B& l/ a
}: A. M! B/ s% @7 b

) W/ S, S- O' I5 k/ n$ a% R& Gvoid        APU::QueueClear()$ r/ r( P; f4 z6 R6 z
{
1 I- h" ~- J5 J4 Q( M8 _' W0 x4 o        ZEROMEMORY( &queue, sizeof(queue) );
' j6 o3 ]7 N5 R1 G* A6 A1 C( K        ZEROMEMORY( &exqueue, sizeof(exqueue) );' a) J3 X* n6 p3 B$ ~
}7 Q2 j$ }' |3 H1 M7 d

  \4 \2 g: O) K) O1 avoid        APU::QueueFlush()
! z! T2 f% \$ G; p{
% r) j9 q% R- p' }0 w5 j        while( queue.wrptr != queue.rdptr ) {
0 o7 B; `. c: w2 F( R3 J/ K/ s" a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 L3 V6 w) G* @0 q  b
                queue.rdptr++;
8 S. m( c8 P8 I! p: @" {                queue.rdptr&=QUEUE_LENGTH-1;
/ \5 k, ~/ x' W' A0 _% l% Q        }4 {6 d% x0 |( R+ ~4 D6 Z

2 n  ]; ]% m8 K% z) T        while( exqueue.wrptr != exqueue.rdptr ) {% m5 h' j9 H# S- r
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );& x& d) ^. J. M& t
                exqueue.rdptr++;( y2 x1 E5 |/ p- n. @; P
                exqueue.rdptr&=QUEUE_LENGTH-1;6 m  B' g5 ^8 @  T) w1 s
        }" Z0 p& M9 f2 R! Q5 x: D) B
}
+ h1 ^: u. V& ~7 s, A
, R& V9 T- O- |/ Y% _void        APU::SoundSetup()$ j9 }( W3 Q, f8 V, \3 m2 y( [
{% G7 k; N! u( x* e( }/ {' @4 M
        FLOAT        fClock = nes->nescfg->CpuClock;
6 j0 J5 J& a) }        INT        nRate = (INT)Config.sound.nRate;; e( [' m. A" n
        internal.Setup( fClock, nRate );2 j  r" V8 h/ A' Z+ z
        vrc6.Setup( fClock, nRate );
6 `+ f$ q5 C' z& L7 X9 F- p% Y0 L+ i        vrc7.Setup( fClock, nRate );/ m- ~" s- a( g/ n
        mmc5.Setup( fClock, nRate );0 u8 I; Z" V5 r
        fds.Setup ( fClock, nRate );
+ u4 k; K$ o: X, Q  J2 \        n106.Setup( fClock, nRate );
# o! R) s% s* U/ }$ a- w6 {        fme7.Setup( fClock, nRate );
# d, ]% ~0 Y8 R/ W3 `( a: N- ~}+ P$ U; g: [6 s6 g+ B
! n, \5 S# r8 u2 k3 I1 ], J
void        APU::Reset()
& s3 j4 K* _* \# z2 A- `, G9 O{1 I3 k; i, W3 ?! }3 V! g
        ZEROMEMORY( &queue, sizeof(queue) );
; r! ?) p/ j/ {        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" ~! N+ c% g7 f+ R$ Z/ }9 s" e5 i* p6 g, j$ q. p$ k
        elapsed_time = 0;* G& b0 i$ i  |- b1 a9 ^4 W! _3 x

! ^1 N6 M- w# S  z0 D        FLOAT        fClock = nes->nescfg->CpuClock;
0 M/ q5 O- G, T' B# u9 a% d5 z7 ^        INT        nRate = (INT)Config.sound.nRate;. k  b: _1 T8 R
        internal.Reset( fClock, nRate );5 u0 S; {; j5 |/ }: V. N1 E: M
        vrc6.Reset( fClock, nRate );
' _  O% W' G# p" y: s1 w# T        vrc7.Reset( fClock, nRate );
) G3 D' p& @# G8 {        mmc5.Reset( fClock, nRate );8 h' G- h# R: l7 N; ~
        fds.Reset ( fClock, nRate );
5 k& A6 E+ Z' G6 P8 P3 j        n106.Reset( fClock, nRate );
1 b. A* b0 {' x) y; C" G; w+ h        fme7.Reset( fClock, nRate );
4 J; s& A: r5 x* f
, k9 S3 O% t8 y9 C, m        SoundSetup();5 v% Z7 h8 ^* Y5 K6 f8 I
}
  C" O$ V! O1 V/ e$ |: y1 f: }) H( t
void        APU::SelectExSound( BYTE data )3 Z: c9 V7 C6 q8 F+ j2 @
{/ U& _8 Y  P% R% r9 k; ]  O
        exsound_select = data;7 h- |: V$ h; |& A
}
2 _$ W$ E0 I0 P+ |8 x. D4 E
# ]2 @7 I& p- ^6 ~BYTE        APU::Read( WORD addr )
! z9 e1 Q$ R( o* C" y$ X4 w{
- M6 U: _1 m) N& W! B+ _: w        return        internal.SyncRead( addr );# J9 ^& p# u7 I- P  X2 N- K* u
}. a/ t( f& |' _' M$ K9 m) j  x, S
  N( A4 Z- I4 R5 _" e3 N" }
void        APU::Write( WORD addr, BYTE data )
, }4 ^+ a4 X5 i6 G: M6 _{
- v6 m3 `) I: ~  m$ I: q3 d        // $4018偼VirtuaNES屌桳億乕僩8 W) T' Z. @/ B0 s
        if( addr >= 0x4000 && addr <= 0x401F ) {
6 A8 w. b6 ^& p& F0 x* g                internal.SyncWrite( addr, data );% [; K! D, E0 A$ O& v& f, ?* \
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# I- V+ F/ X( u. X$ o        }5 K" A& c$ J: W, P7 z
}0 x: l* M0 b# D" _' N8 I9 {
  o- n  n% [0 l
BYTE        APU::ExRead( WORD addr )2 L: {6 p* F* K) q1 K
{" Z( \2 U4 ]/ C# E  }' i
BYTE        data = 0;! c/ _* X8 i+ h3 W/ x
9 I* c: x, S8 b6 F4 q
        if( exsound_select & 0x10 ) {
2 g) C" t5 H4 @* ^. X, a' f                if( addr == 0x4800 ) {8 U/ B. {$ B% Z4 N0 T. V! E
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );. W# E) E* j! z( Z" P
                }
, ~- g( X: L$ W! _. N4 L        }3 j; ~( a, D- A! C# O" d: M0 N  R
        if( exsound_select & 0x04 ) {
6 D& i- ?2 F" T* G# X                if( addr >= 0x4040 && addr < 0x4100 ) {/ O  |& W) p4 W; u  \& Z& P
                        data = fds.SyncRead( addr );
, i4 ]3 \8 d5 N. r# n$ ^                }5 P. {( V, r, t' k
        }
; a+ T2 Y6 K# A% V5 k        if( exsound_select & 0x08 ) {8 r; i) |5 S: b1 s
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 {% |. ~5 y0 Y0 n  T                        data = mmc5.SyncRead( addr );
& D. [8 w1 ]6 R* S; B4 ?                }. Z1 ?  A% Z5 f* ?3 {
        }; i) S8 W( l( f) w* G! B+ e
0 M3 A. t; s, z1 o) C6 w  y/ p- k
        return        data;6 E6 V: L; Q0 M% E2 w
}
, B/ f+ Q) L7 r3 X0 A( G5 L7 J' C1 J
void        APU::ExWrite( WORD addr, BYTE data ): F6 Z5 ^" F5 h1 n! u- e! j" }5 g
{: C( T5 `8 c3 y1 j$ d
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );2 U) N) L& v  w9 @2 b4 g5 U
/ U9 T1 E% B" x/ R- i7 H# j
        if( exsound_select & 0x04 ) {
( }( y3 R3 o% I& u. X# {                if( addr >= 0x4040 && addr < 0x4100 ) {
6 B, a' h% ]! N, D1 F                        fds.SyncWrite( addr, data );
) O& R; V1 x1 M$ _                }2 F% Y. Q( W' a' o+ y9 N% Z
        }. K- H9 Q1 {+ T+ U# i' _* R3 n

% H: L4 Y: j# R% W        if( exsound_select & 0x08 ) {$ {0 x7 K& E% r2 R: L- e4 G# E
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* E  T% |- f* a$ E' b7 Z) a                        mmc5.SyncWrite( addr, data );# m" c# v; D5 A" w# f4 |
                }
2 O2 [$ N( V" l! a        }
  K2 c2 H+ A9 o' Z1 D- g3 r; e}
7 U5 \9 M5 Y4 N- K. c( l. ^) E' \& M7 j  w2 Q+ E+ u# G
void        APU::Sync()
3 r$ a5 L' t# X1 u+ U1 G  e, V! H& c* P{1 [* T" f. G( G: A
}
2 s* {' D7 `  P: {
$ H: e0 w5 Y# c0 Svoid        APU::SyncDPCM( INT cycles )2 ~5 r1 T5 W5 u$ t% o  q! y! R! x( m* v
{
$ E1 B. O) F1 f/ P9 n( z! @, J2 M% Y        internal.Sync( cycles );
# S* ^# L; d/ _! a, {3 s3 u) d: b9 u3 h( {
        if( exsound_select & 0x04 ) {
2 U; M6 d( n; x" M3 R( p* F3 v                fds.Sync( cycles );# \' |, E! H) [. N& ~8 B5 l
        }" x- v$ f, u: z% Z) C8 _6 k4 E
        if( exsound_select & 0x08 ) {* ^& k0 d; y! c5 C9 e* \
                mmc5.Sync( cycles );
" w. H: x9 P+ L/ F7 d        }: m% ~: @6 Y: Q4 H7 a, b' h
}
# k% Y; k# G5 v- ]' k( W* ~* M3 _# T& n7 C! p; Q: o" g  m, e; H9 K- C
void        APU::WriteProcess( WORD addr, BYTE data )
3 M' M0 y1 b! G; V" ~{+ A# ]  K( s6 J
        // $4018偼VirtuaNES屌桳億乕僩
% C4 u3 f  Q: |- K3 x- l1 `        if( addr >= 0x4000 && addr <= 0x401F ) {
& ~$ l$ c, {5 o- A                internal.Write( addr, data );" {& f, c4 I' G: ~( G
        }
9 @" ]. e! E! ]4 R% \}
" p* l4 @: B2 D
  I$ z( D# s  y9 ], V; ?void        APU::WriteExProcess( WORD addr, BYTE data )7 f* k4 u/ Y) s* \1 z
{
+ d+ ]2 i; ]& b- J% w$ ^- G        if( exsound_select & 0x01 ) {
+ p1 s4 L. j; Y3 u' o1 @7 C% t                vrc6.Write( addr, data );
& P0 l& e) `# I        }5 n) ^* d2 N/ a8 L) R; q
        if( exsound_select & 0x02 ) {
: L" B& \8 X, U                vrc7.Write( addr, data );$ \7 ~, X1 r& k( H5 Z
        }
- F% P, k; n$ X# c, }2 M        if( exsound_select & 0x04 ) {
9 X, O" _- [2 \) r                fds.Write( addr, data );8 @0 S+ _& m# T2 @" B- R
        }$ p' E5 g6 v1 k" R$ B' D+ `
        if( exsound_select & 0x08 ) {7 L; {  |5 W" t# `2 l0 Q8 T) D* C1 Z
                mmc5.Write( addr, data );
/ V7 W2 @* ^; T) ^        }+ m. v5 s4 a2 W
        if( exsound_select & 0x10 ) {( x- @( l" b6 m! q, R8 L+ _# ?8 T
                if( addr == 0x0000 ) {  V4 x+ F" U- b9 J2 T* L/ z
                        BYTE        dummy = n106.Read( addr );4 `+ v% d9 b1 [0 _  N- H6 W' p
                } else {
* F8 B+ ?1 \' n! x4 T' u# p                        n106.Write( addr, data );# y; h* F, M' B& q! }* X
                }" ^! |* ?/ z6 i3 [6 s
        }) t! L9 p. y9 O3 ~2 Q6 p
        if( exsound_select & 0x20 ) {
( B5 m- N! Q3 H! X                fme7.Write( addr, data );
" D+ G9 E8 x0 @& @' W        }
; v  r6 I# J+ v}* ^6 V3 a+ n- r; i7 I4 R6 `# G" N

5 {$ J, I' F; n  E( ~  }% rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), v! U9 M4 T: }- j6 W& q$ {
{
  T" ?! v! q2 s# p3 g. ~  K. XINT        nBits = Config.sound.nBits;6 m- C+ ~# E& c4 a
DWORD        dwLength = dwSize / (nBits/8);& O1 t% _3 r  S8 F8 |
INT        output;# J: t/ Q$ l' w( J5 v
QUEUEDATA q;' ]% U* ?1 `* G6 V% ^
DWORD        writetime;! ?/ p- I  W8 J- f/ Y5 R5 B4 F
$ q: e+ k: M0 Q6 i6 z5 E
LPSHORT        pSoundBuf = m_SoundBuffer;) m" I: e) S( U! M
INT        nCcount = 0;
( ^/ A) T% D- I8 n0 l: _
7 y7 q2 b6 ?% @INT        nFilterType = Config.sound.nFilterType;
* l8 Z& e; i! z! P
* ?0 I; n- I" _3 s* d, ~        if( !Config.sound.bEnable ) {' u- ^& q* q+ P; [& v5 I
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );1 ^. H2 l6 ^( I$ C9 k7 O
                return;% b9 V- S* j$ ~
        }
  y3 {# u. v) V' z) ?( C! B) l  i7 z4 r/ V& v$ t
        // Volume setup
6 o; g, l9 F: M        //  0:Master8 V: d1 I9 ~( R  e! m7 M+ I! u. x9 d
        //  1:Rectangle 1* m7 _: D; L/ y2 o  X
        //  2:Rectangle 2
( s# v0 j/ A, b& n) a. f/ Q; o        //  3:Triangle
/ M# r) m/ Z  q0 s        //  4:Noise
6 s1 q- N, {6 `/ J        //  5:DPCM
/ }5 Q/ p4 Q5 f; Z6 q  p6 ?        //  6:VRC6
: J1 _. B# K% p! c2 u; U2 |+ M4 M8 b        //  7:VRC7/ X: `1 L2 v! v# {- U* d
        //  8:FDS- p2 Q; i3 v/ Y: ~$ L
        //  9:MMC5
4 |3 S& v7 N' t6 i5 C1 q8 r/ K        // 10:N106) G. I9 |0 N! {8 F& i7 t. ?6 h
        // 11:FME7, J$ M+ Z& T) S
        INT        vol[24];
8 d( g' w  @6 P% N# J        BOOL*        bMute = m_bMute;
- k1 B, e6 [: a! h. K        SHORT*        nVolume = Config.sound.nVolume;' d7 l5 K6 {% ~4 l1 l5 b
& G  _( X" ~6 ?
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;8 H5 w/ \3 _4 ?$ q5 V' c* ?

  v! h5 Y3 d) w0 O& b        // Internal# T7 V" k# J, E, ?/ u- q6 f
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
' W; r/ ]) U& g4 L        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;, B9 u5 {8 Z* q/ T, ?
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
* N9 ?9 X; n) O5 G5 \# m8 F        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' g/ ~% J. d/ a/ F        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;1 C; l; O" w' }  n1 p: u/ v4 T
7 B( u" m* g0 q9 v
        // VRC6
( ]! E6 U2 ]( o        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 E6 W8 D2 ^: C& s0 a
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( _/ w/ O3 m4 N3 }( V        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ _0 K  @% V) G7 Q2 V& [9 H2 M
0 z5 x$ p# @$ Y2 Z& |
        // VRC7
9 b' l) E3 W2 u/ `8 I        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;" V$ J' l- K  t: M2 F
( K* M! k: h7 S* B% }
        // FDS% B0 r- t9 [) n, n; T: I
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ O& `6 O. f3 B
! n, p( J1 G$ I7 d! P
        // MMC54 i' e; ?0 Y+ a
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 O3 |9 W# S' n, n
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# q6 x1 s. Z2 K- G+ U+ N2 c
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 h: H2 Y- P5 S7 V8 z

0 H( ^  b: S3 @) v7 n5 x        // N106$ y( w( A# T( @2 h+ o9 q) R, @
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! ?! p  K- p7 b
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. S% }* l% f  B5 O2 F8 [! H6 W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" n; g1 X% ^/ N$ v. v2 E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! ?% C8 z( Q% _6 n6 L
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: c4 C6 j; S' B/ _. y1 ~
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 w) |" Q" A9 e0 i# r
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ n' r, Y7 A. K+ {
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 _* m+ q1 |! {' b- k6 h( s3 X! i0 \% t7 H: U
        // FME7
/ D( \' a5 w& d6 b- Q        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) u) S( E; ~6 K( D1 Q        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; ^2 b6 O' i; }' `' Y- J
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 S$ v! D0 Q7 i1 D' r7 ~
2 @% u/ o# ~' a' ?//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
8 K. l4 V  @: Y( X7 [        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;7 r! O) U# B/ z% k$ {1 H

4 j& U. q3 h  {9 f        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& a3 j( ]* n6 i, F* D- s
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: i# M6 D1 c) Y) A                QueueFlush();
% g1 K% z) j) H, z        }
) S4 B/ Q1 K; g0 @5 W8 z
& a! n" L+ w$ [  U( q' E4 F        while( dwLength-- ) {
/ j' r1 R3 x2 b) N, K                writetime = (DWORD)elapsed_time;2 v/ j4 ?# S  o2 v9 k( G; T
5 k8 |3 X8 F; n8 @! Y
                while( GetQueue( writetime, q ) ) {# u/ a& p$ e, C3 l9 N3 `# z' D$ C1 F
                        WriteProcess( q.addr, q.data );
) ~! {3 Z% J: Z: P, @+ x                }
/ i) V$ }. k* `: X. Z8 U( ]: j% k+ Q: K" j$ u! M( n8 H0 U8 E
                while( GetExQueue( writetime, q ) ) {1 q  ?' M6 Z+ n+ l1 a& i
                        WriteExProcess( q.addr, q.data );
7 X, d# N# o. P. ^6 Y6 D                }. P% e& i: K. L, q
- q2 u" R& d8 W. K" }
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
4 @9 V7 m1 W0 h, V                output = 0;
# k+ {9 S* V7 m3 _- s                output += internal.Process( 0 )*vol[0];
4 q& E' g+ N, e  ~7 s- p2 c                output += internal.Process( 1 )*vol[1];
' O2 k1 [- [& r: m9 G- J                output += internal.Process( 2 )*vol[2];8 A$ s! k2 ]; n  ?" [
                output += internal.Process( 3 )*vol[3];
0 B* P+ E8 y, P. j' i9 b                output += internal.Process( 4 )*vol[4];% e7 W) s, M: j; D
) t5 B' H# P. O: y
                if( exsound_select & 0x01 ) {! X. q% C3 B3 J) m
                        output += vrc6.Process( 0 )*vol[5];' P3 n& ^! ^4 N5 w3 V1 A
                        output += vrc6.Process( 1 )*vol[6];* l% V/ G. N4 u9 E2 X8 D- u: _
                        output += vrc6.Process( 2 )*vol[7];
& O2 |+ b( q/ |- w" Y; @3 e1 H                }
5 w  z" `! }$ y& n* X2 I/ t                if( exsound_select & 0x02 ) {
# P- a! _0 _3 I: v# Q7 M7 S                        output += vrc7.Process( 0 )*vol[8];
# O/ c: u& ]4 }. F! \6 n5 y                }) D9 p& W: P  F* N6 C7 x% L7 G
                if( exsound_select & 0x04 ) {5 x3 Q- ^7 K. j; F
                        output += fds.Process( 0 )*vol[9];
' b$ y8 g; R3 I8 ]% z  W8 Z                }
7 I/ d1 }) F# y; D' q  h                if( exsound_select & 0x08 ) {
+ m+ a' o3 E1 s9 E8 {, [                        output += mmc5.Process( 0 )*vol[10];, j) |& V' {) u+ Y% m6 v, a  Q' I
                        output += mmc5.Process( 1 )*vol[11];
; n) K9 W* Q2 K" k' J, n                        output += mmc5.Process( 2 )*vol[12];
# F2 X  @4 S8 x$ {3 h' w1 |' Q                }6 `8 y& f% V5 A; ?' `% w
                if( exsound_select & 0x10 ) {2 `# \2 k5 F1 U6 ^" x) j2 s
                        output += n106.Process( 0 )*vol[13];
% ~: k, {; ~/ c3 x5 l                        output += n106.Process( 1 )*vol[14];* v6 H. l  R0 P7 ~2 L9 S
                        output += n106.Process( 2 )*vol[15];# W* `# W% g7 i. m* B9 q
                        output += n106.Process( 3 )*vol[16];: [% {, |1 T- j# F
                        output += n106.Process( 4 )*vol[17];
5 @2 q6 U# k# o; I+ H  c                        output += n106.Process( 5 )*vol[18];
! |# |5 m$ a7 Y6 `) [; E                        output += n106.Process( 6 )*vol[19];
5 j8 m* J, m4 ]$ I                        output += n106.Process( 7 )*vol[20];5 W7 n) s& g4 W- c
                }" I& B- n. f+ I6 P
                if( exsound_select & 0x20 ) {/ ?6 ~5 `/ R4 Y3 D
                        fme7.Process( 3 );        // Envelope & Noise
/ y5 M/ s% d" w/ i$ q0 J                        output += fme7.Process( 0 )*vol[21];! q6 D8 p% e5 A
                        output += fme7.Process( 1 )*vol[22];  V" ?. H4 f, |
                        output += fme7.Process( 2 )*vol[23];
" Q' O, w* X1 T9 r- e                }
  a  c! Z; e% K& N3 `# L" x5 D4 ~: P4 E3 L
                output >>= 8;2 |. ^& i6 f; x1 G0 A

4 T0 q  R3 H0 Y6 \6 a5 m                if( nFilterType == 1 ) {# C. D- C/ F1 |8 ]
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 F" g0 j+ D, X5 R; w                        output = (lowpass_filter[0]+output)/2;3 u9 {6 b7 v' |8 x3 ]
                        lowpass_filter[0] = output;; K! S4 a# f+ ~$ q
                } else if( nFilterType == 2 ) {
1 w8 u  i  C% m; E- Z2 |                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- J: w% B+ b. m; }' m
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 ]- K% j. p8 e) c9 R: }/ \0 W
                        lowpass_filter[1] = lowpass_filter[0];+ a, e0 v3 C) j# L: g
                        lowpass_filter[0] = output;
* O% `3 y( L) X5 [9 Q! X: l                } else if( nFilterType == 3 ) {4 f8 ?7 P, q. m% R
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)& E# o- V+ B4 W' ~+ H
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; Q2 v- `( d& d: M# N                        lowpass_filter[2] = lowpass_filter[1];5 J% M) x5 ?$ {  [
                        lowpass_filter[1] = lowpass_filter[0];
; T0 O( n. p' g/ n9 e% N+ H                        lowpass_filter[0] = output;
) v- ~' O2 m  S0 u$ {, D                } else if( nFilterType == 4 ) {2 }7 M5 X$ H' H6 s% Q# }
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)) s2 ]; D% a9 |! W. x, ~" j
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( W/ {$ R0 e8 l5 a) L
                        lowpass_filter[1] = lowpass_filter[0];7 O" N' m$ u3 ?4 C" I
                        lowpass_filter[0] = output;
! n3 z* E# ~% H  Y. B1 [                }
4 n* \* L" t8 O. Y5 x* u) d# @
* M6 ^6 a( p+ O# C: q! a4 R8 x#if        0
  s$ E" ]9 D7 y- [9 E                // DC惉暘偺僇僢僩
8 @  _0 f+ k. D+ n                {
6 v. O  V3 [7 |5 H8 R) D                static double ave = 0.0, max=0.0, min=0.0;7 q4 p0 }5 k; I6 C3 u# q6 q$ d
                double delta;8 s1 _' u: F0 @4 e& [/ a" v
                delta = (max-min)/32768.0;
% V& g! f# M0 z* F% x9 T* \6 [+ i                max -= delta;$ q& f) H& ~. x: }) a+ k8 V3 a
                min += delta;
( m/ I- l" }5 b1 V5 b                if( output > max ) max = output;
4 u* y& w7 h3 s$ x; z4 N+ L                if( output < min ) min = output;. L) ]$ W( s0 r" R
                ave -= ave/1024.0;
' @* p" a; w! c4 g0 a! r                ave += (max+min)/2048.0;$ e& b! ]8 H5 M0 w
                output -= (INT)ave;
" ~7 _+ W, L, ?8 x* d9 G1 \+ z                }
; \. Q% x/ ]2 q( f6 w! _  x" g#endif, M/ K( d8 A! L2 T- x5 q, \7 l
#if        1
( K/ ?& l& E/ ~9 o                // DC惉暘偺僇僢僩(HPF TEST)
6 j# a# J6 @9 p1 \9 U( Y                {
& q; I5 k' w$ M- A; V  L( C2 W; G//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& l3 |, m0 o7 d1 s
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
2 k! S+ J. I: e1 G                double        cutoff = cutofftemp/(double)Config.sound.nRate;1 [* @* l7 o* ~% y+ z
                static        double        tmp = 0.0;% b0 D/ X7 p8 N7 y
                double        in, out;1 x9 s. U3 Q+ K8 b, l/ @

/ {% ^/ h! _: Z                in = (double)output;
) R: _' c4 @4 w' e3 n& Y; Y                out = (in - tmp);6 T$ H$ O& J8 a$ [  q
                tmp = tmp + cutoff * out;* j  @1 J7 Q/ B, C  X( ?
1 w, n+ W1 Q3 \) d3 g
                output = (INT)out;9 K' X# B7 f6 |. ^0 r
                }
0 Y! `2 K/ A2 ^) V9 a8 ~& i#endif- H& X( e& S5 L
#if        0
& k6 k4 a8 ^: \0 Z8 p3 d                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST); ^; O, L6 I; c& y, l; I. M; o% ^" u
                {
8 X: O, a) t4 `7 d8 L. ^( r" n                INT        diff = abs(output-last_data);
$ m8 t( R  o, I0 B0 H                if( diff > 0x4000 ) {! `4 b) D: o9 F, ^9 q
                        output /= 4;- K- Y4 D& O$ L/ c# `7 ]$ Z& o
                } else
: Q% F" s6 M7 h4 R7 ~                if( diff > 0x3000 ) {  y& g' _6 J  T# X% d& @. S7 K
                        output /= 3;9 |8 B9 X/ O  G' R) c8 m7 W9 T, ~
                } else8 h: O1 v' k! `% K8 _. S
                if( diff > 0x2000 ) {2 o. a2 i, p( x8 Q) e! R1 Y
                        output /= 2;7 n- p1 g0 Z/ m2 Y* J
                }% w  V% _5 l5 ^! \' O; Z1 K! h
                last_data = output;7 _) L3 H8 z3 c, {
                }
7 f6 F: O/ q- D+ H1 r3 @#endif
3 z( x1 ~2 h2 ^, y                // Limit
" I9 e* i. M/ m3 `: U" E0 _9 ?9 D                if( output > 0x7FFF ) {
5 T* ?$ L9 S7 |7 f) _                        output = 0x7FFF;( l  b9 V& m0 N. M' F' i7 P
                } else if( output < -0x8000 ) {) S; [9 T8 p; \) f
                        output = -0x8000;
- `2 n! M6 G! Z# d                }; l6 H# p& C$ k' V

0 }6 w1 R, k8 n( _                if( nBits != 8 ) {
, |& j: Z) Y+ o) D; A                        *(SHORT*)lpBuffer = (SHORT)output;
0 z9 Z! |9 ~0 v6 \: \: u5 H                        lpBuffer += sizeof(SHORT);
7 w6 b- a6 N) ^, e6 B/ G$ |( D" G                } else {
& ]# K3 z2 a3 m3 }3 X( d                        *lpBuffer++ = (output>>8)^0x80;8 b9 r5 N/ M# Q5 g
                }
( E# _) X* a: d* |* Q) j& S+ X* ]1 Y5 d- {: Y9 g
                if( nCcount < 0x0100 )
/ f- B# e  M/ _7 z                        pSoundBuf[nCcount++] = (SHORT)output;
4 q4 l, K/ K) B, M" e# P
7 _3 z) V8 f( W( {, ^2 m9 E. [//                elapsedtime += cycle_rate;( ~& G' _! |  X5 J- K. C
                elapsed_time += cycle_rate;
0 ~: b, t1 Q4 G; C- r        }
* `- W( W% z$ y% B' h& o, J) Z% e' E* c8 K* L
#if        1
  I7 d! \9 A% d' R' O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {5 C9 d9 z6 t7 Y7 ~7 m& c
                elapsed_time = nes->cpu->GetTotalCycles();
6 I) U* y' D! `6 Z* a        }- j) n! g0 U2 l
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: b0 x/ y0 x7 }/ ]% v% k# G                elapsed_time = nes->cpu->GetTotalCycles();% |3 b: R+ |, L. U4 W* h2 H2 H
        }
/ B9 |$ D; V8 x. x5 ]#else
# q; Z* l3 a+ D, a) m2 y7 Z/ m6 J6 A. I        elapsed_time = nes->cpu->GetTotalCycles();( \" Z& {) B5 P
#endif
, Q6 O7 F& w8 f}  q; r" O! |8 v7 z7 Q. |

' l0 o, h$ L  E: ~/ G: A2 }& E// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
# c" V, v$ i9 V) JINT        APU::GetChannelFrequency( INT no )
2 q' B7 u, \0 Q* D{
1 A! l1 Q' W+ f2 ?- ^        if( !m_bMute[0] )3 K1 d- d  Y( M3 z7 d- W$ V4 i4 ?2 f
                return        0;
; A- }/ F5 m$ M& Q1 C1 X' S" v  U& o: ^! [& q8 R. m! N% `
        // Internal2 ?" S' ~% w7 p7 H7 D* C
        if( no < 5 ) {
8 u) U5 r$ o; ~/ Q# g                return        m_bMute[no+1]?internal.GetFreq( no ):0;
+ m: A; N4 V8 [2 f0 E+ ^6 f        }
0 i" s* b6 B: ]. b( O# ]0 ?        // VRC6
& ~- l* @+ j' {5 Y        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {  n3 y# g9 @  U& z5 a: C0 i
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 J( `, d, h* x2 z        }
" W0 ~# Y, P4 H; J        // FDS
' V$ ^% V! V  q* X0 m6 M1 L% U5 q- Z        if( (exsound_select & 0x04) && no == 0x300 ) {
2 n6 `. A; Y/ z1 d0 Z                return        m_bMute[6]?fds.GetFreq( 0 ):0;- T" A  f6 y( G; B; @" ^
        }
% p2 `, h6 {3 e        // MMC5
. V* i. {3 S6 B' V4 S  o5 V" @  b        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. |& O9 B( j: U4 ?% Y- W/ ~                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
% s3 B: l: i9 j) K# f& [        }
  X' x. g2 y0 C/ O: ^* U& q0 s        // N106* R' T' c, ?$ y# M$ p3 |. e  g8 Y
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
/ O* c5 e' i2 r; A& N7 U                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
0 L/ C& L  C: n* m$ p; L# J; o        }
, x; i+ g6 o; t5 r# s        // FME7! r4 Z+ y$ D7 a8 g- b2 C/ J
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {* @. p$ r% }) I- @8 _
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' L& Z, j3 c/ l+ `# K+ d. n        }
$ E  {4 ]$ o2 k7 u' E+ v0 w% q7 m        // VRC78 ^& R7 E& X; Y; u9 n
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: L) z4 a) Q. K3 g/ ~
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
" `7 V% C6 h( H; B( K+ x        }
1 W4 x/ `& P9 w5 g/ {        return        0;$ x' P0 ]3 ?3 M  p0 m" [) y2 ?! @
}0 z% i. ]8 O% X  g( h
6 x% Y* A# w. y
// State Save/Load+ d7 z# l2 i  Q: Z9 ?& I1 J
void        APU::SaveState( LPBYTE p )
5 x& P3 c7 Y, O4 |& A; d, j{
/ T6 K( A) J% y1 b0 q2 H. }#ifdef        _DEBUG
6 Y4 o( Z$ r+ @" ]! jLPBYTE        pold = p;  f; b1 g/ V# ]+ }$ t7 a, ?
#endif
# j/ i$ J4 ^) l% l. Y* L4 t4 D) \! [5 t, r. W
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞' Y8 x  r: P: t6 i; ]2 D
        QueueFlush();
. z% Y$ r+ F9 Q3 |
2 R* a  {: Z# u! d9 [/ N        internal.SaveState( p );9 Q, N; e/ X' b
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' e+ L- d& _' l+ f; G. }! D! w$ ?+ H2 ~- w2 }6 P' R
        // VRC6
7 u6 A. |# H. H# M        if( exsound_select & 0x01 ) {
& ?+ w; ]9 ^( E0 q* u; j7 H$ g' C( b                vrc6.SaveState( p );
1 P( k8 S" s( v% @2 K, {& v6 ]                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 m4 |0 Q$ T' x3 k( J        }
& N$ y2 P- G2 {5 m' U+ u# X        // VRC7 (not support)
1 w, V: [$ i1 Y7 i* K; P, {        if( exsound_select & 0x02 ) {
, X+ A5 Q2 i* X$ H9 S0 R1 }                vrc7.SaveState( p );
6 L, J  @9 R2 {. w4 d( |' f, \$ k                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
6 q: i1 ~& G3 x: R( ]" Y' j        }
6 I7 d7 P% {5 q* u; z3 c7 J        // FDS" W& Z3 z' y: l- S: M
        if( exsound_select & 0x04 ) {+ h; b; K* W% ?& {' s& p
                fds.SaveState( p );
  X- E$ K7 m! _% V/ S9 p                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ v2 M9 }' o6 {/ L9 \
        }/ U$ _1 x% U! h/ a% T% I/ W
        // MMC54 [3 l. o# `+ s$ q# @6 O3 u0 R
        if( exsound_select & 0x08 ) {( K( ?7 R# ^( I, B9 @+ u
                mmc5.SaveState( p );4 V1 c2 [, G) S$ M
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
/ ~+ h  h2 D3 F$ C4 W        }
1 \3 O0 M" h$ ~) a: G5 ^# |" T        // N106
& b  z4 b% E8 U        if( exsound_select & 0x10 ) {7 o8 X3 b$ t! J0 C( S$ Y
                n106.SaveState( p );
+ P. ~0 F5 u$ h5 |, f) m" u                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 C6 j/ K9 \3 g: V7 x
        }
4 V" F- g" W, H, D$ _        // FME7. F  C+ ?* L  S2 J* [& g3 o. j! ^4 n
        if( exsound_select & 0x20 ) {5 n$ C) u- q+ r1 v, B
                fme7.SaveState( p );) T4 u" c( f9 g1 h! x7 G
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 E& @# H5 c+ Z4 K
        }/ |+ a+ |2 u( F+ a; F, @8 ^+ L( q

! Q: c+ ]' W. u+ M#ifdef        _DEBUG: f- x. ~1 ], a. [7 _1 U
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );) f- q9 t' P3 J4 Y* p% v$ C2 @$ l2 X% j
#endif& ]- ?8 ]: L5 E/ d  v0 `5 m. d0 O
}
- B6 X. T7 H$ ]" @
0 V5 N2 H" s! A2 zvoid        APU::LoadState( LPBYTE p )
8 S/ b( i8 P( v. p' _{
, o, l5 c0 l6 Q" m3 f        // 帪娫幉傪摨婜偝偣傞堊偵徚偡9 y, d) i8 n; ]
        QueueClear();0 ?* A  f& I6 ]2 `0 K* r6 v

' x& y2 B" G  Z% F  s5 h0 ]4 C2 u        internal.LoadState( p );
8 Z3 w8 Z( a% o/ N0 t0 x        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) E* t* p6 W" P/ b  c# Z5 x! B/ z' G
1 u/ I. q7 ~: a' A) t8 n3 p: @& `        // VRC6
& I7 E$ j% c+ f% @, l6 v4 K! f        if( exsound_select & 0x01 ) {1 T* v9 ~; {5 T! r
                vrc6.LoadState( p );5 r7 i# J, j, I: X% r2 w  z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& C+ Z# c% Z* O8 \  [
        }
, W2 N3 a0 U0 d( L$ x        // VRC7 (not support)
. ]" o7 J/ _- z4 ~1 ^% m' B  u        if( exsound_select & 0x02 ) {
. f9 f: D( Z) o7 F* x                vrc7.LoadState( p );7 J$ ]9 b, W$ e( [2 }! y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 Z& K6 [& r5 }  g
        }& d! ~8 t4 D: @, z6 Y9 c
        // FDS& R( f1 W* V  m3 i
        if( exsound_select & 0x04 ) {
0 M4 i" D' y; R3 K- }4 R/ ^& r& p0 J                fds.LoadState( p );
/ U+ H) `5 \/ G5 x) S1 P                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& E! j2 ?0 K" X  O* I- A
        }, h2 d8 k7 w9 ^" J0 k
        // MMC5
1 S& `4 B- A( o        if( exsound_select & 0x08 ) {- C9 c! K- ?( w) w3 P2 H
                mmc5.LoadState( p );! V6 b0 e7 y, O# q* P3 ^
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 u8 Q8 w0 e! ~) t        }
# F- i' Q; ~) C0 P        // N106% `- N5 Q) K. n" Y9 K
        if( exsound_select & 0x10 ) {0 U+ ~; L* T' b+ [$ I
                n106.LoadState( p );, |% t. p- |6 D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( ~( T) e; e1 X6 }+ O( `5 b& a+ ^        }  _# v8 X. L# I% U1 Z* w+ y( }* {
        // FME7- S4 g" j' O1 C1 _* U( {3 O- d" l* F1 V& F
        if( exsound_select & 0x20 ) {9 o0 |% i, v- _# K
                fme7.LoadState( p );! X% w  P+ ~8 W% _
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. v& s* G4 a6 U
        }" k2 V1 G+ Y1 C' }$ |
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
1 D& c) w9 u, M可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
- V; K8 s! d5 \) s- P8 g$ s& J  E  p感激不尽~~
$ l; i' n9 M* @
恩 我對模擬器不是很有研究,/ A% u. G" `& p
雖然要了解源碼內容,可能不是很困難,: F3 K8 t! {7 J8 x5 i- Q9 S3 P% L1 `
不過還是要花時間,個人目前蠻忙碌的。; Q7 I; Q: T" m, w. y! M

! u" H) {8 T6 m給你一個朋友的MSN,你可以跟他討論看看,
9 g' V3 U; S' O# ~2 E; g他本身是程式設計師,也對FC模擬器很有興趣。
8 E1 a9 ^! c2 S2 O% a$ b( }  k1 d' ]0 y9 ^5 V" t* `% {- O' l- w) q
MSN我就PM到你的信箱了。
/ B: N% _9 g" y( N" C0 |
* S; i0 u8 z* E4 _! Z3 j& C: H6 q: E希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 6 `5 @+ |/ F# ~& `
呵…… 谢过团长大人~~
- s) K) L0 w7 m; C" P8 c  B1 I2 m

- w$ i0 ^4 N+ P2 L哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ G, j8 i8 i+ A' R+ d& u3 m团长的朋友都是神,那团长就是神的boss。

6 x( h( i4 P, U; D& e哈 不敢當,我只是個平凡人,/ a- _4 t# @# F; G  @1 c3 x9 q' \) X2 c) {
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙. H% C& P1 `7 X/ M" k' Z0 D" P( J
ZYH
9 {5 i" {% O: O) C6 n8 T% ^1 W9 ^) D, \7 \2 pQQ:414734306: i7 z8 [( L  Q4 ^
Mail:zyh-01@126.com
, t1 @/ v! D+ m' S8 x1 x& [. A5 p
! C7 d9 c' m* `9 t  q' t/ ^他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
& q3 v7 N- h% P6 F) g/ J再次对团长大人和悠悠哥的无私帮助表示感谢~~

4 w9 R/ O5 D/ J* I. @不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 04:03 , Processed in 1.106445 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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