EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 H' Q4 X" S! M, Y- A: U" |
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# O  g6 S( E9 `+ J* M, x- H- `这里有相应的模拟器源码,就当送给大侠了~~8 \1 x+ G, o; B
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
/ ~+ a- Z8 r8 X" u( S% `2 g能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ X4 o( e* ]! L, {; ~4 K
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  Z2 G- R9 n) q: Z- j0 ~) r! e
这里有相应的模拟器源码,就当送给大侠 ...
1 h' x' j+ u2 b
聲音部分(Audoi Process Unit = APU):  R5 _+ B; w' E& t8 w
.\NES\APU.cpp) V& x! R4 u( A9 r, E* O
.\NES\APU.h
4 T$ q' G7 Y1 r3 F9 f; X5 T  G7 P5 E
" H. o4 W2 Q. d% ~' a% |( Z! u( R" S
影像處理部份(Picture Processing Unit = PPU):6 f; S' @' X0 ~4 b, r& V
.\NES\PPU.cpp
" O6 @! Z8 @, _. U6 B3 `$ D.\NES\PPU.h* T- S, \8 C% P1 r* B8 p# s
0 o- {4 {' H. t5 G) M$ {( S8 G
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 E0 b6 Z; N$ _8 H; h2 d0 A. \
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
. c! ^0 N5 P( j' j(由于很多专用术语和算法机理都不明白,所以看不大懂……)
: C9 r# r. f. l# B//////////////////////////////////////////////////////////////////////////
, |' d: V/ j+ Y2 }5 ~  L//                                                                      //5 e& s( P) u1 j5 [! `% D' @- D
//      NES APU core                                                    //
- |3 s5 [( g( q: K% l//                                                           Norix      //9 I4 R8 F# c, X0 e3 u2 m0 o( p# R, a
//                                               written     2002/06/27 //
$ U7 D. }! }0 H' h//                                               last modify ----/--/-- //* C9 ^$ p$ W' ^. r/ M4 @! U
//////////////////////////////////////////////////////////////////////////
& G, Y9 f! U- L, _& T#include "DebugOut.h"
% D3 d- G* e7 R7 g) N5 ?#include "App.h"
; p- d' l7 L) @#include "Config.h"/ A/ k  {: O* q
4 }! E, n% L" `% _) b2 H
#include "nes.h"
2 B6 W+ n: F# c/ u#include "mmu.h"
# z# V/ i' t# \0 g9 {3 K; q% \#include "cpu.h"5 n6 b3 X# u' f4 G0 \
#include "ppu.h"# u6 r. A2 V) H* K  |) q
#include "rom.h"+ o5 E' \. ]- k$ ~0 i* E
#include "apu.h"
) a& |+ c1 C# |& Q2 I9 \( \& ^1 E, G
// Volume adjust. b$ V  v/ j9 {; d0 s4 I; J
// Internal sounds
$ u1 [1 H) v5 L# Y+ z" p9 U# P#define        RECTANGLE_VOL        (0x0F0). f; r5 p0 J0 `3 |; f# n3 A& H
#define        TRIANGLE_VOL        (0x130)
/ L/ N. Y2 U3 B# i# e# |& T! E#define        NOISE_VOL        (0x0C0)7 Y! Q! v' K1 L- h9 B0 N# v
#define        DPCM_VOL        (0x0F0)3 F0 |! @" G, [. k6 W1 ~5 ~' h
// Extra sounds' V1 y) @. O: o( t& O: o
#define        VRC6_VOL        (0x0F0)
9 c0 ]: g, P) l( f* a8 N/ u#define        VRC7_VOL        (0x130)
" c6 v0 e, h; a6 v4 z#define        FDS_VOL                (0x0F0). Z: J2 b- T0 l8 t
#define        MMC5_VOL        (0x0F0)
' ~* I1 ^% l3 b; y& e#define        N106_VOL        (0x088)0 ]8 k" P7 Q6 p$ d, v% _7 P& ?
#define        FME7_VOL        (0x130)
" C: L( L* u7 `" b: e- o
3 e4 {+ R$ L0 {1 x7 o3 [" l' FAPU::APU( NES* parent )
! i& j! h( [3 s& U/ U{8 y* h5 y& w& s* R: U" }1 w
        exsound_select = 0;& u# `' f( D4 J& d/ e/ }

: L6 W+ U8 y. ?8 N        nes = parent;9 s2 R( z" U' E) R* W8 e. O+ H! X8 ~
        internal.SetParent( parent );
. r' k+ s& n8 P4 v4 f
& L" k' T: b9 e3 X        last_data = last_diff = 0;& ?6 [- j5 Q/ y! i

/ N0 \% _' R; l9 z/ _% R        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 c) @/ C+ S4 Z% g! r# j* g
: y8 x5 G4 K3 Z
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
) k+ q! h! i0 o, }        ZEROMEMORY( &queue, sizeof(queue) );7 r  v' U- E$ M2 b6 ^% a$ M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" U, ~: f3 k6 r+ ~$ T1 V' K1 ~# L; q. l0 T. i
        for( INT i = 0; i < 16; i++ ) {
4 g3 g6 |* S+ ?) `: L7 a2 W                m_bMute = TRUE;
" }% K- I# X! o6 R        }5 a5 b: {8 h+ Q# G. T
}: v0 }% ]( h- Q7 T0 `' g
; H2 Q$ N! C" `0 W3 P, q3 s
APU::~APU()% h; E: F' P/ c1 K
{
  F( i) ?, v& H& J* U( c% z}
- V6 o4 ]. O4 Y$ F  ]1 W) g# G
9 r5 }& v3 I$ e7 nvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )& x5 \, l! F8 X6 f( U9 u4 e
{
# b  _( B" M0 W( x        queue.data[queue.wrptr].time = writetime;
* L$ p1 s, a: i        queue.data[queue.wrptr].addr = addr;
+ R* D$ R0 c/ w; ]5 J        queue.data[queue.wrptr].data = data;
' X- _# O% t% p- s        queue.wrptr++;+ J; d3 l5 \9 \* Q* ~" I( c
        queue.wrptr&=QUEUE_LENGTH-1;
" s0 M" l4 N" E$ B' w, |        if( queue.wrptr == queue.rdptr ) {& c( }( `& l7 x, l3 R
                DEBUGOUT( "queue overflow.\n" );6 K! O. u- C5 @/ d
        }% r3 G+ {! s: y( N* n( t! l
}4 d7 r  ]- ~3 e) p5 Y4 T# b
1 X2 V6 b1 e# i; Q1 X; Q+ V0 Z- @9 e# b
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )0 |4 f/ \% f3 B* v
{
2 w9 \; p0 _0 S/ D- V        if( queue.wrptr == queue.rdptr ) {
8 U) s6 ]) F  g                return        FALSE;
0 F9 k0 m/ j) P* \5 m) x3 ~        }
3 e; s& N( B9 C! @$ l5 q# j7 u        if( queue.data[queue.rdptr].time <= writetime ) {
0 ^% P/ `+ s$ G* _; g                ret = queue.data[queue.rdptr];+ O4 T( c* X7 b( v6 G9 @& `
                queue.rdptr++;
4 \" R" p5 @. ~/ i+ A& p  Q                queue.rdptr&=QUEUE_LENGTH-1;7 q% m6 K, R; |1 c
                return        TRUE;+ @5 y% @# u8 o0 n3 `
        }' N9 y) q. `' _  J* n8 k' Q( ?
        return        FALSE;
