EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# [) d  F+ d* E% @- B; }! T/ @% F8 P4 ^
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ Q* o  f  K# X3 Y; j这里有相应的模拟器源码,就当送给大侠了~~) y/ j6 c. Z8 P1 S6 f
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
5 Q7 Q( D  X4 `6 P0 M8 j, E4 [  j3 U: M能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。4 H* i8 Q, G$ d( C6 }: a
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
' v9 ]. C; y! h* V3 E3 p这里有相应的模拟器源码,就当送给大侠 ...

! o' [4 G- _# ]3 L聲音部分(Audoi Process Unit = APU):
8 b5 m6 i+ z1 y/ G$ B.\NES\APU.cpp7 Y7 r8 c7 @6 J. T, O
.\NES\APU.h- p1 {& u7 [* r
. k) D6 R& B8 D7 C0 O

7 {# x6 _" @& D0 Z+ y" y影像處理部份(Picture Processing Unit = PPU):
1 I, j9 i9 h' m7 n0 W7 H; K.\NES\PPU.cpp
4 B; h/ a1 d8 ~  o: o* q.\NES\PPU.h
* R, p/ k, s5 k1 b" N
1 o$ W" I/ `* X+ t  p如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
  e# c" h! Y+ D! P(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 M1 x, W& _) Q9 u. S* F//////////////////////////////////////////////////////////////////////////
, E& H+ r" c& C' i& n. W! }$ R//                                                                      //
- U* [& P3 i7 g1 D8 d4 U2 f//      NES APU core                                                    //
% h# o4 B$ E1 X6 ~; J# W//                                                           Norix      //! ?; ?7 @0 A  \, H/ I  [) @! w- L
//                                               written     2002/06/27 //, Q  u' Q, N5 p/ E4 U/ a( {/ ]! A
//                                               last modify ----/--/-- //
( ?9 }( p& t$ b) ~  A$ y//////////////////////////////////////////////////////////////////////////$ E, N2 Q: e1 Z
#include "DebugOut.h"
9 z9 M7 z% a) o( |9 q#include "App.h"
0 l2 Q# ]& z1 u; H#include "Config.h"  L7 L. @* J( g9 k
8 m: T* w+ ?2 K7 M% ]& C, V
#include "nes.h"
+ L1 r& y9 P2 _9 s& n#include "mmu.h"8 @1 |8 m; y" ~/ p; i. {; c
#include "cpu.h"8 Y+ [7 N$ x: D; V  e
#include "ppu.h"
8 V2 t$ F- i3 N" f3 i$ i#include "rom.h"
8 B1 v: L% y" N. \$ [# z9 J# ?#include "apu.h"8 C8 ]: L: k. r- g; {
- N) r- ?+ L/ o% D" i
// Volume adjust
# R. ^" ^' k2 Q9 H- K" @: f// Internal sounds
  E& C  D8 m# F# F% r0 x& L#define        RECTANGLE_VOL        (0x0F0)& ^# u; o( j# `" o5 z1 C* Z
#define        TRIANGLE_VOL        (0x130)
) @( f1 h$ a/ V6 C1 P8 e( ?#define        NOISE_VOL        (0x0C0)
* d# Q( d% {2 I  v( Q3 n#define        DPCM_VOL        (0x0F0)1 s6 b7 N* F  I8 G6 f
// Extra sounds/ Z6 v  n6 i4 H# A
#define        VRC6_VOL        (0x0F0)
  g  e/ i9 C( `#define        VRC7_VOL        (0x130)
! V! j0 n2 v" k. A  |#define        FDS_VOL                (0x0F0)2 z) a  X- S. z, E+ H0 x
#define        MMC5_VOL        (0x0F0)
' u: F7 H& U; e: n7 e3 f#define        N106_VOL        (0x088)5 R8 z! g4 L- G: S
#define        FME7_VOL        (0x130)
5 l- F2 ^$ [/ o9 K2 b5 @
6 t* D4 S2 N6 G% F. {9 B! |: S' ~APU::APU( NES* parent ): @5 G, B4 }) V* x- G3 t1 L
{
# z$ E/ z8 n# f4 A& s9 o" G: E8 V        exsound_select = 0;
2 W/ b+ |2 O) ]. R  d  l' k$ M3 l9 t
        nes = parent;
# J# {8 {! S/ P; P, T        internal.SetParent( parent );7 p$ c. d5 o- T# b" u6 [( |/ n3 g

4 ~% u* }. L' w  ~/ O9 O  ^        last_data = last_diff = 0;
( g& v, U  w/ [
. L: r: s4 Z# }0 K( D        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 D$ f: K8 k  m' x7 V; ]- q$ t3 j

. V7 U; n) A0 D4 A: p0 W        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, d0 M/ c. V( C5 L$ Y
        ZEROMEMORY( &queue, sizeof(queue) );: E6 ?' D9 _3 [. i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: P) [6 H) P/ W5 I
5 S0 P5 H! q. g! b1 D        for( INT i = 0; i < 16; i++ ) {
( `8 ^9 q. n9 F! O  _                m_bMute = TRUE;, m" D7 j$ d4 G! |; I( N2 q
        }
; W6 U- b# {3 ]6 ]/ z}
8 y- H3 R/ `, g- W0 U) a1 j6 t3 ]$ W- O( b: V+ m( E4 D+ P- \
APU::~APU()3 v- X' L% s# W) Z( d* p6 a
{, z7 x2 f4 ?- M% Q: g. {/ X6 I
}
0 r' t# f- Y% O# W$ T3 L" V$ E+ \; ~" S' B2 ?8 c
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )$ e$ b, X4 i' V* p
{) Q- Z( i8 n2 }9 h
        queue.data[queue.wrptr].time = writetime;
4 [2 Q) A1 t( Y1 m! J9 v        queue.data[queue.wrptr].addr = addr;7 A% p; }: B$ X( ~2 D2 Q1 k. m6 p
        queue.data[queue.wrptr].data = data;; D- u4 c4 y. T5 N  y7 v0 `& A% H
        queue.wrptr++;" h+ I7 r: p+ [$ m3 ^0 N% @# H. g( x
        queue.wrptr&=QUEUE_LENGTH-1;
% A: p& v8 ]) O- ]" w* ?7 b        if( queue.wrptr == queue.rdptr ) {0 b7 }8 O" D; l9 G! a6 e/ A% w$ `
                DEBUGOUT( "queue overflow.\n" );7 t4 [& Q- m% c
        }% G5 G# X2 i3 W; B4 Q: V" e
}0 t. E3 V2 A6 W/ k

0 g2 w! T2 I+ o$ aBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. v' y# @& |- M3 _{
. h. A" P3 J) M  q3 t2 E        if( queue.wrptr == queue.rdptr ) {
% B2 \! W2 |5 w9 ~                return        FALSE;3 N5 G  _' [7 t6 A; R" `$ i
        }
