EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?& R7 ]3 X! W. D( Y1 @! K  R
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! z5 M7 b5 m# c! K# }2 k. u
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. q$ P% F: A6 W' i% d7 \8 B这里有相应的模拟器源码,就当送给大侠了~~7 M" I# T$ i% e1 ?9 g) P
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
  y% c9 g8 ^  l能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' o3 v/ \5 g8 P- q, t" t7 l
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) L$ U$ O9 j. G0 l/ A! {这里有相应的模拟器源码,就当送给大侠 ...

! y! a% L# H4 K6 l/ Q9 u6 u0 l聲音部分(Audoi Process Unit = APU):
* w( S* i* B- }  M; A5 B.\NES\APU.cpp! O7 }2 i+ y1 {7 k0 q% m" F
.\NES\APU.h
' O& \, d7 K5 t: S* x" G% ]. E. U% O% S

+ `# T7 E, G: i影像處理部份(Picture Processing Unit = PPU):! g8 u0 z6 f% K. v- y2 I. V
.\NES\PPU.cpp
5 ?3 \3 q) h, n" Q- J+ D.\NES\PPU.h
" U; M1 P" H$ M/ {: i7 O- B
( c& F, m8 k$ a, T4 V如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
8 j$ S2 Z1 }! P. w: C感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 S  x& U% ]1 U2 E( |
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ m8 t4 t2 Z3 \$ q3 f. O& g# t
//////////////////////////////////////////////////////////////////////////
: l$ Z' I: x# v2 M- K8 d! r//                                                                      //6 E0 H# L( i3 k$ O% v) o6 l
//      NES APU core                                                    //9 E. g; p  x2 L' [2 m
//                                                           Norix      //
$ l; E! y& m  x//                                               written     2002/06/27 //7 j# @) `4 Y' T3 W9 Z0 \
//                                               last modify ----/--/-- //2 y% J5 [5 e  V( h9 J
//////////////////////////////////////////////////////////////////////////
3 T3 L* u/ r8 ]% V4 F( j% l#include "DebugOut.h"( A; H' p2 m+ H9 W
#include "App.h"$ J  l) O  |- v8 E8 R8 q5 f; q! G
#include "Config.h"
3 `, }8 Z* h# h7 e/ l
% U- ?9 }& ]2 T! ^; g6 d' z3 h+ b  c#include "nes.h"
' Q  y& T% v* B. M#include "mmu.h"" M  X/ |) Y; C
#include "cpu.h"
+ L9 ^* g& c3 B) M9 z9 l9 Y# \#include "ppu.h"& y4 t: S5 P$ C) A) Y
#include "rom.h"
% o8 X* h+ |* i+ y2 g& Q) D& h9 i* o#include "apu.h"4 H7 F) l8 e9 C1 P
! l6 [- l4 ^7 T# K$ @. U
// Volume adjust1 k& H3 p3 \! y2 ]
// Internal sounds
8 B8 [+ S* n; D7 q#define        RECTANGLE_VOL        (0x0F0)7 x9 v7 V. R1 t0 f3 a- j
#define        TRIANGLE_VOL        (0x130)/ n/ L) m- d5 w( r  y( ]; T1 ]
#define        NOISE_VOL        (0x0C0)
* T5 M9 W0 f: Y/ W' B6 t' ]#define        DPCM_VOL        (0x0F0)
7 I' j0 {6 A% n: a& y" ~// Extra sounds4 w* C+ Q/ `5 W
#define        VRC6_VOL        (0x0F0)" o( |( o5 q4 f, L# A
#define        VRC7_VOL        (0x130)4 r( R4 V" i8 o
#define        FDS_VOL                (0x0F0)" c3 H, j- o! l! ?0 K( c
#define        MMC5_VOL        (0x0F0)
% w- h0 s+ L5 h3 w5 s$ u% {#define        N106_VOL        (0x088)
+ j/ X2 j1 B' j  n; g#define        FME7_VOL        (0x130)
6 P  y# G# G7 y. M1 ~& t' v$ Q% E+ S) D4 H8 \5 t& v. H
APU::APU( NES* parent )
6 j/ H, F0 r/ c/ C% h{
' e! o9 p: i4 f. z6 J" j        exsound_select = 0;1 |! I$ V5 O9 h) d

1 {4 b2 T) ^  Q" e7 s7 h5 d        nes = parent;
, y# G/ J$ \& s" s        internal.SetParent( parent );7 M% {  V- l9 D( g& ]
$ m* O( U$ t" t, K# n
        last_data = last_diff = 0;+ O$ g7 Z$ q3 c5 |  o

. u) @" ~! D: U' n        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );. \. e- q7 _  n

& T; C! k4 `7 I0 K        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ Y; n# E3 ]# b" h8 \( J5 q; |
        ZEROMEMORY( &queue, sizeof(queue) );7 |- v+ i9 h; Z, ~& L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  g8 n' f% q* V
" E. E8 @! U" o- Q0 `# N, S        for( INT i = 0; i < 16; i++ ) {
' |* ]/ i% J" c, N                m_bMute = TRUE;+ _7 h( u) \& m: j& t& {3 [/ ]0 ]
        }
2 V4 p, j' J( p. @6 o}1 R: E, S# N( s

' {& s* P4 ]5 [7 r  ?& IAPU::~APU()
7 L) a' R' K/ H; _% g{
0 F2 |0 ^  r$ _# K. j9 e; |}
$ i, s. Q* f( G: \7 \" w5 V/ L# s- f* u- C
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) t; q0 f6 w' _1 c3 k{
2 A4 C3 i: p0 f. R        queue.data[queue.wrptr].time = writetime;# m1 Q) W" o; a9 g- M5 O( ~3 Y1 N
        queue.data[queue.wrptr].addr = addr;
; U1 a. K, _4 D* U9 M        queue.data[queue.wrptr].data = data;
! i+ s2 a( |4 }( D( [        queue.wrptr++;
# N7 }3 q, q/ T, o  N7 P3 e        queue.wrptr&=QUEUE_LENGTH-1;1 I$ m4 E) b* @9 p6 K2 R/ R. d
        if( queue.wrptr == queue.rdptr ) {( g* A7 p) o) R
                DEBUGOUT( "queue overflow.\n" );
  }5 @+ u" N  d- J        }
! Y# i; q# q' R. i9 y8 Z}6 Z) v+ i8 P* D! p' p2 J5 ~
/ `1 z5 Y& ]. {/ J. P2 n
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  N! G) P5 V- p8 r) M( c{: ?5 K. X3 C/ W
        if( queue.wrptr == queue.rdptr ) {
+ \: _7 M4 C! ]: y& p! r0 ^$ [, W                return        FALSE;
8 K  \* g7 ?' ^# G1 \5 h7 Y5 u4 ~* b5 H        }0 y+ T& t3 T/ O- `6 B& K3 T& m
        if( queue.data[queue.rdptr].time <= writetime ) {
3 ~4 {) a. K9 C& x8 ^7 V                ret = queue.data[queue.rdptr];
- J# h/ ~5 o3 Y! K, t                queue.rdptr++;( U, U; ~' R" b! @
                queue.rdptr&=QUEUE_LENGTH-1;7 Q, K3 `5 M% R4 m
                return        TRUE;
& O1 m& h& m$ {( a4 h( I        }8 z$ d( ]$ B; B$ u. J
        return        FALSE;
+ o* E# L6 v. }9 g/ r}
. j8 o# L3 I* E2 M$ e& ?! [" E, C3 K6 p* p1 @$ K$ x) X# Q  T% L: P& s
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )8 z5 e/ k6 N  k! Z$ b0 R& P, M9 ^
{
7 z7 O: F$ w0 q! R" S4 ?        exqueue.data[exqueue.wrptr].time = writetime;# l/ k0 r% h4 z0 e7 ^# d# G
        exqueue.data[exqueue.wrptr].addr = addr;
  j) y2 H& O) I3 u1 I        exqueue.data[exqueue.wrptr].data = data;3 j6 v! a1 o3 q# _& J9 c
        exqueue.wrptr++;
0 p. P! a/ ?8 T$ m" y9 P        exqueue.wrptr&=QUEUE_LENGTH-1;* l. D+ |  K: z, q
        if( exqueue.wrptr == exqueue.rdptr ) {- O- @. X6 O/ ?6 g: {+ N- V2 a
                DEBUGOUT( "exqueue overflow.\n" );
7 D: g% H  l! `, Z: ?        }! k5 j& _8 O7 }- h& i8 t
}, Y& `9 Z) S' n; p0 [. ]: }( I
/ L( V7 S1 J- c3 D7 \% [
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 V5 C( y  j0 Z' [! c  ^8 Q{
: ^8 N, G6 F7 t- m$ `  q% i        if( exqueue.wrptr == exqueue.rdptr ) {1 i0 l" Q* L0 A  A  H2 P
                return        FALSE;
% a4 @& c. }( u3 c) T        }
" `: ?5 H9 z4 o- I- c2 u+ C+ a% n        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 t1 R) [. S2 a7 @; M0 T9 z                ret = exqueue.data[exqueue.rdptr];% p$ @; [) N) H- v$ \$ L: Z0 d: m
                exqueue.rdptr++;7 _4 Q$ l! a4 E/ z' D) Q
                exqueue.rdptr&=QUEUE_LENGTH-1;& F5 e4 t$ G3 ^* e1 x
                return        TRUE;
* s2 y8 N# C4 x! \+ _        }8 {  G0 y+ n5 b- I* b
        return        FALSE;. Z- f" f* ^$ Q- q+ l
}: b" j5 W0 X" K9 W0 m+ _

