EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 g( R0 V, u" J" V; z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ r! t2 S) z6 E5 _, p; m这里有相应的模拟器源码,就当送给大侠了~~' o  j% Q$ Z7 m) w4 j; H* r
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * K3 ^2 T9 D3 e5 p4 e* c8 P, S- o
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 I$ v  I$ I- _0 t  r% l+ Z" k楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" Y/ g: }9 T" W+ w) J7 g2 P+ H# w9 Q这里有相应的模拟器源码,就当送给大侠 ...
3 C5 A! G3 J5 J% J& c# S' M( B
聲音部分(Audoi Process Unit = APU):
2 a, Y4 a; z4 K! G" W% i.\NES\APU.cpp8 f+ w2 s2 z7 O/ d& n
.\NES\APU.h
* Y2 u2 o8 C: j- _& {' G
$ A/ M# M8 S! j* E8 V& e% s9 _" y& h- h- U: }, J
影像處理部份(Picture Processing Unit = PPU):$ \7 @' [, @1 ?
.\NES\PPU.cpp: [6 T& ~' O& Y
.\NES\PPU.h3 f5 u" ], G. G' r% i/ g, G

% o2 l) j. H% ~! I2 a如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
' |: P8 H$ }# h" g% x7 U- u5 @感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:: ]9 I, C* H" u1 \! M1 a
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ ]+ C. G0 z8 x/ h7 P
//////////////////////////////////////////////////////////////////////////
  q, t8 _) ~/ r8 p4 e$ c//                                                                      //, a7 D9 R3 {+ R. I# a
//      NES APU core                                                    //
2 x/ c. N/ B: P//                                                           Norix      //$ `. v# u7 _4 a% H
//                                               written     2002/06/27 //( `( P$ [& A( v% L* F) Z- R7 f2 l8 t
//                                               last modify ----/--/-- //' j0 r2 ?; o7 z9 j* l7 P
//////////////////////////////////////////////////////////////////////////
2 d9 d/ h2 q1 f) G7 i) C#include "DebugOut.h"* M) Z  y4 S' \% U; r( A# b
#include "App.h"
# \7 `  ]3 |: u+ ]8 u#include "Config.h"
( y9 Z$ N4 l1 K' z
( a6 s- C( g2 z6 I! M#include "nes.h"
) C5 J0 `& r' K6 S. d) V$ c#include "mmu.h"
7 P* ~" t0 W1 f: I& ?#include "cpu.h"
+ a6 F5 M9 W7 A#include "ppu.h"* t5 e; [4 t* @0 o
#include "rom.h") {( M! }5 s% C1 ~2 s  r
#include "apu.h"
- u* C$ }( c3 c9 n4 @, l2 e- ~
9 X3 o4 C! e& o" x, w3 {1 ^// Volume adjust+ Q  M# ^* z6 t* @6 w6 |0 Y
// Internal sounds$ O% Y/ k2 Q* {& D% B" a
#define        RECTANGLE_VOL        (0x0F0)
- S+ l9 o$ u8 }2 M# B#define        TRIANGLE_VOL        (0x130)' H5 ]5 ^; I  f: m  u, e
#define        NOISE_VOL        (0x0C0)7 ~( y9 N$ R9 y$ Z
#define        DPCM_VOL        (0x0F0)2 Z( b; f% M9 a- d: {: b% k. H
// Extra sounds7 E, a& Z! W4 n+ Q
#define        VRC6_VOL        (0x0F0)6 l# d& e( [1 l3 k4 B0 j
#define        VRC7_VOL        (0x130)! o# z4 m+ l% x
#define        FDS_VOL                (0x0F0)& U6 W2 r; h4 d# l7 Y
#define        MMC5_VOL        (0x0F0)
! l, g1 ~4 e, v7 q#define        N106_VOL        (0x088)8 f& j9 g" z- i) V+ _
#define        FME7_VOL        (0x130)
+ A3 F/ |8 C( L& ~4 s) s
8 S( r) K! B1 R' m! C% YAPU::APU( NES* parent )! }) B' d# I3 x9 D4 q1 h
{! W; Y6 ^9 {: U5 O% p% Y% g0 x- t
        exsound_select = 0;; t+ ?: L) g+ H. ~

/ F$ G# T; n) P1 r0 {        nes = parent;+ P  t4 ^. t. H; _4 J4 Q7 e8 |; Y
        internal.SetParent( parent );
, Q' {2 x' B$ q$ \/ S
0 a% l% r8 v: O        last_data = last_diff = 0;
# W: M$ t' j% |3 A$ a- N- ~8 p. n
) c6 x3 c1 K) f% ^        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );1 b9 n. R% d4 g! S8 u$ k

' A3 ^' q1 h. ?  P1 A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
, }# B3 U* K- Q2 j9 t* V        ZEROMEMORY( &queue, sizeof(queue) );
5 J# p3 D+ @) g5 V        ZEROMEMORY( &exqueue, sizeof(exqueue) );( ]( g8 A7 S" U- J( w+ [  V

4 q" e# D9 `! N) T# f# p- o        for( INT i = 0; i < 16; i++ ) {
0 ^% W2 j- B" T4 \                m_bMute = TRUE;
, g8 l& `* s# A2 C  ?        }
/ j. Y  H& M9 F( B4 ]) t1 r0 j/ }) y}
+ b% F/ Z2 c, Y; Q, Y
) I2 K0 f. e3 @5 o4 h" Q9 lAPU::~APU()% e9 E% u& p" L! `, R; |% q* e6 V
{7 z! S! G6 I: ~4 @8 S9 z' u1 j
}+ A, j- ^" u+ E! d7 _! {' t
. F$ v( F# ]+ v$ x' w
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )* h. @; n4 x; _5 ?  W; k
{
3 H! Z# @( |9 F3 }7 i# e; @        queue.data[queue.wrptr].time = writetime;# X) X- A5 S2 z2 H1 Z: H
        queue.data[queue.wrptr].addr = addr;8 }2 T! T& m( i5 ?6 L9 a
        queue.data[queue.wrptr].data = data;
  e/ B# m: Z1 }- m6 m- l$ h        queue.wrptr++;
( b- y. w; i( j6 w3 N7 X        queue.wrptr&=QUEUE_LENGTH-1;
% f' Q. |. p1 H; \        if( queue.wrptr == queue.rdptr ) {. C: Q) {& [( l$ L1 m
                DEBUGOUT( "queue overflow.\n" );
7 M4 e* i6 w$ ]! h" r        }6 V5 p( K# W( X( n
}$ g, g, m3 ], I7 W9 b0 ^8 Z, ]

