EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; o: V* r6 f* N; K7 D& R7 V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) f8 O3 m2 M/ p2 ]* Q; H
这里有相应的模拟器源码,就当送给大侠了~~1 T* c' [$ M) G7 M/ F
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : f0 j" ~/ k: `
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. P5 M9 j6 }/ q9 c3 p
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( U0 s& Z- G  g1 k! g; u2 O9 K这里有相应的模拟器源码,就当送给大侠 ...
9 K1 Z! B) |5 E- X; G0 }0 l. P
聲音部分(Audoi Process Unit = APU):
) |6 t  O+ g$ n7 x+ A1 e7 W' c; }3 _; z.\NES\APU.cpp! k! |  m( X( \7 E1 t
.\NES\APU.h
/ Y6 R' J( V! s: l/ B# x
8 y$ E  L* A& [. @7 n* h
4 _0 r- g7 f" H5 a% ]# y5 ^' d2 J影像處理部份(Picture Processing Unit = PPU):6 O" a# \( _8 J- p
.\NES\PPU.cpp
0 v" H3 Q+ @& a.\NES\PPU.h5 l1 y! ~5 u, b8 l

6 A! X) R6 T. ]. Y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( x- j0 |/ X7 N3 [+ C(由于很多专用术语和算法机理都不明白,所以看不大懂……)( Y0 a# _" d5 ?2 u* F
//////////////////////////////////////////////////////////////////////////# j! y1 ^' K. S
//                                                                      //
7 w, T# H$ I* a//      NES APU core                                                    //
+ V6 Q9 E' [6 z" @! j" r//                                                           Norix      //
2 y  q. W. i. F1 s//                                               written     2002/06/27 //
/ A# Y, H, ]5 n1 ^& Q" K' n: v//                                               last modify ----/--/-- //1 |% u" A& E% ^8 ^& L- q$ X
//////////////////////////////////////////////////////////////////////////
7 s' B4 W! n, j1 x#include "DebugOut.h"
4 o1 p) u$ f3 w- m0 u, L' Y; l4 _#include "App.h"$ ?( F. y: _- }/ E+ k% f+ X
#include "Config.h": J' ?, ^4 H8 C6 ~  I1 j+ o1 @
/ s; N' F$ X/ Y- l
#include "nes.h"1 ]7 a$ o" U" l: u2 X7 G5 y
#include "mmu.h"
' t6 e' p( f* i0 f$ L2 k) M9 {. i& m#include "cpu.h"- j+ W0 a0 _/ U2 \) X2 Y# |
#include "ppu.h"
, p1 Q2 }7 l! n, \: T#include "rom.h"7 Y0 b7 q, j% u7 S  A5 q) `6 @% N
#include "apu.h"
9 S) V9 R; R% r! B% M+ _2 B& p) Q  N
0 O4 _) z  A% j: I// Volume adjust2 O* z/ A( a' m" S( r( {) {# q- s
// Internal sounds
7 s1 w4 R' [3 g; R" l: x3 ~#define        RECTANGLE_VOL        (0x0F0)# M" F  C7 l) f  @4 O' ~- V
#define        TRIANGLE_VOL        (0x130)* d$ V  v( `3 A4 N! o% S" K
#define        NOISE_VOL        (0x0C0)
- q; ]% Y7 k: y8 V/ C* l#define        DPCM_VOL        (0x0F0)& R. s  V& l4 ]& B1 g
// Extra sounds
- S3 X1 s- M$ E5 E, A& p, Y& K#define        VRC6_VOL        (0x0F0)
( }6 b/ z4 j/ U#define        VRC7_VOL        (0x130)
/ z3 q8 {. B) t, M% u. m#define        FDS_VOL                (0x0F0)3 |  R$ F- `9 o
#define        MMC5_VOL        (0x0F0)
& v7 P) Z0 w) a#define        N106_VOL        (0x088)
8 a  T- ~) r$ z- J) v0 i9 s' S2 @! l# C#define        FME7_VOL        (0x130)7 Q4 K  L7 ?) \1 @, [' ^3 g
0 a- g# E; N% x1 n' i' ]0 [
APU::APU( NES* parent )
1 k: i7 \: c) N4 g{# t  z! _% Q9 t; P% l9 Z" x5 m6 w/ `
        exsound_select = 0;' v& V/ ^7 ^, r7 O2 V
" q9 Q+ s6 y. q
        nes = parent;5 W! N! y) z% h7 u( Q" x: U
        internal.SetParent( parent );
& I% b& D; H* G9 K! H
- W" ?6 o& o8 K2 z        last_data = last_diff = 0;
1 I5 P% n% E9 X* T) T7 A$ ?1 v. B* [
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
% C0 S8 @$ l) p) u7 a* A( ~5 Y: K& L$ |# U
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );; W( p& J8 M' ~5 p
        ZEROMEMORY( &queue, sizeof(queue) );
9 N4 G: |9 r/ B9 n) o9 y) s8 C7 L8 s        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  ^4 C0 Z; `3 ^9 v
2 Z5 `: e/ |9 N        for( INT i = 0; i < 16; i++ ) {
" L: w. ]- f4 b% i+ X+ `+ s                m_bMute = TRUE;5 ^7 N+ C1 s1 k  d
        }6 U( a6 }$ a6 `& e6 @$ L2 S
}
  z* O" o: r) R3 \% u' |, M/ |9 h+ U* u/ E7 ^. ?
APU::~APU()
" K% v3 U* u  E4 I2 Z. C4 f{
& A9 b- q# D3 l4 V. e" L2 h}" \$ i4 Y- a2 K; B3 c1 H* j

7 i* N# B* {: x* X1 avoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )# H1 w* P$ W! p+ w7 o, I
{
2 M, h' J1 M4 }* |2 j' Z        queue.data[queue.wrptr].time = writetime;5 h5 O7 L( A% v/ i+ }) ~
        queue.data[queue.wrptr].addr = addr;
& h! _+ K# {. U/ ^        queue.data[queue.wrptr].data = data;6 j: {* x9 f9 v6 E
        queue.wrptr++;6 |7 V- p" ^- O  t. t2 Y. P0 n
        queue.wrptr&=QUEUE_LENGTH-1;
- {4 f2 g/ a* }5 \' u        if( queue.wrptr == queue.rdptr ) {
! V$ d0 F; B7 g1 c                DEBUGOUT( "queue overflow.\n" );7 T% \, m1 O' A! q( X! Y5 J
        }) z1 v5 r. l$ c4 z9 B& F
}; X! R6 v5 X9 @9 ]  O; _& Z
. F# A! \4 I1 i. c
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )6 c& b2 u5 |- f: [" {
{' x; c$ b$ g0 b3 Q; U1 C! q- p
        if( queue.wrptr == queue.rdptr ) {
. H$ T" Q0 W2 c                return        FALSE;  |  j( T/ Z' f: z: u
        }! I5 X9 B* w" I) j% @/ S
        if( queue.data[queue.rdptr].time <= writetime ) {( }/ K; c0 @0 @, B) j& J
                ret = queue.data[queue.rdptr];
, ~& N, [' A- `+ s2 Y. {% e                queue.rdptr++;
6 c0 S0 X2 y7 W' \" q0 n' R                queue.rdptr&=QUEUE_LENGTH-1;! s9 K6 b" c3 Q" W
                return        TRUE;/ k$ e$ P( T. i  O# Z
        }
8 s7 \/ `$ O8 m; {& {& y        return        FALSE;
' ~% f* \. x1 }# _; D* L+ Q}
5 T; _! {3 S; A, R
( {% M3 T* b# y% Lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; l* e" ~) }  b{3 v+ u0 u: \: v: ~/ i  X" @
        exqueue.data[exqueue.wrptr].time = writetime;
, |5 T: K  Q, }2 G9 `6 T7 [* a        exqueue.data[exqueue.wrptr].addr = addr;- P6 k+ U8 G1 f( L& m: L" o. T& K& x
        exqueue.data[exqueue.wrptr].data = data;
% Y$ d6 s$ B2 d: e  U0 q5 x0 H        exqueue.wrptr++;" `* z& C, W, Q. Y  Z! ~5 T
        exqueue.wrptr&=QUEUE_LENGTH-1;  }6 I' Y% W" R  t
        if( exqueue.wrptr == exqueue.rdptr ) {* X% b7 F$ F  A* C- E0 Y4 K
                DEBUGOUT( "exqueue overflow.\n" );% y8 A% k& D5 i4 F4 L
        }
5 ~3 |+ d9 H# W( L1 U& X! U}
) D% Y/ `$ u8 p# Q4 u& p5 N
! T  J  E! t- y) oBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 N+ K9 E3 z7 r{+ ^$ D' U/ Z" F8 p0 J, H3 z$ a2 r
        if( exqueue.wrptr == exqueue.rdptr ) {
# @- C& B- G# v9 p8 ~  Q8 _& X8 ^                return        FALSE;
. c( u+ v5 m3 g% p& J# ~  b        }
8 y- g2 d! L+ v  R9 W6 j  ^        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
' Y0 f& f: j# C4 l9 Z, r. }                ret = exqueue.data[exqueue.rdptr];
6 i& x* G3 n3 x; e                exqueue.rdptr++;7 @3 _* U* Y- D, i6 f! T5 i
                exqueue.rdptr&=QUEUE_LENGTH-1;+ }0 J3 E6 q; A/ T
                return        TRUE;
. T+ Z7 e$ |  Z' T, x4 ]        }
' m- S, M2 n. L+ W6 l4 [3 u' P( m* q        return        FALSE;
) W' ~& A& ~$ o. i6 h}
" M# R- |5 M& i! r
+ `- |8 i' h, W) Z' t! s* Gvoid        APU::QueueClear()
9 b5 x# A6 `+ v( q; [" T. r$ B{
- r# j% D7 p, \& i+ W        ZEROMEMORY( &queue, sizeof(queue) );
. E2 h  E& \& G; U5 ~2 [        ZEROMEMORY( &exqueue, sizeof(exqueue) );( n0 }, d4 x8 ?- C' ?6 a
}
( ]: h2 L: _+ m" v- K. p) }, K2 W* w, Q, g0 j
void        APU::QueueFlush(), ^" t1 u$ `# I, f# F  @& E, g5 y1 y
{
5 c! o0 @- ?' y        while( queue.wrptr != queue.rdptr ) {
  b! B3 a' [" `" @( A                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
+ _- x/ G+ i4 M3 X% |7 E7 r  z9 Z% A9 u                queue.rdptr++;- j, l2 [- k! O' Y( y: n3 }* \5 Q: j
                queue.rdptr&=QUEUE_LENGTH-1;3 K. V' u" B7 l2 g4 s0 Y- R" o  a+ W
        }* w& `8 ^1 z( B/ _0 A

/ [3 _$ d  x0 N8 c$ Z1 p; ?1 a        while( exqueue.wrptr != exqueue.rdptr ) {0 c& k, [! A8 w. b0 v
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );; w1 j4 j6 S& R
                exqueue.rdptr++;
" ^7 |& G: H$ W1 Y% F$ [                exqueue.rdptr&=QUEUE_LENGTH-1;, F% x9 Q$ m/ z' P9 C2 M* o
        }
% O. q+ N. X4 X7 h/ f}
3 \5 w9 B" T; b* i- C  Z) @5 ^1 B/ k" |! m$ w/ P  T5 J
void        APU::SoundSetup()9 k9 v# m- s3 f. Y
{' C6 d& w8 C& ^- \0 C2 p6 R
        FLOAT        fClock = nes->nescfg->CpuClock;, M5 H, j8 _+ }* y
        INT        nRate = (INT)Config.sound.nRate;
9 P' R/ A# _' C+ `, q  H7 X        internal.Setup( fClock, nRate );
( t8 R9 Y# r/ Y        vrc6.Setup( fClock, nRate );( m9 L: o' {- v& W3 |) R+ U
        vrc7.Setup( fClock, nRate );
5 w: ~! z# v! m8 Q0 ?9 A        mmc5.Setup( fClock, nRate );
# v9 G! X- @/ A# n  `! T. L        fds.Setup ( fClock, nRate );+ Y" \3 j- B" q! H) x( [/ e! @
        n106.Setup( fClock, nRate );( K' k2 O7 Q7 E3 R( P( T
        fme7.Setup( fClock, nRate );
+ }7 J7 M( [4 M}
' M9 u% k4 i3 w8 a; v  F8 i( }& t, z9 n3 d
void        APU::Reset()
: F6 j0 C& G7 W( n% r4 S2 R{
& p' C3 r# e1 Z7 F0 \+ o+ `        ZEROMEMORY( &queue, sizeof(queue) );, q# c) a1 p; l8 @' h
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 G1 [& I+ B$ ?: q$ a% Y
1 y. E  n6 p4 Y1 F6 F4 E' ^# A7 b        elapsed_time = 0;
: Z- L. W  e& V, h8 L- a$ Z/ l2 Q
/ T3 R: i0 x' j* @0 Y        FLOAT        fClock = nes->nescfg->CpuClock;
8 P2 q, Z- W1 [* m- h; \8 f        INT        nRate = (INT)Config.sound.nRate;
$ F+ o1 g5 s* L* r$ h$ f" A        internal.Reset( fClock, nRate );
$ V) f$ q+ e7 T+ j0 Y" p        vrc6.Reset( fClock, nRate );
- p( G0 Q) I6 F4 q' f9 i+ _8 \. F- ~        vrc7.Reset( fClock, nRate );
4 G8 ?0 |1 ~' d  H* Y: ~; v        mmc5.Reset( fClock, nRate );4 P) o! C, U% d3 g# s
        fds.Reset ( fClock, nRate );
# L; O/ v( B* `+ ~" b% D        n106.Reset( fClock, nRate );5 }3 Y& S2 l: L7 W) A2 |
        fme7.Reset( fClock, nRate );
0 f7 ^; W8 ~0 j$ \" z( M" b( z7 l+ I
        SoundSetup();
; d& E/ a+ I% c+ ?5 M  }% u/ ?}1 R4 |; I2 ]5 w: m8 T1 e
2 I; G, H& U- V" t, C8 G
void        APU::SelectExSound( BYTE data )
, v- X/ W+ v5 Z{- I8 k3 M$ P0 N4 a' ~0 `& s
        exsound_select = data;1 T- L; t; D: e# e
}
" n$ ^4 d+ n/ T
" k- O; ~& o- [; S. j. ~/ L/ {4 IBYTE        APU::Read( WORD addr ): s1 z3 q, C+ `) o. f" U' ~. \8 {
{! L+ w2 H% h! U5 M) E+ E
        return        internal.SyncRead( addr );
' k  A7 q! R0 \}2 {# c) a" p- u- [& Y5 y

) o1 V, q0 `1 J" P- uvoid        APU::Write( WORD addr, BYTE data )* |  ^  c9 s5 s$ B
{* O+ H6 K& P! Y8 p" i
        // $4018偼VirtuaNES屌桳億乕僩
3 T, {2 y- l$ O6 `- s# U        if( addr >= 0x4000 && addr <= 0x401F ) {3 s1 J) X! |5 Y. N+ T7 b' V) t% b
                internal.SyncWrite( addr, data );
! Z6 n' W# g+ d" h4 X* P# R# F                SetQueue( nes->cpu->GetTotalCycles(), addr, data );" P7 a: V" J/ }: f! J: h* j; j
        }- w3 i9 b) u& B3 Y3 U- d
}6 y  N% Q/ B8 h

2 X0 h" g. P& q" m! |0 A0 u1 LBYTE        APU::ExRead( WORD addr )/ w, e6 [% r2 X" x% A; G/ \
{+ ?8 R1 D0 `' k& W. t% ^
BYTE        data = 0;  l# ^( b+ J% Y
' j+ Q2 a/ ^# |& X0 H  {3 F5 T1 s
        if( exsound_select & 0x10 ) {/ x6 \1 z* m* Y" k1 m0 I, \# y
                if( addr == 0x4800 ) {
0 ~7 Z: J' b: a# C* u+ n                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
8 K3 e' H! W1 l. |- l- u! \                }: J* d6 I# H# U- y. ?9 U
        }; Y1 P# P2 C/ g7 j( [# D! U
        if( exsound_select & 0x04 ) {
) X- C0 G7 V! n! O' \                if( addr >= 0x4040 && addr < 0x4100 ) {* w6 H. m# s6 e% |1 O% k
                        data = fds.SyncRead( addr );4 c1 g; Q' g! ?0 M9 [' }9 ^
                }0 w% }+ Y. H  C. P2 N3 ?
        }
