EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
  d; N5 J* o  l, N3 K7 B楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ N: T  W, {9 k7 `# h9 D3 a这里有相应的模拟器源码,就当送给大侠了~~$ Y9 i& q0 R* d& i" ^
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
  @( x& x" U$ }* I1 v1 R能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。4 u# v, X3 Q- n+ @/ d8 S# H# h
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 g9 p) p5 N$ O, N% R! R: [; }# a  |1 ?
这里有相应的模拟器源码,就当送给大侠 ...

7 B; O. U) M2 u; M( \5 h, g6 L聲音部分(Audoi Process Unit = APU):
5 g4 o( d% ^, `  g2 v4 Q.\NES\APU.cpp% w" k& F$ i+ f: j# J1 J: y! Q
.\NES\APU.h0 U& ]5 f- v4 ^4 U

4 _, A7 Z! V8 t3 c1 E2 {. Z
# M# E2 f& \! m0 v) x/ V5 }: [' F5 ]影像處理部份(Picture Processing Unit = PPU):; E- b8 m. [6 d; K) c/ W
.\NES\PPU.cpp3 T- h8 o6 V, s0 |: P
.\NES\PPU.h
4 I  y5 X, Z* K6 q6 T* g; r" C
9 p, X# ^( `  N! _5 L4 q0 m% R4 i如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:, ~: u: [6 Z; U/ A4 E+ T. q
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 x5 }9 p0 q9 G7 L
//////////////////////////////////////////////////////////////////////////
0 F2 E1 m7 H, y* }6 Z/ _: J//                                                                      //' c" A  ~0 x- }, K& n: O) p
//      NES APU core                                                    //
- r* W% c% ~8 i) U  l! j2 b//                                                           Norix      //  d* _7 b. e( ?  k# V
//                                               written     2002/06/27 //
- ^' j0 z5 w* |, r  W7 T8 V//                                               last modify ----/--/-- //7 T, C* k, p; N; h0 v% Q% M
//////////////////////////////////////////////////////////////////////////; _: F5 f: p$ @) K
#include "DebugOut.h"
; V1 u1 F; r" S# l4 Y5 K! o: e#include "App.h"( H* Z( J3 ]. k6 g; j- f5 M
#include "Config.h"+ T* L( c# s6 I, X

3 Y/ K  v) ?, c8 L6 }#include "nes.h"7 M6 a& a7 y8 B5 N, Z
#include "mmu.h": q+ X# R5 v* B+ U+ {9 ^
#include "cpu.h"8 f5 v! T( s& D* v  B
#include "ppu.h"5 ^% \/ |* U8 e- \( G4 ]
#include "rom.h"
# F# m7 W, S5 R$ T. Z6 ~0 M#include "apu.h"- ^2 Q% _6 |9 n

+ y7 |4 q3 i! G4 l3 T" z// Volume adjust
. o/ d$ V7 f- o9 X  r9 ?* r# ?8 `; s// Internal sounds+ ]; e0 S3 `& j, |& x6 J' \
#define        RECTANGLE_VOL        (0x0F0)
2 d: @  `. y# U. I$ G! ?  I#define        TRIANGLE_VOL        (0x130)
* j/ [* f* O% m. }  Y% a#define        NOISE_VOL        (0x0C0)3 F$ ~0 H5 N8 S8 e; g
#define        DPCM_VOL        (0x0F0)
; ]% B# I+ o/ d- T' y// Extra sounds
4 j; i" K2 |% r#define        VRC6_VOL        (0x0F0)0 B( j4 u3 |& _6 C
#define        VRC7_VOL        (0x130)0 A  z6 c+ y; m  ~8 p5 f0 Y
#define        FDS_VOL                (0x0F0)
* g( V' G( k, s4 u! R* a: ]6 n: G#define        MMC5_VOL        (0x0F0)# g: c) {$ P) S- T: [% U
#define        N106_VOL        (0x088)
8 o! g4 ^  H" T6 }  K4 ?2 T#define        FME7_VOL        (0x130)$ |3 r2 g7 a% k3 w3 d3 E+ ~4 Q

/ n" x; b0 \+ m5 I; |APU::APU( NES* parent ); ?* M6 O+ \2 w0 C7 w
{
1 s/ }2 t; a4 D! F1 n( m! R  u        exsound_select = 0;( C: [' I' r/ n* z2 X' O3 F9 |

! n0 Y4 ]: w+ w        nes = parent;, s& k3 ~9 X8 [7 T0 E: Q
        internal.SetParent( parent );
+ H# D7 Y- A/ `/ D3 @" D. k. L; L+ Z
        last_data = last_diff = 0;8 N- ?' U3 d+ D+ v1 `! I* Z9 _

