EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 o- A4 _; M4 h! Z' |2 M: J. [  n3 A
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ a4 _  ^2 [' V! g4 V这里有相应的模拟器源码,就当送给大侠了~~0 H8 f* X0 Q* e& N7 g( r' n. X1 r
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
: e7 u, k* J0 E. l& M" @3 n$ s能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% p  P/ f8 h/ @; g% r3 y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~+ H: Z* V3 o% q/ b! Z
这里有相应的模拟器源码,就当送给大侠 ...

9 L: n' z. f. H( D3 s( }聲音部分(Audoi Process Unit = APU):/ f. N- Z8 p7 f) {) a6 x; p
.\NES\APU.cpp- \1 s. F. F# t4 U# N
.\NES\APU.h: S+ {$ Z) j. w, ^1 q: n- C8 l6 Z
0 H- ^  K$ ?0 [2 ^0 _7 ~

  J2 V7 K+ b5 p( K9 y# S影像處理部份(Picture Processing Unit = PPU):
6 n2 A; r6 w5 g2 \/ c: p% E.\NES\PPU.cpp: v9 ^! \0 N' k7 W3 k; C6 y
.\NES\PPU.h* B4 c& p, N# }+ K  |7 {

4 ?5 p, _, e$ z1 P如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- b( o) f0 Z8 G7 Z& ?5 @2 U/ D- a5 n
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:! p4 u% D3 ~  a- n* }, x
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
, |' ]9 `/ @$ D. }8 l//////////////////////////////////////////////////////////////////////////1 m+ n" A# Y' p4 l6 X7 y
//                                                                      //- O0 v* }3 c% Y7 Z' s! m! r
//      NES APU core                                                    //' R2 u7 _6 O* C! Z! b3 w4 S
//                                                           Norix      /// N! t* ~! g$ A$ {* L
//                                               written     2002/06/27 //
6 h; W% U: ^" u# r8 ]7 l//                                               last modify ----/--/-- //+ L. E8 K4 z% a
//////////////////////////////////////////////////////////////////////////
, i0 i# _, b2 g$ M! s#include "DebugOut.h"4 v: v  L$ q1 ?2 B9 `
#include "App.h"
+ z% h, b+ h) w2 L#include "Config.h"
# n: t' M0 ]/ P! q$ Z8 D/ ~8 \# {+ X7 [) i/ v
#include "nes.h". B3 _9 ]+ L# K1 S3 U6 A
#include "mmu.h"& I" h" Z) ]2 V
#include "cpu.h"% g0 V. J1 _, J) J" B0 K, T
#include "ppu.h"& u# I$ T, B! N. y6 x. u) b" b
#include "rom.h"+ q6 ]/ W1 ]/ ^! {8 L7 ~0 A
#include "apu.h"
& y1 G, U3 A3 q, e
( P( J6 t# x  C5 s2 M& A// Volume adjust
: U- W2 `  x) s// Internal sounds8 x  T% t; H& |8 x+ w/ }
#define        RECTANGLE_VOL        (0x0F0)% W8 ]5 M: q. y! r( F
#define        TRIANGLE_VOL        (0x130)6 G! [4 y& A/ r6 P; u8 T
#define        NOISE_VOL        (0x0C0)
, E9 L" v. z& Y) {#define        DPCM_VOL        (0x0F0)
% Z& Z0 _8 [4 X9 s1 z. E* ?2 y// Extra sounds
* k2 g% M% J& s& r. }9 L4 k#define        VRC6_VOL        (0x0F0)
- |' G" C9 F2 E* H3 w4 m#define        VRC7_VOL        (0x130)! B0 A5 H' o; _, v; _
#define        FDS_VOL                (0x0F0)& B* l- N$ D/ c$ C9 c
#define        MMC5_VOL        (0x0F0)
$ {' m' D" q. _8 U. k! i+ t8 |2 L: K#define        N106_VOL        (0x088)
$ o% E! z1 U7 |  p9 p7 V! r9 h#define        FME7_VOL        (0x130)7 J' t$ K; r' ?
' s0 @: }8 d6 U1 @3 K
APU::APU( NES* parent )
* A+ F1 T& v) ^; M! I{
) u/ `. I/ \* w+ g. j% C; m        exsound_select = 0;
4 \4 A! b: s: ]2 @- d1 D9 ?$ l& a2 u9 e. `  Q
        nes = parent;
3 t: c* ]8 E& u* ^        internal.SetParent( parent );$ @" M& o5 p# u' p& O
* b# R5 z+ d1 T' E2 C
        last_data = last_diff = 0;
9 ^& l+ E7 J/ k- b; ^6 r( q) y, K
$ t$ ~# T& I" H9 U( Y        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );9 X5 o  u$ _. a) z" `

  ]0 m9 g* d$ u7 V- I# J        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
( C& b+ C2 \; _# r# K) n1 v        ZEROMEMORY( &queue, sizeof(queue) );) r0 z) F' J% r
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 V/ _8 j! R! H, ~% |' m1 V
6 ^! ?" p* {- f) s$ ^4 [
        for( INT i = 0; i < 16; i++ ) {
3 Y0 o2 j+ B5 R! @, R+ q1 F                m_bMute = TRUE;; Z" z. ?% N4 N+ m4 M
        }6 g, b: ]( q- ]
}
( D' E$ _8 ]8 i6 p! d$ e+ y7 m/ O% _
APU::~APU()& B, J* _0 X' k3 u) e) e" f% O
{
5 K: Q1 m" I- `8 D8 w}
! V1 |5 o1 N( }# i( |7 k4 O& d
3 w; N. `' @8 uvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )  @  ]! [6 e6 g3 m
{& Q0 H  r" z2 G* `# ^# z( x! n) E
        queue.data[queue.wrptr].time = writetime;
" |5 w+ _* M0 B% ]" S        queue.data[queue.wrptr].addr = addr;
3 k) G4 D0 m- w1 X        queue.data[queue.wrptr].data = data;9 c1 ^7 ?$ g! d& \4 u: p* G
        queue.wrptr++;) p; u9 @2 ~$ N
        queue.wrptr&=QUEUE_LENGTH-1;7 E8 ~& M) d0 Q: o
        if( queue.wrptr == queue.rdptr ) {/ o" m+ v, ^- b; d
                DEBUGOUT( "queue overflow.\n" );
, M# o& n6 J  _3 S7 w, r: L( u        }
2 l9 z/ k: b9 l6 s}" U5 q! Q+ f% C0 @4 V6 R8 R
+ }: m# q6 `; T$ L; Z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )0 T- W8 L3 d; L0 T5 C$ Y0 o) ?
{
, m& c. n4 R* f# y' ?        if( queue.wrptr == queue.rdptr ) {* ]* K* r9 g2 b1 T5 B! s5 X
                return        FALSE;0 P* x( q$ J0 }; ~. ^
        }
