EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; T& c' {) }& r8 L! {7 f, F楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% y9 t% F) a0 _' m3 _8 b4 ~' B这里有相应的模拟器源码,就当送给大侠了~~8 F. `: `! ~3 j0 a
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 C% W! @' Z# V
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 l% ?5 R' |9 f5 L6 U楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% t5 _( J# ^" {% x" ~; {
这里有相应的模拟器源码,就当送给大侠 ...
! A! e, ]2 R, b2 U8 o5 [
聲音部分(Audoi Process Unit = APU):
- S1 N9 W1 n$ B& H6 a.\NES\APU.cpp
6 f- l* @$ S" l: {" }6 f.\NES\APU.h
' X2 A5 d. f( k3 ]; d# k8 |( K% |( n

! F" J5 {- a* s3 i' C: d影像處理部份(Picture Processing Unit = PPU):
8 x* j& f1 F2 Y5 Q1 V.\NES\PPU.cpp
; O# v5 a' J# u4 ^2 ?2 V5 @" o: C.\NES\PPU.h
5 k9 D, v  Q. O3 P2 _0 W
3 U( v1 |. ^! a8 k1 A) E4 ?7 u如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; q5 y* \4 t6 q2 k& x
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
& s- T! i6 t# F7 f3 ]! e* X  ~/ D0 i//////////////////////////////////////////////////////////////////////////6 k" @+ z9 ]9 L- m* l/ u
//                                                                      //
9 s+ v/ j. t; m2 @) m& g//      NES APU core                                                    //3 I. [" p( y$ s
//                                                           Norix      //% b4 e' J5 K+ s# G4 J
//                                               written     2002/06/27 //
* t5 r! D4 f) g//                                               last modify ----/--/-- //0 i& S5 `+ k8 S6 R
//////////////////////////////////////////////////////////////////////////, f  Y, E9 W* p9 g3 C. g7 Z) ~
#include "DebugOut.h". W& G. d! L! d  \4 ?' h" o, w! c
#include "App.h"  [. U! v" x& B. Q1 E
#include "Config.h"1 x" c% g" S( ^3 o+ ^- A

/ L3 k1 O$ Y- P9 s% ], i#include "nes.h"
) o# @# h$ L, Z/ ?#include "mmu.h"
/ `" x2 H* [9 B#include "cpu.h"
3 s: {% n( T; {6 n#include "ppu.h"( F- E' S% B. L& `* {2 {$ s# G
#include "rom.h"# m( p* ^( r3 ~/ `+ L' d. s1 b1 J$ n
#include "apu.h"
" Y& r- C5 O, ]* i& c- e; n
' W0 o9 C; B, {  O  V, }// Volume adjust
6 W# b6 ^2 P1 m2 j" a$ G4 J& k& r// Internal sounds
. n4 g2 ~. P) Q# M" _% T. f#define        RECTANGLE_VOL        (0x0F0)
% Y/ Q* l7 L8 f3 v/ [#define        TRIANGLE_VOL        (0x130)( [1 g5 U5 x8 @) g# s1 h
#define        NOISE_VOL        (0x0C0)
% @  w: K; X- o0 \#define        DPCM_VOL        (0x0F0)
& K* @9 z0 F# v+ N) ]2 S9 b1 u// Extra sounds- e; `) l/ o( G/ q& ?, n7 n
#define        VRC6_VOL        (0x0F0)6 C5 q- w- g. u: F" a
#define        VRC7_VOL        (0x130)
2 ^/ h) }: \) K+ S#define        FDS_VOL                (0x0F0)
; ]6 g4 n% Z  |( ]! N. b#define        MMC5_VOL        (0x0F0)0 ~# ?# e. y) ]; e2 q
#define        N106_VOL        (0x088)4 S- E0 A: x8 M2 l) X; `
#define        FME7_VOL        (0x130)& f7 G3 j8 [/ L0 O
  d& U$ g- F+ O1 ~; j* t
APU::APU( NES* parent )* i: n7 @' N" F8 ]# [( y
{
9 Y  m" l2 I1 U% ~9 ^: U        exsound_select = 0;
! G! x4 E1 ]6 l2 L* F0 g! q, ~3 M8 }
        nes = parent;- H& ~+ @! E" a# B
        internal.SetParent( parent );" ^! O9 m% U5 ?& y: H6 p
* l, N. \( J+ }# J+ c% Y% ~
        last_data = last_diff = 0;- ~" H$ w& c  S
. X/ J( `' Z* s1 L$ Y: X6 k* H, q
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) p" y- h& W6 u! j' n
; s9 V% r( _" H/ }9 d: [2 q
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
% h3 I0 v1 k0 B2 F3 ?        ZEROMEMORY( &queue, sizeof(queue) );0 G% j" P# Z  ]. s+ {* W8 H
        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 |9 a2 @9 t' _# e
, B4 h) B' s7 ?6 l9 e
        for( INT i = 0; i < 16; i++ ) {8 F& o# P+ n: V4 [& @
                m_bMute = TRUE;
7 p6 Q1 ], [! [        }
4 _) G- i. ?  s+ U4 D}
; B; g8 K1 r/ @9 ^: P, ?" O$ i" F! r- J5 T6 W: s  V! q$ F, a
APU::~APU()
/ a, k8 L  T4 X) F* @( x& r{
% e2 E, K2 [: G, Y. I; D}  [6 j3 }! J% ?- r
+ D& w6 @% \" F
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )" N. q- X" A" c6 M
{
' \% i- c' }, I. k( m0 G- E% a        queue.data[queue.wrptr].time = writetime;% j, }: K% R# o2 \: o7 d+ ^3 L3 l$ L
        queue.data[queue.wrptr].addr = addr;
& c3 @% `1 `; I! T  k6 \# ]        queue.data[queue.wrptr].data = data;9 F! J" h& g) y* T5 f% j) B, V# u
        queue.wrptr++;
! E  I3 t; @8 _        queue.wrptr&=QUEUE_LENGTH-1;
) C' P0 y7 K9 A        if( queue.wrptr == queue.rdptr ) {
# G- h, b0 E/ z+ U                DEBUGOUT( "queue overflow.\n" );
1 }( E2 s5 y4 N+ a) G/ ]        }
2 m. `" U* y+ }$ M0 h6 F}
) M7 `# C& x' ?6 S# F/ B/ Q' H) p3 S0 d" g$ }  @
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
$ J7 a+ P2 L* Y3 G) V{% q7 g+ q' G/ O$ m8 k3 |) i
        if( queue.wrptr == queue.rdptr ) {- P0 q9 T+ Y) b* m, S, |. j
                return        FALSE;4 n: C4 `! R" J: s* r7 h, q
        }
