EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
2 }* x! v. Z, T; f& K: S. k6 h/ _( UPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, y: j9 {/ U  i& e/ h- w  |
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 m. V- h( a  K) C" p
这里有相应的模拟器源码,就当送给大侠了~~
/ P; l8 h" C& `! s( E) Phttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
) B$ m! d, t% V能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# f, ~. b+ g1 i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- d4 a  L# |( z/ P7 Z" N
这里有相应的模拟器源码,就当送给大侠 ...
) v$ d2 J' Q! L( W$ h. A* C& h
聲音部分(Audoi Process Unit = APU):
7 ?/ ], x# L9 f/ J* s) q.\NES\APU.cpp  a7 k8 f& t# I0 @( ~" ^9 a
.\NES\APU.h( K2 c' L6 D, ^* Q1 _
: d, e1 G! O, M, s* f
& R) q0 A. F0 V4 k
影像處理部份(Picture Processing Unit = PPU):
) t* q& o# j: j) a( f* Z.\NES\PPU.cpp
" W4 |4 }, h7 o! x& G.\NES\PPU.h
$ Z. ^& R' B# }; B" N7 S. q+ }+ p1 w
: |  h' @$ q; z; G# ~2 a- @* ^如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:6 S9 j' V. l) a# ?9 h( R: y: I# I
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 s# {+ F. V0 s$ C5 J6 p* N//////////////////////////////////////////////////////////////////////////
6 t4 p) M7 B* ?7 ^4 u9 ?//                                                                      //( ~, p8 {0 ~; \" c/ D# v
//      NES APU core                                                    //
4 D' N: u, i2 j6 U4 z//                                                           Norix      //
% o- O0 q2 A6 C5 n6 T# s# G) \( u//                                               written     2002/06/27 //
; O. L  R. _* q1 s! G7 g/ A& d//                                               last modify ----/--/-- //
9 B5 u* ~/ I6 x" F' {! I//////////////////////////////////////////////////////////////////////////% G9 h/ T6 }; D! H  n0 {
#include "DebugOut.h"
+ N& e9 `" Y, D+ Q; t' y) D4 h& ~#include "App.h"
; a1 N" t) H/ W+ ~" Q6 e3 {2 w' M#include "Config.h"6 o, ]6 z) b8 i( D+ g$ Y. [" G
6 [% s0 n) `- e6 N6 x' ~
#include "nes.h"
/ K2 R" U5 e- a& P#include "mmu.h"3 J/ G' H/ u4 e. I  x9 m9 m  ?5 ~
#include "cpu.h"
, b$ K0 ?+ D/ h" m, i9 e3 V- Z#include "ppu.h"
* V* o: }0 A8 @% U, r! v7 W#include "rom.h"% E0 q6 P8 B/ E  F1 d
#include "apu.h"( E# p2 u  M2 r6 }) V

