EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。) T/ b1 C: T1 C
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( u" f3 J1 K1 g' n: M  ?这里有相应的模拟器源码,就当送给大侠了~~/ o$ a8 b$ n. d- m% L' d; Y
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 8 `# J: z1 s- @. z
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 R& s- e$ B/ l: F4 L
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* ]' `+ V$ Z6 A% _0 ^这里有相应的模拟器源码,就当送给大侠 ...
7 \: k- [/ h, [" d+ B- L/ a
聲音部分(Audoi Process Unit = APU):! i1 V! F3 Q- \, l( w" d4 @; g9 j
.\NES\APU.cpp1 W+ }; ?# ?" O6 f
.\NES\APU.h
3 |( ?* j) L8 D5 |. _  o! T: e' d' B5 Z2 ]* }" a5 h. R

" v* `  ]2 q' q* b影像處理部份(Picture Processing Unit = PPU):1 z) X9 x3 c" G
.\NES\PPU.cpp
7 J0 o3 M3 o3 `% d3 J" N4 w. y( G+ b.\NES\PPU.h2 D- h9 O, \, k! V: d0 H/ I7 B
- ^+ j. ]8 M8 r$ J" v
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
$ J* Q  g9 P/ T7 J(由于很多专用术语和算法机理都不明白,所以看不大懂……)
- D( K0 p% |) D" P//////////////////////////////////////////////////////////////////////////& W2 d& c3 U) N% p2 y
//                                                                      //
  i7 ]9 E7 h6 R# S( s//      NES APU core                                                    //
* d7 @% J4 E; j//                                                           Norix      //+ @$ K) H/ ~; n$ U) k
//                                               written     2002/06/27 //
3 M; X" Y. f% Y+ h//                                               last modify ----/--/-- //' T, F/ ~  O6 O; W
//////////////////////////////////////////////////////////////////////////& F8 O% b; R2 r+ |0 E5 ]/ _  ^
#include "DebugOut.h"7 h9 a: z$ }* }" M& j
#include "App.h"
* O: U, F* l8 u$ @! }9 l% D#include "Config.h"
& _. C" ~; O0 c& |# `0 N
+ g3 ^2 n- Y" I/ T4 h#include "nes.h"
& o" D9 K, m1 b2 W1 ?#include "mmu.h": q5 S, ?% y  O% N. L4 s
#include "cpu.h"
! R+ ^0 U8 A5 y  s#include "ppu.h"
% W3 b( J  J1 u- d5 E( Z6 l#include "rom.h"4 e+ z6 l6 ~5 B& f' v+ z
#include "apu.h"4 ?2 F$ k9 e! M+ S) C
: x5 O' B( U7 V1 o/ l( [
// Volume adjust1 ]6 O0 F/ z  H' n, f) S
// Internal sounds
! w) c3 X4 q9 Y  ?& E9 j+ ~& B#define        RECTANGLE_VOL        (0x0F0)' V  U4 P5 j  }: J& x
#define        TRIANGLE_VOL        (0x130)
% T3 L4 S& s+ Y" M: F. x; C#define        NOISE_VOL        (0x0C0)2 T* O- B6 r# b
#define        DPCM_VOL        (0x0F0)
! Z$ Q: l, m8 [1 z: A* G* W5 n// Extra sounds- z2 w  @" ~4 o5 j! j9 \8 x. B
#define        VRC6_VOL        (0x0F0)
* k! F% l0 b: G/ ~# s' a! `#define        VRC7_VOL        (0x130)
2 L1 m4 [& b% u#define        FDS_VOL                (0x0F0)& g3 J( b, ]4 c4 E& ~
#define        MMC5_VOL        (0x0F0)0 O" I* S1 b1 f; C& k
#define        N106_VOL        (0x088)
; @# D5 b: V9 Z% S1 k) H#define        FME7_VOL        (0x130)
' S+ a8 Q( C- B! [+ M
) e, k8 @( B2 K) J# f0 @APU::APU( NES* parent )5 ~8 C5 F" \7 _$ X' e6 T6 u
{/ t- Y! B: J5 t1 r- c2 ?/ \  Q0 K
        exsound_select = 0;! r5 }4 H% D6 \6 o
. _: `$ R: l* m8 L9 E; e
        nes = parent;# k& P3 Y% f$ `( ?  q7 v* v
        internal.SetParent( parent );1 i2 \6 ]" y$ Y" h+ U, m
% I1 G! k! `3 n4 n8 Z, H, W3 z" }
        last_data = last_diff = 0;! T7 I% D" S! Z
& g; e$ F2 P" u4 H
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );+ u( _) s3 V) C* F2 ]3 C1 A
4 \5 N  y9 y8 ]4 n" a
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );! h' s4 {+ n! V! G
        ZEROMEMORY( &queue, sizeof(queue) );. s5 R2 K* _# [' F: }' e- j- X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% a2 x% B; G) u' c& F8 J+ t) s* M" _; A2 @
        for( INT i = 0; i < 16; i++ ) {) o; Y9 G/ {- i
                m_bMute = TRUE;
/ Y' G3 r5 V3 p" v2 O. ]# K        }
8 \0 \+ i' e" I% ~9 W, S/ G9 Y1 k}, B* }* z# c- y+ ]9 H( W4 b

/ C, ^' v" o1 }9 ?3 ZAPU::~APU()' N% c3 k( V4 O- `3 L2 K0 b' h/ j
{6 @  r5 W% o; V& o
}# y$ ?- e* c. A) K" x
0 H% f2 U8 G9 L6 n# |  Z" E4 _
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' h7 @8 X4 F; U{0 x& C1 {$ t0 w  o9 Q1 G& y- M
        queue.data[queue.wrptr].time = writetime;$ F4 H2 L7 l/ r- u5 O
        queue.data[queue.wrptr].addr = addr;
# N' B- A1 x2 r        queue.data[queue.wrptr].data = data;
1 |1 i: ?& p8 R9 Z: `& N        queue.wrptr++;
: ]% z( D* \5 O9 x1 t  Y9 P/ L        queue.wrptr&=QUEUE_LENGTH-1;6 u- n1 H0 |* ^
        if( queue.wrptr == queue.rdptr ) {' k4 j2 p' G- ^. d
                DEBUGOUT( "queue overflow.\n" );8 H+ R. I: {( G: @9 }
        }
' a# z3 ?, z0 ]! m+ `5 }4 L5 z5 y}
' b% w9 e  v% t) G+ H2 H- O4 T  ]- w' u: w
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )6 l2 R; [* M6 M
{- R% `+ f# V, A& I! F2 r# F
        if( queue.wrptr == queue.rdptr ) {
' a7 i/ X' d2 n+ s$ Y! r                return        FALSE;
$ Q. y8 |6 Q5 ~        }9 Y3 a1 x. ?: s9 x" u2 K, }
        if( queue.data[queue.rdptr].time <= writetime ) {. [) a8 y( ?0 e2 g
                ret = queue.data[queue.rdptr];. i& n/ K% X+ T( g  ]" P
                queue.rdptr++;5 w0 F1 \# ?2 @) J* R( R
                queue.rdptr&=QUEUE_LENGTH-1;
- ?8 e4 v3 m2 X' b" f3 \+ Q                return        TRUE;4 d+ H  g7 ?' y& u
        }  H' R0 r+ ^# h
        return        FALSE;; E. ?5 G+ |# y9 y* ^# L
}
/ x# [/ g- e) J8 ]* D: E
: Y5 }$ b4 U6 C/ Z& n# A1 @void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! a$ _" @- _1 Y, W# q% E
{3 h! d( H9 B$ N( u4 e- l
        exqueue.data[exqueue.wrptr].time = writetime;
+ m7 x% M, c9 V. M        exqueue.data[exqueue.wrptr].addr = addr;
6 J! A! H% V* y; p/ k# }        exqueue.data[exqueue.wrptr].data = data;1 h4 k! ^' d1 V3 r' R2 I9 K# e& y
        exqueue.wrptr++;
; D# E! Q" l0 p$ [! y4 h0 I2 h        exqueue.wrptr&=QUEUE_LENGTH-1;
* F1 F- D+ h9 V/ d( P% L- f  b        if( exqueue.wrptr == exqueue.rdptr ) {7 _$ T3 }, J& D( i1 @5 \% c
                DEBUGOUT( "exqueue overflow.\n" );+ y: |- _( C7 U; \- E; ?
        }
8 v" l0 q: O8 D, ~" T$ K}
9 |# p' X9 L/ u3 P0 f3 U
7 w  s! C# a" fBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* I/ {  w( }5 ~
{, D' w8 u  [4 B- ~* T) v
        if( exqueue.wrptr == exqueue.rdptr ) {8 R; p4 d3 j5 X1 P0 o( R0 }
                return        FALSE;
2 _# h% \+ d0 K" l  K        }5 s9 z! s$ p' m0 F4 c; E
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! F4 l: M3 k" Z- j& g                ret = exqueue.data[exqueue.rdptr];: G- Z' h& Y, P* k' s% u
                exqueue.rdptr++;6 o& n: }: h' k# Q3 B) T
                exqueue.rdptr&=QUEUE_LENGTH-1;
' @$ t8 O/ A2 H1 x. t8 ^7 Z                return        TRUE;7 [# x' _* c" l1 i. d+ v  G
        }
( N  L6 z) u; L        return        FALSE;/ S- O+ @9 S; ?; u* m
}. K8 N/ r$ W3 C* [4 T- _" @

# f; F% d2 P0 Q6 }) K6 z6 m/ Avoid        APU::QueueClear()& Y; s% P" `! ]
{9 ~# Z( l# ?8 J: I! }: U9 n  p7 x: X# X
        ZEROMEMORY( &queue, sizeof(queue) );9 |6 Y2 i: z9 ], J! F
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. c" I7 s5 k" n( I! k}
2 T# F% T" n3 s0 {6 p1 K# J- D) [0 h5 P8 |+ j7 L! C
void        APU::QueueFlush()/ v' u4 _4 G" t6 a  T
{
4 ~9 {' n! x$ c9 ~$ Y8 ~/ \1 Y        while( queue.wrptr != queue.rdptr ) {; h- r% H4 ~3 G  Q4 Z) m: `
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; x2 ~8 ?7 ?0 b& ~7 D2 R" t                queue.rdptr++;- Z+ u7 S' G2 }4 q- O, Z
                queue.rdptr&=QUEUE_LENGTH-1;
7 y) v! S1 D; G! O0 l        }
9 m3 z2 R8 t, F0 |2 j
1 S0 T7 D' r, v$ \' V7 H" e+ Y        while( exqueue.wrptr != exqueue.rdptr ) {
8 D" ~! L9 d4 |9 |0 l- N                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );6 I1 [4 Q6 `. f3 U1 Q9 i; f
                exqueue.rdptr++;" |9 K6 p; i$ c( \. F4 p1 A
                exqueue.rdptr&=QUEUE_LENGTH-1;4 H7 R' b. o. a5 f7 m& d
        }" d- R3 H% e  r% v. N
}; O- ]$ _  ?1 w/ G

