EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 R& d4 ~7 \& ~9 L) \9 u3 B楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
- @# K) J1 X( B, Z/ l! ]这里有相应的模拟器源码,就当送给大侠了~~2 O3 `8 ^4 \; x- K
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
- N( s: X1 l6 X1 x6 ?+ }/ S能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。- J5 J$ ^* Q" s8 L6 u
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 c9 |. z7 w+ v/ q2 t" \6 e. r' v这里有相应的模拟器源码,就当送给大侠 ...
7 F& l+ C7 e. z6 K- C
聲音部分(Audoi Process Unit = APU):2 B  p% o$ z& P/ N' |+ r) N: n
.\NES\APU.cpp
6 E( \. K4 ]5 @/ n3 N2 L3 L( C.\NES\APU.h5 f2 y9 y( l* ~* v# k# {6 i2 f

; Y. B; ?' q3 a* M
3 b- h- f7 G0 L) P2 Y影像處理部份(Picture Processing Unit = PPU):
: ^% p: D/ r% Z.\NES\PPU.cpp
0 Q8 b) @6 Z0 Y.\NES\PPU.h* b) }0 i1 `0 ~
/ s5 L8 u5 D7 w8 e0 m9 Y' n9 a$ O0 L
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* e' x6 b/ m4 L" E# `+ C6 E
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:0 P3 L% {/ y4 q+ T5 M6 i. r' ?
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
/ m+ P' g1 ?2 n; M4 d. |" l//////////////////////////////////////////////////////////////////////////
$ Y( M$ S5 g! _0 e! P& x, i//                                                                      //3 z) @0 O; |& h$ ~6 |
//      NES APU core                                                    //+ y6 i3 o. t5 ]) T! w
//                                                           Norix      //5 I+ K3 A7 {, x1 X5 y. m4 G1 i
//                                               written     2002/06/27 //, z: F  w; ?. S
//                                               last modify ----/--/-- //
: Z) w$ j3 }' V5 ?//////////////////////////////////////////////////////////////////////////
5 f1 X6 y" t7 g9 C: X#include "DebugOut.h"$ `1 ~; J" h( z- [
#include "App.h"4 V9 R9 e* Z0 [. A4 c; L# l9 _: x$ ]9 }
#include "Config.h"
% `* n& I6 P+ P' `- K8 h% j
& S( P1 @6 }% {- |6 a4 g#include "nes.h"
  `4 L3 ^9 u5 G/ s) `5 V4 z  J#include "mmu.h"2 {8 K' r4 x. @+ w% b
#include "cpu.h"
. f1 o+ V- d' x' V! s1 T#include "ppu.h"
3 {; V* J8 J2 T5 t0 [" G#include "rom.h"4 F1 @4 f" e" t8 b/ i/ k
#include "apu.h"' Z& l9 \$ I9 M
: S0 O, b0 G5 r9 V3 a
// Volume adjust$ w4 v0 J6 q. S7 g% Q9 ^/ c
// Internal sounds; g: a, F4 C+ H, Y6 t3 Q" I% G
#define        RECTANGLE_VOL        (0x0F0)
) n: p4 w2 d& U) p#define        TRIANGLE_VOL        (0x130)" s$ i" e+ Z8 k; J, o) ]/ j
#define        NOISE_VOL        (0x0C0)
! a. `; z- V9 a0 i: f) P4 j! G#define        DPCM_VOL        (0x0F0)5 @1 ~! {) `9 b
// Extra sounds5 c7 Q8 Q$ c7 w
#define        VRC6_VOL        (0x0F0)" \& W) k4 f% \) K
#define        VRC7_VOL        (0x130)
' N1 d% `: \+ m  D2 ]6 ~#define        FDS_VOL                (0x0F0)
6 ]% ?" g7 a0 \0 H7 N; N* }# z4 @& k' [#define        MMC5_VOL        (0x0F0)
( H, Y  v2 z1 Q" z7 N. f9 w#define        N106_VOL        (0x088)
5 ~- J! m1 o. \  E& S" r/ x5 ]#define        FME7_VOL        (0x130)
' V* @* v4 S8 O# w
4 Q! X1 t: ~% B6 Y- p9 `" WAPU::APU( NES* parent )/ F- c/ o/ N( W4 `$ q- X7 k. a
{
* q! D2 ?" h4 ^        exsound_select = 0;( E9 j( o; _( y( K( q+ d: m3 y
8 ]  g. U( J$ t
        nes = parent;
* K1 L/ l! k* D0 P        internal.SetParent( parent );7 K  G+ W5 u2 v2 z& K$ H% C7 b; ?

1 D$ }' B$ Z1 M; D        last_data = last_diff = 0;2 a; Q" O' ^; N& O9 M; q
0 a8 p- X7 @5 z+ M* o, u
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
$ B% ?  p7 v- t  j& U7 a  a3 q4 X& h& Z8 J: ^) l$ C) A- u' `) E* v- r8 y
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
8 u2 x+ |0 W$ a1 d, y2 C9 Q        ZEROMEMORY( &queue, sizeof(queue) );% I& n" X1 x( U2 \
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' |  |- V/ R' O* R/ r) R2 E' ^" W, P% B% _. ~
        for( INT i = 0; i < 16; i++ ) {
- j) M2 ~1 x6 Q                m_bMute = TRUE;
& C5 F' |0 L- |! O4 G: F        }$ p( i$ U& W8 W% Y  ^7 E- g) {
}
  ^0 [* s7 u5 W& @8 ?3 i& ^6 a! z& @5 Q5 V8 a
APU::~APU()
+ p+ K- M5 Z% X( \& {, p, m8 J{) o' [) ~4 \- A* I$ c
}$ h  P  S2 R6 X0 d  F/ E8 F% ~
$ D' W! U: A- Z$ V4 c& P) {
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
  x" d8 ]# _- g$ b/ V$ A3 N{$ f" ]2 x3 `% h/ U
        queue.data[queue.wrptr].time = writetime;
  ?" z- A+ `; I! U1 J- Q        queue.data[queue.wrptr].addr = addr;
! f8 b3 A% B; X% I        queue.data[queue.wrptr].data = data;8 V5 B. S* ~: Y  ?* D3 F
        queue.wrptr++;
. T6 P, D: g* d( h        queue.wrptr&=QUEUE_LENGTH-1;! H( W/ o- ]0 w- r  A/ J
        if( queue.wrptr == queue.rdptr ) {
8 u: K1 b/ Y7 ^  J) J4 B                DEBUGOUT( "queue overflow.\n" );
/ ?! _7 N' U6 C' u0 B* k' p5 E        }
0 I" z& @1 p2 c7 ]! d}
/ y) t- i; P5 H5 O) i' [# a1 ~  k2 ?0 i1 O
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
0 k; l8 Y6 L$ u! O. l{
6 l' _0 y8 g# n7 r        if( queue.wrptr == queue.rdptr ) {7 |! e! y2 K& a$ ^6 K; c
                return        FALSE;
$ y0 m3 I; [" {; \! y4 F" q        }' z5 i6 `; [! s# J% d6 f, s6 u6 {% B
        if( queue.data[queue.rdptr].time <= writetime ) {
* b7 K9 V2 g+ }9 b, F" U0 I                ret = queue.data[queue.rdptr];
. S, k5 p9 [6 y5 R2 W9 L2 ]                queue.rdptr++;
6 U, z. z% q" j. F0 o6 G% [' W! D                queue.rdptr&=QUEUE_LENGTH-1;: w* {0 [  ^6 R% Z- p; Y
                return        TRUE;4 C4 h, ?8 ~& ^2 E
        }
