EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
0 `1 v' F# Q( d1 a/ d& SPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# }) r* C( d% i) Z0 V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 X' C, H! a+ x$ e  ?& J( g这里有相应的模拟器源码,就当送给大侠了~~
4 ]# K1 ^$ N% lhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
; ^2 V4 X( F. b1 ~' y1 S能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 r" S- H" S1 y5 M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& n% i/ w: l7 h6 ^, S2 l
这里有相应的模拟器源码,就当送给大侠 ...
$ A& a3 a2 d8 x
聲音部分(Audoi Process Unit = APU):
1 L) q; o1 A6 `  \, o+ c6 R.\NES\APU.cpp
. b- j6 u# p3 [' {2 D- X.\NES\APU.h
/ j& ]- w/ F( o9 g, S7 G& w
5 p5 g2 C1 N* \+ p. ]3 m$ ^& d
0 s% U5 T, N5 \3 A2 e8 A影像處理部份(Picture Processing Unit = PPU):  v. x( C3 d9 N. T8 p
.\NES\PPU.cpp" l% f" R* P% k
.\NES\PPU.h
2 ]* @3 I/ Q2 T; Q
/ ^, O/ S  @. ?/ z如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, v1 [, j" w9 t9 x7 e) N' B感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:! c" @% Y1 s, R: X3 _
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; L3 D) ~  d) @* Q//////////////////////////////////////////////////////////////////////////
. k- o+ [0 p# ~3 V, F. ]4 T5 {5 E//                                                                      //7 `; x  h' w0 K+ r& w
//      NES APU core                                                    //; C, c- a' A" A. E1 v
//                                                           Norix      //
0 v. Z5 V2 o; \% w//                                               written     2002/06/27 //" o. s' r( {' Z5 u
//                                               last modify ----/--/-- //7 ]' u- V! u7 J& s3 @
//////////////////////////////////////////////////////////////////////////# E9 T' T( e4 `7 W2 ^2 V  ?8 Z
#include "DebugOut.h"
4 ~- A; y- T  j3 Q#include "App.h"
5 c$ ?& D$ H% A/ ?  |( i#include "Config.h"
2 N4 I5 m# _) x! f5 U! M
) J+ l$ {# l$ x2 s) L#include "nes.h"% I; _; z1 m& i; j  D* [7 \" g
#include "mmu.h"
$ m# g$ D, C) A9 C3 t#include "cpu.h"
- }  B+ I: T- ?5 n#include "ppu.h"
! u) r: z4 p. N3 D#include "rom.h"; R9 J- b5 F2 s5 w  u
#include "apu.h"9 S6 K8 T: Z; p

9 Z7 p- `' i1 d8 r+ ]. K// Volume adjust. \8 ?) n0 s3 n6 w4 p* g0 w
// Internal sounds- j3 f% G5 u% m8 @; B. Z' f3 }$ M
#define        RECTANGLE_VOL        (0x0F0)
& |- |/ h7 h3 C! C5 |& s6 N#define        TRIANGLE_VOL        (0x130)
6 A" n, _; o8 i+ [3 t( g) T#define        NOISE_VOL        (0x0C0)5 p- h9 h+ R1 B' O) r& Y+ r4 c4 ]
#define        DPCM_VOL        (0x0F0)* Z% Q1 {4 w/ h6 `. t- }3 T
// Extra sounds
- W- }8 n- B4 G#define        VRC6_VOL        (0x0F0)
: `4 F% [5 ]2 z& E, C9 ]4 `#define        VRC7_VOL        (0x130): K) K4 k8 `3 _3 G  u" S
#define        FDS_VOL                (0x0F0)
; S/ i. k/ t- b4 v+ J3 E$ z#define        MMC5_VOL        (0x0F0)
* p' P5 J/ N0 @. {#define        N106_VOL        (0x088)9 F. |, D+ b3 b; t5 ~9 F2 Z
#define        FME7_VOL        (0x130)$ g; @6 B2 v( v( ^( T

