EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. W7 h7 L4 L* i* v楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 I& N! p* H+ J1 E4 @" o5 A& ]这里有相应的模拟器源码,就当送给大侠了~~
( V; ]4 X4 s) Q$ y# _' |http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 S; O5 X: n" U3 j) u7 d能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 Z' o; N: R& H  u9 \" a0 b
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 H9 {* m# E; q$ J+ |! v这里有相应的模拟器源码,就当送给大侠 ...
" u  O2 s3 H% G+ g) n( V  D
聲音部分(Audoi Process Unit = APU):
/ j4 K% Q3 [$ ~3 ~3 u6 F. P3 X.\NES\APU.cpp1 b, [( R6 ]; s
.\NES\APU.h
0 z" w0 K6 u2 A/ A% w" Q8 s7 b/ q; X7 V1 H/ u
$ r8 r" ^5 _$ v) r" p: x# @
影像處理部份(Picture Processing Unit = PPU):
7 Y8 s; c% k. M! k3 H4 f.\NES\PPU.cpp/ P2 Y1 [3 z: W' r+ ?0 \
.\NES\PPU.h
$ y" P) b; t5 @# I$ B/ ]" ~
0 e4 Y# L" E: C: |# F如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:9 N3 L  A: \' u6 ?
(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 o) q* e6 b7 I4 |( f. D
//////////////////////////////////////////////////////////////////////////5 y4 }% z$ W) E1 `, p: O. |. z
//                                                                      //$ m% ~$ N+ K2 {2 f: E8 ^
//      NES APU core                                                    //5 R% d& q+ ]/ A* p7 M2 t
//                                                           Norix      //( f1 H0 m$ G1 Q+ K! O: C8 Y3 I/ `: m
//                                               written     2002/06/27 //2 \, E7 C9 P0 ^& S
//                                               last modify ----/--/-- //
. c* S5 b, u" t//////////////////////////////////////////////////////////////////////////+ B+ G  Z( y' K9 d; P
#include "DebugOut.h"4 O1 z& b' A0 J! T9 M
#include "App.h"
2 L7 G7 L5 v3 L: l- f* `#include "Config.h"! I5 v/ j( W/ l- _9 V2 J* l
2 d; m4 I- s: d  R3 C; C/ Y* ?
#include "nes.h"0 b: l' l0 S3 ^$ b. S& s
#include "mmu.h": H/ x" l, z1 o- ]# G2 |
#include "cpu.h"& h8 i9 `$ ?2 l( I' M7 b
#include "ppu.h"
- s" ]3 b% Y5 i0 u#include "rom.h") K5 W$ l2 l* O+ s. J
#include "apu.h"
" a: ~5 ~7 V) ?1 [" H7 v( o' y, ]6 a7 E1 B
// Volume adjust! S1 A" y$ O" t# Q$ y
// Internal sounds# H3 K6 h& a6 v6 f4 r  Z
#define        RECTANGLE_VOL        (0x0F0)& g# b. M! f8 V/ i. q# z
#define        TRIANGLE_VOL        (0x130)
* h; c% T$ M2 b- k#define        NOISE_VOL        (0x0C0)
% Z4 ~( W% ^% D  @4 e: v#define        DPCM_VOL        (0x0F0)
$ r, l0 C5 W7 p4 z: E; n0 g// Extra sounds# z' A" W% q* a; d& m
#define        VRC6_VOL        (0x0F0)
& b# f4 O# }; ?7 C, R6 W#define        VRC7_VOL        (0x130)4 j' I% P8 M# q" m0 Z& \
#define        FDS_VOL                (0x0F0)7 }: l8 I. B0 P  P: {
#define        MMC5_VOL        (0x0F0)
/ v4 P& O0 F: j& d' |5 `#define        N106_VOL        (0x088)
/ z+ m) |% T+ P, O! t+ R#define        FME7_VOL        (0x130)
9 r, f1 s* W# X' v. |' a5 f: ~! g- O( }  U9 ~/ M( G0 m1 c: H
APU::APU( NES* parent ), y$ K5 G7 K& d# S
{
. F* @* s" P) ^7 ]3 w& K/ V2 k        exsound_select = 0;* c# q* Y9 j/ a/ h" k
+ o5 A3 d- B, ?0 N4 V
        nes = parent;
! W( U2 Q4 Y" [8 {( X) k        internal.SetParent( parent );
) J4 n, @3 q& v% W, I
) d+ A& d8 j& ?( |        last_data = last_diff = 0;
1 X+ h, @3 o/ s: f8 e2 H
% s2 O0 P! Q7 ]4 k+ F9 c        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' y$ D/ \4 o# [% d/ |9 V3 W! o4 T0 l! O) E' f5 Z; y4 j" U/ Q. U
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );/ ^# E/ S& t* ]1 a4 F6 _
        ZEROMEMORY( &queue, sizeof(queue) );1 h7 {# ]+ O% ]  A5 @, X& b
        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 }5 q8 O4 Z; u2 k3 c" ^8 m! a
" J$ c9 ]9 f. L6 l
        for( INT i = 0; i < 16; i++ ) {
9 Y; c# ~8 u: {2 Q4 E4 V3 l1 S                m_bMute = TRUE;
1 s% m1 ^7 R& {- H        }! u7 E% t0 H' k) @1 y1 W
}. U4 p4 U& N6 X, w% k$ j
& H' u! K2 s0 X
APU::~APU()
' `: p3 ~! T, X; V7 X{
( l6 s. ~3 p& _8 {}! K5 L) T: _) I$ a2 F

( X. r& y6 J) U$ Bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )5 U; @! P6 x6 S$ m" \* s" i8 f
{
& A* l7 X: t2 [" ]/ ^        queue.data[queue.wrptr].time = writetime;/ F# |' ~; b5 s: D7 `6 ~% H0 ^# e/ g! F
        queue.data[queue.wrptr].addr = addr;  }' B+ U  y9 ?9 h" r0 Z9 x
        queue.data[queue.wrptr].data = data;
2 o, i- ]  d& R8 N; y. I        queue.wrptr++;) v9 Q2 G# a9 ]5 }6 H! a
        queue.wrptr&=QUEUE_LENGTH-1;3 E7 o( |6 p( z6 q" ^3 \4 m
        if( queue.wrptr == queue.rdptr ) {' t( ~; t0 D8 T9 @- C. }
                DEBUGOUT( "queue overflow.\n" );/ T" q6 K7 {$ O4 Y. s
        }! W8 j! B2 ^* H7 V
}
  q- z% A# Y5 G8 t. K) ]  o. W3 S; o6 i; S8 g7 x
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
$ k( R, B1 K- N{
$ f$ e5 B! V/ H8 P. D( M        if( queue.wrptr == queue.rdptr ) {: @& X7 v% n5 n/ a
                return        FALSE;4 t7 K1 r% I; C! I# I$ D( f8 C; ~
        }% [) O3 e5 I9 Y
        if( queue.data[queue.rdptr].time <= writetime ) {7 v* R% N  {: T3 i& w* u( p1 J
                ret = queue.data[queue.rdptr];
! I7 I) Y3 S( D* H                queue.rdptr++;0 {* Y. X5 I( `; r
                queue.rdptr&=QUEUE_LENGTH-1;3 P+ `$ T: O/ F0 Z( @! T8 r, S- n
                return        TRUE;: Y" o+ v% k8 M0 J1 g% ~& ^
        }
- M+ g6 ~7 p9 R/ ?* V        return        FALSE;' @$ P2 `: a0 u0 j
}
5 W* M. }% E( W) ]  [& V1 g3 `: x7 r7 ?8 F& O
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ), X1 A* O6 l" L1 d7 U# N4 P. {- o  V
{( y) H6 l9 G7 n4 F  F1 c' c. e
        exqueue.data[exqueue.wrptr].time = writetime;  N$ A% T. T9 @
        exqueue.data[exqueue.wrptr].addr = addr;  l4 v+ M; a$ A6 E3 d: W7 J9 I
        exqueue.data[exqueue.wrptr].data = data;
; ^) F! `( O1 d; s6 ~- g- b        exqueue.wrptr++;% T; i2 V9 E. n0 }% \) F
        exqueue.wrptr&=QUEUE_LENGTH-1;
. E4 G& ]# y9 A- u& d1 }        if( exqueue.wrptr == exqueue.rdptr ) {
: V( i/ F& z) Z                DEBUGOUT( "exqueue overflow.\n" );$ ~2 O6 D' o/ ~2 w9 s; g+ _
        }
$ Z; b. P1 H* t6 s$ C, y}& u8 ~  D8 J6 ?9 e0 r# |
5 d1 H0 ?+ J) z. G# {) e! h1 W
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! J) ?! l* A. O& U) |{1 z" L# D* b; i# V& O
        if( exqueue.wrptr == exqueue.rdptr ) {
. j. a4 N2 }" X9 m4 x                return        FALSE;+ w6 b; V1 G3 }5 @8 ^/ [4 Y6 Y! {; R
        }
/ W# t+ i* }7 D; H, I, J        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
8 B) ~2 Q* i# }- ^4 c% k/ W                ret = exqueue.data[exqueue.rdptr];
; u9 W* e/ e' o- Q0 `                exqueue.rdptr++;
( a; \, l& i1 }: P+ X                exqueue.rdptr&=QUEUE_LENGTH-1;
- N$ m0 h+ W' C( L3 [- D% {$ p                return        TRUE;
# k8 X* A0 k" B& D  u3 U        }
5 ~$ v0 V) y4 K8 V        return        FALSE;- E9 r' M1 A: Z' ^+ g- x/ Y/ R4 u
}
6 f, A" h6 D3 u. `4 V1 o. v0 c
1 H  l+ c" D" H9 Uvoid        APU::QueueClear()' z3 [# O- N3 ~5 w6 I8 [$ ?
{  h% _: ]* ]# M8 q
        ZEROMEMORY( &queue, sizeof(queue) );6 t; i; l# m% w' X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* p# T( C- ~0 [
}+ V; j% }9 c% |
  {5 A+ Y  w3 f) ?! {7 |/ I: R
void        APU::QueueFlush()
, `& k& D: Z1 d0 H! l; F{
- U, u3 n& d7 t' U, G4 z        while( queue.wrptr != queue.rdptr ) {' \5 c% W# F( a( Y
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );7 t' l9 H' J- i
                queue.rdptr++;
0 f$ j- |7 J9 m. g- z0 g( k                queue.rdptr&=QUEUE_LENGTH-1;6 E: ]& l3 W8 X$ e" k9 x
        }
% r! B( _5 X- K1 I1 D! y
' A7 m9 z9 K3 R4 f2 Y, K. w        while( exqueue.wrptr != exqueue.rdptr ) {" c. Z' Y; O# l& F
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% q! J8 l) M/ D8 C/ M
                exqueue.rdptr++;. i* N  @4 G+ V' H9 C- M
                exqueue.rdptr&=QUEUE_LENGTH-1;
! f( O9 K. Y" H        }
0 b% t4 q3 g( u% u5 {}& f& L6 z! u2 B' ]

6 X" @* W1 L1 Y; ^1 Svoid        APU::SoundSetup()* }  R2 q: O9 q) [: `; `7 Q' p% o
{5 a) o9 F( ]5 t3 d. p2 \- k- [
        FLOAT        fClock = nes->nescfg->CpuClock;! M1 p; I6 d# p; E/ Y. K/ i! Z/ v
        INT        nRate = (INT)Config.sound.nRate;7 F0 P! m  _' W  o' m
        internal.Setup( fClock, nRate );9 R3 I) c4 y. |* m' N
        vrc6.Setup( fClock, nRate );
+ V; e* ^. ]& M$ M) P        vrc7.Setup( fClock, nRate );% [, W# o" x0 w; D& [$ P
        mmc5.Setup( fClock, nRate );& K$ R4 G" a0 B
        fds.Setup ( fClock, nRate );* J7 U$ C1 i6 w* m9 R
        n106.Setup( fClock, nRate );
$ L/ e2 N7 u5 [7 l- u; \$ B& d1 d6 m        fme7.Setup( fClock, nRate );+ m& T) W4 J, m, h; ]; E8 Q* T
}  F4 W& S5 {5 C( w, {6 Z5 }
. u0 z% w6 I. A
void        APU::Reset()
$ X! _8 I! {" ], @6 u{* {. L- N; U4 d# j
        ZEROMEMORY( &queue, sizeof(queue) );
9 j8 v' q' y  d! P        ZEROMEMORY( &exqueue, sizeof(exqueue) );; z5 P' Q8 M" G* C  [7 p# d6 |
, q( r9 \4 g1 k  v' J2 m
        elapsed_time = 0;+ J) k* \- V7 p, f
/ C% ]6 P. V! s8 m* t: v7 `, \
        FLOAT        fClock = nes->nescfg->CpuClock;
7 _9 G7 w! a% Z8 K/ Q        INT        nRate = (INT)Config.sound.nRate;! ?$ M" I0 d9 J6 z2 ~% O& x
        internal.Reset( fClock, nRate );, o2 @: T! P5 T+ {; `6 B
        vrc6.Reset( fClock, nRate );
4 w7 \* N  [( K2 C" N/ X        vrc7.Reset( fClock, nRate );
& X1 E7 S/ |& D. K: z; {        mmc5.Reset( fClock, nRate );
5 a5 h' I3 K! S, s, t# G7 G: S. L        fds.Reset ( fClock, nRate );
$ S0 C! R- g" ~        n106.Reset( fClock, nRate );* b3 _) l& O# M7 T5 s
        fme7.Reset( fClock, nRate );* p* v* S% q( t3 c, q0 r+ b' r

- l) Y5 j1 r) l8 H9 v        SoundSetup();- |( f: W/ a, [
}& h: D2 j5 l4 t! u8 L, M% _. |$ B

* D$ i3 n( [# _( P4 hvoid        APU::SelectExSound( BYTE data )
, U  H* G6 s+ k) T9 S9 E{5 V& ?9 B/ G6 d# X' L3 q& U( {
        exsound_select = data;
; J# o. N' k  X# r, R; @3 X& @}
/ {0 T: ~9 X7 Y$ X7 D2 v* i. h- C+ u0 b. K, C4 k9 f
BYTE        APU::Read( WORD addr )
) S: \3 F* n) B5 E7 b* ]9 ~+ H* p{* w: V' [6 D) q- Q! k+ @* D9 B
        return        internal.SyncRead( addr );. _( _  h6 ?4 o" Z
}
- D: |! O& y; h' ^/ D5 @
# L- ^3 `$ Q& C6 X' Dvoid        APU::Write( WORD addr, BYTE data )$ e& {- n+ l7 Q8 c, N- p
{8 L3 q3 a( B) g2 s
        // $4018偼VirtuaNES屌桳億乕僩4 S2 `' f$ C% v3 B; E
        if( addr >= 0x4000 && addr <= 0x401F ) {1 {7 C1 w! u7 v9 t
                internal.SyncWrite( addr, data );" F: T- e& q% `) O
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& ~1 R# e$ I/ \3 p+ }4 {9 M        }! J3 d1 B; j8 k% C: B' G0 V- w
}' y4 o6 l, t$ v  A: D% T! B- `' D, t

8 ?3 S8 E2 w6 }, R% EBYTE        APU::ExRead( WORD addr )
+ z8 j  e# k- W: c{
- Z$ V' g1 y2 n/ nBYTE        data = 0;
/ U+ o$ Z/ t1 H1 M
' y) r3 @" K# N- |        if( exsound_select & 0x10 ) {
2 X' B* C7 y1 c/ X( v) U                if( addr == 0x4800 ) {# f) S9 ~" u# M" ?
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! L% \8 b! z1 t; b: u
                }
7 ?" ?2 w, i. n8 n. P% \, g: R+ L        }/ p2 I/ m8 t, x0 r
        if( exsound_select & 0x04 ) {+ y- e) @# O& p3 m* z1 K
                if( addr >= 0x4040 && addr < 0x4100 ) {; z( _9 N8 _0 @
                        data = fds.SyncRead( addr );
9 J# Q! ]+ Q4 |4 {/ Z  m) r                }7 F9 C1 x* o0 {$ E
        }2 v, H3 T5 Z+ v: n4 q
        if( exsound_select & 0x08 ) {) d# \4 v5 J' ]" m) ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 _# H9 a) ]" b# I$ Z: C                        data = mmc5.SyncRead( addr );2 T  H( B: D4 A% G2 v
                }
, m& k6 L$ x0 I  W: u5 N" @        }
4 F" g- \3 X0 q' `
1 `+ x5 W, K& a& h/ s# g        return        data;: D5 D# ]7 A: w" E8 y
}: ^2 y$ S/ `% O5 ?3 G, o

% ^/ r7 Z4 S  n- `( nvoid        APU::ExWrite( WORD addr, BYTE data )/ T2 ~1 S# R' S
{
5 N4 t% }7 O* c( E        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# }6 P; A/ _3 F7 i- Q4 }) z, S$ J) |' z, K  P# _4 Z
        if( exsound_select & 0x04 ) {
/ a' k5 f% R2 Z+ y) O                if( addr >= 0x4040 && addr < 0x4100 ) {
3 i5 @# p  P; V9 p, i                        fds.SyncWrite( addr, data );
; w. S$ |: [" @4 j- ^6 N                }" D' O$ J) R6 K; `/ K# [
        }
/ r! q8 r8 _7 ?) `# S. ~2 q" ]* g5 P& i
        if( exsound_select & 0x08 ) {  z8 O6 J6 K/ H
                if( addr >= 0x5000 && addr <= 0x5015 ) {
% _* g3 j; v, h  O. t                        mmc5.SyncWrite( addr, data );
7 |. p# H5 f8 R7 }1 }* _( n8 j- ~                }
; |2 t" n- A' M        }  c2 Q( y7 n6 o. J: B, E  O# g5 J
}# s5 B, m! c. M. ?8 X; u

* _; k! \! C7 e1 A- a0 d1 U' u7 V* Bvoid        APU::Sync()2 E* D8 }- b6 `4 {) ]* R4 X/ X
{* `4 d  k6 c- @$ Z+ V
}; c) U; s' v; O' Y7 c
& Z4 F. e% h' o: K* u1 T4 M
void        APU::SyncDPCM( INT cycles ); ^) @2 W  |* u7 P9 _
{/ W) d7 E4 C, _% Q* k4 N
        internal.Sync( cycles );# K- A5 o6 t; p" [. v
* Y$ B: X; E' \; p" v  H5 L
        if( exsound_select & 0x04 ) {
' H  W6 v& u  T( G- }                fds.Sync( cycles );
6 b2 T# G3 E% W        }
2 q1 g5 C  R, E8 w0 g3 ]        if( exsound_select & 0x08 ) {- t" A$ o, R: ]( Q
                mmc5.Sync( cycles );
( Q2 v+ U- M3 O% e: Z        }
7 i# o# M# q# [" ^  m1 s}
+ O) w+ I" V8 V# l/ ~0 w2 i' W5 @5 u2 A2 ^
void        APU::WriteProcess( WORD addr, BYTE data )4 [" l2 b: \: d/ @3 ^% F# y
{/ V9 c& y8 ~( c  t' L- ^6 V4 J
        // $4018偼VirtuaNES屌桳億乕僩
7 S# w3 j$ ^/ R/ O/ h0 s' D        if( addr >= 0x4000 && addr <= 0x401F ) {+ M" c6 @2 n$ E8 U
                internal.Write( addr, data );
3 W! {  K4 u5 a! c        }' X' d0 }' G5 G9 x# B1 F7 [
}, s3 t5 m; t' `0 k- W# V9 y2 X

" G* L) i+ ~6 o8 z' b* Y  K3 O/ ^" uvoid        APU::WriteExProcess( WORD addr, BYTE data )
9 Q2 V  H$ V* M0 I! ]$ \( B7 ]" ?{
3 F! l  g( k; ~0 W        if( exsound_select & 0x01 ) {$ I9 h6 m  P  m. j8 m
                vrc6.Write( addr, data );' d/ H( ~9 d" R9 j( f  \) U) |5 Y
        }
; z8 ]5 I4 }# w6 D5 M8 W6 e6 k        if( exsound_select & 0x02 ) {
  k" `/ y8 q# G8 `, H6 t                vrc7.Write( addr, data );1 t9 B1 j; K7 y3 y3 }; ~2 Z% I
        }