! O& M1 I9 ~. R7 f% c- Q9 b& Z, u# g        if( queue.data[queue.rdptr].time <= writetime ) {
5 E& J) }  a' u! q                ret = queue.data[queue.rdptr];6 K# t; f+ p+ w, |7 b) g
                queue.rdptr++;
( P6 z; Y1 U7 W: X1 W3 x, O                queue.rdptr&=QUEUE_LENGTH-1;
! v  _; r7 [. |$ c                return        TRUE;: V4 u! l7 D" x1 X
        }
) i7 S) x9 i  x9 H        return        FALSE;
" ?, h! M0 ~# Z6 i% N}+ j' m! Q: H+ [& f% _' j( M+ Z7 q

7 T4 I7 R. y2 T! Y  l6 ?9 W) Mvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* ]2 @: q- m( p; [0 L6 @4 H( A{
( }! ]0 D# |+ s8 U: F( S        exqueue.data[exqueue.wrptr].time = writetime;* z$ q2 |% U' g: K' ]
        exqueue.data[exqueue.wrptr].addr = addr;) ^7 ?$ G5 l1 ]! I9 Y" a1 g" H8 R
        exqueue.data[exqueue.wrptr].data = data;9 T$ j6 c: y0 M4 I" }) w, K
        exqueue.wrptr++;! D0 y% W4 a  e/ h  n
        exqueue.wrptr&=QUEUE_LENGTH-1;
3 ]8 L7 v9 W" n+ k7 l* Y  s7 J* q        if( exqueue.wrptr == exqueue.rdptr ) {
3 j4 b! a% b# m+ \                DEBUGOUT( "exqueue overflow.\n" );
: T( @% B# F5 \: X, c9 _$ Y7 W        }, P: E2 K9 b; ~, @
}
% b0 F9 T9 G5 F3 ]) C9 s- Q3 c3 s  T* g$ `
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )+ t# p0 g6 \* ]
{. m5 l  ], B8 P
        if( exqueue.wrptr == exqueue.rdptr ) {
) o: U+ x. a7 o" k! J9 l0 o0 r2 @0 q                return        FALSE;
% f0 s* P# D# }* y+ g! Z% s1 ?8 b        }
6 W! G4 U) a' Q' N+ R1 A        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) o  q8 d, ]8 \
                ret = exqueue.data[exqueue.rdptr];
4 Y! w" z; N2 \( M# k, D: B                exqueue.rdptr++;- Z, R+ C' G! P
                exqueue.rdptr&=QUEUE_LENGTH-1;7 `  P+ L9 p) w) H" d6 O3 c
                return        TRUE;
: J, h8 A* j# X# J6 Z        }, @5 z- O' {3 a9 E
        return        FALSE;
4 D. G$ s" s& Y+ @4 u1 }2 h' E}5 l- G) p+ E/ b6 d& C: k; R
, w/ K4 d' E, e1 d8 ^4 v
void        APU::QueueClear(). w4 U) K8 P( N& ~# U
{9 W" x* R6 c) F4 r, X
        ZEROMEMORY( &queue, sizeof(queue) );
& l3 |2 D! i% e2 u        ZEROMEMORY( &exqueue, sizeof(exqueue) );) y/ T5 \5 c+ E. W; y, p, H
}
. A+ }0 _  s  J
' x' ?2 \7 V1 G2 ?3 avoid        APU::QueueFlush()
) L: y! _+ }( P) K{
# G8 x8 X) ^* B/ c6 ^        while( queue.wrptr != queue.rdptr ) {5 d/ ~, _& o% ]$ E
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );" A- `" F9 z  U, ~) u
                queue.rdptr++;1 D' `& k6 l8 p" ~8 a  S( M+ n: \
                queue.rdptr&=QUEUE_LENGTH-1;' D9 g' |8 ~8 r3 D& [. p
        }8 u* B$ H, n3 `7 w% E1 Q/ R

# s* k5 i) }8 w! U$ I        while( exqueue.wrptr != exqueue.rdptr ) {' ^1 y7 [8 v8 l  g- K% m- q6 r
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 ?9 H1 J. m- f; ~* }, Q* h1 X                exqueue.rdptr++;- d* y. ]7 z" f* J0 l4 o
                exqueue.rdptr&=QUEUE_LENGTH-1;$ x3 y* X" D- ?# C+ R, ]
        }
7 A5 W" @4 ]: l- D- J6 I4 e7 G7 m4 ]6 o}2 C* \! C- ^' ?) F  ]% ^2 H
" I7 K& i, n* w
void        APU::SoundSetup()
% R) p. ]6 z. _5 S# C' ^$ _5 E. }{
& w# [" L# {8 F) V( p4 l) X        FLOAT        fClock = nes->nescfg->CpuClock;# e) c; P* g" U' M' u
        INT        nRate = (INT)Config.sound.nRate;; v8 x) P% ?+ ~0 Z' h# k' G6 F1 e9 o
        internal.Setup( fClock, nRate );
$ [8 K! y1 p9 |8 E) t3 Z# _% Z3 l8 V  _        vrc6.Setup( fClock, nRate );
  H; q9 K8 l& j7 E% i        vrc7.Setup( fClock, nRate );
- @# X& r, f5 E        mmc5.Setup( fClock, nRate );
( P0 a0 Q/ D$ l3 Q& L+ H0 ?/ ~        fds.Setup ( fClock, nRate );% ~, [9 W0 B8 V3 i0 M
        n106.Setup( fClock, nRate );
& {/ z1 }4 @  V& S3 J        fme7.Setup( fClock, nRate );
9 F% c$ C; y' \* u" V9 a}0 h8 M; b. S" L: G

- ?& p0 f9 S4 j* Uvoid        APU::Reset()
' C- j* ~: L( ]6 j{9 a5 s7 H  Z7 v! A4 E
        ZEROMEMORY( &queue, sizeof(queue) );
9 Q* m( {+ o1 h9 a* y: S. i        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 `% r8 `* v* R, ^- w
( S5 w( U9 |4 v- J# Q. F, X5 j
        elapsed_time = 0;
3 C# N' I% I' E% c7 b# J" @, w9 v* N( t; T: U6 J* R; |
        FLOAT        fClock = nes->nescfg->CpuClock;5 e/ Y' M( s! d: T, ^
        INT        nRate = (INT)Config.sound.nRate;0 n9 l! x& Z1 x( r1 x8 `& F
        internal.Reset( fClock, nRate );$ U2 M. {2 ]9 k, Q1 g
        vrc6.Reset( fClock, nRate );
