EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?8 O6 G( [. k8 I+ f# b7 K
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 T0 e; b' h5 ?: Q) j1 r! G" \楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
2 y4 \0 [$ N& P这里有相应的模拟器源码,就当送给大侠了~~3 m: z8 J( z- X  y( }" d
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
1 p) [6 d0 \+ I) n) _, r& u能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* h! r7 S" `7 i& @& ~, Y( D楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 y, j2 e5 A9 s这里有相应的模拟器源码,就当送给大侠 ...
$ k$ J" b/ o) S  o9 L' z! A+ P
聲音部分(Audoi Process Unit = APU):
  V7 T  |3 G8 o: O.\NES\APU.cpp
8 f1 N$ F% s. G: e) T4 e. @.\NES\APU.h- y$ r/ _4 \5 D

, J2 I/ X9 L' V  S+ I, V
4 K" r- p) i* b* M" p; y* d) G9 j5 J影像處理部份(Picture Processing Unit = PPU):
- {; Z1 n+ O% x, u+ ^# J* u.\NES\PPU.cpp
0 z, N+ C# H: e/ Q.\NES\PPU.h
6 m4 D  N  x- k4 [) n2 h  c5 w8 {% W; D! [  b0 d0 V1 s( K
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* m) R3 c8 _' u2 P5 m+ z1 k9 C
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:$ ^8 T) _) R* X& g4 ]$ i
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 @3 E! w4 V% t% P
//////////////////////////////////////////////////////////////////////////+ Q2 S' ^- T5 s6 V- M1 T& _9 L- f
//                                                                      //
2 T7 g& R0 P! o" X, Y//      NES APU core                                                    //+ |, p$ ?7 O2 w6 P0 D) L. k
//                                                           Norix      //
3 C$ d) [7 x1 f3 a* a//                                               written     2002/06/27 //  V0 l9 `6 b  [; Z" S
//                                               last modify ----/--/-- //  v3 |" \- m: r) N
//////////////////////////////////////////////////////////////////////////& t3 b4 |) ]  ^# T2 f& @
#include "DebugOut.h"
5 m, L- @' W+ ?* I' Q#include "App.h"
/ a5 i/ Y7 ]8 O  k0 j  ^; B#include "Config.h"9 X/ {% l& h  j% q0 c! Y
: m7 U0 `4 N( Z3 y. t
#include "nes.h"
6 ?/ Q. F7 V. m0 I7 J: N' Q2 S5 E0 X#include "mmu.h"
2 o* u4 K" H. M4 x#include "cpu.h"! C7 x. W$ e. G2 a8 N$ R$ K
#include "ppu.h"
/ }+ a6 ~) N$ @- U#include "rom.h"
* F" s1 A+ T5 b, Y7 ?8 P#include "apu.h", k- K4 v$ I" u2 d; C# s
- H9 J& e3 L/ r( u* i* H$ l
// Volume adjust
# Q) m( w7 D  a; t: H9 j3 ~+ m/ H// Internal sounds; U( x- E8 F9 ^1 Y, I
#define        RECTANGLE_VOL        (0x0F0)% e2 }) S0 O7 r1 _4 y; Z3 T+ J
#define        TRIANGLE_VOL        (0x130)
: C+ H) J1 U& y; l( ^# d+ _4 t' A6 {#define        NOISE_VOL        (0x0C0)
& Y6 k. [" ?' x! }7 p#define        DPCM_VOL        (0x0F0)
% \! n8 N9 k$ g# R0 H: S) U& S- z// Extra sounds  n  d0 u% C. P8 B, p
#define        VRC6_VOL        (0x0F0)
  `8 u- a5 E0 k6 n#define        VRC7_VOL        (0x130)
$ D5 R% O, D9 }( H. R#define        FDS_VOL                (0x0F0)6 X% B- P: H! a1 A. V1 d
#define        MMC5_VOL        (0x0F0): I) |7 M2 n! E, t* C4 Y0 q
#define        N106_VOL        (0x088)
/ ^. V! E, l- @* Q9 c0 b#define        FME7_VOL        (0x130)
5 u! o$ z7 k& J9 O: Y; u0 y
  n, c# P2 `1 U, K6 m8 AAPU::APU( NES* parent ): a! V/ Q5 ]  Y3 A
{
  H* q" p- {1 z        exsound_select = 0;
5 K9 ?# w1 _& F' ?+ S! X8 c  m% A, G  A' q% n) ~. ^6 u
        nes = parent;
7 W( R! J+ \& r% q        internal.SetParent( parent );7 K! G; K$ a9 N* u( B/ }

8 b+ [$ G1 I. O$ b1 B        last_data = last_diff = 0;( r( ~+ Q2 ?* u& j3 f) e

2 }( H3 Q7 z0 F6 v3 F5 n        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
9 K2 G2 K7 B' O6 D) U3 Z7 M. c; j$ {" \' T# H# J0 n
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: I6 G$ R$ J4 D        ZEROMEMORY( &queue, sizeof(queue) );4 W* l9 u( v" c" }6 |! q4 r
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ J; J2 {. ~8 V% d7 n
4 Y) w, m% c) U0 v        for( INT i = 0; i < 16; i++ ) {/ }( c- v! }4 t: l, L" b% w
                m_bMute = TRUE;# E0 e  \: E1 Y$ r( C( \+ L1 {
        }
: v; g) {. ]$ M' S; [2 M1 X  g}
4 K: Y/ ?! i0 Z4 d& ^5 ?) k2 g
9 M& Z0 H* Q* K) CAPU::~APU()
4 j3 k( Q, Z' t6 M{  u! F4 U4 b& a, h/ v
}
+ F. ~5 ?! y2 |3 v2 E
6 {' \3 t3 G5 Y* wvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& K$ S9 @' h3 B9 L' X3 H{
) t& }6 e8 f. ^# @        queue.data[queue.wrptr].time = writetime;5 X0 O5 Y% B+ L  C
        queue.data[queue.wrptr].addr = addr;
