EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! ~' |8 s  V! `. k6 a, t0 ]9 B
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ j5 x3 [" R5 i( Q) Z% i, q这里有相应的模拟器源码,就当送给大侠了~~
$ b$ M" s& X5 [4 T) |http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 1 H9 a/ P9 a. q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
% W' }' ^* m  F3 y# G$ u8 K楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
5 P$ J: _& P# ?7 ], a2 V这里有相应的模拟器源码,就当送给大侠 ...

+ K+ J0 N5 Q6 K( f8 v聲音部分(Audoi Process Unit = APU):* `5 B0 M; x" x% z
.\NES\APU.cpp
" n7 |' R0 l- Q! f.\NES\APU.h9 r# O8 h- S) A0 g  C4 z0 R% O- h! ?
3 |3 h  E6 b1 f

; ~9 ?7 N, Q- g7 \) v8 e; O1 h影像處理部份(Picture Processing Unit = PPU):
! T( W6 Z3 Z) V: L( h, G3 G* f.\NES\PPU.cpp1 w1 a6 }* w% `# N, |! W' e
.\NES\PPU.h
2 k" L) o1 f0 a1 F7 o
& A( J% [7 T  }8 t+ L0 ^4 {如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:. S* z. H4 f. E2 m
(由于很多专用术语和算法机理都不明白,所以看不大懂……)9 V& Z$ `% H/ {" K6 P! w
//////////////////////////////////////////////////////////////////////////7 @6 P$ \2 y" {7 L" y
//                                                                      //7 I! E" K, h# Q- e' ]. o
//      NES APU core                                                    //+ I/ e* U# h' ^1 `% O  H
//                                                           Norix      //; K. Y4 ~* j6 Y& g8 ]6 h- Z
//                                               written     2002/06/27 //
2 r! H( k! M; V) y( L0 ]6 Y//                                               last modify ----/--/-- //
5 l& a/ q; ~: A8 s) |( C4 T8 @6 E% {//////////////////////////////////////////////////////////////////////////0 v, Z. ~7 b. O& [- o
#include "DebugOut.h"
( ~/ v" D* Y, Q- n#include "App.h"4 k# Y" Y* S6 ^" g- u' \
#include "Config.h"
1 x! j4 I1 _1 s+ _% K/ v3 r& h* d
" S/ p! U" `  M! q#include "nes.h"
0 G- W& E" E7 X& ^#include "mmu.h"
! u- k3 G5 `) K" @& e& e#include "cpu.h"5 ~7 g# \+ V, G4 [$ B. v
#include "ppu.h"5 }1 v* h- q0 J
#include "rom.h"6 Z1 v  ?! E. t/ Q1 V4 K& P
#include "apu.h"
) D( E1 y9 \8 D! ~7 G9 H  L0 {! K" k; e& Y; B1 I% ^$ m+ b
// Volume adjust
& y* f$ }/ x: \" u' V9 o% d* k// Internal sounds! M% |- a6 o5 ~) O( B
#define        RECTANGLE_VOL        (0x0F0)- U, E0 R4 }. ?$ j1 J9 i- i$ W0 }
#define        TRIANGLE_VOL        (0x130)
& U2 W; m9 i/ w" X4 t4 W#define        NOISE_VOL        (0x0C0)
+ v. @  L! a0 U; e7 S& E: D#define        DPCM_VOL        (0x0F0)6 O8 G0 X: O2 T" u7 y
// Extra sounds
& }+ ^1 n9 i: e# @! c& j( g5 T#define        VRC6_VOL        (0x0F0)0 J1 O( c7 {$ _
#define        VRC7_VOL        (0x130)) l9 z% V7 Q; u6 {% }4 `1 k7 t
#define        FDS_VOL                (0x0F0)
9 H) d$ M- `5 c+ e# P" B#define        MMC5_VOL        (0x0F0)) _* }, b/ [# i) F5 Z+ r6 I. d
#define        N106_VOL        (0x088)1 x3 V. g7 U" M5 q
#define        FME7_VOL        (0x130)
  Z- g: f# p) C7 l
/ ^, v( p, @  l" \% [5 UAPU::APU( NES* parent )
: ]: L; t$ e5 M0 W$ h  o' R+ [{2 C: |0 ~: S8 i
        exsound_select = 0;
8 t$ a1 H9 S5 U; D
" c' j2 N/ ^; c. s8 T        nes = parent;- y9 {+ B6 o5 |  V4 d2 L
        internal.SetParent( parent );
7 s1 ^5 i( W6 {' W, e8 j
* @: f( }" O3 {3 k5 z        last_data = last_diff = 0;3 E( v( t$ Q$ B' Z5 q0 m! m: ]
) S; W9 |( K) f6 m5 \" j! M
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 b1 S0 C; J, m) G+ Y& Q9 V

' ]5 y# D) _3 R% h% v        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
% s9 b3 d; b  g        ZEROMEMORY( &queue, sizeof(queue) );
( Z( X, Z6 i5 b) }        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 F/ f- b+ [  `- a4 p

( Z1 ~  R6 h: P        for( INT i = 0; i < 16; i++ ) {! l  n; F5 L  t/ u! Q8 b: m7 ?
                m_bMute = TRUE;/ G! M" ]3 S6 j4 A1 T. I
        }
8 B9 C( ~7 x1 U/ v2 H}) f+ u: P& D9 u; [5 O9 C
1 [4 d2 H% `2 k$ s* ?" d' ~1 X9 l6 O
APU::~APU()
' C) q! F8 ~9 m" |) }# j{' T0 l4 }8 l- L  ?( z& R- f2 a- t
}  v# `& j/ s% p9 ~# }0 y2 o
9 z1 Q6 a! \7 D! ^# a1 Q
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
* j8 V+ `) v" U9 B{/ A! d- H' T* d" K
        queue.data[queue.wrptr].time = writetime;
9 F- f3 G+ \% e( E6 E/ n        queue.data[queue.wrptr].addr = addr;* B8 Z) y. B6 w# R3 L
        queue.data[queue.wrptr].data = data;
8 W$ R& q$ t2 `7 J  V+ _        queue.wrptr++;: {: x1 U0 \# |  Y, t& r
        queue.wrptr&=QUEUE_LENGTH-1;
- B/ G, s" x0 s0 m% V: {( R        if( queue.wrptr == queue.rdptr ) {. y* \! u( G% h- C8 h* b
                DEBUGOUT( "queue overflow.\n" );8 e1 O$ F( n' B/ j7 j1 Y1 S/ n' j3 S
        }: c- X7 i" ?8 L2 s% |) m, a
}% h0 [: H: S0 E/ `  K

/ m- f! w) a: u1 j0 @: k8 [0 \BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- i  [, n! \: f{
* C5 A5 C2 N8 b( a: v/ i        if( queue.wrptr == queue.rdptr ) {
$ H1 z& Q6 j: \2 Q                return        FALSE;2 @4 C: |  J4 h
        }
6 V- c* d9 O) K0 h: Y  k1 G        if( queue.data[queue.rdptr].time <= writetime ) {6 S( K2 E: p0 K, m1 s' {+ r
                ret = queue.data[queue.rdptr];  N% x8 w+ y8 v/ @5 m
                queue.rdptr++;
. t' b, n' U9 b) J2 w                queue.rdptr&=QUEUE_LENGTH-1;
2 Z+ U6 _% d- Q  L" t, K                return        TRUE;; x8 B1 n- D1 f; V$ W
        }
3 G9 M. O: g1 q1 }6 j" d        return        FALSE;9 Y( Y. s, z+ P& z4 S7 u& t
}
( L) ]6 V" l. s) I8 [3 }9 I6 w! K( {7 O& H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )& Z/ N3 I. c2 c% s- Z3 B
{
# @) l3 {1 t/ D  X1 ~- O- e        exqueue.data[exqueue.wrptr].time = writetime;
5 ~6 N7 ?7 n, m! U, _9 H% l        exqueue.data[exqueue.wrptr].addr = addr;
  t4 Q8 o0 M; B. Y+ B4 H        exqueue.data[exqueue.wrptr].data = data;$ h- [6 I  ?' B% f1 ^/ x- D! x! @
        exqueue.wrptr++;) _  v6 I/ @4 L+ K$ m+ p3 X, V
        exqueue.wrptr&=QUEUE_LENGTH-1;' d, o+ y  F. v( B. ]" O9 f
        if( exqueue.wrptr == exqueue.rdptr ) {
5 q( M! o! K# u                DEBUGOUT( "exqueue overflow.\n" );9 J* Y. |* s8 g) T% C; W; G7 \
        }; w1 X/ g+ O9 V# b/ U
}
- O5 t# e" I' N2 w% U! c/ [  J  g/ L0 ]9 i* |
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  [* \" M$ ~5 G
{) P" U8 C' L9 M/ O% V9 c1 [) X, B
        if( exqueue.wrptr == exqueue.rdptr ) {
4 J' B2 T7 T( q% ^" Q& A- g! q  B                return        FALSE;
! K3 I* N* Z& d8 F$ S1 U" ]        }
* b" e* v8 c( c& w6 P9 O        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
( q7 h1 s$ c( N                ret = exqueue.data[exqueue.rdptr];
$ n# C/ |9 c6 ^) Y' R: _$ Y                exqueue.rdptr++;
2 T# C! k% K3 n( t5 {% v                exqueue.rdptr&=QUEUE_LENGTH-1;4 c- v. L5 R/ Z0 o" z4 R$ J% \
                return        TRUE;
: {5 b3 f. A6 I; V6 T; M" [, N9 I        }: k! b* w1 J' M4 ?0 q$ z9 T: f
        return        FALSE;/ S2 z7 Q$ Y6 K: t: B
}$ M( V$ h% T- y4 W9 `* R

. {/ L" O  }2 pvoid        APU::QueueClear()
- {& b9 b( _- ^) {) t{
) |" `% M5 M  w0 x4 \        ZEROMEMORY( &queue, sizeof(queue) );3 T9 Q1 X4 D* W1 e/ z, n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 n! c+ s. G% F+ f. A}
% `0 k- g/ s" R9 Q0 W" Z5 ?6 g/ U9 [
void        APU::QueueFlush()4 f2 ~$ i3 Y0 ?6 v+ n! r! T& X
{$ M2 g0 c% x8 ?3 L4 g$ B- ^
        while( queue.wrptr != queue.rdptr ) {: [0 O0 `  v. K4 i2 d
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );( o; h% P  E$ e8 z7 _- v
                queue.rdptr++;
" f' {2 f0 d0 C  _! c) a                queue.rdptr&=QUEUE_LENGTH-1;" P7 i; I: G+ I# g3 s9 M
        }
7 \. w7 r5 h' @; Z% W
, j  ^: L  _) ?# B6 V        while( exqueue.wrptr != exqueue.rdptr ) {/ t; t9 f6 C: c
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ j) k2 f! q3 Z                exqueue.rdptr++;
3 C" `% u7 l" S0 F* @" S                exqueue.rdptr&=QUEUE_LENGTH-1;
! x6 b6 O; p4 _' i; g6 Z' c        }
+ T8 R$ f' J7 N2 V  ~) |}
) O: x" p' x0 n8 {4 Y' e! u! M
: B* b) C5 ]* Vvoid        APU::SoundSetup()' I( z+ m9 u+ E0 F, M5 j$ D
{
3 e3 g  ~+ N5 j) }6 p* S        FLOAT        fClock = nes->nescfg->CpuClock;
  d! w) C" l* O' o; u' f# m        INT        nRate = (INT)Config.sound.nRate;
