EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。/ h. c% ~7 s$ i1 r' }
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( D$ x. t+ v! K
这里有相应的模拟器源码,就当送给大侠了~~
- M! w) [8 L7 b! x, Lhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% ^" x  ^9 j2 l6 l7 f! x, @! z/ Z能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. ~+ C9 R2 t/ }) Q楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
2 L: p2 S) m- M3 a% E+ T这里有相应的模拟器源码,就当送给大侠 ...
& I& y9 X% T. Y' r0 A* N
聲音部分(Audoi Process Unit = APU):
' c1 C/ U8 _* J) U9 Q1 K.\NES\APU.cpp2 x$ N, \+ {3 S
.\NES\APU.h
9 p0 B. O2 |3 D& k2 t+ a$ j8 h2 g) ]6 P$ X
! O# v7 e" l& R  [
影像處理部份(Picture Processing Unit = PPU):9 d" \: Z: j+ q  ?
.\NES\PPU.cpp5 V+ M+ Z# H! b3 a& f, Y  p: U
.\NES\PPU.h$ x8 E/ s5 d7 K" H  O

$ U( i; E8 s* @6 V5 G5 R( }7 }如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" K. Z% V# O8 R3 L2 O4 w/ v, A: d. m
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
  X* }: K3 P6 ~3 q; \6 [' D  s8 R(由于很多专用术语和算法机理都不明白,所以看不大懂……); z3 r6 b2 W4 E2 W0 z; Y3 X; x
//////////////////////////////////////////////////////////////////////////9 K8 A9 I1 r0 E+ v2 K- t6 k7 J- G
//                                                                      //
" M4 ]3 z1 p/ g6 F  P5 |//      NES APU core                                                    //$ f6 ^$ I0 d) G8 d1 `5 I
//                                                           Norix      //
, B2 Y- b3 ^; g: A5 |//                                               written     2002/06/27 //& L! q0 ], `% ]
//                                               last modify ----/--/-- //
' m$ V% x9 ~' U4 L  r* U. p9 I//////////////////////////////////////////////////////////////////////////+ h/ m8 [; b2 E1 p( i9 e' V
#include "DebugOut.h"
) B0 f. ~5 y1 @. H8 K#include "App.h"" |- F+ U5 b" V( h1 p; O
#include "Config.h"
" l4 _# `! c: V$ Q5 u- }$ V4 S/ e  ^; v1 G% W: J9 J
#include "nes.h"% p4 o3 s0 [, p5 p
#include "mmu.h"7 G9 B+ I8 \. c5 n4 G
#include "cpu.h"! u  G1 i& ?2 h# l
#include "ppu.h"! S; P( }2 q8 ~1 V+ A
#include "rom.h"# T5 F0 K" f1 b! m% a
#include "apu.h"
; L& s. n* U) W! J$ u
% N2 h$ G5 n4 P" d8 t: M1 g// Volume adjust
" l2 o# o7 h5 R" o8 N) B8 T// Internal sounds3 ~8 i6 J' {3 ?- N
#define        RECTANGLE_VOL        (0x0F0)& `- k. `: ?) ~* T9 o2 P
#define        TRIANGLE_VOL        (0x130)8 q# F4 n  l; p+ c6 l
#define        NOISE_VOL        (0x0C0)8 H% Z2 l: q. c8 o
#define        DPCM_VOL        (0x0F0)
- m, Q$ ^" F" r/ H( ^8 E+ l// Extra sounds
, `  J0 f7 d+ i  Y0 J2 i7 B#define        VRC6_VOL        (0x0F0)
+ N' c2 C' N" |- Q' i#define        VRC7_VOL        (0x130)
; t1 b) L; X/ L/ E  j8 _/ ?1 z: ~# n#define        FDS_VOL                (0x0F0)0 ~5 a5 Z9 ~* }7 D& p4 z( k) V
#define        MMC5_VOL        (0x0F0)
( \" ]3 ?$ n) F3 I% h) z4 x* x#define        N106_VOL        (0x088)6 m: S* p; _3 s* ^( s
#define        FME7_VOL        (0x130)
! P  z7 S! D' d4 Y$ A" L, W( X: T; |0 ~- N: I+ O
APU::APU( NES* parent )3 Y  D, w. B: `0 n3 |0 ~6 m, A
{
9 f2 b5 W$ f% [4 ?        exsound_select = 0;/ z+ t+ P# Y, a/ v# w

2 q+ p5 h1 h/ x: e! X9 i  O        nes = parent;+ n# C- U5 E" g6 U2 n
        internal.SetParent( parent );
* h3 |! M/ |! }! Z6 L+ I8 X' q; {
" r2 X1 {. v4 W  [. e        last_data = last_diff = 0;
4 J5 p7 ^. ?+ ^$ h% T! D8 W  r! u: Y- C
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
$ R$ g/ q6 a2 U2 _" h) Q  T+ m' ~' l
' f- z4 C4 }5 s9 y" c$ Q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
/ @, Q* ~: K+ |/ x/ R7 n! U( g        ZEROMEMORY( &queue, sizeof(queue) );, ?7 M) f5 M$ h9 @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- T4 h; D3 }, E4 E6 V1 E- R# C1 n& F- Q+ [! |2 i" ^( Y) Q
        for( INT i = 0; i < 16; i++ ) {
' U  o+ |" P+ x+ d$ E                m_bMute = TRUE;
9 E% Z5 ^+ m& B+ a6 }; k        }
2 ]7 `1 R7 Q# @. W, Y$ L- E, f}
+ m& s3 R! S- ?. ~! k+ T* f5 {  k& C# U
APU::~APU()
* m& t3 j3 z8 F( D, L{3 [3 X) u% L% G$ n  j7 n
}( h2 {! \6 E' D- ?1 q# `. I