( e/ j" X  P6 J+ C2 I. _3 n" Q9 ~void        APU::SoundSetup()
4 j, n2 g  c# t* G8 l5 J2 w{
- Y* {& |, Z$ j& {' R$ o        FLOAT        fClock = nes->nescfg->CpuClock;9 `, `1 s2 y5 U& b6 D
        INT        nRate = (INT)Config.sound.nRate;
# c9 N! z3 r7 }% |3 K* Q' p9 G        internal.Setup( fClock, nRate );  I5 K' T* ?( A: m6 F; S& }9 L  M+ k2 x7 w
        vrc6.Setup( fClock, nRate );$ e/ j  v' l1 L: ]' r, {% J/ ]3 U
        vrc7.Setup( fClock, nRate );
& K8 X$ s/ c9 |9 L        mmc5.Setup( fClock, nRate );
; K- r$ h; }% m; T8 X. Y        fds.Setup ( fClock, nRate );
9 \+ d0 K% \/ b: s7 O) k: E        n106.Setup( fClock, nRate );
5 g9 ~8 Z9 D: X# R- ?2 s1 v5 Z% l. `        fme7.Setup( fClock, nRate );" S' U6 a: V+ t
}
6 w& O  @. _7 ^
5 p8 D% t0 G: kvoid        APU::Reset()) G& U# d2 q. d$ H3 ]* N- X  S
{& a' t' q0 [9 r9 l
        ZEROMEMORY( &queue, sizeof(queue) );
1 p8 f  |4 n8 O7 I' X- ?& O9 c        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( B' j: v8 S4 G; ]7 c& B
" u% F  ?# T( N        elapsed_time = 0;
, j7 t# r$ H+ `! d7 p9 r; f) |! t
% r# d; f, _2 x5 ]6 s- O3 _/ @        FLOAT        fClock = nes->nescfg->CpuClock;
1 [/ G( ]; k. f( M        INT        nRate = (INT)Config.sound.nRate;" g8 C/ {: [6 s$ ^9 x5 X9 J
        internal.Reset( fClock, nRate );
3 M: ?' F& x; M; q7 n& I: a        vrc6.Reset( fClock, nRate );- ^$ q9 }. U1 O# }4 a/ F
        vrc7.Reset( fClock, nRate );
& O+ q4 \4 h  z2 @* a        mmc5.Reset( fClock, nRate );3 Z5 ^9 R& L) _$ ?( b* E
        fds.Reset ( fClock, nRate );
! j3 g! b  t% `6 }        n106.Reset( fClock, nRate );
2 z; f9 q- r0 ~        fme7.Reset( fClock, nRate );( L9 J% D5 a; O! Y, k/ j
) f& A/ y: [/ y2 Q' n; n" i
        SoundSetup();3 i  b" v/ j6 ~0 t; e& `6 I
}' w8 p* O7 M: O9 F% e$ v  D, a

, f& |5 B6 j" O9 s  Kvoid        APU::SelectExSound( BYTE data ); t) S' [5 H% e: r
{. o8 ^& o* u& ]! t" s9 z! @
        exsound_select = data;) Y" O9 B: a* V  [" C! Q1 m4 u9 t% l
}9 d+ `. D- {- v1 h% d2 g9 E( k4 l

4 n7 @& G; r' n+ \8 X) N" c* f0 vBYTE        APU::Read( WORD addr )- Q9 Y7 T/ ~2 T% X! _
{5 h4 r3 ^9 a* `6 ~
        return        internal.SyncRead( addr );
