EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ P6 F" g. t/ ^6 |8 @: q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" j# G3 Q' D. V/ r2 ~
这里有相应的模拟器源码,就当送给大侠了~~
" z8 y% l) U/ }, x2 w7 `9 rhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 % f0 N3 t0 J( V& h
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, H! Y& M, j% Y7 a楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# S( z, ~2 ~+ a这里有相应的模拟器源码,就当送给大侠 ...

9 v% J6 z8 r4 U聲音部分(Audoi Process Unit = APU):  L8 y* p& w# k: N
.\NES\APU.cpp( L  k0 }' H3 j1 {
.\NES\APU.h
. A! d9 z( R! m( V: T. b
' ]2 K( ~* v. f4 F9 `$ |" p, V) d" L0 s1 h6 V
影像處理部份(Picture Processing Unit = PPU):
, I1 ^2 x+ H9 W& a.\NES\PPU.cpp
  I% V/ g( e$ ^* B  z! T0 w/ z" y. E.\NES\PPU.h
& d6 f5 m$ }. M' c7 x) i
; i* ?, Z5 X, A& G. l6 ?5 o0 n  f如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 q4 A. U5 f: L2 y( _% g  F(由于很多专用术语和算法机理都不明白,所以看不大懂……)
; S( G& N7 o( m! |' q//////////////////////////////////////////////////////////////////////////
. u7 r7 e8 W, I. K7 v//                                                                      //
" S8 n9 q+ R- L  A% {//      NES APU core                                                    //
& I" a7 H1 L/ z. }) e- S3 A. w& P//                                                           Norix      //
7 v7 j. S9 E9 N5 l. w3 g//                                               written     2002/06/27 //
( u  ?; ?2 e9 `) C0 l  |//                                               last modify ----/--/-- //6 p/ U3 ^0 ]* D: H9 _& b$ Z
//////////////////////////////////////////////////////////////////////////
) R: v! q. c, b1 ]) C#include "DebugOut.h"
( I# o, H( g/ E* f- R#include "App.h"
+ u9 ~* d& Z, B* v#include "Config.h"+ D1 }. Q2 t* `( D: q. x3 M

0 X# o$ y3 Z" t7 L#include "nes.h"
  L0 }9 v% r1 i. ?2 b# G#include "mmu.h"' |# l8 @  i6 i- z6 o
#include "cpu.h") {9 m. ]* t6 W1 T+ O8 _% |
#include "ppu.h". `$ x4 m' i: B
#include "rom.h"
3 {3 [% |! Q* y  [+ N#include "apu.h"" X. j( d& L  X' F( w
3 s. b+ ~: P2 \9 o& a! A$ g
// Volume adjust) k5 H$ i1 K' d, q' i8 ]
// Internal sounds& e( b7 s8 X% T( ?9 v
#define        RECTANGLE_VOL        (0x0F0); K+ c2 A' X5 Y
#define        TRIANGLE_VOL        (0x130)
+ X2 u9 T" o9 [#define        NOISE_VOL        (0x0C0)( _, O; P, l5 a" M" ~, G; S0 u
#define        DPCM_VOL        (0x0F0)
0 m; z+ C4 L. `; H6 p1 r2 k// Extra sounds! D, O/ R' C! G% V7 r$ l
#define        VRC6_VOL        (0x0F0)
3 I4 s& d$ n1 N2 U* F$ m" v#define        VRC7_VOL        (0x130)% J$ V) I. k2 X- c6 y. X  x
#define        FDS_VOL                (0x0F0)
+ E6 H% L' S3 C- u#define        MMC5_VOL        (0x0F0)% i' Q) T9 m: B  n4 j
#define        N106_VOL        (0x088)
. f' [6 o0 Z( E# f#define        FME7_VOL        (0x130): T5 K  J: k/ a
* g; w/ C5 m; M3 Q$ s$ J* D* U
APU::APU( NES* parent )
; a' u8 R7 @* i{3 i# M' X% w# U
        exsound_select = 0;: o* Y/ a7 e! W4 I, X+ ^  Z  w0 R
4 d2 t2 C: F+ a9 s! G4 C. y) n
        nes = parent;
: x/ Z6 X/ w) T        internal.SetParent( parent );1 i/ `. R9 ^) {8 O4 }# Z
! Q/ M3 T0 l9 B; U- x7 ]
        last_data = last_diff = 0;
  U7 S  R! q1 Z* b" O% x' T  g: y6 @6 t; b# M7 M
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );; f' }* Y; F# c  P2 r7 L
3 O6 u( q) W+ ~
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );/ D6 \8 F; N$ e7 n/ D
        ZEROMEMORY( &queue, sizeof(queue) );
% `; T+ c8 m5 ]* Y% F        ZEROMEMORY( &exqueue, sizeof(exqueue) );7 @, S4 _9 W6 l" m: p
% z; H( l" i- B8 Z: X
        for( INT i = 0; i < 16; i++ ) {* m+ i! N, H* E0 ^4 K- F& F
                m_bMute = TRUE;! E+ g9 v: z8 X4 Z; w. v, ]' P
        }
$ N1 Q7 S# f2 T# d" T}, o7 v, a  J8 h8 @! c- ~" M
$ R6 Y3 y- y, L1 g
APU::~APU()0 o: `1 s: X7 ]
{
" Q& M) Z/ ]- `; z}
% y3 K% P6 e5 C, \; f+ o# u8 ?  D5 ?& D$ ~! [
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ t4 K4 @2 _" e; B7 T{
" o" }2 q; I: ?" J        queue.data[queue.wrptr].time = writetime;
2 l$ \: Q* z5 I% t4 \6 P1 y        queue.data[queue.wrptr].addr = addr;  n% }) D. e% a# Z0 C: ?5 Z
        queue.data[queue.wrptr].data = data;( J1 k3 T4 u2 X. C' O1 ]
        queue.wrptr++;
& A" e) s6 a1 j        queue.wrptr&=QUEUE_LENGTH-1;
# ]4 n8 B+ C& a        if( queue.wrptr == queue.rdptr ) {
0 z( ~. v/ A( Z5 h! r- [                DEBUGOUT( "queue overflow.\n" );* [4 |1 ]8 {4 Q% g
        }
8 |) K5 ]6 O' v! K2 \3 b}$ @1 N0 p4 S1 H, a' V' \6 r+ ]1 H
8 V9 B* N! X3 K2 h, S- P
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
; v& H, R4 i. w# c% n{  o  x' m' g- q7 f( K
        if( queue.wrptr == queue.rdptr ) {- T* g( V, A; K6 C1 o
                return        FALSE;
3 t2 u% Y( U) Y4 u: C        }2 \: I- n; L/ @5 p5 T
        if( queue.data[queue.rdptr].time <= writetime ) {1 R: i9 D/ t$ v$ k- \
                ret = queue.data[queue.rdptr];" Y! h( H/ O! x7 w$ L
                queue.rdptr++;8 C; d9 j# K0 ~* ^4 G$ a
                queue.rdptr&=QUEUE_LENGTH-1;
" h3 x- d& Y. k) a                return        TRUE;# W1 Q/ U0 g! S. Z2 H/ H2 i
        }3 @1 ?# {# V! J" b
        return        FALSE;. N4 y4 I* J. z* ?
}- Q% i+ V/ t5 R* j' Q7 Y

) i4 G) u6 t7 ?3 svoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )( j3 ~0 A8 X. y9 q  t4 |/ N, V: n
{
% Q9 t& l8 t% `6 V6 |        exqueue.data[exqueue.wrptr].time = writetime;- A0 Z& y# r" \$ ~9 C
        exqueue.data[exqueue.wrptr].addr = addr;
: z/ D) U' k( x% R9 q        exqueue.data[exqueue.wrptr].data = data;* p4 T! g6 t7 G
        exqueue.wrptr++;
# t$ g* f. _" y# i7 t( L7 W        exqueue.wrptr&=QUEUE_LENGTH-1;( m. v+ S- [" {" n/ E, a0 {
        if( exqueue.wrptr == exqueue.rdptr ) {. S$ @2 j4 J6 {, d
                DEBUGOUT( "exqueue overflow.\n" );! R$ f# m, Q" S& Z- F* x- p
        }' @/ t3 |/ {4 Q- L8 P( x4 ~
}
: l6 D( D7 k( [/ X& r# M/ D' B6 A1 X% I6 _# [7 `/ b9 o* }
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )) J, Q) M. G. V7 i
{" `1 X( ?3 X6 w) T! y
        if( exqueue.wrptr == exqueue.rdptr ) {8 v; P1 k  k4 z# ^9 o" _. K
                return        FALSE;
+ L8 l" k0 @# H, u        }
0 j: ~9 |; H" x        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
! S" j0 w' t% y+ X/ e& q; R, b3 k; S                ret = exqueue.data[exqueue.rdptr];
  i" K9 |& _. {5 ^                exqueue.rdptr++;
, A  `+ g0 a1 u+ z  P                exqueue.rdptr&=QUEUE_LENGTH-1;
% O+ H- w9 _& J. g                return        TRUE;9 H+ u) _$ I, `1 Z7 Y% j
        }
( D: t3 C8 n. a2 x: q        return        FALSE;8 ^; f, ?' f+ j% R% S
}) R& e: T  D& d
% y3 ?# B5 x" L( {) u7 x- g* U
void        APU::QueueClear()
& b* M# h1 O7 n{
$ v, R0 v: b: s3 d. X        ZEROMEMORY( &queue, sizeof(queue) );9 Q" }* [: j& G/ r' E
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; v% [( g0 z: }5 I) X. |! O; `}
! e. a% O' p2 w
# G2 C0 d# o% q6 pvoid        APU::QueueFlush()7 _& _" ^6 D8 w/ ?0 u9 F9 }
{" ]( c! J0 R- C7 b
        while( queue.wrptr != queue.rdptr ) {
/ h% f, P. J* Z5 {                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );  a$ D, V2 y+ N5 F$ J. P
                queue.rdptr++;
- }" W) x; S2 u0 \                queue.rdptr&=QUEUE_LENGTH-1;: _7 o( a- U- m: U. f+ r
        }
% @0 _& W" W! ?( ]; Y2 f" Q4 C* q" i' V  C/ Q% d- a
        while( exqueue.wrptr != exqueue.rdptr ) {. D# Z$ [( f; ?/ [
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
. n  v: M& P5 ~: t. L% Q0 C                exqueue.rdptr++;
1 C8 \& X! ^0 D- v0 i                exqueue.rdptr&=QUEUE_LENGTH-1;
" g! n2 V# t5 e, s6 Q) o' x        }
+ ]1 g8 R; t7 A# g5 }1 h6 ?! M4 _}" D- E! c* x9 n- _3 }* Y
1 k5 F" A/ o2 T2 h5 k" s% @
void        APU::SoundSetup()- J4 r7 e  P& m
{
; y  s: W) k$ D5 t3 {( ]/ ]( x        FLOAT        fClock = nes->nescfg->CpuClock;
2 U1 p/ m, E9 n: N7 J: Z3 r        INT        nRate = (INT)Config.sound.nRate;
' B+ l# B) a3 S8 E3 r$ k        internal.Setup( fClock, nRate );
* k. g6 ~4 y0 t) m1 B! F6 I        vrc6.Setup( fClock, nRate );$ Q2 s& S1 d# |! D( j0 O5 Q
        vrc7.Setup( fClock, nRate );% |+ u. d$ j0 C6 n, T6 M. Q
        mmc5.Setup( fClock, nRate );9 S9 b7 d% l$ M( \  U
        fds.Setup ( fClock, nRate );: ]3 t9 b5 \2 V) `: A
        n106.Setup( fClock, nRate );
