EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?% s$ ]( f6 E" k/ [3 t' X
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. u* h0 g: W/ c楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 a1 d) }3 n" O; w这里有相应的模拟器源码,就当送给大侠了~~
. o* R8 G7 e+ [% Y6 I3 jhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 ^7 K$ K* X/ T能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ D1 H9 u6 q- H9 U' }1 J8 t楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ Z% ?3 u0 P. g( N" \5 |
这里有相应的模拟器源码,就当送给大侠 ...

, O, O2 e* p5 M1 ~聲音部分(Audoi Process Unit = APU):
) \; K: P6 ~  |% M' f  j5 ?1 a5 |8 a' z.\NES\APU.cpp' u! x" j5 G: [, B1 t! I' }3 R4 F
.\NES\APU.h7 f$ I& M6 y- I( N9 m

8 ^/ c5 X: c" d; R. Z2 u
! j; O$ e" \! J; |9 {影像處理部份(Picture Processing Unit = PPU):0 P& ^* ~! o9 X5 y" A$ S$ y- q
.\NES\PPU.cpp
& s! t7 K, C( O2 G1 b2 o/ J1 n8 Q.\NES\PPU.h
0 W3 w4 y; V) D% t) }8 P& Q3 l& R, s- J" r* b$ A- r
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ s% p5 Q9 r0 a3 L6 ]1 ?4 X8 W/ ]) E
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ H$ F4 _& Q* u+ I9 T; y& X( s
//////////////////////////////////////////////////////////////////////////: ^! Z" ?- ]4 N, ?8 A# B
//                                                                      //
* u& v9 R0 b% B5 e# y6 ]//      NES APU core                                                    //
: C9 I, B3 j1 z; Z, r1 {5 C//                                                           Norix      //  X' Z# I- e+ R+ g$ P1 F5 X
//                                               written     2002/06/27 //
4 g' X7 v& M. Y; [! h1 C//                                               last modify ----/--/-- //
+ Q3 w" S6 I( Y//////////////////////////////////////////////////////////////////////////
. v" x9 T- j3 H& S8 m* d% {#include "DebugOut.h"
& y# g4 i1 z& ^) Q4 W& `3 p#include "App.h"4 ~+ q0 X  y; K
#include "Config.h"
  K* W% r& t! ]1 a$ q' t; h2 \. C8 n# h& o: K& c, E4 O0 `# T
#include "nes.h"$ W9 U1 v, A& O8 c0 Y
#include "mmu.h"/ ~5 N9 f7 R. m- v
#include "cpu.h"
- j, S5 A$ a3 g/ z1 T6 i& b) Q2 i#include "ppu.h"8 O& Y( {. A: o* W% i+ b
#include "rom.h"9 ?2 s& b/ R( X: G, I
#include "apu.h", U- I* o: b5 k  y  f5 X
, ]& b( N4 o) d
// Volume adjust8 F9 [  L6 D0 A* E- T# w" t. y
// Internal sounds; \3 M5 d( z! C0 T+ P9 R
#define        RECTANGLE_VOL        (0x0F0)
( ~" Z( x3 W4 C# A% Y, S#define        TRIANGLE_VOL        (0x130)6 C/ |, D/ ~% A) {  K
#define        NOISE_VOL        (0x0C0)
8 F8 P3 g) n# Z$ A. H  r8 t#define        DPCM_VOL        (0x0F0); q* \2 t/ N$ P- y2 C
// Extra sounds
- [. u5 d) I5 ~- N  ], c1 l#define        VRC6_VOL        (0x0F0)
- m# h2 [# @. G$ K#define        VRC7_VOL        (0x130)
5 D  c$ H2 {7 }. c* I2 ]+ ^: G( @3 Z#define        FDS_VOL                (0x0F0)" W& c0 f. a! t
#define        MMC5_VOL        (0x0F0)
/ `9 t6 Y+ N. R# N#define        N106_VOL        (0x088)
1 f( b) R/ D7 c( I3 A8 Q2 r0 w, S#define        FME7_VOL        (0x130): v4 n  R8 h; Q  z

$ B5 m: f' B, D& {# {1 S& }: [! rAPU::APU( NES* parent )
: q* O; u" ]' z2 d2 w1 @{2 H8 e; j' ~7 Z- s
        exsound_select = 0;! C/ H+ l& B8 H/ D

# F5 e* H: J* @0 a, U4 U        nes = parent;% y) ^8 ~: S8 F. G$ d0 u
        internal.SetParent( parent );
% h- E1 ?5 k$ t. M2 a' Y7 c
2 X+ @# k5 {8 x) a2 m: ]5 T5 E        last_data = last_diff = 0;5 U( y! r( D9 l* G, o" S' k4 F

# j8 P2 v, B8 y7 V0 M8 p. v2 b4 R        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
( s0 j7 G  q. |0 |( y5 Q5 z; N
* E& N: {3 R0 r. a  d! E        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );: f# L0 _; n, g6 W  ~; o. g
        ZEROMEMORY( &queue, sizeof(queue) );
& @. U" q9 p. `        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" ^- {6 L: j) Z7 e, k& m
( }  [+ T4 ?. ~: [+ C* D        for( INT i = 0; i < 16; i++ ) {
( U3 d) W3 ?7 w7 ]                m_bMute = TRUE;8 W4 x! v6 V' q. J/ u8 y7 s7 [
        }
2 U& d1 Y* z4 Z! x6 {}
: j- N% W# P  }* o# }$ D
+ \6 b9 {" j6 dAPU::~APU()# i0 y0 l; U8 A; k
{
8 T( ]7 [1 ~, }}
2 b" Y7 l8 C& S9 I
% U% g- D# ?1 H# |) R; ~void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) z  l: m- ~0 S+ X{
0 \4 l# v* r2 M3 \" R8 ~1 M6 J3 N+ G" Y        queue.data[queue.wrptr].time = writetime;
* L  e  m: j2 d( E$ b0 Q6 }        queue.data[queue.wrptr].addr = addr;
" ^. |7 q; o/ g% A        queue.data[queue.wrptr].data = data;
6 h, H" F7 g5 \$ H2 Y8 Y- F9 X2 I        queue.wrptr++;
% T* K# X+ l1 m7 ]' p0 W$ x0 J' H        queue.wrptr&=QUEUE_LENGTH-1;
. g  l* s& H# x6 E( b' C        if( queue.wrptr == queue.rdptr ) {
/ _4 x+ l4 }) \                DEBUGOUT( "queue overflow.\n" );
4 X2 b" ]% ?* N& J. h9 A3 c        }6 L3 b; e5 S  Q" v
}* i7 `5 w' y# W9 {. _" D# E9 L
% e" s& ^1 K/ T. m1 ?
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )" ^. T$ r# i; i3 b* m
{7 Q  ~/ v# K$ X: P3 S
        if( queue.wrptr == queue.rdptr ) {0 S9 F: z  z) M! O8 s( D
                return        FALSE;
$ j% n+ A: {7 h/ s        }! y' y( A2 c1 u8 K5 B
        if( queue.data[queue.rdptr].time <= writetime ) {
7 v; a! ~% v$ C0 g  @" q/ z                ret = queue.data[queue.rdptr];' H8 I: ?1 c/ M6 Z) x, z/ N. X, a* m
                queue.rdptr++;
2 d" h/ |( V6 J# g( i6 l2 Z                queue.rdptr&=QUEUE_LENGTH-1;+ R5 x% i  F$ N! h8 d
                return        TRUE;4 y, ?% R' c9 _  y& u
        }
  i5 h& }9 o$ [6 O: A        return        FALSE;
; Z2 `* q( u8 k$ o/ i& _2 i. |" F}5 R8 m. p$ n' r( g( D. h
5 ?7 c. N2 V2 H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )1 i) h: Z2 |' x$ V; v- |# I
{
6 H8 \8 o, F4 v/ C. ?% N        exqueue.data[exqueue.wrptr].time = writetime;
; \4 C; `- k% h! {        exqueue.data[exqueue.wrptr].addr = addr;
. v" M) `, q3 P1 L$ X/ ^        exqueue.data[exqueue.wrptr].data = data;
3 b& r4 {4 D- z; Y6 E; [        exqueue.wrptr++;
1 i- k9 b( I( t0 a        exqueue.wrptr&=QUEUE_LENGTH-1;4 X8 C5 ]' p$ g9 m+ ~/ R% h8 _
        if( exqueue.wrptr == exqueue.rdptr ) {& Q: w/ e, M* Z7 C
                DEBUGOUT( "exqueue overflow.\n" );
, |( h/ b! _4 l        }
3 ?" ?) m' d( F. G  ?' q* L}
) `2 l1 h& n+ K1 d
* S1 U& |4 T. ?7 dBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 I" A, I9 F! c2 B, X0 K9 s6 M{, b5 k: d6 X" L3 S8 N% n1 |
        if( exqueue.wrptr == exqueue.rdptr ) {
, V( i4 b+ X! g5 d                return        FALSE;& h; k" X4 |, y$ C& S. W* S- C
        }. i- H$ {$ [9 a* _
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' X8 i6 I9 b1 b! S
                ret = exqueue.data[exqueue.rdptr];
, m3 i% t7 `2 F+ Q  x4 S& J4 ^6 m                exqueue.rdptr++;- G" G; C6 m/ m9 I) F
                exqueue.rdptr&=QUEUE_LENGTH-1;
2 g) x0 e3 j+ d3 I' m                return        TRUE;2 U1 U" ]$ |. J* D; R6 u% \' P+ F4 ^
        }  D* z5 s- s( Q1 t
        return        FALSE;' G  v% {6 f7 w
}
# s; Y7 r" Z  H5 x/ U" `: |, S; s1 [/ _0 A2 `
void        APU::QueueClear()9 j" X2 g$ O7 J/ ~
{
' ]2 B6 \- x; a9 |7 s8 n        ZEROMEMORY( &queue, sizeof(queue) );
0 K0 `7 |" J2 d* N8 N9 \  w        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ G+ y  S' V9 f; r3 E
}
1 Q: u" u& Y  J- X2 A# S& y3 c2 Z( r+ P5 K1 N
void        APU::QueueFlush()0 g+ q6 B1 }4 n% W, A" t
{) g! k2 `# A4 K2 ~  F
        while( queue.wrptr != queue.rdptr ) {5 C: Q4 ^+ L3 x0 |6 ~; z/ e) G
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );7 b8 L+ G) b. q
                queue.rdptr++;
( P' B: j  Z+ P0 W* m                queue.rdptr&=QUEUE_LENGTH-1;% M4 K4 V5 w5 E0 }( N. N& R
        }2 z8 L2 T% o( H# g/ i" z

9 J+ w! ]  C  {9 b        while( exqueue.wrptr != exqueue.rdptr ) {: {" F- q! P( [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );) j3 V: |* D, |0 E
                exqueue.rdptr++;/ [4 z& t( Y' i$ Z
                exqueue.rdptr&=QUEUE_LENGTH-1;
! s5 N% V: Y/ P8 @$ |* }$ y  s+ i        }
- `, z1 _1 Z7 ]. V}
' E8 Z$ z9 v: L) O* n
, \2 y, u% V8 l6 N" M" A2 v0 c) B/ Cvoid        APU::SoundSetup()6 T$ E0 o$ W2 [- P
{
1 P$ F; M$ y5 B& ^* R6 G        FLOAT        fClock = nes->nescfg->CpuClock;
$ I2 h4 L6 A4 i" z5 ~3 v        INT        nRate = (INT)Config.sound.nRate;0 U. }7 X# m4 X9 L* O& H
        internal.Setup( fClock, nRate );
3 J$ U2 D7 @) s- [        vrc6.Setup( fClock, nRate );2 |, o& S7 w. i. Z0 Y
        vrc7.Setup( fClock, nRate );
& e6 B, `, @) \5 E        mmc5.Setup( fClock, nRate );7 D" n- D/ c- C4 \
        fds.Setup ( fClock, nRate );- }, k: ~4 Y) c  Y2 D. \
        n106.Setup( fClock, nRate );
- S3 R% d8 n& I& G5 m8 N        fme7.Setup( fClock, nRate );
" q7 V3 t2 o: D2 w4 w}
8 Z9 t) d1 @% @8 P6 S, H' f. I% Q
void        APU::Reset()( k. N$ a/ ^- i# I- \
{6 n7 _8 S+ S: f, c1 B( ]: t: `0 I
        ZEROMEMORY( &queue, sizeof(queue) );
2 M1 q/ S/ t6 e1 `6 J        ZEROMEMORY( &exqueue, sizeof(exqueue) );- ]. u# @7 a6 @" m! P' B' C! N! c# A3 s
) }' i) i9 c) \' L0 r' E1 x( l: u8 m
        elapsed_time = 0;
. I) _5 c% l3 J( Q8 U* I+ K
+ `- |: A5 t9 t9 ^) z        FLOAT        fClock = nes->nescfg->CpuClock;4 k' x/ x. W9 g9 u; R0 U+ D4 \% l
        INT        nRate = (INT)Config.sound.nRate;+ }- U7 i. N/ C8 W# |4 F) E0 k' c
        internal.Reset( fClock, nRate );1 S' Z( a9 c, B: p9 T* G4 F
        vrc6.Reset( fClock, nRate );
/ A% g* B9 P% Q- S2 ^$ G        vrc7.Reset( fClock, nRate );
# d" D3 w0 C$ R) C/ s        mmc5.Reset( fClock, nRate );; W) U* Y& X. ?7 R% Z
        fds.Reset ( fClock, nRate );
; W6 P& g7 U7 @6 d3 f0 C; r        n106.Reset( fClock, nRate );
, h" }3 }# G. z        fme7.Reset( fClock, nRate );" ?4 t$ M5 w# b! }) d$ T9 J
& f- `2 V! ]1 O( m, B8 K$ j& C
        SoundSetup();
6 I. O0 B$ X; ^5 I" X$ S' T# G}
  F' v5 `, B1 t: K9 k& p5 @
7 H! A$ X) I+ Z: l9 ?5 Q( a# _. Uvoid        APU::SelectExSound( BYTE data )
. n: f1 m$ S; x% D{! e4 `/ K, ^9 z! v) }
        exsound_select = data;* h" H" [$ J% {6 P8 O$ G+ |" t
}
  D2 t4 P1 [" K. g8 F
2 _* d# `/ p+ h' H2 _5 ^BYTE        APU::Read( WORD addr )% }+ x9 S% `5 S- O, W& |: W
{
) {! k4 X2 P/ k) s- R! u        return        internal.SyncRead( addr );
9 h, {9 \; g( C; @/ B* x}8 U3 X3 t  I) I, A( z% K

: b5 X4 v, p7 H8 }8 v1 d' @# Wvoid        APU::Write( WORD addr, BYTE data )/ @2 E. G2 N* n3 ]
{
2 g+ j0 T1 y2 H& Q' G        // $4018偼VirtuaNES屌桳億乕僩
- N0 E( f6 J# I) C% x8 }5 c        if( addr >= 0x4000 && addr <= 0x401F ) {
+ ?% _' v9 ~" D+ r' \                internal.SyncWrite( addr, data );! j# g; {8 O6 u
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
( X4 D* K& R4 g        }. X* ^. \* i  V7 f! e7 n
}
+ h+ l6 c' u+ r; s: [- n1 _* n5 _# g/ I/ R6 m
BYTE        APU::ExRead( WORD addr )
1 m. B" P' S8 ^% \{
. G; a! ]9 x. N2 _3 G7 kBYTE        data = 0;, M3 y$ [' e* h4 e! M/ j/ F4 L& ?
: z& P) r$ z) \) r" }; z7 x
        if( exsound_select & 0x10 ) {) z8 m6 i; D$ I/ z8 a7 ?
                if( addr == 0x4800 ) {
6 y. O! V' i) M) b; P! z                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) }4 V: F& t0 k4 N- O5 R                }
& S; u! N3 E. x  ]        }
; Z+ x- j4 J/ ]  l/ a        if( exsound_select & 0x04 ) {
, D2 m/ P9 }4 ^! n( D& a* ~% |                if( addr >= 0x4040 && addr < 0x4100 ) {2 p$ V; C: l$ S: N& P! H, z
                        data = fds.SyncRead( addr );
6 Y& E3 I3 F, m# ]; K' W5 E3 C                }6 g! X6 x- M3 J! G
        }( d# l# l# W; x$ q$ T  s1 w3 N  T
        if( exsound_select & 0x08 ) {) P1 b% ]) m- Q, Z, p- G
                if( addr >= 0x5000 && addr <= 0x5015 ) {
- r2 x1 ]: ]$ [$ ^                        data = mmc5.SyncRead( addr );& d7 j& g, e6 a* S" v
                }
