EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。8 _) y- y0 D; j( @& E# g
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ j5 L, P* |0 \! B3 s7 o# b
这里有相应的模拟器源码,就当送给大侠了~~7 W5 \) h5 Y. k) A, I6 [# y* j0 W" A: @
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
' O1 V6 c& J  M7 f; A" j+ i能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。8 r6 ]" M# J* ]
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ v* V5 O; I( U0 u: p/ s
这里有相应的模拟器源码,就当送给大侠 ...

4 f4 U2 c5 A' b9 v+ S5 p聲音部分(Audoi Process Unit = APU):
4 g7 Q+ V7 ]7 i; Y7 Z' p.\NES\APU.cpp
( q8 I7 [9 {3 z0 I& E4 S; ?.\NES\APU.h6 r0 j* L% P5 b, A
" G6 I; b9 M5 L7 n

0 Y  F. o+ r4 F5 _1 ]' [影像處理部份(Picture Processing Unit = PPU):
+ l  r6 ]* o7 R1 q# C3 |: R3 j.\NES\PPU.cpp
% E% P4 G7 p9 ]9 x# P.\NES\PPU.h/ K% k' H" y  H% @) {

8 y8 t3 L2 G$ p6 B1 Q/ [( N/ w8 O如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
: F9 ?2 m( W: ?7 z/ J9 d& c9 _(由于很多专用术语和算法机理都不明白,所以看不大懂……)" N; B- x" J) ?
//////////////////////////////////////////////////////////////////////////
& L1 R- [& f9 O' z# r3 N" a7 l//                                                                      //
  i7 Y, m' g( ~2 F//      NES APU core                                                    //# K: ^  P9 k- Q, Y' F
//                                                           Norix      //; j+ _. |1 m7 x
//                                               written     2002/06/27 //' D8 e+ g5 x& q& j6 ~
//                                               last modify ----/--/-- //8 N: H. c. v- i3 U& j
//////////////////////////////////////////////////////////////////////////
: I( u! g/ d9 }- B) P0 ~0 z#include "DebugOut.h", [4 }: U7 j% q+ W6 W
#include "App.h"
" }8 t% G& o+ I5 S' g#include "Config.h"
5 G: S9 H/ r5 `# g. g
, j4 I/ T1 ]& Y+ H. R0 S! g#include "nes.h"
& F0 c! X5 y7 a- J3 U#include "mmu.h"
; y/ w) v+ r" Y7 T8 |#include "cpu.h"
3 ]; r: T' k0 M#include "ppu.h"
* e: c. A9 J5 _9 [. T+ P( ]#include "rom.h"
+ w# I: J* ?7 D( F$ i#include "apu.h"* d$ \* \( H. x2 _+ z" m
: F& ^2 \$ [/ M$ f/ }' T1 l
// Volume adjust" v( H1 f) G1 O) h* e& A
// Internal sounds. [0 g3 P4 b, _+ `
#define        RECTANGLE_VOL        (0x0F0)' n3 J2 C% [9 ~
#define        TRIANGLE_VOL        (0x130)
4 g! K  W; n2 S#define        NOISE_VOL        (0x0C0)
% d$ i# \& p: {4 Q( }  J#define        DPCM_VOL        (0x0F0)4 x+ X. l, B, s2 G$ z2 \
// Extra sounds* P; J6 M9 K9 M+ x' l
#define        VRC6_VOL        (0x0F0)
9 p1 s' w6 \. {" Q' U#define        VRC7_VOL        (0x130)
6 {2 v% ?) h0 `% v4 e. C: c#define        FDS_VOL                (0x0F0)
; c$ \* r" F7 j( L# T6 k#define        MMC5_VOL        (0x0F0)0 E# O- [. ~4 t# F$ x( H
#define        N106_VOL        (0x088)7 B0 ?+ ?- y" R, d1 q
#define        FME7_VOL        (0x130)! T& R1 n% m3 M- T! S% A
! h8 S* O% D* t4 D" f6 b
APU::APU( NES* parent )) O1 {# @% d6 ^* p! k
{
: [5 W% \/ Y# R) m        exsound_select = 0;
' x( m- H% e" F0 @6 t; y8 G/ t+ X: k9 o" b0 G% [& [
        nes = parent;
4 w/ D: o0 N' k9 V( V        internal.SetParent( parent );8 y; k3 F8 ], B- ?4 Y9 a, o& f

# ~: k6 O; O$ P' O: S5 N        last_data = last_diff = 0;& C& ~* M+ L" ~4 s4 g0 r' q% {

7 j" h. b( l* a) X+ Z, o2 h3 i        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 S9 L1 I! O+ h  I+ n$ P* m8 M
8 {5 O3 a# K0 C, ~0 N        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
  t: ~5 p4 K) X2 c1 W- f1 }2 M        ZEROMEMORY( &queue, sizeof(queue) );. U% J  f1 B; ~; h. J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% I1 N& V: J3 i" Q( X6 p% ~1 E$ h9 t
        for( INT i = 0; i < 16; i++ ) {
4 z9 j3 _! a+ t7 L& s9 G0 ]                m_bMute = TRUE;- ]- z* e2 j# b6 V  X& S
        }
8 `  u+ {- U, A1 O- g6 r}
3 {" H5 ^) E8 r3 h4 f3 V* H$ w. g9 w4 J* A' n( R
APU::~APU()% s6 j1 I1 S0 D5 z1 v
{
4 `* A" w6 O- |5 \' P" K}9 f3 V6 |9 A, V! c" v  h4 Y

. M6 v0 Q/ Q7 j) `9 g$ X* Gvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )+ z; U$ w* O5 Q4 [+ |
{" n8 h; W4 [2 i% Z' b! p- E( a
        queue.data[queue.wrptr].time = writetime;
7 |2 p1 q2 `. n) T' ?        queue.data[queue.wrptr].addr = addr;# Z8 u6 [, R/ l: U! z1 L1 N$ I
        queue.data[queue.wrptr].data = data;
7 t1 H: c( b$ K) b/ ?+ T        queue.wrptr++;
0 n! G3 R9 t" R# Q        queue.wrptr&=QUEUE_LENGTH-1;
8 n0 c0 Z6 d' [. q        if( queue.wrptr == queue.rdptr ) {4 M5 K- V0 m7 D7 t3 Y
                DEBUGOUT( "queue overflow.\n" );5 W, J- R  I' y
        }9 o0 z) w( j( G0 w: H1 T' v
}
1 h+ r# n  P3 \3 z: |2 ]2 Y
6 M3 R0 h( C; [6 T1 QBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ l7 _+ \. t, H0 N: f+ [
{) C* S' O$ b5 i9 Q6 Q4 ~
        if( queue.wrptr == queue.rdptr ) {( P7 r1 C+ G3 n4 a( B- U" M
                return        FALSE;+ m% b1 L8 n3 M: ^3 i3 s. Q  n
        }7 D8 p0 Z  e8 d
        if( queue.data[queue.rdptr].time <= writetime ) {
* ~' q0 o+ k' K4 Z( j' b! W                ret = queue.data[queue.rdptr];
+ P& c3 {0 I8 ~7 {3 z6 \                queue.rdptr++;
! ?: l; B& z4 o# r% I; K+ V6 o/ }                queue.rdptr&=QUEUE_LENGTH-1;. a1 c8 s' x! O! k
                return        TRUE;3 b2 j$ U; L1 N+ {
        }
; r3 Y; u$ B5 Z: \  M$ q        return        FALSE;" E/ a" c0 O5 k* m$ s
}
9 D2 b& K* R# [% p7 U! ^8 h( I
4 g# I4 z8 n. V6 X+ G) G: cvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
9 E4 y$ Q0 I. |( d  W/ D{
: `2 ]" X5 {' T* h        exqueue.data[exqueue.wrptr].time = writetime;
2 Y* p$ Y) }& G! o1 J$ n        exqueue.data[exqueue.wrptr].addr = addr;
# q' Q% B: G/ @5 I        exqueue.data[exqueue.wrptr].data = data;
  T% E1 T$ n5 J        exqueue.wrptr++;( [! K( O( }: @/ n
        exqueue.wrptr&=QUEUE_LENGTH-1;5 V9 U" o; l) K$ o8 d, \
        if( exqueue.wrptr == exqueue.rdptr ) {
1 V- u0 m) G, R3 q9 l2 K                DEBUGOUT( "exqueue overflow.\n" );0 }7 ~% E/ d  @
        }- X% Y4 [# F0 X& i0 _
}
- Y/ y; d2 K# r9 ^# q4 u7 O/ y3 T2 S/ f$ F
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! o" s- Q) ]+ h& p- e! ~, D$ R# D4 P{
6 f$ s% T" \' X        if( exqueue.wrptr == exqueue.rdptr ) {; Q2 }) E4 ?- i. m8 T0 f% \
                return        FALSE;4 C# C8 C4 L( g8 _3 I. J" V
        }; u$ e4 |* ]+ `, f5 H" t& n
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* _" p! r% O+ w. @
                ret = exqueue.data[exqueue.rdptr];
( H% T: P0 W& m1 H                exqueue.rdptr++;
2 l$ `; _! I3 F. v6 d                exqueue.rdptr&=QUEUE_LENGTH-1;) P7 j" X$ I3 l, R$ B/ O; p, b* c
                return        TRUE;$ |8 b- q9 N* S. @+ r6 u
        }