! X+ p& D1 j- b% Q4 \}/ m2 W( }% d1 i
) Y4 n: S9 O# {; \
void        APU::Write( WORD addr, BYTE data )
) D; t7 [, O  W4 S3 j4 ]* G{
# d6 R1 Z! b9 x" A. v        // $4018偼VirtuaNES屌桳億乕僩% V9 c) X$ V: b9 P
        if( addr >= 0x4000 && addr <= 0x401F ) {# g5 y$ F9 }6 M: v' q, F- Z
                internal.SyncWrite( addr, data );
2 a% T5 W7 B  s2 y/ @9 C5 w: m                SetQueue( nes->cpu->GetTotalCycles(), addr, data );/ `' V! l0 f* r* l  N
        }
. Y& D( y# g2 I/ C}) n& \) i0 j" A( G9 |

% j8 \' b  Q( U  j& ^+ U1 M" k3 O5 YBYTE        APU::ExRead( WORD addr )
( f7 a1 |5 m( J8 M( F{
( I- U. u+ @1 \, m1 I) ]3 `& WBYTE        data = 0;
0 U: [$ P% U# X7 _" z$ Z4 I1 l0 O2 {- M
        if( exsound_select & 0x10 ) {2 ]/ ]* B$ S2 u8 p
                if( addr == 0x4800 ) {  Q1 Q: r( Z  D
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );+ ]: A! Y$ B4 s# m* a1 M, T' A2 O
                }  p7 V* M5 j" B8 N
        }
& I) ^* y8 D+ D# Z# C# [& i        if( exsound_select & 0x04 ) {
9 F9 z: k5 O' i% m9 d                if( addr >= 0x4040 && addr < 0x4100 ) {, w3 }3 B8 U7 B8 M2 _2 n8 G( i
                        data = fds.SyncRead( addr );
; ?% l/ Q- ]1 [5 T6 x' ~( A                }
8 F" x- _2 v  o        }
( d+ T% ~/ ^* B" E        if( exsound_select & 0x08 ) {
" l: u7 \/ M  G5 p                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 f; R1 Q( ^5 s4 J/ L; t                        data = mmc5.SyncRead( addr );
9 I1 c% b1 @) a5 M* C                }. ]( e3 r. X3 F8 S3 @6 O4 }
        }
