设为首页收藏本站

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

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

  [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
& n" h  n% T0 e3 A8 w( a' ?( a+ \% EPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ X4 b+ w1 G+ g# T3 i& \+ F* J' o楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~* I( W+ E* _3 x. u$ }! e3 v
这里有相应的模拟器源码,就当送给大侠了~~
( P2 P+ y  @, L0 ]http://kenkao.qupan.com/5096520.html
回复

使用道具 举报

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" A2 d& N8 `0 ~4 f. B* O' v/ c# C能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 U; `! f8 X+ j* M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' g4 Y( C- ~1 b& _这里有相应的模拟器源码,就当送给大侠 ...

; A4 t+ @' c" m+ k, \: j聲音部分(Audoi Process Unit = APU):
9 ~# _' i" p0 b" L: S- _0 n/ [/ y. P.\NES\APU.cpp
* v& k" `& i& }.\NES\APU.h
2 g- R  J* g! `7 D$ z1 n1 w" R9 e. C
9 n/ C3 b: _0 D; ]% I1 b6 o9 M
影像處理部份(Picture Processing Unit = PPU):, E' t: ]5 Q5 _& ]* h& k0 w
.\NES\PPU.cpp
; C9 N% \$ w! w; `.\NES\PPU.h
: U. _- _5 M8 ^- ^( r/ m; V, _) p) s; G7 H
如果原碼用C跟ASM混搭也不錯
回复

使用道具 举报

该用户从未签到

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

使用道具 举报

该用户从未签到

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

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
  X' ?. K9 g1 J" Y! y2 b(由于很多专用术语和算法机理都不明白,所以看不大懂……)
( ^2 H, k' t6 g# K" d+ x//////////////////////////////////////////////////////////////////////////4 x5 s1 g/ b. R* o3 d0 O8 K
//                                                                      //! c2 C3 c! a/ v3 x6 g: X. E
//      NES APU core                                                    //+ C9 j1 @" M5 H& ?* l
//                                                           Norix      //
/ ?1 U; {/ B7 z  e9 o# D//                                               written     2002/06/27 //
3 W2 V$ y* T8 m, e//                                               last modify ----/--/-- //
. Y9 O1 H$ U4 v; U( p% V5 _//////////////////////////////////////////////////////////////////////////
+ i. n$ Q9 W1 @8 I: W+ ]#include "DebugOut.h"$ I% t5 U% t7 D* C) l4 k
#include "App.h"
( h) m: N6 S2 m" [  N+ Y2 r: z3 @#include "Config.h"+ ]% k4 H6 h; V- T8 D
' t/ I7 e. t5 ]- ^
#include "nes.h"
2 T% {# m3 k( D2 o- x/ B1 F8 o#include "mmu.h"
" O% [/ R( M- B; h+ p7 F: E6 L, f' p#include "cpu.h"
4 t0 g: n. A. O) J) J* o* ^. f" R  \#include "ppu.h"; f3 q5 ]9 L# R" n9 j
#include "rom.h"! D- R  A/ Q. ~$ c2 G7 Z
#include "apu.h"
8 |8 D+ P; o+ X0 R$ V4 Q' H
/ G+ \* x3 c& Q, J// Volume adjust
3 N) P& _0 U. ?5 `// Internal sounds3 x2 m! q- u  G6 ^" e# ~
#define        RECTANGLE_VOL        (0x0F0)0 k9 j8 I# P' R/ c6 i
#define        TRIANGLE_VOL        (0x130)" H  ^" a! o! y) B
#define        NOISE_VOL        (0x0C0)
9 x; Z9 K/ Q# L- }, B#define        DPCM_VOL        (0x0F0)
# r) J7 l$ h+ s// Extra sounds
: l3 H/ ]/ M/ W, |5 L& n* K$ ]#define        VRC6_VOL        (0x0F0); q& i' H& L8 e1 s8 D3 w
#define        VRC7_VOL        (0x130)
, i* K5 t" h  K% |/ r. ]#define        FDS_VOL                (0x0F0)! b5 V5 I; y2 u9 A1 @0 U
#define        MMC5_VOL        (0x0F0)
$ _" ^4 d* {, c6 m# J#define        N106_VOL        (0x088)6 z( G* L8 m. {7 X$ {
#define        FME7_VOL        (0x130)
; c2 _5 k! r7 E8 F- ^4 k8 T+ ]' Y. [/ G/ r# N
APU::APU( NES* parent )) x5 h" }/ n- i* T5 X. c& k
{
5 P3 `  I1 e/ G- Y1 ~8 F8 Y1 U        exsound_select = 0;% u+ N, ^; `* @
1 r3 o3 e7 K& }, J* \0 j
        nes = parent;: Y8 k/ N/ g( g
        internal.SetParent( parent );' i" Y: g5 e# ?* G1 t* m: {6 a

3 p1 v, u- y! l5 G        last_data = last_diff = 0;
- G& b8 t$ {. t- m& [
8 b2 A1 X  a  k" L, {4 G5 q        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
0 O- @1 g# c2 W0 i4 [: j( C% [9 R# ?+ Y" H3 B  I% ~- K
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
, b/ x. o0 u7 ?5 V, h1 K% \        ZEROMEMORY( &queue, sizeof(queue) );
+ w5 ?$ ~" D2 X7 }0 T9 L        ZEROMEMORY( &exqueue, sizeof(exqueue) );; Q3 V* {2 ]7 E+ l6 P  d. u

6 T& C% I; l) ]( M        for( INT i = 0; i < 16; i++ ) {( D) B4 u8 ~7 @- K8 _
                m_bMute = TRUE;1 e0 i- V. y; n+ ?3 N
        }
: a0 t' S. q% v5 ?}! Z9 l, E2 z, P+ B' j: E  W

# p& s+ W; E' c5 V+ SAPU::~APU()6 \  }8 h; @0 j- G$ ~
{
  n: r/ l& @9 x9 I/ L; p$ ?! e' \* X, C}$ l6 q0 r3 ]  @. d8 V

1 `& q/ ^: W/ F" G+ ~void        APU::SetQueue( INT writetime, WORD addr, BYTE data )- l/ K- s) n/ O
{
% L/ m( }1 a* ^3 O8 [: k8 v. }        queue.data[queue.wrptr].time = writetime;, k: K2 Q) T9 Q* ?) U4 D
        queue.data[queue.wrptr].addr = addr;# }, b+ a. O( [$ \+ K: h; L" ^
        queue.data[queue.wrptr].data = data;
