EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?/ m9 h. O" T# }( x0 I
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. i) I% F/ d; S楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: K5 l# I, m9 s& S3 F; B
这里有相应的模拟器源码,就当送给大侠了~~
' e+ `& w5 y) g2 Yhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
) s" l/ ]/ o& t0 k  m能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 q9 Y( ?4 s; L) t楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 |4 l$ |: s9 t* H# w0 d; g3 T
这里有相应的模拟器源码,就当送给大侠 ...
3 ]& P6 e0 u# P7 Z% U. k. O
聲音部分(Audoi Process Unit = APU):
) m: D, H/ P/ y* J8 _( M, t+ W.\NES\APU.cpp8 F3 u; X) {( d  z& P9 d  [
.\NES\APU.h/ l& f1 d* p2 T# a

( Z7 @. v7 X! k
7 W3 m" z4 K1 c影像處理部份(Picture Processing Unit = PPU):0 w2 h% \) e- S: g; d
.\NES\PPU.cpp
! y4 E- N* _/ K9 e! L.\NES\PPU.h4 b. D0 X" U$ c. o
; y# z( A) S2 z4 x$ t# r/ c
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:' ~! c+ l& t: \4 x! t
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% A% N) p! F- e1 ~//////////////////////////////////////////////////////////////////////////2 ]: M! e* R, W. I$ F
//                                                                      //% [5 o1 A3 [4 [; P( c
//      NES APU core                                                    //
  ~- q! ]/ x. s/ j9 n" d6 E, I//                                                           Norix      //( d8 Z/ J5 u, e; U7 ^
//                                               written     2002/06/27 //$ d# x0 U3 a2 E' D, G. K5 H: |  S" V& Y
//                                               last modify ----/--/-- //, i, N: D2 D3 y; R; [1 x7 V
//////////////////////////////////////////////////////////////////////////
3 P4 I# w5 X: V6 }1 Z2 h" U#include "DebugOut.h"3 E( ?! z6 ?, I; z0 X3 |0 k
#include "App.h"
6 k( T2 n5 }0 F#include "Config.h": T1 z" E7 I9 l# Z! ?; [
, M- t* U) ^  ~
#include "nes.h"4 \, G: d* a; z! \
#include "mmu.h"
* U8 u( k; K8 |% t#include "cpu.h"
) O) x! t, ~2 B#include "ppu.h"
- G' y' j0 t7 \$ a#include "rom.h"! i( t6 O7 F  G* ?  m3 _
#include "apu.h"
( K* y* Q) Y+ n: D8 `( Q
0 W/ [7 y/ n  G( S+ p* i+ O/ X// Volume adjust
4 D- u6 }5 Y2 z) \& A" m// Internal sounds
, ~0 K/ ?4 N* Z$ H#define        RECTANGLE_VOL        (0x0F0)4 z( d1 w3 S  B0 [) c! {' h
#define        TRIANGLE_VOL        (0x130)
2 m2 B! n/ p- T% }5 e/ X#define        NOISE_VOL        (0x0C0)
  Q5 R6 x: h5 V% W# V) o#define        DPCM_VOL        (0x0F0)/ t8 s  P7 S! v7 R4 _
// Extra sounds
' o/ P  x4 z: z; D7 I3 j* V; G" C#define        VRC6_VOL        (0x0F0)
# ?6 [) k( e) e+ q2 O: |#define        VRC7_VOL        (0x130)
2 {. s) J* f# Z#define        FDS_VOL                (0x0F0)
6 Q2 N/ U  L2 I" R6 Z#define        MMC5_VOL        (0x0F0)8 G5 I4 d( g- v/ c7 M
#define        N106_VOL        (0x088)6 ]2 W( D1 v. [0 k) B3 g
#define        FME7_VOL        (0x130)
4 Z9 F* S, c$ {* a* d4 Y
/ ]" ^. F+ N" i/ Z2 J# i# u. ^9 oAPU::APU( NES* parent )0 J! Q+ k+ E3 U4 K, U5 Q5 q
{
9 M. Z5 T; c9 V( Z( k, o$ W0 P' L        exsound_select = 0;
* [( d, V; A; V3 o6 A" j
3 I9 ?7 Y, F' Q. |        nes = parent;% v7 [, L& x) ]7 o
        internal.SetParent( parent );
4 e1 B! X4 G7 ]) o
6 F8 d! j  K1 B( n7 Q$ K7 K+ \        last_data = last_diff = 0;' P* t0 m' D* L! a7 L1 i; J
. y3 n; K6 z% L3 e. F3 Z
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
& {; T* Q$ O8 [& d
# [! e8 H0 @$ O0 @0 d+ j/ t5 i        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 c1 [# W1 ^! X! U: s  f
        ZEROMEMORY( &queue, sizeof(queue) );
# a& P3 F8 }# }" m" Q6 P3 N: E        ZEROMEMORY( &exqueue, sizeof(exqueue) );) s3 [% L1 Q& b; j* }

: s9 y2 V; L3 |" u        for( INT i = 0; i < 16; i++ ) {
% c8 f3 L0 c# B$ I7 e% G, H. L                m_bMute = TRUE;
1 E1 I# i7 w8 m        }
4 z6 y( p5 T8 K" O# Z5 J+ W- g, n}4 I; l( o0 B' s8 C
# [" {/ N+ g9 x/ H5 M2 M6 @4 ]( L
APU::~APU(), ~+ ~+ }4 C* v4 x2 e5 a0 h4 `& @+ r
{
- |) l$ F3 |+ m6 N+ K) G; x5 |}
  f# ~6 K1 h: u4 r7 x- G9 |0 e6 w% y% W/ ]
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
; J! S# t' Z; [. Z7 g+ \; h- ]5 q{$ D' y$ e+ f$ `+ }% f
        queue.data[queue.wrptr].time = writetime;! E) I" n4 ]1 y5 I8 \& E
        queue.data[queue.wrptr].addr = addr;
& R! }4 e# U" M+ h. F( J        queue.data[queue.wrptr].data = data;  E: |3 ?% q6 K( L
        queue.wrptr++;
