EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。' t+ l+ c$ q. P1 H
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~8 O) h5 X3 {- V9 y: j- f3 @' r
这里有相应的模拟器源码,就当送给大侠了~~
# J0 r/ T* a" j; m* w. n0 Z& Hhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 j. U" A) U7 y/ E
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! n6 l3 S+ G% f! j  @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; n. X4 N" ?, |这里有相应的模拟器源码,就当送给大侠 ...
! D3 `$ l. N2 M# a6 f, ^$ D+ s
聲音部分(Audoi Process Unit = APU):9 [6 m5 Y1 f; v% Q) O
.\NES\APU.cpp( N9 m7 k$ @# T# }: A) [
.\NES\APU.h
: {: Q4 Z+ N6 z" z- E( @( g1 g! T) j8 f" v
! c& o4 n; |' i' _' a" x+ _. y
影像處理部份(Picture Processing Unit = PPU):: y- L) {/ c& P2 m7 \% y) z2 y4 K( ]
.\NES\PPU.cpp; K9 S5 i; }9 v# L. o: B% i
.\NES\PPU.h( i' D6 ?3 W. O9 y  H7 E
$ h2 d$ ~9 W+ X  r
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# y. l, w+ S) D# P9 U0 {: M! Y) n6 y( C
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  p7 x7 n. N# F2 n
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
- R& K* s$ q8 B//////////////////////////////////////////////////////////////////////////
! y# @3 l8 g6 Q! I//                                                                      //' o! Z" Z7 ]! I8 j4 x4 J
//      NES APU core                                                    //
4 a; w4 |' `6 D, `//                                                           Norix      //
# _3 t% Y, j1 K' A( U//                                               written     2002/06/27 //# _8 C. V- c! Y
//                                               last modify ----/--/-- //2 c0 [; A: l. x8 t1 o( ]
//////////////////////////////////////////////////////////////////////////1 Q( g; {8 C( v$ L: S2 q
#include "DebugOut.h": M" S- B% B# B
#include "App.h"
6 @# q$ x: X6 q% a+ v#include "Config.h"3 T1 c( e' a" \

( [6 n* V5 c3 V6 G! W8 L% u#include "nes.h"
7 y5 y* V1 |) w* K#include "mmu.h"
3 e3 C( q& t9 s: Q6 B3 ^) r6 `8 k  d#include "cpu.h"* Q/ R# Y4 P" j8 s4 N: K* M
#include "ppu.h"
: }- o0 z3 U3 x2 [+ E; n#include "rom.h"
& Z1 L+ ^% m( X#include "apu.h"
( v8 [& B+ [' a+ E; F: q: Y9 i! C2 e( M  p
// Volume adjust
: @4 S# S" `+ R7 B' T" E5 w" p7 d// Internal sounds
0 E* w- t, p. ]1 k- L) G#define        RECTANGLE_VOL        (0x0F0)
$ ~* b+ e% N8 p! n, H* Z+ `( b#define        TRIANGLE_VOL        (0x130)3 Q) R  E9 P# G) R8 H; L
#define        NOISE_VOL        (0x0C0)5 h  t$ Y: L: b, N1 y5 J3 V
#define        DPCM_VOL        (0x0F0)
# G! ?. J3 G8 D- X/ d// Extra sounds/ B3 p3 G7 f0 A' c. z5 @8 Y- I5 o
#define        VRC6_VOL        (0x0F0)
8 {8 r' A; B& u; r5 Z#define        VRC7_VOL        (0x130)1 Z2 U, \$ S7 c- Z; i- ]
#define        FDS_VOL                (0x0F0)! j" R, A- B( M0 }
#define        MMC5_VOL        (0x0F0)9 l4 C# t2 i( |4 P
#define        N106_VOL        (0x088)1 i( \. g' [( @4 B$ g% O
#define        FME7_VOL        (0x130)
  S/ @1 t5 J7 i7 p$ ~# C: V' o! b/ |8 u! c* b
APU::APU( NES* parent )+ z4 I4 Z% c$ V! [% j( Z
{
5 B8 D4 i" U* q, c9 W! Q        exsound_select = 0;
! k1 z1 V7 z/ p9 a8 z
1 w, G6 X3 Z. }5 A  t; U        nes = parent;
9 `" p) ?0 z( G" P: ~6 v5 v        internal.SetParent( parent );
& Z5 w( A3 E- G% M
9 K! I, B% `4 U% X; H        last_data = last_diff = 0;
+ Q& M2 W# j! l
- N0 s9 p  V+ V! m* v        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
! i; A! h6 S* E( i
: F4 b6 \( F/ R( u0 O3 X        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );, T; L# ]; V1 K. B
        ZEROMEMORY( &queue, sizeof(queue) );
7 v: D' E) h( J! P9 R        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ F! w. H% U8 e) |8 H2 Z" y1 ?

0 H# @) n/ N7 F7 f! q+ `        for( INT i = 0; i < 16; i++ ) {3 e: u0 E  |2 g4 B; K
                m_bMute = TRUE;
. t% q/ r$ W# E" U" \        }3 f7 ~3 s% f9 ?5 j- b( W6 z  G
}2 O2 w& }% J) ]  Q2 O

2 g# n& B3 d1 q* V1 f7 |APU::~APU()
) M" t* K! g* M% J; Z# ~9 y{
  o2 z9 W4 f# T$ R4 o: h}& R* ?9 H+ [1 O: d7 |! \- u

