EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; ~+ T4 c3 S* F5 Z7 _
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) S/ g5 h; Q, H, n0 B4 Q这里有相应的模拟器源码,就当送给大侠了~~" z3 i( L% g: W' b' B
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 3 _% |0 ~6 M& L2 q( }
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 R/ s& c( C  o" S, g& Q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 F- d. Y% ^0 F2 h& `# `( Z
这里有相应的模拟器源码,就当送给大侠 ...

, Z& K$ r# `+ z$ ~+ i) T聲音部分(Audoi Process Unit = APU):% ?, [" T9 d. o  J% y- y5 \) w; E
.\NES\APU.cpp' E2 q$ K' z7 d  F
.\NES\APU.h
2 G6 W% o% ^7 g, h
' g1 l' C6 T8 v! R" @# X$ A
9 u, j5 l. ~1 F* }0 d6 y! ]影像處理部份(Picture Processing Unit = PPU):
$ I9 Z4 g3 G' i, i. r.\NES\PPU.cpp2 K5 ^( B; y1 \1 h! T; O
.\NES\PPU.h3 Y. `( A9 ?" Y0 C
# b! C0 q; _! J# ^( a! ^+ [
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, f+ @- x  c6 c% k# M5 P1 ]
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 ?, t; p3 e! D! j' @, _(由于很多专用术语和算法机理都不明白,所以看不大懂……)
/ M" z; E- a& P7 S6 v$ R# m( h//////////////////////////////////////////////////////////////////////////
6 |# o. Y+ T( B5 H* X//                                                                      //
! w7 F8 e6 O. `' L//      NES APU core                                                    //* x" x4 {, P: M) Y1 K( B
//                                                           Norix      //
1 E% M* s. G7 \! f- N//                                               written     2002/06/27 //
; o, B9 T0 B; c2 v- J& `//                                               last modify ----/--/-- //9 H2 H8 e- M- @5 K& `
//////////////////////////////////////////////////////////////////////////
' d! q1 x# }. X" U  t#include "DebugOut.h"
6 L3 B3 g- ?1 Z1 @- s#include "App.h"
) V* F' w4 q+ L) v$ Y4 I#include "Config.h"3 A9 Z/ [! {. r3 l

9 |6 v6 i6 F  v3 ~2 }6 X#include "nes.h"" W/ t- N( ^. h1 Q7 n
#include "mmu.h"
+ z- `1 K* G) @' f7 k#include "cpu.h"8 E7 [6 z! ~6 {: U7 I0 H
#include "ppu.h"2 F. D- u- ?3 w4 T2 B
#include "rom.h". s8 \( l3 U/ l# N! O: y7 j
#include "apu.h"
& q: J0 Z( b* y( m: R( V3 ~& p: k2 v' H+ s  U
// Volume adjust; F6 L% x/ d  t& l1 N& x
// Internal sounds
4 t' I4 V5 A% b/ m- c2 c#define        RECTANGLE_VOL        (0x0F0)
  C' x! \" G5 M#define        TRIANGLE_VOL        (0x130)) v, i) G' L7 ~' g( M" N- w" \
#define        NOISE_VOL        (0x0C0)
9 c6 l( L2 M  U. r( a6 G#define        DPCM_VOL        (0x0F0)1 V7 ?4 L3 T8 w2 k6 \7 \
// Extra sounds2 Y/ `% K$ R+ o$ S4 z
#define        VRC6_VOL        (0x0F0)0 y+ @0 }0 W5 S/ A; q
#define        VRC7_VOL        (0x130)9 C0 z5 R2 [/ q3 E$ A
#define        FDS_VOL                (0x0F0)! {1 e. X: }0 z. {1 N4 J/ V$ Z
#define        MMC5_VOL        (0x0F0)
9 ]+ z, R$ M; O#define        N106_VOL        (0x088)" w! {/ I' V" u' t1 o
#define        FME7_VOL        (0x130)
7 ?# @# ^5 }5 z+ U$ d$ z9 e$ }: o* g8 v. m7 u+ I+ k' Y' }6 `
APU::APU( NES* parent )* ?% ~9 ~4 I3 j8 m2 S
{
3 @3 R5 M2 ]! U2 n* N        exsound_select = 0;
3 w# T# L8 T; X+ f7 r2 M2 t* J0 k+ P. \: f, E4 n
        nes = parent;1 H" z  ~* }: j2 x/ q7 @
        internal.SetParent( parent );
, b# r+ j; p" p$ T  F! @0 Y' C7 T7 ~& m1 Q% [& u9 i& ]
        last_data = last_diff = 0;
+ ]5 B3 U* U  \$ _" e+ R
1 _. X$ \( T$ z9 S( C% |" c        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 E+ v& A( W8 ]8 V  y
  g9 c* D! F; v) _2 ~& T  z
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );! O) N/ v) I  x. g6 v
        ZEROMEMORY( &queue, sizeof(queue) );. O. m& N( v2 F* d  v# y6 t# e
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, q: I/ q% S, r$ I" M

. {, s& d# e  D        for( INT i = 0; i < 16; i++ ) {
# t8 [( ?4 W$ ]7 o                m_bMute = TRUE;9 J  M9 Q$ e1 w. F+ _
        }' ]: U- X: A( C) j6 c% p
}
- C9 t1 ~4 Z& ?0 ^' N# p+ ~# L$ [; c9 d1 K; M; u9 ^( P
APU::~APU()
3 Y0 i9 }0 v0 {) @( }{
4 e7 ]- h7 l3 ~2 r8 T}+ I2 G- Q5 e6 o5 o# E, o9 h

% q! D. }2 w, K5 a2 qvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )( P' j& O; L) g6 D! c1 R/ |' q
{
  g6 f: J3 V, S9 Q/ T- A! `        queue.data[queue.wrptr].time = writetime;
# M* l& `) a2 U. k        queue.data[queue.wrptr].addr = addr;
4 q' T' f; w9 }4 U9 t/ U  ^        queue.data[queue.wrptr].data = data;  r- C# _# n0 C
        queue.wrptr++;