+ k7 D6 h( G% Z' A        queue.wrptr&=QUEUE_LENGTH-1;
& N# j1 @& ^, `* x8 k8 D" S        if( queue.wrptr == queue.rdptr ) {7 q3 c$ |1 N- b
                DEBUGOUT( "queue overflow.\n" );, _& B8 I9 [1 J2 S) b5 `! j1 F
        }
& W  S# z! Y/ d( R. j2 g}
/ N. ^3 X: G% C5 N! E$ ^
# I6 e% F- z% b# M$ TBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
* b# W0 n- X6 y0 C- a# A{0 d$ p3 p, Q, S
        if( queue.wrptr == queue.rdptr ) {) R; w- W/ w2 x7 |$ G
                return        FALSE;
4 V6 O6 H$ Q+ j$ f3 P# a# Q- v0 t        }
$ Q# S5 z5 u7 r+ [& e5 B        if( queue.data[queue.rdptr].time <= writetime ) {9 o2 L) S" L$ f/ m% D: L8 ?
                ret = queue.data[queue.rdptr];( E4 _0 [& H5 n- f; w
                queue.rdptr++;
( L5 Y8 h, s& d9 q* B$ G  ~  \                queue.rdptr&=QUEUE_LENGTH-1;
5 L2 O' K! C" ^9 O8 J                return        TRUE;3 H, j! O( C  {
        }- P) ~5 O* H4 ?, _7 j' }7 M) I
        return        FALSE;4 B# W+ f( V. v! I
}
5 f% v' a6 C+ V3 X) `% t# E/ @2 Q1 t( G
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 _4 R9 i; G5 {  [  V
{
; H8 s1 V; h# D+ ~        exqueue.data[exqueue.wrptr].time = writetime;
) N# v' t1 {' R8 Z        exqueue.data[exqueue.wrptr].addr = addr;
8 @2 z+ ]+ A& N' }2 Z1 U( X% Y        exqueue.data[exqueue.wrptr].data = data;
7 s; s4 d- W3 O- n4 F/ s+ r        exqueue.wrptr++;
( o2 A& }: c" Q7 t0 F0 e* ?! {- j        exqueue.wrptr&=QUEUE_LENGTH-1;
% ~: I$ k' S9 m" c" U5 t1 @        if( exqueue.wrptr == exqueue.rdptr ) {. u8 R; J* w& m6 E1 O: s) w
                DEBUGOUT( "exqueue overflow.\n" );
4 g- b" `+ G9 l        }: ~9 V! V8 [3 Q3 p/ q2 s/ i
}: A, G8 j0 x1 h) i3 Y" O- E

' Z7 J+ s2 j* l1 L/ o' f0 p3 S  n# fBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )2 W+ Q1 j- ?' q; X
{
% ]7 G, B4 p. |. |        if( exqueue.wrptr == exqueue.rdptr ) {7 c% E" u& s4 M; [- z# N9 ]9 ^) t
                return        FALSE;8 v) E" f2 w& h5 h8 j/ s
        }# S, k: b. N% |; s
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! B) g) ?5 m- S# n. E/ G                ret = exqueue.data[exqueue.rdptr];
# G' A7 l3 {/ r6 E                exqueue.rdptr++;
7 O5 }$ {9 M% j: ^: L                exqueue.rdptr&=QUEUE_LENGTH-1;8 [5 _/ F4 N4 e2 ^7 \( d
                return        TRUE;6 l7 p0 q/ _+ I6 Z; G* `6 v
        }0 D( j) b1 t: ^  c
        return        FALSE;. o. B$ n3 M' f! Z* L; {
}
& N( o5 l& ]0 X; Y& o" x" o4 r# \% |, _( u
void        APU::QueueClear()
2 [8 O4 A/ }5 N8 y  l( b{
6 H4 G* m) o9 M2 F6 ~/ g        ZEROMEMORY( &queue, sizeof(queue) );
8 a! k* j; p" r) O  N        ZEROMEMORY( &exqueue, sizeof(exqueue) );- W. [' m% q% v: F
}% t5 |' O% `% I; B5 J2 I+ w
' z  G' @- l* A! ?  q: n# y
void        APU::QueueFlush()
/ C+ b" c/ I3 d1 V{
9 t! F3 D7 q# }- U) O        while( queue.wrptr != queue.rdptr ) {
2 P. a# s; p/ A+ x( R                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; }7 h$ m' H" ^1 z2 U
                queue.rdptr++;. \& C( ]1 c0 x. G7 j: `7 x
                queue.rdptr&=QUEUE_LENGTH-1;
& O$ a/ |7 ]" C$ v* h1 J/ y- e5 {7 `        }
2 v/ V+ N( G6 n/ B6 L1 a* v" u2 u4 |0 e; h6 P* K  _
        while( exqueue.wrptr != exqueue.rdptr ) {
; O6 ?2 a8 z( [7 ?1 Q2 m) G                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: n2 m! L4 H1 O* p
                exqueue.rdptr++;5 ^; T" r0 {. S3 z3 s$ {
                exqueue.rdptr&=QUEUE_LENGTH-1;
% d$ G" k6 s+ [, z; L: s        }; \/ Q6 U8 @3 S, c# P8 R3 J
}
; F8 o4 T: Q: u2 F  c8 z% R2 `" ?# d
void        APU::SoundSetup()4 p5 |9 \, y# i" m* l
{
( O( d6 l5 q" a1 G; P( p0 h        FLOAT        fClock = nes->nescfg->CpuClock;
4 X" J1 L! ?2 i8 u$ i        INT        nRate = (INT)Config.sound.nRate;
4 }" D# Q# r) r5 A" t% B        internal.Setup( fClock, nRate );- d; Y! h- T7 H. A4 r/ H
        vrc6.Setup( fClock, nRate );
5 w# B, \4 r7 L        vrc7.Setup( fClock, nRate );+ H1 b/ E" ?* P$ ?3 i4 W
        mmc5.Setup( fClock, nRate );2 `& `% J0 H" c  V5 l! P( l) s
        fds.Setup ( fClock, nRate );
$ Y/ L! y3 B% T7 b        n106.Setup( fClock, nRate );
  k: h  n8 t: c2 ^8 U        fme7.Setup( fClock, nRate );) g# c+ U8 n2 l$ O' g6 h, C
}7 T+ P0 l7 d; ~

9 U+ \+ F7 l. E7 Yvoid        APU::Reset()
' w! M. f+ [+ ?& @9 A0 H{- f; P; Y& r3 e5 e4 `1 U* T' d; p
        ZEROMEMORY( &queue, sizeof(queue) );* K4 _  ?$ o2 {: c0 N
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ n; j1 e4 a0 f4 w& e9 _7 v3 z5 v% k, f
. A, q5 e+ V) Q) s: b        elapsed_time = 0;
, D6 C3 i& D& u: M; K) I. J) \: H+ ]1 R6 Q; s
        FLOAT        fClock = nes->nescfg->CpuClock;
