EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
9 @) ?5 J: W' U) I" q+ K  [: QPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  `6 b# d9 V: K3 J/ w5 y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- P$ t' |4 G: g9 j, T
这里有相应的模拟器源码,就当送给大侠了~~
5 r+ ~/ |8 o$ A$ W+ Xhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 1 F6 Z1 y) v4 ~9 {0 a* ^9 q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; i# v) N4 J+ U" Q* T. x* x7 P' x楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ o+ [5 J+ m' ?+ h
这里有相应的模拟器源码,就当送给大侠 ...
$ a) a- E& @. @7 W  \
聲音部分(Audoi Process Unit = APU):" Y" d. Y1 J: [8 [7 T$ y
.\NES\APU.cpp/ U  Q0 k0 L& I0 a! t
.\NES\APU.h
# H/ w5 a* b8 |# [; Q" m
" \" q. k. [& V, E2 i3 m& ?, T" w7 M3 L: v: l
影像處理部份(Picture Processing Unit = PPU):7 I, Z) k! f0 U1 {* P9 v
.\NES\PPU.cpp
" ^. P/ y4 l/ s' A, D& v.\NES\PPU.h5 {4 e4 T& j- {( `% a6 w
3 I" C8 F' b1 t6 d& {5 ]( D7 D
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:! V3 ?' v3 }9 v7 ?5 e) k
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ x1 r' B1 v6 W: Z2 G8 L$ W  T
//////////////////////////////////////////////////////////////////////////1 w# ?3 r  G8 b; [! v0 y8 \$ @
//                                                                      //( t- Z: L* k6 U$ v4 x
//      NES APU core                                                    //7 x% G" `8 x1 t. v( O9 D
//                                                           Norix      //
9 q. m* z( S- m% Q! w5 R. y//                                               written     2002/06/27 //
  {) S. C: ]$ Y- y. a, K% Z, l+ {: C: C//                                               last modify ----/--/-- //
" j: M7 c0 w3 l) P7 a//////////////////////////////////////////////////////////////////////////
0 o) u  X. S1 A/ l0 T6 [+ C#include "DebugOut.h"
& _* h. E! e$ K9 ^#include "App.h"8 H8 K- o; d& y* k* `
#include "Config.h"* G$ y8 ^% f% N

3 v) k* B# D  q" g#include "nes.h"
: ]( L5 W5 Q8 i, }+ _# V8 V, [% ~#include "mmu.h"* T: q( r- m8 u3 x' K' k
#include "cpu.h"
/ j$ s3 W# E& J#include "ppu.h"
0 t' D% c; c& m5 W5 V7 q#include "rom.h"
( h% X5 x4 o  P0 s- i& _# C6 Y#include "apu.h"
; J% U. d% H, `: ?3 L
% h) m7 S* j( I! \6 g4 B: C- [4 Y+ g// Volume adjust* J& }) c& L6 U6 F
// Internal sounds( w5 c) {$ H6 w( A6 G$ Z$ u
#define        RECTANGLE_VOL        (0x0F0), {) K! l1 M0 j' F' z
#define        TRIANGLE_VOL        (0x130)8 F' S; S0 F0 l# c6 k
#define        NOISE_VOL        (0x0C0)* _" e1 U# H# o  B  R2 q$ B
#define        DPCM_VOL        (0x0F0)7 |* M) f  V/ a( o* k' N
// Extra sounds( o9 U4 B! p1 A- z+ |
#define        VRC6_VOL        (0x0F0). Z: ^7 ~2 b0 ]% n3 U- k9 G
#define        VRC7_VOL        (0x130)% A! o+ X& E+ B! t1 L5 x7 h" p* J
#define        FDS_VOL                (0x0F0)+ G9 O, [: \! q
#define        MMC5_VOL        (0x0F0)7 _! j7 i6 U! c
#define        N106_VOL        (0x088)
* y+ O9 W6 A3 A) N5 y, r1 e$ [. Z#define        FME7_VOL        (0x130)
  M( D/ m" b& {# y4 ]6 n% q+ Y+ b3 i( h0 Y; ~
APU::APU( NES* parent )" J2 m# |7 J) Z
{
8 H' A) S3 u) R! @        exsound_select = 0;3 i# M0 m- Q6 V$ Z% H+ L  N
+ f$ t+ k8 R$ j+ H
        nes = parent;
( {# h* I0 _' @; ?/ D        internal.SetParent( parent );$ U  `( F1 I- g3 ~1 I
% G% K# i4 {; B' Z6 n2 Q0 |9 K
        last_data = last_diff = 0;* A, _( x& [: a# v$ I- @) b

; q0 }$ E! {, A% V% D  g        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
& ^1 y* @9 ~' g* _8 ^+ Y- s  }5 R( ?; E8 ]8 S  x; V
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
7 {& z. n3 o2 L7 y  i3 G! y) x0 @9 J        ZEROMEMORY( &queue, sizeof(queue) );- _. i( ?2 |* F. I; T% K
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; c; I! c* P' z$ ~7 [! [& m+ h. N  H
        for( INT i = 0; i < 16; i++ ) {8 m5 p" J4 G" U7 h7 V5 W5 ]. e
                m_bMute = TRUE;$ D& U, A: w% ^
        }
  q0 ^1 E! J( M* z1 J) |! F- Z}% ~/ H9 T1 j, n
1 W+ l/ ^. g3 K& y# l
APU::~APU()
" h- I8 `  d3 _' H{0 M! M4 Z5 [- `! d  k4 m
}
  z: c8 O7 {6 q4 h5 G
9 o# e% p: r( d! ~  F* E  _  ]void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
4 t6 E; ^9 e9 j% k$ K: M5 K{% C: }2 i( F2 |8 |  t9 w5 [- {
        queue.data[queue.wrptr].time = writetime;
2 ~8 ]) D8 Q) u- k, s: [1 c        queue.data[queue.wrptr].addr = addr;
  X5 b0 k; I! p9 W        queue.data[queue.wrptr].data = data;( G0 v" n5 w# S0 E4 a' u' H" U
        queue.wrptr++;
4 }) j0 M- }% P6 b$ ?1 t6 k& G        queue.wrptr&=QUEUE_LENGTH-1;7 s* F3 Q  r4 T& |
        if( queue.wrptr == queue.rdptr ) {/ n2 a+ y% J( d! l1 |: n
                DEBUGOUT( "queue overflow.\n" );% {2 U  B6 d$ U/ x- \( E
        }
7 P* v. C- y: A/ ]0 q; E5 `2 |}
# f/ r0 w4 B  ?+ a  }# s- d$ P4 A# Z9 [7 Y, j" W. \3 ?1 B  ?
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ V* C( O9 e% J1 z/ a3 k
{
4 H7 t0 H+ t1 W        if( queue.wrptr == queue.rdptr ) {
& ~$ \2 p' f4 D8 W7 g  c$ L! H                return        FALSE;! H  a& L. ?2 Q8 ^4 o- n8 f+ C+ {& p
        }
3 c* F6 t; d! {# @* r        if( queue.data[queue.rdptr].time <= writetime ) {2 Y. E0 K3 p0 p/ J' }* d
                ret = queue.data[queue.rdptr];
' H2 _7 \3 a. d7 X) P6 m: [                queue.rdptr++;' M5 G# e5 Q) ^  X+ T; ~3 Y" P
                queue.rdptr&=QUEUE_LENGTH-1;
" H) I9 q- }( F+ R* W1 ~                return        TRUE;
; w% s# q. Y) K* o2 d        }
) ?8 h$ o$ g( a& T        return        FALSE;
4 D4 N- Z1 I9 B}
& ^9 `" D; |5 v$ T% k3 J" W6 e
5 M, [; Q  g0 |5 p0 Hvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  l6 @7 g5 c* {
{6 U. d- h) m4 l) j, ~/ M5 T
        exqueue.data[exqueue.wrptr].time = writetime;
5 e: s+ {. F) x/ O( o" ]        exqueue.data[exqueue.wrptr].addr = addr;
! j* _7 @, w0 f' C        exqueue.data[exqueue.wrptr].data = data;- U2 r- t. ]8 O* y5 Z2 i
        exqueue.wrptr++;  l8 _  S4 X0 O0 {) x6 d: o2 k1 h
        exqueue.wrptr&=QUEUE_LENGTH-1;  M8 [& h4 c1 T9 Q. L
        if( exqueue.wrptr == exqueue.rdptr ) {
' z( I8 }* I! U" Y' R4 P- X8 T                DEBUGOUT( "exqueue overflow.\n" );
( o9 q9 M: y: W: m. G* L        }
/ _" w2 {9 U: @5 g( m; y}1 |) n' n: O" A2 L0 B$ m) u: m- r

& I9 @6 U9 _2 @) b- ?% U% iBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )( o  i! t7 R5 N/ A  {' G+ q6 ?
{
/ K, _6 u& ?+ S" u) j6 L- W        if( exqueue.wrptr == exqueue.rdptr ) {
# V, C* W+ V, p% ?2 z' p                return        FALSE;6 A: A' g" G& k4 c
        }5 W4 J! ]' O' c, ~% {* \
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {+ \6 E* H; {6 |  ^* Q5 Q/ h
                ret = exqueue.data[exqueue.rdptr];4 l) t: n# k/ n
                exqueue.rdptr++;
* K# X5 ^8 N+ A7 e5 i                exqueue.rdptr&=QUEUE_LENGTH-1;7 B  E$ P1 F8 b
                return        TRUE;
" I9 v* D3 S- _        }
( S+ s5 c% G0 }! G        return        FALSE;
* L5 V/ q# N) ^& t$ ]+ X6 _( e}- k, R' g" J6 V. z: j

! f1 g) n! |7 S0 }. o4 c! [, @+ @void        APU::QueueClear()
$ I# o- a! f: K+ J  x7 @, Z{5 A! ~( s, E8 R3 K. v7 I  k& x' H# _
        ZEROMEMORY( &queue, sizeof(queue) );" [" y$ \8 t1 @! }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, y! M/ `( t: D1 h
}' N& i0 w1 u* B; A" ?

2 T- Z8 m$ t* v# ]' ?& |void        APU::QueueFlush()
8 U& D' C* C( j{
4 D$ _8 k9 Z" f4 R        while( queue.wrptr != queue.rdptr ) {
% l" b8 p( D2 V( P2 T                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) x4 F* C0 h  p6 E$ }4 M5 I
                queue.rdptr++;* `" D" X) W. U, L2 q8 e  X5 u
                queue.rdptr&=QUEUE_LENGTH-1;
6 B! }7 k' W. z4 [4 L7 L/ J        }! R$ K5 i  T. ~3 q5 m# ^- B

* x- N3 b( U6 l& Q: f7 F  N        while( exqueue.wrptr != exqueue.rdptr ) {& G0 Z* E" N9 ^; m8 S  [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );2 W& {6 E. P& u# O* R
                exqueue.rdptr++;
0 X  _7 t. N- T+ a. U3 [                exqueue.rdptr&=QUEUE_LENGTH-1;$ a- ^! g1 E; F9 _" B6 C
        }
# y- I& b9 I: l# A0 t& Y}
% X& D+ l8 l& D  y$ K/ \8 Z9 q. E) w/ I! \
void        APU::SoundSetup()( [8 Q8 ~5 ]/ T8 h" C8 j
{
0 M& ^0 \2 B7 F+ ^6 N        FLOAT        fClock = nes->nescfg->CpuClock;) Q5 Q' F, ^0 {5 w, `
        INT        nRate = (INT)Config.sound.nRate;% V4 x4 r" I# E+ T  O/ U  C0 ~
        internal.Setup( fClock, nRate );  t) B! q7 b# S8 p% V
        vrc6.Setup( fClock, nRate );; X, W1 ~* v' U. ?( p
        vrc7.Setup( fClock, nRate );2 P9 X2 j, d( L7 I* [$ G' d8 ^' j3 F
        mmc5.Setup( fClock, nRate );
& Z3 a) l9 p' i) \* |        fds.Setup ( fClock, nRate );
/ z% E' F  a* c# D0 r* n, K# ^$ R        n106.Setup( fClock, nRate );) H" I, F: v+ y  i( S1 e
        fme7.Setup( fClock, nRate );
) ^7 q* l$ t' F' @: U$ m: G: l}
( m9 ~) C* k3 O9 M. e& E* h  z5 z& n) O. G9 N% n
void        APU::Reset()
! t9 {: j7 c% C3 c, j  F+ X{- y, P. _& K, N3 J, E
        ZEROMEMORY( &queue, sizeof(queue) );
4 J) u/ S4 F0 K8 E        ZEROMEMORY( &exqueue, sizeof(exqueue) );" i! U1 t4 v* J

7 {2 u" `! D' j! f1 k/ I% n        elapsed_time = 0;3 v$ v1 _: ~4 ^. f
; |& g9 l4 d, ?
        FLOAT        fClock = nes->nescfg->CpuClock;
5 u  U! S/ O5 N: K: Q# c        INT        nRate = (INT)Config.sound.nRate;' f1 n- J3 p" w
        internal.Reset( fClock, nRate );' u  Z" h) S# a6 p: f* g" p
        vrc6.Reset( fClock, nRate );/ e- I. E# o3 |1 e  n+ c) t
        vrc7.Reset( fClock, nRate );% L- F$ y- _- I: V& x
        mmc5.Reset( fClock, nRate );5 m+ L2 `7 ^4 O, ~
        fds.Reset ( fClock, nRate );5 B( r. S# K$ L1 U# T1 ~
        n106.Reset( fClock, nRate );; n1 i& T9 Q) d/ e( V
        fme7.Reset( fClock, nRate );
6 C0 S2 n4 t+ z2 V1 T5 Y; U7 w8 w. H& J2 S. l$ j8 i3 N9 P
        SoundSetup();
2 |2 ^) s: e2 F$ n, @$ e: i# X}
" f+ r) K6 T! Z* Z# E
9 j# Z" ]4 z9 Tvoid        APU::SelectExSound( BYTE data )
1 a+ ~& E6 U: [# q. a2 _1 g{: B8 G6 \1 P9 E6 f7 F5 r  d
        exsound_select = data;
% n8 I9 y& j4 Q5 @) t. E}3 C/ ~* d$ e. a8 ~# M

+ L% {7 H( U5 J  \BYTE        APU::Read( WORD addr )6 T# W1 T5 B6 j: |- Z! Z' S
{; f3 X# h2 q$ S; q( A) d
        return        internal.SyncRead( addr );* W* w' [  E# p( O8 b
}" b  |# U/ H8 }3 q: g: r
' E4 P+ |0 N( V4 b; m1 v' l
void        APU::Write( WORD addr, BYTE data )
: N2 q; l& C% W, u& a1 P& t{# y* a  C' d1 \( C  J; }. E
        // $4018偼VirtuaNES屌桳億乕僩0 s; d% B, o3 O# V' Q8 r2 a1 b6 O
        if( addr >= 0x4000 && addr <= 0x401F ) {# |9 Y% d* I% w
                internal.SyncWrite( addr, data );
) m/ q5 c1 I3 P" M1 X" i# U" }                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 H! J$ g9 b1 U; n        }( t) l6 K* q2 T% Z' }
}
% A( n; g& x  k3 r
. p0 U9 {2 B$ T5 N) l. @BYTE        APU::ExRead( WORD addr )  D, O$ p2 T$ t0 h8 x
{9 J) P4 `$ D$ y
BYTE        data = 0;
" w$ h/ T( F) I$ V6 P' r/ }5 j, C4 t, p7 B- R2 d3 {
        if( exsound_select & 0x10 ) {
% D; l! w1 w9 z& m) t9 S- m# J                if( addr == 0x4800 ) {
' W4 o& A7 s# }1 `# b! P8 E: n7 m                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
$ v0 B! s7 Y* V, I. C: q% O                }3 k" D6 b# `* G
        }
7 J+ l4 s8 C: y        if( exsound_select & 0x04 ) {0 e( `: u; [  W+ q. G
                if( addr >= 0x4040 && addr < 0x4100 ) {
' m7 V7 U6 z3 }9 a* Y# I                        data = fds.SyncRead( addr );
6 B0 `: g4 ^3 T  P! H  y                }
8 v. n' Q1 D* \- }# H, l% |        }: F7 |* k) |. R/ P
        if( exsound_select & 0x08 ) {4 X# B" p+ k6 r0 ~
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' K& k/ g; i( x* _; z5 V! j' _2 R# A                        data = mmc5.SyncRead( addr );
1 i9 N' l- L! T! g                }# z! ]4 ]! V; _1 a* k8 Y( o
        }: \$ @9 w! N2 y* A; F5 `' b9 x/ W9 |
1 ^* J2 Z2 }; T9 k' V3 J
        return        data;- }; k* Q7 Q! m5 f
}
* G+ T( w, ~9 N  ^. B6 {6 B) i
. o* t9 }. Q* i' e( K' `void        APU::ExWrite( WORD addr, BYTE data )0 U5 K2 ]; Q: J5 m7 C* `
{
  g4 [" B! V( W; A        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );$ U6 o4 R( [- K

* Z: }: R/ \! W  |3 ?% T( D        if( exsound_select & 0x04 ) {  f% B1 g* g! ?1 E, q0 ]
                if( addr >= 0x4040 && addr < 0x4100 ) {( Z: G; c" u3 q/ ?. g" I7 B1 t
                        fds.SyncWrite( addr, data );8 R5 V0 e3 B0 Y) N' [+ e' Y
                }
, e# W4 D; @8 g7 u) C' b. C% `+ I- [        }
$ `7 z9 a/ [& E  ^! a3 O- n% [) H( i
; i' E( @' |* G1 i        if( exsound_select & 0x08 ) {
3 q' p4 w/ x4 p+ i& W                if( addr >= 0x5000 && addr <= 0x5015 ) {- d% z( A6 F! m" }! c' ~
                        mmc5.SyncWrite( addr, data );0 t7 C) X; y+ s4 Q% N- W+ _- Y
                }! \! r& W  c, p! {  v$ n
        }
  J5 f  b8 v. W$ P}
* l! P; x+ i& @5 }
6 D& J, y, `8 E# [, S9 |3 d2 gvoid        APU::Sync()
. x9 v/ h0 T$ b; C5 r( F7 n{
- y, r( W5 B9 K& I}
/ P- d4 F3 n0 h5 g3 L9 O# Q- f0 l3 C; d9 m2 O, c
void        APU::SyncDPCM( INT cycles )4 B9 C" L: Y' K
{0 ?7 m( k: {- H5 i! q
        internal.Sync( cycles );, s$ c3 `  i" e8 a, I7 V6 M1 [
& j+ @( u( D0 K6 h
        if( exsound_select & 0x04 ) {5 I! Q. t4 ]8 H/ U7 _
                fds.Sync( cycles );; U; \. r: `- i$ C; J
        }
* C* n0 y+ m9 ?3 ]: G4 H        if( exsound_select & 0x08 ) {- |7 B: t/ |$ }5 c! h5 A8 j
                mmc5.Sync( cycles );" {5 z2 C8 k  V
        }& L% C: N, i6 w4 v: i
}
! x3 U- |5 Q! h1 I& f2 ~! R2 R4 v6 R. r& y2 z& N
void        APU::WriteProcess( WORD addr, BYTE data )) f1 G& S6 T  o; B* u/ F- @5 m4 {- K
{
* [+ ^8 W! a' y! d9 b        // $4018偼VirtuaNES屌桳億乕僩; K* p# m$ F% f) _; [( W
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 Y8 y- b" b* K9 w& B                internal.Write( addr, data );
8 ~' \1 }) |% f( O5 p8 [        }
9 y0 o! e: u2 w/ d: @, x# j}  v  e; i' p# |( d/ I1 C3 q

5 \. X) C4 |& Z3 J, Fvoid        APU::WriteExProcess( WORD addr, BYTE data )
6 N- s6 G  t& a2 m1 L. O{! `6 _- K# w& Q- e
        if( exsound_select & 0x01 ) {
+ K! R; w9 R* [8 S! c                vrc6.Write( addr, data );
' c  u; k% N: ~- {        }
. ?0 S! S# k& l        if( exsound_select & 0x02 ) {; ^1 _# {7 _# F  ~4 K
                vrc7.Write( addr, data );' J) U9 r3 ^. {6 k4 h  v
        }' B' ~" W" g' B1 F$ n
        if( exsound_select & 0x04 ) {8 D' t0 C" `  P* V2 p: n
                fds.Write( addr, data );
5 |, i- ?0 e, \& f: a        }# u+ v# [$ p$ V6 t9 h4 c
        if( exsound_select & 0x08 ) {) q* r/ |+ W! t3 Z6 z
                mmc5.Write( addr, data );: F. ?# l, D+ t. y
        }5 Q& Q' Q" s8 E! @" t* ]4 O
        if( exsound_select & 0x10 ) {" v  i5 Q6 s) e, F. F! |' y9 L
                if( addr == 0x0000 ) {8 ?* f* n: a" o; ~
                        BYTE        dummy = n106.Read( addr );
8 W/ ^8 J, c8 C- e' l9 L- O8 Q. k                } else {
. r4 T8 O. M6 T                        n106.Write( addr, data );
3 I* R( L, A3 ~7 m" G8 P                }# w9 ^1 Q4 c. m" P: i
        }
3 {$ }+ r4 X3 H9 \7 f8 D        if( exsound_select & 0x20 ) {
4 @* B+ ]3 V) `/ X# G( J- W6 x                fme7.Write( addr, data );# q' b: f1 ?" ^! y" _
        }
" }9 q: C% \/ b" ?8 \( u' C}
" H, h$ ]( F" `. P- }1 I4 r3 h1 }) u! }( F- i
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 d8 _$ W) i6 t. g3 Q% R# i2 g
{! \6 L+ P- M0 V/ b# z) ]
INT        nBits = Config.sound.nBits;
$ U& K1 B' j' q! d+ f% x) ^DWORD        dwLength = dwSize / (nBits/8);
& N: ?6 ^  W& Z# [! U# i4 BINT        output;6 t2 t2 A; e" B) t
QUEUEDATA q;
6 F% H+ o3 r2 U; U) gDWORD        writetime;
# S0 E4 H. e0 p0 P/ e* ~
% O. i" k2 ]3 w; N* p1 SLPSHORT        pSoundBuf = m_SoundBuffer;
7 r" Y7 g$ ^1 R/ p! @9 EINT        nCcount = 0;
" w8 i. \. ~( N- x1 I
! h, Z+ \5 ]5 u: q+ B( P8 W' n% gINT        nFilterType = Config.sound.nFilterType;
: o( A& T- v" @5 r" `- w- q6 r9 H5 e% G1 I
        if( !Config.sound.bEnable ) {
8 i. o1 y- M$ t: W& b, i, Y- E                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
. N2 w) J' B1 T( L3 c8 R; f                return;& u  s6 _! J/ p- h
        }9 X' |* y0 q2 U
" {; ~1 t* j4 S3 I* w# u
        // Volume setup
- `7 q! v4 b$ w+ [        //  0:Master
: n) U, z# m/ A* q& A/ r        //  1:Rectangle 1
" ^$ e6 e8 U6 S; b- {        //  2:Rectangle 2
4 r; W( m3 W# V! B- a        //  3:Triangle
; Z0 E5 K5 m' X, u; V( x: W        //  4:Noise/ ?$ e" W' ?) O
        //  5:DPCM: j% u/ d3 M2 i2 q8 u+ Q
        //  6:VRC6/ _8 Q+ u3 u# j, E: x
        //  7:VRC75 R$ k+ R; C1 m. Q
        //  8:FDS
5 {, [- m$ d3 E& Q# `. `        //  9:MMC5
! J3 _! f! [# m: `        // 10:N1065 _5 l7 b: D. }( x
        // 11:FME70 e( j  b5 s! \0 \7 r, g$ |
        INT        vol[24];
' H6 ~9 ^3 ^; u  V# C        BOOL*        bMute = m_bMute;
4 m5 M; a: ?2 e& B        SHORT*        nVolume = Config.sound.nVolume;
; i' W+ E9 Z& z1 x. U: p) T
" ]2 x& f4 I2 z! O        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# K$ z! m+ `1 S. i* \5 n

2 x4 U, l8 V3 Z! M        // Internal
7 U# a  t* T0 l1 ]/ T# D        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 A/ M" k* A8 i+ z& U5 G2 W
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;0 P4 P5 q/ W4 z4 |; S' g
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
& V; c0 L8 ^# n7 P' M8 H, h6 L* M        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 r! A* |0 u1 E1 O        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;0 K, Z, I6 ?5 A! G1 \/ U" b$ _

3 k3 {1 W3 A: Y: i/ }        // VRC6: D' z3 f9 q5 o' y* x* H" `; f2 U9 U
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  c1 O1 A! h8 I        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ L% J* J; D2 ]2 D
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 Q7 ]% T. T: W% Z, A! u& V% c& M* r$ m& k
        // VRC7
( [0 r+ @; Z- m, {7 P. T        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;9 [# {+ {& l: L

/ A$ U! i& t* {# z/ h; ?% R$ q        // FDS0 c8 f6 R) y. P" I
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ M- X9 I6 Q* b9 J' r6 I9 `/ z: h' ~: H3 x+ m
        // MMC5
  u. i% [2 ?" g) e% t2 E        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) D* B2 `! T* ]: X        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' t$ |2 W3 T% Q
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* g  h( C( J+ V+ Q9 L" F5 A
# K# B% u7 I+ }
        // N1062 b, k. Z3 b  C7 P" H7 F* L$ d" f
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: G0 n8 m, ^+ c: F! P- |2 V  I        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# @4 w6 L8 t7 U5 {( w( Q" l3 ^
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 d+ f* ^* l. x* X# _8 d% Q0 O$ z        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( \9 `2 w- v! W# n
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' G$ C7 {- K2 \, |  f
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) @+ L! I0 X% a" ~1 d        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 f9 p) }1 \/ h9 w( `# g/ a
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 T& l4 y, o+ W; K4 j# T6 [, V2 ]! [% I3 Q1 q* q( U( q! B6 S
        // FME7: ^, L/ \% l$ C: U+ h7 x; P
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  E, C: m- d  e0 F. N2 g, `
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 u! D  F7 u, s6 b: u2 O6 U+ c
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% u) M& z  ^; T0 T' {
& L+ o+ |- f& l* ~
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 I' k. m  e6 `! }, m$ l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 y& f6 X/ e2 U2 q* C, o9 _
* C& V( Q( e/ m7 m( o" W7 ?. Q
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ o: P3 O7 r# ~" N1 b! Q        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ p5 t6 w) U% R9 J                QueueFlush();
5 U! i$ H% ^) {; R        }
2 h7 B* a8 ~, o
- R) c$ ^+ Q+ P        while( dwLength-- ) {
! U  w2 T  t9 ]. K- A                writetime = (DWORD)elapsed_time;8 K9 S0 G5 Y6 a
6 B; C0 J5 G+ d5 m7 H
                while( GetQueue( writetime, q ) ) {
) A, O. E, i+ W                        WriteProcess( q.addr, q.data );
! a! |4 Z, w# w1 Y# O5 r( N! E  e                }
2 W; p: Y3 ^7 X: T; v) M! k6 o, Z2 F* u/ E
                while( GetExQueue( writetime, q ) ) {7 f! E3 n; e* O! I9 l
                        WriteExProcess( q.addr, q.data );
  |. K+ ~- T: B3 F+ k$ f# l                }
. J" i) }0 j/ I# M0 w, M/ l; j  a
, H& I; }7 G0 S8 H9 @% y: i( }                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! z! i) O) C7 x
                output = 0;
3 P7 @7 l0 Q/ @; M                output += internal.Process( 0 )*vol[0];
, K% r+ |  a/ H6 v                output += internal.Process( 1 )*vol[1];
0 |5 d/ Q3 G( a7 ^0 a5 S                output += internal.Process( 2 )*vol[2];
/ x3 t+ M3 H) w2 D# e4 i# p                output += internal.Process( 3 )*vol[3];
& c, B' A+ ~) ~. z+ ~/ R                output += internal.Process( 4 )*vol[4];
. f9 n$ }$ a* p* q, E5 w$ T  N# G- ~8 C, @' `- Z" U2 }6 b$ G
                if( exsound_select & 0x01 ) {
4 i4 c3 E5 x2 K1 Q% q; a, n                        output += vrc6.Process( 0 )*vol[5];
# y( N  ^1 `7 h9 A( k1 F8 b" p                        output += vrc6.Process( 1 )*vol[6];; L# L; F1 F" r) b# e2 \* B
                        output += vrc6.Process( 2 )*vol[7];  U+ |3 z  Y8 C* |
                }
$ R) t2 a7 }& e5 v: P5 }# Z; o                if( exsound_select & 0x02 ) {( n& O$ [3 j2 j' f2 {
                        output += vrc7.Process( 0 )*vol[8];' ~" J2 |3 ?4 _
                }, |, K( H3 |2 ^  T+ b. ~
                if( exsound_select & 0x04 ) {
- O! m2 J; m2 W$ m5 }                        output += fds.Process( 0 )*vol[9];  [: l1 h/ n- ]4 G3 f
                }5 e4 T6 ?, ?, A0 ^& l- K
                if( exsound_select & 0x08 ) {  f' \: W8 {9 t" J. j+ W, O/ W
                        output += mmc5.Process( 0 )*vol[10];/ D0 x1 p9 D+ D) h* P
                        output += mmc5.Process( 1 )*vol[11];
+ y; L: s6 s- s- n2 ^2 M; X                        output += mmc5.Process( 2 )*vol[12];
, Q4 d  W, Y' p+ w                }
. E+ x+ _0 ~7 B" V! o0 i- y                if( exsound_select & 0x10 ) {
  ]( t: T5 l% E7 X                        output += n106.Process( 0 )*vol[13];) n" w* q8 N7 c* H2 O( m& V1 H# W
                        output += n106.Process( 1 )*vol[14];9 i. ]4 @5 }4 O
                        output += n106.Process( 2 )*vol[15];5 s3 j8 D  c  c
                        output += n106.Process( 3 )*vol[16];
