设为首页收藏本站

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

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

  [复制链接]

该用户从未签到

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

该用户从未签到

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

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' V: N0 q3 O  ?# K3 V! V# F! D
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~8 _9 U8 U" Z; v. u* c! U5 y
这里有相应的模拟器源码,就当送给大侠了~~
  O7 ?# |! A) y: t% I2 W+ thttp://kenkao.qupan.com/5096520.html
回复

使用道具 举报

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
7 q' j1 y7 q- M6 M能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) q6 v* Z1 ]1 ]5 G+ P2 e) }' J1 l- ?楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) d: N8 X: w* j- B
这里有相应的模拟器源码,就当送给大侠 ...

' o6 H: t" Y- J6 t  E/ }聲音部分(Audoi Process Unit = APU):
: [5 x6 y3 @8 m# g. R: Y7 ~.\NES\APU.cpp
& \2 v( M) R/ [: i: K7 }.\NES\APU.h
, g' a& I9 f& A) G, A: P
4 q& K; [" Q9 X; g$ a. J! [6 {. b! a* O
影像處理部份(Picture Processing Unit = PPU):" V" y4 p8 T% N6 Q" n, |
.\NES\PPU.cpp
& k' k( @0 t# i$ y- T. G.\NES\PPU.h
, Z8 `) Y& F  G
/ d: K5 K6 l  h4 |如果原碼用C跟ASM混搭也不錯
回复

使用道具 举报

该用户从未签到

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

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 Y$ B' [/ y1 a4 F$ a
感激不尽~~
回复

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
% j3 }  e+ Z- t/ X(由于很多专用术语和算法机理都不明白,所以看不大懂……)
, F9 w- W# m8 |9 ]//////////////////////////////////////////////////////////////////////////
9 J: E: z% g7 M& u2 T: b" |$ E  B0 b//                                                                      //! l+ u9 o5 x4 m
//      NES APU core                                                    //
( S$ G+ T6 q# R' h$ v$ l9 ?& p//                                                           Norix      //
4 @9 O* k+ r5 `//                                               written     2002/06/27 //& D4 B# l$ Y* Y- n8 p1 J1 c
//                                               last modify ----/--/-- //6 s; u1 C* I$ m8 M1 @& w
//////////////////////////////////////////////////////////////////////////- r( {& E, E3 V9 t
#include "DebugOut.h"
' a' A0 M& [6 ^! m: \- ?#include "App.h"
$ r8 B& p6 m" S#include "Config.h"7 F9 f9 S9 f% n- X0 T
+ o/ `' i' l- m: A$ G1 J, H) S7 F
#include "nes.h"# v6 @9 [" Y3 J" B  K4 C
#include "mmu.h"2 ]/ z& i1 j7 ]% V7 F, N
#include "cpu.h": _) B. x/ w0 ~! l+ ]* r
#include "ppu.h"6 z+ R  Y% G, T3 t# p" C
#include "rom.h"
8 N" L: L% J7 U2 S1 ?' m#include "apu.h"
5 g: V( K# f( j+ o3 m  U8 l8 p2 V6 d! Y1 v
// Volume adjust" g9 b0 Q/ L3 g7 N( r, @; V7 i
// Internal sounds
, F7 ]: i: v# S! c#define        RECTANGLE_VOL        (0x0F0)/ G0 ?, ^4 r- O  O1 B" q& j- e
#define        TRIANGLE_VOL        (0x130)$ d  w. Y: |/ a( c, ^
#define        NOISE_VOL        (0x0C0)8 b  K  A/ b" R' {$ k! V
#define        DPCM_VOL        (0x0F0)
  B; c4 y$ n) @// Extra sounds( d2 v0 a, J' i; V+ O1 d
#define        VRC6_VOL        (0x0F0)$ o5 P- R) L( w2 G) @6 f: d
#define        VRC7_VOL        (0x130)
: _+ s: ]6 b- M# D; C  E6 D#define        FDS_VOL                (0x0F0)
3 j, E; o! W: K. X% v% {#define        MMC5_VOL        (0x0F0)
# c; ^- M( f, M, C! b% x# L3 i1 h#define        N106_VOL        (0x088)0 k* T& E: g3 P6 A3 W, L
#define        FME7_VOL        (0x130)8 H$ ~9 y2 v% G6 g1 R: V

" S  E; z" C1 o: _; O3 n2 |$ ]APU::APU( NES* parent )
8 l/ L; E2 z8 h{
+ T. A( N2 E6 {7 @* N7 H        exsound_select = 0;
3 i; V9 ]: X( S+ L
/ H2 G; W; x( r3 P- z' P        nes = parent;9 d8 B. r+ Z. l. e9 e5 I4 K
        internal.SetParent( parent );" n: X  L4 Y# u" m1 o

2 C9 D: \1 d1 G  M        last_data = last_diff = 0;" f5 C9 R& O" N

/ ~' s" I7 ~$ _& ]; y' k, z2 y! {        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
6 P5 U* ?, l0 n9 `8 I1 D
, |6 {( V% S% h+ F% ^( X        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 R$ m. `# Q+ u9 |        ZEROMEMORY( &queue, sizeof(queue) );
& O( J( x% }# q7 S5 n% r        ZEROMEMORY( &exqueue, sizeof(exqueue) );* ]0 w( Y- m/ `9 ^6 J) a0 F( O

8 q( C4 `8 i0 p! `  Y        for( INT i = 0; i < 16; i++ ) {
$ O0 U/ v4 }  b! v& i" W0 d. m                m_bMute = TRUE;" w5 J( m- J* D) [) M! I
        }* Q4 R8 n" x' I
}9 I/ x) g0 r% H' m7 ~

& r3 C0 H! @4 n/ `& x& EAPU::~APU()
# u/ x- c+ l' t& c3 y1 p{
/ W5 p" J5 Q. j' _2 e}
" d& V4 I9 _8 ?6 ?7 n% L4 {( @/ b& b" G1 l. k! |
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
, d# j, ~/ l: Z* @1 P3 N! ?5 Y{
* G( D" P+ C  n, x" L7 R        queue.data[queue.wrptr].time = writetime;
0 V& N/ w& V# t3 h        queue.data[queue.wrptr].addr = addr;
& Z, F1 r1 p3 A- r% I        queue.data[queue.wrptr].data = data;% c7 Z; u( [$ \& k# {
        queue.wrptr++;8 q1 {) z- V9 \$ p" a3 F( s
        queue.wrptr&=QUEUE_LENGTH-1;
8 ?& H' o3 d* G2 @; \        if( queue.wrptr == queue.rdptr ) {
: O! X4 n/ b4 g( Y                DEBUGOUT( "queue overflow.\n" );
7 w% e2 ~* H( h6 f) k" o        }0 J+ ^9 @& J0 h8 ~% S1 A
}
% v( ^" Q- M, P) ^0 l3 G) }$ ?
& T* g# y0 a  T5 L7 y5 C  W9 WBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ), E- Q4 E/ V7 ?% e# z
{% a* k4 R# t3 \, ~' |
        if( queue.wrptr == queue.rdptr ) {# g7 t! L) V" y6 N2 I
                return        FALSE;  u; g5 K* o; {' n# w4 l
        }
, T2 K3 Y! ~4 N9 \        if( queue.data[queue.rdptr].time <= writetime ) {1 A  |' ~7 S9 M
                ret = queue.data[queue.rdptr];8 W# h# s! M; u1 U
                queue.rdptr++;' d) `1 G3 N# p* S2 Y7 S
                queue.rdptr&=QUEUE_LENGTH-1;# C. [- I8 k7 @4 F
                return        TRUE;
" e- L3 v- a7 [# x        }3 g3 S0 U8 V; b6 E4 O& w  ~; T6 ?
        return        FALSE;
& q* E% l0 ~0 D' t' @3 s}2 M9 v) O! I' B' ^& j3 P
/ i8 ^  S" U9 D4 `# B8 B
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
) @# V- l; g5 X5 L+ C{
3 j; d6 u8 [8 r# `( D        exqueue.data[exqueue.wrptr].time = writetime;
9 ~% ?$ t, x" S# c, V+ D8 |        exqueue.data[exqueue.wrptr].addr = addr;/ L* B) H: |5 u3 [1 V
        exqueue.data[exqueue.wrptr].data = data;- y# |8 v% K% X* l1 Y4 @
        exqueue.wrptr++;: Z$ _6 {4 V/ P
        exqueue.wrptr&=QUEUE_LENGTH-1;
; i: o( W7 y$ l- _        if( exqueue.wrptr == exqueue.rdptr ) {
7 b; `6 b/ R9 c0 \) U                DEBUGOUT( "exqueue overflow.\n" );7 B2 [! Z& l2 b3 i: @- H
        }
& O3 E) i5 |1 F4 z}
- U/ O5 \+ A- l. d! f, F4 U& y# C  o" R
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )1 G3 R1 C3 Y1 `6 D+ j, a
{& V- o& a4 \( C& K
        if( exqueue.wrptr == exqueue.rdptr ) {" f* k8 C, [2 S: u5 d" t% H/ g* h
                return        FALSE;3 p; J& m/ r  A, @1 g$ F/ V5 R
        }; I7 l( I; i4 b& Q/ n8 A% {: p3 x
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 Z# n% F+ T# a2 Y: W( ~8 a
                ret = exqueue.data[exqueue.rdptr];2 f& i4 H" s9 _
                exqueue.rdptr++;
1 J' Y* U! q, a0 z- D0 q                exqueue.rdptr&=QUEUE_LENGTH-1;3 U) Q( X. z: {- S3 Z
                return        TRUE;" ^/ M! {! W' E$ H5 Z
        }
5 ?; D0 X( A0 h0 X9 N  x        return        FALSE;
& h7 Q* o/ y- y, |}
  ^8 Q' d  j0 h8 p& N: X% |# k0 j& s: R+ ?: a4 J7 y5 R0 a
void        APU::QueueClear()
( V" V% b7 f9 i- y5 K9 U2 Z% j{( T: G# d- h" Y' T
        ZEROMEMORY( &queue, sizeof(queue) );! P1 L6 @$ i9 W3 N
        ZEROMEMORY( &exqueue, sizeof(exqueue) );# ?4 k" F3 m9 V+ M
}
' p5 h6 x( n4 |! \* X2 [$ j+ z
% T1 O" x) l8 g; ]' [void        APU::QueueFlush()1 j8 n; R. V' ~" @9 ^7 U. E( O
{
  g) [- N& `3 {+ |) I" E1 e: f        while( queue.wrptr != queue.rdptr ) {& p" R: T' d3 n* L9 K0 K1 j
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
' y% a) f: T9 Z4 Z" d% g                queue.rdptr++;/ R, A* m  ~3 ?
                queue.rdptr&=QUEUE_LENGTH-1;
2 s* Y' N! @+ |/ v0 m8 |* @. `        }& Q% ^, e" k9 H: u

- H* I/ N- P, v# @/ ~6 V* ^        while( exqueue.wrptr != exqueue.rdptr ) {& O0 f& G, k! k
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
7 w9 ~( j+ h- t( p8 ]& k, e5 t                exqueue.rdptr++;
6 G8 G0 J' d7 F5 Q' C                exqueue.rdptr&=QUEUE_LENGTH-1;# b; R3 ]% s& J! _# S1 z2 W( k
        }) j, n$ ]( C) F
}: K, q8 H% W0 e& n  @3 w- J

% P* n9 i/ Y( x& y( ~void        APU::SoundSetup()! R' v+ R& k5 Z$ R' K
{# o) I) @; B$ e: o9 G4 }
        FLOAT        fClock = nes->nescfg->CpuClock;8 I, t9 h9 f/ j: x( y9 O+ z
        INT        nRate = (INT)Config.sound.nRate;# U0 [" G- Q( o( I, ^- y
        internal.Setup( fClock, nRate );
8 j9 [/ g% B" E% l9 y% G" @        vrc6.Setup( fClock, nRate );- x9 M4 ~) j; G) ]
        vrc7.Setup( fClock, nRate );
' l6 u: O. T7 C( N) B, _        mmc5.Setup( fClock, nRate );
/ b5 s/ a3 Y3 K8 |: n+ z        fds.Setup ( fClock, nRate );, J6 }$ W7 R# _* D
        n106.Setup( fClock, nRate );
9 W1 ^+ V0 g2 e. g* L6 \        fme7.Setup( fClock, nRate );; q  h% m: B' A: }6 c5 u
}) I; t, J& ?. \1 t( |

/ g4 Z1 [( d2 j8 T* `2 Kvoid        APU::Reset()
; T) @( I) I( {6 j{
, K: ^2 \' [* J% z        ZEROMEMORY( &queue, sizeof(queue) );+ J# l2 r9 O. b3 a; f2 A
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) W# l- _% x$ O7 \+ e5 K; p
, Q  q' v8 P5 |/ w* r4 o( F
        elapsed_time = 0;' S# z7 ?, y. C$ K' \

' b, A! o6 R# I/ M4 a2 c        FLOAT        fClock = nes->nescfg->CpuClock;% s; w+ D  ~& W1 F7 T
        INT        nRate = (INT)Config.sound.nRate;
+ y% }( b7 Q5 W0 L3 |1 V- i        internal.Reset( fClock, nRate );- k9 W1 [! T" x1 c
        vrc6.Reset( fClock, nRate );
7 P( d+ G) r# l; Z( K/ J) |        vrc7.Reset( fClock, nRate );3 @7 x1 Q( Y# i8 r/ f; p# W
        mmc5.Reset( fClock, nRate );
5 y. |2 w, J8 d4 n/ m        fds.Reset ( fClock, nRate );" W+ `3 d4 i: q1 m, M
        n106.Reset( fClock, nRate );
7 ~8 m" e! U  o        fme7.Reset( fClock, nRate );
5 \3 j% K. U& d; ?, k  n' c
; O+ A3 o- x# s+ H; G        SoundSetup();/ f: F9 x6 p! d+ ?5 R
}% X( r1 V. s; `8 x% v' W2 d
; o2 s, [( R# w# u+ p7 u8 i! D/ p
void        APU::SelectExSound( BYTE data ), R* W3 s9 @: R. g7 _7 c
{2 K2 G7 Z+ f/ q) ~3 P$ ^6 U4 m
        exsound_select = data;
! S2 ~$ j4 A" {( {' m}8 }" `6 v7 R0 j9 ^1 v2 p
! _* d, b4 H9 W1 D; j9 g
BYTE        APU::Read( WORD addr )
' l( k% `$ s* r6 ?0 n9 ^{
9 ^* o6 a% P. K+ ]  ?6 Z' n% G        return        internal.SyncRead( addr );
' T; s' T: e  T}
# X! s& t2 i* s, u% p  E2 K9 c8 }. a5 G) O  B; ]
void        APU::Write( WORD addr, BYTE data )
. a9 T" H& E8 k# x  |. A1 u{" V, Z. I5 G4 n3 V% P* ~& b9 B, X
        // $4018偼VirtuaNES屌桳億乕僩: m. ]  H$ z0 w* M" D
        if( addr >= 0x4000 && addr <= 0x401F ) {6 a- ^$ L' b: h( q
                internal.SyncWrite( addr, data );
9 `+ u9 p9 q6 F1 x7 q; A1 N                SetQueue( nes->cpu->GetTotalCycles(), addr, data );+ {5 k2 @' s% t
        }
, X5 J! C5 b, g- b& s- y5 M}
% H, l$ @8 g$ ^& v; R2 g# C/ A& y# H; L
BYTE        APU::ExRead( WORD addr )
$ D  j5 \2 e7 D{
1 q( c" J5 @% jBYTE        data = 0;
% p! x/ O9 I" u. c$ G- {1 n  E% |4 b4 Z) @" \
        if( exsound_select & 0x10 ) {% A. |' k- m8 k& j1 l+ s, J
                if( addr == 0x4800 ) {
4 }0 ^+ n( h, n- G% T                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );; j, W& q4 @; V
                }: \: y3 u8 S, N6 G- b6 L
        }/ H/ A' R4 U5 R! `
        if( exsound_select & 0x04 ) {8 W4 u) \, l$ e) h
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 W  ~" k' ^6 B+ o+ A                        data = fds.SyncRead( addr );, l$ }8 I& @9 P
                }: \; b  k5 |' H7 ]; O
        }- f: H+ n# x! O0 M# H
        if( exsound_select & 0x08 ) {7 J; u+ ]+ }" s$ v$ N
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- y9 n) c5 j  N                        data = mmc5.SyncRead( addr );
8 f, \/ F, t4 ^  _. S9 v8 e                }* }- ?' |1 x6 y4 f6 z! `% b2 x3 |$ W
        }
