EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: Y0 \& B& Y, Y- c+ z
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, o# a9 e; S# b
这里有相应的模拟器源码,就当送给大侠了~~
' l3 {, L# v' F7 v/ ?) U/ `http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
+ c9 L' h: Q5 s' v6 L能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. g1 [- n+ Y+ O5 S6 A3 J
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: C1 V0 p* t; D6 B6 D# x
这里有相应的模拟器源码,就当送给大侠 ...

. {3 v6 ?  R/ f& S& I) q* o4 T聲音部分(Audoi Process Unit = APU):; D( f5 c2 Y; _. c
.\NES\APU.cpp  G) a3 l5 `  T4 {8 p" v" T3 W
.\NES\APU.h
, \& A, v! v+ N. G3 d( Y. @: b- @; @' T' Y

6 M! y+ I2 @, |0 E3 Y* ?) S影像處理部份(Picture Processing Unit = PPU):+ U# r6 n& K& N5 Z  I
.\NES\PPU.cpp5 f7 U. p+ S; |% h
.\NES\PPU.h
* s2 M, V) W. o( F! C! ?! i2 P7 }' E; U
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& G# }8 Y) w' p/ y- s( P$ R  {
(由于很多专用术语和算法机理都不明白,所以看不大懂……)* m- ^' S* u+ j6 G
//////////////////////////////////////////////////////////////////////////: k% b3 p; L" o% j9 ~& }' b. V
//                                                                      //
: y4 F! I  ~; m//      NES APU core                                                    //
4 {0 W5 c. P8 e  u* k4 A% S//                                                           Norix      //
& F# ~. {1 `  b9 X//                                               written     2002/06/27 //! x( p  y% B2 \( {
//                                               last modify ----/--/-- //
2 G5 _, m8 {0 i! E: @, ^6 P//////////////////////////////////////////////////////////////////////////
6 e" u  t; {6 D) I  N1 _2 R7 _2 T#include "DebugOut.h"* ?& v3 ]2 U7 ?" D. W: A
#include "App.h"
( R0 O8 m, ]2 D$ Q% @( O  V. R#include "Config.h"- d+ g1 ~. w3 L# o
6 h8 F  b$ e+ d7 d- {  O% ]$ [1 Q1 p
#include "nes.h"
) F* s6 ~! p6 P" m; Y( E* e#include "mmu.h"
) W- T8 j; O( h$ N! r#include "cpu.h"
) f6 c* B) y( y# _. _#include "ppu.h"0 c7 D# A6 i6 w5 [6 }
#include "rom.h"
' {" J" s" L; e& k# `5 |3 v#include "apu.h"
; \3 D  v. d, d! I& O3 _, }* v, z5 K
// Volume adjust
2 ~( G- l& A. m8 N6 R5 u, W// Internal sounds' r% z5 o9 `! [( O
#define        RECTANGLE_VOL        (0x0F0)
3 T2 l3 r: Z3 I" e" O& \#define        TRIANGLE_VOL        (0x130)
- {6 a& A* V2 D% T: z#define        NOISE_VOL        (0x0C0)% k" g+ D" \/ M0 Y
#define        DPCM_VOL        (0x0F0)$ ]- U& F' H6 m* ~6 @+ o; h) y
// Extra sounds6 V. v9 _, {  A6 w1 ?* w
#define        VRC6_VOL        (0x0F0)! H& A- [) x' o; {6 l7 y
#define        VRC7_VOL        (0x130)& g% k) Z3 _! ]0 u/ X4 h0 p7 @
#define        FDS_VOL                (0x0F0)  l7 u$ S4 r: k* k7 m, h/ l' b( Q
#define        MMC5_VOL        (0x0F0)9 Y) t  W, y/ W' y
#define        N106_VOL        (0x088)
2 m7 K' B+ z3 c" @/ J+ a; ?) A#define        FME7_VOL        (0x130)  J. Q- r. U* a4 d& @3 X
( Q! Y5 q- [" E8 ]. E  x  C
APU::APU( NES* parent )
: E/ c6 U" G, ^+ _+ S{
' m, d! L- q" T# I6 A8 @        exsound_select = 0;
, z0 h/ _5 y9 o$ r+ W+ ^3 {0 m
+ q, v+ u% |- t, {* k, {        nes = parent;. w) N9 T" J# N3 A% M% P
        internal.SetParent( parent );
7 ^4 l; o0 R8 P4 q& I1 ^! L6 t
& \! ?9 s# K' P/ P8 L0 V4 x        last_data = last_diff = 0;
4 m  |" k* v# e3 a9 S% B
1 B/ J* {6 Z0 \        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );4 }4 a* F) T. R1 t2 u
2 P2 `. z- R( d: g
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );  K, ^  F" u& [  m  r( c1 J
        ZEROMEMORY( &queue, sizeof(queue) );
3 l4 V# j* X: r6 B- D0 A        ZEROMEMORY( &exqueue, sizeof(exqueue) );, o. l5 p- g1 k/ x9 x- W

7 I$ P) l, g6 `. |& i        for( INT i = 0; i < 16; i++ ) {0 [+ {/ a4 i& c0 `
                m_bMute = TRUE;
0 ~  B5 x3 \# _        }
6 D% {6 [7 V7 A9 i0 v' y}
6 m  v/ W$ Y% d( x/ d& ^8 S" y9 H! _- i* h+ j5 m
APU::~APU()
5 b% [: B: j9 K1 \4 u( G{
' s4 L4 Q% e9 z}
5 ^9 |" ^$ J4 ]0 R1 S5 g
  @4 u: V7 R, c9 Y3 \/ ~void        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 k2 P7 e* f# Q0 Z) D" r/ h
{
" D! e# o# ~: E! x        queue.data[queue.wrptr].time = writetime;
0 R. i6 W' p7 Q; j/ F1 W$ g! K        queue.data[queue.wrptr].addr = addr;* m  E. s- L) s$ o8 P0 z
        queue.data[queue.wrptr].data = data;
9 J2 ^8 C2 D5 m7 M# m* Q        queue.wrptr++;9 M$ D! b4 L5 K
        queue.wrptr&=QUEUE_LENGTH-1;- V; A: @. L& y4 L
        if( queue.wrptr == queue.rdptr ) {* }2 m7 H+ r3 P+ ^  v
                DEBUGOUT( "queue overflow.\n" );
9 q% C" ]1 }% ], u3 C3 |; d        }
! W8 R2 {0 E$ V* F0 T& |& }}
$ X- E9 O, e& S1 ]/ k8 s% V9 T5 @
% h9 S* i3 z; u5 u. ]' o0 oBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
5 ^" r4 r* I: k8 v! K{
% m* P* [/ X# A" |. o. k        if( queue.wrptr == queue.rdptr ) {
$ u. B4 Z4 ?  G                return        FALSE;5 D% O: y0 t* r  }( @
        }
- w$ _: V$ C* L6 p& e6 m        if( queue.data[queue.rdptr].time <= writetime ) {
( a4 ~- n2 t) @; ]3 U% c" }                ret = queue.data[queue.rdptr];+ S% O- \. `3 y( \9 F
                queue.rdptr++;& o& q# [3 ~& I1 s- G- U
                queue.rdptr&=QUEUE_LENGTH-1;$ g0 c4 t* |2 z6 o8 I/ a
                return        TRUE;
+ r* R3 q& {3 d$ T+ t' P: b" X        }, A0 P+ J! g' l
        return        FALSE;" V& U# x& }5 P
}
1 i: r* X" S( I% \& @1 X/ e. ~9 Q  V" f1 `8 {, {
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
- }: S" }6 P% `/ @( Q( J{" b( I0 s6 D% |7 E% \
        exqueue.data[exqueue.wrptr].time = writetime;* x( M6 P! e2 B9 Z. G  x
        exqueue.data[exqueue.wrptr].addr = addr;4 N5 f) _! Q# [5 N' h6 t! ~
        exqueue.data[exqueue.wrptr].data = data;
, x4 ?+ H; g1 g+ Z) l" }        exqueue.wrptr++;/ L  G3 U' c- s/ Q  K
        exqueue.wrptr&=QUEUE_LENGTH-1;
! ?+ k! `; p/ \% v' `        if( exqueue.wrptr == exqueue.rdptr ) {
. F) W6 E2 K5 b                DEBUGOUT( "exqueue overflow.\n" );8 q: D( l2 S& K: T( Z
        }
7 X' l) a& H; D3 ?) H}
* ], X+ n3 y* x3 y  `7 t
" r7 c. S4 Y0 e4 ~3 OBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )& j4 l7 O9 ]% p; ?
{
: ~; o4 d1 k: L: |2 n% ?        if( exqueue.wrptr == exqueue.rdptr ) {
+ H& c' X  Z, w8 _* y. n; \                return        FALSE;
, r# K; x, x$ f7 n$ c        }
8 i/ r% T1 T: g, q  }, U. c4 f        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 Q. _! N9 Y) Y- t* l: s                ret = exqueue.data[exqueue.rdptr];% u# i6 d$ _" W; {% e
                exqueue.rdptr++;
! `% ~, Q" o7 z  m, L& X- J9 C                exqueue.rdptr&=QUEUE_LENGTH-1;  b/ o# ]! c. q0 n) Z9 E$ A4 Y
                return        TRUE;
7 y  w, T; S  t8 Z- X7 N        }/ z. g. ~# s6 {' A+ U& l
        return        FALSE;
: N2 `! b% W7 N/ R: j}
; u. f8 ?# d' d1 e, |4 N/ ]( {9 I/ r( w0 @; M' V# N, h. w) E
void        APU::QueueClear()
* p' [- d& N* b1 U{
2 Q5 J* n! a' p) V        ZEROMEMORY( &queue, sizeof(queue) );
) x9 e6 g" O- {8 c2 P. H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. k6 w8 ^) @5 N( h4 ^# \}
; \9 d3 q6 _, e4 |4 k6 {8 J8 z  w  t; A, N! ]$ n: T
void        APU::QueueFlush()! |+ _5 K9 f, q5 Q& @% ~
{
) w% u+ n3 J. y  U7 N* J$ w        while( queue.wrptr != queue.rdptr ) {
: V% i  ^- B( v. [7 {4 R                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );4 B* g; k) M; {7 r  X) i, A
                queue.rdptr++;* h" a6 D: w- x$ r) y( n7 u
                queue.rdptr&=QUEUE_LENGTH-1;
, K& H4 l. P/ j3 D- \- [        }
! M& U2 S9 h: g8 E  a' d) `; Q) V$ z+ w: D& {! v
        while( exqueue.wrptr != exqueue.rdptr ) {
$ b- `9 ?! h+ r! ]4 Q                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 O9 P* O% f% O1 i
                exqueue.rdptr++;
# ~% l8 \# u( T3 S. r4 y% T" S! w                exqueue.rdptr&=QUEUE_LENGTH-1;
! p. D. K3 R" K7 R5 \2 G4 d, _        }
! X5 W2 k& Z* R; d  v) i}, \/ q2 u7 k& f& N' j* E

3 }% ~1 `' k  g: svoid        APU::SoundSetup()
% z8 k1 B+ X( X; U0 @{
7 P9 q( D, _9 W9 l% `        FLOAT        fClock = nes->nescfg->CpuClock;
7 ?( I% s. f. K; [2 u2 A        INT        nRate = (INT)Config.sound.nRate;
* J; j8 ~. K2 J7 x/ A* x        internal.Setup( fClock, nRate );- d' {9 G  T. m& \* m7 D4 m
        vrc6.Setup( fClock, nRate );6 X& \! C0 J; S+ g2 w' {
        vrc7.Setup( fClock, nRate );
1 G$ z7 P$ J: f0 e- h        mmc5.Setup( fClock, nRate );7 J' t! {- A1 U- M7 z# c
        fds.Setup ( fClock, nRate );
. S. `1 F0 T; s: k% x$ g  A1 d( W+ i        n106.Setup( fClock, nRate );+ R3 H% _  c" b1 b  ]2 I/ N
        fme7.Setup( fClock, nRate );
5 r6 G( t, b2 o) C}
/ r( y# m5 C. F+ o- C" ^* o; W+ m5 I# I$ X: x6 F
void        APU::Reset()
/ O; i7 \) X' h1 h+ z4 B0 i{# P5 u) o1 f; x# c1 R$ T9 ?* `
        ZEROMEMORY( &queue, sizeof(queue) );7 g- g5 z6 {' ~+ b
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 l7 r# t3 j; S8 I2 y. \
! l' U+ k/ l+ w0 h        elapsed_time = 0;
* E  h% I2 i) t$ l4 }) {, m; k$ x7 z1 l- i1 z' _
        FLOAT        fClock = nes->nescfg->CpuClock;9 _4 m6 a' h3 {' S
        INT        nRate = (INT)Config.sound.nRate;3 s: R9 u# q8 a& v9 q. b  [
        internal.Reset( fClock, nRate );6 L) M$ |7 y  r$ B, X0 G
        vrc6.Reset( fClock, nRate );
+ R) V9 T3 v$ Y- F        vrc7.Reset( fClock, nRate );
# m+ t  `  y; `8 J: A7 i2 f: h        mmc5.Reset( fClock, nRate );
% i: S. F& T, R4 R( ]) @        fds.Reset ( fClock, nRate );
: @# x7 J$ |. t$ t, I# |        n106.Reset( fClock, nRate );
  g2 \% n2 Z4 \$ v) M! z        fme7.Reset( fClock, nRate );% v; S) G2 l! g) C3 w9 V

, \4 Y( p5 F1 m! x% R. r$ m        SoundSetup();
* B. W/ u8 ^' t( a6 S9 u8 F  F}
2 m5 ^- G, |% @3 x% J1 K( t5 j1 Q+ H2 I
void        APU::SelectExSound( BYTE data ): A( l" M- [- Z
{1 W, [# d5 O" X( G
        exsound_select = data;
3 v/ I9 f* f6 f3 }}
1 o2 B: o/ T- F* \9 {! {
& M. o8 {: f1 hBYTE        APU::Read( WORD addr )2 l3 u2 t6 G% [- Q! m( ?
{, t% x" k. O5 E& p# y. |
        return        internal.SyncRead( addr );/ {9 [  B3 h8 O+ t
}" w3 N: r8 V* ]5 Z+ X2 }

! O2 a. u% R! S5 C1 N3 M. v5 A( vvoid        APU::Write( WORD addr, BYTE data )8 ]+ N! Z+ h) B7 h7 y, q  B& O* g
{; b* I/ _& Y8 }+ Z; X
        // $4018偼VirtuaNES屌桳億乕僩: P: Y) V! d+ s3 B6 ?
        if( addr >= 0x4000 && addr <= 0x401F ) {5 C; ]7 e  s' T5 k  l2 b: {0 f
                internal.SyncWrite( addr, data );
. r8 ~2 U6 k& T* E; e                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
; s$ G& T) e6 U; P        }
. o$ u0 t3 r9 j3 V5 n! _5 x& Q}
- G. Y, X! \" n7 e0 |- _+ j* {9 v2 \3 Q8 Q
BYTE        APU::ExRead( WORD addr )
$ H: e; h0 ?1 F: i: }7 J{
$ L, y' T4 m- p0 _0 o# E3 S1 DBYTE        data = 0;
; N& b3 r/ d# `) `1 T7 a
% y' b% y6 \, O6 ^8 I        if( exsound_select & 0x10 ) {. r6 v1 X5 s  \- ?
                if( addr == 0x4800 ) {, J) `9 W. A7 s/ v& u9 o/ g
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& {; H* F/ u; u' S5 @; }: {; t$ Y
                }
3 \3 ?- K9 k: m) `        }  {7 f. u: ~& F. p' ~9 a! ^2 C
        if( exsound_select & 0x04 ) {
: k0 A- E9 L5 m' u( m                if( addr >= 0x4040 && addr < 0x4100 ) {* j) M# t- n- u7 S2 _' x* \! P1 v$ G
                        data = fds.SyncRead( addr );3 @3 z3 @+ O) B  o" Q
                }* _! X* O3 q5 p& s$ k& @
        }* Q  P) y7 v& J+ h; F2 \; q
        if( exsound_select & 0x08 ) {
9 x4 Y' r- n5 X) m, s" A                if( addr >= 0x5000 && addr <= 0x5015 ) {
" h2 T7 u) n" S2 U' }                        data = mmc5.SyncRead( addr );/ }$ Y& q2 Z+ X) |9 H- Y
                }+ H6 x- k/ }0 [0 c# c, A3 r, ~
        }
3 b2 p( `4 k% |9 ]$ d+ H, u$ s' r! @' `  \9 T# n2 ~% _
        return        data;# O- I; |8 T( d; T7 J. R
}9 U; h- Z8 z: z# m# j

6 ?* v! e" z/ d2 e" F! `$ Wvoid        APU::ExWrite( WORD addr, BYTE data )) n' {$ N. H7 z7 N
{
6 n, s3 b7 @& `0 J/ B* x- Z' E- Z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
1 s8 L# ?  h4 t% q5 o
8 b0 D* V- i( f3 [9 a; F: d        if( exsound_select & 0x04 ) {. i) j5 L7 I0 n: z0 `1 u( `
                if( addr >= 0x4040 && addr < 0x4100 ) {
. F4 B/ u8 h7 x  P0 d4 s  `                        fds.SyncWrite( addr, data );
0 h. D$ h2 H  y/ ~! t, {                }4 R6 y/ m5 `0 E5 Y
        }. x+ l7 `" V( l6 h

3 [- t$ o- _' O* Z- Y6 W        if( exsound_select & 0x08 ) {; L' g5 W+ k5 l
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ k( z$ h7 N3 y- ^) D
                        mmc5.SyncWrite( addr, data );
; ~* c: g5 w2 M4 F4 G# g                }: y9 m7 {' E6 v  y. g, n
        }- @1 ^# H3 G1 A# J
}
8 ]1 Q+ T% n: j  k
  ]$ V  i5 Q/ B) |void        APU::Sync()
& K+ z, @  I6 C: V2 S4 t- m{
- \' D# {' {, U2 R% o  B8 n}% w# K4 \2 ~6 q( H  s0 l
& }9 s% g( X( g0 A: @. ]# W. a
void        APU::SyncDPCM( INT cycles )
2 m/ @1 H& V; I5 P/ M$ r! M. t{
' G! j$ w' d) Z' m$ T$ j        internal.Sync( cycles );
) Q  @& g! w  B7 l/ Y
/ v8 B. |! i- [0 `        if( exsound_select & 0x04 ) {; Y. T4 P* {9 k/ T
                fds.Sync( cycles );
5 G. p3 o+ F/ [: ~) B  l        }
* t# h* o, z) d6 a8 X+ j1 g        if( exsound_select & 0x08 ) {# [  N& e1 T' ~" i% c  }
                mmc5.Sync( cycles );% p% E( N! t* W  E, b6 c1 l
        }
5 o7 t. l4 n* f/ ^6 l( y3 r}
) }/ E0 e9 x) Z' x5 d
, g3 R2 `9 f; v) H+ _void        APU::WriteProcess( WORD addr, BYTE data )
$ r! o* N* l3 O8 y% |; E{$ P0 z0 e  s; P6 M# j* M+ r
        // $4018偼VirtuaNES屌桳億乕僩
( X7 I; J% [6 W        if( addr >= 0x4000 && addr <= 0x401F ) {  T6 |) M  l3 y1 m- J- Y
                internal.Write( addr, data );0 s+ ?' w# v: ~; \
        }- \1 ?' E# q. Q( M, g, X; a3 G; w
}9 D2 B/ t4 F. e: l+ g

  n5 m% m/ Y. V; {void        APU::WriteExProcess( WORD addr, BYTE data )
6 s+ u) `: R" w  P  o' w- S+ t{
$ k4 j0 K0 M- h* R# W        if( exsound_select & 0x01 ) {+ ^; [" l) p0 N
                vrc6.Write( addr, data );" E) S, k' E0 N7 S2 j/ D, V
        }" k5 N2 L0 K! A" G# l
        if( exsound_select & 0x02 ) {, B' }- ?3 @2 n% X
                vrc7.Write( addr, data );
- l3 p0 q3 K1 m. ^: [        }
0 ]. d2 p4 R6 l: I5 O7 x$ T        if( exsound_select & 0x04 ) {
  ]# w) h6 C4 c: w4 j, q& o# k                fds.Write( addr, data );; k4 {3 k/ I2 ?
        }! ?) y8 l7 z0 i$ o  J. @
        if( exsound_select & 0x08 ) {
% w- E- o5 J! o$ B( w' F                mmc5.Write( addr, data );# f$ O9 c9 @" d& X7 b7 D  {
        }
- z2 ^1 y$ u. {  b5 C        if( exsound_select & 0x10 ) {
5 U6 {# b: l1 y0 h                if( addr == 0x0000 ) {
% D1 y0 s1 C* u8 ?! J                        BYTE        dummy = n106.Read( addr );6 \; @3 J4 a/ T0 @: C; u) A9 L% f( }( [
                } else {
2 s2 l. j9 K% ]+ L                        n106.Write( addr, data );  Z( m9 |* `% y( ]0 `
                }8 E: r" F' o* a6 K: {0 K; W
        }
( t9 X+ U2 g3 u* \% @# V8 O- R+ m        if( exsound_select & 0x20 ) {
1 j1 I5 l2 e) \                fme7.Write( addr, data );
  o: o- J' h3 H1 |        }
5 ]0 c! Q- X6 T2 c  G}
) w# k" E, M0 j3 ~  C/ Q* _/ T% E# A, `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  z. B6 H" U4 E/ C# N. ]
{
2 K( X7 D9 U3 \6 g. `5 Q5 {, b7 t- E$ JINT        nBits = Config.sound.nBits;
  N4 X- O3 n2 {( I, l" oDWORD        dwLength = dwSize / (nBits/8);
% V1 k& h5 w0 m: N7 u. m$ K2 p6 SINT        output;% q7 j6 `) P4 J8 j
QUEUEDATA q;
$ E, S6 K4 R1 U* j0 b# ]) b1 c+ T- aDWORD        writetime;
2 E2 ?1 R4 E0 B1 ^* f0 ~: y7 x3 b# d/ k5 |
LPSHORT        pSoundBuf = m_SoundBuffer;; I! N: ]. ^) E' n
INT        nCcount = 0;
5 d- W* K2 ]6 ^, \/ n1 [( @0 l' T9 \& m" x$ g$ Y
INT        nFilterType = Config.sound.nFilterType;
- I; N8 |, B4 T3 [  F& N( E# N! ]
, C5 C* s5 F/ E! x9 _        if( !Config.sound.bEnable ) {
( V" }2 M7 C, ~- a$ t& [/ ~                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; s7 v/ j* t1 u# |  ?3 g
                return;8 Z* o3 f3 ]" e. j
        }
3 U! p2 O# A' S  \5 j
$ U9 E" K  q% @" k, N6 |) L1 y+ }! A        // Volume setup( H! [" e7 e3 t  u+ k4 O' m
        //  0:Master
* G* T- z0 |6 S6 X& g( F  S( H% @        //  1:Rectangle 1
( e8 A$ x2 q" t        //  2:Rectangle 2" Q0 w2 @* c0 D0 O7 A+ C
        //  3:Triangle
/ ]& j7 o# K- v+ H+ ]" F        //  4:Noise
0 O9 E2 \1 m7 G" X$ B6 d        //  5:DPCM
( F. U& n; s) J; Q4 E# Q. L! u        //  6:VRC6
- m6 `4 n8 S" d        //  7:VRC7+ p1 d6 e3 W7 H
        //  8:FDS
) ?( U" r! F# Q0 Y, o        //  9:MMC5
) s. W: A; c5 O2 `" K. N* I        // 10:N106; Y6 B" _7 Y) b, l' C# [2 G/ ?
        // 11:FME78 |8 f4 e- T# w8 r$ R
        INT        vol[24];3 {* E$ @& m0 U1 ?  C2 ^8 i. I
        BOOL*        bMute = m_bMute;+ ]5 R' R! v& S  U0 L
        SHORT*        nVolume = Config.sound.nVolume;
0 B3 Q2 s9 C$ Y5 I- l( ]; [
2 f% F+ }' l- S0 s0 X% a0 j  N        INT        nMasterVolume = bMute[0]?nVolume[0]:0;' x4 m0 j4 J# S! i

8 ^# j% H- G- z: H6 x2 W        // Internal5 g: I, U8 D$ J9 s8 J( k: z2 C4 \# Y
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;2 W( x2 i5 y0 ^7 M
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& r2 j" s8 S( ?( k$ x' G        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
) I; r8 C, e. p1 U+ t' H; Y0 F/ O$ _        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;7 h3 F3 E) y4 M: c
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;7 }6 f( Q7 H# E0 ?7 `$ T0 Q* [

- q3 x  i$ o! r/ u        // VRC65 S: Y+ C- v7 d% D7 Q. c4 z- n5 ~
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% ?: l7 g* j# {; ?        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 C2 p/ B, m  l1 R2 P; C        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 {* w- L7 C; p$ r) {: O# g
% ?6 k& X  }7 U3 a: ?
        // VRC7
5 M( O+ e. U8 M- d* l) E4 o        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ j* r3 u( `3 f$ O% k, r$ c  L# x( r% Q( d: m
        // FDS
% S+ q9 G9 ~+ ^, F- R$ Z        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;8 y0 E! x$ h- m% g: W
% K* P6 \* V7 g2 b8 f
        // MMC5: f& d4 J% q. }  f
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' _. Q: d- e* D) B4 F7 `5 R
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) A/ v( D& L3 f% d4 N/ O        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( o' K: E. n" `3 y! s5 d, P

- d7 U! {: V2 s. t        // N106% o' b' k9 k0 Q- {: i0 d
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 @7 w( B8 |% @. j' T0 o* ^2 n/ j        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! H  U/ C: N3 v* S& ^* h        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 N) x9 H5 i9 z. N/ f- c; m: d
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 Q5 u. p. v6 c$ o        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 F% ]5 W0 J( R2 o' ?
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 n* f& c5 o' s0 O
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ H1 |! Q4 y$ d% z: k
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 v5 k, ?7 I2 Q& z
: g* Y( b+ q% u3 I; c        // FME72 X! k- [2 t1 }0 j) }: e
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! ^7 c& a% ~9 g  ~6 X3 V        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) ~/ L& E- C6 u3 @& I0 M6 }        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. z3 {, _! R+ W# x6 L

. C  q+ o2 p% [- C+ M7 }0 b//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;+ G: U. |6 H/ ], |
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: ?, g  O! ]; G' S, w
5 E9 H0 I" n3 N& [7 I1 A2 X- R
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
' h$ K$ k2 A& V( d3 J        if( elapsed_time > nes->cpu->GetTotalCycles() ) {7 |$ b5 i8 ?3 R
                QueueFlush();
: V& l2 l' h+ m0 F& F+ x% [" Q# D        }
4 A. @3 L( m- Q, [2 f  ?
$ k  R5 t+ k! [7 V        while( dwLength-- ) {
6 N2 \* t3 M) a1 E* E, G/ ?7 @                writetime = (DWORD)elapsed_time;
1 v& l' D& {# N9 o1 b! e: _8 ?" J& U1 P
4 a- S9 v" p/ U" \/ Y# z# b                while( GetQueue( writetime, q ) ) {% F! f( W6 H$ u7 Q
                        WriteProcess( q.addr, q.data );
% n' l  P3 C% z                }! P, p  Z' U  z  j) Q

/ t3 P6 F3 h/ Q                while( GetExQueue( writetime, q ) ) {2 h! ]+ S' T1 E6 T
                        WriteExProcess( q.addr, q.data );2 p' a6 N7 }: b! g8 i4 C9 y
                }1 T: N3 o( }+ P

% T+ f1 |# [0 P: s+ o                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
; x* I# J  G4 y                output = 0;
& b& {5 |& ^2 O' V                output += internal.Process( 0 )*vol[0];% f: J  C1 a% m  j7 m0 M
                output += internal.Process( 1 )*vol[1];
. h, T% B3 H& h2 q- |2 z) d3 ~                output += internal.Process( 2 )*vol[2];
, s' e  w* A; B                output += internal.Process( 3 )*vol[3];
; O7 o7 C4 a7 \                output += internal.Process( 4 )*vol[4];
, G% e/ W. G; n- r. {  d0 n1 s
3 u: w+ V# s/ s% x2 c                if( exsound_select & 0x01 ) {* [9 X" N9 B4 m( H
                        output += vrc6.Process( 0 )*vol[5];& |# u' p1 i/ c/ w) W: N& l" Y+ c
                        output += vrc6.Process( 1 )*vol[6];
) E; A( p* w. u. l                        output += vrc6.Process( 2 )*vol[7];
+ H- A. ~$ Z% j9 s2 B$ Q+ v                }
9 [8 V. i& R0 j% z& R3 w. X: V" A3 v                if( exsound_select & 0x02 ) {
  i  W0 V- u& V                        output += vrc7.Process( 0 )*vol[8];4 G6 K5 p7 B1 f& E
                }
- h& P! G* R8 j, d+ B                if( exsound_select & 0x04 ) {
- S' n' L* ?! W* J4 Q9 H5 B6 F* g9 c, S8 D                        output += fds.Process( 0 )*vol[9];- B* v  J. I# F5 G, n( W6 R, b/ O
                }  D1 B& w& `! p$ U$ C/ r7 I( C" s0 r
                if( exsound_select & 0x08 ) {1 q& @; a6 B* t7 B7 H  X
                        output += mmc5.Process( 0 )*vol[10];! U# L! G$ O" o  w
                        output += mmc5.Process( 1 )*vol[11];  v  @3 _& V# {; X
                        output += mmc5.Process( 2 )*vol[12];
5 I+ r/ `( o2 e, Y$ ]- Q' j                }* |& }0 y: h! t4 e! O' b# e- d
                if( exsound_select & 0x10 ) {
9 c7 Y  T8 j4 J, z: _6 d9 ~) }                        output += n106.Process( 0 )*vol[13];9 O3 m) a% {6 M  ^  Z  a# J3 r
                        output += n106.Process( 1 )*vol[14];7 B7 p( S, q; {4 K7 D# D# i% ]
                        output += n106.Process( 2 )*vol[15];
" d3 T+ X7 y+ J/ ]( M+ R                        output += n106.Process( 3 )*vol[16];
- W$ C& W$ F/ i: [: E6 U                        output += n106.Process( 4 )*vol[17];
( y- p7 _5 t& f3 Z                        output += n106.Process( 5 )*vol[18];4 C! a3 t1 H( r, ]0 g* r
                        output += n106.Process( 6 )*vol[19];
9 ]# c% l* X& y( T                        output += n106.Process( 7 )*vol[20];0 v2 W8 [: [5 T# K. P3 M
                }
) T2 w! E' f+ r+ J. U2 h/ ~* f% p4 p7 D                if( exsound_select & 0x20 ) {1 c# a0 P, l: S( n. b
                        fme7.Process( 3 );        // Envelope & Noise; n9 w9 y, c% G5 t3 n3 k' t
                        output += fme7.Process( 0 )*vol[21];
+ {6 M( D6 c. w: i& r& X                        output += fme7.Process( 1 )*vol[22];, Z% \; w3 z! o- G  l9 k
                        output += fme7.Process( 2 )*vol[23];9 T/ F4 n6 R$ u5 N( n* g  \( w7 k
                }
# J/ Y$ b! U& W# y, o) L) o$ h0 k8 @/ R8 E0 ~* C
                output >>= 8;
+ g4 w9 H: w- l% @
* V0 D: i$ X$ `# f3 |+ j! l                if( nFilterType == 1 ) {/ n! q7 D' C& ~5 M5 Q
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
" `1 k) |' W7 X# p4 Q$ s/ ]3 ~4 O                        output = (lowpass_filter[0]+output)/2;3 v" ]% ?' _% h6 L- ^/ C
                        lowpass_filter[0] = output;
8 T' ?6 O& ]! x$ i& c0 }                } else if( nFilterType == 2 ) {4 G. g) c: O; G+ T0 U  T% a6 D
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1): Z$ w$ p6 |( y9 `3 n! _
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; R; @! j  S# h) Y9 C+ u, w1 U                        lowpass_filter[1] = lowpass_filter[0];- @  {* |# M+ W  W1 S
                        lowpass_filter[0] = output;& ~6 @. a6 @, I4 G3 ?
                } else if( nFilterType == 3 ) {
- k. {# ?- I$ p7 }& n" Z  c                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 P0 }+ x( ]1 J+ g9 r, T. S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; y7 d$ o% N' H9 @+ O0 |) k                        lowpass_filter[2] = lowpass_filter[1];
! i4 g  v0 q) _; F- `! b                        lowpass_filter[1] = lowpass_filter[0];
% b6 m. v# ]5 `& T9 V6 y8 {                        lowpass_filter[0] = output;
* B7 H3 T$ ^% a0 O                } else if( nFilterType == 4 ) {4 z0 G+ n- P2 I. S# D4 x
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), B6 U0 U5 R( H& f
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
- `! ?2 x& g. l3 m; Q& z                        lowpass_filter[1] = lowpass_filter[0];
! m: }+ r+ a- j4 [. m6 ~                        lowpass_filter[0] = output;7 H/ K5 y+ C2 z% v7 I# [8 z" m
                }- U' A% `. r  Z" F4 h0 p2 g. u

. h- j/ L1 g4 N4 ^#if        06 G" q' I  r5 I1 l7 b
                // DC惉暘偺僇僢僩
* q6 \; o6 L2 Y# i! I                {8 D6 M$ F: z' x* Y0 G. F2 Z0 V
                static double ave = 0.0, max=0.0, min=0.0;* [  p9 r( \, n' W
                double delta;
1 x3 p, W! I- K- k) E. X                delta = (max-min)/32768.0;
$ O2 F7 ?9 }! {) C                max -= delta;
) p. L9 |2 o& F1 j$ R$ r                min += delta;1 @' o) t0 L2 V. b
                if( output > max ) max = output;
$ b% w0 B0 Q# F" ^% u8 n                if( output < min ) min = output;$ l# f1 Z0 {) Q0 y# M' |# i
                ave -= ave/1024.0;3 O/ X& @4 }: r* l& A3 A
                ave += (max+min)/2048.0;* _3 ~. |% m+ P8 X
                output -= (INT)ave;
4 r3 K! U& e  e' J5 e' T1 |% n                }
% e* Y9 @8 W" y5 i0 V#endif  n0 E( E8 H9 v1 D8 o5 U
#if        1$ L1 {8 t9 [. v5 o0 d  z/ `
                // DC惉暘偺僇僢僩(HPF TEST)% t9 e  F: D, _% \, z) f/ U
                {6 g% k# y; c% R- E
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);' a3 a) m8 w6 G7 R0 u
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
8 a# d. e8 d, A) D3 s                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 ^) \1 i7 H$ @1 {* {                static        double        tmp = 0.0;
# i* k8 Q4 B% O) W                double        in, out;* ]* k# S# W. K" ]: ~# `
1 X/ Z  D! t" }7 U( F" q
                in = (double)output;" K& v( d, J' F, H
                out = (in - tmp);" l: P+ N- O4 `1 e3 P9 I  q6 t$ y
                tmp = tmp + cutoff * out;
: F& Y+ S$ |% ]" H* F
9 U  J: B1 k. W6 h0 r                output = (INT)out;* y& z& Z) e4 x, ?
                }
. y6 v8 ]: K# A5 h( P#endif
: `7 o' Y: U3 R3 E# \* G+ p, Y) V#if        0& Q9 M7 R/ w- ~* l
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 J5 E3 K  x6 a( t5 h                {/ Z) [' l$ r; {$ w3 M7 K$ J# M- a" k5 m
                INT        diff = abs(output-last_data);' B2 m0 J% s2 }4 @! c) q' J4 N* s
                if( diff > 0x4000 ) {
) ?0 f4 {+ O+ ]" m) S8 o. \                        output /= 4;
: B% O. w1 Y1 _5 b! x! o+ Z                } else
& P0 i5 e2 Q4 D" Q, D                if( diff > 0x3000 ) {
6 e% _; t3 m7 f9 D5 b                        output /= 3;
: A/ S- P3 C2 i/ g7 X' M9 @                } else
* E7 z9 {$ [; o( e" n7 M$ ]+ u- P9 V                if( diff > 0x2000 ) {
1 G/ e( z8 H$ c' F5 N- _7 l, Q                        output /= 2;
( n& [# i+ B% s4 w5 q) ?5 P% F                }
, L+ C. \1 h! Y                last_data = output;
2 d; e7 |6 n/ {. y. r" L7 v. g2 A                }
; Z  e8 w* M6 z  ^. t#endif2 f$ E6 h% q( v& p9 }' @
                // Limit. t2 v$ o. R+ e
                if( output > 0x7FFF ) {
' K  e& B7 [/ ?! s5 j. z. V. h                        output = 0x7FFF;8 h* r$ G7 D: a6 }- Q  n, W$ U
                } else if( output < -0x8000 ) {# Z+ Y* b2 L' y+ b# V
                        output = -0x8000;
. L. N0 \+ O# p/ v" M7 |$ r                }
$ `9 I- _' k3 O' K* T1 b; D: H' @& h, U  A, _" u$ H; y- z
                if( nBits != 8 ) {
, T( e$ ^0 A% d1 D* z! U                        *(SHORT*)lpBuffer = (SHORT)output;' c3 q3 q! g! g' v: J
                        lpBuffer += sizeof(SHORT);
$ _5 k# M) P  }+ W                } else {! @9 y' s' d0 i$ s! d6 u
                        *lpBuffer++ = (output>>8)^0x80;
2 D/ p/ g/ N' f" n                }/ t8 E' E! E2 F4 D4 \- y/ y+ a; z
. E; n" X9 X: j5 F* ?  o" ~6 I% J
                if( nCcount < 0x0100 )
  `6 n* ?5 L+ T/ F( y) f1 B- i, k                        pSoundBuf[nCcount++] = (SHORT)output;. \1 a  b& ~6 c1 l; Z7 {

" O1 }. B$ h! t5 V' v# `5 i//                elapsedtime += cycle_rate;
+ \- ^8 p* j2 w6 E' s" v                elapsed_time += cycle_rate;3 Q9 V# J- J: D, t( v& y) ]
        }1 o0 {" r/ ]9 P% Y9 [: Z6 q- [

/ v/ l5 P3 _/ s) i) c$ o  C+ I! p#if        1
$ i/ ~2 C& |* x$ V  x        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: b) Y5 Q4 t- n
                elapsed_time = nes->cpu->GetTotalCycles();
/ }9 Y1 A% N& z$ X) f" f        }
5 T+ M+ P* B7 P1 K        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {" V: I7 _$ K( @
                elapsed_time = nes->cpu->GetTotalCycles();
$ q- h: l. P: w/ N' i; r        }
5 n% A+ g; u: ^* }: S#else
: F  ~. r) m! T+ n1 {3 Y7 x! B# N        elapsed_time = nes->cpu->GetTotalCycles();/ Y# g6 e+ i) W7 [7 V
#endif
& A3 s5 o3 H) n1 Y}; e; [: L6 \& Q/ n' e2 k

& i* D7 C' ~+ _+ z// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 Y8 [" h& j8 q" O" j0 i( e
INT        APU::GetChannelFrequency( INT no )
* _5 ^: u. {$ M  l+ F1 s{
2 C! d+ q* x0 G9 B        if( !m_bMute[0] )
8 D( A% F3 [+ u7 b; E. ?: d                return        0;! S- j$ L% Y: f  D8 k2 h, P4 ?

: t# R+ S) N  T4 R* n        // Internal! q0 P( \9 M2 I" g9 N: j
        if( no < 5 ) {
! o+ z: Y, [; B  k                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- r: A# l/ Y' ?! `8 ~        }
# V, S3 u# _; T8 _8 u0 c        // VRC6
1 c5 a4 ?& }2 N( ~  S! }! A' R        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {. I4 H4 _! B! b9 }7 |8 {' Z
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
5 j2 ]0 z; E6 d) l        }) K  ~. t5 N  d% V5 s  ^" _; S4 C0 }( |! D
        // FDS
# g$ m- ~4 l3 v6 b5 F% E8 Q        if( (exsound_select & 0x04) && no == 0x300 ) {* h8 T* T8 h% }
                return        m_bMute[6]?fds.GetFreq( 0 ):0;. s- s" y8 @# u
        }" A! q9 U  u0 i0 d3 M
        // MMC5
' Y. k" J# S/ P4 M! a        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
! ~4 z+ ?: |0 j& d3 b. f                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
/ G4 h  [# Z/ E: @4 @% d        }. S" g4 A8 Z9 y3 b. o, I
        // N106' Y# ^2 e$ ?$ v* U; n' `- K
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
- i% ?  R  h8 j3 m+ J8 w                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;) q% W; H7 n# d
        }1 ^& z  b0 v" z+ t
        // FME7
