EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?9 m# ^! D$ C( J5 C$ B; o! H2 F
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, n6 T0 }5 H! n0 y  \4 w
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! A6 @% G6 l4 e- Y7 V% L* j- I这里有相应的模拟器源码,就当送给大侠了~~3 r* ]5 p! q5 ^
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
# Y9 g& i# }* M" S; O' w' U能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; u0 n3 a- `6 }- s9 V6 K楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
8 c( t, n. F) c' V* r: y9 N这里有相应的模拟器源码,就当送给大侠 ...
& S, k( [1 w5 O. T7 f+ T* I' F
聲音部分(Audoi Process Unit = APU):
8 G$ p. T& j' L; \* b. s' V.\NES\APU.cpp- \$ \) W# q' W/ V& T
.\NES\APU.h0 t+ E: [; _, f
. |& P8 s5 ^: A; p  a/ D2 U0 Y0 a

/ b% a; N. ^! k( ~! j影像處理部份(Picture Processing Unit = PPU):9 U) y* D1 s* r& s# M. Q
.\NES\PPU.cpp
: n% b$ W! u- f+ z.\NES\PPU.h
5 A  x9 q+ q* \1 D" R& c4 v7 m+ L" B3 Z, X) y
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:. H' O; d7 d% y7 ^1 w6 M  X
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
' _( e+ x! {9 b/ N' Y  g5 G; l//////////////////////////////////////////////////////////////////////////
# t* m! L* f' Z3 q' l//                                                                      //+ w* ?* O% W3 l
//      NES APU core                                                    //
8 s+ I. A" Z( F6 i3 U//                                                           Norix      //
% V; e. Z+ l2 t  w: O, k//                                               written     2002/06/27 //& w" \8 h* O. ?) ]8 S# _1 c6 J
//                                               last modify ----/--/-- //. s! E# K" p' h9 w) n! N# Y# M
//////////////////////////////////////////////////////////////////////////
8 s* A5 _; t6 C  m#include "DebugOut.h"
* Y- x, v# ^( U2 \1 y3 h#include "App.h"
. v* c4 Q  \  I# ~8 F9 o#include "Config.h"
( [! P; O! h, o# x/ @4 G( y* x
2 `+ `! D+ c! X5 D7 Z3 z( p9 u#include "nes.h"+ T) E5 i* G  G) g7 p- Q* v
#include "mmu.h"
3 e  K8 ]& R2 n; l9 T7 q& b  j7 H8 l#include "cpu.h"8 s3 _$ i; I7 k
#include "ppu.h") w; }' d7 Q8 ]. _6 x' V9 J; h
#include "rom.h"4 N0 i$ j6 `  C8 Q0 A# N
#include "apu.h"2 j( x# I1 P4 S6 M+ S/ I$ ~
  @* l9 x$ b, y7 W0 o
// Volume adjust/ r5 l. Q% j- P- N
// Internal sounds
0 i) ?9 H- [/ l2 h  X& g#define        RECTANGLE_VOL        (0x0F0)) l% l1 r* W4 N3 H6 T3 n
#define        TRIANGLE_VOL        (0x130); r* _2 F+ H, }. R( h7 s
#define        NOISE_VOL        (0x0C0): }: c8 P6 p4 _6 D7 ^8 k
#define        DPCM_VOL        (0x0F0)6 X% `9 m$ H, K, `, c
// Extra sounds' {' r% G* D; ?% V3 P( w6 O
#define        VRC6_VOL        (0x0F0)
' m, D* f+ M$ P& T- q+ i#define        VRC7_VOL        (0x130)) @* p0 T* Y! L6 n. B7 M8 N. L
#define        FDS_VOL                (0x0F0)
# O' V7 g3 q" m( H4 l9 N5 l( U#define        MMC5_VOL        (0x0F0)
0 \  B' F1 u2 A5 L: V#define        N106_VOL        (0x088)
3 }0 v# Z3 v# t& V9 c$ u7 E#define        FME7_VOL        (0x130)/ G6 f# T: n/ I# u7 E* c2 f/ l

4 P" y9 b" G3 L/ t% k: h4 MAPU::APU( NES* parent )
" S' H0 y5 i0 K! m% Q{4 o' s& r- L7 Z
        exsound_select = 0;
, ^$ o( q$ x  {% F6 E: m! P) X4 ^
" J. j( g2 |: w) K7 r/ W% ~        nes = parent;6 _4 ^% O* b) u
        internal.SetParent( parent );
* }/ B% R& Z/ m. D2 r& n/ U& H  _( j+ X: l! [$ \( F0 Y
        last_data = last_diff = 0;
+ G, N" _3 q+ r5 O$ ^( l1 }0 L0 B9 S8 f# ^. Y8 F$ ^7 M3 [: C( F
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
9 ]6 ^+ N9 \- i1 D4 v7 j4 C+ e) Z1 W9 |
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
: O& w1 }" F# h+ O, p) a        ZEROMEMORY( &queue, sizeof(queue) );
1 F! {6 R5 @. D- |7 ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ x* _  x8 l3 U5 ?8 S& p, r, T& e1 s4 T8 X
        for( INT i = 0; i < 16; i++ ) {0 Z; {8 Y1 q8 h4 @5 W5 f
                m_bMute = TRUE;) B) g( B! L7 v! \7 P$ U
        }) r" d9 o' p' c7 q
}
3 G% Q) ?2 |+ m% u( Z
6 B7 p' w. }4 L& G9 b; ~2 k! gAPU::~APU()
2 {1 p, S/ R7 J! H- M{; B) c- @* v, Y! G0 G
}
- {3 \. s* ?; D/ x- F# b3 J5 f5 u: @2 A
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )! H  l1 S5 U& X* b1 o6 c! a+ e
{
% |# {/ c7 T5 t; R- A        queue.data[queue.wrptr].time = writetime;
# `  U8 K( @9 R        queue.data[queue.wrptr].addr = addr;3 s( D% P! @7 l, B" |3 r
        queue.data[queue.wrptr].data = data;
0 e. \2 ~1 w# X9 ]# @- v1 i( n        queue.wrptr++;! ^# [+ l6 z% e2 d4 N
        queue.wrptr&=QUEUE_LENGTH-1;
4 f7 U2 B  O, q% ^        if( queue.wrptr == queue.rdptr ) {
" z" J* M$ ^5 {                DEBUGOUT( "queue overflow.\n" );
% O, p' R$ o6 y. f, k        }
( f5 [6 u$ J' b# I7 K  U}" O+ Y8 }+ l# H7 E0 b) p( c2 D

' |& w! N' x+ X! b, x7 {$ rBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* A. A, f! J. j
{
! a- C$ L+ |) D        if( queue.wrptr == queue.rdptr ) {
  y9 s0 G" k* d                return        FALSE;  f6 b) ^% P) U/ E7 b* S
        }
7 k& ?3 u5 f( r4 T6 J& A! C" ?        if( queue.data[queue.rdptr].time <= writetime ) {
$ ~" [  r8 R# A  r5 l! @                ret = queue.data[queue.rdptr];4 v. }) ]+ E" t5 C/ x
                queue.rdptr++;, |3 s$ n1 ~% m3 b* T$ L
                queue.rdptr&=QUEUE_LENGTH-1;
7 n+ u! P5 ^* K                return        TRUE;1 G! T; S% \# j! {% X9 `; j9 n9 D4 a
        }  {+ ?( K3 ?' S$ l2 D
        return        FALSE;' J, @, z" ]8 [/ i4 t# ?4 `9 q
}
) Z- |7 Q8 O) M2 o. Y) C
, T" O( d1 s- R+ d2 I/ s. [, N" l1 Mvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )- J. w9 `) H- j( u" b7 v
{
$ [: w& t: p9 J) a# B5 }& n        exqueue.data[exqueue.wrptr].time = writetime;$ d- Q3 `) R1 l, V2 J, @# \
        exqueue.data[exqueue.wrptr].addr = addr;
: I. v8 \; D& A        exqueue.data[exqueue.wrptr].data = data;
$ ?, ^( r; b7 ~7 A# y/ z        exqueue.wrptr++;
( X8 l" `' J! i/ p; E' ^        exqueue.wrptr&=QUEUE_LENGTH-1;) q( X: ^0 R9 m& \# z
        if( exqueue.wrptr == exqueue.rdptr ) {4 g+ M3 _# [. A
                DEBUGOUT( "exqueue overflow.\n" );
# R; ?2 p# E! s4 C) k        }
0 H  @! L: C! Q. M}! O  g) ?- m5 i% L1 U+ h& V" I* B

! {$ H5 e6 {4 l5 Z6 w! VBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! n- \: G  `, [; @/ G+ p{8 |% P- M* ?2 x0 V" }. N7 F; e* i: d
        if( exqueue.wrptr == exqueue.rdptr ) {# _' Z. Z8 P; V9 e: U  s) N2 n) o
                return        FALSE;
& h" \9 @- f" M, A        }2 t3 j; j) p4 b% c8 G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {: G# Y2 [; P7 }: H
                ret = exqueue.data[exqueue.rdptr];
' Z' ^3 B/ b8 d# @. T                exqueue.rdptr++;
- `# R8 `# N/ {4 L                exqueue.rdptr&=QUEUE_LENGTH-1;
+ {6 \; P( j) z' I/ d                return        TRUE;
5 A# S/ o7 _5 W& q* f3 J; f( f* B6 M        }
3 m, x- }4 K* q" \: r        return        FALSE;2 [! C' s8 n% k( H) t
}' `" M$ r9 B; n# u2 H7 s+ @0 v

% u! F) x- ?* c+ l4 u4 q6 |void        APU::QueueClear()4 C3 c4 B5 p& z7 n
{
/ r9 f9 O" M& Z1 f        ZEROMEMORY( &queue, sizeof(queue) );" h. h$ k7 U6 K3 R9 @: x7 V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );- D3 N5 x0 |, x- X
}
1 L/ O/ }% t1 a- b$ r4 D0 B! s  R- }7 F
void        APU::QueueFlush()/ u2 T+ v% L1 Y* M0 P: P! N
{; P/ _+ a  @, w# {* b; C
        while( queue.wrptr != queue.rdptr ) {3 u8 w7 e* m# q7 v0 x  \
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
' ]6 I; B+ X. h0 |                queue.rdptr++;' f6 T; R0 M% ~6 J& w
                queue.rdptr&=QUEUE_LENGTH-1;
' Y: {5 z3 ^7 h: M        }. b) A0 f* |2 i9 R& Q& R
" c( A6 R9 \- r/ @
        while( exqueue.wrptr != exqueue.rdptr ) {
8 i% A8 ~) a; @6 Z                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 n$ `6 L( Q5 M$ t4 ]0 u0 S
                exqueue.rdptr++;$ R6 c% M2 T4 R# X+ H5 u. P
                exqueue.rdptr&=QUEUE_LENGTH-1;7 \) q# _8 P$ z2 O: A
        }5 b# G8 E0 F- I* i# R8 {
}& b% ~  B; a; ?8 U5 C# Q7 e
9 O7 N) e% z7 j4 Q! b: K
void        APU::SoundSetup(). b) A9 D5 A6 K6 g
{
# U7 D$ p! f, @9 w6 l5 y        FLOAT        fClock = nes->nescfg->CpuClock;8 D# o2 H; Q1 V0 y, {! _$ Y
        INT        nRate = (INT)Config.sound.nRate;
( u1 A( T! [" H& ~/ V! w        internal.Setup( fClock, nRate );6 Y- w' f/ [7 D6 t& m
        vrc6.Setup( fClock, nRate );
; p. H# I4 [0 |        vrc7.Setup( fClock, nRate );
& T3 {/ S5 r, g0 V8 B# A/ o6 A        mmc5.Setup( fClock, nRate );0 h* E4 w1 }6 g
        fds.Setup ( fClock, nRate );
, e" F; P% i( M7 t% u4 b        n106.Setup( fClock, nRate );
& \) X% Z, v" w* Y# A        fme7.Setup( fClock, nRate );
( u) n2 D1 J) y+ L}
# G5 j; V6 |& h0 K9 M9 F
+ g1 R; e& Z8 B/ Avoid        APU::Reset()
! x  m  x7 Q* J" m0 W' n{
  d6 g6 A% @: u0 \6 J9 C        ZEROMEMORY( &queue, sizeof(queue) );) B6 Z% L8 ~4 x
        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 g# x  M1 S. r9 @' r' b
4 V' e! `% V) D
        elapsed_time = 0;
% H3 P# `7 i( R* Q4 i1 ~
( }7 J% z8 y2 H1 C. Q( C        FLOAT        fClock = nes->nescfg->CpuClock;" h' L% j( J6 {0 \
        INT        nRate = (INT)Config.sound.nRate;
% w6 R+ g* T/ j        internal.Reset( fClock, nRate );. X& }" k% z( x  G' L5 b
        vrc6.Reset( fClock, nRate );
. V+ q6 G$ ~9 h        vrc7.Reset( fClock, nRate );6 n, T7 h4 m3 f5 J% P2 n6 b
        mmc5.Reset( fClock, nRate );5 `0 A' ?# |4 n4 _6 ?8 }4 N$ {
        fds.Reset ( fClock, nRate );5 T) I8 ]2 S9 g$ ]' P5 h/ I1 A
        n106.Reset( fClock, nRate );* Q& j% N, `: ~
        fme7.Reset( fClock, nRate );' |  J5 m2 W" U" {# M
! Q' b" q( f9 Q( ?9 [3 L, @
        SoundSetup();6 i3 S# P5 y8 s8 X
}5 o* ^$ _& f$ q' ?& B" l

" E; |8 J* p$ |1 U; G. Xvoid        APU::SelectExSound( BYTE data )
  `' E4 v1 s* E) }: K0 j1 }4 w2 ?{
& B' u* _- G& G3 i        exsound_select = data;
8 n( A' P9 C+ L. v3 W$ n* E/ A}
' K+ _  d  R; q  w2 B- X* P# \4 h  b+ E
BYTE        APU::Read( WORD addr )
  g0 }4 z+ ^$ {{
" j1 f8 d' \3 e5 h        return        internal.SyncRead( addr );+ ]9 U/ K- Y, m; S+ g* T
}
2 R6 c" g; m5 m1 E6 \! d+ v
/ d, N' e1 P* v  ?" gvoid        APU::Write( WORD addr, BYTE data )
2 T2 V1 N' h3 P{' ]6 i$ M! C1 d8 O( h- s# R7 s
        // $4018偼VirtuaNES屌桳億乕僩
, Q/ T. D" D( ?& n5 p6 k: h/ O        if( addr >= 0x4000 && addr <= 0x401F ) {
8 i! w; ]3 D4 y. U$ r* P- k# \                internal.SyncWrite( addr, data );3 O$ i% |& B) u5 R7 m
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
0 l  m8 ?6 \0 V9 w: _, ]9 q        }  W" |1 D9 ?3 X# E5 u, O
}
  O) H5 t" b* a) Z. m6 h- r" w* ~4 q8 |; X) i9 B
BYTE        APU::ExRead( WORD addr )
3 M. `& P: O! ]1 {+ T  W" p{2 K! N/ b. R' y
BYTE        data = 0;
& ~) D' A2 @$ ~* T% G0 f. \8 T+ m# U
9 {" z0 X8 p, _/ |0 W! e( C        if( exsound_select & 0x10 ) {
' ?) i3 Q6 _4 y+ [                if( addr == 0x4800 ) {
5 Q+ t4 k" f- e6 B% k- t                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );; v/ g! U7 J( e/ |' E, `+ {+ q
                }
