EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。( B* l& |* Y4 `7 q  W
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" r; }+ E# R6 A# P1 a. S! U& h这里有相应的模拟器源码,就当送给大侠了~~
) r, Y0 T0 j  [3 K9 H, yhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
2 R9 s9 p" Z. x. e! k能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
- Q. c4 _1 Y! i+ I$ L楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% N% n7 T  D1 p, {) W
这里有相应的模拟器源码,就当送给大侠 ...

, Y" B* ~3 |% R" E1 C& g6 ~聲音部分(Audoi Process Unit = APU):; H2 X1 C8 j( I6 n' \
.\NES\APU.cpp
* }" U1 Y$ R* E5 Z.\NES\APU.h
* ]  ]; x9 C6 O% ?; X; A8 A7 M! N2 e1 W/ y, a. p
0 V( G7 |5 q6 t) S# P4 a! M
影像處理部份(Picture Processing Unit = PPU):
, j8 u: |$ \2 y0 F+ p* q/ l: W.\NES\PPU.cpp
) A% ?6 j8 B' v9 Q/ i3 f1 X8 p' @; x.\NES\PPU.h8 {8 E' h" O! r+ L: \' j

9 @- T0 P8 t6 D0 p2 K如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
4 G" A6 \5 p5 f* s: y) v2 R8 x" B感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:: F( @$ m0 ]+ X9 R+ Q" `$ w
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
# u% c1 o& j( z: H* O5 ?; Z//////////////////////////////////////////////////////////////////////////
/ r+ H2 K* m0 z//                                                                      //
! }/ Q2 @* h, t) s//      NES APU core                                                    //7 Z8 U: i  R% b+ g& _
//                                                           Norix      //9 y. M7 A5 x* |. G
//                                               written     2002/06/27 //
9 r! c  M- s- [! X- m//                                               last modify ----/--/-- //6 j6 v) p9 c5 I* j  Z! W
//////////////////////////////////////////////////////////////////////////* ^: }! H; ^* _4 Z
#include "DebugOut.h"/ D; @& p) y9 i& J) N
#include "App.h"
" |9 Q3 a3 L% U0 Y0 h0 F! `( N#include "Config.h", I2 S; S3 q5 L2 A( x# X  v
5 x5 F& i: t1 k$ H6 h$ l. J3 G
#include "nes.h"
0 k: _! {# P& V#include "mmu.h"
( i3 _' _! X2 i% g#include "cpu.h"
5 ?1 p8 x2 V" [7 Q#include "ppu.h"
8 h9 ?( R& {0 Z- o#include "rom.h"/ v& p: g1 n/ L. j8 |/ G
#include "apu.h"
8 D& `, S/ W2 H. s: t4 o% |4 ]  C8 {
// Volume adjust% O9 `. L  ^+ n2 j
// Internal sounds
$ r0 x/ M9 b2 u6 K#define        RECTANGLE_VOL        (0x0F0)
( U- N$ q& g2 I! Q#define        TRIANGLE_VOL        (0x130)& g% b( n7 \* Y9 Y6 [  |3 f
#define        NOISE_VOL        (0x0C0)" ]$ y8 S2 |0 [
#define        DPCM_VOL        (0x0F0)
- F9 X, b! X/ `! A// Extra sounds$ s% Q" f" G- t) v& q, p2 r
#define        VRC6_VOL        (0x0F0)/ H  k7 C- `: J' [3 I/ ]# n
#define        VRC7_VOL        (0x130)
9 Q7 H9 Z+ N" {9 X#define        FDS_VOL                (0x0F0)
- ^9 \2 U& i5 ~5 j4 f  y#define        MMC5_VOL        (0x0F0)
4 A* F3 e. }) F, [6 g  b#define        N106_VOL        (0x088)* ?% e, F( N4 u
#define        FME7_VOL        (0x130)
7 J4 ~! [% {, j0 C# b
) c( ^( d9 h+ N' {2 q1 V+ Q# dAPU::APU( NES* parent ). u$ \5 X1 T1 L# ^- N
{; `: {* S: Y4 a" [/ E4 R
        exsound_select = 0;" T# g) v/ z. s, N) W5 g
/ n, E6 u; c$ ^2 h1 u5 i! _
        nes = parent;
' S- t( j! x: r. }$ t        internal.SetParent( parent );
2 y4 t; a- }% D. ]  w5 \+ I8 o4 S. b3 s
        last_data = last_diff = 0;
# S/ ^) @' M7 @: }+ g
7 q* Y. k; c+ |" _        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );2 p0 @! d0 ?4 M0 ~4 F. g1 @; [2 b
& Z5 ^( Q. v( C; S5 P5 z- m" F; f
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );8 ~9 y) ?3 S& _" S' m
        ZEROMEMORY( &queue, sizeof(queue) );
& ~' Q1 z5 O4 D        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ X- j! w$ {" F' p, R# A2 e

7 ~+ `1 f" v% \- w$ A" W9 B        for( INT i = 0; i < 16; i++ ) {5 w8 |) W  N0 N  }
                m_bMute = TRUE;/ m$ A# m) u# T( k, m
        }! G$ d8 Y  Z/ V( n% D# p  W0 X3 }* s
}& w5 g6 c6 ?) U$ R
8 }1 d1 a2 H: l
APU::~APU()
6 G) z+ O5 T0 X# m% u/ e; ~' p{( g6 j% @& C9 g* Y
}
$ O( F6 m/ y/ Z" C* I2 u7 _. E- h- {3 ?9 \/ n3 @$ d
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
5 e& v- `2 |+ Y{1 E% t+ x- E" D, W/ F9 K' v, g) ?4 A+ H
        queue.data[queue.wrptr].time = writetime;
1 t  M! ~1 g( E2 g3 y        queue.data[queue.wrptr].addr = addr;
# }  F" t) S, a& {  |# m        queue.data[queue.wrptr].data = data;
4 e, |: [! P, }5 s2 n        queue.wrptr++;% G' K" x. l3 v6 K0 X- J/ s! y
        queue.wrptr&=QUEUE_LENGTH-1;
$ h  K6 E6 F4 h0 O5 S6 k) T5 x        if( queue.wrptr == queue.rdptr ) {
8 r$ F( Q* I% U2 h8 W7 w                DEBUGOUT( "queue overflow.\n" );
3 K3 D0 P9 m; s+ m. k        }
0 H  c5 O% T5 N+ r: u* }5 E}
1 G1 N0 l: u6 P+ ~3 d3 o# e  p2 o# ?' E6 a0 s$ H( T
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ): z  w4 g2 B7 H7 S. @+ r
{
+ k5 D; d2 `9 d1 J8 g% V& G# S- d. {        if( queue.wrptr == queue.rdptr ) {3 [7 W1 V" f: ]
                return        FALSE;
* O! @' D) k) s4 N" b        }) F' b0 N  I3 L* [# u5 K2 I
        if( queue.data[queue.rdptr].time <= writetime ) {4 j8 v% h1 i* v( L( a1 D' A: I
                ret = queue.data[queue.rdptr];7 Y5 Q: j( V6 Q3 r# ~
                queue.rdptr++;4 ]) C) l8 E( D; h5 L9 V
                queue.rdptr&=QUEUE_LENGTH-1;) Q9 B6 @4 u, \; N$ v% @6 V
                return        TRUE;+ ]4 ]% w  w* R3 v
        }8 x. Q7 Y' D8 L. e" Q+ N
        return        FALSE;
2 i2 V: K9 z3 R}' O/ T1 q2 r  p& t
' P, y4 L) ?6 j
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: T$ v5 @" w3 \6 z3 f1 H: ]2 u2 r7 A{# y: z, Z/ C, X# i& p
        exqueue.data[exqueue.wrptr].time = writetime;
5 b: E. z" _6 L; ~+ h4 T        exqueue.data[exqueue.wrptr].addr = addr;- K! S7 r8 b$ _4 w+ A
        exqueue.data[exqueue.wrptr].data = data;
0 f9 B( U) Z! I% Z5 V5 j        exqueue.wrptr++;
" `# m: ^" i0 q7 l! S        exqueue.wrptr&=QUEUE_LENGTH-1;! v: j$ E3 h/ @" V
        if( exqueue.wrptr == exqueue.rdptr ) {  L9 C4 o( c! @8 [$ U9 }
                DEBUGOUT( "exqueue overflow.\n" );
2 |. V% R! x" D6 I9 U8 @- ]1 w4 n        }
- p' c9 p' s+ w+ |7 F+ C}6 Z' n/ Y! {/ O; z1 P

/ i, `, p* P8 N- g$ LBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
, m+ b' j9 z/ t! K. v# X{
8 U" i. _: _2 }: E8 c, V2 d6 Z        if( exqueue.wrptr == exqueue.rdptr ) {3 s- D& v. v+ R$ d: F8 L; n
                return        FALSE;
# m# B. M  j4 ^        }, P/ a2 B  Z) M* ~! C6 {
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {6 ]. Q* F; ?) o& m, m- `
                ret = exqueue.data[exqueue.rdptr];
# W) ^8 m. Q1 y) N, a                exqueue.rdptr++;
  i$ j4 u& V, }, o4 C9 _4 Y% o                exqueue.rdptr&=QUEUE_LENGTH-1;
7 e) t" k% P: l$ u- ?0 c                return        TRUE;
" [& L$ X! U) N- ~: w% u7 L        }1 \+ ^6 H: }8 R  H& l$ T/ C
        return        FALSE;) X" W, G* o8 C2 t& f7 F. I
}2 d' d# ^9 u) f: Q