% ?. I( L0 H3 c" z* D1 {8 Avoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )! r- ^' N, }/ V$ z  c5 X' L
{8 m3 ]* h$ p2 a8 g# c4 \
        queue.data[queue.wrptr].time = writetime;2 [( s) U  B7 m1 ]- O
        queue.data[queue.wrptr].addr = addr;! E5 j/ k. \/ D- e3 Z2 s
        queue.data[queue.wrptr].data = data;$ a; N! A  b9 ?) p) V; L( x
        queue.wrptr++;$ W# [0 p5 R+ @7 l8 p
        queue.wrptr&=QUEUE_LENGTH-1;+ g5 }- H+ L, o5 M- ]: b  [0 `8 E
        if( queue.wrptr == queue.rdptr ) {( o( C# g, r5 X( c1 v
                DEBUGOUT( "queue overflow.\n" );
, n: v4 K4 Q, y; x+ \7 S% v3 h        }* k3 c0 i, f' J# L
}
; F0 ?9 H( s, n4 F0 H* f3 U/ t8 \" a  J5 l& ]) s, _
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
# L+ t( X* x0 w{* z* O7 X2 ~: a' K9 k
        if( queue.wrptr == queue.rdptr ) {
  x) m; i( T0 Z# d" }) h/ a0 x' ?                return        FALSE;, T( o# i7 K/ R: k( h" i
        }7 a+ W8 G& @! |: D3 |6 u+ u+ l
        if( queue.data[queue.rdptr].time <= writetime ) {
$ {  {! Z+ C; n2 d: O                ret = queue.data[queue.rdptr];  Q0 Z9 i- `" s" C/ |# U- z  L' ?
                queue.rdptr++;9 D+ k: i& n/ A9 c; d
                queue.rdptr&=QUEUE_LENGTH-1;
, e2 m+ B! K1 U* K. A                return        TRUE;
' W9 J- {4 ~% f; ?8 [        }
1 ]* `  L2 n# U) u1 F        return        FALSE;
! G' c- C( p0 j2 t- P" V9 p! `# v}5 e/ [. g# }9 c1 Q, a( b

8 U% ~: [5 E4 @; A! i# Zvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
5 c- T% x/ V+ n{' {( l# _* S* v3 L0 d
        exqueue.data[exqueue.wrptr].time = writetime;
4 W: X8 v3 U9 Z8 H. Y& s        exqueue.data[exqueue.wrptr].addr = addr;+ p! O# v1 Z) F$ _  M
        exqueue.data[exqueue.wrptr].data = data;
5 i% k. D8 l" K( M0 X4 ]) s) U        exqueue.wrptr++;3 e$ Z/ K6 ?, M- z: w% v5 H
        exqueue.wrptr&=QUEUE_LENGTH-1;
& V5 w. c2 C. d' j( Y8 \$ f+ N        if( exqueue.wrptr == exqueue.rdptr ) {% ?. |! n# m3 K4 D' G
                DEBUGOUT( "exqueue overflow.\n" );1 |+ w! z( N  x! @) ]' T9 T8 B
        }
- ?+ E2 |$ i9 {2 c1 n}6 S$ X3 S2 u7 L+ z* Y$ T
9 u& n' x! J9 _. t+ |3 [
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ V) o/ T3 N% d- a8 w{8 s& C$ N2 r) p) F5 V( n
        if( exqueue.wrptr == exqueue.rdptr ) {4 p8 n/ ?& i- _& k8 w- P3 c1 Z
                return        FALSE;
4 U: l: w4 Q7 ]# }" W% D        }
2 w: n. ^' a  ]/ y9 h. Q9 |3 f$ `        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# j3 J0 j. b+ y, K9 o
                ret = exqueue.data[exqueue.rdptr];
9 U  p% }, |( C9 h                exqueue.rdptr++;& I5 Y7 x5 ^# _8 t0 L
                exqueue.rdptr&=QUEUE_LENGTH-1;
0 j* q/ X/ F. o4 y7 p  C                return        TRUE;
0 F2 Z2 v) w+ c! x' J% V        }
9 Y; T& T5 u9 ^, H4 q        return        FALSE;
( H, x9 ?, a5 F; ~}# h3 a" U7 M+ w* |

/ `2 {0 @1 g  I. P+ Avoid        APU::QueueClear()
) v: S+ y6 o4 R' M( y: E{6 l4 c* \+ G6 n& Q8 O
        ZEROMEMORY( &queue, sizeof(queue) );
; k3 K4 ^' |1 i" Q: H/ N2 d        ZEROMEMORY( &exqueue, sizeof(exqueue) );% P2 K. T" @7 n
}# P0 [1 _; I1 d6 g

# R" q) x/ D/ i% B2 ^9 qvoid        APU::QueueFlush()
! f& i3 Y2 d3 z; D4 Q/ d* Z{: R( d* Q8 o, Z5 T
        while( queue.wrptr != queue.rdptr ) {+ A. J7 t  O* u* K! a! J6 h
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* F4 S4 m* @! g) w                queue.rdptr++;; h- P: B$ b/ i% c# Q% M/ D
                queue.rdptr&=QUEUE_LENGTH-1;4 Z5 p! m- @& n+ b6 v
        }
! y+ I$ t7 ?* k8 Q4 z  Z; n' J
        while( exqueue.wrptr != exqueue.rdptr ) {
3 S$ N+ s. i2 M0 ?4 `' b7 v+ J+ R, }                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
7 W$ w& _3 v' A+ M                exqueue.rdptr++;5 g5 ?5 W4 _& P# U
                exqueue.rdptr&=QUEUE_LENGTH-1;  D7 D5 D; M3 S( u! Z
        }# W9 @& Y' q. u1 [3 O
}
6 p7 u8 Z9 s: W/ L- H8 }* Q/ l8 k  n& |: l2 M" x5 R
void        APU::SoundSetup()1 B4 O# B, O  c* }
{
. E( b& ~( s( R# ~        FLOAT        fClock = nes->nescfg->CpuClock;
/ l. A3 p# M9 O% x* T/ K: ?        INT        nRate = (INT)Config.sound.nRate;7 w( U- x0 t% L9 ]
        internal.Setup( fClock, nRate );5 Q8 M, @' C) t7 S2 t
        vrc6.Setup( fClock, nRate );
- U6 w; R2 s9 n; s        vrc7.Setup( fClock, nRate );
4 o' z3 a& P/ _1 ~/ Z8 v# I1 m  \        mmc5.Setup( fClock, nRate );, @1 z* J, i# w; U+ e6 j" z
        fds.Setup ( fClock, nRate );
; i! j8 B, m5 t) l) U! f        n106.Setup( fClock, nRate );
4 k& h" d* G' D+ `' T2 b* h        fme7.Setup( fClock, nRate );; k0 p: T4 I8 }) `4 J% b% {" g
}
% d! r  G* A4 K  F( r& B
& E) E/ V1 `; o: F' x* U0 m- D( mvoid        APU::Reset()
  i$ r& O% b! P+ v1 L  e; `2 \7 k{9 Q, \/ u; H! T% D8 ?8 \
        ZEROMEMORY( &queue, sizeof(queue) );* A1 d8 ~0 h. `3 Y4 M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( Y" K# A+ p  [4 S' ?+ Y7 L) T, L

6 C2 Z% h% N+ {8 Z8 D        elapsed_time = 0;
) L: x" V: F9 E: v$ ^' `# f, D) n! F  R5 c
        FLOAT        fClock = nes->nescfg->CpuClock;
% b2 X" T4 M0 [% m, }( ]* K        INT        nRate = (INT)Config.sound.nRate;
& W5 t- L; t2 g* k        internal.Reset( fClock, nRate );5 E) [9 N1 }8 h, T4 i" Z; v  H
        vrc6.Reset( fClock, nRate );
# J6 n/ N2 J2 {) x+ h        vrc7.Reset( fClock, nRate );5 V( y5 M' w0 h$ |' v
        mmc5.Reset( fClock, nRate );8 X1 V! c% ?* W% u2 h
        fds.Reset ( fClock, nRate );. l( Y9 V0 e4 `3 N% c
        n106.Reset( fClock, nRate );
+ g/ k9 b) D: b" I* j7 J/ _8 D0 R" q) U8 g        fme7.Reset( fClock, nRate );5 G" l3 R2 I# E  \
4 x  m+ Y' ^2 O' ~4 h5 y
        SoundSetup();
" m# s% U4 m0 k& o2 }6 o1 `" r}- W5 Q5 W8 M3 d" g# F/ g& K5 h
9 ~+ l/ F! E9 k- O3 x
void        APU::SelectExSound( BYTE data ), x5 Z! L& O5 d8 s/ I3 |
{
) K, Q7 h- s* i2 ]. ?8 I/ v& H3 \        exsound_select = data;; Z% J& m" K  a- o2 F
}  G5 D) f! `5 ?0 g3 C! ~8 y
+ b" b0 o; i% q- G& u8 ^- n
BYTE        APU::Read( WORD addr )$ B; l8 ?9 `% _& F& ^+ P
{  p) l3 S! p% S6 Q& t
        return        internal.SyncRead( addr );