6 N4 I( Q- t* R        vrc7.Reset( fClock, nRate );6 x# C1 m% l0 V& i8 E
        mmc5.Reset( fClock, nRate );
4 ^1 a" d7 s3 f        fds.Reset ( fClock, nRate );  W) ]" I2 t5 e' s
        n106.Reset( fClock, nRate );
3 ]- L6 O/ T" I. _8 o. Y7 B        fme7.Reset( fClock, nRate );' C8 M2 R  |) X
2 u+ P9 J  U1 C# K: A$ \9 t+ z1 }
        SoundSetup();6 F# |. t- ?% |5 |7 h; i# a
}
5 A( X4 s2 h  F: ^
6 W1 p3 x# t, q5 c; Wvoid        APU::SelectExSound( BYTE data )( P4 T5 a/ n9 Q
{
" X5 c2 {5 L( d) Y& G! h        exsound_select = data;
  U2 i1 R. n# I- M/ x}, e( Z$ L. H) i0 {3 ^# P; L
4 \" B5 ?- s( s+ U7 H
BYTE        APU::Read( WORD addr )
# X) u1 A' D6 Y  F$ V{
) G( o$ n7 l! l/ M4 B! S3 v4 M        return        internal.SyncRead( addr );
; f+ _2 Z) U5 P}# K; W0 X+ ~" m

! o+ `( y( T+ ^5 A% Ovoid        APU::Write( WORD addr, BYTE data )' f3 B" s! f3 i/ L5 N- G  T
{
1 u0 C3 L: B* Z2 S        // $4018偼VirtuaNES屌桳億乕僩0 g1 k" J3 @! s6 M$ ?) p' ~4 e6 ^& l* C
        if( addr >= 0x4000 && addr <= 0x401F ) {0 W1 h1 Y& ^, d! ?+ S
                internal.SyncWrite( addr, data );0 d% Q$ C7 m! }9 I( ?0 X
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ }: r( h* J( g        }
9 t) C% o" Z7 V7 z* p) k) L6 ~" O, |}
* v+ Q: ^) W+ f% N- F! W1 p/ _8 v% p3 [/ H& c( L+ K
BYTE        APU::ExRead( WORD addr )
8 d" b2 Q" T* X' I{, i  x# E/ i( j& P
BYTE        data = 0;. H2 Q& K* \0 S. `

& T7 `7 ~4 \3 m0 C7 K        if( exsound_select & 0x10 ) {
( }# Y3 h1 m5 e: n. q; c3 E0 ^! w                if( addr == 0x4800 ) {6 l7 H0 a& _/ ?* w
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
9 x" c% p# g( ]) v- ~/ c                }" S) {" Q1 U* U# p! N, ?
        }
: q* p! K& J7 k$ t        if( exsound_select & 0x04 ) {; H1 e% }" A0 Z
                if( addr >= 0x4040 && addr < 0x4100 ) {
; N+ H1 ~2 c& _% b: W0 a                        data = fds.SyncRead( addr );
: N0 p( c3 m! x) d; \- Q                }
* A7 a6 u0 {2 \1 u0 Z/ Q9 n        }
; S! i! t  q/ J8 X4 L" r2 D0 T        if( exsound_select & 0x08 ) {
* n& u. e4 E* `' `1 h                if( addr >= 0x5000 && addr <= 0x5015 ) {
) A" z1 m% `' L3 |2 e# L                        data = mmc5.SyncRead( addr );
! \: k: g6 c3 Q% Q" v$ [                }1 Z; U2 V* F& f6 o8 N* \) |
        }+ t7 l! J6 U6 I+ L- H. E