" u, ^* p! ^- |" o5 j: o8 k, `        queue.data[queue.wrptr].data = data;6 A/ y  \7 d( f8 l
        queue.wrptr++;5 C" e+ v) B5 G% \" q! J, w+ p: [! D
        queue.wrptr&=QUEUE_LENGTH-1;
$ }  f* A0 u% N/ O        if( queue.wrptr == queue.rdptr ) {4 w" H! e7 F% e6 m) e, \  K
                DEBUGOUT( "queue overflow.\n" );. p8 X1 U: A2 P2 z
        }
+ _/ |+ {8 n: a0 f$ W! s}
. g' J' V' @0 Q. G( w  c7 f8 k( J
% T& F$ J0 E# p- m; bBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
! l! l! O! G- U. C: p{
2 d8 R0 Z; O# L8 i0 C        if( queue.wrptr == queue.rdptr ) {$ W& H7 M" |. \7 s" m3 }+ B- V
                return        FALSE;. x# j. x, f; u4 m2 A; v
        }2 _/ T5 T0 p: h8 G% M
        if( queue.data[queue.rdptr].time <= writetime ) {0 w( n, ?% p6 u* s, h" F
                ret = queue.data[queue.rdptr];: K4 e3 y& a* e+ j
                queue.rdptr++;
# N& Z+ s9 W0 x9 t                queue.rdptr&=QUEUE_LENGTH-1;
, K$ o4 M5 ?/ x0 N                return        TRUE;; ~0 j& L/ b* q2 O6 z
        }2 ?: h: b; M  R- d3 y
        return        FALSE;/ I6 Z: ^/ f4 N, }; n' q5 m2 y) R
}
3 p4 ?1 h8 w. r8 ?1 n5 M4 ]4 E0 Q, T
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 `: \4 Z1 c, H. C
{& O* J" s5 Q! g2 H/ M" L' r+ V1 C
        exqueue.data[exqueue.wrptr].time = writetime;  ?  F2 |& K" K
        exqueue.data[exqueue.wrptr].addr = addr;7 f3 S9 [0 W0 J9 S# c* l4 j" B
        exqueue.data[exqueue.wrptr].data = data;9 i2 r! G8 V) K  c2 j8 n$ o2 e" ?8 o& F
        exqueue.wrptr++;
* d8 R( _) a! v: z        exqueue.wrptr&=QUEUE_LENGTH-1;# r3 u7 [) R0 `; m8 m# ~
        if( exqueue.wrptr == exqueue.rdptr ) {
) |+ S$ O* v- a6 r+ W0 h; r$ |                DEBUGOUT( "exqueue overflow.\n" );
# a/ u' N2 ^$ p9 ]8 Z, A+ A& d        }5 Y- \* `( e3 [9 I4 E* \  u
}
' h: \: F, c3 W$ o. w. `: \4 d( \
# ?. J: f' P* B1 aBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )) D% w& r/ l, D) O/ m
{& w4 Z4 _  u! Q$ a. p3 D' T
        if( exqueue.wrptr == exqueue.rdptr ) {
1 q/ H( Y* |0 w2 f8 f4 j4 x/ b' h9 J                return        FALSE;& K; t$ ]/ {9 Z7 [
        }6 T9 g2 J1 i1 B' K) w% a
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
# V; {5 h: A. h  \                ret = exqueue.data[exqueue.rdptr];" _( _1 K* \$ J9 x: K
                exqueue.rdptr++;
5 q, }7 G& M' ~' O* F                exqueue.rdptr&=QUEUE_LENGTH-1;1 F# ^9 i  q9 O3 T6 t* V3 l9 \6 l
                return        TRUE;
+ |1 [6 q$ \( X0 ?7 g+ T; s$ v        }
& R$ l4 s; O! n        return        FALSE;
9 ]7 n# r4 ?: c2 [) L) z}
2 j' v9 S7 M; `0 e" n* L+ j  @
3 a$ R. |( @; n# K# \void        APU::QueueClear()! O, w8 X! F2 }" y; G2 L0 @
{. E8 }% C, u3 ~6 I6 k- d$ c& H& L
        ZEROMEMORY( &queue, sizeof(queue) );
6 {4 Z- O1 [: }1 [3 y) w        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 h1 b  b" e2 i  E+ T}1 Y0 d# f5 q; f) B
( `0 D3 O1 T  Z  X: g
void        APU::QueueFlush()# T0 G3 K) O6 _+ d+ m
{
" O9 \' \; T+ B) f8 O        while( queue.wrptr != queue.rdptr ) {$ I2 b8 S: Y; N  g+ }8 f/ `1 v! B
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
# Y& A; W* O& }% l: w5 h9 f# Q                queue.rdptr++;, k5 O9 o0 v2 D/ ]
                queue.rdptr&=QUEUE_LENGTH-1;5 {% L4 h5 M; C9 q, z
        }/ P+ d2 `* i8 A4 [0 B1 h

9 V9 J4 P% Y% j8 d- [3 n1 ^        while( exqueue.wrptr != exqueue.rdptr ) {' u, K& u9 ]5 S0 C2 f
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: b, u4 K9 Z" D! \                exqueue.rdptr++;( i4 A$ z) H& P1 ^" C" Y3 {
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 K( x) Z9 m2 ^( C1 i' V* {        }+ `. {3 \1 S1 g( b& h6 O) C7 @
}
0 Z, H8 y# c3 I; J" d- ^3 O5 i' C
6 `( N, l; N$ s+ U1 {void        APU::SoundSetup()
  ^- L. p4 |$ L/ J5 v* c{* i6 R) \0 H) y. R% K% r- \7 H
        FLOAT        fClock = nes->nescfg->CpuClock;* O: I$ _$ z' ]) o$ }
        INT        nRate = (INT)Config.sound.nRate;
; T  l. Y- C4 h9 _5 ~        internal.Setup( fClock, nRate );, O( \6 J3 w) }) f+ C# k
        vrc6.Setup( fClock, nRate );4 n4 s+ S  f6 A' t$ C$ Q6 q
        vrc7.Setup( fClock, nRate );! U7 e# t8 A+ ]3 a" Y
        mmc5.Setup( fClock, nRate );& h8 ]; g) Z. T+ u: `
        fds.Setup ( fClock, nRate );5 Y  }' ^; X6 N( m
        n106.Setup( fClock, nRate );1 p( z6 }/ }( Z/ Q
        fme7.Setup( fClock, nRate );2 {$ {- l: y% ^
}
& l" T! c  `% |" O
7 x/ p2 T$ r" |. W& w! Wvoid        APU::Reset()
1 ^! W1 p* K5 s+ T6 r- p{
% ]3 U+ G; V1 z7 ~6 V        ZEROMEMORY( &queue, sizeof(queue) );
3 }! H% ^* j  a# [        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' L) N2 j( G3 i5 @2 [6 ]0 F* G0 O! |5 [+ J! L
        elapsed_time = 0;
% H7 W( m) i4 Q  B0 n6 ?% Q* D7 I: L7 p) W0 J
        FLOAT        fClock = nes->nescfg->CpuClock;% |  ?9 A3 T4 G* b
        INT        nRate = (INT)Config.sound.nRate;
" D  c2 Q: W. y$ ]" A$ O- ^: Y        internal.Reset( fClock, nRate );
( ^% `! a; H+ c+ ?9 p$ M6 F" P; U        vrc6.Reset( fClock, nRate );
9 g3 }  q6 W& m' Z4 @2 M        vrc7.Reset( fClock, nRate );  ~! ~% h0 ~3 i3 A# X7 G' k: ^
        mmc5.Reset( fClock, nRate );% w6 u+ C" J+ E
        fds.Reset ( fClock, nRate );' q+ p% @% ?$ D. V- ?! g
        n106.Reset( fClock, nRate );, {  L3 ~' U) W0 p- r
        fme7.Reset( fClock, nRate );2 n1 n8 u" f* u6 k" ^" H/ d

3 X* D3 K2 N* i5 h( `9 G        SoundSetup();
- R! c+ B1 P3 d" t" F}6 e. V0 w2 I+ Z7 [  U3 I& B2 t
  }1 @' \  d0 \
void        APU::SelectExSound( BYTE data )4 I7 q7 w! X9 a. o
{
3 y5 U0 f2 W3 |. D  `        exsound_select = data;
4 A3 R0 o, E) y6 K}
1 _" t1 I( A2 D; A# C# C# }+ C2 q. `1 h" j; f, z2 h0 Q
BYTE        APU::Read( WORD addr )
0 s# ^# {/ ~$ [$ U  {{
* e! d3 T6 l. X& k& b8 k  s% H        return        internal.SyncRead( addr );
' `- h9 z4 B0 J# m}
2 H4 X# P' ^& l0 M4 J1 \0 J0 }3 h( N) W  S! t
void        APU::Write( WORD addr, BYTE data )
2 {& {/ L( k$ q3 O6 @! h{
7 M( \: _5 c: h4 }  r) |: z        // $4018偼VirtuaNES屌桳億乕僩+ R9 j7 u2 o. p1 b+ R8 m' q
        if( addr >= 0x4000 && addr <= 0x401F ) {- Q# l6 Q4 z8 j1 e6 z
                internal.SyncWrite( addr, data );
) c5 s+ ?* p0 k+ X8 d* n! K! @                SetQueue( nes->cpu->GetTotalCycles(), addr, data );# A1 O! V1 }. K) {' f  i
        }+ r; u# {& S# U9 p( o% W. [
}$ k6 `% o4 ]1 s4 R9 u; ^0 q
$ ^7 t9 {- p! k
BYTE        APU::ExRead( WORD addr )
4 C: x* z" X  [{/ a& K( B' e# B
BYTE        data = 0;
& S: n' {1 d. V% F& b% y( ?! P! [! H) C5 T
        if( exsound_select & 0x10 ) {
( C$ H1 u, {5 H( @6 j3 ?2 |                if( addr == 0x4800 ) {
/ Q: D$ b$ R; l1 K5 S6 ^; D! f1 x                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
" c1 b# }7 ~; Z) G* \! u1 m                }
: W" ]* S/ p4 U        }( G8 X. E9 p/ X  _1 o' c& `; y
        if( exsound_select & 0x04 ) {7 g0 G& Y6 L5 C% ^- m. @. y* s" Q9 O6 c) ?
                if( addr >= 0x4040 && addr < 0x4100 ) {2 z/ G. z. `0 L0 ]/ A- K: V
                        data = fds.SyncRead( addr );$ \! T; C, _# g* S! P# }! ^
                }
4 \7 S! i$ O: T0 {% n        }% j2 C0 s- y* R9 W4 k
        if( exsound_select & 0x08 ) {/ i0 w, k' Q  R' T' L  Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {  U' b1 y4 L; Q2 P, X2 B9 l
                        data = mmc5.SyncRead( addr );" n- [. a- S' r
                }- V. J( H3 a( ?$ d
        }# y4 `4 Q  N+ k+ A: g/ ^- D

' ]8 Q* T  B3 l/ G! ?4 v        return        data;& j( |. U5 q) R7 M
}' s2 o+ U+ u" O! L- U2 j% b# Y
0 `% O( z6 C$ D1 K. T
void        APU::ExWrite( WORD addr, BYTE data )
$ r" Q  }: k0 s/ W  I+ |{& L/ _: K! ]+ X. A4 j/ }
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
: B# m  z! r/ c$ ?
/ d. B& m! u+ r9 }" T( V$ n        if( exsound_select & 0x04 ) {8 a  n9 _$ w$ B! R* v# [
                if( addr >= 0x4040 && addr < 0x4100 ) {2 v& m/ y" b+ q/ q' ^, V
                        fds.SyncWrite( addr, data );
8 Z7 i6 W" W. U' n' t1 B                }9 {* b7 z5 Q3 I8 w) z/ i0 @
        }
" k' Q  r6 R  V2 _
; w' y! e" k0 H' `6 L9 c        if( exsound_select & 0x08 ) {
3 U4 H2 R3 P+ t" v1 t" _* i( L8 c                if( addr >= 0x5000 && addr <= 0x5015 ) {/ h8 T0 X# i3 l+ e; a, t: {% M
                        mmc5.SyncWrite( addr, data );
7 r& J1 s+ p* q                }
) d4 H$ j  b" _5 H" O! `' A! [        }
/ i. o9 S  r3 t$ o% J5 r}
# i, `) d! F6 o; y# f8 C! {0 S& F9 A' F
void        APU::Sync()) f0 I  p, B0 {# x( `
{) r5 c) f% |0 S: J/ i5 E
}
& o. \4 P0 C7 U7 G3 A: }0 B# q6 l" M! l6 p- m1 `# t
void        APU::SyncDPCM( INT cycles )
7 m; Y4 B% }( j( e0 ^{
$ `' \! M( S7 X3 D+ b  a5 G( z& ?        internal.Sync( cycles );
3 \+ K; K; `+ x4 L3 l/ G* G4 D% |, B1 S0 K! m4 X; R0 m; u& ~
        if( exsound_select & 0x04 ) {
1 q$ x+ T  E: |6 ~. A8 A! p                fds.Sync( cycles );% U* L( ]9 h2 A8 p# v
        }
" T& m( e0 s( ^6 i        if( exsound_select & 0x08 ) {
! o+ y" m# O/ V" r                mmc5.Sync( cycles );
( U5 [/ D5 o, w8 R* c        }
6 i5 l* o& b  V}
1 `9 Q# g% B: T) r5 c; |
  M" Q. F3 A2 c4 mvoid        APU::WriteProcess( WORD addr, BYTE data )
  i/ o4 ]$ B, c1 S# }  P{  S5 u1 `/ Z3 L6 w" Y, Z
        // $4018偼VirtuaNES屌桳億乕僩3 Z7 P# |5 S1 q
        if( addr >= 0x4000 && addr <= 0x401F ) {
0 G# y% U  U) n% W& ~+ E/ |                internal.Write( addr, data );
6 M, s: S4 k5 ]2 V; i4 @        }
; v: _% C/ b  _( f" L9 e4 |}
" H8 D8 h4 L+ j2 S3 V( D) n* a( V2 l0 [- P
void        APU::WriteExProcess( WORD addr, BYTE data )
* I: Z1 h* W% o, x' `{
- K( Q: [+ R  [8 h. R2 n& a        if( exsound_select & 0x01 ) {
3 Z& Z; p" r7 E4 L( `/ ~- q                vrc6.Write( addr, data );) z8 \! F5 Y1 [
        }* R* X+ r- P5 P- w; w
        if( exsound_select & 0x02 ) {4 V% z$ U2 b* ]3 M8 p9 S, R9 W9 o
                vrc7.Write( addr, data );
% W) s# x" N* K        }; {3 r$ N+ j  Q' z% k* T
        if( exsound_select & 0x04 ) {) }  E* {  P# c
                fds.Write( addr, data );* F1 ^4 t3 V, P  p% Y7 Y4 u! @6 m
        }; `; {+ L  {1 t8 h" q' [
        if( exsound_select & 0x08 ) {
- D# L2 N* S" W% E4 f                mmc5.Write( addr, data );
: @  p3 C6 L5 N/ l. A8 i  B9 E        }6 R9 f9 v0 `. c
        if( exsound_select & 0x10 ) {
- L" h- }" w8 L. `" H! \. _+ ]4 P                if( addr == 0x0000 ) {! j# O8 R& g/ h; _+ c9 V
                        BYTE        dummy = n106.Read( addr );
2 c, g' X+ ?$ t! f4 A                } else {6 V. _6 G% t3 P5 g: X
                        n106.Write( addr, data );' R6 Q6 c7 ~6 J( a' Y
                }% J9 L7 h3 j2 y* [: d6 c* L7 `
        }4 z- d* ?+ _$ [  h  K
        if( exsound_select & 0x20 ) {* a# c( X' G( P6 ]: F( s: V, C" f
                fme7.Write( addr, data );" \+ L( e  y/ A5 ?- ~  f  t, ?
        }
; P( Y6 A& j# A1 d2 s}
* V8 ^! `* A4 p4 o( \  b2 L8 v7 C! t( |+ e/ H
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )& ?* X0 s5 Q, L& s. |  R! G
{+ v5 ^+ m; g( i% J7 P9 G  L
INT        nBits = Config.sound.nBits;
9 G/ o3 G0 B) t3 E- N# F/ _) uDWORD        dwLength = dwSize / (nBits/8);
* W; C2 k, z2 H6 s: _INT        output;) {/ V0 X4 K0 j6 u3 H) l
QUEUEDATA q;
! k8 J8 A/ h1 c- [3 rDWORD        writetime;
) r# R) a, d8 Q; s' _7 R" l/ ^4 n3 z* p1 {  m
LPSHORT        pSoundBuf = m_SoundBuffer;' t% A: ~; I( V2 p9 V
INT        nCcount = 0;; h8 A/ E+ T3 Z- X) R4 z

, @7 ]5 }: E  l+ @/ QINT        nFilterType = Config.sound.nFilterType;
6 l9 e1 R# B! i, g4 I8 R3 v* `" X8 R# W
        if( !Config.sound.bEnable ) {
$ ~" V9 x+ k, V0 h7 R+ }1 |                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
. r& d9 p- G$ ]+ D. h9 W3 S                return;( w8 B# V. i; p* [% h7 U- q
        }/ k0 m) k; H" z0 }' ~. m# V

1 T7 D  i/ [, {# {5 J2 b        // Volume setup
3 z8 J4 C; @3 E7 \( r2 w2 A        //  0:Master
  e3 @( l! e! r4 X1 h" _) J. e        //  1:Rectangle 1* X* d+ w; S2 \  @2 H
        //  2:Rectangle 2) }0 C/ h/ q( @
        //  3:Triangle: \7 {: j+ X; w  H0 }( v
        //  4:Noise
# T% r8 N# s! f8 w        //  5:DPCM; n9 M* O# v6 z: a3 b5 w# V; [& V
        //  6:VRC6
: b+ P4 t) i9 n3 x1 W' r        //  7:VRC7  Q& W* O& U3 A
        //  8:FDS
8 q7 I+ X0 s; d+ f* {        //  9:MMC5& _; n+ S" g2 B
        // 10:N106- X6 ?% T% p9 y
        // 11:FME7
0 Z  v' w3 F4 n& }0 H        INT        vol[24];
) K3 s, p9 c6 I$ }0 ^* l        BOOL*        bMute = m_bMute;
+ o1 `) C# q, t( {( w        SHORT*        nVolume = Config.sound.nVolume;
5 v/ @5 \+ H( L( _) I) D& v' C# s% I' K, _3 r9 }
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; T, r- ^" \2 p1 M
* S- P9 C8 Y, G2 ?; r7 \
        // Internal/ o/ |9 u* y# s# ~9 o( m
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;2 u$ _& [! J7 Q% p7 z+ z4 \( Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
! C4 O3 z" Z! |, S8 f& q        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
; }/ Y% N5 R3 `1 Z8 j5 ]        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
% p* k6 q/ X) O5 D. C6 b: M6 J  O        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' [( A% g/ M; ?6 R( n
' Z( p6 q# l6 Q4 g* V, q
        // VRC64 G( a# P4 o" A$ n
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( h4 x' `& u/ q. J
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 v/ M! n+ ^. u: Q9 g
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: W4 O. Q' P( e1 B$ }5 g- Z% [: I% R1 N5 D8 f; Y
        // VRC7: W2 e, l) M8 c; Y' f
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
) \$ d2 \" v2 B; O* H1 ]! @% @( o" B. B9 y3 u  M6 W: L% |, S
        // FDS
9 k( X9 F6 M! `. m' e' g6 s; R        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;! S' S. @6 a8 N; g; k

  S% W& j3 O: Q* b% L        // MMC50 Z2 ?# u) Z  W6 @! E4 h  C3 M
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 z8 o: G8 u6 w4 D' ~        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ y$ }  \2 S" X! n0 l% Z3 ~        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" `. p0 O; D1 K8 d7 g' z0 `: f/ B" u: R+ |
        // N106
/ c  i$ }* j0 {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& K. Y6 H, H2 h. ?! |        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 o3 W. ]8 l2 L: s6 n- [! T; a1 U        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 r+ T. ]+ [; y# @- ~        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 s7 Y4 k, }# j
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- r7 k# l% K* m- x
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' i  X% Y; ?7 A9 ~5 H1 |
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 u1 Q; w4 a, b
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' ~+ R4 \& V& g' n
$ z9 p) K" u5 w- N" X. e        // FME7
7 J, A$ }& {: B) ~+ n        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ A; O0 s) m" O1 b8 V5 Y- y) a. ^# m2 [
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" h, C: b" E( k6 o7 K) g        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) I! V; x+ H. `' b$ b

# s4 r4 B9 w# J  A; ^//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;0 W% a7 R: r' _3 F2 a& J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
4 I% X3 Z" C+ t5 G' `7 O2 X- d/ ]/ i( q8 n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' z  h4 P7 K4 y- O. W+ U        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
% j' I* U# c: S+ `+ c& a: i' K  f7 E                QueueFlush();& o$ I$ x! Q. a
        }: x4 _) R+ N* n) w2 l; b; O; [
" z3 G' v% U- R# |1 K& S- @: ^
        while( dwLength-- ) {+ S( w0 g$ p- r+ h& S; o# Y
                writetime = (DWORD)elapsed_time;
2 T% ~2 {# s2 p: D5 |! W7 D+ y" e
! _2 a- R: q/ W% ~; H                while( GetQueue( writetime, q ) ) {0 m0 ^% w: I0 q# E1 \" q  A8 p
                        WriteProcess( q.addr, q.data );  ^! A' N5 M( Z) h- _; u
                }
8 Z7 m! D( d9 w$ P0 g. R# B
8 {0 w& W; w$ Q+ o9 ~' a, e- W  x                while( GetExQueue( writetime, q ) ) {9 @, n9 B0 {8 N2 n+ `1 a# A  T6 i# F
                        WriteExProcess( q.addr, q.data );: \1 N1 m% d7 d, s' R
                }
- @, n2 t5 R- x/ z0 i4 E7 `9 d- H5 m, i0 p
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
) i) ]2 u2 O* ~) ?, k7 x; l                output = 0;$ I2 K5 Z  U+ r" }* E/ W6 q& S
                output += internal.Process( 0 )*vol[0];! B9 V; C- n* y8 T  v0 U
                output += internal.Process( 1 )*vol[1];- h+ Q* f0 V7 j1 h6 x2 H+ b5 l+ {
                output += internal.Process( 2 )*vol[2];  b" ~' k( P' R9 _/ S2 C$ w
                output += internal.Process( 3 )*vol[3];0 {4 A" k* D) k+ F- Z$ u" U
                output += internal.Process( 4 )*vol[4];
6 Q& \. Z6 K4 z! Y+ y8 @+ \
4 V/ U1 w+ E9 U* E                if( exsound_select & 0x01 ) {+ {1 O$ E5 O; x7 D
                        output += vrc6.Process( 0 )*vol[5];
. v: `" J/ l3 F, Z                        output += vrc6.Process( 1 )*vol[6];8 L$ q, a6 Z( {, i
                        output += vrc6.Process( 2 )*vol[7];
3 N2 H& p% T( I$ O6 t/ }                }2 H' q' O" k! g
                if( exsound_select & 0x02 ) {
3 F" r9 g# T% X4 V/ v                        output += vrc7.Process( 0 )*vol[8];+ z; ~, w2 s( G! Q5 Y
                }$ @2 y- W! B7 i. Y( `, \7 i
                if( exsound_select & 0x04 ) {9 ^) q( a. }6 @2 a5 B! s
                        output += fds.Process( 0 )*vol[9];  H. S: {$ f8 G
                }
$ \  y$ M0 C4 h                if( exsound_select & 0x08 ) {
8 P/ T+ _4 v, i/ c                        output += mmc5.Process( 0 )*vol[10];
1 S/ G2 T" n6 l9 W& Q                        output += mmc5.Process( 1 )*vol[11];& ?# l+ e0 l8 P2 C+ a
                        output += mmc5.Process( 2 )*vol[12];4 t4 s+ ^  O/ q0 `* l; @
                }
# I$ q1 Q1 o; T8 u                if( exsound_select & 0x10 ) {
) T1 W7 Y1 S3 `+ G                        output += n106.Process( 0 )*vol[13];* \' j9 w) n3 x2 m2 Z
                        output += n106.Process( 1 )*vol[14];$ R) e" N% |2 E: H- o) _
                        output += n106.Process( 2 )*vol[15];- O. L) e4 d  W4 x+ B
                        output += n106.Process( 3 )*vol[16];
* |0 v+ e! A0 @% z4 @* \6 X+ f                        output += n106.Process( 4 )*vol[17];
7 K3 b& ?2 K; k( z: i                        output += n106.Process( 5 )*vol[18];. k7 Y3 M" }5 C
                        output += n106.Process( 6 )*vol[19];# N, n! o- O9 V1 V
                        output += n106.Process( 7 )*vol[20];
" A4 U" K% F! G4 V5 a                }
4 m* v2 {/ r* [4 _                if( exsound_select & 0x20 ) {
  s$ w% x* ~; f                        fme7.Process( 3 );        // Envelope & Noise6 q  R( g3 n- t. R9 K8 ~, ?
                        output += fme7.Process( 0 )*vol[21];
) J$ f! ]* ^+ I                        output += fme7.Process( 1 )*vol[22];7 _, n) N& a3 Q& c9 \
                        output += fme7.Process( 2 )*vol[23];
3 a9 x7 ^5 e* ]3 f) a                }
3 y0 g, ]' d" j# b$ h0 I5 k9 i+ J) e" p" w- \
                output >>= 8;
* S* o9 s6 |( W7 t! E4 @& G, D5 Q
' p$ g' `; Z6 y3 E" S                if( nFilterType == 1 ) {, C4 W% K- E$ U" A
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& d: L3 I* A! B                        output = (lowpass_filter[0]+output)/2;9 G8 W7 P: j( D
                        lowpass_filter[0] = output;, u- f& O$ p( h8 F% t/ Y
                } else if( nFilterType == 2 ) {
0 o, f' f2 ?& c! m                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 s, _6 M; T8 H" T$ A, j9 M; u
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; O4 x) ?6 F0 `1 H
                        lowpass_filter[1] = lowpass_filter[0];1 M3 I) g: o# L5 `
                        lowpass_filter[0] = output;
/ U6 i2 B9 x6 \& V9 k/ a                } else if( nFilterType == 3 ) {! Y+ {: X( d% O- u9 c: v) n
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* [, o; B; n% B( F# W3 g3 ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 ?% V/ d8 r8 Q5 y                        lowpass_filter[2] = lowpass_filter[1];0 y# T& T- n% [
                        lowpass_filter[1] = lowpass_filter[0];
, ]' U8 K( `/ W8 ?                        lowpass_filter[0] = output;9 S' y1 s9 i0 j& B" s4 q/ u9 N
                } else if( nFilterType == 4 ) {
2 ?$ C0 |1 T7 \$ I                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)  d% f  r# T) ?/ S: J/ j
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* ]3 \0 e! ]7 ~8 S# ~+ X" J                        lowpass_filter[1] = lowpass_filter[0];# A' }: t" d3 j6 y9 m. a
                        lowpass_filter[0] = output;
( @3 i5 t. t! t+ f* X, Y/ I$ j" \% \& a                }3 C7 E2 F. v$ W

/ ?5 c& X: z" {: G' V- Q: l#if        0
. V. J4 k$ \3 e& _1 A9 \, j                // DC惉暘偺僇僢僩
' E- _; u: n+ f                {4 Y, K  `9 ^2 Y" o
                static double ave = 0.0, max=0.0, min=0.0;
9 p9 N6 c2 r. O4 T, |                double delta;
# ?& E; M' j) Z+ S1 P! J                delta = (max-min)/32768.0;
: @7 A# l' D. a                max -= delta;8 G3 d  [& @" b5 n6 b9 h
                min += delta;
& D" m9 r9 M( [# `! }: {                if( output > max ) max = output;
' W- p9 ~# ^) L* B' Z                if( output < min ) min = output;! X9 W  ~6 H9 Z0 H  r+ B# A
                ave -= ave/1024.0;% L: [: f9 l" l- j
                ave += (max+min)/2048.0;" c/ s9 ~4 C$ A5 h
                output -= (INT)ave;
0 `& H( j* H# l0 s& B                }; T' s$ K; P, v' A4 P  X. m. d+ `
#endif
) ^- L5 r$ G) b' B  Q8 n! [, L#if        1  l! Q. i: O4 q( k' _% ]6 u9 M
                // DC惉暘偺僇僢僩(HPF TEST)
2 B  e1 X- w+ J9 l4 v, _; _                {
8 ]* F4 k  Y* |- ~//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& [  r. v/ @" P$ c) ]$ E
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
% J# Y7 V- j0 s/ E/ Q' K/ ^                double        cutoff = cutofftemp/(double)Config.sound.nRate;; s+ q1 b# M$ W5 e2 @: z
                static        double        tmp = 0.0;
/ f6 c0 K5 D/ @                double        in, out;% |- k' a( g5 P8 d$ f- U& v4 o- |4 k

4 p0 k. L" q, _- i                in = (double)output;
; Q) s8 Z, q5 L0 m* ^5 G' Q                out = (in - tmp);) E, v3 s2 `. d! X" w
                tmp = tmp + cutoff * out;3 B' o8 Q. O* k

# S, d: [1 N- {/ Y! k- r- x* n" h                output = (INT)out;
0 q* x1 k  K/ [$ R7 _                }
$ n7 c! [) _) A7 P#endif) n" i' N3 z0 [* }" c
#if        0' y. M5 s) M# W. i$ Y) U! h
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* D8 Q9 X& B  ^# L# j                {$ H. B' c$ f& A# l
                INT        diff = abs(output-last_data);