# F+ _2 N9 [  _
, a! C$ r+ d7 P( I) m  L) g2 P        return        data;
+ r) }' Q+ O/ u4 O}
0 Z2 h9 l! |, B# e; @3 V# j0 g8 t
9 S/ X. C( I7 Y2 N! t/ x; I- Jvoid        APU::ExWrite( WORD addr, BYTE data )
* L& N) w- Y' D0 Q' q6 R{
! ]) v& h2 u' F        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 n- d7 K- ^9 M/ k# e3 I' n% ?8 B6 S+ E# R7 j# ^
        if( exsound_select & 0x04 ) {
  [( \3 Z% s: h5 p9 Q  W1 M                if( addr >= 0x4040 && addr < 0x4100 ) {
; `3 s6 {9 Z8 p) {/ j                        fds.SyncWrite( addr, data );
9 b" |7 D- x" m                }
- `# D4 g6 {. d        }
! M0 J, s7 _7 z: }  `* F. E$ E2 ~) _; H7 d
        if( exsound_select & 0x08 ) {
7 S6 t; j9 z2 h                if( addr >= 0x5000 && addr <= 0x5015 ) {6 ~$ N1 i# Y$ ]) ?; [
                        mmc5.SyncWrite( addr, data );
$ A; @5 }0 V- a' C6 v                }
- w  q8 B  C, @+ L/ m        }/ W2 V; z' @: G( x1 {6 y$ L# w
}
% Q1 _& w/ R' o7 H
0 c- ?5 a6 H  a$ F" X9 K; [void        APU::Sync()
1 s/ a' q4 v1 L. f; ~% c{
! a+ Y% I  }+ l! J: S! T1 x. o}
, a6 W6 R/ ]- L$ ]3 s
: m, H# e$ K+ R, avoid        APU::SyncDPCM( INT cycles )
0 h. V0 F) b" O6 d# A{
" _& I& o9 V, k4 i! f5 y) X" `        internal.Sync( cycles );! I  d4 \6 [6 P: n5 {6 c4 y

' ]3 E3 h, u4 u6 A" M        if( exsound_select & 0x04 ) {  f& k% ?/ ^. G' y8 W( o. C) m  b7 |
                fds.Sync( cycles );( L: s0 q$ n7 J; A3 T+ U' A
        }
) Z" ?! v" j$ f) ?1 T1 u( a6 Q        if( exsound_select & 0x08 ) {
) R$ x# b0 N; f                mmc5.Sync( cycles );, E) Q2 a0 R9 h3 V$ |
        }% M$ r8 K* f4 V, R  C
}
  A; r' e1 d  H
& o" _$ }/ }+ h: {0 m1 Svoid        APU::WriteProcess( WORD addr, BYTE data )/ S& N0 D3 P/ i* q" Z3 C4 l0 w
{
) k$ H; ]: N, J. {  v. x        // $4018偼VirtuaNES屌桳億乕僩: v. b1 L9 I+ A2 V
        if( addr >= 0x4000 && addr <= 0x401F ) {
& R8 {% d4 Q, X4 \                internal.Write( addr, data );8 r' |3 o; [+ N, t0 o) j2 C2 S
        }& q. ~, A0 V1 C% C* v% {# j
}
; @$ F/ r+ B$ `# P) |% A) M. c$ A) y1 ?% j. g# J
void        APU::WriteExProcess( WORD addr, BYTE data )* s  G( U3 L, ~: d. m' w
{
9 a& [, N  W; W/ n        if( exsound_select & 0x01 ) {
" g7 W- R) J! @5 \& m( z                vrc6.Write( addr, data );
. O0 ]& \" }5 Z. H4 z) f        }
, q( @3 _) u; l        if( exsound_select & 0x02 ) {2 J4 }) F2 L6 ]& w4 i& e
                vrc7.Write( addr, data );
4 \; t- o" Z3 e8 H" U: C3 D        }3 n( C* J8 r/ b9 U! G# Y
        if( exsound_select & 0x04 ) {
* j! y& C2 m% e. N                fds.Write( addr, data );1 K1 ?8 Q* K+ Y4 a$ G9 K
        }& M" i. s/ {! O9 O* p) R! w* ?2 l
        if( exsound_select & 0x08 ) {
6 j  ]/ J0 q6 G( j) t) U. M  X                mmc5.Write( addr, data );
0 P6 s3 n( p8 P        }
/ }/ Q4 g6 c/ d5 f, R' N        if( exsound_select & 0x10 ) {
$ k: B2 {& b; v" K0 J  b" L                if( addr == 0x0000 ) {5 ~' Y0 s7 ]* K7 Y9 J4 Z& A8 G4 p
                        BYTE        dummy = n106.Read( addr );
3 P' q1 A) W1 U( t; S1 X                } else {/ n& _0 E  s9 Q* F: E
                        n106.Write( addr, data );
2 X  Q3 U' `, _2 O) A                }% Y1 v/ ^$ b3 T# ~5 o/ I
        }. d8 u0 u( `4 ^! ~  C& _' S
        if( exsound_select & 0x20 ) {0 b! g# N8 r1 i  F" l8 ?) r
                fme7.Write( addr, data );
; M2 \/ r2 T! b9 {% K* h        }; A- [5 H3 I) c9 [
}8 f0 X! u' A/ E1 A  E" f  c

# Z0 M& |3 a% O4 R% ~* P4 Evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). s) Z- z3 [. v4 _% v
{# N. `6 V5 u8 `9 @) _) d( C
INT        nBits = Config.sound.nBits;
4 ]5 Q! a: J( V8 I) h. ?- jDWORD        dwLength = dwSize / (nBits/8);
: a* i% ^9 _: l3 Y5 {# o4 NINT        output;
2 m! O! ]9 ?. o0 J* F' }QUEUEDATA q;
* a) {7 U5 J+ n1 BDWORD        writetime;: z" F. K# B1 O& R" ]
9 D: p0 W) O9 X) B* p) e/ @
LPSHORT        pSoundBuf = m_SoundBuffer;
& T% j  V! e* R9 kINT        nCcount = 0;
. B9 ?% o5 C1 Q  x5 [: @5 j# G- M9 J0 N, [# M4 m
INT        nFilterType = Config.sound.nFilterType;
) }2 |: l" n+ n! d, ^( G, G4 ~& e8 c" N5 z. B% u+ [
        if( !Config.sound.bEnable ) {
) ?' M( O  a$ R; q0 W) b                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
4 j- ^8 m- v! ]% N' D6 M3 ?1 y. I8 S                return;- G$ ?) m+ z) s' [( a- o
        }) D* }2 q! ]2 a8 v. S  O

: B9 w! Z# O0 g$ F7 A; W        // Volume setup
. a) n( a. o- e3 x7 g7 K8 D2 K        //  0:Master. k+ \. |' ?5 N7 s5 v
        //  1:Rectangle 1* _7 O3 R2 q4 g" t4 b, ~
        //  2:Rectangle 2- u2 X$ Z$ c1 `
        //  3:Triangle
: x$ {8 p7 v. b  E. W6 Y3 |; q0 s4 Z% g8 c        //  4:Noise
8 `8 @5 h. {' V8 |4 {% i; _) S        //  5:DPCM3 Q1 K9 q' M) A9 y7 R/ G
        //  6:VRC6
! x$ M& Y0 {7 m4 U/ W# N        //  7:VRC7$ G5 S! k" y# N0 J1 }" k# G
        //  8:FDS
1 R" }# W6 y7 {5 z) _$ S        //  9:MMC5+ L1 J2 Z$ ]+ u) ?. g
        // 10:N106
: b# X2 f' r5 ~        // 11:FME7* X; D2 u6 b1 b! \3 ?) o
        INT        vol[24];; K/ ]' G: a0 _4 F
        BOOL*        bMute = m_bMute;
4 ~. S! m0 I# W) t4 h# ?        SHORT*        nVolume = Config.sound.nVolume;  k4 y2 z  h3 _
% k1 I# Z7 p5 i  h  I
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;* p2 J2 p. D8 q% g2 f! {6 P) C2 D5 d

; c, [* W$ z6 p* `8 o2 w        // Internal
6 A! r- a4 V* D; h3 C: n        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
+ U8 J! ]7 O2 E. h9 l1 ~        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
: `. X5 N8 p! K. n        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, t8 x7 a- Y. o9 Q' a        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 B' z: ~/ _5 z% x) {0 s: B        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;* g, F# b! H7 @3 L4 \7 U% l

5 M! G" L, x( W        // VRC6
2 p) |& I  S7 Y7 }7 [2 R4 M        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, _5 i; ]3 Y, f( ]
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* x) e1 O1 [9 h" h$ o
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# D9 O  D8 @' X3 l, g
( g; s) F6 j8 |0 A' r$ u) D
        // VRC7
: h. V* B: `5 J8 ]8 l        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; p# C5 Y9 C, D4 j

