EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, ~. I; ^2 S$ ~楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 ^- E  z# i( d; A
这里有相应的模拟器源码,就当送给大侠了~~
: r; c3 g4 g1 X/ b7 C  T: v& v# Dhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ! f2 v, l8 K" E- h) w! M
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 D) x5 q* L5 D9 n" @# o# S5 y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% S" u0 g! n( R$ I( F$ Y! ?这里有相应的模拟器源码,就当送给大侠 ...

$ ]9 K4 Y8 ^# M* A聲音部分(Audoi Process Unit = APU):
  g, Q# c& ~: n  _+ N.\NES\APU.cpp) S# U7 B( o' O: j9 @# X
.\NES\APU.h8 H: ]1 g3 f0 |7 o) g6 t
! S' C$ c) q8 W* }; B/ [' Y

$ A" N  J# z: ?* K: S- c  k, Y影像處理部份(Picture Processing Unit = PPU):
! y1 e6 U4 L" F# g" Q0 C# h) _2 q.\NES\PPU.cpp
  j( u& @( |" O6 o.\NES\PPU.h
( |) }( ~* }* w# v  \
$ d7 m' |9 D$ z; n7 b- j3 }如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 K- n: _2 m; v, |" F* d  F
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( ]7 @8 F7 F0 o(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ X: r" Q9 m+ m) x
//////////////////////////////////////////////////////////////////////////' H8 n9 [, l4 S2 i# N
//                                                                      //$ f* R+ E' }. F8 Y4 X
//      NES APU core                                                    //' s- [4 o' M! K1 c7 E# w
//                                                           Norix      //
$ R( M4 }8 t! c, l8 w//                                               written     2002/06/27 //
% `+ b3 t0 P4 a8 t//                                               last modify ----/--/-- //5 o) N  _  r0 V! U( K
/////////////////////////////////////////////////////////////////////////// _3 f5 x4 a! ]! i5 R. L) L0 [8 N
#include "DebugOut.h"
7 K" B+ b$ B# [6 }5 @/ w4 A. \#include "App.h"
6 p& s8 E7 c- T#include "Config.h"* ?& ]* }' H% @+ y

: P- X9 K+ N& H* X  A#include "nes.h"
8 e, q) `% E7 c8 [#include "mmu.h"
8 x) n0 q; ~* j. S- |+ x8 M#include "cpu.h"
( Y( q& h# E6 l( G#include "ppu.h"
  q4 I7 G, s& P2 @0 D8 e% |#include "rom.h"
- n! D1 X1 I6 I( g#include "apu.h"
$ ~7 j: Z9 {1 R8 p) M$ g% B% G
- ]. j4 \" c2 b- a1 T8 u7 `+ F// Volume adjust
5 \" U) p8 ?1 w0 f5 m$ y5 o// Internal sounds* o/ U( z( q6 c( }% F
#define        RECTANGLE_VOL        (0x0F0)
9 [4 `2 @, U4 U$ o3 p- I5 O#define        TRIANGLE_VOL        (0x130)
# A9 [" R2 \- h- z5 y) U: B#define        NOISE_VOL        (0x0C0)
3 \3 S; f' A  B0 R& F% @* N#define        DPCM_VOL        (0x0F0)
# A  }% V% o& W$ [3 q// Extra sounds
, E9 N  m$ ]  r/ v) R#define        VRC6_VOL        (0x0F0)6 T6 Q# {2 `9 R* x$ ^6 @
#define        VRC7_VOL        (0x130)5 Y9 o3 ^# X! Z6 M4 t
#define        FDS_VOL                (0x0F0)7 r: A3 M" n* \7 L- u/ `
#define        MMC5_VOL        (0x0F0)3 k5 b6 x# d( X0 }/ Z9 u
#define        N106_VOL        (0x088)
2 U5 [# [7 c$ Q( L( I$ W) L' B#define        FME7_VOL        (0x130)# B' o  J8 P$ K* x8 l8 R* S$ K0 k

+ t3 B2 x  u& {* l/ wAPU::APU( NES* parent )
* a3 d9 r! g. x{
$ Q% P3 H5 V: J% Y3 H4 V        exsound_select = 0;6 \* I4 c) N1 j8 z& n; f7 Q& o
: P* x+ u( Q! I/ V4 Z6 R
        nes = parent;
# w6 R* r" I4 x5 _6 D        internal.SetParent( parent );
9 i! p  n+ ~: U* D4 _9 d& B! e8 F9 G9 G7 p. W! w# _
        last_data = last_diff = 0;
- o% l: Z: L, I, M$ A) c' d, i' G4 B6 p+ S7 T8 ~
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
1 P7 K) [+ \1 }- I8 R& k
& O$ ]# M* v( g9 u, g+ F7 I        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
* ~, L& t, C* N+ E9 u# ~) X$ i0 \        ZEROMEMORY( &queue, sizeof(queue) );9 H( f2 i; {* c9 ]+ n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 @! Y, c0 ~1 s7 W/ M: z4 g; z
/ X! h3 V; f. U/ y/ {. ?# t+ S
        for( INT i = 0; i < 16; i++ ) {
* V" j  W6 H  u# H) Q+ t# L                m_bMute = TRUE;
, A8 H2 N$ n* f        }! X3 r: S+ u- G  ^
}1 Z+ `5 }/ ~2 a$ s: [5 D

' `. [. }( c! h1 f" D1 wAPU::~APU()/ A( z) N6 y2 w
{
! O; [; ]! l% T5 f0 o1 R$ Y}
5 [% O2 h* O8 b2 e+ H8 D% q0 b) O/ n" V& _% C/ Y6 g
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )% F: ?: c9 k' P
{
" g# u* _) ]) R5 t! r        queue.data[queue.wrptr].time = writetime;9 _+ b8 g; a" |! s+ Z3 t" I
        queue.data[queue.wrptr].addr = addr;
5 m* K0 W8 q; V- O4 I        queue.data[queue.wrptr].data = data;
* c7 z5 y. D6 m; A8 b3 W' X9 K" Z8 }8 D        queue.wrptr++;
( `6 Q& J! w9 |9 _' U6 `7 F+ J2 H( h        queue.wrptr&=QUEUE_LENGTH-1;6 r( L& X) ~' W; Q4 K8 E, b. o. ^
        if( queue.wrptr == queue.rdptr ) {
7 g# ^) c: A  U! L/ g* N+ o                DEBUGOUT( "queue overflow.\n" );
4 x4 S1 I  R  t* `! E3 Z# |8 |        }" g/ C: D3 M) H  S5 N! x+ a; e/ f$ |& [4 m
}: g- M0 A6 Q: _' P5 F

5 _2 L/ }# S: q3 K; u& iBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
/ d. i( _' u  Y{2 ?" x* h8 c' b" p( D' G: m+ O$ T
        if( queue.wrptr == queue.rdptr ) {
% o( W9 t# e- c( c) d0 |! }! S  i                return        FALSE;
* r' \5 u, P" n+ l: K) }        }
6 M6 G6 J( o  E6 w1 H        if( queue.data[queue.rdptr].time <= writetime ) {
- y- P% e: q9 Z" R! v6 B) r# ~                ret = queue.data[queue.rdptr];0 e1 e* m" p. T' A" u2 p
                queue.rdptr++;4 ~' Z- M: O! D9 \# E6 [
                queue.rdptr&=QUEUE_LENGTH-1;* |* O( c7 W7 P0 c3 U7 `9 {
                return        TRUE;
# \: e) o7 A2 ^! t  G$ F  i        }" J- D% z0 \; S# n3 i% ?9 P
        return        FALSE;
* M0 q6 p" _3 f# s- p}9 q1 K# B5 K9 [: ]) F; F' r
- s, k, f6 |: S# f; x. S7 T2 B; G
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )) K: r# v- _8 z
{
3 M% L3 r! C; U: ^2 [        exqueue.data[exqueue.wrptr].time = writetime;
: V3 l1 J0 L0 W2 ?* ?        exqueue.data[exqueue.wrptr].addr = addr;7 C7 `# @% u' z. @3 Z8 l1 D0 j
        exqueue.data[exqueue.wrptr].data = data;" o# T/ c2 A1 i' Z! v: H6 u7 Q1 v
        exqueue.wrptr++;. I' O+ N* {4 m3 A- i) V; P& {
        exqueue.wrptr&=QUEUE_LENGTH-1;
9 \( |" P; Y  F; \        if( exqueue.wrptr == exqueue.rdptr ) {
8 v9 j; ~) b3 n: d( P0 b  W. s                DEBUGOUT( "exqueue overflow.\n" );  ?. F7 A* j" L( e0 p- U
        }
1 C( V" e- U: ]8 ^}( ~9 C- D" D( H8 N! m

- t, R: ?) L0 m2 mBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 x& ^4 S+ S- O7 n3 j{) ], R7 F; d) u: m. u8 x
        if( exqueue.wrptr == exqueue.rdptr ) {
% a) J) s8 Z8 B) S0 ^% {' v                return        FALSE;" n9 w2 d8 e) I, ]6 ?( o0 f, t5 a
        }
: e# C7 ]9 m1 K1 `6 F3 }. S3 m        if( exqueue.data[exqueue.rdptr].time <= writetime ) {7 @, ?+ X* _3 |; j1 ^/ g% i
                ret = exqueue.data[exqueue.rdptr];
4 }( O: q' e1 I                exqueue.rdptr++;, h3 a, h. _' r; p6 A) d" e
                exqueue.rdptr&=QUEUE_LENGTH-1;
2 B, `$ o0 x: t4 |5 o/ |                return        TRUE;1 m' d+ M! `; i
        }
( k8 M0 f# f$ c9 J4 ]; ~  o        return        FALSE;/ o& |1 y5 c/ w& |7 `
}. ?& ~2 ~& f2 X8 Q; H; ~0 g

) b! `6 g" G8 x) D; \void        APU::QueueClear()2 n( h7 N! }% J# X2 L" y
{+ G: K- F/ |) v# E5 x; \. C
        ZEROMEMORY( &queue, sizeof(queue) );( W+ Y0 G4 R0 s' C5 t6 k+ Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% v! `% \1 U8 `* f2 x, e# ]) O}2 v& X6 I5 G. [- {) P: j
' L3 ?9 K( [/ {/ S6 B% G
void        APU::QueueFlush()' D  @2 |8 h% C
{
2 c0 Y5 p- w: P% N# T5 s& I& I6 Z  a        while( queue.wrptr != queue.rdptr ) {
, o7 ^+ V4 \: L( b; W" B, u. P                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );- w2 i! \: x* T3 x
                queue.rdptr++;
' Q, q  n, U3 V: {8 {* |9 B                queue.rdptr&=QUEUE_LENGTH-1;( c9 q: O6 V' F% u  M# K
        }+ _9 P5 ^, }; y4 h0 V6 {# P

1 k  @0 k7 U  _5 h' Z, w1 K        while( exqueue.wrptr != exqueue.rdptr ) {3 L4 \8 ]( E: A! U- V: O5 `9 t  J
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );9 g5 z& n) z2 Z6 F
                exqueue.rdptr++;
  B. _! w4 K; D3 @% Z0 Y& U9 {                exqueue.rdptr&=QUEUE_LENGTH-1;) A, H/ h! T! C2 _* B2 @
        }, M5 Z/ Y% C7 m# ^+ g/ A0 h
}% P  {8 S$ s5 O& R/ ^
; L' Q3 D' s( H2 e
void        APU::SoundSetup()
7 K5 X5 T$ Y3 O3 ^{% A" n5 L+ h$ v8 W/ J( |' J
        FLOAT        fClock = nes->nescfg->CpuClock;& ~/ F! T: \/ p4 a- [) d
        INT        nRate = (INT)Config.sound.nRate;% M( a8 b% |" ]( E
        internal.Setup( fClock, nRate );
5 T5 M; ?( {- H6 g* Z0 n7 P9 r        vrc6.Setup( fClock, nRate );
0 Y/ b% ]: V5 O        vrc7.Setup( fClock, nRate );
% T6 d  ?9 R, r4 {5 g& L        mmc5.Setup( fClock, nRate );
- t4 `* z# g- H! r+ r: L; P# Q        fds.Setup ( fClock, nRate );
5 W' w- G; @! ~9 L        n106.Setup( fClock, nRate );
% l5 u2 {- K5 S: B0 e* ^        fme7.Setup( fClock, nRate );
0 W3 t, i+ Q8 V7 C! j2 @8 ?}
6 K; ^2 e* S; D% w
/ M( `% f9 f& _, _& V( ]void        APU::Reset()5 \9 E# V  I  H5 B9 i; j, D4 w
{
+ }) {. F" Y" U' K/ Y4 X# P+ {( m        ZEROMEMORY( &queue, sizeof(queue) );7 k0 x$ o* R0 g- R
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- B7 H# o+ T0 z* \' p8 P3 }0 e0 }
        elapsed_time = 0;
: H2 w5 R7 P2 h; U9 [3 f, H! U7 Y7 V9 W" K) a; d
        FLOAT        fClock = nes->nescfg->CpuClock;
- Y3 R  i  D4 R7 j        INT        nRate = (INT)Config.sound.nRate;" Q  n& D+ K3 ?( [2 f
        internal.Reset( fClock, nRate );2 R# K" e/ P( [+ g5 B1 v
        vrc6.Reset( fClock, nRate );
2 b3 D( g7 \6 t2 t5 e        vrc7.Reset( fClock, nRate );. d9 E% W1 r! c0 W3 t3 e# U- i* c
        mmc5.Reset( fClock, nRate );3 m2 \: k# X  Z" P. h2 r8 M
        fds.Reset ( fClock, nRate );# D, R$ J; K- p% ]9 T+ {
        n106.Reset( fClock, nRate );- C( d& s6 h& p$ f2 e8 e
        fme7.Reset( fClock, nRate );" K4 ~; M, u$ P# v/ x
  |/ D1 ~. `# }9 p0 q
        SoundSetup();
/ S* g* i$ {( z}+ s1 K- B+ @* u( s2 ~
# L  p8 l: S- b5 m9 @
void        APU::SelectExSound( BYTE data )3 O* u, x- _* U2 o
{* \6 b* |; {( o. x. H# ?
        exsound_select = data;2 z' l; r. O, y* [/ C4 g
}
9 T- o( G0 C3 d; E, G! F+ C* K+ P4 J" r, ?
BYTE        APU::Read( WORD addr )
" L+ t8 `( }+ E/ }# \2 V{: f6 @! Q0 p: \5 U0 @/ U3 Y
        return        internal.SyncRead( addr );
6 w: Y6 [. u# X7 I; @}# P' d- U, c/ Y8 i

2 F- D& {& H5 `6 r0 d3 Z2 xvoid        APU::Write( WORD addr, BYTE data )
6 D7 d; G: l4 e7 H{- \0 T- D( Z* c) F: d) P/ J
        // $4018偼VirtuaNES屌桳億乕僩5 @; P9 }0 K+ E$ E5 c
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 b% E. }6 y9 w  j# {                internal.SyncWrite( addr, data );" [9 o  _4 p7 ~0 ^0 O# t
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );+ A" _, r/ E8 j
        }
9 k0 R# i# w$ m" }5 `}
" V2 q4 c/ [- _0 [9 k% h: i0 M) Y3 P1 a
BYTE        APU::ExRead( WORD addr ): `9 J3 k/ j4 p" y) l% P
{& q- ?' u0 U' A1 Z
BYTE        data = 0;
4 l" Y  Q5 m. \) D; }' y
% q- B, F( l: Z3 W        if( exsound_select & 0x10 ) {  b0 r: k" u5 u
                if( addr == 0x4800 ) {
6 Z% U6 i: a7 t. D% C# p                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, P7 N) b$ }- e6 l* U8 l, B2 t) R                }5 J3 ^  k8 c7 q6 v+ ]: B
        }/ m" F8 Z: J8 a  }
        if( exsound_select & 0x04 ) {7 G4 H) t( E3 f% N; ?6 n: a
                if( addr >= 0x4040 && addr < 0x4100 ) {1 ~, c( c- |" ^3 C
                        data = fds.SyncRead( addr );
0 p" o0 |# P1 b                }7 R( Y2 [' M3 D# c* m
        }0 L8 L7 J; I' d, t+ B7 x5 \
        if( exsound_select & 0x08 ) {
1 P0 m2 @; f& z) o2 P8 j) j                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 S& C4 K. H* S5 ]7 p! l# y  ~) h                        data = mmc5.SyncRead( addr );2 @/ f+ y1 u  r5 K& u
                }
" Z$ b( V4 e) o1 H        }1 v5 f! e8 a' C" R
* {- X9 ]  c" W6 i
        return        data;
9 l& J4 I1 n2 R# i1 k}
+ d# f) s8 ~: Q, ]. S( c
  I$ q/ a7 V5 D' |' y8 n  _4 avoid        APU::ExWrite( WORD addr, BYTE data )
  d9 E- W% z# d: q- Q0 m8 C: l{2 y7 z! I& \& y0 C8 L7 o* T* L# ]7 t
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );& y9 p- H0 ^3 f0 g( B, u, m2 S$ E
' Y# @" x) Y1 {: h
        if( exsound_select & 0x04 ) {
5 ?% P+ M: J2 C4 f- F8 I! t, [4 n# ~2 C                if( addr >= 0x4040 && addr < 0x4100 ) {
% a/ X7 r) f; K) j                        fds.SyncWrite( addr, data );
8 l- h. e# T* |# K+ A0 f' W$ G                }
+ G4 t5 E6 `8 D- m  a        }  R( m* V2 [4 j) L, d; l
8 W' [' Z& |" L5 r2 X2 `6 `
        if( exsound_select & 0x08 ) {+ E4 S$ m+ t6 d' Z1 b$ S# T
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ X) @3 v$ T6 o( B5 n                        mmc5.SyncWrite( addr, data );7 o6 H9 e/ J! M/ r2 v  i3 J& u
                }6 h. h# a# p7 s8 S9 z9 v7 c; X
        }
2 j2 f# e2 l: s6 W" ]}) D5 P( f3 l: d6 `/ c* _

. W; Q6 m/ z! ?: Q5 x1 gvoid        APU::Sync()
# N/ j7 g# M8 K& e{
$ L7 |( a' Q3 z  G8 @' s2 M}
! u$ l2 H: O% H. V2 w- c) i5 ~, O1 z# v! j! A. ~  u  z- k
void        APU::SyncDPCM( INT cycles )
1 e' Z8 \' X; q+ {' `! C{
7 n9 I1 v& t6 r        internal.Sync( cycles );* j* k7 A3 K, Q; A/ v/ E

' ~/ ~) w9 m# D, k% J' J* E( I        if( exsound_select & 0x04 ) {' b# s1 M# v# o+ S( V( U2 U
                fds.Sync( cycles );' _! T1 o% ]8 n, X" ^
        }
+ [7 e! E  d7 c: l* Y        if( exsound_select & 0x08 ) {
9 z# t0 E& s: i7 g" Q' c                mmc5.Sync( cycles );; p0 K5 t2 D' c" E- i/ J/ n
        }. J  y% S' E/ {5 s
}8 Y  R' u7 K7 J' S4 H; a! D
2 A# A3 \8 r2 T- Z6 o
void        APU::WriteProcess( WORD addr, BYTE data )# D& E9 [- n; J9 K
{
7 ^1 d& m( ^% g6 P) Y        // $4018偼VirtuaNES屌桳億乕僩
5 Z2 C/ C' V' w* `: q8 T1 U4 L        if( addr >= 0x4000 && addr <= 0x401F ) {
* p$ C4 R  [: W7 ^) t. @3 t                internal.Write( addr, data );+ u; @6 S# j9 n' F. N7 I0 ~! }
        }( s5 b: f1 m7 K% {
}
, ], S. ]5 j9 O" ~7 }$ u3 [7 s0 y8 s" ?: E$ N
void        APU::WriteExProcess( WORD addr, BYTE data )% }; H! k- J5 w
{4 D1 m4 n  d& V) j8 z
        if( exsound_select & 0x01 ) {
% J1 p! o* X  i; g' [; k+ r                vrc6.Write( addr, data );; h6 O0 z9 [3 p) w6 k! _$ ]
        }9 [5 j+ ]; V0 |; Z+ j
        if( exsound_select & 0x02 ) {
6 ]* p; O: a0 @5 I3 a" L) l4 e                vrc7.Write( addr, data );
' w; h5 z! T9 W( _) S! G3 L        }1 i( K4 f* Q5 J1 C2 O8 O
        if( exsound_select & 0x04 ) {
4 `/ m8 t1 c. ^6 j  L                fds.Write( addr, data );7 }+ B  J7 ^2 |+ p1 {
        }7 }) B7 W8 O1 r6 r0 p2 }! ]
        if( exsound_select & 0x08 ) {
5 g: W2 G3 m  l0 \6 a6 v- X4 _                mmc5.Write( addr, data );
9 `  G5 D. Y" o        }# j# m) @+ Z4 f
        if( exsound_select & 0x10 ) {
0 Z2 Q6 p$ q4 B+ L                if( addr == 0x0000 ) {" K8 X5 g' n1 l3 u- P
                        BYTE        dummy = n106.Read( addr );/ U  @, G2 d9 J! J
                } else {/ ^7 D" C. k+ U$ S$ T
                        n106.Write( addr, data );
3 q, q2 J. B: k* Z: E; I% C& x                }  n- c' F$ P5 [$ P4 }: b
        }& t: r* v: p; O& x  ?6 t
        if( exsound_select & 0x20 ) {! w  G4 s. \* P3 T, p# Q. {
                fme7.Write( addr, data );+ f& l- f- |; |3 v$ r+ [+ Y' P
        }/ O8 o5 Z: |6 l% x+ E
}8 t8 `: t9 T8 d4 ]. c

, J6 W) y. G- j- q% nvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), G; F6 |; _8 |6 G% E1 z/ Z. Z
{
& A5 @- J6 \2 Y, _INT        nBits = Config.sound.nBits;/ \8 P: y9 Y8 x# O1 [
DWORD        dwLength = dwSize / (nBits/8);
$ {: H& o+ W/ E6 }INT        output;
! {) b' M3 |  ~- M, ^; L+ v0 fQUEUEDATA q;
% d) [. h! b4 }! W% yDWORD        writetime;1 l& r9 H7 n% j$ d

5 J$ o, c" X6 G: m! g. gLPSHORT        pSoundBuf = m_SoundBuffer;6 ^( o4 k: l3 v
INT        nCcount = 0;1 ?+ O5 ^) X) ^6 x. q( [

& M: ?) o0 u; U! O. Z% N5 s, ?$ LINT        nFilterType = Config.sound.nFilterType;
' \5 Q+ c, [- f! R( {
* C3 a# R8 c& m; c  I) y+ m2 m        if( !Config.sound.bEnable ) {3 h7 p4 E2 n/ r3 y& F/ t- G4 B
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );" A, i0 `$ q- m/ g& o4 c/ V
                return;
. l2 C, P; L6 V6 f4 P) Q        }
, l: ^- [8 j6 L; K; k5 a- L' ^# K, e! i
        // Volume setup# y- E! z6 S. |; e
        //  0:Master% g. b8 u" A0 b! f) Y1 I- e
        //  1:Rectangle 1
8 ]# t! d9 J/ t! S$ k5 m' s        //  2:Rectangle 2
; q- P/ S# a. Y4 G- L        //  3:Triangle
9 }" c. z% \; S; k2 E        //  4:Noise- m1 W9 b: o" ?9 o
        //  5:DPCM
* m4 C' o9 N/ f9 u        //  6:VRC6
8 E; v9 Q  D' a& k        //  7:VRC7
7 j) h  ?4 y% D        //  8:FDS
& L& ^9 V3 _; x; {        //  9:MMC5/ N. z: W2 m, l, Z, ?: `
        // 10:N106+ \: f' a4 {* F' R0 O7 G
        // 11:FME7
% R( `! H6 S% f* I# F0 ^, S        INT        vol[24];  `' \0 S2 K3 O& d2 l5 d& ~* d
        BOOL*        bMute = m_bMute;
# R2 u& V+ l7 F7 b        SHORT*        nVolume = Config.sound.nVolume;9 ?+ Z* q3 T1 T) |2 o& ^9 Q

7 j, {4 w! {9 s  l        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
% N" k) C) o9 P7 A9 _1 S% z; S4 E( m1 n; U
        // Internal
6 v- c' S2 s8 R        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
% o" i2 o8 J1 E0 p0 f        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;7 _* h' |) w+ ^0 \1 U( s
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
  C) Q; C, a/ y3 m+ Q: M        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
3 `0 \  v/ s! r+ @. A% R, e; t8 A; J        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
7 W$ @# H  z. [, E! r3 S/ o: k8 a  `- S! H1 U
        // VRC6
1 F5 U0 s" j9 I( r3 W        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( Y; Q, K3 C# y- j
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& p3 l( m5 ]9 x% A% F' R6 u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 [  f7 ], t! I7 X/ P  a, v

1 T2 W* |  q( w1 p+ o        // VRC7  U# [% g, Y, f
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
3 F3 E* O( k% a1 Y5 E$ X% u" s/ x) F* J3 ^% j$ ?
        // FDS  e' e5 R" b: k0 F1 w4 _/ Y- o: E
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
$ n: ~! v1 M* f1 L7 d: w
: U( O& ^- t! ?6 A7 D0 E        // MMC5
" i& P6 \# e4 z  y% L1 L        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
: N5 l9 M: b- y7 Q$ V- A        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# s8 }! s! u" N
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  l  A& |3 Z: j
6 s' r; I& W' D1 c2 H9 n        // N106
" }0 n" G, r/ X. l+ L        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ L! h( k5 G2 J& V# }8 O. E
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; q4 \& H# B9 i& L3 J
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* }5 g" e' C9 n, }& O# }9 M3 Q+ E3 d        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( t7 G' k9 N; C
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  S) `4 W2 t6 T& Q! [
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ l5 A: b, i- @        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 ~) V: A9 Z( C8 B& \4 p8 v        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 T, L6 S4 j  \3 o8 ?& Z
4 @- ?0 {  o7 w/ h0 _
        // FME7
2 q) d: t6 o* e# t- X. F        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ t/ R* p. w2 `, T! E! o5 h* C* `        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: r# i' T" p$ J2 r9 Q5 u* h# V
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 b, }% j1 R" i3 o. u) Q! x9 p+ |
* c, s1 J- k: e: W$ r//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
" b, i2 n- ~4 T8 h5 b        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
$ n5 X' C/ P; @* y5 _) t7 w- O1 o
5 e1 i$ W- @* F' c- D        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟$ T5 l% _  d& u! \
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {( G; y- `, I1 m$ E' f8 f, g6 n& W
                QueueFlush();
+ ^% _1 i6 w& X. O        }  b' q& p" {  H

1 s/ g$ z% S. c& R" k6 Y2 [- S        while( dwLength-- ) {
6 W' d2 q  |. }/ o+ q0 v; F                writetime = (DWORD)elapsed_time;" d' T) l/ {5 X! y

5 T! c1 o' C1 n/ P7 H7 R                while( GetQueue( writetime, q ) ) {  c, `5 }# D4 P
                        WriteProcess( q.addr, q.data );
; q7 h7 Z% t! R5 i) B                }1 M  u- K$ U9 k9 W# L5 B( E

! E! Y9 b, ?3 ?/ p) _                while( GetExQueue( writetime, q ) ) {6 N  M; O8 G9 _. A7 M6 X
                        WriteExProcess( q.addr, q.data );6 U" {( D7 C% d1 {) p+ F
                }
; p# B- U. O: e& G; R8 u8 E1 z# g% X' [. O* h# j8 N) K  m1 ~
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ \, Q0 b& M8 k6 v4 ~) m5 b& v6 D
                output = 0;
- M) ]" q5 q6 b; E" r7 _! g                output += internal.Process( 0 )*vol[0];
  E; ~1 M/ D- F6 O                output += internal.Process( 1 )*vol[1];
; u3 h0 u7 J1 }. R1 n                output += internal.Process( 2 )*vol[2];
9 {* k! r+ q& F: h5 N2 @                output += internal.Process( 3 )*vol[3];' s" q. p5 g& V. M. C- @
                output += internal.Process( 4 )*vol[4];
% Z9 r3 ~4 h! }/ P2 |
5 f* [- }! J' w) R  k- e                if( exsound_select & 0x01 ) {
4 r+ `2 X: Q, L( w6 @                        output += vrc6.Process( 0 )*vol[5];
/ A- u# }  P: }4 b; x9 t! v: W. u                        output += vrc6.Process( 1 )*vol[6];
. N4 B4 ]/ x. k8 q* ?" H) x8 h                        output += vrc6.Process( 2 )*vol[7];
$ x% ~* A  ]9 B; V1 p8 L% W( C                }. a5 g  H9 p* {5 x' }: K" A9 j  h; z
                if( exsound_select & 0x02 ) {
0 L9 N# [* U1 d; v! F; ?4 X                        output += vrc7.Process( 0 )*vol[8];2 Z% b5 A1 q. M5 ?$ Y! `5 x
                }  F# U9 m6 X; w6 P2 m& P' k
                if( exsound_select & 0x04 ) {
/ ]  Q1 |$ K! p6 P4 u' M' t" t                        output += fds.Process( 0 )*vol[9];& d, C2 v( k- [9 x
                }