; g  W8 m) ^% j( ]$ n                if( diff > 0x4000 ) {6 J. t0 Q. U4 H3 N& c, n
                        output /= 4;
5 j4 R! [4 v2 E                } else
+ [2 G8 E! Z2 @. J' E/ R* P                if( diff > 0x3000 ) {/ \+ V/ R7 e/ j( [0 Y2 B9 i
                        output /= 3;' {- g1 b1 \1 w" r+ Q
                } else! T% Y# {# I6 @6 V9 }% O) Y
                if( diff > 0x2000 ) {
- p/ V5 X' V6 C0 }: B, G8 X                        output /= 2;
" @" L% X* t# b/ \2 w6 @. T% U                }
" R( |# e8 D# X& K                last_data = output;
4 T8 {: c, A0 j4 X' Y                }' T0 ?5 J  c2 D& H$ `! E
#endif
0 T  Z: ~1 R0 X, X, W                // Limit  j1 ^" p! J) g
                if( output > 0x7FFF ) {3 A$ c& L2 n- r+ I" S1 k
                        output = 0x7FFF;
. f8 ?: C+ O3 X& q  H5 e- N" ^                } else if( output < -0x8000 ) {4 Q- g. S% c& @: W% q& x6 q5 z
                        output = -0x8000;( h2 v1 S* }9 `" A# J
                }
4 ?7 [! o- u5 v: N5 h. c
2 d9 x4 ~% D. J  V9 t5 J4 w- g                if( nBits != 8 ) {" P- C+ T9 x/ c( Z( A
                        *(SHORT*)lpBuffer = (SHORT)output;
0 q8 X: ~1 _: e3 b' O9 \( e7 R' d6 o0 J: s                        lpBuffer += sizeof(SHORT);$ m% |5 n7 z" F7 ~# H. X
                } else {( P3 ?9 t; \2 z
                        *lpBuffer++ = (output>>8)^0x80;
& M8 x1 d% Y) O2 v" G5 a9 t5 l5 _/ }                }# E( c; A# U( V3 ?

% h- i' ^$ u0 {6 I, K1 p  f                if( nCcount < 0x0100 )
* E- w- N+ ^0 m; ^( P5 l                        pSoundBuf[nCcount++] = (SHORT)output;/ p: u. `8 {- a: F$ Q# c

2 _7 E! a. E0 I3 D; U6 T$ x//                elapsedtime += cycle_rate;' z$ q1 ?# {- D' ]  R
                elapsed_time += cycle_rate;
* N5 X) E. q  K+ B) h* a        }% Y' D6 |/ f: i! w. f% P

1 m. ~  H, D0 H' x, t6 t/ A6 d#if        1
- P( k5 A" ]: j4 j, w        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ _6 _2 A, V) J* N# z3 ^0 z                elapsed_time = nes->cpu->GetTotalCycles();4 y; U; _' k: \9 ?
        }
5 H4 X6 _/ D! Z0 T5 q: q, M* @        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 v6 ]) T$ E- F
                elapsed_time = nes->cpu->GetTotalCycles();
1 G: I+ x3 p# e# P6 c        }$ t! Z* `) Q) ]& [) O# R
#else
# O( U* A& i5 b$ h* M) U        elapsed_time = nes->cpu->GetTotalCycles();
0 t$ S5 ?6 F0 F; H4 `' G* R#endif, K( l6 ^. L% p6 K- V5 T. g
}
3 i  H5 p5 C; _3 C8 E! v
- }* p' ~  g8 e, b6 p5 \" Z// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
0 R" A2 b9 {$ ^& @1 ~9 _INT        APU::GetChannelFrequency( INT no )0 w! I# n% A, d- e* ~
{/ m: K8 M+ _- U2 I( U6 p+ n/ r( K
        if( !m_bMute[0] )
' {* [) }  \$ E$ v5 C! p7 o; v                return        0;
! _: L+ K& Y, G: M8 o5 E  g" F, n$ g& K( y) N0 _
        // Internal  k% ?) i+ F1 E2 K' i+ g5 c; C2 H
        if( no < 5 ) {
- c1 l: O* N8 B9 m% Y7 U                return        m_bMute[no+1]?internal.GetFreq( no ):0;9 b; w" K: T, L; T  m  Y
        }
, K5 |0 a7 }" }! v        // VRC62 u8 s7 A- e, I5 i7 d, d5 e
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {, y4 `+ W! V* X% |7 r$ u9 d
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;+ a  a4 s% ^* S% S
        }0 d# s% E8 U; g
        // FDS0 B3 a  {8 g  e3 v; q9 V
        if( (exsound_select & 0x04) && no == 0x300 ) {
, U: z/ h9 L; T# F. G                return        m_bMute[6]?fds.GetFreq( 0 ):0;5 E' w! Q" A0 g! K0 A
        }
4 \( p, V0 A' Q3 a: k& l- U        // MMC5
/ h! x3 ~' I( W2 ~9 U1 A' K+ @        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {' k- |6 o: W3 y: @- N  I
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) x+ ^# F- ~: h) N7 h        }
/ _7 P# y: c3 J  z% U" A8 s+ N: K        // N106
- Y) Q+ I, D. ~1 D$ d        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {" `. G8 d9 T& E) s" P" u% p
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
1 e  `$ V$ s* K  V0 ^5 Y0 i9 o        }
+ \  e; g, f1 \. C3 P" P  f) s        // FME79 P9 s" \1 r* Z4 d+ J1 i. [. b
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 C0 a* V8 t2 W  K                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
! H" Y5 c" g+ p# }5 N0 D        }
+ Q( Y/ G3 M8 P& n( J        // VRC7: ^4 C4 s9 ~3 ~7 k! K8 ?( x
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
& x- b0 I7 p) C* h                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 ]9 c# w( a% z! K/ {2 N+ J        }  q, Z& o; H" G# D2 q9 r
        return        0;
4 y- H" t; R8 J* C* S}! L* ?" u- g4 s% K; O8 R

! ^  O+ z, f* F// State Save/Load7 M& g; o4 X+ h7 ~, b
void        APU::SaveState( LPBYTE p ); \; N7 l# u- v+ D, @0 Q9 H7 {* }
{( ~; J4 U2 }  n9 k
#ifdef        _DEBUG
/ p  P8 `8 U  a) c' gLPBYTE        pold = p;1 z/ ]: r) r1 x! g
#endif
  z( [3 m- ~* ]+ n
) _# d# U7 d  e  |0 {2 y+ B        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
3 g4 `. L: N4 D3 R3 l9 g        QueueFlush();
3 O  S! f2 O$ L- p% Y" `4 y
( f, B9 J. c4 D- }9 P+ p) z        internal.SaveState( p );  s) W4 ?! c" X+ S: O! l0 ^9 g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 R4 n8 Q& i% g4 K9 F5 {* W. Y% _4 z
        // VRC6