! A$ G5 V3 S3 z4 |void        APU::SetQueue( INT writetime, WORD addr, BYTE data )7 j/ A4 x7 a. Z$ x
{; `) b' X6 \. W0 ^; j9 k& J* `
        queue.data[queue.wrptr].time = writetime;2 O  x0 M9 ~- E4 R2 Q0 a
        queue.data[queue.wrptr].addr = addr;5 v* J; R9 J+ j7 ?/ G& L2 x
        queue.data[queue.wrptr].data = data;+ N( l9 @3 v$ B, @  }/ I$ j
        queue.wrptr++;
5 u  K0 E; v, Z* T1 K7 u  a3 @        queue.wrptr&=QUEUE_LENGTH-1;
4 F! y" T2 g9 ]. M0 G: A$ Z        if( queue.wrptr == queue.rdptr ) {
% f% I* S. {1 V" b6 K, E                DEBUGOUT( "queue overflow.\n" );# \; [1 j& N; l" [/ h
        }
; K, w8 R3 x& K+ c% ?}6 _' O0 c' I/ [9 w

# I; K$ G6 ?: `" N0 s7 q0 \2 jBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
2 R6 \1 G# k/ m4 W+ A{
5 G! G: o+ C1 R9 w/ T$ K1 n: F( \        if( queue.wrptr == queue.rdptr ) {
* O' C6 Z' L; E+ w* q" L% Y4 {4 `( u                return        FALSE;
) S7 M- n+ c9 O: o- }$ z3 u        }
, E! _  a4 w( g+ r        if( queue.data[queue.rdptr].time <= writetime ) {+ y1 k/ D1 l! l$ f8 \
                ret = queue.data[queue.rdptr];
7 I, f, m( H' o* D- C& m                queue.rdptr++;
) X) B1 B/ k7 n                queue.rdptr&=QUEUE_LENGTH-1;8 W6 H: b3 y* n
                return        TRUE;
4 y( t* s8 D! L& h: [        }
0 D5 w. ~3 [7 z9 z+ h3 ?0 S" k7 B        return        FALSE;
5 N( d, I6 _* c}
: R# z& A# U4 f2 k/ U6 e) X0 D" |5 \; K$ g
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ), m/ E/ j0 ]+ ^* |. D1 ]" F
{( C: s/ `! \0 N9 g7 x
        exqueue.data[exqueue.wrptr].time = writetime;2 p0 Q9 N/ r9 t: T
        exqueue.data[exqueue.wrptr].addr = addr;1 W$ _- T$ F3 E" U- r
        exqueue.data[exqueue.wrptr].data = data;" v1 x( E% G( |# U9 k: Y2 [0 H
        exqueue.wrptr++;
+ F- g) d2 U0 @) J- [8 F; u1 W# \9 s        exqueue.wrptr&=QUEUE_LENGTH-1;
; h7 I; y- V3 n* g        if( exqueue.wrptr == exqueue.rdptr ) {- ^- u7 I* k: g- q9 |7 w2 j6 h
                DEBUGOUT( "exqueue overflow.\n" );: a  H, Q6 A: |2 W9 c
        }
8 @8 g! Z/ ~% m! ^  U8 C}; R$ h! @1 D6 D/ n- }
" q9 b& j! e9 W8 r+ J( E: o" R+ b
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )$ n! E& O5 a" u) D! L3 E
{
  {& T. |/ N7 j8 y; K1 S+ ]6 [        if( exqueue.wrptr == exqueue.rdptr ) {
# ~$ B. ]; l( H" Z                return        FALSE;
7 @* `- p8 ?6 [# E7 c        }
& M$ t* n' }" f6 X1 @8 k        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ I/ Q% W* Y0 v3 S/ z  Q9 p3 d1 \
                ret = exqueue.data[exqueue.rdptr];
; V" n, n5 U& q) D7 V% r                exqueue.rdptr++;
' r/ x  S8 [/ G' G6 V  J                exqueue.rdptr&=QUEUE_LENGTH-1;/ v. d/ f1 d/ r& M' K' z
                return        TRUE;
- t, u+ T, e7 u/ E5 N% k1 \        }0 ~) s% w% j% a# L7 B) Y( A# G
        return        FALSE;$ D* z3 u4 j# F# p& \$ O
}
- @8 |/ J8 E8 F2 ], C+ o$ f9 ?% B* I4 B7 f$ Q7 Z1 h( ?
void        APU::QueueClear()) J, g: c; ]! l
{/ h3 `, W8 V9 _! {2 R, b9 m
        ZEROMEMORY( &queue, sizeof(queue) );- Z, h# S) ~; q9 u0 y/ K
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  R* o8 |8 y1 \. r}
' v% c5 u/ V2 W5 X0 X9 P2 e. Z6 o
1 j- c" ]8 O, t6 q7 mvoid        APU::QueueFlush()
" B5 ]! x! n" _7 `9 U- L8 \{- Z& W) E6 n" }5 R( U$ O7 O% W5 z
        while( queue.wrptr != queue.rdptr ) {1 |% u6 a7 u% b- k1 p) x+ W1 {
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );. K" P1 E" b, [. ?7 k7 \6 k3 }
                queue.rdptr++;9 L( ~& k3 V% u0 \0 q+ y. J
                queue.rdptr&=QUEUE_LENGTH-1;, Z4 Z& u9 w! z5 V$ G
        }
" X, t0 j% b6 }' ?+ m+ {# c9 r% r& x$ ^9 C: {
        while( exqueue.wrptr != exqueue.rdptr ) {
' i: I& ]7 }' K; M' e5 @* q1 ?. u: O                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% m  P) [8 I; g" u+ R3 p( a% `
                exqueue.rdptr++;2 w8 [4 L/ _- ?
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 K, U; _% {3 D0 }3 m. G        }# I- Q* J! o2 B0 m
}" T: @, |4 `  L% G3 n
8 T- U8 c+ _( t1 W" I
void        APU::SoundSetup()
" t4 C2 z* \" l3 ?4 Q{  ]8 Y) H5 h2 b$ h
        FLOAT        fClock = nes->nescfg->CpuClock;2 X: e- P) `/ \% V8 m# }
        INT        nRate = (INT)Config.sound.nRate;
# s0 K* b: z( s$ W6 Q+ G. `2 \, t        internal.Setup( fClock, nRate );- O; g1 L+ A' W9 e# o
        vrc6.Setup( fClock, nRate );
+ z( J8 B% a# N# j/ L& P& M  e        vrc7.Setup( fClock, nRate );) T" W/ D' q( E; S: q( K7 k
        mmc5.Setup( fClock, nRate );' J1 |' }$ ^2 j4 o
        fds.Setup ( fClock, nRate );6 _5 t) c; O% F) q/ Z& [
        n106.Setup( fClock, nRate );
' q( Y7 S9 n+ r        fme7.Setup( fClock, nRate );
: D5 z% H/ G4 E$ i9 I3 M}
. v% T* d+ d0 m6 W# N+ w" G- U( J6 l6 a: |. m) G
void        APU::Reset()0 m, r% l6 g# I4 ^
{# U) c+ z& _; _& F! d% x6 p* L
        ZEROMEMORY( &queue, sizeof(queue) );
! w: ^  b4 e! j) }) s8 T$ K        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 G. e4 S# ]6 }1 C
( z2 N' ]: r& ?. J/ B
        elapsed_time = 0;
7 i' b+ j# y1 B; X  u1 L9 D& o# }3 e' j6 H
        FLOAT        fClock = nes->nescfg->CpuClock;% _3 b/ Y0 x# W- e5 Z; I
        INT        nRate = (INT)Config.sound.nRate;0 h( ]0 v$ W; C0 Y6 w
        internal.Reset( fClock, nRate );
6 g3 y1 b3 Q# P( h# [# x, I. ?        vrc6.Reset( fClock, nRate );8 F; ~" v( P, ?: a
        vrc7.Reset( fClock, nRate );
4 y; D$ C( V% X$ i' j) W" h        mmc5.Reset( fClock, nRate );: E+ h7 J$ X' I& V* {0 S& D
        fds.Reset ( fClock, nRate );( S! k; M$ ^% J* X- f* d' a3 s
        n106.Reset( fClock, nRate );
8 J; o6 O/ N# Y5 t        fme7.Reset( fClock, nRate );7 D2 h, ^2 i- ~$ o

+ ^) J6 x4 q! Z% U" \        SoundSetup();
7 V+ s/ m- ~$ n# _1 p8 o% J}
0 k# Q# R6 t+ ]( k2 n! t
( _/ j- b0 t5 D$ V- mvoid        APU::SelectExSound( BYTE data )  V1 {- d3 A& K! K7 Q
{
# J5 C$ u1 P% i* h/ e        exsound_select = data;+ t! o* t' d7 S' }5 x
}0 A* g2 a. e' g& [& Q

  ~$ d4 b4 W! V$ k) D+ |; O9 X( zBYTE        APU::Read( WORD addr )- X, P) B; A* u9 G; i
{$ e3 V9 r3 Z# ~% Y* U: u
        return        internal.SyncRead( addr );, S# q1 L; a5 K* b" U' f5 ^
}0 b1 L/ e" e! d; h
1 \' }4 K9 E1 {
void        APU::Write( WORD addr, BYTE data )
" l5 C' b8 @8 U+ \8 h# N( P1 }( r. N{8 g0 s, a% g+ Y, x7 _
        // $4018偼VirtuaNES屌桳億乕僩7 g; Y; E( L  S9 ?8 G, p1 W
        if( addr >= 0x4000 && addr <= 0x401F ) {% `* ]# {+ Q8 D- n# g
                internal.SyncWrite( addr, data );
7 @' P' V9 E4 _                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 P2 B. w9 {, d8 U& E6 y+ H4 R
        }3 X+ O& n% m  A- B5 r. |4 ^
}
" K3 m6 h% E; g( ~* ^
' Y4 }5 ~- l. r. T* a2 t1 F! I5 Y. aBYTE        APU::ExRead( WORD addr )
1 M' w( R& L, v) Q, Y+ k{. S1 [8 ~% `5 q# B9 z1 F; M
BYTE        data = 0;0 C; U0 [  e% O! X) v

8 G5 D9 o" y( I$ ~3 J        if( exsound_select & 0x10 ) {
1 Q+ W  n+ F, Q8 W: f                if( addr == 0x4800 ) {
" j' t+ E6 l! h                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 ^. l+ O' L; s- \; x2 M
                }0 L; n1 ?) \, d* M- J
        }& d# e) r2 Z, h. Q3 C0 H) _
        if( exsound_select & 0x04 ) {4 F# H# u( r4 Y" B' ~
                if( addr >= 0x4040 && addr < 0x4100 ) {
' Y5 _8 @3 i. D% H$ j+ j! ?                        data = fds.SyncRead( addr );/ \+ f6 ?7 o1 o: E& @- J& }
                }7 g& k8 T- {6 |9 [' b$ M
        }
" b/ }4 K# f5 Q* k3 G        if( exsound_select & 0x08 ) {, D' Q% ?" z) h+ u
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, V# e" x6 P. `/ V! |& V. s1 o& E                        data = mmc5.SyncRead( addr );% ~& j& u4 ?7 a( e  ^. F4 @
                }/ `- |5 ?! h/ T5 A' m
        }
1 ?  h$ ?+ O: N+ P) _5 I! M0 L9 J7 e  b# n' m
        return        data;
! o, a8 ]$ T" h. L4 w- R+ g}6 q  m  V# _2 x0 h
5 \6 Z7 T4 i" X' m
void        APU::ExWrite( WORD addr, BYTE data )+ F1 h# g+ A" U7 t$ {4 j1 t
{
5 A/ b* j( }( x8 K3 F4 ^- r0 L        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
5 U+ ~' f* I5 M4 _! ~( _! N$ G! J2 g* _3 x9 M! ^# i
        if( exsound_select & 0x04 ) {
" Q: k8 A, B2 h5 r* u4 |                if( addr >= 0x4040 && addr < 0x4100 ) {
6 ~! h0 ?8 c6 j+ O7 m2 `                        fds.SyncWrite( addr, data );6 v! j  \* Q* D' w. w7 T$ V5 C
                }- I, e) L4 ?; J( E# E" R1 d
        }
! P+ L, T; n# j5 u2 v# V# F+ l: L$ p# g, f; l+ k' j
        if( exsound_select & 0x08 ) {
2 i2 W( v$ `5 K% G9 G0 x                if( addr >= 0x5000 && addr <= 0x5015 ) {# G( M& M- h5 W5 ?/ W* x! A7 y; N
                        mmc5.SyncWrite( addr, data );
, o0 }1 i+ p, G9 b- A: ]                }
4 S! P1 b3 N9 F/ l        }
: P8 n7 U1 T" }% V1 u' V}! B& L# e: m- N! [# ?8 {

* M& j4 r( {2 i9 a' xvoid        APU::Sync()# U  |2 T6 [3 l4 U) u/ P0 b8 ~' W
{
4 [3 Y9 H4 O* E/ I1 \, e}1 {* p- M; u$ t/ Y1 S4 X3 ]! j
7 a5 Z! V/ k# \. ^1 b; n/ i
void        APU::SyncDPCM( INT cycles ). I% q) C9 J" x! m! B
{
" e3 N# s8 U  p0 y+ s        internal.Sync( cycles );
- D& J- W; _) E
8 l  V1 M4 o! W        if( exsound_select & 0x04 ) {" h  D: w# m( G& W
                fds.Sync( cycles );
- `- k& g5 Z* E# L        }; u" o' F/ ?, }3 P# k, j
        if( exsound_select & 0x08 ) {! [5 n- \2 H; P4 M
                mmc5.Sync( cycles );
# ^8 ]" X# \8 q# ?. W7 X        }
1 L' b$ Y" v  _* O7 i! s}- b  ~* U) M  w  o, ^2 r0 {6 s

, D, e! A; D4 Uvoid        APU::WriteProcess( WORD addr, BYTE data )
7 b7 O3 v' T& B' S4 \{
, K) d3 h0 \5 I        // $4018偼VirtuaNES屌桳億乕僩9 b' @0 e0 j+ S+ Z" f) V
        if( addr >= 0x4000 && addr <= 0x401F ) {
: G2 u  ]% C% @9 ^4 _- i8 H                internal.Write( addr, data );0 h7 P* x/ [& i6 h6 \, m  a, _: u
        }# ]6 Q. x1 z1 r* {
}
* ^; }0 k. m6 x4 O5 {0 ^; L, L0 P* G3 ~, j2 c$ y+ e- a. \
void        APU::WriteExProcess( WORD addr, BYTE data )
7 f3 W/ _- w4 a# g  A$ X{& U3 ~( p7 u+ U1 b
        if( exsound_select & 0x01 ) {
. w# s- ~0 W8 q+ l/ U1 z) J                vrc6.Write( addr, data );
+ r& H2 o- V$ y1 ^        }
! q5 T$ C( V3 D5 \7 g0 Y3 `; A        if( exsound_select & 0x02 ) {. i. S0 h" c1 L! n0 n8 B" w# O3 P0 K
                vrc7.Write( addr, data );2 \/ o9 G+ ?& p, P. W/ q6 h
        }6 c' z  \7 L  f! ^) \$ C5 W6 k7 t
        if( exsound_select & 0x04 ) {
' r- h1 V( O( J; P0 m6 ?2 m                fds.Write( addr, data );% K" E- \3 ]' F0 @
        }
) p/ f+ F) f. Y- |" k        if( exsound_select & 0x08 ) {
8 B7 ?8 T6 I7 u/ C1 u* n7 O                mmc5.Write( addr, data );
1 _5 Y  j" [; m, b        }9 i% e) G4 {+ ]9 J" m' g3 t
        if( exsound_select & 0x10 ) {9 |# l( m8 k$ d: N+ f: C
                if( addr == 0x0000 ) {
. A5 D6 u9 y% _6 u1 R, x6 S                        BYTE        dummy = n106.Read( addr );
9 f$ O8 E& f/ [7 X" q+ H. |                } else {
% u& m3 e2 y4 Y9 M                        n106.Write( addr, data );, r7 l8 }1 ^6 Q3 {' J2 h
                }
2 ~; A2 F) e3 o: i) D4 j- |- d  o, Z        }+ u7 a( E* [2 F
        if( exsound_select & 0x20 ) {
( Z8 J. x8 d) ~$ @) N8 v                fme7.Write( addr, data );/ u8 \* t; l# b8 ?; C
        }: H& p6 ]5 f. Q. j, `" i
}3 S* q' f+ `5 P$ u

" t1 z* J: ]  |8 Gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 E, E5 _" b# W5 a) q- I5 n, z, v{
2 W5 K8 M6 a6 N) G, aINT        nBits = Config.sound.nBits;
. l0 K4 ?/ T. V) r" DDWORD        dwLength = dwSize / (nBits/8);. R7 }: G  f+ v5 O: k; l
INT        output;  [5 [# Q# p5 U8 w
QUEUEDATA q;
7 s! z! \: j9 r+ m. e8 ^7 PDWORD        writetime;
+ t/ g% n+ h/ C" M( [( n: s% s, J0 P' t) i0 ?
LPSHORT        pSoundBuf = m_SoundBuffer;7 M2 r: B- T5 ]% J- l# w7 E
INT        nCcount = 0;9 c5 K7 ]3 D! x7 Y

( V* i8 j: D+ V1 V3 vINT        nFilterType = Config.sound.nFilterType;6 }7 @& j5 R' K7 t& i

8 j/ `3 ^6 D# o% f1 B$ i        if( !Config.sound.bEnable ) {
4 B+ i" e( P9 [  |" n6 g                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
; O& _. a& s6 ^% C+ `2 V: z                return;" Q# |9 `8 _  M! e' `7 Q
        }1 b) H: n2 k, }$ V" b