4 \8 d+ S, }. g, w+ e. \void        APU::QueueClear()
" u5 U" I- P: N{
! F( P. f. \+ N8 C, x' e# ]        ZEROMEMORY( &queue, sizeof(queue) );
5 n; @4 ~) k: C. v& i) v        ZEROMEMORY( &exqueue, sizeof(exqueue) );* O1 I4 |( F8 ^. @) j# F
}3 K% f7 M8 c! n# _
9 U) b" W( G4 G: o/ ^) Z# o, T, {
void        APU::QueueFlush()6 \) x% `; K0 I1 E2 |# D! k
{
3 J6 T/ Q8 m" _/ ?% @3 ~        while( queue.wrptr != queue.rdptr ) {0 x) s' H1 n! B* n9 I/ Z
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
6 M( E* B0 ]( J7 Y# X+ [                queue.rdptr++;
  U" h9 o4 o* A% Z  l                queue.rdptr&=QUEUE_LENGTH-1;! l* E. o- h' }& X3 A, \8 y
        }
" _: {2 v- `2 s, q" [0 w
/ t# w# q, z1 [* m- `1 x; N        while( exqueue.wrptr != exqueue.rdptr ) {# K! \6 ]6 O8 D9 T4 d$ e/ s
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );' ?$ q8 ^% M/ m+ U# @) N' j! t
                exqueue.rdptr++;* {2 @, i9 z/ G" T& I
                exqueue.rdptr&=QUEUE_LENGTH-1;4 `6 _( y% z: ?; l  ~
        }/ g/ `; u. v) W: d
}
; c, B+ _% h6 Z7 N  w8 b* \  b0 h3 h* K9 f
void        APU::SoundSetup()9 p4 t5 j# j2 H6 K. b! q( {1 v
{+ {2 ?3 x& g* P( Z' e- G* v1 F5 t
        FLOAT        fClock = nes->nescfg->CpuClock;' x! R3 R5 l  g( w' m
        INT        nRate = (INT)Config.sound.nRate;! z; X0 t; m  p+ f: V
        internal.Setup( fClock, nRate );2 G; E  N3 ~' ?
        vrc6.Setup( fClock, nRate );
+ @5 O* i+ T- n0 M( P1 Q' k- `        vrc7.Setup( fClock, nRate );  s& t3 B: p9 l" {- h, h
        mmc5.Setup( fClock, nRate );
) b8 u! d% {  y3 X! n# `6 y        fds.Setup ( fClock, nRate );
8 f4 |/ }+ t7 A7 @" s7 J- D4 C        n106.Setup( fClock, nRate );0 i! \# e% H$ y/ G+ }
        fme7.Setup( fClock, nRate );9 e1 r2 F& I* F! S
}
' [/ ~1 Y! z/ h$ D: w) A( O2 B$ i  M2 _' N
void        APU::Reset()
! _$ L  M! x8 M/ Q6 z% m  X{
, A, H, L  i" H( R3 l6 H        ZEROMEMORY( &queue, sizeof(queue) );
) T0 K3 h1 N- P- c* H        ZEROMEMORY( &exqueue, sizeof(exqueue) );' ~- s# h3 Q  e1 F% }+ v: w& `
1 u4 g" z  K% k
        elapsed_time = 0;
% i/ w$ P: Q4 P+ _, [( b
# A+ i! w, O$ G        FLOAT        fClock = nes->nescfg->CpuClock;
0 U2 \7 t; v) K( p6 ~        INT        nRate = (INT)Config.sound.nRate;
+ a2 J8 k7 P5 j4 q* S; y* B1 U        internal.Reset( fClock, nRate );
6 ]/ W5 K, ^& C, g1 P7 D        vrc6.Reset( fClock, nRate );
( B  ~8 X' m" x9 u  t# e7 t        vrc7.Reset( fClock, nRate );
  P* M5 [1 v! g" V        mmc5.Reset( fClock, nRate );
4 t2 h) J& j  ?7 F( Q& q( J        fds.Reset ( fClock, nRate );
1 A4 @3 W( _- a/ z8 y        n106.Reset( fClock, nRate );
6 a' k3 T. H! ]( d# K& D; c        fme7.Reset( fClock, nRate );# m- g' e# N: G4 o: a6 k4 D' g

) g# E8 O' O/ C        SoundSetup();6 O8 Y* |! r9 H3 e! p& C' z# r) R! X
}5 s4 J  X. I; R* ?9 t

( b7 _  h7 V; K* j. l+ rvoid        APU::SelectExSound( BYTE data )" b( N, s! v3 ~, p# I
{
% z7 s0 {# G3 h& Y1 n! D        exsound_select = data;
# v* F) T4 l) A3 \+ `5 @}& {/ D/ k1 O  C

* E; J* }0 U3 n% ABYTE        APU::Read( WORD addr )
9 J7 y. T! F0 u! N{6 e6 ?, G( B- J
        return        internal.SyncRead( addr );4 X8 h0 C5 {8 ]) I) p
}
& t" |2 R3 t' O/ u( ~8 y' X1 i6 {2 C  i2 z3 q1 D; x
void        APU::Write( WORD addr, BYTE data )
% f2 R7 K7 |! q7 x{
% g7 j3 l4 b& B' G        // $4018偼VirtuaNES屌桳億乕僩
5 y6 D4 `. v- x3 K- Y% }6 I* _        if( addr >= 0x4000 && addr <= 0x401F ) {0 v, O+ K8 r+ }( j* n- I# F
                internal.SyncWrite( addr, data );
, K% G, j" A9 h" X+ W                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
: u/ m- X! |  J% d, l3 Z8 t# u( c; t        }
# H3 z( t# o6 L! V! k% l}
2 z" h7 G2 r) V& @+ W+ a8 C( G2 ~9 A
BYTE        APU::ExRead( WORD addr )
# A/ E6 K. s- s! [5 M2 [# o* G! Z' L{
/ [9 V3 v1 P4 I" sBYTE        data = 0;) a* Z& v7 k$ d

% k3 ^$ _8 z% ?" S# W! k. ?        if( exsound_select & 0x10 ) {
* P* D6 t. `. F  C. L6 T                if( addr == 0x4800 ) {2 K& ?* ]- R4 S" x# B/ ]
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
3 `& u) R3 C8 y* D+ X                }
' z5 m6 R% l# i, c# g6 t0 G; W6 c        }/ m9 u! m" G7 F& `
        if( exsound_select & 0x04 ) {
7 ~2 ^& Y3 l2 i                if( addr >= 0x4040 && addr < 0x4100 ) {7 q. }) o! v8 C$ q# C" z- U- c0 v5 ?5 Y
                        data = fds.SyncRead( addr );
& k/ m7 f( X. z3 r; l+ e; A3 T& h                }" m! F0 K. ]$ E* @- k* g$ ^) V
        }5 k$ G3 ~5 Q/ q, z
        if( exsound_select & 0x08 ) {, j3 z6 ~7 W! `
                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ p! y# O% v) n! |, L5 i1 [7 }0 d                        data = mmc5.SyncRead( addr );
( ~5 i  M- s, h  J( R4 {* Z                }* \/ I: @* @2 @: i; ]( d
        }1 ^) A  u6 c9 C: m
7 [! `7 s4 Z0 Y
        return        data;4 M; s# u! k6 P4 T1 c
}' `$ D+ q' l1 e2 Q" i7 u8 o+ M! @, @
. Z( e4 R, J. ]4 Q! }! M5 b" q; v
void        APU::ExWrite( WORD addr, BYTE data ), ?- ?# ^. m# u5 [& I
{
6 `. C  m% D" M' t        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
3 b3 _  V4 O) [8 W! v. t" j9 T4 K6 |5 u
        if( exsound_select & 0x04 ) {% d) a0 ?( b' r4 D
                if( addr >= 0x4040 && addr < 0x4100 ) {. {7 z' @" x) m) s) k9 q
                        fds.SyncWrite( addr, data );0 x. f) c1 @% q5 q) T
                }" e1 c0 O/ `! P9 N( h
        }1 K5 v) S3 @+ ^! V0 r. I! w

9 c! }# e9 O2 J; e5 k% l' t        if( exsound_select & 0x08 ) {
' N( a! K$ v2 ]3 X+ X* w                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 F* q, t, j2 x4 a6 O1 b; A% s                        mmc5.SyncWrite( addr, data );
6 p% n9 u; F* O0 c( r                }
4 J+ u5 S! |  V9 N  C, k        }
4 I' L9 h4 {2 L& q& l$ F& L, h}
9 V7 f  V+ _* Y) ?9 n1 g, Y9 M5 B% l/ t7 ~$ m" H
void        APU::Sync()
/ L9 x, J  x, |+ }2 [5 q{: S1 b7 }2 F) r% E6 r) I1 S
}
& u* a7 S( i; Y0 r# }4 Q- X# e$ ~! A* m" w/ R
void        APU::SyncDPCM( INT cycles )
7 T  Y) |9 `# K{
! {* c- b/ B* k1 g# ^        internal.Sync( cycles );  R/ x1 G4 \  h/ C9 Y4 `; V) E5 [
6 K# R5 S/ q+ I: l. @6 E
        if( exsound_select & 0x04 ) {
, k7 P! f4 `- h: B$ I( v                fds.Sync( cycles );
5 Y# ^1 S; H! X" s        }
* V7 K7 n9 _) Y4 e0 n! ]        if( exsound_select & 0x08 ) {
. g/ n' b5 W% b9 g, o6 ]                mmc5.Sync( cycles );1 ?; z8 t: I: z1 ]- \. y' b2 m8 ]& k8 {
        }4 z" o: n. h' \
}
- h2 f/ W* s% G4 U
* s" U0 A2 Y* r& F' Nvoid        APU::WriteProcess( WORD addr, BYTE data )
  D& d3 V1 h$ S  u. m{
2 h1 k+ L/ {0 g8 A        // $4018偼VirtuaNES屌桳億乕僩
3 ~% P  Q' Q4 b/ _* l        if( addr >= 0x4000 && addr <= 0x401F ) {
5 F( J0 \. P2 r6 ]- D7 T5 ~                internal.Write( addr, data );
" m0 Z5 B) z# n. [        }0 {1 b# }1 f7 p/ R( [) E+ a! T
}
/ C3 b; S$ X# X4 |9 p/ O4 }: M1 c% R/ H- V; z2 u/ J* L' X6 j
void        APU::WriteExProcess( WORD addr, BYTE data )8 L- y; B7 p. \# d( E. O# }
{
/ s3 E% G+ @2 n  l        if( exsound_select & 0x01 ) {
6 r! n# m# ^, ~% ~( d4 h3 I                vrc6.Write( addr, data );
/ y% `9 S0 G3 T        }
4 k4 _5 R% D4 M& ~+ g  N  |        if( exsound_select & 0x02 ) {8 t. F5 [7 ]) G, N
                vrc7.Write( addr, data );
3 f1 p5 C& ^2 n( P: @6 y. u& A' O' ]        }/ Z& k9 Z2 n& J7 a) C& G0 n
        if( exsound_select & 0x04 ) {( D! I# V7 }) f3 `
                fds.Write( addr, data );4 a; R3 V' \" j) n$ l
        }
) {% b8 D$ \; c1 s% `6 n        if( exsound_select & 0x08 ) {
) t% |8 K) m0 l+ ~1 Y                mmc5.Write( addr, data );) k: Y9 \# X  X1 J% E% R9 J6 m
        }
* E+ C( X4 S0 w+ X; b4 V        if( exsound_select & 0x10 ) {& s5 c7 I6 ^& Y
                if( addr == 0x0000 ) {
' L9 y# g1 i9 x1 `* F9 @( F" l                        BYTE        dummy = n106.Read( addr );; i; v$ R6 i& M6 Z1 |) j8 N/ G
                } else {
4 S) w. Y% u; r. f- G                        n106.Write( addr, data );
( [7 g4 r7 l6 |4 d2 b8 X) F- y                }
. a/ _  T5 `. c        }
! q: R6 e0 E6 o- c. a5 Y) F5 {. W        if( exsound_select & 0x20 ) {
2 C8 [: ?' w) @6 h& z" R. X                fme7.Write( addr, data );
5 T7 r6 K! X2 K/ s% W9 B* f$ @        }
' ^7 e# J+ J' a0 d; r# i1 s! n}
1 `  T6 P6 b! }( d* a
, Z3 ~) I: @6 b# Xvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
% [: j. K0 F4 N2 L2 Q6 `9 W{
0 b2 \# V2 n% ], ~7 UINT        nBits = Config.sound.nBits;: B0 `7 b; S0 [. r3 ?# ~6 K/ Y
DWORD        dwLength = dwSize / (nBits/8);
( V. U: V# A6 t. K7 c- ~5 A% s$ N- MINT        output;2 a4 ?6 ~/ F8 x& e( v; }
QUEUEDATA q;- Q1 M6 e5 `% j/ X  m7 V9 \8 }
DWORD        writetime;
9 V1 {$ z& Z3 U3 k0 v- i5 O
, J7 I! t' C9 P+ HLPSHORT        pSoundBuf = m_SoundBuffer;5 o0 i: }9 H+ |4 u
INT        nCcount = 0;6 y2 [9 d3 E; T

8 |/ t! u' H# g4 W$ \7 ?( Y7 J- rINT        nFilterType = Config.sound.nFilterType;
  p+ @, i2 b* r  c0 m- O; t. `
3 |% o. V( r: r8 u4 ?9 q1 G& x5 E        if( !Config.sound.bEnable ) {
% a5 x: j3 [- F2 H4 V# M: Y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );( B  D7 y" s0 d/ T  L) a
                return;0 {) Q' M6 H( p  H8 [1 B9 D
        }
$ l$ k! s5 F  }4 _5 W. ~
. q) R& y9 K" v9 z* `4 g        // Volume setup0 `' ^8 n$ [. b* ?) L5 B' V& V
        //  0:Master) O' Q8 ^. M& e6 ~; H: N% H
        //  1:Rectangle 1
  [" ?" ~+ l& @# P0 @        //  2:Rectangle 25 m& r1 o5 z. A* `
        //  3:Triangle
# g+ O, ?7 A. |1 ^2 Z( ~        //  4:Noise( _9 ]- }  s* X; n0 T
        //  5:DPCM
. K" H8 G6 d. H9 p: x3 X6 b        //  6:VRC6' B6 [9 }/ A, E4 v4 f6 J* ?# @
        //  7:VRC71 P: d) L$ N, P
        //  8:FDS. ?4 _, |3 h0 I- t0 G
        //  9:MMC5
* W, G. G. }0 Q5 c) _9 b        // 10:N106
( I+ Z0 j, f  e        // 11:FME7% e4 Y, S( J: j+ L
        INT        vol[24];, d7 S. f- |2 h
        BOOL*        bMute = m_bMute;3 \4 _; ^- r7 z3 W* t& m: p% A
        SHORT*        nVolume = Config.sound.nVolume;
9 S; Z$ @0 d, b' z& v: }
  [# L8 i2 D! R. G1 _$ A5 }' ^        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' h. E. {8 M, T1 L$ D/ c, z7 o1 J+ a! L) y
        // Internal
" r) [) w2 ^# F6 W4 b        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;. X& E! O: L. U  b6 ^
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;! o2 ?& A0 i3 u) e
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;7 m: p6 |6 ~& [, T
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;- R# e2 J" G% ^* o/ }0 \# [
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;: X- d! R5 P2 R
! v8 M! E8 d* J; y+ h  u$ S
        // VRC6) u9 q& f3 ?8 k1 T! s4 Q% x
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 `4 m' t) z3 a- G        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 I8 M- B0 N/ w        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) u( G. I5 @; }% y$ Q7 E: R) t
, T5 \( @: o8 _& @: Q5 q        // VRC7
9 g4 P* v8 K+ E/ n) S        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- _+ j( F' u$ V: C6 C
& J; w3 `: h6 D" t9 @% F        // FDS; b, Q5 ]3 _6 W6 l$ n
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
1 X9 N7 C4 O% T% ^* g2 A! @- M. `$ t  M
        // MMC5: }: h% }2 s7 e9 @9 p: d3 ]9 @( Z
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( e; e1 f' {  C* @! b0 M: m& _0 M
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 o+ m9 G( O! n: p: C        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ T8 S* P% i" K4 Q
! m# K8 o  X: v+ S  i& d- X3 I        // N106
& X) j  w+ |4 I# W& r        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 n* ^$ v7 D$ B; l; }
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' w1 k7 q9 R; G5 I2 M$ v( Q: ^        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& `' q  r+ A! I& \; }
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 c: y- W* ]: A8 P/ R- L        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 E& v$ i) v$ P; p) S        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 A, x2 B4 J6 ?4 @        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 [7 O- z. c6 D" a  R        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, ~: ^& d3 }/ ^2 W: p
. z0 {3 p  A: i) Q* U0 I: U& u
        // FME7, _3 b+ c3 R8 A$ B) V& F
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) \1 T' ~0 B) V0 ~3 y0 M
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( L# U+ s/ c' O' G
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  B+ L. d. U" l$ M
5 ]( G/ D! E! n7 s//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
+ p+ M0 g! }; _% E  q; A$ P8 @        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
1 k$ V8 G$ f  u8 Y) a( M1 D- y/ S8 @
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
# }& p' l6 P, Z' L* k( z        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) I0 Z$ ?# P# O6 @  O6 u
                QueueFlush();% p" {; ~$ T4 Q8 X$ a5 R7 z
        }
