EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: g9 X* `; @$ x
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' V5 k4 S: Z7 G% r) ^这里有相应的模拟器源码,就当送给大侠了~~2 V) \7 c% h9 B3 W
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- ~8 r3 C4 a8 z+ _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 R, o5 H; h( U# K% |! j楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ K+ m( l7 q* w这里有相应的模拟器源码,就当送给大侠 ...
! d+ e" }. h) M, _4 P8 G' _8 [
聲音部分(Audoi Process Unit = APU):
6 i' A! Z) o, R3 I' O.\NES\APU.cpp
$ ]1 i/ Y: |8 q.\NES\APU.h1 U: I3 R$ D- d% b2 e+ B8 y. a3 n8 M
' x0 w: ?* @) H7 ^

2 Z' K6 T; R" h影像處理部份(Picture Processing Unit = PPU):
. K8 V$ `( a0 F.\NES\PPU.cpp" w8 |, u) m" o8 H7 W
.\NES\PPU.h0 {" I& R( r$ q  }6 U2 g$ g

' Y3 l3 `# `% z% _如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:. Y* I% B3 e/ C* Z: C/ R
(由于很多专用术语和算法机理都不明白,所以看不大懂……)( D$ z& T/ a% o. e" C2 y+ y
//////////////////////////////////////////////////////////////////////////
& G' X8 K4 x; m0 F! q" ^//                                                                      //% S; \5 @. z3 o- T- k# H
//      NES APU core                                                    //: d3 V1 E( K, f! s; f# \( }9 \& \
//                                                           Norix      //$ n3 J; c6 V- u6 r% @; ^/ X
//                                               written     2002/06/27 //8 k6 Y2 P5 V9 g* u
//                                               last modify ----/--/-- //
4 I0 D/ F8 g3 N4 Y//////////////////////////////////////////////////////////////////////////, V" I9 Y& ^1 _7 @9 U4 x3 t$ [' d
#include "DebugOut.h"
7 K& S8 u; n0 j$ V9 ?4 ?#include "App.h"
/ b" f7 M4 ~* `; f6 |#include "Config.h"
9 h3 o6 j$ `! F& q
6 S/ ]9 b. z/ o#include "nes.h". ~- @% l2 s% W) w1 D
#include "mmu.h"9 U# ]5 I$ z$ I1 W" O' G( Y
#include "cpu.h"! b& \8 j8 ^- I" e& R. u& y2 N
#include "ppu.h"7 |2 D2 E+ x3 U. |4 e( a9 |
#include "rom.h"
& D/ V+ t% t, b" O2 F; f5 P#include "apu.h"* D# c3 o7 M5 X% T  C% j( w

9 u: \, N9 C# D0 m4 e// Volume adjust4 `+ `; B# e& v7 @( j( V
// Internal sounds
; q0 Z7 V/ ?3 z. [#define        RECTANGLE_VOL        (0x0F0)' T/ q5 Y0 ]- b' L# p- Q1 H
#define        TRIANGLE_VOL        (0x130)  P2 W9 X  M1 G) I/ ^: A' }
#define        NOISE_VOL        (0x0C0)
: s3 \8 F" s: q9 {! i#define        DPCM_VOL        (0x0F0)
# |' E4 C+ \# P% K4 b% J4 ?// Extra sounds
! k( l; @. c& R- _' m1 K#define        VRC6_VOL        (0x0F0)
- ?. @0 j* x( v6 O* x#define        VRC7_VOL        (0x130)
2 z; ^! Q$ q  W1 u#define        FDS_VOL                (0x0F0)
! T# m: u' M; Z. ^0 B( R#define        MMC5_VOL        (0x0F0)
+ ~$ e  P! b1 B( S" o#define        N106_VOL        (0x088)' j$ L% d& i! l7 B
#define        FME7_VOL        (0x130)
- W) P0 u( _) c* Y0 J
, j' d  \1 o: n, t5 @0 \APU::APU( NES* parent )" a+ ?7 x: q- ~) i4 G' a) j
{
3 y3 @0 m- Z0 J; F" \9 w        exsound_select = 0;
6 }7 T; |. r: J5 i0 h% j# H2 V( g6 k) H9 l) g3 c  o
        nes = parent;  J1 N& f7 Q! m) g0 s
        internal.SetParent( parent );
# D  X- ^  S2 y' r" R2 K4 L
% K4 ]3 ]" R8 r+ [% o- n; E        last_data = last_diff = 0;
, k) r, Y+ D  R% Z7 n* \
  K* N, D/ e; w$ _% a/ F        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
  r( Z6 A6 _5 b
' \- [# O1 ]+ t9 q. W4 s: ?        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
* N/ e. q- y) Q) x$ z% _5 I        ZEROMEMORY( &queue, sizeof(queue) );+ q- |9 N; @: ?! }5 E6 ]# H& G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  y' x  U* X  `0 q' }3 J3 h; K3 {0 N  i7 z' p8 S
        for( INT i = 0; i < 16; i++ ) {
+ E8 J7 U9 F) x. b4 c: w; \                m_bMute = TRUE;$ }, O3 B& o! A/ X1 [$ h5 R  ]& h
        }
8 W! A  P5 p8 A4 O* C}
8 m4 Y  {; x+ E, `! V$ G  }. |* _: F# F, ?# \1 y' Y& f
APU::~APU()# Q- {: X0 R8 Q2 Q& j5 }, r
{
; X8 y0 w1 h- @' l) x! I6 y+ R}
$ T) l2 x" D2 ]8 n7 h; Q+ ?  ^/ o0 V9 V# S/ ?
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 g" ?' W& a4 b* d: i
{3 h7 [; S- Q" Q9 w: N/ J7 B6 }. b$ E7 T
        queue.data[queue.wrptr].time = writetime;8 G+ ^0 C7 C$ N; S2 k" u
        queue.data[queue.wrptr].addr = addr;
4 x# S- b1 ~- q: ^, X9 l6 N        queue.data[queue.wrptr].data = data;7 G3 b3 ?7 k; r3 v. ], q1 p% Y
        queue.wrptr++;$ O% e& O3 v4 g* G! C
        queue.wrptr&=QUEUE_LENGTH-1;
" P* ]2 U8 o% K- ~! o+ N8 P        if( queue.wrptr == queue.rdptr ) {* T/ v' h$ v* D1 ?
                DEBUGOUT( "queue overflow.\n" );
* G# d% u" q( p7 e  E9 N        }
3 S2 r! J/ M& D& p: K/ Q}
% B6 ^  P8 V7 q
; e5 b  ]; y' O$ LBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
6 }; \4 r' `2 p{
' P. [" ~) p6 @# {  M        if( queue.wrptr == queue.rdptr ) {
# O8 [) g& H4 k# A* a' Z6 T                return        FALSE;
; Y. T9 c/ z  I7 n        }
8 T4 @, f/ p2 x8 I. Q        if( queue.data[queue.rdptr].time <= writetime ) {
- j: i. j9 C" {                ret = queue.data[queue.rdptr];
5 f- O2 U5 C; K! D                queue.rdptr++;# t9 k- `' v2 O) D
                queue.rdptr&=QUEUE_LENGTH-1;8 W0 V- B/ J- z) ?
                return        TRUE;5 ?0 L: G$ `: E  p' N$ y
        }8 U  Y6 O, o+ O* t% i( S
        return        FALSE;
) \  v4 `9 ^, G# y. F  r$ a}
* t* k4 e' Q/ \5 p; L  x; d' d# Y1 u$ L* P1 n1 d; X0 \; r2 c5 r5 v! _
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
6 l- D" E3 Y' {2 r( S$ s{& I7 W1 @4 S2 s7 K1 R0 g, w) [2 K
        exqueue.data[exqueue.wrptr].time = writetime;
0 Z# A7 @7 n3 @$ X5 ]7 u        exqueue.data[exqueue.wrptr].addr = addr;
0 z( f) H6 R) g/ p. d# j1 D        exqueue.data[exqueue.wrptr].data = data;
. y, I8 j4 a: Z* q7 V" _        exqueue.wrptr++;& s: H0 ~  N, K1 P+ v9 j) W( q. I
        exqueue.wrptr&=QUEUE_LENGTH-1;
