EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
: D6 q" h/ A0 o6 \) Z2 @% \7 }PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' `& V8 P7 N3 V' f7 s- O楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  N+ G8 N6 k4 p$ Z( D3 ?" X8 }( X
这里有相应的模拟器源码,就当送给大侠了~~0 _0 {- l# _, r; Z! ~4 l! Y& C* l
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
: k1 c( b+ j6 _1 F: N+ U  j# t能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ a0 y. R, i1 _+ u% b楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* V! l# b7 {& v5 H* N这里有相应的模拟器源码,就当送给大侠 ...
8 g0 r: k: |. [+ r4 i
聲音部分(Audoi Process Unit = APU):
1 e* I8 Z8 ~- ?( d* z' p$ q' E.\NES\APU.cpp
$ e( D( Z- d! |& d% ?( Q+ T.\NES\APU.h
& d& ?5 G& `* Q  F4 K
+ N+ c: Z6 {) T' L# e
% }9 c  j, E5 n  f, k" P( p影像處理部份(Picture Processing Unit = PPU):
5 x. ?% r  S: T# z8 s, C0 Q0 p.\NES\PPU.cpp; j6 y) b' w# v+ Q2 b
.\NES\PPU.h
* `' W" q# x# X$ ^, E- n' v  d
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:9 W+ K  P2 w/ w- \5 a! C
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ g& {- Z9 h  F: H5 z8 X8 P5 j) t9 l. {
//////////////////////////////////////////////////////////////////////////7 W0 B9 e) ~6 Z4 Q
//                                                                      //+ q& J2 {( U# G7 m: G2 m; |
//      NES APU core                                                    //
9 n" \+ ~. A5 r. W1 S8 p3 O//                                                           Norix      //
1 P. T2 {3 i! H% J2 J- I9 ~//                                               written     2002/06/27 //
1 o/ l+ ^  i$ V& R3 I& G//                                               last modify ----/--/-- //
  V8 t) g, C7 J5 T$ f//////////////////////////////////////////////////////////////////////////- Q- Z# M: M8 A5 ~$ t# q8 Q: v% a
#include "DebugOut.h"! d6 m; w) Q5 ?9 u" F1 ^# o% F5 J
#include "App.h"
! J  ?5 I5 f+ R#include "Config.h"( Y9 j+ J% F3 T& A

2 X' L8 G: J* I3 w#include "nes.h"
+ v% n! L# H3 X9 d3 T#include "mmu.h"" y# E- {* n2 n1 q3 m
#include "cpu.h": q; c9 x/ _) i
#include "ppu.h"
+ \" N  C2 B7 G#include "rom.h"
6 \9 R7 c  p- E  T0 Y#include "apu.h"
3 ]% b: P% ]/ ?/ J- U8 \1 F( \& m  G0 u! l
// Volume adjust
& m' ^- v$ R2 Y  N. ]// Internal sounds8 E- m7 D: @- G4 w# e
#define        RECTANGLE_VOL        (0x0F0)& |; P4 J# c& K. {' O; ^
#define        TRIANGLE_VOL        (0x130)
, k$ q" P1 F* ?9 Z( \- J#define        NOISE_VOL        (0x0C0)
% j7 o" G% _3 c0 n- }/ j7 `#define        DPCM_VOL        (0x0F0)3 d# x5 R5 m" Q8 ]% ^4 H9 K
// Extra sounds
+ C) d5 z& E8 z! ~/ G0 C& y5 K8 `4 l' P#define        VRC6_VOL        (0x0F0)
; ?" i1 B& P5 _/ A0 X$ v% w#define        VRC7_VOL        (0x130)
! A* |, g- y7 x: ]1 u#define        FDS_VOL                (0x0F0)7 R5 A% s- _3 c7 I% x" I' V
#define        MMC5_VOL        (0x0F0)
  a( S, S$ g. ?: R5 O7 G#define        N106_VOL        (0x088)
- S  R- Y5 U" j  F#define        FME7_VOL        (0x130)
' g, t% a5 d% v9 v+ O) \
0 z& |' O! |7 \; A2 W: T* v# PAPU::APU( NES* parent )
9 C: G$ _+ N& U# V  F' G  D4 v{
# p9 d  u( @& L  n4 u+ L# o        exsound_select = 0;
, C( g6 ^( q6 s( Z. {
! X- j! C" K4 a! G9 V5 f) r9 [/ b        nes = parent;
3 E' @4 t/ c8 `" B% o/ q5 f" I4 X        internal.SetParent( parent );# o& W5 ?8 N$ O) i! c  u% P
! I- x+ ^; W5 z( [
        last_data = last_diff = 0;+ ~9 O, ]! `% V# U* M& v1 U0 _
8 M% V$ O' T$ ~" S+ K
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 [2 m4 [* Y1 M0 y! G: t! T

- N* h, V" ~# x* _  U9 u+ m        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );/ k& t1 V/ s) e, T0 Q2 j* `
        ZEROMEMORY( &queue, sizeof(queue) );$ i" `3 W" ~* w& F% B4 f
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 ]- K4 F5 D% V  I
3 i, E- e2 ?1 s) L0 p+ c
        for( INT i = 0; i < 16; i++ ) {- I7 D+ l- X( }( ^
                m_bMute = TRUE;: a9 f4 D5 R  F, o
        }4 ]2 b* _% m# N1 m) K
}
- k% a, _* g% m0 p3 r. @! s9 U$ Q$ S1 d, Z' Z6 m) ?
APU::~APU()
, ]5 U; R. A; f8 w2 u8 V6 y$ e{
) g, ^' n  {& e7 N: @}% e; r" Q% ~& ?4 y; @& ~$ V1 _

4 s5 j6 {' \- J5 f  Kvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
6 @* j) Z, o7 W6 s. w6 J6 Y* _{4 Z$ l$ Z# A- S( u. Y
        queue.data[queue.wrptr].time = writetime;9 m) ^- f- P1 z; t: B. `" U
        queue.data[queue.wrptr].addr = addr;
# t1 \4 y& |1 Q5 @        queue.data[queue.wrptr].data = data;+ Y' W5 o# a' ^- b3 h3 @
        queue.wrptr++;7 j0 O4 x% w5 q* i
        queue.wrptr&=QUEUE_LENGTH-1;
* N& N6 e2 L* J8 M$ W: `( n* V7 U        if( queue.wrptr == queue.rdptr ) {
( g2 x7 @7 q, S9 f0 d: |                DEBUGOUT( "queue overflow.\n" );
6 p' X9 x3 x2 q# G        }! b/ c  C% o4 m5 T% p& y
}
5 h6 T' h. q! l, z* Y7 A9 }" h  L9 Y7 d7 L9 P
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )$ E3 O% l) e, }5 k* R" A
{+ ?; F; A( D' w. K. U3 ~+ ?
        if( queue.wrptr == queue.rdptr ) {" t2 n4 I4 Q+ P, @! v: ^
                return        FALSE;
- I4 B" {0 h# w8 j        }
. \6 A1 p; I+ r9 i6 B2 [  H' \        if( queue.data[queue.rdptr].time <= writetime ) {
9 j1 e6 y  K- C% s, A                ret = queue.data[queue.rdptr];
$ `( o' j7 W6 p( Y# U. h                queue.rdptr++;
8 i9 I; h7 m" `  D( O                queue.rdptr&=QUEUE_LENGTH-1;
8 q& k$ n: I( `" W' }& k                return        TRUE;# X7 a# L2 g/ Z2 {/ c. B$ V
        }
$ [, Y; ^" |( T) l% T" T  ]5 z4 f        return        FALSE;, r+ U, R1 O- d! S
}
& t" o" J& I) F# ]" h9 R
% p; ]; R  d3 O6 Dvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ). R' P6 ?- u! b) M# o7 |# [5 p4 W
{
# T# K& p* ~4 a2 `# T        exqueue.data[exqueue.wrptr].time = writetime;6 i$ |( a1 L6 X" m
        exqueue.data[exqueue.wrptr].addr = addr;! q  p9 d' N$ S& H3 |
        exqueue.data[exqueue.wrptr].data = data;
+ A- ^8 r$ w) D- U( S) z3 _5 v' N        exqueue.wrptr++;
/ b- p! P9 ]8 w9 |! R1 y9 J        exqueue.wrptr&=QUEUE_LENGTH-1;
% d- i3 F3 C4 D2 _4 j6 Z/ O" {( ?        if( exqueue.wrptr == exqueue.rdptr ) {. Y9 N! {7 }; W" F$ ]
                DEBUGOUT( "exqueue overflow.\n" );
9 z' Y: a& c* c2 t( n- u+ l* L. W        }6 H4 Q* V' A9 `2 M, k2 @0 I  z
}
/ t' Q3 L/ j- ~0 f% T# b5 A5 ~, ~  |& ]: [* S5 b+ p
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! `5 k( s  R9 D{5 N) X' d* [: ^& O9 ]
        if( exqueue.wrptr == exqueue.rdptr ) {- D- \  s7 ^% h9 R1 ~* M
                return        FALSE;
2 S) ]6 g3 A  ]9 l, z1 H4 v        }" o  O& P1 X: X3 a. d9 X$ k
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {! M! [) T) m# s7 B8 r0 p
                ret = exqueue.data[exqueue.rdptr];
, O# x5 a$ [  U1 k4 M2 k7 d                exqueue.rdptr++;
0 a; L, N; w1 z9 W1 i! t- ?                exqueue.rdptr&=QUEUE_LENGTH-1;
( [# T$ Z3 N' I5 C                return        TRUE;# ~1 n) {9 J: A  ^, E3 v. p6 P; h
        }
# t8 T, ^0 l6 {        return        FALSE;6 n1 Z$ h3 r( W/ M
}- G# B8 T$ i0 b1 x3 `5 Z3 Q. ?% l

3 m; ~7 c5 W3 ?void        APU::QueueClear()
/ F6 v6 `, |9 S: V% t{8 a# ]  E& E/ M3 j3 j/ Q6 z
        ZEROMEMORY( &queue, sizeof(queue) );
% b* e& x: k- ~' L        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- F- S% |- l1 H/ K9 g}* M$ q2 o# w5 V. Z6 I* ^' `

/ z3 p& _6 o5 {$ `. h. Uvoid        APU::QueueFlush()
9 R; X& ^6 w$ W9 p  x  x{1 i5 T; o  U+ x- @0 ?
        while( queue.wrptr != queue.rdptr ) {
5 j8 V3 y1 q& L                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 I- J% A4 Z. H5 f6 c                queue.rdptr++;( W' I# _3 o# b. Y
                queue.rdptr&=QUEUE_LENGTH-1;
% z0 j! H0 F! O- C" I3 q        }/ m( H" c4 p. |: n1 q% M
; D& L) P2 \8 n5 K* [
        while( exqueue.wrptr != exqueue.rdptr ) {9 K6 {9 r  j# a0 b# d
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );! d: [" Q( S* w3 ]
                exqueue.rdptr++;0 r  u4 h) W' U
                exqueue.rdptr&=QUEUE_LENGTH-1;7 s2 {1 b+ [% ^7 c% W# d& l# C: ^
        }
  |  }6 \* e& n" r}
3 O2 a- N2 q' c& h
& f9 {8 P( C+ s/ b' o6 l3 zvoid        APU::SoundSetup()
  G. ]- ?* m& \) a4 T, e{
* c) ?$ F  }9 A/ C( @4 ~4 e        FLOAT        fClock = nes->nescfg->CpuClock;1 B1 x% M# A  z7 T1 u( u* z
        INT        nRate = (INT)Config.sound.nRate;
% `% \4 h- G+ h! I5 d        internal.Setup( fClock, nRate );6 {5 h* u! j( y5 X
        vrc6.Setup( fClock, nRate );
4 j& O& Y9 g! l! x7 y( f        vrc7.Setup( fClock, nRate );
( Z; X) r( J$ A" |: d2 J1 D  F- z/ g        mmc5.Setup( fClock, nRate );
: J% r7 h: K& D  |$ o/ C. j& l        fds.Setup ( fClock, nRate );
' s& ]. I8 m; A  ~' h: L        n106.Setup( fClock, nRate );1 [* N9 g# U7 x# a2 W8 v3 G
        fme7.Setup( fClock, nRate );3 B% J- V4 c% _4 g
}- k# ?' G* L! m
9 a8 I3 ]6 p- A2 h1 E. X& q
void        APU::Reset()
5 |: k" S9 E3 D; J5 T{1 O  c4 d2 B7 B  z4 x6 j' U
        ZEROMEMORY( &queue, sizeof(queue) );
  u% n4 h8 V8 _) K6 N7 o        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 ?6 I" i( q, f/ T3 H- J
$ \. G) Y# e# Y
        elapsed_time = 0;$ S: v% z* k& H( y

8 q/ C4 g+ u, u* t, c        FLOAT        fClock = nes->nescfg->CpuClock;4 D- F; T8 o" P; n
        INT        nRate = (INT)Config.sound.nRate;& M2 G8 E7 l( d( N
        internal.Reset( fClock, nRate );4 A& M" X* _" f! W* {& V& r
        vrc6.Reset( fClock, nRate );
5 d/ C8 e: Q" U6 _2 X% I        vrc7.Reset( fClock, nRate );9 D( c# r# V, q, c* k% W3 i- |
        mmc5.Reset( fClock, nRate );6 N! p' ]& F: P. _5 p* n
        fds.Reset ( fClock, nRate );( y4 y- t" ?7 K* @" c! [+ E
        n106.Reset( fClock, nRate );; m( \! n5 y# [0 ~; N0 s
        fme7.Reset( fClock, nRate );" h# @! F/ Z$ O. c
3 q$ U$ Q8 x8 Y; g. x. b2 a
        SoundSetup();% ?: C+ [) \3 J% L7 E6 n, k
}7 ]5 A6 g1 S  b* @( O5 L
% d. _  F; T1 j
void        APU::SelectExSound( BYTE data )
1 a! l* o! v! a- I. c: S{
/ u9 b  J! Y+ ]: [, {        exsound_select = data;
6 u. R& D3 X! B" a}- S( u3 y. O. a1 u8 ~
5 s2 M' ~% H6 l( q# U2 A/ ]5 R
BYTE        APU::Read( WORD addr )1 ^; O, G( K7 u5 ~+ r
{
; H- n8 s+ t  [5 X% H  g8 l        return        internal.SyncRead( addr );8 R6 P5 {- w/ C9 h
}& m+ z# ?* C- K7 B% Z0 K

) O/ `; F2 \; d! i" Y3 H4 Jvoid        APU::Write( WORD addr, BYTE data )3 j: d2 m; w' t$ a! z6 a4 D
{) Q# m8 z! `6 L! U; Y$ c/ `: v
        // $4018偼VirtuaNES屌桳億乕僩
* U: A& R: B! p+ g6 R5 d        if( addr >= 0x4000 && addr <= 0x401F ) {" S: f$ j; M0 Z& ~
                internal.SyncWrite( addr, data );+ N  t) Y/ E) `
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
, ~/ q5 n4 z, _% Z% g& T5 H        }% o5 A( W- U4 v" c. G0 p
}9 M9 {/ f4 p/ u
* l  N/ S! w) {$ y2 {# N! g  ~- v
BYTE        APU::ExRead( WORD addr )
2 }3 T/ h  Z# K9 i{
5 ^" m& U+ B. W, KBYTE        data = 0;2 s4 t* g. }7 e1 |% c. H
! [/ E4 @& d% d& k' a( ^3 _
        if( exsound_select & 0x10 ) {" c- |2 @, U8 I
                if( addr == 0x4800 ) {
5 H, e1 o1 s5 {4 g! b  c/ T                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );0 L2 k0 h; u/ ^( R) r4 \
                }
6 I# u3 N2 C; I& d3 m        }2 U' c. _) o2 \) w! F1 ^
        if( exsound_select & 0x04 ) {5 P& w+ d' e0 s: {$ \& s$ q
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 m. [4 {8 z# g  }: X7 V+ K0 I                        data = fds.SyncRead( addr );
9 T0 k+ T4 Q( X0 e' E- f& o4 s2 Y                }2 C2 f$ ^; W* P( Y# u' ]( B0 e8 ]
        }; B  P9 z7 F9 T- M/ L9 B/ n
        if( exsound_select & 0x08 ) {
! e6 x2 Q; B0 g                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 P$ S" E- n# ]' z                        data = mmc5.SyncRead( addr );
! z: G& y& Q* C% ]3 o                }
5 q, Z1 X( v. b% k& s% U2 t+ s) X( U        }
+ t% c# C& ^3 D# }  `* O' Z& P1 d; ~( Y7 G4 e$ w: B5 @  B7 ]
        return        data;0 f2 X8 A4 o( h% ~& n# {0 k& n  K8 y
}
$ p& P# n+ u0 V8 {4 [
* `$ T. E8 f' V; @* I) c+ x% T# Q* Gvoid        APU::ExWrite( WORD addr, BYTE data )
7 S5 C, T/ f: h7 b{
+ [; D/ o+ T4 m! k; e8 R        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 l! v: e$ y& {. n8 U! {
- E5 d3 R* I' v6 S        if( exsound_select & 0x04 ) {
% O% ~4 q9 l/ X- d                if( addr >= 0x4040 && addr < 0x4100 ) {
" m& ~- h! r5 x9 @) P1 w$ {2 t/ z' W                        fds.SyncWrite( addr, data );+ Q6 O3 U. d, `& j/ g$ R  m
                }
6 r( H( ?) C3 V1 p        }
" ^" m7 C4 v' A. a5 H- ]
; i4 I, Q8 g9 Y4 \% c3 d8 _        if( exsound_select & 0x08 ) {& M: K: S; j8 r! ~& E
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: J( S3 g2 A# l. D                        mmc5.SyncWrite( addr, data );
6 F( \- D7 C  Y, H                }$ t. u& A/ D7 v7 |- N2 \) e
        }7 f; J; }3 O) A* o# g% l3 ]* R% W' [
}
5 q7 u9 a* l$ c. h6 b) X% e' c! F1 E5 Z$ f' [- M
void        APU::Sync()! g5 Z0 e2 j6 z9 R" c" d) ?2 ~) |
{% p0 x9 C2 Y4 B/ }4 ]
}' u! x& p, _0 I0 \3 H) w1 w
+ U$ r- M, u+ N$ x: |$ ~
void        APU::SyncDPCM( INT cycles )
  D/ E- ]9 M+ a# Y{
# F$ Q/ v3 R  L2 r# a        internal.Sync( cycles );5 P5 R+ b8 u7 I
* `* i8 F1 u6 _* r2 C  K3 [* _
        if( exsound_select & 0x04 ) {
* N0 N( n: v3 Y1 ?# G                fds.Sync( cycles );, g% P9 E2 N$ D
        }
: B" ~: [# [4 Y0 k: ]( W7 {        if( exsound_select & 0x08 ) {
- A2 c& }. N6 L' ]" d1 A% }                mmc5.Sync( cycles );
3 o$ V" T' Z" U% o2 {) n% a$ ]" B% s        }
: o+ Z% U+ Q! C2 \& C! g}: q$ [% A; N% o1 g' ]% w$ S4 c2 L

+ U* Y; I6 I6 ?1 N# o. Hvoid        APU::WriteProcess( WORD addr, BYTE data ), ?+ @! u' _' F
{
7 {0 O: |. }, F; T8 \% g        // $4018偼VirtuaNES屌桳億乕僩
/ O: e# D5 s4 \9 y* R$ X/ [        if( addr >= 0x4000 && addr <= 0x401F ) {3 x% R$ S; d8 @% y# Y1 D; t
                internal.Write( addr, data );
: V" n- a% s- j" {* M        }1 W- c8 ~. M+ L. y- q/ _  F' l
}
  k$ O2 R9 |5 |# n+ N" @
/ h# u3 |/ I2 `void        APU::WriteExProcess( WORD addr, BYTE data )
8 `) b: B) C8 b( _8 S' C{
  I6 `/ J$ E* j        if( exsound_select & 0x01 ) {
8 n. M6 k# M5 w! H! q+ m                vrc6.Write( addr, data );& S8 l% v* b5 e% F$ H, V
        }9 K# }5 U7 k* [
        if( exsound_select & 0x02 ) {
3 E1 F6 N7 z. m                vrc7.Write( addr, data );5 ~2 d& V1 G- `  y+ u
        }: }, L3 ]6 \5 g& }
        if( exsound_select & 0x04 ) {4 n) |- s' D: m1 r, l% A2 l( F
                fds.Write( addr, data );
# |" l% I. s' k, l        }) h, m5 E* k2 h  ^* o
        if( exsound_select & 0x08 ) {% k# q" L" D0 C, u* U1 a$ h+ J2 f
                mmc5.Write( addr, data );
) Y, _' n9 {' g% r        }* s3 p0 \" M, @! F$ J0 o4 I" x
        if( exsound_select & 0x10 ) {
8 J4 {) ]3 K( `, Y+ v: F* F                if( addr == 0x0000 ) {
+ S1 s% z7 S/ }/ }* ~& z                        BYTE        dummy = n106.Read( addr );9 Q% `+ s' N+ G* S3 M
                } else {
! U3 P% J/ D9 y& o- T6 v                        n106.Write( addr, data );
6 ?& C) J( M) |4 J# y5 `5 d                }
$ x  Z, ^) P! R! _0 V. V% t0 P1 B        }
3 I; L5 A' |4 a! A& F: Z/ v        if( exsound_select & 0x20 ) {5 b7 c  y2 p0 i! r, @  _5 @
                fme7.Write( addr, data );
: i; U1 v8 \4 ~        }
( z9 O# c4 c6 J" p) g}
8 l1 K6 N+ t3 F8 d. r7 P* W! P) R& X" n3 g
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )* K* e7 `' N' \
{! e0 _" T; A; S3 T- S
INT        nBits = Config.sound.nBits;
$ i2 a& U6 \- c' ?DWORD        dwLength = dwSize / (nBits/8);
- ^' C/ ^  Q% EINT        output;% \) k4 n3 a- r; a3 c
QUEUEDATA q;# e) U: h: ?: N  }
DWORD        writetime;
6 |( T- }- Y1 D7 E+ m
& U' t0 d& ?2 [+ u* ^0 [4 B0 XLPSHORT        pSoundBuf = m_SoundBuffer;
: {  T- O7 c9 K4 G, e+ JINT        nCcount = 0;
5 a, h! U" v: Y! L- m
) ]4 p, Y, b! G2 M5 U+ l6 UINT        nFilterType = Config.sound.nFilterType;
7 ^) e( {6 P( O; m; Q3 O5 k$ N6 g. K5 Z# U
        if( !Config.sound.bEnable ) {
! C% G* d2 e- ~* f5 P+ l                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* e) G& P+ M: ~1 H" l; M                return;
+ s* K8 o$ |+ e+ M; C        }) r7 y3 }# `& X! M
2 s; X4 s9 j) j* ?
        // Volume setup! h" L! k2 T! j! c* u
        //  0:Master
7 U, D( e: m1 G* T4 K8 F9 \        //  1:Rectangle 1
8 L! g/ i- g% p1 a6 q/ s- N/ j' g% D0 j        //  2:Rectangle 2
  Y7 w3 v8 }* Q- x1 f9 j        //  3:Triangle' Z) t! N5 a1 x' v* j) S5 O
        //  4:Noise
) N5 n; l' U" H9 E: Q: q, x        //  5:DPCM
" j0 U" U4 I4 k$ K8 v2 ]        //  6:VRC6
! L/ T& ]7 r8 K- l; G8 r( D) Y' o1 }        //  7:VRC7
: I; A) Y# k0 a* @2 l$ r; n: q        //  8:FDS
; c' I9 T# ~7 V: v4 m1 L        //  9:MMC58 j* Q/ w$ Z# X, n9 g' Y0 s
        // 10:N106