* p4 _8 k  ]! I, u
        // Volume setup
& @6 Q+ e/ s/ C# u/ u" R; e        //  0:Master
+ q+ S/ A( k5 J4 Q        //  1:Rectangle 1# N  c+ Q5 _7 y$ I4 e
        //  2:Rectangle 2$ l$ q0 ?5 L* J  H) j" u/ d% C& A
        //  3:Triangle+ Y# c& D3 K$ N9 O* y) [4 G
        //  4:Noise
' Y. e) N1 w" R4 t% v& W: [        //  5:DPCM
0 Q5 S# d1 q+ `6 }& y        //  6:VRC6* t8 ]/ d4 t/ W" ~) V7 C- R
        //  7:VRC7! W4 H- ^3 l4 f% V8 e: B8 M" ^
        //  8:FDS1 B  o* u7 \" r0 R0 w
        //  9:MMC5* E2 t* S- H1 l9 V  n3 k
        // 10:N106
* D. a) s/ b: _! z* C: |' m( n        // 11:FME7
' `% b  [! A+ k( [        INT        vol[24];: R8 f, T- L  ]& ?+ x  z, U, u9 k
        BOOL*        bMute = m_bMute;
5 T1 l2 o5 ^; ~# k6 s$ c; q        SHORT*        nVolume = Config.sound.nVolume;
; I$ M; i7 \( \1 j+ }, i4 Y" D' h" A8 R+ d' F0 t
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; W4 l& h2 M' e3 l$ f6 o
7 z( Y! k" {$ r) R0 N9 u0 O) t
        // Internal
6 v/ D# M2 \" R- Q7 z$ {+ R+ T- l2 @        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;7 ?$ a5 v) f  ~
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ h; [) N' R# w% b: X        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
) ~( U; R: ^8 q; p- s        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;) m8 E& h/ k$ O7 ]
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
/ ?1 @4 o# @% m$ C+ x: A: b2 p/ t, `" c' @
        // VRC6/ T# A$ Z% `  L' l1 h  ^! s% y
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 n. T. L. L  Y! i" p" m
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 g2 V! y# M- A        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% z4 p9 Y: y7 \% }/ I

  |6 `* {5 B) G; p& o* G  G        // VRC78 ~" c5 G5 ~0 h* z: O, i( {
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* T, |0 |* W* c$ C6 |5 ]( L/ D
. G) A  {: v$ g" P" M; S# O- H        // FDS
  E9 b: F. {8 [1 [        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
. F( Z0 N4 y- q
$ _- W- a2 Z; H/ U' |        // MMC58 D  r: D9 H6 U
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( u6 T; C" O5 a$ @3 s+ T. Z
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ C& O2 f( x- }" u5 g& d  k# Q& l
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 R% K5 P% E! j3 g# i1 F3 [, K& z
6 S- z( c, a8 q# E4 k7 ]$ n        // N106! S. [/ O& s* t# i
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 ?; t2 x1 ?4 [- A, E- q
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: n! [% D8 r9 @7 g3 m        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ b9 V. @, y; ]$ n( w2 V
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 {! X$ o6 X0 W5 {5 ~' h9 W( Z/ Z
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ r/ F4 C/ D& _! F+ `
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) F6 w" v: e7 }0 {, ?        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' X& b$ C  k6 v& y8 d
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 l( ^# J+ p3 b/ r, X
( ^8 B0 X* D$ [) K: O5 W6 m# |+ r
        // FME7; w* Z4 X9 l+ K7 c9 H! h
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 V% k1 z" m) Q- s        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; A' _; x* K; c7 y2 i
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ k8 ]9 q8 q1 L2 F; B2 c- ~' B
2 Q8 D3 ~9 a' N1 f# ]/ o" A5 H//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ J+ p: X8 b# ^, t' ^' k4 E5 {        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) k( y7 x8 c8 R; ^
+ z  K+ ^( K8 w        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
0 t: \- G5 s% w1 C3 A5 b0 [        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
8 }' S9 ?" {8 ^& H* z                QueueFlush();
, h+ Z2 l) A+ _        }
% g! C; B0 S$ v/ R( H! H, a) v# V! G6 n
        while( dwLength-- ) {% ~, M3 y; E  G& r; j; _2 F
                writetime = (DWORD)elapsed_time;
7 o* H& U* Y) Q& i  i
2 M  f+ q: l7 M! q- s$ o                while( GetQueue( writetime, q ) ) {- s2 f* F! N8 Y; n2 w$ v
                        WriteProcess( q.addr, q.data );
4 N0 h# {: o' W+ n+ X! [7 V                }
& y' x7 [- X- F5 _( r8 Y7 \
0 H0 [9 a! K% H5 q- H/ {                while( GetExQueue( writetime, q ) ) {& E! |* I) u5 S- O' w
                        WriteExProcess( q.addr, q.data );! v! |9 v8 k0 x
                }
