EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 P% _3 o; c1 X4 V, ~% P& |' c楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) D, T6 J3 d9 v/ b2 o: l. I4 _这里有相应的模拟器源码,就当送给大侠了~~' ~$ }# x3 q# M( ~. a* K- U0 T$ U. o
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 O; K$ v: D$ {能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 M& C# f  p2 d" x4 w% A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, k" ]' ?9 I9 |: r# i这里有相应的模拟器源码,就当送给大侠 ...

5 A/ r" g* e1 c* [- O* j. c" N聲音部分(Audoi Process Unit = APU):8 s* v$ r4 x, a" |- U! l: i' l0 i% w& q
.\NES\APU.cpp
. W0 R4 R, W+ c. b.\NES\APU.h
: I/ ~# U, }; i: s
5 m* B- L/ R0 N3 b2 W1 P" l
/ s& ]1 ]( h$ r影像處理部份(Picture Processing Unit = PPU):# L3 T0 U& b' z- B# \2 `, f
.\NES\PPU.cpp/ i3 X' R, V5 G% t) R6 H6 t/ e( T
.\NES\PPU.h3 t0 n- _5 |; Z& W! L, L

8 H: W; Q% [" L# |' S/ P如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
; g9 G5 \1 ?1 p8 b) r(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ y: E) S# R5 J
//////////////////////////////////////////////////////////////////////////  K9 S' {# ?  G- I
//                                                                      //
3 D- ~; E1 B+ t//      NES APU core                                                    //, O5 r' [' {4 V0 D4 P
//                                                           Norix      //
- m9 C5 ~" l  n  X$ k9 J6 m' i//                                               written     2002/06/27 //3 g: S* ?! {# B0 a2 f, `- ?' t
//                                               last modify ----/--/-- //( g! k/ g& F( {6 v
//////////////////////////////////////////////////////////////////////////
' E# D& f+ u  N* x#include "DebugOut.h"
" X: D3 h0 q9 O0 V8 X- z# P#include "App.h"3 Z( Q. g% w' {
#include "Config.h"5 F1 z3 q8 k' f$ X8 E8 S  m
3 Z+ ^$ J- _' I) `* D# o
#include "nes.h"9 `: w# l; L% i
#include "mmu.h"
( g$ f1 G2 ?2 u. `5 U9 C) w#include "cpu.h". N( e- i, n8 z) K
#include "ppu.h"2 }+ I! p6 B0 r* t0 t8 n
#include "rom.h"
# Z: c; U* Q; j6 N/ `7 U#include "apu.h"$ j7 p& Y4 {; |3 C6 r0 ^2 x& W! r$ ?2 n! H
, i+ m& E6 i" z: m8 |+ E% t
// Volume adjust
$ ^, ^2 t4 V* J% @+ r// Internal sounds
; ]5 {( J- i( _' p#define        RECTANGLE_VOL        (0x0F0)
; d3 q. A9 B+ E4 J#define        TRIANGLE_VOL        (0x130)4 ?7 E( D( t/ c) q% R
#define        NOISE_VOL        (0x0C0)
* O+ {$ W4 [0 @; o6 V6 @! [#define        DPCM_VOL        (0x0F0)$ v: V$ u( ^& j+ K( e
// Extra sounds
1 l; R7 Q* N& D#define        VRC6_VOL        (0x0F0)- p9 g! B1 I: W$ S+ y
#define        VRC7_VOL        (0x130)( e% s  B0 e5 ]8 A
#define        FDS_VOL                (0x0F0)
0 ^0 Z5 F& z3 S& p) e8 h5 X' ]8 w#define        MMC5_VOL        (0x0F0)
2 L* S  o7 G" [% q% M! C#define        N106_VOL        (0x088)8 J9 s+ T" k. U: `7 g8 i6 E
#define        FME7_VOL        (0x130)1 I/ \3 ?: B. @! S

: n$ q# V  ?) n3 i8 v* j, }- RAPU::APU( NES* parent )
, d' l; Q2 r, d# A6 _; c' D{5 \5 T8 p& u: C( x: D
        exsound_select = 0;" E1 a3 F; D& m1 `4 ^: I7 p9 O
2 ^8 [$ c- \$ n2 L% y1 W
        nes = parent;
4 n' D: `! m7 H5 X9 ]4 d- ~) _        internal.SetParent( parent );6 e# C! Q! O4 U" e1 g
8 b- u# g" i; M2 H0 ^; W
        last_data = last_diff = 0;4 D& _) {  {. ~0 Q
& K1 Q1 Q8 H2 d9 u
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ ]8 E5 U7 _0 K6 B
4 Z4 q7 z! |: e4 c( o( h5 u* K% I# ~
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );6 j0 h: t* J9 b+ A+ j
        ZEROMEMORY( &queue, sizeof(queue) );
, n+ ~4 K5 v$ W* A        ZEROMEMORY( &exqueue, sizeof(exqueue) );# A" \  `6 v! p' b5 n+ j$ |6 x

% W' s) ?: y, Q        for( INT i = 0; i < 16; i++ ) {
3 j8 M5 z! T/ g' {6 n                m_bMute = TRUE;9 h9 ?% }3 l* o  j- i( b
        }
4 v: }, b8 h3 U; b# q! |}
7 A: I# o7 S. r9 z4 W& y) q9 {1 S4 h2 |1 u, y. t& Y# \8 z7 ~
APU::~APU()& q' [9 N- f' o3 U1 a
{( I0 O1 M3 \+ }1 v5 r0 t8 @9 j
}0 x0 m8 X6 G; m7 O8 F

; {# B, S, G5 g( s0 p4 N+ `void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
) z. X2 t5 H4 s6 z- ?6 o{
7 ?- s- \& r% W: v" ?7 ?/ W4 ~9 h* k3 p        queue.data[queue.wrptr].time = writetime;6 X; D0 D9 c- U
        queue.data[queue.wrptr].addr = addr;
) Y8 N2 ?% }+ u& U* w6 v8 {; _        queue.data[queue.wrptr].data = data;4 \% B) \6 Z; _7 M0 c+ X9 R/ s6 S
        queue.wrptr++;
4 S9 _9 o! [+ r  B8 w4 g        queue.wrptr&=QUEUE_LENGTH-1;0 F) T4 U( C0 K1 _
        if( queue.wrptr == queue.rdptr ) {( P2 H! U. y7 B' t
                DEBUGOUT( "queue overflow.\n" );1 ^- N( I+ ^! k7 c
        }' G: ~# Q$ T" j5 [& J" h
}
3 W) g$ q! L' G' l! P" H' d) ~0 P8 e8 f) @5 y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )! W. [" {/ M% f4 I* M0 Z
{- v- X# ?( T: e1 m! m8 ^
        if( queue.wrptr == queue.rdptr ) {
$ m2 v. B. {+ W: ?  t4 r                return        FALSE;. q" p- u1 C$ \
        }
  f' Y8 N2 |# c7 }9 @% m        if( queue.data[queue.rdptr].time <= writetime ) {
, y( K% H1 O& X$ d                ret = queue.data[queue.rdptr];* {, x' m6 x+ f9 ]7 w/ {- e
                queue.rdptr++;+ h+ H7 }. M, }9 J2 ]$ H
                queue.rdptr&=QUEUE_LENGTH-1;
5 I: y/ U( ]/ `$ o# [3 V, Q                return        TRUE;
6 K. c" o. A' v% {+ a3 t$ S        }
$ V+ u3 z5 G! @) T$ Z+ a% Z3 Y        return        FALSE;6 r7 p3 E$ p/ S- l
}0 t' W3 L- ~- V: W) U/ |

/ c( F$ k- I3 O* Lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )* H( @" I8 O: W9 F% E( D$ c
{
- m5 a7 A6 e9 l8 |4 b        exqueue.data[exqueue.wrptr].time = writetime;2 E* G  \6 }* B* z% M
        exqueue.data[exqueue.wrptr].addr = addr;
4 A% v) R' Y+ l; q        exqueue.data[exqueue.wrptr].data = data;2 ?/ w6 J8 c( N1 c! j( c$ [) R
        exqueue.wrptr++;
7 c" {# s, M6 L% L  Y        exqueue.wrptr&=QUEUE_LENGTH-1;
! M& ?1 q0 r6 k3 s        if( exqueue.wrptr == exqueue.rdptr ) {: l" V( G5 `% Y5 T
                DEBUGOUT( "exqueue overflow.\n" );7 H+ L6 U+ W1 y/ l8 _
        }
& ^* x* C9 X8 w3 d" c" W}! E+ p4 d1 `$ ?  f! V. m9 ]! K, }
5 G% V- m- I5 f, N0 l
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )) }" G* X5 i# t! d4 d9 H7 j, j
{% R9 U1 w: S$ B: ?. g. l
        if( exqueue.wrptr == exqueue.rdptr ) {
8 b8 q# N+ y7 m+ R" C                return        FALSE;  O+ k& y2 r- R
        }
3 ~, a! a, ~. o        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 U+ z+ e; v  U) e& C                ret = exqueue.data[exqueue.rdptr];/ Q' `8 z; p/ ]. Q' G% b1 H4 T
                exqueue.rdptr++;
. i  D, _1 J1 u; S/ s4 \- t3 d8 U                exqueue.rdptr&=QUEUE_LENGTH-1;: y$ D, t& W3 ?& C1 |5 p6 T
                return        TRUE;* ~% d( |9 p, r: Q) O
        }
0 q2 X9 K  _( \5 O2 b7 A        return        FALSE;
, v% x2 {7 m2 j* V}; l' p; p# J4 E
0 Z0 m( ^# U/ X7 ~5 I- Y  h3 p
void        APU::QueueClear()6 P" @" f4 p8 S* {! ]4 K
{  _  d: K; n7 x; Y' J! N
        ZEROMEMORY( &queue, sizeof(queue) );
' n& R, U, I: n+ {        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. ]$ W7 d% B: k" `}
) t# a! e2 V! |' _  a/ ^3 z8 p4 u8 W0 L, {
void        APU::QueueFlush()
% g7 H/ N' u8 K% t/ N0 m; E% v8 ^1 T{
2 T; i. J' s' V        while( queue.wrptr != queue.rdptr ) {, o7 e4 z) Y7 d4 _
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* P7 S# N3 r/ {6 T% v1 s. H                queue.rdptr++;
% [0 S- ?4 g7 W' t( b. I                queue.rdptr&=QUEUE_LENGTH-1;* [/ Z4 a) A9 }9 d% q
        }6 W' R1 g$ h, R$ c6 f8 i* q# u9 `
, X( f0 M$ f2 f9 b% g5 z
        while( exqueue.wrptr != exqueue.rdptr ) {
: g. L8 e+ j! |9 u/ P# x" |                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 U1 Y- ?0 Z$ L0 i' ~0 d4 S                exqueue.rdptr++;& F9 L0 {: A' u0 i5 G4 O. z% T
                exqueue.rdptr&=QUEUE_LENGTH-1;
; V1 h3 w9 v8 s" V" Q8 }        }
4 r: Q3 t" w7 r# p: Z) L* {}$ l% ?: K4 J; U$ X
# T$ U6 b7 c. P- ?8 h+ H3 @
void        APU::SoundSetup()
, f  e! N2 f8 T{! a- u$ [7 M% x5 f% l
        FLOAT        fClock = nes->nescfg->CpuClock;) ~* U: \: k( }  J# |+ X
        INT        nRate = (INT)Config.sound.nRate;
6 e; w1 K. ]4 I& F8 h        internal.Setup( fClock, nRate );
! R( v& |0 t, Z6 ^; |8 m/ v        vrc6.Setup( fClock, nRate );1 B2 \  B+ D: Y
        vrc7.Setup( fClock, nRate );, ]5 _% X8 A: v2 s1 R! n4 T& c
        mmc5.Setup( fClock, nRate );* t9 l8 d/ }' g! H& t2 Y/ `' a
        fds.Setup ( fClock, nRate );
! K8 N! f% ^& r2 k        n106.Setup( fClock, nRate );
* D+ J0 v" y) R; j3 K3 E8 K2 E        fme7.Setup( fClock, nRate );
7 i: s+ t8 [8 v2 d4 |}
+ ]! a7 s: Y9 U  s3 ?) G5 S% @; ~8 B* z. q
void        APU::Reset()  H. K8 O# e% t
{8 V. K( n" ~' j* h/ {2 `
        ZEROMEMORY( &queue, sizeof(queue) );9 h# Y6 V% P. n7 i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 |( H6 |: X( o3 {: L0 Z% B/ b& t

4 P/ z; F7 B3 m9 S5 n+ [        elapsed_time = 0;
( V' v7 U2 }6 n: F2 m4 t9 d  p# o  d- h
" s! M7 O$ j! ]9 A, ]        FLOAT        fClock = nes->nescfg->CpuClock;. d5 c8 R5 @. Y9 ?. _+ c9 s3 x6 [
        INT        nRate = (INT)Config.sound.nRate;0 o* v) S7 x- x" y8 b) d) A/ }
        internal.Reset( fClock, nRate );2 j9 H. G3 }) D1 q! |4 I
        vrc6.Reset( fClock, nRate );# \9 Y  }9 W* u6 n( ?
        vrc7.Reset( fClock, nRate );1 m* s- I" `/ g2 B. S3 ]2 Q4 a4 O( D$ g
        mmc5.Reset( fClock, nRate );
! e1 ]& T7 a5 O' @: G2 M* u# |        fds.Reset ( fClock, nRate );
+ D: h- N; o( q# [% X# Y- d  R% {        n106.Reset( fClock, nRate );
; Y8 Q% m8 _6 ?1 t' U: }! T4 V        fme7.Reset( fClock, nRate );: ~& d" [4 K5 ~3 P+ r- t

- h/ S2 o) H. F- d; ^- _        SoundSetup();
5 T9 q! w( Q: y2 n}3 g! E4 N9 _& ^
% z: o. i& c4 C+ p& |
void        APU::SelectExSound( BYTE data )
0 u. L. D* M! R3 p{# \5 b1 Y$ s1 t$ {* i
        exsound_select = data;
4 d" Z  n6 V5 O. S% f6 |}
* T. @9 H# y& F6 J4 u4 H
* L$ _8 s6 C3 X1 EBYTE        APU::Read( WORD addr )
; Y3 Z6 M, I' L{( T% ]7 R! N3 `- H
        return        internal.SyncRead( addr );
* u" |' K8 h2 B( T1 D9 c}# ?, A7 h2 W* _

4 o! ]% q* a( |2 [4 xvoid        APU::Write( WORD addr, BYTE data )
. \7 j2 t! {: |$ C7 e) A{$ V) m& E7 i8 c) g+ X! k" T  |
        // $4018偼VirtuaNES屌桳億乕僩
# X! \( F7 x1 e! m        if( addr >= 0x4000 && addr <= 0x401F ) {7 i+ U# ~7 F8 M( k  ~/ {+ x9 k
                internal.SyncWrite( addr, data );
+ q) M# ^" x" v                SetQueue( nes->cpu->GetTotalCycles(), addr, data );5 |  f# W& K6 m
        }$ m% y4 Y3 ]. m+ C  _& p
}
% N- N4 Y5 X! M, O# H! a# |5 G# @+ _  m
BYTE        APU::ExRead( WORD addr )
' g. i& z6 C' P3 `% _6 j{
+ S% [" {5 V3 d% C1 [BYTE        data = 0;/ i/ \. l; W9 y
, A& c& z. U8 e
        if( exsound_select & 0x10 ) {0 P& F+ r: X4 [3 ^
                if( addr == 0x4800 ) {
& u! q$ o  i4 R5 P5 s- ?                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );( \5 {$ V8 t& e* j3 ~9 l: i% K* h
                }
+ L3 ]9 ?# W( W$ }) o& k) t# q! a        }. R3 X, o. \: g3 t; N! v. z
        if( exsound_select & 0x04 ) {
9 D# Q6 j2 s/ M5 \2 N6 \3 I& A                if( addr >= 0x4040 && addr < 0x4100 ) {0 G" v5 N$ V' e, b$ a
                        data = fds.SyncRead( addr );! v" R( x- E/ b' E. u1 O4 N  [
                }
* p* |" |" }* A# H, F        }
) |3 W6 \8 `# y4 Z8 |! m/ f" h        if( exsound_select & 0x08 ) {& F' I  |, X, K& G( L% M
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 ?$ B3 I( ^! ^" J+ x                        data = mmc5.SyncRead( addr );
6 y$ a2 O1 x/ d& |( x' C! P                }$ ?% H( M, S/ n; h7 Z
        }
& J  r. J( b3 }- ?- j7 P1 w6 x( m' l' Q0 Z
        return        data;2 n. [4 }. O5 J( k, m" F
}
* d3 Y4 `% b& t# e
) b! {0 d, B$ ^: q3 D5 s+ O1 mvoid        APU::ExWrite( WORD addr, BYTE data )
: N( m4 m1 A* S' `% s{0 T2 y" |5 H1 H9 o  G5 E; D
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );" Z! s/ w7 v9 h* f+ g
; s" g  I* ~3 e/ N; b+ P1 V- c
        if( exsound_select & 0x04 ) {
5 n1 o- h9 o5 O1 G- W                if( addr >= 0x4040 && addr < 0x4100 ) {: t* P0 R0 a$ o6 ~: X9 q, r
                        fds.SyncWrite( addr, data );
' j* S1 j& f! _. p                }
& }, v" a% g; u" _# t# w& Q$ m        }
1 Z" S2 o3 p2 \' U3 x4 r& a3 [1 i* n2 B
        if( exsound_select & 0x08 ) {+ \! w  J+ l, z, f% N$ m7 @
                if( addr >= 0x5000 && addr <= 0x5015 ) {
: t: h/ ^, T) {                        mmc5.SyncWrite( addr, data );
( f9 }: b; E/ U                }
, t1 _" y* v4 Q# \0 O$ X0 X7 z        }- x, y& t* p1 Z" {# N7 t' |' J
}% e% c8 U- b+ K' v7 k+ c
) @+ W6 M5 [- n+ D; N! }
void        APU::Sync()
5 f0 n% r/ x5 @2 Y/ y6 d{* B6 u3 C4 e) b, Y
}; L, Y" N' y/ K# {

3 K8 z* ]  u+ L7 P$ s  [$ M/ z+ Mvoid        APU::SyncDPCM( INT cycles )
' F8 U* s" O) ~$ Y{/ n# K' K( F" z  L0 H& K
        internal.Sync( cycles );: _% E' r5 ?4 n+ A
; u1 Y: m/ ^& m- L( V( \- F$ D
        if( exsound_select & 0x04 ) {
7 e- n5 G, D  V                fds.Sync( cycles );5 ]4 \! r( t( S$ X- [
        }
; a- l1 R8 C. @2 c8 f, o        if( exsound_select & 0x08 ) {. |. f. L6 f# S9 e, v0 x4 h
                mmc5.Sync( cycles );" c. I0 j+ N. C9 P8 F3 [. X$ F
        }1 l3 L/ k0 L" N9 e  B4 T7 F
}
, Q6 a  g6 G* ~& g' g& J$ {: C1 a' g3 p, t
void        APU::WriteProcess( WORD addr, BYTE data )3 X  s/ ]) w1 G& u4 K( ~, V
{
! ~  i- y  ]- K1 i3 b+ e9 D2 d        // $4018偼VirtuaNES屌桳億乕僩- c3 Y. x9 _0 ]- @2 a+ o
        if( addr >= 0x4000 && addr <= 0x401F ) {1 M3 n+ ]% ?0 V) _5 L; ~6 W; F) A8 m
                internal.Write( addr, data );
) Y: d/ x: ]7 D0 K3 z/ @        }
( ~) X* a5 j+ ~8 h}( Q4 k* ~# F* ]5 Q% j6 H' @
0 e" O. m$ K' f- M
void        APU::WriteExProcess( WORD addr, BYTE data )) C, q# p7 ?& K1 I3 w
{: m3 d3 m  F7 Q6 X6 ^( S- O% `' ~/ e
        if( exsound_select & 0x01 ) {$ T5 J2 x2 O& ]. E, k
                vrc6.Write( addr, data );& Q9 b2 M: h* q" v& d
        }
  M' A* p1 D3 N: d1 d" x/ g! d7 |        if( exsound_select & 0x02 ) {
+ Q$ F1 N% q; k+ o7 ]                vrc7.Write( addr, data );: v/ q( }1 s- k8 q- M
        }/ ?/ Y: \# T- p0 v( P2 @5 k/ K
        if( exsound_select & 0x04 ) {) s% z9 p; T5 D0 x" F
                fds.Write( addr, data );6 Q' g6 ]/ Y  w, P5 n* P* L/ U. Y
        }
! }$ w2 E. B* R        if( exsound_select & 0x08 ) {& r# ?% W1 n9 y# g4 w
                mmc5.Write( addr, data );
+ R4 |) y- u: c) A( ?; c        }  ?" v7 x* L6 [1 H9 E& ]
        if( exsound_select & 0x10 ) {
2 r* t3 L  T. M/ D7 }                if( addr == 0x0000 ) {
( g. N+ r7 t- I! P9 l' N: G, V! F; C7 ^                        BYTE        dummy = n106.Read( addr );
! V/ V1 ?- W: q7 W                } else {
6 m! ?0 b3 v: y) g9 k/ S6 f7 e                        n106.Write( addr, data );
" q' C2 v9 F4 s! k3 }                }
7 j5 F# x* O4 _. N9 Z        }
/ f1 s( ^; o* x$ l* _        if( exsound_select & 0x20 ) {7 ~6 n1 y: d* l: Q5 u* F
                fme7.Write( addr, data );
1 B6 ]4 |& M  }        }
; e% q0 d# c/ q& X4 a. L}- ]7 ~. `8 l0 H1 Z3 j' O7 w- G
9 H9 }' ~7 a9 r8 `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )  U4 J9 |& Y& v4 [' _# I
{. b2 }. @% R, S; ~3 ~$ R( u+ A
INT        nBits = Config.sound.nBits;' ]( [" G, V8 a. H
DWORD        dwLength = dwSize / (nBits/8);/ Z. m+ \# ]/ U. A+ G* F: i9 B6 H
INT        output;
) |& y8 q* o/ I, F7 v* SQUEUEDATA q;
& g& |) w0 D4 |DWORD        writetime;# \8 r. B6 J$ C# N- k