2 j5 V1 \, Q4 P/ X1 i
" H7 R6 P9 X7 \7 w& x6 \        return        data;
$ P  W8 S7 A5 l" R4 k7 l}2 q, E9 F7 F/ l5 Q5 M1 y* J
. k9 _+ a: e& d* z4 O3 N
void        APU::ExWrite( WORD addr, BYTE data )
( M* ]& n3 ]8 H' V& {" u7 B3 h# O' g7 Z{
# c" @' X0 ^7 o; k& O# Y8 Z- t+ e3 i        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );' d# C4 I4 H% c8 C7 f" V

! N. O& Z: C# p; C7 C        if( exsound_select & 0x04 ) {* S5 J4 C$ N( `' X7 i- G* M
                if( addr >= 0x4040 && addr < 0x4100 ) {
' ~6 @' _+ c6 G. O4 u                        fds.SyncWrite( addr, data );
6 t5 A; Z- R+ z8 z7 w* ]                }% x4 \/ {* p7 i) d
        }4 _" b9 k- m3 E8 Y6 v! \/ ~0 q

$ u/ a, f  z1 [: v; f, k% }        if( exsound_select & 0x08 ) {
3 g, h( Z. S4 ?                if( addr >= 0x5000 && addr <= 0x5015 ) {5 |! ]; ]. j* r5 P7 W5 a4 x
                        mmc5.SyncWrite( addr, data );" A+ }0 C5 [" F
                }# }. F/ O3 j$ M' p
        }