+ P3 g# }) Z* N5 {2 R$ S                if( exsound_select & 0x08 ) {
' n9 k! s( _) M4 M2 V6 ~# s  u1 r                        output += mmc5.Process( 0 )*vol[10];' H% N" o6 j& Y2 l: r
                        output += mmc5.Process( 1 )*vol[11];
( E6 C4 Y9 }+ Y4 Q& I7 S, a% A" N                        output += mmc5.Process( 2 )*vol[12];# y/ c" ]  d$ A; t
                }
3 t- k# P  j' K- x# U" q! H1 o: s                if( exsound_select & 0x10 ) {6 b1 m: Q9 z8 C; G
                        output += n106.Process( 0 )*vol[13];
, b+ F; v  g5 t6 m( L" W6 Q                        output += n106.Process( 1 )*vol[14];
% u9 F( ]( q  w" n2 f                        output += n106.Process( 2 )*vol[15];# y" {3 @0 H3 y$ e/ w
                        output += n106.Process( 3 )*vol[16];
, ^( f: I, Z! B) p: ]* Y3 m                        output += n106.Process( 4 )*vol[17];
7 W* m$ O! s+ B                        output += n106.Process( 5 )*vol[18];
& M: r; f% Z3 o" n                        output += n106.Process( 6 )*vol[19];
6 a: [" |" L, S: q1 H. `, b# e                        output += n106.Process( 7 )*vol[20];1 [" a# S" U  |: e7 M
                }" Y, u! n( m9 P
                if( exsound_select & 0x20 ) {
$ N0 |, x. E: N: W" X3 v6 V                        fme7.Process( 3 );        // Envelope & Noise2 P1 f$ c+ R2 z9 @
                        output += fme7.Process( 0 )*vol[21];# Y* ~  }$ a- [- x5 @
                        output += fme7.Process( 1 )*vol[22];
1 j' ~+ L. p1 i2 B5 a/ j7 u                        output += fme7.Process( 2 )*vol[23];- j: ~& W$ ]' D  e% W
                }
( p1 ~0 D3 w+ C  d! O
1 Y$ A6 x" v9 w                output >>= 8;
# ~: U+ L7 n# n8 o& c
. n# o3 U6 ~6 d4 Q1 x" i                if( nFilterType == 1 ) {0 o- d3 d. Y. X, t7 ]
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), G6 c+ x2 Q+ |0 e. j
                        output = (lowpass_filter[0]+output)/2;" K4 F/ n, X) z9 a" X& Y
                        lowpass_filter[0] = output;# U: a3 p/ e. n$ G/ C$ o1 K! u
                } else if( nFilterType == 2 ) {7 e( @% ?; M) p  \5 x
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
3 P/ u; J7 M. w0 t# F" y9 m' i# G                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;/ s9 p' w- U  z1 Y: e+ F* H. W
                        lowpass_filter[1] = lowpass_filter[0];
- W1 S8 O% R% c6 N8 c9 `, M2 h                        lowpass_filter[0] = output;
3 w! p; Q, b7 g; N' n# ~, N                } else if( nFilterType == 3 ) {* L5 ?* i# J4 H. r; }5 U
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)& T* a( K( v3 W% k
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 o/ o5 ]0 ~! h8 J' c/ e6 Q
                        lowpass_filter[2] = lowpass_filter[1];& I" `8 f+ |6 x
                        lowpass_filter[1] = lowpass_filter[0];
  t$ Q. M/ k; n- {; _* _                        lowpass_filter[0] = output;
! l8 v" O  B- _% h9 y                } else if( nFilterType == 4 ) {
; N, ^; s  Z) {; b                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), l7 L" e8 u* l- _. x9 U# H
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
7 z3 h7 a$ X: l* V: H, @! Z                        lowpass_filter[1] = lowpass_filter[0];0 Z, {: U# j; h# L# @! t
                        lowpass_filter[0] = output;* ^# h8 C: i. e
                }
1 j8 L7 u) q1 W, ^2 M2 k# J4 C, w5 j
#if        0+ m- U+ ]# F; {! m( G; ?& C
                // DC惉暘偺僇僢僩' Y8 H/ ?$ I. t+ i/ X4 K
                {
& A$ v9 |6 r) r7 s  A! ?1 V0 \' ?                static double ave = 0.0, max=0.0, min=0.0;2 N! f$ z7 w* R) ]& R
                double delta;. j) [2 D+ c, n5 ^
                delta = (max-min)/32768.0;0 s: b5 }. F% ^8 [# o1 h
                max -= delta;
4 l! Z0 T9 D1 _/ g5 p# K7 p+ B                min += delta;5 X( [6 C8 K& f( H4 `
                if( output > max ) max = output;
) Y$ v' G: y" Z- Q$ U1 w                if( output < min ) min = output;
& S4 N6 k+ e- X                ave -= ave/1024.0;1 f& `* k( t# `. X
                ave += (max+min)/2048.0;6 e9 ?( w2 f: N: g6 e
                output -= (INT)ave;
/ _2 ~" W4 f) n, b5 b) T4 l3 j                }
/ R: F/ v. a. p# q8 K! L- P0 j#endif+ a+ x4 Z( `6 r' |' f
#if        1  w) M1 M& Y' t, ]& x6 W
                // DC惉暘偺僇僢僩(HPF TEST)
0 s& \) j3 h) F% q+ j7 _: X$ @# l                {
$ Q9 x1 m% v, N0 f) ?2 D//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ R7 \6 x" m. h. y. {+ V8 ^                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( c# [! v, G$ f( A6 i                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 z2 G: {: i! K$ f) p: h/ Y' H
                static        double        tmp = 0.0;
