EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
4 u# v1 [, H/ f; n6 [$ }2 s. P+ QPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* t3 d1 h0 V* O+ R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* ^1 x" t" Y/ }; \, U9 R1 j这里有相应的模拟器源码,就当送给大侠了~~
! T* i: ]6 q" ^+ m7 O9 K. Q" j6 dhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; \) T! N5 C0 O4 T) C
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ ^3 l2 x; l2 ~  _  ]7 ^$ J6 d
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  T5 X. U( M' M) F4 t
这里有相应的模拟器源码,就当送给大侠 ...
% E, W8 Q+ R, L  v! q& t7 S1 i! l
聲音部分(Audoi Process Unit = APU):: L0 j0 Y7 U( _3 j+ _
.\NES\APU.cpp, K6 Y- M- D+ e' d; G6 M7 A3 G
.\NES\APU.h
3 o, Y7 O4 s! y8 L: P; X: I/ F1 `4 x% y: P" o4 E

2 `, y  P+ U- X, g7 B影像處理部份(Picture Processing Unit = PPU):* O' ?% ^# s. J& ^; A0 B
.\NES\PPU.cpp
- N6 ^% g4 C8 y+ W. q( N4 Q.\NES\PPU.h
- s' x6 a5 _( ?5 i4 d7 l0 j$ N- i2 d/ a& a2 r6 J3 _
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:4 y7 C( h$ n/ b* j
(由于很多专用术语和算法机理都不明白,所以看不大懂……)' ~( M' Y) E& z9 T7 b" D$ U5 z5 }& h: L2 q
//////////////////////////////////////////////////////////////////////////7 \/ n. u0 X9 V: s, H: k
//                                                                      //5 t5 I- @2 O. l% O  U; a
//      NES APU core                                                    //
6 u7 b! ~1 {7 b5 c4 P% l//                                                           Norix      /// w- C: R8 @, z
//                                               written     2002/06/27 //
5 g0 Y9 N: |9 R' b* A7 ?//                                               last modify ----/--/-- //4 x; h% ?1 X* S  X# T/ ~' z
//////////////////////////////////////////////////////////////////////////* s8 Z7 Q! x. X% A- r6 H
#include "DebugOut.h"
5 I2 m6 z$ n' g5 n#include "App.h". D% ?0 ?6 Y0 T, ?. I
#include "Config.h"
4 U3 a$ {, J; ~! k
4 f3 g5 r8 z* n' A: E5 D# U9 w#include "nes.h"; k) f1 I/ _9 e! r
#include "mmu.h"
. H- X* u4 r& b7 E+ m0 ^#include "cpu.h"
; w0 |7 a* h4 O#include "ppu.h"0 F* v  `3 O$ j+ P. y9 I+ @
#include "rom.h"
) m6 C) F+ B# c! E3 H) J#include "apu.h"
  X- Y( A& a  }8 F7 B4 m* J5 \! {: R0 Y# `" ?/ O  p; j
// Volume adjust4 e$ C2 K- l' Y
// Internal sounds
  U: H; q. @: |#define        RECTANGLE_VOL        (0x0F0)
% O- ^. O! U  C; P" s% C1 x5 u#define        TRIANGLE_VOL        (0x130)+ W4 x& o% Y) H8 {5 ^* U
#define        NOISE_VOL        (0x0C0)8 L# k6 ?7 W5 c4 d& D  a: v
#define        DPCM_VOL        (0x0F0)
6 n2 ~6 y; C8 |; e// Extra sounds
7 m( G, s. P, v! ]( U#define        VRC6_VOL        (0x0F0)4 N) R2 c1 M3 x, \5 e
#define        VRC7_VOL        (0x130)- b5 Y5 Q: B; N5 _) C
#define        FDS_VOL                (0x0F0)
1 u. p# ^- \, t' w' J. S: R, e#define        MMC5_VOL        (0x0F0)" ~1 V5 W, Z- g
#define        N106_VOL        (0x088)  o+ k# l$ v! D  f& u
#define        FME7_VOL        (0x130)1 s. r! c$ B+ v/ C. M7 X
7 u: G" a9 f8 t8 c
APU::APU( NES* parent )
$ D3 D1 V0 V: G$ a{
3 I, D* O  v' A" U# s        exsound_select = 0;1 C8 _. G+ o' \$ _

8 m) {3 `+ [3 V8 J' D        nes = parent;9 E/ X3 F- k9 E* r2 n
        internal.SetParent( parent );
' {$ I; {3 L. Z! b7 T* \* |+ [) y/ C. l$ J
        last_data = last_diff = 0;
8 u0 z5 g4 m2 y7 m) K
8 c$ b: I% z$ g$ d# s5 @        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: T+ Z' Z* k1 m0 `

6 d' H8 B. X: h+ s6 \% |        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );  P0 f. y4 N: f3 V# Z
        ZEROMEMORY( &queue, sizeof(queue) );
: d" S8 S2 R- X0 [        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 r% P$ a" `& [( V: E' o/ g# [1 V" y9 y8 k
        for( INT i = 0; i < 16; i++ ) {
0 `; ^3 r8 X7 z& e                m_bMute = TRUE;
2 x5 ]& L' k4 B/ y3 Q4 e1 W        }
5 g2 y) q- @4 b2 A$ r8 w}7 a4 y3 P' G7 i7 J8 R$ e5 i

' ~9 S% [6 c" a+ }% g9 FAPU::~APU()' ^4 t; _0 H) S, K/ x# O
{
; I) ?2 t. m+ w1 b# J4 N* t0 T3 x8 ^}4 ?5 L/ H& R! w6 ^' ~; V/ t% z

$ ]& Q$ P( Y, Q, u9 svoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
! ^9 X6 N: H% _1 T. }7 F4 L{
7 |2 r0 d: x0 ?! C$ a' H3 X        queue.data[queue.wrptr].time = writetime;% O6 }8 ^5 p' F. z, ^* O$ ]
        queue.data[queue.wrptr].addr = addr;
+ }  _* T! ^- S! T# n5 r7 v        queue.data[queue.wrptr].data = data;
, f+ O$ G6 J4 _7 n7 S7 z1 q0 O        queue.wrptr++;! g0 P  w2 t( q) M
        queue.wrptr&=QUEUE_LENGTH-1;
