EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( y' C  M/ U, G; d3 t2 h楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) ^- C, z+ E) w! G
这里有相应的模拟器源码,就当送给大侠了~~4 q$ Z2 v" d4 V/ g( A8 h4 H
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# }% n# k+ V. v. r能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 W6 B' F( R: r4 v9 ^楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 h9 ]. t- a/ ^% I' J这里有相应的模拟器源码,就当送给大侠 ...
! t: y. V3 z7 k( ]2 [1 w
聲音部分(Audoi Process Unit = APU):
' V- g1 m* F  j7 z% o1 o$ q.\NES\APU.cpp
  Z& o9 R  q, k2 Z4 ]- {6 i.\NES\APU.h3 r$ m6 `6 t" }, T' |
! y0 R! B+ I7 z% |, @9 g; C: x

/ p8 H/ O8 ?* g影像處理部份(Picture Processing Unit = PPU):$ ?) I; l0 m' w0 H' t/ B4 Q. q
.\NES\PPU.cpp
+ b. O% b/ H: h$ u, ^.\NES\PPU.h8 R$ G6 O) p/ D7 z. V4 O( Y

: ]1 U) A. \: J0 L- X如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:' c3 N4 J1 R/ z
(由于很多专用术语和算法机理都不明白,所以看不大懂……)) X7 f1 l0 t5 J4 i* x: L
//////////////////////////////////////////////////////////////////////////
3 L# F1 _; ~- M( [: x//                                                                      //0 M' m5 z; _( @% M; H  H- C7 j* X
//      NES APU core                                                    //+ O; ~% |0 x$ s: H$ o+ e5 A
//                                                           Norix      //! I$ O( i/ ]3 D& A
//                                               written     2002/06/27 //
, j! b- [. p4 a5 V//                                               last modify ----/--/-- //
  t2 t' @9 w" s: ?% E1 p  x! {; ]% l- i//////////////////////////////////////////////////////////////////////////
5 d2 r! U+ o" W) \3 o#include "DebugOut.h"
4 c* Z' y1 H9 [/ v3 R  k#include "App.h"9 e) }/ Z  B4 @* Y' r* O# K  ^
#include "Config.h"
! S) R, D' p7 X! C2 O6 K
6 ~3 R; R, n! |1 v$ N#include "nes.h"
. }, s! |% M2 {' Y! p#include "mmu.h"
: I& e" |1 O( W1 N* i8 Y* v#include "cpu.h"
) Q3 J3 K, m( M, v#include "ppu.h"
* U& Y+ Z) G2 y# x3 f- j/ U6 ^  M#include "rom.h"
, Z7 g- r' f+ t& H1 w! D0 Y#include "apu.h"
4 ^* f5 g5 L1 c9 @7 d  d/ ~
; L8 m! p/ |4 h  S// Volume adjust& A' T6 y7 Z7 i( k
// Internal sounds" y/ q' {& R! Z5 I% T4 I- [4 o
#define        RECTANGLE_VOL        (0x0F0)$ c- W) Z' g2 d8 b, ^  L
#define        TRIANGLE_VOL        (0x130)3 Y' o) Y& p1 g* f$ `
#define        NOISE_VOL        (0x0C0)
8 Z# [: ]2 E9 i) i, d/ J! G3 r#define        DPCM_VOL        (0x0F0)
. s/ N) {7 [# O, j* I( b// Extra sounds9 |! h2 P5 Y4 c6 Z( E# O' T- x
#define        VRC6_VOL        (0x0F0)1 Y1 I& P4 F- F' f0 J, Y; {8 r8 K
#define        VRC7_VOL        (0x130)
$ I; j/ q* P- @8 j2 y) Z8 \#define        FDS_VOL                (0x0F0)9 l6 A6 |3 t& }
#define        MMC5_VOL        (0x0F0)7 y0 @7 r1 p( b9 O" a+ ^& [- L
#define        N106_VOL        (0x088)8 A1 g  K8 i; j' L3 b/ Z6 r6 _9 m
#define        FME7_VOL        (0x130)  X: c  z. R& ]. i+ J

: w# o% ]. @' t& DAPU::APU( NES* parent )
+ ]7 A- d4 E  I! U* e: K{
% n. \6 E/ c" {% R        exsound_select = 0;1 V' |+ ~8 x) q& d; I/ j5 j

+ j  R5 a7 C& w: ?; e$ Z% z% e( G        nes = parent;/ f8 L* j0 f; K# l
        internal.SetParent( parent );5 \6 E8 T) T4 G$ d4 p, V7 O3 j
' s# |5 |; N* o, H$ o, `
        last_data = last_diff = 0;
6 s8 C3 m( _1 H# r( z+ g" M2 w# j! U9 U; z: S- r0 S+ M6 c. i
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 Z0 I) [; m2 H3 V
6 V5 q$ n  G5 B: F4 X* ^
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );$ o  q* O1 Q" {. o  r/ a3 B
        ZEROMEMORY( &queue, sizeof(queue) );4 M0 C/ n- s: Q. i2 a8 B# X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: R8 C8 z2 E! q& W9 i& t: i

+ v: P5 L+ Q# }        for( INT i = 0; i < 16; i++ ) {  W5 H5 V0 ]! J2 d) \& _# N. u
                m_bMute = TRUE;; C; B2 u  ?* b' L0 H; l
        }
9 v7 s3 o  \! I  b/ ?5 X( K}
- Y5 ^' c, A4 n4 _* R8 ?" q% Q" b' s4 X% j% C& m
APU::~APU()
4 j# B" C3 o2 S% M{# p1 b, P/ Z" C1 y3 T: \! F
}, x, B6 ]* n3 L7 w9 O+ Z+ m