5 x6 V- Q  b/ j& o* d5 b4 `}( Y$ [( G7 T4 L8 e6 }% ]+ j

& p  F3 }  s6 {% s  G  t* jvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
4 J  y- x  H- [, M{( U" a% x/ P6 B# y: J5 o* _
        exqueue.data[exqueue.wrptr].time = writetime;
0 p4 H% e3 D; o        exqueue.data[exqueue.wrptr].addr = addr;3 v% @7 }9 n  p9 S7 H
        exqueue.data[exqueue.wrptr].data = data;- E+ g* h$ n" V1 u
        exqueue.wrptr++;# ~) J+ f( m: Z* [2 [. T, l
        exqueue.wrptr&=QUEUE_LENGTH-1;' F* P7 g$ V! H% f
        if( exqueue.wrptr == exqueue.rdptr ) {! d; f, [- C: X3 C/ ~& v" R) P( n
                DEBUGOUT( "exqueue overflow.\n" );
3 v! @4 q+ \& _( u( H5 U+ ^        }
$ r. ?1 r) A4 G0 t3 D# L7 ?}* J. g- T8 m5 s. a0 \/ ]* M" I
5 o( \: Y9 d1 O2 X: }
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 H) ]1 {8 J& r{3 X2 ?- X6 c5 j) u
        if( exqueue.wrptr == exqueue.rdptr ) {
7 Z  M+ j. a0 ~2 |) P( ]                return        FALSE;
) S" Y0 Q$ U- m& m6 y6 y        }% j& @, p5 h& x# r! x1 ^
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ O; v& N9 F# R$ B; p
                ret = exqueue.data[exqueue.rdptr];0 d0 r3 K& B: ^
                exqueue.rdptr++;
6 `4 E( `; U- N0 O: A; K                exqueue.rdptr&=QUEUE_LENGTH-1;
4 u% J+ f* e2 C! g! t" S! W; y                return        TRUE;( C+ g# ?; {* h* f* `% A3 D
        }
/ q4 s: w; W4 ?; X4 E3 o0 D        return        FALSE;
; [/ b5 K  ~* O$ Z' Q$ G$ [}& s) c+ Z2 k6 l+ c

7 \2 ?$ f' d! R) B. kvoid        APU::QueueClear()8 }- t' K1 ], \8 E- g. e. ^
{+ O6 X# N. p* Q' i
        ZEROMEMORY( &queue, sizeof(queue) );3 }& Y9 A" ]: ]+ r& s7 k+ H
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  P& _  H- @- r* Z9 {}
# m2 P" G3 U% D* S7 G1 Q7 _; }1 k- M# c
void        APU::QueueFlush()
* y4 |, c4 k* T0 j; s! J7 k7 i{
, P  Q, X" W1 F9 Y" ?        while( queue.wrptr != queue.rdptr ) {
5 Q2 v$ P& Q, M  \* H$ X- x: g8 o                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
& G$ R8 P( r5 f                queue.rdptr++;( Q: i8 _; a$ y# `2 V: m3 K
                queue.rdptr&=QUEUE_LENGTH-1;$ H1 Z5 m) u$ ~3 o
        }
# [/ i5 w' N) ]& I& N/ a0 T6 c7 g2 d' }
        while( exqueue.wrptr != exqueue.rdptr ) {
) T4 a$ z: D, E! [) ]4 o# `6 n                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
3 H/ D; g+ }& d+ Q! Q6 `4 ?                exqueue.rdptr++;% c# Z" [" D- z3 ^' Y6 {( D5 R
                exqueue.rdptr&=QUEUE_LENGTH-1;; y" V" K# [5 T7 c- \9 q
        }: o9 _8 ?3 Y- w" T
}) |! `% S+ p# l" _4 Q7 i
; C6 M) T+ O  z+ X
void        APU::SoundSetup()
2 R# M/ S6 r( I5 N{
, N1 R' ]% X$ e8 M        FLOAT        fClock = nes->nescfg->CpuClock;( }" v4 z1 r! ?# G1 e$ ?
        INT        nRate = (INT)Config.sound.nRate;$ i+ i$ p% n" B% z
        internal.Setup( fClock, nRate );
