EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 u) k9 _; ~, k# E( b, W楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~5 d6 i& d! L: r+ x$ R+ L: U% O" T+ m8 g
这里有相应的模拟器源码,就当送给大侠了~~
$ V: g+ R0 o+ |2 {7 P9 ]http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 S0 ?# i2 C4 y+ Q- p. q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 g# y6 |+ ~0 F. ]/ R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) w) f& ]. K1 J/ b7 Q. h: Y这里有相应的模拟器源码,就当送给大侠 ...
  S  _1 Y0 f% _
聲音部分(Audoi Process Unit = APU):& J# X0 q* `8 b. V' H
.\NES\APU.cpp
7 c3 I- V1 j# z; L6 [/ l3 x.\NES\APU.h/ }; T, ^( R' t. G
% B' F; U- F# J9 b4 [8 R* X

+ f" P# q8 q# }7 S影像處理部份(Picture Processing Unit = PPU):
. x4 [' w( S0 C.\NES\PPU.cpp& y* K- k7 |5 _7 H
.\NES\PPU.h0 W8 {0 X1 v" @6 f' _2 X
4 Q& \) H# @1 J7 X
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* s* ?1 K' {! H* O, k5 @(由于很多专用术语和算法机理都不明白,所以看不大懂……)0 c8 \3 O0 h4 N
//////////////////////////////////////////////////////////////////////////
3 I5 [9 e) L; v5 z, f//                                                                      //. F! D2 {$ N$ R
//      NES APU core                                                    //
/ N$ n- U% Z1 \7 U//                                                           Norix      //( U' x+ c7 v, _- l1 N/ a$ W! e; Z
//                                               written     2002/06/27 //, }& w5 \+ V$ f5 e% m/ c
//                                               last modify ----/--/-- //
/ ]( w8 e0 m: i' U; W2 i//////////////////////////////////////////////////////////////////////////
6 W# |$ s2 L3 B. P#include "DebugOut.h"
2 ^7 @! ]3 v2 i) f. }+ a#include "App.h"
# a4 b) ~' s* d% c! e! N( _. y#include "Config.h"
' Y- M+ T6 e  H5 c$ {) [8 [2 k3 N; u! D  ?/ f7 X
#include "nes.h"1 b5 H! Q( r' ~; l+ n4 Q. W
#include "mmu.h"; N7 e8 _1 ?3 o; t9 V
#include "cpu.h"3 F2 ^6 A4 q/ H! }2 }
#include "ppu.h"8 {4 p0 P4 V1 x, }7 B. m
#include "rom.h"' J5 x2 v8 E; q* u
#include "apu.h"& ~6 ^# |7 a. Y! \

