EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?* A& }: f* f/ a* s8 Y# N4 x1 n* L
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" k6 k* |/ ?/ B  S/ q- Y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, h' z. I7 p0 w- f- X! s
这里有相应的模拟器源码,就当送给大侠了~~
: Y! Q$ N! @( P& C4 W: e3 Y2 |http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
! i7 g4 U: l% {+ T! e/ \能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: t& g7 P' X$ \' `5 L/ V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ D3 d1 w) r; l* f
这里有相应的模拟器源码,就当送给大侠 ...

, g8 X" @' A1 y! [# ]聲音部分(Audoi Process Unit = APU):* S# \' `0 _$ [) t  P9 |9 g
.\NES\APU.cpp
9 q- r# t# X# v; G9 g# r.\NES\APU.h
" ^; g, t, G! ]- p: t
, B& r2 F+ g* B) O. {5 A  M" m  P: j6 F6 W; o& ^" K/ v& S
影像處理部份(Picture Processing Unit = PPU):8 D  r% L8 H" T8 z3 s
.\NES\PPU.cpp
2 \4 U  q6 B3 L9 h* f6 X& O' E7 ~8 N7 E.\NES\PPU.h" ~4 K4 f9 {9 H! n5 H* c* ~5 s
5 \- Y  u: l# L/ U0 O- w. j
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
! O4 D) c+ f7 j& t% l+ ?! b感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  h6 a! P4 l: Q( @
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; l2 o5 }% x; D( @# Q//////////////////////////////////////////////////////////////////////////
! ^3 A8 x* k, G//                                                                      //$ g2 f6 ^( v# G& w1 x4 p
//      NES APU core                                                    //& J( M5 J! T% H8 P; S* W
//                                                           Norix      //8 ^( ]- U, u2 w2 d5 Q3 B
//                                               written     2002/06/27 //
( i+ s$ ~9 l+ T, v2 u, [$ l  h0 }//                                               last modify ----/--/-- //1 [% E9 R8 b' S  E, u5 N0 l
//////////////////////////////////////////////////////////////////////////% h, f, C8 Z3 d% K  [1 z! J' @
#include "DebugOut.h"
# v6 d7 g' h3 d. X#include "App.h"
) @( Y7 f% R. @# n1 S1 e1 p) X#include "Config.h"
# S* ?+ E# {3 e- D
; E* E. i5 A. I: P5 ~- T#include "nes.h"* I! R; U8 t" }0 i  B
#include "mmu.h"
, \; {( C+ N5 J4 F& E7 \# o1 h#include "cpu.h"
3 C. \0 n/ J+ ~2 g) A- Z# y" x#include "ppu.h"
: @6 w) b  ^* J! f# {+ s: v# D#include "rom.h"
  R: f% |, v, A! k1 g#include "apu.h"
3 M, x) ]/ {. k! e  v
0 z( Z, Z: N' L: ]4 g3 t// Volume adjust
8 Q" O7 h4 A9 [9 n// Internal sounds
% T' r9 e! \% }" F#define        RECTANGLE_VOL        (0x0F0)
1 y$ t1 T2 D4 M" y7 g1 Q#define        TRIANGLE_VOL        (0x130)# @8 L+ z: w6 U
#define        NOISE_VOL        (0x0C0)
: f4 d" T$ t4 V6 e#define        DPCM_VOL        (0x0F0)
+ g7 w5 |1 _1 x// Extra sounds. @7 l. {* q6 t9 s& z
#define        VRC6_VOL        (0x0F0)
5 S, x- {* O3 V- C- C* Y) O2 J9 M" Q#define        VRC7_VOL        (0x130)3 U0 l8 B5 E; N" f
#define        FDS_VOL                (0x0F0)) S. G5 ~8 F3 S( V. B$ ?2 z
#define        MMC5_VOL        (0x0F0)
% j, _- h5 w8 O8 F; A3 C#define        N106_VOL        (0x088)4 H# {' K+ k% K4 {1 E
#define        FME7_VOL        (0x130)) a4 D2 i$ y: h0 i
& n/ _! F) T) w2 t. N% P4 ?9 Y
APU::APU( NES* parent ). Q2 u, x& v* H1 t7 V
{
4 N3 G! g6 A$ s' Z+ E1 n        exsound_select = 0;
# n) W' l. [" d4 s4 d  y
. h5 D8 A- T# J/ k        nes = parent;
% Y/ v, D& b0 A/ O; P        internal.SetParent( parent );
7 l* F0 {! L, o% q5 X9 e$ \
# F. j1 O8 Z) z! I7 B; p3 D        last_data = last_diff = 0;
. I- ^; b6 H0 e2 |! [
# `! }. s  g5 @        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
% c2 }7 b8 ^" O' h# y
  o& _1 w6 q# c' s; f' j1 ^        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
4 r+ R2 |! e/ k, n# e3 r' i        ZEROMEMORY( &queue, sizeof(queue) );
, s3 ]! [1 q3 X- a6 L0 |        ZEROMEMORY( &exqueue, sizeof(exqueue) );& ^2 N: n2 A7 S9 s. o
$ Z9 K& u- n+ S' Q+ W4 t5 S8 t, ^' _# ~
        for( INT i = 0; i < 16; i++ ) {+ o9 m6 Q' j7 t- @
                m_bMute = TRUE;" I% z. x+ T2 ~
        }
% l+ r8 w2 C. Z1 k9 L% J/ J}
+ t6 b# x* v5 r0 ^6 _3 O  O  A+ E4 l  l
% r4 b* W$ @" X9 FAPU::~APU()
' }7 |* ?/ Z# `; L7 I{
3 p7 f$ X* X# g) {) P4 q% J' V}
. Y3 j4 v* i& P/ z7 i' I4 B& O7 V$ O6 H$ H
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) n! h4 l1 c& U) t! ~{  Z$ D# X. C9 P$ v! d# P6 i/ ?' w) ?
        queue.data[queue.wrptr].time = writetime;
4 P5 j/ X7 s  x# e/ I; F: o$ C        queue.data[queue.wrptr].addr = addr;
, P' c& ]& N6 l8 ~( }0 q        queue.data[queue.wrptr].data = data;
. [9 R1 Q+ v) F6 Q1 j        queue.wrptr++;
& e; \8 ]' e5 H* [* _; I        queue.wrptr&=QUEUE_LENGTH-1;& M3 x0 J7 s8 I
        if( queue.wrptr == queue.rdptr ) {# L: h) C, R1 U1 W" ~6 e0 [5 t
                DEBUGOUT( "queue overflow.\n" );- V4 h) T" [6 v; Q6 s( T
        }5 ^' X0 C' w8 h8 h2 e
}
5 n7 J+ E! b! v6 d) q
% n1 {+ F9 w5 }5 C* hBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
3 E0 P+ u; e; D0 A{
$ x' ]* j5 d# D; O; `- [        if( queue.wrptr == queue.rdptr ) {
0 q; @0 f9 u. Q, O                return        FALSE;! n5 I! R' b6 c% e+ B; L
        }' }: K- p  m1 f. e2 N
        if( queue.data[queue.rdptr].time <= writetime ) {
% A6 i: F8 a/ {1 K/ V4 x                ret = queue.data[queue.rdptr];: r& j0 X* e/ D/ M8 d
                queue.rdptr++;
" L( ]1 L' A3 v& {  O; B  _                queue.rdptr&=QUEUE_LENGTH-1;
4 c! A6 m* R) F; c7 y: P5 y                return        TRUE;8 m' m$ [3 ~* ^, w% E
        }4 a! e/ v8 Q* g1 Y' R; ?
        return        FALSE;6 {9 i7 C2 d" o0 s5 R: B+ _8 s& Y& p
}' x; O% _4 ]' z3 N/ ?
' x* W) C0 e* `( i# @
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  F  w, f; z# q. C. U
{
: ]% O- x1 ^3 o2 A$ z; H: S6 p        exqueue.data[exqueue.wrptr].time = writetime;* ~2 c6 @8 P& c, S2 g. G! @+ O
        exqueue.data[exqueue.wrptr].addr = addr;' {1 _, o: X# ?8 ^/ e
        exqueue.data[exqueue.wrptr].data = data;/ K1 k% g: B0 k
        exqueue.wrptr++;