7 E3 \' h6 [6 ~* q0 G0 w' [        queue.wrptr++;! R' V7 T1 k4 p% i% l- x
        queue.wrptr&=QUEUE_LENGTH-1;% E0 g& ^4 |3 l+ j6 N
        if( queue.wrptr == queue.rdptr ) {: N8 |5 Z' X( n0 i: W5 f9 X7 |+ G
                DEBUGOUT( "queue overflow.\n" );
7 F" k1 p; |4 q: a4 ~( ^7 Z  {        }
  _; z1 s& u6 `$ _}
; [2 h* G4 O7 |; a1 n! @+ M6 a% E$ X5 q/ A
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
1 [: ]0 h2 u' }& i- Z$ n! x{1 Y- G  Y5 u1 D& _3 ]
        if( queue.wrptr == queue.rdptr ) {, ]" V, t. `: W1 A6 K3 ]2 F
                return        FALSE;5 B- b8 D; d" ~( F' s
        }( K/ u4 c. ^+ i
        if( queue.data[queue.rdptr].time <= writetime ) {/ s/ C$ z' S8 f
                ret = queue.data[queue.rdptr];; N& r/ h7 N, I
                queue.rdptr++;* E  Y/ R, p6 t
                queue.rdptr&=QUEUE_LENGTH-1;
, i* P* n7 [7 e& M" p                return        TRUE;- I9 O, w' K) L+ s" b, a
        }
: h" K  }* _2 v        return        FALSE;
' H# r! e# H' X- p0 d% _+ z}
" a# t% A( X4 n6 \% J, ?7 {! g+ Z6 R& h$ X
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
' \5 z2 c) }) c9 G8 P{3 ]- D4 @1 P8 Z3 V+ z
        exqueue.data[exqueue.wrptr].time = writetime;
' x! v0 F# b7 V7 z        exqueue.data[exqueue.wrptr].addr = addr;
6 r  X2 c; [+ W8 Q" V        exqueue.data[exqueue.wrptr].data = data;
. x( \9 Q2 q( d% y( ~" z5 J9 \        exqueue.wrptr++;, K% Q+ C9 `; C+ n9 o3 K4 _& i
        exqueue.wrptr&=QUEUE_LENGTH-1;1 f4 L( W# U  h& Y& w9 O8 [* R2 Z
        if( exqueue.wrptr == exqueue.rdptr ) {# G5 ]* ]9 p# G) q9 U' [4 ~0 l1 j% Z
                DEBUGOUT( "exqueue overflow.\n" );
7 S7 X. n! M$ [9 v2 R: o% ~" S        }4 Y  H* |' r, Q4 ^. V% Z) u) o
}3 |/ X2 S3 L; T2 e  C5 g1 L

" p5 T  Y/ z" _# _BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
+ g) {  T5 r; [* D( S, w{
/ J8 d$ S5 F" @: m6 W& S8 B        if( exqueue.wrptr == exqueue.rdptr ) {; l  z; s: ?8 f3 G1 c
                return        FALSE;
3 C  x0 q7 M: H0 i& w        }) S2 F) G. Q4 e* G6 A; G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {6 O4 I& d% O" C$ b
                ret = exqueue.data[exqueue.rdptr];. h. ^( z7 J% E, ]
                exqueue.rdptr++;
3 r# k  [" D5 p' S- s4 V4 Z/ F                exqueue.rdptr&=QUEUE_LENGTH-1;1 v! _4 g! a- `0 [( i- Q7 t
                return        TRUE;3 ~- Z$ a4 p% d8 a, w" j
        }+ }! x' Y5 V8 a  Y, n; a
        return        FALSE;2 C" m  l1 A" ^( |  A  ~1 l5 |
}5 L+ H: s$ ~# t2 Z

3 |( N8 j% ?4 `3 U: S( Y' qvoid        APU::QueueClear()9 d0 E5 L/ u0 b+ Z
{$ U! p) U6 O8 ]9 K# _$ y, E% W# W
        ZEROMEMORY( &queue, sizeof(queue) );
% v0 K4 d: _+ P/ n& }        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- v9 e8 X3 d8 Q6 u}" E2 D8 n2 U% G3 V( a. e, Z
5 M4 r" C" h; f1 A1 b1 j
void        APU::QueueFlush()$ K9 D( _; L+ y. K/ W# q
{
6 U6 M) @2 Q: U2 N7 s        while( queue.wrptr != queue.rdptr ) {! w& B( e! E2 M" j1 z2 t
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ X2 C3 o0 k( W                queue.rdptr++;
2 H5 K5 C8 e: j5 ]& N2 r& _! E                queue.rdptr&=QUEUE_LENGTH-1;
9 {8 K1 v$ [, m  m, t3 u2 O        }
9 Z1 Y- ^7 d" Z! _7 o1 Y3 p7 C1 E+ j" t! m# V* e
        while( exqueue.wrptr != exqueue.rdptr ) {
2 V2 V+ o2 A- c( U7 |, Y                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );( U& M+ U' X9 }# F, z3 O
                exqueue.rdptr++;) j. D( F2 ^; {' G
                exqueue.rdptr&=QUEUE_LENGTH-1;( F0 |7 T# ^) ~5 x. |! R
        }- ~' `' {: J' x; F# s
}& P+ X* }5 M/ p3 R. k: I
2 U/ a/ `4 v$ x. j% q
void        APU::SoundSetup()
& u% ]0 |, T0 a; I6 Y' T( N{
4 j! P" l+ @: L3 q: E- k        FLOAT        fClock = nes->nescfg->CpuClock;; V/ h7 ^" O4 y" x. o3 Q& H6 o2 j
        INT        nRate = (INT)Config.sound.nRate;, K- ]6 f; ~3 G0 \
        internal.Setup( fClock, nRate );
0 H+ T: A! n, k' d; V        vrc6.Setup( fClock, nRate );
: l/ R$ I' b: a+ a        vrc7.Setup( fClock, nRate );0 j) U! x3 a2 x5 L& o
        mmc5.Setup( fClock, nRate );& L) x# {/ k7 ]6 Z* t& p
        fds.Setup ( fClock, nRate );3 B1 W0 U  a9 B1 U
        n106.Setup( fClock, nRate );7 ^2 v3 h' l# G7 K( ^
        fme7.Setup( fClock, nRate );# E% {7 G! u) B7 l1 V: A
}
% F; z# ~6 [5 x9 {4 r) d" G. j9 [+ O& Y! ?6 K; F
void        APU::Reset(); ^* K7 B# N, P8 [1 g9 B/ W
{
+ C( X& }/ c4 Z: t        ZEROMEMORY( &queue, sizeof(queue) );
% L, ^# c- Y! Q2 Z        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- u9 O- Q# }/ ?9 x- n; P  V  O  H$ _* n& W1 q- Z2 [1 \" l2 P" S
        elapsed_time = 0;( s* @& [; p+ d3 t/ U/ G9 Z. E
$ z2 ~' h  l- T! W: s
        FLOAT        fClock = nes->nescfg->CpuClock;4 a- p5 g& q) I& `( G9 T, C. h6 b/ U
        INT        nRate = (INT)Config.sound.nRate;: k4 E( U/ Q( ~1 j7 z, C  S
        internal.Reset( fClock, nRate );! K8 H0 y, ~1 O( h/ U
        vrc6.Reset( fClock, nRate );
& J( A1 Y8 ~  f& h" e        vrc7.Reset( fClock, nRate );
& q8 i& X% x( O* K, R        mmc5.Reset( fClock, nRate );
- m+ D+ W4 u  D  M6 J' V1 E        fds.Reset ( fClock, nRate );
7 c& ?: N7 l2 s        n106.Reset( fClock, nRate );6 K0 ^7 m; T! c9 K, C: ~+ g
        fme7.Reset( fClock, nRate );9 F- P9 l' o7 I
9 C9 T& Q" ~; J5 J( B
        SoundSetup();
* n2 v2 N  g2 I6 [% M}) {/ n5 H* \8 L; q1 a! y
+ E; F, n2 ^( M
void        APU::SelectExSound( BYTE data ), ^: e1 L4 C( M8 o4 m* W
{8 m" _' _# `* D7 w/ B% y
        exsound_select = data;* E/ d% o+ x2 R2 }4 N
}
  E/ k4 Y4 V- K# r
6 x' R4 M6 i" k1 h0 J1 s( e% ^# LBYTE        APU::Read( WORD addr ); g; ?# m8 J* [
{( Z7 Z1 m( U( R: t- J* V
        return        internal.SyncRead( addr );2 W4 T7 w- n, ^: m+ v
}
# o/ ]% K& I7 n4 N1 a& G& S2 z# f
' o2 _6 H# ^# @& d' ^( fvoid        APU::Write( WORD addr, BYTE data )* e0 Y6 d; ?( S) n
{$ V2 |# C" |& h! `7 u  j* ], ~
        // $4018偼VirtuaNES屌桳億乕僩6 p. Q; z+ M2 s5 F
        if( addr >= 0x4000 && addr <= 0x401F ) {
" {8 g, \$ K# v8 ^                internal.SyncWrite( addr, data );
6 E6 C  N8 V# m% D. T                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
2 F/ V1 ?$ p3 a1 L/ P6 t        }, a" x: [; O( @: T) z! ]; h) h
}1 U/ V' R* f; [( s) ?

2 g: d: C) n+ _7 Y6 D# }: bBYTE        APU::ExRead( WORD addr )
! x( ^0 g* Z" |$ _{
; d: S7 W- W# N/ F5 XBYTE        data = 0;
( i4 O' U( |* r
- X* t  k7 y6 _% i1 k% |        if( exsound_select & 0x10 ) {2 f! x! B' r, U: B! g; |
                if( addr == 0x4800 ) {) m5 A$ T4 ?' Q: h0 Q( ^, N8 c4 W2 ]
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) r" x2 s9 ~( L( Y2 P+ o# k                }
- {' L/ G. w* L$ \* t6 Z% i        }
& T0 i5 b* L) x6 q- l7 P3 s, h        if( exsound_select & 0x04 ) {
, v5 B4 w' \' U- w) S                if( addr >= 0x4040 && addr < 0x4100 ) {: h- W: J) g* z8 m6 [
                        data = fds.SyncRead( addr );
5 v& x* K" c8 q# {  g7 p! [1 J                }
  v% u2 t! v3 _8 s1 S, Q        }$ p$ |) R5 B. i: ]! A0 M
        if( exsound_select & 0x08 ) {
/ c6 ]2 Z/ {: `% z, v                if( addr >= 0x5000 && addr <= 0x5015 ) {5 F$ o6 n& d: ]  j
                        data = mmc5.SyncRead( addr );% c$ j# O  P7 E9 k
                }
1 k9 n" c, @6 v- ?7 a6 N        }
# P2 u2 d* {# W% V8 z) t- h& _$ C. W' E3 F
        return        data;
% F; X6 ^4 u/ G' Y3 e2 h}
, P. A' A. {) n$ W! U7 V0 `1 M" T
void        APU::ExWrite( WORD addr, BYTE data )9 G9 C  w/ \7 a- n2 {. F9 Z
{
& @2 V+ k  s6 `1 n# |        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );. q: ~/ H; G% |
( l, k) {% W: {: g
        if( exsound_select & 0x04 ) {/ C; K# D( ]7 T" b- E
                if( addr >= 0x4040 && addr < 0x4100 ) {
, z* X3 l1 n4 Z: q+ b                        fds.SyncWrite( addr, data );
- |+ H0 Z0 ]( A                }
7 c. r: J" Q+ J$ G0 @! @        }" R4 q5 \7 `& Y+ r, t0 x) ?8 H

" ^; [7 W' j6 w) v6 p$ \        if( exsound_select & 0x08 ) {1 ?+ P+ ^5 Q" Q% H  T6 J
                if( addr >= 0x5000 && addr <= 0x5015 ) {; K9 b) U+ V9 }& d" L9 v  Y+ G
                        mmc5.SyncWrite( addr, data );
2 T/ d- m) v; h* w1 A                }
8 w+ n- O$ Q, c1 ]3 I        }
2 }- a  F: l; S; R  s5 e1 C2 I}
) w! p& D( b) l% d4 v1 S2 Z! C( ~( D7 s4 b4 a- K
void        APU::Sync()
) L! g0 P, J' _0 [( |1 V; ?6 j{" \* R5 k/ N5 y# f  X7 ?$ ]8 M+ t( g1 Q
}" v8 v1 K, i2 w, W6 F

2 w! g- s& ]5 Z; m+ U, M7 |void        APU::SyncDPCM( INT cycles )' A2 A  c! G9 Z! s; `- B: y$ k) L
{
+ d0 D' f7 n  v9 a! z        internal.Sync( cycles );( _! f2 i2 h& g% }
0 X) g& C% r% H5 v
        if( exsound_select & 0x04 ) {
' D7 l3 o- x- g  M( n3 D                fds.Sync( cycles );4 e2 W- m- O4 C3 Z$ K% l' M
        }2 H+ e8 j; q7 f7 h2 y3 ]3 c2 \
        if( exsound_select & 0x08 ) {
# L) O: V0 w8 s                mmc5.Sync( cycles );$ \; |5 @) |3 e! J4 I" L5 ^
        }$ ?" e$ h2 |' E5 @4 C
}
2 @/ F0 P. e6 f, v' C; \' e. s7 @3 i, B  i! x+ F* K
void        APU::WriteProcess( WORD addr, BYTE data )
8 y; Q6 Q9 g; t' ]* G! R0 ]1 B{
" {/ h3 s( I. r  ~$ E: Y        // $4018偼VirtuaNES屌桳億乕僩
3 }( S: I& J" B* |2 x. l        if( addr >= 0x4000 && addr <= 0x401F ) {
4 Q& V. N) s) n; b9 l+ o5 ~                internal.Write( addr, data );
$ }) T6 \2 X) \! V2 _6 B% q        }
; o/ J. [3 G9 j/ R  D}
2 u3 b, A* R0 C8 q5 @8 J5 k( X! A+ e" p5 f3 _, }8 U
void        APU::WriteExProcess( WORD addr, BYTE data )
, W# Y, |* f( C1 l% t{& s' a' t" O+ C2 C
        if( exsound_select & 0x01 ) {$ T% M+ J& E8 [5 E9 G! ?3 f
                vrc6.Write( addr, data );
6 y% b' f0 V) X( ?* E        }. T- e( u! u5 P- }+ O" g8 ^9 P" |
        if( exsound_select & 0x02 ) {5 I! X/ N# j, U$ i
                vrc7.Write( addr, data );
. t9 X, \0 ?/ \: G2 _' t3 H        }
% O: y; [+ U5 p) W+ j        if( exsound_select & 0x04 ) {% e! i2 N4 T# m# r' b* H  q) N% S4 t
                fds.Write( addr, data );- S7 d# K+ b# B, a2 u& |2 m, J
        }+ d" m5 k7 T. z- F9 E! {
        if( exsound_select & 0x08 ) {
( [" T7 |( g, d5 Y) q7 t2 ?0 c0 T                mmc5.Write( addr, data );
9 R% z/ i# L: t. [5 x, r+ N        }6 o* S5 P* V% _) F( Q: j. {& B' H  N
        if( exsound_select & 0x10 ) {! ]/ }) a' H& d% j( p4 i2 C
                if( addr == 0x0000 ) {! E5 N7 c/ U% U3 z( K  e" {# M
                        BYTE        dummy = n106.Read( addr );0 l; H4 l2 t: v3 N
                } else {
+ s% p  ~/ `8 v                        n106.Write( addr, data );, [+ }& H" C/ C5 ]$ ?7 U8 Z4 t
                }
+ H6 c- A( l$ h4 h1 `$ R  }        }9 e3 k1 P4 w+ i0 d% K
        if( exsound_select & 0x20 ) {. ^* G$ t' |  l) F. j, S( Z
                fme7.Write( addr, data );
) R# L4 o8 ~7 P        }0 t; p; l* s% O
}) }* i: e' j9 P4 y$ f

$ p( v( v4 {# kvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
# e7 E8 o) w! B  u{9 U" W! O4 ]& X1 \- S
INT        nBits = Config.sound.nBits;  f' D0 \/ `. U/ s! O+ B  [$ {
DWORD        dwLength = dwSize / (nBits/8);
, U% E9 z8 [1 b' o  t. iINT        output;9 g- U- j' m% P# V1 A' S, X
QUEUEDATA q;
) }& N3 C  r, T! @  `8 K1 G& M6 a" x, G# dDWORD        writetime;' h; i" e3 ~4 X9 e+ l* N+ P

9 c0 {6 c2 J3 v' [  ^, _6 oLPSHORT        pSoundBuf = m_SoundBuffer;
+ w5 D; f, x4 a/ hINT        nCcount = 0;, R2 X& t/ W2 }0 h$ b

! W0 d% M7 i. o$ o; _: I5 j: aINT        nFilterType = Config.sound.nFilterType;, r  r" T0 O! I, q! N. h/ B' `
% D1 ~9 E$ Z2 W+ c9 e
        if( !Config.sound.bEnable ) {
5 n. i3 X* b5 a2 V                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! N7 m6 @# s- o* y; B8 {1 g; k2 K
                return;' i: d% Z" h6 P: t% j4 e
        }( b+ x; C, t" _& V* P

. ]0 A( C* E2 L" {8 W( k4 c$ o4 r9 {        // Volume setup7 j8 X0 c0 e( Z; S4 N9 g! y" F
        //  0:Master1 i! h' ]& g& a- N) ]
        //  1:Rectangle 1
3 v7 w1 l0 I" v! W4 |3 ]  d        //  2:Rectangle 25 w6 g( u, a+ z  [4 r9 ~* Q' ~
        //  3:Triangle
5 Z8 K2 }* ]! w1 S  J0 B        //  4:Noise! \1 T& e3 G( F( b* R
        //  5:DPCM/ R9 |6 M; @9 A. A" a3 ?
        //  6:VRC6
8 r4 I  U- |! o6 ]1 Q0 Y8 v2 B        //  7:VRC7
9 p* Y, L' m$ S8 N, ~) a2 m$ V. U. J        //  8:FDS' |; j+ M, p' i. ^. i" T1 G
        //  9:MMC5' ~# c% ?; C0 f4 s( D/ x+ D
        // 10:N106
3 K% b( J* I2 U7 Z: N/ Q        // 11:FME7
+ e1 I9 P8 K' u        INT        vol[24];
$ o5 W# a& d3 R2 {6 v5 [        BOOL*        bMute = m_bMute;0 ?/ T: e; Q6 k* ^
        SHORT*        nVolume = Config.sound.nVolume;
$ F% Y9 F" M# q5 b  e8 B, b# b/ ~. A7 V9 k% S' b1 }" n
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;* y2 @) ^2 @7 e0 r

" [# Y- F( {3 |' n, \! |! A7 G3 c        // Internal% v( e! c- R# f1 c3 U; W7 M
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( g! J; M, A8 _) E& W7 e        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;/ F* `6 M! n3 }2 Q3 [# a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;, s4 s, x0 e2 N& n7 X7 @  T4 y+ u- T% B
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: Z, I  s, e0 g2 d, e+ F1 G        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
1 P. B1 \, y+ I$ M9 H/ n8 b' u2 M# K. y, I. I0 z
        // VRC6
2 D  a$ w; E1 m; y5 [# v        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* y- @) [" }0 ^# [$ }% x- T) Y        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. a8 U$ Y9 Z" a6 _
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& ~* I8 b) U( P+ K0 m* _+ G$ T3 w4 i
0 o/ q& C9 k+ K, c1 r. [9 b% g+ r
        // VRC7
. M  R! T: z9 z+ V2 e; U        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
9 y/ M2 |: B2 w% B+ W2 l: N1 w3 H& t7 m# k0 `8 b8 \0 b
        // FDS4 k2 Z0 v& S+ m2 s0 u
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ |# U4 @* E5 v. W+ {5 U6 a; }
8 |: t! A) V# j& X
        // MMC5
  r$ \8 t8 H* ^/ u: {$ g$ o        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* ]; ?5 e3 v& {0 |9 O
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. ^/ P. V. W, J2 |  `4 k0 X7 }
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' R) y+ B. z, X. G2 i

; C/ C/ K" X, G! Q2 h        // N106$ b: \  u3 q: D! i7 u" b" k
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 P, H, d* \  H& @5 }0 L
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 V% I' y, i  q$ e; ?
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' Y& [. e3 C& b2 }7 W        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ y1 V6 G/ [/ z. I2 k7 f& L! K        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 m: U+ }& p8 q; q$ a        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( F- M& a" L) ~/ f: ~* J
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! v0 j! x( J. ~. b/ Y9 C
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, U6 k. [! l$ g  P& f
9 f8 M$ C* {/ n, I2 B/ u9 J        // FME7, P9 o8 r: Q8 X! O1 W3 `
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! k# H' j8 B" _' v: ]        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; ]- e; F( P  J% I        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; d$ C: H: k  U" m

) k  d! t" D* z//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
; c3 X6 K( W( z$ H2 l) T* E0 \        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 s6 W% T) c1 k0 K: a
# `/ R/ o' s6 |8 R# R
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 C6 z, F- V. v2 }1 ?; y
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
4 }1 m/ J7 h  I& ~/ N1 ~  G9 {                QueueFlush();
2 [' k& S  B8 I' s- M: n        }
: O8 M" R4 _2 X' e6 r/ A/ P4 B' O. {5 x3 z& L7 l
        while( dwLength-- ) {
2 L, A, |2 X0 v8 M3 f                writetime = (DWORD)elapsed_time;
8 D0 u1 }0 g$ l; {. A3 Y$ E; |7 `  r' I0 p; s/ X  U
                while( GetQueue( writetime, q ) ) {
+ x3 w' O- j; ?6 s2 @                        WriteProcess( q.addr, q.data );
! E. ?/ C! e+ H# ?) c( ]6 P- G                }0 Q( |+ H( ~, i% Q( a: |* Y
, i3 m, A# j  N  u4 w# X
                while( GetExQueue( writetime, q ) ) {# ~+ V) f6 s( z  R9 l- {' @5 S' y1 W) V
                        WriteExProcess( q.addr, q.data );
# L, i" K2 d9 s# ~+ `  [) S2 ~6 u                }
& z1 x/ e# m  g! X, u$ g3 u. j
1 C! w, A% a, E# X" f& {" O# {9 R                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ G$ r- U7 B' C* [& r% }% |: ^3 d, t                output = 0;% k9 A! @4 o9 q3 P, R1 C" ?# C
                output += internal.Process( 0 )*vol[0];
2 I+ a* E3 T$ `( C                output += internal.Process( 1 )*vol[1];1 D" a; F: h0 n$ O
                output += internal.Process( 2 )*vol[2];9 s* I, ?+ ~+ L* x
                output += internal.Process( 3 )*vol[3];
* @6 g! y/ A7 x                output += internal.Process( 4 )*vol[4];
7 z7 j, }& A+ h+ \8 t
9 p! _( C4 N* F% _                if( exsound_select & 0x01 ) {+ \" u) X1 ~' \- k
                        output += vrc6.Process( 0 )*vol[5];
; L0 O2 m. r2 [                        output += vrc6.Process( 1 )*vol[6];
4 a$ }$ V, h, e2 Q4 E$ e$ W' ?                        output += vrc6.Process( 2 )*vol[7];
* _1 ^3 O$ J0 d' N2 e                }# s, Z, P- k8 @. z
                if( exsound_select & 0x02 ) {1 y2 _1 S5 R# a3 {
                        output += vrc7.Process( 0 )*vol[8];" Q' C- h& H% c/ n; `# Y
                }: p7 N" C( e5 L' Y6 s3 ]% |% _: |
                if( exsound_select & 0x04 ) {
5 V5 t: z$ u4 M4 R% K9 [                        output += fds.Process( 0 )*vol[9];
: I9 r- V% V  }4 j$ e+ E7 V$ S                }$ S/ g9 o+ U( P$ V3 g% b  f
                if( exsound_select & 0x08 ) {
2 J% n- p* [5 u1 X                        output += mmc5.Process( 0 )*vol[10];  J* U8 X+ [5 m+ e- @& P
                        output += mmc5.Process( 1 )*vol[11];2 B$ x0 T% n. }* R
                        output += mmc5.Process( 2 )*vol[12];- d3 a- Y& R. H2 j9 |
                }' I' ~9 U4 B0 O
                if( exsound_select & 0x10 ) {
" y1 v4 s( j/ r' w7 E: v* o                        output += n106.Process( 0 )*vol[13];0 ~% O( W5 |" B3 {" n
                        output += n106.Process( 1 )*vol[14];9 x" D; Y. R4 e# D
                        output += n106.Process( 2 )*vol[15];
' D- z( n* G0 c& A3 w                        output += n106.Process( 3 )*vol[16];
2 _  U/ r8 ~* r% H                        output += n106.Process( 4 )*vol[17];
6 o6 n/ h/ U% C' V9 A- X4 J                        output += n106.Process( 5 )*vol[18];
' b$ w- q% S2 r  ~/ v9 t                        output += n106.Process( 6 )*vol[19];
4 D3 Y2 Y$ I9 Q% d% F                        output += n106.Process( 7 )*vol[20];& o. y8 e( j+ q( }
                }" S0 b, V& H5 `
                if( exsound_select & 0x20 ) {, X* ~: A9 i: i8 l) q) j: u3 z* |* f3 G
                        fme7.Process( 3 );        // Envelope & Noise
0 o- g  r* {* h# X                        output += fme7.Process( 0 )*vol[21];
2 z# Z7 F5 z* n3 e                        output += fme7.Process( 1 )*vol[22];3 ~, A5 E0 t+ p* Q
                        output += fme7.Process( 2 )*vol[23];
6 [7 a2 N4 `- K( O& a$ |                }, w& D1 h/ Q  }
& c- t1 h) X# x
                output >>= 8;) W5 }4 j6 _. r; o8 A1 q: b

3 L9 s( K& S, Z6 |2 r                if( nFilterType == 1 ) {6 |: h- C$ \) M8 V
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 |' |3 i) M  a/ G. g, T: U8 p& q                        output = (lowpass_filter[0]+output)/2;
0 Z# J! R, Q8 s1 h+ s                        lowpass_filter[0] = output;& G' V7 `  o+ [3 g+ e% [0 z
                } else if( nFilterType == 2 ) {
; S. K8 B) l1 }* `! U. F                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- y8 D+ Y0 N3 A2 N) d! H' ~9 U9 h
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
  q3 J2 E' p1 y1 `) h0 |" |                        lowpass_filter[1] = lowpass_filter[0];: @  \) ?6 v0 A. X6 S3 Y, F, v
                        lowpass_filter[0] = output;
3 p8 _, Z6 V) ^" n+ j' n2 z                } else if( nFilterType == 3 ) {
: x2 }+ a$ X/ w5 C" e) M: ?) T                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ |% f! \/ ~* h( E, V' F  {0 G3 W                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;, e, q& L/ P3 i
                        lowpass_filter[2] = lowpass_filter[1];
% {6 J' n& F0 |, t1 m                        lowpass_filter[1] = lowpass_filter[0];9 c& g% I7 Y/ O3 p5 w2 A
                        lowpass_filter[0] = output;0 _+ s( w% @7 }" I4 y6 ^) K
                } else if( nFilterType == 4 ) {
$ j' n+ }+ e$ u& M( l- |6 u' j8 L                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)0 {& G4 l: X+ I6 |+ }% j! x
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' C; e# e, l$ Z0 L' a# ]% \
                        lowpass_filter[1] = lowpass_filter[0];
* ?7 ?# J& q; W, a- [8 P  O# N, `$ q                        lowpass_filter[0] = output;# m& t$ _, i* V0 n' ]$ \
                }
" {  j/ b5 ~% e# ], Y) I/ I7 B# S2 L, U, ?
#if        0
" y+ a6 ?6 w1 Y                // DC惉暘偺僇僢僩# ^6 E' ?) s$ c$ P6 G
                {& w* U/ i0 w, M+ o* m* J
                static double ave = 0.0, max=0.0, min=0.0;+ p! m, l0 B# w! v$ J
                double delta;- L& t+ C; u9 U2 ?( C5 R
                delta = (max-min)/32768.0;
8 x1 d" B  p1 |. b                max -= delta;3 E1 A: G9 c. w! n) G& u: l
                min += delta;
9 w  B! {0 |' W, z5 L                if( output > max ) max = output;) _" X$ Z4 x! S% p2 w" A$ e4 b
                if( output < min ) min = output;' Q- X& L$ A7 K
                ave -= ave/1024.0;$ n% S+ y1 }& q
                ave += (max+min)/2048.0;
; r4 T7 J8 G6 n2 X- [' y                output -= (INT)ave;# Z- j: s9 q2 b! a0 ~+ f
                }
: ]) L, I+ V& G$ ~, d#endif+ s$ C2 F% n' h, B4 n! U( |  J! ?" S
#if        10 |* a- H! y6 F9 G' C# X
                // DC惉暘偺僇僢僩(HPF TEST)( Y: A. O, t' ]8 ]: w' g
                {
: t* p' o1 [: h  Q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);$ i, E! q* |3 S: ^9 U5 ^6 E
                static        double        cutofftemp = (2.0*3.141592653579*40.0);) D8 H3 O$ T1 o7 M5 U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;; C* c9 ?# k% z) T) u& \
                static        double        tmp = 0.0;
  b) n! R! k& w# E- r                double        in, out;& T- I# a6 J7 ^
) t8 f4 y0 \; a/ F  [
                in = (double)output;
, z" ?# T& Y. k                out = (in - tmp);4 Q# U2 w- l. u+ @1 S: H5 u
                tmp = tmp + cutoff * out;1 n: R( F" p8 S4 g9 |( }2 q7 c

. v8 ]1 l' Y4 s+ y                output = (INT)out;% N+ Y! k& q7 q2 o5 d7 j
                }
