EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( d) ?1 ?0 w9 o6 F1 S  r  x楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& R$ z) L- V* _2 ]8 U8 D
这里有相应的模拟器源码,就当送给大侠了~~* {# o; ~% h4 @5 H0 n, U5 ?
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; @2 _- ?1 k4 k+ t$ s! \/ k2 R
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  e" q2 t) o& @1 |5 R8 O楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ m2 e  @# }3 A( e这里有相应的模拟器源码,就当送给大侠 ...

- f) O" |2 p9 ]0 }% u% e5 X聲音部分(Audoi Process Unit = APU):: d/ g) {! \" Q+ w4 t: L- ?: m
.\NES\APU.cpp7 V2 u3 l; X3 l& G  ~2 n, D) _" z( P
.\NES\APU.h
2 `$ x  j2 Y" w0 S. J
7 m( g- ^" H9 w8 `" Q4 D. O- p6 v5 ^- A
影像處理部份(Picture Processing Unit = PPU):
  Z/ Q3 B5 x6 a) ?! [.\NES\PPU.cpp& e$ g) ]$ T) J6 U) d6 n, i" V
.\NES\PPU.h
( U/ J5 }$ r- `, s6 _0 U( \2 Z
+ {& i" |5 z  Y2 @( q8 C如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:* I, H$ V  Q2 g9 Y
(由于很多专用术语和算法机理都不明白,所以看不大懂……)  @9 G  ]' C4 w9 m
//////////////////////////////////////////////////////////////////////////7 u& Z/ Z6 ?( k  H, h5 g! }
//                                                                      //
/ D7 B+ e; L; h+ {//      NES APU core                                                    //0 _. I& T$ Q0 S5 d
//                                                           Norix      //9 H: \: K' Q1 Q3 d
//                                               written     2002/06/27 //9 Z- k1 ]3 M9 P5 ~
//                                               last modify ----/--/-- //
. s: v0 B" N( y//////////////////////////////////////////////////////////////////////////
) X1 U; O$ I" e/ ^$ J/ U# s! v( k#include "DebugOut.h"7 O4 B8 |" M5 x$ T7 L6 y
#include "App.h"
* e: i% B+ f4 F& H! `; r9 `$ N#include "Config.h"+ e2 e1 c$ h, F* V7 y" X
$ n. H/ n9 n+ F/ w3 I/ O
#include "nes.h"
$ d5 }3 o8 A; y' m/ I* X#include "mmu.h". y) F5 _' u, x( I0 i! _
#include "cpu.h"/ E: R; A1 P4 ?  ^' X& J
#include "ppu.h"
( |0 E8 p0 m6 R; ~- C" K/ a#include "rom.h"  U' {/ w8 q/ W& {. w1 I  T
#include "apu.h"* s9 b* }& T0 D0 T" L
& w: |2 L6 e0 k3 t- X7 `7 I! s
// Volume adjust
3 t( D# P5 v' o- V% A+ }% D// Internal sounds
; H, E# u% G4 a( [: A#define        RECTANGLE_VOL        (0x0F0)8 w/ l" i( Y" ^: u
#define        TRIANGLE_VOL        (0x130)
1 w9 V; m( P1 \6 O' r2 m#define        NOISE_VOL        (0x0C0)% ?* X0 c4 G$ i; L
#define        DPCM_VOL        (0x0F0)& }- r0 V% X7 I, |( A
// Extra sounds# R2 a! U. B" P( B4 T
#define        VRC6_VOL        (0x0F0)
: F0 y& L; O: X! L& K$ {# {#define        VRC7_VOL        (0x130)
. i+ C" `/ ~! N#define        FDS_VOL                (0x0F0)7 w# b+ D. ~& w3 p4 \- @  U: a" C5 q# O
#define        MMC5_VOL        (0x0F0)
" j' u9 o& P, U8 v- `- p8 l/ W. O#define        N106_VOL        (0x088)! h9 ?0 M3 k  B) O
#define        FME7_VOL        (0x130), ^1 C# h4 Y: x5 t

$ R5 z, c8 G3 m$ n) @& F/ b5 M: Z. qAPU::APU( NES* parent )
$ X$ i0 ?: v( A7 Q8 ]6 @{
9 X  C6 N8 K' X: A' V. v        exsound_select = 0;
" @# q8 s, r0 L8 N
% K, {$ q2 K! _; R" B0 U        nes = parent;
9 s) f& \! O/ M: T5 i8 ?        internal.SetParent( parent );, j( f5 g- r" `- w5 m* Q2 \# ~

6 V4 x  |) O- e4 s* j7 ^        last_data = last_diff = 0;
5 q! L0 ]- V: _3 C. D1 |  C' @5 q; o7 c+ ^5 F8 {% ^: W
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );0 \- L, G3 i( j  I7 B& A- M
0 f( G9 F9 }$ O4 n# H
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; ^* `5 ^$ S: c* f3 X        ZEROMEMORY( &queue, sizeof(queue) );
2 M: `- b: c. T7 `: R        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: U: Q% }  f$ c8 }4 I7 x
% @* [" @! y* j& Y  D        for( INT i = 0; i < 16; i++ ) {
: Z' E( i: I/ t- w                m_bMute = TRUE;
# E- {  V3 T9 a        }* Y' [8 Q+ c1 Z) {8 n; b) @
}" g) w8 X. `9 w3 b3 n

* g3 N& ^$ \: c' m6 d1 u! v, i3 @APU::~APU()
" W7 ], K* E/ I4 `  |$ m- y+ \{
, T1 g8 @3 {9 h( L9 K}) H# D! I. \! \! w
" @! n7 E# o+ b- h
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )7 n7 I3 [. p' V" n& L2 h
{
# {0 R0 k- S; a( i        queue.data[queue.wrptr].time = writetime;
* T7 X( M+ r$ o2 M9 X6 J/ n( A; j        queue.data[queue.wrptr].addr = addr;+ H" A! |: R/ U: G
        queue.data[queue.wrptr].data = data;/ @6 V4 n6 Y9 o7 g' A5 I7 x) _% a5 c
        queue.wrptr++;# p8 r( [& U" f8 S+ l
        queue.wrptr&=QUEUE_LENGTH-1;8 P& `& A$ z/ v6 x5 B
        if( queue.wrptr == queue.rdptr ) {$ V9 w# _! R$ x6 M4 L! E
                DEBUGOUT( "queue overflow.\n" );2 ~% Q7 T- V* ~- N) ]& |0 m7 E, \4 d
        }
, a, |* E' m  u7 n4 |; v$ p}
4 d2 O4 K9 W! S2 P; K/ X! `- j0 o/ C$ A0 k7 U
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
5 S% L& s7 ], a* T% }{  ?7 ~* D- b$ L! L1 L( E; J* @
        if( queue.wrptr == queue.rdptr ) {4 {2 Z/ l6 ?# m1 c# B
                return        FALSE;$ T& P# R7 K* K8 N' T1 G
        }& w% m: f3 s' L0 }0 z
        if( queue.data[queue.rdptr].time <= writetime ) {
: P! m& c2 b4 N3 z! |1 u  ]- ]                ret = queue.data[queue.rdptr];
3 ^! {& N7 B+ H: e) F                queue.rdptr++;7 R+ ]" C4 k/ e0 D7 \6 X) q* s
                queue.rdptr&=QUEUE_LENGTH-1;
1 t, ], J/ o3 g                return        TRUE;" n: G- D. m0 ?. ?
        }
5 {2 G5 @5 f/ q+ P; S" `+ p        return        FALSE;; ?. }+ E, `$ X1 {
}
, b& S/ r( H: @+ L1 s) G: X* B3 H% `* z3 c" E
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )$ Y1 M* ~! ]! V- W) I9 [
{
! B( W$ R, ?+ O6 L1 d# Z. Z) Q        exqueue.data[exqueue.wrptr].time = writetime;1 G; x/ Y% d" Z* Z: A0 g- c
        exqueue.data[exqueue.wrptr].addr = addr;
" P' h! j3 y2 Y" X- s9 u4 \& ~6 C( u; X        exqueue.data[exqueue.wrptr].data = data;5 q, l- }7 C9 F: {3 y" k& w
        exqueue.wrptr++;
' I; I/ N- t8 _" u4 s5 g: b( Q        exqueue.wrptr&=QUEUE_LENGTH-1;
* r) T: p+ W9 F0 M7 J! v        if( exqueue.wrptr == exqueue.rdptr ) {
5 _8 q5 N: e% I6 b                DEBUGOUT( "exqueue overflow.\n" );
. y; p. i6 X: P        }. E- [. F0 _- K! x8 F
}+ u5 \4 @  x- b" U- M  y- Y
# @) v& n/ [: f/ G, k
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
2 n' G- A: x: t" [- O# D{
2 o' b. @+ q% @% l( L        if( exqueue.wrptr == exqueue.rdptr ) {8 M0 Q5 Y0 M% |2 \
                return        FALSE;' j# Q, u) S, n+ K( f$ h
        }
8 B8 }' q0 ^# I! {/ y' G8 I        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! d! k' `. r" R7 B7 {2 I- F                ret = exqueue.data[exqueue.rdptr];( O' \' r/ ~' c. d7 `
                exqueue.rdptr++;
3 B  M2 G7 g% g                exqueue.rdptr&=QUEUE_LENGTH-1;, I. ~* p" d. s" {5 i# Z
                return        TRUE;: `6 ~2 Q2 q9 q  ?" K; B0 n
        }1 k& k5 ^1 }* |/ j* y
        return        FALSE;
9 @8 j" p; ?  A% Q. r& T& F}
( }& f6 u, |: N# S! R. j) ?3 V
: h& v+ v8 u7 D: yvoid        APU::QueueClear()7 l* Y& ~3 S% P& s- Z
{
3 [  i9 _1 e2 k        ZEROMEMORY( &queue, sizeof(queue) );
, q9 M- r" R* C. P3 [, q" k        ZEROMEMORY( &exqueue, sizeof(exqueue) );. a: ^( n4 `! P8 B9 I* L, O" w
}
' p4 p  v- h2 \( G
, ?9 C. i, D# c* {; S  |void        APU::QueueFlush()7 z% s/ t* ~& y
{# t: @" U3 ^, s9 N1 X9 d: W0 D; F
        while( queue.wrptr != queue.rdptr ) {. S/ d- {5 g- m# X) [
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );! l( E. M2 _0 \" |4 d
                queue.rdptr++;& o; {! K9 P4 M3 B6 J
                queue.rdptr&=QUEUE_LENGTH-1;" {; [) K8 W4 L, N2 F
        }3 Z+ J0 k7 \* I; P+ U* `

/ T' x5 M- q9 C% ~2 {: w* f# E        while( exqueue.wrptr != exqueue.rdptr ) {
, M$ \1 u" s9 o" c4 g' t/ f                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: _3 v0 ~9 B( t% ]% a                exqueue.rdptr++;0 W& Q  W) C/ F( B8 [: ~6 a. H0 D( P
                exqueue.rdptr&=QUEUE_LENGTH-1;' M" [% C. u; s# M7 G% V% @
        }
  h6 }4 N: _9 T}. I& m8 u6 i# b0 B$ r( t9 k% m

5 g: u# }* A* J  |1 l% }void        APU::SoundSetup()
" H" \# r- u3 C) I; V; ]{
/ j5 g! v. k1 ?. o% S% b. c0 |        FLOAT        fClock = nes->nescfg->CpuClock;
! R' s# h/ z% f4 r2 |2 J7 X5 e        INT        nRate = (INT)Config.sound.nRate;
% b' m" L, D  |! o5 A3 k        internal.Setup( fClock, nRate );! w+ f! t. l. A  w5 H0 b
        vrc6.Setup( fClock, nRate );: o" h& I; `' H0 v$ z
        vrc7.Setup( fClock, nRate );4 {+ J2 ^7 J/ u7 P3 A! z
        mmc5.Setup( fClock, nRate );
- h/ ~" B  S; I+ X2 c! ~- w6 I) }: b        fds.Setup ( fClock, nRate );1 r% Q' x8 \- M: C/ v5 `3 `, ?/ {
        n106.Setup( fClock, nRate );
' _* ~, S9 N# z8 i" z' ~( v        fme7.Setup( fClock, nRate );' T# Y) N* \! N+ i% h9 r
}
9 }4 W; _+ p/ ~  q3 F' E$ P1 q; x/ }( z/ p8 ?
void        APU::Reset()0 ]+ k8 x4 u7 B4 Q8 ~5 M- A' U1 V
{
! y( k9 F* v  w+ V* L        ZEROMEMORY( &queue, sizeof(queue) );* m/ ^' _* N* _, \
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 J2 {/ T8 K. [: }) S/ I2 N9 p/ D, v/ l, ~: h* b8 h
        elapsed_time = 0;: j0 |: X6 D- b3 |
' T* O# M& I1 f* O- S" ^
        FLOAT        fClock = nes->nescfg->CpuClock;: U! U( ?3 B$ d8 E, F
        INT        nRate = (INT)Config.sound.nRate;/ U) G, T5 F' S* c& n! Y  ^
        internal.Reset( fClock, nRate );
  n+ i  B+ y7 X) h& q# c$ x* ~- V        vrc6.Reset( fClock, nRate );$ ?4 E2 y" B# S* V) u
        vrc7.Reset( fClock, nRate );  {7 v6 K/ u2 q! E- k8 P" F2 x
        mmc5.Reset( fClock, nRate );" Y/ r: r. Q$ m* ]
        fds.Reset ( fClock, nRate );
" i, c' a9 Y! t4 ^        n106.Reset( fClock, nRate );
* p9 o" C! D/ z+ |) r1 `  `3 A        fme7.Reset( fClock, nRate );+ ], W9 C) x7 N# Q* S& q4 D3 |

" }2 D9 e% Z: `& ?$ H4 P- q# Q        SoundSetup();
5 g3 h! [0 s4 R5 f' `' |2 k}& K; V) K+ T/ w9 ]8 {. |

0 W" d5 L' p: C& \# zvoid        APU::SelectExSound( BYTE data )
4 P# S) s) M) ^1 g# t{
& J; T, I' X) |  h* o0 e        exsound_select = data;- A9 ^% G9 \% G- W& X2 ^0 G/ S2 N0 y  v8 D
}* F! a' Z. x+ D5 D

# I- H' \' Q9 o- n7 M4 D/ ~* w+ GBYTE        APU::Read( WORD addr ): j% j4 Z6 i( c9 |1 n" W
{
9 ?: w5 |. m8 l. _3 J2 n        return        internal.SyncRead( addr );+ l$ z* z  r+ n
}
: j7 h6 l! z$ I/ n  \+ d& _, W% p* N9 e6 X& P0 f
void        APU::Write( WORD addr, BYTE data )0 y4 F$ |$ ]) E* K
{
4 J& v' c+ K+ f7 |) F        // $4018偼VirtuaNES屌桳億乕僩
! V. e+ _  W3 ^, s9 b        if( addr >= 0x4000 && addr <= 0x401F ) {
, T3 w0 d* X  c- E8 x0 r                internal.SyncWrite( addr, data );
4 W2 E; v! _  a8 g7 h" T                SetQueue( nes->cpu->GetTotalCycles(), addr, data );: Z9 b4 i! U. N4 O' S
        }
5 ?" t1 Y8 x5 k; P) ^* O5 _}2 u0 W0 y; u2 f) r9 U
3 J( E  C& x* M- @1 U3 t
BYTE        APU::ExRead( WORD addr )
, l8 j& l- h) b- m{+ e, y- V. E1 n" i- O
BYTE        data = 0;
0 p$ _' m4 T, C! K. v: H) _8 Y; H
8 _4 z) o7 K4 H3 T& Q6 {9 v5 Q        if( exsound_select & 0x10 ) {. d: R, I9 I  K# e
                if( addr == 0x4800 ) {8 K7 L( {. f4 k3 U$ R
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
& i: v" e4 l8 F! k, D& B% C/ r                }
# ]* a0 p: U5 I: U& Q        }# V8 J3 {" K$ M1 h; b3 c: d5 w( g
        if( exsound_select & 0x04 ) {
& [; h+ K/ j" M6 J                if( addr >= 0x4040 && addr < 0x4100 ) {
& Q2 B# f4 O# |                        data = fds.SyncRead( addr );
6 b0 W. p" t  w$ D                }# l6 r+ g7 q- D1 B9 L  {$ U
        }
3 l+ {9 _; |+ u1 T; G3 z0 U- @! S        if( exsound_select & 0x08 ) {
' U" J5 h3 Y& \$ W" _                if( addr >= 0x5000 && addr <= 0x5015 ) {
) l: g4 l6 O8 a; C0 v3 G# C: P* L                        data = mmc5.SyncRead( addr );
  W8 m9 @( B; K! o                }
; q$ e0 T8 N: h! ]        }
2 D! `& D9 L+ z% n8 _' Z* v
) D8 C5 U- k8 R9 ~& Y& q        return        data;$ [+ h' ?) N8 g: W  s! Z: l
}$ q0 @5 |5 J; k% i# H! o  Q
; v" k9 l5 c3 X0 {$ L  p
void        APU::ExWrite( WORD addr, BYTE data )
0 @5 N4 k# a2 a9 R* I  y, u; `# V{
: `; C0 a! x2 p* ?4 r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );# f8 a+ u' Q% B" F9 I! ]
4 e! u9 s# P; J3 p( m# r
        if( exsound_select & 0x04 ) {
' @7 e' P% m" g8 W                if( addr >= 0x4040 && addr < 0x4100 ) {6 s4 b& c/ E2 m& S- T0 P2 t! e
                        fds.SyncWrite( addr, data );
& G' e& A- F& V9 c2 p6 H                }2 u0 R7 b& J; V; h/ y
        }
0 u: S- A% a% i6 |" M8 c4 B5 O9 n1 n) V2 u" l
        if( exsound_select & 0x08 ) {
8 L3 Y4 b3 A# b) A2 v                if( addr >= 0x5000 && addr <= 0x5015 ) {+ O" i* m" u: h- _" y2 G8 P
                        mmc5.SyncWrite( addr, data );) u6 H; B" b) q2 z
                }
$ F4 E  Q. k2 A; p' u6 m        }4 x+ e' o+ q* Z- ~
}' \9 Q$ S" S6 D% c
( S1 G7 f+ O9 m8 d- A
void        APU::Sync()/ ~& S  F* q  n/ Z8 y3 M& a
{9 v" k2 `# K' U, P0 @" ]' C
}
% m3 ]$ ]5 F' B. K; I" e; I# s8 o
# n2 Q$ p# {! z5 _* R& fvoid        APU::SyncDPCM( INT cycles )+ E8 f. R+ c# R$ w* ~
{
) ^5 x4 Q" f* ^6 o- u1 h! B        internal.Sync( cycles );" U; }! Y) s' W4 |8 ]  f% x1 f  e
; l8 {5 A  G% S6 Q0 X. J( Q
        if( exsound_select & 0x04 ) {& \! |1 x+ j7 c) A8 u2 w7 |
                fds.Sync( cycles );
4 `% H( M  m0 l% K0 W7 l        }8 a0 n% \4 y& E; k0 a9 ?
        if( exsound_select & 0x08 ) {
3 R7 P7 `+ z$ ~- J9 |0 u  N- H                mmc5.Sync( cycles );
8 _4 ?& @7 Y/ e$ g5 |% y; |        }
4 `6 ]! i8 u- X9 }1 ]9 |8 d6 T; C}) n' a# _6 |& V  t) E1 H

1 _' D9 c! e0 p" z1 [3 l2 ?$ k( E+ uvoid        APU::WriteProcess( WORD addr, BYTE data )
# u. P) e0 s. b" V$ Y, X{6 Y, z. X$ t/ e! w* Y. C
        // $4018偼VirtuaNES屌桳億乕僩* X  Y3 r6 H$ o1 b
        if( addr >= 0x4000 && addr <= 0x401F ) {
# @0 ^3 K2 T$ w/ t6 e                internal.Write( addr, data );
$ q$ k6 W% \; U4 Z- C1 S        }
, q  E$ @5 X- J$ W9 C}- b9 {* H2 ]  z2 O* `* M3 Z

# S: z9 D+ ^  a' c+ Zvoid        APU::WriteExProcess( WORD addr, BYTE data )
5 F: A! c5 A$ H) b{
5 Y2 {. X) p/ |0 C/ t        if( exsound_select & 0x01 ) {$ n9 `' N4 r) t
                vrc6.Write( addr, data );
4 r3 k8 Y3 I- z$ G* ^$ P' R' T9 H1 L        }
( _# e+ ~. o9 `) \$ {2 Z        if( exsound_select & 0x02 ) {
& K+ M3 @, Y8 g9 I7 g5 b                vrc7.Write( addr, data );
* J5 K9 V: m, P& N        }5 z: Z- G% j/ L  K7 }# v6 p4 Z3 K
        if( exsound_select & 0x04 ) {$ t# [' e! \- Q! x  ]+ M
                fds.Write( addr, data );
- O/ P" T% x7 e; V2 K- B        }4 A  y& m7 U; _1 M
        if( exsound_select & 0x08 ) {% i8 I# t7 I' w, k# Y* A/ w( f; W
                mmc5.Write( addr, data );
  [! U0 S6 b" g        }$ D  L7 G, I! \& r% P
        if( exsound_select & 0x10 ) {
3 n; e3 n" s) n( q                if( addr == 0x0000 ) {* R: Y2 W  G! N( T7 s; S" t
                        BYTE        dummy = n106.Read( addr );# o* a1 M3 e0 q$ ~9 M+ Z+ V
                } else {
: \- W: B! v2 Z                        n106.Write( addr, data );
; k  ^7 ?4 c) R  u7 h  n5 @                }
& h0 P% a" {9 S( {; l5 {        }! C4 v) e" ]. z- z  N
        if( exsound_select & 0x20 ) {
% f3 k) x7 \6 k/ L5 e                fme7.Write( addr, data );8 W/ t4 Z+ e! w# v: z! O
        }" l, }' ^) y3 h9 o! m" M2 A% F
}- ^5 s& `' Q; I  w/ V: J
* Q4 Q; g' h3 I: @
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
! k4 _$ U3 r% @. k- O% V" F' a" c+ z$ G{7 e- L3 {: Q( e5 y* k* V
INT        nBits = Config.sound.nBits;
4 P/ I) C  e0 }& g' q5 g9 V" zDWORD        dwLength = dwSize / (nBits/8);
$ ]* X( N+ }3 {/ WINT        output;$ X' h4 P: _7 A9 K  D2 S! i
QUEUEDATA q;$ S" K, V/ [. o8 B2 P' S
DWORD        writetime;* i" R$ d' A* l, G( P5 ]
! S* a& z7 H' R" j) Q
LPSHORT        pSoundBuf = m_SoundBuffer;
* s  c2 l8 i$ N% j  X2 a$ N5 [6 ^4 qINT        nCcount = 0;2 j1 C9 b4 w& K. i  ~

3 F4 d# ^; t% E* cINT        nFilterType = Config.sound.nFilterType;
" Y( O; q5 y; l$ d7 |8 Y7 [9 h7 {0 k4 l$ i1 {, [. X. H
        if( !Config.sound.bEnable ) {0 z* E: w$ w7 O8 c+ h2 k5 K% ~
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" l# _+ M* I$ s0 k; u/ X                return;
: Y# N( t7 [7 _7 W        }% w: c9 F' R6 z& [, [0 D9 y2 M
1 X( ]/ p" P" B
        // Volume setup
) F$ ]) g7 D# F3 T3 L7 P5 i3 d        //  0:Master
: A/ O# p! C1 v! o/ P2 O2 `5 \        //  1:Rectangle 1- H( w9 S8 Z: u2 H; b# [5 q+ }/ C
        //  2:Rectangle 2# b  F6 r" J5 n/ A: K0 i8 o+ h' q' V
        //  3:Triangle. D3 u. @, p7 ~' ^) g
        //  4:Noise
/ w: c0 j/ d# o0 q9 o6 Q; z6 Y        //  5:DPCM
' P5 p" u& a8 v; Y1 a0 H8 G        //  6:VRC61 P* T) a( d, i; r9 M% l9 y
        //  7:VRC79 Q4 _" G. Q* H7 R' m# B
        //  8:FDS
" h# K" k: a5 A  v        //  9:MMC5
' O& W1 `0 R! v0 w5 t        // 10:N106! K" O% e7 z. q, A5 v' w3 @! u
        // 11:FME7" Q& I2 `/ c* j: @% G% N* O
        INT        vol[24];
9 n4 W% ~) j- q, `        BOOL*        bMute = m_bMute;
8 w8 p) h8 a6 i8 ]7 @+ w: e        SHORT*        nVolume = Config.sound.nVolume;
* f3 Z5 m3 f& I& G9 w- w' d+ K& K- L4 i
! Q% ~4 s5 W2 A/ R6 z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;3 S' N  f1 `  R4 x( M

4 z: s2 V" M" r4 W        // Internal$ `6 |8 P. {3 J/ x
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
9 I% Z4 J! N' F& ^8 h" H        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
9 E* ]* m6 D. K/ U' Z        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
% ~! V7 B9 J: p        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 p' ^- W& k1 G
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 y* {/ y( o4 ^/ C$ ~+ s
1 s7 x9 P5 ~: h5 B0 j        // VRC6+ `, [2 S' i  \& E
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" y) X6 g  ]1 t! ?4 n        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ D: A  W6 w' v2 I7 Q  @1 y/ D4 G
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 D3 w8 _, b" v& _6 e4 K% N

, `, ~: S4 V- U7 |4 a        // VRC7' E5 d0 p. \9 c5 Q  q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, n- K5 k- `7 I. t5 m' G) w$ j9 y
/ ]  s  p& k% H$ S        // FDS
) U/ m7 D7 W  U4 _7 Q# o) |: R        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
. `3 ~% t9 H4 M7 I7 K/ ]2 g1 j( a/ t: ?' v/ G4 N. R- P
        // MMC58 e' M8 g- l4 O
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! c) I$ Q2 u6 u. ^5 i, @3 H7 s
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ n2 \: W2 \6 N1 n  Y$ q% v
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" F1 N6 B% Q. g! b

; a+ ], z" Q& ^1 _( L7 Y3 N        // N106
9 n# M# y" l) B/ _1 I# s2 x; _        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 o4 g/ i* n/ b# b( r; q& n        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 X7 f, q# n0 d& `9 C  h( \3 p. I
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% l: m. D! K2 c" W9 p        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 z4 n: B; G; P! K
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. ]4 u5 G' `" W! ?
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ n) \* I9 H7 x6 {  \" u6 `- z. F* A
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- r; I8 `5 v& l, F& T& O* d        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; ~' Z$ f9 V2 w  M+ p

8 u3 E, e. p! g) |        // FME7
# d2 i, ~4 g0 c0 M: `( s9 u        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 A( c, `# s' r4 Q" f1 h5 l
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 z8 b7 A0 }, G% L4 E- c  {2 C        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 r% {: N) N$ `7 t  C! B, u
$ Y1 B9 f6 q' n& X! T//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& l4 }/ {; B* o" F3 l' ?' ~7 Q        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: x/ [! t! k5 T2 ~- Z& \

2 ?3 `3 U8 s( |" W4 w0 `        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
* U% ^* K* c$ ]" b        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
, }  r% L4 Q) f* m4 Z                QueueFlush();
& d9 v5 O6 n. g6 N  a! f0 g        }
# d- W! C0 `3 H/ p# [# L) i% Z5 h1 ?# b& v& {5 P
        while( dwLength-- ) {
" `% ^3 C3 B# V( `- u' M% I                writetime = (DWORD)elapsed_time;
: U. P2 O1 E4 N" L+ k1 P0 {' @# A, @: v) g
                while( GetQueue( writetime, q ) ) {' H* t( J4 w, w
                        WriteProcess( q.addr, q.data );( V# j1 f! z- }! n6 s0 c
                }+ f9 J$ H5 R6 E5 Q

: W' J7 P* I* T2 d& j) q5 _                while( GetExQueue( writetime, q ) ) {# @% q- }( B8 b/ |. [
                        WriteExProcess( q.addr, q.data );
1 N# o- W* M, O3 r                }
& G! H. e1 Q$ \9 y7 d# @7 K: R' `
- ]7 d8 r; N% q' d5 e                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME76 d5 b7 e' O( B3 u  `
                output = 0;8 Z; r0 C8 S: N% J9 g/ c
                output += internal.Process( 0 )*vol[0];! e/ D6 S0 C; m& y
                output += internal.Process( 1 )*vol[1];: T0 X# ]/ [$ G: N$ X2 h
                output += internal.Process( 2 )*vol[2];& e* g( y; K, N4 c% \* {
                output += internal.Process( 3 )*vol[3];
  u) l& V1 I/ e                output += internal.Process( 4 )*vol[4];$ ^9 Z% o8 f: e6 `/ j
' p* ?% E1 a" h: |  |% F2 ^
                if( exsound_select & 0x01 ) {
9 {% D, E$ s" x! k* W. q                        output += vrc6.Process( 0 )*vol[5];* \# P& \  h6 [5 \" u% z1 W5 ]! S
                        output += vrc6.Process( 1 )*vol[6];! @' ^, K6 o( }8 D
                        output += vrc6.Process( 2 )*vol[7];
, o1 ]: ?2 q+ q$ G                }/ G) B% L' P  T! o
                if( exsound_select & 0x02 ) {
8 i6 S) q, x7 F7 d                        output += vrc7.Process( 0 )*vol[8];3 Z! P. I0 h: }; ~* f& V
                }
