EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 n# h8 O% X4 d3 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% Q- {5 \( `# d0 A" o5 B* M$ K
这里有相应的模拟器源码,就当送给大侠了~~
% Z7 ?/ J% s9 k) f! Fhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表   I  \) {! i0 y2 k' R
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。) w% Z7 G' ^9 P. ^* w
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~* k8 }- N+ F% w" V/ Z( U4 e
这里有相应的模拟器源码,就当送给大侠 ...
% f  s" z% {4 m5 {, Y7 `, Q
聲音部分(Audoi Process Unit = APU):
) r0 ]. ^9 {3 \.\NES\APU.cpp
, r  z' }6 U* N* @/ O6 \.\NES\APU.h: m( q, ]8 m$ a
5 B0 @' g8 q! J0 k
3 V1 x8 [' c( [" B$ V5 O: W5 B5 E
影像處理部份(Picture Processing Unit = PPU):4 I8 F- n4 [. D, S" x, J: p
.\NES\PPU.cpp% u/ h) U" n# I  u  B2 g& @& W
.\NES\PPU.h. g; U  Y$ {9 [& ~+ @5 A/ k

" @: G: |) F5 q2 E/ g& r如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 {1 Q  @( `6 U) e9 x1 U& s' ]感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:, M0 r+ u( W2 T
(由于很多专用术语和算法机理都不明白,所以看不大懂……)" Q1 \1 s5 f& W8 d' [
//////////////////////////////////////////////////////////////////////////
; m* e6 D8 x8 r3 {, N//                                                                      //
. _& D3 p' z& o2 X; e+ Q# O0 t9 l1 p//      NES APU core                                                    //% K$ ]1 d, W( T# v3 H0 w$ n
//                                                           Norix      //
/ \8 D! ~  X! I. r' j' M$ ?8 e//                                               written     2002/06/27 //
3 p* ?, W! X0 r- o4 Q//                                               last modify ----/--/-- //
! u7 X+ S1 ^3 @6 C6 ^; V/ q2 T6 Z//////////////////////////////////////////////////////////////////////////4 ]0 a" P5 m3 Y' u4 U
#include "DebugOut.h"# t) F; j. H. e9 d  I% I
#include "App.h"1 E, h$ c. _1 m9 s  g
#include "Config.h"' m# c! Y% m6 R  x8 l
; R4 n3 a- D8 V  M0 i
#include "nes.h"" O. ]- E) I- n/ [) ?
#include "mmu.h"5 m) K" X. z7 i7 A
#include "cpu.h"
+ D; i. ~/ l2 k4 m#include "ppu.h"
  h9 i2 S1 `9 g1 Z1 B0 G#include "rom.h"2 ]5 ^+ O9 ~- n" o! B& |
#include "apu.h"
) q: e2 G9 R! l0 F5 P5 ?1 m) }, m# o
// Volume adjust
/ w) S6 l  D' f3 V// Internal sounds
8 g1 Y5 o/ w8 Z0 U) [' v#define        RECTANGLE_VOL        (0x0F0)
# d, H9 F; s" b#define        TRIANGLE_VOL        (0x130)9 S$ h$ @, z0 I0 O. u  q
#define        NOISE_VOL        (0x0C0)
0 d  S5 Y2 _% l4 L, b/ D#define        DPCM_VOL        (0x0F0)
9 d( ^* E, u0 l) ]// Extra sounds
2 _3 |" K1 _2 L. y# ^#define        VRC6_VOL        (0x0F0)
1 Z1 V; b6 l* T- _3 f: Z( g$ g8 M#define        VRC7_VOL        (0x130)
: o; N$ B% P+ p$ D; b#define        FDS_VOL                (0x0F0). v2 A0 h1 L4 @4 F
#define        MMC5_VOL        (0x0F0)6 _* Q3 o. s9 Q; ~4 R
#define        N106_VOL        (0x088)  m- Z) Y6 [: H& B. a2 i6 V( m3 {
#define        FME7_VOL        (0x130): e0 `' s, |: O/ A& ?  f" o

/ V2 ]2 P, D* D$ }APU::APU( NES* parent )2 [. V! s; R" ~5 p
{8 y2 i$ W( J- X  H/ ]( ~% A8 y$ w
        exsound_select = 0;' u2 Z$ ^4 n; C; ?) d& Q

" G8 r- b% ^8 ^  I5 B+ g- B: M        nes = parent;3 N1 p3 R0 i3 s8 ]; {$ w& n
        internal.SetParent( parent );
( P4 }* K9 N  G5 _: c- |* d' Y$ j9 e6 h) a+ J4 Q+ P
        last_data = last_diff = 0;
% z5 A# [4 U6 p% {9 `* M& @) x
; b! l& b) z" ]$ \' k& ~* F        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
- L7 [2 x5 O2 j% G# f# r* V' x& I7 a& `2 A5 O
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' A" W1 A; N' T) X, t& V; c6 g
        ZEROMEMORY( &queue, sizeof(queue) );$ k! |/ |% d( n9 W" f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 w) c) C  ~2 u# c/ `
/ X) U+ Y5 K2 M; |
        for( INT i = 0; i < 16; i++ ) {
& q% \3 l$ F4 T  H$ T% W                m_bMute = TRUE;3 m' `! B  L0 D4 V0 t! h" h
        }
' Q+ E$ a4 F6 w; U) B: w8 V}& ?* y1 s: X7 `- V" W0 q) I: g# F. ]

' B# J5 `( j. `1 R* S: h$ x+ K; rAPU::~APU()
) g3 d1 g$ R, y, F! E  s! [{
) P) {0 l' \3 s8 x8 V5 h- z}: E9 y' o0 K1 b: N

4 k4 o; h+ u6 T* m# v3 F' D. evoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
1 |( ?! x9 M4 f4 I: V2 m, C{8 I) e% ]; ~- O% O( l
        queue.data[queue.wrptr].time = writetime;8 f0 g# z1 K3 {" v) {+ b
        queue.data[queue.wrptr].addr = addr;
2 A3 O8 }  u# t/ _        queue.data[queue.wrptr].data = data;! G6 D! ?# x6 ~* O
        queue.wrptr++;$ N$ ?5 O1 u  C7 W" l' ~
        queue.wrptr&=QUEUE_LENGTH-1;; O  F) [( ~, b6 ?
        if( queue.wrptr == queue.rdptr ) {
, O1 ~7 {8 x, l, H. S                DEBUGOUT( "queue overflow.\n" );
# @% Q- u, H& P- @6 l        }
1 x, w2 d2 a( O. e}
7 F6 |0 a) V* L3 K0 ]
  J+ ~3 l' {& [+ ]* O" X6 ^BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 t. k! c9 c* v  s' g
{
  |1 g2 A+ W* V) Z$ s0 F        if( queue.wrptr == queue.rdptr ) {% ~& ]  B; w9 k) O8 n3 f
                return        FALSE;" l2 M$ \; h" ~/ d7 o5 E* ~6 g
        }& b. J# [: k( @5 s# l3 p# P
        if( queue.data[queue.rdptr].time <= writetime ) {* w' n5 N: `" ]9 S( u( K
                ret = queue.data[queue.rdptr];
% t4 o& K$ V5 n) ~                queue.rdptr++;
/ H( j5 j8 k/ j: V. ?$ Q0 o                queue.rdptr&=QUEUE_LENGTH-1;  t. ^7 y; f' g2 R- u
                return        TRUE;3 M; s4 v- K( b7 H: s
        }# A% h8 V4 U1 v& V$ d+ B8 Q
        return        FALSE;
3 [) T; O- `) L! k}- t: B+ p/ e: ?% B( Q2 Y, M4 n
  U& a2 Y2 K3 U) ?8 h2 y5 @, |
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 j) K' E( G$ P# L( i- c9 |0 H
{3 u: Z/ L& z) Z$ B/ Q3 K
        exqueue.data[exqueue.wrptr].time = writetime;- g4 [1 P+ v' P5 I8 f% ~1 W" h) T
        exqueue.data[exqueue.wrptr].addr = addr;
1 J0 A3 t% b5 L, e) g        exqueue.data[exqueue.wrptr].data = data;
+ q( K  P3 t. k% g+ }( X* H        exqueue.wrptr++;  [, u/ C. U! C7 [% j' B, a; K
        exqueue.wrptr&=QUEUE_LENGTH-1;
  a4 r9 V1 w" k: i8 a8 `        if( exqueue.wrptr == exqueue.rdptr ) {$ Q, X. M7 i* T6 Y6 j$ W) Z( i
                DEBUGOUT( "exqueue overflow.\n" );
: \! L4 T: Y) |( @        }
) c& [5 e1 W9 Y; L}6 J+ o* O. b# H, k$ k9 [

6 v( Z, R- Q/ w/ e; QBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ); v1 u# o; y) p# x
{; S$ f% G" o! k, _, f3 S
        if( exqueue.wrptr == exqueue.rdptr ) {5 W- A( ]. y' ~/ C1 ?7 k6 V
                return        FALSE;) j  |0 e) T  Z) D0 P8 L
        }$ e% W$ z# r$ b- _- }  L. ^
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {3 t) A; k4 [$ r8 @0 p4 G
                ret = exqueue.data[exqueue.rdptr];
4 R3 X: z$ k# e, |7 ]                exqueue.rdptr++;
% A5 N: b& q$ m! I( R9 R: c/ M                exqueue.rdptr&=QUEUE_LENGTH-1;: t$ M* X0 _* g& W
                return        TRUE;
, {7 J) r2 @; x8 [/ m( h        }% h( F$ S, `8 l/ w" ~7 w' h* L
        return        FALSE;& V1 o: N2 j+ `+ m7 ^7 r- U& H+ Q% w
}
0 [2 m$ D& a, K3 K( ]$ R/ U1 N6 y5 O( [: ?
void        APU::QueueClear()
' l+ A7 T5 a2 {; |* Z{
: L& S' u7 ~# h2 q9 y: f        ZEROMEMORY( &queue, sizeof(queue) );8 ?; X2 z$ R( F; [+ Q6 @8 R6 @% y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 u- Q' v4 E  y$ a
}
( s3 \+ `& q! E- u
& _  [& K3 Z$ X! J1 cvoid        APU::QueueFlush(), ~/ d$ m, `" W7 N; w
{. p3 J: K% x. @" X. a. k$ M$ m- U
        while( queue.wrptr != queue.rdptr ) {' |: _+ P3 K1 t6 g
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );( y- N) [. l0 T7 `& p# e1 b4 n
                queue.rdptr++;4 Y7 [; Z  c, Z/ G. u3 p! d
                queue.rdptr&=QUEUE_LENGTH-1;: ?* S( @0 i5 S2 w
        }) R3 M9 z2 G/ t5 V( P8 l. X
9 g6 j3 q, ], r) n
        while( exqueue.wrptr != exqueue.rdptr ) {7 s- A) ~6 |/ i9 [! n( A
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
# V% V; o! E% t, c' ~                exqueue.rdptr++;
5 L* o; ?4 V1 k5 G                exqueue.rdptr&=QUEUE_LENGTH-1;% ^  s! @4 W8 W; M
        }9 x' [# Z+ s0 {0 m6 U2 ^, n* r
}
: ]% F) ]& r/ `( [: f) M4 U& f* P* P# d* n- \: X. u( V
void        APU::SoundSetup()
9 u" P1 s) t& E3 o% r{4 h7 ?7 n) b5 l! q
        FLOAT        fClock = nes->nescfg->CpuClock;
# R$ t' r5 x3 {5 e        INT        nRate = (INT)Config.sound.nRate;
4 B: g0 g  Q# Y        internal.Setup( fClock, nRate );' z7 W6 K  K0 ^* v1 V% b1 S
        vrc6.Setup( fClock, nRate );# [0 d' V+ F  c+ u2 [
        vrc7.Setup( fClock, nRate );8 k" s7 l% U4 w7 m4 a, A& C* s8 a
        mmc5.Setup( fClock, nRate );
2 }) i3 ?9 H, q* J! f        fds.Setup ( fClock, nRate );: w0 C2 `3 {# l; v. o
        n106.Setup( fClock, nRate );
: q6 h* F# Z. S7 ~        fme7.Setup( fClock, nRate );
! i# c- Y5 `: v4 b1 A. V. Y  b% w}
, U9 \* l# S) x! m3 e+ H' c( F
9 g0 Q9 O, ^: Pvoid        APU::Reset()) L# d4 ~# X0 Z; U* W* `( y
{
  g+ l6 T/ u3 ]4 I; r        ZEROMEMORY( &queue, sizeof(queue) );. w, @3 ~) ^4 Q7 e2 x
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& A3 h: Z" a8 H+ J

  u4 @0 V: ^- o0 |        elapsed_time = 0;$ ^) ]2 A: J! l
6 W& H7 q* G. g" _; Y, e2 @
        FLOAT        fClock = nes->nescfg->CpuClock;. v, Z; v' ]6 J8 G* q* X
        INT        nRate = (INT)Config.sound.nRate;
; @/ u+ K( I1 ^% W: P, A* G4 k        internal.Reset( fClock, nRate );8 p/ J7 g, }/ [. A
        vrc6.Reset( fClock, nRate );
% P6 T4 W$ O2 m! P) n. e" I        vrc7.Reset( fClock, nRate );
- \' s! @" d' b        mmc5.Reset( fClock, nRate );
% F4 |) n$ j! |        fds.Reset ( fClock, nRate );/ Q3 U5 |8 H- e' W9 W4 d& J  n
        n106.Reset( fClock, nRate );! q: f$ A6 Y4 q% Q3 Z( y" Z
        fme7.Reset( fClock, nRate );
1 {) r6 Q) x0 k# Y
* c" X8 Y& B  m; q7 V        SoundSetup();
2 l9 ]4 I3 I1 Z: f* A% c}
. B" r/ s6 s: `3 ?. _: t7 p
$ W& V6 E9 j0 W( |9 l8 Nvoid        APU::SelectExSound( BYTE data )7 _/ t! M; s1 _( w7 N
{4 }( H0 T4 {: w# m4 r5 t! Z- E( W+ H
        exsound_select = data;
% n5 v0 C* k7 L; `}3 k  K: E1 ]1 g( D

- a4 }/ M8 n# M. dBYTE        APU::Read( WORD addr )" }/ j) n; y" x+ L/ M! N
{
- }9 N* \4 B# M! Z5 v/ ^0 P        return        internal.SyncRead( addr );
9 U/ L0 H; u, I7 S% y, m}
( W! D; u& y) s0 F" {: s1 o% G! U- ?) ^" f! R
void        APU::Write( WORD addr, BYTE data )
7 k6 S- M+ r* M; A( A) w{
. R; L! f  m2 i4 k" ]9 z! z4 L        // $4018偼VirtuaNES屌桳億乕僩: B% g. L" O, ]' H3 W- S$ h6 c
        if( addr >= 0x4000 && addr <= 0x401F ) {
' _2 l" o, e( w9 T' b; i                internal.SyncWrite( addr, data );
( l/ K7 f/ n( G/ m- n3 I                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ `* F8 R0 F: N- o9 U( }! O        }& b* q2 h9 V/ x3 Z% w8 K5 C
}
7 Z, ^8 C; \9 E2 F" w
; j& B( {' @2 K# Q4 E* iBYTE        APU::ExRead( WORD addr ); S5 |' x- F& ^2 y
{
1 o! ?+ j# S' w0 @BYTE        data = 0;1 E2 l+ ?- n* @
$ ]3 y) C0 z7 `  e
        if( exsound_select & 0x10 ) {
) Y) R, u1 [0 b- ?                if( addr == 0x4800 ) {
0 _0 L  w* H- r* w" l                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );" p! w) a8 k# F) H% a% _; k
                }/ t# m7 g4 i0 T, P) I2 H
        }2 t! }, c2 ~" d4 g. N& }, r2 n4 Y
        if( exsound_select & 0x04 ) {6 C5 f' D+ O7 z  E1 U' y
                if( addr >= 0x4040 && addr < 0x4100 ) {
- ?8 ?7 r' A4 p- M' W7 n9 l0 j                        data = fds.SyncRead( addr );
6 I* q, Y7 N+ p9 {5 ^  H3 C" b6 m                }: [. W6 f/ q/ l) P' x" u$ `
        }
; }3 u5 d3 ?4 R        if( exsound_select & 0x08 ) {' y! W3 z! D0 w( P' |* R
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ l# R$ D1 v. V+ ?. y1 \                        data = mmc5.SyncRead( addr );" _6 f! ~1 w$ u6 ?. [# B
                }
% U7 j# Y# Y+ q9 w        }
& c' p: K) u* U) I, ~: @% B9 @6 Z- x) o! S" d+ O: r, ~
        return        data;9 b: n% j0 b2 l/ @4 m
}' n- m8 I! s/ s- ]

1 N0 H; s* A' p; v6 T, Dvoid        APU::ExWrite( WORD addr, BYTE data )
! ]- v* U% y! a1 t0 I{& Y; ?) U: N- G6 Y. I5 @* P5 ^
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );: B8 ]" H: G3 [5 g9 a