/ a- @- A9 G* f        return        FALSE;# ~6 ?. k" [! ]/ k4 w9 P
}) ]8 Q) Y! L7 E& Z9 M3 P3 h6 J
$ Q2 c% a; P. f
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )5 x6 L# `7 ]# ?
{  t0 i8 l" Q' B; P' J. w( s& C9 I
        exqueue.data[exqueue.wrptr].time = writetime;
; n4 M* R, C9 x: J2 F. b) l# F        exqueue.data[exqueue.wrptr].addr = addr;
3 [) f( P  {, M8 E5 U( e" k8 ]        exqueue.data[exqueue.wrptr].data = data;
" t8 M4 u0 ^8 P) D# ~        exqueue.wrptr++;
% H& y$ L7 Q' P, d9 H        exqueue.wrptr&=QUEUE_LENGTH-1;
6 `1 n' P0 a# I; x* A# C+ |        if( exqueue.wrptr == exqueue.rdptr ) {& D1 ^' }4 I' n$ K8 `
                DEBUGOUT( "exqueue overflow.\n" );
$ x/ r5 [+ a; @+ b        }6 _5 Z: d0 }0 t/ B% Q) k" U& ^
}
4 p$ H0 f3 w3 j' {9 m/ V* r
" M9 v1 w, i5 g# r9 i+ dBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ); i$ z+ |' T' c. E
{3 a( o" a* f0 b& Q
        if( exqueue.wrptr == exqueue.rdptr ) {
& o' O* g% a) J' Q$ [# Q                return        FALSE;5 z: ~4 I; m3 ~" N/ c
        }
4 E& K' r6 h% z9 ~! E/ h        if( exqueue.data[exqueue.rdptr].time <= writetime ) {+ T5 L  {1 [1 G
                ret = exqueue.data[exqueue.rdptr];6 K- |& X2 S  e+ A6 j# q. ]2 U
                exqueue.rdptr++;( ^% i; l0 Y( r5 f/ i: ?. b* a
                exqueue.rdptr&=QUEUE_LENGTH-1;
: ]" o0 ^* v, ]4 S  ^6 x9 G8 d                return        TRUE;5 w* N! S4 M7 o1 I9 p; V0 O/ ]; f
        }" f: `4 V! u1 D" N8 x  ~7 S
        return        FALSE;
0 C! j  z8 s/ l% l}
3 E; p7 C7 @& S
) _, p; \$ ]# ?4 z3 L5 ^/ ~2 Y' Dvoid        APU::QueueClear()
: l  d8 I' q, k' d. r{
% u% ]' J2 @( ]- }        ZEROMEMORY( &queue, sizeof(queue) );! ^4 p/ @) Q# w* T5 @/ F" w
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- x% p9 u/ N  E" W& {, D* h& D
}
: `+ r- {( M$ O# O7 v. }. }6 ~) z
void        APU::QueueFlush()
4 \; q& h% Q# v: T' S: K+ G{" w+ W3 l" l) G
        while( queue.wrptr != queue.rdptr ) {
! w4 \4 J+ O% q, Y: U2 ?                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );- ~8 ~$ `1 _8 Z  G. E' ^
                queue.rdptr++;, [* ?2 M& k% }2 G
                queue.rdptr&=QUEUE_LENGTH-1;
1 z! x( [; U+ I        }! z% O3 ^+ H3 E" e! l1 Z/ Q9 Z
2 R0 D$ i* G5 V+ `, s% G" Y% D) x
        while( exqueue.wrptr != exqueue.rdptr ) {. w% \; {9 }" ]. g
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: B& ~$ O) m+ w3 I
                exqueue.rdptr++;
0 [1 f4 i  f7 p* h+ u0 Y                exqueue.rdptr&=QUEUE_LENGTH-1;
' X' O! u$ g  m. @9 g        }
- q- E* ?8 {- b- y- y. x; ]( z}
2 j; b6 B4 v0 [
9 Q% }5 \2 B  W( \8 {void        APU::SoundSetup()
) h9 I2 ]! E! t{, q' z4 o1 G+ ~/ F+ o# B
        FLOAT        fClock = nes->nescfg->CpuClock;
" Z' R& o, k/ k& K. B7 ^7 i! _        INT        nRate = (INT)Config.sound.nRate;
1 C+ `4 l: l( m/ F0 x, D        internal.Setup( fClock, nRate );
  U& \) ?! z1 v* G. g        vrc6.Setup( fClock, nRate );5 J% b! s( ?% f1 ^+ S# k
        vrc7.Setup( fClock, nRate );4 W5 e" \% z: N; _5 k0 h3 y
        mmc5.Setup( fClock, nRate );
/ ^$ c) c; v6 X$ h! ?! X        fds.Setup ( fClock, nRate );  E2 f0 F! X. W+ @
        n106.Setup( fClock, nRate );; n* v2 z/ s/ v% t% Z% n
        fme7.Setup( fClock, nRate );& k; _3 O% z* I: j/ b
}
  p3 V0 f4 S* i  c