0 `0 @' z% E4 R4 M! KBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )8 B( r6 G0 i. I. P1 U
{
- a. s" [  U3 M; t        if( queue.wrptr == queue.rdptr ) {* ~0 v9 Q: y5 C7 Z- y8 q+ E  T1 i
                return        FALSE;
# H5 {3 N2 k0 k) E        }3 A4 q( p" W4 D) f6 [
        if( queue.data[queue.rdptr].time <= writetime ) {' T) w2 A( z6 D% X$ W! t6 c. b
                ret = queue.data[queue.rdptr];* E& ?0 d4 w- Y
                queue.rdptr++;
9 B( p6 x+ w% S2 K7 p7 n! J" E                queue.rdptr&=QUEUE_LENGTH-1;
. i/ G2 V5 S9 X4 X8 G9 {                return        TRUE;
( H/ b5 H9 K, X% x        }8 ]% O& G$ N% y8 e9 a
        return        FALSE;: P; n9 ?5 M6 H+ R6 L9 P, a8 c- Q
}
- _7 u* D7 r/ L" |9 {* k9 F& J! x7 {- O& @. x/ B
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
& n. {" r& \* |" R6 s, t4 ?6 |+ R{
7 P0 F  t+ Z: p5 y1 R        exqueue.data[exqueue.wrptr].time = writetime;
+ V3 t1 e) L$ g/ J$ Y  N        exqueue.data[exqueue.wrptr].addr = addr;
+ u0 Y) {4 ~) s2 K# `2 O4 m        exqueue.data[exqueue.wrptr].data = data;
9 N7 V$ x# D# c- h1 k/ }        exqueue.wrptr++;, C! s% K/ Y" k' C* d
        exqueue.wrptr&=QUEUE_LENGTH-1;; T, j! q7 a- k+ j- z
        if( exqueue.wrptr == exqueue.rdptr ) {
5 h, B, T1 d+ q/ S4 ?( ?  v                DEBUGOUT( "exqueue overflow.\n" );
) A9 Y; c, j1 D5 @        }
7 \( u- Y% t/ Q6 T7 H}
, L; ~9 m0 l* F; O. ]3 u+ C0 U4 R% L' D8 B
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 ?: ^6 d' Z: e7 Z7 U6 R
{4 w+ g, Y" C& L. w$ v4 |
        if( exqueue.wrptr == exqueue.rdptr ) {8 S4 Z" C/ w* L" ?' g. t
                return        FALSE;
' w$ w, Z0 f+ K8 y( k        }# W6 D0 `3 _: |* p& F9 z  L
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; p2 l( f+ P" b+ |* b
                ret = exqueue.data[exqueue.rdptr];. F$ F  s7 ^2 b' @7 u% G# z
                exqueue.rdptr++;* M; t) [3 U5 F" r# t: Z
                exqueue.rdptr&=QUEUE_LENGTH-1;
# X3 C! l2 }* U9 l9 k                return        TRUE;
( B+ E( H6 Y! a0 r6 ~' s        }
& q$ K7 Z& d4 ?& q& [        return        FALSE;
, F% |) l! ^& {4 E}! q8 o! G7 q$ ?

0 h3 O7 E% |3 K- X& ~0 K' R0 ~void        APU::QueueClear()
4 ~6 b. j2 @: [{
. [( T0 K  Q; d2 y        ZEROMEMORY( &queue, sizeof(queue) );
7 l% a, Q/ F" \2 M        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 Y( i7 u4 `: w! }0 G3 w4 j& o7 V$ M}
. i5 ~" m6 R6 b( q* j7 n) s6 U* ~6 |, ?
void        APU::QueueFlush()
' E# {+ G# @4 G: h/ \$ g" H4 p{1 O% |! C' n, |9 z- s  g
        while( queue.wrptr != queue.rdptr ) {
. N5 m; A  w5 K( K6 H( {, [0 |                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
4 v3 I7 Z/ h& s5 T1 y7 I- H                queue.rdptr++;* u. r. A- g8 F- t, f$ e  d/ d
                queue.rdptr&=QUEUE_LENGTH-1;
' I) {) d" j/ i- A& K! C        }
$ `& o( a8 u8 _4 W; B8 O! ^  p. s( A: V- p& O1 v& V0 d/ O
        while( exqueue.wrptr != exqueue.rdptr ) {3 G. S+ G4 A; a, r2 _7 L! I4 f
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% y5 \9 Q8 [) Q, {! Y. l
                exqueue.rdptr++;" b/ b9 O4 j- q& c/ e9 V5 k
                exqueue.rdptr&=QUEUE_LENGTH-1;
! D0 q% C" m- k. A' ]        }
+ D2 v& q% i- I( ^}
  L. k0 F6 G& I2 ]/ i) Y) A
9 x4 L4 [2 h  T2 W: }void        APU::SoundSetup()" N8 p, p! p! p1 H- g, \
{, F9 E& Q2 R; O6 X9 Q
        FLOAT        fClock = nes->nescfg->CpuClock;+ o3 P" o# n. q) P" q3 {% I: y7 o
        INT        nRate = (INT)Config.sound.nRate;
2 i+ o: N" x6 j; F        internal.Setup( fClock, nRate );
: V/ o. Y: h1 h$ s+ U2 @        vrc6.Setup( fClock, nRate );
6 x0 L6 o( f  }# |! M4 s& e6 \+ p9 Q        vrc7.Setup( fClock, nRate );
, J- _% u4 K* M6 h        mmc5.Setup( fClock, nRate );
/ I- ?$ r; _: |9 x        fds.Setup ( fClock, nRate );( f; B. y' J& P# a4 z: F
        n106.Setup( fClock, nRate );0 P4 w- H+ K$ Y* M) V
        fme7.Setup( fClock, nRate );
8 x0 F5 V9 Y2 ?( n}" l+ D2 q* M! V- d$ z' I8 c3 |- I
/ E1 t0 x5 C7 }: F% L  z$ f
void        APU::Reset()4 w! Y  K3 C3 T/ b& g. t( u
{& w. D1 b, c& k) D7 p
        ZEROMEMORY( &queue, sizeof(queue) );. @+ z; o/ B9 V$ m; A& C( S+ }0 F1 Y, w
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ E  H8 b. n! e, x+ M. l& ^! C) ~7 k1 H, z, L4 W
        elapsed_time = 0;1 H* ^$ v2 H( ]! ^& V
- f$ j0 {" S  @; ?4 F
        FLOAT        fClock = nes->nescfg->CpuClock;5 Q0 v& I% @' R
        INT        nRate = (INT)Config.sound.nRate;
/ W& ?, g. E7 O  `# C        internal.Reset( fClock, nRate );
6 Y$ Z  g2 ^, T% R+ o& o9 a! T        vrc6.Reset( fClock, nRate );) b. W8 ^2 o8 p$ `: k  _: V
        vrc7.Reset( fClock, nRate );" e# L. h& }. j" P* T! y* O0 ~
        mmc5.Reset( fClock, nRate );
5 b7 ~) s8 _( t$ ~( j        fds.Reset ( fClock, nRate );
, g4 S  J/ t- V        n106.Reset( fClock, nRate );% i6 n) p9 C$ ^7 o( U0 g7 x
        fme7.Reset( fClock, nRate );
3 _) z' m; J: ~( z" Z& [- m1 [/ z
. w. L& F% L1 l  ~1 ]" j        SoundSetup();3 X' j' H* b; f; R/ K2 h
}
& [' l/ Q! g2 T" h, H- W
3 r2 R& a" w6 H2 Z9 zvoid        APU::SelectExSound( BYTE data )7 n1 v& Y! e( M. [  L* X) u$ G3 w
{" N; e* R6 s+ `9 U
        exsound_select = data;8 P9 j* }% a$ m1 |
}
, A7 z( _; ]2 X$ A; t* ?, N( J! U, l+ D" \8 D7 Z2 A
BYTE        APU::Read( WORD addr )
% ?% B: X, L9 {{
; ]5 e0 R+ ]8 m  n1 I: m2 _+ T1 r        return        internal.SyncRead( addr );9 K) j7 d; v, l! y
}
- {) J: e* o4 P- ]
: I3 P7 @3 I! i0 K* W$ a/ X, w% dvoid        APU::Write( WORD addr, BYTE data )
# K5 i0 N7 I1 }8 e% `{
0 n2 h2 `, {7 c6 e7 c0 {" U        // $4018偼VirtuaNES屌桳億乕僩
- m9 X) \2 u1 {# C* d& G. k        if( addr >= 0x4000 && addr <= 0x401F ) {
: w  o( z3 h/ J/ B% q                internal.SyncWrite( addr, data );
9 d# |! W+ R# }% f+ g% b                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
; i1 ]. I5 b" g        }
% z5 C, j; X- F: Y}, l. j$ b- V( A* w9 J+ j1 \

$ A, Z/ o! b* {BYTE        APU::ExRead( WORD addr ): ]" m6 G# p4 I' Z) j+ m. i. O
{1 l5 H4 t! k8 _9 o8 u) i+ c
BYTE        data = 0;8 B% h2 Z' k1 B8 _
' M, X/ n% _! s# N2 Q' [
        if( exsound_select & 0x10 ) {
# a; T0 t5 Z  K% B8 l                if( addr == 0x4800 ) {* n! m* m: P5 t
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );4 K3 Q$ |, Q# A7 K5 X! R; u  E
                }
) A  _/ [$ t8 A( _        }$ \  D; \' e8 ?! l: a9 J
        if( exsound_select & 0x04 ) {
0 @; |5 B; g; J                if( addr >= 0x4040 && addr < 0x4100 ) {
7 M+ k8 K" W+ I& {* j                        data = fds.SyncRead( addr );& u1 D$ _! e3 M; F; g& R6 J7 u
                }
5 f+ p6 u6 t- y! S        }- q; U: h3 {* c" }! M; p
        if( exsound_select & 0x08 ) {
& T: m" B! e6 Z4 X9 _/ h" O                if( addr >= 0x5000 && addr <= 0x5015 ) {+ j  ]0 I" r' ?& R/ V
                        data = mmc5.SyncRead( addr );
& ]0 e3 b! |; [3 ^9 ^. ]                }
) \% v: C" d0 e8 [0 t        }
3 l' Y8 y* ~: Y- d' F! ^' a2 V5 a) x2 z
        return        data;
+ A! m8 c8 A. t, d}- s8 a$ s* @2 }3 e
+ A6 [6 l- K& @3 R" E  }
void        APU::ExWrite( WORD addr, BYTE data )5 z+ e7 I  `0 ?' ~$ j4 `' X
{
& c0 B0 ^) m( r0 O" y( m- G  k) s        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );$ [7 F5 v% _* I8 q9 v' o
5 h4 F: E9 L/ [; s1 X: X' `  A
        if( exsound_select & 0x04 ) {; H6 j+ S+ ]$ v9 s6 y) \: i' U/ s
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 ?3 z5 }* t; k7 D, p0 u                        fds.SyncWrite( addr, data );
% \) x0 s% y$ Y) k% ~4 G4 e' b                }
7 Y; q! ?1 v! T        }* f$ w, J0 r3 S0 }/ Y

! W5 y& r) |8 U2 i        if( exsound_select & 0x08 ) {
% Y  ^/ f1 S9 G) N/ h                if( addr >= 0x5000 && addr <= 0x5015 ) {0 E! F) L/ b5 L+ Q2 I" ^
                        mmc5.SyncWrite( addr, data );$ r4 Z- I2 u  X% g2 \7 [% c
                }
( U& z$ l, R: x8 M9 q        }
3 L) A- t5 P  O% ?$ H}( d0 y5 Y# b! C  @
0 T" S8 J9 r: @- G9 }/ W
void        APU::Sync()( m% P* ^0 `! ]5 j2 e
{  Y  ~9 `6 X; B  _% E0 i1 k
}, L2 ?: [7 M8 F
5 e/ g1 D$ C) E( o
void        APU::SyncDPCM( INT cycles )5 ^) |3 ?2 k5 l" y
{7 g1 p  m2 ?$ d& H2 U
        internal.Sync( cycles );
5 o" f& D; }& I: B/ z5 t6 \/ j: P, L- T& E8 x
        if( exsound_select & 0x04 ) {7 e- G2 {, X  m- H% j
                fds.Sync( cycles );) _. P, }+ M, w% O  v+ w
        }
1 q8 e* m" K9 V) V7 Q# H: V$ }9 Z        if( exsound_select & 0x08 ) {5 A9 _. e/ U+ v- b: [9 j% w1 H
                mmc5.Sync( cycles );& T& |+ J" ]/ _
        }6 S8 J, Y) W0 W! N2 }
}; y( L3 Y! a6 L& I

+ M1 r" n" N4 E+ [- qvoid        APU::WriteProcess( WORD addr, BYTE data )7 m4 O! s- Q4 Z  E
{
, T$ A) d& e7 g4 J) B, o& N6 t" b        // $4018偼VirtuaNES屌桳億乕僩& o, `& \+ d) h) y
        if( addr >= 0x4000 && addr <= 0x401F ) {( v. J9 l- X( w
                internal.Write( addr, data );
) j8 l$ K: K; G- |        }: A+ ?8 m: x7 a, c: {1 a% {
}" D/ [8 o/ V! Y6 n+ x4 {

4 T- q" K0 s$ E+ z$ qvoid        APU::WriteExProcess( WORD addr, BYTE data )% ^! z7 }! y, @+ F2 w  ?& j
{/ P  D% n2 r9 l4 I6 R7 D
        if( exsound_select & 0x01 ) {% b% q5 }7 w+ }( P7 Q* I6 O6 o( ^
                vrc6.Write( addr, data );* A  G4 L, Y7 H
        }# k0 U% i/ v- l( h6 y) `6 C
        if( exsound_select & 0x02 ) {6 T1 N( W% |- O$ ^' e1 G- R
                vrc7.Write( addr, data );6 W- Z9 B3 Q8 ]. j; H
        }" {7 C$ U  d  ?' A/ P4 I& }: b6 N
        if( exsound_select & 0x04 ) {. x1 n$ p1 b: C5 I) E
                fds.Write( addr, data );$ X, G( j  t  Y6 e7 M9 W' y5 d- I
        }
% V$ l9 m* F9 b2 t) N+ D        if( exsound_select & 0x08 ) {2 e* q5 X; g+ k- u7 G. `6 S9 Z
                mmc5.Write( addr, data );
& Z4 x! }+ U1 Y4 S' U        }
( }1 K. [4 R  m$ H0 N        if( exsound_select & 0x10 ) {- Z' @$ f: ^4 K  i
                if( addr == 0x0000 ) {, d' A* {' {" }. @' Y& [
                        BYTE        dummy = n106.Read( addr );
, q5 i3 P+ R$ q" r( A) E                } else {
9 r& j, O/ s6 ~: j! g$ A& S) R6 n                        n106.Write( addr, data );( m; |$ w4 @+ L5 O
                }0 L- K6 k/ f7 {' f. j% e! z# }
        }
- i* z! N- o1 E$ P/ G        if( exsound_select & 0x20 ) {4 j6 `! l) f4 F6 b
                fme7.Write( addr, data );1 i3 m1 n# S  Y/ q: L8 r: C; i
        }
6 |+ O; K" l! x2 t}& `3 K! _% T- ^" w/ ^

7 E# ^5 ]5 c% F3 y/ ~1 I8 p' O0 Svoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ F" y; j7 B7 u, L2 q
{
& O! h  U7 y- D5 z% m, GINT        nBits = Config.sound.nBits;
  N3 M7 c3 d9 y; J7 vDWORD        dwLength = dwSize / (nBits/8);5 a' t9 n9 v1 o; ]3 h7 U1 v$ y9 @. I
INT        output;
; F( W- B, h: x$ B* y, dQUEUEDATA q;
8 B  i: [: D+ B" u2 BDWORD        writetime;
$ j, o* U6 T6 X8 V8 F) K. V' R9 m
* T5 c% Q, N! X) A* K7 {LPSHORT        pSoundBuf = m_SoundBuffer;! A" |* A( s) i4 {  G7 f
INT        nCcount = 0;
2 I. O( h7 g# u$ V) k7 a8 E" g8 S# M5 @* n
INT        nFilterType = Config.sound.nFilterType;% X; l5 G, }( |- h
: F  n; ~0 A$ M7 \  T
        if( !Config.sound.bEnable ) {
" V& ?! T( T+ L% {% y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );# l# K3 U0 |; J" D. R1 ]" n, ]
                return;$ l9 g2 b7 H, u' z5 z; i4 p
        }! Z3 ?+ v4 `* p" z" M3 x, ?
  R: B$ M8 C" z# j" [2 E) q
        // Volume setup9 e$ o0 J: ~3 N3 g7 K& z
        //  0:Master% Z2 S' U& R7 G- [; A$ X6 k+ h
        //  1:Rectangle 1
/ F4 K0 J: K( p1 R        //  2:Rectangle 2* U+ E' q4 ?0 w2 o* `; m. }$ h
        //  3:Triangle
# E$ m' a, q* w( I; J" ]        //  4:Noise' B  l! y1 T! o: f
        //  5:DPCM) t+ ?5 H. V; |* q1 }. U. U
        //  6:VRC6
. m' A1 [: j+ {6 n9 i. G        //  7:VRC7
: s6 D8 z% \# }" A1 u' z! u% z        //  8:FDS
8 x$ C: B2 i6 G; w4 H. y& K' g' W        //  9:MMC5
7 L1 f( c# z0 n3 |+ f4 L( z        // 10:N106
: j* Y% s" ]. Z8 E; v3 k" ^        // 11:FME7
' U0 o. Y1 j# A6 Y$ \0 d8 Z: z- X! W        INT        vol[24];
/ @" W. e: K$ S7 ?6 H        BOOL*        bMute = m_bMute;
5 k. ^* x& S5 _0 w/ h* r; F        SHORT*        nVolume = Config.sound.nVolume;2 e( _4 ?3 T6 s+ X7 {/ I+ {" x) U6 T

; ~4 J* \# U4 ^5 f$ [        INT        nMasterVolume = bMute[0]?nVolume[0]:0;3 f7 L4 p, }4 z% x& e

1 J' k+ X" i1 T3 X& [% I( I) Z        // Internal
8 u" u% \( C' @2 E        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 p6 v: X, ?& t7 G2 i9 m        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; \& L  c! z1 M! c0 z
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
( e% H4 ]$ G6 ?2 Z, C        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
; x7 i& ^# G! h6 _4 Y- `4 t: F        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;# I$ m% i$ e, ^- E0 o/ B% b9 k
3 v* R* Q( [; \  m+ v
        // VRC6
4 `* _) G# k+ R& e        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) D; }- l3 ~* n, U, |4 `) C- d
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% Y( q( q# q: N+ x4 {
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 s# {- g6 m" _8 @
4 {6 D3 S& m6 @        // VRC7" Q1 c1 }  ]$ ]# H9 E% c
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
! \9 s5 \" J3 d# m( s3 _( S9 V1 a2 \
        // FDS
9 Y/ P, C0 L  v( v7 C6 ^8 M! r3 Y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;% t( I# s/ E# |- q6 U5 r: Z
0 Y; T6 o/ K$ n) `. F1 E( `
        // MMC5
8 ~' g6 u- S1 `. D- Q        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  A; F8 l- ]3 d+ v3 [
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* X4 @. @6 D4 i% o8 g; `, S0 c
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% Z: k/ ], m4 d% ^* g0 D  J' `* s) Z- ^/ m  e' h* u) W2 @$ i% `
        // N1066 ?6 K& b" v8 o* s% t2 x
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" o* d  [/ H; Z& ~
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 k$ h% f& G1 x5 ^: e        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 x; ~" l6 p+ D$ D& Y3 }9 t  U+ p' i' I7 D        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" [# k# b; L( M1 }2 }2 n' |% c4 ]        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ @2 u: {  _3 N+ i7 Y
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 X6 y5 f' U/ w& C* F/ d# s        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 ]3 z& l$ n+ w3 d9 J0 |3 L' h
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* `- W4 t- B4 g. w6 q$ F1 T

3 x% r& [$ r* a# ?& u; F8 L  y  x        // FME7" R$ }4 Y" b% j1 |2 v; R6 {
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ V/ i0 V" N3 v6 X        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 c- M* s3 J) c( C
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ k- ?, a9 j8 x; D4 `, Z0 ?, l' {9 h5 D/ w! Y3 \
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
0 ~' G# U, e% p' O& I' h0 y        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;( I, k" s* I' D1 v5 ~/ x% Y2 _" A$ q
* e: E( e6 p) ?' }* B3 M5 }5 m# `0 L
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟* D. x7 p: {+ J2 N
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
1 J8 P4 W' u+ m1 d! T0 V/ @                QueueFlush();0 ]1 ^  ~0 _2 X! Q
        }
" I( [' u6 h3 p6 h8 |: s( g9 Q: \3 I0 t& \, Q
        while( dwLength-- ) {
0 [' ?/ T$ r6 q% X                writetime = (DWORD)elapsed_time;
9 X! n% J" D5 G0 D+ m! d" A% l- o* Z9 n9 h5 n
                while( GetQueue( writetime, q ) ) {5 W3 G  M' `6 \. X" O( @: B
                        WriteProcess( q.addr, q.data );  J/ i# V0 p1 q2 B) v
                }
5 p+ \0 \- I, J* O2 i3 h/ h) w0 {6 y8 x
                while( GetExQueue( writetime, q ) ) {" L: u  P) z: k' Z9 D( ^# m
                        WriteExProcess( q.addr, q.data );9 V) i% a" o: K. W" o0 l6 H
                }+ N+ j# }  j+ v- Z, d8 a( M3 N# a; q

" v" u) R, o7 y                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ O; s" o" ~* _6 S- n+ W4 M4 B, ^
                output = 0;
; o7 C5 w. z6 g9 s                output += internal.Process( 0 )*vol[0];0 t+ q: q! s6 T1 W+ A
                output += internal.Process( 1 )*vol[1];6 u$ m/ b/ ]; |
                output += internal.Process( 2 )*vol[2];  X' r$ v7 W4 x
                output += internal.Process( 3 )*vol[3];
& S2 K9 c& E% ^! ]# N6 Z; j. z1 l                output += internal.Process( 4 )*vol[4];! E, g9 I7 \9 Z- {
* T$ U6 k' Q5 |" k+ F3 L
                if( exsound_select & 0x01 ) {' T; e, U* d" [% u& _& L
                        output += vrc6.Process( 0 )*vol[5];
7 k" O1 ]/ O% |4 y% J                        output += vrc6.Process( 1 )*vol[6];+ ]+ ]  m! r/ W8 Y1 a
                        output += vrc6.Process( 2 )*vol[7];
) W0 D4 m4 D: Z  w$ [                }
  J" q" `" d! v! ]( k                if( exsound_select & 0x02 ) {3 b5 W1 T2 b- m) P5 N0 @- T3 ~
                        output += vrc7.Process( 0 )*vol[8];( r/ w0 Z6 N+ e2 {; J: Q6 R. y
                }
; e8 d, g$ d6 q2 W, C# l. A                if( exsound_select & 0x04 ) {: A6 c9 _3 p; l# C
                        output += fds.Process( 0 )*vol[9];
8 f  k! ?* l: U3 T% X, t                }) Q  @. W% k5 z
                if( exsound_select & 0x08 ) {4 P/ T5 V" G2 F( y
                        output += mmc5.Process( 0 )*vol[10];
* z1 ~8 @0 R( ^* z) ?# ]  @2 F                        output += mmc5.Process( 1 )*vol[11];
) L. K5 Y6 }) L; c- k7 i                        output += mmc5.Process( 2 )*vol[12];# |+ a# k6 v: [* A3 Y5 {# D; H
                }
% i, V! X- U) a                if( exsound_select & 0x10 ) {/ j/ a" N0 s+ Y7 n" T
                        output += n106.Process( 0 )*vol[13];/ u$ N+ U% H4 j" n
                        output += n106.Process( 1 )*vol[14];
7 `0 N' \) k4 b                        output += n106.Process( 2 )*vol[15];& t7 \0 m' \' R: J
                        output += n106.Process( 3 )*vol[16];
- r, d! i7 [* f. n- `& v                        output += n106.Process( 4 )*vol[17];4 a5 V, ~$ O' a2 Z- u6 g3 @! W7 _
                        output += n106.Process( 5 )*vol[18];
4 E7 a( f( k) P0 p0 _                        output += n106.Process( 6 )*vol[19];' Z' [' b. j8 N; x
                        output += n106.Process( 7 )*vol[20];
+ a2 q/ H7 O/ K                }. y+ O- H- S/ w' h6 ~( {
                if( exsound_select & 0x20 ) {, a; B* |$ E: Y& g5 f
                        fme7.Process( 3 );        // Envelope & Noise
6 N6 \6 }3 c/ N                        output += fme7.Process( 0 )*vol[21];2 D% [4 J, U& K$ I% A/ v
                        output += fme7.Process( 1 )*vol[22];
. v9 Q& j( j2 s+ Y) @                        output += fme7.Process( 2 )*vol[23];
3 |: h# w, H. \, L8 B8 L                }* a) q- n& E) `+ X$ L4 j* V

9 V; c7 u! G9 m, S& _! ^                output >>= 8;
3 O. ^3 k+ B$ H/ l
2 W3 e0 c" l; D; d" X/ j                if( nFilterType == 1 ) {: I: s5 N7 Q1 I3 N4 @" e- x
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 _2 _5 T1 `7 e9 ?+ j
                        output = (lowpass_filter[0]+output)/2;  L# c  G; f  K+ a: f. V, ]
                        lowpass_filter[0] = output;7 c( J$ j' z% l  W% m
                } else if( nFilterType == 2 ) {( f3 I' ?/ n. M
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
7 u- C; Q/ k* l4 |8 o8 i                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; Z" S. q. T" s: Z6 x& f5 I
                        lowpass_filter[1] = lowpass_filter[0];3 h9 ^6 Q) V( T! b4 I+ K% N
                        lowpass_filter[0] = output;
# m! h. u, m3 D8 q& _                } else if( nFilterType == 3 ) {+ ]  ^3 J1 X, z" d. t
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)1 s4 P/ W1 s. t4 Q2 |' U
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" j1 X6 F: B6 j; U( g9 L
                        lowpass_filter[2] = lowpass_filter[1];' K8 g5 J9 Y6 d' |: F2 Z
                        lowpass_filter[1] = lowpass_filter[0];
1 _) X8 }6 n( B. S+ g! g: {9 K                        lowpass_filter[0] = output;
. C2 u7 Q1 T9 p: T3 r* x/ I                } else if( nFilterType == 4 ) {
: X" G3 J  e* `                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)% p* u9 q8 v/ {: [- }3 ]
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
/ V; m2 Q+ m1 E, t) ^                        lowpass_filter[1] = lowpass_filter[0];
& b$ _5 W$ Q# n                        lowpass_filter[0] = output;
0 i; E1 Q( q  Z1 y: Z7 L( @                }2 f8 b' [, L' z9 A9 E* y

% d4 G  \  X6 o) W6 V; x#if        01 I. H6 }9 j0 F, G* p
                // DC惉暘偺僇僢僩
- V6 u! o( ~' @, L1 U) X                {! F+ N0 Z/ @5 H' G( Q
                static double ave = 0.0, max=0.0, min=0.0;+ s4 F! J/ j+ ]2 |/ |/ F/ k* e2 l
                double delta;
) w8 N3 b. ]  F3 `3 \2 g7 n0 o                delta = (max-min)/32768.0;
& _; \5 F: N/ |0 ^$ K                max -= delta;) k- q  A: p# u2 n4 ~( O$ `
                min += delta;
4 V) m6 p$ c6 X6 L, _3 l1 Q. m                if( output > max ) max = output;
9 d; T# \$ X, J& `                if( output < min ) min = output;5 S  D- W$ U+ i! g4 f2 D
                ave -= ave/1024.0;1 Z( O6 X& T$ }1 o
                ave += (max+min)/2048.0;' n: C* s+ X6 m7 R$ K
                output -= (INT)ave;
8 K1 i  C: M1 d/ ^5 M* j                }3 v$ k' x8 u/ y5 x& ~9 w
#endif- V! i2 r% v  U2 X" @
#if        1" a4 ?" \# _* w$ @; w
                // DC惉暘偺僇僢僩(HPF TEST)
6 ]  ]: I: P. Z% `9 U                {
8 r- l( S8 o4 J# G4 O//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);8 C! C9 G# u! r0 `& U
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
1 G- b- O' p: M' R                double        cutoff = cutofftemp/(double)Config.sound.nRate;
( R+ P) t% b% t0 B6 [                static        double        tmp = 0.0;
# L% p' ^# I5 _& G1 p. U, s                double        in, out;
" o/ Q  d% P* T% P+ u( v& B, M: s- d  H( N8 U" P
                in = (double)output;
1 J3 q7 ~& K2 M; A                out = (in - tmp);8 i* J$ f3 S; S; O8 E/ g! r) t* A7 Q
                tmp = tmp + cutoff * out;* H! O# R* z2 s" P
* W- P$ C5 Z( j4 N8 T) T* e) b) p2 p
                output = (INT)out;2 M# i& I( [. s' f9 U/ R' e  L$ ]; F
                }
( b$ ^/ C% |! `' `/ {, ^5 {: ~#endif
( i  U: y- X1 Q- l( H% _#if        01 o) ^2 a) S+ M1 h
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
: I; V7 \3 Y% _  R                {
# T) @7 e; u( i0 s4 g1 n& z0 }7 ^                INT        diff = abs(output-last_data);0 z) ^6 L# i0 N, c+ I# U) J
                if( diff > 0x4000 ) {: G1 P5 J5 E; K1 k8 w& C' S7 G8 ]" D
                        output /= 4;
2 ], ]9 ]5 _% u( K+ Z                } else ( q4 k; }) [* z& C" W- [
                if( diff > 0x3000 ) {4 e: d2 J# |& ?: z. a$ k" ]
                        output /= 3;  I1 M/ F9 g% \" X5 J. o1 Y
                } else
7 u/ X! m* Z+ f                if( diff > 0x2000 ) {! N7 A/ z& O; F* V
                        output /= 2;
. v5 z; P( {. g7 t( ?: U3 k, r                }1 C6 p/ f4 p9 {$ @5 m' c& Y( J
                last_data = output;# S5 i6 J4 y- n
                }. \5 i- _1 f9 |/ I/ X! i
#endif" F/ ~: O4 O. B! t/ D5 B
                // Limit
/ z% }# r" T9 ]9 C! m& c                if( output > 0x7FFF ) {3 U& [, x/ X6 n
                        output = 0x7FFF;( {0 `! S- L( c3 V& `0 y
                } else if( output < -0x8000 ) {
/ P; `2 D7 t1 B0 w/ ~                        output = -0x8000;
. Q+ x) g2 C! t/ p                }
" u  i" f0 T# O
6 [1 p/ ?# z- u* q2 ~/ f+ }                if( nBits != 8 ) {
( ]: @( {5 T. e+ G( X/ ^# g                        *(SHORT*)lpBuffer = (SHORT)output;
( T/ ^( O( e& F. h0 f( |                        lpBuffer += sizeof(SHORT);
) E: i" L- p/ J, |/ x7 ~                } else {
4 m: \3 r7 r5 [                        *lpBuffer++ = (output>>8)^0x80;1 g( D# R! H5 `8 c) N: A
                }, e# y6 f$ `; C, X% ~

0 E: C" u$ S# |, y                if( nCcount < 0x0100 )% S( ^! Q1 s8 l) b. y5 S1 N
                        pSoundBuf[nCcount++] = (SHORT)output;
$ N/ @5 E2 Y" y/ A
& M# ^1 P+ A* A0 S//                elapsedtime += cycle_rate;$ f# E6 s  E/ _1 A; }2 m4 e
                elapsed_time += cycle_rate;. \1 ^' X8 L( r9 I. J' N
        }
; {% C5 D! D! c: P
) e0 A  O+ f9 |4 x+ y#if        1
5 |7 R0 e2 [2 L9 r# A! z( r* l        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {3 F0 H- E+ i; ]. V8 @
                elapsed_time = nes->cpu->GetTotalCycles();
- `* S! D* R4 ^9 c! a0 V        }; c; Q9 Q- Q9 r  M6 G; f  s( W" d
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
$ s6 G# v- N( ]3 M                elapsed_time = nes->cpu->GetTotalCycles();
- p. B! Y( d4 }, |# u& K* E& }% O        }
  D0 M2 U, @* k5 p#else: u* j* f) f' d5 v- n" f5 f
        elapsed_time = nes->cpu->GetTotalCycles();
7 q# ?: ]+ Z- |9 e1 e6 z" T#endif1 [, o# g: t4 w7 C# _
}
' G( t) w; M. j" g5 K3 u/ @5 L
+ s, D* o$ V; w/ V" o8 |// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
; P% y8 z5 a* F7 ^3 XINT        APU::GetChannelFrequency( INT no )
5 }6 Y3 Z* K% t4 i& ^0 s2 D  j! j{7 T5 t, I3 Z; j3 J+ O. l6 W! x
        if( !m_bMute[0] )
- K- x# c  L- p0 Q4 o; _. h                return        0;
6 i4 [: c9 h( ?% U- r: H. K% R6 f, X
  b. q1 S+ w& r# O6 V8 o. g! M7 @        // Internal5 @5 S. F: e) a
        if( no < 5 ) {
/ B* B6 a" J2 D                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ S$ n8 r  [& s4 R; [
        }! R9 k  W" P5 u# b" ]" U
        // VRC67 v; F1 E% s, E% c5 d# D
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
2 h1 I) |& x- o$ N/ p- }" G                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
! p" g: s3 ?0 f. G, k0 r        }
8 N. N" B2 p; u: Y% j        // FDS# a6 h9 k; G/ N2 _# t
        if( (exsound_select & 0x04) && no == 0x300 ) {6 g1 ?6 C+ D: m0 L
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
1 B0 f: l) @! N        }9 z( _% F* v8 W
        // MMC5
7 A' a6 u% o$ |+ ~, g$ u$ {9 r" I        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {' A, g# ]' T3 V3 p4 S
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
  u" N, Z# P6 R! ^8 _3 M) X        }# L6 o" B. b% V' y0 _
        // N106
( S& X$ N# V' @        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
% u3 }" q& w7 j0 k1 u0 Z( z! l; R                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;/ q6 U& W' _& R0 z9 Q/ M
        }
7 s* C/ ~; F0 V        // FME78 K1 f! y# [; s5 [2 ?: }8 v" N0 |
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {& A6 C$ }$ t# _* R
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;5 N4 E3 I6 ~8 X6 N- e1 T
        }
5 D: E% |( M1 L3 [( X. \. \        // VRC7
7 I. A2 q$ J/ m1 ?2 b, U& ~        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
5 T9 ]6 L) F# n7 Y: P* X6 Q7 `1 G                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;' ~$ y8 q1 I! P0 u9 c
        }
& C& ~* r  B, z2 k2 x        return        0;
" `9 f# l3 @& ]: w. b& D, d7 Q}
5 }7 l8 V8 K3 J% A! R. _* t& d2 q' j) M: u' B" S4 I. l
// State Save/Load
! n" Y9 Z* v: x8 P7 D7 Kvoid        APU::SaveState( LPBYTE p )+ z& F2 Y: J. U0 T1 {' S  K0 q+ `
{' w7 b& F: j: I7 |& F/ M# r6 L& ~
#ifdef        _DEBUG
, s$ a* k" h$ E3 _2 k7 uLPBYTE        pold = p;# @  [9 V1 |' N+ c$ A$ W
#endif
3 }' T2 x6 h) f8 Q/ ^
) E0 I7 S$ R% D: h) s- T+ v        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
# I7 v1 \% N" C! g        QueueFlush();
- q6 S& U' x6 |* c3 @, }
: _) x' M, J2 c5 A" i9 i& B3 u        internal.SaveState( p );6 S9 K6 ~% w! y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" O+ f& X1 c: n, u; b- m% Q( n, ^, c9 M2 ], {' G4 D& P, t0 ~. K* O
        // VRC6- \& l" M* Y9 [
        if( exsound_select & 0x01 ) {
( u- Z( M( \% @, T* A: R) t) f! C                vrc6.SaveState( p );
3 R3 a8 I6 |" K1 D4 i1 ~6 ^                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
% k. r( Q4 K8 k6 ~% o        }
# W6 D: e0 W7 ^) v; P& N( J        // VRC7 (not support)- V/ P0 O. w  V7 B/ [
        if( exsound_select & 0x02 ) {
' L9 u& \: G, ]# J3 j& `8 e                vrc7.SaveState( p );
5 f# H0 p0 |3 v8 R- [                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 @6 e4 ]- H8 r; M        }( e5 b. F0 _9 Y# _  H9 E* c7 C
        // FDS( g5 ?7 C* m6 z& U+ i( `# |! O/ _" k
        if( exsound_select & 0x04 ) {- W- Z: h  G4 C2 s8 t+ p/ y
                fds.SaveState( p );
% u8 ]- @# }! u' s# |0 K! O, v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 ?/ ?! P  x5 D" t$ \
        }
& y. Q# o0 D9 x. i8 K        // MMC5
; d7 U$ p' T7 R: F7 A        if( exsound_select & 0x08 ) {" m$ X4 [) q0 u9 y# H  J
                mmc5.SaveState( p );
( `( v% M( E- c                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
3 _/ K1 h9 I+ f6 }$ C8 [        }8 W: C& {  m( u% a
        // N1065 i3 q, f! i" ~% v/ L$ E
        if( exsound_select & 0x10 ) {
3 a- G  \* E! q" F0 q3 }* C. V- v: ^                n106.SaveState( p );- p7 I/ T  G5 T5 F7 G
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( W5 j; x4 s8 v2 P
        }0 d! n& @6 V5 i" [# \% {
        // FME7, Z+ u0 N( s, f% [' E; b% A+ C  E( \
        if( exsound_select & 0x20 ) {
5 o; C$ j8 s' z; M" {                fme7.SaveState( p );
5 ~1 d' z7 n  h                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" b- f) ~' z% u7 ^  ~' z. S        }0 J9 w! r0 S" W. I+ p

! \* x9 t1 ]7 O: }#ifdef        _DEBUG6 V; m9 ^4 [" w4 ?( P" J
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ n: `# x. c0 j6 x, J; w$ L. y, d#endif
; b0 O. f$ X" s, p2 R! H! m}% I2 g% C) x/ ^: n* A, H

$ T: k4 l3 W. {* k3 ~  Z2 Fvoid        APU::LoadState( LPBYTE p )
% R$ ~, c6 M- m: s1 ~{2 I; }/ e- ^( h9 |9 A! u5 |0 t
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 w* h2 C& `8 `        QueueClear();  W6 N2 I* y& K1 K0 q2 }

" g" k) g: }% e  U0 V: n# `        internal.LoadState( p );
1 b. @' w& n/ ]6 u" B& [3 e5 [        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 O  |9 o* n5 N$ S/ `! P' N
$ b; u* m; T3 g$ |: Z
        // VRC6
$ R0 _4 R- D* _4 @" d6 y        if( exsound_select & 0x01 ) {! ]" f& w  g8 f8 c& R2 z* g
                vrc6.LoadState( p );
* `: U3 {. X2 S7 A                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, |% t  P6 c8 v) G5 K( \& \        }7 E: Y! `( r9 k2 Q- I0 m
        // VRC7 (not support)
9 U, B0 R6 _: N( r6 l& E        if( exsound_select & 0x02 ) {6 U: J5 t* u; D. J; R
                vrc7.LoadState( p );
& c& Y7 F! q4 y# T                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' g4 u3 F: f: t& e( z
        }
- v0 \/ R9 V( B; }; s7 ?        // FDS  a7 S- f9 [# P0 P  t* r
        if( exsound_select & 0x04 ) {
$ k$ b0 X* }  ]8 K. ^0 \) H                fds.LoadState( p );  L* G4 N1 [! l3 E
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding) |6 q2 h  @+ `
        }
" q. U# X. f  t. c6 E        // MMC55 O/ X$ Y) l+ k) D" ]
        if( exsound_select & 0x08 ) {- C% Q, W( f" _7 m
                mmc5.LoadState( p );
; e  g8 d  i7 [3 D% X, B2 t                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 g; H1 ^) E. T5 R2 k7 P8 E        }3 e9 B5 A* N5 H" W
        // N106
# Y! r) I2 m" J/ M        if( exsound_select & 0x10 ) {
2 u" l2 H* w- C# v/ D                n106.LoadState( p );
% v  v0 N: n* f9 H; \! a                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' V5 A- q3 H# S! {3 i8 a; Y: V
        }
: L$ `$ Y) a/ [8 l& m: o" F* g5 ]        // FME72 q7 c2 W5 w; [8 T6 u( C; I
        if( exsound_select & 0x20 ) {) M; s3 C' w' T& A9 S2 \
                fme7.LoadState( p );( l% k) q/ u% X* v' |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, |& Q. A3 R% m% V& I+ f* @        }3 Q$ k7 Z2 Q  o5 W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 4 R; J; v7 z$ S6 B& ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 N# p& ?" ?4 ^+ k9 U感激不尽~~

- J4 E2 s$ T$ Z' G恩 我對模擬器不是很有研究,: E: h* [2 F$ S$ B! b) p2 M6 w/ _0 w
雖然要了解源碼內容,可能不是很困難,
+ d5 i" i; r; C& v不過還是要花時間,個人目前蠻忙碌的。; @+ t! I1 a" S9 `* o- f
# H4 q$ Z) e( G. z$ W; O* e! I' ]2 u, ]
給你一個朋友的MSN,你可以跟他討論看看,/ y$ H* S% B7 y
他本身是程式設計師,也對FC模擬器很有興趣。/ p3 o$ A/ j0 m& F2 Y

  A8 `; Y1 F# t2 n( J5 VMSN我就PM到你的信箱了。8 r+ A# I9 E( z) S$ {
- t: ^. [8 i$ N- w
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表   v& J0 f5 ]( [! i: W
呵…… 谢过团长大人~~
5 m; u& ]) v; C7 J* k$ m5 Z. s. v

% o& L& y+ V2 @, L% ^, P6 y哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 " T* S4 ~* C+ Y# U( m
团长的朋友都是神,那团长就是神的boss。
5 v8 F. y9 S8 ?6 e' a3 `2 p
哈 不敢當,我只是個平凡人,
" S" d/ }3 c& i( p& X要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 _9 ]5 \+ e2 f  H# kZYH+ u' N( I# T0 B
QQ:414734306
1 V# v! F; U; L( |4 nMail:zyh-01@126.com
8 J( ^% J2 b( H% ], k2 g& O
1 p+ m! ~( z4 S他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
/ K4 C* {1 ]8 @  K; K2 p再次对团长大人和悠悠哥的无私帮助表示感谢~~

$ g( L- x3 C) |7 b: I不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 08:58 , Processed in 1.095703 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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