2 i! _, f4 T. f8 D" C% J4 f# o        }3 n5 @. i4 |- E5 k, G6 b

" A! N; x5 X: }- x        return        data;
* v4 W& X. g2 t# H& f, D+ |}3 |* t( G+ @" d: j6 m  s8 @. [; ~. q
: P+ Q1 |; Q+ C: Q) q6 [1 ]7 H4 p; r2 ?
void        APU::ExWrite( WORD addr, BYTE data )4 v6 [& T5 A4 `! X+ i
{! X- u/ B, R+ A% A( a
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 l0 E2 w# F- o
+ I7 L  [( Y" y) W4 g8 k/ u        if( exsound_select & 0x04 ) {
) j! r' A6 z* @8 ^% a3 K6 N; [                if( addr >= 0x4040 && addr < 0x4100 ) {9 G! ?" ~+ v& d9 [6 v* w; ]
                        fds.SyncWrite( addr, data );$ v9 V$ Y) c6 m) V  H2 ?
                }
& e4 d# X& _! @" d8 M% D  H* n+ j# Q        }7 G* R. B$ Q$ @; e" H$ u; Q
% J; i* G& I8 v- C& ^
        if( exsound_select & 0x08 ) {0 R4 [! u" g! f, z
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! u4 f; r8 D/ P9 q& H3 Q                        mmc5.SyncWrite( addr, data );
' q& r+ S$ o5 m6 C                }2 U; f% M  t1 A% ~0 G$ {
        }% _- \( I0 C3 [1 N; b0 h! b1 T
}
/ s# J3 Z: b% ^" W% Z
8 }/ U( C% t  @void        APU::Sync()
/ ^( q& [2 e* i2 G$ `! T{
/ D; `  k5 \& |' o4 s; v}
2 y- [+ i- J# U$ q6 [! X6 u' h2 m: B" Y; s
void        APU::SyncDPCM( INT cycles )5 V2 o, n; r9 L6 M% M
{
8 Z1 o- `) q1 U$ s, d# K3 @        internal.Sync( cycles );
$ v& T5 h, _. f  u0 B& q- k) P$ r# ~+ y. C: {! d7 ?
        if( exsound_select & 0x04 ) {9 w' I0 A& D* R4 N& {0 p/ M
                fds.Sync( cycles );. ?" {; q) U" F# ~5 d2 ?
        }
