EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( n9 z  N7 ^1 P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& a7 k5 G3 D* |2 N/ s. Z
这里有相应的模拟器源码,就当送给大侠了~~
/ k) j2 ^* W2 I3 m& m, n; N9 }http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
2 F7 O4 Q$ K! n" E% n能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。7 R0 W2 s" i: A% P/ H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# J/ {4 Q0 v/ U0 b, V  D6 Y. M
这里有相应的模拟器源码,就当送给大侠 ...
5 `8 p! y" \" M) ]- g- F% G2 N
聲音部分(Audoi Process Unit = APU):6 C2 a2 \# J* n( J
.\NES\APU.cpp
1 ?" I8 n# _6 f: t% ?- D# k+ a.\NES\APU.h; i+ f$ ^# D3 J) `) Z2 x0 G  ?3 M

4 _3 L2 z5 L4 d' y" d1 l) w3 p8 h" l3 G& N) ^$ `( X3 ?$ Y; i
影像處理部份(Picture Processing Unit = PPU):/ j9 C6 c' V% b1 h  R; g3 S, m
.\NES\PPU.cpp. Y9 g8 O% l) g* P% b
.\NES\PPU.h% h5 y9 M" m6 u# a$ _3 r8 p0 B
8 d; y: g6 r4 r9 r' _  c8 t# p6 O
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
+ @9 a8 z4 @: Q  F9 {(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 I/ y5 G8 e% b7 ~9 k
//////////////////////////////////////////////////////////////////////////
) n$ N/ e7 w# M$ [) l: y) i//                                                                      //
! K. f0 Z- g" t5 u) x7 V2 ^//      NES APU core                                                    //1 b, z! D' i+ N! l1 N4 N& n
//                                                           Norix      //
7 \1 H+ s( ]: j0 `+ g" `//                                               written     2002/06/27 //! v$ z4 R8 E' @0 N: g4 P7 i
//                                               last modify ----/--/-- //
: A6 r% f6 G" T; @5 ]5 o//////////////////////////////////////////////////////////////////////////
$ o, @. C. K- x& f& b3 W2 Q" E#include "DebugOut.h"$ h1 H  {* }2 T2 }/ t
#include "App.h"/ C9 b  B- j% D5 i- m9 }( C/ k
#include "Config.h"
7 g2 @3 x' \) d2 l/ P7 I7 |0 t" E8 d  T. g
#include "nes.h"1 [" U  j% y9 L+ A% C
#include "mmu.h"
+ a/ J2 t5 c( X/ K4 U#include "cpu.h"
7 d+ t. B0 ]3 p/ r5 [#include "ppu.h"
+ d0 o% q5 l; x; [% X#include "rom.h"
1 Z. h* W$ @" z- D: d% V( d$ P#include "apu.h"; r- D0 `7 g; @. t4 a% K8 j' v

# N/ ~7 x4 t- {// Volume adjust: r2 [8 _0 D7 E* i
// Internal sounds
( n6 r' U/ w" O#define        RECTANGLE_VOL        (0x0F0)
( N* ^0 K( C$ B' V#define        TRIANGLE_VOL        (0x130)
+ a) b: n/ D9 j' ]# l! B#define        NOISE_VOL        (0x0C0)
' a/ v8 W. d4 m5 g8 e+ X9 O0 s; G#define        DPCM_VOL        (0x0F0)
& w& f$ ^& J8 }$ j# h: }' n1 j$ v// Extra sounds
, z* m7 o. g0 h#define        VRC6_VOL        (0x0F0)) }7 ^9 s- M4 m2 _' h5 t
#define        VRC7_VOL        (0x130)
# t7 C$ U, C! p# b# M#define        FDS_VOL                (0x0F0)
2 h% N! i, |1 R% s+ E$ n4 c#define        MMC5_VOL        (0x0F0)2 f4 p# h4 w3 x( r8 j
#define        N106_VOL        (0x088)! J' X  g1 B! s: q6 z
#define        FME7_VOL        (0x130). g: U+ ?" k4 s$ U% t3 A6 Q
0 ~) w' o* h! n* ]
APU::APU( NES* parent )# i- Z8 h/ E4 |. D2 E- ^
{
( y8 o4 Y- o* |# v9 I        exsound_select = 0;4 E# `" U8 x8 ?. s# |3 z

% a. G4 Q* \! l  E5 f/ q        nes = parent;
/ L+ A% Z0 K" }% K* @        internal.SetParent( parent );' O$ \8 r* ]& ^" J

" Y  Q9 q/ ^7 _6 y# s3 m        last_data = last_diff = 0;& T/ z; ]" E5 ~* f4 y7 W% o/ t
9 ^, c5 Y3 l& I5 v! ?
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 ]2 q* d7 O, ^  ~/ V. \
. I. |; f3 T3 r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 e1 Z  [- t  ~* o3 X5 B9 E; V& L
        ZEROMEMORY( &queue, sizeof(queue) );) f6 x* p4 y( I# ~/ ]) B- P: k7 m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ x  V7 L8 S$ I: E9 ^6 W1 E

) S; J! S# y! Q1 B, Z8 ^( ~4 P        for( INT i = 0; i < 16; i++ ) {, F: ]! X6 d0 q& d3 z8 h
                m_bMute = TRUE;& u( j( U, l) d' q) [3 o( {: O# d
        }- g0 G6 L& L7 X0 t5 k
}
" b0 Z* q" ?* E. P5 o+ V0 L9 {- {% s) J3 r6 T, G- v+ D* \
APU::~APU()5 @) F7 u5 d0 {3 W
{- R9 z0 E, H: V
}
  t5 r! o4 a0 [# H! C8 s5 E  ^: p; B
* F* D: `5 A+ W. jvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
6 @  S# X; q* h  Z{
2 t+ v8 D. ]2 L" m        queue.data[queue.wrptr].time = writetime;
$ o6 r3 H. P* R' J' H2 `        queue.data[queue.wrptr].addr = addr;
% X6 F. h2 f6 k* V6 e: c        queue.data[queue.wrptr].data = data;9 z' k( o, x+ t7 G2 G5 L
        queue.wrptr++;' d" ~% P& N9 _- x/ I
        queue.wrptr&=QUEUE_LENGTH-1;
' n) v) m+ u5 ]/ [2 P/ W7 O        if( queue.wrptr == queue.rdptr ) {
6 e! _+ w  m4 J% v8 g5 a& g                DEBUGOUT( "queue overflow.\n" );
: d7 _  R/ E. G9 V9 a  v0 f        }
: {4 w' I2 u: s' x0 B2 J7 F}
/ T: G# N/ p+ ^: X" I- z$ {+ s' [4 B$ U- T. U9 J) C4 o/ F
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* r& [( k. ]" \/ E  \+ `; _, L
{; C. |3 W; j7 A6 e
        if( queue.wrptr == queue.rdptr ) {
7 u! {. I. O0 o  b                return        FALSE;, X  j6 y6 R4 Y% E; s( o
        }
1 m: `! ^, ?' D8 L; S9 J        if( queue.data[queue.rdptr].time <= writetime ) {( |# J' D; y+ t( I' @
                ret = queue.data[queue.rdptr];; V& K# r$ M! K0 z6 e& b9 o+ {
                queue.rdptr++;+ J+ t( E) g6 v' v7 S# R2 D6 M
                queue.rdptr&=QUEUE_LENGTH-1;: \+ @* a  q; w7 c! g0 A4 Q
                return        TRUE;
- Y$ [8 C$ e* [8 C9 R1 b) a# x6 u( W        }
! ^: i# u# T3 q& ]# ^7 ^6 f        return        FALSE;3 o; [/ W6 x* G9 H
}. v) P7 O( N! `. a3 b- k9 @
3 m) r( n+ u1 k( k# z
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
9 u# v% |3 X: N6 Y{
3 T% M4 W+ \3 T* J) t* j: @: f        exqueue.data[exqueue.wrptr].time = writetime;6 G/ J# X' g' m& e& o8 T
        exqueue.data[exqueue.wrptr].addr = addr;
1 Z4 r9 ^5 A* y" A        exqueue.data[exqueue.wrptr].data = data;
2 K6 q* e% r& a) t        exqueue.wrptr++;- J  m' K. ?$ H2 ~
        exqueue.wrptr&=QUEUE_LENGTH-1;
9 r2 Y, Z  V% W6 _6 m% e- b        if( exqueue.wrptr == exqueue.rdptr ) {
& T% j+ @/ v) ?/ C5 w8 u, r                DEBUGOUT( "exqueue overflow.\n" );9 G. V1 U1 O+ c
        }
3 h) p4 h( {  O9 U- g$ p9 e}
0 B+ k  P% }/ E* V* z+ c' Z! w
% R: K" l' r9 U# |# {BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
0 o( G/ Q/ g, q$ ?{
' ~8 y2 a/ \9 p2 m) H        if( exqueue.wrptr == exqueue.rdptr ) {
* h$ y: _5 t3 @. k! j% X8 C8 O% Z2 Y                return        FALSE;, I8 Y% j5 T5 l. @4 w
        }
8 V6 @+ p" [- ^% m        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( l. y3 w$ o7 \6 \, x7 g4 r                ret = exqueue.data[exqueue.rdptr];
/ ~( F+ l7 V5 y. N                exqueue.rdptr++;, @/ z7 Y; H6 H5 y' U
                exqueue.rdptr&=QUEUE_LENGTH-1;
- B* ?  E2 g7 p0 y  a; A                return        TRUE;
3 a9 b) k/ C& ~1 u        }
% ^4 U* s) B9 W. U& @        return        FALSE;
3 Z3 Q) b9 n" k+ G: x# Q}( o9 E" W# U4 z
" r% i4 |) ~% ^- k2 d
void        APU::QueueClear()
3 M# i: a" M- a/ f{
; l5 B2 I+ F  }0 L% u/ L1 y        ZEROMEMORY( &queue, sizeof(queue) );
6 u5 e; M) O6 o! |        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, e5 M- u* z# D9 D2 Z}( d5 o; O: H# V, x

; L8 |* j* @" N! z8 \void        APU::QueueFlush()
; H: g. y; S( l# u8 M{
9 b; ?9 P1 A- N. @- \7 x        while( queue.wrptr != queue.rdptr ) {  ^) P* u+ z! E! K
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
) n* u$ ~& g" Q2 W6 H) D                queue.rdptr++;
5 F: a, C% L3 ^2 [7 p) `                queue.rdptr&=QUEUE_LENGTH-1;* V2 d* _$ ^$ h8 M' _: j; [. M
        }6 ?1 D  [$ B; a8 G$ V% ?# i
7 A7 e$ v( l. h, }" M- M
        while( exqueue.wrptr != exqueue.rdptr ) {/ P9 s& M' ?; m' e0 M
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );+ E1 L5 \) c  g. A+ }
                exqueue.rdptr++;
2 ~" O- m7 o; y3 l$ {                exqueue.rdptr&=QUEUE_LENGTH-1;
  ?* s) E; r* A8 l& p) F. }$ d        }( V! W+ ~7 X. E, ?1 m7 ~! `7 W# d
}
2 G, m' t& ~# I1 o7 @3 T* g
& o( C4 ^/ i6 K+ yvoid        APU::SoundSetup()
% D/ b" \1 [) A3 W{* e( X7 `* P) R3 d: |; D
        FLOAT        fClock = nes->nescfg->CpuClock;
/ R0 |' `+ q- ~1 l2 I        INT        nRate = (INT)Config.sound.nRate;' h7 i, j' Q: |! c9 h
        internal.Setup( fClock, nRate );* V& j  {) T0 d! ?% E. n
        vrc6.Setup( fClock, nRate );
3 g+ K4 G7 s* H: J: F        vrc7.Setup( fClock, nRate );1 i* P( }5 K, f1 K; R
        mmc5.Setup( fClock, nRate );
) [' `. [( u( P: @1 k; v        fds.Setup ( fClock, nRate );1 J  k2 b/ V7 C6 ^" |/ ?5 d. Q
        n106.Setup( fClock, nRate );
  W/ t: w2 M8 Z0 ~" V2 K- H        fme7.Setup( fClock, nRate );1 v5 f- m0 d; ?. a6 X/ o- T7 y
}
% a6 h/ H4 |8 T: d: R2 U4 Z+ J/ N) c' `5 t. Z6 Y) Z. Q# X1 P) D
void        APU::Reset()4 V5 m" E) I+ C
{
( `" J: K) t1 Z+ G        ZEROMEMORY( &queue, sizeof(queue) );
3 k/ M, W. E  A) E        ZEROMEMORY( &exqueue, sizeof(exqueue) );. }& _2 V- o: j- ^- m2 a& @! j8 G

1 ~% |5 x$ K8 v- B& d        elapsed_time = 0;
1 ?0 W$ G- b3 s: _: t  E
% H, h6 s) m  x1 L        FLOAT        fClock = nes->nescfg->CpuClock;
7 n4 T" j6 p8 Y$ J+ g" U4 Q        INT        nRate = (INT)Config.sound.nRate;
+ V- L# }: o3 B0 O1 \        internal.Reset( fClock, nRate );" w! N1 H8 M$ o, T- }1 O* u# c* r
        vrc6.Reset( fClock, nRate );
8 V2 b2 X. ^# e8 ^# B. e        vrc7.Reset( fClock, nRate );
0 `  j; u8 ^, S, `( B0 ?        mmc5.Reset( fClock, nRate );6 D9 R/ l- T7 _$ y# U0 p- X/ O7 X
        fds.Reset ( fClock, nRate );
# O" n7 C. ~& ^        n106.Reset( fClock, nRate );
; C3 I& U: n3 T3 u- u4 M        fme7.Reset( fClock, nRate );/ A* h! ~. U# ^
6 ~  P8 ?7 X' W/ u  @
        SoundSetup();
( R/ J  k) A0 O& R. `% R) N}# ^: Z- K+ _5 ~
( [0 c) H+ e+ C6 w
void        APU::SelectExSound( BYTE data )
9 u/ L; }3 M0 D! C( z; t7 k{
9 C' b0 g; w$ {5 I6 o        exsound_select = data;
& {1 @+ E5 H! z}
$ U( }! k4 r% R0 @7 N7 @% F! h
+ d8 i: i2 E! TBYTE        APU::Read( WORD addr ): X$ z8 i& w# G( G. O* ~9 Y' O
{- i' K* i6 h, Z9 J( e2 W( D
        return        internal.SyncRead( addr );
+ X$ x& G1 H$ a! H6 u}7 u' n3 T. L1 F  ~4 N7 x* m6 d
4 Q# E3 U! p- T. L* ~; m' E$ `
void        APU::Write( WORD addr, BYTE data )9 D, M7 l+ y- A2 i0 D* k( ~
{' T1 A+ z6 q8 K' Y; W+ T
        // $4018偼VirtuaNES屌桳億乕僩% m" y- a! t4 i# @' A( L, u
        if( addr >= 0x4000 && addr <= 0x401F ) {
+ u0 |- D2 e5 n9 _9 N. ?                internal.SyncWrite( addr, data );+ g6 j* \) n. Y8 O* ]
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 _! T, h- J$ E+ q5 K) ~
        }3 I7 B5 \0 i7 _8 i
}
4 d) t# z$ O: X9 @7 x9 j2 C0 D$ l) a: g! C* f
BYTE        APU::ExRead( WORD addr )0 d5 f5 j# l! |; K1 I7 }  p/ b
{/ B9 Y6 T* e  [  [
BYTE        data = 0;/ {, J- Y) w5 S3 v
7 f: F- Z8 @( b7 r9 u8 _: F/ M1 ]
        if( exsound_select & 0x10 ) {
; t" n" P6 v% f+ t4 g! \: R8 ?                if( addr == 0x4800 ) {
7 i% K! C' N7 y$ ]7 w9 \                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
* X$ Z7 {; R6 c7 Q                }
$ d; e! Z% X" C3 T  c" x. Q/ ?        }9 e1 S6 v6 e( X# o7 L3 v1 v
        if( exsound_select & 0x04 ) {
$ f3 O$ e. U7 Y% Y                if( addr >= 0x4040 && addr < 0x4100 ) {
" L3 b! u% |% |; b                        data = fds.SyncRead( addr );
$ y' v/ {9 F" H* B                }
/ [  u! R3 \$ R6 m! e2 L        }/ n  @4 N8 p7 w. z( h( p' X
        if( exsound_select & 0x08 ) {; Q5 p( \/ f5 g# C# h: f
                if( addr >= 0x5000 && addr <= 0x5015 ) {
. z  E' l/ [- H; J5 e+ y- \                        data = mmc5.SyncRead( addr );
0 D$ @; t9 m' v- V1 E* Z9 Q+ T                }5 R2 c; b6 |8 |( n3 t
        }7 f3 s, R# {2 C1 P
3 }7 P% {7 }, s+ ~# P5 i
        return        data;
0 v! I2 o( Q% o) a}
( p( Y# l) N' s( {3 g  A+ R% }% o! @/ h5 N4 p
void        APU::ExWrite( WORD addr, BYTE data )
1 k7 x" h! x# u) w1 I' b{
$ w$ m$ x# M% }% f! M, z  i' Y        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; a. R3 o6 X: |; M3 |' u
0 r7 [% \9 \' h5 a$ W8 M% P        if( exsound_select & 0x04 ) {
+ w3 {3 Q' o! P: v( `                if( addr >= 0x4040 && addr < 0x4100 ) {/ S! w- d1 W0 x6 U7 C8 n
                        fds.SyncWrite( addr, data );
  ~* e* T* V9 X5 G9 E$ g0 ?                }
. G( M' A6 E- S* ]        }: E3 M0 P* G! b

0 r8 {8 h+ J: I  e/ \- H        if( exsound_select & 0x08 ) {
/ h+ P( U* U1 j' q6 u                if( addr >= 0x5000 && addr <= 0x5015 ) {
( B- e7 [3 J- l4 N+ N" D' I                        mmc5.SyncWrite( addr, data );
3 ]5 K; |' X0 @. ^$ v                }
6 ^, O: C5 F; I        }* U) [; \0 ~9 V% X5 L; K4 ^: o
}
* K) }1 M4 j6 G5 i' s- _8 ?5 A( k3 N  d. ?3 W% w8 t
void        APU::Sync()/ m3 n2 d0 K' b0 f; ~  D  Q" U* C
{! u  W9 B! I: T0 A+ c
}
6 L$ u6 C, z- ^+ R0 h% ^, C0 \; P2 y) l5 i  w3 q" \
void        APU::SyncDPCM( INT cycles )1 w3 e, _$ _+ G$ z4 W# c9 |
{
$ B. p, p+ c7 }9 K/ B/ |( }; H        internal.Sync( cycles );
1 ?! G1 u( }: X) t1 U, W) p- V7 Z9 }% f
        if( exsound_select & 0x04 ) {
; e- r9 [3 |+ m, d- Q# e& }: Y                fds.Sync( cycles );# u: j5 B: C$ E! O
        }0 R  l, G0 f/ H; m
        if( exsound_select & 0x08 ) {
: ^& c# x1 y+ k& e1 D8 q4 f1 P$ j                mmc5.Sync( cycles );
! E: R5 C& Z" d) `        }7 E% g9 y5 C& i1 @/ `: k
}
6 y, }. K0 k" Y/ a8 _0 E# i, R9 L4 W6 q2 ]' A% S
void        APU::WriteProcess( WORD addr, BYTE data )
7 g# m! Y8 k9 x% X3 q0 P) X0 x{
- w7 m/ ?  b( A7 N        // $4018偼VirtuaNES屌桳億乕僩
& Y/ {" S; n9 X5 e1 d6 u: G. c        if( addr >= 0x4000 && addr <= 0x401F ) {4 u' f! q6 j5 i
                internal.Write( addr, data );
) [1 t8 ?) l7 K3 w  z7 I        }2 I" U. D9 c( z& k' E$ ]8 p4 g0 z5 t
}4 z8 f! `- Z' K  L9 I  h, m7 y
0 g1 x2 c0 L: L2 z; s. x8 F0 J+ k
void        APU::WriteExProcess( WORD addr, BYTE data )% i9 @" M7 b6 ~  w( R
{; s- [; S! O* Q
        if( exsound_select & 0x01 ) {
: H3 D) S0 X3 i, k, j5 k* w                vrc6.Write( addr, data );
0 H' k+ @) f# n        }* y; w  o- O. d0 p" w; s) I2 X
        if( exsound_select & 0x02 ) {
0 o/ H" n; g, j1 x! d9 `                vrc7.Write( addr, data );4 U- k5 W- e( a, N5 u6 P
        }9 r) x! G+ K0 o9 l8 Z- a, N7 g4 Y
        if( exsound_select & 0x04 ) {
9 {& J5 Q5 Z: y! U+ I2 k+ U                fds.Write( addr, data );
# S% k, o& l& p  W$ U+ Y8 y6 V6 n. d        }
8 u/ B* I" z& E' I        if( exsound_select & 0x08 ) {
0 _  V+ ?/ w; ~, g7 T5 J& M                mmc5.Write( addr, data );0 M( u1 k( D% i# G, w
        }
7 P; D' ]5 P, Y        if( exsound_select & 0x10 ) {
8 x+ F6 c+ Z' A! F+ t                if( addr == 0x0000 ) {+ k' M) ^: X& V. m9 y. d
                        BYTE        dummy = n106.Read( addr );
8 i9 ?' K7 N1 @; \9 q                } else {1 o1 W, p( L* @2 J0 d5 h2 K7 t
                        n106.Write( addr, data );
8 }' Z9 O- y( S; R3 w                }
& \( a- Q, s, K$ P0 P0 |9 t        }
: z& ^  a3 `% T7 m4 B, q( [& E        if( exsound_select & 0x20 ) {- Z0 i, S. c  _- t7 J1 |6 A
                fme7.Write( addr, data );. p) W9 v9 G7 w5 j
        }
1 A" P: Y1 o" t}6 x6 U* o; a" J6 m

6 L8 x) L' S# Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )! d1 A! V6 E( g' h
{' }3 T7 o# X8 R7 O' Y, H7 x
INT        nBits = Config.sound.nBits;- Y; Y5 `  L$ _2 o- a$ J* w1 v9 X
DWORD        dwLength = dwSize / (nBits/8);
/ @- N2 c$ K) CINT        output;
. ^- \1 u- Q0 m  hQUEUEDATA q;
& s% i; O( |$ m: q" {! c4 h8 oDWORD        writetime;
9 r+ S. l! U& u" h& o% Q
4 F  c1 N3 U# F# k6 R& S$ kLPSHORT        pSoundBuf = m_SoundBuffer;
) }( n+ J# t' {% d6 k4 e" MINT        nCcount = 0;, N4 ]6 W& w: y) O/ {
7 s' A0 A# W" @! Q! _* c! i
INT        nFilterType = Config.sound.nFilterType;, g4 w4 d8 Q2 i0 \, z% g8 n' O3 o

0 v. F2 v0 z8 d- O        if( !Config.sound.bEnable ) {; ~: k) ^1 R" E) n; c
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
$ S: D( C& ~& W# p5 V* ~$ c: b                return;
$ B6 @5 @8 S3 |. g6 u4 }- T        }  _0 f; Q' @: ?: N4 f

* t$ K. R9 t6 R$ Q- T# |8 i        // Volume setup
6 U3 e  c& n/ \2 P6 `9 D. x9 t4 G8 u- ]        //  0:Master) [' p4 c) i" @. A" R" V8 A1 ~6 M
        //  1:Rectangle 1
  w4 ]; I; W% k0 P( N- {( u        //  2:Rectangle 2
) X" e; Z, r) _8 y; Y% g% `5 b( J1 L# u4 M6 ]        //  3:Triangle
/ C" E' a. m- w% }* O3 k' X0 u; t        //  4:Noise6 z7 m- O& }5 u, g% T7 }
        //  5:DPCM" s3 t; v. ?" q( D1 T4 T3 Z/ q
        //  6:VRC6
; z5 E% K) |( K6 Z. G        //  7:VRC7' E. i- N  `5 N7 ^# _
        //  8:FDS& ]% Y$ z$ G: c1 ^# O
        //  9:MMC5
* w* z6 w# W2 J' E  A5 w/ j' T8 Z        // 10:N106' A' ~' A+ _/ O- Y9 Q/ G7 Z
        // 11:FME7
# W+ |& l; ^7 V! r2 }7 Q0 B        INT        vol[24];
' ~$ \. Q4 h: P7 `0 {- a9 Z7 G        BOOL*        bMute = m_bMute;
  Y/ X3 u2 |/ j        SHORT*        nVolume = Config.sound.nVolume;3 H0 W; {3 d2 ]

0 R% c; \  i9 o        INT        nMasterVolume = bMute[0]?nVolume[0]:0;8 y* }/ s7 ]- k

! T; d1 ]$ U% |        // Internal* W4 w0 p: L4 p3 }4 Q4 t2 {' e3 d2 S' K
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
& g3 M* K4 o1 ]- r        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;0 u" `' \. w2 ]) Y; ^1 S
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 E9 s' q) Q. J3 c  t
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;* T4 W5 f) S$ z
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' W) g; V- L& o6 ~
" d6 q$ D9 g' L1 U+ R        // VRC6
# {. `0 p( W$ O" `* x        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 s  R7 q7 a4 m* J
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: Z6 ~0 G* [8 _$ {" T9 I        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 s8 |0 i& x3 x1 M6 @$ j. x" r! a; ~
        // VRC73 ]" E, v) r' r9 B+ [9 V. j% {
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; F3 E. q9 ^* r" H
1 m" {7 \  k( ]
        // FDS- c  \1 c' U: ]% C3 b' g
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& K, [# Y$ ~$ @! M5 L' ?1 v+ \/ y8 d6 I' b9 Q1 Z
        // MMC5
! }! C( W6 M! Y        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 E- i/ Y& c( {$ N        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 u: C. t, e) x+ [3 {* l( g
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. y* d( q9 m3 v! k. d

& c, P  c1 v5 C6 n        // N106& }" @" h' ]7 Y
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 x" Y" n9 R; k6 l4 j0 W2 `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& e) R( b2 F7 x; _; [5 o        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  h& o1 Z2 B" v4 `        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 H; D# i- x: r2 ?. `) P! T3 T2 w        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* C. t$ O# G& Z0 I, b8 |
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- V0 B2 t' y* b  t; W6 P        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 ~; I9 @4 x2 I$ B/ }        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ?+ R+ V5 L" S3 d/ T* M" T

# C$ i; Z6 r) j0 r7 ~        // FME7& B8 L5 \6 K/ @: Q
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 n  Z6 W9 h; j8 ?, E8 |& T9 x9 [6 n        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. V1 T5 ^( w) l6 Y) |4 |
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) I  o  o1 b* l# i" Q0 @% b! O1 z" ?5 [6 }& C
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& I1 J/ a8 l/ v% `7 V( c* n        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;) W" b; {6 h+ S* d5 F

1 \* k1 a* ]$ H; o+ Y0 d        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
2 {, C2 W: R5 \% ~5 N4 S; W        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: E& ]) t  e+ d3 u
                QueueFlush();) s; H0 `, j/ r' n& d
        }
9 j! `' ?# S2 M, Q" ]: j& S2 ~% f: Z3 O1 v
        while( dwLength-- ) {  s8 D. U/ o" ?! s* u* f
                writetime = (DWORD)elapsed_time;4 K3 Q* w7 B) C3 H

. h  z8 Q4 W; P0 p5 r1 g5 o                while( GetQueue( writetime, q ) ) {5 Y$ j- e- y& \2 |
                        WriteProcess( q.addr, q.data );' [% n* R, l3 U3 Q
                }
" S/ J: B3 |3 C
7 D5 u3 c- X' Z, o                while( GetExQueue( writetime, q ) ) {, J% w0 S- y; q" ?! q
                        WriteExProcess( q.addr, q.data );0 H( @* j$ c4 P" H
                }  X4 v7 I- |4 R; u. U! R4 q
& g: H6 i- ?, G( n+ L$ p$ b, [  ~5 y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
6 m, j9 N# e  H2 ?                output = 0;
. I( e$ t* d3 r; j) I: {3 A                output += internal.Process( 0 )*vol[0];/ d) q8 h$ O0 y# K/ f; `& e( w
                output += internal.Process( 1 )*vol[1];# _$ m5 P# K/ J" L& S6 \8 B
                output += internal.Process( 2 )*vol[2];
; G$ O, f1 x& I% i# e                output += internal.Process( 3 )*vol[3];, Z; s' d' ]5 k; ?% }# y
                output += internal.Process( 4 )*vol[4];
( ^1 ^5 n; {9 N( c+ N9 s' T3 `: z8 n  P3 X  F; |
                if( exsound_select & 0x01 ) {
9 s4 b4 _2 o% f* ^                        output += vrc6.Process( 0 )*vol[5];
% U/ d7 U( g! {7 v. U                        output += vrc6.Process( 1 )*vol[6];, c2 f+ O1 d2 Q8 b
                        output += vrc6.Process( 2 )*vol[7];7 t4 z4 y( a2 j9 E6 k* o6 p3 X
                }" g7 x6 S: ^4 m
                if( exsound_select & 0x02 ) {  x* h7 U4 G" i4 a, Q& M) ?
                        output += vrc7.Process( 0 )*vol[8];
9 m; t  l/ h6 `  k8 E* `                }
6 E. ~$ ]" P% i: R3 K; o5 K7 x; A                if( exsound_select & 0x04 ) {
' j' w! K$ T! _                        output += fds.Process( 0 )*vol[9];
$ {6 S- b3 @) U9 ~) Z& B! h+ O                }
1 E# M% g" l+ t- k$ u* {" |" h                if( exsound_select & 0x08 ) {( }% B  `" [! f' y9 f- m3 R4 j
                        output += mmc5.Process( 0 )*vol[10];% k$ W4 C: Y: e# Y
                        output += mmc5.Process( 1 )*vol[11];
# O; _# Q4 u  O# a                        output += mmc5.Process( 2 )*vol[12];
5 z5 O  C0 Q0 [! {/ J/ t4 T                }
+ L8 C6 l7 y0 j5 u1 x5 h                if( exsound_select & 0x10 ) {
! x+ f; k3 x( j3 J% H2 L: t7 c0 V2 l0 x                        output += n106.Process( 0 )*vol[13];
' |) I+ R' L1 f7 O, [) y2 b                        output += n106.Process( 1 )*vol[14];
: d' k  `; R  ?+ @) S) j                        output += n106.Process( 2 )*vol[15];: _3 e- }( C: q
                        output += n106.Process( 3 )*vol[16];
" ~7 X# s+ Q& e: Q8 G+ o6 c                        output += n106.Process( 4 )*vol[17];
  V$ R5 P  n7 @% x: H& e& P* b                        output += n106.Process( 5 )*vol[18];- t* ?1 @% M1 c$ C/ V" C$ |
                        output += n106.Process( 6 )*vol[19];
2 N4 a0 H' U, z                        output += n106.Process( 7 )*vol[20];+ [6 @/ p. l' ]9 P' R5 {
                }( [2 S! Z: }. B' S" l
                if( exsound_select & 0x20 ) {
# g. G; k' L2 V$ g6 {                        fme7.Process( 3 );        // Envelope & Noise
! B; |" ?  v( X5 G' r* J; P# Y                        output += fme7.Process( 0 )*vol[21];# |" Q6 C/ o# ~% F7 |
                        output += fme7.Process( 1 )*vol[22];
, o: r8 N& O/ W- L. C. _8 \- ]                        output += fme7.Process( 2 )*vol[23];1 T4 R3 Q0 V+ y: K  p8 N2 p( ?+ M
                }
5 Y% V! C+ F; R3 `( I7 y3 u
) E- g3 a$ P- @# i; G, q5 m                output >>= 8;
, F' f& b& s0 M/ b  K. x4 A: F9 E0 K( ^8 \' X5 k6 K
                if( nFilterType == 1 ) {
4 D1 f" F0 q7 \. w                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
1 c" b" J/ g. E1 O- I, N                        output = (lowpass_filter[0]+output)/2;+ q+ o1 F" [( [  @. b
                        lowpass_filter[0] = output;
* @% Q7 P, w  y% P1 @1 l! d0 T9 R                } else if( nFilterType == 2 ) {' L5 J6 h; f4 I+ C, p
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
. L4 A- e- F6 n7 C* ^+ G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;6 J2 m3 P" B& _1 P3 m
                        lowpass_filter[1] = lowpass_filter[0];" q, r7 r+ c: z6 u( o3 n
                        lowpass_filter[0] = output;
$ q0 T' Q! b2 K- }/ N                } else if( nFilterType == 3 ) {' S6 q, x& \* Z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)# I' b- r* d1 g- t/ o6 h
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
! W: ?! U; b9 G7 N4 |# F' S! k                        lowpass_filter[2] = lowpass_filter[1];- N: ^/ p7 m) A& o$ [
                        lowpass_filter[1] = lowpass_filter[0];
9 m* f: B# I4 s8 n) b$ Q! H% `. L                        lowpass_filter[0] = output;
/ k! L* |0 [: r- t                } else if( nFilterType == 4 ) {
3 F, e# R2 T3 m5 L                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ }! S* ~, ^$ t8 w; b                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
6 K3 z7 {" ]- u9 p$ M                        lowpass_filter[1] = lowpass_filter[0];! `9 ^6 p' l2 E# K; L9 X
                        lowpass_filter[0] = output;) |  P2 W6 e+ w/ o
                }
' D7 a4 n7 A* k: |" ^9 c# w. c" O% [' p
8 q# F0 |" i6 }: }6 T#if        0
. I  r. O! y/ Q0 m+ Q% q                // DC惉暘偺僇僢僩
- w% o! _. S# Z* s6 J6 }                {: d8 J1 L( H1 ^
                static double ave = 0.0, max=0.0, min=0.0;6 X% H% o& n7 f' ?% ~( H4 Z* e2 s
                double delta;+ d7 r* i0 x5 p1 E0 _3 A
                delta = (max-min)/32768.0;6 y7 D4 l, v* S$ f0 o% a
                max -= delta;
( Q3 r+ `1 O% F/ r- m' s                min += delta;" _- {  |, k. W( d  B, h0 q
                if( output > max ) max = output;
& D8 ?+ v1 ?$ ~1 I" y* n                if( output < min ) min = output;
# J2 @2 q, ^- |: j                ave -= ave/1024.0;
/ X& k9 d+ G) W: i$ L' k% O                ave += (max+min)/2048.0;) O$ r. H1 o% x+ c% K
                output -= (INT)ave;
; M2 H2 C% w8 @. }) C# S- J( w                }
) r5 S! B! P$ o0 T, V6 [#endif# l% T# {! e; z! f- G
#if        1( o5 G- r  \( u* ^0 i
                // DC惉暘偺僇僢僩(HPF TEST)
, m) [% v- ^& j5 W7 L                {. T( F7 `" ]* R9 J0 j
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
# X$ _& k( c% F) F                static        double        cutofftemp = (2.0*3.141592653579*40.0);6 I6 {1 _0 i. D( p! w
                double        cutoff = cutofftemp/(double)Config.sound.nRate;' r+ P2 A% m3 I$ H; P# J+ D8 B  I
                static        double        tmp = 0.0;' M4 F1 v3 [5 }
                double        in, out;
' z; y" W: `( t, K" \: _: G6 }; T: A9 L, b+ n
                in = (double)output;+ U8 X( ~/ J4 W  s
                out = (in - tmp);
4 {* b9 H: H" `  ?                tmp = tmp + cutoff * out;
. R, m- {! _0 Z: R9 x0 E. X$ Z. c. h
                output = (INT)out;
3 E, W9 I  w# U) ]8 n                }
- [6 S* w3 O& I#endif& f' F: [) {. W' D$ d, M) ?
#if        0# L9 B/ T$ G) z3 k7 E
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
" X5 i/ F6 \# `4 a                {
8 F  e* ]- u! K4 D0 x: T6 Y                INT        diff = abs(output-last_data);
% u+ a$ a' l2 K                if( diff > 0x4000 ) {
' [- B" J( i+ M2 W9 x- F. o, I" `                        output /= 4;" S  i4 i9 }9 L! N& |
                } else $ |! f) n& C7 e% d, T
                if( diff > 0x3000 ) {
: b; ?/ \: w8 G" L9 G8 d( b                        output /= 3;9 M& Q6 E# l1 I' O' R, w8 [$ s
                } else+ N2 @5 P2 Y% Z  N6 _
                if( diff > 0x2000 ) {
+ n$ g% t4 E, ?- z8 o1 W                        output /= 2;9 s/ Z$ o, [  w& |
                }. K- N' l6 o0 r
                last_data = output;
" c/ e( \; Y; \$ Y* c$ L                }: V( b5 k$ h* e- g0 D
#endif
9 Q( Z% Y8 e* L8 ~& o) V3 u                // Limit
! _, }; O2 E) G0 ]+ {5 l0 Z                if( output > 0x7FFF ) {3 ?1 X/ A7 Q- N0 \: {' J" V% K
                        output = 0x7FFF;
7 u1 x8 i/ f% P; G+ q                } else if( output < -0x8000 ) {
6 D9 W% t0 `; Y6 a1 j                        output = -0x8000;
$ a$ h/ h3 b  u, A1 Z& X                }
; F+ s4 ~" R. e. z* A9 {9 P5 @2 g' p$ ~/ u' _. M, q7 u
                if( nBits != 8 ) {  z: e; K& q9 ?, \
                        *(SHORT*)lpBuffer = (SHORT)output;
+ e$ U' H7 h/ |# z( x9 r/ }                        lpBuffer += sizeof(SHORT);
& C2 N% E9 o  h" a. S                } else {
2 _- j# w# n& ^/ \- C+ E                        *lpBuffer++ = (output>>8)^0x80;
* w, o1 G0 E* i" [                }
' g( p% f5 A- T
9 z0 Q+ d+ _; @7 H' d                if( nCcount < 0x0100 )9 S7 i) S$ I7 ^  k: v! R0 h
                        pSoundBuf[nCcount++] = (SHORT)output;
: k2 o5 g! d0 w  V, c9 S& }3 Y% r
2 I  z6 l. J0 }8 r! m/ ?//                elapsedtime += cycle_rate;
& N1 X# Q7 v% A                elapsed_time += cycle_rate;
8 {! k: o8 j3 V- N: M& Y$ P        }
9 G7 z9 N7 Q. T" \# t( d
& v; E, ?* f- P& [1 t: J#if        1
" {/ O! p6 L* s8 Q. n        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {1 h% l1 W8 \! N1 N
                elapsed_time = nes->cpu->GetTotalCycles();
1 C. F& _) j7 r6 H* n        }
) R6 }9 _1 V) p# r3 D$ y        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {) e; u3 y$ X: h) z4 Q
                elapsed_time = nes->cpu->GetTotalCycles();* P/ v9 R# o9 p2 }
        }
% V0 O* `' \. H1 g3 J#else1 H2 `( L9 r2 }
        elapsed_time = nes->cpu->GetTotalCycles();
4 U9 P' C9 r+ G) \( c* n& d#endif
1 [% B9 `* C3 Y" ]6 K}6 A8 L) W# w3 U3 ~: d
1 H" ?  I1 r4 N. F- C. m
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
7 `( h  c3 B7 L* L1 ZINT        APU::GetChannelFrequency( INT no )5 s; M. o) _6 M0 W5 y
{
% C' R2 E& f! e0 i' ^6 f# r        if( !m_bMute[0] )
$ h. c+ y- h( @                return        0;% O6 A- Q9 u( r: G/ Q  Y
: y+ M, s2 k  e/ ?
        // Internal
/ d# U4 p$ F: }* n4 t# Z        if( no < 5 ) {
2 c/ p6 s! X$ V' J- H                return        m_bMute[no+1]?internal.GetFreq( no ):0;4 M3 Q) l9 L' J
        }  j, D$ E3 i# W  l  D7 k
        // VRC6, `+ o, o: l( n( i4 [% y: Y2 T
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! ?# s; Z6 Q! K- t1 O                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;0 J- r3 w" ~. b# u4 C
        }# s! j3 r; A: w
        // FDS+ D$ c5 `- m3 e2 |$ w) U
        if( (exsound_select & 0x04) && no == 0x300 ) {  [$ b4 _5 u5 S+ k! J+ T
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
* \) I2 S3 i% b: m5 f9 k/ w# r: r1 X        }
- \+ j' l, A7 J/ H$ h# e        // MMC5
; p3 j" a' U& w6 p/ g        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {/ P8 u* j2 l# J- j
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;; A! ?0 ?, j2 J
        }3 W2 C( ]% Z* X" \9 X# c6 W
        // N106' `7 B  A6 C2 ~# [6 y4 P4 J! U! o
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {, r! T1 A% O; A) U# O3 ?
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;8 E  W' l# K$ P. W8 q" y
        }
+ b2 u/ M2 Q8 ~1 h& G        // FME7$ y9 C" ~4 h0 @% ?( K/ Z" C1 p+ M
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {1 ?2 \5 V* C4 M# l
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
2 [5 q, ]( r9 D        }
/ K; H2 E2 \8 T1 x        // VRC7, v1 Q! v/ ^" T! T1 H
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ _  Z& {6 F/ I" {& Y                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
  k7 Q: Y2 ]8 v6 d5 I# M3 N3 u        }
3 e6 s5 N# ^# [6 e- Z* a, T        return        0;$ j% z0 i8 Q. m% z  z
}0 \1 m7 y1 L# @/ Y* |  Q
; O# W2 u! r; |
// State Save/Load/ s& y! W8 R2 n% l* Y
void        APU::SaveState( LPBYTE p )
3 j0 Y: B8 \/ [1 y{
! d! ^, s" W8 o, w5 ~8 `#ifdef        _DEBUG
: |' j! k3 n1 m8 O0 `6 G7 QLPBYTE        pold = p;! e) |$ w( M1 I8 _6 w8 _+ y* r
#endif
5 A& l1 {1 a) B2 \; d# I5 }+ _4 h
; Z7 Y) t+ |6 U! C4 a; d! u( L8 z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞" \& r0 h: _- W. X, k& {# t9 h, T
        QueueFlush();
+ X: I' ?" m% ^
) v$ h1 C; y1 @" ?: \        internal.SaveState( p );% o4 D7 R( A3 w) r& L* R0 b
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 D' c6 \4 z& Y' O2 u
8 M/ b7 F- h8 n5 q! F6 i
        // VRC6% @/ i& m* q7 a: I/ E$ c6 g, ]4 |
        if( exsound_select & 0x01 ) {! H# @# ^) B, k
                vrc6.SaveState( p );
3 Y% c' g8 E6 t6 F' b5 g+ s5 b                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 i" H( E9 D5 P  u& ^9 |. Q+ V$ @
        }4 Y9 E3 [9 c8 `- y- Z6 }
        // VRC7 (not support)5 z. D! x/ h# e5 {% u+ r4 p
        if( exsound_select & 0x02 ) {
. k6 h0 G. ]4 {1 W                vrc7.SaveState( p );3 D6 K2 i, I5 S7 ]
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" {2 Y3 @- D6 U* g/ [6 _
        }9 ?8 `2 P- U( b! R; t' L
        // FDS
3 V5 P+ c5 b* b( O        if( exsound_select & 0x04 ) {+ N! U  }, v& ^9 K0 _; ~1 }- m5 R
                fds.SaveState( p );0 l8 z- `4 w- B# H2 b/ q
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 m2 [* _4 A  _3 n8 G& O! q( }        }
9 w; c- z# [4 G# _        // MMC5( w  l9 s# \& B' ]& ]
        if( exsound_select & 0x08 ) {- M* H' w/ `# x6 ]7 I7 M
                mmc5.SaveState( p );
9 P) F4 z7 ~* Z                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: t( }9 a' c) `) v# O% t; X( m" n        }
( x/ @# q* s  V* `( C2 K        // N106
6 a) I# ?% ?7 U9 q$ y) B! U        if( exsound_select & 0x10 ) {
( M4 r/ ?% Y/ N, f( J! N7 `                n106.SaveState( p );
+ `. ^- G# o/ D1 y+ b                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 y: R. l' z: y% u7 q        }
( Y. \  U3 C3 s2 H# i        // FME7
3 ~" q- ]; n! V        if( exsound_select & 0x20 ) {% `& b: b; R0 Q7 P
                fme7.SaveState( p );7 [0 R9 N! p: K- z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 ?3 `2 k( K" g6 ~" w/ M# J        }
3 H$ d/ l' m0 G& o. P; L  s/ y0 [
#ifdef        _DEBUG
/ k6 B& t) G# r" P/ n" L3 ADEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 Z& Z& j4 v5 c1 ~0 |% {9 Y#endif
9 `3 N% ^/ U( a. B% I- ]9 A6 U}
/ a: ]" F8 w* d! J1 y& @
* }' O( ]# K" \# G/ I+ M; N6 ]void        APU::LoadState( LPBYTE p )2 y+ R( Z5 C. q3 ]9 F; ~  _
{
# P$ d* l% z1 R$ d4 d        // 帪娫幉傪摨婜偝偣傞堊偵徚偡: w" e  ?% j& s, y) i( G. |% G
        QueueClear();, X- B/ ]: p  r5 s8 N" y7 H' d
& h4 Z+ u3 D% F3 l1 d  O
        internal.LoadState( p );! ]$ Y: `% u& T, V4 x) X
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) x& X9 j6 _( d' F4 I/ q& x' r

. m1 d' o+ w0 x+ }; w* n& C8 d        // VRC64 N% Y5 d' w% q  b. N# r
        if( exsound_select & 0x01 ) {
5 g4 r4 p2 k6 ?" o( u2 T% h                vrc6.LoadState( p );) v4 Q' X6 T9 \. `2 }' I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. M. w3 R' |/ `        }
8 ~: G3 @, ^& t* G: p; `" F* r) o        // VRC7 (not support)
) \& M& ]! F, P: ~8 x! b5 f7 Q        if( exsound_select & 0x02 ) {* J! k+ h3 k3 ~: f& E
                vrc7.LoadState( p );
$ H" b1 ~5 E$ g$ z! E7 _                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# r- l, ?, ^, v9 M* [# N3 U        }; @  ~7 `. j0 ~4 F3 @
        // FDS
% E/ y( c/ ~! K: j        if( exsound_select & 0x04 ) {+ P! d% q( z: E0 L1 L
                fds.LoadState( p );7 ]+ S$ t8 X  x# v% n- I
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 v) Y  e" t9 \1 x- a
        }
4 g- r/ X5 J6 Q* K7 F        // MMC50 ~1 [* [/ Z& M# w' a0 }
        if( exsound_select & 0x08 ) {
* s2 ]. _: S4 F' S! u- D2 M                mmc5.LoadState( p );
+ _: f5 Z  L$ b: h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding) x" {: x' P4 S' C0 h
        }
) j, [. w7 y  Z        // N1064 ^* E2 O* P8 o5 C/ S  ^
        if( exsound_select & 0x10 ) {+ E, n& s* ?# s% D3 L1 b  U
                n106.LoadState( p );
' g( I+ R5 \* m& c  d! a                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 A* x4 W' `$ `: ]* D: `        }
1 Q$ a( d1 Q( S6 v        // FME7
9 x! ^6 }( R+ N; g6 m4 R* Q        if( exsound_select & 0x20 ) {5 _6 Q: I3 j3 V! I* Z
                fme7.LoadState( p );* G6 e7 k/ p) W" F, L1 y9 H5 [+ |. w5 I3 T
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' A- v# g" r$ G6 x/ a6 e& ~+ B+ g        }& j$ ]9 H3 I0 u5 w2 q$ ]* @
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
. g6 z( f/ t- {2 m  k3 N0 z2 |; Y可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。7 }5 {! X& y, W. R' S5 F
感激不尽~~

7 A: p5 w# |3 d8 U* J& g+ D- d& P恩 我對模擬器不是很有研究,
  \' h0 W* @( _雖然要了解源碼內容,可能不是很困難,7 q1 t6 ~: i. k' Z1 T7 w- @2 G7 z0 ~1 B
不過還是要花時間,個人目前蠻忙碌的。: |8 t8 H- P+ Z
( N3 G% ^2 S. z0 V, j% D; }  u
給你一個朋友的MSN,你可以跟他討論看看,
) ?# s, {' U$ A0 F# ^/ I+ Y他本身是程式設計師,也對FC模擬器很有興趣。" V9 c% ^  o: W2 R, h
& B- v- b1 B# p; l4 ~$ o4 a4 v
MSN我就PM到你的信箱了。
3 @; l5 O5 ~% O: N& B3 }  i
  @' d+ p. M& P: r+ 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 发表 2 B* `3 ~8 G4 a% C. L
呵…… 谢过团长大人~~

9 w* z) T" l: G7 {+ j/ r+ s
& V+ `% M7 l3 p哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 @. E6 p! l% N+ s, o
团长的朋友都是神,那团长就是神的boss。
' f0 N* m# d! L( T3 t$ D7 z9 U
哈 不敢當,我只是個平凡人,# ?% w5 V  p" p0 P8 D% A
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
' Y( G; K/ r0 q0 m; \& sZYH
0 z3 x+ U, X8 ?' q/ C# L0 [0 sQQ:414734306
) v% G- K; S! d) m! t, ?: d6 z) kMail:zyh-01@126.com
; L8 f, `( e( A2 |8 _- B: z
; _% e4 E& i: U. T3 s他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 ^+ u* V) {0 @0 E再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 {5 K, P8 q8 ]
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-7-6 17:58 , Processed in 1.071289 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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