+ p4 n' u4 u- t2 Z        // FDS2 k% B% _: v, P# l4 q
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& c: o- b. f. r' A  B% x; d) c  }
, N2 @+ A3 v; d# R0 F        // MMC5, [% f, i+ b( N' @$ K
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 f2 t6 ]+ D+ a% ]$ Z        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! ~4 B# m# U/ s0 L6 q& J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: f# G0 t# N1 `, m* {, V

8 P' r% W5 D5 X$ q2 v7 y        // N106
8 d, I" n1 ?4 u& q( r8 [& ]# t: Q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ s& v' @, B# R7 h3 `, I        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* V" F7 G4 B) n: @        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- i$ V  z0 _0 E  a3 Z8 B
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ ?0 T6 d1 y3 A6 D4 V# l$ |9 u
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; @6 |$ e& f3 b        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% {1 {4 F8 x) {# R' m
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 I1 g' v+ j# p  L9 j3 Z9 ]        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ t5 f5 I, T2 g9 D" E: s( Q9 B

4 i: @. h% ^- e& D) V( N        // FME75 b( b" y& J; T8 o: Z9 m2 c8 b
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ H+ X) K. g4 a7 r' v* T& }, O0 X
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) m6 \" P+ d3 K: I- b
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 e9 w0 F, v/ O) D/ }6 b

# G' u% e, t; N//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;& |6 a" d1 q% \, q
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
4 P2 z3 _9 y; y/ h0 z( p# X: L7 C' u& j$ U* k
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' T8 g7 m! [- P2 d# b1 Q        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' L$ o+ E' S+ W( K
                QueueFlush();
' B) U' k- n- p5 R6 l* Q) E5 F- D        }6 e$ n" q/ T7 {; q' g
; k0 t% d* f5 U# O4 D6 `% v/ X+ ?& _
        while( dwLength-- ) {
/ U# U! I$ R4 i* W, H3 g4 x" ~+ x                writetime = (DWORD)elapsed_time;
! T- O0 T/ v# S3 d4 I3 G, p+ a" L2 I9 f# Y, d$ `7 F
                while( GetQueue( writetime, q ) ) {6 ~" N- _2 q! V9 w$ U. b
                        WriteProcess( q.addr, q.data );
6 G8 T3 H. k# X/ S  v- C                }3 ?, d4 h% C' f+ v/ Q* R; x4 w" ^
5 J% H! K' |3 M+ H: B( O/ O+ j
                while( GetExQueue( writetime, q ) ) {
2 E9 ^+ T6 v/ R: b/ a# x$ |% }) U) m                        WriteExProcess( q.addr, q.data );0 P0 |: [' j- i9 u  G2 {9 d2 r7 O
                }7 w; S' }! I- Z, k
9 Z# V, n* i; o* m2 K* t# v( I
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
- R/ j7 i4 ~1 Y                output = 0;; m" b8 ~( s/ |
                output += internal.Process( 0 )*vol[0];
9 v3 T) }& @: B, ?- U; S, y2 b                output += internal.Process( 1 )*vol[1];
0 ?9 U0 m- t) i$ ^  k4 k7 |                output += internal.Process( 2 )*vol[2];7 W, A; S; q1 B' p- a$ G3 P8 P
                output += internal.Process( 3 )*vol[3];
' |  S  s: d2 Q# R& q                output += internal.Process( 4 )*vol[4];+ w5 p: D/ ]8 g# ~% v

; T! M9 p( C0 e6 ~1 ~                if( exsound_select & 0x01 ) {6 ^# y! s" K& E5 B8 Q$ n
                        output += vrc6.Process( 0 )*vol[5];& U1 C/ [. k5 m/ z* I* R
                        output += vrc6.Process( 1 )*vol[6];7 {; G2 r. J% ~: f
                        output += vrc6.Process( 2 )*vol[7];& k3 b( d& q) D3 D* ]* _
                }0 i+ ^- ?- h# a) D: i" }
                if( exsound_select & 0x02 ) {  X# k; d8 e/ }; O
                        output += vrc7.Process( 0 )*vol[8];2 @4 ~0 @, Y9 ~
                }
% y) j- U, T3 j' z* f4 |                if( exsound_select & 0x04 ) {5 h, x& ?2 `8 U, K: L
                        output += fds.Process( 0 )*vol[9];
& o: F5 \/ C9 ]" A                }# q1 D% l' a% Z4 j: M. E
                if( exsound_select & 0x08 ) {
8 Z$ ~& a9 X/ Z2 m: j4 C1 S                        output += mmc5.Process( 0 )*vol[10];& h$ ^6 i" W' ^- ~
                        output += mmc5.Process( 1 )*vol[11];
6 i$ @3 W+ u/ t7 G                        output += mmc5.Process( 2 )*vol[12];; _% f0 Y7 U+ R: t8 F
                }
" t# ^$ p8 D. B, z6 u1 D                if( exsound_select & 0x10 ) {3 z3 M# e: s, s0 x% b
                        output += n106.Process( 0 )*vol[13];+ @3 F7 ~, X6 P, E
                        output += n106.Process( 1 )*vol[14];