8 T0 K& |: H# `9 M8 v        return        FALSE;
8 N/ t) g+ R/ U}
  F  j' t5 q4 Q6 D, O  {. _
9 N9 B3 N3 s! z6 U& wvoid        APU::QueueClear()
2 q6 B  d9 g6 w" \{) c$ i  c9 C. `8 G& h) K) m
        ZEROMEMORY( &queue, sizeof(queue) );
% Q2 b8 i  Y4 T        ZEROMEMORY( &exqueue, sizeof(exqueue) );; Y; @8 i* W; E+ k. h. y
}1 J$ V# G; W2 L: |7 o  E2 ^

( s- ?7 a& w9 f( X% Cvoid        APU::QueueFlush()
2 {3 E; k, N- I! M# P7 ]+ x$ i* x! p{2 Z- m8 z' L1 y8 x& `: m$ I
        while( queue.wrptr != queue.rdptr ) {( D  D* P+ |0 b
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# E; Y+ ^$ c( |9 f
                queue.rdptr++;0 r* F4 x. ~! I/ U4 ~3 q# A
                queue.rdptr&=QUEUE_LENGTH-1;( I. T: R9 a$ k% E( v- ~$ t
        }
0 g) a: d0 R3 ]0 C* q: C6 f3 `/ h( e( C/ {' [
        while( exqueue.wrptr != exqueue.rdptr ) {" L( f7 \3 }- M8 Z* ~
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );9 S( x0 t( S$ ~0 x* @; |8 U
                exqueue.rdptr++;
9 S% h0 Y9 d' W7 v                exqueue.rdptr&=QUEUE_LENGTH-1;* a( @  S) y" N* S* G: G: D
        }
: z# S4 I: j+ O6 P) N}: x' m1 n+ O1 H% l' W/ x9 k: `2 q* n
. O' j; J# P# D6 R; V8 Z
void        APU::SoundSetup()
6 F. s0 v' F% O7 K* z{" Z/ r' [5 n2 N2 |
        FLOAT        fClock = nes->nescfg->CpuClock;
( k  i9 L2 j( `' t7 n* W) n# a4 D        INT        nRate = (INT)Config.sound.nRate;
; {: @  Z6 s' v7 ~/ A8 r8 ]        internal.Setup( fClock, nRate );" d2 b( n  t2 q. T
        vrc6.Setup( fClock, nRate );$ i- V) C* E3 y* ?9 H+ z! r
        vrc7.Setup( fClock, nRate );9 r& Q4 y6 Q: j( s
        mmc5.Setup( fClock, nRate );
* }+ ^2 B% s9 r& {! Z; D- ~        fds.Setup ( fClock, nRate );( h$ d4 Q9 d* ?  s" z1 P7 Y/ l
        n106.Setup( fClock, nRate );8 m9 v" J8 \5 q& A3 k. t" _( V
        fme7.Setup( fClock, nRate );' E% R1 s0 X( K& G, \
}* B& |8 h* `  w3 {' c
+ h" c% n. W) n! v" t
void        APU::Reset()$ h  s6 P1 f2 }$ _9 I
{
) U, q$ K' J, ?* d9 W* k        ZEROMEMORY( &queue, sizeof(queue) );
: W  t8 M+ ?7 f; m* n& T4 A        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 i0 w, _7 f: f1 \/ }. @

! J/ }: ]5 ?1 v# B# L        elapsed_time = 0;/ c- J; V2 ~: W6 A% I, T" _9 J
- U  P& a8 G( |: N, O2 }
        FLOAT        fClock = nes->nescfg->CpuClock;2 ~" x: U- B, |8 s8 `4 A
        INT        nRate = (INT)Config.sound.nRate;) n- i% B6 Z; Z* B& E0 u
        internal.Reset( fClock, nRate );/ [$ f/ B9 S- o. e$ [' V
        vrc6.Reset( fClock, nRate );8 V# d4 m  i& Y7 I- h8 l
        vrc7.Reset( fClock, nRate );. h1 U( p0 h* H6 j; b! s" z. T+ P
        mmc5.Reset( fClock, nRate );- k: ^  O: ]9 s: @+ d& i  j; i2 L
        fds.Reset ( fClock, nRate );/ t( V: R( ~7 E# D6 U! g: J% Z
        n106.Reset( fClock, nRate );
: d9 U3 D9 U" Q/ e0 G% t/ s        fme7.Reset( fClock, nRate );
. i0 ]( H9 Z6 K. C
& m( g4 c! r8 e/ \        SoundSetup();; x+ l4 o* x2 d0 e* d
}/ D7 F1 g7 S! E8 O. P' B
: b1 z( `' H! I  _% P
void        APU::SelectExSound( BYTE data )
1 P% W# R! H/ W{/ G# Z4 ~! X) W6 B
        exsound_select = data;
) f/ Z5 H  s: k" W- ~7 u7 \}/ z. c9 }; V; U: O! ?
$ k. y; v2 b4 p1 j* O8 S9 i5 @
BYTE        APU::Read( WORD addr )4 g! Y4 K9 [, e7 F1 M& V$ {: ?
{
* ~, M: N/ W& ~6 `& p# O% o        return        internal.SyncRead( addr );, B) x8 s% B: p/ r( r
}: y# Q  y3 s) K) t# C
) Y9 S  V1 y# N' j3 v
void        APU::Write( WORD addr, BYTE data )
: a% G2 f6 F( P  K* n3 I" W{
, A9 m' w% D+ l: A0 A        // $4018偼VirtuaNES屌桳億乕僩. }6 a- ?) j& s- q; _' s
        if( addr >= 0x4000 && addr <= 0x401F ) {
& q$ ]( F1 `8 \8 w/ r                internal.SyncWrite( addr, data );) k4 o# T' {* e
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 i7 H3 C# J# W  ^) D        }5 ~, f5 ~8 k# W) H6 W2 K
}8 Y5 n# d/ K2 |1 K9 @% N' |
/ N5 ]  b, @7 \' J
BYTE        APU::ExRead( WORD addr )) @0 `. [( O' X* Z
{2 j) q4 f& w/ }1 o6 D; {
BYTE        data = 0;
3 p! x9 a* Y" l3 V$ j4 [4 o. @1 B" U; D
        if( exsound_select & 0x10 ) {8 E+ R& P0 }+ e/ E+ S: c6 R, \
                if( addr == 0x4800 ) {
! z( A( y5 ^9 W8 W4 X5 Q                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );$ [3 F, Q9 S5 }5 F: z7 Q
                }5 h% R; L$ M7 b8 x% ^% D
        }) m* `8 J/ s) V. s
        if( exsound_select & 0x04 ) {
1 E/ Y1 u5 q; ^+ G                if( addr >= 0x4040 && addr < 0x4100 ) {7 y3 y2 N! d, s! o1 ?$ V
                        data = fds.SyncRead( addr );
# L3 ^/ E/ R5 }# Z3 f4 L                }3 v% C2 T9 c; l9 C
        }1 g. x  a: i/ \, E& o  r$ u
        if( exsound_select & 0x08 ) {1 V5 t% O$ P( Z% \3 C# Y3 _
                if( addr >= 0x5000 && addr <= 0x5015 ) {: a5 P0 o$ L) o% k  V" Q0 H4 M
                        data = mmc5.SyncRead( addr );/ G0 Y. j2 S1 b8 l1 o
                }
! q8 }( x: w" F& J3 c0 E* P        }
# z0 n/ \; i1 y- ~6 {3 q# P# s$ _3 }3 x/ X4 }* K0 p  a
        return        data;
  P9 D8 E' _2 `5 ^7 f8 w0 D}
6 z+ e( F8 T2 c, O6 P# V( P( Z. ~0 L0 a8 t) v# d
void        APU::ExWrite( WORD addr, BYTE data )
' N. G9 L# k1 I8 _{
0 e9 B0 o5 C$ X) e$ C        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 i" k) c' n2 i. k6 M

( T, p0 o) b8 a+ e4 a        if( exsound_select & 0x04 ) {, ^$ _5 [. r; Y# Z. I/ D
                if( addr >= 0x4040 && addr < 0x4100 ) {
. e0 X6 }1 e5 g% ^) K                        fds.SyncWrite( addr, data );8 s  q* ]% ~, c7 e) W5 }
                }" [! ^/ e! k! T6 ?5 |7 S, T
        }$ t- B  v; ?+ C' X

  d* s+ T1 P( k1 d        if( exsound_select & 0x08 ) {3 a+ A2 Z6 I% u8 L) h9 m3 m
                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 s& s# w8 h# o7 l) h4 _                        mmc5.SyncWrite( addr, data );0 o) H  Z0 ~) I7 O/ g1 z6 o4 T8 c
                }( V- x& \$ F1 W. R. M* I2 s6 F
        }
3 W4 \/ V9 P  T3 _% R& m. \! a0 o}
  S) k, a" R2 t2 l4 `# D/ P' y0 e
  x3 j, A& p' R0 N% Wvoid        APU::Sync()
; x; `' g1 e0 P1 B{/ w$ ]! D' B" ]0 j* [0 h
}
1 B) R3 t/ z7 _4 d) C* g# o; ]
) \6 W9 f! x  B, Gvoid        APU::SyncDPCM( INT cycles )9 F4 I! z5 c; k7 t9 i) c8 g( z2 x
{- W- V+ h% e" y' }; W2 b
        internal.Sync( cycles );. |7 B9 y" R+ Q6 Z

' [: s% ~) h8 J4 L& E        if( exsound_select & 0x04 ) {
, [( ?  ]. u5 j9 W0 @+ j& d  N                fds.Sync( cycles );% }( K  E. G! O) Y9 m
        }) @! v! c) u& s) _
        if( exsound_select & 0x08 ) {
1 T$ h- v: m8 i( y! B6 h8 o                mmc5.Sync( cycles );
* r" S; S# E& y        }
! P6 \  ~* j4 |7 z, [}9 O4 G  n2 m/ D9 A
* ~; y: E% y! Q' X* d, ]
void        APU::WriteProcess( WORD addr, BYTE data )0 r" H! k# B6 C
{
7 a0 g4 S% n; z% h3 d# s        // $4018偼VirtuaNES屌桳億乕僩: k# D( R$ |0 g! |# ~( b
        if( addr >= 0x4000 && addr <= 0x401F ) {7 k& S" W. b( |% f
                internal.Write( addr, data );
% x, b( W- k0 S7 e9 O8 U* B: a        }: T; e- u/ C/ H- S# u( ?
}+ r' m# \$ S+ _+ o: d. q

( D. u4 b% z# p1 ~% J/ Pvoid        APU::WriteExProcess( WORD addr, BYTE data )( L6 ]' h% @; S) i8 Q7 {% c
{
# l# c1 c6 N5 |        if( exsound_select & 0x01 ) {
0 X& \- d+ a# z; k# O6 B                vrc6.Write( addr, data );
/ `: s# J7 Q8 S& M# [) R, d, f& U        }2 t* q1 p+ {; I
        if( exsound_select & 0x02 ) {8 }6 q7 d6 T& W0 `) f" d- Q# ^
                vrc7.Write( addr, data );
$ X4 s3 W" q) M; }4 p! `        }6 `. s8 q1 B( b
        if( exsound_select & 0x04 ) {. _$ C8 r* ?4 p# \
                fds.Write( addr, data );2 d& X! o4 @8 Z" G- Q9 T, a
        }' x8 t1 \# |2 H" \) v' H. S  S
        if( exsound_select & 0x08 ) {- |1 W8 o, E0 x6 w2 o( x8 j
                mmc5.Write( addr, data );
. S9 n4 P$ t2 @& k( K* e        }& k2 m: u& T1 n3 l
        if( exsound_select & 0x10 ) {
0 E3 Q2 J; X. N6 J& f" l                if( addr == 0x0000 ) {+ r. h7 I2 T. q; J& B& o
                        BYTE        dummy = n106.Read( addr );" W8 f: R' Q9 [( A! ^
                } else {& G* F9 }% Y* k9 O) [% u4 ^/ E
                        n106.Write( addr, data );
# j# Y0 {7 j* @) g# N                }, a( O, F- D7 ~1 C  F. D  M4 H. j
        }
0 r: {1 @" \* O' R, l        if( exsound_select & 0x20 ) {3 j7 z  \: Q( W' A2 C4 b1 B( M
                fme7.Write( addr, data );" x0 I9 E% `) c% Z- N- [% X
        }- D8 @# L0 a/ B& v) F' p
}
8 f) X8 `5 W+ F* e$ h! `9 A
# C" I3 F$ W, |9 b: T% P( `( ?1 svoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )/ d0 }- W: \% O8 H0 a$ r, |$ v
{
( G/ n+ T$ V$ ?8 H% n" CINT        nBits = Config.sound.nBits;
) T2 J+ q/ J6 o1 _. kDWORD        dwLength = dwSize / (nBits/8);
) p7 z% v  G  q0 [INT        output;
% {5 A/ P$ z% _# f$ B- F( @+ gQUEUEDATA q;, h$ p, n  @$ e, h6 {
DWORD        writetime;$ H+ |/ X3 d/ b5 Q8 h
/ c9 B8 [# c% J) Y: n1 w: k9 @
LPSHORT        pSoundBuf = m_SoundBuffer;
* ^+ E3 S5 v- t8 E( w0 pINT        nCcount = 0;) Y8 m, p7 }/ ]) @$ x