7 c8 q  l4 l# w+ ~. u- W                        output += n106.Process( 4 )*vol[17];
( V) O1 K, j) U- o: }/ }7 n                        output += n106.Process( 5 )*vol[18];
; }9 E# F3 Q5 e0 F0 P  {                        output += n106.Process( 6 )*vol[19];/ v. x' @, l; ^+ M! Y' D. L
                        output += n106.Process( 7 )*vol[20];' G" F( p6 z2 c  J# }+ e6 S
                }
% F! n- g8 Q* Q                if( exsound_select & 0x20 ) {, s3 O0 C/ \3 \* s  s6 v
                        fme7.Process( 3 );        // Envelope & Noise1 U9 F' X  _2 p& {: h( M# S
                        output += fme7.Process( 0 )*vol[21];& K& z5 }* d  o) t
                        output += fme7.Process( 1 )*vol[22];
7 z) g0 y1 f! S/ m1 P5 N. q                        output += fme7.Process( 2 )*vol[23];  N  o3 k0 q5 c6 w* J! E
                }
1 d4 |# s1 y/ }1 E2 `2 V3 i; W6 u$ O" {" F7 M+ o9 f, l3 \% o
                output >>= 8;
* g7 S7 H$ I0 g  o1 m& u. `. o# B$ R4 d3 ^$ a" }6 G& ]
                if( nFilterType == 1 ) {; y& V2 b' K& d' }
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. n  |& K& T) D$ ^, s                        output = (lowpass_filter[0]+output)/2;
7 t+ n- Y2 U6 ?. M                        lowpass_filter[0] = output;
' z) r* X5 h2 t; ?' ^! W  f                } else if( nFilterType == 2 ) {, c6 B$ `# J9 U8 E( S
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
) a6 r# M7 e7 D                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;. d+ l: Z1 o2 K4 o6 i: L
                        lowpass_filter[1] = lowpass_filter[0];