6 u" r! Y. m7 g$ V) u: Q        // 11:FME7( ^5 N: a, u2 V3 ^% D7 \6 i
        INT        vol[24];
1 a+ Y6 F. L5 P/ S        BOOL*        bMute = m_bMute;$ X% x$ H3 E/ u4 b1 C0 k2 ]! Q
        SHORT*        nVolume = Config.sound.nVolume;% p. [1 M7 w0 T4 R6 A$ m

1 e) H% B1 v; ?+ k9 u  B( R        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
) b, S1 e6 w* O& U; G# b
9 Q1 y8 t. ?" Z& ~, a; B4 t        // Internal* C" e7 H7 N  n! A. r6 z) v* I: @( s
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;% Z+ v. r8 C! p
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;7 P& y# V5 R( Z! E5 ]5 `" [
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
  o$ W/ b- u& @, {( o5 w        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
  o; t1 K7 l; ~; T        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 f8 x+ r' @8 X& m, v$ T
! E& P. b; d; j4 M        // VRC6
1 y( ~4 @2 S/ w; q8 m; d        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
0 C* v: h) K0 t% U7 p% ~        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  h  e) E" Y# C$ b% u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 Z% G5 P3 {4 [; x7 E
5 a2 _: q" E3 w$ }$ z8 J+ S( `6 d
        // VRC7
0 ~. Z' P; R4 ?7 _" v        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  {0 T$ U8 N  ~. J: m! g
0 x# ]1 g* [* K& ^        // FDS3 y8 D0 i* K0 d# z% ?" j
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;! F2 e. S$ t+ J! }- m
2 e4 S9 ]5 N# j5 F3 T( ^2 w# M9 M
        // MMC5
