EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
" l3 L, b% V5 Z! D  c, C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; q& B& g6 u" [% ]: }+ E: r
这里有相应的模拟器源码,就当送给大侠了~~1 t* n8 L. |' r. o
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 9 w8 x; J# U9 n5 Y9 t
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 {5 ?, i. ?0 v& l  b) }楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~6 @# h9 {. s9 d# p7 t# Y+ O3 }+ e
这里有相应的模拟器源码,就当送给大侠 ...
+ x/ h# h+ f" l, b2 j1 o
聲音部分(Audoi Process Unit = APU):  r6 N: w0 h. R: V1 k
.\NES\APU.cpp: R+ ?$ X0 j1 G! D: u4 \2 ?
.\NES\APU.h
9 h# L* ?8 r/ K: E8 j, A, x  }% G( p, l/ ^+ W
4 j4 e1 N) f9 [; a* v$ j& F: s2 _
影像處理部份(Picture Processing Unit = PPU):9 h# ~: Q+ D  i
.\NES\PPU.cpp! s- \7 _' l+ r2 W, K* f  }4 o5 }
.\NES\PPU.h9 ~, L+ C, U8 e) O) [4 l
6 e/ F; X! o6 K7 O$ ]  ]% O1 R" V
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
4 K$ W1 H7 S+ ~" z5 Y' B) ]" }; q感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
) M7 v* J& t6 A% @(由于很多专用术语和算法机理都不明白,所以看不大懂……)
. t7 `( P7 S& p, z7 m* W$ Z9 |6 v1 l//////////////////////////////////////////////////////////////////////////* U& z& u; l' D$ J% g' i
//                                                                      //
2 M5 n: D; J0 |0 I* ~+ T//      NES APU core                                                    //" a& y! `/ m. c& s' E
//                                                           Norix      //
4 r/ S# S  y% d& p- y0 {% [2 t//                                               written     2002/06/27 //- H: U) ~  l2 z7 Z3 s1 U
//                                               last modify ----/--/-- //) j  m, V+ R) g$ i8 t$ J! F
//////////////////////////////////////////////////////////////////////////
) [) G! j- l: I: l" U: Q8 y#include "DebugOut.h", t7 y, w, ^) z& ^0 d% B
#include "App.h"
! {/ r6 S* }1 g: M1 q#include "Config.h"6 }8 b. Z8 B: M1 Y, W# t/ ]
! t' @6 q* n  x4 V! I" J
#include "nes.h"2 X6 I2 T* ]+ g
#include "mmu.h"
( s7 Y- p% n& u" Z& x#include "cpu.h"
1 |) U' {! `, \! m#include "ppu.h"* B; i; J" `2 f$ L+ U) }
#include "rom.h"
- R* q6 o) `# ^: d#include "apu.h"' C* q6 k( e8 F/ t, w4 a2 \7 o

/ J9 C7 Y: j! E- k// Volume adjust: \" {' t: Q0 s% P
// Internal sounds  P" u# C: M$ z. k9 X  h) I, n( a
#define        RECTANGLE_VOL        (0x0F0)3 J, [! D2 Z* l8 e8 a" A
#define        TRIANGLE_VOL        (0x130)
# N! s4 z4 L) j$ L% W9 S. R#define        NOISE_VOL        (0x0C0)
. s) \! k) e3 {7 R0 X  [0 n#define        DPCM_VOL        (0x0F0)
- C! D" s7 U. l5 }5 c& }' ]: ~: _// Extra sounds
* l( T! T. [) M' D#define        VRC6_VOL        (0x0F0)3 q% \# {- P" s7 s
#define        VRC7_VOL        (0x130); a8 k9 v/ p9 `" F# f
#define        FDS_VOL                (0x0F0)) o" \1 [/ ^& P2 N
#define        MMC5_VOL        (0x0F0)1 s, C( q8 V& v8 s
#define        N106_VOL        (0x088)
, K" d# ~: f/ B" G7 d5 h3 H9 E#define        FME7_VOL        (0x130)
1 J2 r1 E( G# Q2 e2 J" }
/ \& {6 n/ B+ p; r( bAPU::APU( NES* parent )4 }8 P$ ^/ u' e% v( Q0 R
{3 ?& K* u/ j- g& D* a
        exsound_select = 0;/ K* ~) A; }" F( j: }
8 l& D; ]( Y6 n
        nes = parent;
4 h& a1 x4 W& i( D0 j+ W- Z        internal.SetParent( parent );- p  B, e3 P  `/ f
* L+ u1 `4 z  @. Y3 S
        last_data = last_diff = 0;
; y$ V. a& T7 f9 y) P: v6 ^. ]" U' s7 Z4 x2 k
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 r& a1 Z4 J. X6 Y/ G
2 G4 f6 T3 _( z! K3 n$ ?$ N        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );! i1 B2 g' k" p" y5 N8 E
        ZEROMEMORY( &queue, sizeof(queue) );- g4 N5 w. M5 @3 G+ Y" x1 J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ p+ z, S, j8 b. J% c: F4 M8 D2 w7 [  [8 [& B% i
        for( INT i = 0; i < 16; i++ ) {
& E# u0 c/ [5 B! s' Q                m_bMute = TRUE;
: v8 z. X5 N) J# k  x        }
* F* M2 X( e$ s1 \2 Q}/ Y2 d9 F" M$ i# c, e# v9 a$ `
0 d: Z; s. U6 [" s) j4 P
APU::~APU()
; O3 O3 u5 ^8 {: c: D, T4 ~- P{
6 o) b! ?% E: P) P3 p7 d}: o  K! W- E& j- s: ?1 u