9 Z' E% `; T- q- l: s$ |: o/ s& L0 F        if( queue.data[queue.rdptr].time <= writetime ) {
! X* K/ z; a5 N: ^: R                ret = queue.data[queue.rdptr];1 s' r- r" L: J% o. l9 R' T
                queue.rdptr++;
" @7 U' `2 h7 ^/ ~' \0 \                queue.rdptr&=QUEUE_LENGTH-1;0 y6 |8 y6 G8 o% ]
                return        TRUE;; n; i1 I  l; |% k2 Q
        }
  g- Y3 l( T$ `' V0 [$ W        return        FALSE;
4 g( T1 \. F' O1 _) S}
1 S0 _) C8 Z  O" ]/ r2 v7 {0 H  i
  _) v5 C6 q1 y8 lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
5 A4 C& V" \$ \0 n{
. s  G  }0 d$ X% L& `7 Q+ S! o        exqueue.data[exqueue.wrptr].time = writetime;$ h' U4 ]" f( V" M4 n3 G; C3 k
        exqueue.data[exqueue.wrptr].addr = addr;: G( ]2 Q& T) f1 r
        exqueue.data[exqueue.wrptr].data = data;! g8 H3 P* ?* @  g, p
        exqueue.wrptr++;
# g! S% |0 V5 p% ~( A/ s: p# z4 A        exqueue.wrptr&=QUEUE_LENGTH-1;9 ~3 D5 M3 ~! b+ a9 \5 ~5 a$ n
        if( exqueue.wrptr == exqueue.rdptr ) {; Q: {9 T1 X4 K9 w7 [1 U
                DEBUGOUT( "exqueue overflow.\n" );
# m/ b2 Q  X  |; C& P        }
8 A( U* ]1 G; n, y3 i% k}6 I8 b1 G" U% r5 q0 k

5 F' u% J! w+ t1 [BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
9 \% B% a3 n, F{7 g' ^8 }, A# J) e0 Y4 p
        if( exqueue.wrptr == exqueue.rdptr ) {
- r5 p5 d3 Q9 Q- f3 H  A$ }                return        FALSE;$ W' I1 J+ z5 v' Y7 I
        }. p; Y5 {) @' I( j
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
- t, V. O( D5 B* T# ?- X: q                ret = exqueue.data[exqueue.rdptr];
  ~/ g2 C4 ?, R: L7 L                exqueue.rdptr++;
* e; o7 c7 u$ F' c                exqueue.rdptr&=QUEUE_LENGTH-1;
2 e3 a7 Y; |1 R; \                return        TRUE;
. X% J- F2 P# }$ `$ P& l        }2 ]" A6 Y# f7 p3 o2 W. [& k
        return        FALSE;
. Y  h6 T% ?" m7 Y) Y( W}6 y1 p8 V8 h) _5 F/ E
+ }/ o. w" b5 c; }( y) ~1 p6 ]
void        APU::QueueClear()
4 i( F. g1 S: G" b9 a. R% f' E! Q& Z{0 w+ i7 L3 m, b9 A, Z$ s
        ZEROMEMORY( &queue, sizeof(queue) );
9 C* E/ |% _, H1 s0 y: G        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# F: x. [7 P9 V. Y4 O! p}
! p; C- l' i  e
) F& b# _7 i* z' Y! j! b& Qvoid        APU::QueueFlush()* i! N- Y. i: j5 o, E# C8 Q
{; f' }" j) |& X4 r% K( g
        while( queue.wrptr != queue.rdptr ) {% K4 ?% b. W) T2 r* q3 F
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
) m. s- N: w$ P, {, z# _1 W                queue.rdptr++;
: @; \+ b( _6 J. }5 [                queue.rdptr&=QUEUE_LENGTH-1;
/ }4 ?( n: o6 s. |. Q  _; e        }* x8 }" l9 G1 W, U2 Q9 z2 M* h
% p4 p3 z( @# B
        while( exqueue.wrptr != exqueue.rdptr ) {
2 F+ j$ _: x' g$ D% N$ Z                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
4 @. n8 S& G# h  k                exqueue.rdptr++;
, t  A2 \9 ~4 n) i) N/ h                exqueue.rdptr&=QUEUE_LENGTH-1;# w8 m, h% B: C. w
        }$ c: C' G" X1 _- A* ?% U
}; g! R9 c1 r5 p, `" M2 B

1 G4 d3 M- K* ivoid        APU::SoundSetup()0 U3 Z: j4 _, M7 Q& h
{
8 Q; r, ?2 ^2 S, y/ P" d        FLOAT        fClock = nes->nescfg->CpuClock;% I5 N0 C5 a/ b! s0 ]5 X- t2 L/ ~
        INT        nRate = (INT)Config.sound.nRate;
% x, B6 I- L# R9 J! B        internal.Setup( fClock, nRate );. t) c: A, |& Z1 d9 z- R+ {
        vrc6.Setup( fClock, nRate );; o. c+ S7 k) Y6 z
        vrc7.Setup( fClock, nRate );' l5 y3 o0 b3 G/ y6 h7 r- H, l
        mmc5.Setup( fClock, nRate );( c4 n. j7 U7 s) R  y4 ?! c, P
        fds.Setup ( fClock, nRate );
  f. A9 P( C  r/ |2 z  ^* o        n106.Setup( fClock, nRate );
. w* H" I& Z" i! H7 F        fme7.Setup( fClock, nRate );/ |# a0 R2 i8 O6 Q" e0 F
}
5 G! x  C  ]3 H* f- O; [4 ^- ?" O# A8 u  T$ d
void        APU::Reset()
' ~8 y7 S" D1 ?& y: r# p{% j& A; S8 T$ c9 P. }
        ZEROMEMORY( &queue, sizeof(queue) );
  I4 {7 v9 H: T" ~        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 s) ?: Z( ]! a9 i) T3 Z7 ~7 {
8 y/ J$ K0 c: {& m& v5 e/ _, `        elapsed_time = 0;
) p, j: c  y' E/ Y! n0 R
) v! s8 b3 n2 B4 w9 c$ e        FLOAT        fClock = nes->nescfg->CpuClock;
! @# `8 ^3 _' l- Q5 _! S( T& D1 t& z        INT        nRate = (INT)Config.sound.nRate;
' m! a% r+ d7 L: n0 a9 ?        internal.Reset( fClock, nRate );. o2 p& T# a7 k$ M: W' z
        vrc6.Reset( fClock, nRate );