7 o. [2 f8 ~, R8 x        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {" R/ {/ @5 ^+ k2 S0 J% B
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
) J: S5 v( `8 h' @        }# k7 r0 ~" j- E
        // VRC7+ h8 I. O( i% p- \4 e) c/ [+ ~
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 Y7 m4 l9 e! i" u0 G! g                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; M& }5 K# `! _
        }
! M3 z1 A* N( J6 B7 D        return        0;
0 h8 _7 {0 E6 U- |}
  p. a/ x0 O6 @1 h  I2 V+ {3 t% Z4 S/ F; }' m
// State Save/Load
: n# ~1 b- a. u8 v4 Vvoid        APU::SaveState( LPBYTE p )
3 B7 B; S" V# w. }  W{
2 [; Y3 U. t& k2 g+ W9 S#ifdef        _DEBUG/ u3 K1 z7 L* W* u& o& a
LPBYTE        pold = p;
" g0 V/ ~4 H8 s#endif
& z" m8 F4 R3 W/ P' o9 o  {' N3 Z7 ?: c; k
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞& M! p% g/ U0 Z  @/ u! e. y
        QueueFlush();
1 ~( W, X' Z/ I: C0 k& Z# E
( g; E& F/ T2 O! e. P; _4 o        internal.SaveState( p );2 y+ z% {& i4 @
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 ?1 b/ t1 d5 }/ S  n: h! g# G8 [) j$ m9 x6 ^. i
        // VRC6
! o7 `# y2 |! B; |        if( exsound_select & 0x01 ) {
' G1 ?# P5 r3 f; _                vrc6.SaveState( p );
, M) L# F8 O! [1 C& g- z& H                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding& W) [1 g* v2 O  H9 L1 G4 C
        }% |$ H; i8 L- p5 t2 x" H3 A" E- j
        // VRC7 (not support)- L" M) G2 {2 B, G" x
        if( exsound_select & 0x02 ) {! p5 S5 W7 f, y9 J6 _
                vrc7.SaveState( p );: V* `9 R! S8 C. d; v3 @" L
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ ~4 j, l. T. o* O8 w4 q7 M0 y" V        }8 ?$ Q& }; @8 h9 ^* X8 R
        // FDS
( _1 W- w' e( I) w        if( exsound_select & 0x04 ) {
  ]* G  r- V- s: _( B0 v                fds.SaveState( p );! p' ?- y* f  W+ O% ]9 T- ~
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' J7 y8 I7 f6 ]6 h9 L+ N        }9 P) z3 u1 g  d) c9 D4 o# u0 V8 T
        // MMC59 u0 s1 [. R$ ~3 {
        if( exsound_select & 0x08 ) {7 q9 X: i8 r1 E
                mmc5.SaveState( p );
: y4 f8 ]. D: B# s0 X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: \2 q4 h7 ~1 E
        }
  }) r7 A7 q4 \, g        // N106
7 R9 T3 E# T, Y$ r! q/ w        if( exsound_select & 0x10 ) {1 u5 }0 \% \/ b' g" k
                n106.SaveState( p );
2 R' o, @& ]  O' g: w  y# Z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( @6 z/ B2 O+ d1 P/ c        }
+ H9 I4 i0 Z" h, E# G+ `# o& e        // FME78 |+ V( `$ z" U4 S; k" Q2 L
        if( exsound_select & 0x20 ) {
+ B0 {8 y$ C; F4 Q  B                fme7.SaveState( p );! H4 i% Y7 G4 \, T0 ~" P
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) g" ]+ ^; R8 r1 p# _$ K        }& k( U/ G9 S7 ~9 y$ f" N) X8 F
0 Z- r! ^  f% W! y8 l+ u1 }
#ifdef        _DEBUG* B( C0 _# y6 V6 Y6 M
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );# N- a1 t; }7 G6 S! r# Y7 G) H
#endif
0 D( J: ^, J# O+ M9 P+ y}
8 k: H- |! d1 v& F% X1 g6 ~- \) V( p, d4 o8 A4 `8 J( Q! |
void        APU::LoadState( LPBYTE p )
' }8 {* {; @5 ?, d/ n% u{
! h5 o& V8 b. v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
# r6 r/ A! N! w; j% d8 p5 @. E        QueueClear();
& y. a: F6 h8 i2 B; ]3 K; T. c5 h5 L* f/ o' q  u% w
        internal.LoadState( p );5 ~" h" y5 F! B6 g: N
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 e% i2 ^$ C' e  @  @( p9 w/ `8 g$ P/ n  e7 l* G" ?2 }/ \1 C
        // VRC64 g, i9 r6 L' k8 s* z
        if( exsound_select & 0x01 ) {9 A6 h3 d  L& D: K1 d8 l
                vrc6.LoadState( p );! Y' M' s  k& _% J
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 I( i# ~. x( D1 ^3 @/ j
        }5 U6 E; X# o- L, W* T3 T
        // VRC7 (not support)4 I2 \  N9 m9 h4 t1 N- t8 H
        if( exsound_select & 0x02 ) {
2 I& n. {' R. }7 z1 g                vrc7.LoadState( p );# j3 O$ ^) w5 X3 p8 S
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! Y# |7 b1 M& G  S, T& X5 I+ V5 k7 c0 S        }
/ V5 B( T% s+ M" W  I        // FDS
: E( s1 ~$ }- P: T6 z        if( exsound_select & 0x04 ) {
9 A: b. m: J- u2 X- B" l                fds.LoadState( p );
8 E8 E; y* ~! F& c) N3 ?                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 X- T- B4 ?& X6 t  n: P
        }
' ~5 m8 n0 M  a        // MMC5% P+ t" M% H: G. {$ O% Z4 U, }
        if( exsound_select & 0x08 ) {
1 c# S; Y+ R, l2 ?                mmc5.LoadState( p );
2 ^  @2 V# B+ @& Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 W# R& R! P- C
        }- v8 ~# z! J7 F7 c+ u* f- _' ^, L) H
        // N106
, w  h& s3 J, M$ J* m* H( w        if( exsound_select & 0x10 ) {
! s( E) C+ D3 F5 k7 M8 Z' C                n106.LoadState( p );
# o# Y+ L# u# B" b/ |1 h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. D9 u9 N! K0 S3 z' g6 r4 [+ Q        }
/ i4 ^( a2 j5 N! b6 L$ U        // FME7+ z7 ]5 c7 k4 Z' b
        if( exsound_select & 0x20 ) {
% i# f( x* [/ U7 k0 p                fme7.LoadState( p );
6 u6 \( d& I4 k) S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
. w( Z- R% |0 N" }" l3 ^, S7 d* b& x        }
) K2 y6 u, L3 J) k- h. f}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
- @* y, B& k- I1 J# x6 b可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! p7 ]' L' l8 V, v" y
感激不尽~~

3 d2 t5 q/ e0 x* E1 I2 e恩 我對模擬器不是很有研究,
5 R; ^- a& c! T  Z0 r, @- f1 ~雖然要了解源碼內容,可能不是很困難,' Z8 L! B% J) K1 _4 d
不過還是要花時間,個人目前蠻忙碌的。8 _, t1 B. I( F0 r# j3 n1 B

' t: G% g; ^* Q4 o給你一個朋友的MSN,你可以跟他討論看看,- F: f) t, a' E+ G- v, _- j" a: z
他本身是程式設計師,也對FC模擬器很有興趣。
( P7 N( x# h8 ?1 y! G1 _- R& D) b/ j1 |/ I% d0 F8 \8 r
MSN我就PM到你的信箱了。* p) k, ~7 {" s7 r$ V

1 H! A/ Z1 {& V. R9 k% ^7 s希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
8 q9 G  |' @1 N6 y) m% A0 |1 p呵…… 谢过团长大人~~
4 a1 T/ \/ g$ g& D( ^9 H! e
7 Y  h0 v8 C" x5 l
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 $ E/ |; M5 R. ?0 B/ z- W  M
团长的朋友都是神,那团长就是神的boss。

( K, a& c- g6 p$ H, j哈 不敢當,我只是個平凡人,1 c9 U% l: L4 y/ O
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
' w. j7 T; [+ r3 e5 k- kZYH9 P8 ^4 i  {9 x5 K/ H
QQ:4147343065 [( k7 h3 p1 u! P/ S
Mail:zyh-01@126.com! h' X0 \2 N2 ]! ], W4 g) N0 p- _

$ H! `( A" \5 m7 d+ f5 ~他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 4 q( w) W: v8 a' Q- d6 C
再次对团长大人和悠悠哥的无私帮助表示感谢~~

. N0 t$ _/ G3 w( ], t% U) w4 s& \不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-8 12:14 , Processed in 1.072266 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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