8 L9 `* m) }, S$ j6 t: {                if( exsound_select & 0x04 ) {
4 B9 ]0 i/ g7 }( k% ^1 y                        output += fds.Process( 0 )*vol[9];
5 D5 C8 T1 j, b6 _9 N& G$ b                }
, g3 |' R/ h9 Z- m                if( exsound_select & 0x08 ) {
. g5 b! W$ ?/ U, {                        output += mmc5.Process( 0 )*vol[10];( c# F7 V1 w; C- j2 G% R# p
                        output += mmc5.Process( 1 )*vol[11];
" E1 O, A, v8 w                        output += mmc5.Process( 2 )*vol[12];8 E5 Y( c, {- p
                }
4 ~2 B4 a  @0 j- X; }1 e                if( exsound_select & 0x10 ) {
3 T& w2 m9 V: j' y# B& e; M                        output += n106.Process( 0 )*vol[13];
. g# W3 F6 G# v$ E0 |                        output += n106.Process( 1 )*vol[14];4 [8 }1 \& J" ~0 V8 U! d
                        output += n106.Process( 2 )*vol[15];# \. S0 y4 s! [; I* u/ _
                        output += n106.Process( 3 )*vol[16];
9 ~, D3 X6 u6 D, `) U                        output += n106.Process( 4 )*vol[17];' K; N( a$ u8 y3 A$ z( V
                        output += n106.Process( 5 )*vol[18];! ], f3 Q3 g! o5 H9 |; L
                        output += n106.Process( 6 )*vol[19];0 o; n% p0 X& B! K* t8 a( T
                        output += n106.Process( 7 )*vol[20];1 U" V4 Z; d  v2 [. }2 ~! A
                }* m  K% h; r0 z" z# B* z+ L
                if( exsound_select & 0x20 ) {
2 p) I( @+ O( u3 X" Y0 p- a                        fme7.Process( 3 );        // Envelope & Noise5 g9 T% Y/ Y" A) c
                        output += fme7.Process( 0 )*vol[21];' b& x, `' C( ~+ }& A) X; e1 K
                        output += fme7.Process( 1 )*vol[22];