% B8 P7 g! r% u2 b! E( ^, V, S. s: ?# c" f5 M5 [) S
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# J2 e. Y$ v' m6 [
                output = 0;9 J: k1 `4 Y$ C$ o
                output += internal.Process( 0 )*vol[0];
( D$ A! n7 m8 f2 V3 G0 W5 i                output += internal.Process( 1 )*vol[1];
) i" [  R* N, N& f                output += internal.Process( 2 )*vol[2];9 G& a( c2 K2 o8 Y
                output += internal.Process( 3 )*vol[3];
8 }6 ?9 G$ N- U0 \# |$ |* ]9 ^                output += internal.Process( 4 )*vol[4];
/ X0 W( F5 I7 z2 j2 l" F0 N( a# F& U$ C0 m8 l+ b6 d
                if( exsound_select & 0x01 ) {
' j3 l/ _# T8 }" o                        output += vrc6.Process( 0 )*vol[5];
+ i+ l5 l  d0 D- D$ N                        output += vrc6.Process( 1 )*vol[6];% z2 p7 w7 v! Q1 X, L6 T
                        output += vrc6.Process( 2 )*vol[7];/ s' J; E9 x: q" P
                }
# h7 E0 w3 W/ g# L# l: C                if( exsound_select & 0x02 ) {
' C& a- q' P: l                        output += vrc7.Process( 0 )*vol[8];
( M6 m: L5 Q5 r4 f& T, P  ]                }. X  |; Q" y- G- ^5 ^8 g6 |+ S
                if( exsound_select & 0x04 ) {2 g' ]6 [& B& V6 x: t3 s! L/ }
                        output += fds.Process( 0 )*vol[9];/ d/ h+ D' S7 d. }4 }9 W
                }' }( Y5 q9 o0 z9 f9 B2 _8 m
                if( exsound_select & 0x08 ) {6 r+ `( C- X+ e
                        output += mmc5.Process( 0 )*vol[10];
5 t& L0 p. G( z* d6 ~                        output += mmc5.Process( 1 )*vol[11];
0 `/ k, z2 J$ j! a; `8 R  e% B7 h9 y                        output += mmc5.Process( 2 )*vol[12];
' [1 p7 A4 q' r8 l, A                }
7 D5 h7 n% ]0 @0 v. B  r+ F  z                if( exsound_select & 0x10 ) {9 y" j" B  C  A) M8 l
                        output += n106.Process( 0 )*vol[13];
7 Z+ u! j) e: _0 K                        output += n106.Process( 1 )*vol[14];8 |6 k) {5 b% ~3 h; E  f4 N
                        output += n106.Process( 2 )*vol[15];
1 D9 v5 y; ?% p: r  R* s5 I5 X                        output += n106.Process( 3 )*vol[16];
# E2 b$ d" }$ L                        output += n106.Process( 4 )*vol[17];
$ M. `8 V# W, F2 B' M, x                        output += n106.Process( 5 )*vol[18];% q" }, _  a! M( t( E
                        output += n106.Process( 6 )*vol[19];# d8 p0 c+ F0 s8 u7 d
                        output += n106.Process( 7 )*vol[20];$ s6 J1 _. t! p( L1 M
                }
3 q+ T2 G* l2 T. i# |: V                if( exsound_select & 0x20 ) {5 Q+ m7 L$ f- _( F- V) V9 r  o
                        fme7.Process( 3 );        // Envelope & Noise- @3 z5 d& X$ w0 l5 @2 i  @/ F
                        output += fme7.Process( 0 )*vol[21];
6 b$ I) q  n, y) |                        output += fme7.Process( 1 )*vol[22];
0 I3 d- S$ O7 e7 W: O6 b                        output += fme7.Process( 2 )*vol[23];
  Q+ ?1 O+ ]5 s. ?; s; p                }
) b7 U" R& ~& Z+ C; t  t
. k& [- ]2 J! Z# u8 q) i; o9 Q# D                output >>= 8;: i& F. l6 \4 B5 E4 Y
; Z5 u! p1 ^& P  O; B
                if( nFilterType == 1 ) {
  ?; O, l8 v. f1 g3 J                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
! d0 f" {( W# y                        output = (lowpass_filter[0]+output)/2;- G. q- m  _& z0 m, `
                        lowpass_filter[0] = output;. X  y, i6 E4 j- X. J0 g
                } else if( nFilterType == 2 ) {- t4 Y* P" v# H) e2 q  Z# P( ^( Q* K2 l
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
9 ?% d$ Y) R( L1 h0 W                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 s; k" \6 g# M2 U2 g7 c2 F
                        lowpass_filter[1] = lowpass_filter[0];
( ]  y9 i3 ^7 ^/ b. A4 N4 W                        lowpass_filter[0] = output;7 {) k# P/ A1 A2 L
                } else if( nFilterType == 3 ) {, ~! j. U9 x" K  l, M
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* u. c. q$ |, r" j9 m* {                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
3 k: Y% h  y, y5 b                        lowpass_filter[2] = lowpass_filter[1];
- m1 x' u% |( W/ F                        lowpass_filter[1] = lowpass_filter[0];6 R! M2 ]+ y  v+ w' K8 U2 M: s
                        lowpass_filter[0] = output;
9 D6 y& K  Y2 t- M! R                } else if( nFilterType == 4 ) {4 U0 V( @8 x5 E- C8 F
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)5 i: q0 Z; D6 b& a: z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
1 K7 S* \0 a( [, U5 o) |+ y& q                        lowpass_filter[1] = lowpass_filter[0];
& ]# j, r" q! B8 A3 K3 H$ G) l                        lowpass_filter[0] = output;
# n1 |8 |' A% d& P# c                }3 ~* v) i( _9 \! x

4 c& B- \( K4 m1 D* `#if        0
1 f! U3 Z: K! y( c; E                // DC惉暘偺僇僢僩
$ _9 t1 g9 \' [5 w$ v                {9 z; y1 r) Y" C7 x, g
                static double ave = 0.0, max=0.0, min=0.0;
! u; Q: k1 [+ \8 f9 w5 k1 G                double delta;4 _8 I1 \: B$ a4 N
                delta = (max-min)/32768.0;: F8 z* }% O) Y8 @
                max -= delta;6 }) v4 D$ t! J, j
                min += delta;
( \, r* j/ ~& o: f: B5 L  a2 _                if( output > max ) max = output;
1 ~' v2 b  }, Z3 |# F; c                if( output < min ) min = output;" t6 T8 X- g! R
                ave -= ave/1024.0;
/ t( X7 R& g% F& {, ~  E. z                ave += (max+min)/2048.0;: Z. M5 q# f: Q* H
                output -= (INT)ave;% h* k7 S' o+ j& h8 n9 g
                }
; @, u0 [/ w" ~6 p* {#endif1 J. @) f! @4 u( i9 Q- g, N* X
#if        19 A: R, j1 r1 c) u/ o
                // DC惉暘偺僇僢僩(HPF TEST). B% {" }0 ?3 n7 ~; j
                {/ V) }, o7 E$ }# M$ x4 r
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% w+ Q; ?' O/ G4 o( |6 H8 I
                static        double        cutofftemp = (2.0*3.141592653579*40.0);  V' Z5 R  @7 E* d9 D
                double        cutoff = cutofftemp/(double)Config.sound.nRate;8 H6 f" o$ P- v: o
                static        double        tmp = 0.0;
4 t( H/ M6 n" M7 r! G+ W                double        in, out;4 j$ R0 p! ]  P
% s' ~8 o: {/ [0 P8 |( Y& p+ n& N
                in = (double)output;
6 ]. J* E1 B, @% `                out = (in - tmp);
4 y8 `8 F8 U, i. l+ I. [% p2 T                tmp = tmp + cutoff * out;
7 {6 E2 j) ~9 o: _6 I
! p9 i- T; K7 m% o! m4 s+ e                output = (INT)out;
& V8 ~  |) |- X2 Q                }
$ t+ p- c5 @8 h- \#endif. {4 T1 \' h7 b! {3 |
#if        00 k9 L3 [5 |( x: O8 w% U+ d
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)0 U6 I6 J) i8 _1 w5 x
                {
) A: ?0 m2 g  r                INT        diff = abs(output-last_data);3 h* H2 F4 a5 J9 y' D: |* S- _* V
                if( diff > 0x4000 ) {% R! W6 K1 i1 D# ^0 q
                        output /= 4;! J1 ]1 M) R* c' j* s# [
                } else
" |$ l4 Y0 y9 Q/ F  i8 Y% q                if( diff > 0x3000 ) {. `0 Q% E% N0 T' F0 i/ x
                        output /= 3;4 f% G7 J0 }& a3 k7 Z" \( P
                } else
