EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
6 S( j7 T* K) U9 b7 F* QPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。! K; \! [% Y5 I$ e/ Y# [" W
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 f  _" A8 k, @& Y  _5 l
这里有相应的模拟器源码,就当送给大侠了~~& o* f6 `$ e% R4 ~( `9 k. w
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ( c1 K' a7 a3 c$ u# F' G" f& `
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。  k1 G8 l( d1 h$ z9 e1 m' y# h( V
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 n8 Z# Q. e0 K% S, [, P; @: Q
这里有相应的模拟器源码,就当送给大侠 ...

& `/ W1 h. U! D7 C" Y* \聲音部分(Audoi Process Unit = APU):/ B8 x  j3 X/ d; e4 k9 _
.\NES\APU.cpp
5 u! v, A/ u5 u8 h% e1 B4 Q, [.\NES\APU.h4 M8 V' g# \) [' ]5 m; y

7 R# Y5 u( e, \* _+ F% V
. V0 b/ l7 _: L3 q! u影像處理部份(Picture Processing Unit = PPU):
+ g1 j- H8 G# {- l7 \: x.\NES\PPU.cpp
' ~2 Q# T( V1 x' F2 [- [.\NES\PPU.h2 K9 Z! V) ^2 @: c
- U8 g3 m! ^4 x' F
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& E: D, @$ q) R. g- v% s, H7 y
(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 F) ~# ]2 L2 ?4 L5 W7 m
//////////////////////////////////////////////////////////////////////////' v2 z2 V1 `' K, F$ ?
//                                                                      //
3 L4 F3 c) i( |8 O6 p//      NES APU core                                                    //
2 X4 C6 {9 [7 D, l//                                                           Norix      //
/ M8 q: E# R* t) O2 a- X3 l4 {& l# U//                                               written     2002/06/27 //1 \7 t, P8 `: k9 p' h* @
//                                               last modify ----/--/-- //
' t8 O; b" j( \, K//////////////////////////////////////////////////////////////////////////+ n, ^; e8 P9 M9 h! a% F: _4 G
#include "DebugOut.h"" L. {# K4 I( ], l
#include "App.h"
2 `# G: z& C7 x: w& ~: S% G#include "Config.h"
6 l$ O1 O% [; h$ f2 z, F$ l, Y/ J" v
( }- T: `4 d& ?* U7 J#include "nes.h"
1 c7 `7 A7 @* z: M# J5 P3 E3 e/ Q- }#include "mmu.h"
2 {# K) f0 H. `' p1 c( M#include "cpu.h"4 w- i" [! v' \& E- x
#include "ppu.h"
4 ?  K7 o2 l. U* o#include "rom.h"
( \8 w! G' U1 r4 c6 R2 e9 P/ B#include "apu.h"3 S0 X" o- x5 a+ T( N* S( ?" v

! v6 `/ Z; Q' ?7 O1 G8 g: L// Volume adjust
9 b$ D/ k; X6 `- t/ V// Internal sounds/ h4 y0 l+ {1 T- x0 x- p& @
#define        RECTANGLE_VOL        (0x0F0)
7 m$ j& ~7 w' b8 ^  e#define        TRIANGLE_VOL        (0x130)
8 U5 R4 n. v/ R( g3 p, v#define        NOISE_VOL        (0x0C0): ]; P5 ?2 k! z) K4 u6 w
#define        DPCM_VOL        (0x0F0)" D' l( [+ E$ G2 x$ l6 W
// Extra sounds
2 q. E( S3 {# a' Q6 l#define        VRC6_VOL        (0x0F0)! M* l# o0 j- e5 V- n/ I/ x( S3 f1 K
#define        VRC7_VOL        (0x130)
  C" i' @. y  c. e' b#define        FDS_VOL                (0x0F0)+ q* R; F. f$ s4 f
#define        MMC5_VOL        (0x0F0)- S; g) G+ {7 g6 z* F0 m/ X2 W
#define        N106_VOL        (0x088)( k' p& x9 d, x- z3 m* @3 C
#define        FME7_VOL        (0x130)
) ?5 w* b( e! D# M# C
' D/ U  C3 s8 [0 e, B7 C1 YAPU::APU( NES* parent )
1 h5 A% p$ b) X7 h+ L. w{# c6 I/ o. B0 g. g
        exsound_select = 0;
( ^9 Q9 M! `1 \. t
! u, a: s( @# o1 \: x        nes = parent;: ^0 Q# E6 m! h' J* J
        internal.SetParent( parent );" d1 e: Q7 q' P9 x2 M7 D/ r
- [, H8 t) C* j' l5 O$ @/ i
        last_data = last_diff = 0;
$ W$ X- o# a2 X. R2 I" Z2 O2 B. N% f# ?
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );6 A) T5 E) c' E) d2 b3 R) L

2 }4 z! n- k; ~* j        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );" D, _" H) P5 e) q
        ZEROMEMORY( &queue, sizeof(queue) );
6 I5 q2 c1 \% p5 b! W        ZEROMEMORY( &exqueue, sizeof(exqueue) );; p1 J! y+ C, T8 v' b5 w

' N5 G. T! w4 g9 {9 ]: g        for( INT i = 0; i < 16; i++ ) {5 O* ]+ [8 L+ ]5 u) m
                m_bMute = TRUE;
! E2 k! N, J# d/ F  M2 X4 |: B        }" V5 t* j+ a- h+ ?9 O% E
}1 F: p) Y7 a$ c' b, j
- v% ~% t8 L1 z
APU::~APU()5 T) ^! i, ^) L7 Y% e! K
{
+ _8 a% G5 t( {( Z- Q# g  u}
. L1 F8 c6 N$ j: v! F; V
) C% }$ b4 F1 ?void        APU::SetQueue( INT writetime, WORD addr, BYTE data )6 o4 Z5 W# p- n( R$ ~& b1 q
{* z$ J6 R! ^5 Q+ Z+ {: {
        queue.data[queue.wrptr].time = writetime;+ J8 O& m7 ~! C# u: E3 w
        queue.data[queue.wrptr].addr = addr;/ R% {) [  L' W2 D9 l* |
        queue.data[queue.wrptr].data = data;
8 I  _; O5 x  G5 [! x        queue.wrptr++;
0 i, A4 G& N8 b9 z, V! T        queue.wrptr&=QUEUE_LENGTH-1;! b1 \# g* x) U
        if( queue.wrptr == queue.rdptr ) {& o9 X  _! Y. R4 Z, y  f
                DEBUGOUT( "queue overflow.\n" );
: Y5 V' @( b/ y0 l        }
2 D9 |" s3 @& w; y7 B}# x& _; g* j$ r% i& n# ^
! r! V5 {: Y) i  M, Z0 f
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )( ?% u/ ~, w% h7 F* c- |- }1 u( s; L
{% q0 g, m  I$ d: I2 ^
        if( queue.wrptr == queue.rdptr ) {, u( ?* F, b8 f2 x- [
                return        FALSE;8 u/ b" n7 X9 S# R
        }. F* f  M" Z( D5 n) ^: R# \2 J1 v  d
        if( queue.data[queue.rdptr].time <= writetime ) {
$ r7 p2 [4 `1 J: R+ x- q                ret = queue.data[queue.rdptr];
& ^. E1 D' R1 ?                queue.rdptr++;
" M) D# x" {, a( ~/ j                queue.rdptr&=QUEUE_LENGTH-1;' p5 W4 c9 |- v" g
                return        TRUE;
, ^- s: M6 X( X" h        }
2 K5 z& K4 M+ \        return        FALSE;* C  [9 ?. I9 e
}
- B8 @% m. }6 _+ x. x7 O/ ?% f6 _% M0 D& C. |  J3 T8 V
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )& d! I" z% u! D8 N% B
{
' n# s. z1 p; j3 \        exqueue.data[exqueue.wrptr].time = writetime;. d8 k- _) r* x( F" H3 N0 o
        exqueue.data[exqueue.wrptr].addr = addr;
* P8 m& Q5 C9 @( ?2 B& J        exqueue.data[exqueue.wrptr].data = data;3 i. V* D% h, q
        exqueue.wrptr++;5 Y. L. e* f* X3 x9 h: u
        exqueue.wrptr&=QUEUE_LENGTH-1;
( V" R: k. o& A: y) {        if( exqueue.wrptr == exqueue.rdptr ) {( [% Q2 O9 S  v! O
                DEBUGOUT( "exqueue overflow.\n" );2 e" J# i5 V/ ?2 [3 M  w5 h* K( r) m
        }" |3 q+ K, q. E: q2 a. b
}, t; r/ J8 a0 @+ O% V5 j
. p6 w7 z. O1 u9 _% J
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
( G& ]- ^( [2 a& j0 T6 k- q{
# k& O; i  M3 u/ W9 x/ W        if( exqueue.wrptr == exqueue.rdptr ) {5 m8 U' D4 X& p$ Y0 p! p) p6 g# @
                return        FALSE;' |/ w$ L+ ]0 h2 o+ H# j; z$ l5 j
        }
5 k& g" C! ~, U; O+ q4 Q# P        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% c- S, N9 Z" O. w
                ret = exqueue.data[exqueue.rdptr];
. J$ W( A$ c6 |% r+ U                exqueue.rdptr++;
! d+ y- a$ Y5 t6 P# s- @$ K                exqueue.rdptr&=QUEUE_LENGTH-1;
. K$ _7 N/ I# Q) l, \                return        TRUE;4 s' {' _, f7 l% d
        }, A: }+ ~9 J& Z
        return        FALSE;
9 H3 ^& H6 F+ R+ t( ~" [! Y8 ~}
" h; B. k4 Y3 ^
5 i8 T- \$ A. q; C. Y6 ^) a: Avoid        APU::QueueClear()' _( \; A/ L% a' _
{
: n* `7 {1 L8 Y% e# Y        ZEROMEMORY( &queue, sizeof(queue) );
- C4 K" [, g3 u2 n        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 ~2 r" Q" n1 u2 K7 q( G$ ]  C}
/ i# ?- X. v  v" W% ?1 Y5 n* F8 p! y3 O5 o
void        APU::QueueFlush()
5 b) F  e4 K3 D6 N{
; [1 b7 Y4 I6 `" L. j( m        while( queue.wrptr != queue.rdptr ) {3 j. I; Q3 c# U" F
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );$ f+ q* m' N, L: S
                queue.rdptr++;% n  m1 E  G& u. C3 G2 ]$ F
                queue.rdptr&=QUEUE_LENGTH-1;
& c2 J; \' c7 D- G+ q: K        }+ q0 c, l/ R  P

" P1 T- }2 s2 U5 h        while( exqueue.wrptr != exqueue.rdptr ) {; N5 S  B0 {; l, b, F/ f( o
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 S: y- o, [+ v4 t
                exqueue.rdptr++;) I4 M1 z& Z+ b! `
                exqueue.rdptr&=QUEUE_LENGTH-1;
& @, E( v; r. N" T0 c        }* E6 b$ N. p- o% S
}/ S+ k. i6 R; _3 d

3 w! H$ d& s, T1 R9 h7 qvoid        APU::SoundSetup()  Z" `. s# F8 |. w
{
8 X5 Q3 k3 ]; p5 v        FLOAT        fClock = nes->nescfg->CpuClock;
: @% Q; Z  U$ Z6 [2 ]/ I% L        INT        nRate = (INT)Config.sound.nRate;) Z3 b1 p1 P4 {( h( u
        internal.Setup( fClock, nRate );
% O: a9 N! d7 L. b5 d" j        vrc6.Setup( fClock, nRate );
6 v1 ]7 a3 {+ r! `& h7 w        vrc7.Setup( fClock, nRate );
1 R1 M# J+ N. X9 a$ Q0 U+ b2 X: k        mmc5.Setup( fClock, nRate );4 @/ f! d* l; M$ _0 `. ]
        fds.Setup ( fClock, nRate );
' }- _. d' r) v( ~: r) K        n106.Setup( fClock, nRate );
& ~) v4 p$ U4 G- ~        fme7.Setup( fClock, nRate );
, ^. x/ ?( C& F6 j' U}) w. ]) i6 a; \" U  t/ K

4 u2 r* p& m  avoid        APU::Reset()
. @8 b! h! H0 y{" l* Q8 P; l" ]; x, ?+ ^
        ZEROMEMORY( &queue, sizeof(queue) );
  |3 |/ c. P8 d0 f/ G        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 }( M% e5 c7 F3 s$ L9 l

8 p+ M8 {- v+ S% G: t" r9 @        elapsed_time = 0;3 C! |1 W: Y, S+ M+ E/ [
8 n( s$ b/ b6 |5 [
        FLOAT        fClock = nes->nescfg->CpuClock;
3 P2 t0 N$ }8 y6 n        INT        nRate = (INT)Config.sound.nRate;
% H1 e+ ]% ]. D  D        internal.Reset( fClock, nRate );
3 \- Z+ `* E5 [, s! M# s6 S' _        vrc6.Reset( fClock, nRate );0 b6 [5 V( }% Q
        vrc7.Reset( fClock, nRate );
" U8 V% I: w+ g        mmc5.Reset( fClock, nRate );7 F# n/ B- p6 d- a
        fds.Reset ( fClock, nRate );
! m6 c( q# x4 B9 q. w& W5 V5 v        n106.Reset( fClock, nRate );  B" k  |! L) R! Q
        fme7.Reset( fClock, nRate );
& W: R) P$ R& p* J7 i1 z1 R
/ J' L$ x% V8 z0 k( Q1 R3 }        SoundSetup();
5 l" K+ Y1 C! x4 @}# M# W+ f  E- d; y

5 K6 o& k) X/ D& |void        APU::SelectExSound( BYTE data )
+ T, J* r# U9 u, B6 T% f{/ `7 Y* {9 ?' W8 z6 D8 m( d1 _
        exsound_select = data;: m# P+ P  C( W# d2 E9 t
}7 i" a# ^2 j% a- ]1 F* o' U# M
7 m$ {. b6 r0 W# i; a
BYTE        APU::Read( WORD addr )# e, C7 C3 ]8 g4 f: R; S) m
{
" f& x0 _- _. H! R4 {0 {, |        return        internal.SyncRead( addr );
2 A. S; P) D# W) Y$ W. R}; p" A9 M: Z1 \- r+ k2 R5 R& n
3 n6 ]* c) I8 b% ~4 s' ]) Z- c
void        APU::Write( WORD addr, BYTE data )9 g& C8 ?* C7 O. [* v8 R' |
{
7 @  \. ^$ Q- Q  a8 k        // $4018偼VirtuaNES屌桳億乕僩) n: t3 c+ `4 U) }4 z9 V+ g5 I* q+ c+ k- Q
        if( addr >= 0x4000 && addr <= 0x401F ) {
6 j7 U1 m$ m) m$ d1 E/ F7 `                internal.SyncWrite( addr, data );! e) u' A  z( h( ]$ e5 n0 [# `3 p
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );- \. @2 z) P' E6 `! f1 O" N
        }4 K8 q: v2 z. L0 g( \0 @" C% O
}
" J* @3 Q" m+ S! y; U3 L+ }$ h. P9 [: M; z* g4 A, ?
BYTE        APU::ExRead( WORD addr )
9 p! M& R7 e7 d0 @8 t# s{2 i. G; }: e2 `
BYTE        data = 0;2 o8 z" H  G. U6 }- H6 u6 g4 p
% Y5 c4 o6 c% ^, U/ w0 r5 I4 S
        if( exsound_select & 0x10 ) {# d. {7 J" `8 d9 w6 \9 G
                if( addr == 0x4800 ) {
2 w& l/ k; Y* \4 W5 G                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
0 _$ B6 f  y' F% a8 ?, a, x                }) Q' ?3 z* D# X4 A- S6 m2 z
        }  _# M! k  _2 H: W
        if( exsound_select & 0x04 ) {
% @/ G4 M! x/ u+ ^( P1 z$ a                if( addr >= 0x4040 && addr < 0x4100 ) {
* z( Q2 _/ b2 @7 x8 R                        data = fds.SyncRead( addr );
8 Y: ?- |# d' B- M* C. E                }
7 w  M4 A# m' j/ c; f        }
- D4 J9 u' j$ Q& y% _' ~8 _        if( exsound_select & 0x08 ) {
4 S+ {; h: V1 p$ Y  t                if( addr >= 0x5000 && addr <= 0x5015 ) {. Y6 A& {! P7 V+ J5 ~/ x) z% b$ m
                        data = mmc5.SyncRead( addr );: M. v5 B' x+ h
                }) b( E8 |. r! b  ]9 I
        }
9 j" I9 H  m# U# v! Q+ K- e8 A, A. K
        return        data;, M6 u9 m+ g; y1 w& d
}+ k; _) R+ C" E
* p4 N( y/ N( F0 Y1 j, z
void        APU::ExWrite( WORD addr, BYTE data )
7 _3 Q/ S- {2 `4 `. K{
6 g7 ~- E" E7 q8 b3 b6 b: P3 g4 b        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );% ~  [  ?3 l+ c! |
0 v8 Z7 e. K' Y; @  E
        if( exsound_select & 0x04 ) {
4 _9 i& k/ S; z* d9 o4 G                if( addr >= 0x4040 && addr < 0x4100 ) {. S4 }9 f, q( G/ R. r; i1 C' C
                        fds.SyncWrite( addr, data );
" X( x) q# h" }                }
$ P( o3 _7 E* v/ L  j        }' B$ [" |" }$ J2 M! @5 X
. m1 [$ `6 R1 g
        if( exsound_select & 0x08 ) {. \$ L# j" p9 D7 F8 o
                if( addr >= 0x5000 && addr <= 0x5015 ) {8 \/ x& A( U* n1 P. x# q4 N8 P
                        mmc5.SyncWrite( addr, data );4 p6 R! w) Q: K; W5 q# q. V
                }
, }2 I' B0 I! P        }. R0 k! o. C; C6 X3 |
}
  W. W! m; |, e% _" J- k7 _7 w) X6 g3 |- }) j! }  O
void        APU::Sync()3 C$ F& t0 t: m
{
, O. N' r. N- p- P# }}
2 R  p* ?3 R) x9 o, T4 n( _
) b* I& w4 L+ N( J. e) Y' Lvoid        APU::SyncDPCM( INT cycles )
. u; v; O$ `3 x2 z{
2 P& o" U5 l( T" t        internal.Sync( cycles );
. W) X$ y/ F! m+ q$ m7 h8 ~- G4 c2 q' p7 s& Y7 d  H
        if( exsound_select & 0x04 ) {" w9 ^% @5 g8 c7 t# b' |
                fds.Sync( cycles );
: v8 o% j0 V  K. g9 F! a        }* O0 J+ v# F, L* Z: N4 O
        if( exsound_select & 0x08 ) {
8 h; W7 U; {9 T. d3 w                mmc5.Sync( cycles );0 [+ p  M- U# j5 s7 \0 R; O: K4 B
        }* g& R/ }) u, G: e
}
6 l& H4 u" e; f! k, `$ m, b6 J
8 K& u3 k7 T; q& Q4 m9 t  |void        APU::WriteProcess( WORD addr, BYTE data )
: x! o5 p2 Y; h; J0 l$ r3 F{
. X: p5 S- u% l" C) p+ ?' i        // $4018偼VirtuaNES屌桳億乕僩
* y9 F" I0 N5 `: z1 ?, U8 F1 D+ D        if( addr >= 0x4000 && addr <= 0x401F ) {5 q" C, J8 ~6 d$ ]: u) @6 ^+ o1 A
                internal.Write( addr, data );
& r8 P. {$ |( l* j# \( F" h5 G        }4 z0 l$ n, |' S
}
3 @& P+ N' x: [- y2 g! u
, _$ k! a0 Z5 i( p9 }! ~6 o% svoid        APU::WriteExProcess( WORD addr, BYTE data )9 n+ \# I  r9 v/ X2 S/ T1 E
{8 x, K8 D( l; V
        if( exsound_select & 0x01 ) {
0 ]+ C, ^7 E8 S/ p$ i' M1 }5 W' `                vrc6.Write( addr, data );
5 W! M6 D2 L# H6 S0 z9 ^# J3 t        }
( w1 o& h6 o- y& ]        if( exsound_select & 0x02 ) {7 ~& O' p' F3 W5 }
                vrc7.Write( addr, data );
5 {. a' Z$ i3 X( M/ @3 i        }
* a4 ?8 l: ~' }, R1 W        if( exsound_select & 0x04 ) {
% Z. a, s! c& |- R, q# u6 n9 A                fds.Write( addr, data );
. _- ]5 |4 c+ B+ a  w, c9 E) q        }
: D- Z& f( Q/ X1 f1 R        if( exsound_select & 0x08 ) {# b/ z9 I: E- ?+ T% n+ n
                mmc5.Write( addr, data );* p9 b) Y& r; [
        }) N0 V8 B$ ]: c) Y' ~0 |3 b
        if( exsound_select & 0x10 ) {/ O2 @3 l/ M' {" p$ _7 m% x8 u
                if( addr == 0x0000 ) {
$ K3 z: n" |/ {& m3 r                        BYTE        dummy = n106.Read( addr );& c; U, C6 D/ k
                } else {
1 n) T* s* s; L1 M                        n106.Write( addr, data );, l- ^$ w$ S& S3 t( `
                }( }% `5 k: x6 x& ^
        }
, v+ n4 r' D, Q6 i& M        if( exsound_select & 0x20 ) {
. v6 N/ ^2 n, {$ I. B                fme7.Write( addr, data );
* P- V5 b- L1 K2 l) k) T- m; K        }+ o6 q  H2 K4 v/ [1 ]$ _& ]
}
( a, l( ^$ g" z$ E/ u0 V7 d) W" l0 c1 @* H4 V
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 H' v. |* F6 H{/ N7 E7 t. \. F+ W
INT        nBits = Config.sound.nBits;: p: k4 @" Q2 `0 e! v5 ?! }
DWORD        dwLength = dwSize / (nBits/8);
* _* `5 I, c# ~: [. S/ E" zINT        output;
& Q5 r# S( M+ bQUEUEDATA q;& B3 A4 X: R6 I2 e. a2 e& X1 S& y
DWORD        writetime;
; @4 y; U/ ~- p1 Z
  z$ u1 w# l/ p7 P9 A: DLPSHORT        pSoundBuf = m_SoundBuffer;
  U! h9 k. _8 yINT        nCcount = 0;
9 k; J- |. g( Z0 i+ ~  N
1 |& P% @: D7 ~3 U* v( zINT        nFilterType = Config.sound.nFilterType;
) l. |/ t. I) j; y
1 r1 N/ R/ m. n# r0 N        if( !Config.sound.bEnable ) {9 i7 s. _1 J. u3 O  `
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
& B# H) e' U0 X8 ^; l( a4 x  H8 t                return;/ L' w# P, m) U' B
        }% e$ V6 p* i1 |% m- V
5 ?4 I& g+ F. ^
        // Volume setup
  n  q0 D6 {  S6 r        //  0:Master
8 E2 ?* w9 A# \2 R  s: }        //  1:Rectangle 1$ R  R- {6 b0 F  E" s1 e* g
        //  2:Rectangle 2
# k. {8 J, p' ^3 B( Y        //  3:Triangle
  B4 }6 b# Q8 v  E5 M, }& D( H        //  4:Noise9 _& e/ W7 z" e, @
        //  5:DPCM
. B$ h9 K/ K7 n# r        //  6:VRC6
" l, {1 y# x, n! k  Q! Z        //  7:VRC7
8 ^: V! q: P- [; g$ V0 i4 s9 G  V        //  8:FDS. f2 r5 b" j( q
        //  9:MMC5: W- a( i$ c! c$ Z
        // 10:N106, ~. O; M- v9 ^6 s  |
        // 11:FME7
2 c: t0 ?9 e% ]. l+ G5 s        INT        vol[24];5 S& }* M4 Z# Z
        BOOL*        bMute = m_bMute;- l" W0 a3 L, w% t; V+ y
        SHORT*        nVolume = Config.sound.nVolume;9 t) Z5 g  k0 B) W

3 _/ C) B  f, D: j" R4 W3 R        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
* V" n7 D2 c" f
- T6 F+ ?, }5 E# Y        // Internal' ?; h" Z: j" V. l' Q3 C9 H
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;- [8 }( i% L  G: Y+ r
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, E, X) P6 Q3 _  Q* n2 ^3 n        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;( p  M! M$ S+ W) n. H0 J, Q" Q
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;. p& u/ h- |$ X3 }
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;8 Z  ]4 C' _% n3 x$ b
8 V+ X; K1 K+ w2 ~: I
        // VRC6
& J3 Q5 }5 Z/ V! u; e; x        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ ]! b6 r( O: j: M2 P! C
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 V, m" F! j6 N8 f1 v( O
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 V) f, O2 L) I$ m

' E- ?# D& a' w$ m: }% H5 b        // VRC7$ J/ Z" U- G8 X# R/ |
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 C- l1 I9 ~' T1 c- Q3 m

/ k8 _  N% t% Q  x6 y        // FDS
% W) E2 j6 \0 U  x        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;4 x# \; o$ {6 ?
  R% p$ U: c! ~) n7 L7 M3 r$ q
        // MMC5
* q/ e1 A  Z9 G/ }! {7 x5 ^        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;- P! Z8 K/ \& L2 P: Q4 \
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' g' w- B' ]  h( K. s        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! _$ D/ M- Q, O
& W7 [* {, G9 R4 @        // N106
& Z% q2 ^7 T- R! h, s        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& a- E* Y- I& {  d5 Z' d9 X- t; C        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% G9 _. V, V$ f" Z5 p  }        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( y5 e+ ?' l% A8 Y- n% o
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 w  w" i3 p  N0 _
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ A& i. j5 C8 B
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% y4 z. f% S0 \        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- c! M: x: Y- e& O4 C0 Q
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* ?$ m4 `3 G. M" `

/ N$ w) H6 v7 @; ]3 `+ t) ]; d        // FME7
: {; h. x& x" i& D1 X' ?7 t        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: p1 m( t$ p2 z3 n, @) ]0 a" r        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 J5 }4 {! P3 ~( J. ?$ R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 R! i" ?. m6 }, I( }5 _# k3 w: Q: l
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;( I  }' `* A% g, U8 ?
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
5 H: b) q) r  [; V, q" v  u
8 `/ A. G: S3 `  C3 c( C. k" E        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
" I/ F+ V- ?5 f% U        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
- K( F, [5 }& ^1 A" u                QueueFlush();
7 Q! d" i! j) L" B. V. M2 d. }9 y9 \        }
% U$ ?% M( X) F* a+ t) ?- h( G
/ w, l# P& T3 a0 w        while( dwLength-- ) {2 `* u! `/ t2 d3 g: f
                writetime = (DWORD)elapsed_time;
* u6 [! Q- F. r# h: A3 b- O! n- b7 S- r
                while( GetQueue( writetime, q ) ) {
6 u) }; r1 O  D7 E7 Z+ }" ^4 j: S                        WriteProcess( q.addr, q.data );, E+ K4 u3 D% q* `, n9 G/ ~( Q
                }. J8 `( r( |2 I, s4 K: w$ s

% Q3 b/ o% X+ ]" y; X                while( GetExQueue( writetime, q ) ) {( p1 h- p; v+ f# m
                        WriteExProcess( q.addr, q.data );' [% S5 j" R+ x' c' [% t* s
                }
$ u( z: N* W* k* K' w4 V
6 D( g  H0 r& v- t4 w4 H7 `                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME71 ]) B1 l+ R1 e+ ^' i
                output = 0;
