EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 I: W: u( h! C9 r3 \) \* N
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ b7 Q) z3 X& ^9 C; m这里有相应的模拟器源码,就当送给大侠了~~4 q* i9 V! h9 R$ a
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 + `  @8 g: j0 b- ]
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。) T  N7 U9 ~7 o5 R
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ ]: P" e0 k) \. ?
这里有相应的模拟器源码,就当送给大侠 ...

( {% Z9 w' b% O4 O聲音部分(Audoi Process Unit = APU):" ^# d, [# g1 R6 B5 I2 _$ a
.\NES\APU.cpp
4 c8 |, }3 B) ?2 D.\NES\APU.h
8 \9 ~( U% p  _
" ?6 Q2 W+ _% Z0 K' P  q2 i
2 |, c# K% L5 t! C影像處理部份(Picture Processing Unit = PPU):' x9 y9 f0 O3 d4 W: @& v6 W
.\NES\PPU.cpp
2 y" H/ E' w; e  C.\NES\PPU.h
1 m' r9 u9 O; B1 k6 e# O9 x8 H
4 D( T1 S3 O- a如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 ~8 z* y# R+ n; n  M7 o4 @1 X(由于很多专用术语和算法机理都不明白,所以看不大懂……)
  p  ?8 B6 t4 ~0 I' @" `: p//////////////////////////////////////////////////////////////////////////
  N& `# }) E0 T/ g8 u+ x//                                                                      //
- L) Y/ E: ^$ }0 k. `4 E6 \: y6 B3 s//      NES APU core                                                    //' e9 L5 Q7 J& ^7 J2 S# n: b+ }
//                                                           Norix      //
9 r) M% n0 s: M( e8 h//                                               written     2002/06/27 //
- R( j3 L5 s0 ^' j! J) N# t//                                               last modify ----/--/-- //( V1 U* M. u& L; k6 V
//////////////////////////////////////////////////////////////////////////' |9 y8 I% L; _0 `/ ~/ D
#include "DebugOut.h"
5 m1 v$ ^; `/ x# Q) U  h2 m" x#include "App.h"
# Z! D$ G& _; x. _$ }# s#include "Config.h"  y- z0 Q) _1 c5 n

- S- N' P7 k, w5 d#include "nes.h", [5 D/ R0 W2 `
#include "mmu.h"3 W9 ?' l0 z. g: M- A4 [
#include "cpu.h"1 _  A  `) H7 Z1 R
#include "ppu.h"
7 ]( B! b0 L( [7 M#include "rom.h"+ H, U9 e: b) r
#include "apu.h"( y/ a& S3 j0 u0 P: j% W6 E9 s
' t: G* O5 U) |- p% t
// Volume adjust; P' @6 p0 P7 O2 ]
// Internal sounds7 z1 L& L$ a  y. Z
#define        RECTANGLE_VOL        (0x0F0)/ g+ t+ k6 v, u( ?6 z: l
#define        TRIANGLE_VOL        (0x130)) x; ]2 {( r* b: k5 b# W. D
#define        NOISE_VOL        (0x0C0)  D! d) Y$ E2 `( |5 ?) S6 _- |
#define        DPCM_VOL        (0x0F0)) |$ J6 ~: S: i# C+ Y: |% b
// Extra sounds2 g2 S) W$ v# d' I, f' ?; o
#define        VRC6_VOL        (0x0F0)& _$ A$ @1 f" J. J6 Q& n. `/ V
#define        VRC7_VOL        (0x130); R8 x1 {: d  I
#define        FDS_VOL                (0x0F0)
1 U7 {  k) A$ |9 t5 C! T#define        MMC5_VOL        (0x0F0)( M* B5 c8 {& {; Z+ y
#define        N106_VOL        (0x088)
2 K' y; F. ], s9 }9 i" @2 j- S#define        FME7_VOL        (0x130)( N6 C9 y7 N8 F* g7 a( `

( T1 U' q- T. ~0 m& EAPU::APU( NES* parent )+ a# W4 s6 p  u/ }( m7 S
{0 H9 ~! c* h9 j7 K+ q2 q+ M6 k
        exsound_select = 0;  s+ W8 w' u$ c# ^8 E, D

( b5 ~( |6 N: S0 g        nes = parent;
$ r) @  U, y7 g8 M! e* K        internal.SetParent( parent );; q0 t2 z4 _# }  [& B7 y) ?1 Q

0 m0 Z( H. _( M# b5 J        last_data = last_diff = 0;2 ]5 P# C+ r  z. E. G/ h: m& X  E

; x/ P8 R/ v8 j- u6 T        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );6 M' Q5 [% G4 t4 B# A
6 {7 z& w' z# B7 L+ L' w$ _
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );% L2 j: g1 a0 I% h% \& P
        ZEROMEMORY( &queue, sizeof(queue) );
$ J5 v+ Y* F. @" Y; y3 x1 E# d6 A        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ J5 N3 q. X2 C5 P% r0 P

! z) Z6 y( {. b8 K$ n: O        for( INT i = 0; i < 16; i++ ) {9 O  x3 A. N! S4 k/ i. m  x
                m_bMute = TRUE;9 ], T0 y, ?+ F7 r$ |
        }
* s0 S+ i2 h& F$ K* @+ p7 a0 m}; n0 B* o6 M" X) N

  z$ [) `/ l# ZAPU::~APU()
; D4 q" C  a: L# l: R- O2 o{
4 ]$ u+ c  @+ n7 F& k) w}
5 d; j5 f9 d+ |: K1 _: Q
  L9 O* F  G+ k3 n& r7 v3 y* Dvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
6 M$ Y0 K  M# C4 g* T( K. m{( e; y- m/ G1 t; z! V, D9 y
        queue.data[queue.wrptr].time = writetime;5 \* P) d0 F0 w$ H  k: _
        queue.data[queue.wrptr].addr = addr;$ g7 P6 N: ]* o  P, q
        queue.data[queue.wrptr].data = data;4 }2 Q$ ]; ]% g
        queue.wrptr++;
# n( n# X/ P) P% s' y  Z& j        queue.wrptr&=QUEUE_LENGTH-1;2 ~- L/ S5 X6 p- T% h8 \
        if( queue.wrptr == queue.rdptr ) {  Z1 R$ _/ @, u9 c$ U0 r# }! @
                DEBUGOUT( "queue overflow.\n" );
* J5 f% U! d# Z% c        }$ U( V, p- r9 t+ D& }6 Q
}
4 m' d/ k" j" t9 w% |- c
4 \  X( P* m0 @$ I& [BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )% V6 O$ j# i9 p
{. A4 @- J7 F6 C6 L2 Y: z7 {( |
        if( queue.wrptr == queue.rdptr ) {
8 o: }) d9 d; K2 |% s# N                return        FALSE;) A$ U, u6 X$ _: Z& Y9 Y' c: v9 ?
        }
! e4 L& n, e& R: s9 N$ b        if( queue.data[queue.rdptr].time <= writetime ) {
2 x- ?8 U- [. b4 D5 B% ]                ret = queue.data[queue.rdptr];3 T8 V: f. \& d- ~$ h
                queue.rdptr++;
  C, D, Q. t- z) \/ r/ s. @5 }                queue.rdptr&=QUEUE_LENGTH-1;5 z' z6 g. z" {" P6 U# {$ W
                return        TRUE;5 d4 z9 a1 ]. s3 |* r
        }
8 w" [* n, n7 W, u        return        FALSE;
. \3 p" j2 d0 {; ~! Y}
% g( H7 M/ T, g7 f8 v
$ i1 M8 B; j3 Gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )* w( A) N) i0 h2 f
{
, n4 B% K/ t" m% j+ ]$ x4 ?        exqueue.data[exqueue.wrptr].time = writetime;* c/ R7 _- l% r' B6 Q
        exqueue.data[exqueue.wrptr].addr = addr;
# B0 C- s! i+ ]- C3 `8 \( J        exqueue.data[exqueue.wrptr].data = data;# j# q9 w- S1 w' R1 j1 Y( s# b" U
        exqueue.wrptr++;& J! f0 n9 ^7 o! \: A2 w* b
        exqueue.wrptr&=QUEUE_LENGTH-1;
. ?  D  R' a* I' O7 P1 q' |0 u        if( exqueue.wrptr == exqueue.rdptr ) {
' P7 Z, m& F: X* i; w! y                DEBUGOUT( "exqueue overflow.\n" );
& Z4 ?3 O1 a, D        }
+ ?- P  n+ A' ~7 Q! Z}
1 P) H8 K) x$ v- s- q
8 T& L9 G1 S8 J2 pBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 ]& g: ^5 G0 O+ ]' ^' u; o{% S/ Q* I$ ~6 d0 ~
        if( exqueue.wrptr == exqueue.rdptr ) {
" J% v( A4 t; U* |/ ?                return        FALSE;8 W7 _' S0 n8 w/ K  K  @; j
        }
+ W( W: E0 i5 H6 d        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% Z8 m4 r5 `% _! a" N% _2 V
                ret = exqueue.data[exqueue.rdptr];5 Y& N0 k- T( B7 N" `
                exqueue.rdptr++;( L& g: c2 N1 _/ ~) o8 s
                exqueue.rdptr&=QUEUE_LENGTH-1;
. `# k4 M0 G2 p1 _: }4 b0 g0 ]3 }                return        TRUE;
) p* x1 o/ r8 R, u        }6 O- z' o8 q$ a3 B+ X& d
        return        FALSE;+ W# L& a' H  ^5 \/ z
}, t% B6 x8 d5 ^4 ?7 a6 h5 x% \) d, N' Z

% u' Y) l. r6 m7 W1 |4 o; U# tvoid        APU::QueueClear()
3 w3 o0 [8 }1 e. o( A{; N" T9 L( r. q
        ZEROMEMORY( &queue, sizeof(queue) );
  M2 C: x& |' Z" n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# A: P$ u: \$ N' R}
- o9 G; n+ C& B# H4 Z/ a
: t5 k: M; N+ t5 W1 s' w; c) A2 fvoid        APU::QueueFlush()
$ M# s7 g% D5 l! ?. g& \- j! E{" M5 K4 m8 R" M. b- R4 \9 e
        while( queue.wrptr != queue.rdptr ) {8 L" o% h$ z! F, D" E' H
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
9 A/ l3 R! R9 B" G) K  Z# w                queue.rdptr++;
: ~3 y0 F: [# b2 T                queue.rdptr&=QUEUE_LENGTH-1;
5 f! B( C! V/ n+ c1 @1 S1 l* }        }$ V3 j: G" n* r' Z( l. n5 d6 k  E
! H4 G7 t3 C+ i+ p( X* r1 k
        while( exqueue.wrptr != exqueue.rdptr ) {7 `( f: B9 l3 J+ p& K
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );( x5 w9 v4 z. A, y% P9 ~! D& [' Z
                exqueue.rdptr++;& _! d# O* P" L: E$ O" ~2 A
                exqueue.rdptr&=QUEUE_LENGTH-1;* j; k' U3 u) w0 }" B  @$ v
        }
3 r4 i6 Q( |. n) \4 Q6 Y7 z$ J9 o}, r4 x* N6 O; l' w( G3 c$ {

. h; w. n$ n5 s6 m. A7 N! w9 Gvoid        APU::SoundSetup()
# [) L, A& Y6 \' @5 e) V" f{
& t' U, I$ ^  v8 L6 ^        FLOAT        fClock = nes->nescfg->CpuClock;
( E9 D  g& O* |( {. b6 o$ ]        INT        nRate = (INT)Config.sound.nRate;2 A3 u4 V4 e, z! z2 X
        internal.Setup( fClock, nRate );6 y& P8 Y/ K$ J4 b9 H3 B' Y
        vrc6.Setup( fClock, nRate );
8 p6 w. [7 {: f' _- K, K. s1 U        vrc7.Setup( fClock, nRate );
6 i6 a2 g( t7 I7 n3 M        mmc5.Setup( fClock, nRate );
. \+ O& K, y5 `9 r; L3 X        fds.Setup ( fClock, nRate );2 K& a, x8 Y( U  T: ]
        n106.Setup( fClock, nRate );
+ \* k+ g$ o# j1 c" b        fme7.Setup( fClock, nRate );- w- l( y; v2 c  \2 \2 P
}2 _5 h5 I) Q1 A, j- [* y  V/ }  W
+ J4 m3 b* ~' `
void        APU::Reset()- n/ ?& G3 R) r0 _) j$ w
{1 B' h5 _7 @& c) ?
        ZEROMEMORY( &queue, sizeof(queue) );
+ h! p3 n+ C6 F: G# T        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 H; S& _: H& B& b* R/ o1 M0 g& ?* M
        elapsed_time = 0;3 {- P0 w+ A, W' J! c
. ]$ M: y' d) J" @
        FLOAT        fClock = nes->nescfg->CpuClock;2 s4 |/ j6 W8 q8 A/ E
        INT        nRate = (INT)Config.sound.nRate;6 f- i6 {7 Y+ l
        internal.Reset( fClock, nRate );; _) g# T& d6 S$ F
        vrc6.Reset( fClock, nRate );
& v3 W) J8 k& u7 i. ?. l3 c6 N  G% |        vrc7.Reset( fClock, nRate );: t; z" w3 B, w; _
        mmc5.Reset( fClock, nRate );
4 M* o# V. Q& U6 {        fds.Reset ( fClock, nRate );
3 y. t. Q4 }  C8 R2 @        n106.Reset( fClock, nRate );# G2 O) J& @4 s- _) U5 }3 M
        fme7.Reset( fClock, nRate );
- Q  B2 q* f( u# P
6 h0 s/ Q1 b6 k) D# ?7 Q! M" k  o  h        SoundSetup();! f8 J9 w0 i5 q: _0 p* T
}" w/ \7 i5 |9 N& ?3 N* b7 `
8 Y& a6 X. r0 y! L# p
void        APU::SelectExSound( BYTE data )
) l0 @6 O! s2 J5 [0 f( G{
! g( N/ J/ Y- e' P        exsound_select = data;7 ^! \) j5 {, `  M4 t
}4 }0 h" F( P2 p- @7 Z( D( S% k
5 P/ X( h! Q. z7 P- p
BYTE        APU::Read( WORD addr )
& O. ^1 T( o* z3 b) A  [8 ~& M: o{
, j: w" K% L# Z  p- U* p, C9 a( }        return        internal.SyncRead( addr );% o" f8 C4 [# j8 o
}
3 J2 D% I4 B/ f8 ?9 X+ u+ {( w# k) S& f& O* J% l. q
void        APU::Write( WORD addr, BYTE data )
1 I( D' `# Y3 L# G5 i( H* a{
! E' W6 `1 Y: `- y( I' s        // $4018偼VirtuaNES屌桳億乕僩
7 K6 f) ?9 p$ K4 L6 W, m9 |' j        if( addr >= 0x4000 && addr <= 0x401F ) {
# f1 E1 V* r5 ]& v, r                internal.SyncWrite( addr, data );2 O' e9 ~6 Q+ e7 J$ Q
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& W; g. L; _' A( G, p        }
7 J; m7 P& \9 c/ U% Q}" Y8 f/ E8 s8 i2 M6 E; C3 y
: E# T+ e( l' i( K; ^* t
BYTE        APU::ExRead( WORD addr )
; e( Y' g3 N9 \2 _. @/ S{
% X, H, Y$ t/ r  {BYTE        data = 0;
: {# g' [. S6 |, Q
6 }. x# D8 h) o% a# a        if( exsound_select & 0x10 ) {; R. X3 p: O: B+ ^& I1 W$ B
                if( addr == 0x4800 ) {
; d# ]& K0 y4 G  Y, G! C7 H# u                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& a, D  O( r6 F0 j+ `
                }
6 e, s( ?. R+ |: E  D        }
; S- \' t9 }1 k8 `) g% ^5 ]        if( exsound_select & 0x04 ) {
7 `" j/ O( U  t' B* \, O& u6 g                if( addr >= 0x4040 && addr < 0x4100 ) {
: h4 C& h9 ?  @7 _                        data = fds.SyncRead( addr );; J# Z! f8 [9 E2 `* N3 H
                }
5 [' x0 C2 I3 b1 R& c& U# X0 R        }. B6 h- ^# {* J0 f9 }, w5 J$ s
        if( exsound_select & 0x08 ) {1 B2 e& }9 e/ N$ e9 P
                if( addr >= 0x5000 && addr <= 0x5015 ) {
( z; B6 D6 h5 i" {8 R8 n                        data = mmc5.SyncRead( addr );4 k, W; u, g" j" A9 v' X7 e3 v
                }
5 W+ f! V( X' c& }" z% O( d2 B        }+ c& k; [/ d& V  Y: R7 L, G$ T

" J: L+ s/ t: x) n1 x        return        data;7 X" c& i6 f( q' f* ~
}5 b( |" O9 n& p; N/ @0 N# q! h
8 k$ Y+ q+ ?8 G+ P# }
void        APU::ExWrite( WORD addr, BYTE data )
. C# [8 m4 T) D{) F$ K7 V: G  I4 x4 X
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( s$ w3 y% ^& I0 F+ j' l  o- x7 B" o% x5 N- m4 H5 N
        if( exsound_select & 0x04 ) {# v" j& b+ s6 H; l
                if( addr >= 0x4040 && addr < 0x4100 ) {, E' ~0 ]* G; M+ V
                        fds.SyncWrite( addr, data );' @3 P* _+ S! T- P5 y$ Y  F" e$ p
                }
; q6 B5 q) ?# v& e% E' I        }
/ R( r( d; s; ?/ i1 a" v$ W4 ^" l8 P/ k" s% K7 _5 C$ f
        if( exsound_select & 0x08 ) {
) o2 U6 ^) B3 h( E9 D0 d5 Q/ I3 b; L                if( addr >= 0x5000 && addr <= 0x5015 ) {
- O2 X( Q3 `3 \; Y                        mmc5.SyncWrite( addr, data );
( d. T, n5 y1 {; Q  M                }
' v3 G! K' x: X; b6 U: R8 ^: y        }
2 w: a" ^/ ?* X! }! Q; g}$ ]% U9 X- B% n5 x, E! m0 b) ]# i
! D! Q9 j* ^2 F2 {& y6 w* b
void        APU::Sync()1 W6 v1 M" q# m$ f9 Q: g
{
/ K5 a1 }" ~9 X2 g0 W6 w}
/ K$ ]! G6 ?9 A9 W* W
% j; M0 O# Z- ?( @  Tvoid        APU::SyncDPCM( INT cycles )
) ]: E! F" g5 ^7 i% A0 c1 ?4 p{
" B- ~) c4 g  I+ Y        internal.Sync( cycles );+ ]+ s! `" S! d
- ^$ m+ V/ Y8 |' H# x& ^. \) E
        if( exsound_select & 0x04 ) {7 f) K, a9 i( m  \( n9 M
                fds.Sync( cycles );
& Y" e* V5 h) s3 o1 j3 a        }
; q* s9 L, D; G6 u        if( exsound_select & 0x08 ) {
& R3 p/ v# `( L4 @, C! R6 a% c) `                mmc5.Sync( cycles );% q' T6 t- E8 k) r: ?
        }
0 T' S3 D( T  r7 A/ U* O}9 Z9 e$ f( `) o% L$ y* \$ |
8 F' n' t" \; _$ G
void        APU::WriteProcess( WORD addr, BYTE data )! ^+ g% S1 b  H2 X
{0 U* E  i$ P6 B+ S  k8 d
        // $4018偼VirtuaNES屌桳億乕僩" h. u4 C# V. p/ {& b( X
        if( addr >= 0x4000 && addr <= 0x401F ) {
$ ^) a+ G, K0 b5 ?# U. _9 x! k3 o" m, u                internal.Write( addr, data );5 n( M; ~4 L( o: g! r; P0 B# A+ i
        }/ N: C. R: j4 z% }
}5 q2 P" B8 G& o2 [* L: C( e9 v2 f+ ?

/ U; ]5 K% K; p0 m0 P$ U# \void        APU::WriteExProcess( WORD addr, BYTE data )
6 v5 G5 I& |1 [- o7 X{- m  ^2 p) V0 H8 b; `3 x9 q4 a* U
        if( exsound_select & 0x01 ) {
7 u0 ?, \! D+ [                vrc6.Write( addr, data );+ D3 D3 O2 g$ X) A
        }# A) A9 t+ n. n# \4 \: Q
        if( exsound_select & 0x02 ) {
4 S4 j, d0 m+ i4 o7 v, O+ M                vrc7.Write( addr, data );
: p- C; \5 m; B/ ^4 p. m' x, ]1 B        }
& C: \/ x$ i9 w2 @" d6 c* _/ i        if( exsound_select & 0x04 ) {7 {1 c) i* K; k. U# H
                fds.Write( addr, data );
  ]/ B2 p4 T' o5 S( _        }, i" J; C7 b' k. s4 b/ }
        if( exsound_select & 0x08 ) {
3 M4 }$ j! u1 {" r                mmc5.Write( addr, data );6 Z6 T/ M9 G% Q0 L( @9 B: _( P9 Q
        }" `! {0 Q" f* z/ F$ ~* D# x9 P
        if( exsound_select & 0x10 ) {7 w& Y+ K. ~% l
                if( addr == 0x0000 ) {
/ t7 J4 l& J! X0 V                        BYTE        dummy = n106.Read( addr );
( ]0 J1 B0 q, I* `                } else {5 ]' w1 W9 W1 @, @, E0 a
                        n106.Write( addr, data );
/ R" ~* U8 M2 I+ `                }
# A+ ~' c3 G2 `; S* T4 j. S& d        }2 [# l4 M0 I9 Z4 F4 s6 m% d
        if( exsound_select & 0x20 ) {! n: @' {5 B7 G' M
                fme7.Write( addr, data );
4 d* q$ o( Y% z        }
6 A3 k- x' R7 J}
6 Z0 v; Z' a. q$ e2 |. s% Q; l# }, V3 @/ b
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 }( w$ p+ Q$ O: e& L
{
; B1 a" z, o1 K' sINT        nBits = Config.sound.nBits;, e7 q1 s' o6 S( h
DWORD        dwLength = dwSize / (nBits/8);
; q, F9 O3 S) U' }INT        output;: d2 i3 B# [1 j! w6 [8 e/ y0 ]
QUEUEDATA q;
# F. t5 I& \3 k! R% `# t1 |6 Z2 TDWORD        writetime;. |5 X1 r7 B: t' `6 k" R4 k. v
* H7 F; I0 v( W( K4 b' L
LPSHORT        pSoundBuf = m_SoundBuffer;
! D3 G/ V8 L3 ~* ~5 G% iINT        nCcount = 0;3 {( Z8 T* G3 F) \- |5 E
" b5 u" K5 n- x: x# G4 l8 J
INT        nFilterType = Config.sound.nFilterType;
. c6 |1 B1 c, b9 q& Q* p* q' h2 q9 f' @; [
        if( !Config.sound.bEnable ) {* j! ]- U) p: d; w6 f
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );: L  y8 Q2 n, A# ^8 ?+ |; F
                return;
6 [, W& L& d# @; d        }
7 @  P( e$ x" q2 h/ H8 x) G1 M: v% B$ L- N1 d
        // Volume setup
* \9 V0 m$ E% v        //  0:Master" t3 j/ E0 {+ Q9 P, e3 R
        //  1:Rectangle 1& Z: X: p9 l, F+ ^4 D% z
        //  2:Rectangle 2& W6 _. U4 N8 m
        //  3:Triangle& U* J% z# j- o3 S# U$ E  t4 P- {
        //  4:Noise/ H3 U5 u1 P! Z, U
        //  5:DPCM+ h! }) A5 j6 `$ H' M: @" I- s5 S
        //  6:VRC6
5 B( o0 J+ T" Y: y$ u4 D        //  7:VRC70 }6 F( T' d1 r9 X8 F: \
        //  8:FDS+ f5 Y$ a5 n( e' o6 J) P. o) ]
        //  9:MMC5  H  e0 P9 C/ g7 p  ?2 M
        // 10:N106. x6 O" F* c. {# H
        // 11:FME7/ V4 S+ _+ c. Q4 a
        INT        vol[24];
, t  h  O3 C& Z3 @- P5 n+ `0 P        BOOL*        bMute = m_bMute;
& |9 |+ z& e* `$ }, _2 r        SHORT*        nVolume = Config.sound.nVolume;! ]0 }$ F% y: R. H

3 d- @& J" L( o; M8 \7 G5 M        INT        nMasterVolume = bMute[0]?nVolume[0]:0;) {% ~: ?" }9 F- g* P" h5 u' Y
7 ?( s5 M$ u; l5 G; D
        // Internal
. [, r2 M5 E; |        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( U$ c$ a# D& |* i# H3 a# }
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
8 h4 I- f5 m1 W% O        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;( }/ I6 k. w' F; e* |1 c5 r
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;8 E! X0 J0 J# r6 R* m$ Q
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 _) q6 }' A; {$ [' h# i% V6 A$ |; w( a5 ^) ~3 i
        // VRC6
9 \/ G9 _+ h7 n: E        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# Y  w& c0 |( o# @, w$ Q
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ N8 p2 o% ]& x6 Y0 C: [% d        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 G# E! [5 o& S9 h6 \
4 S/ s+ w' W$ v8 ?7 c
        // VRC73 c9 [4 }" G( R& n2 W
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ z4 t/ g& C/ ^6 F5 b9 q
* s' D! e3 |; \        // FDS
; `) ?# }6 E$ m% Z+ H        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
6 E0 {. n6 |) Y/ B, W4 `. P7 u- K2 A9 s/ L
        // MMC5; C5 f4 ^% _$ T7 Z1 n' U& D, k
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& A$ R& ]5 X- i        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& w5 F* b4 V& ?        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) i4 G  j8 j, h! E: Z5 h. \" O3 a6 I

0 ]3 I/ I4 A  z. D        // N1068 p5 F7 x' B; X" S$ ^
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% A+ E2 A" z$ W  q6 f0 _- x
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 I1 `/ F! s( ^' A9 ?
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 U1 r5 U$ t: |: _; D
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  U$ `4 @. m. G+ l( n2 ?/ c7 q        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 F* ]- ~! D) f- W. q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 Q9 }: q+ b3 v! Z        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, X' B9 M4 s7 A
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 o+ l5 C  V$ i0 K- p7 A0 q4 W8 r+ B. e5 T! Y( s. d
        // FME7
% @4 r. r1 R9 i2 D" A4 \6 u8 O        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( u( Z- [7 ?( ~7 F
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 ]8 u; ^* _, g) J  K- ]
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 L4 w0 h1 z0 [2 X& I5 _- ?
3 Z8 q" l7 U. W7 x+ |
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% |$ i& g9 C  M4 Y" P' _9 w( a. L        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' T# I( d% r/ c0 A: [, M) X" j( s0 N- @' m& h. _
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 n$ O1 A$ ~1 i& ^        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
' m% L1 T/ a; p$ u1 G( O4 Z& v                QueueFlush();
* \4 ~% _1 ^7 W6 C" H, t4 I        }# |. ~. V4 ?6 h2 j( z# u

: r- V; O. R- C* U! E# R5 w        while( dwLength-- ) {' z* A" [% }8 c% @) I( N$ z7 ], ^; `
                writetime = (DWORD)elapsed_time;% n. ~) S6 ]' L  S% n  Y2 y! P

1 C; `; t7 J2 i                while( GetQueue( writetime, q ) ) {& t  x* Z; N6 s9 I
                        WriteProcess( q.addr, q.data );
2 T% c7 h7 ?: p0 _9 w4 R                }4 W1 Q' Y# X" ?8 }+ n( i8 |

& |9 \" Y' Z8 e' C  P                while( GetExQueue( writetime, q ) ) {3 V% L) S7 s: J1 R! ^
                        WriteExProcess( q.addr, q.data );
" {  n) s5 q2 [7 x                }
3 |7 X+ U: Q2 w5 }7 {
/ j7 W3 q2 G  N7 D6 K" S6 D                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ [0 @2 W3 ^+ ?8 G6 j7 u# Q                output = 0;
. d; e8 i7 Z' g& D                output += internal.Process( 0 )*vol[0];
# J, {+ X9 ?( c, p3 _7 ^& X" z8 l3 ?                output += internal.Process( 1 )*vol[1];9 h. x6 A! X5 _6 s3 v8 |0 E
                output += internal.Process( 2 )*vol[2];
. \+ T+ s2 z# h7 p0 C- f                output += internal.Process( 3 )*vol[3];* e+ r$ l8 z& X& B6 y! a
                output += internal.Process( 4 )*vol[4];1 d# x" q' j2 K2 c$ S5 z& k
6 n  ?& Q$ d$ y7 ]( Z
                if( exsound_select & 0x01 ) {( y1 M) j0 V) q, o' s
                        output += vrc6.Process( 0 )*vol[5];! B' D7 h/ N9 h! \
                        output += vrc6.Process( 1 )*vol[6];* _/ _7 P! o( \4 I$ {
                        output += vrc6.Process( 2 )*vol[7];
- r4 U! t) G1 r5 h& Q2 s2 W: z& |1 G                }. @, b/ s7 M- N7 d( V  H/ |
                if( exsound_select & 0x02 ) {
5 H) j" {/ }, z. N+ }1 _                        output += vrc7.Process( 0 )*vol[8];6 }0 C. ~/ e: H( @
                }
0 h: J1 [6 i3 u                if( exsound_select & 0x04 ) {0 k4 [6 v9 j( G9 s9 U) {8 a: w( D
                        output += fds.Process( 0 )*vol[9];0 A6 q5 D2 b3 T+ |# r2 i$ g6 J
                }
" n7 I4 I0 W8 u7 V2 j* l                if( exsound_select & 0x08 ) {
, h9 L0 S" q7 C3 D& n1 U  z                        output += mmc5.Process( 0 )*vol[10];, U5 r& M9 \6 W- Z2 w
                        output += mmc5.Process( 1 )*vol[11];: d9 g: e7 e: f7 X/ K
                        output += mmc5.Process( 2 )*vol[12];5 W; h+ x) K! h
                }' J  R: |* j& p; @- D
                if( exsound_select & 0x10 ) {  X% z! Y/ x5 S9 x, V. t% x; }4 n
                        output += n106.Process( 0 )*vol[13];
' P! m, b( y5 O" {5 t& W% F                        output += n106.Process( 1 )*vol[14];) C  P  n9 P' ]5 ~
                        output += n106.Process( 2 )*vol[15];
: p5 o! D8 p9 F                        output += n106.Process( 3 )*vol[16];! ?/ b! c4 {7 G) @8 v
                        output += n106.Process( 4 )*vol[17];- N' y0 Z  t5 |! G+ a( z/ f% }
                        output += n106.Process( 5 )*vol[18];! I, G4 S+ i7 I! k4 b
                        output += n106.Process( 6 )*vol[19];9 I1 N8 `# e- r9 W. v! L0 x: ?6 m
                        output += n106.Process( 7 )*vol[20];
4 K9 @, C" F- m& ^0 s$ E                }; y" u% J5 y; z* X  x# D' a- G
                if( exsound_select & 0x20 ) {5 Q5 ]5 W- t2 m! ~& ?
                        fme7.Process( 3 );        // Envelope & Noise+ `% V: l7 `# e$ ~1 r
                        output += fme7.Process( 0 )*vol[21];3 }: d/ j9 C, s% Y
                        output += fme7.Process( 1 )*vol[22];
+ \3 F" a" `+ D+ [& Z7 A                        output += fme7.Process( 2 )*vol[23];- q) ]$ Q2 B0 H3 ?6 j
                }4 J& N6 O. R+ a, L- M
- I, K- k. N6 k7 c' D" y; w1 A1 z! z  r- o
                output >>= 8;0 `1 [8 r& i5 r
2 U: @6 G: a* r8 n: y) R
                if( nFilterType == 1 ) {! H$ o* B: i; i+ I( Y
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 S0 |- f* `8 X( R9 [
                        output = (lowpass_filter[0]+output)/2;/ R+ i# y, K  W; H/ K8 O
                        lowpass_filter[0] = output;% I7 \' o, [0 |) a* ^* K
                } else if( nFilterType == 2 ) {/ b3 y; h) X  x: F4 [
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 r4 b; {2 A0 \5 h0 f$ z                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
) L& C" I- {3 r6 C( ^: y                        lowpass_filter[1] = lowpass_filter[0];
3 P! `  J/ p) J                        lowpass_filter[0] = output;
9 n4 ~6 F9 W9 y( l, V                } else if( nFilterType == 3 ) {
, ]* I7 X$ W  u                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)& @$ G+ c* z" n4 C9 S
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;9 \9 K- Y( ?3 E% `
                        lowpass_filter[2] = lowpass_filter[1];
' p, |  V1 P0 i! Z6 {                        lowpass_filter[1] = lowpass_filter[0];- Z, E* v% k+ @! `) S  f# t
                        lowpass_filter[0] = output;
3 v5 M9 A* l4 q1 V" x! U                } else if( nFilterType == 4 ) {  L7 ^+ a: M+ H) M# k: x
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3): M. \$ Y6 z! Z3 t: l4 t) d
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* y  Y# Q6 [2 {5 c' f5 j                        lowpass_filter[1] = lowpass_filter[0];
" k9 q4 ]7 J7 c+ `9 V4 j                        lowpass_filter[0] = output;& \% N" H: ^; N( P) s
                }% }' y% X1 R. G2 G- `

2 F& w) K+ [( o* J1 Y6 }( u#if        0
4 W8 a& W) P& M0 R) T4 w                // DC惉暘偺僇僢僩+ ?* H: t8 J! c: ?4 d/ d' m  v
                {
3 D# A. j' U" _* }* l0 J6 _6 H& v- r                static double ave = 0.0, max=0.0, min=0.0;
& j$ s1 c* P# g                double delta;
9 E$ d3 I+ e$ v  `) }                delta = (max-min)/32768.0;
& w, g. D0 F- q  G. i7 q* i: q                max -= delta;
6 j# h5 |7 a0 B. ^* o3 W                min += delta;
2 s& O; ~- @- K" d; c                if( output > max ) max = output;
' J. z1 P2 n7 B& Q                if( output < min ) min = output;2 B5 t+ f+ B) u% d
                ave -= ave/1024.0;
1 F* w: o2 n# R% o9 r                ave += (max+min)/2048.0;' b. y* c' O% V% S
                output -= (INT)ave;: l/ q: i  ~& i% y
                }6 F6 F& X1 X. J4 T/ r7 u/ k1 q
#endif
3 Q& c, j, W! p) }: k#if        1
# u, a/ o, U+ J# h3 C! H                // DC惉暘偺僇僢僩(HPF TEST)9 Y7 E) e  W" z9 J& Y& J" A
                {8 d0 C- ~1 \: Y. ~; D1 y$ T. d
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ Q  u+ P% o7 @2 J( T                static        double        cutofftemp = (2.0*3.141592653579*40.0);; W) F9 \$ v8 R6 l3 y& |$ m0 u/ a
                double        cutoff = cutofftemp/(double)Config.sound.nRate;% C' @4 W- |( s6 k
                static        double        tmp = 0.0;
% \  h  M) J4 w8 D                double        in, out;
! m: A& }+ C6 L1 Q# f1 V+ o6 g4 U/ x" ]3 u0 P  Y2 `" Q
                in = (double)output;- {5 H" r) P- `, J! ^, M" c
                out = (in - tmp);
% u  U7 c& ?$ `- O2 l8 N% z, I                tmp = tmp + cutoff * out;9 `0 ~: [' y* g! f
9 U( q- M& f( F$ M9 D
                output = (INT)out;- I* G* p) A9 W$ }4 l0 x
                }7 s4 p8 E. h; w2 L; I7 d! V! X' Y
#endif" a: p! c/ U6 n9 o
#if        07 J$ ]# K1 n7 e( U
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
5 ?/ l4 R) Y1 M$ B                {
) B* Q, a' B7 b  z                INT        diff = abs(output-last_data);8 M- R2 ^5 Z' O+ }1 `* E# j& X
                if( diff > 0x4000 ) {
+ L5 M6 e% B5 b/ k6 O4 u6 T                        output /= 4;
2 \$ e# T4 F1 |+ S                } else
+ d" Y1 P/ H# ]6 W                if( diff > 0x3000 ) {
' z6 A; P  W/ Y! K; ^. p2 W3 r" P                        output /= 3;
, m& _5 ?* _5 [* O7 M' w                } else
' |$ ^9 ~* t" _! G1 t% o                if( diff > 0x2000 ) {
0 n1 }" M$ Q; Y: C                        output /= 2;
) z: Y6 `2 @6 I- r4 u* g                }0 o( j# H6 E$ x! D
                last_data = output;
4 D% X' O8 K. `4 h+ B; W                }$ |, ?8 U* \  x: z' a; b
#endif; @$ v* v/ D8 _/ a" G' L
                // Limit
2 g$ u" Q' A# b# b                if( output > 0x7FFF ) {  B1 n5 F  ]; i9 d6 ^: q
                        output = 0x7FFF;
: W6 Q3 e6 |/ e7 o; h2 b$ X. ?                } else if( output < -0x8000 ) {& f, Z1 K. w! Q' u8 O4 w  R3 ?
                        output = -0x8000;8 F: a8 w( d% v6 j) ]1 A: R5 q
                }
; L4 x+ {- w" `! L7 R  B* ?' J% x. z3 x* c5 b
                if( nBits != 8 ) {
5 B: ^& F# p4 l' o3 i; x6 c, G; r                        *(SHORT*)lpBuffer = (SHORT)output;3 b; A8 N, i  z0 p: A% G: O( h
                        lpBuffer += sizeof(SHORT);
& K, M$ X( F9 G                } else {6 v# d7 W+ F5 I- }
                        *lpBuffer++ = (output>>8)^0x80;
1 o  }) [" q4 L; }                }: R( b7 Y( ~- n5 ]( C$ a8 u: @" }0 Y

! \" M) b6 x! v# Z                if( nCcount < 0x0100 )
3 ^! i# x5 C2 j6 h( Y8 J: k                        pSoundBuf[nCcount++] = (SHORT)output;
: n: K) p/ ^! b1 `) ]' d
: _, q& N0 b3 F6 e//                elapsedtime += cycle_rate;! \( d& m- i+ B, a7 x; l( e2 k
                elapsed_time += cycle_rate;" V. R, Q9 {5 K, h2 z2 O
        }0 W: ?/ a3 R- [) e" L2 I( j% C, x

# v; C: b  \( ~+ @! J#if        1  j$ s" G: t1 ~+ \
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {% J' x7 U7 s& a& }% {5 _8 q
                elapsed_time = nes->cpu->GetTotalCycles();
( x( N5 B  ]8 h# p8 \        }1 i: D8 h- r/ c6 R
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ Z4 _, y& t0 g2 S6 b
                elapsed_time = nes->cpu->GetTotalCycles();1 n. V- I, {( A) v: t0 u+ t
        }/ `9 _7 u* }$ Y1 K8 N/ k
#else
2 `) l7 B3 }. A; v6 q& I        elapsed_time = nes->cpu->GetTotalCycles();
0 E0 {) V8 w* T5 @% b) p#endif$ t) Y7 c0 u; \4 m5 h1 k
}
$ E( A# y4 u8 s5 m6 W5 P. W# d
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)7 e6 m1 U8 y  l, a
INT        APU::GetChannelFrequency( INT no )
$ Z4 u( P+ s) f. c( l, C5 p{
4 y7 b  F9 B5 J( p) X8 `; Z        if( !m_bMute[0] )4 o5 h: k) u! A) [
                return        0;  a* _8 u$ u& u  M: d: F/ j4 T

8 c$ \) K$ S7 q4 h$ b) ~        // Internal
7 L" X% D+ Z) Z8 ~& }7 N        if( no < 5 ) {  s  l4 r0 G0 h6 y
                return        m_bMute[no+1]?internal.GetFreq( no ):0;  u9 H+ M0 O4 r8 e8 g7 G
        }/ a- i2 O+ p% u& v* x. t" h# {
        // VRC6
3 v4 c+ d" j& j7 m5 s% B6 K        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
  ]' E7 N- D  [, k5 U# M2 n% `                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& Y+ y! j3 a3 H: [( Q        }
  o- `6 ~! L, a- f# ~        // FDS' _+ u# ~4 M0 ^: M
        if( (exsound_select & 0x04) && no == 0x300 ) {
/ i8 o5 O* `" W7 D                return        m_bMute[6]?fds.GetFreq( 0 ):0;: S5 B4 h1 v7 j- X: W& A# r9 V, H
        }
6 x1 o; ~* g* Q9 Y! u        // MMC5
. i% O8 M4 a- y: B6 s        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
) u+ T9 h. J/ Q4 F9 i5 |6 ?( A( W: ?5 Z2 [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;. \7 N; I1 S+ F
        }' h' Q0 z  W, J7 Z6 Y
        // N106
% C: y& I. f5 o6 T- q+ B5 P) [6 @) W        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" H3 S) o+ _! f- L$ V                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;+ s5 X/ h! F' h9 m
        }
3 O3 m8 u& n4 b        // FME7. m- G5 q* _3 Q( ]% _4 x  Z
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
/ i! S, A+ B3 B                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, N3 q# Q3 ^* m7 ~# R, ^8 V, S1 [
        }
0 {7 Q1 u1 |" N! q3 u* ^- v. A. u        // VRC7
/ \' I: S2 w2 j3 F3 M, Q! j        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
$ [9 c. C  O! l2 ?& n                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
/ C& \& E# b' K8 J2 s9 V0 h        }
% y: @& w/ ^9 s" O2 j        return        0;
* A+ T" N) f% w}+ q( ]5 e! ~, _& Q, K0 w
( M" \+ ]: j" O+ V& Z
// State Save/Load) N' u+ g  a, j" i" {
void        APU::SaveState( LPBYTE p )8 h2 ^$ I8 U: D0 L5 j
{; g8 B6 }$ v) |5 y/ _
#ifdef        _DEBUG2 R5 ~$ `# h8 u
LPBYTE        pold = p;
( O/ O* N; _$ h6 @#endif
8 r4 ]5 t: d7 a& p; Q0 e8 [3 b9 u* s$ [& ~8 E
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- v' ~6 c6 w7 Y" n2 c        QueueFlush();
; N  ~1 J1 ~0 v" S8 O; V: f4 m; x" t" x  F, R6 U0 g) C
        internal.SaveState( p );
' j' }5 O) k  M0 c8 S% e, W        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 S) x5 _  [4 X
! H* E, S7 S. Q) L7 E* T% i" f
        // VRC6+ i1 Z" g) R4 v" I
        if( exsound_select & 0x01 ) {
5 j7 x% D, F% S8 G                vrc6.SaveState( p );" K, B  A8 Y; n' _' M2 {: A! c
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) |* W% L. M+ }        }; {3 K8 o/ b. _2 n, |
        // VRC7 (not support)
. e7 V$ l, O2 a/ Q) g/ \        if( exsound_select & 0x02 ) {
2 _+ ^- w+ W5 ?, J, S) B                vrc7.SaveState( p );
7 E& p4 Y1 R1 a$ c, M7 o* N2 O! `                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 i0 ^& S7 g0 y! d" e, W' T+ e3 N        }
) g# s- t6 X; _0 U        // FDS
+ ^4 D" ?$ r) R$ x5 Q$ }" k        if( exsound_select & 0x04 ) {
5 A- b5 A+ O+ M  \$ u                fds.SaveState( p );6 v# l* s! z; c
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
  O( L/ y$ V! q1 ~        }- b6 h( c; H2 g
        // MMC5
# g" ^/ b6 b# P* R3 r: w        if( exsound_select & 0x08 ) {
  m9 L2 u% ]( U" ~6 J                mmc5.SaveState( p );0 Z7 J$ _8 {$ E, Q
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& h5 p* ]# F) {0 c' b        }/ M, @9 h" q! L( @
        // N106- b1 |! s  g( w. z7 ^* t
        if( exsound_select & 0x10 ) {8 `: D+ j' q0 O$ [3 e4 t) \8 o9 u% m
                n106.SaveState( p );# z5 [+ u( L: E9 O- T
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. _: q* x1 Y- f1 e7 U) s! R/ W4 ^
        }