! |  i' i4 Q- m  g$ w1 T0 s                        output += n106.Process( 2 )*vol[15];
+ v8 X. b% T& I  k3 D1 Y                        output += n106.Process( 3 )*vol[16];
0 O( @! _% U0 C, ^                        output += n106.Process( 4 )*vol[17];: `/ v& F& c% b5 d9 d0 z7 @
                        output += n106.Process( 5 )*vol[18];/ ~1 Q8 b0 Z) P4 i- w1 E) Y7 ]
                        output += n106.Process( 6 )*vol[19];
) g3 b2 ?; O5 |# t9 q: E8 ^                        output += n106.Process( 7 )*vol[20];
: w; ^& P0 J. z7 M. G+ k                }
- }* N# e) u7 r. w# E6 t                if( exsound_select & 0x20 ) {
9 m' u" `( I7 h, F2 z1 v                        fme7.Process( 3 );        // Envelope & Noise
. X: E5 k% l) W4 e, t; U" X                        output += fme7.Process( 0 )*vol[21];- k( T, t& r" \& b6 R
                        output += fme7.Process( 1 )*vol[22];
2 M: L$ `6 T  B/ F* E) A1 H/ B                        output += fme7.Process( 2 )*vol[23];
0 l% Z3 C9 T+ I4 O5 C! x                }9 j9 I- d3 ]  f5 m

' F  N. z2 Y! z* k                output >>= 8;& W8 Y, M, E) b# @; e5 ?& O6 n

  d2 R! x( E6 d3 ~0 M8 f                if( nFilterType == 1 ) {
) Y1 M+ d8 V! N. a. c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)5 F/ Q5 H; s$ e8 c3 R2 W: S
                        output = (lowpass_filter[0]+output)/2;$ V7 Q- M& Q* |/ N, w
                        lowpass_filter[0] = output;$ v1 H7 d, y' M- R0 c: e3 O4 `
                } else if( nFilterType == 2 ) {
% j. _" S/ A* V0 O2 f% i% n" T                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1), r8 s, V+ j/ ?! `6 V2 B& W+ I( v
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 h  f: h& _- I- k
                        lowpass_filter[1] = lowpass_filter[0];
8 w# A6 t# D! p* ~3 S8 Q                        lowpass_filter[0] = output;4 `# ^" R/ B; n( \" A
                } else if( nFilterType == 3 ) {# k% c/ D/ Q) s/ q
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)' p5 W  N( s1 N! q
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;' w$ Y9 d2 r/ s6 E# T- \% A0 U: b
                        lowpass_filter[2] = lowpass_filter[1];
) }$ K$ |  f  K! E                        lowpass_filter[1] = lowpass_filter[0];
) z2 L' Z7 E. l* y                        lowpass_filter[0] = output;/ z/ N; T  P+ f1 p" ]9 W
                } else if( nFilterType == 4 ) {
8 |+ N, R  v0 q+ G0 Z- ^                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)8 n& @' u7 c( h* h
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( S/ @* D3 n/ a$ l; x! `                        lowpass_filter[1] = lowpass_filter[0];. Z- D/ t4 p, t& J
                        lowpass_filter[0] = output;
: r" e+ [6 i- r, R) G                }
/ @6 y5 H8 J( e! |
0 c' d! \5 G/ `+ ~#if        03 c! s' H- m2 Q1 v; F, G" y
                // DC惉暘偺僇僢僩
1 Y: S+ }4 _1 S: n# a. w3 c5 f3 E                {
/ K: h, j5 C% t. C! q' e                static double ave = 0.0, max=0.0, min=0.0;
, E0 l8 n1 S* D( M; m9 @; ~                double delta;+ Z! n9 [5 ]7 c4 P* ?5 b& R2 n
                delta = (max-min)/32768.0;
' [$ j4 B# {! }$ |                max -= delta;
0 c( M) a+ G* x                min += delta;5 V6 n+ h. q2 \! F) u8 o8 q" ]( c
                if( output > max ) max = output;/ C8 ^2 i6 e  P1 ^& I. i: G
                if( output < min ) min = output;# k- m# o' [3 X0 J& H/ X3 c
                ave -= ave/1024.0;
1 r0 [; I2 ]: P. O, u$ e7 A& _' {                ave += (max+min)/2048.0;
& [+ l& p8 x  p0 W: f                output -= (INT)ave;" d8 b! Y  w( _& F2 C1 l% [
                }
6 Z8 L* I' N% L% D  A#endif) q' x. C7 k# j/ T, ~7 ~
#if        1
+ I6 k7 V9 s7 t4 T1 V2 x; p                // DC惉暘偺僇僢僩(HPF TEST)
4 E6 C$ P! A! K- ]1 O* b                {6 w5 d+ f, ^2 i6 R$ i
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);  J, W$ @5 \, ^
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
+ X! G8 n& g" L; k                double        cutoff = cutofftemp/(double)Config.sound.nRate;1 h/ s( ?% f3 ~1 M2 b- q  P
                static        double        tmp = 0.0;
6 U* ]7 f" t& V3 B, Y                double        in, out;
& y$ c' T* M$ }+ k: |6 }2 c
: t, T% N3 e2 q" L  \$ w* S" r: ~6 R                in = (double)output;
% `  h; B) H5 a8 [6 l5 n3 a+ U                out = (in - tmp);
+ m6 y4 a0 D" t4 a5 j                tmp = tmp + cutoff * out;( r# z" Y: m8 L% o' t8 F
; W) L  [2 n& i; f2 k# E2 w& M
                output = (INT)out;
" T* ?# i5 T" ~0 w8 \: l                }
( K+ R0 V5 d, {$ |& t( d& ~1 s#endif
. l9 [& D, z  O0 m9 H: W#if        0( r/ Z- ~* A( I6 A) I8 p) [
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
2 b2 K+ v: t! P; ^7 o) b                {
6 o* X" g% u$ B; Y/ w                INT        diff = abs(output-last_data);& }( N$ D: Y  c7 f1 |; S; F: g
                if( diff > 0x4000 ) {
. H3 G+ x/ y0 {5 r7 R1 u1 S. H9 V                        output /= 4;* t, X) U% G& q& b6 L
                } else ' c+ \3 T0 C7 P6 g0 L  O; \. t
                if( diff > 0x3000 ) {# G6 O) S% @2 x% v5 c6 b6 p  _4 S
                        output /= 3;
, T7 c9 q( \3 ?* K: z7 V; g. s. d                } else
: e$ S3 h  ~. ^% M: \( ]  L& y                if( diff > 0x2000 ) {
: _4 d3 C3 g' ^  [, M                        output /= 2;, h' X+ M: i9 {! ~/ m
                }/ d) `+ B# I. E1 O9 r
                last_data = output;$ V7 F! h6 v! q" ^5 V3 n% s( m; L. f
                }