! g& H- [: L( k( z7 S9 T                output += internal.Process( 0 )*vol[0];
/ r9 D" o  y4 n( ~. {, N) Z7 A                output += internal.Process( 1 )*vol[1];
% _; b4 Q! Y. ^3 W& [                output += internal.Process( 2 )*vol[2];& e- u4 z/ V& W' [# i  P
                output += internal.Process( 3 )*vol[3];( L3 D) B6 J, o
                output += internal.Process( 4 )*vol[4];
8 r/ F) x9 T; \% |5 `) @
* ~# C  _* e% f                if( exsound_select & 0x01 ) {
9 Q% a/ v( s# N7 ~0 t) z6 z                        output += vrc6.Process( 0 )*vol[5];6 V) d8 g  ]# r7 u
                        output += vrc6.Process( 1 )*vol[6];) {! L: u) Q9 l( o+ n$ ~
                        output += vrc6.Process( 2 )*vol[7];( p$ M7 o/ B: L. U8 J8 B
                }
7 r" @0 c2 `& f: E                if( exsound_select & 0x02 ) {
9 \- y: a6 [2 y& B' H( b& p                        output += vrc7.Process( 0 )*vol[8];/ a/ A7 S) O9 b. d) c7 P% Z, {( w
                }8 E/ m( i. t2 K6 K
                if( exsound_select & 0x04 ) {
$ S) V" v3 n) e1 F; T8 [8 @                        output += fds.Process( 0 )*vol[9];
- g8 r# u" ?0 J+ ~+ c6 q. @8 C6 }                }: v* A1 F. G# L
                if( exsound_select & 0x08 ) {8 E2 b& }8 K, z3 D, w( U! l; s
                        output += mmc5.Process( 0 )*vol[10];
' H/ I; _/ R$ U* e/ B7 ~: v                        output += mmc5.Process( 1 )*vol[11];
7 h4 |; T/ D  u4 ?+ Q                        output += mmc5.Process( 2 )*vol[12];
' v! F- q) l- j4 J# G- B/ y                }$ R' @. f1 S9 d
                if( exsound_select & 0x10 ) {' V7 `0 ^0 ]& h7 g' r9 r
                        output += n106.Process( 0 )*vol[13];
5 \$ ?( h5 D4 ]' w- V, p) B                        output += n106.Process( 1 )*vol[14];) z0 `0 e! d3 K6 P* P
                        output += n106.Process( 2 )*vol[15];; B' C5 Y! T5 i" X" d
                        output += n106.Process( 3 )*vol[16];5 I, K; u4 L8 |+ q; h
                        output += n106.Process( 4 )*vol[17];
5 `/ g8 g( \- s- W$ W                        output += n106.Process( 5 )*vol[18];
3 U5 B/ G; @2 u; t                        output += n106.Process( 6 )*vol[19];; d- K. c& o/ M; q# p
                        output += n106.Process( 7 )*vol[20];
8 }, n5 R' h3 r$ P6 ^& X8 B                }$ r# Q$ {4 D  c
                if( exsound_select & 0x20 ) {
3 x" F9 H3 ?; E) i" p& |5 ^0 Y                        fme7.Process( 3 );        // Envelope & Noise
0 B' C" X8 U) N9 l9 }4 S                        output += fme7.Process( 0 )*vol[21];
5 ^( L4 A- G+ g5 K. t& o" {; g  N& |                        output += fme7.Process( 1 )*vol[22];
' X4 S. K( V# p( x, U# a                        output += fme7.Process( 2 )*vol[23];' F7 t, e: O% @1 r
                }( i1 y- F; T1 r( R& |1 G; F- Q

+ e5 Z0 K( C8 ?& T& Z                output >>= 8;
: R6 \( i# `& c2 j/ t0 z: h2 g  S8 V0 v4 t+ V5 W4 V% |
                if( nFilterType == 1 ) {* l% X' p' C( C# ~7 q( A% C" E' N
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
7 X: J5 R+ ?! f) L/ C) N1 H+ m7 u( y/ F                        output = (lowpass_filter[0]+output)/2;
- ?4 v  A% \% ], B                        lowpass_filter[0] = output;
/ T# ]+ F" o( [6 P% ~. V  i3 ~                } else if( nFilterType == 2 ) {5 p( ?5 n0 b& ~% ]
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)  U) P0 U1 N3 U/ |" y
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 K' h1 M; F0 Y& L  Z; D. ?3 q
                        lowpass_filter[1] = lowpass_filter[0];% W5 {: A  k& W! G
                        lowpass_filter[0] = output;5 d4 [/ S  v$ `; Y% s8 z' X, ~
                } else if( nFilterType == 3 ) {
8 z$ z8 D* l& G7 F                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
3 S: {2 a' ~% I- l' }                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;; l) S2 R; I" I
                        lowpass_filter[2] = lowpass_filter[1];! k( l( c5 m5 \, k
                        lowpass_filter[1] = lowpass_filter[0];+ O: J& X1 \/ Z" T5 Z- ^6 N1 [
                        lowpass_filter[0] = output;& o: j) H. B0 t9 u1 y; d
                } else if( nFilterType == 4 ) {+ P: q5 l  I0 g0 q8 S0 O+ k
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
" l2 {. D, s4 S4 p                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;% t& m& t$ G# @- H5 i
                        lowpass_filter[1] = lowpass_filter[0];2 v/ z$ h' I0 u3 T2 b4 p8 C+ q6 d
                        lowpass_filter[0] = output;
+ @" ~! K$ D0 J! B  H% b0 ?. U: A9 c                }- P/ \% V9 s$ ?# Q7 d

  }& }5 l4 a" P8 D: k#if        0
' r6 c; ]) v+ A( C                // DC惉暘偺僇僢僩: q6 }5 |0 x( }/ f+ d
                {
8 b1 L# M# L- p4 y                static double ave = 0.0, max=0.0, min=0.0;8 ~$ Z# K5 n/ q; y& h
                double delta;
1 \' J: l, F9 C/ ?1 d% r                delta = (max-min)/32768.0;+ J9 c5 V7 D. b  E
                max -= delta;
3 C; ]$ [, S5 \                min += delta;
5 y( ~" v( \3 Y                if( output > max ) max = output;
; x2 C- ?  W6 f3 }6 M' m                if( output < min ) min = output;
. d4 {, A/ a' M' ^8 G, m  g% l+ Q                ave -= ave/1024.0;
  U9 \9 D2 x# v% |7 K7 X. ]+ D. [                ave += (max+min)/2048.0;
2 b8 G7 U2 h& N! T7 V. i5 V. I                output -= (INT)ave;
% L" ?* g# l+ a8 Z, M* z. L; J6 K; r6 V                }
- |  j- `2 F# k#endif
6 X, l" x" B/ p, l  I#if        1
* h' _' L: x' x& T3 j                // DC惉暘偺僇僢僩(HPF TEST)3 j0 w& m1 Z: [# g0 L6 M$ g, \
                {+ P1 R* _) F+ P1 J2 o
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
3 j  H  P8 w; q2 a8 y2 J& ^                static        double        cutofftemp = (2.0*3.141592653579*40.0);
4 `2 V3 L3 e2 d8 K3 W! \; X                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 F2 U+ G( v, `' b7 _8 V                static        double        tmp = 0.0;3 g9 s( \, E# X6 w6 N. `: \: e
                double        in, out;+ d% n# H. E% c2 V4 _% B: H0 k

8 p) y9 A- D& T0 H                in = (double)output;
; C& K/ ]+ p; W                out = (in - tmp);
& t- v1 D* I* G" K2 U" H                tmp = tmp + cutoff * out;" O. [  X  Q* ^

. G: b9 Z* [; e: X7 \) i                output = (INT)out;3 _- t, V& Y) ~" L, d
                }
/ k4 Z9 p' \7 D% ?; [' V- q#endif( R1 w- l& T, }
#if        0
7 t; a) a5 x) U" }8 M  a4 j                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
0 F6 O5 ^8 y# h) c7 T8 _. ]4 t                {' N2 w( D2 T$ p4 v+ f- t* e- h
                INT        diff = abs(output-last_data);
" o6 ~. |- O2 f: q7 ~. J& @                if( diff > 0x4000 ) {/ X# v4 K6 }1 L- a- S
                        output /= 4;3 Z5 m% m  _; b; F: ?
                } else ' j( `4 F4 L  r0 G6 W( X
                if( diff > 0x3000 ) {
4 y  K% J4 ~( o7 ^2 H; {: `                        output /= 3;
5 N& i% d- g$ f  i; P                } else" i, E2 i( P/ h9 p
                if( diff > 0x2000 ) {
" V5 u' B( I: Y; E                        output /= 2;4 q. m5 S/ X+ Y+ K, t# x( p8 ?; B
                }
% q/ j/ n6 S1 Z/ l  P( |4 |                last_data = output;
3 J+ F4 @% d6 U% B0 @7 [( W; V' n# N                }
& x& C3 C- k( f#endif
+ v/ W( d# A2 h$ H( K4 ~3 b                // Limit" W" L5 O! E# r$ C$ u" V* e( k
                if( output > 0x7FFF ) {
. o/ ^) l; x$ K' |) ^                        output = 0x7FFF;
0 L- }9 B& H+ }1 t  r2 h. P                } else if( output < -0x8000 ) {
  x1 |( i8 u" O8 R# D4 L' J                        output = -0x8000;. x3 j4 b3 v( N
                }
0 q2 E5 ^, P9 \
6 b; S5 `' {* F- K3 V                if( nBits != 8 ) {3 \; _+ @. e0 K( s7 r& A0 i6 I
                        *(SHORT*)lpBuffer = (SHORT)output;
1 A5 h& w6 d" h# n. E                        lpBuffer += sizeof(SHORT);
3 [7 R- U7 m- O' x0 h% G* M8 M                } else {/ w* v1 Z' Q( A4 K7 L$ U- y
                        *lpBuffer++ = (output>>8)^0x80;
( H5 N; ~& {; X8 `/ H4 _7 J- x                }
8 {  |2 H6 X8 ]/ h! ]+ g% ]
; Y% u$ j7 B8 E& ^                if( nCcount < 0x0100 )$ b3 h, N( P; f0 f  s
                        pSoundBuf[nCcount++] = (SHORT)output;7 G; R9 {0 k5 L% s1 O  z7 [' k% N

! T* n1 _9 l8 R/ q8 S4 Y- j' b5 p//                elapsedtime += cycle_rate;; x7 N6 F0 w8 T- z6 @
                elapsed_time += cycle_rate;8 a0 \" w, k9 m/ Y  }4 _+ u) K
        }- n9 Z* a6 v  H& x# z' i5 `: m

( Y' U2 ?9 O( t$ t: S! c% b#if        15 K# V( X* B) K  D, k
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
3 J$ ^5 n; d+ Y6 s; u9 P' a                elapsed_time = nes->cpu->GetTotalCycles();8 V3 h( a) n" w) ?! r/ J  J, z/ k+ R
        }  j% ~9 ?/ w% E
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
* F# Q! q5 f) q8 J1 k& M, q1 Q- Q% m                elapsed_time = nes->cpu->GetTotalCycles();2 c2 n2 q  V% e) R* p7 e4 g4 F
        }
# \, v& ^+ Y! I#else
- c, N, l7 e6 H$ b6 D; W( q* U4 G1 ]        elapsed_time = nes->cpu->GetTotalCycles();0 z* v4 I0 x, t* V' P, U
#endif+ F' f2 N/ a) w' V4 Y* a
}
$ u$ N! j' ]& h. A9 n
& l/ y, L8 w6 ~7 E( F  e// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)2 [! ~" v; Z8 C0 C0 ]: U# l: n$ B
INT        APU::GetChannelFrequency( INT no )
/ D, q4 ?' `3 d{6 |( W$ O6 T5 m5 s5 x9 P' M
        if( !m_bMute[0] )
! G- C% y+ {& `                return        0;
, D3 D8 @  N& H0 x$ z' G5 C8 w* E: B. u% G" k
        // Internal0 n1 e1 p7 Y4 t* ~% L* y- Y
        if( no < 5 ) {
% c" O4 a3 b; U. ?                return        m_bMute[no+1]?internal.GetFreq( no ):0;
6 L8 p7 }' o% m) k$ w# }' q        }
/ j( w+ r) g% ]& Z        // VRC6
! q7 v  J. g. k- L: M+ l, i& ]        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 F; I1 u7 g- v7 R( I+ v, p% o6 [8 b2 R                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;! J! w4 u4 F% t! a
        }9 |7 h# U* c. N$ `, N9 L) Z, ^
        // FDS: k, c3 V3 o" m7 j8 I
        if( (exsound_select & 0x04) && no == 0x300 ) {
- F5 B1 Q) B' A                return        m_bMute[6]?fds.GetFreq( 0 ):0;; R$ n$ p6 \/ E! k* u5 C; ?
        }
) _8 O  ?7 u$ O& [: ^, l$ o        // MMC5
, r0 M( F2 e( Q& W        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: v7 J& r0 j2 g8 y
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) G9 n' T; w4 B: n& Z4 _4 A        }: l( B0 y, y6 g
        // N106
- b( q! w" ]1 u# ^        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {# }6 J( d4 I# ~; P" U0 k# e  ~
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
. ^) q4 f2 Q& o: T        }
2 ]+ k4 c( z& V- [$ f8 `        // FME7
# c  f5 t4 z, g. R# z5 j4 y+ \        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
7 O1 P! ]. @9 C% O( I                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;( D: D) ^& X) j6 G% A" e
        }* z, y. r& H) q  Z- l7 @! r
        // VRC7
7 M9 U# y5 a& D2 `, J/ f; t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {& G, q$ ^) \2 Z3 u, R
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- m: [* x0 l2 n
        }9 J: g8 ]: o" U" d
        return        0;9 e7 q+ f3 v( R, O' b
}
& V  B1 f" n6 h- R3 A  i& r/ C' n# r
8 U+ H7 [) c4 i// State Save/Load9 T$ F' Y6 H9 m7 |0 z1 v
void        APU::SaveState( LPBYTE p )( x- ]: D% ~0 ?1 r9 \' u9 h
{
/ M) m. D$ B/ c0 a8 F#ifdef        _DEBUG+ {% u/ h& n5 O
LPBYTE        pold = p;
. {. `/ W8 }: A9 ]( ^; F5 ?# _#endif, L$ i  V0 K; u3 `' V1 |0 G

1 C& v" I% i0 p' j8 d; b; h        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞9 _' d* R5 D% p: |% |3 Z) g# h; }
        QueueFlush();
5 y0 `& Y# |! X" W2 n/ A, `4 g
' H0 z, Z" d% R6 m' b! }, D9 W        internal.SaveState( p );
0 T7 K/ [0 C; H) g! Z. h        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 @+ J! O! }* s7 J9 O9 ]
7 M* k  g/ K( X; O3 q5 _5 w        // VRC6
* \9 p/ }+ t6 u5 e8 J5 {, X        if( exsound_select & 0x01 ) {" V6 L- ?) H* H, Q9 J
                vrc6.SaveState( p );3 ]5 C! d* J( Z  ^+ O+ O( I
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: v. P% P% B2 Y        }0 B% p( m( z$ _# {) n' ]1 |
        // VRC7 (not support)1 g3 r4 S1 n2 f6 B& A  V" o% v
        if( exsound_select & 0x02 ) {4 p& n: t) ^5 z& C  g0 e
                vrc7.SaveState( p );
$ J6 Y# p# x5 T+ ^  I                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 A6 I  G% z8 [( S        }9 y  b6 T6 N/ I6 A' n7 [7 r0 [$ m
        // FDS
- A; o0 t6 C  j/ C        if( exsound_select & 0x04 ) {" D4 g) F- q4 D% u
                fds.SaveState( p );
! H8 R7 z, }* f; y/ i                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding  l- q; @7 ]2 C$ O( b( M
        }  r5 g3 ^! B2 D& B. M, |
        // MMC5
+ z; P: B1 U0 V8 E        if( exsound_select & 0x08 ) {( s6 S+ `* B0 X! q
                mmc5.SaveState( p );
& z7 `- k8 t3 h8 A! _1 d                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
% x+ u, ^% ?: o2 J        }' |! c# D9 q1 n% Z1 \2 q6 y# l
        // N1062 R+ o0 D$ b; ]3 g7 }+ C
        if( exsound_select & 0x10 ) {0 {3 a3 a. E7 _7 A
                n106.SaveState( p );
4 X. N5 N$ y2 i. ?- Q$ C                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* N, y# E+ u/ o" W, g3 K" m        }
) c( k& h! j8 o" G        // FME7' D" q, z  o. L
        if( exsound_select & 0x20 ) {# p5 P3 |, y+ `. ~
                fme7.SaveState( p );
0 ]& ^5 r7 b. L% O                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 N+ k! y% Y  U9 _7 Y/ T6 V% v        }
2 t) J" w2 l% K5 C3 i( u' L8 i" r6 W) X+ n+ y% V9 z/ q
#ifdef        _DEBUG
& s2 |$ w* a5 G8 A# Q* LDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" M/ d: i* j# t#endif$ c8 }7 ~( f% c& b$ s7 T
}0 |4 i6 q5 q3 `) Z

. T+ E- l8 B1 q. A$ z$ S. A: Qvoid        APU::LoadState( LPBYTE p )
4 |+ c. K0 A: s6 A{* \! a& p2 }2 `: Z0 K9 U* ]
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡6 w3 H( x3 N6 f- b
        QueueClear();% }% r; }( M' W

+ P& L/ Z5 R" g( B+ q% |  V& Y        internal.LoadState( p );6 W1 A7 e2 G) T! C* l
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 Y/ }" ^$ t9 |4 ~, d- o
3 i2 U( R& f+ P
        // VRC6- _$ _4 v6 Z! @5 j! Q4 M
        if( exsound_select & 0x01 ) {8 k6 S" k# \5 B$ I1 c) K' f
                vrc6.LoadState( p );
# S0 o0 c) R" Z  `9 `! h% z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' \1 Y; r4 C( |( C4 @7 i  J' n
        }
2 ?3 \; T  F) y5 \8 c        // VRC7 (not support)
- W2 A7 C& I2 o% T0 |2 v' o8 b6 d        if( exsound_select & 0x02 ) {6 u$ g" ]7 u2 ~/ B' P
                vrc7.LoadState( p );
  }1 x& a: p) P                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 Y1 r0 ]  W$ _3 G1 g' b
        }- N& n" ^9 \' f3 b4 V* j8 z
        // FDS4 d% w- ~, j1 q
        if( exsound_select & 0x04 ) {1 g/ J' I0 j! `% r
                fds.LoadState( p );
5 `: m/ b2 }: N% s+ }. i  G# v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 ~8 I5 b( @: X& o7 I
        }1 G0 j! Z9 q. c
        // MMC5( s4 W5 [6 m+ D) z% a" f& k
        if( exsound_select & 0x08 ) {
0 x" \' S& ~8 p( r8 ?4 ?1 p                mmc5.LoadState( p );, z7 T4 u. F" a( [% o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 S3 A8 h6 |, T6 V- `5 X4 k6 \
        }