" y2 |% p" `% `2 P8 T0 f6 h        // FME71 g/ r9 x: A" c. l8 y$ \
        if( exsound_select & 0x20 ) {
* [& M; ?' M( z% ^                fme7.SaveState( p );% |* {% N4 Z/ d! a/ v. {3 P, w8 v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; x# M# _* u: k
        }
4 _" i: c2 z, {1 B( |4 G
& L2 z0 i5 i6 J% [/ K  I#ifdef        _DEBUG
  p% Q: v- u  A  G5 L8 r" ^0 cDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
& V% Z- ]" m* B: L2 L! N#endif0 Q" B8 t0 t% w; n2 l, u1 I, U
}
& h; K+ d) _$ ~8 U8 `; {
# f' h3 c: B3 b) W8 {8 mvoid        APU::LoadState( LPBYTE p )
/ R6 ~  S7 R' Q( O1 |. Q: u{
& U- I& h- o: K5 Z9 x6 h$ N/ ]        // 帪娫幉傪摨婜偝偣傞堊偵徚偡  q2 v* h1 v3 r# q/ ?3 f1 F% C9 U
        QueueClear();, L8 @8 z6 q& \8 O) C  n
9 j5 P7 e" e( o2 Z: b
        internal.LoadState( p );
1 P. M+ i- \. Y2 K4 F        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ J- L( T3 D6 M; d9 P5 Y) `, z6 }, b) p7 ?3 Y
        // VRC6