3 S- ?" a. H; N. ^& ~- H                if( diff > 0x2000 ) {' r: u$ Z$ \  n) E+ ]) g# \, S6 I- Q4 C
                        output /= 2;2 T& R/ S0 k  }0 p$ W
                }( L  `/ q$ O: f0 Q5 b+ A) r( K! ~$ L
                last_data = output;
% p# {$ `! L! f' B( I. k* I3 s                }8 M( i% F, D- I1 v1 z4 X# ~% @
#endif0 _$ ]& C2 ?. |5 `, ^
                // Limit
% [" f" I" o- i                if( output > 0x7FFF ) {0 y9 \/ _) |$ O2 ^* m1 S" ?
                        output = 0x7FFF;8 H  o- A6 s9 ~9 b
                } else if( output < -0x8000 ) {" V+ o0 W3 f; R* E4 N' Z  m8 M3 s" J
                        output = -0x8000;5 a8 l, G) P( p' `" q8 A' N
                }& X8 y* O: V) R

& q0 U0 C) n, ?$ m/ J4 a( ]! Z& ~6 C                if( nBits != 8 ) {
( P! `% `/ `+ z' w2 k                        *(SHORT*)lpBuffer = (SHORT)output;8 L! o! Q: t5 F; K4 M
                        lpBuffer += sizeof(SHORT);
2 n$ w$ c( m$ c2 ^                } else {
  E3 N6 c4 \$ r+ {- o2 x. S6 i. _                        *lpBuffer++ = (output>>8)^0x80;
7 D0 t& \: ]. d4 D                }
2 O6 Q. q% N" O7 @0 [4 G) H5 V) v. @6 S0 {. ]' x8 B8 V
                if( nCcount < 0x0100 )
. N" Q1 l; J7 l; x' i                        pSoundBuf[nCcount++] = (SHORT)output;
: X( R3 g7 z0 G8 i* Y5 q! u4 ~% K- [  A- p% c
//                elapsedtime += cycle_rate;
3 C$ @5 F7 Z7 k/ G4 Q                elapsed_time += cycle_rate;4 V" A, z2 m" x# n& v' [' |4 T
        }; B0 L/ V1 y. [- O( l& W% p6 Y3 u
* m+ T2 f! c3 x6 Y
#if        1, T& D8 {# h5 N* O5 r
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
: a2 O/ U/ N1 M, z& z+ w                elapsed_time = nes->cpu->GetTotalCycles();- j$ U1 {# H$ A/ `
        }
7 s5 K6 q5 @% n+ v/ @& f" [        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {8 q( V8 C  B. x) c7 `+ g, \! u6 c
                elapsed_time = nes->cpu->GetTotalCycles();
( e; Q: z) b- G! j        }
' t. I0 P) F& Q7 \) ], n( m#else+ v. l2 L6 z8 }  ?
        elapsed_time = nes->cpu->GetTotalCycles();% @' A- ]1 N# I& n2 n! n7 O