; B2 ~1 ]( @3 \  K+ x8 Ivoid        APU::Reset()
8 ^' L1 c0 Q. B4 P* p& k{, J8 l% z  E" C1 b
        ZEROMEMORY( &queue, sizeof(queue) );
# m9 N; [6 M( M- U, c' m% N. @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ c& ]" Q& w) `# T$ ~' \9 e& u
0 z. u, p& a; }) I1 Z1 k2 ]        elapsed_time = 0;
- h& g* E# M6 A" V$ u5 B/ l- h4 u( R, d6 J6 [; a6 i
        FLOAT        fClock = nes->nescfg->CpuClock;" L5 U6 t. b: N' W) F  q# O
        INT        nRate = (INT)Config.sound.nRate;! t/ R5 J9 G# h: y! E$ i
        internal.Reset( fClock, nRate );
& V, q1 [8 q: s& M6 p, I        vrc6.Reset( fClock, nRate );" X& C6 q( m2 ~/ z+ ~
        vrc7.Reset( fClock, nRate );  Y5 s8 o1 D2 X2 M3 U9 i- @) M
        mmc5.Reset( fClock, nRate );
$ a) b/ z: o7 e& ^        fds.Reset ( fClock, nRate );
, Z3 P, F2 r& D( P) G4 l        n106.Reset( fClock, nRate );% i$ X  r) G2 ?& T# T8 p1 l
        fme7.Reset( fClock, nRate );. c( ^6 L& }/ h9 f, c

/ Q  k$ q# ?, ?        SoundSetup();
2 C5 W/ e2 W6 N/ a0 Z& ?; [) U}
$ F- i. f+ ?3 ]: J, N, p1 D4 b
' p8 ]2 ^" n/ @- @& J& B1 ^void        APU::SelectExSound( BYTE data )
9 k; I4 H0 R( N2 w8 x+ B{
1 g9 z/ Y7 K5 y! t9 C, h  \        exsound_select = data;/ q  }4 X0 d# K4 ]* h0 Z
}
3 {- f. f: T" A" X$ }
! F/ `) H5 D  d, A, CBYTE        APU::Read( WORD addr )
, W- E5 S; X, s. _: [{
" K. c3 m  \8 S9 [5 N$ q        return        internal.SyncRead( addr );
* k/ n1 P5 ~! ~- t}
5 ~$ S9 T; m- z4 w  P7 A. y  A  a% \6 N* b
void        APU::Write( WORD addr, BYTE data )" w' z, J: G5 a% m4 c
{
1 V$ i5 s, A9 d% q  D% D        // $4018偼VirtuaNES屌桳億乕僩
# G5 N7 L' U% [. p        if( addr >= 0x4000 && addr <= 0x401F ) {  [1 ?& G$ Z: k5 R4 X9 S3 b
                internal.SyncWrite( addr, data );
1 `* Q1 j% }6 @6 K( c                SetQueue( nes->cpu->GetTotalCycles(), addr, data );5 E) m4 [3 p/ W
        }
