EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 U' u) g- S/ u8 j2 r$ Q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
& h1 L& U& D% B+ X, F这里有相应的模拟器源码,就当送给大侠了~~- u) I9 W1 p+ W, e
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 - z$ n: N9 i% J' d6 {/ V+ z" B' s: H
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, t& U) K7 B2 g* X! L* {
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 L3 c7 D# F$ ?+ Z0 `3 V7 R0 n
这里有相应的模拟器源码,就当送给大侠 ...
# J1 G- k( d) x
聲音部分(Audoi Process Unit = APU):; j, V( d8 n- r( U7 M
.\NES\APU.cpp9 [9 V- l8 N! ]& [0 I$ }) X; F- ]
.\NES\APU.h- Y9 d6 \' N' P3 r3 k3 }2 T
! _3 _: @3 _; A* b
; U2 ?3 T: O& {. N" R  E
影像處理部份(Picture Processing Unit = PPU):
7 x- U" Z1 g) E! V.\NES\PPU.cpp, ~3 f4 h9 X4 E9 T
.\NES\PPU.h
& r8 D$ ^; T) \# Y, F+ U: X; v. U& ~, `. M6 Y) z* }
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:) l5 H/ B% @" L' w$ Y" c& H* S
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
" v+ t+ v* v) g- i7 K6 y' |//////////////////////////////////////////////////////////////////////////& o) E# x$ M! R* p3 a; o1 B
//                                                                      //
  T7 t0 B- n4 X  h//      NES APU core                                                    //: _8 N' s$ _# Q! J0 c) f- `4 l/ d