8 [9 o# q; s4 W$ ?5 |/ Q        if( exsound_select & 0x04 ) {0 _& l. _: H( r; X* S
                fds.Write( addr, data );
; m# L: ]: e6 _, d, q' j        }! A8 }* `3 _! L( n8 T& S8 o4 T
        if( exsound_select & 0x08 ) {
0 I3 A' T( K. L9 v' e! R                mmc5.Write( addr, data );+ |7 Q% i+ }" f5 r& a1 J
        }
. G+ p' k5 r: z# L6 ]1 {& J        if( exsound_select & 0x10 ) {
9 E- m5 ~: C" u0 @+ t                if( addr == 0x0000 ) {
% ]: E; }( k1 q4 ~' O# H                        BYTE        dummy = n106.Read( addr );* L' H- K4 @/ ?# q; T
                } else {4 a' X3 N  b6 X' e% F+ R9 F! w
                        n106.Write( addr, data );, L! x( D2 c8 ]6 d
                }
+ m7 n9 J/ y; w$ y% H; \5 v7 x" e        }* N& z# X" l) G8 F, B( U
        if( exsound_select & 0x20 ) {
. o. E- n6 {) s! Z3 O                fme7.Write( addr, data );  R6 E! }' \7 R& c7 I& D
        }
; x2 ?) ]/ r. D( S}. ^+ _+ ?; s- G& _  D, s: m
) _; K8 ]. j6 C5 N" M" f
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ P: i/ S. i/ ^* k5 }$ s
{6 [: c; u; u( L! @) c4 V
INT        nBits = Config.sound.nBits;3 }3 ]( y+ K( ?% Q; G
DWORD        dwLength = dwSize / (nBits/8);8 f" }1 p2 q% s0 T1 x: K
INT        output;. f5 E: E, n) i' q! A
QUEUEDATA q;/ L3 z  y* Q* t5 G1 z( t
DWORD        writetime;
; _2 N: h. q$ p5 o9 y7 i9 g! N& I! x
LPSHORT        pSoundBuf = m_SoundBuffer;
2 N. F5 E% f6 m1 v: ]INT        nCcount = 0;. ]1 P/ E+ d* ^7 u' J8 O* M0 m0 |. R
+ U6 O) j1 g$ K9 \7 Z# i9 q
INT        nFilterType = Config.sound.nFilterType;# r! B$ I- ?2 a