7 F: q7 X$ j& K7 G$ L5 I* |        vrc7.Reset( fClock, nRate );
7 V) k8 g6 J, S1 R9 F- E* _        mmc5.Reset( fClock, nRate );
) ^( W* l1 Z" M0 L9 R        fds.Reset ( fClock, nRate );+ ^, P  h# g9 L4 L0 u; i9 o$ O3 @
        n106.Reset( fClock, nRate );/ S( k& }9 x! n9 n% ^
        fme7.Reset( fClock, nRate );
  `) x/ v2 {- R8 Y( i
* b4 L0 M; d, d" I* B- W3 r        SoundSetup();
; B& D6 K8 e% u$ |7 D}) `. H& g' ~  g( I

% y* D$ T5 k5 W5 y! [1 K5 yvoid        APU::SelectExSound( BYTE data )
5 f+ D, x4 u2 \{
8 }5 z: A& S: W# {( @6 T        exsound_select = data;# g/ x' y7 k, ]4 \
}1 [2 j* i/ F$ `3 w3 O9 R4 b. r3 ^5 J$ Q
5 ]3 {; x1 ^6 d* T
BYTE        APU::Read( WORD addr )
2 n) \; J4 {, T" C7 q7 x- q{
9 B- D6 K3 N' g1 {2 v) k" P        return        internal.SyncRead( addr );
( ~& D- y! Q0 T, k) g+ W}' s0 k& r6 T" n* n5 r3 A
0 V+ f' O( u6 T4 m7 H" ^  \
void        APU::Write( WORD addr, BYTE data )4 d( U: e) r8 I- ?+ p2 v
{3 v& F* R# s1 c) N) h  L+ o
        // $4018偼VirtuaNES屌桳億乕僩
- Y+ Q5 N& H3 W8 [( F0 p) \8 R        if( addr >= 0x4000 && addr <= 0x401F ) {
0 n( F9 k, `" Q6 [, C                internal.SyncWrite( addr, data );9 H) a( p! k$ X! u; w. R  T2 y
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& H: D0 s6 K0 _        }* n6 d4 r" q0 d2 F( U8 B
}
* E9 {: C1 L/ A. n+ L8 W8 ^6 G0 k8 s! A6 \, G1 {
BYTE        APU::ExRead( WORD addr )' m& I& ~- ^6 j# S' d* \* X
{
, s9 h) x: z& P6 KBYTE        data = 0;
; y0 M& C' E9 J7 e& g0 E  ]5 n; U' \4 P& W  n% {, R5 F! F
        if( exsound_select & 0x10 ) {( @* E9 a2 H, \
                if( addr == 0x4800 ) {9 t  J/ V1 F) j
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. ^$ C, n* w& l$ w3 h2 M9 U& _) y                }
) i$ Y5 |7 i8 Z& o7 G; q        }
% J  l( u' D5 N        if( exsound_select & 0x04 ) {
1 R  e3 }! z0 _                if( addr >= 0x4040 && addr < 0x4100 ) {
* @8 y( f7 k+ z( i                        data = fds.SyncRead( addr );
  t6 W" P2 _- u$ r& V+ A2 w                }
( o8 q" _- C: T  B! h9 n5 @+ d        }) c! ], r# {- I, f9 ^% E" U* P
        if( exsound_select & 0x08 ) {
: l$ z( Z7 o' o5 d                if( addr >= 0x5000 && addr <= 0x5015 ) {
, H  R  r% O  f; B- x* ~/ [+ [' }                        data = mmc5.SyncRead( addr );9 j% m# V, a2 `/ t  i" D# a
                }6 `9 t6 \6 U* e$ N4 O: k2 E  Q# f6 c
        }3 |/ v; ]' R. Q

, y5 \3 @( g) C! d! D- y        return        data;
, I% }5 m$ {$ ?5 x3 Z  R+ L}
( o+ c8 @' K- ]
/ R/ ?8 P& Q5 V* T- T; L4 Hvoid        APU::ExWrite( WORD addr, BYTE data )
* C; W6 i6 i4 Y# G1 |% A9 Z& z{
6 b2 H1 o, g5 R4 O        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& w  S! A" V. H& t" f9 [
$ i8 J2 m# x6 ^! c  D$ E/ C+ a! b        if( exsound_select & 0x04 ) {
: c7 X0 q, M4 b/ d                if( addr >= 0x4040 && addr < 0x4100 ) {9 g. z; e. d/ W5 E. y+ i
                        fds.SyncWrite( addr, data );
6 X& K, F2 ~. U- N# |                }6 p/ k7 Q; N4 F
        }
! s) H, j2 r& x: @( i# V! L1 G: r8 x" M4 D# X
        if( exsound_select & 0x08 ) {
( [; Q  |$ v& s3 j5 f1 L                if( addr >= 0x5000 && addr <= 0x5015 ) {1 J6 ~7 w- z. O, O, h( d/ l% @
                        mmc5.SyncWrite( addr, data );
( B5 [  g  ]( ?8 o) z+ x3 T7 H# ^' X                }
8 q$ H6 T/ q" X. u( i        }
  ^! u+ ]& V9 ~! a7 O/ y}) i* i; W1 s8 H1 \
6 \: G/ r) c. Z2 h
void        APU::Sync()
/ g4 ^/ L  W# @; }8 j{; ~/ d& v3 a' i; b
}: d2 N/ U1 L% \1 M' [8 K$ H9 [: v4 j

! W& g3 Q: f' p; ]void        APU::SyncDPCM( INT cycles )+ r# ~, ]7 m9 c' V
{3 `% Q: @6 \) P
        internal.Sync( cycles );
" R4 ], j# X9 N( F0 p3 I9 ]: v7 @
. b1 s* k! y- o/ O: J% S4 F3 t        if( exsound_select & 0x04 ) {1 V& s: q. ]- j$ W1 V& c% N
                fds.Sync( cycles );: i( v2 @# \8 l3 g9 r" F. I8 I; R+ d
        }# y% X4 D/ O7 H
        if( exsound_select & 0x08 ) {
. Y+ Y* e3 G1 F5 H                mmc5.Sync( cycles );
& h' R' Z9 l& h+ q4 i/ T        }1 g  v, t7 g$ l) o
}+ J4 B1 t) b9 c& y0 k
% D( J  M) Y% X. B+ `) P9 x" W- B
void        APU::WriteProcess( WORD addr, BYTE data )
+ `: ^! p6 N! l/ ]) d{7 b; \7 O! Q1 s4 K7 Y) S
        // $4018偼VirtuaNES屌桳億乕僩) V; P& Q1 ]7 _* ?5 P# c! e
        if( addr >= 0x4000 && addr <= 0x401F ) {
! F' D4 U; P+ T* z' j4 k- m                internal.Write( addr, data );5 P! l  v5 @5 u& a8 t) |
        }
+ C: H. V9 b" x- O. Z( o* S: O; @, K}/ t, F9 G7 s4 Y0 j. T* d1 T
6 T! m7 R' a% q- N' b
void        APU::WriteExProcess( WORD addr, BYTE data )
. F3 p3 F# P  A! a. t{
( t# R; a- T! D( ]% K        if( exsound_select & 0x01 ) {
/ h$ F3 s/ J; I. x3 Z                vrc6.Write( addr, data );
# s1 S$ m+ l7 [        }
' ?' n! R) f) P  [, @        if( exsound_select & 0x02 ) {3 S/ J. U9 R% e1 R* F  B  C
                vrc7.Write( addr, data );
% K: P  z; B' k" F5 m        }
/ O- k3 |) o2 c" [3 u  D+ O        if( exsound_select & 0x04 ) {
( {# k' N8 H/ [6 S5 B' E                fds.Write( addr, data );9 [, i6 f7 J( l
        }) s4 ?8 F, Z5 F+ j0 O
        if( exsound_select & 0x08 ) {4 W' [) _. M7 ~3 y
                mmc5.Write( addr, data );9 W) N  x  G- P: W
        }