3 e0 |: o; A/ m2 F        if( queue.wrptr == queue.rdptr ) {& E) m' D# A; U+ M" |* T* d, B. B/ J
                DEBUGOUT( "queue overflow.\n" );
+ e3 F" H7 ?1 @, U( i4 X! D        }
8 o! t. m/ C9 s}
) }2 C6 t+ o1 m2 M, o/ k; X$ A. ~1 X# T& Y8 a/ Q0 D
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  }+ y' v7 s, c{2 h3 \$ @2 Z$ |1 F
        if( queue.wrptr == queue.rdptr ) {2 Z7 ]: l: d# K. A9 q
                return        FALSE;
0 r& E9 h% r* c8 S, }. M, Q        }
' @" b' b; Q% J5 G6 n  g        if( queue.data[queue.rdptr].time <= writetime ) {( L* Z8 m% y; I  u. K& T2 m3 V
                ret = queue.data[queue.rdptr];
; t7 U, k3 b# ^. y# T! Y! O2 G                queue.rdptr++;0 |2 o2 J7 X# A7 V
                queue.rdptr&=QUEUE_LENGTH-1;' U9 b* d" ~0 g* I3 _9 }8 `! L* L6 A
                return        TRUE;
3 V# t  y( a3 Y+ F3 ^& i        }
, T) f  F& F) [9 S" i. z. r        return        FALSE;' @9 K- ~) n7 v+ D9 Q% p1 A4 l
}% @. \0 v! t! _6 @2 n1 c

; C. C2 |- b- T( Y, s1 Gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% j  o2 }: H) S0 T3 m
{
& L$ H9 Q1 _8 e( @& h  O% N        exqueue.data[exqueue.wrptr].time = writetime;
# `, \# u# n* X9 j9 p- n/ B        exqueue.data[exqueue.wrptr].addr = addr;
; x6 R% D' R* S: `- V        exqueue.data[exqueue.wrptr].data = data;
( Z) p  d4 P& p" D' b" ]$ r" F2 c        exqueue.wrptr++;
* K2 N; V1 D$ g; ]7 Z* M- \3 y        exqueue.wrptr&=QUEUE_LENGTH-1;: @6 [) Z6 q2 k# G% E
        if( exqueue.wrptr == exqueue.rdptr ) {4 J+ e! ~& k8 P) p  M( P5 p* Q
                DEBUGOUT( "exqueue overflow.\n" );
; n0 y" t0 L+ E2 }        }) F& W! N6 v  M( k( n
}
6 F9 f, D  U& G. ], z; b- c5 F' n( q
5 Q# P9 y2 v8 O& ZBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )' X/ i. N) z3 d) h$ y2 S- D  w
{1 f% X) e  H' Z5 c' o! ?" x3 [
        if( exqueue.wrptr == exqueue.rdptr ) {( G" Z$ L9 ]: b; U7 H
                return        FALSE;( q$ F( v) \# y. j6 ?0 F
        }/ S$ a% H1 k+ v# Y. i
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' O0 O( _* x& \: N. j
                ret = exqueue.data[exqueue.rdptr];- H. B& |% {. V* V' V& ]
                exqueue.rdptr++;2 c5 Y% i* O$ i& l$ n& Q
                exqueue.rdptr&=QUEUE_LENGTH-1;7 O; n% Z5 j' g) b
                return        TRUE;$ f! I9 m) ~2 a* {* [+ @0 Q, r. @5 b
        }1 y+ Z( _6 Z5 h" T
        return        FALSE;
6 G0 z- l/ X/ X" E# B}- J" E" X0 C. E, V% X' C. m

; r8 ?7 B( |6 R6 E0 N0 Yvoid        APU::QueueClear(); e* q  T8 G' ], U
{$ S, ~' ]& p: p: I/ z! e
        ZEROMEMORY( &queue, sizeof(queue) );" q. ~9 S' j, J6 x5 X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! @. [* s; V. J9 ^) r
}
8 z/ }) w1 D' t; K$ |% @  E% \4 }. D3 R9 @% x0 r4 b; X
void        APU::QueueFlush()) j8 h$ I* w  ~4 w9 k& D" m) L) W
{  h* b$ L! J1 Y! F
        while( queue.wrptr != queue.rdptr ) {" _4 P3 K) e: t, N! z5 E
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
, w0 Y5 ^+ g; `/ Y3 k0 h( ^$ c                queue.rdptr++;5 i8 E; d1 j! ^1 x* s( y
                queue.rdptr&=QUEUE_LENGTH-1;
0 q* o: g0 a* c% q        }
9 v' v1 }: |0 e# x1 j# y3 [' C' a7 A: J) C- r" e+ C
        while( exqueue.wrptr != exqueue.rdptr ) {
2 i7 j* X9 ~- W" {                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );; g& E  S  g; j# U6 l" I
                exqueue.rdptr++;
/ i. \& l$ r! Q3 T0 _                exqueue.rdptr&=QUEUE_LENGTH-1;7 i4 K1 v& b' y- w7 Y
        }
. U7 h$ T2 [/ V, {( S}& t4 F" Z' V& L( _! `4 ]
) u: U$ N, ^1 b/ E1 s2 j1 W8 @: F5 u
void        APU::SoundSetup()
) u* e. W/ B+ \6 d0 L2 m# D. u( Z{0 K" W- B# ]* |1 x' p) C; _
        FLOAT        fClock = nes->nescfg->CpuClock;% E3 {6 ]* m" o7 U. L1 J
        INT        nRate = (INT)Config.sound.nRate;) _7 ]  e3 L6 D- {! n3 m) [- v
        internal.Setup( fClock, nRate );- X. I& o, A$ Z" J9 w1 h
        vrc6.Setup( fClock, nRate );5 o; x. \' C+ R
        vrc7.Setup( fClock, nRate );
2 p$ q2 f6 l% w0 k! H$ s        mmc5.Setup( fClock, nRate );# A& F) R( F/ S, _: v! S
        fds.Setup ( fClock, nRate );+ H& r2 H! i& C) ], F! e! J, A. V& ^9 Q
        n106.Setup( fClock, nRate );