+ t( u$ I) I) e0 c        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 a. X  X9 b, v8 ^        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;  p5 e( x/ j* S2 K; @$ y: H
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* {  h- b8 b8 @2 d  b! m& ]) y, q7 q3 d; P5 X) I" E0 c% h* l1 r( h
        // N1067 A" V. I( ^( G* ~/ J2 k8 S5 n
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, M& |* y% p' I) t
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 d, b& D$ q; d5 Q2 ?! x
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  f; f8 H' q1 O9 C# n        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 \8 q: u1 A. E1 i+ `% J
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  m  s# F* P) r! c        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 |- U4 |0 B  q+ H" i9 y        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ s$ J% G3 r9 t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ L* s$ m  C8 [9 G" Y1 y
, E8 s" e7 P# @
        // FME75 F1 G$ {3 P1 K, E
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ z- ]/ N, E) N        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# M- r% a$ k' S
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 G  Q( @$ S7 R% y3 y; K

* _3 h$ v$ U! Z; R4 N//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
, F/ @' U4 H0 r2 `3 |. a        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ j) n2 E& W- W* g2 }: G0 }0 K( g1 f. L! [, g& }  }
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 x) C5 s6 A, d" s        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: U6 w6 ~$ f& G
                QueueFlush();
4 I, Y+ M9 w2 I' W5 \        }
' @* n( p) M$ U1 D3 X
4 }9 ]' b7 W1 S% o% Z% A        while( dwLength-- ) {
. Y" k" g" Q( W0 x                writetime = (DWORD)elapsed_time;4 ]9 T2 A9 m' O; Q) s5 r

