EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 R3 K' f7 N, S& ?# E( T楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ g8 b, ]7 F- p1 a9 x这里有相应的模拟器源码,就当送给大侠了~~
1 V" k6 e- _1 z4 j  @8 [# f- H8 rhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 - ]- s% K6 A+ x1 `  j# @+ y
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% k0 Z0 u( R# r% [! @! `楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 n" ?+ C; v, K% u这里有相应的模拟器源码,就当送给大侠 ...
, S1 S6 Z0 O) z6 ]: [
聲音部分(Audoi Process Unit = APU):' ?+ z- L* F* f: g& q; K
.\NES\APU.cpp  b! S; c8 {: W3 j+ ^% n1 F7 ^  T
.\NES\APU.h
6 V. p- h8 b" J" ^" g! u5 \! y; J7 U- e5 S- S) y1 b
; F6 a) h8 y2 \5 }5 a
影像處理部份(Picture Processing Unit = PPU):
8 U4 T' I+ N0 [! H% |.\NES\PPU.cpp6 M: p8 x( ^( D$ I( I7 l
.\NES\PPU.h1 F% ]$ {; d! C: S. A

2 i; c' A7 W. n5 q( ^/ z2 F如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。+ u! F8 w0 `) n$ @" j( p
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:) o. }! @  I( o0 T' f  f
(由于很多专用术语和算法机理都不明白,所以看不大懂……)) P: C6 o7 {& M: w5 D( S% N
//////////////////////////////////////////////////////////////////////////
0 M  ^: k3 c- h//                                                                      //
/ i  ]4 k& M7 e' u4 S3 J//      NES APU core                                                    //
$ s! ^# @, m' k5 X//                                                           Norix      //
* \0 x* Z: p' H, W) j1 j//                                               written     2002/06/27 //- _5 Q6 ~7 P" K1 e4 Q2 A* H. s
//                                               last modify ----/--/-- //( [6 ~, r# p5 H
//////////////////////////////////////////////////////////////////////////! F! @5 n: s8 X9 d5 W/ g
#include "DebugOut.h"
8 _- K6 t2 X$ k9 x7 R# X( L% A#include "App.h"
! b' l/ _% {% E! R#include "Config.h"3 s2 q9 D  Q# e2 G7 g7 K  W
( d9 g$ [+ R2 B2 G* D3 a- u
#include "nes.h"
  a$ X& l' ~0 K# b#include "mmu.h"' z* A" g6 H7 `  P0 b* B" D8 X
#include "cpu.h"
+ N, W  L. i+ _) N) \, R#include "ppu.h"; W. X" l6 _4 z: {: I  i$ k& _
#include "rom.h"' }9 |3 r7 U( L" e, a
#include "apu.h"& W6 p- k( p3 `) s. L4 _! U- V& C

& E# M$ p: ^$ @: b2 K2 V1 _% A& \// Volume adjust
& `& k% q- q# k' a* _$ Q* S// Internal sounds
" T) r$ l; j- n7 T, W8 `6 {4 g; C#define        RECTANGLE_VOL        (0x0F0)
1 }) }3 \6 f: R  C" `6 x4 A5 Z1 m' v#define        TRIANGLE_VOL        (0x130)
7 Q; n) f" x: Y#define        NOISE_VOL        (0x0C0)/ }* `' J7 X3 m: z
#define        DPCM_VOL        (0x0F0)2 O, J! j9 \5 f; z
// Extra sounds) t4 V/ H; @% b( A
#define        VRC6_VOL        (0x0F0); `" ?+ b. [( k& e# K8 p* V. f3 o
#define        VRC7_VOL        (0x130)4 R: F( b/ F3 g! r; S" E
#define        FDS_VOL                (0x0F0); l' U) j$ B( r/ S% Q0 |6 O6 K% @& l
#define        MMC5_VOL        (0x0F0)
8 r# m  q( U/ \8 o/ Q' [6 \#define        N106_VOL        (0x088)
9 H. ]0 ?1 [  V#define        FME7_VOL        (0x130)
, K1 Y1 T& k( \0 L/ b: z$ H! }& L7 O; W: n  r
APU::APU( NES* parent )
/ k! r7 \0 c) T9 u- m{
" E1 X% X4 n/ ]* |; {        exsound_select = 0;% B) s7 @  y' W$ C7 T8 o+ r

$ d% e( S, s9 ~4 T! I# J        nes = parent;# ?8 m4 Y2 m% j$ {
        internal.SetParent( parent );
" n# F7 a, l. l' g- r. Z; T7 b
) }8 e. {' x$ y! R' y% O/ A& B        last_data = last_diff = 0;
" g" F) t! n; {( Q' Y" U, v
' }) u8 w( I! F8 T! _        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
9 w" c* |! Q* |" N
! o) a3 m3 s% \2 D  H+ C: A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
! h8 [$ q2 M  S! Z        ZEROMEMORY( &queue, sizeof(queue) );
, a% Z9 ^* v& Y8 e: ?3 W/ K( C        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 {: Z9 w4 a8 l- q3 i; f

, Z5 v1 M- H! q" A/ e; ?        for( INT i = 0; i < 16; i++ ) {6 k* \( C' E; O+ @, X$ ]
                m_bMute = TRUE;
' V$ t7 k6 I  H6 m0 a        }) T. u7 u# N  [: C5 S7 r- }& i
}- q+ z4 u( o! o  }

. v( h# k$ Q& m. t5 w; b+ ZAPU::~APU()* b2 V1 k9 P( I/ l+ j6 n: n
{
8 U% j- _% ]8 V# ~}
( o1 D4 z) O, f8 `$ v7 D* E% V; m
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )# v) M; c- H6 h, F! j7 e
{, [4 X4 v- F0 }+ b' j2 t
        queue.data[queue.wrptr].time = writetime;2 W4 e' w& F, j  g3 n# L# y: p' p2 d
        queue.data[queue.wrptr].addr = addr;" u' {  t2 B" r& v5 k
        queue.data[queue.wrptr].data = data;
$ x1 Q- k! ?+ G" y4 U8 H4 ]        queue.wrptr++;
; r" B) I5 T8 j8 ?; [7 Y        queue.wrptr&=QUEUE_LENGTH-1;. ^0 t+ ^1 F5 S* Y
        if( queue.wrptr == queue.rdptr ) {9 p8 a, A7 z) n6 M2 {5 V
                DEBUGOUT( "queue overflow.\n" );
0 Q( j3 X& z$ h$ a/ Q        }4 U% Z  C% `1 |
}4 n* T& O  K) x2 T! P
6 |& D+ ?1 X# D) I# C! B8 D
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )8 S8 L7 s# g( l$ N% L- p
{
" n/ U3 ~& t" j        if( queue.wrptr == queue.rdptr ) {
/ s5 _+ \/ k# X7 W2 m) ]                return        FALSE;$ A# }# ?7 q+ g; j) g1 g
        }
9 A; J8 q3 q. f2 Y        if( queue.data[queue.rdptr].time <= writetime ) {7 S3 {( v6 J( F, x
                ret = queue.data[queue.rdptr];# {4 _  w5 J. C7 r, \; ?
                queue.rdptr++;- a/ B$ I: x& k1 X! P4 R
                queue.rdptr&=QUEUE_LENGTH-1;' s6 O# F% U3 q* E  t! \% f  f! l
                return        TRUE;
* n* N8 D5 T; M7 ]        }$ \! s5 x, D6 o; J2 m$ G
        return        FALSE;5 v( i2 w0 o2 {; I- d
}- a+ D7 a! r' v4 U
0 d& O% M6 u( w5 f  \
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )" y9 p) y& J' b8 u* U! i) o; d
{/ s5 L% l" [2 s' a+ c: H* m5 ?0 F
        exqueue.data[exqueue.wrptr].time = writetime;$ D$ E* b, h; w: y" M
        exqueue.data[exqueue.wrptr].addr = addr;  E: m$ f' f( D% r" S! B
        exqueue.data[exqueue.wrptr].data = data;4 U- O4 \# {( p/ z9 Q7 z2 ]+ N
        exqueue.wrptr++;
; T2 R5 B1 R; e        exqueue.wrptr&=QUEUE_LENGTH-1;; X9 h) u: a% G4 u( y
        if( exqueue.wrptr == exqueue.rdptr ) {; m# `3 a* l8 U. i
                DEBUGOUT( "exqueue overflow.\n" );
& H. j: N$ d! D' K5 R2 ~, W        }+ B) V0 ?5 c, z
}
& b8 l* F7 h  _  U9 ]% G. W3 L" B! g. i8 w
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
8 y$ l/ U3 p  b- t9 s- W{7 b2 T2 c7 _7 q3 G- I0 O0 I
        if( exqueue.wrptr == exqueue.rdptr ) {- R, Q& a( y, H, p6 r, D& X
                return        FALSE;
5 a1 P/ E! u( \7 Y. C( H5 B        }
2 [3 ~2 g& e2 I& h8 `8 g        if( exqueue.data[exqueue.rdptr].time <= writetime ) {8 F- D3 U1 c6 u, K
                ret = exqueue.data[exqueue.rdptr];, x$ r; J  N2 z( S6 Y
                exqueue.rdptr++;
1 ?: R$ o8 B! `% I+ {. V                exqueue.rdptr&=QUEUE_LENGTH-1;
# p2 I# ]2 W* }0 d' A# U& W                return        TRUE;
4 g7 C* L2 D; I5 J1 ^' `- M. m- M        }
, [$ p6 }* p# @2 n6 [% ~( v5 A3 ^        return        FALSE;% R, Y9 K6 l  K& r' u( D) @5 v5 s
}
* f2 ]+ v9 k( ~, _( P9 b; K$ b3 t- E+ R2 ^# g0 e* ^- V0 J
void        APU::QueueClear()( y; a. T9 L2 E# z2 j% g4 |/ T+ Y
{
$ z+ s. f- n+ I        ZEROMEMORY( &queue, sizeof(queue) );
% k+ `  W+ f1 h) o& H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  `: l: c4 m& G4 a}
# A: @( e7 h: l" T& x) ]+ q! W
# A0 R1 d/ \8 P6 q, yvoid        APU::QueueFlush()
! n4 o4 M: n. q) u( n$ l4 h+ O{; H& ?+ J% n1 ?: z
        while( queue.wrptr != queue.rdptr ) {; U$ p9 W  k/ o
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, ~# N# [* _! G) v
                queue.rdptr++;2 R4 }; a2 q- a( c: }3 w% {
                queue.rdptr&=QUEUE_LENGTH-1;! B2 c# g& I6 ]* t1 w9 z
        }* i) U" L; I5 v( t: R
& r- K8 U; a8 a  G1 k* x
        while( exqueue.wrptr != exqueue.rdptr ) {
+ E% [5 E+ `. d                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );+ E, @2 p! K+ {
                exqueue.rdptr++;
4 q0 P& V9 I  r* q- J# _  x                exqueue.rdptr&=QUEUE_LENGTH-1;& k# C  q2 L3 M. R" S
        }
- A3 v: w5 _6 k7 ~( u* Y6 [}* [3 h' O8 Y! s# p4 a
4 ]1 F0 o% `( [# |4 }+ B
void        APU::SoundSetup()
* L) ]" E; C" |9 t4 J{
: @2 q9 }5 @5 |" Z. k5 n$ U' y        FLOAT        fClock = nes->nescfg->CpuClock;
8 l5 v0 ]/ F) c- u8 S* E; |        INT        nRate = (INT)Config.sound.nRate;( w5 K' {3 H6 J# j1 c6 d
        internal.Setup( fClock, nRate );+ F% }( P! U% _, o  l2 p
        vrc6.Setup( fClock, nRate );
* a1 {; J5 C; I& u9 C6 E" ^        vrc7.Setup( fClock, nRate );
3 l; J* `6 \: m/ X* x' C* ~- L  L        mmc5.Setup( fClock, nRate );7 b9 d$ y6 l* j7 W
        fds.Setup ( fClock, nRate );
0 j2 l* X5 m2 n) N4 W        n106.Setup( fClock, nRate );
9 n/ P" ?7 l) |, f        fme7.Setup( fClock, nRate );
, z1 J5 f* m+ {$ c+ Q% w}; ]! @: a' v! ?3 K5 w

$ F1 n" l# D) ^+ Wvoid        APU::Reset()
, D: ^* A. A# ^4 p5 w' A+ X3 Z# y{
( _6 M; _( G; Z: {, s" ]8 m        ZEROMEMORY( &queue, sizeof(queue) );- r# v( m/ q, h4 n% V6 Z. H( C' J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ g( Y) Q7 Q0 p1 ^4 \8 X0 N% X' ^4 x* B
        elapsed_time = 0;
. Z4 @1 q3 A! K- f, I! c+ @, j5 d* L% @$ j# o6 q$ V: t! [6 Y: }
        FLOAT        fClock = nes->nescfg->CpuClock;, K7 T9 X! O+ S. e  C' C/ J8 I$ c
        INT        nRate = (INT)Config.sound.nRate;
0 _/ W9 Y% R/ F/ C; g* d% B( n        internal.Reset( fClock, nRate );
; Z6 e, M$ U- i        vrc6.Reset( fClock, nRate );
+ v1 h  U2 v# h1 D/ b4 i/ Q9 [' R3 @        vrc7.Reset( fClock, nRate );2 I9 }2 @' t. [: ], |5 x3 s# b
        mmc5.Reset( fClock, nRate );
1 }" Q6 x2 S- }0 ^; u        fds.Reset ( fClock, nRate );, I" L( @( ?1 m0 e, c" t9 j; H
        n106.Reset( fClock, nRate );
; d' ]/ S! W& O        fme7.Reset( fClock, nRate );# k6 j. b0 Q( Z8 w: @

2 P8 B; r  P! x$ A8 C% w        SoundSetup();8 K$ U2 [0 U$ g$ l# T; Z
}& z2 o+ V7 t6 _% y$ O1 }

! u% S* v& s$ a) Kvoid        APU::SelectExSound( BYTE data )1 u& f( \6 j4 T/ g0 h
{" H: B9 n9 ^% B! W2 o+ P
        exsound_select = data;) ?8 t( p$ ~& `3 L8 o) _- M
}
) Y( \2 p( p7 ?
6 z+ n+ a& I  \! W+ hBYTE        APU::Read( WORD addr )2 i: c& q. O) ?; P/ H, {- C
{
: t6 q  C( t9 h( x* e        return        internal.SyncRead( addr );" n8 I" S  V) h
}
2 p6 C3 u. }( G, A% \7 T3 m0 x2 y" c" D4 G+ n
void        APU::Write( WORD addr, BYTE data )0 d8 k9 S; t# R! S" @
{
6 `: X* \0 I9 v  y        // $4018偼VirtuaNES屌桳億乕僩
, o3 \/ a2 V& P( I4 j6 o        if( addr >= 0x4000 && addr <= 0x401F ) {$ [6 \& S6 P5 S' c& G( H
                internal.SyncWrite( addr, data );
& v* O7 @6 \# O                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% a2 C* U3 P3 H( e! q9 O+ D
        }$ A' f1 v% p1 L# v- t/ h! g
}
9 y; Q& g$ j# y5 j" k& Q  {/ ?. g
  H7 ~9 w5 R# W) d/ WBYTE        APU::ExRead( WORD addr )1 j1 H5 _" @- s+ U
{
# g; c; |% M' nBYTE        data = 0;6 j% f' P! p9 T, L4 Q- b
; |. o% n$ @0 d
        if( exsound_select & 0x10 ) {
1 T7 y2 ^# n$ m# N1 w  T5 J                if( addr == 0x4800 ) {
' Y8 a/ v# U( v5 ~" T9 P                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
0 r& Q8 `( G3 |4 D                }% C* e8 i4 c7 w; r" W$ y: r! d3 r& s
        }% x& \' @* @, a/ v
        if( exsound_select & 0x04 ) {1 X4 d: ?+ D% s
                if( addr >= 0x4040 && addr < 0x4100 ) {3 I! V; M# F( t6 _  h
                        data = fds.SyncRead( addr );
8 Y9 W0 V# [; ]* d: n+ N' _                }
7 x! u* Z$ I) S+ X$ e        }
, Q. E' d( m6 X# P5 X; g. ^9 s" l/ A7 m7 J        if( exsound_select & 0x08 ) {. `, ~2 B; T* Y2 g8 R. f' J$ p' Q$ y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ P: o. z2 t9 w  I; d                        data = mmc5.SyncRead( addr );
2 }- ]* q4 E1 P9 a1 `. S                }* L0 K+ W: V- V! \  X" U
        }4 Z0 s1 j' c( m3 X7 i

/ Z# Y; T* [: c. K* v. w        return        data;
0 ]. Y4 I5 F8 L7 ?3 C}
$ E5 D1 M" n- O7 G$ ]1 Y5 {2 U* x- a7 [( o, B# M
void        APU::ExWrite( WORD addr, BYTE data )
6 v& s/ F! v9 W3 i3 G% b. I4 |{" m1 U, c2 h! r
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
7 b0 a0 w& O7 g3 @" b
6 E# h- a5 d8 ~/ G        if( exsound_select & 0x04 ) {& l% v* A7 E7 ]6 l
                if( addr >= 0x4040 && addr < 0x4100 ) {1 a" a* X8 {) }6 M" t
                        fds.SyncWrite( addr, data );3 v- {2 Q& k3 y; H0 n' ?
                }& j2 F' n5 _; H
        }
0 F/ C' ^- c! _1 p
3 y6 J- O5 R9 S9 ^+ _2 J, G        if( exsound_select & 0x08 ) {4 P7 g+ T. C+ Q
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 V) P0 [! f' _+ {  e                        mmc5.SyncWrite( addr, data );" G% C" R2 S# l
                }
" Y& r4 ?/ o: s- Y) d8 J        }, q% X4 h$ Q9 C3 v- }9 u
}
3 Y: \. |6 Z. N3 j' Y9 y) o. u( C4 d1 e: P! o3 O- Z
void        APU::Sync()4 u9 U$ h5 R% J
{
+ N; D# ]; S) F; @" V' E, Y  `- {}% n7 A& ]! ^: K) \3 n  D, |

6 W& K* a- Z  hvoid        APU::SyncDPCM( INT cycles )
' ]; b# ]2 {  {5 ^2 ?  I{) O. r( [# m8 N: Z3 ^- @: h  }
        internal.Sync( cycles );# P1 o  u" s2 v& w2 d

% M  m2 @' b# h8 A! t1 B( Z        if( exsound_select & 0x04 ) {
* J* \  h' B! ^                fds.Sync( cycles );' v% T: G( v2 s# x1 {
        }
) X# |4 ?6 }  i8 e$ j8 b        if( exsound_select & 0x08 ) {% x+ D# e! ^$ j- D# E* d
                mmc5.Sync( cycles );* S9 e; w9 T' Z4 O: t. T' ~/ w
        }
/ p' ]8 y/ ]0 M  J, g9 W; S$ o5 A. ^7 j2 S}
: s/ G/ q) o0 l* a$ B1 T3 T; o! }7 }" [* v2 A% a  V
void        APU::WriteProcess( WORD addr, BYTE data )) }5 b- b1 g1 p# H
{2 {5 }/ I& T% E) o; [2 f( B
        // $4018偼VirtuaNES屌桳億乕僩
+ W! p: Q- K9 ~% O' |/ T1 t5 F  A        if( addr >= 0x4000 && addr <= 0x401F ) {' r% d. t3 g) R( O2 h! t" \
                internal.Write( addr, data );* J+ v- {: I9 m* Q
        }: g5 D0 _9 r% g" {! i4 A( _- |
}. b, l  D0 M% k# A0 [' l

2 s: l; t! ?" n) E# X/ X+ \$ J; Yvoid        APU::WriteExProcess( WORD addr, BYTE data )
7 K! A/ N* E: i6 e1 h4 @' D* t( \{+ V) O3 f1 @/ k: e$ `
        if( exsound_select & 0x01 ) {
- w1 ]! S% a% H  L! |8 S5 x                vrc6.Write( addr, data );
: A0 \# ?$ Q& l. M        }
& \  {8 P* L, D& o- @/ ^7 U( p        if( exsound_select & 0x02 ) {  ^9 j! A) [! r& x- f7 E9 Z% ?$ g
                vrc7.Write( addr, data );
4 s0 w/ B2 G. R. A& F        }
5 ~7 V1 o% x; H6 d        if( exsound_select & 0x04 ) {
# q) J6 t4 W- m9 r( G$ m                fds.Write( addr, data );
. w8 e1 G. ~& Y3 |        }+ Y  \/ Y& j! ?( y! a* t6 A6 \. f: R
        if( exsound_select & 0x08 ) {! q' ^) y1 b" Y: S. W' U2 A
                mmc5.Write( addr, data );
5 K4 J# R6 p7 d        }
  D/ _. c3 g" ]        if( exsound_select & 0x10 ) {
4 L1 F! X" @3 |; C                if( addr == 0x0000 ) {
  R/ p$ k$ g7 N  ?( z                        BYTE        dummy = n106.Read( addr );
) H( v% j$ O" p6 c6 E                } else {- H0 x  \: Q( c  S1 B( P
                        n106.Write( addr, data );' w+ z: y: n6 O* v8 c( [( W
                }
+ b' j* P% y8 x1 ]' e' O! U- Q        }4 b$ W% v' F! C0 n
        if( exsound_select & 0x20 ) {% P. H1 ^# \' N: M8 Z
                fme7.Write( addr, data );" y0 k- @: L  r. t
        }
! G9 i% U8 @; A* n}0 z  k0 U4 {+ j* t4 v
% i9 t; ?! s; O1 Q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )/ E& C# z# w0 D: y. ~8 l: [
{2 U& c0 }0 u' G4 d
INT        nBits = Config.sound.nBits;4 T2 b) o! Y1 [6 {' K
DWORD        dwLength = dwSize / (nBits/8);8 _) ^8 @: S3 ^  q
INT        output;1 b2 f/ I9 _  o) S
QUEUEDATA q;
+ |) Z8 J4 V: R( E4 l8 \DWORD        writetime;
! q9 s# q, t* O7 b1 j# u% H+ o5 ]* f- _- i* K
LPSHORT        pSoundBuf = m_SoundBuffer;
6 ]1 E4 ]2 L" ^" R# W/ NINT        nCcount = 0;
. k/ m3 |/ F. U* q9 A! M, |! o: V0 z+ N% V  @# @, e
INT        nFilterType = Config.sound.nFilterType;! _. U0 Y2 y$ Y/ O8 V7 w
7 z3 c. ~. m) @" h
        if( !Config.sound.bEnable ) {$ @# V" w. m9 \( _+ d% _+ y
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
) \5 z" ?3 A/ x. `                return;
' x% }8 H6 \6 @% S$ i2 Y        }5 t, @4 Y* P6 _. F( ~" f

8 F* b6 ]  e" w/ a4 j        // Volume setup7 H; Z2 u$ s4 _, ^- Y9 t# b0 ?$ V
        //  0:Master
( O8 B( d; ?6 e; c3 S        //  1:Rectangle 1
! l! n  p! C3 c) C- i8 t        //  2:Rectangle 2
! d: t3 d# E' ~# D6 t: M        //  3:Triangle! [# h# ]5 W- W8 _
        //  4:Noise0 Z4 c: h6 H& T
        //  5:DPCM
( C4 `1 q0 m* L8 p# g        //  6:VRC6; w. v. K) n" i0 r* h* I( |
        //  7:VRC7
3 z5 [9 Q  Q' i3 ~        //  8:FDS
. F5 j, I5 S3 e0 k9 B        //  9:MMC5# B% u2 T) T! f5 F" S1 V. h
        // 10:N106: f+ ~# m0 G/ d) [
        // 11:FME7
9 o; U2 Y! Z4 V, [6 }2 T3 ^        INT        vol[24];
& y+ F( _0 g5 ^        BOOL*        bMute = m_bMute;9 V. U$ N, `% {6 ~! G: o) W
        SHORT*        nVolume = Config.sound.nVolume;5 M2 E3 h' |0 Y. n5 D

. Z/ D/ l  d$ T7 F3 g# P        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
5 \0 m. a  k4 }; B7 S0 d
* r* p* u% \% U# f; N/ S5 ^) y        // Internal: W; L( _' P+ L2 p/ n
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
" T4 ^8 ^# I- I0 p  E) c        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;- G/ ^9 P8 N: J3 |2 Q
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 D" z( ^7 D; O, e3 M! x. R        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
, ^- r1 {6 w6 o5 h; r' p9 `3 h$ B        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 o# c$ P( m# \9 S) w! E5 l  o# N( X7 N: Q/ F; J
        // VRC64 x7 d; J% O& D2 N7 c
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: {6 w1 {$ r1 g& i        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. b1 C& a; C$ o7 _8 M        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, c* x+ Y9 l- p5 v8 }9 K( o
' a* }3 T* N, c6 I1 J! O
        // VRC7
  v7 Z8 F# K) D& K+ o        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 G, D8 w9 F. ]3 J# Q$ f1 f! n2 G7 q' r0 d9 l- z2 S
        // FDS
  D6 X* h5 G; A        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
( T9 o; B# E7 W* u/ C
9 \/ O; L6 Z2 y        // MMC5
0 d; r  _- B3 b  z4 E2 P5 R9 R" ]        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 l( B4 @/ D! [2 q6 f* i5 y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. n( U- V$ U2 W# g$ x4 J+ t        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 H: z5 [5 c+ J$ L1 \

$ {( K% ?3 @/ I, F& x        // N106& Y7 d, {; d9 u
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ t) _' `" W9 M. U' N2 H$ g* [! e& v
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 z/ }. R/ l, Y) K
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: V: ]0 w. U2 n4 c( n' b% w# V
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. w! s9 H! T: p' `# t( W! r6 u/ g
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 g- m( J3 R5 R1 ^  q) Y. z5 u        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  T* t% J9 i+ Z% O/ ~        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! M6 ^" d4 J0 T: W: G6 E2 v
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 r0 V( f  T  }0 v' k+ e
8 ?/ J( h( l+ R# R  e0 N3 {3 Y" o9 I5 _
        // FME7( s0 n; f  I  v9 m, }9 |# [% L
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  ~( |7 s* Q6 y' l0 X        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 v8 D. f8 R7 }! U1 a5 n
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ H0 o& U8 H" p* i9 }* t1 E
+ o0 x  Q0 Z: @  q' e+ {//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;) d) P0 i( y4 W8 g8 }- o4 v3 O) w
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 S7 v) k" `+ [4 `

# d* f$ R/ Q- }& e- |: N9 o5 D8 Q        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 [! \0 ]& o$ m4 i1 A9 c        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) C$ m+ \4 Z/ o5 _- S6 ^" w. y5 ^
                QueueFlush();
! l, k, \; ^9 ?" y# }        }
& y! K) I# r. E9 F0 @9 @: W6 w' C
& M! p' H/ L, Y% f- Z! Z6 W        while( dwLength-- ) {0 B9 M* o- p$ }
                writetime = (DWORD)elapsed_time;; F) G& @; E; i( z! m9 R5 D% P
, j) H# d# N2 q8 W2 G
                while( GetQueue( writetime, q ) ) {
; b/ v6 E1 A) V/ G- e* k2 H                        WriteProcess( q.addr, q.data );# K5 \. G' e" H# P% t+ |9 R
                }
1 g3 ^. r5 [! [' x# H$ ^3 R, s8 A  [( K0 s4 x. w5 z- F; M3 e
                while( GetExQueue( writetime, q ) ) {# @- i2 Q, k* ~% R
                        WriteExProcess( q.addr, q.data );
2 O$ [( U3 V- h                }
. p9 U+ P( N! u8 y. {
8 r/ o5 O# A" `  Z                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
! R4 f- W& w2 c' `4 f                output = 0;  i& Q" C) u9 `. H1 v
                output += internal.Process( 0 )*vol[0];
: C6 p6 `; s. _0 o' z& ]* J; V                output += internal.Process( 1 )*vol[1];
5 H  c- e4 d5 [. e  t$ i                output += internal.Process( 2 )*vol[2];
% |% A  V% b# M7 H# X! X                output += internal.Process( 3 )*vol[3];
- Y5 }7 ~& h( q' o. }8 m0 u                output += internal.Process( 4 )*vol[4];& ~4 r, U0 Z" X! H1 M9 p% f) B

+ K: g# {0 |+ J& n0 s, q+ ^# p                if( exsound_select & 0x01 ) {, }8 E8 h: ~5 V7 Z( t. d  m
                        output += vrc6.Process( 0 )*vol[5];* k* G* y* g; b
                        output += vrc6.Process( 1 )*vol[6];& D" r9 Q3 V/ ^" |) A; t8 U1 T
                        output += vrc6.Process( 2 )*vol[7];
3 h' Q5 }' i; u1 Z# _4 w8 ~                }9 O$ m) R( c# y! v
                if( exsound_select & 0x02 ) {0 M7 W! g1 b) g' b$ i* e$ Q
                        output += vrc7.Process( 0 )*vol[8];# o% H3 D; a8 M/ Z
                }! Y1 U8 Q; s0 M' s& ?9 ~/ u4 \
                if( exsound_select & 0x04 ) {/ ^- E7 ]" D8 b% S8 V' W: N: O
                        output += fds.Process( 0 )*vol[9];, \2 W; ^; d5 Z3 Q' \
                }
9 h2 r* \" p3 r, x1 l1 z                if( exsound_select & 0x08 ) {
$ [& C' S9 _; m$ K& e                        output += mmc5.Process( 0 )*vol[10];3 C  ~3 ^4 c2 o' p/ U/ ^. l
                        output += mmc5.Process( 1 )*vol[11];
- U4 B! }! I8 J9 Q                        output += mmc5.Process( 2 )*vol[12];
0 r0 h. D2 }# h7 M3 u9 F7 _                }
* @% N6 y. ?% V9 a; X9 L                if( exsound_select & 0x10 ) {( v' y2 Q& U( c; o
                        output += n106.Process( 0 )*vol[13];
) v5 |! ^# w$ n9 I* Z  Y                        output += n106.Process( 1 )*vol[14];
3 {/ U. h4 @! c, x  R& f5 O                        output += n106.Process( 2 )*vol[15];
7 R, h5 J3 s! ?5 [                        output += n106.Process( 3 )*vol[16];
0 e- c+ r+ g1 Z' K- v( R7 V7 V! m7 M                        output += n106.Process( 4 )*vol[17];! U7 q# c# o4 l" g. x& i
                        output += n106.Process( 5 )*vol[18];
& Y/ {5 ]! g+ L" w' M2 T% G, p( C                        output += n106.Process( 6 )*vol[19];
% E" S8 v- i) I  i0 n8 f                        output += n106.Process( 7 )*vol[20];/ Z1 \, B. `" ^
                }
, U! x; Q3 A5 l; T, k5 {' T                if( exsound_select & 0x20 ) {
1 y3 ]& r! U4 I: t) l9 o% ?# L                        fme7.Process( 3 );        // Envelope & Noise2 g+ y4 M6 M% I7 T/ [
                        output += fme7.Process( 0 )*vol[21];
7 a- R' }3 P) J/ |% [' q5 a* L                        output += fme7.Process( 1 )*vol[22];
' x1 C) J3 z) T) t                        output += fme7.Process( 2 )*vol[23];" n' a1 k8 y# ^/ S- [6 N
                }
  r+ P+ l+ Q# @- P8 |9 S( c3 n  S4 w. D# l. Q$ g
                output >>= 8;
! Y5 ~" N2 w: W0 o' ?- M8 i. p8 M& G" }
' o4 A; R+ `/ s* l4 m  s1 i                if( nFilterType == 1 ) {
9 M3 p- L. I2 n  H6 W: B7 s                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)" R, q2 \1 |- q9 f6 H0 a
                        output = (lowpass_filter[0]+output)/2;9 ^  [0 e& j( P$ |
                        lowpass_filter[0] = output;- G" C, D0 H2 {) X3 w9 z% Q: h
                } else if( nFilterType == 2 ) {$ F. S9 |/ A% Z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
, D9 G" E6 M. Y) W: k1 G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;: S1 ?/ a2 m( P2 }' _; ~5 h& ^
                        lowpass_filter[1] = lowpass_filter[0];
; [) i$ N- j4 ^: ?' k0 }9 l" d* F                        lowpass_filter[0] = output;" w! J. a* M* q: v
                } else if( nFilterType == 3 ) {7 s) u# }2 `9 j* j# C
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ h) s% G" n3 k3 v3 R. n* f
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;+ c0 `. U$ C/ e: i) E
                        lowpass_filter[2] = lowpass_filter[1];
3 A: j: U$ w6 e7 K  d# e1 n% d                        lowpass_filter[1] = lowpass_filter[0];
! Q( J! Z1 \- Y, o$ Y                        lowpass_filter[0] = output;" G8 Z3 y5 ]4 |1 N5 G) h' o0 r
                } else if( nFilterType == 4 ) {
, E2 v! X# J8 {4 N/ E; h1 Q                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3). G& v  i1 v$ r
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
) `3 v  k4 @0 d' |4 a1 c% Y                        lowpass_filter[1] = lowpass_filter[0];
/ P4 u- d2 c2 [8 J" C0 i                        lowpass_filter[0] = output;# N! W2 M2 M! m1 ^
                }
  t3 u2 v0 }4 Z, G8 h* P: i8 s" T' P0 |
#if        0$ R4 Q$ X! G( g) ~" ~+ R% a
                // DC惉暘偺僇僢僩
) }7 A# E  x0 e) w8 m* H7 v                {
  ?* {& n  i8 d: h                static double ave = 0.0, max=0.0, min=0.0;
( ]1 t; z) W6 @& d* N' L' |7 O                double delta;  c6 y9 Y+ d& h* [" l  W4 F
                delta = (max-min)/32768.0;7 p8 L, O3 d+ X, r
                max -= delta;" r7 P0 `6 T+ V4 H  j
                min += delta;! `6 F7 `  @% i! o
                if( output > max ) max = output;
2 Z) {4 \3 P7 x& R- C+ W                if( output < min ) min = output;
; [1 c  \1 O6 t- `2 ~2 O                ave -= ave/1024.0;
* e& H! U4 t8 i' ~6 k                ave += (max+min)/2048.0;
% l5 U, T6 T/ E2 x' C                output -= (INT)ave;# d; j7 m% z9 O, u% X
                }0 Q' l) R# s9 F
#endif
- A5 r7 |+ R5 V6 P! f#if        1" E& b) L! a7 y- M" F2 E/ F! d
                // DC惉暘偺僇僢僩(HPF TEST)2 E$ e+ g9 ?5 v5 |' E
                {  o; K0 \8 J. L/ s7 f5 `) V" v
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" ?: N) R0 M: ^; u: s8 A$ d% D/ m  ~                static        double        cutofftemp = (2.0*3.141592653579*40.0);
$ A# H# K: K0 P                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, Y2 R% b  c7 x  a                static        double        tmp = 0.0;4 m1 ~8 p, Y6 V: [
                double        in, out;/ z" T2 v, n1 L+ E0 z0 L
- r5 A) V0 T5 j2 G4 I) \  U* @
                in = (double)output;
  H; b" h$ k3 ^: G; g                out = (in - tmp);
1 j& t0 N0 B" Q8 p& Y                tmp = tmp + cutoff * out;1 p1 s+ q' p6 w" L

$ `5 R& U  l% G                output = (INT)out;
+ L# n2 H; i1 i. J                }
8 }6 I' N+ u- F' O2 \9 X; k" Q#endif3 |( y- G0 ~# E! p1 k/ h
#if        08 i+ A/ v9 u+ t9 C1 a" v7 k4 u
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. Y) q: a; V: _% l; ?                {3 Q, H# z/ ~% O
                INT        diff = abs(output-last_data);' b  G1 B* Q' a- j4 d  C( {: i
                if( diff > 0x4000 ) {
! i# `7 W% c9 x  ?1 q$ _                        output /= 4;
& U6 i* }' [/ X9 ^# n                } else + A3 P" i+ Q6 ^* R" F9 H
                if( diff > 0x3000 ) {( ?- g$ J! G2 }+ y2 F" f3 y# F
                        output /= 3;5 a1 j. D; ?) F4 k
                } else