/ N4 c2 v$ a' n. D# p        exqueue.wrptr&=QUEUE_LENGTH-1;1 a7 o% ~' U( w1 e, X) J3 O8 c- R1 W6 f
        if( exqueue.wrptr == exqueue.rdptr ) {
% V& K( N- [* X$ D4 M1 X                DEBUGOUT( "exqueue overflow.\n" );" m. U' c$ x6 A/ F1 _; ]: o) E
        }
( F$ T# b2 i" j}
& B3 |! J+ L! O: F$ Y( O  K- I8 T6 A- G
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )9 P9 k  \5 _$ J: d1 y! X
{
7 \# f/ J4 r8 |        if( exqueue.wrptr == exqueue.rdptr ) {1 Z( m6 k6 T; A* U8 G/ ~
                return        FALSE;
- j- `2 N% \6 s/ t& R        }
3 {" L: P2 T1 |3 K3 Q& Q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& i: q$ p3 N7 V$ U5 i
                ret = exqueue.data[exqueue.rdptr];. U& {# q3 w8 q: K  A0 Z
                exqueue.rdptr++;4 y  ?, n" F2 q. B' ~! K
                exqueue.rdptr&=QUEUE_LENGTH-1;
: h0 ~$ k' l0 X( b9 ~& d; s. T: _                return        TRUE;, K* Q  P  }8 c: S3 y, y
        }+ E* c: Y0 e5 J8 [
        return        FALSE;# h& q# ~1 c6 `( o2 h9 A! ]: g
}1 {  l1 q8 }* L4 R* p5 R1 ~8 e
% ^5 D- J# b8 |# @2 w9 l
void        APU::QueueClear()
' b$ t+ F- T2 [: i! Q{* X2 k# N- u7 B# W( z- W/ \
        ZEROMEMORY( &queue, sizeof(queue) );
; k: l- I% a3 c" B/ a, W        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: Z+ f- Q( B  E}
$ B: b( v7 E7 J! q
3 c  @" ]; t" c$ I* Dvoid        APU::QueueFlush()
2 U! k% O2 @& g' j6 N{/ F! D1 f. H* m
        while( queue.wrptr != queue.rdptr ) {' P' [& k' M1 k2 b
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
+ L6 e8 N) ?. d) U                queue.rdptr++;
( S. ?0 Z" N% p( {                queue.rdptr&=QUEUE_LENGTH-1;
8 `' P, N* q! v4 l        }. o/ k% F& a. \
$ j; e: v1 U" G
        while( exqueue.wrptr != exqueue.rdptr ) {# R8 @* w! I6 ]- E0 f9 [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: s4 j8 N; E( ?8 @3 i- ]/ F                exqueue.rdptr++;
% _! s% S9 _. O) p                exqueue.rdptr&=QUEUE_LENGTH-1;/ p- h) k4 u# i* m
        }3 b5 v$ t1 @" ^5 H
}
+ e. ?( q; y5 q3 O* ~, G) Q
) r& l  }3 u3 Vvoid        APU::SoundSetup(): V! Y9 c3 X' d
{8 R( L- |, f3 |# ^( }
        FLOAT        fClock = nes->nescfg->CpuClock;
% Z: _1 ~5 x/ i2 q/ ?' m: w        INT        nRate = (INT)Config.sound.nRate;
* M, y4 M: N5 x2 r9 i& Y9 c7 a        internal.Setup( fClock, nRate );
& U+ w! e' P$ h$ s9 e        vrc6.Setup( fClock, nRate );
1 c: d6 p# X( f  O* `        vrc7.Setup( fClock, nRate );
. y' ]7 t$ S7 B! g8 R. w        mmc5.Setup( fClock, nRate );% d# y: e9 J* x1 u2 ~0 s
        fds.Setup ( fClock, nRate );' ^' e: a4 Z; Q8 }
        n106.Setup( fClock, nRate );/ j8 |8 y, C, V9 t* I0 z
        fme7.Setup( fClock, nRate );8 h2 M) E; x8 F! `
}2 u" w% f$ Q4 V$ K7 V( B$ M3 V
' y: {) @) |7 t' ^
void        APU::Reset()
6 Q- S1 c; J, t; N+ F{
% K8 E6 C0 z5 h        ZEROMEMORY( &queue, sizeof(queue) );
8 E( g# f, T9 U3 u: V5 r+ ^  y1 _        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: s- Z4 G! b: q8 y/ Q
( _. r3 b+ T$ E2 b3 d; a# w0 T        elapsed_time = 0;
5 z+ S& i3 ~4 ]: S- e
, P+ S% ^1 F1 m8 |        FLOAT        fClock = nes->nescfg->CpuClock;
0 `# N% _& b5 j. a, O' S9 ~# Z        INT        nRate = (INT)Config.sound.nRate;; [  v% F4 E+ b: ^
        internal.Reset( fClock, nRate );& W6 I; J$ z$ q* F+ Q6 U* V
        vrc6.Reset( fClock, nRate );  j$ C: X" m0 m" F1 B+ Y; _
        vrc7.Reset( fClock, nRate );! c& E) t5 S- V) X& |( t$ k4 `
        mmc5.Reset( fClock, nRate );" {6 F' c$ X- i) W+ `- i
        fds.Reset ( fClock, nRate );
& p% I" E9 x7 `- _        n106.Reset( fClock, nRate );
8 f) F( Y2 m+ b7 `- }% z$ J/ Y, v        fme7.Reset( fClock, nRate );  j8 }  u1 D6 P- f4 s% \4 l& t

$ |: K) t8 a9 s8 y1 P/ a$ k        SoundSetup();
3 s9 O/ q2 [' {  h; G9 ~}$ r- u' i* h& k2 E' n* l& [3 I

& i! g6 Y" c4 V; `0 b+ j7 Tvoid        APU::SelectExSound( BYTE data )0 _" z# J0 `; P5 d, B. q1 i
{: o7 N* `. l. }& k
        exsound_select = data;; K. K; _* u9 {# [1 P% R, B
}
; w& O2 v! [" M2 S: V$ S/ i8 \- [  B
BYTE        APU::Read( WORD addr )
2 E& g6 a3 b5 A3 T! z{
( T( `- n* _- J; `8 m9 O        return        internal.SyncRead( addr );
& @  o5 y8 P% c2 D6 A$ b5 c0 i}
1 C7 d3 Y$ k8 {8 W4 z  y$ i  J# k, a, W
void        APU::Write( WORD addr, BYTE data ): A6 @" N' A: F, D4 ^# ]" Z
{6 n5 X" c, p( g
        // $4018偼VirtuaNES屌桳億乕僩5 n4 H$ {! O, n7 s1 L9 P
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 Q. @3 a" ]; Z3 C( i' n                internal.SyncWrite( addr, data );
+ |) d& |, n9 q9 f( q  @: D                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
+ _6 b' r" a" l; l* I+ X1 w        }5 ~8 s9 l! F: t1 A2 l6 @$ G
}' _4 f. Z" H8 @, S1 z7 H+ h
7 [1 q  U, ]! W3 F6 l- c0 v3 a
BYTE        APU::ExRead( WORD addr )
$ Z7 i" z+ Z/ L0 g9 N; O  M{7 r* x2 z& u  `+ `
BYTE        data = 0;
& W! B& ?% w" @1 I0 B. Y6 _' M( R! e! Q+ D
        if( exsound_select & 0x10 ) {" P. \6 n* I5 U5 D0 \9 Y. H) P
                if( addr == 0x4800 ) {
% Z% x; l7 a/ M1 V' ~                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 u+ Y; i8 n3 q8 S% p- J                }& J$ y6 B. n: M6 L7 `. \
        }& m5 c5 H8 t! x# t, q9 j
        if( exsound_select & 0x04 ) {  e& \/ X9 C& t: |/ s( Z5 R  R$ ]
                if( addr >= 0x4040 && addr < 0x4100 ) {) I3 |$ i! P0 f: y6 S' {
                        data = fds.SyncRead( addr );
% ~* a0 g/ }5 s  V+ S4 |                }/ b8 ~" S6 `; P* n; S
        }1 N: E( u& o- h! Q& i  w
        if( exsound_select & 0x08 ) {
, [" a* L8 `" X& C                if( addr >= 0x5000 && addr <= 0x5015 ) {
" G+ C& o4 u1 `5 a7 @                        data = mmc5.SyncRead( addr );9 h7 y- n  D# @% P( w# V. l# g+ ^
                }
8 a6 k( K; [' p& F2 h) y        }
2 g* V& z; s% Q$ Q
  V3 V; M+ ^& ?        return        data;* v4 _" w" N, I2 h9 v: _/ M* b
}* a# d7 o1 r0 @# c- T! E: T

' z- p& n6 S$ _2 G; ?) bvoid        APU::ExWrite( WORD addr, BYTE data )
- E1 I- @! h5 {( R- ]$ S{$ \5 W2 B) i7 a% Y/ t8 R
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# f& i$ V  T* b  R0 W& [/ ~% t" v$ ]  w+ N4 t
        if( exsound_select & 0x04 ) {
! f, y8 T5 j; r                if( addr >= 0x4040 && addr < 0x4100 ) {
0 e$ o& P. ~; f                        fds.SyncWrite( addr, data );  {4 y" h& v5 ~, m
                }2 ?1 I" r' u3 U! c0 S' ]5 R
        }) f3 E, K6 R" g( g0 C$ w

+ j' U( p/ M1 T" e  J2 H        if( exsound_select & 0x08 ) {1 B$ g2 V4 T, x) `! h- s2 v' m; s
                if( addr >= 0x5000 && addr <= 0x5015 ) {
& @/ X. S" i* H2 Q+ j  j0 T                        mmc5.SyncWrite( addr, data );& A. S* `9 o" h- z
                }0 U1 h' c. Y4 M& D1 L
        }  z: e. y6 \' {, A' t8 y4 X
}
+ i/ H- W1 k% c. R: ^" j5 F2 ~" z. @) k6 a9 m( j. k* [( G
void        APU::Sync()
3 D* D. ?7 E. t$ M, U{
9 c/ t+ Y' M$ p) h3 y4 H+ w}
" i0 [/ E+ a1 A+ M# C
' `, O6 \5 u7 @void        APU::SyncDPCM( INT cycles )2 |$ m: `# }8 U; h# V! f1 L: O4 T
{
; ?1 ]  J1 T. p% \" D& K        internal.Sync( cycles );
( V) `* x9 O- A5 r! k5 H& k$ y% }$ B- w1 |
        if( exsound_select & 0x04 ) {
! |# ~/ \- V' v- `# I# M! u+ o                fds.Sync( cycles );, _, Q( P( K2 \5 h5 @) X) @4 Q
        }. h8 h4 t0 D' C9 ^; x; }( f, C. ?! p
        if( exsound_select & 0x08 ) {' e5 {4 @8 _$ H# g& m: s6 x
                mmc5.Sync( cycles );2 h/ o, I5 P0 d$ c- j9 j  f
        }0 Q6 [9 ], d- H' q/ v
}6 q/ _! z2 Y7 `5 R

6 t8 V$ B7 b1 x0 l' k5 {" ]void        APU::WriteProcess( WORD addr, BYTE data )
1 Z# l. Q6 {! X3 @{$ I9 n; L! s4 E& t
        // $4018偼VirtuaNES屌桳億乕僩7 \' t0 `' a# {0 r( Q1 r
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 y! }& D& a0 |; n7 d                internal.Write( addr, data );1 L! [# O$ e; P
        }
$ A/ b# @2 t, K}1 k: M* F- ?; S6 E) `
' v$ w0 @- m8 T% q
void        APU::WriteExProcess( WORD addr, BYTE data )' A/ Z! g9 R2 s: T4 d
{
3 z+ ]% @$ U7 x8 ?& s        if( exsound_select & 0x01 ) {' ~8 H" g, \# D. Q" p1 s( ?. L% Z
                vrc6.Write( addr, data );
) _9 J+ \; [$ g8 a        }. A  l8 B) ]8 l% G+ }5 a
        if( exsound_select & 0x02 ) {' V8 B* h1 \* ]- i/ h- k# D- F: E
                vrc7.Write( addr, data );
# F( `2 p) b1 q% I- Q        }' V) b, P4 I# i6 y" @/ C; c  V) ^
        if( exsound_select & 0x04 ) {6 ]: b* X1 x5 u" E
                fds.Write( addr, data );
, Y! d6 i; ~# T( [. r        }
  I" E. j+ O+ h        if( exsound_select & 0x08 ) {
; r. `9 h5 b! R! M1 l6 Y7 b- D6 F& S                mmc5.Write( addr, data );: t0 h# e% K1 T% H
        }
1 p7 N, d2 X; y        if( exsound_select & 0x10 ) {2 G  n- w% n- F: L# _
                if( addr == 0x0000 ) {, _% t1 ?" I3 U4 T+ B
                        BYTE        dummy = n106.Read( addr );+ D0 V$ \7 X% v0 t& l) Q$ V. S6 f
                } else {: D) q6 y/ V5 `! p
                        n106.Write( addr, data );1 |6 M( h& u/ ^+ s: s% b4 m) e4 C
                }