5 P) J) e0 Q' ]4 ?; {* SLPSHORT        pSoundBuf = m_SoundBuffer;
9 \! T* R0 |7 w5 x* C# eINT        nCcount = 0;
) x2 m& `6 v# ?( y; R* h
2 C' [, C$ a; KINT        nFilterType = Config.sound.nFilterType;5 D6 _  \/ S. j8 k; D4 ?; p6 ]# S

6 F& a  J1 e% ^5 K5 j: D9 {        if( !Config.sound.bEnable ) {3 \5 a3 f' `: m8 b5 c% O2 T$ A, K
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );. }: R$ z: V. s3 \
                return;
) @9 j# k# @3 x% G' y! B  U! \! p  Q        }
" T5 U0 W: G! M4 H. Z8 d% W( p6 W- f' T) R- ~3 N' n
        // Volume setup
& |3 G% S% J$ d; c4 I) y        //  0:Master
6 T. m1 A  G6 W; f: G/ G        //  1:Rectangle 19 w/ M4 A0 z: y! j" N+ s& r! o
        //  2:Rectangle 24 o: g! f& B. ~; Q6 V% B
        //  3:Triangle2 [6 M. w: a* @; ~/ m6 A& K
        //  4:Noise
' I7 U% o* `, s( y        //  5:DPCM3 r1 m1 K4 W  r
        //  6:VRC6: f- D4 P8 n9 a2 v$ R% H. f
        //  7:VRC7! {+ `  N1 `" F; s# E3 d9 A# d8 ^9 z3 ]" L% E
        //  8:FDS1 k. ]& ]% K, m  @2 |: e
        //  9:MMC5" [- `. Q5 O8 F3 r& Z
        // 10:N106