& J  L0 u; W# J0 H, B8 G}  ~9 k) D# Q! T1 `' K7 F+ N  _
. v0 k- O3 S6 W/ G
void        APU::Sync()9 N* ~1 k% f8 J* B1 a( e
{
% G4 d4 K- G3 _! N6 y3 A* A2 S}
8 o; ?" ?: F8 v: I; }% g8 ]+ U8 d0 I3 m' A( F6 o- n+ Q; X! t
void        APU::SyncDPCM( INT cycles )
3 D! x" [$ G' f2 K1 y{# d( B* \+ ]+ E! L" I. q
        internal.Sync( cycles );
( B& n+ z/ P) u/ h+ |* f; W$ r, O% Q
2 {) e/ N- m- y# t0 }) v& b, ~/ C8 h  o        if( exsound_select & 0x04 ) {
; Z! b  p- E. S: ^                fds.Sync( cycles );- v. V* J% c+ Q* @8 X- `
        }
# Q. R. o" I4 \) g* K/ m, p        if( exsound_select & 0x08 ) {  N7 U2 Q/ o# X8 {  X* p! E' K
                mmc5.Sync( cycles );
% \+ l1 Y6 o5 n- U        }( Z& J$ M5 G6 ~0 y; j4 M1 ^6 i
}
7 W6 L' M4 v/ r$ _9 y: e$ E
+ A2 D  f# j$ w# K8 Z1 K7 U; Dvoid        APU::WriteProcess( WORD addr, BYTE data )5 O7 N5 q. y% l1 n6 d  M* w
{
+ [- S% q) G& W        // $4018偼VirtuaNES屌桳億乕僩# @' S9 K0 e  @4 F% ?
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 {# C+ m# P$ T: i( _' x) ^: j                internal.Write( addr, data );5 m3 o4 K% V- B% X
        }
. j/ c" B/ B+ v  ~" v}5 O0 X0 X, u: G, }% `$ v
9 t4 W6 P9 s4 z3 d' S3 B' U
void        APU::WriteExProcess( WORD addr, BYTE data )% @) @4 j7 }6 `8 R
{% O: k3 b' Z. |# w9 M
        if( exsound_select & 0x01 ) {
, R$ L8 O) K3 g4 w                vrc6.Write( addr, data );
; i; u9 r& G1 e' r& |        }1 |1 K# W- T6 U3 ~1 G
        if( exsound_select & 0x02 ) {
+ f* x6 h# g" c# p+ n                vrc7.Write( addr, data );
; q" \) Y% X, }1 w5 k, `        }
) D( e5 {/ B2 k8 y7 w; e+ m5 B        if( exsound_select & 0x04 ) {
: b; p0 r9 q( g8 P) p+ W/ u6 A6 k                fds.Write( addr, data );8 ^; ^; _  w" t7 y
        }
2 [  j* N5 R1 Q) x2 V        if( exsound_select & 0x08 ) {/ f, v7 \1 p. N# R
                mmc5.Write( addr, data );
2 Y! S. B2 ^8 k" P" ~        }
. k: E9 K' B! ~: t% a        if( exsound_select & 0x10 ) {7 a1 U8 o: Q/ u9 M# m
                if( addr == 0x0000 ) {
. C% `6 ^6 c# V( N3 o& G; Z6 g: f                        BYTE        dummy = n106.Read( addr );( w4 v+ f7 B# c0 Y3 P! \+ p
                } else {8 v) X* L1 ^3 {$ B) @: q
                        n106.Write( addr, data );
4 L  p- T8 a- V. v! j                }
: D; e. E. O: h+ G; X        }# p5 [7 p  Y0 b* B& Q+ D; B. b# F
        if( exsound_select & 0x20 ) {+ K4 U6 ?, A+ s6 j, v2 R1 v  b
                fme7.Write( addr, data );: g1 K  X) D$ }9 j
        }( j, D' f& m$ o  E5 L- _) ]7 B
}
/ l' O; k2 e: k  ^/ n! c: z% o# [
& ?2 }( R6 i& R2 T1 X1 i- }3 Ivoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), `. R' F) Y! f* E, t, P* f
{1 {% ^0 \, K& K- P
INT        nBits = Config.sound.nBits;
' q( l6 e2 i' m$ sDWORD        dwLength = dwSize / (nBits/8);3 u' ~/ w4 J" S6 E' @5 I9 V" Y
INT        output;* Y7 @. X& P2 y* k( f( ?: N
QUEUEDATA q;4 {7 |* N% p/ N5 d7 Y
DWORD        writetime;
" ~* {5 h; `1 R* |0 Y- ^2 R: `* Z# k$ S, O- |$ R
LPSHORT        pSoundBuf = m_SoundBuffer;5 n1 p" F; {, u7 }! y
INT        nCcount = 0;
4 b8 l" F, K& m  P* g1 }! y
$ |- V# d, W4 b8 ?, Q% wINT        nFilterType = Config.sound.nFilterType;
0 V' J* j; C, j: n
# ]% A9 @9 a! n- |# j. S        if( !Config.sound.bEnable ) {# F; |0 [- b; S9 }( N
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );3 j1 L9 m, k6 A
                return;0 p  z0 S( h8 W. b# t' c
        }
( q+ M- M$ p$ i/ p4 B' @: w1 S
; E6 Q* A  z, k+ n' ~; `        // Volume setup
$ u( B$ _6 x* B3 ~6 D        //  0:Master4 b2 j( b$ i  t6 E" e( H7 e" O
        //  1:Rectangle 1
2 W' A0 l/ J  @4 X        //  2:Rectangle 2
  j! G' o* |5 g        //  3:Triangle% a+ @$ `& q" V$ ]
        //  4:Noise
) x; B* q) w7 \8 N' s9 w+ Q: p        //  5:DPCM; H9 d' x( A+ }; J' b& W
        //  6:VRC6
- m2 Z: u0 H- T2 g$ e4 \$ l' {        //  7:VRC7+ \* @3 U7 m1 n3 e- m# E
        //  8:FDS
1 w! m) U8 ]' u8 S        //  9:MMC5
) V; p/ b! s$ x# C( o' c' {3 v        // 10:N106
& H4 L& H- w* N* t3 a        // 11:FME7- i2 S  v( C1 E' a- \
        INT        vol[24];
! N7 M$ T9 T) [8 T0 c        BOOL*        bMute = m_bMute;. b/ y$ F# K/ M' Y: O( G. J/ S
        SHORT*        nVolume = Config.sound.nVolume;
+ I: I3 \0 I! ^( c: C
% w" v+ b+ ?9 H. \1 K        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# E1 M1 ~4 w! z

" ?. K  @5 T3 _        // Internal" I) A1 R. O, D% i0 D, N
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 O' ]- B: P, [3 L        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;* s: A- a) \; \& i3 [" h. r
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 q% a+ p5 E# H$ Q% ~1 F( G5 G
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: W8 f9 N0 O5 l! b, N        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
  `; V( I* }" g" }" M9 T  I5 ?
5 }- L; P6 W' k1 ^( u$ v+ n. M5 W! N        // VRC6
. R/ U: u' O  c) s        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 |4 l+ G5 n) R4 {        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ Z4 X( p+ V7 f        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 t/ y7 m  e* v# ~5 U% m) ^6 Y: g# n2 z6 D$ Z
        // VRC7
1 |7 \1 i7 l2 D" u        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 K1 E- D" R/ |" W
( Q: p3 }# |6 {% X( w  \
        // FDS! z. o. W' v- A& {
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;, o1 m( F7 M* M# `" H4 O4 ~

7 U* Z! N6 D" B; w; H0 O4 {( w        // MMC5
' g" j- \" g+ c( i% m0 C" d        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& p) Z& [8 l* O' V
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( z* b  [  [# i3 T
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# N5 L. l3 P& g; m( R
/ `1 j3 t* ^( R. W! y& d: N; B
        // N106
+ F8 Q% L; W: x. S( [% m, l1 n        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  `* q9 ?$ g# v  I3 p# A        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& s  X7 P( R- ^3 e4 I        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ H: S* {& q( M! j        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# f2 Q$ Y2 r! F
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 ~* Z; ^- i# s1 U+ R8 ?9 J        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 A6 c$ x9 v; N1 _+ C        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 ]5 |6 [2 O8 g        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" h$ E, }0 ?$ t4 Z. t4 c1 z+ q3 L9 N0 C% Y) Y
        // FME7
7 }# J  [, w& ~# I        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 x4 G. t% \$ r" ]        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 p1 l+ [8 d5 @  l" A3 M        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ E) {6 W! b5 n% i9 A& _
" o) r4 t1 D1 ?3 Z- s2 p//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;. b, ]0 w$ u+ D8 |5 [) Z
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;" O" }+ `4 D3 w

9 |2 g% y! m' }7 @1 e' H; F        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
7 ^8 ~+ W' q% ~  _% z0 s        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ A" O2 h8 |  a: v$ K! E                QueueFlush();
8 c5 W8 l/ H; K4 @. G" Y- [        }
4 k% n) {+ w1 t3 D' P  N9 ?3 r* d% \/ y9 [! `) W; V% c9 b
        while( dwLength-- ) {
7 U$ ?7 A4 d% i$ G4 `; n3 P                writetime = (DWORD)elapsed_time;
) `- t2 o/ C) b" z4 f8 E2 i
8 P8 E$ x; V2 Y                while( GetQueue( writetime, q ) ) {
4 ~$ i9 l% j/ \4 P& S0 a                        WriteProcess( q.addr, q.data );4 @  ?  K7 M* H, y
                }" B3 ^8 N9 o/ I( Z1 }
( K+ E# I0 {; g  s9 }' G
                while( GetExQueue( writetime, q ) ) {
& Y3 V9 o3 M+ D9 U0 F: E                        WriteExProcess( q.addr, q.data );
5 Q. F9 E7 q) i+ E" y, r                }
4 K  @; j% X8 ~" Z' o9 R; I& l2 p4 a. K; [6 j: a$ D8 r  Y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 y$ U. k/ s% J' ?
                output = 0;
9 o6 R9 D" G- p4 u( \3 a1 @# ^                output += internal.Process( 0 )*vol[0];$ q5 m5 o# A  ?1 z, U* t& P
                output += internal.Process( 1 )*vol[1];6 e2 E) ]: T  S1 p. B7 `2 p, m' ]
                output += internal.Process( 2 )*vol[2];
3 m* m$ @' [& |& j                output += internal.Process( 3 )*vol[3];
% j7 @9 C+ p2 C: G                output += internal.Process( 4 )*vol[4];3 z  I# d2 L; Y; K8 i
5 n' a3 [$ k8 p
                if( exsound_select & 0x01 ) {
5 I  G" C2 A, T4 k9 L: }                        output += vrc6.Process( 0 )*vol[5];( t5 z: }, U3 K  x3 H, z- \2 i
                        output += vrc6.Process( 1 )*vol[6];3 Y! Q3 Y7 t$ j6 |/ q2 X" T
                        output += vrc6.Process( 2 )*vol[7];0 [; q, n  Y" J- P4 |
                }; q1 _5 ^/ P3 t1 k9 _% Q5 _1 w
                if( exsound_select & 0x02 ) {
5 S: p7 y2 F& J  X                        output += vrc7.Process( 0 )*vol[8];
- Q1 h  h% H4 b) y# I) [                }, F, {$ M/ j  {
                if( exsound_select & 0x04 ) {
  r, w6 {5 J- w( C! `; [; J9 X9 A                        output += fds.Process( 0 )*vol[9];5 O  W5 m# R0 }4 c% C6 R
                }
! Y/ `; z7 [+ _1 N  u                if( exsound_select & 0x08 ) {6 C) A2 U4 |" L1 [$ g4 @' I$ d- |
                        output += mmc5.Process( 0 )*vol[10];
# l9 M% a8 U* `6 s. z! x                        output += mmc5.Process( 1 )*vol[11];
7 u7 F- K1 M; J' {8 p! T: b                        output += mmc5.Process( 2 )*vol[12];$ {" {! E: [6 j+ X; b7 Z6 G: s
                }
. X  _, |- t* E' B2 ]                if( exsound_select & 0x10 ) {7 A  Z3 m1 q" B' C# o
                        output += n106.Process( 0 )*vol[13];
$ L% x, W7 K- f) I# C7 t" a3 W3 v                        output += n106.Process( 1 )*vol[14];; o3 U3 W7 d2 J' u3 g/ ~" V
                        output += n106.Process( 2 )*vol[15];  G3 M3 j1 x0 b
                        output += n106.Process( 3 )*vol[16];! c9 Q: y3 W4 q# Q5 S
                        output += n106.Process( 4 )*vol[17];
5 H. \1 {8 N& A. Z8 _* L                        output += n106.Process( 5 )*vol[18];2 [9 L4 U8 w) ^
                        output += n106.Process( 6 )*vol[19];
! B& r1 h4 v' E9 t1 z, d( E% |                        output += n106.Process( 7 )*vol[20];
" F5 v- W0 W5 |) I4 k& b                }/ r4 h/ ^& c, R) D) e
                if( exsound_select & 0x20 ) {
7 t& u$ D2 l7 x6 w9 T, K                        fme7.Process( 3 );        // Envelope & Noise
1 C1 U  K; K  Z: L                        output += fme7.Process( 0 )*vol[21];$ L! P- s- |' U- f0 a
                        output += fme7.Process( 1 )*vol[22];
& s* K4 O0 B2 i0 a$ J! _# u                        output += fme7.Process( 2 )*vol[23];
  Z" s4 @5 d8 m& [                }
8 z0 Y, g; b9 V' O' P3 ^0 v
# V1 ?' ^& K* S7 H+ h4 ]" @' m                output >>= 8;; L# ]1 b/ _3 e0 a5 B7 @

# p8 a0 L$ @7 }" `                if( nFilterType == 1 ) {6 |& ^8 [; o4 d6 `- J5 x$ G2 _
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. Q, Z9 f1 g2 Y. W( ]. A  F                        output = (lowpass_filter[0]+output)/2;
' U& I* P7 ^' F! K/ x% R3 @  E, \                        lowpass_filter[0] = output;
; J* _. s: y$ m- y; v! q! t% S/ `% u                } else if( nFilterType == 2 ) {" J+ m# ?' n3 p) l  Z+ `( g9 R
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)# w! B" V0 _9 J$ l0 b
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- [( Q/ I" N$ b- N" l% n                        lowpass_filter[1] = lowpass_filter[0];
$ s# W2 W, E! W9 [3 g7 j7 l1 _                        lowpass_filter[0] = output;. R- M: C( h* N2 Z* v1 _9 Q
                } else if( nFilterType == 3 ) {8 b4 x& {- H! e+ V8 b$ e
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; e7 s, W# }4 E# d* O% Y8 }                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;- ~+ M% V5 E% ?
                        lowpass_filter[2] = lowpass_filter[1];% i# b1 m6 H, ~* E. f
                        lowpass_filter[1] = lowpass_filter[0];2 l' l# Y1 _( P
                        lowpass_filter[0] = output;* y/ x# g* R1 v& t+ ~& N  y. u
                } else if( nFilterType == 4 ) {. q. h" X2 I) V7 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& h0 m. Z% F# I& ]# A
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;) u9 x1 k! c; C6 ?
                        lowpass_filter[1] = lowpass_filter[0];9 C# b9 c; w4 N6 H
                        lowpass_filter[0] = output;7 V1 Y2 s: ?. U) x3 g
                }
$ Q$ C3 q! o' x1 f0 ]2 ~7 C+ C4 j; b# z
#if        0
9 g9 ]& L' H+ }; d& a% f                // DC惉暘偺僇僢僩2 r" i5 t- q2 z. t7 N/ }
                {
' @& m6 O* l/ N. J+ }                static double ave = 0.0, max=0.0, min=0.0;
1 p* U' E* T! v! g& i& C" N4 O                double delta;) {( r9 y3 [2 M, W
                delta = (max-min)/32768.0;
6 ]  z, x3 }2 j' X                max -= delta;, {) _+ v6 _- C
                min += delta;
  `6 o. \6 P2 |( N# W( i" {                if( output > max ) max = output;" d( b, |- @! v2 {- i; N# w9 h, o
                if( output < min ) min = output;
. W  W, d# y9 _0 _5 C+ A1 t                ave -= ave/1024.0;7 s2 X5 p+ ^" S  P! ?, E0 K
                ave += (max+min)/2048.0;
; [- x) u/ T6 b) h2 N                output -= (INT)ave;/ f3 E1 h0 ^$ t7 B; R4 b5 ?
                }5 d. l. [7 g3 U# u* ?
#endif! B3 G: z- @, K  @! U& C
#if        1. C+ G: z9 W& M" @& c2 J
                // DC惉暘偺僇僢僩(HPF TEST); Z& M* k6 s* S
                {
3 O6 |2 ]/ g( F7 l5 s/ t3 u3 |//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);9 r; W' L# c8 o. [
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
$ D8 p  s! R: a: E                double        cutoff = cutofftemp/(double)Config.sound.nRate;6 h- w. B6 J2 p: l$ o5 Q3 P, K, Y  d
                static        double        tmp = 0.0;
! }+ K! a: l$ I5 M  b. B                double        in, out;
1 F/ S% z8 {3 j- _( r% q. y, s; W) {7 M1 H" m
                in = (double)output;0 {% u/ [6 C5 d, S) A
                out = (in - tmp);. ?& w# k7 q  I" [' t6 c
                tmp = tmp + cutoff * out;
0 O) I* h! b! [' ]# }# U
7 T% ~5 ~7 g( Y4 L; t                output = (INT)out;
2 _+ X$ ~! g) C" Q; {7 W. Y                }+ Q' c$ y# k1 D* q
#endif
9 r9 e+ j8 M, h/ m6 r6 J5 \#if        0! F) X  }+ X; E  n# a6 v
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
% o9 |- T: r8 U% C" c1 F# D- M                {
4 |2 i  C7 E$ L8 Z6 M  n. O                INT        diff = abs(output-last_data);
8 ^, L" `  g. ?5 M' Y6 C$ w                if( diff > 0x4000 ) {
" t" T7 V, f5 F$ l; ?                        output /= 4;& O" ^- p" E' w. v4 e
                } else