$ B5 Q, Y- b" b# x' y, W        if( !Config.sound.bEnable ) {( M: L3 g) A, W8 o' c4 Z0 ]& E
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
( J% z1 \" d7 [4 n6 X                return;
2 Z- Y9 H; }3 w" |" |        }$ r( p6 c- E9 o: H: S& v
  Y* F4 p4 }1 r. ~$ {
        // Volume setup% p8 V! M. p5 J
        //  0:Master
4 R$ U8 S1 E7 ^' N: C6 B9 e+ }# w4 j        //  1:Rectangle 1
1 Q$ Y9 W; u' ]/ @* I) w6 ]7 k- s- m        //  2:Rectangle 2
& @* D9 V  \0 h8 @        //  3:Triangle
7 B$ X0 @! S1 E7 o        //  4:Noise4 H# `( L  Y3 e7 O+ E% ]
        //  5:DPCM
6 s% E2 k' }( N        //  6:VRC6
# R" _4 s) @5 c) j  ~. v+ ]6 i7 ]        //  7:VRC7
) O  o/ `4 ]. G5 X        //  8:FDS/ O: b5 c* f7 \
        //  9:MMC5, i; e' K5 X. B) k9 z# a$ i- S# {
        // 10:N1066 \2 a$ j$ C9 o2 Z* j' |* ^4 _: g
        // 11:FME7
$ i+ Y  i2 ^3 p# `8 P; n  V6 Q        INT        vol[24];
3 A* h0 ?1 _- R        BOOL*        bMute = m_bMute;% J# _9 k( u* y5 k) C
        SHORT*        nVolume = Config.sound.nVolume;