; S  j* e, W+ M0 I9 H9 X. H; I        }( U! A3 ?  p! X3 H1 q
        if( exsound_select & 0x04 ) {
: g. O1 n) p: T( r                if( addr >= 0x4040 && addr < 0x4100 ) {7 \, U! D5 @) q( X$ V) K/ `, f$ R
                        data = fds.SyncRead( addr );4 R6 E# ?9 e4 b/ w* b1 R5 }& N
                }) q  l- I, u; [& R9 P
        }
6 Z- m: @* h- l- Z        if( exsound_select & 0x08 ) {, w" o/ j1 a# @4 C8 {
                if( addr >= 0x5000 && addr <= 0x5015 ) {& Q2 e) m/ H& u; F
                        data = mmc5.SyncRead( addr );
: [0 y- j( M: t3 m* [4 R                }! G+ X% q4 n! S3 _6 x
        }
# Q) H9 e; x) K. A5 A% `- }2 `; {  q  q& p  _$ N# g
        return        data;
/ K# s, f+ [$ L# N) s7 M}; m' |* n) F) f& u
$ t# U! L' |7 B& v' R% K
void        APU::ExWrite( WORD addr, BYTE data )
7 r& J; L0 E/ {{
( R# l& a  d2 y* V7 F        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );  ~. ~- S1 x, t# r; ]  G! r' X

6 S& \/ ^+ t; s, a' R) x% x        if( exsound_select & 0x04 ) {5 Z" v- A8 s# s* U3 I# _8 [
                if( addr >= 0x4040 && addr < 0x4100 ) {* |/ {$ ?- v# q1 H6 m; ^/ `3 u
                        fds.SyncWrite( addr, data );. D: D# x+ G6 D% W. F6 \
                }