( C( v3 y4 a  W2 ^8 @9 o                if( diff > 0x3000 ) {, H5 ^5 u( j: ]% ]7 S7 p$ S# Z
                        output /= 3;
: x: [* m* D8 B. E$ m                } else
" D! C4 q& M' o; N! z                if( diff > 0x2000 ) {
& x/ y" w1 x& F                        output /= 2;
$ U/ J( X! C5 _# ?0 N                }" |4 d, w, i5 r( P1 |) P  Q
                last_data = output;( s2 y; C6 a; y4 R2 W
                }
) {% |9 {2 X" ~- J' |" e7 w1 {/ P#endif
, ^) k/ d5 p- r                // Limit8 G3 F, W/ w2 d( C
                if( output > 0x7FFF ) {
" B: x! g9 T. e9 P6 e& c% ]- E: N3 }                        output = 0x7FFF;
5 v8 G% s+ K5 D& C* O                } else if( output < -0x8000 ) {
$ L7 ?# Z  ^2 p: z- A6 K  \                        output = -0x8000;; A$ ^8 p+ Y0 O8 T  }' k1 ?
                }& n7 \8 m5 l2 a5 }, B! A* [. R  C  P
+ d  Q% d/ W. e& m* P  ]
                if( nBits != 8 ) {) S4 H+ O' f+ c  Q0 q; h  _( s0 m
                        *(SHORT*)lpBuffer = (SHORT)output;
/ s. y/ E1 Q; A4 H                        lpBuffer += sizeof(SHORT);
/ {( q" k: U9 g# \- l                } else {, ?2 ?5 L2 z5 x- ~
                        *lpBuffer++ = (output>>8)^0x80;3 w2 i. @/ q5 e5 j2 J& h
                }
) h1 U0 M- A3 @* j/ y9 x6 b$ n8 O' F1 ?8 m2 Z5 \
                if( nCcount < 0x0100 )8 h# x$ b' Z$ Z2 ^9 l9 O
                        pSoundBuf[nCcount++] = (SHORT)output;
  Z1 W7 I( o1 a* N4 h. j' M1 s. e3 {# o  ?+ h* B6 M
//                elapsedtime += cycle_rate;
* E7 s/ W2 x3 P; Q& f                elapsed_time += cycle_rate;$ f9 A, W; }& U; o% S! H0 k
        }& ]0 f5 g) N" B& q