- U. |! d  f& i2 ?  @" N$ D  f) D$ u: B
        while( dwLength-- ) {
, Z8 j1 c3 l% Y! U                writetime = (DWORD)elapsed_time;
* K/ h: A9 ?% k- p. B  d, X+ c6 c8 S, {
                while( GetQueue( writetime, q ) ) {+ d% F3 T7 Y, s: q7 C" K
                        WriteProcess( q.addr, q.data );1 g$ s! O/ y1 Z: l1 P* v. p
                }
# b+ K% x+ v% h8 o
6 F1 J, x) D& n/ x6 L; {: O                while( GetExQueue( writetime, q ) ) {- ]5 E6 |4 m, d( t8 B7 X# ~
                        WriteExProcess( q.addr, q.data );
" |7 o- a- Q4 c* d* a                }
9 e: l0 m' L2 [+ }" @! j- a1 Q; K) D: c
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 U' p* k6 ]4 |5 @; ^& {
                output = 0;* D) H8 L+ {) x0 y5 w
                output += internal.Process( 0 )*vol[0];
% f- U* U- w- W" k; G2 c" d3 x                output += internal.Process( 1 )*vol[1];
/ }5 ~, R& @! ]  ]1 z! e/ ]/ S$ |                output += internal.Process( 2 )*vol[2];6 {# k  i+ L) J9 w7 o
                output += internal.Process( 3 )*vol[3];& n* S  Q1 [: F& c: l$ j% e
                output += internal.Process( 4 )*vol[4];( Y# @9 j" p3 m! p

; J. m: S( p& t1 X2 X! @0 k                if( exsound_select & 0x01 ) {
( a: ^& W  @9 _1 U                        output += vrc6.Process( 0 )*vol[5];2 i6 w7 B1 ^3 ]1 _$ n* h
                        output += vrc6.Process( 1 )*vol[6];
9 i0 h& ~- q7 k8 ^  d                        output += vrc6.Process( 2 )*vol[7];
, B" M2 o4 r3 E/ @% w                }
- i/ ]* l3 |; @! J( a) e                if( exsound_select & 0x02 ) {
3 Z! x* u: K7 S. s$ W                        output += vrc7.Process( 0 )*vol[8];
. ~% Y/ {4 m/ s" N3 z                }
- }9 Z, c) `0 b1 w+ J, T& }. c- @                if( exsound_select & 0x04 ) {; _8 S# Z. U' P4 C8 e9 X
                        output += fds.Process( 0 )*vol[9];) C# J5 ~* D' I- U2 z# M+ G
                }
1 a1 j0 ]. B" u! X- P                if( exsound_select & 0x08 ) {0 x, N, O' ?$ T+ u4 G2 \
                        output += mmc5.Process( 0 )*vol[10];* L8 y$ d% v* g; `  V7 [
                        output += mmc5.Process( 1 )*vol[11];
* L$ y+ H0 F' i8 I3 o0 S. h                        output += mmc5.Process( 2 )*vol[12];
5 H: S6 Q  o+ R/ B                }
  M& ~9 d4 y2 t$ t+ f( x" N                if( exsound_select & 0x10 ) {: O( g9 _2 ~- C* s4 l( F- V
                        output += n106.Process( 0 )*vol[13];
$ M; i$ I+ }  n5 @2 i% d                        output += n106.Process( 1 )*vol[14];6 _4 c  D. _/ S" S% a
                        output += n106.Process( 2 )*vol[15];% v$ u0 g" C8 ]' |6 R
                        output += n106.Process( 3 )*vol[16];" z( n8 y, |; Z- d+ O5 {" e  S
                        output += n106.Process( 4 )*vol[17];  }3 e0 H. z( @0 o
                        output += n106.Process( 5 )*vol[18];$ i# y. @# m& p7 z" z
                        output += n106.Process( 6 )*vol[19];. f7 L7 J& Q" d3 a* A! k& u: Z
                        output += n106.Process( 7 )*vol[20];4 W$ H# i/ h/ I- P$ u* l6 n- [/ K
                }
+ `4 a: J- O: l; X7 `: s' o; ^                if( exsound_select & 0x20 ) {6 o6 l; C8 }3 R" M
                        fme7.Process( 3 );        // Envelope & Noise# N0 V( m. [. A9 q- j' V
                        output += fme7.Process( 0 )*vol[21];
7 w$ G# Z, t- i4 O; X- y8 E                        output += fme7.Process( 1 )*vol[22];
' b3 m+ l+ ~9 G( i$ _                        output += fme7.Process( 2 )*vol[23];
$ l/ j  t  z3 Y- I- D( J# \/ ~                }7 ~. Q* a6 |# s/ s3 E

( Q$ M& {! h/ U9 g" ?                output >>= 8;& t1 K# O$ E  e# P

2 h0 X- O. t. p! T$ b% f! G+ I                if( nFilterType == 1 ) {8 ?- T( W6 P* t; O2 R5 _% S4 b5 T# f
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 O1 X- z( M+ w: j( m! I/ t
                        output = (lowpass_filter[0]+output)/2;
& r0 R. S+ w! O  H! K# e                        lowpass_filter[0] = output;
6 ^% G, N, ]7 J( r- B9 p                } else if( nFilterType == 2 ) {/ r$ Y5 y1 |/ v
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
( x! o; Y1 l/ z8 C                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 K3 J! N" O+ U5 l+ y4 G- ~. u
                        lowpass_filter[1] = lowpass_filter[0];) L8 Q5 b8 ^* x' }, V0 x! N/ q
                        lowpass_filter[0] = output;+ P: k* ]1 U  c1 w( ]
                } else if( nFilterType == 3 ) {& p( c9 Y! R* r7 t2 a
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)  S" m: Q/ ^& B  g
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
3 y: B" C# v5 W  C) h! W. b7 C                        lowpass_filter[2] = lowpass_filter[1];. o. x3 N6 U- K/ B
                        lowpass_filter[1] = lowpass_filter[0];- W! Q3 y$ V: ?2 y3 J9 v1 Z! m  J
                        lowpass_filter[0] = output;
) B2 t% H! Q4 ~% A/ l( Q! ?, m  N                } else if( nFilterType == 4 ) {
* z0 p1 q$ k2 l+ L& \5 }0 @                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 }4 i$ w7 w2 D" E5 A% N. `8 I+ f                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
" D( g0 [  p( j; X- _1 _1 I$ ~                        lowpass_filter[1] = lowpass_filter[0];0 Z- g, K$ E" A4 ~$ E; s* C# l
                        lowpass_filter[0] = output;
8 _5 }8 n5 X* V                }  D) t" w, _* e3 P0 y/ q
- V( {# X  a) r5 W' q
#if        0
" h( V0 _2 p1 m; r( e                // DC惉暘偺僇僢僩
7 q2 V- k7 \* a/ d& t. @* n1 q% u                {
& m9 @8 k7 P2 U& S% H                static double ave = 0.0, max=0.0, min=0.0;
- `# s9 m8 _1 {" x9 x2 w                double delta;
( t" C1 W+ Q8 s1 \; L! C, C) T, B: W                delta = (max-min)/32768.0;; N5 p% N8 C0 E% i1 L2 C. K
                max -= delta;2 k  d5 y+ X0 b' o. ?: f
                min += delta;7 w3 u4 _) g" l( R
                if( output > max ) max = output;8 z) q+ P+ P* Z! t; V$ @
                if( output < min ) min = output;
8 p$ p% d- @8 O                ave -= ave/1024.0;
9 t6 j9 D! w* v* p8 e7 h                ave += (max+min)/2048.0;: f% o* l9 X9 v% u& u
                output -= (INT)ave;8 m) R8 n1 N: F% N9 T% x4 N0 Y
                }2 l, B" U( I: w6 J
#endif
4 A9 ^& n4 s# d6 R4 K" U; [#if        1" i& N8 w7 ?* q5 ?
                // DC惉暘偺僇僢僩(HPF TEST)$ l1 f8 O& B; w
                {
0 x+ H6 l9 m/ P, G% J9 |//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
# ^7 T1 y& b% P6 `% q/ z* C                static        double        cutofftemp = (2.0*3.141592653579*40.0);
6 f8 e: D* o# P; @. E8 z                double        cutoff = cutofftemp/(double)Config.sound.nRate;
/ \4 T6 I4 b/ m, X/ c                static        double        tmp = 0.0;
$ e4 ~* Z) `7 G' E                double        in, out;8 T; `2 C2 y. ]& R: D

+ G1 x( ^/ s( g- S6 q) m5 w: P& }; n4 X                in = (double)output;
; U6 M4 ~$ T# [! q                out = (in - tmp);+ M& `5 C$ q+ W' O. X8 s+ w
                tmp = tmp + cutoff * out;
# a: R& `0 \6 t. q, o  a& G7 f5 b$ L  M7 A2 f3 L
                output = (INT)out;
1 n2 @3 J6 o8 e0 o! J" z: L, V                }
6 P% L8 Y" A: V. U$ W( O! U#endif0 v( \8 u) w- B/ |3 V- F
#if        0
( I" `( S, e% y- u                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
; d9 I# O# d: ^                {
- d, f9 l7 v4 [9 w8 Q                INT        diff = abs(output-last_data);
( @. Z1 p: i: A: Z! ?- s# z( E                if( diff > 0x4000 ) {* h  u/ c$ i0 w% I3 j% P
                        output /= 4;  m$ N2 v, f8 e+ d7 ^) g/ x
                } else
3 Z% w; O/ O$ k& q                if( diff > 0x3000 ) {
' E* z4 c" t( M/ a5 L- d                        output /= 3;# _; x5 P) L" ~+ f1 r: U6 C
                } else
4 a( q( p1 H3 M                if( diff > 0x2000 ) {
/ }' U3 r( ^' C7 ^                        output /= 2;
% ]2 m3 @& L2 M* _  k  _! j/ U                }
7 |) O& k) j/ K/ x                last_data = output;. L0 F9 t5 [# P
                }4 O3 s& Q( d( D' x# u0 W
#endif2 }& u( h' K+ M9 z- C  D4 G8 c
                // Limit
# E* W: l; D/ P7 a( b& K7 B                if( output > 0x7FFF ) {6 B& K  g" |& x) \7 N
                        output = 0x7FFF;
' A7 r4 W' z1 L, f* G                } else if( output < -0x8000 ) {1 A1 x! [0 u0 n' `% T1 Y( P
                        output = -0x8000;1 L7 {+ z/ C) Q) N6 o5 L
                }3 F  x6 @; O0 V6 v) r# @

+ A! d- C' U. B+ ~9 z$ o: u# Z                if( nBits != 8 ) {
1 {  T6 v5 G2 m& E! r                        *(SHORT*)lpBuffer = (SHORT)output;* \' Q3 q9 L  c% e
                        lpBuffer += sizeof(SHORT);
$ t- {) T6 V$ A& k5 k+ D$ i/ c- ?                } else {
) }& n& c% P, L: Q) q                        *lpBuffer++ = (output>>8)^0x80;0 P) F, m/ o& w  o" K" g
                }