8 b! W" v( h8 \1 Y( h        if( exsound_select & 0x10 ) {
3 T" f8 r# S) E- l2 O                if( addr == 0x0000 ) {3 n3 p+ d5 H& d
                        BYTE        dummy = n106.Read( addr );
* p9 p* e4 O0 N3 [; _                } else {
4 i% P, i9 g1 D# d& z: v                        n106.Write( addr, data );
& T# }! w9 J: }) u/ W                }
8 N- ]1 o( n7 n' I4 P        }
. g8 O3 L, I" u3 P        if( exsound_select & 0x20 ) {
+ Y  J5 i, F* t( O                fme7.Write( addr, data );) j( q  C- ^* n$ j; }: C
        }
% K4 ?8 I; s3 m0 V5 y7 _}" p$ A' O6 p! `9 y/ ^$ B  k2 M: k

( y6 g0 j' g( evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )% q: E7 ]2 V) s! I1 F' k
{
! W( u. r$ l3 i5 ~INT        nBits = Config.sound.nBits;
" O+ h! ?! J+ Z/ s. N4 FDWORD        dwLength = dwSize / (nBits/8);4 l" x4 ]9 U7 k- y0 F
INT        output;
7 Z8 r) R- O. o7 A# m* zQUEUEDATA q;$ _7 y- O! a# v: ~7 f; W
DWORD        writetime;: w! }. _& S8 P; L; m% ~
* H  l! c# B* x9 r( e% F7 C
LPSHORT        pSoundBuf = m_SoundBuffer;
* h  I9 i9 l3 s+ O/ a- XINT        nCcount = 0;
# a7 ^) _4 l" a$ f- m/ u( x) m& g  D9 k" f$ |
INT        nFilterType = Config.sound.nFilterType;
0 e7 ]6 X5 X) R. f/ m/ a/ j8 V' Y7 E1 {7 \
        if( !Config.sound.bEnable ) {( ?7 h' G, \3 k' ^3 C7 [
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );1 u- F* i" t& ]& i
                return;
7 v6 E1 D% Z$ l  t6 N/ s% t        }8 z7 j' e( e3 H  x( T. m0 k2 Q
+ l4 R" p! w2 u& S. s
        // Volume setup2 V: k1 S$ _4 T, z" }! j4 _3 K
        //  0:Master
2 \' h* o0 n% a        //  1:Rectangle 1
$ r1 c5 i% B1 `$ n% b+ L. o& s        //  2:Rectangle 2
- a% y4 Z3 ]3 k3 [        //  3:Triangle0 j0 q, W+ ?( D7 @6 T; R# Y' A
        //  4:Noise
. _, @! L* r3 }# ^( |        //  5:DPCM3 Y. B; t4 g" m2 Z# D
        //  6:VRC6
: y" G; |' z# z* v4 h) h        //  7:VRC7
# e8 z% \" S4 W* N  i        //  8:FDS
) Y+ `0 A/ ^5 P        //  9:MMC57 c$ c$ q4 Z7 M9 E8 E& p
        // 10:N106
% y" {: C( v) v4 J4 r* r% J+ C        // 11:FME7( q9 {+ ^# [! D) j6 H; Z
        INT        vol[24];! l7 @0 c7 n" O4 t' F3 M2 c  W
        BOOL*        bMute = m_bMute;
