EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。/ `; N& H+ C* k1 \
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% \- [! h8 Z+ p- }这里有相应的模拟器源码,就当送给大侠了~~5 M% i% i! r) P' x. t
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
! T& X5 s& U' Q( Q& p! M3 c+ t能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) [) y! J% m" R, f/ g: l楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- G6 _) ^8 P0 r  \& U4 \
这里有相应的模拟器源码,就当送给大侠 ...
9 X! C  E3 M0 u) V* h( T0 x; M, X
聲音部分(Audoi Process Unit = APU):
% L5 J0 R. C8 |* V& C.\NES\APU.cpp
" P! ^4 @. H1 a* R.\NES\APU.h
* D( }' {" k, x- n/ e4 g; }* z, `( F6 v- A* X0 M; s. u9 R$ U. s
- g8 z6 @2 v: w9 t
影像處理部份(Picture Processing Unit = PPU):4 X7 x  I% k+ c9 H/ ^& |; }
.\NES\PPU.cpp
& Y" `7 t6 a" U& I.\NES\PPU.h7 n! t: u  M. Y* R1 Z/ j9 y* M- I
5 ]: ^! p2 u( h* E0 S8 r: _) m
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 X' O" S) h+ g! `! y1 x5 V! o" b感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:" h& }' [7 E; P8 b& L; N5 Z
(由于很多专用术语和算法机理都不明白,所以看不大懂……)/ c. o7 ?5 s( g2 L+ g# b2 O8 ]
//////////////////////////////////////////////////////////////////////////
4 p7 R$ L0 ~6 F; G# j$ Y5 B//                                                                      //* J, f5 s: [( c: S( e
//      NES APU core                                                    //. k9 r5 F5 V, L! l6 a# I
//                                                           Norix      //! z7 U6 G0 e/ @/ R7 E5 V/ z
//                                               written     2002/06/27 //
; w0 v3 l! x, p: v//                                               last modify ----/--/-- //
/ P& E' T+ O- T  w+ m//////////////////////////////////////////////////////////////////////////
; b& I; G/ O" Q; \0 Z; a3 y#include "DebugOut.h"
) m; C( _1 a  J% G) O4 G1 m% z% o#include "App.h"8 `  g1 k, c0 _+ j8 @
#include "Config.h"
3 n0 |3 J, p# [8 {' w( M$ g/ s) K( [. ~1 C" x
#include "nes.h"6 |/ k4 V0 G9 B  M- o8 V5 m+ ?1 X
#include "mmu.h"
4 y, O4 Y+ s) @#include "cpu.h"
. k: Y$ K' t" {  R2 y! Z#include "ppu.h"9 P7 F. W8 ^% d8 M: C
#include "rom.h"' r/ Z2 `4 l; }5 m
#include "apu.h"
2 C; E" F% Y* `1 x# M% L- ~# `4 v2 m, g( _" C; p5 K# y
// Volume adjust9 C* ~* {- `7 `! Y& o- C! f
// Internal sounds
# ~/ c( c) z! M( w4 p9 r; a0 i. e& I#define        RECTANGLE_VOL        (0x0F0)1 ]5 ~7 J, b; g
#define        TRIANGLE_VOL        (0x130)
  ?( }" \% _6 A, B: v#define        NOISE_VOL        (0x0C0)