( X5 x/ B. T" T+ I: Y; b        internal.Setup( fClock, nRate );1 x4 N  c4 X( D3 J$ E
        vrc6.Setup( fClock, nRate );
. J' A/ d  ]% ^5 n1 d' J' I- q9 s8 x        vrc7.Setup( fClock, nRate );% q1 u8 c3 N8 K
        mmc5.Setup( fClock, nRate );2 C# }# C  J) W- e# R: @
        fds.Setup ( fClock, nRate );2 f) b* D( g% z2 t& l- K% ^) B6 b
        n106.Setup( fClock, nRate );- m2 s# l6 W6 G$ P; v# j& e
        fme7.Setup( fClock, nRate );
  L! y) r* g3 I' D7 A! l}9 D6 g( s" S. z# R

2 U7 \& f& k5 @2 w  vvoid        APU::Reset()
* e4 i8 P$ n: ^- j$ z{
* p) ]9 e7 T  Q2 F        ZEROMEMORY( &queue, sizeof(queue) );
' K" H+ Y6 S# n' U7 f; p$ X        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 u- U5 P2 Y( {" ?: A( c
! g* P2 p: p; j# d3 x
        elapsed_time = 0;( O/ I$ `# c( B1 x- p# z
8 n* @2 C8 o( p
        FLOAT        fClock = nes->nescfg->CpuClock;
* M9 Y" O/ h8 W5 m. v4 {        INT        nRate = (INT)Config.sound.nRate;
: Q% {1 N$ I  \' z        internal.Reset( fClock, nRate );+ c0 E; i$ }! v1 ]" |! Y& h
        vrc6.Reset( fClock, nRate );
* q* i4 {+ E8 s3 `) B6 o( X% o        vrc7.Reset( fClock, nRate );( z- C4 [- v# t5 v! p
        mmc5.Reset( fClock, nRate );7 ]4 V0 K3 F$ ^2 x7 f" X
        fds.Reset ( fClock, nRate );$ c* {7 J, P0 T( ~1 j3 |$ X
        n106.Reset( fClock, nRate );
4 X+ Z, l& c2 }5 [: v& l+ N6 f        fme7.Reset( fClock, nRate );
1 k; ?9 m( y+ G- G* y$ a: G4 B5 Y$ k
        SoundSetup();3 i# Q$ h' J, C5 x) f& a  f0 R
}; N; {& m# \5 C) F3 j

$ t' c! M% s; l0 }; X+ A: tvoid        APU::SelectExSound( BYTE data )
: l! q8 i- T" Z$ W9 i) y{7 u: p* J2 B6 d$ K/ z9 o
        exsound_select = data;' ~+ Y0 n6 o) J8 g- r, t! ~
}
/ A' ^3 r8 ?" p" @7 w  E$ a2 T& S& @; v* a  B
BYTE        APU::Read( WORD addr )# P" g3 ?1 s" h9 ~
{
2 P5 x$ B2 A" ]        return        internal.SyncRead( addr );
# z3 Z* ]% L) `% ]% t4 v( B}+ M) b! Y; ?! J% E* @

8 N+ i6 \$ U; [6 H5 W2 X6 j* Q6 ?void        APU::Write( WORD addr, BYTE data )( k1 J5 v! b% H, b
{
3 a. t$ z) Z1 V7 `4 v        // $4018偼VirtuaNES屌桳億乕僩
, S2 T  N9 m! P4 a        if( addr >= 0x4000 && addr <= 0x401F ) {- N' a! _) M8 U+ B! p0 Z
                internal.SyncWrite( addr, data );& R8 c6 R2 ]/ K+ v8 x& E. |
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
0 [. [0 {# s. E8 C        }
' S: N7 N. Q  F1 B}) N" c, G7 ]" I) t
* X; E! k& p' Z* Y4 r& w% A  L
BYTE        APU::ExRead( WORD addr )+ Z! t. `; t' s7 j1 h3 ]; @  J
{/ g8 b2 |; a" c1 R
BYTE        data = 0;
+ r3 p$ |, V4 l* U2 E
0 [- E% W( f  B( a3 n" s        if( exsound_select & 0x10 ) {
8 `: @2 H' H9 N1 Y% F' x% R7 g                if( addr == 0x4800 ) {
) z/ _( O# T. k3 ~" D8 }                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& a/ d* a( r' M& `1 o
                }
$ X8 [/ E& z- r9 h6 ~* ~        }4 l) y  M- i# U: U1 l, U0 A1 V, M4 N+ r
        if( exsound_select & 0x04 ) {% n+ Q* C/ P. `  G, g/ b  ^
                if( addr >= 0x4040 && addr < 0x4100 ) {1 m1 k# p4 ?3 e
                        data = fds.SyncRead( addr );' N7 k' [+ @5 c( z3 p, r
                }
, j8 I- b/ j4 K; i        }0 ^: [7 K0 U2 R  k
        if( exsound_select & 0x08 ) {- d7 c5 S. ]- w# |& w4 o
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 A# @/ O! G( H: ]5 w1 p
                        data = mmc5.SyncRead( addr );5 k5 O: |$ u) h# y7 j1 g
                }
& l( E' G0 |" l* X4 a        }
' T+ ^- c/ Q& d5 y: s( \2 J
7 m9 b3 |- b4 j. B2 u6 {$ k+ |2 \        return        data;; y* W' N- p2 @$ F3 j
}7 g  r  a, \$ [% C0 ?8 ~2 ^
* V" }5 M( U+ v0 z0 V+ W" W
void        APU::ExWrite( WORD addr, BYTE data )
0 E. |% s4 [6 s, h+ s' k{
: `  S! P) L, _9 W9 A        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( ~! L% \0 Y5 W: T: m5 q& @1 b: z# ~1 t* k3 t7 [  b5 D
        if( exsound_select & 0x04 ) {
0 f( @- n* P- w) Q- J8 g                if( addr >= 0x4040 && addr < 0x4100 ) {
( e7 \9 P" s( Q; [6 L                        fds.SyncWrite( addr, data );
; o; G  C2 G0 P5 w- a& v                }
- A; l4 X2 y$ f! [0 ~" k- R/ [; I        }
+ K( V' E' p% p3 p
6 B- g7 o7 P6 h8 S) Z4 A        if( exsound_select & 0x08 ) {
/ b7 d9 Q( ?) U0 Q8 G2 D                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 g1 ~3 i# R% ]/ V- m6 K                        mmc5.SyncWrite( addr, data );; t1 a. R3 N4 Q+ T  Y# h( I5 m
                }
$ ~/ X9 t$ v# F+ d1 K        }
! N: z' R# |2 ?+ y( C- D}6 u  `. ~- \  F/ ]
+ g* [& S) t. i& [% P6 `0 A
void        APU::Sync()
* o) }& f' E7 ^; E6 x9 }4 n{
3 v+ E" T) t. p* M% Q}" V( T6 A) B3 f

/ ^3 Q+ K" ?; W/ O0 Hvoid        APU::SyncDPCM( INT cycles ); y2 Z% i- ]: c, r& U
{
9 Q1 s6 C8 C. @% h% X9 |        internal.Sync( cycles );
2 i( ]$ R( _. M" Y' k- B! c  }( m( ?' u
        if( exsound_select & 0x04 ) {
: Z/ ~7 w' a5 E; N. _                fds.Sync( cycles );( a# x4 ^9 j  o
        }3 a% h  v( e8 U! g3 M
        if( exsound_select & 0x08 ) {
" N3 r, d% \+ \7 _                mmc5.Sync( cycles );
+ @: k- n; k6 q) I: E        }$ R$ }0 f* |$ V4 b& k/ X
}# c8 c) G5 e! Z$ l& I" @& g* ^

: k" T: a: A2 P" V/ o* rvoid        APU::WriteProcess( WORD addr, BYTE data )
, V8 m! G% ^: l. X" ]; G{
" [2 Y7 Z2 |; X& ^8 e        // $4018偼VirtuaNES屌桳億乕僩
- y2 a1 v3 R, |6 j# X5 v, V( R        if( addr >= 0x4000 && addr <= 0x401F ) {7 E" P* a: y1 E* d) h9 |2 ~! y$ M6 m
                internal.Write( addr, data );- v. P# E9 D$ k, V7 N
        }
1 a% {  G! C; J- W. P3 s4 ]; _5 M}
! X1 Y; Z: T: X, X6 b7 j* F- {1 m& f9 z3 z) R) x
void        APU::WriteExProcess( WORD addr, BYTE data )" S: Z1 e5 V0 U: j8 w
{  I+ y$ D$ A. W4 a# {! h
        if( exsound_select & 0x01 ) {
) z' ^9 f4 [- L: ?5 k+ F                vrc6.Write( addr, data );2 }! i3 J% B+ l; f
        }
/ D- F( P$ q% j4 X1 H        if( exsound_select & 0x02 ) {
( k" s  f! M' Y' ]1 T                vrc7.Write( addr, data );- M- W" q% q6 T4 J  {& L5 z. v$ {# S
        }; G( m. `2 |1 }
        if( exsound_select & 0x04 ) {: T7 p* ~3 y3 O9 M. P. T
                fds.Write( addr, data );8 R/ ^; _+ }; l8 m; y$ @9 Q
        }  S7 D* k, k; _1 I8 M5 b! C& a" @
        if( exsound_select & 0x08 ) {
& f8 \' m! V/ i6 {( i                mmc5.Write( addr, data );4 k6 P2 o4 i" n, O8 f% Q4 y% Y6 x
        }  f7 s+ Q8 R0 @& Z& z
        if( exsound_select & 0x10 ) {
: h+ m6 g$ l3 O8 T6 D. B7 d. R                if( addr == 0x0000 ) {6 }, @; n4 |, Z- U$ Q) A* c
                        BYTE        dummy = n106.Read( addr );
' S  N& c" ?4 v, y8 {1 _$ Z* e: {                } else {* r# H+ c& q; a. j) m
                        n106.Write( addr, data );. Q/ a' D. C$ g; \/ E
                }" v% M' c3 }1 _) W
        }
+ L. d4 q2 d5 `; ^        if( exsound_select & 0x20 ) {3 S+ V0 F+ ^# A1 ~6 p! N' s
                fme7.Write( addr, data );$ W- h" V( R% @3 Z. E
        }
+ R9 X" O6 z( q. s}
0 A, ]) Z/ H2 m4 K7 r. R4 B; H' t* h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 ?4 `$ L2 b' O$ V, v; Y0 e- }
{2 }7 x5 Y! J& r' I7 K- Y+ ^/ N  H
INT        nBits = Config.sound.nBits;: U0 {4 O6 b0 Y  E9 q0 t1 I7 M
DWORD        dwLength = dwSize / (nBits/8);% \0 h2 v; p& z, ^1 Z( r- B1 ?- `
INT        output;
( C. o# e, ]" g: Y5 ~1 b5 FQUEUEDATA q;) ^% Q$ {* }! f$ q( M3 i
DWORD        writetime;' D9 f  D4 [/ b9 X0 V2 w6 H) a' o
9 Y) G/ T  ?/ q3 }
LPSHORT        pSoundBuf = m_SoundBuffer;
0 {7 }" |  [6 U7 A: v3 |INT        nCcount = 0;& f! ?+ _3 R+ U/ Z" q( [/ W6 g

( [9 W; G2 b6 L+ a% }INT        nFilterType = Config.sound.nFilterType;
9 I. T5 P% g0 ?5 ~4 {/ M( Y( x
( F* R- P" w! D        if( !Config.sound.bEnable ) {$ z- y, i) }- U. ]& ]
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
8 Z' b5 L; v6 ?+ I                return;
1 q, |* m+ L1 k; K3 p. B9 L) ?+ g* \' w        }
$ b, n# ~* T6 a( _: L
8 ?+ d! K+ O6 p, [1 S3 _  K        // Volume setup
" [; ?8 }* m7 _& X        //  0:Master8 L4 d4 o$ N0 D. v* F
        //  1:Rectangle 1- A/ i7 \2 a# W
        //  2:Rectangle 2+ D- W7 V9 d" h! g  \
        //  3:Triangle) [% n# K: T# R- h8 H' F
        //  4:Noise" F  }$ `  y' e  P
        //  5:DPCM
) ?: `7 {8 U; f: S        //  6:VRC6  X5 {, \& S) k" o6 s. v2 A
        //  7:VRC73 n. r3 Z3 o+ P9 w+ I' s7 N4 b
        //  8:FDS1 v; c* o2 V( h, b% c
        //  9:MMC5' `6 o1 f/ c/ m) g! A' {7 V1 _5 t" I
        // 10:N106" x4 k6 ?8 O  ~$ |5 u6 P
        // 11:FME7
$ k8 c8 ?3 q2 U2 g        INT        vol[24];# T( m; H8 A  N5 ]) T2 u3 P8 B
        BOOL*        bMute = m_bMute;
9 b: U+ E  A- N7 g! `  R        SHORT*        nVolume = Config.sound.nVolume;7 j6 h3 g5 d2 M  U
! @  C1 N0 y+ ?! F  Q; }3 c
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
* x* I- Y- p9 V- o/ a3 g
7 s9 ?6 v9 {- f7 S* ]9 o        // Internal
4 b8 P) a0 d% l0 k; w        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
7 s; O4 [& z- F* |' v        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
7 w! p. F, k; K        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
' f/ D4 P, e1 T+ Q! r4 m        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
) d0 @  q. T& \( R/ J        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
7 e7 {0 `6 V2 U, B4 ?3 b- l$ `
* ~5 n6 K. l4 B: |        // VRC6. J! U8 w' y9 v. o& }5 {* o
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ R, s* d" T0 H# P# T1 V
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 \- T+ i! e! ^, o; x) q! P2 l$ [7 j
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# y5 d+ C% X0 T# g' Z. R

, n- X9 [- t3 K% v0 C        // VRC73 @* {, i9 c; V; q2 W( X2 ]% `+ m
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 M0 ^* ~, ^9 \* y5 |4 ^) K
/ }  J1 e  K  i" u
        // FDS
4 a) k! R+ W  }' B; F1 u% |        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
! \" r5 |" S" j+ h. ?% C. G& R+ S
        // MMC58 j# ?4 ^+ F$ c8 R! s) m
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! h$ v8 c3 M) O4 T3 ]
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ U' G& J) [" J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. ]: G3 }  e6 z* T1 M# R; V# F# S+ m! w8 L3 q. N/ U
        // N106
/ V. w+ S# J1 H) x        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 ~2 n+ E; B9 Z* x        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, a: W2 D: y( v2 F- k( H+ ?  J; E' }
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- ]6 O. q! o; L# H
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 w$ {( f7 u* E4 b: C  w9 N8 f( G
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* j; j! ?; K! p0 }0 ?- h
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" K, n! b' [8 |: B4 I- ?
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. l( K& z1 I1 j! q: @
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# ^# B3 N# w5 l$ h# H8 K' t! H) J3 [9 l  k. z2 \9 h: S, y
        // FME7- O7 Z0 f) o/ j+ t1 l, Q
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 u) v7 ]! b" p) M5 ~" o/ `0 W5 V' t        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  G" m0 w9 C# ]
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 T  {" {" @% P/ s$ ]1 Q$ n* p1 q! y6 G
- [" E) Z/ R* J' O# `, s6 I
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" `6 C' l( c1 S4 V7 v# A' `
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;0 [  C* v$ p5 {5 j
  W' Z, g) B# Z4 l
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟+ X4 f; H; T9 A5 F, v" [" ]
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {. D) W0 ~: z2 n
                QueueFlush();
7 \- I8 J5 @' h: _! @        }
) h/ U- l  _2 b" i6 @/ A2 P! s- |1 |* P; E
        while( dwLength-- ) {
4 F4 f/ O7 w4 \1 H0 @  k- B2 V" l                writetime = (DWORD)elapsed_time;1 Q  X: f$ |. i6 t
) G+ D8 @  S) w) w: {# [" I: L
                while( GetQueue( writetime, q ) ) {
- j' t1 |  T% G/ g# L7 b                        WriteProcess( q.addr, q.data );& f' f; x4 s' h( ^, @
                }2 w* o, F# t* h7 M& Q

: T" J, u+ N" H% Z* M+ U                while( GetExQueue( writetime, q ) ) {, Y* B( u5 l, p2 ^& |+ R
                        WriteExProcess( q.addr, q.data );
$ C- s, B! ~' n2 R" v# y5 i                }$ h" ?; r- O6 k4 Y7 z# B* I

2 a# q$ j  F0 Q" w# E* a0 c- y                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# d% h3 E4 v4 v! V
                output = 0;
1 I( b1 o% i0 E! G) A/ v* h                output += internal.Process( 0 )*vol[0];
# N) m7 d( {' [' `- o7 a) P                output += internal.Process( 1 )*vol[1];
; z/ L' ~) n! w% G/ {& Y                output += internal.Process( 2 )*vol[2];6 R+ U0 Z( M- H$ @5 E
                output += internal.Process( 3 )*vol[3];
% ]8 X' l+ ]. Q6 a- u' U; s                output += internal.Process( 4 )*vol[4];# K8 z" P" a% Q, x* j

& t/ }' Q3 d" z7 ^, t& _2 y                if( exsound_select & 0x01 ) {
( K4 B: h) k: }2 w) R# z                        output += vrc6.Process( 0 )*vol[5];
7 N0 H) `. m3 _% }: t6 r                        output += vrc6.Process( 1 )*vol[6];
9 d. G/ t% n5 j8 a  b4 @                        output += vrc6.Process( 2 )*vol[7];# O9 D8 _# v2 j% D+ t9 ?, _7 z
                }2 B/ i! D' m+ p2 U& L
                if( exsound_select & 0x02 ) {
4 T6 }! d! n  K* R                        output += vrc7.Process( 0 )*vol[8];
% j/ s; ]  L6 m# {& G+ t5 k                }- \% G' z/ ^& |
                if( exsound_select & 0x04 ) {' o6 b4 ], e" X+ B7 f& C
                        output += fds.Process( 0 )*vol[9];
+ z% b" F! s. N* ~/ ]( c4 P9 M                }9 R: Z' z& [  K* ~5 \3 `
                if( exsound_select & 0x08 ) {+ U& G, S# M/ q% J
                        output += mmc5.Process( 0 )*vol[10];1 ?! F$ m6 }8 z) A/ e2 D5 }
                        output += mmc5.Process( 1 )*vol[11];# M+ S) w) v& }/ ]1 i3 N7 S
                        output += mmc5.Process( 2 )*vol[12];) J) l5 m* k; X: W, Z; Y$ M
                }