1 S4 ]- `3 K7 T# I7 K/ I$ Q#endif( X! z. i" k9 u7 h) m) B# L; D
                // Limit
6 Z. m0 F  V) g                if( output > 0x7FFF ) {
8 H) k- k6 _0 \                        output = 0x7FFF;& t; }5 d- B8 c# U0 O
                } else if( output < -0x8000 ) {
4 \' t/ a% H/ t' R! |. L                        output = -0x8000;
: ^: u8 g, s% A. c5 K" v; j                }
  c* }* e! F  n; D! X
" y& Z: N2 Q% H0 {3 [* Z                if( nBits != 8 ) {
! N& \! T" k5 d! ^9 X' l, b                        *(SHORT*)lpBuffer = (SHORT)output;" m4 t; {0 I; m* X; P% a" A# |2 p
                        lpBuffer += sizeof(SHORT);
: R  c5 p) m% c                } else {
) S. B# C5 Q5 a- G                        *lpBuffer++ = (output>>8)^0x80;
! \( k; a* j# a* J: k, J  u; b                }
$ |. Z1 P0 r4 J; P
$ [* h+ h9 g: B- w                if( nCcount < 0x0100 )
- _+ o0 c+ e+ _$ N& B. U                        pSoundBuf[nCcount++] = (SHORT)output;  j4 X' p! [* |/ P2 i+ M$ D! d

2 z' a# u8 K8 ~0 g( p5 @! h: y! _+ ^//                elapsedtime += cycle_rate;
! ~. ]9 A( n. o2 u4 H. L                elapsed_time += cycle_rate;* \4 x2 \( g' @, a" W, V
        }. a4 \7 d- |9 {# ?8 @- k, ~: [2 D
5 z* c- d" {$ i- Q$ e
#if        1
( K0 p  A4 m( A: k3 _) C9 D! U! |, L7 c9 q        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {8 @  E: B& U' H0 v  Q/ A8 {
                elapsed_time = nes->cpu->GetTotalCycles();
5 A: G9 G5 l) q9 g# u2 Q0 }        }. T( t$ g1 @0 a8 V) m$ M
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 o% g* C. o  z( L2 j
                elapsed_time = nes->cpu->GetTotalCycles();+ t$ |: A  g3 y6 n" l, J" i# F1 W3 E
        }
" r0 ~& [& M# w#else0 z" G# `# x+ \# c
        elapsed_time = nes->cpu->GetTotalCycles();
, C- Q* F' A& n3 Z1 Q+ A#endif; D: _# A7 n& `* }6 A* r5 N
}
- H8 D1 x9 M, `. n0 ^, C7 _
3 H+ i) [" N& _- z0 r# Z- Y// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 A. i) k2 }6 @6 h
INT        APU::GetChannelFrequency( INT no )6 J! B5 I1 T9 O" v: R/ v7 C# X1 z6 O
{
! `$ r9 l4 j4 R+ T( ?' f        if( !m_bMute[0] )8 }6 J# M, o- l' @2 ], X7 u+ v
                return        0;" a* H8 S, _! _  K6 s# t% Z. A
