EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& U( Y& f/ A8 o  D楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) s9 j  V: q2 r$ G% h- l' c这里有相应的模拟器源码,就当送给大侠了~~( g0 _" i4 v: u3 u  k
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 - Z2 n0 e) m/ g1 E4 |$ B
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! ]: ~$ N! \# W& Y+ Q& \) Q$ U- v楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; t' K, z% y, L. d" D, g4 `
这里有相应的模拟器源码,就当送给大侠 ...

/ `, y  m. u1 L$ b7 x1 v7 V% V聲音部分(Audoi Process Unit = APU):
4 d0 o8 a) B; A( x.\NES\APU.cpp- ^' B2 K/ O7 w( W; A
.\NES\APU.h
% V9 d9 p9 L, @% U
% w/ k- M; {  f, c" e+ G! }* }* @" }- V9 T6 Z4 h5 {
影像處理部份(Picture Processing Unit = PPU):
1 o: q' J+ x$ o.\NES\PPU.cpp
8 V. Y. U* \* T# }0 D# T/ A+ \9 A.\NES\PPU.h5 m" Z; c) d4 i9 K* d
4 @( ]/ s( @4 D  c& J. P1 H/ u
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; E; U# D$ N, H' Z% M
(由于很多专用术语和算法机理都不明白,所以看不大懂……)- v) U; g: C" X
//////////////////////////////////////////////////////////////////////////4 v# Q# A. d% j% a3 N1 G
//                                                                      //
, J# |8 f: k- f//      NES APU core                                                    //: p5 T7 P* w; S* R4 m- `" L" X
//                                                           Norix      //
; r: Z/ k# A* Q4 r* ^6 T6 i$ y//                                               written     2002/06/27 //
# ~- [1 z' p& v. i% L2 ^//                                               last modify ----/--/-- //5 q0 |* ~$ R9 y' l' t) @1 N
//////////////////////////////////////////////////////////////////////////+ A: {3 a& n7 L/ O, v( w
#include "DebugOut.h"* D) H- A: G6 v  f, K/ F2 Z
#include "App.h"$ y* _. g1 Q6 K5 U% {
#include "Config.h"
) E* J$ ?2 T+ Y, l% k* s0 q2 V( w. o" Y9 ^/ @
#include "nes.h"
3 H8 b8 Q0 }# Q- z- `3 [#include "mmu.h"
- C1 l# [9 Y3 a( D0 v, X#include "cpu.h"# j+ @4 M2 O& Z/ `) @: I
#include "ppu.h"3 K. O. r$ d3 u0 X- D
#include "rom.h"$ h% j4 X2 j7 h& h1 g: J
#include "apu.h"
" F; u& G; z+ z- n5 n' M% `: t& s: `
// Volume adjust( R! k5 E) N8 a, Z1 b  X  N8 C
// Internal sounds
+ Q, W2 ]) r+ G: m+ F#define        RECTANGLE_VOL        (0x0F0)
% d9 V  V" }0 k+ f% B#define        TRIANGLE_VOL        (0x130)7 }1 ~4 l' i$ M6 c
#define        NOISE_VOL        (0x0C0)
- h6 C. I2 n3 c- Z* E3 I" I' t#define        DPCM_VOL        (0x0F0)% N  \$ o! C& m
// Extra sounds
9 W" g; G. ?" R* c& ?5 l#define        VRC6_VOL        (0x0F0)
/ s: g0 B& l- N' o: x9 g6 d& q8 m9 G#define        VRC7_VOL        (0x130)$ t5 {& P1 s) U7 `& F, `* L" X
#define        FDS_VOL                (0x0F0)) a% @6 k5 [9 T1 G5 q, z! @& v; V
#define        MMC5_VOL        (0x0F0)/ |  ~( r+ l+ Y
#define        N106_VOL        (0x088)
3 P7 `* A3 Z: i7 i  P#define        FME7_VOL        (0x130)
( \  q# H8 A$ C; Z3 u# Y$ V6 c' O  b2 _8 P9 I9 I
APU::APU( NES* parent )4 Z/ ]9 ~8 q- ?* g8 G6 t/ k
{* h2 Y1 Y; Y& X+ `
        exsound_select = 0;
( F: u. B8 }4 d  a
8 y; F, d+ d* l1 P% T& z; b        nes = parent;
7 s; S- u& A5 t        internal.SetParent( parent );" n' Y/ ~! c# r7 M
' S4 |  s- l( G# i. F0 v% Q! h
        last_data = last_diff = 0;5 d1 U: X' y2 i0 {5 M; |