3 W2 `2 ]  m$ f, E7 G- Y        queue.wrptr&=QUEUE_LENGTH-1;
1 U2 v  s) y3 K( G# i5 f        if( queue.wrptr == queue.rdptr ) {
7 K* G6 r* t% X- @                DEBUGOUT( "queue overflow.\n" );
2 E: Q% w- C* x! z/ w        }7 z. ?% e0 S; Q7 v
}
, Z4 o8 C& N+ D5 v" b# V6 |
% o: S# x- _) S( y/ Y9 F! xBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
9 R& \" X4 V) g7 M{
7 }" U9 ~" Q! d5 ^, n, l( H        if( queue.wrptr == queue.rdptr ) {8 ]) [1 y8 v. @, Z) S9 V* _9 H" o
                return        FALSE;
1 r& ^; f# z6 K/ y; N! Z7 [, \. `2 ?        }
$ k: s( h5 z5 U        if( queue.data[queue.rdptr].time <= writetime ) {
5 `5 w* a0 h! ~5 ~# g1 R# B* m                ret = queue.data[queue.rdptr];. u% r8 |7 s  Y0 ?8 D- M
                queue.rdptr++;
  b! Z" O7 a. F) c* k                queue.rdptr&=QUEUE_LENGTH-1;
( U6 d: B( N: v! J                return        TRUE;
6 Y- z# a; A- y! L$ S! f+ s        }
+ ?& ~' v. a8 F; D; T: a        return        FALSE;
+ e! d/ z& q* }% `$ w- @' A}" U" b8 i2 `0 S) O$ k- ?  t
4 f" ]3 C7 \1 E4 Y5 V2 U
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ), {6 ]  J4 d/ D3 y0 z
{9 ~: Z% t9 d, c8 M9 B9 r' D* ~# s% j
        exqueue.data[exqueue.wrptr].time = writetime;0 D5 s: F) ^* z7 ^, N
        exqueue.data[exqueue.wrptr].addr = addr;
# u4 w0 W# ], h/ t6 Z+ }" L( I8 D        exqueue.data[exqueue.wrptr].data = data;
6 d3 f. ^0 v2 D+ o2 J  E/ f: p        exqueue.wrptr++;
6 ]4 t4 ^5 K8 D6 y4 f1 Z        exqueue.wrptr&=QUEUE_LENGTH-1;/ T# s  g( m& S0 L
        if( exqueue.wrptr == exqueue.rdptr ) {, }& g: m0 ~( P' l
                DEBUGOUT( "exqueue overflow.\n" );
) B) n4 ^. m; r6 ]) j/ l8 z7 {        }
" E7 h) R: ^, @2 j1 v" r% f}
8 R5 m5 C) M/ |2 z" g2 _6 i( V: g
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
8 W9 A+ M, h6 }& X9 ^{. U3 G0 F+ N' L' T1 Z& Y, \8 |8 ~
        if( exqueue.wrptr == exqueue.rdptr ) {$ f% w2 x0 t& @5 K0 H4 F
                return        FALSE;7 r' z; i+ m- ?7 ]; K$ Z2 x
        }
' T4 b% V, K) C- x7 a        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
+ G9 }9 u6 L5 _6 l8 R2 R. m: a                ret = exqueue.data[exqueue.rdptr];8 x8 D) m* H' g, C$ C1 V3 H, x
                exqueue.rdptr++;% G1 O7 W. I) [7 x% @
                exqueue.rdptr&=QUEUE_LENGTH-1;
! h+ E# G" x7 v( |3 n                return        TRUE;% z; p6 w8 Q9 H3 K
        }$ i, H2 h2 c% u- G
        return        FALSE;& o- w6 d- h2 H& {. z
}
& o( q, Y0 |  s+ ]5 x% O7 e/ c0 O, T$ T1 g* r
void        APU::QueueClear()2 i/ b" {" t8 P1 q) z  h  M
{
4 m' Z, O  P% g) U4 V        ZEROMEMORY( &queue, sizeof(queue) );' ]3 c! ?) Z9 J! y& D1 d2 T; r/ l
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 W+ @' g7 K" x% I; i% o3 L
}; o/ q1 {' B; G( M8 C
& ^) x' v6 U. F/ O, |
void        APU::QueueFlush()% a: H6 V* L, g
{* L2 Q, x/ J, ~0 Q+ O
        while( queue.wrptr != queue.rdptr ) {2 y9 q' c# b3 ]0 @' U
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, J; J- J, B9 f& C+ r
                queue.rdptr++;  r9 h1 D" }4 a' B$ j$ f
                queue.rdptr&=QUEUE_LENGTH-1;, R  y" P8 H# O9 X2 h4 C" ^
        }
2 c7 |, |; I. H+ v$ |7 o7 s( b
3 z1 u# S5 W" r& D: T        while( exqueue.wrptr != exqueue.rdptr ) {
/ y' |% J# x# G0 u. ^( D* z                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );) a4 Q7 J8 F" t4 z
                exqueue.rdptr++;  B0 g) r; M; {: Z3 H
                exqueue.rdptr&=QUEUE_LENGTH-1;
9 U: M# \. O' i0 `2 \, o        }" D, W2 Z3 Y4 B8 C2 a* Y' ]
}4 U$ L4 M! D" p7 s% b5 @5 x
! S( y6 P/ o- }5 y( u" d2 w% ^) Q6 ]
void        APU::SoundSetup()% J1 z; z0 M4 o
{( z& D4 c' I/ z8 W7 m" @6 P% ]
        FLOAT        fClock = nes->nescfg->CpuClock;
  P9 u# S; i3 z  g1 f        INT        nRate = (INT)Config.sound.nRate;. V6 p7 Q# H! N
        internal.Setup( fClock, nRate );5 c, C' i& B0 I  V0 E* @# E
        vrc6.Setup( fClock, nRate );. d& D7 S8 H$ Z. t3 _2 g0 ?
        vrc7.Setup( fClock, nRate );
* L+ C, q- i, N9 G        mmc5.Setup( fClock, nRate );
! n( m5 j: k" d- T/ t: ^        fds.Setup ( fClock, nRate );
" G+ l. e9 E- t0 D2 x        n106.Setup( fClock, nRate );
- `# @$ E" j- \: ~1 ?7 \9 ^$ w4 u2 L        fme7.Setup( fClock, nRate );
& f) f$ l2 s7 E" B( j9 k6 z. E" `6 p+ M}
" g0 [7 }- N1 t/ ?# i
) A* |% `/ [' A* J4 B5 Lvoid        APU::Reset()0 j% Y4 T$ o8 ]0 W- w4 g& f+ s1 a
{
# n' R- y$ K8 G9 U        ZEROMEMORY( &queue, sizeof(queue) );
/ l5 P( l- |, i& T- o: p" W. f        ZEROMEMORY( &exqueue, sizeof(exqueue) );. U7 L$ o9 N( E# ]7 b3 f

' ~/ ]3 W( `9 }% s! j        elapsed_time = 0;7 D  }* _9 N( b2 G9 G2 E

1 O: v  c% K2 M! u        FLOAT        fClock = nes->nescfg->CpuClock;! y) a. T( t" A! \  V; ?) t# ?7 A; Q
        INT        nRate = (INT)Config.sound.nRate;
) U  A8 ]6 h: t0 H        internal.Reset( fClock, nRate );: B! Z+ o% m& [
        vrc6.Reset( fClock, nRate );
* N6 t" B4 O6 v* o$ d4 `/ ?        vrc7.Reset( fClock, nRate );  m* b; s* F; L
        mmc5.Reset( fClock, nRate );
8 C! l# `& d( w" ^) A        fds.Reset ( fClock, nRate );1 g% i, P6 S& L) a+ N. N9 U: I
        n106.Reset( fClock, nRate );
$ I( ?1 s! @* w' B7 O        fme7.Reset( fClock, nRate );( j: d, B/ C& Q  j0 j

: ^; w6 V7 L; Y        SoundSetup();
4 [# M& C$ [3 q, b, f; J}
- ?" L' x6 x% h2 R  C) t
! z& P0 k/ {/ S; B9 uvoid        APU::SelectExSound( BYTE data )1 Q3 K, q& N7 G* o3 D) X; \
{
: Z0 s2 D: i5 S0 t" o0 L        exsound_select = data;
& v9 [) a+ e1 {$ n! j* c  W}. l; {1 n" l9 z4 d2 v# S( g
7 K+ ]6 b3 x5 X* U+ v
BYTE        APU::Read( WORD addr )2 ?6 N. D& Y4 k
{
6 |  c. G9 {- q        return        internal.SyncRead( addr );6 K  j8 n9 E2 `0 A+ x
}- [4 l& ~# q$ ~! G5 q. b
) x- ^- J& ^& H# m. x4 i
void        APU::Write( WORD addr, BYTE data )
" Q4 \/ k, i9 }* Z( a3 K& A! x{
1 s3 w4 J: d; b8 @        // $4018偼VirtuaNES屌桳億乕僩, D- Q. r3 M3 w: X9 L  B
        if( addr >= 0x4000 && addr <= 0x401F ) {6 `4 t3 X' w4 N& P( m! W/ u1 U
                internal.SyncWrite( addr, data );0 {& k4 N8 x- ]/ E
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
, N# h+ t) e$ v6 T, z2 J, l9 z        }2 y# N5 d* a# y& ^
}$ @: O, L* A& I. Y; N" r& C5 ~6 f+ e
; D! s& e+ X$ x0 J
BYTE        APU::ExRead( WORD addr )
4 [  y5 f- f, r( U  F{6 I# y; u( W6 O$ f- {6 h
BYTE        data = 0;
+ r# u0 L# d% q. d5 B, j  s
% A( w. @9 s' m6 P, K9 h        if( exsound_select & 0x10 ) {8 P$ o( }; u( \, V  i
                if( addr == 0x4800 ) {
" j; }. V; b% P" i1 f0 B+ d0 m: a4 T' K                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );" r' |9 b' W8 {  m1 ]0 t
                }8 Z8 u: i" z: n2 D" u# M9 m
        }
# u3 `* b$ A  W        if( exsound_select & 0x04 ) {/ Q2 H( A, b: ~  I8 T4 A2 t
                if( addr >= 0x4040 && addr < 0x4100 ) {+ M9 }# R' N" e# w" p
                        data = fds.SyncRead( addr );- ?7 W( M6 b( Z3 O( }# P8 P9 B
                }" b$ M+ n& S+ B) E
        }' F) H% ~! K0 x+ a9 @
        if( exsound_select & 0x08 ) {/ V( D2 d9 p  s6 p. q5 x/ Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! L' N/ C; g$ |; n8 v* U1 w2 d' H& [                        data = mmc5.SyncRead( addr );
: i, ?' \: m. t- {9 L                }0 `, S! _. o2 f  P
        }6 u1 N3 F1 {! s( t) H, D/ K

9 G3 b5 @& ~3 ]: w' w( M        return        data;) l- q3 L7 N4 Y" S4 |5 C
}1 v. A2 U; X% ~& M7 O' O& ^

, I2 P# b( A3 U1 r6 X6 nvoid        APU::ExWrite( WORD addr, BYTE data )4 _2 _: }5 q. \1 M; C# ~* R/ A) r
{
" i' b1 y' }. F' y3 i/ c5 _        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
  L, s; A  a: B7 \/ t& Z6 g6 |; y9 s% P6 b  k1 c
        if( exsound_select & 0x04 ) {9 s% f, d. Z9 O# J7 V
                if( addr >= 0x4040 && addr < 0x4100 ) {
# W9 O$ e, g5 Y. }1 C8 ]& z                        fds.SyncWrite( addr, data );% u5 `+ B8 T7 c5 H
                }
9 u+ R1 X0 f. I9 D4 t        }: `# Q" l" @% H4 |" |

( j- P; e; @+ [        if( exsound_select & 0x08 ) {8 |) x, D! a5 E& h8 V9 Q5 w; l
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* o; B1 U9 h2 M- a( @9 W; t4 B                        mmc5.SyncWrite( addr, data );& O" L% z& P! i' P+ h
                }7 r8 ^. X* x5 W+ i2 \0 u3 r
        }
6 s% P& i8 ]5 L5 @: u; W}/ ~1 L8 T% p' U& {5 N  {

; S5 N- R; o; Q1 E( ]( l& hvoid        APU::Sync()
8 q  D9 @8 e2 x{
- ^6 D( E- N  M' p}& P! L$ n7 S4 V6 h& ]

$ E# S- p# M( ^6 Y% u, |8 G: Pvoid        APU::SyncDPCM( INT cycles )( Y1 s: Q0 _8 v5 @* _" l# l, y
{
  ]9 |: l0 y! D# g0 K& W- N        internal.Sync( cycles );4 c; S/ o. T6 W  S0 r
5 V, W, C, w9 t
        if( exsound_select & 0x04 ) {2 ?& r* {; Q0 [# M! y/ {3 q5 n- O4 B4 h
                fds.Sync( cycles );3 u! b$ @6 T1 Q& e  S
        }" L# n6 L% s* U- z" V
        if( exsound_select & 0x08 ) {6 A( H- Z' b* J6 H
                mmc5.Sync( cycles );
9 S; ]7 e' b: y; Y0 `        }2 W- k1 a8 l) [  J9 R# Q$ u
}
2 n' H7 J; ]: t- ~
9 z, Z- [0 c6 C. [% z% m+ M0 y; bvoid        APU::WriteProcess( WORD addr, BYTE data ), O: z1 l, v% e# b4 y
{
! E/ f# M1 b4 x' Y* s( X        // $4018偼VirtuaNES屌桳億乕僩2 u' z/ @3 O  K! T6 m2 B
        if( addr >= 0x4000 && addr <= 0x401F ) {$ {0 u- n6 K. B: \8 D
                internal.Write( addr, data );
! @" r* F/ T9 o; t" g$ `        }# Z& d: K8 j; P! L* d0 x
}
* q" M! f0 h0 x5 Z# M& Q  {: j4 d0 m& h; a# I0 z7 k
void        APU::WriteExProcess( WORD addr, BYTE data )
& O3 _1 g' r. m& m{# w1 v/ Z7 Q  [$ d0 q
        if( exsound_select & 0x01 ) {
$ j% ?% @. G2 {- [9 ]" r0 \4 o                vrc6.Write( addr, data );
$ C# `. v' t9 k0 {8 W' a        }" v: g2 r0 ~* h/ }* Q
        if( exsound_select & 0x02 ) {
6 J2 m; r6 |; Y% n( m, ]: Q  b' `                vrc7.Write( addr, data );
- t" t  U: u% e. f. ]+ ]        }, G" q- n: A5 G+ Q6 D
        if( exsound_select & 0x04 ) {
' n: b0 |3 d7 w. C+ K$ Z                fds.Write( addr, data );
  @7 P3 P7 Y; {, `* m        }% `5 ^8 \& K) z8 |) v2 h; E9 M
        if( exsound_select & 0x08 ) {& Z) m  c# \8 a9 ?: c
                mmc5.Write( addr, data );
# \! z4 q( ^4 @' e/ i        }
  E  @! D6 x) Q- s% j        if( exsound_select & 0x10 ) {
. P: y8 N  O, d  n' ]                if( addr == 0x0000 ) {
6 c; M7 S6 S0 ^( P                        BYTE        dummy = n106.Read( addr );9 q4 K7 G. h2 G+ d, V2 D. w. z
                } else {5 R; g" O: f( o. N7 v
                        n106.Write( addr, data );
! }. E6 Q6 R0 {                }9 t) H5 o9 [+ h; f) ?
        }& P! s/ L) y/ b' c
        if( exsound_select & 0x20 ) {
  o# Q; `4 f8 `. X) H9 e                fme7.Write( addr, data );& `# Q6 J- C* Q2 Y/ f
        }
6 A  j# `# k3 k- ^8 q% e* Y}
) a) ]6 ^7 W2 w9 f! C; o; k, j5 W5 |7 ~7 e. e" q* c1 h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )* q* G" x- J$ N: q  g. F( o- V
{
- u' F9 d4 I& c* U  p& O4 x& m' CINT        nBits = Config.sound.nBits;
' M3 V& }9 j3 v: m- k! q5 \DWORD        dwLength = dwSize / (nBits/8);
0 M5 Z2 x* y& ~+ X- A3 }3 G; F+ GINT        output;
% k- K! i$ p" p9 |QUEUEDATA q;+ X/ c. w. v/ U- g  O* Q7 `
DWORD        writetime;
5 Z1 R3 @1 S9 b& q1 z; E, ?* ~" ]3 a5 x9 h$ f1 ~. E
LPSHORT        pSoundBuf = m_SoundBuffer;* _  G7 z, @. _* m
INT        nCcount = 0;* B; X( ^( ~' Z" Y

- [* {' U! G9 S4 Q! iINT        nFilterType = Config.sound.nFilterType;$ j  P# |7 o6 q
1 h6 A, \% ^8 {! x1 r3 `; R
        if( !Config.sound.bEnable ) {$ v/ [4 [6 n# t9 y( r6 {; Q$ A
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 X# P7 N8 [! V
                return;
; b; m! x; H; f! x9 ?* h3 T4 I& P        }0 R( m0 i/ v0 q& I3 ^( ]9 ^* Q
1 @/ Y. r. _9 B9 l. o/ B3 j: d, X! a
        // Volume setup
6 f6 ~; ]5 Z- l: Y0 [, H' @# c        //  0:Master8 S8 o5 a) N* h5 o! F
        //  1:Rectangle 1
  f( G9 _: d  F' c        //  2:Rectangle 2$ Z) u9 K+ `8 H; D# t# o; g
        //  3:Triangle
+ z6 d) c: j8 e. i5 E        //  4:Noise
- P) L+ h  s$ d8 j        //  5:DPCM& F& ^# `; t, w% Z2 T$ k7 D9 |
        //  6:VRC6
% o$ d: Y1 g4 Q: h. ~% N! j6 N        //  7:VRC7
0 a: f" R' M. Y1 e4 a5 x) K9 W        //  8:FDS
$ o  G& ^9 ^$ R/ x        //  9:MMC5
, c4 p3 r6 p) D) @) O        // 10:N106
& S, e8 e' a6 Q        // 11:FME7: e2 z+ M+ s0 y  H
        INT        vol[24];0 f2 a6 r' T$ U4 A' O. _$ r7 k1 Y
        BOOL*        bMute = m_bMute;1 E: N$ ~. c& W  F4 |
        SHORT*        nVolume = Config.sound.nVolume;
9 s) p  `, h! k' ^; ?  ~% L
, a9 h7 F: f$ [. S4 K        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
2 Z6 j  p: _# ]2 D- i( C$ H; d
' ~% f& Z. |( R- x: S2 A. D3 @        // Internal
0 u* H9 U4 V3 q9 H" I4 f; r' R        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 I0 H: X7 E, \# U- }: p
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* H$ h* P$ S. A# \8 \8 |* m$ A        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
0 @3 q# v* n8 n  ^/ g+ B) I0 P        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
4 `; ~* j  a& [3 W5 m        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ e) C) A; A% u
: k5 m; S$ y! f0 D! j* ^
        // VRC6
) e/ v6 q5 r2 q1 `' S% @        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 I. J* E* R, c4 e* Q3 n# j+ N
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 H( h( z6 M! z. \4 f. t+ n! @% Y        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% A' b& \+ c  Z; x( T
% _, |. b8 f3 G2 M) d5 a( d        // VRC7  ]) X1 q; A( N" H) a! H" U
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 b" k; t' b* W" O) ?" l
+ {8 P  |9 C" z( o( z1 Z
        // FDS3 D+ O/ p/ p- f7 y
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& j' S" ^- k) ^5 S: [- v' I& i7 w9 D2 X2 L1 @. h, |
        // MMC55 r. [, v6 s( o  j/ q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( y! i$ z/ o$ F: g7 i
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( g; M6 Q0 j! c& R  [
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- {2 @- X4 T  D9 Z

6 z3 w7 ]3 N, o, g( K        // N106; [# W# c7 L1 `1 D' n! c
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" l% j1 |8 P( V2 v" W" a
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# Z" f/ D) D  d/ F  u5 b        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& S, N: s, g3 g4 W2 M) G' w7 j
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 J+ c+ o/ _/ ?: S' T. E
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 b9 d. c. F5 R) H- b
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( M5 q( F# l) Q5 r
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) V& p, a$ A7 r. V6 B, F( m
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! P% P7 x. \! u% R4 U; n! T6 M
* R$ x- r, H* R& b, ^        // FME7
: }! T+ ~/ V4 M. x, t/ N' M        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! g8 p, L9 I9 Z) t4 E" x$ p4 y& a7 E        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ {0 C( {0 j5 H3 H6 z1 t% {        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' T/ M$ a: O" h6 M$ m0 l+ |0 W5 J9 A2 U6 W
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, j. c5 y" }0 x, n
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* Z# [7 b2 k; S! s7 D$ _& ?5 w0 B, \# s1 z8 Y* f8 b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟" }/ d) v/ K* |6 T6 [  d
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {/ f+ Q+ s+ c, R$ z: m# d
                QueueFlush();
- ~0 L  `9 u. d+ a0 ?, Q; y5 B9 _5 X# {3 a        }
) e8 w7 u$ V- k; R' `2 s0 U# s8 T7 T9 [2 O) F
        while( dwLength-- ) {
2 Q  U: m: v3 C/ z. y                writetime = (DWORD)elapsed_time;
, q; n% \; J7 f9 }5 E$ R' M/ V1 @# x. E, h: @( U& g( N  _
                while( GetQueue( writetime, q ) ) {. M# u( K7 a9 z8 ?) r7 `
                        WriteProcess( q.addr, q.data );
! C# c( r/ G. u6 F. c7 S( [                }/ l5 r  q5 t  @1 A# u" W
6 m  I2 z# p$ i" N1 O9 h) t
                while( GetExQueue( writetime, q ) ) {
! z$ T# d3 B5 e: S1 A- L% ]9 _                        WriteExProcess( q.addr, q.data );- t; Z3 ]/ a: [' x: p! U- ^
                }$ q$ K; }# ]/ O5 M* y8 h' \" d3 @+ F

7 J4 i7 |) t2 L/ k+ u                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
% l5 C' z7 A2 S                output = 0;3 u. D7 s: t, P+ D3 |
                output += internal.Process( 0 )*vol[0];
7 a+ R* m5 s! @0 P% W0 B                output += internal.Process( 1 )*vol[1];) m( W; C) G) R4 l7 ]# L
                output += internal.Process( 2 )*vol[2];9 D+ V  U+ }$ _. G& |7 I4 ~
                output += internal.Process( 3 )*vol[3];- W2 N2 d* C/ O' g8 x$ w3 ^4 q
                output += internal.Process( 4 )*vol[4];
- A9 L, r7 L5 D4 d0 V7 z( ]% v- ]
/ L" N" |& _1 B                if( exsound_select & 0x01 ) {& Y! C7 B; C+ K  O2 m, |9 j8 ~
                        output += vrc6.Process( 0 )*vol[5];
$ {0 _& [& G2 L5 T7 l                        output += vrc6.Process( 1 )*vol[6];
9 B7 Q. e2 D5 |! u/ T                        output += vrc6.Process( 2 )*vol[7];) I0 X2 E/ S$ n$ q! K* C: u4 D
                }
; q2 |/ D' }$ C, {                if( exsound_select & 0x02 ) {
* ~' P' e/ X& I                        output += vrc7.Process( 0 )*vol[8];
( i0 B4 z) q; q! i- q6 b9 v                }
3 E+ Y5 L% ^* `* a; t& D                if( exsound_select & 0x04 ) {
4 V9 j! ?" X) k. y                        output += fds.Process( 0 )*vol[9];* g; o* H3 \% G5 t
                }
9 g' j3 c8 l1 e# n+ A3 f                if( exsound_select & 0x08 ) {3 ]+ f/ ~0 s/ r- i
                        output += mmc5.Process( 0 )*vol[10];
  U/ @  @2 u2 K+ x4 L8 Q                        output += mmc5.Process( 1 )*vol[11];
& N, z  H0 P* g                        output += mmc5.Process( 2 )*vol[12];
% }( |0 ~, [' J5 m" }6 F                }* u: R9 F9 L: t& }6 c9 {* t# Y7 D
                if( exsound_select & 0x10 ) {
/ Y: `7 i+ }# d6 j- _! N! {) ?6 @                        output += n106.Process( 0 )*vol[13];
+ ^* x' v, {) Q7 D3 s# V  Y* v- X/ g                        output += n106.Process( 1 )*vol[14];
& |# d$ t$ G( a. F/ Q0 y% c, s                        output += n106.Process( 2 )*vol[15];6 m1 j. H5 h# b; X
                        output += n106.Process( 3 )*vol[16];  ?1 A# f  d8 `& ^
                        output += n106.Process( 4 )*vol[17];
