EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, ~% d; p4 h; }) W" u& _; D% }  V* ?
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~# v! M( u7 |0 ]& _. r; v
这里有相应的模拟器源码,就当送给大侠了~~; @) F# U0 q$ s! z
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 5 h2 Q' A' `& F( T1 H
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。4 |) p& [( o/ F6 @
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  u' f- `0 m* f) g* |+ m这里有相应的模拟器源码,就当送给大侠 ...

+ F# L- x% M9 Y) a聲音部分(Audoi Process Unit = APU):
  r2 k0 ?9 O4 k2 D.\NES\APU.cpp
$ E% h% l8 J3 A$ j' z.\NES\APU.h
" b2 \- G5 ], J/ ?4 g2 ^' ~. k( Z$ k2 m( S6 S
4 D1 O0 X: Z) X' A/ a; ~
影像處理部份(Picture Processing Unit = PPU):) q* K6 l+ T9 v7 g0 l1 ~
.\NES\PPU.cpp* b3 Y* a% K. ~
.\NES\PPU.h. ?# {9 J$ N/ q' c( h
) L$ w( e3 F- p! h. F! s
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 u$ S9 k+ [+ b" J(由于很多专用术语和算法机理都不明白,所以看不大懂……)
5 a9 H, B7 s" I( T- X$ S//////////////////////////////////////////////////////////////////////////
9 M0 J4 g  [" a. _' |0 M2 F//                                                                      //
5 \6 B! U7 C8 P9 V//      NES APU core                                                    //4 A$ D4 N4 y0 ^2 N
//                                                           Norix      //
# B: n( k& O( k3 L% q! S4 @. h//                                               written     2002/06/27 //
0 I4 D0 W$ Z" }% Q, W//                                               last modify ----/--/-- //
+ V$ t8 A7 T& v- E" |* R8 H//////////////////////////////////////////////////////////////////////////# m$ K9 Y1 i: G& M# n
#include "DebugOut.h"+ L1 P" Z8 V, o6 _* Y
#include "App.h"
; H; \' S2 Q9 f4 U$ F#include "Config.h"
% ?9 r8 }4 @( S, `7 C! g* z: H3 r7 O% p  ^8 j# Z* z
#include "nes.h"/ B7 Q. A' U% X! X- E3 _# h, c
#include "mmu.h"
4 l8 ]- M8 J; X2 D& C1 g5 K5 d# w. o#include "cpu.h"
& T- w5 [2 Z: N* O2 }  J9 y$ S6 e#include "ppu.h"
: s' p4 B5 S# R#include "rom.h"
! k6 R8 B/ u: Q2 A6 v1 S' y! \1 I#include "apu.h"
  c( t+ c8 o3 g1 q* j$ C4 u6 n
% X  T) ~  B; j// Volume adjust
% _3 a( X9 k1 e5 m// Internal sounds
0 G# n) e! Y& H+ d  Z#define        RECTANGLE_VOL        (0x0F0)4 v# k# {: @0 {* }, n
#define        TRIANGLE_VOL        (0x130)
2 k! U' m1 W$ n$ x- d9 [% Q! @; V#define        NOISE_VOL        (0x0C0): c( o& Z4 g: V$ D% a  `% K
#define        DPCM_VOL        (0x0F0)/ y  p* g6 j+ f: |8 ]
// Extra sounds
% N; v4 H4 U$ L+ f  A. a9 L2 K#define        VRC6_VOL        (0x0F0)
* V0 \4 n7 ?# r* H#define        VRC7_VOL        (0x130)9 k* }4 R# f3 S; f: Q6 K
#define        FDS_VOL                (0x0F0); o& [- Y3 ?4 v
#define        MMC5_VOL        (0x0F0)$ k2 y# d( R5 W& F
#define        N106_VOL        (0x088), _: P1 l3 q) B4 q; R
#define        FME7_VOL        (0x130)4 R% y6 _* G- M/ y" r
) A& E3 k1 t/ Y# y7 B
APU::APU( NES* parent )
: j6 e  N6 o3 m{
5 A1 t# d- F" P! X# |, R        exsound_select = 0;
; i' _" ?8 @1 r. s: X4 `1 J  W. e2 h- E& z; A7 u0 V
        nes = parent;
) ?2 [* `  Z! I" y) P        internal.SetParent( parent );) r* Q/ X& [2 D
* A5 M* I5 D+ [& x3 T& d
        last_data = last_diff = 0;
+ K) e; G' X! o0 w2 _, Y8 e" `" G8 F# _+ ?; `
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 t4 d/ o# Z8 N8 _8 I0 U+ q7 M7 V
( U4 q! o' z6 n# h# E
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );3 J1 Q& k4 [2 j) G/ a
        ZEROMEMORY( &queue, sizeof(queue) );2 }$ D# P, _' P, J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 k1 ^( Y  U. y8 G% c  F- A) Q1 B% J8 C4 w7 X
        for( INT i = 0; i < 16; i++ ) {
( H# R' A/ ?. M) H( ?) ?' f0 w& ~                m_bMute = TRUE;
2 e' ~! V( ~( A6 i- Z$ q        }5 b! D) N% H5 X' s& g3 W, L
}+ [5 ~& n: h/ w6 H  h  h

& z2 R! {! }- p: R+ }! bAPU::~APU()
: v7 r- i' o: c. g  s, s: S  z{
4 L$ ^  p" L: I. ^3 O) u. b}, N5 b  P  r+ l1 O: b% w5 v. _9 i% i

' L/ z2 V1 @7 ]- S4 N( T# Mvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 z' z" w4 G; ^, J
{/ h, j+ g% G' n( s! k! L/ |
        queue.data[queue.wrptr].time = writetime;7 S3 |% X+ U) j8 [
        queue.data[queue.wrptr].addr = addr;: l5 T  r4 h- Z' @, O
        queue.data[queue.wrptr].data = data;
- a, Q8 R' \6 J% H        queue.wrptr++;! e3 o9 q, B7 U) \& m" B2 N2 g
        queue.wrptr&=QUEUE_LENGTH-1;
2 o- e% U" x1 V9 T  V        if( queue.wrptr == queue.rdptr ) {
. @/ G0 t( w. A1 q' j                DEBUGOUT( "queue overflow.\n" );+ g" l: L1 T; F9 F% J& c; c
        }: y4 u7 T+ e, Z$ k; b2 ~
}5 v; s: W, O* y4 V* @2 N

- Z8 v, W7 H6 b8 v# n' D+ ~BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
% R8 w5 z, g4 l) c) y; O; F{! m/ U/ S! a/ {/ F
        if( queue.wrptr == queue.rdptr ) {9 y" W2 B! l$ w
                return        FALSE;
% |1 g, g- p& A- f3 S. w6 C' z! r        }+ A0 W, n" ^: }, R
        if( queue.data[queue.rdptr].time <= writetime ) {
$ I, s7 h1 S& H3 y! F; E                ret = queue.data[queue.rdptr];
  N- b6 t- ^# {/ ]                queue.rdptr++;
9 [# }* h! x; u3 j7 _* ]( K                queue.rdptr&=QUEUE_LENGTH-1;/ d) a- }, I) ^0 j
                return        TRUE;& }4 _$ w8 |+ w6 U: O: n
        }. c7 o3 j" N7 N0 B8 X1 Y% G: R
        return        FALSE;  R* P" N# u0 W7 h* ~+ ?
}: ^3 i, D( w6 z0 y
/ @6 ], X+ Y" c( G+ \
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )1 P3 B% v/ B( B+ E" k4 L9 c
{- ?* a3 ^. {" [% X9 [' M
        exqueue.data[exqueue.wrptr].time = writetime;
, i+ M! z- q: k$ D9 h/ J        exqueue.data[exqueue.wrptr].addr = addr;% C/ j4 d  T6 ^0 V  z
        exqueue.data[exqueue.wrptr].data = data;
& A! O2 r: q1 z( ~3 V4 K( H* s        exqueue.wrptr++;
4 P, p  w, o1 ^* ^$ ^        exqueue.wrptr&=QUEUE_LENGTH-1;
: D4 U& ?- }' r; q+ f        if( exqueue.wrptr == exqueue.rdptr ) {
2 ^* G5 y5 P$ j/ e: F9 J! j                DEBUGOUT( "exqueue overflow.\n" );- r  `4 ?: P8 y7 Z' s/ \* O3 _
        }
* C8 a; [+ a' P& k) F) ^}
; G5 C4 r! C4 }' R+ ]% @8 I; r* D4 q, S& ^
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )" Y0 D9 @/ w4 n# @8 D
{
  X+ B- X4 o3 D6 e) S. C" b( ~7 W        if( exqueue.wrptr == exqueue.rdptr ) {
! X! d( Q8 q- T( D3 a) ]  K                return        FALSE;4 W+ W8 f" C) Z6 C4 ?3 W3 U! _/ C
        }
6 t# [5 y, P! {( p/ j0 M! C! N) m        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# B; n/ g& o) \# {- E
                ret = exqueue.data[exqueue.rdptr];: A* n0 o, R/ z
                exqueue.rdptr++;
6 G5 O2 K& b; \6 D0 J) H                exqueue.rdptr&=QUEUE_LENGTH-1;0 z/ T1 W9 K7 i5 }+ R
                return        TRUE;& f6 L  J  E& ^$ N
        }
& s- `. @% i  ]- b        return        FALSE;
1 S- J2 j- W. I7 L* C* j}
: m: m$ H( M# ~+ ~9 ]2 U0 ~
! J) P4 Z/ Z5 b# dvoid        APU::QueueClear()' _1 n- {8 E1 c. J( R; l6 T0 ?
{
% |! U% o" v) B) E2 F        ZEROMEMORY( &queue, sizeof(queue) );5 W" C; ]6 ~; k0 p
        ZEROMEMORY( &exqueue, sizeof(exqueue) );" Z. {  x7 `: z% E$ J9 A; M
}1 A% E( S& h6 N! a. z
3 r7 ?% r# r: p" Y& j$ M$ `
void        APU::QueueFlush()
" P% [! c) J" k; O6 n2 T" }{4 ^' {* ^5 ^* {% J# N
        while( queue.wrptr != queue.rdptr ) {
1 M  k# V' m! F, P7 q                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
9 r  b9 H, X7 [0 `" L% P                queue.rdptr++;' H9 V0 K  w7 j+ |
                queue.rdptr&=QUEUE_LENGTH-1;1 q" f- l  D4 M& t* w
        }
( U; u7 x3 u! k& Z2 r
. U2 }4 H+ f& I  J        while( exqueue.wrptr != exqueue.rdptr ) {; X8 s$ U7 K: W4 Z1 a: x/ P8 g4 @# r
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
- }! U2 p! _4 u/ V                exqueue.rdptr++;
* ?9 j& F  b8 N5 E, T+ Z+ T                exqueue.rdptr&=QUEUE_LENGTH-1;) W8 U1 f2 R2 r
        }
7 |+ _' ^- F3 K; O}
: S6 s) [( L7 w4 ]" m3 m8 K4 k- p5 l; g8 D  F& l' q
void        APU::SoundSetup()1 y# f! @, E& h+ h  @9 v# B
{
8 k, D! r& ]1 I5 i. e$ t        FLOAT        fClock = nes->nescfg->CpuClock;
1 J6 D' T5 w, T: C        INT        nRate = (INT)Config.sound.nRate;
6 ^) X" G- V( L; u  {        internal.Setup( fClock, nRate );6 _& R; L; {! J6 i( b" a0 p! Z' w
        vrc6.Setup( fClock, nRate );
  g+ x/ j) T+ ^% `. N        vrc7.Setup( fClock, nRate );
1 b2 n' ~* L$ G: p( Q        mmc5.Setup( fClock, nRate );) w# @# u7 }; _6 l6 C
        fds.Setup ( fClock, nRate );& S( z4 a7 D0 b1 {
        n106.Setup( fClock, nRate );, U* S6 }4 }% [0 C
        fme7.Setup( fClock, nRate );
% R& _  j" M. _3 E9 ~, A, B}& P# l5 `) f9 s
9 m7 m& a" x. D# Z
void        APU::Reset()
$ A! l8 B  c4 R& g( c3 T{
0 s5 v: }; s; R9 O1 n9 ~' s  @4 f- C        ZEROMEMORY( &queue, sizeof(queue) );
3 G1 x, ]+ {# X4 c" H' P        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- r& \+ U% L: q! ]* @" Y& [" N4 l: s
        elapsed_time = 0;0 d, [% {& P2 G
1 o8 l3 _& Y' Q. R& e
        FLOAT        fClock = nes->nescfg->CpuClock;
' N- v7 V$ M9 G7 k7 X5 Z- a        INT        nRate = (INT)Config.sound.nRate;& T0 H5 N8 c$ y+ p( P$ l
        internal.Reset( fClock, nRate );
0 z% g4 w, _* p  M$ c4 k. P        vrc6.Reset( fClock, nRate );  U* ?* v" }6 E' {$ h, ^' X
        vrc7.Reset( fClock, nRate );
# r& x. P8 a6 P! _7 _/ g0 p6 Y' V# }        mmc5.Reset( fClock, nRate );- Q) t; f7 B( t* k% x  S
        fds.Reset ( fClock, nRate );
( B2 }8 Q* e# r2 N, Y        n106.Reset( fClock, nRate );
- A2 [- f( F4 @! F& V. m1 f        fme7.Reset( fClock, nRate );
% H. @! ^: O* W- _+ Q
4 _1 b, |3 S- A. Z, ?" ~, R        SoundSetup();
8 `) o# ]4 o% `% n" U}( T4 c6 w; C/ H8 H
7 f$ V) v8 {' i( O! T& ~% X( T
void        APU::SelectExSound( BYTE data )
7 y& ?  O9 d' d  S, d, N{
- D. j2 F9 r+ _0 |        exsound_select = data;/ P9 o0 q6 x% O/ M, y
}
# a8 ~! c) Y1 H/ K% s5 ?/ S" I$ D* c. B) b# I$ w& L
BYTE        APU::Read( WORD addr )
6 v. e8 O- R* Q6 M3 T$ s) [{
2 q- m- ~/ o( W/ {! O        return        internal.SyncRead( addr );! a5 Z: u; U, _, b$ ~% X; [
}5 S+ ?: v% I; g

- k: |2 n: y! v1 vvoid        APU::Write( WORD addr, BYTE data )
; K/ h' n( m/ i/ f8 P  s{
% I$ i* i& v8 M, K. Y        // $4018偼VirtuaNES屌桳億乕僩
7 \* `# e# r. y8 t        if( addr >= 0x4000 && addr <= 0x401F ) {
1 Y1 V, y! I! `0 W1 ~1 T- q; x                internal.SyncWrite( addr, data );
( P9 o! `7 P$ \& p. V9 b                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
2 d$ y; Z, A7 O/ Q5 E6 d2 `' P) C        }* d1 q* i5 {* n$ R$ y  q
}
- w2 }% @6 H* l4 F. j) |- _& B8 }. V: w
BYTE        APU::ExRead( WORD addr )) T! e* t+ z6 {* J) d0 H
{
" S4 p* l0 m& R. QBYTE        data = 0;
3 p: a: M5 Z9 v; w3 Z3 w! H+ ^6 m; w% O" K* i; ~( e" I2 Z2 }
        if( exsound_select & 0x10 ) {- _/ u0 H; x+ E5 a+ d1 @
                if( addr == 0x4800 ) {
  c- S5 V; m. p                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. m2 t, O' P' |4 Z8 _0 Z                }
) r; [6 s9 T+ v1 t2 \        }
0 ^% V2 ~# M! p) _8 B+ b- S# h        if( exsound_select & 0x04 ) {, N& Y6 ^' R6 H
                if( addr >= 0x4040 && addr < 0x4100 ) {
" c- T) t, B: d                        data = fds.SyncRead( addr );) I1 d0 S- g6 a0 ]9 v  ~8 v
                }
" r! A! z  X( D1 h        }7 n* `7 P9 @% p* L5 I5 g
        if( exsound_select & 0x08 ) {
3 h, }( R  S$ U" c0 `0 S7 O. h0 K9 e4 ]                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 B1 w6 K  ~- T* f  q" i                        data = mmc5.SyncRead( addr );5 Y  t5 ^! Y& h0 `2 C; h- b
                }; M7 X; p2 \. f, S' L; v8 ]5 p& ?5 \
        }
  W$ {) z' b+ J5 t) B# |) w/ m6 P7 K/ }5 _4 O
        return        data;7 [$ A+ r& `- G. B
}
* }9 w6 N/ L: Z6 A' B( |! v5 K- R
void        APU::ExWrite( WORD addr, BYTE data )
9 N1 M' o# {7 B+ v{
3 `! y- J% }7 D0 K% i5 j! S        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 Y+ P( u1 q- P3 E- g

* s  M2 j; |4 M2 i        if( exsound_select & 0x04 ) {# e2 c! e# X5 N6 S0 M7 n/ \0 W# x3 @
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 g0 |$ b0 [3 Z8 c0 Y                        fds.SyncWrite( addr, data );
' O8 R) t" b8 u8 \1 L                }3 H" I& B& _2 F: M0 n7 G
        }
/ d- l; @1 o9 `$ `+ Z1 W0 x3 J; u' W  V, m
        if( exsound_select & 0x08 ) {* D% c$ S6 M" }% p
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' F, {3 I! a" j3 L$ S' Q+ Z                        mmc5.SyncWrite( addr, data );
) d/ o6 D( j( L/ k, @5 E6 z                }6 g# k7 I7 o- N
        }
; u7 ^* f7 M4 k/ w9 h1 l0 m; @2 O}
* w. S' |0 S1 d- i4 P6 Z: d+ b: Q  ]# _- l# y5 `, U
void        APU::Sync()1 B8 N, d1 y/ M& r* t5 ^$ v4 U
{( _$ |. n$ b5 g# l# C3 w7 F/ w
}
+ t! ?* ~0 {- S  O3 K+ h% n+ Z. {5 m& e5 C* x% w; `
void        APU::SyncDPCM( INT cycles )
+ J/ k5 w. N  J6 D# p1 y! z{2 W+ Q' |! r& u/ Y. V3 p2 F/ B
        internal.Sync( cycles );
5 v! q& ?+ V1 k* {$ F' x$ N8 R% Z- w/ f! }6 z. c
        if( exsound_select & 0x04 ) {
# A: Q9 ]0 Z( w# P3 q4 ~0 r                fds.Sync( cycles );! }/ b8 q+ w* L( d5 Z6 T' M
        }
2 G  W5 f( H) L1 M        if( exsound_select & 0x08 ) {( W$ [) U3 J& r* s* _' V. n
                mmc5.Sync( cycles );
) Z2 V) }6 x* }+ F1 @, S        }
5 i0 x. c. t' G6 m/ v2 z}
+ }0 u8 w+ y! k+ ?) D
, Q6 [" X9 t  y0 Cvoid        APU::WriteProcess( WORD addr, BYTE data )
' G, Y7 ?7 t. p{) S4 S% c2 e; L* P0 L% i
        // $4018偼VirtuaNES屌桳億乕僩9 k9 u# b# a+ {7 L7 b
        if( addr >= 0x4000 && addr <= 0x401F ) {! j! a# F4 |( f+ j
                internal.Write( addr, data );, [  }- ~! Z0 ^* Q
        }
1 {7 Q0 B/ M" L: F4 A+ C}
( z0 Y* V4 }) E  X4 a
0 X: A+ I( \6 o, ]- I; p" Pvoid        APU::WriteExProcess( WORD addr, BYTE data )
, d) q1 w) A6 H; j{
8 ]1 @( E" e5 J; W7 l1 H        if( exsound_select & 0x01 ) {
8 B! N( l4 ^  f                vrc6.Write( addr, data );1 W. x6 |5 W' }: x# Q
        }
0 E* `; E! f$ F) E( f: A        if( exsound_select & 0x02 ) {1 @( f0 l+ L, \7 t' o% q7 f
                vrc7.Write( addr, data );" B6 F- C; S; t/ o
        }
& v6 W( u9 ]# g% z7 }+ w        if( exsound_select & 0x04 ) {  m) l9 ]2 {! h9 d" ]
                fds.Write( addr, data );# N9 v& v. q6 \! i
        }- @% R  Y0 P! D
        if( exsound_select & 0x08 ) {0 L$ b4 f& s( t% G1 Y
                mmc5.Write( addr, data );
# a( w: j) `6 ]/ ~( P% N5 A8 `        }
' z; z1 u3 T! k) j( n2 q% u        if( exsound_select & 0x10 ) {8 s2 `5 Q1 G5 ?4 E
                if( addr == 0x0000 ) {/ j% [7 u8 q4 \( Y9 c
                        BYTE        dummy = n106.Read( addr );
9 Z" h$ h) _9 C: u1 r: I) b                } else {
7 Y/ u- b$ ]; C; ]  _) S" G                        n106.Write( addr, data );
: i0 K1 Z6 U+ q3 i; X                }% P0 @$ j$ p8 {  U
        }
8 a4 u1 i* z# H$ n, e9 ?1 y1 S        if( exsound_select & 0x20 ) {* i& v7 T: V- E/ y8 w* t. Y- {& ~
                fme7.Write( addr, data );
0 I0 K/ t/ V# X. V+ H        }
* G/ _* b8 Q9 A7 W% S}! w: R% M: y) Y+ H0 Z- l% ]

9 b. k- S7 U& y' J5 K3 Hvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
7 \( M5 w0 x& i; Q' x0 t{
0 ?8 _& m. ^! M( C% a9 H; EINT        nBits = Config.sound.nBits;# v+ c  b8 J5 k1 c
DWORD        dwLength = dwSize / (nBits/8);, D" [1 A$ [* D9 r9 M6 }) W
INT        output;: J/ r9 u: L4 X3 F; S
QUEUEDATA q;
/ T. v4 V' c" |3 z/ k! V' eDWORD        writetime;, F0 o/ H3 ]% @

! W# D8 r6 ~- J2 B0 a1 PLPSHORT        pSoundBuf = m_SoundBuffer;
; u9 ?/ S/ G! E* H2 O/ m6 bINT        nCcount = 0;
) t2 ]. P; {7 o5 [3 A- y7 F* ]" K3 q% u8 G7 j. h5 {! j# }
INT        nFilterType = Config.sound.nFilterType;
& H: m: }% N4 v7 a; d2 D' u1 b! v' |6 h0 p' J
        if( !Config.sound.bEnable ) {
  i% c3 d+ D3 |                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );% e" f; \2 }( n0 V& l. k
                return;
0 c. G% e$ @% v( P& M7 F- [        }
4 R8 U/ ~7 e( n' S4 _
" h+ {4 c& W: w' k4 h2 c8 c" M- R% s5 G        // Volume setup
0 P2 _  V) T3 ~+ [1 l, o        //  0:Master; h( P" f8 w' X- ]9 f7 e
        //  1:Rectangle 1
4 J8 J& D1 u( ^        //  2:Rectangle 2
* ^' B* {$ E7 {3 L        //  3:Triangle
2 F1 }9 t; C% F, }% i        //  4:Noise
0 J, {3 r: e. P& {+ Y        //  5:DPCM" ^. H9 D+ A, O0 `0 c# U+ |% v" I
        //  6:VRC6
  L* h" X7 X( a2 a( c        //  7:VRC76 F9 b7 U. _4 i$ T
        //  8:FDS4 J1 {$ H3 f. @6 I
        //  9:MMC5
$ z# Y: `5 L; r! N        // 10:N1064 F- [1 m' U- J7 @
        // 11:FME7
: d! O: m7 R  ^- _0 m  k; g        INT        vol[24];$ F6 C1 l, C! S& Y- q7 K$ u4 c
        BOOL*        bMute = m_bMute;+ h; T' t; z& M& M/ h' N# v& |
        SHORT*        nVolume = Config.sound.nVolume;  r9 G  L. G1 V3 F" `6 H

" k+ O& \, U2 n- e' ~        INT        nMasterVolume = bMute[0]?nVolume[0]:0;: {( ~6 O: T7 f7 u8 o+ v
- }6 M$ p' A0 j$ |  |% O
        // Internal, ?2 G. V. ^# T: g
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ r$ D) O+ P- m3 S
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;2 D9 D7 X8 f2 `0 Y0 t' Y2 K8 C
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
2 t1 q* b, B% r" r& n        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
+ M4 Z: ~0 ^/ Y! t- T0 K        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 `) x/ l+ ^; F8 Z- t0 k" x
# i8 B& c: L4 I" B        // VRC6
3 }! V7 J7 X: G        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* j% }! e' ]" J2 ]5 q2 N( z/ `        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 Z! ^4 R( n( x  ]+ I: {! `        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* d! @) k5 K* Z$ G

0 ?0 z6 d3 X9 g; a8 R6 K3 G; @        // VRC75 S- m/ a- ?( a. T& b5 G" F3 l
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 g( J- u) E4 D- k& Z
" a4 G3 ~' S& i6 C2 \
        // FDS
6 z" t# ?! I; O$ ~        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;$ C1 q0 q7 ~, j; o) U* x

- c& b+ o$ k( |' {; B2 T3 c        // MMC5
1 m! [6 i/ `1 n& X  _# d, `        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 f9 h- k$ f6 }# U( v, `        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" U( @; h8 N) X        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( _* p  y# _7 N  o' j. _: z. ^$ Z
; ^4 b  i" O1 L/ P9 [2 C
        // N106" o' ~$ x- P9 H% z
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 V. Z" X# V1 a7 [* x" ^        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! t8 b+ u& G9 ?5 H7 u
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 t/ W5 e1 E7 z1 E! `* d& `5 e. ~8 \
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ m: g* @( R: j! d6 b( |        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ e$ F/ F9 @! E3 s/ ^" z/ J; E
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 |0 q! T; G$ b% r4 j. q  r$ ~4 i9 S
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 L5 k' Z% Y4 [# j- ~  O. M
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 D) ~. p) m0 b( ~
* `8 G+ c3 }& C: N
        // FME7
# g  r: B0 C$ ~9 u" ^, R        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 y3 k1 e/ V4 z* t  s
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ N8 T* T% z' s9 }0 C4 E
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! I% H( s9 L4 b+ y, N/ G4 q$ Q. P( X0 q- J* v; f
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
+ C1 b( O8 m- o        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
( [) @4 R: L: C" J$ X1 s% }
7 h$ Z# @2 F' }+ v( _        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- G% _& E% [$ k# Z% @- y        if( elapsed_time > nes->cpu->GetTotalCycles() ) {% `/ j3 ?3 @5 N3 K
                QueueFlush();
$ H6 g4 [5 O3 t$ N2 p, i% R4 \8 B        }
$ j0 V2 B6 W; o, S) {2 M
4 d4 t0 f% K+ `  y7 T        while( dwLength-- ) {4 x6 Z5 i5 F5 m% ?- P4 c
                writetime = (DWORD)elapsed_time;
( @7 j& Q+ l2 C( {' @* e# H: D: z6 a/ i
                while( GetQueue( writetime, q ) ) {4 n( k: r5 b" F% D1 M/ D( P/ R
                        WriteProcess( q.addr, q.data );
, w: ^0 L- z2 g$ H& q, [( a                }3 O6 v& T  Z4 w) t

) p1 R5 I4 a- z. N! ~+ Z& m* h  M$ Y                while( GetExQueue( writetime, q ) ) {( `5 H2 |. S% ^8 X+ S+ F
                        WriteExProcess( q.addr, q.data );
( a9 y# g' Y, g, g$ R. v: a                }
1 G6 X- @( J+ g$ D  w% \# o$ @: z4 b8 v" z7 b0 ]* J
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7* h3 j3 |) ~* u3 J9 N
                output = 0;
& Q5 s) T  F2 \# M$ W$ J                output += internal.Process( 0 )*vol[0];
1 W1 Y# p! g1 W$ J: G/ m7 s                output += internal.Process( 1 )*vol[1];& T0 F  r7 J5 i. X
                output += internal.Process( 2 )*vol[2];
& f$ @+ B. ^! G0 g                output += internal.Process( 3 )*vol[3];6 F$ D* X3 T7 B: Y) ^- v5 [3 ^
                output += internal.Process( 4 )*vol[4];' F, ?1 g( s& y2 w+ X
5 A- c) k7 l# c5 j/ L. i/ @
                if( exsound_select & 0x01 ) {" e' G5 W: n$ N
                        output += vrc6.Process( 0 )*vol[5];& ]+ B; T1 K, x  A7 P' z  \
                        output += vrc6.Process( 1 )*vol[6];
& Y1 Y4 q  A4 M6 z& E0 c                        output += vrc6.Process( 2 )*vol[7];  m; \  N) o- u
                }
- l- a3 l: b& ?! r, {                if( exsound_select & 0x02 ) {, E- `( j9 `, r& z: ?/ X3 T1 m0 ]
                        output += vrc7.Process( 0 )*vol[8];
7 ^" _; C3 |0 `' I0 S2 M1 h, h! K                }4 m4 ]' c& W) k, T/ m  c. C; F" n$ [
                if( exsound_select & 0x04 ) {
2 n+ U5 _. k3 E                        output += fds.Process( 0 )*vol[9];
$ p2 b6 m2 b8 M  j% D                }# i" {: ]" c0 Q, f+ q
                if( exsound_select & 0x08 ) {
. v% T( h9 c+ Q2 ], Q                        output += mmc5.Process( 0 )*vol[10];
" {9 K' g$ e$ Z9 f3 u& ?" N                        output += mmc5.Process( 1 )*vol[11];# ]+ G7 W4 m! ^2 J* }. i
                        output += mmc5.Process( 2 )*vol[12];
6 k  o+ c; p; @( @/ ~                }% l; @6 _! c2 I4 A% w" y, X# n7 q
                if( exsound_select & 0x10 ) {
: K' R% P$ Z+ ]  ~3 I3 R; k  j- H                        output += n106.Process( 0 )*vol[13];
. y' [, D$ Y, a  n                        output += n106.Process( 1 )*vol[14];
/ {) K: o7 L  L- }: U$ c                        output += n106.Process( 2 )*vol[15];1 A) l$ A2 ^; G2 M: d2 O; b, {
                        output += n106.Process( 3 )*vol[16];' h0 x; D; W9 I
                        output += n106.Process( 4 )*vol[17];9 a. T4 n: k3 |0 f7 `/ X( Y, g
                        output += n106.Process( 5 )*vol[18];
; o' F$ c! l8 T$ n                        output += n106.Process( 6 )*vol[19];- V5 P$ O: x! C0 n
                        output += n106.Process( 7 )*vol[20];
% }) m. b& v7 ^* H4 P7 X! X                }
: R- i& g' O9 M2 ~0 M                if( exsound_select & 0x20 ) {, [, m1 l& W9 g+ X) m5 {* B
                        fme7.Process( 3 );        // Envelope & Noise* F7 R( F- t9 g$ {+ B9 m3 Q# R
                        output += fme7.Process( 0 )*vol[21];. @; y+ G7 f& e
                        output += fme7.Process( 1 )*vol[22];" R( L4 N% k- @2 A, z' h
                        output += fme7.Process( 2 )*vol[23];* s. e% l7 E" p9 T: `
                }
( M; f" Y+ O9 G: ^3 R! `" z
& h! b  P& |5 S8 b2 ?                output >>= 8;
8 K, q! s0 ~* D, n2 f& J# x1 @1 ^
                if( nFilterType == 1 ) {
* [& ^/ J) _/ {  J                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
9 y' O& D5 x7 P% O                        output = (lowpass_filter[0]+output)/2;& Q  h4 e9 }* X2 r+ M8 U8 d6 m
                        lowpass_filter[0] = output;
, i( }9 V' v4 G                } else if( nFilterType == 2 ) {
: s( A  W# ]/ S0 h+ p                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- S6 m7 i3 L: I; d; E# |4 K" c' j4 J
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
/ o1 {6 R9 \; K- D/ a                        lowpass_filter[1] = lowpass_filter[0];1 \* ]2 |( C; p
                        lowpass_filter[0] = output;1 l* j% ]7 ?9 L# D( ?
                } else if( nFilterType == 3 ) {
/ R0 E. U$ ]+ ~% y) D# K  h6 t                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
8 N" V) g: N: |* ~  F                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
/ B6 ^* `8 D3 K' y                        lowpass_filter[2] = lowpass_filter[1];- v8 \4 [) H( m6 z; Z+ a
                        lowpass_filter[1] = lowpass_filter[0];* X8 P6 j* p! _* t* Y
                        lowpass_filter[0] = output;) Q8 y& {5 k4 V' K# f7 ?5 z
                } else if( nFilterType == 4 ) {) W9 u1 v3 T, @! H/ _+ Q* N. e$ T
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 u/ y! g' v6 r$ k                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ H. R. e* o1 B( v  m! k1 W0 D                        lowpass_filter[1] = lowpass_filter[0];
( I1 l  d' {6 k                        lowpass_filter[0] = output;
* p0 o: M6 X2 v/ [/ p                }6 ?1 _& [( E5 k' _: X

) w: k* k. l1 f. l" J- E#if        03 h. `4 s& I0 z; @5 K
                // DC惉暘偺僇僢僩
% _+ u! K/ y1 l) V7 V                {
3 ~# s& l( S# K- w                static double ave = 0.0, max=0.0, min=0.0;  z0 u% T4 N+ I  X( }# d: M8 r
                double delta;
9 m1 c  ^/ k, d" }" a/ w, R                delta = (max-min)/32768.0;
$ r0 \8 _# f- J4 Z                max -= delta;
. z+ \! m/ H- d& x/ n2 T' {                min += delta;! q/ X% W$ [( R4 |  t
                if( output > max ) max = output;/ w3 V7 Q2 X$ a7 D! O
                if( output < min ) min = output;
/ \9 u! R- Z5 Q4 O  c+ N7 m$ j) A                ave -= ave/1024.0;
1 U# C4 f5 ?  U6 }& b9 v                ave += (max+min)/2048.0;
1 u4 U8 S% F! N! f8 E                output -= (INT)ave;
. G" y4 p  h8 ?; m- Q5 F# r; j                }
8 }6 q+ q0 F- \) e1 S9 W#endif6 \  [3 Q' S7 K; I1 m
#if        16 D2 ?; [# H" m& @
                // DC惉暘偺僇僢僩(HPF TEST)0 d2 F0 s- |# G) u0 P' s
                {* [* l3 `! M/ k* R- u+ w
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. }2 x) D2 Y" P7 \% x0 y/ r' Z+ |
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
3 t( S# X: b( f6 {                double        cutoff = cutofftemp/(double)Config.sound.nRate;, l0 o8 {6 I9 {" S5 n' f& I
                static        double        tmp = 0.0;
: ~9 ^$ m" z+ H- M# x# C% b4 ~                double        in, out;" h3 D/ a9 B/ x0 g
" z* a, X; J$ A
                in = (double)output;. t8 ]4 E" c, |. P6 t* y; ^
                out = (in - tmp);$ C: v/ g9 W" f# v) N
                tmp = tmp + cutoff * out;
/ z- G2 V1 ^  V# k
6 n% c8 A4 Z  }2 Y. q* c                output = (INT)out;( ^" r5 b+ O: _
                }
4 t0 Q/ P& n  V8 O- h  \#endif
- V/ V2 X: s% z0 H#if        0
0 h; _% ^# ~9 B                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
3 ?# |' s* E4 z/ I2 W3 J                {; M6 e2 o8 ?3 ]( u; X; U* S3 f
                INT        diff = abs(output-last_data);$ g% @  r$ Z2 z: Y9 C, n0 f) Q
                if( diff > 0x4000 ) {
0 F9 J0 {& ~* P& V- X4 r" g* W                        output /= 4;- D# g( H2 [( B: u
                } else ' D5 `( t' w6 E; _- q8 X% ]
                if( diff > 0x3000 ) {
& J6 v. o: ~1 {; B; P                        output /= 3;9 B& D9 j( c2 K2 n
                } else% ?/ h" \- Y0 Z5 y5 W9 s1 M5 T
                if( diff > 0x2000 ) {- q* f0 P+ R1 \! W. W; b  y) m
                        output /= 2;
1 T& N! i- W( Z( B7 Q                }
# p1 m* E3 P* r% g                last_data = output;: K) p7 t! W; m# ]
                }
' Q2 o7 @2 e( `#endif7 W* P. B& Q( a7 D
                // Limit
2 t) P9 p) l2 \: _9 g, e! k. f                if( output > 0x7FFF ) {( [/ W, J2 F  a, C5 H5 \# M1 x
                        output = 0x7FFF;
7 N/ W  G9 b3 L/ U1 N                } else if( output < -0x8000 ) {  A- X( Z9 i8 D3 _' g) I
                        output = -0x8000;5 a! {. i1 @8 x9 ?  h, [
                }
& T" P' i( r' G$ r: W2 K/ M& O
& |4 F1 W0 h7 ^9 `2 `4 t                if( nBits != 8 ) {9 Z4 P" V6 ~' j+ d8 p2 |  p
                        *(SHORT*)lpBuffer = (SHORT)output;
* \1 M/ k9 i* B5 k! J+ ?3 C                        lpBuffer += sizeof(SHORT);  {- C: G9 N, Q) K9 ]/ u+ B4 e
                } else {; ]4 x7 y% `& O* Q& Z% @' f# r3 T
                        *lpBuffer++ = (output>>8)^0x80;$ f3 x4 O! X# }  |5 K
                }
+ X# P$ R- D* E6 ^! j9 n6 y' U
                if( nCcount < 0x0100 )6 g$ S2 j, a( s( I/ T
                        pSoundBuf[nCcount++] = (SHORT)output;
7 A1 ^" K( s& ^) q9 W: h
& l/ Q5 y* d9 P//                elapsedtime += cycle_rate;
4 N+ C6 y8 K% x9 H                elapsed_time += cycle_rate;
& T, W. e" Q4 |, P8 r- A2 k* R$ p2 N        }
- P: R, j; G- D2 q8 Y! s' t) ~# B5 R, T% ^* O; d! o/ w/ x
#if        1
8 ~3 Z) P* g& I& v1 r! y        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {6 z: S) B' ~1 H3 Q$ }' f
                elapsed_time = nes->cpu->GetTotalCycles();$ s  W" u% C( n1 d" d& `
        }2 X# N7 _; s+ J- h% }8 ~) |
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: u# d( n) a: Y  _1 F# ~" w                elapsed_time = nes->cpu->GetTotalCycles();
0 [- m; L3 m5 Q  p# p3 B5 R% o        }3 j! l5 o6 u* A1 z1 J+ u; P
#else9 b* w0 N: T9 n: C4 y% w
        elapsed_time = nes->cpu->GetTotalCycles();
  K4 S+ G8 {2 I7 Z" V( A/ f#endif. n2 k0 n9 Q. `
}
0 a+ g2 F7 E- ^: ~) V) h$ A; h; q" J$ E+ G& p7 O
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡). J- w5 f4 e) V& @, @' o( g9 a
INT        APU::GetChannelFrequency( INT no )
" H; e6 s# A( Y4 p/ q1 G5 J{
- ~* {. ]* l4 \8 {# c        if( !m_bMute[0] )2 J! x. T$ a( [( u# c, I8 e( d
                return        0;
: V5 S' k" d+ M5 X( v0 i- T/ I# I4 e" I% s1 z8 D8 M
        // Internal
! r$ S/ `+ g# v        if( no < 5 ) {
( d- M) A  Y: `( H* ^; q& U                return        m_bMute[no+1]?internal.GetFreq( no ):0;
3 o# I! r1 T! U4 F" r3 d        }; }& e, U6 c1 K
        // VRC69 Z( |; y; B/ O5 m7 p
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {, i9 L7 ^2 x; s
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;; q3 i# W" h5 n; A
        }6 ?' v+ G7 B# p) S( k7 H' Z4 e$ c
        // FDS8 n( i9 q; R' K
        if( (exsound_select & 0x04) && no == 0x300 ) {; I2 D2 m! ~6 g! }( i( F
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
2 q8 u$ e$ J* a        }
( X8 M% W5 F9 S5 G4 Q- K        // MMC5$ l/ E+ g5 X% J
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
/ |7 W+ p. W: I# R3 Q# P                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
* a. H- m) J$ Q1 J        }
& E! b% U8 P4 y5 ~# U% u        // N106% _/ T9 I3 f  W: h3 j
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
/ C% x  R$ H5 I: \  d                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  ~  o  `. `, R8 ~7 R9 t$ ]/ ]# \        }
& h0 F$ z- A% m- a2 i& R) ^3 J        // FME7' v; t/ K+ v9 L7 F5 J7 ]* w* R
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 q$ P) f3 Q3 v+ k4 Y* {  \4 H% s$ ?
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;# _7 i4 v1 O3 z3 u1 T$ P
        }8 i' G: `9 S% G; G1 n( y4 y! t2 t
        // VRC7
; V0 P# T3 V; x) o        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {0 c7 F( |8 H4 e) g
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 O. F' ?/ U7 V2 _5 A* K        }% V/ n. ^9 A( s
        return        0;) a+ c9 m  h! J  j5 ^, K. X: ^
}0 @& ]8 k; x7 o$ K! d# p
5 z7 |+ Z/ f" b' z2 o# j
// State Save/Load
: o( k2 r; S+ @( n0 ~0 k) Ivoid        APU::SaveState( LPBYTE p )
  R& P7 |3 @8 ]/ c$ i{3 [8 R' H! ?1 j' E
#ifdef        _DEBUG
  j+ Q5 j! g$ \' @+ ^* ^) ?' j, MLPBYTE        pold = p;
- ?9 b: u" D# z9 p( R3 p7 p1 E#endif
3 {; [. \: p0 P( _" P$ z8 E$ R3 ]4 c' l) i5 C
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞& X% G( N5 }/ b
        QueueFlush();! r' l* r+ ^: ]4 h

: P# T9 |" s+ Q6 J+ i$ z( ^        internal.SaveState( p );
; ?6 [& p& L7 l8 a( f3 V4 V        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) }7 L/ T+ \# V. m8 y% }9 ^, k
        // VRC6
4 {: `2 z9 s% X  X2 D. x        if( exsound_select & 0x01 ) {
; d. z6 d* H$ H2 A                vrc6.SaveState( p );
3 k0 S. Q# X: Q& S& V: Q% L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
9 ?9 ^2 V3 v& J; l& a        }- G) g. p7 \2 \4 [+ Z
        // VRC7 (not support)
8 M1 c) M2 K6 c+ ~7 m# o+ d* h        if( exsound_select & 0x02 ) {0 d* ]" _+ |! x' i2 Z. k; ]  J
                vrc7.SaveState( p );7 v* ^2 b" R5 J" I
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ b: i* w* ~, [        }, G) w6 I& k, V' L& U: k+ S, X
        // FDS
% u3 d9 ~3 ]1 ^        if( exsound_select & 0x04 ) {
$ P: C- W/ L7 L                fds.SaveState( p );
4 Z' o7 I7 M, B, q9 x                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
5 W6 y+ Q3 G; R  f  v$ ]        }1 J, Y" s( X$ ~. w  ]' C& O. m
        // MMC5
! [8 l. B6 h* R' O4 F2 \) [. _/ a        if( exsound_select & 0x08 ) {; P; {- J) ^% B6 ~2 j
                mmc5.SaveState( p );7 C: P- i  G, _4 ]  l
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding8 p( H, E# [6 O6 s! s
        }
6 ?) e* N, [5 i3 p8 j        // N106
( e( d8 U( |3 e        if( exsound_select & 0x10 ) {
' }# v# m  e5 G/ E" l# j                n106.SaveState( p );
, g, F7 _: L$ n, s7 Q4 r/ `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& ^' q' [/ x% B- ^- I4 U
        }: ^& m% g5 G  B9 x
        // FME7  }: a( ?% u. W! q9 b9 {
        if( exsound_select & 0x20 ) {
4 `8 R/ y! _+ \6 y                fme7.SaveState( p );
! b0 e& {7 T" S2 w9 L" |6 ]. v7 [                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding( Q, E$ e' x4 k1 S0 f$ Z
        }  `5 W3 @6 S1 ~9 v5 t1 R2 V

7 `; {, O, l3 k: X* j; w#ifdef        _DEBUG
3 t  I4 Z0 {4 G. m  kDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ p- S) D& G4 `* y& q9 f5 V#endif$ l. L+ \* ?8 Q! Y0 X5 A
}! W/ F8 X: |# W2 ]
2 f4 a4 I3 }, N1 J5 x
void        APU::LoadState( LPBYTE p )
# o5 y  d# u( i( Q{
4 K$ q$ T* G' S' [' f! a        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ ^% h9 \) O1 y# i        QueueClear();
2 M& v0 P; B5 V) u8 P
, p4 E2 |' b% C+ [  o( a        internal.LoadState( p );9 k4 U2 g. K& \4 P) X
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, h7 u  W  C/ H

' V% u: U, B' Z        // VRC6& x) ]$ G: U$ z+ a* ^
        if( exsound_select & 0x01 ) {' r4 S& b% B% l0 ?
                vrc6.LoadState( p );
. L9 Q% W3 {2 |2 @, r6 F                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, J4 e- k* ^& L; P; x8 m; r% i        }; p/ I; E6 {# e& x
        // VRC7 (not support)7 V( t- {  f2 N# D
        if( exsound_select & 0x02 ) {
) O, v3 T: ]2 O5 e, N                vrc7.LoadState( p );
" B. W. A4 x9 _                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 O. A- M+ q) \( D        }
, Q% I; ]. \3 k        // FDS7 h( m6 H# c* m/ r& f# u6 y! V
        if( exsound_select & 0x04 ) {8 f" U( p7 @) C2 _, d! Q
                fds.LoadState( p );
8 `) r2 e7 j, h$ u) Y; Q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! v: L' ]. C' H1 ^4 [& W% ]9 |
        }  v7 t/ T) B% [! c2 s
        // MMC5, H) a$ T) \0 `8 Z: c$ e5 A& h
        if( exsound_select & 0x08 ) {# c9 _4 u" b+ i& W) g, K
                mmc5.LoadState( p );
* o* C) f9 o4 B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* A( e7 k3 }+ @+ c1 J
        }  ~+ m' x- s7 H6 [: J
        // N106
. e6 s0 [, l( ]2 _+ F2 [8 U3 d6 }1 i        if( exsound_select & 0x10 ) {% X! C: S2 }( a! N
                n106.LoadState( p );
8 y# u# b8 ?5 m# I8 R! G6 Y7 C. i                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
- ~3 v2 q" }$ e- O        }  E7 ]& Q8 T1 ]7 F4 _
        // FME7( l; Q$ `, L3 U: h+ V' t
        if( exsound_select & 0x20 ) {) `& }3 w2 b1 K" _: P8 E6 A! w
                fme7.LoadState( p );
: w2 j0 q4 A1 n0 Z                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding( Z" F! t7 w3 Z( u7 x- }: p
        }" i! |6 G4 y" m/ r, r
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ' w! K) d7 C. i& J8 D2 h; r
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。; y3 C6 c/ u8 p2 q0 E
感激不尽~~

4 U$ Z) ]0 Z+ l8 }7 ~恩 我對模擬器不是很有研究,
' R$ D  f5 v' Z- J8 k雖然要了解源碼內容,可能不是很困難,. J  Y2 g# X; D: o( F* w: J- u
不過還是要花時間,個人目前蠻忙碌的。0 r: o  {, p& h+ J: o% H

' s! W0 P( r. z9 W) j$ L$ n1 _6 [給你一個朋友的MSN,你可以跟他討論看看,3 Y: ]' C1 F3 |+ d9 F) F
他本身是程式設計師,也對FC模擬器很有興趣。
6 s1 p( m- ?0 D% d8 F, q# Q. b& T$ T7 ?" i3 ]: `* z/ K
MSN我就PM到你的信箱了。: K3 m! O/ `( X& A) O

6 m7 C" x8 B9 Z. `' L希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 2 F7 }/ y; k- R4 {  s! ^% \4 |$ M; }
呵…… 谢过团长大人~~

; T/ F  ?8 l- U; X% O% p; J. H) v& y$ Z  \
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , F7 u, m9 Z0 F) `; h# [6 ~
团长的朋友都是神,那团长就是神的boss。
# [: O- x1 A, G& J: x
哈 不敢當,我只是個平凡人," V# U+ M; P; {" k. V! j- S" Y$ ^0 r
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 Y& |0 P" \4 p5 w* R0 LZYH% z- g' g# t, r
QQ:4147343060 k% ?4 r$ p7 J; O  l$ y
Mail:zyh-01@126.com& u# E# A3 s3 N9 Y9 n

: {. L0 a# K$ |他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 & D" J( j& L  r, j$ \1 v" `
再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ g0 r( j2 `; X' V( w6 s不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 04:20 , Processed in 1.075196 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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