" X" q$ n! A9 w9 D( w3 v, {// Volume adjust
" h) `# B4 c+ U6 [& n// Internal sounds6 m& j  s" q1 d% t( p/ |
#define        RECTANGLE_VOL        (0x0F0)+ e5 t. E: e3 d, R% Z* q8 C' t0 R
#define        TRIANGLE_VOL        (0x130)! g% ^( R$ u' Z( r- f4 q
#define        NOISE_VOL        (0x0C0)
* ]+ p& |/ W; n6 l6 h4 H! S#define        DPCM_VOL        (0x0F0)
3 U: ~0 @" A* J2 ]! |( p- P( @// Extra sounds
2 r4 I8 _9 L7 o7 A, J4 O, H0 j#define        VRC6_VOL        (0x0F0)
* \) T  H$ w/ c7 g9 }/ h6 E3 u#define        VRC7_VOL        (0x130)
  f1 u2 E  X- O  V( F; M#define        FDS_VOL                (0x0F0)
' h" R8 ^0 i5 Z. O* {/ W#define        MMC5_VOL        (0x0F0)& {8 S' w  [4 R+ p% Y( L
#define        N106_VOL        (0x088)7 t3 L: b6 t- b2 S$ N8 M- r7 P: g
#define        FME7_VOL        (0x130)/ |! Y' a3 \- W
( V# j  u! e9 S. I6 I/ R2 h, n
APU::APU( NES* parent )* e0 `' ?! M6 l9 f4 o! |2 u
{. \. e  f! \8 o1 _' _
        exsound_select = 0;* f# N; Y# l1 ~7 F% F
5 Q: m: S$ j( n/ A7 L
        nes = parent;
  }3 [! v% ]( @- I- F# @3 S" ]6 l  W        internal.SetParent( parent );3 @% H6 O- F* f  C% g" R
; A) m$ [/ E" \) j" c* ~
        last_data = last_diff = 0;( J% j, t4 i7 Q; D9 P* L

/ ]; R  L8 |$ s- x        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 r- u- v4 ~$ b% m
  \/ T! C; T+ l2 G        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
' q$ M4 G; q" p1 w7 g2 j7 r        ZEROMEMORY( &queue, sizeof(queue) );2 L8 _* O4 u# O" O# w& o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ `! V  m6 o! C1 e6 e( M

) O( e# i  B6 c' \* B% Q3 `        for( INT i = 0; i < 16; i++ ) {
" l$ e# Y5 S+ P$ X                m_bMute = TRUE;: X3 ~% X7 f/ t& G% p" q+ F9 V
        }7 [4 ~) _8 c# P
}9 u4 ]( ~3 q/ }7 t1 z

, u" g. A: c  H* ~. s3 nAPU::~APU()
* M- B6 ^  a: e. [{3 K1 H  E2 e, p0 h
}/ j8 Q6 p9 \! m8 [; m+ V8 U
0 e( h3 Y& l. |  [; i- b) T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
7 y3 ~/ u: }; |0 a( Q; N& S{# y1 z/ }& r$ k
        queue.data[queue.wrptr].time = writetime;2 N1 S0 K5 ?- {2 T
        queue.data[queue.wrptr].addr = addr;" p* s* r& m! D8 g
        queue.data[queue.wrptr].data = data;
* h1 s9 E9 e) m, N        queue.wrptr++;
/ G7 k" n0 T4 G2 ~6 w% R) H        queue.wrptr&=QUEUE_LENGTH-1;
: u% d0 ^3 {1 w; p- {+ v, K        if( queue.wrptr == queue.rdptr ) {$ c1 A# Y+ h% c  r, X  J. t! n% \
                DEBUGOUT( "queue overflow.\n" );
0 Q6 }+ j* f" F3 `( y' o# e4 V% u        }
! M5 L3 R4 Y( B0 @4 {}8 P4 O  ~+ W; F: @# }6 p+ s+ |
0 t+ x' O- [) L2 i& f
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
' m& t, f0 q5 j% B2 u  E, {{* v7 E0 F, C+ `: [( P
        if( queue.wrptr == queue.rdptr ) {2 ?6 L+ e: @+ z/ e
                return        FALSE;
% Q7 i6 m+ E5 b6 N* P5 n        }" C& x. E2 R) E+ A* A
        if( queue.data[queue.rdptr].time <= writetime ) {
+ ^* G4 ~$ g, w5 y% C- @                ret = queue.data[queue.rdptr];
* ~/ P6 u. R9 S, X; ~' H' p4 ^% K                queue.rdptr++;- k# y# h% k% @
                queue.rdptr&=QUEUE_LENGTH-1;
' d0 ?, n! h: ^9 E& n6 r2 B                return        TRUE;6 e. _3 t3 j! Q/ N6 N
        }
& K. I) m0 Q7 y3 o: F        return        FALSE;
8 }+ m- s3 v. \2 U, u- P}0 C. ?% G4 H5 R% B+ ~

" t3 v1 W& d7 u8 G8 Q& Evoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
  d  f7 B2 L% t, H2 f" L0 X- R{
. @1 h8 R0 a( {7 m* Z        exqueue.data[exqueue.wrptr].time = writetime;, v' C5 C( M9 Z, z6 ]0 ^5 K3 j' U
        exqueue.data[exqueue.wrptr].addr = addr;
2 j$ w$ {( S; a3 X$ U3 s        exqueue.data[exqueue.wrptr].data = data;
; w$ N( W5 v( e& g        exqueue.wrptr++;
+ g, r1 T, F3 Y: x% Y4 N        exqueue.wrptr&=QUEUE_LENGTH-1;8 j" j8 P5 p  }7 z" h2 Q# E) P3 t
        if( exqueue.wrptr == exqueue.rdptr ) {
( x- q1 y+ u: J: O" p                DEBUGOUT( "exqueue overflow.\n" );+ `1 U7 u3 }7 I) y* @! c
        }, Z9 J0 N1 g1 p' J
}( J+ G. k* x( k2 c+ A2 x% O

+ P3 h$ @0 T) |0 P$ zBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* y7 j# k0 z* ^) u& f9 }
{
+ D6 l: F0 |# t8 q        if( exqueue.wrptr == exqueue.rdptr ) {9 J' i# {8 U' i  V
                return        FALSE;
" z4 n: a2 u* e: B3 h  d$ e        }
1 e, k0 {" u( ~4 R/ l- \        if( exqueue.data[exqueue.rdptr].time <= writetime ) {+ R. M- y! B$ g  m% m; n0 j
                ret = exqueue.data[exqueue.rdptr];
* C/ r% f% O. r                exqueue.rdptr++;
5 p! P. O7 ?! A3 @6 I2 @                exqueue.rdptr&=QUEUE_LENGTH-1;
5 E) @0 o5 _0 u3 \: t                return        TRUE;, n- }. Y7 d* m/ C& Z! R7 r6 E
        }" n4 \2 F/ @+ y, f! L  {0 C& f
        return        FALSE;
3 I) @( D9 h3 U( C& D7 o}
: s4 a* X& y3 P- a: V1 U$ H9 Q
* J  d) O0 G) _( m& Bvoid        APU::QueueClear()- S, }/ u' L; k
{
! E! r* O) u0 ]        ZEROMEMORY( &queue, sizeof(queue) );
0 v: d6 v! l  a" a: x/ u& f5 u        ZEROMEMORY( &exqueue, sizeof(exqueue) );: v# R. v' p; `9 M
}& R. F: o$ Z2 l( ?1 [. ^
: H4 ]# E; f" r3 a7 [
void        APU::QueueFlush()4 [+ o8 I( F; L& Z: ]* e, g
{1 ]8 p9 J- t2 Y6 K; W
        while( queue.wrptr != queue.rdptr ) {
$ W: \( y. E2 d1 P! V                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );; L! v) N% w, ^0 W4 H2 H! w
                queue.rdptr++;, ]5 ~/ v. T7 V. E7 `/ I
                queue.rdptr&=QUEUE_LENGTH-1;
+ u% m+ a. Q; {: z        }
( L1 }8 z6 P9 s% F3 k8 q! b5 P# q
        while( exqueue.wrptr != exqueue.rdptr ) {8 C5 W* S) D$ o% U
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
; [( c4 F( d8 @$ O& K8 d( Q, @: k                exqueue.rdptr++;
+ w  l3 T7 b9 P8 V' u! c4 c                exqueue.rdptr&=QUEUE_LENGTH-1;3 l* f. a0 N" L  u+ Z2 M2 S) T  U
        }
5 ~$ ~$ _: I) }# `: o}
5 h( g0 I2 ~8 I0 p$ S5 c- t" Q# K6 B; v+ T8 V$ S
void        APU::SoundSetup()
0 R  X. ~8 \0 O{' u3 V! m  x# e5 B$ g  Z, i
        FLOAT        fClock = nes->nescfg->CpuClock;
, T* [1 c) H* d        INT        nRate = (INT)Config.sound.nRate;3 c9 r$ O+ L6 K0 R9 R
        internal.Setup( fClock, nRate );2 A- p, K" y9 u" ~; U: F/ S4 e  y
        vrc6.Setup( fClock, nRate );$ `) F: X/ N4 H5 d. O; ~! P! ~
        vrc7.Setup( fClock, nRate );: p# M7 _# Z6 E6 G; n$ Q
        mmc5.Setup( fClock, nRate );
, w$ T- s9 B1 \$ A$ m        fds.Setup ( fClock, nRate );
* _) B" k+ c6 `1 V% O2 j5 E        n106.Setup( fClock, nRate );
5 J  x( N% p7 @  `4 ~        fme7.Setup( fClock, nRate );/ a) x% Z/ k# ]" R. x7 i( c
}
. K' ]6 C3 T& z0 l( b' s. }& m8 D# H. q( x9 K) |3 ]
void        APU::Reset()( q4 V& W( ?0 O6 |; ^
{1 k/ I1 L$ y! N5 S
        ZEROMEMORY( &queue, sizeof(queue) );( `( o3 o7 ^4 }  T/ @" t( ]9 }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& W% c! b2 _" P
- E, Q* k2 ~. Q  M4 h        elapsed_time = 0;
3 w1 m# q0 A3 Q' H& v$ E
; W! e% _: C" K$ H        FLOAT        fClock = nes->nescfg->CpuClock;* h8 ?) u: h; t4 H
        INT        nRate = (INT)Config.sound.nRate;( B2 p: H. _6 ~0 b
        internal.Reset( fClock, nRate );% E4 U2 p* u6 e' G. E$ @" [% z
        vrc6.Reset( fClock, nRate );  E7 V  _0 D) t, i7 Z
        vrc7.Reset( fClock, nRate );3 K4 [$ l7 B" ~  N+ h
        mmc5.Reset( fClock, nRate );- \# S) Z: p; ^$ L1 S. ^: B
        fds.Reset ( fClock, nRate );, a- G$ u0 X# ^8 E0 i& g
        n106.Reset( fClock, nRate );
/ r7 Y7 X7 T- @8 E9 O& e7 P        fme7.Reset( fClock, nRate );
! c/ F. |6 z4 _% h
0 l5 z2 `! t6 M; k2 K        SoundSetup();- i9 p4 Q9 A) p& x) Y- d- p, f1 q. ?
}- i: g! b  H6 \  k. b

3 |9 N1 n" x  G. T7 |5 L8 ivoid        APU::SelectExSound( BYTE data )4 [# d8 }. h' B8 J3 [
{
' Y0 |, y, }, f2 K9 n; t        exsound_select = data;$ z- E0 v1 d* h/ p( Q* X
}
5 Q5 |1 |% i& b8 s  u6 L+ c( c' M; F4 k0 L$ p' F. N6 o. Q
BYTE        APU::Read( WORD addr )
8 [* X, w6 p6 U1 [5 f0 M. I{6 `' s) W" S. e( |- K
        return        internal.SyncRead( addr );4 _  Y% l9 d6 J9 S$ K4 J; I  E" ?
}* ?% C+ X2 p1 ?& s' r: h2 C

+ u$ u% a/ a& D, d$ o$ Y- yvoid        APU::Write( WORD addr, BYTE data )
4 Z+ F/ `# G$ f- |1 ]{# ^8 X- a; W: h" \, [& W
        // $4018偼VirtuaNES屌桳億乕僩/ x5 y6 a6 ]" z" {" u0 O
        if( addr >= 0x4000 && addr <= 0x401F ) {; c$ f2 |+ L8 A2 X. C; z
                internal.SyncWrite( addr, data );
# j3 O  \4 n* Z5 G% r" Z. B" l                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
5 j, ]( ~8 `) X        }- e) H1 y. U* i. r" Z
}
8 Z; r( E; }7 S7 \6 ?* Y" X
& G" }. [. U, d; ?* g) RBYTE        APU::ExRead( WORD addr )" ^6 x9 v# y* Q( Q: Z, o
{. k8 S( s. ?/ ^# x% x
BYTE        data = 0;0 u" q4 O1 c2 {* e
1 f1 m( E- M" A3 g
        if( exsound_select & 0x10 ) {
2 X$ E& }3 z. Z# c* s                if( addr == 0x4800 ) {2 v# q3 I. t- p; Z; i; O9 {
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, A$ X% }9 n( r% a  |) i9 r                }1 I+ [) o8 c8 J. r+ {
        }. G5 N2 h' G2 B0 \
        if( exsound_select & 0x04 ) {/ O: y- O% x5 Q$ ]3 t$ A
                if( addr >= 0x4040 && addr < 0x4100 ) {
  h; k/ h1 q6 _4 [1 C2 l                        data = fds.SyncRead( addr );8 R- D* u) Q( M4 t$ K. o2 L
                }
* N% \  k" l- R: P; h/ t        }( r# r/ \( J8 R8 I
        if( exsound_select & 0x08 ) {  X( H9 \) L8 Z% K+ H( j. {: Z9 l0 Z3 y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 N% p' _5 N* _" V                        data = mmc5.SyncRead( addr );, ~' Y4 ^! Y; l7 ^! ?$ I
                }
! c6 b. ?) a* N" m0 }9 ~7 i+ V% [        }
: D* B# R6 @% G* V& `1 i+ r
9 @, F* l' c! b0 E+ _: E        return        data;8 J  Y( P0 l2 P
}
% b1 q! t1 f8 Y) v7 S. e0 }
' w% D2 y1 Y) \2 ivoid        APU::ExWrite( WORD addr, BYTE data )$ N# D* _& x8 g
{
6 I4 i8 `0 K/ @3 _( d% ~/ @6 `9 Y        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
) Y% O) s7 y  q: T* |' ?
7 B5 F8 J& W; [* Y# q0 l' {3 c        if( exsound_select & 0x04 ) {
3 Q- d4 r% q5 j1 Q. e: L                if( addr >= 0x4040 && addr < 0x4100 ) {! z% [4 S# X( o7 X5 u) f
                        fds.SyncWrite( addr, data );
& i' H5 J  K. M7 a                }
( E5 R+ J1 a- J! t        }1 J, {2 R) o3 P/ c+ I/ l% O

; _* d0 g8 F. ?2 D        if( exsound_select & 0x08 ) {) X9 E0 Q- ~. ~" C+ n
                if( addr >= 0x5000 && addr <= 0x5015 ) {
' b, d; ^0 r3 }( m' w- Z                        mmc5.SyncWrite( addr, data );; x! T& s! Y) w" v/ c1 o9 C% q( T
                }
+ d+ D  z  P1 ]        }, T- x# h( T) E$ F) A- V. }4 M
}
2 q7 p6 n. F1 `; r3 A5 g$ v$ y# W5 z
void        APU::Sync()6 ~, j! \, x0 v% a' ?5 r0 X, y, ]
{& Z3 O( h2 @0 d% o  O( |& {) {
}
0 Y5 {# M+ I, C0 ~: F8 s' y3 p; X# ]1 [! m
void        APU::SyncDPCM( INT cycles )2 |) V' e/ K9 ?4 U' p
{
9 u' ^: s4 q0 ]' |& x: V: z2 h5 @        internal.Sync( cycles );
, M) N8 n" d1 @9 x4 X* B9 V4 Y
/ Z/ Y0 b; h" F9 [$ w' S. l        if( exsound_select & 0x04 ) {
  E. l+ f. p1 F4 v: a                fds.Sync( cycles );
6 h0 b9 r' Q2 H$ ?, l        }
- N8 U' d+ j* S+ @        if( exsound_select & 0x08 ) {
1 M% v2 G* B# [3 K. D3 Q) v                mmc5.Sync( cycles );( y, I7 l( `, A4 ^5 A$ Q
        }
% @# F' T+ x' U( d) t# L& g}9 P# {. ^- p1 ~4 f7 c

6 s0 {& |) k2 |1 z  C6 xvoid        APU::WriteProcess( WORD addr, BYTE data )
' F# e; z. ]1 q( V) ]  B% J3 F{) U- F5 h! M; N3 |/ R0 c. [% v
        // $4018偼VirtuaNES屌桳億乕僩0 J# e5 u; N3 r% _- [$ x& n! x
        if( addr >= 0x4000 && addr <= 0x401F ) {& Y1 O9 f! F- t) |  n
                internal.Write( addr, data );
/ g, V% c: g- n$ B/ V, R        }+ j4 D$ @+ s5 O5 c* A# j
}& O3 {9 y2 Q9 T5 ?0 R/ C/ M3 b

" N5 r5 f3 ?3 z8 e* l4 {2 fvoid        APU::WriteExProcess( WORD addr, BYTE data )5 R' T1 L& W3 P: _4 [
{
! t/ @4 }; r( a' b% f  b/ u        if( exsound_select & 0x01 ) {, p, c2 D. @6 `
                vrc6.Write( addr, data );7 c# P" i8 Z3 K/ n6 u$ y
        }
- L  F" t& i; O3 Y8 w        if( exsound_select & 0x02 ) {* ?/ G+ R8 Q: |
                vrc7.Write( addr, data );6 \" k4 g, _5 p$ b; u
        }  h* z! q' V/ T8 R! b: h: s# c' d
        if( exsound_select & 0x04 ) {
! ]& ?8 W1 ]6 z2 C5 g+ [                fds.Write( addr, data );& }0 O4 G; U* _! x) A
        }9 X5 R; t: t3 e' U
        if( exsound_select & 0x08 ) {- a6 F- ]& t+ l1 J
                mmc5.Write( addr, data );' N+ O/ W$ {  n! k3 p9 h% U
        }