* p( [1 Z$ c: r& X8 |) o+ I                while( GetQueue( writetime, q ) ) {
& G. U7 z' \4 T9 B1 P# |5 x7 a, W                        WriteProcess( q.addr, q.data );& @1 R' _0 R% t& G) V8 O" b% r
                }
! K& t6 e# |5 g
1 d2 m* _2 t  N) p                while( GetExQueue( writetime, q ) ) {
0 p" w" y) W. ~% Q; B& b3 Q& b                        WriteExProcess( q.addr, q.data );
+ ]( O( ^6 S' H0 D& a6 r                }  g; Z" @9 J& K% q

/ A0 N1 p& ]/ G; r/ T! `  n2 p  X4 H                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7' I) y8 D1 W" s
                output = 0;+ V% v" S8 M! u
                output += internal.Process( 0 )*vol[0];) z4 x4 b/ O" d6 I
                output += internal.Process( 1 )*vol[1];
% ?& u+ V: @& b, [: Y9 O                output += internal.Process( 2 )*vol[2];
2 K7 k" i0 @- `( @& E" l+ _0 ]4 g                output += internal.Process( 3 )*vol[3];
3 h0 [$ C9 d, O, g# n" r                output += internal.Process( 4 )*vol[4];, g" X4 b$ j! H9 H) [+ a; E
! ~8 N+ h. f# p4 l1 k8 H) k
                if( exsound_select & 0x01 ) {# b, R9 J% x1 X4 s0 \
                        output += vrc6.Process( 0 )*vol[5];) g+ V+ I) ^' }# N, @( P9 N% p  C6 q
                        output += vrc6.Process( 1 )*vol[6];: H+ f9 b* N0 X2 f/ C
                        output += vrc6.Process( 2 )*vol[7];
4 T* K. b# ~- r9 r2 O* U8 d0 {( h1 H                }8 }$ J8 a! K& o0 B8 K. o! E
                if( exsound_select & 0x02 ) {* m& J" H* s2 E$ [5 t% p( C6 d
                        output += vrc7.Process( 0 )*vol[8];
0 O, Z6 I+ P1 }& Q                }$ x  P3 q' M! j% G" H3 f5 G7 x
                if( exsound_select & 0x04 ) {
; k* s& y  C9 E  m8 ?# H                        output += fds.Process( 0 )*vol[9];& i; m' e) R4 i
                }
9 b) }- s* \- g9 j                if( exsound_select & 0x08 ) {# h0 l% R( r5 p, t- c4 `
                        output += mmc5.Process( 0 )*vol[10];5 L' L* I- G' x! w! G" w6 H) g. `1 |
                        output += mmc5.Process( 1 )*vol[11];
' ^" [/ U; v' i! B6 i1 @; Q! S                        output += mmc5.Process( 2 )*vol[12];; e" z, O6 `' C; ?, Q/ f2 c' W5 Q: O
                }  D6 \5 F6 x# w$ s6 e- \; v) {/ k
                if( exsound_select & 0x10 ) {
3 ]7 R! C/ {) B9 w( Q                        output += n106.Process( 0 )*vol[13];8 D0 Q3 K5 o2 ^& _: I* f5 d) D. d
                        output += n106.Process( 1 )*vol[14];