3 ^# ]9 O# A0 ]
#if        1
5 Q  b) {" ^6 M& c' x3 f        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {- L: S5 |" C3 _
                elapsed_time = nes->cpu->GetTotalCycles();
3 X8 f. O" [) ^& T6 @* y# ?        }0 G7 V- x: q0 R- q9 c9 w
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 w, F  ]! P7 G6 ^6 V% n                elapsed_time = nes->cpu->GetTotalCycles();/ C& }1 Q5 t4 C( ?& w. F, }
        }
! c: m4 Y, {7 I#else8 }/ x, h9 q4 d% E
        elapsed_time = nes->cpu->GetTotalCycles();
% J" ~  u. H  F7 z#endif- _. t- \3 U5 i
}6 Z) x2 E2 C" l% ~

3 |* M' L4 |7 H, _' U7 M// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)5 v9 `5 u1 C& m' K- _8 G+ S1 J" p
INT        APU::GetChannelFrequency( INT no )
5 f2 s# G6 I5 y1 E" f) }0 x3 T{
) ?' G- x- ^8 U4 ~" T        if( !m_bMute[0] )
! Z3 Q( O' y# Q, y4 J+ P2 k" M6 {                return        0;  d% C9 Z/ `: R

: a$ O$ Q6 K4 e' z# Y        // Internal: z/ @8 l# w! A2 g$ |7 m: z; a
        if( no < 5 ) {
- d8 t+ b6 B( V# w8 Z7 D5 K+ ?5 X                return        m_bMute[no+1]?internal.GetFreq( no ):0;
/ `% G$ r4 i" X; p/ J: U; @        }
$ L, m, Z3 q0 D( M. N        // VRC6; J" ?8 ?" Z2 G6 O! Y
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 z: ~! i  E. b+ p
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% A' v& Q; V4 Z
        }
/ [; U1 G9 v  R; P        // FDS3 @' ]3 ~! W0 l+ ~0 V" s
        if( (exsound_select & 0x04) && no == 0x300 ) {
& p$ {. Z8 H! p, F                return        m_bMute[6]?fds.GetFreq( 0 ):0;/ o2 h5 b( c" G2 m2 l3 i6 k
        }2 c6 d# t; g# E3 Q" _8 Y8 E
        // MMC5
8 w6 F4 N2 x6 r; X- b$ ?        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {( ~  `3 b2 v4 H- h: Y  k
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
/ }4 ~& L) {4 _2 L, e' _# P        }
" W! v6 G4 y( R3 W  G        // N106' h) Z5 l1 X2 P- R
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' z, I( }% r/ O! m' w/ ?                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;6 ]/ s6 Q8 @0 Y% y* @) B
        }/ f8 u: D. _/ {# v' q6 `8 q8 |
        // FME7
! A1 R3 n. y2 F) ~        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
5 f4 ^9 u. U# U8 b& E; F: X1 k                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 \& s: e' x* t5 O" e+ e+ T2 I        }
3 E! Q+ k# e% h5 k/ \7 {* A        // VRC7
( b8 L; V' |+ p% Y$ b8 P' Z        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: q/ n8 s6 D4 ~: K2 q                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
1 f- n9 g4 ]3 i# Q1 m        }
; ?1 g: G- F, d0 d+ u# W5 h% [2 W# O        return        0;2 W# o3 Y7 S9 O. Q5 k
}
" B( G  t; O, S; D0 j8 m/ ~
7 |* s9 A* u  c4 P1 e1 ^# u! f2 e9 ]// State Save/Load# q+ F$ Q5 t/ a5 \4 V( N
void        APU::SaveState( LPBYTE p )  }6 N, E7 [& Q4 s# h3 x  O: t- [2 s
{4 a  }: h0 C4 b/ q% C1 `9 Z
#ifdef        _DEBUG5 S# K8 w7 ^2 L4 W% E+ L
LPBYTE        pold = p;- W& {! w) P% A( \5 D% j7 ~
#endif
7 h3 Q9 i: r/ B+ t
& E! n* q4 U/ B  `. O        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞: S  s; Z, {1 l8 ~
        QueueFlush();: a5 C6 U6 A7 B  `5 q0 |+ n! @3 h. R
9 v1 m+ a+ y; L0 ~7 K  X' L
        internal.SaveState( p );/ Z8 N* g, B/ e$ R, ^! t  N
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
5 A" u0 e& }) K/ P  B# q1 |, X
# `0 z5 u7 O/ C2 i: X        // VRC6
% r& w  B" X  H6 c$ T' L. d        if( exsound_select & 0x01 ) {3 {5 T6 a' P5 o4 V! b9 u, j: w& E
                vrc6.SaveState( p );
- R" D6 H2 J2 S. i% k) x! H. M/ e# R                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; H. ~$ Q) t! `/ k' d        }" p. J( ]/ ]0 l$ Q1 M% R
        // VRC7 (not support)
, P/ ]8 d0 `9 e. S        if( exsound_select & 0x02 ) {
0 G9 C7 i3 J3 y5 `: I                vrc7.SaveState( p );5 W2 Y* q& u& s  u8 p( H
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding& s- A$ ?" n# u4 O
        }