, Q2 T7 [* Q; C#endif/ K' w. W3 f/ G. q6 B3 a
#if        0
& J4 \2 @( j- N) `7 e                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ ?$ d2 M4 Y! V* n* Z                {! J! X! s" r' g
                INT        diff = abs(output-last_data);
4 k, N+ b4 |( e5 }, l" c! x+ D, B                if( diff > 0x4000 ) {
( ]+ K5 b2 K" X% l                        output /= 4;
% v. D& q0 b* d, P: c                } else , w) E8 d8 N8 n  i# o- I
                if( diff > 0x3000 ) {
7 A# X, H* S+ W                        output /= 3;3 O1 v7 k2 d* L9 ~) t
                } else
) @2 Y$ r5 A8 _% l1 v8 X( P% f" u                if( diff > 0x2000 ) {
. ?+ c' P$ Y9 e- s0 x( @* q                        output /= 2;1 ]- i/ j7 R4 ^; n9 g8 X/ C8 M9 P
                }
2 G$ f% f2 U/ Y# s6 O$ K                last_data = output;
! G0 ^% k, T/ \                }
; i* N* e: |, r* g, A# T+ h#endif
+ J. y% h# s* w! l9 E! y! I2 ]4 U  J+ h                // Limit( w. r9 k) ?" o' f
                if( output > 0x7FFF ) {; |* W. t, n* @  a' v5 P" `
                        output = 0x7FFF;
) E! c7 U! F6 g+ n  {+ z                } else if( output < -0x8000 ) {! f% y8 D+ l/ \! t, I9 B- U
                        output = -0x8000;
/ P  h1 z# f- ~! e+ t( H4 w                }$ |1 S1 g9 q+ _& F: O' C: i6 U
0 N( F9 d; l( `
                if( nBits != 8 ) {/ H9 R* B) [4 p3 Q) m8 U: \9 G
                        *(SHORT*)lpBuffer = (SHORT)output;; E) C% `4 P3 @. y1 l
                        lpBuffer += sizeof(SHORT);( X: P- P# ~) \  V
                } else {
5 l  \' d8 M7 ?: v5 V4 h                        *lpBuffer++ = (output>>8)^0x80;
8 N9 C9 n  s1 N+ k) x% s9 }                }, y) V1 r: H0 f1 [' ]* N% q

# d$ g0 _6 c. [9 F- Z                if( nCcount < 0x0100 ): `9 }6 W1 J3 N
                        pSoundBuf[nCcount++] = (SHORT)output;) k, }, S. I+ N& y+ b& D