7 G8 Q! O. N9 H! J, G2 k; kvoid        APU::QueueClear()# q+ w! E. O: p7 D
{
9 t; U5 {5 w  p, U, d6 q        ZEROMEMORY( &queue, sizeof(queue) );$ h6 t  Z) {: ^! n" o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, B  `  s: K, d  p/ U% M7 J}
( m1 I' ]' }$ D
& s7 ]) M. h8 U* }void        APU::QueueFlush()
/ v+ M9 h+ A! N- U: n2 y{0 A3 P  H+ d7 u3 c5 U
        while( queue.wrptr != queue.rdptr ) {9 r7 n8 B- g, w7 U. r2 _
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& t/ q- Y( _. f+ A5 E, y2 b" t5 |
                queue.rdptr++;, D9 u4 h' _, m0 z1 K$ y: g1 I
                queue.rdptr&=QUEUE_LENGTH-1;
9 U& A  o& B; ~* d        }: u2 E; Y9 E' e2 T+ M. l6 y: O
& n) l; ~) q, a8 W
        while( exqueue.wrptr != exqueue.rdptr ) {
& f* R. P$ D! \0 t) K                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: K( _* x. ?4 G% g                exqueue.rdptr++;
% p4 `! Y) D* Y3 K9 O. g9 T                exqueue.rdptr&=QUEUE_LENGTH-1;! {# a( B6 }0 Q) G6 D
        }
- L: N! t# M. Y( Z! ]0 J) V) t# Y* q( O" N}( ~  P  T% Z: d& {4 U6 K1 w

( h5 L, H7 E) m- w8 M1 j* ?void        APU::SoundSetup()
7 |) v& b4 \! K& H1 p{
1 l' ~3 U8 z% v. q3 |        FLOAT        fClock = nes->nescfg->CpuClock;, S, A+ X0 T) m# u7 T9 t8 |7 G) ?
        INT        nRate = (INT)Config.sound.nRate;/ q6 _  E1 {2 Z) D
        internal.Setup( fClock, nRate );
" `5 W2 n. e* W        vrc6.Setup( fClock, nRate );
0 U8 H+ |5 J* m' \" a        vrc7.Setup( fClock, nRate );2 ?" Q& N7 K3 A1 W& H6 z
        mmc5.Setup( fClock, nRate );) H- `2 f. T0 C- f; w0 Z
        fds.Setup ( fClock, nRate );
5 b) r) t4 {7 E% ]0 \( K! e        n106.Setup( fClock, nRate );0 `* o; T6 \. C" r- b' f% F
        fme7.Setup( fClock, nRate );) p) R7 t" v/ B! Y2 T
}! v% u0 k* m2 m+ X# Y1 i

