EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?# i7 P3 S/ c& ^0 E# ]3 ~! C; w
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* M# z, S/ S3 n- ~/ |1 \楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( B2 u" c, [% f/ @' C  V
这里有相应的模拟器源码,就当送给大侠了~~
7 `! P4 y9 \. p! [$ G% ?http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 \! B* A& d! h. K$ E9 G5 k能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* B& ]0 \' r. ]楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" o2 Y1 P% P2 {6 E$ \) S5 y' G
这里有相应的模拟器源码,就当送给大侠 ...

" G; m( s2 z; Q聲音部分(Audoi Process Unit = APU):
8 t, A/ D5 s. s5 J+ |. k, m  h.\NES\APU.cpp: N, u) ~! Q5 b! f
.\NES\APU.h% L: T& f- m+ f: v

: L0 N1 `$ m7 N- H5 M  q5 z5 U( g. W) ?" k& q
影像處理部份(Picture Processing Unit = PPU):* S; W2 {) b# H% i% y9 O
.\NES\PPU.cpp" v+ _( X3 |* d. G: j+ ~) v
.\NES\PPU.h
% X% |% u3 ~& r  `6 @0 E( D$ a
) F. D$ E" Q3 F& S; s9 z: _0 e5 M- |* L如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
0 l$ q2 {+ D, `! r; R7 w! E(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 h) ]5 J( Q% x% m4 p  E. n
//////////////////////////////////////////////////////////////////////////4 n+ v4 u( A' f& w
//                                                                      //) i% f* l/ F6 H: v
//      NES APU core                                                    //
2 O+ C" H8 G5 z: N* A3 H+ T//                                                           Norix      //- \6 n9 C1 g* d
//                                               written     2002/06/27 //
. J! C$ V  j9 p$ a% A//                                               last modify ----/--/-- //
. [/ L$ Y8 g4 }3 q6 J) J6 ?( x//////////////////////////////////////////////////////////////////////////
; z/ [$ A5 {, e' u#include "DebugOut.h"! b+ ~; c  J" G- i
#include "App.h"! i5 R) \8 {; ~$ U( m' n4 H
#include "Config.h"& n. H" {* F4 w/ W5 h+ u

* t/ R" c( w) x) T: h# r#include "nes.h") s, |0 Q! Z" u7 a- y
#include "mmu.h"* Z. y5 C  f* c5 S
#include "cpu.h"
% [3 A9 I; v+ h: ~#include "ppu.h"
& l* E7 ?1 k& L, @7 v#include "rom.h"
' n$ i$ X! n# l4 O#include "apu.h"
7 a7 W4 ~) d0 P6 R! L& q# S. ^: q% Y5 ]& K' m/ f
// Volume adjust
# f" b1 u" w& [7 O& z+ j// Internal sounds5 d$ z6 u* q7 s) F; F5 y# v6 w
#define        RECTANGLE_VOL        (0x0F0)
& l+ p# U+ J& h- e#define        TRIANGLE_VOL        (0x130)* h5 u, Z8 b; W" D2 `
#define        NOISE_VOL        (0x0C0)
8 K" r7 t: P. H9 Q# {$ l$ p#define        DPCM_VOL        (0x0F0)4 H$ @* R" `; E
// Extra sounds
4 i# i9 k" |- Z4 R1 m% m, [#define        VRC6_VOL        (0x0F0)/ m8 j/ U- O. v3 ]0 S4 i" |) W
#define        VRC7_VOL        (0x130)
6 I  r0 L* @+ D! g#define        FDS_VOL                (0x0F0)
  T9 v* j7 T8 j1 F5 n+ N" I$ l#define        MMC5_VOL        (0x0F0)
1 t) t& [8 v2 G#define        N106_VOL        (0x088)
; V1 ?& u% P8 r#define        FME7_VOL        (0x130), n. ?. l. t8 S  Q4 \: [
7 j  Z6 Y  z$ d
APU::APU( NES* parent )
) o$ _& w; m* t8 r+ E% |{
, x3 u/ X+ p, p2 {% j        exsound_select = 0;
( v; _/ N7 U, k! V, S% h& }4 n4 S1 g. x; }# g0 g5 @$ C
        nes = parent;
0 S( v& G& X. ~( X9 `5 R4 x+ |        internal.SetParent( parent );% T; J% g  f, I! v% M* i5 a

% E& H; t1 y( S+ {        last_data = last_diff = 0;
4 s! ?8 @# p" C6 ?2 V* D( |& \9 N7 }2 T$ N% v* a
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );" }' F& p4 Q* S: R

$ D: r: u! {- e2 p& O) l1 x        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );9 O) q; r: f8 m9 m
        ZEROMEMORY( &queue, sizeof(queue) );
% e: u. v6 ~- O        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ u0 v; B. c0 c2 m% {- O
/ ^' u/ u/ o+ B) \3 U) V4 X% H        for( INT i = 0; i < 16; i++ ) {! _: q0 ^  T. c
                m_bMute = TRUE;
6 v! U( _5 Z, M" F6 f        }
4 B0 [4 V$ N$ L% \}) y/ V) b% Y1 ]" }$ q
$ d% ~" M+ p1 w4 v$ A' M1 G
APU::~APU()
7 g$ o' `9 i8 g/ z% h3 b! G{) t9 s- I5 Y3 d9 u( K! x, T
}
$ y" w5 N- D% Y0 z! n. B2 O1 v0 W0 f$ i6 u0 e
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )/ w9 d- \/ y9 }
{) x0 [3 Q5 K0 S* ~. [0 n5 ?
        queue.data[queue.wrptr].time = writetime;: I* I  m6 C2 Z1 `
        queue.data[queue.wrptr].addr = addr;9 Y; B' _) l2 o' q# M/ D; y
        queue.data[queue.wrptr].data = data;1 G7 g; @# w5 {# M( U' W6 F
        queue.wrptr++;
8 p7 t0 H, R4 _! B        queue.wrptr&=QUEUE_LENGTH-1;
. {( X  x# A. u0 q  B! e        if( queue.wrptr == queue.rdptr ) {" e9 k4 z+ t! U. C: f5 h
                DEBUGOUT( "queue overflow.\n" );  {( i3 K9 G) B5 w. `! y
        }+ _+ ?  k6 ?) y3 K5 ?) s( f2 b
}
7 W5 I  U0 g# D' b: a/ H: k( J/ Z0 k; g* R4 Y# ~
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ): [! b* S3 ]5 t& _% u3 Q* }7 S
{1 u, P; @, s# x
        if( queue.wrptr == queue.rdptr ) {
/ o6 g& r; L8 ]& t3 I                return        FALSE;# J" y- A. h4 @
        }6 F( p$ Y' v$ O1 E$ C( X8 C/ a* B; @
        if( queue.data[queue.rdptr].time <= writetime ) {: N$ i# k- f7 }/ \6 Q
                ret = queue.data[queue.rdptr];
8 z0 ]9 S. S; }; i$ [                queue.rdptr++;& u  w" G5 w5 m
                queue.rdptr&=QUEUE_LENGTH-1;
/ N4 R9 |8 y8 s* p; Q. t: ~* J                return        TRUE;9 I# w, H1 i- d; ^; o4 o( Q6 m
        }% I+ n2 S; m( l
        return        FALSE;  G$ f8 k. S5 K. b) Q9 r, V5 K: Y
}
$ I$ E* ]/ X2 s; |, h1 l$ P' U) k4 O' X: O3 X) A
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )9 l2 W- b9 Q' R$ E8 G
{6 ~0 D# M$ W' K4 }4 w  X3 e& P
        exqueue.data[exqueue.wrptr].time = writetime;
4 i0 p: w) {. X; {7 _: n        exqueue.data[exqueue.wrptr].addr = addr;8 `2 Y; M# v% E& O
        exqueue.data[exqueue.wrptr].data = data;
0 d! ?; \: F9 T# i        exqueue.wrptr++;" P( X1 v  c% `
        exqueue.wrptr&=QUEUE_LENGTH-1;0 G4 a; u* s4 w/ t( j
        if( exqueue.wrptr == exqueue.rdptr ) {
' D/ J2 H' ]. {# b* D9 T# `' T                DEBUGOUT( "exqueue overflow.\n" );
7 ^0 v- r- N1 i6 G  D2 D        }3 k" n7 x2 ^) i& ~/ X4 x) M
}
  \' p- G; @8 L) [# y7 r
; o6 K5 J! K. l* m/ W. Q" mBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )+ x1 H! _' A+ |
{1 N% q8 C3 ^: T5 p
        if( exqueue.wrptr == exqueue.rdptr ) {" K5 g, n0 X; a/ o
                return        FALSE;
  J- _9 t; K$ \% x' b7 i        }
- o6 ]+ d4 C7 k3 T7 A- S        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* c$ I' H+ B' @( N8 C
                ret = exqueue.data[exqueue.rdptr];+ ], V& j3 {4 n; S
                exqueue.rdptr++;
( \( P) ^/ m/ A- n; ?+ `/ K                exqueue.rdptr&=QUEUE_LENGTH-1;
+ H/ M  F" K" @7 t: G* j4 p                return        TRUE;
- {8 Q; u0 r# s: |: T$ N        }5 x; l1 N0 @+ Z; A) O
        return        FALSE;
# l6 \/ ~3 K' B  W}; `+ o' Y2 W' ?

7 R  N  W% g+ L* ]7 n: ]void        APU::QueueClear()
5 b5 s* Q0 B+ v% _- [{
- q& p' p+ [1 y( l2 n+ [2 x) q        ZEROMEMORY( &queue, sizeof(queue) );9 g- n) e! J. U1 r3 F
        ZEROMEMORY( &exqueue, sizeof(exqueue) );' R4 K) K8 D6 G' U- M6 r& j8 J- U
}0 s$ X) K: w* O) ?( z

+ ^' h* r: s4 g( C5 u9 I) Hvoid        APU::QueueFlush()
8 I" R% m9 L" e! v; n# n{, v/ A0 O, z" D6 L4 r! a: Y
        while( queue.wrptr != queue.rdptr ) {
4 v: H# M5 n$ q" N                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );( `; B' L: E/ H5 c3 p% x! J
                queue.rdptr++;
' g! o4 W6 C! q. y1 A6 {  W                queue.rdptr&=QUEUE_LENGTH-1;0 s) f4 g4 Z$ v
        }
. Q: w8 W" M; I6 Q, T1 k
% U0 W. A, o% H        while( exqueue.wrptr != exqueue.rdptr ) {1 M2 h! N9 ~% M& I: v5 W
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );# d  j. u: S  u! D+ ?" K0 W5 v
                exqueue.rdptr++;5 }( K, `+ Q9 b- ]" L6 Q
                exqueue.rdptr&=QUEUE_LENGTH-1;
, t. S' v3 u, g  Y/ p" D2 B        }
( |/ T: w" o7 a- o' I' |) z}" _1 r0 x' ]) K9 j
! S& P7 W& _# v) B5 J
void        APU::SoundSetup()
# R* `2 ?. n8 m3 X- ?$ u  p{9 h0 ^3 h( a7 U, S& y. ]& y
        FLOAT        fClock = nes->nescfg->CpuClock;+ M/ K( N; z, O; E& l
        INT        nRate = (INT)Config.sound.nRate;
& k0 f' A$ f1 B- ~: S8 s; b        internal.Setup( fClock, nRate );  h! e. _# v7 T1 |) q5 E
        vrc6.Setup( fClock, nRate );( c% ^9 b$ R  ?( w1 [5 w! E
        vrc7.Setup( fClock, nRate );- P- w6 p5 ?% F5 s' p0 \1 y& W' U
        mmc5.Setup( fClock, nRate );
2 v: ~# N- {3 I5 R- O3 K  X        fds.Setup ( fClock, nRate );( |& d3 p- G3 Y. m, T/ ?- P
        n106.Setup( fClock, nRate );
. q, x' Q( z5 o- Q' G2 N4 L. p        fme7.Setup( fClock, nRate );+ W2 o) i" D- ~4 q% a, Y
}
0 w) R& a3 a4 h/ s2 e) Q/ g+ h* K: n! j
void        APU::Reset(). R2 K  x- B3 M) _$ \1 W' g- v
{: H! N' q. a, ?3 Y+ [( ]
        ZEROMEMORY( &queue, sizeof(queue) );
5 T* @3 l6 P( E0 J' k* f3 N7 ~        ZEROMEMORY( &exqueue, sizeof(exqueue) );# a* L8 ]  \- n+ b

, M4 o% h- f" k        elapsed_time = 0;9 p& @9 i0 J4 k5 V

( [6 o* l. A' \; g1 t        FLOAT        fClock = nes->nescfg->CpuClock;
3 z8 Z) @/ f0 N- s: c9 {" i        INT        nRate = (INT)Config.sound.nRate;  M+ H* l1 @% n& B
        internal.Reset( fClock, nRate );  _8 a, R$ h, g
        vrc6.Reset( fClock, nRate );3 |# {( C+ k- K: f0 e' F/ e- D
        vrc7.Reset( fClock, nRate );
3 w  F5 O/ a+ u8 P: a) V        mmc5.Reset( fClock, nRate );
/ B! F9 J, o8 e4 v# X, j        fds.Reset ( fClock, nRate );
5 D, ~" j/ o$ F/ ?+ D        n106.Reset( fClock, nRate );
$ B2 _* }  s: L: [/ H        fme7.Reset( fClock, nRate );
8 i  ^5 z% u+ z) X; F, F
: ]" E. M: q) ^        SoundSetup();% I% k; m& l6 M' W; L3 i- Q; a
}2 \( ~* z. z- `3 Y

: e, x6 u% B" I8 X5 e7 ^void        APU::SelectExSound( BYTE data )- c8 \; K( x0 Y2 d. C8 N
{3 {% G( l6 s# g' g" f
        exsound_select = data;
! B- [+ w9 v  V/ o+ Z( H/ t. B}
$ y$ h% z: o, }1 ?# G0 l0 j1 @
BYTE        APU::Read( WORD addr ); \! @, |" ^3 B5 u5 W: E# Q- D& ?
{( ?5 f: ]5 V  r9 m: c' H' C
        return        internal.SyncRead( addr );
* g, N! _0 P7 A5 b9 X}
0 ^" K# O2 p/ [" r: \
5 \7 @0 a3 G# D+ ~0 @void        APU::Write( WORD addr, BYTE data )# T- f* m+ o6 Y" K( `" {" c: n  {
{3 _! U9 H: o3 D' I$ s4 Q/ x1 w
        // $4018偼VirtuaNES屌桳億乕僩
" P" o4 N+ r+ N0 \/ g4 Z        if( addr >= 0x4000 && addr <= 0x401F ) {
# L' ?9 V; z( s- c$ O: d( ]  Q                internal.SyncWrite( addr, data );; I6 U) S9 s: y
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );2 X% v' X( m4 ?, b0 r
        }
. g/ o2 \+ `1 D  M9 t/ y0 B+ W7 m, V) J: S}
% k! h9 t  @# j4 l; Z% H" ~2 W+ B, [7 j: k
BYTE        APU::ExRead( WORD addr )
0 a1 I: T5 R7 B$ C4 f% K{
# t- P- m7 B) C" d  {BYTE        data = 0;" s$ T* \3 j/ i. w8 G
% U, \1 K3 |5 k' [. {
        if( exsound_select & 0x10 ) {
+ W  V. D) {! r& P) d* Y6 X                if( addr == 0x4800 ) {8 n" j0 ^% @7 T+ `$ _$ d4 q* r% p
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
+ B5 N2 O  _$ t; P/ P# ^% V5 H) V                }
3 x% N5 v, l. M: J# F        }
' S# M( t# U4 v" R  G( |& y4 j        if( exsound_select & 0x04 ) {
& R8 Z( q# ]5 ]% l. M                if( addr >= 0x4040 && addr < 0x4100 ) {
, d3 M( ^! `8 L7 b1 W# B                        data = fds.SyncRead( addr );" f/ ^5 i" \$ {/ l
                }8 L+ f6 j: ~8 o; E0 W5 V
        }
) Y" @  X1 j1 U. H( a: ^        if( exsound_select & 0x08 ) {
2 y) T: ?# I: g( w$ }. W                if( addr >= 0x5000 && addr <= 0x5015 ) {0 D/ q/ K; M& u- z2 {
                        data = mmc5.SyncRead( addr );, e5 g0 L+ ~. t- A. O3 H  P
                }5 t! A0 _1 R$ g* j5 D) D
        }
& T, b2 i0 c7 {9 q" f6 A0 v8 n
        return        data;( v6 O* f: c+ T) Q! W8 ]3 m
}
2 N3 s' ~- v1 B5 k" b9 L
4 U1 |% {( r: F& S- b* X, O( X5 Vvoid        APU::ExWrite( WORD addr, BYTE data )2 ^& D$ g$ x9 L/ b/ F
{
4 M  G, f2 l/ [        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
9 A! Q& \" E* {; x  X/ v  Z- X9 i. ^! ]
        if( exsound_select & 0x04 ) {
3 f+ U! M- B# }! R: Q5 f' J                if( addr >= 0x4040 && addr < 0x4100 ) {7 ]% i) |5 e4 v4 T/ F5 N
                        fds.SyncWrite( addr, data );/ j9 x+ h; S6 h2 z
                }5 E: S7 \$ q# i3 P
        }5 J* o) o, j2 A* d$ G! K( m: M$ q* G

" ^9 |7 `) k- q: ]+ ~, c( h        if( exsound_select & 0x08 ) {8 w' y( o0 V6 o2 D
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ d% x4 B" M( q: R, I; k                        mmc5.SyncWrite( addr, data );
6 i$ q  Q4 A* B+ c! x- A5 f                }
" c1 d2 X+ g" P# m+ I        }8 `/ c, N8 d# W
}, n8 ^! `1 M! t) U1 ]  q+ G

4 ~5 {# v4 `9 _$ e$ a* ?void        APU::Sync()1 G# ], q, q& {8 F; @( S
{
0 y: O2 o/ F7 l0 [}  N3 \# k+ i( m! p. B6 _8 A
  w" o' G  ?, l: ]3 w1 `& ~
void        APU::SyncDPCM( INT cycles )
# @% Y8 M# u2 V; L% R{
, n! N9 H- ?/ O        internal.Sync( cycles );
) k& f1 u* K6 z  M  I. v) {
8 m5 Z9 U! o  @' h# k5 X& k6 n" s# F        if( exsound_select & 0x04 ) {
8 g4 W5 W, \5 _. X6 I) _                fds.Sync( cycles );
4 d/ U/ ~2 j( X, |! T4 {        }+ x3 ?) C& |! J: \
        if( exsound_select & 0x08 ) {! b* c! e0 ]9 s0 L
                mmc5.Sync( cycles );+ H9 C7 F9 a4 X+ A
        }
  F- c1 }3 m' @5 x}
  G( H. J1 H, k/ U5 P( H3 H# }1 \, R+ F
void        APU::WriteProcess( WORD addr, BYTE data )# x! J* d: a; h
{( n9 u1 }2 f5 p. s- \
        // $4018偼VirtuaNES屌桳億乕僩. W* M' r' J6 B3 G6 n- i- h
        if( addr >= 0x4000 && addr <= 0x401F ) {! g% b2 j' y4 l* d7 o
                internal.Write( addr, data );
4 G$ x. ~( y: `1 j: R+ }# N  E2 \        }
3 l9 q* Z1 ]6 _+ w}
1 `4 x& r0 m8 L2 v6 Z. I, C
# N, B5 V; K/ x1 h* hvoid        APU::WriteExProcess( WORD addr, BYTE data )
5 O' O' p7 K: h2 M: C{
' L+ R/ u7 @8 X/ W3 J3 ~' v; I/ q2 }        if( exsound_select & 0x01 ) {) k9 b+ P/ {7 J- H# `3 r) l& y4 N3 Q
                vrc6.Write( addr, data );
5 Z& O( v: ]/ ^; V: A3 Z2 O4 x: T        }% T  q* V: B: L9 C7 p% L
        if( exsound_select & 0x02 ) {
- @$ O% R0 e! E% M& {  P                vrc7.Write( addr, data );
# ~1 `5 n* i  d! a" C) i) ^        }9 j; @  u4 k# p: P8 a6 ]+ ?4 P3 z
        if( exsound_select & 0x04 ) {
' C2 J  Y% h8 P) M" X2 {$ P5 z: s2 g                fds.Write( addr, data );: x/ k/ a5 C. q! h0 y
        }
8 i8 N7 Z. D" D5 x* Y! L9 P$ v. s1 y        if( exsound_select & 0x08 ) {
1 q) B' R- B8 [3 _                mmc5.Write( addr, data );
& N" g  _7 s4 j  Q3 ~        }
' p8 V4 B  a1 u7 ^; f        if( exsound_select & 0x10 ) {' u5 i- `6 r8 i8 }5 K6 o9 y
                if( addr == 0x0000 ) {
' z$ r3 d5 }; ~( E2 I; [& D                        BYTE        dummy = n106.Read( addr );- q' N. N% k6 z- s7 _( \5 h" s
                } else {
" ^+ f# A: G- e# d                        n106.Write( addr, data );
: N* W6 Y2 }. m* V4 H. @                }4 w7 P* X5 h9 r0 q8 q: P" p. ~( k
        }7 W9 p6 }% Z" B* K$ m: Q
        if( exsound_select & 0x20 ) {; ?  P* Y; D# D# g6 D# W5 h3 k, s
                fme7.Write( addr, data );7 g1 M( t" I5 d' i: h1 t, y
        }
! W5 c3 m: t2 U% V}
7 D" p; Y0 J: `8 l. }- b0 e' \' y- \
& {: j" [+ v; L7 u* A7 Jvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )' F$ N$ D' H1 T+ f- S5 z
{, h4 Z" P: R0 r7 ?8 p0 }' I
INT        nBits = Config.sound.nBits;
3 C/ I! Y5 U, }DWORD        dwLength = dwSize / (nBits/8);
! W" }' H8 H& M. t. s: tINT        output;7 Z; ?* w- [4 S# r2 Z$ }
QUEUEDATA q;. r& X. H; m$ f
DWORD        writetime;
4 E* g- i6 H8 Z  a" W6 k1 R8 y# W# e1 l0 v8 b  e* h; J0 F
LPSHORT        pSoundBuf = m_SoundBuffer;4 [; o( e1 R" v" @) W
INT        nCcount = 0;
  [% k: z( O  O/ `' N* {
$ P9 e, Z+ U( T3 C& H* JINT        nFilterType = Config.sound.nFilterType;2 a- E6 y; h/ |" u
1 I8 g& u. j( W) h
        if( !Config.sound.bEnable ) {
# N* [5 J) _; Q# p0 G+ f                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );" y/ B7 h# e/ i2 `& p, g
                return;
$ q) y" i. W, E4 z, k  y4 m; O        }
; l& h& X+ t3 q! _: ]+ n  d' Z# z- E, @
        // Volume setup8 F; c& A& W$ K
        //  0:Master0 o! c& v; j6 ?- g
        //  1:Rectangle 11 d* Z; p* B9 v$ v) F! h
        //  2:Rectangle 20 c* e/ l% I6 k
        //  3:Triangle
5 \& N0 C+ ]. o" z) ?2 W        //  4:Noise9 o8 P" J( Z3 \- q; ]# |( I- R% p
        //  5:DPCM
3 g! U" z& [- S( L. X2 m        //  6:VRC6, K$ G6 C5 G2 ^  x: |' ]
        //  7:VRC7
4 d, p3 o( P! s0 d        //  8:FDS  S5 M  s9 q* M# o
        //  9:MMC5# u: W+ I4 r' L# C* j6 z* W8 M
        // 10:N106
, B4 J4 Z* U7 w# e# M        // 11:FME7
- S1 {0 m) |( o# a' g" N3 P        INT        vol[24];
* q2 p+ `7 o6 v        BOOL*        bMute = m_bMute;
% W# }4 x4 @4 o" X2 i        SHORT*        nVolume = Config.sound.nVolume;* R* v& r- t& i& q" N
6 m5 V7 E+ R4 V7 b4 g
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
8 q  ?& t* v  X" `2 `# ~% w
: P, C/ |5 Y* Q5 y) Z) C( ?        // Internal
+ Y) e, P5 ~, K$ L' H( n9 \. \! r        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( k9 i( b1 B' X% o& p. h& h
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;0 A& b4 }& j9 f8 V* A5 A) l3 C  [$ q
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
2 B& k  _5 {+ \; s; F. I$ X: G" m        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
4 w- k  `9 \$ W$ C$ H2 S6 f3 z        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  L- k; Q( A; @
6 Y3 u1 |  V, w# H; x
        // VRC61 q- j: ~, u9 A, F  L! X- G
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- M9 h9 C; p5 \
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 P8 @; L3 w6 K2 W4 ?, f
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) T  n( E0 W& [: }( k8 Y* ^, l9 O0 G

. W; K' w* t7 g2 m8 Z        // VRC7
$ q) d$ [+ \) Z' Q        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
( b, ?! v) y4 X8 x7 w
) d( L/ D" j( W5 e        // FDS
- Y( n0 _: [8 {) n' y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;' p; S6 P, \, z$ F% R
- ^4 U8 \; H" }. ^
        // MMC5) h$ f- Z2 O8 @. H4 m5 r& M5 f# p' E
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  i: E8 N0 q* q; r% [        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; x5 {/ @+ i$ n
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ u; H$ S1 m( P# O; x3 o) q# L, ~8 g# O5 e( q- I: Y9 w% O) s& v
        // N106
5 n  n$ b: ^5 w( w9 }" }# O        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  W# |0 m  Z5 e* J( d
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  k3 {3 m8 V7 _3 B        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 J: W/ P9 Z0 g        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 x2 B7 t8 q1 D5 n' K- P! H        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" e; }2 ^3 d: _) ^! {        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 B2 ~# \8 i! \7 B
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 z: J; Z4 H. U$ S# p% ]5 ]
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ Y9 N6 |/ {* B# m; @5 W0 s( Y  [' m8 \( i; \+ t/ \& B9 P* W& R
        // FME78 F+ x9 M2 x8 B5 G8 ?4 C, O
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, L! d1 V) w0 A/ D        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, Y8 c  |2 q2 X0 ~  o9 Q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) s2 S. |/ Z/ I. ^2 l, F. ~7 B

/ R) I0 o$ P( P  z2 j5 T9 i% ]//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 D: R& T3 E3 V, Q9 m, o  R        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' d9 `6 C1 a- q0 d, Y
. g% `8 E! |: _7 c: p        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟4 q. v+ d6 f  k8 `$ T
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
& Q8 F( l+ h! Z; `/ F                QueueFlush();! c& p- O  V) F$ p# u8 A/ d) N
        }
5 t! y; y8 f5 J! \% E3 B
8 X* Z7 J: W( J" |7 Q* `: p7 V5 h3 T! @        while( dwLength-- ) {
! G& u9 Y, I# t! U/ f5 n# I4 g                writetime = (DWORD)elapsed_time;: R- S3 w5 t$ v, p( ^" R/ W7 Y

9 ~6 X6 v7 O( t                while( GetQueue( writetime, q ) ) {, S" \; h+ S; U; |
                        WriteProcess( q.addr, q.data );
0 S3 `0 U9 T: L4 K                }
* Q1 K1 v: f& g( ?& t/ S) B) W0 ?: N6 C3 y: S
                while( GetExQueue( writetime, q ) ) {: y5 [/ |* Y2 y
                        WriteExProcess( q.addr, q.data );
% v3 q, O+ D- C" T6 w                }
. j9 N# U5 _% {! v
' {4 d. n# W3 m5 p2 k+ ]! ]9 ~" {                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
: m" c4 R, l: I7 W                output = 0;
( ^' D/ c' T4 I7 K% t4 S9 B5 ~; s9 |                output += internal.Process( 0 )*vol[0];4 c8 n  y4 F" P1 V
                output += internal.Process( 1 )*vol[1];
, B7 B" W# p& h( ^! k3 }                output += internal.Process( 2 )*vol[2];( Z$ i  _4 T* E3 e6 b9 Z! R
                output += internal.Process( 3 )*vol[3];
% e# [: K6 N$ T8 d' R- |, t1 S3 j8 J                output += internal.Process( 4 )*vol[4];
" O/ k* B4 s8 e9 N& a
7 ^4 }* m+ S( {. @                if( exsound_select & 0x01 ) {
" p  \, K' @/ T                        output += vrc6.Process( 0 )*vol[5];. L4 q, ~/ h' ?) [. [
                        output += vrc6.Process( 1 )*vol[6];
( S' P$ @5 d' m' p) ^; ]! |                        output += vrc6.Process( 2 )*vol[7];
- `8 F1 `6 }+ @# f# D# C                }
6 Z" U/ t- ~2 v( x                if( exsound_select & 0x02 ) {
% x5 H2 }; z  \  f                        output += vrc7.Process( 0 )*vol[8];, L% u- Z7 k0 p- K3 ?
                }& [6 g: o1 f! P2 P4 t& f
                if( exsound_select & 0x04 ) {
2 u7 O9 ~2 r5 r' ^; f$ J                        output += fds.Process( 0 )*vol[9];7 Y; c6 V; V* B7 P: Y
                }
* j/ X- e  X2 N                if( exsound_select & 0x08 ) {
( U; Z* c7 x0 V7 p                        output += mmc5.Process( 0 )*vol[10];/ s$ B8 o7 D" Y& p- Y7 G: u; j( ?
                        output += mmc5.Process( 1 )*vol[11];4 ~. q' z& Q* ~0 |: T7 `
                        output += mmc5.Process( 2 )*vol[12];
7 |% C# Y2 ~# k# S) U2 K                }) l9 n0 V4 p7 R' o! a5 I) H+ j
                if( exsound_select & 0x10 ) {
- u& h  m) h# w( q% Q9 d/ X                        output += n106.Process( 0 )*vol[13];
) D' e$ G  I5 B$ Y! j. [2 Z8 S1 g                        output += n106.Process( 1 )*vol[14];
8 ~. M0 W0 g6 `- h& u4 C                        output += n106.Process( 2 )*vol[15];& ]& V# J% i8 W2 k
                        output += n106.Process( 3 )*vol[16];
, H2 N/ k' n9 S# U+ l                        output += n106.Process( 4 )*vol[17];8 G; G7 B, X2 m( Q3 ?& P% ]8 q
                        output += n106.Process( 5 )*vol[18];+ K3 o. h2 @( T/ t9 V) O
                        output += n106.Process( 6 )*vol[19];6 l9 A3 E- I9 l7 M  f; \
                        output += n106.Process( 7 )*vol[20];
6 u' ?( X7 i" [1 S5 m, Y- m                }
+ D  f, T) \" I6 J! H. w/ w4 s                if( exsound_select & 0x20 ) {
) n2 c+ L* C& K                        fme7.Process( 3 );        // Envelope & Noise; i) V' {$ f; r( z- F5 d
                        output += fme7.Process( 0 )*vol[21];" f4 o7 N4 Q, V
                        output += fme7.Process( 1 )*vol[22];
8 p% Q5 ]* `, I& b3 V  G! y9 t4 ~                        output += fme7.Process( 2 )*vol[23];, W/ ^4 C  I. r* I
                }* @3 V: k. t' l% |' Q. ^8 n9 \6 Y! V
3 R4 U/ Z" G& v% F3 {& [1 G
                output >>= 8;
! m( z6 O5 [8 ~5 a- _. D. U6 }. l9 D* e
                if( nFilterType == 1 ) {
- Z9 m5 s. B1 V) }# D                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* J9 `) ?# a( x2 \9 o3 d; B                        output = (lowpass_filter[0]+output)/2;
: ^* K+ R2 l+ I( Z                        lowpass_filter[0] = output;+ l, |9 z' ?5 t
                } else if( nFilterType == 2 ) {
9 v% ^: `9 y" x; _0 G: p                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 P/ O, s+ J$ ^, b+ Q" z7 \$ ^8 R! S6 j, {
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
) S4 y/ O0 ~: G7 O! |+ R3 ?                        lowpass_filter[1] = lowpass_filter[0];& c1 ?2 H3 E, M# D0 T( h$ B) h
                        lowpass_filter[0] = output;
. g2 E7 N* R# B9 p' t                } else if( nFilterType == 3 ) {  g5 b/ H0 ~% r! N9 g: ], i
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2). c7 o5 v$ @- k9 b* l) P
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
! e! a3 Y& Y8 D' a; L                        lowpass_filter[2] = lowpass_filter[1];
+ z, c9 {2 j4 B% n) N                        lowpass_filter[1] = lowpass_filter[0];/ r" ?0 E- }* D3 w; i" f
                        lowpass_filter[0] = output;
2 D5 \5 H; ?6 Y) l" }, c, h3 V                } else if( nFilterType == 4 ) {
/ U" [. U4 q3 E# _. ], j: n+ [  v% i* U                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 a8 E$ }& w4 P+ ?# S0 v
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;, d5 R- u2 X" Y
                        lowpass_filter[1] = lowpass_filter[0];0 d4 x7 g7 i) [4 E3 v; x
                        lowpass_filter[0] = output;8 p$ w! X* a7 Z3 z# b! M
                }% ]' O7 w( w5 g0 u1 _# S
- M+ I. i9 ~- J* |" I
#if        0
) c& v2 O# k5 d: D0 y1 o$ k- b/ U. U                // DC惉暘偺僇僢僩; B3 V# `/ M. O  `# E. y# R
                {
" W7 r: L; S, M! h9 u& {                static double ave = 0.0, max=0.0, min=0.0;
0 K; j  X2 ~3 k; W- t# Q$ W0 {                double delta;
) l$ P) ~' A6 X) q/ S6 P                delta = (max-min)/32768.0;
3 t0 ]3 H: x. c% r) F& n+ R- R                max -= delta;9 f5 E* p* t1 ^- e
                min += delta;
" \0 H4 k! a4 Y                if( output > max ) max = output;# H2 e, x$ O0 [4 r$ @9 {
                if( output < min ) min = output;
+ \4 P, G# F  C7 O                ave -= ave/1024.0;
; Z' w+ I. C' E* ~: j2 o7 S! z                ave += (max+min)/2048.0;
$ t# r2 x4 ]5 N( v  |. T$ I                output -= (INT)ave;
, f4 K8 W$ s  c" Y5 g- T, X3 I, q/ L                }# }7 i7 h/ O! ?. i1 V3 p1 ]! n: ^
#endif
. j3 b% }) l5 a; F4 k* D# ~#if        1
" K  _  ^4 X( ^6 ^( t! z) V                // DC惉暘偺僇僢僩(HPF TEST). S' P/ ]( G# h4 g) J  i0 H
                {
! l* u  E8 J4 a" ]  \0 D4 p7 `/ H6 E- j//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
) P  {+ b9 p  c! S6 Y. u1 Q) t                static        double        cutofftemp = (2.0*3.141592653579*40.0);
- V8 R, a' e7 Y/ K& A( O+ b* g  i                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ G7 F& o2 w" G2 I                static        double        tmp = 0.0;
; _7 ?4 ~0 _- f- o6 G' A                double        in, out;
. Z- Z9 p1 {( K  A0 K2 }3 N% |8 r! V0 v. C( S: e) |
                in = (double)output;
8 F9 s9 p! Q# \) Y( H8 x7 i9 C                out = (in - tmp);  ^, R. @" G+ Q4 M
                tmp = tmp + cutoff * out;
8 ]4 d, d) z- D# u6 A+ f  v2 w) c' i- i# K
                output = (INT)out;' K$ m1 C7 w1 P" N& r$ g
                }+ N% ^  l0 R  k0 e, d
#endif
" F1 R8 X$ C2 c- p0 l: Q+ e+ `#if        0
: ^: \2 s8 P6 v0 }                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
+ k- D( r& s1 r& ^) C                {
6 c& p0 U4 j6 O2 i) n, i                INT        diff = abs(output-last_data);+ E0 P& F* \' u: f
                if( diff > 0x4000 ) {
' D4 l1 w+ O7 N$ p8 {) z                        output /= 4;* J- d" R# N" P: a/ n) h1 j- [$ l
                } else 3 j9 @; E; s1 Y( H0 n+ I- y
                if( diff > 0x3000 ) {' {. l. O2 ~5 F, X1 U) P
                        output /= 3;& D7 `8 b% t% a. n: e) J
                } else
" E0 X2 ?# `. a6 M& ]                if( diff > 0x2000 ) {7 T0 Y" B5 C' n
                        output /= 2;5 T9 |0 }6 }1 C1 ^3 H1 R8 }8 W
                }+ z1 m' L. x' s2 |/ a' v3 p
                last_data = output;
9 m! S# ~0 J, W( S% N4 V                }5 y2 D6 D  o) t( V7 D6 s
#endif
! Z7 O4 u" W. Q: p) Z) [                // Limit
. t3 c$ ^# V5 ^; v$ k                if( output > 0x7FFF ) {
5 F, i/ S8 p* r; n/ N                        output = 0x7FFF;6 I! M7 b5 L+ v4 e
                } else if( output < -0x8000 ) {
$ A1 {% p; s2 c. |7 g4 F$ u                        output = -0x8000;- }& r! T2 z6 J6 Z
                }
% u9 H0 Q1 t( C6 R; o% L# R. r' s  K+ q. k; J7 m& @! I* e
                if( nBits != 8 ) {
3 ~) u: d8 u  d/ S: Q7 [/ U                        *(SHORT*)lpBuffer = (SHORT)output;
) M$ f) e! M; L5 N% j                        lpBuffer += sizeof(SHORT);
4 v% k: ]  Y0 I( x5 |+ d                } else {
7 K9 t- p4 t) {  ^9 q                        *lpBuffer++ = (output>>8)^0x80;! h7 n6 @& b% z; i9 m  @
                }) l6 a. V2 O  F) Y7 b
. i8 A: K/ ~/ Y' }/ f
                if( nCcount < 0x0100 )6 |; q. k" n# B. t2 {. t
                        pSoundBuf[nCcount++] = (SHORT)output;+ {; \9 G8 O# }" ~2 G2 w8 C9 h1 l

2 M! _7 L* I- Y# f2 I//                elapsedtime += cycle_rate;  L5 z7 m( C' C
                elapsed_time += cycle_rate;: A8 k' z  W' D  d
        }
1 C! A4 p/ U" f4 Q
, F- k' G1 V* D1 o% \; ?#if        1
9 b+ ?: l. m8 i, X  o        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {# I# w) P1 a5 M- K' `$ g) p8 P2 j" F
                elapsed_time = nes->cpu->GetTotalCycles();( M/ d* i3 E4 j- b( y9 c
        }3 B! n% z% M" T1 P9 f4 K6 K
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ z& y, v" y5 }
                elapsed_time = nes->cpu->GetTotalCycles();
7 I" W7 H# D& }- M8 b+ X  M        }: V( ~/ t4 L: x; ^. X9 }
#else4 I, \- L/ W1 r4 V9 R' x
        elapsed_time = nes->cpu->GetTotalCycles();" l# ^* g8 p( _4 O- U4 a9 ^- z
#endif) z: o* H+ L( e7 l& O
}( h( ^" U: k0 D; B4 Z% Y9 a) T
4 ?& ]$ `$ w- Y. ]
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)7 [* M  Q" B, U0 l: J1 B
INT        APU::GetChannelFrequency( INT no )  Q2 Y& S! T/ s: Y- i0 _" B1 |- |
{
- S% J4 Y7 [9 r; b( ^        if( !m_bMute[0] ). s( g# t  h; |: Q" U7 _6 u! i
                return        0;
( ~! X, `4 F/ k1 U0 I  N6 X; E# v* ^, S7 S0 D7 U" {$ u" t
        // Internal5 k+ d' Q9 b7 Y" O/ n
        if( no < 5 ) {- Y/ q1 x) k- `: `+ X) L' L" ^, h
                return        m_bMute[no+1]?internal.GetFreq( no ):0;) a) N7 C0 o- B
        }9 O+ e$ S# u" h3 X( \
        // VRC6
+ }4 N" {; a$ P" r4 b9 j+ G5 \        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {. _3 T( _8 b! ^. w; X$ }
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
0 ~* L+ i  ?1 j# `5 D7 E        }1 q& a5 h2 X" ?  t
        // FDS
5 w2 {+ ~% x/ |* r5 F        if( (exsound_select & 0x04) && no == 0x300 ) {
  [( Q7 {5 d, |# X                return        m_bMute[6]?fds.GetFreq( 0 ):0;
: ~# Q; `8 k- M/ l# \( _( M2 n        }
  K% _% N! u  _- s) F8 r$ E" E        // MMC5* ?+ j2 ^  F+ `& Y0 I0 F
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; [( O9 \7 ~. C8 u! ?& K6 t                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;* m, `, z9 N! w
        }' k$ o/ ^. c& b; |
        // N106
" ?5 g# }) D' q0 H) G0 _        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
1 @: D  g$ Z0 ~' @                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 [' ^; s' I  ^( R6 P3 o% b; q. s
        }
: l" T# f+ D* E  D        // FME7
  q% K6 T$ l7 K2 D1 \! S# O7 v        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {  v7 m0 V! a/ l; F# x1 y5 g4 t
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  K, H8 N# ]) e8 Y* e( V7 B        }
% b7 n+ h3 }4 c# D        // VRC7
6 l& D3 V& b$ O- U; l0 ^        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
4 P. R9 n- E9 [% |1 l                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 l: U( k  j) T. J+ h        }
$ M3 o& \+ z  a4 M/ a        return        0;
4 {. G! }7 a+ s- o1 a% y}9 B! C  N" f1 k2 d; Z' X1 F

! s$ t% G. A6 A7 w6 h; G// State Save/Load
& N% H$ N6 n7 E4 Wvoid        APU::SaveState( LPBYTE p )# c& H0 o; C' N% w5 t# P: E4 J
{/ V5 }; F* |" z1 |
#ifdef        _DEBUG
, i/ t. j# y8 ^2 yLPBYTE        pold = p;9 M; V9 e; {% h) z( _, h5 p
#endif0 d+ ?0 m" k1 I# @2 n# o* `4 f6 C
! O0 A: ~# D0 @" V+ R- p9 ]/ H
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
( J/ ^* z7 U% J! ^        QueueFlush();
& P& B; {6 s. O3 E6 g' l) C9 x, G6 r" s; ~6 P! i
        internal.SaveState( p );
! x# j$ b# r/ G7 w* t        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" f1 S. Y- F% X* M2 i5 X. s/ e* a' l! l  m6 L3 x
        // VRC6. x. |0 F: p" i1 q* `( ?
        if( exsound_select & 0x01 ) {& [" }2 y) t- q4 C5 {1 S
                vrc6.SaveState( p );
! i9 r9 m9 t9 j" |                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 F% k0 ]$ W. K, O) a* h  X+ L        }
" n9 G& ^- H# x; {/ V        // VRC7 (not support)
' C8 V/ S5 V- k- K        if( exsound_select & 0x02 ) {5 X8 P! @: F& S4 L
                vrc7.SaveState( p );
* y2 N8 @( _; e                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# ]  a) n6 D/ o+ R  e) H2 R% z- |
        }
3 ~& t8 I; V$ |+ R% B. A        // FDS
% o7 o, a( q% P/ b3 `, x        if( exsound_select & 0x04 ) {
9 y- _; E$ ?1 ?9 V) Z) a, x) E                fds.SaveState( p );
- C8 ~/ g. o4 N2 f6 A2 Z' E1 j$ Q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" t3 V: H6 A4 }. n        }* }6 S$ x+ q$ P, i5 p7 s
        // MMC5
) V8 V- M; P  _. `        if( exsound_select & 0x08 ) {
' e9 D, m$ i6 J7 X3 J2 b. V  k+ j1 H                mmc5.SaveState( p );6 G: Z4 d; w4 Z/ E  Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' C: u' a! M8 d* N9 B
        }
$ `: r0 z: I' j9 g& `. J        // N106
3 w6 B6 E% R4 s' J        if( exsound_select & 0x10 ) {5 o0 w4 S. h0 h
                n106.SaveState( p );5 ?  Q2 t3 d- H) w& e2 d6 {
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
+ m+ n' H; _) m1 y+ I* x        }- X4 W4 E0 }5 T
        // FME7" I  f- ]5 w% s1 Z5 k; U9 C1 N0 ^
        if( exsound_select & 0x20 ) {. W; L% o( H$ q% T
                fme7.SaveState( p );
. W+ e( Z$ K% w- z/ r* S5 T                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. u2 }6 ?# l/ h- r! e4 Y6 V
        }
) \! a- Z5 h/ y
& F3 X3 Z# W5 ]6 y. G" F. `$ l#ifdef        _DEBUG8 Y( M- i9 l& `6 m7 R: c7 Z
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );  v4 i1 U2 B/ c" G/ x
#endif9 ?# E1 P' J; U  C; |; m/ z$ j! `
}
, p, K4 n$ \/ [% x4 J: m$ P
% f; U, c- Y; d% yvoid        APU::LoadState( LPBYTE p )
9 ~# K2 P, ~6 d' s" t" ~{
$ Z9 v; c! @! `' s4 I        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 n; q: ]; M, K# D5 j$ n  E        QueueClear();( n0 H! t) P1 }" w
1 O4 Q% c, _5 B" z9 d
        internal.LoadState( p );7 g% S- c- Q" w. [
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 K" r9 x* f0 g. m& S( b' h7 \# u; `9 ~1 D$ ~
        // VRC6
& k& Z0 b& g- r1 \  p        if( exsound_select & 0x01 ) {
/ s2 G2 I% P) H* s/ }                vrc6.LoadState( p );
' L, s! ?) Z4 e. o- ]& V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* A  @, ?/ e0 L        }
# Q  s" {- v  F        // VRC7 (not support)/ E2 D: t1 Q4 j. j( ~7 [7 ~
        if( exsound_select & 0x02 ) {
. a8 Q3 Q6 u" D4 k; g- h7 R$ _                vrc7.LoadState( p );
% `. k- k% N  u( y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% m- S0 i6 m- o1 ~) F& j2 @( b0 c        }
  f1 C1 |: W/ ]1 {        // FDS
( @2 _/ O* I3 v! q7 m" R  q        if( exsound_select & 0x04 ) {# G1 U& F9 N: D& u/ ~7 I1 z, h
                fds.LoadState( p );" |/ x2 u0 O* L8 b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ V5 {9 C( [- G3 B, t$ i- J7 E' A        }
; Z$ R, W6 y: E8 l; d        // MMC5
7 h5 _+ p0 w9 y& V        if( exsound_select & 0x08 ) {
& g; t) G: z; c, _0 H                mmc5.LoadState( p );  l! V/ f/ d8 `' R) W! G
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 o- v- c6 \+ J$ l
        }8 r9 u) ?% k2 {' s  C
        // N106
) L, c  G& E9 D        if( exsound_select & 0x10 ) {
# }# e' D" U! B2 [3 S0 k0 E0 w                n106.LoadState( p );) p% [- Q. P5 J2 S: e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 C$ \& F0 Y- _7 E$ \1 V6 o/ [
        }6 Q+ e( z) t2 d" C
        // FME7" H, M5 V- f: j) l
        if( exsound_select & 0x20 ) {- U# H+ o! ]9 ?) v+ `$ C7 s
                fme7.LoadState( p );
: V: `( @4 {$ k: p& K9 y' k                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# G4 V( j5 R5 _, _! U        }
# _+ Y7 b/ H: c# o  M}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / q5 @2 C3 A2 z) L! d! G
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。3 R: }1 I6 Y3 u  U7 T* ~, {8 P
感激不尽~~

2 K. V* }1 X) T5 G+ H恩 我對模擬器不是很有研究,+ N' Y& ]* I1 C# s0 d# f9 h" w2 Z  R' Z
雖然要了解源碼內容,可能不是很困難,
, ~  t- m/ e# T! z; V7 h' g- t: ~1 b7 b不過還是要花時間,個人目前蠻忙碌的。
& }9 V" q+ p! L- b  C! x( I* g1 m3 x. ^$ h. h
給你一個朋友的MSN,你可以跟他討論看看,
# \$ G  C* d+ Y他本身是程式設計師,也對FC模擬器很有興趣。
( B6 [' G! j; S2 q" x. d
7 {1 u  j  @0 A! Q! I6 J" w- n* LMSN我就PM到你的信箱了。' C  j. Y  Q7 }/ J& s, |* l

5 a, P6 L: Z  w7 f& k希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 , O. K% O4 n2 d" r' k; I
呵…… 谢过团长大人~~
/ M  Q" }7 u: t: @
2 A) N! g5 v* j. J
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! t) E6 r! X: D; n: B2 _  F团长的朋友都是神,那团长就是神的boss。
4 L- l  V) w6 j# {( {/ a2 e! g
哈 不敢當,我只是個平凡人,
9 I, n: j1 R  T) W$ w要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# D2 i" |) |" D/ U% B; U/ Y9 ]
ZYH& N+ u# D" _5 `* j
QQ:414734306- X0 ~/ I, Q5 S3 c- |- K: V- m1 s4 t
Mail:zyh-01@126.com
/ ~  b- \" R- Z3 _8 m/ a; A( o
* B7 o- e1 x; x5 B2 m他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 a( S# s# ^8 Q& p1 i* C$ ?
再次对团长大人和悠悠哥的无私帮助表示感谢~~

- D: T$ W# L+ c不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-8 19:25 , Processed in 1.073242 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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