* b& y7 ?8 b4 {1 H        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
9 E' d* [6 J  R1 c
# m% b5 _5 u, I/ E, ?        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
5 t' O1 k: c% G# j: O; Y6 r        ZEROMEMORY( &queue, sizeof(queue) );5 d' ]! }9 }6 t* Z1 W* V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, H* [  y, @; q0 L. {; a. s) Z5 s+ [3 y) j; w& [" N9 m! [
        for( INT i = 0; i < 16; i++ ) {: W/ I  l" K, m1 a
                m_bMute = TRUE;  ?4 ~1 p' r! U2 W! X  K
        }
; V/ r: h: H. @( w+ S- I/ m. L; ]}# P; F: Q( {( m  r& g9 y( w& S9 G# H
* k, q8 q$ g- V4 ]7 L
APU::~APU()
' T0 K( q: F: c/ ~: b{
$ K( Q( s% d4 M9 K  r}8 O; B! y% [( l  G; E3 Y! C

. {5 l" i9 k. ^+ R+ {/ S# t1 ivoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )/ o  t3 z9 T3 `
{
" h9 E- x- p9 I        queue.data[queue.wrptr].time = writetime;
! f! H: n, k: u( X* W% {+ k        queue.data[queue.wrptr].addr = addr;$ G& v  r% g  I$ U; M2 b: r1 J
        queue.data[queue.wrptr].data = data;: Y% K, F; y4 g. G! n8 |7 p
        queue.wrptr++;8 B& @! z9 d2 k/ |
        queue.wrptr&=QUEUE_LENGTH-1;
* H/ M, c; d* T3 `5 B- U        if( queue.wrptr == queue.rdptr ) {% ~9 m% e3 }5 z- B
                DEBUGOUT( "queue overflow.\n" );
4 O; t; R2 X% }; H/ f% }        }
5 c: A2 S! ]# ~; P2 F- R/ \4 H, ~: |7 m- N}0 @: l( v: X* E# _$ Q
5 k3 C  x* ^: Y" r; h
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )2 R1 }1 t# S' r8 }" G+ d6 J
{' ]; j- B4 M0 W( z& I& `
        if( queue.wrptr == queue.rdptr ) {
2 y( t( F( W+ x5 }& Z                return        FALSE;
& {0 J, @  c( j; I1 I0 F! n" q; z5 m9 u        }  g1 l# r5 b+ u5 d/ S- {/ b; P+ J7 J" k
        if( queue.data[queue.rdptr].time <= writetime ) {, @3 l( m1 ~' n
                ret = queue.data[queue.rdptr];! T* [+ r, I7 R. B% }+ Z$ U( f
                queue.rdptr++;5 C5 l) x3 t; B& I- T$ I
                queue.rdptr&=QUEUE_LENGTH-1;/ r: o" K0 z0 j7 s2 Q+ _
                return        TRUE;/ G. ^% K* o% Z1 J* w( Q
        }
' ]2 P  i4 h- o6 q/ A8 C' A        return        FALSE;" d, H; k$ c6 \0 u0 M
}. |: u; t8 E# M  i5 V7 }

5 Q$ ~+ ~! g4 [1 K% dvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )3 y, J7 n. N6 T
{
* y9 R$ s  z) n" A5 X1 ?. [        exqueue.data[exqueue.wrptr].time = writetime;  u7 X5 R: v. y" M% g0 O5 C. p+ H
        exqueue.data[exqueue.wrptr].addr = addr;
6 v" h/ N! \- t1 d' v# V; y        exqueue.data[exqueue.wrptr].data = data;% r8 A7 V9 K6 W
        exqueue.wrptr++;/ l2 D$ M4 t! C- A( d4 ]3 L  O* }9 e3 M1 j
        exqueue.wrptr&=QUEUE_LENGTH-1;
1 j4 _5 `- q1 F        if( exqueue.wrptr == exqueue.rdptr ) {
+ L# T8 s9 n! m0 S5 T1 E                DEBUGOUT( "exqueue overflow.\n" );
/ R" c$ u+ a% q2 w        }
/ {0 N8 b6 }- ]3 [/ |  y: l}
* U: d) j3 S- W/ r1 W3 [
- _  c+ b! U) c& `4 V. ]/ OBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
- e5 y5 m/ E. T9 I{2 n( q. ]/ F# e) u* O
        if( exqueue.wrptr == exqueue.rdptr ) {
. Y' U& Y7 E4 y+ p  L                return        FALSE;
0 r, z0 i. b8 \3 |. N. z, r        }) y) i; r) K- A9 D, V
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
/ u1 k% W% Y" W0 e                ret = exqueue.data[exqueue.rdptr];. I6 X8 q3 z) N0 v3 {
                exqueue.rdptr++;- ~* Z/ ^2 u, Y8 _
                exqueue.rdptr&=QUEUE_LENGTH-1;
$ C7 y8 I. e! _7 Z                return        TRUE;
$ `5 `+ m6 e0 i6 T3 _1 h        }9 L7 x' a: }0 e# n
        return        FALSE;
9 c4 e8 t) D& V2 ]. k}- V$ V0 j+ D. p, t* [1 H& g

9 k$ z% d7 Z' g) bvoid        APU::QueueClear()
# w- X/ R: L, G; y* T8 l{
# n0 G: O( N7 d7 u& A- T        ZEROMEMORY( &queue, sizeof(queue) );: x( @' s) s; t' s/ l0 [
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, |3 j& c" H% C$ H! @
}* y8 t8 ?2 X1 v' b! H8 Y
0 d* `- i7 A4 u$ M$ o
void        APU::QueueFlush()+ T6 ~2 [" J7 B% o, E2 m
{
/ E1 `+ h# R. ^. r. L, }+ u        while( queue.wrptr != queue.rdptr ) {3 d9 I& d, y7 o0 w; D- A
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 O0 g2 M7 x# ]5 c                queue.rdptr++;
( g0 ?2 i* m9 G                queue.rdptr&=QUEUE_LENGTH-1;
- E+ `/ S5 _( T- u5 i        }6 u/ y- ~$ g$ u% k5 A; T: R

+ T; ^5 e: A7 X* {        while( exqueue.wrptr != exqueue.rdptr ) {
: u3 `( w8 U# i+ i3 |8 B8 Y0 u                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* y4 Q. q6 F1 e9 H; I                exqueue.rdptr++;
5 L$ \; y4 {$ l                exqueue.rdptr&=QUEUE_LENGTH-1;
$ B% c) z3 q) d5 r1 O        }" c7 A& }5 W* i4 @* |" `
}
5 p1 i4 C, k, H# b* B. N- m1 ]  q; [
void        APU::SoundSetup(); O0 c! E' l) U4 y+ Q( z  f$ ~
{" K8 ?  q  C# x" Y' W% z
        FLOAT        fClock = nes->nescfg->CpuClock;
! D, `+ }* X$ p1 _5 ]2 l  X        INT        nRate = (INT)Config.sound.nRate;1 O3 s, M8 _. I& x0 u8 Z
        internal.Setup( fClock, nRate );# j5 h* u9 k& M. W
        vrc6.Setup( fClock, nRate );6 d; B, U" d1 y4 h
        vrc7.Setup( fClock, nRate );
( l' S/ L; R, G) _1 Y. h; k        mmc5.Setup( fClock, nRate );
5 ~- s1 z7 A/ O4 b  p# v9 o% a; g/ r        fds.Setup ( fClock, nRate );1 Q" j6 R4 p3 S' _
        n106.Setup( fClock, nRate );
7 ~" X/ y& C$ c. `# h, _, x        fme7.Setup( fClock, nRate );
/ O! e3 l/ b+ h1 U2 ]}: A) Z1 t+ g, ~$ m7 |# k6 ?8 J
) ^. W% U  V+ ]# n
void        APU::Reset()" _( X. N8 _3 V
{% I" \7 H" W/ |. H0 ^
        ZEROMEMORY( &queue, sizeof(queue) );  A1 T1 C7 ]( K! U
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) j  s: p6 R1 H  m6 k/ p( `

6 Y4 v+ V6 J: s" X4 p8 x# [8 D        elapsed_time = 0;
: u6 n/ S$ }% j8 Y* o+ L  a& j+ i, s! H: V3 o+ M
        FLOAT        fClock = nes->nescfg->CpuClock;. ]5 I- G# c, S" w. G
        INT        nRate = (INT)Config.sound.nRate;: T# Q. W+ v, f; K
        internal.Reset( fClock, nRate );
' ]! ]  `+ S, i3 ], S/ E  t+ K        vrc6.Reset( fClock, nRate );
) @2 ?% G2 I( a$ a        vrc7.Reset( fClock, nRate );
# q3 G/ ^7 N$ _, c- ?3 J0 x2 P" ]        mmc5.Reset( fClock, nRate );1 e8 J$ J; D$ v: A
        fds.Reset ( fClock, nRate );
9 @5 e6 m% |9 K/ [- D& Z) D7 U        n106.Reset( fClock, nRate );" Z0 y, ?7 O; I: m( z. Z& q
        fme7.Reset( fClock, nRate );
& v: p- A) W0 H! W
- e8 f% x) s' ~0 P        SoundSetup();
# k! C$ }8 K$ V3 }}5 n2 j7 S/ h4 O3 c
9 J, a" x# b5 W- J7 P
void        APU::SelectExSound( BYTE data )
& Z8 M4 G, S5 v3 g2 L{3 @7 q$ g7 F" R. `' t$ y6 V$ I% ~$ e
        exsound_select = data;
6 ?% y+ j! e4 E8 V  ~* M) Q}, ?2 r) g3 Z* A2 S