#endif" g% R: a* |& x6 i3 y
}( P; H9 r: A- g/ u, x& c

' C; @0 v9 }7 j7 _' E# f' `// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
* X3 k# |: q8 |3 \7 p; n) ~0 a, nINT        APU::GetChannelFrequency( INT no )
+ ?2 p% }  \$ s{
. R' H/ t9 ~7 g5 }2 y' [7 c( g        if( !m_bMute[0] )
0 z1 `$ _3 s6 j0 f                return        0;
0 ^4 b* W1 y% b+ D- v& C0 j( d% d( j* m8 N( E
        // Internal
0 S7 m/ ]! \% X- }7 d        if( no < 5 ) {
/ [3 N& g" W% x5 _% ?7 Z                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 y. y$ B* Y* D: x# b        }% f" I9 h1 J/ f9 ?
        // VRC6$ `5 o  V, {5 x/ V! X' S& Z
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
0 z2 f# a8 m- z. i# J4 H, b# n                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;, H+ S3 R# n) ]0 L
        }! f9 ]/ O; [6 X
        // FDS1 L- Y; n3 X  P
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ j( e  B( u2 v. E1 E7 a/ T                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 u$ I8 J' R) R- {9 o3 T1 Z
        }
' S/ u+ E# R1 |0 D; l        // MMC5) ]1 c9 D% U% ?5 s, c
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, C# f3 p9 t% @% k                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 U" l, f2 D: Q' D
        }* h9 M: f5 ~  h
        // N106& I/ p1 g- \. c7 t( ?* }% |
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 ^  t5 Y* k, b$ N4 g                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
( Y3 X& A+ D: y7 k        }
! N$ r: }# x% w  H2 N2 M, A        // FME7
8 ~: o) R* R$ {        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 ]6 a) ?% k) s  A                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;( n6 t7 S) v8 a: U+ A1 r
        }