% O* r" |1 u2 {$ ^0 ^void        APU::Reset()% v( ^# w  E1 S. I
{% n7 k* w' i" @; U, r6 I
        ZEROMEMORY( &queue, sizeof(queue) );/ I4 ]- |/ X$ ^$ r8 j5 _4 b7 o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( A6 P' @( i$ F9 ]& K1 P
( T. B& `& ], x% k- N/ {        elapsed_time = 0;
6 a9 y& e9 {2 C+ C4 c# v4 C. }7 b: \' l. k, h; `8 s
        FLOAT        fClock = nes->nescfg->CpuClock;
$ z- r# I% n6 E        INT        nRate = (INT)Config.sound.nRate;
) F7 {. T( }" K$ q9 U        internal.Reset( fClock, nRate );
/ o: r+ W  H6 E: T0 }- `* A        vrc6.Reset( fClock, nRate );
" z3 T2 r' `/ t* V        vrc7.Reset( fClock, nRate );5 j* G2 A' ^) {% X2 o( C) |+ p
        mmc5.Reset( fClock, nRate );, i- L& c. s* ?7 G3 [3 b% _8 E2 g$ p# _
        fds.Reset ( fClock, nRate );. @8 v3 u! _# V0 `; p
        n106.Reset( fClock, nRate );
* R. \3 j) w' J' H/ P! }# p' U: V& P        fme7.Reset( fClock, nRate );
$ u5 _$ Y" D; `  _' i- ^3 t9 P, E1 Q  b
        SoundSetup();
  T9 v0 U- H/ P$ J# N}
/ ]5 I( R/ [7 `
# L# K, f, L; q" ~, Kvoid        APU::SelectExSound( BYTE data )$ w  o7 L6 _9 F- |  C" h
{- o& i7 M5 W+ B- M# O3 E& a+ o# }5 s
        exsound_select = data;
: S5 X" C7 e5 Z9 M! i}" z/ @& Z7 q- u" A6 w, V

3 j$ T% S. B/ _& S+ d8 ~BYTE        APU::Read( WORD addr )$ [/ S9 F5 h: g5 o
{0 _0 }) y6 N6 E  w
        return        internal.SyncRead( addr );
# E2 E9 N, W6 \% r/ C" E}1 f/ \0 m+ o2 `" ?$ q9 R

# j7 K4 \9 [& W% ]- B( Avoid        APU::Write( WORD addr, BYTE data )
5 y2 u; s3 w4 ]/ m2 W. ^{
* e- w$ O4 u8 A2 q# T        // $4018偼VirtuaNES屌桳億乕僩  `! F& P  v6 m! m
        if( addr >= 0x4000 && addr <= 0x401F ) {
, q6 n1 y3 P' W) w8 _                internal.SyncWrite( addr, data );; d# g0 @; B; O" f! d1 l
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );1 r2 S* p+ u8 x; S- ?4 [; j
        }
' L: P4 I1 e$ m# @}/ A, M+ X1 k+ Z$ y/ s1 Y  P
* u# C* D4 V# D9 I$ E! i3 O$ W
BYTE        APU::ExRead( WORD addr )! ^* L  l- ]3 @! P; K
{$ ~; A0 }0 p" b4 a# D
BYTE        data = 0;
$ i% |8 O6 T1 _$ A; t0 x2 `$ K$ z7 ^0 i8 L! G8 }
        if( exsound_select & 0x10 ) {
8 n5 |3 t6 w+ J& I& o' I% p% H                if( addr == 0x4800 ) {: }/ s$ j; q/ F
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );6 e1 l+ G* K/ I9 i/ J: C5 J
                }. Q  g1 n( h) g, `1 x' l
        }! r; \1 {1 B3 `  b! }2 g( N
        if( exsound_select & 0x04 ) {
8 @" @+ m; k* ~                if( addr >= 0x4040 && addr < 0x4100 ) {
9 [1 t2 @! q9 f                        data = fds.SyncRead( addr );# k. ~3 Y5 X0 L/ g
                }
& _) q8 g' N7 @* t) k8 |        }: ^6 `/ A+ O" e9 h. K  m2 y4 e
        if( exsound_select & 0x08 ) {
$ |. a# ?  K5 M- @; z  ?2 m                if( addr >= 0x5000 && addr <= 0x5015 ) {) |2 U. o! d, R5 V. B7 ^
                        data = mmc5.SyncRead( addr );! q' W8 Q) g" G2 z3 e
                }, x  {1 v9 r$ P* q8 P
        }
+ P/ i* Y% d- c. _4 t" L+ U: C- u/ T1 j- M. a. y$ W
        return        data;) F( b9 x# F: n/ c2 _$ ]" q& G$ l1 l
}( v7 ]) X5 u" j5 g
$ a1 U7 V" p: v  N( ~% b, e
void        APU::ExWrite( WORD addr, BYTE data )
8 p( e+ t) Q3 |: e{
) d2 v3 e$ B7 ]        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );8 L  Z1 L! X9 \# T/ |* ?9 z' H- F
2 t* T+ f8 C: z, i2 ?5 K7 N2 G' N, K
        if( exsound_select & 0x04 ) {
) e! r2 ]4 j8 \# u( r) ?                if( addr >= 0x4040 && addr < 0x4100 ) {
1 V1 X  y0 k/ b$ W3 a6 g) C                        fds.SyncWrite( addr, data );6 Y7 x- \+ N& ^# `" n- H, \. \3 y
                }
9 s/ Z2 t8 O1 n2 m0 R  \% b) C" @        }
# f. |  c  ]+ O3 ^/ p: e. n6 m! L, U7 r9 N7 F) Q- `1 z% y
        if( exsound_select & 0x08 ) {; }$ W3 r' `' C8 D, Z
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, w; m- {: K$ X/ @! u                        mmc5.SyncWrite( addr, data );0 h3 h# V/ ]$ y1 d, T+ U
                }0 i# S; p; q( `% w
        }& _5 w- H! m8 Q* _$ A
}3 g, @, |5 o' p( Q# }3 Q! O5 N

