EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: J; X2 }# |8 p/ x& k! f3 I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 e7 l/ [: `; _+ E; Y/ t. b
这里有相应的模拟器源码,就当送给大侠了~~/ w* d- L* T6 [- k7 q9 l& `0 D+ O
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ' E$ p: U; B3 v6 t4 u9 x
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
# U$ ^" v# A% J9 `. \楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# K8 \, V7 f/ x' E8 G
这里有相应的模拟器源码,就当送给大侠 ...

& a  Q+ {$ o! x8 M0 i9 @聲音部分(Audoi Process Unit = APU):4 D5 g3 t2 L: b; l& h/ J" S% c
.\NES\APU.cpp0 n7 L  i( S: ^5 V( }4 d# y  B, L3 M
.\NES\APU.h! d+ g% f* [" Z$ p
: q/ L0 t6 R& o0 j6 i  _4 D

( W( A9 j; F6 Y) Z7 Q3 @影像處理部份(Picture Processing Unit = PPU):
6 A& S1 j" M, b1 e; l.\NES\PPU.cpp
: H) j7 L  u5 I6 M' Z$ }.\NES\PPU.h" f7 O8 t: ?9 y$ `" j( n. a& i
8 r3 L( j( P* j- N1 ?) l: m
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:# s9 Y' X! S% E* o. G
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
/ v* P4 V( Z7 |, i//////////////////////////////////////////////////////////////////////////
' ~0 A( H" m  t; A1 y9 ]* H! I2 B//                                                                      //* j  x0 L( U) f$ O! c) R/ v$ X
//      NES APU core                                                    //
6 _- g1 F' B) U: M7 r, F//                                                           Norix      //7 |, O0 x, Y" C  J6 }: Y- Q2 B
//                                               written     2002/06/27 //* k& o  m$ n/ t9 E8 W$ U, t% ~6 B
//                                               last modify ----/--/-- //7 V8 ~4 b( ~, ~
//////////////////////////////////////////////////////////////////////////+ Q$ R, f; u: |! X9 T# H# J
#include "DebugOut.h"7 m& d% O9 @* r) ?6 D& t- m0 @
#include "App.h"
/ g, D2 f' O" q#include "Config.h"+ U3 H* @9 I+ u/ W

7 g' _. V+ ~) i6 z#include "nes.h"- u$ a2 ]& d9 K( P% P% f
#include "mmu.h") Z# e1 F! A7 a2 `' x# v
#include "cpu.h"
$ I1 o* N6 L/ }#include "ppu.h"
9 s0 U. U9 C2 Y#include "rom.h"7 Z  Q/ d. G' ^; ]  ?
#include "apu.h"
; ~" \8 P6 C- O4 m. t3 p/ a: z0 X6 G, \
// Volume adjust
& A4 ]; h: S- {// Internal sounds7 o8 Z+ J+ p" h) z7 K) N+ {" Z
#define        RECTANGLE_VOL        (0x0F0)$ ~  d0 ~, [. w% n8 T7 R
#define        TRIANGLE_VOL        (0x130)+ G5 h3 b7 r# e* F& a
#define        NOISE_VOL        (0x0C0)
+ [9 }( r! j; U#define        DPCM_VOL        (0x0F0)
2 \$ ?" [- X- @* K// Extra sounds
% Z. A+ a; C" B#define        VRC6_VOL        (0x0F0)1 E5 A* G/ v, h. D# |) b
#define        VRC7_VOL        (0x130)( K! c8 L0 p2 I2 S" p3 O
#define        FDS_VOL                (0x0F0)
1 n) A' Q' T  V9 K) D#define        MMC5_VOL        (0x0F0)$ g" i$ q6 m' E/ l9 G2 Y
#define        N106_VOL        (0x088)* ?! b, ]& k$ ]3 t
#define        FME7_VOL        (0x130)
% M' G- [5 n* m9 u+ V' Z
5 W: X. t8 X/ `3 A( dAPU::APU( NES* parent )6 T/ p7 y7 n( P( p: Z' @7 z
{$ n3 u9 i5 }2 p# x' T3 P; l7 x: F
        exsound_select = 0;
2 z9 j+ u' S) E8 ?- q/ [
) P8 p1 ]2 i1 P* @$ ~        nes = parent;
; h: S/ u# `+ f6 Q        internal.SetParent( parent );6 w# Z4 x( ~) M7 Q1 `

% Z1 e# `5 S. B        last_data = last_diff = 0;
, X+ c# S+ S) A) z4 z7 I- v
7 A4 F) C+ y$ O; g9 P- t" ?        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 P5 }0 Y( ?5 M1 E# X' H3 S9 ~- K; j8 s8 D
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
* n) }! F* b/ M% v# A! W        ZEROMEMORY( &queue, sizeof(queue) );
: E! x/ V" J" i        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, c+ `6 Y8 v' g- I! J9 J" I- e( y- ^+ u+ _0 u- I$ h2 g1 d  Q
        for( INT i = 0; i < 16; i++ ) {$ C0 A: G) T9 b0 ]& l" X
                m_bMute = TRUE;
7 x, B, N, ]5 c8 w* v8 w        }- z+ H. I. |; w8 v4 _6 Z
}
2 ]- M  O- v$ k* X
6 T6 y- M- v$ L0 c' Y$ \- ?APU::~APU()
- r  p+ Z: ^2 y/ b4 O. H3 t{
$ n0 @" E! q7 m2 w}
( z$ s- G9 S! w& }0 s" V: J$ }1 L& b+ I* A& V7 T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
. t: n, r0 J6 S9 N9 v# K, o5 m{
1 R# b! e4 t* j" [5 N' R        queue.data[queue.wrptr].time = writetime;
1 ]- x, W7 H; P: r  |! E5 N  u3 _5 h. s        queue.data[queue.wrptr].addr = addr;
) B" L0 R) r6 B7 ~' C7 T+ B) ]        queue.data[queue.wrptr].data = data;# ^; M& C  s1 ]3 a
        queue.wrptr++;
$ S) v7 d- f1 s7 o- ~        queue.wrptr&=QUEUE_LENGTH-1;' ^' T! l/ m+ |2 C! C
        if( queue.wrptr == queue.rdptr ) {
2 M' i- o! ^/ u+ e                DEBUGOUT( "queue overflow.\n" );6 Y2 k+ O  o. Q' u' Y
        }9 s+ |; U& |; F# a) }3 K* e
}. {. z: i$ F- b" m. @9 F
" q+ y( d% B& r1 i0 Y- C0 B
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )8 @$ h- T4 c$ Y" T! i3 i  g/ _- e
{
% ]. g( E; n, D; ~$ }        if( queue.wrptr == queue.rdptr ) {
2 \8 r  D9 b6 C: ?                return        FALSE;& q4 m' i. i3 i3 @) K
        }  \" u: O) _2 R. B( y
        if( queue.data[queue.rdptr].time <= writetime ) {3 r9 f0 A" U4 c; T: Y) g8 ]7 e) r
                ret = queue.data[queue.rdptr];* E2 L3 C* ~9 f* v6 m
                queue.rdptr++;! [! }9 g8 @- h+ S
                queue.rdptr&=QUEUE_LENGTH-1;
9 S2 j4 ?: b6 {6 @, ^/ L  ]                return        TRUE;
) f. U  x! \, X* Y- @+ X- R, d        }) q' M2 ^; E1 ~6 b4 b; [. U
        return        FALSE;/ t- e, ~& ^# I  z( q9 S
}0 K9 e2 E- N% W/ f2 G
; I( H& @. d- t
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )4 j- S& e  i. R, o& M& h8 n
{$ o0 w! U9 i2 I, N7 q/ W  K  J
        exqueue.data[exqueue.wrptr].time = writetime;& p+ n" k2 W# q9 {9 }2 N9 R
        exqueue.data[exqueue.wrptr].addr = addr;! t; G4 o# C: V# S. V' q, Z! [
        exqueue.data[exqueue.wrptr].data = data;
$ F% b. W3 \. f- c- Y! a. z# [- R        exqueue.wrptr++;; i# x) V  O6 K% q! N6 B' {
        exqueue.wrptr&=QUEUE_LENGTH-1;& X2 Y# a& C6 T/ u( [2 O
        if( exqueue.wrptr == exqueue.rdptr ) {
# H# r" {: P" Q6 O" v$ y3 ?                DEBUGOUT( "exqueue overflow.\n" );" v( b. _0 V) T- c8 {
        }
8 W8 d. e# B( r9 v. b}
9 _8 W( S0 [5 I: L. e2 P
  x1 }! }* q2 B0 K/ h' i: U: L8 S& }BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  f+ M8 w3 F5 v8 t0 `/ L
{
7 c, v8 T! {, m8 q1 v/ }: F7 X$ W        if( exqueue.wrptr == exqueue.rdptr ) {1 r1 j  K2 o; p1 s- [. J( n+ U+ ]' T
                return        FALSE;6 m+ D: `  m# ]/ X% x  Q" _
        }
) t- Z1 i: s! f+ m/ Q# g! r9 [        if( exqueue.data[exqueue.rdptr].time <= writetime ) {7 m+ u( W" G+ @/ U8 H+ r. i  q5 J. C
                ret = exqueue.data[exqueue.rdptr];
4 X( I' k* l8 v/ A. J4 Q                exqueue.rdptr++;
: j* v# l$ b  q" J: u) c: t                exqueue.rdptr&=QUEUE_LENGTH-1;2 Z2 m6 Q' {  ~7 w/ k" X4 R
                return        TRUE;
4 F: P7 ~9 G/ g! b1 n( Q! [; R        }6 G. E6 w& ~. V  ]
        return        FALSE;( M( @0 }. }5 D" f  H1 P
}
1 X. s# V$ e8 o0 d
3 [/ q, C/ ]/ N- e" Zvoid        APU::QueueClear()1 Z; |/ ~+ G5 o+ p6 y' m0 A! ?) \
{& w( q& a) {( U/ D8 _# f# X
        ZEROMEMORY( &queue, sizeof(queue) );
% P% s/ {2 a+ [  }, p        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 S' U) S( E7 B# _
}! k5 R3 v9 k. S# ~3 `

0 ^( O0 `$ }* F- A2 V- M8 _void        APU::QueueFlush()  ~$ q- L( a# \& p
{$ `% ?# w5 u- @% S) G0 w
        while( queue.wrptr != queue.rdptr ) {
' x7 z: ?/ A7 }  {) o                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );2 `! ]" w. B3 y9 e6 w" k6 S$ d) m
                queue.rdptr++;' v' ?$ D3 d  t: l2 x7 d2 j9 z) s( o
                queue.rdptr&=QUEUE_LENGTH-1;
% a* c2 l/ s! F; k        }
0 j6 i$ j: r9 u/ n! _6 ?$ A+ I# J4 f8 j4 n
        while( exqueue.wrptr != exqueue.rdptr ) {
' n& {( {0 T$ z" o/ m0 [6 m& x9 e                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
$ W' z; c8 E! A& X. ]6 n2 k& U                exqueue.rdptr++;
$ {8 Y" C& U5 \, N9 G                exqueue.rdptr&=QUEUE_LENGTH-1;
" h% q+ o1 }3 |5 S+ p- L2 X8 f# r        }, P: u9 u  j' v4 n+ M  ^# m
}3 [# p8 t3 @8 o5 J( [% A, v+ [% h; F

0 P, y) E+ K" F( T% D- C9 Gvoid        APU::SoundSetup()
3 C" j7 k0 t1 b/ E( H9 e& ]{2 F2 X7 `! [0 l- s8 S- I+ }% C# e
        FLOAT        fClock = nes->nescfg->CpuClock;
* ?7 y5 f  D5 d, ^( T8 Y! I; f        INT        nRate = (INT)Config.sound.nRate;
. u% @% D% U. P- g6 W9 Q* A        internal.Setup( fClock, nRate );
1 l' S* q3 M2 d8 O5 [        vrc6.Setup( fClock, nRate );  q& U+ U2 c& ?: P0 |$ n: d
        vrc7.Setup( fClock, nRate );
5 u$ Z! e- ~3 K' G        mmc5.Setup( fClock, nRate );
7 J. t8 |* Y; _4 x9 y        fds.Setup ( fClock, nRate );7 l9 a1 x+ E! x/ S; T2 O
        n106.Setup( fClock, nRate );$ B) ~$ p1 G3 d' U0 d
        fme7.Setup( fClock, nRate );
8 [, \) m; I" q1 y}
  ~1 C( T, O2 B
2 R) H4 m6 s" ?3 @void        APU::Reset()
; u6 q! R. I6 v' V{& _$ i7 O6 c( [! O
        ZEROMEMORY( &queue, sizeof(queue) );
5 L1 x2 l9 N- s7 ^  P( ]$ z        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 S1 R1 @6 `& _  a1 E

" r" y: E6 b8 t4 r/ m7 R' [$ ^8 B        elapsed_time = 0;
4 b& N, l0 o0 Y# [' e2 r& M
3 X, s( c7 V6 @: S$ w        FLOAT        fClock = nes->nescfg->CpuClock;& ^3 Z% i7 }: c1 \. L8 }! ]6 s# u8 q
        INT        nRate = (INT)Config.sound.nRate;+ Q. _5 I) Q$ v2 k3 ]
        internal.Reset( fClock, nRate );4 |2 c( ?" a9 H! g" ]( N
        vrc6.Reset( fClock, nRate );
1 }8 ~5 U2 e3 n4 v        vrc7.Reset( fClock, nRate );! U5 f$ @# V7 b: B( \: S  u5 _
        mmc5.Reset( fClock, nRate );
. O! C1 o6 f9 q: O6 N  [% l7 m        fds.Reset ( fClock, nRate );
9 {( h. J8 i  n. {& F        n106.Reset( fClock, nRate );
+ z4 R* J0 L) o        fme7.Reset( fClock, nRate );9 l% a. o% X, J  y3 X

5 O% y% _; m# l+ U        SoundSetup();9 \$ T2 D" |6 v" m+ D) i
}+ J  i" k4 d8 e; G: H
+ M: i2 ^* d- u" A% g
void        APU::SelectExSound( BYTE data )! o% K4 [" Z9 L, p1 @
{7 }3 p9 j7 q7 a, n6 z+ C
        exsound_select = data;
1 P* x6 f) }) T/ S}7 ~( V# k* H1 S8 U0 ^& F

- f# D# ~3 {1 h, j: w* ?% DBYTE        APU::Read( WORD addr )# G, B9 h8 K9 Q* b3 r: ^- v
{
5 y7 {$ _0 t4 D& e2 ?0 U; }        return        internal.SyncRead( addr );3 K+ }8 s, c& ~6 g
}6 U# t% I/ o9 N

0 A( M* _, m+ Q. C* gvoid        APU::Write( WORD addr, BYTE data )
* I7 r7 G# V7 W; U{
; L  K6 V6 Z' Y0 L, ~4 \" G        // $4018偼VirtuaNES屌桳億乕僩0 i- q+ x4 b3 v& f/ u  O* l
        if( addr >= 0x4000 && addr <= 0x401F ) {$ B% p* k- {0 e
                internal.SyncWrite( addr, data );, d7 L! V3 M' x0 G% U, A
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
7 i0 X; y4 ^- f$ I# f; ]        }$ F6 C+ c1 u7 @2 P+ }1 E: f
}
! i6 C/ K# S, L4 J5 P& F/ o4 ]- _: h, O1 Y2 Y
BYTE        APU::ExRead( WORD addr )
3 Q" Q& H. f: N{
* x* R* w1 `% L! B) OBYTE        data = 0;
. F3 N1 p. c/ g  @! i+ g1 I
8 O6 |& o! F4 G: J$ A. K        if( exsound_select & 0x10 ) {
+ Q) L* v; h; l                if( addr == 0x4800 ) {, \, K2 z5 p& I+ p8 m/ Z6 o
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 E. N" [  [3 L/ Q8 t                }
( K  d1 ^0 _1 [5 r$ s        }
1 b' X$ v5 i4 d1 \        if( exsound_select & 0x04 ) {
' {1 A( l; O0 F" J: ?# p( U3 a                if( addr >= 0x4040 && addr < 0x4100 ) {
2 j; ?: w: n# `2 |7 l                        data = fds.SyncRead( addr );
, q% z& O. g: v- U( P! {1 T) ^                }
+ K' H) ^3 A( l0 A6 p6 U        }8 H: O. ~8 b. D% y. }
        if( exsound_select & 0x08 ) {
3 i  q  k* v/ `/ h& K  t' J: S                if( addr >= 0x5000 && addr <= 0x5015 ) {
% Y& z; l- O6 ^( K# V1 [3 ]+ X! ]                        data = mmc5.SyncRead( addr );
7 D1 J; x& b# N# Z3 {, m6 [8 R                }
, j7 S) O) e4 z/ R5 h8 P        }
) ]1 E8 |2 |5 `9 E* c! H% _
/ h5 Z  R2 g7 M  p; _5 k; h        return        data;1 t5 c2 v1 A, ]( J
}" _& C7 ?& Q2 R7 b  r

: J$ `. v$ Q# L8 S. Z. L; A" {void        APU::ExWrite( WORD addr, BYTE data )0 C! Q5 h3 I" A. ]( x
{
$ }2 j+ X) V  \" I7 X        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 J5 L) a9 E9 x, a5 _6 F% s: N
; V* y$ E& }+ B! j( ^- t& }        if( exsound_select & 0x04 ) {
& C2 H0 q: ?4 h                if( addr >= 0x4040 && addr < 0x4100 ) {/ T: H* P* r5 ?, j
                        fds.SyncWrite( addr, data );
/ P  B( t6 G2 g+ ]                }* z# `7 h7 ?: q( D1 n4 A( d
        }+ j7 L& G# o0 O5 D& W! y( Y+ p

/ p6 }' r' Z+ M( V, X5 R        if( exsound_select & 0x08 ) {
! I3 i3 b1 P9 e0 |7 w! r                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 A- [* X2 b9 k, B: h+ v                        mmc5.SyncWrite( addr, data );$ T4 I7 N2 h; Q8 R/ O! i5 o
                }: ?3 X4 Z8 @$ [: m! X
        }& F7 T4 d( I$ C. B2 n, a2 l/ C
}
7 j& Z0 ^$ v& N9 ~8 q
) |; L0 ]8 x3 A; B  V% P% j3 C. |void        APU::Sync()0 c0 a8 \6 T: I' x3 `9 i
{- O8 t7 H+ r) l3 t( q0 L- X
}" v& l+ [, a  \0 u9 O
- a  u& P" a# w! p6 ]$ `
void        APU::SyncDPCM( INT cycles )
3 x, h+ l' [- O+ I9 n{
/ w1 C5 w; y1 ~1 l        internal.Sync( cycles );% c7 }1 j1 L8 x7 U$ P2 Z) w& C# f
8 G7 k( }# @$ a' b3 S- A* [; I
        if( exsound_select & 0x04 ) {
5 n/ Y: G& `3 Y! q4 _                fds.Sync( cycles );
4 c% H6 ~" o  o. G  @8 K; S' q  S' _        }4 _. @* s! \9 z" [) M. Y9 b1 @
        if( exsound_select & 0x08 ) {
# f& L3 v# v+ G                mmc5.Sync( cycles );8 |) s6 Z2 T. [* I7 @: g
        }
  [- v" ]/ W, t6 V2 A( @}
: T3 b' c. ^: B  a. _0 ~6 M/ c' z9 d& `4 k" k) t
void        APU::WriteProcess( WORD addr, BYTE data )6 k' q5 e3 U" }  ~( f
{
% I: C$ }$ u  E        // $4018偼VirtuaNES屌桳億乕僩) p1 K7 \( O* W. X
        if( addr >= 0x4000 && addr <= 0x401F ) {
2 o" Y5 @) ]! E' z! \4 Q                internal.Write( addr, data );
( I# V* n3 J# k2 E; E2 I        }
# n& A% X: \1 C}
+ c. y5 W- f1 b, O7 t& o+ w& D# j3 m+ ~- n1 |$ K
void        APU::WriteExProcess( WORD addr, BYTE data )1 n8 Z5 c. Z% W# E
{) r6 t' N7 L$ m/ r% b6 x
        if( exsound_select & 0x01 ) {8 F  ]9 T/ V7 r- L4 `! O
                vrc6.Write( addr, data );
& I& I8 |' a+ W7 Z3 `        }6 _' m) h% a7 N* L
        if( exsound_select & 0x02 ) {
4 Q  `5 F2 U" {/ z/ E                vrc7.Write( addr, data );
9 H: d4 V2 {( A% \        }( B1 `! P# |# j  f/ d5 c
        if( exsound_select & 0x04 ) {# a! Z; y, Z0 U- Z1 g( c$ V+ z
                fds.Write( addr, data );' q/ P+ ^& {8 R% T
        }
. C% X- c: L4 |+ y        if( exsound_select & 0x08 ) {
3 r8 I: s4 E/ z  Y/ v                mmc5.Write( addr, data );2 M# }; C2 z1 E, B7 S0 c; W8 o
        }
9 h  V% g7 G* v* n# p; {        if( exsound_select & 0x10 ) {
% ?+ ]2 v' I2 ~3 Y2 Z, _7 t                if( addr == 0x0000 ) {+ l; ]; B; s  m
                        BYTE        dummy = n106.Read( addr );
7 A( Z7 c* a* Q$ h2 H3 X                } else {9 Q  K: b! B3 x& B  D+ n4 ?: m
                        n106.Write( addr, data );, A0 z  g% }" s6 p% H
                }
+ K% n" Q8 ]- K( V        }# B' C0 V1 o; I; i1 ~
        if( exsound_select & 0x20 ) {
- r7 G! [! Y+ a                fme7.Write( addr, data );
2 d& y. Y# L$ B0 B: E; Z2 }        }
/ G  a' S) ~5 v) X, I) `$ d) X}# Q% s- R# k6 J# U& y3 {3 H

, c( C' u3 i/ \8 ^! }) ^void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
2 v8 A7 v2 u$ w+ f{
# b7 F; k' y9 p' D" L1 XINT        nBits = Config.sound.nBits;0 w: P+ ]# D! ]
DWORD        dwLength = dwSize / (nBits/8);
$ o6 u$ }/ P9 A5 LINT        output;2 u3 [$ |3 o9 C3 \' Z4 U0 D5 c" i
QUEUEDATA q;
- h, d6 _* Q* x& bDWORD        writetime;
) B( r+ F. C. A) V: d  _9 E0 B% E5 _# P& w% s
LPSHORT        pSoundBuf = m_SoundBuffer;# ]) a. `4 w9 n2 s7 U& q! J" B
INT        nCcount = 0;
. Y8 U  x* c1 l
$ l, l# Q4 d1 S, m" m$ G9 KINT        nFilterType = Config.sound.nFilterType;
! \0 S9 j2 g& }8 y3 a8 X+ B
; \( J* v  N0 P) g: g- y& T* y& W        if( !Config.sound.bEnable ) {
3 D; f1 _% S( ]) h: u! n                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );6 F  g+ i5 m9 i7 G! m% {
                return;
& {* d9 V: {* \6 {: H/ V3 j        }7 Q- \$ B/ d4 \' n0 a0 ?7 n

' ^5 k' h' Q. _) J/ p        // Volume setup
* g, R: G1 A9 N8 k( `        //  0:Master& S! r, U7 m, t  r2 h
        //  1:Rectangle 1
! H3 p. S+ i, z# F: g        //  2:Rectangle 2
' ?; U1 G0 ?6 R1 n8 B" U8 @        //  3:Triangle
0 X- L5 a3 w, W* {  \( F        //  4:Noise
* ~+ Y6 q! n1 C) |2 v        //  5:DPCM
" o5 `7 c* o$ D' }9 i# K4 ^        //  6:VRC6
& w4 Q" q+ U7 D; A5 L  ^8 v# r0 d        //  7:VRC7$ ^% v/ y, U1 X: A# a9 i' ^3 Q
        //  8:FDS
9 T: n/ a; u) ?% d/ d        //  9:MMC5
% k/ L! R2 ?! B0 b3 S9 @        // 10:N106! N- y) K# q# T
        // 11:FME7
% i  K# B5 x; U( P5 F0 I        INT        vol[24];
: v$ p# E' n1 s$ S        BOOL*        bMute = m_bMute;3 x$ W: ?" Q0 N8 {1 ?
        SHORT*        nVolume = Config.sound.nVolume;* O0 I- z2 h+ G+ [
+ r$ E+ B( R" P3 l6 E  k
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;! w# D% J9 I+ L+ t* K# Y

  X1 K9 d/ w1 L% j" S        // Internal
$ s: y* O' g$ [0 e$ x5 O        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* M( w# b5 w+ C3 h        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;' J2 d, [, @- V! }# p/ `  E0 F) l
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
9 _4 _) }( ^4 t        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 u) M; e7 j) v; {
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
9 K* \0 I0 _' Q$ D7 [! @1 i' c
. Q$ h# ^( N+ m        // VRC6
4 I: V" I& w8 ^7 I9 ?        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& E8 g0 w- B% N0 I1 D2 s( \" T        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# u& v! B8 l6 o$ N2 @+ G4 G+ j+ r' M
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 z/ d' _4 q* W5 \) O' g7 `
/ p9 o; r1 E5 E. x! w( q) q
        // VRC7* J& {$ i3 U0 I7 P. J* i  {
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( e8 \/ n5 F* O

) U) l/ J" w4 k$ P        // FDS
  T/ V: i& o/ V' l: U, h- z        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ H2 H, C* G% K2 ]2 i$ N: B  e  U, {! z& Q2 i8 d
        // MMC54 ^" l& V' H, ~; P1 Y+ U
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 D5 C) ~) E8 ~9 U5 v        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, @( T/ Y# |0 b( b2 M7 B6 E
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 ]+ H6 ?! d. k

- h0 E; b( T( m* ~: o! @4 E, h* t        // N106
' @! M! [, I9 {, r/ O        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 ^) G+ ^. n8 X! x  p* |* i; Z        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ r& Z* O" X' Z/ H7 M3 @        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) t3 x3 \7 F. }6 j
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 X1 L7 o0 m: A) U
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 j) b& @% K% J, w& s: l9 f        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& z* E) R' C5 h7 Y4 a4 O: I        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. Q, c$ \$ X7 ]- g        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( d* X0 D/ p; Y6 R
6 e) B& ~! y: z. J6 f+ t( z2 q
        // FME7
& c/ M4 m& y" S" H+ M        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- N; s: [# Z" D8 B
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ a* H' n' k" H! q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 ~( Z; F8 r2 Y8 c' e- p6 u
# F6 x0 `2 F' h1 C6 q5 x
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 H, I3 S* h1 z, w$ E
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;% |+ [0 H* ~# U. I: D
  a2 H# |. u) l$ x
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟1 c% @& I% u# f8 v
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 J( m! h5 a+ f# W                QueueFlush();$ A' y6 r5 ~; }! d9 J0 q5 [+ h
        }) ?9 ]1 k& K( |: G% f
. c" Q7 f# W' Y2 B7 q) Y
        while( dwLength-- ) {9 i3 ]; |0 X) a4 C1 g) e/ r, b2 N
                writetime = (DWORD)elapsed_time;
/ S- W, |% v; N
1 j" `  L" R  g, m8 ~  b& V& U                while( GetQueue( writetime, q ) ) {
( e9 y. k& ^6 V                        WriteProcess( q.addr, q.data );! Z) Q3 r) T* n/ m3 ?( K
                }
- n1 e+ O/ ^/ d3 H' F6 `6 r5 A0 y: j2 w$ d
                while( GetExQueue( writetime, q ) ) {
. H5 [$ c5 ], V& ^                        WriteExProcess( q.addr, q.data );
5 J$ h7 s& D! f- p" M* R& s                }; l4 a) a* ^& l! e+ {  k. n

, }# u. Q) F0 r+ S/ a                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7, l1 d/ Q! R! t$ d
                output = 0;
' e  i8 }+ W& Y4 b                output += internal.Process( 0 )*vol[0];% q2 e# _2 q, A/ v3 ]
                output += internal.Process( 1 )*vol[1];
( k+ J5 o" }0 C3 p; x! `' E/ E3 C                output += internal.Process( 2 )*vol[2];1 K) z7 D* c/ Z# W9 N
                output += internal.Process( 3 )*vol[3];' c3 [- @# C" j6 Q: r5 t1 q& M# j" X) D" @
                output += internal.Process( 4 )*vol[4];
, a: r- U1 X" [* ^6 T
* S. A  ~- X* g/ o  r                if( exsound_select & 0x01 ) {: I$ M" d7 L# i; B
                        output += vrc6.Process( 0 )*vol[5];
1 S) S8 b$ T& C& J                        output += vrc6.Process( 1 )*vol[6];
) `7 K2 j9 e0 o* v1 T: t1 K                        output += vrc6.Process( 2 )*vol[7];' P+ H: d* y# f2 b7 s
                }4 H: a5 v! D8 {$ H& Q
                if( exsound_select & 0x02 ) {
) E! f, D5 \* D  \: I                        output += vrc7.Process( 0 )*vol[8];
; ?" O, B8 D/ Y9 I1 K- W                }
& L! L9 v' O$ ?  o                if( exsound_select & 0x04 ) {) H/ |' U0 J) D( ^6 m( w
                        output += fds.Process( 0 )*vol[9];: M' @! ^# ~& ~& j5 d/ z& ^' P
                }
$ c0 _- d% b0 r/ `+ G0 C8 Q/ d/ l                if( exsound_select & 0x08 ) {
( V  I' U0 C' d6 m" k0 N                        output += mmc5.Process( 0 )*vol[10];
6 G; F* K$ ^# i4 J+ r* I4 x! S& ~) b3 ~                        output += mmc5.Process( 1 )*vol[11];
7 N' J" U6 ?. K, {3 d1 }                        output += mmc5.Process( 2 )*vol[12];
: K9 S- }% _. H" k. T5 L                }
# S/ R3 i. ]/ T7 V                if( exsound_select & 0x10 ) {
; o) G- y; d3 f% r. z                        output += n106.Process( 0 )*vol[13];, n/ y# y9 E$ e, F( {; ?
                        output += n106.Process( 1 )*vol[14];
; @0 W9 Q! A) N' D: ^0 A  `                        output += n106.Process( 2 )*vol[15];# a2 w/ F( H  j! H
                        output += n106.Process( 3 )*vol[16];8 R# y. |2 |( e1 l, i) ]9 Y
                        output += n106.Process( 4 )*vol[17];
9 x9 ~* o; F; W                        output += n106.Process( 5 )*vol[18];9 ~9 {2 Y; z% n3 W% X
                        output += n106.Process( 6 )*vol[19];# a/ X" V3 A2 q7 h
                        output += n106.Process( 7 )*vol[20];8 T, ~1 M$ p6 r( A4 b3 |7 q( @
                }
' n! f/ N  l$ i# G* [$ L4 b                if( exsound_select & 0x20 ) {' h* m8 T2 q7 B
                        fme7.Process( 3 );        // Envelope & Noise  B# ~4 h3 Z) O6 _0 \( L
                        output += fme7.Process( 0 )*vol[21];- Q/ {: X% I1 T) t( D8 |) g! G
                        output += fme7.Process( 1 )*vol[22];4 \0 r! W/ b1 s* _: R
                        output += fme7.Process( 2 )*vol[23];
  D* B3 c  ]  [$ f9 v                }0 ~7 N- i4 y6 @! h& ~1 q( l

7 c: k3 L+ K1 D1 Y' v                output >>= 8;
( \% X8 B6 V- @
1 F) X/ ?, A" j4 u0 z                if( nFilterType == 1 ) {
/ D0 O# o$ e: r6 [* [0 j# T: F: Y. g                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple). ~' v* g# T- N+ i$ ^5 }4 Z
                        output = (lowpass_filter[0]+output)/2;9 C% _8 l/ S& K
                        lowpass_filter[0] = output;
" k, o0 A5 Z6 b9 j3 D( E+ g/ Q5 B* ~                } else if( nFilterType == 2 ) {0 v; b/ {! F1 U9 j! T/ Z/ t( a
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
8 V- P" s7 ]7 P2 S                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
, z5 i; p: ]  ]$ f/ Y7 r                        lowpass_filter[1] = lowpass_filter[0];
) i1 s. I0 R) l+ c3 n2 `$ o                        lowpass_filter[0] = output;6 i2 u# I( N& t& b' L, V* q
                } else if( nFilterType == 3 ) {
- }+ [, a4 S) t                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% h, b5 }- {- e3 G, H5 k( p+ K                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
4 }6 e$ |) u! J& X' m                        lowpass_filter[2] = lowpass_filter[1];
. o  V' j$ c' t/ r; |( M                        lowpass_filter[1] = lowpass_filter[0];4 z) E; F# r* X* l+ X" N. F1 x
                        lowpass_filter[0] = output;
1 ?8 H9 J: a$ u, M                } else if( nFilterType == 4 ) {4 @! L5 v7 H2 R$ n
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
2 |3 k6 u3 ^& f/ b9 a4 f                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
: l6 n( W" x6 m/ z$ w  l! _$ h                        lowpass_filter[1] = lowpass_filter[0];
1 M, a1 ~2 W6 b                        lowpass_filter[0] = output;6 Q# h$ ]; p8 v1 i' S1 S
                }
( X- d: z7 @! F" N
8 q+ t5 x7 ]' b9 z% w#if        06 \) a( C, z, [8 p; U: O
                // DC惉暘偺僇僢僩+ p/ s5 k6 V0 z. o- \% V5 s
                {
# W! S% D9 l* o1 A                static double ave = 0.0, max=0.0, min=0.0;2 y4 L/ v7 i0 X; o
                double delta;1 M( V$ t7 T7 w& `7 n" @) ]
                delta = (max-min)/32768.0;$ V- G# ~5 l3 E
                max -= delta;
2 v/ M. e( I4 X                min += delta;* ]0 o( O. B. R5 E3 V+ r& q
                if( output > max ) max = output;4 N7 T' F3 ~% n7 s$ V2 L! g
                if( output < min ) min = output;
: a  [4 ^6 K" a                ave -= ave/1024.0;
$ j4 Z; v9 P  f2 K3 ~                ave += (max+min)/2048.0;  |- Y3 Q) R; b9 m. v
                output -= (INT)ave;% a3 t0 z- {2 B: X
                }- V. `6 G% n5 N+ T6 ?
#endif
. x! r' R/ o) Y7 q7 c#if        1
( L! m$ X- g* q/ k% a+ S                // DC惉暘偺僇僢僩(HPF TEST)1 }; [' f( ^3 G; y9 I
                {
! r" U' D& p3 X//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);" N' V. z0 b# H) V6 R
                static        double        cutofftemp = (2.0*3.141592653579*40.0);: N4 o  r$ X5 W5 O$ O
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
' `/ I+ R5 \/ k                static        double        tmp = 0.0;/ D  l; a% B; q; u
                double        in, out;) Y# Q" G) _/ R9 ]& Q4 D( d

( r8 _' B- @+ M% f/ d. W* P                in = (double)output;
# Z0 ]3 Y& W" `0 x6 F                out = (in - tmp);
- g# e. d0 t0 o) d  v" i- s5 ^                tmp = tmp + cutoff * out;1 S% ^( W" U" U

* B2 _; v+ o4 a                output = (INT)out;
4 H) c: L) N3 p/ b' |0 X                }2 a. s. G4 i; E2 s' }  [* [- J. X
#endif
- I* z2 ?+ k) O#if        0* w" k" @" ^6 ]. E
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
; g- f) ?$ K4 {. ~* b, w: f. ]                {9 }5 T0 e% Q! D8 r+ t* c2 j
                INT        diff = abs(output-last_data);. `& Y1 t. z9 L6 A2 q4 m* \
                if( diff > 0x4000 ) {" f" I2 q6 T+ p; D, D& W
                        output /= 4;
: U3 n: D" C& D! d5 P) b                } else $ F$ f) P* i2 S' ?+ g4 @
                if( diff > 0x3000 ) {/ p& O5 S" T* m. y" `
                        output /= 3;) b2 z- A, k7 e$ ?7 R
                } else4 p: F- i5 o" _8 {. Z
                if( diff > 0x2000 ) {+ N" Z: [( _. Q
                        output /= 2;
" r' ?5 q" s* g- K8 F                }
: M# E5 O) Y) ]8 }6 k- h, P                last_data = output;6 E+ g6 d, a3 k  V3 g. g. {7 P
                }
