EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
4 k: N; A) }& i% h% pPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" n9 W$ l; l" J, U+ g, Q  z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 a0 n! m, s  W! U) c4 q这里有相应的模拟器源码,就当送给大侠了~~) S1 j& D3 H, {- i# P" q( r
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 2 @* e' a' t" [9 i; d3 J) g  k; z3 \# V
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 k* b# R6 @# q5 W( g
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' O6 X$ n  C9 x: ^这里有相应的模拟器源码,就当送给大侠 ...

/ Q! A$ f# {# V+ }0 ^聲音部分(Audoi Process Unit = APU):7 q$ `9 l$ \5 N  S; A
.\NES\APU.cpp
% r/ L0 p1 A( ]9 l* k2 X4 Z.\NES\APU.h" U# Z5 W3 r) j% _" r( W* a

+ [1 i0 k+ f9 v0 w+ p, V' N! J4 {4 b
影像處理部份(Picture Processing Unit = PPU):
8 B6 m( ^4 j. T7 a+ M.\NES\PPU.cpp5 o" s. I4 J4 S  v3 j
.\NES\PPU.h
0 i  i& R5 V- \# ?2 c" P
" ?6 v. |6 X$ b: _$ Z5 o如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  ?* m) V  |. t  \$ Z
(由于很多专用术语和算法机理都不明白,所以看不大懂……), x: E$ M$ n/ l, W# u& v+ f
//////////////////////////////////////////////////////////////////////////
. S0 M6 ~- F: _$ x9 l6 U7 x//                                                                      //% E/ e  Q: l# o8 @2 ?5 l$ l
//      NES APU core                                                    //
0 W0 i' y* j( W+ ?/ g" w# ^; @8 z//                                                           Norix      //
2 Q6 S% d3 A* y//                                               written     2002/06/27 //
9 F* [+ c# m$ n/ z& q! e//                                               last modify ----/--/-- //
' F* ^; ^' j: U# ^; J$ F) A//////////////////////////////////////////////////////////////////////////
' E4 n- J9 O2 @2 h0 D2 i, z- s% Q% z#include "DebugOut.h"
: s7 g( p0 Q8 A* U6 H& T#include "App.h"
: n4 F" d  q  z4 [! t#include "Config.h"
" L$ p' M+ w/ Q% b) Q- U" E
2 a& T2 z4 u6 x3 x: N8 j* U#include "nes.h"
: y+ B) q4 E" G! T' Q1 A* Y( J. l6 ?#include "mmu.h"
# z' Y+ X/ K) f: ]. y. u#include "cpu.h"
# V8 D* m7 j3 U; _#include "ppu.h"
9 ?/ ~  i3 c# p/ h#include "rom.h"" O1 B! y* x; l
#include "apu.h"& v; W* D' i" q

6 s: {$ ?7 y, f7 u// Volume adjust' V" m/ x! L4 J! K7 _8 s
// Internal sounds5 {$ Y0 I/ H8 i" }# i( F% R
#define        RECTANGLE_VOL        (0x0F0)# q( }$ D; V: a  S" {
#define        TRIANGLE_VOL        (0x130)  i9 U' r+ O$ ]0 g
#define        NOISE_VOL        (0x0C0), X/ G% Y" j; q4 {! A' A
#define        DPCM_VOL        (0x0F0)
: w0 ^- m9 t4 c4 a// Extra sounds  h7 J8 z. }' I: ^5 S8 Q
#define        VRC6_VOL        (0x0F0)
& i* W2 ^- b2 U  G( u#define        VRC7_VOL        (0x130)0 I& P) `1 }2 y# ^, \% i7 P
#define        FDS_VOL                (0x0F0)
2 G% G4 X4 j) R  G  `+ ~#define        MMC5_VOL        (0x0F0)# x) Q6 H- m) I1 g  _  @* Z
#define        N106_VOL        (0x088)
/ v9 X5 f8 o  ]3 P: M1 u$ O#define        FME7_VOL        (0x130)
% a& x6 h! i' N: z) Y3 ^9 N& M0 Y" F- ]  C1 _( ?
APU::APU( NES* parent )! K4 J5 [  \4 v0 Z2 a9 g: S
{& F1 K6 q! G& u. _+ {
        exsound_select = 0;* C( U3 `9 m$ V1 E/ @; b

+ |7 S( G6 `) n4 G$ G        nes = parent;/ ^) U! O; A. ~
        internal.SetParent( parent );  W/ @6 N2 F( e

& {4 M, V6 c0 @. X. ?# d        last_data = last_diff = 0;5 v; O9 H1 l6 k/ B% S3 I8 y

* r5 @8 b6 s4 _% G$ `        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
% \+ `, G  t3 Y4 M3 T
. h' f# a: o; c5 Q: L  R; L. U8 |        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
+ O! H* M; S3 G3 Y5 z9 I3 G        ZEROMEMORY( &queue, sizeof(queue) );( \, p8 X! D/ x0 v* q! j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 g* I& b6 p2 C) ?- F! a. v
0 o- P0 h$ }+ B2 D8 o
        for( INT i = 0; i < 16; i++ ) {
( }8 b) g+ y: m& E: J% f" C& ~; W                m_bMute = TRUE;
* O( e  \. r) [* L; J% X+ K. y+ [        }
% Y* m  n! C& M/ k}
4 s: D& b5 ~, S1 P9 f) ^0 q; p% M/ U
2 V0 S0 M( {2 o: m7 b0 N  h. tAPU::~APU()
/ [3 v  |: M4 R{  R& v! ~. f; i  S4 B# o
}$ F3 }  v; _8 y5 ]3 c+ N

" v/ y2 z- b+ m  J2 Bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
2 ~8 [  s% o5 Z, ?+ Z2 M5 B{# C/ S+ J( o! [& W4 F
        queue.data[queue.wrptr].time = writetime;6 g% A) o' f, B3 }$ E- n. W
        queue.data[queue.wrptr].addr = addr;
. m! s& B" _/ B' s        queue.data[queue.wrptr].data = data;
0 A8 ]( I) ^* F8 G' j( O% f- r( t        queue.wrptr++;
( H' b* ?2 E6 \8 ^        queue.wrptr&=QUEUE_LENGTH-1;' C' c) B8 V3 t/ C- C) M
        if( queue.wrptr == queue.rdptr ) {/ n$ a" y. _, n+ C5 S
                DEBUGOUT( "queue overflow.\n" );
0 R* B  l' q( t9 S2 ]% v  ~! V        }
8 V: A' Q+ G1 V! ^; p- M1 J: K}
. G0 H; Z! I3 M, }
) n& K9 [1 d3 o; r# h1 Z$ t0 q$ |% |BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )# M0 I0 L; Z/ G# b, J9 m' |# K
{
" U" y6 Z. i) s+ i- S9 u/ _        if( queue.wrptr == queue.rdptr ) {
# i$ n% i( W" ~( T4 d6 @                return        FALSE;+ \& C' U( U+ q: j
        }+ R& q+ R0 R$ N% ]
        if( queue.data[queue.rdptr].time <= writetime ) {* |, V! Z$ J, u+ q) i1 q
                ret = queue.data[queue.rdptr];! U0 N' S5 ^- m: x& d7 ^
                queue.rdptr++;
% Z' R4 K. c& T5 z2 Q                queue.rdptr&=QUEUE_LENGTH-1;
- B3 R' J7 a& m                return        TRUE;& o( v( t7 i4 [8 _& f3 k
        }+ F% Y! v/ Y) M" `7 @3 J
        return        FALSE;
( Y. k. k. a# u9 C" `+ G' r4 F( i}
. p5 f6 p1 r$ p: A$ O  q2 J+ [4 T( C5 L0 w- t! \9 l9 B
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ r7 g* F/ l, O- \8 }% s* r{; F- B; G4 Y1 K% n5 K9 m+ q7 K& w
        exqueue.data[exqueue.wrptr].time = writetime;% u. F5 k; o" O5 z
        exqueue.data[exqueue.wrptr].addr = addr;
( q5 c$ y! i. [0 t8 ]) [- A        exqueue.data[exqueue.wrptr].data = data;5 L0 e- `% V# G
        exqueue.wrptr++;4 f+ R* w; K! S* ?' t; {& D, O
        exqueue.wrptr&=QUEUE_LENGTH-1;
9 Z& a. t5 E; C1 h2 z5 ]' [        if( exqueue.wrptr == exqueue.rdptr ) {3 }  A% [0 o/ W+ o' A
                DEBUGOUT( "exqueue overflow.\n" );
( `- d- D1 G4 Q0 z        }
) t# d- s4 J) U- i! I8 ?1 k}7 z% a# S( ^7 S
3 j5 p! n) V% x
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )2 [: I6 X. W+ `2 K
{
2 p% w9 C& m$ r! w, R+ m        if( exqueue.wrptr == exqueue.rdptr ) {- I1 A6 H3 ^5 l& `3 d! h, K/ J
                return        FALSE;- v; Q4 C  m, l. M- \- e0 b
        }
' r3 k! p1 c, B9 W8 O# i% s: D$ {7 t+ z        if( exqueue.data[exqueue.rdptr].time <= writetime ) {( S7 ?5 d# B# h  l
                ret = exqueue.data[exqueue.rdptr];9 ?8 ]* s  M- K! u2 ^
                exqueue.rdptr++;' q2 F# m( g# w, f2 {
                exqueue.rdptr&=QUEUE_LENGTH-1;- J' _6 _# ]9 A9 O
                return        TRUE;# D9 q  Q3 f- s, c; M; G
        }( r  I- j% R' o) i  Q1 y1 ~; v6 M
        return        FALSE;
0 q1 a( n/ M; p: p: j# B0 [. n}
* U, Z7 ^0 m% _: ^1 R
3 Z/ L" v8 R7 E) M3 t' P' S* `void        APU::QueueClear()* C- ]& a+ e" Q% ]. s
{
& P; ~0 \6 m' k& L  E1 V. B        ZEROMEMORY( &queue, sizeof(queue) );& Q% L( \; m* U
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; i2 D1 K1 N7 P3 A}% I- X8 G7 F6 {; I/ |+ C
1 i4 w9 e( A" G/ R* g
void        APU::QueueFlush()  C0 n; Q' _9 g# n- i
{: T' A8 v; P& s: e7 Z
        while( queue.wrptr != queue.rdptr ) {
7 n1 K9 N  l* q' g                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 ?  s0 c6 [, U2 T( }
                queue.rdptr++;: J3 K5 v% F) z0 H# [5 Y" T0 ?
                queue.rdptr&=QUEUE_LENGTH-1;
0 Y4 \$ D- }  s* u1 ?6 A! J        }
# B& a5 v7 H7 {* t( B9 ^' {* m3 l
- [' I! m% @- E        while( exqueue.wrptr != exqueue.rdptr ) {
" r1 W, {) Z* d& h( u/ X+ h+ W                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
6 B9 C8 K5 z/ l                exqueue.rdptr++;
' ~9 M8 Z5 O$ c6 Y9 ?! w& s1 r! k$ j                exqueue.rdptr&=QUEUE_LENGTH-1;
) S7 g( f( \, ?1 b* z& J        }% U  w9 u# O+ p! q- U( {/ N
}' _6 {$ k+ ^% M# ^

! H1 i7 m# s- P3 h) T8 \9 ?void        APU::SoundSetup()
! r- c) U) m4 @& M; a" `{
# K2 c4 y( a3 r5 b        FLOAT        fClock = nes->nescfg->CpuClock;
+ |0 \$ K$ `9 v8 t        INT        nRate = (INT)Config.sound.nRate;0 n6 H  p- j, a& ?
        internal.Setup( fClock, nRate );# X7 z1 a3 P5 p' A- |7 y
        vrc6.Setup( fClock, nRate );7 z7 e/ z5 Z: k% {# q0 j' O0 @  V  j) W& ^
        vrc7.Setup( fClock, nRate );: k; F, H, S+ {: Y3 [0 W
        mmc5.Setup( fClock, nRate );
/ e/ |3 m8 U! f9 s        fds.Setup ( fClock, nRate );+ z7 C, V0 i/ L, z
        n106.Setup( fClock, nRate );& [7 r& e" }+ O# g  V9 p2 h8 t/ \  b
        fme7.Setup( fClock, nRate );
1 D9 a0 \8 |. k}% `7 M: Q5 S% V0 T1 f

) d# F8 @3 u: m7 ?# ]- uvoid        APU::Reset()" C: V* j8 n% q# j: ^( |
{
) P- Y& \& Z7 T+ D4 [& Y& _# F        ZEROMEMORY( &queue, sizeof(queue) );
* i7 d* N+ c6 l) V0 ^" o        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  a0 `5 |0 }  m2 K, e
) w4 t( z5 V7 A" U- J        elapsed_time = 0;/ \  z) W/ x0 c% e4 S

5 F$ U+ E: l- G" U- O; a& Y1 V        FLOAT        fClock = nes->nescfg->CpuClock;! E: p0 K$ R/ v' }" J, Z
        INT        nRate = (INT)Config.sound.nRate;9 E: u; {/ ^4 {6 ~
        internal.Reset( fClock, nRate );
, t% q) |; _. q$ U2 P        vrc6.Reset( fClock, nRate );0 y0 L* s; d. W2 h# W
        vrc7.Reset( fClock, nRate );  l) X! L# S5 I( @& g0 g. x! @
        mmc5.Reset( fClock, nRate );9 n7 R* k6 m# a; y7 g
        fds.Reset ( fClock, nRate );8 y/ \6 M; u: J$ e
        n106.Reset( fClock, nRate );
6 p0 Y! c( k5 I        fme7.Reset( fClock, nRate );
) g; C6 Z3 \' v& A! \. ]
- Q" A4 n$ g) l5 J( ]        SoundSetup();' }/ W0 F1 X% V
}
0 \  h1 B4 `  L) P0 I: H6 c$ `3 s8 L. F, K% J
void        APU::SelectExSound( BYTE data ), |: ^1 s2 j$ i" ]* B3 Y
{
& ?$ S. l* w8 a7 Z5 R        exsound_select = data;
. K/ ~& ~7 C: `}' e. l; h5 i$ p" ?' W+ O5 }

1 P% ^  B% v3 I4 D/ I* uBYTE        APU::Read( WORD addr )5 Y3 E9 t: Y' |9 p- L/ N0 `/ Y
{
- d6 f7 t/ b, ?& Z        return        internal.SyncRead( addr );
) T+ c- F- Y& K$ ^  }! f6 b; W}
! ^' x' G/ v8 ]
) j7 a& o: M, I7 x# ^! d) Avoid        APU::Write( WORD addr, BYTE data )1 y/ B0 h% I% j! N3 f8 E
{
5 ?* ~% D1 J* T& K) A        // $4018偼VirtuaNES屌桳億乕僩
* q+ n9 D2 ]7 S/ {7 q        if( addr >= 0x4000 && addr <= 0x401F ) {
1 v* Q, e& L$ X1 m$ @                internal.SyncWrite( addr, data );
2 G' x% j9 D2 r( s                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 {. h$ D- ~  ?* }9 K* E        }; ?' F, e! S3 s4 d+ {0 n6 O
}7 L, p5 ?' d  ~. D; r
/ e( X3 `2 |* F/ k( P! R- j
BYTE        APU::ExRead( WORD addr )4 W" I- `1 X/ ~5 c
{# Y/ e% f4 P. V! }, j8 c
BYTE        data = 0;% x$ O* M' p7 ^- D6 `

6 X0 o9 o1 g! [8 d        if( exsound_select & 0x10 ) {& K7 u) L5 q( Y; R0 M; m6 H
                if( addr == 0x4800 ) {
8 [% J7 y' t; D; b- F                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 U. Z0 N9 J% }' U4 X! g0 Y                }% j0 u8 B6 t+ I' S
        }0 p* D' e# S+ E- v0 i4 ~/ e. n
        if( exsound_select & 0x04 ) {  |2 U% k/ t: B: y- q: F9 i2 U
                if( addr >= 0x4040 && addr < 0x4100 ) {
$ |- A; I0 m# I                        data = fds.SyncRead( addr );6 E% F. D7 c5 R9 P0 D! ]5 j
                }
8 q2 a7 Z1 w6 X7 Y; v        }, I' j' k: D/ `% \7 O. s, @* d
        if( exsound_select & 0x08 ) {
9 H8 g# _; Z. c/ @5 C                if( addr >= 0x5000 && addr <= 0x5015 ) {: {# Z3 J3 D- v7 C
                        data = mmc5.SyncRead( addr );
# i4 x  @* I. x: ~) ?. z                }: v& U" Z* y& ^: ?- L6 t' r- m2 Y
        }
: }/ I6 ?9 e+ G' t$ d( d' ]. f8 T# D- K( J5 x
        return        data;
) a. |' O( S5 ?- l' H2 [( I7 W}) t5 y' v6 t* ]. D: {& V

0 J8 c, l. V! u& W3 v0 z. U1 @void        APU::ExWrite( WORD addr, BYTE data )
  t" L/ b4 U" c3 d8 [{. f  L) G6 W7 I5 O0 x  }, E5 m, Y
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 i, J1 O- B- a8 @; z4 x) I0 b. W$ r/ J8 C
        if( exsound_select & 0x04 ) {. |8 X. u0 ~5 k. ^
                if( addr >= 0x4040 && addr < 0x4100 ) {4 [5 [% K9 V; s' w- z1 J
                        fds.SyncWrite( addr, data );
: \6 x9 [3 t9 F) l$ [: T5 y. k                }) ?( ?$ k* s- X) q' @3 M- S
        }
' w  e$ |: f; Z- z7 e
  `* I& W; ?: d7 P* d+ @        if( exsound_select & 0x08 ) {
4 Z1 V8 u; D$ `; ^. |1 t                if( addr >= 0x5000 && addr <= 0x5015 ) {' {) C5 p- |5 W7 p
                        mmc5.SyncWrite( addr, data );
- Q' W. k5 n! D: l# J( ~7 m                }  I# M: T! k( n# @8 Q- `' U& G
        }- ^. g+ E) J9 a, |
}
: x; F! T, m) y& P' u* l9 `5 n/ Y- w; X
void        APU::Sync()
. S* i! G( a# h0 g& a( p{
" ~& T# M) g7 S3 O! u3 m% `* x}4 X; ]3 h9 h+ k6 T  g" u+ Z
6 \+ F) R/ A) N$ Q' D4 I
void        APU::SyncDPCM( INT cycles )" O2 h! L7 x3 l
{6 z* [$ f6 _/ `1 b
        internal.Sync( cycles );2 [  V1 ], c' B8 i+ o( x$ P
  ~1 `, S; E" H
        if( exsound_select & 0x04 ) {
; }: n! r7 a6 t1 o                fds.Sync( cycles );
; d# {9 r! S2 `7 V9 S7 o        }! i" l6 ^7 c2 V8 d) i
        if( exsound_select & 0x08 ) {2 ^3 y/ O1 T( a2 `/ e
                mmc5.Sync( cycles );
2 w/ m6 U- X  ^) F3 u        }
9 `. p2 V& H8 N: [4 g5 U}3 y& h% ^( j+ b6 L8 ^) w% I; `

% p* `8 U0 ~8 S2 o6 t9 {* Y/ ]void        APU::WriteProcess( WORD addr, BYTE data )
+ c4 e7 |; u  m0 |) M{
9 x) l' A0 D8 u  s! t# X! _        // $4018偼VirtuaNES屌桳億乕僩
+ W# i* C7 _+ t- M2 T        if( addr >= 0x4000 && addr <= 0x401F ) {8 D, B4 e) f/ `
                internal.Write( addr, data );
, x- Z# ^9 T& Q( e8 y: @        }
- e0 y2 F2 [4 c}3 Z: j) a3 _& Z! ~: T

5 ?" A4 K; c/ |# v1 v2 yvoid        APU::WriteExProcess( WORD addr, BYTE data )6 }" W6 y4 a7 c% P. C+ S
{5 O' v  L+ y/ x# A" z
        if( exsound_select & 0x01 ) {' B+ [2 l8 z9 p9 s2 g5 E
                vrc6.Write( addr, data );3 M. q; e) ?. Z6 T* E4 L
        }
' o& y7 L5 i1 i5 o        if( exsound_select & 0x02 ) {
0 Z  {% E0 K6 u! S                vrc7.Write( addr, data );( t  g2 j9 j9 [' x! A0 a3 Y' w
        }' o& h- ?/ |6 S3 ]. |5 L0 ~6 \
        if( exsound_select & 0x04 ) {& _) _8 ?* m) O6 r4 e( U
                fds.Write( addr, data );2 E' ^0 S2 Y& Y) W" e9 W- @% L
        }
" w6 ~" x* x9 M; F3 S& D        if( exsound_select & 0x08 ) {
0 H9 y: J1 A. c/ `                mmc5.Write( addr, data );
6 X3 N5 P' H9 l& j. ^7 |3 ?2 S6 T        }9 n. Y1 L! q* i  a# y7 T
        if( exsound_select & 0x10 ) {
; ?7 w0 p! F& a9 L6 G                if( addr == 0x0000 ) {
4 c5 F! j7 l( N# q                        BYTE        dummy = n106.Read( addr );7 ]$ X" V: c# I) D2 d
                } else {
, p, `% s1 m  d- u6 s5 d% t; X                        n106.Write( addr, data );
) x- `) f1 Y4 e% e8 F                }
( z9 E4 h& Y$ O$ O5 Z/ }        }, j) R( U$ V6 s& N( [0 \* A' _
        if( exsound_select & 0x20 ) {1 L4 y, {  R9 R  ~2 r
                fme7.Write( addr, data );
; L2 E/ _7 _" H( w- O        }( G5 j. \) K) r4 _; o, `( C
}( t% N) k2 h0 O, R1 w) h
' ~" v6 W4 `" k
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
' a, _$ {: T% J2 k( h, N{1 X. n0 g, x4 L! q
INT        nBits = Config.sound.nBits;& u! W) `8 D+ y+ A) X* Q1 v
DWORD        dwLength = dwSize / (nBits/8);: p' \5 h- R! k! U; L  U. V
INT        output;+ p) F* f( d; ?% l' U
QUEUEDATA q;1 r& m$ d  o  }! R1 N
DWORD        writetime;
- d9 O' Q4 |. A& B7 A+ L8 s: l" H* \0 P
LPSHORT        pSoundBuf = m_SoundBuffer;: h8 g4 ?% J( H- T8 f8 j+ O6 \
INT        nCcount = 0;
, L, e, @; Y. ~  e3 n4 `0 u0 z1 V/ v/ {% E
INT        nFilterType = Config.sound.nFilterType;
1 h# a% W' V1 y6 N1 R: @; g0 z
$ E  e8 k- w5 }  j: b; h+ E6 H        if( !Config.sound.bEnable ) {
& u# S$ C; k& p5 v$ q" C* r                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );% |; U, h; [, m! K4 {
                return;, i) V% O# e4 E6 P
        }
5 M- f/ B6 ~6 o( B4 e
( {8 J/ \; k: g3 d% J5 q+ ?2 W        // Volume setup, ]; t' P. v$ B* q7 L1 S6 ~
        //  0:Master, W* @4 Q) M2 ?; j
        //  1:Rectangle 18 q0 J4 ?, J* S$ l' g9 D
        //  2:Rectangle 28 O$ t6 j2 n! x7 T3 a) V
        //  3:Triangle! u2 @2 S; f& {  t+ x% J2 H. G- v
        //  4:Noise* O; y2 m) t! V, z4 s7 |: w$ M
        //  5:DPCM7 I; u! v# v: |. C1 G( H5 a, A
        //  6:VRC6
7 t' ]1 D- @! J4 _5 O  ]        //  7:VRC78 m6 E( o+ l+ l3 a" d
        //  8:FDS: a5 ]  G' f* b1 M# V* U4 B
        //  9:MMC5
: u2 U5 @! w' x' R        // 10:N106
  j$ r: \+ O+ b/ L, d7 k' I& a& |        // 11:FME7' f2 Z- T) }" d
        INT        vol[24];' F/ K. D1 u6 F! s1 u3 O
        BOOL*        bMute = m_bMute;
0 _, \5 P( \: w, I% `: M        SHORT*        nVolume = Config.sound.nVolume;
, Q1 N6 W- O8 f9 }) }# r) ~' o5 [* `/ ^; |# ]
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;/ V& n7 q& C) R2 G: ]0 Y: s  R
* V( w: ^3 J! F2 h& j9 t9 N
        // Internal
& I  s1 y$ _) t/ j1 [        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ e/ _2 P- D3 d! Y- s
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
3 r: r7 `: w* P: c        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
0 U; Z$ u) Z7 s        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
- n& B, }+ {+ _+ U. l        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ l* }, l4 h8 K1 a3 B7 `
0 S) {* M" Q  g7 I. s9 C
        // VRC6
$ ?$ I3 @4 Q! t        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 q2 [: D* `" V        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ u! K. d& p. _1 n, ]        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 o+ t5 ^/ ^4 s- e( Y9 C, ]5 z9 e  c2 G
0 K- m( C2 j. I; i( T# J+ Z        // VRC7
/ W* ]; \$ f! d( u' x        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
" A- ?$ E# V7 u" k
4 A; Z( l( E! u4 Y4 H9 r        // FDS3 V( r0 M$ z; V) F
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 ?) N" X: V  r$ Z9 t4 {
( V* M2 u! p+ o, M
        // MMC5! C) k8 c$ N2 T3 o
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ R( P! G0 t2 x4 s- `  [* S
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 u/ [! m; N2 g7 ^+ F
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; Q+ f/ d4 V/ \/ {
& c3 d1 I! n# L& w/ j- c        // N1064 [% f9 c9 I0 A8 `' e
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ y- n; W4 b. G6 A: K, r
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 b2 K7 u- Z/ [" q
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ S) ~* |' N& l$ t
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) Z, r% Z4 {; b4 z8 g        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 P- n* ?  k4 A5 R) F        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ L! e' V5 {: ^7 g- s/ J+ }        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 N( D% `* i" ]3 E0 T        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 ?: f1 e% c2 ^
  @1 K& u& o3 r- Y
        // FME72 G% X/ S$ b/ ?5 W. b- A6 h; q$ M; d
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; i: T6 M" R5 i, v2 ~8 J        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! Z, ~. q" w# s* ^4 t! T% R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 c* m( X' {% `1 b' p7 a7 P5 I
( G4 Q! ^. y# k7 m( g2 L& N//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' U& c3 D4 e: I# F        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. w* j" k9 O8 r# F
+ n' S9 {" T* B        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ e' E3 K) Q! r3 ]. d, D! A        if( elapsed_time > nes->cpu->GetTotalCycles() ) {8 X# @3 r. x0 ?. Z  [0 o
                QueueFlush();# `1 ]/ Q" s% g7 f1 @8 E
        }$ B8 F% N# ~' f6 R6 u! ~5 t8 p# W# U
7 g: r1 U5 Z" n; V6 W
        while( dwLength-- ) {
( m6 L9 `1 W+ Q' N/ b. ^                writetime = (DWORD)elapsed_time;
/ {+ A) i' r% K( k) Q) m, Y; j% ?# o: Y( C
                while( GetQueue( writetime, q ) ) {' B8 u1 J# n/ Y' _1 G
                        WriteProcess( q.addr, q.data );
5 V  G% u* B0 N  ]" G                }7 V! b" J- s% b- y) O) C2 J* F

0 f+ a5 X' F3 }! d. z, e) S0 c                while( GetExQueue( writetime, q ) ) {
$ y& e) W* B/ s6 }6 a9 G3 D                        WriteExProcess( q.addr, q.data );
5 C3 v) A0 T: C: G3 }                }( W4 H- ^9 W. X5 u  S2 z

' z0 x, i0 f3 G" }                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 E2 o6 J$ p. S: f( E/ A
                output = 0;
5 J( G& C' X  p) y$ E% k                output += internal.Process( 0 )*vol[0];
: O" e4 ^2 ~* s- v2 A9 y9 F                output += internal.Process( 1 )*vol[1];
' l3 F" z2 Y  }3 p" ]2 q5 N                output += internal.Process( 2 )*vol[2];% E* \* N- I) e, ~0 i- N
                output += internal.Process( 3 )*vol[3];8 e* Q& s/ _: ~* ~* ]2 d
                output += internal.Process( 4 )*vol[4];6 K. |0 P/ N! D" _- h7 [1 H
, S  S: W7 W' o2 E/ q$ x: D
                if( exsound_select & 0x01 ) {( o/ y: u' D  B3 J) H
                        output += vrc6.Process( 0 )*vol[5];
% X+ l1 g  t) a; {! _( n                        output += vrc6.Process( 1 )*vol[6];( [' t6 Y6 w9 l- N3 w0 E/ Q# v! D
                        output += vrc6.Process( 2 )*vol[7];
3 [6 w/ F- F- f3 u( l! J% [1 w                }
; s4 q. R+ [8 C2 D, \) Y6 I. r                if( exsound_select & 0x02 ) {
0 b, ^6 b( E) W% y8 R                        output += vrc7.Process( 0 )*vol[8];
/ f: n. B& B( \* t                }2 |1 l2 B+ Q  P+ D: M$ S+ B
                if( exsound_select & 0x04 ) {+ I: }9 S9 _$ ~" h4 H, _$ g, j
                        output += fds.Process( 0 )*vol[9];& W+ f5 A( b0 Q( a3 _7 e4 v
                }, v8 r; ^. E  F) d- G- r1 Q5 f
                if( exsound_select & 0x08 ) {
2 e6 @  ?) j2 M& f/ ?                        output += mmc5.Process( 0 )*vol[10];9 D9 H* N* U8 t( w& c  g' d
                        output += mmc5.Process( 1 )*vol[11];/ O! I- Q3 ?7 g$ v0 g
                        output += mmc5.Process( 2 )*vol[12];: r6 h# p! L& O" m5 ~9 h0 p3 s# ^* A( Q
                }
' z. J- J" R: k# e, g9 K  V                if( exsound_select & 0x10 ) {
" D6 @; ^- V$ S# |8 ^6 K& `4 S                        output += n106.Process( 0 )*vol[13];
! t: P% |3 R3 u+ Z' j                        output += n106.Process( 1 )*vol[14];' j0 a& ~2 K- t/ Y6 _! K$ x
                        output += n106.Process( 2 )*vol[15];: N+ o0 Q; p( Q. d2 V
                        output += n106.Process( 3 )*vol[16];$ i: I1 y6 R1 o+ Q2 k4 n: v' I4 e0 P
                        output += n106.Process( 4 )*vol[17];( ]: A7 K* j3 |) k4 a( m! S
                        output += n106.Process( 5 )*vol[18];
( f# d: B( G; u% G/ k                        output += n106.Process( 6 )*vol[19];( ]3 w, k* \' f8 ^. }" W
                        output += n106.Process( 7 )*vol[20];& p" W4 f1 `2 b$ M5 U  J; t, p
                }* _- n$ _0 ~3 `
                if( exsound_select & 0x20 ) {
6 ^$ z! t8 K5 l% T: r1 G                        fme7.Process( 3 );        // Envelope & Noise/ l, l5 K. d- k2 h
                        output += fme7.Process( 0 )*vol[21];
/ ?1 d  Z6 ?) e8 I0 [& Q4 T9 Z' L' N                        output += fme7.Process( 1 )*vol[22];
2 m2 n' m; H% v5 L2 q$ q                        output += fme7.Process( 2 )*vol[23];& g% \1 k+ P  `' Z9 m
                }
4 J0 J2 c. s5 e1 y0 O% {  B& v$ J' }& U$ `6 B
                output >>= 8;
" H  v! }, ]: Q4 h% D, r4 @* [8 }. z: P3 ~% {. o5 e
                if( nFilterType == 1 ) {
4 _. I: q! @! g. i( p  s9 c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
+ i" m! x+ h4 e; \3 v7 ^                        output = (lowpass_filter[0]+output)/2;- ^# p2 x- n6 l7 P1 O
                        lowpass_filter[0] = output;% g! R/ t, Q7 a+ W' O# c3 y8 g6 Z
                } else if( nFilterType == 2 ) {5 F3 b* ?( E" ]  U0 S/ }
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)! @: I/ L4 T5 ?
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% F# @- ^0 _' w& V' O9 Z; F0 E# U0 T
                        lowpass_filter[1] = lowpass_filter[0];
  P2 T) g+ i' K) j4 e                        lowpass_filter[0] = output;! E  I2 E' A. Q+ C% E) |* k
                } else if( nFilterType == 3 ) {2 D+ d" ?! N4 o0 H
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)) h# ~6 }! c# M2 I, N
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;# `& l$ t1 i7 k% k# Z( j$ u% u
                        lowpass_filter[2] = lowpass_filter[1];& s" b8 Z; c$ B% O7 x% J
                        lowpass_filter[1] = lowpass_filter[0];/ ?4 P" o/ D+ Y5 [1 n% C/ {' v
                        lowpass_filter[0] = output;1 \8 b- [- G& Q! C8 q
                } else if( nFilterType == 4 ) {
, c/ g8 l7 u8 v/ R# {, a! f" _                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- \4 w; D7 W/ i- v
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ T$ l4 ^( G2 c6 f" x                        lowpass_filter[1] = lowpass_filter[0];3 e: h" p' [4 G! x, Y- B
                        lowpass_filter[0] = output;* ]# a: G- J3 P) k! S. ~0 t7 l
                }
+ E4 Z! H2 s  Q% D+ ^) u2 O
) X& U" o- l; [, t5 N: A  T#if        0% ]' u3 u: ], z6 m% I, K; |0 c/ u" w
                // DC惉暘偺僇僢僩! R4 B" ^, L! x  v, ~2 J
                {" `( X4 I+ j2 ^: m6 r9 `
                static double ave = 0.0, max=0.0, min=0.0;  g0 \: M! X9 o; q* {* D# o6 N
                double delta;
) B4 b* t; x; A0 g0 [9 e" h4 \/ A) U; s                delta = (max-min)/32768.0;
; \, U6 F) Y; b& F) @) B& ?% t" P                max -= delta;
! B8 D& O" `) F/ t                min += delta;+ b5 s. W& i1 B2 L0 b1 Q2 E
                if( output > max ) max = output;4 G. I& U6 A' a1 @0 E
                if( output < min ) min = output;
& ]: D  R$ S; j6 n( f                ave -= ave/1024.0;% H$ K* v7 l! [6 y6 X8 T, j
                ave += (max+min)/2048.0;
* }7 `, ?9 U9 b  ~; h- Z# S8 F                output -= (INT)ave;
1 j  u* G$ {8 L/ ?- N( P1 c                }
$ \  j# A  z! C3 D! G3 [& q- J& _#endif
$ m% l- X- Q' M. S% s6 O6 n#if        1" a$ i$ t6 J! f1 T& w: H: F
                // DC惉暘偺僇僢僩(HPF TEST)
- h% Z4 Q6 v  k( f2 t9 w                {" w( p& v4 C7 C; K" ^) f  X
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 O( }7 z& H/ r9 {3 ]                static        double        cutofftemp = (2.0*3.141592653579*40.0);
. P6 Q" Z. d% v, C2 h                double        cutoff = cutofftemp/(double)Config.sound.nRate;
; S' w5 s$ P- f/ f( T- F                static        double        tmp = 0.0;
* ]  a% T6 b. s( Q. i  n* y/ ^                double        in, out;
- U" O) _# S7 L: I1 `
, ~$ I+ J0 a; t- n6 @; m; V# M                in = (double)output;4 V% k6 o) @* z" i5 ~; G# x
                out = (in - tmp);
6 E+ e9 k+ P1 W7 P% ~# R0 C) ]                tmp = tmp + cutoff * out;$ `2 R% w, Z- {% u3 y. _

$ n( n& o9 o1 |- c" D1 {  i                output = (INT)out;/ Y  N6 q1 M. P9 p0 K
                }: V( Q9 h/ N& x( r0 Y! {. D
#endif
! C7 S9 E( @0 f+ S: G#if        0  p5 y7 w1 t. ?& v$ F( C
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 g( K) j% j0 F# q6 S9 M
                {& R7 Y# g/ F+ V7 e, f
                INT        diff = abs(output-last_data);. x/ T8 Q7 ?# r% T4 d
                if( diff > 0x4000 ) {
- W% O7 G5 |& \" T- T& K                        output /= 4;
' }: s2 D& ^) U- {# h                } else
. X% z" [! _" `& W, Q* Z8 @* _5 \                if( diff > 0x3000 ) {
1 N& X0 O% K! u' {0 B5 V                        output /= 3;4 Q( m, a- C. ]' p3 x! o7 P
                } else
5 k0 D6 u& [; I2 d' S1 f( d                if( diff > 0x2000 ) {8 z4 e- ^$ Z4 y$ K) h  @6 O
                        output /= 2;
; U4 _# k: |, h; B/ i  G                }
2 O$ B2 ]" G: ], t+ X$ x2 x                last_data = output;
9 r: W0 K7 M; S/ F' H4 @                }8 S5 b: c/ o6 J; j' ?
#endif5 W+ _6 ^0 `" N6 _0 ^* f
                // Limit
/ ?, _  G  K2 r# f; A1 i; P                if( output > 0x7FFF ) {1 ^# ?! S; i, |) o
                        output = 0x7FFF;
* i8 {+ B7 p6 h                } else if( output < -0x8000 ) {/ v" q# z1 `, U+ Z2 i  }
                        output = -0x8000;1 p9 M; B+ n+ y5 A0 W- f
                }. @) W$ l' b3 t4 o" L9 v
# v0 {1 e. w# m- ], g0 Q
                if( nBits != 8 ) {
( a. a4 ]  p' W2 g. r                        *(SHORT*)lpBuffer = (SHORT)output;
0 ~+ t: J' e! v) w                        lpBuffer += sizeof(SHORT);
/ @: T* P4 a6 {1 ~                } else {$ j1 N" Y; ?6 V( Q9 j( k6 f: q
                        *lpBuffer++ = (output>>8)^0x80;- [& E) h& n) D2 f7 @# |
                }! U' y" S* e* F! y6 a1 }& ~
- ]( K3 C6 [3 b4 {/ G; R
                if( nCcount < 0x0100 ). T2 [& ?9 C7 K4 f
                        pSoundBuf[nCcount++] = (SHORT)output;& p0 v9 G$ _1 p+ ?

$ A  y9 _! Y# O# @//                elapsedtime += cycle_rate;
* Y0 i; ?/ H0 v6 o) {4 k, q( r                elapsed_time += cycle_rate;+ e$ R8 \' v2 P9 n, q) Q8 G
        }" L* h" y  `" w/ W1 J
: R# E. V$ z" E' ^. N7 l5 v
#if        1
% ?" C4 W8 T# U. n( w% m, {        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
2 ^2 w% ^+ n6 N  [+ q$ u% T                elapsed_time = nes->cpu->GetTotalCycles();+ {: z1 C" ^! M5 t- O
        }
6 f  K6 B2 K# q7 ^3 b- x! U        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {9 j: I  s" E9 a" u( l: T
                elapsed_time = nes->cpu->GetTotalCycles();
9 I' N% @" j+ v3 r& e8 d        }( x4 ~  p  U8 D' i$ H& {
#else6 [9 X& `" V9 Y5 f7 i
        elapsed_time = nes->cpu->GetTotalCycles();
, ]) f, `% p0 m+ B/ W" \#endif* s. o  L2 U2 N% j
}
; E$ `+ M* q6 H2 R" _$ i$ j" V; Q  m  |
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)# o# o( Y: R. y" p8 I
INT        APU::GetChannelFrequency( INT no )
8 T/ x' B+ C# @{
0 Z: d( y2 E7 Q4 J& F        if( !m_bMute[0] )
8 h  }: r; W$ I; ?5 C                return        0;
1 K. D- U8 \# I  Y' M3 V# R. n+ _5 |4 W9 \' g; X4 \% I; |9 |$ w' O4 c
        // Internal
4 D, K2 I  n3 D9 W4 \* `/ m  h        if( no < 5 ) {
/ V% J1 c; ^' f, x                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- u  ~+ u  A: c' |4 S        }9 G$ \* |# I/ B" |  g& Z, ~7 n3 G
        // VRC6
% L' b; `  w3 i        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
$ J+ w" _2 ^& ~* [4 b9 Z) j                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
* Q) W0 A& t8 A( Q7 |5 p6 b        }
; K3 g6 X) G1 N$ C# U& S5 N3 j        // FDS
: E/ i' G  O( J& w6 ?        if( (exsound_select & 0x04) && no == 0x300 ) {
. I8 n; r  j4 F                return        m_bMute[6]?fds.GetFreq( 0 ):0;
) F( o: K) c) h, v6 y. O        }
$ M" b1 ?6 }- t        // MMC5/ O  a: O% H+ D; M
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
3 P6 c) p/ ^6 o- q6 Y, u+ Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
( ?8 H0 O  X  x. H& t% D4 i        }; P( Q4 g4 `1 E' K
        // N106
- M. A5 n2 F' Z4 {9 J        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
; B3 u+ X+ R. W# M0 m) M2 J) Q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' b# g: q4 V3 O- C# ?' l5 W        }/ _% @2 f2 i& ~6 k4 ~, X8 @# N4 s* C
        // FME7
# A  K: _& o6 E- H2 N  }        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {; e" _! j8 |( T' h3 Q) m+ t
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;! s" B* U4 o4 Z
        }6 x, P! _  H$ A7 x3 S8 l
        // VRC7! j7 f3 C6 o" ~( P
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {/ M: ]' \: I# Z1 m- a% f6 A
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 |$ \2 M- }" T( L$ C        }
% U. N1 ^8 p+ w! s- O5 _        return        0;
% Z# [2 U8 E0 W$ g}" ^- T# r8 Z% z! Y) s  S* ]

  g6 Q) c0 X# s! ]) P5 L// State Save/Load
# k! g5 [* M% m2 H& N2 nvoid        APU::SaveState( LPBYTE p ). r, e" s0 H9 l9 b9 \# u! C  ~* u/ }
{
- w4 M6 D; w1 E% ?#ifdef        _DEBUG
6 K2 A; U+ ?2 E. _+ DLPBYTE        pold = p;% M* }  f' o0 P' P8 C- b* {0 @
#endif. h" q7 n0 @, Z7 ]9 U6 s' p1 l

0 Y0 Q2 |) a3 U: g' z1 a+ ]9 f        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ S/ E: v. I8 a( i. Y
        QueueFlush();1 k( C/ n8 U1 ]5 k& J

9 H# y! K; b+ z& R0 K) p9 L! G) T        internal.SaveState( p );
" U; J2 T8 A4 c7 b) I( K: G2 q: q2 E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! w3 A# \8 A2 E1 e, r1 l6 o4 z9 N8 T4 e  s5 ^
        // VRC66 z0 N* G6 x8 |( r
        if( exsound_select & 0x01 ) {# o2 |/ x. B4 S4 B) d
                vrc6.SaveState( p );
6 |' A6 k  h  x+ `2 P% J                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  F2 g- K: C0 T' D1 _  D% G        }
5 |0 N1 U7 h  m8 e8 O4 ]        // VRC7 (not support)
& }5 ^5 C/ N7 r! ~8 V: |        if( exsound_select & 0x02 ) {
$ D# L9 N# N1 k8 \& W  [                vrc7.SaveState( p );
" r7 E$ ]3 {0 \( M6 p7 @                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 c. t. k5 {/ G% Q0 l# ?9 ]: o        }
& F3 T- d5 n: r  E' Q7 m: {  G0 t        // FDS" J/ \. l" V/ P1 H3 E2 n
        if( exsound_select & 0x04 ) {
# z/ a4 p' z% ]                fds.SaveState( p );: S4 x) A3 s' m2 T$ D4 X1 N6 b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 ?% {! W! L5 E, H3 ~5 B
        }, ~: h# P8 {9 E3 k* ^
        // MMC5
3 W$ i+ [5 U; N" Q1 t* F0 U/ E        if( exsound_select & 0x08 ) {
/ b/ U2 a9 P% Q2 |- ~. {0 \                mmc5.SaveState( p );
% ?3 H1 G2 \( f0 R! I8 Q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 @2 M& N7 I9 ^6 a* W  i" F        }
- g/ Y/ J4 L. ^- u        // N106
; ?( `* ?$ v" L* ?7 M. L  V        if( exsound_select & 0x10 ) {* I' x) n; J7 d& l2 ^4 {
                n106.SaveState( p );
: v0 Q" D5 I" c% J% f6 W7 j2 z% @                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& k# {3 j+ y. v
        }" y4 N, \, h' O
        // FME7
: L1 N& x5 M% O  Q7 x% C$ N% x# h        if( exsound_select & 0x20 ) {
) p- B: i+ s# z1 }9 h' w" m+ {                fme7.SaveState( p );& V0 V1 {2 O7 S* d0 U/ {$ N9 n( L( H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 e8 \0 D3 M: T2 K4 m" g
        }; Y4 ~; @& e' Y4 Z6 B$ G

2 v* k! p% y1 E4 V#ifdef        _DEBUG
: ~  S1 a6 V9 ]8 ZDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
* A$ L$ c6 e: n& l, Q1 E+ l#endif
: _4 ?8 c8 {4 j" {}* x  y) h; w  m# U& A
* Z; ~) H3 i' N4 |5 ^& d: `
void        APU::LoadState( LPBYTE p )9 w6 q4 R" M3 Z
{
2 U" ]* i/ Z! O% y3 S% K# Y        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) s4 f# \; m# [* I        QueueClear();2 e) ^7 w" O) q

8 i) W. Q" i( t- l! M        internal.LoadState( p );
) R3 Y; V/ \6 }" h/ W% h0 N3 U6 s        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding" f2 Q0 _( v- B9 S

2 q+ n. v/ t3 Q4 d& N( {        // VRC6! }& x- J" |8 I+ t# r
        if( exsound_select & 0x01 ) {
$ `5 F; E) A( C- P7 {                vrc6.LoadState( p );" D) X  V! t; Y/ |3 Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( k" {( o4 a+ W# K$ V3 g
        }
! |9 |$ {! t7 f& H2 H* t& u( _, o        // VRC7 (not support)" K+ E7 _) [9 r
        if( exsound_select & 0x02 ) {' V( X7 ]8 }4 ^! O6 _
                vrc7.LoadState( p );
1 c7 ?7 a7 g. ]& z- {' k4 D                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 P. h' F1 B2 \- M# h
        }& Q% }8 l  i0 U4 R; a2 U
        // FDS
( M  V5 y: A( l& t3 G/ D        if( exsound_select & 0x04 ) {
! k' ?7 p: d( g2 c; @8 e' h                fds.LoadState( p );
" b" _9 ?# K7 m1 N                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 E3 c0 c5 J* @3 h/ e        }% [7 X+ D; F& S- n  D
        // MMC5
4 r) Q, Z8 x: V" }+ K! X        if( exsound_select & 0x08 ) {0 Z1 C9 x& c  t% Y1 o5 I, w
                mmc5.LoadState( p );
3 d9 j7 V) {, V" E: o                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" M- {, k- R- M  l$ L8 W% E
        }
7 R, P5 K0 c8 J' f        // N106
2 r( e9 C8 T( E2 r$ H; i' m; D        if( exsound_select & 0x10 ) {
% Z$ K, |: R) L5 M% F' b# ~  ?                n106.LoadState( p );
% j3 A7 ]2 ?- h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: r0 O, `" U3 y4 E2 X. U
        }, [, s; w' p  S8 Y" B
        // FME7$ r: H$ o1 K% l+ y, F- i8 v
        if( exsound_select & 0x20 ) {
8 ^, ?7 A3 R+ n  {5 h                fme7.LoadState( p );
8 @% J5 [1 u: ^" g3 M& H/ Z. c                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ F! g4 T5 c7 e; m
        }, [" Z. \* U1 \7 K
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 9 v% Y) B6 V9 p' m
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。) f3 x4 i( v4 s
感激不尽~~

- e2 x9 U% D* B* H) w& z6 C恩 我對模擬器不是很有研究,
7 w- L9 l5 M0 J* u% k3 ?雖然要了解源碼內容,可能不是很困難,
! K6 k+ P& e% P5 Y) o不過還是要花時間,個人目前蠻忙碌的。
5 B  ~. j; o9 g4 }/ u8 B) z% @6 Z; ~4 k! Z2 K
給你一個朋友的MSN,你可以跟他討論看看,# v) b9 ~, b/ E/ N
他本身是程式設計師,也對FC模擬器很有興趣。
% y/ B. R2 ]8 G+ z& X8 I; |9 _9 m. y. d! [- j( {
MSN我就PM到你的信箱了。  N; z2 q2 Q' ?2 @" D# I

  r# c6 {% C1 [+ a# L2 G希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
; ^. A; q. D9 u' N呵…… 谢过团长大人~~

3 I3 X( G6 h0 L4 X* R$ r; \
. i1 Y6 ^- Y& e& o) n9 f, }( ^+ ]- [哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 . T7 b8 O1 W2 K
团长的朋友都是神,那团长就是神的boss。
8 u5 P1 R# ~2 i  i- @  @5 z- z
哈 不敢當,我只是個平凡人,
9 S! d  C* t+ ]要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙4 d; v5 x! C* F* r
ZYH' `" j8 ^5 S5 e
QQ:414734306: ^1 f8 Q, Q1 C  M# s8 ~
Mail:zyh-01@126.com
8 a! |$ [2 S0 ^6 A8 X- E$ b$ e: r0 P' Z. Y  ]1 X1 G
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ; e- S$ l7 u; c% S- `3 L
再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ t, k* Y  ?' a2 m5 [8 y
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-10 18:00 , Processed in 1.101563 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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