, _% y2 J( B; H4 i8 @4 S( n4 A4 i  k; \% L
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
; x, j$ G3 d8 n6 y! s) g1 d( E) r8 t
        // Internal
( o% I! R0 B" `( j* b% o        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 B) M3 l/ C/ H: W* ]/ U* `) I* m
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;" P" t6 ~7 U9 g; Y. T
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;. }  }& p8 b; ]5 G  i! L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;. N9 V/ ^" d' g) A  _: s# m
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;1 ~  o: F- ?% }/ Q& X& x

1 @- O% }. g2 M6 G' G2 u9 B( Y& s        // VRC6! U" }5 ?8 s! F* ?3 _# \
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& h, \. M" w6 S& |6 E
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 H* z6 \4 f! ~! d4 x6 f2 |! l
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 }+ c5 K* g- b, ~- C$ L  [8 ~! g, _9 V+ `
        // VRC7- O* r- L" N% Z* n$ V, N
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ m' O- c3 C) H6 Q: v) m- E

8 L5 b0 a0 s7 i0 f7 f# z        // FDS; g# J9 F; n7 X3 ?- H; e
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 o+ g9 X) ^6 [% T2 h/ h; _
$ p3 l8 ]- \% G$ j5 }
        // MMC5
, d1 k7 v; P* {- Y7 }        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 \! j  _* w9 `3 V# {# w        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. P8 p/ K; \, n1 G# R* q0 [
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 ]' h2 s. n6 |+ p" ?0 Q$ y
' `0 e. w" G* q. v6 O        // N106
& E2 K" r3 C' x( h9 P        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 S, l# q! H; S/ C+ s+ b8 L3 m$ g        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ c) }5 Q1 _6 n; Y) ]        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' H/ W- w" b9 t# y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# v8 \7 L- f3 [5 x% O7 `# c        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 L4 p/ G: l" ^/ _1 j2 ?        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; S( @2 W9 I+ E3 p; S: Y. z$ m( i
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 O9 L0 E! E) r4 o. v5 s+ Y
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) ^- Y; w5 E7 F. k, w# d* A; O
- c; g5 \! s6 }! l* A- s3 U        // FME77 }0 b9 t) Q6 j% ?. D* `
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 ]/ C+ @9 D- O- g2 m9 L        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* o" y8 a1 o( G1 e; f        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 g! n! ]5 v& Q/ B' n