. A& ~" w4 S7 c4 u4 s        // N106
1 [! g; P  M/ A1 g  A, r        if( exsound_select & 0x10 ) {$ X, b+ b3 f6 {/ v0 E5 V
                n106.LoadState( p );
8 G2 g" U+ e9 H2 o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ y  F3 A/ c6 V        }
7 s0 q* n: a) ?        // FME7
4 D9 ]0 \  U% B1 k        if( exsound_select & 0x20 ) {0 k+ z. m! M# H1 t- |
                fme7.LoadState( p );
! M* z0 o9 w  I2 a' E/ k                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 _, Z) L2 B  `8 g: G9 D        }
9 r( }6 a9 B7 E0 r- B8 M8 B}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
& y8 L/ u  @2 P$ u7 w: Z可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。4 f" \2 R1 e/ p% v( s7 ~4 v
感激不尽~~

% F  l$ l: }, X) u7 X恩 我對模擬器不是很有研究,# ]( M; \% h; [1 }6 U
雖然要了解源碼內容,可能不是很困難,
8 L( h. G7 t+ a% {, e) [不過還是要花時間,個人目前蠻忙碌的。
7 P- b- p! w/ D1 D& s6 o. g3 U8 W& u- B0 i, t+ `3 l1 q( w5 x
給你一個朋友的MSN,你可以跟他討論看看,9 s$ W, [! X) |' L
他本身是程式設計師,也對FC模擬器很有興趣。- j% |2 n7 |5 ]4 N' n; m* X) B

0 U/ z8 b% ]0 d" A+ DMSN我就PM到你的信箱了。1 i0 C' u# [5 A5 O* V; v8 Y3 u+ E
& p4 P% c2 c7 p6 U+ m: w
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
. e* i% @8 U7 h' \! X; q2 e1 Z呵…… 谢过团长大人~~

, B# O- O0 j2 B( l. R( p5 p& a: L; ^5 r/ W
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
7 E7 P- v+ C* c/ q* t) U团长的朋友都是神,那团长就是神的boss。

4 |3 P8 N0 a: C4 H0 t7 G$ F& N哈 不敢當,我只是個平凡人,6 S0 K* a! F, N) e- e# C! q
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# j" U, h. E2 d) F
ZYH9 A3 T" Q/ x7 A, b  O& Y$ c
QQ:414734306
- G0 R' p! U1 T+ i7 n7 @  d  }( J* q0 w/ pMail:zyh-01@126.com
2 s8 X( d2 N7 ?+ x* ]" n8 u$ w5 U1 \$ {" G2 ~
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
  ]) B: b: I  Q5 S+ b$ t再次对团长大人和悠悠哥的无私帮助表示感谢~~
% ]" _* X  h3 r4 m/ ^. V' o% o
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-28 23:41 , Processed in 1.081055 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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