, E( L" L% x: K% r        if( exsound_select & 0x04 ) {& G# _' L7 o5 `7 |$ Y/ Y
                if( addr >= 0x4040 && addr < 0x4100 ) {9 V) \, _  O4 n+ A) l( \* O
                        fds.SyncWrite( addr, data );4 K$ o) ]2 z6 N! x7 u
                }8 o: c- Z3 s  {. H# J7 F7 R
        }
  }! [& T; r1 i4 V, N
- K  R; y! X, f. X7 I        if( exsound_select & 0x08 ) {" P9 \/ U& R2 L8 h
                if( addr >= 0x5000 && addr <= 0x5015 ) {4 Y' o5 C/ X# J8 F# k$ l6 O4 ?
                        mmc5.SyncWrite( addr, data );5 c3 y' G6 ]& v0 O! O
                }* G" [. _% P1 n1 O5 L
        }
* O* H% `9 w  |, C4 ?}
+ j' t. r+ O+ \+ x% |8 s4 `% m; z. [3 L
void        APU::Sync()
: _4 z/ @, m$ b/ G# o5 u{
8 S- n& r/ P; ~0 G0 Q# N2 N* N}& d, q" a9 @0 }' D
4 i% r! ~# f5 b. F1 r9 q
void        APU::SyncDPCM( INT cycles )
  h- I5 {* a& s0 N/ b. {8 a+ D{
7 ]4 D5 O  U- S9 v5 J  O3 R        internal.Sync( cycles );
0 K9 _% y0 c& O6 F% a* d2 M0 c) c8 ~6 ~& `
        if( exsound_select & 0x04 ) {8 A( T4 |2 h' ^3 Y6 u: E3 u' P
                fds.Sync( cycles );
- |: J/ d6 W+ G1 h        }
0 s, b1 J5 }. v. r        if( exsound_select & 0x08 ) {& ~) x4 }+ J+ }4 `) F( t! \! k
                mmc5.Sync( cycles );
( V# W. d: O% J% [0 F        }* g2 S7 L' q) N: W: h
}3 [5 m! D7 i* j# C
% r4 Z! X+ u# T1 p4 p0 I+ d( a" s
void        APU::WriteProcess( WORD addr, BYTE data )
1 D4 S- I3 E6 j9 z; N& t{
9 K$ T7 U& M0 u# i        // $4018偼VirtuaNES屌桳億乕僩3 H: a( c+ ?, M4 V' \# ^; e
        if( addr >= 0x4000 && addr <= 0x401F ) {
# l- {1 L% g; Y" y                internal.Write( addr, data );% D7 R7 c. |9 I& v& d
        }
& H& J% r( B) l7 ^}
, H9 t- M* H3 U8 g( v) w8 i
/ D$ Z( t7 [0 K! o* S0 q2 A5 I0 e% tvoid        APU::WriteExProcess( WORD addr, BYTE data )$ I  G8 b1 S& F8 l7 U# F5 Y, F
{8 W( e$ s- D( @: ~/ m. E5 T
        if( exsound_select & 0x01 ) {& E6 H7 u% }# Z1 e2 K( i
                vrc6.Write( addr, data );
1 k0 y4 _; i; U( q4 z9 o! n3 A        }& r( N  U9 D: P6 ^4 m/ r8 K: U8 E* q
        if( exsound_select & 0x02 ) {
1 J# Z* O( Y6 @" J1 p5 Y5 c, h, E                vrc7.Write( addr, data );
; I* r" h3 P6 \% D/ a' j6 X6 W        }+ n3 P# T7 q- q/ y% |. U( L# N
        if( exsound_select & 0x04 ) {
9 M5 H, [9 R) Y( e2 W' a                fds.Write( addr, data );: L) V5 V/ B1 H
        }5 N" [. ~$ h- b, u; Y8 f! d
        if( exsound_select & 0x08 ) {
% N9 J& |" ]3 X                mmc5.Write( addr, data );# A6 {" X& n5 `# N' {; n4 k
        }8 R0 ?; F$ G# A
        if( exsound_select & 0x10 ) {1 T& ~1 x9 ^! D" A$ o4 F" s
                if( addr == 0x0000 ) {
$ u" ?8 i* d. Z; K6 T# n( B4 c3 A                        BYTE        dummy = n106.Read( addr );
5 V& C" k' P! o( [. j$ ^; I+ t0 W                } else {- _$ [. o, R( d- ]
                        n106.Write( addr, data );% e! t- |2 ]( Q+ b6 m0 `) C2 B8 l
                }) x1 |& r' p% C9 z  O
        }
: X  A1 l+ S/ A4 f        if( exsound_select & 0x20 ) {
' L8 i" q0 ]2 T/ h2 Z! p8 [6 V                fme7.Write( addr, data );; v( ?3 U2 ^3 T! s" H
        }! p$ X# H. ?; ]4 i
}. a' x" V7 @5 F

6 q8 n; u  i. ~6 e9 F9 Z; K$ Wvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ r% u) M7 y+ {1 {/ l{3 n8 |% }7 i: }8 u; i/ L
INT        nBits = Config.sound.nBits;% b, [  F0 p1 T
DWORD        dwLength = dwSize / (nBits/8);* p0 p5 A4 U  F7 a! Z) f! m* ^
INT        output;6 n9 l8 e: p. Z0 I) Y' `/ G1 |
QUEUEDATA q;. `$ j6 x7 Q6 F; G6 I4 n9 a
DWORD        writetime;
+ H# c5 T: }! s, d! N) z8 ^% [# M8 a! U5 S' {( I
LPSHORT        pSoundBuf = m_SoundBuffer;/ o# @  m8 a+ @
INT        nCcount = 0;
" Z& b6 a# G3 d& Q: q8 H& ?5 G. g/ A
INT        nFilterType = Config.sound.nFilterType;$ h- m2 |9 z2 Y# s

# M: s# B4 m, V7 h! S        if( !Config.sound.bEnable ) {
. w7 ]$ u( i# _" G/ x* |                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
: E8 v1 ~9 `6 ]1 u                return;
9 P( \* K  |& f        }/ x3 a3 r1 V4 n* J. D9 j8 ~: ]

: |% ^' |4 a# L$ ]0 N        // Volume setup2 h+ O0 Z4 I# X" i( x4 z. M
        //  0:Master/ d* ^$ t) v0 i3 e' o
        //  1:Rectangle 1
1 A0 j& z' ~" F1 K! d  ?7 K* U        //  2:Rectangle 2- F# B$ [, F, D$ f
        //  3:Triangle
. s3 {; s, l0 u. B( a        //  4:Noise) b4 `& g( l* O5 N' ]% ]
        //  5:DPCM
# f, H: q, v' F& C        //  6:VRC6
/ j6 K% p8 d5 |& F        //  7:VRC7( B8 I9 \; @7 }! c
        //  8:FDS; |1 U' O: |) o5 g
        //  9:MMC5
" O. |% a) E3 c2 d8 F3 B- V        // 10:N106
: I, V( ^( k' w2 y3 F- ^" {: ~2 l        // 11:FME7
5 u; O( ^7 g3 F) f        INT        vol[24];
1 F$ P6 T' g' f2 \        BOOL*        bMute = m_bMute;% k; y# j8 |6 X- x5 n0 _
        SHORT*        nVolume = Config.sound.nVolume;$ q. Z7 A8 |. R! T

5 L& ?  [; k3 D5 W( N% k        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
2 s" N  E" y0 m6 u6 H; D
$ E5 x% X! x: ^' v7 R        // Internal
" w7 }5 h6 O" Z* m; b  ^        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 ?% _4 {6 f8 }1 ?# X8 `# V& R
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
) D6 d# n2 x( J/ ^        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 w6 \  H( ]# k/ l* \
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;: }# l4 }1 x! d) X/ G5 B
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 [# ]. N# K' S. D
  y  k' s  U7 X  e( G3 Q: e  [9 R        // VRC6
" y6 l, p; s6 c, i( P; ^        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- q" x& x6 l6 z0 X; P5 I
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& @8 n( n' z8 s3 U- n
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ i+ Q$ ?1 l& a/ Y. \& p
+ g) `  \7 h. O6 _4 Z6 h4 g, Q        // VRC7
7 \, N; p5 [; |& e* v0 h2 K  m        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;" _: k- ?6 |; ?* F4 h

% I6 }, m0 T( j  \4 C4 J( H        // FDS
- p4 W* E- K4 I) d( A        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;2 g9 {4 o' s; s7 t% d
* L; W& K) G2 L& p
        // MMC5  [# ^) G" t: A( N- x9 O! t+ ]
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 F$ ^7 f$ e& b" P- ]) R& a9 C( [
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 e' I# ~5 a. n        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 s: y. O8 M. A; {  H8 H' k" z. A( O  W/ p
        // N106
$ O: X1 F" E% `9 `/ L  O        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  b; J# H+ u& p9 V4 X  p        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( @2 _. L5 `$ |- U- @" q1 |! h
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 }/ U* \" ?4 V        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ p& _. V! p& x$ r# B
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ C' ?3 `  f/ a! [7 A% u  ?+ D
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 W7 l( _6 l: ?. |        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ u7 J8 t  K( u; `- [) [( v
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 e8 J: L# y) w6 g+ g7 X/ V& u9 [4 W4 y0 I7 h8 v) C5 c  H
        // FME7
9 F; L/ b: S( e3 l3 c3 i& b. [% n        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( \5 N' F5 @$ l' z% ]: ^
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ b& W; d* o" f( F3 }        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" g. m4 y" P9 k& S- @
3 t$ h, d. j+ ?- G9 t/ K//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" W' A1 M: D# C0 x; p9 Y9 Z- e( R% Z        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;- @; ?& b; i3 S& v. E

+ W- Q* G, R  K+ d4 z        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& X9 D# ?1 W/ R- b& a' D# J
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# t  |' p+ A& _
                QueueFlush();
8 J' S# i/ `6 l$ s* h) k5 P& n; @        }' K! ^$ J& ?" _. @, U6 r) [# Q
8 ~. o$ b! K! t- u' N% }9 z
        while( dwLength-- ) {
" D1 W% }% M3 V* f! ~# ~                writetime = (DWORD)elapsed_time;
: Q1 x* g# x5 r! A6 U
6 a. ~9 S* v, L" Q4 U6 D3 V5 K                while( GetQueue( writetime, q ) ) {, a9 z* S; N! J( r& r
                        WriteProcess( q.addr, q.data );
- `( P+ A1 B% p6 Y                }
# ~) h. a5 \1 A: S% A+ ^7 _( G5 L0 K2 m% _+ q7 F( c
                while( GetExQueue( writetime, q ) ) {
: m! C2 p/ q1 g2 J  @( o- ?                        WriteExProcess( q.addr, q.data );" {' X3 @! f8 K2 r. d: R/ V
                }
- E+ _/ \: F# |6 [8 u$ L4 c
+ d+ h; z/ m+ e0 b( ~2 h                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME73 u* G2 {: }  R) {4 E
                output = 0;
9 ~/ [# S9 A( ]9 k: w                output += internal.Process( 0 )*vol[0];  Y1 S2 b! Z; ]* }: i4 [* j
                output += internal.Process( 1 )*vol[1];
4 B* Y" E* H3 {  Z                output += internal.Process( 2 )*vol[2];3 A# A' N: W: @
                output += internal.Process( 3 )*vol[3];: M) S8 u$ u$ |
                output += internal.Process( 4 )*vol[4];
2 C2 M/ S3 @* e2 B+ H8 \! a) n: {7 M5 G4 ?8 c
                if( exsound_select & 0x01 ) {9 f2 x4 L  _0 V4 U
                        output += vrc6.Process( 0 )*vol[5];/ J. A: z& D) V& D% l9 _" _* |
                        output += vrc6.Process( 1 )*vol[6];
+ U% r) S0 X" t' o3 O' m                        output += vrc6.Process( 2 )*vol[7];
# f9 Y* l' z8 y4 m2 C                }9 v* J: J9 s" D. w
                if( exsound_select & 0x02 ) {
# E1 V( Y7 E) b; J7 u                        output += vrc7.Process( 0 )*vol[8];
2 F( p0 N8 \8 ~+ Z5 {; n                }$ A% `$ m) i) T# _! v+ a8 d
                if( exsound_select & 0x04 ) {
+ C: b- s/ e+ G& e3 Z, N                        output += fds.Process( 0 )*vol[9];( X( L  ^4 Y8 w( ]5 [0 w
                }
' T& b5 {5 E  Y1 {* \& r5 r8 L                if( exsound_select & 0x08 ) {
: t3 W* o* G0 n8 Q( y' D                        output += mmc5.Process( 0 )*vol[10];/ g: e) K; }% G2 B
                        output += mmc5.Process( 1 )*vol[11];
, T, N: P, m/ `6 T                        output += mmc5.Process( 2 )*vol[12];" R. W" }; k# j: J+ q  a; y4 j
                }) @' x' w- C# W/ |& m
                if( exsound_select & 0x10 ) {3 G& J+ x" D% O) o, L% M& Q
                        output += n106.Process( 0 )*vol[13];% ?7 f1 ]2 u$ R* k) S4 I. Y
                        output += n106.Process( 1 )*vol[14];5 j2 C5 M6 W8 {) l6 p
                        output += n106.Process( 2 )*vol[15];4 ?# S% W" }0 d5 s5 Y: M9 i
                        output += n106.Process( 3 )*vol[16];! B( W2 i- |! v; R
                        output += n106.Process( 4 )*vol[17];& I7 K/ d8 |$ z8 [5 R
                        output += n106.Process( 5 )*vol[18];! ~- L, |2 G( ^5 m
                        output += n106.Process( 6 )*vol[19];% _" I; }% e' r/ u" G3 j/ a: T
                        output += n106.Process( 7 )*vol[20];
. O( U: _5 G, p4 W# N                }* h& I4 }' F, h: y
                if( exsound_select & 0x20 ) {/ W/ W& m# b1 d5 m# C
                        fme7.Process( 3 );        // Envelope & Noise3 j$ d! \1 X$ O5 P3 p  s; Y- p3 F
                        output += fme7.Process( 0 )*vol[21];
8 h( S2 W- |8 r8 Y5 _                        output += fme7.Process( 1 )*vol[22];
' b% ]* A" ]# m/ J; z1 u                        output += fme7.Process( 2 )*vol[23];8 g; y7 z% z7 W4 e
                }
2 a) n) K9 Q% y& }/ K
: b1 F; U/ M4 q+ e; C/ S                output >>= 8;
; l! @, U1 L5 l# ~" y
8 [3 ~. W. \) u& G                if( nFilterType == 1 ) {; L* ]  A" M, w
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 s+ N( i( V7 w* j
                        output = (lowpass_filter[0]+output)/2;$ B/ C4 j+ D6 z; P' V
                        lowpass_filter[0] = output;8 Z$ a' o  j: b' b6 D4 C
                } else if( nFilterType == 2 ) {2 E2 a' @  |# u  t/ P
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1). Y& g0 X& Y9 q4 j& A3 Z! I
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! D" @8 E/ N! _/ I  [5 c6 o& O                        lowpass_filter[1] = lowpass_filter[0];: x4 G6 b! H, U0 K
                        lowpass_filter[0] = output;
$ B( \6 Y5 E+ M! V                } else if( nFilterType == 3 ) {* L9 c' h8 p6 E
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
  n3 }) n; e' v5 ~+ w                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" [6 r/ ^  I: s- f& x                        lowpass_filter[2] = lowpass_filter[1];
/ a9 \5 w& C! o. L! d2 H6 y                        lowpass_filter[1] = lowpass_filter[0];
2 c* B3 M0 C9 N  }, t1 y                        lowpass_filter[0] = output;
, X/ O' N, I) `0 d# }                } else if( nFilterType == 4 ) {
- `  @. p0 O) x; {' F, H                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 ~" `7 H) I  a2 {
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
& G# `- Q+ l% a2 Q4 g; m; b                        lowpass_filter[1] = lowpass_filter[0];
3 ^; D- o5 |9 e) {# x# A9 p  l. F                        lowpass_filter[0] = output;
3 T  Q6 C9 q0 u/ j/ L                }" l/ x% _/ J! \5 d

& U8 N! f# P; N9 J#if        0
4 k  F" P& y% J: C                // DC惉暘偺僇僢僩- e3 {& w  N! L. C
                {; D2 k; U- O$ U, P  q( E$ U/ U
                static double ave = 0.0, max=0.0, min=0.0;3 B% [- B" l7 ^$ w- d" q
                double delta;+ D* G5 D# O. {' U7 d' B1 r8 A
                delta = (max-min)/32768.0;
; t! P+ \3 l7 ^                max -= delta;
9 o  `* Q' v$ u3 g# M$ B                min += delta;  a  `# X& h! o7 j+ K3 |( _
                if( output > max ) max = output;
4 r' S* e8 H4 f$ Z: M* p% L                if( output < min ) min = output;
% s8 N* ?/ k+ W- K! T                ave -= ave/1024.0;
! l& G) q. [7 y( p8 O                ave += (max+min)/2048.0;) H8 \; _2 p+ H8 h: d% `* Y1 e
                output -= (INT)ave;
8 I+ w5 P8 a  _  Q+ Y9 C                }
3 ]# \( Q2 {# e4 h2 c/ u5 x' L! H#endif
2 E; H9 a& k# W! i% U2 ?4 m$ G#if        1- ]2 v+ L, ~2 m
                // DC惉暘偺僇僢僩(HPF TEST): f) l* z6 E; W  L
                {8 o' [( m, U1 z+ f4 g/ E
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ e; k, O7 Z0 i! Y" _# M) }0 s                static        double        cutofftemp = (2.0*3.141592653579*40.0);
/ \* v# p+ U. B2 \                double        cutoff = cutofftemp/(double)Config.sound.nRate;6 u1 H0 t. ^% q6 D3 S: B% ~
                static        double        tmp = 0.0;
  I- C- h. k" j  d% ^! g8 q                double        in, out;
% `' e) @# v  T1 c, e
6 |( i0 R% B6 k1 @+ \6 L8 R/ Q; ^                in = (double)output;
# N" \& j0 s2 S3 m                out = (in - tmp);8 N4 T% A  m* D' |
                tmp = tmp + cutoff * out;: }- U2 T0 H% ?
8 y! [  Z1 u# u
                output = (INT)out;3 }' t# V: _3 J. P
                }
' M0 |/ k6 ?! K: m#endif
5 k, T3 Q# A. ~: Q3 u#if        0. `, _2 \' v  p5 ]1 Z4 e; i
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  \/ Y$ @) H: w! i
                {
3 u; r( I# x# I$ \6 u& }& X                INT        diff = abs(output-last_data);6 H8 V0 I8 w% I* c' j6 y* J
                if( diff > 0x4000 ) {, h* T$ I8 ]4 B1 @* a: \. b; w
                        output /= 4;* b9 Z1 T( ]0 e9 y9 D# Y
                } else 9 M- w( c. d( T* j3 O
                if( diff > 0x3000 ) {
5 ^- A" E" `+ Y' y% w. W                        output /= 3;: }$ M/ n: U$ E# o$ d
                } else
1 N' ]1 K+ x1 S                if( diff > 0x2000 ) {. g2 N! C3 v( U* V0 ]3 s
                        output /= 2;
7 t: _  |2 |) N& L                }; Q* ]* _& F8 k
                last_data = output;
- {4 N; h8 N; b/ W: N" F                }
& G$ B' v. i: T6 [3 E& q4 Q2 F#endif1 |' q1 h: Z% E# ^' l. Z
                // Limit
9 M0 S1 m6 f, H                if( output > 0x7FFF ) {/ I* J4 o: c% P
                        output = 0x7FFF;- A  }+ c) }5 c) O& ^
                } else if( output < -0x8000 ) {' @& k0 a; R3 M- o
                        output = -0x8000;+ R4 X( G6 a5 Z0 y6 }& G; d; P' k% p5 g
                }
  c5 S; N+ X  H7 a& O" j! R  I3 z9 a7 K  r3 c) x3 ?
                if( nBits != 8 ) {3 L  _* C9 M" }+ R/ f4 D0 V; O
                        *(SHORT*)lpBuffer = (SHORT)output;3 F% z) s3 o# Y( R
                        lpBuffer += sizeof(SHORT);+ P2 V6 w/ O/ V; l$ I/ D7 Q
                } else {
% [! N  {( J7 V( t- J) ?+ e                        *lpBuffer++ = (output>>8)^0x80;
  T' @0 J$ \, V! D: `* }; w                }/ C1 C4 ?8 C; T& E
, o6 F6 ?2 ]3 P: I$ z
                if( nCcount < 0x0100 )
8 S5 y/ g9 x' b- N6 q                        pSoundBuf[nCcount++] = (SHORT)output;
$ w3 q( M  I+ k
0 o0 {2 ~* V+ |6 K$ d# E//                elapsedtime += cycle_rate;# B4 F5 B% l  Z
                elapsed_time += cycle_rate;
6 _- t. I# Q1 I& G$ P6 A        }
% A& T, S1 ]# h) n
3 d8 W" c( ^0 z2 W- h0 G1 |6 K; S4 `. E#if        1
% l! ]+ O/ f6 r8 G- g* |9 |        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {; l% D4 [( V# v5 q
                elapsed_time = nes->cpu->GetTotalCycles();
: q, o- a: z# E) s2 L& G        }/ D1 D1 U6 c$ G! m
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
; n2 N# {$ \$ y9 V' b                elapsed_time = nes->cpu->GetTotalCycles();6 m/ b$ E5 B3 ~$ v1 G
        }
7 Z* Y; N$ L! d3 r& W" I7 q% y#else. P9 e5 X; N7 R& Y
        elapsed_time = nes->cpu->GetTotalCycles();
- p5 S6 K1 ]3 {#endif6 t" T  [& _( h# I' @: x+ m% |# p9 Y
}
7 V: s' B' b; m1 k* ~" y) s
3 `+ A: T* J- O# E// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 J5 g) ]$ M" q. w4 X9 lINT        APU::GetChannelFrequency( INT no )
# J0 g4 @9 M! B) ~2 V9 N3 }{
# u0 {0 z! `. D7 F        if( !m_bMute[0] )
' M2 }4 F6 V( x: p/ R/ K9 A% [1 h1 g                return        0;
: w/ }9 _* q5 M# c0 z$ M+ j* C) M  F7 f3 s' X
        // Internal
* Q9 d4 s% U- c+ u" {# L        if( no < 5 ) {5 j$ M) i5 [: w  J
                return        m_bMute[no+1]?internal.GetFreq( no ):0;) U7 \2 O( @  d2 w6 O' [# x
        }
+ e3 W1 Q4 }( X        // VRC6/ ]& ]# Z5 S7 ^2 g) e/ D' f8 H9 b) h
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
5 ~; f+ R/ O  P7 L" h                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 i) [$ z8 |% E- @
        }
8 S2 B. |3 i/ G* ~4 C- f' r        // FDS
6 Q. Q4 i1 W4 C  D3 j( h        if( (exsound_select & 0x04) && no == 0x300 ) {3 Z* B6 Q7 h2 t, q
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
! C+ b" G& k9 T4 v5 N! U        }9 n( G+ ^# K7 D5 b* X, S
        // MMC51 T/ J0 e( {1 _0 l7 j+ x% A9 n  t
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* D) O4 m" c" H( v, T
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
+ {% _& A, W6 T) v( Z9 N: e        }% b+ `! N* ^* h1 U# F9 u4 Y/ T
        // N106
/ ~1 X: B/ t+ H& k        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {7 c& Q2 Y7 a  O  w+ z
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
3 L; O  w/ x0 n. T% g. A  y1 p        }
+ N( M+ q) @/ F        // FME7
( x. E$ O4 {  V5 a6 \. i3 `/ k        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {+ M* i. s5 K9 Y9 G
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) R/ f! W3 ?9 H5 [- Q. ]; {
        }
% V6 u' f& D3 `/ t: \) ]2 c( P        // VRC7# j3 t; b4 V' \# _, M% r4 e* r- E
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {3 x! x  `6 f" I5 D( F0 x# D
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
0 K: R# _* @4 {. s6 m- ~        }8 N( }$ g9 G* K* y4 e; i! d
        return        0;! `: M; k# }# h% H/ g! d
}$ E" w! S; k* l3 u/ H
7 n7 p8 e: |( E( E
// State Save/Load6 e3 g! @  S. g) U, `
void        APU::SaveState( LPBYTE p )2 J+ o  p: F3 z  ]" R% O/ l( b
{/ Z7 K: I. B) c( B* y6 o& ^4 a
#ifdef        _DEBUG- D* s0 b5 A7 w8 c0 g' p- Q) `2 A1 ^
LPBYTE        pold = p;+ A  M$ R) g. W, B( |* \: m' N
#endif
2 Z: x. S9 Y( R: d; r
7 K; M0 @, @9 W% j% B        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 S+ K4 O& ]# C$ E6 X8 ^7 D$ I
        QueueFlush();
! m: R5 a- B7 n, e- p0 n# B/ J  O) T$ e! u0 O
        internal.SaveState( p );& j: Y5 k$ M5 F& o- U
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 I% L' q+ h1 u) V; Q0 P2 K( y( h0 U
; }6 D& C$ t  H
        // VRC6
7 F# m4 ?) c% X        if( exsound_select & 0x01 ) {
  D7 v7 O0 c. E3 c8 D. d                vrc6.SaveState( p );. I" C1 Z7 ^0 t
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% o8 ^# v( [4 M2 ?0 R        }
+ W7 s+ g4 i* t/ ~        // VRC7 (not support); K9 h  E# |% o0 w# h! S
        if( exsound_select & 0x02 ) {
/ T  u. n- m6 p8 ]( Z# e, j; u                vrc7.SaveState( p );
9 P; T/ e* C- |; s                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  u6 i( V, D% _! U5 K' l
        }9 ^9 X5 @( s" @2 Y
        // FDS" j- d2 a" ~" b- }
        if( exsound_select & 0x04 ) {
7 I7 y1 X! w8 Z* U8 b. I                fds.SaveState( p );3 y* ?- S% \" P' n5 Y' t# m
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 o4 \% t9 I& j7 \' u# g6 U' @
        }$ A, D- X( n) X2 U* S
        // MMC5
- C! W6 i0 D3 p' r# |        if( exsound_select & 0x08 ) {
; S4 L+ O$ N/ k                mmc5.SaveState( p );
3 |7 D4 J5 L- `8 d                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) P9 \4 @8 `; a! M# o3 U        }+ B3 S; y+ K0 p+ n
        // N1062 W+ r0 p+ \6 P3 x- Z3 t
        if( exsound_select & 0x10 ) {
/ S4 P# \1 p6 C3 V$ n5 U/ b, U                n106.SaveState( p );% e: q7 G! I' N) d
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& f3 W9 \, }) m+ f
        }) ]% S. g/ q2 _, u, J: w
        // FME7
# N0 a8 r9 `* d! [        if( exsound_select & 0x20 ) {
% {$ o3 Q2 p9 B) G5 g                fme7.SaveState( p );
! L  M% d2 `5 P% i! x9 @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: U. C! a7 f6 I  s
        }" c$ W" S; A* D; y1 _1 w
- e; R) R. O" ^, R" `
#ifdef        _DEBUG
: L& u( f& G8 \' f! c3 V. B, U# kDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 x, O, t8 Y' W8 |' G2 A  X
#endif
# T: O- z/ G6 X$ {: s, M}( k* |2 F9 Q" @1 ?! `

: C, O: g8 x; Q& H/ uvoid        APU::LoadState( LPBYTE p )0 I5 Z) N! k- U' ?
{# E; Q; o: L& l$ `/ A5 C% N, [6 x
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
' p& j& M. m* r9 d  x- o        QueueClear();
' u, \: t6 Z4 A5 q; Z9 X
; X4 K. V3 p$ E2 I, m        internal.LoadState( p );* _( Q% e' O" O, O' Y7 B
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! N1 t: V9 ]+ e# f- x; f
3 X# t1 e8 j  }4 z# C- G5 s        // VRC6# b# x1 y; b; w2 H* P
        if( exsound_select & 0x01 ) {
/ E( [. L) z4 n9 [3 F7 V6 |                vrc6.LoadState( p );
+ G: g3 N9 V  Q; G: X; f- n# b                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" V$ X5 h( H/ j' ?# r- {7 e        }( ?! Y6 {5 D$ V) [0 ?; E* X# V# `6 W
        // VRC7 (not support)8 P0 u( t  E* |; x' M
        if( exsound_select & 0x02 ) {8 i: J7 I  ~/ w# y$ ?' y
                vrc7.LoadState( p );
) x# x, d# @1 \# A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 o4 _' o4 Q' C& H! z0 Q9 a# X
        }( T. q5 D7 q5 ]# C
        // FDS, Y& T2 n, I# H2 C% P
        if( exsound_select & 0x04 ) {
2 F2 d; a0 _) ^6 K6 C                fds.LoadState( p );6 v) _! Q2 B8 q% M
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) f* Y( ~8 v7 w% ^0 X; P        }
* y# W+ C1 b0 x( P        // MMC5& K8 H! r4 D; v3 }3 f+ _
        if( exsound_select & 0x08 ) {
* f8 @" L9 S% ~9 R5 w0 G( X( z                mmc5.LoadState( p );
- Q3 v" e5 n* H8 h9 x# P1 A! w                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, O; q1 h& A+ U: _
        }
& }( w1 T7 ]4 H8 [        // N106
! e' ^; A* n# ~& @* s        if( exsound_select & 0x10 ) {
4 B' s  b3 m" \! ^4 `, _                n106.LoadState( p );
0 R- g- R. X' z9 R+ \. k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! v% R; d; D3 a1 L        }0 H* i3 C* W& N, N
        // FME7
" U# F/ V+ P  ?. L        if( exsound_select & 0x20 ) {/ x' L4 B2 T+ P4 B1 s! z. f
                fme7.LoadState( p );/ f  Z% d! q& V1 L$ c4 G) u* n2 ]3 f
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' k6 {9 E8 i; z  I
        }8 E- r; m* t/ r, V9 u4 Q
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( ?( {# i- t: y3 `) |) q3 B6 w可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 w9 O; i7 V1 t. |7 Q3 o0 ?
感激不尽~~
: r. b6 E' a) r  `3 N% W8 O
恩 我對模擬器不是很有研究,) a% S- r/ a3 p2 u2 J
雖然要了解源碼內容,可能不是很困難,- [; P/ [+ @7 J
不過還是要花時間,個人目前蠻忙碌的。3 o' [! }0 V) Q- E; [& E& Q4 f( i
! T" @5 T; N) H8 x0 s
給你一個朋友的MSN,你可以跟他討論看看,1 l7 @0 Q7 G0 H! a7 w' ~# q. w
他本身是程式設計師,也對FC模擬器很有興趣。
- d0 F4 D1 v' t: X, b: F* K1 U1 G3 H5 c4 R
MSN我就PM到你的信箱了。( V: u3 }+ Q" V

4 u4 w  L; B  O希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
& }7 b, c% J9 _. d呵…… 谢过团长大人~~

* ]* I7 L0 e$ z1 S5 k
0 n. |' i2 U% a! N' c9 e* X哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & e/ j& V  T( N" _+ G& q+ b: W
团长的朋友都是神,那团长就是神的boss。
7 a- C% C, A' i  \2 K7 F% Z
哈 不敢當,我只是個平凡人,
# H1 K$ k$ y+ _( J' s! i6 [+ {& m要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙' r3 _. ~1 X( s1 S4 R4 K+ [
ZYH
  g: S4 b4 T, V% T5 O. y, dQQ:414734306
# ]5 g0 [  @- N6 t. U& HMail:zyh-01@126.com. L, h2 K* I' Q0 Q; V& p
6 `5 w) M2 E0 Q
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 5 H% @% O2 b" _% T( V3 u
再次对团长大人和悠悠哥的无私帮助表示感谢~~

$ d4 Q4 x5 b  \# f6 j; f不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-26 09:17 , Processed in 1.092773 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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