: F3 {3 _1 t* K& Y" @  d5 K        }, X4 a7 ]0 b; _) o" U

) `6 t! ]6 C& O' q. y        if( exsound_select & 0x08 ) {" U1 k1 P& w" I8 C  W0 N
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 o$ u  ]# t+ a- {4 g) T                        mmc5.SyncWrite( addr, data );6 s8 J7 A- f  _6 W0 R9 h
                }
2 E0 H$ T; ?+ _5 u) d  K        }% z% B% k' g* ]- y
}. L% O+ b+ `: ?
9 m) y: Y% z. |0 g4 L% q9 d3 D
void        APU::Sync()( P+ K* r, C; V8 m! w9 ]4 L7 k
{+ J- l. P% S3 o
}3 x& Z; _- {  j! O; f) ~# Q
) d  J2 f6 _2 G
void        APU::SyncDPCM( INT cycles )
' j) U" T& y* t6 M$ {  E0 J{
6 ]$ y) k$ f% F. R- N( \8 o        internal.Sync( cycles );2 h5 c( t1 A# T) B$ g

6 f* }7 s  s4 n, c! {        if( exsound_select & 0x04 ) {2 o: U" o) J% H0 U
                fds.Sync( cycles );: _/ |% Y; Y) n* H, T/ X
        }* ~# ~' p9 N3 S! s( T* w
        if( exsound_select & 0x08 ) {. ]2 y4 i; U9 @
                mmc5.Sync( cycles );
) ~; O& h- Z2 U) B+ J        }
# _+ F0 \6 T9 q+ W' s  b  G9 H% ~}8 n1 E% \1 M. M" y5 P8 f% R8 r. X
* s0 c% b! K! `! a3 \/ {3 a
void        APU::WriteProcess( WORD addr, BYTE data )
; F% R. U7 \5 y' @9 {{
( }8 m. T6 B3 D8 w4 C: E5 b        // $4018偼VirtuaNES屌桳億乕僩
& d2 L5 Y( {% D0 e* R! }' W        if( addr >= 0x4000 && addr <= 0x401F ) {4 @, G1 e2 P5 o
                internal.Write( addr, data );
1 E0 s2 H& o7 z        }3 ~- X& G  ]; a7 M( ~
}/ t, M. ^5 @1 i/ d

6 I# j6 Z& x" }8 T  Dvoid        APU::WriteExProcess( WORD addr, BYTE data )2 f2 ?) W+ [- x4 [
{
+ }/ g- z% d: ^& }1 A        if( exsound_select & 0x01 ) {
$ z$ I; g: j- U  l3 v                vrc6.Write( addr, data );
% I5 R. F" f! m% u; @        }  S4 r/ \. S( b- z; c; }! `
        if( exsound_select & 0x02 ) {$ }7 y& C7 X0 A0 A
                vrc7.Write( addr, data );
