EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 T0 e# G0 W+ T  C% r; u3 q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  v8 Z4 s2 E& ]9 I# q这里有相应的模拟器源码,就当送给大侠了~~
0 I% c2 _* m, s1 F6 N1 Phttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : U3 h; W% Z, r- ^' p/ U1 }
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; y7 q" d) u1 X" ^# d3 z* Q楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, j/ o% s. D3 K) w7 G$ L
这里有相应的模拟器源码,就当送给大侠 ...
2 ?% E2 n/ E2 k2 L) T/ _
聲音部分(Audoi Process Unit = APU):
4 T. k4 Q) [( x$ I. ^5 Y.\NES\APU.cpp
7 w& f- y; I5 ].\NES\APU.h0 j" N" K" I# D+ n6 c- C1 B

; Q2 y5 ~" Z4 `& G5 S# G( \, C5 \1 V8 H  ~, W" L
影像處理部份(Picture Processing Unit = PPU):
* V  P2 ?; d) ]) \- B.\NES\PPU.cpp2 |! u; }; t0 F0 ^. T( s
.\NES\PPU.h
2 x# T) ~* a$ k- P6 \5 F2 i3 u; T; h& T3 Q; k+ {) X1 g
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 r1 K: E8 R1 q  f1 r; _1 q$ |(由于很多专用术语和算法机理都不明白,所以看不大懂……)
3 {7 `. ^% p6 d2 E! z$ e//////////////////////////////////////////////////////////////////////////! ~" a8 I" p+ M4 j
//                                                                      //
- O# Z# O; H* @9 T+ K6 u! k//      NES APU core                                                    //8 d7 R1 k3 |$ Y
//                                                           Norix      /// O' ]7 A9 ~6 O1 w% ~
//                                               written     2002/06/27 //7 R& `  P3 Y# ?) P: t/ h
//                                               last modify ----/--/-- //8 N4 v- r/ D0 x; V/ A
//////////////////////////////////////////////////////////////////////////
6 X5 @/ e( }8 r& A* Q1 ?/ v#include "DebugOut.h"
% B+ W. j- e0 o8 Q( ?% J, ?* J#include "App.h". G" M- g. p$ y3 N( ~
#include "Config.h"1 o; s0 a, g& V# ?
' J  V, h% y6 J- m
#include "nes.h"
$ E* }5 g, S$ m7 M  J: e#include "mmu.h"
9 k2 M% N9 M: N! N9 A2 \3 R#include "cpu.h". E; G% S6 f2 j$ z
#include "ppu.h"
! G: U- p( Y. F. a6 @) P# s6 m#include "rom.h"# Y8 y2 k& C! g' C( M" I/ h
#include "apu.h"5 _- W5 |, }# N1 h' r0 e" I& {6 {! R

& e+ I/ @  o! |0 r0 u6 C// Volume adjust; u7 o1 `7 A# s# C6 v
// Internal sounds
- ~) D; t% [) a4 z8 r+ D( r9 }#define        RECTANGLE_VOL        (0x0F0)
) y2 M5 B& B8 V2 }5 `#define        TRIANGLE_VOL        (0x130)
7 b' w9 B4 M" _) a8 F#define        NOISE_VOL        (0x0C0)# f7 E2 A, z# F% _
#define        DPCM_VOL        (0x0F0)
) P1 J9 {& t& ]! {# o% h// Extra sounds
* A+ x) v' Z( [5 R7 S, F% L#define        VRC6_VOL        (0x0F0)
! w- c- S& R& n: x( }2 V#define        VRC7_VOL        (0x130)/ z! ~4 n. N# T( O" ^# Y; U8 b" T
#define        FDS_VOL                (0x0F0)& k3 \3 |0 b7 R$ s1 ~4 l# _# S
#define        MMC5_VOL        (0x0F0)$ \6 _0 ?/ j! D
#define        N106_VOL        (0x088)! Q% U8 n7 _- E+ p* ]2 d
#define        FME7_VOL        (0x130)
; b+ M0 C- s  T6 L' w  |" E2 B/ M! I4 a$ R# L
APU::APU( NES* parent )" ]' }: X0 y! S2 z8 t+ o
{# n- P- C4 I1 ~+ o# o9 `
        exsound_select = 0;