3 W  @! ^" U3 y6 _2 j7 N        // FDS
2 F% u9 J, {' P) ?- |9 r0 K        if( exsound_select & 0x04 ) {
: P; F8 t) j9 e  ]                fds.SaveState( p );
+ n. C) n  |- D1 P% J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 a1 i) F4 c; ~3 w' w
        }/ ^2 I1 X$ E1 ?8 E; T* _
        // MMC5* [5 \4 e' X/ b+ T. l0 k# Q
        if( exsound_select & 0x08 ) {
3 @- c3 g* v( D- q6 m% X- c4 Q                mmc5.SaveState( p );1 H! Z7 _. {4 G* \+ @, c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding! W9 q- A. T8 ^: Y
        }4 M2 x  Z% M1 x& f; K% I3 @
        // N106
& |" K3 C- ?4 F/ L9 s% [) F        if( exsound_select & 0x10 ) {9 _+ d0 U7 H1 N1 ?& s
                n106.SaveState( p );& o/ i2 [0 p/ c( z9 u, b  i
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 n* x5 E  v* j$ P1 ]
        }
. S. D8 j( c2 E; \        // FME7
" O& B" h! j1 R) y0 q        if( exsound_select & 0x20 ) {  O, z, S( K( b/ D- e, L
                fme7.SaveState( p );( N% _' m: z( Q9 o) V
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& Z# g, I2 ?& v3 Q% A- m        }  b! p, N/ l$ Z7 B& Z

. c& |7 L9 s4 `) U, ]0 W) ]; j#ifdef        _DEBUG
% t9 h# [# b0 b% L. sDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
4 z0 e8 `/ B; o#endif
; F! S+ C$ |0 ]/ C1 b# U}
  |+ u2 J/ _; g2 ]' ~" n0 x/ C$ ]. m. K6 a9 {+ v
void        APU::LoadState( LPBYTE p )
# F' \" Q) a7 s$ e/ u{
9 m+ n  b3 L$ A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' s! Q8 _* o; u& v0 Q/ o2 t
        QueueClear();. f# @6 t, |6 S% c  s* ]" C
/ ?5 x( }- Z# p! _- M! V4 C- p
        internal.LoadState( p );
4 |5 ], d. U8 R  B# `        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding" w0 z; m) V7 }. M1 Z6 ]
; P2 x4 @% {# a8 E) M; N4 @
        // VRC6$ M6 r8 }: c5 O0 }% ?- ^/ E8 n; h
        if( exsound_select & 0x01 ) {
$ E* r7 A4 p) n" @+ ^) n% T                vrc6.LoadState( p );- B; f/ g  o3 v4 G$ p
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ j! p: [5 |1 Z# i! S2 ^! `8 Y: I; t        }
. V0 z4 h& D% R( J        // VRC7 (not support)
5 q! f$ z5 Y! A) u# N5 x+ d        if( exsound_select & 0x02 ) {
+ x2 F) \% h& S9 s                vrc7.LoadState( p );/ [2 e3 x* F2 h; x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' F2 ^! r4 k5 M2 U# |
        }% c5 @( y; i- f5 L3 |
        // FDS% {; `* F" k  m( u* w% W
        if( exsound_select & 0x04 ) {' e# z: z" ]/ F4 n; k) s
                fds.LoadState( p );
0 Y7 t' g' j# x( {& `                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 T# L2 d4 e; ]$ U
        }- D0 `. w5 Q. w. O+ o$ N
        // MMC5
- @8 k0 I. [& C6 i        if( exsound_select & 0x08 ) {
0 f3 \2 [  \" \                mmc5.LoadState( p );2 `1 [0 @" Z# }9 \
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* H) b9 d: q6 Z2 I! u9 t0 h" H
        }! j2 d7 P# }0 e1 n4 R" ^
        // N106) Y8 ^5 V& G- _! ~* e6 @
        if( exsound_select & 0x10 ) {
% j9 t' d1 m! t4 H                n106.LoadState( p );9 B1 T0 \) d6 N/ j9 a4 J, n
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 U- f# g0 _' o# D; _) y! }( x        }! `  I% M* O; j& C4 [7 X
        // FME7
9 C& a4 Q$ \( T" l- R3 a5 M        if( exsound_select & 0x20 ) {
" D2 l- n+ M* E+ A; H. E' H                fme7.LoadState( p );, E1 s8 t! `! z3 L4 |+ l
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 }3 @0 Q6 d+ a4 ]6 a! K! B: I5 a        }% E" h- g. t1 s0 z
}
回复

使用道具 举报

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 " F" s6 \3 k& C7 ]# t- e
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. u9 {$ ]: t; I& I感激不尽~~
' L  w8 p* F' d- `0 @
恩 我對模擬器不是很有研究,; s0 n4 @. n1 `9 J" z
雖然要了解源碼內容,可能不是很困難,% |9 `( |6 C: F& |& ]& l
不過還是要花時間,個人目前蠻忙碌的。
3 f: \7 X$ s" _7 ]" E, {: f6 S
給你一個朋友的MSN,你可以跟他討論看看,, r$ ?- e4 t4 ]( _7 l' R9 O
他本身是程式設計師,也對FC模擬器很有興趣。6 |- a# B% z$ c- b7 K' |5 T- H

+ ?" P$ G( U3 J- G* T7 AMSN我就PM到你的信箱了。9 X! d& {; `9 n6 w" V( s2 l. D3 s

& C5 w( ?$ f/ C. F6 S. Z希望你能有所得。
回复

使用道具 举报

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~
回复

使用道具 举报

签到天数: 82 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。
回复

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
- r0 F$ T! t; j2 T5 g- |呵…… 谢过团长大人~~
2 y6 K+ R& v0 p; k9 m5 f
0 v; X) i' v! \' Y; P
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。
回复

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
* I/ f: g& F6 [+ r, ^) E  d  Y; B6 |团长的朋友都是神,那团长就是神的boss。
: v. v3 O: x5 y3 o, i
哈 不敢當,我只是個平凡人,
% r$ U* v! I' {. S要吃飯喝水,光吸空氣是不會飽的。。。。 :)
回复

使用道具 举报

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; u4 W" O* K/ f0 P, HZYH
" s( o0 y( W4 X7 G# GQQ:414734306
/ t6 |( ]% h; G, g. wMail:zyh-01@126.com
" g! M& c" _4 S) |. Y! n
$ j# p  Z8 @& B他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的
回复

使用道具 举报

该用户从未签到

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

使用道具 举报

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 w, C. b  ^# R
再次对团长大人和悠悠哥的无私帮助表示感谢~~
/ {2 p1 n2 b' Z0 ~3 F
不客氣  ^_^
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-8-26 03:17

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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