1 S2 M0 R. Q) YAPU::APU( NES* parent )! G8 J, x2 j3 R4 @( l
{
/ w7 s& [  a7 L" S        exsound_select = 0;
3 w# ^3 l& R, x) E- \6 r
( O2 y1 s  F: P1 y7 y        nes = parent;( c6 }6 D; t% v
        internal.SetParent( parent );) v+ h% S. Z+ _
. _# e' l! g/ m# P3 @  \& G
        last_data = last_diff = 0;
- v; B2 \# C8 W: b% j; u/ Y! F+ H  k% {7 e+ f! `
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
* g$ j! p" t  I  J  {
: b8 K6 J  O! t4 X/ y( f- I9 r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );1 w' Y8 L: K. E* ?) Q8 H# V& i6 Z
        ZEROMEMORY( &queue, sizeof(queue) );
  ?" {; i9 F. g$ B4 o1 U        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ o" N) j4 {+ Y- C0 [) @$ k

8 T* Z! \3 A# P, P% D6 |; [4 A        for( INT i = 0; i < 16; i++ ) {
+ F& M8 a/ N! D5 S( ^5 T                m_bMute = TRUE;
" B) U5 J1 M6 t+ u% D1 t8 K3 i" \        }
2 ]% @1 b/ j' R}
5 p) {! _9 p: n- c/ K0 N/ c4 [( |: i7 H+ _6 h! s3 x" v' j/ V4 f
APU::~APU()
' ?; T: O2 C& P9 [{, w% M9 ]6 w4 a3 N5 ^& m8 m$ b
}) T. K& @2 |: X9 w! E3 c
& Y% c, q+ R" C* g+ c
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ Q8 T' Q3 V$ u  m8 A' b7 B{' B/ t, t( a& b( Y
        queue.data[queue.wrptr].time = writetime;
6 C, m: U0 G& \        queue.data[queue.wrptr].addr = addr;
- Q$ `( B& m0 Y        queue.data[queue.wrptr].data = data;  k+ f9 [/ O1 u: A- h3 U3 v+ g
        queue.wrptr++;& _* v) \; r9 L' w( A" f; }
        queue.wrptr&=QUEUE_LENGTH-1;
6 o4 y- j1 u3 ~/ J        if( queue.wrptr == queue.rdptr ) {
! A3 ~; Q/ y, r3 E7 P! D9 t                DEBUGOUT( "queue overflow.\n" );! c2 _& m( b3 C
        }4 Z0 C6 t8 h) v' G+ b
}
" k* a# ^1 n6 u% v* C5 T
8 c9 M, l" l- |9 p8 ^BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ U( N" C5 j6 t/ U$ ~. A- u- c
{
7 e: [; K* `! _! X7 j$ {" S        if( queue.wrptr == queue.rdptr ) {/ u6 g. ?& `& V: a
                return        FALSE;  K# S; f3 Y  ~3 q
        }
# t) T3 c$ M& X5 V, A        if( queue.data[queue.rdptr].time <= writetime ) {
$ G1 K- @6 b$ Q9 n                ret = queue.data[queue.rdptr];
$ k/ C1 W0 J& H/ F$ Z: f                queue.rdptr++;( a  V4 U6 f) ~* Z0 X8 H
                queue.rdptr&=QUEUE_LENGTH-1;
# Y+ M& G9 @- ?) }5 R                return        TRUE;
* [) Y' p1 w" s0 ~' A        }
1 C* k3 _" {  Q. C        return        FALSE;5 {  S+ }7 p( ]
}: z  M, j0 P. q! E
- c4 o6 w6 I' X& w! F
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
  Y. m. O4 p  b: j6 i{
$ E0 V9 G9 m: j5 i: [- J. a        exqueue.data[exqueue.wrptr].time = writetime;  }9 i, H# j) L0 z
        exqueue.data[exqueue.wrptr].addr = addr;
8 `5 h* V  T0 ^4 s# V$ j        exqueue.data[exqueue.wrptr].data = data;: n9 `/ m4 Q5 a8 H
        exqueue.wrptr++;
! H  O0 g0 @3 z5 L        exqueue.wrptr&=QUEUE_LENGTH-1;+ Z( x0 ~6 j. z) F4 }" _2 B
        if( exqueue.wrptr == exqueue.rdptr ) {/ c( ^( s7 Z; C( z; Z: ~7 ]/ N9 C
                DEBUGOUT( "exqueue overflow.\n" );. |' e/ r5 |& }& f2 a' f
        }  z* a6 K/ y6 ?, F
}& P/ O2 G8 c1 }+ F. f3 @0 Z, ^

. `6 d3 {4 Q& d  ^BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
0 A, O/ ]) I) P3 G& L, L& N0 N8 N{
8 x4 _% ?$ ?& M9 X        if( exqueue.wrptr == exqueue.rdptr ) {
7 o8 @/ n6 Z: h. W& h                return        FALSE;4 C+ w" A+ D( u) |$ s' A# d
        }
5 o. n7 q# B9 q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
- F8 o: t/ F7 l$ ]7 q# H6 v- K                ret = exqueue.data[exqueue.rdptr];; I+ b  P/ G- c: j9 M' a
                exqueue.rdptr++;
2 Q3 |  j! ]/ A! o, Y6 t                exqueue.rdptr&=QUEUE_LENGTH-1;& L/ U/ w3 S+ c6 g. ?9 N
                return        TRUE;8 b8 F. l$ f0 v
        }; R' N* K$ @$ \
        return        FALSE;2 r, \0 g5 n: G
}
2 k, E; l5 C& V5 a
" T- a1 K4 H: S) N# tvoid        APU::QueueClear()
& h4 \3 k1 {0 k1 K9 O  @# [7 b{3 a2 s" r" e# z9 u3 J
        ZEROMEMORY( &queue, sizeof(queue) );* U' n, a4 T' \: ~6 n0 Z7 Q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 ~7 J- c; N( e# B- h9 f
}$ N) x' h: p' t$ C9 N
1 Y" e0 b% y4 A4 b$ \
void        APU::QueueFlush()
& y/ F8 p& t5 j{/ r2 B; K0 _' d/ t8 J$ p' X  j
        while( queue.wrptr != queue.rdptr ) {
+ n: F& o" W/ O; @4 k                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, q* ^/ v8 E4 R' l. {
                queue.rdptr++;& r+ L: |6 o1 [& Q) M# q) ]( t
                queue.rdptr&=QUEUE_LENGTH-1;
0 Z6 _4 k* d$ G5 x( {- P+ n8 r        }
/ K3 M4 y1 f2 L) I4 l' @8 ]; u1 U1 f9 D  t$ n
        while( exqueue.wrptr != exqueue.rdptr ) {* Z9 i9 m3 e# k1 M
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" F( M$ j  s, s4 o4 A: M7 `, Z8 a0 @
                exqueue.rdptr++;
8 D3 [3 G% w- T7 h: l; M) g0 Y2 `                exqueue.rdptr&=QUEUE_LENGTH-1;
0 @( J' ^' U: W' I        }
4 M. T- ^+ `9 o, K# W9 E3 l! ^}. }. m5 N% o' B: d0 z

: t& _8 j9 A" T! `6 t( \& hvoid        APU::SoundSetup()
  r2 o# P5 v' T{
# J; I8 Z) X4 j0 R0 T8 }        FLOAT        fClock = nes->nescfg->CpuClock;
/ K4 o! \; V# R2 @4 a( W        INT        nRate = (INT)Config.sound.nRate;
$ k1 Q; t& ]9 S( b% v3 e        internal.Setup( fClock, nRate );" A- _# D/ J3 |
        vrc6.Setup( fClock, nRate );. H9 o: i( {3 q& c7 n
        vrc7.Setup( fClock, nRate );# k5 _7 i" Y; O6 _% V/ t
        mmc5.Setup( fClock, nRate );# J2 x5 Q1 v/ @5 U* t0 S, T+ J* f7 i* \4 |
        fds.Setup ( fClock, nRate );
8 `" Y! G  u/ W) m: E5 b! p        n106.Setup( fClock, nRate );
3 O) F7 k! x6 ?" c2 b        fme7.Setup( fClock, nRate );2 J- U+ u) j) R+ w
}4 M. Q( z1 U' c# Q

/ M# g, e8 N7 ovoid        APU::Reset()2 [& l, u5 E- V# q; a) [
{( F+ l. G5 X0 z) V# `
        ZEROMEMORY( &queue, sizeof(queue) );
* s0 M3 o( x! ?. D7 C) Q! ?" G        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& g& \9 B& _9 y+ v: l, |  x3 G. F
9 n% l2 g: P) Q, k8 ~' _        elapsed_time = 0;
+ e: f0 z, J1 O. e, R% Q6 {1 p, x, p1 {2 _* _$ H5 ~
        FLOAT        fClock = nes->nescfg->CpuClock;
6 J  \* d5 b1 J4 I! ~        INT        nRate = (INT)Config.sound.nRate;
# h8 Q' K- F; l        internal.Reset( fClock, nRate );  s. Z. L" u0 C4 b& L& a
        vrc6.Reset( fClock, nRate );
# f- N+ t9 t% Z" }: e4 `0 {        vrc7.Reset( fClock, nRate );
1 G/ [# m/ B4 i/ B6 @. _        mmc5.Reset( fClock, nRate );
) {- V  S1 P1 C$ ~8 n        fds.Reset ( fClock, nRate );+ Z, Q$ L. I$ X7 s. ~
        n106.Reset( fClock, nRate );  H# C, A' O) y& X, O- ~! q
        fme7.Reset( fClock, nRate );! F/ x0 y. S4 |' Q% o
( s  I- M1 b% s* w4 E8 n
        SoundSetup();# q: R) T) N% ]  l) F: ~
}
! t( S0 I  k1 z, m" C0 D7 `
$ i) G: T/ B) h. Qvoid        APU::SelectExSound( BYTE data ). o$ `, J* g3 k/ @' s
{
- |- z  s+ a3 j6 y0 ]! y4 n* d" F! P        exsound_select = data;
: V1 t! Q" G9 J  |. x! [  o* l}( U9 Q5 V8 [' U
' s' L5 r( O" i+ \
BYTE        APU::Read( WORD addr )
7 s+ b: P- s# X" p{
7 h3 g/ a9 v; ]7 j+ M+ Z& k% |6 s* W; y        return        internal.SyncRead( addr );
0 E, l& j6 z' M' A: r7 P5 S" {}
# Q  l8 K, ?; h& b7 h+ K/ x% t5 _4 O9 {/ r& }# S2 P! Q
void        APU::Write( WORD addr, BYTE data )
# Z! U; f3 p6 _% K& b5 H, r% Q. }{1 R4 Y8 h! k6 n+ Z( X( ]1 T
        // $4018偼VirtuaNES屌桳億乕僩
9 z4 }  g/ k4 o. w8 B: l) Q1 I        if( addr >= 0x4000 && addr <= 0x401F ) {
8 ]8 B5 E1 O8 ]" P+ [, y/ o                internal.SyncWrite( addr, data );+ @5 v1 \. T7 v
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 \+ p, y% j5 s        }
. C! ~. G% v( X$ m) L$ X}
( ]. D; j' }( _% P* E5 |4 a) i# X5 F% p* U7 z8 [# n( v1 \. F
BYTE        APU::ExRead( WORD addr )* t8 z* m8 N$ y. H/ Y7 T- l1 L
{% |0 z+ s9 i+ W: C6 L0 N
BYTE        data = 0;
9 L$ @  A/ h& H7 ~, y$ X7 |8 ?
4 f% q4 U$ J7 l( K! o, T; _: d        if( exsound_select & 0x10 ) {
7 u. m9 J3 w% h' T8 r. [5 H                if( addr == 0x4800 ) {
( I6 ^5 b/ G2 X$ \                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 e/ v/ }4 z6 Z1 y                }
% F) \% H' V! s' _% l; g/ _        }( s7 u  _) E% S) G% Y0 U. w
        if( exsound_select & 0x04 ) {
1 X( Y6 q( |% t. }  N. p; ^7 G. \                if( addr >= 0x4040 && addr < 0x4100 ) {; I( q1 X  o/ \4 L# R) }
                        data = fds.SyncRead( addr );
* e# C+ J, o9 l; }" w; Y5 U                }0 ~  r' i% Y% D8 x) G' h7 M! m
        }
' b; b8 P' ~- q        if( exsound_select & 0x08 ) {
6 y5 {7 q1 H. g- Q1 j                if( addr >= 0x5000 && addr <= 0x5015 ) {' Y9 ?6 x: A( C- L7 X: k1 N
                        data = mmc5.SyncRead( addr );8 o; A/ W. U9 I4 |4 N5 C
                }
; r8 G, V/ G) C: D2 Y2 e: ^        }  Q4 G2 |2 h9 \$ i8 D  Q# G6 I4 }

$ J4 l7 K" }# H+ d% b% o% U        return        data;
; M# u, L- g2 D- O4 w* b}
4 R2 T/ ~" L7 r- \' b+ t9 m) S% t4 }" _% }% S
void        APU::ExWrite( WORD addr, BYTE data )% S' X$ E+ b7 K4 O3 y  G* W+ x
{
6 @( t) n3 p2 X( p        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( k, x8 J, C& ?8 [
0 |; b& m8 r- O) \5 I4 r  o; ^9 U, Q        if( exsound_select & 0x04 ) {. |4 ~' l: Y4 b4 A, l
                if( addr >= 0x4040 && addr < 0x4100 ) {3 e: q. }4 C% E& H. E$ q/ ?
                        fds.SyncWrite( addr, data );8 w- i& g7 [- p( b2 m
                }1 E( H# f7 z, t6 R
        }
& B3 |( d, }" `3 f/ k1 @3 x0 k2 v
" v" \% G1 T6 @        if( exsound_select & 0x08 ) {: W. R8 r+ O  Q# d
                if( addr >= 0x5000 && addr <= 0x5015 ) {
5 F1 U3 w& }# \/ [! B                        mmc5.SyncWrite( addr, data );
, _9 C: `! g4 W1 K0 X! N2 U                }
9 b8 n3 U4 {* d$ A7 E        }- }7 E& y2 w! m/ [' i$ T( U7 T4 a
}, h7 @! R5 X; z8 @  o
7 W: `6 c3 E- K: N7 q2 c
void        APU::Sync()3 R+ J3 J" K4 }
{
6 L/ D  d0 @! }1 V' K  \/ U6 i}
2 i+ N6 j8 @, f  Y
  j! K% L4 `$ h1 Z, L3 \! rvoid        APU::SyncDPCM( INT cycles )  K8 d1 t: W- M6 o: ^% T) s: k+ L
{
% a4 S! e3 b; |( G: S  v        internal.Sync( cycles );
0 h4 g2 u+ b9 E6 X
5 U7 G, K" o5 m8 _( K7 X        if( exsound_select & 0x04 ) {
: Z% q5 {+ v$ n& {6 A9 }                fds.Sync( cycles );) J3 i' A/ U% H: C" t- ^+ C
        }$ w9 R8 Z9 Q, U% q) z
        if( exsound_select & 0x08 ) {
* y( F4 F/ Q; b) Z+ Q- c/ V* r                mmc5.Sync( cycles );
' _- G8 Y1 L9 Q0 C! t        }  `' q+ j, j' R1 l
}
+ T* D0 w3 N6 ?2 w
$ j) l. x& \( e! Z! z# N. I* O7 Y$ h& Zvoid        APU::WriteProcess( WORD addr, BYTE data )+ ^( S- T* [, a% i8 B& m% h+ }
{
& c8 v+ O# X+ u' |$ U2 ?        // $4018偼VirtuaNES屌桳億乕僩
/ U7 u; ~8 t4 G9 d( ^, q        if( addr >= 0x4000 && addr <= 0x401F ) {1 Q+ T8 Y* [  u6 t( n
                internal.Write( addr, data );2 S1 L  u/ K8 m3 r: @1 H
        }
. E- \# Y; v; p2 J# I% G$ [}
# k5 o( S3 R# o' m; ?; d4 p. Y/ E+ k9 E
void        APU::WriteExProcess( WORD addr, BYTE data )6 Z9 }- j5 Q+ d# K) X* b8 o1 r' k
{
' u: s  e5 Q" P% p1 D        if( exsound_select & 0x01 ) {: m% T3 j7 g* ~3 G
                vrc6.Write( addr, data );, L$ N4 {7 x9 {9 p8 V
        }
  `- f$ f/ `% p8 g* `& E: e6 k/ t        if( exsound_select & 0x02 ) {. ~) l" K% a5 R, x. q% K
                vrc7.Write( addr, data );9 N* f- P+ x2 M; a
        }
% B% J7 s% @& k9 [        if( exsound_select & 0x04 ) {
. s7 K; U5 _& g3 M" ^                fds.Write( addr, data );2 F, z/ c! S0 {: d
        }
0 A8 c; ~+ Y. @0 l" G  X        if( exsound_select & 0x08 ) {
3 c8 i" l5 W1 O7 i4 b                mmc5.Write( addr, data );7 V# z1 Z( T( ]# M3 j- M& c
        }: o0 u+ z( ?# d1 j
        if( exsound_select & 0x10 ) {
/ ^" L* w0 T7 |$ B( \5 j4 M                if( addr == 0x0000 ) {
- ~/ a" Y( t5 O  a0 L                        BYTE        dummy = n106.Read( addr );
$ G2 N! v9 p; {# H2 P9 h                } else {
5 H8 V5 e2 _/ Q! g$ O. m: g. x+ P                        n106.Write( addr, data );
8 ~" }; _0 E9 p9 p                }3 y& t5 r* S, ?- P$ X+ x
        }
0 |6 F$ d5 X8 Y! l0 j7 d        if( exsound_select & 0x20 ) {
6 o. ?6 f6 `$ H4 k5 k5 I# |                fme7.Write( addr, data );4 |3 x0 B8 O$ t) f6 v7 u
        }
3 D" J1 ?( k) w# p7 s}
  b. A0 t* K+ X8 ~" Y& Q* u# w4 o4 k& g" [- S
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
) f# y( a8 Z9 {" l3 m/ {' M{
7 ^; X, y/ G1 VINT        nBits = Config.sound.nBits;
* c+ j/ B' {* tDWORD        dwLength = dwSize / (nBits/8);4 }3 ~1 m2 E$ Q) z" l
INT        output;
0 m: t1 b! M5 W' {QUEUEDATA q;
9 e' V/ {) ^% |2 s# P5 aDWORD        writetime;/ e! r8 G, k  o  `
: w) v. ?  R6 B- s
LPSHORT        pSoundBuf = m_SoundBuffer;
/ D0 Q+ V: f# I5 j! Z6 TINT        nCcount = 0;( p& r# ]. ?9 ~, M& g" L* z( Q

( ~. Z; }: f" h2 l, [4 e8 F# {INT        nFilterType = Config.sound.nFilterType;
1 c9 X: e/ h8 N( y" H
4 k  @1 k2 `; k/ Q- m% L1 W6 y        if( !Config.sound.bEnable ) {0 C  d6 F# r3 p# R$ O- A7 ?" I( K
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; I* m4 }. H, I
                return;& @5 W, ]6 P: C" b4 D
        }# i" n% W: C+ \; M6 u  R4 w- C
0 [+ {3 C6 f& g" r: {& @  l
        // Volume setup
0 Q6 d( n9 s$ Z0 {, k        //  0:Master4 B$ }5 M. e7 l% W7 r
        //  1:Rectangle 1! ^$ M) j. W9 F* |8 z) Q! x% [; N
        //  2:Rectangle 25 U% P3 ^) O( T
        //  3:Triangle: U8 B8 m, z( @6 k
        //  4:Noise% q# B- n3 V. ~
        //  5:DPCM. ?% i) F$ x8 ?. f; i' M0 e
        //  6:VRC6
$ H; u- [; U9 _& a        //  7:VRC7% N* g  @' e# A/ K: }
        //  8:FDS
2 J) V2 Z6 I  [1 M6 i5 s, O        //  9:MMC5- T3 {: R( `% L
        // 10:N106% }3 p! K( I# Q
        // 11:FME7
/ ^. O' D# W" ^        INT        vol[24];) h2 p( j1 r, g+ \1 @
        BOOL*        bMute = m_bMute;8 f& o5 Z8 p7 R0 ^' ~6 i' \! y) v
        SHORT*        nVolume = Config.sound.nVolume;0 D9 M8 J, I8 d% M( h" o: z; q
- n! k; p. d, I$ h
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 t+ G5 d  r" g; x$ V+ I5 x) a0 V" Q/ J% ~- I
        // Internal
3 w- g) c: b2 G$ o: r        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
; i( H$ A% l- C( ~8 U9 {3 j        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
+ D5 O' W' b8 r) o        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;, ^! e5 l4 i1 r8 a% w- R. h
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;2 x# o1 x- j9 C$ v+ Q! f' Q: C
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;3 l4 Z* S+ F/ q

. S" N8 M) }" L6 N5 @        // VRC68 a; h# k. ?$ z8 U+ p3 m  S
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  g/ a- R, j2 K( \        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( C2 r4 E- F, b3 U0 g' N7 C
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ K$ Q# [* p9 D* \7 R: j
. w6 \( P- ?* g0 X& t
        // VRC7
" E4 G0 c# |8 o9 k6 P        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;; g1 q8 H5 G* w6 I* ^+ f+ M' ~
* q; l3 O1 @' ]5 ]- ^9 K* {  j
        // FDS
7 T4 B1 Z; R" ?9 o( z. k0 V  a        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;" B5 u' W$ J5 g) R' \. W: w. }

3 L& @. X- q) V0 x: w  j        // MMC5( V* b- H. \# w4 b4 m! G
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; P( `/ x5 T4 G  p        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 k+ c0 R! W. A; l
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 ~! l5 F. W3 }, B. B' t+ \
2 c% K9 P; \7 s2 g        // N1064 a% y6 ~! q& f; @
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" Q- e5 o+ h3 x! ?  i7 v! }6 s
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& N2 M" }+ E" l3 {
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: W' u6 n) n( c. m
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 C1 B. g! O$ E- w1 L6 p3 a2 j* [
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 \9 F4 i* _" n
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! z' h, \7 o- L4 ?2 T- R        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ N& V' l+ E# O+ v& R. i& w
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, l" D! f5 ^, K2 N) b9 M. U. J8 q0 T  E% D3 |5 t% X( ^6 P
        // FME7, G8 P5 C% z- [
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 ^  ]3 o2 Q' T! a& {5 I/ V
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% f3 L  Z# J9 B% P1 P2 @        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 `6 ^7 N, U* U2 c6 \7 R, t/ F- t& Q- ]: \/ Y5 r4 b; d2 r7 f7 r* V8 f
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;+ h% P0 V8 i% `! o9 x
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. z1 X: f2 w) x' J) ?- }' L
- G$ @4 \/ v+ [( `        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟: e3 Y! a+ b, V7 Y9 d& S
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {1 q6 `+ J4 R! M, Z. u4 S/ H" y# k
                QueueFlush();3 P) f+ B9 A- a7 o$ s& _
        }
  ^' o5 F( J( }: u( S4 ]) u9 ~. ]: D" o8 v
        while( dwLength-- ) {
  w2 a5 u$ k4 l8 p0 y                writetime = (DWORD)elapsed_time;
/ A% ?4 B6 [( o! `1 L3 c( _+ O) c1 N' s% V8 F; G+ w; W
                while( GetQueue( writetime, q ) ) {
3 B, x" H$ y. O                        WriteProcess( q.addr, q.data );
9 [6 G3 A: ]4 `+ e$ A                }
! S# r3 P0 f/ N0 J. A2 W" }9 D" m: o2 G+ g5 ^/ @6 N; Y- m/ A
                while( GetExQueue( writetime, q ) ) {% p0 {* l6 Y) J9 n$ V5 M/ ~% V
                        WriteExProcess( q.addr, q.data );
& ^& D3 k4 ], }  ~) m3 Z1 f                }# g& X) y$ \) A& I) @
' q5 g0 D& ^% `4 b* B& O/ @6 a) N3 Q
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
4 H3 V- R  x1 b# w& Q% W/ O                output = 0;
, @/ g: K: c9 Z5 I5 a$ u$ X                output += internal.Process( 0 )*vol[0];
; m% {$ a0 _1 W& N. e, E                output += internal.Process( 1 )*vol[1];, w2 e0 t% U' M; T  z4 y: M( C. y6 Y
                output += internal.Process( 2 )*vol[2];. w3 P  u$ Q; h' L$ h% `& e
                output += internal.Process( 3 )*vol[3];* Y* T# v, p  l
                output += internal.Process( 4 )*vol[4];8 E( Y0 s0 R" F# `

+ H5 A, q# f4 C& S' [1 y0 _; P! Z                if( exsound_select & 0x01 ) {
# M+ O6 K' z. A- _1 y2 v                        output += vrc6.Process( 0 )*vol[5];) A7 U0 v3 K, J- g) ~$ T3 Y. m# H5 g
                        output += vrc6.Process( 1 )*vol[6];
) `% R8 p1 d" d6 E4 T                        output += vrc6.Process( 2 )*vol[7];
  r( @( e! ?0 N8 z# h                }0 U0 Q* P& o' |* s2 k
                if( exsound_select & 0x02 ) {
' N4 i$ b# l4 _                        output += vrc7.Process( 0 )*vol[8];
8 S/ F+ k! Z! H                }0 N5 p4 q  L( L5 L
                if( exsound_select & 0x04 ) {* W9 W1 D- A) x5 k3 {8 l
                        output += fds.Process( 0 )*vol[9];$ f9 g$ L& n2 ^# O" ^2 d; i
                }
( ]1 n; u4 G4 \) Q' E5 p                if( exsound_select & 0x08 ) {' D. d8 k$ }0 M: S6 i7 z/ n; e
                        output += mmc5.Process( 0 )*vol[10];
1 ?( r* _9 U# N4 |, V  l6 {                        output += mmc5.Process( 1 )*vol[11];. v/ H2 t3 \/ F  u4 M5 U) n8 b" `+ R
                        output += mmc5.Process( 2 )*vol[12];9 p  q# M! A5 K& \( E5 R! I) g  ~
                }, E9 @  q$ N4 Z' L! z0 {
                if( exsound_select & 0x10 ) {" o3 H3 Z1 A7 e
                        output += n106.Process( 0 )*vol[13];
/ l' C. x$ E# s8 E  r; |7 v4 |                        output += n106.Process( 1 )*vol[14];
5 k& P4 J8 t1 q  p                        output += n106.Process( 2 )*vol[15];
; ~! A* H  w: Z: |: j9 [                        output += n106.Process( 3 )*vol[16];
. O1 z" P6 Z9 x5 d+ o7 n                        output += n106.Process( 4 )*vol[17];5 Q+ F( b& c2 t
                        output += n106.Process( 5 )*vol[18];& m* l9 J: r& n) @$ r- J
                        output += n106.Process( 6 )*vol[19];
0 V& ]* |: t+ A# x. p2 ~                        output += n106.Process( 7 )*vol[20];
1 }& R4 F, m/ U2 e& w                }
9 B; G! Y( {. ?* g1 u# K' b) `% E! D; F                if( exsound_select & 0x20 ) {
% {0 W2 k; g1 C, X                        fme7.Process( 3 );        // Envelope & Noise6 D: \$ n# b! @- N! x/ Q- B
                        output += fme7.Process( 0 )*vol[21];1 T3 u: X( X/ F
                        output += fme7.Process( 1 )*vol[22];' j) r, c' R  W1 k
                        output += fme7.Process( 2 )*vol[23];6 l; ~3 S, y- ?7 D
                }
* @* t0 z5 a6 _/ f
8 N; a0 D! ?8 T7 C* Q                output >>= 8;( N5 T' t/ ?% ]  {8 a% v6 `
0 [, u1 E- |/ g. d. _7 ]
                if( nFilterType == 1 ) {7 ~7 d0 U* N4 c# t0 c& q& C
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)" @1 l# E5 e% J9 }$ d
                        output = (lowpass_filter[0]+output)/2;
+ F1 g" k! H4 B4 u                        lowpass_filter[0] = output;# {; g# s- [' W+ o) E* T
                } else if( nFilterType == 2 ) {( A4 p. i$ s  G$ `
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
$ r- D3 e8 f, Q' Y2 @5 Q& E1 t                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
" B2 I0 y# V9 z                        lowpass_filter[1] = lowpass_filter[0];, x! P: ~) n; _. ?  z9 N
                        lowpass_filter[0] = output;
& i4 P  Z; j% `9 u' g2 O                } else if( nFilterType == 3 ) {
6 _( r/ P. h+ U                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)/ |* B* N' U5 J: E0 j
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* A, ?6 M4 Z7 K1 _' x- U
                        lowpass_filter[2] = lowpass_filter[1];& T/ I& U: {' q% }% N1 e
                        lowpass_filter[1] = lowpass_filter[0];
' o. C9 a0 W  z/ J2 _                        lowpass_filter[0] = output;
9 r" F  B% [- w8 O5 C                } else if( nFilterType == 4 ) {) E9 W; w, P+ R4 N+ N
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 t2 T$ \0 e$ r( V1 x
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
# [- [0 s1 m5 g5 b* q( u                        lowpass_filter[1] = lowpass_filter[0];- t( N8 n5 _+ T6 w3 J# H
                        lowpass_filter[0] = output;
2 t" k7 G% A$ G$ q" m                }
6 w# ?( t. B; g0 ?9 a$ q7 s* w0 _  c0 K" u  z1 K' _  i
#if        0% R1 i- m) Q; _5 R# X9 `
                // DC惉暘偺僇僢僩$ O/ U0 N7 j+ a& s
                {0 L/ c4 d  b0 O; p- F! Y! r5 f
                static double ave = 0.0, max=0.0, min=0.0;
9 }+ L% h1 f0 H                double delta;6 }/ u) o4 x. W" i4 I: a& Z
                delta = (max-min)/32768.0;( V2 W- F2 B# r" F$ T- H
                max -= delta;. b  O6 z2 J0 s! T6 l
                min += delta;9 W  ]' L( [# `# v4 a, E
                if( output > max ) max = output;
/ G' c& s$ i6 }$ P* U. a                if( output < min ) min = output;
1 x. [- e& `! d2 ^( C9 ]* Z                ave -= ave/1024.0;, O/ y. f9 f! l* o
                ave += (max+min)/2048.0;
, s4 l8 I$ h8 U+ }; V, {4 J/ g                output -= (INT)ave;
6 x1 f/ c- _3 F. i' ^6 n# ^) r& P                }7 L; a" r4 d% a3 ~! Q
#endif
- s( h1 W% U; [) D0 s; E#if        1
4 Z5 C' [9 q' G% |) m' G/ E                // DC惉暘偺僇僢僩(HPF TEST)) H% }7 A9 v. P) U
                {
# x* L! n0 s5 L4 y7 T, U. P//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);; l- I8 ^; J* [0 _
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) q5 B" O: i7 r0 E, l                double        cutoff = cutofftemp/(double)Config.sound.nRate;
1 I% ~) E/ A$ u8 Y6 M                static        double        tmp = 0.0;, |! \# }1 x1 m2 J
                double        in, out;
, S% G. {% W  y: U' I7 U( w$ S8 z0 _& l) X! K
                in = (double)output;
& [5 s& `2 P  @* ]- R9 P                out = (in - tmp);
- X, b* x2 g3 `                tmp = tmp + cutoff * out;
1 I2 x" g2 l, T; i" {2 G, m4 z2 x! D5 @
                output = (INT)out;! _* g2 x3 s* [) N, G7 S" n
                }
- {: w$ s) O# i#endif% o+ D; d1 v3 [, ?
#if        0
' p# S0 H* _& F1 S* ]  i                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
6 R" z; H4 \: C3 ?4 f: n. x                {5 `4 ^: g5 R3 W  G5 h
                INT        diff = abs(output-last_data);) U: f5 R  |: C+ l& x
                if( diff > 0x4000 ) {" n: T/ ?, s3 D3 g6 u0 d" c0 b5 e
                        output /= 4;/ I& {" @* Q+ S5 Z: o' p- ~, t$ O
                } else
) q0 G# m$ n# @: o                if( diff > 0x3000 ) {( U: A8 t- k% q3 ]& c- p
                        output /= 3;/ f. I6 v" w% r+ j% O
                } else  a0 _/ c; [8 J; G# O
                if( diff > 0x2000 ) {
, |* |0 g8 X5 @/ w5 H  }                        output /= 2;8 m1 d8 x  q, F# [7 s9 E
                }+ _* L9 e. d3 h0 g& c
                last_data = output;% J) p) H! _% T0 x' Q2 s3 i( B
                }
$ ^, B$ U, Y6 a#endif
: F  h% R8 B% m/ Q9 `5 X; M                // Limit
- W9 y+ y0 c( J3 t/ c& x1 v6 \                if( output > 0x7FFF ) {
3 J9 u- S/ Y- h/ L2 ~. q( `  b! r                        output = 0x7FFF;
1 }" n( f6 p  C  N7 L9 p' H& [                } else if( output < -0x8000 ) {# f0 Q/ [9 L% o# r
                        output = -0x8000;
) ]6 e# `1 i. _4 B6 W. W2 w                }+ x. e' M1 ^! i- e; ]. m
% b6 Z* n( r1 i& ?1 }- h0 C( f8 ?
                if( nBits != 8 ) {5 P/ a0 c6 B! b# X6 T* G' A
                        *(SHORT*)lpBuffer = (SHORT)output;+ ^* o, K: _7 R# P. S8 q( S
                        lpBuffer += sizeof(SHORT);- F( z+ v& G: S" n1 i
                } else {; i: [5 s, D$ o+ w
                        *lpBuffer++ = (output>>8)^0x80;
4 V2 B# Y, G$ [& q( M7 U3 s$ O( r                }
  q- N4 h8 g7 Q4 \" K) J$ t% A1 x: h$ A' D. v" e0 N
                if( nCcount < 0x0100 )
  H0 R8 D; G" H' Y                        pSoundBuf[nCcount++] = (SHORT)output;* v7 L8 S# {% t  {& g
% c8 P/ ?* d/ x; T
//                elapsedtime += cycle_rate;. _) N% I7 t+ p2 c' F
                elapsed_time += cycle_rate;
/ g* P$ }: h% }# a        }" v( M5 {& H, d9 }- \1 O: T, `

/ t1 D3 P5 E5 W' i#if        15 f  Z9 j4 e' l# K  ?: v) W' [
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {; @5 y8 C4 e- i- d; P. v( e/ x9 v
                elapsed_time = nes->cpu->GetTotalCycles();* v+ W: J5 B$ h1 S$ @
        }
/ C4 q, Y0 h! M( E- J        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {# ^5 a  A! u5 h
                elapsed_time = nes->cpu->GetTotalCycles();
; k, b7 O, I( v$ v% p$ K        }1 N* E1 t- ]6 `8 p  q
#else
" Q& k5 [5 R6 F' j2 @        elapsed_time = nes->cpu->GetTotalCycles();( S3 a* I3 Z, t, N; m' z: e7 e) N
#endif
/ L* u5 W. W* b/ j; u  h( c}
7 O4 x7 k! M5 Q. k" u% j) M/ e6 n! P% b9 l# S: ]& u
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
2 ?$ h3 L+ h' m0 k4 h+ lINT        APU::GetChannelFrequency( INT no )" O2 x& Q5 I$ I% O4 T; u
{
" @9 O4 C" R, Q& x5 J, O        if( !m_bMute[0] )
) r+ u4 X9 C6 n1 L, {0 ^                return        0;
. G/ f' y$ {; y7 M( j* l3 ]1 x! ]/ O, o
        // Internal
9 @. M! ^8 D( i' h) S4 p1 e        if( no < 5 ) {* w2 [7 m* _) W' W' R& a# o% T
                return        m_bMute[no+1]?internal.GetFreq( no ):0;7 }  Z* T5 x; Y  j; F3 M
        }- W  e2 ~( z+ k, k. H) @6 d+ e
        // VRC6" G5 q5 d. W* y: k- E2 e
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
6 R; N9 g7 ?+ I- g3 i% A, N                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
; Z0 F# i, q4 ?2 d: T  u) T        }
0 S3 l% L! |) j$ F# \6 C        // FDS
8 M" n% |1 {7 p, j0 \        if( (exsound_select & 0x04) && no == 0x300 ) {
1 R0 t) B. {. P                return        m_bMute[6]?fds.GetFreq( 0 ):0;
# A! L8 Q, Y- [; M/ q. D        }
/ i8 h% T/ C# T+ q        // MMC59 w! d2 }) D# l' S4 _
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
; C% a! {$ |1 x3 C1 j/ R                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 i1 e1 M6 J; w) b' B% N/ z
        }) Y8 M  ~$ T7 N* W3 g# T
        // N106
1 W8 j- f% W" U+ ?! J3 B+ N        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) L- T4 m6 X+ @) z
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
' {8 ]' Q' G9 q! C        }8 R# L( i) q* h0 j  t: }
        // FME7
7 W% x: I# Q' \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
' G- H8 d) t6 ?4 C' K9 L0 D/ M# m                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
. f% `+ U* `3 _% a% b        }( _* A' h& V+ e  b' O" b5 V* W
        // VRC7
) t4 [" K/ G& b: F% w7 Z        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {4 A* n6 A! I: A6 ~% f; J# i# {% r! F
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;' H8 r: N3 G9 j* Z7 n4 K4 |  z
        }: a# F6 a+ i! o
        return        0;
- o4 {5 G4 q. J& H/ h! A}; V% f  q0 b' }' R5 g+ j: E+ v

( w( z0 O+ H' ~# `// State Save/Load
, v# j% _3 A2 L) U( Zvoid        APU::SaveState( LPBYTE p )
  G; W, N- R6 n3 u8 p: @: `6 i* o  w{
3 P9 P( @, B# ~+ i+ ?4 b, y#ifdef        _DEBUG
' d, c/ C+ a" Q' B" a4 ]5 y! BLPBYTE        pold = p;% `* J/ K0 ?, s  O& ?, ~2 v
#endif; V  S5 d3 @* E: I

3 x1 ]+ F7 M  T1 t- c        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
9 }, X' I0 J& Q8 f9 a; k, i        QueueFlush();
# v; v2 x- K3 H# E% U' }
7 C# o+ u- f) ^$ T7 S3 B        internal.SaveState( p );
" }& C: S( p8 c9 @        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 B! ]: u! }; q, ^5 \, ^1 q8 x( Q3 G4 i! ^" N5 H  x3 K9 F  x
        // VRC6
6 Z# K% l  k. d0 L+ Y2 E        if( exsound_select & 0x01 ) {7 x: W* w7 _9 S! n' J3 ~# @) T
                vrc6.SaveState( p );$ @/ T1 C- y# M) I( G4 h6 L, v7 W  i
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, U/ z8 z+ r3 E" G) h6 @
        }+ e3 |- B( b" N  t( V3 n/ E
        // VRC7 (not support)
( l' g& i8 f; u0 |0 d: o        if( exsound_select & 0x02 ) {5 d5 ~4 j5 N. |. R. K9 t* ~
                vrc7.SaveState( p );
- @! n1 R$ ^. D                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" Q8 W; r8 t' i9 A$ p- f        }
- Z5 w" Q4 V0 d  M0 p3 |# @        // FDS
( R$ a$ k) Z- q+ |+ K  Z) z        if( exsound_select & 0x04 ) {
  H  }* d. A6 O  L4 P( A- b                fds.SaveState( p );
, v% [' y9 z3 X$ A& n( H* p- D                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding  `$ F0 n4 e: [! @8 [7 o2 J
        }. d8 [! u$ M# R: X  @5 `" y4 ]: \
        // MMC5& U+ Y9 b% x: l. `' B
        if( exsound_select & 0x08 ) {  e( v9 q& B2 @, v/ O( ]
                mmc5.SaveState( p );
& J& T# p! ~; s) W1 \4 _3 R1 h  E                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: V+ D( G1 f0 D        }
0 ~/ S$ X$ |2 {, q  W        // N106
/ `& P% N8 L' ?1 B        if( exsound_select & 0x10 ) {
" W: e8 O$ W: B6 Z5 v5 Q# ?                n106.SaveState( p );, ~- r  M& Q& S* O4 a6 E3 K" L
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 l8 R$ ?* _1 b& K5 H6 i
        }% a* b3 y. H: ]: X  @5 w
        // FME7
$ d0 Y( k* R& {" K4 V        if( exsound_select & 0x20 ) {/ X/ R- |( ]% ^4 R, o
                fme7.SaveState( p );
9 b! s! A* Z/ ~7 b4 C( q8 U4 V9 N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 k7 C  M5 U+ }6 \' I        }/ A. k/ |1 l1 {) f
! C: B# d* ~1 s; M& [: {  h
#ifdef        _DEBUG
: W" y2 d: r, d8 y: k" U9 g; ODEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );- y2 u  c7 R3 x6 ^9 _
#endif1 V5 M9 ?$ F1 g, }2 ]% M
}
' M: [5 \$ r6 K: i0 g
0 l2 F0 [( C+ G! l* X3 Lvoid        APU::LoadState( LPBYTE p )4 V4 q6 A  V* J8 P" l3 Z
{
7 g$ I3 `, N$ l" C        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% B) u9 U. k/ |7 i0 C        QueueClear();
0 [# v. O* e8 N$ {/ q4 n9 h; X7 X0 x& Q: [( X  ^9 `. s1 Z
        internal.LoadState( p );* U6 q( @+ M1 q) s% |5 j( o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* y# j2 e7 ]6 _1 E  n6 P$ ^& d1 ^4 x5 r
        // VRC6  v/ G( l9 Q7 E, Y  J* Y+ d" y
        if( exsound_select & 0x01 ) {# M4 G3 x4 H: V# n! U2 u5 u
                vrc6.LoadState( p );2 }! Z" q7 U. |, x: R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, J1 ]+ w5 R/ M' z
        }" a1 u, B, G+ l# r2 `
        // VRC7 (not support)
; N3 V" C# l6 q. ^, T  a        if( exsound_select & 0x02 ) {
' w# I8 z& u0 l. M3 Z# ?                vrc7.LoadState( p );
/ K4 L$ A- Q6 C7 h, ?0 l7 ~3 g6 f                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% w: D; q; u3 F/ T! q8 w
        }
0 e- _, ], T2 c9 {7 N% }        // FDS
$ F1 Y& D8 }2 b1 q6 p) b        if( exsound_select & 0x04 ) {
1 X+ o! R: q" E! x; R$ q% F                fds.LoadState( p );# A- f4 g& B2 E# P1 K2 d
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& \+ `8 j7 s* K! T; |3 f( P+ n: C3 R
        }
' a+ B& A& e, z: m( Z" D! w' p        // MMC5
$ w: V5 J/ |* l3 M) s4 @  m% V        if( exsound_select & 0x08 ) {
, E, b6 a1 m3 m" i                mmc5.LoadState( p );
$ @0 ]* Z) ~9 }, o9 I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 K. u0 p; v" m1 y3 i        }/ S+ g; p3 v9 Y8 r+ k$ Y0 l# }: i" O
        // N1060 I- X3 l: p  H0 [* ?1 X
        if( exsound_select & 0x10 ) {
1 _+ `  S4 ~; b' e                n106.LoadState( p );
- ]0 O0 y. y3 F. b' t                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 e/ z+ L2 N9 J3 G        }3 k: I2 I' W$ y$ y' J1 d5 \: q- z4 |
        // FME71 s4 |" a1 M0 `- d$ A, U( d
        if( exsound_select & 0x20 ) {
, [, B7 {$ c$ v4 j                fme7.LoadState( p );% t" Y8 Y1 J8 b  `& [
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 ~- |, M4 s, S. z
        }
% D) A. a* m, K9 O8 @}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
8 w# r# ?6 p" E% T; P$ P. d; ]$ W可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 j. p( V1 I+ {) a
感激不尽~~

+ ~1 z( ~" G) ~2 i2 z恩 我對模擬器不是很有研究,* C3 b3 T) H- \9 |- V% I
雖然要了解源碼內容,可能不是很困難,) I2 C" Z  Y' I9 e3 D
不過還是要花時間,個人目前蠻忙碌的。
6 m0 G- u7 H* j* _! r% i/ x  F8 p
給你一個朋友的MSN,你可以跟他討論看看,
$ w% V" t$ d- d) Q他本身是程式設計師,也對FC模擬器很有興趣。. n1 m* `3 S1 Y: f% j0 Z* E
  \4 n0 s$ o3 v
MSN我就PM到你的信箱了。
7 y3 ]2 b1 ]$ l
9 G. u& ~; Y8 N5 i3 f希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 & r1 e5 f  [2 o" Q
呵…… 谢过团长大人~~
) \% p1 O% ?* \7 T- V) s  m
. a5 M1 _8 X! F1 k* ^- Q9 ~3 m( g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 7 c' d$ n) s+ }0 g9 I* E
团长的朋友都是神,那团长就是神的boss。

5 O1 U: Y3 R# N5 Y3 g哈 不敢當,我只是個平凡人,
( r8 e* G4 e0 }# ]2 G要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" S. o! m: g& fZYH
# s0 g$ r4 s7 @7 _/ GQQ:4147343061 F7 n; Y) l0 O( p) l5 o
Mail:zyh-01@126.com
# U0 ?# K* J9 \* n* ?# [
2 r7 G& _9 v4 a, \他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
5 {: y' d  c7 N3 c  y: j再次对团长大人和悠悠哥的无私帮助表示感谢~~

% }% S9 S) I6 P+ P5 A不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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