; v8 x) k6 A) n. j#define        DPCM_VOL        (0x0F0)
' K" p$ b9 N5 ~) ^% W// Extra sounds
; M# H, n" G6 l, V% V! |* I7 P#define        VRC6_VOL        (0x0F0)" d1 n* h8 K% M# F8 t7 \8 p( V4 J
#define        VRC7_VOL        (0x130)
9 E. n7 x) ?2 _5 ]+ t#define        FDS_VOL                (0x0F0)
+ f, J$ Z# V: Y- T5 r: c#define        MMC5_VOL        (0x0F0)) S( R( k4 ], {0 c+ b" p
#define        N106_VOL        (0x088)
# D, o: n9 p+ s#define        FME7_VOL        (0x130)
$ _0 F0 d6 c. N& P* V. R6 d5 p0 ^3 r1 {, I6 D8 e
APU::APU( NES* parent ); m' }: g: T  l1 X( \
{: c- p! D: r. E& S0 R# X
        exsound_select = 0;% B+ O% H: e1 l! o* Y. p. u
0 U7 R  V! C' F) K$ n) g% a8 n
        nes = parent;
1 ~( k# Y' Q6 N) b& X) J9 t5 g        internal.SetParent( parent );
- R5 Q5 n# q# c8 f* g) z( @% I/ o* E
        last_data = last_diff = 0;" O8 q# n2 K' v; Q, {( {6 u

( r! _; S- V. T9 ?: G, v        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
( J  u# q3 r6 t  `; c& u" s3 E+ ^& c' f! M4 ?3 Z
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
1 C5 R* y% ^+ u" D$ _, Q8 `  Y        ZEROMEMORY( &queue, sizeof(queue) );
% J- {3 V$ \2 H* m& \' T        ZEROMEMORY( &exqueue, sizeof(exqueue) );( }% L3 E! M4 @0 n$ N
: ^( V0 Q0 G' L7 i& j: F3 m
        for( INT i = 0; i < 16; i++ ) {
$ r: e7 a5 s: T3 k6 `6 `" M                m_bMute = TRUE;
! b9 Z8 V5 G0 i( ?) M        }$ v' M7 R7 z" `( x
}
6 W/ V7 P2 b$ \( `6 {. _9 L/ a3 N) |4 `6 ?- c$ f
APU::~APU(): _: N. ^) F9 Z8 z& O+ _
{0 r, i/ w! l' w9 m; v
}( V* @9 Q- V& X  e

; n( G$ T; q! g& ]1 N9 ~4 I6 Nvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )! ~7 W2 Z8 h0 O) p% ^$ C( t# ?7 T! e
{* Q$ k* @* [& p  [: X5 e
        queue.data[queue.wrptr].time = writetime;. T6 j! m0 q7 W" }, y
        queue.data[queue.wrptr].addr = addr;- L; T7 q6 [: t
        queue.data[queue.wrptr].data = data;
7 S7 p# D" l$ y$ n        queue.wrptr++;
! U9 n4 Z! A$ n8 b+ Y+ Q: s0 w% i        queue.wrptr&=QUEUE_LENGTH-1;
1 U3 Y+ j+ B1 H- L- U        if( queue.wrptr == queue.rdptr ) {! T. R% l1 ^8 H8 F
                DEBUGOUT( "queue overflow.\n" );% F0 |' W) ^- b& R" f3 o
        }
/ Q3 j, [" q$ E0 C& A}
$ p: M7 x: v3 x0 c3 O' k* j8 a/ Z! u- C2 B7 h+ Q
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )3 D8 g5 z9 }" `$ A1 t
{
% C4 a# Y1 ^& T5 {. J3 ]% f        if( queue.wrptr == queue.rdptr ) {
: Q4 w; g0 F9 g7 u# `                return        FALSE;
1 Y9 `3 n- n) y1 _# o) o9 g        }. ]( `' K3 g: q, H5 ~* M; @
        if( queue.data[queue.rdptr].time <= writetime ) {* s2 H$ \2 }% w* H0 t/ h
                ret = queue.data[queue.rdptr];
9 c" I4 U: ~. @; g8 ~5 r! P: @                queue.rdptr++;! I% c/ R5 n9 A& z
                queue.rdptr&=QUEUE_LENGTH-1;
3 s) P9 {: N( `" S+ X0 P                return        TRUE;* @1 x) o1 @2 m: _! [
        }7 H! A1 }* k% J% a
        return        FALSE;
, Q, m& Y! m  R7 j# Y7 Y}
: m2 W. m) |9 U+ |1 w- v5 b  [% U8 D# y% ]6 F
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ ~- f8 T# x  O; g$ ?
{
5 ]9 ~* t. c) G$ x        exqueue.data[exqueue.wrptr].time = writetime;" Z4 \( ?0 A$ H' M7 B/ @5 M! r9 e
        exqueue.data[exqueue.wrptr].addr = addr;. G& F; Q1 ]8 o  u$ p
        exqueue.data[exqueue.wrptr].data = data;/ P- X2 j9 r" J( v
        exqueue.wrptr++;5 v7 R* @9 t# w. @+ X' J$ R5 u
        exqueue.wrptr&=QUEUE_LENGTH-1;; `! q4 e; e4 z' B# J
        if( exqueue.wrptr == exqueue.rdptr ) {
' C- o, G5 N8 ~4 f                DEBUGOUT( "exqueue overflow.\n" );2 p" u8 M6 b& Z+ e: J8 B
        }" {1 {& W, J3 x2 K; _/ i5 e# R$ B
}( {$ G) q) q4 K- g; H
. C0 i, G* p) c; ^# k+ b
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* U3 t' b6 I. Y3 q+ @9 P" _1 x8 r. U! H
{
# i' Q! o# i: a        if( exqueue.wrptr == exqueue.rdptr ) {4 J+ R6 t1 K  b3 X% m
                return        FALSE;% m5 q% l& `" M9 Y  ^
        }6 T5 r8 [9 H  x4 n- `: X- P
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
- e' Y6 b( ]& q- c                ret = exqueue.data[exqueue.rdptr];; \' T/ G4 P) E- |
                exqueue.rdptr++;
6 J& j: q* T! i( j" P  u/ d) @1 z                exqueue.rdptr&=QUEUE_LENGTH-1;
9 R' t, K0 P5 U                return        TRUE;3 w% m! K, D+ R( ^- @6 s: g; x2 E
        }
9 M* k2 f, u% M5 F  d        return        FALSE;
% S- e! x* Z; k  E; p% j6 b) T}
9 v& ?+ O" p+ H3 b8 m, D  c9 g+ k% T3 W
void        APU::QueueClear()9 n! c; a$ N# c! b" B8 }) B7 \, D
{
# n0 ]3 a/ k. B" n        ZEROMEMORY( &queue, sizeof(queue) );: X( u2 n" `7 y- c# `
        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ B: t+ ~# q* U6 T/ \  B
}
. b3 w; T9 J* X
2 X7 S) H- Z  b" B& W5 t* x" mvoid        APU::QueueFlush()
8 m# Y5 i; X" D# @0 v" q8 a0 ~, R0 @{
* p/ Y+ h, ~+ q. @) x9 H. ^7 ~) e        while( queue.wrptr != queue.rdptr ) {
3 ~! L. L  G* _% I                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) O- K* X" m; @
                queue.rdptr++;
  q/ c9 I# M$ [5 k                queue.rdptr&=QUEUE_LENGTH-1;
" x" W) X1 D8 b. E! o        }
* v& J3 |1 c1 E3 \5 s$ W
, l7 f: u" q+ B0 J5 w; y% A        while( exqueue.wrptr != exqueue.rdptr ) {
) d) U$ W+ d. l( k                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 F# z% z. q) G  n
                exqueue.rdptr++;1 ~+ ~1 n' }5 A2 O* H
                exqueue.rdptr&=QUEUE_LENGTH-1;/ b8 A7 \3 o. R
        }