1 T& @. Q% k8 N
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
0 N: G9 I0 h- V1 D" D; C6 @) B" N0 k  s( S+ q- j7 |
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# E5 c, e4 m: I  [' L        ZEROMEMORY( &queue, sizeof(queue) );# B3 X% _* @, q( T7 w
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# G# K5 R$ J/ c/ h+ K: _8 I9 x. q$ U/ `6 e2 w* B
        for( INT i = 0; i < 16; i++ ) {
0 p6 T0 |3 i+ ^7 C                m_bMute = TRUE;
) \' |$ c8 T3 I9 ^8 L        }
5 N7 W9 Z! e3 j' b! h1 T; D}7 C8 @& b7 B1 ]4 \& C- Y

9 s+ A3 i) m2 Q8 P. {4 u3 B4 pAPU::~APU()
& k+ X- }% A- c. X$ Y{
$ p9 k- @2 }" b; f}3 A; o# E6 Z0 N1 k& I2 O
; B, F" Z/ v) g- P+ Y4 e) o; {
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) |6 b$ P, @8 U( u8 v! \; \: Y{7 W! \  y6 d2 A4 F8 K
        queue.data[queue.wrptr].time = writetime;4 [0 |+ {4 Y9 ~2 |2 @4 G, I
        queue.data[queue.wrptr].addr = addr;) ~2 h. A- f& u& j# a
        queue.data[queue.wrptr].data = data;
3 m- ^9 q: m+ h6 d  @/ \& A" p        queue.wrptr++;! ^  H$ I- }4 j5 X$ K3 R: `0 o
        queue.wrptr&=QUEUE_LENGTH-1;
* k' U& _* D& T        if( queue.wrptr == queue.rdptr ) {
5 y  j/ ^! F# b6 S' ?                DEBUGOUT( "queue overflow.\n" );$ `' e0 O: A( M0 j7 g: o: t& n6 Y
        }5 j) W  O6 N/ g; X
}% X# P3 A9 y  K7 N+ N3 o9 P

  m7 K1 T- {0 p% p/ [BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ). E! R7 }4 [) ?; {6 W- d% U
{- b5 O" \2 [3 y# }, F' u- A
        if( queue.wrptr == queue.rdptr ) {/ E* I" b1 T8 T9 j$ x/ h# p9 a
                return        FALSE;# {+ S; y4 s1 `
        }
+ E3 _: b: A9 L3 L3 s* x        if( queue.data[queue.rdptr].time <= writetime ) {
" B1 I, q3 @, d- m' a9 I                ret = queue.data[queue.rdptr];
, j( n6 t6 s/ m$ b                queue.rdptr++;7 P' @2 ~: W/ x( ^
                queue.rdptr&=QUEUE_LENGTH-1;
! [+ _3 H7 [. P  s                return        TRUE;
7 B3 `' z4 e9 |$ i! Y$ X        }
/ B5 y' p" p) P) a; ?        return        FALSE;
/ G! p4 s& l4 x* C}! E  Y" c% t. d3 a% ^) i1 r
- y5 J7 v# o* t: C( i. `6 Z: b' J
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ T, T. M% x2 f, d* F& q/ e8 a{+ D6 O& `& S8 `: x  S) {% ^
        exqueue.data[exqueue.wrptr].time = writetime;& ?9 r* z. a* m+ B* u# @
        exqueue.data[exqueue.wrptr].addr = addr;
  x  t3 @' H4 n& b) f. Z- j        exqueue.data[exqueue.wrptr].data = data;
6 v, X  [' I/ `        exqueue.wrptr++;7 u( C9 {3 K7 S6 t5 |6 ^! u
        exqueue.wrptr&=QUEUE_LENGTH-1;
- B; \: R1 o  w! J# |! o4 o# ~        if( exqueue.wrptr == exqueue.rdptr ) {
& m2 l  U  ?0 H6 S. T2 t" R                DEBUGOUT( "exqueue overflow.\n" );6 J9 x5 Y  l1 {: l& G
        }
: p/ B! S% C! i; O& M! d}$ p* p" D3 n$ }6 m( s+ h* R
! E( F) c$ I0 |/ G, `3 Z
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )' l+ Y$ Y" i4 X
{. f3 X! k1 G* P' k
        if( exqueue.wrptr == exqueue.rdptr ) {
  P$ h5 U2 b% Q- q  k( c& A                return        FALSE;8 l* L4 }0 W5 a( X4 d) m
        }
6 |" |. E+ c' _- H/ {+ L- Y        if( exqueue.data[exqueue.rdptr].time <= writetime ) {. X5 r% d" d9 z  |6 N
                ret = exqueue.data[exqueue.rdptr];
# a1 u9 c1 ]$ V+ n" g8 c' M                exqueue.rdptr++;' _% ^; n3 N, d# d
                exqueue.rdptr&=QUEUE_LENGTH-1;8 R7 }# {" w0 {% ^$ s
                return        TRUE;5 K+ [" m$ E/ [  ~$ B7 h+ y5 a
        }
& V% P* D. C' h* x% _/ X! ^        return        FALSE;
$ a' X/ f8 |: u: M% Q3 \! b}6 n! D5 R$ }/ I. g
8 V# O. Q2 Q. |1 P. [, ^  H
void        APU::QueueClear()
+ A# R. n, ]. O4 z  H- k$ [6 `! _{, [7 w0 a! A  ?" T" d! }
        ZEROMEMORY( &queue, sizeof(queue) );: N3 K& e, j7 T7 Y# H  F
        ZEROMEMORY( &exqueue, sizeof(exqueue) );' q0 U5 l' C& S2 A$ y, U
}
8 _% E, H) k: e+ j3 I: d; n5 \' y. w
void        APU::QueueFlush()7 x9 ^5 H; ?# q  u
{; D  U$ g0 q1 ~( n# T
        while( queue.wrptr != queue.rdptr ) {
" C( D# @  @4 `& m- M                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );5 W) e- K9 |& R+ F6 b2 ]$ V
                queue.rdptr++;
: G. i3 B, L2 H! g3 ?: U                queue.rdptr&=QUEUE_LENGTH-1;5 ~7 u5 k3 K, Q3 Z3 ^8 ~1 ]& T
        }/ M# Z6 _9 `: p& K: R7 a
' `1 ]7 ~: m. B& ?% s
        while( exqueue.wrptr != exqueue.rdptr ) {
  B: o/ \9 ?+ {3 A                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 n' K, e! a3 u0 c4 S) u
                exqueue.rdptr++;
+ }6 `0 Y+ h. A                exqueue.rdptr&=QUEUE_LENGTH-1;* `: j# H- X/ h
        }
3 F9 Z$ e" {/ J* K2 s}
( }  Z1 [, I" e9 [! W4 L- u& l  P% |) K/ R7 f, d
void        APU::SoundSetup()  s( Q( W7 f0 j) \( m& u6 i
{# l0 X& `8 F  U5 r. v
        FLOAT        fClock = nes->nescfg->CpuClock;8 L6 f% e, F8 @: T
        INT        nRate = (INT)Config.sound.nRate;
: B$ |: S1 X3 N, R* m0 [5 |! O        internal.Setup( fClock, nRate );# a0 B- n! t* p
        vrc6.Setup( fClock, nRate );
. h  f$ n6 w8 Y0 I3 a        vrc7.Setup( fClock, nRate );, u) p4 `6 H7 i! ~. F" u
        mmc5.Setup( fClock, nRate );+ I& b% A0 o: l8 l8 S! R3 s
        fds.Setup ( fClock, nRate );
* N7 J: {( [  y) X        n106.Setup( fClock, nRate );
$ N& C# b8 J/ |3 ~        fme7.Setup( fClock, nRate );2 ^( l7 \/ a  F$ ]. W* K3 R7 E2 Y2 `* F
}# P1 w2 Q0 T- \; W# {

+ ?. j/ z0 @4 ^' `9 nvoid        APU::Reset()
, M7 G6 e3 @) S{
- P# l3 {* R- `' j        ZEROMEMORY( &queue, sizeof(queue) );( p  ^" d3 K; \- ^  U. \1 l
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, l. M2 D5 i$ {& b# y2 G
" ~6 \* M. {# X" t" E. z9 c
        elapsed_time = 0;
6 y7 N2 n' Y/ |! }  a6 \  L. N8 y7 D+ R0 J2 [; a1 E: Q
        FLOAT        fClock = nes->nescfg->CpuClock;( v8 A6 |; @+ t- [+ V# k
        INT        nRate = (INT)Config.sound.nRate;# g& e/ W' k! r; M& g' O
        internal.Reset( fClock, nRate );
, ~3 s: H$ a- s0 T* U$ D) f        vrc6.Reset( fClock, nRate );  ?% G: V8 P* {3 K
        vrc7.Reset( fClock, nRate );0 d( q: |7 M/ j/ t# n  P
        mmc5.Reset( fClock, nRate );
# d. \+ J& Q: Q, M+ O! @        fds.Reset ( fClock, nRate );) Q! r# A* Z  X8 C! ~
        n106.Reset( fClock, nRate );
- n% F/ o4 ^% @9 X- B2 s$ K3 M2 p/ ?        fme7.Reset( fClock, nRate );9 n* G$ |. r' m3 d2 @

$ y. ?/ K$ R1 p) \3 I8 {        SoundSetup();
, z; y8 @' [+ f; G5 L5 ~0 G6 P}) T0 l* _3 B: f5 {$ Y% e; \5 J4 j

) I4 ^; S) B# }, N8 wvoid        APU::SelectExSound( BYTE data )
5 H! s: W8 S$ l( v& F0 w+ g* \& Z* \. Q{
- G0 t  p4 o/ i# O) f' t        exsound_select = data;0 u' E( E* |* a0 }# Z" f3 |( ?5 h( ?8 N# w
}
0 y- a; l2 H1 E  ~+ a( D7 q2 F9 I: g- t1 K. ]1 D
BYTE        APU::Read( WORD addr ). v& W6 h% n6 O! ?
{" c  @$ u: c( D4 |) A2 f: t3 q1 Q
        return        internal.SyncRead( addr );6 b. G+ n7 r9 `  ?& D
}
1 I$ U. M5 w" s  U  i6 n$ G7 M, t+ p# @6 Z9 S$ k! j) f
void        APU::Write( WORD addr, BYTE data )
% f" F2 P9 t! g3 n/ D4 K" g{
/ u; m, M9 k3 X. v, ?) b0 j3 l$ w        // $4018偼VirtuaNES屌桳億乕僩. R: [6 E8 d- i' j) n) R& P* [
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 |* I) d$ z0 r5 j: O                internal.SyncWrite( addr, data );! j# V' @+ w: h8 v2 D% a& z( w
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 ]4 `% k1 d  b/ z7 E3 l+ W9 t
        }$ N8 P5 Y; z) p  }
}0 u5 R6 \! ~3 S, N' g" s% V8 c
3 V- `" m, |4 q9 x
BYTE        APU::ExRead( WORD addr )
( k1 z1 @4 T5 Y1 t. J{
/ N! d' R7 |/ h. vBYTE        data = 0;
8 T. M1 C$ ]2 }' K3 c1 J9 _9 X4 ?& z6 t9 X4 [1 X, [% C
        if( exsound_select & 0x10 ) {
, o: D2 I- O" E  h: e                if( addr == 0x4800 ) {
: t: c! [+ Y' B0 o& x0 l7 Z! B                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );1 i3 Q+ I$ V0 w& Q# J
                }
7 e2 [) e: d4 t& B+ p; F( [        }. l! R7 J; X7 X  B6 _' P" [7 r& N
        if( exsound_select & 0x04 ) {/ b+ F) h* ]0 Z
                if( addr >= 0x4040 && addr < 0x4100 ) {
% O9 d& ?5 y6 S) c- n5 S                        data = fds.SyncRead( addr );7 U: U8 {, G! W  |" t5 W6 G( }
                }* Q4 y0 f; e9 c
        }2 W; V: {: _  h* J
        if( exsound_select & 0x08 ) {7 {+ e4 g, Y9 a; M4 ~& A0 O
                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 ]( F1 V6 d8 m0 H  s6 Q* y                        data = mmc5.SyncRead( addr );/ a/ Y! k' d; x. t- g/ H& V
                }, W- H! Q. x8 c) R# ^* M3 M
        }% y; x$ c8 O- f0 Z

. ~$ P) S1 C& r+ w        return        data;& n: }  I% J+ r
}; y0 @* q3 n5 |8 o
  S5 @! B4 C/ l: v  i
void        APU::ExWrite( WORD addr, BYTE data )7 X& `/ [6 I. {
{0 v' f7 c& m. a; V! e1 d
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
+ Q- K( K, O7 l) B  E' Y, \% {& m* X4 f( l! Q5 m4 w% V! R
        if( exsound_select & 0x04 ) {& L( E# R/ ~4 X$ _( k9 |8 v- G
                if( addr >= 0x4040 && addr < 0x4100 ) {
8 q. t  ?6 K0 s0 ^1 }5 C) ^- M2 [  Y                        fds.SyncWrite( addr, data );
% i; d5 Y2 `/ m( M                }8 V3 Z& p7 h/ o: I2 \
        }. S) ]0 n: C6 f$ H) {& r2 }

+ ~% m. l; V3 ]  j& U% v        if( exsound_select & 0x08 ) {; u; e  X: ]: \, `! R6 B
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 |6 e3 k! z9 R6 p
                        mmc5.SyncWrite( addr, data );1 _( v+ ~/ O; M  h) s
                }* z) w" p* R' @; k; P- R5 h
        }
. ^, F$ a2 ]9 x7 e2 C4 i3 x* J}
- w. I6 f0 r$ G9 u( Y: r4 [( i) M( ?! A; \. V1 C) T
void        APU::Sync()
' {7 ^6 |$ a" m& ^0 K{  Z  T2 g0 S& v# _# c* L8 l8 Z: e
}
7 j+ Z8 @9 M% B. Y$ o% g' b( B9 v% v# D
void        APU::SyncDPCM( INT cycles )
0 i2 v9 N! d8 g4 j6 R{: E2 w. H8 H( E& {( k( d
        internal.Sync( cycles );
2 Z6 l4 L" l/ c, U
7 J( L9 M, w$ \4 v$ m3 ?! K4 b        if( exsound_select & 0x04 ) {
) h' H8 y$ T9 J6 K% f( c7 T5 U* C                fds.Sync( cycles );
8 d. M0 o' I, n( D5 `        }( }- F- y' j4 F( y! ]' T2 Z" F/ @
        if( exsound_select & 0x08 ) {
) \% Q  D6 C( K2 S6 g0 X) y' M% B                mmc5.Sync( cycles );  \0 ?5 [" E7 v  R' P7 \
        }( h: V) o9 W# R3 y. d
}4 J7 c7 V7 r; y( O' F

1 i, P! s* }/ L% q3 N& svoid        APU::WriteProcess( WORD addr, BYTE data )
+ y/ Z. i. c6 }  g{
" W7 S, D( _7 D& k2 R; \, l        // $4018偼VirtuaNES屌桳億乕僩
% q0 o+ k* G. [' Z! I# S        if( addr >= 0x4000 && addr <= 0x401F ) {  f6 h, [( i4 r' J; S- j
                internal.Write( addr, data );4 `4 W0 [: B" }, |
        }
/ H  P9 O. ?0 Y0 B8 R0 o}- t$ z6 j& ]! T8 d# ^$ P

2 ]7 p. ]  Q: u+ r) y, G  c& ovoid        APU::WriteExProcess( WORD addr, BYTE data )
# @. p9 \' e; E5 Y8 x{
/ {$ A/ O( h9 {9 m3 D% a        if( exsound_select & 0x01 ) {
0 M- E5 P% g0 t. Y5 L! a9 N  q                vrc6.Write( addr, data );
0 Q+ U. e9 J- U' w/ v1 c' U        }9 @' I5 F( G& E
        if( exsound_select & 0x02 ) {
! s$ h; T, P' Z5 }) G! a                vrc7.Write( addr, data );- g2 I8 h/ D; ?% G+ v
        }0 a& m# I; |# S, {9 l6 ^
        if( exsound_select & 0x04 ) {
9 ^& @. E1 i2 `- ?1 I- f! ?                fds.Write( addr, data );# E+ V( A" }# W/ l
        }5 v( K/ }# I5 E* H+ _3 R, B
        if( exsound_select & 0x08 ) {
  a! @4 ?) }6 @( _# k                mmc5.Write( addr, data );
5 T6 H( n( @0 Y  n5 y; ?        }
+ ~. x8 I+ ^" h  y9 n' }1 S- y        if( exsound_select & 0x10 ) {8 P; _  Z3 d1 O) A: a) \$ C9 o
                if( addr == 0x0000 ) {
  T/ C$ e  E+ d4 ?; W                        BYTE        dummy = n106.Read( addr );
3 x5 a4 A1 {" K; l: x2 z  z* N1 g                } else {% _/ P: u' Z7 b5 S
                        n106.Write( addr, data );+ {2 x: F1 r" W9 B3 h1 a
                }8 n9 }% E+ K, |$ N
        }
2 o! g) w- I4 `! [/ |. p; E) }        if( exsound_select & 0x20 ) {0 ]/ T+ n9 S$ a
                fme7.Write( addr, data );3 T6 }" s; g  ^0 C8 ]  `$ w
        }& f3 m1 w8 N$ {: x+ R8 c1 O: ^& y
}
' s6 t" v: ]5 m9 }* j
- U( o; C; \$ A: c& o6 Cvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ ?) f3 h7 q( J8 Y' i3 @/ X- G{
( i8 e$ b5 W6 S' R$ yINT        nBits = Config.sound.nBits;: K# z4 g, _4 i3 _+ m; Y
DWORD        dwLength = dwSize / (nBits/8);2 q' I" s# q- s& P, q  ?
INT        output;% G8 O, S& [/ t- y3 D3 o
QUEUEDATA q;
( x2 F  p* }2 WDWORD        writetime;
; Q& ^' d6 m$ l8 h: G! k. K+ w+ A" `
) J' l( c% l1 C8 m9 l; [LPSHORT        pSoundBuf = m_SoundBuffer;5 P' O4 j" P( y
INT        nCcount = 0;% x, j' R0 b) V" w6 }' P9 f4 u! h

4 g& n! D8 @6 s5 X, H; q: FINT        nFilterType = Config.sound.nFilterType;
! I2 `0 X) _* }; f  E( m+ J8 q9 F6 z/ `4 `5 q% ]5 Y
        if( !Config.sound.bEnable ) {8 o0 [! U: E- g
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 ]- Z) m) u+ d: O3 F3 B5 P( g; `3 R
                return;3 ^3 B: ^5 t3 H, N- K
        }
! V. D- j1 p7 m8 G2 ~% V) X3 z9 V# ]( `  \) g  @% p
        // Volume setup9 f1 n. z! d3 k1 b7 J+ S0 w$ V8 F
        //  0:Master
$ L' v8 t) i7 }8 y6 K+ z* f) U        //  1:Rectangle 1
7 G2 J3 ]" [9 V0 M. v: r5 J        //  2:Rectangle 2( w- P/ l! Q( G" P
        //  3:Triangle( a2 N; Z. N- t+ u& c6 R
        //  4:Noise" k3 d8 a* s0 L- P% G5 n/ Q/ h
        //  5:DPCM
+ ?; J+ q$ s6 s" {. j$ s/ ?        //  6:VRC6
- ~3 o2 f0 X( F3 ]' T2 O  x! L/ i        //  7:VRC7
  I. m5 L% M- o/ Y1 q& Q        //  8:FDS
! T2 e2 h8 Q7 {5 M# C        //  9:MMC5
; s' v  {/ G7 H( \2 J! h* `        // 10:N106) M( _* J- t' s' H
        // 11:FME7
0 U5 b2 W' V4 N3 F/ n        INT        vol[24];
" K, _1 i; I9 i6 i        BOOL*        bMute = m_bMute;
$ X8 Q  m0 x6 w        SHORT*        nVolume = Config.sound.nVolume;+ K3 \, j+ s/ X, _0 I* Z1 Q5 H) ?0 ?
- T, ]! E' U" x. h; M
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' P: }6 z3 U. v# E* q! u9 F0 I) S/ p: _2 w! N6 e4 H: i
        // Internal
2 P! y- K* L: L+ _  A        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 f6 \" r7 E7 {/ k, e
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;& h- A! v! S5 a0 d' h
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;; T6 X, j. e& G' E' i
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ G$ J4 B' H( a; y" E4 J" g7 a6 l
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
8 }9 u7 I7 Z9 _" O5 H
/ F4 G% F- t- U- x        // VRC69 ~" q/ }8 k8 t* o7 u6 v8 D
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 m2 e: D, e/ V! N2 D2 b3 W        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ R# m) H  q8 m  j        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; n1 c. ]/ l& k( Z) x* m& d1 h) y! y7 j/ ]5 N" b5 i- B+ |
        // VRC7
5 z  G' R: A$ j: G6 B/ t        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
! m; m" b- ?& B- d# G6 g* ]  `) Q' C$ p+ ~& W/ R2 o; x( C$ F  L
        // FDS
. Q7 O4 ~3 `+ g        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
1 M- f2 I9 ]$ r" k; J; M, p3 {* O# H: ?( U' j3 p
        // MMC5
6 ]: @8 h# W" @3 I5 o/ H        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ s, F/ J9 |+ N  z9 n# v
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 W! O/ u3 v1 P: B6 x) n/ N
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ L7 U" b/ u! \
# m1 @' I/ `; u0 E+ e0 [        // N106' x4 \: y# x7 B/ O0 d
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ?# ]2 B' b, s; H( t        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" G3 r" I& L- v, K+ m2 g
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 t( Z" q9 ?5 ~5 a7 l& W        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' ?' Y4 x% T: G. p% `        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- A$ M0 M! M& d/ H+ x, h! `9 T
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* h& j  z; ]- t        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 J, i# \! }3 l( d$ H& K        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 O# C3 @7 x+ ]+ O+ f$ M; n
; v0 }" L. R+ Z( A3 `
        // FME7
( w8 D3 J* O  R0 p, h8 `7 @        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% Y" h8 z* m5 U' R: @
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! \- t4 G' T3 E" [9 t1 h+ U" ?1 Q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 \) w9 U) v3 }, o2 y, n0 R5 z% T
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, y) ]; N1 a, G8 R5 s* n+ X! M
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;, T+ r7 H+ B; b% s5 n: r
" S: J+ X* V, K( R- N
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
& W  p8 T9 t% n3 O% d        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ {% }3 Y; D1 Z2 B) A                QueueFlush();: H* G! [. Y/ W0 I& ?
        }. o  F2 E# P+ Y: t8 D

& K, T- s4 G2 g2 A2 u6 Y( S* s7 X        while( dwLength-- ) {
( n/ \+ \* z- ^! r* K1 ^+ G                writetime = (DWORD)elapsed_time;6 D* r" c1 ~4 S7 g7 W

! C. o7 N3 [) K- J* q                while( GetQueue( writetime, q ) ) {
# F2 b5 n0 G" ]; g* V                        WriteProcess( q.addr, q.data );! c$ U% V& G2 W+ T) ^
                }
) L- V4 O  L6 A. N% s; D- |1 R4 w" J8 n% @( }
                while( GetExQueue( writetime, q ) ) {# R& b! P; c, W5 r  g
                        WriteExProcess( q.addr, q.data );
& I6 A1 o. i. y. Z, T                }! E9 f1 Q8 ?) L5 Q$ S' Y

7 L  k- \) |$ L/ b% \' ~                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7/ c# z* |5 z9 C9 A# b) w
                output = 0;: v' j2 q, P0 \( k
                output += internal.Process( 0 )*vol[0];
( |: l+ `( y, c+ ~3 U                output += internal.Process( 1 )*vol[1];2 I6 Z- X9 Y  k1 A9 ^# [6 a' ^% E8 z
                output += internal.Process( 2 )*vol[2];: B$ h5 G9 Q% B, G) m. O6 P. M# c
                output += internal.Process( 3 )*vol[3];
( g5 L1 n3 q1 N7 H. D+ X                output += internal.Process( 4 )*vol[4];0 W/ b, D1 ^. L4 x% o

& m+ J" f* i# [: ^                if( exsound_select & 0x01 ) {' R8 J7 }6 U& L. n6 }
                        output += vrc6.Process( 0 )*vol[5];$ A4 m! G& A$ S+ l/ s) u: l8 h* T- @) s
                        output += vrc6.Process( 1 )*vol[6];
7 _3 k* G: D6 C) i% G+ S                        output += vrc6.Process( 2 )*vol[7];
' d6 O( u' m# b                }; p5 H% ~, _+ T1 l
                if( exsound_select & 0x02 ) {
! [& x& t4 P% T) j! n) Y                        output += vrc7.Process( 0 )*vol[8];4 V# f! w! S0 }& ?
                }6 x: |1 F7 V( l: I( i& A+ @& X
                if( exsound_select & 0x04 ) {/ @0 j% T8 ~$ U- C% I) E
                        output += fds.Process( 0 )*vol[9];
9 K9 L3 \7 |( E$ g( D                }3 w' D; l4 t& }  c
                if( exsound_select & 0x08 ) {
% M. F5 _6 G. F                        output += mmc5.Process( 0 )*vol[10];# a; F( S  v' l$ P
                        output += mmc5.Process( 1 )*vol[11];
$ m, z( |' d9 b2 q2 {                        output += mmc5.Process( 2 )*vol[12];/ B, X: Z7 u' K( X# L
                }
" J1 z  V1 ~8 p; |. {, d+ L                if( exsound_select & 0x10 ) {# F( |6 H' Q, c2 P, W! k& B6 P
                        output += n106.Process( 0 )*vol[13];
. Y( q) r7 k& o+ O! t                        output += n106.Process( 1 )*vol[14];
/ B' b' N& z8 T* \, t                        output += n106.Process( 2 )*vol[15];
2 c; I: b  [3 T0 z2 B' r                        output += n106.Process( 3 )*vol[16];0 W1 e7 ^- b1 g
                        output += n106.Process( 4 )*vol[17];- Y* |$ F& w& a( p
                        output += n106.Process( 5 )*vol[18];9 k1 x( @+ w! H
                        output += n106.Process( 6 )*vol[19];
8 m3 r4 N& T, ^9 j% W, V                        output += n106.Process( 7 )*vol[20];
1 S; m$ D. E8 S7 j3 m6 ?: t                }
6 D" r6 y! A0 O, g( o" v                if( exsound_select & 0x20 ) {
: `, s' @, h( r+ X# ^                        fme7.Process( 3 );        // Envelope & Noise/ R" W% j$ _# l/ @  a, P
                        output += fme7.Process( 0 )*vol[21];
9 T3 T. O( |% f3 w. D8 A                        output += fme7.Process( 1 )*vol[22];
0 q) N/ ?0 S, d; D  C                        output += fme7.Process( 2 )*vol[23];
& z# `' a5 ]; |% K                }
% _1 I* M; n+ i9 j  q! N! s" ?4 I! R! }. h1 T
                output >>= 8;8 w) m4 o8 B" F7 X0 i2 n$ w7 m: Q

+ \- |8 V8 S3 v& @: o/ r( I                if( nFilterType == 1 ) {
. H( `3 c1 a  }( Z* E8 @. E/ m( h. V( J                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ v! p6 D, p. {/ V9 E* W/ G+ d7 Z
                        output = (lowpass_filter[0]+output)/2;5 S4 F3 F7 L9 W' S& L; o
                        lowpass_filter[0] = output;% ]4 b  J: W( H1 A5 c% e; W) X
                } else if( nFilterType == 2 ) {
$ D$ z# y% J; I: h( Q5 j# k1 X" v                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! w( z' A5 j" n9 D# T                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;$ V; n" l6 U  }% p: W! ^
                        lowpass_filter[1] = lowpass_filter[0];
, U# a/ A) B5 p& Z# ?. Y2 X                        lowpass_filter[0] = output;
; {" x* Q: }) p1 l                } else if( nFilterType == 3 ) {
% n" Q- s- S* j                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)1 L+ n+ D2 z; j
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# C7 J" ]/ E% O- U& g" [9 f# q, ?                        lowpass_filter[2] = lowpass_filter[1];( J5 p. n+ }2 W/ L' G4 N$ g
                        lowpass_filter[1] = lowpass_filter[0];
3 U; ~8 Q4 p) J5 o" v9 j                        lowpass_filter[0] = output;+ l* d# e! b+ t5 e# L# K2 o
                } else if( nFilterType == 4 ) {
/ f6 [( W' S1 E% l                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& O9 i$ o1 G5 ^
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;. A# m' Q" C) H- Y& T4 v
                        lowpass_filter[1] = lowpass_filter[0];4 `% P2 u1 C9 d' R* V2 O! ^
                        lowpass_filter[0] = output;  A  ]" l7 b' f& w$ i7 k
                }5 R. F( P7 G& S% Q6 A: s' E- ^) ]3 [
5 l# w. v2 i% D% q- H; K
#if        01 S5 `9 G% ^4 d: n+ Q" r8 h" d
                // DC惉暘偺僇僢僩/ E) S) F; I5 j
                {
5 \: u6 q# N& o                static double ave = 0.0, max=0.0, min=0.0;. A: j' u( b' G6 D0 g" m4 C
                double delta;& P8 A8 k& i2 I+ j3 z/ B5 V/ P
                delta = (max-min)/32768.0;
, H! r* t8 e( v& g7 n, {/ R3 d# N                max -= delta;( k$ B3 p" S( Z0 v3 U" d* h
                min += delta;
. s. e" _7 \5 \$ p; t  ]# _, y                if( output > max ) max = output;
6 D0 F9 I/ _+ f8 k% V9 v                if( output < min ) min = output;+ ~; @2 i8 K  J  m3 t' j* N
                ave -= ave/1024.0;
& \7 i/ ^0 J. m/ [+ L9 ~3 K$ U& Q                ave += (max+min)/2048.0;+ s/ \0 I& ?$ K
                output -= (INT)ave;3 a4 }' P. S2 \' Z# a2 R, N
                }
* F3 U* S7 S7 p6 d" l: _; `/ \#endif/ w% g3 n4 T" E. }/ W# L
#if        1  ^$ z4 s! j3 e4 A: G: M4 g
                // DC惉暘偺僇僢僩(HPF TEST)( ?- z3 E) j) j# ?9 K+ n/ q/ Q5 |
                {
0 U3 C% f* s8 {% f: M+ g//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( R5 ]9 B: B# W4 ]
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
( m, k" n% N3 N. R0 B$ D) G5 e$ W9 s                double        cutoff = cutofftemp/(double)Config.sound.nRate;
" U& K0 Q0 q6 N2 m: j# U* Z! C2 y                static        double        tmp = 0.0;6 l9 Q' m" g! b4 n5 [( v5 k3 H
                double        in, out;
3 ?2 t, p* i9 e* j! \' X7 g: {# O
: B+ Q6 ^' q. B- b% d( t                in = (double)output;
6 ~1 R! f  X5 B" M" a) Y5 S5 h                out = (in - tmp);. W/ F' o  B  v/ P7 A
                tmp = tmp + cutoff * out;+ A2 \( g: p& |! i  M
  t# z+ c+ K4 R* |3 E6 P
                output = (INT)out;/ H7 w/ h9 C# O4 @2 y( R) j+ ]: I
                }9 ~3 ^7 M& K: E" q" r: S
#endif
: F2 n# N$ |' ~4 O8 x) |. t6 m#if        0
/ f$ n- o+ G! y# @& |1 ~                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
( C2 y: m8 b+ Z; L$ |3 ?                {
. p* E  L/ u( k/ C: o3 e! h                INT        diff = abs(output-last_data);
1 D4 E( q/ s& U                if( diff > 0x4000 ) {6 f8 ^; d5 n2 i
                        output /= 4;
* W9 L* w. i/ o0 i9 |( I                } else
( Z. i, u! v# v/ A                if( diff > 0x3000 ) {
& q5 \  @1 P  G, n1 @9 H2 T                        output /= 3;. x, B9 _/ a* }5 R+ j1 X- ~
                } else! }% p! ]  |  L, G6 k
                if( diff > 0x2000 ) {
& l+ V2 S$ F% S; H8 c- B                        output /= 2;6 ?: h0 c) I  s( {# I6 N
                }
% }' d/ N( Q7 r( r                last_data = output;
- d! H7 r- _$ K7 ^& p8 o                }9 S9 x) K8 [0 y9 \6 A$ `8 W. `
#endif3 `) e4 p9 Y7 M) f6 }% P' h7 Z) }
                // Limit# ~) Q( T# y; X; b0 Q3 S
                if( output > 0x7FFF ) {
) B" G0 t: E* U3 O( F                        output = 0x7FFF;$ ^8 Q$ N' r( ^* r3 d! _
                } else if( output < -0x8000 ) {
3 P4 P- Z4 o1 j) ~2 S                        output = -0x8000;
  b. n2 _/ o' A8 p" ~# S5 h* t- \! q                }
1 A( u# B. v/ G* l# g, {: b
/ Y: O4 S6 R4 z1 b5 b  t                if( nBits != 8 ) {/ _) t4 `# b9 I6 `
                        *(SHORT*)lpBuffer = (SHORT)output;) ?$ e4 Z  h0 o' ^& a3 C1 ~
                        lpBuffer += sizeof(SHORT);' }3 U1 h: E3 E( c! r2 |
                } else {- ]/ L) W# `) @& U# F- b
                        *lpBuffer++ = (output>>8)^0x80;# V! z; c7 @8 j/ D% i) q" d9 y. N
                }3 Z/ @! J  q  Z# C; w
8 S) ^- ^1 w/ _- P1 d+ z
                if( nCcount < 0x0100 )
6 Z+ T0 l+ ?( A/ ]0 N$ n                        pSoundBuf[nCcount++] = (SHORT)output;2 i2 T1 G) w" R% [, T

* U- M. u; k/ O7 S2 [//                elapsedtime += cycle_rate;0 a9 }4 M' i1 ^) q0 W# ?
                elapsed_time += cycle_rate;. u  _7 U/ F1 h% E" Z0 p. O
        }
2 h5 A" W; ^9 T! l2 B* r4 p/ h& P& k( b0 c" G0 k& e+ i* _
#if        1
. B* b! ?- `1 h4 r$ F8 T  E; d        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 ]1 f& g& R; L+ K# ^3 ?                elapsed_time = nes->cpu->GetTotalCycles();
  l) y3 C; ^! U' |/ H5 M        }
5 F3 ~9 y8 t- L        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& s, u9 U1 J1 h! h: t+ D1 K: F
                elapsed_time = nes->cpu->GetTotalCycles();
3 Y/ }1 D# R; }0 q7 I) ~        }
8 N$ b9 `/ z( }8 C) Y' T6 S7 P#else
7 P& `! T$ o/ |/ G2 B        elapsed_time = nes->cpu->GetTotalCycles();
. c- C+ A  v4 k#endif. I. u# F2 N2 U+ l. U& e4 I
}
8 d0 e0 I1 Y7 W& G5 w$ }; Q9 c& n5 }! q5 Y( W0 m
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 V% M, a- n( M/ x- Y3 xINT        APU::GetChannelFrequency( INT no )/ A6 R2 g7 s! m& ^1 L
{3 v- o& q8 _: \! J
        if( !m_bMute[0] )
. e, o/ e5 o& C% e4 x9 u                return        0;
8 N  U; N+ l' y! g3 P
0 M2 E* o" y% T8 N$ U2 ^$ [1 [        // Internal
' W2 _& g6 u. \) ?0 K$ F. g        if( no < 5 ) {
" E4 g& R5 U4 C) p4 V6 c                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ S& T2 O" H9 f/ Q1 |! S
        }3 ~" ]  |/ F- _1 @/ [
        // VRC6
3 A% c% C2 |* X% d7 g# v, H' h        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
# Z5 D& O9 g8 W2 _/ Y% @& x+ @                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% a0 j" |& S0 y) ^8 ^
        }7 V* a, N1 o* D- e# {
        // FDS
( l' x: R4 r5 x$ D8 O  M$ h) e2 z- b        if( (exsound_select & 0x04) && no == 0x300 ) {
. ]- F( r! ?$ d  H3 N                return        m_bMute[6]?fds.GetFreq( 0 ):0;
( l  ^/ J& F" r        }' y: I2 s% b6 ~5 H( C
        // MMC56 E2 Q2 k) a: I. l) E9 E$ g
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {- R5 ?! h. Y3 m3 r% ^* I
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ ~. B. N' r) Y- e/ I+ q- q% M
        }( O* p7 \" k! \5 H4 G
        // N106
* `( [& x+ [+ |: B* a        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
* l0 F! [" f/ N3 m+ A                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
9 g0 K9 S2 m0 Q) |. z        }
0 P7 C+ P; w0 A8 d        // FME7
7 h. c+ J; x" [        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {: _  J; Z0 x  D3 P. [, }. O* ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
, y! }3 V0 C% u0 v8 E        }2 ~1 L9 ?+ M7 z9 E* [/ F
        // VRC7
. w) S! F8 j# K- @( `        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 q# e3 Z  T, B/ E# w4 z" Y
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& e% G2 d9 F/ R) \  t8 B        }) d$ Z7 d- u. Z5 I& R3 D5 G
        return        0;
4 C4 x, G* l" j& e}
7 {% w0 J9 G2 o; c2 c8 v0 `
( U6 A5 L. F& c9 }2 u// State Save/Load9 G' l- b) V5 |' L  k
void        APU::SaveState( LPBYTE p ), Z' P. q" c4 u2 U3 ?* O
{
/ N( u; V; G0 A' ?" F; B" L#ifdef        _DEBUG' Z& o' |) i! U0 V+ K2 Y
LPBYTE        pold = p;
- p( C& x& Q$ k9 J" ^& x, [4 @, `#endif6 v9 e( Y1 Z. ]3 _
: m; [/ v9 ^& G: C1 a( `6 z
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- L6 T6 S+ w% e: ^9 P        QueueFlush();9 p) @; o% F7 K3 b
" Y- K) B$ K3 k! Y! z3 A7 a
        internal.SaveState( p );
; e# S5 [& b0 v        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
% N) G4 i$ y0 p0 x$ q: f- j+ @
5 F7 J3 P5 j1 ~4 Q( v* V        // VRC6
6 L4 @8 {4 H, y4 d        if( exsound_select & 0x01 ) {
' I% G" ^9 K4 t9 Z8 P) m+ K+ `                vrc6.SaveState( p );
, ]$ i/ Q% K  }6 {+ l                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 u- z6 d/ w# w5 v/ m+ {& o
        }+ x: y! k: X, d; T) t- M
        // VRC7 (not support)
' N7 x, p, @* v+ J! b$ v        if( exsound_select & 0x02 ) {
0 j" r0 R  C$ c! {3 }( M                vrc7.SaveState( p );" F* i* [: Z% a" S6 p
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. A. K, h0 c3 |6 C        }0 E% Q9 c6 ^9 O: K5 a  W$ Q6 y
        // FDS* S8 c$ C! M: _& y' w3 G/ y
        if( exsound_select & 0x04 ) {4 H) a. F( D& A7 H7 u
                fds.SaveState( p );  I2 j/ y, L1 i: }. o* }
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! U% F% z0 A3 J1 u8 p
        }6 {/ s: ?, w9 @% B& G6 A8 t& L8 ]$ ?& A
        // MMC5# g. g: T7 M1 k7 l& ^
        if( exsound_select & 0x08 ) {
6 H% h% x5 y& ]  ?8 s8 C5 z. i                mmc5.SaveState( p );
8 S- y9 Y% R' h( [( Q1 |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. y3 K6 n0 ~  t- T# d+ N. p! |        }, W2 d) v/ L5 R4 f
        // N106
9 o* j( ~& o" V2 n; u5 Y, \5 @        if( exsound_select & 0x10 ) {6 v' `; X& c# z. _! d! ^
                n106.SaveState( p );
) R. w% }% `" b5 E! z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 g( s$ V5 j9 y( Q  p% w        }
! g$ c2 J/ U! `% v# d, q        // FME7
- P0 W+ S7 O/ v0 E        if( exsound_select & 0x20 ) {
) `3 J, o' ^! n8 h0 l$ U6 ~" h9 I                fme7.SaveState( p );! L1 l  O- d$ z# O! }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; P* `! P+ U2 y' w        }+ n& C/ b4 S8 d. x
9 z1 M& B8 ^. ~6 s8 {  z
#ifdef        _DEBUG8 Q( z6 ]' E) L" j% G
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
( o7 J0 e) V  H& y#endif
1 Y' O3 I: }  K. Z$ a$ ?# K: r: V}* `( _8 I& c. _: O

) `' ^4 B  W& {* Hvoid        APU::LoadState( LPBYTE p )
& c4 k# W$ p# v; H{: t2 q  M+ d: Y4 m8 x" }; E
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! B, g  _) `- h* f4 j7 k9 K
        QueueClear();$ e( X9 W. Q$ W7 _  A; @% e* K2 L! r2 p

' |% C: J2 I! K) F8 P- K        internal.LoadState( p );
# y$ f3 C# K4 t, q  T0 R        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding. y+ F, c  }# L, g$ r# x7 N

, T* X8 q( u4 c        // VRC6- S+ h+ S0 O" l
        if( exsound_select & 0x01 ) {' c! O3 M# g/ g# _' t
                vrc6.LoadState( p );% g) l+ [% Y$ ^  F$ e3 o7 q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" o  x* d& x0 C, }+ c6 _1 e$ |
        }+ h) k8 n5 w% Y& A# D* C
        // VRC7 (not support)1 D2 [! h6 x  Y% q0 N) z
        if( exsound_select & 0x02 ) {
% S# \4 A. X2 [" N: m                vrc7.LoadState( p );
6 H& N8 K& s+ B" G  Z' y3 {! l  Z& f0 G                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding2 ~* [4 l! B& {5 G
        }+ _1 V" @+ o: I8 l0 W
        // FDS
! T" u4 `1 i% u4 h7 K1 p        if( exsound_select & 0x04 ) {0 J+ c# Z- {1 V* h1 ?, @; V$ j
                fds.LoadState( p );
- [: {: c* L. n4 W7 b* J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 @" O, c- A5 {9 D
        }  F: {( n, S1 j  A
        // MMC5
! {0 |! Q6 j0 v. t: e8 G        if( exsound_select & 0x08 ) {+ f! P% D( ^9 {6 R/ A4 o. q
                mmc5.LoadState( p );
' B2 u0 D( h- o& v& \5 c                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding0 X+ G4 a5 E' U- \
        }# b- [: X5 f# \$ s- y
        // N1060 j8 N1 M2 b3 U  \4 n
        if( exsound_select & 0x10 ) {8 u( M0 U5 K+ r! c+ ]
                n106.LoadState( p );
, v' T& K' S5 w0 E5 `& m                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" Y+ l* c7 v9 ]! `$ h  G, V        }. Y$ \9 v0 z1 E! D
        // FME72 |7 d7 Q, i. I5 D( n; A
        if( exsound_select & 0x20 ) {
" G; L- ]4 ]+ {- M5 n                fme7.LoadState( p );* E! U2 Y5 o4 f) m$ J/ A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
. T' G0 L1 p9 L! g% o1 n        }
! \4 \4 v0 ?/ _) y- S}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + D# _( I7 t9 j  u" S
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 ?! A4 V' @+ C9 L
感激不尽~~

, O$ T. l* k- d9 X0 k* h. T7 _恩 我對模擬器不是很有研究,
  Y0 @2 Q, g) b( ?2 n* p- V雖然要了解源碼內容,可能不是很困難,
' w- y) j3 t; T6 \  X不過還是要花時間,個人目前蠻忙碌的。/ v+ M2 \; A0 q! Y1 i
* T) k* R5 |) _5 O2 Q) U6 G$ }
給你一個朋友的MSN,你可以跟他討論看看,
/ h( Y' X0 M/ `5 s- P9 \他本身是程式設計師,也對FC模擬器很有興趣。; L% Z2 e1 {- ]& F+ j6 H5 y
) q2 e3 W7 ?+ K4 n  s% X
MSN我就PM到你的信箱了。* @4 [# W/ s  C: D$ E

/ S1 X/ \" i0 P% y1 Z* P希望你能有所得。

该用户从未签到

 楼主| 发表于 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 \5 {* Y- S# G; M
呵…… 谢过团长大人~~

" x- z# V4 y  A
; F( i* F9 X/ w* [) ]( G6 E/ f哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
& J: \! R" Z3 x% N4 l7 u3 |# [# @团长的朋友都是神,那团长就是神的boss。

' t" L* I6 F$ E0 ]哈 不敢當,我只是個平凡人,
6 b6 Y' J9 e. M. T4 t! V) X) S3 ]要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 p* Y+ O" W$ {6 sZYH
8 k* d- p# D, nQQ:4147343061 O' w5 z% P" _6 e" L
Mail:zyh-01@126.com$ e  \* a3 V8 {: H9 T- S4 K

, x: X% Z& O" K# n9 L  {6 C他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
( H0 G$ J. R+ W. V7 K  J再次对团长大人和悠悠哥的无私帮助表示感谢~~
- _* W) [6 w1 F7 n3 \0 a9 e
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-7 01:15 , Processed in 1.121093 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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