EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 z$ Z8 T" M( C, m
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ d% u* F  [' _) L/ h/ P" F
这里有相应的模拟器源码,就当送给大侠了~~4 {7 G4 r; Z" e
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 7 b5 ?0 F; [; h# M% t. b
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ G' H4 _& c+ s楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, h" }1 r" `# F% j' S, D这里有相应的模拟器源码,就当送给大侠 ...

% {" j& h( b; Z- i  L' g; p聲音部分(Audoi Process Unit = APU):5 P7 t+ D. u+ f3 {
.\NES\APU.cpp% o6 u( J0 |3 D) F' v1 R' a
.\NES\APU.h
8 R( n: J" a- E, L
: |* {& j* S) ^8 g6 n2 L" o+ r% B/ O2 ~  \  T1 z
影像處理部份(Picture Processing Unit = PPU):
" }+ a" w) o  o) ^, k.\NES\PPU.cpp8 h6 X0 k& _- {" X* B
.\NES\PPU.h! y& Q9 M4 g) C" M/ l# K

1 r. {' I$ B  F9 |$ J7 h如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:# t; ~# u) }$ ?. d
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
- y1 g- m: K& n' _2 H, T$ t( @//////////////////////////////////////////////////////////////////////////
  q7 k4 ?& j: J//                                                                      //
+ _+ `3 W5 y( a" G9 {1 ?//      NES APU core                                                    //* E# h6 r% J4 V; e0 \! I2 x& }
//                                                           Norix      //
# J1 J& }) Y8 F/ r+ t//                                               written     2002/06/27 //1 V# j: I* ]6 t9 ~; V
//                                               last modify ----/--/-- //
" z9 E8 z2 K6 }2 D+ ^/ g9 ^# x//////////////////////////////////////////////////////////////////////////1 [3 n) H1 a* B! U+ z: D' J) u
#include "DebugOut.h"1 _$ S. s8 n  @+ q0 n
#include "App.h"
8 ^; x/ ?* x6 j4 a+ h8 G( c#include "Config.h"
+ D) O' p+ H9 j3 R, l+ f* z6 k8 S9 l4 A+ Z% e# }; O2 ]3 D
#include "nes.h"! o& Z- H3 S3 X1 }$ Z
#include "mmu.h"8 c+ Z1 ]- l8 @# T2 J
#include "cpu.h"; z4 ~$ T) s! A/ i; Q; T4 ^
#include "ppu.h"
8 ^0 w  O0 S1 o' F. o; V6 D' [2 d#include "rom.h"( ~% v& y7 }# i  U2 \8 _' p
#include "apu.h". ]' |' [) o. u0 h' t/ O% Q

: M+ i5 P% ~+ w! o  y$ c! _& `, x// Volume adjust/ F# X: A& p3 S
// Internal sounds& s2 T7 J1 P* K7 w( `* o$ i, A
#define        RECTANGLE_VOL        (0x0F0)& v. x: V& d! @% w
#define        TRIANGLE_VOL        (0x130)
2 t* R* ^& V8 ~" T' l. ~# F2 T- O#define        NOISE_VOL        (0x0C0)
1 X$ e0 {  r& [1 ^#define        DPCM_VOL        (0x0F0). e# V3 w% \0 _3 e- H; c
// Extra sounds
  D- [/ t% ]( v2 V6 Z#define        VRC6_VOL        (0x0F0)  N" A# i3 q9 [
#define        VRC7_VOL        (0x130)
( e3 R$ i3 Q# ^4 v$ n6 v#define        FDS_VOL                (0x0F0)3 d! f. R5 |( j" {2 b* v0 ^5 z
#define        MMC5_VOL        (0x0F0)
9 V3 F2 J9 {) X. e#define        N106_VOL        (0x088)
; s% E7 k7 N3 ?+ J3 X% M#define        FME7_VOL        (0x130)( p2 Y: F( Q) D

6 h5 b9 z9 {5 R# uAPU::APU( NES* parent )
/ X# ~  g6 @) h/ S# {: `! |& j{
. e2 d0 E, A0 }! [! r2 L        exsound_select = 0;: m, ]) p+ J% m# j) F1 E% c

* t5 M& S2 k0 }6 q' _' h        nes = parent;) D2 O. Y8 }# U, U/ `( X( h
        internal.SetParent( parent );8 O# }/ `; W6 y' K% G* }
9 @+ Q4 H5 {4 c7 N1 h9 w/ r
        last_data = last_diff = 0;
: w5 |$ [! M" W8 H! U" r: B7 @2 y6 U9 m1 t+ Q' u1 u1 X( S) }
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( V4 l6 z2 n; w% V/ k

; k6 q! T. z/ p+ p# V        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ h! S' S+ T4 r8 W' [
        ZEROMEMORY( &queue, sizeof(queue) );
1 `( ^" N! P! b( h) Z5 z        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 W6 n. ^( u9 A7 ?, U, Y4 x: \3 `0 N' c* B1 H# x
        for( INT i = 0; i < 16; i++ ) {9 c9 k3 }% l8 i9 z. o6 r
                m_bMute = TRUE;
0 o7 k6 j0 v/ p        }4 `, x, A# k& L: p
}; z, p  S1 Q  i  a

% P2 [9 z2 a! ?* r( ~1 i* JAPU::~APU()& Y; G2 s$ w% ?. e* S& B
{0 i  Y2 F+ O- Z3 m( I
}& M, e0 P2 C& [# x
. m) i9 S; f- h: b3 T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& V2 z' ]* s" f) e% I/ i{* x( a. o* F' Z0 @
        queue.data[queue.wrptr].time = writetime;
# _- W; G6 b8 a  m$ k4 M0 s; \        queue.data[queue.wrptr].addr = addr;+ b; v6 ~$ ?. ^3 j* x3 q8 k: x, E
        queue.data[queue.wrptr].data = data;. _6 F7 ?3 {$ f, f" A( \: X0 b
        queue.wrptr++;3 [$ I) Q0 D0 |# @* R
        queue.wrptr&=QUEUE_LENGTH-1;
! Z, I* S; \" O3 G9 f2 I8 y  @        if( queue.wrptr == queue.rdptr ) {
3 {& w2 o0 i/ ^                DEBUGOUT( "queue overflow.\n" );6 U3 x9 p1 s# B' L" Y) e
        }
6 F. ], G- T" `9 i' d: O/ t. C. ]}0 e2 M. C3 l8 }# X
5 z) M/ f+ d& p' I9 Y9 A" d+ C! |
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )' |; X+ R5 E2 r, D. x
{
" B# t  }& E" ^' b( m5 [        if( queue.wrptr == queue.rdptr ) {
4 \/ Z8 s0 U1 I1 u                return        FALSE;
7 z6 Y- x$ k. a        }
( B. O+ _- t9 d- t8 K. H        if( queue.data[queue.rdptr].time <= writetime ) {
) D; ^/ @0 Y2 C. F2 L: m$ p                ret = queue.data[queue.rdptr];
  v7 p4 A8 v& S                queue.rdptr++;
, B2 N- U; t! p, m1 e7 S! `                queue.rdptr&=QUEUE_LENGTH-1;
# \% Z4 T- }- v                return        TRUE;- c* y; I! B* A. O
        }, I7 M1 F# B, C. o; g/ J" Q
        return        FALSE;4 y/ z. M: F1 U* v: w1 v
}
# O) D& }. z9 {- z# d6 e- s9 v
6 \' \6 p! O. n4 d' c0 r7 vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )# @8 [7 B% y: g' E& ^- n* p% M  _5 W$ A
{4 b0 I5 a6 D& a9 x' E
        exqueue.data[exqueue.wrptr].time = writetime;; T7 ]% r! n5 {9 \7 h' P
        exqueue.data[exqueue.wrptr].addr = addr;3 i% Z/ G' H$ n0 G
        exqueue.data[exqueue.wrptr].data = data;: H# {$ x5 R( N5 [* D% k
        exqueue.wrptr++;
5 h, R% m1 \& n+ x* ~        exqueue.wrptr&=QUEUE_LENGTH-1;% t" |$ I) b+ Q, u' ]; X  c
        if( exqueue.wrptr == exqueue.rdptr ) {3 c3 \+ N1 [- e% w7 u% e
                DEBUGOUT( "exqueue overflow.\n" );$ u; x2 U# U5 a/ W
        }
0 b5 ?9 W! ]$ T" T8 _. R& k}) i8 T) [$ h9 J) t
$ V5 b: k) \2 W) H
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. X0 P4 ?! \# f( ?- @# n{
# P2 L  U' [; I6 b4 w! H        if( exqueue.wrptr == exqueue.rdptr ) {
( W# [. {6 ?" x5 I0 m                return        FALSE;3 |3 p9 h3 d+ D" C  d, e
        }
* ~( U3 z$ k5 P7 \6 G5 q$ Y9 B6 B        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
  _* g, d9 o, O3 B$ N5 A0 d  ]  r                ret = exqueue.data[exqueue.rdptr];
# g8 R7 ^. P8 p5 H                exqueue.rdptr++;0 Q6 |: A( R- W! W, k; X* J. ^3 M
                exqueue.rdptr&=QUEUE_LENGTH-1;
$ Z+ b. r# c( D0 S" c                return        TRUE;& x$ e0 t: ?1 D2 v* y, R1 T
        }( I5 `0 R0 T$ I  Q: c2 o6 s( p) Q
        return        FALSE;9 \$ Q+ q$ B5 |% F" A) k* z+ ?
}
$ b! P# e1 H8 ]. p
* E2 _% s' k" wvoid        APU::QueueClear()
6 F9 u9 z- M1 O! Z{% M4 x( a  k8 ]! P9 i
        ZEROMEMORY( &queue, sizeof(queue) );9 v+ j1 S9 ~* ?$ q
        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 _/ r/ I( A* C6 ?; O+ v" d
}
6 `9 j! q( }3 }$ n. `. H3 G8 S: i; u, S  P
void        APU::QueueFlush()
1 R4 o. x4 \5 z{. e7 I6 h! d7 k& U
        while( queue.wrptr != queue.rdptr ) {/ A8 t) q; T- m6 z
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );  e9 }6 U! a. n, |% l5 x  j
                queue.rdptr++;
6 `6 `3 e/ n7 M+ k: {, B) c0 ~! A7 A                queue.rdptr&=QUEUE_LENGTH-1;
# \4 N8 k6 A$ W, H* [        }
" B+ p- w, f6 y# F2 u4 @- Z* u$ S' l
1 F' L! H! P: W) L        while( exqueue.wrptr != exqueue.rdptr ) {
; }7 |) Y8 P7 P7 f3 K  M$ d0 {                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );  y* ]& v, `, W" x% N) l1 F
                exqueue.rdptr++;% i& U9 b% V" S! U/ g$ g
                exqueue.rdptr&=QUEUE_LENGTH-1;2 z0 B# J: c6 Y$ N
        }& T( {2 e9 S- G/ j+ t, Z- f
}# A7 f. @$ r- Y* A

) `1 t5 j4 U8 q, h/ F/ D9 Wvoid        APU::SoundSetup()! S, P* b! }- V" J* b  O, W
{4 P" T5 B+ y; C) g+ z' `6 A
        FLOAT        fClock = nes->nescfg->CpuClock;
7 f/ c( J" T: K# h* a        INT        nRate = (INT)Config.sound.nRate;
, R  K& g" L( b; \" g# q        internal.Setup( fClock, nRate );1 o, e. h" k1 F: t, D
        vrc6.Setup( fClock, nRate );2 s4 o- D  ^3 n$ V. z: M: i
        vrc7.Setup( fClock, nRate );; X! n1 D5 D* i
        mmc5.Setup( fClock, nRate );
' F- G2 I) l6 p. o8 R/ q. D        fds.Setup ( fClock, nRate );
$ P; [0 z) V" A1 {        n106.Setup( fClock, nRate );  J' t, q) W  K, W
        fme7.Setup( fClock, nRate );% o$ I8 o) t: I  t: }
}4 U6 B) x! N2 J
3 \7 [& u2 x4 r1 f+ p2 t
void        APU::Reset()5 i5 z/ @. J: z. m
{
# @, Q) ^- [  u$ k5 Z. N        ZEROMEMORY( &queue, sizeof(queue) );$ c8 @% G; q$ b3 A+ @% l* o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ M) o3 L! N* F7 n( r7 ]' H7 h: l8 g
        elapsed_time = 0;! I; D& S- H1 r' D- r" I* w4 y

( E2 v1 h3 ]% R9 U% V        FLOAT        fClock = nes->nescfg->CpuClock;) d; Y% w5 H- @* M0 l' V6 Q$ K" i% H
        INT        nRate = (INT)Config.sound.nRate;$ m. {; m. r0 b$ w, D7 s
        internal.Reset( fClock, nRate );0 B' ^  ]6 C; h+ e: n. ?
        vrc6.Reset( fClock, nRate );9 N. R$ H+ K- b* x* ]
        vrc7.Reset( fClock, nRate );1 }+ ?  _. q' E
        mmc5.Reset( fClock, nRate );9 n" \3 ]. k' P4 s
        fds.Reset ( fClock, nRate );/ d# ?( w; g8 k0 P! u- q9 z8 b
        n106.Reset( fClock, nRate );