7 j! d' B3 X" T2 a% V2 I+ O}
* Q( p' J, {# u% i: W/ g4 r* B2 u$ B* s% X: V, [
void        APU::SoundSetup()& u5 _5 b9 w; C* e1 N3 E! U
{
8 |( y% i! L, U' H! }        FLOAT        fClock = nes->nescfg->CpuClock;- i8 ~7 t% H8 Q+ k9 C! g( i
        INT        nRate = (INT)Config.sound.nRate;! f: J' ]. A- Q# V& m* v; j
        internal.Setup( fClock, nRate );
9 k8 t9 t1 b/ v( R        vrc6.Setup( fClock, nRate );
* t" Z' B3 i* o5 _7 D        vrc7.Setup( fClock, nRate );
/ }1 x( C- S0 K# a4 ], x4 U$ [5 l( _        mmc5.Setup( fClock, nRate );6 b$ k4 w3 }/ V$ X0 {/ z7 B7 o2 A
        fds.Setup ( fClock, nRate );% f2 `/ V4 G7 J( z, N( y
        n106.Setup( fClock, nRate );" f" b6 E0 }, K% b/ K& ~% h
        fme7.Setup( fClock, nRate );7 G! c  ~8 `; i, x, T+ F% f
}
! P" h: u/ f$ z% H: e
* C- ]6 X* }. Ovoid        APU::Reset()
3 ?! L4 [5 {6 j{/ U7 }* Y$ v2 H+ P4 L6 H; E) b& {
        ZEROMEMORY( &queue, sizeof(queue) );
4 q% s/ F" N  q* I" {4 Q/ L$ E        ZEROMEMORY( &exqueue, sizeof(exqueue) );: N* m5 ?2 Z" Q9 d7 Z

* Z9 U- f% {" o5 H+ p  C" k' M        elapsed_time = 0;0 j3 j& F2 x4 V5 T) M9 Y& h
0 z( R* O) [+ d
        FLOAT        fClock = nes->nescfg->CpuClock;
  t; ?7 h% y, }% l) W; Q; r" x) V        INT        nRate = (INT)Config.sound.nRate;
7 P; X( n# d* `* U3 O" Y+ a        internal.Reset( fClock, nRate );1 {% x( z  R  b  m' s
        vrc6.Reset( fClock, nRate );2 y/ K( e$ s( [7 O6 B5 c, M: a
        vrc7.Reset( fClock, nRate );8 S, |" K1 z# `9 f5 W! ^3 q
        mmc5.Reset( fClock, nRate );
( [& f5 A0 I2 t; L: T; G+ P" {        fds.Reset ( fClock, nRate );
! {+ u8 r9 L) q4 ^' v5 H& K        n106.Reset( fClock, nRate );
+ A* O8 W- Y! I* d5 w& z        fme7.Reset( fClock, nRate );
* C* `) ^) i6 Y4 p5 _) S9 S' ~. t  d) f
        SoundSetup();7 I' [) [' x; i+ w3 m
}
9 y7 }+ Y8 o$ G8 ?& ^2 B; \
+ \8 Z5 X* F% h2 Pvoid        APU::SelectExSound( BYTE data ). P' O" [4 b- d
{- Q3 T, U+ g! w. }1 Q! M
        exsound_select = data;% Q' s* F0 R+ x3 f
}
" A4 i2 h! ^' Y* i, A" l5 b; @: `7 Q) C
BYTE        APU::Read( WORD addr )
6 i' G; d* m4 U{" U4 O3 P9 S; T
        return        internal.SyncRead( addr );
! R# c" [2 `( B7 r}) {$ T. K: x+ h. r, ?

3 j$ `7 a" t9 F* c  o* Avoid        APU::Write( WORD addr, BYTE data )! S& M+ q7 E- r3 ?
{9 g0 l  Q7 z0 c; ?' w- z4 M
        // $4018偼VirtuaNES屌桳億乕僩
$ y: ~6 m2 R) |3 g7 A9 ?        if( addr >= 0x4000 && addr <= 0x401F ) {
+ P% V  E! U; [" V6 y                internal.SyncWrite( addr, data );
7 R6 g# W4 c  G2 D, Z6 j7 `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 ~- Y& r, w& O9 s  B4 R
        }
  z: H. `; d2 v}/ l% I6 @$ K2 m& e
9 a: Q9 e1 X; t1 g
BYTE        APU::ExRead( WORD addr )
7 n8 G2 c2 C% B& a{" i5 R7 G- O6 ~% X
BYTE        data = 0;4 S4 ^/ n& s5 [1 d( o

  Y0 E8 V8 m, ]3 P9 I" Y8 Z        if( exsound_select & 0x10 ) {
  G( r1 D$ R% J/ l5 k0 d                if( addr == 0x4800 ) {
6 P$ T! k. Z0 c' J0 J                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: t# u& J) R3 u6 o9 U5 b* g' ~- V
                }
0 ?; j+ @# e! b9 b, w& g" ~        }8 r7 l2 m; U+ x5 I
        if( exsound_select & 0x04 ) {+ C4 n+ n. B7 M# }+ T( |& L
                if( addr >= 0x4040 && addr < 0x4100 ) {' \$ [5 x: z% n- h- N0 c! ^5 `
                        data = fds.SyncRead( addr );4 d& ^8 J) O* I$ r9 L) _5 I
                }2 m( A3 K" @$ n7 C9 T& t; I* H
        }7 G- g4 y! _9 b$ P# a
        if( exsound_select & 0x08 ) {6 T" _0 B5 r/ D6 x" P1 F
                if( addr >= 0x5000 && addr <= 0x5015 ) {  K% v8 B' w6 ]1 `4 Z& F6 O4 m
                        data = mmc5.SyncRead( addr );
- F/ i+ `' O1 c2 p/ u                }* A  i. i4 m) `3 \4 R7 |
        }' f* `+ ?: W3 N  A
5 E: `( f' T  Y0 T6 A2 E( U) t+ u
        return        data;$ W8 S) n7 ]) j; a: Y, y# }
}% R% \( a  N4 V$ J

' w) t& ^  ^. F# m* g6 gvoid        APU::ExWrite( WORD addr, BYTE data )
! g5 T) y+ m1 Y' G# p, S* X$ D$ K{
* l, g0 {: h1 [4 \; j% T1 Z6 {        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
) z; K5 K& ^/ l* U9 N5 g4 w: M
. c( ]- E7 W$ u/ w% O7 n& A        if( exsound_select & 0x04 ) {
+ _5 x! m" u4 I' j0 L5 D7 O4 t                if( addr >= 0x4040 && addr < 0x4100 ) {
5 Z  U0 _( K) G3 U                        fds.SyncWrite( addr, data );
6 G! l( ?3 S) C: |# l% E" h+ ~0 w                }" J1 h* q3 p, P8 Q$ R
        }0 v2 r) ~* d8 D, A* I3 H

" g! a+ Q" W+ g3 U7 x        if( exsound_select & 0x08 ) {
9 P5 N8 k% }1 \+ v; D                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 N( ?% o5 x) j3 M% f* r3 x( u                        mmc5.SyncWrite( addr, data );
( X& G+ l* c& @- `3 P! t                }
; o8 Y% i! m2 a        }
# \- J) n3 J1 g0 r}
5 r& F/ x! i2 }  ^/ c) ]6 B5 S# y* m; E: k* j+ |
void        APU::Sync()0 O  c* _! c" ?! o6 n: b  T
{
$ G' l$ k6 B0 i1 ]* A3 v' g% K}, p8 t" S+ }' m3 L  |9 a

3 U. z& e, j! hvoid        APU::SyncDPCM( INT cycles )" h: D# I- x7 y, e2 B! {1 j! k
{2 v1 g$ A7 _& _; ?+ _; G
        internal.Sync( cycles );! t' K' l( K" `# t% T0 B/ p1 S

3 b: A1 s  E" d: B7 K& f        if( exsound_select & 0x04 ) {
% O4 v1 R; t4 T  \; s                fds.Sync( cycles );
, a7 y* D5 `2 J9 B) K- F5 \0 i" I        }
- X9 x0 n$ y0 J! e) f        if( exsound_select & 0x08 ) {. J) {8 L6 j5 i
                mmc5.Sync( cycles );
2 }; n- D4 k; o# j        }
# W0 K1 m/ V% ]1 v}& `( C0 U% u* y. h) g0 P8 Z/ S
, K* z/ L& p! l! g, v8 j, N
void        APU::WriteProcess( WORD addr, BYTE data )7 h# ]+ p4 H( L& J
{0 s" Z, }# W* B5 y* D
        // $4018偼VirtuaNES屌桳億乕僩
  ]# K! `2 ~0 r; o; v% H        if( addr >= 0x4000 && addr <= 0x401F ) {- j+ c: S, u* V. w4 c; E  n
                internal.Write( addr, data );
  G0 s' v; O6 W* v( s        }" g( A% R/ p3 w: E8 @1 s; A$ s
}' p4 Y  C$ o6 @. \# s2 s
6 P/ V) k8 _" z3 z! i2 f3 T
void        APU::WriteExProcess( WORD addr, BYTE data )
# K3 F* u  K# A* n{
* r; M2 H& X  w0 u# d1 |, Y. ]1 w5 y        if( exsound_select & 0x01 ) {
2 U6 y0 @; p3 O, x) T$ F* J. `                vrc6.Write( addr, data );
# K4 I  |5 n3 L        }
) w- b" H4 |/ n        if( exsound_select & 0x02 ) {& r( ^" W# _: S2 h7 i6 ^
                vrc7.Write( addr, data );
+ c9 D, N+ \  F: g- H; M        }" Y) y/ G+ X; B! n6 p
        if( exsound_select & 0x04 ) {
" b" x: ]$ a2 f1 {( O3 S                fds.Write( addr, data );! g+ n6 p5 k8 ], P! \
        }
+ ~' [' g; o& }- A$ F0 \        if( exsound_select & 0x08 ) {! X, @9 i& a$ [. a/ P
                mmc5.Write( addr, data );+ q' O6 {7 ?. s5 I& S1 Q# s
        }
" p/ F. g& S! Q# L: h7 s: x        if( exsound_select & 0x10 ) {( ^, z- X8 E& }8 k: E( k( C
                if( addr == 0x0000 ) {  Q  @7 f( B; Y2 V. r& A
                        BYTE        dummy = n106.Read( addr );, J5 z4 ?- `2 S% T
                } else {
9 S* q  W  i8 ]5 f( z! K                        n106.Write( addr, data );
3 h: F+ H2 F& h                }
4 e9 ~$ x6 }& i: f/ |& k        }& z+ B" F; x9 g# q
        if( exsound_select & 0x20 ) {5 M0 b! D( }, k/ q5 ]' I: L
                fme7.Write( addr, data );