0 R: L* A7 E. M' ?3 o// Volume adjust
* U# A% A9 i; E4 O, t' {// Internal sounds
+ b6 z  O' f/ V+ s# ^6 y7 K. h6 `#define        RECTANGLE_VOL        (0x0F0)
& l) \% ^- J7 w" a#define        TRIANGLE_VOL        (0x130)3 e; u/ k% I' A
#define        NOISE_VOL        (0x0C0)
  j- `6 M* X& Y; }#define        DPCM_VOL        (0x0F0)
: E! s/ `7 D8 t: S' J/ q// Extra sounds+ z' {0 m+ m- p8 v. y
#define        VRC6_VOL        (0x0F0)
$ _/ H' Q- @5 ^( ]' u/ g#define        VRC7_VOL        (0x130)7 `4 |+ t5 T" f
#define        FDS_VOL                (0x0F0)
! ]/ R' T+ E- l- @8 \$ [5 F3 d#define        MMC5_VOL        (0x0F0)
* {7 e: c- \' P6 u" W4 @#define        N106_VOL        (0x088)% v% h/ O2 M. X: E; Q
#define        FME7_VOL        (0x130)6 D" s6 p( @: W* m6 _
" G! l. W& j' \/ O/ r. r
APU::APU( NES* parent )
8 C( i* l2 }" P7 n. Y{
' R/ Q2 X+ k6 d" c. t& j' B' N        exsound_select = 0;7 i: ~# q6 U1 e( {- h
3 A# }5 c7 v7 S# z2 ]: q6 U
        nes = parent;
' u- w: w% f( K7 I6 S9 j/ o        internal.SetParent( parent );
) A6 a2 c5 Y/ A- D+ e1 C
8 r( j+ I4 u0 o, W2 I8 t3 {        last_data = last_diff = 0;
# g2 x# s  j, [5 {0 _9 C& m2 g
4 R3 E/ C* M, T+ d" S$ H4 u        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
0 [; k& e& q8 p# q( Q, u
: l% {# _2 R; F" x8 J+ G$ A+ O) n        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );1 p; q8 Y  y! R1 @* D' N; s) v
        ZEROMEMORY( &queue, sizeof(queue) );
: M+ u/ M7 Y7 L+ t( q        ZEROMEMORY( &exqueue, sizeof(exqueue) );  a. Y' a5 }6 u) H9 J2 @$ L
6 K, L1 ^9 a- I9 \) n
        for( INT i = 0; i < 16; i++ ) {
! L+ J- P/ c, i1 a# m6 o3 |                m_bMute = TRUE;! V5 i+ u$ n' q+ p& n
        }
1 L  [" X8 h$ t3 i7 A; N' u0 [}( U3 b% N/ A- L3 X
; H. E6 o6 r. o/ B$ k) l# g
APU::~APU()
8 w) Y7 j0 b* J  U, |: |{
$ h- q$ F" p" Z}
5 D5 [8 |5 p' G) Y, e* T/ p
% B3 v% k" H+ K7 y  rvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 t/ W$ l# j+ k9 `" X
{- ~, L9 ^& y% u
        queue.data[queue.wrptr].time = writetime;
  r3 C4 f% C8 T        queue.data[queue.wrptr].addr = addr;
) M% [- C' c/ `1 V        queue.data[queue.wrptr].data = data;
5 J- W) U6 `" e+ P        queue.wrptr++;1 J* g' k3 k, F$ d
        queue.wrptr&=QUEUE_LENGTH-1;1 c# F* p* C, |" U2 R
        if( queue.wrptr == queue.rdptr ) {( ]$ ]0 O" n* T8 ~: l& q1 R9 n
                DEBUGOUT( "queue overflow.\n" );' g- ]7 ^: ]# L5 C, Z
        }
+ ~/ S- L& _' b5 p0 q- w}
2 ]1 k* X6 Q; z1 V
) T1 Z- i3 ^9 M$ s' S( pBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- o  l4 }  B2 b; b{) o! S0 g' t# V7 n9 r; R
        if( queue.wrptr == queue.rdptr ) {2 v( ^9 G# J  e+ G) O3 _
                return        FALSE;
, F3 S% f/ ^4 |2 r' J        }
1 M. \1 E3 k; j* c2 w  k        if( queue.data[queue.rdptr].time <= writetime ) {
5 ?, |+ F! C" T; Y- I% h                ret = queue.data[queue.rdptr];
4 p6 j! h7 a& ]- E/ Y                queue.rdptr++;
" n" \1 |* A0 w                queue.rdptr&=QUEUE_LENGTH-1;5 F$ Y9 ]1 f7 T* O3 d
                return        TRUE;$ Z0 I+ {+ t0 C0 [7 I; Q* x
        }4 F4 |7 K2 C( H3 {
        return        FALSE;2 g& [  `# ~3 q7 F- ]
}$ ~$ e7 w: U) [) q) O  S! A
: U4 ]4 x) r  N
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); K" m* Y! K% |% H9 C3 `. T+ f6 o
{( k. q: M2 P+ ~1 K
        exqueue.data[exqueue.wrptr].time = writetime;
$ L* f! a; N2 g6 Z5 M- n        exqueue.data[exqueue.wrptr].addr = addr;
, D, {& H4 S; L( @  i% o* x! Z/ E9 Y        exqueue.data[exqueue.wrptr].data = data;
: [" L% b, F" @7 k; U& E2 L        exqueue.wrptr++;' s; Y3 B. i0 |/ j( M0 s
        exqueue.wrptr&=QUEUE_LENGTH-1;
( `6 H( L! [2 ~8 [        if( exqueue.wrptr == exqueue.rdptr ) {
5 V% F$ v6 ]6 W* O; Q3 H' ^% k! t0 b                DEBUGOUT( "exqueue overflow.\n" );; r2 j0 h7 ~, Z4 F: z, ^+ ?: ?
        }
! O/ Z1 Q/ O/ n  }. G7 ~& m! s! L}
( I8 _: U- T4 D$ {; D6 F6 J) Y
# a$ _1 v) |! L5 ]- TBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )8 l4 p. v, t# d# D. a
{
7 f+ k1 j! V& z. a        if( exqueue.wrptr == exqueue.rdptr ) {- U1 f( w9 ]+ [
                return        FALSE;
* g* b! s3 P' T/ \# n4 f5 h        }
7 R5 \) T6 B' n4 g8 {& J, e        if( exqueue.data[exqueue.rdptr].time <= writetime ) {6 h; o2 t! ]- [' _/ t9 j, c
                ret = exqueue.data[exqueue.rdptr];) z+ e9 T# V4 }; |2 Y! v- T
                exqueue.rdptr++;4 c: e* ?6 {0 g, [% |( E
                exqueue.rdptr&=QUEUE_LENGTH-1;
+ p  n' X7 m5 _. J3 C                return        TRUE;8 j0 v7 U8 y$ l' t/ ?  R
        }8 j7 h8 b6 U0 e# }
        return        FALSE;0 d+ y" W# |0 d0 j; O% h- p
}
. K* O% c3 f2 q& M- Z: m  @: Y1 L+ E
' z% w" p$ r( w) Q7 r' ~void        APU::QueueClear()8 ^. z% h) j/ l8 T
{
1 C1 f  P6 j. Z( q        ZEROMEMORY( &queue, sizeof(queue) );, J$ Y$ m3 E, z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( H. ^( w/ o* N/ E. \' A}
* f1 Z5 L7 m/ Z& w5 \
. C/ ~4 q" S, R- X; Lvoid        APU::QueueFlush()
' B7 F7 W6 {3 ~6 d' B! B" `( L0 _2 y{0 q$ h$ Q8 e/ C( f$ S  `' N* \# G; n
        while( queue.wrptr != queue.rdptr ) {0 Q" {! Y/ d0 L3 h% b) b, \
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# ~: ~7 w% X* r+ {! _; y" O
                queue.rdptr++;
/ q$ t8 W: J: B' `$ B" z4 U3 H                queue.rdptr&=QUEUE_LENGTH-1;, \$ }5 o$ Z) P! B5 T: w
        }, H6 ]3 R- X2 [3 c2 k( @1 Z. {

3 x4 {4 D, m3 M+ A1 w: p9 R        while( exqueue.wrptr != exqueue.rdptr ) {
( x4 U# f8 _8 {3 p$ J; i                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( U4 u, T1 z9 A3 w' Z6 S2 `+ o                exqueue.rdptr++;
; y5 x, C, M$ i3 y- }3 y; P( @# ~                exqueue.rdptr&=QUEUE_LENGTH-1;& Y4 j0 f# w# [5 ~
        }3 O7 x4 L5 B0 q4 l2 ?
}
$ J1 B' z8 ~+ j. q( J* g5 o; S2 \4 _
void        APU::SoundSetup()
9 t- x3 r* {1 W4 ^0 ~6 a4 m+ z0 D1 f{
8 T- H! W4 ?& M& j0 {8 V' F+ N        FLOAT        fClock = nes->nescfg->CpuClock;
9 I4 q9 V+ u5 h        INT        nRate = (INT)Config.sound.nRate;
' d9 V: k& L/ g. h5 |9 ~        internal.Setup( fClock, nRate );
1 H; E) [0 K2 j' m        vrc6.Setup( fClock, nRate );
* ?( C, S7 g) M+ i# B+ K: x        vrc7.Setup( fClock, nRate );
; w  ]* m; u) M- R4 i8 {        mmc5.Setup( fClock, nRate );
- k! l& A! V& C2 M' m3 R) m  k        fds.Setup ( fClock, nRate );1 |  T4 t; f- ~% K
        n106.Setup( fClock, nRate );. _7 J$ z6 i0 A& K. e" ?
        fme7.Setup( fClock, nRate );) {8 h8 j) L- y6 f
}5 t1 d0 a$ _# O6 W
: F, Y/ N) T/ Y( V8 w3 P% l% Q
void        APU::Reset()6 K. f2 T/ x7 ?' Z3 ^, ?0 ^
{. A+ g  U: {. m; ]
        ZEROMEMORY( &queue, sizeof(queue) );- e! v; b' h* i: {6 |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 d/ ^1 _4 F7 J, a- \
, ]. X( S0 i- g% F. k: c
        elapsed_time = 0;$ {" s( i9 y/ w9 p

0 f/ S: \3 ~8 H4 H3 l0 M7 L6 R        FLOAT        fClock = nes->nescfg->CpuClock;: |5 N) [# c; J" d0 c1 Z5 N$ [' X
        INT        nRate = (INT)Config.sound.nRate;6 Y4 j. g8 ^8 T5 h- b
        internal.Reset( fClock, nRate );
* N+ q- l2 I) J( S. e) q6 @        vrc6.Reset( fClock, nRate );
  V3 Z) ~8 _9 w+ U' ?3 ?5 V/ f8 C        vrc7.Reset( fClock, nRate );
# z4 Q& H' M# c6 d        mmc5.Reset( fClock, nRate );
; l: b. C7 I3 `/ J# L, T        fds.Reset ( fClock, nRate );
) h7 Q! s+ V% l        n106.Reset( fClock, nRate );
& @3 p$ E1 u5 S        fme7.Reset( fClock, nRate );
) t& E" K' G: V$ h& X! j" z1 W
. ^6 ?2 b# Q& X6 t% b, F* a        SoundSetup();
# M2 U3 U  C) h}5 m5 {- F5 H4 j4 c* G8 Z6 y% X4 n
5 I& B% r1 k$ }) J9 v- ~
void        APU::SelectExSound( BYTE data )- v8 d2 e# o) _  q! m0 r8 c
{- s- E: M0 Z5 E4 N+ _+ I
        exsound_select = data;* m  _5 X* y$ ?: ~" D* |
}
8 q9 |  b8 g% Z/ A1 N4 \! \- W3 _
: k% Z8 @7 V3 j, M0 Q. SBYTE        APU::Read( WORD addr )) a  h2 Y6 L$ B- @; n
{
3 z7 t4 ?' y& t6 ~( `) ~5 F        return        internal.SyncRead( addr );6 ]; \7 _  A6 v% \
}6 V% @, \6 Q, B1 D" h

& W3 S% r% v4 H7 Y. Z% n, M1 Xvoid        APU::Write( WORD addr, BYTE data )6 ?3 w  A6 F/ s& c" \; k
{
& u$ T+ G8 o" x* g        // $4018偼VirtuaNES屌桳億乕僩
* m3 L# X1 y5 a# b9 _        if( addr >= 0x4000 && addr <= 0x401F ) {
  `  G6 q  \- h2 P! ^                internal.SyncWrite( addr, data );" a3 z$ w( V: K' D1 v4 B
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
0 T- O0 s8 Y5 R6 m$ O3 B        }8 M; I* a) H* f6 J  ]
}
6 ^5 x" s* V3 N/ B1 B4 y
& e& W5 s) U; v% \! [# r, ]+ u* HBYTE        APU::ExRead( WORD addr )' K0 P- t4 |' M2 T, Y
{% Q+ k% J# I2 O' \4 M
BYTE        data = 0;
/ F3 R$ S' Q. Z: J
$ X. i! ?3 `. x( E        if( exsound_select & 0x10 ) {
" U5 v9 @1 n( M) p" D" C$ ?: u  {) L                if( addr == 0x4800 ) {/ s! `' l! }' X4 c( J* E; x  d
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
8 o' n0 s) z6 }# ]/ r5 A                }5 b8 B4 t/ F( L" _( U$ t1 v
        }
. _( r- v  X2 {        if( exsound_select & 0x04 ) {/ S2 ]- A0 {+ `: \& p+ j
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 x; Y! Z/ h5 Z) n; L                        data = fds.SyncRead( addr );
# y! |+ T4 v# m                }; `5 R  n0 |0 B3 |0 f  b, M
        }3 Y* g7 u% T+ K4 M2 [" Q* d1 g: ?: o
        if( exsound_select & 0x08 ) {
0 z% J; R6 F6 _6 m# p' O+ c                if( addr >= 0x5000 && addr <= 0x5015 ) {, h/ X% K) i( x: Y6 z
                        data = mmc5.SyncRead( addr );5 `& j' G9 L" k* |. }# b) R/ l
                }
$ ^' M- b- ~: g        }
- D( \( S5 @  i: z( r$ s
7 {; E- G- U- d; e2 i4 ^        return        data;
" b: k0 h. D( U$ G& Q5 m}
' Z5 N1 D  D) h8 {' p  m
6 @' D3 U! c# `8 m6 ~2 c. M+ ~: C2 q5 rvoid        APU::ExWrite( WORD addr, BYTE data )
7 [3 {8 r( e  u' T7 Y& i! ?{
$ `# O$ F: r3 c8 w8 C        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
  p2 Q: V9 c! o. k2 f
1 x8 m4 @% b9 h4 }; h" z8 q* r        if( exsound_select & 0x04 ) {
& M" N# N: T' n: Q) _                if( addr >= 0x4040 && addr < 0x4100 ) {
, Z1 a( f: I" L5 w( v4 M% `                        fds.SyncWrite( addr, data );
2 i1 ~9 G+ d# \! B! k# R: m/ N                }! z1 d& x" i5 |! z( i1 M
        }
  w) B6 r+ A* s- |; _5 }. q) Z! a* s& c  L- x
        if( exsound_select & 0x08 ) {% ^. a+ m" X, v5 l1 f) G1 ?" Q# R8 K
                if( addr >= 0x5000 && addr <= 0x5015 ) {2 `$ Y/ L$ ^# I, n1 ^
                        mmc5.SyncWrite( addr, data );2 p/ S$ x) Q* n1 \! v7 M/ n% r: D
                }
9 f7 S, m- a2 ^        }
% T7 S  A4 A+ F, h5 j$ K, P}* Q8 _5 Y9 J5 w5 p/ |
" N: a7 `1 D/ Q3 `, t, i
void        APU::Sync()
+ V( T- w, \! X1 `6 v" p; D) L( ?; z{
' g% G% P7 k) ^$ R, a}
0 w5 A2 p8 Q4 J" e) ]
8 y1 b1 d) G* P- a" Bvoid        APU::SyncDPCM( INT cycles )( w+ s! f* d# L! q3 n) c
{( m) _) P$ l. g3 R/ \8 S7 ~
        internal.Sync( cycles );0 }5 X/ z4 Q" m/ ]
! B6 \$ M/ t3 t( q# q2 n
        if( exsound_select & 0x04 ) {. C, n6 x( O$ ]! ?; p6 I# ~
                fds.Sync( cycles );
: p; s" }+ M3 F/ J9 I8 c/ Y        }7 r' @. ^  t9 t* p: G; m7 L
        if( exsound_select & 0x08 ) {/ z% f' O5 x" N$ E9 O1 k% y4 c7 B  t2 {
                mmc5.Sync( cycles );
9 \/ p: F, o! X- K- J4 \        }
) _1 D$ E! M: n& r}8 l' R% s  B9 l; d" ]

' |6 ]6 R7 `/ I  E: Fvoid        APU::WriteProcess( WORD addr, BYTE data )
' i" b, j- o% s{
' j8 p4 @+ g; S' U: Z        // $4018偼VirtuaNES屌桳億乕僩* R# [& I# r8 |0 v9 f
        if( addr >= 0x4000 && addr <= 0x401F ) {' A- v; C7 D) X9 Z$ H1 f
                internal.Write( addr, data );
, D& s/ }, N) b" e$ q        }
7 I6 T$ k& W9 M$ Y3 t( ^& K}
. V/ ^8 Y% z- T7 l+ j) e( Q+ j" ^9 H9 y
void        APU::WriteExProcess( WORD addr, BYTE data )% S/ C3 H4 x) v
{
, r+ c7 X) W" ^) x3 Z% d        if( exsound_select & 0x01 ) {
& u: T" x1 x- Z1 P                vrc6.Write( addr, data );
8 w+ ?; V, V& c+ f$ Z        }1 l7 u9 y: G. @% C) Q/ p2 u* U
        if( exsound_select & 0x02 ) {
' }1 Z+ ]" |. U# h$ M: v                vrc7.Write( addr, data );
* p7 E8 |2 T/ V0 B+ K% }  o        }5 K& h1 ~5 B0 @% D2 |) c4 o
        if( exsound_select & 0x04 ) {8 `7 R1 C  ]! i1 p4 A( e
                fds.Write( addr, data );& N  N6 S2 ?& j; ]* Q' c
        }& C% T2 f$ m  z8 ~( l. n* b
        if( exsound_select & 0x08 ) {% t3 u+ V) F/ i
                mmc5.Write( addr, data );
+ l5 x) Q/ t- Y! A        }$ M% k* L- M/ u$ {3 ?
        if( exsound_select & 0x10 ) {
* r& c1 e* k5 p) V% O2 V                if( addr == 0x0000 ) {# |; f) j0 K* a% U2 N
                        BYTE        dummy = n106.Read( addr );
  i$ Q6 t1 l; a( w                } else {, z3 a9 n) X( y0 a9 O1 O
                        n106.Write( addr, data );8 M7 z" B2 s, ]$ o+ Q
                }
+ Y7 ]2 K6 ^( I        }
# j2 B2 B! S+ _# ]- \0 T        if( exsound_select & 0x20 ) {
" }, Z& ?* K+ f% b1 S2 L                fme7.Write( addr, data );6 G! `, o# P: W2 @* O
        }
6 ^; y6 u/ j1 D( _3 P/ e0 ]/ j}
% d2 U2 n! X+ {5 Q0 j8 N- i7 Z" }  p
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
( @. I; n5 ?9 L& U2 s{
: c2 R5 t: z" u; a' R) Y* ?INT        nBits = Config.sound.nBits;# b9 ~9 [, Z1 Z. |' f. i
DWORD        dwLength = dwSize / (nBits/8);, x! Y! Z" p/ r' O( d) {  [' B
INT        output;! C' |6 b) r# K
QUEUEDATA q;) H0 B( L2 G" l! X0 c* c% P8 S) r
DWORD        writetime;
$ `- B2 C+ @) r) E- `4 x+ ]' p; k
LPSHORT        pSoundBuf = m_SoundBuffer;/ C5 a  B6 E% Z$ y2 }) y0 S
INT        nCcount = 0;+ [6 \0 f4 \: F" |# s' `# T

- a% v9 w! }) ~9 Z6 o5 N3 c3 iINT        nFilterType = Config.sound.nFilterType;  h; f" {5 K8 h7 N# a0 t
& F, ], g) F% d
        if( !Config.sound.bEnable ) {& \% O0 E2 h; f1 @% x# @7 i" t
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; Q/ F* ^3 v4 m; \8 y6 C- L
                return;+ U" ?/ U: V! F% M
        }( f# s: X6 Q  B( M/ M% b0 @! a, [

: {- ?7 ?4 d2 T  C        // Volume setup
$ }3 S4 O: u  ^8 n0 D& h+ b. f        //  0:Master
+ \3 F3 H( }3 X        //  1:Rectangle 1
0 T# d4 f( z+ U        //  2:Rectangle 27 H! S8 V4 C' l4 K
        //  3:Triangle) Y% @1 v% b9 Y8 z! p. v# \/ s
        //  4:Noise
3 y) y1 ?# _2 n; q: j        //  5:DPCM7 A5 e- o* V/ z/ ~: ]5 b
        //  6:VRC6; {$ T+ w6 g! `. e
        //  7:VRC77 N( Y1 Z8 V: H" d2 w
        //  8:FDS
) W8 g7 G6 |7 h/ C2 w        //  9:MMC5
/ G5 t( H; M: c        // 10:N106, I" W# K, E3 m) W4 d
        // 11:FME7
4 F- p" I/ B6 D* p, E2 {) w        INT        vol[24];7 N" k% W4 q  u$ }* V- q7 f
        BOOL*        bMute = m_bMute;8 Z, G. L5 }4 c( W
        SHORT*        nVolume = Config.sound.nVolume;
& |( E  z6 O! K% M3 o0 @( [# P; K  A3 L- s9 }( J  T
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
7 C9 K$ W' K; v5 J! W! Q" B8 ]( j$ R) i9 S8 {5 m9 S$ k8 e& i
        // Internal# K3 F8 m$ N# G. r+ X9 R8 E
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 S1 E0 _! M9 @  _        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
7 G4 I, z+ X" T# a4 v, _        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
3 g( i; v" Z# |" D  X        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
# A8 J$ w. @. j        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ a& k) s, U' c! }" b9 B1 T9 M, E9 F* j
        // VRC60 Z/ l6 @! T. v( L5 A& P8 r. j
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 f) ?" r7 j7 |9 x7 }        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 z5 m* `/ F; [$ l  G% i
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( x- n3 `# M/ l, A5 S
$ _5 m4 n9 [9 {3 u        // VRC7
. c# v7 e! |4 @* ?! M8 F        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. L0 q" t3 }2 n0 {7 R* P$ m3 I

( h' @, D4 J2 G) {' C* e0 y4 v4 @        // FDS
7 h# S: \2 E) [1 g7 H9 S        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;. {. _& ]' o: B

2 L" g7 T4 G4 ^# F7 E8 F  A        // MMC52 [. Q5 S! W) S  S
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 T8 O2 j; {: j7 v) l        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" y( O1 k+ F, |! r/ v4 A9 ]  `, f! d
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( y  l  G/ m. A6 n# }9 R
9 T3 V" }9 V3 W; g- C; z        // N1067 N$ V" A) V' [) y: g
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! P6 Z1 F0 ]% u7 K9 ^6 |+ }        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 O, \: z, o5 u; k2 l; O        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. K0 F$ U# F6 Y( W; r/ D) t' O, e! s6 p
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& r& R! a6 Y; E& s0 T/ f$ n; l, T        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! Q4 i: Z, R" O1 S6 C: G' c2 Y. Y
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; l* F1 B( ^4 W+ |8 F
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 E3 m/ Y* ]( t  S* B        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ `$ b' j5 k! a6 l
9 K4 G: Z0 T  B3 L% d; s) I        // FME7
2 Q- }$ q" J9 t' P; P" D        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 ^* D$ D; p; o7 a+ s0 F1 D* I% m
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ N# V! Y* r1 Y        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- Z6 J( s" O) v2 [. ?& V5 B& H$ `* N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ l$ x3 w" u0 T0 K& C1 \) Q2 K( i2 x
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
! S$ I% d/ e6 i, m; y& a  |" `& v0 g) ?9 h
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
2 {' N/ \+ _- t        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
' v' G! e: E' U( B9 C' T                QueueFlush();- \, x& s) [  O6 v" B
        }( p4 B" Z7 b7 @0 ^" R+ k5 o: R

) e5 W- g. c/ \        while( dwLength-- ) {' N8 w* k5 A2 ?) C, X6 r% }. H
                writetime = (DWORD)elapsed_time;
" x6 Z; _3 _3 ]: }% s* H6 B- g5 T% M3 s# U5 M
                while( GetQueue( writetime, q ) ) {
- q) [/ `. B- Q# m                        WriteProcess( q.addr, q.data );
1 z( R$ w" x4 l# n- w                }
9 @! b* ]2 B0 @' Q3 d
* J1 T- n9 E: [% D                while( GetExQueue( writetime, q ) ) {
& q+ b1 s4 d3 }                        WriteExProcess( q.addr, q.data );
$ Y9 e# |' f3 b* T1 d6 |                }# l9 @: l6 k0 n1 R9 I

, [* J0 W; r3 X5 o; o                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 ~' y( _$ [% Q1 V$ m
                output = 0;
5 Z2 _3 _- S. V2 u, g' i' i$ t" r                output += internal.Process( 0 )*vol[0];
) V7 {. D" |$ d! m6 r, i9 y                output += internal.Process( 1 )*vol[1];8 T- }3 A% O4 t3 t6 m& q
                output += internal.Process( 2 )*vol[2];5 {/ [. l7 x2 T' g0 I, r+ R
                output += internal.Process( 3 )*vol[3];: o* \( f' J; N. n+ {
                output += internal.Process( 4 )*vol[4];) i! e" v; w4 G" n8 G2 g

1 u9 U; z: J" s                if( exsound_select & 0x01 ) {' W) W: `6 N/ E
                        output += vrc6.Process( 0 )*vol[5];
9 [  R0 T8 F9 l: ^5 p) j8 y' m  G                        output += vrc6.Process( 1 )*vol[6];
; ?4 ]3 s- b( f1 e' X/ ?8 J0 N, }                        output += vrc6.Process( 2 )*vol[7];
( _5 I' i7 H6 Y/ x7 z9 C                }
* S( G' D  U. g5 f                if( exsound_select & 0x02 ) {
% M* K) o  C6 Z3 ~9 |/ {                        output += vrc7.Process( 0 )*vol[8];
/ |6 L! }7 K. h: |1 x                }9 \: A9 p. S* M
                if( exsound_select & 0x04 ) {  K" g; _8 z+ O# ^$ z
                        output += fds.Process( 0 )*vol[9];1 E) s# ^5 r/ P6 e/ E" M
                }
! p4 }5 `, c! V& _3 k  A                if( exsound_select & 0x08 ) {
# Q& g- F5 ?4 S' v2 a+ o                        output += mmc5.Process( 0 )*vol[10];
6 a$ U9 v7 l5 q  Y3 r' w  E                        output += mmc5.Process( 1 )*vol[11];
7 T5 D# P  U& V" S9 d  z                        output += mmc5.Process( 2 )*vol[12];. y) z  V; l/ V, G7 D% A
                }& e" |" [  g5 w  ^  u- p8 D: I
                if( exsound_select & 0x10 ) {
. f. J8 }4 O$ m  l% d- y                        output += n106.Process( 0 )*vol[13];' U, C2 w, `: u, Z/ ]' r
                        output += n106.Process( 1 )*vol[14];7 K6 b! x7 L: w; @' H
                        output += n106.Process( 2 )*vol[15];8 C; v, O3 g! n, U2 }- |
                        output += n106.Process( 3 )*vol[16];
$ }6 ?% J) ]- n, c- S; X                        output += n106.Process( 4 )*vol[17];
9 K, B, k! Q5 u$ k/ p6 }: c  O                        output += n106.Process( 5 )*vol[18];
. I: ~; ~" k! n; F/ O6 q( O                        output += n106.Process( 6 )*vol[19];( Q( o3 g; h1 ^/ h' J$ X8 y* t
                        output += n106.Process( 7 )*vol[20];