' H: }: c$ Z: C7 E& b. o$ c8 [/ j7 h        fme7.Setup( fClock, nRate );
; g2 `9 d0 B) k- ?& b}
* H- a* [% O. A8 r# ]8 }# n! _& Y( L. D
void        APU::Reset()( H' C  `6 G& Z7 w  K
{6 _  }, G& Z1 G# j7 K
        ZEROMEMORY( &queue, sizeof(queue) );
. t% P6 i# N. p        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 ]3 g1 R% F0 T5 C: g  b
) [" k( v! ^+ {: Q. `* w9 r        elapsed_time = 0;4 y# P/ A+ [, t5 t# a7 x
* z7 @+ l4 g1 a0 K$ q& ~% B
        FLOAT        fClock = nes->nescfg->CpuClock;/ L( y2 s3 ^! q1 l% z
        INT        nRate = (INT)Config.sound.nRate;2 F% n: G% w1 }. A$ b( {
        internal.Reset( fClock, nRate );
" [0 ?, L) g" e        vrc6.Reset( fClock, nRate );# u# I( X4 o( ?  e
        vrc7.Reset( fClock, nRate );
& W1 p+ u: X8 Y0 x5 I2 [- F$ R        mmc5.Reset( fClock, nRate );1 ~) c$ r( u3 g
        fds.Reset ( fClock, nRate );
$ B, l1 }, X3 P% ^5 u8 @  }& m        n106.Reset( fClock, nRate );# f4 m% V4 j8 A  F0 Y- ?. D
        fme7.Reset( fClock, nRate );/ ~; _! q; E% Q& D4 N+ X" m( W

; ?2 I% N* S8 f        SoundSetup();6 L5 a1 F  H8 h9 w- c% @" F2 N, Q
}0 m' V# z" p! Z) O+ W
/ }& g# a  i) r+ }# z
void        APU::SelectExSound( BYTE data ): u" i) v2 B0 G  x" Z
{
0 F7 e2 v2 Y; Z: Y! _7 X5 h' L        exsound_select = data;9 |3 S9 L8 f  x; h0 x$ y4 A; J
}
  h* m! s$ v$ o  I. R( L2 ~
! W+ B) g* [' C: N# W2 s. f5 B1 Z% WBYTE        APU::Read( WORD addr )3 }& Z# g8 B0 E6 [% W
{
. U( w" _; m4 z# I5 U+ W' c        return        internal.SyncRead( addr );
3 u, G' ?# r* U& j6 t  ~}+ O* P9 {5 R- y8 m3 s6 k' l

- N7 w1 V1 d. f+ a" Ovoid        APU::Write( WORD addr, BYTE data )6 N$ U% s' W( A1 D
{3 U+ X; {! s" A8 Y- A
        // $4018偼VirtuaNES屌桳億乕僩7 }) P( O9 f! C: c
        if( addr >= 0x4000 && addr <= 0x401F ) {! Y# T& A; Z# m
                internal.SyncWrite( addr, data );
) y, e3 G% @6 f2 D8 u) n                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
8 g: p4 Z5 B! x  [) [+ w/ g3 n; ?        }; h4 m" Y$ Y1 j7 f! r
}
  x4 O" S, x$ `4 I* _. `. A7 k( T
$ w2 ?0 d3 h( ^2 f# IBYTE        APU::ExRead( WORD addr )2 D" V0 m8 y8 ~( G
{
+ g0 M# A9 @6 o4 U( z/ yBYTE        data = 0;
5 N9 x1 e9 ~2 t/ |$ B5 i6 N9 ?1 b0 @! R; u
        if( exsound_select & 0x10 ) {
$ a+ P+ r) `; r* t) a7 {9 `) D                if( addr == 0x4800 ) {
4 y3 r: A4 y# `3 g                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );( n" `' ~- X6 [0 |( v
                }9 }' X9 @$ ^4 Y9 i
        }
% q$ @6 i& ]  H        if( exsound_select & 0x04 ) {3 M* m9 N8 Y9 D
                if( addr >= 0x4040 && addr < 0x4100 ) {5 r0 U% p, \$ ~6 o0 g: L5 x7 D
                        data = fds.SyncRead( addr );
7 t* c4 A+ d" ]* Q# a2 B4 r                }
7 o' r5 j) q, A5 W5 h0 H- B' ~        }4 q) d3 P4 ?6 D; s
        if( exsound_select & 0x08 ) {
4 U. A" ^: x3 h$ }                if( addr >= 0x5000 && addr <= 0x5015 ) {
% y) u0 W; ~& \, W8 x, x! N                        data = mmc5.SyncRead( addr );4 u2 c5 g7 L: B& ~5 k% d
                }+ i$ h: u* ], z' Q
        }
7 Z2 v; T9 ?6 Y' v- P& D9 ]& K# c( g% j
        return        data;
