EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。8 x" b8 H7 A- ?* H, r
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
6 D$ [& o. t% z3 P; E1 a9 Y这里有相应的模拟器源码,就当送给大侠了~~
0 W' D- [' B! d& t/ _http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : g2 u8 g# B8 v2 C/ E
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ P! B# d6 Q! N* Q0 r2 `) C
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 @" D7 t+ d. p  {! I, _; u, e
这里有相应的模拟器源码,就当送给大侠 ...

! K1 X& g/ K0 N  M聲音部分(Audoi Process Unit = APU):1 L/ o  O$ ]% f! ?) D! R( Q3 ?" l
.\NES\APU.cpp
3 m* _4 I# x1 }0 V.\NES\APU.h, E" q" a: Q) v6 J6 U- g- q6 ?

6 B9 f9 u; m9 j( B
7 U0 N# d: e- M, y4 t& d8 p  t+ F影像處理部份(Picture Processing Unit = PPU):
7 f" C, l) a. T  ?) y, L.\NES\PPU.cpp+ Y& d' I- m# [% r# K9 \
.\NES\PPU.h) O5 U3 L5 b7 t9 c/ C+ l

. x5 \. _: @5 o$ k& T% E* v如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:( Y  I0 E7 U! c( y& r+ E% H0 @7 B4 O
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
5 j6 j# N9 v) O0 K+ f//////////////////////////////////////////////////////////////////////////
8 l. S" |/ Q6 B" P, ?//                                                                      //
( @: `9 \4 e" e1 D, D& e0 O* @) n//      NES APU core                                                    //8 f3 O8 J+ \6 h, H- |3 U4 I
//                                                           Norix      //
0 G3 k5 t2 _. P) ?% E//                                               written     2002/06/27 //' v9 q% Q8 j. b2 L; g, K0 O/ f5 l
//                                               last modify ----/--/-- //
1 Z+ r) o- q1 h! r* u/ E" j/ q//////////////////////////////////////////////////////////////////////////
0 i$ w% Q" a, Y4 K8 A2 C( K#include "DebugOut.h"3 v( w8 u4 {9 B
#include "App.h"
* S" j& c0 |* c4 c8 n# q6 K& }6 ]#include "Config.h"
: S# X2 X) a+ \% @4 T
7 P2 w' _1 j( d; B5 M  w- Z5 d0 b#include "nes.h"
7 w9 `5 h* f. E% e+ g" e#include "mmu.h"
5 e; q; r4 T$ y% [; F5 z$ P* K#include "cpu.h"6 _3 z) ^" f0 X& {
#include "ppu.h"
. A$ f9 d9 ]& x& `" G; U#include "rom.h"
& v" W+ H: k- C) U" Q#include "apu.h"
: r5 v# ?0 t: S0 S" |) g7 A) k) w  B
// Volume adjust8 X1 D7 [. R  F9 N
// Internal sounds. l7 {+ g0 L" W
#define        RECTANGLE_VOL        (0x0F0)
% y7 ?3 ?# D& u8 q' [) C#define        TRIANGLE_VOL        (0x130)
% D* _8 J  H% f. P$ E#define        NOISE_VOL        (0x0C0)
0 U$ [7 _: R' k#define        DPCM_VOL        (0x0F0)
; W# @) M: \" O9 `) N// Extra sounds& G, d' ^" r- T  ^9 I$ w8 w
#define        VRC6_VOL        (0x0F0)
$ R. R' v, q' q$ g: t2 |9 X  `#define        VRC7_VOL        (0x130): S% |- E7 P- x2 j
#define        FDS_VOL                (0x0F0)
; \5 f" }" i5 T  J! U#define        MMC5_VOL        (0x0F0)
( @5 {  G7 U3 d0 h) j! a* v#define        N106_VOL        (0x088)
: ~" v. P9 z  X4 D#define        FME7_VOL        (0x130)/ @: A1 l3 R& r* q& @
( ~, Z4 Z6 m" e: ~) U8 j
APU::APU( NES* parent )3 l) f* {3 W8 C1 M
{
  e2 T5 m+ G. k( X        exsound_select = 0;- c) t3 u+ Q7 I/ k0 H/ x

- ?, P+ b3 @1 B1 b        nes = parent;( y  d$ W( x* ~$ j5 P# ~
        internal.SetParent( parent );! Y1 \8 f( C# A( W9 C) T

& v5 r/ {: ?0 S; e* l5 S        last_data = last_diff = 0;4 B- e4 x0 G  C- {2 O! O+ T
- }% I5 F. s# B
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
0 n1 j0 _! c1 A: m' `6 J0 D( i
6 \+ R* s9 p( u. p6 A& X3 k        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
4 _) z* U2 Q- `8 \) Q7 I8 Z        ZEROMEMORY( &queue, sizeof(queue) );- t) g# H) R( @, G, k; l
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( W) a1 ^' L! G2 m, l! _% q1 t( c: K4 S3 O% S
        for( INT i = 0; i < 16; i++ ) {
4 B$ J% }+ P( Q                m_bMute = TRUE;0 L' D  b* E5 ?
        }  K2 k7 O) B" ^: i) P# }5 y$ c6 j
}9 N/ R! X1 o8 O+ @' B

# M+ ~1 A$ T. v& g, _3 R5 s' l6 ^APU::~APU()
2 E! d) @  G; U{4 ]6 E4 F/ @, h+ z+ v3 L
}& T, `. l2 ?8 ?" J' i
; Z2 \  U* p* z  C  T0 a5 K9 O8 X
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
6 T- d: R( X: `: o0 C{
9 Q# Y, e) T; }( C3 c# J& f        queue.data[queue.wrptr].time = writetime;! r4 v' G5 ]& X- v* g! p+ X: X
        queue.data[queue.wrptr].addr = addr;+ P% v$ a5 W' I) s
        queue.data[queue.wrptr].data = data;" y0 n7 c6 o, n. i' y& y$ f( m: P- q
        queue.wrptr++;
4 ~7 A' D/ d" |) w        queue.wrptr&=QUEUE_LENGTH-1;
/ F7 d  a4 ?. ?4 a; W8 p9 _8 H        if( queue.wrptr == queue.rdptr ) {
; ]: c! d. s6 e9 J                DEBUGOUT( "queue overflow.\n" );
  S7 m3 _9 P, }" }- Z$ z% `  _' Z        }4 v/ G4 d1 w0 c+ J( E# ~% I
}
/ [- s$ ]& B, D3 E7 R/ F
. B& M/ }' {7 t! j6 d% \/ v2 jBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 d$ ]* W  u. v3 h
{
8 i5 o5 N2 K2 z2 B& y. J        if( queue.wrptr == queue.rdptr ) {  H+ I* n9 r% G* }
                return        FALSE;
# u/ i0 b' ~+ R0 ?% d; Z        }
$ }7 v7 e9 }8 b1 w        if( queue.data[queue.rdptr].time <= writetime ) {
/ i+ N) {3 c: m# F                ret = queue.data[queue.rdptr];% ?$ O' H- Y: U, \( F: @. m* I
                queue.rdptr++;5 ^4 l, o& B. J
                queue.rdptr&=QUEUE_LENGTH-1;! u, J& }* o% ^* h6 Y
                return        TRUE;
9 e3 t# W# B% R, _( X1 C! O        }
! R% b! ]* y& s$ J        return        FALSE;( T) [& T! f* Q
}, J7 u; f* O7 v- P1 H+ n% k
  p/ x& S- B; l7 L+ P5 [- O0 Y& Q
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 B$ H7 X) O" ^$ N$ v# X{
- h5 X$ I2 C: u+ @$ w( W        exqueue.data[exqueue.wrptr].time = writetime;
  m$ x1 _1 d$ g        exqueue.data[exqueue.wrptr].addr = addr;) n6 _1 h- O1 l# ]
        exqueue.data[exqueue.wrptr].data = data;0 I0 P* v1 J3 \) w, p
        exqueue.wrptr++;
1 n1 J7 n* c0 i. O; H  X        exqueue.wrptr&=QUEUE_LENGTH-1;
5 ]; g; z" U0 v; S  ~$ t4 x        if( exqueue.wrptr == exqueue.rdptr ) {
; Z( g9 G8 I$ R% x                DEBUGOUT( "exqueue overflow.\n" );% u4 g8 A; x2 x' C0 ?* ]
        }9 |* e/ A9 x  J5 y( b) V
}* U, ]9 @: W; h0 U, a
5 s1 H4 K3 \& G2 z) P# R/ O. I
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ): M- l0 `/ \$ d0 q0 x" z. b, c
{
# B( F1 L/ a& s& I; @  C8 F0 E        if( exqueue.wrptr == exqueue.rdptr ) {
( C, M- r8 U5 V  j  Y                return        FALSE;0 y$ O% n9 \9 N$ u
        }
5 D9 g6 n) {! H* O        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& D( x+ b5 ^& X4 F0 p9 S, q+ T
                ret = exqueue.data[exqueue.rdptr];
3 F) T6 s, ~5 C) q0 n                exqueue.rdptr++;3 }* [: Y1 L$ i- u* E  l: w
                exqueue.rdptr&=QUEUE_LENGTH-1;" O3 Y0 k! R2 c
                return        TRUE;
. e2 W+ a' y- G        }7 D7 I8 X; b- M2 w. g
        return        FALSE;
- T3 B4 j4 S. }0 D- G7 U* |! S  J, O5 [}
  l% f6 r' T; o: g8 \& J7 @& Z4 X8 x4 Q9 |; R! [$ C4 L! ?
void        APU::QueueClear()
$ J0 G# w1 b5 @0 c3 g0 y7 R1 Z( P{
, P( [" _" k1 q        ZEROMEMORY( &queue, sizeof(queue) );
$ V4 w# Y6 a+ f        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 e0 v6 i. Q7 D9 w0 x9 ^& `1 r. h1 v5 I
}
; R. p6 M0 M8 F& j' r! o& q
8 f$ Y4 k9 j7 i6 K! s% z/ Yvoid        APU::QueueFlush()
( ~9 `* O  I: M6 [3 M6 V{# i7 a2 q3 g- V# I! L) {# M
        while( queue.wrptr != queue.rdptr ) {) M1 o7 ?5 R( l8 X" p3 k
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 }9 I0 |8 U8 N0 {" p+ W9 {- u7 b
                queue.rdptr++;
( U* {; }; R  ?5 j( {1 Y* g5 j                queue.rdptr&=QUEUE_LENGTH-1;
4 o* X2 k" X' C# P3 J        }! H3 R( X( U9 n0 b0 ^: c1 Y
0 f+ v5 S( l3 H% v/ \" P+ i
        while( exqueue.wrptr != exqueue.rdptr ) {
7 x; t& y' d+ @: N$ q                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
0 ^, m+ l  \$ Q( r' o+ ]                exqueue.rdptr++;/ T  H4 `7 ]: X8 Y
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 ]+ h4 \4 O3 h2 s& n4 T        }2 V1 @, e8 S% R2 [4 {
}; c( R7 [) R: U2 z4 ]/ e6 D9 T

( ]$ B, Z8 a6 c' X, ]/ k2 d! m9 ivoid        APU::SoundSetup()
. C, ~0 k9 A; l{# N; F/ Q7 M- A# z% G( v6 I% L9 k7 ]3 ?
        FLOAT        fClock = nes->nescfg->CpuClock;6 e$ F+ L6 R+ @* a" m* H
        INT        nRate = (INT)Config.sound.nRate;
2 K  o, b5 Q5 q8 V' [# L* e        internal.Setup( fClock, nRate );/ p/ i" V5 u$ i6 v' n+ t( S5 f  c
        vrc6.Setup( fClock, nRate );
& e# f) T) j4 `7 B        vrc7.Setup( fClock, nRate );
# r+ F8 k- _7 q# }) {8 }        mmc5.Setup( fClock, nRate );
8 [1 d4 ?6 R9 Z2 f6 }- z/ ?        fds.Setup ( fClock, nRate );, q2 [& W5 L4 \, a2 r' `" ?
        n106.Setup( fClock, nRate );9 s+ Z  t! f- F2 r6 D
        fme7.Setup( fClock, nRate );/ s+ ^  p; d! ^
}
, Q# X1 w* e/ f9 S6 ~! ?
8 u  T3 n4 Y0 P9 }% Yvoid        APU::Reset()9 @/ q$ v: y# d9 i! l! x% I
{; Y" |% B3 E7 O% X
        ZEROMEMORY( &queue, sizeof(queue) );
( }; O, [4 U' Q3 V; Y( B        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 @" N4 B  X' L
! ~* d4 W$ y! i5 q/ `7 H
        elapsed_time = 0;
& i- N4 Q+ Y" H$ Q
: y/ ]4 @, Q$ \. D9 m& Z        FLOAT        fClock = nes->nescfg->CpuClock;  e/ g6 l! L* B* A# m2 F: D: f
        INT        nRate = (INT)Config.sound.nRate;
, w: ?& }5 {& M' ~. ~8 D+ N, p        internal.Reset( fClock, nRate );
2 L* V2 }  w9 B% {2 G( P3 y$ D+ E        vrc6.Reset( fClock, nRate );
7 [  g' x1 s* G# m6 ~3 z" S0 Q        vrc7.Reset( fClock, nRate );
6 J( M1 n6 R) D3 o3 x& }        mmc5.Reset( fClock, nRate );
. q% ?# T9 e9 D: N7 W( n        fds.Reset ( fClock, nRate );
7 x+ S7 u) w2 U8 J0 I        n106.Reset( fClock, nRate );
+ N" z0 i% @0 p/ [* z. ~1 Q4 v7 H3 `        fme7.Reset( fClock, nRate );
- n$ K/ z2 B. n0 C6 H0 \, J
: s/ I7 [! A  b/ {. n        SoundSetup();* b( h$ [* n0 e5 t$ Y
}4 V; V: g, F9 j4 Z! b$ o" m) c- V

- c6 j1 r% U; \; o1 k1 Q+ cvoid        APU::SelectExSound( BYTE data )
; c. `& q- {( I0 U( G& s  R' b{0 v6 i2 x( }* O; k" j' Q
        exsound_select = data;
5 o& R4 G  |( y2 \: @}
2 g! @: |# k0 h( u" S: B: M/ j# r: w# Q# p
BYTE        APU::Read( WORD addr )) w4 F5 s7 u# d/ \# u4 ^- H
{! O) N8 I4 N* ]5 d1 V
        return        internal.SyncRead( addr );
+ x; c% d) P7 f7 L% v1 L# A; E( ~+ \}
/ `8 Z: A2 }- V( j3 ?7 H3 w' C! ~( R- `$ ?
void        APU::Write( WORD addr, BYTE data )/ s5 w, z8 L# g/ j
{- l, P' T1 r/ p
        // $4018偼VirtuaNES屌桳億乕僩6 W9 o% E0 R6 u! z- A
        if( addr >= 0x4000 && addr <= 0x401F ) {3 j; Y% E$ q/ G
                internal.SyncWrite( addr, data );6 C! \$ H+ X9 [
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
# X" ?6 H- L+ ?! y, H$ V5 c        }7 _7 z3 F5 a3 x; v
}4 q) C# B6 s! t' x! Z3 z. i) ^7 ~

3 y* v6 A. p% R7 V' R0 ~. N" WBYTE        APU::ExRead( WORD addr )
: p6 d: @$ B' b{
1 v" t; H- [2 a+ v9 u: HBYTE        data = 0;# l3 C7 o) l* V0 N& L% y

! S5 V- w) b4 C' t' \2 H0 ?        if( exsound_select & 0x10 ) {' o% f: o+ ]; _" j& d9 B
                if( addr == 0x4800 ) {
3 n% }( E; r  I                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
' R2 m9 c' L5 L! f                }
7 J1 I+ F1 v7 B# F5 e        }
1 k( y% Z+ N  I  K4 \6 n        if( exsound_select & 0x04 ) {# F3 a& u' i* j* S' w; n& L
                if( addr >= 0x4040 && addr < 0x4100 ) {- @+ k+ J8 R7 K, |  d1 h! q
                        data = fds.SyncRead( addr );0 @2 P+ B! C+ I# V) `& r! y- a$ T
                }
8 e: k- ~) V: H; o        }
' A' u, e- w" ~: j        if( exsound_select & 0x08 ) {
2 [6 k7 v4 A1 t3 p                if( addr >= 0x5000 && addr <= 0x5015 ) {
# M7 J6 ~9 x- y' W                        data = mmc5.SyncRead( addr );/ a: s; m8 k- _2 a- h
                }
  Y, L  G/ a$ c4 r0 m        }8 v! c% z: i2 d% {( T

" C  k; w9 l, s1 P: [9 g) r        return        data;) L# n( e+ F/ v% v. h" S: \1 A
}
% W8 G; o6 R8 ?5 f
% B! v' Y" J$ G7 o# a3 evoid        APU::ExWrite( WORD addr, BYTE data )
" s, d( ~0 }+ e! j{
- l7 p: |- D7 d% e( k        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 E! d" y- [- \5 U' J
) F$ R, u( e. t4 h        if( exsound_select & 0x04 ) {
; f. {/ a3 A6 [- P. z- D9 u; [                if( addr >= 0x4040 && addr < 0x4100 ) {& b9 D" c0 o# E' Z/ y: h
                        fds.SyncWrite( addr, data );; Z; H; c* n. t/ s3 O
                }
& L5 e. d9 L" [0 `: P9 G* }- v        }* N3 U4 j0 Y5 ]
! {7 Z6 I$ O2 F  N$ S2 D' E8 H
        if( exsound_select & 0x08 ) {
" @& N! \& K& _4 U2 Y% n# r9 w                if( addr >= 0x5000 && addr <= 0x5015 ) {- d0 B7 ?" j- y+ }1 w5 m+ n, k, K1 X7 c  }
                        mmc5.SyncWrite( addr, data );
6 @! V8 Q/ k  g* J" m                }( X: w! |; u0 v4 u7 q7 r5 @
        }
) S# p' \0 [# x3 U6 G! C}
4 d+ n& \3 ^7 V- k6 k
0 I  e! k5 q% }1 w0 Gvoid        APU::Sync()
1 ?( b) p: t( I2 J; L{
, e( }5 ]: D& i# U1 }+ h}6 H% U# \, j5 N

  D, ]( t0 g) G6 Mvoid        APU::SyncDPCM( INT cycles )
5 R2 v' @# w  b. G5 N{$ c: w% {/ d7 _2 ]% D
        internal.Sync( cycles );: o8 L2 @# a9 T8 q

% v* R0 h3 E- y: s        if( exsound_select & 0x04 ) {) p" V  n0 S% {$ b; D
                fds.Sync( cycles );
$ o1 o. @1 ^8 \' N. k& W9 G        }9 L# x4 u* }. {" }& @2 B
        if( exsound_select & 0x08 ) {8 I5 B" D( _! w  [' i% y- X3 p
                mmc5.Sync( cycles );
* h% F" U, Q5 p6 {+ u2 V& ^  ~/ d        }8 u& s( S0 u8 J1 m2 |
}
2 v$ j& X: f% d3 \) H8 f0 Y+ d/ j0 k3 Z, S9 F
void        APU::WriteProcess( WORD addr, BYTE data )
+ p6 C$ X8 h( u2 r4 d{8 h" g8 k' i' F+ n
        // $4018偼VirtuaNES屌桳億乕僩
5 J+ q$ \6 s, w9 U$ L        if( addr >= 0x4000 && addr <= 0x401F ) {- |9 B5 y3 O$ `- j3 h
                internal.Write( addr, data );3 ~4 Q$ S% Q% [
        }
+ \1 T( ]. C" y4 s}1 u! m0 q4 s) m0 F* ^0 G- Z

. g4 C- P! N0 d( T0 c2 V+ {void        APU::WriteExProcess( WORD addr, BYTE data )  f6 n# I/ O, F$ P/ e
{
1 C& u' c+ t4 H" F9 @        if( exsound_select & 0x01 ) {
5 |' |  U% x( x. Q) p' N% w                vrc6.Write( addr, data );$ _; Q. I0 J( a3 U9 B. D% a
        }8 K* b$ H) Y" ^2 P
        if( exsound_select & 0x02 ) {4 z2 Q" [* _3 j, S$ m
                vrc7.Write( addr, data );
+ W7 Z; p% g$ t" p1 r        }% }& V4 K- n/ C% F* ]
        if( exsound_select & 0x04 ) {9 |- Y8 P9 N$ t' @
                fds.Write( addr, data );
+ p  }9 D- \/ I' o5 c+ E3 [- _, ^# z        }# x2 Z' C4 N2 M' [. u7 m
        if( exsound_select & 0x08 ) {
0 g% k1 j2 U& z4 r: ]                mmc5.Write( addr, data );
! p0 t) H( T0 d        }
2 P1 E2 H* |' [( U2 U$ C* M9 W        if( exsound_select & 0x10 ) {
8 _  f/ ?# M4 ]                if( addr == 0x0000 ) {# S7 a, v/ N+ ^& V
                        BYTE        dummy = n106.Read( addr );7 k9 d2 f* o% |* R2 z# Q" ~8 y9 n
                } else {
, Q# {0 u6 m+ V' W! A% p+ j+ ?                        n106.Write( addr, data );4 Z7 x2 q1 d& u8 `, e
                }' E; h+ e  w/ c! \
        }
% `8 q1 ]4 f$ E3 L) t        if( exsound_select & 0x20 ) {& W' }6 ^9 G. d" c9 ~$ \
                fme7.Write( addr, data );: \% F& H9 o7 O4 j/ Y$ `& Z
        }
% P: F0 E5 w- i7 p7 k2 S7 x6 Z" N}+ G8 `. H* I# X; N9 A8 L  Y; N  N

& O% \9 |- [4 e" B- ?; Hvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
4 @$ m& ~9 l* q  [7 j{. L9 j8 s4 [  b! j. J) m4 O
INT        nBits = Config.sound.nBits;+ s7 ?8 b5 M6 U. y, I; {
DWORD        dwLength = dwSize / (nBits/8);4 q9 k& b1 K  m. `6 {3 f0 D# X: }
INT        output;
# `+ _- p. y# ~3 K( h# z. V7 T' DQUEUEDATA q;* h$ N' o- ?$ H+ v: y1 O0 F
DWORD        writetime;" o% w# s1 u# @; e; l4 |7 G; \2 s8 c
. }1 \8 y, Q$ }- B
LPSHORT        pSoundBuf = m_SoundBuffer;3 p$ w) D5 u5 O1 m; N+ w
INT        nCcount = 0;; l3 u! J, a: H; @3 c

+ u2 e* u+ o* U# VINT        nFilterType = Config.sound.nFilterType;, u  A6 {4 I0 E

$ X# V! m9 [+ U$ o9 q8 f        if( !Config.sound.bEnable ) {
7 m# v& n' i6 W# a: D% O                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 q& d7 ]( a% L, N                return;8 \1 w8 ~) x0 i2 |5 l/ B
        }( ]! r4 T2 X+ @- ~$ o5 Q& y

2 g8 ?6 w- h" l' X1 e1 h        // Volume setup6 D4 g* D4 u9 o# k* p
        //  0:Master( @; H8 D& b5 b$ V' f
        //  1:Rectangle 1! s, D+ H* E% I
        //  2:Rectangle 2
- l* d+ c$ M8 ?# N' L* F        //  3:Triangle) v5 E( U) K6 L* a
        //  4:Noise
7 d) v/ j: H4 v        //  5:DPCM4 y; O+ P; Y6 y5 ?! \
        //  6:VRC6
1 Z' y+ T  d* X        //  7:VRC7
% y  j; j) I; }* _! Y. K        //  8:FDS
* i' K2 G6 Z/ m% L. b" z1 @" `, J        //  9:MMC5' b; S" {% @( E6 Z, y) k
        // 10:N106
% P, o" H0 n( p        // 11:FME7
& u% w  P- i. Z% U) H* E$ n; T        INT        vol[24];1 n9 L' m# \; G2 Q; D! }
        BOOL*        bMute = m_bMute;6 S+ U1 A) l1 x  m  Q: Q* L; q( {
        SHORT*        nVolume = Config.sound.nVolume;0 Q* H5 X4 [! {$ ^% |* z

9 r" N) ^( Z' L0 {8 }. }6 f        INT        nMasterVolume = bMute[0]?nVolume[0]:0;: D9 }% X+ i$ F% \4 ]3 U4 e5 h5 j
" t* [' u8 C: _. N) L
        // Internal+ G/ G$ E' ?+ _
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
0 x# a0 F  k$ c0 l1 Q  V  n        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;2 b) N: n( A% h5 s6 K  }1 O4 a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
* O+ v; p1 H8 g4 _8 q' z  k        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 {& r7 `" F* }
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;0 e1 t0 N) b, `( p
8 T: ^: I0 w2 U0 u% G
        // VRC6% N+ g$ {4 S6 ]& l9 _/ Q( k
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) s. G9 L/ w: `3 c0 Y$ t        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! c! @+ Z' q; z# G3 n& R        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, w! S( G3 F3 u
# _2 |! _2 N, u$ ~1 h, W        // VRC78 j$ e) v; C: j% {, K- l/ D: |
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;! E1 X- e1 s- Q3 }  }* q
3 B; m8 k( J. @
        // FDS
+ [3 r/ l% j8 [8 L& g! r        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
* R) F- e) M# }
- ~; F' }5 u; k- P' |# ]( k        // MMC5, s# ]1 u$ W, W6 L' k( m0 r  e
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, _7 t. c& V3 N/ G
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( @6 l- s: a8 q! h2 F9 X        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 ?' t- H4 y/ \  D; c& G+ j, H0 S3 H) }' E2 r: c4 X) x# b
        // N106: G& D2 N  g% G- j
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 ]' Z# {' g8 R: ?( u9 Q
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 i. n+ @% r2 R# x; h
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 X5 |  v! ?! r4 ^; C* v
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ D% |1 \4 ~: O  H$ Z        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( ?7 d" k2 E0 a        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, }' S% ?" P- w( ]: W4 G8 Z6 g        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ^3 S% z, \0 }( @( F1 H- m        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 Q& n( A2 Q0 l0 C" X0 v

$ Q# }* v' R; s. [3 `        // FME7
/ N4 m  P& h1 w; G5 z  h* b( O        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# ~6 ~) ]1 I8 N& G- F' q
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 d/ J* [8 P' A5 Z" V8 W        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  p5 T8 x% o! x7 O$ Y) W) F
: v% I$ h8 x5 }. m" I. E9 e
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 K( E- r: V* x        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: r  M/ V- j0 l* P+ f) ^" a
% D/ X5 T; \) f/ C* X
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& z6 h, p' O+ Z* e! ^6 e; A
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {7 |2 i1 e8 P" X9 D5 ]
                QueueFlush();/ Z3 u) L% p5 `0 J
        }3 W: d, j* F% O3 H5 m. \) W

7 Z% r" R7 {% f7 c  I        while( dwLength-- ) {/ S+ b( C' O% _, M3 p
                writetime = (DWORD)elapsed_time;3 x* z; Q7 z# _; @

; a% G& r" Y& q  v- Y                while( GetQueue( writetime, q ) ) {8 w9 m0 R8 ?& @
                        WriteProcess( q.addr, q.data );
3 K8 g% O- L4 _1 e6 ]                }2 i5 i+ h9 J- n, D1 m) L
. p+ ~0 M3 L+ z; G/ N
                while( GetExQueue( writetime, q ) ) {
: x; g4 H- d# \, c- n% \                        WriteExProcess( q.addr, q.data );
2 r: Z/ D( W" r6 P6 p                }6 Y% Y2 ~5 u; Y' r
: S3 O9 B) g" g1 F6 {- R1 }
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
0 a1 a( u7 E' e; l1 k& ~                output = 0;
8 t( b: \- ~6 R' G* Y                output += internal.Process( 0 )*vol[0];
1 F: E$ _1 W7 S2 |; I& {                output += internal.Process( 1 )*vol[1];
0 [( b* _* I' u& A% N                output += internal.Process( 2 )*vol[2];# s0 R" Z0 u9 n% C
                output += internal.Process( 3 )*vol[3];
  U4 O& L: Y4 V2 V% W0 v                output += internal.Process( 4 )*vol[4];
( S4 {* l* \& K# Z, g+ g" C0 c( [. P0 j
                if( exsound_select & 0x01 ) {
2 U5 n5 H& ~) ?& J                        output += vrc6.Process( 0 )*vol[5];
- D1 |, O. ^7 M9 M0 ^% C& j                        output += vrc6.Process( 1 )*vol[6];
5 a- Z: j+ k7 J* P                        output += vrc6.Process( 2 )*vol[7];
/ o6 T' X9 Z, ^                }
( ?7 Q$ m, }0 w0 ]% e6 d. t                if( exsound_select & 0x02 ) {
6 k0 Y8 F$ a( _$ u" T8 z1 O                        output += vrc7.Process( 0 )*vol[8];
7 F9 g- z$ N. B" W, Z8 F$ z2 x  ~                }2 z1 L5 [9 n# o$ M
                if( exsound_select & 0x04 ) {8 K, n8 }- w; }
                        output += fds.Process( 0 )*vol[9];
6 }; {9 K! o. d; T8 ^7 H/ m1 \5 b# k                }# w3 ~7 c$ l% z4 k: R+ v
                if( exsound_select & 0x08 ) {
! ~+ I& ]. W3 {+ w6 Z& ]# v8 o                        output += mmc5.Process( 0 )*vol[10];
1 m! X  P" p  u$ a  Z; y                        output += mmc5.Process( 1 )*vol[11];
) h( P5 }1 E" T( ?! F: z                        output += mmc5.Process( 2 )*vol[12];% R: T8 p$ F# t6 Y8 x
                }/ A* [9 d6 S0 W9 W8 o) s* J
                if( exsound_select & 0x10 ) {
6 y5 |# ?- k% {2 f5 |2 Q                        output += n106.Process( 0 )*vol[13];% g% C3 Y1 H+ ]6 Y
                        output += n106.Process( 1 )*vol[14];
  h! l7 R5 p% Z8 b3 C) Q, a8 D                        output += n106.Process( 2 )*vol[15];- h; M9 S0 L9 W, w5 y
                        output += n106.Process( 3 )*vol[16];5 \6 y' c& w: n' [0 A; d# L6 {
                        output += n106.Process( 4 )*vol[17];
4 V+ \, T, o$ J6 s                        output += n106.Process( 5 )*vol[18];
" M1 ?) F- ~7 G' W& U                        output += n106.Process( 6 )*vol[19];* \" g3 x6 Y7 t& \
                        output += n106.Process( 7 )*vol[20];
9 [- Q3 m% K  q! g2 Z1 |                }
- E) j! s* j: M0 E; v) P                if( exsound_select & 0x20 ) {2 r, ]" }3 i% M' Z( G3 S) V
                        fme7.Process( 3 );        // Envelope & Noise, @7 `- R; ]1 C: q
                        output += fme7.Process( 0 )*vol[21];
! A' J8 l! L/ [                        output += fme7.Process( 1 )*vol[22];
# p% S" A- C% B/ C! L                        output += fme7.Process( 2 )*vol[23];/ V  ^1 S! x- g' [' ^: K# c
                }
( i1 v% Z$ f: |; b  m8 X6 [# b& S' P1 Q# n9 Q' U
                output >>= 8;# X7 y. q) K* L1 Q+ q& f% v

( t' w& U+ I6 S2 I$ Y                if( nFilterType == 1 ) {
& e0 r/ L2 ~: V0 s' z: b/ \$ A+ v                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)" f. ]; v! v4 c2 a) B" v
                        output = (lowpass_filter[0]+output)/2;
$ F' {, A! Z) z* c" [+ ]                        lowpass_filter[0] = output;4 f; d6 J5 s' h1 E" F0 S+ v) E
                } else if( nFilterType == 2 ) {
* Z, _& r1 S1 D$ a                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)6 t7 r1 f+ q1 s$ ~
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
& N. Q2 l% C: p3 ?* e( Z6 e$ a3 b                        lowpass_filter[1] = lowpass_filter[0];
% d% a: A+ ]; ^+ o                        lowpass_filter[0] = output;5 L6 |& S: b# L. C
                } else if( nFilterType == 3 ) {$ f) B  {# o& I/ V4 G
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 r- f; F$ O, I! U& e: r                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
2 O5 ]* n; ?" c& V8 S                        lowpass_filter[2] = lowpass_filter[1];' O& y* F; q( D5 \- ~! ?8 \
                        lowpass_filter[1] = lowpass_filter[0];
4 t, _/ t8 Q1 J) Z) d                        lowpass_filter[0] = output;8 @- J4 a, E9 L2 C7 S4 i
                } else if( nFilterType == 4 ) {7 h  k- ]- Z0 h6 y
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* U3 r/ g, F  A" b- Y4 J                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
# v) T) ]* u2 L( R, A4 X                        lowpass_filter[1] = lowpass_filter[0];* k' n1 J+ D* @2 b( g
                        lowpass_filter[0] = output;
) G# E3 e% }- o( N                }
0 B9 f+ ^5 s5 W" |- k! M5 |
8 Q- F4 x! o1 i#if        06 J3 |8 J( p" A* {# [% S, \
                // DC惉暘偺僇僢僩3 q$ s- p( y! ^) a# A
                {1 M' n" t8 @) P" y6 }& p8 J
                static double ave = 0.0, max=0.0, min=0.0;0 [# ^, Q% B' ]: h! @
                double delta;: z$ G0 v3 C+ L4 k% ?* S( R+ l2 i
                delta = (max-min)/32768.0;
( i, B2 ]$ e6 q( b' j1 T                max -= delta;
6 M: A' i. J! O- J3 ?                min += delta;1 s, Q. l; q0 [  B7 F7 h/ h( `9 i
                if( output > max ) max = output;% U$ H+ V- L) @$ i: @. Q
                if( output < min ) min = output;
  D2 L: Y3 T- m                ave -= ave/1024.0;* ^; _$ o( \+ c8 |
                ave += (max+min)/2048.0;4 J; a, v/ d3 y0 a7 v
                output -= (INT)ave;; {* _6 `! P) z0 N* j+ b
                }. e# U) s/ I- ^* d* ]) T
#endif2 v+ j/ o  m! Z# [9 Y* F6 M9 s
#if        1
8 p1 p* C% u8 @; ]                // DC惉暘偺僇僢僩(HPF TEST)1 f1 x- H! f( k2 q8 Y+ N- Q- b
                {
( y/ G( q6 G) k8 d$ Q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
( A) q0 t6 Z- `3 n6 ^2 p& h: m& W# s, O                static        double        cutofftemp = (2.0*3.141592653579*40.0);. z! [* G, z% s& U1 N* U
                double        cutoff = cutofftemp/(double)Config.sound.nRate;1 B* u1 N9 ^' y! ?$ N7 d
                static        double        tmp = 0.0;8 H1 q& y% K! Z2 }' V& M
                double        in, out;7 }7 m- Q6 m& u- f7 z$ B* R
9 {& U; O  q8 b- O" C# o$ j0 ?
                in = (double)output;8 P- d% \* J; B9 w. N( O# q
                out = (in - tmp);
9 q9 A" G: E, R7 W. R- P9 T8 m* D                tmp = tmp + cutoff * out;
' X  X* }( x* w$ Z* G) q1 Y" h: P6 s9 p9 ?
                output = (INT)out;
9 X; `  I# `+ Q. x/ \9 L4 s                }* J$ Z! s$ j, P+ ^' C4 z
#endif
  R) i! X8 D9 `#if        00 Q. t( s# D% N  B- e  N
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
) m" C: }  L+ m9 e' a/ @                {3 d1 g5 D1 B! f2 j6 T1 A
                INT        diff = abs(output-last_data);
5 W, j- a1 X7 s/ s  T                if( diff > 0x4000 ) {6 |1 r' t( s2 l! m! I
                        output /= 4;: c5 V3 @! c1 ~& O- v8 ~5 ]3 a! H
                } else
+ K2 G# p, u# ?( n' j. }                if( diff > 0x3000 ) {' @4 m7 w5 c: k/ a; L! C
                        output /= 3;
( Q% O0 t5 ?# W! s% O5 a                } else! X5 d3 Z7 A8 G: X
                if( diff > 0x2000 ) {
; ?9 p: q& N* o3 `! ~2 T4 o                        output /= 2;: C9 E6 Y  o' }1 Y; [9 u# m" L
                }* v, S$ u4 q: g( m4 B' @
                last_data = output;
/ i/ T0 g1 Y- {$ p                }% L- m9 \: n' w) T5 }8 {7 y
#endif
" L3 j3 _* p4 ~. w% h# |0 `                // Limit
7 i) J3 n( T# Y# }, o7 m                if( output > 0x7FFF ) {
0 a0 O! S: |$ z9 o" B                        output = 0x7FFF;; C- |3 w, ]5 f; C
                } else if( output < -0x8000 ) {& n3 A+ ]$ g6 E+ \+ d
                        output = -0x8000;+ f! {; I9 u3 T; [! |! U
                }; l- A8 i6 @# _, y( o( F. Q

7 }, P% C( Q( d                if( nBits != 8 ) {
$ K  _- D7 K+ h7 e; T2 f                        *(SHORT*)lpBuffer = (SHORT)output;
6 q0 }3 ]  J3 J  S- J( P                        lpBuffer += sizeof(SHORT);
+ L/ f6 `$ A- @6 C& r5 j7 e                } else {8 P& i: b! ~  {7 ~$ ]
                        *lpBuffer++ = (output>>8)^0x80;8 C3 ?9 F! b; c7 ~
                }
) ^1 X; ]/ m/ i
4 a, R5 L9 ^8 Z: R                if( nCcount < 0x0100 )1 F" v  Z# r5 O  A; E
                        pSoundBuf[nCcount++] = (SHORT)output;8 y6 K- l4 O: c4 V+ O' u

" H& u$ m% J& a  z' X% d5 I; b, b//                elapsedtime += cycle_rate;! w8 p0 O2 K6 k8 G
                elapsed_time += cycle_rate;8 A4 z! E+ J. b" R2 ~* C
        }
8 m4 k; i+ h. D, |
/ h3 Q( j4 f- R* w% K. I6 N#if        1
& E+ H4 }0 B+ J  x9 {        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
+ k* }: {  `# `/ b7 ^( f                elapsed_time = nes->cpu->GetTotalCycles();
* V# I1 u" p% s7 W        }
& M6 A' m+ z# n        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
" f& h3 ?5 y) }, z: f/ J                elapsed_time = nes->cpu->GetTotalCycles();
: g8 i- i+ h% L* T, r/ v" _2 y        }( T. D* d; t3 u: s0 m6 Z5 ]- s
#else
0 |  Y* a' T+ y$ A3 z, @/ O1 X        elapsed_time = nes->cpu->GetTotalCycles();
) P; Q' y% H$ j* q: F. B9 c) D#endif
; D% V8 H/ Q4 ~6 d  B}
# m' T5 K7 n! S/ o) c, S1 a5 f$ T3 ~
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! ~- i8 [# u! c3 o/ m4 {9 fINT        APU::GetChannelFrequency( INT no )
" e. I* v; j1 W; v" b{
! Q. z, r$ I9 Q) J9 ?$ D1 t        if( !m_bMute[0] )2 q: [) f- E/ v0 [- J
                return        0;5 p+ m* @* U* d: l; V

/ U& Q0 |! z1 `) G2 V. T1 o        // Internal0 q. D# x' f! E* C) A! G" l' v
        if( no < 5 ) {
$ C0 {+ B' K/ S6 }/ Q9 k                return        m_bMute[no+1]?internal.GetFreq( no ):0;2 Y( F  Z8 ~: v/ d+ l7 Y  J# ~
        }
. ^1 a. R* [" I# {: S        // VRC6
1 e! A+ ]( W9 e  ^$ [        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' j" q% Q1 t/ E5 ~4 T2 ?' |% K                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;9 [$ y* P$ t5 |
        }& ?' l. p) z3 t  o6 G, S
        // FDS
+ Y+ Y. X9 U; R4 O& H# y8 j! d        if( (exsound_select & 0x04) && no == 0x300 ) {
. b: G1 n6 N' ?% q2 {# H                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 A& Z1 B* o( z/ E" y' P7 C
        }
" c4 D% r; p# |6 k        // MMC5
! Q4 M9 K4 z" Z" e  _2 u) v: a        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {5 N2 T0 z: O$ h/ x3 E6 i5 W
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' y4 L7 a% T- q4 S6 S
        }3 W: L/ h, Q' g" k, @
        // N106
4 r5 B: C- X; v1 u        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* v- g# K; d! N3 w- w0 ~2 R
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* [! J: Z* k& u3 v$ z% S        }
3 \& e2 w' p9 R, h2 e        // FME7
0 C* E8 F6 i" o/ P$ l5 f/ f        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
& w, N+ N. f  c" G; n5 c                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* _  _9 b. \# _0 e0 o        }
" H! P. q1 C% i  h0 C2 Z8 z        // VRC78 l8 o$ }2 k( H8 X9 J
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
- X7 O$ _0 Z& G, v( p! v% u                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
# E! i6 D5 Q' I/ a3 ]2 V        }
. A  g  u. w5 G. [        return        0;
- z' o! C2 F; k+ Y}' q9 j2 b  ~/ H6 N: v& r) r
( f3 K  u% M8 q8 U5 W3 T
// State Save/Load
! s) b1 [' N6 f2 F0 M, X9 k2 nvoid        APU::SaveState( LPBYTE p )0 Z' x* l9 r; z. B+ M
{' J9 @0 |3 ~  V5 x7 }" e
#ifdef        _DEBUG
( E8 x+ x. T+ E2 E" R( G7 D& CLPBYTE        pold = p;
5 W( E, A) N5 s+ c4 F#endif5 B+ m2 f$ \" w+ U4 p- S6 `
3 \2 s: J; l7 h9 A
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 F8 A( B) z* V* A* f' \+ W, W2 b        QueueFlush();/ D! h& b* ~& X7 ^

) a% \4 M5 m+ x5 G8 ]0 Z/ P        internal.SaveState( p );
( ~& l& _' ^) d# S. t+ X8 T- ~        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% S( H2 e: [. e4 l9 E; ^9 w
# V. R- J% @% g* |* J
        // VRC6
* W- H: \* @4 ?7 W; F' M3 W6 E        if( exsound_select & 0x01 ) {
& N8 _0 A# F  s/ P( d/ P6 I                vrc6.SaveState( p );, j, a7 z% o9 h. \5 R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ _. i7 Y# {) h" t' y
        }/ C; D0 s8 m/ K0 J  b7 J9 z. c; L7 ~& n' G
        // VRC7 (not support)
3 |) S! ?+ G- |; M/ ?& Y        if( exsound_select & 0x02 ) {/ V5 i9 l  L3 Z$ R' w
                vrc7.SaveState( p );' }8 o8 A* H4 f1 y, u% O
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 c( d  m* }+ G& d
        }
. L/ F5 P' U+ ?        // FDS  Q0 P+ i# ~' c6 R
        if( exsound_select & 0x04 ) {6 ?) m$ M: u5 i7 |) ^& o7 U
                fds.SaveState( p );
% V& L( t. S$ \/ X$ a                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ h0 @, k  Y1 C7 |- T, k9 i
        }
, V2 A: ]2 z( O9 `6 z        // MMC5, n4 ^# [2 e1 ^2 X
        if( exsound_select & 0x08 ) {4 m6 I, J; t! D9 I# O" T# t0 e
                mmc5.SaveState( p );
( J) X' O! ?' y& J$ D                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 V" z0 a; h9 M6 ]9 m* o
        }
2 S) K0 w% }3 ?4 X( }  P& @8 {        // N106
7 S! K0 t5 Z9 p( N( n2 u* q6 f, V        if( exsound_select & 0x10 ) {
3 D- z: q) {$ s, \% t                n106.SaveState( p );
0 M/ E( Q! }) D: l% k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 {' o4 S" w. H& w  P3 S3 R
        }2 Y0 y* P, I& i6 f% ?
        // FME7
# n) L$ \) H1 a1 c0 U% n& U        if( exsound_select & 0x20 ) {
) _( |! K7 Q% x                fme7.SaveState( p );
0 g1 n$ B% k2 y$ Y/ Q, w                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* U2 k4 ^% O; L2 l6 S8 I8 d. [
        }
, {$ S: `! e( `: x3 q2 Z6 }
4 z( v/ v4 w9 y0 N  J! R#ifdef        _DEBUG
2 j- }' X5 X* N' e( mDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );- \! W$ O1 Z: c' z& s- ~: E
#endif
  i3 c+ V- z3 ?5 `}
) X& a6 _# m( v- L+ e
& ?( }2 u, c0 T+ X7 D, b1 ]. Dvoid        APU::LoadState( LPBYTE p )
# ?0 P6 j2 A$ x: {, A{. X# o& N+ h9 @: f% C, g
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ Q; L& i( x/ {        QueueClear();
: e, ]3 S) M; H& c* b; o/ _6 p( A4 F: r
        internal.LoadState( p );
$ z  x: M8 ?3 B  z6 M        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; c4 _5 E* O- {( C. |

3 P. u$ R0 k7 f* F7 V, |8 \2 P' a        // VRC6' X2 L) ?7 C  a4 V) A
        if( exsound_select & 0x01 ) {
. n, A) v. x0 Z: W8 u+ |                vrc6.LoadState( p );
1 {# v& r+ H' b! C3 K( D                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* l! `; A8 L: Z0 X
        }9 i  J% H$ v4 \+ O0 X) W; [# l/ M
        // VRC7 (not support)
7 S6 @3 f: Y3 t6 o3 O6 x2 O        if( exsound_select & 0x02 ) {. W" Y$ @- c0 B4 j/ [
                vrc7.LoadState( p );1 V$ y' a' N9 j' C
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. K+ d$ Q$ h% I! K+ c        }
# ~" I* E) z- F0 \, x0 r        // FDS  ]9 e' _9 ^' e
        if( exsound_select & 0x04 ) {
+ s: k! X1 w* ~8 D" `                fds.LoadState( p );; x, m# d8 F* e1 M. C  a
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 G( W$ x+ d) C+ n& P- n& W- b
        }
& i& G) o) S7 L1 F( g% i        // MMC5$ n, l3 t! u2 m1 I7 y
        if( exsound_select & 0x08 ) {5 h8 }* q4 ^* @- h! ^* W
                mmc5.LoadState( p );* Z0 T, f( q, l* i
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: H/ q+ n% i9 ^1 @# X3 |: @3 t        }
% F4 g! y) V! @4 {; M        // N106
8 s. v6 k0 p8 t        if( exsound_select & 0x10 ) {/ ]. S1 v1 }: M" x
                n106.LoadState( p );
% }- C1 `: R' o, N  |0 t                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, r7 X8 C  a* ]; j' R
        }5 H9 ?9 @1 L) M0 Y# `  ~( c1 o
        // FME7
" c; I+ a" f2 }1 A( Z        if( exsound_select & 0x20 ) {1 C+ O' G/ M) |$ E8 q8 G
                fme7.LoadState( p );! \& v; k' m8 o# ^5 ?
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 a# H7 b) }0 n* G& D! }
        }" R& u$ Q* h# H
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
; e& |9 K8 d* K$ K* c8 R" S; z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# m# p2 S! ~+ H" N5 s. a; a
感激不尽~~
. E5 S* R* `5 }0 E2 f
恩 我對模擬器不是很有研究,6 ]+ u3 T/ b! B* x& g
雖然要了解源碼內容,可能不是很困難,2 s: Z3 g, c* Y1 J; D
不過還是要花時間,個人目前蠻忙碌的。
7 ^1 M7 o) f6 }) Z$ h$ U
+ w( w1 J% t" I0 u/ ^給你一個朋友的MSN,你可以跟他討論看看,+ w5 V. i6 C  i0 j  O4 q( T8 B
他本身是程式設計師,也對FC模擬器很有興趣。
& ~4 V' A) h- Y6 A5 W+ R
7 c( X) K: d  O! N) Y5 l% YMSN我就PM到你的信箱了。$ d7 b( k1 M+ b3 N& q
/ L1 _# p; d# N2 J7 D
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
' j6 Q; _- D9 W呵…… 谢过团长大人~~
3 D2 K2 {, ^( d) H$ ?3 B; g, }) B

- y7 d" \) G6 E+ D' L3 A哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
1 t) ^# W1 T- J( w1 k团长的朋友都是神,那团长就是神的boss。
! v0 j; Q3 X* ?, G! Q
哈 不敢當,我只是個平凡人,; u; @8 @( [; }) |7 K  t6 X4 @# U* T2 g) s
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; E; h7 z& f. U1 V$ X% b/ [/ B& HZYH
$ j; u& C1 P, K; _QQ:414734306  X0 p0 C/ p  h7 b3 C
Mail:zyh-01@126.com* p; z- Q( U$ |' G0 J. e: x* A

3 t& X+ Y  o, Y2 e- {  D. R他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 5 o7 b, p( h& m
再次对团长大人和悠悠哥的无私帮助表示感谢~~

$ Z& r( N! p$ M不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-24 01:40 , Processed in 1.115234 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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