EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 v1 E7 r' Q. t& t& r3 H1 p& h
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ N0 C+ T/ [: m$ |- P/ A* f
这里有相应的模拟器源码,就当送给大侠了~~
+ A" ]7 G  E# Ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
* G4 ~  t9 `9 w0 f0 P% D. K4 K) k能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 Z3 V! V, D+ M/ O$ J
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: p* ]# w1 i2 T% ~  E- A5 h
这里有相应的模拟器源码,就当送给大侠 ...

$ w0 C9 V& A+ p0 K5 w聲音部分(Audoi Process Unit = APU):
7 o1 `) a+ Y" T# m1 i; ]$ B; h.\NES\APU.cpp
+ _, L" a+ C0 X.\NES\APU.h
, ?. T6 j; ?) v: B- c! [2 g" q( [7 C1 C# u2 w; v8 t

# p0 J: X$ k/ ^# M9 O影像處理部份(Picture Processing Unit = PPU):
. p, j8 @# {3 E4 S7 T# u1 X.\NES\PPU.cpp
' v5 S) }, K1 K.\NES\PPU.h
4 O5 w2 n6 O% W& i* c
! x0 e( n* K  f: \( h. g如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( \) v' }; C( X9 h# K7 S6 z3 t(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% t$ b8 z( L9 ~" `) ?7 O: x1 ]//////////////////////////////////////////////////////////////////////////
7 V* ]1 B% J) O) X4 E5 M//                                                                      //. f+ v9 Q' q$ _7 S5 U  o
//      NES APU core                                                    //: U) m, `2 B* M) K( ]- C# T
//                                                           Norix      //: i; F6 Y) K6 h- l0 j# |( j
//                                               written     2002/06/27 //( |! @+ W4 O5 A! j9 l$ I3 D4 C7 M
//                                               last modify ----/--/-- //6 W" J% i9 p: U1 b  O* q5 m
//////////////////////////////////////////////////////////////////////////
! ]2 M: j2 i5 |$ D$ V8 f' K3 I#include "DebugOut.h"+ b4 o3 I1 }  c; F
#include "App.h"  k1 S" D4 _* p: q$ \5 @
#include "Config.h"# Q4 E. J+ u1 o" Z+ _