9 {: C- d) ~9 q6 ?% _1 b        vrc6.Setup( fClock, nRate );- S: L9 N" Z, W2 U
        vrc7.Setup( fClock, nRate );! ?" c/ U4 W! r. Z! D
        mmc5.Setup( fClock, nRate );" U. O6 S( A5 c, U# H' s" [- [+ H
        fds.Setup ( fClock, nRate );
9 X4 f3 V7 ]) P5 `5 _( P( j        n106.Setup( fClock, nRate );
6 Q8 H3 p6 Z* \" }/ k        fme7.Setup( fClock, nRate );* e( y/ p9 X- j4 s6 \  G
}2 Z. n+ h2 `) T0 H6 M/ W
. [- Z# u4 g. l9 @* x0 v
void        APU::Reset(), F  J7 A8 v# o
{
2 I% i* @2 e4 }5 Z  H        ZEROMEMORY( &queue, sizeof(queue) );
! A* I1 g: `7 }; T  h        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ |& C  ^2 P% A1 b6 E  W: f9 T/ s) f6 b" R( ?, @
        elapsed_time = 0;5 L5 Y( |* L6 C: _9 u4 |0 f
* ]+ h" ~9 W' a" \* A% K3 ~! P8 O: |2 R
        FLOAT        fClock = nes->nescfg->CpuClock;
  b( ^+ {/ Q# [0 R) F        INT        nRate = (INT)Config.sound.nRate;
" H% T; o8 \5 p: \, p" ]        internal.Reset( fClock, nRate );
4 w' A) T0 _9 T9 g6 q        vrc6.Reset( fClock, nRate );
6 u0 i' h3 F. Y) e        vrc7.Reset( fClock, nRate );+ O% ?6 ~  @' z7 @
        mmc5.Reset( fClock, nRate );' M' F8 i% q. B
        fds.Reset ( fClock, nRate );3 A; r/ S) z3 {
        n106.Reset( fClock, nRate );
! w9 Q, |: p# j8 L: U        fme7.Reset( fClock, nRate );; c! \% v' h; z7 o) B2 j1 w( S. \

( G: I" R; b5 d( ^/ U3 x+ g        SoundSetup();
& t7 ~  |, B2 T# e}' a6 S4 ~3 M* s- S& f

  m3 ]7 \/ m$ ]% q( w+ w" H( @void        APU::SelectExSound( BYTE data )
; f, x4 G$ b8 b4 P/ K1 `{
4 \' H/ r& U' T2 S6 X+ Q" b+ p        exsound_select = data;
* _5 @& B3 U) D0 Y0 @/ y}
# P- N+ }" b/ p$ N5 [
% T) `& I' W. x  }BYTE        APU::Read( WORD addr )( F* u2 `: O9 X2 P+ n
{
% {  u" a, T  h  U% K        return        internal.SyncRead( addr );/ R# l; X$ J, o& @- H4 W
}. s  ~! }& e( T5 b  B
6 h. h1 E- q5 }5 z+ H
void        APU::Write( WORD addr, BYTE data )
; L$ a' o  ~3 ~* Q{) C* Q: s$ P  d4 @! ?, d$ t
        // $4018偼VirtuaNES屌桳億乕僩
2 k3 }! q4 D5 T8 {4 u        if( addr >= 0x4000 && addr <= 0x401F ) {
. ]) d+ {" m" R& O: I                internal.SyncWrite( addr, data );& @% K' Y5 P( y( O
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );9 ~9 |9 \$ Q" i8 |9 z
        }, D3 q( ~; b6 u6 ]& C: Y
}' l9 `0 W% d# f+ [% t