- ?. H1 M8 s! _9 O; e' a        // VRC72 d2 F, l9 B/ ?7 ?2 o& k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {  \  R9 m5 G9 ^! C
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;: }, n0 M5 g! y2 G5 Y/ e' \
        }
2 m0 l7 u7 N5 W' V        return        0;& B$ M! @. N5 y7 t# f" ~
}7 ~  t6 T& |. D9 {* ~( W$ W
" C6 V0 t5 M; j' A
// State Save/Load
# P! |* `- h$ l; yvoid        APU::SaveState( LPBYTE p )
; {) X% i  I9 `5 d3 Y2 \{' y* P( A0 ?  a, z
#ifdef        _DEBUG7 r" P4 F* c5 ]
LPBYTE        pold = p;
& q3 }! \* a' k& G% z( {#endif
9 A9 j! x+ F2 d5 b* ~/ A6 c) `3 t3 @1 h0 W& W2 o
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞! N- o; w, x4 u+ ^3 Y5 M/ J
        QueueFlush();6 }# @3 r% a& W9 |0 E1 Q4 \
6 ]3 ~7 H+ V, N. I" R% f& @
        internal.SaveState( p );! Y$ D: n6 L' \4 x, }
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 y5 M3 z7 m' g
1 J6 e% |5 ^2 K2 ]- C4 E
        // VRC64 x, y- X' b$ C% R
        if( exsound_select & 0x01 ) {* ]+ G" R8 B. {& E/ V3 S' E' q
                vrc6.SaveState( p );
4 w1 Z9 v/ G. n6 c; d* w9 {: G' A                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) n! B; g5 j. N% b) X/ K% ^4 k) U
        }9 T. M7 t, [2 q! j; Q) y4 t, i/ R
        // VRC7 (not support)
9 r  }& J" \0 [) J        if( exsound_select & 0x02 ) {
$ s/ r7 W! m* M. K                vrc7.SaveState( p );3 e! e$ l4 }8 _& f/ K* [) s' B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, x% K( O1 h& X$ I# i! u9 t) a" |
        }