; G) e0 F3 |7 A( l; ~$ m7 O#include "nes.h"# @! r& ?9 V1 `3 s
#include "mmu.h"
. n) T" I( T5 G' q! b6 y; P- k" o7 }$ A#include "cpu.h"
4 R& g" m2 ~: c1 R#include "ppu.h": \. m& e6 K$ i* a1 C
#include "rom.h": K' e! b; t0 Q& M7 U* {- X
#include "apu.h"- m; d# y- {6 _, u
6 f# W& |4 a- h3 S4 u! w6 t
// Volume adjust9 c' H  e- ?: J. P7 j
// Internal sounds9 Y* Q5 V' e) {
#define        RECTANGLE_VOL        (0x0F0)
$ v% Z8 k4 N6 h6 H1 e#define        TRIANGLE_VOL        (0x130)
  |+ @$ `! c' \/ D#define        NOISE_VOL        (0x0C0)' K( Y/ b( W! p7 ~% @) }  v' ]
#define        DPCM_VOL        (0x0F0)/ I5 _: n! p9 A0 v
// Extra sounds' j$ {/ Z% Y9 e2 w5 E' U
#define        VRC6_VOL        (0x0F0)
" F  J+ O' U5 F. j#define        VRC7_VOL        (0x130)
7 H+ ~  Z2 q* z! M#define        FDS_VOL                (0x0F0)1 i/ \6 G0 _" @* {6 \
#define        MMC5_VOL        (0x0F0)
$ F" o/ n+ `6 f* M#define        N106_VOL        (0x088)
! O/ e% Q* V6 C8 ?0 n( M! A' m0 W" V#define        FME7_VOL        (0x130)' b" W' j" p* c" T, U! `: e( d) H
! h4 m9 G1 W; ^# y$ i/ ^1 Z
APU::APU( NES* parent )* L1 @5 K5 m5 I: |
{
* T; n0 J6 ~6 K: Z7 @. ~        exsound_select = 0;
7 t9 v- W# [; x5 D) l5 _8 ?  V: U
' ^0 n% C: p1 R        nes = parent;
- ~# h6 i; y) z! b4 M        internal.SetParent( parent );
! i. l& x' ?, ^5 j2 N5 e* S. J6 \, V  Y% f0 _7 K9 e5 V1 Q, @
        last_data = last_diff = 0;1 u# @( J* ?7 A, d
& s; l& [1 V7 H) I
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 k( P$ O# \+ Q" H/ H
! a, Y7 ~5 ^9 w  O
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, r! x3 u, y* O& h
        ZEROMEMORY( &queue, sizeof(queue) );7 K8 h2 i. R2 Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 }: H; m6 m5 y# e3 V
3 v/ V5 G* {4 Q* X1 k0 }. D        for( INT i = 0; i < 16; i++ ) {, q* ]9 y9 l# t4 {6 G! m
                m_bMute = TRUE;5 [8 S- B$ f# C7 O
        }
6 ?: u' |+ y+ R+ o; D5 i/ j}
+ \/ M  I. q8 }- l. w1 Q& j/ f- \; T4 r7 g  r! C' V/ f
APU::~APU()) }/ h3 M, X- K; H4 N: V
{
# m/ g% {7 c" I: y3 j' L4 Q7 i! G7 H( ^}% A+ s- B8 R: K
4 D+ S! ~( q/ e: f* x
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# n; P# D' I1 U' I) X" A{
! L0 Q# i' }7 l: @6 s3 s        queue.data[queue.wrptr].time = writetime;1 s' E' Y: _' b* `
        queue.data[queue.wrptr].addr = addr;1 y" P4 l; V% U$ B( D3 X
        queue.data[queue.wrptr].data = data;
2 m8 }+ E& N; D- W- K        queue.wrptr++;
2 D. F$ j( g; t5 t% J        queue.wrptr&=QUEUE_LENGTH-1;" f( q: M1 ^" {5 S
        if( queue.wrptr == queue.rdptr ) {
8 x& v7 d5 Z' \6 v1 ~                DEBUGOUT( "queue overflow.\n" );
. B5 Y' F7 ]3 l* i        }
9 B" G+ c* `8 V# @% ?+ p# B: A' V}
7 l) ^% w7 o$ G/ I! F9 l5 {) v% A* I$ H
3 y3 o* o0 n# F" Y& W5 ~BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
( U6 h' a' a- x$ b7 i2 M{
: m9 I+ A, X, J1 s        if( queue.wrptr == queue.rdptr ) {6 X, Z& E$ ?/ d! `1 k! j" P0 a  t7 o
                return        FALSE;  {: T9 z3 |+ _4 r
        }
4 B0 c5 D& H1 Q3 `4 m; L        if( queue.data[queue.rdptr].time <= writetime ) {
7 C* d+ X* O, l! b. }                ret = queue.data[queue.rdptr];
6 o1 W8 n* Y3 }* r                queue.rdptr++;# t: r- K2 |, i
                queue.rdptr&=QUEUE_LENGTH-1;
+ P" M8 _4 W1 L9 F4 H: b                return        TRUE;; D/ ?- {2 Y" q0 \
        }+ k! w& h6 g  h$ D/ ~! P
        return        FALSE;
  _: X+ ]  ~$ G+ q. ?}- Z7 Z, Z0 M6 q' ]6 a' m
( \- E+ F) R9 J6 D( H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! O# D5 _# c5 v
{6 m, f  D& D. p5 h( }5 c
        exqueue.data[exqueue.wrptr].time = writetime;
, X) `7 ?$ ]( z2 A        exqueue.data[exqueue.wrptr].addr = addr;1 _1 b( H6 I2 {# H; v* @
        exqueue.data[exqueue.wrptr].data = data;5 p, n) |5 D( r4 H1 c
        exqueue.wrptr++;3 X3 Y9 g* i, L' S/ j$ e, A1 M
        exqueue.wrptr&=QUEUE_LENGTH-1;% H; t! a1 b0 |
        if( exqueue.wrptr == exqueue.rdptr ) {8 z: ~9 w! z& A1 u: U6 {
                DEBUGOUT( "exqueue overflow.\n" );
& f6 j3 \) ^$ l( U- p  c0 Z/ z        }: S* A3 ^, H& ]
}
2 `2 ~) h" H  _5 Z8 g. k* ]1 i) t& s- |# O5 {' Z' O( y2 W! i
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ), l) W3 j" g4 h, u% a
{" J7 N( p8 P% M; _1 Y
        if( exqueue.wrptr == exqueue.rdptr ) {2 w/ X5 t1 q' C! ^  u3 @6 _
                return        FALSE;, X2 E) `! x# d6 v% ?2 F
        }4 [8 k8 ~1 B: h( o% D9 B% [7 o0 W
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {  Q' P9 I# x+ t9 X  N: g! e
                ret = exqueue.data[exqueue.rdptr];  o( ]$ D4 \4 L9 z' t4 \; k6 {
                exqueue.rdptr++;2 c" d4 ^# t/ N3 s: Y+ ^
                exqueue.rdptr&=QUEUE_LENGTH-1;
; e4 e8 ?$ g( ?, H                return        TRUE;
: W# e3 L" Y8 q, C. S        }
( V$ R& h% I7 g; K4 I3 ^: W7 ^1 @        return        FALSE;
. u: B6 H; W% v$ {9 |, y! a7 [}
5 r1 Q( [5 j) d( ~" i) p. \5 o
8 B/ I& O: z8 G5 {: hvoid        APU::QueueClear()
  Z5 W+ D% ~  F# n3 F& ]* i{
4 o; B0 C; e7 o3 y        ZEROMEMORY( &queue, sizeof(queue) );
3 z; H) J/ X9 J$ y        ZEROMEMORY( &exqueue, sizeof(exqueue) );; p3 C( ^9 }/ v" b/ f" J4 i
}
6 d2 Z2 t" j' B! s; C( ^, s- P  T
: H1 G: w+ @5 kvoid        APU::QueueFlush()! L+ D! v% ?  ^6 f% D8 p
{; c$ @- s( J4 z4 i2 s7 F. F
        while( queue.wrptr != queue.rdptr ) {0 N+ e+ ~9 c# |/ P5 k5 g
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
1 Q, W0 b* D" U) W' _' I                queue.rdptr++;$ M& u& a1 B. e/ Q1 G  F
                queue.rdptr&=QUEUE_LENGTH-1;
/ B4 P9 O" n, `5 j' T        }  w! @1 Y% c- g
# c& D: X' l8 [2 S2 O8 q
        while( exqueue.wrptr != exqueue.rdptr ) {/ h5 Z( d: l  Z  R9 b4 z
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: M; ?7 c* K( F                exqueue.rdptr++;8 ?, C/ V) W+ M2 M" W- \2 `( y
                exqueue.rdptr&=QUEUE_LENGTH-1;
/ ^& g& l8 L$ W" d! G        }
9 t3 e4 s" L) S+ n) C$ p8 z2 c" |}
& n9 D: M. J" ?$ ~( I, S1 r. o5 a. A6 @4 C8 E, ^
void        APU::SoundSetup()
' B9 F# h2 a- y' I7 I7 z, i{
* w) M  J% A, I        FLOAT        fClock = nes->nescfg->CpuClock;
8 u+ y8 ~* D! h/ E( f/ `+ m0 C        INT        nRate = (INT)Config.sound.nRate;: s* `7 n& q7 h4 S
        internal.Setup( fClock, nRate );
# S% Z' i9 o$ `$ q" p8 h        vrc6.Setup( fClock, nRate );: ^" @- y$ t& y' i, E0 O
        vrc7.Setup( fClock, nRate );
. }% l" e. P  l. X' E8 ?; b        mmc5.Setup( fClock, nRate );
3 m1 m( U( O6 D9 g( D1 |/ m        fds.Setup ( fClock, nRate );9 }; V2 t5 c! }2 J. r' b/ d
        n106.Setup( fClock, nRate );* d+ o+ b6 B: |- C( u9 x6 e8 e
        fme7.Setup( fClock, nRate );0 @6 i3 f4 t/ d( j( b
}3 f( Q  v5 v) T. |& A/ Y
' o3 n+ A7 p6 |) x: N2 \; I& X; J
void        APU::Reset()9 u" G* A: m0 ?6 n8 @! G/ k
{: Y& }! d0 f0 h' H# y. X
        ZEROMEMORY( &queue, sizeof(queue) );
$ H5 u# ?& H8 ?7 y        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 A$ }1 F) Y" L; {8 v2 L
" y1 A$ z5 I* q
        elapsed_time = 0;  {( N$ ], W' V9 h; R- J% ~
- G/ Y; W6 e8 j! V4 |
        FLOAT        fClock = nes->nescfg->CpuClock;
* ~) ~+ F9 {  `* j5 @. y        INT        nRate = (INT)Config.sound.nRate;+ ^% E% T+ }3 p* l0 X2 u8 V: c
        internal.Reset( fClock, nRate );7 C3 ~# \% v3 j1 e6 @
        vrc6.Reset( fClock, nRate );; x0 x$ V& x) S) [5 [
        vrc7.Reset( fClock, nRate );+ q1 k) K# d6 X( d
        mmc5.Reset( fClock, nRate );
: \; a" C& U' E6 n, P; }/ [: V        fds.Reset ( fClock, nRate );1 m4 Y4 d7 x$ F7 ^
        n106.Reset( fClock, nRate );! u$ a: S; p7 d+ w0 c
        fme7.Reset( fClock, nRate );* i6 ?& B  D! V1 a+ c1 g2 J
4 j, a5 H# g! v( Q& R; a: g
        SoundSetup();1 s/ k6 b  I" V1 C3 X2 ^: ^
}
) e' C( z& |! p, }3 B/ z! o) E
void        APU::SelectExSound( BYTE data )& g$ s% T  M! j- V- E
{# {/ ]% ]+ ?. A9 I8 e
        exsound_select = data;
0 w# R$ z0 ^9 L) d8 y, M}
8 u) O6 n; C! t; l' J; B" f. J( ]$ b0 o
BYTE        APU::Read( WORD addr )
3 i  }& w2 t& l{2 ~( W+ G4 T) ?3 H2 w% m" ~% v( s5 |6 ^
        return        internal.SyncRead( addr );. i; N+ a" X0 F1 m) u
}# U% _" W' u. s: E6 z

0 x% l4 X5 I+ T/ {void        APU::Write( WORD addr, BYTE data )4 U1 w6 G& |2 U; ]2 o4 h
{
; e! F# V* ?, E6 k# v- f' O        // $4018偼VirtuaNES屌桳億乕僩
' b  y1 n5 W) N8 s& P        if( addr >= 0x4000 && addr <= 0x401F ) {
5 O! ^' m/ _: J. g2 A/ i0 g* p                internal.SyncWrite( addr, data );
$ A* x0 i* o4 n. e/ F! i0 F                SetQueue( nes->cpu->GetTotalCycles(), addr, data );" c: `- k5 J' h) V! |- ^  o
        }% s: O) d9 M0 A& u+ u
}
* c9 N4 u, s6 M$ |8 u! M2 q) A
6 n# M9 \' o! x7 e" z$ nBYTE        APU::ExRead( WORD addr )
. a5 c, L$ @5 x$ ]{4 r+ o# I% h. t! a8 X3 @
BYTE        data = 0;# b8 }: b& y, d

: Q6 p3 q4 G! T, w+ M  b        if( exsound_select & 0x10 ) {, o1 m+ S" I, h% e; t' y7 a2 }
                if( addr == 0x4800 ) {
( U8 w' d$ J. n* G) z* d# l                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );' }1 Q) S* j' Z( ?
                }' y0 w7 \* x! H9 r7 b5 }
        }5 k1 J: m& o7 B& k4 h
        if( exsound_select & 0x04 ) {
5 u* b% ]6 }+ H* J& C1 t! M3 m; [                if( addr >= 0x4040 && addr < 0x4100 ) {0 s( r8 L: x8 T6 S( _3 U
                        data = fds.SyncRead( addr );2 w) e% P" x* @% M  q0 ~
                }: n/ m8 T0 u: p  N% ^
        }( X1 E, C, d) T# U$ \( G
        if( exsound_select & 0x08 ) {' t0 T/ `$ |+ o2 d% _
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# Z. w5 W% b7 b. B" h+ a                        data = mmc5.SyncRead( addr );" L2 g/ y' [+ Z; @* q) {% {$ A
                }
  c7 ~' L: q; G        }
7 X2 f2 r/ c4 _
2 |$ ]# W0 o  g$ E6 h        return        data;
- {6 z6 ?+ e6 @( z2 n9 h0 d}: n* A4 q7 z) H- H; s8 p6 Z9 {
4 u. A; A/ q/ a" ]% Z! @
void        APU::ExWrite( WORD addr, BYTE data )5 H1 d1 G4 `" [3 f, @& b
{
0 z! x8 H* c. Y, V8 V/ N+ W$ E% Z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );8 X% y0 y; r: s: H

- k! C, P; ?! _" r        if( exsound_select & 0x04 ) {
  l% o, p" k1 C7 [( ^$ d1 N2 Q                if( addr >= 0x4040 && addr < 0x4100 ) {7 `8 |2 @4 B( x0 s4 A8 Z% v% U
                        fds.SyncWrite( addr, data );
1 ?1 `1 l7 E3 C7 n) P- P                }# @7 P, F" a& j5 S9 X) O+ F' W
        }
! L$ N4 c2 P5 `4 ?4 p0 `( g; r7 A% y2 w. m7 [" k
        if( exsound_select & 0x08 ) {9 E) v" _. m6 \1 u6 m  E
                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 a$ u& I1 C" P+ R                        mmc5.SyncWrite( addr, data );5 j$ G6 j6 Y0 [  W3 O6 |& [# Q. U
                }) m1 |+ T' t. Q* K2 y7 @7 D" ?
        }
; Z: P9 z5 e& x1 t  w/ D% }8 x}
, d' L  `$ S" Q+ {# ?% W# y" i; l0 k9 W
void        APU::Sync()
" @- k. J; z* c3 \: U0 ?{; G+ [, q$ D( O  W
}
# C7 a/ ]6 b! s# r) g0 @5 P" }6 ]1 a
void        APU::SyncDPCM( INT cycles )
) @& I4 l+ ]. ]{- `1 m4 [$ [& d+ }8 {: {3 U8 }* s
        internal.Sync( cycles );" C& S! ?" h. O$ w
/ ^- n5 c1 `/ w% W/ }
        if( exsound_select & 0x04 ) {
' ?1 k1 G( K& p' s; C1 w                fds.Sync( cycles );0 t0 d5 A/ r" T; I. D
        }
