EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
7 P+ r$ s0 D& U楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. Q7 W% P+ o6 C, X0 w# t) M
这里有相应的模拟器源码,就当送给大侠了~~
7 l" z& m5 Q; a4 ]+ yhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- I( L! F7 s* `9 X  |( w( W5 R能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ r7 r6 H7 n2 v& U1 F- A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% ~9 J% F. a7 Q) O
这里有相应的模拟器源码,就当送给大侠 ...
) R$ }& e# A. R& g5 F
聲音部分(Audoi Process Unit = APU):) P- _1 F/ ^& I8 P6 o. b0 X4 r/ ^! p
.\NES\APU.cpp  G* J# T& h5 f/ C7 r  \7 Z# v
.\NES\APU.h
. s  _( t; F$ e- U2 m) t9 s3 Y' l/ V" ]) M+ F

9 `& }( C" b" Q0 W影像處理部份(Picture Processing Unit = PPU):' _. R# I1 h% c; F) ~+ \
.\NES\PPU.cpp
( H$ s# n+ v2 s.\NES\PPU.h
6 @2 L8 l  Y7 R* E' [: g" I- G: x' {% W  s% `/ o
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:7 E3 i' \) T  P4 `% B
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
2 Z% _! i: ~) F  y% \8 l% C//////////////////////////////////////////////////////////////////////////
+ m1 C* _* h% D8 d) L//                                                                      //
& R( t1 H- `! u//      NES APU core                                                    //- Z2 O2 s: e2 x3 |2 G7 Z
//                                                           Norix      //
+ g# M5 U1 C( ^" l; o//                                               written     2002/06/27 //! \% {) h3 R5 D) E# A, j/ H
//                                               last modify ----/--/-- //
9 S  q! \7 b  ]2 l8 y; c1 E! v* s: G2 K//////////////////////////////////////////////////////////////////////////
; Q3 i' K% A2 n  S$ b- T#include "DebugOut.h"+ j" [9 d: C5 ?. \9 N
#include "App.h"
6 e! A. w  w. N5 |#include "Config.h"$ c& s1 V; S1 q7 F

, X; U' T5 J/ p9 \5 R( G) h#include "nes.h"
( K! I  c, ^1 m' u# J9 A5 i" M! P& \% q#include "mmu.h"
+ [, J9 r# |/ [#include "cpu.h"
: q/ H" s+ E$ Y6 U#include "ppu.h"
8 ^( p4 r3 W5 E* r#include "rom.h"
( Q/ J1 d4 X6 Y3 ?& ^5 ]  H9 P9 Q#include "apu.h"1 g- P4 |+ N$ }5 H2 k

# \9 k1 `$ F/ f" H, _: q( ]// Volume adjust
6 W* [6 @+ {; \0 S# v// Internal sounds
4 y/ }$ P' }' r) H$ T#define        RECTANGLE_VOL        (0x0F0)( Z1 C9 N: w  p
#define        TRIANGLE_VOL        (0x130)
- A. j! p( B3 ^8 n#define        NOISE_VOL        (0x0C0)
" O' M; J  X- Y0 @* U7 t* U#define        DPCM_VOL        (0x0F0)
9 z* D+ ^: }2 y7 y/ e( L// Extra sounds+ G; F- ~. T" v5 ]+ O
#define        VRC6_VOL        (0x0F0)3 d* J; Q# ^8 r- g8 L
#define        VRC7_VOL        (0x130)6 a# r0 F% j. H1 V  v( X2 [+ a! O+ Z
#define        FDS_VOL                (0x0F0)! P* T/ X% D# m7 W" p
#define        MMC5_VOL        (0x0F0)( t4 v- q/ v- g1 F) V
#define        N106_VOL        (0x088)
! Z- Y$ B1 a8 Q9 a! D0 N% F#define        FME7_VOL        (0x130)0 F8 E) }; W' m( ~. H# H
9 j6 q4 u5 c7 P+ k7 \' Z/ M
APU::APU( NES* parent )
$ {# z7 M% f& s: e/ O{6 w8 _& G+ X6 ?8 c
        exsound_select = 0;
9 S7 w# P3 j; r7 J( |7 f5 B8 G+ d6 @# D& t: u" m$ a# r
        nes = parent;
% Y: o) E! Q9 `/ S1 i- H; C        internal.SetParent( parent );
3 h% J( o) q5 o, l; U8 a
' c* W! e5 s6 P: s        last_data = last_diff = 0;
7 {# c4 d2 E3 q% z$ r  T4 N2 L# C3 e0 ]) _
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );9 D7 Q9 K2 S7 t& M' g$ G

. R8 F5 k( w4 O( W5 F/ v5 D        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
  n( v' a* W0 f& y, \2 R7 i        ZEROMEMORY( &queue, sizeof(queue) );
# f5 A. `5 m) ^. P        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 a- |# b) h" S7 O) b) D
0 H8 L' u, R' K' ]7 ^; y
        for( INT i = 0; i < 16; i++ ) {
4 p8 o3 O2 k7 f! B0 q+ d& v                m_bMute = TRUE;
; G0 f; m5 E  F8 c+ _        }
" L: [0 W2 B/ D9 o$ Y, V}
& T) |4 _8 F$ h" ]. l, d1 g! A1 k9 p$ Y
, V# x) L' T: t9 L5 j# T! }APU::~APU()$ B- ^2 D3 a8 m) H" F
{
5 L  H4 {7 z* a0 A& z9 V9 H& L* [& O}- f+ p1 d; ~( W( X# d9 r
6 U* a* F- W( o% U: w4 q% C4 _8 f
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
- r2 Z- L' U0 `# Z5 f- b{
1 j2 P/ x! Q4 C1 M        queue.data[queue.wrptr].time = writetime;
- |  v0 d& d0 W* c/ Q& q        queue.data[queue.wrptr].addr = addr;
, n$ T0 T, s. f0 A$ e        queue.data[queue.wrptr].data = data;/ ~1 s( X% r" F- U0 @; X! E
        queue.wrptr++;
& P; ^- J: W6 u: U3 [+ S# K+ O        queue.wrptr&=QUEUE_LENGTH-1;
  Q6 Q! T8 A, @& A/ q        if( queue.wrptr == queue.rdptr ) {2 V2 X! z( A. U. k* q1 T" h
                DEBUGOUT( "queue overflow.\n" );1 E' z8 V7 n' k8 n" {' Y) ~
        }
& D& V% |- Q4 e) W+ K}
. d# ~0 G* x# z8 V) Y3 i5 m. {" |- h* ?0 _7 ~
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& V$ N  S7 r9 S5 [{
  M6 y2 X. y6 |9 ~* u/ C        if( queue.wrptr == queue.rdptr ) {
- V" Z7 U* M6 S; V. w                return        FALSE;# Y5 \; C+ {2 P/ m! ?" o0 V  Q
        }
+ D- ~0 `4 l- \" B$ k        if( queue.data[queue.rdptr].time <= writetime ) {
2 b( c1 D4 c/ h                ret = queue.data[queue.rdptr];9 w) D# @5 i! \9 I6 L
                queue.rdptr++;$ o7 G; [5 T+ m- V$ I
                queue.rdptr&=QUEUE_LENGTH-1;
+ y: X5 H) _4 o7 W9 {                return        TRUE;
) _& c! p! \! i7 i, t* L% U        }+ N) f+ S; d  h8 G$ Y0 X* U3 [! F3 f
        return        FALSE;
, x5 W# h$ f$ a( o}
/ @) t; G+ f. a  A
( p& u7 g- m- ~void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; g4 \9 S' y; K& I" r' r0 }{  Y" C( H+ m2 P
        exqueue.data[exqueue.wrptr].time = writetime;, @$ i- I! ?: \" O- t; M3 @0 k" ~. J
        exqueue.data[exqueue.wrptr].addr = addr;, E' B3 N/ ^3 l0 P
        exqueue.data[exqueue.wrptr].data = data;
- Q6 @4 ^5 ~# a; v( I* ~  s        exqueue.wrptr++;1 N" W/ N' c. F& q
        exqueue.wrptr&=QUEUE_LENGTH-1;
7 x: L. V2 {5 a! {3 h( q4 {  A        if( exqueue.wrptr == exqueue.rdptr ) {
6 U! X& l- @/ ]6 [- P/ y+ v                DEBUGOUT( "exqueue overflow.\n" );
2 F9 ^- F7 w/ ?/ p: m        }7 ?2 d) Y" t# P! q* s; P
}( }% p/ v' Y1 d% X+ c) Z% K! S

( h0 K$ a$ v) g, `BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 S% f* k* c* h, p; u% a; O' v
{/ z# ^. S! Q4 x+ Z4 s, H
        if( exqueue.wrptr == exqueue.rdptr ) {
' c! M. o, L% q( ?" S                return        FALSE;
2 x. b* [3 r; [5 U- J: R. c0 h* F        }% e+ G! b- T, j+ U. B* A$ x
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
# ~8 s) P+ t8 c                ret = exqueue.data[exqueue.rdptr];+ Q' C4 M# W: C1 i& n
                exqueue.rdptr++;; G& x  A# H" e6 T5 m: C' A
                exqueue.rdptr&=QUEUE_LENGTH-1;
+ M9 V: j+ R5 t; V) M+ U                return        TRUE;# l9 Y( I3 T8 u3 i0 e7 E7 t, }1 T
        }
4 n. E* _& X; Y$ a0 @- w        return        FALSE;. |2 D4 Z+ J  s
}
  A& I" @7 I. S
/ E+ `: J3 w% Y& `void        APU::QueueClear()
! s9 j8 r* ~6 k9 {1 }7 q% U{1 k- N' C1 k9 z9 F; Y9 D
        ZEROMEMORY( &queue, sizeof(queue) );( E0 J3 Y( _& J$ o- P
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ O# }* M- z4 g4 X- S
}
3 |5 H. }$ c. {* m6 V( ~! S
) X, b/ Q. n% T2 G" l. }0 Uvoid        APU::QueueFlush()
2 P" A; R4 q3 j7 `6 U{1 m; z: W, l% R1 B: `3 T+ n) X  N* p8 M
        while( queue.wrptr != queue.rdptr ) {
( [8 I5 V3 M6 X6 z3 ^9 d' m$ ^                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );% Q8 [2 i: L) G
                queue.rdptr++;! U8 ~* I+ \/ F, X9 t; R
                queue.rdptr&=QUEUE_LENGTH-1;
9 L, ?$ P3 U- H: d! S) X' T        }4 O" \& [  k, k3 m! E
( e" ^9 @8 w4 @+ |
        while( exqueue.wrptr != exqueue.rdptr ) {
' s8 V% D9 W: F/ g# `! k2 c                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 ]# V% e$ _- x5 {$ f, c
                exqueue.rdptr++;# D5 v  D# y) ~' D
                exqueue.rdptr&=QUEUE_LENGTH-1;3 S7 e" p5 e* w$ h0 e; m
        }
0 q( m+ Q$ H4 x0 t7 |}
# z& a6 f' I. t3 u9 u) ~
" G9 f4 ?* M9 |" O# b  m! b5 O" gvoid        APU::SoundSetup()' y, Z6 p8 k) e3 `* z7 C% D
{/ ~7 b! o3 S  {) ~' n
        FLOAT        fClock = nes->nescfg->CpuClock;5 Z( c) U# X$ L8 t" Z3 |
        INT        nRate = (INT)Config.sound.nRate;2 p( g5 j- M6 G/ l/ b
        internal.Setup( fClock, nRate );* N7 n- ]% t3 j" x  u5 U. G2 J" b
        vrc6.Setup( fClock, nRate );
) ?$ y2 p0 m3 b2 t8 s2 J/ p4 ]* X        vrc7.Setup( fClock, nRate );
6 S9 f+ l- j, F7 A0 a        mmc5.Setup( fClock, nRate );! g4 P/ C% j5 n5 h# G% R
        fds.Setup ( fClock, nRate );
8 |: K  O2 U; q3 b, G3 C- p        n106.Setup( fClock, nRate );
% a) {, `/ J, \5 M2 L        fme7.Setup( fClock, nRate );
5 F* S1 Y8 g) ^5 s}2 t1 x+ T7 Q, |& O( C6 ~$ h8 U. ?
  o! U* q& Q9 b, }6 N8 X
void        APU::Reset(): J0 B, ?! e, T
{
  ]. ?1 e' L1 ?2 B6 F+ Z        ZEROMEMORY( &queue, sizeof(queue) );
* {# s# k. F9 `6 E        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( f4 P) G( A. J. V% ]8 _% m1 H% p# x! y
        elapsed_time = 0;
& G" z% o+ @9 C+ f
% M. v& {4 k& j$ ~        FLOAT        fClock = nes->nescfg->CpuClock;
) D- h% D6 K5 }4 d        INT        nRate = (INT)Config.sound.nRate;; B3 w( z. j; R/ A  o
        internal.Reset( fClock, nRate );8 w; T; C" K* ^
        vrc6.Reset( fClock, nRate );! @# G) I5 h$ F) ?
        vrc7.Reset( fClock, nRate );* _/ W4 o, p$ v! _
        mmc5.Reset( fClock, nRate );' O2 Q( o  ~% Q( f4 N" X
        fds.Reset ( fClock, nRate );! {! Q( k6 g5 l4 k$ ^9 E
        n106.Reset( fClock, nRate );
: l. Y. i2 R& Y        fme7.Reset( fClock, nRate );
- ^, H* X  A, }- P% V4 k, M, h  Z/ B6 R; U6 ?- L- T
        SoundSetup();/ T0 I6 S; Q5 D  Q! A! ]0 q. t" B1 Q
}( \( l, O4 X8 C* |8 b

4 L$ \" f. m( r9 C( Xvoid        APU::SelectExSound( BYTE data )
8 w) O* V% U6 ]( e" m% v{
* [5 \8 Q8 i7 v* Z        exsound_select = data;0 B0 K4 N; O7 w" F4 p
}+ r2 [' [! R6 E9 B. Y: F2 S( ]

1 g( G# x$ m7 ]* k5 {- k' C$ uBYTE        APU::Read( WORD addr )
. k' H# b, ?$ ^- Z3 k/ N! k{
; l* m4 k) l2 ^  l        return        internal.SyncRead( addr );
0 G( ]' _6 y. n- P8 |}# @0 v- K( ?. ^7 @( S7 g( h* I) k
) F; K: v. M  _6 z% l
void        APU::Write( WORD addr, BYTE data )
- h9 G! Z, d7 s) X$ }# X. y5 V4 Y% t{
8 z5 g6 M. ^- @$ ~5 }2 j# {7 g        // $4018偼VirtuaNES屌桳億乕僩+ i' P1 a4 U3 L3 W7 H/ t
        if( addr >= 0x4000 && addr <= 0x401F ) {
$ x6 R2 r: d9 j4 L& M, ~& X+ q                internal.SyncWrite( addr, data );
9 O2 m8 A2 Z; w9 s& p) ^                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
8 P6 }. z) ~- k5 z5 _+ _1 W  i        }
8 F1 ?  M: N! @( a4 V( x/ o3 f* B}6 j8 W4 k; m8 X3 j
: f% E; C8 t+ S' z0 w; C0 R
BYTE        APU::ExRead( WORD addr )
$ [9 K8 r- ^. h1 S5 z: b{
9 R' b3 w8 H( [. V% J' Y, M& b& M* ^5 _BYTE        data = 0;9 Y) x. v: g6 X$ V

+ N6 |6 W9 S, {& L! }        if( exsound_select & 0x10 ) {6 Z- Z; W# u4 H! o0 H
                if( addr == 0x4800 ) {
. J/ Z# @* ]& K% {                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! `1 J- L5 }4 Z
                }
' _# _5 {9 r* v/ Q2 m        }) s' N) v) u; t9 U& j& \
        if( exsound_select & 0x04 ) {
4 s8 _: i( Z; [) E+ t' G, o2 w                if( addr >= 0x4040 && addr < 0x4100 ) {1 J' d/ ]  u- j1 j1 o/ Z7 I+ G
                        data = fds.SyncRead( addr );1 o5 j1 h; w/ ]; v5 T" P; ~
                }
3 H; K1 F# v- H1 k8 D3 P        }. R4 i" ~2 x9 s7 M
        if( exsound_select & 0x08 ) {- L% P' t! m. c2 j
                if( addr >= 0x5000 && addr <= 0x5015 ) {, U  K3 g5 b$ B! O- G3 E
                        data = mmc5.SyncRead( addr );4 W/ R5 N) x- z  r
                }
( ]2 n, N% `3 {7 i9 R& p$ X0 s        }
7 J. h+ s1 W4 i. D, i7 s" h/ y8 Z  g; O7 K/ J! V' g
        return        data;
# c3 w) w7 m9 W" m9 ~. B6 S& H}2 S/ n! e7 n6 }- s% o
- Q4 }. m" h. |
void        APU::ExWrite( WORD addr, BYTE data )
8 u* p, f7 g# q6 X{
0 l, v: N6 \" u4 E        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );( x/ ?1 Q& a( D( }8 N  C

/ q/ v7 G% O- j; w! z5 R4 Y( K8 G        if( exsound_select & 0x04 ) {7 U' c, t! }- r0 o9 c
                if( addr >= 0x4040 && addr < 0x4100 ) {
$ N* o; P6 r% o6 I  O) x                        fds.SyncWrite( addr, data );
2 e" N! n" i! D- t/ A- ]5 u                }
  [4 E# o1 H8 B: g2 b        }' @% @$ T" ?+ \' p9 o  F
3 u* b' \. }$ E. l& h
        if( exsound_select & 0x08 ) {0 u5 l2 v& n/ T" i4 R4 X0 S5 |1 |
                if( addr >= 0x5000 && addr <= 0x5015 ) {3 k, A$ R, ?. l( g: N0 w. ~
                        mmc5.SyncWrite( addr, data );
; |! e4 f$ S& i3 j* [( e, ]- G( E7 p                }
% J- o% P4 ?) n& t6 H9 e7 V6 k+ U        }) K1 m4 a% r- p0 c+ a% x
}, ?+ M" [* b! D& f  C5 ]' h
( Y% x/ t  _: h1 i9 N. k
void        APU::Sync()
$ {1 c3 [' O' j' a; q{
" P* ]' e: I; Y! w}
* R+ z# F5 S3 _  v
, C3 a" Z7 o0 r" {' M: t: @void        APU::SyncDPCM( INT cycles )' F1 l/ i+ Y& ^0 g9 Q
{
1 k/ G. Z4 u7 e# A" v        internal.Sync( cycles );
* p# y* ~% W% [  B, @- H' l
5 n5 g! t, B/ F+ F7 @3 C        if( exsound_select & 0x04 ) {
/ `% f& a0 H7 C$ ]( e2 x- p+ V                fds.Sync( cycles );* b" m, u9 m+ g) Y: M5 t% }
        }
7 S; b5 k9 h, x4 z) k1 |        if( exsound_select & 0x08 ) {
! L/ U0 P; }. E* n3 L; @4 T- J                mmc5.Sync( cycles );
/ j+ S. w! b! Q( L& }, M) }        }
" ^, u: W$ ?" d5 X}" {, l3 n0 b8 F7 h, e

) f2 \: z2 v% x0 hvoid        APU::WriteProcess( WORD addr, BYTE data )& }, E$ U% M" ~+ d5 y! U4 P$ [
{4 ^9 l1 R" R9 i* e8 c3 m
        // $4018偼VirtuaNES屌桳億乕僩
! @- L, G8 T1 f8 X. b        if( addr >= 0x4000 && addr <= 0x401F ) {9 J# c' @% X4 L3 g
                internal.Write( addr, data );8 \0 e& w4 d2 P8 l! R, ^) W7 P
        }  U3 p7 O+ d) E$ R3 S
}
* q& Y% X( G# E/ ~& h! J  o7 {; A. H- R3 V
void        APU::WriteExProcess( WORD addr, BYTE data )
. f! p8 ]# d: ]6 K3 r' [: m2 i; ^{6 g4 m( V% I* ^) P- G) z
        if( exsound_select & 0x01 ) {6 C& q/ O, c9 Q$ `* Y9 I
                vrc6.Write( addr, data );$ b0 P4 p, e/ b* D5 u) [
        }1 y( ]* [- Z3 W0 u' N
        if( exsound_select & 0x02 ) {3 w9 s# ^% E0 F; i2 P; |
                vrc7.Write( addr, data );
$ R* g; q( R9 q4 V        }
% g; ~, g/ O) r; R+ T+ v0 O! W, j        if( exsound_select & 0x04 ) {
2 k6 @; n0 f$ P8 O, ^$ P( N9 J3 _                fds.Write( addr, data );$ y3 S9 p; L. a$ N7 ~7 t- m
        }; t1 p, {& ~/ X
        if( exsound_select & 0x08 ) {' b# Y$ o4 s! O( k4 Y
                mmc5.Write( addr, data );
' L* ~% Y5 V3 }2 F5 b1 A/ N        }
3 N& ^7 V& Y" `$ Q$ N4 t4 ^        if( exsound_select & 0x10 ) {
4 \. b0 P1 P" L: z8 X: T                if( addr == 0x0000 ) {
" u3 h# y+ e7 G                        BYTE        dummy = n106.Read( addr );
  n! G2 p$ M3 d0 I. r                } else {
) q( [/ a# r( D; v5 J                        n106.Write( addr, data );, b0 U5 E# G6 D7 A& f
                }
) ?; f3 E1 `9 y0 V        }
/ W- R+ @- g& s3 W4 o        if( exsound_select & 0x20 ) {
) k1 h$ i* |$ Y! o3 Z3 x, B& t                fme7.Write( addr, data );2 [* q- r( l, R  J) Q4 i
        }
9 K# ?7 |. j: b. P, g2 b; [5 g, s}
/ |2 s# L2 c2 O- g8 W" K2 G& z! \/ i5 F) u/ L
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ): D: j8 P3 A6 n9 e# P# T( T
{( `* k4 v6 H( i$ I+ s& `
INT        nBits = Config.sound.nBits;
5 D1 Q" z1 w* a0 h0 b- F+ dDWORD        dwLength = dwSize / (nBits/8);
; E5 \: f: F+ O& N4 N$ WINT        output;6 V( S- ]9 M( d) }9 V
QUEUEDATA q;
& v% t  r5 t- s. B/ H5 p$ `- uDWORD        writetime;# o9 S+ v0 N8 q9 h% t6 ?
/ c; x4 H1 W. G, P* @
LPSHORT        pSoundBuf = m_SoundBuffer;2 I* m$ t4 A, i" ]# S7 m
INT        nCcount = 0;1 J$ w7 B# o/ D' x/ H$ y! c
( `! a- ^% ^: m/ o3 y
INT        nFilterType = Config.sound.nFilterType;
" L# ^2 f3 A5 l" C" s0 e
& E* r, n5 f0 f        if( !Config.sound.bEnable ) {
7 ^  m2 A% d) u& w" V9 O                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );& s. E! ?& e* h: L! S& n# ?
                return;4 z7 ^7 ~$ F8 ^4 P/ z8 k9 s
        }  a8 y- c# y, @) b* T. e7 ~3 T' B
7 v5 D' ?6 P) d) n6 A6 @
        // Volume setup
0 u& a6 p6 t$ ~4 p        //  0:Master6 r( I- G! C& e- X* u+ u# Q
        //  1:Rectangle 10 q5 V' R! s& D% ], t# m
        //  2:Rectangle 2
) n$ M& J. b+ d; R8 J        //  3:Triangle
! s. \0 G8 X( i) ^+ M        //  4:Noise
. V& Z$ m- }3 @# w0 n3 ^- G( j        //  5:DPCM
* y. y- c; M5 N0 W5 g  U        //  6:VRC6
  c3 Q8 n8 Q; w* G" i        //  7:VRC7
1 i) ~6 s" H& i        //  8:FDS
  g" {* w1 F% ?        //  9:MMC5
, R7 h, K1 B" F! I( S- _        // 10:N106
& f+ p- U: Y! H" C: d( ]7 V0 E        // 11:FME7
3 i: P9 W: m8 W* Y& h; G        INT        vol[24];/ }. B- Q" Q+ m' b' U1 ~
        BOOL*        bMute = m_bMute;2 }* A. A5 N" z0 i! h+ J
        SHORT*        nVolume = Config.sound.nVolume;
' t6 X6 I7 s3 z1 Y
6 T" {, {7 K* @' D2 Y+ U        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
+ c. B7 m0 b: [4 J8 _) x
, r  w; e+ M" |* w# B$ S/ W        // Internal
; Q4 c4 u" _" ]* j! C) L& @0 x        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; y3 C6 A9 e9 I6 H2 c- [' Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;3 y2 J, T4 [/ s+ i
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;8 L! s0 b1 t/ Z- V, V
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
, {2 J8 m& X! R        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
* e3 s5 d0 S1 R; N" M) i6 w; W& S7 s) q
        // VRC6
. t- T1 D$ r, U2 u# w# V        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* C- f  G) ^) u9 G% p  d        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 S8 x- P( b- m4 r3 ]% t. m
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) l, ^. O) x& T( ?4 G" c, i4 b4 p
# i& M& R% A' M) h0 J2 r% n4 n6 |        // VRC7
: A- `# b! a9 r2 U# X% U. s: M        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
1 g0 y3 d2 r) @9 f# G
  S9 g5 N7 c' g7 ?        // FDS+ q9 r8 _: C  R9 [
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, ]6 V) ^- ^/ o. J8 k: c$ a2 B+ S; ?. n0 X. s7 h' ?
        // MMC52 Y9 e; X7 q% p! ~' }* [8 `, V" E* P
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- I0 `: ]; ]9 W0 B5 ?0 S7 v6 T
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 o! b) j6 N" l, M* R+ O2 w        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ \7 W! }0 C* e4 }0 G& O+ k( u* y

8 Z" {  k. k6 Q* d        // N106
* P- J! H# x% m9 W+ L        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 K' x. T8 |* A+ M
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' |* u3 H, A% z# Q. w
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! Y) ], M! l8 U; u1 D& L# F
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ s3 k! Z# c7 y% A* Z2 [* n5 _8 I* B        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# G4 ]- L' y: w" s9 w& j! E        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, A! q6 k7 ?- q2 R) L        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 T# t8 `2 W! p4 \/ E) G
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. e% `% Z' T9 D* o
( g6 V6 P5 a+ g  A. h4 d
        // FME7
3 ^/ a+ y2 w( a1 c$ _! \  [" u        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 }9 ?  g5 m0 o1 ?4 W$ P" ]' l
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! \% h4 R/ |  i8 @, r7 f+ \8 i
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 L4 O# v. k- ~6 @6 d- O  C

# \- z$ i1 Y1 p% ^. E: |# z//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ {# G; A2 y2 L( z! p        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;1 I* ]! @$ ~' K- F4 a0 y
& h7 {1 X$ W- ], o; n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 }1 w9 E" n4 \7 x4 d0 q        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  k( g. T4 S3 n/ T, y  b8 J                QueueFlush();! w+ ?- s& r( I. C
        }3 D  ~3 G6 A- `6 _( {

6 B" B2 g; _  f2 ?  w0 S8 r        while( dwLength-- ) {
6 g- S. R' L- F1 X                writetime = (DWORD)elapsed_time;* F- T" H& U2 n; J4 h
; o: G# A5 _6 n: R- W; O/ u2 N
                while( GetQueue( writetime, q ) ) {+ O" Y4 N1 J/ T( z9 \
                        WriteProcess( q.addr, q.data );3 i0 {+ G* P5 t6 m2 l+ [
                }
0 b8 _9 @+ T( E% d: U4 B+ ]4 }  v! X, l. U0 A% ?! u+ T/ Z8 f
                while( GetExQueue( writetime, q ) ) {
9 R" [8 w) U8 `) a# X# }                        WriteExProcess( q.addr, q.data );
3 v/ f6 g( O2 I, ]3 B& L) C8 V                }
- y% [! E( F% d( v2 ]. Y
6 Q* S- w$ h6 a* l$ d: ^                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  \! ~% a$ j3 X; F* I                output = 0;9 B! I6 v' P, g
                output += internal.Process( 0 )*vol[0];* l; o3 X. Y' h$ Q1 p7 w7 J
                output += internal.Process( 1 )*vol[1];3 W! @  Z% K! B8 ^0 c, w
                output += internal.Process( 2 )*vol[2];
$ R- h, f3 ?% R                output += internal.Process( 3 )*vol[3];. b. t9 m  x6 h5 l& a6 x0 E
                output += internal.Process( 4 )*vol[4];  J$ m. j- z& Z9 ~4 L! W6 k
0 Z  n! E( g* V, X+ a6 M3 l, I
                if( exsound_select & 0x01 ) {$ m& X7 R& T5 y- X6 F6 x4 L8 ~4 k  m/ S
                        output += vrc6.Process( 0 )*vol[5];' s* e+ e9 l, i5 ]; O: M
                        output += vrc6.Process( 1 )*vol[6];
5 h+ s; U; E5 n: S  B                        output += vrc6.Process( 2 )*vol[7];6 v+ o, B& F( z) [7 K( ~
                }1 @8 D) m1 z! M& T' J0 z8 ?0 S# k
                if( exsound_select & 0x02 ) {$ X  z; I$ d, L: x
                        output += vrc7.Process( 0 )*vol[8];
* O& n+ w2 _  W. e4 l5 v& V: A, r                }
* i2 o9 H6 A; J# [" b5 [( _. d                if( exsound_select & 0x04 ) {" M3 U9 A9 E' O! _- h' f2 y
                        output += fds.Process( 0 )*vol[9];
8 x7 q5 h  c7 L8 k+ h                }: D3 j1 k& x* v2 d, N
                if( exsound_select & 0x08 ) {6 y$ a; }( M; ^, F+ b; H/ n% j
                        output += mmc5.Process( 0 )*vol[10];
* x# }; a/ a9 z' A                        output += mmc5.Process( 1 )*vol[11];
' y3 z) z- b, s                        output += mmc5.Process( 2 )*vol[12];" }; b. X' @5 K) k% s" E- |2 m
                }2 W0 U8 E, v3 T: r  g
                if( exsound_select & 0x10 ) {
* P5 @/ X2 a6 Z! D1 O                        output += n106.Process( 0 )*vol[13];+ C# n8 O- m: Y9 M! b
                        output += n106.Process( 1 )*vol[14];
: r1 t0 k4 A3 H* j& x& T                        output += n106.Process( 2 )*vol[15];
( @# a7 d2 q0 M' W+ G$ ?0 ^                        output += n106.Process( 3 )*vol[16];5 V8 E% B1 [9 g. g1 t5 {" ^
                        output += n106.Process( 4 )*vol[17];
, e) V( i) D4 `1 D' s3 C  I0 q                        output += n106.Process( 5 )*vol[18];
# j; @: V& z) f3 v+ z7 Y                        output += n106.Process( 6 )*vol[19];; f$ e  T+ c6 D9 A0 Y, z' Q
                        output += n106.Process( 7 )*vol[20];9 L* D2 `5 s( c+ k
                }4 S4 n% o( t$ j7 ]
                if( exsound_select & 0x20 ) {
: E3 K# L, k% B5 d) M7 Q6 v                        fme7.Process( 3 );        // Envelope & Noise% X- _' r( m1 p  Y: r
                        output += fme7.Process( 0 )*vol[21];
8 X! [! J4 f  N! z" q+ R                        output += fme7.Process( 1 )*vol[22];7 H6 D3 ?) j# K2 S
                        output += fme7.Process( 2 )*vol[23];- g- m% @+ D% [% O
                }" P, d& q! a( a* U  }' e8 ~
+ l( \! ^5 _: t! j: e. \" m
                output >>= 8;
- P% U, l* h; q7 }+ t2 u
. u2 w! f8 y' A7 M                if( nFilterType == 1 ) {( l% c( ~" v6 Y4 c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, I% e% H' B2 I' U% I* X                        output = (lowpass_filter[0]+output)/2;
  D: q  Y5 |+ l; W6 w) b. o                        lowpass_filter[0] = output;
# D" d- F6 \- K7 p4 g5 r4 Z                } else if( nFilterType == 2 ) {
1 N; Y6 X' X& Q/ R# E* i                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)% w  ?4 k& Z1 m9 U8 b, Q
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
8 K% H' V1 o  j6 h( o1 T! T+ a                        lowpass_filter[1] = lowpass_filter[0];. J' |9 ~: }6 v& ]  A% \& M% K
                        lowpass_filter[0] = output;
) d# {- T4 N9 _9 [6 H2 T! @% X                } else if( nFilterType == 3 ) {9 N9 K% y! P' K# V  r
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 E! E1 A, B6 T$ n# A                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;$ D* J, d5 ]7 V8 I# f2 Q2 [1 i2 G
                        lowpass_filter[2] = lowpass_filter[1];1 D$ T1 C7 i3 i  U! S
                        lowpass_filter[1] = lowpass_filter[0];
+ d- m, l6 `; E$ I' h                        lowpass_filter[0] = output;
5 }/ V) m* O+ g$ K& ?" @                } else if( nFilterType == 4 ) {+ Y& d% z7 n( w' ^1 z- \7 I0 k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); G. i$ i$ N8 S- t# s" Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
! Q4 o' S9 |2 j- h4 z* V+ g                        lowpass_filter[1] = lowpass_filter[0];
# q! O7 n  }2 T' ^* Z- C! x. K' Z                        lowpass_filter[0] = output;: U% n3 `* k8 y+ `6 m( n
                }) @7 F9 I. S# n

1 a& R* W* d- d#if        0
4 O5 Q* G$ c( f- O9 P% F9 F3 E  e                // DC惉暘偺僇僢僩
7 a, F0 f* C% ^' p. e9 @" ~4 V                {" e% Z3 f2 J2 D0 R! J+ s4 i" S/ d
                static double ave = 0.0, max=0.0, min=0.0;
( ]* L3 f8 Y6 ~  ]2 |9 |& e% d9 q                double delta;) l* P1 v7 G" U$ O- ^) b+ W! X
                delta = (max-min)/32768.0;
2 K% `6 H. _) B  U& N                max -= delta;+ {2 c- \% w1 z0 B' w
                min += delta;
% u7 T4 G3 D# d1 A; b1 y8 s                if( output > max ) max = output;
9 u9 K5 s$ e( @9 o5 H; s+ @                if( output < min ) min = output;$ ?  {  |# h" ~- x& G
                ave -= ave/1024.0;* n4 a! t: r: c- v" Y
                ave += (max+min)/2048.0;5 G4 v& {( i. O' |; i# O
                output -= (INT)ave;* b& c( z1 Y5 R5 b7 S
                }
2 L+ A6 u  B0 N1 }#endif( [$ b) R/ z8 B7 c$ |
#if        1
# _" C# \( B/ D2 ]5 n' R                // DC惉暘偺僇僢僩(HPF TEST), w) c3 z8 U) I, X5 {# ~
                {& a7 k: }2 f6 ~2 |+ F8 c
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& A& ^& O9 T! r
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 `% \+ A* ?* v& T  i                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ f' Z+ r+ v! S5 [8 r                static        double        tmp = 0.0;6 q% ~& k; w& c$ Z2 O& C. E: R( {/ R. P
                double        in, out;8 P; s4 u; m7 Q
: n. v7 q7 ^/ T! D2 G2 v( E9 t' C7 ]
                in = (double)output;2 U% l1 x+ S0 s' v  n' Q0 p, o3 ~6 _# P
                out = (in - tmp);7 G3 D$ {  {) K8 G; r
                tmp = tmp + cutoff * out;
% U7 @3 a% |# F& ]
, S1 ?1 o7 M- `" @5 c' Q7 `/ H                output = (INT)out;$ M; Y0 }8 J' h
                }
6 B. W( G$ l! Y* j& i7 Z#endif9 k$ e' N4 @* W2 y
#if        08 Z8 U7 ]2 I3 s4 U9 \5 P; Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
% Z" R8 l6 o6 C2 ]5 \                {
! B) r2 E- s2 `7 Y                INT        diff = abs(output-last_data);
; D9 h3 i2 q( _7 M2 G+ a6 v% W  r% U                if( diff > 0x4000 ) {
2 l# @# |2 e: U: N  p' l. M( D& V                        output /= 4;1 B* C2 ^8 r, _1 G
                } else
; {7 t! S0 J+ g/ ?                if( diff > 0x3000 ) {
  x9 ]) v5 O4 X9 i' p! L                        output /= 3;6 u! W0 C* V/ x# N2 j9 `, {- s6 n
                } else' i5 E8 J0 l: y0 }: K8 Q
                if( diff > 0x2000 ) {
3 |2 d  o+ W1 V                        output /= 2;5 [5 T6 h/ [+ l/ E5 N
                }
; r5 J+ Z1 P  I- g$ ^0 I                last_data = output;
" u' ^2 p0 Y/ J0 @                }
( D2 D! H% `3 `$ c#endif2 H9 A# w7 I6 k) g$ f- E. w, k
                // Limit
( M- w# g& H) L' e                if( output > 0x7FFF ) {( d6 x0 j, r$ y# o# D3 u
                        output = 0x7FFF;4 k& l8 u. \/ B+ U* r
                } else if( output < -0x8000 ) {
1 k' n" _. P" A                        output = -0x8000;. L( f+ J  T  V( X3 q7 C
                }/ b7 w) u; L# H" t9 c* ~: E( y7 q
5 l1 o: W) W. h& r+ p/ w
                if( nBits != 8 ) {5 ^( \1 U- R" {$ `
                        *(SHORT*)lpBuffer = (SHORT)output;3 y9 J" j* M) m& ]. N' B4 y
                        lpBuffer += sizeof(SHORT);8 o( D, Y, R* e$ X; J7 x! G9 _! h
                } else {* V/ J8 a* z0 T; m/ G
                        *lpBuffer++ = (output>>8)^0x80;
, C6 |& D0 e/ u9 g  j7 A                }9 p1 e& z# M  ]) m5 n7 m6 s7 e
( l4 C) Q, x( F7 d
                if( nCcount < 0x0100 )7 z3 R2 S5 A4 \5 J" Z4 x
                        pSoundBuf[nCcount++] = (SHORT)output;$ {2 j6 h5 i& K% Y" g% q

' Q; [( `. [3 ^1 Z  E//                elapsedtime += cycle_rate;" N, V% q5 x4 e9 j. v
                elapsed_time += cycle_rate;
2 n- P& g# Z6 e9 g( v5 m/ r1 Y        }  Z8 [/ W4 J/ G
; m6 V: Q5 }8 n$ U5 r! b$ w6 p
#if        1
5 @3 a. R  I& q4 w- o: p7 m9 ?% T+ I. ~        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {" t& t6 t7 p9 H0 _, {+ L
                elapsed_time = nes->cpu->GetTotalCycles();
; c& ^/ m- ~* s, V  [/ z0 x        }* m6 T& G3 f* w: j2 X* u+ J0 S- t. T: A
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. ]* W; z- R8 D6 {! T1 D                elapsed_time = nes->cpu->GetTotalCycles();
5 }4 D# f) H1 k+ I( @        }' ]2 T) v* M$ ]" q- Q+ c
#else
7 x' n5 A, b1 e- g        elapsed_time = nes->cpu->GetTotalCycles();7 ?9 y, [3 F# l7 Q# b9 w3 ]
#endif
6 _% E; L# L4 M}
0 u3 Y% k: K& Q& S$ w) [3 b4 ^' @' c7 K; m6 f: A
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! A7 _" Y7 \" X, ^+ @0 lINT        APU::GetChannelFrequency( INT no )
3 S) \$ |$ W! y; d6 w{; ?3 ~7 I3 d9 u; W  p* a) c8 O
        if( !m_bMute[0] )
, g; l7 {+ R! m6 q! p6 L; l# {: ]8 ]                return        0;/ y3 i, N0 y* [* K
. i. k7 ^- Y! H' |
        // Internal
/ o$ b  w+ u% J0 Q$ e        if( no < 5 ) {
7 @+ o- Q- W& F) s3 l5 {                return        m_bMute[no+1]?internal.GetFreq( no ):0;
5 H5 u& P6 h/ C) N; C+ u* G        }
5 Z( a  R8 G' M) x        // VRC6
2 G9 M: N& W( ^' v; p3 I8 B        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {( U! u" [1 L0 L& `" W
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% \, g5 a) w. E, S) `0 o
        }' b$ F7 ]# E5 b9 {
        // FDS
/ K# C. U% B* Q+ }        if( (exsound_select & 0x04) && no == 0x300 ) {
( Z* f: V4 E  P* F4 V3 e( m' u( y& v1 ?                return        m_bMute[6]?fds.GetFreq( 0 ):0;& f8 h3 }6 @+ Z+ _
        }; E1 Z+ }! R& q6 {7 ~* l
        // MMC5
/ A0 E7 Q: F' l2 E6 m1 `2 K  N; P  W        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {4 \6 N/ j7 ~8 f, N; I0 O
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
. E6 n8 G5 A0 Y: I        }% d. o1 h0 H' E- @9 S( O6 O
        // N1064 z' N4 G2 k0 k5 [* V
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
7 \' {  V) X7 m/ Y/ Y                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;6 f" m1 |9 V9 }8 x3 t9 N# ~
        }
+ _, h) y- h: d5 L& {( h6 x        // FME72 k9 E/ F( w- v" X' G$ ^
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
& C+ A9 R7 |8 P& z                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) j) @% }% L. l1 I3 M1 B5 X& X' Q
        }
; U: f; U) B7 R& d  b1 p        // VRC7
9 q! N9 ~6 }* o7 A9 ]# y        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {( w' |" ^. \! o1 \
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
. _  p: T0 s0 L- I( V        }
' Z7 @8 M3 A7 o/ @* ]! |        return        0;( P6 g- c( S& ^/ C7 \
}
  s, }7 R6 H$ e8 T0 Z; ]! D! y. y: H3 }