& K, h5 K- D" ?! w' E' l1 [BYTE        APU::Read( WORD addr )! |- A+ I+ L: l8 h' Y+ \: }
{
+ R2 s  F6 H+ o+ \        return        internal.SyncRead( addr );
1 `3 ]; h0 O, J) M}
- H" U. B3 Q  Y7 G& s1 e  v: G4 k0 S1 P, a% M0 w6 T
void        APU::Write( WORD addr, BYTE data )/ \) L" `" b3 a% Z+ v
{- i7 b" D1 ]3 M4 j0 I5 |* [8 v
        // $4018偼VirtuaNES屌桳億乕僩
- P5 U) c" e3 i7 ]        if( addr >= 0x4000 && addr <= 0x401F ) {! n6 W/ q. M* K0 k0 y
                internal.SyncWrite( addr, data );% q) M5 h, D7 Q; K% w  t3 U
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
: e+ d& y9 _  H6 {; Z' D        }
& F% H# E3 l) _9 Z}
/ E3 [3 G, @, ]# o, f. P- }+ o8 X, c
BYTE        APU::ExRead( WORD addr )/ L6 \% F& O" w: c  {
{
4 ^9 {+ u$ g$ }/ x/ }6 xBYTE        data = 0;
) n0 q8 V3 n/ e# T+ c3 ~: s/ H3 |* F, K% b0 ]+ R) c- m3 z0 N! y
        if( exsound_select & 0x10 ) {
! c9 x7 F6 ^) o$ D/ d                if( addr == 0x4800 ) {9 x6 Y$ k! i2 l; G# f
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* _; u$ A; y& {6 B* x' y
                }
7 f5 }  U( ]8 g0 t1 U& m        }
  _! A* \0 c! y! X2 D, I        if( exsound_select & 0x04 ) {3 K; @7 c) K: C7 h' b; Z  ^
                if( addr >= 0x4040 && addr < 0x4100 ) {/ h% E% H  [6 r0 q) e( C6 p1 q' T2 m
                        data = fds.SyncRead( addr );
" o+ A( @" g1 O4 f7 {+ y                }
6 C, @3 w4 S! d$ l: _/ z        }
2 V- m8 }: i0 I, O; P        if( exsound_select & 0x08 ) {
* z) Y9 ~# w4 E5 I                if( addr >= 0x5000 && addr <= 0x5015 ) {
% Y4 n' K) L* t' n0 Z6 k                        data = mmc5.SyncRead( addr );* [4 |# ?5 t7 m! H0 a, Q( c
                }8 j( ]. B4 ]0 }9 f
        }
0 \4 s4 |; X; A5 H2 l( N7 B+ E, G3 G! h- z- G6 r2 {8 A
        return        data;3 D3 F! m0 f" Y5 U1 H
}) l. h- @" I; A; q( u( `7 Z' S

) t+ d1 D. N' q1 Dvoid        APU::ExWrite( WORD addr, BYTE data )
; q( y* z( [( i& N{
/ @; e! E5 U7 X, ?        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 s0 f  z$ z2 s/ `+ g: X' ?

% H/ U$ n  f( @- @        if( exsound_select & 0x04 ) {0 D2 W1 t; Z. j) b$ `$ @
                if( addr >= 0x4040 && addr < 0x4100 ) {* u9 g! h  ^1 O! n/ f; `" G% ^
                        fds.SyncWrite( addr, data );
1 K- Q8 y' V# V! K                }8 o' D' S9 @$ v8 W3 v- X1 e# a8 ~
        }
, e2 M, f: \1 D# W. V( Y9 i
# a1 d7 F0 k8 d4 g8 O6 t' \        if( exsound_select & 0x08 ) {4 s) s6 t. {  z; Q
                if( addr >= 0x5000 && addr <= 0x5015 ) {' R! B. d9 Y/ O% \3 v9 {# y
                        mmc5.SyncWrite( addr, data );
, o, {2 F, ~5 }2 Z4 l, Z                }3 ~8 H# r4 }1 I/ e
        }
+ C  ^) g/ V1 s  R9 ~/ g}0 L3 Z( X' {9 d1 g

9 B% {- X. q8 v0 ~1 O+ U& [; Hvoid        APU::Sync()' c$ a& d! f# L+ l. y5 ~
{
. `7 O7 }5 k- h" l" F}
" l( W3 [& J' h! l, c/ w( o4 z4 u7 ~/ S9 D; A
void        APU::SyncDPCM( INT cycles )
- V" Y2 ^9 ~$ @! O{) Z1 v3 i" J& E8 b& ^# B# ^
        internal.Sync( cycles );# V9 U8 Q, \  S( \% H
8 ^' Q( T. Z0 n# f: \
        if( exsound_select & 0x04 ) {1 C; S( d# i) g' z
                fds.Sync( cycles );/ a. X6 x* i, \
        }
7 O+ T, C9 o: N8 V        if( exsound_select & 0x08 ) {/ Q: \4 b) }7 O, b! F
                mmc5.Sync( cycles );8 F& i1 }: X- b2 m) R! o3 g, G
        }