1 i4 ^$ m: e! H. e0 I, z        // 11:FME71 S: c# a  ~' N, N# M% \
        INT        vol[24];4 N. n' L' i5 D" y, p( [4 I
        BOOL*        bMute = m_bMute;
' u3 G2 R9 M- i" O5 Q        SHORT*        nVolume = Config.sound.nVolume;# Q' ^+ ^7 c8 c4 F: h

4 s' l2 Y$ _3 W; j5 x/ B6 S        INT        nMasterVolume = bMute[0]?nVolume[0]:0;9 K9 s: _& s' P& z( m: A/ o* ^$ f

6 r1 `) A' ^- |1 `. o( N, W        // Internal: x0 n/ @: a5 r" k6 W4 E
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;9 o) n9 s8 w1 W
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, [* e5 k, v: r0 R* H        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;  X) P" \4 o( f
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;/ ^* P  D# A1 \. K/ o  L
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;) ~; q; I7 {* A& N, O% I7 F
& X4 N8 X# ]& j# l
        // VRC6
2 [9 u6 x3 S: o5 S- E6 T        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ E4 O9 k  y' q        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ N8 q1 f. J9 f, i$ E  @& ]' H
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, A" A* G' J- ^5 f9 S

% ^% R* v' B9 H% h5 F6 S! ~        // VRC7
( M5 n" ~  u2 ?3 C. @' ]        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
) \9 }# U9 H/ H' Y" k$ s8 w' m7 U/ P
        // FDS4 J2 L: u8 y& V8 c7 @4 U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& ~" b0 y2 _$ p+ ~5 M

/ `5 b2 ?) ?! R# w' T0 S        // MMC5
3 ?) l2 {; R8 L        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; [( T. u/ }7 k# m        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 v, y8 Q8 o. K/ S8 l: f
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 I' N; i8 S; k  ]+ Z. r" w( O6 J& j+ Q' z/ q$ k' Q" }
        // N106
* N  P. c: J% q9 h( c6 |        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 |* t5 I; r* y: `/ M7 g
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 a4 P- j$ J: j7 M9 g) b3 E! H        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! ~, l. F; `! y* h/ E! H# |+ P        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, `( L/ O; s8 @0 \5 D        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ B# a) A6 u( x5 c/ ^1 v( q5 x* @        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* g2 X  J# a1 z( A5 J5 D) a% B
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  k( _  i! N" a# r: o7 a/ r7 S
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 t9 k3 t8 {. R6 b0 f( j

/ O% E  o% ]; x        // FME73 D. y2 H- ]/ o7 @' E
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
6 W# F9 C1 w5 \" R/ W+ r  f        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 A$ ]& |# O5 C( J9 G! [1 b+ a        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 P6 V5 ?+ a) ?+ m
, n/ O* i6 f! y: v6 b" \, W( a
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;/ h3 O' ?6 g/ p5 f0 ^
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 `) F1 E. j: Q: x$ w

- q' C8 K, G% [/ b        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
7 P, s2 y7 ^6 p. P# e9 H" Z+ P8 I) A        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
7 f# `6 P3 s2 J7 J0 r) a- f                QueueFlush();* ?4 l9 r: G" u: ]" x
        }
1 `" ?, r- a" ^. M$ g: b% O: R, X& M
        while( dwLength-- ) {1 G& f( q% V- L- c& |, G
                writetime = (DWORD)elapsed_time;, j7 ^8 T7 U8 y! D

* j: h4 q$ x% z0 Y) }                while( GetQueue( writetime, q ) ) {
8 C, l" L) w3 \- h                        WriteProcess( q.addr, q.data );
2 L8 |( h( s& H/ o) u& \                }
4 J4 A+ _  C9 R! a( V1 s& P) C; e9 [3 l
                while( GetExQueue( writetime, q ) ) {! i/ W* i1 n1 s. a1 s( E
                        WriteExProcess( q.addr, q.data );
4 y  U) @$ u! f' _                }* [. K& C" V( `

) S/ d) H8 H' m6 y6 E                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME74 m7 Z2 `! f/ i) }# O
                output = 0;  p* @7 A- c0 a8 s4 G
                output += internal.Process( 0 )*vol[0];- e0 i3 E" q: @. c" V/ J" |+ n
                output += internal.Process( 1 )*vol[1];