9 Z) ~6 b) @$ J. B; a. \9 o/ D        if( exsound_select & 0x08 ) {5 \; D  Q1 h1 g) `2 G: I- B% D
                if( addr >= 0x5000 && addr <= 0x5015 ) {& c; Q7 C  m+ z3 N* K- x8 y
                        data = mmc5.SyncRead( addr );: d6 A. b0 H0 ^8 b" D
                }
/ v/ m  s$ V1 j' V) I1 u        }
! N" {3 b3 N  T+ y' V4 y2 {' y/ h! n% e" l) G+ P6 K
        return        data;
3 z: J% L6 C! Y% ^) C- d}
0 q: d" O: u0 B6 e6 _( T
$ ]: n  N, B8 z% P% h$ `! Q' Fvoid        APU::ExWrite( WORD addr, BYTE data )
- z, X- N: O/ |( v$ C{
/ I  r# U$ \5 q/ _        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
! j( P. y  {( o* |# }, v& O* e/ K- ]0 o" c- S  d
        if( exsound_select & 0x04 ) {
0 w! r' z2 J* O& O                if( addr >= 0x4040 && addr < 0x4100 ) {; }5 y1 X6 q+ N4 H
                        fds.SyncWrite( addr, data );/ s, ~) }+ J1 J2 D; M
                }$ \) L; m* o& L$ y2 I
        }
! w/ C0 `* |+ e6 b) S  R; y0 i
( d9 f. I# E, k2 }' v        if( exsound_select & 0x08 ) {' s4 X8 D! e* f, s$ c, w0 d! P
                if( addr >= 0x5000 && addr <= 0x5015 ) {! h+ t$ f, |- ?* d
                        mmc5.SyncWrite( addr, data );6 ?1 ~( k) \; a
                }* f3 Q+ X2 e1 J8 V4 l: J7 i" r/ m
        }
, Y& L1 x2 G) X9 d/ n}) h( X4 ^1 F+ B! ?- R

: W! S) [- A* H( \void        APU::Sync(). P% k$ y8 O4 a  O1 _, J) y$ b+ C
{
: I5 C% u. T: V; y# `8 r2 F}2 Q) Q2 ?- Z; a. w1 D4 d' g7 {/ r