. V& m* P' i% ~7 P        return        data;& `% G- g2 ?9 P7 Y8 ~+ g
}
/ x) p7 ]- d: e1 B+ C
7 I3 d* |+ H+ w  o  Yvoid        APU::ExWrite( WORD addr, BYTE data )
% T1 H  z" o! d) Y$ m{* h4 w, f# ?. Z# z2 i+ c
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
$ R* K; b8 E( [2 n4 x7 _& ^% }5 z+ v3 r1 E( I
        if( exsound_select & 0x04 ) {
: n! `9 E% w' b. G7 A) a                if( addr >= 0x4040 && addr < 0x4100 ) {1 T6 f7 w2 \3 U- ?7 Z7 F2 L! u# j
                        fds.SyncWrite( addr, data );
- K0 Z- \) x) V6 d6 |; M                }
2 c& w3 Z# C7 H9 ?) E9 Q        }+ |  L) j9 L; P3 G7 C7 S. B4 |: m/ _
2 C6 C/ x  f) p# g" G; F
        if( exsound_select & 0x08 ) {9 ^1 E8 L* x7 A$ H# \2 G/ C- C
                if( addr >= 0x5000 && addr <= 0x5015 ) {
. R6 N1 g9 B7 [) z                        mmc5.SyncWrite( addr, data );
% {3 _  ]$ B) N                }8 Z! R% {8 J  D5 D4 A4 @
        }
5 I  g1 u5 c! [, d6 A}& \- P4 R- N* b& z7 V  k1 y9 q

) j  Z/ g  U. h# C2 h/ l! pvoid        APU::Sync()
3 o. G: u) k) N) |& ^2 a$ `{+ \: S$ `4 [4 r0 j& G% t# l7 A8 K: @
}' E/ s; T7 W! Z

$ r0 s- x( M% a: {' ?void        APU::SyncDPCM( INT cycles )$ J" e4 f3 |2 n
{+ J5 Q9 L" A* S3 ?- o/ Q0 j
        internal.Sync( cycles );
* W- M$ Q( v& q) j3 [0 b$ r; p3 H7 e# J2 k" O. r( e4 t
        if( exsound_select & 0x04 ) {
  o4 A6 W. ]2 @2 ^0 U8 Y$ J                fds.Sync( cycles );
3 @2 C/ G) q7 j6 H6 a* k; c3 \  @        }
* K0 p+ ]6 G# L, D& \        if( exsound_select & 0x08 ) {
; \2 a4 w8 d  m2 M/ w. s                mmc5.Sync( cycles );
+ j  Z  w2 y  x1 q7 c$ r, a        }
& E, e- M2 D, x' U+ d+ l+ a}; y: B2 J, S. @7 @/ X
& Y8 U# C; M1 _0 y' [! u2 A
void        APU::WriteProcess( WORD addr, BYTE data )
# X+ d3 P4 C% f* `$ q{
: p/ k# W8 V$ ^: q        // $4018偼VirtuaNES屌桳億乕僩  g% x6 o' d$ v/ ~7 `: u* f
        if( addr >= 0x4000 && addr <= 0x401F ) {2 h: B$ [3 ]# C: K( h8 c# b. m. e
                internal.Write( addr, data );" S% B2 V& }% b3 A0 r! }3 |
        }
! Y# j9 r- k7 E( ?! u2 C4 X}8 O8 y% N' l1 s

- m# A4 V% M5 ^! d8 xvoid        APU::WriteExProcess( WORD addr, BYTE data )
, n7 m2 a1 z) K{  e7 i4 O- p$ i% u
        if( exsound_select & 0x01 ) {
! j: c( z* v' a/ G. e1 w                vrc6.Write( addr, data );9 k1 h8 t0 k5 j7 t
        }
# x& J$ R( L" s6 t* h        if( exsound_select & 0x02 ) {
- q( }/ ?  X1 V  K& u( D5 o2 }! r                vrc7.Write( addr, data );# R$ M) I) ~  y  q
        }
7 Y+ d6 {* ^. C        if( exsound_select & 0x04 ) {
" d8 k' G  E/ f                fds.Write( addr, data );/ z8 ]6 l. Y- n: b9 O" }
        }
4 M1 M. h# O9 v3 p* h        if( exsound_select & 0x08 ) {
/ V7 r# u0 y$ }3 ~( J                mmc5.Write( addr, data );7 U, L! T, B0 w8 N6 U" Y( {$ D  n; W
        }3 Y; K' |* K/ p$ Y  w& D! I# }7 N+ C1 m
        if( exsound_select & 0x10 ) {
) ^9 [1 `7 `8 g9 L5 ]  T) Y                if( addr == 0x0000 ) {
6 c- {7 x( L; I                        BYTE        dummy = n106.Read( addr );
9 [; }9 W; m5 ~. Z                } else {, H& d. m! k+ f0 m2 `+ W% k* _+ ?# ], |
                        n106.Write( addr, data );
. j- x% L5 H6 Y' Y, H                }' M4 C9 U' D4 L3 S( m( S
        }
4 C) Z. W- g: r2 ~        if( exsound_select & 0x20 ) {
6 `5 r+ R, B3 k7 d                fme7.Write( addr, data );" z3 k# N2 n! j: S/ z
        }
* j9 t$ I0 W' `9 ~}
; w* J! V- P2 O: v: P& N, l' I( F* `( Q' D, `3 s, i1 W  R
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ B: A; j* Q& p" c+ e{
0 c* ]& W3 b# b5 N/ `) BINT        nBits = Config.sound.nBits;0 {4 u$ v! F2 P* Z' N4 j4 w
DWORD        dwLength = dwSize / (nBits/8);
8 a7 L+ H/ `$ xINT        output;  ^3 c& b) U6 D- F. C8 S
QUEUEDATA q;7 A- E2 U% j# i/ f1 Q. Q/ |
DWORD        writetime;
) S7 B' c# A8 L4 [. D9 t% w& W! f
2 Z2 j- V9 G1 |, |) FLPSHORT        pSoundBuf = m_SoundBuffer;
2 l7 R5 A* S: k* J3 a- iINT        nCcount = 0;
* S( ~# n. ]  m( @& D8 O) j" X; G5 J6 L/ ~5 d
INT        nFilterType = Config.sound.nFilterType;
! M, r' P& U( G
+ u8 k+ Y- ]/ e0 _* D        if( !Config.sound.bEnable ) {" J7 q% h+ \  C: r+ h# h6 c
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
/ \1 p  S7 o% K                return;! {4 [: S! |/ U( ?0 G2 C
        }! n7 f* @4 E* v' i9 ?* e

9 K' c7 ~+ ^% T# F. c        // Volume setup- Q) `: ]# t8 B, z1 v+ R! a
        //  0:Master) \4 W" i* O& U  O
        //  1:Rectangle 1
6 V7 e) q4 _/ s0 u; m9 t! Z        //  2:Rectangle 28 j! m- e3 _. T5 O8 O
        //  3:Triangle
7 [3 {% h/ v) N5 N$ p. B3 G: Y        //  4:Noise
& p1 B" ?" Q5 G9 b        //  5:DPCM0 {/ ?5 v3 f0 L, H2 C: y
        //  6:VRC6
7 J! `0 y8 d2 R1 l        //  7:VRC75 V4 q. L2 I- H( B2 m, w
        //  8:FDS) x$ u/ \; o+ v& g+ X" d% h4 q. x, e
        //  9:MMC5$ O0 ~7 F" e' k- s
        // 10:N106
- w3 n/ S, J0 t) Z        // 11:FME7
, d, p% |! c4 q: k6 Q/ ^6 R        INT        vol[24];1 ^' m8 A, R, f" W9 X
        BOOL*        bMute = m_bMute;9 Z: O6 S+ H. k3 J0 G
        SHORT*        nVolume = Config.sound.nVolume;
! a9 y) ^, A2 s. }5 K. `
3 d5 c6 S6 z0 i        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
# J7 F9 h) p& X/ n2 t1 Y$ @0 ?0 I; Q( n$ C* I$ k+ D
        // Internal
0 E2 x5 `7 x1 l. g  T+ d        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;) }" D5 p7 X- k' A6 v" K  O+ N
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  C$ l+ _. r; @3 s: p( @
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 Y: G' b- M  W: c/ e5 Q+ W% w
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;( z" z; L, z1 Q# y9 M. I
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
1 e8 P6 c9 ?$ e: ^- K4 Y/ H) G+ R- [# T) V! a! P
        // VRC6
* `; l4 R$ [' W        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- @2 J0 [# j/ w" u$ ?        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  S3 i+ p( x$ s) \( M        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ H% l. ~1 ?* i5 w9 d1 t

  H  n. h! T  N        // VRC73 T. x* U, m& H. [% w
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;6 R/ O( b' x: x; `3 ~2 O, R; r
& D4 T- e3 f5 D# v
        // FDS
% y* B* P1 o( `- n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 J; c% }6 V" L! s1 k7 g6 ^, H& ^1 r& H
        // MMC5
0 F& j2 a. R3 y' Z( ^) n$ A9 y* D        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  W3 f1 p9 u. S( U* M9 K
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 {6 A# \. M$ ]        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* S' `( C. e  ]2 N# X, [1 M. C2 ^. k( m, h9 A. K! r
        // N106! \0 ^" t) ^7 [" K, r
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 ]2 @1 v+ T4 q5 k6 S; X! h
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* a; Q1 G$ G# Z6 ~
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 d+ g7 i( l' f3 |# V- Y
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. C+ O- h  Q) f' Z1 H        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 \6 ?# s6 T& `8 S1 ~        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 N/ L+ k6 Z# N& T  ]  k        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) M5 E8 G3 V& K, |( I        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 A) V$ \. f' n# Y( Z: `& L7 U& w9 ?6 c
        // FME74 O" j/ {' z' g2 D6 n: c6 d
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; n9 R6 F% v% y. @- Y( @        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 ~  Z6 D5 q7 x        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" A6 C3 w& B& |- n1 m/ r( J1 d
- u# X- w2 E, O& U4 T
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 u; [0 X9 M$ @& o0 [; k        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;, k2 o) `3 o' {( i6 R3 b# x8 j

7 @) V! K9 m# p0 a# p1 Q  b        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
+ a$ O+ [. ~- a        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# h9 g' M4 R) |1 b* ]
                QueueFlush();
+ M) l/ \& z  W( n1 Y! q        }
3 \: E6 }3 e' }
& R7 f9 F+ z3 R& N" F        while( dwLength-- ) {; X3 s% \8 G$ M& b# V( I
                writetime = (DWORD)elapsed_time;
5 b6 a, k7 K: G
5 S7 Z& i# {0 ?                while( GetQueue( writetime, q ) ) {5 x% [1 t7 r( B8 R3 T, Q) ^
                        WriteProcess( q.addr, q.data );
+ a0 k8 h" u) R  N" F4 n                }
3 v4 d* i* K- |) o0 e/ ?0 T! b& A* e3 q/ Y/ R4 c5 T
                while( GetExQueue( writetime, q ) ) {1 I1 f( }8 r7 b8 ~
                        WriteExProcess( q.addr, q.data );; Q" f" [) d% ?& z8 n$ t& H. I
                }
/ w* K3 b& C5 p  g$ [$ r9 N5 V, x$ _6 N
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
. g: d2 K( z2 q                output = 0;7 n/ T9 O# P( G* u: k5 A
                output += internal.Process( 0 )*vol[0];
; ?! l% J' ], E                output += internal.Process( 1 )*vol[1];' e! ?7 j2 }( U3 W- X
                output += internal.Process( 2 )*vol[2];
: F" T% K7 G  W0 g* A+ {                output += internal.Process( 3 )*vol[3];
: h) q: p5 }$ N0 o+ G                output += internal.Process( 4 )*vol[4];
+ O# l( j% i$ Z' Q
8 _: y2 E' M. V9 M% S                if( exsound_select & 0x01 ) {
; [. j( w* g; a9 k; B: A+ e. `- }                        output += vrc6.Process( 0 )*vol[5];' V/ j) p- s8 T  u$ S
                        output += vrc6.Process( 1 )*vol[6];$ l" u- b/ b8 x( D$ m  z& k. b
                        output += vrc6.Process( 2 )*vol[7];
- k3 }& c+ u) ]4 M/ |7 R( [( q" U                }
5 |$ s( q( w3 g. V8 B' k                if( exsound_select & 0x02 ) {
/ s6 B- @2 k0 g( A* w" {                        output += vrc7.Process( 0 )*vol[8];
3 w5 r8 @9 y& }/ G) u. k( n9 K                }
" y7 S' G' r" ?4 L& A2 X' k" `                if( exsound_select & 0x04 ) {% e  n& X2 X# ?  @
                        output += fds.Process( 0 )*vol[9];
: q/ h( w1 w* ]- S7 l0 k                }* C) M$ ^3 m) I( n2 R
                if( exsound_select & 0x08 ) {3 b! m- h- t8 l1 K3 v% u1 D
                        output += mmc5.Process( 0 )*vol[10];5 s4 M) I1 H$ o
                        output += mmc5.Process( 1 )*vol[11];7 @. K5 i5 {' J" y  I
                        output += mmc5.Process( 2 )*vol[12];
& i' K% V  L" b" t. U                }
8 j4 q3 h: X$ v- v                if( exsound_select & 0x10 ) {3 T; p! V  T  g1 [  `
                        output += n106.Process( 0 )*vol[13];
& Z, a) q1 x/ G' p! c+ j: k                        output += n106.Process( 1 )*vol[14];& L0 B8 {$ R# }6 j% s
                        output += n106.Process( 2 )*vol[15];) `9 d8 P( N. `4 y% W8 s6 H
                        output += n106.Process( 3 )*vol[16];
! h, n$ `; K8 u+ F- O! F" W* q                        output += n106.Process( 4 )*vol[17];
+ ^4 R1 o, U' J6 ~                        output += n106.Process( 5 )*vol[18];
' a: F0 n) G# O/ ?                        output += n106.Process( 6 )*vol[19];+ l7 g; ^9 v0 c4 E
                        output += n106.Process( 7 )*vol[20];/ B7 X9 [" ~; R% }! Z
                }
- M. l0 b5 F! m; ~0 j6 ~8 f) c                if( exsound_select & 0x20 ) {
$ R+ y8 y# G( o, f                        fme7.Process( 3 );        // Envelope & Noise
$ U) E- t, G: f% n* n2 _                        output += fme7.Process( 0 )*vol[21];
, O1 o# `9 D! O0 c# f6 {8 k                        output += fme7.Process( 1 )*vol[22];
+ ?3 J2 a) I' G                        output += fme7.Process( 2 )*vol[23];- c7 k( x7 W& k$ O6 b/ j) x
                }9 ~/ N4 A2 U+ A& w5 s1 [3 x% E

% C7 W5 h2 z% D4 F6 y& p                output >>= 8;
  S4 m* |0 z! N! x9 T7 S) ~* v
4 ?4 S, c- b. I                if( nFilterType == 1 ) {: i6 v+ I( J& O3 D  U
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& W: I; _$ q/ Q                        output = (lowpass_filter[0]+output)/2;
( K9 s0 C; y9 f* s7 m                        lowpass_filter[0] = output;
$ V" \3 p" @* C1 {2 d; o                } else if( nFilterType == 2 ) {
# @) e) C4 B! y5 W7 B* W                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
  f1 ^4 D* _/ _, X5 _: n                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
4 i; c, R4 }' x& R1 T                        lowpass_filter[1] = lowpass_filter[0];
9 J* x: N4 N) |" z, f0 P( n                        lowpass_filter[0] = output;
' R7 {* W* ?/ t" w# w+ h* l' m+ ^                } else if( nFilterType == 3 ) {
# f7 _/ F4 z. `1 u" O                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% D0 u; `, a4 Z; x4 _                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;: U9 ~: p& }+ ~' Z6 ~% [" }% U3 V- N
                        lowpass_filter[2] = lowpass_filter[1];
. k  O3 n" @" I, v! C. v) _                        lowpass_filter[1] = lowpass_filter[0];
/ H$ P7 E' u4 v' G                        lowpass_filter[0] = output;
7 s* J7 U2 N2 e, M' t0 v# Q& t                } else if( nFilterType == 4 ) {
' C& ?0 _+ F: l) P3 l( ]. q4 b                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
) v: s  R) R+ U" @" ?" o& Y                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
9 a! P9 @* B# T: O                        lowpass_filter[1] = lowpass_filter[0];$ Y% t  E2 N& Q& l8 `6 A
                        lowpass_filter[0] = output;$ q; t/ Y3 ]8 z! X1 D) }+ D" ?
                }! l- A5 k1 l; ^" Y# g

1 g1 }$ C& l$ H: u$ s' Y9 I1 O2 N#if        03 T; a8 j+ ]2 U9 d: H9 _! T* h) c
                // DC惉暘偺僇僢僩8 r& O7 T9 P# G& D& P- d8 c: |
                {, Q7 s7 U$ N: C5 k3 D# I+ x
                static double ave = 0.0, max=0.0, min=0.0;% m" s8 p# w. w9 l" A7 A
                double delta;
  t* k3 O6 C3 M# |  m                delta = (max-min)/32768.0;
5 `" o8 D" p: M# X1 R3 G$ P! q                max -= delta;
- a# _8 ~8 a/ [( v5 ^3 E                min += delta;0 j8 Q8 N( v  `  B( X7 f1 ?, V( ^
                if( output > max ) max = output;
8 m. q0 l; ^# `/ _( U0 m! I" I7 `                if( output < min ) min = output;7 h/ B: s1 P0 n& I% h8 C) Q
                ave -= ave/1024.0;
5 B0 J7 M( K9 x% z2 i2 H% _  M) Y                ave += (max+min)/2048.0;
1 [. ]- W% A# O; ^5 f, r! o                output -= (INT)ave;
$ U# d. x# o: Y9 S( o                }  w' [, c. g& L! i: O5 ?9 }. B
#endif0 S- o; |: O, ^" Y6 N
#if        1
- n9 e4 }  G2 N. k) ~+ o                // DC惉暘偺僇僢僩(HPF TEST)- U; U) ?' G3 r; M  X% p0 Q
                {
& ^+ U( z5 A$ f, {3 X//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);5 w9 {  @3 y! W1 ]' C+ Q' A0 P6 ~
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
5 c/ J0 o# H$ {0 U( {% {2 I4 E                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 M2 A# y! ~/ f1 z; C' g9 m
                static        double        tmp = 0.0;1 E0 M& S% M: E$ p, x
                double        in, out;
: v' b. g9 P- b' I% o: S' R1 P0 x5 a+ L. E* m; c* v
                in = (double)output;9 v# K: u! i' D$ s' t
                out = (in - tmp);4 P) ^1 M! g$ K, G! Q0 I- N& Y, q+ N
                tmp = tmp + cutoff * out;
' V& K, ~: t) j- C* a4 y6 d6 J
9 `: f9 z7 p2 h! ?5 Y                output = (INT)out;- E* h5 @+ j9 j1 k) T# k
                }7 _# u/ p/ _2 l- l. C7 f
#endif
: m+ \! @0 b" [7 K5 d#if        0+ R! w' F, z% L8 y* m+ {
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
8 V% u/ `/ I! U% |& Z+ U- J# S- ?( N  y6 `                {
3 [9 |, t& d5 s7 ^4 Q                INT        diff = abs(output-last_data);! ]% N2 P# i* N. v; |/ j
                if( diff > 0x4000 ) {
2 f9 d  h, p3 f9 k+ [                        output /= 4;
* ?: ]/ {6 s4 R0 @! k# E  ]& x7 T9 w                } else / c& ]' k; p8 Z, }" s
                if( diff > 0x3000 ) {
4 J' }# }1 N4 Q# t" \                        output /= 3;
$ d; ^; B. O8 c) w/ }                } else
9 P8 h- ^+ X- s4 B" V  Y                if( diff > 0x2000 ) {' S$ H. v. Z1 q: ]$ ^) E& }% `7 v" ~& x
                        output /= 2;
" a/ E0 T$ _) i9 p4 c* k                }/ c2 Y6 ?1 _' v
                last_data = output;
$ z) J4 R; w% ?2 ~) G                }# Z. k/ C: @' L9 F
#endif
5 c% ]5 h' U8 R& |                // Limit
0 R3 _/ m2 t" Y6 S$ {- Y7 w                if( output > 0x7FFF ) {0 S+ F! t7 D0 U/ V) o
                        output = 0x7FFF;
