EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; q' r" E7 A( {6 @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. I* l  H- m0 ~/ a: _这里有相应的模拟器源码,就当送给大侠了~~" N; `, w; y- C8 F( R2 g8 {* ?
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 - O. {" [( v- v* D" `9 X' B% F
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: K0 `: g2 \  m) a% \! m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& o7 U" H* q" e
这里有相应的模拟器源码,就当送给大侠 ...

' T6 f& V& ~) A1 r$ l0 `6 ]/ e聲音部分(Audoi Process Unit = APU):
/ m( ~% P6 g- U/ Q+ f7 C.\NES\APU.cpp
6 R/ w+ V0 |% L3 K# Z0 v.\NES\APU.h+ C$ b$ ~& h# x2 M2 W" Q

4 O0 W  `% O% r$ ^4 a' T' y, k4 M
, [# e, X  j4 f$ e5 E影像處理部份(Picture Processing Unit = PPU):! y7 }3 {+ Q0 k
.\NES\PPU.cpp' J& ]8 f! q( B  B) H! p5 R( J; \, ^+ a
.\NES\PPU.h
$ [8 l3 j" O  y, q. X2 L! u- Q3 V' c4 P7 z( p# F& r
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 a5 h: D( s( I(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 e2 w# B3 D; T. ]/ p2 |//////////////////////////////////////////////////////////////////////////
7 M* M! r) Y. t2 U4 a0 A: d//                                                                      //
; p  J) R, S" I( K0 i$ C5 ^//      NES APU core                                                    //
/ v8 m* Q7 w$ f6 B( r" \. X//                                                           Norix      /// _5 R: L  o) _5 E7 C
//                                               written     2002/06/27 //6 `2 v) E" E: ]- |. W
//                                               last modify ----/--/-- //0 h& P3 o3 p# z1 u. `# G
//////////////////////////////////////////////////////////////////////////
7 a. J2 l- O) O) j7 a) `#include "DebugOut.h"; Z" o  p4 Q4 u+ ~
#include "App.h"; W" D* x8 Q# m: d+ L
#include "Config.h"
- s: V5 r% J) H/ _- Z; v: E
( K7 b( j' K6 ?# R#include "nes.h"- L# w; z. x2 a8 t' Q
#include "mmu.h"3 }! ], E/ O$ p
#include "cpu.h"
! M" ?  k2 \8 F. q7 g#include "ppu.h"" H8 {, S3 Y" m
#include "rom.h"; B: ~- N. g/ o" u1 f' g
#include "apu.h"* }. r0 o$ g  G9 g/ c

" q( I5 b  X% q$ @3 X# C9 Q1 U// Volume adjust& Y& W& h9 w, }2 W
// Internal sounds
4 z9 f8 a% m) w1 ?4 g+ T: S#define        RECTANGLE_VOL        (0x0F0): F7 t4 _+ i6 ^* {8 Y" x, _' D
#define        TRIANGLE_VOL        (0x130)
7 h" N$ d- _( M" S0 J: D* H#define        NOISE_VOL        (0x0C0)1 D. }& {  j; U+ U' Z# E/ u2 d5 J
#define        DPCM_VOL        (0x0F0); ]8 |0 X# x- a/ V! v6 X+ l  x( x0 F' |
// Extra sounds
$ C8 ]; r' U+ K( u#define        VRC6_VOL        (0x0F0)4 o/ C' ?6 p2 ]
#define        VRC7_VOL        (0x130)" u, H5 p+ m) J3 S$ a1 j) c9 O
#define        FDS_VOL                (0x0F0)
1 n4 W; G- ]; i- M$ U#define        MMC5_VOL        (0x0F0). H% I; B8 D/ I1 m! z/ T  i  }* b
#define        N106_VOL        (0x088)
+ U5 _& K( G- J/ N. D2 y; c4 F  C#define        FME7_VOL        (0x130). c1 Y+ Z7 \6 s' D. t9 m, E

4 P  C3 g% d. h3 W5 ]( b! BAPU::APU( NES* parent ), }: X% o) j: W, h# `
{
4 T0 \: K" t. ]        exsound_select = 0;) ^" |3 [& ~( R* C
5 m. S7 n5 Y! H& B- ?
        nes = parent;/ W, W, {7 [9 g8 A
        internal.SetParent( parent );
2 B1 K1 V/ Q3 ?. o2 k- k; `1 B7 f! |% z
        last_data = last_diff = 0;
3 K& d  J; a+ f# E9 `4 `5 ]- M# I. c' S
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- N: p! x" N- d

8 X' a+ D* S% l, ~1 z        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
9 J& x" v7 s. K9 \2 v1 P0 Y/ \        ZEROMEMORY( &queue, sizeof(queue) );$ z( u! N$ ]7 K9 P6 [  X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 d( E; L7 x. ]

' E& [; t9 T  N9 E3 _3 _3 C        for( INT i = 0; i < 16; i++ ) {
. \; j$ m( @& c# W1 K+ M                m_bMute = TRUE;
3 O7 E' P) ?2 U: f$ J( Q1 J        }
7 i8 O, S& Y* c, X}
. v2 n2 ]) p; ~* G$ _- D5 |
, v6 u4 c6 X, I2 U+ w9 c2 ?APU::~APU()
' G7 }  H4 O0 c{2 X3 c8 U% R# w. ~0 m) Q- J
}
4 c4 x" S2 S/ r0 O" e
1 q3 {% t- R4 \: G, Fvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )9 g8 @: E$ ~+ a; Z
{
  b9 ^& \7 _9 E+ `3 A        queue.data[queue.wrptr].time = writetime;; r% u: w5 _1 b; `- ?
        queue.data[queue.wrptr].addr = addr;
) j& n3 Z6 W' D! \        queue.data[queue.wrptr].data = data;" `5 X6 C# t" n( @7 J/ }
        queue.wrptr++;9 Q: T/ K1 }4 E
        queue.wrptr&=QUEUE_LENGTH-1;
/ p% Z6 h+ e: _& U        if( queue.wrptr == queue.rdptr ) {
8 b. J' _3 f" S+ w# ]+ W. W( r                DEBUGOUT( "queue overflow.\n" );
! T& ~; ]( C6 H" t6 Q6 V        }
+ i8 R. l* X, E# N. \1 B}5 |  I/ X. w$ ^# ]8 h* V

5 _; M/ Z+ F2 ]. l" o0 r* `BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
6 e, w& k( Z# x6 G% h3 O% V{
+ h$ U: {& O2 D5 T# S, k        if( queue.wrptr == queue.rdptr ) {( H. e+ I* H4 B' o
                return        FALSE;# c2 G8 c$ ^: f0 s4 z0 m
        }
/ K( h% v& L" a* i. u/ G; }4 A        if( queue.data[queue.rdptr].time <= writetime ) {# v/ l/ t: p) @2 v  i6 e# y/ Y
                ret = queue.data[queue.rdptr];
. x5 ?  A9 Y* y$ n) q" c                queue.rdptr++;+ [$ S  Z; t0 {; ^& G5 Y5 V
                queue.rdptr&=QUEUE_LENGTH-1;' @, s/ ]1 I$ F: [
                return        TRUE;; z* k+ ^& U, Z0 h1 K, j" N. h
        }
9 ^, P# v) h4 u5 P& F        return        FALSE;& |$ j  |& H' L) `( ]. w
}9 G5 f3 l; }+ b' W% Q) x7 T' v

. v6 z6 E# ~/ @) i- svoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ). o* H9 m3 L( ]
{
- s7 i4 o, V" _        exqueue.data[exqueue.wrptr].time = writetime;$ R% @+ R4 h, |
        exqueue.data[exqueue.wrptr].addr = addr;
4 }9 O& q8 ^1 Y        exqueue.data[exqueue.wrptr].data = data;% Y" C9 m/ z3 U; d) i' C0 w+ z
        exqueue.wrptr++;' X7 y/ T' j+ [8 w# o3 t$ W
        exqueue.wrptr&=QUEUE_LENGTH-1;9 g+ d' J: ^- T' @6 z% |* J
        if( exqueue.wrptr == exqueue.rdptr ) {6 T4 y5 b% V9 A* N
                DEBUGOUT( "exqueue overflow.\n" );8 N) b& s3 g1 W
        }
$ @" `) c! E' `- J' [1 w! g}% }2 i, q7 o6 x6 s) w8 m* s0 M# J
* h/ D3 H" A8 n1 N# p) b1 ?
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 {% H4 }( ]2 D$ a0 [{
$ I6 J4 D7 B9 V" d6 F! R        if( exqueue.wrptr == exqueue.rdptr ) {+ V4 W3 s$ w& E. t5 L! j; A$ a
                return        FALSE;. y+ \: x/ k: E+ V8 W$ n% N! Y' Q5 ]
        }
! U: k; Y) G* l) {& D/ _) v* F        if( exqueue.data[exqueue.rdptr].time <= writetime ) {! z% R: ^! Q5 r) `$ i" K
                ret = exqueue.data[exqueue.rdptr];
* B5 q3 Q* l1 {& v+ b- \' I2 ^# ^                exqueue.rdptr++;9 P; _% V* m$ L( N. p8 c
                exqueue.rdptr&=QUEUE_LENGTH-1;3 N2 l1 g5 E. E) z$ T
                return        TRUE;: h/ D4 g% n2 l! L9 {
        }
" s- C& h' N3 {- I        return        FALSE;
7 x- \! S. l1 z* s7 F& Y}4 U7 Y2 s! `/ Q" J) G, z
2 t# G0 g1 ]7 `9 X
void        APU::QueueClear()
$ b8 x, }! S3 k" A5 _& `{% M8 P; {( h  v" B9 P0 q
        ZEROMEMORY( &queue, sizeof(queue) );
  M0 |7 J3 O5 H0 X        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 f8 n; A# Q3 a: ^}- Z1 b" O, Q/ x  z* n" V
