EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& I- s/ {" h9 G. M7 G) d8 ?5 h楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- J2 Q6 l/ R: b& w$ s! m3 n9 `% h
这里有相应的模拟器源码,就当送给大侠了~~
/ b; _; ]0 c) b1 h- o% mhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 3 Q) y1 o. f/ o# c+ ]. p
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! K3 d" ^6 `% k. F) V1 j) R* [& @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" H7 q8 p$ q* ?
这里有相应的模拟器源码,就当送给大侠 ...

/ _* _) |( V7 m( O+ H9 ]/ J聲音部分(Audoi Process Unit = APU):
- h# T# Y& y$ Y.\NES\APU.cpp0 Z! }& P2 s# S, q. x5 _0 V, g1 U
.\NES\APU.h
0 h) u. F( H4 V% g( w7 |/ e! y/ y/ @+ t, k; W1 T7 ^

: r8 m& J! r' G+ \1 [' Q影像處理部份(Picture Processing Unit = PPU):
) J1 g7 ^0 X& J+ M2 e1 Y, w% m- t.\NES\PPU.cpp
4 D; _3 Z5 `: q$ [. ^! K& G7 _.\NES\PPU.h8 g1 N0 B: Q- H% H
+ f. x2 C$ E& B' J9 S( y9 B
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 l  {8 k4 V% L  w(由于很多专用术语和算法机理都不明白,所以看不大懂……)
5 Z9 }( D* u# c3 X6 ^* [//////////////////////////////////////////////////////////////////////////
% h' \' I, d2 L8 Z5 y# ?. u//                                                                      //. Y/ ]8 C! c3 A: N4 R. j: R
//      NES APU core                                                    //
1 `$ F) z" W) y$ ~  n3 b2 b//                                                           Norix      //5 f! W5 \* i5 C% A6 h
//                                               written     2002/06/27 //8 {! Z# N9 R% s9 N. M
//                                               last modify ----/--/-- //3 K$ |4 {# {  Z2 s6 P1 g8 C; Y
//////////////////////////////////////////////////////////////////////////
) Y" u6 o5 f6 z' U1 _& u/ j$ w#include "DebugOut.h"
* y* P  E/ z! M: g2 p#include "App.h"2 M" O# y$ X, T6 E; t# e
#include "Config.h"  @1 p% G5 I5 o