. P' ?! B1 G  Y# a6 ]) I0 P4 k# C        }1 O* U( H1 E8 z0 j, c
        if( exsound_select & 0x04 ) {
, R3 C# o1 T& }5 v' T% u- V# x                fds.Write( addr, data );
8 @- Y6 O6 U/ d! x( _% e        }
$ q0 `4 I! F1 n* z# @        if( exsound_select & 0x08 ) {
" I$ b/ m* e! u2 Y4 S; j' {9 `% d                mmc5.Write( addr, data );
4 F4 o! ]2 G: M' M        }
8 F6 l0 n- ?: k8 ^& m4 {# u        if( exsound_select & 0x10 ) {# G6 |3 L( N; |7 n' G
                if( addr == 0x0000 ) {; q& h7 {, v1 O. n+ n# k6 `/ e7 ?
                        BYTE        dummy = n106.Read( addr );. d& Z2 d8 H- h. X& o5 K7 B
                } else {- X4 G2 _0 R* v9 v: L
                        n106.Write( addr, data );+ l4 O9 N4 I5 S
                }
$ s& [+ O, `0 {/ e8 o        }
* n$ }1 d" e+ G% {4 ?" O3 x. u* i        if( exsound_select & 0x20 ) {
/ d7 y- Y. K  Y) r4 q/ z8 c                fme7.Write( addr, data );6 H- `/ ?, O" D( l: S5 _( A
        }7 ?* b* ]# D" _/ F3 d8 M
}" ~* E% R+ ~6 w. c
3 f3 i; H0 I" \# M  P  p1 N
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
5 b$ ^; A6 m+ j0 |{/ u, E2 M0 a, ?! W
INT        nBits = Config.sound.nBits;
. ?2 t7 g8 m' ~' Q' |' Q' Q! JDWORD        dwLength = dwSize / (nBits/8);  `( h$ p) }1 [" d1 r  g
INT        output;
# a7 q: s6 \) X  |QUEUEDATA q;$ ~- O1 o% Y8 T+ [" ]4 w( ^8 L
DWORD        writetime;* W! T; u$ F3 @2 ?% u0 r& v

* \! M7 `- ]  y# Z1 i; d: mLPSHORT        pSoundBuf = m_SoundBuffer;' M1 @2 z3 Z; S  ]$ G
INT        nCcount = 0;; J: a; `4 ^6 |/ O

. x( t# M. A+ T, J" tINT        nFilterType = Config.sound.nFilterType;; s0 j# a) s/ `' {8 g8 V, O  S0 v+ m

/ L8 N8 G. r0 y" ]- D        if( !Config.sound.bEnable ) {1 h% U2 d' _; ?- @5 z
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
+ S7 O, Z' A( T+ d9 H                return;/ J3 p. i( I8 U1 ^7 q" t
        }
8 D& I2 e8 Y1 K8 f+ \+ C) s
3 W! {; i3 ~5 Z% A        // Volume setup
) g5 x1 q: E8 H& i( T( ~- O  M% k        //  0:Master
( W% L. @6 I2 O- K9 j        //  1:Rectangle 19 \7 ?1 k( k& F- Q9 j
        //  2:Rectangle 2
# [/ g/ D! o2 E, a2 Q9 U        //  3:Triangle
  [- I( b8 p& N8 ]2 V; ?6 ~# l1 c. }( C        //  4:Noise4 d& I# H7 v5 s0 ?" f
        //  5:DPCM
" H, w7 g! v: [8 d        //  6:VRC6
  ~% l$ S- L5 |        //  7:VRC7( n! o8 @4 L. ?0 j; W
        //  8:FDS# ]0 D; p( q+ z: Z! X) d. z
        //  9:MMC5
$ d/ s4 {4 D4 T) C5 M% @, g0 J        // 10:N106
; j( A- p$ Q  B1 e! S6 |" G2 j        // 11:FME7
6 |( D0 O2 M7 F: a0 t        INT        vol[24];( n/ Z; e3 G" N: [$ }$ C
        BOOL*        bMute = m_bMute;' y4 J. X# z7 d0 U* o  m5 s+ N$ [+ T, j
        SHORT*        nVolume = Config.sound.nVolume;, s) e# I' y$ g( o9 s/ ~5 ~

( K  w6 {4 c! o% ^: f        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" c- q1 l4 x. o  u  g$ @2 k% n
2 V7 y: c& A. C6 d4 I  T1 h2 h9 w9 L
        // Internal
! L. G5 P; P  m4 y4 C- j$ r        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;4 y7 T7 L7 z3 G
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' |9 y% T: K  s( }+ y% u        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;& V5 M& A: {+ K. \7 |9 ]6 ]
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 _2 ~6 B- Z2 D9 t" k, R* Z2 [
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
- M8 m9 L5 D3 P% J; ]" K
! [/ |2 n, Z) Q( d# G2 v: x" W        // VRC65 X2 m" V. A; W
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- d! e9 w7 T: u! U$ b& `
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;3 o. N7 H: w7 z% U
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- @, d& S+ @; L" s, \, @( u% l& I3 p

* ~3 ^( @# w4 z( Y: R* ?2 }        // VRC7
) g; I/ ]1 n% W9 @6 G        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
3 I' Q: ?, N/ U5 Y# I  N+ c8 ?9 U$ z! i# I) ~
        // FDS/ o. v: C# P6 L; R
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# k6 G& u7 V! t; u/ s# q- m4 u7 Y+ J5 q  h" N/ E3 X7 A' w; n4 B% b
        // MMC5
. v* Q; l" V" R: s5 |8 |        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& Y9 t7 a" V4 s) n
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, |" z( {- Z) g. Y* M& d
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, Y) Z. C% J) Z8 d1 z2 D$ T) o( @$ K
        // N106
% d. \; L2 m3 Z0 [/ Q; k        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- h5 H/ Q. _, A9 n        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 Z8 ]; t( D% I! }6 W4 G! Y7 c; j        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) c& S7 o) `6 R' C6 d% y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( }0 ?  ?; K1 P- e        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 C$ A# u0 o  K# b  I& {# ]        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ g/ e4 o/ _) Q8 v, k. @. f
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 \. O8 g* e4 w% n        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 r9 _' K6 J$ C
: V! p, P# |/ M6 r; v: w- M        // FME78 P4 Q! I& P  Q$ q7 }
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 l! x' P! u( A* ^( D: V4 X9 }        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( ?- A- X. f! v+ ^: a
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 y/ @+ t( U; F- M3 M  I" L7 w3 p' L; d: U6 Z
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
2 i) p* |; U" I* K' @8 ~6 @: M        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 G$ |9 P$ W$ ]
0 a- `. m" P- H
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
. `2 g) b" v. L6 n! g        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 \) U2 @. o( c0 j
                QueueFlush();
7 {8 U- }) P# V: N$ [+ |/ f        }0 @) q1 z8 |* O7 ?' {( ^/ p

' _1 H1 P$ e& m+ l. ^! q; N% ~1 ?6 C        while( dwLength-- ) {' ^3 h  Y0 C6 \+ p
                writetime = (DWORD)elapsed_time;2 A/ d5 g0 B0 R/ g! J

$ ?9 ]$ o7 U( F2 ?                while( GetQueue( writetime, q ) ) {
" p- L8 B% B, q/ w/ n- e- {3 K8 u                        WriteProcess( q.addr, q.data );
! w3 n. o4 J% J: g                }" H2 k9 k9 N% H

1 K9 M( m  H7 L# J( U: M                while( GetExQueue( writetime, q ) ) {
9 C3 b8 G# H) l3 {! d& g" [. G                        WriteExProcess( q.addr, q.data );
2 D* e4 X; z- Y/ c                }3 B5 J; e$ h9 h9 G, ^7 ?) i' m; n

( ~) O' F+ d( P$ b1 J' Z/ M                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7; S) n! H( T- [  l% h1 v- f6 n
                output = 0;6 N0 W1 W  F& g( l
                output += internal.Process( 0 )*vol[0];
1 U1 o- n" X$ M                output += internal.Process( 1 )*vol[1];
+ L$ G/ [' @4 p, R                output += internal.Process( 2 )*vol[2];
, r, X4 y. {, s                output += internal.Process( 3 )*vol[3];  I+ v& }* X1 S; G8 ~- U  t
                output += internal.Process( 4 )*vol[4];
" {% ^0 r, ]' l2 Y: ?" W9 ~8 K
) [  L* n$ H9 h0 h                if( exsound_select & 0x01 ) {
" I0 N4 H2 a. z. j% L. u, h  D                        output += vrc6.Process( 0 )*vol[5];6 i" }/ M+ [2 H  N$ y6 R( }
                        output += vrc6.Process( 1 )*vol[6];. S. E6 I. h/ d9 O
                        output += vrc6.Process( 2 )*vol[7];6 r# e6 `) J* G* h+ @. x& q( l
                }/ n: G2 X2 v) `- X9 [: O9 E) j
                if( exsound_select & 0x02 ) {8 y$ Z# }) S8 G
                        output += vrc7.Process( 0 )*vol[8];6 \  b0 K7 y7 D
                }- [+ \: [/ ~' a5 m$ c) u
                if( exsound_select & 0x04 ) {: i. z( d2 x; e7 y9 D
                        output += fds.Process( 0 )*vol[9];3 I7 K9 f! Q* S. w# ~$ O9 K$ A3 @& {
                }
. b# _" C; _. @  m                if( exsound_select & 0x08 ) {! g5 H0 a& l" A/ x7 d3 a; [
                        output += mmc5.Process( 0 )*vol[10];
8 l7 c  r3 K2 K9 U                        output += mmc5.Process( 1 )*vol[11];$ ]9 m# N3 y" U5 p) l4 T
                        output += mmc5.Process( 2 )*vol[12];# f9 W0 r' C/ P! G9 i
                }8 A+ }7 F) q2 [) p* @( a: R0 X
                if( exsound_select & 0x10 ) {
) n+ o2 h; r) \                        output += n106.Process( 0 )*vol[13];
( ~) R4 {  B/ f" ?                        output += n106.Process( 1 )*vol[14];
: @: y; J* x& e, ], g0 c  u                        output += n106.Process( 2 )*vol[15];1 i: ^' d' ?9 K% Z5 m
                        output += n106.Process( 3 )*vol[16];
, p0 {. p" `" j9 h  f, S6 t# V. |                        output += n106.Process( 4 )*vol[17];
; _5 U7 }- v$ Z; T$ `                        output += n106.Process( 5 )*vol[18];, ?- @6 i6 Z+ s9 G' [5 l: ]
                        output += n106.Process( 6 )*vol[19];
  k) W4 ~! t* m/ R& Y) ]; x6 _                        output += n106.Process( 7 )*vol[20];
6 Q% X4 a. U- @                }
# ]2 `+ J$ B7 l8 F% m1 P2 ?8 W                if( exsound_select & 0x20 ) {
% p8 I6 g; l; [4 E! D& T6 `0 k. t                        fme7.Process( 3 );        // Envelope & Noise  q5 X% p/ f# w. f' X3 s5 u9 E
                        output += fme7.Process( 0 )*vol[21];1 c6 s: \; x& Y
                        output += fme7.Process( 1 )*vol[22];1 ]0 `+ K# Y8 h6 |$ S2 T9 ^
                        output += fme7.Process( 2 )*vol[23];( `& O4 Y9 ~4 _+ y. G) u
                }" D) ~" D( Y0 a7 d$ ]" Q

; `0 W/ L+ z6 Y                output >>= 8;
# D; N; S1 }9 J5 c% P2 u5 [4 l7 M9 _$ u4 X: w9 F
                if( nFilterType == 1 ) {
" T7 v# o1 y0 U% \- F$ C0 J                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)$ @' t  U9 \" g8 @
                        output = (lowpass_filter[0]+output)/2;
5 X9 N# M% s. _                        lowpass_filter[0] = output;" S6 `' M0 g' y1 }0 I* T. \
                } else if( nFilterType == 2 ) {, U1 u$ i/ X7 S" P/ v/ e0 s) d
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
' p$ N& I1 l; g, m! p% u& r5 p' o* Y                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
( x$ p# e% A+ O% z* @- x* O                        lowpass_filter[1] = lowpass_filter[0];, u$ ]# N. X. v" s9 E
                        lowpass_filter[0] = output;& K5 [1 h+ ~. ]: f. B& p0 {
                } else if( nFilterType == 3 ) {
; j: k3 k) _% g; r2 S                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); E0 K$ L" ]" U4 Z1 Y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
. A7 V% S+ h+ U3 J  _+ s                        lowpass_filter[2] = lowpass_filter[1];- N+ y8 S$ G$ }9 F! A
                        lowpass_filter[1] = lowpass_filter[0];
9 m9 ]/ `9 }, D2 E# w                        lowpass_filter[0] = output;
# b1 h, w% ], E& T7 S+ }- ~* g, {4 X                } else if( nFilterType == 4 ) {
/ E0 |) S, o' u4 V                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)  f/ Q" }& m5 t
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 n% ?( K( p( k                        lowpass_filter[1] = lowpass_filter[0];
, R& I# g& u; @- Q7 s: X  B. ~( m                        lowpass_filter[0] = output;3 Y' V; e$ Q+ K! O1 m$ c" B3 T
                }
" }5 t9 @4 J# h$ _( y% n9 p4 }) a, C1 J& Q4 @  V7 ?
#if        0
  C4 Z  ?2 S5 |  E, [2 A! a, V7 V, E                // DC惉暘偺僇僢僩
$ V. O7 G0 Q4 {( q5 K$ x1 B4 E9 ~0 |                {* Q9 f) ?$ r- R. e
                static double ave = 0.0, max=0.0, min=0.0;
- d% j" }2 K7 Y- c2 O                double delta;. R+ S9 L6 ]7 {4 W  X
                delta = (max-min)/32768.0;
5 W- d* X( R4 _2 \                max -= delta;
$ V- r; B* M0 `  I                min += delta;
( A8 u! N* L0 L# R; {4 [                if( output > max ) max = output;* c7 O% O! ?9 e0 U: j
                if( output < min ) min = output;: G9 m1 C% k2 Q6 @6 r0 b
                ave -= ave/1024.0;
  d+ s# L3 K& }. g. c+ y8 S                ave += (max+min)/2048.0;
; t) A( \( y' Z# V5 n% d  S; O                output -= (INT)ave;: S: w5 Z5 M/ E8 Y( c4 R( P
                }
5 S* P) f, ^, k  W6 H#endif/ \5 m  H* c7 e! a* W3 I# i! `
#if        11 a# A. s# i' R6 ^8 o- `
                // DC惉暘偺僇僢僩(HPF TEST)
3 Z6 X* Y3 u4 K' x: d% R8 I& ]- i                {/ ~6 B) U; c/ a6 m' t' J0 s
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);8 f7 ^/ \" F! G3 x" k
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- V4 I) H8 O( @1 E, Q( q* X                double        cutoff = cutofftemp/(double)Config.sound.nRate;
. X" `! b$ }, E( ^* K/ v! {                static        double        tmp = 0.0;
, u9 [" U. b- L& q                double        in, out;: l3 Q1 W) f6 Z' t
! Y" k- n/ E7 y# F
                in = (double)output;
; u* l/ |" ?1 l. H& Y5 U7 Y& f' h6 b                out = (in - tmp);2 H0 n! P5 d, {9 }& I" E# ~: D
                tmp = tmp + cutoff * out;
  c" c+ f( G2 E# W2 ?" l5 |
( o# O5 H1 N" S+ {, t                output = (INT)out;
' z' V# c$ ^8 A+ s2 D8 x& Q1 W% U                }1 X/ p( J- K6 u( I& ]
#endif
& ]( h( y4 |' t# r# g4 C#if        0
9 O$ a& a) S! J8 `' Y                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 `3 W6 d) y* k: K! X                {
; X5 k- M5 T0 |                INT        diff = abs(output-last_data);
5 \/ w2 b- n9 g9 U( w! b                if( diff > 0x4000 ) {9 s4 P* }; X7 |7 C/ z
                        output /= 4;# H8 P+ _: J( p1 D3 D
                } else
9 R, l$ Z# W- A5 p                if( diff > 0x3000 ) {. g8 ]( q) ?3 W) }7 M
                        output /= 3;
; x) _5 `5 j+ o1 P4 N7 X; t4 C3 {0 L                } else4 r# B" S+ ]8 ?- V7 B* D/ B2 r
                if( diff > 0x2000 ) {
1 u' ~+ M) k, J                        output /= 2;1 h6 z2 r& H$ O: D8 z3 |: t+ \: t' i
                }7 `2 v' d, D8 H6 p3 j4 V9 z  C
                last_data = output;) i! [5 K  e0 e2 B) c
                }
# r8 D& k4 z' m) G#endif5 s% C/ Q( Y* E. @% [( \8 A, c
                // Limit9 v' S3 q7 j; u: R0 C" r" @
                if( output > 0x7FFF ) {$ V# c: L5 W1 t2 S3 j- B& \( G
                        output = 0x7FFF;/ g2 |9 n) P# L% `7 A; q+ |% I$ z
                } else if( output < -0x8000 ) {
9 u! x# [7 o  h3 {. D5 |2 W                        output = -0x8000;5 b  c$ D% g* a9 z1 M) D6 F) c
                }/ F$ t4 ]" H; R( L/ y7 @! i
0 D7 T% X6 ^* x* V: r4 m
                if( nBits != 8 ) {
, Q9 x$ S6 s' A- V                        *(SHORT*)lpBuffer = (SHORT)output;" e) j& |: x. v- X- g+ n
                        lpBuffer += sizeof(SHORT);8 V# \+ ]7 w. E5 M& X+ u
                } else {: O* G5 n' Q/ X8 d( s3 S! U! u" ^
                        *lpBuffer++ = (output>>8)^0x80;
( {+ {% e0 N# h$ W# s* W9 g! n3 ?                }
( t# }8 j. G7 H! w# S, \" c+ f$ N5 M' `7 \* C& ]3 y
                if( nCcount < 0x0100 )$ [$ `' v* T3 @  Q) Y2 d
                        pSoundBuf[nCcount++] = (SHORT)output;
) w7 r3 O! q. y2 {9 N( O
( j+ }. A. [$ j& A) E0 b//                elapsedtime += cycle_rate;
' d' Z% @4 U3 I                elapsed_time += cycle_rate;, S1 o) ]2 n) x
        }
% h! q, l: e. C! L5 c. e
( @$ Y, t# _# h3 n7 I$ `#if        1" w) f$ U' I' U9 E- ~
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
7 f7 ?% I: T+ S+ N( m/ g                elapsed_time = nes->cpu->GetTotalCycles();
1 Y. i! D- w" Z% r9 p7 m4 d        }
) X- ]& q, j4 I        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {5 V- M5 z/ x% Z$ n, h* z. V9 L
                elapsed_time = nes->cpu->GetTotalCycles();
, y! l# ?! ~( y. R( l  ^. S        }
+ d8 e5 ^* ~6 v: H#else
0 c0 D5 H+ @/ T5 q/ ~        elapsed_time = nes->cpu->GetTotalCycles();
4 ?) o' e% g2 r! ?8 K& j1 z6 N8 y7 H#endif) D9 i3 |8 j9 s4 ]
}3 U, s+ ~$ f' R

) v, y" D, d& s+ D! m( Q( a// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)# y0 ]. n" g, I0 g" K
INT        APU::GetChannelFrequency( INT no )$ S# u9 p  c8 p9 p8 w' }6 u0 U
{, k1 @4 s& O3 [8 S2 l
        if( !m_bMute[0] )
9 i1 N& J; z1 |' a/ ]: [0 ~                return        0;/ }4 m! k, f& N9 S7 z$ s
' i: l, A! N4 ~- }- L! a/ w
        // Internal
  w$ ]5 E6 R; F+ V4 ^3 M, E        if( no < 5 ) {& x) k3 ]$ G* R: q
                return        m_bMute[no+1]?internal.GetFreq( no ):0;  o- I: ~  O, o! p) ^+ A$ W
        }6 f. I& W% V( I
        // VRC6
: u4 |) v* |4 ]7 B, {: C3 n        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {  I. K  ]) a6 ]7 v4 o) r5 Z9 [
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
7 R3 |& X" C, I        }  b6 {% j5 B* W3 M7 h4 Q- L8 U
        // FDS
7 z1 Z7 |5 f. z$ z8 }        if( (exsound_select & 0x04) && no == 0x300 ) {0 x5 f' ?% c* A, i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
4 Y2 d- g8 X7 F' L        }; M! v4 ]' v; Y0 Q3 F
        // MMC5
/ v: m' ~! p/ {0 n$ Y$ o' u! T        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {8 u; A5 }! E) ^
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% n6 Q( R" P2 w/ [3 X: ?9 }# m
        }
: j$ D# a0 p, t5 k  }& j" U0 d        // N106, ]) R# p' R, E3 k3 x  M7 b
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
3 O; r8 L7 F0 [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' e4 I$ `4 d0 X' |$ P        }
4 ^1 Y7 P' o( }2 n* ^* a        // FME71 i# t: b: c) v" b) j( C/ K
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
, ~* b& q  r1 k+ r, r                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, Z! |% K% B5 P8 K+ H
        }
' }  v; n( s* W* H' d1 j6 I# |6 T        // VRC71 t1 g7 K- v6 q
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
. Y  k1 u' f8 M4 u                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;4 Q; R' _4 x4 I0 s
        }
+ B; ?: P5 J! {9 P5 L( W- l        return        0;; {9 L: w9 r4 H) [) _+ H' n
}
- E' Y/ U6 B3 q% i0 S* V- F$ ]: ]; [3 A0 y7 c. t
// State Save/Load
3 a7 E& n8 z% c+ @1 ?9 ^void        APU::SaveState( LPBYTE p )4 _+ W8 z6 ^: |* u& T
{) l1 C$ z* L2 f! h
#ifdef        _DEBUG
' N9 U5 W' H9 F/ x; v. J0 GLPBYTE        pold = p;
1 Z' O- v% k! U#endif4 c3 c; h2 R7 o6 _
7 S( |( R8 e3 Q) H
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
( B' }! G& J- a' v. h        QueueFlush();
' Z( E# S/ q5 H! K* w& p; {# A: F& a+ ?2 M0 h- F# b2 {* z
        internal.SaveState( p );  J, r1 e" u) q$ ?  w
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, V2 U/ ]# `) M. y; B( ^, S0 M  a/ `7 X+ y
        // VRC69 ~  F. z7 c' p: [# F4 e+ u; V
        if( exsound_select & 0x01 ) {
; i7 Y. z- ^$ V5 s( [4 b                vrc6.SaveState( p );! a' P+ B2 @% N% b9 L
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. H" U, q  T& }1 \5 X4 J' |        }
5 p7 `6 N/ {4 G) Z- Z0 V( l        // VRC7 (not support)
- c) k4 I# k5 ^* k        if( exsound_select & 0x02 ) {% C+ N8 n$ i5 \! i2 d  l
                vrc7.SaveState( p );
0 n& r# R/ k& @1 ]) a8 g. ]+ n6 V                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& R) ]2 d* o' z2 Z* X        }) {- w6 h# \; W! f, h- H
        // FDS
7 N: x* {  O- T        if( exsound_select & 0x04 ) {
  [: b* Z: z# l8 b; A9 C& y                fds.SaveState( p );
* C! K2 @3 [3 {& {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 i' B, |( a! B3 ]
        }$ H& l2 E# ?$ r7 B/ V, L
        // MMC5* F' Y3 h4 }2 a) t. M# x
        if( exsound_select & 0x08 ) {
7 M9 {& a3 ~1 f: F' u+ k6 P                mmc5.SaveState( p );
7 o  T5 o9 {/ ^) ?7 p, s; K6 A                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 [3 k% R5 f2 u7 d  I# D) @( B        }
$ @% @8 W8 D  x" |% k) G5 L- F        // N106
/ F; }  t! b9 v( h: Z8 i        if( exsound_select & 0x10 ) {
1 a+ H# t; v: F6 v7 W/ y, A4 z& k! K1 j                n106.SaveState( p );6 @1 f7 ?# K7 O1 ?* E8 v
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ [1 A, t8 d: ]1 r
        }
4 ?  x- ~1 s4 \8 V9 k, @9 H2 V+ H        // FME7
0 D9 b8 Z4 m+ x: x% @        if( exsound_select & 0x20 ) {
/ n7 f+ r, S) [" R                fme7.SaveState( p );
1 y7 ?% h( Y- H  l, a% N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ q/ P& z9 Q" c
        }2 T+ S  Q3 G( o9 b( D0 q
+ s! [. ^( A, N' e* g( e0 ?
#ifdef        _DEBUG
0 f8 c0 O* [% ^0 O, z- g( q" x. U6 }DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
) l" J6 F; X2 i4 O: K5 q" ?# @#endif' H/ W! g  R+ q, J! \
}( {1 j! w4 R8 }- L

) ]8 `% _. d8 x9 e1 w7 vvoid        APU::LoadState( LPBYTE p )9 L" t: V  \1 q3 ~. U7 j6 R& l
{/ L. b3 ?: m2 {9 p0 m
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! H# L: n* i, T( ?0 I9 z3 c
        QueueClear();
! b/ S. g7 \4 {/ l2 c6 p  X; |7 _+ @) [' X
        internal.LoadState( p );5 A" ~. J3 g" O9 v& k/ U
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& W8 y! i! b' q" z$ x& l  @

" _0 N/ Q' P: ~: I) g. ?        // VRC6' n- y5 m# G  I. L, K( k  k
        if( exsound_select & 0x01 ) {
  p/ q. e. |. ^* [/ e' C* M                vrc6.LoadState( p );2 {8 x/ g8 t( L2 D6 y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, q- H7 f& `( M: y7 T# c7 u
        }
: q# E6 J9 n. k( E- p. g        // VRC7 (not support)  q+ }- m- W6 r: `% r
        if( exsound_select & 0x02 ) {
1 [# ]& R/ e7 ]% s) F2 Y" D                vrc7.LoadState( p );. g9 d" t" @! j! b- b; N$ Q
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 T6 E4 j+ X0 H; t# D: j  W        }6 I6 L0 i- ?1 D; h
        // FDS: C: B/ M! Q: p: U4 H' U2 I" ?
        if( exsound_select & 0x04 ) {* s6 O6 i# z+ a) y1 k( B$ b& }$ [
                fds.LoadState( p );) w+ ]/ F: o5 S
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: y+ M/ u1 w3 X7 E. i+ o
        }
2 w; Q! P% O: o& d7 y        // MMC5& c. A+ v- k: B* z% X
        if( exsound_select & 0x08 ) {
% b3 I8 z* J. K( v% x$ Q) ~7 @                mmc5.LoadState( p );
, \* Y4 {/ D+ p! g$ e+ u7 J                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 F  o; N6 H  _9 u/ `4 Y! W8 x
        }8 L5 }+ {6 A& M3 a4 r& d% R
        // N106
3 @  ?1 f+ }# E: Q- z$ k: U' d        if( exsound_select & 0x10 ) {
+ M* H  @4 f7 F4 O) E0 Z/ t! K                n106.LoadState( p );
6 L- m, P; P; ~( y; T  u# z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 C9 F/ U: U2 J. x$ I        }4 Z, e% B/ i3 o: a/ I
        // FME7
& E* I$ i* f3 p$ q' O7 Y/ }7 b        if( exsound_select & 0x20 ) {; H% i3 d, K  J# u. w- B* I0 T
                fme7.LoadState( p );
& {* @; v) i, k" z2 p/ O                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 j& ^, q! G9 N9 V$ }( p' I" d  |        }
8 m* F% x+ R( Y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 7 W+ X  ?; p& }& O
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
8 R4 @! y' ?" L% x. ]5 C感激不尽~~

! _; S4 _. c2 m9 g9 c7 ]2 |恩 我對模擬器不是很有研究,
: f1 E6 Q. [  \$ e" A雖然要了解源碼內容,可能不是很困難,4 T" r  c2 d6 c$ X+ y) y1 q
不過還是要花時間,個人目前蠻忙碌的。2 l$ }) M' n0 w' N) z7 f
% y- f& l: Z! \+ y
給你一個朋友的MSN,你可以跟他討論看看," F1 b- `& i# `) \$ J5 n( E
他本身是程式設計師,也對FC模擬器很有興趣。
, t  x! _4 N  G% o; Y7 _7 R$ U# r- B0 `% q. n% n
MSN我就PM到你的信箱了。; B: m2 i$ n/ \- A. D: y
) U' g! S# ]) U1 @7 a
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
: ]* m' J- D7 L) ?$ x: \: f) e呵…… 谢过团长大人~~

! f/ P* P8 O, y1 U
4 j' ~; }: {( p哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
& G; C0 Y) q' p5 y$ A团长的朋友都是神,那团长就是神的boss。

7 A* F: v% W$ G8 x+ j, g7 h0 L哈 不敢當,我只是個平凡人,' F6 V4 i& Q' X
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# l+ J/ l: g# C- K$ W8 L
ZYH
; ?' ?7 e) ?' f2 O& Z) eQQ:414734306
6 T7 C( }# P/ N3 Q$ ^4 @Mail:zyh-01@126.com5 a' p3 N( ^5 m. S' a* l6 S

. F1 d& y1 i& D3 c7 ?. S( z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表   b, [' ?# t* k+ w  \
再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ d% P. V  [8 k+ {1 D  X% b
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-4 13:21 , Processed in 1.085937 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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