' m- p+ m1 t4 P+ s}
  C; H+ n: `5 J) L+ z) B" v# g8 m3 a& L6 ^1 u$ F8 V
void        APU::WriteProcess( WORD addr, BYTE data )' e( _, A' }# u4 a* f  f
{# b5 L: ~; V$ k5 f
        // $4018偼VirtuaNES屌桳億乕僩
2 N" _% d" G. Z% O, Z% j; j        if( addr >= 0x4000 && addr <= 0x401F ) {% S$ n* F0 P' J9 B
                internal.Write( addr, data );! j5 W0 M2 \9 N; L, H6 A/ {
        }
3 C: Y8 X  ]+ o% V}" ?+ q6 U) U( N- v3 x
0 h  z. Y$ I' r9 C2 ~% b
void        APU::WriteExProcess( WORD addr, BYTE data )
  f/ j/ a/ B5 u# n{
. p2 v/ Z0 ~3 {+ A$ I0 r        if( exsound_select & 0x01 ) {; ~: |% w( [( q+ t& U. T
                vrc6.Write( addr, data );$ o& n9 |4 l: x
        }; j5 k' N. G8 l
        if( exsound_select & 0x02 ) {
8 x2 [* ?: ~: p( `$ ?                vrc7.Write( addr, data );. {4 j4 o! A9 ]: f5 A
        }" r6 y% W; {6 E7 ]
        if( exsound_select & 0x04 ) {
& Q) [+ g. u3 G. }                fds.Write( addr, data );, |) R# r( j) ~4 }. \. l% Y
        }7 R) L: K2 k% \* {( P
        if( exsound_select & 0x08 ) {5 _% K8 k, O5 C' G/ B7 i- X$ Z- Q
                mmc5.Write( addr, data );" M3 U$ h% b0 Q; g7 r
        }$ o9 C$ p1 D% p
        if( exsound_select & 0x10 ) {
' \2 ^# t" {" \2 d' g                if( addr == 0x0000 ) {
( Q" z/ E. ]2 D/ p1 J% m                        BYTE        dummy = n106.Read( addr );
7 f7 S7 F7 B9 \. x                } else {1 V4 [- q6 f+ o2 W( c, x8 q; M: r2 A5 `
                        n106.Write( addr, data );
' k! u! ^4 [: C* F( c                }
( {4 r, G2 f+ _( ?+ L        }# }* `4 b1 a* ^7 r
        if( exsound_select & 0x20 ) {: b* @3 X' q4 F  _% A2 J
                fme7.Write( addr, data );5 y+ ?- E- P" ?3 V$ m+ b
        }
* h4 Z8 v/ Z0 T1 u; H' n}5 a6 x% z. p" t5 Q! ?

/ h1 r5 Z' _& t+ i& Xvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )4 O2 p2 M7 {+ p9 ^5 T2 }$ e
{3 J  C: u/ p( ?7 Z( t2 L* y
INT        nBits = Config.sound.nBits;5 b$ a" E; ~: D& {6 Z1 o0 Y% T* q
DWORD        dwLength = dwSize / (nBits/8);! h" W' \! z! v! `  I9 T
INT        output;6 M1 c3 E8 N& Y* B' y1 P! C: K. U
QUEUEDATA q;: [; I8 l" i+ F3 \5 i( Y1 C/ I
DWORD        writetime;* v3 Y, }  D: u  |6 o6 O. f

: H! E; L. T0 b: |0 B8 PLPSHORT        pSoundBuf = m_SoundBuffer;( W& q$ _' S' g1 j- @
INT        nCcount = 0;
0 g# l5 @" Z2 w+ s) |3 a. v
4 y' H' a$ m' LINT        nFilterType = Config.sound.nFilterType;% K8 M/ o% d5 \5 }0 `; T
% x' K- ^: n  d  |; B0 O
        if( !Config.sound.bEnable ) {
2 ~4 q: G7 ]3 ^" h* y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
9 T9 l& s8 f0 F# U' B                return;5 T. C2 n+ w3 r& U" l- J; L
        }
# x/ A3 z/ P2 n, @: U: |; P0 w& Y* \1 \8 ?. F; \
        // Volume setup
1 h0 P+ D9 J* b- p. N        //  0:Master! A0 A' K4 C( ^
        //  1:Rectangle 1
3 A3 B! X, F; _1 E/ c# m        //  2:Rectangle 2
* S+ t! q% e' x% O        //  3:Triangle
8 `" _  D" O' ]# x        //  4:Noise3 T( J) f5 O& U! g0 r( l' v5 s
        //  5:DPCM
5 I, N6 j5 L# [# }- k        //  6:VRC6
0 b. W( `  x0 }% g7 {, f1 V# P        //  7:VRC7  e& l8 F" P! Y
        //  8:FDS. d; X- i' A% p: O/ B
        //  9:MMC5
  T5 ~% r6 [9 m, L; c        // 10:N106( t* e, |/ [9 f' K1 b
        // 11:FME72 Y, {3 d+ X5 L; R4 K
        INT        vol[24];* m+ |6 m9 q, @' \% e9 g
        BOOL*        bMute = m_bMute;
* @1 }6 r: W& W+ D/ D" l        SHORT*        nVolume = Config.sound.nVolume;
1 m) l" I$ ~1 p/ K  J, P, G! f$ f5 Y
* B% W2 n/ j  `0 ~9 r# e4 z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;4 k- y4 V* Y& ]. h; o, Q$ G* V

. A0 R' c/ n9 h3 t+ c        // Internal
' R8 L& S2 Q6 M9 i6 u7 D. C$ l        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ {' {: \8 I2 P6 e. R
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;* C2 g7 W7 T7 W9 @
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: V" L" g+ T# _% y& \- k/ |6 U! {        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 \+ G4 l. d# g: ~% \
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; Y# v: x; [- G( _8 d
% l6 |' ^5 Z/ A/ s7 I, |  j+ l
        // VRC6* J# T* m! z  b- U! g
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( J4 F  \/ V4 c& T8 M
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" [, H, ^6 S$ E/ R% j+ |( }8 F' Z+ h        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* d8 t& ]( N! B1 }- P2 ]4 I
! S  ^8 Q6 [  j* E$ L1 r        // VRC7
) `. S( X9 U7 O8 E( K        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( x: @7 y* Q3 _# v* n

2 M# k3 V- _7 d  @" |4 Y! w" `0 I        // FDS
) Z4 W8 V/ J) h6 u4 ^% A# y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
( y5 c! D6 g" D  T! Z  r; i, L7 a$ ~) v
        // MMC58 t' ~( A: h, v4 V. ?, p4 W
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 e7 w' ]9 o4 v$ \7 l
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 m- L; Q9 m& _
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;# \; h) F' Y8 _. k( g$ l
& [% K9 U# _) Q9 j* m- F: j
        // N106
3 p; ?, `* }5 V        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" r( X* A2 k  m  {% Q- m
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) t( B0 Z0 U" I1 b- A        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, _1 R5 v) u' l1 t; ~8 p        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! a( B* v9 s+ g  m/ W        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ e. V. y, o0 c: c
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, t* e0 ^3 }$ p, {; _        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, Y! n( P# _- K& _* A3 j9 h, \
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. x5 F+ ?" ]5 O$ ]4 D
5 J1 _" O2 t- J1 d8 e
        // FME7/ k0 g) C1 ?0 q. V
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( |$ ~9 B0 X" K. x( N
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 U3 G% a2 P; ?2 c
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! _5 ^# `. h6 _, D

! c2 w, k; z% i( E3 g//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;: X, ^$ K$ x- X! P' c" u+ U
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; R4 z9 i( j& `7 [+ f: m( l( z' ~6 Z* r9 l- t: b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟7 Q4 P9 s$ j( {3 l" V
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: Z8 I" A: @9 T  `' e5 W% L9 h. k! L
                QueueFlush();9 P6 m/ p3 J2 s& |: _9 t' N5 H$ |
        }
) I4 |* W* W* A: y' N/ _; x7 }2 Z- j) |; d( H$ Q0 X) T& v
        while( dwLength-- ) {4 @# @/ o5 [0 M0 N) F& e0 f  f
                writetime = (DWORD)elapsed_time;
. a- C% H7 k3 @
% T" M! A! K& b  ?' D' X% L                while( GetQueue( writetime, q ) ) {+ A8 u/ k1 F0 x7 v$ ^+ t& L
                        WriteProcess( q.addr, q.data );2 C) W2 S" {) U: g
                }
- h9 A! J- ~/ u, c. w, ~5 Q# j; z  {  ~3 o
                while( GetExQueue( writetime, q ) ) {
9 K- H: v/ `6 J$ {2 {- C# p                        WriteExProcess( q.addr, q.data );
( W1 S& ?5 {+ a3 C+ b4 e1 t* U5 S                }
# P0 r& x  ?) L/ }; A
, ^$ b3 W* H0 J4 n+ O4 I                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7# A! K) M. Y3 o# r7 \
                output = 0;7 Q- l$ P: b: _! k7 o
                output += internal.Process( 0 )*vol[0];
- s4 L0 M/ c) f  D                output += internal.Process( 1 )*vol[1];
$ ^3 \4 j0 M2 }$ ~1 `# ~2 `7 w: {                output += internal.Process( 2 )*vol[2];/ K' ~  Y" j( d
                output += internal.Process( 3 )*vol[3];
' ]# L- y: R5 A: G, C; q                output += internal.Process( 4 )*vol[4];
) K- T+ n' g3 l; C+ ~
* ?* C: J% k. i  z2 K) _1 \                if( exsound_select & 0x01 ) {
; |) R6 w1 M% G  z  P$ v) `) d                        output += vrc6.Process( 0 )*vol[5];
& G; J/ l, K9 @' y6 i                        output += vrc6.Process( 1 )*vol[6];
( ^2 |' t6 Q7 P* T! o                        output += vrc6.Process( 2 )*vol[7];, r: o9 V; ~3 e( M5 A/ y, F
                }9 P# x9 W; w6 c
                if( exsound_select & 0x02 ) {
5 h" l, V" ~. r- C' Z                        output += vrc7.Process( 0 )*vol[8];
* H9 R" T# e6 ^8 n+ d                }
6 j: U7 T6 S& G9 l. P                if( exsound_select & 0x04 ) {
4 ]7 ?2 {. R: d& h  _4 _7 t                        output += fds.Process( 0 )*vol[9];# m% Y( A4 _9 f: k
                }
/ y6 D% e' V  Y& M                if( exsound_select & 0x08 ) {: O8 g6 ?; {% z2 E  N( Q& Q- z
                        output += mmc5.Process( 0 )*vol[10];) y# Q% ?) K+ o' j4 f
                        output += mmc5.Process( 1 )*vol[11];
% f0 Y# k7 X0 c                        output += mmc5.Process( 2 )*vol[12];
# Z% X4 R' H# t# y                }
  b, L9 A4 [8 |; r: u9 y6 h                if( exsound_select & 0x10 ) {  `- s" S, H) G* I6 H  P1 a
                        output += n106.Process( 0 )*vol[13];
3 `. @1 W, H( {6 J! ]: c& H6 B                        output += n106.Process( 1 )*vol[14];* E& u: r* @1 W! F" B3 z: L
                        output += n106.Process( 2 )*vol[15];
0 ^. \1 g' z: N8 S9 D' ~                        output += n106.Process( 3 )*vol[16];
) G5 w, K4 _6 \4 R( Q                        output += n106.Process( 4 )*vol[17];
, G' [1 n6 a! f/ A4 y. F) t! V1 H                        output += n106.Process( 5 )*vol[18];9 K! |5 A( N, s0 D* I0 ]: Z6 O4 [
                        output += n106.Process( 6 )*vol[19];
5 S8 g; U7 V, e. s6 W2 @. L2 h8 }% s                        output += n106.Process( 7 )*vol[20];
0 E2 m5 f0 Z8 F5 c+ ^1 g) J5 k                }7 r" S$ X& c) j0 T7 X
                if( exsound_select & 0x20 ) {
3 W) ?0 \: x$ I& N4 K7 k! _                        fme7.Process( 3 );        // Envelope & Noise% C2 D9 ~8 P& h7 G
                        output += fme7.Process( 0 )*vol[21];
2 l  B6 \: D0 x+ q- ]6 U: F: N3 O                        output += fme7.Process( 1 )*vol[22];
( ~0 j5 m2 F* V) Q3 S- F                        output += fme7.Process( 2 )*vol[23];4 I. D: S  j( b9 [4 O5 e5 E! t& S/ ~
                }
0 P8 ~$ V& D$ u
" y  V; {8 \& _& l, S* M! O                output >>= 8;3 `% J- u; j9 y- ]" i, Z
0 B# L. s7 _0 p- E0 z* }2 L4 E
                if( nFilterType == 1 ) {
* ?& @3 }  A1 m' x" z                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple). T/ U) W2 O: ~2 Z" U8 x
                        output = (lowpass_filter[0]+output)/2;$ ]0 s  R$ b* I! P
                        lowpass_filter[0] = output;
2 Y9 T3 V& g! j: i4 O$ ~0 Q                } else if( nFilterType == 2 ) {' F# D' f2 p1 J1 Y/ l; P
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
) S. G! V- W9 v5 D" A' Q                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
2 X5 {' z1 X; T8 k                        lowpass_filter[1] = lowpass_filter[0];5 c4 m7 b% L4 }* g# s2 m
                        lowpass_filter[0] = output;- Z: v! Q: }& ?, T9 t
                } else if( nFilterType == 3 ) {1 a1 _% y) S4 {1 t0 _
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
- L; Z% g; z. z- o4 L; Z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;8 E/ @/ }; h7 _7 E0 E
                        lowpass_filter[2] = lowpass_filter[1];
, P+ i/ [0 h. E8 \: L! ^3 j                        lowpass_filter[1] = lowpass_filter[0];, `' O1 q- n, V, j2 n# J
                        lowpass_filter[0] = output;% j' S7 ^. t% \+ n
                } else if( nFilterType == 4 ) {2 y  K8 ]" j' N" Q4 z0 I1 z
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
, L6 n- j! \0 q( z# {                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;; I- e0 K" p% e
                        lowpass_filter[1] = lowpass_filter[0];* e1 W/ B  E9 M$ b3 W9 R
                        lowpass_filter[0] = output;( c9 s4 Q4 N$ Q7 \" y2 |
                }0 d; j% l% @5 ]( g
  S2 G6 C8 p# p8 V: w
#if        0# T* v9 q5 g0 L' F& E: ^* |4 [
                // DC惉暘偺僇僢僩
$ u" m+ E  G0 G7 d+ J5 V                {
( B4 j, N7 p& G3 a  n                static double ave = 0.0, max=0.0, min=0.0;' b( Z: C9 F- R7 o# |5 [. R2 ~% C2 m
                double delta;
/ u5 x9 o" @) N; v% M                delta = (max-min)/32768.0;
" C4 |) C: V) z& h: _                max -= delta;
5 z3 Q: \1 S" n# I- @. u% v% S                min += delta;
" E. H( C, r7 I5 j: Q/ F                if( output > max ) max = output;- R7 |3 g; V* J- D; U
                if( output < min ) min = output;
9 O5 a) h% F. ~* K2 M! H- r                ave -= ave/1024.0;
% ]* q' f1 }, h3 P                ave += (max+min)/2048.0;
7 b7 a0 e, J* o" X  V# H1 x, a, K                output -= (INT)ave;: E" u4 g& u0 U2 X+ o( |
                }, L" C3 q( R, M& ]/ S( n0 Z+ [
#endif
7 E4 T; J9 X3 I1 x( _7 l5 i#if        1
) u. {& _3 U* @* G' N) U& y                // DC惉暘偺僇僢僩(HPF TEST)
3 Q5 D* h- v" O8 h                {, c2 _( P: \# Y! h/ ]* Q
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
. ~0 q; ]3 T: S# t. z+ Q                static        double        cutofftemp = (2.0*3.141592653579*40.0);/ J. _. P% q; y, G
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
2 ?) k; I8 b: K$ B5 P/ q                static        double        tmp = 0.0;
; H# L/ c! v3 @1 n( @8 b7 w% N: U                double        in, out;
: ?) j8 H8 N# e: ^0 I0 e+ x3 j
1 Y/ K7 t8 c& k3 H. K                in = (double)output;/ N# m7 D% f' U& x+ l3 ~9 _
                out = (in - tmp);
3 X% E/ c- K' p  V( }                tmp = tmp + cutoff * out;
6 e9 z- {% W$ m9 h8 F4 v2 U
1 k- B) Y0 `) Q3 s                output = (INT)out;
" x5 a8 j4 i- ]. `) }% r7 h" a                }* ]2 Z) {, t! c, h' C& L) X  T6 ]
#endif- E. i: d3 h0 m3 ^# P
#if        0# x5 w) g3 R/ d% S
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
1 l* @* O0 l6 b6 F  c                {$ B& s) P4 k9 v
                INT        diff = abs(output-last_data);
2 w" C! u, N% g8 t9 w                if( diff > 0x4000 ) {6 _) Y: z8 j3 w
                        output /= 4;" G8 y+ {5 O1 G# Q, _: Y) H2 [9 k
                } else 1 c  r& F, J# g
                if( diff > 0x3000 ) {
( z- M4 L/ ]/ b& [+ d                        output /= 3;
' I+ W! h( y: m( Y: r' c7 b                } else
5 k; i% F5 v) ?% ^* b) U1 a+ B8 I9 M                if( diff > 0x2000 ) {* w: {. E2 ]1 ^: D2 D. Y
                        output /= 2;- G: b3 q# g. m  T1 C+ ^
                }3 Z. d' y) x: @; a* s$ }; \8 x
                last_data = output;5 J' A& P8 {9 x+ W- H
                }