9 o8 H' @: w: O# V' {, v//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;6 V6 d2 R  ]/ |9 v8 W$ y# ~
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 Z, }: _5 h8 `# l

% |: |. _( f7 h1 x# h        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 v/ v. V3 L4 _        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
# `* i1 q5 k1 e) Z  h# a                QueueFlush();  X8 U  g9 H" U
        }
# Y8 P, c2 T7 Z, [( v! N' o+ b) i& H9 K# C' b. w/ s% r; O3 L
        while( dwLength-- ) {1 _/ w9 w% l- T: F) A8 G
                writetime = (DWORD)elapsed_time;  C& p4 v) ?! D/ ^1 Q( E

5 A9 W8 G  U  J' o                while( GetQueue( writetime, q ) ) {
# T- O  Y4 a  ?1 O                        WriteProcess( q.addr, q.data );
' {" @) Q9 u1 ^1 L6 {, {                }
- ^2 l8 w5 w% l- K8 x# E2 |" t: D+ H9 E8 E8 D; E
                while( GetExQueue( writetime, q ) ) {
3 T% C& q" a3 F4 h) C8 Z9 V( R3 t                        WriteExProcess( q.addr, q.data );7 B/ Z/ T, S# T. R: l
                }# Q" _+ X+ e4 H7 g
  d$ s6 h- B1 C, T8 l9 s' [
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
6 ^" b/ A  l9 s3 Q" ]8 x4 f/ i                output = 0;) \: _. {% D" p9 T9 o$ y
                output += internal.Process( 0 )*vol[0];
' K0 y8 M; L4 L6 z7 Z3 s$ S! w9 S                output += internal.Process( 1 )*vol[1];
$ H3 N, O$ q0 L5 T1 s$ ]2 i                output += internal.Process( 2 )*vol[2];
7 O8 H4 p% H* s7 I                output += internal.Process( 3 )*vol[3];
( O8 |# c" u: e0 x                output += internal.Process( 4 )*vol[4];
/ _( f1 C9 t2 ]( A
- V# w- p: _$ r! x! Q                if( exsound_select & 0x01 ) {
# W+ U  B9 L" I* \) W  ^7 i                        output += vrc6.Process( 0 )*vol[5];1 \. w. _. S# W0 y& U0 ^! T1 z
                        output += vrc6.Process( 1 )*vol[6];: J2 W% w" \. h
                        output += vrc6.Process( 2 )*vol[7];
9 Q9 ^$ e9 N9 l; X, J                }/ W9 U6 W; U% G
                if( exsound_select & 0x02 ) {
/ T; Z" I4 z% x  j: k3 y                        output += vrc7.Process( 0 )*vol[8];2 n! q4 ^  B# m! j/ i0 D: D  b
                }
3 q7 I7 a* ~! ]9 k                if( exsound_select & 0x04 ) {
+ v; A- }) w6 D# r( j1 n9 [# N  Y                        output += fds.Process( 0 )*vol[9];
# S% Y2 Y0 \: p. G2 n% @; ^2 ?: r                }
6 X' k5 }+ o* H                if( exsound_select & 0x08 ) {/ \, t9 \) [6 @2 f8 L3 T: }) D
                        output += mmc5.Process( 0 )*vol[10];% w0 |1 [) P" s9 v) A  d7 u) n: C
                        output += mmc5.Process( 1 )*vol[11];
) c7 }: r# X! n- l1 V                        output += mmc5.Process( 2 )*vol[12];) Q9 X, t0 V: R" k! P" G3 b+ `
                }
- h. h5 `' o6 L5 w3 u1 A                if( exsound_select & 0x10 ) {
5 @" F' z5 z/ P  Q                        output += n106.Process( 0 )*vol[13];6 E$ G) x; c! Y$ ^% `+ Q0 x. y/ T
                        output += n106.Process( 1 )*vol[14];8 j6 f8 F. A/ M: N! g4 T
                        output += n106.Process( 2 )*vol[15];