( h2 e- Q2 l2 E2 _! Y                }
2 U' S2 W/ g! {0 Y  i" Z3 @                if( exsound_select & 0x20 ) {
# n: x6 V3 @5 F3 P( C& }" I& u                        fme7.Process( 3 );        // Envelope & Noise! C! _3 n$ ]- Q; N& I. Z. T/ i3 V
                        output += fme7.Process( 0 )*vol[21];
+ L2 ~) A4 q! \* o0 z                        output += fme7.Process( 1 )*vol[22];2 j* G) k, O% |+ {
                        output += fme7.Process( 2 )*vol[23];
- }% v+ P( M! i( o  o1 w3 c: ^                }
4 g0 E6 }, ?7 a" g: ]5 a/ N& g# a
                output >>= 8;
) @4 ], X& z; X$ E7 d
" Y* Q& W2 Y) g- j; g/ p$ d                if( nFilterType == 1 ) {
6 O! k: f8 Q5 }# Z* q5 W                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
8 b* p* D0 x3 y# b1 _: y" U, Y7 q                        output = (lowpass_filter[0]+output)/2;
- _; o( L* \( ]2 E* }- p" W                        lowpass_filter[0] = output;
  A5 m. l% a5 Z- c% |                } else if( nFilterType == 2 ) {2 b! N& P' w" f) F
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
# I' s, o* @6 v5 g; l                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;. Q4 f. M' v7 t* Y7 m) [& q1 Y
                        lowpass_filter[1] = lowpass_filter[0];5 Q8 M3 I+ x; e; a6 z& c5 a1 Y
                        lowpass_filter[0] = output;( I6 O' {& z* E; \# @  G' l1 X5 {
                } else if( nFilterType == 3 ) {, j; U& s/ a& A  Z- W
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
5 |8 ^5 k, n' l/ S4 i" R                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
% n. s+ r) V- w5 d! t, }                        lowpass_filter[2] = lowpass_filter[1];
" t* }; R4 @7 c; ]                        lowpass_filter[1] = lowpass_filter[0];" E/ `" U7 Y/ @& e7 a
                        lowpass_filter[0] = output;
, S' U( T) r* b                } else if( nFilterType == 4 ) {3 I3 o* D* e& I2 G' c) {9 `
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 `2 G5 `' W4 S) Q9 n% D7 u                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( C2 I( B& o7 B4 d8 d! l* Y
                        lowpass_filter[1] = lowpass_filter[0];/ Z" l, c3 N% i
                        lowpass_filter[0] = output;* p! d' l* @% E# q6 ?
                }