. a- i$ J) K, h9 {  U
//                elapsedtime += cycle_rate;
& @2 X. g4 {3 ]( V6 A! k                elapsed_time += cycle_rate;
/ z& j& S* r* e1 M        }
3 W9 |3 e/ ^5 X9 ?) h5 U
! r0 S9 f$ x. S" d: E" o#if        1
0 P$ T3 u, }8 \& _: J        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, q! d9 [$ D; w  C
                elapsed_time = nes->cpu->GetTotalCycles();
7 C5 E0 }0 c4 ~" Z1 y) c        }
; v- d) K  W, q" h% i4 i: y        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 v5 w$ f+ D8 o+ C# ~
                elapsed_time = nes->cpu->GetTotalCycles();8 m/ g  S, j0 V4 p" y
        }" }/ Z* a& A- n. P3 M& H, c- o9 z+ W
#else( u7 `3 I  ~4 `. @0 f9 X/ Z& R- U7 N
        elapsed_time = nes->cpu->GetTotalCycles();) z; l1 X/ G$ F" P) |7 v9 H3 ^( {
#endif  H4 M" O) F, Z7 i9 N5 _4 p
}
4 u- h+ K7 E$ U) Q! P$ x) \2 m5 {9 u. }; H1 O
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)9 Z3 Q) ~6 ?+ ~! e2 C
INT        APU::GetChannelFrequency( INT no )
, S3 f+ H8 U4 K% J2 A& j{: C: U" L3 {* n& l
        if( !m_bMute[0] ); m% Q( M2 e6 C% w+ g$ y
                return        0;
  B1 K5 M: h/ e3 P0 A- V) q* L* h! `# h  ?
        // Internal! L# }3 M" E2 ?8 d
        if( no < 5 ) {6 G0 s  y; L1 r# V
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( x( C8 v) Z% D/ ]        }) r3 o7 p  s' n( H! u" }5 V8 [2 l
        // VRC6
7 c* B' K/ Y# j# H9 R8 Z( t        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 U/ Y0 k* I! Q: l+ n                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;: ?, C& i5 o; W2 N+ r: w8 `7 s
        }9 O" G9 G# `  R% ^# R9 N( m
        // FDS