1 j1 i/ a& Q' T8 i# s/ q5 e                output += internal.Process( 2 )*vol[2];4 [/ E: p7 ]- Q2 h6 [. N
                output += internal.Process( 3 )*vol[3];
: {* z2 `$ ~; K$ c                output += internal.Process( 4 )*vol[4];6 J) q& r; O( t1 O! s" M, B, ~

7 D3 ~) i% p+ G- t" p9 T2 f                if( exsound_select & 0x01 ) {3 A1 L! A- [) z- w+ @0 d+ C' B8 b
                        output += vrc6.Process( 0 )*vol[5];
& {2 L) [. l6 I5 d9 ]. j                        output += vrc6.Process( 1 )*vol[6];
& W! T: B; N; F: h/ V* D                        output += vrc6.Process( 2 )*vol[7];
/ m' |/ M  n: N  D+ h- J                }
$ j( Y+ o) r0 I1 G                if( exsound_select & 0x02 ) {4 G9 L/ q  z$ @4 y5 ?5 G8 }  f# s
                        output += vrc7.Process( 0 )*vol[8];8 d& t; Z, R4 B1 J5 L
                }' W% L: v  e6 c% [% H8 s
                if( exsound_select & 0x04 ) {) C$ R: u& P0 K" w+ y2 e' o7 F
                        output += fds.Process( 0 )*vol[9];
: G' b! N4 v$ M5 g; Y9 q) D# W                }; Y( G2 F" V* \  X3 X
                if( exsound_select & 0x08 ) {
! M* b' E% ~8 L; i                        output += mmc5.Process( 0 )*vol[10];
( C2 i- o; n% W* Y                        output += mmc5.Process( 1 )*vol[11];
4 E0 S) r% |3 {5 q                        output += mmc5.Process( 2 )*vol[12];' F3 V+ j9 D" N. z2 l# N* B
                }
0 [2 x( D  K, c4 e$ w                if( exsound_select & 0x10 ) {
3 ?' p5 l) q4 p5 \6 q                        output += n106.Process( 0 )*vol[13];2 I" s& v6 n- }9 s2 ?
                        output += n106.Process( 1 )*vol[14];
9 M, V1 w- z3 x                        output += n106.Process( 2 )*vol[15];* Q7 q) k/ w' {9 q
                        output += n106.Process( 3 )*vol[16];) Y$ B' ]4 Q" |- l& W; ]
                        output += n106.Process( 4 )*vol[17];
! ~1 ]4 z+ K1 Z  x                        output += n106.Process( 5 )*vol[18];3 \0 H: B, e; `  K
                        output += n106.Process( 6 )*vol[19];6 V; T. T# O) U% d
                        output += n106.Process( 7 )*vol[20];% t0 N, d: ]; z  [
                }