8 o$ [+ ]: H- \  Kvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& r: X4 e5 ]0 \* ]* G4 |( S
{9 W7 Q* Y2 k8 m6 k- A( U: _3 Z
        queue.data[queue.wrptr].time = writetime;; h4 [, a8 X, Y, b# ^
        queue.data[queue.wrptr].addr = addr;
# G4 t: ~7 i$ D        queue.data[queue.wrptr].data = data;3 o& U6 y* Z3 ?" K- y7 c1 c
        queue.wrptr++;
! b8 K9 W9 J6 V1 n6 D        queue.wrptr&=QUEUE_LENGTH-1;+ \, [' }; f: F: Y2 _" h. y2 D
        if( queue.wrptr == queue.rdptr ) {
' Z" w7 x+ H: d) f% m4 O  q                DEBUGOUT( "queue overflow.\n" );; z% u1 N+ C- ?+ L2 }+ q
        }) [6 i, M( J. [. t, z' O" _% u
}
% b$ W  V1 J5 r+ b( D9 K! m
1 g% u# a$ y! ~! G, V% aBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )4 T' O' a; A8 V" L( n9 L
{
8 y, H% o$ T. g/ V        if( queue.wrptr == queue.rdptr ) {
; d% X' d2 ]9 D0 \                return        FALSE;, ^! F( ^( D) v( i! B
        }9 s' h0 k: R/ @. @5 ?
        if( queue.data[queue.rdptr].time <= writetime ) {! \5 ~1 ]! `# e) w) P
                ret = queue.data[queue.rdptr];: u9 H( J3 o+ c3 g& S: R1 Z& r
                queue.rdptr++;
( `/ A" I4 }" I4 E% D2 d+ W9 X                queue.rdptr&=QUEUE_LENGTH-1;; Q/ u" j) ^' T: W: _& |
                return        TRUE;
& D) s' B( l7 Q8 G        }/ T( j: \5 U- d  K2 K6 _1 Q9 F
        return        FALSE;2 m" E" E3 H0 I! ?2 X8 U/ U8 z0 I
}7 ^/ m5 Q& u0 t2 ?# F' V$ B+ t

+ \  f4 z+ P& Z5 q. Nvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )/ S4 a! L0 w2 N
{
: a/ i+ Q. @  C; w: h        exqueue.data[exqueue.wrptr].time = writetime;
( i; M( z3 v* ?# A/ g9 I" N        exqueue.data[exqueue.wrptr].addr = addr;
& R  n4 D) N' I8 B  y: D$ P9 \' M        exqueue.data[exqueue.wrptr].data = data;
  |) q4 C, o+ U, U        exqueue.wrptr++;( k: M# I& R7 Y! G9 ~
        exqueue.wrptr&=QUEUE_LENGTH-1;8 M) D2 e# U" Y1 G6 E4 k5 _' i
        if( exqueue.wrptr == exqueue.rdptr ) {
, L' G$ J' a' ^4 p. p                DEBUGOUT( "exqueue overflow.\n" );
- V- ^3 z( ^. h        }
8 e& ?/ k4 B  V$ M}
2 k# B6 V1 K* N5 R& C: w' c
# q! v) ~# {; ?* B/ s2 `BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ }6 u. H7 A8 E! o! V{
+ B0 a; Z- |* y# L2 b' A        if( exqueue.wrptr == exqueue.rdptr ) {
4 H7 e( h$ X! y% Y                return        FALSE;- q' B- l) j8 t* N% n
        }) D) z9 g, H( ~% D5 B/ H0 B
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, W, ~& R6 I, s. q$ n9 f' {
                ret = exqueue.data[exqueue.rdptr];, x9 I. _( C$ H
                exqueue.rdptr++;6 w6 i& a# i/ \- ^; M
                exqueue.rdptr&=QUEUE_LENGTH-1;
% Q2 j1 a: r% |                return        TRUE;# E4 Q% N3 z6 `' Z$ Z
        }: h) J; O( i3 m. y  c# f
        return        FALSE;
" `$ M. O. Y, x3 E7 M5 {}5 r7 J  F  b2 S! ~
  {- d, y8 ^) b% Y. L
void        APU::QueueClear()1 r; b1 b; w8 u8 ]. a) d. S0 f
{
; J( I2 [! [4 x        ZEROMEMORY( &queue, sizeof(queue) );
6 {- K  @( {5 c5 M8 v        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" y: i4 \( ?6 X" k! `* F9 Y}
) d9 F7 z7 O" P+ _. ]$ I
% a- d( Q$ D; J( i  `& Pvoid        APU::QueueFlush()
6 H7 Y8 w2 A+ I) W3 A& N1 }* n- q{
, j2 J' q# q" ~. B. o        while( queue.wrptr != queue.rdptr ) {/ B6 c$ W7 y+ f8 |+ |( h9 o
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );% p; @8 H: m- V
                queue.rdptr++;. O3 \3 Q# a/ H# j; v, E9 a
                queue.rdptr&=QUEUE_LENGTH-1;
- g9 }( l5 G0 A        }
+ C+ @1 {( R* W! F$ L1 E2 M& P7 ]! k$ [  N' G/ b" c  X9 T5 a
        while( exqueue.wrptr != exqueue.rdptr ) {/ t: j$ R3 Z% G; i, E/ `5 K/ s; C: e
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );' X7 k* t! m* A* v% w! I
                exqueue.rdptr++;0 H/ {7 x  y2 v6 Y# V1 Q
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 a$ V# }  P# ~        }1 C3 v) p) ], |" n  M
}
% j+ d0 n+ U! o3 x6 a# U# I- [% n: u: ~0 D' T* Z/ ]
void        APU::SoundSetup()3 }7 h4 v! p+ z
{3 X1 V6 q! M" E3 l8 N3 ~
        FLOAT        fClock = nes->nescfg->CpuClock;
7 h" I3 u. D1 @        INT        nRate = (INT)Config.sound.nRate;7 K$ X0 A5 f- |( q* D8 n
        internal.Setup( fClock, nRate );/ |7 e7 Q8 [4 ]8 ^
        vrc6.Setup( fClock, nRate );
/ n. ^# d# e; G; s        vrc7.Setup( fClock, nRate );3 e( G$ J7 j" R( o( `
        mmc5.Setup( fClock, nRate );
) ]3 B1 e! N4 B9 w        fds.Setup ( fClock, nRate );2 R+ x! Q/ @. a- A) j" D) y
        n106.Setup( fClock, nRate );7 F9 B+ h( }; a2 Q  K$ u9 R
        fme7.Setup( fClock, nRate );
  P1 ?# m; f2 L) [}
6 n) a2 j/ }+ H; N
) G* w( u! X' h1 S" Q( {3 Mvoid        APU::Reset()2 L6 y( _1 ~) X- i
{
# i- ?3 [/ F6 A( W1 l        ZEROMEMORY( &queue, sizeof(queue) );
8 i. `4 p% [9 J0 M( Q3 Q* K) ^7 B: i! O        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) I3 r& \/ i( @5 c8 T' ?5 }' v: j6 X* P0 E
        elapsed_time = 0;: {, o3 Z1 a$ M+ C% X0 ^) o
+ \( A- a4 b4 f% _
        FLOAT        fClock = nes->nescfg->CpuClock;
8 i9 D) h' x* E5 l6 `2 {        INT        nRate = (INT)Config.sound.nRate;
4 ^9 \' j2 ~! T5 f1 R( N/ m( z        internal.Reset( fClock, nRate );" N" J/ [6 Y: |' Y7 s
        vrc6.Reset( fClock, nRate );. ]4 W3 {$ i- V* B: @" ~4 s8 i
        vrc7.Reset( fClock, nRate );
3 q2 k$ [, ^1 i- m# O* h        mmc5.Reset( fClock, nRate );" q/ N% i- i( i: @4 @
        fds.Reset ( fClock, nRate );. C0 g8 N/ J7 ~# W9 ?% r! v6 I( ~
        n106.Reset( fClock, nRate );4 ~( P6 f' X, C! I3 K$ ~, s# q
        fme7.Reset( fClock, nRate );* Q7 Q' v+ N2 `1 H) [2 e* d# q
, _. I- G* a$ F5 A4 c* z! y- n# D. ^
        SoundSetup();
* D) z9 R* U; r  [0 B6 D}
) F# P9 u. X9 L: u% ]! F$ X: k% _! ]5 [; J) G8 V3 ?
void        APU::SelectExSound( BYTE data )
, a* g" b" Z# `; O: r{7 p( L7 W0 r5 @! Z3 b
        exsound_select = data;
8 G/ ], \/ k" ~/ G7 Q3 O! N8 I* \}" s: H( w3 J& V+ C; W8 F  ^
9 b6 u$ j% N4 ~+ X- k$ a  r0 X3 N, ?
BYTE        APU::Read( WORD addr ), e" @0 k0 A2 U+ O. D( ]% E
{$ L) ^* C& {. t' m
        return        internal.SyncRead( addr );! W! v8 ~  {$ t/ w2 t+ c
}
! p4 r: s/ p  J3 b
: ^4 C& ]" {1 K, G0 H7 r6 ivoid        APU::Write( WORD addr, BYTE data )
- y! y7 r- i8 Y2 `{
  P6 a6 f8 n" \* O        // $4018偼VirtuaNES屌桳億乕僩
+ M) e  T' x; U9 \* Q        if( addr >= 0x4000 && addr <= 0x401F ) {
! e2 Z+ j+ O! m+ i  \9 g                internal.SyncWrite( addr, data );
2 [% o) c+ N6 h: f/ I* f                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 _5 ^6 g: g$ q, j/ x8 l0 `3 h        }+ l/ U; k6 k6 ?" U2 l
}6 O% s# N+ e, ?/ J! ~8 ~

0 q( l, |( G2 R1 k' b% OBYTE        APU::ExRead( WORD addr )
; h" B( H% f7 H  d+ E0 m! K: [0 T{
1 P5 l9 d4 }$ b2 I  wBYTE        data = 0;. y& T) ~! L# t
  u- V# K  `7 X! r
        if( exsound_select & 0x10 ) {
# p4 C( M# M, ~9 U3 p2 R                if( addr == 0x4800 ) {1 X+ `9 B4 q) K; _+ m) A. p$ o7 W
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );% G5 e& O. @0 C9 j  c
                }
4 i% H) P" @+ T6 }        }  R: V' N" @( g; o
        if( exsound_select & 0x04 ) {
3 j5 ~2 d. ~6 A( e3 J                if( addr >= 0x4040 && addr < 0x4100 ) {
$ {; F- O# r9 e7 G8 f9 k3 L3 K                        data = fds.SyncRead( addr );
( Q. h: M% A% R* H7 L$ g                }
6 C- y) Y  L9 u2 m) I        }
: h3 t% a0 w% K3 {1 [        if( exsound_select & 0x08 ) {
; y1 P; K* V. G                if( addr >= 0x5000 && addr <= 0x5015 ) {: K  g  k6 H; B* r
                        data = mmc5.SyncRead( addr );- H# [( |6 `; L
                }) g. z# m/ B; p9 C1 v6 B1 l  ]" R
        }
( Q/ l+ h- b( i1 G' x4 P3 w' Y% ^! e5 H( y# ~8 C$ q4 t% p' K+ s
        return        data;
7 i# M+ D9 c( _) t  V' U}
3 Q( Y5 w: q5 m. P9 i' Z1 z2 Z
void        APU::ExWrite( WORD addr, BYTE data )$ E- P, L9 _9 x* j( y; Y. P& w7 Z: N
{
) A) @1 Y1 o; E& f0 |        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 I+ J1 K3 Z5 w6 N! k4 p* h$ l

6 b: h7 g% [; C  F  \; H        if( exsound_select & 0x04 ) {0 J' F) l0 f. C* {; n  n# a% i" ]
                if( addr >= 0x4040 && addr < 0x4100 ) {  @, d4 V. L* s# ?4 C- p$ s
                        fds.SyncWrite( addr, data );
' r0 q$ U0 |, d6 R8 ~. D" l; p                }! T8 m, L/ p4 n8 u& Q# y( T; D* r
        }
9 S% y. R( x, t2 j( [* e2 H5 |7 E
: }9 l0 |8 n. C. q& G        if( exsound_select & 0x08 ) {) z; d! l) U; s" S; z
                if( addr >= 0x5000 && addr <= 0x5015 ) {
  G7 L0 S1 i# u/ _8 a3 J5 v                        mmc5.SyncWrite( addr, data );
$ Z4 Y4 T* \! c6 F, q- C                }" z% V% o6 D/ \. v
        }+ @% X9 ?& a" s  j$ x4 q
}/ u* }* N( O: e
+ e5 Z  C0 }, ~9 D& l7 M/ z
void        APU::Sync()& h2 b9 B. }1 n" {# z7 `- R- P0 ^
{: s* x6 N7 f+ V3 e
}
! N5 J+ i/ a9 `- Z2 k" ~3 {2 J+ h7 d& q( j. r0 c
void        APU::SyncDPCM( INT cycles )
5 ^; x( v1 i- P' [" B/ ~3 f3 ]{
* A: e: U+ U  I! |        internal.Sync( cycles );
% H7 Z. R; n3 j. y' A' j
4 i1 c# b( H$ s7 O9 J( r3 u' o% P        if( exsound_select & 0x04 ) {0 |. N3 m" E) P$ U+ z8 x0 a
                fds.Sync( cycles );" v* ]/ J* S; \8 p! X+ ?
        }8 k* J3 I! J3 J6 W
        if( exsound_select & 0x08 ) {
* _  k4 u( L# U1 u- s2 \4 f" C                mmc5.Sync( cycles );8 [) p- T( R; q4 x5 ~
        }
+ V' f: \3 H6 O7 W5 E7 J8 f" z& u8 @: z}4 x* ?6 O' j7 M' v
1 K8 k( b; e7 _; O
void        APU::WriteProcess( WORD addr, BYTE data )% c) t9 T4 U! L8 p
{
7 c& H/ G  y3 S' _, T& ]  }        // $4018偼VirtuaNES屌桳億乕僩+ n8 Z  N+ n' f/ c. a  o
        if( addr >= 0x4000 && addr <= 0x401F ) {' j4 e. N  @" g% y; b
                internal.Write( addr, data );* X8 y( r; U+ n: m/ |7 w
        }: B5 j/ W% q2 z- h) l7 ~; v
}  ^4 m0 i. b$ H6 D8 _
; S0 W/ k8 \3 ?4 b% h' k& I! C
void        APU::WriteExProcess( WORD addr, BYTE data )
! r* X  n4 Z2 h; d{* d6 f1 L; y" w5 o9 W- c) c: I
        if( exsound_select & 0x01 ) {" u' \. c1 G7 r, r  v: Y, k3 P
                vrc6.Write( addr, data );6 v8 [* G: s* G4 a9 O. s0 O1 p, q
        }( R$ H, \& o$ i
        if( exsound_select & 0x02 ) {3 E% F/ h" l7 J8 u+ R3 U+ d' F- r
                vrc7.Write( addr, data );) ?0 k! U+ V- g
        }5 f3 f5 t5 {5 O1 Y- Y
        if( exsound_select & 0x04 ) {
$ u6 s2 t; U& J$ p                fds.Write( addr, data );
2 \  |" W! B. H  U6 F6 q) K        }
; @2 |* S6 t1 t& e        if( exsound_select & 0x08 ) {
+ i0 m  d2 ]% V  j3 r) J                mmc5.Write( addr, data );
3 |/ A) Z0 P4 g+ {; f! R        }/ X' E  A' _- ~( A9 D) z; S
        if( exsound_select & 0x10 ) {: p2 P& G/ I0 Z4 N2 m
                if( addr == 0x0000 ) {
7 ]. E3 K. m6 a& ~                        BYTE        dummy = n106.Read( addr );. J! g+ Y0 w- [9 w3 y
                } else {
7 Q  P; K) u) H5 p# \1 f                        n106.Write( addr, data );" o0 _# {9 I. _
                }( Q# C0 b/ o5 {9 T/ V) s' s# z4 O
        }. D; |# g% x+ o. D) k9 V$ N7 J1 h
        if( exsound_select & 0x20 ) {1 c$ H( r3 I) P' `! k  W
                fme7.Write( addr, data );+ I. }/ n8 N' D) X, v
        }% ]6 p! e1 K! |
}
; v( _6 {. o1 y+ q7 G. R9 n9 `( o& o' O# Y/ h! T8 P
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
  r" e3 {* i: B, }" a8 \. H{
% I6 l$ [0 U. ~$ [INT        nBits = Config.sound.nBits;: r4 ]0 G% e' ~/ [2 Z
DWORD        dwLength = dwSize / (nBits/8);
9 q4 R" L; y; VINT        output;
% J7 D5 k- |6 o& H4 MQUEUEDATA q;
* P1 r3 T; v% E( @7 z% x- lDWORD        writetime;
: J* X' G4 C; E3 H2 K8 y, a& h2 k2 g1 |' d* }) H3 ~# ]
LPSHORT        pSoundBuf = m_SoundBuffer;3 R% v" B4 y+ e) O3 p5 i! l
INT        nCcount = 0;
+ t. _3 W  v+ U3 i9 ^5 g; \' S
; ^. W0 }1 D% O3 [' s) TINT        nFilterType = Config.sound.nFilterType;
% _' D3 y8 Y; p' g: i
1 q7 r! s* A  o( m2 }4 ]4 ?        if( !Config.sound.bEnable ) {
0 ^7 N7 H, f4 }% A                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );2 D+ J) I/ o" Y3 r; ~
                return;
! a! U! T4 C; u/ y! t5 t3 ^        }# q5 P6 i2 R3 S& A* f! d

! e1 R; \+ z0 L% G) {+ ?. {+ g        // Volume setup! e5 t. Q. I8 [  Q
        //  0:Master
8 I$ u% i& S* Z        //  1:Rectangle 1, l5 z. f% o" G- ^% O: w: r
        //  2:Rectangle 2. l& f) r8 j  A# a% |, m9 w8 }& m! w
        //  3:Triangle5 k% ~" S6 j. V  W% T
        //  4:Noise
2 z; ~6 h7 T3 A2 q        //  5:DPCM
, j  h/ [6 T# \. q$ D        //  6:VRC6
6 d6 ^" D8 {1 k6 d# X$ U2 }/ ]        //  7:VRC74 P! b( k2 d( E1 n$ N. C. o
        //  8:FDS; y2 m3 K3 m9 \8 s$ T2 a) H
        //  9:MMC5
8 V/ \4 l8 q4 E0 A- I        // 10:N106
- a9 Y4 a8 x6 h3 R  R% i) t" ^        // 11:FME7
( C$ h5 G9 E( H! r& ^        INT        vol[24];5 q8 \; [3 w  ~! O+ L
        BOOL*        bMute = m_bMute;
# @( n( b9 R; s9 _$ X4 V        SHORT*        nVolume = Config.sound.nVolume;
. D1 K. `; }  D' M. e/ d/ `4 _4 Z6 D- \8 a8 T7 R8 i
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;. x& \; f' D: s& p" `; t, W% C: w
2 s7 E. n* n; H: g: h1 I0 S
        // Internal
% |, N2 u8 ]% I+ X% Y, R& G        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 m0 Y( `( R/ `5 Q6 g; k
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' x- w  D& D7 y6 _9 k1 H, t        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 i& t' A4 @/ z# b. a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
# P; h' p  R" r3 }+ T1 X        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;! U; x0 r0 S. @' E" u7 P

2 M. x3 _8 o& K6 G7 p        // VRC6
4 Q1 n# Q- q6 v0 ]; C' l; U0 d        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ F+ C5 j3 N5 y& _8 _! X
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" P( E9 l  Q* [. ?
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, U; Z8 i) Z' o5 v$ S% V

) f' ?6 e. f3 [0 M; y        // VRC7
/ @- q& E; Y% {' G( `3 Z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;5 ~+ B  K4 E/ M2 h! A. a, g: E
9 i3 k! K% J' D) y; I
        // FDS+ H) K1 c9 K1 M2 ~" R$ j3 K$ b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
$ @! t% @3 r$ J( ]1 H$ t0 p9 F( M: n1 Q  @8 u# V$ E" |
        // MMC51 ?, s& u2 l. f% c4 j: @
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) ~6 {, d& ]. q- n  n        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 b9 r6 o$ G6 {- Q0 N9 F3 ]
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) `) W& D! U" l$ X! k
" c* j% m. q% V2 u: p. m$ E        // N106
  ], U9 c: F* H" V        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. `/ O% ^) v# u# C9 Q1 Y
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 P+ k6 h2 @7 h- C/ F3 I        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# y- b# n! r! S* o
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. X) N* |% Z1 @6 l+ V        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ L6 C" G# d, c- M& P$ h
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 z  k: P9 f- V; k9 v% h; V
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ E  T5 V7 N% Q9 v8 K        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- f9 Z% m7 x4 i8 e* h  G, ?. J( [' g
        // FME7% A( b/ m5 t5 G; b- \+ ^
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 _$ f( u: b  P        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 G1 o" f0 I" V% j2 Y% L0 o
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 l8 |8 ~9 c4 P  Q3 p; z( {# D
& ?( ^4 j1 w2 c/ x+ |
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ R4 }  M, G! H( q1 K
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
8 X- ]- w2 V2 |( o( V/ Q& k' a1 P- O) L' W" v) s; @+ ?
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
( D. X+ s- J! t        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
* U7 \$ f; J% K- m                QueueFlush();4 L% R: ~, m& A3 H/ E
        }  V" J# M3 h. E8 I) z
& F; F  T8 e3 o9 r1 n: H
        while( dwLength-- ) {- {4 Q* U6 ~" F; g0 [, {/ O. I
                writetime = (DWORD)elapsed_time;' ~7 r4 x2 l% ^0 a* a, v
2 D& B( K& b9 E; E4 Z/ E1 q$ o
                while( GetQueue( writetime, q ) ) {
. O) O' F: t# F4 v; |6 U" V+ g5 Y                        WriteProcess( q.addr, q.data );
/ F. ?7 n" ]: A6 f% f                }) n2 c9 R+ Q9 v/ z4 n7 X! F1 h

8 f# q$ L6 n* S) I' E1 {/ h                while( GetExQueue( writetime, q ) ) {  E- C9 `) C( R2 k( m& p! ]
                        WriteExProcess( q.addr, q.data );; T/ N% _9 ?3 c7 u0 l- m: v3 U' S
                }
) m: o( x1 b! z7 c$ q3 w0 `' w% \9 M: j1 b! o
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 A1 A7 H; X3 v
                output = 0;' j, D& E! D' `% W
                output += internal.Process( 0 )*vol[0];& }/ x( ~% Z6 S7 }) A
                output += internal.Process( 1 )*vol[1];
; B  |- C7 o1 C& R8 U0 o                output += internal.Process( 2 )*vol[2];5 @: A! ^$ C4 ~; C' ?2 a" |4 o% V4 m; Y
                output += internal.Process( 3 )*vol[3];. u: }7 X# K8 O8 z  T- U2 s) K  v
                output += internal.Process( 4 )*vol[4];( L  p4 Y3 }$ v4 Q2 _
% C% J/ X  J/ T8 ~* c  v
                if( exsound_select & 0x01 ) {9 O$ z7 D' U7 _
                        output += vrc6.Process( 0 )*vol[5];
* `4 J% ]& j: X) O4 ?# v                        output += vrc6.Process( 1 )*vol[6];$ S. }$ V4 y9 @0 a, T4 ~
                        output += vrc6.Process( 2 )*vol[7];# x6 {& X% {( X  S- t
                }
8 o8 A5 y! U; m. q, s3 p( r5 Z                if( exsound_select & 0x02 ) {+ S& _* `- c6 N1 g- b/ _) u
                        output += vrc7.Process( 0 )*vol[8];
4 K" w2 H( {- ~* x                }
2 O8 e& g/ ]) C# E                if( exsound_select & 0x04 ) {
0 n9 [$ d6 S5 s* L" a                        output += fds.Process( 0 )*vol[9];9 V5 `% ^) g  F& i; m
                }9 d$ f& e" ~! l/ q
                if( exsound_select & 0x08 ) {
( h! L/ u0 m  ?: e                        output += mmc5.Process( 0 )*vol[10];! k0 ]4 w+ K  i$ \5 @* H
                        output += mmc5.Process( 1 )*vol[11];
+ ~* I0 h- a& ^  k. r                        output += mmc5.Process( 2 )*vol[12];9 P: Q# |9 K% {, H0 e
                }" z" a) x# o8 M$ e# n0 A& U  H
                if( exsound_select & 0x10 ) {
, x- h: R) w. U/ s                        output += n106.Process( 0 )*vol[13];% I3 A7 K2 X7 D0 h6 X# P7 f
                        output += n106.Process( 1 )*vol[14];
! n8 ]- n. Q/ A% p) N# b& t                        output += n106.Process( 2 )*vol[15];7 _8 C' A4 W, t2 G& z; b
                        output += n106.Process( 3 )*vol[16];
/ g' `5 o4 b5 o& `! f                        output += n106.Process( 4 )*vol[17];
5 Q  e& z: b2 X- v" I                        output += n106.Process( 5 )*vol[18];2 t/ ?$ ]+ ~; b6 x3 X
                        output += n106.Process( 6 )*vol[19];5 ~/ I3 r* k; q/ ~, ]# o
                        output += n106.Process( 7 )*vol[20];# U1 z2 Z, T+ H) e. t! H  \
                }) b0 Z* X# j. t; _
                if( exsound_select & 0x20 ) {/ B; j7 H4 L& q; [
                        fme7.Process( 3 );        // Envelope & Noise# D+ g3 X# j, a* S
                        output += fme7.Process( 0 )*vol[21];
8 ?& l8 ^0 @6 _, f* @! M8 p                        output += fme7.Process( 1 )*vol[22];. u* h3 a& e' |7 K; ]' n* `! D& p
                        output += fme7.Process( 2 )*vol[23];0 |* p5 d& `# `7 f* I  ]
                }
: G- _; K6 {8 F) Q& j8 f& h! {
' g* F. V: J3 \                output >>= 8;
1 ]/ c8 O2 \  r  z0 \. A* S7 \/ x* P2 z+ q6 X6 M
                if( nFilterType == 1 ) {& Y  u+ i6 M" a+ ?
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
/ I; X" e  j6 o( v& d                        output = (lowpass_filter[0]+output)/2;
, }1 [, h1 U( J                        lowpass_filter[0] = output;9 K8 ~: o9 w6 {1 c  \: l1 U( V& D
                } else if( nFilterType == 2 ) {1 L8 L6 i  ^6 [8 [
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
, r1 N: q9 B) O$ J/ u4 K% |  k                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 X( u! t' a' R' b' k1 Y7 d3 d( L
                        lowpass_filter[1] = lowpass_filter[0];
5 z& X& D4 W% i3 i                        lowpass_filter[0] = output;# F( t9 B  C- f( O* q
                } else if( nFilterType == 3 ) {
6 S0 d; s1 k7 M4 n( i                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 v0 V8 b' ~5 N2 D6 b7 k: n2 m! _
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" o& z& Q2 c7 q1 {                        lowpass_filter[2] = lowpass_filter[1];/ E1 V( W4 h* p4 t- w7 D1 O" _4 C
                        lowpass_filter[1] = lowpass_filter[0];) _4 M9 ]% M1 `; y
                        lowpass_filter[0] = output;
! M( G% I9 h  C6 `; f1 F                } else if( nFilterType == 4 ) {
) Y) Q' E* U, U8 ^2 z! u                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)! B, h, L% |7 _* ~/ h  R
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
  @7 M5 N3 F7 A: i# Q; j                        lowpass_filter[1] = lowpass_filter[0];. X4 N8 {, @1 F9 C5 d
                        lowpass_filter[0] = output;4 @' p& \+ Y' K; j, ]; I; |
                }+ x: q% P( O- m8 U- ~

$ j- r( K0 v0 d' H; [! ~5 q2 P#if        0
& [/ i2 s) J* M& x4 m                // DC惉暘偺僇僢僩
1 R3 t) V# z0 A                {5 t/ r, N9 k% H' }
                static double ave = 0.0, max=0.0, min=0.0;
8 l! [; H! x* u( o                double delta;) C* W1 N, B; @" D' {: d/ v# @  C
                delta = (max-min)/32768.0;
( h  B7 O8 b7 K0 R                max -= delta;/ M% W9 a7 |( i/ w
                min += delta;
' U0 O' A) Q6 S9 \) D; b0 |. U- |                if( output > max ) max = output;9 E  ]& ^. T9 s
                if( output < min ) min = output;
9 N- g% y& v7 j$ Q) K                ave -= ave/1024.0;
* D) O7 h* p+ G7 ]! U1 ^                ave += (max+min)/2048.0;$ L" u: W  M/ f: N: x7 E" o+ ^
                output -= (INT)ave;
5 X% w' k% Z6 T- Z                }
: F5 ~. n$ q" ]/ C8 q; Q# n#endif
' j+ D+ M3 l6 |/ s" y* T#if        1, u9 K* D3 T' w/ M% f3 a
                // DC惉暘偺僇僢僩(HPF TEST)3 k  G8 I+ K# }% o) ^; U
                {
5 e& g# O: z2 r//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);/ l0 ~2 U/ @' r' |3 P! w
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
4 m2 p% X- J" u2 `, b4 n. X                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 j4 |- O; b9 I                static        double        tmp = 0.0;
$ j/ z/ r2 C. C1 M8 H                double        in, out;
+ ?! w& s0 K7 `, |3 D# c8 X' h" P
/ j0 y0 K/ r' R9 P. g% q                in = (double)output;: C, d) c; I/ F& r( [( A5 \8 H: |
                out = (in - tmp);; v) q8 ~% z6 C* K6 o
                tmp = tmp + cutoff * out;
* m- X; k8 ^2 U; m' W
' U6 x1 G+ z  u                output = (INT)out;% _, v3 f* Y/ k
                }4 {( u' k$ d- ?
#endif1 u6 U" d4 ^* T4 s
#if        0
8 z% Z, h8 R7 `$ F                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST): [; K: P( X3 ^/ K  H9 K+ U
                {! C# z% e7 r3 U
                INT        diff = abs(output-last_data);
1 Z$ H! p6 Q. q9 P' T0 x3 u- f. s                if( diff > 0x4000 ) {) r* U& ?* |# l
                        output /= 4;6 `: \8 w- X3 o# h$ y
                } else # h" O, }4 u+ ~! |" J% |1 @) R/ x
                if( diff > 0x3000 ) {
7 i9 b- O, @" k% l: |1 m, k% Y$ a                        output /= 3;
  a; L% s# P1 N6 g                } else
; n) ]  {: a$ a0 i5 G                if( diff > 0x2000 ) {
+ m0 r5 M- U" @5 b6 q                        output /= 2;
/ ?' y# h0 B! ]/ k9 N                }" C4 k6 I( H0 F  h0 @
                last_data = output;
5 o$ |& p1 B$ B# c4 {# n- J7 `                }9 a) L. q5 \+ O- j
#endif
1 z9 S% @9 h9 R1 t: A0 M0 a                // Limit' l: m) k5 z, E* o
                if( output > 0x7FFF ) {
) }3 _8 T: p1 N0 o                        output = 0x7FFF;, w  B( O! U  u( j" E" E9 [- t! B
                } else if( output < -0x8000 ) {
/ k% t: A+ {9 H5 i                        output = -0x8000;
9 @; _, L  X4 t2 k                }4 o! G+ I/ i2 {/ g- v

- _, G. O2 O; d8 Z                if( nBits != 8 ) {/ X  R: F. F( j) S
                        *(SHORT*)lpBuffer = (SHORT)output;
# m( C7 `+ f5 N3 y                        lpBuffer += sizeof(SHORT);
6 v# ?6 O/ m- u0 p9 N                } else {
% L/ t$ v. g* @' Z3 v& R                        *lpBuffer++ = (output>>8)^0x80;! p8 Z; }5 n9 Y6 \/ F9 A" z  J- A
                }. Y6 `+ w1 w# [% B1 C% q5 z
" n  y$ a; p3 S1 D6 R
                if( nCcount < 0x0100 )
2 Z6 ^9 r+ ^- U$ f: s+ Y& v                        pSoundBuf[nCcount++] = (SHORT)output;' ?  s6 M" k: `0 v8 j! Y2 Z

% V* x3 K& ]- V* z. w: f//                elapsedtime += cycle_rate;- `+ \% L' Q" a* L$ w- Q" F8 L* i
                elapsed_time += cycle_rate;$ u! o; U5 e- p" t. |* C3 e; [1 ~# R/ {
        }8 W& G8 |$ Z. ~, ^. \8 O6 y% D# u
9 O% G5 g6 M9 ?8 ~0 q# X- S) L
#if        1- m9 v* t+ A5 K# N4 p
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: x; _0 i6 S# v/ K' v6 f  X  _8 A
                elapsed_time = nes->cpu->GetTotalCycles();6 B- S( w! f0 a& K4 J
        }
$ a# y# }1 _/ e2 E& `        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
# R# F: ]* p1 _9 V, k                elapsed_time = nes->cpu->GetTotalCycles();" e7 g  T1 a1 B5 N8 n+ a
        }8 e2 Z, p4 B7 V8 q
#else
: `% N/ B6 c) L. W2 _! `5 h        elapsed_time = nes->cpu->GetTotalCycles();
  d  |3 A7 ]4 s2 Q' ]#endif5 \& i" y. \" m: y& @5 G1 d
}
& g7 U- i. \' q
9 A' Q7 ]. D6 ~6 B7 {% o/ O// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)- I3 M5 J; x. H/ d2 _
INT        APU::GetChannelFrequency( INT no )1 b; V/ U4 r( l+ K' _9 t5 J
{
6 [( I5 _$ A- S  {        if( !m_bMute[0] )
1 o+ I4 J0 g6 L8 b( Q) ]2 h# ^                return        0;5 @+ q! A7 h/ F) z- [
) \1 {) ~; L! n, J, x. Q  ~0 r2 z# X
        // Internal
5 \$ x5 n9 z. E0 p6 W        if( no < 5 ) {
( O8 |" N# E4 ~0 g4 D$ H8 ]                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 e& ~: \! ]$ ^8 j
        }( p+ u( e4 p8 P( q* b
        // VRC60 J/ j9 d8 U# S% F4 \
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! M- X- s- M1 r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# a7 R1 @9 h! G) ]: S* y: R4 g
        }$ i/ ^4 ^' I* C0 d3 p1 p
        // FDS1 h0 }$ q7 g: b; Y
        if( (exsound_select & 0x04) && no == 0x300 ) {
( i$ _+ h  Y- {8 W1 C4 M                return        m_bMute[6]?fds.GetFreq( 0 ):0;
. v% j$ @3 Y0 H2 V4 O) v- e9 I        }
5 ]. C! p. g) S% V# t3 e0 ?4 r: K! B        // MMC50 c% p0 C2 Y: s1 d3 \/ q8 C, E
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
! R7 k$ w* W& W2 Y                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
2 U  b6 [# e9 F9 ~* V+ B        }( {: ^, O3 B7 [1 b
        // N106# d0 {( x( s; ~  {; u# S
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
1 ^) g! Q8 |1 ^3 w2 x                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;/ w+ C6 ~  m. w" K. F/ C; r
        }
" s! U" a+ V( J$ z: k        // FME7+ Q% _, K  x- f; i: Q; c
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  p0 a+ C8 [! X+ a  n' U% m4 @8 U1 ]                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 U( n! d4 H7 d  j. m        }
7 e* c# r  s$ P        // VRC71 Z' D9 H" U2 H$ s8 w% ?
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {6 f. Z0 ?9 x, ^- m! [$ _% }' U) v1 u& N
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 R7 K& }2 w) K9 T0 a7 e- n4 _; V3 b        }3 G2 B7 _6 O6 [
        return        0;
! A7 X2 M! @! R5 ^& ^: @8 C$ _% G& }}* @& z! `2 d8 g1 a; m
1 U- k( b' Q7 m. E
// State Save/Load9 F, a8 l2 R, g& F* o
void        APU::SaveState( LPBYTE p )
2 F. l" k2 [9 r9 U{
# q! O1 r9 D5 t8 q1 w: W- r#ifdef        _DEBUG
- {" o4 ?5 B; N$ g, gLPBYTE        pold = p;; P, ~. j$ r+ H. B: J. L7 l
#endif7 W& B; J6 ^& _0 Y

( u5 d4 L$ Q; x# s2 p        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞) l) W. t1 X" U/ l
        QueueFlush();& w& F' }7 J- n' y

' L9 x" L$ S, K6 B        internal.SaveState( p );
& C" q: n8 V0 \( r        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding2 `3 _3 H. A- B
: N/ G# {3 M+ b0 f5 p. `3 I: o
        // VRC68 ^  u0 y2 w3 e9 M% K0 s( s. R
        if( exsound_select & 0x01 ) {2 N1 H: P+ \  E
                vrc6.SaveState( p );, x% c- @: h; r
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; u% R$ I  L7 a3 Z# n        }2 z# f" y% h5 ~% h: z. V8 Z
        // VRC7 (not support)$ n3 u- T2 m9 U) J, d7 a% w, u
        if( exsound_select & 0x02 ) {
2 h- ^- [5 O8 O                vrc7.SaveState( p );
7 k! `1 n1 _4 W. q7 ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' q& H. ?8 m; e  `
        }* @7 \; Z. z! x3 G3 ]6 X9 c
        // FDS6 T+ S8 b# q: [6 q$ z2 w* i! E
        if( exsound_select & 0x04 ) {- v/ [% N+ v5 J- q' T" Z) e
                fds.SaveState( p );
: L2 l8 R# ?1 L0 _                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ B" a" k1 h: [        }  g' J" J( g1 b7 Z: J$ W
        // MMC5, G) p' z( b+ k$ J! @- ~8 @1 [
        if( exsound_select & 0x08 ) {
* ^! ?# d/ B* N& R                mmc5.SaveState( p );! i" I& ]" d; L
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. {0 i- V6 i+ v- R8 ?        }
6 A' C3 t3 i- ]- V) u1 \3 F        // N106
- {2 d  I: x) I+ a6 \( I        if( exsound_select & 0x10 ) {, R- X& A9 M/ i+ L* p  l: M  X
                n106.SaveState( p );
4 X8 u( U6 j- B" u                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 f6 o% y7 k9 J! P7 R3 r        }
# c& f" l- p' y        // FME71 b0 V9 u* C, V) U- P+ i1 r3 U* m
        if( exsound_select & 0x20 ) {
! S' H$ o4 H6 Q4 j8 P( \! j                fme7.SaveState( p );
: }  ~, {* e- g5 E& V: p7 y- ?2 P                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 z: p( D  x2 v) ]        }
2 q: U0 @' R+ t. @( ~2 z
7 `) P. y6 `3 m# A9 H8 m. t% j#ifdef        _DEBUG# c/ j2 P- c1 `! u' q, q) C
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- Y5 v$ v9 \/ B6 C0 i#endif
3 j$ h; }6 B, K3 R! E}
# I2 P3 e2 v2 Y- D
5 R- a8 U2 }; {/ ?- A0 kvoid        APU::LoadState( LPBYTE p )
: C5 O0 A/ x2 K! J{& b- e- K) k) _7 C- e% Q, F8 i  ?
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡# A5 M% K1 ]1 k& g0 V
        QueueClear();
; w) p0 M( K" y  n8 l  }' ~% P, e) D0 p1 C; P/ c) g
        internal.LoadState( p );
7 M9 b: A/ f/ q) q+ b0 w        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  {; {7 C' q) x/ v7 f+ `$ ?2 y# ]5 v* X9 J4 C: q" _7 K  m
        // VRC6
1 z: U, \7 u# H4 m        if( exsound_select & 0x01 ) {
) c) k: G# \+ K0 s! ]9 }& u7 E8 w, k( _. _                vrc6.LoadState( p );, g+ w& q' D9 @% A0 X. V( q# a
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 d, W0 i* K% |4 x
        }
: W* c" s' P* k" c; b6 B        // VRC7 (not support)
0 H) q( Z: }4 H' D7 \* |( k        if( exsound_select & 0x02 ) {
3 x- P0 E4 a1 f" N5 B( b                vrc7.LoadState( p );
8 a$ E( O5 b0 J/ @5 R! ]3 h* ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 J# H( Z2 k- T% \' [
        }
' t( O9 @" l. R1 v+ O        // FDS
$ a% z' b3 U7 z4 ?* v+ d" s        if( exsound_select & 0x04 ) {: T2 Y& M2 p% s, z0 K& ]7 g
                fds.LoadState( p );% A+ C( @# ^! }
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 k7 S4 W/ @2 z
        }
+ l7 b- |/ c4 H* c' j        // MMC5. E+ U' A7 m- Q1 e7 a
        if( exsound_select & 0x08 ) {( ~: p& R4 {0 [% y: G; K
                mmc5.LoadState( p );) O/ e5 p. a9 N1 I1 y- O" P
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
% Z  @) k6 A, y- J9 B. d6 i. |        }
, U) ]1 ?! s5 C! ~. d+ n        // N106
* I; G  |$ A2 [. S+ W- p        if( exsound_select & 0x10 ) {
6 s+ N* M7 @% D& q. ^6 K+ @                n106.LoadState( p );/ Y% U  {1 c' p* d0 I) H, @0 m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 L. y* f7 `+ f3 [4 n' t
        }
0 Z* _- ~: Q/ I, a        // FME7
( ]  y' t' G. Q$ f        if( exsound_select & 0x20 ) {3 B* {9 d% _  w) D2 s3 S& J
                fme7.LoadState( p );! }% t* t" y" j# y6 q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ Q; ?3 D  [# i  S4 v
        }9 O7 D7 d1 r: A" u
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
1 p8 `$ i8 Z* S* O& e/ O0 V- F可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  t: s" m1 v+ e! Q: i& b/ i, g+ {感激不尽~~

; c; l6 Y" ?0 e$ ~, p; F$ H恩 我對模擬器不是很有研究,
/ f2 z9 a! w7 m* b, X# ?3 G. [) K% a雖然要了解源碼內容,可能不是很困難,2 N6 M  O! _: s( y, @. {
不過還是要花時間,個人目前蠻忙碌的。
2 F: z# a5 d) t3 M1 ?0 R+ s! _  m9 Y& a
給你一個朋友的MSN,你可以跟他討論看看,
# B4 a" m/ A/ ]他本身是程式設計師,也對FC模擬器很有興趣。/ M3 c/ B7 c  o; N5 ^3 j" g
1 ~$ }3 b5 p: ]" v; |- P8 {
MSN我就PM到你的信箱了。2 w. a, E) P8 B) v6 Y% }9 _" d
4 Y% U: `* c3 b% b
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 e2 t+ H3 [2 [2 V/ X: y8 J2 c
呵…… 谢过团长大人~~
8 V/ H( n" d3 T2 Z& S2 K
1 |6 J: `& h0 u# s. @0 M
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ i9 A5 ?* J* Q  P+ y: c) [, X团长的朋友都是神,那团长就是神的boss。

- C( m( b/ w3 H哈 不敢當,我只是個平凡人,: |2 d. a* _% V1 F' E1 [
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
' ^+ G0 K- |+ D& s( I5 c( xZYH. r' Z. `5 R' j
QQ:4147343063 J  x$ o% Y1 x6 B0 D
Mail:zyh-01@126.com5 u- P$ f! n  g5 D/ _2 {

5 t% u3 O4 W: Z& W- Q2 j他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 L/ E, D5 L; r+ C6 `, ~. J. \再次对团长大人和悠悠哥的无私帮助表示感谢~~
! F8 [) r* o) S  x3 v1 i: o
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-24 13:12 , Processed in 1.104493 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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