# v  b/ U1 ^+ a        if( exqueue.wrptr == exqueue.rdptr ) {$ k/ j$ P( L3 q
                DEBUGOUT( "exqueue overflow.\n" );. }3 O% q  ~0 v/ N3 }- b
        }- R: q& n8 ?/ l& b
}' \7 T+ }4 p3 v4 h  U0 V- G/ |7 j- @
* N" W  ^( g" g9 Y( `5 j7 l! _1 R
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )6 h4 `) k% W! W* Z8 r0 V
{
/ x( P+ F" K; w4 U$ f& _: n$ Z# u( l        if( exqueue.wrptr == exqueue.rdptr ) {2 v- o) ?: a; F' H6 X$ p0 O
                return        FALSE;
) R1 o4 e+ |7 e2 V. Z8 G7 m9 E        }; p4 T/ b' D, A" R
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
2 x! R$ v  j7 w                ret = exqueue.data[exqueue.rdptr];0 F4 g0 o- P( H! }' s$ x1 g
                exqueue.rdptr++;4 D$ ?: y( s2 a7 c9 B9 Q4 E
                exqueue.rdptr&=QUEUE_LENGTH-1;3 z7 l; }3 R2 s. Y, z2 u7 \
                return        TRUE;( H3 Q$ L8 ]3 v9 _) M
        }- d, o" X% |( m9 v
        return        FALSE;
1 a5 ]8 w/ m0 b# e) Y}, |% _/ Q+ x/ y7 R( B9 }