6 I* }$ t0 |! ]( L8 j5 p* d* D        if( exsound_select & 0x08 ) {7 H+ }3 j( h; h, o; E: Y( t
                mmc5.Sync( cycles );+ U' v! e: a  q! E: ?' ~5 ^
        }  V6 k( h6 Q5 W: c8 c3 b# {8 }
}( k  U8 u7 q, k( K
4 W; _9 T9 P' E# B0 h: Q
void        APU::WriteProcess( WORD addr, BYTE data )! P1 m& C+ V$ b% E$ ^" q' P( d
{0 C  Q) H$ s; Q# P% ]
        // $4018偼VirtuaNES屌桳億乕僩
7 V/ N! c' f1 I  H! o+ p* A        if( addr >= 0x4000 && addr <= 0x401F ) {0 `# K' a, X, i! s0 ?6 g  p
                internal.Write( addr, data );3 a( T, I' }) K" Y( q" p0 P' h
        }
! x! c$ l  \, [! C1 ~) M}
9 W/ I/ J: @. p$ o+ A
4 C4 @9 d% i# b: y, \$ cvoid        APU::WriteExProcess( WORD addr, BYTE data )+ [( I; g+ g/ O, ~! _! u
{7 |/ c# E0 u% x1 K) i2 f* I1 _$ C4 \
        if( exsound_select & 0x01 ) {" F$ d6 k' ]% h& q
                vrc6.Write( addr, data );
7 A) z3 ^6 Y, @        }0 P0 C- R8 Y  S$ j
        if( exsound_select & 0x02 ) {, i5 l& O' _% X' Z8 ^' E: G
                vrc7.Write( addr, data );
! t) ~9 u/ s& O9 t/ T, o, Q        }! ^4 J% P3 @# U, }
        if( exsound_select & 0x04 ) {) j0 e( U, E# ], Q+ Y
                fds.Write( addr, data );/ A* S6 A3 T% i% D' R; c
        }
- c, ?$ a0 I- Y, h+ n9 @: c' p        if( exsound_select & 0x08 ) {/ u4 ^. ~& i, c3 ?" t6 G
                mmc5.Write( addr, data );
' E( p- B0 w6 \  ^3 y        }
% K4 R# `. S3 [9 I5 w        if( exsound_select & 0x10 ) {3 n# q9 F( ]7 X" p. F
                if( addr == 0x0000 ) {
! i  x: N5 B3 O- G3 S" O3 H                        BYTE        dummy = n106.Read( addr );
; w8 ^% k" g( D7 D: K                } else {
' t; c" s* r0 ^0 v7 \' Q                        n106.Write( addr, data );# Z% ]2 j. q  l
                }
" F3 h# e/ G3 H7 e# E        }7 S6 d' I2 z% D; S
        if( exsound_select & 0x20 ) {3 G$ A0 m) {5 `
                fme7.Write( addr, data );- O0 T3 e2 b& Q* K, L( \+ l1 y
        }8 X& b$ e( D  D8 H5 I/ I/ L( Y8 N8 n( w
}( M, Q* ?; q# Y. X: X
7 U+ Q$ f# P0 V/ }8 w+ B8 `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 W' [0 F  ]. _. ^9 Y
{
- y( K0 _; |+ ~, s0 P! h! D) EINT        nBits = Config.sound.nBits;6 @: ~" k' Q  e& I
DWORD        dwLength = dwSize / (nBits/8);
# d; L. e( P; C( i- [2 YINT        output;
' C& _( G4 ~; w. T, i1 CQUEUEDATA q;% A8 j' ^1 L9 D- i6 t6 }8 B
DWORD        writetime;9 C# Z- l: @2 v+ m/ P- T

7 d: Q5 Y+ c. G- H% d8 NLPSHORT        pSoundBuf = m_SoundBuffer;
# ]; t' O/ }! }' ~- zINT        nCcount = 0;( p, w* Z1 D; B

: _) |; |) R# a/ q8 l1 O# tINT        nFilterType = Config.sound.nFilterType;0 |& U/ X4 m- U: N% j2 A- u- y
, O# ?# F! Y, Y# I
        if( !Config.sound.bEnable ) {
+ L* D3 \+ o8 B7 z                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
' |6 i. Y, ]1 Y- L* C& }                return;/ ~( ?1 y# S9 |1 n! k+ Q
        }6 F. }1 @" H+ ]" v/ ]