# F! v, Y3 z+ @                        output += n106.Process( 2 )*vol[15];0 ?/ z, }4 ]) x" S" p9 K- x, F8 w
                        output += n106.Process( 3 )*vol[16];. _1 {% v" x4 ]! D
                        output += n106.Process( 4 )*vol[17];* j; u- d6 Y8 h
                        output += n106.Process( 5 )*vol[18];: i9 i' Z$ j/ f* Q
                        output += n106.Process( 6 )*vol[19];
$ N* Q' o. F/ ]                        output += n106.Process( 7 )*vol[20];, K4 o) t7 ~. F6 |
                }
# u& c% P3 I( J2 [. W: ]8 [/ q5 k                if( exsound_select & 0x20 ) {
) @5 w: i3 q+ l7 ]4 D, c! W' A                        fme7.Process( 3 );        // Envelope & Noise$ |4 A) ^& c6 D' w4 p/ `  z/ W4 \. t
                        output += fme7.Process( 0 )*vol[21];
, l; {4 M+ j: ]; K) i                        output += fme7.Process( 1 )*vol[22];8 e- h$ Z- t6 v8 a, N: [
                        output += fme7.Process( 2 )*vol[23];* E9 @4 l; o, s- }0 B8 J
                }& J5 g" n$ j1 i: V

7 B6 r/ @9 E+ q5 C/ S( K* ?                output >>= 8;
3 O4 R9 D( w9 U) {
/ Z/ M" v# |4 p" `3 t' K                if( nFilterType == 1 ) {/ n, u/ X  h6 i: J# a5 z8 {- {
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
! c9 X4 `' x4 z6 X2 l0 ^0 Y/ @7 T                        output = (lowpass_filter[0]+output)/2;" b# P! X7 Z3 O, ]! m
                        lowpass_filter[0] = output;. g1 B/ \% I! y  t( ~+ L
                } else if( nFilterType == 2 ) {' u0 i; G3 f4 ~# `
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)* D( |) ]2 n& D
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
/ p" D" O0 C' ~# E                        lowpass_filter[1] = lowpass_filter[0];% s/ }- l5 g1 f* \% x4 n
                        lowpass_filter[0] = output;