: T4 B* Q2 U2 n! d% |. k0 j        }& ^) L/ Q  J# Y7 Y* T
}
. ^' a, C- {: I+ L
# t( k. `1 g( @# b  A. s9 I' Z5 l3 Rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )# w7 |4 `" U& s) l2 s* z& N: N
{9 P5 I! t' j. o+ K: D$ Y* G
INT        nBits = Config.sound.nBits;
; m& K6 [+ V  |+ NDWORD        dwLength = dwSize / (nBits/8);
$ l2 M  m1 J2 ]1 t+ v) @INT        output;- U+ w% b% x* \
QUEUEDATA q;
4 b4 D1 V! U3 y* O& K9 a9 iDWORD        writetime;3 [) u9 ^  z" q# I9 ~2 j5 S
$ S- n. `, {* _0 }/ |/ a9 E- m
LPSHORT        pSoundBuf = m_SoundBuffer;; o7 ^0 \) E" ~& ^" d$ A/ l
INT        nCcount = 0;/ q0 h$ X3 B5 F7 O

! I" }7 U: I0 VINT        nFilterType = Config.sound.nFilterType;
2 S  k$ v1 J0 G( t% |; N2 \$ {
6 ~7 }( \: q/ p) n        if( !Config.sound.bEnable ) {
5 u; T3 F" u. A& C- r! W                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; V& d7 _) _0 J0 r* _. r
                return;
8 Q9 D% ?1 v- _# D5 n6 P        }$ P4 ?  h! g& A3 Z

, p% I8 u& n( ]+ L+ L& F- \8 k        // Volume setup$ Q/ G( S0 A. I5 M7 e: a0 j$ P
        //  0:Master
0 x- A1 O$ Q9 }' P2 ~" y6 t        //  1:Rectangle 1) \! w) X2 [. j6 V" t
        //  2:Rectangle 2
% ?& ~% ?( m1 `; a( p        //  3:Triangle
: e, Z2 p! v, ~4 z! R, A# [2 W7 b        //  4:Noise
( I' E! a( J/ `1 ]        //  5:DPCM
8 @$ T* J0 z! J* W9 e        //  6:VRC6
3 U& d; R& C; N4 L& C  r        //  7:VRC7
. P6 Q- y0 C$ _* Z3 B: Y        //  8:FDS5 E+ V+ G$ q, V+ Q' D, }5 ^% Q
        //  9:MMC50 l: m& ]- H' ]) |- i1 v" Y
        // 10:N106
! d3 L5 X$ Y/ J, H' y8 m        // 11:FME7% K7 k/ q% @( M& f& n
        INT        vol[24];
' {9 N2 X2 P5 D5 x' C        BOOL*        bMute = m_bMute;
. S0 @/ S- U$ d) ?+ o        SHORT*        nVolume = Config.sound.nVolume;
* J- j% r1 G$ |$ `) i# g1 u; y. G& k. P% _
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
2 ]8 h0 o( N$ x: d$ o+ G( B1 q' V$ ~0 g2 {* |
        // Internal
1 s) {( W; h2 J7 m: i; h        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
: O' V2 f3 \! R% a+ m/ j        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
5 Q* f. p/ l' P2 p) `. {% f2 C! W5 r        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 N9 ?5 }4 x8 D* v1 }, f, h9 C0 k1 J# l        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 N- _; X/ O  @2 A! z        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 X' Q  ], U6 j. P
4 S) i- V0 e7 f( F, Q6 Z4 J, v0 W        // VRC6
0 I% U3 h/ `) m) @9 |        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* D6 Q/ I5 M  ?/ D0 v
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
$ b; ]7 \' C; E' `  H3 w        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; i) {" T9 Y& {  M

1 _; _$ m9 I* u4 f. H        // VRC7
' |& b- _% ^! z& O1 w& N7 t        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
; L/ F: h" s. }1 Q2 _* R$ p/ R0 T! v4 J- ]: ]( l% H- y
        // FDS
) l6 ^7 ]' R) r4 N) Y& R) E" K        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, {. k( t0 r( I
7 a8 L* c3 y5 ~2 Y; }% [        // MMC5
2 T, P% r# ?; k+ h        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ c# t# R! {+ n8 ^: X' V2 ^$ {        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 M+ B9 o  l- P+ e2 S% r# B
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- k$ o8 r6 E! I
, p, r2 f' A: l7 w  j# \: A
        // N1061 V2 M7 X& D& {5 v8 Y3 d( C4 t6 E
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 [+ _4 m9 i2 c' N# i* a$ }
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 p8 n/ [# w) [1 T        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 }# ~% G6 g4 A- f' V. M( E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' x* N- w; N# P8 Z& B; z, H8 a. e3 c
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. `+ N( S  v) U! {! x  u: \
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 @2 C9 ?; w- G9 n
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 \. ~2 S) @! Y9 w
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# W0 `' D. v+ J: R( V1 M

. S9 \$ A! _2 x4 \        // FME7( a& X2 i6 o& H2 \+ M% ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ d' i0 u* [) a& h" Q9 r
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 k% W4 E- ^9 S2 w& A5 d) a! a        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ a" F5 I5 O& u7 L9 i4 i
( Y9 z" l; L: K1 \//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
5 d% s# |) T6 E8 o( m) L+ e        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# F+ h) u0 V$ Z5 F, Q  O
" d5 W1 P3 W  o5 z$ W% E
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% O! Z7 p; r2 |+ j6 |$ z% m        if( elapsed_time > nes->cpu->GetTotalCycles() ) {; v+ s5 t1 n8 s7 r2 H6 @& {
                QueueFlush();3 u6 f' q! ~6 f7 r! q$ t- ?$ V
        }
9 Q: H6 ^* _& r- V+ e3 V* n7 v
        while( dwLength-- ) {# g, p, q/ M7 I9 V" r
                writetime = (DWORD)elapsed_time;! s! D9 Z  l. t( M% N# K
- u5 B& t7 ~% x7 u4 P+ D  I+ U4 c
                while( GetQueue( writetime, q ) ) {# Y$ J" k1 O' v; |: {) ~. \0 F
                        WriteProcess( q.addr, q.data );
) v& N% E7 r, h# E5 H                }
4 x5 d) A$ j/ [. j
- k- `% T. U0 l' d8 G4 d9 i2 M6 B                while( GetExQueue( writetime, q ) ) {, `1 t: U5 o5 Z3 {
                        WriteExProcess( q.addr, q.data );
# |- h+ Y  X5 M; k& B                }
$ u" f  t9 R! w# O8 n( U( M- l: }" P3 {" e7 f7 g; N9 @* |$ U
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ j6 a( |2 `: b; ~% I. }, L                output = 0;5 U' E0 Y2 b$ ]7 Z& K: u' W
                output += internal.Process( 0 )*vol[0];
$ U0 V3 m  [. q. q8 f                output += internal.Process( 1 )*vol[1];
# Y6 i5 a, v2 l- P5 `                output += internal.Process( 2 )*vol[2];
; J! y9 T, u+ E- J/ a& w                output += internal.Process( 3 )*vol[3];0 o% O1 R: k, z, d
                output += internal.Process( 4 )*vol[4];1 A/ Y4 J0 `; v: ]; C, ]

2 v0 {% V) S, V" e                if( exsound_select & 0x01 ) {  w3 b, K& u" F$ z
                        output += vrc6.Process( 0 )*vol[5];$ Q: P0 Q; Z; ^1 B% ?
                        output += vrc6.Process( 1 )*vol[6];
; x- T& {# `6 c4 ]. r                        output += vrc6.Process( 2 )*vol[7];3 a- `- W) T* o7 L$ f
                }  I8 d/ N, A* w, V
                if( exsound_select & 0x02 ) {
2 Z% ^3 Z; A( J5 p6 J2 f8 l                        output += vrc7.Process( 0 )*vol[8];
  F2 I# k4 W+ `/ w, o3 t9 B( ]                }
2 E  u0 @' Q: k1 ^0 T/ X/ D) Q* V                if( exsound_select & 0x04 ) {
: ]; ]5 H0 i: ]( F: ^9 v# d                        output += fds.Process( 0 )*vol[9];* z7 k2 c/ R# O6 ^! U8 y. H9 \3 Z" m
                }
( {4 B  E! Z2 k8 @/ a$ ]% }( ]                if( exsound_select & 0x08 ) {
  E! F- J% v7 N! b6 W% m  B                        output += mmc5.Process( 0 )*vol[10];
8 D  ^0 t0 s# |8 O% u/ s5 C                        output += mmc5.Process( 1 )*vol[11];! n7 ]) t+ Y' U+ m3 n; H
                        output += mmc5.Process( 2 )*vol[12];* `8 c$ \1 r+ \& X
                }
/ x5 D% J* d  @2 E! _                if( exsound_select & 0x10 ) {
2 @2 S3 M7 t( A3 [                        output += n106.Process( 0 )*vol[13];2 T: v+ H1 l$ `. h$ i$ Q
                        output += n106.Process( 1 )*vol[14];
9 f5 [% m- g: v2 m4 V                        output += n106.Process( 2 )*vol[15];4 j+ k4 G& o( H4 H* A- q9 @0 F+ S
                        output += n106.Process( 3 )*vol[16];
+ ]: \2 A8 n$ W0 \) c* D/ X                        output += n106.Process( 4 )*vol[17];
" S& A' d1 I1 g                        output += n106.Process( 5 )*vol[18];
4 f$ u! R; Q1 D6 K# j+ Y                        output += n106.Process( 6 )*vol[19];. C4 ^2 Y3 X  ^. A
                        output += n106.Process( 7 )*vol[20];
( `  i! o$ E, P1 s$ F                }
0 Q4 [% I( H2 i! V                if( exsound_select & 0x20 ) {3 e5 o2 p9 {- o6 K7 `2 v
                        fme7.Process( 3 );        // Envelope & Noise4 F5 H4 R. A: y6 `' R
                        output += fme7.Process( 0 )*vol[21];& l; j3 o' ]3 L8 \# V
                        output += fme7.Process( 1 )*vol[22];
2 J' y5 y- R& q; L                        output += fme7.Process( 2 )*vol[23];
- ]2 \) ?7 t5 `. R; o                }6 Z$ j% ]2 Q1 i7 ~! d$ P, K

& }: ]% N1 @+ r                output >>= 8;
5 u' z0 S. R2 o9 |3 W" s
; q; K$ d2 Z3 |2 [0 K: o) K                if( nFilterType == 1 ) {
2 R! Q0 V( R8 O                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
, H- H( |0 w" T3 ?                        output = (lowpass_filter[0]+output)/2;# k+ o: i) w4 l
                        lowpass_filter[0] = output;
9 Y0 u3 @. e. H' d9 L                } else if( nFilterType == 2 ) {+ H9 w2 Z- ?- X- H
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
; S! V6 d( @" s  a3 X) M4 S5 {7 h                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
" w: c% {& C) k% v* v                        lowpass_filter[1] = lowpass_filter[0];5 m+ n) a# y5 x2 [) O
                        lowpass_filter[0] = output;# X  N, [& }; A- r9 o
                } else if( nFilterType == 3 ) {* _4 H- A/ C# \% d* S; k/ }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); C9 p" a7 o; K# T
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
( L8 M! z% }* G% j; d" a& d                        lowpass_filter[2] = lowpass_filter[1];- V' A" C/ W& D' ?5 f+ ^
                        lowpass_filter[1] = lowpass_filter[0];
+ y2 \; G4 O  c9 _4 t8 d( x, m                        lowpass_filter[0] = output;
9 G- k" h/ {5 A# A. X                } else if( nFilterType == 4 ) {
# o; D+ f/ l+ `                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)& M* v$ |; Z) W( H: _7 ^5 ^  Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;* o7 l; i7 b/ Y! x4 O1 v
                        lowpass_filter[1] = lowpass_filter[0];0 v- K/ B9 C/ B1 d1 K5 y& @0 c/ H
                        lowpass_filter[0] = output;' G# u9 P3 \6 b
                }# @# b! r; R- @8 a9 T6 k0 w
- a4 A+ |- b( Q& G
#if        08 @/ H, u6 H3 h+ b) E' _
                // DC惉暘偺僇僢僩6 {, H- X4 J+ }  v' O" [) T
                {
2 S* g+ G8 p5 [: i2 H                static double ave = 0.0, max=0.0, min=0.0;- }  S+ _8 w5 o
                double delta;
- Z  b& A1 b6 @2 X6 G                delta = (max-min)/32768.0;
7 ^) e1 I+ S% {! h2 z* x3 S/ H1 w2 t' i                max -= delta;
( Z9 p! f" h& q6 w7 l0 p                min += delta;
9 o6 P& v+ h) `) Y                if( output > max ) max = output;& i% }" x- Y$ M) `/ B
                if( output < min ) min = output;# ^8 {1 [1 a1 g2 P' g, g% Z
                ave -= ave/1024.0;
. H: ?4 V( v' S  ]3 o                ave += (max+min)/2048.0;
7 |2 {' l  B. U                output -= (INT)ave;4 e6 R. H& ^1 B! A: m# ]% \7 R
                }7 G+ e3 s; n4 |% k
#endif
3 c; H/ U( a5 K. N3 \* `+ ]+ m#if        1
) ^+ ~& s8 ~& z8 m2 W) M! k6 d5 X8 L                // DC惉暘偺僇僢僩(HPF TEST)
4 G3 J; a5 Y8 @: |' {                {
8 c7 ^& S6 j, @* Z+ Q/ V- T//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 L0 y7 G4 Q! A( b7 F! x( ~, B
                static        double        cutofftemp = (2.0*3.141592653579*40.0);  w7 e0 J- {: n9 P* B
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
1 G  `2 t# k& X7 p3 f$ O- E                static        double        tmp = 0.0;! {1 ?; @; z; v
                double        in, out;- @# [9 _: ^8 w! _6 e- ?

* {6 ?/ s& U; S                in = (double)output;* J  d8 k  f# n3 e
                out = (in - tmp);/ M2 J% M; V; O2 k- X
                tmp = tmp + cutoff * out;
, ?* v8 g+ J- }4 I$ J1 T8 F1 S5 F+ @. G% u* _/ t( u1 t
                output = (INT)out;$ A4 |" G( a7 i2 H
                }
2 [' @1 T( L3 y" n4 M  D#endif3 B/ C7 ~% E9 _& Y& G9 }4 P0 a/ \
#if        0' P3 r( ~1 s5 P* ]0 A: h6 U
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)  \9 ~# N0 C  z# d) t
                {6 E# b2 ^: n- E1 ?) m, K# T- Y
                INT        diff = abs(output-last_data);
) g) {0 F5 V5 U, h                if( diff > 0x4000 ) {/ d: T. P$ @7 ~
                        output /= 4;
% O% l* G& j1 R                } else
8 n5 F, K4 X" p# n4 F                if( diff > 0x3000 ) {+ x% h6 c) y# L' B4 Z
                        output /= 3;% f& c; Y4 r9 a2 E  x
                } else
9 `- y+ r# {( V, \9 i                if( diff > 0x2000 ) {8 \! y6 ?: }( X/ @) _
                        output /= 2;
( }7 w1 b6 E( R: e6 ^3 j* B" N3 p1 K                }
' U; T( }2 W- C* _                last_data = output;
" r9 T. \8 Z4 O' z# N                }
- V% n& _- X% T) n3 I6 D#endif- u* }$ G1 n, L2 l+ X7 G! u
                // Limit. f  V5 @) ?+ L' l/ y6 ]1 U2 m8 {
                if( output > 0x7FFF ) {; h/ q8 o2 P* L4 A
                        output = 0x7FFF;6 x. j2 X' u( @% m' ]' A  l/ ^! e1 E
                } else if( output < -0x8000 ) {
! A; r& ~5 b) d& w- O* h                        output = -0x8000;
1 E3 D( G! {; a* C" x5 t                }
* q- A+ f) K" c6 x9 v+ d7 E% T5 j) m( r7 ?" D7 r1 H1 ]& I
                if( nBits != 8 ) {/ E3 _$ A7 \" E2 v
                        *(SHORT*)lpBuffer = (SHORT)output;
2 S) J" ^; a7 L7 C                        lpBuffer += sizeof(SHORT);0 h: e6 l! T: K
                } else {
8 A6 Q% k; y" \% C                        *lpBuffer++ = (output>>8)^0x80;4 b+ m/ j( _# {& e2 O9 S& `
                }
- r; G$ U; W0 x( V- b5 ~9 ?
8 J7 _2 J" r8 E* i) Z                if( nCcount < 0x0100 )
) ^0 k( x9 [: [4 e# d: g$ ~                        pSoundBuf[nCcount++] = (SHORT)output;/ B4 d* W5 q$ s' f" m" |! L6 ^0 N9 S) E

; c. P' T- F* X* E* d: E' _//                elapsedtime += cycle_rate;# [! y. p+ ^+ I/ A
                elapsed_time += cycle_rate;8 R. f2 D4 b) A; k: x" y
        }
7 L& o! n) N7 ]9 g# ~' o" Q8 s
, J9 B: q! _. I  ]3 b. k. n#if        1
0 e2 v+ A0 X. ]        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
+ [% ^; h' i, T: H7 @/ I                elapsed_time = nes->cpu->GetTotalCycles();% ?! ^% C0 L6 W3 [# _* v0 Q
        }
) R; f  V- F- |: o3 `$ h1 M" a7 W) H" ]        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {/ R7 I0 V7 i( {
                elapsed_time = nes->cpu->GetTotalCycles();
0 V0 b% W  B1 _1 p) I4 P; x        }
8 ^" s* E! \2 I  R+ w9 S: G#else
% \( A7 i! ~* w% X) F        elapsed_time = nes->cpu->GetTotalCycles();
9 [/ o- K( e! y( j7 |6 A; h#endif
7 T% |- f0 a- P+ G, w}" e* E; l; P+ }( y* A
6 K7 W& F( N! j  G( X+ Q% n& ^
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
4 u+ t; R# B7 T# r) _6 \INT        APU::GetChannelFrequency( INT no )
7 w: ^; T. f/ V" ]/ f: Y9 x) M{, w3 R; _" K2 T" W
        if( !m_bMute[0] )! {4 ]$ X' C# a. A$ L8 |- r: `2 r
                return        0;