' E( s3 l1 E7 c# ], q8 [#endif  K/ Y" m* B2 j5 z7 O; n
                // Limit
" S# d! {; ]9 M3 }9 w8 n                if( output > 0x7FFF ) {
2 Q$ m) I' n" m5 R& \                        output = 0x7FFF;
2 B% y6 i4 f: X: W                } else if( output < -0x8000 ) {
4 M& r* T, A" ?2 x. U                        output = -0x8000;* ~* A) V& X8 w' `* n% a
                }
$ V$ @. d& t9 q
) T# G2 \* f( L+ t: O                if( nBits != 8 ) {, v' B2 Q1 Q; l3 `  T/ U( O
                        *(SHORT*)lpBuffer = (SHORT)output;
$ z" B) Z: X! F; D1 a& x1 f                        lpBuffer += sizeof(SHORT);
1 n0 ^# L; |6 C" _: T( P9 g                } else {- z' w4 g1 g! g, _7 \
                        *lpBuffer++ = (output>>8)^0x80;/ w5 {* W; X% H: B4 x" W
                }
7 h5 N1 Z7 v. Y6 I3 r, w0 D
  }) Q0 e" N; ?5 M' I3 J                if( nCcount < 0x0100 )
1 C* y  m$ R" ~* o  ^, Y                        pSoundBuf[nCcount++] = (SHORT)output;* z" l' V6 h0 ^3 M3 F1 {+ W