4 H, F% S5 [8 b$ Z4 A, X& H5 ^                } else if( nFilterType == 3 ) {
% U: A) G& \5 _0 G: _/ j$ R1 A                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 d: t$ ?6 Y7 G% s- Q- A                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 Q) B3 A. I  P# b' s                        lowpass_filter[2] = lowpass_filter[1];1 j6 G4 n1 {" L9 r" A2 D4 N
                        lowpass_filter[1] = lowpass_filter[0];
& D" C9 N4 L  }, s" |+ n( H                        lowpass_filter[0] = output;
3 V' i; u/ Y/ [: w$ |0 M                } else if( nFilterType == 4 ) {
- I( v. D$ L$ V3 g                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
( g4 w( H/ A3 m' }( X                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
% t- C3 v( K. i$ Q' W                        lowpass_filter[1] = lowpass_filter[0];+ H; W9 o) t' C% V# C
                        lowpass_filter[0] = output;
1 i% a$ V6 t3 v% V; {& d                }2 t& Y3 n( Y& m- w. q; k
5 t) w& F3 R8 @
#if        09 o/ \+ H, g: S: {3 f9 y' q' L$ c
                // DC惉暘偺僇僢僩1 P1 \( h( x4 m, j9 a/ P: C
                {+ k5 ~: z* B9 C. N, r
                static double ave = 0.0, max=0.0, min=0.0;
$ [7 v/ ?( W3 E* k( }+ }' q                double delta;
: |# G  [4 d9 t7 g7 W- m                delta = (max-min)/32768.0;
; z1 B. P. k) z9 k                max -= delta;$ t7 v& x: N& B/ O2 j- z
                min += delta;  J' y( U. Q; U$ O* C' f
                if( output > max ) max = output;
. M( y* z; [7 \( M, N% ~                if( output < min ) min = output;
* F9 @" Q3 |  _9 B7 V5 h                ave -= ave/1024.0;
* M1 o; \9 `" Z( Q% t- C                ave += (max+min)/2048.0;* z# w+ T- F7 L- A# P. K
                output -= (INT)ave;; r1 A5 X4 L' [
                }. ?# y) ]3 G$ V. K) Z; z" q" X
#endif
7 q. c( w1 y. V" [% S! R#if        1# t; L3 S+ p. |1 X1 i# c" ]
                // DC惉暘偺僇僢僩(HPF TEST)# A' T0 J+ P* p# B+ m* R
                {
& N( ]0 |" o0 H) [# l$ z//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);; D2 a# U  _/ p+ E- |  |  u* R4 ]
                static        double        cutofftemp = (2.0*3.141592653579*40.0);- D, {3 B+ Q1 Z4 F
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 v( ]2 @4 W1 Z( p" }                static        double        tmp = 0.0;2 V4 l6 b' ]6 s7 e
                double        in, out;- r+ l+ M& |- p0 W( I5 V

0 l6 s0 u5 u- \4 O                in = (double)output;+ ]& G6 h5 W# E
                out = (in - tmp);
) {# D# P" n. G4 k. u; V# Q; q                tmp = tmp + cutoff * out;
5 @& S6 w' @: u6 T: D7 C
, T8 S2 [7 s2 j                output = (INT)out;3 h2 ?9 }  y; `+ e) m
                }6 n( Q  e) `/ E" ~7 E
#endif
- H- j# j5 E: s2 |# i1 H" H#if        0$ ~) Q, S- a3 R0 P1 `/ u8 z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)5 B, g1 f4 W& K1 L
                {
) y2 G7 d5 F3 ?4 \8 p                INT        diff = abs(output-last_data);8 L! |: {4 n5 ?8 t
                if( diff > 0x4000 ) {( x: s6 \; t& L& A5 g# V+ B
                        output /= 4;
* e% Y1 D( i  i7 ~1 J                } else + D3 B' H% Z" i+ ^$ R  A
                if( diff > 0x3000 ) {
# S/ x4 G' I. _                        output /= 3;; {  |! h$ u! x( ~
                } else$ n3 \" D9 k- q; ~6 o6 v7 e
                if( diff > 0x2000 ) {
0 W, f; f1 o1 M( d* J                        output /= 2;
1 r. C5 h* e) T, i' Q                }
+ b  g% @1 ]4 X: \                last_data = output;
) k( a4 ^, u- h6 A$ K& q                }& a, N" t1 U8 D. }
#endif% I( P: a2 k9 ?" D! p8 K; s
                // Limit
: [- }1 ?4 J3 N: v# U; s5 o                if( output > 0x7FFF ) {9 }6 b3 g& Z& c) X8 ~3 u
                        output = 0x7FFF;
* d3 A  W% B! u4 c' ~' R                } else if( output < -0x8000 ) {1 j; q& m: W. ]) i
                        output = -0x8000;
, w* j( R3 q2 s* q$ `                }
# x* J" s/ ~  ^$ @/ G
! N9 j" b/ T) o                if( nBits != 8 ) {3 j/ K6 A7 _) e: }
                        *(SHORT*)lpBuffer = (SHORT)output;, y( p( o1 W7 `+ u* Y0 h
                        lpBuffer += sizeof(SHORT);. H7 J+ k' L3 w8 E9 a
                } else {0 j, {4 y2 y" z* I
                        *lpBuffer++ = (output>>8)^0x80;6 R7 |" A" q& S
                }" l3 Q# e/ x# [: ~0 h

) r0 z; h6 T- u) i' s! m                if( nCcount < 0x0100 )
3 X5 U. n  ~. a( \                        pSoundBuf[nCcount++] = (SHORT)output;+ {: ]  i0 K' B, M" N8 ]2 D1 h
4 U& c! P  C: z/ l( d) n/ |1 h
//                elapsedtime += cycle_rate;- |; W6 i2 ?0 b4 k0 q! c8 F
                elapsed_time += cycle_rate;- |4 a4 Y2 R, ^! A9 ^! G+ D
        }
6 T4 Q' r" z% o$ L% G7 I
4 {7 j5 X$ Z2 F$ `+ c#if        1
& {$ Q6 X' g, s6 g        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {8 ~) i2 f" `. x( }# \
                elapsed_time = nes->cpu->GetTotalCycles();
6 o2 Q1 c: }' h6 I        }
) {& H4 z0 C! \* [        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& z, ]% t, _/ u8 |2 v: a
                elapsed_time = nes->cpu->GetTotalCycles();; ^6 }5 E" `  w5 z  I8 q2 Y
        }
% `, b5 e+ i6 z: \, m' F6 P/ M#else
" a" K- ]) w% n$ c        elapsed_time = nes->cpu->GetTotalCycles();6 O+ ~- o7 |- }% }8 B
#endif1 I% n, U9 H7 ^' F& J) S  h; F
}
, Y+ B9 t4 T" c! w
; {# B9 D: {' Q7 h1 w2 O: U5 G$ @// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
/ L' X9 D3 m( i! Q2 z* \0 |' U  ZINT        APU::GetChannelFrequency( INT no )) P0 _' s* [# t, [' u' h
{/ e2 f0 t. q4 C, ?7 F# y
        if( !m_bMute[0] )
# V, X+ E: n& k3 F                return        0;
3 N, l; M7 Q0 [$ u3 Y! @3 N2 Q( X
0 |7 r, Q. E) T, {5 z+ Z& r) Y) c& _1 p        // Internal
5 {  y: ^; S" \% C& r        if( no < 5 ) {4 v9 Q, C# a2 P- t# I
                return        m_bMute[no+1]?internal.GetFreq( no ):0;  R* Z/ \. }) T9 w4 L& |
        }, q% a3 M4 U$ M' M3 r  ~: v
        // VRC6
0 Z4 z) T! C8 m$ H/ N        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ h  T) P! R( c1 O                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
! x: D6 V. W" C5 A! r+ @- u8 u        }
" }/ v% S  ~8 n8 [7 W6 |0 w# L        // FDS* M* i. U, Y- T5 t! A5 h+ t
        if( (exsound_select & 0x04) && no == 0x300 ) {
( T# A# B4 [  A& K4 o                return        m_bMute[6]?fds.GetFreq( 0 ):0;
+ [6 t& a& D+ l        }
  V  Q' x" _. ^) h. r) {        // MMC56 D! ^, W  B3 p6 X6 [
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# D* ^3 U8 _! v! l& G& [8 X                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;$ m6 [+ y, N' B6 a+ w+ c! j3 e
        }
7 j( u3 A# n% \" y- c: h$ c: \        // N106
3 m4 Z  t0 i3 P0 K; {0 G4 E. w        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {( w+ V- l1 o( r7 @
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: @% B% f$ x1 [. M; j
        }
  p1 h0 W# V' k( A) [) b, T# n" z        // FME7
5 t+ `1 |$ Z0 L7 o        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
9 W9 P1 K! v; z6 D, b                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
3 r2 D) f0 z. C- C% T) H9 ?: Q. o        }* X  x6 g7 |4 a
        // VRC7