+ `, q, K$ P: }4 Y+ f                if( exsound_select & 0x20 ) {$ `5 W2 W/ @* g7 d' u8 O: h- W8 T" A
                        fme7.Process( 3 );        // Envelope & Noise9 l( t: n4 C/ V: E8 W- e2 O
                        output += fme7.Process( 0 )*vol[21];
) \' n4 u- D8 @                        output += fme7.Process( 1 )*vol[22];  T$ ^0 C+ H* @- N
                        output += fme7.Process( 2 )*vol[23];
  n+ z( @7 v1 J) w2 _9 O: e                }
! c2 ]0 T* P, _2 F: F
0 @* U' ^" k( G0 x& M" M                output >>= 8;
. C; x2 c- n$ W8 E' x% |8 v2 g: h/ O% d" V# y
                if( nFilterType == 1 ) {
4 }) B% E- f' o; U* t: ?                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)/ ^6 {$ z+ Q' r  j
                        output = (lowpass_filter[0]+output)/2;1 E9 J) Y5 N% P2 R" ^8 p
                        lowpass_filter[0] = output;
: O9 P6 x' s/ d9 U9 ]                } else if( nFilterType == 2 ) {$ ~3 e& N1 K* Z' Y/ P) d6 Y, i
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ ?; g/ F5 M2 A                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
% g" H% B+ C. q  F+ T& }8 R" S+ A                        lowpass_filter[1] = lowpass_filter[0];
- O- [& d: ]+ J3 G) s                        lowpass_filter[0] = output;2 }7 s! n# m4 V- Y8 }4 {
                } else if( nFilterType == 3 ) {8 e) f3 W$ d: u) A$ q
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)" g3 q  S1 n: k% t2 {" f  X1 u
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;; W% f3 B, l: m, B! v) }1 W
                        lowpass_filter[2] = lowpass_filter[1];