* n* y( s6 A' b1 O+ N; j" M& @                } else if( output < -0x8000 ) {# _' d& n+ q3 H+ K# h4 N5 I
                        output = -0x8000;
/ m+ C3 v/ U( Q% i( N; B9 L                }9 @7 G+ t. R$ c2 d& j1 k% e
! F3 Y* l) p! q
                if( nBits != 8 ) {
! L8 N- d5 c* z' b0 k                        *(SHORT*)lpBuffer = (SHORT)output;
; h2 V9 d) M) l1 T& b# ]                        lpBuffer += sizeof(SHORT);" r5 v9 B  T3 b$ f8 b6 t; S
                } else {/ O* G2 a! g" s* y( s9 l
                        *lpBuffer++ = (output>>8)^0x80;
- u0 |& A8 I. u0 Y                }
/ u, |9 C" g  W0 N  X, f: v0 Q4 e: e# Z/ x
                if( nCcount < 0x0100 )0 v6 @: {/ ^) D1 W1 Q
                        pSoundBuf[nCcount++] = (SHORT)output;
6 \5 @2 U2 s( A# D/ L; X' n7 c1 c6 U3 ?% T* H% ]# r
//                elapsedtime += cycle_rate;5 }* z* n% ^. e/ T2 Z/ s
                elapsed_time += cycle_rate;+ d4 V1 G! F) ~. u5 G, H
        }7 ^6 B. f/ i8 m1 T  a- f& k

) [1 {6 L8 j* }% ^# v0 E2 `#if        11 t) X9 A( I1 t  |$ O) T% V0 M7 I
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 I1 W" s1 n) ~& x! S* f; @                elapsed_time = nes->cpu->GetTotalCycles();& Y$ O% w  H3 e# L6 y9 F* c
        }