: ~% N: w9 B- [. Kvoid        APU::QueueClear()
$ Y7 s0 _: ]4 ~  i6 H{
; l+ M' x6 l* g$ X( b        ZEROMEMORY( &queue, sizeof(queue) );
0 D. A3 o+ ~& Q7 j6 L& q( @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 z' D6 b1 u1 {% A+ y}
2 H$ e* c% i1 V" ~( m$ b+ S, }/ m% n! x' p2 a8 m
void        APU::QueueFlush()
) I& Q  Q" [* `( W{
% A$ ]( q0 m' K. U- d3 p% b        while( queue.wrptr != queue.rdptr ) {+ {+ S+ Y3 V9 ~: h2 W. I8 O, `, C
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; I3 K3 p5 S5 m7 V  ^* p0 [
                queue.rdptr++;
: R& w8 W- r0 G% g% {7 J! O                queue.rdptr&=QUEUE_LENGTH-1;. F" E4 e( m  ~7 H
        }
7 R' ~( h* E! ~% N
& P# l3 J6 N8 O3 A        while( exqueue.wrptr != exqueue.rdptr ) {, s6 y. C# _! q9 E! A, a4 ]8 R; B
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: e( C' y% z$ W/ r                exqueue.rdptr++;
1 _1 |9 x. {0 g" ]0 I6 \                exqueue.rdptr&=QUEUE_LENGTH-1;
3 i2 L" p/ b) W4 y6 v& K        }
4 z8 S$ g  c* B" h2 z}: h1 A- ~0 K. ^# _$ L5 r
6 }( e' Q6 Z9 V% ~$ s
void        APU::SoundSetup()
( B/ s/ V! I( j$ I{
/ N' M+ V  \5 c8 U4 q" d        FLOAT        fClock = nes->nescfg->CpuClock;
9 C$ [& l8 e) X$ `9 l: q4 e7 ?        INT        nRate = (INT)Config.sound.nRate;
; B% m' v( I: e9 e& S8 X        internal.Setup( fClock, nRate );" v) O) F7 u1 M
        vrc6.Setup( fClock, nRate );1 L* \! d+ L3 w' F9 Y. t3 w5 P
        vrc7.Setup( fClock, nRate );' l" ~$ Y3 C& E( z
        mmc5.Setup( fClock, nRate );
) u8 q4 t/ b& H' }1 X        fds.Setup ( fClock, nRate );
3 m+ w2 e4 c# {, J: Z6 M0 Z2 v        n106.Setup( fClock, nRate );- ^  }0 F) A% B" |& R
        fme7.Setup( fClock, nRate );7 {# p5 K; K8 O) G; C+ x  M; V
}: s0 E$ h) D/ K

/ Y, m( U$ l" D' @void        APU::Reset()/ ]- [2 Z" {9 e8 H3 g3 ]
{
9 [. b+ p, f! q0 i" x" x        ZEROMEMORY( &queue, sizeof(queue) );
2 P& d4 Q* ?: }$ j" m2 A/ v- t: S        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 ~6 V) v" ]+ a3 Q; ~
* E; ?. V. G& i$ x' d+ n9 P
        elapsed_time = 0;
8 j! `2 R0 v) D3 q* {
9 N8 i% x  R3 P& d) ?- S        FLOAT        fClock = nes->nescfg->CpuClock;
- v) b9 x( t& z4 ^4 y$ X+ t        INT        nRate = (INT)Config.sound.nRate;
5 f! `# d0 Q) f- z1 K5 N' v4 c        internal.Reset( fClock, nRate );
. X. w: q8 `! m$ W: k# e) E        vrc6.Reset( fClock, nRate );' e6 m& X; r9 O% F( i
        vrc7.Reset( fClock, nRate );
9 \4 T  U: O4 n! ]# w1 T  M8 D        mmc5.Reset( fClock, nRate );$ N; _$ S% b$ N! v
        fds.Reset ( fClock, nRate );
" m+ a& l  \3 w$ I        n106.Reset( fClock, nRate );  C! P$ o, X6 s) C% u( u
        fme7.Reset( fClock, nRate );/ r3 Z" u& l" V; i. s
% _/ x! C: a! V+ E! n: W
        SoundSetup();% O% w! S( o9 c- |0 ^* X. n
}
8 V: V2 e+ X& X- P  }9 x; w2 L
" s' s: |& R! L7 @* T! r3 b4 Pvoid        APU::SelectExSound( BYTE data )  g, i- I4 i7 J  T
{8 o; X" s& M& |: e
        exsound_select = data;# ~5 U; z7 E  S/ L6 N
}
8 W" G" H" F$ T' h+ J* G; U
$ _0 H: \! H. r8 Q* dBYTE        APU::Read( WORD addr )
6 J( z, W  d+ _+ I% x: j  _{
9 a! q6 `5 a( s# z& _' [+ n  R        return        internal.SyncRead( addr );. T2 F2 j5 u$ n& a3 _! g
}7 k6 U. S, P9 H, n- l2 z" G( }

& ]! i8 Q; S" @9 Svoid        APU::Write( WORD addr, BYTE data )* O3 s* C/ S3 @  M6 s+ h# ~
{
1 o6 T0 f- p1 ?" y        // $4018偼VirtuaNES屌桳億乕僩' U3 u/ }/ |1 C$ a, {
        if( addr >= 0x4000 && addr <= 0x401F ) {
6 [) X- \* ]& E; m( R- n' b- k                internal.SyncWrite( addr, data );
) W' _9 y  o! A  j8 L: L: `+ J                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# ^0 D4 n$ v3 A        }
: }) K" S$ u( J. n; V6 P8 U) i}
( z* P. T* U  O: |0 K2 F# [& [2 Q- u& y. E
BYTE        APU::ExRead( WORD addr )
8 ?/ V+ F0 Z7 X3 Z{
. p7 R. ]# h( e7 _BYTE        data = 0;& V6 l9 c0 M# _) s

9 X! K/ x" f( u, S. C        if( exsound_select & 0x10 ) {
* U  ^' _: \/ \                if( addr == 0x4800 ) {# A* ~- V& w- E/ u" X
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
- O9 E% ^( Y9 L, Y5 T% g                }2 H4 l: R- W6 Q
        }. V0 n6 g4 Q6 @- j" M" q% v
        if( exsound_select & 0x04 ) {
/ m  r- `8 D9 _1 l3 X" n2 c% e                if( addr >= 0x4040 && addr < 0x4100 ) {
" Q6 P( n; z* x* [- K                        data = fds.SyncRead( addr );: Q/ N+ R: q2 q
                }
0 y" j$ {% ^7 ^. C8 W. S        }
+ s+ w$ I! {4 T/ j( T        if( exsound_select & 0x08 ) {8 M: x( P  w3 I! b. Z
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: E/ e6 M( d% X$ L* ~: B0 F2 H                        data = mmc5.SyncRead( addr );+ e( q- a) Y2 w+ j
                }3 q! Q$ n9 H: c9 [5 y
        }% t3 {. F+ [, M) [
, M8 V% A9 Q6 {8 p4 s8 F4 T4 \
        return        data;
8 W+ c* g( x% d* `' k}
3 A2 a/ O; B( C' b* O' k$ s
1 y  |+ k' j( ?void        APU::ExWrite( WORD addr, BYTE data )
% [5 [- P7 e+ c' p# K; C( X1 x, E) o{
5 {0 [" s  N# q' n) U) E" ?8 O        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 u1 H  R/ A$ G4 k& F/ o3 K4 T5 B9 h' y
        if( exsound_select & 0x04 ) {
/ H3 M# V1 L" o3 h                if( addr >= 0x4040 && addr < 0x4100 ) {
. d1 {+ G) B8 A& y9 O$ c  {                        fds.SyncWrite( addr, data );
% c. k( V7 C6 [6 i; R( D+ {                }
: z2 T$ X$ ?+ \, `4 T9 J% t        }) I- |) E$ b) G% v

, V0 F% L; r$ Q( p. k        if( exsound_select & 0x08 ) {$ U$ o+ f0 Z+ X, u6 u0 L. t5 k
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! [7 e  r6 a, m* V' C9 J+ H+ d/ ?3 t                        mmc5.SyncWrite( addr, data );; k+ x. a: e) V  A3 ^% V0 x
                }+ t5 \' P" W3 L. z
        }
. T; y7 i& e- l% @7 n* A7 |}) p$ {$ k( i+ {) f

* N1 [4 Q6 Z9 w0 X, H1 B( nvoid        APU::Sync()! Z$ c1 \& m. Y- B, ^* n9 Y
{9 P1 L: _% s: \3 Y# z1 P& O/ r+ a
}' |2 P' `; {, a& [: a0 r
  A9 x1 l# l, x1 A% M0 B$ v
void        APU::SyncDPCM( INT cycles )
' u  Q& P( Z* r, U0 y% c0 g) s' @{2 L" u/ l  s( [3 j! L2 U( F  R1 `
        internal.Sync( cycles );
  z/ ~2 ~+ Q- L7 A" X7 \
/ X1 [- d2 e! ~9 L: b, O        if( exsound_select & 0x04 ) {
, ?' b. ?3 T; c9 P/ @2 K6 y  {; {                fds.Sync( cycles );, N: o% y, \7 K4 ]
        }
3 U4 o6 k: _0 ^( j        if( exsound_select & 0x08 ) {
1 v% R1 s  I' O0 h9 {1 W$ Y7 z                mmc5.Sync( cycles );9 ^0 C, u8 i% h1 e( }) N
        }6 T& T) a6 e7 Z
}$ @4 v3 t/ g" k3 w: L

1 g6 T( n( F  x7 s5 d6 I  D3 i2 wvoid        APU::WriteProcess( WORD addr, BYTE data )5 p# Z$ P, [8 e& h( a) P# B
{
& W) E; J9 a' `! |1 b, ~) L        // $4018偼VirtuaNES屌桳億乕僩$ r2 C9 E2 n# `: V* g
        if( addr >= 0x4000 && addr <= 0x401F ) {
9 O) a; V+ B6 _3 c1 l                internal.Write( addr, data );
" C2 J% s* s1 R2 C        }7 F7 b( V6 r# o# l
}3 M) W' i- o9 G( }0 C1 f
( I9 s( c- _9 y  E0 \+ r7 k
void        APU::WriteExProcess( WORD addr, BYTE data )
, \# V5 l! ~: Z  g{% Q3 e( M5 s& X; d
        if( exsound_select & 0x01 ) {
: J# I, ~6 \6 \: Q7 d5 b                vrc6.Write( addr, data );
; T- M6 w5 N" G8 m' v8 D  l0 O        }  L3 n6 [$ \/ T1 j: }: ~! Y; y* V
        if( exsound_select & 0x02 ) {
2 ~8 N# S( e' u: ~5 H. P                vrc7.Write( addr, data );
7 I% s. J2 h* F% g$ Q        }2 P; Z) x6 b4 y% c& Z9 |% J
        if( exsound_select & 0x04 ) {# y0 f8 l4 y) f5 F1 g+ u$ m
                fds.Write( addr, data );
& Q( n7 R& l3 F8 |* ?        }! ?- Y/ m4 ?( U5 d1 D
        if( exsound_select & 0x08 ) {/ M- v' ~  |- G) |, H" ^& k7 E
                mmc5.Write( addr, data );
! ^) K8 m8 G6 b) ]* p3 l( ?; E        }1 h- Y  w$ I/ `/ |, X
        if( exsound_select & 0x10 ) {
% c9 b6 j8 b7 b$ e0 I; F. T: T4 s                if( addr == 0x0000 ) {! k% G( N( ]8 |% I- u! l
                        BYTE        dummy = n106.Read( addr );
2 [  o) w' m% k+ S( B                } else {
% _/ S  d8 V) d0 ]+ U                        n106.Write( addr, data );
" ^9 w) Y$ ]' S; O                }
% T3 M5 J- t3 B. _7 Z0 I& T        }
# H1 w4 |0 T7 R9 t* F        if( exsound_select & 0x20 ) {1 i5 ^3 S8 H' a; m# h& D. E
                fme7.Write( addr, data );& V1 C4 ^' L8 u4 p, ~2 l
        }
  o7 U) s$ q0 `! |, O}
: z1 f- j, i6 s
- D4 w0 t7 o, w5 Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
0 i4 b+ \  s1 i( F{
% U$ U3 H  u  y/ T. KINT        nBits = Config.sound.nBits;! C* s. |. k- O8 J
DWORD        dwLength = dwSize / (nBits/8);8 M( L8 g& {% H5 ?; |: Y' @6 r
INT        output;
6 b) a" D' q( ~" M- n7 ]QUEUEDATA q;
" C1 B* H5 g: a( \. ]! TDWORD        writetime;
5 n: G7 b# p, d; V# Q! z3 B2 z2 S/ N) [$ P6 x. {
LPSHORT        pSoundBuf = m_SoundBuffer;
6 @2 z3 x# H, {( PINT        nCcount = 0;
9 `% l% n8 L' x6 h" T3 s! k1 r5 s0 Q# y- d! O
INT        nFilterType = Config.sound.nFilterType;( t4 I6 R1 g4 J. O! D

9 y* m8 S$ M: k$ [- S        if( !Config.sound.bEnable ) {& T4 ?7 V  u% W$ m: j! Y  I0 p
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );: p# k- F6 c6 c  X
                return;
/ K% K* o$ L) W& H7 L7 N& w  u        }
; v2 D( ^2 O# D# d6 F1 b+ f6 ?; Q4 a' P0 r, W
        // Volume setup" E3 ?) M4 r4 v9 W" o
        //  0:Master3 S3 s" n+ L1 I
        //  1:Rectangle 13 ^/ s4 X; R6 e2 t  L
        //  2:Rectangle 2
/ P8 o* D4 ]0 E4 r  {1 r" j* I  \3 m        //  3:Triangle
) z: d& `6 o$ Y6 j: d. U6 O        //  4:Noise% ?: l& W6 Z& l( v/ u0 d9 X1 y
        //  5:DPCM
# h6 k3 |" v+ r& k- C        //  6:VRC6/ X# A8 k1 m# q. @) D# }; p& U& x
        //  7:VRC7
0 C' l( M( W3 ^        //  8:FDS
5 b  Y2 G# ^% e+ F        //  9:MMC58 `. N  O: S& r" l5 z; I: I! U
        // 10:N106
( c; a3 U, I3 b( a        // 11:FME70 ]! x) ^* i+ d! i
        INT        vol[24];* t$ W; F* P5 k2 V0 ~# u. P
        BOOL*        bMute = m_bMute;
! N" x, ]  M3 p        SHORT*        nVolume = Config.sound.nVolume;+ [' K; f8 M4 M" h

- @7 z: r! K" X0 H) p3 e        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
0 e3 Y! i. w6 i  q+ E  m6 f2 O7 C) f( o; s. K( a+ R( v9 J
        // Internal1 d7 c6 T" r- v: Y
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, C" g4 h+ b- L        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;$ F- b8 f: S4 A4 H, k( ]) J# U
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
3 k8 Y0 v) L' \- T# g3 p        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
$ H( w% `3 ]& k        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;+ _" w) ^; d4 S

1 Z- j: C: ]- ]% N$ A. G        // VRC6" p* M/ e9 u* R& t/ K- O
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  S6 w+ y' }3 f! ?
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& S( y3 }7 F; `) K7 R! l        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 g! F5 Z5 C! n' @1 R
0 I/ [1 `: E3 `9 D: W/ U
        // VRC7
) f9 A" m; a( t0 Q3 P5 Z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, \  l6 q9 [+ \/ L1 `: k( M( d9 v* x  P
        // FDS$ C" \& ~, a5 x3 m5 E
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
  z0 n% ]8 M: J' D6 D( J9 j, Y2 d8 i
        // MMC5: j; E  r& n7 Q* L2 |+ m" z
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; R: U( C. o) s6 M0 J3 Y        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: k& Z# B* j9 X
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) a9 k( s# Q7 {2 f
, c, l# ?# G0 N- S1 g0 L6 Y        // N106; X  c3 b& q5 n
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& @9 C- F5 s: X6 g" _* K        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 z. x1 f+ V( R7 t3 Z        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( b& y# @1 o* d& ?: L# H        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 i( W3 |& v! U; i        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 M% M* ~9 B+ Z5 N        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 R/ p' _; p6 h1 U( l) L5 ]' _        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. y' J8 G1 ~8 F# w! L1 {, x        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ s  }$ Y, ^) p0 ?
) A  }8 C" K9 r- H( c( M& n2 C
        // FME7
1 B4 Y& m# H. L' [+ Y$ f$ d( O        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& U9 N! y; y7 T4 r4 P& T
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 F$ V' i2 f- x$ Y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" M% D3 {, _* u
9 V- w/ \6 v3 e/ H6 W
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;4 C9 L. E$ p) d" L, F
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) ^' }$ {1 Z% K  q0 R  i1 A
, B, g0 e: I9 p/ ~9 E7 J        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟  p8 K# ~$ W, x$ H# Q  g6 [$ t
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
- e& M5 D8 y* _: r9 Y9 C                QueueFlush();( |4 x. Y8 R* X
        }
( Q& Q: [; A) c
' l: Q. B3 [8 n6 [        while( dwLength-- ) {3 d1 }$ t; o7 c' J1 a) R3 Q2 ]5 D" }/ ^
                writetime = (DWORD)elapsed_time;
; K; U+ j/ a9 k* [6 N, D: G' J' M9 _& t$ G3 d) T
                while( GetQueue( writetime, q ) ) {
4 A* d- F7 _/ p2 ?) G5 @2 q                        WriteProcess( q.addr, q.data );9 Z2 a' e  B9 ~) @- J% L
                }
5 F- }. K$ ~& o7 L# d. o* G9 ~% c
  c# v( S# \; ~9 n. _                while( GetExQueue( writetime, q ) ) {. W1 G5 c( ]& B! \9 W% t5 T
                        WriteExProcess( q.addr, q.data );
- I; W% _: J) f& \" D. D1 `+ i* [! A                }
( s& ]  {) ~8 R4 B3 \. {* T9 f4 w. J0 ?
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
3 X" O- f- h, Q! V                output = 0;
9 l  P- U. c$ m9 V: X  T+ e5 ?                output += internal.Process( 0 )*vol[0];
. L, E& p# X. I- I0 K, h                output += internal.Process( 1 )*vol[1];
3 X+ u  C  f& h. m* T; y                output += internal.Process( 2 )*vol[2];
( [5 ?$ T; v/ m% |$ U0 a1 d  H                output += internal.Process( 3 )*vol[3];' }& p5 T+ i/ s4 C/ n
                output += internal.Process( 4 )*vol[4];
9 D% {& H( g! M* @. j2 R; o
: O. {8 Z# E0 Y; N2 R3 R5 R                if( exsound_select & 0x01 ) {
% D. t7 p0 v% I' V4 Y                        output += vrc6.Process( 0 )*vol[5];( |& l. E& `6 X* i: u0 L8 D! t' Y
                        output += vrc6.Process( 1 )*vol[6];3 ]3 \2 P. Q3 ]7 O6 h
                        output += vrc6.Process( 2 )*vol[7];
- o: n4 u. }; V* Q: Y) A8 }                }
+ J6 b3 `5 [2 `% ^! i( K                if( exsound_select & 0x02 ) {
. a. j; }, Q2 J3 z                        output += vrc7.Process( 0 )*vol[8];% Q' Z* ~! t$ h, r6 O5 G# e
                }0 ]( L) y  [5 E# I/ w1 y, w7 j9 |
                if( exsound_select & 0x04 ) {
& t1 S/ A9 _5 Y; s) v, |# A: r                        output += fds.Process( 0 )*vol[9];3 p; ~& u$ x9 |3 Q) e4 Q
                }
+ N) w7 W# a8 g  n6 X1 J8 ]0 N                if( exsound_select & 0x08 ) {: ~  d( g4 R8 _% Q+ i
                        output += mmc5.Process( 0 )*vol[10];) w) d- x' ~# Y. x
                        output += mmc5.Process( 1 )*vol[11];  Z; n7 Q9 O( F, s. u+ m& \
                        output += mmc5.Process( 2 )*vol[12];
5 _# u* T0 M7 q( ~- R/ E                }) l7 Y5 f6 @$ i" v, J
                if( exsound_select & 0x10 ) {
( u# e$ \# U+ U8 E                        output += n106.Process( 0 )*vol[13];
. q$ `$ o0 N% w& r# o# U; h                        output += n106.Process( 1 )*vol[14];! @+ M2 u' X. j6 e( g
                        output += n106.Process( 2 )*vol[15];
' h5 N$ ~) A& [9 |                        output += n106.Process( 3 )*vol[16];
; |8 s; |/ d* P. A3 S                        output += n106.Process( 4 )*vol[17];0 X( L" `% S3 s# G7 V" I$ f: C
                        output += n106.Process( 5 )*vol[18];
. z8 V! h' P. v) G  f4 A+ @' d9 X- K                        output += n106.Process( 6 )*vol[19];4 p* n: L) u' H" ~3 h" ?7 ~
                        output += n106.Process( 7 )*vol[20];' V6 F. Q6 V. c, z5 I& ]( s
                }
3 T! S6 U1 [& D: l# @9 _                if( exsound_select & 0x20 ) {
1 i5 Z4 n1 z3 S4 w0 ?                        fme7.Process( 3 );        // Envelope & Noise/ {) F) n) Z) ^# P8 R
                        output += fme7.Process( 0 )*vol[21];
: r# l( D8 r4 O% _; ?7 i+ d: Y                        output += fme7.Process( 1 )*vol[22];
! K% \# H! G' k+ s! X$ A4 P- |                        output += fme7.Process( 2 )*vol[23];; X1 W* R* E' M% h/ E  g6 S1 U
                }& B( f/ z' o5 r2 I3 n8 k
; |6 o/ ]' K3 l3 j0 r7 Z# X
                output >>= 8;" f! c; G* _; t8 ]: A4 I1 Y
8 H7 u0 a0 Y5 t) E- H
                if( nFilterType == 1 ) {7 }6 ~5 ?: Y* y5 M. K  Q/ l
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 q4 x4 W# f0 ]0 l
                        output = (lowpass_filter[0]+output)/2;
! L- V' i: }; O  J                        lowpass_filter[0] = output;- Z# _0 S! J6 ~6 |; R1 a
                } else if( nFilterType == 2 ) {
/ t5 w" ~8 S' \( C, @                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
) [  b4 J  E: p; B& t$ T                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 {- S) D: ~  t; G* M9 W
                        lowpass_filter[1] = lowpass_filter[0];( u* T7 y) B: i- v
                        lowpass_filter[0] = output;% M; ~% `. k# }6 W  C( x9 ?$ e
                } else if( nFilterType == 3 ) {4 y0 c" W5 M  q& l3 L: T
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); G, e( S# G, c  x; G9 x3 o
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; K5 A+ `! v2 r5 W: s! M2 O* N) N                        lowpass_filter[2] = lowpass_filter[1];
* y3 b! k) R- ~" J, O. {* `                        lowpass_filter[1] = lowpass_filter[0];3 J6 o$ \6 j% G4 e% G
                        lowpass_filter[0] = output;/ k' e% L- r6 w2 |$ S( m/ u: K4 K
                } else if( nFilterType == 4 ) {
6 ?  t  k4 G1 E                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
2 S/ a+ Q7 ^: [/ u# n" n1 B, s                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
! j5 J4 |7 [5 w/ g5 h                        lowpass_filter[1] = lowpass_filter[0];) ~+ t* V: H% g
                        lowpass_filter[0] = output;% m  x6 E* W6 L
                }
1 U" b' ]* v( ?  v% W+ o. g4 n
( k- h0 ^$ [" p; ]* y3 H! L7 T#if        0
$ }" L' R0 w# A- Q8 v& a  f                // DC惉暘偺僇僢僩, Q3 I( i2 p6 l- C9 n: C
                {  D  J7 R. D1 v' B6 C% J4 L" g
                static double ave = 0.0, max=0.0, min=0.0;& b8 ?+ {% G  x) }  v2 m
                double delta;
4 P) x) @) m+ ?7 s% A  K                delta = (max-min)/32768.0;: {# c3 A2 F/ w& c$ [
                max -= delta;
1 S* \1 B, O, U  f& ~+ [$ n& t                min += delta;
8 K! E. C0 w2 k. v, H4 l                if( output > max ) max = output;
, o+ v' }; ^/ ^+ F! y% q' [                if( output < min ) min = output;$ {, J% I1 N" W( }+ l* S
                ave -= ave/1024.0;" m, Q" h9 V8 J( ]. U
                ave += (max+min)/2048.0;
5 r9 ^: Q. b1 `3 _1 h2 d: F% C- p                output -= (INT)ave;- w% k) t$ y$ P" a( F5 `
                }3 a3 v/ k! E: }* B' @, q
#endif4 c  K% v  M  i& V, R2 B
#if        12 I0 ~" t5 S! ~0 N& h
                // DC惉暘偺僇僢僩(HPF TEST)
2 g# M: o- v' u! B8 S& d* [                {
9 }) P" E$ J+ b  P: G/ N6 o0 F//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);: U& \, I( {2 S
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
$ v9 A) O1 y, ^8 ^                double        cutoff = cutofftemp/(double)Config.sound.nRate;* B8 T9 a7 ?' s- m, N
                static        double        tmp = 0.0;
: ~' g5 W% D4 ?; Y                double        in, out;" K/ l" G  o/ p  w- t# V% J7 o

: R4 d( Z# q3 C6 n' c' ?                in = (double)output;
1 L# \1 @) B0 D5 W& ?6 `7 C. R                out = (in - tmp);
$ K% p" ~- g4 v! d- s/ _  _1 K                tmp = tmp + cutoff * out;
9 i3 x2 W. R7 n. }9 O
* O# e! |  c$ ]! l7 ?- \                output = (INT)out;
# ?  U5 n% f& \. }9 q8 f: R                }
" C) h' x9 Z' ~2 w/ k# X/ ?#endif
& ?) Z) `: W! }0 ]9 N; z#if        06 `$ r% l" Z7 u% K- `
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 y3 W0 `/ ^; {+ V( z/ n% g0 y* L
                {
6 ^( a5 u/ }# E; E5 V4 @                INT        diff = abs(output-last_data);
0 i- g% i2 ]- S: r                if( diff > 0x4000 ) {
) Z, I* j" a7 ^. O" d2 W; k                        output /= 4;
  z3 t! g1 `. E& f6 Z* L                } else ' U* p6 ^3 T- u7 G- O0 P7 W" B' R
                if( diff > 0x3000 ) {
' y! O4 ~# G9 x. f% q6 [                        output /= 3;
& Z2 g7 z2 a' |6 y' l3 p                } else* _2 d7 W5 u; q1 @5 d
                if( diff > 0x2000 ) {1 B' Z, A2 c2 `3 s% A3 k4 _  C
                        output /= 2;
" z$ @) I  E" `' e; M                }
- S/ ?' m1 u" _                last_data = output;; @3 L3 k9 S0 j
                }$ I" F; p3 L: v: t
#endif
! o! A, R% Y  y$ L2 c                // Limit/ d# W4 _  q2 @6 q
                if( output > 0x7FFF ) {& F: H* ]3 V% _& d; k& r4 H* _
                        output = 0x7FFF;
; R0 i/ W& \" O. c# w: I5 d                } else if( output < -0x8000 ) {9 ?+ A4 k2 K) K! d* X  o
                        output = -0x8000;
# x3 ~4 n. _+ @! l                }
1 R- D; Y) E+ x1 H6 v: v2 ?# s( @/ X! i9 E4 [7 P* q8 ?
                if( nBits != 8 ) {
6 A6 A0 m4 D. ~, w* }, Z) U! k# S                        *(SHORT*)lpBuffer = (SHORT)output;1 h- t# G  F: b- u/ U
                        lpBuffer += sizeof(SHORT);7 U6 N$ F; D: R3 M# l" o4 `
                } else {/ D' b+ b8 |1 A" L9 p- c
                        *lpBuffer++ = (output>>8)^0x80;
; ~/ b5 K' L5 Z7 w, b% d                }
' q+ D( E# X2 [* [+ E; ~; U& Y: D$ o% L7 U
                if( nCcount < 0x0100 )3 \9 ?+ n7 W* g$ D
                        pSoundBuf[nCcount++] = (SHORT)output;; C/ q! z) ~, [7 @: D  e
1 @" b+ \+ z- P) g, o3 M9 b2 H
//                elapsedtime += cycle_rate;4 F% @% F* @  V1 z3 }
                elapsed_time += cycle_rate;" d1 B" [4 c* t, l8 [- B1 G
        }& l8 Q: [4 q' Q& L. }0 r: v
  y& l6 p  \" D/ I% w# m# q1 s/ Y7 g  F
#if        1
$ ?% I6 s7 `' }& k        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
5 K. y7 l; k. i; v! A& q5 E  I3 T                elapsed_time = nes->cpu->GetTotalCycles();
! ^# Q' G9 h; |' {4 }* g        }
0 p+ @( W( F4 ?/ ]# \+ L7 H        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
1 v  v9 d- |. w                elapsed_time = nes->cpu->GetTotalCycles();/ a3 g3 C. _. M; b; y7 V9 T
        }( F$ i) I4 E/ A% S" i& f
#else
* w7 F& F( z3 |$ s' c0 Q        elapsed_time = nes->cpu->GetTotalCycles();
' E6 q$ B1 k# c2 d#endif( R% n  m) r( o7 m+ [' c* N, @
}, P9 G$ E+ I/ {  s+ F/ l7 c. {
; @9 T4 Z* g, r" X7 z% l& o
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* i- {2 Q$ l$ k" S$ N" [
INT        APU::GetChannelFrequency( INT no )
" g! y5 X) X: u3 z( n{& J' |5 v  |/ ?8 O/ l2 r
        if( !m_bMute[0] )1 a) T0 p5 ^& Y% p" {+ {1 x
                return        0;
. m- h( h3 P! z& L4 V' i/ u0 C" @9 D. c4 \5 O' v
        // Internal
3 E0 }& T% }) n2 T! T# x) u* D% b3 q        if( no < 5 ) {
- @0 J7 ~: u3 i* y: w: g                return        m_bMute[no+1]?internal.GetFreq( no ):0;
3 \1 U2 w6 k4 A# L        }
) V5 g+ Y% P8 a& f5 q; A1 a        // VRC6
" d5 J) o$ @" p6 |        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; Y/ o; Z; y: a
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;0 M  i' X2 P+ c3 ?
        }
" B6 n( S  E4 [( L        // FDS
1 N) y2 p& X( _4 y- Q        if( (exsound_select & 0x04) && no == 0x300 ) {
7 P" T. [' u; ~8 C- `- g& |                return        m_bMute[6]?fds.GetFreq( 0 ):0;* S' e$ P* Z$ q) _4 F+ a, H
        }
3 j3 C4 M5 T7 B. U0 s        // MMC5
! \$ J* ^5 W) x( C, h6 ^        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 @, L5 Z+ F9 }( S                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;1 A& j) j7 _  X3 O5 H7 i6 |
        }
+ C! S4 C( ^- Z* b        // N106
. z  A' F0 i7 A% a, h; m0 W4 k8 q; ^, @        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {" y, \) z& Q: W
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ q0 B! \, \$ X/ N        }
( @& u: K  x  S4 H        // FME7
( h' K! `3 C$ G+ E: I& ?: f5 \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
( ^3 t! x" j0 j6 M  |0 k8 _                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;6 g" m" M1 o1 l$ m+ Q, c* ]2 ]
        }4 E$ V- p0 z# n
        // VRC7
! c; Z* `, a& M        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ t8 K. y, }1 V) A                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 B% y) v+ @- i$ ~9 x" H        }
3 x! X6 g$ s  S; F) @8 f2 {' D( X        return        0;
0 y) K7 d3 G) H$ ~+ |; g}  w# `+ m6 K- A& K7 C5 f) x, G

8 \1 U8 p2 E  R- H: N6 o, u/ r// State Save/Load4 ^/ m6 `' D( H9 {
void        APU::SaveState( LPBYTE p )
  h+ A+ W9 R' g6 h$ G{* c' g, x! z! T
#ifdef        _DEBUG
+ Y; N; L: x8 f7 WLPBYTE        pold = p;
9 D7 C) ?5 D9 k' s2 B! a& \#endif
4 Y/ Q/ N% ^8 a( A$ c" f2 C* v1 k# M; n1 M  [# a5 U0 K
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞/ G  I- `6 J8 ~/ U0 [+ L
        QueueFlush();
/ A) s4 s7 B  N3 B- X
( }1 m; O- z: X( T6 H. w2 H        internal.SaveState( p );
: J' A4 T; t  F  M8 t        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 @+ n1 u  n4 e+ s* X1 y% L: e' O
! {/ i0 |, y4 w+ E* C9 V
        // VRC6# u, y9 u: Y, u& y6 j% I4 Z. s3 `
        if( exsound_select & 0x01 ) {+ E7 y! {$ p/ _7 E# u% j/ ~- F! @
                vrc6.SaveState( p );+ v7 B9 S- A# n# {
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding- u- Q$ x* Z7 B6 f6 n- g& {
        }
0 I8 L6 a- _! ]# Y0 R        // VRC7 (not support)5 w0 L* k* O- F3 @) W8 b
        if( exsound_select & 0x02 ) {  B- P: k1 D" [9 V8 I6 r
                vrc7.SaveState( p );
- |6 w% J2 y+ S, H6 Z9 B, o. k; B                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( o" T8 g' A2 [: T1 X1 C- {
        }8 ?' H( P  U3 J8 b* _; P
        // FDS0 Y8 c( n# `" g; I$ m1 W
        if( exsound_select & 0x04 ) {: \* g& b$ T' L6 |/ v
                fds.SaveState( p );
0 H2 s) p4 [7 M1 W                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ {4 \! @7 c9 }7 _3 Q) N* Z" r        }+ Z+ g1 V/ V  {/ I5 ^# ~
        // MMC5# O' H) C, U: B  j
        if( exsound_select & 0x08 ) {
( c0 `9 p9 v5 i- `% z  O' _; w# U                mmc5.SaveState( p );
$ J% J; y2 {4 k5 a, f8 E                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 h7 n1 m0 M0 L3 S+ Y
        }$ Q* [5 |9 T. Y3 h- j3 e; Q
        // N106
: D% F( u1 {  j8 Q; d, m        if( exsound_select & 0x10 ) {, q2 R. a' u& T" ~0 Q
                n106.SaveState( p );
6 Z+ i! \6 _5 ^* C                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; T1 e5 h' `5 k7 _
        }+ z" H/ d! `! p# ~
        // FME7
; M* q* d1 m! ?, ^) L+ Y' S        if( exsound_select & 0x20 ) {- p- L) w, v1 r" e  H: ^' h
                fme7.SaveState( p );" `$ ?) W. F5 P! d2 S2 J# b5 @2 D% t
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* j5 W& W- g) E1 ]; I. a        }8 s3 a8 u( P* e0 N. D

- Z* E# U& f4 e& T, I& E# {#ifdef        _DEBUG
2 }% Q6 @2 y: ?$ U, yDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 n7 p( D  H4 w
#endif9 H% ^3 d8 v2 w+ k' e  f
}
8 j2 T0 k1 ~( h
3 Z/ J, \: h5 |, ~) ~5 h! Tvoid        APU::LoadState( LPBYTE p )* r* j0 u, ]; g4 L  X4 f7 N& C2 ]' B  L
{* n  c3 y7 u. S8 q* B1 w9 m
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡7 ^) {$ J" M' _3 L
        QueueClear();$ Q3 Y, P7 p) J4 a) D

( p" M9 \( P  y$ _        internal.LoadState( p );
; ]9 e, t5 n0 J        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ O! Y9 a3 Z4 b; N8 j, Q- W( U( Y% i% A3 i- x  [2 o
        // VRC67 P. }& r. E4 H+ u, _
        if( exsound_select & 0x01 ) {
9 s5 K3 @0 H$ @" y2 z7 e" e                vrc6.LoadState( p );
( e% P4 X2 n3 `1 d8 h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 t) X! C. B) e/ b) Y
        }
/ ~; N2 j1 m. r4 k( t* M        // VRC7 (not support). j$ F% a) N+ P7 B/ ^+ z
        if( exsound_select & 0x02 ) {9 k, i0 o$ [5 U8 y% f
                vrc7.LoadState( p );' `2 t1 `" i& l7 Y3 }
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ b5 L& Q7 O0 A, D! ^$ m2 b1 R        }
  q/ d5 x) n* `2 @        // FDS8 e8 P; Q& N: f0 n) S) [6 t; B
        if( exsound_select & 0x04 ) {9 ^7 F) [; [' B4 {1 b' t! Q+ K9 K
                fds.LoadState( p );7 I# L" ~' f1 Y7 N3 V
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' s, c* \/ M, h
        }; r* X4 F! R! N6 O
        // MMC5% q" O8 F1 N; C. i1 r# Y6 G1 c4 H
        if( exsound_select & 0x08 ) {" {+ Y; `' q5 k4 [4 z" L, z
                mmc5.LoadState( p );. ?8 B0 x: L0 x+ B
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 R% u- Z" y$ e" N' X        }& u  {/ j: v9 c2 O) d9 ^  K
        // N1062 H" _0 c) O( O
        if( exsound_select & 0x10 ) {0 Y( E3 y1 F9 S; F6 a3 M; L; O/ t
                n106.LoadState( p );1 X$ q  I+ f' \% f9 ^7 R- }
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 o0 t: L1 j# o) h
        }
/ h+ \1 Q6 k9 d        // FME7; h3 h9 J& J: G3 z
        if( exsound_select & 0x20 ) {# M+ b2 }6 y) }
                fme7.LoadState( p );" d. ~/ b/ d) E- f
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" f0 c5 W& I. {: Y( w2 n
        }$ f# x# d. y- z) M6 K# ]
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 * m, a3 F/ m, E$ W+ Q" n' i
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: v( T) q; ?3 o0 B感激不尽~~
  N7 Z3 o* r7 i& G
恩 我對模擬器不是很有研究,, T1 ~  m- ]" X& o
雖然要了解源碼內容,可能不是很困難,
6 _% |& u& m, r" h- o不過還是要花時間,個人目前蠻忙碌的。
; u2 c9 k* g8 M" V6 a- z5 e: ^3 _' W+ x4 z4 r0 O. V6 B
給你一個朋友的MSN,你可以跟他討論看看,
( A3 v% ^" }) K他本身是程式設計師,也對FC模擬器很有興趣。' \7 ^% \  f$ c; M# F

7 X) s7 {9 R1 F) f, VMSN我就PM到你的信箱了。
! L4 n: B- j, z" F2 X
; C$ d8 D  `0 E) d- N4 a. P6 j希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 - q0 q9 S* ]7 I
呵…… 谢过团长大人~~
4 P1 e4 U9 g0 s. g! y4 Z
9 {( t0 w# m# c" [, d4 z
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & z" T5 J: c5 i$ z5 Q& |5 {2 \- }
团长的朋友都是神,那团长就是神的boss。

- h2 m/ J7 w6 c& X+ s8 P5 F3 P$ m, b, `哈 不敢當,我只是個平凡人,$ j' K" `& X9 u: c
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# J. c% b$ y% s# m! A
ZYH' F, [& p! u5 a6 Y9 }% {( x8 [
QQ:414734306
- u* ^" v0 y$ V: W- T* f/ e1 iMail:zyh-01@126.com
7 d0 U& O  J7 C! o. l: e
& X$ `6 W5 q4 L4 O他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * N5 @! ?- `3 y0 D6 O
再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 N5 T; K0 w) W
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-24 09:43 , Processed in 1.083007 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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