( F7 [7 n$ t- I
void        APU::QueueFlush(); H+ U6 L2 w2 o8 \" o
{( r9 w2 u1 j: v8 X
        while( queue.wrptr != queue.rdptr ) {# o' ^$ x( g: S6 J, Q
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );1 }8 ]$ ~7 T5 M% h# I
                queue.rdptr++;2 `2 G/ ?; u% v1 Z* ?7 I9 _( S
                queue.rdptr&=QUEUE_LENGTH-1;8 Z( P. I3 P9 W
        }
# U( f+ m8 h+ y4 n3 L! a
$ j9 Z* J  {. p: p        while( exqueue.wrptr != exqueue.rdptr ) {8 k# L1 @3 e' m! Q, a
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 O# o- B1 r4 ^6 K. w6 Z2 q' O                exqueue.rdptr++;7 t$ J* p3 P/ W6 M8 s1 n+ X6 x5 O
                exqueue.rdptr&=QUEUE_LENGTH-1;* B: b5 _6 `* R: x
        }
* E7 c6 k( E1 z+ a8 ]9 q}
4 B* o5 q! w) o% U7 F) ^4 ~/ X1 z/ _; `. `2 e& M
void        APU::SoundSetup()
& k1 h& P  N7 p( j{
8 e8 e5 m0 ^+ Z  P' f- b7 n- k        FLOAT        fClock = nes->nescfg->CpuClock;" V( c( D4 U) E$ q
        INT        nRate = (INT)Config.sound.nRate;
& T' O% c! c2 u( Z& T" k4 i% p        internal.Setup( fClock, nRate );
3 K% J; C. w9 d- o$ `$ `        vrc6.Setup( fClock, nRate );* M6 W& @0 N# F4 `( S
        vrc7.Setup( fClock, nRate );% f* g# ?5 u) }
        mmc5.Setup( fClock, nRate );! d5 v2 C) f4 X  c  Q7 f1 J, _7 i& R
        fds.Setup ( fClock, nRate );
7 T4 c2 F7 M9 b9 h  G- \        n106.Setup( fClock, nRate );
' n' E5 M) h! o, {. [, d        fme7.Setup( fClock, nRate );' H; }4 f$ s1 r0 ^/ u6 l5 x5 }
}
, R) [5 a( q! g* F2 ], H2 o0 P, q
+ q7 T& ]5 Q: c7 ovoid        APU::Reset()
& Z. w7 F& h, G, F" r- y/ }7 ?8 ]{
" |; _( o8 @& t1 v+ d        ZEROMEMORY( &queue, sizeof(queue) );
7 H) f: V6 `& d$ c        ZEROMEMORY( &exqueue, sizeof(exqueue) );. E$ F4 ~' E2 _' E& ^

' k/ g. O- V" n6 A: M        elapsed_time = 0;1 A, m$ S9 M: `. o0 q$ F4 x1 @
/ e' L  _% p- |6 |; A- Q0 n1 _
        FLOAT        fClock = nes->nescfg->CpuClock;