5 {2 ]( v% z! ^2 `
        // Volume setup. c5 ~" W- Y! K1 V
        //  0:Master& A. G4 @# K! J# |# B
        //  1:Rectangle 1  V1 w9 p" }$ s, P2 n' r/ m
        //  2:Rectangle 25 X8 F$ v1 }& m$ Q' j
        //  3:Triangle
  ~+ U7 H3 ~. A. I' l5 a        //  4:Noise
8 r9 Y* d- g( Z. @        //  5:DPCM
/ t$ v6 p  o& X        //  6:VRC6
! D% |- q2 ~' n1 s        //  7:VRC7
* V9 J- ?5 _6 n+ }7 i1 ?        //  8:FDS, T3 |  r7 @9 h; p. L$ X
        //  9:MMC55 c$ w8 t8 l. S2 a
        // 10:N106% d3 A3 m5 |6 X! x; D. n% v
        // 11:FME70 P' Z( J/ Q5 M0 G* p
        INT        vol[24];
8 b% }# ^8 f# ]& V% q# U( ]% p* _        BOOL*        bMute = m_bMute;4 D9 w6 B. X& u- i( U$ D
        SHORT*        nVolume = Config.sound.nVolume;: E& ]* P0 P( B1 s

9 z5 ]- f* |7 O4 i( w0 k        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
  k. s+ P% p9 k( H' Z" y
$ \! I9 R3 ]" W: Z! a2 I3 X        // Internal) ?1 m$ ~, e' r6 c
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! x8 k% K" j% D/ [& q6 ~0 [( o7 k        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 b, R; ~3 G* t8 _; n, b& h0 R
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;0 e6 j% e. V0 v( V
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;0 U) T( f" c2 P
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;0 i5 ~8 t- o% i' E) D
6 T4 D% m3 `) v7 @% t( e
        // VRC6
8 Z1 L+ @' ?8 O2 q8 o1 E        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 I* M4 C5 |# b3 A# i% `: V6 p        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, ~' O9 ]& F2 E: Y8 `1 O
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, E, P' S8 H( f* m- b+ X6 M5 V, l
        // VRC7
, X7 S; N5 s# r: N! q# h        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 |$ J# O% F, D/ R/ f. n
. _  G  _6 {2 o+ a        // FDS* x4 Y6 V5 k) e+ t% D
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# w: I: H- Q8 x; j2 a  ]* t
; _7 _/ o. j! N. Q' t/ }        // MMC5( E" y" E: T8 f& j! i  F
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;% i# K7 g: u% E; B- O3 ]8 W
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# C/ l" A; Z' T4 i. w        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' P6 ~, x" B8 y8 P& V! o
5 v. g) S" i/ V# ~+ N
        // N106
( Y) n, V! I! M/ o# ~        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. P, u. _3 K8 f
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ E* J0 x1 j7 R$ f3 u) E) W- _8 ^
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* l, V+ H8 i6 ^3 u
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 P6 t2 l5 p/ P; i0 w; g" D3 }3 p        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 d( @+ `3 y- O' X+ S! V4 l. g. G        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 M; d( q7 }4 a- g; d  z4 k# U        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 {- [5 w+ H0 W6 `5 ]
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; `# |7 |% b& W% s# g7 l* h: X
  F& H7 ]0 P9 q* S6 @. R
        // FME74 I0 X  u0 |) h- [
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 e% R4 M, r9 o. A        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 \! |! g& V' T! F        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 _. e6 c' m3 B$ c
; M6 O! t& o8 X6 L
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;: R. t4 _5 H' u0 a  c
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 {' g2 y: }! B- Y
6 k& q$ }6 y8 h0 l/ k) N
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟% ^3 z3 n( [6 e! r
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
9 r" Q! ?) a3 l                QueueFlush();
, h& O# g1 w, `, i3 T        }: q" x% Y; w3 Y& t4 a0 @) D1 C
# b. U; N$ b/ S. k! o1 C
        while( dwLength-- ) {
* V0 w" O+ G: P8 U) x) U% a4 i* ^                writetime = (DWORD)elapsed_time;6 q- B1 h2 m- J! }" a& _$ W) D' T
2 h" @$ m( I1 R4 K1 ?
                while( GetQueue( writetime, q ) ) {+ P  U/ _( p) m0 K# U$ U8 p
                        WriteProcess( q.addr, q.data );
4 E# W6 B& P# z/ I                }
# I2 K, v8 J; O5 G1 Y! m7 m8 g3 B) B, o8 o
                while( GetExQueue( writetime, q ) ) {* p  [3 N  {3 }0 w
                        WriteExProcess( q.addr, q.data );
2 i/ j/ c7 Q, m* d                }, d" P# w# m1 Z1 }; Z9 y" v+ S' h

- O7 h' b; z7 ~                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7; C6 G* M9 k4 C
                output = 0;+ `8 v  y* H& \* H: U+ G$ C  H
                output += internal.Process( 0 )*vol[0];6 K  P8 R; h3 _7 K9 A
                output += internal.Process( 1 )*vol[1];; F: O8 S3 {- T' C: n" g2 \  q
                output += internal.Process( 2 )*vol[2];+ Z0 w+ e6 p$ c. U6 l
                output += internal.Process( 3 )*vol[3];
; p  y( Y4 p7 Y                output += internal.Process( 4 )*vol[4];
  n! R* U9 u# T9 x" t2 B; E7 j! M% ^. u6 ]$ ]# B
                if( exsound_select & 0x01 ) {! V) `5 F- @7 P
                        output += vrc6.Process( 0 )*vol[5];- {: C) R: d$ a2 B
                        output += vrc6.Process( 1 )*vol[6];2 x3 B- I+ W# X
                        output += vrc6.Process( 2 )*vol[7];' J. }. }$ I  D- ]. B; Z: q
                }
. _4 e: h- [% Z: w3 i                if( exsound_select & 0x02 ) {
  S5 E8 O* ]4 P" z6 |                        output += vrc7.Process( 0 )*vol[8];
* }1 J. [  w. t" [                }; ^' S9 P" A, b% `; S5 P/ K; b& ^0 N
                if( exsound_select & 0x04 ) {
% i: {% v) P4 I. K# q, S1 U                        output += fds.Process( 0 )*vol[9];
. x3 J' h$ x6 J8 C; s  q% M                }
9 ~; r7 Y. Q! R0 D2 ^1 p- t                if( exsound_select & 0x08 ) {5 K3 L& e: H' o4 ~6 o* B; r* ?- H# V8 i
                        output += mmc5.Process( 0 )*vol[10];# n8 r& d. A1 O; q1 W" ]
                        output += mmc5.Process( 1 )*vol[11];
+ N6 s/ h; Z  u. [/ X                        output += mmc5.Process( 2 )*vol[12];7 C" f2 ?1 G9 `: _+ {4 L
                }
6 I, g+ v, q* ]. |2 u4 i# p                if( exsound_select & 0x10 ) {4 ]4 g* `% [* ^" Y
                        output += n106.Process( 0 )*vol[13];
7 ]# [( E+ o+ V) @! G( z2 Z6 W# [                        output += n106.Process( 1 )*vol[14];
% S2 _+ l, I# U& \$ U9 U                        output += n106.Process( 2 )*vol[15];
1 U! J" Q4 @7 X- i  R                        output += n106.Process( 3 )*vol[16];
1 Y2 O# L  U* ^/ h                        output += n106.Process( 4 )*vol[17];
% n2 B! t5 `/ x$ m  k  r                        output += n106.Process( 5 )*vol[18];% d, A9 o) V1 `/ v* Q
                        output += n106.Process( 6 )*vol[19];' U% ?# R. b' v* j; D$ O* z! M
                        output += n106.Process( 7 )*vol[20];