1 w  ^  t& t. B, n% Q4 d' e        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {( Q$ Q3 o, x! I1 V0 Q8 h
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* i( y5 H& P# u, C4 z' \# A
        }
) z$ s  O9 C/ O        return        0;) ]& y. h% T, ?3 h0 ?7 z8 K
}
0 s$ t0 [8 J% n) I3 f! O5 G/ J% A* B! t- c3 ]2 i) y: a0 y. k5 V
// State Save/Load
7 d2 g$ v( h8 ~( S5 l6 R9 _void        APU::SaveState( LPBYTE p )
. [" k  b4 b3 b{  X6 g6 _5 k8 B* z5 p4 V2 x
#ifdef        _DEBUG& |# J5 T' J  x' D4 s- J% k' A1 a) o9 s
LPBYTE        pold = p;
: w& h$ F4 C$ [, G- y' q. O' H#endif6 o! l0 b' c6 w0 n& ?# M
; M6 ]6 [; ~( d3 ?# ]
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞" }; ?; K$ Q2 n4 s$ X8 y" k& V
        QueueFlush();
3 @$ ?' k6 m! F2 i- a
3 u% x8 g# D" D, K) D6 o        internal.SaveState( p );' M' C0 W: Q8 Q4 M+ I4 i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% i( y/ d* R, E

" [1 p8 N9 T3 f( @# c        // VRC6
* \' J1 F. ]# [  k2 A1 Y        if( exsound_select & 0x01 ) {
- C; g2 `/ S* ^6 u5 C                vrc6.SaveState( p );0 b5 c: E+ M3 {9 s* c4 x
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# T& M  c* W& J1 y: z
        }
  I1 c+ O4 O$ l        // VRC7 (not support)
, Z  R9 ^0 R9 s; Q: S        if( exsound_select & 0x02 ) {5 `2 M' N4 W+ d
                vrc7.SaveState( p );
3 [9 ]  H7 V9 d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding* ~! P2 A3 u; m
        }
4 ?8 F, \; e# f        // FDS8 R/ e: K8 M1 ?) @+ L2 [/ d. Q
        if( exsound_select & 0x04 ) {
% K9 x! h7 g! A+ }( c" K# A                fds.SaveState( p );" A9 q3 w0 |; {( c
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' N; d! X8 s" v' I
        }- Y! Y8 n8 p1 z  M
        // MMC5# `! g. Q. Z/ r) o! {
        if( exsound_select & 0x08 ) {
, M9 }5 `$ [: v$ f9 l3 g                mmc5.SaveState( p );
, N& X5 f; E  o- H4 I% L                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 e* P% L. v0 j) L4 k
        }
/ r" m3 s+ I* T) t) [% e        // N106& m$ F, H% ^) A9 f; P  ?! c0 h, Z
        if( exsound_select & 0x10 ) {
7 r9 A& [( Y5 w                n106.SaveState( p );
1 a! O- C+ }5 ?4 Q% h) [                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ J2 ~1 w4 n: ]
        }
% |) a, w/ t+ ^+ |/ N; `  D/ N        // FME7
9 T9 ]2 g0 l% o1 J1 t        if( exsound_select & 0x20 ) {1 k* j! o  b, l% b! a
                fme7.SaveState( p );
7 W: D8 V% \$ n1 U+ q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 u$ d3 w& a+ W, e; I        }# j+ c. i4 f; b2 m9 Z

( y! K) G' c0 g& s3 K#ifdef        _DEBUG0 K+ z8 D; `; f# V/ n) v6 N* R" l
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
& E1 g, o9 _! K: A# q#endif
# u( @/ J( U; X+ ]9 c. B}3 ]' \* O$ k9 @. _1 R! A' F

$ ~% H8 {& E0 T& w( s0 Evoid        APU::LoadState( LPBYTE p )' Y( t  E; {0 U1 }5 g
{
2 N' N% w" T5 g7 p        // 帪娫幉傪摨婜偝偣傞堊偵徚偡% a1 M. U* N* G' g
        QueueClear();
9 S( _; U" ?; U+ L! [8 J8 |6 e
# _" _( p+ W: _        internal.LoadState( p );
' t/ i3 H6 l( A8 e! H7 s        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding* V. V; ?! d* R% B2 q. Z' X2 ?
, C1 L3 w) w+ g) P- x
        // VRC67 ^5 @: _( I. A& x# V
        if( exsound_select & 0x01 ) {
" e: s: f& ~0 T2 y% @                vrc6.LoadState( p );
0 k) t7 R6 p+ S- ]6 A                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 R) @$ V) P# D" u3 N- Y        }5 [9 e# o  @0 ^) N1 L7 o
        // VRC7 (not support)
( Q1 g- Z) S; E) q        if( exsound_select & 0x02 ) {, K/ b) Z/ j0 f& r$ w( j0 |
                vrc7.LoadState( p );
+ Y" Q! \5 H! U+ r" `4 u3 ]                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 l. ^: ?2 C* j0 `  J! K
        }3 M/ Z& g; a' U9 U, Q  q, v
        // FDS  S0 z: {; L$ E, `! f
        if( exsound_select & 0x04 ) {/ P- U( |. F/ s, C3 @% k5 u: V. i$ P
                fds.LoadState( p );$ B" G' p3 y' Y/ L9 _- I
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
; D5 P( ^' u& \! _4 N: K: t. V# I        }7 C( s! g6 k3 W
        // MMC52 B9 r  E; a6 H) V3 m5 o% H
        if( exsound_select & 0x08 ) {
3 N* x. g6 u, `4 ?) L$ O: X                mmc5.LoadState( p );
( L% x  ^' R6 t8 I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ c* l, a+ [6 d5 Q0 t& y        }0 L6 E! p% P, B$ Z" N
        // N106
6 O8 `0 b6 f1 D# }% N        if( exsound_select & 0x10 ) {9 U$ R5 C$ [; H4 f. k" l) y
                n106.LoadState( p );" m5 V* \+ J; [& I
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& I  |# J% {6 s. Y6 ]' `        }
! Z9 t7 X$ I" p5 a        // FME7
/ F: |8 x4 T# n! r0 h" b3 O" ]        if( exsound_select & 0x20 ) {
3 m9 @4 h, P4 E8 G# w3 {                fme7.LoadState( p );
& B+ }8 D. E# k. M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 J9 F2 |0 c2 ~0 R' I7 A# t        }# A2 C- Y$ c- S6 \' ^
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
6 Q; F6 l* x) x1 ]" a可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。9 C1 |3 V6 u) J) H
感激不尽~~

6 V; [9 A) A2 [# R5 |$ @恩 我對模擬器不是很有研究,
$ G; y9 `0 z/ g1 ?3 W7 M雖然要了解源碼內容,可能不是很困難,7 w% z# F8 g& H
不過還是要花時間,個人目前蠻忙碌的。
9 y7 f& m) i) |5 C! V# A0 R* g7 A6 C0 h; e( I7 x% ~1 O
給你一個朋友的MSN,你可以跟他討論看看,$ f) W! ^* N% I* s/ S; }7 N4 _# a% T
他本身是程式設計師,也對FC模擬器很有興趣。
9 }7 f7 y( k2 R: S0 N' K# H; a. G" X3 k9 G3 v9 G* U0 K/ R
MSN我就PM到你的信箱了。) w! i4 d) e* V- I5 N  e
4 d6 T  K& J2 i" @
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ; y" E  e6 Z1 A0 j' C# c
呵…… 谢过团长大人~~
! W; E- A9 ?. K' d  Y; s/ Z3 v. _! O

  H6 D3 c! L! D# F7 k% X' R: N哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 5 J  g9 l0 k* u0 H0 ^
团长的朋友都是神,那团长就是神的boss。
" O* b# p7 u. z7 e( M( ?$ T
哈 不敢當,我只是個平凡人,1 Y! A1 c: Q. M9 p) ^0 W% @- y8 D
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
  d- J& R& t$ v6 TZYH8 i' }" O; t0 u
QQ:414734306
$ \$ ~" L; b) }) tMail:zyh-01@126.com
; E! v5 P" i# g& r( ]: L; b4 `' E6 E; ^) @; M- J$ s; e. L& h! E0 v* U
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) y* E. J. ]; ]9 B4 p: W再次对团长大人和悠悠哥的无私帮助表示感谢~~
, V5 s% n! U  u7 z$ O
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 15:49 , Processed in 1.178711 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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