8 p, q0 g. C( a% e" B# ^}
; \$ ?. v+ {2 a$ ]. W/ r# C) s  {5 s1 C* ?8 Q
void        APU::ExWrite( WORD addr, BYTE data )9 X7 l+ y/ @$ d/ R; E5 X
{
( Z. U. x$ g* z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
' B$ h( [$ e6 [6 Q8 ~3 Y, ~5 R) w7 e
        if( exsound_select & 0x04 ) {/ g1 g$ u" T& B
                if( addr >= 0x4040 && addr < 0x4100 ) {
# y7 v! M, T% z% R+ O6 D/ W                        fds.SyncWrite( addr, data );9 B& E  F& q$ N
                }
- a5 ]8 ~6 e( J0 L# g        }
! ^6 a' m- }2 V# c7 v! g1 x  ?
& |9 T/ ?4 R" [" U$ j, ?" }        if( exsound_select & 0x08 ) {0 X% r& p3 C' h( r4 F# T
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: C4 y3 x$ K/ @- B" ?8 d9 q7 f7 a                        mmc5.SyncWrite( addr, data );
: r& y3 A0 L* [8 \, ^/ S                }
( m5 b7 a; Y# ~- ~. y! T& H        }" R, Z' j9 a" V  {
}
; k+ v4 s( D& Y  |5 n$ t+ e7 w+ r0 c) {' Q8 Y  h
void        APU::Sync()+ u0 C% y( s5 B" m* k
{+ O4 j$ V* I& t) k$ C* G. s
}: I5 n( h2 A) v$ z' `
6 m. [* A7 o. Y" T  S) b
void        APU::SyncDPCM( INT cycles )
& R2 A1 {# e. y6 d0 r6 x{
$ ?- @4 t: z) H% q3 [$ ]& O# I        internal.Sync( cycles );1 v5 E8 @2 J: v  v+ i
6 |+ M: @* t9 Y  _% B
        if( exsound_select & 0x04 ) {$ ^2 R2 _  v7 X+ |, A
                fds.Sync( cycles );
( o1 f. q! j  x6 I7 K        }
; P8 }2 P" y1 r6 [- {" z        if( exsound_select & 0x08 ) {
. A) Z2 n' ^, {' o                mmc5.Sync( cycles );" Y1 H  n" N7 @  `* r- x1 Z1 v( ^
        }
/ ?) o) L3 N" v% K9 I}
; C) i' Z+ J. H& V1 l8 |: p1 |, H- x* y! s
void        APU::WriteProcess( WORD addr, BYTE data )
: O% B7 j$ C2 z/ x* z& k{. V0 {- K8 n2 }5 q4 W5 h  o9 x) G+ v
        // $4018偼VirtuaNES屌桳億乕僩8 O$ i6 g$ e) _
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 Z4 X# h$ I# N0 p. G7 R                internal.Write( addr, data );
9 O+ n0 R$ d) J/ I+ O0 i        }
2 n1 ]% o1 s% m8 ^' A7 e6 P}
; a( O1 j0 L! y- O- H9 [8 b3 t* K0 i, a* R8 x  u  {( I' l
void        APU::WriteExProcess( WORD addr, BYTE data )* c2 j) K/ m/ V  W9 O
{
4 ~1 J2 }/ j0 q! ~- M, h- s0 y2 t, |        if( exsound_select & 0x01 ) {
9 O" i4 [9 ~  f9 E* x                vrc6.Write( addr, data );
% f: \  v' V& Q0 V. |3 N        }
  {, d4 l  U; n' D% s/ ~' E        if( exsound_select & 0x02 ) {
! V, @& r2 h; y; B& D* a5 h0 j                vrc7.Write( addr, data );
' q9 G6 h! V3 z- c: K        }
: c  G: Y- }) J$ c        if( exsound_select & 0x04 ) {- |6 \" p" o0 _! u
                fds.Write( addr, data );
! a: h5 `, z4 ?7 `1 l7 H. ]        }: v/ D' ?- J' c$ ?) _, }
        if( exsound_select & 0x08 ) {9 Z4 p" O+ j7 f9 g4 u; ?
                mmc5.Write( addr, data );
- Y  h3 o$ U" o/ U5 d; P        }6 e% [1 n  M& W7 V+ f# \
        if( exsound_select & 0x10 ) {5 |# }1 C- \2 i- J1 [$ o4 w5 p
                if( addr == 0x0000 ) {5 c; D4 q8 B" G! V
                        BYTE        dummy = n106.Read( addr );* N2 i# Z& `4 d
                } else {/ Y1 x/ D# F9 t% ~
                        n106.Write( addr, data );
0 F' p) }( k! D, O  j: K/ M                }
6 D9 z, P# b; c7 Y: y4 u        }
/ T! @6 T" y' x# D        if( exsound_select & 0x20 ) {3 S) V! m# x! U
                fme7.Write( addr, data );/ f; i* }# N7 I7 i. @
        }
& ]5 j' U6 |( l- p: ]+ Y, q% u}
. `1 z; `4 C5 g; v, p! |' n2 N4 b. S) G
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
; t! ]  s4 Z7 B+ K0 ~{) _2 ~" D; J( H$ j2 u& L
INT        nBits = Config.sound.nBits;
2 `, n9 v$ ?" M& hDWORD        dwLength = dwSize / (nBits/8);
+ V# s8 E" W/ g9 y. h. M( jINT        output;
: X) `' B1 o+ H7 ~# }QUEUEDATA q;
2 T* [% \1 O: FDWORD        writetime;8 t" |0 q$ A0 j+ [

8 i- l- U* n* R- Q" A6 v1 _LPSHORT        pSoundBuf = m_SoundBuffer;
; L9 g0 y1 K: BINT        nCcount = 0;8 h1 T& w2 T2 C3 K" L7 ?. W5 [
6 _, S% p& y4 R( u
INT        nFilterType = Config.sound.nFilterType;
- N. c, h& g+ W' v. l% l! L$ H- k' j
        if( !Config.sound.bEnable ) {
, V) o9 ]- I# U# d                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# _6 n7 X& n* `' d# r                return;
# d' ]+ Z, Q0 N* q, E  ^( o        }! k: W# Y% M$ p7 q
; |4 _1 i# P- G
        // Volume setup
+ f" g% J( O7 X, A( t8 I        //  0:Master
- e. L3 E! v1 k7 b        //  1:Rectangle 1
/ x# `" ]" \$ c2 n, l        //  2:Rectangle 2
5 l% }" F0 T) b3 z% g; @) R4 e        //  3:Triangle, \6 h  F, n: T3 z  R8 k7 c
        //  4:Noise2 S! b) g" W' R& P% i$ J
        //  5:DPCM- s! T" |9 s& v5 |3 ]& b2 ]
        //  6:VRC6" c- y4 N+ N: S4 _6 l
        //  7:VRC7
7 M& N+ H9 m7 M8 u, h        //  8:FDS
9 _0 S. n8 C8 Y$ S; F& I        //  9:MMC5
8 @5 _5 \( P# e        // 10:N106
3 _- m2 N9 b/ ]( ~# E% E" l$ w        // 11:FME7
( d* K1 i1 x- x5 D( w2 h- U8 W2 ]. x        INT        vol[24];
# c" z3 ?) t0 V        BOOL*        bMute = m_bMute;
7 q8 Q' |% m4 s' w& j9 u        SHORT*        nVolume = Config.sound.nVolume;
& k: D! Z0 M. e1 _2 |& d& l' N; _3 \! G1 G; x
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;2 @2 |1 j3 v4 I- n. s( o

0 C  z7 a# ?) \$ ]        // Internal
4 |0 u4 Y8 O7 N9 C- M' ]9 v        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;! G0 @! b! R4 {8 K4 B2 n( Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;. a% v7 l! u5 {1 L$ b
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;" M4 j. ~+ Z, O$ q% H1 o
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;, d- S4 R8 _; i
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
" r5 U" V* c$ i+ K6 o' ^
; b. Q$ k, x1 o        // VRC63 }% _/ a- d& F4 Z3 V$ v
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ P, j4 F3 A/ `: I1 i5 x9 x1 |        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 V; ^/ E( b: @8 Q6 I# Z
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! Y5 O' a! E9 G8 f0 }# Q; i

8 E7 W- e: P6 L1 Z9 _& L$ q        // VRC78 A) A0 [, H" n: d- m) m! _% w; I
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% K0 {$ W1 |  H- I) w" k. [3 W
& G5 P9 J1 v9 X& `" J. H/ S
        // FDS! M; n3 p& u( V/ \! t
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 w' l: J. A% g; r% V& P3 k" y* q8 M: b- p- H3 j
        // MMC55 \/ R5 s- m; \1 k6 m
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( ~( [2 I" }1 G        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 Y% S! B) s; a* E4 O' v        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& H$ f/ M. m' o

3 k4 J! X  r8 d        // N106
1 U6 e$ N: }  ~9 E        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) Q4 z( t; W# |/ L. B& G7 G
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 A0 V* V$ M+ ]+ B( j: h% l        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! }, w8 {0 T: }5 k        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 |% o+ e6 L2 b5 C8 U
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% u: A3 y+ v8 B8 F+ r# c/ L
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 p  N; f0 k1 z/ t1 q. t
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 H+ y. N/ _3 k( G) B# r& @        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; t9 x" U( e+ M& Z/ }
& y' N0 p6 Y$ k: E  a8 C
        // FME75 d  w* T  {  H! C  t: ?
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;/ z: A: ~7 E. M% @  c. h, u, [
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- d* B0 Z: ^. l. w        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  H- Q% i+ i3 u/ g; i: X: F7 [% W, @) @
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;9 `. q7 X& L1 |7 a" N
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
1 C! s6 F" i: B0 @/ ]  d
0 ]' p8 O0 ~% O  }) E! l" Q2 Q        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% h' a, t6 E# l2 E# e5 v        if( elapsed_time > nes->cpu->GetTotalCycles() ) {9 F5 W. P2 R2 Y2 F
                QueueFlush();/ p. u. j; e% p
        }
' c& y% q1 z  E' Z- e: g
" @8 z4 e6 N1 n4 Y; b+ Q5 B        while( dwLength-- ) {; I; d/ ]( h* i9 _
                writetime = (DWORD)elapsed_time;
9 p- z$ v* w) R; c- S/ I0 O
( ?5 ?+ a" X+ }5 R! J- K                while( GetQueue( writetime, q ) ) {9 x$ y( J: J% F6 J1 T6 w
                        WriteProcess( q.addr, q.data );3 B1 ]# M" P) t# T
                }" ~9 o, x: T- x& K

! g% v% ?: |3 {6 @2 O. `                while( GetExQueue( writetime, q ) ) {
9 I8 d) F8 T$ C                        WriteExProcess( q.addr, q.data );$ E0 M8 A1 f9 a: p" z% `
                }. J. \, X2 P3 G# f

, ?  ~% B0 x$ G7 b                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 W' M9 k8 T$ ^; x7 L
                output = 0;
' ?9 T" w6 U; T( J" \/ w. b                output += internal.Process( 0 )*vol[0];
; C$ s6 Z6 I" o" w: P/ _                output += internal.Process( 1 )*vol[1];# E7 B9 y9 Q' W/ H6 f
                output += internal.Process( 2 )*vol[2];
! T& \+ m' |/ a' I; D                output += internal.Process( 3 )*vol[3];# g  w; F6 @0 A  M" s8 ]
                output += internal.Process( 4 )*vol[4];0 c& E% {+ \5 h5 L6 }8 _, x/ W! G. e

- ^$ I& F( A: ?7 \! X2 H: y                if( exsound_select & 0x01 ) {
2 P2 i. c3 Y" g1 x6 ?1 J5 z, J                        output += vrc6.Process( 0 )*vol[5];
4 [5 G6 g/ F5 J7 c                        output += vrc6.Process( 1 )*vol[6];' J3 ]$ \  D: b! t( ?* A* Q
                        output += vrc6.Process( 2 )*vol[7];; P3 C- L' c% K' T# r
                }
% |2 ~# ]' s/ i6 r; A3 p& ?                if( exsound_select & 0x02 ) {  N) W0 X) S( g! i, L3 h
                        output += vrc7.Process( 0 )*vol[8];
9 v* ^) Y; k1 x- S! u                }) ^/ Y4 h7 D5 W: {- _
                if( exsound_select & 0x04 ) {* i, E% S  P8 [
                        output += fds.Process( 0 )*vol[9];
, C9 ^/ d4 h/ d                }
6 L& L- V; t( @( k- D                if( exsound_select & 0x08 ) {+ C0 e& E# n+ C5 K
                        output += mmc5.Process( 0 )*vol[10];3 a8 j" C  K. v7 B2 z( [
                        output += mmc5.Process( 1 )*vol[11];
; t# a" T+ W2 X: {                        output += mmc5.Process( 2 )*vol[12];
3 ^3 p; b% ], I                }/ V( P$ Z2 U+ K7 R9 b& g
                if( exsound_select & 0x10 ) {
7 e8 I4 v3 P6 M$ l                        output += n106.Process( 0 )*vol[13];* o  G1 j  K9 s" \8 k2 u+ F
                        output += n106.Process( 1 )*vol[14];
3 b' {+ P6 ^" p& Y& S% q  K: @                        output += n106.Process( 2 )*vol[15];
9 r4 a! u" N& P& w/ t' J                        output += n106.Process( 3 )*vol[16];
4 T  h- R7 C4 ]4 h                        output += n106.Process( 4 )*vol[17];
- W/ [% H- p8 m: S$ V                        output += n106.Process( 5 )*vol[18];/ [& I; \& T) J1 t
                        output += n106.Process( 6 )*vol[19];( D4 A4 r. h) I5 I: u: e
                        output += n106.Process( 7 )*vol[20];4 a# j3 Y  b2 }: i/ M2 S9 Q
                }
: z( v7 g6 N8 v' q4 b                if( exsound_select & 0x20 ) {& `4 c& c6 D4 Z. o
                        fme7.Process( 3 );        // Envelope & Noise$ t: C9 W- r  r$ w! O
                        output += fme7.Process( 0 )*vol[21];9 ?% X2 O- N% ]. i
                        output += fme7.Process( 1 )*vol[22];
1 m/ o( G4 w+ ]# I3 ]+ e                        output += fme7.Process( 2 )*vol[23];
  I" `. `- ~4 a6 v/ ]9 n6 I                }/ j* H: t$ c4 N! E  X0 x
3 c! x6 i& m2 b  E
                output >>= 8;
  s1 A+ |2 F+ x, y+ w/ o: M4 e; _/ K" k
                if( nFilterType == 1 ) {
0 o' \( v3 s: u) m1 Q                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)8 S0 @: L4 v- @$ d  A
                        output = (lowpass_filter[0]+output)/2;0 {4 J' y) Z# w; j* y
                        lowpass_filter[0] = output;
  |3 U8 _' v" @! G- k+ U                } else if( nFilterType == 2 ) {
$ l0 H! Z" Y8 U' k                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 F2 e2 t& y; F' C# @9 ^                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 f& f: q! B7 T% L                        lowpass_filter[1] = lowpass_filter[0];% a9 B- L4 D  A) I+ G  a- F- Q
                        lowpass_filter[0] = output;% G) @6 d- o9 m# Y( o% b) _- @* @; v2 N
                } else if( nFilterType == 3 ) {
% P' a6 j- p0 j/ \; x3 O2 o                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)1 P% Z8 F# S7 f. o  N' Y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
- n# e) Y% B& F' m5 k6 O                        lowpass_filter[2] = lowpass_filter[1];5 X- h$ A1 w% t' O
                        lowpass_filter[1] = lowpass_filter[0];
. ~" F, U* P) F+ G+ c                        lowpass_filter[0] = output;) o4 \, {4 S8 L- {, J# y
                } else if( nFilterType == 4 ) {5 K) J0 ?4 G3 I& T. J
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)9 V$ W% D: m0 g
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 Z; _1 |- f4 g, U
                        lowpass_filter[1] = lowpass_filter[0];9 A5 O* O* `' `7 @
                        lowpass_filter[0] = output;' O, m% {( p* P' y0 m
                }
- D2 y- ?% E6 t) Z+ z" j% o0 F# M- m) z6 p5 v' S
#if        0
1 r- E$ U) f1 p, Y; V( R, V9 l9 \                // DC惉暘偺僇僢僩
0 {0 R- h6 Y; p8 k7 B5 U                {* v, Z! x9 o9 q  d( r* a; A
                static double ave = 0.0, max=0.0, min=0.0;
% ^. ?: N9 b' W3 b- F* e                double delta;0 o2 I& F% v5 b: K+ r( [8 J
                delta = (max-min)/32768.0;
7 \) Y! n9 e0 n9 i/ P+ \                max -= delta;
$ s3 Z, I9 a  Z. W; Q                min += delta;
, w" ]9 r  L$ d; d! n% q, A4 R                if( output > max ) max = output;
' N0 e7 s/ N* {. F1 O; S                if( output < min ) min = output;
. o/ d) s( L5 Q0 ]! C2 _' m) ^3 K0 c4 I                ave -= ave/1024.0;
3 V; ?2 S& k2 }; K2 ^                ave += (max+min)/2048.0;. |2 C$ i0 E0 `2 ?, x, H) X
                output -= (INT)ave;8 W  ~$ |. T+ w& E7 f6 o
                }. }: u% q4 M- [9 S
#endif
- A" M9 v/ s- p* Z#if        1& c; i6 }4 S5 H) v- K0 K
                // DC惉暘偺僇僢僩(HPF TEST)
" h/ B3 A, O8 A7 K5 u# A6 G                {
' [' l( T7 R# q+ H  I9 p0 i" x8 b2 G//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);  m- Q/ c4 X8 s+ P
                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 M6 {! ~- d5 {1 ^) w
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 n- L! J3 x; _0 o                static        double        tmp = 0.0;
" u1 t3 O4 G0 Q0 ?( O' i                double        in, out;
; d0 a0 y4 d/ }  C+ W( S; E3 j0 J7 j& t7 e+ n4 |, t# I! R8 S9 V0 z  o
                in = (double)output;
6 V$ H7 I- [- Q, T                out = (in - tmp);! v  g# A2 v# U& |" u4 U* b
                tmp = tmp + cutoff * out;- n. }- J4 A: c6 ?; o

3 r" ]; r: g, D' @                output = (INT)out;
. L. Z! z: G/ `( a                }
8 g: M2 \. D4 c; F# S0 J7 g; x#endif) {- _' J/ Y9 f! b; s: r  r- W
#if        0( W$ w. n6 r9 v* E' \0 B3 Z0 d
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)& I0 X6 j. D+ X& N. Y" I
                {
* V, [+ \1 {, k                INT        diff = abs(output-last_data);% }$ i: X9 j. B( f* b& K, E
                if( diff > 0x4000 ) {" F, u% G: F: h5 R7 H
                        output /= 4;
* q: Z  j* H6 A1 {0 s  T                } else
. ^% b4 h# @! k* J* @! d                if( diff > 0x3000 ) {
% o# J3 e! P7 H3 A' U# J                        output /= 3;# M2 ]0 A3 \. c; R  n
                } else; o: q1 p  O  e# A) i" F
                if( diff > 0x2000 ) {* U) ^1 S" C, H, |% N/ l  u
                        output /= 2;% z4 X' d1 j  D4 U
                }
) B# J( L& r0 F0 c7 [+ f                last_data = output;
7 d* j! R$ H& U- `                }2 z$ ]/ {; n- r, |4 L" a
#endif1 G. ~* q) j3 J8 Q7 }; D, a8 {3 l4 E
                // Limit
. x' o2 W  I' ~6 g6 o0 ?                if( output > 0x7FFF ) {
/ v4 f5 G, V! q" G( ^: Y                        output = 0x7FFF;/ M( \$ W' Y, ^2 }/ V
                } else if( output < -0x8000 ) {, D8 X6 G. t, [3 u( f
                        output = -0x8000;! L4 F. L. x) V" O; ^
                }6 c. ~) F" t1 \7 @. l0 v+ k

, z, @- d1 T# R6 H$ X0 a6 b                if( nBits != 8 ) {
' D+ H/ K$ H  \/ X8 W- |9 [                        *(SHORT*)lpBuffer = (SHORT)output;6 K* ~& h5 D4 k/ B2 f3 k) r5 G' D- M
                        lpBuffer += sizeof(SHORT);
# P6 A. S& i8 S2 |  X: O( O                } else {  X0 I: T# M5 H8 y: v/ O. C( {; K6 q0 O
                        *lpBuffer++ = (output>>8)^0x80;
/ F, \; W" Q# Q' _2 x                }
3 z" I+ x7 f: \& }3 Q
/ x1 Q- A% u8 K8 r1 ^" Q# V; \/ n- I                if( nCcount < 0x0100 )
8 ~6 d1 t# X' z: ]                        pSoundBuf[nCcount++] = (SHORT)output;
: N. P0 M! d" x: m( ?5 ?8 p; K# ~) E1 u5 V& e
//                elapsedtime += cycle_rate;# Y2 _# ?. n1 _# {# I
                elapsed_time += cycle_rate;
* B5 O, G. q* C/ U7 j" b+ |; Z        }; b% f: T# \# _) C0 @9 b
; e) ^2 v9 _  J) f: x- k
#if        1
% ~3 ^- K$ V& U( {" p        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 M% l. W1 ~2 O$ ^, \                elapsed_time = nes->cpu->GetTotalCycles();" e& u3 x( y. B6 u3 Y7 h
        }0 u; y6 v% @# G; u: H
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
6 E5 D4 `/ Z" W" o6 o" V! n$ ]                elapsed_time = nes->cpu->GetTotalCycles();
" @1 W6 Q( O4 T        }9 B/ g, E$ F9 l* {; O
#else6 q" j+ d, P# D2 R9 }6 M
        elapsed_time = nes->cpu->GetTotalCycles();
& [6 S' P/ x  B#endif  m  F0 B( \" G. ?# A6 t: j7 G
}
* E; L; @+ T" v) C" l; j3 z3 O% g% {$ k! b. J: m5 z
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
8 G: J7 f, q+ `! ]0 dINT        APU::GetChannelFrequency( INT no )
' U% d% M. Y6 k* e+ ~+ M{1 `9 A: N: H. k$ E* ^
        if( !m_bMute[0] )
0 p6 [: K0 w/ c$ p3 c                return        0;8 D5 y/ n  F$ G
1 J' ?6 |1 l6 D" A2 [
        // Internal
# n4 W# W2 }+ W- n        if( no < 5 ) {
+ A9 H0 m5 n, C0 a6 U                return        m_bMute[no+1]?internal.GetFreq( no ):0;
2 H8 k! n6 j" n' ]5 t        }3 |) f9 _+ l# |8 D3 R) j5 O0 U/ v. f2 s
        // VRC6" f1 x5 T' i' T# M: f" y8 `
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 w8 L, _! e5 {3 B
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
' z6 I. q, h  M  G: `        }
% u& y5 G/ L( F7 ]. Y        // FDS
0 I9 s7 H) i$ M: @# U        if( (exsound_select & 0x04) && no == 0x300 ) {
! O* n) Z( g  @% f                return        m_bMute[6]?fds.GetFreq( 0 ):0;
) p% s; L/ K, J3 t6 w        }6 c6 Y' n9 |# N* [$ z4 U
        // MMC5
$ N4 D  `6 H) B        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
+ z" y1 V- Y3 Z5 O5 n0 O0 Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
/ s) `* T# Q, H' n+ H/ N5 Q        }( Z7 P5 u7 c% v: R8 m( A: {. Y7 S
        // N106* S7 h2 ]' Z2 z$ i) R& Q. K
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 @" _7 I+ k* W5 R  j
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" Q8 G/ |7 v2 Y- o/ H! L        }
2 c: b+ x" F3 V4 U2 q+ U. i+ i        // FME7
) b8 p; k! S+ j) Z; ~* @        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) E* d4 ~; i& T2 l6 ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;8 c# ]& c5 Q8 Y! l  q; O: F/ q
        }6 [+ P/ g7 P( B3 a% M6 o
        // VRC7
! J' {# q' k) ?        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {& b' G2 N: p0 X  s+ k: r  x0 ^
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;& p8 w* m6 s4 ~0 R3 _* I
        }
  r# e+ M* v% H: ^        return        0;
) ]2 J6 T+ E  ^}
- b& H8 S  T1 q! l6 K  {; d4 M/ k. j3 \# s0 b; Z6 D
// State Save/Load: [* U3 ~) L4 Q$ l) [
void        APU::SaveState( LPBYTE p )
& Z; @* T: ]$ h) o$ |' `/ }{
, k1 K) f1 e& |' z8 q( _9 m#ifdef        _DEBUG
5 ^  q3 O% S! X9 YLPBYTE        pold = p;
2 w8 e+ x  U, i' |#endif; M8 s. K% [$ `0 M
% \# b% I' ?0 P* b9 b) z, Q. k
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞2 S/ A8 d) C( j; Y, V5 B3 f$ o
        QueueFlush();# b5 A- H4 v: B" o, y4 M

( b, |2 k+ Y% }* ^        internal.SaveState( p );4 ]  ~4 `3 g7 v# }
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 A6 x  ]: {" }0 V3 }
! T: h" w/ k, D; \0 P
        // VRC66 V6 }3 x4 w( H
        if( exsound_select & 0x01 ) {
) P6 s$ ~1 L0 n* r  t                vrc6.SaveState( p );
- j, H# {! `% N                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding" S9 [5 d, y- Q) X
        }9 J) \, [+ W: U: {: [# h
        // VRC7 (not support)
4 P2 `- b: D; f' E/ d; h1 M6 w1 Y        if( exsound_select & 0x02 ) {
' c) j" i& ~  G+ ^* |0 r                vrc7.SaveState( p );  x% K8 R. {1 |( o. s
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* s( E7 K/ i# Z        }
7 x% F8 y5 s3 G4 t% r        // FDS& R* x4 m8 w* V" r
        if( exsound_select & 0x04 ) {/ Q' i! f6 }6 i, D
                fds.SaveState( p );
( O( h' Z' F5 w( z" a. a, P# F                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% p1 k3 R1 `! c. M6 U7 o        }
  K) \9 F% ^( N        // MMC5
: z# S' [- s% Q/ K8 X0 F        if( exsound_select & 0x08 ) {
; Q1 G' Z5 X; [8 W9 \                mmc5.SaveState( p );
; D) ~$ R. N. K! c, Y( L                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 @' [: l, E( v- q7 v5 f( Q6 u- n        }
2 M+ I0 K$ I/ a( H        // N106. n! O2 |, V( _4 U
        if( exsound_select & 0x10 ) {
( \. ^7 `; N' w                n106.SaveState( p );
4 w1 ]# m" i, I: Y& C4 r# H                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 R/ n) z& e9 a# f3 M# @: {: G
        }/ w! w( ?3 E! Q
        // FME7
# Z) `+ A, K3 O& _/ {; |        if( exsound_select & 0x20 ) {
# K; ~! V7 B; C% r( q* h* l. E                fme7.SaveState( p );$ l6 g2 O0 w) v8 t, f7 m
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# E- s; a) ^' C4 w. \1 S( W% ^) V# Q6 N, ?, `        }$ D% z# A  _- `- L# F

! L) j  p/ d* f. x; P( {#ifdef        _DEBUG
# k: t. P6 o: UDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );' R5 ~; `  ?9 a) }: k& i+ C
#endif. p7 J& t  J& M6 T+ Y8 |! @
}, x5 W# v$ T6 e2 l$ B
7 {" I7 u0 I; \7 f9 S
void        APU::LoadState( LPBYTE p )
4 ?; k7 ~5 Z1 j, V5 e3 d; V& s  g' P{
2 K3 K1 H# w1 z. ^        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
2 b* N6 k7 R/ \9 Y; A9 W        QueueClear();; r# n* Q& T% V" ]0 \0 S& ^

  j6 E! A+ g, t6 L% Z8 x3 b* j        internal.LoadState( p );1 X0 ^3 }$ B' ^# y( _
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( J% N9 r9 w& F4 E/ z; D' K+ t" ^
( p$ l$ t4 q& d* N3 C# d9 q: _7 K        // VRC6
' k! f9 i6 }+ o0 T        if( exsound_select & 0x01 ) {9 I( F/ b2 I& v5 s1 z
                vrc6.LoadState( p );3 n! h( L" ^1 d' s/ h; _( I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  g! M! e, k( c        }
# ^( t7 ?8 z, I0 A0 y; Y        // VRC7 (not support)3 e6 K# e+ {( i$ ?2 z, v4 o3 Z
        if( exsound_select & 0x02 ) {
: n2 ?' @/ @/ b5 `                vrc7.LoadState( p );
$ L. q5 D# N, E/ ~/ w3 p, A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ v2 ]- s* N6 l( P1 T5 Y
        }
! {) ]! f& W! ^+ U- a1 L6 t        // FDS9 f8 c- Y$ c  t; W0 `$ r" i. Y
        if( exsound_select & 0x04 ) {( v5 j# a( o& d% q/ C
                fds.LoadState( p );
! H1 ?4 C$ `( p5 p                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. s/ ?9 v, g+ l* T0 p7 Q        }) o7 S7 F( ?7 i3 t, ^3 z
        // MMC5: B3 y$ p* q% C  V# u4 y8 l6 C: [
        if( exsound_select & 0x08 ) {
  p! g: j/ v' S2 N                mmc5.LoadState( p );/ H. T: D  o2 a' l! e
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding$ d4 ~- K3 e9 g! c5 O% a7 G0 }& h
        }6 _# y) [2 i: B! S
        // N106
3 \- C# U# f* g' C        if( exsound_select & 0x10 ) {
9 z: c- i$ q: C% X3 r                n106.LoadState( p );/ l; w1 V4 M- h5 g
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ c  b# t$ d' E
        }& S# L) g& e1 p$ b7 [* L
        // FME77 Y. J, A6 v3 B: C0 m8 |
        if( exsound_select & 0x20 ) {6 {; r& J( r$ t' O' q$ b
                fme7.LoadState( p );
  Y4 i3 g1 q! f' B( v- S  U                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 t' r( [' \3 i; C; }7 g        }
6 X; z% c: ^5 g& V9 C; y; X8 S}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
$ A4 F! r8 \. p4 |) v3 c  h可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。. S. U" P) I( H( q( e, [  m! ^
感激不尽~~

% }  `0 ]) o( i  e% a' Q8 @恩 我對模擬器不是很有研究,0 z6 \- e' T7 x+ j4 E0 H5 o
雖然要了解源碼內容,可能不是很困難,' p6 ?8 ?+ p- }& v2 S
不過還是要花時間,個人目前蠻忙碌的。0 s1 ~& O# l( u& s

# R7 }9 T* a; L3 u給你一個朋友的MSN,你可以跟他討論看看,
8 z8 T/ x) i2 r& [他本身是程式設計師,也對FC模擬器很有興趣。
8 k, F: }& A% P6 o8 g- y! @9 H. D7 w( a  k, b
MSN我就PM到你的信箱了。
$ W7 r* C4 a% W& P: R/ v7 f, E
, h" o4 T* a" y5 {" u4 P2 T希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 4 V- `; `+ D8 P2 B, g
呵…… 谢过团长大人~~

* Q  X' B# H4 X9 C$ k) }* G* M0 X2 |' l; t1 V) k8 K# }+ l
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# ]) c5 E+ U! T6 S2 z1 s& u; `团长的朋友都是神,那团长就是神的boss。

/ V! c4 I+ x$ M! A5 ^9 }哈 不敢當,我只是個平凡人,
6 V5 X& U5 H2 Y0 K要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
- F0 {  r% N) [3 y9 SZYH( ]9 F3 w7 g! f# K& I1 r/ F
QQ:4147343068 G9 t* @/ H; ~/ i0 \/ S) q, N
Mail:zyh-01@126.com7 W8 h( k9 ?. r$ x  L
1 V0 l5 w' z  ^9 h& a7 D+ I" e' s" ~
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 + F* d: N3 g0 y. I. Q- |
再次对团长大人和悠悠哥的无私帮助表示感谢~~

( F* v+ ~6 d8 q. a" b3 G不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-31 22:56 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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