, {2 P4 T- b8 B& _7 ]void        APU::SetQueue( INT writetime, WORD addr, BYTE data )& V  Z9 C- M4 P
{/ g# z% g7 w3 A) ?3 l* f
        queue.data[queue.wrptr].time = writetime;
, D# m, t+ G0 P$ \5 w! X% p+ _0 E        queue.data[queue.wrptr].addr = addr;1 C) t8 \+ E1 m0 Q+ [+ Y
        queue.data[queue.wrptr].data = data;, Y* N, Y1 J& n1 J% H- p
        queue.wrptr++;* O$ q2 X% _4 P& W5 m/ R
        queue.wrptr&=QUEUE_LENGTH-1;
0 B# U! p7 I  l        if( queue.wrptr == queue.rdptr ) {5 q. z- Q  t8 V3 Z
                DEBUGOUT( "queue overflow.\n" );
- H5 e0 _: t' X; R- |        }
7 O. l! _8 l1 o- R" h' d}
6 c3 `& N$ z' J9 t8 y% u1 ]& u# g
# F7 ?& H2 C9 @4 }* T0 W! z# oBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
1 s: M1 ^4 ^9 Z) s1 t{
; M5 |: _; E$ D8 K        if( queue.wrptr == queue.rdptr ) {( b3 |/ W1 l$ A) \& V& [
                return        FALSE;$ }2 O' t, ]0 o# h) s. Y
        }& I* J# P# W: e5 O
        if( queue.data[queue.rdptr].time <= writetime ) {. J1 i; ~; F' l2 i
                ret = queue.data[queue.rdptr];" P. O3 t( }2 q% P1 {: J' H1 @
                queue.rdptr++;
! W, B$ h0 m( R) f- c6 ]7 A                queue.rdptr&=QUEUE_LENGTH-1;1 O" h: R" A0 }# y0 X' g" ?# C
                return        TRUE;
4 M. g! Y$ y1 w  N4 Q+ g        }0 Z6 J. T9 T' X& j/ \) F
        return        FALSE;
" Q  t6 D2 \* M3 S  B  G3 g, C! f}$ E9 @6 w2 M& v8 l% j; I

3 w- P2 I2 E8 d/ e0 gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )& {+ `/ \1 \: H' }0 M9 J  D
{# w4 I$ x, |$ }! W/ u! L
        exqueue.data[exqueue.wrptr].time = writetime;& D2 U6 w/ F, K
        exqueue.data[exqueue.wrptr].addr = addr;% c, X% _$ N8 ~7 G
        exqueue.data[exqueue.wrptr].data = data;! H# W9 G$ q9 b
        exqueue.wrptr++;
1 u( `% H1 L0 k" r6 j" x1 V        exqueue.wrptr&=QUEUE_LENGTH-1;
$ j: G5 T& d( T/ o3 ?) i        if( exqueue.wrptr == exqueue.rdptr ) {1 }3 X9 b' N% u! e
                DEBUGOUT( "exqueue overflow.\n" );/ w5 f, r$ b" e! C  `
        }
- ~. U8 V$ d# U* ~! }2 s0 @- {}
5 M- r+ @4 A" X( x& r$ s) f; a' w
. j- n/ X& l; J1 F: B  y" S6 iBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 b& R+ }2 q. U# B) p  J2 M{
2 L# ?" P/ C) \* W5 J        if( exqueue.wrptr == exqueue.rdptr ) {
' T4 O5 h1 k5 ?1 K3 @                return        FALSE;
6 ?) x# D, {  F" J+ \+ C        }: W/ h' ?) O( g2 R- d
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {/ H  f7 A" S0 M. ]9 v
                ret = exqueue.data[exqueue.rdptr];3 ~4 _% R/ F8 B, E! v, o! S
                exqueue.rdptr++;( X" B+ `. a2 [* M7 T
                exqueue.rdptr&=QUEUE_LENGTH-1;
4 f. D8 }( I! z: l8 e8 h% [* o! t; F                return        TRUE;# K+ A0 o: {$ c1 H
        }
+ r& q% R5 Z- D, S        return        FALSE;% n6 S& U& |" _" b% t8 o
}
( }6 p8 I8 \- [1 d
$ W2 _4 ?. m/ c1 ^void        APU::QueueClear()3 y! x# ]# w3 x& F2 w. @# T, M, h+ d
{. Y# y* i( F4 A; b5 T) N" K
        ZEROMEMORY( &queue, sizeof(queue) );8 e- j- F$ z2 c8 o3 B, ^3 ]8 t$ Q( V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 ^- E+ |+ C$ j" b! b}+ t; q7 w* u! W5 F, N8 A
! E& K, f% N/ }1 m6 |+ l% T3 V
void        APU::QueueFlush()
+ H0 u5 }" q* ^" B) H{; Q& H0 z# Y6 K3 d; z
        while( queue.wrptr != queue.rdptr ) {
; [& t; c, Q, b% A( T                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ g& Z, l  {( X7 ~7 a& a' J- h
                queue.rdptr++;
  D. {, O* o7 |  |4 t                queue.rdptr&=QUEUE_LENGTH-1;5 ~/ K& d8 I9 b9 l1 ^7 `
        }6 N: A) @% e% V. I( \' s- S1 `
/ M  u) P6 f: f, }8 W* R; _6 P
        while( exqueue.wrptr != exqueue.rdptr ) {
% I1 z, b( `; K4 k, u% ?                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 x; }) f; @4 k' W
                exqueue.rdptr++;
6 v  P+ @. R4 i9 v4 g0 z+ L6 K$ k                exqueue.rdptr&=QUEUE_LENGTH-1;: O  T5 I( L: {# b) K2 h: v. l
        }
3 t  F' T4 u" \  ~}; }( k" ^; N: b, e
6 E. c$ {5 p' T. H& O' h1 }6 W5 V
void        APU::SoundSetup()
9 q: K4 O+ V; J! Z( P) F" W{, L) }# z6 t4 g( Y9 ?! ?
        FLOAT        fClock = nes->nescfg->CpuClock;
9 q% F: |; h/ C3 e; a8 G" x$ S        INT        nRate = (INT)Config.sound.nRate;
0 }7 p$ Y. Y- y; r# m        internal.Setup( fClock, nRate );
/ ^4 d/ A# B7 L: E4 k! c* J        vrc6.Setup( fClock, nRate );
8 \/ Y4 ]. b! r# ?  N. C; D2 [) I        vrc7.Setup( fClock, nRate );7 Y4 Z5 o4 m! M3 Z/ L" f2 K
        mmc5.Setup( fClock, nRate );
( t$ o, z/ W3 G3 e9 Y  q        fds.Setup ( fClock, nRate );
9 ^  ^% w8 f* @        n106.Setup( fClock, nRate );
$ S. F# i% W4 B5 a& k+ F7 H        fme7.Setup( fClock, nRate );
/ i! s# O9 j$ \, ^2 H/ [}: v$ \- }% L5 |" J
% n. f4 E0 V) m+ x/ P
void        APU::Reset()* y- ]5 J$ d/ C' e, M" ]& t
{. }& c! K5 T2 c
        ZEROMEMORY( &queue, sizeof(queue) );
9 P5 U# e. i, M0 L6 X        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 Z6 j  \6 ~# c  ~* z! }
% l: X: o5 F0 g+ C. W0 E% D        elapsed_time = 0;
& P$ b: o8 g4 s2 m0 w, W; m' \6 O- X4 u  C3 ^( @* b- h
        FLOAT        fClock = nes->nescfg->CpuClock;
! g% |  f# Q7 p4 n( |  F0 h4 O        INT        nRate = (INT)Config.sound.nRate;9 @$ r0 q2 ^9 ?% f  l
        internal.Reset( fClock, nRate );
* o. p* ~1 ~% Q6 L& I$ Z8 s        vrc6.Reset( fClock, nRate );
5 P5 k% E8 K/ O        vrc7.Reset( fClock, nRate );
0 [# |) N4 v& ?6 H- h# F" c        mmc5.Reset( fClock, nRate );4 g* P: C2 D) g; u- B+ @
        fds.Reset ( fClock, nRate );
$ H& d, W' z$ O, s3 p        n106.Reset( fClock, nRate );4 O3 H0 q6 x# n$ ]1 ]
        fme7.Reset( fClock, nRate );: [7 V8 }9 A4 J6 _" }/ i6 b
6 c, h# F0 a/ X1 L5 u4 ?* ^1 X! \
        SoundSetup();7 {8 B* k6 e6 C( f
}) ^& f- T7 X2 W% O# I
2 p7 G% u# C' C7 f& _# D
void        APU::SelectExSound( BYTE data )/ S/ x5 t6 k2 I5 P. E
{
  e% q) Z: ~6 Y4 _        exsound_select = data;* v% a5 T( v- y& m& Y
}
' Y$ P8 B4 |# l( s6 A
  B+ c* z& s$ G- a$ P5 xBYTE        APU::Read( WORD addr )
; ?: S6 H7 i) K. P# f; j6 ^{; o% G& Y# c7 l$ \( {& L& A& V* n
        return        internal.SyncRead( addr );. v, c9 s+ `/ X5 C/ q* g
}+ w5 @5 \) X" Q

$ q  A9 z) P6 Q: {, f5 I+ pvoid        APU::Write( WORD addr, BYTE data )% Z5 x$ T( _. N1 `8 H# y5 u
{2 G- A# d5 T# a" A( l
        // $4018偼VirtuaNES屌桳億乕僩- P  c0 k' L7 z) o/ T& S) S* O8 c4 ~
        if( addr >= 0x4000 && addr <= 0x401F ) {
" B! T: I0 @# }* O+ ?! S                internal.SyncWrite( addr, data );
! q/ H3 B  B# D9 Q9 {& A$ a4 K                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 X0 {: j% ~8 i5 D+ D6 \        }3 h, d# N9 K% L( v8 B
}
/ S( H) M- f1 E: t; i+ s1 j' q
( T" _5 ^7 t+ v$ |8 {BYTE        APU::ExRead( WORD addr )$ g; m; P- n! c
{
+ w" I( _( v: f( g) YBYTE        data = 0;7 d" b; U& k( I
( p2 Q7 {: Y4 z
        if( exsound_select & 0x10 ) {
7 D" g' E* r- [! Q& U2 [                if( addr == 0x4800 ) {2 H7 U, I/ b3 x. p
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );" F6 N$ T5 W% ]2 k
                }( ^( T% q3 n- z$ a
        }. g5 S; \% p6 F  O4 T$ ]' i8 d% R/ \
        if( exsound_select & 0x04 ) {
7 u2 ^; ~9 z! g: X3 }7 S, l                if( addr >= 0x4040 && addr < 0x4100 ) {
+ Q* s8 O/ r. |0 _  h( e                        data = fds.SyncRead( addr );; _* [1 l- g$ n% @. u- ]/ n
                }
0 z  f- D6 H3 u! @( o        }2 ]# X# w3 ~$ Q" u
        if( exsound_select & 0x08 ) {
2 j; Z6 ]! q) F5 h                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 o3 t0 d$ k: O! t* R* z4 N2 `9 W/ ?                        data = mmc5.SyncRead( addr );
) J# x. \3 t' h  Y" b                }+ {4 ?8 [) r8 c) R
        }
! t% S0 V+ |( A: e9 |+ S/ B/ H8 _/ `+ B; q7 W
        return        data;
+ D9 h) d6 T0 r# D6 y* W}
- h# s5 X' \& [5 ~3 m' D/ o% n+ P" N: R4 @# U& h- P
void        APU::ExWrite( WORD addr, BYTE data )( ^- s( E7 z# o# M% ]
{
( Y0 f$ T" \  }        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
. y# w5 M- @' \& T
) u+ k% V2 P0 p% A8 I; r8 T: d        if( exsound_select & 0x04 ) {
. \7 _* l3 O. j                if( addr >= 0x4040 && addr < 0x4100 ) {
: V3 y) h4 m2 K, c) e: a) @                        fds.SyncWrite( addr, data );
1 T/ V# L1 A4 R( c! r" U                }5 x7 J* H0 s7 [1 |9 l$ [/ W2 Q
        }
6 u2 r# ?$ N) q  O
1 k! r; x) O; A5 j4 g        if( exsound_select & 0x08 ) {
. Q% |+ `( b; F- U                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ \1 o& V& z/ Z1 i4 S, Q                        mmc5.SyncWrite( addr, data );
( b$ j; X6 W: @/ y& d, k                }
1 Z2 s5 j+ T* {& Q* X# l        }
, v9 p9 R4 J0 @2 w+ z4 r5 q}4 @0 ]* ?. L' c/ ]+ a+ o- B

" U3 c! [" ?- Ivoid        APU::Sync()
) e7 e* i5 O$ q4 R: B* K+ X{+ w* D3 V4 F. ~; r
}  I* r3 R0 L/ {; J' Y1 q
2 p2 C- ?8 P' Q- T- x2 l. H
void        APU::SyncDPCM( INT cycles )
$ ^, T/ k4 g- G6 z8 |; M: K( O, |{/ q- q; k5 j3 B/ s
        internal.Sync( cycles );
, K" l, ~7 p- k
4 x" {8 J$ `! p5 W' ~8 p        if( exsound_select & 0x04 ) {2 x4 `" t$ k; |0 }$ A
                fds.Sync( cycles );3 k: v. G# [; K: j# N4 U6 z
        }4 V" j$ ?2 K/ c. P, Q5 O& o4 \
        if( exsound_select & 0x08 ) {( t9 |( {  s8 {3 B2 L" b, E
                mmc5.Sync( cycles );4 _& I- q$ U4 S5 I5 G7 ?
        }4 B% B8 s$ n2 W
}
' N9 {% K# O# X5 f/ W
5 S$ Q4 j9 H- Z1 Vvoid        APU::WriteProcess( WORD addr, BYTE data )
- t! [6 Z, L$ M8 M* R- |% v{
& `3 J) f. {' T        // $4018偼VirtuaNES屌桳億乕僩( k" _# @- N# N8 S% n! K
        if( addr >= 0x4000 && addr <= 0x401F ) {% S2 y& T" Z, U: \+ n
                internal.Write( addr, data );8 {% p  O9 @3 C) m
        }
4 _1 f: Q; ^2 w6 l, o; r/ ~6 r}4 f3 s; ?6 T8 {$ C* w$ L
6 q1 s' b4 B) W  l4 M- o) k! m" C
void        APU::WriteExProcess( WORD addr, BYTE data ): j+ e( n! ?. l" d7 K) M; Z* B
{( k* _, U1 P1 F3 z! `$ w, I/ r' z
        if( exsound_select & 0x01 ) {% E4 Y" f( M" C4 n8 u% q
                vrc6.Write( addr, data );
" S- V0 T. @% H# u        }! K: T$ k9 R' u& m
        if( exsound_select & 0x02 ) {; {/ t/ u- t% i
                vrc7.Write( addr, data );2 X' p# S# i8 T& h
        }" @: k  h+ w1 v& `, P
        if( exsound_select & 0x04 ) {
' R! u- ^  G" V7 I; w6 q6 B                fds.Write( addr, data );- Z$ x6 t4 v* |" g. |
        }. h' [5 ~' v9 v3 y0 ]: U
        if( exsound_select & 0x08 ) {
$ _, x- _8 [& Q0 ^9 I                mmc5.Write( addr, data );
- v+ S* G  `: t3 S        }+ Z$ z1 C6 P* [6 e* J
        if( exsound_select & 0x10 ) {
5 N! \9 a( d; [/ Z                if( addr == 0x0000 ) {
1 w( o6 O; C6 a                        BYTE        dummy = n106.Read( addr );
6 m3 v7 g5 P! W" S                } else {
6 V  G. w0 y( G) E! J! r; J                        n106.Write( addr, data );
  E6 n" o8 \1 F: p- `8 w, A                }
( C  W" ?3 L9 K0 Q# R        }
. `% U. V7 l2 _6 Q        if( exsound_select & 0x20 ) {
' W" c1 m  M! ^* B9 b" r                fme7.Write( addr, data );8 f' Z; ^6 I6 Y5 J$ |
        }: H# g  m. T# t$ r' |' X
}
) f# u* U; O6 d; G1 G6 n3 d+ ^& a( C, z% {1 a7 X
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )- f5 {$ C2 J  G
{1 }/ q. B- c" X3 F, \, |+ Z7 X
INT        nBits = Config.sound.nBits;, p, H, ~' Z& O4 p. H
DWORD        dwLength = dwSize / (nBits/8);- w- T( o6 N' |" K0 G( h  z
INT        output;7 l' O: D; ^* J
QUEUEDATA q;' j9 f5 [4 p" {; `
DWORD        writetime;8 `# w9 W7 s& N1 U0 H

* b+ ?$ Z/ h! @* D7 ]6 j, L) cLPSHORT        pSoundBuf = m_SoundBuffer;3 |1 V0 B0 I! H" n' V2 f* U' L
INT        nCcount = 0;
/ l) J  Q, E: z; W9 k, m8 q4 j
6 ]4 e4 I( D: O7 e* Y" x0 RINT        nFilterType = Config.sound.nFilterType;
" H+ `! U4 \- e$ f5 L+ K# v
2 r$ {# Q) N; G7 _  I/ [" ~        if( !Config.sound.bEnable ) {+ F* W+ y- F9 |" T8 m7 s0 K" F+ r
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
8 b  z7 i& d1 M( c                return;
  w" }$ Y% V! a! `$ @/ H) y1 }        }
2 k: k* Y" R) F6 Q3 F
" e" V9 K: M- M3 l6 w' R3 V8 P        // Volume setup4 H9 U# R4 z; h9 V
        //  0:Master! P7 s0 _5 z' |5 T% w
        //  1:Rectangle 1  U# k3 S+ _5 \- _* B  s0 m. m
        //  2:Rectangle 2
' g6 g$ m; y4 g; a* p; _        //  3:Triangle" e9 O6 t2 Q( I) L
        //  4:Noise
: j, L! ^7 w+ x5 v  Z; X" Z7 M        //  5:DPCM' c" h+ e6 {# g+ A( J
        //  6:VRC6
: g6 e& y( ?: G        //  7:VRC70 {* ]1 B/ z7 ^) k3 U8 a
        //  8:FDS& w. ]0 P% I; c, M6 y
        //  9:MMC5& f$ c4 m+ N+ j
        // 10:N106
. [) l/ j% H" j* h& {6 Q        // 11:FME72 |9 ^# y% D- C, }  i
        INT        vol[24];
. u  g3 s& ]; C+ z2 n9 @        BOOL*        bMute = m_bMute;( c" B* J! ^; y0 u3 ]4 W
        SHORT*        nVolume = Config.sound.nVolume;, [& Z; \! q. J- s

2 K1 b& j  w! r        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
9 l( @& C+ I1 _0 l) T0 o- f$ M: q( x% q1 \
        // Internal
4 h+ [* u6 `* n/ q- o        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
" A7 T; r  @; y- f# N3 C        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' l0 J1 R1 e3 T$ X# x& u& [        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;  Y. B2 U* }5 v9 W9 u  P$ m
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 u$ f, Q/ Z' t  _& v  E- _6 j3 i        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) A5 h  e/ r. J$ C' H
% X' T" ]8 v1 O' C+ j1 [        // VRC6
( W$ s# Y/ [7 `& [- q6 e4 v# L        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% Y3 T, L2 Y# t: P2 e. U        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! I: F& G, G6 o: ^  h0 F9 r0 Y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ y3 `2 C6 B* u5 J
. k  O0 z# @% B
        // VRC74 f+ R9 M) s8 p; y* M9 c
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;7 {3 H  t0 U! D, G+ z0 O8 G
9 }$ {4 Y( F  O3 M2 M
        // FDS+ A* |9 C- w1 |0 |
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;2 ~( b( m2 W, _( S
# }0 }' C+ _4 ^* K) |
        // MMC52 {( F: R) [# N5 @6 j
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- y; I" Y' V7 y" T6 K        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 r* i$ Q1 I# K/ m, z" l6 s+ S  ~
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  W( L) v0 k! y) O" V+ P( Z
! k) U, Q( {' P! R  U
        // N106
) _' C; A# s1 r/ I, ^' P1 [6 E        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% k0 N( I# A4 P" N8 R0 f7 t: d. _        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. D6 B( |8 ]' k) Z2 K3 F
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 d3 A0 |$ Q, a) r' r* `4 P
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 x! s, _" e3 }' I: e6 _+ K        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ T; T- d0 S( L" [* A2 \4 V        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 r2 R* G- A3 r; H. [' {' m        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 t$ J0 R5 O. u. O        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' j. G6 z5 @' Z4 q7 [& P
% y7 Y2 g2 E; O+ K& \# b& ~        // FME7
+ S$ v" e0 o" m0 ?2 J        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ \: |# V% g$ ^9 y# Y2 D) E8 @
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. c: T# ]! W6 Y( C- e$ P0 U- m# d        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, U: G/ j  V: }. C- ~! F) ~6 K
2 z" x0 t* L/ v% f3 L8 B//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 C1 V4 |' m6 X6 _  _& h8 d9 T
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 c& I: H9 U, N9 ], M  ~3 \) K1 e
; Q4 m4 c/ d8 M+ o" V3 H% l        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟  D/ W; w; z, p  x) Y4 l9 z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {/ w( K+ _) D' g8 x- w
                QueueFlush();
' I! k- j# i9 M9 Z( T        }4 a% s, T8 W3 Z
$ s' y9 u& C5 }% ?
        while( dwLength-- ) {
2 X8 n0 ]; \3 U+ W/ B6 K& l8 R' L                writetime = (DWORD)elapsed_time;
: r& Q" G" p" E0 K! ^/ l; i* C# I6 y5 P' O
                while( GetQueue( writetime, q ) ) {
7 b1 v; y3 k$ W  A6 {                        WriteProcess( q.addr, q.data );- y: a( |& C) e2 P" y
                }/ a: t! n7 `/ d2 t8 Z& G: b+ }

1 @! |( h  R5 p, X6 C9 P6 D, ]1 x                while( GetExQueue( writetime, q ) ) {
- V, Q0 U% A5 Y7 F- R                        WriteExProcess( q.addr, q.data );
) z1 S; h6 @# W+ O! z' N3 B                }+ G* F$ O3 G4 o

# S. t" O3 W! u+ ^$ |3 h                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
) |% ?% d7 e- X7 X5 D% k                output = 0;% p% _- Y& K4 r. j9 _1 x
                output += internal.Process( 0 )*vol[0];% D, s( X( a: p+ I6 K9 e
                output += internal.Process( 1 )*vol[1];7 I# ^. S6 n& M2 M% U
                output += internal.Process( 2 )*vol[2];5 p2 y+ V+ n5 T- Q' d) j
                output += internal.Process( 3 )*vol[3];( j' F4 y5 J6 n2 N9 D0 R! y
                output += internal.Process( 4 )*vol[4];, f5 d  u* S# m8 n* c! w  Z* k

& ^% S: U- ?, p4 F; M4 |                if( exsound_select & 0x01 ) {
, R6 b9 J& h2 f                        output += vrc6.Process( 0 )*vol[5];
# v5 v( H& }8 v% O                        output += vrc6.Process( 1 )*vol[6];/ a; ?. _2 C+ w: b. B7 @# d; a
                        output += vrc6.Process( 2 )*vol[7];2 ^2 V  c3 ]; F
                }
. I2 n/ C9 k4 \  q                if( exsound_select & 0x02 ) {6 w3 Y- J% I- J6 O$ M8 x, z
                        output += vrc7.Process( 0 )*vol[8];2 C: j& F! I# k; n! H! K$ t- P
                }/ s* U7 v) j1 f$ O
                if( exsound_select & 0x04 ) {* s. j1 E: X) U/ E( U. N$ `7 f) l
                        output += fds.Process( 0 )*vol[9];; B) _! [! I' n5 @/ e
                }2 c, ^& H8 r% X. r! K9 I& B( b' C
                if( exsound_select & 0x08 ) {5 }" Z1 R% R* F
                        output += mmc5.Process( 0 )*vol[10];
) N2 ~9 W9 x. k7 I/ C                        output += mmc5.Process( 1 )*vol[11];
( |  r( r( H) W% v7 p% e: e8 l                        output += mmc5.Process( 2 )*vol[12];
9 A  e" V# _5 S' M                }1 H2 ~$ U, m# R
                if( exsound_select & 0x10 ) {
, V* T1 I) {) |* [                        output += n106.Process( 0 )*vol[13];0 o5 K1 x, R" T1 ^$ l: ?
                        output += n106.Process( 1 )*vol[14];; Q; ~; g: S) ^& G$ j
                        output += n106.Process( 2 )*vol[15];0 K4 X  j6 r& I8 O6 K2 Z! r/ s
                        output += n106.Process( 3 )*vol[16];
6 P9 j$ ^& l& T4 r7 @2 R                        output += n106.Process( 4 )*vol[17];
3 }5 E8 `, Y& s) E" ^                        output += n106.Process( 5 )*vol[18];4 N; h5 b8 {9 p2 ~3 s
                        output += n106.Process( 6 )*vol[19];+ o3 c6 ~4 ]0 y2 J) v4 C
                        output += n106.Process( 7 )*vol[20];
, Y# P# K" m4 h/ k                }
( B) ^7 q/ P* f) L3 F1 o                if( exsound_select & 0x20 ) {5 |+ x7 l1 @0 k$ I
                        fme7.Process( 3 );        // Envelope & Noise
7 u+ u1 V. ?9 q                        output += fme7.Process( 0 )*vol[21];
( `' h3 x/ `* w( p                        output += fme7.Process( 1 )*vol[22];
% V6 l, r+ P5 {6 B7 I                        output += fme7.Process( 2 )*vol[23];
$ X) S1 s* h. g/ E0 U8 [1 Y                }
; p! t3 v, Z# i  m/ e1 O: F2 d& U# W  Q7 U0 J" x! d3 W/ ]* R0 H
                output >>= 8;
9 f2 b4 [! k4 _$ R* P: U; ]! D1 U( P  I" r
                if( nFilterType == 1 ) {! V. f9 V5 U3 Y3 x& C0 V5 Y' H% I
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)5 p" A' u9 `2 o
                        output = (lowpass_filter[0]+output)/2;
9 ^. {6 {& F* j$ {6 d3 ]                        lowpass_filter[0] = output;$ H( F5 P( [1 @
                } else if( nFilterType == 2 ) {9 G4 z7 j8 c; t- I$ f, W# d2 p: K7 z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)# l$ z6 ]' B/ i% X. L! w; b
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;! b5 X8 i4 i/ [7 ^
                        lowpass_filter[1] = lowpass_filter[0];
2 j, c8 _- V0 K5 x2 ?  Z1 W& m: ~                        lowpass_filter[0] = output;) k& w" i3 w8 v2 N; H5 |
                } else if( nFilterType == 3 ) {
2 R' G4 J) [- I0 d& x5 X                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)/ l$ c5 q7 E! Z) p) f
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;4 a  ~; r) c4 t' i$ `
                        lowpass_filter[2] = lowpass_filter[1];
- `. R0 i4 C+ K5 \- e' K0 G                        lowpass_filter[1] = lowpass_filter[0];) N8 h9 k' T8 H# z, ]' y
                        lowpass_filter[0] = output;# C/ O* l. F" H% \
                } else if( nFilterType == 4 ) {' s, q: t% z2 S. O7 X1 {
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
; H3 u9 d0 ~+ t                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;/ i8 M) A2 c& H7 u  `
                        lowpass_filter[1] = lowpass_filter[0];" K0 [% l# V! p, P+ o7 L
                        lowpass_filter[0] = output;9 ^: Z: \0 ?8 n  I
                }4 k7 ]8 J4 e1 M: W7 Q8 l

8 }2 A6 S; B6 X" e. q#if        0
7 i$ i) x& S/ M                // DC惉暘偺僇僢僩5 D+ p# T5 v/ p& m! E
                {8 R) W) p8 n: I, ]: g; ?( P
                static double ave = 0.0, max=0.0, min=0.0;3 e5 ~1 |/ R- F% k) U, W
                double delta;7 h" c5 r/ J5 [! ?9 J! X3 h, r
                delta = (max-min)/32768.0;
) @: ~" I% f6 C& t( R1 M                max -= delta;
0 n# I" E2 Z6 q: l1 B* R" \* |4 }                min += delta;
& S+ C& @/ u" T$ A. k; q4 \                if( output > max ) max = output;
; P1 G; {# d* Q1 a5 `+ x                if( output < min ) min = output;6 v. L( x1 ^" l% T; v8 @
                ave -= ave/1024.0;
, i+ r, B: ?1 j, [/ ~$ q0 r                ave += (max+min)/2048.0;9 G! `3 L9 j3 ?/ h
                output -= (INT)ave;
! a, l8 c! t  y0 g% t                }+ I5 R& w' F: {9 g) ]  J$ I( L
#endif' o* z; }8 a5 S
#if        1
9 L; Y  z6 }4 K) ?0 H                // DC惉暘偺僇僢僩(HPF TEST)/ J3 y' C) f* R
                {
3 w6 K5 E$ W% X* g: `- e  ]//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);; p" _! Y% o0 q% C7 Z( U. y$ r9 z% V
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  f3 N/ n7 x, [                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 v/ {* n0 v, Z) u8 P
                static        double        tmp = 0.0;
9 ^( Z0 w1 P2 T- b0 l                double        in, out;3 _/ z# N3 n$ L& r- \
% Y6 j6 P- b. R) x* F: h
                in = (double)output;
0 Q7 p# }. V# j                out = (in - tmp);
2 A+ m' f& n8 d0 Y( X- @9 G& r                tmp = tmp + cutoff * out;
8 o0 ^4 ~, ~! R$ F: ^+ |
0 `! ^& l4 u8 m4 {& n# I                output = (INT)out;" e6 M" V2 k$ B9 z
                }1 n, \5 K7 ~1 u5 r- ?
#endif( o) \. x$ A# r) {# {" D: O4 V/ J
#if        0
( r+ W0 ]( Q* N2 `* ?" F                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* u, a: F( {# F- D5 T$ G" k                {4 ~" l& \. t4 m' I. |8 Y1 x! c
                INT        diff = abs(output-last_data);
7 V) ?8 B& d% l' ~) j9 o                if( diff > 0x4000 ) {
# }( a/ _! u" B/ K7 a# f6 Y                        output /= 4;
% a" }7 ~7 b9 r  B" r5 I                } else 5 A# ?6 m/ D3 V; o
                if( diff > 0x3000 ) {* o0 E- e/ s& V; J! y6 r1 S
                        output /= 3;0 W! g1 w) f# r3 o8 S! [! O1 p) q2 C
                } else
; k; B1 K: ?6 {, n9 u; L. t                if( diff > 0x2000 ) {/ m/ I. r5 u5 h1 f8 A
                        output /= 2;
" I( h1 B' m  k) J+ |                }8 O4 ?% ^" ~$ l& K" |6 L; N7 l5 \
                last_data = output;' K9 F4 {1 i3 c+ C3 }4 G
                }3 e+ m& X5 K5 X" d# u2 Z* j* W3 S
#endif
# v3 g. m& }$ y8 n' X                // Limit! `1 o/ `5 ]1 R  l# h
                if( output > 0x7FFF ) {0 Y# b  A3 v6 r% `; h( y5 T
                        output = 0x7FFF;  \  ]2 a1 A$ g. {- V' Q0 f: K' x" v
                } else if( output < -0x8000 ) {
# m- _; ^. ^% J                        output = -0x8000;+ Z6 \# q& Q3 R
                }, p! ^4 r% O- Z% z3 u

! w  p9 F. t. `9 {/ J4 d8 I/ m                if( nBits != 8 ) {
- i+ \( ]/ _( N5 K# P4 g7 C                        *(SHORT*)lpBuffer = (SHORT)output;6 a1 V0 C6 a+ _# L" s- ]# u" k
                        lpBuffer += sizeof(SHORT);
' G& o' A5 S+ F: K/ k* C5 }                } else {
, X( m: s1 W0 @  K7 _9 }, Y                        *lpBuffer++ = (output>>8)^0x80;
" Y+ o! j, |4 g$ H! i+ j                }1 M& L) g, y0 k: a

4 u: @# Y" {- V; ~. Z, {                if( nCcount < 0x0100 )
: A& F* i9 v; J, e& N" t                        pSoundBuf[nCcount++] = (SHORT)output;0 x9 ?; t0 Z5 g- k' Q( j
) s3 I1 |4 y! R, C! I; M, ?# X
//                elapsedtime += cycle_rate;: G" k$ W3 g" D0 T% ~! Z6 |$ b
                elapsed_time += cycle_rate;
* U; C4 f' Q7 U; q& _: I! I) u! a        }
: }" {0 D% x' p1 @9 M% `) D% H
/ T8 _1 s% y; |$ K( Y) S. N#if        1
6 J$ [8 P# y) ^- e% |! r        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 y( G0 K' P/ _: t+ \                elapsed_time = nes->cpu->GetTotalCycles();
3 F0 {/ S8 O9 {+ V. v. D7 ~6 G        }
8 v5 f$ ~; [3 j. Q9 U6 v        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
% x% D* ^) U6 ~( p* Y, ]) ]                elapsed_time = nes->cpu->GetTotalCycles();
$ f$ ^: W* X2 ^% j8 s        }
7 ]3 C5 \0 c8 `8 \! q; E0 C#else
6 ~4 J! G) ?8 L8 W: r, p        elapsed_time = nes->cpu->GetTotalCycles();
6 `/ \/ N8 q0 ]! o5 L#endif3 @" T  ^# o; G' E' n2 w, Y
}
$ g8 |: F. n8 ]- @1 m, w7 n$ O. ?$ _3 D+ u- r$ y
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. @/ E" M' n9 I/ ~8 cINT        APU::GetChannelFrequency( INT no )/ @- `* `, k) k. G2 S% i
{
; y: n0 I# ~, L5 x2 |; a+ k1 n        if( !m_bMute[0] )" D8 R8 h5 J5 V( l
                return        0;) j- z" Z( \2 L
2 B5 ]6 ~; r: i) q& i' i
        // Internal
6 ?+ e3 T1 y" m6 u  h1 O        if( no < 5 ) {
& k. s3 `1 N5 v; X* j' g4 z                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( q1 y+ {; |" B: k        }. J4 B1 g9 A4 g9 u, a0 U
        // VRC6
$ d- {8 t3 Q4 |9 C0 x        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 _  d! t% K) _
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
7 r  l: e5 x; U% K' ~, c        }$ X7 a4 q5 z* g0 c0 H# m( R
        // FDS
- G1 E( g- u) v7 o6 @. {6 y, U        if( (exsound_select & 0x04) && no == 0x300 ) {
( m- S3 R. f6 E; P& `6 M! s2 i                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% S% {0 \0 ^& O0 {! C% i* Y2 ]        }' ?) a" o" A3 g7 H: s
        // MMC5! p( S  c2 b6 F5 }% V
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
& ^1 g# a' |' t; v0 Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
& }9 r- \1 O! B# t& t        }
0 Y# F7 q" E0 C6 }        // N106
+ d# x6 R# {: |% k        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: P1 X3 _4 Y1 a% y
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" e& N8 L# k* V* }3 j* Y        }
: E% E# s0 ?& _        // FME7! i3 l+ F/ ?1 ~/ f- D' |
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" i9 u0 B  ?4 B: S$ U( A                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;* c2 l) r$ q8 g) t3 M; [4 ^( K  X
        }  Q, i/ x* J' q6 M: ]
        // VRC7  w. S; F# s  N% [, G
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! p$ i' `0 `' T
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
! t; y+ P4 P- s9 V% B0 }        }" r; y7 x0 k3 ?$ i- f( f6 b
        return        0;
1 A' C/ [  s0 i# o7 \5 X. C2 N5 [4 k}
( g0 A/ M3 ]5 ~2 Y0 @3 v
) ~/ @7 J" M! j. ]// State Save/Load& s5 \0 ~5 [) T, M# F
void        APU::SaveState( LPBYTE p )
, G8 q( o; {0 R{
1 r; B7 y# t0 k) W8 L, m" U4 h7 l: e#ifdef        _DEBUG
3 _; r6 }* Z" W+ H7 D( V( KLPBYTE        pold = p;
! W5 H, @* `  _% q# |: u' `! B! k#endif
$ p. }: a, i' e# G$ D. `7 x& B5 N! p& ^1 a+ |* X: R9 \2 p
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
" B4 F+ z2 o1 Y& v8 x3 u! e+ K        QueueFlush();8 i& f1 @" g1 u: `) W5 X& i; l

6 b7 X) z$ M; n" Z6 w  r. U        internal.SaveState( p );' v, c, u/ d+ ~8 A
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 M! G7 i9 f3 z& [& x0 o
4 `7 I3 Y# c) m
        // VRC64 Y& U8 X, X3 x, f' w' @$ k$ R3 Z, U9 g
        if( exsound_select & 0x01 ) {- k9 r6 L* [8 @8 Z+ F% U9 S
                vrc6.SaveState( p );
0 o4 z9 A3 p1 `0 N# R5 y$ F( o  w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, z' g2 X% s8 N( I        }8 U# e& ?: q* r% x. k
        // VRC7 (not support)
; B- c3 T- q& x- g& W0 ~7 }+ L        if( exsound_select & 0x02 ) {
0 u& I( B! o: _9 ]; S6 S" Q                vrc7.SaveState( p );
! g* K8 e  [/ _" H- T5 d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ L2 L8 S( m. [1 O1 ~, F        }/ f. D9 T7 Z3 N" I' F) k9 R2 a
        // FDS* L" R, _5 A" ?3 [
        if( exsound_select & 0x04 ) {2 d5 m7 M- v  Z4 w3 F1 X) J
                fds.SaveState( p );
5 m1 m3 Q8 s4 ]8 N+ I: |/ n                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! f1 }, a1 n% w9 n
        }* a1 v1 Z5 l* j% D
        // MMC5
) X5 O+ w: l  c3 ?+ v        if( exsound_select & 0x08 ) {, y: G+ W0 i; ]7 Z8 t" L
                mmc5.SaveState( p );* `$ W7 I7 B$ a2 K9 ~
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( X% W( v* N$ l. U  ~$ [
        }3 [) X7 z4 q- |6 d3 E
        // N106
/ p7 v0 h% e- a7 a* x- r        if( exsound_select & 0x10 ) {
, N5 }" F8 I* c% n4 _                n106.SaveState( p );- J) I  t0 g; a( P# q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 X0 A3 N3 M+ s8 m        }, b- w& D" b+ l! Y/ R$ y
        // FME7
& b0 f, ^1 E; u7 }  }) C, n        if( exsound_select & 0x20 ) {
& ?1 I5 [/ k( K                fme7.SaveState( p );6 A  ~2 a9 f- k# s1 t% U
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 P: l1 \% r0 t7 {  i        }8 g, z$ @+ k, @: k

3 N6 {# l. p) o#ifdef        _DEBUG
; a$ ~4 m+ x- |8 J+ ODEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );3 X" B  F/ u" H, S8 |  o& f
#endif; ?4 K  k" o; _
}4 I* V1 g5 }6 u5 o9 O6 m- A

% [7 Y8 ]8 ?/ s3 S  s% _void        APU::LoadState( LPBYTE p )9 T( x. S% Q7 r( @$ {) d0 l- L
{
! r& h! D; g9 }4 j        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% M# R$ g( i: S! n2 B+ ~6 y        QueueClear();  M2 p6 ]2 Y( ?* q; j

$ Z/ A, I* c. m/ x9 ], R        internal.LoadState( p );
0 U5 M& X; j# i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; L: z; }1 L* {9 a5 d0 C
0 K7 L+ J! y4 ~1 o" U7 `" o& \
        // VRC6
7 \7 C6 j5 m  i5 _$ i$ D        if( exsound_select & 0x01 ) {1 s' ~! i8 A, O7 d) a+ S2 Q7 \
                vrc6.LoadState( p );
- q# M4 A- t! L2 Q                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ p& l, N& ~1 i7 `8 v
        }
# _7 [1 ]$ T) r& h( Y        // VRC7 (not support)
" B4 v: Q3 S1 A" H        if( exsound_select & 0x02 ) {
$ E' |: r$ A5 z; I5 e7 R) |  Q5 j                vrc7.LoadState( p );
3 I% A% B! `  E0 y1 u6 l+ P* l                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 S/ |) l. F3 J& i% Y9 N        }
3 `2 q: u4 {) f; D6 \        // FDS
( v  {, _" f* c5 F3 w        if( exsound_select & 0x04 ) {
% [' m  h6 D7 p2 z8 F+ c                fds.LoadState( p );
- g, |+ v7 o1 i% S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- z5 }+ Y6 Z; D( m        }' y, G& ]& ]! F% @1 V5 u
        // MMC5; p  F2 m3 v9 N% e. R
        if( exsound_select & 0x08 ) {. G4 g. ]( f- P0 z1 A2 Q
                mmc5.LoadState( p );
$ P) F" @( a8 b/ M+ C) I0 S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding0 A9 @# p2 h% r1 j3 o2 ~
        }
: Q; f3 i  |; u+ [3 S* u6 a        // N106
' u2 I- E7 Y' s5 b& u1 v        if( exsound_select & 0x10 ) {
! Q2 l# Y! d! y. Z' U                n106.LoadState( p );
9 ]5 E3 h. w  t' @7 |+ R                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 e" V: g  C$ F" Y4 }- \! s/ g
        }, K$ K  n) b5 e$ }  ?0 \! e
        // FME7
" e0 ^# B# E$ A        if( exsound_select & 0x20 ) {" P; M2 d6 o9 }" e8 b5 q1 h$ D
                fme7.LoadState( p );
3 p1 E- }! Q6 d8 P  [8 W                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- o6 h( t; M; V6 t4 a: o
        }( L- |& i5 G7 n! |, z* a$ g
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 . G1 p: ]+ q$ {+ A" x$ K+ s
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。% W  }8 l$ O9 ?& J: [/ J
感激不尽~~

- C# {. y" ^  D) c/ V# L  G/ S恩 我對模擬器不是很有研究,' d" M7 |: s4 @8 \! b3 l
雖然要了解源碼內容,可能不是很困難,% o4 z; I1 N# j
不過還是要花時間,個人目前蠻忙碌的。
' O& C9 H. Q/ ]% S1 t2 d$ a$ [2 G1 c
給你一個朋友的MSN,你可以跟他討論看看,# k9 S) b6 I- Z% N
他本身是程式設計師,也對FC模擬器很有興趣。
0 L, w' z8 D( f. d. `0 i# Y
, V' U6 t5 E8 Q, A( G: zMSN我就PM到你的信箱了。( u; I) W& D4 k- S9 b# x5 x

! ^0 y9 I4 r1 X希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
( e& k$ A2 m+ n# G3 x/ v/ L% E% d呵…… 谢过团长大人~~

* r+ @1 \# V6 A- x3 b- }; H: p
% T# t( c3 a2 y8 t4 t. d9 M哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
7 y8 f" J8 J' k- I1 g6 n: S6 _团长的朋友都是神,那团长就是神的boss。

" i9 O3 O( G: G5 \哈 不敢當,我只是個平凡人,) l* v) V( P% e0 l7 X
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& g! H0 ^: Z( B7 n! y
ZYH+ Z$ C. C0 a$ o( e9 T7 U
QQ:414734306
" S- X9 W" e) w0 G# x4 ]7 b# XMail:zyh-01@126.com% V- p7 j. @7 G! Y$ K/ l' }

2 k. x! i! F; ~他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
; S6 {0 c& ^" b* R7 m& @' D再次对团长大人和悠悠哥的无私帮助表示感谢~~
9 g7 {) J1 L- P0 N0 ?5 j, H2 {7 c& }
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-7-6 10:46 , Processed in 1.069336 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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