6 F: s  a/ g+ j' Q4 L. F' K}
6 \# }% {% T9 \8 J  B5 @. R% s& A
+ b+ E& D, V- m' C! g# pBYTE        APU::ExRead( WORD addr )
: O3 G7 V+ O& k' }7 Y# e! k& |{
9 t% e& E, Z1 U( x3 v* LBYTE        data = 0;' U/ ?$ \2 r' f: j1 x$ T

: H; W. x- I6 \        if( exsound_select & 0x10 ) {3 Y& D/ e6 T# Z- D9 p
                if( addr == 0x4800 ) {
& v# N! b( n- }3 ~5 A2 P% [4 d                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );. H2 X; j6 `- v3 s. k5 m4 T
                }
# L: H. N0 G2 v1 ]- U! W) |        }+ t' Q  F: N" V
        if( exsound_select & 0x04 ) {
% t$ a. ]& q6 J3 G8 r; h                if( addr >= 0x4040 && addr < 0x4100 ) {
; ]! T: l! W  @1 C                        data = fds.SyncRead( addr );: d% f- a0 {) T6 w2 M3 R" k
                }
% C3 a6 F6 q, N0 A- {1 S# k/ k        }
: ]( R! o1 o* t1 Z        if( exsound_select & 0x08 ) {
6 N9 w( E  s7 m) J+ r3 E                if( addr >= 0x5000 && addr <= 0x5015 ) {
' X, S9 b3 Q( M2 c                        data = mmc5.SyncRead( addr );
3 c6 P. {5 T: b# H) i# U                }
& K; g# _! O4 R        }
. q6 W7 b% \7 f% I4 o, d0 }* R; E. n' y- A" F
        return        data;* Y" d: _& O9 F5 a2 @
}5 |# {3 o2 n1 R3 F. E& T
2 v6 Z$ T  N& j$ Q. ~  |& ~5 i' y. @
void        APU::ExWrite( WORD addr, BYTE data )1 [' h: b; K! S9 H- [" [) i. O7 d
{
! o/ ~. T: J1 x) W1 H2 m7 c6 F        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );6 [# S7 N- @% S1 N- G
+ W* i. A! x# Q+ F' _# i+ o1 d3 O1 O
        if( exsound_select & 0x04 ) {6 A# S7 m; B: E) |# }
                if( addr >= 0x4040 && addr < 0x4100 ) {  O" N4 U0 C! f6 }
                        fds.SyncWrite( addr, data );- {5 B( ^5 K# Y
                }, I8 r2 W9 _, ^* T& v  z. Y% e
        }
& [& w; [1 g& m
- Z1 r1 C7 Z  ~        if( exsound_select & 0x08 ) {- [$ \8 b, T( _4 S; c. O
                if( addr >= 0x5000 && addr <= 0x5015 ) {% X( `8 c: i8 p  M! x
                        mmc5.SyncWrite( addr, data );
- Q  W- A6 c, p( N$ a& _                }
- z* F* R+ q: d7 {& b2 B        }
# w& Z) D0 @! B8 b& N" T4 O}/ [' w+ N  {6 w; ~1 X, i, \
9 R- h! ~. q+ s# T
void        APU::Sync()' Q* g7 ]7 _$ p; `" X, T1 N3 \
{
9 R5 T4 e$ A6 v. m}
9 x& ?6 ]/ p- y& j/ W
3 a! \1 h1 J2 i2 z& |void        APU::SyncDPCM( INT cycles )2 o( p4 Q$ p! `. r; i; ]
{
7 W2 e5 e) x( s4 o  i' K% ?; C: t        internal.Sync( cycles );
0 E- d+ o6 _6 X7 Q/ ^' t' R
# b9 `: U7 V. j& p2 ?        if( exsound_select & 0x04 ) {- r( F$ w" d+ ]; N& O* K+ W, B
                fds.Sync( cycles );  l6 C7 c* G/ G. P/ J, _
        }
+ t. h8 N$ k7 C' e* t9 Q        if( exsound_select & 0x08 ) {9 x  s. T8 u! f6 y2 D9 K! ?0 C
                mmc5.Sync( cycles );# E( n1 I. t- ~, ^: ^* a4 P# p
        }
- ~7 Q% E: N; C3 b" b}8 _. T2 q8 j: G& K
) ]" {5 o2 w3 Y: a/ G# C' x
void        APU::WriteProcess( WORD addr, BYTE data )5 l  w# ~" T; O& c0 U7 q
{
8 E( Q4 N1 U+ Z        // $4018偼VirtuaNES屌桳億乕僩
0 D3 ]& ^' {7 d3 F1 J" N0 o        if( addr >= 0x4000 && addr <= 0x401F ) {
5 c* q& _; X* Q) L  r, S" q  w                internal.Write( addr, data );
1 g7 X" g( w1 O7 \        }
6 F7 P- W0 G3 L$ T( J" K6 d}) w! W6 i! @4 ^. w% \6 F

( d* h: f7 k1 Mvoid        APU::WriteExProcess( WORD addr, BYTE data )
2 e2 T# v" i: H7 d( A{
* W3 Z/ F6 P" x" N6 k8 J        if( exsound_select & 0x01 ) {
* J2 t' X' m9 Z& N9 @: H2 F, ~                vrc6.Write( addr, data );) r; K* z. R1 T( C6 d4 J( N5 U) R$ X. i
        }5 U' k6 r7 w, N% V# A+ V( C, U
        if( exsound_select & 0x02 ) {
% Z. F6 f( }. ^, V# K8 t4 q                vrc7.Write( addr, data );
9 v; t/ O# `) o7 [0 ~5 D' n+ F3 Z        }
2 J  j9 y& }6 B6 w        if( exsound_select & 0x04 ) {
, F( c1 v2 a, f& o& c# v( b                fds.Write( addr, data );
, Q, j! B8 Y. [3 P, b. E& N        }' [( k% U, w( x9 Y$ q& U# g% Z
        if( exsound_select & 0x08 ) {
3 C3 b" o2 T/ w% F                mmc5.Write( addr, data );1 l/ ~, ]! z' ~- U
        }) H$ v2 ?4 O3 e! Z9 T
        if( exsound_select & 0x10 ) {2 {/ p% }3 }8 `
                if( addr == 0x0000 ) {
6 C$ r  Z! i5 X& S+ V% e                        BYTE        dummy = n106.Read( addr );; o  Y: g& x. k9 m
                } else {# \: m! H3 F3 d) f, D& a
                        n106.Write( addr, data );
: X6 g' T% ^% t8 e) h                }
: S  p0 x8 \: L# Q+ j* k6 U        }
$ C& i" j$ b9 R/ v$ |        if( exsound_select & 0x20 ) {
) V* d) U% `* L                fme7.Write( addr, data );
( n9 c) \; }( o# i        }8 m7 `! [* i5 v1 I& ~/ \
}' x" |$ B2 r2 I$ X/ a  K
# M7 m# S3 g0 F% D* V' h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
  R( q# m4 O. p0 H4 {{+ K8 U) A) H9 Z: E- S, b4 `" t
INT        nBits = Config.sound.nBits;
& X1 p  A, F* q6 L5 G: vDWORD        dwLength = dwSize / (nBits/8);
& `1 N4 ]# h( nINT        output;. }7 B& T+ F2 B- q
QUEUEDATA q;+ l  U) q# F7 `6 f
DWORD        writetime;0 j7 H$ \1 P4 G  n5 N6 g" l% q

. T( u# f2 Q/ r/ }5 [LPSHORT        pSoundBuf = m_SoundBuffer;
, _1 c) r1 P$ s% w$ }1 F& LINT        nCcount = 0;
/ N* d* s; z3 [$ B9 x2 K. k( Q& c- W1 ~
INT        nFilterType = Config.sound.nFilterType;9 w2 C" F+ H6 l* z" Q5 |" j- I
+ ^3 g# m8 y7 Z1 f, q& ~( G+ Z
        if( !Config.sound.bEnable ) {% c9 o# R( i. l/ O
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
2 D" N. q( n$ L                return;1 A- Y7 }% v$ i
        }
7 |2 `9 U) d+ O2 |) D" p& B
6 u/ O6 a, B* _: W* {/ T) m: g        // Volume setup
8 }6 h5 h# ]1 Z- u) F, J        //  0:Master$ J0 X* g! J0 k' j& z+ h3 j
        //  1:Rectangle 17 Z0 u. P& b1 E' X2 a: u9 R  \
        //  2:Rectangle 2
" D2 t: G. g' e1 H, [, r        //  3:Triangle% {2 V0 |: a- w3 N0 Y
        //  4:Noise
3 u) x/ g: R# c: P! x% {        //  5:DPCM
% H1 \! _4 a! ~* X) S6 G2 v# @        //  6:VRC6! j" [: L9 }: a2 ^
        //  7:VRC7
' F) f; q% w* W        //  8:FDS
1 {) L& U3 c2 K7 z) S+ V9 W        //  9:MMC5
- d( ^( }& X6 X7 A3 n: P1 B: |2 K        // 10:N106
8 A+ [" r6 F) t( a/ F        // 11:FME7& T: w' [. S* i6 s8 {; Z
        INT        vol[24];4 X. S& Z& m. Z; P' T8 E& \
        BOOL*        bMute = m_bMute;9 n& ^. R. O/ R7 }
        SHORT*        nVolume = Config.sound.nVolume;
3 w2 o# W" k1 R! l$ P
9 }( E6 f1 \* }, S( p& i4 x- |        INT        nMasterVolume = bMute[0]?nVolume[0]:0;8 a' a* o/ Y* X; i( v
# ^# Z( U: f9 n. v' S, a
        // Internal4 D' c" x# L& b7 g3 ^& _7 `+ w
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' W9 P9 E' W. Q, k" @8 m
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
9 \! [9 O8 P" H6 ^. F2 |( m2 ~+ h        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
7 E2 f& F7 I; r        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
4 f& ~( r$ x$ d' J0 e        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ o; ?( L4 D: t8 h
+ _' l" U; J# ]  t
        // VRC6
$ ?# f& g8 m1 ?/ ^' }2 a        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 L* y# S7 ~, W; n& Z7 C- ~        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( U) m) A5 d3 D! F, a! o, J
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. K: w+ O3 M2 R; F

" O+ t( X0 `- L3 J3 S% r        // VRC7) O# D; D% J7 y
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;& W( G" N2 g/ v/ F' q8 D

  o- v6 h0 C7 c8 `) B5 W        // FDS
/ {9 a6 [4 w' R( Z$ R9 i        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
% _. ^9 e. j7 K! @* i) C( y; A* o$ q6 ?4 u5 @, r9 z
        // MMC5
! ?' t* f7 r' t4 o- [4 @        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ y8 s; R1 {  [2 T9 n- k! ]
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! O' _' X* B" o
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: H9 E) H1 ^+ P

/ {! W8 [0 ]" @5 I3 c3 g        // N106
1 i1 V# W9 v+ l        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% c/ @, W9 e; M- Q" p9 J; i0 g! r        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 K+ {/ P. R2 s8 @0 \5 H        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 h( Z  I/ R5 b3 R9 L' p) G        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( a3 b: X- c8 u. g
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 F4 K9 g9 a) p        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 I" u" j! v& D3 T' P. y" _9 Q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ Q. i3 N1 y- l% P
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" H2 T' W  d' W$ N& a+ R
- T0 W0 ?& D! e4 l+ x& t
        // FME7
1 k7 X) q% P( B4 s        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ E# S+ ^: F. S" f        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) b/ T0 D( n& o8 @' k- @        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ U1 a5 Q8 d+ A) [0 g( h# r4 ]
1 z+ ~) }4 J. A//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ ~7 z9 {  N: J/ D/ _* u
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
" t( `& D- u! T; ]$ j* E5 k
1 w4 Q, W9 \, J) [! U* c+ q        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 A$ ^0 p( D8 R4 M4 Q' d        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
2 X0 n" c# y7 f8 Z5 E; a                QueueFlush();
6 m  L& `$ ]( [* D        }" f, m. Z: @3 S+ c
; ?& {; `$ D, \
        while( dwLength-- ) {5 f! y/ A/ ?8 i2 {! s2 ~) K6 h
                writetime = (DWORD)elapsed_time;1 J1 K3 J" p" u" M: I# O

' [, I. `0 C6 e5 [                while( GetQueue( writetime, q ) ) {' C/ y7 {/ |8 p4 z1 p- N
                        WriteProcess( q.addr, q.data );/ t$ U& W) F+ s$ E# c  J  e6 A
                }
( q* f: a9 l) Y& x* M& b7 X* K1 E3 U! G3 `) A8 S( d
                while( GetExQueue( writetime, q ) ) {
3 t7 j' ]) b- J9 ~* M                        WriteExProcess( q.addr, q.data );6 \( ?) v2 w7 {1 e
                }
$ K! U, x! [2 m% w
7 }: _& P$ W( F: m; B) _/ S1 a                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7( i4 W/ e5 Z" z. {. q1 l" ]
                output = 0;& |  _, [' K) m% n
                output += internal.Process( 0 )*vol[0];
3 ?1 f$ U; h( ]. ~4 z  v( W                output += internal.Process( 1 )*vol[1];3 {# @$ v& D7 J8 w! Z2 ^: r6 ?
                output += internal.Process( 2 )*vol[2];& V0 q* M  D" }7 v$ k, A7 C
                output += internal.Process( 3 )*vol[3];- I7 d' V9 h8 S9 u
                output += internal.Process( 4 )*vol[4];
5 g3 J- |! h% Z4 B5 S; `9 Y( N7 ~
! ^; h& C9 z* S5 g1 E                if( exsound_select & 0x01 ) {
+ v5 l0 v) t8 Y. d& |# f1 P* M                        output += vrc6.Process( 0 )*vol[5];' X' L9 b0 E8 b# j1 S
                        output += vrc6.Process( 1 )*vol[6];& k/ _' }- j+ g' w
                        output += vrc6.Process( 2 )*vol[7];, j9 r/ Y$ G. Q! t
                }" W  o/ Z9 C$ K! e& G+ _" q( P( R
                if( exsound_select & 0x02 ) {" I. E' q5 K. t2 l9 j  \
                        output += vrc7.Process( 0 )*vol[8];2 i8 r5 y$ R4 Q* q9 b
                }
$ m0 M0 |- S* h' n% l8 y; A0 G                if( exsound_select & 0x04 ) {
6 D) n1 P1 }- F8 O, E, I                        output += fds.Process( 0 )*vol[9];7 J5 v& \: h7 G- Q! C
                }" W: b7 Z' T2 |9 i8 P
                if( exsound_select & 0x08 ) {
) N1 J" V$ `) R$ T                        output += mmc5.Process( 0 )*vol[10];
/ T, O" r$ I& l+ r5 n4 \                        output += mmc5.Process( 1 )*vol[11];8 o1 \) o6 p: I
                        output += mmc5.Process( 2 )*vol[12];9 s' A, F# Q% K, @1 s% g+ t' s
                }
7 g* L: h: J# F" I) W6 E                if( exsound_select & 0x10 ) {2 u' p7 r9 E% O
                        output += n106.Process( 0 )*vol[13];
/ b/ Y$ p( x$ _4 a$ ^# h                        output += n106.Process( 1 )*vol[14];
$ l; b- Y, r' g                        output += n106.Process( 2 )*vol[15];
1 T5 T  z* E6 g- @) Q8 h4 T) Y* Z                        output += n106.Process( 3 )*vol[16];
$ |7 U& \* }5 O6 `$ z" L7 n( _                        output += n106.Process( 4 )*vol[17];3 a0 Q4 m9 c6 s$ Y- d7 b3 E* C
                        output += n106.Process( 5 )*vol[18];
3 Y* Q1 k: O* q5 O                        output += n106.Process( 6 )*vol[19];
! c) m6 C* w% k" L2 K                        output += n106.Process( 7 )*vol[20];3 \0 |+ N7 {  v# t1 @
                }4 v. }/ f+ A# ~# a3 I9 V) `4 X: h
                if( exsound_select & 0x20 ) {
/ G; h( o2 x; X" f                        fme7.Process( 3 );        // Envelope & Noise' B* P7 o( x  M
                        output += fme7.Process( 0 )*vol[21];0 p' W3 J* _% x+ f+ o/ V
                        output += fme7.Process( 1 )*vol[22];
! m  v# C0 I% W; B% V) a                        output += fme7.Process( 2 )*vol[23];
2 {0 ^% m& W; p- c                }( x$ O+ W8 d" Q* x! j

2 ~) r. X  B) y# W                output >>= 8;) G5 o8 a) p( M, e" \% w6 g# d" o( V
# k5 J2 a) {7 k; |% g) j' u
                if( nFilterType == 1 ) {. y# h8 u5 C+ V9 g0 k) {' o% @# ?
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), B9 ^* j* c( o
                        output = (lowpass_filter[0]+output)/2;0 W; z" J/ r: A6 w5 I# \
                        lowpass_filter[0] = output;
( F' ^3 R+ ^( C. |                } else if( nFilterType == 2 ) {$ j( m, N2 \+ }# q9 z) e
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ l3 k6 F7 |% u4 G1 P: [, ]2 p
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;  r; Q: X  l7 N1 b+ y
                        lowpass_filter[1] = lowpass_filter[0];
% Y! c; ~# D4 o+ @. D3 J                        lowpass_filter[0] = output;
& D, L/ K1 O' A                } else if( nFilterType == 3 ) {
& I5 Y. c, ~' u                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)2 t4 ?2 z( e% A: ^( G
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;  t& \( {! j) F  \% |% u0 u
                        lowpass_filter[2] = lowpass_filter[1];
9 `$ |. f' g+ d/ x: G' X                        lowpass_filter[1] = lowpass_filter[0];- U" b# t( J' S. ~) ^
                        lowpass_filter[0] = output;
/ T: L# l" j5 w                } else if( nFilterType == 4 ) {
8 C/ Q+ Q- i1 l9 L2 X                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% N' i4 K9 p2 ]$ g7 v0 @, n) s7 z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;; c. t/ r0 K' {+ Y6 Z: q
                        lowpass_filter[1] = lowpass_filter[0];0 `9 N- k" @* r
                        lowpass_filter[0] = output;
2 c% r" ]: D8 `; ?                }
  a( B: R! c  T  \$ ~) D. z6 n' K+ L( a8 A2 ]  A  r
#if        0# m- D5 o" f4 }: X
                // DC惉暘偺僇僢僩; M% ]- i6 L8 J. y$ y
                {! w) e* }' ?: X
                static double ave = 0.0, max=0.0, min=0.0;  V5 J' f7 o: h
                double delta;
) s) m6 @6 H- ~                delta = (max-min)/32768.0;
" {. E6 f, K3 D2 |1 S                max -= delta;
5 `* P2 n, m% Z: R; h8 {% Y, `                min += delta;
' l9 z+ l4 v% N4 D! p& R! A  |! d                if( output > max ) max = output;
: L$ G: M9 c* a: y: m& |' b                if( output < min ) min = output;' b0 [5 f) V4 K( F5 ~
                ave -= ave/1024.0;
' v. b8 E/ L  _1 r# s0 _5 J& ?                ave += (max+min)/2048.0;* k; f0 P0 k- p% v0 `' B1 d
                output -= (INT)ave;+ R6 C8 Y* {6 V. |! \; C) w* o
                }
, b# a3 {: d$ t' K#endif5 Q; e+ e  V. r/ k/ |
#if        1
6 e0 I0 y: M3 B! w8 _                // DC惉暘偺僇僢僩(HPF TEST)
; n( \) B6 H) |! m; B& S                {
" Z( w" H7 }3 W+ |8 L7 C" {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
6 I8 |) D. v. U" i5 k                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( R: j$ }9 U# f" s                double        cutoff = cutofftemp/(double)Config.sound.nRate;5 m* h) A, J9 a" J- y
                static        double        tmp = 0.0;
1 E2 I/ t' q0 ~                double        in, out;% o% L( ^$ W$ j/ S. q6 J: E
$ B5 B1 L2 j1 K0 Q2 [" ?' C
                in = (double)output;
" m7 L2 K4 b9 y! e                out = (in - tmp);; b# O0 k( t) q$ e  h# O
                tmp = tmp + cutoff * out;
  s# o% g2 t" ^! s& b  s
9 {. k+ R. ~7 {                output = (INT)out;8 M9 e8 T" E" f: l0 Z+ ?5 k3 e
                }
0 K7 t, I' t6 N#endif
; I; P3 q4 e! {/ o. E#if        0
5 y% O. L3 l/ J0 x                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
" [. w  [$ ^9 K/ m- g                {
# ]0 ~" a6 F6 Y0 v# S1 L9 P                INT        diff = abs(output-last_data);# N1 c' w5 Q" o+ x1 Y
                if( diff > 0x4000 ) {
5 `7 q, c) T& f' L0 T4 w0 Q                        output /= 4;
3 u9 H" x& y3 }2 |                } else $ Q# {& }8 J8 W7 v. P1 X1 C
                if( diff > 0x3000 ) {
1 U) _4 t: _: M% `3 Y$ j% f                        output /= 3;
; r4 e+ h3 U' _4 N6 n/ h5 ]7 E- ^                } else
# k& g4 c3 X2 v9 k5 l! l/ E                if( diff > 0x2000 ) {% \5 X7 V/ o5 `+ C+ c8 t
                        output /= 2;) b0 u- O7 S# ~. G2 P2 h' }
                }
1 |. V2 u7 I+ ^/ B& S5 @                last_data = output;7 r9 e9 \# i/ q+ J" R
                }
' ?, W4 l! y3 \* U* y#endif
1 d# V  S/ p* T0 W' a4 }                // Limit3 a7 D7 h% j/ M4 G5 A. O  P
                if( output > 0x7FFF ) {0 J9 ?6 [7 Q$ S) E' d2 ]0 F' _
                        output = 0x7FFF;
& O1 r) v8 O' c5 {                } else if( output < -0x8000 ) {
. Y! w- }8 J) F' C, d                        output = -0x8000;. [# u, G" R2 v7 p& C1 I7 ^
                }) O* u3 q; H# Y2 t

0 Z" w/ B) }8 {. Y7 ]: Z0 V, {" t                if( nBits != 8 ) {
0 b& x# m( c  x* E" h                        *(SHORT*)lpBuffer = (SHORT)output;; n  ~. p( y* O1 J
                        lpBuffer += sizeof(SHORT);/ b: A" {  d% Y* @4 b
                } else {: H5 T/ ]. W; t8 X3 c2 f! V& a
                        *lpBuffer++ = (output>>8)^0x80;) s8 e  A3 L( G5 a: m+ q
                }
, a' y$ v0 k, s* Z4 R" s* ?$ z1 ^6 }# C
                if( nCcount < 0x0100 )
+ p1 [. a7 l$ @+ L                        pSoundBuf[nCcount++] = (SHORT)output;4 h% a; F4 I, X
* g, w. Q- _) {7 d. U
//                elapsedtime += cycle_rate;: E1 P* ~- \# k6 D
                elapsed_time += cycle_rate;
. t3 q3 ]$ D6 @7 n- M$ N        }6 _4 x* w7 D% ?4 s5 }2 S" ^. \
4 p# @7 r6 G: Y
#if        1# K" @. v) J. O) R3 H3 o( ]
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ d8 x# P7 `# l' w1 d1 b9 [$ q
                elapsed_time = nes->cpu->GetTotalCycles();1 g/ C% i6 ~7 @; ~3 R+ W" W
        }% I: H9 D. g. W, d9 y9 A" u
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
! m6 j& {# `3 h* C+ \                elapsed_time = nes->cpu->GetTotalCycles();
$ [. A- W/ e, L# s        }0 u& j& L" t+ b& A
#else
& [0 U* e/ \6 n, E4 p0 G5 i) [! v        elapsed_time = nes->cpu->GetTotalCycles();' j4 g* |5 I3 v6 O: E! a
#endif3 Z. V7 X; Q+ ?, H4 ^- G$ B4 K
}
/ f2 s: `/ T7 E) h( O7 A, Y; T/ Q# R7 f/ K" ~
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)3 j& v# L/ S  k  ~/ w: b
INT        APU::GetChannelFrequency( INT no )
/ ?" Z/ [5 C9 e/ b$ B* f8 G{
4 L$ t( I# J  A* H* q/ {) V! }6 y- {        if( !m_bMute[0] )
' ?7 \- P2 E+ `% g6 s                return        0;7 S0 {  ~* D+ F: ~! `1 P
1 v) N0 i, U! }- U
        // Internal, i0 L1 R' p, O/ Z+ V: c. r7 N
        if( no < 5 ) {
5 F6 Q5 P3 Z9 t% b2 w' G) f                return        m_bMute[no+1]?internal.GetFreq( no ):0;
9 M  k: _- g9 e* c) A        }
/ N: v- p- h2 D! P        // VRC6) c# P. J+ O9 e* O5 `" \  [
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" l1 b; i% ~6 @9 F                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% }4 R* f% t' I( Q        }, N7 s" @# G7 e
        // FDS
- q/ I1 D* h, w7 z! V        if( (exsound_select & 0x04) && no == 0x300 ) {! v" Q5 q# Q8 k; {. K( J
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# t5 r: u3 i3 O0 y. r% Q
        }' z! I& b+ o3 Y3 P
        // MMC5  I- u% b: t# ?' S  ^
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {2 b. Y& c( f  g; G+ y) ^8 s
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" n8 ?) B$ ?2 u3 ]& P
        }
# v2 A9 C6 T+ z: w9 K        // N106
* O3 ~' Q; f% a' O. I0 {  a        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
5 F& p: a0 [; S9 g# X4 @' j3 {                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
( j! ~3 _& Z( Y, D        }
- m( p6 h7 t1 [2 }: ?. j        // FME7- a1 R  Q* @1 ?% i7 e
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  M. F1 h9 Y6 g! i7 P                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 m" R( x$ h" t! L( @9 C        }8 @! ]) x+ n3 S+ Z( s
        // VRC71 W( D- K# l3 }  N+ q; k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# Z6 t2 M( I7 e4 [! N
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; V8 T& z% S3 b! y0 G# W
        }# N1 h2 h4 j$ L) R* F4 l+ q- }
        return        0;# e7 K5 M( U7 K; {  G
}# o# e7 m/ J6 o2 M1 o3 ~
: U# Y( L4 Y. ~' i0 u
// State Save/Load
% A8 p4 n- R6 I# c; ~1 P) R1 c4 t( v3 ?void        APU::SaveState( LPBYTE p )
" B5 W/ J0 Y: }& N& Z' V3 ?7 n{
( |3 r4 Z) C$ X5 a: p* Z, ^) L#ifdef        _DEBUG
4 m. z, @- t1 e* W. q, i$ f* YLPBYTE        pold = p;
% U1 h4 t4 ^8 ^7 s8 |#endif
' n1 H. N, ^; u+ F1 `  T4 W8 |
1 e5 _7 N9 |, N4 I; N        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞2 G* c" |4 O" W& E4 F
        QueueFlush();/ Y) [( I- \7 _- D5 l' y

8 o. N9 ~+ r/ ?4 o        internal.SaveState( p );
/ u* H  v) o( q" j: W; x        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 L, y9 Q2 N0 j; N
0 \8 r0 o" K. w* \! p: Z  y
        // VRC6
: b3 E* L! t2 a+ f        if( exsound_select & 0x01 ) {9 w0 {7 l% r) S% I8 N
                vrc6.SaveState( p );
' D; R/ t  o# ~, [% m4 M1 s) [                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: x1 V& P% ^8 q' r! w
        }5 {! \5 ?- o: o2 K) ^; q, \
        // VRC7 (not support)$ j2 H9 n9 i& Y3 g+ O
        if( exsound_select & 0x02 ) {5 ~7 q+ b% g- ?/ S( i
                vrc7.SaveState( p );
, _: N1 F' V4 a% a" w/ K" {6 h                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 M# z9 [1 ^2 \. b- Z- s2 {9 r; E        }
8 R; ]- U7 ]# V+ u: t" [        // FDS( j' z) z$ w9 E& M
        if( exsound_select & 0x04 ) {
2 Z. \0 ]" D9 V* [                fds.SaveState( p );. w9 S, L) Q+ n0 r4 {1 A0 K& [  X
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& e7 u$ _) l1 }) C; ^% b1 g# ~        }
1 O: T; b5 K6 c4 n9 l& ?        // MMC54 k3 ?* j5 c* i0 `
        if( exsound_select & 0x08 ) {
, g" o& @- y# `6 z/ F                mmc5.SaveState( p );, ~9 F$ q+ |% E0 r
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' K9 x5 u6 ~" ~6 M# v( J& J8 `        }
  e; t; P" J" L; X- |, {: O        // N1065 ^6 I! j; b; o5 U" \7 R
        if( exsound_select & 0x10 ) {9 Q/ r$ Z* w( x4 ?" E
                n106.SaveState( p );
/ T6 X, m1 G. z* m9 D( Q4 X                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ \- S3 e8 p! z  ~5 d( ?
        }
% L, G1 m8 M2 e6 v% \        // FME7$ c4 J. e% i; g- B5 c; J6 g! L
        if( exsound_select & 0x20 ) {% E1 R; _. N" {& K
                fme7.SaveState( p );! }( v: D, A$ ^5 O0 \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  o1 `1 b6 w9 x, V+ a
        }
; U' M) a) I, K5 ~8 F! h# L# y" n8 ]
' g# W( ~9 s1 D3 F( _7 D#ifdef        _DEBUG
1 f' Z1 o0 s; G. G& @( G8 t# PDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- Y1 F3 D& `+ r3 o- R% Z* k- b#endif# S/ z7 d3 r3 ~
}- m0 D0 F( c6 W- K$ q0 s
1 I7 v# F! H$ ]" R
void        APU::LoadState( LPBYTE p )
3 k! [* W' ]5 i3 o! k0 [{& o& X9 N* @0 [- M! v6 m
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. c% T/ H4 K6 S( ]  S. e2 ]& c+ O        QueueClear();
, v6 \" I" ~* u; F8 z! a2 N  b# o* ?; b7 P3 U7 R2 b3 y
        internal.LoadState( p );- U" N7 e3 ^' s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
5 G/ A* y" R7 g- G3 h- c+ v3 q" v8 w+ \3 Z% Q" v; `2 {6 R: y
        // VRC6
* T6 Z: }- }$ o& o        if( exsound_select & 0x01 ) {" D9 S+ Y4 U& A7 W" |' ]
                vrc6.LoadState( p );
6 ~& I! `! O$ u                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! s7 V- T0 b$ L2 [" T
        }" F# s4 W: t* O% n( {/ n$ R
        // VRC7 (not support). B! E; n  @, H3 r( G3 l
        if( exsound_select & 0x02 ) {" u% N8 o; F7 r" `6 N
                vrc7.LoadState( p );' U$ G  E! B  O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. [5 h# b8 P& i% {& D$ N. b8 u
        }/ O, r8 ^5 B. c' F5 C# X) [
        // FDS  u8 e# J: _3 |" u. I
        if( exsound_select & 0x04 ) {
2 Z, n6 ]  m% h- K0 m& x                fds.LoadState( p );' c$ c: p4 O; R8 Q+ h4 m' J2 \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding1 J" t2 c, Z- N4 T; H+ t# |
        }
5 f" {) V( t# K) C8 N5 m        // MMC5: d& z1 f$ F  Y! `) \
        if( exsound_select & 0x08 ) {
( Q) Z  s" Q- r3 t                mmc5.LoadState( p );. s2 I) F. E4 j
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding, u0 ^! L9 e( w9 H# I. ~5 U$ {, l
        }& ^) Q" F( O0 l, o# C0 a6 R
        // N106
0 Z& t4 F/ n3 o3 l0 a, z        if( exsound_select & 0x10 ) {" Y8 o' h" w: Y2 B- R7 d, _. l& g
                n106.LoadState( p );5 l; m; v3 O# F- O3 s6 k2 }* d
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 T/ {. ]. }+ ?! e3 Q: M! J1 L        }, p) H! v7 u1 K* r
        // FME75 {' Z. h# j" E9 s/ M4 w
        if( exsound_select & 0x20 ) {. k9 n0 V& d9 T: X# |
                fme7.LoadState( p );' j0 N" b: G  e/ K0 x
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 @. w0 C0 \- b" K1 I& L; S
        }
* i) W* B( c) H" v}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 6 y3 z% e- h4 b- g
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。' u" j+ U* i* f8 a
感激不尽~~
' ]) ]5 W7 z4 x6 w! U6 d
恩 我對模擬器不是很有研究,. w6 @8 x" F/ o3 @% t: i6 h
雖然要了解源碼內容,可能不是很困難,1 n. n7 f9 u! b
不過還是要花時間,個人目前蠻忙碌的。! w& }5 j8 t- G9 h$ `, i

9 D' D7 D$ V0 B, E' g5 x給你一個朋友的MSN,你可以跟他討論看看,2 \, ~1 M# {- I' @
他本身是程式設計師,也對FC模擬器很有興趣。
! R4 P* P5 [5 e5 ~# r9 o! e& h5 O! {# Y7 X1 O8 e: T- Y
MSN我就PM到你的信箱了。
* V% |" e. }, _- Q$ D: I/ p7 u  D9 [+ W  u6 D, w. ?) {; _
希望你能有所得。

该用户从未签到

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

签到天数: 80 天

[LV.6]常住居民II

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

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 - C# y0 @  y3 F1 N
呵…… 谢过团长大人~~

; `+ h7 \" h8 x  O$ e
' A: t# O, N9 `2 b6 \8 v  y% M哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 * L5 M  h1 l* x& Z- y- P
团长的朋友都是神,那团长就是神的boss。

! [3 K5 `: N* l哈 不敢當,我只是個平凡人,- @$ U1 O. r  E+ e7 i  r0 N* I
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙  a' j3 v# L) l: |  C8 ^) ~
ZYH
6 \9 L; L6 e0 J+ cQQ:414734306: K% Z& v  g; M  y9 [0 L/ s% K
Mail:zyh-01@126.com
/ l" ^; b) e9 `- o: E; C4 e
$ N) H) a: `( n0 n  f3 p他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 9 |2 E/ i" ]0 E  P
再次对团长大人和悠悠哥的无私帮助表示感谢~~
) I( f# l8 I" E- N9 M
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-5 18:08 , Processed in 1.079101 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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