1 u6 r' r6 M7 k+ I9 r+ s        fme7.Reset( fClock, nRate );" _' ~5 V6 |6 |& p& s
& P* L& p/ M5 c" T/ E8 I
        SoundSetup();3 ~4 J, e% u, \- t2 l* M
}6 s; l2 S' C# _$ a+ X0 K* O( Q

5 c) c# H, l+ \) v! xvoid        APU::SelectExSound( BYTE data ), n0 F, a1 N, i6 V8 M
{
5 ~! U  F2 t# x4 v# s0 [. Z/ M        exsound_select = data;8 B9 h, I# X; I8 X: ~
}& V  d& e6 @) c! I) e
% @" U4 `' _3 y6 A- m. W
BYTE        APU::Read( WORD addr )' p  c# y  q$ t% h! h
{! u1 Q  a! k0 c! V
        return        internal.SyncRead( addr );
: f. p3 h2 Q" R0 Q6 J}
: R2 b& u; ?6 \3 @# c
! o+ N  M% \' J4 P; W9 O0 a( t: z/ lvoid        APU::Write( WORD addr, BYTE data )+ C7 p1 J' S* ]: ?
{1 U: w% {' w- v% p9 e0 V1 z0 g
        // $4018偼VirtuaNES屌桳億乕僩
; V6 n0 n" h5 \1 k* v: B        if( addr >= 0x4000 && addr <= 0x401F ) {. u# T" ?  f+ _0 M+ a
                internal.SyncWrite( addr, data );4 z6 Q3 A5 E+ Y  r$ M* r9 M6 G
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
4 N) W# Q% e  u# p        }1 a- m7 |; j6 O, \
}
( H% l( o/ E* ?1 ?* U9 s
5 |9 X! p. ?. zBYTE        APU::ExRead( WORD addr )0 S- o. Z  \; t2 y/ P3 h9 i1 G
{
# S) i1 f! X; jBYTE        data = 0;; x% ^/ S7 i2 f9 b# ]5 r

0 d3 X2 v  o$ F        if( exsound_select & 0x10 ) {
  {0 {3 t$ r3 q* b" C' s  h                if( addr == 0x4800 ) {
: l9 j& E% {% w) P1 }, |                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );6 |7 r/ k1 [* `+ }
                }* L! s/ o, o4 [7 T- V1 _7 |; e
        }# O6 u% G" v% {0 e
        if( exsound_select & 0x04 ) {
/ X* {4 @' B; f/ J7 c8 e7 w5 ]* }                if( addr >= 0x4040 && addr < 0x4100 ) {. Q; v( Y% a8 w
                        data = fds.SyncRead( addr );
% {+ K5 I4 ~% ]) Q                }
/ X  v7 D3 P4 p0 _8 C        }
/ b) V3 }: z  E" o" E  Z        if( exsound_select & 0x08 ) {8 h8 H; J7 o0 l, E/ x% N1 M2 Z
                if( addr >= 0x5000 && addr <= 0x5015 ) {- V  r( \+ s6 h
                        data = mmc5.SyncRead( addr );; @. i' j! y6 a& H% C
                }
3 q* ]: h, Q! V" q0 X        }* \" @1 K; D6 L4 Z
0 u2 O. P4 N3 a. w. s& X2 w
        return        data;
- V9 I+ I+ z7 Z% ]/ ~}
0 h) t1 ]$ G3 j' C# |7 {; k# s" j4 Y- n9 y( S
void        APU::ExWrite( WORD addr, BYTE data )
- c) e" c- f7 y' s& w9 g# B2 X{
# y% x/ C# O8 g! O) H$ S8 w        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 |0 D8 Z" [' H2 [3 V+ v0 q6 ^
: E6 o; a  `8 l! H& P' k
        if( exsound_select & 0x04 ) {
9 m# h! a# s8 v0 O, `9 l                if( addr >= 0x4040 && addr < 0x4100 ) {
! m. N9 v. V  a- X2 S6 p8 I                        fds.SyncWrite( addr, data );4 F1 w- Y+ Y3 C# c6 H. R# s
                }
" h1 E- ]0 r  x6 x1 ^9 k        }
7 \! Q' Q1 t. E4 G4 ?
3 c; e+ i" y: t3 H3 c! t" g        if( exsound_select & 0x08 ) {
, A2 D6 [! x  V; n                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 L3 ?& ^9 h4 l- J: q                        mmc5.SyncWrite( addr, data );
# i+ N& H9 O; i2 M6 `9 ]. E0 Q                }
2 O* H$ F4 Z' R$ e* X2 v        }
" S8 V# u6 \3 K/ @}
! @9 h* L- ]& V- b+ l0 ^4 }1 i7 x  s& t) E: j
void        APU::Sync(); l0 F- P: M- V4 T8 o) X3 g, r5 N7 d5 _
{
6 l& s8 H: L5 E5 n}
# V- q  ~6 H  f2 d' A) V4 `: D: V# p/ X# F; B5 ~  X6 Y! |
void        APU::SyncDPCM( INT cycles )3 P- H% F/ v% ~+ [- _
{3 x4 x- f$ I8 K- M* o: s4 r, q
        internal.Sync( cycles );
9 u5 g( ~. n) q: [
/ N3 W7 @, }3 n/ ?- m! ~. [) |# \        if( exsound_select & 0x04 ) {
* Z8 N! B3 p8 {* F7 M4 q                fds.Sync( cycles );
: s2 E* m) m* X; `# t        }1 ?& ~! u1 a+ T) m: S: @8 E
        if( exsound_select & 0x08 ) {( t3 Z  Q* E  a  m) I; B
                mmc5.Sync( cycles );. q4 U; m) z  T) S; p
        }9 h: |" C, e$ b/ Y% t
}0 n( c6 C3 M+ ?0 S& ~- t

* f. L& |! U& y& {void        APU::WriteProcess( WORD addr, BYTE data )7 q7 [1 k" L2 l# \! |, z9 v
{3 f& ^8 K* ?# Y3 h
        // $4018偼VirtuaNES屌桳億乕僩
$ W- H/ L3 ?8 Q' j& m' S        if( addr >= 0x4000 && addr <= 0x401F ) {7 w* Z2 g/ F! j
                internal.Write( addr, data );: u! ~6 e4 b" i' F& @1 G6 R
        }6 O* J6 {$ h0 Z$ t
}/ O' z7 S! F* p) f, Y9 c  X/ J2 V
3 d% [+ T: H* ~7 X" k
void        APU::WriteExProcess( WORD addr, BYTE data )
8 R9 z4 h0 ^3 s6 m3 }1 Y. Q{
( z: }. q% D  R) q- p9 w% X& _        if( exsound_select & 0x01 ) {& l& K- u/ y% B; N, v
                vrc6.Write( addr, data );+ ?* O- ?+ I% J, W+ }3 R3 D. S
        }
0 F) P# I& p  h5 _# Y6 B* A$ R        if( exsound_select & 0x02 ) {
1 Y, ]3 u1 [4 }- {% J' K5 M. W                vrc7.Write( addr, data );
: W# o  c5 ]* k9 D$ H% v/ v        }
/ a9 a8 k+ E8 r( Q        if( exsound_select & 0x04 ) {
' V/ S  B; M" u! Y5 ^7 b0 W                fds.Write( addr, data );- W* v% m- u# Z2 r6 n
        }2 R/ I. |: r9 `7 W/ N
        if( exsound_select & 0x08 ) {+ F! i4 @) Q$ E% V# b- D. W0 E
                mmc5.Write( addr, data );
! W0 U1 |* V0 D8 u        }
) O5 p7 e5 @4 s. E" \        if( exsound_select & 0x10 ) {; Q- N' K7 O* c3 [. I
                if( addr == 0x0000 ) {/ p, R3 z* w1 K3 _
                        BYTE        dummy = n106.Read( addr );0 q8 L4 J  I" ^1 g9 v0 a
                } else {
1 S, X' ]1 A0 R7 G* \                        n106.Write( addr, data );" ~3 ?6 h. ~4 K! n
                }
( m2 }0 r/ N6 j: a/ ^        }5 g" f9 B7 r- ]  o; G
        if( exsound_select & 0x20 ) {% f6 Y  x3 b+ K$ X: I: e, u
                fme7.Write( addr, data );
$ N/ p6 ~4 U3 T; _0 e# E        }, W3 b& [9 O; ?" O$ v
}0 V2 D' ~( E& G, d& I+ s
+ ^+ I& ^8 Z4 E# Q/ P
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
3 u0 Z6 @: m+ f  I' N" c{" g6 R- ]! Q- C" D+ G' c
INT        nBits = Config.sound.nBits;$ X$ R; }$ J, s- f3 P; \4 R
DWORD        dwLength = dwSize / (nBits/8);
0 _8 L! b0 n9 M' C0 m4 l$ a/ ]INT        output;$ q# s0 K5 J0 v7 c7 r+ q. `* T
QUEUEDATA q;
$ B9 L6 z+ H7 B& T: A: @DWORD        writetime;2 K: E: C! J; j; j
$ y' T2 A  p5 g! s: [$ J
LPSHORT        pSoundBuf = m_SoundBuffer;
! A2 Z' L# {  h3 H4 pINT        nCcount = 0;
- M2 E# s+ n% a: k7 M% o" w
; T/ h: c  @! ~  s: r( |. k7 Q4 XINT        nFilterType = Config.sound.nFilterType;3 u3 [; Q: C/ ~8 s! x( v3 a# T

4 i; q  q6 l) n* y' `6 e8 y        if( !Config.sound.bEnable ) {3 e" i3 L. W) p9 h7 t' h
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );$ K' L# S& T4 x0 g0 V
                return;* u: T. k8 ^/ J. l' Q- }5 `6 g) N
        }# [: d: H3 N5 ~& m4 q; G
3 _/ V$ {1 m& h. o: y& ?
        // Volume setup
. w) a1 d# B. X3 D0 @        //  0:Master
* J$ X5 S9 z1 S. N2 i6 E9 l        //  1:Rectangle 1
) ]# U" a9 K! ~2 ^4 _2 y        //  2:Rectangle 2
! X# L" N7 ?8 L6 U+ O3 U8 x        //  3:Triangle
: r7 O& {5 k. v        //  4:Noise
& o' ]* _- ^0 j# K6 E( J* E% I        //  5:DPCM
' X% A6 {5 E8 K  i        //  6:VRC6* G" P7 t; k9 L. j
        //  7:VRC7
9 N/ \9 X) \7 i) Z. F2 w        //  8:FDS* r& k, l( I. l8 v( m) i
        //  9:MMC5