$ r" O! g$ H) x$ }  L- E$ b        // FDS
% a, u. m& B( ^  C  {+ c, o: m5 _/ R( S        if( exsound_select & 0x04 ) {& ]. U. w4 g8 r& ~1 `
                fds.SaveState( p );2 W$ I. j& C% M: B
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' t) ~" g+ a0 C1 o        }
) T; N( A5 I, N" B# v/ G: D! x        // MMC5
3 H% l7 F& y  v& d3 }) [  o, T        if( exsound_select & 0x08 ) {4 o% T, W! X6 z) ^! n3 N
                mmc5.SaveState( p );( B9 I, I) p: y8 r' W; I# Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 h  E& i. ~2 U2 g! |        }
% N# N6 O# y6 K/ K' a# [        // N1066 w% E; D! J' ?. b
        if( exsound_select & 0x10 ) {
7 W3 X1 z  v' v- J1 N1 n' T& Z                n106.SaveState( p );  B# z8 y- {9 m( i6 T/ O" v
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 \7 F( v% @1 m' h# A2 e
        }
2 C5 o/ r0 ~1 [% v8 s" X        // FME7
& u! J3 _% |8 G  C        if( exsound_select & 0x20 ) {6 f7 L. ?. X) V7 _5 g3 |; q
                fme7.SaveState( p );
' j6 C  |& C' c! l9 N7 e. `  d: J                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) j/ }- G# G0 s0 p4 D) }* Y        }
- U# x- O9 a. s  h6 e6 ?% I: C! L: L9 t, \' g: h3 p8 h: ]9 S1 \
#ifdef        _DEBUG
6 v: o, w; h, |4 q6 nDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );# O% r/ k+ `: B1 T
#endif
( Y2 z8 }8 J  I* l+ N1 Y8 W7 v}
# V) L9 M' G) H. b( s. ?, {
( x& ?2 ]: ~" E# A* I5 Q8 lvoid        APU::LoadState( LPBYTE p )
& J- {4 Z5 d: \{9 O2 j% i/ }1 Y4 d. }1 H4 i- f! Q
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡9 S1 c  `; Y$ y2 ^
        QueueClear();
0 E" F7 b* J  V5 n# E
4 x$ N5 K3 C5 F        internal.LoadState( p );
9 F3 x1 }9 p5 o+ l; w        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 _# }8 g3 l7 Z6 q6 L7 {. d! k+ N
* _2 i  B$ m* J
        // VRC67 s# t+ ~/ m/ F2 b) h" [
        if( exsound_select & 0x01 ) {+ H/ }. N# w! [% U2 y
                vrc6.LoadState( p );9 t5 ^8 `, K8 b9 g, ]
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, @- O6 a  @8 w( g, k        }
. {- j( O" _" D9 v$ A. i        // VRC7 (not support)5 z- O2 ~) ]: x
        if( exsound_select & 0x02 ) {
- ]8 D+ `) }4 p                vrc7.LoadState( p );
! e) b. `2 _/ J. ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( V& P8 S# E! y6 o6 e/ l, }. ^
        }, v  ^2 V8 J& P3 [4 h
        // FDS- }% E9 Z: \/ M; a7 B
        if( exsound_select & 0x04 ) {
6 W: X( b) n- p  `0 F5 W2 j                fds.LoadState( p );# r/ x) H0 |6 L/ M$ k3 d4 e, i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* m* L3 J8 u# ^/ i5 l6 {8 J
        }+ u, }3 _; h$ T8 R" M2 a5 j- I
        // MMC5: R$ q0 I! B/ W
        if( exsound_select & 0x08 ) {
. c: ^3 A: V' L- a- |$ B                mmc5.LoadState( p );
' D( `- r% O6 N4 H                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* C5 u" `8 k2 S' y        }
; l) I4 h7 x7 R: b$ i- e+ w        // N1067 n9 @" w3 A) u
        if( exsound_select & 0x10 ) {
2 p$ L, r9 }# n) m7 G                n106.LoadState( p );2 [; A+ t" N4 n; q& m% u: p- ^
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# o, O+ N9 t% v" X        }
% U- R& b; Y  X        // FME7$ h% \/ `9 n2 ]1 A  ?4 O/ k
        if( exsound_select & 0x20 ) {# P! [5 t. Y  S( Q" [3 v! r
                fme7.LoadState( p );7 R/ \7 T$ @8 I- e
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 V) y4 d) C- W
        }
4 D& L3 I' b: s6 L: B}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 9 x6 I8 x9 w% e% j& \2 c( H, R% j* m$ @
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
; j* Z  D! f8 [0 Y- o/ E' m感激不尽~~
2 r# @  g- o" y
恩 我對模擬器不是很有研究,2 s% D4 u2 p9 e, f
雖然要了解源碼內容,可能不是很困難,
9 o0 f, M2 h  n不過還是要花時間,個人目前蠻忙碌的。* Z3 w1 t  w+ g- }$ u( Z

5 b- N- j2 ~* L; \" H給你一個朋友的MSN,你可以跟他討論看看,: M4 Y, t5 F! C" h, D
他本身是程式設計師,也對FC模擬器很有興趣。7 J0 P+ v& c- n

0 {& c- K# f5 w* h( X% L% tMSN我就PM到你的信箱了。, Y& S  r' Z8 u: y

2 C7 r, M2 a% R/ P3 k4 z- O( D& C. D希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ; \) t) n9 h3 L/ W: s
呵…… 谢过团长大人~~

2 H$ L# A: g& `4 w+ _2 T$ O) w" ~: k0 Y# a+ g+ p( t4 J
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! C. i. F1 l  |4 l团长的朋友都是神,那团长就是神的boss。

0 B6 s" E0 P+ l+ n5 S9 F( H, T哈 不敢當,我只是個平凡人,
) H1 C+ W8 @. H) L要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙. y- j$ T9 K. \9 ?& D% I- u
ZYH
% e& y! C/ ?2 j' [/ YQQ:414734306% L0 _: J1 X) j1 k- F* Z
Mail:zyh-01@126.com
4 Z% J6 f" ]1 H- e
: x& j6 z! |/ V' Y8 Y8 t! E  i他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 M* e0 A2 [) q5 x7 l3 Z
再次对团长大人和悠悠哥的无私帮助表示感谢~~
  r# P6 j( e% E8 {& L9 g! W
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-3 22:49 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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