, Z, k( G- l/ O, Y& M$ x& y        if( exsound_select & 0x08 ) {
5 ^: C3 t$ n) N1 a; X) Y                mmc5.Sync( cycles );. u4 i& s! t) b3 y+ \  `
        }) n0 [: ]$ g- b$ I  j
}# P; U% H: I; [. e
+ \5 N! x# @# @; L. \5 R
void        APU::WriteProcess( WORD addr, BYTE data )
  f" I, }+ s" K/ h8 m4 b1 W{. c8 v2 Y) f* i2 M. i& h0 x& H5 }
        // $4018偼VirtuaNES屌桳億乕僩
" ?4 Z: M6 D6 x2 o, D6 L; w7 g, V# ^! y% e        if( addr >= 0x4000 && addr <= 0x401F ) {
, P* B. \' l* Y) J2 K4 Y2 T; j                internal.Write( addr, data );
% w# Y% }$ }* [' E) H        }' q8 _2 _% A5 Q$ a9 n2 h! E
}
& D  d1 F! o1 i; Q) c: j& C' v6 a# h
void        APU::WriteExProcess( WORD addr, BYTE data )* [) Y5 A) M. O; C2 O$ H6 o$ x
{
% a: ^) A$ o4 v, @        if( exsound_select & 0x01 ) {
$ Q" l; q, j& J( r2 c, s, \- c8 e                vrc6.Write( addr, data );; u# \4 j1 }7 j' ]# b- H1 z, W
        }
$ B: K( G8 A  V- z        if( exsound_select & 0x02 ) {
7 m- b( A7 e) p+ G& e                vrc7.Write( addr, data );
  T4 \1 e7 H  z8 I6 B8 X! A3 w        }
3 g+ _- m8 x/ E. I# P9 R9 G  q        if( exsound_select & 0x04 ) {5 D2 a- }" O1 G9 c8 Q3 c
                fds.Write( addr, data );
9 m& u9 ^/ V, c8 |  p% B9 [- b$ u        }: B1 S% }0 p7 b0 ~8 J+ a" \) T' f" S
        if( exsound_select & 0x08 ) {
8 [' r+ l! t7 A' y6 Z                mmc5.Write( addr, data );
+ f$ U" ?( [+ N$ k) O3 G        }" u+ N. I7 {; r  Y3 M# I0 I
        if( exsound_select & 0x10 ) {# u$ Z" k3 k9 ~' @# E
                if( addr == 0x0000 ) {0 ~2 l! p4 ^: F) M: E
                        BYTE        dummy = n106.Read( addr );3 v1 Q- D1 v: b7 ]
                } else {- j9 u: l# s- T  V- f& j; ?' O
                        n106.Write( addr, data );
! J& O* a+ m" O9 C( f' Z                }1 d& Z& T; l  T" Z- T4 ~9 {
        }$ L2 a3 Q6 ]9 M7 \$ C0 ?1 ?5 i, E
        if( exsound_select & 0x20 ) {0 g# [6 i. g6 f9 O; g. N
                fme7.Write( addr, data );
! O$ A; l0 w* V8 L) L5 k, v        }# u5 g/ l; n# q$ P
}
! q8 X  @2 u& x. ~. j
9 T* l: H  ?- |. C9 ]+ |void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
; X; Z4 F' R$ N4 i3 i{/ L1 C, V/ J* U: I4 W# s% s
INT        nBits = Config.sound.nBits;
5 T2 V( a( T8 ?7 V0 [3 {6 YDWORD        dwLength = dwSize / (nBits/8);
' g1 `# @! y! f! \# C/ ]0 UINT        output;
0 D0 P& _% L1 T1 I! e4 zQUEUEDATA q;* Q, w1 e& x( w" g; w% G
DWORD        writetime;
" W" D9 X2 Z- w' y2 }, m: @: ~; K+ K+ X7 J/ J, {
LPSHORT        pSoundBuf = m_SoundBuffer;
* ?; s, R$ E4 W8 i) F& S+ cINT        nCcount = 0;  p% E5 ~" w5 [
) T  V9 e) {& }8 ?3 s' B( T
INT        nFilterType = Config.sound.nFilterType;
. V" S& X% F$ i' `# U* _1 s' I. Z! r+ b+ S, V7 p
        if( !Config.sound.bEnable ) {
7 b) [1 b! w- {4 f- L8 F                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
" [/ ^1 b# B* w' q! l; J! d( q  U                return;3 m6 e  d8 [2 A
        }
# n# g% F9 ]1 O8 p: \, m. K9 q9 Z4 j: H
        // Volume setup/ i# u4 i4 y3 p; a6 U# c: T  o, e
        //  0:Master" q/ L* X9 u8 z( c9 s& \
        //  1:Rectangle 1  r0 x4 m, q1 ^& @( y3 r: O
        //  2:Rectangle 2! H8 o2 W) K' x' ^; s8 E
        //  3:Triangle
0 f' Z. O# W$ s+ O9 K        //  4:Noise7 M& y( p) V$ k) M6 ]; _
        //  5:DPCM4 d7 |2 j& v' m- t+ C
        //  6:VRC60 A6 @9 y4 ^: K3 o! D1 @: w9 _/ H
        //  7:VRC74 X, A' v! A; S- z( S1 j5 Y
        //  8:FDS2 l$ g% z, S' p" Z
        //  9:MMC5
6 e* V' T' w! a( Z# ~* @        // 10:N1069 M: n+ I  V( i; y
        // 11:FME7
% y- y& u- |* e9 B        INT        vol[24];
5 ~. x2 ~3 }: |        BOOL*        bMute = m_bMute;
  a- d* z/ ~! B6 \0 M' q/ d        SHORT*        nVolume = Config.sound.nVolume;6 A- m3 Y' l$ b+ S% v# T

8 Z7 j! z! X- ^+ t# D! g8 L        INT        nMasterVolume = bMute[0]?nVolume[0]:0;0 c: V) f3 c6 P+ o' e9 A) r
/ p6 G* v- m5 j* U/ K  \
        // Internal
4 g' l9 K; A$ ^        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! e- e4 h& z: n# a- D8 h5 h        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
$ W9 v; q1 s; i        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 B7 R0 O* [  W9 @1 n; N' o1 k1 c$ c        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 [, V. t3 x4 ?5 V        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& p: H8 D/ a: L6 k1 w4 }
( H5 N2 B  I: u' g0 ~+ c9 @  s) _        // VRC6
1 v+ s, \* q' g        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ s- K3 t* {& y5 @- T
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! O- x' z1 c" Q' E) \8 r7 e# H
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: X; J# |+ j- d) g
2 W6 R" y2 {6 N) t7 L        // VRC7  O/ f- F- U8 p/ l- [2 v+ V
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;! P2 A. B$ }- h/ I+ I

3 Y) F$ J: H6 i0 o0 N* I        // FDS
' @; M: a$ e7 p* E* q        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 [! v* S% R  p* s: J8 P
: L" q4 ?: Q+ Y        // MMC5
: P8 Q" v! [0 H, {3 s        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ q* [% H, W( g! A        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' v$ z* h. L& y* b. E3 ]
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 \+ E0 y! B+ c0 ^" S; v: M4 N- l& u3 [+ p1 |! E
        // N106  _4 G" `1 L0 I! ]) o6 Q0 W# P
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. M5 k" P1 L4 ^& K+ ~8 ^3 L
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 c, p5 G8 C0 {% ?1 M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( T! d( x& A* O        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" X* h. W% A3 g
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 Y% `$ s' K: S; L. i1 B
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) Z- Y1 |) T! ?0 g* ~+ a6 H# h# e
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 d4 z) k  I' b. X0 Y        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- O( I5 N8 p: ^

. {" p" {- g4 w. H& L  |9 w7 Y. n        // FME7
6 r, d  m+ l) z8 k& S# G        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 q$ j: _; k" j        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 j% P: ?: Z$ Q8 {, s) f+ W  a- j
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 Z. w- q! j$ \0 Z
5 i9 o! ?2 {  @- l% K* B$ g5 @
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ d' Z+ F" y6 S        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 N/ }2 p# q- T+ D! P

' H! P1 U, I" m        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟5 E4 E. M% g- l/ {& g1 j
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {  w- m# y7 o4 S+ C9 ]0 L4 C/ ?8 W
                QueueFlush();
1 u3 p' Y+ D9 [* J        }9 B! [, u4 y7 }
) E' X) D: x1 v+ g) [9 U6 Q3 b
        while( dwLength-- ) {
4 U  m3 w2 p. P  Y) ?# W                writetime = (DWORD)elapsed_time;
' z! Q; f. u* R! u+ i" v0 D) ~$ l4 E( w% x7 l: m! [( V
                while( GetQueue( writetime, q ) ) {
% g) h1 M) ?; ]& F                        WriteProcess( q.addr, q.data );
* P% S! s. j+ s  b' o. Q: j* o                }6 {1 T1 I+ w& D* S2 @( r

0 J7 J1 P, L5 R1 f& z( V                while( GetExQueue( writetime, q ) ) {
8 W  d* L5 {, N: D' B/ f# Z                        WriteExProcess( q.addr, q.data );7 ^2 G  W; x7 G! E' G2 ~
                }, |' S/ z  ]  d, \% Y

1 e. I- n  K1 I# y; [$ e# F, \1 P. f                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 k: L. Q1 x/ G7 Q  z8 z
                output = 0;& {: B- T  A5 a+ h$ W: Z
                output += internal.Process( 0 )*vol[0];
) w6 D) b* J% h2 q7 S4 o" l3 Z                output += internal.Process( 1 )*vol[1];
7 Z. u  k% O2 ^, M' y  \5 B9 T                output += internal.Process( 2 )*vol[2];
: X4 D7 @$ u: A% q' V* ]- x5 O. ~                output += internal.Process( 3 )*vol[3];
  ~( k3 L' s& |; k" V                output += internal.Process( 4 )*vol[4];
; W' J# a* `! z6 C7 w/ e! A7 i, S- s7 `5 L! k- d
                if( exsound_select & 0x01 ) {
; I5 K7 w  G" ^0 l                        output += vrc6.Process( 0 )*vol[5];
. W: N  _& G- T3 e+ Y                        output += vrc6.Process( 1 )*vol[6];
, Q6 L5 ^( b1 }                        output += vrc6.Process( 2 )*vol[7];
8 H5 ~( L( ?7 n5 s5 X+ J0 i8 r                }
. @5 k2 b: U, H6 M1 V; \                if( exsound_select & 0x02 ) {
7 p/ f1 X$ {7 G& N9 q                        output += vrc7.Process( 0 )*vol[8];
/ \& D( {4 L3 z, |" X5 Q: W                }4 ~$ |4 ]6 @3 W4 v9 R9 S
                if( exsound_select & 0x04 ) {  e" q+ y: D8 D4 h' b9 B( g- D
                        output += fds.Process( 0 )*vol[9];& F' |8 w7 w9 S' d) f0 o
                }
% n& P8 y) _$ ~8 D                if( exsound_select & 0x08 ) {5 ^! x3 M1 a" ^
                        output += mmc5.Process( 0 )*vol[10];9 P/ n1 O- K: y3 N0 s
                        output += mmc5.Process( 1 )*vol[11];0 ^! x# l- ?" Y. T# v
                        output += mmc5.Process( 2 )*vol[12];" _3 N; i' Z7 A' Y8 h% m4 B
                }  j! C: }: a, v) b
                if( exsound_select & 0x10 ) {2 ~# v9 b8 ?6 Q+ j9 l7 x
                        output += n106.Process( 0 )*vol[13];
$ t( [- |4 ^9 q3 X# w1 z                        output += n106.Process( 1 )*vol[14];
4 V/ q7 P" |  K- w                        output += n106.Process( 2 )*vol[15];% h; Z9 k, W" {1 ?/ V" z+ J
                        output += n106.Process( 3 )*vol[16];9 c% ~# ^9 v% Y9 o/ V8 c' A
                        output += n106.Process( 4 )*vol[17];
! ~" v# H( Q5 c+ j% F7 a% c                        output += n106.Process( 5 )*vol[18];  B* {. ?( |7 M3 T
                        output += n106.Process( 6 )*vol[19];
2 p+ t; S- D1 Z5 M; C" h                        output += n106.Process( 7 )*vol[20];# `+ l6 W# N& Y9 ~0 u
                }
/ Q3 p" ?9 z1 Y. A" O9 {1 u& A                if( exsound_select & 0x20 ) {( t$ d, P( y: o6 J0 A) ^
                        fme7.Process( 3 );        // Envelope & Noise3 F& J5 i0 Q  R4 Q3 Q  V3 @$ W
                        output += fme7.Process( 0 )*vol[21];* S) A! O) l! L# O# M$ ?8 \* @
                        output += fme7.Process( 1 )*vol[22];
$ H& ~% [, `, K/ B' ]; R8 b                        output += fme7.Process( 2 )*vol[23];' N6 ?0 _9 F- v/ y8 v6 O, |3 g
                }4 l6 `( l* ]7 d, m% b
" P' t, S, l% P$ P
                output >>= 8;
7 ~: q6 Q5 P3 {6 a1 E4 y3 A$ c' m$ Q" ^
                if( nFilterType == 1 ) {2 @9 {% C. A1 c" `( [' P* a
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)! r# `% w/ K1 k  F: W
                        output = (lowpass_filter[0]+output)/2;
+ P; R/ ]9 Z% c0 \; T' q: i                        lowpass_filter[0] = output;
9 j! _& I2 |6 O8 _. D5 B! ?) y$ \  G                } else if( nFilterType == 2 ) {# T! l0 i" o& k( j
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)) g9 p  p# A3 F# K7 B
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
- |$ }. e; v/ v4 W. g1 ?                        lowpass_filter[1] = lowpass_filter[0];4 D- u- F3 ?2 @% b- o/ Z2 N
                        lowpass_filter[0] = output;# {+ d: S/ U2 Z
                } else if( nFilterType == 3 ) {
2 R$ n1 w+ k& T8 a' u: `4 [* |" n- J                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
' z3 {$ C# V1 X. R                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# E6 X! z# T: [. X5 N                        lowpass_filter[2] = lowpass_filter[1];
2 {+ R& }9 t1 e1 F                        lowpass_filter[1] = lowpass_filter[0];
6 m! F9 }& f. z* U2 d                        lowpass_filter[0] = output;
) x* B7 L4 |9 a! M5 J1 A                } else if( nFilterType == 4 ) {: s% \7 t* ^) y5 w9 e+ d+ y8 {3 f
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)+ U# G+ r! s' g7 C9 b3 c
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
2 S) c8 {! W, y. I+ ~! u6 R                        lowpass_filter[1] = lowpass_filter[0];
" L( o. X7 J3 v                        lowpass_filter[0] = output;
5 f7 ^2 `7 M0 w  D9 |                }6 h0 T. i# s& V2 Y( O

5 q  t; _! s; j! M/ R0 l; q6 s" R#if        0
; f' ]1 W7 |  U! F7 [3 F& [                // DC惉暘偺僇僢僩
$ s5 j9 e% R' m7 [& G                {
( R, p& u) B% A! Z: M2 j  J                static double ave = 0.0, max=0.0, min=0.0;
; r2 a) a$ v7 o% a* W9 s                double delta;
6 v% \& p* y9 X4 b: W                delta = (max-min)/32768.0;
8 k" Z, G3 p' O                max -= delta;* Z  p6 u4 E8 ~- Y; }8 _4 ~% x5 p
                min += delta;
4 {! R4 ?' {% l, v' R! ]                if( output > max ) max = output;( S% K- T; W7 F0 G
                if( output < min ) min = output;
+ P& p* g1 P; `                ave -= ave/1024.0;( L  Y0 G/ g/ I: q8 H6 {9 N
                ave += (max+min)/2048.0;4 [1 B/ X9 z" d. f) l# H1 r
                output -= (INT)ave;' j( V6 S% m+ I- Y1 E
                }, }# ?' k) g/ v7 w" E- P
#endif
0 @3 o/ p( C: B1 ]# b1 ^#if        1
- D0 H7 ?8 @9 T' E; U, a# f% q8 C                // DC惉暘偺僇僢僩(HPF TEST)
$ R% p$ U  v/ u" F                {
, g" z. Q  X: m+ g# d//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- c4 s* _, h) J* D7 i! y, ]
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
8 n) K+ C) o1 u1 ^' l; e0 V! C                double        cutoff = cutofftemp/(double)Config.sound.nRate;
) l9 U. ~$ v; D# j                static        double        tmp = 0.0;1 K/ V: ~+ Z: Y, t% S4 e, t
                double        in, out;/ t+ X- V8 Z- U' U, ~! ^7 z