8 V5 @7 k4 Z$ p" K        SHORT*        nVolume = Config.sound.nVolume;
' p1 l/ P( z' ~- E, Z+ D  |; F3 H/ l! T/ H# \  ~+ L9 B  W9 s* Y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;2 X, n+ \% t7 z, V, t7 Y# V
0 C% E5 z# L1 g5 t" t, _
        // Internal( M$ e, ?1 J6 C" O
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;7 q* J( i, K6 [  n
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
5 Z( E2 \$ f9 E) @9 B        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
4 K( @& z( X- V1 f        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
& |7 [; q, u0 x9 n  i4 }1 T3 G3 b3 U        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;9 ]% D/ V# J6 H$ u3 V1 m( e
- E% ?" ]1 |# J0 Y  b4 y
        // VRC6
# B$ d& n, [: F4 s        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ u1 q3 R7 D4 C& e
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 K7 n; b2 W9 g( G: `
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ X, E4 K( L. o3 N
1 d9 ?7 \8 J7 R& m2 \* ~
        // VRC7- ]! _- l4 A) V7 n9 b
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, c  Q* Z8 q, f9 f; t/ A1 i- Z  E7 i: @$ ?6 Y: V- E8 B* L& {$ c& \& b$ z
        // FDS
5 F% s8 M; T# U        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
! w% J1 v3 K5 h& o8 p5 Q! p5 ?& P) U* \0 N, }5 C
        // MMC56 o) P: [' W: P3 x
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% v& j1 q2 I; }% r) N' _  a        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ K( A: o- V" {' ~        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 R0 G- q" n* a- c) }4 Q+ I3 z9 B
        // N106
; a: _  V0 X+ n        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  D* s- p3 d6 X1 e+ t0 v" T7 i/ I        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% ?5 ~* @' K1 K( \! }& ]4 i! S
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 L/ J6 L. C) S* d  \! m        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# ?" S% Q3 [- j
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ t' N  ]' O$ Y2 c/ k        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' @7 G, u5 n" S% m6 j! f5 Z) _        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 y! d$ p6 r" f6 c# E' W" v: n
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 p7 L+ o! D$ ], v

9 D+ i& G3 Z( H        // FME7
# x; A" d& `# i$ t3 g2 l. k        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% V1 B& L4 S$ Q1 H        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ e- K4 K1 ^( j        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 |% e, @' d. }
, s- H7 |, f: N8 U; r
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
) V. ~3 x6 H" e9 |& }; A        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. a* ^' q' o& B9 _+ D- a5 @# l. h: b$ v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
" S; |( Q6 P1 i        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
% M6 M" X8 V! k' c                QueueFlush();9 O8 v$ {0 P# U" z2 F, q% E2 D! @
        }
+ G, P+ M4 [, X: f2 J8 F. S4 d3 x# n
        while( dwLength-- ) {
5 h0 C1 d' f2 o0 ^8 v8 `( Q; D                writetime = (DWORD)elapsed_time;
* _! k7 Y9 Z2 N2 }$ W; F9 s- ?2 U: Z4 Z6 h% {6 `
                while( GetQueue( writetime, q ) ) {
; M) e: D; S2 D                        WriteProcess( q.addr, q.data );6 Y# g0 p1 ^0 c: k% \/ a0 S
                }
& I: V" `: d3 t! o9 r1 v
6 d8 v7 ]) T; l9 j* b' @2 O: a                while( GetExQueue( writetime, q ) ) {, N4 `3 ~% |/ c# e- g
                        WriteExProcess( q.addr, q.data );
1 }% `! f" a, y0 t                }9 I$ u: i8 R5 P6 F; l, [

! x! Z) Q  S! ?# @                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" V5 {! s9 R7 T& X                output = 0;) F4 g# ]1 s* z* D2 }3 Q
                output += internal.Process( 0 )*vol[0];. s/ C+ `% o6 m6 [/ o4 O5 t
                output += internal.Process( 1 )*vol[1];
5 Z6 l8 g4 T6 t% p                output += internal.Process( 2 )*vol[2];6 }: k  F" [  X" [1 t
                output += internal.Process( 3 )*vol[3];3 a6 V' v1 k3 N* l
                output += internal.Process( 4 )*vol[4];
" n$ w$ T$ P$ V9 g, ]
) M. ]/ Y7 Q3 a7 B                if( exsound_select & 0x01 ) {% K8 n7 P% t6 \( C7 t
                        output += vrc6.Process( 0 )*vol[5];
% k+ U  ]3 m7 j  r. F9 m                        output += vrc6.Process( 1 )*vol[6];) d7 x0 t  i& ?3 H9 ^: ]: K. r
                        output += vrc6.Process( 2 )*vol[7];3 X7 h" f, u" {
                }& @) I$ k1 p, u* L8 |9 r% ^/ N  n
                if( exsound_select & 0x02 ) {
2 q0 _8 z8 B4 X' l+ Z' h& K4 Y0 J                        output += vrc7.Process( 0 )*vol[8];
9 A8 U) K. Y' P9 B                }  p7 l, N; J  m( a" E, G
                if( exsound_select & 0x04 ) {, A. c& {4 S8 j& u8 j/ Z
                        output += fds.Process( 0 )*vol[9];% b4 n4 x% H' d4 b+ J( i
                }
% w, Q+ j- V( ?! ~                if( exsound_select & 0x08 ) {
3 I& B. _; ^% v6 `" U# q  W" K, g                        output += mmc5.Process( 0 )*vol[10];
' I; o) v% [" }& \: D) v7 K( r                        output += mmc5.Process( 1 )*vol[11];! B/ j. j+ U0 l8 j8 W
                        output += mmc5.Process( 2 )*vol[12];
! P8 H( A0 V$ j4 k                }# G7 X! v* W" [8 e3 f0 F4 B
                if( exsound_select & 0x10 ) {! p& C' U5 h8 _8 l2 b& n
                        output += n106.Process( 0 )*vol[13];
, l0 D6 n8 J& L( ~- i, I                        output += n106.Process( 1 )*vol[14];9 ~; W  K6 Z& z1 V4 q" L
                        output += n106.Process( 2 )*vol[15];  I# L+ M. `3 R4 s
                        output += n106.Process( 3 )*vol[16];
! ~% }* b$ N- Y5 ?8 T                        output += n106.Process( 4 )*vol[17];
* S1 ~& o& s( v/ L8 e3 @2 K, b; R                        output += n106.Process( 5 )*vol[18];
$ _! H* i5 T7 s; ^                        output += n106.Process( 6 )*vol[19];
7 Y$ R6 W5 F! T8 H8 H' t% {3 f; p* x1 e                        output += n106.Process( 7 )*vol[20];2 B9 v7 k% z  V& W1 e6 @; ^1 }, W
                }3 @7 z* t+ U  J! ~2 p0 [
                if( exsound_select & 0x20 ) {5 C% G! ^( v3 ^7 ~( }0 Y/ b+ e
                        fme7.Process( 3 );        // Envelope & Noise
. J, x/ H+ a- V& a( b* L; Q                        output += fme7.Process( 0 )*vol[21];
+ [! q4 _3 Z7 \* q  G4 H                        output += fme7.Process( 1 )*vol[22];
% m- C/ y, F) j5 u) b. G                        output += fme7.Process( 2 )*vol[23];
8 q3 b' l8 o) n+ G                }
1 G0 y7 w) Z5 `6 V6 N2 B+ y
, H" D+ o4 L6 ]% V0 Z' j                output >>= 8;
& {  c0 r9 f2 f! N7 H
2 ?3 q; E* t8 [8 W                if( nFilterType == 1 ) {
' r" {; I, I  j% O                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 Y% p+ V# N7 C6 i" I! A; @0 N                        output = (lowpass_filter[0]+output)/2;
" q4 k. Z# O. D8 u( x) `7 @                        lowpass_filter[0] = output;7 c5 I. M& z& R5 U0 b
                } else if( nFilterType == 2 ) {
- O* h0 X! J  Y7 s                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
" u9 E! I- {" D( V% E: _- E2 }                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ m( ^. x7 M; n5 \* g                        lowpass_filter[1] = lowpass_filter[0];
( h. j, X/ A, ?! L$ z7 x                        lowpass_filter[0] = output;
1 g) q; j4 r8 j3 M1 c9 ?9 W3 _9 M- z                } else if( nFilterType == 3 ) {6 k$ m' n* f$ ]6 X( ?+ T1 Y
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); c& `# X9 t8 h" `' ?6 V
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 }3 }, r3 d5 ]2 u                        lowpass_filter[2] = lowpass_filter[1];
& W  k  _8 Y( w$ r) O                        lowpass_filter[1] = lowpass_filter[0];) J' ?9 s+ {9 A4 u/ E+ i
                        lowpass_filter[0] = output;  I( c5 \% r) {  r+ p( X! @& \
                } else if( nFilterType == 4 ) {
2 n+ a) l  A: k0 d3 Q) l                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
) v; G7 o. u3 m, c- e9 W* R                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;" L  o+ m" e1 J8 }+ h. v- F/ t
                        lowpass_filter[1] = lowpass_filter[0];