% \- r% G, x* ~: }# PINT        nFilterType = Config.sound.nFilterType;, \$ @# s/ ~+ }0 ]+ @$ q9 _

  `& K- t7 p$ Z# b) l, X        if( !Config.sound.bEnable ) {* u- \7 w: I! P& Q6 r2 ]
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );: P6 f3 X3 `3 d
                return;
3 ^( K: }/ t, X! I- Z( n& [        }
5 t) A. R6 h+ k: R; b1 t
+ f% @+ N8 f: a        // Volume setup1 Q$ O' u6 U* O9 Z/ e' H9 T
        //  0:Master
$ v/ n4 B. o# }* J        //  1:Rectangle 19 ~, V+ g) e5 S3 m, ^* q
        //  2:Rectangle 29 w: D: r7 H  V' U8 l& N2 O$ w4 t
        //  3:Triangle
! t" p6 Y3 N  ?; `& Y        //  4:Noise$ S+ \" U9 a: [3 l7 {8 U  g
        //  5:DPCM
. S& s' h3 \0 M6 u: n        //  6:VRC6
$ c: P8 f9 B5 {8 u# [: f        //  7:VRC7
+ Q# A& j" F. \- ?0 N8 @        //  8:FDS0 G  i' P2 p$ K5 p5 D% x- K
        //  9:MMC5* w( H( m& \# G; Z. C- ~& i$ k" K
        // 10:N106) N& X, h" M% e2 D
        // 11:FME7& p) M) x9 S3 {$ ]- s
        INT        vol[24];
/ S% X5 }  {+ N9 E/ {9 @, h: c        BOOL*        bMute = m_bMute;* s" {$ ^: ^& k3 m( ~5 b. }
        SHORT*        nVolume = Config.sound.nVolume;
7 u3 i, N4 B, s4 L& N2 ?& f5 u( S0 `- G5 C- P' _
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;) \8 V' d0 g& d- ?$ A

9 H" p: `/ l, I$ Q/ o& D7 H' ^        // Internal; |, A( @& m. R
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;" U8 ~+ ^. D4 X; u
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, `8 g7 |1 G8 B) U        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;. i+ O' O( v" u% `9 X
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
: w7 ~) O6 `6 |        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
; S$ [) m. Y0 Q% q' H# }- j0 s4 X7 Y, A
        // VRC6, Q5 [* N$ J6 a! V7 Q
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! a! a/ T2 q& r3 M, j$ k- c
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* H; F, n- h2 ^) B, {7 V
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! p* A2 g0 u& [! f+ ^6 u
9 s, V7 {+ u* W5 o1 _1 D
        // VRC7" L! V" \% K/ v
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  n! E3 T. e/ [9 |1 G
7 T; }% j+ _- k9 w: r' s2 |" N        // FDS+ ?4 v. ?4 r% j% z0 [
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;. a$ z* _- _- f, e) d

0 W( X6 J) Y7 |- J$ l4 J* s        // MMC5
# m! Y. r! w4 T4 O: p8 j; Z        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 d/ s. S: b) i3 s  [
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 K% @$ e- L2 j* @' v
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( l8 E5 \. W! s" c- T' I/ Z

! d' C5 w& J# a" i1 B        // N1067 D( H# e9 v# Z' r' P) O
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! c( u0 p6 V- u- k' E- v
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% S* {3 g& t) z  a  b6 S        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! b/ B/ X+ \! r' s1 [        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: V) z% ~" \- N
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  {+ N$ q+ P2 ~9 X        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 m. Q. G8 O, ^9 e0 G4 Z6 D7 \# B        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 f; _4 _2 Q& p8 U+ C
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; t8 G7 k$ u+ ^+ D( a- ?

3 ]% v" G, r. D. b5 N: d        // FME7
) O$ o9 r2 ~8 h) @        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& y  o' K$ u# h& }' f3 P0 V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- C2 [, n& q8 d) ]; u
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ {' X" \$ A# d, J
" K, Y/ I% m- P1 j- A# L0 w6 d- Q' N
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
( O0 U: x2 X6 W7 |: Q3 D        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ {6 K" X# p- \- x& u
- b4 w; W" g8 n4 x        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ _) C' V" j0 j. C; Y! a2 u' d
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {. x, f  o5 v5 [( j& e3 i
                QueueFlush();
& [, p4 r$ i0 U2 g: S* [) J- |& o        }
- A' _# V9 f9 @/ Y3 T& S
4 J/ e$ x  @7 w' B        while( dwLength-- ) {  C! ?/ _* l. k$ \+ l
                writetime = (DWORD)elapsed_time;* H' a7 n  z1 v' |: |
/ j0 e! U- n6 ]3 U' W: v
                while( GetQueue( writetime, q ) ) {+ s- R7 b7 d+ _3 ?' @) ~
                        WriteProcess( q.addr, q.data );- y, d9 `* s% t7 t. [
                }
" A& s4 t' Q' P4 W2 |. o7 |7 L' p/ j3 h% \4 r: D' J
                while( GetExQueue( writetime, q ) ) {: I! j) r, i; @( r$ }/ u+ S
                        WriteExProcess( q.addr, q.data );( H% T* K# w" n& l( h4 x
                }
* E% L2 s/ ]# @: ~- [3 I1 `+ l' N# d
$ s- F9 v" {$ _                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7+ U; _8 V6 V  c( R3 h- ?
                output = 0;
) \7 Q9 L1 a3 v+ N, t5 D' W: R* i                output += internal.Process( 0 )*vol[0];
* d* A( q, g$ g                output += internal.Process( 1 )*vol[1];
' N1 b- C, d5 K5 O                output += internal.Process( 2 )*vol[2];. ?6 c  \" y* y: C6 p% \
                output += internal.Process( 3 )*vol[3];
9 Y3 ^  x# `& \+ l                output += internal.Process( 4 )*vol[4];/ [, J7 U9 t; A
+ S& c5 e8 }3 Q% s% i, J/ _
                if( exsound_select & 0x01 ) {$ n7 S) A5 [) K7 H* A$ ], E
                        output += vrc6.Process( 0 )*vol[5];
) p/ ^8 ]7 C6 |5 K                        output += vrc6.Process( 1 )*vol[6];
6 d  _6 a! }! V  U- k                        output += vrc6.Process( 2 )*vol[7];# Q- n& j) s5 }2 s. L9 b4 c4 K: T& A
                }