! g4 N3 p8 ?; D- v4 a2 B                        lowpass_filter[0] = output;
1 s- Z# h, u, ^3 _                } else if( nFilterType == 3 ) {* A" f' c6 I2 g- R5 }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)% h8 L6 p' C5 B+ B2 \2 g2 T
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 e' r* y( w# U' {' \8 p$ ], M1 l" f                        lowpass_filter[2] = lowpass_filter[1];  f9 ^5 Y  h  \5 J4 [5 K' q
                        lowpass_filter[1] = lowpass_filter[0];( ~" }, H, W+ x! S+ G% p$ l& [& S
                        lowpass_filter[0] = output;+ ^: I; H3 ]% H0 M
                } else if( nFilterType == 4 ) {
' k' M" P! X$ @' `( @; y                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
: \2 \# c4 T5 Q. \' ?0 s                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ [) w5 q) K3 [7 C
                        lowpass_filter[1] = lowpass_filter[0];3 C2 m, Y$ q. ^" e2 M6 v1 P6 n
                        lowpass_filter[0] = output;
4 J& V/ j3 ~2 }# N- U. s# J) R                }  Q# t" f. O$ z+ s# L" H" \* ^

2 ^8 P2 L$ s% W1 y; M#if        0
2 w+ Q9 V3 c% ~8 j! z5 Z                // DC惉暘偺僇僢僩) q8 f3 ^& E5 @' {+ l3 m
                {
" O/ d$ g8 G" _2 T; P) f0 r5 E0 e                static double ave = 0.0, max=0.0, min=0.0;
+ q, i+ Q- E1 Y                double delta;8 N7 n0 _3 O8 q! g3 e8 a' C6 l
                delta = (max-min)/32768.0;3 s5 Q. D$ ]9 Y* Q/ B& q
                max -= delta;