/ `% {! V! {) C; l7 s+ W/ X' z& O}
3 N# \" y* J% ?: H9 {8 t% b" X" @6 p
void        APU::Write( WORD addr, BYTE data )
" q" I4 l+ t1 e3 J9 D{
) [6 d$ a1 ^  U3 J7 K+ O/ o        // $4018偼VirtuaNES屌桳億乕僩
% d7 z& {" t* t" p        if( addr >= 0x4000 && addr <= 0x401F ) {9 R, M! b+ l" Q: V+ m1 F. t
                internal.SyncWrite( addr, data );. u; r( h6 Y2 I+ g) x0 a
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& I0 w$ m0 \! C8 }5 _* ^8 B9 G        }" w  ^( |2 W0 |7 v" }3 b" j+ s
}5 t* L& K8 G$ q8 V$ u1 E3 U

' S5 v9 V' V4 |, ?% L' \: v5 V) Z, [  oBYTE        APU::ExRead( WORD addr )
0 C% y3 D4 _- }{
/ G& `/ K. z2 a4 |& k% UBYTE        data = 0;, U5 M9 u. V  H! X! z  }# R% D' r7 x% O

. P5 ]6 ^' b- d2 i( d/ O1 }        if( exsound_select & 0x10 ) {- q  T9 F" s/ ~; I1 X# e( W" u4 u
                if( addr == 0x4800 ) {/ G4 B% ^$ z) E9 e! {, @; e
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
+ h9 F( l! d  y                }- Z( J! f2 D9 g- ~" v
        }
  t' c. K8 h2 r0 M( r1 o( E        if( exsound_select & 0x04 ) {* x% r( C. o1 d4 @
                if( addr >= 0x4040 && addr < 0x4100 ) {
9 W4 a! I( e  I/ q, K( z2 {: O                        data = fds.SyncRead( addr );2 x' d5 n1 e# K. m" Q& s/ Q" x- b
                }
- E# O' ~. s* t3 p        }9 I2 p# Y% C8 F# M6 W$ t1 F- c
        if( exsound_select & 0x08 ) {' h/ k9 }' D8 x  j' L4 Q3 h
                if( addr >= 0x5000 && addr <= 0x5015 ) {/ o0 K, O2 ]' e5 a
                        data = mmc5.SyncRead( addr );
7 R, }8 x1 r7 Q- L, B                }
5 u0 S2 n" P3 P1 I$ K8 T        }' M4 Z( J& [/ O! X' H$ S

* b9 O& |1 O+ K        return        data;
( c" }  o8 N, g9 t$ N}5 x; [( D1 d  Z3 G
. R' A8 e3 E' c2 Z% p6 g
void        APU::ExWrite( WORD addr, BYTE data )$ t' W! h6 z- A. A0 y6 @
{
  f# F8 l7 T) I. K$ S        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& Z/ \' D- s. q1 c% n" I
" ]" T+ r* K. v- F        if( exsound_select & 0x04 ) {0 \0 B+ i: P3 _) A2 c& i: _+ C5 Y
                if( addr >= 0x4040 && addr < 0x4100 ) {
" k9 E$ m( d- p$ r8 \                        fds.SyncWrite( addr, data );
& S2 @) L9 M& x3 @                }, N$ b# p) L7 b; t
        }# ^& C4 q* I' |
+ W% G" e8 A( R6 W" X. c
        if( exsound_select & 0x08 ) {
# N6 Y/ f, l/ M$ g# x% r" X- s- t- c3 F                if( addr >= 0x5000 && addr <= 0x5015 ) {
" s2 K, ?. X7 o  _( h                        mmc5.SyncWrite( addr, data );
- Y9 Y4 N' b( T0 D2 @: q                }
& l7 l, a$ Q* R# H% j8 L        }
9 j( w( ]7 D' A4 A$ U}4 r% g2 u- [5 i6 X
. c# x8 h6 O% c. j1 w4 b9 ]
void        APU::Sync()
( ]- X+ b+ v3 @$ A8 G{
$ A9 @& {. ?' S' g}
+ U' V- Z5 m8 D! u4 G. c1 b; s, u7 m0 C
void        APU::SyncDPCM( INT cycles )
: H- W( {4 n/ c7 e4 [5 V$ J{
* Q  z# {4 h# j# R' r- |        internal.Sync( cycles );
. x1 |% b. f5 w4 T) A( P0 M; u
        if( exsound_select & 0x04 ) {
5 K% j9 h2 c/ g( M" j$ \$ v                fds.Sync( cycles );
0 B9 [. v+ W$ B6 `9 L        }8 J: {" W7 `0 m1 I
        if( exsound_select & 0x08 ) {; n; A9 R8 v- o/ l% W! _; e/ ?
                mmc5.Sync( cycles );
! j9 h& e6 c. ?* f        }* D) ~9 r' M6 Z+ {5 r' P
}
; H( |% ^# y, P% b4 X9 C
6 O# v% x3 C& ^! zvoid        APU::WriteProcess( WORD addr, BYTE data )
+ `* a% d; ~" U) F% V, x3 h{" W( N' u# w$ r3 F) {: m' Z
        // $4018偼VirtuaNES屌桳億乕僩- ^8 @+ }2 V/ k/ l, k5 j8 t
        if( addr >= 0x4000 && addr <= 0x401F ) {0 N% P( _2 T# e& R
                internal.Write( addr, data );1 M% l7 f  C( u/ L; }
        }% d* I" P' N6 e/ W" x
}
( Q8 p0 Q4 e# o3 [8 p1 D
0 P& e5 e1 K" L9 q. R/ X, W4 yvoid        APU::WriteExProcess( WORD addr, BYTE data )! e& L$ x3 Q! k. t& \8 X) \
{
# \: }: ^$ x' h4 _0 t6 w/ v        if( exsound_select & 0x01 ) {
  h! ~- ^5 o5 l7 O, X                vrc6.Write( addr, data );
! L0 S3 }' c7 i( e        }
) q9 i- S* e' s2 L( N        if( exsound_select & 0x02 ) {! d% L7 P, N" f9 n& N
                vrc7.Write( addr, data );  ^2 T* B5 _; n1 ]- R
        }( a5 `( B2 H8 `3 }2 N5 K7 L
        if( exsound_select & 0x04 ) {
& |0 A7 e* T- P# I7 g4 M* Y5 K                fds.Write( addr, data );6 _9 w. \) F1 g) l. G
        }
1 s7 Z, A( G* Y+ g  R0 ?        if( exsound_select & 0x08 ) {
9 R$ L8 u6 U. b/ I) Q* g( p                mmc5.Write( addr, data );+ h8 c. B$ P# r0 ?* u3 J9 B
        }% ?7 z8 m% v& Z
        if( exsound_select & 0x10 ) {
) y$ X  p2 c0 S) U* d0 H* z8 y                if( addr == 0x0000 ) {& j7 t1 V2 O+ q9 u& O
                        BYTE        dummy = n106.Read( addr );" q9 W, X3 ^6 y1 J
                } else {
+ _7 ~1 I1 U# _' o+ q1 J                        n106.Write( addr, data );
/ E/ k: Z* z8 z$ J% s: x                }! L$ _8 j% V! d
        }
; h/ A% o3 p5 w# w- e9 j) @/ c; ?        if( exsound_select & 0x20 ) {0 z" @2 K5 R2 {6 k4 ]' k
                fme7.Write( addr, data );
* b9 T5 k3 E+ _  O) z+ R! E4 s        }" P# S4 p! e% D# U  F2 e; P
}% K/ y3 [  ], n7 d/ Q1 K" P% b/ s

* w/ D# F7 G  ?void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), y! |. j, z- k) _1 V: N
{
) x/ ~$ ?0 X1 ]9 g9 G' {- FINT        nBits = Config.sound.nBits;/ p/ R( u, C$ L8 z) h' G2 L
DWORD        dwLength = dwSize / (nBits/8);) D; n1 ?! R& c7 y1 @8 a1 D
INT        output;2 y* X, b+ l% U+ f- L
QUEUEDATA q;; p/ u. a0 F* m; `
DWORD        writetime;
) i+ S4 F  r- e. `4 Q0 }
7 ~/ E- G2 R. }LPSHORT        pSoundBuf = m_SoundBuffer;
- M- s/ J2 S. _, Z- o+ T) k3 C2 uINT        nCcount = 0;7 d7 X, m& M: D" s. U  Q+ W

5 w& m) P3 p. |7 L% aINT        nFilterType = Config.sound.nFilterType;9 U8 L0 m& A. l# d9 B

+ l0 b- F/ j  j6 i6 l+ q6 ]& f        if( !Config.sound.bEnable ) {. \* O6 X8 ~/ S
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
0 T$ T8 g0 |8 s$ b  a% Y/ n                return;: q! Q6 `) {# z' j( B1 `, k4 O
        }
1 J+ x/ _6 e( r) P4 H" k
" W  i" N0 R( F" j9 R$ ]        // Volume setup
, U$ ^0 T) l4 U! W4 E        //  0:Master
7 J# ~, ^& l7 g) K6 P( F  J0 [        //  1:Rectangle 11 Y1 N# Y) k2 {* h, P2 @. l5 u
        //  2:Rectangle 27 q) T: v/ T: v1 M* e
        //  3:Triangle
/ R2 S$ W2 x4 v        //  4:Noise
, c& u1 P( o; [9 {$ M' C        //  5:DPCM& G0 W6 X/ y; S; _2 {+ o) ^
        //  6:VRC6- R& o, I  K. ?
        //  7:VRC7) u' {5 ~5 `5 r) y
        //  8:FDS) j* t* A" o* g" u
        //  9:MMC5% c/ C, f: I( d* C# @5 ~, K  R8 f
        // 10:N106( f1 c+ o6 S# }9 i6 \4 ?4 T5 t
        // 11:FME7
! {" r& D2 e  i( I' j        INT        vol[24];
. y7 i0 G& O8 v) l+ R- j3 h: f$ O9 j        BOOL*        bMute = m_bMute;
0 x. Q  l* T- T% i        SHORT*        nVolume = Config.sound.nVolume;( \3 k: h- _6 |- J
5 ~, p5 F/ C5 K8 |" O- @
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;6 Y! C9 H/ O2 a: k- A6 z" U
+ d2 s! V1 o+ _% i" D
        // Internal, G3 i% K1 ^! @7 w
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& Q( W$ K' d5 V& |. A; B
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
' i! s0 g$ c5 z. t5 p% E) [8 U        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 F! y) Z6 S+ [7 [+ P( m
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 ~, \  ?: b, T4 S4 `        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;: h5 x3 u* O4 h% p; D' `# P

8 N8 Q' M3 l- n        // VRC6. ?/ i6 e  Y9 {
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. \7 U' @% O8 m. B. D/ b) V+ _        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, |4 s( r- [$ r, w1 {
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- P) I9 H! @, \3 g
$ L9 Q) N  z* X" I  p; E1 c. R- h        // VRC74 l- f* Q; l- V# n# r% s* d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( e# P% J& o0 ~& U* @4 Y5 v

2 B6 f2 C  H! U        // FDS
, ]+ R6 z& k' b9 A5 i! F) O+ Q, R  Q        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
. x- t5 g8 O$ B+ K% O# Q0 ?4 S3 f# T# }# M7 P4 H
        // MMC5* w$ M% i% h( e
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: p, f& J% h+ D2 T, V+ [- Z  u
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ I- f. U" {+ t5 a5 |
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 ^1 H/ X3 G% {; V8 l6 d2 ^  n9 J/ u* m1 A- a+ c! m
        // N106
: K! p! w4 ]& V        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& M( M$ R4 X( _, {9 |        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 o. z( [/ B# {# O( r$ p        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 F, `' U5 H; k' b! C/ R' G
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 [  S2 G4 [" Y7 r$ A
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. F" ]& I9 r& z1 |
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. J$ e: y9 \8 s
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 t* E2 ?) e! R. Y- [+ c8 @
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 x( A+ v0 D0 F8 f3 g( n' l3 n! w- i( ]& N: Z) v
        // FME7' t; S0 h: S" T' Y
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  m" C( B1 I" a# \: V        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- E9 }- A/ _- j, d% Q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. Y+ P3 ^+ ]7 U8 c8 p+ z" d4 p9 i0 {  n0 k- n
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
. H' a3 B7 ~# i( a  `8 Q        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
( @& [9 e) L& N9 _/ t3 _$ p5 M; M! b
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
, B# R* q, H( P, I' `* @5 \        if( elapsed_time > nes->cpu->GetTotalCycles() ) {7 i9 s) M( ?$ Q. f: {
                QueueFlush();
2 F& T" }, Y4 R% {7 ^        }! y7 Y7 x5 u: |" H
3 N" I: I, a! O( R& q$ ^
        while( dwLength-- ) {3 v5 }8 u( k- x% A% s) a
                writetime = (DWORD)elapsed_time;
! o" T+ d' L9 \; k: V7 I
: a  e* Q' X& @+ R- @' \4 Q9 N6 k0 i6 Q                while( GetQueue( writetime, q ) ) {+ @4 Y8 V  s8 C) L
                        WriteProcess( q.addr, q.data );
. q( J) ]. q1 `1 x7 M                }! `( M/ ^( J  g' C( J
( ~; J. S6 E$ f1 e7 }9 e9 ^2 @/ O. j
                while( GetExQueue( writetime, q ) ) {
0 h- K' c9 n: Z2 c5 N2 Y                        WriteExProcess( q.addr, q.data );
9 Q5 w2 ]* e$ T. J                }$ \7 p$ ~5 D/ y5 r* A% H
# M7 g" c4 l0 S( P# I) }6 o
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
1 V9 k4 @' Y- I                output = 0;
2 P/ i- Q/ M8 m6 y/ p  h! }2 e                output += internal.Process( 0 )*vol[0];& }  `# C% O& S: N
                output += internal.Process( 1 )*vol[1];
5 A1 R3 `( F1 ~1 |% ]4 y5 g                output += internal.Process( 2 )*vol[2];. ]' E; k% T' O5 ?' t
                output += internal.Process( 3 )*vol[3];1 p- R. a$ a8 x( a/ r( P
                output += internal.Process( 4 )*vol[4];
$ b8 L, O1 {" G# j( t3 I* x9 u; _
; f) E( I, v1 S  M! F, X                if( exsound_select & 0x01 ) {& C5 B" \$ ?3 N
                        output += vrc6.Process( 0 )*vol[5];
' ?7 @( E" c# O                        output += vrc6.Process( 1 )*vol[6];! ]5 A2 l) y* G* c4 g1 ^4 c
                        output += vrc6.Process( 2 )*vol[7];. U# Q( ?- u8 q, x9 u2 N
                }% w! n# l) Z9 u- @( Q" O% u/ t
                if( exsound_select & 0x02 ) {
) Q* d; [! ^. [                        output += vrc7.Process( 0 )*vol[8];
# D$ b* L4 j3 y* d2 p) w% `0 s& p$ ^                }! ?8 C  T: y9 {, o- E0 z" m
                if( exsound_select & 0x04 ) {; R* h0 p. f8 t2 d# v+ ^
                        output += fds.Process( 0 )*vol[9];
: G. H1 I' v, H7 l( s6 l                }0 b* H) [: ?! j, G8 p
                if( exsound_select & 0x08 ) {) `4 p3 x  s: W8 i; w) g$ l
                        output += mmc5.Process( 0 )*vol[10];' K, ^. P5 F3 U  S
                        output += mmc5.Process( 1 )*vol[11];/ [$ j: y7 e8 d2 \. d
                        output += mmc5.Process( 2 )*vol[12];6 O8 A& P5 Z6 k* c( A
                }8 C5 V. b, `* z  h* v
                if( exsound_select & 0x10 ) {3 A1 @2 b6 r; U0 J. R, n" a3 r
                        output += n106.Process( 0 )*vol[13];
  d% P' y  d9 X! p( m& O. J, Q* U                        output += n106.Process( 1 )*vol[14];
# ]% H3 p( ]1 V) o! Y- j0 ~4 x                        output += n106.Process( 2 )*vol[15];
1 J- s2 `* x$ _9 ]) B                        output += n106.Process( 3 )*vol[16];; I4 Z/ j5 v* F# p
                        output += n106.Process( 4 )*vol[17];
- x* G0 F  X/ T. ?: f/ C5 j0 P6 ~                        output += n106.Process( 5 )*vol[18];
, g  I, \4 i/ g3 l) G                        output += n106.Process( 6 )*vol[19];9 `% }2 G" q. G" X
                        output += n106.Process( 7 )*vol[20];% y& j: G5 B' U
                }5 y5 N- U! J6 B3 E5 E; {7 G3 A; [
                if( exsound_select & 0x20 ) {
" N8 W) I* [# m: m                        fme7.Process( 3 );        // Envelope & Noise0 A0 l  j7 g! q- j, ?) B/ v' h
                        output += fme7.Process( 0 )*vol[21];
& I  Z) D. K: V5 R& h                        output += fme7.Process( 1 )*vol[22];
6 w$ d! n$ R& G% n+ F  g3 s                        output += fme7.Process( 2 )*vol[23];+ Q- E' V. {8 O; J
                }
5 l5 j- d2 H1 d' {5 b
  k- Q" U# N7 f% @- t8 ^% J                output >>= 8;
; V! e+ `6 Q, r+ L
9 O, s& [4 k& a: c                if( nFilterType == 1 ) {1 v5 z; Z) U; s2 K) j
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: _9 j4 p8 U+ v1 b# X( M                        output = (lowpass_filter[0]+output)/2;
5 Z" S; @# Q6 g, w                        lowpass_filter[0] = output;8 ]  K5 T" d2 z' x8 v. r
                } else if( nFilterType == 2 ) {9 s& d- G/ }1 l
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 d$ r. Y, V$ v2 K* j" R4 X                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
. R  J9 o$ u) r3 X& }# L$ T                        lowpass_filter[1] = lowpass_filter[0];
3 H# n7 y- S; q1 ^6 f$ X" u( `& K                        lowpass_filter[0] = output;3 d1 k# u& t' J8 D2 A8 R$ o0 e) J
                } else if( nFilterType == 3 ) {
. ?8 D6 ~& p9 P; c& F4 {% X) F/ G2 Q                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)( `) k& u, i6 c  h
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;; O* r  @2 e7 @+ L; b
                        lowpass_filter[2] = lowpass_filter[1];
3 v9 u6 s/ i* J" X/ P* G) O! D1 ^                        lowpass_filter[1] = lowpass_filter[0];
- v* C. o9 \3 X+ S& z) D                        lowpass_filter[0] = output;4 I1 ^9 `  t1 }( u# B( [) N  }3 d
                } else if( nFilterType == 4 ) {
( T: M, \" s8 H8 x/ C! t                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
( }7 K# b2 y* z! [                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
" p/ V( Z" L# d5 C& q                        lowpass_filter[1] = lowpass_filter[0];
* ]% S' t4 }. ?) x8 U7 ?                        lowpass_filter[0] = output;
; B* ]) }, Q- I* S$ m' j                }0 b& }% W& X- z! M/ @
) s8 }2 u, q5 i$ H5 }& A7 o9 i
#if        02 x9 Q! I, G, L7 K: ^( X7 P0 m6 f5 Z
                // DC惉暘偺僇僢僩7 Z+ e/ q, o5 R1 M6 L5 C
                {
9 \; [$ E/ ]; \1 P: b* A) g                static double ave = 0.0, max=0.0, min=0.0;
3 I- e" Z  E" R9 ~" t$ J9 T8 ~$ ]- I- B                double delta;* X8 i# u/ C" E% d: N( v
                delta = (max-min)/32768.0;
- B7 t, p+ J  o0 z                max -= delta;
6 v3 `- i- @0 s9 Z1 i                min += delta;& Y; x. H# |8 ?- V2 h- {  y4 B5 C( q
                if( output > max ) max = output;
% s7 t+ \/ k1 N- T) Z( D                if( output < min ) min = output;
3 @: s5 H' h6 l  O# i- E                ave -= ave/1024.0;0 b5 e8 d7 D2 k' x
                ave += (max+min)/2048.0;
/ P* _' g% r& X6 R                output -= (INT)ave;' W% ~0 y: u, D! @+ A
                }4 K( w8 q+ l! A+ X  q$ H* M% j
#endif
1 v" j' t7 I  k, c; h6 G- Z0 ~* T#if        1
2 J% V5 y  j0 N' n                // DC惉暘偺僇僢僩(HPF TEST)9 z. p/ H' B" Q3 G
                {
+ H( {/ t. z* z7 F0 B) J//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 W# [' j3 o) P! p: M- Q                static        double        cutofftemp = (2.0*3.141592653579*40.0);% u7 o3 v8 S, B( e: V6 b6 A# \
                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ N  |! V9 J% u! a+ U1 [9 G- `6 Z
                static        double        tmp = 0.0;
/ T, X: I7 v4 z! n$ ]                double        in, out;' C( `  O. M: y
* @0 C& p8 p# w3 B  Q
                in = (double)output;
" |0 m3 M& K4 @8 s- L8 Q                out = (in - tmp);
/ V2 ?1 Z& C1 A, O- G- B                tmp = tmp + cutoff * out;
$ i3 `9 N) I* C9 ^2 m' L* k
6 _. v2 V! N, B/ s                output = (INT)out;5 S" U" K) h. K& u" d2 j
                }4 t- f2 j4 I/ h4 S
#endif
* t( X( n+ B" ~6 V#if        0* K* a- d& ?& \& V& H# d
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ X- S& _$ U! d$ e" E                {0 O9 E" b* w9 {
                INT        diff = abs(output-last_data);
% y% g3 v5 l3 E2 e. \  ?                if( diff > 0x4000 ) {
" b4 }, Q% i( Y# ]' E8 w                        output /= 4;+ h( p6 |/ D& }0 ~( M! H) }$ g! Y
                } else ' r) |* q& x* B. X1 B
                if( diff > 0x3000 ) {  F0 X0 H% Y6 y" C
                        output /= 3;
; a# o6 B& d, y  I) z% N. g' L                } else
- L  I' X0 C% Y2 J& u9 H/ ]                if( diff > 0x2000 ) {
* s) l, t, J. s6 L$ K                        output /= 2;; X! g$ _* E5 b# ~
                }
5 ]4 ^: L( Y  ]                last_data = output;
/ B1 Y  O- ?' a: X( p                }
" Y7 n5 G$ I4 h) U: B0 l#endif% h6 Y4 @3 r4 J
                // Limit
; O& D  ]( L$ T& l6 k8 {                if( output > 0x7FFF ) {% t+ _- X3 _0 {9 b2 W3 n- I8 e
                        output = 0x7FFF;
1 }1 J3 z5 e9 r( J  i                } else if( output < -0x8000 ) {' o5 W- [2 S) h* _/ }3 b, H% u$ Y. E
                        output = -0x8000;+ J) h! B& ?; a  w
                }0 [  s# Q- W: w9 p4 w1 d

$ M( r/ p# {, a                if( nBits != 8 ) {
/ |9 P3 a' u% I2 o6 y) v& Y                        *(SHORT*)lpBuffer = (SHORT)output;. U, D, v0 `1 X6 K' F5 t5 U( L
                        lpBuffer += sizeof(SHORT);& B2 e% e% b  s6 l" g* g1 r5 p
                } else {) m$ B% W) Z1 `" |$ ~# r1 ]' l
                        *lpBuffer++ = (output>>8)^0x80;
( V3 f# `' e( p. }                }8 q# Q' s# A' ^8 S7 y: g$ ?

) o! |3 i( d3 K  w                if( nCcount < 0x0100 )
9 N* T9 f2 o3 v! I/ R                        pSoundBuf[nCcount++] = (SHORT)output;0 u$ _3 A1 b3 ]9 g! a, A% N
4 l- b. J+ Q. o9 O  Z3 B4 k5 p
//                elapsedtime += cycle_rate;
. m2 z( c, G1 W; A                elapsed_time += cycle_rate;
, K9 [3 {4 u! B% j, o        }3 _& {7 `6 V% Q# z0 A. P
  A: N; l! q7 x
#if        19 l7 w& I& D( _3 D4 a: T; w; V
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ ]$ T4 R4 L6 }0 g2 p# p0 X0 M7 D
                elapsed_time = nes->cpu->GetTotalCycles();) _7 I( E! P0 L9 U5 P
        }
" A3 \6 u6 A# y( r; K7 b2 f7 S) n8 e        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
$ s+ m/ F" ?! I- Y5 L! ~                elapsed_time = nes->cpu->GetTotalCycles();, ^7 h! r+ j$ f2 j, `/ R
        }3 j6 b% Q! ?9 K! e
#else
# C& `2 ~' q" F8 G( O/ n: P7 w        elapsed_time = nes->cpu->GetTotalCycles();
! H! H( R$ Y: V0 c0 @, l#endif4 L  F6 {& j1 P" n9 S* B/ p
}  N& i/ J! U$ K4 ~- x
& _  o/ G3 [: q$ W4 S% ?  n
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
$ m; Y/ \0 V5 G2 w- W% OINT        APU::GetChannelFrequency( INT no ), l5 J. K, z8 c3 \( S7 w
{
, P# P1 x6 L' e' w4 t3 c( y        if( !m_bMute[0] )' `2 S6 t+ g0 a+ @; ^
                return        0;
$ ]) m! N6 I7 \3 a: w% x
4 k3 o; X+ \, M* u4 T        // Internal3 N; v  Y* i5 [6 S. z6 }3 Q
        if( no < 5 ) {
; Z+ D% E( Z) V$ W0 x- |                return        m_bMute[no+1]?internal.GetFreq( no ):0;
" o9 w" A# e$ \8 l  \        }' o0 C) f' `' T3 P  ?
        // VRC6
, u9 |# l* Q7 v: G& j; P' V        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ Q; p/ Y- z1 h9 u0 W6 o9 ^                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
: Q- b- W5 ^% U# c' \. s$ f        }
. v2 E3 o; W& h* s        // FDS
. U4 ?0 L$ d) [/ x* X) a7 G3 K        if( (exsound_select & 0x04) && no == 0x300 ) {
& U8 E7 X% c1 C0 `" \- H1 {' s                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 y" j: t( B; G# P5 ^8 n/ O) v1 w
        }
& }6 G+ i6 o0 X) n( o        // MMC5+ Y* K1 ]( R- u- a3 P$ z, p# j
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
2 C7 c8 e) ?; D                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
) c9 T. D8 o$ z  Z) Q8 Z* e        }  X' c+ f( x* E1 ~2 |0 o- M+ ]( e
        // N106) \6 r0 b$ f3 m  E2 s5 ?
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {. z1 p3 Z* }6 N+ t& a
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;2 A# U" N) u7 C8 ~7 T1 Q: N, Q
        }
6 N! B+ D: j6 ^: T  ^        // FME7. J0 ?% k8 v, M+ @
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {5 ?# q4 U* a0 G# r
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
8 v: E7 u. R! p+ s: |" z3 z" f        }
) C& r8 d# [- a& U2 o2 ?) B        // VRC7
8 B, P8 B. x8 t+ V% W        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 Q0 {  ^' w$ h: G7 Z0 z0 C6 @                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 h$ x6 O. ~8 F4 ?        }3 W. K  j" P% v1 R  w2 H
        return        0;
- `7 j: p3 N8 u! k8 s8 G}
$ P* s" W+ J* f  {  }- O- s: W1 W" l# l/ h
// State Save/Load5 F8 N9 ?/ j. q6 w$ N. N' w, q
void        APU::SaveState( LPBYTE p )/ z7 r4 L* l5 ?. c5 L5 u( E5 ?
{
; z# S- Z' ]" H! K# q#ifdef        _DEBUG* O  }, J# O  H0 Z
LPBYTE        pold = p;
: r1 K# i# S3 q1 W- ~8 E* [, v#endif, I7 R( O& B* H# N5 B5 ?9 X
6 E3 v+ T( C0 I% s; Q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* B; u; Z3 k2 H' S! ^' F$ s        QueueFlush();
+ b/ c1 s8 m5 j% `2 Q  x
, X" V# T( l% \0 `        internal.SaveState( p );
3 u( t" W9 i/ l$ _        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding# q, k- U% E2 [- R' G# r% e& _6 \1 {
) d! K6 Z$ ~0 Z7 r  `
        // VRC6
, H. O4 R5 ^" K' T! M. \6 ?  T        if( exsound_select & 0x01 ) {; I! I# J. J$ b, z4 e
                vrc6.SaveState( p );4 T* p9 Y) Q8 Z7 g9 J8 @9 C6 {
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ m+ e1 ?! ^2 H9 B: t        }$ z( b" E& W* |5 e
        // VRC7 (not support)$ m! ?) s: Y/ F  U" ^& k7 O+ V8 h
        if( exsound_select & 0x02 ) {0 [$ @, O- A% D+ w
                vrc7.SaveState( p );
+ o% L; x. f9 H2 ^. g# L) `                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- x: T; f. T1 I7 G        }7 {1 T* h3 J( K4 }
        // FDS
" N3 w. M: [" x8 M  A        if( exsound_select & 0x04 ) {# ]' T, j4 P2 Z* X0 b
                fds.SaveState( p );0 @2 x' o5 i! f* k* p
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 W- D- m- l' V6 s
        }
8 c  R5 z, z$ H4 v/ `        // MMC5
! G: ^( t; ]9 S        if( exsound_select & 0x08 ) {! O+ O" j! z" h: Y" N: U$ c
                mmc5.SaveState( p );8 z3 J8 L4 F( H2 K% Y
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
9 t3 U1 w" O8 ^( x1 D4 r        }
/ r5 E" r" g3 }/ n! l        // N106
4 ?+ K5 E/ r2 I2 T' h0 S        if( exsound_select & 0x10 ) {
' W. m: P4 D. `; G  T1 |9 V                n106.SaveState( p );! y. @6 @0 R1 D( }( k2 y
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
0 k1 s% O' Y. I! c* y        }
' d8 u1 M& Q) z. F        // FME7" U8 ~0 N( z2 u; U8 p
        if( exsound_select & 0x20 ) {
' E7 f# H* @1 D+ I2 u1 q& B                fme7.SaveState( p );
$ O7 Z  v( }" A. D- W' N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- m0 t. M7 v, w5 L! m* \  `        }
; f# b; h' d" m" J6 M, ^6 c0 a2 @" }; K8 G  n' ^/ K0 P- g- V
#ifdef        _DEBUG: k! X  [- X. R( I! j$ O
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! n6 b( ^  z' g$ x2 o. V#endif
) ^/ i$ d# k, |& W+ a: t* X}
( t6 V) E5 j: v7 N0 h/ U7 f$ s6 W6 P! \! {: P
void        APU::LoadState( LPBYTE p )" g2 {6 u6 C1 b# q1 J$ T
{0 O; z2 u2 `$ a# v* o  k: s
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
: H8 S. ?* c) g1 a        QueueClear();0 ?, e, n5 }( ^1 {* {- Q2 t
& E* x3 v4 r) R7 }! b
        internal.LoadState( p );
0 d) Q6 p3 h+ q/ Z) I' a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' v/ P% o" {( o8 {8 S! k& m4 r) D0 x" Q- W$ F; n7 u
        // VRC6
7 h' a7 V7 J1 k/ d  R        if( exsound_select & 0x01 ) {
+ V9 B( k3 z9 M1 Q+ D3 }& }                vrc6.LoadState( p );! P% t. @( B9 E
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, ?: H; @8 W2 f) W; M0 w
        }
* H$ Z7 [& f5 \- d0 [        // VRC7 (not support)
+ a; k/ i2 e2 S2 _1 D        if( exsound_select & 0x02 ) {
4 n! r; o4 X9 [                vrc7.LoadState( p );
# R4 ]6 v  T- p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. `# E3 {" H  T1 h4 A6 O        }7 R3 }$ q. S% o" B$ I  V
        // FDS
' W* ?8 w( [+ i4 W        if( exsound_select & 0x04 ) {
# Z, K' j5 P6 t. b5 O, G                fds.LoadState( p );$ w4 o! I4 z2 }2 c# A; N
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% u- t* X  ^# l5 |7 }. f$ M6 N: `
        }
$ v& d. }4 R" J0 _1 V        // MMC5; e( B9 J. S$ b, l/ B: O
        if( exsound_select & 0x08 ) {
* o0 T( E& d2 H, l. q- X! V                mmc5.LoadState( p );* E4 O. Q7 s$ B: I3 a. I7 N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 p5 a/ K+ Y" l2 |0 a$ j0 Y2 g        }
3 c% k$ }( ~& S) c        // N106
$ A; l' q+ Y& q" a1 A        if( exsound_select & 0x10 ) {7 D) X0 g* f/ I8 V$ o* v4 x$ |' r
                n106.LoadState( p );7 U1 S2 x. C8 l. P; f: F3 U7 O5 e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' }; l3 y  n6 W        }. {7 z1 g0 f8 w) |+ g% Z+ J
        // FME7" C1 `0 p8 E4 w7 I, u1 [5 l! @9 ]
        if( exsound_select & 0x20 ) {
# g9 G) y) e( v' A- r7 f                fme7.LoadState( p );; T/ o5 [& X! X7 |4 C4 N) U* ~
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding* l! J8 g5 e- k! m3 F& e
        }- B' g8 e/ I6 T9 F
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ' V! N7 V* G( W6 A2 b
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 E, x( i$ {) o2 J8 _感激不尽~~
5 h# p2 P8 D9 e2 Q& u# X' N
恩 我對模擬器不是很有研究,/ X6 }6 I- s1 \( f7 Q
雖然要了解源碼內容,可能不是很困難,
$ J9 @5 [  n4 G2 C. W2 `不過還是要花時間,個人目前蠻忙碌的。
; s/ f% ?; \2 l& P, P
9 x2 y7 _$ G- c1 \* k- h, ^5 v給你一個朋友的MSN,你可以跟他討論看看,
+ t' z( p: @/ `& T他本身是程式設計師,也對FC模擬器很有興趣。, X0 C3 J& Y6 Q5 f3 d

/ Z& M3 V! M- s, C: L- bMSN我就PM到你的信箱了。
5 `) h% f% x0 d3 |' @' n, Y2 F& E0 n# q& p& f
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ( _# o+ Y  {0 X  {. K+ G% Z
呵…… 谢过团长大人~~
8 r' f9 u1 s  w4 p

- P* w1 E  E5 Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# Z+ W- o2 ^: u团长的朋友都是神,那团长就是神的boss。
4 V! p$ l" F( j0 z& ?: R
哈 不敢當,我只是個平凡人," s9 p; b1 ?7 F: y' e* N) [$ O1 f
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙# H& \! _6 u: J" J$ t! Y; {
ZYH
6 }2 N; P% G* v. w1 E# L9 v4 l" v6 MQQ:414734306. T# R, I, E( B' ]& x
Mail:zyh-01@126.com6 X+ w( A1 K( M. N

! h! @% a: i" Y3 T1 M0 J) S/ V他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * r- H* C  ^# Q& [
再次对团长大人和悠悠哥的无私帮助表示感谢~~
6 j3 j. |; G- x
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-1 03:39 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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