$ u3 k) j, H  V7 p( a* x) @        if( (exsound_select & 0x04) && no == 0x300 ) {  v( p+ x+ Q$ A& K
                return        m_bMute[6]?fds.GetFreq( 0 ):0;5 b. ]2 c' E5 Q( g( E
        }
8 T2 f  `! t- Q) ~1 L& u# q        // MMC5
6 F7 F% l) N$ L, |) }+ }        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ }' s7 }5 k1 I                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
$ ~* V2 v- R4 a1 U        }, d! {* U; g5 [! b8 y) t# k
        // N106
" l' {8 I8 n0 u( y1 Y" @4 e        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {5 @% h1 [. c9 F& N( E2 M  b
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;' k% E; q& u9 r  e4 q
        }  U3 Y6 Q- p0 E1 p
        // FME7
+ ?  _0 a# n" l# Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {" I$ s2 s* h* Z* E3 _. W. B1 M
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;: P1 O( M; Y/ X& I
        }5 u1 ^) G: Z1 M; m
        // VRC7$ p6 V. h7 s  I7 ]/ r' q
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' ~. h* y4 i5 T$ m. l2 k
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
1 ~* v/ X3 x6 }9 _) ~        }% }% Y3 x3 L% L' Z- _
        return        0;0 n2 \; ~( |! s" F* F* ?
}& h: `+ P: L& L( Q1 H, j) C
) f3 s( U; X/ ~! y
// State Save/Load6 y# K- B+ \6 s1 S* Y
void        APU::SaveState( LPBYTE p )
; Q0 z% d% e$ H- @# Y, ]; P. s{
$ ^2 F/ [9 J+ p2 I3 {, @#ifdef        _DEBUG, ~0 \6 [6 l/ D, z" X5 O$ |
LPBYTE        pold = p;
& m/ h0 D- y& A; g3 l6 H* K#endif! _6 v6 }' S7 o( }0 m/ I

4 p! R8 r: }  G' Q. T, x- V  ?9 e        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
$ o; ]7 U, c! d4 j; @& G8 b5 O        QueueFlush();2 o, s$ L7 b0 [7 m

9 `" A! q3 \1 A/ j  y" |$ b        internal.SaveState( p );/ e- f3 [: K; @' k( R) v
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) ]" Y- |) V( T  r
8 f3 V9 J& G4 l0 [
        // VRC6
! r0 O$ I1 Y& u  p6 r2 R" x        if( exsound_select & 0x01 ) {
8 P4 v) R: W" ?: u  u                vrc6.SaveState( p );
7 E# u4 U* Z+ z: i* H7 F. f                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% H0 p6 ?3 N, p  m
        }4 d; G3 ?5 Z5 T- x
        // VRC7 (not support)* B! k" b: v/ u
        if( exsound_select & 0x02 ) {
6 Y2 O5 h" H1 E  J  n                vrc7.SaveState( p );
; `3 e0 d  J+ n: Y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( {' R6 Y7 _* x: i( N        }6 L% E" t- n, h( X6 @
        // FDS. N& n5 D' Y# U+ ^# w5 ]' ~
        if( exsound_select & 0x04 ) {
3 l0 B" M) W( Y, u- p0 n                fds.SaveState( p );
' k4 e4 j  p2 i. L& ?                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ b& P/ Q) _+ W1 \2 x        }
/ ?; @# y  v4 c+ n$ O9 f$ X        // MMC5# l& b, \5 ?" l3 l% Q
        if( exsound_select & 0x08 ) {
% D- Y7 q) }9 q                mmc5.SaveState( p );6 X" _- a! t$ o" t. V
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 U$ m& E& Q" l* I" v7 U
        }
9 h1 f8 Q) T; N: `        // N106
9 d5 F5 O& b, ~0 r        if( exsound_select & 0x10 ) {
1 E( \& R  g/ l) H: |* F                n106.SaveState( p );0 A( u, X6 n' I% ^6 m. E  @3 @3 F( B
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ h& u" w0 K# c( ?, S" `2 }" p        }
% j4 ^+ `5 c8 W6 o, J5 ~9 |) O$ r) L        // FME74 Y4 }5 g; }4 P+ W1 g
        if( exsound_select & 0x20 ) {' E1 l! O) C6 t" z" f
                fme7.SaveState( p );
/ M1 Z# |, Y4 D6 f! z9 `                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 P8 P& E  S* ]1 X1 q! y. u
        }6 a: ?4 Q0 F( j' t% O( Y
0 \  d+ u  z3 ^* \  ?# q" _
#ifdef        _DEBUG( g# V% F2 Q- V  w
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
, m: ]& P, ^( u+ J9 \#endif
) P" ^+ V; V1 I# E- B}0 ^0 |. c  D8 ~& c8 [' ^0 t