' i' ~' K) e3 G. M8 L* O( O# j        fme7.Setup( fClock, nRate );
. q$ k+ b& ^$ ~4 Q}) _, Y' Q/ Y! {- s. t4 [! m
- r& ]4 W" p; O+ \
void        APU::Reset()
3 @0 [- V% @! D/ n! K$ W$ f- d% j9 c{" ]- z7 V& k/ e1 l6 H3 i
        ZEROMEMORY( &queue, sizeof(queue) );7 [+ K3 e# V$ X' E: W0 Z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );; _3 c9 A0 w: Z/ b, }5 Y
1 v) o0 {4 y4 _  M$ k7 A9 m% g8 J
        elapsed_time = 0;
" w; n9 |: J9 A5 L4 q' G4 U3 S8 g7 z! q- m7 |; K" V# T
        FLOAT        fClock = nes->nescfg->CpuClock;
/ M' G& @, f; D8 D1 A        INT        nRate = (INT)Config.sound.nRate;* W" ~& ]9 |3 A, y
        internal.Reset( fClock, nRate );0 O6 x1 X7 a4 n+ g. O; t" P8 @
        vrc6.Reset( fClock, nRate );) T- b9 L# p8 Y" S. |' _
        vrc7.Reset( fClock, nRate );
! h2 D, x) O7 q( Q3 t" b        mmc5.Reset( fClock, nRate );
; x9 }; p! m6 J' J, @. H5 r4 J        fds.Reset ( fClock, nRate );7 P1 Q( f' m' I5 |: m# q! O
        n106.Reset( fClock, nRate );* ^9 Y& _- j% Z# D# x1 d& Q" r) u
        fme7.Reset( fClock, nRate );& ^6 h2 t( y" ~

5 r) Z6 N, e" x0 V- [1 f4 P        SoundSetup();1 g7 s* w  D4 _, m
}
) }- ]) W; c: a9 z( t& w
% \  u  B6 s! i# d4 ]1 K9 o  i3 Pvoid        APU::SelectExSound( BYTE data ). ?- S! u5 O" q  I" E9 Z% H
{( l; o3 Z+ X* K) o- I6 n( L
        exsound_select = data;+ F  F( _$ a2 c5 k, Z8 p
}5 `" Y" ~, T6 |: D: ]
/ A% S; W8 S7 r: i0 T) C# r
BYTE        APU::Read( WORD addr )  j7 U& y7 c* ?0 t' x. l- c/ f
{/ n. X  a6 y9 h( p: p
        return        internal.SyncRead( addr );/ Q! I* A0 Z; i4 L# G1 y5 k
}* [/ c  h0 o: q! }+ R1 R4 _& f+ r
  N/ g: h/ i1 J, w  G- q/ o
void        APU::Write( WORD addr, BYTE data )* n, g& s# Q$ w! h. o. d0 I( F
{& J6 ^( I. h0 B) v8 E
        // $4018偼VirtuaNES屌桳億乕僩0 s, b- W0 i6 q( I7 Z- U
        if( addr >= 0x4000 && addr <= 0x401F ) {# \: s( ], w2 J- |/ S# r; W, b- R
                internal.SyncWrite( addr, data );  f" d; b" |0 a
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );5 J8 o! f6 D' w) V1 ]" s
        }
! h+ N; c5 g" D: P" m! ?+ l. W8 n: H}1 G2 x( _, w  J. f/ b

2 d! O1 w6 {8 w6 ]# J" {5 J* H" y1 fBYTE        APU::ExRead( WORD addr )3 A- M4 d; V( S
{, e% X7 p, L& D( ?; S" l4 e& F  ?
BYTE        data = 0;
, Q; [) O" n) N  ~& A' p! U. _: |$ m6 g  [, h6 F8 |) ]
        if( exsound_select & 0x10 ) {; F( J. t7 N0 T( z
                if( addr == 0x4800 ) {
7 F& `8 R* ]% P3 j  a# w% a                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );. t4 o) M  K2 w9 N4 Y: S6 W
                }
+ K4 i8 `( ?# ]6 p) F        }4 f* v! S1 U3 o8 @
        if( exsound_select & 0x04 ) {
8 ^! w6 M( a" [9 K$ p1 G9 X                if( addr >= 0x4040 && addr < 0x4100 ) {
* u4 E# C; |& G( K% I2 G                        data = fds.SyncRead( addr );
+ ?9 |# n- ]0 l                }
6 K4 ?7 d* ]" j9 a        }0 _- v( ~! _, P
        if( exsound_select & 0x08 ) {
, w% b8 G# i1 p; y, e                if( addr >= 0x5000 && addr <= 0x5015 ) {6 c# X% L" e% ^' R' g- J; c# c
                        data = mmc5.SyncRead( addr );. d4 ?9 Y  h; k' [, [8 P
                }
* e) ~% ^: Q) q# U% x! B6 @( N        }: U5 q2 }: o) D; P( y) e; m- F

9 [- \8 H/ ~! K# d        return        data;
: z# I" h8 t' v0 ^}
' q; A  j& J% h( Z1 h
7 _5 ?$ ~$ U. Kvoid        APU::ExWrite( WORD addr, BYTE data )
; D  k% y' g) P0 M{
8 R1 U) G, Z4 f: }3 N8 G        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );& D3 i# f1 z4 W  R+ w
6 A4 |# i9 C. x# Z
        if( exsound_select & 0x04 ) {
( ~: z* _; Z# P3 {5 \7 R; H# \                if( addr >= 0x4040 && addr < 0x4100 ) {
7 e+ [: E$ Z# K                        fds.SyncWrite( addr, data );- p- I* _) ^% x8 r( N+ p2 D8 |
                }* c: t( i+ [9 I  ?% h: ?! e4 m
        }
: p9 J/ v8 `6 ]+ J: W4 `/ V( G
% l. A0 X. f4 [# `. }        if( exsound_select & 0x08 ) {' c& e: u% Q! {1 @+ n3 p) p" N
                if( addr >= 0x5000 && addr <= 0x5015 ) {+ a0 x% @7 h' i& ?7 i
                        mmc5.SyncWrite( addr, data );6 J8 Z1 h8 O; b9 `! o& {7 M2 U
                }1 K6 Q' N( ^6 [$ f7 _: m( I5 V
        }! w2 P% r+ t; S$ Y* F2 A
}
+ E( }" k1 _2 P6 d1 T/ B/ e, p; H$ P! m" H9 j- A, K
void        APU::Sync()
: z) K3 P; c/ v  I{
: F3 Z( P# t0 j% p, o* n}0 O: r$ `8 y/ \

. G6 E4 V8 g. ]1 L6 U" x- T: a6 Wvoid        APU::SyncDPCM( INT cycles )8 W0 e- A% b! Z2 p9 l
{3 u- q( ?' P' A$ D  \8 I; E; q
        internal.Sync( cycles );$ M; c, c  a9 i5 M* |/ v$ D4 t& S

5 e6 T  E6 p9 c1 ]4 ^4 [        if( exsound_select & 0x04 ) {
3 m- U3 s1 [4 z8 f/ G4 S# S) e                fds.Sync( cycles );
7 B/ [: ]' S/ K( ^5 W3 b        }/ V: G5 l3 M$ T5 l5 s3 m
        if( exsound_select & 0x08 ) {
4 O, |1 E: \& D5 T& Q" C: n                mmc5.Sync( cycles );
: N: {& c7 y( {' m& h        }3 i: E3 f' a4 u  Z4 H
}0 z  h6 R3 n0 M; E; j

! j4 }  p7 U. B# ^/ D, I. K. cvoid        APU::WriteProcess( WORD addr, BYTE data )- M! I$ ^+ r- S3 w1 d' C
{4 }: w' K; q5 S' {0 n% V' Z6 \
        // $4018偼VirtuaNES屌桳億乕僩
1 X. V  Z, y! p3 ~) b6 q2 P        if( addr >= 0x4000 && addr <= 0x401F ) {
  Y: W' Y* L& u$ L                internal.Write( addr, data );! A  [3 M5 \4 B! g1 r
        }# J( T' |+ p" {* s7 r
}2 f3 E8 K% M6 I& K" H9 L
5 ^5 E9 d2 h0 W2 K$ J4 s
void        APU::WriteExProcess( WORD addr, BYTE data ): a+ H* u8 b( [. S; g4 \) j. I, ^
{6 T6 L4 W) r6 \# Y) Z- t0 U2 l
        if( exsound_select & 0x01 ) {& I% a7 i' Q# @& S$ f3 ?( c1 J( W" h
                vrc6.Write( addr, data );' _2 _( p) H: H+ ^) O& i
        }. p# o; M8 l0 r+ g) i! t& E+ z- `
        if( exsound_select & 0x02 ) {
' o2 X+ A# ~; r5 o9 w/ N                vrc7.Write( addr, data );4 e/ X: [5 K* F4 R
        }# g2 s' D7 M& q9 }
        if( exsound_select & 0x04 ) {) n1 Q" {) O: r( h. g5 b
                fds.Write( addr, data );* x8 W/ q( B* i# m. L: H" X: w* A
        }6 G& S+ o0 p+ k; A
        if( exsound_select & 0x08 ) {
. u7 }1 U% X8 h: L7 @                mmc5.Write( addr, data );
! t- }! u2 L3 _" {, q, x0 r& ~        }
; [  H3 E# \' q- d; n. Y# q9 |3 _. [        if( exsound_select & 0x10 ) {; o* s% v% x- @2 W) c9 ?$ A1 p- b
                if( addr == 0x0000 ) {
; L; @" _2 B  Z4 q+ {" i                        BYTE        dummy = n106.Read( addr );
5 ^! T/ l' J0 ?0 ]+ a. ?+ h1 i                } else {
2 M- `5 e) R. X- c  e                        n106.Write( addr, data );
+ w+ ~3 \+ g5 j) ~2 B8 W                }$ N5 M7 s# C$ u- g
        }1 g; S  b7 s2 r2 B
        if( exsound_select & 0x20 ) {  h) H9 `' b1 _- u
                fme7.Write( addr, data );. F9 V7 H0 j  {6 h0 @3 G" ?
        }- N3 s, z" S' d2 _
}
0 A: i, _8 ?" \* `- ~6 R, j. c) X" L: N
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  W! ^* A1 Z/ N' m- u, Y9 x) c
{. z0 Z+ @4 j1 [& [# L% c" ]
INT        nBits = Config.sound.nBits;8 |9 ?8 n  w- R- x
DWORD        dwLength = dwSize / (nBits/8);4 `: ?8 I* D- C4 m3 s- W( d
INT        output;
5 B+ Z% r9 V3 L' s4 Q) ]) n- I6 u+ y* QQUEUEDATA q;
- v1 @* }! t+ MDWORD        writetime;
8 t8 q2 C, I, y5 V0 V' m- K# N9 B
- q& H8 o4 q! G3 fLPSHORT        pSoundBuf = m_SoundBuffer;
- p- o4 m8 E" Z- J! P$ o) w2 ZINT        nCcount = 0;2 I  `) y* o! P2 o4 T9 L5 v

+ a. p( Y0 ?& V5 [+ _! \4 u4 `INT        nFilterType = Config.sound.nFilterType;' Q- ^! h+ k& O" L* C2 x
7 S  S( j6 l+ ?6 f# l4 A) Q
        if( !Config.sound.bEnable ) {" g6 z5 C6 l# h. x# i! b
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );- }/ W1 t6 P; T4 \  Q
                return;
+ ]! _7 G% J4 ]( W/ O        }$ a# v! \. c+ a% R; D

/ I3 Y/ `( R! Q! M        // Volume setup
& J+ j# p+ r# b1 {; @) ?& ~        //  0:Master* T! H* x) h9 u8 c$ u: k7 R7 F
        //  1:Rectangle 1
) J' s& |( ^: R& |# H        //  2:Rectangle 2
: m) O# `' ?$ Z: |: X4 }1 t        //  3:Triangle+ F% S) T: c4 b! S6 r; ]
        //  4:Noise
* C. l7 G) |, t$ @* i7 V) S        //  5:DPCM
8 e) ?- ^: H4 F+ `: S- [  o* ?* P        //  6:VRC6
1 P( E5 n1 [- b        //  7:VRC7/ M* q  M5 Z$ g2 X* `1 M7 m; G
        //  8:FDS2 P" A' J" x4 l% A! D0 K
        //  9:MMC5
# m( P, N" [: q  T8 A        // 10:N106
6 Y1 c" u5 m% k% S; W( J5 P) X        // 11:FME7
5 X* e0 w) ^/ X, D+ Z: i5 s4 G; v' F        INT        vol[24];% P1 c6 [  W5 L+ f3 X9 Z, x8 U! w  ]
        BOOL*        bMute = m_bMute;( R- ]7 r' W: _5 ^7 j  t3 C6 b# Q
        SHORT*        nVolume = Config.sound.nVolume;5 D9 o* o3 |  M# j

1 c* A- i$ ^$ ~2 E% q) p. X' W        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
+ X5 k1 w& s5 m7 D
) z5 u0 x3 z; S, ~, S$ g        // Internal
- w) d. V7 s) X4 F9 }        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;% j1 l. P/ n6 ?$ v" F- l
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;- i, O- ^  `9 b* M7 S( M* k
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 n0 W0 W" v# ~0 e
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' u9 @' m  d& ~' N, a% U1 h+ [
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
5 T! y( y+ I; p5 S  l1 o5 o$ k! K  S0 g5 B
        // VRC6
# P) o7 f1 w+ V" R8 i8 w- ^# R        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ M' Y# D& `1 j& I( k
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 x" X- G+ z! d* t" R
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  i8 X8 a5 ~4 K( T4 I5 l  L( z
) q4 t% L+ ?5 P& d2 |: U) i
        // VRC78 o4 H+ k7 v" s' d. u* q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
7 R) \! ]0 r& B+ S/ j0 W' B! Y1 u# C# X1 x& B
        // FDS