! m  h; T1 X# |3 a3 r        if( exsound_select & 0x01 ) {
/ I1 ^- H" J% j0 [" ~) m9 r                vrc6.SaveState( p );% R' \- j, F! m
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. J* R; {. }5 Y/ Y3 E5 T        }
) y6 R& \5 r4 v4 J/ \7 l        // VRC7 (not support)+ R3 ]0 ^/ @& P& n0 \) j- b
        if( exsound_select & 0x02 ) {2 N$ \9 k( ], w2 b& t4 Z$ p
                vrc7.SaveState( p );
: x. I% |1 O8 f1 P                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 l  ^+ P9 Y5 x- [; O- @
        }2 T$ B/ z0 \8 U2 O! ~) P9 {0 Z
        // FDS
" O4 d1 ]/ ^0 ?. E5 z& I. E        if( exsound_select & 0x04 ) {
3 H% @4 B9 Q$ v  z                fds.SaveState( p );
: R9 _- j  {" I- Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 X$ W' N4 q6 C3 Q! \
        }
: A% e$ }, O% Y4 K        // MMC5
. w' e+ J/ ?: Y" A4 U; z, |( k        if( exsound_select & 0x08 ) {
. F9 O& c( z2 p/ V4 z) n6 V8 l                mmc5.SaveState( p );4 S5 D, K2 C/ V( s8 \% l
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ j" i6 Y. k4 r' o) A        }. x, v7 c4 q  _4 F7 Z3 I
        // N106
: c; q. d; Y# s. e) X6 i; P        if( exsound_select & 0x10 ) {
( D$ Y3 r* v/ o& d                n106.SaveState( p );! o$ l1 n4 s+ F5 m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 y" s2 t7 m1 S1 K" f8 O. E* z
        }2 g6 c& ~) P  F
        // FME7
; d0 v; G+ d' O, F* v& w% I. x        if( exsound_select & 0x20 ) {
; U5 b& G  P: q  x/ Q' ]                fme7.SaveState( p );
, t# X* j+ J+ F2 d  E) i, ?                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# }+ E* O$ t! r( A3 A& Q        }
2 `9 z5 a' c3 z9 z# W8 y1 R) X6 @! q" i6 Q
#ifdef        _DEBUG
4 U) ?% y/ V% I4 {! c: ~) z. FDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );' g' J& A8 i+ F5 b
#endif! J9 b( o2 v: _7 l& y' }  e; u
}
( k; K/ }6 ~: L* z6 @9 n5 v! R  I. y  Z
void        APU::LoadState( LPBYTE p )
& B- z+ G2 L: V# w{6 O% K6 k! R1 U( W: a: f
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
4 B) s. o" }, h) t/ q        QueueClear();
) F) ]# E3 @9 X/ O3 V/ C, i" ]& q! N% m: y! y4 T; q% j
        internal.LoadState( p );. P' B4 u+ _. h3 g5 }, O
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 W2 r* x( B2 J; Z6 F; M& x% @4 N; k0 ^& @1 a+ u
        // VRC64 H9 e9 F) l7 @
        if( exsound_select & 0x01 ) {
/ _. o2 i5 {! w& L+ Q                vrc6.LoadState( p );9 h- B; Y1 u/ Y# O# X
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ ?) A; ?- _! \2 R8 z& w
        }
1 g& D0 e" X( ~4 L7 L/ J2 E        // VRC7 (not support)7 c& [0 S# N  Z$ W* c
        if( exsound_select & 0x02 ) {: q5 R. G* X; P8 d0 M( P+ O2 g
                vrc7.LoadState( p );" D$ A2 u- h2 ?; @- h# L3 ?
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 ^' H- S! E8 J- j        }
! x! n2 R! W; w  n, g) d        // FDS" U& ~7 h# N- f6 B; @5 T
        if( exsound_select & 0x04 ) {
9 @" c* j3 v( U( n5 L0 ~$ A4 Z                fds.LoadState( p );
& ~5 y% u; f7 q/ G1 [3 {' d6 n                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- {  n" `% n6 o6 J& s6 _7 K% |! h
        }9 O8 c& v$ K; ?  H) f: o
        // MMC5  s; v, F( K6 K+ H
        if( exsound_select & 0x08 ) {# r% ?" i& D( V
                mmc5.LoadState( p );
6 }7 s% H) d$ C0 j+ b                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 i( h9 @; G$ E/ _. J2 }
        }
) p( R- _/ [# z% ?8 |7 ~        // N106" \/ }+ X" C5 v* l: g0 n
        if( exsound_select & 0x10 ) {. ~2 k2 {- U2 z# b) ^2 I
                n106.LoadState( p );8 V1 k" c' x2 j7 R
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: P% `# g7 o, E0 F8 }0 Q        }9 v! o% W: G" H/ m! s
        // FME7
% ?7 L4 ~+ I7 b+ ?9 j4 t5 {        if( exsound_select & 0x20 ) {
, Q+ n( B! v+ `2 Z" L  y  z                fme7.LoadState( p );
4 t/ S' s2 q* A' |# V3 c                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding6 e2 x; q3 h! ?- T
        }2 d, V' `1 ~  Z; n
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ( z1 R) c9 ^* k* q" l) U' F. @
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
# Q  _' d: q' j# P: Q, B% q感激不尽~~
# y6 J& h6 t6 ^- i" I$ k
恩 我對模擬器不是很有研究,  u( C6 ]! w4 d8 U% F" W4 Q& v
雖然要了解源碼內容,可能不是很困難,, o7 ]# K* X% A5 L( w/ }
不過還是要花時間,個人目前蠻忙碌的。
8 h5 T2 K" c, p( l3 i. s5 K, F. G0 F' I
給你一個朋友的MSN,你可以跟他討論看看,9 `( k/ f6 K; @0 V* k% J* X
他本身是程式設計師,也對FC模擬器很有興趣。
# m  [9 @1 x, L' i" D/ j! i# H; N. z8 }8 c0 I3 @9 b
MSN我就PM到你的信箱了。
( y) v! Q5 W2 q: @- E  R( o( ~: h9 V8 o, ?- c4 i
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ! k: o! w' [7 X3 Q# x7 L- o
呵…… 谢过团长大人~~

; t/ A7 m& ?3 X% r! k: g  m; K, @$ X9 E$ X
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 G: ^9 F% F5 R! D( t* T
团长的朋友都是神,那团长就是神的boss。
( P6 t+ U% v7 z! u+ _* M9 s) K
哈 不敢當,我只是個平凡人,
' D8 }  y  c& ?% \% j' D要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙5 Y. |5 R9 S+ G) ?
ZYH# H' ]+ V  I8 [9 N5 k) t
QQ:4147343065 n# Y6 k* j& d
Mail:zyh-01@126.com
& T2 x$ ~. H% G6 ~9 m5 n$ z+ w& b: b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! w2 C/ L5 X- X: P再次对团长大人和悠悠哥的无私帮助表示感谢~~
: H. y% ^! X8 K
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-31 08:25 , Processed in 1.263672 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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