% S5 J2 X% I0 B        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 [( u' c3 c, M0 W" h
                elapsed_time = nes->cpu->GetTotalCycles();3 H$ |( l5 z1 m2 T, S: n2 b/ d
        }
" W4 w4 u6 B) J6 ^# f: d#else
) i& x) a  z8 s2 k% k2 D        elapsed_time = nes->cpu->GetTotalCycles();% X  V* d+ r6 j- [
#endif
* a2 \  `* O+ n2 y}
$ ~9 W( v+ @1 z8 T" m+ ^( S
$ x" S: P( h( j1 @' B( ?// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* s( |& M8 }9 @* p2 {2 @
INT        APU::GetChannelFrequency( INT no )
0 ?9 Z) o( U7 R" s/ z1 C{* ^% ^1 V* r. y7 Q3 ?5 `/ q; j
        if( !m_bMute[0] )
' Z) D; n  y/ [                return        0;: S1 K) I1 f  n# o# u  t

$ j# l- @9 g  o7 K, F        // Internal9 i* ~% Y* _9 o1 f/ h3 x2 i
        if( no < 5 ) {
& c, x+ F- E0 h- n                return        m_bMute[no+1]?internal.GetFreq( no ):0;
" a' s0 r4 C9 O, D3 e        }
  n4 N4 m- D9 V        // VRC6
4 k/ }9 P. t/ ^        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
6 _* S, J5 `/ a, j4 R  v7 ?                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;0 X% W% C( `" a' G  d6 q& i8 [
        }