9 E4 G+ T/ f! V0 B: |( \4 @1 ?: Y1 l, V8 Z/ T
#if        0
$ J0 Y$ W; a, q                // DC惉暘偺僇僢僩
$ k8 N! |( w4 c9 Q+ c+ y! K; Q! J                {* Q* q5 u/ Q5 C1 R
                static double ave = 0.0, max=0.0, min=0.0;- I0 z7 A* j9 Y! F
                double delta;
. d+ H0 X( p3 R2 J3 k( u% w                delta = (max-min)/32768.0;, j& v1 a2 j! j3 M8 G+ y9 y
                max -= delta;$ T7 ]4 z! j5 o
                min += delta;1 E3 O9 [0 o: Q' _' O5 o7 p
                if( output > max ) max = output;2 A! V8 O2 Z9 i/ [$ I
                if( output < min ) min = output;
6 w) e  ?# i0 R                ave -= ave/1024.0;3 F. h- b4 a" w+ U  ~
                ave += (max+min)/2048.0;0 ~2 y6 @- \4 Y# `
                output -= (INT)ave;2 L' @- U) C: Z. p
                }' c4 f0 C  o. G
#endif! J  U7 C4 Z/ W1 D- X
#if        1
* B- H" ^/ Z/ P. O; r                // DC惉暘偺僇僢僩(HPF TEST)
3 f9 A. n% M  m6 o4 ]* `! K7 g5 A                {" \. h: @9 h! I  ?% ?2 H; P
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);+ i9 u5 p2 y  _$ S& {* ?
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 u; n: T, m) X                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ b. }0 N/ {' B0 h9 ^                static        double        tmp = 0.0;, B1 R' B: X) H
                double        in, out;
& q( k7 \7 Q4 ~- u
/ N  z% Y; ]" K& d) C3 y                in = (double)output;
# G% h1 q3 x, s$ j  h                out = (in - tmp);
5 g' x$ ]% q$ ], j2 {                tmp = tmp + cutoff * out;- x/ P3 f* @- V6 C6 K+ T
# A# \+ K) q& K6 M% d$ F$ Q- p1 u
                output = (INT)out;$ }" W6 `" N( P: C
                }
! l" g3 a4 y. R#endif  P* _7 ^3 j$ `
#if        0
8 u$ ~* p3 [, ]! L, R0 e                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
% d- s1 _. ^6 O: F6 z2 p                {
8 v9 t& ?+ w; p/ I" @                INT        diff = abs(output-last_data);' Y4 `4 X: G0 C" C! H. M
                if( diff > 0x4000 ) {/ D3 o9 _1 K. w6 o- x
                        output /= 4;8 x: h. [& h7 u6 I% I- ^* W
                } else
- |' R5 h+ D9 _7 l                if( diff > 0x3000 ) {
+ \) S+ N- r" j0 ~                        output /= 3;, N' |- |, o, P. K; Y$ U# |$ W! a' b
                } else2 _' s8 b9 A8 ~! ]$ v, D% ]
                if( diff > 0x2000 ) {
% U: `/ f2 d/ z( T                        output /= 2;
" {) T+ L: B; R+ B+ j2 G                }+ c8 F9 ~/ a' F7 g* t- S
                last_data = output;( ^& g* Y* D9 z3 D/ {
                }6 Z. V/ s6 Q  }, C
#endif
. D, J- G) b" l3 z# Q' W& r                // Limit
: Y. B. r  Z# [2 ]0 v                if( output > 0x7FFF ) {
' E( Y3 D5 e  T. w                        output = 0x7FFF;  D( G0 W( _0 D7 B
                } else if( output < -0x8000 ) {) r- f: _: j) W8 q) E: b$ j3 |
                        output = -0x8000;
! }% z( ^) x1 m0 v                }
0 L, S0 L( ]0 f( S  c; K0 K5 J: `! a% L- O
                if( nBits != 8 ) {
: M' b( m7 ~- Q( J7 w                        *(SHORT*)lpBuffer = (SHORT)output;
0 G, e; k) R/ ]! R4 s3 K3 z+ W                        lpBuffer += sizeof(SHORT);3 m: Q+ W. m  g+ k* s# w6 s
                } else {
) s) o7 v/ q3 C1 b                        *lpBuffer++ = (output>>8)^0x80;
0 T! ]& H& E$ D, E                }4 s& u' C* C9 X8 F1 H. g
$ t+ |/ `4 z5 d3 z) J$ f7 ^6 [+ \6 k+ D
                if( nCcount < 0x0100 )
# F/ F/ B  R: y' H9 {2 K( ~: L( v1 |                        pSoundBuf[nCcount++] = (SHORT)output;
$ Q" j! g1 Z  l' g
! R) @0 V' w# |9 x% }* m( g//                elapsedtime += cycle_rate;8 s$ Y/ O" ]' p
                elapsed_time += cycle_rate;
! \1 x. ]+ h0 Z$ Z0 \+ Z/ V, d        }
) t% g/ h; [( y) G9 }0 K  `
) u$ j- F) h) _$ [+ Q, W4 v#if        1& d0 O1 `7 e5 I# t9 F; g3 N% z
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# \* b# }* }4 c
                elapsed_time = nes->cpu->GetTotalCycles();
1 \# _$ G& x; O  |5 N  C        }
$ Y. f0 H! x: P0 w        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {  W: F) D0 ^9 H4 `4 D, R
                elapsed_time = nes->cpu->GetTotalCycles();
- M2 j  Y# s# b5 ?( J) H* D' F        }) \4 n; y/ h6 ]9 y2 o) ~
#else' k  d' n  S  R/ W$ @- J* F
        elapsed_time = nes->cpu->GetTotalCycles();
+ k5 ~, _) L9 y& I" r+ p. e6 G  d#endif$ X- J0 _  q; j8 b- m4 L
}
2 J/ {) Q4 c, v$ g/ b
' c4 j$ Y2 h$ C// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: |! X: E( c8 y6 K4 jINT        APU::GetChannelFrequency( INT no )% v# r" n: d& y# I2 A* |
{
- x, i$ E, h1 H. T' k; S        if( !m_bMute[0] )/ T$ X3 ^0 u, G' N- r# z3 s. s
                return        0;- P$ B) E; h# o& \+ @
! Q5 c: e, o' |* B3 e' w
        // Internal
$ s& ~% q: B$ c/ i        if( no < 5 ) {
6 K: _: V, q) }2 C* I9 l# r# v                return        m_bMute[no+1]?internal.GetFreq( no ):0;
% O# I, k, o/ W  F! q! W        }4 H' }" S7 r6 u
        // VRC6
" r" |- L- i/ V4 \& D* t! t& l: Z/ u        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; Y% b& A. }( i3 f* A$ N: z8 F                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
0 O6 N; }' }- n' K! g7 T! p        }
$ ^4 |8 G4 e1 X* J5 [        // FDS8 w0 _1 m9 Y* f+ a7 Q
        if( (exsound_select & 0x04) && no == 0x300 ) {
! U8 g9 y1 v( h. I* w' {                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- B$ E5 b; M6 a0 F+ a  O! o( d3 d        }
: l9 I) m3 N3 }& C* m) N8 V* R        // MMC5. T  F; B! j& o5 ^' n
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {/ I3 E% f. k2 v' a
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: Q* a2 Y8 \1 v8 N- n7 v2 |  K, J        }
' C7 n7 C. T$ A7 x) I5 I7 M0 W8 g7 v        // N106
- O9 d' ~! }  Q- @( r8 O* W9 b        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
7 d  c& B% I* [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
% t9 A( {* S% x1 f5 T        }1 m! P! _  [& ^+ U9 I$ E3 x
        // FME75 V9 E& W; J# ?
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) ^  Y: E% \. N' o6 k
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 N2 {2 x8 ?6 q+ r; X) v. h        }
5 g/ u6 s( w& k% Y# d7 a5 s$ b# c) K        // VRC7
, G. |+ B5 q- ^: v, L        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {6 C( ^% j3 ]4 O2 L. S. r/ z1 b4 T
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; E0 n+ I; I4 g% _
        }4 l' k4 Q1 M, u1 {
        return        0;
0 G- Y9 J3 u* w8 J}
. M7 v4 F9 p: o9 q
2 o4 a; i# x4 e) G. b// State Save/Load
7 Q* t1 B1 ?( Cvoid        APU::SaveState( LPBYTE p )3 d9 t. U9 R0 x
{: l: J  p# |" p/ L5 e' D  c3 O
#ifdef        _DEBUG: @/ j- \: n# r! C( Z: T, a5 M
LPBYTE        pold = p;
0 `8 k8 q& m/ K" E5 h/ T#endif
/ z2 y  c4 V% f: `9 b, e0 {- _" T! A( M+ G2 K) }! ]+ r
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% r" y+ A7 V) ~3 N- T, X2 L$ i        QueueFlush();. g: Q' ^: r* w- ~

1 H, f/ u9 H; j: k        internal.SaveState( p );
4 ~! g( W$ s4 R7 r& l1 i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, a1 r7 r$ i; x* k: K. d3 f
0 M4 X( L: |: T$ O  n2 J* H
        // VRC6
8 N9 d- {1 O1 i        if( exsound_select & 0x01 ) {
! u. p. K6 O0 [3 H* j0 j                vrc6.SaveState( p );6 {( Y: J# {. W
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 ^  {$ G9 A& T' i8 M
        }
& ?6 R" b2 d1 N        // VRC7 (not support)
" [# C& `8 Z1 j: r# Z# X& g3 y& m        if( exsound_select & 0x02 ) {6 S/ L; m9 o4 Y) k2 ?: g/ b8 ^
                vrc7.SaveState( p );
5 ^  Y: Y! c% p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
5 F- J9 M! M9 m. l+ @        }( Z" t) D" B7 X6 g
        // FDS
5 I7 D# ^2 @$ f% `! E/ W3 k9 n6 Q        if( exsound_select & 0x04 ) {
$ q% L+ s) E, J* n                fds.SaveState( p );5 ^2 w" V/ ^6 `* h& d9 V- O& h  I' h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 S& u! }5 [1 V6 D% v" J( x
        }