! t( }: {7 w& c0 O! ^: s; I6 b                        lowpass_filter[1] = lowpass_filter[0];
6 V0 }$ i2 O% a0 s                        lowpass_filter[0] = output;
9 g1 A& M. t0 e* }- h* e                } else if( nFilterType == 4 ) {  f7 m9 ?! Z7 W8 l9 K
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 n  ^9 c0 {9 j! Y/ J% ^2 K6 |* y                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
; d' d2 r, f: Q6 a% z                        lowpass_filter[1] = lowpass_filter[0];
: I+ i; D& u# i, l                        lowpass_filter[0] = output;
& a# G# P4 n: z" g6 S% Y8 o                }& z  `6 X' Y! Q! s( A! Q4 a* x4 [
# z' M" \, J: m0 x
#if        0, z$ S3 W+ G: B9 i7 v
                // DC惉暘偺僇僢僩8 t" o' I) H- K; l6 s8 _. t
                {
4 o- P7 I* g! a2 E; G0 p                static double ave = 0.0, max=0.0, min=0.0;# N) k& [# k# l. U7 d& `; P
                double delta;
$ d* i+ f3 u: d: \* o                delta = (max-min)/32768.0;( S# M# q3 |7 k: l* z% z
                max -= delta;+ s2 |( `) L$ f8 Z
                min += delta;: D; k; d& l: `
                if( output > max ) max = output;
$ ^% }6 f" y: x& R                if( output < min ) min = output;
& w' _" H, W; s% j                ave -= ave/1024.0;
" i+ l7 M! ^7 O! N0 b, m/ X+ s                ave += (max+min)/2048.0;
2 m  S) X6 s3 U0 i- ^                output -= (INT)ave;
$ Y# D) O  x- H( d                }4 F2 T2 n$ a; ?" ]) q
#endif3 P4 p8 }' [0 `
#if        1
3 T- u+ M6 r9 E5 y% z2 F                // DC惉暘偺僇僢僩(HPF TEST): v+ F+ L2 w' r# O" o/ b: b
                {
7 [: C& b6 M- a& ]' I3 Z//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& `& z  [" \' \" t) A                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 @' U' D- s+ E( w' F) q" u; u- G3 @                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 B8 U8 h* f- v$ [" |
                static        double        tmp = 0.0;) {3 k6 G* r" J5 O4 `8 y# ^( m
                double        in, out;. }8 b4 d' B+ D4 r( ~" B

) |) |& s! S/ `  j% B                in = (double)output;" f# |& S2 M% @" _' h
                out = (in - tmp);7 Y- y, i+ s; ~& o
                tmp = tmp + cutoff * out;4 F8 c4 R* h% N, C& s: ^

7 p( s7 d/ N* n/ h: {8 {5 ?# B1 D, o, h3 ?                output = (INT)out;1 q; r# ?) j0 e; W' k2 w
                }
8 z; e# T. Z# w% S#endif
" V0 H) V0 f  U' q#if        0: @# d7 {6 T. R/ F$ M
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 \3 q$ T  ]# k7 t+ s- _
                {
, d6 @' @" |5 `5 {6 }+ a1 j                INT        diff = abs(output-last_data);
  J0 H' V! H8 P0 O; Y                if( diff > 0x4000 ) {' L9 ~6 [. b8 D/ s  `& `
                        output /= 4;
) r, j* U7 J7 F  e# V  c+ U5 C: |                } else
6 f  a$ x* v7 [                if( diff > 0x3000 ) {' w; D6 h2 d" M0 C+ y, F* y
                        output /= 3;$ s: l( e/ ^2 R
                } else% b3 O2 H2 v7 u. h
                if( diff > 0x2000 ) {
0 P$ U* a: F: p2 J4 F( l" q) }                        output /= 2;! }  q; y5 n% g# W
                }
; L1 ~1 o% u& `- p                last_data = output;$ _+ z  R' P" \' K
                }
% D# \5 Q1 g$ s- M#endif) L7 J8 v0 m4 \
                // Limit8 G! L, g' n* X' d
                if( output > 0x7FFF ) {
; a" i3 l2 x. y4 o6 f                        output = 0x7FFF;2 f. c( q( S4 Y' m4 }0 _9 |
                } else if( output < -0x8000 ) {
* Z2 @& x1 q6 v$ b                        output = -0x8000;$ M8 ]+ W* \1 e, u8 `/ P
                }) i* X# k/ e5 d# x* L0 e

: M: Z& x5 d1 ?8 _- s$ ]  j                if( nBits != 8 ) {6 z  ?2 v+ H  Y( G& \- d- t
                        *(SHORT*)lpBuffer = (SHORT)output;
& T2 v( P+ m. C  C+ D                        lpBuffer += sizeof(SHORT);' o' F" l6 H0 D1 ]  d& M! ?: P
                } else {
. N& V3 l$ @. K8 A( Q5 z                        *lpBuffer++ = (output>>8)^0x80;* z6 R3 f" ~8 K6 t, }/ x, i
                }
7 T( H8 ]! T4 w2 \' l* K2 o# P/ ^( c8 a
                if( nCcount < 0x0100 )& G6 G' E6 ~, m2 }  p
                        pSoundBuf[nCcount++] = (SHORT)output;: Q- Y2 `$ S( T8 ^

2 z, }; l3 k3 d7 c//                elapsedtime += cycle_rate;. n* j" L0 r, g# O; w: l
                elapsed_time += cycle_rate;0 e4 S( k3 H! H. e
        }4 }0 c4 g" B2 U) r8 R! ~# g$ g
( p" w9 J/ s! i5 i5 l0 t- @+ Z
#if        1& K/ ~0 `) C9 `  h
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 w7 f5 f; ]+ U4 r
                elapsed_time = nes->cpu->GetTotalCycles();
! r% \8 ~0 [9 J! h. z5 b0 K; U2 W        }' R/ F6 U6 O. o. j% ?8 q8 [) f4 n
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 P8 U) i% v( r2 I6 {4 {0 E' V                elapsed_time = nes->cpu->GetTotalCycles();
+ e8 Y" w4 E3 _. d6 Y- r        }9 `  U. i8 ~' g% C) n# ^
#else+ t$ T) q' K, H  Z: W
        elapsed_time = nes->cpu->GetTotalCycles();; s" \4 J' O, u* b5 ^8 X6 h
#endif
! z0 v# A- c0 I1 d- v2 A# h* D}
3 K" w6 m. T; T" N3 L8 X' K4 E& ?/ `6 `1 ^- Q; D
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
4 M- K# l7 v3 |4 KINT        APU::GetChannelFrequency( INT no )
& e; P& K9 _; r" K! f* Y7 Z# O{
$ f) w1 X% J+ V+ x        if( !m_bMute[0] )2 S% B% {) b0 I& u  |1 I
                return        0;
# h% H4 M: p: e/ W2 P
3 l" G4 z: w" W: z. A; b        // Internal
6 s* g4 v" B  R0 \        if( no < 5 ) {
2 A3 Y4 K$ W# W. R8 ]) C6 l: F                return        m_bMute[no+1]?internal.GetFreq( no ):0;
& E- e( d+ R% m0 n' y( r        }/ w" Y% S( Z. o2 g  f. l
        // VRC68 {  Z( ]* A# E% u; q
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {$ W( e, Q+ R. Y* q
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
) z( {3 J0 s" ^; f5 e$ ~' h( g* v        }: b% _; v: ]6 L& {+ [
        // FDS
4 W/ y5 R# g( }8 ~6 G        if( (exsound_select & 0x04) && no == 0x300 ) {: Y1 L# V& i8 N( V% p& M1 ^/ m
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
$ B5 l- M1 B6 m        }8 {6 `6 u9 J0 K
        // MMC5
/ o6 a/ Z8 u' ~) ^        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) B+ N7 ~, X3 ?4 Q. `% O- r$ R* z& R
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;  }: L& h+ w7 N) |7 p4 y7 d
        }
7 |, W; s5 v! Y) ~& F$ h7 m        // N106
8 D, ~# E7 w2 j- S" v9 _        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
" Z( O1 L8 \, j2 [                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 O& d- r( K% ]
        }