9 h' w$ I2 o1 V% E, U# \                double        in, out;4 e3 d7 D8 ]3 ]% p! b
: J/ O; ]. ?+ b0 f4 k. Y- ]9 {% \
                in = (double)output;: ~6 D; M5 Z4 ^
                out = (in - tmp);
1 g! V( \! z# u                tmp = tmp + cutoff * out;' W/ y8 C3 H' H8 E

9 [  ?* V$ P/ O9 S2 O( c                output = (INT)out;
3 W" K; ^3 Y* N5 ~4 i                }. V# W" f+ g5 ?! \  ]
#endif
" x8 r* G  F; B( l! I) @9 v, {4 ?#if        03 N$ T, g* D1 G8 y
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ m6 A$ ]( b: ?# a9 C                {% u& c- |0 P4 P5 W# K
                INT        diff = abs(output-last_data);; j# \' X- h) u3 \+ Z+ p9 w+ y1 J
                if( diff > 0x4000 ) {+ s5 J7 j8 N1 E1 ^: g* q2 _
                        output /= 4;8 m- j% B; a5 O1 a& b: ]; H  u4 Y
                } else
) `) b$ a2 `/ [/ R                if( diff > 0x3000 ) {
0 }$ k! n0 U* h5 t8 `& h                        output /= 3;
$ l% w0 S# Y* [: _3 q" q$ n% {                } else
% ~$ `. N- q+ }+ V+ X2 u2 a                if( diff > 0x2000 ) {, M% _- S: h7 g9 _: ^- o5 j
                        output /= 2;* Q* b: O6 r9 t1 O# o9 ~% S0 ^
                }' M9 p9 |0 \4 C2 Q$ w9 @, b
                last_data = output;! p0 o; L1 R8 c& a$ R
                }+ J; z! R+ W+ Q; m! B. G3 A# I& o