0 T1 j- N! B) y3 H/ O        INT        nRate = (INT)Config.sound.nRate;
/ u# r& Z. X0 T1 u; \6 ^8 }1 [& F        internal.Reset( fClock, nRate );
5 h7 B7 e8 R  Q0 _5 `) ]        vrc6.Reset( fClock, nRate );
, z6 e8 p4 T' z5 b0 g, ?        vrc7.Reset( fClock, nRate );
! S% S3 w  A% u( T  E        mmc5.Reset( fClock, nRate );
2 w, n" R$ s  S" T# q, F- v# ^        fds.Reset ( fClock, nRate );
& J0 f- D5 {! l        n106.Reset( fClock, nRate );) L8 d# R/ e# L; i. K; a& E; x! x3 h6 Z
        fme7.Reset( fClock, nRate );7 ~7 z( {8 e! E1 }8 H! V
$ q" }0 E6 i. e. G$ p8 u# g
        SoundSetup();
! V" m, G7 |7 {+ x}+ t: _+ z$ F, |% ^' Q& D* [4 |8 w' s; Y
% i; i, c% }, _+ M1 q, S+ G, h
void        APU::SelectExSound( BYTE data ): g* |/ i3 e, [+ H- w2 ^4 p
{) J( N. I( j1 u
        exsound_select = data;  d% }0 \' w" ^
}
$ z3 _" C& l3 S7 i8 M* r- I1 J; Y' B' S7 j% Y
BYTE        APU::Read( WORD addr )# n" }8 P  {! B9 T& Z
{
' r. _6 ]5 G/ T% c! T        return        internal.SyncRead( addr );: p3 ^8 `3 V: s7 d4 G# j4 b8 @- Z
}% P; B0 o+ x* p$ j
6 h' W1 t( h2 |3 o  y" P
void        APU::Write( WORD addr, BYTE data )
% s$ e' B; a( J, j4 Y{+ M2 Y6 y1 V3 y. G
        // $4018偼VirtuaNES屌桳億乕僩( _6 B/ \6 a0 @8 M( ]
        if( addr >= 0x4000 && addr <= 0x401F ) {
2 T2 V! C) f8 E3 {                internal.SyncWrite( addr, data );3 K, s0 }) o% {' w8 w5 d  b$ y  Y0 P
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
* ?+ Q; Z, a# W6 \        }0 X0 w# ?1 y$ W: |* z2 V: x6 h! P
}
5 N/ R. L# S% F5 z3 Z5 z, |7 J; U/ P0 ~, W8 Y, _6 g9 Z
BYTE        APU::ExRead( WORD addr )
' b# p* ]8 S  _5 [0 i{# d% C+ r; I. P4 k' V1 i* G3 B
BYTE        data = 0;
  e& N2 ?+ h0 a& v; ^/ K' l