6 j* A% ?+ s$ {! ?        // FDS: J0 }0 }$ R8 y8 ^- t
        if( (exsound_select & 0x04) && no == 0x300 ) {
, R; S7 e# r) q* L3 X" O                return        m_bMute[6]?fds.GetFreq( 0 ):0;
. G1 n5 l4 O1 S9 _" ~! G, _% D        }
' y" C% Y2 h4 z        // MMC57 }4 B$ q9 X- Z- ^
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {- ~$ @3 e  L/ ~& m/ Y
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  U9 }  F  r) I, i" m3 F, U9 b( N$ g
        }
8 X7 E+ z$ P8 v  j3 R  l7 u  z        // N106& r7 z7 y' d' a' ~( s
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
5 g  ]+ s7 K( U                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
8 L- U- s/ @% H& U' E7 m. j        }' [/ ]" z( b2 b
        // FME7
3 r+ _9 [" G4 D% V" e, t2 y        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% l) X4 o9 U6 M) K# N: ^
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 x  ]# _5 M* U+ u: e# s& h        }
: N, L/ P: d. x0 i2 r6 q" e$ S        // VRC71 P0 I: h5 N' ~
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {& Z/ R; ]0 ?" n/ Y
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;) D  ?- e$ P1 I1 o) c6 P; Z9 [
        }/ C( D$ }$ R4 |; Y7 [3 ~  C# `9 N
        return        0;/ ~" ^1 B* g! p- N9 Q% S
}5 w( b2 [  [; u8 ]  O6 C2 j& i
! V: Z4 h- C2 B
// State Save/Load$ H4 }; {9 Y* p1 k; S' B+ R. w
void        APU::SaveState( LPBYTE p )3 S" `* E8 G1 |& G
{! s( Q) s6 ]$ L% c( V" ?/ s+ `
#ifdef        _DEBUG
& G1 q3 n8 E5 t$ \8 JLPBYTE        pold = p;
2 c7 `6 m. A; @4 l#endif
; S3 `8 u, |1 {( `$ ^' S7 g7 X# y' e, M9 V8 t( W  q; s: D; _
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞* ^6 H+ P& I% [3 T
        QueueFlush();' V' n) U  }0 H3 m$ _5 x4 v) S

1 a0 F3 e3 l9 O4 j& o+ V        internal.SaveState( p );  v* S! z$ e9 K8 K1 W- E
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
$ \5 I* X  {: N% k) v9 x; n. ]7 k/ a5 }, D
        // VRC6
% T" P4 {6 B+ k/ d  i1 K) G  O- J        if( exsound_select & 0x01 ) {* ?" s) P( N4 ~9 a: q. V- g
                vrc6.SaveState( p );' `% N3 p4 s0 D
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; q6 @/ m! K7 {$ \  l, j
        }
' R, s% B/ `) ?5 `        // VRC7 (not support)4 x! C  l- T# `! W% m* ~( h5 t( G, V
        if( exsound_select & 0x02 ) {+ h3 ~( N5 S0 j9 t' T7 B% B  Y
                vrc7.SaveState( p );% ^! p' ]9 J6 L& m6 D
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* O0 F) ^$ J0 M5 r
        }! ^/ O* \8 d% \# C' W
        // FDS
/ @0 K- B- j5 C) y$ Y6 N        if( exsound_select & 0x04 ) {
) }% o/ i. d8 J9 _                fds.SaveState( p );
  ?5 {; h1 T9 h$ Z) h! L7 v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 X1 z/ s) Y/ x
        }
4 r9 V8 o% i4 }' A% E0 t6 ^& y        // MMC5; d( O) F6 ?/ q. X" z
        if( exsound_select & 0x08 ) {
- y+ p% A, Q  d% b# z) ^4 V                mmc5.SaveState( p );* m3 M0 }- f: b# O' }7 t. F
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; T/ x+ h0 ~2 m7 j6 j        }* d2 p+ ?; f" b9 m3 m
        // N1068 v7 K, f; b& G4 h9 ~2 n/ y
        if( exsound_select & 0x10 ) {9 R1 ?* i$ g  v. c1 J, Q, m$ R! u
                n106.SaveState( p );, p9 F" z: P% i6 p( x: u
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) ^8 L5 A1 H1 i: G- U7 [& Z/ g
        }