3 Y) ^+ C# D7 I* Rvoid        APU::LoadState( LPBYTE p )
5 [7 m% j8 G1 m( }4 N{
; ~9 n8 i! s6 A, o, M$ f        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) C) h/ W/ g. x0 G        QueueClear();- |. {  P2 Y2 y2 r2 @" d

" r) X$ y. `5 O$ I; c" ]3 X        internal.LoadState( p );' D" ]8 \! |6 ?* J, U3 [7 z) o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 t" L1 i% Q2 }5 ]) W1 Z1 v! {9 \' C

: t) ?1 ~$ L, u        // VRC6
6 J8 l" @" W0 }" v        if( exsound_select & 0x01 ) {: y+ t1 C9 t0 B5 I% `
                vrc6.LoadState( p );
5 T, M% y7 R' w( b; S4 V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: i3 Q4 d6 B( o0 d        }
1 M2 o) c+ w& ~        // VRC7 (not support)/ N: ?1 A8 E, u
        if( exsound_select & 0x02 ) {3 ~4 v2 T3 _8 j# d% g* v
                vrc7.LoadState( p );% m' A3 s+ P2 |+ j; X8 r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ f8 ~+ j+ p* \' x, `
        }
+ r( U, o% d' N        // FDS! y' |2 m  }' W+ [% p  h# K- K
        if( exsound_select & 0x04 ) {- K0 J& v& N5 Q  y: j  q
                fds.LoadState( p );- ?, F) M$ S( L) h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  {6 e  F3 |( v$ T8 Q' O6 n/ F. B        }
$ X6 l, \) ~: g& r        // MMC5
; E- H- Z  C! ~6 i0 g0 v( ~        if( exsound_select & 0x08 ) {
3 j5 N5 P  C% c4 [9 n3 r+ b! L: \                mmc5.LoadState( p );
9 b9 B3 x/ z: _7 K  c) g9 v                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 q6 s# M, K) w        }
5 d) e! W* _( U0 Q6 {0 C        // N106
2 e% U( ?# X0 z  X, @+ u        if( exsound_select & 0x10 ) {
3 X7 O& h# Y5 V" K8 t                n106.LoadState( p );9 T3 l6 }. |0 v# a* b1 t
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding! j+ S& q3 i1 h# ~+ h! ~: w
        }
7 A) t+ n+ [# P9 o5 [; X; k( x. i6 ]        // FME7
! w% x/ E% Y( K1 L0 {  d+ R& ~        if( exsound_select & 0x20 ) {
, n5 B( J. M' q9 ^- w                fme7.LoadState( p );
) n+ M" u* i7 H: `/ Q$ n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 S" Y" c. I: u; n
        }
) y2 H& ?9 o& ?) @. f, s}
回复

使用道具 举报

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 - Y5 [5 a' E3 f: B, z4 X
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: a! ~/ E  o( m4 W感激不尽~~

2 b/ f8 U% ~5 |恩 我對模擬器不是很有研究,- X' P& {6 E, o8 ^6 g4 d$ j
雖然要了解源碼內容,可能不是很困難,
% i, k2 @  G" A- }# ~: b不過還是要花時間,個人目前蠻忙碌的。
" x: K' J  H) ^- }# l3 P+ W. E% \7 {0 h  w9 j/ M( E
給你一個朋友的MSN,你可以跟他討論看看,' F0 a# S, |1 @
他本身是程式設計師,也對FC模擬器很有興趣。) ^3 `! d& d! \2 `, u7 V' A% m, S, O

) x9 E+ k9 @: _' @7 o9 WMSN我就PM到你的信箱了。* C: ~+ F3 A/ B; z. S7 O2 l
; K* `. O, o2 t" c
希望你能有所得。
回复

使用道具 举报

该用户从未签到

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

使用道具 举报

签到天数: 82 天

[LV.6]常住居民II

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

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
+ S! m( X7 X+ x1 O呵…… 谢过团长大人~~
7 ^) g# y/ P. B! G. l9 ?

9 c8 f* }$ q, Y4 [0 l/ [+ o* T6 N5 r哈 不客氣,算是順便幫他找個伴,大家可以一起玩。
回复

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ z' `+ ?/ J' \! r* N团长的朋友都是神,那团长就是神的boss。

6 v+ C; Q7 T6 Q7 x1 P哈 不敢當,我只是個平凡人,
7 K/ k& e9 i  _要吃飯喝水,光吸空氣是不會飽的。。。。 :)
回复

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 P( @- P8 y1 u; oZYH3 s1 _/ ~: _1 v) x* c. U- \, y0 E7 _# p! I! L
QQ:4147343060 V/ O4 H. n% r0 Y% b
Mail:zyh-01@126.com
5 M# t0 [1 e2 D- f6 v3 E# z+ i
/ q1 U2 a% c. M, o* O他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的
回复

使用道具 举报

该用户从未签到

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

使用道具 举报

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 9 s8 g1 T) F0 X
再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ }6 \& ^9 w4 I. r8 i不客氣  ^_^
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-6-6 05:22

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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