0 W0 n5 ], n) ~' u, y& g4 ]#endif
+ D$ c  L  U. C# _2 b6 c- K$ u                // Limit
& v2 s5 b" o' ~- ?0 I( y; w* a                if( output > 0x7FFF ) {
) K8 G6 R$ U  q" s9 k8 b* P- v                        output = 0x7FFF;
* p( R2 d1 C. e8 O3 ?4 ?  j                } else if( output < -0x8000 ) {- g/ V9 _: A1 i: G# d
                        output = -0x8000;
" v  _; G- a5 e0 i2 e) E                }
. H: A. k% m! X: [- Z
# {, a" q2 P. N0 Z                if( nBits != 8 ) {
1 O% v1 E. q4 e                        *(SHORT*)lpBuffer = (SHORT)output;
# C+ |2 A+ a% ?                        lpBuffer += sizeof(SHORT);
% U" z) r! O4 ]                } else {) F* P) j/ s4 E2 l
                        *lpBuffer++ = (output>>8)^0x80;6 Y6 A5 e) {) s: v5 k
                }
( T0 i0 W. F' l; I7 F/ c' o( u$ V9 B$ ?
                if( nCcount < 0x0100 )
, P* ?% P3 B* ~2 R. H                        pSoundBuf[nCcount++] = (SHORT)output;# }3 C0 ^" ^1 C4 T8 S" X

8 v& v$ F' m3 O, ~% q2 P: g//                elapsedtime += cycle_rate;
0 a9 P$ ~2 O. K                elapsed_time += cycle_rate;1 w% V4 h: w+ p. p4 w' {( B
        }
- h2 [/ ?4 i9 [7 c% Y- x" ~6 M' ?! O3 ^, R2 P
#if        17 |3 W3 |8 V+ G- K9 y) I% g" N
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 g7 ?1 g4 ~, h. k% L% m                elapsed_time = nes->cpu->GetTotalCycles();
) g; G" X- ^: o2 |0 k        }
9 b4 f8 r% H" l$ A+ p% \' G        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 d7 [+ ^0 s1 v2 b2 j$ P# t                elapsed_time = nes->cpu->GetTotalCycles();8 p' U" ^0 p$ q& P* N7 N
        }
* }# @7 g6 j0 y' D$ B% n* n#else
) Y7 [8 B* H. r% L. s2 T        elapsed_time = nes->cpu->GetTotalCycles();, C: H0 H" @. Q- g4 o' w
#endif! S4 G1 h& S% A' ~- l$ ?# S6 m5 }
}
3 k) G  M' j, D4 m
  V* p. U% [# V+ B; E( a- G// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
( k1 S3 ~+ J1 o1 aINT        APU::GetChannelFrequency( INT no )
. w; g0 P* {+ m7 E3 H( P8 {{
1 r* C1 B6 Z4 `1 r/ |- f3 V' a        if( !m_bMute[0] )
7 @! W- H% ]$ u, H/ v/ h6 y                return        0;0 t7 C' H; g3 I; C+ u% l! h) H
" p2 u) m0 a- S0 W
        // Internal3 v4 c4 O7 z. }8 F- j2 q
        if( no < 5 ) {
$ |: L. q/ @% y2 S+ t                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) i; x0 @. g- r2 x; Q( c% r8 I  g        }
* D9 E6 @3 v) N: a- G! R. Q        // VRC6
' K5 y9 A" s$ s: A$ Y4 y        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' h3 y; ^+ V  ?# |+ Z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;6 _2 U3 Q3 e+ W' I+ j" ~3 |- I9 b
        }+ r7 ~7 d' {/ G4 e0 W
        // FDS
: @7 M7 C- @1 k0 |        if( (exsound_select & 0x04) && no == 0x300 ) {
: C4 o' L6 r  i, y7 K                return        m_bMute[6]?fds.GetFreq( 0 ):0;" ~; N; E7 e- e3 o/ I, z2 z
        }
$ J9 s2 N9 q. C) }0 V        // MMC5
. i8 H) Z* d2 c, Z( ?, `0 e        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: w2 e9 b, y5 C6 I' W9 o
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
9 n  [+ R8 x1 {4 _- L! X4 G        }
  R3 u! t' {( J# K# J        // N106
, O- H6 }$ J$ p9 S. {% F: c7 w( V! I        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {2 L. ?% g9 |/ v. }" F$ ^
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: Q. f( N! t* z* v1 |4 @( t
        }
2 H0 ?' |: G" L        // FME7
2 B4 K% L5 U. e2 T        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {+ x* X5 y3 h- b4 I% L0 B, |
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;0 P  @  C* j9 H# U% i
        }$ p6 g. B/ W) T
        // VRC78 J+ d, q: o+ M  S
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! u  a# L$ J7 l0 }' f
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- {# j- F; z% W, c3 B        }
8 Z/ i2 K5 S# z/ K  x  r' a        return        0;, G) v/ A' ?. l
}* k& ]8 w7 E5 e; L+ B- ]( s+ z
7 t5 s# k. J( P( v8 d9 N
// State Save/Load
) k5 l/ A1 N2 @/ G* f! f, l: Q9 ~void        APU::SaveState( LPBYTE p )
  K- C( q7 C* F6 E* m' i, ]5 M{
9 X( ]4 o" ~- w4 e6 E1 H#ifdef        _DEBUG% l) P# }0 @8 F, Y" ^5 p: g
LPBYTE        pold = p;9 Z; m4 K8 X+ R
#endif
5 ~& s2 @0 ~- H9 e- q0 K) M) X$ c! I% q0 b
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
9 ]8 q$ W2 G9 x# \& s* [) y        QueueFlush();# _( B* o! l" o& a2 @
. t5 p; I: v/ v5 m) x
        internal.SaveState( p );
& ~9 X7 @: c! T0 p; G9 |$ k. Z5 p        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& N. h1 C3 y& M. C
- r' Z5 R: q- N- L$ ^  m! g; y1 H
        // VRC61 L3 d" O& e7 ]8 m
        if( exsound_select & 0x01 ) {
6 A7 q8 N& }, w4 Q0 o* a3 d4 ~9 l                vrc6.SaveState( p );
: [( d" t7 Z9 ^                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% c! c* j: N" @, j3 ~) k1 |1 r
        }, a/ ^; U. B2 E8 R- O9 }4 n' m* O
        // VRC7 (not support)# V# q8 @: e- K" ^6 u
        if( exsound_select & 0x02 ) {) e0 H% d: T% N, C
                vrc7.SaveState( p );
0 W1 R9 k' C* l5 B! j$ p5 \/ M                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding, V) y: }* o" [% ]8 f( k
        }7 T: A5 c) `! Y; f4 g
        // FDS
* D' z0 u9 Y" q; X! [5 H8 F& d        if( exsound_select & 0x04 ) {
3 N, ?, V% O) m# e5 i9 g                fds.SaveState( p );" i$ S: s& N9 o: Y3 t# J: P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- A2 ?0 C/ `1 z0 K& I- h5 W  D& E        }
% _  ^, Y6 X+ V( X4 M% L) B# h; \+ k        // MMC5
- b  z6 _7 B& j0 I+ `7 w6 S. M        if( exsound_select & 0x08 ) {+ _9 U# q5 e( y% w
                mmc5.SaveState( p );0 Y3 D' w. }7 @% o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ ~5 ]$ i: r9 Z# P. U
        }
2 P" a  E) @# E$ [4 @        // N106" J3 T4 ~! T$ }( C8 w
        if( exsound_select & 0x10 ) {
! O6 O- Z5 Z& q# ~4 u$ X" I' h                n106.SaveState( p );# j/ S0 t/ t  Q9 g7 r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 G% Q, m6 T$ M! n$ p        }1 m* H' |* Y4 s. E- [
        // FME70 v& O4 Z! }/ _% \1 L
        if( exsound_select & 0x20 ) {
+ ]# N& C1 p9 v2 }: l                fme7.SaveState( p );
1 z) j. l) Y2 z( i! e- T1 c. n/ B                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* N* U5 X+ H0 ~1 I) W# O: P
        }. s; ~! X( p3 Y# u3 p, o
( J2 Q% ?. }2 l2 t% D; }
#ifdef        _DEBUG, {$ j, r+ J, c/ ?- r
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );  v! k0 p2 |0 ~, |
#endif
* ?9 ]2 \1 n* j! r4 w* a}9 c3 Q& a' q: S% Y: [0 W, a  L

+ c0 V+ R& n; J5 rvoid        APU::LoadState( LPBYTE p )
& x* X8 c% Q& p7 S, Q{6 s9 P* |. s% }6 _' q
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 ^5 j& d! i& A
        QueueClear();
, p) ^7 W, _9 d' q5 t6 z
2 A' N; ]9 j; U        internal.LoadState( p );- C& I' f# Y( r+ P% |
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 A! I+ z6 Q& a" g2 w# r3 }+ }, o
/ `( v, W' Y, |  f# x! M
        // VRC6" C7 R4 B& S5 m# R9 P! {# \/ j% Y
        if( exsound_select & 0x01 ) {( z5 v, e: ~6 j+ |4 p
                vrc6.LoadState( p );
0 V* u. I2 B: V3 s9 ~( X- e2 `4 ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- X* z1 q1 f  \        }
% e) F7 k9 R. A5 k        // VRC7 (not support)6 A- q# G' q1 y8 ]* }, H
        if( exsound_select & 0x02 ) {
7 i1 H6 A/ t$ z) F                vrc7.LoadState( p );
* |2 t3 K! z# g7 ]. o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; S: a, ~- f/ C9 b$ g
        }
) S: }$ J: q1 \0 _2 w: `4 d/ G; s) r        // FDS; T  t- ?1 W2 `4 d" W: t
        if( exsound_select & 0x04 ) {7 B  M6 C& p. |6 T4 Z4 ]
                fds.LoadState( p );0 }8 S2 T! {$ D& T! t& Q: s: ~2 h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ J3 v2 F; B1 t! w
        }
8 n: Q# i( A" `        // MMC5
0 o, T9 ^' u) ?. k/ u: K        if( exsound_select & 0x08 ) {
+ P9 {$ }8 R$ n8 \0 @+ J5 [0 a9 T5 B                mmc5.LoadState( p );6 r& ]% n  q6 m+ W0 ?
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! h  K/ s3 V  F0 |$ d% U        }
+ @# K+ K. n2 V; w- v        // N106
! R4 V0 G  s$ ~0 r3 O8 U% z        if( exsound_select & 0x10 ) {
% k8 o+ {; K$ S6 z; u                n106.LoadState( p );
6 z2 L$ u" ]& y0 N- a' c6 T                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding! ~' {- k4 f2 m3 _) r2 P% v0 x
        }
! ]0 D4 x# `/ J/ [  U2 G: E        // FME7
& P1 v7 r% U, r; h  H  r        if( exsound_select & 0x20 ) {
% T. r5 J  c& t& X. @                fme7.LoadState( p );. O; o# ]) i' ?* K8 K8 e$ c; i
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- e! o" R- Q/ u9 J
        }# g3 R5 f# R# x  V
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
' v2 ]- R+ `- i% N  l可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, i8 \9 W  d7 i1 G- H: b
感激不尽~~
( I+ y( s- I, J% G5 M, ?
恩 我對模擬器不是很有研究,
& G. T6 \& }' F: M3 [雖然要了解源碼內容,可能不是很困難,/ p: U( Y+ }3 E4 M
不過還是要花時間,個人目前蠻忙碌的。
! r+ n/ i& c* x2 |2 a% n2 l; R  q6 Z! M% |' h0 n4 W2 {9 n
給你一個朋友的MSN,你可以跟他討論看看,
( y. y" b) s. M, B他本身是程式設計師,也對FC模擬器很有興趣。
% m" ]* Z9 f6 X1 M2 G
  \0 q! R# ?1 Q& a: K* c' D: mMSN我就PM到你的信箱了。
" k+ H/ S  x  y; D4 Y! @/ l
4 T# K' v$ s. _) Q1 v  T0 m6 F希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 , g2 T( F) P6 o" y8 ]
呵…… 谢过团长大人~~
7 B( }) t7 \* z/ L' F4 w) a( u

! `; a% A/ k  A8 d9 q  p哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
( X) w; n5 @9 q# B7 W+ U  R/ D团长的朋友都是神,那团长就是神的boss。
* Z$ l, w+ F5 X; Z& T
哈 不敢當,我只是個平凡人,% z; n' F8 [8 d
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
: Q6 U  B/ R- U9 v" g+ S) TZYH7 D  y+ [4 E# m- @7 X; @: t7 e8 o
QQ:414734306
6 R5 ^& i% I  L  {# bMail:zyh-01@126.com
5 j" H- C- S2 u. B" j1 Y
6 R, {+ j2 X  Y$ [$ y* u7 v他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 k8 F) k- z6 o0 w) C% E6 j% B5 \
再次对团长大人和悠悠哥的无私帮助表示感谢~~

# A* W- j$ H8 `" a/ W, c- o不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-13 07:43 , Processed in 1.105469 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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