- S, K& }# m8 ]- V        if( exsound_select & 0x10 ) {% s% o8 O" U, @- O, T7 h
                if( addr == 0x0000 ) {2 I! `& E! X: R7 ^2 F
                        BYTE        dummy = n106.Read( addr );
: G1 y+ O. c: k9 o3 P4 `                } else {. E9 B5 A. B: n  D2 I# ^' E
                        n106.Write( addr, data );
+ k. C) P: i( j                }
, v- b$ E* r, ~6 u        }
' K( I1 k  [: ?$ P5 K        if( exsound_select & 0x20 ) {. W$ w# T. C; q$ q
                fme7.Write( addr, data );- W: d' K0 T4 b
        }
( X& F) F& t* ]% _}
5 s/ c8 o# K7 F% c6 w& c! E7 e5 i
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )5 P. W) G& ]2 a9 R# M# F
{2 c9 F( a- U; ?( x! {8 {$ v
INT        nBits = Config.sound.nBits;
# N6 Y" Z6 H1 B% u% M( X8 PDWORD        dwLength = dwSize / (nBits/8);9 ?: m) e; I2 o3 L/ O
INT        output;) C: ]# C$ H* e" Y
QUEUEDATA q;+ k8 |) l: h! J% F5 Z3 U8 h7 \1 l
DWORD        writetime;1 E  a4 _: ^, I) A7 R3 N

0 q1 ?9 x$ P9 W. C; }LPSHORT        pSoundBuf = m_SoundBuffer;% i8 C- s+ N) B6 A) V% c
INT        nCcount = 0;
! v# G# ^- {  f4 [6 Z( j8 ~- @! o; o3 f7 `
INT        nFilterType = Config.sound.nFilterType;
' s8 z8 h+ |! ?% w  m' f6 G3 V% t2 o1 p# C6 B
        if( !Config.sound.bEnable ) {
2 y! V2 C  ]+ h9 C' W% z$ n                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
6 c, W( h  V% q" Z                return;
0 c  S. {; P8 Z1 s8 B        }1 a" [3 n3 c# Z8 x! R
0 R) F7 g& z: _7 r' ^+ R
        // Volume setup; j) K. ~% S& B/ c: ~% ^, ]4 g. v! g
        //  0:Master6 o! B7 F8 i; w1 {. R1 H4 i0 w( n
        //  1:Rectangle 1