" k% |+ {, `  G6 z0 W6 ~                min += delta;
/ H: ?+ I/ Z1 _3 g8 @4 }  a8 i                if( output > max ) max = output;
- Q+ ?3 u$ l7 C) [& D$ J1 K  k                if( output < min ) min = output;) B  d, m* J1 o0 W
                ave -= ave/1024.0;
5 ?  H0 f1 O3 X                ave += (max+min)/2048.0;' Z3 e# p- j- z* T! ^9 M
                output -= (INT)ave;
$ v5 d. B  L8 q5 O8 m6 @# U                }
& U; _. R+ p0 q3 }4 Y  G#endif1 R( h4 e5 F$ x! B: `
#if        1% G3 D: q6 L) W8 j
                // DC惉暘偺僇僢僩(HPF TEST)
, Q5 R0 w0 \* Q# e% B# `; ]                {
9 Q( |6 C; T9 _  y+ B2 d+ K6 }3 m//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);7 x0 o  S( ]5 m
                static        double        cutofftemp = (2.0*3.141592653579*40.0);( L4 C$ Q' B8 o7 |6 H1 K
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
* J9 T* o- t+ m                static        double        tmp = 0.0;4 z! F. A9 |; D$ @, t
                double        in, out;
, o4 P- t; u6 r  i
$ n% @; c4 r7 D& v3 V- ~3 o# J                in = (double)output;) y/ j4 [& R" q( D- @+ F1 C
                out = (in - tmp);0 `: ^/ W1 H: h6 V7 @% G
                tmp = tmp + cutoff * out;4 E  }3 p$ }+ U
, L" ?. ]3 B. y
                output = (INT)out;/ S5 w) ?4 h: @9 j
                }  B5 l0 l5 `) t9 q5 `! f$ w
#endif
! j1 d0 s6 \2 s0 T#if        0
4 _7 ]% n1 c' `7 b5 n                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* f# j% b; u* l# h  I' ~9 J1 ^) d2 S6 f
                {
; h' H4 R  }1 q7 @5 y8 z                INT        diff = abs(output-last_data);* @' \2 L% C- i/ f5 p
                if( diff > 0x4000 ) {
4 v5 I: A1 n# j. o( P                        output /= 4;3 V7 C6 o* N( G% d6 p
                } else
8 e: l* d4 T: [2 j6 a                if( diff > 0x3000 ) {! F/ C7 l& Y; L8 b4 u. r2 `# [
                        output /= 3;3 H, e4 T+ m0 f* r$ C" E9 u# G# A
                } else
$ n# S' \9 p( Q( ?& Z                if( diff > 0x2000 ) {( Z! p7 h5 L9 i; K8 m
                        output /= 2;
% J. W, k8 F7 T                }2 c1 F9 |2 B0 I/ O. s7 N& u) x
                last_data = output;$ B1 q4 r) c+ E7 N  f# H  Q
                }
( n9 d, D: M, h4 \6 N* t% @* N#endif5 Q, [  v' w/ a) w7 B4 }: h* L
                // Limit
; v$ ?4 Y0 i$ v- i5 L0 h" g2 R                if( output > 0x7FFF ) {& y9 C) q/ j3 ~! V# {
                        output = 0x7FFF;( v/ F1 Z6 [  b& j; }
                } else if( output < -0x8000 ) {
1 e8 i2 H+ I! I1 U                        output = -0x8000;
  K9 b- v5 ^4 I9 O9 j                }0 E( k5 r3 l0 I8 d0 |; B

* r, S6 L  }2 K8 @5 A                if( nBits != 8 ) {
4 U1 R( v1 ?3 C7 {8 W# B                        *(SHORT*)lpBuffer = (SHORT)output;8 b6 z, C6 `) t' e" R9 j
                        lpBuffer += sizeof(SHORT);
! B5 Y& b' n5 _' z                } else {2 |) i* e" X$ N$ r) A0 H
                        *lpBuffer++ = (output>>8)^0x80;& X4 U5 K" |* z' [3 b0 `
                }