- b' e( ?/ y2 z6 l4 T0 n5 c5 C                }
( K  v) t! u( C* K                if( exsound_select & 0x20 ) {
: P- O( b& j5 L$ @                        fme7.Process( 3 );        // Envelope & Noise2 E, ]7 d2 t% N4 [3 T. I4 k
                        output += fme7.Process( 0 )*vol[21];
/ R! u5 n+ ~3 l0 }* t                        output += fme7.Process( 1 )*vol[22];0 S2 d7 z9 K9 m: N7 R1 h
                        output += fme7.Process( 2 )*vol[23];7 ^' t0 }, D5 S
                }( n* m8 q3 `8 @* z6 ~8 J; g

/ ]2 P1 B+ K8 @: `                output >>= 8;
: C* K* q3 E7 \' b' n  V4 ~
! v; c0 f, w4 J8 G2 Z0 O5 I5 O                if( nFilterType == 1 ) {
5 w$ F9 ], I; Q/ u; g% b; n/ i: j1 d                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 c3 E& X) X9 p- Y& R" Z8 A5 G: X
                        output = (lowpass_filter[0]+output)/2;
6 O2 e! I: L% O( P0 a" b+ @                        lowpass_filter[0] = output;
/ Z9 w2 _3 ?% N' w; \$ Z5 l                } else if( nFilterType == 2 ) {6 V7 Z) D9 C7 Z6 z" |
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
- u. v5 D4 N# Q" a                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;5 @9 f9 r$ P/ _: v, B2 A
                        lowpass_filter[1] = lowpass_filter[0];
6 S; k$ @! V; O9 {* d2 F& P, s                        lowpass_filter[0] = output;
$ x8 a3 J+ J( H% Q% o9 F7 w! U! I                } else if( nFilterType == 3 ) {
" R# u  I+ _7 B% Z/ f                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 v. R7 @2 N. u# O: i( I9 S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;, F+ P& p" V/ Z% H
                        lowpass_filter[2] = lowpass_filter[1];- m) M2 C6 K9 y( ?0 `9 n# a
                        lowpass_filter[1] = lowpass_filter[0];5 ^" b+ W* z) |( e: R5 M
                        lowpass_filter[0] = output;
- x1 o9 n3 C$ f' U                } else if( nFilterType == 4 ) {7 z( J' H. H) T1 I
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
( I" U2 \! [4 |( t4 e                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;" p( O* a- M9 j2 @5 r# t0 l. O
                        lowpass_filter[1] = lowpass_filter[0];$ }( f9 k; m. w6 m5 L! H8 ?
                        lowpass_filter[0] = output;9 P; h( s6 t  e: [
                }/ a, C! S5 e% L& B1 w2 |
5 _$ U" ~4 \  a: k- V
#if        0
( x5 Y" K" H, Z  ^1 J/ K. ~                // DC惉暘偺僇僢僩  @8 D' C( ]& }3 n7 J1 B
                {. l7 c/ Y4 Z- u: p: j) t: C4 D/ Q
                static double ave = 0.0, max=0.0, min=0.0;6 ?, I" b, B! f% [# {+ @
                double delta;% o+ \4 O" M/ D+ U2 X) n: S
                delta = (max-min)/32768.0;
4 M+ G8 T( R7 R7 |$ z3 I# G8 B6 ~+ z                max -= delta;+ ~" x9 k/ z7 b. s( G6 _
                min += delta;4 P3 W  I8 {9 f* \' C- ~4 n% x
                if( output > max ) max = output;
3 x5 i! x3 [) @) Z8 v, |: l                if( output < min ) min = output;
- R+ }; z6 n" E$ g7 p                ave -= ave/1024.0;* ?  F* e1 O' w. ]/ K. O0 r, H* Z
                ave += (max+min)/2048.0;; t. q; L! Q! k: c2 n
                output -= (INT)ave;% U! ~9 k: V1 L: W1 \6 G8 |/ Y
                }
6 ?3 O+ a; t8 J  @& \#endif
) D5 z! C# O; x5 W& I#if        1
+ h0 R7 `0 a' M& i" b" c4 ?                // DC惉暘偺僇僢僩(HPF TEST)- s5 h5 e! I$ m' P
                {
( T! h/ |( K* \1 l2 m/ I) s//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- R8 Q+ t. b9 U9 S* C; P
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# ^- P; V1 Z% H# M! X2 @* W                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, h3 p: j" w. w5 a6 l. ?- E. X4 p                static        double        tmp = 0.0;
+ p4 r1 l0 g' o( K: P                double        in, out;
1 _  m* b, {0 I4 i2 }
$ `) f. y9 ^' x/ C+ R2 N9 ?+ ~                in = (double)output;: [' Z' ~, Z- \
                out = (in - tmp);; W- H* ?4 ], z' P# ~
                tmp = tmp + cutoff * out;- P/ a! |! x. d. c  |" W7 p8 Y

$ W. b# F' A7 A0 u& ~                output = (INT)out;
9 T1 d) |4 e  l# \8 w( N  A( j7 Z                }
- {/ F% Y% J& e#endif
  `( ~1 m3 `- n4 \9 M& V#if        0
4 z5 Q& X$ {( P0 X: o0 g4 \& }                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
# |/ ?; ]3 \* ]2 s/ A1 O+ C+ u                {
, x3 `1 Z4 b/ |) i                INT        diff = abs(output-last_data);6 `  `$ i% K  U2 B" M
                if( diff > 0x4000 ) {
: W. b* m$ B5 J& P; U4 v9 w                        output /= 4;
0 ^- V1 w! }; d7 X                } else
$ q/ W8 k9 w3 ~  _4 C                if( diff > 0x3000 ) {3 y/ q& y& J7 L
                        output /= 3;
# z9 ], ~. t8 i$ ^: U) }# w, T( l                } else! C  g* }. ]1 h' {8 ]
                if( diff > 0x2000 ) {
3 b$ U" _. S0 C0 M, X8 e                        output /= 2;
6 H& c! Z7 H2 x* f  x0 f8 v                }4 K2 s  u* f4 S6 D4 J' C: Z
                last_data = output;( h/ m* Y0 @; `: i4 R! {
                }
& X# e/ c6 `: D$ |- @9 ]#endif# }: v/ G3 H: Q. L1 a/ d$ }0 f4 l
                // Limit
, Z7 L6 N$ e1 n& x/ E( T0 ?9 _2 ~                if( output > 0x7FFF ) {, V+ P* w* F! v5 R1 T: i
                        output = 0x7FFF;% ]/ Q. g2 R$ q8 a# }2 p4 ?/ n
                } else if( output < -0x8000 ) {! n/ Z5 P$ A. b3 R
                        output = -0x8000;
: R- G# T  E% g0 k                }
0 e' I4 O% N4 X4 U) R
- n6 t- X' K; F: O6 P1 |                if( nBits != 8 ) {- E$ r" @1 B9 c- o1 R5 J, x  g
                        *(SHORT*)lpBuffer = (SHORT)output;  A: J2 L6 y; N) F* u: w
                        lpBuffer += sizeof(SHORT);
% k* U" z1 m' j0 d4 C" T                } else {
' x- Z5 K# @5 n% n1 ]                        *lpBuffer++ = (output>>8)^0x80;
" j1 _6 g# C  T4 f% ~                }
' Y% ?. ^9 d/ C/ {  L0 H  s. L( j2 [3 C7 S
                if( nCcount < 0x0100 ); D, g# k' `3 q
                        pSoundBuf[nCcount++] = (SHORT)output;$ w6 {" E' z5 h2 x0 O

' K/ N. L! j& s/ J) d. Z//                elapsedtime += cycle_rate;% I. x. v& |9 X
                elapsed_time += cycle_rate;/ n9 a% I+ i' g/ y1 C* O
        }$ ~/ m+ _) @, M6 _, ]
) j# _* P6 M+ A% `5 l; r0 {8 \$ a  M1 N
#if        1
0 o( j( A0 o" G        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {( p4 x$ j: u" c6 Q4 P* Y& O
                elapsed_time = nes->cpu->GetTotalCycles();
6 |5 C1 x' U+ M  ?" k% Q        }
* j3 |( `) H3 Z        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
! l) k+ g; z8 D5 C                elapsed_time = nes->cpu->GetTotalCycles();
* d3 Y/ G( I. T  \        }
- `. z6 W, D2 L) @#else
; R9 b! Y" v* Z) U        elapsed_time = nes->cpu->GetTotalCycles();! S' B" B( a0 u, M
#endif
( B3 R  ~  b0 B# g; X2 u}
2 {% l9 @7 I& `6 V
( ?+ C! c: \6 E) D3 Y& I8 k// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡): C* `3 j3 @$ F2 T/ }* {
INT        APU::GetChannelFrequency( INT no )
- L- D- j# V+ Y* ]) M0 w& a{
. m/ W* y8 ^6 y% Q" c        if( !m_bMute[0] )
# N  o, o6 Q0 Q1 O                return        0;" V( L- U7 \& |& T" f
8 n# b  D7 z  a; [9 s
        // Internal/ w1 s9 W* i9 k, p: f
        if( no < 5 ) {
: t4 I* @* x4 h                return        m_bMute[no+1]?internal.GetFreq( no ):0;1 z% ^* }, i% R3 z6 o) R
        }
* G  J( z* o7 Y2 k7 k9 a        // VRC6
  D6 p( E9 h- }% H4 e# }8 e' z        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
% B. a# _5 e- y1 T) a                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ T+ L  A3 |7 d4 H1 w% }1 e
        }  A: y6 O! X( v2 @) e2 U5 o% b
        // FDS0 S: A& M% i: I% n8 m$ L; C) C
        if( (exsound_select & 0x04) && no == 0x300 ) {
; R7 P5 c; d4 }- B3 j/ c8 T                return        m_bMute[6]?fds.GetFreq( 0 ):0;3 U/ ]5 T* U: e# K+ A
        }# N3 x  ]# B8 `5 D; ^7 S
        // MMC5
5 N9 J. P4 K+ T0 u        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
) R2 _, U, a; r                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;+ v: o: G: b! d* _) e# _& N
        }
9 H7 h, |+ m2 t* K        // N106
: Y- _3 ^( j8 ?, g. b1 U4 o        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {. h3 B$ [; Y: A7 o' r- \
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;/ M7 D* u) [2 K9 V
        }/ X" J) Q1 h# L$ s) b2 d
        // FME72 d$ c/ i9 O5 t  f6 u7 l
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
2 U; ~8 |( j% E1 V7 K1 h9 d                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* K7 K. o6 \% V1 f& }& `# r8 ^  j        }5 C5 j2 e1 }2 C! U$ l% E) \
        // VRC7& Z- z0 N# L2 T8 Z: v0 X2 O
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 N. P8 N6 u) B: J/ N                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 q" T* M  i$ a4 L8 i. m% D7 ~' e        }) G7 u4 [$ _& X1 \) a; s
        return        0;# i. L: ?3 [* s; R6 D
}2 v# t+ E  r8 e! D: q

7 W2 {& @% F; w// State Save/Load
% R( }; Y5 U. z5 Cvoid        APU::SaveState( LPBYTE p )
; k0 g# \7 p1 Z, }/ F! U{( g7 x# j& |6 h% ~" ?4 Q
#ifdef        _DEBUG
+ a/ C1 h5 S8 q& ~, ?' U' u+ uLPBYTE        pold = p;
$ R$ h) N5 P8 r6 G+ d9 Q#endif
( h% U% U4 D7 E6 k5 _# y8 L
: |5 Y7 u" E; d; D- Z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
, Y( ?7 u% s+ n        QueueFlush();: v" t, b( v0 J/ }

1 p" f1 {5 {/ w        internal.SaveState( p );( m9 F/ A6 i/ i7 ^3 l
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding" w1 [6 o2 [! R$ K# F
. {. w8 x' G" r4 v1 v
        // VRC6
; {/ N( P' z! y        if( exsound_select & 0x01 ) {2 o$ ]- k  v% o( g) _+ Q& G
                vrc6.SaveState( p );
2 R' b* ~3 c# y; |  X                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 X6 o* B; o: Z+ a( [        }
: H- t* B8 P# O6 M8 P5 r' }        // VRC7 (not support)
; y: h$ R7 M) _: l& J0 S7 Z        if( exsound_select & 0x02 ) {0 V- L, b( p, m7 \
                vrc7.SaveState( p );
7 y* R" B4 D  ?, N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ I# A' `. S1 _  R3 `, a# m3 b
        }$ x/ N: k# u8 C6 r' ^; K; {, d
        // FDS: H1 x- e$ E% z; R
        if( exsound_select & 0x04 ) {
9 e5 M2 a* [4 L# S                fds.SaveState( p );
+ t! x$ Z( A' P3 r# ?$ I$ U9 L                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! I3 X; y6 r, L% f# I        }0 x, V- x9 r* N
        // MMC5# Q# c$ P  P. O( a5 z, s
        if( exsound_select & 0x08 ) {  J* I! m- |: n& f. m1 B3 T) D
                mmc5.SaveState( p );% y8 ?+ J3 D; Q/ _
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& `% A. Y" d" Y
        }
" F) s6 g9 ?) K6 |9 c9 X        // N106( g+ S3 d" M# o% T  p
        if( exsound_select & 0x10 ) {+ E8 i7 O$ R  r8 {
                n106.SaveState( p );
! R- }  y+ H% [1 Q                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 ]8 L# g( I0 }% Y- ^  W8 _        }( b7 @$ v- E7 U2 E6 i
        // FME7) Y+ E$ O- T- L  u( [8 P
        if( exsound_select & 0x20 ) {" T; i4 O$ C1 G) n0 ~' u  i; H
                fme7.SaveState( p );7 [$ u. q# {# i& G* k
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, S9 |( S4 b% R$ O, O& z+ X1 u        }
! ~* f) }" v0 Q7 y" Q$ j* d% X* l- _- T. X7 S" ^. @" l
#ifdef        _DEBUG( d$ a; b$ e6 I7 f
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
& x% R+ p4 a! @  l#endif. V1 x4 A4 {4 h8 f/ c# g$ Z5 O
}
* t9 |% u& \, n3 w& Z
2 t3 L. r7 J( Z6 Wvoid        APU::LoadState( LPBYTE p )
. I) Q$ |( B# @- J{
  O5 j. |- C& o+ [2 }, h9 D: j& S$ f        // 帪娫幉傪摨婜偝偣傞堊偵徚偡4 ~7 e6 M. D. O) N7 D+ E
        QueueClear();
2 a: P% ~) s8 v
% u5 U, z' R6 C% r9 A5 X        internal.LoadState( p );
2 K7 i* G7 b( `; R8 [( ?8 _        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: `) x! e6 T- F0 [$ x
2 Q' F( I. Z$ f2 V7 y% ^        // VRC67 C" Q1 t3 E- O
        if( exsound_select & 0x01 ) {6 K( n- ]' C/ w5 g
                vrc6.LoadState( p );- X- Y: f) l" f! D! @
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 F* x# V8 z4 @1 k2 [" V7 _6 n+ a1 Y
        }
5 @* }0 s4 U5 G, \7 q        // VRC7 (not support): |4 v2 O; r; j3 G( B' c" ^# d
        if( exsound_select & 0x02 ) {
, j, j* m) s2 V/ Z- ], f                vrc7.LoadState( p );# e/ g$ o- J7 f2 r! z5 b- s
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 G7 l9 U4 D# g' h- M$ e9 a
        }