, M2 k, r# {6 A2 y) p4 j                in = (double)output;
/ Y0 A, G8 T0 t8 V4 s5 B9 W" _) r  w                out = (in - tmp);
' b) {: z, [/ |7 h                tmp = tmp + cutoff * out;
/ {4 c! a9 a6 J: R* f8 k! t3 Z1 s- B# \' U% J
                output = (INT)out;
, `- i8 j. w8 y) |                }
  _4 N& v: k5 D3 A#endif
/ F. j: ]* V2 X/ B3 P#if        0
3 K1 D2 L+ J- F! _6 p% X                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
7 A1 g, m" S6 @$ }                {
% v! e% {8 l1 t                INT        diff = abs(output-last_data);
0 X" j  f$ ], y+ z                if( diff > 0x4000 ) {
' h4 [# k  P+ @! ~7 d                        output /= 4;
* J# {( J2 P. s2 `                } else 3 u3 v4 k) d. L7 O8 n4 p; n
                if( diff > 0x3000 ) {; ^; i0 _! i% ?. c: K1 M
                        output /= 3;
1 f- N: x( Z/ r* {1 P" l                } else
& S2 ~! c0 u- E7 d$ q                if( diff > 0x2000 ) {: U: U( W  J  ]. ?* }
                        output /= 2;' _9 s# E+ B" v: ~& q
                }' n' L1 N6 H, {' C5 a, b* E
                last_data = output;  y' ]+ D/ O; t: T- x' r
                }! v, ]7 i2 H, Q+ J9 V6 Q6 j3 u
#endif7 I0 b' C" V! k4 N6 ]
                // Limit$ h: O8 j+ a2 x8 o5 X
                if( output > 0x7FFF ) {
  [: l4 I/ b% k( a1 k                        output = 0x7FFF;# x& \; t2 G7 b$ M9 F
                } else if( output < -0x8000 ) {
  l+ N! b/ J, V; k3 d7 f                        output = -0x8000;
4 [# S# b. q3 r$ Q/ p9 q& u                }8 k9 n4 D3 k& u+ N

, J5 r) l, Y6 v5 K$ e                if( nBits != 8 ) {4 }6 X% y' `9 _) R3 y: I8 D# B
                        *(SHORT*)lpBuffer = (SHORT)output;
5 d! k. S/ V$ ^) y. {                        lpBuffer += sizeof(SHORT);
6 r' |4 l4 w' t5 a8 F1 C                } else {
  K& r1 m1 X$ |' Z' q& L                        *lpBuffer++ = (output>>8)^0x80;8 z  w: {5 v. R' b' B1 ~
                }
; v8 j0 E8 h. C1 g9 `3 @4 \- @; @, }( T  u
                if( nCcount < 0x0100 )
; c) r% P& l6 [( d" J# t; j                        pSoundBuf[nCcount++] = (SHORT)output;
% ^/ ^; X  S9 f0 }+ P# J- h1 W- @' r& k
//                elapsedtime += cycle_rate;7 R: A+ i( M) |! g' ~9 K" A
                elapsed_time += cycle_rate;
/ h( R# \/ {3 p$ |" `        }
8 P  v1 L# R5 L1 [0 e1 p' j# ]! {3 M; `9 x: `5 y  o/ p% s3 z5 j. d
#if        1
, g0 ?2 h( @, n/ h6 u        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
, `. m' \1 V8 E& ~( e4 Q  y# C5 p                elapsed_time = nes->cpu->GetTotalCycles();
- x7 s# ^7 [" r3 I5 y        }
, t- Z& J4 d- T% _4 O; b        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
- K, H7 U+ q& G" Y1 F                elapsed_time = nes->cpu->GetTotalCycles();
3 e( L6 y4 P& X& }+ O5 X* L  y        }
' e2 ~: H, d, @/ F: R/ u( u- F#else
; R  z8 V1 v6 s& V9 O) j1 \. I        elapsed_time = nes->cpu->GetTotalCycles();6 p/ V! J6 k! Y) r
#endif3 q1 O! Y2 ~( k/ L- e2 s
}9 k* l) [0 |/ l9 }: I4 F  e8 L+ x

* C$ F& w" a: ]: S( p1 G, G$ w3 {  q// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 Q. Z8 c0 F" A' d7 m9 yINT        APU::GetChannelFrequency( INT no )# B! Y. v* L( H) N: r+ D
{
* S# Z9 V& I3 D2 H) ~        if( !m_bMute[0] ): o- Q9 d8 r) q' s. J' c- Y9 ?- K7 t
                return        0;
& G8 d2 s0 ~* d# P' b( P
; ?  H; G9 U+ \* L/ S( Z0 E        // Internal
  A) r1 ?* P, \6 t; c0 Q  ~8 m        if( no < 5 ) {
, j' v" T5 Q5 ~9 L. }- R2 T                return        m_bMute[no+1]?internal.GetFreq( no ):0;
  J4 R+ o3 R  Y1 M5 @8 [        }
6 V' f3 X7 f' @* H* }        // VRC6- H7 t& }) Z0 R& M
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
- \1 u" B( }2 X7 \& E                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
+ J3 n9 p# m, f5 G        }( D( R7 m4 D5 a, Z
        // FDS3 ^- ~! A8 c0 U
        if( (exsound_select & 0x04) && no == 0x300 ) {, F5 Y! c: E# X) @
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- r& e/ h4 c; I$ p; {4 _        }
& F0 C5 b# `) y6 J        // MMC5' E3 ]) ^, s" B+ m
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. y9 N+ z4 O8 g7 x. U                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;- F4 E1 U- W) [0 T& v3 b& o1 [
        }
) S, I+ B9 D; Q! H; w% \$ V' F        // N106
- f  z$ N* B$ `; m7 t        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {9 f) a$ g9 Z0 C+ y+ _  H9 l
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; `+ ~5 V5 b* w
        }
& }% Y1 t1 x8 V7 c# }* m8 b        // FME72 n, d0 E) E" r/ M# J  o
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
( q9 T% C: N* ~                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;8 x( l4 ~* a( m+ I- D, d
        }
* L8 E) P$ {3 Q/ Z% }        // VRC7, i* M; W$ R# l2 u4 z; r5 r& q( }5 S
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
+ v8 M' b2 z# r/ H                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;! r3 s) ?+ j; u/ A
        }3 d' q. O- q3 v2 ]% ]0 L! R! l
        return        0;4 E, U9 p" ^' v, S( |, i  f, }8 z2 t
}, [+ L; n+ x8 [0 d$ U
6 [! k7 e1 u* h+ _, g- g: G
// State Save/Load+ o2 D5 Z4 e7 Q4 {" H8 |2 f
void        APU::SaveState( LPBYTE p ), i/ G1 }( J. X/ p5 @( H- t
{# Z  \6 L2 p8 u* Y
#ifdef        _DEBUG
( l. R7 L! |, A8 pLPBYTE        pold = p;! r  y  @9 T" G: Q+ r
#endif/ l2 g( E" v& n( a9 h4 z
: J0 @* g( |1 ~: W) |) ~2 R( I$ ~* M
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
  Q  V6 B/ t' z( n        QueueFlush();
5 X# O8 B9 H1 a5 ]: w. Y3 Z
3 i$ o3 x; D* E3 p1 ^        internal.SaveState( p );
- d' t- F* ^2 r, v+ I        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& e9 y0 A& x9 Q7 }  Z

6 G7 R3 x6 R  Y5 e. i# Q! ~        // VRC6
' t- p" m2 Q- D& @        if( exsound_select & 0x01 ) {7 B, p# W( x: H; [: u+ n. V
                vrc6.SaveState( p );
; ^9 q! D$ D6 G* V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- o/ J  O' ]) W        }0 C8 H0 @& o. l. o
        // VRC7 (not support)
; q' U6 C9 }5 O( ?: }! I        if( exsound_select & 0x02 ) {1 _/ M* w2 b- W+ [( B
                vrc7.SaveState( p );
# T9 @8 ^: g* c$ @  y9 X                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 I* X' I: J% I- A- r5 r
        }3 c2 G0 q0 y, m( n9 Y
        // FDS
) k/ Z8 c; N* p- \% a% R        if( exsound_select & 0x04 ) {+ R' n# s7 h7 J2 _; x
                fds.SaveState( p );
1 T1 E8 R+ ]- ]                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 _0 }+ m- x- l- S/ M        }
  `4 X; R0 o  q7 M# @        // MMC5
$ y* H. f9 f' u2 {3 Y5 O; }' {        if( exsound_select & 0x08 ) {- P. Q% s5 C9 Y& j
                mmc5.SaveState( p );
6 ^" n* L" W  S) k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 `& `! ~! d$ S7 {6 m6 M: [        }
2 m6 T4 D4 u% b) U% O        // N106- p% _5 v4 V) G) }% K; A/ _& o
        if( exsound_select & 0x10 ) {
2 s; n4 |+ B9 f4 j                n106.SaveState( p );$ s4 J9 G# p6 t8 L0 H
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 T  f' ^' g. Q  v+ |
        }
9 Z( n* V; L2 ?% y$ n        // FME7) V* H) I1 T% ]& Q3 F% v
        if( exsound_select & 0x20 ) {
% z) a1 A$ i8 M) `4 |                fme7.SaveState( p );! y* ]$ j; |  N+ y- K
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ d# v: i  n+ `% H
        }1 Q/ ]& r8 q+ ^& S% |1 T