9 H. T0 Z% n2 Y1 M# a+ V        if( queue.data[queue.rdptr].time <= writetime ) {
. g* C% Y" e) D: R& I                ret = queue.data[queue.rdptr];: H: r$ E* Y% v0 [4 B, ?
                queue.rdptr++;
) C! c0 e; m# I                queue.rdptr&=QUEUE_LENGTH-1;5 ]* m, R3 g6 G4 L, T  ^- E
                return        TRUE;
' x/ {: c0 h, Y' r# A% c) T: X        }
, z  h, u' D# ]/ S# _        return        FALSE;0 N0 _% R9 v- j8 L, E; q
}; h5 f; X' _( ~8 n6 ~
2 F' X8 j3 r( K/ t* o
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )/ S% t2 Y+ S' w; K
{
4 r, N6 |* v& `6 q' I# b( s/ V        exqueue.data[exqueue.wrptr].time = writetime;! v2 F6 C  v; a! a7 u$ G; O
        exqueue.data[exqueue.wrptr].addr = addr;
% v5 p) B# _! |0 c5 M* ^, Y9 v        exqueue.data[exqueue.wrptr].data = data;
" g- G$ b& _1 I/ \5 ?+ o: o4 G) V        exqueue.wrptr++;8 a* y: _" C2 N5 B+ b
        exqueue.wrptr&=QUEUE_LENGTH-1;
+ e. A+ F, B: ^! `2 p) j5 R# x* S& H        if( exqueue.wrptr == exqueue.rdptr ) {2 f3 V* p6 S3 P
                DEBUGOUT( "exqueue overflow.\n" );7 n/ G/ m  I  ]+ [
        }9 ?% D+ L* ], [: L
}
! ]6 _, S! S' o+ }" w8 z. k& \* u8 H4 o8 M. I- d
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
$ W. b# k5 b! v9 v{' r7 v; G+ d" o6 H( J
        if( exqueue.wrptr == exqueue.rdptr ) {6 a+ w" F0 a2 A3 A9 u+ Y9 T
                return        FALSE;+ P# Y' o; Q) E5 C# B) P
        }: A0 q4 I- e9 }. R
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- z, v% G, a$ ~2 V
                ret = exqueue.data[exqueue.rdptr];