1 t6 J8 R% l4 F. A' t; d. z0 J9 @// State Save/Load4 ~. \) [" m. [+ A
void        APU::SaveState( LPBYTE p ): d8 x1 }1 H% g6 X! z: J- Z
{
. k% a, ^; o) I/ q3 Q! S: Y  M#ifdef        _DEBUG
# R& n/ a- e8 l: ]- `LPBYTE        pold = p;. U/ K' f: r6 D4 H) Y9 K. M
#endif# s$ k9 W& F9 d

8 x# H9 m$ T2 U2 P        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞4 O& q+ \2 W( O
        QueueFlush();/ w# T' L- v& }# w( |* t8 P0 A

( o( K2 t. z( Q- d        internal.SaveState( p );+ L  W- ]" g$ g9 p# Y6 e- F! Q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( V; s0 x! m& B! _

. i% }% C9 S$ C# g        // VRC6" t7 y7 Z# m5 L( y3 q2 R6 f
        if( exsound_select & 0x01 ) {
$ g7 a  d, `. Q                vrc6.SaveState( p );2 g2 _/ O! _: H8 l$ f+ I- a2 e# h+ \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& _- V: I7 p6 n/ g
        }
8 x) ^5 c) w5 k% ~4 K: r; t; f* d$ U3 G        // VRC7 (not support)
) W$ B! Q* \4 e# V9 e        if( exsound_select & 0x02 ) {+ Q6 z% Y; ?4 L' Z/ z; H/ G  H/ \3 o
                vrc7.SaveState( p );
6 {! W! ~$ m. N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* \/ e5 \) r! Q* _! ]( Q! x        }
" \( V! X4 b' D/ I# M  V, [        // FDS
+ o. C' x- }9 J5 S- ~        if( exsound_select & 0x04 ) {. `- m) _9 o' a/ [% S
                fds.SaveState( p );" C4 F: U7 |8 ^7 v- b/ {, \1 ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ D+ }* d# `" i" L' w, G
        }0 C2 t& s) z2 L* Q/ @& v, h* w5 [
        // MMC5
  k; N' A+ [$ e6 |        if( exsound_select & 0x08 ) {
% r# J  t, s% ~3 o5 L8 G. e                mmc5.SaveState( p );
( @$ ?  c. e9 n5 c1 {- p7 ~+ [                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 J, b1 w. m3 y$ y
        }
% t7 p$ l5 w, J        // N1060 e. s9 M0 |* G( m# w
        if( exsound_select & 0x10 ) {
% H* J6 Q0 N) n. m) i                n106.SaveState( p );
9 p1 z9 \: I0 ^; g- b6 j  G                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. n" q' J9 Z3 @0 _5 U9 k
        }
/ ^1 c9 \& K% V* _& ]" \        // FME7
" ~5 n, W: ^9 y7 h        if( exsound_select & 0x20 ) {5 P" Z, d, u0 V- p" [. k' n, L
                fme7.SaveState( p );