2 n9 O5 E( ~8 G: G* g! S        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
7 X' N) c) `+ C  J# |2 x, p- Z6 w4 j; w: `" Z+ j. z
        // MMC5
; Z! `! W8 D: a2 a. n        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 n) q# J- Y( J  |6 o5 j1 T, _: k0 K
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) ~& m1 u5 }6 O. q0 w
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 ^4 p- J' j# i$ e6 z
" p# p3 Y. }: y. q' ?7 a        // N106
  d: u( c9 ^& r9 H- K; ~& W        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, j- a! L( k# [$ W. M7 Q        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; L, X4 k: X# E" m4 n  J8 c+ u1 F        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' k# D. f- }4 T! D$ X
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 ~- M$ @: Q* ]' c        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, m2 n: R- A4 z
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 V# i- H  }$ O, p5 M! V
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 J6 _' G  D4 w) e        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 L1 V6 O4 O. U

: D9 p2 v9 a( @        // FME7% A' n6 H% P5 D* D! }
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 F9 U+ f  @1 F8 V$ R
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
" s9 w1 Z3 B- [1 {: G        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ y& S( Z* G; n0 F. a* K& ^0 \
5 E2 m# C5 M) a! j- P, l9 H3 x//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
8 s: R0 U, g  x- k        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
: n. K1 ]6 z* p# ?( [- I) o7 e
' |" U+ l1 A) v; ?3 r        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 j5 t, g1 k0 V! v( K* V3 C        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) V6 e$ d; T' U
                QueueFlush();2 C7 P; E! S+ q+ W: {8 I8 n
        }" L+ D$ O) s* v

' A- W( ^3 m6 N        while( dwLength-- ) {
1 A! I, p, a+ B; f. d                writetime = (DWORD)elapsed_time;
9 z$ J6 `% u$ k7 L& H7 v- }
1 z9 _( g6 G3 |                while( GetQueue( writetime, q ) ) {
- e% `$ I5 f1 `8 u- w- @- @. J2 g                        WriteProcess( q.addr, q.data );+ V( I/ x% h# l4 ]) R
                }. _' d& t6 y+ q+ w% ?4 Q; d' X
4 R' b( L4 f0 a9 y. _
                while( GetExQueue( writetime, q ) ) {
( y+ o9 L7 k5 s8 ^- h+ I                        WriteExProcess( q.addr, q.data );
4 f+ a& @3 a& n                }
7 H9 a) Z2 b  L& }/ H. o: d8 h' f# D% X( C8 k9 Y
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7; o% P8 Q6 U  j; |; }% o& m5 G/ ^
                output = 0;