8 n$ L4 `6 f  v        // FME71 z: Q! D9 H: k: m. {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {1 i$ }3 E' s( ]( [
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;9 w+ c( H! A4 M; U
        }
4 r' F$ g6 [3 ~2 ?$ R3 x8 |8 z# b3 x        // VRC7  H& [' m5 t! P9 T1 x1 p
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: s. a7 z- M9 Q& S  w2 a& [
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
5 s, l4 ~( u% F' b% w% f+ M* E        }
2 l- ~1 |. G' b1 O) k        return        0;
$ S: j3 {; B) _" V) ^}
9 b- r6 C! C3 [, K0 I2 |) R' K- T
// State Save/Load: v, G5 U9 m  _
void        APU::SaveState( LPBYTE p )8 `$ M; C8 Y! f! b0 I
{0 i8 K; e5 R; [1 k# I  }7 J
#ifdef        _DEBUG
1 R  Z& @* z* j, YLPBYTE        pold = p;+ D  X/ ]1 w- I- p
#endif# A) H0 i4 e. v8 {

& p0 j1 f! A; S8 w        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞, E9 F3 h7 c2 Y
        QueueFlush();
7 d3 }; P$ E- f8 O" n
& }% I1 k' j6 T/ w$ t8 s& @        internal.SaveState( p );
3 \. r  J4 M* `* y        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 T* E* {9 W  ~. d3 y1 ~

) t, `1 y0 p3 i0 M7 a        // VRC6
; B+ K- v* i# _# Z        if( exsound_select & 0x01 ) {4 n. ^( Q8 o% n1 t
                vrc6.SaveState( p );, B$ n# e2 i8 J8 K, P) e" O9 O
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding/ |) J4 Y( l- c4 j1 n" n/ c. K* N
        }! [8 t4 ?7 n7 R- X7 f% d- a! M+ Z
        // VRC7 (not support)
2 [  I0 K  k1 z1 Q- Y        if( exsound_select & 0x02 ) {8 w/ p( G9 T9 e9 K1 o
                vrc7.SaveState( p );
$ X' Z) T7 K* m8 ^- [- h                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- X' ^' P, D2 w! F6 n
        }' ?5 ~3 n/ t( }6 \5 B
        // FDS
; g+ p* j1 v5 J  s+ f* y        if( exsound_select & 0x04 ) {
  a6 L8 v0 B  q# ?4 }+ ]: c                fds.SaveState( p );2 p, u1 `2 @7 p; q% D+ p- i$ J3 _
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 p, y, k4 g1 G& |) x+ m4 c. A
        }
- z0 ?" A* {2 @8 [) m        // MMC59 ~! X. N, Y" X2 v, O  X& z
        if( exsound_select & 0x08 ) {0 M$ v5 P0 V9 Y4 j
                mmc5.SaveState( p );4 n- j% x0 R7 U. c, N
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
; R3 X) `1 ?, e: v& s# z& ]        }
/ x% }1 T. D, k( \! j& W        // N106
4 a5 H& D: l6 x9 A: I. U8 f: A5 _        if( exsound_select & 0x10 ) {. l' F0 l: [2 i
                n106.SaveState( p );
7 z; }4 d$ \% \/ O. e                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
& C" O# n$ }  S        }( k, Q8 C- O: M* K2 Y
        // FME75 c5 g( k; |. l% p7 }
        if( exsound_select & 0x20 ) {
7 Q  o, V9 [) g6 Y1 i) k: e* z                fme7.SaveState( p );
: {$ Y& W% H- [/ A! A                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! P/ e8 e8 e, e% n& W
        }" c! M6 U, \; L3 f* x6 f

0 \) Z& f4 j& q8 D% q" s4 U2 J- {#ifdef        _DEBUG
: o/ z  M% x; g* w0 O2 u. m6 j) x3 _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
8 N; u+ t0 _; M$ O, g7 Y( c#endif& E- E- @$ d6 i. U$ z
}6 b% P* L* ]/ p+ h' X! K
: V5 T) t! N& s! G2 R0 K  W# b
void        APU::LoadState( LPBYTE p )
4 V9 G; O# r, p) N- I{2 k# _, ]4 m0 T9 _8 J
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
; n" N' |) p7 p" ?! D7 w8 U1 t0 H        QueueClear();
1 Q+ h5 j9 ]5 N, E7 `% D4 @. f, J2 J- P) p) m& o" d' F$ l
        internal.LoadState( p );