: o! I1 O+ Z& c7 v4 h  x        if( exsound_select & 0x10 ) {  D( H! t, H  z- M4 n+ ^3 ?) X  ?
                if( addr == 0x4800 ) {
' q3 g3 P" Q8 \. z/ b                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) a2 \2 I" Q6 s& O4 j                }
# h) c% r$ k1 k& [2 h        }" ^3 Z  k5 j4 M, e3 C% Q% W) E
        if( exsound_select & 0x04 ) {
: i; q0 [5 t/ Q' a4 i+ h                if( addr >= 0x4040 && addr < 0x4100 ) {% T1 c0 {0 J9 n
                        data = fds.SyncRead( addr );% m! p4 n$ Q. [% q/ j7 ?# V
                }
3 K; ]" b/ h5 r" {" D8 Z6 }        }& j% T' W( ~; Y
        if( exsound_select & 0x08 ) {' }8 d( I3 ?; {4 e' O- w4 b
                if( addr >= 0x5000 && addr <= 0x5015 ) {
4 C7 O0 }( S3 w' C, Z3 }0 ^                        data = mmc5.SyncRead( addr );
/ A+ N! E9 S* R) p/ E3 X6 i- I                }
, g( F4 O4 W% O        }8 \8 M  y9 w! Q! t9 e* \
& o5 M, e/ c0 d. C: H7 m# }
        return        data;- Y5 N: C8 l8 Q
}; F) R" F- E" d2 [( M7 c: Q* L
* ?/ ~) M$ b$ S7 y' w! K
void        APU::ExWrite( WORD addr, BYTE data )& T" C0 G. S+ M  d2 W$ ^
{1 J7 s: T- [8 R% L
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );" {8 X& Y7 e/ c- t8 \: D

1 I- s- W* N) [- I& K% Q- d8 J        if( exsound_select & 0x04 ) {
  `$ |9 @5 m9 x3 F6 v' Z                if( addr >= 0x4040 && addr < 0x4100 ) {7 x0 O$ o8 A, G% i
                        fds.SyncWrite( addr, data );
8 f# \+ w0 B" e0 I& h0 ?                }
3 x& _3 e2 M1 \4 y- C. ]- m3 _        }
" e2 }8 ~$ g7 w4 |: d2 P
  e6 S) f( S, ^* s        if( exsound_select & 0x08 ) {4 a/ S2 R  e3 Y, ^' W( o1 G
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, m4 K' f% F- E9 U4 {: v- e/ x                        mmc5.SyncWrite( addr, data );
; |4 ?' W4 Q- _2 s6 P                }
3 V6 n. `4 e! W$ a  X        }
- ^) ^0 d- i5 [$ x" C3 }1 y& \}3 j! `# @( X; B+ {; V

: E. {) @; h8 j% avoid        APU::Sync()0 G6 I* ^6 s3 z9 u( p
{  p! h- r' d! T5 h$ {4 j) G- l
}
: y! J, m1 h0 r$ \1 l0 Z1 |1 E* C7 O3 c  o, U" \
void        APU::SyncDPCM( INT cycles )' P: S6 U- a# y) Z1 m
{
, B' U8 R- Q4 ], n  U4 {! h- C        internal.Sync( cycles );6 `3 ~9 `& R+ s1 h* H& @
( f3 f5 k/ z5 t: j8 B& f0 t5 d- R
        if( exsound_select & 0x04 ) {& y1 O* o% q3 T( N! U4 _* c: b; T
                fds.Sync( cycles );
" p) i4 r+ }6 X3 j% M  P5 X5 u+ V        }7 Q  h9 N( t" I+ W
        if( exsound_select & 0x08 ) {( ^% N0 ^) u0 x) |/ A9 [
                mmc5.Sync( cycles );& G  x) p- }, D0 o
        }  J: L& P8 |  W5 H- `
}& t$ Y- H$ O9 ]( F  d8 N* X: R
! O: n0 P" ^) e* `
void        APU::WriteProcess( WORD addr, BYTE data )! Z0 x5 u+ R6 H! C
{" t' ^! ]7 F% b; N& G9 x
        // $4018偼VirtuaNES屌桳億乕僩  n& j! z4 v" R# P) k+ e' V
        if( addr >= 0x4000 && addr <= 0x401F ) {8 N& n4 B4 W; I" T0 G
                internal.Write( addr, data );
! N; f0 o6 c' A& n5 C- S, E0 M        }
6 u4 k" Y! j+ q8 h: I2 ?}! ]: F' K7 Z- m, L* {
. B. u4 Y; l, Y- L/ e% j
void        APU::WriteExProcess( WORD addr, BYTE data )/ Z2 s+ l9 e! g  Q% b
{* X) t& o' O" A! ]7 v) y: w
        if( exsound_select & 0x01 ) {( j2 ?9 X9 E2 Q( N, z0 F) Z
                vrc6.Write( addr, data );
" G& h  u* f& j8 Z        }
0 Y# F  z6 f4 \        if( exsound_select & 0x02 ) {  k9 e/ t! G# i: }% K
                vrc7.Write( addr, data );' ^" F- @# ]' V" q6 y3 x9 J/ q6 \
        }; L+ b" B3 ?5 j
        if( exsound_select & 0x04 ) {
9 x) _3 p6 O7 {% b                fds.Write( addr, data );4 k* ^: |- K% m5 |' U2 C. R; q
        }+ R9 M/ M0 b1 ~! h" u3 J; ?- [
        if( exsound_select & 0x08 ) {0 d% s; e6 s* r) r3 ^* ]) \
                mmc5.Write( addr, data );
, [/ Z' J, t7 Y        }! R% z4 P% b: i8 O- \: x' ~( B. _
        if( exsound_select & 0x10 ) {
; c, x4 \) V& A; M                if( addr == 0x0000 ) {4 }) f+ D, _' l' ]2 X
                        BYTE        dummy = n106.Read( addr );
# P9 u$ q5 h; o$ s                } else {
1 @9 A) h, r+ t+ P1 K: \* Y                        n106.Write( addr, data );) t3 r# w, N' q
                }
. G3 \. u. [9 A; _7 ^3 H        }/ _& U* z  Q* {2 o3 x$ ~" x0 n
        if( exsound_select & 0x20 ) {4 d+ W  s! A' w' g" ]
                fme7.Write( addr, data );. t/ A# g* p; [" B
        }
8 `7 Z1 B8 s. S! X6 x. N}
( K9 Y- u3 _1 r9 b" E0 P" C( @/ n& W7 K+ Y# ~2 f. S
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )( u6 e  M' J5 M$ N1 u9 C6 W6 D1 V  {
{. G8 m# L/ ~4 Y* Y8 F
INT        nBits = Config.sound.nBits;+ J" H0 v/ f4 M* Z
DWORD        dwLength = dwSize / (nBits/8);1 Q4 u6 k8 {3 K/ s. R: @
INT        output;
0 O) [. Z, C' T" v0 {. K& mQUEUEDATA q;+ k: ~9 w' K* f5 |
DWORD        writetime;. k# h, w- r- W& ~' N
% G3 _9 @% C+ x6 C5 l
LPSHORT        pSoundBuf = m_SoundBuffer;
( j; ~5 p* T4 J! M3 UINT        nCcount = 0;
" S1 G7 J% j, c! R' s: C8 y; O' f9 ^6 r' F6 `) j
INT        nFilterType = Config.sound.nFilterType;
$ r, Q! ]# d; z; T" S/ _9 M! t2 P
3 Y0 z( _% K  s& u        if( !Config.sound.bEnable ) {
- Q2 b& f! w' [$ f/ @% n( T$ Z                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );1 H; C% I* J! u9 c* U6 ~5 D; ?
                return;. k9 v2 H+ u( A1 g
        }# ?+ l0 i) K1 f$ u$ w  H/ a

% t7 h7 o$ I  Z        // Volume setup
) g) P# {0 r2 q: J6 s* ^, I$ n        //  0:Master
! J. L7 E/ _4 x3 w2 _( V        //  1:Rectangle 1
# y- q% T0 J' R# L# o        //  2:Rectangle 2
0 C3 C; z) H% Z- N; Z, W* L& t. i        //  3:Triangle
$ O  P$ u6 t, \" M/ Z4 q/ H        //  4:Noise! M4 p, _# e0 S! r
        //  5:DPCM1 c- q& Y' l& u6 P* B" E
        //  6:VRC6
4 G0 ?& M! M: a/ B0 _        //  7:VRC74 b$ c' r! ?  z( a( k+ j/ k
        //  8:FDS# C( J3 x9 F  m
        //  9:MMC5
4 M6 X2 s7 H( F( l. Z" p        // 10:N106. E% ~- e' w) f' n
        // 11:FME7( I, W5 |( a  r/ l1 i" o) b8 z( H
        INT        vol[24];
$ K3 u4 |) w, l& D" j        BOOL*        bMute = m_bMute;
# ^; [# d. C- a- w+ m9 q( b        SHORT*        nVolume = Config.sound.nVolume;8 r5 X6 Y: T* K

2 ]7 x) L  k& M0 `5 `' H        INT        nMasterVolume = bMute[0]?nVolume[0]:0;, y7 S: q1 a1 l2 E2 R5 E4 R( |
  |  t$ o  k( L% \/ w# K% P
        // Internal4 D% B" B% c8 |6 O7 u  \2 @
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
5 g+ c" q7 h& U. F+ z1 z& g        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' h  b2 s9 w& B1 A/ T- F' `3 u        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
, [, [& a: Q9 l) t& Q. \        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
/ y, M7 Q2 b7 a4 }# g        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;" r" Y( Z1 R0 @: H9 g
$ j0 a% _9 h, ~% y* x
        // VRC6
- J6 ]- Q7 @4 k( R) [( \        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) q7 J9 \6 K9 D$ c6 _7 l) k
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 b8 \3 Q/ d4 E1 i; h. m( |
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) C1 g( j" g. ]
' b  l, D  [$ V4 d  Z* c        // VRC7
9 u, h0 e) @9 H" d6 f; J4 y        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  O' e8 J; f) _; q9 a, e" [& }% |. P' c$ W$ `7 }* K
        // FDS
* x: Z+ b* Z" P! N! h& `        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;4 ~# w1 Q# a3 ^
( I4 O" J! s4 W/ {# t
        // MMC53 R* e2 o) P" v0 ^9 O, N
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 ?- g* m  Q/ |( o; K0 ]+ Y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: Y" o: D# s8 Q! v
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 x; w: E+ L/ y4 R/ o: f
8 C3 U. C" J, j7 S- K! Y
        // N106
5 U  W. \6 }( H% [( }$ L7 c        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 W: G4 n6 Y2 `3 P( t! C/ \        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 G5 [) I( X( K' p- U6 j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 I1 h, [' _, R4 H  I4 E; k        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 T% R' E: Z$ T& d6 \        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& F& A! |0 J; a' a$ c  e
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& z( _  y0 [. t( _! q% s        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" W& [* b1 J% D4 B1 R6 c
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" G  @6 C" k* t: k& ^4 {" J6 [6 G8 i

1 ?; a& y* K, W3 J5 T& M0 l        // FME7- ]9 [8 n8 ~% s0 _" i0 S8 H
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 `, l' k, r1 w5 c! y0 T. I- i1 M
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. w, f8 {! T6 q1 t
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ W8 g4 G6 l" @" m6 n
- a/ }6 l3 F! [8 l5 {, m" y) A0 M$ K//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;% D# i- A0 ]! {& l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
$ U& ~, |8 q/ n; d/ e/ Z) L- V
, I; n! o% z1 g: {& L7 F        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ v% I. k( Q- A        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
* E$ N# S. X4 C( ?' s, S3 I" r                QueueFlush();
7 y' Q6 m* K$ E& w8 \1 |1 m        }
7 u. t+ K( {+ f- h/ z9 \1 v( {/ ?; d! J! A
        while( dwLength-- ) {
" y# c$ R, M* T; y  X/ |! W( L                writetime = (DWORD)elapsed_time;0 O3 H/ S' x- L/ L  G* ?

* E' T- s# ?! b, Y0 [- _                while( GetQueue( writetime, q ) ) {7 Q5 N( ?/ M! z; L
                        WriteProcess( q.addr, q.data );
/ h; v) [  d( e# q4 x6 i* b2 R                }
9 j: m6 R& w( G1 N+ X8 G! |
6 Z8 @' q8 B4 ~' R) s- p                while( GetExQueue( writetime, q ) ) {0 Z0 |. i; E6 v9 ^& Q$ }0 _& Y
                        WriteExProcess( q.addr, q.data );0 }9 G* a, x, m- q/ m* n
                }
! x4 |  I9 S7 @) L6 g2 ]
8 Q3 ~& _6 M1 L: z: |                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME71 n- X) y' A5 [  }
                output = 0;: r0 k  U' [3 q5 [1 m
                output += internal.Process( 0 )*vol[0];5 b/ M8 o7 r  r- I7 e) }! X9 N' V3 c, M
                output += internal.Process( 1 )*vol[1];
% B7 v/ o. e! l: n+ v3 |                output += internal.Process( 2 )*vol[2];  t2 a2 p9 ?, |" c. I. L: e
                output += internal.Process( 3 )*vol[3];
: M3 }' B# `0 Y$ E% p3 F- Q  D9 C                output += internal.Process( 4 )*vol[4];
9 j0 i! e7 N& e* o2 r! I# p: w2 }5 H2 c, B7 C7 `  Z' f
                if( exsound_select & 0x01 ) {
* |2 b. G+ o" T# j) @                        output += vrc6.Process( 0 )*vol[5];
- {' }! _9 H. A6 X" h                        output += vrc6.Process( 1 )*vol[6];# A0 A& O/ x* G4 m* b; j4 V5 U- ~
                        output += vrc6.Process( 2 )*vol[7];
, h) @' {# `) k6 X* G( R                }7 q3 P% F  o# t' k, d, {
                if( exsound_select & 0x02 ) {
6 _# z3 w5 B  }                        output += vrc7.Process( 0 )*vol[8];# p, f. U) P' w4 E( g' U
                }# `& E* q+ f- n% T3 M
                if( exsound_select & 0x04 ) {  r* j$ Z: v% _/ S
                        output += fds.Process( 0 )*vol[9];
& d  D% Z1 |( h2 F& s                }7 R7 F6 t+ F$ F0 Y* j( A
                if( exsound_select & 0x08 ) {5 {* b( U1 Q  C
                        output += mmc5.Process( 0 )*vol[10];
3 R( b  W# j1 F* ~                        output += mmc5.Process( 1 )*vol[11];" }! |& b& @4 ~5 H* |0 w0 g5 v
                        output += mmc5.Process( 2 )*vol[12];' O3 V) Z$ i5 P
                }
6 y0 x- y) ?2 f0 B                if( exsound_select & 0x10 ) {$ |# }3 a* D8 b. c
                        output += n106.Process( 0 )*vol[13];
0 A9 s5 r* W& i                        output += n106.Process( 1 )*vol[14];3 H; Q9 p( i  b1 {
                        output += n106.Process( 2 )*vol[15];7 |. @  D8 r3 Y, [
                        output += n106.Process( 3 )*vol[16];
/ ]( j7 K; E& b2 |: c  M                        output += n106.Process( 4 )*vol[17];& n7 Q% r& p* N) H- ?1 r
                        output += n106.Process( 5 )*vol[18];
8 P: W' Y4 E$ V                        output += n106.Process( 6 )*vol[19];8 p7 v- r) H0 C! l6 {! ^
                        output += n106.Process( 7 )*vol[20];
8 `$ m. `$ `9 t: W9 i+ ]                }1 c& |$ \8 v( k% o0 t4 p: D; u- p3 ~
                if( exsound_select & 0x20 ) {/ J2 Q0 }) }0 i1 d% A. r8 x9 K
                        fme7.Process( 3 );        // Envelope & Noise  `8 z  P! x$ ~& B
                        output += fme7.Process( 0 )*vol[21];
/ t2 w1 l" q* g: Y. f3 \                        output += fme7.Process( 1 )*vol[22];
! n% k7 h  C3 c1 |* n                        output += fme7.Process( 2 )*vol[23];5 N3 g5 H3 Z5 W1 Y* z7 Q; T& m! W/ v
                }3 C. K( k9 N* u) G/ v" i
5 Z5 v. m. C' Z  w* w, t# C
                output >>= 8;9 u5 A' U1 n- ?  J% B2 o  a

2 g6 j2 P* |! F                if( nFilterType == 1 ) {
  p4 u4 {& r) n- a                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
+ I3 _. T% q. m5 q4 }" W                        output = (lowpass_filter[0]+output)/2;
( e3 j2 I5 ]- E: w" q                        lowpass_filter[0] = output;$ b1 g4 @& n" r. Q' Q3 j5 k
                } else if( nFilterType == 2 ) {- Y7 K; L; N) v! D2 S
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
" C( K" r. I: [/ m                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
( M& G6 d" l! I  F9 U" V+ c( c                        lowpass_filter[1] = lowpass_filter[0];
% g0 R4 g2 K0 u& y& k                        lowpass_filter[0] = output;
6 F: u2 i* C: i7 p: d                } else if( nFilterType == 3 ) {) C+ I4 j9 |: m5 U- R. _
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 u& z0 X! z9 L$ o* C
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) o0 R) _8 R/ w$ E/ ^
                        lowpass_filter[2] = lowpass_filter[1];
6 j# K" P! U1 V7 T' E                        lowpass_filter[1] = lowpass_filter[0];
1 S* \, m# t; z7 e7 H- B7 R9 w                        lowpass_filter[0] = output;
6 K( B' \! S3 u% g& I                } else if( nFilterType == 4 ) {
/ ]- k# p# v2 G* D% w                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
7 o2 u( @9 N; t% I' ~                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
1 H/ v# `' l- s6 J! U5 F3 ]- b                        lowpass_filter[1] = lowpass_filter[0];7 J( x, T8 f5 |
                        lowpass_filter[0] = output;/ k. \* q( s7 S, i
                }
* F& a( O: p. _/ [- R* W5 o+ |
) O1 P" ^& [, W5 Y#if        0* ]- N" ?; u: T8 T' p+ r
                // DC惉暘偺僇僢僩
$ q+ |' X; y! k1 A                {
6 u$ I* j3 b; Z; z- G" X5 K9 k/ \                static double ave = 0.0, max=0.0, min=0.0;
' J! [$ M2 W. a                double delta;
; |% Z4 h% b# `" `. ^  j; a# v                delta = (max-min)/32768.0;, E) t# j6 A9 f) n
                max -= delta;5 [1 Y8 N6 ]  Z  W1 e0 a
                min += delta;9 z7 Q% Q/ {4 P( b
                if( output > max ) max = output;
1 R# r( [3 d- B* w                if( output < min ) min = output;
, f' M8 k: K/ d' I2 }4 R                ave -= ave/1024.0;2 {4 y% r; V- j+ O1 m
                ave += (max+min)/2048.0;: I, @3 S6 o; m3 H  z+ v2 l
                output -= (INT)ave;7 m& N! G0 |* n  ]3 c2 a
                }
1 J& K8 U" p4 z* E5 z( q: T6 l#endif! w; \5 M( e% ]$ n6 c3 Y
#if        1% }% ^% K. J8 e
                // DC惉暘偺僇僢僩(HPF TEST): s( ]3 z6 V) R- f
                {
* U3 O3 n* i$ T* {7 W//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& ~3 u) [1 a# K$ D: U( Y8 W# f
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 @0 r, N0 T6 O6 d7 y                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 d% W& H6 h  b$ T4 `+ [                static        double        tmp = 0.0;' p! ?" W/ Q* A2 G2 o
                double        in, out;- d/ C5 d$ |. Q  q1 N, h& ~: o

& G( v# K7 l: ]# c) X4 x                in = (double)output;' |% z! J& Z+ Z9 a5 R4 K
                out = (in - tmp);4 A, ]& A2 I$ Y' I% r: q( w
                tmp = tmp + cutoff * out;
( O* h) O6 F0 M' K) k
# C& d) \# s6 L* T( i6 T                output = (INT)out;+ Y9 Q. o% s+ F8 O6 D
                }
8 Y" X  [% ?+ I' Y#endif
/ D, j# l" y! e#if        0
- p/ \- r5 J/ v2 p8 }1 B6 {2 E1 j                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 D3 G- J! b% B
                {1 y4 m( r+ i2 {% Y
                INT        diff = abs(output-last_data);
0 |% M1 J- w0 M                if( diff > 0x4000 ) {
9 p4 e  ~, l7 R% M                        output /= 4;
4 L) n# R& P! L9 G1 A$ I. F                } else , D" P9 E2 f; \/ i$ h
                if( diff > 0x3000 ) {
- M/ t6 O; S6 y0 O                        output /= 3;! W( H0 a8 Z5 t5 G8 s( _, K
                } else
8 t0 M( x  p2 h; D% m                if( diff > 0x2000 ) {
' Z& ]8 t& O  K& l5 B% n: }( R* ]                        output /= 2;9 |9 J/ e7 \, C: {- w7 I
                }; A1 t0 |' O- a% X7 l- z
                last_data = output;2 m5 O) E/ ^! @" u8 ]' b5 r- ^
                }
* n: i1 V3 J" Y9 h2 U6 L) a  y5 ]#endif
. o# }. {3 @8 k" S' r* @                // Limit4 E! j& R$ W0 k: r1 v- ~
                if( output > 0x7FFF ) {" c& A% R2 B$ [6 G4 R& \* N/ `
                        output = 0x7FFF;
6 Z5 v5 J: S; g0 y& s" {  t$ x                } else if( output < -0x8000 ) {
& f' S: c6 ?3 K) B                        output = -0x8000;
, u. ?5 \! P9 E& ?" K2 b                }
9 d" I9 Q; W( z6 I/ u+ ~3 ]: i' ^' ~8 A! }
                if( nBits != 8 ) {
* v9 x( K$ G, ?2 W                        *(SHORT*)lpBuffer = (SHORT)output;' S6 Z! N4 T1 ?! o* I6 n8 H
                        lpBuffer += sizeof(SHORT);2 \7 W+ y# X& s, e( S  Z. W
                } else {
/ E+ G3 M7 |4 c/ {# a                        *lpBuffer++ = (output>>8)^0x80;
" C9 P9 u, b' r( m                }* z/ t/ a$ X8 M% F0 {4 p( U, F7 A

6 @3 i) a: E' j                if( nCcount < 0x0100 )3 p6 V5 R0 V8 h  y# I3 }1 E6 v
                        pSoundBuf[nCcount++] = (SHORT)output;
; U) X: [% l, _+ M3 c5 q) d9 i4 \! K" C1 Z
//                elapsedtime += cycle_rate;
' ]! ]- m  Z' C9 B: M% c& ^                elapsed_time += cycle_rate;
! P$ c) p$ q; l. X        }0 u8 y6 Y: M" n/ J- a2 |% C# ]

. Q" R3 W" |+ ]8 @2 f; y7 G#if        1$ z# W* m: D' j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# q) Q% }" M( l7 n2 B  y
                elapsed_time = nes->cpu->GetTotalCycles();+ h3 V1 q* J5 X& e) x) \+ e
        }: N: k2 W- @' G3 A' I
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {% w& c; Q6 R0 G. x& I6 l3 k
                elapsed_time = nes->cpu->GetTotalCycles();
9 {* p+ O1 ]- s        }/ a/ O* a5 P% B
#else; Z9 S, B+ L0 R" B) k
        elapsed_time = nes->cpu->GetTotalCycles();
, p; C  N+ D! `: G! b: i% k#endif' R( T% t- T+ l5 g
}$ I$ t6 w, P# t* T  N
& L% n3 P: ~4 B) E0 o+ i% r; c
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)+ U+ f/ g# t5 q: J7 h# k5 c: a9 x
INT        APU::GetChannelFrequency( INT no )5 h3 O! l+ l4 v2 v2 V) _# s4 o4 O( j* z
{
% s3 q5 S: L6 }        if( !m_bMute[0] )
! b' Z/ p5 a( e) w6 `; [* t                return        0;' {( T- L4 E% {( [0 V
# ~* e1 `9 M0 I! t6 c
        // Internal9 d) E- K: Q* h! j) w
        if( no < 5 ) {
: x+ a) N0 T$ T9 F/ n: j                return        m_bMute[no+1]?internal.GetFreq( no ):0;# F3 I+ `8 N6 a6 w6 @
        }
! m1 c$ `& U3 }' S7 n        // VRC6: r/ ?/ u* X0 c, H* a& H
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
4 W+ X  v9 y% H' f: J& p                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! u8 z' a1 h) X. U
        }5 w  O  N: ?3 K) J
        // FDS+ Q0 ?" U  [( [* B5 ~
        if( (exsound_select & 0x04) && no == 0x300 ) {* \3 c+ ~( j/ [2 _5 r) a, ^0 P
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 E4 F  V6 W$ i7 o        }
5 _8 b! c8 A3 l) P- b) s  o0 p. k        // MMC54 S( x; _6 u! [" S9 Q; F! W  a
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {/ t/ }- b) F* N% [7 m, L* u# j
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;+ v6 A: g7 d8 L: F4 Q
        }" v8 a1 I4 [% O+ O% @
        // N106
. N  V: Q5 c! m+ |$ N) H1 y        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
) {. o/ @7 D- I                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;( `, d: ^5 `1 r4 ^6 \* w% ~7 J
        }; T5 ?0 l& ?) D# k9 J* G
        // FME7
0 V) q6 z" y, \  y* r        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
. K* I9 |6 T( Q5 P                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;5 B. e8 l3 }2 b( Y
        }
+ K/ V$ b" l( f8 i( n' C        // VRC7
9 l& [3 p; z' C1 J% J' l; b        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
, z) G, c5 o7 e% E. l2 u                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;( @* |. f- k3 p: I
        }
5 g/ b2 e2 f4 i6 w# i9 x        return        0;; q1 T, [. a* F8 _. g5 d/ d+ F1 a
}
! \$ m0 A) P" {  r# j7 `+ Z
+ q1 X) f# ]8 C2 k$ @// State Save/Load5 B* g# e& N- p$ t1 `' s( T
void        APU::SaveState( LPBYTE p )
2 j% |3 a  {: V6 q# [( N! ~{
% P* R9 U. f2 k1 A#ifdef        _DEBUG$ J2 r( |7 }5 {0 a
LPBYTE        pold = p;
/ I! w5 U  o" [  `( e4 i; f5 a3 G#endif" u6 A3 [9 D8 L& G
( P; A' D* E  ]
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- r+ K( K8 r$ J. S; f
        QueueFlush();3 q4 t$ o5 w1 P/ Q; w9 T3 |
) @3 c; [8 _# m! W7 U) F" a
        internal.SaveState( p );
( A9 C6 P) E$ @        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* _) F8 h* C! Y1 R+ o! E7 O5 T& @# r9 J# ^( I; r2 y" j
        // VRC6) j  t& }$ h' G4 O3 @: g7 n, l' |
        if( exsound_select & 0x01 ) {% g, {, o4 d* z4 d: f1 `
                vrc6.SaveState( p );
8 g1 Z. R( d6 Z" i8 _* h# I5 i                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 q: I4 y  ~5 K0 |- l2 e        }- k& ]  i+ u& E/ r9 S. x* D
        // VRC7 (not support)+ a, C& z0 n1 u) i9 f
        if( exsound_select & 0x02 ) {
$ U5 Y' Y4 ^* D" n                vrc7.SaveState( p );
. X$ P- {1 t" F3 j) }) U                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" y1 }7 {, B! s! v# ?. }4 d
        }" z# x4 g2 ], Y/ u6 Z& q7 Y" u
        // FDS2 S5 l9 f( Q$ ?; B: ]  x/ T
        if( exsound_select & 0x04 ) {6 x! z# `) M1 Q3 p: b
                fds.SaveState( p );9 u# D% M/ j3 K2 F8 [, v$ t
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 e# ]# ]5 f) y  x/ a8 [) i% h2 ?        }
  ]  g! M& s/ J6 Z        // MMC5# |: A$ Y, T" d, T- V/ T: f
        if( exsound_select & 0x08 ) {0 U+ ?* t2 s  J
                mmc5.SaveState( p );
' Y3 x! {" ?/ u7 ^: U; \                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) r6 X- {/ e2 S# E1 u, v/ X        }/ Y0 Y9 `3 j. b- R$ M8 f5 B
        // N106) G) K" _4 C9 E! J8 m. k
        if( exsound_select & 0x10 ) {, B9 K/ X2 D- ?5 M
                n106.SaveState( p );% |4 F! m* v  |: E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding3 Z+ X; x5 @2 v' T* D! [& M
        }
$ L/ ~# `: V/ [8 l" w3 L        // FME7
! w+ z: q. w2 b$ j3 k1 L        if( exsound_select & 0x20 ) {- U+ J$ ?" n; Y# S8 H/ g
                fme7.SaveState( p );
* A6 w5 \+ X4 q: e# X6 S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# i2 Q/ Z" _9 x" Z& n/ p) ]7 S
        }8 P" t+ v) m& P8 {
9 Q. \2 _7 l' D4 o2 E1 R
#ifdef        _DEBUG
  m# W2 ^4 Y8 D  R; BDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- ]/ w6 X1 M, L" W( I#endif8 H, C' f9 \& `
}- Y0 |# s' C9 M! i
) [+ N9 a. B  i, p
void        APU::LoadState( LPBYTE p )
" h6 T/ y* Y" U* l1 T{
; _" n' G0 p8 t+ g0 D        // 帪娫幉傪摨婜偝偣傞堊偵徚偡  G; W: e1 G+ {8 v+ a
        QueueClear();3 J8 @2 F3 B! i* L

2 R/ p6 s$ j3 z7 F        internal.LoadState( p );
5 D' ?' m$ @. G. D7 D& e        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 F' ~" B- p! ^: n; N8 P
& L3 @$ T; h1 s$ I        // VRC6
* R8 M3 y! C8 p6 S+ p! e        if( exsound_select & 0x01 ) {) }( C; X1 q" |8 A! [9 B/ D+ [
                vrc6.LoadState( p );$ [$ E# Y* z9 q% t8 X) q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ X6 L4 O: [" G! l4 ~: u
        }
5 {, S+ C0 y, S        // VRC7 (not support); c0 p9 ?0 ~0 @- N, Z
        if( exsound_select & 0x02 ) {
1 r3 k* p4 C% _1 E& I                vrc7.LoadState( p );
" R9 A$ e% n: U6 L0 W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ z' H% t, \$ {5 @; i
        }; p$ U  _1 l/ ^7 y
        // FDS
, S7 J% Z/ f1 n2 G+ ]; B/ I        if( exsound_select & 0x04 ) {
$ k. p. s. i; I6 S' _  ~. E' ?                fds.LoadState( p );
! a3 S& K- ?+ i$ T0 h                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 D: b. D9 i8 V0 A/ u! v( \        }
$ J' T4 F2 y" W- `8 q: X% l* T) O! g        // MMC56 Z; U" k& N1 M7 I7 ]1 D( V
        if( exsound_select & 0x08 ) {: s7 e: Q8 y8 x7 J; r$ l. |7 }
                mmc5.LoadState( p );- b# [9 }4 x. g
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ D+ v& I' D4 D3 ?        }% c$ K# n% a( o' k* l9 b
        // N106# {4 L6 B5 e4 }! `% T6 J& l; [
        if( exsound_select & 0x10 ) {
6 |, |2 m7 a5 r: o0 D                n106.LoadState( p );
$ o% A9 t# a" b1 t5 `; `" ~% h+ u                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 [' g, Z$ R& ^6 E" R        }. `5 ?4 ~$ r3 ^8 R+ a. Z- n5 p' U
        // FME7
8 g: E3 w" O; A6 L# ^: `2 b/ ^        if( exsound_select & 0x20 ) {
* D$ L9 x( C. G7 q: G                fme7.LoadState( p );0 s+ O# V1 ]- @# q" e$ R5 M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. e& p' A. H! e" w
        }
. ^  B% s% U6 R8 u+ ^: m}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 X3 i$ s" p7 f  R) R) A1 q1 f可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
$ T) K& x' }- U' l, x3 s% Y2 [4 |感激不尽~~

, J7 j$ v! M' z" `6 _+ t$ z3 O恩 我對模擬器不是很有研究,7 H; e; C" D6 p6 S8 V. ~7 T
雖然要了解源碼內容,可能不是很困難,
: _8 H0 I  @& p不過還是要花時間,個人目前蠻忙碌的。
- P( e3 J! x1 a& x3 }/ d1 Y, w- l. \: _1 V$ K( c  F' ]
給你一個朋友的MSN,你可以跟他討論看看,
. `' |( W6 L  I他本身是程式設計師,也對FC模擬器很有興趣。
% t  ?4 ^% e, S" b$ A* u
: t9 n$ h) N$ FMSN我就PM到你的信箱了。5 O# [! c- A; b  R- W

, ?* e! O$ Y+ L! e3 W希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 6 ], `6 J9 y  f$ J
呵…… 谢过团长大人~~
" c% G" l5 j+ l- g3 ^
. {' q9 Q" t) f; n0 G# z
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 M- J  Z- V: \: p3 H6 r团长的朋友都是神,那团长就是神的boss。
) m! u, c5 W3 ]  S. e; A
哈 不敢當,我只是個平凡人,  i; K+ f  O3 D! e* v& S
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: g% Y$ Z; _* g1 B
ZYH# Q" ~+ B( g+ ]; i* @0 `
QQ:414734306
/ Y; P) n+ A: c0 r+ aMail:zyh-01@126.com
$ ~3 ~; q; Q) f  A
* d/ j6 V1 F1 y! w* [* D  ]% v他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
  y; w6 W4 Y" I. v  r% b( S" F再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 t0 s2 N6 {% F: Q" @不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-19 19:15 , Processed in 1.100586 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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