5 h& k& O* S- o( Y- ^% |void        APU::SyncDPCM( INT cycles )% t( I  E& I% ~3 {
{
( v! M8 ?( o3 P+ {* r        internal.Sync( cycles );
8 D  [, V1 j8 O' v# |/ c0 Q" a( A9 Y- ?
        if( exsound_select & 0x04 ) {$ \1 y, c7 k: d' O
                fds.Sync( cycles );
. j- T5 N$ J7 V4 S* n+ d        }
# f: m$ k3 ]  ], n        if( exsound_select & 0x08 ) {; O$ z5 O. D% m. h$ p
                mmc5.Sync( cycles );) o* w* v# {+ t5 j5 p+ v
        }4 j$ H5 W/ j( z8 F) J
}( z8 Y, G0 @3 w

* z: Y& q7 d, _/ m2 U5 b& ?void        APU::WriteProcess( WORD addr, BYTE data ). U, Y9 `- ?9 n! [6 v
{
. t  p1 C% I  Y* p) _        // $4018偼VirtuaNES屌桳億乕僩
* }1 |/ X( v* i4 u        if( addr >= 0x4000 && addr <= 0x401F ) {2 ]! s, f* P! U& u; M% G
                internal.Write( addr, data );* P1 ^. ^8 G2 E: p( t: N5 N
        }# R& [( i3 y1 {
}
' z3 Y5 h; K+ f$ U" y( f1 `; o5 O0 g% Y. m
void        APU::WriteExProcess( WORD addr, BYTE data )
1 w+ j( K" G% F  K5 ?9 Y{. f/ w$ Z: {. l3 h
        if( exsound_select & 0x01 ) {0 S3 I4 L) g; K5 v! r0 M" O
                vrc6.Write( addr, data );2 S' i$ F; J$ k) Q  @# d
        }# W: q9 D) `7 S' j7 E( ~6 H
        if( exsound_select & 0x02 ) {& l; i( R8 j' H9 v/ O
                vrc7.Write( addr, data );
* j# G, y! F$ y" i9 Q        }1 a9 C4 z" K" E2 K0 V
        if( exsound_select & 0x04 ) {
; f; e+ W# ]1 G& W7 R) ~0 v5 w                fds.Write( addr, data );
6 U  n6 `: _2 |1 ]2 ?+ v+ e        }6 _5 `1 {$ m! _: G: P
        if( exsound_select & 0x08 ) {! Y* ?1 I; b& l6 S1 x3 i1 \/ u) F
                mmc5.Write( addr, data );
0 `# w, f1 o5 [4 l& P        }
: S, N' e( F% g8 B& ?        if( exsound_select & 0x10 ) {
. S4 M& \5 ]1 p3 M& s                if( addr == 0x0000 ) {( \- n; L- W1 M% m; t
                        BYTE        dummy = n106.Read( addr );
; s0 Z7 `' E% Y' W& r                } else {! \$ x4 C. V" c; p% Y" Y/ S
                        n106.Write( addr, data );; _. \" x+ ^5 T, W% v
                }# j2 {% ~3 |. f" O" e3 S4 A' t, i
        }- a* G; I; n. l& K8 a" g4 _) a/ S
        if( exsound_select & 0x20 ) {6 |( D% f, R$ h+ m
                fme7.Write( addr, data );! Y, C( t2 C1 }: E
        }
8 |# X+ s/ C* ]+ F6 z; x  m( {}( r! ]# r" n2 Z

. N# h4 m( T# N* n5 j( Q7 m2 \void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
1 o/ a% s5 m" Z" T4 X: r{# K+ y& E2 y! u
INT        nBits = Config.sound.nBits;# W5 v/ R' M. B  L( ?: o
DWORD        dwLength = dwSize / (nBits/8);
6 I/ }+ [7 F. q# ZINT        output;
7 F4 z1 G2 h0 r  N! E7 sQUEUEDATA q;
* F# y4 ]% p% ^( n. V* ~# P# v+ XDWORD        writetime;
7 z% G6 [/ x! ]7 r
+ q( Z' F" g# S" j& h* W3 HLPSHORT        pSoundBuf = m_SoundBuffer;  e* A7 l7 k; [2 `' Z2 p0 x
INT        nCcount = 0;; b; C+ J; `8 r* M* I3 \

* P2 K1 @6 g: V0 N( M9 V' aINT        nFilterType = Config.sound.nFilterType;
( m& m/ o9 `+ J% Q- U
) Y; W9 C  l! v! J        if( !Config.sound.bEnable ) {
' [8 Y3 x5 \6 \  g! |                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" ~. b1 T0 z$ P! D+ P, w                return;  k* @  x: Y4 k: z. I
        }
2 h: v$ f% [- C5 P) F! f1 f; ^: |& |6 b/ }6 i1 m- s3 U( C; ?
        // Volume setup
+ `: n0 ^% F& T1 M( \# w6 p/ E" i6 s        //  0:Master) R- k. F8 Q- T
        //  1:Rectangle 1
( ~: \# n4 s3 ]7 [        //  2:Rectangle 2( I  J8 s* z, B# {0 N
        //  3:Triangle
/ D; k+ j7 ?9 l3 R- P/ c; x        //  4:Noise: V& ]7 E) Y7 i- s" o! h0 j
        //  5:DPCM, V' u7 h# {0 ^& q
        //  6:VRC6
! r: o6 v3 v; e6 L0 W        //  7:VRC7
8 _+ J& ^2 R+ n. E6 s        //  8:FDS
& ^4 U. n! H! F* O        //  9:MMC5
7 p' w9 [) n5 o" `, Y        // 10:N1063 G. k. [$ d9 j# J
        // 11:FME7
. o  q9 y# @* J        INT        vol[24];7 ^% P* v* Q1 V" d) L
        BOOL*        bMute = m_bMute;
: ^6 w5 U6 A; j& v" h        SHORT*        nVolume = Config.sound.nVolume;
. K- f0 `# B+ }0 ~! Y- ~% m5 ?, v6 Z5 Q% e
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;, Z: F# x3 Z* z1 J

  u/ T" \# L7 |/ a6 J        // Internal
- U( I" h! @- f        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
% q' b. l! u: b  Q8 {        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;8 s/ T4 e( @' `. r. F' H
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
" I* x1 j* i" ^0 S$ Y: @8 T- F        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
5 T3 M1 a2 i' ?7 a6 |/ l# |        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;7 P9 v' _; K4 y5 D
5 h5 W, x8 O2 L  B3 U
        // VRC62 r) B% D! M$ C( ~: s
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& O+ \+ {5 f5 k! L. v/ z        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 E/ Z) i  z* i/ @6 E' f* J        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# }3 C/ g' p9 P+ i6 Q' C

, N3 \* y6 Z* \3 \        // VRC7
+ \6 C3 G$ u+ s  [- o, I, e        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
1 ^, T- M% o" x9 [6 ?) A! y( {. B8 e+ _! d
        // FDS
% j2 t% I# ?+ {. L- z        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;+ j# P5 ?: U) y2 {

$ t4 \% _* U5 B% Q+ ^        // MMC5/ L8 X  k7 `9 z2 q, a7 x
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ l+ e; k9 j8 ^: b) V        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 K5 ^9 V; J) w8 G& A
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 A, [, b7 U# ~* f
& c" }- o' C2 F' x
        // N1062 ^8 D4 k' z1 T% E! Y6 M
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ E' G7 G' n. P3 u
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% f; R# [" e% C4 Q        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 z9 t# Z" z- L% L0 W, j
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! m" Y5 \% b) J3 G
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) ^7 [9 C5 T; Y8 N, }7 A5 @* F
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. m0 d. J  }( ]2 s! s3 F7 ?; n2 e
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 n; z% i0 [! c8 m  _+ d4 |        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 w5 ^5 K% G5 j6 T5 T

6 U9 z! [0 c# R7 s) C. f6 r        // FME7
1 h* `7 V& I/ o0 o6 [& E3 X* _7 d        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 }" i; }6 {3 ]: ]0 ~- Y
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' r0 U% X- |: Y# T
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! C* ^# z9 q$ e% D+ _3 x
' X* b9 B3 F$ l8 S9 C# y3 |//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;3 N# M4 L6 [7 ]
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
" O/ q* y2 d. [8 X" g# O6 x4 D: u
- A4 G$ c2 z7 H, d9 o3 \        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- L1 B: F1 D# o4 ]- [6 a) F8 k        if( elapsed_time > nes->cpu->GetTotalCycles() ) {8 ~; m' }+ d5 r$ w6 d, u
                QueueFlush();
3 g) m3 Z, t4 }" M' W        }
! d1 U+ S4 R# Q  s! |) I
+ c! {, }8 ^" e. C8 Q7 L% b        while( dwLength-- ) {" ]) A& X8 D, D7 Z! K) h
                writetime = (DWORD)elapsed_time;  J6 ]4 G+ f- G

- i2 @; ?) A% M1 Z, \! u0 n                while( GetQueue( writetime, q ) ) {- T# @; T! I& }! R
                        WriteProcess( q.addr, q.data );' J9 m; T- l1 |! J$ j6 K- y: o* r! K4 X
                }
. z# U+ f; q, h$ A' g
  m3 ~: `+ W8 _2 Q: H' w                while( GetExQueue( writetime, q ) ) {
2 v. g3 B! `4 F  X; e/ Y8 F+ U" ^. R                        WriteExProcess( q.addr, q.data );
3 A% W8 s+ {! }, ?: Y                }
' ^; A( Y4 l7 u9 D8 Y
: ]. G6 r3 D0 A+ O                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" R6 f8 X5 i- |                output = 0;! B! m% u. M& ?( o" G* r( v
                output += internal.Process( 0 )*vol[0];# @# \/ C) q; x/ L' p! x
                output += internal.Process( 1 )*vol[1];
% H; V, r2 n! n                output += internal.Process( 2 )*vol[2];
$ b3 Q8 M5 F. ?( S                output += internal.Process( 3 )*vol[3];% R0 K0 C* `" q* k9 S# J" J
                output += internal.Process( 4 )*vol[4];6 ]- F; w, O( A" \

% {& q/ |$ ]# j! {                if( exsound_select & 0x01 ) {+ ~* Q. o1 Y* N; _
                        output += vrc6.Process( 0 )*vol[5];( C, ?4 C' ~7 ]- B+ t2 ~2 b9 g& T
                        output += vrc6.Process( 1 )*vol[6];6 ]9 r: e. W2 @- k& m3 `
                        output += vrc6.Process( 2 )*vol[7];7 C8 F$ W/ _: `- A& \: L6 j/ U; Z4 c
                }
7 p0 {- Y! C% ^3 @: k                if( exsound_select & 0x02 ) {6 R8 \  V7 u6 Z. x* z% X" K" {5 u
                        output += vrc7.Process( 0 )*vol[8];! z/ y  E. d4 p& k" [  X
                }
! ]* ?# `& p. Q: T3 E* `                if( exsound_select & 0x04 ) {% B& X4 d. \0 p; U, m. K( {- c% G
                        output += fds.Process( 0 )*vol[9];
. I7 p% X2 Q! _0 l                }
5 o5 x, ~$ N0 }3 z8 I2 O" q3 R4 Z                if( exsound_select & 0x08 ) {* Y5 i" M& F4 ?
                        output += mmc5.Process( 0 )*vol[10];
3 u/ p( A9 Q9 u                        output += mmc5.Process( 1 )*vol[11];
$ `/ X9 N! H8 l1 |5 }* n" p' t                        output += mmc5.Process( 2 )*vol[12];0 @5 Z+ E8 C% N* `4 v
                }6 f/ l9 E( U& H  ^5 k+ m
                if( exsound_select & 0x10 ) {
/ ~1 A: t5 x" D                        output += n106.Process( 0 )*vol[13];" M( `' h% k1 G. T5 n* h5 ]
                        output += n106.Process( 1 )*vol[14];+ e" H- ]2 M! J/ ]0 f! ?) {
                        output += n106.Process( 2 )*vol[15];0 N" M9 w$ x1 R1 a
                        output += n106.Process( 3 )*vol[16];9 \, P8 S2 V' a7 c! ~
                        output += n106.Process( 4 )*vol[17];( j9 ^. p9 n$ \
                        output += n106.Process( 5 )*vol[18];9 N. E# R% e! ?, v6 H
                        output += n106.Process( 6 )*vol[19];
8 V* c* H7 x  o5 U6 @                        output += n106.Process( 7 )*vol[20];- U7 P# @  @( }1 R
                }! c( Q( M% g+ T3 {1 b0 _& J
                if( exsound_select & 0x20 ) {5 V8 u3 `3 i+ w. K9 G. y5 D
                        fme7.Process( 3 );        // Envelope & Noise9 y6 D0 l% _7 G% W1 ?& _2 ~
                        output += fme7.Process( 0 )*vol[21];
6 l3 T3 e: m; A1 U, S% o                        output += fme7.Process( 1 )*vol[22];
. a* L: a, s3 `0 n* c, V                        output += fme7.Process( 2 )*vol[23];
9 r) n% @( m7 _+ F" I$ A                }& v; ?- a* M6 _0 U( v4 ~

7 V+ a) b! ~; G9 c" Y: R( K                output >>= 8;" p. @" n# @( U/ R7 U# E8 D
* P/ x3 d7 q; W6 K$ Y- J
                if( nFilterType == 1 ) {$ p  s. N9 L% r4 B# S
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), ?0 u0 h: i! Z& _6 L! Z
                        output = (lowpass_filter[0]+output)/2;
" @; ~. d8 E5 s  ~0 P0 I                        lowpass_filter[0] = output;
# e5 k3 Y9 p: h( B9 U                } else if( nFilterType == 2 ) {3 I5 }! L7 Y0 Q4 i8 J
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ }; K2 y) U4 o- P& _( {                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: ~3 u7 C6 x, k. s  \! Q8 u2 e                        lowpass_filter[1] = lowpass_filter[0];
) a, N( t- k7 u8 g                        lowpass_filter[0] = output;
) G5 P" @- B, K5 b% P" p                } else if( nFilterType == 3 ) {& m) o; V% C* _4 p7 l
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)( [: V+ {. ]6 T/ u) t0 b! j- [# K
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
. u! _5 b0 o# C  V7 a, w                        lowpass_filter[2] = lowpass_filter[1];& ^9 J# T. q) @1 u
                        lowpass_filter[1] = lowpass_filter[0];$ c9 V2 ^0 m  l5 e. K
                        lowpass_filter[0] = output;+ S9 p; Z/ w3 z( l; @
                } else if( nFilterType == 4 ) {
6 `9 S: j" A; G' P% T1 m5 I                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& C! n1 }; Z5 c4 F% j0 {' ^
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;3 }+ o6 I9 R& M
                        lowpass_filter[1] = lowpass_filter[0];
  K# o5 S: M7 `# z+ K# R                        lowpass_filter[0] = output;
3 y3 U8 F# V( Z& C                }9 t" V3 ]; _, X4 I5 K5 N& Z) W

. k/ U2 ], ]1 e% d6 I3 \* N' J#if        0
& \% o" ?- G3 a9 F  e                // DC惉暘偺僇僢僩
# {( e% D% F- \6 R                {0 d! ^& e0 M8 B
                static double ave = 0.0, max=0.0, min=0.0;5 ^0 {7 Z* }" r( H  k6 r2 A  v
                double delta;
: e' N  w% k( V% f                delta = (max-min)/32768.0;: F2 t- D9 R1 u3 f" ]5 _& W/ J+ g0 ]( F
                max -= delta;
2 g3 {, `8 R+ a$ Q$ Y1 _                min += delta;
$ A. I3 Q5 @4 d                if( output > max ) max = output;
( w) U- U7 b7 Y% [  I$ s                if( output < min ) min = output;6 p  P- a7 Y1 z0 Z; u2 M' A
                ave -= ave/1024.0;
/ h# U- o# V4 @* g                ave += (max+min)/2048.0;
6 x# c  R( h. G% F5 b, I. s                output -= (INT)ave;
/ w+ [- J. n2 _+ O2 i                }
9 W4 H( h' M0 b- k& d7 R6 p% [#endif
5 Z$ @- e4 F2 x#if        1
' p+ m( K* V/ m" H. b1 A                // DC惉暘偺僇僢僩(HPF TEST)
! k$ r' v& |, u2 {- X" u                {
- V! o# p. `3 u8 T//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 B3 c9 i/ M: l0 D                static        double        cutofftemp = (2.0*3.141592653579*40.0);
* K3 G8 R5 L! d                double        cutoff = cutofftemp/(double)Config.sound.nRate;
: R" L# m5 A/ C  T  n4 w6 _  n                static        double        tmp = 0.0;' G, ]# ~3 O$ n/ l
                double        in, out;, ]! a9 }  R4 p  b+ _7 }

4 L. k2 U: h+ U+ J: m0 z: z4 o5 E                in = (double)output;4 t& ^! b! s  @8 Y4 V, I6 J
                out = (in - tmp);+ M: P: s, C$ h  e" w
                tmp = tmp + cutoff * out;
9 T- u2 g6 V( d: J9 ^7 Y+ J$ r' L& k$ _# w" s
                output = (INT)out;; m5 A0 x3 n- E; |3 F8 N
                }2 s/ t9 K4 Q9 a$ b! ?
#endif" V& M. f3 Y) v2 D2 P/ u* D
#if        0/ d" Q+ q% a  K: l0 t6 A2 N
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)' r. b9 N1 q9 l' p; y' @
                {% }# c# S+ w  @
                INT        diff = abs(output-last_data);
4 v0 T; y0 {4 \* ^1 t% C" n4 r                if( diff > 0x4000 ) {
: a$ h; B" J0 t# e                        output /= 4;) _5 F% }7 H+ x4 T; o8 w
                } else 2 v/ i( [% D+ e6 v! C6 u
                if( diff > 0x3000 ) {
8 l. y3 R% R& H4 \: g# Q& \                        output /= 3;
. f8 h. u) ^3 _- y                } else
6 A9 H$ x/ p+ a9 q8 X) y                if( diff > 0x2000 ) {
! t( e4 x5 a6 x5 R                        output /= 2;
/ K9 ?! p$ \$ t8 ]6 I. I( F                }
* S' d0 _1 F' s. Z8 _                last_data = output;
3 h! B- D& K- C+ J, @. `% u                }
8 l: J2 Y: i! s  k$ q9 ^& N/ C+ d6 i#endif  A4 ^5 j" e& k( i
                // Limit4 e2 \7 U3 \6 k, Y" \& D
                if( output > 0x7FFF ) {
1 |3 Q/ \( V  u$ J; w7 @                        output = 0x7FFF;( z& `+ q" @* `0 d7 T+ A
                } else if( output < -0x8000 ) {3 J- ?# x0 q" {& G! i2 E. V
                        output = -0x8000;0 E$ v; D0 Z6 F& p6 h$ e
                }& g9 T" w& ?4 D9 F, Q

( g$ r7 r2 ?* _. K# R, T                if( nBits != 8 ) {
" x' I- z; d0 E8 K7 Q5 T                        *(SHORT*)lpBuffer = (SHORT)output;
5 a) R: M3 x- x4 o& p; ^                        lpBuffer += sizeof(SHORT);
6 C! |, Z( g% M8 i8 ?- `                } else {
$ G- j$ s7 ?1 P2 r# g, S                        *lpBuffer++ = (output>>8)^0x80;9 o' J( f0 ^" A3 {
                }
9 G9 n4 {1 W. n/ I) N( D5 N8 l- I- a- g2 ^
                if( nCcount < 0x0100 ), C/ g" V3 h3 ?& Y8 F. W+ H
                        pSoundBuf[nCcount++] = (SHORT)output;! Z% J6 `6 A+ N# o3 Y/ ]8 V+ ]

  l; ]# \& }5 `, `# {! V; p//                elapsedtime += cycle_rate;
5 T; c: i0 j( b# a/ y- z                elapsed_time += cycle_rate;
5 o. ~" i' w( b) c# H& I        }5 O: W' J" r8 n9 x$ ]  W( D
7 {6 g- @* N# q# ^* }; d; e& W
#if        19 i* n! q$ G5 D' y
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 l+ m8 N/ G  [5 z; j3 V
                elapsed_time = nes->cpu->GetTotalCycles();- Z* V0 C& ^/ N8 @  Z/ Q: X
        }
# w. Y  q" t) U5 U# `4 q! B- C        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {. Q! w& S( j% Y7 p3 g8 ~5 `0 X- V
                elapsed_time = nes->cpu->GetTotalCycles();" m; d2 I# @1 v+ o# N2 `) z8 y: [
        }
3 f: s6 G% x. t& {3 O#else
+ S- `! {, ~5 l4 p& y* _6 d        elapsed_time = nes->cpu->GetTotalCycles();
3 e9 Q5 b! I4 K, ^, i* r4 m! M% m#endif
1 l. q9 N" s" `% r, G9 M! Y}5 s/ @- k% ]7 g& O- B

$ ]0 K7 T' r  [+ S// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ A# |/ U$ P& C. @INT        APU::GetChannelFrequency( INT no )
* I! Z% V" A& K{5 v/ @. ~; g# I' I7 J
        if( !m_bMute[0] )9 H% @; l7 w% Q. E/ n6 k
                return        0;
$ T  i. S* }, X" K7 V+ \
& w8 D$ t( p6 ]0 {/ q: y        // Internal; P; o7 d/ j; K' _5 `) K
        if( no < 5 ) {
' b$ C0 X8 |) @                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 Y% E4 w2 A5 ?9 ~5 l
        }
. u" h) `5 Y4 w  N" M9 P+ K3 k        // VRC6
2 _4 f9 c1 E+ H6 ~0 O        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* d% }9 W4 L* G# h: b7 r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;9 x' r3 u0 R2 g3 d  _! o$ M
        }! s% p! K+ s3 R0 \
        // FDS2 h# Y; m' R& {6 V8 A* Q$ D
        if( (exsound_select & 0x04) && no == 0x300 ) {3 J; |9 S; g  }" d% O7 q
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
2 [0 @6 G7 I2 D6 Q        }  }0 B6 G  y( G7 z! R) t
        // MMC5