: v( Q, v7 M- P! Y! y/ Z% Z* \- e8 O3 E. t6 o; }
                if( nCcount < 0x0100 )
# [0 f8 B6 L% C' R                        pSoundBuf[nCcount++] = (SHORT)output;
: B* O& L1 c6 Q. c: X  e* _7 N
& g, `8 P& D; i  M//                elapsedtime += cycle_rate;
, P5 |: D4 q+ g! e" D                elapsed_time += cycle_rate;# }3 \0 o6 i% b7 p( ]$ \6 o% |
        }2 B8 w; s* F7 Z3 U4 E) \

3 |: D  `5 v1 S$ j! m#if        1
! F9 y6 S! v+ k% b1 K9 A        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ [* l  l4 \7 V+ V  u
                elapsed_time = nes->cpu->GetTotalCycles();9 u, a8 ]& `2 k! X# ?1 A; G4 N
        }
: P7 u: E' q9 M8 E" s1 `- y+ V4 _        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
* g7 N9 k, `5 L* d9 X  y+ M) ?                elapsed_time = nes->cpu->GetTotalCycles();5 x7 ]; Z, y3 p, H" X4 k8 d2 H' ], ?8 J
        }
6 E$ v, |3 o$ L. p3 y% X7 B#else  Y7 F; b6 F( [4 q
        elapsed_time = nes->cpu->GetTotalCycles();, V+ ]: D* F5 |' S
#endif
; u# S6 w& x3 D4 n: }}& T% P3 I1 V; Y: R. J' K8 _7 c8 Z+ N

6 G) F8 s% r# H$ o5 V9 E2 E' l// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)0 ?9 l. }! f  e8 q
INT        APU::GetChannelFrequency( INT no )
9 \5 F3 a$ ]% ^+ K% s( {* E{
8 \$ Z8 R3 k5 y! k* m  z. U        if( !m_bMute[0] )
3 h+ J5 {0 R: `                return        0;3 _, C" G" G! v- @& [) U
' W' O- `5 n4 t, W. n
        // Internal* _8 L2 O2 F; y
        if( no < 5 ) {
9 Y5 A( \/ Z8 Y: F: \3 z                return        m_bMute[no+1]?internal.GetFreq( no ):0;
# F# U( Y5 D- E: F! k( ?        }
9 k' B1 M- d! _# `        // VRC6
: ~4 v! g( m3 [        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {- m9 c. Q- q' v
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
- Y- ?# w2 Y. p$ f+ s        }
6 W5 [: b/ ~8 S        // FDS
" g( x2 Z& _5 E- d4 A        if( (exsound_select & 0x04) && no == 0x300 ) {
* g8 B# }; I5 R: e* I: r6 _7 Q) r                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; w' F9 k; s6 O8 I3 R+ ^        }
& v/ r0 D' {1 k        // MMC5
) F3 O& a  o  h' u0 V        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {# u3 r& o) N$ n+ q! _7 i2 R* N: F
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;7 p& n! k7 A* _8 ?0 }
        }% m/ D$ t% i% P: u- S! ~+ I" }/ \
        // N106
9 q7 p( I1 I; ]2 j2 }# P+ e        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 ^! }9 i* ^' q! z1 e% T                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# e4 M- e+ ^+ s2 |/ K. I# p        }
* h5 B& w5 s+ ^) o  Q        // FME7
9 H/ a/ u% R$ o. s        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
% g* [2 ^5 o3 Y6 K; M                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) A6 {$ s% Z/ e. Q; `) d+ G/ P$ @
        }6 F' s9 j" n/ n, \* ?* E
        // VRC7
# P* J- g# z( M6 G8 f+ O2 v9 p, p        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# B3 B' I& ^. L" C, @( F2 Z! w7 {
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;. ?% q6 ~4 w8 t7 y! W  r
        }3 ?; c% k4 \& @, c
        return        0;/ ~' u# v$ f& L* \
}
' @/ H- X% |' ]; Q; F& X. F0 O9 t; L
// State Save/Load
, k$ n9 d' @) Pvoid        APU::SaveState( LPBYTE p )
2 w# l  g# N! j, F{! B, z% C6 }1 `% X' W1 a
#ifdef        _DEBUG
4 A5 T7 W8 o% ^( @LPBYTE        pold = p;6 [+ o3 X# z' L7 d* \. c# Q' b
#endif  r6 w6 [+ k0 J: ]+ E6 J5 O5 c( t7 ]

( t' D! Z2 X( h* H# ?. m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
) ^. g, U% b4 @. q3 ^        QueueFlush();* r3 e  c; _4 c0 V# U9 e
; v/ m* R5 A; b7 n0 H) N6 o' @. [0 }
        internal.SaveState( p );
  D  T9 q0 b# l) T  y* t3 U        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) ^% k6 Y) @  W  }; t, W* ~3 ], m9 W& X8 V3 U
        // VRC6
' |# C* @- a, l        if( exsound_select & 0x01 ) {# l( P2 s5 r8 G
                vrc6.SaveState( p );
+ [1 {" ~% C& }; t) k( F5 @' |. H7 m                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ s9 n" X' B8 k9 Z$ Z% L5 G! _
        }: i- @" V. V0 a0 @# F9 G
        // VRC7 (not support), c7 j9 f/ a- A
        if( exsound_select & 0x02 ) {
% r4 e3 A: x/ J' K3 b8 u                vrc7.SaveState( p );
$ }" c! ?8 M1 M* j5 ]                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
9 e1 J% y1 ~! s: T3 f        }4 l, |5 L- }2 d' R5 B
        // FDS
& V7 @* @# a3 F9 n! k        if( exsound_select & 0x04 ) {2 d# @+ h* o- M3 r" b# }
                fds.SaveState( p );
" @4 x- E+ ~2 r1 K0 o6 B9 P                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& _+ r( M2 r+ Y        }. l# E; b1 }1 `( N4 c
        // MMC57 p7 @% `- K2 R% U
        if( exsound_select & 0x08 ) {: y+ C  n9 U1 D/ V/ c
                mmc5.SaveState( p );) C8 o+ l) D; N( a: U( j
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
, U; \9 V1 G4 d* G+ F" N9 k- {        }
* j& Z. k% h5 f. y( P        // N106
! C# Y4 |% Q2 j7 x  T( Y        if( exsound_select & 0x10 ) {
9 T/ Z. d/ `5 j2 R6 r                n106.SaveState( p );. g) C$ |' t% k4 G  L6 b, d
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding# A' x1 d2 f  ~/ |2 C
        }
! w" U/ V9 s8 C, v6 n5 E# P9 |        // FME7
9 h+ C) f; [+ d3 f& `( e        if( exsound_select & 0x20 ) {& s$ p- \; k1 y
                fme7.SaveState( p );: x9 b6 D; I) Q& y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ o; S* L2 N/ `) I' K; }
        }  Q. u$ ]8 p  m3 p2 o

& p" E* i7 h" A+ v3 o#ifdef        _DEBUG7 l$ h4 ^2 K6 l, z
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );6 q( I4 v/ r1 w8 u7 r, @, x/ V* W
#endif0 D; N* R# e; ]0 D9 B
}1 `1 u8 _4 ]! B

! e% U4 P  B. wvoid        APU::LoadState( LPBYTE p )# g- {/ z  [: z( X" f# n% I
{
4 `4 O- e8 Q( Z1 G        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
5 L: D9 A$ G7 Y! N# r: b/ _( a% a        QueueClear();+ C! _( w8 k" H. j  b

4 j, J6 g5 h; y, b        internal.LoadState( p );
9 \: v+ [( D$ o* `, ^: D" g        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 ~* B& `7 G6 X3 n: |
$ |6 v, ~3 W: r2 X/ @, }        // VRC6
  `: C3 U) Q+ v        if( exsound_select & 0x01 ) {
/ _) a) p8 ^4 f3 c* {. S, D0 C/ y                vrc6.LoadState( p );1 q8 f3 F: |0 m9 W( ^, c
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& w8 n% c! {. E, C8 G
        }
; i: w" w- T# P  Q        // VRC7 (not support)
) K; x0 y; Q% q1 Y3 i7 w" |        if( exsound_select & 0x02 ) {
7 e; `* M$ L0 J  \4 z6 h                vrc7.LoadState( p );7 M2 l. a' f, C( T/ s% g6 u
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ V$ Z# I: A4 a- k+ h4 H1 o
        }
  }2 G3 l9 E6 d* y3 H: U% r        // FDS
! o' j- i4 J/ Z5 P4 W! m        if( exsound_select & 0x04 ) {
6 H+ F0 O% j3 q. o$ q& Z                fds.LoadState( p );& E( v0 p( R$ ?- X; t: x
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" e# p6 M0 B, a5 ?3 Q        }8 _' W' F- Y9 S6 O1 a* Z
        // MMC5
+ w7 e0 u% \6 C/ M+ m" h        if( exsound_select & 0x08 ) {
- ]8 }/ s/ M2 E7 G  S. ?$ G2 E                mmc5.LoadState( p );
/ z' e- E5 |9 a" o. B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! ~/ _$ G" {$ H; e4 ?% r% Z        }
8 ?( X+ q' X$ k3 o% p; _8 y        // N106
( x' i# }* K- Y& r  Y$ z        if( exsound_select & 0x10 ) {, p" r- s, P; w1 n& T) n3 E
                n106.LoadState( p );" H. c; B6 b/ J! ~- Y. \, b1 x1 ~
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 h* I1 H+ V) }' w/ p        }
" H0 a& O" E$ x4 K        // FME7
. X1 I1 t  g0 p2 K  S        if( exsound_select & 0x20 ) {1 h) j" y4 m% n7 N( e
                fme7.LoadState( p );
5 o  D; l; m! s: F' _                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 s5 Q% ~- R$ k( e) c9 O" L; S
        }