#endif
# q$ z5 ~7 O! A" T+ \6 v/ Y                // Limit4 j2 B: M* }7 m  g, T' D( ?
                if( output > 0x7FFF ) {
  z! t+ K% }9 y1 Y/ ^6 {2 ?                        output = 0x7FFF;
& z+ L: Z) G- k  N0 y                } else if( output < -0x8000 ) {
+ k9 g) p+ x" E! `9 B7 D                        output = -0x8000;
1 k3 n: e1 z8 A# L                }
4 w5 i; a8 d# y) t: z) @! `+ Z, t3 Z( J7 _
                if( nBits != 8 ) {7 o6 I" k+ M$ @9 X: f
                        *(SHORT*)lpBuffer = (SHORT)output;' b9 D. ?  Z6 S5 U6 F: A% X+ y
                        lpBuffer += sizeof(SHORT);
) b+ U# T) l3 u6 i+ h& R7 j                } else {) {1 z# b, h* M  {
                        *lpBuffer++ = (output>>8)^0x80;4 @9 g1 X; ~" @8 }
                }. P9 ?) ^& `  t$ k4 l8 h

+ N" g' P# M  ^/ A                if( nCcount < 0x0100 )9 Z( x+ p6 J9 j1 \. a: Y, M
                        pSoundBuf[nCcount++] = (SHORT)output;2 t8 e0 Q4 I1 I6 V" [0 `6 s