+ {- g6 v) p0 A; n1 @        // 10:N106
# ]) T2 q3 s) Y4 i, v3 p5 y" A! K        // 11:FME77 M8 ]1 T# U$ i" P
        INT        vol[24];
5 ^- k8 A# A: E5 W! s- F/ @1 W- l        BOOL*        bMute = m_bMute;, C- @. H/ T* h) T8 W( X  U
        SHORT*        nVolume = Config.sound.nVolume;
- E" C4 V: C5 n5 P
* C' {3 p0 {8 d        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
; ~1 \  H( m( w' c# }' B1 }7 Z/ J" I
        // Internal
) Y! U6 t5 T+ Z2 i- ]        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
& F% ^6 j) f+ s" c        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' R5 z0 d1 o$ X' ^( W        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
; L' _3 R9 C  L: _1 d! }        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 ?7 P) Y% g5 e" N; t- y) b1 ]        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. r+ m- g6 L! W8 ?& c" G- u' n( D- r9 ]. M
        // VRC66 \4 J; b5 K' M% x3 Q) |4 v, R
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: h( G: t9 n7 g7 V8 J: N
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  G% u* v- K: D" \( V" [
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- l0 w! {: A, }
# {) [) p( B8 {9 v1 f5 o+ T) S- e
        // VRC7- U4 h! c( m0 ?% S
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, v' |/ E* ?8 m. G; X
% E1 d; A" E( }5 U& @- b) r! _        // FDS  g4 a" W2 y! k, g4 j9 b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& o  |/ l- q  z

, H7 a7 i6 o7 G7 H6 S# E0 s        // MMC5; @! z2 }& E' ]; E: A  L! H& W4 X: W
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 r, ?  B3 D! R8 O& ?" Z1 c        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 }5 f: I) j9 n& c+ A. k        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 P1 P# C$ j6 g7 j; [+ u/ |# b4 E  c- v5 f5 W& @
        // N106
: H2 W) h) R* g* b' z4 N2 Q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, Q' r6 O: t! _% X( a; v2 Q* k
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, \! X6 h3 J- W; y% ^
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 r' A) l4 m0 m. N/ @- O        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ j* Z% ~" _% w+ I        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 S% b: q( j$ ]
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 G7 j& V  X* \: X5 A
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 `! |" U/ A: q
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& s5 Z9 _" Z; m+ o9 e' H

% |1 t* ]8 v" ~5 e        // FME7
0 L/ n. o0 q7 P! M0 k/ R        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& Z5 e( w4 n' g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' o, j+ Q1 ]1 I+ H
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
; l7 w! k# l. r3 o, ?
2 X  A% A% \5 `8 x//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' U% ?8 O/ z8 y7 d5 x7 _$ U- O        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;; h- P3 w; x: x  ?. n

! f8 k2 x( j3 G6 y9 J5 M" m        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& ~; Y/ R6 Z+ t3 w3 P. L2 F
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
* j9 L9 `' v+ ]" w3 L7 d                QueueFlush();
6 u6 u% C& T* F        }& x6 m0 I1 n% j' A% o

  J2 E7 a, U1 N        while( dwLength-- ) {; p( _) M" ~5 y
                writetime = (DWORD)elapsed_time;0 U8 {& r% R  _. Z& q) I
! r/ Y# Z" a9 v) g
                while( GetQueue( writetime, q ) ) {7 F5 i- g, D$ w* {
                        WriteProcess( q.addr, q.data );
, M7 J; F% N! b$ A: X0 V                }& i6 G2 D' _9 W  ^1 a
  Y: h8 Y* S1 u1 Y! Q' G
                while( GetExQueue( writetime, q ) ) {5 G$ C& n* L6 U! i+ [8 O% a
                        WriteExProcess( q.addr, q.data );
! q6 b- u6 q" r3 W% f1 l3 ?                }% L  F; ~4 S  B8 K2 k  h! w8 A

$ e0 O* ]0 @$ \                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ ~) A( U6 J- N* z; b, |0 A# n: [                output = 0;. l( g- Y) R6 O) A1 \9 t+ K: k
                output += internal.Process( 0 )*vol[0];; [6 k6 m( ~$ _+ r6 B
                output += internal.Process( 1 )*vol[1];4 s  C. A, s* o$ g: u3 l
                output += internal.Process( 2 )*vol[2];
' _5 w" }+ T+ x+ i                output += internal.Process( 3 )*vol[3];
2 G  |: G, n) i0 g' P' h0 k3 D; f                output += internal.Process( 4 )*vol[4];
* L3 b# |! D+ ~/ l8 w* i/ d1 G  F' J# D8 j- Q6 T
                if( exsound_select & 0x01 ) {  \' Q5 F$ H  h
                        output += vrc6.Process( 0 )*vol[5];
  M/ i, W* a" E, w. g                        output += vrc6.Process( 1 )*vol[6];4 D2 B; b1 w3 r- x
                        output += vrc6.Process( 2 )*vol[7];
+ N* Y( I  ~- w5 O' a                }; E. d2 M& I1 |
                if( exsound_select & 0x02 ) {
. d0 ^# @% E. Y& C4 u. N                        output += vrc7.Process( 0 )*vol[8];8 |0 S! M. v2 ~, }
                }
* W' A# u- K1 n5 w9 A0 M                if( exsound_select & 0x04 ) {8 Q8 l. O: f& p1 X1 E" h( Q4 y
                        output += fds.Process( 0 )*vol[9];/ {. q' a$ @$ E% j0 m% W
                }  C9 }+ j( B, i% o& X7 q
                if( exsound_select & 0x08 ) {
, o! C- k& a9 Q! X6 _# o                        output += mmc5.Process( 0 )*vol[10];
( I6 Y) R* q  Q                        output += mmc5.Process( 1 )*vol[11];
' Y% q: L5 V2 Q$ E9 P$ \                        output += mmc5.Process( 2 )*vol[12];
3 F! Q3 {( W3 ]                }
* h8 I" p1 O6 k                if( exsound_select & 0x10 ) {6 g9 L! R4 L( m# K
                        output += n106.Process( 0 )*vol[13];
2 o5 Q: J* p& x0 y! E! k6 A                        output += n106.Process( 1 )*vol[14];3 h6 a. v; G: m  S
                        output += n106.Process( 2 )*vol[15];6 P* Z) w, a+ _( {# ]3 j' ]
                        output += n106.Process( 3 )*vol[16];. K& u. O* R4 r, g3 E0 h
                        output += n106.Process( 4 )*vol[17];2 @# A7 A2 q2 b6 c9 n& D9 h
                        output += n106.Process( 5 )*vol[18];% \6 n4 \: G9 f, r
                        output += n106.Process( 6 )*vol[19];
6 e/ A- q0 _, m2 N2 N; ~. e5 ~- z4 r                        output += n106.Process( 7 )*vol[20];
8 Z  [+ B( m4 n1 m) F, P4 R% r1 |) |; J                }1 z. F  ~5 o/ T  P, ]1 M
                if( exsound_select & 0x20 ) {0 U% K7 E* k# Z* ?9 ~) Y4 U
                        fme7.Process( 3 );        // Envelope & Noise: w- x1 G3 `: M7 q% I
                        output += fme7.Process( 0 )*vol[21];
/ J1 s* J) A) c                        output += fme7.Process( 1 )*vol[22];8 T, g( b" U; K0 B0 {* B8 n
                        output += fme7.Process( 2 )*vol[23];4 k" i/ m0 g0 ?9 D) }
                }