3 t& h# o# u% V' ~                if( exsound_select & 0x02 ) {
9 p! X7 x. ]1 |- D! _. V                        output += vrc7.Process( 0 )*vol[8];
$ W3 S5 Q! q5 w4 H  R/ I                }
' y. `+ @9 S, D3 o* ~! R                if( exsound_select & 0x04 ) {5 t. w3 r2 N$ H% L3 o' e
                        output += fds.Process( 0 )*vol[9];
/ F  O9 w7 U: ?( S- B                }
5 u! L9 ^6 d( \3 u                if( exsound_select & 0x08 ) {
4 a" U& h8 I" Q6 Q" C$ ^9 E6 d% q- P2 t" b                        output += mmc5.Process( 0 )*vol[10];
2 X, }) A; a' V8 Y                        output += mmc5.Process( 1 )*vol[11];1 w" M( m# q% B( N7 ^6 H
                        output += mmc5.Process( 2 )*vol[12];
- |) ^' `3 w/ i. `+ K, k8 a# m                }, C( e0 d  P$ X* ^
                if( exsound_select & 0x10 ) {( a+ Y# j  x. E7 n8 a
                        output += n106.Process( 0 )*vol[13];
3 R# u, e5 s* V# K) U0 O' |                        output += n106.Process( 1 )*vol[14];
2 f( v/ N! U+ Z* r+ y$ t0 i                        output += n106.Process( 2 )*vol[15];! V7 `' A; y7 A
                        output += n106.Process( 3 )*vol[16];
# o7 \. v" v% F9 i( r                        output += n106.Process( 4 )*vol[17];+ a. {, q6 Z8 s4 e8 Q$ `
                        output += n106.Process( 5 )*vol[18];" A8 F! l8 K, g0 K
                        output += n106.Process( 6 )*vol[19];5 R" G9 j7 G, ?# l
                        output += n106.Process( 7 )*vol[20];
2 B! R6 d# ^$ H% o6 F                }
' Y9 s. _/ |' w, [                if( exsound_select & 0x20 ) {* J- ~2 M9 S9 T0 b+ P+ O% e! B7 v7 }
                        fme7.Process( 3 );        // Envelope & Noise0 L) Q/ K1 ]+ M3 K
                        output += fme7.Process( 0 )*vol[21];$ f3 k9 w* e8 {1 x+ o4 H; b; i
                        output += fme7.Process( 1 )*vol[22];
4 p7 j* S- z9 w! p! C  Z9 |                        output += fme7.Process( 2 )*vol[23];
2 e# x+ |& S  o0 I0 U                }+ J0 T  F8 ?2 z# |3 ?

1 E6 M. B. f1 P: ]+ V                output >>= 8;
  |# F/ j4 |. g0 t4 ~8 y, y, n$ r; P' M
                if( nFilterType == 1 ) {
% `) D) y8 X9 ]                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)1 l2 @4 p  h3 g, q$ D7 h
                        output = (lowpass_filter[0]+output)/2;# P; s! r3 b" E- O
                        lowpass_filter[0] = output;4 v' j( }( k1 a3 Q4 [7 e' C
                } else if( nFilterType == 2 ) {
5 n+ n* M8 y6 Z" m1 {                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
3 V0 E2 V& Z/ ?$ E$ o& ~                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 I' {3 n& ?% S& V- f/ N; m, c
                        lowpass_filter[1] = lowpass_filter[0];
4 D$ Q! I7 H6 n$ i5 }                        lowpass_filter[0] = output;
, |. B9 Y7 w, p9 _7 K                } else if( nFilterType == 3 ) {) \! D& m) r( p3 V; a, |# ]. \( N
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 X! r' \3 [- Z# m; ]5 z% k                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 h1 \( p4 g7 P; ]                        lowpass_filter[2] = lowpass_filter[1];/ j& f; p2 c5 d- u* W. x! t
                        lowpass_filter[1] = lowpass_filter[0];# ~6 f( T& c5 r: o2 D4 D
                        lowpass_filter[0] = output;9 V* g# L# R4 ^
                } else if( nFilterType == 4 ) {
! A( i3 b# y2 a9 `  R! f2 S: z                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
4 d1 _/ Y/ ]' h) Q0 J% E                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
6 \* P8 ~- K( V7 {2 B                        lowpass_filter[1] = lowpass_filter[0];
! N: g3 R' Z/ S5 k3 \# t                        lowpass_filter[0] = output;
$ Y" h- j$ s# I* p5 g                }
, ~+ h4 S' S& O+ ?4 q
1 o' K5 C# u# e. k#if        0
& {. {5 T2 J: x7 L- b+ z, E$ G% _1 e                // DC惉暘偺僇僢僩0 O! Q! U. b3 k  P+ {
                {) [1 I; X( q% f+ A
                static double ave = 0.0, max=0.0, min=0.0;
# t0 [) t. Z$ C- R% L4 |, U; z                double delta;
* ^; `6 Q6 d$ j; H/ b% \                delta = (max-min)/32768.0;
% B! r! N5 b4 ]. D: ^! y: ?- S                max -= delta;
! ?6 Y6 C$ L' U/ H. L8 F% b5 g                min += delta;. l/ ?$ N9 \* e' L& V- l3 P( \
                if( output > max ) max = output;
& s, q% z3 S, {' W                if( output < min ) min = output;/ [# Q4 u4 s9 I, j1 u. [
                ave -= ave/1024.0;
/ @' V" r' `9 H1 J3 N% z                ave += (max+min)/2048.0;. F; z7 r  V+ p" I/ ?' g
                output -= (INT)ave;; K) O4 f" D: r! N* @
                }
" N% t- T! t8 F; L6 h2 _+ [& j#endif4 o0 @( r, ~. g, Q, W, W
#if        1" W2 ?8 {; w6 j. J
                // DC惉暘偺僇僢僩(HPF TEST)
. E1 A( I% w1 F                {
0 C$ X" Q( C3 i5 t2 B5 Z' r: q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* Z  x' U% ^) I: ?
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
3 J6 H* L* L1 }3 D* A# j4 M                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ H' A! g% f  q* J, r                static        double        tmp = 0.0;; D% }+ Z: b& k- X& H. Z9 V4 ~
                double        in, out;
4 l2 p+ W, ^: f+ T- @$ b6 b$ p
, u. T: T% s% S# R, u. @- O                in = (double)output;
; I8 W% k: H& J: w  _- o                out = (in - tmp);
3 H' v4 s5 h, W& g                tmp = tmp + cutoff * out;
4 l* Y0 a% H: s) y9 _+ u7 a* N( L+ P  Z$ Q& s( Z1 A7 v( s& F
                output = (INT)out;) A2 ~& ]% W! t+ S3 H# [
                }
* I) u0 Q! C, A  L#endif
1 c& }% }' y. K4 ]#if        00 [+ M0 j4 K* I
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
4 s$ J# B6 q! \7 }: E+ T                {
" B5 v  Q# y* h% A                INT        diff = abs(output-last_data);& w. k: `0 C* J" K  b, |/ h0 G, S
                if( diff > 0x4000 ) {
) W# U/ B  w4 J! B                        output /= 4;  }( x- B1 {5 d
                } else . F, A/ r. d* N
                if( diff > 0x3000 ) {
, ?4 o, }7 u2 Q% u/ n1 j                        output /= 3;
. {" e& t% l. ]3 _; X                } else
' n0 |+ e! a% G, l. S                if( diff > 0x2000 ) {, Q* Q  n: A. h
                        output /= 2;* u2 t. N+ c; p3 l# x' u  L- D% f3 _; L
                }
: P. w6 f* l1 E) V; T# G                last_data = output;
5 B  ~3 h% g# G# {. z                }
. G- j, [1 J, }#endif
7 D4 `1 ^7 w* d8 W9 H                // Limit* Z  M5 ^+ B: t
                if( output > 0x7FFF ) {
) E& T' I5 J# Y1 F8 F2 J6 O                        output = 0x7FFF;
4 t* {  J. E' E# Z/ x                } else if( output < -0x8000 ) {  H0 r* Q4 J8 [4 g/ P
                        output = -0x8000;% t0 e: f& x' j& I: c
                }2 F  {5 L/ ?" T5 ]: i2 g

" b5 W' z( o7 f" ^                if( nBits != 8 ) {
$ Y" k" K$ s: }+ L                        *(SHORT*)lpBuffer = (SHORT)output;. S& M3 A+ {2 K" T" `; M
                        lpBuffer += sizeof(SHORT);
7 r! j7 P! g5 P+ \8 b2 z                } else {
6 F9 g0 K7 _/ A% B+ U5 [. R                        *lpBuffer++ = (output>>8)^0x80;" w* q8 q; C" b1 a. v1 B
                }
& `9 V/ i6 F4 |0 h+ J& p% w* P3 g( p% A) A5 o$ ?* u
                if( nCcount < 0x0100 )4 D- I# u9 B+ I) Q
                        pSoundBuf[nCcount++] = (SHORT)output;, s$ D! t2 J, x' v- W0 R( [

7 q# c1 X3 a% p8 X$ a//                elapsedtime += cycle_rate;; z) _6 L6 K! r0 P
                elapsed_time += cycle_rate;
( O+ E$ g+ A+ d% O  z6 M& d8 A        }' ^! ?4 t% D, W/ f) D- k' _

6 F: P% H1 ?* y+ [#if        1
: ~5 S+ j. ]- b0 b0 l$ C6 K        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
4 D2 E! @/ A$ ]$ m0 r                elapsed_time = nes->cpu->GetTotalCycles();
( D  u( f0 q; D        }9 M) E8 f8 W9 Y. N+ J' [' B
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 H6 P$ P5 X: f% n, E
                elapsed_time = nes->cpu->GetTotalCycles();
1 Z  h- n& H% [# g) s        }$ I" S; |, Q5 d/ \) ~
#else
# Q0 N8 ?, A% t- R( v        elapsed_time = nes->cpu->GetTotalCycles();9 i/ f6 A2 q. ]9 J; ~- \/ K
#endif
5 A  L- y6 `) Y8 c}- V; [5 n' I  v% e1 s  U
7 w" N0 z! p  {' F5 E! E
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡); U" Z  @+ G' {) A" P4 ~
INT        APU::GetChannelFrequency( INT no )
; Y; l# w: k& N, }$ T{
: r1 ~' u0 v( ^  X+ c9 k  t! {        if( !m_bMute[0] )
/ `: ~: f0 B0 J$ d2 o                return        0;' L" x1 s; v, S1 I- L# o
& Y2 T& k: y9 m4 I! v
        // Internal
+ g" G6 n( G- a        if( no < 5 ) {+ e5 a2 N8 l6 i% `2 a! Y; _9 t
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 P  o5 u5 e# ^  J        }
) W. `. Z3 P$ S" m& z: d        // VRC66 L) ?7 G" y" i$ O" l' Z$ u- b
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; Q1 e9 n! K# ]' v! W8 Z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
' e5 J+ v# A* _" {% `        }
: S* u2 ]" k9 q0 O        // FDS# @7 G9 S6 u4 `/ c- ~
        if( (exsound_select & 0x04) && no == 0x300 ) {
4 y( J: Y/ E6 L) t' a* k                return        m_bMute[6]?fds.GetFreq( 0 ):0;
8 F0 r4 j: |9 A- S' l+ m+ A! y# V; |        }
& F) Y4 e4 L/ C  [        // MMC5
+ o' Z) q; [- v1 }- I: J        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
1 x7 t* ?! h+ g) e  ^. D$ x6 b                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;; B. d2 n2 R. [8 {
        }
2 r" c' h. m4 o8 E+ F8 `' M, N5 R        // N106
  f; n+ X( \/ Z( c  N6 U* F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
# B0 b" q6 U0 f/ s3 b) x; b                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;9 {0 x7 h9 y* M8 Z( e7 k
        }
( V/ n, S" Q! ^/ ?* z5 K/ r  m$ P        // FME7& J8 W, f/ k; ^4 W" h
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
6 ?! a: L& W" G3 `; W" ?                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 F3 w$ a7 j6 S- [/ I6 V7 N        }
" E* Z5 V, ]  K# N3 z1 P9 _  c        // VRC72 P8 ]% V; T: f! k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" J1 d0 ]5 }; c5 ^; M% V4 ~4 m                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 Z% r5 K! {4 I( t
        }' q4 p5 ~+ V% f
        return        0;' L" K& j# k( E" D
}
) i6 C6 a: s8 e, x& ]4 q/ F- q( e" b- e+ R% v& Q0 S; j
// State Save/Load
  _4 O, r. t$ R' D0 P2 l2 y) zvoid        APU::SaveState( LPBYTE p ): D/ e( q" j: Y, U$ b* |5 _* _
{
, k+ |' c6 O; G5 G  b4 M3 w2 K#ifdef        _DEBUG; m1 p& Q) a" m' ?. {% s+ ^3 B
LPBYTE        pold = p;
% I8 A# U" B& o/ F" N7 q#endif
& t) i3 s, P3 ]9 ^% W
' u9 k/ g/ f% R* S! s6 I        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞8 h1 U) m+ a/ N% O; C
        QueueFlush();1 e5 I& ?3 r" [2 w5 x9 c  T2 u

' |3 s, @. I/ A* C' e) f$ k        internal.SaveState( p );; Z5 _. i# d; `1 D: C& p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 g( }/ ~) o1 F& a% m! ~
1 D* \$ @* |3 R0 \  p" T! X9 [/ l/ P        // VRC6
2 T7 E- h0 \: W# G; k        if( exsound_select & 0x01 ) {$ |' q) L0 ]3 m7 D
                vrc6.SaveState( p );& l6 u) |3 O, b0 F
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. \, m% N- B$ Y) e; J: N. @        }( H* W8 d. G4 Q( y% F
        // VRC7 (not support)+ ~# a5 f+ `( X: e, S! A4 I
        if( exsound_select & 0x02 ) {' E/ ?8 c* }$ L( X: H% ?( F" Z
                vrc7.SaveState( p );7 {' g% ?$ T) ^7 F' v. ?
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* r% i  a7 K* c7 `- e
        }
0 I9 k" u. d9 Q; G/ M3 h& f  r        // FDS
1 e: M: X8 U8 d( p$ P3 m* G        if( exsound_select & 0x04 ) {
) m! i* Y6 e+ ]% C                fds.SaveState( p );( [/ q  w) \- R+ o3 C  C  i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% T1 L' T0 j) r( A. f4 y$ I8 O- c        }
( s$ y; w  ^  ~. D4 }: t        // MMC5" T: H/ ]2 u& ^2 G" u0 m- V
        if( exsound_select & 0x08 ) {8 S2 i* {: N  v$ E$ S' M" d
                mmc5.SaveState( p );
* x" @. w( x% w; ]2 f' k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# Y  J9 ~1 s+ G/ t. r        }
2 N9 l4 B) G8 [) O, q& S        // N106
; ~: H! E0 L4 M' W! L        if( exsound_select & 0x10 ) {/ I# f! V. b1 K) F% q
                n106.SaveState( p );3 T- Y/ {9 T( |% G9 |2 s9 |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  g, k- q5 E4 i! \4 {        }
/ J2 S0 G! x& Y8 v+ P; n! y4 m        // FME7. @7 N2 Z. r7 D: V/ Q' F
        if( exsound_select & 0x20 ) {2 B) z( c0 _- P
                fme7.SaveState( p );9 Z3 Z. ^  o) C: K- @: @6 g
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 L) p9 g; T' k9 j) Q% d4 c  G
        }
1 k/ X1 W( P( L9 t! k" U
: h- h  j9 f% F2 S4 t& ?8 S#ifdef        _DEBUG
$ [; x& @0 w. v) aDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
, }: w. |& V* D- f6 S# k#endif
9 O# s) z1 m& @* C8 Q}
3 O! s/ Y  K0 }9 z& q& f# N5 M2 P, s' h5 i, x
void        APU::LoadState( LPBYTE p )
% K' o2 w/ Z( Q* L6 c3 H% o" r{& o+ Z7 `. P& X0 F
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
9 M' G7 t" Y( Y" p; X7 w+ z: k) @        QueueClear();
; p! h2 W# B1 h6 G8 q( @, `+ x6 p  Q9 A  J- Q: ]4 w- |8 N
        internal.LoadState( p );* ^3 K6 U0 S/ ]( X. Z4 S7 L/ d/ x" y! P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* {  [  m" U! F. p: o4 K/ i# z0 g0 i- O+ K8 Q
        // VRC6+ B5 p+ S& h9 c) _2 Y- N3 F! u  |
        if( exsound_select & 0x01 ) {
0 I& O1 x/ s2 J& l( Z! p                vrc6.LoadState( p );
. Y$ f. v. T, w* n- M4 |                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. Q' O# F% V$ m2 P- v        }
0 M6 r& h' w& W/ z) v$ D        // VRC7 (not support)# R( G$ t) _4 t) T: c) ]+ g  i0 u
        if( exsound_select & 0x02 ) {
: e2 ~+ |4 {3 t- v9 Y$ T                vrc7.LoadState( p );9 e, s( W1 h9 ^2 x. H* N- w' Q" p
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
( A" D- ~; B: e% w/ A/ Q        }
' [3 z3 ?6 L2 T8 [  \+ \4 G5 n        // FDS
& V' v+ c1 [* r1 j. M' j2 ]' Y        if( exsound_select & 0x04 ) {
( E* K5 J  Q6 b5 q                fds.LoadState( p );
6 c" w2 d& J0 Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 q$ l3 R6 N) S/ @' C+ t        }0 h: @1 g- w- P- F* F2 e* k$ [
        // MMC5
6 g& [7 k8 `5 x5 s        if( exsound_select & 0x08 ) {
+ Z# _1 ]6 [4 D/ u' ]! f, M                mmc5.LoadState( p );
6 U  W( T% p( o8 G2 O' y3 d                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 _4 Y( s& v( E& x7 t  s9 T+ J        }
" f+ m4 C$ b( R, _" E3 Q; x        // N106
) T- h4 |8 d+ n" O% A  E        if( exsound_select & 0x10 ) {
( U$ k" B  X" q                n106.LoadState( p );8 l; t" s- e4 b
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 D0 t" `: F6 s" X( m
        }
" S* Z3 Z% Y5 n3 U- R7 ^        // FME7
) z" g1 i1 Q+ N- o$ j8 k4 h1 P" v1 G        if( exsound_select & 0x20 ) {% _" X. U( A% L# H% h
                fme7.LoadState( p );* r) o$ G" @$ p) ?' x+ t/ {
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ n: y- T, H  h% b8 i        }5 M- I+ j9 V! o6 h
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 E/ F! f2 V) U1 ^* w) w0 [可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
) H" _; j, |, p# P, I1 g9 ~; c" I感激不尽~~
' J& P6 f8 |, Q+ \" Y6 m
恩 我對模擬器不是很有研究,8 s7 Z9 X( @0 [9 B
雖然要了解源碼內容,可能不是很困難,  ^6 g/ f! d  @2 T, M
不過還是要花時間,個人目前蠻忙碌的。
% Y. M( }: `4 {( w% F# G* s8 U. e1 M2 z8 y4 x* g
給你一個朋友的MSN,你可以跟他討論看看,
9 M) P( o8 \' q0 L2 w+ @他本身是程式設計師,也對FC模擬器很有興趣。5 L* [% s" @% d3 M9 [

2 X& ^) w  z3 CMSN我就PM到你的信箱了。
) a- d- }+ L. H4 A! x: T1 j9 j
8 c+ c0 c+ f) @1 F" @7 P# K' M希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
& z' o& ?4 J% v呵…… 谢过团长大人~~
( H* S/ M: M# E; I+ j( o) r. U

/ D1 O8 y$ U* C5 ]5 L. u" v( K哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 j# S. R$ l2 f6 W; \
团长的朋友都是神,那团长就是神的boss。
7 c7 z& q% [6 g! n4 Z/ i& a1 ?
哈 不敢當,我只是個平凡人,/ f; N. _: u9 v* @* t) P0 ~% j  c
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  H7 A# n2 e# }% ]5 x+ l) j
ZYH
1 S9 E$ n2 C& X5 B8 a; fQQ:414734306, l7 H6 y$ f% \! S* V
Mail:zyh-01@126.com
7 H( U6 Y3 I4 d% Y: d9 U" x! Q: U5 S& W  H
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
; a. {: m3 F( G2 |0 P再次对团长大人和悠悠哥的无私帮助表示感谢~~
  X2 t6 G* U# J5 N# V
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-6 23:01 , Processed in 1.079102 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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