* m- v2 c7 W- W: o% o5 s4 A        // FDS2 k+ z- {& m9 h# O/ C
        if( exsound_select & 0x04 ) {
$ t/ B' n0 X) A8 j                fds.LoadState( p );1 s1 I; x9 a( _3 v; z1 v* y; C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# B" _* A5 f  o& l% o9 L# l9 E
        }* j; c8 P" L! `9 X1 w7 h/ @
        // MMC5+ H% I  W( v" B" B' s2 v( N
        if( exsound_select & 0x08 ) {4 p) l2 Y) C* }- ]3 _; l" E0 k
                mmc5.LoadState( p );7 M2 I4 i6 f+ U/ z4 B7 |9 z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' p9 _* A  j! K8 d- K$ Z
        }+ l" J5 m! V+ o# }/ _( V
        // N1063 d9 p! U7 l/ n- ?& Q
        if( exsound_select & 0x10 ) {8 T1 v3 X; d5 k
                n106.LoadState( p );# i# c: z3 Y3 t1 g, [5 h+ X0 M! C
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 c6 V4 E  }4 W2 a, R
        }  ?8 ^/ h- A+ [" u: N0 g/ a
        // FME7
8 X6 }8 L& E, }  ~6 G; |8 u5 |        if( exsound_select & 0x20 ) {! B8 _  ]1 }5 g5 _5 C
                fme7.LoadState( p );