' C1 R) ~: h4 S1 S                exqueue.rdptr++;
0 Q# d$ r; j1 X* W  _8 N) a/ y3 f                exqueue.rdptr&=QUEUE_LENGTH-1;  h6 N4 U9 c$ s6 ?
                return        TRUE;% Z- U- J8 b/ w5 H  y# }; H
        }( k, H% N( r1 I  d
        return        FALSE;
/ k, g$ s9 d7 e( s" `7 V}
: k; v* g5 i! b" p
. D; m9 s1 P1 i, ~void        APU::QueueClear()7 ]* m4 S! @" K6 {
{
- }1 R* A8 c  L% Z5 S$ P7 j5 D        ZEROMEMORY( &queue, sizeof(queue) );# F& Y: u- n4 B; I# O1 F6 W
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' p! ?3 R8 ^" J3 ?}
  `9 M* d# F' {* S2 T) G2 a9 V; ~8 d0 _* E  X7 \7 t9 X
void        APU::QueueFlush()4 G& c5 z+ M) F1 e7 N- b4 r
{
' s6 I0 ], h! B( C% o3 ^. A0 P        while( queue.wrptr != queue.rdptr ) {
9 c0 C; u+ n8 i( V8 F( Q( D/ f/ m0 a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; [7 K' f$ S( s
                queue.rdptr++;9 K! \! [/ A; p& v3 H( b
                queue.rdptr&=QUEUE_LENGTH-1;- a1 K1 r. i, G, z5 u& k% J
        }
- v# C+ x: ^4 G) ~  X! d( ?0 H7 [! I/ Y0 j0 p+ j8 P( I
        while( exqueue.wrptr != exqueue.rdptr ) {" z6 i- u* z9 [: F8 e' u0 Z  S, V
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 t3 g: t5 n4 n/ B, D
                exqueue.rdptr++;
% b* O& m& B5 c& t9 _; `                exqueue.rdptr&=QUEUE_LENGTH-1;
& l8 G! N8 X; f% Q        }, {- H& _- j2 l% P  F
}
% @' t0 p  S. @4 K5 A* G- O
- G; O$ e, A8 w. p5 u1 b; B* Lvoid        APU::SoundSetup()
$ u! J. }2 [, c# p6 U4 ^. p{) H, O& h% D6 O: g7 c( [3 }7 O
        FLOAT        fClock = nes->nescfg->CpuClock;
# ]: t' h* [  ]" q/ f        INT        nRate = (INT)Config.sound.nRate;+ b) X' u# d4 V* Y5 ]- ~
        internal.Setup( fClock, nRate );
" Z. O9 C4 e- s. C- Z        vrc6.Setup( fClock, nRate );
- l* M. b% |  o: D  m( v6 e7 V        vrc7.Setup( fClock, nRate );
7 j2 k& a% T' B. V1 P        mmc5.Setup( fClock, nRate );
" N: f, o5 h. i; A# z; Q  K4 W        fds.Setup ( fClock, nRate );
" x$ t- e4 v" e2 L( F; O3 X2 l8 Z- v        n106.Setup( fClock, nRate );
: _. l" ]& P( B+ N. t# l        fme7.Setup( fClock, nRate );
; t+ a. Y3 j1 v}* f8 s/ q! a# c- @
( p* J; Y) s6 w" ^  A! y- H2 L# b
void        APU::Reset()
+ A2 \2 q2 A# Z$ e1 R* [2 r{
5 {; r: c7 u' _7 Z* c        ZEROMEMORY( &queue, sizeof(queue) );$ `, l% N1 u% a7 m1 z$ m) N) V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 }* _+ \0 ^$ O+ a7 F& {- L

: ]( y' L% \1 a& ]+ o* k        elapsed_time = 0;
6 P, a. ~$ Z4 D
. H2 h6 Y. C4 q: a        FLOAT        fClock = nes->nescfg->CpuClock;
) D; V' }3 @5 `2 m        INT        nRate = (INT)Config.sound.nRate;7 T% o- ?, j( q/ H8 p7 B
        internal.Reset( fClock, nRate );
* h; d, X" }* P' @- F        vrc6.Reset( fClock, nRate );
# Y% q2 r. S# j  A% V$ K+ q( z1 r        vrc7.Reset( fClock, nRate );
' W* z0 m5 N5 p" o& R        mmc5.Reset( fClock, nRate );  e3 z! C4 V/ \+ j  @; y. c
        fds.Reset ( fClock, nRate );
' t3 ~7 `% L3 H( W; e        n106.Reset( fClock, nRate );9 K* x7 u/ z; P. r2 e
        fme7.Reset( fClock, nRate );0 [; {4 S2 C: N# K: Z

- ?: h2 j/ D/ ^& @) a! w4 s5 e; q        SoundSetup();, P; S9 _9 ?7 p# Z4 ~1 \2 L  l3 r
}2 N# B3 b8 l9 T% t
) p& v( X" R( A4 E
void        APU::SelectExSound( BYTE data )  V  Y7 {4 Y2 |; n. B" Z
{1 q  Y) D# g! |# d( Y) t
        exsound_select = data;
: `; u3 ]+ e8 }6 I  r0 |; {3 r. Z}
3 x* G$ ]5 n# h+ s7 n+ u/ J
2 o5 h7 w1 ?- P+ v" G: `BYTE        APU::Read( WORD addr )9 d6 P) X5 z8 \, ]5 y; i; M  k. T
{
- N% d) m& A4 P% s        return        internal.SyncRead( addr );# C7 L) K8 G9 g# n5 h/ H) B
}& Q- f( H8 d, G3 X
* b: t1 @; d3 c! N
void        APU::Write( WORD addr, BYTE data )
2 G  r2 s1 x& L1 E: d# X  K9 w9 [{
& n' y7 K3 V8 {9 c        // $4018偼VirtuaNES屌桳億乕僩$ s- Q! J$ G0 ~6 _5 t4 t+ a
        if( addr >= 0x4000 && addr <= 0x401F ) {
) P- s0 m/ v  n+ _5 E( P                internal.SyncWrite( addr, data );* x4 o: l$ ^6 s2 U
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 K3 ]. T) \7 `+ F8 Z0 M8 L+ j        }
$ w" K) \% K8 i! u( ~  g}
' w7 K$ Z' y% d
3 ^  w) `- @1 |$ F# ABYTE        APU::ExRead( WORD addr )4 g4 x: r* I9 t% y* M" t1 w' r% O5 l
{2 `$ U, ]! h9 e% p, a: A' B
BYTE        data = 0;
/ E, ~. c7 Q0 n4 H, G0 F: G- C+ X
        if( exsound_select & 0x10 ) {% X* G1 F6 E* M; _  o# i  M' \
                if( addr == 0x4800 ) {( P! U$ O. F& L) b7 m! \
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
0 g$ y- Q0 t. K8 y3 j                }( F$ \3 I6 u: p9 }' E  N3 m/ t
        }  B- q  ~1 R# V, \8 l3 B
        if( exsound_select & 0x04 ) {1 Y- b: ~0 w& s# w: S; G3 [
                if( addr >= 0x4040 && addr < 0x4100 ) {
) e8 G9 A1 u* P8 }5 ?% r                        data = fds.SyncRead( addr );
, d% }+ m) Y" I1 _  Q, {" G5 j( _                }
8 z0 _' p0 c6 j: {. W        }: e- h. q2 y$ S! Z' ?
        if( exsound_select & 0x08 ) {
% l$ a" E- w. b! E% f                if( addr >= 0x5000 && addr <= 0x5015 ) {
  ~- u' H7 }% }8 a) G5 Y, F                        data = mmc5.SyncRead( addr );1 p; H" P% E9 X: e
                }
9 N3 X: P0 Q" m& [$ j        }" B/ J6 l  f" y0 E1 @) I& B* ^8 g
! l4 V. q( M) Z% f- _, ]# G
        return        data;
4 G/ [4 |0 f' |6 F1 |' O4 h}
) n4 a* E5 v0 B# J; O' b9 K/ N# l; ]( ?$ R7 z
void        APU::ExWrite( WORD addr, BYTE data )
& j. |$ Q' B. d1 o{
3 j( _) |, Z: Q& {. r# @        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 [+ {, {: j* x4 [3 R$ H' x( s1 x
& J4 N1 ?: J+ ^( S
        if( exsound_select & 0x04 ) {
  g$ G2 I! x- m: }) E                if( addr >= 0x4040 && addr < 0x4100 ) {, G: g) L; c7 P
                        fds.SyncWrite( addr, data );% C, C9 G3 I6 \) P. \9 {
                }  X9 ?# h/ V% `$ B, v' _: [9 R
        }* q7 F8 P  h# v