7 C4 w5 ]  ~9 i8 N# H5 M) w
6 U2 L8 q4 J% O0 L, w/ n        nes = parent;
- v7 [+ l0 H/ F3 \0 F/ Z1 {, n4 L        internal.SetParent( parent );: {& f/ J6 Y* G8 ]

% t2 G2 F9 B0 Y" L        last_data = last_diff = 0;
& q2 s  |* l8 h# L
% @! D( g' `' @        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );1 n& W  b" h$ B8 q5 F: `  v

: H7 s7 q8 h6 {0 a9 b! G! ~3 x1 G        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& c; M! V% N0 |6 a        ZEROMEMORY( &queue, sizeof(queue) );( ^+ @7 Z* z0 o! |/ L! p3 M' @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' ~, \4 b8 R' Z) Y% Z) H
" U9 O8 `/ n* @* m! ]# M        for( INT i = 0; i < 16; i++ ) {
% B0 E4 A0 I4 B; C* L                m_bMute = TRUE;
* w" n+ d9 R3 A, a) m' E1 z) u$ Z! e        }0 k, w3 h) m" I( b) G+ ^$ ^
}3 T3 B0 T# G9 s8 A# E* O

$ v; h% \, V4 S3 ^4 [' E; \APU::~APU()0 _; s% ~# E% A" b3 x
{
; }# o4 ]# J' K7 J}3 v* t3 A8 d( r) q' w1 A7 w

. @$ i$ Z* {2 Y% J# S3 Q; `  svoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
3 y6 g) b$ z  j2 S{
3 |) \+ [9 |; g        queue.data[queue.wrptr].time = writetime;
' W* e# j" C. j! R- v- A* `        queue.data[queue.wrptr].addr = addr;* x; y9 L, F) i5 K* V/ c% }
        queue.data[queue.wrptr].data = data;* a3 S7 p* _/ j) x* I/ V3 i" o' L
        queue.wrptr++;* B3 O. f8 r( Z  y/ `7 x
        queue.wrptr&=QUEUE_LENGTH-1;
4 l1 Q6 K% e6 ^# K$ V$ \& N' R        if( queue.wrptr == queue.rdptr ) {
: ~& }; n! s8 |, p                DEBUGOUT( "queue overflow.\n" );
; f' S9 D9 w* X; k/ H        }- e( C6 a: R/ ?( P/ c- x
}+ e, y8 y& y0 K6 ^5 v' x
% w% y! h* v5 M3 j% t. z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )- V& A' E0 |, Q# X* x
{
% v8 T; O( }$ f# ~7 x        if( queue.wrptr == queue.rdptr ) {
; _! O8 |! q( G. v& }1 e) m                return        FALSE;2 n6 t* j( J1 e+ C* _4 ?1 H
        }
+ j/ o  {' Z3 q! D        if( queue.data[queue.rdptr].time <= writetime ) {
4 Y3 D' O  V% p. V4 |                ret = queue.data[queue.rdptr];
: x, ]: u7 @! ^! L% Z                queue.rdptr++;5 i6 H! U/ I$ Q1 E! q
                queue.rdptr&=QUEUE_LENGTH-1;
, F, i$ S2 o+ I                return        TRUE;* y$ M+ o" D/ d. |: |  M
        }
1 {: S- d8 x; f$ ?- E- M! _        return        FALSE;
: Q: X& @5 t. @2 k}
. w8 H- y) E' H2 E7 t& `4 ^2 T1 i
  p0 d: D' W8 w* V  L! {, R2 dvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
8 E0 a! A2 E. Y: V{
$ N7 `+ Q2 B0 {% b7 d$ R3 T        exqueue.data[exqueue.wrptr].time = writetime;2 N/ {! x$ a# a" w- u
        exqueue.data[exqueue.wrptr].addr = addr;
+ Q) z6 i7 ?( u# h" Z" o        exqueue.data[exqueue.wrptr].data = data;/ O  M( O( L. D( k. [& W. ^
        exqueue.wrptr++;
6 S) x; B) t7 ^) C. u! t9 d        exqueue.wrptr&=QUEUE_LENGTH-1;
2 Q- z' M- p* H) w        if( exqueue.wrptr == exqueue.rdptr ) {8 ?  `; M& e6 N$ d7 d( }
                DEBUGOUT( "exqueue overflow.\n" );2 t+ o! M1 Y. v4 L  R
        }* i, e; {, q( q$ m  |; t: D; ]
}4 h1 ^1 d4 Z& G8 Q6 E

$ V0 O9 E& C, tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )+ ^7 I1 A1 ^5 s+ G# p+ X
{
6 O- W8 S" k2 _0 {. Z: _& i$ b0 F        if( exqueue.wrptr == exqueue.rdptr ) {, {/ Y3 p1 P' G
                return        FALSE;
$ _3 Z5 ?, k( `; r0 t        }
* ]3 ?6 ?$ |$ ?        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- S# l& y: a( |; w0 W- m7 `
                ret = exqueue.data[exqueue.rdptr];
: o6 P" r. X, L' t& K                exqueue.rdptr++;! l8 o+ L% a3 x* k
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 {4 e' Z& I: u( `: K4 @1 x% d5 l                return        TRUE;
( f5 k' E# i5 o7 ?+ o- Q0 C        }1 q: g: ~* u1 o6 P, M  W
        return        FALSE;
& O8 j& {# q: v' J* o}
2 {5 `! V' N$ v; L# t+ @0 w. j/ ?' `- R4 v/ s" F" i# w; N9 z
void        APU::QueueClear()* x* c0 \* n1 T4 V& m- f
{
/ R  k' U7 m; d8 r# _( B        ZEROMEMORY( &queue, sizeof(queue) );! Z* I' N' E, \: }" W" K0 Z! c
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. Z/ i( Y$ a+ c}
3 i6 F! I% S3 i, z2 b9 \, f7 m  y7 j1 z( D
void        APU::QueueFlush()
! q/ O' K$ v8 U; y7 @$ J7 w" f+ q{
+ u3 h5 n: u! r+ K% a" s) F5 Y        while( queue.wrptr != queue.rdptr ) {
7 `  G* n7 L, {( n" F                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
5 V0 e6 S/ R& R, B# l  k7 s                queue.rdptr++;: i# K5 u5 a! h; e: [
                queue.rdptr&=QUEUE_LENGTH-1;
: W  n" C# K% ]# z4 `8 t        }9 b8 z3 l+ q2 _1 K, [6 V! b
% a' d+ I4 `1 g. a  j( I
        while( exqueue.wrptr != exqueue.rdptr ) {
4 d/ c; A# ?! H0 {' _! Q3 n                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
0 I' s4 S4 c- G9 Q- t7 ^7 l                exqueue.rdptr++;: P* e, F9 b" ~* Y) b
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 o3 u( a+ q; ^4 D) I        }6 ^( u9 u4 u- A! M, o/ G  c
}9 N& e$ Z4 W1 T' w0 Y
& g6 H, H" O& a7 U: p! P
void        APU::SoundSetup()
* E" w. V: y4 z  y7 s( c{
9 X3 z0 W0 F$ i( N3 O4 j        FLOAT        fClock = nes->nescfg->CpuClock;
- j) [" |1 Y7 J        INT        nRate = (INT)Config.sound.nRate;
. o, T: |; l# w9 ], Q        internal.Setup( fClock, nRate );
: }; _' l4 O: x1 H* T        vrc6.Setup( fClock, nRate );" E: [+ E, o, W" l/ E
        vrc7.Setup( fClock, nRate );; ~0 t* H. `  W) m- T+ `- W
        mmc5.Setup( fClock, nRate );
. ~! Z( N0 X" {% F; K" Q        fds.Setup ( fClock, nRate );! u, d0 h/ ^) X, \5 K
        n106.Setup( fClock, nRate );
* }0 O) ~. N% B/ b        fme7.Setup( fClock, nRate );  h8 y; P# f0 |6 W+ f6 h" Z
}
( r8 Y, s* U- x/ ]9 E) E4 I# ^( z! }3 U; ]5 ^
void        APU::Reset()
3 L2 p$ l1 d% C; }# T  J{
: W& R+ `) a; {' [0 g        ZEROMEMORY( &queue, sizeof(queue) );2 }4 M7 q5 |  C
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ J9 U0 P" J2 z& A* Z$ G2 [, e: J. Q( i" h$ U
        elapsed_time = 0;; \6 ^9 W$ c& h8 T) W

1 ~& n9 |; j* y/ c+ M9 p: B        FLOAT        fClock = nes->nescfg->CpuClock;
8 w) G6 X. O% `6 K9 D4 ^+ O        INT        nRate = (INT)Config.sound.nRate;+ f9 R: u+ d8 F3 V- {2 t$ E# p+ f
        internal.Reset( fClock, nRate );# ^4 t# `' R9 T3 X& F
        vrc6.Reset( fClock, nRate );
" o* s8 D: c9 C/ y        vrc7.Reset( fClock, nRate );; @8 H, Q( [8 O  }: B/ ~1 ?/ }! I$ Z: y3 T
        mmc5.Reset( fClock, nRate );/ K  i1 g# c1 _* O0 v& \
        fds.Reset ( fClock, nRate );+ v4 P5 R, s9 _2 `. Q( N; K
        n106.Reset( fClock, nRate );
: ~$ [. L* I6 X. y        fme7.Reset( fClock, nRate );
, Z! I1 ?$ z% j; U: l: N1 W
6 Y! W6 T5 a; U4 Q9 W' Z        SoundSetup();
6 `2 J0 c7 R, L1 K}7 L8 c( d5 r4 E

+ p3 c( g* ^. b4 n, x0 ]1 R; \void        APU::SelectExSound( BYTE data )
* W( x( m. s) B" D  F, Y3 N& [3 M( o{  \) ?2 s3 o0 @5 W8 B2 Y
        exsound_select = data;* l# I, f+ I/ q; t* }2 h) A
}: V% A% r% p% S( S! G) g" s
" w+ l% p; g/ L9 n% M- g6 L  h  ~
BYTE        APU::Read( WORD addr )
" Y0 ?1 l$ F7 r, ^( S+ C3 [. v{% V  T: C) d, ]) s
        return        internal.SyncRead( addr );
& ^3 ^% d/ w9 ^5 j}
' I. [1 Q/ @; l4 M' @0 m3 `3 }" D0 [: S! v+ k5 u3 e' d) g5 R
void        APU::Write( WORD addr, BYTE data )
2 ~* c/ W  A( t, }/ n{6 i& q1 h6 w( k! M$ _5 @+ V1 `# f
        // $4018偼VirtuaNES屌桳億乕僩
( |& [3 x- ], O( q+ J2 r        if( addr >= 0x4000 && addr <= 0x401F ) {. o: Q, U- k5 y
                internal.SyncWrite( addr, data );
& Q5 S: K7 D+ A6 T8 y( \                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; Y- w: ~9 K5 @$ T* t9 M
        }( c5 e9 k. S) E. G
}
$ Y" D8 z6 L7 E
+ J' [! S6 R6 K/ z+ }% U- {' R$ rBYTE        APU::ExRead( WORD addr )1 S4 u* T0 \& P+ H! E6 L) Y
{. v$ Y, |2 `" X
BYTE        data = 0;
1 G6 \0 V& [0 t) ?, L
) r' V$ g$ c4 k* ^5 Y, ]! Y        if( exsound_select & 0x10 ) {
& b6 P; d& G, w% n$ m/ `4 l                if( addr == 0x4800 ) {0 D# P0 n6 J7 V9 X. d  ^
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
- ~2 z1 `6 @: A( g; r2 T                }+ y/ M- \% @4 ~# H5 S
        }
+ Z, n/ I0 g7 x        if( exsound_select & 0x04 ) {
  c: {2 I0 i: E/ y' M+ o7 [8 r                if( addr >= 0x4040 && addr < 0x4100 ) {
, b' N% s, ]- P/ g+ m                        data = fds.SyncRead( addr );
7 v  {/ _" H# {( e                }
) x# t' x: N% ]3 N0 r& a        }
3 {0 i2 j+ {0 J3 ?* n        if( exsound_select & 0x08 ) {' e, t/ u  J6 C, T, n! q9 Q
                if( addr >= 0x5000 && addr <= 0x5015 ) {7 c% K" K. X) o  }
                        data = mmc5.SyncRead( addr );2 O4 d3 A% q- e0 G# \6 L9 N
                }( @' y: x, a0 D
        }
0 \/ E3 u! C, H" |
0 w4 B7 L& v: K+ w* `        return        data;0 x6 B: r, W# {( v: T. o
}  S1 l' _6 _" N% W7 C
% m$ _( ?! H4 @! I7 g6 Z! O
void        APU::ExWrite( WORD addr, BYTE data )
* U! ~3 Z( R' l1 m( k8 u{, D; Y: D4 g/ S% y4 F
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; d3 K+ j! F9 I+ m" J. o: h  V$ n6 M/ `. L5 Q
        if( exsound_select & 0x04 ) {
/ ^) o1 Z( f- x8 _/ H                if( addr >= 0x4040 && addr < 0x4100 ) {
" Z$ P. R. \  b5 B/ P                        fds.SyncWrite( addr, data );% F. g1 P: \+ T2 f2 t
                }& Z0 q' ?/ r1 X. O1 J) r; }
        }
  ?$ h. b3 P* {0 B$ l- d( g9 e2 r& u$ c! M# I
        if( exsound_select & 0x08 ) {3 t+ [6 K3 h+ T$ }3 j
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' _* {( q8 q9 R  D                        mmc5.SyncWrite( addr, data );# O3 \: i* Y/ I) @
                }
, l9 v9 f! O4 l+ O        }
8 Q$ D0 |8 y: ]! ~: S  o4 ~$ X}) h% v- A( A! c5 `+ X5 v( y/ Y6 a
0 h. b' _. {" j; ~! H
void        APU::Sync()
6 t% T0 ?" m0 A& H{
  H+ x7 W* [( Q' m- @}8 S! d2 F; t& W# O

3 t% B: ^  {7 @- U- j9 rvoid        APU::SyncDPCM( INT cycles )+ {  `" ~  h  I; M# a" D7 A% C; y
{
, y, N7 z- N& d3 n        internal.Sync( cycles );2 Q4 S1 ?3 r, F5 {2 h& g( b0 P+ {

2 ^+ j' Q8 R: c& \        if( exsound_select & 0x04 ) {, {/ r: m( ^" U- N8 d
                fds.Sync( cycles );
+ J$ N& q1 \: f1 ~. Q8 T  ]        }
$ @, o( p9 ~, q& u. u, N0 y        if( exsound_select & 0x08 ) {
# G: t- S: k6 U& o2 `- o& j0 {* n                mmc5.Sync( cycles );0 Y5 h5 j; k" ]
        }
' i$ |( x% p6 I% ]/ z+ m9 \}
+ w/ c9 A' E( K' s
; Q& g# D, G, G! Qvoid        APU::WriteProcess( WORD addr, BYTE data )
0 b0 `7 m/ T/ s6 z& F/ A" X) _{
+ g" @% Q. l$ j* |$ _( p" r9 o% l        // $4018偼VirtuaNES屌桳億乕僩- r" z7 `0 Z0 t0 a
        if( addr >= 0x4000 && addr <= 0x401F ) {( N0 ^9 I; g* g3 r0 v  o
                internal.Write( addr, data );
* f' u" A0 K, c        }
% |, _% r$ w) s' u}
2 D) r: u) M" ?9 ^- y/ l) t  z9 L" S8 ^
void        APU::WriteExProcess( WORD addr, BYTE data )
" t! U0 W& Z* C1 U: {/ h{
  w. d, V) T3 U7 ^( M6 D5 B3 v        if( exsound_select & 0x01 ) {' z0 W; D/ f; o* z' T
                vrc6.Write( addr, data );
, u: g' E( x& J; J: `* j        }. ^: M0 \+ {- f; Z, e
        if( exsound_select & 0x02 ) {1 ]& z2 h' i& ^6 }
                vrc7.Write( addr, data );. |  s# d( j. X9 t) Q
        }
8 I* C' c0 o9 k. n; A6 V6 j        if( exsound_select & 0x04 ) {; F: g( t& s# ?2 N2 r' D
                fds.Write( addr, data );# M2 Q1 X3 V. O0 A+ }/ T2 S7 V
        }
5 ~! t/ @/ V: p7 v7 {- Y        if( exsound_select & 0x08 ) {
. l& d' C. [( d) E  U  ~& d  j2 [                mmc5.Write( addr, data );
& t8 ]! N5 S9 ]( j6 i) \1 Z# y5 _        }) n' T3 A0 ?9 z0 E
        if( exsound_select & 0x10 ) {3 \1 A7 l2 j9 S; J- ?0 _
                if( addr == 0x0000 ) {' v# N6 U& I8 @# R' t3 ~
                        BYTE        dummy = n106.Read( addr );' E' L7 f4 m1 {
                } else {
: H' a, L" Y5 _- w7 |                        n106.Write( addr, data );
# ]  N) o9 K! b$ v: F+ F, X" [2 t                }4 i5 Y4 u. n- o6 \" \
        }
5 I  g  `* Q$ s2 r' t        if( exsound_select & 0x20 ) {
6 C$ v( V; a0 d- w# \" m% ~4 N: X, B- \: I                fme7.Write( addr, data );+ g( H3 T- A% Y' B$ t
        }$ o( d/ `9 y+ K  Q5 y  A: Q2 W
}
' A$ E5 L$ q7 H9 G- e9 d; S6 z# j9 m8 S0 I7 g
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
& @' M1 ^( x% C6 ?1 q: O- m{
! L( O5 @2 g* O+ n2 R. oINT        nBits = Config.sound.nBits;5 Y% l0 D0 ^; Q* u
DWORD        dwLength = dwSize / (nBits/8);
+ }$ c/ o  c, pINT        output;2 b3 i* q2 E& s# w9 S% H) K
QUEUEDATA q;
5 ~3 Q  P* \5 b6 S- g8 Y' eDWORD        writetime;+ R8 P( M" M% w9 U% b

& J1 Q; h- A) I- @LPSHORT        pSoundBuf = m_SoundBuffer;* Z1 @; ^, n2 l, K6 |
INT        nCcount = 0;
6 }3 U. |2 X5 B/ J/ s, W; Z0 ?4 ?& x  u
INT        nFilterType = Config.sound.nFilterType;: V7 F8 j, p" E4 S/ X( u! D

$ a3 S' w' R- }3 ]: t! Y8 Q        if( !Config.sound.bEnable ) {
! z8 |* ^8 {9 k- Y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );  D4 R! ~/ @1 ?# H2 u7 n
                return;$ ?5 o, i" a% r2 g1 F
        }
  O0 ?  I2 y6 d3 d& t" b7 R  S/ _, @9 N- q  H; q
        // Volume setup
# G9 Z) g! f; y. b        //  0:Master! H1 w4 v' v, F4 W7 y' E. F6 e
        //  1:Rectangle 1
7 J7 `. Y$ U& @! y        //  2:Rectangle 2
' e5 L$ x5 X* V# q+ X8 F        //  3:Triangle
' |, p8 y% k* T$ @: o        //  4:Noise
  D: V& v& Q0 ~( l$ k        //  5:DPCM
5 k+ e' o/ h; {4 {# T# u8 Y        //  6:VRC6
4 g( p$ T4 z8 I! [8 p& S+ N: B% O* p        //  7:VRC72 R" I* M8 S* f0 q( x! y/ ~3 c$ S' K% ~
        //  8:FDS% |- J/ l8 N5 }; G
        //  9:MMC5$ K: I- G3 [. {; J
        // 10:N106
! M4 p4 K' {& |/ y2 h        // 11:FME7. Z* y6 W( Y! r4 x
        INT        vol[24];
* t/ ?6 \% t% C. f# y+ e5 y: k  H        BOOL*        bMute = m_bMute;
& g7 Y2 X; X) _  C% @- B' l        SHORT*        nVolume = Config.sound.nVolume;7 _% s, @7 o" V3 c
0 C3 a) c/ O, P  t, y6 C; e# @
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
1 K# a3 k/ [$ v- A! g( n/ L  o( {, }" z: s" ^5 b" E4 T
        // Internal/ p. ^8 k* |% @/ g# l! X
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
' |8 ^  j, c) R        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 W$ Z1 F) _9 J+ o* d
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;" |" O: B2 @7 r: E: {
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
% ~# N8 m7 H' |6 n9 y0 n9 A        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
7 w, g+ F) Z" C1 }" p/ p, U  B1 [7 |
$ m1 [1 U4 F* Y1 i6 @: i2 |8 t  F( T        // VRC6
/ ]* Q, q& k. x( O) X" ?. x2 h        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: R7 h8 X7 Z/ F9 _; H1 m
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 ?6 ~" u* }& u9 N$ m6 Q& A
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 F5 C! v5 K+ c8 `8 \9 ~1 T
$ S! k; ~$ k, w6 o        // VRC7! A" T% d( `2 h4 @5 p$ ?' A
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
' F9 @( `$ s: r/ R7 N1 y* N7 A: q& K2 U$ I: o1 W3 @7 ^& X
        // FDS
7 f) N; u+ v8 i3 k        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 k! {. T2 O% b- r
7 A, c: R% O, ]% C        // MMC5
8 G2 ~: S$ z2 h% }* d: @( \        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; Q" D" K8 f2 f# W. i9 ~
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ o+ B. f: U, ?5 z; [2 D        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 [& r, W- }* h6 g1 e/ L1 E7 q
" T; x9 [2 v, ?% |, u$ U, B* [0 A
        // N106
5 f+ c5 F; N+ R        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ @  y. \* D7 x- {' R) z3 o* Z
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 j! K1 J. ^% \+ z2 s& V9 V2 U
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 N% b/ k! B, ^, l! [3 Z1 }        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; I" e) g; [1 f  _, c        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* T+ b: m# R1 S8 q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 {0 s& }0 g" e4 w  n$ u% r
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 M+ i* |9 v& k& ]& o% t; U        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; @- T0 {$ k2 B  @& F3 s
) m9 Z0 G& G4 n: R" Y7 b& w        // FME7
) q# j$ O# x; R* i" Z5 K& U+ j/ q+ i        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! p9 t4 W5 s1 A1 V. M' I: r2 S        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 S* N/ [& Y/ @+ ~; L+ `4 }! T- _9 L        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 A+ o0 a+ z: P3 p- u  j* l* I+ W" T3 J1 H' X6 H) N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
4 o# X! D" d4 C3 `6 k4 X1 {        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
2 y& B9 A( l* x  m
6 \$ s( u, S. t1 C+ [1 y        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% W" M  A8 L3 @+ z5 t- ~9 ]& i        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' n. i3 H0 x% c0 ~8 }+ N4 @
                QueueFlush();
" J' p% W8 |$ N) Y8 J) a        }
3 H  {" r) v' n' T9 k% a& D
; n$ ?6 ~% k( @$ Z; g        while( dwLength-- ) {% `" ^; Q& C. W' \# h: k' X
                writetime = (DWORD)elapsed_time;' C5 D4 i* ~3 c% O9 l! X' W

/ a3 O# k- g& b! ?                while( GetQueue( writetime, q ) ) {
. [) u9 i7 \4 n$ d4 ~( }$ Y                        WriteProcess( q.addr, q.data );
0 m9 B  P  B0 C7 I) F                }
" g/ ?: `# j1 y: N& _. y  e+ A) {" N0 n7 t& A9 l6 C- A7 @
                while( GetExQueue( writetime, q ) ) {
9 B* C' W* P7 d) k# x                        WriteExProcess( q.addr, q.data );
7 l8 @) H7 f6 |! J* W: N7 ]7 p                }
0 [( W. I4 P5 }! _5 }% B
) y# Y+ |* O, W                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7% i% d3 T* H& o# V/ f) m0 ^
                output = 0;3 R& J& I+ M7 n" ?  h
                output += internal.Process( 0 )*vol[0];% J6 ?$ v% L" r- ]# u/ |5 q
                output += internal.Process( 1 )*vol[1];
7 x$ V  [: ?9 X! l                output += internal.Process( 2 )*vol[2];
+ K* `6 l; p  a1 o7 G4 _' O                output += internal.Process( 3 )*vol[3];
! y- y9 V% U% Z& x  P% A                output += internal.Process( 4 )*vol[4];
% q7 f9 H0 T* s, X) Q+ x% n+ l9 R7 K( T5 k, k4 T( B5 q
                if( exsound_select & 0x01 ) {
# K  W, q% S* c% O" F, M                        output += vrc6.Process( 0 )*vol[5];
# L2 _1 I6 u. B) k                        output += vrc6.Process( 1 )*vol[6];
! {" b# r8 p# E7 t  |                        output += vrc6.Process( 2 )*vol[7];
4 j' k* ~; l7 w* C/ c' T- o9 T                }
* |" _8 b) d/ [, P; w& v                if( exsound_select & 0x02 ) {! `, B% u% Q5 a3 x  h: |8 u
                        output += vrc7.Process( 0 )*vol[8];
- v3 H& a' g1 X  I& j2 u                }, y& p) x0 y8 K# i; T3 R& U
                if( exsound_select & 0x04 ) {
9 x% T8 K) l+ w3 W5 _                        output += fds.Process( 0 )*vol[9];/ Q' ]# M7 o0 W  h
                }$ m( L" a  y0 q3 H0 |; {
                if( exsound_select & 0x08 ) {3 m& E: j) H! a+ W
                        output += mmc5.Process( 0 )*vol[10];
3 L% P/ T5 H- z! }6 Z! c/ x2 Z                        output += mmc5.Process( 1 )*vol[11];
/ L4 {3 N& l% W- |. H3 G# ^                        output += mmc5.Process( 2 )*vol[12];8 @( {3 d0 b3 F9 c2 r
                }
7 W( }" n0 H3 v! a/ t* K. y8 Q2 d                if( exsound_select & 0x10 ) {( M4 y; ~( x* D: s
                        output += n106.Process( 0 )*vol[13];$ [  V: ]% S1 s* C( C
                        output += n106.Process( 1 )*vol[14];& A- e. r* r! l! F5 |
                        output += n106.Process( 2 )*vol[15];
6 n( M' g- d: q- \+ V                        output += n106.Process( 3 )*vol[16];9 B, _7 ~" r$ t$ }9 g% a% {
                        output += n106.Process( 4 )*vol[17];3 w2 D" \: O8 w3 ^- N$ y7 }% x+ x, A
                        output += n106.Process( 5 )*vol[18];. z2 ?" z* r2 Y! m8 q' |
                        output += n106.Process( 6 )*vol[19];3 p; y5 M! q4 c6 u5 ~
                        output += n106.Process( 7 )*vol[20];" A) {/ |1 \8 Q( t$ c$ ^$ w
                }/ Q2 e" [9 z6 ^6 {( |& p' S
                if( exsound_select & 0x20 ) {
1 n5 I( i$ T4 j6 I% \0 u, Q, V                        fme7.Process( 3 );        // Envelope & Noise
4 @) a- _& }/ N" T) O% {0 d                        output += fme7.Process( 0 )*vol[21];
* {+ H! R9 f3 u- e9 ?% `: V  v0 X                        output += fme7.Process( 1 )*vol[22];
# d% Y" a* o) _+ R0 d8 q% d$ ~                        output += fme7.Process( 2 )*vol[23];6 w4 [; Z1 }+ Z: Y* B& z) Q
                }
+ b: [0 Z# i  [' {: P- {' c6 I) x* x6 D4 o2 Z! r' p& p' x  l
                output >>= 8;8 _9 Y$ d8 Z- b( i, E2 z, s
. R2 }- o7 A9 k8 O8 M. j$ Q( {
                if( nFilterType == 1 ) {
" W5 y6 k3 G  m* C4 I                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
# ]4 s5 e4 N/ I+ w! S# a3 P- d& q                        output = (lowpass_filter[0]+output)/2;
( Y- S3 _; f2 W/ W9 k4 T3 f, N) M                        lowpass_filter[0] = output;& \- A- R( _& k. W1 z! i; f
                } else if( nFilterType == 2 ) {7 K! O4 R( Y6 ?$ _  q" o6 F* D
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)4 p, c. w8 E* e
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
. |, L1 e( J$ v& ^7 J8 Q                        lowpass_filter[1] = lowpass_filter[0];  u. j) G5 z( _
                        lowpass_filter[0] = output;: h# O+ ]- ?9 E) b
                } else if( nFilterType == 3 ) {+ Y1 W- F2 l( h/ w- @
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' i# d" Q1 X% k3 {3 ~5 d- Z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" Q% q* o. }3 e* S0 @# |/ E                        lowpass_filter[2] = lowpass_filter[1];
+ u% c( X' F0 f- H& ~8 U3 ?                        lowpass_filter[1] = lowpass_filter[0];
9 ]8 ?3 m9 ~1 Z  R: D2 G2 J                        lowpass_filter[0] = output;
0 k3 N8 ~7 Y* l                } else if( nFilterType == 4 ) {! ^: c" k4 L& q5 H- y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# t# m, q$ ]6 g. @& ^- ~; Z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;6 b& {7 b: D+ F" ~
                        lowpass_filter[1] = lowpass_filter[0];
, ?" n; G, r% m5 p9 k                        lowpass_filter[0] = output;: c4 N3 h5 v6 V( @
                }
# x; A3 Q8 o9 k" M/ N
( t! d/ {4 F! [' ^9 x+ _9 J3 N1 ^2 V7 R#if        0$ M6 ]3 Q# c% M2 V  C) g  }9 u
                // DC惉暘偺僇僢僩* y; Z7 Z  L) m( d
                {
9 L+ R8 B/ a  q7 F  _* k                static double ave = 0.0, max=0.0, min=0.0;
% @. k! ?. x( l% u; }) K5 Z" d                double delta;6 q' _4 w  l" `; x, r
                delta = (max-min)/32768.0;
& O% B8 K. K% K4 H9 N                max -= delta;: n- b7 s, l! w
                min += delta;
. v- T, u0 c/ r' A4 o                if( output > max ) max = output;# s- |9 c2 h- O4 N- @$ y( D
                if( output < min ) min = output;" X7 C( _  l+ s9 W* R6 O- ~
                ave -= ave/1024.0;
5 v$ h. r8 r* P' R/ O; ]                ave += (max+min)/2048.0;
3 q3 p; S2 P5 B$ Q" J* w6 ^                output -= (INT)ave;( S8 i: E2 u6 C% g( \
                }# S8 v4 D# S8 v$ \$ c
#endif3 P! p( w. Q( u' k% R
#if        1; O4 K0 H2 @4 i4 F0 ]9 X2 G7 }
                // DC惉暘偺僇僢僩(HPF TEST)
+ s; E) k$ q- I                {
' I# b( a/ |( b1 X1 p$ Y//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);, S8 R1 H" C- p  S( \
                static        double        cutofftemp = (2.0*3.141592653579*40.0);9 M+ a$ \/ x8 X* U. }. N9 y
                double        cutoff = cutofftemp/(double)Config.sound.nRate;  A. C. Y$ ^  h! e1 j" z$ a& M( X
                static        double        tmp = 0.0;
# c7 n( w& `8 k' Q# G" x# G                double        in, out;
/ V$ X0 y# f  x) x* c6 s0 }( ~2 E3 C; S
                in = (double)output;
( B0 {9 {" D. {& o0 l/ Z                out = (in - tmp);
) J3 T4 j2 ~! w" R% R5 w7 T0 e                tmp = tmp + cutoff * out;
3 Q) z7 M( j1 d
4 i3 ^$ u* m( |( |7 g  e                output = (INT)out;4 I! P4 ]7 _7 P
                }. q7 n$ I* p8 s) l; g1 E) s1 L9 p
#endif  V, ~- Q8 Z$ {( B7 I$ k
#if        0
" X" f9 |, v" G6 ~                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 f+ @7 Q. V3 ~1 Q) i+ V: s( T                {) z4 ~2 ^  X; z' P. v7 r
                INT        diff = abs(output-last_data);  V# v" e* u, Z' K+ y/ r
                if( diff > 0x4000 ) {! ^  U- f) T) z
                        output /= 4;" J0 ]; s. N1 d0 D0 Q
                } else & \1 ~1 v2 y1 m- c8 f
                if( diff > 0x3000 ) {' P8 y2 E3 C( r
                        output /= 3;7 E  W+ T$ J/ |
                } else% g7 ]* A: U9 J* D
                if( diff > 0x2000 ) {0 }0 M; P. m; f
                        output /= 2;1 L. ?! S: v5 |5 l. W8 V
                }
4 y8 O  ]) K2 t+ K4 ~                last_data = output;
4 r1 U, A1 M9 C0 i" |                }) U2 X$ {& L$ O7 |9 u( q! K
#endif
* Y0 R9 O2 U& J3 C                // Limit
% A- \9 w4 r! Q6 J5 |" F                if( output > 0x7FFF ) {
4 `  ^; s2 c8 d" V" M; s                        output = 0x7FFF;# l0 N( g" @5 u7 G
                } else if( output < -0x8000 ) {
$ k6 k5 m6 \: o2 s# ~8 Y                        output = -0x8000;6 c$ @* M1 k# I- T4 g, P' ]3 I" ?
                }
7 s% w6 _0 W2 J5 I$ u. I
, o) ?3 d/ D6 k. k, h9 f                if( nBits != 8 ) {
' V2 R& ~# M* B; J# W! M                        *(SHORT*)lpBuffer = (SHORT)output;
. d/ Q. Z8 F6 S9 t                        lpBuffer += sizeof(SHORT);* V* C. @8 P5 D' L( s% m) h: |  V. _
                } else {
2 q6 p: N7 F* ^* `3 M                        *lpBuffer++ = (output>>8)^0x80;
" K, _& r" ^. [9 k2 M3 @) I                }
$ q$ A) N0 ^% _* |6 j
( Q2 [' n2 B+ u3 Z: n$ Z( c" y                if( nCcount < 0x0100 )
+ d6 F9 h' b1 P" V4 w7 N                        pSoundBuf[nCcount++] = (SHORT)output;& d1 G) r% J6 K+ L+ R
. J; h. O+ O, p3 j1 c, K- e
//                elapsedtime += cycle_rate;
0 a2 L6 x7 D% l                elapsed_time += cycle_rate;
9 |3 L+ h, b! d8 L/ {        }
/ u& f/ ]# M/ v- V( D  V$ e( t! p" X/ d: W; K1 H6 E9 ]  u7 B+ e6 g3 ^
#if        1+ p0 K$ D5 @1 ^
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
4 Z/ ~. r& q* W, I- `- E1 O                elapsed_time = nes->cpu->GetTotalCycles();6 O" S6 m2 k$ A2 p- S7 {2 Q
        }/ _, a! y) M: w4 T' b6 U
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {! x0 P8 D- \: y+ i
                elapsed_time = nes->cpu->GetTotalCycles();0 g2 G; e8 c% A3 p) [
        }4 K/ z' g. n$ q1 Y2 T
#else
/ n5 N: |8 x" z- `/ w* _        elapsed_time = nes->cpu->GetTotalCycles();
) E7 C) w9 A9 V, z& _) r#endif
+ |& \' E7 t' m1 Z# y* \}) c. b2 Q" g, A# I/ z

. o1 c/ ^4 a" G$ m// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)+ f+ J; ?, k7 `* t9 Z  V' P9 v
INT        APU::GetChannelFrequency( INT no )4 K9 b% u$ W; v0 V! w
{/ e( X/ g8 }1 M6 P. w5 C
        if( !m_bMute[0] )) D8 ?% ^8 c7 g& M; s) [: ^& v
                return        0;
$ |$ e/ {5 }3 t! Z" M  U  t0 f' E% V% m
& _7 i+ d+ d* M& y        // Internal
% y! _2 r5 l4 V5 i6 `        if( no < 5 ) {
: h: @0 p* T& U/ N                return        m_bMute[no+1]?internal.GetFreq( no ):0;) y. L3 W! S9 i7 q3 N/ I& @+ ~0 ?
        }# Z& r$ l0 i% v+ S) O
        // VRC6
5 e# I# ^  [! A% {4 h! Z2 \4 N        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {9 w  S- F$ v$ W: I
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;+ a$ C4 \; e8 n
        }. _0 q9 _: p! G# T& V4 l+ N
        // FDS
' D2 R! V" S5 ?2 ]: u8 T% ?        if( (exsound_select & 0x04) && no == 0x300 ) {
1 L9 f  L. w- A6 U5 n                return        m_bMute[6]?fds.GetFreq( 0 ):0;# n: N# E$ V3 y% c
        }
" q2 E) a8 K1 t+ c$ ~! q5 c        // MMC57 q" ~4 L6 m, c$ Y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {; @) x& i3 [( N5 R; ~
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;, E6 y4 b6 c' [& z
        }8 ~; e1 a5 a2 K% \% s* y
        // N106
8 R* a, v- Z& E) O        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {; ~( r; \) F1 Y. ?+ X: ~* ^
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;7 ~$ a3 |) U2 u4 f) [
        }
* G2 `$ \0 B) _9 [8 s        // FME7
! ?" S; e" B2 F5 L% d        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {. S/ Y9 D5 y8 h5 E+ f
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;( ]' c8 W: t3 }, [) X! t, N* a
        }# e3 n6 L$ d  _2 l+ R: X# B6 Z& ~
        // VRC7
/ X8 m2 G# b1 H, p- V* z5 Z        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
- Q7 G8 F& v* L% K                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
1 D- z/ J3 K( V4 v- D9 a        }+ a* k( f0 H# q9 ~( r. n6 h, k/ x( Q
        return        0;
% w" O5 ~3 \* }1 J' R# W" Y: o}
4 ]2 t) M; N0 J: D( n
* Q: Y- @' \" M: A8 u( [3 l" H3 l// State Save/Load- J  |6 E0 V% t- ~+ {4 l
void        APU::SaveState( LPBYTE p )
' f# f9 q) l* O+ ~{
, ?$ {# z$ c* p#ifdef        _DEBUG5 m* I1 p/ }+ P6 j: ~
LPBYTE        pold = p;
  t# j1 a$ H$ u. ^0 }/ c( v' z#endif
5 L6 G- P6 P- R8 A  p4 h# A; ?, t( c( D( E5 @6 Q( S/ Q. `
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞4 b! c  C  ^5 N, S; G# B
        QueueFlush();
4 I+ T. G9 z& \( H
8 H/ `5 t) ?: A2 z" R8 y+ D        internal.SaveState( p );
$ Q$ @/ Z4 t1 V2 l& P        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; V9 v0 F3 w: I0 Q. D2 G6 \; V# }
2 q- {* N4 h* |3 L" m
        // VRC6; G  z, y, B* `: f
        if( exsound_select & 0x01 ) {
, K' G% I+ t: }. ~0 X4 {                vrc6.SaveState( p );* [$ G* b- k7 g6 I0 o, s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( f( t# M, h3 z; i% v        }! M! h' R5 v9 n
        // VRC7 (not support)
" I9 K' N- {1 b$ i0 |: E) B/ K        if( exsound_select & 0x02 ) {
3 G' ?/ ?6 Q7 j$ ~6 s                vrc7.SaveState( p );6 _2 e3 G+ j/ ^, w7 e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ U+ M  }# ~( ?2 a3 j. {, `        }
' t- e" Q3 y7 d# o4 L! \        // FDS% d3 E& ]$ g' {9 [0 a/ K
        if( exsound_select & 0x04 ) {
) L8 a, D1 R! G) s9 y- A, m                fds.SaveState( p );
5 j& ?: h4 X. b/ m& _' j                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 W* s3 z# D4 u/ A/ d
        }
2 G+ T2 o' b+ T' y        // MMC5
, v0 N& m. {+ W+ L; `) @$ d        if( exsound_select & 0x08 ) {
3 f1 N1 M" `7 [6 c                mmc5.SaveState( p );" W) ?3 o4 l, a% F: `3 f6 c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 L9 T1 g- p7 A7 a
        }6 }6 {0 M9 k- R# W) r( D9 Q
        // N1069 l; B; r9 a" d6 _1 m
        if( exsound_select & 0x10 ) {
( J$ o+ p( L- y6 L                n106.SaveState( p );
/ B  B2 v2 p4 q                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% e; W. ~: i" Y6 E        }
/ ^1 h  d9 i5 P2 P        // FME7% _# t  m: \! E
        if( exsound_select & 0x20 ) {3 k) J5 l) }( i( `: F$ b
                fme7.SaveState( p );& S* r$ D2 I5 q% ~& E9 z2 b/ E
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 }+ K. e7 ?; p  n        }
, ?8 I  ^/ H( H0 v! D7 a, U' _+ M+ d7 K; ?$ P" ^
#ifdef        _DEBUG
( u4 X9 a2 o7 D" Y4 b6 I! DDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );& }0 N. R! I  F' w- M
#endif
% E2 A% W- t9 X7 o% y}
) M/ H. R- v8 p+ X- L! U8 d' q/ \6 A* L" E5 W1 Z6 G/ h. t! `3 }
void        APU::LoadState( LPBYTE p )
% q: x0 O1 k7 X, d* L$ Q{
/ ~6 B6 v  o  U4 d& U        // 帪娫幉傪摨婜偝偣傞堊偵徚偡" V. F$ C: O3 |) f$ \. [
        QueueClear();
# O( y7 [" y" s6 v8 X6 ~, u7 v9 K! H$ K9 P  d
        internal.LoadState( p );
: L5 X2 Y) B0 \7 u% E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding0 ~" Y' A! z' Q
& Y0 v- G: w2 H/ h2 X+ j: |
        // VRC62 s7 D3 x: U# |
        if( exsound_select & 0x01 ) {7 c) Q5 I7 N/ I# q; c# u0 _  h
                vrc6.LoadState( p );. W' S$ _* z% d3 i' A
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; A, r; m5 \: P! F
        }
( v9 N" w  N) [3 R7 x        // VRC7 (not support)
: v) c* w4 Z% G9 o8 U9 o" T        if( exsound_select & 0x02 ) {$ Q/ ^) e" V/ U0 O
                vrc7.LoadState( p );
+ W, }' M) ^' s* b+ m) ~. @; A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% E% T+ b; M/ m3 a6 ?# g
        }
9 n' S1 R- x" n! N+ z; c8 |; o        // FDS; i0 c* k! q9 e7 P# j" @! B6 e
        if( exsound_select & 0x04 ) {
$ P( B3 ?8 }8 d3 b9 s- [                fds.LoadState( p );
; i8 E0 E# e7 A& Y4 L! h                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 L$ |8 q; D( M
        }
7 ]- ~7 U5 g' ?& ?        // MMC5
* Y) F. e  s8 [* P% q! ^        if( exsound_select & 0x08 ) {3 H4 x3 V; S+ c8 Q
                mmc5.LoadState( p );3 {6 m# b: K% }2 m
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 v2 v( ~' b6 C& g8 }+ {        }& Z1 _( ]* D  U. m5 b
        // N106
0 }1 [* c( O& M( L0 Y2 _        if( exsound_select & 0x10 ) {
  F7 }, e. d, ]                n106.LoadState( p );
( h3 B9 W: m0 H9 p                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 S' w+ ~0 S; F        }1 M; `. P6 S/ C% p0 c/ I% c2 S
        // FME7) \" q7 e3 {, f9 N
        if( exsound_select & 0x20 ) {9 Z3 C6 v8 [7 m) x" o8 K3 H' Y9 K
                fme7.LoadState( p );
3 s- O( Z' G7 z& P" g6 {2 W                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' g7 o1 z$ e4 u5 D8 S, w        }
) y3 P/ T' p+ v+ @5 ~}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
6 q* Q2 s7 Y  x+ K# Z8 b' n可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. k! o. r( Q# @" P6 i; S感激不尽~~

9 T) {9 R' G0 D恩 我對模擬器不是很有研究,
' T4 X3 J" o3 ~雖然要了解源碼內容,可能不是很困難,
" b9 x  n, e( i! q  O2 w/ W' T) j: h不過還是要花時間,個人目前蠻忙碌的。
+ E0 F$ x) w, g; ^/ y: @. d2 e, O3 k$ y0 m/ p
給你一個朋友的MSN,你可以跟他討論看看,# q0 k  q- H3 H- t1 \1 M
他本身是程式設計師,也對FC模擬器很有興趣。
  B! y" q2 t! T/ u! x
3 n, L8 A9 ^" b( J* ~+ AMSN我就PM到你的信箱了。
1 w& S3 Q& ]8 F, I% R% J5 t3 \( |8 e8 g
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 5 u  o$ _$ y0 O* Y$ x
呵…… 谢过团长大人~~
9 H, B+ r. t! Y& g& `
5 j, y: S/ U- J9 ?& V8 ^9 R
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 m7 |6 Q: h# N  I; ^团长的朋友都是神,那团长就是神的boss。

" P" w# k& j0 [9 z% }2 G2 {哈 不敢當,我只是個平凡人,
8 Y/ c: I/ R9 k% `要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" ?* @: E- ?: K4 F: z  c4 X1 M7 xZYH# R1 M- K3 u# g; i# ^
QQ:414734306
( f4 x! O) W" g# L3 K- fMail:zyh-01@126.com
  l4 T7 F7 z* R9 e4 N2 ?) ^; }% U. g" K
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
0 {* O: B: e; [& c: T# c再次对团长大人和悠悠哥的无私帮助表示感谢~~

' [6 g/ ^4 T7 O7 h1 R: c不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 02:38 , Processed in 1.071289 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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