( F3 p! _: t; u4 }* V                        output += n106.Process( 5 )*vol[18];  z# H6 P6 S, k& `) c" b, p
                        output += n106.Process( 6 )*vol[19];
. M8 ?: b& z8 C( w. O                        output += n106.Process( 7 )*vol[20];
& V: C8 m2 Y8 J7 Y- Q                }
, W- M6 t2 ~( j6 @                if( exsound_select & 0x20 ) {( R# U- j$ e: x4 c
                        fme7.Process( 3 );        // Envelope & Noise
. @; D7 M% O% c4 J- X/ m                        output += fme7.Process( 0 )*vol[21];
+ ~! x- x/ Q; T2 t$ c                        output += fme7.Process( 1 )*vol[22];9 A1 ]* T' f8 P; T" O
                        output += fme7.Process( 2 )*vol[23];
5 j/ J2 B4 v2 ]% f; X& d                }
) C( F( h' n6 T5 p2 L8 G' l' p0 }7 s- b" V( ?
                output >>= 8;
# d* X! ?3 v+ z; D3 ~$ T% G; T' Q5 l" q% P- k! G
                if( nFilterType == 1 ) {
" n% W) ]1 ]- p4 x1 A                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& A. C- P- P8 P4 ^8 n
                        output = (lowpass_filter[0]+output)/2;
4 k& A$ @7 W* q0 J  }. _* l3 ~                        lowpass_filter[0] = output;
  W5 O2 z+ w; A2 _* I                } else if( nFilterType == 2 ) {7 f9 k6 `9 v* b: V% A$ \' L
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- r3 \0 I5 t9 I* N- {0 z
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;: v" k: x2 l* K1 g) H9 G; e; n
                        lowpass_filter[1] = lowpass_filter[0];
0 y1 T2 ~. k! u7 f8 j                        lowpass_filter[0] = output;2 a: ]) u1 x0 S- U9 U5 v
                } else if( nFilterType == 3 ) {' `. R8 y' G( e5 k
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 e- v" i( s( h                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
) ]8 M; a- z/ d8 _                        lowpass_filter[2] = lowpass_filter[1];
) U0 n2 o0 [: y( Y                        lowpass_filter[1] = lowpass_filter[0];
3 o( b( C( R  }# Z9 @" c                        lowpass_filter[0] = output;
% a. \: B$ r2 {                } else if( nFilterType == 4 ) {
: N+ w1 q  J* w& \                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)3 p6 |, i2 k' C7 b$ B1 e0 t
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
: X. z; r' W3 M+ h  t                        lowpass_filter[1] = lowpass_filter[0];. C# p$ ]. z) g8 a* W" ~7 r0 L
                        lowpass_filter[0] = output;5 r6 \3 y5 w- k) P. k
                }
9 ~  r. g- {+ L) `1 N+ E* I0 H" |6 F8 y4 c
#if        0
* [5 b' c5 z8 z! J- }                // DC惉暘偺僇僢僩
/ _0 q" h# O& ^- @( O                {& o: H3 e: }5 o3 S# `( ?# U3 ?
                static double ave = 0.0, max=0.0, min=0.0;, `4 f3 O3 _5 ?7 B$ v+ d
                double delta;1 O3 b) l! m% m$ A+ `( Y
                delta = (max-min)/32768.0;: {/ k* a. g" c
                max -= delta;
. [( \0 ~  Y$ @  I                min += delta;
4 |  \$ p+ s* @8 P! A% a                if( output > max ) max = output;
/ T- O, P$ |; g                if( output < min ) min = output;9 f" Z9 J) d3 L) R. X+ {
                ave -= ave/1024.0;
/ I% B% A% E/ Z$ t( c                ave += (max+min)/2048.0;
9 D( p* |$ O/ w$ d: }9 O0 w$ U                output -= (INT)ave;/ h5 o( G9 o: T. v) C
                }' g, z# t* |4 [8 b
#endif. ?$ k5 @: M* j3 a; K: x( j# W& U
#if        1
2 R! R5 J( R8 h9 b                // DC惉暘偺僇僢僩(HPF TEST)
) Y/ ]4 q6 ]/ F* P                {
: W5 _5 X+ o+ U2 n//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);5 u. v6 y5 d8 ?5 E8 b- R4 v
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
4 a  A( C2 G/ E3 Z8 T( I0 E                double        cutoff = cutofftemp/(double)Config.sound.nRate;* t% }$ E0 d* e# g3 i
                static        double        tmp = 0.0;& l; D! G+ n- f; p
                double        in, out;% p# z& K( I3 |5 H, F

; g& s6 ?. x" h/ C& L* T5 U! n                in = (double)output;
$ M- u7 [- ^5 D                out = (in - tmp);* x) U3 h9 Z5 S3 s9 }
                tmp = tmp + cutoff * out;
# L, G/ A: r3 b! `0 R$ u* y  L- l
2 s# t) p% V' H7 j2 H2 B9 e: b( {3 p                output = (INT)out;1 }' _0 Z! Y2 ^% g+ A
                }
( J; z) q5 |" d5 N#endif
; j# G: `# Y$ z0 O1 m#if        0
) N4 q" B8 r. }" \& b                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)% l& Q: O; b, m
                {) I) j: S7 X) D% P& R6 J+ f
                INT        diff = abs(output-last_data);6 c$ X6 S6 h. v
                if( diff > 0x4000 ) {5 W4 f) C! r8 n- L' J3 n/ D
                        output /= 4;
- v! H: C; `6 w1 H                } else 0 q8 N9 Y: p7 d! f
                if( diff > 0x3000 ) {8 s9 s3 G2 C& `
                        output /= 3;. Y# [6 g) F+ e3 x: o6 q
                } else