# F; G( m& Q" i9 b3 Z# c' T        if( exsound_select & 0x08 ) {8 d/ D' @9 h8 @1 Z. j
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 u; X. N7 w8 E! ~3 k6 `
                        mmc5.SyncWrite( addr, data );6 D  r9 Q1 q- C
                }
* E  _5 R) d- w0 n% T- f        }' R# y1 `7 |: y4 }& T5 D
}
. ^! @: x: w2 L/ f$ j$ k8 l+ Q3 ~2 ]. }3 s& G! W& F
void        APU::Sync()
1 K5 D, T% {0 n  h. i3 P{
6 }( u3 |! R* b. e}3 q/ h% |& l( Q$ R$ s: J7 Z; R
3 t4 J* d+ S* J9 f6 o8 r
void        APU::SyncDPCM( INT cycles )
6 H* ?4 x0 K; S- y+ Y{: K8 a/ G, a% R
        internal.Sync( cycles );
7 p' i$ g, J! [" @  o7 D6 m/ {
3 X) @; V, P) g7 B7 q        if( exsound_select & 0x04 ) {
( p5 `9 _3 @& B5 P5 b* x* }* n                fds.Sync( cycles );8 o  f8 w5 X4 E' _
        }
; C  @0 X* w& M        if( exsound_select & 0x08 ) {. [4 O& _' Z; L1 J
                mmc5.Sync( cycles );
9 c  G9 M$ r2 t/ ~/ s" u4 }0 e        }7 `" ]# L) _! ~# J6 W" s4 K- _
}
9 f) ^) x4 l! l8 }) Z: U3 X4 D* A- X& z# R
void        APU::WriteProcess( WORD addr, BYTE data )4 T  x+ t) i4 i
{
: I8 ^% j6 N# {! K. ^7 {        // $4018偼VirtuaNES屌桳億乕僩
# D  ]% v6 a  Q7 A. b* @        if( addr >= 0x4000 && addr <= 0x401F ) {
* {0 N' p6 x9 n; h                internal.Write( addr, data );
& i6 Q- h8 H& R9 d        }, }5 ]- E' `8 G9 Q! ~6 p+ T( T
}
+ p7 e' E) c, W( U  A5 T+ b9 W6 v7 k" w
void        APU::WriteExProcess( WORD addr, BYTE data )
7 k" u2 H' r/ S- }, O8 b6 p{+ j2 e* }: s/ Q  c9 h
        if( exsound_select & 0x01 ) {- \" \$ _! K' {( p8 R
                vrc6.Write( addr, data );
2 y* m1 {- Y$ J% s/ e        }( w1 `; @/ V* V0 [" v
        if( exsound_select & 0x02 ) {- F9 N/ V  }  G9 Y: [
                vrc7.Write( addr, data );  j7 y1 R8 @3 {9 C- @) L# x9 F
        }
. W) a: I$ R; X: A. G0 H        if( exsound_select & 0x04 ) {% P' G* s0 X+ q, J+ u9 V4 {
                fds.Write( addr, data );
9 l/ c; @, g- z9 X, R( @        }% ?9 E- u9 C0 i: S8 s' K- [& `
        if( exsound_select & 0x08 ) {6 I- r* V# H: y
                mmc5.Write( addr, data );
2 a7 Z5 g' P3 o; _$ j        }
/ E' K% z! F  ^        if( exsound_select & 0x10 ) {. t7 c+ I9 p6 |, W9 W) N
                if( addr == 0x0000 ) {$ F6 o. v: W3 X; N* |
                        BYTE        dummy = n106.Read( addr );
* \  A, E( _1 n( V2 W* w                } else {# F, s" z; q/ i  u2 T* [2 c* s
                        n106.Write( addr, data );
- S* F6 P4 m6 z9 E& Q( h; H* V) o                }! a$ L5 r" }# X* W. B" |/ c
        }
! x) B% X, S) D( k        if( exsound_select & 0x20 ) {. ~5 |3 q: \1 `8 c9 d; ~
                fme7.Write( addr, data );3 g- u, i- K/ I! H9 l0 m
        }% y. [0 _) x% i2 X% q# u9 p
}
! ~2 B+ m3 x/ c! I9 o# Q$ p+ Y* @. ?7 U8 B" [' G8 `! K
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )* k) Z, V, V/ o2 l+ {2 }
{
2 ]1 `* p$ Z9 ZINT        nBits = Config.sound.nBits;
7 ^$ F/ ]3 o; `/ H# D" `% sDWORD        dwLength = dwSize / (nBits/8);
1 T) y: I1 C, r7 R' WINT        output;: }9 x! Q$ J5 o6 j/ W; O* {/ E% b
QUEUEDATA q;
" F7 j7 z" P3 R6 H/ p9 SDWORD        writetime;3 Z4 k1 [- Y; H. S9 b4 ]% e2 Y9 K" {  S
& y7 _. A0 S. i3 D& R% |& ?2 y
LPSHORT        pSoundBuf = m_SoundBuffer;
* ]0 M9 _% w' l" I; ^INT        nCcount = 0;' o. s4 J3 {& j
1 p  k6 r+ x9 e% B
INT        nFilterType = Config.sound.nFilterType;; [: T# `5 [! n. v: b
' f% k; n1 }" c( {
        if( !Config.sound.bEnable ) {, V! r& L) Q1 y7 w2 K8 e
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );6 [6 S( E. ?4 j. [
                return;
/ Q0 @& G7 S9 W+ o' ?        }1 ?4 D' H; j1 g
! x- }$ A( n) Q& A& E* L
        // Volume setup
: z8 ]9 ^# N9 |- r0 a6 C6 e  c        //  0:Master- b- Q4 c6 e7 ~  [+ F+ l
        //  1:Rectangle 1
" `1 u4 Z* Q& x5 V3 W5 V. u1 B* K8 ?        //  2:Rectangle 2
- W9 f8 h/ q7 h7 N+ ~        //  3:Triangle. J( r% \/ Z5 ]4 F0 l6 W
        //  4:Noise1 S$ y8 K3 d' M; t: `7 M* n# J8 v
        //  5:DPCM% N- G1 p" U+ N: ^8 Q$ T/ a- r; G
        //  6:VRC6
0 p2 l8 ?' q1 F+ [, v        //  7:VRC7( H6 U& w+ o8 k" f
        //  8:FDS4 Z" @3 H+ O/ M- x# Y
        //  9:MMC5
& J' o: J* G9 f! Q" I7 n        // 10:N106  S8 Q, i+ N+ ]) _' ^+ q( f
        // 11:FME7
1 U8 n# f7 H; _1 w" w2 {5 U        INT        vol[24];
  X  _+ r6 Z( E" l6 z! \7 F  f% z5 H        BOOL*        bMute = m_bMute;  z3 n1 E9 T: F1 C) z9 d
        SHORT*        nVolume = Config.sound.nVolume;
1 Q& o! h3 k* n
5 ]1 v9 q3 C6 I        INT        nMasterVolume = bMute[0]?nVolume[0]:0;$ A* C6 a4 U+ d2 t$ B

9 D2 s: X* ]2 {6 q- w. L; R3 u        // Internal
  K5 f# m4 q- i6 N8 I3 p  {        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
7 ?1 |/ o5 j* j& C4 G        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
6 Z2 D9 v/ Q1 B  r. P. I        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
' I$ r" B/ q) V/ B" a* H        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;1 \  e" X. F' M0 X3 Y% U- ^& ^
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. ~, i1 `, t8 Q: W9 y5 K! _7 ^1 a7 @; t& `
        // VRC6! V6 M0 t% |# c: B6 |; X9 h: R
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 J3 e' v6 R% x6 b6 m% i+ C- w7 O        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; Y/ @# x/ W( k1 L* Y( S9 E3 ^        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 q  Z3 {! ]' o. D8 T6 L1 o% _; V# U# B+ ^
        // VRC71 U( v; L* F: h) T
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
' J% i6 l, x# o4 k" `
1 b% ]8 T# t; g        // FDS
6 q7 b" q2 r8 {& z# S  ^* g        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ D3 l. v8 k7 J% b% w- p$ l2 j+ H! v2 k1 f. e
        // MMC5/ A( r& b" A% V5 x! ?6 m) l5 |
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 B) y! t- X' d1 \! X9 @0 @        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# w9 G+ k4 P$ B. p* v# K
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;/ Q$ r1 t9 p* @- H

) e: P+ L3 b$ |! v2 b8 L8 n0 [. l        // N106
3 k. U% _5 g" n, t' O        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 |8 j. [% g) c9 v1 G
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' D# q, |2 |' G5 i4 O! C! ^
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) d7 [, f+ m) Z! N! d
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" {5 y/ L( I, s# a0 c5 _        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 Z  w: {. n1 X. g0 }4 D+ w
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: t$ g, {* W( p7 s" u- f        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' v( B0 r1 L' H! w+ q
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 ^1 y6 f9 t, k0 ^" C: J9 j$ |( F9 k1 L; ]
        // FME7
& i. e+ m9 o1 t$ q$ h        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 f5 ~+ [& E. U( s        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& Q3 R1 K5 ]0 B        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 N6 }5 T2 R! p5 A& b" {
. T6 O8 p9 a" ~' Z: S- u  M//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;' e/ r$ E2 w2 i( K, k  }- J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 [! W8 T! ~8 a) H& e, W) R0 w7 S/ t8 E" b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟4 [* \9 x" l9 K4 M. _- e" O1 J
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
( z+ @3 @6 I3 o0 B                QueueFlush();
: Y7 `. d3 t: w        }! f3 X1 w! |  l* G+ F1 T
  D1 J4 `7 d# N  |% H1 N8 V
        while( dwLength-- ) {. x" A  o4 h( ?  J3 {1 V$ Q' `
                writetime = (DWORD)elapsed_time;
3 H: {5 e- M' U" H- E) f5 R5 [" L- ]+ v  O$ z6 a0 b2 \+ P1 F+ Q
                while( GetQueue( writetime, q ) ) {
* z) Q1 d7 \5 J1 \                        WriteProcess( q.addr, q.data );
  Q7 W0 {1 R6 X; L                }# d$ q: R9 S' y  w  y4 O" y8 F8 {
3 h0 E2 h7 N. q% h, j
                while( GetExQueue( writetime, q ) ) {
2 q- w, q$ r; s: s                        WriteExProcess( q.addr, q.data );
9 T+ l% b8 W, y) @                }
( k) f( L3 a+ k1 c0 ~' \$ i" V, c1 t! p+ y4 A
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7, i0 M. k: ?0 R6 d6 |1 o: w
                output = 0;
5 h( Y: g* u" w# ^  i4 t                output += internal.Process( 0 )*vol[0];
! H2 x+ s! P+ v" \+ J# j                output += internal.Process( 1 )*vol[1];
2 k3 y3 p5 K2 L; s5 K1 E" Y                output += internal.Process( 2 )*vol[2];+ `$ {  [: _, R( X* ]& |7 ]- N' s
                output += internal.Process( 3 )*vol[3];* j( ?( N" i5 z- D: J
                output += internal.Process( 4 )*vol[4];1 ^, L: k% r' f3 n6 f2 j+ s
' J/ q) H& b, p$ z
                if( exsound_select & 0x01 ) {  {# H" \9 i8 J! J! X
                        output += vrc6.Process( 0 )*vol[5];
; S* p: w. z' H% c' n                        output += vrc6.Process( 1 )*vol[6];' R0 R0 u2 E; y
                        output += vrc6.Process( 2 )*vol[7];! r* |2 ~0 h9 f  v3 r
                }
4 P$ H9 t4 `* T1 W3 _; A: e! |                if( exsound_select & 0x02 ) {
8 r4 X2 u3 T: N5 y) l2 u                        output += vrc7.Process( 0 )*vol[8];4 K: _4 F8 h6 l; Z' E" X2 Z8 x
                }: |" ^" w* x' d: o/ r
                if( exsound_select & 0x04 ) {
& e3 Y  H/ o- O. a                        output += fds.Process( 0 )*vol[9];
* }3 k. g' Z& {1 ^# t+ F7 I$ J7 Z                }
5 P+ ^0 G" e& v9 S, G                if( exsound_select & 0x08 ) {
6 m" s, Y; e' O" v: J5 A                        output += mmc5.Process( 0 )*vol[10];( x3 h2 {& z7 @' X! X5 d% O
                        output += mmc5.Process( 1 )*vol[11];
5 B0 v: Q) |. [3 B                        output += mmc5.Process( 2 )*vol[12];9 _6 R3 i2 `7 s, q+ i/ I1 H1 x
                }- G$ @& V1 N* c7 {( A$ L
                if( exsound_select & 0x10 ) {9 j- \- A! I8 @7 b
                        output += n106.Process( 0 )*vol[13];
- |" `2 |5 U- |' W6 ], ?) d4 j                        output += n106.Process( 1 )*vol[14];
" \# V7 c5 f$ B                        output += n106.Process( 2 )*vol[15];  o: y1 W! b! [  o, O  [2 m& a
                        output += n106.Process( 3 )*vol[16];( v. U6 z& r$ o
                        output += n106.Process( 4 )*vol[17];* D9 z& E& d' X& p
                        output += n106.Process( 5 )*vol[18];3 h- z' n/ ?. y+ ^
                        output += n106.Process( 6 )*vol[19];
  k- t/ t9 W; v" \                        output += n106.Process( 7 )*vol[20];
/ l. s/ X1 ^3 s$ f" K2 A                }
; Z. N  A, G' e3 z" Q- M6 E                if( exsound_select & 0x20 ) {
1 p2 G  m" e, Y* M; @- i5 b/ g# O                        fme7.Process( 3 );        // Envelope & Noise$ q+ H) e% F1 @, i' Y  s
                        output += fme7.Process( 0 )*vol[21];4 S4 P0 @7 [* y, v; H7 p4 z
                        output += fme7.Process( 1 )*vol[22];
, g( h, K7 [% h2 h; X                        output += fme7.Process( 2 )*vol[23];3 i5 V4 A8 [9 m, {6 s$ V: {
                }
/ {1 k$ c! j% F2 A' c7 o6 Q5 \. i$ W2 k
                output >>= 8;
, g( K% a# m: c, h7 X3 G/ x
! Z' V! ~, B5 V* M/ f# [                if( nFilterType == 1 ) {% @* W/ F2 \9 H. w
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 ^; r  h) g* n4 F. l
                        output = (lowpass_filter[0]+output)/2;
  E* z& w& j; s& A; X1 z                        lowpass_filter[0] = output;3 W: P$ O6 w. H6 e! I( z
                } else if( nFilterType == 2 ) {
, m; l! s7 V% ~" U4 D                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 m0 y$ A8 e) _0 v) K, g# y
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;) ^% v* v( B. ^( [% P
                        lowpass_filter[1] = lowpass_filter[0];! H( C/ {( a  W% h  @3 T4 ?
                        lowpass_filter[0] = output;' J" n$ r- w! i4 h" L
                } else if( nFilterType == 3 ) {
$ n& b4 C- A5 a6 k+ O! U: n9 n                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 b& a7 G5 N) `# b$ A
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# Q" g+ h0 K/ M6 r6 C                        lowpass_filter[2] = lowpass_filter[1];. Y, k; l* Y  x2 U
                        lowpass_filter[1] = lowpass_filter[0];9 R- P+ O. [9 V4 o
                        lowpass_filter[0] = output;. @5 y  Q9 r9 G. \7 b
                } else if( nFilterType == 4 ) {! E+ }& \1 m6 r5 J. f9 ~1 {
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% }2 h$ f, m( Y: `% y& C
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 F4 M4 {8 M7 }; K" h$ _/ G                        lowpass_filter[1] = lowpass_filter[0];" q7 x% K+ D9 G" p
                        lowpass_filter[0] = output;5 g7 A* e% \5 W" y7 W$ f4 V; Q
                }
1 i7 F  H4 r" J( a0 F/ a+ K* Z/ X6 h  z0 O, E  I! p
#if        0
% d6 B( g: h9 J9 s* ~# K) x                // DC惉暘偺僇僢僩9 r8 P5 g' M" J: w
                {6 I! X5 N  `% h/ o
                static double ave = 0.0, max=0.0, min=0.0;; ^, X: s: `0 @% v, l$ L6 k9 N& N
                double delta;
6 s' c' v( N0 m                delta = (max-min)/32768.0;5 _5 w- s5 j* }6 |, o
                max -= delta;. i1 _4 |" a4 N( w( H( |
                min += delta;
5 a6 m9 v6 e5 R6 o                if( output > max ) max = output;
% G# v4 R: @6 u. r1 v6 ?) e                if( output < min ) min = output;
" g4 u7 b0 @. E1 D# i0 t                ave -= ave/1024.0;
$ f: b; d( ?% ^- l; j                ave += (max+min)/2048.0;
( l. j/ g6 i: c. i- f- ~                output -= (INT)ave;
( ]. Z! L4 K# |. o$ |/ R7 x0 \! f                }
! \! I! b& }% e6 X  a# c#endif; M: N3 T- L5 y, R1 i/ }" L% t# `
#if        1
# x$ T  T" R+ ?+ z& E                // DC惉暘偺僇僢僩(HPF TEST)
) q/ u# ~& O4 f5 _7 c8 }4 u                {
2 O. r$ ~3 [1 }- V  Z/ d* I, u# B//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
* t4 `, f; b# i5 y% y; v                static        double        cutofftemp = (2.0*3.141592653579*40.0);
' D- |5 w9 x- D7 W$ d& F                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# `! @  v/ y9 T" l# A8 Y2 O                static        double        tmp = 0.0;0 n& [+ r/ d1 I) ~4 T8 p
                double        in, out;5 B- k+ ?7 W( a0 ?0 q0 v, F
! V* l# [# U& I& R4 m0 A, C( m
                in = (double)output;
: k/ r" v: W, C: X2 L, M4 ~                out = (in - tmp);
9 a# M0 v" b, a+ U* k) Q                tmp = tmp + cutoff * out;* h, y- A( B+ Y( S2 Q+ W) f

4 M3 I  G5 K9 D0 Q) o) L/ n                output = (INT)out;
! J! W: [9 I+ y  M. I) q                }
/ u4 S. w8 O3 N5 g: T0 G* J$ Z4 D! z" G) C#endif; b2 S6 x' @/ W# z0 g7 B4 s# x
#if        0
. Q8 A2 a% f. Z) A7 X                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)8 t: E  K# e5 C. w+ ?
                {2 F# ~4 E2 ~& ]. Z& X: U& e$ C
                INT        diff = abs(output-last_data);
. W3 l5 z! U9 I; g- _                if( diff > 0x4000 ) {
. _% l/ m- v: M                        output /= 4;+ X# W5 O" ~( B
                } else 6 i$ P' _) \; z
                if( diff > 0x3000 ) {
& D" d7 h8 h# D& V7 F% N                        output /= 3;
( ]) R4 i$ Y- q% v, N* z5 Q3 h6 ^                } else( t% h2 ?9 z; j$ y& H0 {
                if( diff > 0x2000 ) {7 P' c+ A1 K+ T9 A
                        output /= 2;( |; J1 M& C+ ~# j  G3 u) P% E2 t
                }
, G" @( N$ b8 n                last_data = output;
' o) V  R& R* ]& H. ?' v/ {                }: A( L  @: C- g' h& ~3 Q
#endif1 l- I3 n* `0 _$ J, ^1 }: O
                // Limit6 X- W5 ?$ v5 m4 ]" ~. N( j
                if( output > 0x7FFF ) {$ Y0 T0 o+ e* y& T6 \
                        output = 0x7FFF;9 |( C* u! Q. ~, K* d8 P, ^8 w
                } else if( output < -0x8000 ) {  V8 @8 Y7 q4 `! ~) l; H
                        output = -0x8000;0 Y8 ?& h0 x; G( C) o; E7 z
                }
( ?% Y  M  T5 h( ]# H7 v* a5 m1 ~  \9 D8 z. F$ h1 p8 g; j
                if( nBits != 8 ) {+ ^( v( y/ k3 J' X% n
                        *(SHORT*)lpBuffer = (SHORT)output;
+ t0 Z2 E; f3 P2 N                        lpBuffer += sizeof(SHORT);- |  j" m( C2 h9 E" e$ n6 v+ W
                } else {" B& T. p* A2 T* O+ y
                        *lpBuffer++ = (output>>8)^0x80;4 l" S9 p# N6 Z( f9 D
                }
7 A& w* f2 V7 E# U" n7 j; S# F7 O* M/ }+ w, U9 b
                if( nCcount < 0x0100 ). }  j9 X' t1 R# `: ~" r. M
                        pSoundBuf[nCcount++] = (SHORT)output;* u2 w, O& B4 e- M* v. z  t2 K
; ?' l4 d# p8 L
//                elapsedtime += cycle_rate;: h. v8 x! Q  H7 [
                elapsed_time += cycle_rate;
0 q9 E+ N9 H3 b$ f4 f3 ~        }
" R6 d% g7 V, q2 R( U  o1 C& Y, f' T
#if        1
" r- [$ a0 I3 o. w4 F  y, P* ?        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {* P1 F' y& r4 q$ y1 D- @' g. l
                elapsed_time = nes->cpu->GetTotalCycles();1 ]+ M' U: K, j3 r1 H) ?6 o3 S
        }
* t  D7 k. T7 {! t        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {) r. h+ ^8 w/ q
                elapsed_time = nes->cpu->GetTotalCycles();
. o& R8 `, Q; S& A( U( H( @. P        }* k; X/ V4 [6 Y9 @
#else
  `8 q- p! v" |) q        elapsed_time = nes->cpu->GetTotalCycles();; C3 }; Z) }- a7 D; K" ~
#endif
; I+ `0 K/ z6 g% ]8 l* @}  B+ N$ e) Q9 s3 D
/ t6 a& Y$ h3 b% I  v
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)1 q8 j4 G4 M9 f' q3 z- o0 B- U
INT        APU::GetChannelFrequency( INT no )0 g5 v5 b1 x. Q6 ~# L
{
% B( b) d0 N9 t: ]' D        if( !m_bMute[0] )" v; W( k. F0 V. D- o
                return        0;' i1 N' l, r% E$ k! D9 ]
# W( v) |8 [. V; g- q1 F$ H9 w
        // Internal7 {! L8 ?& ~; b0 `3 C* |+ X& `
        if( no < 5 ) {
! Y% m, p) |) U( l                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 s# a9 B% e# w9 ]        }
0 I. E& {( @6 L) ^        // VRC6
* g# a1 D( \( |! }" {' k% z7 \1 }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* _2 D$ R7 N9 T1 @4 K! n2 n                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
4 F, z4 p2 Y5 L6 Y; y2 z6 s        }
: Y) M; P" H- t. g* l        // FDS0 I+ e5 c$ h* x
        if( (exsound_select & 0x04) && no == 0x300 ) {
( u* B2 k/ ?1 E/ W3 G4 B; N                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: n1 v0 @6 t2 e" d' i        }* ^5 ^1 ~- q7 G$ c
        // MMC5: f$ _; c2 `; e: d3 v$ V
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. d9 k' |# X3 n9 d) s& ]                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;4 `' ^4 m& j1 p
        }
4 D, |7 M3 g3 l        // N106" C6 @$ x$ g3 t& A* G* [) b
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {6 @) n8 E- ]; G0 ?2 o( a2 [/ \/ x$ K4 k
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
: I) c" P4 o- D9 q' z* W        }
; H0 l" D; ?- t* M        // FME77 Q* j4 l  F, L! a- z1 t
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
/ m! R; q0 a: P+ a) K                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;  M$ ~! b0 F8 S, H: t- ?
        }! g% Q( w  j8 o2 C( J$ e
        // VRC78 G+ n" `2 A' E5 y$ S- G- y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: G, C# e+ \: v% V+ j1 W% t) Y9 a2 Z                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- C4 c% E7 X  |# ~! ]! i8 l        }% R- c& y( x+ w7 s( P
        return        0;
) {' f* l, R6 R2 o! \}
0 E- K2 k6 I. a& s& r4 ~
: s% q/ g& n8 S1 m) W  L5 W0 B// State Save/Load1 ?7 }- V# X* f1 F7 u) r
void        APU::SaveState( LPBYTE p )
4 h! v  c. ~* ]$ p  z{. \( A. R4 Y1 r) R; K2 Q& ]; a
#ifdef        _DEBUG
5 W# U2 G7 V3 _- }, c3 P* }! yLPBYTE        pold = p;: n' M8 |2 I' e! g& G
#endif* t+ v( h$ b# K& L
8 e  J2 L3 |) l- H5 e! Z5 a
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 @1 Y7 z- N2 ~
        QueueFlush();
- ]; j' y4 g4 J# q; j. l1 Y8 j. U2 b# S& r
        internal.SaveState( p );- V2 e, j& ~6 m* Q; t+ E
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ Y! h9 Z6 c" ^4 \1 d$ U2 m2 ]
+ H+ g' |/ n9 r+ `+ B. r- A! @
        // VRC6
! }9 z/ a6 q! f4 @+ k7 c( L' W        if( exsound_select & 0x01 ) {
, v8 B' ]4 ^2 l                vrc6.SaveState( p );! D: S, B! \( F9 q& E6 }
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. n3 F5 O8 U2 z6 C        }
) h* _% o" n1 |        // VRC7 (not support)) O- I5 O" y. ~3 q  g5 v
        if( exsound_select & 0x02 ) {
) M7 E: N8 N& v2 D8 R# z2 n                vrc7.SaveState( p );' u  ^+ m7 ^& \, a. f, ]) L9 @
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" {! M( k- X  Q7 j9 H4 }5 k        }1 C/ C, p# {% O  E6 _! R* O" ?
        // FDS
) M. ]& O1 |! `$ v# \% t, ^) I        if( exsound_select & 0x04 ) {
& k/ E0 q. p  q                fds.SaveState( p );3 N6 ^) r3 M- y* `$ S; s0 a" e3 i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: W0 d4 Q6 s; ~* @; V
        }
; a8 s, ]" C1 _% N- K- X        // MMC5
+ t# |1 d: H& f7 e5 l9 o# C. m        if( exsound_select & 0x08 ) {: H; ^  b8 O, {& |6 _; R# }
                mmc5.SaveState( p );$ l+ m4 V8 w6 u6 Z0 p7 S
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' z" Y3 t3 B+ g3 @! f/ q1 m& {8 Y
        }
& {& b& u9 t& |0 J( O        // N106: k. @5 Z& ^3 x% I) T" F1 ~# q+ c% i6 T
        if( exsound_select & 0x10 ) {
  _7 l6 i: C3 ]6 i( G                n106.SaveState( p );6 C8 S+ V' `) p. j5 @) c- z: M  w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% R! x6 j: s" Y+ I        }
! {4 M( \8 k8 C$ A+ V. t1 W        // FME7- k: L6 d7 {% f- z/ ^5 o4 d
        if( exsound_select & 0x20 ) {0 P& h' e1 ]1 a; s
                fme7.SaveState( p );
* o- o. l1 J% i+ y/ U) O                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; c& C/ n+ u- }/ c! [5 f" o4 Z        }& S3 j1 B  Q1 }3 w% I9 H! ~, h  o

* D  ]: g6 G) z5 C( ]4 F2 O#ifdef        _DEBUG
& g( ]' h% |! @) FDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );* u) @3 P7 L  i
#endif1 L1 f/ m, I% E8 o* j4 \; ?1 e) f9 c
}
4 S  _& D; A; Y# ?
7 b1 J: [- \7 e; ^* G) U! a9 lvoid        APU::LoadState( LPBYTE p )$ V2 i, o6 e" }
{
1 T5 O% A6 s7 q+ Z: h( O7 W; G6 J/ @        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 q; I; d0 h9 X) K; |" B        QueueClear();
; E$ _8 U/ p* K' l3 |
  ~) o3 l+ E) r1 Z4 Q0 I        internal.LoadState( p );. J  B* y6 k0 s% D7 W0 `
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) a* z2 u2 c; Q1 i, n8 M1 i/ s  b0 ?8 V+ ~
        // VRC65 u# |; c1 f/ i2 H9 i' D
        if( exsound_select & 0x01 ) {
! t2 x3 e& i0 g9 t9 ]4 b- W                vrc6.LoadState( p );
* h) F* A  ~  h" h* \# y( Q, c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, y3 d( v7 O9 }. b" x  ^        }$ Y8 V' c5 C5 f6 S$ \  Z
        // VRC7 (not support)
2 O6 o9 a+ n) ^" S6 @        if( exsound_select & 0x02 ) {
6 }9 Z  ]) Y# h& H                vrc7.LoadState( p );! Y' U+ F3 Y% k- \5 u
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 K6 D% |/ X8 t) K" E
        }, B. P; x; N6 E  S2 j- r. ^
        // FDS
2 F; E8 j8 C& E0 [$ `        if( exsound_select & 0x04 ) {$ X' K; S# I  C. Z4 h# X% O
                fds.LoadState( p );
1 B, A8 M6 Z- ^! P( {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 ~7 H) d7 ?& o! [4 H
        }; b5 Q. E8 n$ V$ N) s% x
        // MMC5( x) @. S9 b" d; ~4 C# r+ W
        if( exsound_select & 0x08 ) {% F4 n0 y. ~4 T
                mmc5.LoadState( p );
4 y9 e# w2 z, X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding- t& X9 T4 {2 u7 o6 u% m# y: Q1 b: O
        }3 a; u" K8 a; {! M" L- ^
        // N106- _$ p) B8 W7 C# _0 C* B
        if( exsound_select & 0x10 ) {
! G4 f+ J: Q$ n; |+ b# e8 i                n106.LoadState( p );
2 T8 [- n1 p5 N6 Q6 `3 _! W6 Q9 y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* S% {/ g  w5 b5 G
        }
5 q! n0 s; L* x        // FME7
, z6 {$ `8 @$ P$ ^        if( exsound_select & 0x20 ) {
8 j7 T* R& x- F6 c' Y( M% {! f1 a* r                fme7.LoadState( p );
5 c1 A/ P3 i( z1 {+ S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; n8 b8 C$ P0 i( v6 V7 {        }
" l! z, d; j! e; R, s}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ) @4 [3 V: g$ S. J/ c
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& |& H4 U0 D* K感激不尽~~

8 G. V3 o9 t9 t; |. j# O* D恩 我對模擬器不是很有研究,
( f8 i6 W! E, l9 P6 H+ w$ U6 G雖然要了解源碼內容,可能不是很困難,
2 f# x; J  [$ s" x# R" R不過還是要花時間,個人目前蠻忙碌的。
, E7 b, F4 h7 Z- g8 S
7 Q9 c  y+ G& i0 G- F) G給你一個朋友的MSN,你可以跟他討論看看,
0 Q& C" u7 a9 D: U* U他本身是程式設計師,也對FC模擬器很有興趣。" Q7 W. d5 h4 {; A+ S
+ C( ~# s3 }6 w3 v
MSN我就PM到你的信箱了。3 L7 _' \3 P0 U- t& z5 P

* g" D- @, }& @- r$ T! E2 e希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
, K2 P; @9 o. V* e呵…… 谢过团长大人~~
# v, ^5 X+ @8 F) r  b# f

$ K0 }- M& S: t哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
: L8 T  B; ]6 w8 i" W' Y团长的朋友都是神,那团长就是神的boss。
& D) j( e( Z: I; b9 r' k) D7 j. |
哈 不敢當,我只是個平凡人,
# B) h9 y; U* y+ e' Z& _要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 G6 S( R2 E( @( ?- a4 m: _ZYH
2 N% k$ u/ n+ L7 c0 a) ]QQ:414734306) k- [% g6 y1 i; I6 K+ G9 ~
Mail:zyh-01@126.com, g  R; S& Z, T$ ~

+ ]6 T! M8 D; w: g" Z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 ~4 O- A  W2 l2 f' W" R
再次对团长大人和悠悠哥的无私帮助表示感谢~~
) k# Z) C' I0 C6 V3 U
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-6 15:46 , Processed in 1.104492 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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