! H, z/ P$ N2 c* K% v        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {3 J& t+ R) r, G: m, q$ o/ Z& r
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  l7 Y- C7 K( z/ E" i) L* ^7 m
        }) f0 q, m$ C* i1 w+ \. x; V+ `- l
        // N1066 U; r( s! e0 p9 x
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
8 m# r9 X. [. u0 S9 q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;6 D' r! ?- H; E8 O* Q' L
        }. N+ B" F! V8 L( `
        // FME7" }% ]" Q  C4 g9 D( c
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {! E! ?. [  B7 h. a/ H$ _
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
. e6 x& E( G$ ]  r; k) d        }
5 f0 \7 |  M7 z) h! ^        // VRC7$ z4 a* [/ e2 ~2 X
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {& [3 m% y. l- y* p1 Z& y, {
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;8 B9 v2 l1 X4 H
        }
8 t/ }7 r8 p# s' F7 u3 B) g        return        0;' @" s, L: H4 O9 P6 @
}
7 W+ u( J8 Z8 ?" \1 d% y
0 `1 s; F5 ?; Q6 f+ M0 L// State Save/Load
  z; K: P6 F) P2 zvoid        APU::SaveState( LPBYTE p )
8 n1 I# }: ~/ Z% `3 h{- q, {& a! p6 R
#ifdef        _DEBUG
7 y  Y4 }# i! x* l% dLPBYTE        pold = p;5 Y  p$ K) Y) t$ m
#endif
% @% [7 y, v0 h# u# z0 W1 |6 W2 D2 K! {1 J6 w2 B2 d; L
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
4 q( G! h3 |0 ^! ~2 z7 x        QueueFlush();
! r- r4 O  \; X4 N% {( A- a
1 \0 n  J) {2 x5 X! ], R        internal.SaveState( p );0 g' k9 Q/ d- m2 |$ f* ?
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 U/ h& d9 P) P7 V# K+ D& b  m( \/ o
        // VRC69 n* {6 T3 v. T: f" B
        if( exsound_select & 0x01 ) {- j" ?# o7 z/ E' ?. Y- ?
                vrc6.SaveState( p );
% c! Q. {5 L/ m  _9 ~: d) q- @                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& U- |8 Y7 x+ s, r  Z; ~8 N        }/ H, E7 E# ~/ t' u2 d4 J
        // VRC7 (not support)
2 ^& |4 v( j3 O        if( exsound_select & 0x02 ) {5 e$ ]" i- @) H9 _; [0 Y  T/ i! b
                vrc7.SaveState( p );) e- N8 \  X0 ^1 D! ]( R* {
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ z3 U4 |2 P# K
        }
7 @7 j3 B1 n) G/ n; x        // FDS
* g! D) j. f' w- f        if( exsound_select & 0x04 ) {7 `5 `2 G* I; m; U$ D% K3 @& }
                fds.SaveState( p );
' ^: N, o: v( l2 p' ^  b- Q4 s                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 s' W+ J7 u7 z! g
        }
. i  v) q# C: ~+ L& Q        // MMC5+ P0 x% z! m( X5 s1 b1 C0 N
        if( exsound_select & 0x08 ) {# y7 ?" f8 ~# v, b
                mmc5.SaveState( p );
* v/ j" b, `. ]. W& J& S( G5 C                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# |& c$ S8 q% O9 \0 h5 p" j
        }  d# [3 n) v0 }6 X
        // N106