9 ?7 L4 b3 s  V0 i                if( exsound_select & 0x10 ) {
7 U, y) l7 F9 r4 Y* }4 U: U$ N! o                        output += n106.Process( 0 )*vol[13];0 p' j% B8 u0 T" d
                        output += n106.Process( 1 )*vol[14];! i1 O- a# O  U& ?  Z4 I
                        output += n106.Process( 2 )*vol[15];
, }8 U% q) Y/ U$ w                        output += n106.Process( 3 )*vol[16];
" }+ E( ?6 S0 v) D8 |& Q( B0 H                        output += n106.Process( 4 )*vol[17];
4 u  [/ m2 G2 a! U  j1 p  q                        output += n106.Process( 5 )*vol[18];
# c- w( h, i. {$ B! q. I                        output += n106.Process( 6 )*vol[19];
" Y( x7 \  k+ W                        output += n106.Process( 7 )*vol[20];
, K' X5 C; e5 p: |1 [- _                }, u5 m  I( c: E2 B- R' N. p7 b) X0 F' ~
                if( exsound_select & 0x20 ) {
* S9 G0 L4 X* Q" W3 `                        fme7.Process( 3 );        // Envelope & Noise
- c8 ^6 T: R- }( C                        output += fme7.Process( 0 )*vol[21];& _  t) C7 e4 h9 O5 g1 k6 k$ `; L
                        output += fme7.Process( 1 )*vol[22];
. |1 b0 d! T$ X' T1 \. d# @) Q' ?                        output += fme7.Process( 2 )*vol[23];9 ^" T5 o+ j1 y" m/ W
                }
0 T) S: Y$ z8 D" L
1 y$ w( u8 Q& g3 o2 N& ~  {                output >>= 8;
( ~3 P6 I/ u0 g1 C6 r# s# k% B: e! N9 L: Q% d* h8 ?8 {4 y8 D
                if( nFilterType == 1 ) {! G* G# ^" W2 {
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, A: Q4 k. j5 g1 _                        output = (lowpass_filter[0]+output)/2;
. p& h& I3 W! J9 c* F( t* }                        lowpass_filter[0] = output;
' s+ ^- R* I, X+ N                } else if( nFilterType == 2 ) {7 D/ {6 A. ~, q4 w8 ^' N) L
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)+ w& a$ z' p& D3 H+ o' a
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 t7 H3 y7 q" S1 Q/ L. v1 Z
                        lowpass_filter[1] = lowpass_filter[0];0 l: {1 U- n' ]! U
                        lowpass_filter[0] = output;
! v: y9 Y' b2 d) j7 F# O+ g                } else if( nFilterType == 3 ) {
* h& q9 h7 A8 _: K4 u8 K) T                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
+ }# Y' [0 O  N! f& d                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 Q4 @- S0 Z5 u% M; A  B) a+ b3 g
                        lowpass_filter[2] = lowpass_filter[1];1 m; U( ~0 D3 z/ i# A0 _& M
                        lowpass_filter[1] = lowpass_filter[0];
2 @' U  {; L# g+ l& X9 F8 L7 k                        lowpass_filter[0] = output;
5 _# d' C, ?+ N* ]6 W                } else if( nFilterType == 4 ) {# _1 N% \* ~8 _& t4 F" v$ N* g0 q: {
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
/ j6 N7 m! I$ r                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 r$ F7 j" n5 l5 T4 g
                        lowpass_filter[1] = lowpass_filter[0];
* r& M" o4 c& E6 f7 G3 x9 S6 P                        lowpass_filter[0] = output;
) g1 U5 m% T- I% D2 Z7 S                }
: Q" e( _+ _: K! v5 ~
3 _9 D8 A% |/ P( J% T#if        0
. U8 d! P! M( S( ]                // DC惉暘偺僇僢僩
5 f  E8 e' f) D# w. F) @0 l( Y                {1 q9 N9 }: b, J7 D. D
                static double ave = 0.0, max=0.0, min=0.0;
8 z. R# s2 @9 R3 `9 E4 G7 i- C) r                double delta;! V8 h+ P! K- p
                delta = (max-min)/32768.0;