+ N0 M5 ^4 i$ m2 N+ S3 c                output += internal.Process( 0 )*vol[0];1 T, b% _2 F  }" g' p
                output += internal.Process( 1 )*vol[1];( r( H" ?8 t. c8 I8 q2 T/ C0 C
                output += internal.Process( 2 )*vol[2];
' S! Z5 b( P, E2 D" L                output += internal.Process( 3 )*vol[3];
  ~5 `7 l9 K: H$ ~" y5 h( o                output += internal.Process( 4 )*vol[4];
) ?9 R: J! G/ G3 P7 _3 g& v
, M7 @0 ]! D( {  R+ h6 g2 Y+ z                if( exsound_select & 0x01 ) {. N! b6 I" g6 f+ o8 A
                        output += vrc6.Process( 0 )*vol[5];
* s+ C( X; j  W  s2 V2 K1 s- h                        output += vrc6.Process( 1 )*vol[6];
$ T* R6 ]) g- T9 \                        output += vrc6.Process( 2 )*vol[7];0 ]" e, X, a, [% \5 Q! |4 s5 `8 Z
                }
. x9 D8 ?6 o& c( M                if( exsound_select & 0x02 ) {
/ {& R" R5 I4 [6 G0 Q, A# S4 f                        output += vrc7.Process( 0 )*vol[8];
. t1 f, S# y; H  C0 a" l& v                }8 h* t9 O6 X4 M; X
                if( exsound_select & 0x04 ) {
3 j# I. ]* w$ p, }  ~( X                        output += fds.Process( 0 )*vol[9];) i7 _# m7 u! O. z! \7 @/ k# @
                }. g4 x; d" m) Z- m% H
                if( exsound_select & 0x08 ) {! w- H! R! ?% P& g  V
                        output += mmc5.Process( 0 )*vol[10];( }$ [, O/ K, k+ o
                        output += mmc5.Process( 1 )*vol[11];
( [( z+ d/ H: A9 M! Q                        output += mmc5.Process( 2 )*vol[12];
9 s  q5 ~3 O2 w; R- F5 R2 q                }
; r* F. u: U" e) f' m                if( exsound_select & 0x10 ) {1 k+ I( {/ O) x2 v' j
                        output += n106.Process( 0 )*vol[13];
9 d& z, ^0 k" Y+ ]$ t7 U8 |, L                        output += n106.Process( 1 )*vol[14];0 O+ [: Y$ ]% Y* K+ a3 v
                        output += n106.Process( 2 )*vol[15];5 o$ R* a, w8 b
                        output += n106.Process( 3 )*vol[16];
. j; R' L5 t) o& }6 N                        output += n106.Process( 4 )*vol[17];
4 c- e6 G  O* P3 y7 F* j3 m                        output += n106.Process( 5 )*vol[18];) r; \/ M( z$ k. X/ k7 a# k: R- A
                        output += n106.Process( 6 )*vol[19];
' i$ G% ^/ d! P! U; D/ _$ j                        output += n106.Process( 7 )*vol[20];6 Z: J. {; p: P
                }
- [; S6 o. C# B2 E- X                if( exsound_select & 0x20 ) {6 }% N5 l' H' W+ r' x4 Y  a. k# Y
                        fme7.Process( 3 );        // Envelope & Noise
, m& Y/ k+ `( f                        output += fme7.Process( 0 )*vol[21];' v& ^  m3 b2 p# j! S
                        output += fme7.Process( 1 )*vol[22];0 m9 H$ _8 X! \4 j% F5 f$ ]
                        output += fme7.Process( 2 )*vol[23];
( s! z1 [& _. j/ ^  `                }
! E! Y% V* U/ W- s. P; u" J! i! G2 b
                output >>= 8;, b! N# x3 b# U9 ~. T
% j% Z; F9 l3 O% h
                if( nFilterType == 1 ) {  q  R9 g7 \) p: w, V, R$ u1 f& I
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), c( A  D" u3 R9 ~, d
                        output = (lowpass_filter[0]+output)/2;* E8 H# g! H+ }; Q* \, v
                        lowpass_filter[0] = output;( ^# i0 J2 K  n  {! B
                } else if( nFilterType == 2 ) {: p, ^1 v* I+ M! \8 |
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 R9 v. N: `3 {7 X7 m& _+ F                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; y! f/ _( \' h( A) S& A
                        lowpass_filter[1] = lowpass_filter[0];
9 ]/ ^! z0 [8 d( ]6 ~# N& a) g& m4 R                        lowpass_filter[0] = output;, R& h+ u; _: w* H' c7 Y
                } else if( nFilterType == 3 ) {
2 |/ T, L; z( a7 m0 g                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)1 n* u/ C4 s' e9 S' l
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;* q1 l2 T, d, |  \' i: {$ a
                        lowpass_filter[2] = lowpass_filter[1];
5 J6 ~, Z  F" u6 @# q: a3 g  Z                        lowpass_filter[1] = lowpass_filter[0];
$ M/ ~3 G$ ^3 D" _. A, D/ u; C                        lowpass_filter[0] = output;
) K4 ~" X& o1 x, `3 j                } else if( nFilterType == 4 ) {) o  H/ }; H' s+ _9 R) ^# T& `
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& Y3 C: n2 B2 O! E4 v# u, B                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
. N7 @9 f4 i+ z                        lowpass_filter[1] = lowpass_filter[0];5 b  R; i: {% G+ z1 M
                        lowpass_filter[0] = output;' i# \, m1 s8 `2 G4 r
                }& l. a( t2 u9 k- J# _

) x0 s, Z0 e0 D' K, v% z' D* w#if        0# o# c! S- q" Z* q8 {  r, P
                // DC惉暘偺僇僢僩, Q6 N4 d/ ^: K/ b0 w' `" r1 ]
                {, W+ H0 ]; x/ p
                static double ave = 0.0, max=0.0, min=0.0;. v5 B: K0 z9 Q( ^9 v
                double delta;
+ D  m' H( }. Z& G% S+ k                delta = (max-min)/32768.0;3 I! j- d4 R( q/ A" o2 a
                max -= delta;
$ Y" |/ C8 V( ?7 x                min += delta;
) |' z6 r4 W% f                if( output > max ) max = output;
' y% R; |2 O% S/ ^1 h. _/ G' N                if( output < min ) min = output;
0 d" Q( O4 p  O                ave -= ave/1024.0;3 G! e, S* v2 |1 }6 ]9 f" p: m
                ave += (max+min)/2048.0;
9 \4 l+ M+ n! B* N7 j0 t                output -= (INT)ave;8 D1 H4 O2 Y6 ?! ~
                }
/ N. m- p, ]- Y* X# Y- f8 Q#endif% b1 n5 F# D+ f! ], U) ~
#if        1) D: x+ \- m9 j1 C8 E: m
                // DC惉暘偺僇僢僩(HPF TEST)
& Q0 Z5 ^5 i) g8 l6 d9 U) E                {
0 q% i3 @* @6 z% W7 ^/ H//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);/ X) M) Q2 [+ l$ E* L* b) w
                static        double        cutofftemp = (2.0*3.141592653579*40.0);% S6 S+ {. E# x, V9 v: S) T; [
                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 Y. q9 ?! c, a$ O, p9 E/ J0 \
                static        double        tmp = 0.0;
: q4 t/ S9 ^( e6 c1 L9 n! r                double        in, out;
1 f9 e2 Y+ q) v! s
+ h( r# r3 u! w/ t0 a                in = (double)output;
" P2 |& C: h7 H1 M                out = (in - tmp);
, h/ e2 z6 R% a3 N                tmp = tmp + cutoff * out;& q1 O- o& u, ?% c. }/ [

0 l7 u9 v8 x( U, I' m                output = (INT)out;
7 V6 B) l6 K7 P- v( N% M5 Y                }8 O* X2 v9 J  m$ U9 x$ A
#endif
- K. L  l$ N( B. }#if        0
8 u, k- X0 F1 g2 |9 T                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)8 ?8 S9 z! W  l% l$ Z- A9 V8 s
                {$ R1 v4 p, i  Q$ |# N- F* H3 x2 l
                INT        diff = abs(output-last_data);/ }& H* S3 {: o7 m% w3 s+ H0 d
                if( diff > 0x4000 ) {" z& x- b/ i+ s. B$ a
                        output /= 4;
0 p4 u3 a* _. o; u* U                } else & v( I1 {0 }: o$ l: |7 V
                if( diff > 0x3000 ) {% v2 H7 m1 w$ e
                        output /= 3;$ u: {! F% q8 \  h! u
                } else
# Y' Y; K% u2 s. p0 @                if( diff > 0x2000 ) {
" s3 T9 n7 S0 L8 y- V                        output /= 2;, U6 I  @9 r8 W  H0 B# o2 u# C
                }, x3 h6 u5 i8 s+ u4 ]3 u
                last_data = output;1 W; @& S& B9 B, Z% O9 N! V  w
                }6 |$ O- k9 G' d" E. m! s
#endif
$ y3 z1 D' F! K* q. Z6 g                // Limit/ m4 @: r0 _. ^. L( h1 q9 z
                if( output > 0x7FFF ) {" z8 R# T' I5 h3 r) o
                        output = 0x7FFF;8 W! H# k- o4 V3 ^3 l/ L
                } else if( output < -0x8000 ) {, F0 ]8 `) D& G8 Y9 g, Z- U- y4 _
                        output = -0x8000;0 f. S- S" b( Q  i( F8 `
                }' X1 a4 j$ K0 \/ V; v
* l9 s# Z) D' r6 f& Y5 V' c0 E4 ^* B
                if( nBits != 8 ) {8 J' X7 S: I/ }) ~
                        *(SHORT*)lpBuffer = (SHORT)output;/ a9 L1 ~. A' C3 x! \4 U( H" |
                        lpBuffer += sizeof(SHORT);1 [, C- J2 R$ Z& @
                } else {
( R2 K5 A) a2 x" G3 I- [                        *lpBuffer++ = (output>>8)^0x80;7 r: [! F. ?( N( S1 Z5 Z6 n5 h
                }. m1 ^2 N4 b! ~* M9 R7 V
! _5 b* ]$ s$ S% \* H
                if( nCcount < 0x0100 )
$ r- k4 s: w; z+ }, \                        pSoundBuf[nCcount++] = (SHORT)output;2 s5 U1 E/ M! A+ ]8 P$ h/ I: R) L9 Q
; v5 i$ R; ~( ~2 q8 h
//                elapsedtime += cycle_rate;) B8 W) E3 o8 E7 ]6 L) R6 h
                elapsed_time += cycle_rate;
& c  T' E* \6 \, S6 o$ {        }
8 t( ^& d6 y% P1 R; U+ S8 M
' x2 H) C/ E( M9 a1 D* Q  u#if        1
6 P% w% t# f  n6 ~: {        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {! U$ V1 s& E- l0 N( V' Z" B8 C
                elapsed_time = nes->cpu->GetTotalCycles();
" m+ q9 P- V4 s        }! v* b6 ^9 D; p  m# d8 Q6 J: r4 j
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
" n! }; p  |' u! c4 u                elapsed_time = nes->cpu->GetTotalCycles();! V6 H: I- d$ F9 h! ~
        }" A4 \7 h/ `$ l
#else7 ^: q& K, p; c9 n4 |5 U
        elapsed_time = nes->cpu->GetTotalCycles();3 D/ A( J" ~7 ]  s3 o3 u6 a- |# a0 T
#endif/ Z3 F( o7 h3 h* M" a8 ?5 X
}/ |1 P4 R* y; s4 p4 o  h2 _

. e" n4 }, L" i' h// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)1 y. s' S( s3 Y0 }% y
INT        APU::GetChannelFrequency( INT no )9 m( `4 D$ V7 h5 X
{6 P) w( P; o4 H- z
        if( !m_bMute[0] )8 v, M1 H, S+ Q! D% h
                return        0;
8 T( s6 y3 K1 k' T' M9 [' J- u- L: Y4 h" Z
        // Internal. f, R% a+ [" Q  u( @8 G
        if( no < 5 ) {
* r7 \2 G% J; h% e  v/ l; x                return        m_bMute[no+1]?internal.GetFreq( no ):0;& L& m" q" _9 W
        }; W6 a# B/ j+ i
        // VRC6
0 x1 v! @& e2 x- x8 D9 z+ d        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
0 f; j# N* N' N) V                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;( n) \) p: m6 Q, u' Q
        }0 w  d/ o% m6 Q0 h9 E
        // FDS
; O8 O$ E% v! }4 Q+ z( c7 t        if( (exsound_select & 0x04) && no == 0x300 ) {
- E1 r' h6 V$ N6 j                return        m_bMute[6]?fds.GetFreq( 0 ):0;
4 q3 j. s6 l1 c3 @6 P/ Q) A) [3 ?        }7 A7 K4 B0 W6 i% t3 w2 D, q
        // MMC5
0 G  E2 e9 m4 A4 ?* X        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
) s6 D! f+ G+ q+ k                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
" K" L( d& X$ R) F: ]        }
- \% Z% s1 i' M( A! J        // N106, ]. o3 z) ]- t% i
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 ~8 I* S$ e6 D6 r                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
, w* l6 \+ x7 c1 z6 `        }
  J4 W% D3 v7 D2 ~3 l( \/ I& c: a4 u        // FME7
: D6 |! R  ~5 w, q6 K' A' J+ s        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 B' p+ f7 J4 _/ C' T" j# X) _7 s                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;7 \3 |3 |+ n" V+ P& q2 G. J- b: Y/ T' \; w
        }3 R& s9 ^! h+ F) Z
        // VRC7! P2 Q+ Q' ~, ?1 m) E5 l
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
! z  a3 q  T; q8 n9 @) `                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 L9 }# e3 o3 V# V! {& L! s
        }
& y" F  |( Q4 t! r        return        0;
% J: V. }6 O: e# K2 M! Q}
! v$ H/ [; O7 t8 O; O( R* r. E  `9 ~6 d- G% c3 Q. R/ Y
// State Save/Load
2 z; G  l7 U# wvoid        APU::SaveState( LPBYTE p )5 X$ A$ e7 H: b8 F. o( P4 w) r
{
2 Z$ S8 y+ H! }5 R/ B8 z$ U#ifdef        _DEBUG
- g+ M. U, p! D$ E9 v( K! H* M9 TLPBYTE        pold = p;" F  j1 q& _1 [. Z+ I) t' g
#endif
7 q, Q7 x% `* o6 H3 m
% a* n; Y0 I4 ^# \+ v# w5 a4 n        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& U8 G1 `1 X' s4 M0 v' g        QueueFlush();, }# M8 n1 y4 o& k7 g. A& F