2 ]6 c! R& f( A1 a) r" `$ |
9 v7 ~. a$ {) P& w                output >>= 8;: A+ g% o0 \7 p8 z$ c0 \2 O3 W3 O
) R/ _( i' R4 M% n, r% e
                if( nFilterType == 1 ) {
+ F2 |3 k$ |+ l: q; l% O% f                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 a  _' k% u- Y$ S2 V! Z                        output = (lowpass_filter[0]+output)/2;9 I, A7 N) b4 |; j, Z" V% M1 R
                        lowpass_filter[0] = output;' k  `1 u8 Y- _7 l0 w( \3 R2 x3 j
                } else if( nFilterType == 2 ) {2 L! o/ d. @  j
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
2 v. H$ `! d7 r0 B                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
& L+ D: P, }. e& d                        lowpass_filter[1] = lowpass_filter[0];4 r: j  H' r0 Z& i) v4 T+ O
                        lowpass_filter[0] = output;$ z4 l# W  Y, ^* U  f& k
                } else if( nFilterType == 3 ) {  [$ w( t1 J0 w: }) c7 I$ Y
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% Z8 u: \, A8 Z0 D9 R8 b                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;+ ]. d/ u  V' c, Q
                        lowpass_filter[2] = lowpass_filter[1];
1 Y) M+ l4 m  ~- P                        lowpass_filter[1] = lowpass_filter[0];, C( Y5 l* I4 N0 h8 ?% |
                        lowpass_filter[0] = output;
6 n& m- Z' ?5 E8 T& u                } else if( nFilterType == 4 ) {
1 {  x6 X4 e, O1 Y" @                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
! d8 t7 ]8 G' \1 F: A0 |4 _! L) C                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;9 S/ d- [+ u7 T
                        lowpass_filter[1] = lowpass_filter[0];
  o' a- N. x/ n7 H                        lowpass_filter[0] = output;; t# @  y0 }3 q9 `  y
                }
- f& @8 W2 f. g1 y+ i- |, b7 K& A7 {4 @4 Z" L6 S. N
#if        0
, H- J; k8 L3 F, f! Q5 @5 u4 @- m                // DC惉暘偺僇僢僩/ d3 I* M1 x/ T3 u7 ?
                {' d+ c* W0 H0 O0 A4 W7 I. N6 R
                static double ave = 0.0, max=0.0, min=0.0;
( I# {0 n- f! e& P; }: d5 p/ n2 D+ L6 J                double delta;
7 G& O  I" z2 l8 N                delta = (max-min)/32768.0;$ k) h# L! s( g* X
                max -= delta;
  x6 O$ j5 L. x$ |1 E* o                min += delta;) O5 G2 B% ?' G5 H* {5 |
                if( output > max ) max = output;
# y9 a* K* P9 f8 u8 M* i- U                if( output < min ) min = output;
2 j  r( M2 S& y, w; m9 G                ave -= ave/1024.0;9 B8 ]' H+ k; X% ?9 Q! f. K
                ave += (max+min)/2048.0;  \+ v$ F( t, z0 b
                output -= (INT)ave;
: Y4 n/ J' W- v9 D' x                }2 H; L, c# q6 }7 {' x
#endif
" v7 B8 `1 A  G' Y#if        1
* I0 z( ~6 O0 E$ h; m4 a3 D) j                // DC惉暘偺僇僢僩(HPF TEST)
7 v& d, p5 q  g) S) u9 r5 D                {( H- M# [3 {4 U* k  z# k
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 |+ {# k2 r% s
                static        double        cutofftemp = (2.0*3.141592653579*40.0);2 T# x8 S3 y$ V( U: z
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
, i6 \1 m( i! L$ d* x2 \6 W; y                static        double        tmp = 0.0;+ f$ c  [; R9 ]4 c3 p
                double        in, out;0 v  n4 L7 c$ m5 \' m: u  a

/ g# x4 A+ {" T1 M' n$ T% V                in = (double)output;7 Q4 V( Y8 l: L5 G. G/ J
                out = (in - tmp);" C" n' S/ G3 f/ i- l9 |7 o0 C& }
                tmp = tmp + cutoff * out;3 p* j9 [' q% G+ V

9 Q- F% C; I' Y) J# a2 G4 n                output = (INT)out;
/ [& d* N# w9 N0 `% a                }' w+ K: x. E4 c  s  E( [! k- t
#endif% R3 [# S& r7 J) N9 L3 e& I" m- b
#if        0
: k  _7 _4 [# M  |6 p                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 A) s% K. ]: Y7 B. `3 O
                {
3 p1 ?; m- V& E: G, ]) \                INT        diff = abs(output-last_data);8 d5 y9 ]. Y. i5 o5 r! {9 C  _; b; `) Y
                if( diff > 0x4000 ) {
. v2 ^( `6 G; L                        output /= 4;& E0 G; N6 e' x) I: V, t
                } else
+ v  P: R7 X1 p: i9 D- ]                if( diff > 0x3000 ) {7 r; i/ `- u; F! s/ m
                        output /= 3;
2 C$ H$ G5 O: J7 m4 Z                } else
% E) P2 ^; A' n0 H                if( diff > 0x2000 ) {- e3 k/ G2 ]) ~( r( P5 V
                        output /= 2;4 a% u: K( f8 j" x1 _
                }8 p# D! y% n: Q! E2 O8 a: L: o5 c
                last_data = output;
1 s+ P3 Q  f. j) T/ X0 ]                }
  l% ]& Y1 T2 ?; u#endif
: P- L3 T# c$ b5 X                // Limit3 y* f1 a) D9 s* S- U( Y
                if( output > 0x7FFF ) {
8 J9 f( `9 M" f7 F+ P8 f7 V* y                        output = 0x7FFF;) {+ E  R9 I* ~
                } else if( output < -0x8000 ) {
; `2 O2 ]5 Q9 _* i                        output = -0x8000;  [  r/ \; n, M$ S+ o
                }
* w0 ^' X$ u/ M4 a: y$ L/ ^) l! E
; B! U+ H/ ?$ g% S& R- D$ z                if( nBits != 8 ) {' ~$ A3 w1 S- r& `( n* S
                        *(SHORT*)lpBuffer = (SHORT)output;
% V# G# j' T! \                        lpBuffer += sizeof(SHORT);
9 B3 ]' d: c; w                } else {
' k9 c5 n. }1 O# ^! t2 |) @                        *lpBuffer++ = (output>>8)^0x80;
% T# v$ `+ u6 {/ {                }
( e9 x2 b  O1 E6 O: ~
& T- P: c7 g1 V# f0 W                if( nCcount < 0x0100 )  O2 i3 \0 v  _  u
                        pSoundBuf[nCcount++] = (SHORT)output;
7 d& G' o- H2 b6 }  A4 v& H
+ Z9 c# A" M. o* l. H$ W//                elapsedtime += cycle_rate;- S- I# e6 {1 ^* @: Q! ?$ k2 ]( N
                elapsed_time += cycle_rate;
' l# Z0 r# [" I9 P        }
0 {3 \, \7 _: x) ]% C/ z+ v6 N. Y$ q
#if        1
# P( ~! x( T" i- J        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {9 i; ]4 p" c4 i& I
                elapsed_time = nes->cpu->GetTotalCycles();
5 Q, U+ [# h: x# _! N; o% ?5 m! ]! Z        }
# b& A% W  h# ]0 l2 E        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. O/ f) ]2 O6 s( X% W9 R                elapsed_time = nes->cpu->GetTotalCycles();
9 p8 X0 o- I! n8 ?) W, y        }, x6 l3 Q* \5 ~, A3 ~' q6 j$ T4 x! V
#else
6 p% |" Q; L5 }        elapsed_time = nes->cpu->GetTotalCycles();+ k/ O7 @' ^" g3 y
#endif3 `9 I* y# u0 E( @4 k
}4 d+ E, u( C1 [3 v1 r: y4 E
9 _1 k( q/ M& ]2 g$ h
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 z2 b+ ]* K" s8 T: TINT        APU::GetChannelFrequency( INT no ). A9 f* p8 @7 x% X. z
{
3 i. o4 t/ p& ^1 v0 y        if( !m_bMute[0] )3 x5 M8 O6 g3 D
                return        0;  ^4 U8 V6 ]6 e& z
( r, S3 G1 d3 U
        // Internal) ]; v+ L! `  |- }  G% H" N
        if( no < 5 ) {. C6 V! g9 D! K8 E
                return        m_bMute[no+1]?internal.GetFreq( no ):0;( X# \9 L; |. D' ]6 Y
        }& o) I, z. F+ g
        // VRC69 m$ p7 o2 j; ~$ ?' O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {( t5 q% W* L2 n( d2 G1 D0 O
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
! Q2 d0 z$ b; P8 X9 ^+ q        }' J( s% g6 J- v3 X# K
        // FDS" v) q8 \" P" A" o# _+ m! K, |
        if( (exsound_select & 0x04) && no == 0x300 ) {
% x, ^6 e9 t( A) l                return        m_bMute[6]?fds.GetFreq( 0 ):0;$ b# q) V! V! g8 F5 X: F' I% A
        }% ?" Y2 C& {& d6 }" r
        // MMC5  D3 ~2 A2 [. ^" [
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {7 s! v/ `3 o# F5 N6 i5 R
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;" @: Q7 [# u' n/ `/ a
        }& U  Q/ x* `* D. l2 e
        // N106
; P& \2 K/ N$ u9 a, F        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: A3 y# J' ?/ o: k) ~$ R
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; A5 Q' `- a  F' c1 s
        }
$ a/ w3 ^- w8 \% t        // FME78 S1 k( C& L; }" O
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
4 X: \& S" y3 A1 Z8 R6 _, Q. N) k                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 M: {  w8 Z# h7 A. ]) h$ U4 }        }
. ?/ p- |8 x! Y        // VRC7
; x: p) |' k! p4 @1 V7 A        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
2 d& z2 ^7 i4 u) o+ M( o                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- Z! |+ g3 Y5 z0 s7 U        }& \% s: r' ~+ t/ [5 b/ R+ ?+ _
        return        0;2 ?; w& q$ A6 e( ]+ O2 {3 r$ u
}1 X) l  |, a& o4 y$ [( L
( l! T# U/ U; \) m/ Z1 `! S
// State Save/Load) `+ \4 ^6 G' s0 a
void        APU::SaveState( LPBYTE p )
0 I/ O. I! O/ \# ]1 z6 F7 i- e{
5 I: b; B1 y4 H3 E#ifdef        _DEBUG
7 v- ^0 x& R0 f, T  y3 H' L, iLPBYTE        pold = p;
* q* T2 Y, d8 ^9 y: m#endif
" h) ]0 i) s7 e2 n$ G0 l& I( P2 C9 ~9 @% L4 D- j& f# ^
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞. K9 g7 p! }; Z. [) E0 G
        QueueFlush();- o8 ?* c# a- l

2 e( ]- r" o$ g! l3 t6 O        internal.SaveState( p );1 o# P+ K, x" ~0 ~8 x' L2 N# Y" k
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 `; r& u& Y( C# F2 t
& d/ D9 m% v6 j1 F" c& m) G        // VRC6
/ Z- {8 m% P4 U- f6 [% R        if( exsound_select & 0x01 ) {
+ G! T' u2 H* j                vrc6.SaveState( p );
# j0 @7 [* H; ]  u. |; C9 t                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  D) _  L5 h: H9 ]        }, I/ c9 Q( R8 n
        // VRC7 (not support)
. x( m( W4 F; T# N; S4 k: ^! g        if( exsound_select & 0x02 ) {5 u. z, C, `5 l5 s  ], \* J$ t
                vrc7.SaveState( p );: ^$ ]4 o; j7 c
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 j! \+ W4 Z' \9 r. u4 R7 n2 ?        }" F( D" d, A6 c6 q% v
        // FDS
$ T- c) O; ]( f! f' ]6 N( q: i        if( exsound_select & 0x04 ) {% S% ^3 \8 _) i! z5 V  |" c) I
                fds.SaveState( p );
! P' k! G# i. p1 K7 q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% f' k( z- C0 ~  ~: m
        }
0 d. k9 z/ E# X0 j        // MMC5
( c: n! n6 z0 \; \. D" X% o        if( exsound_select & 0x08 ) {
, O0 ]" _( E9 K0 @2 d/ H3 ]                mmc5.SaveState( p );
4 R8 l* I& c4 a, Z7 k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 T+ {% r+ p0 h* X1 F5 Y0 B        }
8 W9 T; b2 V! I% S: T        // N106
! J% z, w; K- y        if( exsound_select & 0x10 ) {
1 t$ M- o. `2 w                n106.SaveState( p );
' y9 `+ ]- m' o7 C& r5 U3 M/ M; h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' a# f, G* D4 e( l8 ?+ ?2 H        }" A+ R- K4 C$ Z
        // FME7
) |2 H$ x, r, l! ]0 X. @        if( exsound_select & 0x20 ) {
' y5 D& n  a$ O) W3 R  v' D7 t0 f                fme7.SaveState( p );4 _# Z, G8 G/ H# ~3 L8 ?( K. m' r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 M6 O+ ~+ t& f- p6 I5 W
        }