2 c& O, G; z$ {! P$ R% N                        output += n106.Process( 3 )*vol[16];; X! P5 N# E' g' C' T
                        output += n106.Process( 4 )*vol[17];" [" W% [1 a  j1 Z" q3 j
                        output += n106.Process( 5 )*vol[18];& f. T: p$ d1 P6 C. W0 y
                        output += n106.Process( 6 )*vol[19];; ~, r+ r1 N! Q
                        output += n106.Process( 7 )*vol[20];( s2 D; i; c+ M/ k( g/ m
                }6 u5 E/ X4 Z9 W8 x+ h/ Q3 e  Y4 J
                if( exsound_select & 0x20 ) {: e! D0 B% i& d/ J8 [  B; H0 `
                        fme7.Process( 3 );        // Envelope & Noise
, q: {# \. ?" p  e                        output += fme7.Process( 0 )*vol[21];
1 v# `$ l1 L* a: X& F9 O+ r% ?                        output += fme7.Process( 1 )*vol[22];: T% A7 p1 j4 g9 o! _. o' o
                        output += fme7.Process( 2 )*vol[23];6 N% {  [# ?( r3 T
                }* I7 m! X( K6 |0 }1 I
& M" u- C$ B  ^0 M6 O1 E
                output >>= 8;" B6 P% _) t& g  M7 x2 p

1 |: c& [1 v8 N! E1 b! N- O                if( nFilterType == 1 ) {* ~+ k" L  q; L% `3 z* s
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
+ y# X) Z3 n3 B1 u                        output = (lowpass_filter[0]+output)/2;
# D$ _1 m: G) u/ z; u- O                        lowpass_filter[0] = output;
; \' X8 s& Q% K# F                } else if( nFilterType == 2 ) {
  Z# j$ P, `4 e5 {( C! Y5 e                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! Y3 j9 B: c( r  e# `% k3 Y/ {+ `0 T                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 E( s3 A! B. i
                        lowpass_filter[1] = lowpass_filter[0];
6 I) k  K# S: T" @                        lowpass_filter[0] = output;
2 L/ o7 H% C8 J                } else if( nFilterType == 3 ) {/ b8 Y+ Z$ k5 ^% T  I$ g4 \1 o
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
& x2 F1 G+ y3 @5 B7 [- {* f                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 w' F' Z6 d4 z* L" g
                        lowpass_filter[2] = lowpass_filter[1];
- h/ `) @! w  M; g- e                        lowpass_filter[1] = lowpass_filter[0];) i' m# z) p' }# j$ H! W
                        lowpass_filter[0] = output;
* V0 `* J* p( D$ w! H                } else if( nFilterType == 4 ) {
6 h9 o2 A* ]) W                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- U+ {' K( B4 |; o                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;# v7 m2 P/ w2 i7 g
                        lowpass_filter[1] = lowpass_filter[0];
' |8 r- m; H8 m" s5 a- s                        lowpass_filter[0] = output;
& I* @, B3 T) h' K$ Q. T8 v                }
, b, j3 T# o4 v" \, k) E+ q% l4 t% Y! N/ n3 [3 S' X
#if        05 l' g: k% y* c
                // DC惉暘偺僇僢僩
" Y0 Q! [- |$ k- e' u3 m; ]( q0 I4 z                {
" z9 K* d. @& H+ n$ m                static double ave = 0.0, max=0.0, min=0.0;
) L' v1 ?2 |4 H% c( p& U* ?9 X                double delta;
' X0 [% X( k6 s3 q' S7 I                delta = (max-min)/32768.0;
% x( y1 R: Y3 h' U$ ]; f                max -= delta;
; ?; T4 @4 S+ `1 m9 n; ~0 X                min += delta;0 o5 p5 v* \, T3 W1 d5 M0 z
                if( output > max ) max = output;0 U  y7 m) I9 ~
                if( output < min ) min = output;" }& N8 Q# D, M2 M  o
                ave -= ave/1024.0;+ u7 l  {+ m& M' J" H( Z( d  M
                ave += (max+min)/2048.0;! @( n/ j0 N9 v- ~2 W
                output -= (INT)ave;
( g' E7 }4 K5 @4 b                }
) O: w# a$ b( Q3 q7 H& }#endif
% Z6 F/ |+ h4 l/ W#if        1
  J/ L; G9 N% |0 x( F4 X0 _                // DC惉暘偺僇僢僩(HPF TEST)
5 _. i% w) o5 c5 W                {( Z2 N- k% I, ?
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 P+ A: L5 w. [  A0 U8 W: A/ s3 o
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 Q1 D' N$ `  j$ B' }4 |                double        cutoff = cutofftemp/(double)Config.sound.nRate;/ v1 V; d$ N" J7 ?) t
                static        double        tmp = 0.0;
# o; s" {) U+ F                double        in, out;$ {8 q5 v1 c7 r' R& }

$ b( D( C7 @/ ?8 E+ L" {                in = (double)output;
0 A% X2 T* o+ M$ U                out = (in - tmp);9 j3 G. `4 T! \/ F* p& K
                tmp = tmp + cutoff * out;. W5 c7 y! ?. ?9 n" ~# A
$ o6 C" o3 m; i0 l" n/ c3 f$ L- |
                output = (INT)out;
3 K2 f2 G% ^  b- ?' N8 d; |                }
/ ^* a9 [8 o' T& ]+ a- _3 E( `#endif4 D% q( W+ z1 Z' V0 U! u- i
#if        0
7 L  R) u6 m' ~                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  B% ?, L7 }1 b0 M2 x& y
                {
' u3 c% P% P. V                INT        diff = abs(output-last_data);
- _1 L; T9 q# M5 N6 b                if( diff > 0x4000 ) {! l2 i& k* f) Q7 P9 k! q- ~
                        output /= 4;9 M8 |0 y8 T: p8 \
                } else 5 w- u7 ?. N) K5 n( n, W4 T
                if( diff > 0x3000 ) {
% @; @  }: F! k+ ]! z! u                        output /= 3;) `' ]9 z' v6 p) M% o2 l
                } else: o4 a7 i6 `. m
                if( diff > 0x2000 ) {0 k$ r* A+ y6 R5 u; k, I, B
                        output /= 2;+ F" ]0 e2 ^# l: e# A3 U
                }! A+ z! P6 Y& V8 z
                last_data = output;$ ]6 t1 Z7 L- J, f$ E
                }
  @* N) Z/ J; z: e5 O5 t, C% V( l#endif
$ `, k% e$ x- ^& e* X7 C6 Q. m7 \                // Limit6 P/ f9 U$ ]) K2 d
                if( output > 0x7FFF ) {
0 v% W( K) i2 _% P$ A. k% d- d                        output = 0x7FFF;7 p# L$ ~3 ^  J) U( {- R! R  f
                } else if( output < -0x8000 ) {
  F1 B5 J: K0 k  A: Q' O; P                        output = -0x8000;
: c0 a$ p, j8 h" p                }" ]. P5 x9 M2 K- p- X

( d) z# n) H6 _! Q                if( nBits != 8 ) {, c. d6 A) L0 f+ @
                        *(SHORT*)lpBuffer = (SHORT)output;
& l. x3 N2 \  o                        lpBuffer += sizeof(SHORT);
$ p/ \4 Q% P& Z7 ~, d+ W                } else {( M9 z5 k3 m" G$ F, y6 \/ G6 W
                        *lpBuffer++ = (output>>8)^0x80;
1 H& R  ]& l! K1 Q+ Q2 J! t! T# E, D                }
% Y* f1 K- D7 H8 t; d( d: _% M/ n8 M- Q) ]: H. E, V1 c/ Y
                if( nCcount < 0x0100 )' G. I, Y& F! E, a
                        pSoundBuf[nCcount++] = (SHORT)output;# m+ P7 [# Z( Y" Y% L' V

, Y" _. Y/ f/ ~! Y! K8 ?7 A//                elapsedtime += cycle_rate;
. x) n' ~' Q! T# ~: F$ Z# K2 T# }+ M                elapsed_time += cycle_rate;, n5 A$ `# m2 J7 u2 C, b: ~
        }
1 G5 k! l: I1 C6 s+ w
3 }! b* e, J" L" b! F( a; V#if        1. m& p. w1 @( f8 Y
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
- X0 K- `6 H( f8 y8 B                elapsed_time = nes->cpu->GetTotalCycles();
" H+ h# S1 n# p* z# h        }6 ]0 g, |. s. }% ^1 ?0 y1 k
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
6 W, r* J" s" q- U3 ]; t                elapsed_time = nes->cpu->GetTotalCycles();- N6 H. U; {$ g6 ]3 C3 T
        }2 m3 q$ j/ h( n; d; I7 n( K
#else
2 q# E( f; U; r( L: H2 F" h% j) t6 A6 Y7 {        elapsed_time = nes->cpu->GetTotalCycles();
7 _- V- x$ a1 Y#endif) G: l* Y$ z# u$ a" F9 K# w
}+ ?1 w! f; g$ D
2 S* ~; {; k9 ?
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)/ N- Q# B7 @" n+ H. a- M
INT        APU::GetChannelFrequency( INT no )
* Y$ |! Z5 d; h* `+ N5 s$ V{$ h, j9 D* _% A$ @
        if( !m_bMute[0] )2 o8 S; C, d% ?
                return        0;
7 F* \1 O8 p# P3 T  R; x
- l7 ?7 r$ v. G        // Internal
4 i0 L' c- v- ]        if( no < 5 ) {8 g# V! E% \. {6 A8 r; j
                return        m_bMute[no+1]?internal.GetFreq( no ):0;; O' V4 T3 }" }+ F
        }
/ q' {' u1 Y+ M' S" H' G" b        // VRC6
7 G7 ]5 [' @3 q$ a        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ p7 S+ U2 N) I8 w6 G
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
3 |# ^2 E" p" {1 }! l* f# L        }
8 s8 y" h" A$ V4 B- c        // FDS, i, x. L1 q+ T' t& A0 @
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ B/ `( Z! z& {4 i# t                return        m_bMute[6]?fds.GetFreq( 0 ):0;
3 y' j: g! }+ ~# `        }$ j8 o3 s2 |; ?$ W/ K' H2 q( H' e( A2 N
        // MMC5
3 V8 {. ~6 x! _4 J        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: B3 v" c# y, _2 O3 e
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; ]! ~( x9 U& e7 v. v) t+ L        }2 b- v! q2 j' _5 v
        // N106) L8 b; t6 K$ P) k- h$ j" Q
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
: a$ d8 \, }  Q' z3 W                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
/ D) h  ~2 S$ f) L3 E1 V5 x        }; ?; d+ x4 e0 M0 P5 d* ^: h
        // FME7