0 S3 K* z) t# x  f                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, `' `% s& K5 C. S# i+ `( E" Z        }6 x$ \. @* W" M! Y, q
3 h- t& y5 J6 ^7 y9 `7 z5 D8 Y
#ifdef        _DEBUG% p2 M: O% s% z' G" E
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
# ?. Y! B# a- K) [/ f7 ^#endif1 I" {7 n: \: e: m. d* ?: k
}, q4 f5 {9 A1 f

1 |& m+ \1 P! J  E9 y3 ]void        APU::LoadState( LPBYTE p )  @6 j# v% N, B! ]
{( A+ v+ `1 u( ^# L
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& d- H$ a0 ?; V4 E& W
        QueueClear();$ U, N$ s% w# y
2 }0 N8 s7 R3 H8 B2 ]
        internal.LoadState( p );
" l! K6 C8 `- D) w        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. V5 o7 q. i& w8 U4 v/ a) |: V
' T  c& D* Z, u, `
        // VRC6! x- \- a5 }, [# ]* J1 ?) D$ Q
        if( exsound_select & 0x01 ) {
" t9 O% R) O% v- R8 ]: `                vrc6.LoadState( p );7 l1 S; [1 Z$ m+ P* y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, t  {2 B1 A6 j9 B        }
& ]9 R( \3 k- S        // VRC7 (not support)$ H# s9 ?& J3 o, X; I9 B
        if( exsound_select & 0x02 ) {* [9 b9 H- w. @* L2 @3 e7 m6 \+ i
                vrc7.LoadState( p );
$ {1 i2 k7 K- w6 J( x( c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# x& u1 _6 l, T7 ~7 |+ m        }+ ~6 ]3 p$ S) Y$ C- z7 @0 C' I
        // FDS
; p9 A/ K' u* W3 ~- P        if( exsound_select & 0x04 ) {+ Q2 X# F5 y1 f  z; }
                fds.LoadState( p );3 F: p) M& l7 N+ G' I  u' q; n; [5 i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, [, t% a! P9 U3 v1 K        }5 G/ N* o0 u9 h9 T1 d% Z
        // MMC56 x' M7 t$ R/ e' V$ {) W4 h
        if( exsound_select & 0x08 ) {& A2 M5 T' S( ?* B1 n. Q& e. J
                mmc5.LoadState( p );& o: ~' O0 i2 G3 U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# ]  `/ J) @6 U2 K& U+ }$ J7 o! P0 v
        }
( d" q- Q3 s5 z' G* D        // N106$ p6 H1 K- @9 n) M5 ?. v
        if( exsound_select & 0x10 ) {
% n) q1 S! h' C9 ~! x+ u                n106.LoadState( p );
$ I: q3 d5 k, \6 x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 Z8 l- [2 v, s9 v6 ~# A
        }
: z. f/ l; g% q        // FME7
+ ~. N7 ~2 J+ o- w7 C        if( exsound_select & 0x20 ) {
$ ?+ q* B) P) K! O& D4 |5 L5 h  N                fme7.LoadState( p );0 n' f" ^$ T( S) C2 M8 L, ~
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; a6 u0 p5 c) `! y& c- s0 g  ~
        }
5 Y0 @$ `0 \/ K$ O) G; Y* q% u}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表   U, o0 |: ^6 x/ m4 _$ Y3 N
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
$ ?8 n; ~  C8 t1 l% }, n0 E感激不尽~~

- E8 i: \, f5 K  d恩 我對模擬器不是很有研究,
# _8 ]$ W) b6 [! w+ i( W雖然要了解源碼內容,可能不是很困難,% @( M! c5 A, ]) H7 x/ Z5 }* Q
不過還是要花時間,個人目前蠻忙碌的。) S! K6 Y4 m3 P2 D# a' P' M
% P8 {! Z  ?: R9 I- A0 x3 D. l+ N
給你一個朋友的MSN,你可以跟他討論看看," a% J' o4 z% w: \4 A% P% o
他本身是程式設計師,也對FC模擬器很有興趣。
7 F3 f3 M1 _- N$ x$ x' z1 o; ~- }1 j/ d
MSN我就PM到你的信箱了。, E. r1 u. B6 L  b$ h8 [
4 A& G1 s6 U) ~8 Q
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 8 P* G. f4 `0 v* E
呵…… 谢过团长大人~~
; R& X; X  n. {

1 a) f: R2 F; Z8 B4 z, s! }' W哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 0 t& t& D8 b- x0 g7 H
团长的朋友都是神,那团长就是神的boss。

$ q4 H% D  ^* O' I哈 不敢當,我只是個平凡人,. ?& \% T/ @9 z
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 Y8 h% D1 o2 y3 v9 z* m0 ]ZYH
$ H  v8 C( |8 Z- Q% B3 N) {QQ:414734306- z) ?/ K6 h% H+ Z: B( F- k( h
Mail:zyh-01@126.com/ P+ {+ N$ t& R& w( t+ [
) N! E/ r; k! v% t6 Y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 q! w6 w; u6 X% Y再次对团长大人和悠悠哥的无私帮助表示感谢~~

2 U) B' E0 P$ ]5 X不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-4 19:33 , Processed in 1.095703 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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