//                                                           Norix      //
$ w+ C; k# `' E4 j+ q2 {//                                               written     2002/06/27 //
7 U0 W9 I3 Y; [$ u$ w3 N% X2 U! q. O//                                               last modify ----/--/-- //; W1 P4 N4 Y8 `+ c- M; p
//////////////////////////////////////////////////////////////////////////
1 v" z/ n6 J* h/ x#include "DebugOut.h"
# S0 v- y3 X! Q3 a0 h#include "App.h"
2 o0 d( z/ F" H- m9 I( f1 b: `/ @#include "Config.h") H$ I9 Z7 z* ~7 m- w
+ x+ L4 Q0 c# h) c
#include "nes.h"
( h( n( H0 Z- P* [3 P6 _/ n#include "mmu.h"
8 e$ ~4 c& b; g% `% \#include "cpu.h"
% e6 s) y6 ^1 U#include "ppu.h"- X  g0 g' C9 z3 F5 t# q9 C2 }
#include "rom.h"
2 f8 v" U" U; n#include "apu.h"$ c' s2 g" D: W- ^5 }+ K

' h3 P( U# Y/ x2 _// Volume adjust- v, z; V% Z. B/ O+ X  H% w
// Internal sounds
, `: \% z1 ?' [* J- I+ D$ P+ ~#define        RECTANGLE_VOL        (0x0F0); B" o$ V+ I! U5 S# Y6 Y
#define        TRIANGLE_VOL        (0x130)
# R4 ]& B& _1 }9 d' G#define        NOISE_VOL        (0x0C0)5 i  l6 C% J5 ~
#define        DPCM_VOL        (0x0F0)7 f% U- p+ x+ u7 v0 K% a1 o) u
// Extra sounds7 u2 c6 [  r2 h, x: @
#define        VRC6_VOL        (0x0F0)
% ?+ B7 b# s, T#define        VRC7_VOL        (0x130)* A9 P$ D4 p2 N
#define        FDS_VOL                (0x0F0)% l: g; C( J0 H# X& t7 A
#define        MMC5_VOL        (0x0F0)* S( Y8 v7 V# C. ?' T# }
#define        N106_VOL        (0x088)
, g0 `/ G, ?  q5 W#define        FME7_VOL        (0x130)
* F6 L0 m; L" J( G; H) `6 K- F- _4 c* e  Y5 N; o6 l
APU::APU( NES* parent )
) l/ T; H3 [  V; A( |( A{5 w" q  N9 O- s# o% @' [5 o& d! n5 r
        exsound_select = 0;
/ t! Q" Y: t: {4 X4 S& U, |, `" G5 h  N
        nes = parent;
: }& f2 h5 `- q/ W0 L% I        internal.SetParent( parent );
9 J' J5 t* p  I: x7 j1 G/ l2 q$ w& d/ z* Z' W/ i3 Z
        last_data = last_diff = 0;
" f4 |. k. J  l* V0 J; w1 K+ P: |. g/ q, Q- `  W% O+ U
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 H* m# K, u, Q6 C
, m4 N, W8 b4 G& A+ z. E
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );5 l' X- j8 q0 ?
        ZEROMEMORY( &queue, sizeof(queue) );6 L9 ]  a- [+ ~3 a9 y/ k
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! g; U5 j5 |) c/ n: F
) l+ E" }8 e! s5 o9 b+ ^        for( INT i = 0; i < 16; i++ ) {
4 R/ m* m6 T# t                m_bMute = TRUE;* L/ ]7 N: M0 y, W0 U( U
        }7 R6 `9 \0 v  l( d* ^! q' g
}
+ e$ X6 m' b) D5 T% _, V' A8 t5 X  g6 _# x1 Q
APU::~APU()
: U5 `6 C+ Z( b* L0 a7 o{2 J8 o, Y& H" y6 O
}4 |* C) l; r" o& W. ^
7 U8 ]! j% T7 @3 F8 J
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' w" B8 ]2 b! M9 A1 ?7 W{. M1 o' W: ?% v
        queue.data[queue.wrptr].time = writetime;
+ Q: ?$ n9 q7 K4 E6 u        queue.data[queue.wrptr].addr = addr;  O' I3 T' G4 L6 {: X, ^& p9 Q
        queue.data[queue.wrptr].data = data;
( R9 A% D/ @+ F  B& k9 d        queue.wrptr++;
- D) [* K4 d6 Y4 K; F, r        queue.wrptr&=QUEUE_LENGTH-1;
. |# l9 j  t# z/ X0 A        if( queue.wrptr == queue.rdptr ) {( O7 N7 D7 W. d- j# v2 n
                DEBUGOUT( "queue overflow.\n" );
# W; ^. H( X6 P0 V2 J9 H: t        }
  ?/ U- Y3 z! r- ~+ t}
% v3 U, k/ k0 F/ ?0 o! t
! t$ m! z# z+ {& y3 fBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ M5 _; [# e  {) ^$ W/ R
{
) o6 B" N3 I3 Z4 Q8 Y/ a, d        if( queue.wrptr == queue.rdptr ) {% l$ c: \5 `. S8 V! T
                return        FALSE;$ L0 H- h5 C7 v$ h2 J, M2 \; f
        }
2 C" X5 h7 p5 Q; I8 W" H: Z% |4 Z( ?        if( queue.data[queue.rdptr].time <= writetime ) {- _) ~8 r% G  `2 C7 C" z! s
                ret = queue.data[queue.rdptr];
* E7 I" n, Q. [& x5 w# v9 S! @: A& f                queue.rdptr++;
$ K! T+ P1 a" a4 V                queue.rdptr&=QUEUE_LENGTH-1;
% J% `1 J7 H. r, c, @/ n( }                return        TRUE;4 Y1 `" p( a; N7 R+ Z. Q
        }$ Z  q9 {7 {) U) X
        return        FALSE;
; K9 x8 B) T* o7 Z0 q, _# _}
) a& R) H0 E2 y, L, n, P* U
% z$ e9 w; T- i) |; [8 uvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
! E# E4 E9 l+ [{0 q- G3 Z/ W4 I; c: _, D
        exqueue.data[exqueue.wrptr].time = writetime;
. B& H+ A; H0 p; q1 W* e$ K        exqueue.data[exqueue.wrptr].addr = addr;/ K2 i# X/ g9 B* A
        exqueue.data[exqueue.wrptr].data = data;
# U/ J6 U$ b) T% m        exqueue.wrptr++;- E/ V+ @( K" g1 P, Y( _$ C  _
        exqueue.wrptr&=QUEUE_LENGTH-1;
/ t* ~) r. k$ h! t        if( exqueue.wrptr == exqueue.rdptr ) {* ^; T4 |( d1 j4 M, o& v  ]
                DEBUGOUT( "exqueue overflow.\n" );
" r8 [" F( x) r# S        }& f6 l- l2 |1 t# w7 c# U$ t. f/ v
}- W& N6 c/ Z/ y9 M

) c5 ]1 T: A& s. v4 f: H$ vBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
1 o6 P' }5 L" M4 U7 e: ?" |2 G{* d/ K: ~2 K; t. O
        if( exqueue.wrptr == exqueue.rdptr ) {7 x' d! A- R+ E+ w5 T' W# f
                return        FALSE;
2 f8 I+ C  I$ e8 g, F8 n        }, m# r! g& F4 T! c5 O- F
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {4 E  s" X* b5 p  K* Y$ Q+ I
                ret = exqueue.data[exqueue.rdptr];
1 G/ |# d; P* C3 L" C                exqueue.rdptr++;9 v$ y: m' ^. N
                exqueue.rdptr&=QUEUE_LENGTH-1;1 w* ]2 o# n- F! F; o  N
                return        TRUE;
8 G& y1 _+ D) x" C        }
4 B8 @# K' P9 `. Q        return        FALSE;
% o9 C/ }- P1 a0 ~- _/ f% S) x}" q$ q4 @$ {. M- `! o4 Z& R# Q
& X# O# M% u2 I- K5 r0 k: y! P
void        APU::QueueClear()8 J! v% j) O) z; ^: N! r( R" U! t
{. J4 ~3 \3 g+ Q) \/ @
        ZEROMEMORY( &queue, sizeof(queue) );8 c& h- V; c  i1 ^. n
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ X& H$ ]6 q) A* T4 d' x) d}
1 I! q3 m  S' Q$ y+ C, m8 P# b" w8 H( l
void        APU::QueueFlush()3 X( h6 d  h& m( l4 d* y. U
{
8 m1 X8 R4 @. h2 ]  Y        while( queue.wrptr != queue.rdptr ) {7 [  D+ z& }& n* s7 }& J
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; H. R; S, Z7 k6 |4 N
                queue.rdptr++;( D6 D0 c: o0 |, z# @; n
                queue.rdptr&=QUEUE_LENGTH-1;
! v0 g. o3 x* E* N3 t+ }3 |1 [        }
6 E6 p& w2 h, ~2 C$ C2 D: [3 Q2 x  ~2 ~: G4 {+ Q4 v! V
        while( exqueue.wrptr != exqueue.rdptr ) {5 n6 [& X/ ~8 N8 O! b1 r
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );1 W, ^& E9 s# |7 W! q  D
                exqueue.rdptr++;
7 [& W' E5 y+ j# a                exqueue.rdptr&=QUEUE_LENGTH-1;
- {: y* [) ]8 ]9 j+ h" Y% ^        }6 r: X0 e! C5 v9 X8 I) a* s3 P
}
8 c: i# \7 u- ]5 M: z8 |! y4 E, a5 e8 `5 R) N% e! @
void        APU::SoundSetup()
4 K8 ]  I, q  p  o/ r{
2 b3 Z4 H) {- O; P        FLOAT        fClock = nes->nescfg->CpuClock;& d- h' e9 u. g/ @+ V# W. a
        INT        nRate = (INT)Config.sound.nRate;. V0 ?4 X+ d; Q7 J; v' Q6 D
        internal.Setup( fClock, nRate );
* U# ?9 s7 @1 _+ ^8 h1 w        vrc6.Setup( fClock, nRate );. u! T+ w, g) `
        vrc7.Setup( fClock, nRate );
" p  c+ b, m% U8 H        mmc5.Setup( fClock, nRate );% ]5 W8 c* {% B: i5 [' [
        fds.Setup ( fClock, nRate );
& o& d: [7 q* r# o, h  G        n106.Setup( fClock, nRate );: S# [* G. l4 N/ W
        fme7.Setup( fClock, nRate );
9 ~% p. [* h4 z4 t) w' l}
( b2 o# t4 z# ~; t5 }
: O! g2 j8 R8 H7 {0 {- Y% W' Vvoid        APU::Reset()# a' ?1 O, v3 ~6 J& o
{( W/ Z. J0 }$ n4 `6 u
        ZEROMEMORY( &queue, sizeof(queue) );
' ^$ [5 C% l/ D) t        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 y) J  i5 w) J3 {/ d
+ R0 D* k! t/ c9 Q# ]- L' F. {
        elapsed_time = 0;7 @: R: X! }. M# y" b+ L& y3 o
% g0 l- t! |% q2 _( ~0 }; R
        FLOAT        fClock = nes->nescfg->CpuClock;; ?3 r" V/ r. R) A6 A
        INT        nRate = (INT)Config.sound.nRate;
- ], n! F6 \/ b8 |/ f- N( w) c        internal.Reset( fClock, nRate );
$ k  ]; x. H; k! n        vrc6.Reset( fClock, nRate );
0 c0 R" y0 k% M4 x1 K- [* H        vrc7.Reset( fClock, nRate );
: m" H3 D2 }4 Z% [( ]        mmc5.Reset( fClock, nRate );% ^+ Q3 X% _& F# Y- V6 y' {
        fds.Reset ( fClock, nRate );% Z2 ?% S+ {+ K" r2 B6 N
        n106.Reset( fClock, nRate );8 \' d+ |; W) }/ H! `) M
        fme7.Reset( fClock, nRate );, J- {# |$ g& x" o8 L
  k& v: E8 @% r6 n
        SoundSetup();
1 t9 L' i1 V# x: b}4 G9 K1 L. q. v8 N! h
9 X% C8 I' e; l' B( w5 y
void        APU::SelectExSound( BYTE data )& z8 F4 n9 F8 i+ P8 _3 u, ]5 D
{) Y+ }2 S0 s; f3 a2 k' E. Q
        exsound_select = data;
: t/ T- k7 M$ ?9 r% z}
3 I. o+ e0 b0 h1 {
# _2 \. n; F& G0 j! ]' S) r( x! `BYTE        APU::Read( WORD addr )  ?2 t4 F3 p9 x) H6 I
{! u% |6 T# c! M4 V  K/ o- e
        return        internal.SyncRead( addr );
( V' W/ S( ~. e; D( _3 X! h0 S}" Z" \; A# Z# L9 ?2 B- ~
# M/ b( v2 b5 P/ l3 V) Y; d4 k
void        APU::Write( WORD addr, BYTE data )' F3 w5 V& X/ g  O, ~3 e
{6 e1 [; P( N* A! @' D) ^! U
        // $4018偼VirtuaNES屌桳億乕僩+ L) C% C* ~6 s; X- Z! B
        if( addr >= 0x4000 && addr <= 0x401F ) {
0 |- a" k  l3 t2 C' q                internal.SyncWrite( addr, data );+ K7 \9 a9 i1 a3 \* x; u
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 i3 ?" t+ v4 u
        }: T6 q! I- n% R* F0 @) V
}
2 L/ D& w' F2 Y1 z. U6 U( E
( S2 Q4 b8 y% L0 X% N/ P% Q/ GBYTE        APU::ExRead( WORD addr ): g& s9 ~7 |0 U" C" Z' e" F: p9 w
{
. h) l9 v  g0 O. L) sBYTE        data = 0;8 z; X. C/ ^+ q8 ]* v5 ~
) B6 y2 `! `$ f+ b( b+ W& j
        if( exsound_select & 0x10 ) {
9 }8 ]: H- Q9 L! H0 {3 Y0 k                if( addr == 0x4800 ) {
: c: H5 R* A- r3 C                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );5 y5 j9 {3 x1 ~8 H5 u+ C! u
                }7 t" ?2 @/ |5 P3 }  |2 l: @
        }( O  B. S: M7 `! f  a) b. h
        if( exsound_select & 0x04 ) {1 U/ o# g7 V5 s* @7 T& A
                if( addr >= 0x4040 && addr < 0x4100 ) {" p3 `+ i' [/ n9 _0 K
                        data = fds.SyncRead( addr );
1 t& O: B$ P7 i. u1 A6 c                }
0 K5 V  c+ n3 T' _        }
; C1 q" D4 C2 X0 S+ M. \8 I        if( exsound_select & 0x08 ) {
6 q$ |  r: a, q. l- r6 k                if( addr >= 0x5000 && addr <= 0x5015 ) {1 U3 J) A1 L, ?9 o0 v! E
                        data = mmc5.SyncRead( addr );
6 y- ]5 R  Y* [- z. y0 v3 v                }: f7 f9 U$ m% X% i! c+ w
        }
/ h5 X* M" P% y7 Q1 C
" M- J) f' Z! F$ F) w* \" N        return        data;" }# C' X& M2 B& \3 u5 g2 x, T
}/ g/ ^  X5 H) i" `; S
4 y6 V) U7 z' L
void        APU::ExWrite( WORD addr, BYTE data )* k, T! e, c. [* k! h" A) c7 }
{
' F$ r. @+ V1 _3 Q9 n        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );! K" [, h: j1 f/ B0 s
: I2 ~, D1 U8 F* @, E
        if( exsound_select & 0x04 ) {
" {, |4 o, ~; q! J: K* N* n                if( addr >= 0x4040 && addr < 0x4100 ) {+ T; _+ J6 J+ }/ {. O9 E
                        fds.SyncWrite( addr, data );( c- S0 L! h: S) q. H4 I+ H
                }
( G$ B( Z1 O  ~0 ]        }
6 E9 ~( ^9 X8 A$ J/ Y& V/ B  g5 h) z' I/ C+ p' Z
        if( exsound_select & 0x08 ) {
( P4 }- k3 N6 L- T/ [                if( addr >= 0x5000 && addr <= 0x5015 ) {. B" F* W4 x( k% ~# V* B1 t, X
                        mmc5.SyncWrite( addr, data );
' Y/ g9 j) U: \& [                }' G0 {8 w/ C- p. f2 o
        }
) c& u8 f9 Q+ H( K% C, @}
- k) _; I# \( b1 Z! J* F7 ^1 E$ I- [% Y, o8 `+ C% U0 |( G
void        APU::Sync()
) h) y; O/ {( _9 v0 @+ N{
3 S" v' H5 b) ]" Z6 n/ {' c- X}
5 q, K; D- E+ G2 M, h$ Z' g3 ~* g8 V1 h
void        APU::SyncDPCM( INT cycles )
6 c: n  o2 Z1 B8 n  c1 d{! v2 n% w2 j' `7 k
        internal.Sync( cycles );
5 w* j. P3 t5 a: U2 @- W2 ?5 r* N. d$ ]# ~5 W) z( b
        if( exsound_select & 0x04 ) {" |( n5 m* {6 \& v! I- g9 k
                fds.Sync( cycles );& I! u+ E4 p. w
        }1 a7 U% q, N$ A
        if( exsound_select & 0x08 ) {
# w. W: v$ ?. t' f* c                mmc5.Sync( cycles );
. B' k! M' W2 }3 L9 V        }
& E4 x. a9 {* J0 i7 H}
6 H1 }( H# Y( d
$ G- V& k0 ~8 g: m7 F2 Hvoid        APU::WriteProcess( WORD addr, BYTE data )( m( F% K' ]& v( J- F
{
0 q* V% N0 f* ~1 f        // $4018偼VirtuaNES屌桳億乕僩' q! S' O& A% C5 J$ p6 C7 u; X
        if( addr >= 0x4000 && addr <= 0x401F ) {
% N, U% V7 h- R6 g3 P4 z                internal.Write( addr, data );  g. b0 W1 s7 P  h) T
        }
- }% k, z9 t9 U$ u$ K5 Q# t  Y}7 R" y9 F* ?: q

7 j% c( A1 b& B  P  Avoid        APU::WriteExProcess( WORD addr, BYTE data )
, }" W5 g* a0 U- x! `6 ?) I- ^/ L- o{9 ^7 Q0 E! S3 ~2 {
        if( exsound_select & 0x01 ) {
9 S! X9 ^( f( Y: B& }/ k% b4 j& h                vrc6.Write( addr, data );
* d; L) M' G  |        }+ {) Z( ~) [+ d4 }! j6 T* l. N5 Q3 n
        if( exsound_select & 0x02 ) {) L" u; r: U! e
                vrc7.Write( addr, data );
% f9 ~$ }  t) d: K6 p( }2 H; U        }- V2 a+ W. W9 b& [
        if( exsound_select & 0x04 ) {
- x& ]* O$ y+ K                fds.Write( addr, data );
3 w6 l* j% `# k: B7 c: o        }
- j3 }( @, B1 [        if( exsound_select & 0x08 ) {% c  U% A* G1 D  q1 O9 Y
                mmc5.Write( addr, data );
. Y, E5 ^+ H3 M" W        }4 u3 r' u2 ?0 x. |0 A3 `) \
        if( exsound_select & 0x10 ) {
! p% ?; S! R9 v6 f4 I. @                if( addr == 0x0000 ) {
: y  A6 y5 w* {4 k                        BYTE        dummy = n106.Read( addr );
; r/ P9 j8 a" Y( K! _) Z  f                } else {# d- z6 H. P8 F% ~4 N
                        n106.Write( addr, data );
# ]0 ?' a+ r# f& x; V: t6 \8 g                }
% B9 k7 [/ _8 @( c1 n0 A5 @4 i        }
; z8 ]# W. v! h" n3 n" _        if( exsound_select & 0x20 ) {7 b; }$ r$ ]" t! [" b
                fme7.Write( addr, data );6 |% e" p; ^) Q0 M7 D
        }7 \& M4 E* B) `# Z7 F0 u
}
- `: I- E2 |. @5 R1 T" u" B7 g& l( `! ^# o* _3 y1 @; x& E
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )0 W; ^' ^2 \* T; ~6 K5 `" d( P
{" U% q4 z1 a. I5 C# N; h% W
INT        nBits = Config.sound.nBits;. ~7 {8 ?! E' V' q
DWORD        dwLength = dwSize / (nBits/8);( k: C, Y5 ~% m, `3 f0 i+ V
INT        output;
& _4 U! O& W( S, J+ H+ T9 A! @) MQUEUEDATA q;/ }# M/ c( V& t
DWORD        writetime;
1 C% Q; E5 q( \7 G8 l  Q- L! R, f) ]' N, o% g! Z
LPSHORT        pSoundBuf = m_SoundBuffer;
" c: Y4 t& i. R9 O+ nINT        nCcount = 0;
" P7 ~4 `) f  x% P6 K$ p9 K  A. d/ L) h8 E$ k# R
INT        nFilterType = Config.sound.nFilterType;
: C7 r' T/ f) ~3 l$ n5 U  V8 ?; W4 ^, r+ ]7 H& i8 y, w* f
        if( !Config.sound.bEnable ) {. P0 r+ W0 I6 x1 Q. a
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, r( f$ ?: D" F1 i5 W, e1 b8 P0 ?                return;0 C) ], D) H  V% ]; q! R
        }3 y2 ?8 y! S7 ^1 R  l! ^

* c+ ]: _" x  E# H& C6 m        // Volume setup
& I8 g! p# T* S) g& I( Z, x6 l        //  0:Master& V# |2 J+ i. P0 F/ `& a2 F: \
        //  1:Rectangle 1
% N; C* ^! c3 N* w        //  2:Rectangle 2- s: o0 o' P. a4 I5 I9 A0 B
        //  3:Triangle5 [# Y/ l: ]8 X0 a, R6 D8 {* C/ @  h
        //  4:Noise. H+ X) n! b& c; f7 M( E* v: P
        //  5:DPCM
- z5 q. i, `1 J- c- Z; c        //  6:VRC6
& c, h$ z0 B' q0 U        //  7:VRC7
; H0 ], G" g- ?        //  8:FDS. v' W9 J! R7 ~9 x$ [6 r
        //  9:MMC5
! _; s: N+ N5 {; H% ~; E        // 10:N106
( M+ ]! b; `0 D  k        // 11:FME79 `9 }6 V! _  ^1 T) X5 @7 Y. A' D
        INT        vol[24];
& t2 z- ~$ s, Z9 v! d        BOOL*        bMute = m_bMute;& {; Q1 ]! y$ G* f4 `! }! d
        SHORT*        nVolume = Config.sound.nVolume;+ q! C, s# {4 o2 @. R
. L5 A/ ?2 x1 v$ v6 u# e* |1 X
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- Q, K1 U6 M$ ]$ ?: |9 y% M9 X( _3 Q; i
        // Internal
" s( }" K4 r& {, }        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;" _# s" i$ A! K2 Z+ K
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;) G8 n8 J# j5 f0 x+ p4 C& t/ ^
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;( f  ~; d: H  M% v" ]0 w" J
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;% A* I. ]& ?0 @$ R( Q
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. e2 g1 X) v; h0 Y7 {& I& Z: y4 w7 N, N/ \8 r* u% Z9 ]
        // VRC6
) S# S3 w3 i( I9 |; _8 U        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 M& [: e. M4 ^1 c1 Q# z0 s9 O
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 R- h$ g9 ^2 h5 l4 j$ P9 s
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( `& i4 ?2 q& I1 Z

: q  V+ M0 j' d7 L, F/ U, @+ V        // VRC7
9 d' c" y, B" g$ v6 g        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ {  j$ J7 V! W; [1 v) L# p8 H: L, V
        // FDS1 B  o: H* J& ~6 o& e6 W6 ~9 d
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# L! h# Q0 }! ~4 o6 M* p8 x4 P9 r; u* _0 Q; o& A
        // MMC5
4 V9 Q1 S2 j( B# r  [* u* A+ J        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( @% A+ s  ]( x7 Y
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- E1 Z3 g0 q2 {) g# @: d0 r( X
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; W7 @1 L- \5 x2 ~
4 r3 n) e- r/ J, V( {, s9 e6 m0 J        // N1060 v" T- q) W) n( \" k
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# f0 j! O+ S, Z3 s        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ s# ^; j: I5 K. U* j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 T/ N8 d8 F" O1 F4 u        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 D1 `( r! E- h0 a        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  h) |# G& K7 c! Q
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 m; `, a% d4 J
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' y5 j" u: W1 b; S9 [" E/ G# L) u        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# n' Q# E4 ^+ K- V+ @

" c* {' d7 z( {) p        // FME7/ M" |4 ^: Q/ V1 O2 A' B& A
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. Q2 ^. h& {/ a/ F$ V        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
( V& q& p. Y# c        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, j: T4 O/ A' e2 R6 ~$ m  e: Z
& k$ p4 D5 ~% m/ m: f4 n9 @//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;! W2 C, A: y- J8 B
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
0 H  @; s9 z0 C" C3 W3 r! H) q8 G2 U  O7 X. O1 u
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟: S% \; ~  l% Q+ F) i
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
) Z$ y/ ~/ w: l; Q. ]                QueueFlush();
/ o, B  i! b6 H- n" i2 X' k        }; g4 A% k4 M: S

; e9 ]4 j9 S; U1 i7 i        while( dwLength-- ) {
1 k8 W; O9 _* c( y) r                writetime = (DWORD)elapsed_time;# ~; X8 \! X* M
* \6 p# i. _9 w7 y6 b
                while( GetQueue( writetime, q ) ) {! m; ?. Z2 Z7 X6 n5 @8 s* [. R
                        WriteProcess( q.addr, q.data );
. f4 c. U2 ?  B+ h- |6 w4 p# ]  r                }
/ d& ~' c- Z; q8 U3 l# m- e& |/ j
, E4 ]4 W5 \# P) ?                while( GetExQueue( writetime, q ) ) {& t& l9 ]0 c' P( y: F
                        WriteExProcess( q.addr, q.data );
9 O, S% q& L$ ]0 u+ T                }* p/ p% L6 z. d3 W
2 }# O: [- Y2 ~
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
$ J% [6 e* g+ N- d                output = 0;3 ?9 o5 k. q! o  `0 {
                output += internal.Process( 0 )*vol[0];
3 G, o0 t6 k7 c- @9 q& [) `  {                output += internal.Process( 1 )*vol[1];* ^; |) e% w7 c" w
                output += internal.Process( 2 )*vol[2];
3 v% p$ [/ g' {# _5 A* \. u                output += internal.Process( 3 )*vol[3];
2 }. b& M' b$ E$ W+ B* l9 _                output += internal.Process( 4 )*vol[4];
( b% z7 `: }% p3 C0 B1 V; w
/ N6 n7 r( i/ o8 G5 m                if( exsound_select & 0x01 ) {
1 Q: ?8 i; F; Z                        output += vrc6.Process( 0 )*vol[5];% B2 `: @; k9 r) E2 ^: _1 P& n
                        output += vrc6.Process( 1 )*vol[6];+ L  z2 y' ?& y. l1 _) Z
                        output += vrc6.Process( 2 )*vol[7];! {+ ^- y: b. {
                }
0 {1 d/ f* ?# _; a2 Y                if( exsound_select & 0x02 ) {
: E1 L7 U; \' V0 a/ X+ E                        output += vrc7.Process( 0 )*vol[8];
! i; l2 J3 _9 ?1 e                }
7 M8 u, N: G7 R/ b9 O7 z: O                if( exsound_select & 0x04 ) {# P6 I  r8 |" w
                        output += fds.Process( 0 )*vol[9];. Q. m1 R+ S% S
                }
1 L3 d* n" {; l. ^  U3 P                if( exsound_select & 0x08 ) {
% V+ Q- h1 H  i& t0 w" e1 u                        output += mmc5.Process( 0 )*vol[10];0 d# L4 c7 \. Z! _7 d2 s/ l
                        output += mmc5.Process( 1 )*vol[11];. [6 }+ m, t# T0 {$ k" L
                        output += mmc5.Process( 2 )*vol[12];0 |) e$ h' z! X1 n' {
                }0 B0 g% L) t9 u7 {" F/ b  f
                if( exsound_select & 0x10 ) {
! [6 `% c% J' ?, \8 K                        output += n106.Process( 0 )*vol[13];4 V5 _1 A7 c+ C3 U% ^; h
                        output += n106.Process( 1 )*vol[14];' R+ G9 T. t. T* o7 P
                        output += n106.Process( 2 )*vol[15];
9 ~. B' _; I( g' F% v1 [; w                        output += n106.Process( 3 )*vol[16];
) Y/ O8 V6 B7 U* z: \, X5 [                        output += n106.Process( 4 )*vol[17];# @0 x$ t1 {# |
                        output += n106.Process( 5 )*vol[18];+ N. q! a: M# Z8 m' S4 i  b3 v
                        output += n106.Process( 6 )*vol[19];
4 ~4 u' e9 z: [, I                        output += n106.Process( 7 )*vol[20];! G5 k( {* C3 K1 s) t
                }9 b, O" L3 d) s& I$ e8 F
                if( exsound_select & 0x20 ) {
6 h3 X' ^2 d5 @$ r6 T; D& e                        fme7.Process( 3 );        // Envelope & Noise
  v7 z3 O: z" |" P% M) O' a                        output += fme7.Process( 0 )*vol[21];3 r; b3 L% Y8 b7 h
                        output += fme7.Process( 1 )*vol[22];. n) ^  F2 W  [7 P
                        output += fme7.Process( 2 )*vol[23];! k6 X, b0 Y2 `* E1 @
                }
: I0 o' R9 _" V4 j( J0 e
4 m$ v5 P# K8 x& e, |& ^/ l9 A                output >>= 8;/ ^- |6 x2 J$ R

4 F4 Z$ }! }" ?                if( nFilterType == 1 ) {2 v' G* M" ], N+ ^  E
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
/ `: a" J" l' ^; E( P% x                        output = (lowpass_filter[0]+output)/2;! Y9 W- P- C2 k: X3 E1 `2 q
                        lowpass_filter[0] = output;: r$ v3 n$ N8 s7 J# u0 V
                } else if( nFilterType == 2 ) {3 A8 A+ r  z% A2 F: U5 `( o! ?
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)9 ?1 n0 {' @4 y6 K7 ]
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;7 m2 _  L) \5 Z* L7 B' [; f/ P5 z, n
                        lowpass_filter[1] = lowpass_filter[0];/ k  n: o: u( J% Q0 L) z  P
                        lowpass_filter[0] = output;4 ^8 D" L, @, W- D! C8 X. i
                } else if( nFilterType == 3 ) {
; P9 ?# U$ _6 x. |* F8 o5 L# M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
9 O! E- h: Q4 {% j' k                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# g: b8 n! v- c; ^( m+ H8 h                        lowpass_filter[2] = lowpass_filter[1];* N! D( Y8 X/ a, Q' j: s8 c
                        lowpass_filter[1] = lowpass_filter[0];1 ~* c+ x& |% d) F1 b
                        lowpass_filter[0] = output;! T9 f9 I) p7 f* C
                } else if( nFilterType == 4 ) {
, N0 o+ c6 V4 M8 N                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! {9 J" o* Y" y# I( i0 f                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
* o5 |4 H0 V9 W9 c7 q; P                        lowpass_filter[1] = lowpass_filter[0];
% _' u4 o; i! r* t                        lowpass_filter[0] = output;3 ]  n+ N' x2 |
                }
5 _% @+ Z7 \; Y- p9 @
+ }0 J5 t$ [  \" Y6 n; i#if        0
  l8 y' z4 r# j, ?) N! G                // DC惉暘偺僇僢僩1 W# C* m" h/ Q9 Q1 c5 Q
                {
' n* m- j  B1 J& f3 W( @: z& G                static double ave = 0.0, max=0.0, min=0.0;
/ b0 ?6 k+ H: w7 N                double delta;
. s6 f2 [) }5 R8 {! d2 ?4 J' k                delta = (max-min)/32768.0;
+ |# g# e/ A# H$ B( D- E# C( U* {                max -= delta;
6 E; o) f. \( k* Z                min += delta;8 W2 t. E( b" y$ x
                if( output > max ) max = output;* I8 D0 ?7 H7 [  @% P
                if( output < min ) min = output;
7 S- ^4 Y; i8 C                ave -= ave/1024.0;
  k! c; e6 j# ~                ave += (max+min)/2048.0;
4 ^8 L  r0 h5 [+ G( V5 G2 v# B+ m2 z                output -= (INT)ave;9 t/ }' ~2 z' l5 H3 `: U
                }3 L5 d; L1 h+ W9 s9 z% |+ O* m# \' d
#endif, f: t* e; ~( p1 E' z
#if        1
3 y1 |; P1 @6 I1 c0 G3 d                // DC惉暘偺僇僢僩(HPF TEST)# w  S) p" g$ U/ Y! F
                {9 s! w) x4 n9 t9 J/ M1 o5 o! d5 q5 \
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! \1 e% P8 x9 L8 f                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 e6 @* x& W- _
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
( u; W2 N5 Z) W$ k: p                static        double        tmp = 0.0;- K, U$ H* [( A
                double        in, out;
+ K5 G0 Z9 c0 B. \7 v; H! d% \" i$ e( n6 g" F  j4 L
                in = (double)output;
0 x$ z4 A8 |. B! v: C# P                out = (in - tmp);6 A4 Z9 g* P( K, g( c; A! m
                tmp = tmp + cutoff * out;- c1 _: S. J1 J+ g+ R5 |' }$ I

7 u2 L0 }/ d7 F6 u/ [% `3 n                output = (INT)out;. ]- W1 W! `6 p9 \4 o+ c: C6 t# V
                }
# E" y1 l/ Z8 n3 a2 b6 Z; J( P; R$ |#endif7 y! M0 `: ~/ o
#if        0
0 q! p: }- K& p5 p                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
, D6 q8 }5 \; V( Y* E                {  v5 G9 L: X, c, L% @" \9 J
                INT        diff = abs(output-last_data);
8 p6 T) P3 K+ J4 y$ L7 @; j                if( diff > 0x4000 ) {! H6 i6 x8 H4 y
                        output /= 4;
' `& ^6 E6 a3 [" s                } else
% Q* C" l+ }4 n  }% w, P; a+ ]' l                if( diff > 0x3000 ) {# ?! p" R$ N/ b5 N# {
                        output /= 3;
$ q9 n" @" j6 k: `0 }                } else
% P5 Y3 A: g$ y: O                if( diff > 0x2000 ) {
- k7 W4 C0 T/ D- v- S                        output /= 2;
) @$ ^+ m" W' c2 s& X, t3 C" T/ Y0 ?                }, Q5 M2 L. i0 j
                last_data = output;& ?4 V6 N) Y- h# ~- R- r
                }
* |! }  B  H& x( Q- b7 m#endif* `6 Z8 _" f9 W% r9 B+ r9 `
                // Limit. c; K  E( n0 _0 _6 Z' G" D
                if( output > 0x7FFF ) {* |" W, {- B+ v8 [3 }9 F
                        output = 0x7FFF;& K1 f; }- c$ H2 v8 S' k% J
                } else if( output < -0x8000 ) {2 A2 r) ^; g7 @- C* l7 k
                        output = -0x8000;
/ n3 U' ^& N5 X# z                }0 Q. N9 U# ~3 i7 d: l7 h9 v
* q" x# {% a7 }7 q  K
                if( nBits != 8 ) {- C8 z8 z* s% h, L8 w" L) }3 A3 `! H
                        *(SHORT*)lpBuffer = (SHORT)output;+ T9 A9 a5 {  d. G) Q! z
                        lpBuffer += sizeof(SHORT);
4 h$ ^. S- f# d                } else {. _; u$ Q4 B) I, k) V; a
                        *lpBuffer++ = (output>>8)^0x80;
# m7 v8 t: B6 ^2 l8 n                }
$ r, G9 b2 Y3 y  n3 n0 Z4 W& _+ h) x% F; X
                if( nCcount < 0x0100 )5 k' F9 l7 d$ |3 z
                        pSoundBuf[nCcount++] = (SHORT)output;
! i& H- f. k  m! K2 h; \- _5 Z
8 }# _; B- v  u//                elapsedtime += cycle_rate;& d; i) h: @' }9 I+ d& A  E+ ~
                elapsed_time += cycle_rate;2 ?7 j2 b: b/ R% b; L
        }
& a; k7 Q3 N4 I4 |+ i! g' A: y. @% }; k
#if        17 ~* T3 f% M( x0 ]! X1 a' Z( {$ v
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 A; a% X* B3 H8 P                elapsed_time = nes->cpu->GetTotalCycles();
3 C/ a; _! h6 A. ^        }
( s( J& b2 W3 ^# O* b        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
' F3 c, W4 \7 X0 ?# W                elapsed_time = nes->cpu->GetTotalCycles();' p. ~3 A! _6 y4 R" A. V7 \4 b
        }: O  M5 o, K: a  T: V
#else
9 Q. W# ]2 c* i% _9 @% E        elapsed_time = nes->cpu->GetTotalCycles();9 Z; e8 L' L3 \2 w8 d6 {) o& Z* `
#endif) U; ^' B2 f" r$ M1 }9 T' O0 z5 Z
}
$ w/ t' Q2 r, S/ G) n9 f, ^# y. t% W7 [' P
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)( T9 y* ?8 g$ [3 m
INT        APU::GetChannelFrequency( INT no )
1 W7 X9 V' ^2 n, ]{" z$ n9 J5 {9 w" U, P
        if( !m_bMute[0] )& A1 p4 m. U, |3 C, N
                return        0;5 o' ]& \, |! I+ ?# G+ n

" \( l# M% _' D8 C' c4 O5 H& k        // Internal! r' R  n1 ]2 w# B
        if( no < 5 ) {
! V1 O) }5 H' {& Z- d2 T                return        m_bMute[no+1]?internal.GetFreq( no ):0;
  Z# Q( `: d) r* B        }6 L4 E4 }$ p. ?
        // VRC6) {8 h, m5 s' q# m$ U
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ G, x/ t" H& x* h7 c, {: e' k                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
, Z: O* W  {$ B! R( I* Q& n. N        }' R- P/ p$ _9 W% H" a* ^
        // FDS; e5 x4 X9 [4 y* l% u. N3 S
        if( (exsound_select & 0x04) && no == 0x300 ) {
; C; P" [# M3 m8 Q  i# o4 x                return        m_bMute[6]?fds.GetFreq( 0 ):0;
7 D" q7 T6 i1 Q        }
6 R/ l) }( F" [2 }2 G3 ~        // MMC5
# {) I+ @( ]! Z3 l; Y8 B1 r0 C& u        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {  b/ t( K: [8 Y) D4 D+ U: o
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;, R5 q' Q8 B( k9 S7 u& s
        }
* g0 M: N, g: z% }        // N106
, ?& [. g9 W3 j        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: ^  J2 \/ U+ f3 T. u
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  \" C2 r1 ^5 F( j        }$ e: Z: y( W, \0 s8 s$ M7 T2 N
        // FME7
* e" G7 y. \! o" o( \3 m        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {6 I6 ?" E# e1 T% R
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;+ A% f4 _1 E' h" k& _8 P
        }$ W4 V0 Q, ~! y! N% _& M
        // VRC7* R: }. f9 d2 n7 G
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {; I! N6 n  f3 D# J
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- @7 S: j5 J* b8 @# M3 u# w
        }
$ `0 R' c  ]; ?0 @- k2 w        return        0;
; _% A& ]' W3 ~( K; G6 O) F5 Z}2 U* c! h' Z3 F6 ^! }

% I' o8 c0 I. k. {& v// State Save/Load
+ W2 W$ y0 M$ G; i5 h% Qvoid        APU::SaveState( LPBYTE p )
4 g6 L- s6 d( ]. C" G" J5 W0 z0 k5 x{
8 R$ y; K% P5 w0 p#ifdef        _DEBUG7 f2 [: v# q! v! V% I
LPBYTE        pold = p;
7 x) C7 T! e9 \' b#endif+ j1 [# ^3 [# o0 t4 [2 f

# m. F- ~. O* o9 y( f' O# S        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 n* u$ Z/ B2 y# }0 I' `' H
        QueueFlush();* m# \$ P$ U$ n, P
* X6 e3 e- L1 W3 L% X1 s
        internal.SaveState( p );
! N; @" w, f" {8 ^1 L. O3 E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; J/ B" y* @0 Q. W4 X5 e# p0 Y& S0 [" S6 F4 o. E( J* Z, t* J
        // VRC6: |7 ?" A/ z0 K/ B. W, L+ @
        if( exsound_select & 0x01 ) {3 e) n8 S; P4 J$ U: j7 C5 R* |
                vrc6.SaveState( p );
# M# M. F- N% w+ M                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; G) I. Z9 K  M4 D3 H2 _
        }
5 v' a9 y* h9 N9 ~        // VRC7 (not support)
& r" y2 {6 W* s: u2 x# ]! H        if( exsound_select & 0x02 ) {
! h) n% T8 |- a5 w                vrc7.SaveState( p );
& m0 p0 s! z- H& ^                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, i4 D  z) ]$ y6 @* q; K        }
' a/ s, U+ ~& f$ ]1 d6 i        // FDS( N; V; Y5 T6 O9 ]  F
        if( exsound_select & 0x04 ) {' \1 u$ d7 b+ g% @" `' |: [; P
                fds.SaveState( p );2 j) y1 t% `; ?+ m( ?
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
1 \  x6 h6 |  L- o, T        }! M! M# j4 d3 W3 ?
        // MMC5
# t: c& [1 d5 h( c9 e% s4 z        if( exsound_select & 0x08 ) {
* e6 {/ D. ^6 x3 {+ i                mmc5.SaveState( p );
9 ?3 v! }% E% N# M4 V" A% h                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 u8 V" ^0 @5 p        }0 m9 H; y; b5 v& n4 c" s  `
        // N106. q: g, ^) X" x- l# Z
        if( exsound_select & 0x10 ) {) d$ o) L4 \- J. t- o: U
                n106.SaveState( p );
- u1 K2 [; f4 A2 `6 h2 {                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding: n! W6 _" \3 N7 U: A; u
        }
; Y5 |: O7 v- x# f: B- s/ L* o9 _        // FME7
8 j( O: @+ B5 \; h        if( exsound_select & 0x20 ) {# q6 n9 M6 }6 W6 ?' K6 M+ M: D
                fme7.SaveState( p );3 p# u- C. [, C+ R" ?3 A1 W
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. |2 p0 @& P9 z
        }
$ N2 _% S, p9 e3 n. f; \2 {6 `% W/ ^! r
#ifdef        _DEBUG1 M+ j% e  D8 r
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 B3 M# }7 U5 L" e$ H1 w#endif
* n: p" y, i0 ]: A6 M& S}
: z2 e' Y) t' l( H0 t+ P! _4 e& o6 Y5 M: d0 [/ W/ z/ C% ]
void        APU::LoadState( LPBYTE p )
: K1 V3 m2 b" i! {{
) M+ O7 Y" [' q7 l( r4 `2 W" _        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& }& `( o& B& L
        QueueClear();
( a4 y. {; T6 L4 Q* A7 P1 w8 E' _/ ^- P7 u8 I
        internal.LoadState( p );! \" d6 Y9 F% M4 Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
% p+ R9 x" T: k: y6 M6 Z
% r3 |0 C+ g1 L; j/ t: `        // VRC6
: ^2 n% H! F7 n7 G( S        if( exsound_select & 0x01 ) {
" Q# B  B( @( g                vrc6.LoadState( p );
- |7 {& Z5 V2 o! d5 Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. R! `4 L3 y! J. H, K
        }. j9 u; J: A6 C& [  u6 G
        // VRC7 (not support)4 G5 ?, a/ T6 Y# A
        if( exsound_select & 0x02 ) {
- M6 x4 S) i! a  |                vrc7.LoadState( p );) [# A6 T: \/ w7 ^8 N
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' u3 ^- p. ~" ?' Z        }
, G$ m  z) r- p        // FDS1 N, v3 t2 J- U6 B: ^! j( E/ P) S' n% C
        if( exsound_select & 0x04 ) {3 _2 D: K' R% M
                fds.LoadState( p );
* g& U+ ]  o* O                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- f. N, }$ |3 j/ o4 H        }
4 ^9 g8 b6 k/ h0 `2 E) o" ^, B        // MMC56 T" F7 M% L+ v$ q3 \" N
        if( exsound_select & 0x08 ) {
: |: @  V) B) l: b4 L                mmc5.LoadState( p );
0 H: g" m3 U: h4 y" ]                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 L! `  H# L  ~/ ?0 f$ Y
        }
- ?! `, \  Z6 e3 I- i        // N1067 A  }7 K/ f" d1 A" t; L
        if( exsound_select & 0x10 ) {
0 a' X5 N3 J* |- P( `                n106.LoadState( p );7 c. L, K% q, ~7 Y+ D2 {7 ~1 a2 Q. D7 f
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
% L, G9 L3 z! B( |. `8 N        }/ C3 @/ M$ M0 z  `& @
        // FME7( O7 l1 {; U6 M  Z$ t
        if( exsound_select & 0x20 ) {2 e3 y8 w- c5 T  Q. u! D9 M
                fme7.LoadState( p );6 p: D/ P  t- u
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  q9 N' C7 [! q% c9 O        }; y+ ]5 J: W8 @  z7 V
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
# y, ], h2 N- e8 ^: E& r可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
7 w& D/ N: }% o0 V" T感激不尽~~

  E1 w. V: |! q2 ?9 }; O: c恩 我對模擬器不是很有研究,* U- d2 U7 q/ h, y& X
雖然要了解源碼內容,可能不是很困難,
; M$ |- O7 y; o不過還是要花時間,個人目前蠻忙碌的。
" @  x- v: X2 p- K  H: [) K" J5 B* i: W; N$ u* q$ u" U+ {
給你一個朋友的MSN,你可以跟他討論看看,
5 L! N* N- F5 Y: f2 v) b他本身是程式設計師,也對FC模擬器很有興趣。2 [+ h  |2 t" p3 w4 j1 R. g

1 j- T1 Z- }/ m8 @MSN我就PM到你的信箱了。
* P" X, w& n  o( U6 d+ x" R9 T6 Z0 Z: u2 s( V/ a( |
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* P4 q! u, K0 d0 G呵…… 谢过团长大人~~
7 _; n1 N  W" N3 B. r
2 |! p! @/ u4 _) }* L
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 v& h  D7 @0 ^2 x& s- B团长的朋友都是神,那团长就是神的boss。
$ R4 g' ?' t! `  h
哈 不敢當,我只是個平凡人,3 H; z( u6 I8 g2 K
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙* _, y$ y: n# F. m
ZYH0 @9 x4 x. K  B' T' T/ |$ ~* L
QQ:414734306$ ^5 g2 v0 R) ~* {! y
Mail:zyh-01@126.com  W5 ]7 t/ @; j% ^1 }

1 w' H' P* V  s% Z( M" L他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
, ?# E9 b, X* W# C- F再次对团长大人和悠悠哥的无私帮助表示感谢~~
5 z$ o' }& ]( h6 R
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-8 02:45 , Processed in 1.064454 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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