( l% e1 i. Y7 Q& S/ a                if( diff > 0x2000 ) {3 E! R- S6 z3 N* X- U8 c
                        output /= 2;' p# c2 |5 k5 V! h8 z+ n# f3 b
                }( b% Q  e" h/ L" ~: p
                last_data = output;
( H8 a6 u6 J- {8 F  V; H5 `3 g. s                }
" P7 ~+ h9 T. F6 |" @( a! _#endif+ C' T3 @+ F" Z  T: T- Q5 Q# ~5 o/ v1 T
                // Limit0 @+ m! N$ J& b0 s3 W. B3 ^7 \
                if( output > 0x7FFF ) {
0 p. A6 }" k7 b+ z/ A" A1 Y                        output = 0x7FFF;9 a% A0 u1 [1 g1 z# T1 x$ Z$ z
                } else if( output < -0x8000 ) {' O4 j8 g0 _; }) R
                        output = -0x8000;
. `  [) s# \/ K6 I; n                }
' K  S. i. x( W' Y5 F& @* U' X
6 C3 |4 a% A# J9 O* {) R( o7 N                if( nBits != 8 ) {$ x+ [; m7 \6 A0 r* h: ]7 Q
                        *(SHORT*)lpBuffer = (SHORT)output;) \1 q9 p' m4 ]5 n
                        lpBuffer += sizeof(SHORT);+ {  X! r, {8 {5 d# R; _
                } else {5 x+ P2 O2 Q: K" h
                        *lpBuffer++ = (output>>8)^0x80;7 K9 c$ }3 O, N7 h
                }
: c- B" T& ^( K/ p, Y) P+ w
& Q: f; u5 ]' K' p8 [% V3 O                if( nCcount < 0x0100 )3 a( R# l, e) E' k3 J% @7 Z- D
                        pSoundBuf[nCcount++] = (SHORT)output;
  Z! p$ [, y& r4 [
" }/ z  v! ~: J. P& ]8 n//                elapsedtime += cycle_rate;7 |  u+ r7 }# a8 p" J$ X% e" L
                elapsed_time += cycle_rate;
" `+ P. ]7 I9 r- N  \% ?" B        }& {( h2 m3 S% Y, j* G1 C# T

; s, P  y& i" e+ f  G$ B#if        1+ G) u8 r/ S* a, v1 s5 r
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ N2 v, ]! [, \& t6 A- e+ P/ g                elapsed_time = nes->cpu->GetTotalCycles();
( [2 F; W# b9 I2 P1 P' o        }. S$ u4 Y7 l2 {) ?
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
! H, a2 s, G+ o, F: b# c# `                elapsed_time = nes->cpu->GetTotalCycles();
" f* k; q( G! R& Z% V' F+ K        }# b" o# Q7 p+ A$ U+ x. Y
#else, v3 s" z* v* L4 H* q+ }
        elapsed_time = nes->cpu->GetTotalCycles();* c" d  w5 S$ h
#endif! v; W/ D" Z! U% I6 L3 [2 n+ |
}
/ }# X! G5 \8 z% e6 b
- Y& i* D1 U9 V4 u// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
& U; D0 y( Q/ N0 S1 M% @$ ~INT        APU::GetChannelFrequency( INT no )
, t7 B1 G* ]& T0 W{
( b8 k1 j% Q6 ^: Q- F6 B+ J        if( !m_bMute[0] )
% D% M; v/ ^# w' z5 ]/ _                return        0;' N& F1 n) h, U$ ^* `

* k5 @, c: U# Q        // Internal
" n! C0 y  M3 c% y* J; _* D        if( no < 5 ) {
1 R2 f  W( ^2 ~, O/ A                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 ]- Y8 Z2 s# Z3 E; _
        }  m/ @& v$ t& s$ d
        // VRC6
( T  C: d- u! [6 N        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {( h9 `) m3 h' r. {+ l  Q  R$ c
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  E/ }5 \2 f/ Z1 ]
        }5 H) h7 _3 \3 N6 J* i* n
        // FDS  O4 u; j3 C" E0 y
        if( (exsound_select & 0x04) && no == 0x300 ) {0 n0 s; W0 Q  M, `8 R) B
                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 |) P  Z, A7 M$ E: Y- h
        }
& v2 M, O  c5 Y  b: H        // MMC5
# E# y6 h4 e0 J% U        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {# m! q5 G! o- z( V
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;: j! p& M& _' J0 E# ~$ v
        }# R7 y* F/ H1 g! W/ E: k0 G) d
        // N106
3 b$ A/ H3 _  C3 u6 W2 Q) G        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 N: m7 q2 T0 b( C/ C
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
% y% s( S3 j+ `5 y' m        }* |/ v2 r3 Z  m. ?2 X) ~
        // FME7& N1 ^  h1 K% e4 A1 h5 r) A; {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
- N: t  U+ o- B9 S( W2 |* B                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
2 g/ P5 E5 H: C, u& [" [" [* M        }: f6 c) F$ X% y% i, T3 F; w
        // VRC7
$ @1 ^+ C: k' {+ u4 V9 ^; c; b- v        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# y2 K$ b& w- ?* j                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;3 c6 v% a) f( ?
        }
( C' Z: |- _9 [3 r% N6 f2 L9 s        return        0;+ ^( J% o1 M0 g6 Z# K
}' {% G+ }! }8 _
. t4 A3 p3 o& l
// State Save/Load
6 S" G# m; v1 w7 o9 Mvoid        APU::SaveState( LPBYTE p )# S- a% V4 y+ z, N3 S
{
3 d# V( R* ~- l5 X/ w#ifdef        _DEBUG; Q1 i' d' Y- M
LPBYTE        pold = p;, `( }& ]6 j" ?. L1 q
#endif- n1 |' H1 n$ N5 X9 A( w" @
5 S: @3 t6 m1 k) |
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞  \7 t* U; ~4 X5 z& m
        QueueFlush();! G3 m( J) k* a8 L9 Z% ^7 C8 h
# H2 ^! D. @/ I( j9 ^0 @
        internal.SaveState( p );( P% f) t/ U% G3 Q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* ]/ f! v" Q7 K1 T+ E) C+ o. F1 V2 E/ h0 k
        // VRC65 @6 H& @& x% Z# D. ~
        if( exsound_select & 0x01 ) {5 I4 C) r  G3 c" l4 d# ]
                vrc6.SaveState( p );
# ]2 }( i2 }- c( [9 J: X+ h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. G- k7 f% h4 [* @2 N) C7 j
        }( a# e& e  h$ x2 F; `2 R' ~
        // VRC7 (not support)
# w: r! V8 @( q6 V        if( exsound_select & 0x02 ) {& y1 O7 h3 D0 o7 Q
                vrc7.SaveState( p );& N3 v4 \4 r, l+ O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 A6 J) L. _6 _4 J. B
        }
; D& x+ r* Y  Z; a        // FDS0 W/ V8 k: ?; J9 V! \
        if( exsound_select & 0x04 ) {
6 r+ k: F; B* D$ u$ O0 o                fds.SaveState( p );
; T2 v  A/ }% P/ J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- H8 m6 O2 E' }  m  i- y. F: F7 c        }
: X+ v9 o$ w( q; ]* b& y        // MMC5
5 D$ Y' m0 {# I' {        if( exsound_select & 0x08 ) {1 L$ k1 w+ k+ Z2 I' I
                mmc5.SaveState( p );1 F" K& o/ n0 j  \
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 Z3 l4 W$ t  b
        }
$ M' t3 G1 z; G8 I+ d        // N106
8 y1 `. d( x& u9 ?# _: F' e7 E        if( exsound_select & 0x10 ) {" d+ b7 S# v1 G# i7 Y: X' ]! B- u
                n106.SaveState( p );
1 i+ u* y7 I5 E% t$ ?2 p) ?/ @                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; u1 Q, j$ Q0 T0 L" Y% v
        }
+ x# b7 ~# s. k/ D5 s- p6 s        // FME7
, E5 a$ c7 |. t+ o! f* `        if( exsound_select & 0x20 ) {
0 p7 }" O7 F9 B" v$ f. x                fme7.SaveState( p );
! I/ F0 K1 c& J4 f" }$ k                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' ^; Y4 d- K& ~9 ^
        }, M/ m& ~  J+ G+ R
% {, r- b% {' D  }  V
#ifdef        _DEBUG
7 ?# h8 @) O' c% q  EDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
. I) W5 v! }# ]( n#endif
0 @9 B9 u) h! B4 Z}% i$ U7 }( x, Q. ^$ Y6 m( s% {

& a% p0 P. y( t! I' \# q7 [void        APU::LoadState( LPBYTE p ): m3 g3 W8 V- q% U% B2 Z' Q+ ~
{; o! b. a, S: B% k7 n
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡' N- n9 e1 r* ?1 R; i
        QueueClear();, j+ _. [! n- C0 }

9 U) [/ x* b8 V/ t% K# e        internal.LoadState( p );
& A4 z) q/ p  c3 |3 g. b  Q1 F        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  w* X" [! D( A* o9 f& Y% i5 F; }. S) F2 Y+ h  B
        // VRC6% s1 x; l+ N& @2 r' }7 G
        if( exsound_select & 0x01 ) {6 r* T1 N" |' \  u- W9 R  g* S; A
                vrc6.LoadState( p );( ^/ `' |+ f+ v6 Z0 ?: s$ R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ A0 J! F7 A9 K- z' ]
        }& h, u" m* Q* ~8 Z# u/ Z1 Q
        // VRC7 (not support)
4 U* w$ F9 x: y- D- `2 s; m        if( exsound_select & 0x02 ) {% Y* D  u9 i7 h2 f& h/ G+ Q  t: B
                vrc7.LoadState( p );8 c* t. Z+ C& h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: y: ~( z9 O2 b2 H% ^        }
( ]) C' G& b+ |: H        // FDS& Y7 e, _# M9 k/ W( j7 q
        if( exsound_select & 0x04 ) {+ n2 ^; {4 i( ~% r$ R5 p- P4 M; j
                fds.LoadState( p );
- M' Y. F+ r% _% f2 N9 X                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 B' ?3 l: a0 f( \* Q6 `4 n; o
        }
$ ]+ i" s5 n/ l2 S+ J+ n* T6 W        // MMC5  i0 C1 \3 r) h, X
        if( exsound_select & 0x08 ) {
; o- W4 }+ H1 Q/ s- @1 X                mmc5.LoadState( p );
. l7 u1 C% h$ |7 d9 l$ S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# w  [0 q, k" U6 w; h$ G- k
        }% C+ e0 r( ]) n: l, n. K
        // N1068 v  S3 r* s' L: d) O
        if( exsound_select & 0x10 ) {
; v5 G0 |/ S7 x6 z& y$ v, v# ?                n106.LoadState( p );
% C- l& b! ~8 n* H1 q% q# u                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* j: v. }7 B3 {0 V
        }: W* Z0 ?$ f! m7 x3 v6 ], y
        // FME7
$ s1 V: @& r, Q* x        if( exsound_select & 0x20 ) {
8 L4 @+ Y+ S( s/ M' r; P                fme7.LoadState( p );* ^! I6 [6 n8 P
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ p0 ?9 X; n# M9 b9 f. X
        }, e. i, _1 t" T. u
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
) e1 a2 c- b. \) U5 J可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
1 `' p  E: g  o感激不尽~~
1 a% A- C6 U0 J& g% q
恩 我對模擬器不是很有研究,
, Z+ A  |: V4 r' D( {- \5 D雖然要了解源碼內容,可能不是很困難,* U3 z+ V  m* ^: l, `6 W
不過還是要花時間,個人目前蠻忙碌的。. R/ T; i2 x9 w5 r
' E2 {+ ~" c0 \9 t' S' ?
給你一個朋友的MSN,你可以跟他討論看看,
' k7 `7 D' @! V8 ]0 R他本身是程式設計師,也對FC模擬器很有興趣。
, U' m  K6 n! Z8 @. E- ]$ V
/ X- D) H* Q- ?& h5 _7 x) N8 ]MSN我就PM到你的信箱了。
* I: B$ f& ?: a& R( [; t% Q
: D; O2 ^  [) ^9 F$ Z希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 * i# p# q4 K% o# t9 p7 Q6 o9 B& e
呵…… 谢过团长大人~~

4 U4 G) a6 O" x' A. t  J/ V' x6 F1 [2 Z8 D
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 4 C2 X- ?5 ^7 x1 Q- `, U" l
团长的朋友都是神,那团长就是神的boss。
! e4 J5 U) e! ?  l- ^
哈 不敢當,我只是個平凡人,
0 _  U3 l) m# v, j7 i要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" R) S) ~' V. [' W, I& dZYH
$ v( ?) Y& x0 R- k, S. r3 e5 {QQ:414734306
# x+ [' U2 v& E/ nMail:zyh-01@126.com
! H( z' a1 j7 T" @# _6 H, o4 F( ?, Z3 R# y4 J3 R
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 $ m4 \* m5 O! w6 u: W* C
再次对团长大人和悠悠哥的无私帮助表示感谢~~
2 N" k% z+ |' {( z) c
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-7 23:51 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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