4 X  x- w- W; _2 }% c                        lowpass_filter[0] = output;2 p! l, e  L1 T5 x
                }
8 r5 }$ F, v' v+ c8 R0 F
/ D( G/ Z# H+ h/ e/ n2 \, |% ]#if        0
% Y" |6 W/ t2 ]                // DC惉暘偺僇僢僩
$ W# X8 n5 i/ Y# N4 C; B: W+ c                {" X( T; r: I3 Y( A. L  q* {
                static double ave = 0.0, max=0.0, min=0.0;, i! ^2 m# m! w6 R: |* ~: \4 Q
                double delta;% H. J. o  B/ O9 _2 t: V/ z
                delta = (max-min)/32768.0;1 w4 p' a/ G' r- J* y  l$ p) A
                max -= delta;7 v* q1 d' W' M3 M9 L  w
                min += delta;% @! ?" Z5 T, J3 X  \9 z* O
                if( output > max ) max = output;8 x! M" Q( O) e4 T/ E- y
                if( output < min ) min = output;
2 z- I* Q( e) N! n% b/ k' m                ave -= ave/1024.0;
  a# W: A* c3 \- o. U+ ~* z                ave += (max+min)/2048.0;1 p, L# H* p2 S- u2 R
                output -= (INT)ave;" p  ?7 a% o4 `- d/ V+ G2 p
                }3 C$ e6 O3 g0 \0 G$ F- _  Q