; }" T3 z9 ~# `0 b7 l. E1 A6 y        // FME7% B; s$ T9 m# W% _
        if( exsound_select & 0x20 ) {
& ?4 d& X- R4 X% @# U6 q                fme7.SaveState( p );
  v4 W8 D) |' m( p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 z% L2 u. z7 h' ~
        }/ ^! P) P) F- u, Q: p% L9 F0 ^/ ~
; ^1 R: T/ t8 D+ ~' F/ ]+ A5 P! V
#ifdef        _DEBUG- B, Q1 d6 ]. O$ m7 q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 A! D7 L. E6 V( [: x# f
#endif
8 L: O$ c3 L7 o0 m$ \, g; B3 U, J}
. p- p" z- H6 P/ G* Y" b  i" F# b; W5 h
void        APU::LoadState( LPBYTE p )2 T1 X7 g7 h3 l; n! u
{
; }) T; g9 @2 P9 L9 q; R        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ O" h* |; Q/ P1 R3 x& O
        QueueClear();
3 n3 ^+ U1 P; s- R3 C
( z$ |) z1 d: V) |6 t        internal.LoadState( p );
+ o3 |1 `" g2 `; n1 i9 ^: l* e        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding2 ]) Z, C- G" c

& a: \) I# _' H# V) M4 v        // VRC61 I  N$ F2 Q3 L, ^. c6 T
        if( exsound_select & 0x01 ) {
# [( D" _, P8 r- ~" T& m                vrc6.LoadState( p );
( d- F. W2 X+ U# p2 X& _* s& Q                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 e/ J; s0 p* q0 S        }0 k7 S* r9 S$ P+ L7 f- L
        // VRC7 (not support)# x- N# @! I$ U% ^9 }
        if( exsound_select & 0x02 ) {, }$ {2 B/ W  l( U( K% @! Q& n* [
                vrc7.LoadState( p );
9 S8 d" N6 s) T6 ?. N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
0 d) F0 Q( @3 n( O        }0 S& x  L- G! V7 g0 h% v
        // FDS
; T% |# ~5 P" a+ ?5 P        if( exsound_select & 0x04 ) {' p1 v$ f8 m! O
                fds.LoadState( p );! W9 b+ i4 g& f/ J& e6 \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, D* ^" \1 E2 O: j+ s8 h        }
3 ~) Z8 N9 M7 H3 A, b. R: _        // MMC5
4 n! f' a& G* k; k' ?$ T        if( exsound_select & 0x08 ) {! a1 P& R7 }" C  M  d
                mmc5.LoadState( p );/ t  J+ _8 y& k
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 z) u6 Y; L) \# c  q
        }
. L4 \+ }- M2 b! a. V        // N106/ S! ~  T* G. `0 p7 \
        if( exsound_select & 0x10 ) {2 h, X  T: R$ n
                n106.LoadState( p );
1 J9 M1 X/ s3 W; c. N3 D                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 l. X4 P* I/ m- e        }" K) s$ ~, l& O6 }* V7 \" o6 g
        // FME73 n3 M/ ]1 X7 I$ Q
        if( exsound_select & 0x20 ) {
5 L3 F0 |' s1 ?9 T; l6 e  g                fme7.LoadState( p );
6 r' T0 P. ^) K                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 c7 _3 t/ F6 E& K9 K5 K' h        }% V' E( R2 ]4 T* [+ c1 j( O
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
! c% C! P2 x6 v9 g可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
* W/ u) r' q- s2 S3 p$ u' N感激不尽~~
( G4 ~7 N; E$ v5 K' K5 h
恩 我對模擬器不是很有研究,% B8 e+ E6 w9 L5 g' n% u% X1 l
雖然要了解源碼內容,可能不是很困難,
' u$ S- v# r( S( {2 Z: ]/ Q1 w不過還是要花時間,個人目前蠻忙碌的。
( J4 D1 N/ q: g' a1 J! k! f2 F' C/ ?; A
給你一個朋友的MSN,你可以跟他討論看看,
# J, H+ b; Z( E& z' _他本身是程式設計師,也對FC模擬器很有興趣。; u+ g- U/ A* r( R. H& V
3 I  r! O# \0 ?3 R  E- A* W1 m) C
MSN我就PM到你的信箱了。9 ?6 l- L. @  T; T+ ]
$ P/ {! r. p8 p
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# w0 [! b' N, N# E4 O呵…… 谢过团长大人~~

1 x7 o  J# \( \; T( r8 ?4 u8 J% P! L, b% [( Q* [8 L' _
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 8 ~, f% d5 h; L- b7 E; m
团长的朋友都是神,那团长就是神的boss。

1 ^* s3 p& {9 B% h' s6 W2 b5 {哈 不敢當,我只是個平凡人,
+ `1 ]0 q0 G; W5 b2 j要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙- k$ f  J, C6 u! |; p2 I
ZYH
/ @/ X0 v/ n9 v! }) `QQ:414734306/ D, @* C6 I& u- S5 j
Mail:zyh-01@126.com5 u, ]0 r' m5 S2 x0 a+ b; M% Y

' d, n! `! Q" P他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 - i2 {' C3 X6 t/ R0 f* W7 p
再次对团长大人和悠悠哥的无私帮助表示感谢~~

6 C/ F, a0 G8 b# R" W不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-17 16:03 , Processed in 1.091797 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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