7 J2 V, |& O4 S5 T/ |/ }# F2 x#ifdef        _DEBUG
# ?  [" |& `/ H7 |# YDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- \$ ~4 q5 ~" p; L; t#endif6 A  \. i" |$ l, }' S; c8 |
}
6 x, y" j5 d& H8 ]; }( [+ A6 l
& L% ]' z* A" P' Wvoid        APU::LoadState( LPBYTE p )- Y8 Z* t4 m$ Y( a* [4 V4 d
{
3 B1 b2 l& L/ u9 n. F& `( c        // 帪娫幉傪摨婜偝偣傞堊偵徚偡" a1 b( I" w/ W. \9 q9 }! k
        QueueClear();2 T* a/ j  ~+ A) [

! `- y2 ?/ ?( `5 z6 O        internal.LoadState( p );
+ ?$ E1 b+ ~' }! V7 _, S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 T+ T* ?5 d! e5 ~( L$ P( @5 k' ^" ^  Z9 e; X. S+ ]2 ^% i
        // VRC6
6 }' e( n1 H, H        if( exsound_select & 0x01 ) {
+ w3 r7 U! n) ^                vrc6.LoadState( p );  q7 G' W6 M* g3 T& `  Q7 K
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; O1 _* Y9 s5 ]' r        }
* w& b/ U) A( p- ^& `        // VRC7 (not support)1 q- }6 H; i& X- V/ Y  n
        if( exsound_select & 0x02 ) {* D0 _8 I' {! T% r* o
                vrc7.LoadState( p );( S+ g4 g* l; I& W7 V5 \7 [6 a9 i
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding0 X5 H% Q  b7 p9 `3 I) z$ p! p
        }6 s. @/ ?( Q. B' U/ T: Y
        // FDS
: u8 E. V4 u4 K        if( exsound_select & 0x04 ) {. }% Y/ K1 Q6 }" u& x" _3 Q" }8 {
                fds.LoadState( p );
( j  c( W  i6 d: E                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& S$ G/ M1 f7 l; m, `; N        }
( e' j7 D1 |3 E. A+ {7 U        // MMC5
) b0 m; Y9 l, T, U+ @2 k        if( exsound_select & 0x08 ) {
* z2 S% F" ^  ]9 p- v2 Q4 S                mmc5.LoadState( p );
' ]1 @1 l! [+ P( `                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 C6 \) Z: L, a  H' U- X+ K        }
$ n5 Y! I; s" H9 H9 o        // N106% r$ E$ e* D2 }3 A7 n! I* b
        if( exsound_select & 0x10 ) {
8 k, n2 l+ n: E7 o  F. Z$ E                n106.LoadState( p );
0 t7 ^9 k/ z; S                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* M1 Q" u* Y1 t: a        }+ \; w  P% c& H1 M$ {! G0 K% m
        // FME7) t0 }1 y) J' s, Z9 f, O5 S$ X  r
        if( exsound_select & 0x20 ) {
7 l7 q6 {1 g2 N' Z                fme7.LoadState( p );4 Z7 \  @6 O7 p
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding) M8 e; o" Q' o) S" a
        }8 i4 o  I/ P6 N9 @( M2 A1 [
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
3 f5 F* }3 E, J, u. D可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
- R  _% @+ z6 S8 i  z) K' R感激不尽~~

3 N( ?0 s, A* I* @1 q+ _( S恩 我對模擬器不是很有研究,+ g/ F0 y0 s5 p% J5 e+ ~) R
雖然要了解源碼內容,可能不是很困難,% [% U, w4 Y% {+ K: J- D
不過還是要花時間,個人目前蠻忙碌的。
0 w; j  z+ {, i* i1 e
" B1 j# g1 \* o給你一個朋友的MSN,你可以跟他討論看看,
, S& [1 D6 q2 M2 M7 M; A他本身是程式設計師,也對FC模擬器很有興趣。- G+ M4 e+ k  |
$ P+ U$ r. ?1 i3 k" m/ Y# ~9 p
MSN我就PM到你的信箱了。' [9 G" o- ~; X' u- s0 Z
8 e- s& ?9 i9 `7 t8 u" l1 ]
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 + u( H3 A! v( Z8 ?8 Y/ Z6 H
呵…… 谢过团长大人~~

* E! w! J0 ^- X  e* Z, r
: w% d+ D4 P1 g  Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
5 v& R5 ^2 P. _0 [团长的朋友都是神,那团长就是神的boss。
& `; h$ k- V5 r* d' H$ S0 k2 m
哈 不敢當,我只是個平凡人,
% N9 x$ ]: n9 s3 R; D' ~) \要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 c4 B- J% t& j* vZYH! t! w6 W! Y, L
QQ:414734306
3 G/ [6 }1 W# x5 X1 c1 k2 `Mail:zyh-01@126.com
: V: w4 X5 a1 i  U1 i2 z# a: C3 D- U+ v* y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 l) a( K% A  `* a
再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ i+ e8 ~; \- P( X* X+ S6 f不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 15:55 , Processed in 1.073243 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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