; @8 I7 g+ O( u; `                if( diff > 0x2000 ) {
  n. q2 \% H. _( h- e                        output /= 2;6 Y6 d5 \' a  N+ b2 j
                }
. n7 B$ J( G- j: _3 h                last_data = output;
* B( |7 M8 r# o! m; e- P                }
" M6 e$ a! Y+ p+ p6 x#endif
# d" S; `' Q: |1 a4 l5 }* h                // Limit7 I0 C1 t/ a4 w2 |1 r, a+ H
                if( output > 0x7FFF ) {
9 ?4 T3 I( F) |- I5 ~: ~% @. }9 F                        output = 0x7FFF;3 X, D4 ?6 a: [3 }! i
                } else if( output < -0x8000 ) {3 ~7 n( _; m- W- `/ ?' N( D$ r2 f
                        output = -0x8000;& v- \0 e( m7 ~6 Z) e8 b
                }' A2 _, d! O1 T7 o- p  p3 D5 _- `% X

% t6 U2 ?9 R8 q7 Z                if( nBits != 8 ) {1 S' d+ ]& b4 B5 H
                        *(SHORT*)lpBuffer = (SHORT)output;& P9 a. q8 z8 ^! I" m# S
                        lpBuffer += sizeof(SHORT);
  L" T# ~7 b: |& M6 B! r1 T                } else {
% u0 t% r7 p4 w5 \$ t# i; l' ]                        *lpBuffer++ = (output>>8)^0x80;
: M9 u' U% R0 y) Z0 u6 v1 O1 Z* |                }  {. ^3 C* l8 a  [$ R+ d/ o

, U) k) V0 |# Q; s                if( nCcount < 0x0100 )
! |4 Y* k2 l" N- t4 R5 `                        pSoundBuf[nCcount++] = (SHORT)output;" `$ u) i5 ^! B- A6 r0 m2 y
3 Q: }% b, Y7 s5 L- X& n- \) k
//                elapsedtime += cycle_rate;4 f  a6 e$ E6 \/ z" R. g* \' ?
                elapsed_time += cycle_rate;; q% L# u, B, H/ W# j1 N
        }
" A' D( j1 `' f2 `% M' `! Q) G7 ]
9 l6 W6 b) J( m% U#if        15 ]" m+ w9 F. w, V
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {' x" J- _. Y4 a5 D' P/ y0 u( @2 o( h/ t
                elapsed_time = nes->cpu->GetTotalCycles();
5 z& B6 {3 @; Z$ ]* E        }6 |7 ^4 o9 [) X8 J' |/ o
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 ?7 k, P) L3 c/ v3 o                elapsed_time = nes->cpu->GetTotalCycles();
4 }  I; F) c  q( F, q        }
& ?9 {) T0 f% L#else) H; P1 P# P4 x  O2 e1 j
        elapsed_time = nes->cpu->GetTotalCycles();$ [6 \$ _% ?/ }7 N% @
#endif# S! k) I! \; H* T; h
}
! W6 N2 o' I) ^* S0 D
  t) }" F5 ~" G7 T3 s$ X// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡). H- V* H: x" _% k$ v6 B1 {
INT        APU::GetChannelFrequency( INT no )
6 ]+ D. @: g2 o. ?% ?! \{8 {7 h* b8 v9 Y/ _
        if( !m_bMute[0] )
! U6 H* w5 C- O4 G+ X- p$ U& h                return        0;/ ]+ H1 y1 d( F- _4 M7 V& H

4 @  w0 f8 @5 I: ]- {6 z* R        // Internal
5 c# U. ^+ E. T* V) t        if( no < 5 ) {  g- k! k) K: C6 b7 y7 Y! f/ m
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) z' G" E& O5 @+ F        }& k. k- j: `  j' @9 q6 p
        // VRC61 e1 q3 _" _0 m1 x' ~& ~; q0 P
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
! n# \6 n; ~! w0 S6 y/ P                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 A- l  `$ `  {( t6 ]1 Q( y
        }' P" e5 ]% F; }% K. c8 t! I
        // FDS9 ?# j2 N: C& p7 v" G5 }+ z) A  z
        if( (exsound_select & 0x04) && no == 0x300 ) {
* O/ m- D1 m7 C7 V1 d- }8 H                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 ?/ B" |- [; u6 l1 b  N
        }/ {  ?) s+ F0 e- W& U  p& \3 H
        // MMC5