3 V# f( a7 X5 b7 _6 B& d        // MMC5
: {  k9 n) `( m        if( exsound_select & 0x08 ) {# r; S5 T3 g1 c1 M; u, s3 |
                mmc5.SaveState( p );
! Q4 c: a9 t5 L5 h. E                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 v* ^9 ?2 f: ?! d        }+ z$ }- E+ V; D( q5 m
        // N106
4 u+ n4 ]0 A! b4 b/ \( Q        if( exsound_select & 0x10 ) {
! f$ a( |4 X) b3 h                n106.SaveState( p );
( [8 X2 O7 w$ k6 b' S5 ^                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' O+ ?8 }$ U# X- ]. X8 _# D' R: X( ~6 X        }
8 T. }, n: C5 L) p        // FME7
. J0 t+ N! C$ D+ H        if( exsound_select & 0x20 ) {+ q+ R9 f: K& }
                fme7.SaveState( p );: @+ ^% u, V2 z) \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" p2 e+ v/ j, I        }
  E; A2 h0 c8 K7 l2 R' C. g( z6 M) C& _
#ifdef        _DEBUG" P9 a2 h) ?2 R% u! P: P9 V
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
; `$ `, U- ^7 c" \1 q: V#endif
; d) C" t1 Q( F% _, m2 a: }}
' S" G' \7 G+ D/ K6 L/ E& @( C8 ^4 w
void        APU::LoadState( LPBYTE p )
( {/ R5 a4 T" p3 j" m" C  h{0 O8 f# d4 E  D4 ^/ T
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡8 L; ~9 {0 x; H4 E- F
        QueueClear();
% @( c% K( k9 v# e) _, S5 i( F" y  S. W* Y+ E; _1 ?1 Y( @/ O
        internal.LoadState( p );/ F% X+ z! S+ \* ~6 T$ `0 Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" V! n0 V) Q: T- Q