5 i; A5 l+ u  U9 @        if( exsound_select & 0x10 ) {8 {9 V. O/ h2 b6 a3 N" U
                n106.SaveState( p );! H/ J, U2 P+ J0 |" |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 {: y7 ?+ E$ y5 v% {+ {5 H
        }
( d+ h9 n$ x$ N7 i6 s+ U        // FME7
0 S/ g  j/ c$ `+ h        if( exsound_select & 0x20 ) {; O2 K! Y4 g6 h5 h7 s/ G+ d$ B; f
                fme7.SaveState( p );# Q  P, o: H; T/ N: ~4 S2 T% Y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ ?2 n: J5 _6 F& b+ h7 c        }/ C6 B  t0 y. Y6 ]. [

! {  _- [6 h2 L# L7 Y#ifdef        _DEBUG+ i  N9 w/ B  o) z% i1 O
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
# Y' g6 ]& W( W! |9 _' A, v#endif
5 W/ c5 c8 s. A7 |}0 T9 V+ m, J+ W  v) p

4 k% H# y; y. B1 Vvoid        APU::LoadState( LPBYTE p )
* y' A% q1 E  |% d+ _{
  R* n" |# ?" H) |6 O$ h+ A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡: r% _; \; ^1 {% S6 r+ r" f
        QueueClear();+ _6 ~4 N! H: e' u2 w! k. r
! R" v9 p6 _! e9 m
        internal.LoadState( p );4 s, C: l5 d; g3 Z' h
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# B; ~3 O$ K- u$ p8 F" l3 H) W; m
        // VRC6
: s2 n1 H; M& @) r2 T8 P        if( exsound_select & 0x01 ) {
  s9 i, {$ q- M) p( I$ A                vrc6.LoadState( p );
& c1 x0 H( v* e0 j0 R7 A! w# H                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" C0 o, X, F" G" y$ Y0 I        }* L3 B' N* w$ ^6 d( K# O
        // VRC7 (not support)
2 S) L8 P/ D- w% Y$ r( \        if( exsound_select & 0x02 ) {4 E$ i& [# i! {8 q$ f8 Q
                vrc7.LoadState( p );
1 a9 P* O3 E; f; Q6 @8 O                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
5 J) N1 Q& \$ u. S- F* H& i: p        }6 {+ d) C( G; k; E& Z/ I: s
        // FDS4 B" _# E  {; ?# _: }! s3 j
        if( exsound_select & 0x04 ) {3 }! S; y0 V; j! m8 I# @' v/ u- [
                fds.LoadState( p );
* p6 x  b* b/ J3 `7 {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ r3 \1 W% h9 v! ~% P( H
        }! t6 [$ o- v: M! w- V% ~" V
        // MMC5
/ N3 H& X" b3 n; s* q& d        if( exsound_select & 0x08 ) {
/ H  d/ J1 I. i' b: `                mmc5.LoadState( p );
/ M# K; |; [! W+ t6 y) _) _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 v- [' K% Y) G% k        }  O6 _; v3 u- B$ b
        // N1068 O) ^4 r8 Y. ]2 x4 V0 L' c/ k) \
        if( exsound_select & 0x10 ) {
, ^: r0 O1 e/ @+ b* S0 M                n106.LoadState( p );" f' p) t3 p" g1 l+ f. g
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 S# E0 z* U6 O
        }
# X. I$ _8 w. B9 B+ }4 O: C        // FME78 e, Z1 `$ {- {8 Z
        if( exsound_select & 0x20 ) {
7 W$ i9 P+ p4 k' [                fme7.LoadState( p );* l# P$ N9 W' M8 b; N/ A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: Z7 Y9 M5 f. ]. A% ?' ^* A; m        }1 G' w5 \! A9 O8 y* c4 ~
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
3 [+ Z! j& k. W7 X, k可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。' Q' v# X+ [8 v& O0 ?
感激不尽~~

, k! u. h. P) Y+ ?5 a3 [  V恩 我對模擬器不是很有研究,
. ]: J7 S- X2 B& i) p& V雖然要了解源碼內容,可能不是很困難,
4 v3 X6 ?( R, n8 o6 W8 q不過還是要花時間,個人目前蠻忙碌的。
( j8 |2 d4 P, }. ]! F2 N5 y5 M( }3 n! N: y
給你一個朋友的MSN,你可以跟他討論看看,
4 k8 G+ H9 s9 N4 O+ U: p0 @他本身是程式設計師,也對FC模擬器很有興趣。
+ O- M/ K( J6 C
5 i2 y, f& Y/ b  ]! MMSN我就PM到你的信箱了。
0 q. {4 n) C! Y# \: b+ [- S& z8 W
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 $ R* C4 U/ }0 M$ o7 S+ h
呵…… 谢过团长大人~~

) o8 V  B! j6 q1 Z
# B/ x& j' e. P& j# B$ O* V哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
3 u1 ]' L8 U6 A0 r) x) y, F团长的朋友都是神,那团长就是神的boss。
; x8 `. L: s3 N& |$ b" `  U( w  S
哈 不敢當,我只是個平凡人,- n0 `- d8 `8 {
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) {" }' X; y0 s! p* K6 EZYH. Q" a) X' J! ~* k/ @
QQ:414734306! e5 R: {$ D% e  c; l$ R4 }
Mail:zyh-01@126.com8 u$ }* }4 {6 w# p

6 N% E. ]5 H, R+ e& z) d4 N他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 4 C! Z1 s9 s' ]. X$ J
再次对团长大人和悠悠哥的无私帮助表示感谢~~
! J$ U# c9 z) D+ @3 f
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-14 07:57 , Processed in 1.085937 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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