* i: y7 E  g4 C/ h, Y        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {$ R7 @$ E7 V) g" ?
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
% E" _3 n. M# u: b, A0 V        }, ?, t4 ], u: X6 P) R( x9 m
        // N106# X9 P8 X' {1 ^  q
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {0 B! \. c$ h; i. k6 e
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ T. H$ o5 T5 D$ _
        }
$ {8 b% }7 P/ c$ y% c        // FME75 f! N. w5 c7 y. p
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
, ^, M! F3 [2 }                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 p# K* D& _% b$ h' r' U7 L        }/ H2 H- I8 P4 \5 g
        // VRC7
8 v- B; _) {. g1 Z7 i( i        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# ?$ `/ U3 o+ S4 F  [8 r                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
( Q% `! G4 M7 k& U5 ~7 B        }) ]; j# {  c3 }! I" o! Z- Z5 y) G% V
        return        0;
; p5 a3 c$ _$ M' J}% G! N. \/ T. r+ \7 y. Q
! ~" [: u3 e1 o& @$ Q; _2 I% n; H
// State Save/Load
& `# z2 r8 }/ K& N6 Ivoid        APU::SaveState( LPBYTE p )# |1 h+ @4 \3 M5 e1 {4 \; }
{
! a) t1 z5 f7 J' a. K& d#ifdef        _DEBUG* v7 A8 y* @. F, V6 J1 |
LPBYTE        pold = p;
5 b+ U! q, [! A0 h0 W7 J#endif
2 w+ [( f& y  f7 M; B; p. w& K* B1 j" `" ]8 [! R
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞& i% ~/ D8 i9 V# N
        QueueFlush();
* r2 p8 i' y$ S
  f0 n2 h3 ^; Q; y        internal.SaveState( p );1 d$ X" d1 b/ ]. m2 [4 o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 E# v* p- u4 L
( ]. I1 }# q7 `$ V8 t1 I* D, ]' K3 h        // VRC6
. v) y% t" m6 A$ z- p1 C" ^# P        if( exsound_select & 0x01 ) {
! e! g5 D2 ]$ k* l                vrc6.SaveState( p );  |- c- O& y6 P; V! f
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' ]; _9 a. j+ u* J9 L- f7 R
        }
9 q. D7 @* [0 Z0 h( k6 F, M        // VRC7 (not support)
6 C- {5 m9 \9 ^8 X7 E        if( exsound_select & 0x02 ) {
2 y% W8 g8 {# B% }" W                vrc7.SaveState( p );
9 y1 M7 M: `6 [/ o5 Z: n5 G                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) ?$ `  f( W9 o' e3 o- b        }
$ d% u* ?0 g. s6 Y0 i4 U& T        // FDS
9 G' E" w* r* I        if( exsound_select & 0x04 ) {  U5 j; }" m5 `! H. Y  r
                fds.SaveState( p );
. k2 T6 |8 l* B" K$ l& q; m                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 t, D, R  a& I; e3 G
        }( C' J! n6 S( `, `3 G" N/ L) b
        // MMC5. L+ b  t! ]) G9 I$ X: I7 G
        if( exsound_select & 0x08 ) {" Z" F* O  i% B$ b; Q) l; \
                mmc5.SaveState( p );
0 D$ O+ ^7 T4 `' ~- o; M. g                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 L1 K5 `/ E7 D, Y6 `        }' Z" y6 P% H0 m
        // N106* _; I* F! [2 ~& V/ I3 s9 U* n0 c2 O/ g
        if( exsound_select & 0x10 ) {
7 P" \' R9 [. E1 m8 _6 M                n106.SaveState( p );$ \6 v+ H+ ?- Y# J! a
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 {% y3 r  Q2 e/ M! c
        }/ R) r9 J" T8 R* }! r
        // FME7
; }7 V1 Q! M, E, ~        if( exsound_select & 0x20 ) {/ V% c& g3 B: C) U; c
                fme7.SaveState( p );
9 m3 k& A; C( U' R2 H                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( I2 o& v" W* C5 h. c. k: C1 ?) c        }$ J5 C0 [% G1 I' Z9 ~2 x9 v+ N
0 K, z7 @( [( c' `2 b+ }
#ifdef        _DEBUG
; Q: `: n' R8 \0 ]1 [DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
4 ~0 T7 W* m- M% Z1 h1 ^3 q. v; |#endif9 R5 `% g8 c9 O4 F
}
# ?$ p/ S; [  P" J  i  {4 ?9 I0 G- B- u0 a7 ?
void        APU::LoadState( LPBYTE p )/ f' D8 K6 ]9 T; z3 J
{
; B. X, ?# U6 `+ i( m: o9 j: g* A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡- A% _* E! {/ t% z$ g* Z5 V( c" |
        QueueClear();
# k  U; Z  c. \5 h: i
/ q% P# [# x- V* N: m0 I" k        internal.LoadState( p );
: d. y1 Z* q$ e5 l- x2 o: L        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! ]) `( C# Q+ c6 j# l
  ]* e- R; l$ o- V! _1 c        // VRC6) r7 P0 N1 }; I4 M
        if( exsound_select & 0x01 ) {
$ v" d3 b6 q7 s5 H% R; s                vrc6.LoadState( p );- Y. X2 V) j- @
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' v4 `: C: h/ A1 v% G: u' z
        }
" }7 \, s) f1 y: J+ n6 Y! l        // VRC7 (not support)
* K& k- p6 l6 x# l0 e- N, \        if( exsound_select & 0x02 ) {
9 f, L& x" b4 F! t2 ^8 \3 u* t* p. i& l                vrc7.LoadState( p );4 N1 d& _& v5 N
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 p$ @2 f) y9 C9 T5 q
        }) _  |% P, }( M  ]& \+ I
        // FDS0 N7 z  w! ~$ _/ f2 G6 A6 A) O; `' G
        if( exsound_select & 0x04 ) {
1 O1 q+ e& v6 c& g; Z: z7 W$ F                fds.LoadState( p );
/ L, w# i0 x3 B3 W9 S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 M; n% d" s3 @# C        }8 R+ }$ p1 D7 }, y, X
        // MMC5+ ]" T1 q! f- ]. ~+ c4 z
        if( exsound_select & 0x08 ) {
  W! v. \9 y+ C1 x4 g                mmc5.LoadState( p );, j' m7 X- M6 [- F; k% L
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% h$ S: d% `4 k
        }# m0 b5 g; u5 S: F1 ~7 J
        // N106& B$ [+ T  }8 Q6 Z: E3 Y! }
        if( exsound_select & 0x10 ) {
( R, {* s9 I7 D2 r                n106.LoadState( p );/ J' s8 d5 N, \) S  {: o
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 F8 l) z! b1 j0 y' }2 w$ P# ^
        }9 B7 ~' W& {$ b
        // FME79 ^8 V* w8 w0 O1 y+ B
        if( exsound_select & 0x20 ) {
1 K% _: ]# R4 F7 M                fme7.LoadState( p );
! b# F" }5 |, p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" T2 s% \& y$ I7 s) V: c
        }
, C* W! O" ~( N8 b3 x# O}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表   j' [+ s5 Q  O7 F
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
6 {! H: {% m  ]; w( p4 U1 b感激不尽~~

' K3 [1 w' i7 D' M; S* Z2 q# b恩 我對模擬器不是很有研究,
+ l& J+ E: O& S6 }) W) R: z雖然要了解源碼內容,可能不是很困難,$ e* e7 b# l9 M
不過還是要花時間,個人目前蠻忙碌的。
4 Q, o% k) D+ [. j
: L( _$ n  I3 D9 o0 s6 R  I給你一個朋友的MSN,你可以跟他討論看看,  h) N0 Z3 g# @" F9 ]
他本身是程式設計師,也對FC模擬器很有興趣。0 j7 D4 j8 q& y. v, M  e
" d* a" U1 q' J2 o& X* @
MSN我就PM到你的信箱了。0 V# L  V5 X0 K& G! h

7 P( B( T& C- {0 `希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
$ I$ Y3 E6 \5 X( g! `- J2 Q$ q呵…… 谢过团长大人~~
" n8 z5 h- u5 i0 L; u6 `  o

- N0 I" f4 S8 R1 x" k6 l& c哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
. `8 e$ E0 Z& i: I团长的朋友都是神,那团长就是神的boss。

) d% Y. y) y( D6 I$ y+ E+ Q6 v( |( |哈 不敢當,我只是個平凡人,2 d( X. A) @7 N; |6 x) B: h; r4 d
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙, S7 u. v; l" E& U: \5 f  h
ZYH" m( p1 z( Y3 y( n
QQ:414734306: H0 s5 r! c& m0 d6 A. S5 T( Z
Mail:zyh-01@126.com7 O  ?; b, j5 Q
' C; N; N2 ?4 b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 - Z6 J! A, r+ I0 u1 W0 L0 Z; r. l3 I
再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ @; t* V8 p7 h' Q. Z0 r不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-6 01:51 , Processed in 1.083008 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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