6 c7 h& R- i- Y* W7 R3 @  e        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding+ n( ^7 h& }% H& k1 U9 J4 o

9 n$ B4 ?  K* i" V) J, X$ S        // VRC6' g: f8 ^9 h, }4 M5 _
        if( exsound_select & 0x01 ) {6 P# X8 X# I7 C9 [: N- w* b
                vrc6.LoadState( p );% I0 N  Y0 P' w8 X) {
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: g: \* M( P' k& \9 {4 o1 m
        }
# c! v& `/ e7 R0 B5 j        // VRC7 (not support)& ?% ~5 G  E1 r2 F/ k' i) z
        if( exsound_select & 0x02 ) {5 {: a2 |9 l: S: m
                vrc7.LoadState( p );
( E9 J* [8 F: A% M                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
6 _# t9 q% I* w! v* V        }
! C; l: P; D6 V  ~        // FDS
! I- s! V5 y+ x* W5 }6 v        if( exsound_select & 0x04 ) {1 L$ h0 W5 I# u% F- Q: d! b
                fds.LoadState( p );
  F- }" \# ^! N/ {" I                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 `8 \  i6 L/ _" Y% x        }
$ H1 v; @& @( `0 w% C# T' @% }& c        // MMC5
& q- S2 j$ G1 ^3 \; }; `        if( exsound_select & 0x08 ) {
& Q/ ?) m) g5 d! f, x4 C+ e0 f1 ]                mmc5.LoadState( p );
7 [3 g/ W& x# P6 f1 V                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" v! }& W" b$ ~  w! I' Y( C! L0 K
        }
% F7 F1 ?, @( ?$ f( N3 p; ?        // N106  D' L. E" J9 T+ w
        if( exsound_select & 0x10 ) {; y; C2 d, g6 m; }( l
                n106.LoadState( p );
: J: ~+ [2 E8 Y7 B                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  u; T! z/ L. e( O0 ]
        }1 U/ g7 J0 }% k& l( }) l' A
        // FME7
7 y5 B+ F$ y8 _8 r( v. J        if( exsound_select & 0x20 ) {
9 }. ~8 X  ^, L! j9 ]' Y                fme7.LoadState( p );/ B3 x* y; G+ S. O7 o
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
+ B+ n9 V$ S; j        }
: z$ w# _; V* t" i6 I}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
9 P1 a; x4 ?5 l) ?" E1 b可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
  J8 x2 r7 E6 y: t感激不尽~~

# X/ V7 e7 I9 n/ O# D+ q' ]7 @6 j" l恩 我對模擬器不是很有研究,7 C3 _) T# _4 J
雖然要了解源碼內容,可能不是很困難,
  S/ n  ]( d9 K% G# e& ?0 b2 F: t不過還是要花時間,個人目前蠻忙碌的。
7 x6 d" Q; l$ L/ ]) E& W# w
& |6 f9 O, l0 Q給你一個朋友的MSN,你可以跟他討論看看,
, L8 t  Q/ @- s0 n, P/ w/ S+ D1 r他本身是程式設計師,也對FC模擬器很有興趣。
; \/ ~; ^7 K" }+ m, z; v+ a; d. {8 B1 B8 m/ K( y. w" w* f$ |
MSN我就PM到你的信箱了。
" \. i$ ^- \* _7 X% j6 q2 w& @8 J
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
2 m* `- h' k$ c: v呵…… 谢过团长大人~~
  @' H6 Q+ k" @& K& X

# ~9 `  m  d- b7 ~6 I; W% s哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 / S9 ?% v: D$ u; ^6 M7 g5 L
团长的朋友都是神,那团长就是神的boss。

" p3 L3 B5 u7 Q* E1 }  A3 ~( B哈 不敢當,我只是個平凡人,/ A" c# s  M# ^, \2 V' {
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙5 l8 {4 i% v; C
ZYH
3 a; ]; ~7 A. t/ y) E& sQQ:4147343068 k' a  o" C8 C. P4 b
Mail:zyh-01@126.com9 c5 u: h6 T" |, X* C

. D) ?) ]/ y7 |+ U6 Z他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
. v. O! F+ |2 P/ s( ]- v; q再次对团长大人和悠悠哥的无私帮助表示感谢~~
) U1 P+ z% O9 K, S! w( w1 W
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-9 04:31 , Processed in 1.106445 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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