" ?5 G* F- [- J! n! e+ ~        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 J7 o7 a& U, N, P                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
) N1 c5 g$ G" C) {; P; c. y        }
5 ]8 t9 l. ~) G! Z; Q4 o2 B5 I4 t        // VRC7
! N8 O$ H+ v% ]$ z; ]: ^        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
) c9 J7 ^) \* s                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* n) W7 b' Q2 m5 }3 s7 N/ w
        }7 K& S+ }1 v$ |/ n2 _0 ]3 P
        return        0;% f* x% E$ D" q  e$ t! @
}6 g5 W6 `+ F6 ?& y) c# y; s" z
5 X" G8 B6 I/ N, a
// State Save/Load1 M. ^+ ?/ s1 M9 b- y( R: f) c8 i
void        APU::SaveState( LPBYTE p )4 ~0 `  F' w- a+ y  Z
{  s, R; j5 A( N8 n+ D
#ifdef        _DEBUG7 ?0 h, H' t' Y, A7 b# n9 `
LPBYTE        pold = p;
7 R  l: {( R3 o3 s  A' s#endif
5 t* R1 ~5 |- p  ?9 b. y( {# e, Z0 P8 H+ M3 o
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 t4 t6 U6 @' y6 O" e        QueueFlush();6 O" L. k8 T0 U& g  t$ S" M# p5 ?

7 f6 A8 Q. L% t1 U4 }        internal.SaveState( p );' W  R/ l) _7 N4 O% E0 J$ u
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: r! C9 g0 z5 V- p' F
" ^7 M. g5 ~" e" }, L# `1 N0 n8 @        // VRC62 U# x' T7 x+ U: j+ I  b
        if( exsound_select & 0x01 ) {
6 ?+ z3 E# X" I4 ~* P9 C) P                vrc6.SaveState( p );" p, P$ b3 o6 ?, {! P) @) W2 T
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 I. m) ^+ R) O1 L. m4 ^2 Q
        }6 L+ p4 m; g4 A! B' t) g
        // VRC7 (not support)" t" p: w/ s, F' `! W
        if( exsound_select & 0x02 ) {/ P$ J. a* _! W9 ~( `
                vrc7.SaveState( p );
. y% M+ v; X& B5 V" k4 n4 a                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' ]; R* g2 n7 _4 c! x        }
  V. d. m: Y8 L1 I" x+ f* a" z        // FDS- g9 \# u/ B9 u  S6 N
        if( exsound_select & 0x04 ) {
% L( }% l. B9 ~; ^+ f; W# w                fds.SaveState( p );1 u) f/ Y0 k) [' t1 E- D" a
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 b5 V5 F: I, U: T6 _, T/ @        }5 I) j. P% S5 m( Y" y! W* E
        // MMC5
$ W6 v! R3 i. ^5 K  r        if( exsound_select & 0x08 ) {
: J$ u# d- ]/ B% Q* M" G5 ~4 M$ n& ]5 r                mmc5.SaveState( p );
$ z( l9 X1 p0 U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 a  h: E; m( Q7 i
        }
- R1 ^) e4 c. A* T; O# k        // N106
5 R( c- u1 e. D, g/ D5 S. v1 A        if( exsound_select & 0x10 ) {
% f: Y0 E) r  W                n106.SaveState( p );( r/ f+ ~8 W0 N1 U# O: g
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, N" y- ]7 r4 z# d! @1 E& u* q        }: b4 r/ H2 o* G. K$ C" u
        // FME7
. c  H7 M9 Y: T* C7 ?) d6 X# }        if( exsound_select & 0x20 ) {8 E( H, E0 f0 Z- g8 N  K# Y5 S" N
                fme7.SaveState( p );
. G& K9 Z9 I9 _8 I6 F2 K# _                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% R; _  D+ B) a, k: ]        }
/ r( l' M7 @/ B4 }- n  p% T* u' ~& s2 d+ \. M0 D' I/ E4 x
#ifdef        _DEBUG% p" E- w6 f; O4 C6 Z$ c
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );* u$ \7 Z% p/ J$ h, G
#endif- U# z: r4 u0 w/ n5 h9 J3 ~' r' m
}9 ]4 R8 Z! ^& w+ \: v

8 b$ @/ ~2 G: I5 ]+ s+ rvoid        APU::LoadState( LPBYTE p )
# R) M; p0 n! y) L; t6 M{
  `! ^% H5 i  t! ~        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 R4 j4 z2 b$ H5 {; A. \        QueueClear();; U1 p4 f5 e5 a5 k. A3 T, r9 O- r

- }/ Q* Z' E( j, y$ \2 \- a; ~        internal.LoadState( p );9 ?% x2 M& x. o$ V- j
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 ]! y: Y- J% U' f, D; N: ?( g6 z7 n; A+ p' e
        // VRC69 E8 p- Q4 m9 {$ a. q4 v. f
        if( exsound_select & 0x01 ) {
3 u* i; p" ~; o$ |& [$ a0 a% k& O* ]8 _                vrc6.LoadState( p );- t, @$ {% k* [6 O. N( u1 W
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 W9 {% Q) Y) y        }
% T& l  g6 ?- F4 ]* T9 X" A        // VRC7 (not support)
" {! O1 y; \4 k3 g, V. A# V! e7 C) Y        if( exsound_select & 0x02 ) {# E5 d0 X7 M; x3 i. i
                vrc7.LoadState( p );
# p1 a1 k9 n7 m4 ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" {5 \1 g) I, E7 d) `
        }
  `& c2 R" _2 q% V6 k8 i' y        // FDS
( O1 w0 F) Q/ b6 C) o        if( exsound_select & 0x04 ) {
) ^! W* O' H. h$ e3 y                fds.LoadState( p );
/ C# `( ~: V' O                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& t' D8 M7 y3 P        }
6 f( W, W. b1 B1 ?        // MMC5
: f# `$ R& T) C6 P        if( exsound_select & 0x08 ) {
# J5 U9 w% @6 `$ N" [) t: H7 M                mmc5.LoadState( p );% Z# ]) Z- E4 {1 V3 M: i# y, v- W; l, I
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ {5 C0 d$ V) Q. H% }        }$ W. Z$ q# `5 T" k% x6 @
        // N106