, p- o7 n- O, E: k        internal.SaveState( p );
; Y, u0 g. W4 r) U/ W/ K! F        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. Y6 t9 S- D# u& D: b, h2 h! p4 W2 D) T
        // VRC6/ C. Q( R. T$ M# G" {% ~/ _- I! Z
        if( exsound_select & 0x01 ) {- h- L) Q. D" t5 C  ^
                vrc6.SaveState( p );/ T3 T) x+ z: S7 o/ y) K- g
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ O2 D6 b( O8 y- e% @7 Z4 F        }/ x4 Y9 Z# A  }# h: C4 ^
        // VRC7 (not support)
# |; Z- X5 l! F% S# E        if( exsound_select & 0x02 ) {9 c1 z: C1 c8 g, C# A9 s
                vrc7.SaveState( p );
0 Q/ E5 }1 K. N; X3 V/ [% h$ A; m6 Y9 y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 p" I9 y+ [0 c6 M. H$ H  k" o        }
/ `2 Y7 Q- f. Q& L$ }+ o        // FDS3 L2 a( \, f; e: K% H
        if( exsound_select & 0x04 ) {" l6 O7 H( f$ ?9 t. A5 M
                fds.SaveState( p );
7 l! e$ k0 R; M! q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 z  J3 _! P/ a8 `/ i
        }