& H, U! s1 \- r5 E        INT        nRate = (INT)Config.sound.nRate;5 n3 M0 R) X9 y+ u% E9 Z' O
        internal.Reset( fClock, nRate );
4 g6 R5 p# W. Y        vrc6.Reset( fClock, nRate );
% c' T( E6 e( Y4 ?. p- T% H        vrc7.Reset( fClock, nRate );
+ y) |* W- X3 }        mmc5.Reset( fClock, nRate );
2 k4 J1 R. p$ R# F        fds.Reset ( fClock, nRate );3 O5 i! b: R" l  C
        n106.Reset( fClock, nRate );0 O! J0 @& e$ U2 H9 L% m( _
        fme7.Reset( fClock, nRate );
" C1 F9 ~+ ~; h
6 V+ K' s  z. {1 {+ j& F        SoundSetup();
! H2 n; |! ]7 @' r% K}  d9 `2 F4 D2 ^9 K% P

- T1 G9 r3 ?& i& y0 ?  pvoid        APU::SelectExSound( BYTE data )
- C+ X- C7 r  }( W2 x{8 \% d8 I0 {9 ^5 ?1 l* ]
        exsound_select = data;
- k* }( Q9 S  Z7 F}
( ?; H4 s4 @, Y( F: Y. n- e
$ u& r5 T4 ]8 X  I( k8 V5 q5 w$ nBYTE        APU::Read( WORD addr )+ K2 `9 S" l# |/ L7 [6 O8 N
{
- \. |* `! w, Z) r3 J+ ~1 d5 q        return        internal.SyncRead( addr );. z& q& q+ p1 C/ G0 {) X
}
3 ^: ?) P- c) s7 L2 r4 g5 }! K: I8 E2 Q
void        APU::Write( WORD addr, BYTE data )6 C! ]5 U# L! k1 ?
{3 f* M$ B* m- v4 J
        // $4018偼VirtuaNES屌桳億乕僩
$ u/ {$ O# s) ^' Y3 ?9 U, A        if( addr >= 0x4000 && addr <= 0x401F ) {
; E* _+ A/ c" ?* E! s                internal.SyncWrite( addr, data );& y1 _$ F) J4 V& G; j  _, _
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );  m7 B( w$ b  ~2 N3 o: `  g
        }
) S, f/ Q0 M" D) |- {) \}/ T$ v( z) o* _9 J2 C  ?

7 z0 g% I+ V( Q# uBYTE        APU::ExRead( WORD addr )( U9 U0 t9 v9 ^+ i0 k8 C1 f
{
: t& Q2 d( V1 f) x5 \; ]BYTE        data = 0;
* a9 ^. |/ k1 X! V/ n: V+ M1 i2 [/ _; H
& O9 H) q; j( l$ l& a- W- a        if( exsound_select & 0x10 ) {
+ x8 S5 U  [3 V                if( addr == 0x4800 ) {
8 B/ f% |" R' @1 i, l4 B: i                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );. p) W7 a) _, q
                }& r+ A5 C7 K8 q: F9 k
        }
; `' ~3 _: N* D( i5 m& J7 a        if( exsound_select & 0x04 ) {( H' a1 z/ r% l0 j
                if( addr >= 0x4040 && addr < 0x4100 ) {
% \5 q+ z3 Z# Q2 N; o5 ?5 u, M                        data = fds.SyncRead( addr );
1 u5 u* j3 E! v                }. b  c" X3 x5 w+ ^6 I, r$ V
        }
% |1 q/ X  k: ?. B5 ]3 _+ J, V        if( exsound_select & 0x08 ) {$ o; ^9 {7 Z9 k) G; ]+ Y. k1 B
                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 ?0 U8 s) U: X" r9 J; [4 `( I                        data = mmc5.SyncRead( addr );
# M3 [7 ?5 _# }' w5 a7 W                }+ }! c: m& b3 C8 V1 q+ A( I, u% y
        }2 u; W* D' O2 E0 S1 d