- K% ^$ g  m% w& j6 q6 y* N7 \9 ~+ k1 e+ \! O/ X0 ^8 v
#ifdef        _DEBUG/ |( |- ~3 p' n# [1 l1 _
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );& n+ n  H( K( V6 i4 [- c1 T
#endif" x) A( ^8 S' m+ C
}/ F0 z- @/ ~! q& h0 J4 C+ k

9 c5 ^! w' X5 Q+ G, Hvoid        APU::LoadState( LPBYTE p )
6 j- W) S" Z$ j" W3 E{: T: [$ K' g+ \% i$ P) J7 t- R+ X
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
" g* w% s# u$ Q' ^1 ]        QueueClear();: ?$ Q: \( S6 ~4 g* [, \3 N
8 q. v! L6 w3 ?
        internal.LoadState( p );8 D, g8 c" F2 k4 g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 k' {- z3 E2 R8 w

2 ~' ]% O- g1 z% a! d# n        // VRC6
* x+ R& `# ^) ^0 d        if( exsound_select & 0x01 ) {
/ E3 a- E" T0 l( o/ w                vrc6.LoadState( p );
* U4 a+ ~# H: t; R                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* g6 l9 N) t+ V# Z8 u0 H
        }
* M8 b  M3 y: R, i5 s1 ^0 Q$ N7 B        // VRC7 (not support)
  S, |8 f" y. E( X( w. t. a/ L* n        if( exsound_select & 0x02 ) {$ `7 g2 X. H# L
                vrc7.LoadState( p );8 G! A/ {* b6 I% v0 h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 B' n$ k" n2 W: e6 a0 p5 r
        }
8 K1 \) Z$ l- n8 W& a        // FDS
( [7 ?, [# `- q6 Z8 e& ~! Z  B        if( exsound_select & 0x04 ) {/ E1 Q- r3 }1 A4 n9 h6 \9 h
                fds.LoadState( p );
, A& E3 |; |3 x2 f  s                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* O% B$ F/ W8 K0 k        }# e: ]4 ?2 o9 M
        // MMC5
$ O% @$ r* n% F1 U* T+ X6 O        if( exsound_select & 0x08 ) {
% q  ~; c: O& G0 L2 P                mmc5.LoadState( p );( d1 I# k; I" q' }- j
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 N, Y# }# V/ [0 i. k8 z& q        }
2 I4 R# z1 j" |# \  Y$ {        // N1062 O: v8 j5 i: v& n4 W9 b
        if( exsound_select & 0x10 ) {
1 g/ G0 w* W) {- H# A                n106.LoadState( p );- U' Q6 R0 c4 n% ]5 ~* y
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
7 W% w5 ]$ U, s! i$ a& [( ^        }) h6 x, i- `* H9 v
        // FME79 E' g- U* S7 o8 A( n
        if( exsound_select & 0x20 ) {. k# y' X7 r$ n. P9 v4 N+ F1 F; {
                fme7.LoadState( p );& g% s" E3 a/ ~0 r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 l$ z, y5 p  y5 v; @+ r( c5 l# g
        }
4 {2 S* c$ N! ]}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 , b: S0 Q- d2 H5 i1 x$ U/ q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。) l! h& P4 ^6 }  }! J* G
感激不尽~~
- |. Z! b) M  ]& j
恩 我對模擬器不是很有研究,2 B# Z0 y- w' N. P2 b
雖然要了解源碼內容,可能不是很困難,
  N3 ^+ ^  M2 [8 _- |不過還是要花時間,個人目前蠻忙碌的。" P! S0 u, s  l5 k2 l2 f1 u
/ Y: h( g8 ?  X( @3 b- `
給你一個朋友的MSN,你可以跟他討論看看,/ z% _; g7 ?: c* n& W0 C3 q
他本身是程式設計師,也對FC模擬器很有興趣。, S; W, w# H) B6 Z( L9 R- Y/ a

% u- B" b& Y, ^2 X1 H4 S+ G2 R% pMSN我就PM到你的信箱了。
& \! P1 q& u% M4 X: q. y. M
' N/ I) @% y. T& s希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
! i, A8 P% d; ~! c, Y呵…… 谢过团长大人~~
& g! a5 f5 m, {6 @; l% v
3 w4 l5 V" t& B7 \; a0 A
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 {6 s" O% g4 H" @- Q5 {! ^/ \
团长的朋友都是神,那团长就是神的boss。

) g+ ^. R" Q( Y* F0 {0 N! I哈 不敢當,我只是個平凡人,% ~9 ]1 O5 S/ C# W2 {. t* [0 w8 k
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
- Y- G# o' L2 ?0 j* AZYH( J7 ]3 e; q( ]0 n0 R6 W: w
QQ:414734306/ K# V( E5 y2 S3 ]8 f* l
Mail:zyh-01@126.com: V: x' {2 [6 y; s8 j/ m) O

1 `9 {3 }$ S2 J9 w8 H他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
! e4 S6 A' g- h. x) R再次对团长大人和悠悠哥的无私帮助表示感谢~~

: j; _; ~% s% O& o( y3 p3 t不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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