EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" `0 F9 F3 {% u* |/ W6 S
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 x) O2 V5 o0 M) d7 W
这里有相应的模拟器源码,就当送给大侠了~~2 \3 d5 q9 s5 W3 W  v+ r+ ]: h
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 * `( ?% O: c; n. j% v
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 p& n' R% G7 f2 ]
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 ]( y* C) y" N+ W
这里有相应的模拟器源码,就当送给大侠 ...
! w6 W3 i/ C! |/ F" Q
聲音部分(Audoi Process Unit = APU):$ U4 u4 P8 B2 J; w: n
.\NES\APU.cpp' u# Y: m8 L5 e4 X5 y& E3 F
.\NES\APU.h2 U% u$ c4 p" E2 s8 O
# p5 o/ a# @/ K+ i& A( I+ s
  A' }6 S7 [' Y. T" z6 j, P+ L
影像處理部份(Picture Processing Unit = PPU):' J+ U9 v- N5 B/ P1 O) N
.\NES\PPU.cpp4 p7 o" d7 f  Z8 R& P& }6 T" t
.\NES\PPU.h2 H) i7 k, N8 o
6 M' P! D7 J+ A! i5 h2 Y& t
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" c  P: ?2 q( `, z3 c0 `, f8 h
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:% U: I2 }: B- }* B/ X
(由于很多专用术语和算法机理都不明白,所以看不大懂……)3 W$ G% H* y( O2 c1 l  h$ G
//////////////////////////////////////////////////////////////////////////) k9 B% P- u4 t5 `
//                                                                      //, R" \4 h: W. P$ S
//      NES APU core                                                    //$ o2 {" d, S6 S& k- b8 d9 ~
//                                                           Norix      //
4 s1 ?' y' K$ y, {5 C//                                               written     2002/06/27 //; [. N- Y+ T5 \
//                                               last modify ----/--/-- //
* U  M% g2 a0 Q# ?8 [  o% h4 K4 m//////////////////////////////////////////////////////////////////////////9 d& [0 u6 m) H& W, l3 J7 v
#include "DebugOut.h"
3 ?6 F* _7 B1 b: B) {( \; O, W, @#include "App.h"3 s1 I9 e( O; k0 ^) R
#include "Config.h"- r' x$ [9 U8 U- [- `; f( g

( K* j0 m! h8 Y#include "nes.h"
, H4 s1 a4 P$ W: l1 p#include "mmu.h"
0 j) V5 W3 U3 E# x#include "cpu.h"( U# O5 ]- Q- y7 z; Z
#include "ppu.h". R) |/ j( N. z) [, f  [& H
#include "rom.h"
% t+ U: p) @, v( Q+ D7 T5 @#include "apu.h"5 F* _: d/ E# h# A7 @

. g9 u$ n; a. i0 N// Volume adjust
5 J) B/ k4 C. G) N// Internal sounds' s8 j& s/ h* ]- ^# A0 ?
#define        RECTANGLE_VOL        (0x0F0)
( R8 ?6 s$ m+ Z2 q#define        TRIANGLE_VOL        (0x130)
# w  N, ]$ x  t; q% T#define        NOISE_VOL        (0x0C0)
6 t4 e5 Y( x4 H! G5 G' C#define        DPCM_VOL        (0x0F0)
1 X  C2 [, b/ k3 C3 N4 C// Extra sounds1 _( s* v1 T) ]6 W4 l- \& j
#define        VRC6_VOL        (0x0F0): V' r- b% I/ @8 v+ @1 O
#define        VRC7_VOL        (0x130)
( Y2 B/ A7 R9 m#define        FDS_VOL                (0x0F0)3 J7 Q2 ~$ q, ]. ~  y
#define        MMC5_VOL        (0x0F0)
& m0 Y: I5 [! p7 q% J5 D$ n+ l#define        N106_VOL        (0x088)! {1 X7 ^- {0 u1 U8 {) \
#define        FME7_VOL        (0x130)/ x) C7 D9 N! l! N
/ B3 v3 L- k/ H$ A& I, O: q$ I- p
APU::APU( NES* parent )8 J! A3 F! Q( F2 {' D; Z' Y
{4 S4 [/ |8 X9 C8 C
        exsound_select = 0;
: q8 u; }8 m" W- S& D) G% W# E+ o0 E9 w
        nes = parent;' z( K4 W  G0 \/ ]5 S, h' r! `
        internal.SetParent( parent );+ o2 ?% Y7 L+ u; ^$ m& p

5 W, k& @% s% h1 f5 z1 Z* b7 e- H        last_data = last_diff = 0;
% J: C) i" C9 z" Q1 B6 S1 G. }- f" y8 ]+ i
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
$ V) B0 r! X  e+ U. L$ S
7 [) j1 e& p$ {8 ~( |! Q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );$ G/ v, P4 |4 u3 c8 T) I( p
        ZEROMEMORY( &queue, sizeof(queue) );9 q3 s: ]- `2 F! L3 A" f( ~. h3 d& e
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* U: Y& q4 {8 z. K! o9 {

3 e  p2 q7 W  A6 p. V$ p        for( INT i = 0; i < 16; i++ ) {
+ {0 x1 o& ^! r4 ?: q9 h5 m0 l                m_bMute = TRUE;( K* l8 n# [0 s7 J  C4 g
        }' ~$ R7 Z# _6 q. R
}+ C8 v  U. L7 M) [

2 ^' `( w( M1 h3 xAPU::~APU()1 v( S4 ~4 B$ @7 u2 D$ S9 V8 O' j- X
{
  @) ?. Q0 I$ s  ]1 `}
# U  C- d" ?3 J4 x0 {
9 H, |! B% b- Y5 |5 E$ {& Zvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: M& |7 c- v, W: u5 x! x& P7 [1 {8 X{" r+ m+ w! h' H4 j5 H# z
        queue.data[queue.wrptr].time = writetime;
' R0 x9 T  w  J' ^* A+ \* j        queue.data[queue.wrptr].addr = addr;
% Y3 e  C* s7 e3 a' Y6 J        queue.data[queue.wrptr].data = data;: q0 q7 x- Z/ S! ~# y$ i
        queue.wrptr++;! a( w1 ^# T+ r! \  x5 |7 ^! t
        queue.wrptr&=QUEUE_LENGTH-1;, e6 S' [0 q5 j; ~( b6 S
        if( queue.wrptr == queue.rdptr ) {
4 U) X6 C9 w# L2 L% t% s                DEBUGOUT( "queue overflow.\n" );& S: j" e8 f1 x
        }. l9 v. \+ s% l
}
  _+ o3 q. J6 U( }* _  h* f) _
/ L  I3 ~+ |+ X/ p0 {2 Q  kBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ A) O# z4 V4 M
{7 n+ x3 p! T6 q
        if( queue.wrptr == queue.rdptr ) {
, J# q# T9 C* K" K+ T. ]* b# |                return        FALSE;
$ Z6 v6 N5 m" B  Y! _        }$ @9 u* C6 i+ a' X: d. i
        if( queue.data[queue.rdptr].time <= writetime ) {/ m3 B8 Y# J2 c' h9 I
                ret = queue.data[queue.rdptr];
5 h4 D* E* a) S9 y4 d                queue.rdptr++;
( t- e$ m) ^. v$ j7 E                queue.rdptr&=QUEUE_LENGTH-1;8 S) o" P! z: K, Z
                return        TRUE;
4 |* p4 S: a) h) [8 d        }9 j  u$ S/ m& B$ ~- x, m
        return        FALSE;
% d& [2 u$ h" h. T; V+ }0 ?}
  \4 @! f6 X1 `% L1 b
# W( ~. u/ t& evoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); X2 x8 l4 m/ ]( T) Z
{! r+ R. Q' }: u0 A7 q' @8 P
        exqueue.data[exqueue.wrptr].time = writetime;
1 W& o& O) w! ^1 c! A        exqueue.data[exqueue.wrptr].addr = addr;0 u; \+ y$ U  K- [$ W, B1 [
        exqueue.data[exqueue.wrptr].data = data;
& E& A; R7 s  e5 n* p: L        exqueue.wrptr++;5 h, M: O. O( N' u8 j9 [
        exqueue.wrptr&=QUEUE_LENGTH-1;
& Z( n4 h) p+ H3 M1 m4 Y        if( exqueue.wrptr == exqueue.rdptr ) {! ?; @* S; `' B3 d
                DEBUGOUT( "exqueue overflow.\n" );* T" K* D! {' L
        }
" r5 \6 s& l$ ?8 z+ o  O$ e0 b- {}
! T- Q6 }+ Q( e3 l1 f- U4 W9 }. @( g: q8 T7 b4 T" i2 [8 ~
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ). X. }1 v) q9 b+ @) U& y3 J' B
{
) g$ o/ n  K$ N0 N. o        if( exqueue.wrptr == exqueue.rdptr ) {! L- \5 _# ]3 a6 u3 Y+ F
                return        FALSE;; B2 f1 D  v6 X  E( F
        }4 i8 Z* @: O3 g
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! t; L0 q9 S4 v' U1 f. F- Y                ret = exqueue.data[exqueue.rdptr];$ a% v, ?/ j( @* n  C
                exqueue.rdptr++;4 z' _: ]& i) ]% T( d
                exqueue.rdptr&=QUEUE_LENGTH-1;4 z' Z. V9 C0 L2 W
                return        TRUE;
: p) h7 [7 V5 F$ r- a5 ]        }) A1 }" ~( F6 ~
        return        FALSE;$ C, s" n' X8 c, y0 u* q
}
: Q" w7 E* b5 }7 Y# g; g: _; k( ~& U6 z; ^
void        APU::QueueClear()
2 X0 }! c. H# M{6 s2 ]& O9 B; z$ _# h2 J# d6 i2 h
        ZEROMEMORY( &queue, sizeof(queue) );$ K# u! J& ?+ f9 {5 B$ q  P5 o4 A
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( X5 d  x' F  [+ c5 d}
5 x: B' m! i5 r8 \8 p6 M# ?
2 B% c7 f0 O5 q0 O# @2 gvoid        APU::QueueFlush()# h4 r1 C) S4 y) A- c0 `; h( i
{
4 J( X+ D& J; J; s- S$ q( c        while( queue.wrptr != queue.rdptr ) {) A8 Z5 b% j# q4 H$ ?8 p
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: U3 P! o% b. _. _                queue.rdptr++;4 `+ }! }$ u! W# l$ X+ Q
                queue.rdptr&=QUEUE_LENGTH-1;2 L' u8 ?9 ~# o1 y* i' x
        }
0 o( @' x$ k4 e3 j& b
2 A$ `/ b3 |1 \4 G7 ^/ ?' r  {        while( exqueue.wrptr != exqueue.rdptr ) {
/ ^  j& W( n# [# M6 v  ]  ~                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
# L4 S, q: d; X% n$ J' l                exqueue.rdptr++;
" U  q' {; d; j7 n" M                exqueue.rdptr&=QUEUE_LENGTH-1;
# Y4 V% a4 O% z2 d% }        }
. A+ R( T) S* A% Y$ c/ t}4 ^  c  G. O" y3 E: L6 P8 m" }
- S( |4 ]1 B# A' F" I  K" b1 Q
void        APU::SoundSetup()$ P  U* g. _) z% |5 }: q; r
{1 _% Z2 m$ M* n! U( v. [
        FLOAT        fClock = nes->nescfg->CpuClock;
; M0 |: @/ e7 S+ D        INT        nRate = (INT)Config.sound.nRate;, L' {% T3 U0 L. c1 ~/ `* n
        internal.Setup( fClock, nRate );3 i; @! @/ S3 r  g- _3 l8 C% [
        vrc6.Setup( fClock, nRate );  H1 m( g  o' Z  H2 e1 z. Q
        vrc7.Setup( fClock, nRate );
( o8 }2 Y5 ]. T8 W        mmc5.Setup( fClock, nRate );
8 H1 z$ J' E9 {, K9 S: R        fds.Setup ( fClock, nRate );
+ h. D6 D: _/ B; S7 w, l        n106.Setup( fClock, nRate );, x# i! W2 I% ?+ [% J
        fme7.Setup( fClock, nRate );
) N. ?- {$ C% D9 d2 C5 H. e}
5 s. P* O$ A5 y
% C8 p+ \1 b% B9 m: y( j8 b! yvoid        APU::Reset()# d% S( l* A# |+ J7 h( n" B( |
{
' X: t$ z" ]0 i8 o! K        ZEROMEMORY( &queue, sizeof(queue) );
; T3 T2 q0 l: [' h7 y6 Z* H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, `) W, F0 V' H  X  [
# }  y/ }5 W) V1 `- o        elapsed_time = 0;! q6 \- [- k# x( Q+ D# Y" h

- S& r: W5 V" R/ r$ c        FLOAT        fClock = nes->nescfg->CpuClock;
5 y) g7 f, X# @9 b/ D# B5 L4 Q! J        INT        nRate = (INT)Config.sound.nRate;
" y1 v: V7 F8 g1 A" a" H$ ~- O        internal.Reset( fClock, nRate );+ b6 F5 _7 @4 E& g
        vrc6.Reset( fClock, nRate );
2 I* m0 F! B8 G/ V2 D4 V: A        vrc7.Reset( fClock, nRate );% {' J  b' A$ N% S- q. p
        mmc5.Reset( fClock, nRate );) v2 @* z, M! `
        fds.Reset ( fClock, nRate );7 o$ z' f: e8 s' N3 U
        n106.Reset( fClock, nRate );0 L) z& w2 i7 R( `
        fme7.Reset( fClock, nRate );
# A: s5 u; p3 }8 s( p  w! r8 }1 O/ X9 o
        SoundSetup();- [# A" D! g1 i3 X  {- B/ H- x
}
* |' j: B: E# {  s3 w1 f: v& i
, v' K5 n) q; b( S9 _9 L! c1 Tvoid        APU::SelectExSound( BYTE data )
  g! j3 e0 b/ n$ f) {/ z/ y{
( [$ m) {' N) j. e        exsound_select = data;
$ u, C! f. O! ~3 L8 t3 t}
/ P7 r+ `$ v0 J4 [& P0 \7 d7 E$ u1 G. t$ \9 v' i
BYTE        APU::Read( WORD addr )! |* ~" e/ h0 p2 `
{
5 Z- {) m( s& U" g, h4 R* c4 E5 D        return        internal.SyncRead( addr );2 R  Z0 k2 x* |9 b
}
6 s( t  m7 m+ X/ |- P# X6 I2 t
3 F+ ?9 o% i1 K8 Wvoid        APU::Write( WORD addr, BYTE data )
- s8 A( f. v- K; W% b: m{
7 ]( k' ?0 g8 u, _1 n0 I        // $4018偼VirtuaNES屌桳億乕僩5 F7 l# {8 Y% p; [6 {
        if( addr >= 0x4000 && addr <= 0x401F ) {4 H" D+ m4 n# t- V. B$ Z, T2 f
                internal.SyncWrite( addr, data );
" C: @$ Q& P1 z0 Q1 e/ [                SetQueue( nes->cpu->GetTotalCycles(), addr, data );, ]$ |4 K- n# C% u
        }
5 J3 a3 j- t, }' V% x}
1 ~7 x5 W: W+ Y5 |. {* \
/ q  V  T! i$ S- o# s8 `BYTE        APU::ExRead( WORD addr )
$ v4 J' K8 C6 K9 J" R1 @6 |% r{
( |( J' ^# A" oBYTE        data = 0;$ `; c5 u7 a1 O& s5 ~9 A

7 d- R5 }8 L1 I0 {. X% ^2 F        if( exsound_select & 0x10 ) {
7 z" I5 ^8 U& |  c+ T                if( addr == 0x4800 ) {
) J& Q, m+ V" R. w                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! g' Q4 L8 n( T
                }
0 m  {! u0 e' C9 C9 U        }
1 p7 [* m" d$ g        if( exsound_select & 0x04 ) {
7 K7 R& C) y- B9 m                if( addr >= 0x4040 && addr < 0x4100 ) {
5 r) _' n5 C& X! i4 d8 u* C                        data = fds.SyncRead( addr );! e5 t+ D" X1 O" S/ q/ a/ G
                }
' c1 x9 t4 C2 _  Q# o        }
# K- `- o. p; l% w1 ~        if( exsound_select & 0x08 ) {
8 A9 e3 ~! H7 {9 K! K" J( q                if( addr >= 0x5000 && addr <= 0x5015 ) {
% t1 B' [% h7 B0 d1 Z                        data = mmc5.SyncRead( addr );$ Y7 h$ R5 a$ h8 V5 t) y* v: u
                }4 ?0 S4 f+ G/ _! P0 ?" W
        }: U9 S; ~  V: c* z0 |

  T) `  d- P% X- J" R- q0 F8 E" u        return        data;, ?4 _  o! |. x. Z5 N; M
}+ p. Y+ z( k- n' W" R( _
# @! v9 L! a8 [0 ]& E' O- K5 }6 p
void        APU::ExWrite( WORD addr, BYTE data )
) Q; L# p( v- G1 K7 v; B+ @, w{
- F. d, f( I, [. d9 v        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );$ v) y  E$ ]/ ^3 e; d( r

$ x" F2 k, h. F; {- C        if( exsound_select & 0x04 ) {
; s; |$ N0 _8 a3 t5 c, L: D9 C                if( addr >= 0x4040 && addr < 0x4100 ) {
  l) J4 W& d. C, G                        fds.SyncWrite( addr, data );  Z2 Q5 [1 C, c; M) w) z/ k. m
                }
+ w( F- Z' I9 L; ~& l8 B        }
  l) R' Z, `; u4 T' n1 I8 C! D2 P# d2 V( @& T6 d* g* b; j
        if( exsound_select & 0x08 ) {+ U$ \6 c* s) w2 K" b( R7 ^5 Y0 P
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ d  f4 }1 y9 {+ k6 I
                        mmc5.SyncWrite( addr, data );
) U1 D+ {5 S- O                }" Z. O5 x% p) W7 l# H, V
        }, `4 p. G6 q1 U9 T& R/ b
}
/ j- x) ]! y; S$ W* ^3 w5 }$ I
* `' u6 s) z: Bvoid        APU::Sync()2 Z% z7 \1 E$ A1 g4 ?
{7 x; H+ k0 @8 N
}
( l$ |: S7 G2 x4 d2 [# X2 G. r' `  W8 g8 E; w
void        APU::SyncDPCM( INT cycles )
  @0 ]! \9 N0 }* Q8 Q( c{) j7 L7 L" U/ O, ~6 k. l, W) Q
        internal.Sync( cycles );; h9 i5 e9 z2 i% G' R
1 g- Y- p. a( N/ ?& b
        if( exsound_select & 0x04 ) {
( [, M1 ~" I  R                fds.Sync( cycles );) {; m: y1 D( G) S; b& K$ @
        }
- i& M% J7 _" U2 R+ S$ c9 P, \2 |        if( exsound_select & 0x08 ) {
3 T( [5 `, G6 k9 }) t2 A                mmc5.Sync( cycles );$ R$ h( g9 Y( v" \; @# |
        }
5 e0 D) E* [( u3 {3 d}
" F# }+ `7 @6 \6 j( j" M1 J$ W0 [$ k6 t; p9 r
void        APU::WriteProcess( WORD addr, BYTE data )
( @1 E$ ?  A, v{
* k2 S4 r6 c" P1 X: q( X) t        // $4018偼VirtuaNES屌桳億乕僩
4 R7 h2 s/ {9 C- M' Z  r) G1 N5 N        if( addr >= 0x4000 && addr <= 0x401F ) {# A; G6 m  T" {  B7 V7 _- |5 l
                internal.Write( addr, data );
$ V4 ~1 X2 ?/ H$ l        }9 U9 [! ~4 W: Z2 l
}
6 f: n' L8 w  ]( ~, {1 @7 N$ {: I2 ?) u; \. w) P1 W
void        APU::WriteExProcess( WORD addr, BYTE data )7 x- s3 j/ x4 o
{
8 l; l, u. }  M5 [8 I4 B        if( exsound_select & 0x01 ) {
5 D, s$ e3 J6 G  r$ u                vrc6.Write( addr, data );
0 j$ Z) A) F$ S) l6 Z) L        }
3 ~' z5 S) N, Q& |/ X* w        if( exsound_select & 0x02 ) {' L/ p6 ~6 n9 A2 b* O0 X7 }
                vrc7.Write( addr, data );4 v) j0 v# p& m
        }& W- y1 O* [% X! t! U' k8 K; w
        if( exsound_select & 0x04 ) {, f' d- B1 K& ~# f5 M
                fds.Write( addr, data );7 b( l; N! W; `" T8 X4 [- F. ]) O2 e8 O6 J
        }; J# [3 w3 Q0 r
        if( exsound_select & 0x08 ) {# H6 E$ Y2 d0 X" O
                mmc5.Write( addr, data );
% I3 I  j( E. Z) E+ G        }  t5 m8 c- a! x5 ~
        if( exsound_select & 0x10 ) {8 V1 [4 c  O/ |, v
                if( addr == 0x0000 ) {8 {1 G4 u# V* j' f; h
                        BYTE        dummy = n106.Read( addr );" I. a' T( q/ C# n8 W8 l, P: ]$ M8 c
                } else {, _& D7 s# n' c6 Z3 V7 _9 |
                        n106.Write( addr, data );4 M$ |+ w) e( Y' e" Q! e# z0 \8 z
                }
: E4 J3 D8 G" L0 F/ R        }
) g9 R9 \  r0 Q/ d/ n  |0 W        if( exsound_select & 0x20 ) {
& E( b2 x3 ]) m5 E! B; D                fme7.Write( addr, data );7 u3 f4 g0 \1 |) ^/ @' a( K1 q8 |
        }
3 C; ~1 A" C; U8 s}
; B8 [( G  n. h1 `$ M
* U7 B. S' \8 {& F* Y' uvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )8 D+ r5 u( W: Y
{
# Y9 z1 y6 I+ U2 N. ?  HINT        nBits = Config.sound.nBits;, d' v% d+ ?# x8 J" B: w
DWORD        dwLength = dwSize / (nBits/8);
! A9 K, v  C: A: `4 xINT        output;2 \( e: |/ j# z- s, n: J( o6 d1 d$ c
QUEUEDATA q;
! Z: h, @- }. v0 KDWORD        writetime;7 Z) k& w1 G& n, j! s: J

! U6 @* b) Y0 J1 m4 m5 hLPSHORT        pSoundBuf = m_SoundBuffer;3 a2 v) ~) p5 k7 H
INT        nCcount = 0;5 {4 n4 V! C0 J$ q& b
1 O9 E* ]8 j, d
INT        nFilterType = Config.sound.nFilterType;
& `2 a0 P& A9 ]* C) u8 ?# {. z  K( e$ H& k) H
        if( !Config.sound.bEnable ) {
; d) q# B& P" L+ A& {                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );% f5 v- l3 I/ Y0 E( Y3 [
                return;
. c+ S( f4 y. A2 X$ N3 c8 w        }
& K) P8 C& b# S7 S! q/ X0 w8 V7 _1 O+ G8 c
        // Volume setup
8 s% k8 l' v3 ]* {        //  0:Master
) v, w0 E4 ^2 m3 G( m) T; h+ x        //  1:Rectangle 1
1 I7 I6 ~, `6 F* q7 p" {& n5 B        //  2:Rectangle 2, ?2 @+ z, Q: n! r& \4 Y/ R5 ~8 }
        //  3:Triangle2 F  e; D# A5 j5 p
        //  4:Noise
9 Q7 o1 g5 T/ [- w8 }- ?        //  5:DPCM" U/ e* ^  d0 C. \+ Z3 \3 {
        //  6:VRC6
( M3 t& g( v+ P) H0 i& x        //  7:VRC7
7 `) R: L4 x4 b$ X5 B" d        //  8:FDS# F$ e, c# A9 G, M7 K. v
        //  9:MMC5) Y7 j/ M0 u! t1 P! D/ T+ a
        // 10:N106& k2 O# x; A! b& b8 e
        // 11:FME7  n3 I. A+ M7 l+ F
        INT        vol[24];
1 _  v4 o. _% z2 `. d! c        BOOL*        bMute = m_bMute;
& a* n5 j/ p/ [        SHORT*        nVolume = Config.sound.nVolume;7 r& l4 O! e0 [

, ~$ J1 R) E) @% B2 m+ P2 m3 H        INT        nMasterVolume = bMute[0]?nVolume[0]:0;* _" y2 q- y  V9 A5 {
* }( Q, o2 S% f4 Y/ d6 m
        // Internal
( w' I- P+ s4 a& A( M9 C        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 P1 b+ \$ \, w1 _* j
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;/ W; J2 A; z% Z" x4 H
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;& Z. m3 e" D' Z3 z( q
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;/ B/ H! O( |% P2 c
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
: U' f) P+ E" b5 |. q* t7 X3 y# ^) ]+ [5 b% h
        // VRC6
% I' r. _! N4 A; f4 f7 k0 }        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 D) Y. x$ r) M; k1 I        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 Q- ^' ?9 [0 I! w
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% ?1 e! U3 X. c! c7 ^3 ?7 l/ f8 l7 v5 m1 M! n- m
        // VRC7
6 ^0 P/ v7 R; c# \        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;6 E* U7 T/ _0 s  E8 B
# K" o# U( e. j+ d/ i2 \3 G
        // FDS
9 ~/ r; z! l+ A! H( r7 Z8 v        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
* D& @3 i4 P6 A: f" @, i. t& f& ?
        // MMC5
. H8 w# s6 I- f7 h0 p; n        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 S% k4 |7 G. c& G! h
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" A2 A, C  k  F' o        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 h8 G+ c3 A( L( M2 U7 u3 G
, J! c  M/ M8 ?6 B# Q; B! T! }9 J
        // N106
* F# K% }' N% D4 W# I& K$ Y* w! s        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 i3 n7 b* p1 B9 |8 c. C3 z
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! M/ S+ y3 L  `. v" u+ j  B
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- U0 l7 M  \( o        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) Z- d% N+ a) m# u8 |' K- l6 X        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' T2 a# U% r: Z! o9 v2 h        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; E* N# q9 Q; z' o        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* E; \" u7 g; i
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. U& R1 V4 X  K5 r9 P

6 y9 L' e9 L& t) q$ B        // FME7
0 l) @- \: l  [7 C# p! U* A* u        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 v" G# O: Y/ p( A, g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 _' d1 i" z% N0 g
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 |/ @, C  J. L% D
$ H  c3 o& {( ?" c//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;- F+ t* B: d, k6 o' z! T% a9 |
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;3 H, {& n5 ?7 e- n) e

% {( Z6 w% o8 N% V4 ^9 \1 P* n        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟( Q  e2 _  ]1 j. H, Z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 W# e1 t3 T" i                QueueFlush();" T9 r) o6 V  T
        }# `& n$ q/ c9 n2 B# T
8 w$ S7 Y0 @9 K. z4 u) I' I
        while( dwLength-- ) {
4 d7 a& W/ S/ e' H7 L! Z" D                writetime = (DWORD)elapsed_time;
* p) U7 J. Q/ d2 \
; G; W9 R% A0 L  N* |                while( GetQueue( writetime, q ) ) {
3 y8 }8 k: C1 `) Q. B. t                        WriteProcess( q.addr, q.data );1 m1 n3 j1 H2 q5 m4 k
                }
/ R. W" t  _7 v5 F6 _% s" L5 d% r9 Y2 {7 G* r
                while( GetExQueue( writetime, q ) ) {( X& F0 z5 e' w. A" X# k
                        WriteExProcess( q.addr, q.data );" G+ I9 V) `4 |( i0 w
                }
! t" X/ s4 O# H9 P/ s* i, J0 |% v; @' l1 i
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME78 A, i( t( ?: C+ i0 z& n
                output = 0;' @% D6 W* W+ t3 `- k  W
                output += internal.Process( 0 )*vol[0];
% I" v' W( H4 U6 F1 p  J                output += internal.Process( 1 )*vol[1];
# D$ l' [1 g  {& S0 A3 H' z                output += internal.Process( 2 )*vol[2];
/ P5 g' \5 a7 X) c: R                output += internal.Process( 3 )*vol[3];$ {7 Q9 K8 r5 B2 g
                output += internal.Process( 4 )*vol[4];
0 |4 P- z# N5 h; ^3 z- q
! q% @2 h) ^& h: k                if( exsound_select & 0x01 ) {0 Y8 G! Y4 Q1 R
                        output += vrc6.Process( 0 )*vol[5];" ~% R" Z6 H  s2 o( ?" F2 M
                        output += vrc6.Process( 1 )*vol[6];$ b/ C$ f) L  f- W$ a4 U
                        output += vrc6.Process( 2 )*vol[7];
( G5 i3 @( h) m7 t" ^                }. L) ~: H0 G+ t: W( W% T
                if( exsound_select & 0x02 ) {; {& _! g1 r& K; ]4 {
                        output += vrc7.Process( 0 )*vol[8];
2 |! J, N" \- a' D  @" `# {                }$ ^5 l) Z' }9 d) V
                if( exsound_select & 0x04 ) {$ p) c1 ]& N) ?- e
                        output += fds.Process( 0 )*vol[9];7 F; G& s! |( k& ~* ]2 o
                }! s' F4 i" u5 C' I2 {
                if( exsound_select & 0x08 ) {
* m% ^% `* x; [" {                        output += mmc5.Process( 0 )*vol[10];
2 q# T, }& T3 A$ F                        output += mmc5.Process( 1 )*vol[11];7 l: }: z; Z* ^( |5 w  j' U
                        output += mmc5.Process( 2 )*vol[12];" |1 ?) }8 Z1 m! O1 t0 G0 s2 C
                }
2 k7 o. E" h* m- a                if( exsound_select & 0x10 ) {# T! n$ U# {8 \9 z# o
                        output += n106.Process( 0 )*vol[13];* |2 b% \) m$ O  u5 |
                        output += n106.Process( 1 )*vol[14];2 h! [5 v: `4 I
                        output += n106.Process( 2 )*vol[15];
3 n) k, G9 }& B  R7 G9 R                        output += n106.Process( 3 )*vol[16];, O7 d  @2 f: \4 I6 i8 v+ G
                        output += n106.Process( 4 )*vol[17];
- |% E% W, t; o( K5 E& T                        output += n106.Process( 5 )*vol[18];
, O+ B2 R6 Q6 h6 x5 q                        output += n106.Process( 6 )*vol[19];
+ c3 g5 S# U, F6 y/ [                        output += n106.Process( 7 )*vol[20];: C! m3 F( `) R$ ?
                }' Q4 g# j' A1 H, E2 @- d
                if( exsound_select & 0x20 ) {
4 t* r: y  b; A3 V6 l/ n                        fme7.Process( 3 );        // Envelope & Noise
9 [4 Q3 e0 F& K                        output += fme7.Process( 0 )*vol[21];. j) x5 z9 ]( j9 O4 ~
                        output += fme7.Process( 1 )*vol[22];
, a& n5 L  H& ~. h2 J  e, Y/ d2 i                        output += fme7.Process( 2 )*vol[23];2 R: p6 W7 _6 L& I- J8 x- B
                }
+ |/ Z& z+ w2 o( l! m/ g% G1 L7 C- |$ v! ]$ q$ K* ?, P& l- h
                output >>= 8;, H& k) ~4 m" ~. S
1 P9 i( n$ `# x3 s! T
                if( nFilterType == 1 ) {  s$ V7 c4 {2 d8 C
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
5 W! q6 D! X. ]. `8 j; D0 o8 L, x                        output = (lowpass_filter[0]+output)/2;
% r) k$ h+ A" _) V                        lowpass_filter[0] = output;
  y4 v4 @0 _+ c. U1 B! j/ K% ?                } else if( nFilterType == 2 ) {
6 m) @* W1 w% v3 b+ y% _( J                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1), ]. E* p; c$ K8 Z' h
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ v  w. G# u8 L                        lowpass_filter[1] = lowpass_filter[0];5 u% R4 ?. G# |, H+ l  c' B
                        lowpass_filter[0] = output;+ p# g- ?$ @2 p' S1 F# Q% Z
                } else if( nFilterType == 3 ) {
9 e1 v; M; R( z                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
2 ]: ~! g5 \  x; ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 _9 J6 Z1 d, S) b7 g* G% X$ l                        lowpass_filter[2] = lowpass_filter[1];) }) l  w5 ~: ^; ^! m& B
                        lowpass_filter[1] = lowpass_filter[0];* D4 u( [' V; g7 e$ `- A6 o
                        lowpass_filter[0] = output;$ h# N, o4 M6 m( B' z
                } else if( nFilterType == 4 ) {
- Z* ]+ s/ b  b+ x+ T4 T                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! g  d0 V4 K6 h3 e7 D: \  q# I6 s                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;9 A+ j3 L/ O! [9 [
                        lowpass_filter[1] = lowpass_filter[0];
! W2 r: m9 x  I( w                        lowpass_filter[0] = output;! _. O0 ^. X: N6 b
                }
, K# s* t0 U* Y& e7 Z( f2 ~6 a: |2 g) D+ q
#if        0
8 m  A9 i) ]: C* \6 r. e                // DC惉暘偺僇僢僩  V; i  H& Y' Q% ?7 t( z0 r
                {  w* r6 d6 d  k1 X- r
                static double ave = 0.0, max=0.0, min=0.0;
- Q' t& C% B2 J( P4 G                double delta;
6 s' ]# v5 Q1 B2 D2 E( Q                delta = (max-min)/32768.0;
3 a4 j  ?3 C2 O  [+ h1 b                max -= delta;
( L' w& i& d" j8 p$ Y7 x                min += delta;% _# A( q' f" K% ~
                if( output > max ) max = output;$ }* G. q8 c( l) b, B
                if( output < min ) min = output;
6 y; ^4 R& F+ J3 r1 I8 k7 b                ave -= ave/1024.0;& L* R% C: U# o! J% k( e1 T
                ave += (max+min)/2048.0;
  n- w$ z6 m$ t                output -= (INT)ave;( @2 K9 y3 `1 O  V4 r7 X) x( h  c2 p: |
                }5 M# O" L* p0 K) z/ m, j- O* d
#endif/ c3 V" h2 Q* B- C0 W5 ~
#if        17 o9 M0 C; K; u5 t
                // DC惉暘偺僇僢僩(HPF TEST)
1 k7 I/ g7 U3 b3 N$ O. f                {
$ ]# U: S. n  z/ f//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);% m" m$ A% f7 u8 Q- d7 t* f
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
: J; f  o4 v; E- W3 F                double        cutoff = cutofftemp/(double)Config.sound.nRate;
+ R3 g1 r- w7 D- D9 [+ N% b1 h/ k                static        double        tmp = 0.0;6 f, W/ W- u% a* ]  p, ]
                double        in, out;
2 O% [* U: R* f$ n( H% h; s( e2 d1 v1 K
                in = (double)output;$ A2 X' d8 h( C. q! S/ L
                out = (in - tmp);
0 J, I+ B* [% l% W  F3 W; h  j2 \( E                tmp = tmp + cutoff * out;
% v( v4 P- [6 J& L$ ?- {( `; f! d3 I5 A" J( ^8 O/ y1 D
                output = (INT)out;
6 A: U5 L! n6 d                }
; X1 g, L$ E. g# x#endif
9 k, ~: C) t5 ?# \, h/ Y, w4 ]#if        05 T" n( }; N; B. f2 O: @* g
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)) l/ ~2 W6 o$ }: K: c
                {
+ g8 j( ?. _( M% t* m6 G" x! o5 H                INT        diff = abs(output-last_data);  p4 @9 L7 H3 h/ {: [4 h, r
                if( diff > 0x4000 ) {0 ?4 J; ]% o: ]5 x( Y0 X. M
                        output /= 4;
3 h; A. h1 y# A( L, J! I; |                } else
& G" D4 O- O- M$ f$ z$ I                if( diff > 0x3000 ) {/ D; P4 |) W+ Y2 ~# Y7 P% `) K
                        output /= 3;
/ A7 b+ O# ~* s: R1 @                } else
* `9 B6 m2 u- G* p                if( diff > 0x2000 ) {" y, p6 V7 X" N, U* ?) S
                        output /= 2;
7 t4 i- U8 E8 J: _4 a8 E! `                }
- z- b" Q& M3 E) ?$ q# v+ H                last_data = output;6 g+ M% @. G: Z, L" O
                }8 ~6 `$ s( V1 i( g
#endif, s" ]7 ^  j% `; V
                // Limit+ f9 F# W0 T" ~0 O2 e# |4 ~" J$ f
                if( output > 0x7FFF ) {' o) w8 b$ Y+ ~5 K
                        output = 0x7FFF;
# _& b/ ]8 \: ^$ h                } else if( output < -0x8000 ) {( I# l+ [6 r0 ]7 p# b! w  E
                        output = -0x8000;  n5 t# I6 a+ `* @4 g
                }
' w, l, [; d3 g/ c2 a* D3 a1 h) {& y- T  r% n: \- W) z
                if( nBits != 8 ) {3 R- k# W# H) }$ X0 M
                        *(SHORT*)lpBuffer = (SHORT)output;
; L- z3 p# t* i                        lpBuffer += sizeof(SHORT);0 W# B8 Y/ g- Y( ~  G
                } else {3 v3 n7 ^/ A7 z% P0 p/ u2 Z
                        *lpBuffer++ = (output>>8)^0x80;  p' q6 ^8 z; D* Q/ f# r# |
                }
& S. d. [( O7 w7 F, a' Z4 ^7 d2 }# e  w: t6 J# F: ?
                if( nCcount < 0x0100 )
- U* [! j. }0 g% @6 h1 K: {8 q6 H                        pSoundBuf[nCcount++] = (SHORT)output;
# \, V7 k& k& p# t5 s7 ^* S7 [/ b  S9 Z( I2 c1 ]' w& r. S
//                elapsedtime += cycle_rate;  L  a# x7 Q  A6 M4 `0 t: F4 T
                elapsed_time += cycle_rate;% I$ l& v$ h( u/ I0 m
        }, z; @* x. R' M) S

5 l7 X! Q" `, G+ N8 @$ y: Q  j#if        16 L; j3 D7 a8 d. D/ s- m
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
! }4 ^6 a: T4 K- i4 o                elapsed_time = nes->cpu->GetTotalCycles();
$ ^8 _0 D2 I) x( Z$ V& J! L+ u        }
' m; T. _. q! P2 F        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 O1 h( u9 D$ B+ g0 m* S- P                elapsed_time = nes->cpu->GetTotalCycles();  ?1 M  N8 M6 |  B
        }4 g" x6 B% l+ w
#else9 M0 b+ x7 w2 M: |. s# b
        elapsed_time = nes->cpu->GetTotalCycles();$ a/ R5 Z6 o& G7 i6 g- t+ G; S. r5 B
#endif5 h7 o3 ?3 P% @3 A4 z1 R
}* J* s  Z: k/ e4 i+ L- W
) X; [) @* U! l8 E& |: H+ Y
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)6 h! l0 ]+ Y% I
INT        APU::GetChannelFrequency( INT no )
( ~8 M$ s& ]" V4 ~2 o0 g' t{+ r3 c+ ]5 R$ Z; c
        if( !m_bMute[0] )+ G( K( H2 L& u" O6 f1 d( ?6 u: J
                return        0;
3 }. [9 y/ R9 n% g6 n4 L1 x
: ]$ F' L2 B& u1 C5 Z9 u+ q        // Internal) z. W  |1 `- e1 x4 w0 a9 {
        if( no < 5 ) {! I3 G, S0 z, M. m6 [
                return        m_bMute[no+1]?internal.GetFreq( no ):0;$ j8 f# n! Z5 f( r
        }
0 |/ u0 |# v- S1 A2 g- a8 ~8 W        // VRC6
4 k( S/ \4 t1 R/ }6 q        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ C" Y, p, T- M  z- ?  [
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
( T1 e! Z: Y  S4 Q: G% T        }
9 X* Y2 P! U4 t7 U* D0 U2 M        // FDS
. c/ E% q. S( Q" y        if( (exsound_select & 0x04) && no == 0x300 ) {
0 ]" x% _* v+ i. w; m# s4 [                return        m_bMute[6]?fds.GetFreq( 0 ):0;$ ?( v. ?1 ^% l' W8 q2 q7 f& ?# @9 H
        }0 F  U( n# N' s. N# i
        // MMC5
5 \# f) ]/ m. F# a" `9 |        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
& Q, F4 O/ S3 d& o" D5 [; S# j                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 ^9 o6 D# g* ~" S7 j
        }
4 z4 L2 @. H2 j% M7 f1 f  t- ?        // N106
; M) D( ?5 b2 g* b- a% O3 K  q' W        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 a8 e- w3 |7 ?' L1 b                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;. _$ I, T& m0 P4 G
        }
* X# ^/ h$ _+ G2 F        // FME7. {7 v4 h; j# T
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 E0 E& U) |* g                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 ~4 m& x+ f. @; U6 {' d  n% b- A        }
# A$ Q0 i, f7 G; o- U  |9 J        // VRC7
6 ^8 u) K2 o6 w# _( P" w# l        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
- O) ^6 ~2 O& N                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 a. E9 q% t* L' B
        }
' d  f& x" f2 `. \        return        0;  @5 [6 ~$ L' v0 O6 V
}0 h$ Q9 c7 ?" |* ~" J

2 o8 M4 B' N6 M4 H6 ~4 Y// State Save/Load
' r! O% S" i7 S7 r0 @void        APU::SaveState( LPBYTE p )
  s' x* Z+ A8 t5 j{) s  s, T3 i- N5 L$ T
#ifdef        _DEBUG+ u  a4 t3 @4 h5 k
LPBYTE        pold = p;
( h; d' z* l4 Z1 Q& l4 P) _% t) l#endif1 h# R9 L* N: l9 g

! O5 S+ e1 F/ S. B3 q8 q! E8 j        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 A1 @3 }" Y1 K0 L
        QueueFlush();8 M/ a& R8 P/ a
3 L! B( w9 q2 E1 F+ m6 M3 V( i
        internal.SaveState( p );
$ G9 Y! g9 ?1 A2 ]8 B3 u! H3 j        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 ?2 t- A9 e# R* L: H: V1 a' Q6 J% N
+ c/ j" |% x, }/ y* U        // VRC6
! ?# C; t( F. j: U, l        if( exsound_select & 0x01 ) {3 G( p3 k! b3 J) E2 ]8 q
                vrc6.SaveState( p );, \" _' O) ]% G8 I" |) r  f
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) N$ n# {; _  w; B& O
        }# q- U8 K2 D9 S" H, A- C+ D1 k' f
        // VRC7 (not support)3 }6 e- c. Y2 I+ l* |/ F% {
        if( exsound_select & 0x02 ) {
- H! p. y+ e. O9 E& o& D1 {                vrc7.SaveState( p );
) s( z- m# @  h                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 p" s4 U: a% C2 Z        }
' I, a2 n* a% ]$ ?        // FDS% J1 X) s8 v& u
        if( exsound_select & 0x04 ) {
: |; Q; e0 ]; G' z* c                fds.SaveState( p );  O. I. V: o  I& \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! W" }; l5 X3 |; D
        }
; m  z- V5 I9 D9 x1 {% D. n6 O        // MMC5
- U( i7 Y3 T. W9 o6 O0 _# U        if( exsound_select & 0x08 ) {
" s$ z  b2 \" _6 p! s                mmc5.SaveState( p );5 y" }+ _6 e& H
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 U& U9 _, @& B
        }: J8 U2 X+ R% i
        // N106
3 m5 d6 N0 w$ y; m' Z% `        if( exsound_select & 0x10 ) {) [9 h' [( D8 k! C+ F$ Z& f
                n106.SaveState( p );" L( f8 q2 ~( a  ^) L/ D( s
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' ?& i9 ^% a9 @) ~5 H2 z        }
: |% g9 }( i  @4 M/ A# X        // FME7
7 v5 L. v* ~4 g1 n# W5 {1 y/ f2 X4 b  F        if( exsound_select & 0x20 ) {; Q- i: Y. h# G/ ], p
                fme7.SaveState( p );: _' D/ R+ }! M. e, m
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 C/ ^; W$ ]: V  p( g        }% W7 u: c' S# y/ u& W
# N/ ?+ k! g9 F0 p1 G. J( V/ {3 D
#ifdef        _DEBUG/ I) t; e6 a+ S' [. N. [7 }2 W
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );5 {0 L" |7 t9 M  G6 |& Q. ~3 ]3 O6 @) P
#endif) x5 u% A2 V2 K0 \: O+ p7 r6 H
}
! M% S$ U/ c6 o" h  A9 `$ A1 u& g' x) }* C0 l2 M/ Q
void        APU::LoadState( LPBYTE p )
2 i0 D! ^, z: P0 F{
- c: {) ]2 t0 Z% p: _  G) _        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
( i4 q: w: j3 @' o        QueueClear();# }: C2 L& Z$ a7 c, C

2 q& H, D* D. m* |( a8 N8 _        internal.LoadState( p );
5 ~- j/ a, t& X+ t7 \- h# z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 y9 {& N. i$ s5 e' i; Z! a/ }' R  Y' C& A: L8 z
        // VRC6
  k4 e, W+ }/ h        if( exsound_select & 0x01 ) {: z6 X  d% \  L: r# N! Z4 Z9 ?( @
                vrc6.LoadState( p );0 h. `: T  h! R/ N* W
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: @# s' v7 L) I; u9 h        }
1 E2 ^! }$ X! g        // VRC7 (not support)4 P7 D/ J( s; w: a
        if( exsound_select & 0x02 ) {
& b  l1 [  j/ x$ t/ Q- i1 ^                vrc7.LoadState( p );
; H+ s9 a. L7 s                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; g) ]6 o) M, m& R: U
        }
/ y5 l# ~8 U1 F- ?/ H        // FDS- m' ~- j, i% ^% [: I
        if( exsound_select & 0x04 ) {
' u5 v# r2 s# p# A                fds.LoadState( p );/ B4 Y0 T2 l( O5 G3 \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
( e: A2 X" Q' W+ q4 t        }
7 }# N  H7 r# r6 R) C8 R        // MMC5! s3 f4 m. D' d" ?
        if( exsound_select & 0x08 ) {
6 z$ Y- J- r( t  [& `; ^3 p! B                mmc5.LoadState( p );
: h+ k  a. s' G3 r                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: [/ N3 R* L$ F* `/ U" i+ j0 R
        }
! c0 X. G6 f5 s# d        // N106, y# o* g& n! H" c' }' V
        if( exsound_select & 0x10 ) {: ~& P" Q  ?  X; d4 k4 x- k$ @
                n106.LoadState( p );
! e# \/ b1 x$ _4 `# B% b7 c% n                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  Z$ v6 z. S2 e; S        }  E. j& m8 S% H7 J& e- ?- A
        // FME7
- q; s% y0 H& {, i+ d        if( exsound_select & 0x20 ) {8 f2 R; n9 n/ o2 }- j4 U8 l$ T
                fme7.LoadState( p );3 Z* d8 F: x% |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 L6 `3 _  [  Z% _        }
' T" `' R1 ~: k8 a- P2 g9 M* `}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
5 @5 t4 D- L0 y/ @- a3 Q可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 @9 ^% a6 I5 x& Z; A
感激不尽~~

! A  ]/ k, Z- n) @恩 我對模擬器不是很有研究," a& F4 ?; k; J5 U2 S
雖然要了解源碼內容,可能不是很困難,1 c& z* T9 g) S  d1 i
不過還是要花時間,個人目前蠻忙碌的。
- A2 x# f' G6 S0 k# T) Y3 t9 J$ A. e. M3 \' E
給你一個朋友的MSN,你可以跟他討論看看,
6 t* G* [7 O: u9 h4 w他本身是程式設計師,也對FC模擬器很有興趣。
; J- p( I8 s. n: i+ k- L3 F( u3 A) f. P$ O  p4 Q4 W
MSN我就PM到你的信箱了。; b" U+ |: y2 k: g; }* G

2 A9 D% r  X0 E2 D5 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 发表
% W- T9 C1 x6 m& ?0 y呵…… 谢过团长大人~~

6 @& c7 @- Z$ y$ p! Z* S0 S( N: f, ]$ ]& l
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
' Z$ i- P* d2 q! M, }4 I8 ?, p2 ?; O团长的朋友都是神,那团长就是神的boss。
1 f) O, G2 A; A+ p
哈 不敢當,我只是個平凡人,
, c' u! x  p: L) G& p要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
6 a  o4 ?& J. Q7 J- U; h3 iZYH) g- I$ a/ o- W7 D, ^$ m* T
QQ:414734306, }4 x# @( f* z, n7 z9 Y7 F
Mail:zyh-01@126.com2 J: Q1 i4 Q) s/ x# _
6 @4 Z' U& j  _- f. `8 M  |
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
3 h5 o  d% W0 H/ h再次对团长大人和悠悠哥的无私帮助表示感谢~~

! O9 F* j0 X( O; M* L$ l不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-17 07:43 , Processed in 1.084961 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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