9 M+ R" @. H& W4 e6 v4 c& y
//                elapsedtime += cycle_rate;& k0 p" K" K; B8 J+ w! ?
                elapsed_time += cycle_rate;0 i! }% R- b5 Z1 m1 z( K
        }
* y5 I9 o" p9 ]/ r
; |6 ^& o4 e! V! ^6 H3 u+ H#if        1- d& i( R5 Q/ _8 ~6 `6 X: X% f
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {5 c% p' C2 Z2 e1 F
                elapsed_time = nes->cpu->GetTotalCycles();. a) P+ u" b6 D
        }
6 L4 G% p$ L' s' ~. D# A2 e        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
7 N0 V. \9 H$ M# T                elapsed_time = nes->cpu->GetTotalCycles();# s2 N+ x$ F9 L$ p6 a9 ^
        }
) e  I" d# _6 l& F* M#else
. V, L/ G( W' q, ^, i+ z        elapsed_time = nes->cpu->GetTotalCycles();  C4 x- a. v. R; z+ u! y: Z
#endif
1 v* t$ y0 i; i. O8 R}4 ]2 C1 |. Q. b! Y& a% C$ k

& X3 f) O' t/ f  `// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)+ |* |3 D( @) D  H' W, I( u. V
INT        APU::GetChannelFrequency( INT no )
9 m0 Y6 D0 ~0 e- Y1 W$ X# n{
; i9 g/ {& x& _! _7 E0 `' }        if( !m_bMute[0] )
0 P6 v0 E. g. T7 m) z; \                return        0;
/ a& j  H( m! y! U6 |2 ?! l- Y! a% e% U* D* i& k
        // Internal  S. m0 U! v. y( l5 R
        if( no < 5 ) {
) A0 n" x# x! z  c8 x& r+ V                return        m_bMute[no+1]?internal.GetFreq( no ):0;, f% ^( a, H8 M5 ?8 k' J. a+ a" {
        }
0 O# _; D2 t1 `$ @  ?        // VRC6/ F, G3 Z" T* h; V3 f
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
, O* L5 C5 C0 K0 l6 y3 C                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;: W% P, f$ q$ _4 K9 K
        }( B3 \" [) Y- [0 D( B) r" C4 b
        // FDS
( F3 |+ b- z8 F& y8 [        if( (exsound_select & 0x04) && no == 0x300 ) {
% A0 K8 ?% _3 @                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 Q) }) [, G5 M
        }- g) E7 v: y+ P$ x  a7 E
        // MMC5
+ @3 W" B/ G* [        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {( }# f* f" @/ o2 P3 @& l, h1 x. e3 G
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;9 I& f: W" E. F) U- H
        }