! m' x! B. ~- U. p  A4 J& N        // VRC6
0 Q% ~/ O# R7 ]% P        if( exsound_select & 0x01 ) {
% B4 [' D0 A" @4 V, T8 N                vrc6.LoadState( p );1 \: h6 d4 J1 u6 r1 b0 D. V
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
# F8 H7 [  \7 h9 L: |, m: P& P+ D        }
/ h2 r5 {/ d9 k  a        // VRC7 (not support)
- B3 `5 `" L- T% r. p/ I$ j* l0 f5 u        if( exsound_select & 0x02 ) {$ u4 z+ f; j) }7 J/ O- a. @0 L
                vrc7.LoadState( p );2 N, f: D# ~" Y. [
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 T/ B% m2 J$ l
        }
3 ~8 z& I9 F5 Q' o; a        // FDS
; v6 q9 ~8 n: p3 q- _1 \1 K8 t        if( exsound_select & 0x04 ) {$ Y, h7 N1 @3 F; L8 q+ U3 U
                fds.LoadState( p );
- G3 k4 }7 d2 m3 `# K: R; t                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. p$ w! z8 H' i& `0 j
        }
, y, ~; D8 A( Y: Z) B, z        // MMC5
# Y6 {  z1 c1 G6 U5 W! Y        if( exsound_select & 0x08 ) {
  o  V) r; i0 M* i- E- W6 _                mmc5.LoadState( p );& m" v2 @3 [2 y; v- B
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( v  G, {: v2 I$ A" F1 H
        }9 a. n3 r% O  K- _4 J7 [
        // N106# f3 h0 I9 N6 I1 ~# p
        if( exsound_select & 0x10 ) {7 d( r, W3 B1 t0 Y5 b. P* v7 g
                n106.LoadState( p );. g, S8 w: S4 a4 S5 U: W* z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" ~4 \5 I, C- v, L        }8 G5 b  n: X5 L4 b$ ~
        // FME7* V1 X+ X' V& H" E
        if( exsound_select & 0x20 ) {
3 X! y1 N* |  i$ S- d& e4 w                fme7.LoadState( p );1 ^/ i7 Y+ f. o  g
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ t7 A0 E: \# u6 i# u
        }5 Q6 e4 }$ s1 U7 K: q0 P6 s
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 8 h0 E; K" R" L0 S  t
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 ~9 v; H1 x6 w9 Z# A8 e感激不尽~~
* h: S6 s5 A$ n  |
恩 我對模擬器不是很有研究,
2 e, q1 v+ F) {' [/ }8 n! X雖然要了解源碼內容,可能不是很困難,& r1 s6 ~$ X" j' x
不過還是要花時間,個人目前蠻忙碌的。% a/ P' t8 S& s: U3 m
+ n* G. ?2 k/ J  b& K3 @
給你一個朋友的MSN,你可以跟他討論看看,
0 x+ u0 m! c  a( N他本身是程式設計師,也對FC模擬器很有興趣。' _9 c4 i  D. w- I; }- V

: {1 M3 @0 ?: vMSN我就PM到你的信箱了。
& W) w! D. G6 d; G/ G
; C" o, D8 u, g% C/ _! w4 \希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
3 }0 r4 [3 O3 i' ~6 Z# K0 W9 G呵…… 谢过团长大人~~
9 k7 A( G% I: t

* L& v5 _6 L0 O  v- @) O哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
% ]# B' m2 r9 I5 R/ X' h团长的朋友都是神,那团长就是神的boss。

8 n( a' A: m& |! k/ g3 a+ Y哈 不敢當,我只是個平凡人,* t. U8 p$ W/ G9 j# u! p
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
7 @0 D4 D5 N$ Y( C8 l; Y$ Q- DZYH
- @3 Q& X" c* s* x4 k& X2 nQQ:414734306
; b( b  k3 s1 o) p& zMail:zyh-01@126.com; D" S" n6 `8 V/ {

9 @, d* b6 {5 I他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 h0 w0 c7 q- k4 K; {/ C% E) G+ m
再次对团长大人和悠悠哥的无私帮助表示感谢~~

7 |- Y8 V  e4 {, W0 r不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-23 12:40 , Processed in 1.115235 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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