9 @# S# i! ~4 JBYTE        APU::ExRead( WORD addr )3 o  b4 j4 P" w2 U4 ~. D
{2 f9 H- L( {; E5 N! h$ X, H
BYTE        data = 0;( y, ?; Z0 X0 |  D; ^
# h8 y7 f# U! d9 u: q# J/ a
        if( exsound_select & 0x10 ) {2 ]- j6 v) L& ]. j7 u: U
                if( addr == 0x4800 ) {. T3 G' d& T5 N( E2 d$ G4 l
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 e  i" a  G7 F7 d9 u# ~
                }
( K0 ?6 {$ R' y9 f+ z- _        }
  s' Q' Q) |+ \/ m. T  i5 v: S' K        if( exsound_select & 0x04 ) {4 j3 u, E. W& I- a- C
                if( addr >= 0x4040 && addr < 0x4100 ) {
, H3 q; K+ I3 s                        data = fds.SyncRead( addr );6 D4 y+ e  P) `7 A6 U& h3 J
                }
, t4 o! ~" {) M0 `: x8 v9 v( x, n. F        }
; j( K0 F. @9 g" G+ Z        if( exsound_select & 0x08 ) {
& M2 c' F2 s' [2 r6 k                if( addr >= 0x5000 && addr <= 0x5015 ) {5 v! I# E1 B# G  f
                        data = mmc5.SyncRead( addr );
/ N- j6 c% |  l  m                }
6 F) b( D! V$ K+ ~  ^8 e& t        }
4 N+ V+ N. p, H7 ?( w- [
" ~' s) r4 k; i3 d% j( d        return        data;; v0 ]' u$ e" V. U
}
0 L2 N. o- s2 h* e% [0 u' B" R" A$ V0 B; y6 T4 q- q% R. F- M/ ~
void        APU::ExWrite( WORD addr, BYTE data )
% x& A6 ]0 F" Y; `2 `{% Q/ [4 `- }9 H" y4 S
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 z1 D7 N( Y, O) M6 Y. K1 {6 f6 S. [
        if( exsound_select & 0x04 ) {$ c, e9 [# |- u6 e0 f7 V1 ?! Z
                if( addr >= 0x4040 && addr < 0x4100 ) {# ]% T& j' N) R& _; w5 Y8 s5 I
                        fds.SyncWrite( addr, data );
2 h+ K- z+ O* ~/ n2 y6 Q                }
" m% X; g7 F' |0 b        }
* y; V, n! R! l+ Z; B
: M$ P# V7 [! T6 T        if( exsound_select & 0x08 ) {
& o* O! M  @+ o$ x                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ k# @! W2 ^9 ^; D) R& _* F% M6 G9 r; g                        mmc5.SyncWrite( addr, data );* I2 c/ Y$ ]. C7 r
                }$ J3 z" c& m- ~4 A/ R6 V
        }6 \4 R4 |0 A) O& z: g5 t
}
9 w" [% J* H" I3 r5 p5 x5 t
5 Z# ^# t/ A  ]- t' h, r. j! c9 wvoid        APU::Sync()
9 r" U) F( J; _4 ~, Z6 X{; |: A2 o3 U* w) i" j; J
}
4 s# r4 K6 \+ Q6 F/ G8 v9 [' J  _% K6 V7 Y# ^
void        APU::SyncDPCM( INT cycles ), e, ~# J, e5 b+ j! D& Y/ Z( Z0 E, U
{) C% y% l6 Z, t( `! f6 ?7 F; }
        internal.Sync( cycles );
/ b* W8 k7 J7 W
: s+ }: e, R+ g; [( H- y        if( exsound_select & 0x04 ) {: J# m6 H+ O0 \
                fds.Sync( cycles );
6 C% L* n" X4 E" o9 M- h        }
- a: Q2 P6 ]" ^  ?7 d! Q1 r- \) [        if( exsound_select & 0x08 ) {, Y0 m' G- I% ?! x
                mmc5.Sync( cycles );$ {1 ]1 O7 W+ F/ B) N" N: ?1 e) ~
        }
2 k# C2 z$ z0 b+ m3 {}
6 Q* O4 \2 W0 P. z! {
$ f; \; p: ]) d% U. h$ s$ Bvoid        APU::WriteProcess( WORD addr, BYTE data )+ n1 k  M  m1 m3 S
{4 a+ R9 U& }/ ]# ~5 ]
        // $4018偼VirtuaNES屌桳億乕僩2 e+ I: F) T- c% d' l5 F
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 M, F0 |2 T. H5 y& W* O                internal.Write( addr, data );; g7 u' i' r9 |: Q' B0 o( ]
        }
  {! V9 p2 t, @; I2 U3 p9 b}
6 z- `; P3 m4 T6 a0 b
& E4 t& d' w$ [& h" mvoid        APU::WriteExProcess( WORD addr, BYTE data )6 a0 O5 g/ y" m" I5 K( f: D
{
! r; f/ g# _7 E" z1 j7 \! F; _7 X        if( exsound_select & 0x01 ) {
* }, l, k6 z3 x8 F6 }                vrc6.Write( addr, data );3 j, Q7 E7 {8 V6 s4 a
        }/ G6 z- r* r8 t$ O2 E% W1 H
        if( exsound_select & 0x02 ) {
, V( `  e+ A" k0 ?6 S& ~# @8 r                vrc7.Write( addr, data );
. `; {/ w8 A4 i; ^& e        }
' h0 q5 e8 r! I) A& L        if( exsound_select & 0x04 ) {* t9 F* j' w( b( P8 W
                fds.Write( addr, data );  P- B! L  z* ~/ t! D
        }
% c0 w, F0 M! V2 g9 l% L        if( exsound_select & 0x08 ) {1 K5 T% q% ]% A1 {
                mmc5.Write( addr, data );; I+ r' N* A- K1 J9 k  e
        }1 N4 B9 B8 S! }2 N3 e
        if( exsound_select & 0x10 ) {: v$ x; S% y" {. D! e
                if( addr == 0x0000 ) {/ Y7 X- }* [. \2 N$ B& m2 P
                        BYTE        dummy = n106.Read( addr );; ^" N% A/ L' S; K% D6 S
                } else {/ N" F7 p7 w* w5 |3 |2 N2 q
                        n106.Write( addr, data );
; y, b% b; c! s  S                }
4 P* {+ o2 w. K* H$ d& i! |4 Z8 S        }0 r' |, t) k* |0 e
        if( exsound_select & 0x20 ) {
8 r3 v) S0 Y% |/ L* ?* j" Z                fme7.Write( addr, data );
! A6 B0 \1 d4 I# D; A4 z        }
' D/ A  k6 x) f+ P$ V! ]}# D+ j* f: F" e2 H( P3 {

. f6 I! K# O# V; L9 [3 Ovoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
- G( Q5 J+ C+ f  n& \3 c# x{: H. ]4 f0 G* F& Y  ?
INT        nBits = Config.sound.nBits;; ^. E8 E& l, f4 L
DWORD        dwLength = dwSize / (nBits/8);
4 o9 @. q# r3 G3 W+ y7 [) W- GINT        output;7 t- T! f0 Y0 f& |" R7 p
QUEUEDATA q;
, [6 [7 @8 d+ B  s9 {DWORD        writetime;# i* Y: z- K0 i/ a6 H7 ^% K
6 _) o& S* Q+ B( {6 z$ E: H
LPSHORT        pSoundBuf = m_SoundBuffer;
6 y+ s/ N4 j' y% W) SINT        nCcount = 0;
' k( Z4 o: ^' y# f
8 s6 M7 u# G+ c8 N  B$ d! {% CINT        nFilterType = Config.sound.nFilterType;
- w5 K, v4 E1 K' q' v+ x% u. c" I
0 }$ ]9 \7 t0 B  D4 v1 {5 k        if( !Config.sound.bEnable ) {
+ ]# U. Z) N2 d                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
6 A$ Q) t/ `4 h8 d                return;9 `+ c) K8 x2 j
        }5 M9 p+ A9 v7 ?

  o& C  P( x  n. I& J$ x' o        // Volume setup
( H* c3 \& m5 @9 n. O$ I        //  0:Master
. b: V2 S4 T3 G7 G: {. {* N* i        //  1:Rectangle 1% _0 \3 y/ \, k/ s
        //  2:Rectangle 2* a% d7 U' r2 l  `0 g' x9 A
        //  3:Triangle
. S5 Q: D: m  l+ K) X- ]        //  4:Noise! o) Q" G& R3 ^; Z! k. f9 U( Y
        //  5:DPCM2 [$ x# c& A5 A1 u6 G
        //  6:VRC67 D7 \4 A& e; B) O/ c
        //  7:VRC7
: B# ?5 r1 s+ @8 S" O& n' h        //  8:FDS
* b& c4 }% b1 I7 ~        //  9:MMC58 T+ {. S6 W/ x- |
        // 10:N1069 r. K  ^" z& Q$ V
        // 11:FME7. D' h0 c: o( u
        INT        vol[24];( ~; L+ U( b2 v
        BOOL*        bMute = m_bMute;
5 |# O* |# t( \" E6 S4 ]' t        SHORT*        nVolume = Config.sound.nVolume;3 _) W/ [8 {& c

2 e! S7 ?; w8 v* f0 m# l: n/ K        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# E/ v; d. E' O$ i/ J- n
1 ~8 K/ q) P# N2 @  L- a# a
        // Internal
: _' n6 d4 J2 c5 ?3 t. A' Y        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 D2 a9 h7 \1 u* o) e* w4 [' A
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 i3 D( M1 v$ g+ T6 j. T% @        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: V/ E+ c) E: r
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 v+ f; e* y( i$ x" C/ g        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;6 s0 k" F# ]* s. t8 q2 J8 H

) S1 x' r8 g) d& _  r        // VRC6
& F5 u1 D, p( I* D7 b" G        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 Q8 ~3 N7 F! C        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; I2 M: \0 [- ~8 Q        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ N+ p. X' D1 V6 K/ @9 z3 B' h

( p# f! M' N1 g! x2 [* a        // VRC7
1 P4 q" r) u/ o5 q        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
# M' \" j- R  D1 T& N' [) C* k' e0 N- z
0 _' |  X; ^! a# X. ^3 ]        // FDS% R0 N: h, j4 @6 r! U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
; C/ F2 }! X; B3 B5 c- m- k
# t" q6 q( v+ Q/ ~0 u        // MMC5
& ]; Z8 l) I9 c        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 @1 i0 Y" P6 s0 W% C
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: M4 \8 ~( b$ Y0 o* v$ M        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ K$ F$ K$ N0 |
% j6 S+ u- K9 J4 g7 \        // N106
2 }3 a( f+ k( C/ ?* ~2 z        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, g; J) O6 w' {/ G        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ P$ H" Z: c# B7 g& @6 e- S
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* C1 F; X/ |3 O) c0 G( F0 v        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ Z0 Y' w& ]2 i3 O- o
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% k8 D9 T3 n2 I5 W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 {) W8 l! ^2 X  G        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: u, N, f4 T, O8 w* q4 x8 R
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# b* [, [! J% n6 b! @
) E* ^5 {5 W8 w: ?0 v" A
        // FME7
+ Q2 a, Q; |& G/ c7 Q$ Z# ^, r        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 d3 e8 V4 t4 l4 i2 l        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 h4 A% p5 Q8 J, B
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! K' T$ K/ j& b; F

: F- {5 [* p/ \7 v) E//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 |# R- R1 `, V+ l: T! ~$ \
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;$ g6 c' }7 E: c2 y: ^8 {% @

! g5 F; P1 a3 w2 p' \' e, ]        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟7 s3 l* M2 G6 [# S& M5 b& s( J# Y
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: C8 Q- _  M: N5 A
                QueueFlush();
, F" K7 a, q. Y) b0 h3 s        }
3 U6 c1 F! f0 R) F5 \- b6 K8 H  K: p) t  o
        while( dwLength-- ) {
* |( V# F* X' B# N                writetime = (DWORD)elapsed_time;2 d/ Q+ P# X2 q
8 N& ]+ W; d2 L* Q3 `- ~! H
                while( GetQueue( writetime, q ) ) {! q) P/ _! V/ P  Q1 L6 ]7 t
                        WriteProcess( q.addr, q.data );
: i8 z0 I4 E) ]) b) ~                }2 D3 J0 }. x" _
6 X9 [9 r3 D0 A6 ?% k7 S9 ?
                while( GetExQueue( writetime, q ) ) {
0 @% C* ?# L! Q5 }) m6 @) L* W                        WriteExProcess( q.addr, q.data );0 J$ h8 {- q7 ?- Y6 t
                }# O, G. q' R0 l$ N& ^7 s5 C
/ U+ _* [! ?* K  L8 n  F& c5 Q
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 j: G. `8 }) ^6 S2 z
                output = 0;# w# u8 k2 s1 B7 q+ U, H
                output += internal.Process( 0 )*vol[0];
+ [9 B/ ^& ?6 _                output += internal.Process( 1 )*vol[1];
7 D4 V. v1 `8 n  ~2 y7 b. ~                output += internal.Process( 2 )*vol[2];  A+ \* ^( h2 M0 B$ B$ ]
                output += internal.Process( 3 )*vol[3];7 c0 \4 r" a1 c1 e
                output += internal.Process( 4 )*vol[4];
6 F$ Q# U: ]) d, m. `6 Q  X* L/ Q0 @6 q  A. R
                if( exsound_select & 0x01 ) {8 q( g9 A) Y! Z/ d. P
                        output += vrc6.Process( 0 )*vol[5];; {! Q* j- e6 Q& s9 e( T
                        output += vrc6.Process( 1 )*vol[6];
* \" o6 u% q+ t6 K% K. X  T                        output += vrc6.Process( 2 )*vol[7];0 k& W7 E( A* w; W% _
                }
0 Y! m% \8 ~/ B  u% x1 @                if( exsound_select & 0x02 ) {5 M8 F5 Y$ \! E4 |$ {' X# `9 b7 T* t
                        output += vrc7.Process( 0 )*vol[8];; H& c% P& N1 ^9 u# t, q) i2 N1 Q
                }& @, {6 c& t% c/ Y* b+ a
                if( exsound_select & 0x04 ) {
" P1 N4 `) z! T4 z# a                        output += fds.Process( 0 )*vol[9];
1 g& R& y9 Z4 ?: P                }0 v1 o# c8 P1 c0 K4 K) L0 l  ~
                if( exsound_select & 0x08 ) {  l- {  G) x2 G- N1 k
                        output += mmc5.Process( 0 )*vol[10];2 S* B) N+ X. h' s
                        output += mmc5.Process( 1 )*vol[11];+ k4 m' p8 l) L# D/ l5 P
                        output += mmc5.Process( 2 )*vol[12];
) V" y+ U6 ]6 K3 l9 F! N3 r                }
, k+ m' K$ l: E6 C% D                if( exsound_select & 0x10 ) {* \4 v$ W' o. L
                        output += n106.Process( 0 )*vol[13];
7 H8 p& F: h- G: l                        output += n106.Process( 1 )*vol[14];. {1 \5 o8 G# @' w' x
                        output += n106.Process( 2 )*vol[15];
$ ?9 P2 e1 k: S8 H* s                        output += n106.Process( 3 )*vol[16];
3 l- Z3 T* o) v5 c: S& B, t  {5 y                        output += n106.Process( 4 )*vol[17];# ?1 u" c4 G4 D1 k& @9 U
                        output += n106.Process( 5 )*vol[18];
( E7 Y) r* w( M5 W3 C, j                        output += n106.Process( 6 )*vol[19];* g" b+ _1 L  @' o
                        output += n106.Process( 7 )*vol[20];% V; S( N# `- D0 E& @8 @
                }
8 G6 ^5 g/ S9 b8 Y  k, q# I4 L, \                if( exsound_select & 0x20 ) {
3 D0 M# U, l9 C+ @, A* u: W& d                        fme7.Process( 3 );        // Envelope & Noise
7 K8 n- R9 }, F$ \                        output += fme7.Process( 0 )*vol[21];9 l5 T, {5 J/ N3 K6 L9 c" U
                        output += fme7.Process( 1 )*vol[22];# q5 s' x& b5 d6 i
                        output += fme7.Process( 2 )*vol[23];
, s/ ^2 F- ^4 I* p& Z  ]                }8 H! A5 k8 i* i

/ n" K; v7 x# ?3 _& h. e1 e                output >>= 8;' V1 q: U4 z9 W$ z. u3 z* [

5 h0 a' ~9 X; p6 J# A                if( nFilterType == 1 ) {
$ \  g% n8 g' @. x& P% }4 s# \                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)0 t- O0 B: p$ C  }' G
                        output = (lowpass_filter[0]+output)/2;* G6 p: J: W0 F* z8 S
                        lowpass_filter[0] = output;, [: c9 H0 s& k+ C" R8 w
                } else if( nFilterType == 2 ) {6 E( L" u* u- w  B
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)# F3 p! U! c# @9 A, @$ d9 c
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;& |2 R3 ~' W1 E, `. ]5 o
                        lowpass_filter[1] = lowpass_filter[0];& Z+ @1 Q; S6 R3 |
                        lowpass_filter[0] = output;8 ?% n% {% |0 Z7 T4 h! @
                } else if( nFilterType == 3 ) {- C. u0 u8 V  L, G+ O4 n1 U" ]* }* r
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)! W: I& b  O# e$ c1 N8 l' o8 }
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 {9 H& R- ]1 v5 f" Y& o8 b- e                        lowpass_filter[2] = lowpass_filter[1];/ Q, V% Z- w: i
                        lowpass_filter[1] = lowpass_filter[0];! q9 s+ r/ Y0 q" H+ ^
                        lowpass_filter[0] = output;
& S4 I8 U+ E) d4 ?& A                } else if( nFilterType == 4 ) {& |8 F" X$ g# i/ P5 v) \
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)3 n' k/ x% }* t: b1 r* g: ~0 ^6 y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
% q7 v: K* V! b: R( y                        lowpass_filter[1] = lowpass_filter[0];
$ P# i6 r, D/ q* o' i) ]                        lowpass_filter[0] = output;
1 |( i% J  T6 G                }
0 T. @5 S) J+ \# u$ E( y! p% D7 z- o& [, x& R9 w* N
#if        0
8 I( b9 s. r( U- b. j9 ^- W5 B7 [                // DC惉暘偺僇僢僩- G- B! h" |* _' `5 X! |
                {
) v6 F8 c& X' d: @% k& w: C( Q                static double ave = 0.0, max=0.0, min=0.0;
4 o* ^' |$ V4 e+ o* z                double delta;( T- \3 V% \# }* K2 ^$ O
                delta = (max-min)/32768.0;
3 v3 M5 G" R. @4 O                max -= delta;% H" m5 O" X6 s) D: F3 L
                min += delta;. ]& [9 @) |/ S6 w( @2 [) P
                if( output > max ) max = output;: K4 y7 x6 k, w
                if( output < min ) min = output;
+ [. {5 I6 _6 \; W/ G6 O. s7 G                ave -= ave/1024.0;
. L3 p7 X& _7 U5 z+ F" U8 R                ave += (max+min)/2048.0;. \6 x9 H* Q2 i2 |" C
                output -= (INT)ave;# P: a( r7 ~" ^7 i; y, B% z5 H4 S
                }
! u( p& w8 F7 f" j, j* L0 o3 S( m#endif
; F% X6 g4 E  u$ w" x. b#if        1
5 u+ J- U/ r+ p$ \  _- W                // DC惉暘偺僇僢僩(HPF TEST)6 \9 R  `- C/ J6 }
                {
8 A# F' X5 z: L2 G//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);: y' R' ^1 I( d6 P$ k
                static        double        cutofftemp = (2.0*3.141592653579*40.0);" H/ T& x) W2 `3 H" B  K6 h
                double        cutoff = cutofftemp/(double)Config.sound.nRate;5 ^+ b3 R% N+ r2 r: ^
                static        double        tmp = 0.0;
9 M. ]. }  D9 v3 Z2 f* g                double        in, out;, \7 K2 i$ {/ d' T7 R4 {3 X

5 x! g1 F4 X7 V: ?1 L4 |! }' D( L' Y* g                in = (double)output;
- l% V! B! x4 m* r5 E4 e! H                out = (in - tmp);
( @4 i8 ?4 U6 Q& e2 |                tmp = tmp + cutoff * out;
1 _) ?- P4 b  e$ W6 c* y# Z& e4 t) t* L/ L  H( }$ L* V
                output = (INT)out;1 }, h. [& Q& w& ~
                }
- D$ V* [$ z6 |) Y; h5 f#endif
( f! Y" M9 \. g/ Z#if        0
% E1 v8 F; Q1 [. Z/ f) p, h                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 z+ v5 w& ~$ _
                {" y0 N# v) e6 Y# v7 m; u( L
                INT        diff = abs(output-last_data);: U: }2 c4 ?5 L1 V0 s0 ^# y
                if( diff > 0x4000 ) {# F8 T0 P0 p& j2 e1 D+ ?) v
                        output /= 4;
! u" v2 \" R$ q  h" U* S1 [                } else & {. c4 y7 J9 Y1 J! ^
                if( diff > 0x3000 ) {- T9 U! l' c0 e' E7 g- o$ m
                        output /= 3;
) T* t2 ~6 R* k                } else
/ R* I1 p: J* ~3 [. w7 h/ r                if( diff > 0x2000 ) {9 L6 x  O. S6 E0 ^! K
                        output /= 2;
- t7 m( E; r* k% d+ T5 C5 w5 O7 ]                }: z- M: t6 g8 o  c
                last_data = output;( J% M& V& o4 k! \* H9 `) ^: h
                }
8 E7 G: S3 S& B+ F/ u#endif
1 ?6 L8 l) x/ h" }7 p8 ]3 O" M                // Limit
6 Y( T' Z4 F: p! a                if( output > 0x7FFF ) {
: p% C7 K9 |3 K6 w                        output = 0x7FFF;0 n. o, e' g+ _+ k
                } else if( output < -0x8000 ) {
" u0 p& Q$ R$ ?5 T+ B& X( D5 x                        output = -0x8000;5 ]& l; P  l2 Q2 Y0 [4 O
                }  y( }/ \0 t2 u$ h: j

% f8 f7 L: h( G3 t  n1 @" o( r                if( nBits != 8 ) {* d. a/ X# K1 Y8 V$ `. D5 J
                        *(SHORT*)lpBuffer = (SHORT)output;, H1 ~; F9 N. X$ `" w9 ^
                        lpBuffer += sizeof(SHORT);
9 }- B! \7 P; ]                } else {
5 k: O' a! r0 N4 |& N4 ~1 o                        *lpBuffer++ = (output>>8)^0x80;
, m4 D6 m6 |& V( R8 }                }
9 }( P, o1 M& R, C' z5 @/ G- |# P6 T% g. M  K( O4 U& n5 r. @
                if( nCcount < 0x0100 )
% t& Y, j7 M+ e4 E, a/ P' N                        pSoundBuf[nCcount++] = (SHORT)output;& P0 c5 |8 E7 M3 Y
# D8 |  J, L+ L- b' U( ]! H. F% R% E
//                elapsedtime += cycle_rate;
( r% K8 r6 p3 \) m1 X                elapsed_time += cycle_rate;
$ x6 D$ P9 k; u3 x. T5 r        }
% \! Z) H+ ~0 [; J+ i9 D" [
6 `! h& M- Z4 e; l* E9 T2 m#if        19 `+ K6 R; ~+ T/ w) W" l  x
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" m5 J  z  ~2 j; H7 G' m8 k
                elapsed_time = nes->cpu->GetTotalCycles();* h1 v1 K9 l0 P
        }# Q$ N# P3 B  T" k; H* T/ X$ C" n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
, D% ?+ B4 K0 {                elapsed_time = nes->cpu->GetTotalCycles();: a1 F" ^5 @. Q# D4 k% j( R# l* x
        }% k5 b: `2 {, i" Q8 q
#else$ E0 I/ s* s. a# |5 m  J
        elapsed_time = nes->cpu->GetTotalCycles();& ]  ]$ h% s  w/ p' F/ b
#endif
+ \6 o, o" n4 @' F3 l' h}
% ?& i# C. a7 R1 }( n- Q9 h$ x9 j$ v4 q1 ]* n' }
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)9 h4 y9 ?. E; z& B; B4 `# ]
INT        APU::GetChannelFrequency( INT no )+ \4 U. S" K2 h5 e: s) n
{
' w; _+ F  R$ J        if( !m_bMute[0] )
$ m) P) O9 h6 Q' V7 y: N                return        0;2 t; X( b$ |2 |& T' ~

3 o( J" S/ j( ^( m        // Internal: [4 M7 ?1 r8 W6 g* u
        if( no < 5 ) {
# x3 _/ f0 r) \* W! w* C% }4 J                return        m_bMute[no+1]?internal.GetFreq( no ):0;
8 Z  H2 W( ?, {5 F2 C        }# K, `  k" U  v5 Z) H( v  G5 w
        // VRC6
6 }  U3 K" ]7 _$ K* M( Q1 z        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {- V+ Q3 b7 Y% M! c' ~
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
  ~6 ^/ J* @0 ]8 r) u6 y        }& I( z; S  S; t: I8 K
        // FDS
1 b$ _" U; Y( Q) Q; ^( s        if( (exsound_select & 0x04) && no == 0x300 ) {, u& a# |+ X$ I- A( b6 ]
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
& W9 Y, M# |! U4 ~        }
9 n! i2 w4 O6 z        // MMC5. D2 k1 ~8 {; F' T
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {' ^: T  E+ X3 O! `
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  k% o7 F1 p& [5 c& M$ \. [" Z
        }
" T' }( p, n; r: X        // N106  x7 W  a: s% |# o; F2 Q
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 q6 ^3 F* X( o9 J  C/ n& X                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 s4 Q- ]! j9 j: y
        }+ m( ^/ k$ a5 S7 n7 C5 a
        // FME7, j; z( y- o9 @4 ?" v7 ]
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" b3 D" W3 ]2 Q, |" f                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;1 V( |, B3 F' F+ j4 t: i
        }
9 l: s8 o& K& P+ k        // VRC7
* V% a) f. B# ^4 b+ f        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
' o4 q. J. _+ [3 f& K9 t                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;8 I4 S6 j7 x1 ^' S$ z9 ?
        }( R7 A+ L2 b2 D* |
        return        0;# U. ~8 _' U. x2 U
}
  \, g2 V2 Y9 P8 O" q: C% _7 Z: Y- w6 j1 j' G1 |& t
// State Save/Load
2 B6 F. t1 y2 @# F# }void        APU::SaveState( LPBYTE p ). R  t5 ?8 V# c# L+ ]! k) }5 ~
{& d7 V$ o7 M; b( r( z
#ifdef        _DEBUG5 z( t5 V, X- \# ]  y( F9 r4 I
LPBYTE        pold = p;# W3 G* y1 \1 \9 m, I4 J3 A
#endif
8 d# W) ~" W& O) `0 |" }0 i/ J. m2 W" P6 F7 d
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
; E* m; t& B' R- d        QueueFlush();
; D4 J# L% E+ M5 B# y! ~  p% E  P8 n/ r9 f5 E, P
        internal.SaveState( p );
. @' u" D0 p7 h: h        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ n: o) ]$ [, [

9 _; q7 f: ]  `2 y        // VRC6
9 J0 F) ]+ N( [- v  o  Z6 j        if( exsound_select & 0x01 ) {
* k+ e3 w/ D, M                vrc6.SaveState( p );- ~+ {: D. o( H0 G% |
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* ?. K: s4 E+ R( F8 P        }  V% {& w) L! J8 F6 H
        // VRC7 (not support)% ^1 U$ U0 L7 u3 h2 l2 a; C2 b
        if( exsound_select & 0x02 ) {& \3 \, _: }$ h$ M5 |5 a4 h
                vrc7.SaveState( p );6 [! m$ Z' e5 C' V: E, S
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( T, m5 M: z. |! j5 k$ N
        }
& h+ A0 h0 q/ `/ `% A: O& j3 Q' J        // FDS
8 p* w! E/ ?/ O6 y, q' Y# E  [2 P        if( exsound_select & 0x04 ) {
* h8 s$ h+ D3 [9 f3 G, z! `                fds.SaveState( p );
5 V7 z- v9 }4 X) U' i                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
; ~' }& Q! p4 v0 M        }
1 g7 w0 O$ z. c) n; s        // MMC5
9 C9 E' U6 N- A: y        if( exsound_select & 0x08 ) {- {" b( m# c: G4 v; D
                mmc5.SaveState( p );
. W3 U% g) c$ z& ?                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 T# O/ l# u; N8 Z3 ]9 p9 t
        }6 O9 r3 M/ G8 ^$ v7 ^
        // N106% [, W2 }0 k4 |* n
        if( exsound_select & 0x10 ) {$ X0 X3 O  v% c/ G6 P( U
                n106.SaveState( p );: M" n, v# n# q9 ]
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 d) [/ }' r" @! C
        }! e+ a! F/ V* _, s' M
        // FME7# T0 D5 i% {+ [0 @9 j
        if( exsound_select & 0x20 ) {
. w% A* q' s- P3 d7 m                fme7.SaveState( p );
" X/ e; w7 L5 C9 X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ }; f. z0 z7 l2 e2 a3 e; P
        }6 g- ~- J8 V2 |- O* q7 }8 A
% e# l' Y7 L$ y( d: i) H, ?" h+ c
#ifdef        _DEBUG
- D, }- m/ a1 ~DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );2 q4 G; W( t7 r& Z7 ?- Z
#endif
$ s7 t) I+ o  |4 V6 P/ N1 n, {}
9 J0 Y5 z& I% R3 L. p! k* U% |- M/ R
- h- q6 L0 d* h! h3 U1 h- g1 i2 Avoid        APU::LoadState( LPBYTE p )
6 h: P* B- I& B6 J( d2 V$ ]{; \: B3 ]/ t' F; x9 S
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) {) o. f. }2 H! x        QueueClear();
; c$ e/ J; M, h$ s' X  y
9 ~0 y+ a! ]# R        internal.LoadState( p );- ~8 l; U$ v& c
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 k# k$ O! E2 X' a

# I6 J$ ^/ v. w# w$ B        // VRC60 a. d& B  r- W  K  V/ Z
        if( exsound_select & 0x01 ) {
8 _) [: K6 I2 W( j! U5 }                vrc6.LoadState( p );- g6 Q8 X; F/ {/ l4 O8 D/ I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) @9 \2 r3 |/ K  a        }
: P! I! _" }0 |        // VRC7 (not support)
; u" ~" p9 W5 t. [# w/ p2 w* o7 D        if( exsound_select & 0x02 ) {
" \, j$ Y* x* d# p9 ?) h. _                vrc7.LoadState( p );+ T! h3 ~7 x' \3 a+ M2 J( h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ B: l# r& z! u( I, Y4 g: D        }( T' T% i: W* {9 v
        // FDS
) p/ x; d4 T' J' `- T        if( exsound_select & 0x04 ) {
# _/ Y$ J4 w0 n                fds.LoadState( p );. Y) I$ ^% b+ w, |3 f1 X9 ^1 k
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& A- {, M7 f0 {7 C. U6 X        }+ G2 X! R  e# B6 X
        // MMC5' y5 D3 K" ^: C/ l' p) S! ^1 e  |1 y
        if( exsound_select & 0x08 ) {
# x; g# p( U/ x% U& C/ L' O  a                mmc5.LoadState( p );) [, }  {0 k4 q2 c2 q8 W' S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 g  u( ^! U! x& @, S* s" W
        }- ^6 l% Z* V* k% ^8 J; f" B
        // N106
7 t& }: S: S3 o        if( exsound_select & 0x10 ) {
1 M8 t! V5 |5 |* J5 U                n106.LoadState( p );: i2 T( M  L: h  ]( ?
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& n( J, c9 D+ m9 ~
        }, M7 L' M  h5 v5 l% l6 j
        // FME76 v4 X4 r: ^& D9 N. h& g* L- {, ~
        if( exsound_select & 0x20 ) {
% U6 A$ T# w. f9 f                fme7.LoadState( p );
4 J! k! R! W& @- Q" d+ J4 Y+ k% I                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 A( X+ l$ O/ m1 o  H' `- n        }$ l" h3 Z; ]8 L% R
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + S0 U$ |5 D; V$ A! `
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 M# D1 u6 @9 J1 T+ j3 P感激不尽~~

$ S7 i, S' {) H' L* W3 F恩 我對模擬器不是很有研究,
7 {( [, G+ M' c1 I  h' g2 S0 H5 n雖然要了解源碼內容,可能不是很困難,
  X/ I2 }2 t) a+ w% ?' t8 X; X不過還是要花時間,個人目前蠻忙碌的。
% G: b7 D+ V% Q7 ~3 [7 K) k  u7 N9 N; N% f) @, t9 |9 r
給你一個朋友的MSN,你可以跟他討論看看,
, O. a5 J; K; o" V6 @) d7 K他本身是程式設計師,也對FC模擬器很有興趣。
. ]7 s) Y& i/ e6 h7 c: ?
8 D3 H6 k) B5 ]9 u- Z! `# d" r, PMSN我就PM到你的信箱了。5 p6 X; c) q* K5 G' \% Z( V3 \$ ]
3 R/ h( M. |- ~2 e0 u
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " V8 a5 n; }, J2 G/ h' N: j
呵…… 谢过团长大人~~
0 h6 z" M5 s" b" u1 B
! p- ^6 O8 Y) K$ j# |
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ q1 n# |4 d* [5 Z, k' n1 _团长的朋友都是神,那团长就是神的boss。
/ T' Q5 d/ X+ y. h1 e! e7 B* u) j
哈 不敢當,我只是個平凡人,
$ ~$ f7 V- E4 K. Q2 [. t8 `1 `要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
' J- [) n. d+ [ZYH% H7 i8 P7 \0 W! S; S
QQ:414734306! {% Y8 Q: n: L9 c) J$ w
Mail:zyh-01@126.com* q: j8 }8 {3 {) z6 c6 a* m
# J( _3 O, ^3 x" F
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 / ?' @$ w: c) B  a: e0 ]! r5 A
再次对团长大人和悠悠哥的无私帮助表示感谢~~

  `, n" s; X7 x0 h8 z  u5 R不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-1 12:37 , Processed in 1.109375 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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