; M8 v. ~) b$ r7 g$ e
        // Internal; \/ f1 g3 ~& E  `  x9 {: B
        if( no < 5 ) {. j3 U; h9 A: h; S& m( C3 T  o* m
                return        m_bMute[no+1]?internal.GetFreq( no ):0;. ?! @$ u+ J3 ^) T" d" m
        }2 H8 N$ c, r6 ]. @, P7 Q
        // VRC6: F, [7 X2 G: i$ v
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {% M2 [2 r. t; u7 h6 E  r% K
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( O; N. T5 k1 E$ `, e) b& ^        }
1 z' K! G, n8 p) o        // FDS% H+ Z# W0 V, B) u' d6 P4 b
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ h. b5 _! j! j: X                return        m_bMute[6]?fds.GetFreq( 0 ):0;
* ]! Y5 _- L) [7 x& N# p6 X: @        }
* T0 p$ D5 h/ m$ \, k1 A+ w6 H/ A        // MMC5
* \( t# E7 t0 i" u  [! c& O        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
( t7 t* s+ w$ G& Y3 u5 a                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;* n$ s* i' x/ j2 e
        }) S( H, T1 X2 ^: Q
        // N106
" `. o7 @0 r3 }        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
7 Z# p) g& I5 ]2 O' }# M                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
- ?' u" O1 v7 P: L, c        }7 P  D2 F/ d" g1 A: v2 O7 [- s
        // FME7
2 N7 p. T) x2 I7 n        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  B  U  ?; m  k' b                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 K3 g. ]0 p, U$ \+ @$ c5 }- G2 m6 t        }  u3 C% J6 f* `/ }# ~
        // VRC7
" M- a- Y) @5 r- h3 O# o        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
* }% i" R9 U! Y, ]5 \                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
9 O( {2 J1 A6 X% d+ g+ ]8 e        }
- N! }5 Q* M1 {: w        return        0;3 P. A; Y. j4 O+ s$ i
}
' S5 y) B- A) [- o, j  l, w  k  X
8 v1 I: A/ [! I6 T// State Save/Load( D% {% I7 V- z$ }
void        APU::SaveState( LPBYTE p )# i, E3 x! A: X/ U$ n
{
9 I" F# U, `) Z* ]: V: {#ifdef        _DEBUG
! }! r  V' @5 y3 tLPBYTE        pold = p;( v1 L! ^& [. _' `
#endif
6 P0 T7 s6 C9 b, v- c/ A2 L" k% v* j* g) {5 X, c  b
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
; Z6 M0 n: x6 n3 E! |- ?# r        QueueFlush();  `# U* e% Y/ H

1 ]0 b* _: m/ z, b; n        internal.SaveState( p );
) q; C6 I4 q. I8 B- ^% l3 |        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ I) V2 ~0 Y9 `3 ?
* u& Z! H4 v' m        // VRC6
' _% h2 i, U  z7 h        if( exsound_select & 0x01 ) {8 d9 G/ `- ?' {8 N% L- q
                vrc6.SaveState( p );/ K4 Y& w. ~# W6 J- h- e
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 v+ e; y3 H6 @) Z6 v
        }- M+ p) R( Q# a% W; ~! h' r1 D  L
        // VRC7 (not support)& U8 y1 X; W4 ^2 j8 ^( O: b
        if( exsound_select & 0x02 ) {
) a. J1 r# E5 x; {                vrc7.SaveState( p );
: O9 \3 Z! v0 l! }                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# l  Q% Z5 U0 p' i        }
/ a. v4 y( b' `) `( f! b! S3 k7 G        // FDS
. B& r. F9 p9 |8 U$ ~; [* A4 Q        if( exsound_select & 0x04 ) {; I0 _& U8 U. p- j. q8 W9 Q
                fds.SaveState( p );6 \' @! z$ I# D" j  g
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 l0 J& [6 q+ B, l0 M        }# O5 t$ R; a% ]9 K
        // MMC5+ e6 b" h, O( E5 j- {' }8 D+ c
        if( exsound_select & 0x08 ) {( I- g/ n, c- Q9 m& v
                mmc5.SaveState( p );
, w; o) B, E1 q& b6 `                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 M- H, [7 y& _7 X( M' s$ K, \
        }+ S$ Y; r$ c! h8 E: C
        // N106
) K; ^8 s+ U* A! P# l        if( exsound_select & 0x10 ) {* t. O$ T& ^- [/ w" r! Q$ |4 f
                n106.SaveState( p );
! \" t# C7 o4 _0 ~, S  n5 D& k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 R  ?& t$ a( K' A( _; w0 J
        }
  r- B+ t& Y7 K; d0 j2 u        // FME7" {# q% e3 O; s/ u8 q" @
        if( exsound_select & 0x20 ) {
# j* I" d, R/ y! X8 B                fme7.SaveState( p );
4 f6 F2 C5 a/ m: U; G                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" Y" g" h" S5 E' w# L
        }! Y* x9 B, ]- G" }( {

# C- W% l& e- `, b#ifdef        _DEBUG. p: B0 b+ e+ T( S- v5 T, R
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
8 a! X2 \; R6 `1 O. _& ?$ w3 a#endif
6 z% k' Z9 x& R( p5 {}/ G: L; r' F, Q0 H& o) x

9 s  @5 ?0 i& Z# b% }void        APU::LoadState( LPBYTE p )5 U$ V3 r0 b/ H" z! v; Q: R* z
{
7 Q1 @9 Y% {4 v& @. t  R2 a& q# b        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
6 L, H) h8 N" _1 g  L# o        QueueClear();
  n4 P( L& U" `. C, G
7 b! n- `7 r! a: j/ n! ?        internal.LoadState( p );! Z  y# y3 l! I2 G" O3 _) \
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ n. w2 C* a/ H! z: G
7 ?7 ~8 ~. {" h, I        // VRC6
: z& i! |* r2 M/ {        if( exsound_select & 0x01 ) {
- ~0 M/ @! I) {2 T, ]5 M) x                vrc6.LoadState( p );
8 @" n; M+ t) G9 L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, p; t  E) F: l/ a6 {
        }( e& u, q3 [5 S% u. o0 }3 n
        // VRC7 (not support)8 J) b! i, s' ^  \0 F2 y, T( k
        if( exsound_select & 0x02 ) {
) N# ]! \' Z' [- T/ k5 x. Z' }                vrc7.LoadState( p );& e1 W5 J5 ?' |5 e2 B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ \  T' S8 E! H6 R        }
( ~; Z+ x# L( d( J4 V1 n2 j/ S        // FDS* E& E7 b; F" V3 F; P
        if( exsound_select & 0x04 ) {
2 h+ o+ S" I* Z9 H3 e                fds.LoadState( p );
) `4 F( e" }: i+ {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
/ r( a$ y9 g- M1 i# f7 d1 n/ n        }+ P6 [- R; q3 x+ j5 h, h2 G  L
        // MMC5
5 l- P8 l9 K! p  p6 _        if( exsound_select & 0x08 ) {
9 N( ?3 v8 T' B8 \6 T) q                mmc5.LoadState( p );) e8 m) r# y$ X6 A4 M3 Z; J- Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( F) m! W- l& e! a
        }9 h  s. c+ _9 @3 t6 ^% ?
        // N106
4 }; h- w+ o9 \5 u& O$ j: N        if( exsound_select & 0x10 ) {1 N7 @' o1 a2 u) ~+ A8 V( `7 Q* P
                n106.LoadState( p );
: ^' i: Q0 f2 B& `, y9 P                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* N9 X8 X- E2 @( N        }# I, u- s2 r+ P7 |, m
        // FME7
+ |% k% v9 q' x3 M& E$ F7 `5 E$ J& b        if( exsound_select & 0x20 ) {( O! v, `4 t% v' ?3 G4 {3 D
                fme7.LoadState( p );
! x0 G4 U+ b/ c2 {& P                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 w/ f2 v& ]$ E, c0 c        }
$ j/ g9 A: a- t, k0 d4 ?}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 & G) ]% r" f7 R  e
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。7 v( d( w; {4 g; e9 y$ z
感激不尽~~

) M, E5 S  o& v1 B恩 我對模擬器不是很有研究,: x( k( x! N: N* |. e* V4 O& v, X
雖然要了解源碼內容,可能不是很困難,' }/ w: Y5 ], t
不過還是要花時間,個人目前蠻忙碌的。: M8 H: |  R. X
& J/ n' W5 U6 g8 T& J  z
給你一個朋友的MSN,你可以跟他討論看看,
+ j8 _' |+ e/ |; K9 i他本身是程式設計師,也對FC模擬器很有興趣。: S: F" H' x, O& P

8 s' w, M2 ?" L- D3 B! h' BMSN我就PM到你的信箱了。% B) @1 u9 I( o
5 P1 k+ g6 D% F4 n, q' P+ X2 \, @" V$ J
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
4 Z9 Y/ |, s9 M% `# J* J呵…… 谢过团长大人~~

5 R5 w1 w, ?7 x& t0 N! b# b
) U0 d5 e/ z' x& X0 l. ~; y5 z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ k9 M6 O) h, N1 A3 k, U  L4 p8 w团长的朋友都是神,那团长就是神的boss。
! D( ?1 b) l9 Y) ]
哈 不敢當,我只是個平凡人,
7 u3 }. \/ b" K' c5 g$ r要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
+ _* `; O% E* n! F* eZYH
2 m8 f% k$ [2 u! h; p$ Y9 J9 i" @QQ:414734306
% }7 t: N4 b" K$ ^4 RMail:zyh-01@126.com+ Y4 r; H2 x8 g1 G

3 E; z2 o9 z* w$ ^8 A. a# ~0 j他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 a- V9 i. t; k3 {: Z2 Q
再次对团长大人和悠悠哥的无私帮助表示感谢~~

; O% u% Y+ p; D; \不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-30 03:56 , Processed in 1.101563 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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