8 {8 S  i2 e1 V" n        // N106$ J" a: ^/ }# T& D, u+ F
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {$ y% f- N2 i" q  z( G' K
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  A0 w. \  O* Q. ~) @# h0 t8 M( P, K        }
5 x7 b8 n+ z% q! N3 ]' j        // FME7
1 I; y' \+ ^. j1 r0 L& Q% [6 D        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# j. o& j5 m, j1 @1 l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
% N8 O+ @, J. E" `        }
. K0 [. F3 N, q, m6 X9 X        // VRC7# P) M6 i* [6 T4 G$ M" k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
$ s6 B) k$ u8 {) a5 ~3 @: g" f& U                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;4 f2 W7 |" ?- }# {$ l& P1 }
        }5 m: t% ?, e  {& F% {
        return        0;$ a6 k7 g! W7 X0 k5 h* ^
}) m) {7 F4 D8 Z8 u' }, E

9 e6 W- I3 P3 q& g# N) P/ w// State Save/Load
# U% n6 h+ C! I. ]void        APU::SaveState( LPBYTE p )
, x& S7 i' ~2 g  r" J- a: W{1 E4 [% v6 d" ]! g% Y, K
#ifdef        _DEBUG5 w* u& l. z9 K
LPBYTE        pold = p;
; y+ T8 b4 x! {9 o1 X$ p#endif
; G# L* N" ?! |3 K5 {8 P, n6 C2 Z0 E$ @$ J1 H" `
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
9 u5 w0 x0 {* S; E- D4 B        QueueFlush();
# |& @3 h5 e+ v
  W; M8 f" L  P3 A0 B0 Q        internal.SaveState( p );
! G: F, w, \2 V+ ?        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! G9 n$ ~. Z1 M) `

# S) M" {3 z5 N4 |$ ^% N1 C        // VRC61 w# N8 p$ D  k3 I
        if( exsound_select & 0x01 ) {
0 L1 ~# u5 I# d                vrc6.SaveState( p );
+ a4 c& q) t* ]. V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 `5 I% U7 Z# @/ e$ U
        }
7 K5 A8 p, d4 M, R8 S# t( n( z        // VRC7 (not support)7 J" b, G& T: G
        if( exsound_select & 0x02 ) {
5 {+ p. P' V! l# }                vrc7.SaveState( p );
3 n' E! h3 `, L                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% @. l. v' R  s/ g        }
& @' {6 f1 @! s" O+ b0 [' U& @        // FDS+ ?. n4 F, J# g- T; [" ~! |% \! V" r
        if( exsound_select & 0x04 ) {
/ y! r8 x3 z5 p8 g9 @9 a                fds.SaveState( p );
# b, `2 L1 N) v6 @$ ]                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. `5 U5 I0 |9 b' n+ S) Y0 m( S        }
$ A/ D3 B+ E. Z- }        // MMC5
. ^! m; P. @$ t! c# m, ]! M4 X( l        if( exsound_select & 0x08 ) {$ g6 n! R+ l+ m9 f) z+ r
                mmc5.SaveState( p );
; c" g3 Q& Y/ L: _4 d                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  Z  q5 t" V4 ^% G1 J2 M0 h        }7 x2 v& H6 c3 ~& M$ s7 X/ T- ]
        // N106