# _$ I4 l% q4 j0 r  V  W" }        if( exsound_select & 0x01 ) {
! L% ~9 {5 x7 k- {4 h" T- j$ v4 n                vrc6.LoadState( p );9 J* E6 ^1 B- p4 i: ^) y0 J
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 M0 f# a7 \  F! e        }
9 O$ n/ f9 D8 L  W        // VRC7 (not support)
: U6 U6 J  [5 q- g% P0 b6 ?        if( exsound_select & 0x02 ) {
; L# f; p, X6 D" Q* N) T/ s                vrc7.LoadState( p );: m9 c5 }! A9 ]6 j. h' q  K( e9 R9 ?
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 Z: W7 i; J/ |$ Y" h1 B        }
) s+ }9 p& y1 W/ J6 r: [/ B        // FDS
9 m4 t' O% n5 W' c9 _# |* I' J1 t% S        if( exsound_select & 0x04 ) {
8 [: l. Y! m! n                fds.LoadState( p );, \6 {5 N- _/ \2 T6 G( }
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 P8 ?. ^$ b. ]  L+ T. @' F
        }( r& [4 O' x+ v. X/ g$ U
        // MMC5
* m/ ?, i$ U' l  T# V' U; ]0 c& z        if( exsound_select & 0x08 ) {0 O4 h3 E  Z8 S: }0 L
                mmc5.LoadState( p );9 `  E% K" d9 w+ M; B1 e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 h. {" f5 L" A+ l& y
        }
+ H8 `% b8 A# ]1 {1 `3 b( U        // N106
  B6 X) ~0 E: {# z. b+ @        if( exsound_select & 0x10 ) {
* \4 `' L, @! F                n106.LoadState( p );
3 ^. A' u9 h; V6 G; [0 h% X. E                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  V& M' E/ F* @' _/ A2 D% M        }
6 Q% \' d) R# N8 X: V  M/ o3 x9 |7 G' J        // FME71 F6 `/ f# {7 X( J. h, k7 K( ^
        if( exsound_select & 0x20 ) {/ R) M3 N: a, \5 \9 K+ X8 z  a
                fme7.LoadState( p );6 [& b+ k+ A1 j( I/ U4 Z4 T5 n- e4 Z
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ l3 Y; E, q2 }2 n4 Y( B
        }
, e% y% b+ i" i8 l: ~7 v/ H}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 $ c( L9 y4 ]: P/ Q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ k" a1 N+ q2 i0 }
感激不尽~~
  r' t: f% f2 ~2 C& ^
恩 我對模擬器不是很有研究,0 V; p1 f* T# w
雖然要了解源碼內容,可能不是很困難,+ s+ }# M$ W* x; L2 j% d
不過還是要花時間,個人目前蠻忙碌的。
. |- `. }9 `' A9 A2 {6 ^) P6 \9 }/ P' b& J1 o
給你一個朋友的MSN,你可以跟他討論看看,# N1 u: s6 l$ L) P' ~8 X: z5 L
他本身是程式設計師,也對FC模擬器很有興趣。+ [! k: O7 e  A+ e3 [) a8 f5 `
# x3 h1 J3 }( ^) p( o( v& v
MSN我就PM到你的信箱了。( V. v; a8 O+ Y+ T$ p% N+ n4 O
" K* V) H" L, e5 t$ Y8 E6 y7 Q+ J
希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
6 L$ H& D8 a( k呵…… 谢过团长大人~~

; h$ y8 i0 [; ^' t( U. l: F
, m" a. m) T& W/ n% E' D* e6 d哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
6 p, b+ f4 v1 x团长的朋友都是神,那团长就是神的boss。
+ S$ }( @  _- J: o6 t. S
哈 不敢當,我只是個平凡人,
8 q% M( `1 T' @! d要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  O; U" C8 G: [) Q: M, ?& J  X
ZYH
5 {1 Y# g1 O" T! H; aQQ:414734306( @: l+ j& a) `+ B+ R( f. ^
Mail:zyh-01@126.com
+ {# f) ]0 n: H: Z9 }' T  E2 }' i+ Q+ d1 s/ K) q. z
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 b- C% Q' H4 s; C; a% a' s
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ V( H& S. J" h$ K
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-29 23:54 , Processed in 1.083985 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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