EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?1 g- g5 q/ W$ ^/ s& L+ k4 m9 Z5 K( ^0 R1 O
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 y" X( u' n9 y5 a楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! z2 O, a# W" {$ u* ^( j( N' ^这里有相应的模拟器源码,就当送给大侠了~~, N5 e. A2 ?5 J
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 \3 M, @9 d; b能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! P- p0 e0 ~2 a- t% k9 S
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 h+ ~: e; Q5 i- n) h- w这里有相应的模拟器源码,就当送给大侠 ...

+ [* P% u1 a8 C; V! b8 N" y聲音部分(Audoi Process Unit = APU):" i+ j5 P% H1 t; n! V0 g& y
.\NES\APU.cpp
' A# f. F8 a( x. H  o.\NES\APU.h8 r  w. i* {: l5 b5 {7 S- B

0 A6 `% o3 m3 d2 j5 f. \
) V) L+ K; r5 q+ Q. s7 R影像處理部份(Picture Processing Unit = PPU):' m  m+ S' [/ {) W7 X1 a( F
.\NES\PPU.cpp
1 Z& v, a5 Q  I, H1 J& I4 `7 u.\NES\PPU.h4 z2 p/ o1 z  |4 a& W0 w) N
2 g- M* y" g/ e, \. G
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 N5 p" R$ z3 U  B(由于很多专用术语和算法机理都不明白,所以看不大懂……). O# H; u. E. A1 ?# q
//////////////////////////////////////////////////////////////////////////
: M# u' X( o8 \- ?' W% D//                                                                      /// v4 J  x( [0 @# d( m7 z
//      NES APU core                                                    //
6 @$ T: I8 C2 a# u7 o  T//                                                           Norix      //' e+ @: f% M5 H5 e" n1 t' x+ N
//                                               written     2002/06/27 //0 I. |- {$ ]% x8 X. V" A
//                                               last modify ----/--/-- //$ S" m, p7 f8 c8 H5 ]* F1 l
//////////////////////////////////////////////////////////////////////////- W1 E3 P* H1 h1 W$ Y; u2 s
#include "DebugOut.h"
4 x3 {6 l* O8 z' a8 }& Y$ a#include "App.h"
6 ~6 v/ h" v+ s  ~#include "Config.h"
1 j4 E$ M- L/ E! S+ D- ~% U; N* j' \$ F
#include "nes.h"6 b2 |( X  K( c" g+ c2 n
#include "mmu.h"
# n$ ]" j$ `& X( Z9 o#include "cpu.h". _2 k1 o3 q" C7 J9 e: d
#include "ppu.h"& Z; q2 U$ l5 M* R6 n- L
#include "rom.h"1 a+ k5 f4 z( {- A9 M3 D
#include "apu.h"
0 H9 M0 \. k1 A5 Y0 f+ C3 V* r2 P; E0 x3 J. |4 j
// Volume adjust
" ^" j+ a9 v+ w+ B// Internal sounds: p' W* X* ~7 n, G* F" R7 T
#define        RECTANGLE_VOL        (0x0F0)
: P7 r2 u# w6 z1 }: {#define        TRIANGLE_VOL        (0x130)
3 y5 h/ Z( ~0 @4 D# e* M#define        NOISE_VOL        (0x0C0)8 s+ |9 q! i7 @& O. ~8 _/ K
#define        DPCM_VOL        (0x0F0)0 L7 V0 T" F, H6 S4 j
// Extra sounds7 m& j0 O% W6 D+ v" l1 A
#define        VRC6_VOL        (0x0F0)# g% a" X/ d! P* Q+ D
#define        VRC7_VOL        (0x130)
6 o8 x/ O$ i! {/ r! S#define        FDS_VOL                (0x0F0)% [; V7 n5 d+ @1 G. V9 P6 A
#define        MMC5_VOL        (0x0F0)
. v% x4 V" y8 Y# ]/ r#define        N106_VOL        (0x088)
" c& i  ?' M# T; C#define        FME7_VOL        (0x130): Y6 X8 q8 h9 r! X( h
  p: `5 n3 t/ G8 w' ~" M
APU::APU( NES* parent )6 d# _9 I& x( K& Z9 H; B; i4 `" T# N
{- w0 U% o" M3 k# o: `; ]
        exsound_select = 0;6 [) v. x, A  r. x' |

: x! w# }5 U% `5 Q6 G5 X        nes = parent;
, v. a- z. K2 B8 @, ~        internal.SetParent( parent );) X3 {8 w# c) `/ H( G

( w* d6 Q. F2 v6 M        last_data = last_diff = 0;
& U4 S& {) u2 f7 q
0 N; Y! R. b. K6 o/ E+ f3 f        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' k- \3 D9 |. ?  W$ P; Y4 u7 V. P9 F! }2 N: S
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );8 A2 k! ^1 y1 K, y' j
        ZEROMEMORY( &queue, sizeof(queue) );
; u6 r4 W" h' D3 r        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ S  u& Z" N# ~% O  C# U8 s
& _* [# r7 v% J3 ?+ b
        for( INT i = 0; i < 16; i++ ) {; i: K) o! }: c2 Y& i7 u
                m_bMute = TRUE;
# \4 G# {" p9 {: q7 _. R        }
8 ^: C, Y3 ?0 y, e- b0 w}
- i9 o4 a# [" i- f) H
' o! ]: |8 _% M  x/ `. Y3 }APU::~APU()
  b  e2 @# p; \{' {$ V0 m9 q% n$ ^( I- N1 u4 r' R
}" c/ |4 H: f3 {) B6 Z( }0 v$ D5 J* j

5 S: \1 J' P3 {: t# ovoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )6 I( ~. k9 U" Y9 F5 V  C
{
2 N1 I6 `+ H4 K8 |2 J! c        queue.data[queue.wrptr].time = writetime;: e: J  K- D0 i0 U( F% q5 X
        queue.data[queue.wrptr].addr = addr;  n3 `$ q4 k8 p" G
        queue.data[queue.wrptr].data = data;# _3 v2 p( X/ v7 ?
        queue.wrptr++;. k5 H% `$ i8 v8 O9 P% W
        queue.wrptr&=QUEUE_LENGTH-1;. G+ r: u; m) y6 P
        if( queue.wrptr == queue.rdptr ) {
: g* \. F- ^$ i0 ]4 `( W6 |  s' V$ i                DEBUGOUT( "queue overflow.\n" );
9 \# ]3 Q* M; X  j$ F9 }6 Q( T        }$ O; C3 u+ A) T/ \! o
}, f% Y+ }6 d; @- b- R4 a$ V
+ |0 G" M- g& d4 w+ Y! Q, ^
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
, X! F2 [, x( ^5 l! I{
9 g. G3 {0 ?0 l7 w/ b& P8 \; }( `        if( queue.wrptr == queue.rdptr ) {
- k9 G+ R: {% X1 W                return        FALSE;' x  c; v, V7 Z* B- _
        }
3 h$ S  M$ J2 q8 g+ ^        if( queue.data[queue.rdptr].time <= writetime ) {! ]+ V/ u6 m& X+ ]& J( x
                ret = queue.data[queue.rdptr];6 e! D2 t) J! D1 V8 |6 Y
                queue.rdptr++;5 a" R4 c* N9 ]! n7 x
                queue.rdptr&=QUEUE_LENGTH-1;
1 g- {) d: P7 y3 b                return        TRUE;
( R* Y  _! T6 n$ x        }4 N3 M" ~' Q- I. N# B3 \- g( c/ }
        return        FALSE;
' p$ ~* K+ a' f8 G. _6 Q- w/ l}
/ S! Z6 z& {" e3 y$ G' ]
* q6 U- R6 \, O# _( v, j$ evoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! A, T7 x: s% L1 d
{1 J3 [% j9 B; w5 m% {# ^8 C
        exqueue.data[exqueue.wrptr].time = writetime;0 p! K$ B1 l- ?/ m+ O
        exqueue.data[exqueue.wrptr].addr = addr;
: z. B7 x2 G' u, `" }        exqueue.data[exqueue.wrptr].data = data;# o0 A$ Q2 M/ G7 j
        exqueue.wrptr++;
8 S& z- o  k6 P( K4 M$ v( `        exqueue.wrptr&=QUEUE_LENGTH-1;$ C( k- J6 l1 ~- h- N- Y( u
        if( exqueue.wrptr == exqueue.rdptr ) {
' Y% V. E  {' A) O                DEBUGOUT( "exqueue overflow.\n" );3 R/ P# y- G; Q, `( I
        }5 ~! G+ V9 `; I. O
}: @! P4 r6 _, Y& E. r* ~, A; z

/ V& ~" w9 g9 R. R9 I3 GBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )$ r5 n( Y/ b: j; I: P
{
( b. h2 C1 w- n1 o# b" U' u2 O1 q        if( exqueue.wrptr == exqueue.rdptr ) {* |" |0 q) V+ F
                return        FALSE;
5 c# ~1 N+ g7 W" G        }# z$ |9 H( l9 ~2 U) m, e
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: K# b6 X# }" V  R# f" r& F' i3 e
                ret = exqueue.data[exqueue.rdptr];
. X& E! I) m- n; T: l                exqueue.rdptr++;2 F1 F  ]! e" ^  c
                exqueue.rdptr&=QUEUE_LENGTH-1;' Y1 ^& n& z% F. I3 n( ]# ]
                return        TRUE;
! N6 P: f8 v5 z& H: y+ W- v  e        }
% Z- ^: V* Y3 l, l" q. L& U% }        return        FALSE;
" V( T+ l  ~$ H) U/ N9 {$ A}" G; h3 _3 M4 y: g) N/ K( z
% }" b% U, b# ^- r1 V$ M7 O  X
void        APU::QueueClear()6 ~, R/ P9 ~3 a3 u2 Y/ M
{
# ?& Z+ e6 ]4 A  p5 ]        ZEROMEMORY( &queue, sizeof(queue) );
, y) g; X% W' G0 O% D- i        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, N4 Y  y  J$ F1 _1 l9 P}
$ J0 |- A' ?6 I! n+ V" k7 O0 C! ^
void        APU::QueueFlush()2 ]9 {3 A# z% [$ }7 T; a
{8 H4 u0 ]- o8 l
        while( queue.wrptr != queue.rdptr ) {
6 I5 x8 b/ o7 V+ S, y1 }3 N                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
5 j) _7 r# c% E5 K% g( f4 `( W( M                queue.rdptr++;' O. I9 f; _! V! l; U
                queue.rdptr&=QUEUE_LENGTH-1;
$ {( n8 x6 }  V9 }        }
: R& ]; C  \, Z7 v8 |0 m) t* c" X
5 u7 @2 p1 ]% O        while( exqueue.wrptr != exqueue.rdptr ) {; Y, ?+ P2 ^% e- E2 ?( Y9 H' A$ f' u
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
, G8 _; p4 w$ a6 L) T- V                exqueue.rdptr++;
: O% U5 V# {  u/ g" N2 F) M1 v                exqueue.rdptr&=QUEUE_LENGTH-1;$ \' W0 K+ a1 h  S
        }
& |! q7 R1 Z. U2 a# I0 {}5 Z/ r- h) X/ N/ F9 m
. x  c4 E  m7 M- c& @% m' H
void        APU::SoundSetup()3 C2 v% m6 ^; D2 j
{; r% t1 P# {! t* u) f) E
        FLOAT        fClock = nes->nescfg->CpuClock;
0 i4 H2 }" Z: U/ D2 [4 w2 x        INT        nRate = (INT)Config.sound.nRate;: o5 Z# p0 [8 R. H) ~) J
        internal.Setup( fClock, nRate );  z% k- B) |5 H7 k* S+ p$ I+ A2 `
        vrc6.Setup( fClock, nRate );, o3 @- z$ j. [7 t  n! A
        vrc7.Setup( fClock, nRate );2 t* P& B/ y  y& s8 }) @
        mmc5.Setup( fClock, nRate );
/ F2 ?5 ]3 L+ q        fds.Setup ( fClock, nRate );
+ P% m) `% E; u        n106.Setup( fClock, nRate );
8 B' N1 O4 j/ s        fme7.Setup( fClock, nRate );
  H. M3 v5 k, Q+ |- h$ Z  q1 R7 B& M}
4 V7 Y" a2 u; |/ [7 ?1 \- ^4 V+ `& D
, G: q8 f/ G, t2 |; Wvoid        APU::Reset()
7 L+ v& K9 m- S1 M" \! ^& K{
: u* T/ F0 e+ z3 }* o        ZEROMEMORY( &queue, sizeof(queue) );
; G( i1 E6 S+ M( s        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% P7 C$ c, R. m% i( z4 U
$ l: W$ [% [- o1 ^        elapsed_time = 0;" l; e4 |5 b% w: Y8 l

! H% s% ?3 a2 H- y7 t6 N# k* g        FLOAT        fClock = nes->nescfg->CpuClock;
- N6 k& N5 C3 H- m6 F! h* J        INT        nRate = (INT)Config.sound.nRate;
6 `8 B, O6 v6 V: v, @: ?) q4 L        internal.Reset( fClock, nRate );
" M: u0 a3 O: k. Q        vrc6.Reset( fClock, nRate );
- u* c5 e. ^. B4 i        vrc7.Reset( fClock, nRate );
6 `' y$ _) T: X. f, m9 k* F        mmc5.Reset( fClock, nRate );( M: t" x0 v( x
        fds.Reset ( fClock, nRate );7 A* l% T( I0 Y+ Z9 U9 q& W
        n106.Reset( fClock, nRate );" Y+ D: D* }& A) k6 B; [1 X& H, W) x
        fme7.Reset( fClock, nRate );1 e* G9 d$ T% F; r
) o1 `, c* a0 _" L
        SoundSetup();
2 {) z6 Z7 L$ t}/ Y- [; z  l3 {- G2 O: G5 }
$ ^! b; I& }, p) U
void        APU::SelectExSound( BYTE data )* x8 `8 p) v2 f8 V# J" z/ O: n/ o! U
{
+ u. c  ^/ `; {9 J% l" s        exsound_select = data;
+ J. n2 K& q9 c}# [3 J8 k* D4 k, q3 K, @2 y2 T/ s

0 |! @; z  D+ E: A4 C- r( i: T/ ?BYTE        APU::Read( WORD addr )* Y& S, l3 P/ W2 B
{
1 _. ?; h* n9 M8 H        return        internal.SyncRead( addr );4 W; k5 k4 k& h* g6 W
}7 p. K( L  M8 K* n; e7 Y
/ T+ A# A. C5 u4 }3 P3 ]: r0 D6 z
void        APU::Write( WORD addr, BYTE data ), ?: t- ^: v9 q. N+ ?
{
# a" H9 Y% W. `  I" B* I        // $4018偼VirtuaNES屌桳億乕僩3 R$ m+ b) G# _  T' l0 S& O& v
        if( addr >= 0x4000 && addr <= 0x401F ) {( d2 i, t3 y, f& @9 e0 w( R0 O
                internal.SyncWrite( addr, data );
6 q& g! T: u: q& u$ N                SetQueue( nes->cpu->GetTotalCycles(), addr, data );1 f# l8 x+ A  L" V  o
        }
! l. H" E) V4 X3 W}
1 z  K8 l, s( q0 G' @4 v2 B$ F2 J1 k8 n% ^, R) F  F. j6 `
BYTE        APU::ExRead( WORD addr )/ {+ s2 p, j- j" {
{$ H0 P7 J4 b7 h: y6 {1 M! H: `: Z
BYTE        data = 0;/ r; Q" O# a  S- p8 L
1 r5 A* r! l0 D" ]) ~0 W. F
        if( exsound_select & 0x10 ) {
- m# g- D5 ^/ c                if( addr == 0x4800 ) {6 C6 S5 z8 M! ]6 a
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
' X5 p, ?8 g9 Q/ O, D; d8 o# ~                }6 P6 U3 X4 {# C8 m+ J: H( O! x
        }" }8 T( D# W8 @; B' T8 S" m5 D
        if( exsound_select & 0x04 ) {
! ~. n; s/ e( o: H1 A                if( addr >= 0x4040 && addr < 0x4100 ) {
3 u( W4 C2 ~& b" T1 R( H/ v                        data = fds.SyncRead( addr );8 ?4 o3 m2 A. d/ O# x" \/ F# h
                }9 B; e( J4 m. I5 V5 Y9 Z
        }% ^$ B, U2 n" [. D1 b
        if( exsound_select & 0x08 ) {
0 S% s' E+ ]) b4 }; S                if( addr >= 0x5000 && addr <= 0x5015 ) {
* e0 Q$ _/ y2 a1 O, N                        data = mmc5.SyncRead( addr );
1 h; q9 P' d( P* y                }* V+ t5 J5 ?% H* r, ^
        }
7 O0 l# q: C. q' r8 ~  Q8 A- f1 |" x" z- C
        return        data;
! b8 T: ~+ [, r: S5 X}
; O; Q: j7 H( y( U% g" A, a- H) d4 ?' t/ C
void        APU::ExWrite( WORD addr, BYTE data )1 o9 ~% S& m# Z# m8 t- z, G( w
{
, e6 s% ?# x5 e9 O2 Z% u9 U        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );0 b5 M& A% U/ o, c/ k
7 r& v- P  W: v' m, n
        if( exsound_select & 0x04 ) {
! [5 @  N  V* S. j0 [: I5 M' }                if( addr >= 0x4040 && addr < 0x4100 ) {
7 M5 |! N5 i* Y2 D4 N6 \                        fds.SyncWrite( addr, data );
' p9 B0 g% \2 F% R+ c                }
' }+ t$ r+ d* ]# F        }/ `/ o" [( c, F9 A; o

: @$ m0 g) i$ Q7 E3 E! v) `        if( exsound_select & 0x08 ) {
* K9 N0 X2 u: I% f1 h0 a                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 E2 K; ]3 ?& f& W+ o4 v5 B  ]+ A                        mmc5.SyncWrite( addr, data );
; h( L8 h( E  d3 L6 V% E3 W                }& q. I) M! G, L4 @9 P
        }
, a8 ?# ]# c1 {2 G6 |}, h  e3 Y$ z# e( I% l# v

5 u2 O  G/ j- `5 K' Fvoid        APU::Sync(): T6 R) i0 O8 Z% _" n) K& H: P6 @
{( w& {6 x; N. u  f* J8 @4 B
}; y, _' Z8 N! P; w
" H/ i+ L9 o: y/ M9 f- w
void        APU::SyncDPCM( INT cycles )4 a( e  n  M& r9 R: w
{
( C$ c$ F! m; I        internal.Sync( cycles );
/ [$ ]8 Z* W# d( j
' o+ P" c+ Q7 o4 A7 O        if( exsound_select & 0x04 ) {' V! [- F9 t4 S* d
                fds.Sync( cycles );
; n! {& X+ X; v        }
6 v" J" Q, H3 i: k" X# M6 O9 s        if( exsound_select & 0x08 ) {
5 S% U2 k+ b6 C                mmc5.Sync( cycles );  N" d/ U' i4 L
        }
7 N( U, F: O5 N3 ]1 ?2 e  R4 m}; j+ c" S+ E- k
" S. }  H' |# Z
void        APU::WriteProcess( WORD addr, BYTE data )( o' X+ w6 [* K) s- k1 B$ @+ N
{
8 m! Q& o  A! H7 J. v8 B/ T        // $4018偼VirtuaNES屌桳億乕僩
5 h' V' a9 @  ^. k. a" ^4 t        if( addr >= 0x4000 && addr <= 0x401F ) {
: M8 q8 T5 D, B7 v6 r" @                internal.Write( addr, data );9 @4 q5 i% L% l. ^, `* E/ s
        }
( K/ k3 U) F5 I% i}
3 i6 y/ z0 J+ b) @# ?& `) L
! t1 f# j) S& Q" S: bvoid        APU::WriteExProcess( WORD addr, BYTE data )# h2 ]1 x, H5 r0 h
{
0 \! l  Z- w  {; C2 Y- u        if( exsound_select & 0x01 ) {' _" d) G) @! c. E/ d- `. ?. j
                vrc6.Write( addr, data );3 _. D0 @' a4 F  C: p$ X
        }
# l# g/ b% d3 b* ?( ~        if( exsound_select & 0x02 ) {
% U$ ]5 U' A% a2 P                vrc7.Write( addr, data );- N2 y) N) v8 l2 X$ q% E
        }
# U. o1 B6 s3 i: @( C8 |1 S9 e  H        if( exsound_select & 0x04 ) {. |' d: o/ r; Y8 l/ r& l
                fds.Write( addr, data );( }! F1 D+ E" }/ V
        }2 q7 h2 R9 b; e4 ]# h  W8 d
        if( exsound_select & 0x08 ) {
- j  [( e" c3 l. I5 ~. L                mmc5.Write( addr, data );
( x  q- s! d! A2 |. t- ?        }, P( a0 p, S& X6 ]
        if( exsound_select & 0x10 ) {
- S# S' l. `# d; x) N+ j* w: S                if( addr == 0x0000 ) {
8 G# [- t' w( H# y2 l                        BYTE        dummy = n106.Read( addr );
* `+ c1 l4 `! l* b                } else {, E* S$ W6 B. M
                        n106.Write( addr, data );, i5 _$ ^/ z( a8 ^0 R6 ~, S( h0 C
                }1 t& O8 x% v  H3 T
        }
4 x8 e$ E2 j& R- A& o3 M8 U        if( exsound_select & 0x20 ) {: O) U% ?+ f% a
                fme7.Write( addr, data );% ^( j0 j: U; U' \9 U" ?- O2 X! q8 s
        }% M8 v8 L8 K- R- j6 K1 ^0 x
}% r3 n5 y" }0 W' R
% B& V4 C+ v5 z" A9 ~
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ); i$ U0 y7 x& r5 L5 `
{
7 v* Z5 m4 a. g; D( y. c8 K* @: T% KINT        nBits = Config.sound.nBits;
( d* z( ]9 p5 L4 J! {DWORD        dwLength = dwSize / (nBits/8);
9 N& [0 _1 v9 }7 PINT        output;) U6 s% }$ |) J6 q: L  W
QUEUEDATA q;# ^0 Y9 R! C* E8 W. o
DWORD        writetime;
" v/ e$ @! n! A* P* K! N/ F9 y) T2 f+ ^' @4 [' H, M
LPSHORT        pSoundBuf = m_SoundBuffer;
# O* T( Z1 h$ V! iINT        nCcount = 0;* p, }% m  f! y8 [
; a" X" q! U9 h+ d8 j5 e3 _
INT        nFilterType = Config.sound.nFilterType;- \$ N! `8 w) {2 ~7 w/ _" m
6 C" t9 s' K- M- w5 C) v
        if( !Config.sound.bEnable ) {
; h- q; \6 j* @                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );# `+ w, F/ I- M
                return;4 @6 [9 Y! ?5 p/ \* e
        }
% I* }5 c$ W5 c+ Q
. ?" l/ @* u8 o( e# A        // Volume setup
6 j5 q5 D  j4 w* s        //  0:Master( d( L5 _6 p4 Z+ g" q( `2 Z
        //  1:Rectangle 1) K" }5 U+ N* r( y! O# Q( V
        //  2:Rectangle 2; k9 G) U: A: O* W1 X/ z1 s0 r
        //  3:Triangle: @. @0 h& |, o  H! g) w# G. H* m* j
        //  4:Noise9 A4 W( W8 i2 t
        //  5:DPCM
* N, j# t, H$ ]8 s2 P        //  6:VRC6
6 g- i% }5 r2 q7 @7 K* d1 h        //  7:VRC7* k. f: V5 _- d! P2 b
        //  8:FDS
+ C2 h# e2 B6 M8 D; S        //  9:MMC5# `" {6 C4 b* O( J
        // 10:N106
1 B8 k" c/ u" M# F3 g# G        // 11:FME7
& ^9 f% v2 |8 }0 p* w        INT        vol[24];
( `5 F% r/ E! a$ b2 J        BOOL*        bMute = m_bMute;
# \; M) |, P1 v        SHORT*        nVolume = Config.sound.nVolume;& v9 p  d) m" A9 T* ^6 {6 G0 m
4 s" h! z6 V' |/ ~9 \0 ]
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
1 a5 c5 G) O+ i; s& Q: S6 u* D, V& N- t4 c6 N
        // Internal. ^& {& P, J- ~6 _
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
0 Z3 C* [5 b8 `: g2 f        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
( H  E- m( y# S4 X        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 l( ^  `8 g( I& X1 [& b
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 ^# z  j* V% I& F4 R, A        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
, b0 |2 s; z0 Z& ^& J" v
4 l1 W0 L, L! ]5 V# w5 D% a9 D8 z        // VRC6; M9 D# L: ?- m7 f1 u
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  n% L  |) g0 V6 f$ M. \1 E* ^/ H        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ U+ C. R9 J% W& n$ Y- y, e5 u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  s) t- |* m* }! ]

3 d5 M* ~" ^2 a$ K  r' Z) X        // VRC70 N7 ?. u' [$ a9 @; I9 p
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
& @$ t* J5 N$ p4 w+ N- E+ ~" N' _/ e
        // FDS8 `( }. s% B) F, V2 j
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
2 G; Z) T. w5 ^0 u
" D7 h: B( E: Y- r+ U% d        // MMC5' i4 Z  A3 Z( T* {! ^/ M0 ~- u
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  M* {( h: `: z1 L. ~
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! Y- S4 ~% A& {
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 B1 r9 H: K+ C; s
+ Y3 j- P* `3 ^        // N106) e! X0 ?  H0 q- R" a
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( Q* N, k& _1 s. I
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 y, J6 w0 }  I$ F
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; A4 D% s2 t; D0 q* w# O4 d
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, S) e# ^9 W; k, ?/ z
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 M* d" C4 |% D5 J. W$ r
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 h1 k9 b% Y9 T& R! o) }
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 k% A! `, Y8 ~        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" A3 {" N2 d4 C0 H  A; G
4 j# r+ l9 j! p  c% C. ~, B
        // FME7
# L" g6 |/ a7 Q/ z9 p# p        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 H. ?2 f( |  R; [% f% Q5 ?        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 g% R: Z7 e7 u9 s' [- g5 e; E. _        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; L# K* D7 x$ D8 E  v4 e7 [) }6 X  j4 e$ n8 N- n. e
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
4 Z. B/ X# i/ \        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
  X! V/ w* e# ]9 F7 v
7 ?1 `4 |! t, {* P$ r& l        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
& a% D/ u1 P- ]" w        if( elapsed_time > nes->cpu->GetTotalCycles() ) {+ N( x0 M+ j. Y% U! q) U( _
                QueueFlush();' r7 q- u3 O, E, d5 `( J, `0 s# Z1 E
        }+ ^" I1 ~, ^* X7 z9 S1 t' s

' a$ _  \& w1 v  G+ n        while( dwLength-- ) {
$ H# S9 \) @( G( O% e  W* G+ y                writetime = (DWORD)elapsed_time;
$ E# E- C+ Z& C% O6 v# o7 r2 O: c9 ]5 {7 A) F
                while( GetQueue( writetime, q ) ) {
$ p( h+ j2 P" V; R6 u9 D, d" d1 m                        WriteProcess( q.addr, q.data );
; T2 k; I% [. {# u3 O' l2 n. J, C                }
) l" i' a& E0 n" ]4 t  {) ^" a1 H% e) O* \' X0 f& G5 K
                while( GetExQueue( writetime, q ) ) {* Q) c: j9 ^) L! C% J
                        WriteExProcess( q.addr, q.data );
& a3 I3 U) v/ h+ F6 A% k  _                }
" s" `% N- R* o  `' C" ]: |
3 ?6 b  Q: i  ~. j5 Q. R! H                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
# D& m6 C4 m5 L                output = 0;
* p8 ^# Z# _- d* Y) p1 f" d' O                output += internal.Process( 0 )*vol[0];. [* ]# m3 G) ]8 I
                output += internal.Process( 1 )*vol[1];
+ v" w9 B) C3 g" @$ P1 m0 g                output += internal.Process( 2 )*vol[2];( Z5 m- M' h  `' E! Y* W( {1 f# ^
                output += internal.Process( 3 )*vol[3];/ s8 i1 g7 Q$ m. x1 G+ i
                output += internal.Process( 4 )*vol[4];1 C) O$ e% {0 l. r% E& M* W
7 b# {& A! s- p, G2 L  g3 l6 \4 R
                if( exsound_select & 0x01 ) {: s  a7 x6 K) `
                        output += vrc6.Process( 0 )*vol[5];) g" M! V) M5 ]5 `4 r
                        output += vrc6.Process( 1 )*vol[6];
; L& @7 e/ F- D' k" ~1 m, b                        output += vrc6.Process( 2 )*vol[7];6 p4 \  a) H" p  I
                }. ^' E& _! n/ C# X0 o$ R& q& I
                if( exsound_select & 0x02 ) {( y) V  H& Z& t2 I; D6 V
                        output += vrc7.Process( 0 )*vol[8];$ Q: u, k1 A/ i" ^
                }
9 g& B$ X- G$ W, [: B9 e                if( exsound_select & 0x04 ) {
1 k; a+ P  ]* _4 U2 T# ?                        output += fds.Process( 0 )*vol[9];
; @* N$ D3 ]# k! V9 E' u: T                }
" m! H0 ]9 Z! y* M                if( exsound_select & 0x08 ) {, t' r4 }& A/ v) J2 l( p
                        output += mmc5.Process( 0 )*vol[10];
& ?, M9 I$ }# f5 U2 A                        output += mmc5.Process( 1 )*vol[11];
- k- R6 q6 z; g+ @/ V/ {  X: H- V                        output += mmc5.Process( 2 )*vol[12];! _. z0 q4 C5 u
                }
3 H2 L9 O3 u" F2 g! n# K                if( exsound_select & 0x10 ) {2 U( [2 T1 U( i; J
                        output += n106.Process( 0 )*vol[13];
* }* S5 n* ~9 V( ^                        output += n106.Process( 1 )*vol[14];
# Y) R$ j. c- W; X' \9 L, ~9 e                        output += n106.Process( 2 )*vol[15];
7 A1 i0 z/ i4 T/ q" \$ H                        output += n106.Process( 3 )*vol[16];+ Z, u/ i/ w! I0 L
                        output += n106.Process( 4 )*vol[17];
' U6 ]4 U4 K6 l5 I% Y; R# t; w                        output += n106.Process( 5 )*vol[18];4 Z; H1 t' |8 _' T: U5 Y
                        output += n106.Process( 6 )*vol[19];  r' L! I$ a% h+ f, V
                        output += n106.Process( 7 )*vol[20];! t1 N! E, C. g+ w9 H
                }+ [$ N9 P+ m2 q8 b8 A4 {1 M$ R' E2 i
                if( exsound_select & 0x20 ) {6 ^0 C; s' d* x' H8 j
                        fme7.Process( 3 );        // Envelope & Noise
0 @  L. W+ T( ]7 ~- N5 @3 d                        output += fme7.Process( 0 )*vol[21];& m# i9 L- e$ z
                        output += fme7.Process( 1 )*vol[22];
! |$ ]8 q3 E! ^, u" I2 A                        output += fme7.Process( 2 )*vol[23];; g) T5 q' n# ]9 S# G* [' c
                }
7 f6 J. Z! Z6 q& M8 L$ a
3 ~* Z  Q2 f/ ]6 K+ Q9 }                output >>= 8;
5 i1 ~4 F; P" X. ]1 l6 m( d5 i% j
1 X& @2 m4 I' @: o6 K2 z: C+ R6 b                if( nFilterType == 1 ) {0 M( H: c. K$ P& ^
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, T6 J8 @6 c) G                        output = (lowpass_filter[0]+output)/2;, D8 g: G) X; ^0 ^) @
                        lowpass_filter[0] = output;
0 k4 Y+ M# E6 P9 l5 b! D5 J                } else if( nFilterType == 2 ) {
3 j" f) i5 c/ Q7 Q& O                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
1 K- Q2 c/ i  |) o                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;0 w  k: j' d' n
                        lowpass_filter[1] = lowpass_filter[0];
; \3 C' D5 f8 [* Z; r                        lowpass_filter[0] = output;
/ M8 l! L6 ^! _8 q& m- q0 s* U# \% y                } else if( nFilterType == 3 ) {, j/ e: q! C: p1 K6 ^2 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
, ~9 b4 W7 E# o% k0 F9 I( k                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;9 ~7 t+ N/ A: N4 d8 [$ _
                        lowpass_filter[2] = lowpass_filter[1];
, Z0 K6 }$ n  p3 `1 Y                        lowpass_filter[1] = lowpass_filter[0];
6 o, S+ a2 l8 v1 W: h. s                        lowpass_filter[0] = output;
, M& m; s; Y2 R: B! B                } else if( nFilterType == 4 ) {
6 l; R2 J' P7 ^+ `% m0 g                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 Q# O0 k8 O% {! i" d. v, E
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
( \" A4 [+ \- Q1 y                        lowpass_filter[1] = lowpass_filter[0];  K0 \3 ~4 P6 w- U
                        lowpass_filter[0] = output;
# ]- R$ q- G4 \                }; }* a% M" u' }0 |8 q8 V3 I

8 I3 a. S) r/ h+ ^6 F% i#if        07 a, H& D" T0 T  @4 R. ^, s7 D
                // DC惉暘偺僇僢僩  l0 o/ `) }# i& b) c/ X
                {: ~* N# K2 \0 V2 r% ~" q& U
                static double ave = 0.0, max=0.0, min=0.0;9 |! E: v& B* F( D! c& U
                double delta;" l/ i3 S2 |2 D; I3 h5 e- b! m% P
                delta = (max-min)/32768.0;
6 c: J+ w8 }* j- l+ c5 u& l                max -= delta;4 r# ^- m. _: v0 A
                min += delta;5 l) L5 c9 V8 j1 O. y2 ~- b
                if( output > max ) max = output;( l! y! W8 Q  I  u
                if( output < min ) min = output;! m( V  g; U9 h# \- _9 b, D
                ave -= ave/1024.0;
, S- t5 ?) z/ D& d/ ?& f( }8 ?                ave += (max+min)/2048.0;
* S) O4 v+ Z0 {' c" [                output -= (INT)ave;9 U$ J# u' @' K  L: a4 E! a. K4 a; |( j
                }
- i; [/ O5 H0 s5 v( Y. m6 Y#endif) r# c( D" m; g1 H8 j
#if        1( w0 ?! G. r! C3 N
                // DC惉暘偺僇僢僩(HPF TEST)2 d/ O% g! T+ j
                {
5 g) K* f' g" V+ J9 r4 S9 G- q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! f& Y6 \0 {/ w                static        double        cutofftemp = (2.0*3.141592653579*40.0);
1 @: R% o. U& Q' E: O9 T" y/ h                double        cutoff = cutofftemp/(double)Config.sound.nRate;8 [$ b9 C9 b/ [( _
                static        double        tmp = 0.0;
" ~: |( s& `, s; E$ e. _. N                double        in, out;" z' @2 g4 L; D3 a- k0 o4 Q

! T+ s/ g% ]! l( _                in = (double)output;4 A( z5 ~9 y$ u
                out = (in - tmp);' c* V6 n# g! e/ A8 O/ h
                tmp = tmp + cutoff * out;
  G  q$ z4 V+ D+ c0 _( w7 S  j) K9 g' Q( A. C1 w; d' X
                output = (INT)out;1 p3 \4 q1 F- N, l1 @+ A' \8 E
                }+ g1 z2 q/ a# b3 h1 z+ g0 \! t& S/ P" B
#endif
( n( _1 c: R( z: q" [' I#if        0% \, i+ b$ L* x* T( y
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% S3 P$ E' a. _
                {% c, l; D/ t& J2 }; F2 b+ b6 ^
                INT        diff = abs(output-last_data);
% ]2 A' H& W  ^, E                if( diff > 0x4000 ) {
4 L9 Q9 n$ T- u& x                        output /= 4;
" {% h$ ]$ s, W( p. v5 X                } else & d- W' S( g, s# A1 F3 \
                if( diff > 0x3000 ) {' D1 F) G! m1 w9 U0 l# ?8 [9 r
                        output /= 3;
1 U" ^$ J3 Q- q  U                } else# o3 c! F' G5 ^
                if( diff > 0x2000 ) {7 c- j8 `' b4 X; x) ^0 `  [
                        output /= 2;3 R: W2 @6 |, P
                }4 s! y2 |/ ]% I" u- v
                last_data = output;
) Z$ A* E6 K+ U1 U; ?! F; p                }1 P* ]! r/ D4 {" q! r! m! `+ h/ t) A
#endif
5 S7 U- [# ?/ u# ^$ l3 M: n& U                // Limit
0 f0 j: g; w  q5 G- E1 L  E& d                if( output > 0x7FFF ) {" K# W  j8 C% F
                        output = 0x7FFF;% k# K, F6 u& @: r" Q  j8 D
                } else if( output < -0x8000 ) {7 t% b* D6 B2 U4 u- N1 m% l
                        output = -0x8000;- k8 ^; e' G, v; z7 T
                }
; |1 Q) [' Q5 g* O+ m3 t( e( a- h) Q
                if( nBits != 8 ) {' n# I8 L+ y5 H- T! T
                        *(SHORT*)lpBuffer = (SHORT)output;
2 i+ r6 v" [/ p! g  U6 D                        lpBuffer += sizeof(SHORT);% [( E2 d. O+ @* [, w- F- S) l/ X
                } else {6 I+ {) A, m2 O+ r
                        *lpBuffer++ = (output>>8)^0x80;2 I" N7 \% f2 |. O
                }  O. {) Y# N- o# t( \
2 |9 q6 `4 U, U* W
                if( nCcount < 0x0100 )( n  |: w" x* F: L- Y( H2 N9 ]
                        pSoundBuf[nCcount++] = (SHORT)output;
, P6 K+ O/ O6 f& W5 O% i
+ ]* o/ i3 n  w1 R//                elapsedtime += cycle_rate;  T2 n) [) \% N, R
                elapsed_time += cycle_rate;' p- O$ ^( A1 Z7 @
        }; g9 S% l$ u2 h( q. ]5 S' ?/ m
5 E8 x: p8 \' n, v* F" D# ]% T
#if        1
8 D; H7 [3 S* |$ s# B        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {- [1 w, q, M, L+ C5 N. P
                elapsed_time = nes->cpu->GetTotalCycles();5 k) l. Y2 d, u$ G; q
        }
" h, x* s# T' H$ B; M6 ]+ ]' t) ~        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# {# C: O9 ^$ X0 c% x$ j
                elapsed_time = nes->cpu->GetTotalCycles();  c, i1 z( n* l# o$ R6 V: u  j4 \
        }0 _6 t' i! Q7 X, r3 u% i
#else0 n/ L2 M9 A( ^
        elapsed_time = nes->cpu->GetTotalCycles();
- H6 R6 K1 Y# ?8 j0 j7 V#endif
7 ]7 d# }8 c; ^3 h$ n' n! I}
7 Q: E% L4 W' T0 G  F4 \; a; S4 w- F2 _
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ p/ ^; R5 F" l% x+ C1 s7 qINT        APU::GetChannelFrequency( INT no )
  u& c2 `( Q& k4 x7 u: Z{! ~$ R  H( D0 y- a
        if( !m_bMute[0] )' v) c! Q3 A' k) i3 P# c* q! A
                return        0;6 n3 C, O) A6 `
1 ^5 q6 ]* _/ w
        // Internal
* y1 h# C$ W3 Q/ Z# K3 B        if( no < 5 ) {
" m  W% v7 z1 e                return        m_bMute[no+1]?internal.GetFreq( no ):0;, p3 }* z) `  Z* L/ @" Q
        }
6 V  v! t8 c% o3 d( E        // VRC6% z5 O, B8 E2 d( j; s, Y, x( N
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ y: V1 S. m* D: C) B# m
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
1 M9 j: m: O, z1 v& A2 I        }1 R6 y1 i# |8 f1 ], _
        // FDS
( o3 ?( e0 M& x/ B( F# S        if( (exsound_select & 0x04) && no == 0x300 ) {7 J4 p% I2 V' w" W9 f
                return        m_bMute[6]?fds.GetFreq( 0 ):0;! I$ x" B( R+ _3 Y
        }0 Y: `1 z$ [/ C" F# {
        // MMC5+ E; ~( i- d, K7 X5 c1 d8 P
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {& b: Z4 A7 H" J) q9 `* |# ^6 Y( [
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
1 f/ X9 l$ e# N3 W# M8 q3 X        }
% e2 H& L, H& b1 S1 [2 C+ S        // N1065 O$ ]( H- P* D' u8 W! d9 e: [
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 s" y. D$ i  h$ Z5 w* x                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' f: o6 d; {' M$ t7 C' f        }, R: z1 i: O( f5 N) F
        // FME77 R" i* L) {" f2 Q4 ?# w0 V* n  i
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {+ M+ |5 O4 ]- V! d
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;2 e5 |+ ]' a$ b# n1 b$ I3 x
        }5 [& r& s1 z% X% u( y3 X( L
        // VRC7
8 I8 g4 w0 s$ s; _' `3 w+ w        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
  I# Q+ ]( O: O/ D  P' [- H* w# A# Y6 z                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& k% x; J- Q% F1 Q" _- V7 [0 G        }
  x6 N+ ?' J& n# J) u8 Q! Q' O  _        return        0;
3 T: t, p, x( _4 l}
* @* W/ q. |' P* u* G. R0 Z1 U6 s
4 r. X; D9 i2 x// State Save/Load
. m* w7 T) P+ Evoid        APU::SaveState( LPBYTE p ): p# E8 a  h) Y/ q. j
{
8 f6 b. K& D% h; o4 G#ifdef        _DEBUG3 t3 W* Z9 s6 L0 E/ s( z
LPBYTE        pold = p;
4 Y: s& |" C! J' m. e! G# v8 M#endif" M/ R' d" K% h' j" v/ F1 S. [
6 v  d2 W" p3 u/ {: r
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! n5 _' x: ?/ ?& c0 i/ T* o9 o2 L        QueueFlush();
2 p" E- ]; e/ ~+ V0 x( c/ W8 n7 _6 u5 u2 k
        internal.SaveState( p );
+ N  x5 R5 l0 q; E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ K$ W: f: s& q# K% j
6 D- k) J' I) k- ?* r
        // VRC6. y8 a: Q2 u- M3 G5 s* M, L
        if( exsound_select & 0x01 ) {  m6 t- c1 ?7 Q$ o8 S
                vrc6.SaveState( p );
$ W$ ~9 F( w5 j" s% N* b3 e                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ q6 s2 }4 _. y( f  @5 G! Q' |        }! Y1 x2 _6 }0 `
        // VRC7 (not support)
; O# b) J9 w4 e$ A( X        if( exsound_select & 0x02 ) {
3 Z0 M0 O0 ?( g, J6 C, [# n$ h2 U                vrc7.SaveState( p );0 Q0 n. |9 x# ?! |% H/ t- O$ d# \
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; |# C7 m, ~9 V
        }5 [3 e8 J% Y# r
        // FDS* x) {! \$ ~8 n
        if( exsound_select & 0x04 ) {8 N4 w4 w  C9 z& l7 H& r7 V, d
                fds.SaveState( p );8 I9 f" B9 Q, E/ _- L
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! B, A5 F2 I2 Z% R: }+ s/ J  y        }9 w5 c! m. r0 o  k: Z9 |
        // MMC55 c7 B- a1 F/ q' [
        if( exsound_select & 0x08 ) {
* a( K  g% W; m0 {% `- n- |                mmc5.SaveState( p );' e! d3 E$ N; Q' F* a" b! N0 w; s
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  r& f1 }0 U4 [3 x        }3 e! V: I8 t! F. h2 G$ P) v" {
        // N106
( g  V0 D( m$ d5 y3 z4 o6 k        if( exsound_select & 0x10 ) {& {2 H4 R2 Q, W. M8 J; |; s
                n106.SaveState( p );
" i$ g! I; G+ M, I1 r                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
9 x/ v+ Q3 [6 T' f$ E* Y        }( w) ^6 E  [1 U) Y' _9 d7 T% E
        // FME7
& @5 ], Y& P* L: s" l* j        if( exsound_select & 0x20 ) {; [& c/ P. M3 a0 L
                fme7.SaveState( p );
# i; Z* B& I; q& t1 g                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 X# H1 c- n0 O9 B5 u) t        }
  S& _" C7 H/ ?) v) c
1 V4 ?9 G) p* s8 K. h% k#ifdef        _DEBUG
( \+ y& \2 O3 l% Q' UDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );2 @& _' u% k* W) X
#endif( H5 d3 j; \+ w! w& V* j
}
0 [4 p* o7 N: G1 O) I
6 G' Z( ~0 D% T. k! F* X1 Pvoid        APU::LoadState( LPBYTE p )
: C3 Y7 E$ |0 P1 Z9 {' F{
1 ?6 o2 e" I5 N; J% @        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
( m) ~3 v" z5 X* `; p        QueueClear();+ W# h" K2 y, M; o% B* s3 [2 C& n
5 q+ ?- v+ W! Y
        internal.LoadState( p );
3 I3 f1 D- ]7 p& @8 \: d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding' e; h8 ]$ f  D

/ n( m* H/ m. g7 U- o& U3 S        // VRC61 P# F' K1 R1 V
        if( exsound_select & 0x01 ) {
- T/ |$ N* m, t: H( z                vrc6.LoadState( p );9 i" i( w& q; L& h& \8 M
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. `5 B. g8 v/ c- z0 ?
        }/ x7 v5 d$ D4 W" P2 m3 h- K
        // VRC7 (not support)2 D" ]+ m* y: D3 z7 t3 l* k
        if( exsound_select & 0x02 ) {
+ M& U6 p6 S8 p# m+ f- ?! u" i7 Y6 z                vrc7.LoadState( p );0 j" M* a  r/ ^8 P3 e' M( Y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. }0 M) {/ O+ K; N+ I
        }
/ a, p# S6 B; G, H; J# X        // FDS0 c. w1 @9 F) y6 A; b
        if( exsound_select & 0x04 ) {
7 D6 b* ?" C0 e+ B, d. O4 y% |( B2 c0 r                fds.LoadState( p );, N3 s/ g2 @( r1 j# z
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* N  S! y2 R1 S: n" e4 \        }, k0 q2 S' J' l# F
        // MMC5; w" W+ o; x/ k8 a& W
        if( exsound_select & 0x08 ) {% Y/ c5 g- {: K. m2 y- }6 ^
                mmc5.LoadState( p );! ?- w! {. g- X
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 c1 S0 P8 e1 v* H" e  w        }
1 @; V9 G8 X0 p% [9 _& _" o6 N  }        // N106/ `/ d+ q8 `7 V! h9 u
        if( exsound_select & 0x10 ) {
$ y. f# h7 S+ v! ]                n106.LoadState( p );
5 ]+ L+ o7 ]+ F                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding" v" E; |+ _( h/ a0 E0 @! g5 j9 L
        }* B# _- u9 Y+ l( R# N3 p
        // FME7
# f7 F8 ?' |2 P        if( exsound_select & 0x20 ) {
0 j: ~+ e  z0 Q% X( K& t$ M                fme7.LoadState( p );
9 P+ B3 A! F! L* W: U9 |9 G& n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 ~8 q- Q. }! B. n" Y! J
        }
3 \* H  b+ w# l* }4 m}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 1 _3 q5 \0 H, k- ~6 j7 H+ M& x7 R
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: F7 ]4 c/ w3 `' _6 p' e0 N: n
感激不尽~~
1 g% q& h3 `* |
恩 我對模擬器不是很有研究,
" M! l4 H7 J) R. t2 Q4 x, l) ~1 L雖然要了解源碼內容,可能不是很困難,
+ y/ ^- w  S/ y9 ^! {4 K不過還是要花時間,個人目前蠻忙碌的。# B+ A- }  C; \2 r( q2 O6 O$ J
3 e) B4 k; j6 @4 L& D, e
給你一個朋友的MSN,你可以跟他討論看看,
. K; N7 z  ?2 `# i0 O2 U他本身是程式設計師,也對FC模擬器很有興趣。( I% v2 ]. b9 Q! j: k# L

4 P- i0 f: M' F% m4 E# }! eMSN我就PM到你的信箱了。2 |- L' L' X1 Y7 S+ s. W2 R* Z
4 {8 R- O1 Y$ ]5 M; \
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
$ m( ?% o+ L! m% Z- R% w- {! f8 A: |& o8 u呵…… 谢过团长大人~~
/ `! q  l: G! B' t* k
7 J8 ^5 J2 p1 Q/ F2 O
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
( H3 y; x- x4 y2 U" e团长的朋友都是神,那团长就是神的boss。
3 h9 O* o2 `4 V) i$ Q9 |1 {9 R+ Q3 M
哈 不敢當,我只是個平凡人,
, ?2 }- V3 Q3 j& n: P  j0 ?: n) ]要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ {' v0 J+ `" m9 t9 H
ZYH
. X2 J. @' W3 g3 ^* |9 [QQ:414734306
; r! r( o' h: H! c: B% e" SMail:zyh-01@126.com. d  L# A! w1 n* @
8 ^5 q6 `" O' \; ]- p
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表   J% L) r* Y' \) u2 _
再次对团长大人和悠悠哥的无私帮助表示感谢~~
* K2 `" u3 ^+ K9 e  J
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-25 09:00 , Processed in 1.077148 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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