0 E# X8 Y9 o) r- c# Nvoid        APU::Sync()- @  t( I% B6 U' R6 h7 j# J
{
; J7 _8 A& N7 {+ i* D}8 c2 k6 b" q7 c4 `5 Y

- g. q; }# J1 qvoid        APU::SyncDPCM( INT cycles )
, @( E7 W* t. R$ D$ X{
. s$ ?- c  d7 b6 j+ u6 O        internal.Sync( cycles );0 q) j6 O  j! r
/ g0 S4 v$ z+ M
        if( exsound_select & 0x04 ) {
* W0 u# {1 W5 Z8 ]3 G; E; Y' _! V2 M$ J7 c                fds.Sync( cycles );
" P/ K. @1 f# O        }
$ c  S1 j9 {. I+ h' @- s        if( exsound_select & 0x08 ) {& @0 \) T  M3 l* g) F. n1 d7 K) i. n
                mmc5.Sync( cycles );* v2 P( g; V$ [0 @8 r+ T
        }7 J- t- j3 e& k* {1 U. i' x
}
; C" I# M' _+ [
2 B# X" u" \$ ovoid        APU::WriteProcess( WORD addr, BYTE data )7 B, c5 v, p; E( V  U' x
{0 T, |# z- o, E7 k: F" h9 y, z
        // $4018偼VirtuaNES屌桳億乕僩; E% U# i7 y( B5 ?; w2 K1 o
        if( addr >= 0x4000 && addr <= 0x401F ) {' G7 G3 H+ `& M, n5 U
                internal.Write( addr, data );
. |& v; M5 b* \5 Z6 U  Y3 P: ^. G+ ~- i        }
6 B; G# _9 {: U( Q: r}; I) T$ b( ~% ^/ T
/ X5 R, y& n( d7 }: t2 B
void        APU::WriteExProcess( WORD addr, BYTE data )2 {5 k- g% x: }! I
{6 h4 ~- D0 f. ^0 a: R6 y9 R) O
        if( exsound_select & 0x01 ) {
0 w' I# D+ l. V# P( L2 ^                vrc6.Write( addr, data );
& X$ t' l3 g! C$ G- b; e        }
6 v$ W  f# n0 V$ y- \4 D' B/ t. y        if( exsound_select & 0x02 ) {" ]; C* Z9 W0 k# [
                vrc7.Write( addr, data );
1 U1 e' g' R" W        }
/ t6 X3 e* t; F, S5 C        if( exsound_select & 0x04 ) {/ @' M/ j5 E1 k+ N5 Y' c
                fds.Write( addr, data );6 S- J# ]" B* f7 _) M7 N
        }+ i7 f6 G5 V" l6 B; x# B
        if( exsound_select & 0x08 ) {0 a" L! F: S: m4 H  C
                mmc5.Write( addr, data );
4 z0 ~0 Z8 L" Q4 h7 J8 Z' L* H" m        }' o$ k9 a3 H$ R( D
        if( exsound_select & 0x10 ) {
* o& `1 G/ g: J% W; I8 r9 {                if( addr == 0x0000 ) {0 o: |5 ^2 N" }( b9 v& ?9 U$ {
                        BYTE        dummy = n106.Read( addr );8 b* G. h* Z. P
                } else {
8 B1 I' M; R, h  N( {; {% H                        n106.Write( addr, data );, }5 o, P0 m  C: `
                }
" i  d6 q. v0 L' Y# `! L        }4 q: j+ u3 [' u
        if( exsound_select & 0x20 ) {
# E1 Z/ ]# o7 @$ h& y( s$ h                fme7.Write( addr, data );  p7 `' k# {  K. Y5 l
        }
4 u6 y/ q$ B+ I+ m! j}
3 S+ i7 q. M! @* c# v) ]) D: H- n; N4 E1 F4 L
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
# B$ K5 t1 t$ W0 K{3 [! c9 o# {7 n, n
INT        nBits = Config.sound.nBits;
% O1 ~" p0 ]$ i7 ?6 A0 R% |+ PDWORD        dwLength = dwSize / (nBits/8);
- |. f( N! q- `: t3 c4 {% U+ t) j$ c: KINT        output;
. b9 ]0 F2 X4 ^$ h7 l/ e, CQUEUEDATA q;
8 v) @9 o: a* E& c) n3 \7 pDWORD        writetime;
+ L1 T+ n6 l. Z+ c8 s% \9 J. O8 \3 _8 L0 W0 [  }( O
LPSHORT        pSoundBuf = m_SoundBuffer;
* K: `! B, V% H$ ^INT        nCcount = 0;
6 F1 y! M* F  X& ]
2 H% ?# n5 n! A/ A$ gINT        nFilterType = Config.sound.nFilterType;
, e; L& X9 O: e6 k# R+ G6 z
3 G, t6 e& E5 V4 S' A        if( !Config.sound.bEnable ) {' `$ a# g- n  p! G( S8 @
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
4 C8 h* p0 m. {: ?1 w% h                return;! F0 Y/ C2 a7 i  K5 d- p
        }, i, G5 q% D( @- y7 T$ k$ A  N$ S
  Y% @, a( N5 w0 I3 y
        // Volume setup
# q% W. T' q( \0 [. M6 ~        //  0:Master  S& d( ~0 n6 e  I4 j/ M( A
        //  1:Rectangle 1
" E' c0 K+ R# N7 n; r9 w5 S        //  2:Rectangle 2! C4 y7 A6 h% r, R3 o! s
        //  3:Triangle
' x5 l4 |1 M3 b% r( a        //  4:Noise$ r1 a7 u& E8 b+ \" u9 N0 p
        //  5:DPCM
$ ?) s' ~" G5 q        //  6:VRC62 }; u5 ^( A, L- b# _2 e  o
        //  7:VRC7. E& t5 T1 O6 ?3 F& h9 k: \# _
        //  8:FDS
. r' m7 ~/ e2 w# x" Q        //  9:MMC5
! p5 j0 n' q2 u  n        // 10:N106
6 C' F8 ]+ f5 w1 Z2 C, p        // 11:FME7
6 F8 l1 q. I6 n, [; P/ [. |. O        INT        vol[24];) p( Z2 K) n* g, T8 G! y1 N
        BOOL*        bMute = m_bMute;; T* l; E( H3 Y6 @# q" Z
        SHORT*        nVolume = Config.sound.nVolume;" @/ q: ?% z: r8 l) j. h# |: H
* N+ V9 v' z3 f+ }! b+ A6 W
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- O% s; x- k5 U. @

2 d4 J/ L. G9 Q/ V! Z8 W0 S9 P+ F0 a        // Internal
: O6 V0 H' O/ H) b, ~3 [" K        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 @* y. p3 A* u5 Z/ `
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# {; N% f( d) d  i" t- T        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
* n( ~: t! `) L        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 f/ S" ~4 p. ^: D" F2 _        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& H; r$ a1 \. }2 ^2 l: W% s
0 s# V2 l$ e3 d* D7 A        // VRC6( @8 Z2 }( t! b- U' B; ~
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 t+ ~. K1 h; c9 W0 D9 E) |1 N8 c$ a( k        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 t7 A, N/ {" |* Y+ C
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 F* M! \. h- E+ [( g- V/ }4 S, h$ t
& k# \5 k4 f+ n5 J9 K5 x  y9 i        // VRC7
. @' I+ T' }+ N9 F        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ h' e, R4 |' e) @) g  F1 S: C
9 k0 G% j5 h" ]5 _
        // FDS1 m8 T5 g2 G( b! I1 M9 J: |$ {
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& ]8 U: s$ q8 _
, Z' D; v, D+ j1 p4 @  v        // MMC5
- [3 C$ A" W, T& k- P        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 U2 |: l% r2 Z% ~: w, S: A        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" f6 z3 g; u# I        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* d9 ?) p* \) ?! n

% j3 N+ E' J/ U6 ^/ }        // N106
1 K; s5 f' \# A. y' K, K        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% f( t2 s" v" \8 e        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 r  F1 U' x/ H1 i9 V' o        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ s8 ?( `$ G# V
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 I/ e+ o3 n, l0 j# `
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  u% Q# k2 Y7 N/ M  q0 j4 G        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* T4 r; {' A& S( r( ~, \$ E7 M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 T, ^6 C+ a3 v9 n
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 V) Y+ e. u1 J- t

: L3 F) y7 z& I8 x8 D% x        // FME7
, h& U# f+ N4 Q1 k, U        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, \9 c0 ~% o2 r4 Q, a) z        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: `7 O  o3 l0 J4 c9 F5 Z  c: ~3 z
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  l. `+ n+ ~) G6 V/ L0 P9 o3 S
: i) Q/ i7 r" _' T7 L$ z0 [
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;4 l, W7 |; U" ^
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;1 @' j7 ^& ^: a8 i, V+ e- `; m
; E) H; W( _7 P2 q7 ~
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟4 p6 F. a8 l; b" U
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  ^* ^: F: J9 ?1 t1 Z                QueueFlush();
4 `# M( I* \( w. P8 K        }) Z+ {  S( i8 F
" `4 |0 O; V3 h, _9 T' |# }( c% y
        while( dwLength-- ) {* \1 l& z, r6 S# m2 P+ ^, _
                writetime = (DWORD)elapsed_time;
! {8 t3 i  Q4 Q' M. s0 f: }) p! T0 i! E$ Y0 ~
                while( GetQueue( writetime, q ) ) {
" ~2 x" i$ P6 h- Z                        WriteProcess( q.addr, q.data );  {  c6 |! ~0 J2 [) A
                }
' V3 n7 Z$ I* E1 g5 U% D4 R6 a8 S6 J! h5 z0 L1 D& c5 ~$ U
                while( GetExQueue( writetime, q ) ) {
# I& s' K9 Z+ @7 f* i, ]$ t                        WriteExProcess( q.addr, q.data );0 T% F! F1 [2 S) m- A, `( a
                }( D  o( X( W! Q* y( U
1 H. v3 }; h( k
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7' B. r+ P  G% r- [) n( b, i) B1 W
                output = 0;1 o6 [3 h( D9 @4 Z& z
                output += internal.Process( 0 )*vol[0];
/ f  T) ^- Q  z4 g0 Z" f: Y6 d2 p# {                output += internal.Process( 1 )*vol[1];
9 z4 w% ^$ ]; n- s1 I. P1 z! h                output += internal.Process( 2 )*vol[2];6 n- u% z# E( g: }7 n" p
                output += internal.Process( 3 )*vol[3];3 j# |  f! N* m6 D( X& C/ M+ F( V
                output += internal.Process( 4 )*vol[4];
9 k' g1 T. }# c& M) g7 r/ L& R) |9 R: X0 H5 e9 @/ a
                if( exsound_select & 0x01 ) {
4 E2 l6 i5 @9 L6 b                        output += vrc6.Process( 0 )*vol[5];
2 ^8 f5 J( v) b& y  R                        output += vrc6.Process( 1 )*vol[6];
! Q# b' O; O$ H% }                        output += vrc6.Process( 2 )*vol[7];! u6 T% }7 x5 \
                }
: o% {$ N8 o5 d3 \6 G$ Q                if( exsound_select & 0x02 ) {
3 _1 i1 L1 g* B% c2 [                        output += vrc7.Process( 0 )*vol[8];# v5 o5 ?5 J4 R
                }' @3 _& z( H3 O6 V) K3 \8 m! |
                if( exsound_select & 0x04 ) {' _& q3 \8 ?- z( @6 Z: S3 u
                        output += fds.Process( 0 )*vol[9];
3 \1 |$ P& [! v/ j                }
# Z. Y$ ?8 s! q2 x/ p7 W                if( exsound_select & 0x08 ) {, q3 R3 O* q% i; z) V
                        output += mmc5.Process( 0 )*vol[10];
8 Q6 e5 @' ^$ c& G1 c$ {                        output += mmc5.Process( 1 )*vol[11];
* v5 W& F7 V: ]/ Z" }! G+ A3 R/ K                        output += mmc5.Process( 2 )*vol[12];
1 T3 h2 w+ Z# Y% v2 L/ H2 N                }
" }" I1 c$ a* \) m- A                if( exsound_select & 0x10 ) {
2 u+ _# p1 H: E                        output += n106.Process( 0 )*vol[13];
: {0 ^# Q2 R$ F0 ~) j6 m                        output += n106.Process( 1 )*vol[14];- J( o+ O" p/ U( t' t
                        output += n106.Process( 2 )*vol[15];
# e* t1 q' z9 c+ o: |                        output += n106.Process( 3 )*vol[16];
. ~5 I! J9 n5 ~2 v) T, R                        output += n106.Process( 4 )*vol[17];
9 B$ K+ H: I: Y- p% W                        output += n106.Process( 5 )*vol[18];
7 u! E+ f( r. [                        output += n106.Process( 6 )*vol[19];
$ L' T; L6 I8 i# \- O                        output += n106.Process( 7 )*vol[20];
# Z5 b. u, E& T) J6 b1 |, F! ^( e  {                }8 f2 l; N. H( ~, z+ {
                if( exsound_select & 0x20 ) {; _8 Z  `7 s. `. C7 F2 c% a
                        fme7.Process( 3 );        // Envelope & Noise: y4 J' u0 ^& t' D0 M
                        output += fme7.Process( 0 )*vol[21];
6 w+ y3 B  \5 E  t1 |; n                        output += fme7.Process( 1 )*vol[22];
: x1 Z% u0 p0 l) f% S                        output += fme7.Process( 2 )*vol[23];
/ J2 C+ \' H) m2 t8 @                }1 Z* U, e. p; Q' {- V

) G8 `4 R9 d% l6 w                output >>= 8;3 v9 g% i9 T- z8 u: ]3 \- g

) g) k* _1 b9 R; R                if( nFilterType == 1 ) {
( H6 C1 u3 s" N! v: R2 M                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
$ }$ M6 @/ u* y3 v  K) ~' ?& a                        output = (lowpass_filter[0]+output)/2;
; ^0 j5 p5 g$ F7 s# K& D                        lowpass_filter[0] = output;, a5 a3 C8 H6 M+ X; i4 V3 b5 z
                } else if( nFilterType == 2 ) {
2 I. n; b5 v+ c0 g1 U$ i                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
* X* G4 H) m3 ]/ ~                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
% ]  A/ A: u" ?& N: p                        lowpass_filter[1] = lowpass_filter[0];
: J% w* N2 e+ m. K                        lowpass_filter[0] = output;
! P) T+ y* O) k' N7 n                } else if( nFilterType == 3 ) {# d7 L7 {5 v" _# L" t9 T
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)8 r( ?4 y" Q: G0 @* \" L' k9 l+ B
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
, }$ @+ G  D( s) F3 z) X6 O) n& B                        lowpass_filter[2] = lowpass_filter[1];
4 L2 Q& P0 u' Y! P                        lowpass_filter[1] = lowpass_filter[0];. K& H4 p$ x3 S
                        lowpass_filter[0] = output;
& G: G2 V& l! p: i* S  t* Y                } else if( nFilterType == 4 ) {% c- r. m0 E: @1 o, o$ M
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# j  b% w. B% N# F
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;/ R; s; x& z- A
                        lowpass_filter[1] = lowpass_filter[0];
- Z1 L" C+ U+ l$ n% Q0 }4 C: Q                        lowpass_filter[0] = output;5 v9 f& C0 H+ B& J: ]4 l
                }4 i3 F" E8 Y% s* ~8 K: w

9 [2 `8 {7 c. H- }" W! B#if        00 Z; x$ D7 x% B9 A
                // DC惉暘偺僇僢僩
2 S; ^' }( U: I5 G' ~$ b/ B! h                {
! n" f1 ~* R% B- F! n4 S                static double ave = 0.0, max=0.0, min=0.0;6 N. R2 c: n: U: s- E# d0 I
                double delta;
1 }$ C& L: w# @' g2 U                delta = (max-min)/32768.0;
* l, F+ @. o/ d                max -= delta;9 C, _$ D$ `0 E
                min += delta;
" Y( s5 G  K. l! ~) S9 J0 j                if( output > max ) max = output;! M& c; ?' [* \, M3 a* Z) s0 {
                if( output < min ) min = output;
% C, p6 h5 V% D: j2 w( S                ave -= ave/1024.0;
$ o% `- ]+ d) a  C0 V( j, l: n, [( M                ave += (max+min)/2048.0;
% t9 a# t6 p- j& |                output -= (INT)ave;
5 x0 U5 L. }! }/ b                }( s$ F; g# J' R6 S& {% l
#endif8 ?. W7 ?$ L& y! N& I! [( q
#if        1
( S! N. }  {& T9 k                // DC惉暘偺僇僢僩(HPF TEST)
$ \9 J* x9 p9 Q( `& u1 h; D$ y3 @                {; Q/ f, M; E# j" R
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 n) i: H4 Z7 v: V                static        double        cutofftemp = (2.0*3.141592653579*40.0);
" _5 m: u) _/ K1 A2 u                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 N4 F0 [  P* Z+ W( W, B. {                static        double        tmp = 0.0;
; z+ O/ S6 w( k$ F8 }& m                double        in, out;# \- j, W6 W! i" R
" k: e; u) J! W9 g) |
                in = (double)output;
: v: u7 a& P# m" ]* A                out = (in - tmp);: ?' H  G" ]$ V/ d6 O3 s/ S
                tmp = tmp + cutoff * out;
3 ?( @2 V. k5 |0 e6 }6 r1 W, U! z3 j2 I4 `$ o2 u
                output = (INT)out;( F+ S; h4 h5 z% h2 Z0 P
                }
4 U' R/ d) c0 g#endif+ O0 |' z! U( I  ?; F9 ?
#if        0! ~: q. V4 E+ O3 M7 _
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
0 d: N$ Z& X/ ?" w. j                {
, [. U( e; O! v7 O" L3 E. d2 z                INT        diff = abs(output-last_data);% d% e5 f6 i) h0 O8 }
                if( diff > 0x4000 ) {
4 D! K- d8 u7 m, q2 h- s  p, g; U                        output /= 4;3 p1 G5 {; |1 s' _0 z
                } else
. ?6 D2 Q. v; _* I                if( diff > 0x3000 ) {
1 r+ N( [3 _; L& d- x0 r4 E' i                        output /= 3;& L( i% S8 X; G) o' ?
                } else. V/ J: `, n; v
                if( diff > 0x2000 ) {- J" {. u- C; Z  W% |9 G
                        output /= 2;. S4 Y0 P4 H! J0 i# P7 Q" s
                }9 `8 G- v* V/ Y* }+ z* X1 G8 H0 t
                last_data = output;# n9 f+ ?) h1 w5 E" \0 W0 x2 K
                }$ Q( d7 J" s: ]
#endif
. Q$ b1 `# `; N0 ^' S8 Y                // Limit- `& C3 {+ M& q5 _2 h% ^( Y- a7 g, ?  W
                if( output > 0x7FFF ) {
+ }3 [/ G" h9 i. t0 z                        output = 0x7FFF;: p8 t- P+ c7 C
                } else if( output < -0x8000 ) {
; W# T6 e' {- m2 t3 C8 s. j6 F- v                        output = -0x8000;
8 g1 d+ |* |& n/ M                }$ H3 l+ e# H  l1 v" D# T% ~) I
6 o. X% V4 R2 t3 B0 _
                if( nBits != 8 ) {& m" o& _$ D( W0 F) ^; d9 @
                        *(SHORT*)lpBuffer = (SHORT)output;- S$ [4 p6 \6 p% Y4 r
                        lpBuffer += sizeof(SHORT);
& L& D4 r8 ~' G) f9 N                } else {4 \4 _9 A/ C% ]5 g- K
                        *lpBuffer++ = (output>>8)^0x80;
+ h7 ?/ C: u- \5 s                }: v& T5 I: r8 J/ B
4 {9 D9 u8 a! M; G
                if( nCcount < 0x0100 )
; ], Q- a( V1 [2 m                        pSoundBuf[nCcount++] = (SHORT)output;% ~  k; Z6 \9 }$ h1 q' j3 D

' \  e4 k% L0 ]//                elapsedtime += cycle_rate;) B' J) Q6 _; `7 S
                elapsed_time += cycle_rate;$ f' F3 p* [4 i, a+ H- j; B
        }
# {/ R+ l4 r8 F+ n+ p' N9 ~( C* |% \  t+ s& t4 z0 Z) X; u
#if        1
# r6 l7 X* b  c# T: f# B: k        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
8 M( d* K" `9 n& b& O$ b6 i                elapsed_time = nes->cpu->GetTotalCycles();+ d+ S. l9 O& ]8 C
        }1 |% R4 B( `7 H0 U. d
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
- k( ~  M! D: v; N! C                elapsed_time = nes->cpu->GetTotalCycles();$ B, y9 R! Z! B) R4 r  S( T) K: l% ?
        }
. M+ o, K* l  S" S$ d#else" \6 C; W$ K7 t! R0 }
        elapsed_time = nes->cpu->GetTotalCycles();% \  ^" e+ I" Q5 f# i8 ?
#endif
4 @/ @" |) ]2 g' p}5 b+ X$ m, G% }: j  P, |- W: n

1 i  l$ w5 K% G, O6 O- H, W7 F* a7 }// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)) N) q; l9 u% V# P: N! h5 H( P
INT        APU::GetChannelFrequency( INT no )% G* y8 w# n4 b! l% h. h
{3 U2 p; o( [. a4 e3 M4 d; q2 z! X
        if( !m_bMute[0] )
1 o- h& v8 B$ A$ Z) B2 t. q                return        0;
$ W; M' Y! ]& o. ^, i7 K9 p% A% C! e4 q- j1 v8 i
        // Internal
. M9 Z2 E" |8 d) ?8 M        if( no < 5 ) {* c2 {  P0 z8 i' A
                return        m_bMute[no+1]?internal.GetFreq( no ):0;: X& m9 B* V  \5 l; z
        }! |! U- o6 V( I$ N) }# ^& E
        // VRC6
9 `, K' S* L% L. V# O2 G0 t        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' X! D( a$ F8 R$ F: Y. O4 C# x                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;) r/ [0 D+ f. a3 u. U4 G' u( k5 \
        }5 L) V* Z* E# |6 D/ s
        // FDS& h, g. i3 @$ q# u5 A5 [
        if( (exsound_select & 0x04) && no == 0x300 ) {% T6 b2 O: Y  W8 {# q7 z6 i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;: \4 `- U) C8 t2 t3 U' w8 G: d
        }
5 m' V7 T; \! d8 J        // MMC58 _. B0 b7 O( S' u% q
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; Q2 ?( |& @! ?& i7 V( P, g/ I- S                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;! ]7 q4 x' h3 x( ^6 y" g  \
        }
- \2 L& `- }6 }' O        // N106- l3 k) I  I2 ]  M
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
! k2 F. H) `. i                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
) {( v/ A! @3 C' T* w4 x/ H        }6 L( R/ U3 \5 r  t0 G
        // FME7
1 o7 o6 J0 A: u) f# ]        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {  \) \$ w# j" S+ N7 b! ?3 S9 T
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  C, D4 N! x* w- r0 r% J        }: L( g2 Z8 W/ h4 J4 @2 L) S" z2 D
        // VRC7
4 E6 L1 z) f5 B/ |% {% _        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {( W0 t( Q# A" a1 z  h: g! K7 a! ~
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;: W; U) V0 t& Y2 L
        }
' x; d, y# y9 {2 \9 u        return        0;% u8 r4 C' ]3 V( ?- W; i# s
}  |4 z" e7 i! X1 y* h% v0 p

; f1 N" _# t1 O; U0 T// State Save/Load/ a# H) A% i: ^& f' s1 v5 W
void        APU::SaveState( LPBYTE p )+ w8 M4 x) u9 }3 u3 }3 C" u
{
% H4 T8 s  U" {#ifdef        _DEBUG
" w) p' Q3 F( w# n0 o2 DLPBYTE        pold = p;- @7 v4 U# |7 K$ \( r- U- [% \
#endif. F2 r- a6 ~5 J$ o, ]
% m7 @; q5 M7 f5 a: W
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
7 G5 l. y! F, s0 I$ _        QueueFlush();
1 v% |1 f; q7 u" a
  Z; x* i- S9 B& N& d* l6 X        internal.SaveState( p );7 m0 u: k1 N- I( u- K$ s; j" T# d5 M
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# U2 g5 {0 |# z7 d9 y1 d) T: n- C' g$ K" p$ e+ A2 `2 H9 T( i
        // VRC6
  b: |$ F- q7 Z        if( exsound_select & 0x01 ) {8 w- F  h' E& _5 P$ y
                vrc6.SaveState( p );2 [' j. c/ |7 Y. g$ q5 ]
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# H% h7 w$ J% s" ]
        }
0 A6 f% u! |/ \( Y        // VRC7 (not support)6 H7 L. x/ z6 d$ N! X
        if( exsound_select & 0x02 ) {
! C/ k# I1 [- ^0 g; |2 N% D. s2 R                vrc7.SaveState( p );
; O7 v$ B) y% Z7 N3 ^, m3 Z# N+ i- L                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. s- T; p& i& y0 ^: e, i, J5 a
        }) N# z; j3 J6 D7 D
        // FDS* z% V# [6 u  w2 I, [, a- A
        if( exsound_select & 0x04 ) {
# q6 @& R2 Y7 \* M8 r                fds.SaveState( p );
  J7 Q6 [$ h: \7 V( L9 s" b0 l                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- g; r& {0 }, g3 X, o: O        }
0 |5 c, \( ?$ C2 A: Q7 U3 L$ f/ G        // MMC5
0 Y: s+ O; W7 L5 y        if( exsound_select & 0x08 ) {
# s9 K4 t  E# ^, w7 k  X                mmc5.SaveState( p );: `/ M2 e$ a2 d9 u* q. r/ j
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. r3 ?% o2 Z( j1 _( [: v  M        }4 S, p5 D6 d- e  E% m
        // N106
, F+ e6 t' a6 K: ~+ d3 X- T8 K- w        if( exsound_select & 0x10 ) {
* E. _: e* |  j                n106.SaveState( p );0 ]& b* j$ d  ]( `* |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ X6 T2 m% C0 M$ X& v. J1 F, l  z        }
7 k4 X: B; E( N! p9 |. L1 G& A        // FME7
/ g8 e" }/ n+ ^. F        if( exsound_select & 0x20 ) {
" T( ]% {8 B$ C* G. t: i                fme7.SaveState( p );* [, |( t, X3 ?  u7 @
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% z& V7 j1 p2 u, R  o3 C        }
. f3 C$ j9 V6 n( x: s! R' \: |2 V. `& S" w( c  \/ ?5 p4 g) |
#ifdef        _DEBUG
1 m3 O5 D5 h  Y0 Z/ KDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
( l- h  }6 E6 S8 E# j#endif
% }7 p! M. G5 N! k}. }' h! m) p" ?/ V# i) ]# G

8 D' Q' N6 n6 t: @void        APU::LoadState( LPBYTE p )
7 ?! @2 P) g/ D9 f9 e& b; g8 K4 V{$ M! A0 g+ X7 T* v* M
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 k6 F5 s6 q! Z: ^
        QueueClear();
" q, f& T& o8 n' U4 R) K4 Q# b
1 I) y9 h2 a) [/ i3 U, m9 s        internal.LoadState( p );' H- Y9 `- M0 r
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ x0 e. t5 t" A; P5 K

" ]- h: J1 ~0 c$ R& f- b0 i7 t1 ?        // VRC64 ]3 t; m/ ^; b  p8 o, e9 q* r. g2 v0 q" i
        if( exsound_select & 0x01 ) {: j) W& h5 Y3 V& `9 Z0 @  W/ W
                vrc6.LoadState( p );
* k* i+ K0 d3 b7 F' m                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 t  W0 i8 Q- I, w& Q5 [8 {
        }
' }6 g1 @; D3 C        // VRC7 (not support)
- l  V9 q- t2 U; i$ o0 o( q: {        if( exsound_select & 0x02 ) {
& [: o- f) ?5 H; y( A                vrc7.LoadState( p );& E9 l+ b  [  Z; k# e! y
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding! m( j$ ~* I& p. F& F- H
        }
& S5 G9 p! R$ q+ |- M        // FDS
# I& |8 ~+ Z- K0 ?1 I9 [        if( exsound_select & 0x04 ) {' \) I6 h, H8 o4 h' L
                fds.LoadState( p );; G1 a: i8 Z; w; V  [
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 ^, F3 j0 n/ w* d        }% G( P: q# g+ N  T+ Z) ^
        // MMC5
5 H1 b5 I/ v( e( `" D" m        if( exsound_select & 0x08 ) {1 C$ m: A$ P2 c* Q$ s
                mmc5.LoadState( p );; T6 z* W. n7 D7 K2 B
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- h7 k2 e: m8 Z- n7 L& x9 Y        }
, F+ [+ j  D/ V/ x9 \        // N106
2 c4 o: w) t) l1 D" s# k0 b) Z        if( exsound_select & 0x10 ) {
# I4 z' p7 q3 u/ J                n106.LoadState( p );3 h* {. l, G! M/ N' g8 X2 d; Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' X+ v5 y4 l1 i  u6 q3 q
        }
. Y: e3 G. m! D2 y! u; x        // FME7+ O8 y0 ], v2 R# ^
        if( exsound_select & 0x20 ) {
( \/ H9 m$ ]" |0 a" o! v                fme7.LoadState( p );
" U8 `& a' {, Z& j1 F* J                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 t( j# ~1 U  d# e        }
$ A* e7 j2 v7 r' c5 x9 o3 w  B9 q! @}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ' \! s% @2 L* V# U! ^( H
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 \. ]( [) Y2 F/ S感激不尽~~
7 n/ h7 ?; V4 Y6 O3 D
恩 我對模擬器不是很有研究,
& q  U2 e4 p3 R8 i$ B) U9 y9 b雖然要了解源碼內容,可能不是很困難," U) d- A7 M( e1 Q: E
不過還是要花時間,個人目前蠻忙碌的。
* x7 F+ |; Z2 w4 ^' r* `8 O
, X, O- L, }3 ^+ H; }給你一個朋友的MSN,你可以跟他討論看看,6 W5 }, `: X0 n9 L4 r- m' o
他本身是程式設計師,也對FC模擬器很有興趣。/ n7 o# f& k& Q5 n$ Q% @

, A# D! h/ c, W6 Z: i2 {1 l- @MSN我就PM到你的信箱了。
& j+ f0 h4 \3 E. m3 Z7 U' r/ x' [
% u( {) B( |! E& _3 h# @; U0 b- Z希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
: S4 h! o: W* ?; C2 e呵…… 谢过团长大人~~
- v2 v4 x4 k4 C( Q3 D/ c( b) N! x7 P

* K' ?3 ~: }6 c5 I& J哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 7 e- b3 _# I5 M' g
团长的朋友都是神,那团长就是神的boss。

7 x' ?& E# u- ]6 Q7 D哈 不敢當,我只是個平凡人,
( M9 l# @3 A( E( Q+ V要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙) s. |& j. t" }- R5 O4 f/ Y! H5 ?
ZYH3 j; @0 d* y; e. I" t6 ]6 @3 l& t
QQ:414734306
1 @3 C( Z* ]) t* e. fMail:zyh-01@126.com; l, @& M- g. L5 b0 y& U6 u! F2 R

0 a/ V3 |# u" e" B  Z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 " S; Y8 H2 j: A2 E4 `
再次对团长大人和悠悠哥的无私帮助表示感谢~~
8 [  t/ l$ O8 N2 Y, d% O8 r& s
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-9 13:51 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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