+ P: E# J; o- e+ g1 W4 Y# Y        }
& u. C7 J8 i4 ~8 F$ m) D6 p        if( exsound_select & 0x20 ) {* ?, h, M0 E0 X+ a4 a' w
                fme7.Write( addr, data );# @3 A+ v; c: N5 K+ Z
        }8 x% {7 ]6 B5 N4 Q4 t- Y9 \
}
3 f: i( Y* e  c  s! v3 C. H6 a. c0 o4 r- q4 Q! T1 T
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
7 M2 s, Z5 q/ r{& [  S& T# x5 [) t4 Z; k
INT        nBits = Config.sound.nBits;
) a. M8 E8 n" o) v# c( f0 A2 r: i1 cDWORD        dwLength = dwSize / (nBits/8);
( \. A# H" @& r$ ^INT        output;$ I8 c5 E+ D0 z  r/ D! C, X7 U- s
QUEUEDATA q;
/ W4 G% ]& S" v! B( eDWORD        writetime;) D) _0 }' `, B/ A9 O) j  L

  x' C+ Q$ N$ l% }, {LPSHORT        pSoundBuf = m_SoundBuffer;2 R( n7 [) O# S1 u( O: C
INT        nCcount = 0;0 ]0 j4 L1 U, v; d5 Z! D/ r
% S. ?: [4 j' t7 {6 B6 d
INT        nFilterType = Config.sound.nFilterType;' F' e* R, h  W5 {

( d9 M5 _4 u4 |        if( !Config.sound.bEnable ) {& G- F. q4 D% I7 c' ]: N* N
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
0 g5 q. U/ _  d; [8 o                return;; Z5 D: O# }. [6 x
        }  T6 O# Z; y# [& W0 {2 e% p

1 ~& \: Y6 d- r- K# N3 K. l        // Volume setup
) G+ J2 F) [! a7 [& s- Z7 ]        //  0:Master
( }* v5 N* u+ F8 [; ]2 u$ K        //  1:Rectangle 1, a! s# j! h+ I/ Z
        //  2:Rectangle 2
! G9 E+ ~3 D3 d5 j5 f+ m. Z  Z        //  3:Triangle
/ ~7 @8 z7 J5 X8 }" h$ n) j        //  4:Noise2 R* [* U8 p' @* s
        //  5:DPCM
! \2 J; N; J2 {) @2 k        //  6:VRC6, ~4 Z& P6 @  ^. s
        //  7:VRC71 D- w0 u$ O- _+ ]8 o3 v' e$ b
        //  8:FDS2 c+ \% h2 Q( K0 {  q. O
        //  9:MMC5
3 k* `9 v* r" i) M0 O        // 10:N106
' g0 C) }- x. U8 u+ b! U' p- q        // 11:FME7
% u$ c- U  l1 B; p        INT        vol[24];
- h4 E$ Y# `: }" b        BOOL*        bMute = m_bMute;7 z0 }+ @' @6 f+ j( K
        SHORT*        nVolume = Config.sound.nVolume;/ L  v! [6 e% o: u$ L/ f

; ?0 a- O3 ?( w7 |" z/ r6 J        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ g" r9 P! g2 Q; Z
0 {4 q! T; p$ O        // Internal
% B! g) O- P2 r5 M! X        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;7 W6 u# f+ m4 H
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 [; m- g0 D9 R/ S* ^        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
6 F1 Q' y  |, P  a- c4 b        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' S- x* D; F. [( u% z4 `        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
$ M9 m7 t& j2 y: K
+ m) N: ], n+ x; [8 e        // VRC6/ C. A; x4 b. N$ Z% U/ O
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( f( {$ o, G* v8 c% x        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
1 K0 Z0 c6 o; I* t! E        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 l  R$ I) j) X" k6 Q) Z
% _6 e6 N, u5 F# @) s
        // VRC76 X5 A' n$ n1 T( u" p* D- w7 q) ~/ j
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;7 l: M' y( t6 j. s% G6 Y1 i* h, r

: J0 m3 _. O  |$ ~* Z        // FDS
/ q1 [/ ]6 s& L: S: Q) X0 ?% c        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 G9 q0 a5 c1 y5 w: r: E

' Q9 @' U& C7 U5 E, W3 b        // MMC5
% p  k' f5 w5 d! f* \6 B        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 |/ o/ P) W* I5 o# l% s, n( O
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 V/ L/ k7 Z) N, j
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 K1 ^6 `5 q- L- {* D

. o, v* e) J( F! y        // N106
9 G9 Z& T3 |. E' L        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- d/ j( `6 c& R8 A& ^
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" V* I5 H. @7 U8 S% s- C
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& u0 S! W# p* X. K4 L7 ?! w        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% F6 f' y" z. m' i  _        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* ~& \- S2 Q$ P6 n: m        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" I) u: K9 b3 C# W        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 v9 w# Q9 T1 y1 Z  T) b4 k1 w        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- `2 f5 o/ i2 X# q6 K. S: Y! V
1 Z  P. O# ~7 q+ J4 I: j
        // FME7
. F/ [" z+ n3 }8 C) P& z; z6 f: x        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 C6 g0 v+ o3 p% y
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% R3 p) M9 d* l: c: M0 X7 t        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; k5 y- }2 g% @9 k
% i. g& T9 F; ]//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;) Z7 w- E: Y  x: x4 x' E+ O. @& t
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;& m- ^8 |9 }7 N, E- z# X6 x
! d3 E+ `% x% L
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟9 X7 N/ q  W  Z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {! `# ^+ J8 g" S4 N
                QueueFlush();; s, e2 T' E. l, W7 N9 s4 J8 _* r
        }
/ V! z# C9 i* E  N. _  T2 \$ w$ p
        while( dwLength-- ) {* t+ W# \: |2 O9 P# g  b
                writetime = (DWORD)elapsed_time;2 L. e) I- z+ {1 c& {3 j

& x$ L& P8 I7 T3 q  |                while( GetQueue( writetime, q ) ) {
- O+ x: m9 W: e" L$ a                        WriteProcess( q.addr, q.data );; Z/ M6 A& V7 N3 ^% B
                }5 x- V* U3 }0 W3 D% x

1 ]! h  N: k  x7 C9 M) `1 O                while( GetExQueue( writetime, q ) ) {3 E& O. W! c9 N& H3 `0 O% h3 f
                        WriteExProcess( q.addr, q.data );9 A0 ?) K! M0 V/ O
                }
/ i$ u' a% V/ H6 Q7 F
4 B  J" x4 [3 Y, {% {3 e( E                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME71 l6 R) h( B# ?+ r# y: P, _
                output = 0;
( o$ H$ b+ F2 D                output += internal.Process( 0 )*vol[0];
# @9 W$ v  d3 J6 A# W9 Q( s                output += internal.Process( 1 )*vol[1];
% d5 u0 o7 |* e                output += internal.Process( 2 )*vol[2];  {5 {  ~5 c- l* ~' ]
                output += internal.Process( 3 )*vol[3];
2 s9 E" K3 o2 W                output += internal.Process( 4 )*vol[4];
  e+ g) p4 H: ]( e; Z  M; t% m
. S( \, k( P5 q: {! N% o! |                if( exsound_select & 0x01 ) {& T4 s8 e9 f' t4 A/ A- V% p
                        output += vrc6.Process( 0 )*vol[5];
# I4 S0 X  u6 D9 M. [% u                        output += vrc6.Process( 1 )*vol[6];) |. ]  _; I4 P" ~) k
                        output += vrc6.Process( 2 )*vol[7];4 _8 D5 m+ J( Y' g7 W% g
                }
0 I7 \* W" X% [6 a% ?3 i1 l& k                if( exsound_select & 0x02 ) {
& H" j3 ^5 ^1 S: ~: K                        output += vrc7.Process( 0 )*vol[8];, ?" q: h8 s2 A& z7 |& W' I) N
                }! [- H# y$ m# U3 H5 V" b  b- s6 g
                if( exsound_select & 0x04 ) {
7 o- `2 Z: E5 H+ q" X: k                        output += fds.Process( 0 )*vol[9];: k, r0 R- ^. j0 z$ i! S" _$ B
                }
) }; S4 T9 y) c; P$ D                if( exsound_select & 0x08 ) {
& w( F( V7 N/ ^8 i0 o% R                        output += mmc5.Process( 0 )*vol[10];
4 a3 E6 O' \1 T( x$ _& H                        output += mmc5.Process( 1 )*vol[11];
* x. [% ~% [6 C% n7 ~9 Y                        output += mmc5.Process( 2 )*vol[12];4 ]; H( t5 Y# ?% o% k
                }2 u( r8 l* l8 r' T  i
                if( exsound_select & 0x10 ) {
3 m+ z5 p# J- a! ^2 _: d                        output += n106.Process( 0 )*vol[13];
9 v( I0 J, E' g                        output += n106.Process( 1 )*vol[14];! D) L, P7 {+ E- p
                        output += n106.Process( 2 )*vol[15];
& _# A: M! h+ f8 v8 {                        output += n106.Process( 3 )*vol[16];: h! \  Y" }# ?, i! a% s
                        output += n106.Process( 4 )*vol[17];
1 M, C2 H- P7 H- E5 H% F                        output += n106.Process( 5 )*vol[18];
* ]/ Q# U; g9 n: f: a5 t                        output += n106.Process( 6 )*vol[19];
, R: w* P) ~0 d  u/ [# @                        output += n106.Process( 7 )*vol[20];; i0 T6 ~3 g. Z7 f6 k$ q
                }
  W& Z" M: j2 ?/ f3 |                if( exsound_select & 0x20 ) {2 v, J" q6 ?$ @
                        fme7.Process( 3 );        // Envelope & Noise
! y1 E& B; c+ L3 ~9 h                        output += fme7.Process( 0 )*vol[21];
1 h2 \: M& U+ i+ L' W$ l                        output += fme7.Process( 1 )*vol[22];" b7 d+ Y! C$ T( d/ i$ _
                        output += fme7.Process( 2 )*vol[23];% G1 D6 D. v, V$ H
                }
0 M( d! H; F! F0 U) X! {* }6 c. G
+ T) m. I- g* o( J$ Y; H3 ?                output >>= 8;8 r3 `8 V! Y4 U0 _4 j
# @' m6 C  {. g
                if( nFilterType == 1 ) {, P6 Y1 H/ b2 E( [: }( c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& R) n2 ]2 }% a# \( p9 h                        output = (lowpass_filter[0]+output)/2;4 Y7 N. X! ?( z! z! y" u) ~
                        lowpass_filter[0] = output;+ s4 f4 {: f1 l! H  X# S6 B
                } else if( nFilterType == 2 ) {
9 D7 h5 Q! Z9 f7 u                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
& z5 S3 W% \7 w7 ^  X% O! N                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
5 m0 c9 z( L" e. ]. I6 i                        lowpass_filter[1] = lowpass_filter[0];
6 R1 x& \/ h  z' N5 p/ z8 H0 m' N                        lowpass_filter[0] = output;
3 Z7 j; |: z' `* n% Z                } else if( nFilterType == 3 ) {
0 E; I5 ]/ |- T0 K6 b# I' X. B% i5 X                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
1 b8 a3 l  k" k6 S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
+ P: }9 t7 H5 m1 k5 N6 T                        lowpass_filter[2] = lowpass_filter[1];2 C- D. F5 v5 K' U- x$ }8 h! ^/ _
                        lowpass_filter[1] = lowpass_filter[0];; ]6 S( p0 Z" I8 Q
                        lowpass_filter[0] = output;
' V4 ?* B4 C- |5 e" @/ ?                } else if( nFilterType == 4 ) {
& ^! \( _3 M' i8 f2 a                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
- X+ E; M$ P  k- ]* H5 U( L                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  M. b( g/ c9 X
                        lowpass_filter[1] = lowpass_filter[0];$ B, b* m7 I; h, U" O
                        lowpass_filter[0] = output;; u5 |+ G/ c3 A3 L5 ^' E
                }
& z  k! g' u$ q, n2 j% l( u7 Q3 J) Z, \4 W& S9 a# j: k* z8 m- D
#if        0
% L+ j/ C, Q! F. g! R, `5 b                // DC惉暘偺僇僢僩
1 w- R! p/ a/ R) p) Q2 H# r                {# H" e3 R* L, f% t) X% l, H6 x
                static double ave = 0.0, max=0.0, min=0.0;
& O1 e! ^5 t; ^+ I4 k/ l                double delta;
' e  f$ o; ~% E: k: ~% C                delta = (max-min)/32768.0;6 e' [5 f$ ^! q; [. o/ }8 l& y
                max -= delta;; j: K% }" \) R0 F2 E
                min += delta;
3 j. i) j7 s$ L2 D$ k  }7 \/ S) B                if( output > max ) max = output;# P6 T2 H+ C+ g/ G0 I
                if( output < min ) min = output;
* [! ?* f& ?9 e, {$ z5 |                ave -= ave/1024.0;
$ M' z+ `$ C5 _/ t                ave += (max+min)/2048.0;( ~* |4 O  S3 e
                output -= (INT)ave;
2 e% `2 b3 p5 l3 R  e0 C                }
+ U. k' V% A- c9 a4 h7 h7 L9 b#endif1 z; a6 f* u" u; a3 z# n8 i% f
#if        1
# ]. c( M7 K! y9 K7 D% L( p* B1 z                // DC惉暘偺僇僢僩(HPF TEST)
% e, q( D9 Q2 [6 K: }3 P! g                {
- H) Q1 u; X/ p; A. I//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);0 R. {+ j8 X; h7 X  \( [5 b' @9 i% F) }
                static        double        cutofftemp = (2.0*3.141592653579*40.0);4 f9 B8 R$ l- a
                double        cutoff = cutofftemp/(double)Config.sound.nRate;4 ^8 r0 y5 I& c4 ~2 K& f9 U
                static        double        tmp = 0.0;4 ~1 l# ^% e( V; g& ]6 E
                double        in, out;
: D8 M/ C8 z' S, _0 P- W+ K& _! V4 n# n. v7 j
                in = (double)output;
! d/ D, J7 H5 ~1 e                out = (in - tmp);' V8 ~  r" g5 O" v: `0 U# E1 |
                tmp = tmp + cutoff * out;7 b  G  G; m( M4 N+ V1 J" v

1 n, ?+ z. e, `7 w# `( }% Z                output = (INT)out;
9 v# _' H* b$ ~                }& b! m# y- p5 K. t4 T
#endif
5 N8 Z' y+ w# ]. ~2 _- v9 d9 b#if        0
* |3 o1 o  @3 v2 u2 {6 h                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)( Z1 o0 i# l6 W2 {/ H
                {9 M, N( W4 U4 A3 T5 R; M
                INT        diff = abs(output-last_data);
1 S; [  L! I2 F! C4 z  p+ Q                if( diff > 0x4000 ) {' O/ r; q% k* }# J7 R7 \3 Q5 B, u
                        output /= 4;
2 M* V: w3 a' E# z; A                } else / e" \+ q9 V( o. ]. B1 g
                if( diff > 0x3000 ) {
4 y+ f2 R( y( x/ G0 N                        output /= 3;
; h+ G9 @" M0 g- L                } else
  }1 G  B$ B0 z; L1 L0 c0 C                if( diff > 0x2000 ) {& K1 U% z! u2 }0 |6 p1 V# `  q( j% a
                        output /= 2;
/ U: j- ?% k. R0 \4 n9 }, d                }8 p* f( |! S$ G( Y
                last_data = output;
+ e* [' B9 K. X( I$ w                }
# f- P1 j9 g' f% l- z9 V#endif& e: a$ E' v& F/ v$ Y( e* H" X
                // Limit
5 m9 a; E0 \0 I! i7 ^% A7 v" ~- G                if( output > 0x7FFF ) {
/ y- |) _- W, N+ E4 w6 l) J                        output = 0x7FFF;9 I- h( O7 P! b; y- t. c
                } else if( output < -0x8000 ) {" I7 o4 z' F6 K& @9 X
                        output = -0x8000;4 p3 a3 D  {& W( j
                }, A8 {$ x' Q) }/ P4 [

4 y# D& E/ k1 |8 J                if( nBits != 8 ) {3 w5 p9 |$ f; V) ?5 x1 l) ~
                        *(SHORT*)lpBuffer = (SHORT)output;
7 b2 m' u" j3 D9 O9 J                        lpBuffer += sizeof(SHORT);3 U. b$ x5 J( P4 j1 s
                } else {
6 a2 t, U, N3 V  ]. }' f                        *lpBuffer++ = (output>>8)^0x80;4 x% }$ ?, T* w/ H3 j( C. w+ N
                }
% V) q8 ]# X2 ^& d, N! q/ n' j/ j- `# J; K
& u  k; q( w$ n                if( nCcount < 0x0100 )
' `! W) Q) c- H# w; I/ G$ a! J                        pSoundBuf[nCcount++] = (SHORT)output;3 u& Z7 x8 s4 {% E/ p
0 h3 k  B% x* G. ?5 g0 {" ]
//                elapsedtime += cycle_rate;
9 Z$ l3 k6 W% |, B                elapsed_time += cycle_rate;  J" z3 ^7 p) t
        }
& b3 ^9 l# G3 T2 i/ \5 k! s& L
* k/ h8 V( s0 s- t: }' w7 a#if        1$ s# X  w$ m# X" h( O
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {/ a& s# D' A2 V" P& h# L( `1 N
                elapsed_time = nes->cpu->GetTotalCycles();9 Q, P  Z1 V0 X7 f) B
        }
/ B* z  ^: Q, [, U: l/ f        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ I1 l/ i9 i/ _/ w# Y( g" l7 b
                elapsed_time = nes->cpu->GetTotalCycles();0 X7 m) {5 S& d  ?8 j, h
        }
5 E$ d* l8 P2 F; y#else
! Z9 W( h0 k6 C& |0 p) d- I        elapsed_time = nes->cpu->GetTotalCycles();  D/ [! B  G0 y/ H
#endif
/ L" Y, y7 J: {3 {}1 \2 T2 J. p* d* F4 y3 g

7 C5 [9 O4 W8 ]- _, }1 l' k& x// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- r, j0 p. n4 O% D& W  N, P' ~  xINT        APU::GetChannelFrequency( INT no ), O, A3 T* Q- H
{+ f  \6 }/ N, r0 c  a4 ?' }  s$ M: V
        if( !m_bMute[0] )
2 L. q3 h5 j  T: I2 \$ N( k                return        0;' k- K1 j% b$ X7 v1 ^# E$ z6 l

9 c2 p) v0 [& \' e, a- f$ P        // Internal
! C  S  _& E8 [        if( no < 5 ) {: _5 X6 J2 G6 ?
                return        m_bMute[no+1]?internal.GetFreq( no ):0;- t$ w/ h1 V% {2 S9 T4 A: I) h; ^7 j
        }
4 y( v# X5 v& _( R7 J  x* Y% _( r% x. r        // VRC6
5 j9 }9 p) X8 B  e        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {) F6 j. j/ w. c8 O! j
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;  K/ ~; E, `" k* @8 e8 V
        }
; g! n$ s0 m& {, z: X. a        // FDS2 R4 z5 h9 `! {0 Y9 _6 m+ D) T
        if( (exsound_select & 0x04) && no == 0x300 ) {3 l+ L- K$ j7 _: H, a7 @5 G
                return        m_bMute[6]?fds.GetFreq( 0 ):0;( H5 D2 E8 g9 |$ O; s8 w
        }
2 d  h% S4 u% k        // MMC5# m" U' N. ~5 }3 L1 i! |
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
4 H/ n- ?3 Z7 ]9 t! z) Y9 ]                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
2 B, g8 f' y, V0 i        }
6 q8 p1 G( b0 v& I5 W* x        // N106" Y- S0 f3 x5 u, F" V" B
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {, w, H0 A& C5 f* l2 l2 l
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# Q" ?  {; M# ]* B7 v& ~        }) N: i; C. i& p% k% X4 e
        // FME7
/ ^9 p7 `' [  ]1 p+ V& o        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 J' }" h& i' O5 h; L  r( g' S- A                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
9 w, k5 M- y! y* D7 z        }+ U2 I3 T( e2 }% K8 R; I! s- R! H' V
        // VRC7- j. X( n0 L. W3 J6 C0 L( R
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
; P9 i& H4 p8 {) {3 v' V+ j+ A                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
. Y" A5 C) M5 ^- y# z' A0 z% v  h! p+ P        }
) N9 P' g: D, h        return        0;8 R" A5 _0 V' L; ?# t0 W
}# `  ]3 ^7 }* L2 ^0 K

* p  m- p* T8 I% ]3 q7 ~- V+ N// State Save/Load: q6 f1 i4 I: o( ?3 a, ]
void        APU::SaveState( LPBYTE p )! ^2 T" L, J. L" O7 ]) \
{
2 X* W/ ]- s, R7 A- m" ]1 @9 K: u#ifdef        _DEBUG$ e- ?4 ?; \# f+ p7 A# t1 p; q6 t
LPBYTE        pold = p;
7 {( @$ b5 J$ f#endif
: p3 J- n5 ?5 y' Y2 y$ Z! l2 S# Y7 a1 H8 Y' \/ d7 X8 [1 q% P
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞/ W3 O6 k  K! p
        QueueFlush();' i( y1 q( p( D8 g4 ]: b. v! Z- A2 Z
& v' J8 A, h: L# x* U: l( u
        internal.SaveState( p );
" I3 ^% z* c* a  v% ~4 Z0 _; d# E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  K# X* @0 F) Z$ h( }; v
- |' U; Z# O7 A6 G+ @" |
        // VRC6
' n! \6 `8 k8 Z3 Y) {5 ^0 T1 `        if( exsound_select & 0x01 ) {8 U- D& ]" J5 S& F8 N5 @
                vrc6.SaveState( p );
, `  v! g% S; K. P# S: U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: G2 o' ~+ n1 h5 m: t) E0 \# _0 c
        }
# q6 R) _" h5 T7 m3 n        // VRC7 (not support)
4 Y: d* q2 U* o, T. }        if( exsound_select & 0x02 ) {
' p/ s, x7 [2 D1 S0 b: A$ `6 g1 Z                vrc7.SaveState( p );
: C4 B  N8 U8 q* o7 A( S1 t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( `9 O- x/ p: n0 t1 K; a
        }
7 k( B& i, U1 U5 e7 N1 N; F+ ~        // FDS
" r/ Z% q3 w  }& ?* F) q# f: ~        if( exsound_select & 0x04 ) {1 [$ T5 Q& y4 x0 r* M' \* V+ m6 n/ M
                fds.SaveState( p );
/ m: a5 s* v7 h  W; I  e3 d                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 F/ T6 W% I* o9 T# o, \
        }5 h- {2 ~6 n- @1 @& n, R4 l
        // MMC5
1 B: \' i& g  j7 r2 |- K        if( exsound_select & 0x08 ) {
0 z% j8 G, j) r                mmc5.SaveState( p );/ k: E8 E' d% |8 j% W
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
  O# [  \( j/ o# N9 H. [        }
  U& T* l% y$ E        // N106
( H$ h* W2 _/ G' N        if( exsound_select & 0x10 ) {
2 I3 c  G" U( d7 z4 O                n106.SaveState( p );
, d; Q( x1 ~& j: A+ W& r7 A                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 d2 b$ U  ]# W5 i! Y
        }  u1 F2 A3 R1 E, ~; J
        // FME77 U. A% m9 i& t* B8 @+ d8 E8 n
        if( exsound_select & 0x20 ) {, p' E6 B. q( M( T/ w2 x6 D  F, b
                fme7.SaveState( p );$ H0 w+ u- w- B' [  y6 |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: D  I* V' D. Y- K        }
1 z. A4 F: B) K1 a' K- p
0 v; K, p: E! O: C0 g; @4 p#ifdef        _DEBUG4 G+ f  Z. `) H
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ J0 g& L# B- F$ f1 C#endif" _2 F: l6 g0 k/ w/ X' g
}$ {5 h, p' Y8 g* H& E3 i
! {8 g( b- L3 U; |
void        APU::LoadState( LPBYTE p )
* }$ e$ n1 J4 n& H{' i7 e' z5 w# A, M
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡# J' Z9 p4 q" H9 y; n# M* y* @2 m. z
        QueueClear();; y: D) `9 t; e; R; X( C
( n. G% ?1 Y& t" _" F8 r+ Y
        internal.LoadState( p );) F7 y) J/ `6 [5 Q2 B; \
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding0 R" B+ n7 f* T! E

; Q% l$ J4 ^6 v' G/ P; A" o        // VRC6! c, R# x1 `: v3 @; R
        if( exsound_select & 0x01 ) {
3 C+ ^( T% J! E7 t. Q' B  P                vrc6.LoadState( p );
" Q1 c& B$ g+ i. E* c( _( s                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: i5 l% V# M! u/ V
        }
2 z# }6 j1 [% ^( E! B        // VRC7 (not support)1 x2 t1 D6 m' S# o4 K& d
        if( exsound_select & 0x02 ) {5 I, G# w6 P) s
                vrc7.LoadState( p );5 p' I! ?9 [, O8 a0 j
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' J& a; c8 J, h$ v- {        }2 Q: {& M1 e1 t# x
        // FDS
8 l1 ?$ Y& @5 P- v7 V# H        if( exsound_select & 0x04 ) {
" r- P- n4 D2 x5 z                fds.LoadState( p );2 \( Z, A' U% r$ q( [' k
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: O% @2 K2 J- g, ~
        }
! I; s9 z: `0 l7 o; z+ F$ x) ~$ q        // MMC5" m1 w1 ?. X- ^; Q5 F  R3 N7 `7 n
        if( exsound_select & 0x08 ) {
, `9 Y0 _& ^+ X7 H! {: z4 k                mmc5.LoadState( p );# d5 u/ a* ~3 `2 O# m
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ i1 W9 }7 `% o! k' S        }
3 Z+ w# I) Z/ }  e" C        // N106
0 B. V% R/ v7 @+ I0 v9 s8 {        if( exsound_select & 0x10 ) {
6 }. K; r. L1 C# Z( Q4 k                n106.LoadState( p );
4 D7 `# z9 K" h" m! u# h  C7 N                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
! q9 V  H' V, ~; r8 T$ ]6 |, {& b1 d        }* j. D9 T+ J1 F6 F
        // FME7
, @% u" g% h7 \" H2 H/ M& P# j' P        if( exsound_select & 0x20 ) {
$ S! M8 ?- H  v2 ^6 b( v                fme7.LoadState( p );
" `  [  L0 F8 H5 t* j                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 X. {5 u* S7 C) U
        }
- O; b, z; u7 s$ s3 ]) s}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % c- R$ d/ R/ k6 z8 A+ ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& R6 R5 t: y) c( o  d6 H感激不尽~~

0 X5 D  u8 r* G; Z& Y恩 我對模擬器不是很有研究,9 t! |- ^" T9 |4 m
雖然要了解源碼內容,可能不是很困難,4 Z' G; E1 u- {: R8 Z5 P, o. ~
不過還是要花時間,個人目前蠻忙碌的。% o2 N1 j3 D  a2 j

+ z4 m9 G: v* F8 P  S給你一個朋友的MSN,你可以跟他討論看看,
# L) v" P  g4 O! m8 Z$ M  U! }5 X他本身是程式設計師,也對FC模擬器很有興趣。0 x- o" V; \( v  P; q0 W) P; T4 R
- P6 N) @" Y4 F: r
MSN我就PM到你的信箱了。
# n" V# P; X+ O6 o' Y3 y* U4 X- {8 i( _$ t) @
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
' C6 j) v1 F; V- J  L0 L呵…… 谢过团长大人~~

0 P; i8 f: V1 Q9 S8 G6 {5 G% r4 O: Z: b, q' \: g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + F2 Y% k/ k$ V& b% t
团长的朋友都是神,那团长就是神的boss。

6 C" P) z: W$ _/ Q6 l  [哈 不敢當,我只是個平凡人,
6 B. ~* _7 h: `. O4 @* e要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙+ W( w7 x7 ?% O+ R9 Y4 i' x3 n
ZYH. V  N6 D# n" i( G  i* Q4 ?. O
QQ:414734306
0 D+ ]6 d( v: Q- M5 `, DMail:zyh-01@126.com; V# X( X) X$ n3 a

, ^( c6 t% Y2 G, L, S他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 3 p% H0 s# Z" ^5 c1 t
再次对团长大人和悠悠哥的无私帮助表示感谢~~
- k- N/ A( I: m5 r* b
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-4 16:21 , Processed in 1.118164 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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