2 {+ j$ C3 o8 q- q4 T, y- T//                elapsedtime += cycle_rate;
) B4 x. N) B( D7 U& i* @                elapsed_time += cycle_rate;6 i- _0 [( v, C- I, U
        }( v6 |8 x4 e" ?% z4 @2 q- B
6 J/ @! F8 b4 e  t. j
#if        1
; Y: B- u8 C$ O9 I- _" _3 O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
* a) g" z# Z( s+ z                elapsed_time = nes->cpu->GetTotalCycles();, [' p. `+ t1 s9 |
        }
( e  o+ }3 @) p) V" G        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 @9 H$ t" z: |3 b3 z2 f
                elapsed_time = nes->cpu->GetTotalCycles();+ j" X* ^5 x$ U( p' {' t9 l
        }
. ~( ?& r% x& T* c#else: l6 R/ w0 G  R: u* s- u
        elapsed_time = nes->cpu->GetTotalCycles();1 J! L+ F- E" d; [
#endif
" o6 |/ w! p4 K9 F9 p- ^1 P}
2 |# [! D8 _7 Z9 ?3 F* v3 \" _) _: h! N( E' t: c$ u" n4 M+ x# s! S0 l
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
4 G  O+ b  m3 kINT        APU::GetChannelFrequency( INT no ): U) v) _& I2 V1 v7 F) ^( x
{& Q- j; J- A# n- b  {) o
        if( !m_bMute[0] )8 y$ `* X5 Y9 l- \0 O' {
                return        0;9 K; _7 y* y2 N1 X7 S
4 n4 \: V0 g# K; N2 f0 A6 h4 @
        // Internal7 Q3 u! X3 G1 g6 O: @) j  }; O
        if( no < 5 ) {! W: @# U5 O6 @- O( O4 x9 R
                return        m_bMute[no+1]?internal.GetFreq( no ):0;, ~8 a: |' [: i+ q: M% R) n7 E
        }; o8 F$ O0 Y3 G( w  k7 _% l
        // VRC60 V2 l$ w# Y" L6 V. k  O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; n5 G# \# L9 r/ Q7 M                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
* J* |9 f: Z+ ~# m        }
! u& ~1 q7 o4 _" ~4 x0 c, o        // FDS
! ?! H$ G1 h  j. L, T        if( (exsound_select & 0x04) && no == 0x300 ) {4 Z1 U- R+ `* R+ Q& Z
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% I& u% _2 {3 m$ T. I/ ^3 i" c        }
" h5 g9 B$ d# i3 N  S9 |, l" _! O0 {% D        // MMC53 b1 X  `8 C; s1 `1 x: {# }
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* N$ `! n# H' |9 Y! d- g
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;, z" W; d: |6 u0 Q) s
        }
7 D( B* L, A5 |3 m6 ?. B! Z        // N1063 f: G8 l% r# b% f
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
! m5 M: g2 ~0 ]; F% i7 u                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  W0 c8 g4 j2 ^+ c. B3 p$ ?        }) T! a8 q7 j7 i8 V2 l. r
        // FME7, c# x2 p0 ~* Y% r! E# ]0 S
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 J0 s$ |+ j4 _                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
2 ]8 T. P5 P: l+ t0 B2 i/ E        }
( \! W# R. L+ W5 u        // VRC74 ^3 f( o3 q! E* S7 b
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
- ^! a" Z& }% [/ C1 I                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
0 F9 V' Z+ a2 o+ C. O        }0 S& z0 k& M5 [1 m1 j
        return        0;
3 H2 W: u6 ^( O6 s! ?}
. }! f( U0 M- u5 w8 g' q: h  H, _/ B  K7 K. v
// State Save/Load
1 B/ m. J' L6 D, s2 |; nvoid        APU::SaveState( LPBYTE p )( ~# K  G: \0 N
{; v5 F0 o6 F5 F: l. y
#ifdef        _DEBUG9 ^, E5 }; V; _& e& p
LPBYTE        pold = p;
/ c0 k: D7 T, ^& a( V& g#endif% ^0 C- f$ v( _! N5 j

+ X9 z. Y6 F! L: u( s( ?        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
3 C3 n2 K& v6 W        QueueFlush();7 F6 M  _  }7 X& F) Q% P( U

9 A7 R, z1 d" Z5 f+ \        internal.SaveState( p );" ^8 K5 x& T7 U3 k
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ M- D+ d% r: ^2 t" ]) Z7 W" _
& U" m5 d: u/ L1 H# p* U2 D5 E0 |8 R        // VRC6
1 m4 F& @: Z/ r+ b        if( exsound_select & 0x01 ) {
* p  g5 ?( D: [+ s                vrc6.SaveState( p );& @4 J3 n5 S; h, m1 O- q+ j
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ N3 N7 R' \- g
        }
/ F. o" h) y! O5 E        // VRC7 (not support)' Z9 Q$ c: z  N+ a& T' c
        if( exsound_select & 0x02 ) {
2 @* `5 Y; Y/ u                vrc7.SaveState( p );
+ V' `- v$ n9 D) v: t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
  r! H- U  J7 u. _- `        }+ ]3 l# |) J% I- ]7 _* ^
        // FDS" \. f, ~( h& u3 @
        if( exsound_select & 0x04 ) {% I* \% c+ e! W5 j" V& o
                fds.SaveState( p );
$ Y6 g0 v7 [8 d: S! [: H  |, H                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ h( c/ K$ f4 G1 t: c( y, F        }# ^/ W% e4 Y# p: P- e2 d) ^% y
        // MMC50 b) l6 k) g. r
        if( exsound_select & 0x08 ) {
- ~( ?7 U4 G6 H# \7 l: E4 D                mmc5.SaveState( p );
7 l" i( z* m2 ^5 s7 g3 U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 G: x0 n4 C0 a* P6 d( j. p
        }
! c9 B, v& ?0 c9 B3 {        // N106! V9 F. Y% N: I1 I7 v% N
        if( exsound_select & 0x10 ) {+ T- [8 u3 E3 G/ ^* ~8 c
                n106.SaveState( p );6 |& Y/ s$ H) k  I$ ?& s
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 ^( |0 s$ }% n; t( R' S- Q( Y
        }
  ~: R% q! ^3 e% s6 w0 o        // FME79 n5 ]4 k  M7 j( r& e% n
        if( exsound_select & 0x20 ) {5 m3 n, H5 S; [  Y5 {
                fme7.SaveState( p );6 D6 m) }) O+ C
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" ~0 u' j; l, W, E2 |' }$ v
        }' k1 j+ m2 n5 n! J
$ z" |3 C, `4 a# b
#ifdef        _DEBUG) e' E; a% n, ]( O0 g* H
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 f3 K  P6 R5 Y9 t! x3 l
#endif( k+ y7 C0 a* h" b7 }
}+ |0 @( u: Z) x$ W$ `  c

: F' h3 W+ u! w; Tvoid        APU::LoadState( LPBYTE p )
* b/ N* y/ t6 o4 Z0 |9 Q$ K{+ L4 y" m8 q( M9 m3 h. [
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& f# r* p6 C/ F
        QueueClear();2 T* u8 l1 S+ a% y8 ~" @

2 x7 ~; S- F0 P! H$ @2 [; {- }        internal.LoadState( p );8 |$ R$ g0 F8 X3 P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( w; G# _1 Q8 Q. b7 f  l
0 w6 d! y2 s" w6 H" P
        // VRC6
3 C# b, H1 g+ r" ]7 z2 H% H        if( exsound_select & 0x01 ) {
1 t5 H0 @) B1 [                vrc6.LoadState( p );. t3 K% m  }2 v
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ J# w5 q- m2 i0 j5 f
        }
) W' h7 n, U, f4 ^        // VRC7 (not support)
2 L3 p  b2 J- @! ?# b9 K) E        if( exsound_select & 0x02 ) {+ J4 [5 g& S" N# j7 L2 a
                vrc7.LoadState( p );
' R* h2 V9 N7 O& A; @: g3 w                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 r/ F9 p: d  M) E% T        }* h6 d0 n) F6 [
        // FDS( E; o3 M* N; _1 r; D7 W
        if( exsound_select & 0x04 ) {8 Q+ n+ P+ j7 t+ x/ V  }/ u# u
                fds.LoadState( p );  ^% k) q3 y5 |( _/ B. {1 o
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! [$ d" @) t+ i2 U6 Q. K
        }
6 A/ \: a7 r& z' m1 l9 o2 ]# I& {        // MMC5
( R+ S$ M1 X$ _: _3 o4 T% R        if( exsound_select & 0x08 ) {9 Y9 t3 G; v& [; @
                mmc5.LoadState( p );- ?1 V. H- y( K' ?/ c6 o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 h) c1 u6 W: W$ d8 ?: z
        }( j/ M+ o& w; B
        // N106) a- l/ }  Y3 p9 K9 G  ?/ ]+ N
        if( exsound_select & 0x10 ) {6 e" D$ ]8 c  d0 ?" D  T$ K$ b
                n106.LoadState( p );1 `; I, i* y, Y/ _  A
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. x( k! l2 _0 x, w
        }
9 h* J9 J9 O0 S  H+ S* E        // FME7
; h% m# K" S  T! Z, m        if( exsound_select & 0x20 ) {, ]& f" S- ]/ M8 s. Z1 q( o& S  U
                fme7.LoadState( p );$ W2 q" Q1 m' j7 |, Z4 t7 C
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 `( d: \7 u$ N  ^        }
: E; d) F3 D1 n( x- Y7 ^3 O) T}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 : C5 q+ v* B% ~9 d- b0 X' X
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 }3 j1 C% b; [/ R' n感激不尽~~
& W6 x9 N- f$ D" r2 l
恩 我對模擬器不是很有研究,1 B5 q+ \5 h# D' F) d
雖然要了解源碼內容,可能不是很困難,
2 I; D) U# p1 x$ N  |' J. G) I2 |不過還是要花時間,個人目前蠻忙碌的。
$ J" J; q0 c6 D2 W0 q+ J+ }$ m
" P) |; j" l( e給你一個朋友的MSN,你可以跟他討論看看,6 H% B4 w1 P5 N7 M. v
他本身是程式設計師,也對FC模擬器很有興趣。
' _/ M& A9 Z7 g% [5 _4 _5 Z& _" J' E) v  ]. a5 R. v. J( E3 W
MSN我就PM到你的信箱了。
/ {" d% G# W* J) V+ z
0 x  k4 Y% V& ^0 [0 P4 J希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
7 ~9 s2 O- N7 _7 Y# g" a呵…… 谢过团长大人~~

: K' ]8 q3 q: _" e6 G' @2 ?- a  ~# ]2 q1 o; }* Y
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
- [  n  d+ U; z0 p3 i2 j团长的朋友都是神,那团长就是神的boss。
1 o9 C) D! @; ]4 Z
哈 不敢當,我只是個平凡人,5 D" m5 h: c. q; P5 y" b$ b& u
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙3 u% v2 C* t: a' s8 t) W8 p
ZYH1 Q  O1 g* `/ C9 O2 @# m" }
QQ:414734306/ Z/ P) W& D2 j# T
Mail:zyh-01@126.com
2 q- v1 F+ n* h: g1 C9 k% T, u9 T8 n
' M% Q# [6 D" n2 x7 v4 D1 x1 x他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 5 k$ r% Y2 H! B2 t  I  I  X
再次对团长大人和悠悠哥的无私帮助表示感谢~~

+ |: X: a7 y5 y7 M. H$ M9 L不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-1 20:31 , Processed in 1.073242 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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