1 P1 p0 z3 U2 c+ ?#include "nes.h"
# L: S  F  `; K& Y4 S. |- e9 F#include "mmu.h"
& F4 s* I0 A$ f( z#include "cpu.h"
: b- x/ s7 N  ~/ P6 d! l! c4 p/ D; E#include "ppu.h"
  {' S$ A, X! Y: w( ?- s3 m7 t! D, t#include "rom.h"
( [$ o: D+ S- Z/ Z1 [#include "apu.h", ?* M6 q8 y* U4 N8 g6 `/ i

/ O1 Y; _4 q( F$ z9 F# U5 \9 U// Volume adjust
- i" a  c$ I4 X, \// Internal sounds
! m* {/ w; s& G( N" x8 U. S#define        RECTANGLE_VOL        (0x0F0)
# A# l2 v6 p8 {" p  z1 ~#define        TRIANGLE_VOL        (0x130); Q6 p  _& M. ~4 G
#define        NOISE_VOL        (0x0C0)0 L5 x& Z% v; K$ V
#define        DPCM_VOL        (0x0F0)
. w* z2 D, y  k3 R) b! [// Extra sounds
" e! b. R! s. r6 _3 ~* i2 K/ a#define        VRC6_VOL        (0x0F0)7 ], l' M* D7 d- l2 S5 ^
#define        VRC7_VOL        (0x130)3 i9 p$ Q6 [  ~) M# v, M# w
#define        FDS_VOL                (0x0F0)2 x' a* e7 A# O" W. ]
#define        MMC5_VOL        (0x0F0)
1 h& q/ K) ?, m4 O#define        N106_VOL        (0x088)7 l- V, [# O: C& E. E! ?- r3 x
#define        FME7_VOL        (0x130)
/ s3 x6 g# X  d6 M" s" r
/ {. ]$ K6 S9 V' i5 ^9 o7 d1 qAPU::APU( NES* parent )" r7 w; p2 L# D
{5 r4 t8 Z6 d2 ?
        exsound_select = 0;
  T( K$ Y2 r. r6 i) U& d+ U1 B& P1 H, |9 I+ C, G2 G9 ^
        nes = parent;% a2 M& S+ Q  t0 A4 H3 n" ]/ d6 o
        internal.SetParent( parent );/ v3 i) a0 x& O4 e( |/ L' M/ H
- J; Q- C5 i( w( l0 t' n
        last_data = last_diff = 0;
: r/ R  B7 Y0 g3 p/ C3 P. z
/ C9 N/ e9 X( g' k& N        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: x9 L. D  q/ L8 f/ i
1 Y& N1 q: q  A4 D( V" ^
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ B" g; N3 G/ R$ S. u
        ZEROMEMORY( &queue, sizeof(queue) );
' L8 n: q* ?$ O$ B        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' S$ J& a& v1 `: u' Q
  ^8 [6 q" s3 A* r( H; R        for( INT i = 0; i < 16; i++ ) {
; N3 E5 W) r0 d6 O( G$ [                m_bMute = TRUE;
* I9 E) y+ {: D! |! c' q5 u1 u        }
: R2 j9 s4 Z$ j}! p" k1 H1 Y* `! [8 }
: f4 y' v% J9 @8 I6 Y, d
APU::~APU()
; @! @5 [; T4 u+ l{
9 D; g) j% q/ W}- X6 {1 S7 X* E/ }
8 {9 o7 E* l8 e0 U) n: Z
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: i7 C4 [0 P9 X+ S{
& ~% f6 d1 S- S9 q: J4 e3 |8 o        queue.data[queue.wrptr].time = writetime;
7 l! q$ |: b0 ^* q* h2 t        queue.data[queue.wrptr].addr = addr;2 f0 D* M: e. I' j) p; c
        queue.data[queue.wrptr].data = data;
. D, p8 k+ \+ t- h  o        queue.wrptr++;
5 ]+ v; g% k" k5 }( p; r4 ^' z        queue.wrptr&=QUEUE_LENGTH-1;
! Y. I6 ^- d9 o8 {* g, B! {# r+ i        if( queue.wrptr == queue.rdptr ) {
% @; s$ P/ h& O! R5 W                DEBUGOUT( "queue overflow.\n" );; \+ c$ l6 M. H- H% f2 {
        }1 \6 e+ S' [  p* [5 u1 P3 x
}
% _+ y0 o2 a) s- s3 U# \2 Y6 q( v. e! }) O
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
& g3 m1 A, y1 U% `! z  y2 j8 W& ^{
/ D- y. a: k. Z        if( queue.wrptr == queue.rdptr ) {4 x- e1 N: I; m$ x6 Z& K, y
                return        FALSE;
% j" g, j; ?7 g        }' A) T+ Q  R+ F/ D9 w
        if( queue.data[queue.rdptr].time <= writetime ) {- v1 u  n# l0 W# P! x# w# r4 X
                ret = queue.data[queue.rdptr];
4 F' b4 a) T( p+ Q6 h3 F                queue.rdptr++;
. a. K5 |1 G% ^) Q/ n                queue.rdptr&=QUEUE_LENGTH-1;
. u" c  n% h- l6 f! N8 P                return        TRUE;
. a0 g* V, {; d5 _- e* ]        }5 E. _( x$ G* F3 Q# q) J8 `
        return        FALSE;
% `5 H$ [3 F( \  T6 K" q}, T; \( M. b2 B/ L5 d) h
: I) w! M5 a( z8 m# F  v" k
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )- N: z5 O4 f3 ^' F& |$ s
{
4 ]2 T9 l  w+ `5 `* C        exqueue.data[exqueue.wrptr].time = writetime;
, P- b5 H: e" L        exqueue.data[exqueue.wrptr].addr = addr;
6 R2 u2 b; y2 k8 @, K4 }        exqueue.data[exqueue.wrptr].data = data;
' z0 ]8 E! N+ k        exqueue.wrptr++;% E8 R4 P6 e4 ]: y5 C6 Y5 c
        exqueue.wrptr&=QUEUE_LENGTH-1;5 L7 E+ j7 J- U3 p4 t4 Q! H
        if( exqueue.wrptr == exqueue.rdptr ) {
- n0 [% w: Z3 M$ D5 N- l                DEBUGOUT( "exqueue overflow.\n" );2 o* h: M  G1 _9 z/ z! [8 V( @
        }
% e+ w2 I' s" V5 `6 a5 e; ?4 x}' `' C# T4 x! d/ s, U" y1 u

  H+ z5 a* S0 }* v! R' H. IBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )$ @, C* \4 Y9 s( Y
{1 `$ ^" E/ \& ?) D2 a" ~' R
        if( exqueue.wrptr == exqueue.rdptr ) {, I3 j5 K. i+ z9 Q/ E/ X
                return        FALSE;& S* a6 k/ a* |5 C
        }5 v( J) g! Y7 N- {8 W( z& P- Y6 {
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {$ ]) w* p' g# {* j
                ret = exqueue.data[exqueue.rdptr];% A2 K! Y" A9 D. i/ a; M7 F
                exqueue.rdptr++;
7 ]2 Y4 w8 O+ k: c  h0 s  `2 l                exqueue.rdptr&=QUEUE_LENGTH-1;9 ?, [4 P4 A; a* M- Y+ |
                return        TRUE;
* |% l6 o6 _' V- A3 w# }+ f        }
  d- X7 z- ~' W# V# v# _7 P        return        FALSE;8 m% S- p2 a. y7 T" v" H
}% ]9 j/ ~' O' O

3 q6 L  ?* i* [* ?void        APU::QueueClear()
6 e2 g* @( |- C{' u4 u3 h$ {% w3 ^
        ZEROMEMORY( &queue, sizeof(queue) );" p6 B( i  @6 D
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 J& G( l8 t' r) ^" F6 b. c}
/ m2 K3 K4 o5 W; f- p  S- y2 S- D7 s* k
void        APU::QueueFlush()# o5 _* q1 L4 {% j% z% g$ J- G' v3 H
{
. O2 |5 ?+ C1 T% C        while( queue.wrptr != queue.rdptr ) {: L' D2 |, l1 Q' |
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ i2 G7 S0 M1 j4 l# T/ B6 P                queue.rdptr++;% u5 k. ]' q. q3 [. E7 `& U' v" d
                queue.rdptr&=QUEUE_LENGTH-1;
5 w$ k, T$ c5 M+ S3 w) ^1 \# b        }
: m* R7 W3 h! N' j4 `- @( f: K5 J6 ?3 F" ?
        while( exqueue.wrptr != exqueue.rdptr ) {+ j& ^- g) X' a8 ?4 S- `% R2 }
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
( ]5 E9 A' j8 M' D  F/ f                exqueue.rdptr++;& Z" c1 C4 e7 e) z! j
                exqueue.rdptr&=QUEUE_LENGTH-1;- F7 `- x" A  v6 A' G+ q: E
        }# }% m; e* l- B6 ^) F7 }/ F* _9 H
}
9 s; Q2 }' D4 I# y2 [9 J2 N+ X) y7 e4 ^# W( V
void        APU::SoundSetup()$ {+ R8 Z8 v4 @. j$ S! j
{( e" [1 |; a- d$ f7 M0 Z6 U
        FLOAT        fClock = nes->nescfg->CpuClock;
; U0 M0 X) \$ e5 m" V: O        INT        nRate = (INT)Config.sound.nRate;: ?' V+ q0 U. a6 W
        internal.Setup( fClock, nRate );/ m% U5 ?: ]8 g
        vrc6.Setup( fClock, nRate );( C! I0 Q6 ]0 Y/ D# Y# N$ s9 J1 k
        vrc7.Setup( fClock, nRate );; L0 G% r, {0 {3 \0 E% v# i- u
        mmc5.Setup( fClock, nRate );
5 P7 A3 D1 G% b        fds.Setup ( fClock, nRate );
8 @7 B; s1 m% r        n106.Setup( fClock, nRate );
( B) {! ^' W9 z& i9 U' K* u* g        fme7.Setup( fClock, nRate );+ d1 A* {! q$ `1 G
}
7 z+ t% ?2 A, H7 Z2 q4 s' p, o0 U7 u0 M" i! S
void        APU::Reset()1 H/ s- L5 `  C4 f
{
: [7 p3 H% u2 c) P( D. q  }/ [        ZEROMEMORY( &queue, sizeof(queue) );
  V1 ]9 O5 t- P9 c1 M, T5 @9 z  D9 e        ZEROMEMORY( &exqueue, sizeof(exqueue) );' `. p/ W' W1 A& o1 N9 I( F8 z
) M) W- o) g2 q# R% b; ]) G/ l
        elapsed_time = 0;
2 N5 n" {7 E6 J1 L- {% l# j
/ T' m5 F" V$ I" q1 m  E/ G, e        FLOAT        fClock = nes->nescfg->CpuClock;
& G" n0 a% \$ h        INT        nRate = (INT)Config.sound.nRate;
  W2 e2 [3 C$ x- i        internal.Reset( fClock, nRate );
1 u3 |: u6 O! U0 R, J4 [& T        vrc6.Reset( fClock, nRate );
( J" c6 Q0 g) A" p/ p" _        vrc7.Reset( fClock, nRate );
% {' U7 w- k) I) T  c        mmc5.Reset( fClock, nRate );
/ P; Q) E$ `0 b6 R3 r        fds.Reset ( fClock, nRate );
( I% ^/ ~/ u3 d8 Y0 y$ T        n106.Reset( fClock, nRate );
0 R+ o1 B8 l! g# f8 l3 K        fme7.Reset( fClock, nRate );
) `6 }" K5 P% f7 ~' z
3 w; r  p/ [  a4 m+ _- f" A        SoundSetup();
' Q# o( V8 A" {5 B+ C' O}" J5 D2 Y+ O4 Q/ Q; B; ]2 o
4 d8 D' ~! x  j) V2 T0 m
void        APU::SelectExSound( BYTE data )
8 `/ F/ E- J: ^7 H; e$ Y+ `{
' c% N. s( h# s' r' r3 j, M        exsound_select = data;/ e: ~8 h8 L4 s& ?
}/ r5 E/ a4 U4 B7 z3 C) F& B) M

0 [8 q4 ?: e' NBYTE        APU::Read( WORD addr ). Q( d1 {9 t+ G: p# o4 E
{* I2 u3 t# v) c; o" S# R. ~. }
        return        internal.SyncRead( addr );+ O3 Y7 C+ ]; ~
}- }+ ^; C$ S5 Z* U( x5 v. w6 h% Z7 d

8 F$ J0 X: O3 ?- r6 u2 `void        APU::Write( WORD addr, BYTE data )
. K5 M/ Y/ q  ^{
2 k! Y# z- u6 V- {        // $4018偼VirtuaNES屌桳億乕僩; m; s1 V5 t9 L$ |8 M$ |
        if( addr >= 0x4000 && addr <= 0x401F ) {
, k/ A' J+ a! u, |; x8 k+ h8 V                internal.SyncWrite( addr, data );5 ?2 j1 ?6 ^5 _3 ]- l4 K
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );' g( G$ t4 ^8 S. b  b* T
        }
2 Q- t/ e/ a4 u% h3 F}
/ t3 ]) z" m$ H/ s& A) `8 {7 K/ O9 y' n* o  V; }0 P2 p
BYTE        APU::ExRead( WORD addr )* o1 \6 V& u/ g+ u' R, k5 {
{
* B2 E( K% z. S& J" q8 R  EBYTE        data = 0;6 T: O4 ^5 g% h
0 \. e' X* \% M0 s# E9 G* k4 x: w
        if( exsound_select & 0x10 ) {7 t) u; a6 H( x
                if( addr == 0x4800 ) {
  b# o# Q( }) K. M- c8 J7 e+ S                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* ?* k$ v0 y0 u2 E0 d8 ^
                }" j/ H8 w9 Z( l8 x5 r% Y
        }% g% t& [; L5 Z, ~$ ~. l
        if( exsound_select & 0x04 ) {
3 ~+ `. w8 x9 N: X9 u$ J1 W/ s                if( addr >= 0x4040 && addr < 0x4100 ) {* d1 G: T8 ^! |, f
                        data = fds.SyncRead( addr );
* t* U- M8 p; o                }& L# }( L% S' n7 [' ~
        }
) p* Y, Z# t2 D# }9 h2 t6 K7 J        if( exsound_select & 0x08 ) {
, ]( X8 h3 I7 _" R( R                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 Z( \3 C2 ~, j2 G& R! H5 v; \                        data = mmc5.SyncRead( addr );
' @( K# f; W: B7 y, L# ^                }
* z2 y. u: q# a        }
" |) m% ~$ h1 r2 B: T" U
! e: I. j3 h6 D! ?. p4 J4 l7 U1 H        return        data;# F: E, H* i+ x* E4 u
}5 q2 Y6 o, \' F: c: t9 I
4 L7 }9 G# V0 z' ~+ Q8 G
void        APU::ExWrite( WORD addr, BYTE data )6 a2 D. \$ ~6 n- ?
{
8 M& L6 T6 h$ r6 A; X* ?: T        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 f% a- A. v& `! ]/ l
" E9 O! O* L( c4 w        if( exsound_select & 0x04 ) {. O5 W* a8 ~% _3 s8 K# R
                if( addr >= 0x4040 && addr < 0x4100 ) {
* H- R1 H4 O& k  P% j) ?                        fds.SyncWrite( addr, data );
$ m8 X  i( R5 K1 M* t( K                }
7 C$ C& h) M* u* }1 c  {        }
3 F( s( ^+ a0 A! r8 o" B( R/ T8 v* [1 k9 w; }' J7 _2 R9 V
        if( exsound_select & 0x08 ) {
" u7 ^! V! g' _: T" G3 c2 p# i                if( addr >= 0x5000 && addr <= 0x5015 ) {* c4 J% C$ D3 ]
                        mmc5.SyncWrite( addr, data );
. _6 O) a: E& c* g                }
/ w, U' ]! z7 r3 y0 R        }
( M/ U+ `* e: d( A7 h}
7 F4 T# {: H. n# o* f5 Q5 g- [' ~/ f* G9 P6 b
void        APU::Sync()
6 o9 [" n& |" T; w4 }2 L* W{
, L5 I  A' E0 n}
, ~3 {# p7 C- e" W2 H) Q7 H/ C2 Y8 r  P7 s" z; q6 E/ E
void        APU::SyncDPCM( INT cycles )  w5 }4 q5 o2 n! b. X$ e3 e
{
& c6 L" B. C: i5 y" F        internal.Sync( cycles );# U, }7 B/ f; h  N; V2 m
$ a3 i% x2 S- G" L
        if( exsound_select & 0x04 ) {
8 a& j# a+ e' \9 H                fds.Sync( cycles );* V( Z1 Z( a* Z6 Q9 u5 L; h
        }
9 h+ v5 u9 k5 E: }; N) F        if( exsound_select & 0x08 ) {
4 F3 }* W  g8 t+ k) u8 D                mmc5.Sync( cycles );& C6 l2 y5 I2 P; f- c( ?
        }
8 U. C& G/ @  f}8 \9 d7 ]/ P, X' R* \

, L, N: A% ], |' B# H; ~+ ?void        APU::WriteProcess( WORD addr, BYTE data )
/ L5 V& h) d2 F  J" `% S{+ f6 q0 W" Y' i4 A% k3 M
        // $4018偼VirtuaNES屌桳億乕僩" K7 L; V  ~( b5 `( g( j7 b
        if( addr >= 0x4000 && addr <= 0x401F ) {5 Q, b# Q# U; Q: t- h" n
                internal.Write( addr, data );  Z8 V, F& f9 a+ p( U) E& \3 H
        }, z$ o2 O& a  J. `5 y1 d7 j$ W
}* ?9 d* @) D' K: y. F) @

( i( ^/ h5 i8 v7 p# M9 Z7 }void        APU::WriteExProcess( WORD addr, BYTE data )  Y  N* r6 M- k2 s, ~. c( a
{
- j2 x$ R, k4 O/ m        if( exsound_select & 0x01 ) {' w3 K) W# j% Z/ |5 a* _: B* ]& m- q
                vrc6.Write( addr, data );
- }; E/ Z# j. W$ f        }
+ |& a; U! B7 S        if( exsound_select & 0x02 ) {0 g. u( g- B$ ]
                vrc7.Write( addr, data );
: Y9 P% e8 Q7 f5 o4 ^        }
) C. ]9 w* J- O" r6 n3 R: W8 x        if( exsound_select & 0x04 ) {
2 r! T2 h# l9 x, q' G1 e                fds.Write( addr, data );
: W* ^* |, H! b! `6 w' x' u        }
# D& }1 @  u  q7 p( L! ?" n        if( exsound_select & 0x08 ) {
# `& ~' c$ `' H% W7 G                mmc5.Write( addr, data );& J( s3 M+ b3 A2 f5 l& n  R
        }+ {" r6 M# {: o- v( `/ B% J/ s
        if( exsound_select & 0x10 ) {2 I; S6 h6 M% A
                if( addr == 0x0000 ) {
* t- L: `' W- U& Z                        BYTE        dummy = n106.Read( addr );
" V7 J2 n% J8 C/ N                } else {
/ Q+ w  T8 c& M. I: i7 O3 c                        n106.Write( addr, data );* }  Q* H) ^( [2 H& c+ y. K
                }; l6 b3 ], Q; z! u; v
        }$ B5 L! {" U3 Z; a
        if( exsound_select & 0x20 ) {: L3 q& Q( i  o8 A$ E6 ]$ u
                fme7.Write( addr, data );: h/ V) N9 X7 I' p
        }
9 T9 J, _$ a6 G" j2 Y9 _}7 B' }+ c3 d% V1 i

$ h  ?) _8 F; Gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )1 b( U) H2 I7 R- |4 v+ U
{0 b; o. M& V7 L3 K( ]2 h+ J# o9 E
INT        nBits = Config.sound.nBits;% ?# B! M- J  _3 k6 b
DWORD        dwLength = dwSize / (nBits/8);
( n# A1 ?9 h0 `INT        output;
2 S( r& r& Z. D1 U, r6 ^QUEUEDATA q;% ]! Z9 V! z5 [6 u
DWORD        writetime;  k  U9 O( n  F$ S9 p2 J

& E3 Z  _4 I& `/ XLPSHORT        pSoundBuf = m_SoundBuffer;  w6 o0 I  c, i& C' K
INT        nCcount = 0;" B0 V* W8 u* s+ B

- P  G1 R. ]; n* V: N- k5 H5 ^1 _INT        nFilterType = Config.sound.nFilterType;3 K- B5 l# }0 k: v

# B1 y' @. I4 N. k3 g3 X        if( !Config.sound.bEnable ) {
. K5 U# k$ G) r) b                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# h/ P3 {9 V( i, P3 s                return;
5 i% L9 ?( {1 n% W. _1 A/ {        }
7 U0 A7 w+ P4 w, g9 b7 I6 W3 Y6 p- v7 r4 y  c3 k  Y
        // Volume setup( h$ P% C  @4 _% l2 }3 K
        //  0:Master2 l2 N) \4 V9 W7 @% w* c5 L& N
        //  1:Rectangle 1
) f8 n+ I2 |# S( \; z, ]        //  2:Rectangle 2
, H) m; h! f8 x1 S( d( Z) P, v        //  3:Triangle; \4 ?/ Q2 ~; [  a; F+ A) O
        //  4:Noise
' y# q6 \- Y+ S: W6 d        //  5:DPCM
- j5 G7 ]3 ?6 h        //  6:VRC6& u- C. V0 V: @  C
        //  7:VRC7
' P9 e  q& ^# y$ {: D8 D5 W        //  8:FDS+ t# m2 V1 h7 l, k0 k+ S
        //  9:MMC5
0 _# L' h6 C" m3 P/ N" _        // 10:N1060 D5 Q+ _& h7 P: o  z
        // 11:FME73 m7 w3 f9 K! D8 K0 M
        INT        vol[24];
+ B5 K/ m7 x: t6 G3 W% C# Y0 C        BOOL*        bMute = m_bMute;
4 A$ h: ], |* n+ w5 R" ^; g! z        SHORT*        nVolume = Config.sound.nVolume;8 f- I1 D# K3 Q" F" Q0 j" d9 M) A; p

0 H. X$ |8 s' @& _  \% ~        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 R1 W( S' ]% P+ W& ]! Q

+ \5 v5 k" n" x, p3 H, I, ^8 r        // Internal
; S1 j9 P! u$ J& U  d2 w$ W0 G        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 V0 }. M# G' ]- \  \/ D6 |# h
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
+ w+ n- n* s( p* `, u4 j        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 g5 ^8 h5 [! R* V) r) j. U/ p1 k        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;1 W: E* v7 E5 O1 j
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;. C, V1 }+ h/ z! w/ ~7 r
( h% J/ m/ L' \1 @+ V
        // VRC6
: m) C4 @. |: X7 p& R        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ m# @- J  H/ d' v
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 B; k3 S9 O; T% X; i* p
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- Y7 }6 G0 y) C7 _, Y
& ]8 ~9 `+ F% f, y5 I4 R        // VRC7+ ?6 u* L& T! ^# g+ S- {' |
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;' P. [. A0 Z6 @! ]* j$ n; K
0 b$ i1 z/ Q( B! h$ s
        // FDS
2 s5 }5 `: _0 I$ c        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 K, @, L7 w% E5 g1 n# T

& d" A1 o: f' b2 u        // MMC5( m: ~3 F( {0 K, r- |
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: A$ W) r2 I3 S: j8 g
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ r4 J; y  Y  v: N! S' J
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 O9 W5 q+ h0 I, w6 A9 r" H( [
5 L9 e4 g, Y* u) x, S# q) T        // N106) ~3 h  a& C+ T9 d1 s8 j
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 X# }6 u+ L6 ]: i2 D$ X
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 `/ t3 W! A* d" L3 T; k
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) h* X7 W6 ~  [% R9 X9 I        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' R2 l7 D& F5 J* N) `        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) i9 V& ~- H( }7 a8 c% S        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- J1 \  q: x2 v# L8 l6 M
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 G! u( F0 U6 m3 q. q
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 m& c' [3 z" P) n9 ^8 v3 O: H- R$ A2 u8 C7 d. Q. N
        // FME7
& Q3 J' C5 N5 Z8 U) b  J        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& J( c5 N5 I8 l0 Y: ?; }8 E        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) A% |0 Q3 l' A5 W; j. Y# `5 _- s
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 V) S: y0 s) {; r5 T0 }3 x
6 Z- }* X, n6 h0 v& K
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
# v# \6 c0 A5 t  k! P/ a        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;4 M/ a; h& e& f/ s: x
  d* t- \* S2 G5 i. C
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟2 E; ?5 B* P( [( g' @8 `
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {3 @+ i, Z- V3 Z
                QueueFlush();
6 g/ k0 D& S  [; o        }
7 \( l4 A0 M, p+ B. Q) q2 [$ \% O) z0 a/ s
        while( dwLength-- ) {" }6 x- [( B" u+ b& M% u+ ~5 O+ s* G
                writetime = (DWORD)elapsed_time;
2 p  P1 S( q& m: L/ v+ t7 T& c- C: Z3 N9 y3 Y5 r3 n
                while( GetQueue( writetime, q ) ) {
% i( C3 E2 B" `% W                        WriteProcess( q.addr, q.data );# r4 c+ X) n4 R* D( t
                }
( p/ g/ m, v! @  ]* C& p& Y( _
+ V7 r) z) U5 Q# x; g7 v                while( GetExQueue( writetime, q ) ) {
& o# Z: b8 H3 t/ V                        WriteExProcess( q.addr, q.data );" q8 F" Z  ^, v( k7 m/ N  b9 A2 l/ k
                }
( U9 T- L/ O- m. y/ g- E7 Q8 q! r" n0 N
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ B. a- R) x+ P# }  t
                output = 0;6 _# R4 h( F$ K; k" \/ C3 |3 t
                output += internal.Process( 0 )*vol[0];
+ l. J) [& C; I- t                output += internal.Process( 1 )*vol[1];9 Z# q' V: ~% C5 i# b
                output += internal.Process( 2 )*vol[2];8 q' ?. L% K* d4 Z# r! V1 ]0 T
                output += internal.Process( 3 )*vol[3];
' {! o5 K, }  h! o) d! Y                output += internal.Process( 4 )*vol[4];
3 W1 q; v4 N: r2 L6 b5 Q8 U) f0 ~8 q4 [
                if( exsound_select & 0x01 ) {
" j5 r5 o5 U% k6 `" k& [& L                        output += vrc6.Process( 0 )*vol[5];- A/ x( S1 j5 v; F+ ?5 s0 U4 y% G
                        output += vrc6.Process( 1 )*vol[6];
: m# Z4 [: @' D                        output += vrc6.Process( 2 )*vol[7];7 p5 X$ H0 R. P. X) S7 q' o
                }
3 @- {0 i; }# N* _# s* G$ ~0 q                if( exsound_select & 0x02 ) {) e4 u7 C' ], E, b( D$ i. I8 u& T
                        output += vrc7.Process( 0 )*vol[8];5 @, i# _; o3 h% H
                }
7 q& C+ M, I4 d) ]' i$ D                if( exsound_select & 0x04 ) {  X/ U/ Y* Z* i9 {% f5 T- d
                        output += fds.Process( 0 )*vol[9];3 U- w6 i& N! u7 m+ @8 a
                }) v1 V2 x0 N6 L* y" q. E$ C
                if( exsound_select & 0x08 ) {
& B8 ]; `* H" t& P& F8 d0 u                        output += mmc5.Process( 0 )*vol[10];6 F$ d6 p  x% @) x' f  \' S6 g- w
                        output += mmc5.Process( 1 )*vol[11];" v' {9 l4 ?% W: e& \
                        output += mmc5.Process( 2 )*vol[12];
: ?# J, C6 Z/ t4 I                }
( E$ h! ~, q" E6 \                if( exsound_select & 0x10 ) {
8 F7 ~, e7 n% ]' q6 V# c3 m7 k4 `: c9 B                        output += n106.Process( 0 )*vol[13];
. r+ Z3 q; d* ~7 W. n) G                        output += n106.Process( 1 )*vol[14];- p/ U# k6 e9 V9 g* |5 @
                        output += n106.Process( 2 )*vol[15];
8 w1 y% \6 z5 X$ Y+ R* K                        output += n106.Process( 3 )*vol[16];0 X4 p2 H- |4 E: L: g, D: R2 \  \
                        output += n106.Process( 4 )*vol[17];
! b% D' x) o4 ?4 ?. E4 `/ F                        output += n106.Process( 5 )*vol[18];
0 {/ ~* q5 o& |1 p: c                        output += n106.Process( 6 )*vol[19];  @' E& w. T4 S1 n
                        output += n106.Process( 7 )*vol[20];
4 U. s8 W5 P' N  t- {                }
" M; A9 C; p: h  C                if( exsound_select & 0x20 ) {
' c1 y1 `" S& x# e                        fme7.Process( 3 );        // Envelope & Noise+ r7 t' y3 S3 i& U, A/ r2 V& M
                        output += fme7.Process( 0 )*vol[21];: e) O0 \4 ?, {. D; V
                        output += fme7.Process( 1 )*vol[22];9 m% F. l% {/ `, ~6 }8 n+ Z
                        output += fme7.Process( 2 )*vol[23];0 V2 i" ~  C6 ~& S
                }8 x7 Q' T0 N9 i" o
# u* R& w0 Q& a2 @; B) U+ r
                output >>= 8;
# c' O/ q3 w4 z" Z8 @
2 |7 x5 q: \4 F( z& {# F. [                if( nFilterType == 1 ) {
3 `' Q) D3 w. O6 @9 O                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)" V" H; E$ q4 l0 u
                        output = (lowpass_filter[0]+output)/2;) _1 C; c  m% Y0 f. L% v$ [
                        lowpass_filter[0] = output;+ w: S3 B$ j6 T9 L6 O7 I% _' j" J
                } else if( nFilterType == 2 ) {
+ A5 R! e* m, i$ H; X( z* I                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
' U) X5 Z: V5 t, ^, c( P3 p/ ~                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 ^: O& p, m% ^/ D/ L
                        lowpass_filter[1] = lowpass_filter[0];4 l7 Q# C4 K; Z
                        lowpass_filter[0] = output;
. [; V5 ?1 f* v/ f                } else if( nFilterType == 3 ) {0 K/ G1 _0 T) _6 p' S& k
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
+ R8 Q, T0 c/ ?, d9 _% ?                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;! L4 w1 c  Q; I3 _. e7 G
                        lowpass_filter[2] = lowpass_filter[1];( e' U8 ^/ E) a# D
                        lowpass_filter[1] = lowpass_filter[0];! X* Y( V* x1 @5 v* d: g
                        lowpass_filter[0] = output;
  _5 z4 m0 _  J" ?* y                } else if( nFilterType == 4 ) {
; z, r$ O/ X0 W4 j  o                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
: G; @4 a6 H/ a* P* E: a: M                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* W' w; [$ p1 n# l+ i                        lowpass_filter[1] = lowpass_filter[0];, X5 ~, k  R3 _: W8 [
                        lowpass_filter[0] = output;/ V( k+ u; f8 {
                }4 ^  c- p* F# X6 g: V
& ]; M3 R" r- N3 N
#if        0& |/ d( D# w% E# F5 p# D3 @
                // DC惉暘偺僇僢僩0 I" j* V' T$ e( `/ B3 P8 P
                {
' u( R4 K( `, u: ~                static double ave = 0.0, max=0.0, min=0.0;2 n2 ^0 @7 r% Q0 B& Y6 q7 G
                double delta;7 l+ d2 `% A1 Z$ I' G! K- w% j
                delta = (max-min)/32768.0;$ `% g. x- F) Y1 u" }9 T
                max -= delta;4 ^% P9 k! Q- n  H* z7 T( T
                min += delta;
8 S" f9 I2 a5 _& F( C( N# g1 Q                if( output > max ) max = output;
- \# k2 L0 b) h0 s$ R9 C: \( K& V                if( output < min ) min = output;& }5 n2 w; e: X2 c' G! s
                ave -= ave/1024.0;
" D0 S% r( N' D# k: k4 \1 b                ave += (max+min)/2048.0;
! v# n; A% j; d4 h$ O                output -= (INT)ave;
7 [3 ?# x: |/ p# S. c- ]8 u                }
" b. T( z6 x6 H# ~0 P$ d#endif
" L0 H" A. w' ?0 O5 g. r#if        1
! ]: s# k, N$ `" ^' @2 ?                // DC惉暘偺僇僢僩(HPF TEST)
5 L! i' i  `' \% t8 g                {
/ H+ C: n. R, Q) Y7 ?! x1 l9 d3 E//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);- }$ u4 `, s- H( a& o
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- e& ]  B6 a! q: \( z! f% Q2 H3 o                double        cutoff = cutofftemp/(double)Config.sound.nRate;" J7 o2 M" d/ v
                static        double        tmp = 0.0;
3 w; G; d; S6 t9 k( a0 ^                double        in, out;
; j1 Y) @5 C% X% m+ w* p' Z$ e& a7 c  m- z
                in = (double)output;9 Z6 n) h& I$ T$ y
                out = (in - tmp);" h# b8 _- u3 u
                tmp = tmp + cutoff * out;
% V3 J- {9 ?8 ?( }9 c' H
/ a! J; g/ k6 L6 v- U% V  J                output = (INT)out;& T$ Y) i: U$ G, h( F3 c1 h
                }$ u5 ]$ o  ~8 B% _5 [
#endif
( z8 [" C; r5 O" J5 W: R#if        0
0 n/ ^* B9 r+ N( V) j6 b- g( N                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
6 s8 v8 b9 N. e                {
7 n+ c$ n& X1 {+ L" d+ e* t                INT        diff = abs(output-last_data);" ]  p, ^) k# R! B" l
                if( diff > 0x4000 ) {( T. E. [' c. V
                        output /= 4;
. e8 r/ i& E5 G9 T                } else
8 P- |0 }" q- b* {9 \# R1 i                if( diff > 0x3000 ) {
6 V; ]1 ]- O- O4 S                        output /= 3;
! G/ _- l( A! t" E# N+ A                } else1 h1 O! E$ w! r
                if( diff > 0x2000 ) {! Z) a  g0 d  [  x1 [3 s- G/ t" \
                        output /= 2;
. B/ @/ R. l% z, Z& u1 P1 @9 Q                }
) |- a7 w! i, I9 X' x( u, P                last_data = output;$ F$ h' _) D  `
                }- [5 h2 m# |/ Q- q# ~7 C/ U
#endif9 A. \8 ]# W1 L
                // Limit
, W; _' D) v4 ?1 m                if( output > 0x7FFF ) {
- M0 z' x5 A, Z                        output = 0x7FFF;3 d/ Z9 y. P) d; U4 A$ v
                } else if( output < -0x8000 ) {9 b9 r) W5 S# g$ H2 e
                        output = -0x8000;9 _) B; }9 v6 c; W3 s% q8 }9 ^7 x
                }
- S& N2 H- F4 c7 H! `- Z- S/ T+ z# p' e: C( h
                if( nBits != 8 ) {
2 Z# M5 ?# Y& D$ q  j                        *(SHORT*)lpBuffer = (SHORT)output;
! `2 `& T% d4 d3 b! A7 L                        lpBuffer += sizeof(SHORT);/ b8 X/ Z: V+ a. m8 h2 H" g( ~9 \
                } else {) O" g$ e# \: V; r9 ~+ E0 r
                        *lpBuffer++ = (output>>8)^0x80;7 \# j% M" B" c6 o
                }
8 `4 y% W3 Y% t) [& \) c! X) r' a% O6 \9 Z/ s: e
                if( nCcount < 0x0100 )( t2 B' K; [8 }
                        pSoundBuf[nCcount++] = (SHORT)output;
) y5 q9 y3 \% p. s7 l( D. J# f8 [7 {
//                elapsedtime += cycle_rate;7 r; P) V, d: ~1 L1 }" Q3 o' ^
                elapsed_time += cycle_rate;
& D  U& _" m% ]9 Z& O/ e* X        }
0 X! y3 }  r0 |) A7 ~3 O4 D' o/ f# ^
#if        1
+ J, X6 ~9 H. n% C        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {! `5 @( c5 b4 v) Q8 j; Q
                elapsed_time = nes->cpu->GetTotalCycles();
! m. g" E! Q9 }" F  C5 {& l/ u        }
! O1 Q! c" k) Q' k7 I        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& N0 J% ~& W9 e" E# R
                elapsed_time = nes->cpu->GetTotalCycles();
! Z& ^' ?3 ~: I) |- |& [        }
6 M2 ]; N* n6 D" v6 F6 T5 [: |#else- |* u5 I% x2 ~1 |
        elapsed_time = nes->cpu->GetTotalCycles();5 Y& E8 S  b7 J' ^
#endif
. C% F2 s/ p$ j) N% C; d4 V}
, v( l% O) z/ K) ^
3 d9 m3 @7 W' K# L// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡). `+ u8 j$ z& y$ l6 c& {
INT        APU::GetChannelFrequency( INT no )& E4 J7 `4 O! I5 \% e
{0 ]" Z. |  w5 p( H& |2 Z
        if( !m_bMute[0] ). _3 Q& ]% ]& m2 i
                return        0;
9 O" n' [; g" G% |4 G2 z
5 T1 U' M/ C5 G- l        // Internal
9 O5 ?' u+ i; Y$ U  k        if( no < 5 ) {, I5 n5 Q4 R5 x( {0 Q# `
                return        m_bMute[no+1]?internal.GetFreq( no ):0;4 [. J% a- H, c
        }+ U! L: U/ U8 Y" E5 p
        // VRC6
$ N0 B& k$ ~) l; ^8 b7 {. t: B        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {  y+ U; y/ X( M- x- w! z: O
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;: @0 C) j5 M: m5 x
        }; |8 }/ N$ K! i
        // FDS4 Y! ^1 N/ u  {0 L8 m. G
        if( (exsound_select & 0x04) && no == 0x300 ) {
  J+ r9 Y6 T/ w  X4 }! H7 P% ^' b                return        m_bMute[6]?fds.GetFreq( 0 ):0;
+ h  D3 {; {* f* u" O4 P: C% v        }
9 G, U5 S# K1 {: s" P        // MMC5
% o2 B) I" t& X        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- ^6 y# E' {- T8 S- _                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;- S9 q! G5 O/ I2 o
        }
) z0 b; ^1 i- w1 m* S/ \9 Y        // N106
+ b3 E; _/ E# ~- a) H. ^) d        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
3 T. y) b; U9 w, U1 R0 \9 F6 L, \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;* o+ d! T5 D* V; y
        }
" U# O# |9 S, L, x. [; |& J        // FME7$ t( Q( R4 Z2 G' q7 c
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
( c: Q% v/ q" H+ m! I- y+ S                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;2 p8 ?: q% m& F' z
        }8 e' m! Z, c, F; z
        // VRC7
7 r! ^" N- x  ~; Q& L- N        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 e7 \" @2 d' U& _0 q, ^                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;6 U( h1 w( M( p0 S+ f
        }' u! O" q7 H0 [0 p; Y& n
        return        0;
8 N, X4 c% B! z6 t% @}
4 z3 H+ J, J- C
) c: M2 T. U0 N1 w( C5 @* M// State Save/Load' m2 `2 h6 O+ n
void        APU::SaveState( LPBYTE p )* y3 p& K5 U. z9 i
{
  e7 t+ i6 y4 J& m#ifdef        _DEBUG
, ~  m" A! S% j& jLPBYTE        pold = p;
/ M$ p0 f3 Z' W+ J( d#endif5 r6 E- {' X2 W/ |

9 Z3 n2 {& n: X  U+ n, D5 d        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
6 o$ s, j; r% z. Z9 o        QueueFlush();
7 K4 g, O/ C' h- a- u. o  g6 ]" n* C3 j, q& J( h, A  d
        internal.SaveState( p );
  K3 F2 g3 A# _& b& H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ o) C$ [' I4 m* m. a
4 ^2 G" r) K3 J4 t/ ?
        // VRC6
: c1 L% ]1 f$ r5 X- a) z& k* R        if( exsound_select & 0x01 ) {, n+ Z5 f0 ~% t0 l' _
                vrc6.SaveState( p );; a) \4 @4 ^0 ?. x- G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' U9 n1 k7 d. [" g        }: _$ W' j$ |% W  L! |/ m
        // VRC7 (not support)
' c& c) K; r, u3 L7 l& F  S" M7 A        if( exsound_select & 0x02 ) {/ a/ v; {' _  X' m! p! d% [; t
                vrc7.SaveState( p );  h; x5 k- V0 k$ D8 x" ^: O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 v1 ~) T, L5 x        }
0 A* |- _* U$ \3 b$ ^        // FDS
/ j; m9 c1 _& E2 W9 x2 B        if( exsound_select & 0x04 ) {$ P& M* J4 d7 I1 g
                fds.SaveState( p );5 W0 J% w0 Y# f$ R  G3 z/ n+ E
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! V! e9 b+ [$ |3 A! I- ?        }# k3 ~# l' G( |
        // MMC5
; h" ], O9 ?& ?5 D4 ]3 N        if( exsound_select & 0x08 ) {
* K% ?* o- f3 p0 E8 |7 d4 p                mmc5.SaveState( p );. c0 ?; C, U9 p8 `0 H; {* I* w
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( y' l4 p; N: w; c; E/ x2 r+ K
        }" d4 l! r2 s0 e; K1 z5 X& L3 V
        // N1062 N( P1 X% I3 d6 O6 b, _
        if( exsound_select & 0x10 ) {
" v1 I& v$ U! A! A4 S6 L& A                n106.SaveState( p );1 \: L3 W8 Q4 `& U  q. |7 R3 e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 K7 i# l/ D! T1 z3 l5 q
        }1 e: q) p5 c9 g+ i2 Y: t8 s
        // FME7
9 `# b) v2 v3 b! `9 h- V, L, N        if( exsound_select & 0x20 ) {
7 V& T* {1 x! d" e+ r' e                fme7.SaveState( p );& B8 x& r- r9 ^
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
. ~# V; q7 w) z9 t; e7 H        }2 W! |, h/ L- W. A! x% Y* x: Y9 c
1 W$ e( p( m& A  j" L! Q
#ifdef        _DEBUG
9 T+ Q7 a; |+ T( nDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
0 b; d% O7 ?/ A* F& ?4 r% \# b#endif6 i% P- o8 L5 B7 Z; [
}
! I3 i. _6 z5 m& r5 H: w0 [, R4 O/ p
void        APU::LoadState( LPBYTE p )
% a* Y/ ~* J) N3 ?5 O+ Y- X{
; j4 M  W3 \  ?! C& R" n( F+ c* n8 \        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
: G% V3 y  b. h/ Q! R8 j6 @9 \        QueueClear();
3 l/ W8 m1 d/ U% i! X- q7 I
+ J$ H  Q. p1 y+ ?0 F        internal.LoadState( p );2 {  }$ R$ w. m* }
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
: ~! B9 v8 z  B$ |( Y! b5 L  g8 u1 F; D
        // VRC6
- M7 b, E. Y( W: c1 i& V# B        if( exsound_select & 0x01 ) {
8 j# w" L) F: X  c- k* @: d) I                vrc6.LoadState( p );
3 v# I/ Q4 s5 q" N0 K                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
& V' k; r1 Y% q& Q' v0 s        }
! u9 d1 I0 o* X& J        // VRC7 (not support)& O# u" A. T0 d6 T
        if( exsound_select & 0x02 ) {& ^. Y2 _+ p" _0 B1 J
                vrc7.LoadState( p );
0 N: O, M" [3 D) F                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, A- o, `6 n$ _' D1 K        }4 N% i9 \8 @/ }9 o; U% ]- i5 ]
        // FDS
! Q2 g7 B. w4 N4 V9 j        if( exsound_select & 0x04 ) {
3 b- a* k  G/ y. T                fds.LoadState( p );3 l( b# l' M) x: v1 h5 I+ n
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ x' H( C3 v0 D4 o2 c* X# F        }! C0 p$ ~$ Z. t1 {* ?8 N
        // MMC5
( L& z$ x4 g! Z" ^) R0 |        if( exsound_select & 0x08 ) {, S7 s; C  }) C: ~
                mmc5.LoadState( p );$ {  u5 X; h+ U5 c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding. R( C+ o! d% b6 P
        }
2 x- p, l. _) H2 F9 i! m- O        // N1060 O- A  {: x" W; Q# Z8 _$ w
        if( exsound_select & 0x10 ) {
; Q& \! H" e9 D& ^# V* m8 k4 k                n106.LoadState( p );6 M- K5 R4 W) p/ p" \
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ {' m- s" z# {$ a  |9 q
        }
3 F' k* N2 S6 s) k        // FME7
. a1 a6 ?0 s4 Q# x% Z7 u        if( exsound_select & 0x20 ) {/ T$ w* U  O& b' u! _
                fme7.LoadState( p );9 @7 M/ [$ D) _" f& }) L/ B( @6 L
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 z; y. }# U5 X( q  J        }
% ?# P( \8 O. p) U}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 Q  B8 f1 d% K/ T% m# p) Y# M可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 a  U: O( z' @感激不尽~~
1 k8 @& Y5 e; j0 ~7 {6 a2 Y7 I
恩 我對模擬器不是很有研究,
, |. O) c" ~% S/ \' v% P雖然要了解源碼內容,可能不是很困難,: ~0 i* n) c' q! G) `& U
不過還是要花時間,個人目前蠻忙碌的。
0 w- z. a% p* L* W, k, F+ l6 J/ c( d& H! ^6 f6 m
給你一個朋友的MSN,你可以跟他討論看看,5 W. \: J! n0 _: O3 a
他本身是程式設計師,也對FC模擬器很有興趣。9 `* v6 x* Z) \+ E1 v2 n- ]. o2 v

% B0 \9 M" B9 C5 n% `& Y) _2 bMSN我就PM到你的信箱了。
0 b7 {1 F  M/ f! w% I' o8 ?6 y; }  |7 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 发表 6 ?- y$ X( R+ m( G
呵…… 谢过团长大人~~

+ j8 Y% p5 J2 b. L" z5 ^5 p
6 ~9 S' [# m* R9 v! O) g" b9 V, o哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 2 q) F( ]+ g. ~8 s' U+ r9 ?; `3 Q
团长的朋友都是神,那团长就是神的boss。
4 o6 [1 T1 Q: j, ^: |* n
哈 不敢當,我只是個平凡人,/ _3 _- {1 }* r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
: k0 X; J& v2 A' n" U3 z' kZYH
* Z. @( M# J" wQQ:414734306
7 a3 [* V4 ~. F6 G; E* |Mail:zyh-01@126.com4 V3 t5 h( f& c1 e
0 I' |- e: z; F. _! h
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ) E" k6 u/ F; |2 G3 e$ I0 E! H
再次对团长大人和悠悠哥的无私帮助表示感谢~~

3 c# r" ~" k$ x; f* ]不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-5 12:10 , Processed in 1.082031 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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