% l! s% a4 ?, `! L  t5 D        if( exsound_select & 0x10 ) {2 @; [, s  i; t' a/ ~
                n106.SaveState( p );
0 d( Y& t3 G: {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  l  k- G: m/ W
        }
' g9 @1 x% o* K! p  V! o        // FME73 T: z) Y8 B& g) {5 T+ o8 p- x
        if( exsound_select & 0x20 ) {) _6 U+ E4 G! h; e- Y- }6 [& R
                fme7.SaveState( p );8 |1 v. @6 v9 k: m/ D3 K3 B
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- i1 W; c( f. ^$ t9 V" p3 l" P& w        }# H. l: |! N) P0 e0 [

' l% [5 [6 J" O2 B& U% l#ifdef        _DEBUG; r* f/ A) A2 J, w) i6 w1 q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );, g6 ~3 {: |8 T& a2 h$ ]' ?
#endif: B; N0 B( Z8 T/ [4 N# H& Y0 U5 _
}9 ?0 H+ M, j' ?, J! b' J, y; M

4 f8 R& V2 g$ L# m0 @$ _# h' Mvoid        APU::LoadState( LPBYTE p )
8 x& n5 K5 \9 ~5 u) K7 c{. w  m8 O) z* D9 B
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡. U2 E. U+ S5 \' z
        QueueClear();$ Q0 C$ N# r- j" N1 x

1 K4 g% h2 v; i- @* D$ b* m0 r- O# Y        internal.LoadState( p );
6 d3 H% N$ L+ r; i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: z1 O3 N' A0 a8 l& \

1 r" L  f0 d& r! \. K+ V        // VRC6& s! \% W; Y5 F3 s
        if( exsound_select & 0x01 ) {
- S1 U7 S- e+ e- v8 o0 Y& y1 y+ q                vrc6.LoadState( p );6 l, j9 t; U/ {* Y% i# Y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 F& ^* O' m' R: t& D! X        }/ A0 C8 d- b! D
        // VRC7 (not support)+ R: {: y2 P. M' p, Q6 j/ _9 _& _
        if( exsound_select & 0x02 ) {1 x; q3 v7 g; C* I
                vrc7.LoadState( p );
% s3 {# N# n% b                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, o( X5 C& Y) w) C6 i: ?2 K        }+ }5 k& y: y% o1 f5 u- v  Y3 n
        // FDS
. k- J" Q. P+ @2 @; b6 t4 H        if( exsound_select & 0x04 ) {
- R( p3 B5 ], J) h1 g                fds.LoadState( p );
* E" x1 D9 K" D& a* S0 Z! b' Z" M                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 A+ |+ Q* L4 b2 g        }
" B9 b5 G8 p6 v6 Z- L' Y9 d        // MMC5
9 t3 Q6 O- |: i  t7 J* j        if( exsound_select & 0x08 ) {
# b9 v% G7 Y* d- O% R* g- a                mmc5.LoadState( p );
, X+ d* l. B! T8 M0 v                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
8 H/ b3 g1 h) H        }
, D- x9 [/ C0 ?        // N106
$ ^) A6 Q( N3 ~8 o        if( exsound_select & 0x10 ) {5 V/ A* R8 E2 I( D; w' z( V
                n106.LoadState( p );
' a% ?: F: W  T& ]- `+ S- P                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- P3 ?1 e8 a: k        }
) o: a- n2 a8 k        // FME7+ p( d7 s, W& t& U& J
        if( exsound_select & 0x20 ) {1 o; z" `. ^, U0 H
                fme7.LoadState( p );2 m! \$ |7 \' U' Y3 W
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 T) j) {% U' E4 x* ~: N8 J1 t
        }5 L* I2 q; _" U, A# X$ x
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
2 F; g& q; M5 ^# h% o0 k: e可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
7 ?# M1 z4 n$ F5 u3 r0 d感激不尽~~
; [7 b+ j4 `7 @1 G5 k3 e! E3 ^* |
恩 我對模擬器不是很有研究,0 u- S1 W5 \3 v" S. s+ Z- G; Y
雖然要了解源碼內容,可能不是很困難,
: S% k/ b; n; |& v8 h2 {不過還是要花時間,個人目前蠻忙碌的。
9 i3 f6 h0 k/ V2 U( g2 j2 Q: L0 \! b+ e/ `% E* h% J( A, W0 W3 ]
給你一個朋友的MSN,你可以跟他討論看看,; d* }( o2 S# Y* s
他本身是程式設計師,也對FC模擬器很有興趣。
8 n0 {+ _" d) h- A$ @7 X4 L- z: L+ r: d/ H: W: L+ t7 t" V4 O
MSN我就PM到你的信箱了。
" N6 z/ f/ z  P5 A3 n5 g( G
& |- Z$ f. e# w0 W! R+ m0 c希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 e* h1 p& M4 j8 _8 f7 ]5 r8 u呵…… 谢过团长大人~~

* s% s/ |; O7 Y0 s4 p& Q5 p5 n7 k
/ J% f% i- v  c% ^4 [9 ?哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! P. Z1 `: n: W% C: n
团长的朋友都是神,那团长就是神的boss。
4 R' k4 R9 g$ g2 b
哈 不敢當,我只是個平凡人,' E2 ~4 u1 H* j* ]" j
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙' R' Z; E$ {2 }7 z
ZYH; j! P# |& v- t; u+ `
QQ:4147343067 H. ]% @( R5 q8 z7 W0 j
Mail:zyh-01@126.com
' E4 q  [3 {* b/ R; ~. [4 q7 M5 y5 J* R( o; ~+ i
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
. j8 B! J# r" o/ y. I7 I再次对团长大人和悠悠哥的无私帮助表示感谢~~

- P8 @8 d2 U0 x! g4 O; d不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-18 12:44 , Processed in 1.082031 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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