, b! c7 O' w9 F1 n! W                        output += fme7.Process( 2 )*vol[23];
# s& f) g* l/ @* |                }
( r, w& P0 `, f8 X0 K) c6 O: Z4 z  e* W1 \. `) _
                output >>= 8;; s- y3 H$ p8 ^- F8 {

$ [: I! O2 l& d                if( nFilterType == 1 ) {/ D5 N. J0 w6 G, @( ]. c2 l, W: C! R
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: x) F+ [+ J8 R2 G9 [# a0 w                        output = (lowpass_filter[0]+output)/2;
6 h1 w. c" T5 f6 w; g: F                        lowpass_filter[0] = output;
' M2 r$ v& S) x: s1 _( e                } else if( nFilterType == 2 ) {6 _$ I0 R: c6 F5 @$ W" m0 j: H1 `
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 `- R3 e* ?$ V8 ]' K
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 T$ z  l2 G) U7 s1 v4 t/ A
                        lowpass_filter[1] = lowpass_filter[0];
2 c3 o; G6 X& f: R                        lowpass_filter[0] = output;
5 ?6 Q' k" n# G! f                } else if( nFilterType == 3 ) {
+ g" p/ R+ P- \0 O                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)# O3 j! P3 S8 W) W! R: ]. c
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
  Y# [$ G5 o) h& ]* S9 c- u. ?: f                        lowpass_filter[2] = lowpass_filter[1];
1 @+ z) {1 [2 L4 b: [                        lowpass_filter[1] = lowpass_filter[0];
4 z4 y* H/ [* k; [                        lowpass_filter[0] = output;
# M  L: i6 m, ~2 \                } else if( nFilterType == 4 ) {
- F# w$ x2 ?5 C                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)$ m! p/ k9 W1 s( K1 h, `' M% H
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;7 M( w+ b! A- {! s$ l$ F
                        lowpass_filter[1] = lowpass_filter[0];6 T. R1 H( ~3 b( P6 @
                        lowpass_filter[0] = output;0 f. ]8 U! t2 r
                }
6 q, `0 X4 D0 K& T
8 E6 i8 [. n; k4 R) W: e) p#if        0
+ u2 V$ e* D: D. ]5 O/ a                // DC惉暘偺僇僢僩) o* m4 P, \9 d1 K9 a
                {* U0 I$ j; @- I' ]6 a0 }5 V
                static double ave = 0.0, max=0.0, min=0.0;
9 K- G, A7 o" ]7 V1 a2 g                double delta;2 Y& n, i2 ?" o+ [1 M  M/ X, J
                delta = (max-min)/32768.0;
6 Q% E, t, _, B/ s7 i: z; v                max -= delta;; }8 d" F5 Z7 B/ g0 K
                min += delta;3 ^  p1 N6 n4 g# [
                if( output > max ) max = output;1 d, I, {5 u; X1 X, _0 ?
                if( output < min ) min = output;
; R3 ~! ^/ @9 [6 |, K1 k                ave -= ave/1024.0;
0 Y: t& j+ _/ G4 o; P9 x                ave += (max+min)/2048.0;
7 ]3 U; R0 q2 L8 D                output -= (INT)ave;
: W5 j6 a, S% N; u5 H$ O5 Q: u                }6 e+ @. U! S/ a. o
#endif, \% ]; ^0 O/ N9 S- F
#if        14 D2 T1 F$ d; L9 `+ c- o
                // DC惉暘偺僇僢僩(HPF TEST)3 U' G+ J7 q( X9 K
                {* z- O  }; I) b4 D  ]
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 G4 O$ m2 }  H1 I) U0 D* W' K                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  q: v8 e5 L* v4 N                double        cutoff = cutofftemp/(double)Config.sound.nRate;! C+ V  _4 Z9 P2 l- b
                static        double        tmp = 0.0;" D7 W# c; a2 C- W5 N
                double        in, out;
* _0 `# @4 ^3 n; C3 u% `' p7 Q0 X
                in = (double)output;
, s6 y0 l  o' U- ?4 x, C% G0 ?5 a                out = (in - tmp);/ Y6 V1 Y4 y$ h" {
                tmp = tmp + cutoff * out;6 U% F6 k$ K( s

' }) U) ^0 z( T( P) x; a& h. m                output = (INT)out;
8 H+ D+ \& o6 j                }6 d/ r2 b3 e" e/ O
#endif' C7 \3 v6 q9 G2 R. [' O/ e
#if        0- B) h, r5 G  i  M7 r
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)9 |8 Y/ w  ^3 L$ `( r! G! v
                {
# @- T6 P8 f3 t. Q2 s                INT        diff = abs(output-last_data);
; g! w; y9 L% G, O0 G                if( diff > 0x4000 ) {
$ U5 ~! l! E" P: k. }! l: x                        output /= 4;& n( S( m3 ]2 @, ~' \" M7 G
                } else
4 m$ p+ \9 W+ I/ S7 C                if( diff > 0x3000 ) {) F1 l! S# V5 G9 r8 a% s; V. Z8 b
                        output /= 3;
- ?* y' ~9 p" m1 a$ Y                } else. x: N2 R: W1 u, r7 J
                if( diff > 0x2000 ) {% N6 d1 O6 e4 v% j& _8 {2 h8 V
                        output /= 2;/ |) S" @/ E* e. Q: [0 }1 m
                }
; P: Q7 y6 j' u$ ~1 G                last_data = output;
2 n# H) Q4 `2 r& `1 W                }& H% X2 w- N  W  ~! N
#endif/ N! |* ]2 N! E! T$ l$ ]
                // Limit0 u- w9 W, T# E( a
                if( output > 0x7FFF ) {6 g6 e) P1 q+ \2 k7 o& H
                        output = 0x7FFF;, }: R1 ^0 O% D; A! M% w0 O: D) K
                } else if( output < -0x8000 ) {. n3 r6 h# x  q
                        output = -0x8000;8 V3 u9 C8 j, O2 v- l* ]
                }- I* N6 u% \8 F# |# r- X" O( Y

' }1 B5 q4 d9 ~4 ?                if( nBits != 8 ) {
6 T0 @7 o. R1 B  {; ?+ P, b                        *(SHORT*)lpBuffer = (SHORT)output;+ C0 ?! _& r. t2 n  E$ r6 [
                        lpBuffer += sizeof(SHORT);( q! Q* a% q- u8 R2 V
                } else {
* K5 |7 ~6 s+ |; T8 O                        *lpBuffer++ = (output>>8)^0x80;/ i: ^. n0 @; E7 z( {' j5 w: w# B& T, |
                }
9 }! B7 U; j% E7 b' B  y' r$ ]* G
+ R, s* o$ g0 x, v" N0 D' O0 z) I                if( nCcount < 0x0100 )) C. {8 F4 r1 {
                        pSoundBuf[nCcount++] = (SHORT)output;! D5 c) X9 n* z  n2 ?
& |' J( T- Q; G: T
//                elapsedtime += cycle_rate;9 |5 B& D6 }8 ]8 l$ D7 _5 F
                elapsed_time += cycle_rate;* ^1 L, ^# v3 ~# u0 Z! s
        }
$ k+ Y- p* d5 I) l. Z5 t1 V/ F  J$ C! S% w  S$ j3 W
#if        1) H+ ^( W" E8 E+ |$ |* C4 f( W  W  T
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {& T+ U/ J$ J# i1 Y# w
                elapsed_time = nes->cpu->GetTotalCycles();
0 L: U7 W+ p6 p% e6 N+ A        }4 ]$ [* e) W9 `! s+ m, {. O
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# t0 x# }. m% U% Q
                elapsed_time = nes->cpu->GetTotalCycles();
4 y" F* `5 R$ C9 g$ ~$ P9 s& K/ i+ r7 o        }* R- n. D. b, H2 n. n1 o  c2 `
#else. [) |; ?2 e3 H! F
        elapsed_time = nes->cpu->GetTotalCycles();2 B5 q- ^8 G' a' Y. r
#endif- L# C5 B% v- q5 t( T
}% Z5 t: `6 ~9 F0 V( E

8 b  e* X" v% N, w; `// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
6 p; L9 A% _) S& q  v+ S, ~! X+ rINT        APU::GetChannelFrequency( INT no )
! d" Y( H) M6 V5 }{; p! |+ {$ _  p% E0 c/ B5 h9 Z
        if( !m_bMute[0] )5 B3 s3 d) Z. a
                return        0;