3 t# p2 ?7 y) {* [, ]                max -= delta;' O9 n2 p% Y4 Y9 c
                min += delta;
3 w; i1 |1 \- c3 p5 P                if( output > max ) max = output;
. h, ]4 ^. @, G                if( output < min ) min = output;. w! l" e( x2 v  A/ C
                ave -= ave/1024.0;; ?: W7 z) d# `
                ave += (max+min)/2048.0;
4 G. O! x+ u, [/ E                output -= (INT)ave;
2 C( c& L0 d( b( X+ s8 T, z                }
# h  Y6 T6 r, K, S0 S#endif
, C4 N' V8 X' t/ X#if        1, u+ {! V6 e( T$ _& x
                // DC惉暘偺僇僢僩(HPF TEST)4 l% B5 P& [# N7 o
                {9 a8 L; Y2 A4 p0 G3 O2 @' c
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 U8 D1 J& `$ D& s8 F$ C                static        double        cutofftemp = (2.0*3.141592653579*40.0);1 h# _8 r0 }/ B) B
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
3 |: B4 N( D5 A+ [. I                static        double        tmp = 0.0;: `$ V9 ~  Q/ l0 h/ h
                double        in, out;" ^: j# P( ^0 V6 [! R6 d) l
0 K3 _1 U( ?4 N% R  R: g, ?
                in = (double)output;
4 ?9 ?. r# X- f                out = (in - tmp);) b' T, G  Z5 u9 r5 E0 e8 l
                tmp = tmp + cutoff * out;
! W; V( `2 c# N) Z0 o- Z2 l3 Y: v+ l9 u8 G; c7 h% H
                output = (INT)out;6 Z7 i2 l, q9 B. f
                }3 |9 t8 V2 ~( M$ ?
#endif
2 \8 A8 |4 q0 h! H, g/ y#if        01 e( y0 r; r: O% w
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' R1 C3 W& y- q; e                {( ]0 A3 n0 |$ s7 E: l% }+ U% R
                INT        diff = abs(output-last_data);
8 p9 R/ p) y3 s& L6 j  v: `                if( diff > 0x4000 ) {
7 c6 A8 J2 W! X9 c0 y0 B8 o  f                        output /= 4;
: W; q$ Q" B/ S                } else
/ C3 F3 g3 x' [; _- u' ]                if( diff > 0x3000 ) {7 }4 K/ E9 f6 J: d! X! D8 S
                        output /= 3;
' z: F# ]- C  i. t& {                } else. ]3 U. @& W: p2 `, I
                if( diff > 0x2000 ) {, ?3 Z/ t2 I/ z  n  @- _
                        output /= 2;5 }* J3 M" k# i, H5 ^
                }9 N1 x/ `2 v1 }4 @- v4 f' o0 d
                last_data = output;: c( P! b. R, ?! A4 _
                }
& U# J7 T8 p+ k) K7 ^4 ]2 l/ U% f#endif
; e5 S9 [  }# P3 F" }) s* w: j                // Limit" i- V7 {) o9 w5 `$ ]. I5 D
                if( output > 0x7FFF ) {9 f" g% t; C: @3 ?5 B' y
                        output = 0x7FFF;
& o4 n! K7 n, [                } else if( output < -0x8000 ) {
1 _* g0 a  l- L9 _& o                        output = -0x8000;
" t' g. S7 r! J4 `* r2 J/ `                }
! a) z# e+ |2 f5 Y- R
( s: U( m! Q' R! w# F/ _6 E                if( nBits != 8 ) {1 c8 C* A' n% _5 g
                        *(SHORT*)lpBuffer = (SHORT)output;
( f0 c; `. ?" P                        lpBuffer += sizeof(SHORT);7 o* Y+ m) a, U5 e6 X
                } else {( k5 t  b: s- y& k7 D3 [4 d1 d
                        *lpBuffer++ = (output>>8)^0x80;
# V- Q  _( b4 ~( B* h/ A                }/ f6 [2 {% o( R/ t) I
, h% n/ W- B" {2 L- d, M
                if( nCcount < 0x0100 )
; m3 ]- U/ D, q, f0 h! {                        pSoundBuf[nCcount++] = (SHORT)output;
1 w$ d$ H& u6 T# r5 L' J3 S9 O8 d' d) {$ n2 n+ L
//                elapsedtime += cycle_rate;
; ]" _4 L7 B5 @                elapsed_time += cycle_rate;
8 J$ H, M' t9 z  t& T; x0 o# u0 B  U        }
, S. @4 t# j7 g" u/ u8 F4 }* J( E' w& K" s& ?6 r6 _9 g
#if        1$ Y: L, s: O& @
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ K! ?( o# A, g' E                elapsed_time = nes->cpu->GetTotalCycles();, s  l4 Y' |6 m0 \7 ?
        }
3 ^9 R  v- T4 k        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {! Q+ Q$ C' u9 I* _) {# W
                elapsed_time = nes->cpu->GetTotalCycles();
( B% w! R$ r1 g+ i0 ?, x. l7 U7 T        }8 C; r5 t; r2 i' E; E# S! F6 i
#else5 j. W- A5 K) S
        elapsed_time = nes->cpu->GetTotalCycles();8 w; f7 ~" s1 E1 v4 _3 H6 w/ |
#endif; Q% Y" t7 f  }5 I
}
" z3 C! b8 N: c0 L% v; n$ I4 K" {& o4 u3 U
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡): Z, b* A" E  X* ~
INT        APU::GetChannelFrequency( INT no )& b9 u; a) U; n$ l8 f
{
" V) a/ F. I9 D$ w+ R/ l  N        if( !m_bMute[0] )# H  i8 I; _4 p! v/ s7 P  y3 p5 z
                return        0;4 m% k7 Q8 m- G

2 j( A$ H) `% x( C2 m        // Internal; X% Y" x! `) w% [' ]6 J
        if( no < 5 ) {) o: P& Z* P7 O" |% r1 m. k
                return        m_bMute[no+1]?internal.GetFreq( no ):0;6 E7 W4 L' N/ \+ ^' v$ l: m
        }7 K: h9 `9 a* q9 _! p3 a4 x+ j
        // VRC6: o! f9 F5 ^0 ~. Y
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; j5 n6 O' U9 x
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# q! ?" H% |# Y
        }
) L& m  o% S( v+ }        // FDS% e, g0 N# M6 f+ c' T9 A
        if( (exsound_select & 0x04) && no == 0x300 ) {
2 b; d8 Q" d! E8 Q7 [3 ?" C9 B                return        m_bMute[6]?fds.GetFreq( 0 ):0;
5 W- W1 R0 v, K0 S/ \        }2 q$ L9 D! |+ Q7 ?* o$ t2 W& ?0 z
        // MMC5$ |& W& i% H7 l) b0 l8 d1 Y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
7 C  O$ f; ?8 S& ~                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ {& [! r3 e  N9 s, n/ b% Q2 U/ S        }
6 h' B# `7 D8 e        // N106
) C1 ]1 e( ]( k" |7 x) _. ^        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 m8 g! \2 _" a2 d* D1 u                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
% r2 n) z! O5 |, a9 R( y. y7 I        }
! G$ Y$ e/ ^8 N& N8 ^) U5 m0 I        // FME7  V! [0 G6 H3 x! E
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) s8 h. s- U7 q* h) o
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
" q4 D: C% x, z% M, c        }
3 J6 {- @4 ]7 }. D: I" Q$ D        // VRC7
& F3 |1 l+ q- b- B9 E( `  j        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
& Z$ j% L% C% ^+ K5 ?                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 y# q* K0 o* i+ e        }
; A  x+ J( g" a( ?6 d* S        return        0;
' ^& L7 ^5 f* q! F. [}6 O" |0 H7 V' K

1 f3 z2 y- E- J+ Q6 v0 o// State Save/Load' f2 B4 D5 o8 {9 f
void        APU::SaveState( LPBYTE p ), [$ T* ~% s7 H) `5 v4 A
{
9 F/ c# C6 R3 F5 x, _) c! {#ifdef        _DEBUG* V2 h5 @! e7 \1 F
LPBYTE        pold = p;
8 U: W7 }, k( N! z" ~#endif5 d- I0 ^5 |* Q8 W8 ~) |; p
0 |: Y! }1 V( [( Z% u' Q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
# E1 O+ n' ~* I/ t- p- }- N        QueueFlush();- u) h7 q8 p6 b% L+ r' W

$ g. G6 W  Y6 m$ V! H, m" l        internal.SaveState( p );
) w8 h: z) o2 s& z# i! C        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* L# M( |1 I/ B9 }
# A/ q5 a: P& R. Y, Z+ ~        // VRC6: c1 F" Z8 |& |; j
        if( exsound_select & 0x01 ) {
5 G; x: W$ x2 Z7 l7 P                vrc6.SaveState( p );; C# I" N+ N: }" a9 Q, m
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  _8 l2 n8 _( l% q        }  d0 M0 u* w  t, L1 l4 m" T
        // VRC7 (not support)
4 K4 D+ n8 T5 T; I7 E        if( exsound_select & 0x02 ) {
* g: l0 `% z3 R1 i% z: n' S4 I                vrc7.SaveState( p );
6 w5 i0 `; {4 N% H# b0 V7 I1 a                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ q4 ^6 Q9 q+ k  W2 i. b        }
5 K+ c$ }7 I  m" I1 r& k        // FDS6 e  W6 X- C4 [; [9 e
        if( exsound_select & 0x04 ) {
# ~1 f4 r4 O# D1 ~9 l: h3 [& p                fds.SaveState( p );
0 ^2 N0 D0 q; T$ `8 B7 e                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 K) N$ K9 C, ^" m9 G2 X) {8 d        }, t( O- Y. h# `" u) H3 @! g  f5 B
        // MMC5
0 i0 N: k  F6 Y1 `" C        if( exsound_select & 0x08 ) {
. F1 g1 G0 o% A9 m. }                mmc5.SaveState( p );
- d' k8 o  ]' i8 R. a9 u$ Z                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& z. v/ h7 A- _0 ?' q/ L        }
$ U7 W2 D  j* d# Z        // N106
& u' g5 o. s. R) A* x% b        if( exsound_select & 0x10 ) {
6 X+ y, w5 O% ^& {9 o6 J8 f                n106.SaveState( p );6 ~7 U5 ^8 E2 T' Q( S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding! u8 o' l/ i; C/ U# S
        }
) f4 Q4 t# l; A        // FME73 Q! U3 j' h& ?2 t* _3 }: a! h9 |
        if( exsound_select & 0x20 ) {
# H+ C% {% @' u                fme7.SaveState( p );
, o* l9 q; ?; e' B8 h% Y) p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding1 ~8 [, Q* j# K' ^8 k3 u7 b$ P
        }. m; C) L$ Z% @( ]8 v" ]# D
. m2 `9 y, w8 n/ K  t( A
#ifdef        _DEBUG
9 N* e9 L% \  y! ]- kDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 Q; P* O. G3 l2 l#endif
: p- N& o* {. N: x* y}
% X1 j+ y/ B2 [
0 r" z  K) q0 F8 h' y. c- F! Z  l. Nvoid        APU::LoadState( LPBYTE p )+ A' Z* C6 M! N8 A: e+ g+ `
{
* J9 P. x0 Y8 ]- ^# l        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) u( m8 Y( z, W        QueueClear();
; l4 ~  {+ p/ E2 e, d9 F/ R4 v8 X( M0 y. V' G! ~1 I  H, _
        internal.LoadState( p );6 j' u1 F7 p; `! y( W  f
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' _+ @9 G- v- D& @: ?) [$ s. s+ h
) B0 ]+ |3 B6 v4 h. H        // VRC6
9 {- ]7 B+ ]/ A0 `* ^: p        if( exsound_select & 0x01 ) {# q% S+ z' e7 h1 X
                vrc6.LoadState( p );: z! {8 A5 L! ^9 Y' [0 Y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
8 Q, b; Q" ?# H) R' I  [        }5 w0 b0 o$ F+ y$ E
        // VRC7 (not support)
5 W2 G4 a+ r% b/ w        if( exsound_select & 0x02 ) {, i8 e" k8 W# }- ]  {3 k: W
                vrc7.LoadState( p );
" b3 Y0 q# y; P4 F! \' H% Q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  U. `& [: I: e9 q, Z
        }# d' ?$ O8 r- ~* Z0 b
        // FDS2 t  C+ ^% F6 V$ `$ N% x; ~
        if( exsound_select & 0x04 ) {9 A& B& d0 N: K. G
                fds.LoadState( p );/ g, a8 c, @+ X( f
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ {4 m) P" x. A8 E: y        }
9 e$ f' w  U! n; q+ l: M+ q        // MMC5
4 B+ ^( a% G8 V7 {" c" U" l0 i# O! x! t        if( exsound_select & 0x08 ) {: Y; w! @% n/ G5 A
                mmc5.LoadState( p );
- `; ~3 U2 A  |, H* g4 V- q  A& x4 d                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. {  Z7 R8 y; A
        }& k) b7 R* D3 x1 _4 h
        // N1060 P. E( {$ G$ K, a5 {, z4 F
        if( exsound_select & 0x10 ) {7 X/ o, }% a' a( _8 ^
                n106.LoadState( p );
* x9 J% F; v9 e                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 e7 ^2 @; v4 ]* I) k' D4 m        }
" a" p& U* m; ^) C        // FME7
" |2 C3 w8 y" R: b9 c        if( exsound_select & 0x20 ) {
% X" {0 @/ ?( I, b# e                fme7.LoadState( p );0 X. W( o: s: u4 g: J
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# s: A1 i- [! a7 q# d  A        }( l' s3 k2 v8 \
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
- Z- Z1 q) H: ^$ n可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& B# q- l# q2 z$ W$ o( d# g( x感激不尽~~
% T, m8 R$ z; w; i7 W
恩 我對模擬器不是很有研究,
1 K# ]2 H: J) U雖然要了解源碼內容,可能不是很困難,
" `: g" G, K. y2 N不過還是要花時間,個人目前蠻忙碌的。
9 ~3 e% F9 M# C" w4 V+ s# D
! R  y+ R6 `, f9 ]* z給你一個朋友的MSN,你可以跟他討論看看,
+ W8 U1 S7 @3 Q! ?他本身是程式設計師,也對FC模擬器很有興趣。
. w: W) f! d9 y6 S# Q& a6 E
8 I! S6 a$ o3 g; L, tMSN我就PM到你的信箱了。, Y' }+ r' ?1 `  N. ~4 m+ I) ^8 A

& }  V- R; K, V( u希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 4 }6 i; F3 Q) R5 ?
呵…… 谢过团长大人~~

( M' k& G* o: ?) {9 Y6 B1 ~# h
' }  A! A6 s* X1 {哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 $ T7 D; Y. m1 W5 y" b- D0 R
团长的朋友都是神,那团长就是神的boss。

2 X$ S! z! i9 r& j7 `" y* u5 g哈 不敢當,我只是個平凡人,2 `) ~- c' V. p6 _, O" t, ?; e( q7 A9 N
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
7 V# w. e* {7 e" @6 m7 ]8 M3 DZYH
6 R" m. {4 a; T* `% S, r2 CQQ:414734306
# ~( U" J& a; V* eMail:zyh-01@126.com
( X! y! ?9 G: O5 j/ r( B5 {3 g0 a" g+ F+ X1 X" y/ N2 ]2 ?
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 $ M6 B& k( @  l  l0 r
再次对团长大人和悠悠哥的无私帮助表示感谢~~
4 K* u/ b: h6 C& u( n# o# R0 F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-31 20:33 , Processed in 1.088868 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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