# k0 G9 A+ A$ b: H+ s        //  2:Rectangle 2
2 H0 T0 i' h9 }0 Q$ R; {) u        //  3:Triangle
# N+ d' s$ W( T        //  4:Noise
& _: G* h" w; s. |) B        //  5:DPCM
0 s3 k+ p% ~% `  x, a  i( }5 p* c        //  6:VRC6
+ ]! N. p. b7 d* c4 i        //  7:VRC7% U$ k) {2 b; ?0 I$ j1 K; [
        //  8:FDS
( ^( K: `% l2 }5 M; Y- Z        //  9:MMC5. v4 l6 [) n& x! f7 ~
        // 10:N106
8 a+ t  c' c* c! Q/ ^' n# R        // 11:FME7
' Q  I- E4 B/ K4 K: a3 q% h        INT        vol[24];
' ?9 [( a' `; ^        BOOL*        bMute = m_bMute;  E- H0 P; ]4 ~: }  l" J  R
        SHORT*        nVolume = Config.sound.nVolume;
4 {) Y- s* b; `) L
, Y5 z$ T  i9 v7 a' {: v7 T+ l        INT        nMasterVolume = bMute[0]?nVolume[0]:0;$ o' m! c; U6 K

+ G. i' t) T4 J6 t: L        // Internal
% ^. C9 A9 {3 Z) y( r0 ~        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 \0 A! w- Z' Y
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; {' w6 ?! F2 l; m% a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;/ L: g# W. `  f( h' L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
3 S5 q/ o: [, |! a0 ?; A7 y* z        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! T4 ?  V: [3 d) z6 _& u- m
. E% g9 J0 Z1 L; S        // VRC6
: a! `  L1 @. v$ i4 D        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 _5 N/ F& e9 R1 K        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& Z& I; i/ R3 r, W        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: y$ l: m, j0 K4 h2 W" S
+ r2 s4 t3 h8 r" l4 m
        // VRC77 h9 C' ]5 u8 |# q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
8 @1 R. X% P) a4 G& P1 M% _) d) q1 b4 A* ~- \$ f
        // FDS. k; B2 o: I8 Z) f2 M7 }5 L- S/ {
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
) _9 w1 A2 I( W4 |. t" ^, r/ O) F7 K- g  q8 j
        // MMC5
/ P9 D* w9 T$ Z( f- C$ Z/ J. E        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 V; m+ M- d& {$ g
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ ]3 {2 {& @- g  ^' v( p' Y        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ h* b+ H- t& x6 M0 V. g' H
( j/ E% Y+ ^( u
        // N106
" y9 q8 ]  @1 U7 U" C        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: h8 a+ v7 f7 d  A$ I        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 V' B5 J% g  a% A& q1 L0 |( W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 ~+ [2 u" ?% r4 A- D7 E
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: S: P/ F- ^& F, ]. K7 K
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) d- k# L, W& V: ?- z! V        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! O, C6 f3 D! K( h$ g        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  h) \1 ]! z# T/ O
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 r9 S/ p& n# J9 _% g
0 Y+ B7 G5 p' b0 P+ j) r# ?        // FME7* e9 p$ j2 R" d1 w
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 `6 F, K+ z5 c        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' ?: l) E) H( S* [1 p' M* `  H+ l
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ P  y1 i5 `7 f& s* k6 [. Q7 w' a; Y! w7 S
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;; e8 j- M8 K2 }! e* _, ?# R7 B, s
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
0 x' R* h- s. v' q( q0 w* o- d/ X: v1 v2 _1 d5 A8 s- f; e
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟3 C/ h4 y! ]  P, A$ s7 N8 `
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {. e3 ^# D. P) r3 S
                QueueFlush();+ ]. f0 d$ h' f; k2 @8 l
        }
) h  w: ^- Q' t' i
+ P+ F6 e; x) {3 u7 \1 a        while( dwLength-- ) {+ `: z& {9 S. [0 `& Y& y
                writetime = (DWORD)elapsed_time;
% d; l1 N& U7 [  P. q" j1 x. K
8 c9 k$ e. y) O3 N                while( GetQueue( writetime, q ) ) {
+ n: H- T- u- A6 J" x# [                        WriteProcess( q.addr, q.data );
2 S2 o- N3 M& K& R" q" n                }
' b0 ~9 u; C5 y" v' m8 v* u5 S; f9 g* V* l9 B/ {
                while( GetExQueue( writetime, q ) ) {" K4 R1 ~: C: N7 W# g
                        WriteExProcess( q.addr, q.data );
% M$ t$ p) W9 z$ Z                }
( s, P4 w& i! v! n9 ^) q. h" H, z1 V) v3 a' d
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME75 N1 r1 G( D: c7 D6 H2 h
                output = 0;. r, }! a* p' `/ _
                output += internal.Process( 0 )*vol[0];" H; M1 V* z( e& y6 m- ]5 u
                output += internal.Process( 1 )*vol[1];
( ^* Z% u' h+ y% q! j                output += internal.Process( 2 )*vol[2];8 }) Y! R) T$ G$ z% {4 O7 o
                output += internal.Process( 3 )*vol[3];% C( _, ^. D1 {6 G7 j3 x
                output += internal.Process( 4 )*vol[4];2 t4 [/ U  J$ R5 B

6 G8 o( O' q4 N, S4 W- c% q                if( exsound_select & 0x01 ) {
1 z! s$ J" L& a1 z                        output += vrc6.Process( 0 )*vol[5];
) _" `6 l7 `) d. D2 V$ j# r                        output += vrc6.Process( 1 )*vol[6];
* w/ s- i7 F) d* J% }% ^9 k                        output += vrc6.Process( 2 )*vol[7];: |9 g/ Q$ G* U/ [! D  g( z/ `
                }; `# ]0 @. G) O' d
                if( exsound_select & 0x02 ) {
  N8 [$ C- ~! U3 a; I1 ^- I- G                        output += vrc7.Process( 0 )*vol[8];
; P0 u; L% |/ ?7 B" g                }
4 `- W1 p- J* m. L                if( exsound_select & 0x04 ) {3 W1 y6 t5 p% D, \3 H
                        output += fds.Process( 0 )*vol[9];
' S/ u8 K) x$ o# u& M; }6 y                }
9 A# K' F; ^- v  B4 U                if( exsound_select & 0x08 ) {
% t/ A" O2 e/ u, j( f' C                        output += mmc5.Process( 0 )*vol[10];6 x0 ~4 l5 S; K8 O# v, \3 q
                        output += mmc5.Process( 1 )*vol[11];% g& J  {1 f+ h$ p3 W
                        output += mmc5.Process( 2 )*vol[12];
& [6 F' }' q# `! J                }
; }& h9 O7 o. X# S; J                if( exsound_select & 0x10 ) {
; L. R. l6 R  F+ q                        output += n106.Process( 0 )*vol[13];
  R: v' c5 n  v* k2 V/ f                        output += n106.Process( 1 )*vol[14];+ w. S: I" H+ ?" A
                        output += n106.Process( 2 )*vol[15];1 J; M: j* c7 _/ }( ~/ Z" \8 r
                        output += n106.Process( 3 )*vol[16];- G! Y; q0 i$ _0 I# u# P
                        output += n106.Process( 4 )*vol[17];  v6 h" f9 Q5 T2 n
                        output += n106.Process( 5 )*vol[18];' R& d# G8 l" H
                        output += n106.Process( 6 )*vol[19];
: V. F( n  V6 ^4 M3 V: L1 a- [" u                        output += n106.Process( 7 )*vol[20];" N* t: W1 t! q+ t, m6 c
                }. B4 R$ f' `8 e
                if( exsound_select & 0x20 ) {, Z: G4 p0 _2 H' c. q
                        fme7.Process( 3 );        // Envelope & Noise8 O4 }3 l4 {" J: A  V
                        output += fme7.Process( 0 )*vol[21];! i5 m, d5 G. j% T4 R
                        output += fme7.Process( 1 )*vol[22];
- G0 o0 W/ r) g2 |' M; S                        output += fme7.Process( 2 )*vol[23];8 u( n: o- p, Y  o( o" t! a! N
                }
, |. r! R9 |( A% W( y
. o- a$ J/ G# m6 l5 M                output >>= 8;
; t( L# z  K7 y- F) |
" b3 f+ L0 O& B9 b, {% a                if( nFilterType == 1 ) {
) g6 i( F2 Z/ _9 {( B8 R5 h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple): s" ~6 O7 G4 S5 E+ l
                        output = (lowpass_filter[0]+output)/2;
# R4 e/ M3 ^  W; J* {; o# t5 \                        lowpass_filter[0] = output;
6 d7 J/ p" V% k* J: c4 j$ E                } else if( nFilterType == 2 ) {  w: I5 b0 w  b# G
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 ]/ F2 w* b/ l4 I
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;4 r# _9 B: E6 d' a& l  j% m  U
                        lowpass_filter[1] = lowpass_filter[0];
; }8 {  o# T. J+ z- U1 |+ x                        lowpass_filter[0] = output;
5 k/ Q7 j6 {+ o" x                } else if( nFilterType == 3 ) {8 ~) ], A& q: {7 u9 B7 V
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)' a( x8 ?4 R. u+ B' r4 ~( p1 s
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
! G! R( t2 U2 }% j, M                        lowpass_filter[2] = lowpass_filter[1];
% G6 r9 C  e9 w# R9 l3 e                        lowpass_filter[1] = lowpass_filter[0];
; q; L. d# q7 ~- B. ]; d/ r                        lowpass_filter[0] = output;
* Z4 a' x) c; A1 e1 S( m                } else if( nFilterType == 4 ) {' U' k" F6 f* i, V4 a% x2 o" u
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- W- }9 M( c: j2 q  K! m1 ?' x
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
! J- Z, R& p8 [                        lowpass_filter[1] = lowpass_filter[0];
3 W; o$ Z6 B% P6 J5 t                        lowpass_filter[0] = output;
7 s, t% `: k- L* l! i                }
# m, l# l) `- h9 b/ d
# [) q2 }2 s7 _8 L- H#if        07 |! Z5 G3 H' a0 u; E
                // DC惉暘偺僇僢僩) @$ d/ S. X! ~5 n% C4 V
                {0 z) L8 y% M7 j
                static double ave = 0.0, max=0.0, min=0.0;
" s+ t. o3 ~# `* Z                double delta;
1 t& H" q! b8 {+ \% s" J                delta = (max-min)/32768.0;
! s% t# N, U+ {                max -= delta;4 |; b9 ^# d1 }; k' N. r# j
                min += delta;2 u: U! A% L) f0 n/ B5 Z% S0 o
                if( output > max ) max = output;3 d: W) x. ~6 U
                if( output < min ) min = output;( Y1 v& O: i4 P' F7 Q. {
                ave -= ave/1024.0;. s: ^+ I; [3 i( a
                ave += (max+min)/2048.0;7 L. C. k6 ^+ W7 h
                output -= (INT)ave;
# q! r- O3 ]) g2 G! H' v7 ~                }
" J" @; O$ y7 r  L" W9 a& g#endif5 X' ^* p$ v& ?: F8 k
#if        1
  w; ]6 x8 W+ C& r8 K% ]                // DC惉暘偺僇僢僩(HPF TEST)
' l. a! }& c& O" }. m- q                {; S; c& h$ A2 _9 @+ z! D2 w
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
' L2 x# ^4 y+ [$ x5 |8 @9 S6 l                static        double        cutofftemp = (2.0*3.141592653579*40.0);- B: y& Q3 p+ B7 {3 F
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
( U" e" c) L% C                static        double        tmp = 0.0;2 I% r! g' R! ?0 m4 {' q  S0 v6 O5 s
                double        in, out;5 u: u; x! a% r5 ^  `: U& \" e# s8 Z; @

* D/ C  K+ G4 Z4 P                in = (double)output;7 C, c: B$ H3 L1 |: L! G# x" [
                out = (in - tmp);+ ?6 i% z& N! C, u, D
                tmp = tmp + cutoff * out;' K$ W) N5 `4 ~  i! Z( U
6 Q+ d* d8 e- P
                output = (INT)out;' S% w$ g& Y% C
                }0 A. Y/ o( d4 z) T5 [
#endif2 w$ J0 p5 V6 r
#if        0
4 E4 i/ U" |; G" g9 n                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)+ M# i: k! u$ R3 t
                {$ D9 E, ^9 j, i5 s& Q2 B- d. V
                INT        diff = abs(output-last_data);
- b1 c- \- c1 d3 r) u+ q                if( diff > 0x4000 ) {
; M% H! @# b% ?) a$ m                        output /= 4;# I; ?9 A' K0 G
                } else
8 a5 `! X7 A# ~, h                if( diff > 0x3000 ) {
; A& x: y" ~6 n7 _                        output /= 3;
, C2 o1 i: t3 ~& [; X                } else
4 J. Z  {! O/ {, c+ _                if( diff > 0x2000 ) {; l5 r- X* m9 N) q% W- l; Q
                        output /= 2;
- [9 b/ Y' J: Z  j: _0 R. I: [                }
. b+ i7 V1 S! F/ M4 g4 L% I* z$ x                last_data = output;2 \  E& k9 n" M, A- `
                }
3 Y  }/ \6 [: G* C! m/ |; {& t#endif- w. Y) ]( }. u
                // Limit! J9 Y$ q# Z- B! f1 G7 b( @
                if( output > 0x7FFF ) {
  y) G) Z" Q- B' D                        output = 0x7FFF;
9 I; d/ i+ a$ c                } else if( output < -0x8000 ) {
: S  L1 n$ A* H                        output = -0x8000;
- }) W# W: i2 l1 E) G                }( x& s& n# e- p: _" d0 |' n

( |4 m& X& m$ r; K! X' n                if( nBits != 8 ) {
. w7 [/ m( ~! j5 N. p                        *(SHORT*)lpBuffer = (SHORT)output;: p% O* Z+ R7 D* P( P' v' R% A2 }% m
                        lpBuffer += sizeof(SHORT);3 V+ U/ ]) t7 k* r3 c
                } else {- T8 M, w: A# X9 n, q7 T4 |: ^
                        *lpBuffer++ = (output>>8)^0x80;, e( s# X8 m) N9 ?
                }, y7 Y6 I3 \6 }- m3 O3 G+ a3 n
6 y% j8 }$ w* }( N* }
                if( nCcount < 0x0100 )2 x; M/ z9 }! n" g
                        pSoundBuf[nCcount++] = (SHORT)output;
: t) T9 A( Z( W) b; D+ m' f9 I: Z# g! Y
//                elapsedtime += cycle_rate;/ F" _: q4 U  s- y# s# `
                elapsed_time += cycle_rate;( F  W' N- G9 h. A& Q5 X6 N
        }
: x5 n- N& w" T& c* h
4 g7 y/ i3 V8 k5 |#if        1
; Z+ L6 p9 Z- {9 x        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
: ]. k9 T% E, G* N8 i( H: u" k                elapsed_time = nes->cpu->GetTotalCycles();* J- k; M8 g5 q* _0 J0 p6 Y; k  _
        }' Z% `. L$ P" r  E! U' F' \
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {5 c! D% }: P" B2 l
                elapsed_time = nes->cpu->GetTotalCycles();
5 N& Z4 L3 v, `0 d6 H3 Y        }
! r3 X; v6 f( B: _* n: W& e3 n#else. l. z! [5 v( ~
        elapsed_time = nes->cpu->GetTotalCycles();2 s3 y' J9 Y7 G
#endif* }0 }3 d( Q2 B
}5 w- f; S2 F* P$ K3 G

+ ?& O6 i/ Q/ c5 Y// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
; i0 B9 }( s8 Y) hINT        APU::GetChannelFrequency( INT no )
$ X) R1 Q0 ~( Z5 i: c{) o. v. Q; j* O" g, T& Y) z4 B
        if( !m_bMute[0] )7 e0 H' Y0 W1 c% J* t: I
                return        0;
& [( ~7 W( q7 a5 K! Y( V& v( ?) i, O! v3 u
        // Internal* R- A: U/ h( F4 }
        if( no < 5 ) {
+ u& j0 R! h  |/ s* L                return        m_bMute[no+1]?internal.GetFreq( no ):0;
/ B1 t2 i' O+ u# P2 Y        }2 y6 D: B. y! |) F" M6 T
        // VRC6
. n& T! |" v8 z4 S0 o# H6 }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {% A6 \$ L7 v. q2 d6 H! u. W7 r
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;2 U8 H9 E; X5 C/ _2 B
        }" l. R- ]8 _1 |- Y9 p; C" Q3 D& [
        // FDS0 K- o7 Y; a( T, f: [
        if( (exsound_select & 0x04) && no == 0x300 ) {
$ g$ y+ Q) Y9 g; K: P% B( ?  u                return        m_bMute[6]?fds.GetFreq( 0 ):0;
& _0 |. C8 G9 S1 _, r        }
2 }' d3 n& c% K0 @+ @  q' H, c        // MMC5
5 A( D: O0 V2 t0 R        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
% @+ G% E( f# Y                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;# w- k  n' n) J1 C$ ^
        }
5 n/ d3 ?. B& a        // N106
' |( b- ?; i# k* s" B        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
9 Y9 P# j9 c4 ~9 O" u: X                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
( ?. I+ d- q+ k- f4 X        }  |1 }. ^. m! Y* o8 q6 u7 B
        // FME79 |8 N2 y/ Q* `( {4 \& K
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {: C% y' \4 o$ {# O3 y: O
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
6 |6 Q9 v2 w, \# p        }4 @! h, o4 ]& z, B+ I
        // VRC7. ^2 q, W0 f% t$ j
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {. |4 c- w1 F6 B
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
* ~7 S) G& ]: |) W        }
4 m" q) v. E9 [( U        return        0;5 w+ }  ^* @% c% b  o. n% Z
}! T0 K  H- J0 t0 z) w# A: I5 j

( W$ E, M$ s  C, ^9 I3 w// State Save/Load
) \$ Q$ U7 j) B" A1 e; avoid        APU::SaveState( LPBYTE p )
' B4 B4 U4 }% Z( ~8 X( M{( B2 b8 }$ B( ?1 x, N/ Q
#ifdef        _DEBUG
5 }: {- `$ g  t1 j8 ~LPBYTE        pold = p;
. d9 d& ~# Q4 d8 \+ v+ F#endif& Z! {) Y4 |! Y. T
; u. S# t. I3 o; m2 w( Z
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 B% J' E4 a2 f9 |( |4 c% `+ C        QueueFlush();
& W2 _, T% V" A, Y- e! m' @- ~1 @  w5 ]- l# G
        internal.SaveState( p );+ |! `& {9 S7 P7 x4 a+ _1 B5 j- {
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% o, W6 N4 l+ n

8 r$ W5 c/ X. f9 e  c6 |4 o; i        // VRC6+ B$ ^( @" T1 C) f% c
        if( exsound_select & 0x01 ) {
8 T3 d+ O' j& q                vrc6.SaveState( p );! L$ K  L4 t  Q
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
/ \* J% r2 n5 o: z        }* f+ q! A2 w9 W, S
        // VRC7 (not support)
# u1 j4 w- g" ~0 u        if( exsound_select & 0x02 ) {
. X, m" I+ s' S! @: K9 R                vrc7.SaveState( p );
. K+ }2 u3 J' k                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( ?: d% _$ I0 h' l: v
        }
  s3 b' F2 t6 Q- f/ I        // FDS. c3 X$ n: H+ i3 w0 s
        if( exsound_select & 0x04 ) {* C9 f& [, F+ h$ G* `1 _
                fds.SaveState( p );
/ T% s2 a' }3 i8 J8 c" D2 M                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 x) e3 F* E) U2 U7 J! U
        }
  F, l! V1 Z5 b( y7 @        // MMC5* p- a  ]2 y) P) d" Q6 R
        if( exsound_select & 0x08 ) {
- B7 m. {+ p- z+ _3 o% a/ S; E. f                mmc5.SaveState( p );" r4 _& e- D: Y  X% L' ~
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) R0 g; S- E7 H# x# x1 z, ?        }' D# L+ R: K( Y2 @) c
        // N106
1 t( E7 a# F; v+ N+ K& W        if( exsound_select & 0x10 ) {
0 ^) t1 L4 B" W                n106.SaveState( p );
9 r/ l$ ?& ^5 r, Y3 Y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 H) \" I& S/ s( w3 c) k% n8 B8 G        }# Q9 k7 I5 D) b
        // FME7- e' ^: L% |& T3 b/ v& Z$ Q
        if( exsound_select & 0x20 ) {
4 B. T6 W/ c0 j1 C                fme7.SaveState( p );
' X0 \4 J5 g, f7 L) e+ [% q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" j  e8 y$ \; ~) S8 s        }# a: p% Y% m, w: Y

1 H# z+ t7 ?% x9 I' @. ~4 M#ifdef        _DEBUG
. {4 p' U+ v) M' ?( @2 N6 A4 TDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );% H4 M) |5 u0 Q
#endif7 i! t2 K+ J# i$ B
}
1 I6 v) l" c9 x2 M
+ `  ~5 ]/ A$ I8 M0 }void        APU::LoadState( LPBYTE p )
* ~2 ]2 k- m8 {0 C( I7 A* b3 ^; }{
, D" X1 i0 O) A        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& `( `2 b# w4 o/ W3 C  w
        QueueClear();
+ l) k4 w; a+ L' a& V3 X( Y9 e5 w+ |3 \$ W  x$ S$ M, o
        internal.LoadState( p );9 k/ v8 e/ h) J1 q6 G
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: n6 ~9 ^% f( h" w( h" Q, G
7 i) }1 c% J: k% M
        // VRC6
2 I0 A7 ^: l/ l# z; ~- r/ Q        if( exsound_select & 0x01 ) {6 k  a) E" n) _. C% Q
                vrc6.LoadState( p );6 B/ ~! l6 g& J/ |4 F/ T
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 T+ Z, |# m  F4 |2 {9 n: B" p
        }
" ?9 J6 {. x4 x, t/ ~" l        // VRC7 (not support)
4 Y/ M1 @  v  j, A3 z$ y        if( exsound_select & 0x02 ) {
4 J5 r  \6 s7 }0 X6 w                vrc7.LoadState( p );
) M: u3 _8 p* o. }, x                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 `6 ~( I$ H0 k# E5 r, A
        }
7 t( j7 F: }/ u* Y        // FDS1 d+ u; m$ B1 p' T
        if( exsound_select & 0x04 ) {
% ~  B1 I* M! X                fds.LoadState( p );1 ^  u- ?: }0 s  d, G
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% U) ]9 Z% C/ Y        }
- p! l) X5 _0 y" P4 @) _1 B& ?        // MMC5+ A" Z) j/ y( d. J7 u2 k, C
        if( exsound_select & 0x08 ) {+ v2 x% |+ I5 r3 }3 q% A
                mmc5.LoadState( p );3 z- U$ J2 f0 P' H& I8 g
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& Z: b  |& y2 H( t/ j8 Q        }, A2 ~+ t2 q% m5 o( W7 N2 g
        // N106
) L5 w& d. O1 i2 }. K, m( Z        if( exsound_select & 0x10 ) {
4 h8 v. b5 N+ O; I                n106.LoadState( p );: r" a: Q# F5 a. f* l
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' V- L+ @3 m# C3 w! a$ D        }
' N4 }) g, m8 I! \8 x* R3 C7 F        // FME7
* U. O4 G% {  o$ A) T0 K5 [        if( exsound_select & 0x20 ) {
7 @1 G3 I; D2 D                fme7.LoadState( p );# o7 I4 S* v' A' e9 P- b& d" H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: D! M8 m* E/ x- s4 H7 P        }: ]1 X- T% H1 B6 ]7 n
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
* |. A: v9 t0 ]可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。3 P0 f3 ]+ J- y; {
感激不尽~~

% f- O/ I9 A# F8 r恩 我對模擬器不是很有研究,: [1 }7 W$ l9 L5 K1 m) l
雖然要了解源碼內容,可能不是很困難,2 }* D( ~& F0 j" [9 D, d8 ^
不過還是要花時間,個人目前蠻忙碌的。
" g5 }% W1 d) L) j
% C5 ?3 }- |9 Q5 L* n0 J  u! J給你一個朋友的MSN,你可以跟他討論看看,/ p7 W; K4 X* o& U/ s
他本身是程式設計師,也對FC模擬器很有興趣。
( B% n8 [: C6 W# r$ S1 {
) u; H$ G5 J# NMSN我就PM到你的信箱了。, x5 v8 c) ~4 H" _  y

: k9 h4 ]/ R& V9 A# r希望你能有所得。

该用户从未签到

 楼主| 发表于 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- t6 e& Q' B+ |- t; ^
呵…… 谢过团长大人~~

/ x. A! q% D* y7 e7 S' ^; P: C. G1 ^; Y
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
" i  T, l1 V+ x8 e' V% A, ~团长的朋友都是神,那团长就是神的boss。
* c" X; ?- m5 N: h+ D
哈 不敢當,我只是個平凡人,1 r$ U/ H$ ^# w0 j
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙, E0 \9 ^! ]/ v6 n+ I8 G& F
ZYH
  p6 N* e+ H" |) o4 r8 qQQ:4147343061 d* {1 h, |/ R* G6 R/ `
Mail:zyh-01@126.com/ ?5 k0 W# A; Z7 B7 F' t

; u# v+ }2 c* ]+ Z. q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) H1 H8 l, u! l1 ^2 D+ m再次对团长大人和悠悠哥的无私帮助表示感谢~~
9 r" c4 x6 m$ B: a
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-7 04:35 , Processed in 1.089844 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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