- [$ \( J2 A9 M        if( exsound_select & 0x10 ) {7 |% P, |( E  u' G2 v/ B
                n106.LoadState( p );* w1 X6 p+ N; [. g" ], t" w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# |: v; o3 P$ A& E# E3 H( H        }
4 C% M+ P' ~, B% x) [        // FME7- a- p: r/ u$ I. P3 i& d1 E
        if( exsound_select & 0x20 ) {1 g. {- @$ c) b8 e& \
                fme7.LoadState( p );' \' ]. U  Y5 h& P
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 ^! H  @/ `' @' p7 H
        }- i( u, D6 w3 W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
  Z3 U. K1 t& w, _4 F可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: @1 r$ c9 V7 e
感激不尽~~
% ^( k& Q. n* q0 _# K6 G
恩 我對模擬器不是很有研究,
8 X+ A, @# k; k雖然要了解源碼內容,可能不是很困難,
! Q' c2 B8 Q/ J$ T- @' S7 P不過還是要花時間,個人目前蠻忙碌的。' d/ p6 c% {" K8 w% W; S. |% O
1 i1 ]; c* b9 `* i. B+ n* N/ ?
給你一個朋友的MSN,你可以跟他討論看看,0 F" I* s: C7 W+ v3 }/ m
他本身是程式設計師,也對FC模擬器很有興趣。/ m0 J, M8 [  A# p" v; t) |. }, r

8 G4 v) E" R" f( L' nMSN我就PM到你的信箱了。
! h' `' M$ T- Y" s: g! g" L/ t& h4 [  c1 E3 v0 O
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 d, [6 G" t+ L$ n; {2 L# I/ C7 [
呵…… 谢过团长大人~~

) \( o4 W& @2 L- H' d* ^/ }, n6 }7 Y. p- ?
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
1 X" e3 k- K) o/ i团长的朋友都是神,那团长就是神的boss。

3 W) c" b4 _% o* L哈 不敢當,我只是個平凡人,
0 I' L6 L2 G! O7 [9 H+ k! x要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙- Z/ Y4 s: z, _' W$ S3 x' W) d
ZYH
  M' r/ N) l8 K  `QQ:4147343066 q  Y8 `* h6 r; X" ^
Mail:zyh-01@126.com& [$ V8 Y3 i; f! c' j2 M
6 a4 |' G: r6 d" g* u# }+ ]
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
" H# \; e& }8 B7 E" V- h' Z  ^再次对团长大人和悠悠哥的无私帮助表示感谢~~

3 k# y4 W8 B* y0 z' `6 O不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 23:53 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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