1 k$ ~5 I  \2 {/ E4 I3 u8 }8 ?  K" Q. |- _# G8 i2 E! m
        // Internal7 r8 T' n- C, Y
        if( no < 5 ) {  }' {9 \: v4 I
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
9 n; @5 f% m5 C0 f# z" n        }( c( G% w, [# |6 Q
        // VRC6' p6 w3 q- k4 L; S2 s: O) i9 w
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ a1 }8 I8 \. L# V+ M7 t
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;3 [) T# g2 H8 e" R8 Y
        }) q) U7 K' |/ N* k. D: w
        // FDS
; O! j9 Q4 E8 `, E. d/ o        if( (exsound_select & 0x04) && no == 0x300 ) {( k3 e/ b, x, I' [( F- r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# a3 c6 {; @* e& q  }. e4 \
        }5 X2 C1 `5 p) {  `5 O) w) G
        // MMC5
* ?) ~0 ]& c4 k. A3 P5 W+ y        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: h7 s: ~1 i0 b3 _% A
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
' n- w0 W5 Q" V* ?3 B        }4 @# r& Y0 y2 Y, Y
        // N106
9 m. o% E$ k, y* Y        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
$ L, [: ^7 [" H9 F                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
0 [: w7 Q/ M! Y0 o2 s        }
0 R. R2 z" \4 Z* @        // FME7
8 R' v0 O8 D. n/ O# K7 U        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  [5 M5 _  e/ m& C3 H1 F9 \/ ^                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
7 @* |# d2 E1 U3 |4 c7 t        }
& J% O# b! w/ S! _4 ^) w# @4 O        // VRC7
' G. o( }" G" W# v9 G        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
1 P. N: G0 S+ _: G/ \' `  p                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 x4 p- x+ p! A9 _+ V6 k& R        }* p! {& g8 a3 |4 N& S; l8 q
        return        0;1 i) @  ?: Z1 r& L0 D( C4 q, Q& V
}
! L( a2 G* s' i0 M2 y0 M1 Y+ z/ |0 Y6 {7 v0 \7 s4 Q
// State Save/Load, f/ ?* r( z1 s
void        APU::SaveState( LPBYTE p )
4 Z. M) q+ |$ V0 m0 J{2 K; x# w( q4 j! ?5 W
#ifdef        _DEBUG- j8 r' E  u: J7 M) Z' j* I8 U
LPBYTE        pold = p;
6 I$ H* U; G- z) p0 r* O9 ^#endif
+ s) E9 G% x' D4 L4 A7 g0 E9 m+ Y9 w! R  Z; d
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! k5 ~; i" {2 H( [. {        QueueFlush();
  m* ?* G) t, C  s) [) G