2 M, i3 Y% {6 T" G. E}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 9 \5 f: ^' d; x9 {# [* t/ ^
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 ~+ S8 o/ b2 N) ?  V' M6 W" B% d8 r
感激不尽~~

3 n7 O9 @2 K% y9 l: z恩 我對模擬器不是很有研究,, }, Z3 S  ]# ~$ d! P
雖然要了解源碼內容,可能不是很困難,/ l4 c' X1 w( b- I& _
不過還是要花時間,個人目前蠻忙碌的。
4 e' z7 R7 X/ _! x" G0 T7 p
4 z. i% J/ X8 I9 O給你一個朋友的MSN,你可以跟他討論看看,  _) E9 r" I) x; g& S* g) I0 k% H
他本身是程式設計師,也對FC模擬器很有興趣。2 X+ I* @; Z  n+ \: |
% D1 K1 E4 b* C6 }1 d9 \% @+ k
MSN我就PM到你的信箱了。3 T+ ?$ o2 p8 {, V) ~

+ Y3 i- I5 T8 e希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
" \6 K  \! g0 x, X, ?$ F6 ^呵…… 谢过团长大人~~
0 Z: O3 c' y3 H( ^) y: M( _5 O
! ?- w7 J% ~1 S" }1 p% P9 x. Q1 W
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ r) y: @* M2 K" ^团长的朋友都是神,那团长就是神的boss。
6 I5 D% U3 ~/ K' G
哈 不敢當,我只是個平凡人,. Y' D$ m, ?) J- N( X
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
/ e1 ^5 Q! \- T, F0 w9 M. bZYH
" j+ U, I! }8 X% ?0 K2 t) @QQ:414734306
; T* m- U- Z- c2 f9 m: PMail:zyh-01@126.com
6 l& o5 k8 B* q! i
' E# F3 q; S/ |8 M( s- D" i. s他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * r" W3 ?3 ^7 h! Q, T7 |. b! j
再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ M0 |5 h- p, m! C: ^' c3 e不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-11 18:51 , Processed in 1.096680 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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