EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 p+ c0 z$ m, \: A- Q9 ]& B
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 n8 D3 ?* O+ I0 I# g
这里有相应的模拟器源码,就当送给大侠了~~; r, `' s$ \  C0 [  N+ g" ?
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
& ~+ S5 ?5 L' }. g9 t能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 U% Y. p0 q# Q6 N8 C0 I0 Y( H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( v5 E% Q( @- l; p, W4 Z这里有相应的模拟器源码,就当送给大侠 ...
) O- G, u4 l1 e0 {4 q) L
聲音部分(Audoi Process Unit = APU):; K& B. X; Z) r# `& W1 ?
.\NES\APU.cpp
0 M/ E( G! o# f.\NES\APU.h2 M/ u& T( u0 E! L. p2 {

5 G+ a/ `6 `3 }+ V* k; Z
" F) e% C& b5 c7 H3 ~( n( d1 B8 \影像處理部份(Picture Processing Unit = PPU):
3 p" m& G9 V% E.\NES\PPU.cpp( m; L. l% Z, E) E( o4 f8 w+ s
.\NES\PPU.h' Z8 G$ D- U5 R' [6 b1 M

# ~  J  B0 g" q5 N+ t& G1 V如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 H; l# I3 P4 I+ m3 B  l, ^. O, w
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 T+ b  |: H( S
//////////////////////////////////////////////////////////////////////////
  M/ N! Z7 U/ ~% T, I//                                                                      //
( a1 y! _5 N7 Z! ?5 J# f//      NES APU core                                                    //
8 ^  e4 k4 ?7 Y/ N% V. u3 {0 J# ]//                                                           Norix      //
8 |/ _$ u+ |. T% o$ h//                                               written     2002/06/27 //
# B. t  D9 Q* ~1 E1 G4 Q+ X3 I//                                               last modify ----/--/-- //
1 z. u; D8 L- F! c! d8 x//////////////////////////////////////////////////////////////////////////
/ F0 I' M! T! X- b! h+ z/ D#include "DebugOut.h"
5 z: {' C- L4 x#include "App.h"; [, B+ L4 I' C$ ^0 P% n5 O
#include "Config.h"
# ^. k# }; L/ s4 E# a
; I" g, @, m& O#include "nes.h"
: }1 T. n2 r0 s, z, ?#include "mmu.h"
# |: g8 A9 `5 m: t#include "cpu.h"3 u- K" o, }3 x. \  x4 f
#include "ppu.h"% F' e, ?$ a, z. R
#include "rom.h"1 P8 M+ m% N5 \* ~
#include "apu.h"
1 s! C7 }4 g2 W* j7 v  d( ]( j: C( |6 J' o4 I2 y
// Volume adjust
, f, a7 ^* W1 ^& f9 A// Internal sounds: v& u7 L2 S! b
#define        RECTANGLE_VOL        (0x0F0)3 i9 h* n: b$ W, x" W0 d# @- F5 c: S
#define        TRIANGLE_VOL        (0x130)
. T; n, q0 \7 M1 Q#define        NOISE_VOL        (0x0C0)
) a2 {  [, @  m# l#define        DPCM_VOL        (0x0F0)
$ J6 \  u  Z0 N! n// Extra sounds: H- p( Q- w: c% N6 V
#define        VRC6_VOL        (0x0F0). X1 m  L( N4 }$ v8 q' B( J- t
#define        VRC7_VOL        (0x130)% m2 @% Z2 L# u0 O4 C! F
#define        FDS_VOL                (0x0F0)2 q2 Y7 C+ I; S6 ~* k  X3 _( B$ ^% Z
#define        MMC5_VOL        (0x0F0)
+ ~$ e- d2 }5 F) M% @- W% E#define        N106_VOL        (0x088)
) H% f  k1 |+ A2 L8 l. o1 v; @  a0 B+ j" L#define        FME7_VOL        (0x130)
: f% g5 q8 ?! g; a2 T( f2 U( c, I$ M2 ^% p! P0 J& ?
APU::APU( NES* parent ); |& k( f/ G1 H
{$ W7 j$ M; a, h
        exsound_select = 0;
" s+ E0 \" v' _1 @5 @5 `/ K2 Q5 U) W* m2 _
        nes = parent;
2 `$ {- l: L( J2 y" p. F' I) R        internal.SetParent( parent );
4 X$ a  V/ q; q7 z0 ^" @: Y+ z: K( J( g5 J3 ]
        last_data = last_diff = 0;6 |; C5 Q; L3 B! \

9 Q- V! ~" i6 A) m4 C" W) }# X        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );- B* u  p+ Z. m. I. c& `' ]# b
- k( j5 f4 i% ^2 Q3 r
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
% X  r2 {& ~& t) B* s& ^        ZEROMEMORY( &queue, sizeof(queue) );# }, R% b' y2 f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# ~+ H$ C- V# q0 w- s9 ~) T- S( I( [6 Y5 d+ n* G9 w
        for( INT i = 0; i < 16; i++ ) {
4 b: s9 T+ a& a* f0 A4 U                m_bMute = TRUE;
2 k: f) R' r) i& A  M- I2 s        }
2 ~, w+ l9 ?5 d4 k, S1 X  M}
& e' z" z+ a9 I# t5 L* x
) A; @1 {. Y. M5 I0 v4 AAPU::~APU()' i3 q5 o6 o8 W( z) D
{1 M: ^- P% t5 C2 @8 T, J
}
' i7 S" H5 X* T# R, b
: \+ H8 J; F, ~! `void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
3 j8 I6 m' ^8 ?  e) v$ [{8 P. h4 B* v+ w; }& _
        queue.data[queue.wrptr].time = writetime;% D( p: a8 Z# _3 a
        queue.data[queue.wrptr].addr = addr;
% q  I7 J5 R* @8 d0 R        queue.data[queue.wrptr].data = data;7 a# l' j  [7 J& i/ u
        queue.wrptr++;
7 g8 w' w2 Z  l/ X        queue.wrptr&=QUEUE_LENGTH-1;) a: z% x5 x4 A; _2 b
        if( queue.wrptr == queue.rdptr ) {* e/ Z, P: H: }" L- S. P! i' N
                DEBUGOUT( "queue overflow.\n" );
, D! E4 O: x8 _1 D. h* Y' k        }
- s+ A+ P3 Y) [1 x7 ~- w}# ?6 C4 f( s- ]% p7 C2 P
" L) I. ~$ c% Y# x  K3 J1 y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. h+ x6 V/ x1 D* P{
. u: ]. h: X1 }" W        if( queue.wrptr == queue.rdptr ) {
- R( q$ Q" N  n! ^3 C                return        FALSE;2 Y. g, S, n: O% O' x
        }. s/ n) e% I3 o) r# \+ r! E, z# O. j
        if( queue.data[queue.rdptr].time <= writetime ) {9 S" m, w9 V  W
                ret = queue.data[queue.rdptr];
7 a  e# r) g+ K6 P- h                queue.rdptr++;
) r% t% x3 H4 e; p0 @' b                queue.rdptr&=QUEUE_LENGTH-1;8 ?! }+ j* X* Z- r. h% K$ t
                return        TRUE;& E/ j4 B8 L  ~3 ~1 L
        }
- V; A. b0 \  n: [- f        return        FALSE;
3 U1 c! t& q8 Y7 N}
# Y% H. ]+ f/ {6 U  ?0 g
* e& X" J) S; |' T+ ^4 Tvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )( v/ F' q! ]8 k% F* h- m. u9 Y6 M$ u
{
* w- L9 v8 a, p! C3 E! Q3 O( q* p        exqueue.data[exqueue.wrptr].time = writetime;; {: E* s+ K) ]  ?, y( W
        exqueue.data[exqueue.wrptr].addr = addr;
0 a7 t  I' o3 H0 y        exqueue.data[exqueue.wrptr].data = data;6 Q7 f8 G+ |1 B; N! d/ f
        exqueue.wrptr++;
9 e& n  F# F/ N3 q2 l        exqueue.wrptr&=QUEUE_LENGTH-1;
6 H. `! k. f, D' p+ g3 q# o6 ~% k        if( exqueue.wrptr == exqueue.rdptr ) {
2 h0 W2 k9 P9 \% E! A" q                DEBUGOUT( "exqueue overflow.\n" );4 P) [7 f$ l: s0 J3 u$ }. G
        }: e# ?% r0 C; {! @+ C) c* Y
}9 h* l1 h- t% ], t. w: Y0 |

( E  K4 H: o! oBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
  I) k, h; q8 o{
% ^5 _, E. k0 N8 H        if( exqueue.wrptr == exqueue.rdptr ) {& S: U, G/ O+ g8 c
                return        FALSE;
0 M9 @0 p$ Y$ q7 f/ b2 k        }
# H7 Y" S$ J" t        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ R2 v: d  y4 j4 s9 B
                ret = exqueue.data[exqueue.rdptr];
; h2 q% C. W% }* l6 h$ w$ D                exqueue.rdptr++;
- G% ]9 H1 p& I/ c2 |                exqueue.rdptr&=QUEUE_LENGTH-1;1 L, b' k. e4 f9 W7 }3 @4 X; @" J
                return        TRUE;
' ^0 A" w. _- Q5 Z& x9 S4 V        }; C; T/ I. T1 h' R( X, G
        return        FALSE;
5 k) @: O1 ~/ i. @" B4 |8 s}+ d0 y; }0 Y5 `+ R8 A! D  `
3 x2 ]! @" {7 K7 Z& J, G+ V% U
void        APU::QueueClear()
  G+ P5 u6 ^& I) L2 z5 r7 ]{) b% W( ^6 y0 i$ ^
        ZEROMEMORY( &queue, sizeof(queue) );% P  W0 I3 z5 @. f6 E0 V  a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 r, B  g% {( s" V. h1 j4 o9 k
}
1 ?- @+ j3 Y6 J& J& x
$ Q' r7 N$ ~6 ]3 t5 B) Svoid        APU::QueueFlush()
5 ?% \$ T2 v2 q& f, E; [( P8 M/ {{
8 V( P% X: }: u( G) n5 E        while( queue.wrptr != queue.rdptr ) {
  g$ a* b* l) s                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
. W; k, Z  e# U1 l0 F/ P                queue.rdptr++;
7 R; t( K0 }& F: f# A" H2 s" a                queue.rdptr&=QUEUE_LENGTH-1;1 {) C- j8 N* _2 p$ @
        }/ {9 Z" H0 j. \
' M8 q% b# Z2 {; H' B
        while( exqueue.wrptr != exqueue.rdptr ) {
" L1 H+ R. S, N8 z                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 Q/ G* J% [5 o2 G3 [( S                exqueue.rdptr++;
1 ?5 L0 L9 d( k! ]8 t                exqueue.rdptr&=QUEUE_LENGTH-1;1 W7 g2 |& J6 r: b
        }
; W7 S# d1 Q; [; E& \, ?9 ?}# @& g+ x% F6 W" h6 I* N% V$ u
( l" d# G  k2 u! H. m; `* t
void        APU::SoundSetup()
# z9 X- l0 b3 C; C{
2 D% g3 x* R1 S1 d6 U9 E2 j: m4 j        FLOAT        fClock = nes->nescfg->CpuClock;  A+ @# X4 L* C0 A
        INT        nRate = (INT)Config.sound.nRate;
) i% D- z% E4 g$ P& y        internal.Setup( fClock, nRate );
! _4 g: Q2 n4 W: |9 s  r        vrc6.Setup( fClock, nRate );- B# K& Q! D" S; A9 H% M
        vrc7.Setup( fClock, nRate );
5 W" b6 O3 L1 i        mmc5.Setup( fClock, nRate );  _2 v9 Y% a8 c
        fds.Setup ( fClock, nRate );
' q0 k# o; B2 H0 @        n106.Setup( fClock, nRate );
  `$ ?4 p: |9 J9 v5 G& A' G1 n        fme7.Setup( fClock, nRate );; `6 i6 H. j3 Y8 A! S
}
" U3 T) J. K1 Q- R$ h& o1 _
: A" I5 a2 W& Y3 B: Ivoid        APU::Reset()
3 ?( X2 @0 x2 T" \{
0 r/ l* `" f/ `6 p/ y: ]9 Y        ZEROMEMORY( &queue, sizeof(queue) );9 ^, T2 m4 L( h. e. {/ O
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  u9 F: W3 _0 U$ N1 ]5 i* c
* c+ U7 u( }6 W        elapsed_time = 0;
/ z" ]( `/ w5 E9 K4 ]( _+ E
8 |: O% ^& Z, p9 b6 F3 f7 |        FLOAT        fClock = nes->nescfg->CpuClock;- a$ L/ z- ?  I$ ]% P" G7 j
        INT        nRate = (INT)Config.sound.nRate;* @0 F# o0 h# K
        internal.Reset( fClock, nRate );
5 l1 t0 _; k! y        vrc6.Reset( fClock, nRate );7 {* K' I7 H$ ]& o; [
        vrc7.Reset( fClock, nRate );
' W, m; c( f3 D        mmc5.Reset( fClock, nRate );" i+ o5 D! B# M- d! N$ f, p+ O
        fds.Reset ( fClock, nRate );0 i. A4 x" p! A
        n106.Reset( fClock, nRate );" K6 o9 o$ j5 q
        fme7.Reset( fClock, nRate );
! O' B% l0 \6 ~! C; ?- Q
+ u) T/ R" |6 n8 R3 n/ V        SoundSetup();
5 K8 w, k! q# H3 \& {( N}
4 d( C: c/ m) r% f7 D) R* O. U1 R4 b( s8 d1 R# e8 @+ o! T
void        APU::SelectExSound( BYTE data )6 C1 i- g4 l( E' b5 m8 o" M* ~
{
  N$ l; A9 T3 J. a        exsound_select = data;6 l- R  V. |% O  l) y8 h
}" U9 M1 z% X- [
- C; e0 G, \% S5 D) q$ ?" ~7 I. i
BYTE        APU::Read( WORD addr )
, f/ S; p# y! S2 V* G+ e{0 q& V" U$ c+ h. V/ S7 C8 a8 H
        return        internal.SyncRead( addr );$ d7 F0 H+ k3 {/ O# a0 V' E4 P1 ]
}
0 p7 j( c$ ~! x# Y  W0 Q% G' C! W/ F% T5 U/ a- M) D+ l
void        APU::Write( WORD addr, BYTE data )
: g  z5 o$ m. J  @{% k% L! q: f. ?( j" h
        // $4018偼VirtuaNES屌桳億乕僩) q4 r+ W. ^. r6 v# j2 Q  l; {- N
        if( addr >= 0x4000 && addr <= 0x401F ) {0 s5 v2 v' ?9 y
                internal.SyncWrite( addr, data );
6 P+ a& K+ t1 o                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% B/ O9 I# Q2 q* V  U( L
        }
) R- R- o% y- W5 r3 B5 c9 B}
. ]7 [2 Y: o. ^7 \! B  C
1 R- w2 n, g8 UBYTE        APU::ExRead( WORD addr )
1 T  h9 ], o3 @2 Y0 _{
$ w! [  W% z$ f+ J# H! wBYTE        data = 0;
, A7 S- d6 F/ q) X+ W9 P+ ~# ?  |9 O+ E/ R. h! i7 W
        if( exsound_select & 0x10 ) {' b+ Y* k- ~) D  P4 V
                if( addr == 0x4800 ) {
' n# T6 |. v1 s- A8 L+ d! |                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 G& H( ?  K3 u% Z8 V! f
                }
- d# `" s, a: ]/ X        }5 O- }9 B* ~4 _+ l# Z
        if( exsound_select & 0x04 ) {. y8 y& U' g& ?/ t$ j
                if( addr >= 0x4040 && addr < 0x4100 ) {0 i5 e" ~3 P3 Q8 E
                        data = fds.SyncRead( addr );
' i6 o+ R; F" Z: J7 A                }1 K8 C4 k5 L4 Y% v8 a
        }
9 C& ]% N. E4 L1 _5 P' W        if( exsound_select & 0x08 ) {4 f! _" L0 q1 V, M  P7 ?) R9 p
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ h0 N! R7 p! O1 E: `0 r
                        data = mmc5.SyncRead( addr );
% m) E4 W* Y4 ~0 A! H+ Y6 |* ~                }
4 C; J  k4 S+ {        }+ x2 E/ g5 U" G& Z0 D
5 a& P2 t+ S/ r
        return        data;* P, u! Y2 q# U1 a7 p2 z7 i
}. @3 o: S: Z( y( y; {6 e; B
' Y$ A5 D6 c# Q2 w
void        APU::ExWrite( WORD addr, BYTE data )
( c! J7 a( A1 O  s6 X{
. i% Z; \! |% V        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 g2 _8 c/ x: L! Z- B
+ M/ I" y, z* M( q# S4 [& ?        if( exsound_select & 0x04 ) {
+ l% o7 P5 u1 \  [                if( addr >= 0x4040 && addr < 0x4100 ) {& r" ]# ^! b8 v
                        fds.SyncWrite( addr, data );
' o9 J0 d' t; [5 W9 o. e* o, t                }
6 c9 [9 R1 {3 Q5 r! ^        }6 w& B0 k/ [. Z9 m8 t
  G9 |  P7 G. o
        if( exsound_select & 0x08 ) {; X3 |% x! U( b! d- m
                if( addr >= 0x5000 && addr <= 0x5015 ) {1 W# ^7 M' {' {5 ?7 y' N3 |8 @
                        mmc5.SyncWrite( addr, data );
8 Q7 f* ~1 z6 e: t5 K+ m* [                }; H5 s9 i9 c: S9 m0 W* s
        }6 B% ]! r/ }6 h+ b) F7 s$ O
}5 v7 Y7 r: \' @" }5 h% \
; ~, O# u2 f; Q, I6 E* o( H) W
void        APU::Sync()
) x, _4 X, R; D& i{
4 |% y1 n- H9 O" G5 E}0 c7 B" }# {- ~! r

( ~+ w4 W7 k- {/ x0 L4 ?( Ovoid        APU::SyncDPCM( INT cycles )
; J3 D( q& C' Q# @{
* @+ D. A' ~4 E0 z& {5 H0 D8 j        internal.Sync( cycles );
7 d1 j: Y2 Q4 U7 y; Y/ }
8 p1 J- q- D5 q, R        if( exsound_select & 0x04 ) {
) c+ m# l# d' W8 G* c8 X6 J  N9 _                fds.Sync( cycles );+ ^( X5 a2 v( d& o: U/ v. Y
        }
# j( ?' l( `3 p! e6 [5 H        if( exsound_select & 0x08 ) {
/ J+ }8 v( Y, t, i' R                mmc5.Sync( cycles );6 D4 Y; n. P* ~& }3 N* U* p5 S4 Z
        }
5 T& o- ]- O) ^0 N6 C3 k% m}
! h0 s8 y6 T) u; {0 |* V- c4 Q9 D) u$ E; _/ ?* t7 F( F& a& \
void        APU::WriteProcess( WORD addr, BYTE data )
9 W# i! G! h( O! c, R$ [{4 w; t" R7 |! ?1 U4 G8 G
        // $4018偼VirtuaNES屌桳億乕僩
8 R5 O0 [( ?9 B0 M  C        if( addr >= 0x4000 && addr <= 0x401F ) {: \2 [- E7 g2 Y7 v: K
                internal.Write( addr, data );1 \8 v  L7 ]3 m9 r
        }7 w) S  M5 s! s4 ~$ {) H- m
}- _! T$ h6 U& Z  N* S" G

' F. q& o/ Y" V- V) P: o, r4 E- Hvoid        APU::WriteExProcess( WORD addr, BYTE data )
0 w+ _3 T) [$ P0 c{+ h; f( l8 T1 n* u6 u! [
        if( exsound_select & 0x01 ) {
4 V7 o5 A. b2 z, v                vrc6.Write( addr, data );1 J1 B; ^( h4 Z& O; E$ Q
        }
  j# D5 j, ~# U* U. M3 d# }3 q        if( exsound_select & 0x02 ) {
% ?# A+ o. P- b0 V, B                vrc7.Write( addr, data );0 ?' f* W" B( }$ o; q1 E! g
        }
, n0 _( T8 c$ g+ P) I        if( exsound_select & 0x04 ) {
, a; P6 ~! U$ |, D5 }. u( n                fds.Write( addr, data );! z5 l" i+ {5 u& j, v( @
        }
: b& U5 Q: k/ O1 ^2 C        if( exsound_select & 0x08 ) {% }% G0 g# E: F' o3 R3 @& W
                mmc5.Write( addr, data );  N& o2 y5 y: `3 k) L! v  c% D
        }
- y) M# C" y4 k/ j        if( exsound_select & 0x10 ) {' E1 d3 C: x4 e9 R' \7 Q! t# h* _
                if( addr == 0x0000 ) {
7 T( V- Z+ H; h# g# l4 B# p2 k+ _$ e  c                        BYTE        dummy = n106.Read( addr );7 a0 ~4 U+ Z/ D( m4 S) \
                } else {
! X$ G9 l/ Y* |: p                        n106.Write( addr, data );# Z. m! B+ Z$ E( b, Z5 n: K  ?4 s
                }! I: T* p/ v; F. Q
        }
; ?- S$ U$ U% @  F. a; G/ S" p        if( exsound_select & 0x20 ) {
( }8 [- p% t! V  g, V$ I                fme7.Write( addr, data );
* V# q6 e, ~. P+ i" x# a0 e0 K9 a        }6 y  f, S/ ~/ Z3 S. ]9 p) i
}" d6 x: ?4 Y- H" {

* P4 }3 W! G% g: X/ b1 z7 B+ d' {void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ); G& O6 T5 D6 l7 \. V# l
{
  O4 i- k, b1 Y1 T* pINT        nBits = Config.sound.nBits;4 }: v4 B! q4 d# m5 p9 f
DWORD        dwLength = dwSize / (nBits/8);5 o7 m  E8 B, h. t* x) B
INT        output;# p( q1 q: l7 a+ c* w  g
QUEUEDATA q;
( ^+ P( C2 k- \0 JDWORD        writetime;
. k8 O, ~3 j$ d  k  r; j4 M6 M5 _- `- Z3 R$ i4 }/ ?! }
LPSHORT        pSoundBuf = m_SoundBuffer;( I1 ]+ c, C9 ]  _+ @1 U( z) F
INT        nCcount = 0;# K5 G9 c1 s3 m- B/ a
: {# H  M. T$ W; j
INT        nFilterType = Config.sound.nFilterType;
% l  P4 Y) a$ ?% u
0 T2 Q! z2 I$ O( r  y        if( !Config.sound.bEnable ) {
& a, D. Q" I3 [+ H% R3 k( C* l; g                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
$ O+ [8 ]* g! n+ d                return;4 y+ B8 h" a8 e
        }
! G# R: X6 s1 V0 u6 E& |. d3 w. g# {, N; M) D/ T
        // Volume setup
& m; A6 H+ J1 H/ V; {( u7 I9 u        //  0:Master
8 w/ K# D3 B" U2 L        //  1:Rectangle 1( {! N5 f& e, ?4 L
        //  2:Rectangle 2
* `6 M% Z" [7 o3 ^        //  3:Triangle5 I( {9 |1 {) C9 W% Y
        //  4:Noise
- y! F6 v$ R. P( G$ \6 o        //  5:DPCM
2 O* j$ T; y- b        //  6:VRC6
; J1 B7 h* m# ]' P$ B# r        //  7:VRC74 R  K: s8 b- c' p$ e' U( {
        //  8:FDS
7 Q8 L" H8 e) N) {% @! K        //  9:MMC5- k5 c% [* _' i; o0 ^& a
        // 10:N106
* }6 a* d/ I% E$ J4 r4 C/ W        // 11:FME7
- p8 B* t$ O( m8 m' N        INT        vol[24];* Z4 b( I, j* l0 |) B9 `+ T
        BOOL*        bMute = m_bMute;
2 D8 G, k: X9 R% b        SHORT*        nVolume = Config.sound.nVolume;$ ~# C+ t$ A& d

0 p( l, j( a& J2 ^9 J        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
* B( ^' a9 f6 |. q
" ?+ B& \; v5 @: H. x% i4 l        // Internal
- l) n4 J. K' I+ M% {        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' h: I8 J5 `$ T
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;8 K3 P: f8 ~! w! S
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
+ O: q8 c/ o- m& m$ e        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: X1 K! d1 Q; y/ |        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' p9 p- n4 B6 K2 ]& \+ x; ^6 t' G6 U. q& Z5 i
        // VRC6! W: h8 |' D: Y8 A* K
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 H3 y& `5 v# z. f* }5 K3 d% m
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 W' k" g- S- |: l2 W( i: e$ Q
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 r+ ]& Z8 _' @" E) f% L

; i: j6 b  a' g  [        // VRC7
6 i( |+ ]  o$ m" {) q1 o* t$ `0 ~        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;& t- v5 Z, @& X& P

" ?$ E4 T: j. l' d% o3 {, H        // FDS
! d! s$ c; C! E: u        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ z0 ?2 {* Q8 y" t8 J, F- H& b. S: M/ p1 q  W
        // MMC5% G# g: K8 c8 ]6 v4 I* }
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: C8 e# F+ O8 u# V7 ^+ Z+ A        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( f, g) y6 n( t( W. p        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 {2 r, ]& A3 j
3 P# R: E, V' ?3 R/ P( f
        // N106
/ Q& R% o" A- J8 N4 ~4 w        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 G  G7 ?( k: T. o( P( \8 ]0 Q2 K        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 f* v3 k9 D- g7 D8 X( j7 b
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 t5 s1 J- }4 V& y; r3 ]
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# ^0 F6 }+ p& c* U: ^        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 Z. k0 i/ B+ A% K
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 A! z2 A' f, l        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 P. Y" V3 t* T' n
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) K( b5 f2 M  @5 ]
/ U! M. w+ Q$ `
        // FME7
! d/ {+ _3 \6 R' X2 C        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% F& b" z- f- T' r( e
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* N8 J" ]/ n( u; N
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 |7 G4 b* p' y- T1 x. ~

" ?# W- O. H! l  y& C/ b//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;0 K4 k' J$ b' ^9 g0 h
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 T5 x9 Z5 y) T: t8 m3 d3 B
, m4 ~% h# e  `  {9 J; a
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟# m. g5 F1 c% u3 j9 _2 K
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {2 x$ `9 i' u: W3 h. T+ ^! |7 }
                QueueFlush();- Q: i2 L$ B; j0 g( `& v/ h# G
        }
. W# m3 U; O5 m* Y+ N& k. V+ t# X0 F: t3 c$ T3 w) J3 o) d& m0 S
        while( dwLength-- ) {! }1 s. {0 \9 C
                writetime = (DWORD)elapsed_time;
: `# G( |5 B  |" G0 W# N4 z  {. r9 W5 L5 X# m- y1 ^! R; d
                while( GetQueue( writetime, q ) ) {
% {6 v" r0 |: y                        WriteProcess( q.addr, q.data );
2 Q$ z0 E% p; P7 E2 C2 }( w                }) U( i8 }' w' m5 B# e4 g' r

2 d& r5 ^6 H- g, W                while( GetExQueue( writetime, q ) ) {
- g6 y0 y$ F0 x7 K                        WriteExProcess( q.addr, q.data );
# g7 b9 p# g4 ^5 B3 s" v$ e                }
/ q/ g7 K" i  j' @
( `% @/ |, G9 |* e. m+ [3 x- s                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7' `5 E# f4 L0 P3 x4 x
                output = 0;; d+ ]6 h9 Z3 p4 m
                output += internal.Process( 0 )*vol[0];
/ A* T# L: X0 ]/ i, D5 G                output += internal.Process( 1 )*vol[1];: v. c0 C1 z& ~9 T
                output += internal.Process( 2 )*vol[2];
# ?# U1 b# L: I: i9 R. N/ ]                output += internal.Process( 3 )*vol[3];
( H( T+ z' Q* p6 V; Y                output += internal.Process( 4 )*vol[4];
4 J2 Q; n" k# M9 X1 V+ Q# B' R
% A9 I. B0 b' t* w* _& j  q' {                if( exsound_select & 0x01 ) {
5 T) Q+ y& p1 j$ ^  n                        output += vrc6.Process( 0 )*vol[5];; p4 U( M1 r$ k
                        output += vrc6.Process( 1 )*vol[6];
4 _4 X8 ^* n2 V9 z0 \- G% u# A                        output += vrc6.Process( 2 )*vol[7];
6 A# C7 i* V# _) f5 p; P                }
1 u5 ^% |. Q6 c9 t/ D                if( exsound_select & 0x02 ) {
- j/ T5 {4 k% z5 }( B% e; s& u                        output += vrc7.Process( 0 )*vol[8];
- F% X2 a" D' [- L! M9 @* D8 A) X                }
! Q% f! Z& e+ n! z                if( exsound_select & 0x04 ) {
3 i, k$ `* ?) ^9 i0 J8 ?                        output += fds.Process( 0 )*vol[9];% c1 B# C- a# j$ w) e* A
                }
; U1 b# N0 B7 |5 w2 t                if( exsound_select & 0x08 ) {
5 C, i, B- e1 g7 c! L: `                        output += mmc5.Process( 0 )*vol[10];
8 r7 M5 g1 K' X7 m1 @% a+ Y. _, W1 K                        output += mmc5.Process( 1 )*vol[11];+ o% S% q" }' j( b2 d5 j7 A9 V; p
                        output += mmc5.Process( 2 )*vol[12];
! n$ b2 q# ?; l/ r                }
" j( l5 k8 a6 c/ W4 ?8 G8 T; S& w                if( exsound_select & 0x10 ) {$ }+ x* ~+ N- R8 ~& M: A
                        output += n106.Process( 0 )*vol[13];
6 l! ^% X+ b8 h' h* I# G                        output += n106.Process( 1 )*vol[14];
3 j# V3 o8 x4 s9 d1 k" J7 c: F                        output += n106.Process( 2 )*vol[15];
$ X1 V" A6 k! m, t5 K7 c+ E) `' K                        output += n106.Process( 3 )*vol[16];. J; i  Q: s+ [" }) X
                        output += n106.Process( 4 )*vol[17];
2 {$ f0 v: N9 u3 W1 |                        output += n106.Process( 5 )*vol[18];
1 l" q0 X* I4 Y: L! a. }/ G                        output += n106.Process( 6 )*vol[19];
0 u; u' P- q  a4 a. m1 K9 r( U( z                        output += n106.Process( 7 )*vol[20];
* S: ~5 @  J( u6 G: {2 R                }7 d8 }( i1 y# R/ r" q
                if( exsound_select & 0x20 ) {0 L' k$ P# P1 r9 M8 j# d* A3 H
                        fme7.Process( 3 );        // Envelope & Noise9 R1 E/ E9 e# x/ g5 z1 D/ p: h
                        output += fme7.Process( 0 )*vol[21];; p' i( Y8 ?4 I. V$ G! S
                        output += fme7.Process( 1 )*vol[22];
7 t& y4 T1 [3 t) q2 M                        output += fme7.Process( 2 )*vol[23];
) N6 [; c) V, c                }" k0 O* n, Z; H: q
; R9 s$ q" w! U% B/ p6 g
                output >>= 8;; E0 J  G8 k2 Z  c2 x2 n5 ?
2 X1 O8 w1 M. T  i( b
                if( nFilterType == 1 ) {/ ?% \0 t, d4 \8 n' N
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)% U8 j. a2 \, x4 Q. E: O$ K
                        output = (lowpass_filter[0]+output)/2;( w; D+ b: i5 T* h# X" k; W! m
                        lowpass_filter[0] = output;$ Y. R5 e2 u3 S: P* T, o9 t
                } else if( nFilterType == 2 ) {
' B. U) W" |& Z% p8 `) e* h                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 Y4 N& S+ x' q1 T8 N! ?                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 B) B( ]* ]  N9 e% t& {/ w                        lowpass_filter[1] = lowpass_filter[0];
# V1 [+ N) Q7 w+ Y5 l2 H                        lowpass_filter[0] = output;
5 K6 A4 W0 O6 n( W  P2 _5 @                } else if( nFilterType == 3 ) {
, e6 T. j  T, \1 ~) k                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)& k4 W+ j7 C3 N* W' a3 u
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* i8 B, u- }4 w  E/ h  \
                        lowpass_filter[2] = lowpass_filter[1];( o1 f+ X7 w( M2 F
                        lowpass_filter[1] = lowpass_filter[0];
1 x1 C4 B1 {$ U7 M/ i                        lowpass_filter[0] = output;
7 _5 f0 a- Q7 x                } else if( nFilterType == 4 ) {! M1 T5 a. B( h1 N0 K, D0 g
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& B( J8 k1 f. [: Q8 d
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;3 }9 w# s6 n8 {, C
                        lowpass_filter[1] = lowpass_filter[0];* u; W! w# {( F3 m7 E
                        lowpass_filter[0] = output;4 y8 k, K( h9 D+ U
                }+ U  h" k: D8 }" K  O& X

# M& s$ A4 p5 z#if        0
& E. z  o* q6 L' W                // DC惉暘偺僇僢僩  W. Y1 e9 c. j  |$ V, Y
                {6 w5 }# o1 S/ W$ p; @. K
                static double ave = 0.0, max=0.0, min=0.0;
0 m7 b5 u+ @6 k! b3 @3 N: `( Y                double delta;/ x$ m& y* B) F/ i, L
                delta = (max-min)/32768.0;
* ^# _# j; F1 q/ S# i4 o6 w                max -= delta;
6 ?3 p$ c# U6 Y* p* p- A2 S                min += delta;1 ]+ ?) l5 L9 }& u/ w" ?: c
                if( output > max ) max = output;
- m! v4 l5 S$ b" h/ ]/ G* N7 h                if( output < min ) min = output;
7 Q+ U& i; X6 Z) [' J0 }                ave -= ave/1024.0;. S  a9 v, d) c- b0 z& \
                ave += (max+min)/2048.0;
( G' T" a: ^; y; i/ W                output -= (INT)ave;# ^9 }. H7 I) X. j' ~( q. v
                }
, g0 F, t9 X7 u/ O#endif+ P) [1 V1 g. x  N0 \  o; n5 U* n* W+ |
#if        1) t5 O% L( \' K1 J' V& c
                // DC惉暘偺僇僢僩(HPF TEST)
$ A1 U- w+ o) b/ e, J0 ?$ A                {
9 B4 r5 O1 `% t, }9 I//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);9 d0 @5 C) m) W4 ^5 d
                static        double        cutofftemp = (2.0*3.141592653579*40.0);6 b( z3 ?: u+ X, I
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# w5 A% Z8 q5 M; t9 S- w                static        double        tmp = 0.0;+ ~4 a7 B- N  D& s, ~6 g
                double        in, out;$ t6 y9 P+ ^$ U% {8 z' v

# O7 a7 ~% c; m5 B! c0 N. x, k& r7 g                in = (double)output;
7 l% R; F5 s& }% ?5 F, `. F, `                out = (in - tmp);
( f3 t  T4 o4 q                tmp = tmp + cutoff * out;1 L" f! j3 o5 a( ?8 D
8 w% [9 H2 ^, R
                output = (INT)out;$ J4 G+ [" L/ V) X
                }
! P  e# [% p# q#endif% D& j3 A& h* x0 C
#if        0$ h8 N1 }7 v" \) D, Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)$ G. S* }6 H/ o3 g/ J3 _
                {
! z0 {/ o6 [" l( o/ w! N2 b                INT        diff = abs(output-last_data);
/ B9 O6 |; k6 m; M8 v                if( diff > 0x4000 ) {; ~, o" t. I+ r9 V
                        output /= 4;
/ H! l  Q! Y% R* Z- O                } else : {8 g* N( Q/ p' t2 w' L+ K- Y
                if( diff > 0x3000 ) {0 {0 N" V  V3 ~1 p
                        output /= 3;, W# A& x2 l; N+ H  Y+ A/ v+ L
                } else
  Z' s! C6 T% h                if( diff > 0x2000 ) {
5 p( c( D5 k+ W                        output /= 2;0 `5 F: T5 \, N9 v9 y" [
                }
! r9 _, e" f. n9 G3 S# o6 x                last_data = output;
0 C0 J+ [0 w/ D" Z) w: I* q                }
; g) V5 s* j! P1 `7 Z' t#endif
/ r9 F  N6 H& N3 S                // Limit
. v- g3 ?+ }9 T  d, Y                if( output > 0x7FFF ) {8 ?0 {; e, |# _: T
                        output = 0x7FFF;) t$ Y2 V- H9 }0 @4 I8 C, _
                } else if( output < -0x8000 ) {2 v) q6 y6 l8 J; z% Z( B) w8 Q
                        output = -0x8000;
7 }6 a3 N( }* S                }
+ M$ x" t4 t- |
1 Q- B4 V& l5 e                if( nBits != 8 ) {
7 U& H/ F  d  W1 t! G) y9 j' V                        *(SHORT*)lpBuffer = (SHORT)output;: v/ S7 E) H. u  |7 W# {3 X5 k1 D
                        lpBuffer += sizeof(SHORT);
) g# D. y6 z0 S/ y                } else {9 _( ]6 N+ k4 n9 Z
                        *lpBuffer++ = (output>>8)^0x80;6 C1 [. n/ c% t$ Y! B
                }& P( x+ E0 A) p* h2 e

3 F# P( q! W5 L* x8 X( t- E* w+ ?                if( nCcount < 0x0100 )
( z# Q. i1 d6 L% G2 r* X. q5 }                        pSoundBuf[nCcount++] = (SHORT)output;: \) I! P4 g2 d7 ~1 j( R

: C# r0 g3 X! B//                elapsedtime += cycle_rate;
7 T4 p8 L0 d2 U8 L                elapsed_time += cycle_rate;* ?/ c3 d8 M, O2 f" m
        }  a7 W1 y9 `5 K' |/ F6 U8 Y9 q

" k7 H0 |  ?5 C. U3 r$ [! W6 O#if        1
  t5 M: Q) V3 y/ @1 F5 h& o3 }        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
& Q2 ^2 J) e! R# O                elapsed_time = nes->cpu->GetTotalCycles();+ [2 k* c% @; {! i; w5 a
        }, y7 H+ C5 @: i( z: l% P+ ]* D
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& ^7 b5 l4 y- H- W2 t: w- N
                elapsed_time = nes->cpu->GetTotalCycles();7 |4 A% |0 J: A: t
        }
) A6 H, P9 O/ o6 h- U% H#else1 l* R. {$ j7 q+ B: |% j
        elapsed_time = nes->cpu->GetTotalCycles();
3 G% p4 B# o2 L7 R& N#endif! h9 y8 y! A- T# r) i
}
( G7 L9 x9 R6 d1 C3 p# ^6 V
- _8 b6 _; r0 C- ^+ ~  E// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
  c- L. Y7 z; o. f) Y" BINT        APU::GetChannelFrequency( INT no )
" g8 {# ^0 d8 m3 v2 x{
7 g, d1 {: m) O3 z: h        if( !m_bMute[0] )
& a4 M! o* J7 i: D6 c( B5 f                return        0;2 a$ C; i7 X! J0 z

/ @3 g) p( f2 S6 W9 N4 C; g  X) w        // Internal
2 h  d9 I# C0 C* g# E% ^2 W- O        if( no < 5 ) {
6 f% q% U; S: |6 |% ^% B                return        m_bMute[no+1]?internal.GetFreq( no ):0;5 u9 L& r! w$ [0 p- e' w
        }) ^* c# R9 T4 G* D' K! h
        // VRC6
6 T- R6 `* t$ h# D1 {        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; w  p+ g6 V3 ~) M' P0 m
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
  j; R; c2 Z) c6 P        }& I2 H6 |, \2 D* F# I
        // FDS5 f8 b& i. @8 k9 v
        if( (exsound_select & 0x04) && no == 0x300 ) {0 G# C: `! V" E9 {# \
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 l7 G2 h9 v- u1 i+ L) U        }, L, n& i0 N/ Y1 }$ h' f
        // MMC5
6 L* d# o0 n" y# t" K        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {7 @- q& I9 t  l# i0 D
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) e) e! J6 o6 o, ~( Y        }& k$ U3 ]. G- x7 U! M! J
        // N1061 b8 Q! V/ w$ M& L! l% O. z( u& K
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* d' S8 T: A; S9 ^$ Z& P& L: ~7 ?
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;% s9 {+ O0 p/ V
        }
% N' x% x& G8 }& v5 ~  P# R: c9 a3 A        // FME7
% q, i& C2 v- M        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% L" R4 u6 K2 z3 e) q2 B
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
6 Q9 K* C1 v( D4 _; |2 A        }
' y( ^, @) Y" b% u1 S. d3 p, @" F        // VRC7
& }) h1 f9 a% ?8 u% q4 F        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 ^" B, M/ f: d; `                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
# I$ E# u0 [1 `9 R; y* Y        }
% W9 s" f6 |- M9 ^        return        0;
  }( n: }: ^% P2 E}
8 d: @0 E8 P# @1 G, A# n! [2 p. t1 i7 T; p. f2 i6 o: I
// State Save/Load6 K1 ~- c3 ^& X, l, r+ Q
void        APU::SaveState( LPBYTE p )( U( i/ }) R0 X: Y4 S. ?9 `
{/ V7 ~3 a0 R- D0 x
#ifdef        _DEBUG
( _! B* \" Z: D. s4 X4 K$ }LPBYTE        pold = p;* |: D1 }% ]% S* k+ ~* i! e
#endif
8 Y; f7 S8 F6 h# P  o9 g6 x! q  J+ `( C6 ~, x1 C0 g; }! J3 m
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
4 q# S( f; n7 @" }* V. m" Q: f        QueueFlush();% ~  @' [" O! y9 v* r0 I9 r% Z  m, J2 \+ L

" k9 }4 H- ~/ ]* ^& V7 o! m9 {        internal.SaveState( p );" @' Q& T* C9 I6 d( q" ?9 P$ j
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( z9 V! U2 C/ r. Y" W0 Y
; ?% p* a4 F$ }- w
        // VRC6* t  E% x6 O4 g  |6 F
        if( exsound_select & 0x01 ) {* d' L6 j  k& u7 f4 Q
                vrc6.SaveState( p );
) Z0 A( j  c  [3 k, N                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. S$ J5 ]9 `& O$ B, V
        }
4 c3 d* T2 c' X) \, w        // VRC7 (not support)# {3 r* E# A" T3 W& w" ^- h- K$ H
        if( exsound_select & 0x02 ) {
7 u+ V6 b- t5 ~% M# u' a+ w                vrc7.SaveState( p );% \! t" j8 H; C" u. D
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' R& u4 u( U. d" V* ?
        }
  Q/ T9 S& ]" ~$ {+ |7 C# Z        // FDS
3 R* b2 c- X! o6 P% W& t: ]        if( exsound_select & 0x04 ) {/ l2 y. `1 e# O% ]5 ]
                fds.SaveState( p );: w; S) ?+ E; s
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" J# n( f* @4 X5 S6 M$ w$ I  b
        }2 ^0 X3 p. H4 I7 w. d3 I* o, k
        // MMC5) q0 ~8 p& j( J" w+ J; _, Y
        if( exsound_select & 0x08 ) {
1 Q4 _$ s. B# o; `. `* b$ r0 N                mmc5.SaveState( p );$ G, Z3 Q* R7 P: U( p( ^
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" R3 `. [" o4 }3 ?# Z
        }
  n/ Z) `+ O: G        // N1062 U# F1 g: L! V$ U, E
        if( exsound_select & 0x10 ) {$ T! K+ Z0 e9 s7 G7 d  h- A
                n106.SaveState( p );4 ]  U, e+ T' g) E2 m& v& M& u2 w& c
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% f* @+ q1 W  n; p. t4 C        }% H* |6 n' \  I" D% h
        // FME7
) P6 m: W, M  K        if( exsound_select & 0x20 ) {
6 O( u, \% K  V! Q) `                fme7.SaveState( p );
  D/ U/ v# ?9 c$ }  S& l6 d4 Q3 B                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 D) U1 Z% }+ i8 I' Y4 u# n        }
% s5 M, T/ p' `% Z3 a( i' r; H1 Q; e' y# \: f6 k1 n. c
#ifdef        _DEBUG" N3 F' G# g1 {) U8 q1 B
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );: }2 l6 L9 Y: @& V4 B
#endif
4 n6 B+ y3 V( R2 m% O6 W}
8 u8 w1 v7 \. N
' b2 X8 [- q. q% Pvoid        APU::LoadState( LPBYTE p )6 ^% }$ X: ~; s; M
{
0 @% D& R( P% x# w9 m        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 W1 S# ?" E7 _! a0 Z( |        QueueClear();+ |3 @% l/ M! |

0 H9 v" P( y( H$ k  Y, L$ O        internal.LoadState( p );2 w+ L# W! Z% ~+ m1 J5 {! [! h% }2 w2 I$ k
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 V0 s* b! ?" j6 L  V
5 m" `* J& z: i! g) X        // VRC6
2 A, N8 c. P/ d* T6 n        if( exsound_select & 0x01 ) {
0 Y8 _2 F6 C! N9 h& L6 n                vrc6.LoadState( p );3 Y8 _* w( J4 Y0 s1 x- w1 w+ Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, y) q  K4 q" v$ r( }        }, {; ]3 \- }5 ~: C- Z0 j6 C% t3 @
        // VRC7 (not support)" }2 P0 v! t6 C& j
        if( exsound_select & 0x02 ) {8 D5 a8 P  E8 ]& V# ^
                vrc7.LoadState( p );6 D/ I* s+ E( g$ E1 x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, d/ q+ u- V  j& V% R        }( }, f6 E) H3 l. m2 j, a
        // FDS$ R% P+ b! ?  t6 }4 {
        if( exsound_select & 0x04 ) {" d; v3 u; j  o: U8 O
                fds.LoadState( p );9 I: E# p# }6 F0 W" C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' C4 q1 R( Z( L- _5 q+ g9 Y
        }
5 \- m8 M, P$ S0 @/ g* b& k        // MMC5" N7 h9 i4 Q# O4 z- Z
        if( exsound_select & 0x08 ) {
. h- b- o6 |  `) B3 x: G( C                mmc5.LoadState( p );
% e# q* ~# G  w. j2 p1 `& r                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& l7 ^% N$ t" r( w
        }) |9 b( y/ y, [' A' U1 ~3 u
        // N106
9 A6 [: e: g- O        if( exsound_select & 0x10 ) {0 @' I  y& F6 c/ w9 T
                n106.LoadState( p );8 z) B+ i! B1 u, L; b
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 l/ K9 o5 s( a6 R) A        }; r8 w( y" x5 u+ i. M$ ]
        // FME7
3 K& M* B, Q. }" T' [& W/ j0 l        if( exsound_select & 0x20 ) {9 h: y/ E. n+ k
                fme7.LoadState( p );  ]9 L, V7 M$ [( T/ }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding, T9 V8 m* U- E: {, Z/ ?
        }8 A6 n7 l' h# s4 @
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% L0 t$ m- [( |可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' p! x2 b; D! b% W# ~$ m感激不尽~~
0 G5 M. C. n: d) \" g: L  e
恩 我對模擬器不是很有研究,
( I3 e6 N" j* z% @1 Q$ {9 C雖然要了解源碼內容,可能不是很困難,
7 |+ K8 O1 c9 s: j8 r( k3 E! T不過還是要花時間,個人目前蠻忙碌的。
) j/ z' ~# n* D
6 _3 M2 _4 R% D- R# \: d給你一個朋友的MSN,你可以跟他討論看看,. ~  E  ~1 E8 e/ H  ?1 U2 p# [
他本身是程式設計師,也對FC模擬器很有興趣。
$ i7 ^# K3 V" _7 e3 O. W6 U
. y6 t4 {" y& m9 _. HMSN我就PM到你的信箱了。
5 N. q4 ]6 V1 e+ q. N/ Y# Y/ j5 C2 j; \& r5 m  Y8 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 发表 2 C; r7 w8 r( m- P: O
呵…… 谢过团长大人~~

% Y! g( ]2 h5 Z; `$ b
0 s1 @- N+ u, T$ c哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 2 P+ J7 M$ p0 X# F
团长的朋友都是神,那团长就是神的boss。

/ E. S/ W2 O# B/ R% A哈 不敢當,我只是個平凡人,
- M$ A9 s1 ]7 `要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! [5 o5 V; {( U& {8 i' F) e
ZYH
3 B% b9 H0 c: ?) R  tQQ:4147343062 X1 L9 P2 E4 ~$ @' K
Mail:zyh-01@126.com
2 s$ }/ T0 x5 P9 d% p3 y/ p& B
4 c6 j" S+ [4 A7 X, q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! P% e; g6 p/ p3 |再次对团长大人和悠悠哥的无私帮助表示感谢~~

5 @0 A) K0 V  ]4 l5 S: R8 B5 l不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-20 08:01 , Processed in 1.110352 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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