* Z/ Z7 c( [+ F6 U3 ], x; k* N( g                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& R0 T6 q; ~& L, v        }& G. y- c" M% G$ [# I! D
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
3 [0 \: y% l8 {可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
* s, B% g6 F, U- i- q感激不尽~~
  r) m( U. j" v) N5 h
恩 我對模擬器不是很有研究,3 _' X1 [: X  Z5 P1 F
雖然要了解源碼內容,可能不是很困難,
! Y! n0 t8 Z* N) k不過還是要花時間,個人目前蠻忙碌的。
/ w+ q7 C6 h+ l& K2 x9 u$ l* Z: A
給你一個朋友的MSN,你可以跟他討論看看,% k+ [) b# g# k: q  y6 I# F! }
他本身是程式設計師,也對FC模擬器很有興趣。, l. B$ u! I. F: [6 Q1 r- }
' O  M# [# g# S) Q( z, K# v
MSN我就PM到你的信箱了。, V7 e; X/ r$ s. F- y

, d& Z, c9 M% T$ j" a# ]希望你能有所得。

该用户从未签到

 楼主| 发表于 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 I0 E- y, ]0 o
呵…… 谢过团长大人~~
, d+ p6 S/ J6 ^% z7 ~2 y8 H" @
2 H2 \9 |7 Z3 h6 n
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
* t4 a2 ]7 ?4 ^+ z: J# X" Y' r8 ]9 d团长的朋友都是神,那团长就是神的boss。
' E: o1 s+ Y' t1 Q) a6 r
哈 不敢當,我只是個平凡人,3 \7 I. q) v$ N, d
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
6 H, r, {. l5 u3 DZYH
! s# r' p3 u1 HQQ:414734306% P- E( a2 H7 o" Y0 t9 D# c. J
Mail:zyh-01@126.com# g# s+ Q; D) @! a: ?

' J# M% z# U2 b, N0 _- S他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 - B  d0 I# x7 w3 w
再次对团长大人和悠悠哥的无私帮助表示感谢~~
  q' E- X8 [+ }6 k3 h8 Z
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-27 04:13 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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