+ m  C6 v: B- V7 P
  E1 i% j, F; U9 G% T( d                if( nCcount < 0x0100 )
0 J/ ^, _0 W  P                        pSoundBuf[nCcount++] = (SHORT)output;1 L7 _: {5 z2 _( R7 x- V/ X/ z9 _
, m" n6 C+ U: \6 H# K
//                elapsedtime += cycle_rate;
1 ?1 u3 t" t% z! E( c                elapsed_time += cycle_rate;1 `7 Y) x) K+ V0 {0 n3 t. ^* F
        }
' K# S' j1 l6 H1 N  S% l" W+ H- r8 ~# z, X9 h: p% H* t) B' x: F
#if        1
2 R0 M/ \. f. [, f+ J( D        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {) Q' }1 j- v9 T" D# P8 x  U3 n- @' Z
                elapsed_time = nes->cpu->GetTotalCycles();; ]2 u; U# _" h, i. s7 B
        }
7 U: W. Q6 T7 [, q( N/ U        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
  g4 V" u# o# w/ E6 w                elapsed_time = nes->cpu->GetTotalCycles();4 N- A3 V7 k+ u0 u8 C6 m
        }- q9 z+ u4 u  V% S6 w
#else9 s1 z, y2 b- Z- ]
        elapsed_time = nes->cpu->GetTotalCycles();
3 i- C( I3 c7 f. r2 G#endif
9 o$ D/ a& B5 }3 u( Z& _" v+ I) }& e}
# k+ V9 K" g1 @1 t$ |; P% a$ a$ O- P. s% W
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
& V' N6 ?( H. {! U1 HINT        APU::GetChannelFrequency( INT no )' U: s# Q6 ?3 C$ l9 ]& d% x( F
{+ f3 V" a- Z# u, W9 A  n6 v
        if( !m_bMute[0] )
" r$ `) T; N0 ]; I2 k! B* F                return        0;/ ]; }" B, E2 [5 \4 r, E" K- e6 `

9 t  ]# q( {0 Z        // Internal( z$ T3 H3 L9 e0 I# m
        if( no < 5 ) {
  o  [/ W4 q: e$ A3 C                return        m_bMute[no+1]?internal.GetFreq( no ):0;+ O  `0 e/ k0 C2 r! Y1 l9 y0 ]
        }
4 \9 X* j, z6 O: V! m3 C        // VRC6# ~1 `  d5 a( p" P, Q
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {8 h7 R& {6 t% W
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
4 ~2 M1 h, |. d, d$ H        }
, L* x+ T$ Z, u% Y        // FDS$ N7 n! j+ S$ N# I
        if( (exsound_select & 0x04) && no == 0x300 ) {
# O3 X% e+ n, t1 ]                return        m_bMute[6]?fds.GetFreq( 0 ):0;% j' `$ a/ ]* t
        }" V' m- f* _3 C* ^" h+ H
        // MMC5
& y4 ~7 ]9 t* s; x" H        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
" u. T+ L# f* {( h# t                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% _: _( ?5 f" V* C3 W7 h" Q( o6 z
        }, V2 \: a8 ^. h' ~8 Z9 p
        // N106$ R# O7 l# U; ^3 G9 `0 P
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {, J7 m0 k% x- q9 ?& V1 t# s
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;3 w9 a' \+ z% m7 m- ?9 C. A6 z
        }
, A& ?8 }! J( I- ]- C$ G6 {( Y7 k        // FME7
# U  w1 C$ y" z7 `& }        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  _  R* ]3 l+ M% n0 x8 @6 z                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 ^1 k& A$ z$ f; }2 W        }
, o. g% h! u1 G6 P9 |        // VRC7  J' o6 t# c  X1 o( j
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 }9 t5 Z- e4 k2 `                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: S7 e/ M6 ?* b# a' T# B7 L        }6 A: `. ~4 g: U, ~& N. s. j3 N
        return        0;# M  o1 j% x4 k) O; M- ~
}6 F1 F- W( ]) |" V* X! m4 \

- T: r3 m: J2 |- ~/ u// State Save/Load7 Z3 @) Q  _, T; h8 y
void        APU::SaveState( LPBYTE p ): G4 o" Z% ]5 C0 _
{& R' L0 R& L0 v) `0 U$ Z
#ifdef        _DEBUG  n1 S, b) ]$ g1 e+ S( ?0 @
LPBYTE        pold = p;# z# {  t5 f5 W8 a! E& N0 t
#endif) Y8 ?" r2 H8 Q1 O3 q7 I, I

1 E+ Z6 j: |6 m6 G  |        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, ^  U' I9 ^2 U
        QueueFlush();
' |" D6 w/ _; T& F7 U5 Q1 Q! @: @# V
        internal.SaveState( p );
1 @0 O1 o: q/ t# D$ X        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 P3 z! t) ~" K3 X2 J; ?) w  ?/ [* w! g! O; ?0 F0 k
        // VRC62 t4 b7 O  E& n  g" t( O
        if( exsound_select & 0x01 ) {1 \' {+ i8 b0 r8 b' X
                vrc6.SaveState( p );$ j5 b) @* t; Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 \) ~! O0 d* o/ y& `+ t& {6 d
        }# Q' X  S  Y  p: Q7 ~; U  s' e
        // VRC7 (not support)/ L. v( ^0 S. I. ^3 Z" H% c
        if( exsound_select & 0x02 ) {
! @' e. q. x/ F+ a                vrc7.SaveState( p );7 m1 _/ S+ H3 R1 ^
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* b3 N4 k  p& J5 ~" f7 {
        }2 U- q7 O, ^4 N  z% U
        // FDS
1 }- N: D6 Y# K        if( exsound_select & 0x04 ) {' K/ z. K0 w! R6 V/ A5 ]
                fds.SaveState( p );- l2 @& L! I' N! p/ Z  U) M
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 [/ z, l# H* T
        }+ W6 ^- t* k: E' I  O* ?
        // MMC5$ f3 t/ I3 F0 S" u+ H0 T9 I
        if( exsound_select & 0x08 ) {& n$ z4 p+ ?8 ]
                mmc5.SaveState( p );! Q+ r, E0 s: c* x! @3 H+ c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
, u( a% t$ q. n1 {( t, U% L        }
/ J3 w2 Y; ?/ R$ t9 `- @        // N106/ i. O/ M: M" @5 G
        if( exsound_select & 0x10 ) {
* h( [/ I( u6 a4 ~+ Z                n106.SaveState( p );
- |4 o. W9 \% V& D) k2 ]& ~1 j                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 k$ P4 T% j  d+ E+ L5 ]3 H        }
  H$ m0 d) D# ?. b        // FME70 }9 P# Z- ?9 J( y5 ^1 f  j# c. \
        if( exsound_select & 0x20 ) {
- K; L5 G% |! ]/ ]                fme7.SaveState( p );- [( f0 f8 R+ H7 S+ B' S7 t
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: M8 l) d  I! L$ H/ i* j) N        }
4 Q$ y! e7 h$ Y8 S* B% @3 o- L* R8 Y+ Z3 v/ [- J3 p
#ifdef        _DEBUG$ A. Y' j, w! Z' v" Q/ E. t
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );& ^9 Q2 q7 f# w9 p! a3 K2 w
#endif
( x* l+ H& v1 S( {}
6 c3 N2 K7 n% Y/ Z
9 x" O" W3 J: G+ O) E/ w% Dvoid        APU::LoadState( LPBYTE p )
& W1 w/ z3 O# R6 F, j% F0 l{
" `9 s0 I0 j6 W- h  U        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 J) Q) I, P# m1 K* k        QueueClear();
* A* M  s% l0 }3 r
5 V- x' n( y- y! B2 [, r        internal.LoadState( p );0 Q5 y9 Y. K* I1 U
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ V" P9 D3 G; T6 O5 b
# x# Q$ ~# p+ S* ^0 K4 X
        // VRC6
. `4 Z+ K- ?, m. |3 [) T  q        if( exsound_select & 0x01 ) {
) J! Z. X* b7 F& y4 U/ A9 i) N                vrc6.LoadState( p );
/ H7 e  p# k% {8 j" V1 X1 Q1 s# M1 U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, {% y# p% t1 t3 }) {) ~7 p        }) [7 ]& d% h4 X# W& [
        // VRC7 (not support)4 {2 T% U$ V2 P  S  f* h
        if( exsound_select & 0x02 ) {+ n- X4 b6 \1 K, P1 ^5 ]; v$ ]1 y
                vrc7.LoadState( p );
) Z5 D: D  @% r- t! V0 h3 `                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% `; ?* T: E# W        }
+ R' b; j$ q1 s( o3 ^        // FDS
6 j: ]7 W+ r3 ]: V! Z, Q& _, r        if( exsound_select & 0x04 ) {
  t& I' _% |8 }; E                fds.LoadState( p );0 [- q" [6 J) q2 r8 V5 k
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 I( W5 j4 u6 a7 V9 F7 n        }
6 Z' R" r) c# K0 d% ]+ p3 s  w        // MMC54 O7 `8 [: S9 q5 @
        if( exsound_select & 0x08 ) {
. x! D8 K0 Z$ H& h' f                mmc5.LoadState( p );3 U$ v' ^  m- x8 ]4 x1 J: w
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ p5 M( L) b; j0 Q0 e        }
2 S' e) T9 k6 e        // N106& t  q. [+ Z; x% F& \7 }
        if( exsound_select & 0x10 ) {1 _: z  R' F) `
                n106.LoadState( p );) W2 z+ ?0 P1 Q  C* |3 P  r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 u7 C( O7 {& S/ E) E        }2 X0 z3 Q( Q& z, c+ W. P
        // FME7; S' M" v$ X8 x* P9 @( L
        if( exsound_select & 0x20 ) {
: T* _' d7 o0 E                fme7.LoadState( p );
7 h  K: o# @8 K- C+ o+ T. v2 T                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 c. g+ L$ T& S# w# d+ F% n        }
# f9 x7 m8 ~$ H}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / u( c9 [1 Y3 S& P" t# h. d% ]" z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。) ]8 w8 @. |! _4 g- x& v- s
感激不尽~~
, Z# |1 P( ?# g4 `" ]
恩 我對模擬器不是很有研究,) ~7 j, A  F5 a6 \/ }
雖然要了解源碼內容,可能不是很困難,
& K7 L7 |6 j) C不過還是要花時間,個人目前蠻忙碌的。( J5 y$ ]. q. p3 r/ S' [! l
6 c1 e) B4 p' [0 p6 D" U& ?
給你一個朋友的MSN,你可以跟他討論看看,
3 ?' D9 F% g! s他本身是程式設計師,也對FC模擬器很有興趣。  r* D( B) o; L/ r, J  b" Y1 J
3 `. n, G. r+ u
MSN我就PM到你的信箱了。
7 Z* \/ J. S1 p$ N: B8 v/ v* m9 P6 M: l
$ }- N5 z! S- v  H; l( _% S0 ~希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 % ]$ t! L8 a, u
呵…… 谢过团长大人~~

# ^; P# w4 s! v7 Z# T( D
$ I0 y9 A, W1 ]# B哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
. B# L6 p. y* {# L团长的朋友都是神,那团长就是神的boss。

2 k: p' _: k& V( ^# ^& C; f哈 不敢當,我只是個平凡人,( l7 M: W; s2 K/ y" Y
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
- W9 I+ I' ~4 |2 g; S( ZZYH! q7 g7 ]+ M" G  k
QQ:414734306* o) D# a# t7 h0 p) t
Mail:zyh-01@126.com
3 R; ~. f! Y, t  k6 u: ^: D% ~( V1 t/ C( }% Q$ \. f
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 / _$ |, k- T' G8 L
再次对团长大人和悠悠哥的无私帮助表示感谢~~

0 i0 p' _) {. B% k; I不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-17 14:16 , Processed in 1.088867 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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