+ c; D# q! a3 u- l: @
" [! O* [6 U9 X3 t' A( d' s        // Internal3 u9 F- s( b6 q; j( i) n- s
        if( no < 5 ) {# f4 z* e+ g7 Q
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
" K, V: y9 K  V7 v% _        }
; y4 }* `, ^, B        // VRC6
- N+ `# P1 _5 D        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 b9 N0 L# k8 [( ^) j                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 X5 Z" m* G' a. e1 h' T/ s8 @
        }
: W6 F4 I$ E' g% `# u2 D. K" |        // FDS0 L9 y- r% ~- b0 X, Q7 i1 Q
        if( (exsound_select & 0x04) && no == 0x300 ) {
* F4 Y2 g: {4 J7 r                return        m_bMute[6]?fds.GetFreq( 0 ):0;# y- K) m8 i6 m+ [4 f5 e0 f  d( J
        }
9 E: y3 ]0 F1 W, m# y# ^        // MMC58 a/ o  z7 y5 c( C# }5 R. P1 b8 o
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
8 o4 `# Z. S6 t                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;6 `: q# h; M" C1 S
        }
0 Z8 {1 W/ g9 j        // N106  Z8 m# A4 m' f: ?; K( X. ^5 Y
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
1 `/ F' U3 O2 t  B; ^                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;! \7 y( s( w2 v' p3 T' {2 t
        }) b9 m5 P' i6 K) w) i7 _
        // FME7
% @  `& w) I& i! R7 G2 y        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 M$ U3 `+ g4 B: f! [
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;9 }4 \* x& Y* Z# L) W  L( Z
        }
' u. m8 N/ a' K- |) p' [  t        // VRC7
  b) S. b5 P7 h0 s0 Q& c. w) l        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
5 f7 J# p' u' x2 i, g# g                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;/ v- @+ D$ }' |( a9 X
        }$ q8 _; h( R+ R' p+ h5 e" R
        return        0;/ Z) p( D% X) Z% n
}) S6 z6 g' U3 C
9 `  L* |! A, z. J) v2 u+ I
// State Save/Load! h. R! B$ t. f* W& n( u; o6 {# l
void        APU::SaveState( LPBYTE p )# A1 y$ E  z/ x8 S# q) x- c2 j8 |5 N
{
6 b% S0 r; q2 F+ Z( ^3 q#ifdef        _DEBUG
' ^" g; l( r$ g- JLPBYTE        pold = p;
8 m5 I# A+ a- b#endif
. f4 e& c8 t+ d( P7 \6 L& z$ R( ~" F# J' ?* C
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
  [+ z. L$ l) x        QueueFlush();
$ m3 J* Q8 \! g* [
& j! z$ L1 D$ L, E% r        internal.SaveState( p );
0 G* D! \1 A% h, L        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  O8 }* |: `9 [/ H, K

5 ^- H( V2 V7 s) u  @# L8 J/ Q        // VRC6% D8 m* i9 z+ O1 z% ]" \- ^$ O
        if( exsound_select & 0x01 ) {" o7 d; V/ ?. V, L! ]
                vrc6.SaveState( p );, t4 i+ K0 ^% e, G
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 t# ^  F9 R- J2 K. Y; e
        }! h  _5 L4 z8 C2 [; e
        // VRC7 (not support)+ k- o" v, `, K  o# b; L7 R  ]
        if( exsound_select & 0x02 ) {  F/ O) [) H. p. Y$ u
                vrc7.SaveState( p );
( ^! i5 D6 B5 y- L8 E8 G                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 X. Z* J# c- U3 ]1 T" d! B* y
        }# p+ P, u% |; V) K. G8 R5 Q
        // FDS
/ Q8 j! s- c6 R" T: y! P. u        if( exsound_select & 0x04 ) {
, M& P8 B8 u+ u/ r# S                fds.SaveState( p );
+ t+ P7 P( q+ |                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. m4 S! u- W6 f7 y0 S4 ^        }
. K0 L: P" l$ p; I% L  s        // MMC5% j8 h, H- z& I2 X
        if( exsound_select & 0x08 ) {
7 R7 s0 o' v# G6 [$ }, F                mmc5.SaveState( p );
1 [; u2 n# y( M                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  Z$ [7 y3 ]: i6 I) `
        }2 K/ H" ^. E( W( j  S7 O* [  i
        // N106
4 j5 H! y$ H- b        if( exsound_select & 0x10 ) {; r" m6 e2 E9 T3 o, G
                n106.SaveState( p );: S; A! `- q/ C' ~/ E. i6 {& b& J
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: F2 J2 @2 Z+ [
        }
9 K" R# }9 H8 d# F        // FME7
6 f$ [* T5 g& e        if( exsound_select & 0x20 ) {
( m9 n) W0 ?4 Y                fme7.SaveState( p );8 D& I" k0 i) L; g0 C9 v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ O, g$ ?' p: P+ A4 p6 m        }
* u2 E: w$ D( O% s
5 L9 E, @3 B; L! Z  {: k+ p#ifdef        _DEBUG- O! e+ J) F* w4 w" j' Y" I
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" O6 d) j/ c3 g" A5 x
#endif
& h7 K: v# Y1 L( u5 S0 |}
" a! l+ x% U* z8 i3 h
6 I0 I) H/ W' [# w: q2 B0 N  nvoid        APU::LoadState( LPBYTE p )
0 l& ^& G' ^0 {2 N! V  _{
! t) ]7 x8 n* r8 S1 [1 E+ H        // 帪娫幉傪摨婜偝偣傞堊偵徚偡: k( w/ q5 a) x) [9 w4 R
        QueueClear();
, M. \: X+ J# p) s8 `1 l) F1 \' f9 ]
        internal.LoadState( p );# o% c4 P2 _; f2 v. J+ l9 g- C
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
1 i% R7 ~! [  W5 J! a5 Q; Y8 L% M
4 [# T- s( O: A# z        // VRC6
! ]6 Y8 k9 d0 G        if( exsound_select & 0x01 ) {. {. V# `. e. ^
                vrc6.LoadState( p );, c# w" S" p, e7 k6 F4 k
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 X+ [* Q! Z9 p1 b/ A        }
4 ^+ w/ `' `5 f. F" q: G        // VRC7 (not support)$ s# w2 i5 F5 H5 q7 m
        if( exsound_select & 0x02 ) {
# ^) d( L" w: r4 @- b- I  j5 C                vrc7.LoadState( p );5 R1 B# W( V. n4 Q% Q$ R' v
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, k( b( ^8 A$ ^( \; ?/ s' p8 C; g        }
- g$ e4 @, l0 y2 g' q. k        // FDS& ]  b5 }. O; F3 V  i) E* ?, K: O
        if( exsound_select & 0x04 ) {
( H. [( i( A9 c1 x                fds.LoadState( p );. I0 D- G( E# U* R# ~' C: s9 N! B- b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
/ N7 c# s/ t8 w2 v1 s- c, h* {' w        }
$ t. X6 W6 R) Z# v1 g9 d        // MMC5
, G& T% }: {9 D& U' z        if( exsound_select & 0x08 ) {
  ?" k* O( l" o                mmc5.LoadState( p );7 e" a! K; f6 p6 D0 q( ^2 z3 W
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. U6 C2 E* E9 ~, ^7 Z        }
9 K6 Z' P  S  u        // N106
, `) h$ L1 m) v* i) L" b        if( exsound_select & 0x10 ) {* h, E1 A! l$ n/ ~5 y0 ~
                n106.LoadState( p );  V& u, q, E4 u* I8 z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ E* n, M# Q3 n. L/ h5 [' X        }
% C% u3 L% g; Q2 l- v        // FME7
1 |, Y, J/ |0 Q        if( exsound_select & 0x20 ) {( `4 w7 h/ ]7 M. w, I: o
                fme7.LoadState( p );
' z6 V$ i. j! @( ]& j                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ I" h0 @9 q+ a  l" s. w
        }
% W  ^# @5 N/ d8 K}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
* r; Q& d# G: v$ i2 z, s% H; V可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
5 C1 C- l6 a3 c2 r7 s0 W感激不尽~~

; x6 f+ q8 b$ t: S( y: @恩 我對模擬器不是很有研究,4 s" M6 s& X( p& X2 q3 y5 U
雖然要了解源碼內容,可能不是很困難,
5 H6 y9 T" h/ e6 e6 X6 l不過還是要花時間,個人目前蠻忙碌的。
4 R1 ~+ [3 Q+ o! p: h. A+ w0 V9 u1 w6 V9 A* Z, b
給你一個朋友的MSN,你可以跟他討論看看,
3 h' `* e$ N" p4 j他本身是程式設計師,也對FC模擬器很有興趣。1 y4 W; N5 |& B
$ q6 ?5 r5 `3 u  z5 I" o
MSN我就PM到你的信箱了。5 g2 U/ E/ i: {! S$ ~+ O
" E2 P: b8 A3 n" k, u( c
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
% o& u' G$ w% ]& @3 x呵…… 谢过团长大人~~

' R8 ~6 U% j9 c" `9 i5 B
0 \- ~! ?* S5 N2 e$ V! m哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! J. H6 d/ O0 w/ b  A0 L
团长的朋友都是神,那团长就是神的boss。

8 ]) H0 p. N/ ?哈 不敢當,我只是個平凡人,+ o- D$ ]1 f! {1 w( |
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙) e5 e3 q' G  L% W
ZYH$ U" u" T( X' k! G" ^5 l
QQ:4147343067 Z5 {, ~2 i& B2 |( m
Mail:zyh-01@126.com
3 g2 ^( \3 _( \2 ~7 [8 O' h3 z' c7 H6 n. R% U
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
8 u: f: K% M$ H2 l. U再次对团长大人和悠悠哥的无私帮助表示感谢~~
" B; d9 K1 D8 L* K% O* m5 P4 l
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-10 09:15 , Processed in 1.067383 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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