#endif
0 W3 C. m$ ^* t- u* K( Q#if        15 [4 d5 k8 ?. Z1 {; Y) H0 w; A' K6 V0 \
                // DC惉暘偺僇僢僩(HPF TEST)
) L5 M5 x2 x" z, @# b) `8 w2 B                {( I* @/ a+ C0 E
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 b) a3 ]5 ^; {8 v                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# H' U2 [; W+ U  l8 e& R" ?' r                double        cutoff = cutofftemp/(double)Config.sound.nRate;6 h7 I1 G3 \! y2 W: K' J, M- X  a
                static        double        tmp = 0.0;% M8 Q! j% s8 [- J  u1 ]( H- ?+ D
                double        in, out;  b( z) `/ ~  `! x8 k& ~( ?" n4 O

8 M, z2 v9 d7 T3 w! Z                in = (double)output;
  T, |  l- \3 T9 l7 Q                out = (in - tmp);7 N. z, {% x" a+ U/ l5 n4 A/ `
                tmp = tmp + cutoff * out;  N$ o( J4 {& I4 K; @1 P  Y" ^
* r; t) t7 E) a
                output = (INT)out;2 q0 k" \$ a% |, Q( B# N) Q
                }
9 h/ U$ h$ r2 x+ s$ N2 K" F#endif6 R: w1 {* @3 O$ J+ S$ o0 N
#if        0
. B8 v6 s8 Z; b9 l  U                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
3 U# m* N/ I  c$ n2 r7 h                {5 \+ Z" F% ?7 S" }2 P( l/ Z
                INT        diff = abs(output-last_data);
/ g* K# o, U2 U                if( diff > 0x4000 ) {
6 j& W0 h9 ?2 H0 q( b                        output /= 4;
5 y) V9 O1 q; P* _                } else , g; s" v3 I1 `8 I/ S6 Z# D
                if( diff > 0x3000 ) {2 x( V8 `. n  s
                        output /= 3;
6 f/ [! y' N. T* j- o                } else
% K$ Z) X. D7 r' Q+ I                if( diff > 0x2000 ) {2 i. I: v1 Q" X/ u/ w
                        output /= 2;( Y1 j2 V" C0 w2 F
                }9 h. x9 ~" ^2 ]% V" t, j! |$ R
                last_data = output;; i; P8 J8 T: t! ^# m' ~
                }
+ o8 h( u' |7 e) r$ _#endif1 g. B, Z9 c' I
                // Limit2 [& ?* D5 \* [3 X2 t' P1 G  u
                if( output > 0x7FFF ) {
8 A6 S: t( M& c" @; j8 W+ O                        output = 0x7FFF;
. f$ ~5 _5 e: h0 q% s. Y# }                } else if( output < -0x8000 ) {
3 H/ e! m% X; C8 v3 E+ `                        output = -0x8000;
* X) w6 k* O) @4 S8 A" G- ?                }, B/ ?- [0 g$ i  }

% R6 V, V. D8 k' L; Z: M' j, o                if( nBits != 8 ) {5 L- u* S+ M5 U9 S9 Z
                        *(SHORT*)lpBuffer = (SHORT)output;/ k. i6 b4 k4 r; n% n5 z: W
                        lpBuffer += sizeof(SHORT);
4 W* Q- ?/ c6 W  O/ g, P+ H0 [                } else {' n4 H3 w/ D& m( J
                        *lpBuffer++ = (output>>8)^0x80;# U: K7 E3 `/ @6 j
                }. v  J- G9 q* v- v: X
0 Y/ Y8 G; i$ X( P
                if( nCcount < 0x0100 )5 ?$ O. q2 M6 ]. A7 Y
                        pSoundBuf[nCcount++] = (SHORT)output;
. x- r8 o- J1 L/ a1 `
. g8 ?4 a( i8 Q1 q- [; G//                elapsedtime += cycle_rate;
% x9 J7 D$ S; f' [3 ]                elapsed_time += cycle_rate;7 D( c, Z+ S3 V3 F" r) p
        }( u3 j! ~4 D5 W! k3 y% q5 G( A

0 U7 U, y3 C! T% ?#if        1) B0 v5 R- U6 ~* W9 e7 g
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {' i& F6 v9 _! }+ S1 R9 A9 g6 J0 A
                elapsed_time = nes->cpu->GetTotalCycles();
2 D. d2 e  |! |        }
8 B: I/ T4 O0 B1 O( K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. Y4 O0 M+ l, m5 l' q                elapsed_time = nes->cpu->GetTotalCycles();
% G( p1 \; c8 E. D  m8 `0 J2 O. a        }  [7 T/ _3 G4 B" V* L1 ?# o
#else5 @/ j( H' X7 H" E6 J5 c
        elapsed_time = nes->cpu->GetTotalCycles();
0 [6 P9 c1 n! H8 X( t& T#endif- k! O. E0 N: q, O0 m7 \
}8 s. y) ^8 `( E( C; a
" A* y' u5 v( N8 f; H6 b. |9 U
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
% M/ x- C  {8 G) Z, e1 RINT        APU::GetChannelFrequency( INT no )+ I. x9 g# J; ]4 K$ Y, \9 D2 O1 b
{
0 `7 x: h1 V: t" I$ \. P0 T        if( !m_bMute[0] )
; J, F5 }# {5 Z1 K. A+ y, D2 F                return        0;
& `2 B: ]1 u: C9 O( f. t" V
5 I. r3 w( l$ w1 k3 Q        // Internal# H" Y/ y- ~2 c( G1 e" h) Q- P# j
        if( no < 5 ) {( j. Y& w. m$ W5 |7 m. G/ X: V: G
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
7 q! i2 @9 v) e! R* M- q4 [2 {        }
' e  K1 c3 B1 P' n, t        // VRC6
4 W( e8 j% ?+ A9 Y, A        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {7 M8 Y- @/ q; T: m
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
# l; M; t- A; L# k* D        }' \' E' }! f) F
        // FDS
9 t7 U8 w* x3 ?6 U; E2 B4 r        if( (exsound_select & 0x04) && no == 0x300 ) {) ^2 O4 v) Q5 c' O% e, ?
                return        m_bMute[6]?fds.GetFreq( 0 ):0;# W. C: c4 y2 Z; m- L& y3 E2 W
        }
$ J8 s; j9 M: U! q5 s9 J9 o7 x        // MMC59 M" A9 V1 x& i2 w
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {4 X$ M5 u( q0 [+ C( E
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;6 R! d: I2 S4 O7 |
        }
$ I' C6 S1 N7 h9 X( p4 x0 [        // N106
/ a( U; s% I, J: T$ T3 ^: ~        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" A' r( Q( j( S& L) W, [( G' ?* d                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
9 f6 m6 v3 F# R$ A9 f" @        }% A1 Y8 R2 c9 B
        // FME7
7 {" e& W- v0 l" P. I* [$ ^        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
0 C' ]6 b4 q5 a9 B  X                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
' _0 E# d6 R. i& K1 |        }! m8 c/ B/ ]3 H3 d  |$ D
        // VRC7
  P( l. f- R7 s( M  f2 T, r        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {% _- C$ \8 c# Y' f
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& m! `: M4 \6 H6 p        }
1 K* K4 [, p$ H* m6 o        return        0;* q: D( n3 }/ p& `9 `7 Y
}
7 J8 G2 ?( n1 e. T9 m6 p& R; V7 F* ^# e' C' F
// State Save/Load1 \, l+ O8 K9 g2 A/ d
void        APU::SaveState( LPBYTE p )
0 k' w  |* \, x) r( n" D, Z{
: A! P$ q) Q( f% u( b; L( ~#ifdef        _DEBUG
( B! {0 c6 Q# Z# M! Y8 _9 ~LPBYTE        pold = p;- b' r* }5 d7 L" C' l
#endif
4 {. f+ L# m, N( N0 s' j% `% y6 ]7 H% s& T! V6 e
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞: m1 f% J1 X/ P* e, ?
        QueueFlush();8 i+ [* B! o' z( I" z2 y/ k" R

( E- _' Z* g, O' K) k+ V% H        internal.SaveState( p );; t- h! a' q( ]9 p! j/ A$ R
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ e: v0 ~3 U3 d* S% P

* S  [# \% {, V5 H# K6 S! m+ E! M        // VRC6
6 Q! k" o1 ^8 _, n        if( exsound_select & 0x01 ) {
2 |' {- G* [* |' V2 ?! L6 K: H3 K                vrc6.SaveState( p );# q1 l1 `1 [3 g" S
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- e# X: H8 Q8 N* J+ J/ F5 d, R        }3 F$ z1 b0 u7 Y
        // VRC7 (not support)
) O6 Q; H4 L' h! O0 ^        if( exsound_select & 0x02 ) {
8 w: \0 c8 o0 E7 e" t# P7 F                vrc7.SaveState( p );- w% \2 k$ p$ v' H: z3 a
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* K' _% ?3 H7 p! \! `+ t        }  h2 ~6 `8 G1 g: O5 B! R( ^  u
        // FDS* |: Y* i, M; g' y$ I: {& \- Q
        if( exsound_select & 0x04 ) {
  Z# D' v) D: J" b5 g/ f                fds.SaveState( p );
( q0 H* H! ^$ o% @' G) X) s                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 [' {: l, k% p/ h9 T
        }, [% Z. ^* \4 n2 Q0 Z' W
        // MMC5% v+ J0 B# A: G3 x2 K; `
        if( exsound_select & 0x08 ) {+ T0 m6 P, Y3 N# v! B
                mmc5.SaveState( p );0 o& V( c" U9 M
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 A+ H; a4 O2 U/ b8 O( h
        }
2 T: g2 `2 ^; i9 N1 {% Q0 ^8 Q        // N1067 K% G: {: S2 ?8 }: y' A
        if( exsound_select & 0x10 ) {2 `7 e# d- B# L3 x
                n106.SaveState( p );
9 t' ^0 o2 Z2 R9 q1 _                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  J6 X+ \8 x3 s+ \4 i1 \5 F3 q, o& z        }
4 t! M, K7 m5 ^6 R! Y" C        // FME7
/ M  a7 ^. n% o5 v( ~0 j# J        if( exsound_select & 0x20 ) {. j1 t) |; h+ O* u9 B. M
                fme7.SaveState( p );' ~4 E* u) m' s3 Q$ C6 }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" a0 S( \! I+ u: Z: W  U6 m        }: `# r+ p/ g' e; C9 n

! i4 M  s  P1 U9 |; U#ifdef        _DEBUG
& E/ ?/ p' J1 f$ S% ODEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
' `9 f8 [1 |& }; f3 E* [* N#endif
6 b% E6 T$ S; L& R}
- s4 C: F, `( v2 n. M: _' d; v, o( y( P; }( ?
void        APU::LoadState( LPBYTE p )) g8 [7 O: o" `: h) t1 [5 n
{
. k) \$ u% ~* Y" i; `        // 帪娫幉傪摨婜偝偣傞堊偵徚偡# r% H' Y4 S  H1 v* O
        QueueClear();" I, r& l5 i- v6 y" c8 e* d; \. v1 J5 ~5 Q

$ j' q5 o! e  F8 e        internal.LoadState( p );  K! T9 v% U# K% i! C
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding- f! |5 H9 g) b2 s* U

" k& g$ h& |; |2 T        // VRC6% i; B! q; S9 f/ u8 g# R! n, n
        if( exsound_select & 0x01 ) {$ i3 T+ u- C' R" T3 V% L# O
                vrc6.LoadState( p );( k5 X) L- k4 i; X
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 @: }! Y0 w$ k& L; A* |
        }* z$ y1 ?' ]  Y/ o& q. S9 _
        // VRC7 (not support)) \; j2 I3 }" V! P! U) z6 W4 G
        if( exsound_select & 0x02 ) {
( T9 _$ z1 C8 Q" D                vrc7.LoadState( p );
  d7 Y; o3 Z6 D9 o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 n# w2 L! D5 V! [. b        }3 h5 K# t: D' W* ?) `# G5 h' X
        // FDS
0 v3 [  d! m, v1 b9 e: [9 Z        if( exsound_select & 0x04 ) {* @2 Q- w: Z/ ~/ y- {& s  G
                fds.LoadState( p );: F: h  e: Y1 S: l+ ^
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, _) B' c% G; [5 H' d4 z6 S: I        }
/ d5 o- t8 @: L- V3 L* `8 U        // MMC5
8 k: m6 y* G- h8 Q; ~$ \4 n        if( exsound_select & 0x08 ) {6 b$ z* H6 i8 K  e. R0 j7 |
                mmc5.LoadState( p );
- J2 ]+ Q& r: Z: {# |" _. ]                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* d6 h  D3 ]. c& _/ M) E        }' K5 x0 _5 b% t0 V
        // N106
; O! O' i7 `4 B% {: @' e        if( exsound_select & 0x10 ) {
& B6 R# G# f" p. Z" p+ T& U                n106.LoadState( p );
" V/ t2 c& U/ h  ^                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% u! j3 s/ n" N        }
$ Y! {2 k/ E4 H( k8 j        // FME7/ G: Z1 }6 k' O# z
        if( exsound_select & 0x20 ) {  l+ H0 p% s+ e& r% }3 y
                fme7.LoadState( p );
5 Z. K! \4 C+ {# X; e                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 u7 w" H$ u( g        }
5 s& c/ _  S$ ~& y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 2 M  O  o! }/ E  A2 r( r' q# e
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。) e& n) \  H  l3 I1 L. P9 X
感激不尽~~
9 L0 J) Y6 \" P+ x9 i# ~2 `- E
恩 我對模擬器不是很有研究,
8 d1 [4 h! F; b雖然要了解源碼內容,可能不是很困難,
: s9 {% j4 I. ^5 i不過還是要花時間,個人目前蠻忙碌的。- m* M9 I) c; E( |
. C* Q* \; D* G4 x5 |/ P& q
給你一個朋友的MSN,你可以跟他討論看看,
) ]4 u! J  h& W& M9 ~他本身是程式設計師,也對FC模擬器很有興趣。
  }' ~( e2 Z; j; f4 b; {  s! ?* j( a; i7 k3 p8 ]
MSN我就PM到你的信箱了。1 J# e! @! E0 T

! k- e$ _; ]$ k3 I2 v' G希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " N4 V! u3 a, w  @* @, X6 U
呵…… 谢过团长大人~~
* I9 S+ |2 T, J$ [7 E' x' ]

7 U+ p2 {" x9 [% K  B$ I4 j0 C$ N; V( n: T哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ( w  l, E3 @  m: m
团长的朋友都是神,那团长就是神的boss。

' s; {6 O* P+ [) \# z  m2 I8 F哈 不敢當,我只是個平凡人,
, \/ w) m( N' k+ {要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
/ M! T2 m- G  b2 b) M+ FZYH* y9 A+ x  m6 V
QQ:4147343066 k% C- U- f' |7 t5 l- a
Mail:zyh-01@126.com$ i& R; D2 S; H8 S3 K* x
, r  l2 y6 {- C$ U' Z* W& D7 G/ }
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 7 B5 i9 o5 p( |- m
再次对团长大人和悠悠哥的无私帮助表示感谢~~
5 A' i! C: @+ o/ }* @
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-23 11:06 , Processed in 1.088867 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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