2 F% _% x( Z9 o! [  d7 m* i' z        internal.SaveState( p );
7 s/ @, Y- K* F! J% L        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! {5 h6 L0 @, k8 C

+ X3 O7 ?4 R: w        // VRC6
; E" j+ R+ l) x) Q2 \8 F        if( exsound_select & 0x01 ) {
' h: \0 `. r2 t: E                vrc6.SaveState( p );# B2 T& |* Z/ m0 H: E
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; N2 t" |4 i' F  J2 `
        }3 z0 x9 K- i. L4 B
        // VRC7 (not support)) ^3 Q4 I6 o+ U7 i) t8 u* o
        if( exsound_select & 0x02 ) {3 y0 ?5 g6 _# X8 m! S' V
                vrc7.SaveState( p );' [  Z+ B- L' t2 K( L
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& {% f) V$ I3 g, V8 h        }8 c- Q$ ?* Y4 I" L1 m
        // FDS
3 @' S# E1 G+ m% |! L$ W9 J        if( exsound_select & 0x04 ) {
3 \! T( R. W! n1 B5 {                fds.SaveState( p );5 q& V+ p0 @: `$ M5 ?' n. }9 O
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 E$ J* v$ _2 J: o        }/ S. S% F, @. T/ e
        // MMC5/ T1 d( ]2 k# ^" W0 k
        if( exsound_select & 0x08 ) {
: F. h, @  N+ x3 H4 x                mmc5.SaveState( p );
) b( Z, V9 u8 F# m8 h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, u0 ?( V% R1 @. K. X
        }
5 i, u/ _  q/ t( D& o        // N106
+ G1 z) s! G5 ]" S7 g% \        if( exsound_select & 0x10 ) {6 e: Q0 v( s  d, j5 a) ~8 j5 q( _
                n106.SaveState( p );, Y+ r, i# R2 b0 v, `( k: E2 x& N
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! o6 q+ F* ~. o. f' w! v9 Q        }
6 k# P. k3 n( C$ t8 f. V& n5 D5 w        // FME7* S) g" J. I7 A0 m( F$ T: V
        if( exsound_select & 0x20 ) {
  m% F& S" e* ]0 B( o" _8 H: o! K                fme7.SaveState( p );1 \& E; S" `9 j. |+ ]
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
1 w8 _' t' l" n        }% K9 X& i5 F7 I, N3 R
( f2 f+ q! o  s. J
#ifdef        _DEBUG
7 ]- O5 x+ W" n& \3 ^- D' p* h, uDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! z4 J+ T% O0 A* z' X#endif. C. v3 w# B0 V7 X2 K  T
}9 ]$ Q" D8 v/ h5 ?' e5 Y

" A, e3 R& H# m" Zvoid        APU::LoadState( LPBYTE p )% k& h+ @, r' [: s8 J
{5 m* `/ y3 }* x1 w
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡) ?3 J1 w2 Y: y0 B4 A. \! a4 t
        QueueClear();
' p! w! _. v, I- h
+ K! x2 J( @' H        internal.LoadState( p );; A) H4 `3 b: b: a0 {
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 \. t0 _) m8 w! w4 ^
8 Q0 y4 y) L+ j) r: V6 x" ~
        // VRC6, D. c2 \& O5 f9 n' @5 b
        if( exsound_select & 0x01 ) {
4 I1 ^" Y& W; o- b4 q# }. E                vrc6.LoadState( p );- C) w2 Z% m. T$ }9 A& L8 `/ G# d- _
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; ?- O% q1 M4 {% e  L+ a
        }
9 P! b" P# |& B1 ?+ C        // VRC7 (not support)
9 T' Y3 K8 ]1 D: w        if( exsound_select & 0x02 ) {0 I5 o+ u+ d( x
                vrc7.LoadState( p );0 g7 @0 N2 J/ v5 b
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% p& v0 X) V' {2 ?+ S        }6 ^  X2 `5 u1 c
        // FDS7 E2 j3 t$ ^8 q% K) _
        if( exsound_select & 0x04 ) {) N. D5 S, L. x9 A$ l
                fds.LoadState( p );4 q' t- H8 v; X( h: j
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 W3 S6 g: k# u; b
        }
! p/ [& z) Q; n/ y/ a        // MMC5
' U* f6 A" v" b5 h& s$ |        if( exsound_select & 0x08 ) {# B/ G( P, d' {4 r
                mmc5.LoadState( p );
7 b  N7 G9 p9 v, ]% B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. G4 |# c  }. B' V  m. {; s) {
        }
! O+ E. c: A( A/ V3 P        // N106! U: ?  d0 U9 g5 B( A& K. G( ~" L
        if( exsound_select & 0x10 ) {6 T( t- G" i. @3 [0 V) C4 ~
                n106.LoadState( p );
; {9 k- h1 i- H/ a& [4 {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 Y: T2 I' {8 z
        }2 M; _2 u" g' N2 }8 g) O6 u: ^" ~
        // FME7
& @& O( ?% p5 Z! }' P% A' N        if( exsound_select & 0x20 ) {) [2 R' E1 t( |: W; L# i  z8 _
                fme7.LoadState( p );
) C* @+ O3 r4 K8 U4 D0 v* B8 f" Y( ^                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; [7 X& n2 L4 ], R' k$ N) d* @. J        }- e% ^+ c9 b- P% z- B6 j7 P
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
$ v- j( a$ W, Q  Z$ g可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' e& u8 L  y+ U7 O感激不尽~~

  }; Z3 a; k$ z恩 我對模擬器不是很有研究,
" G! m# P6 m; b; ~  W/ \雖然要了解源碼內容,可能不是很困難,
4 v* D( r: U/ ^3 A* X7 V( }不過還是要花時間,個人目前蠻忙碌的。
7 ^- Z1 W7 _0 K: d3 c3 ?% U# r/ h# V0 Y) M9 i- `
給你一個朋友的MSN,你可以跟他討論看看,) I, H1 ^! x9 F
他本身是程式設計師,也對FC模擬器很有興趣。/ c& I6 E, `- G# J' W5 `2 p
, z: P2 e! K5 V7 p: T
MSN我就PM到你的信箱了。" y' e7 X- p: I/ b0 V
5 g: `# S) c5 V4 K3 L
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 9 ^" l, [  B+ e! N( ]
呵…… 谢过团长大人~~

$ X7 s& L  {) `" O! z& ]) S/ ?' M4 P+ v( Z  v$ @4 f
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & W5 j- {0 J9 k: j
团长的朋友都是神,那团长就是神的boss。
- {: B  S, I; z: M0 N
哈 不敢當,我只是個平凡人,# O" _# |, o' f& H& G' |! S
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
4 f, Q6 M  @- o4 c/ HZYH6 r2 J. O+ k6 g5 j
QQ:4147343065 D: C. R$ g2 `; W7 o* N+ N2 u
Mail:zyh-01@126.com7 m$ D9 B! ~8 C% a1 n* j
- `. ~5 u; x0 O% M) Y5 N; d
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 / S0 ?$ {/ `% O/ L+ [, v  l! K2 S5 T
再次对团长大人和悠悠哥的无私帮助表示感谢~~
( x/ y# i* z5 x: G1 F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-12 06:18 , Processed in 1.086914 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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