3 _% H4 F* x7 b3 y$ U6 j3 l4 b        // MMC5
6 l. a. k$ O, }) _' U        if( exsound_select & 0x08 ) {
; w* Z0 N7 I8 c( H$ T  `                mmc5.SaveState( p );8 W. V* \( _2 [1 L
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 t8 t0 w1 {0 |9 B        }
) S" q& I/ J+ M; f4 f: M3 n        // N106! K. m; `. f$ ]/ C) l( ~3 |
        if( exsound_select & 0x10 ) {
5 b; _7 G- v# p2 _2 n                n106.SaveState( p );
  G8 Q( B  M# y" r                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* t6 ?' s( A% y' |% Q2 X
        }1 c/ k. V9 X: {# f6 x0 P. t6 [6 s
        // FME7
/ @. P& U- r( ^5 `" P$ u  a        if( exsound_select & 0x20 ) {) m7 \( [$ W4 @5 v1 ]
                fme7.SaveState( p );, Y8 |* C+ z$ t* ~1 E1 [
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, t7 p! S0 v4 k6 u  ^; J$ I        }3 A+ v. l* q2 B0 x
$ j" X5 o. e9 o9 Z
#ifdef        _DEBUG+ d4 M8 Z1 ~$ c0 J3 Q  J
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
- |9 Z/ @4 F# k4 m9 n6 B#endif. J) A% B. ^* {- }
}
* L6 p% ?6 Q& ?$ Q5 v- j2 \" K3 s: B$ r1 d$ c7 f& h" i* L' |1 f
void        APU::LoadState( LPBYTE p )9 s  T3 W- |2 E) V, C- S
{
2 j4 b2 M' [2 f2 h9 Q        // 帪娫幉傪摨婜偝偣傞堊偵徚偡* m5 _, @+ V9 L$ W& j3 r" x
        QueueClear();; `" R; z, p0 w1 b* E

. K$ u. N" t/ n# |$ o        internal.LoadState( p );# n+ V( ^5 L  C" g$ o
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding2 B- \6 y  d# O" f

7 K7 \) n+ f' z: X1 c5 p        // VRC6
" L! P$ g: x& ], C/ T* _% D8 z        if( exsound_select & 0x01 ) {  c0 q# u- z8 \4 B7 Q
                vrc6.LoadState( p );
* {: a( q4 L- H' P3 |                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 }6 G( t1 S% a, }        }4 f: u9 z; t4 g/ p# v: y: J  Q
        // VRC7 (not support)
1 L- O; g8 \' b( g        if( exsound_select & 0x02 ) {) b8 J: O1 |; i( a) G* e: {& o
                vrc7.LoadState( p );% g3 p+ f% c2 r% [7 p4 O5 w4 `
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# L$ _& o3 T) O$ @        }, |6 b. J+ a8 d: E
        // FDS
3 V/ e8 ]) x& W% p, w3 f( X! d        if( exsound_select & 0x04 ) {- _; R; j. W" I) J
                fds.LoadState( p );' |  t4 K$ ~' N6 N0 i7 a( u
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding( B  i: F7 C3 T/ j  x- R
        }
/ p! Z: r1 R& D9 v2 |        // MMC52 z/ z3 P, [2 x! _' K9 n* B
        if( exsound_select & 0x08 ) {. @$ h# j: f9 F; m7 y' o3 P
                mmc5.LoadState( p );
' l. a8 r4 P+ c- I. S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 o( p4 Z- ^, w        }
$ N9 U5 ^# Q# C0 W        // N106% x: L- c  K. ]5 N5 v3 B
        if( exsound_select & 0x10 ) {+ ?6 z2 Y6 Y8 p* c- L' a* O+ |: a
                n106.LoadState( p );
% ]4 \+ o2 N" R2 L, n2 X1 g- f, ?                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& |& c! q: ?! h- r8 w6 w  W        }, z* q  {. g' {( H
        // FME71 p% b7 K* C0 o
        if( exsound_select & 0x20 ) {
+ c1 ^; F# ]' t; M                fme7.LoadState( p );
& `" o! u$ Q8 o: G4 l                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 O: f" P% W" n3 F8 W        }
# [3 h+ v/ N0 u/ s* E}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
( Y% T3 J' G4 c/ t" P+ u6 \可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
$ i+ ^+ v; D: @4 N感激不尽~~

( A# j6 J, v* X恩 我對模擬器不是很有研究,) x$ n* r* F- i% Q
雖然要了解源碼內容,可能不是很困難,0 z0 d1 f- ]: W; M
不過還是要花時間,個人目前蠻忙碌的。* J% a- _) F9 ~4 @. {

; n+ o7 I# r( }8 A% v給你一個朋友的MSN,你可以跟他討論看看,4 p$ `! x* V- P+ G
他本身是程式設計師,也對FC模擬器很有興趣。
; E2 c0 A6 H, m% ~7 ?5 t. q# W5 @5 {7 Z8 b
MSN我就PM到你的信箱了。  q2 s0 I+ P. F

3 G5 n9 a' X0 O1 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 发表
4 W5 m7 F, ]0 W6 S7 l& i8 E/ K  x+ w呵…… 谢过团长大人~~
/ a8 s/ N) E2 b
# u! y  l( y3 H1 A9 L/ L, v
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ( B6 |( |( V5 Y' m+ x- h
团长的朋友都是神,那团长就是神的boss。
, \3 V: ?" s: s
哈 不敢當,我只是個平凡人,+ t. l. u$ d7 s5 j: W4 w' T
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
( M- g7 y  _5 |$ {* H& OZYH' h2 X6 R& ~* A4 u9 }# e( Y
QQ:414734306
) P. a& F, A2 Q" f: g: A0 pMail:zyh-01@126.com
9 t& U% s2 ?. q/ e8 E6 [: i( @' |$ u/ ]9 K" I
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
3 e8 Z# s& V. A- V- s再次对团长大人和悠悠哥的无私帮助表示感谢~~
2 |9 |, |0 i4 S
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-31 07:30 , Processed in 1.175781 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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