0 Q* c! B+ d, V- G' o6 P2 S        return        data;6 ~0 W8 o; d1 J- P& J; }
}$ P. m9 H! j4 }, a
9 n1 b# @! |; ~
void        APU::ExWrite( WORD addr, BYTE data )( J  {. z% w3 `* @& Y
{
' h8 z* L8 w8 `) w        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );4 B% k( [. D% V, J4 A* w( \

' Q/ N0 c5 k: K) A1 ^6 P7 e, V        if( exsound_select & 0x04 ) {
* P* P0 v5 `" Z* m6 d                if( addr >= 0x4040 && addr < 0x4100 ) {
" j8 j) Z8 j$ t. X% T                        fds.SyncWrite( addr, data );
2 Y2 T* F8 c: z" g) x4 A% S                }
* v1 O  U9 U& a* B6 y' z2 m        }; N  f* ^0 _: g# Y/ h; H7 M7 E

/ p! ^. T  _. ^' D3 S" Q        if( exsound_select & 0x08 ) {
7 K, V/ c! Q5 Y; a                if( addr >= 0x5000 && addr <= 0x5015 ) {2 e+ A; z+ ~# E0 K# h/ D
                        mmc5.SyncWrite( addr, data );
' G- P( ?4 r/ ]) B& i" O                }
, N8 S: h9 L$ C& D: e; T: ?2 @) z        }5 _7 _' t& m8 b' x
}- Y& b  w4 q+ w8 K

; M6 T- e2 o) l* E  ivoid        APU::Sync()
5 B! K, I4 H  s{
# O; [5 j5 Z" F: y' \. m$ m}& {( v" L& C. m) ?9 a4 Z

, N$ }1 H% [" l. h) [void        APU::SyncDPCM( INT cycles )
; x, u+ \7 a4 x& ?( I{
4 q+ x! {  i* b! q        internal.Sync( cycles );
: G3 U0 ~- w+ E- ?3 b; }9 L: C0 H2 x
        if( exsound_select & 0x04 ) {
, a! `  N8 S! f! {6 Q& F                fds.Sync( cycles );% L' o9 o( l# \" {+ X6 k5 V
        }( J0 c2 l' Y  S" M  V" b
        if( exsound_select & 0x08 ) {& l0 H1 Z5 j; ]: \
                mmc5.Sync( cycles );
! R( e1 Q2 R: y! p! N/ z        }
' ?+ L2 l. ^# G; h5 L}
7 ?, M2 y8 Z! A! Z' i& V8 b. j2 D- [+ {2 P2 ^/ D, L
void        APU::WriteProcess( WORD addr, BYTE data )
1 Q) N' M6 a& e{* m1 F. h% I5 c6 m- _; t
        // $4018偼VirtuaNES屌桳億乕僩$ W  [  h( ?5 n  o
        if( addr >= 0x4000 && addr <= 0x401F ) {* X; Z& U& F1 X% c
                internal.Write( addr, data );
% i! R: b$ l: |. v' [        }
9 f+ l+ {% Q1 Q+ O}
2 H2 X5 E, S+ }0 V/ g6 [' ^* \/ r  k% f2 V4 `
void        APU::WriteExProcess( WORD addr, BYTE data )
0 }6 G% [* [7 i8 o{1 w+ ?, \, @* c: C' `; f- \/ |0 r* ~
        if( exsound_select & 0x01 ) {: H/ l$ v( T. G
                vrc6.Write( addr, data );
3 `# ^% b+ r$ D- t5 i4 P; O( \        }) |& m6 I' d! i5 _9 M  J; T
        if( exsound_select & 0x02 ) {
# H4 j, H- @) H4 H0 q. E                vrc7.Write( addr, data );
- {! ^5 A' \+ P  u" z( `' S        }( S* C! t+ V' B3 q/ U4 y
        if( exsound_select & 0x04 ) {
( i$ o2 B+ c8 W% r                fds.Write( addr, data );* r  E" I$ e  Q6 r  V7 `, ^
        }
+ [6 l4 Z2 ~( @        if( exsound_select & 0x08 ) {' c$ m+ H/ f9 S$ V
                mmc5.Write( addr, data );
2 `; ~5 c+ E8 W; [8 l" {        }$ ~2 H( h: I+ j/ d
        if( exsound_select & 0x10 ) {; }/ {: x/ V; h$ f7 E
                if( addr == 0x0000 ) {
# D& w8 Q, r4 K# Z                        BYTE        dummy = n106.Read( addr );' H( w5 g# R# D" F+ N
                } else {5 @8 z1 o/ C' m5 \- Y0 F
                        n106.Write( addr, data );
: n1 m6 _& `' D/ I4 L3 a  E! `                }5 y9 T2 g/ K, a2 ~! s
        }
/ F5 k( A0 W9 {! g/ C+ q        if( exsound_select & 0x20 ) {3 w* e9 E$ P5 i' n" x. H$ ]
                fme7.Write( addr, data );, A7 c2 g' v! |5 J8 ?2 u5 J
        }5 E: }, W; k0 Z2 o5 E
}) e" d+ F0 U$ `$ a& T
" N0 W( X3 f3 e9 O6 v& z: B( a. `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
) Q" x+ @6 T/ _1 N# R{- V: @& j1 T+ ^8 R( H
INT        nBits = Config.sound.nBits;
0 \( p* w, D1 G7 N' D, ~$ {# w( R$ TDWORD        dwLength = dwSize / (nBits/8);: b( h6 n; b% C) F
INT        output;7 ]: |* O( B& C; u& N+ e8 L
QUEUEDATA q;* v! d  n2 z1 ?  h" q0 R
DWORD        writetime;" X0 ~8 G* K5 Y9 S
% B* G, [6 K( b% @  e
LPSHORT        pSoundBuf = m_SoundBuffer;
0 O$ w% c9 O; w$ wINT        nCcount = 0;
, G! ]0 s+ O; Z6 P7 R
4 Q: G/ R1 ~( P/ U5 IINT        nFilterType = Config.sound.nFilterType;
! l1 R1 L/ N* |* x* r
- t. m; }2 v0 n, p. ~9 m        if( !Config.sound.bEnable ) {# M& D. g" P# T, y/ l1 F4 V) r
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
+ m9 X- n0 y2 x# p8 r' T4 {6 i                return;
) T8 X0 V' T" q: R        }
7 w0 A. P% U  q  X
- J; J  ^4 V4 U  y( w0 f        // Volume setup
% @2 f5 g0 x  @( x        //  0:Master
3 Y7 k3 e' O; |/ `& k5 q        //  1:Rectangle 1
+ K) j( x1 G. H3 Y! e        //  2:Rectangle 2/ w* s' U7 D" d
        //  3:Triangle
3 z( N0 E; B: H( X/ {        //  4:Noise
* L4 v$ g2 b6 v8 u* Q, O        //  5:DPCM
6 S+ ]2 @4 _4 ]! N        //  6:VRC6
4 C1 f$ G" E1 H* F7 V+ \9 X        //  7:VRC7
. q/ ~  }; A$ {1 Y. Q4 `, i* v        //  8:FDS2 M* K& Q; t  E8 H
        //  9:MMC5
8 z( H6 [- u' S- D0 J2 f, D6 @! o, A        // 10:N106
' E/ h" x. h/ q- d        // 11:FME74 c& Z  A  Q( e
        INT        vol[24];
4 u5 u( ]1 c" r4 u* }' C  s        BOOL*        bMute = m_bMute;
5 J$ }# z- ]; |5 c2 P& u* q6 l        SHORT*        nVolume = Config.sound.nVolume;  E) Y* V' c' u/ d
1 i0 o) Q! X1 S( D: L
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
* G' S: p# v* S" V: R4 Y# _# ^' X- _6 c
        // Internal
- U' X+ T( z' k; t& ~8 G! |        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;! ^% s5 J* y1 d; \( @
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
$ A) S( y/ o% C+ Q. ~: ^        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;8 L  Y( G8 K$ B
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
9 |% ^6 P: L' p3 d( W: V        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& d' B5 a3 \$ z# K
" M! H7 E# j8 K5 F9 V4 ]. ~# x1 F+ A        // VRC6% m8 Z" e( ~( a* Q' R" O+ M  S
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% ?6 H+ d8 I0 T5 a        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 Q1 y) @3 K$ D8 J$ L0 u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% u3 Z  \5 L$ E" P% b! u

6 j( Q4 |- H9 A, N4 q9 b        // VRC7
, |# Z/ \0 m6 [, m        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
+ R( c- V3 |/ o
- ]: q+ S1 l9 _; V4 w( }        // FDS9 H' H+ U& p4 [1 v& g6 v0 z
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, {/ ]- j7 S7 K, R- }' G0 i1 S% X
        // MMC59 T8 f: H. W9 d, }8 g3 ^8 z
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* l: E3 T5 ~" r$ |! X) d
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( b: n3 e; V6 z4 u9 C9 ?' P
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' ^, p$ a" K( \9 D4 [, j/ L5 ^2 {& v* A' r  P: w6 n
        // N106) P" ?0 q* `/ D  B; i
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( }7 _  j# g/ G% b7 x1 c
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) {; X0 m& a  J: Y6 Z        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 N% b$ w( k6 t( \* I/ S! B% `' T        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 U/ `. h, z( X4 w) E        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) [  ?: O. L' L. c' O$ A  q+ E4 J
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( y; m! j$ |' Q5 Q" n0 W7 h! k        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 x3 }* k$ D# H* r. B        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' N: b0 N& R& ]% I- W
; a1 c! B* d! G) c. S  r        // FME7
8 T1 a! B% N' I! f; {" I/ g        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' E/ b7 Y5 H% m  h$ R$ S        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 j' y% F0 ?' j; O; }0 I        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( n. O/ t4 R" V4 O( C% K
: z, r: l& {; n+ I( N+ ?5 X4 D7 P" Q
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
5 N# F; ~7 @( d) L        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
- m, u6 o9 B' `9 }% N' e4 ^& H
; Y% y+ P* }, \3 `8 r/ _        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ W+ l; e  c7 ?! u- V
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {8 w4 ]0 s6 B' Y/ G/ N
                QueueFlush();
( S+ H+ O) [7 [        }1 C# c' f% m9 d2 w# j: F7 P

. v2 T% u0 f' w/ B5 h$ n! Y) p3 Z        while( dwLength-- ) {& Z0 F6 ~; Q& P$ u2 B8 c/ n
                writetime = (DWORD)elapsed_time;
) L3 I) l1 r# D% E& R2 |4 ?9 E9 h7 i9 r! p$ K
                while( GetQueue( writetime, q ) ) {; k# o' h7 W( t2 x. g  r) M
                        WriteProcess( q.addr, q.data );
3 {/ i- v) h! H( [& ^2 G                }
: ^2 e6 J; ^2 L) |! f
( D3 l( P, [* q) i8 ^' t                while( GetExQueue( writetime, q ) ) {; _! r) z+ B: r( g: n( T
                        WriteExProcess( q.addr, q.data );
# g# h* n: n: L. I& |( f( S8 d                }
& j0 U! v# W- _8 ]- ^9 |3 L8 W
, J( {6 X1 O8 i- h. W                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7, j* D* M: S6 `7 j5 y% p7 \( J. [
                output = 0;$ z3 d  k$ w) B# f* l. K1 t
                output += internal.Process( 0 )*vol[0];
: C3 E& L1 O' r0 Y$ ?                output += internal.Process( 1 )*vol[1];
1 R" a! s/ ?1 `& P( n5 p                output += internal.Process( 2 )*vol[2];
+ C% r$ x3 f0 }. q, F/ ?                output += internal.Process( 3 )*vol[3];
4 J" H* S; I9 Q- s2 O% b7 e                output += internal.Process( 4 )*vol[4];" X  ^7 ^. @6 G3 ]* _
& t  P+ `& O& Z& _
                if( exsound_select & 0x01 ) {
( E. a; n5 X+ U( w                        output += vrc6.Process( 0 )*vol[5];
% f" n0 {) Q( ~6 e; B                        output += vrc6.Process( 1 )*vol[6];
  e0 s) V' ^) K8 ]" [                        output += vrc6.Process( 2 )*vol[7];" V1 V: e/ m1 o  V7 K& Y3 ]
                }
% {% V9 L7 }- A, S8 `5 @& g                if( exsound_select & 0x02 ) {0 j3 X) [5 n2 p# ^, Q3 P
                        output += vrc7.Process( 0 )*vol[8];
: X( Q, G, v# l! p. j                }1 N' }" q4 k0 ?# o  ?
                if( exsound_select & 0x04 ) {
5 V; @# w9 `9 [$ _- q. I$ f7 S* ]                        output += fds.Process( 0 )*vol[9];+ L. S- ~1 u4 R3 o+ A1 J( |
                }
0 \1 X& L7 n- N                if( exsound_select & 0x08 ) {
) W% ?& ?: Y0 z* v                        output += mmc5.Process( 0 )*vol[10];+ t1 ?+ x( b9 y
                        output += mmc5.Process( 1 )*vol[11];" U) u$ P. p* I' B
                        output += mmc5.Process( 2 )*vol[12];8 m: o0 j6 z! ]
                }
$ a4 N/ ~: v* p( K! W6 B9 S                if( exsound_select & 0x10 ) {
3 G8 _! c. H$ p5 i2 B; q                        output += n106.Process( 0 )*vol[13];1 U% G' h" u. g8 E% W$ t
                        output += n106.Process( 1 )*vol[14];
/ ?7 [8 ~4 V9 x* P6 }3 A3 l+ K                        output += n106.Process( 2 )*vol[15];
2 k! [/ i$ E/ L2 C, |1 u                        output += n106.Process( 3 )*vol[16];
5 f" D. m' n/ X                        output += n106.Process( 4 )*vol[17];
+ k# X0 U2 D4 n* `: B                        output += n106.Process( 5 )*vol[18];5 }8 M9 g6 i4 S. T5 A  i
                        output += n106.Process( 6 )*vol[19];6 A3 t" t9 |2 f% o4 l
                        output += n106.Process( 7 )*vol[20];9 ?$ Q" @+ I1 e- A5 e
                }1 B  a& {% }# O5 L4 M8 _& z% |
                if( exsound_select & 0x20 ) {
6 M; E' M) Z) A* T                        fme7.Process( 3 );        // Envelope & Noise9 ]; p. Q# j3 D% G
                        output += fme7.Process( 0 )*vol[21];+ \1 x* ?3 N$ U; n, T
                        output += fme7.Process( 1 )*vol[22];! c$ \; {8 }3 j, E: Z
                        output += fme7.Process( 2 )*vol[23];& \5 Y+ R+ X. k+ e! r
                }
" }5 M( o; g+ n4 u- d2 {6 t) l% b1 n; ]+ N" Z
                output >>= 8;
( K% Z6 f1 \% x; ?5 P% f7 O
- }) j2 J3 N/ y/ z                if( nFilterType == 1 ) {- a0 x6 v3 P" D1 ]& t' r: Y+ R/ @
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
% y1 U" z; ^" y6 m                        output = (lowpass_filter[0]+output)/2;
8 ^- H  A. m: d2 q) ^9 t: b0 x4 k                        lowpass_filter[0] = output;
- Q$ `8 r3 n8 N& X2 K# h                } else if( nFilterType == 2 ) {& k3 O7 r! h+ t& {
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)# v$ b! k" {$ E2 z
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ n/ f  {2 R9 F2 m# Z, P" l                        lowpass_filter[1] = lowpass_filter[0];' `' L0 D6 x" A) X: |
                        lowpass_filter[0] = output;2 F: G6 \1 B: [) |; n1 v
                } else if( nFilterType == 3 ) {
% k2 R1 M. [+ J/ J8 L  v) S: R                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)# d* U  l9 u& L- r5 o* ^; e
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
& {2 e9 h  ]2 w( M                        lowpass_filter[2] = lowpass_filter[1];
: \9 }1 v& a3 q6 J$ U/ O( P2 p- v                        lowpass_filter[1] = lowpass_filter[0];
! }7 A3 P% o8 R7 f                        lowpass_filter[0] = output;
: C- X* G3 u0 k3 B' }7 R1 r& J                } else if( nFilterType == 4 ) {
% J0 L$ g; n7 `9 b4 A                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# i/ b* m. i* G2 H7 ^3 z
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
& g" I. I6 U3 S, g/ j/ o: k                        lowpass_filter[1] = lowpass_filter[0];
1 F: [. a/ i+ l: E                        lowpass_filter[0] = output;' ]4 G& s) j' j+ \  L6 m, z( _0 H
                }
1 d! _) O7 y4 m, @; C4 R5 z# {) t- K8 g
#if        0
1 {. Y) W' g) Z$ L6 l5 ]+ Z! i" @% N                // DC惉暘偺僇僢僩. m+ m# N& ^+ P. Z# w* q1 U
                {
8 L, p' t' h$ F$ H% v0 I1 b6 U                static double ave = 0.0, max=0.0, min=0.0;& o2 u; L# K3 j# ?! F5 O
                double delta;* X( W  ~' h* p: L1 R7 Z; W
                delta = (max-min)/32768.0;2 K- T# l: C4 [* \
                max -= delta;
1 \3 n& j2 k, Q9 b; p  U                min += delta;1 }( Q3 Y) j1 Z  `1 s
                if( output > max ) max = output;, C5 Z. R& V6 U3 g" ]7 k
                if( output < min ) min = output;% R' ]+ D, @# N' f( {
                ave -= ave/1024.0;
' P. X: L7 s; ?. E! A                ave += (max+min)/2048.0;  u" F" k1 W. l  u. w* x% N' t# ?
                output -= (INT)ave;2 I2 w" k8 z! T# M% g7 Q
                }
$ O0 u8 k) W! C6 p+ O( V#endif
7 h2 q! k1 O( `) ~( p8 T#if        1
& g" T- F5 i3 ^4 S                // DC惉暘偺僇僢僩(HPF TEST)
1 H: W! T# R' |6 k, G2 B                {' R0 d+ t" m& s/ d8 {: n
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);0 Q* @( R' s8 Q- u. f
                static        double        cutofftemp = (2.0*3.141592653579*40.0);' ]- N3 T# R  h  H
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# Q: E8 |* U* b. \! ?8 v& _& }4 G                static        double        tmp = 0.0;
, |7 t9 m, \! z' }. y& S1 z2 S" ?                double        in, out;5 O$ J4 c, V1 ^4 M

8 g1 K2 q3 w# j3 a+ r                in = (double)output;4 i" ~( [- V! P7 t5 s
                out = (in - tmp);* u* v% a0 x* {# [$ j
                tmp = tmp + cutoff * out;
3 }3 A) G- m  U9 |! S
7 }: y" G5 q9 u6 E! U3 o                output = (INT)out;
% `+ e/ ^. \9 z5 R                }
$ E/ [3 U2 g6 c9 `" O' [, s% X#endif7 E0 }! b( U/ L5 P. H
#if        0
4 b) P- h6 L" X/ ]5 H3 k" n+ ^                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
; e( U" B- {" ^6 {9 N                {( ^9 x- b8 t; G
                INT        diff = abs(output-last_data);- s: D3 z7 X1 w: \
                if( diff > 0x4000 ) {, U1 M4 S4 J5 Z
                        output /= 4;, P* h# m3 _- S) X0 K
                } else
+ d  M3 l& S" t; [+ m9 T2 |% `                if( diff > 0x3000 ) {  U) R& T" n) i
                        output /= 3;9 t. R7 y' u: H1 C3 c3 f
                } else
0 C* Q  V+ R/ z; e5 Y, C7 P; |                if( diff > 0x2000 ) {
: V2 ~% B3 z1 y: a/ k, Q# J                        output /= 2;) f: f6 f% i6 ^/ U: B# P0 ~0 j
                }
% ^1 w% o" {. B( j                last_data = output;; A4 M$ P: A5 i2 P  v6 y2 N: x
                }
+ q' ~, {9 T6 o  H/ {' v#endif; l3 @& R3 M- S9 g# {8 _
                // Limit
% w: m" b( j; a! Z; I( [                if( output > 0x7FFF ) {5 p$ n5 s% R/ q+ \; G0 D1 P4 ^
                        output = 0x7FFF;( y* g* ?1 A% K8 e# u
                } else if( output < -0x8000 ) {
2 g7 k3 M+ m3 p# Y                        output = -0x8000;
  l) j8 k4 c, h" k4 k  j                }
; F6 U$ w1 @' m' }3 g/ V0 {7 ~/ V. M8 \) K; d' X
                if( nBits != 8 ) {0 j; i1 A+ {5 P$ b+ z3 h# b
                        *(SHORT*)lpBuffer = (SHORT)output;! f. ?( B& L* C  e5 [) Z1 u2 [( V
                        lpBuffer += sizeof(SHORT);% N7 z, _1 D8 s2 E0 W
                } else {( F0 c6 b- ]( o1 L- e2 A
                        *lpBuffer++ = (output>>8)^0x80;( x; `( l" h% g, l
                }; N0 w: A" j! f3 a

  `+ i" V$ |7 ^& H& Q7 C) l* t/ Q                if( nCcount < 0x0100 )
7 P" t3 G) t- R7 @5 p/ U                        pSoundBuf[nCcount++] = (SHORT)output;; y$ o" z8 `3 l! A+ m+ u8 N
7 _3 @$ x# Y) ~/ M( y8 @( v7 u! B
//                elapsedtime += cycle_rate;8 u6 t: Y, [$ X3 ]' V) [$ M
                elapsed_time += cycle_rate;
" z6 ]( T8 j# G. G        }
% P* \8 ?' U6 g5 k. B  q; X' L9 ~6 Y" E  j9 y! [( k# @. ~+ H
#if        1
* N3 q5 J5 `+ d- ^8 y, N# ]7 b        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ y8 _3 [4 A, Y1 Z7 I+ t                elapsed_time = nes->cpu->GetTotalCycles();) q4 C# {0 V  C3 U
        }
. f5 D/ s: j; G9 ^' u        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
3 u7 O: o' Y# U3 y( ?' B                elapsed_time = nes->cpu->GetTotalCycles();9 M9 m( |6 [6 C# Q
        }* ^1 t: ^* k$ m! u
#else
$ B+ Y: r  I. L  W( b1 r" }        elapsed_time = nes->cpu->GetTotalCycles();
, z! F& ~+ G9 x4 F" i7 D. U#endif
) P( z/ h' A$ ~}2 f" S; y, G& r, C1 q/ z

+ E: F, H6 i5 w+ G; [// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
8 G* _" @+ c+ L' X4 kINT        APU::GetChannelFrequency( INT no )
9 T; q' Y+ a/ H{
. g+ v0 m3 D1 z( R# E        if( !m_bMute[0] )
& _4 {  V7 y% X2 W' x" S0 y2 m& ~                return        0;5 }6 H* O  E) s4 D& H

- v/ _9 U2 N  V        // Internal
8 V7 ~: e; D! \. G        if( no < 5 ) {/ O5 c/ r3 a! |& q4 z% e8 K
                return        m_bMute[no+1]?internal.GetFreq( no ):0;4 |- h8 V( @( h% P
        }" e0 p5 T- f0 L7 ~9 S
        // VRC6
2 o: a5 [; I. }! z4 ^1 F0 M/ b        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {# \% n: J) a' h. U: G+ J" J7 p5 {
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
. H5 ?  v8 O/ N6 H& d4 i0 K. `8 N        }
& g4 w( s* ?/ e. t- o        // FDS- o8 |9 K+ H9 g
        if( (exsound_select & 0x04) && no == 0x300 ) {
7 Q, ?- r/ }: g6 T9 @                return        m_bMute[6]?fds.GetFreq( 0 ):0;0 W6 v8 ]. ]1 m0 L
        }! c, F; Q3 C( t, L
        // MMC5
2 p9 ]8 `2 t* k9 j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) ]+ _; a+ a+ R+ @3 @( T# h
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; `! w/ K6 L' L. j# w: ~; O+ K        }
* E& z  q, y& Y% f9 w9 |        // N106
$ O( b4 @/ ^# c% E        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
5 ~2 Y" S4 Y" ]4 j# I% H! p+ t, x                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;% V  `$ Z8 [# J5 K/ ^
        }& n! p: M: H8 ]5 t- g
        // FME7
0 t' x3 W! K: ?7 y$ M3 Q8 x1 ~        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {/ v* D* y- ?+ i  S
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* }5 e1 D+ Z9 L4 Q# S& f; G) ]        }
; X' V. N7 X4 R0 p4 S8 N, U        // VRC7. H' P% S9 K, [& a; ?
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" W" d% n9 ^2 I                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;% g# \5 h4 B* e, x: J5 B
        }
" S- d& e; C) R# e        return        0;- Z; @/ w6 ^% N* l( n, y! N) d
}
) P; q; ^7 R# ~. y! `' ]  X( o
# o# R- ?/ ?% Q) A0 {' C3 N$ @// State Save/Load
# u  J1 J1 ~- q; o3 u1 Tvoid        APU::SaveState( LPBYTE p ), ?& J" W% j6 v. w% E8 G
{
0 a8 N: a; ]) r4 l3 [# i) S, e+ n#ifdef        _DEBUG
; r2 ]0 k; X# U+ SLPBYTE        pold = p;
! @8 t- E5 N# k' e#endif
7 ~1 A. |7 M  z4 Z5 k' G, \* q
- |; r# [3 w5 l        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% {* a7 W7 p/ l) a        QueueFlush();8 H; X( H' D* Q$ n& ?( d

! v1 K* h. W. x# s; q        internal.SaveState( p );' u8 u  `. [5 D5 N7 V. t/ Z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% X* G! Z' z/ j5 _

) I+ X# d; b+ J+ r. y        // VRC6
* z6 n0 N# a0 ?9 y8 ?5 C        if( exsound_select & 0x01 ) {
* Z" T& `- h- }! d                vrc6.SaveState( p );
/ G$ N: i2 `& D# V0 p$ w5 t" J                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, ]! R5 r" ^) ^5 }% ^
        }
5 D6 d' G! \7 }( u( l3 d        // VRC7 (not support)) {6 t$ h  A9 A
        if( exsound_select & 0x02 ) {5 D6 R# d% I, \$ M
                vrc7.SaveState( p );
, Y* V1 k& |( ^                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" p" s# I. e! b& h% r
        }$ _5 U  J% j6 O# t
        // FDS
0 f, G( z1 N/ W; [        if( exsound_select & 0x04 ) {. |+ L0 g  S/ n# {( v3 U# i! }
                fds.SaveState( p );1 h3 l$ P" k2 h5 O$ X
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- E1 ]( \: A3 U+ r        }
* C. `5 u4 W- j1 a        // MMC5
, {  ?' V- d8 z$ |) W: w4 ~  h        if( exsound_select & 0x08 ) {
# K& v7 ]2 o4 W5 t8 V+ m$ ]                mmc5.SaveState( p );
* [2 R; q) x3 U2 s0 F8 u, _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 u) b3 \) U& J+ c
        }$ F+ Q5 n8 L+ N9 q" ^( b2 f7 w
        // N106
9 J" g2 C7 M4 v7 I, Q        if( exsound_select & 0x10 ) {% g2 W7 d1 S4 u- R. m
                n106.SaveState( p );% P9 h$ T: X) `
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ m: `6 F6 x7 b0 U/ x
        }
9 j/ b& Y- y% N3 m0 h0 K! z        // FME7+ J2 j( U, f9 G, t& ?
        if( exsound_select & 0x20 ) {. A$ R4 m# y) ], C' C2 K! a
                fme7.SaveState( p );. c- f! t8 f, Q7 X
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! s$ X# w. Q/ `" k9 J- [2 G        }
" i+ g) Y1 X; f3 J9 P) e6 a7 @: `- I) P* `8 \; N
#ifdef        _DEBUG
8 |5 I- l6 W. c% F# o: V3 Y5 _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! p; Z0 W% @. v" \) z0 K5 c$ U! d#endif
4 H9 n* ~8 O0 `- B" f! ^6 _}
( S& e0 c: n$ k7 h/ ^2 f$ a$ F% F* X% e$ Z
void        APU::LoadState( LPBYTE p )
  W1 Y  a$ {8 N/ I( h, Y{; H8 u. s; Q( `2 I/ {  a1 U
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
8 V2 N3 p8 ~: h7 F        QueueClear();# ^1 i$ E& M7 b' h
) K+ m8 o# h+ ~# V7 _& v: i* G" O
        internal.LoadState( p );
$ {' p1 H- Z( E* ^5 A) Q6 G        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 S+ J" R' ~4 c' D- V
0 C% Q  ^- r$ ?$ i
        // VRC6  Y' n# S" v- E( f" b& o
        if( exsound_select & 0x01 ) {8 {/ q; F- X% b& i
                vrc6.LoadState( p );
. d8 R" @- r' G) ]( c, M1 Q) W                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ I* k( l0 U) Q" o3 y        }
3 {, E% p" @( e2 z5 S        // VRC7 (not support)' X6 z+ z) V4 j2 q5 f1 L& w$ V5 i; Y
        if( exsound_select & 0x02 ) {! `2 W& v" s% N. }' b+ ]. H
                vrc7.LoadState( p );
% o0 F7 k/ U' {' F1 l5 F                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ O% z7 n# D4 x% C4 v( v
        }
: ]$ h& ^% m/ ?2 i1 v        // FDS2 e9 G! J7 d/ v
        if( exsound_select & 0x04 ) {
) {* l/ B8 D- C! I# w3 _; u                fds.LoadState( p );
% v$ V9 H6 r# L" L* t                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 D% H! N; ^" m+ n
        }# \1 r  g) O# A' q( C
        // MMC5) y* Q, p! {( W1 |; O
        if( exsound_select & 0x08 ) {
# K, @8 [* L' d! J1 r                mmc5.LoadState( p );
, j/ s* }- h; B% N7 Z! G                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" g" g' Q( z) b$ Z9 x5 i. T
        }$ P( Z2 V4 T% i
        // N106
0 _4 P; K" ^8 X* {; F( m2 ^% |8 w        if( exsound_select & 0x10 ) {
  ~0 _. v3 x: E* Y                n106.LoadState( p );
9 N% \# V, C" y5 `+ c1 q+ h) K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 H3 c8 k4 c. R  {& f. e7 f
        }* ~- G* Y- \4 u
        // FME7
$ k7 W, G" d; w4 b( g# {' ^        if( exsound_select & 0x20 ) {/ ~3 B, Z. b+ }) k
                fme7.LoadState( p );2 y) x5 N  a; ^- `4 ^7 j
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( W; W& d4 `$ e        }5 I3 Z' k3 Z3 d' a) @
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 2 o7 {! g- G" c" D, x/ X6 w& m9 n
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。2 I2 p1 f/ N8 \6 F
感激不尽~~

5 v9 E$ W# [* \( ~恩 我對模擬器不是很有研究,% T6 {9 s- c! A
雖然要了解源碼內容,可能不是很困難,) r- r5 T" s7 i& R/ R( v2 ~- B
不過還是要花時間,個人目前蠻忙碌的。' A" P7 u4 w8 G  C1 N! Z

& M9 H- y+ G7 y& Y. O給你一個朋友的MSN,你可以跟他討論看看,' k; T4 K5 t. R  x8 p% Z
他本身是程式設計師,也對FC模擬器很有興趣。
9 H0 \+ U( l0 F* b4 f* m% z- t
( O6 Y+ a) A- q% v: }# B" sMSN我就PM到你的信箱了。4 ?7 X& X. a; n

8 D. a) q* r" t1 S5 q/ h$ E. H2 M希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 : X/ W  w& z6 u- q  A% A
呵…… 谢过团长大人~~

5 D' }' P! O6 I+ ]
* M7 q  e4 w; D8 s哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
; Z& y9 P) @0 L# ~; Y8 `1 a团长的朋友都是神,那团长就是神的boss。

: Q; g; g( _; Z4 `& e1 |' M哈 不敢當,我只是個平凡人,0 ^: C/ C8 F0 f0 B6 U
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
) U" K6 ~  [6 I/ B6 a% ^7 ]5 aZYH, [/ O2 M! M: Z/ l4 N1 o& w# {
QQ:414734306! Z  r& J2 F5 a! s# B: f* x
Mail:zyh-01@126.com7 ~9 T) G9 Q6 b% }" P0 m. j
, d% e9 K6 i! C8 k, w' z% Y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 : Q6 T9 Z6 _% x. a8 b
再次对团长大人和悠悠哥的无私帮助表示感谢~~
, v8 r" e  @2 B, Q+ X8 u
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-14 12:17 , Processed in 1.078125 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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