EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
$ a$ b( G* k( Y* x# `* C. Q2 g, qPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 I5 r& ~! ~7 L' g4 I0 N
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
5 K* I' I+ R5 l  |这里有相应的模拟器源码,就当送给大侠了~~2 E/ K, Z  r; |3 s7 f; f
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 0 d. z  T! X1 y# [% c4 o0 }: r
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 ]! m# w! L* s7 Y0 m8 u6 }8 d# J楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~/ n: H( A+ d2 W9 o4 D
这里有相应的模拟器源码,就当送给大侠 ...
! [; m3 b* ]4 U1 `6 K
聲音部分(Audoi Process Unit = APU):
& x  G# q( F' Z- H.\NES\APU.cpp1 Q, j+ u: q; c6 W8 l* ~6 p) R
.\NES\APU.h
1 R) {/ N  q8 @) l0 C0 s7 U3 O
" ~$ K5 h. B6 W  s& n
  l/ x3 M6 [" c5 K! l% k影像處理部份(Picture Processing Unit = PPU):  y2 C4 B8 K& r! H
.\NES\PPU.cpp
( Q" x# ~# a. l) O.\NES\PPU.h2 S' i4 I; P5 J: [" r9 T
6 B" w7 K8 {. z. ]# z8 X: b
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* Z8 m% a) w5 L; G& Q( J
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 \  m$ Q, l- M, f- v9 u
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% o0 n* z/ D) C: q3 C$ \9 M//////////////////////////////////////////////////////////////////////////( f, t7 O- P+ O
//                                                                      //3 d# g' X1 [1 j3 I# u2 e5 a" D
//      NES APU core                                                    //7 @  f. n# `' u
//                                                           Norix      //
: @5 R4 c' i4 E: C9 B7 m//                                               written     2002/06/27 //6 r6 @4 f! l1 ?& v7 C
//                                               last modify ----/--/-- //
  V* F- w8 M9 ~//////////////////////////////////////////////////////////////////////////1 M. F) O: U8 h3 f! H( l
#include "DebugOut.h"; D7 c1 z3 x4 \1 d0 i
#include "App.h"9 ~* n! z" `& K! ]2 U! a' T0 Q
#include "Config.h"
5 ?7 L5 [, s3 T" `/ j+ \) t( z( \, {2 ]3 X0 Y1 ]
#include "nes.h"4 u0 A4 y& e3 _2 ~2 o
#include "mmu.h"
, X, W$ V0 @5 n#include "cpu.h"
3 }9 n' j) I; u+ F* j" @#include "ppu.h"
  F% W* J- h8 O+ G5 F4 ]: E#include "rom.h". _) r0 E# Z8 F' F
#include "apu.h"
$ d. Z! V; z7 ?* r# t* i# T9 e0 b0 B/ I
, f4 I8 [$ e1 f- T// Volume adjust
% m: @) o7 {: \+ t5 \. V& p' O5 Y// Internal sounds" r  M/ S! k( v% P
#define        RECTANGLE_VOL        (0x0F0)
0 A: ~8 `# M6 z2 `( h0 s" s#define        TRIANGLE_VOL        (0x130)
( o; C! b" `- o#define        NOISE_VOL        (0x0C0)
! K" y0 f! G+ {- k+ S8 v2 o9 k#define        DPCM_VOL        (0x0F0)
+ q9 d0 g$ R% j. o5 n! I% w// Extra sounds  F' m4 L! {4 m* s$ I& ~7 c
#define        VRC6_VOL        (0x0F0)0 }6 i* M; f1 G
#define        VRC7_VOL        (0x130)
& s* Q* c% E; G$ @7 w#define        FDS_VOL                (0x0F0)6 Z# J+ ~7 r+ S& R* U  _& n
#define        MMC5_VOL        (0x0F0)
* s  S: q7 Z( }% b#define        N106_VOL        (0x088)6 e2 |2 z, s. y/ ]
#define        FME7_VOL        (0x130)4 |; d; ~) o& x% p
- o$ C) F; g5 T5 k: V  b
APU::APU( NES* parent )
" F& _  t* \1 E4 u+ \' G; }{
/ u( @* |' @( n+ q        exsound_select = 0;# L, R$ N; K0 G5 t
- D/ }' n4 A7 k
        nes = parent;" R& G  w$ U, \  m
        internal.SetParent( parent );
4 m" o  L- s5 o0 P/ B! {' }) _  |) R7 H1 a% B; f
        last_data = last_diff = 0;. O% E- r6 G3 D
$ n6 W4 u& L: |0 s! N5 [
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( I1 L, [: P, i! o  O1 T# {( |6 o

1 g# ~4 Q' y0 I5 N9 j/ q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
" t2 d) j4 ]( E' `5 }        ZEROMEMORY( &queue, sizeof(queue) );
/ u8 c8 b0 ?! f  P4 X4 D' Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );- C8 ^3 Z5 d+ j* |. [# ~
. y& K1 g8 i" z0 B
        for( INT i = 0; i < 16; i++ ) {( f: s$ n. K9 N* p3 o  v
                m_bMute = TRUE;
+ g  Q+ r$ Y$ V1 U( X; N        }# E  a) {+ r* n  r1 }- f4 h$ @
}
/ s: L  h$ R4 e1 I& C
( p( A, }4 G$ n: x8 BAPU::~APU()
+ p& v- }$ O8 }{
/ A, Q, J' {5 t1 r  }( Y}: k5 l+ @, ~% v+ e

4 E* f" f6 o8 @2 s" _5 S3 j" Tvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )' z5 `. r2 E! {, S4 K9 H
{( z5 {  p1 C4 i: Z# a
        queue.data[queue.wrptr].time = writetime;( q% G$ G0 o4 W8 Q
        queue.data[queue.wrptr].addr = addr;
. h5 \- C, N9 Z        queue.data[queue.wrptr].data = data;
0 G7 Z. P$ m, I        queue.wrptr++;$ t, D# L3 n6 s- W( W7 Z
        queue.wrptr&=QUEUE_LENGTH-1;
  P' O" W1 S+ ?        if( queue.wrptr == queue.rdptr ) {
2 Q5 v& Y: g. \8 @; ^( t- g9 Z                DEBUGOUT( "queue overflow.\n" );7 }2 R+ O1 F+ U3 D" w: Z
        }8 E, U6 D$ f* K( ~; H% p) b+ U; d
}
5 S9 A1 I; C) h% E5 ?" Z, K: @% X5 t$ ^, H
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )3 M3 V8 ?' d3 h; }" K' }% a0 Q0 t
{
0 i4 B$ b: M  c' i! b/ I# c        if( queue.wrptr == queue.rdptr ) {
1 O/ ]; l; X1 I1 r5 e0 @- d                return        FALSE;
6 q3 N% j/ I" c        }
$ [7 r9 Y: g- E# m/ }! z  q. Q        if( queue.data[queue.rdptr].time <= writetime ) {
3 x$ O4 O* l+ Y, U                ret = queue.data[queue.rdptr];! C5 e+ s% r4 L2 ~4 \
                queue.rdptr++;* J6 P, m! Z8 f* ~% n
                queue.rdptr&=QUEUE_LENGTH-1;- L$ c( U$ V' E7 A
                return        TRUE;
" `  l8 v: ]* P/ w        }- \3 B) r: R: N3 m0 |
        return        FALSE;" x1 Q) e1 X0 P8 `; J% d0 t# a
}
& h8 q# U! h/ N- H$ X8 y! l# b: w, A8 C. l/ P4 r9 [, C( C
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
' t8 _" p( F' g& X+ v{# i/ q. \3 I) ]& B8 L9 q) l
        exqueue.data[exqueue.wrptr].time = writetime;
3 T, v  h! s$ O* J; F1 c: \2 f        exqueue.data[exqueue.wrptr].addr = addr;
( N+ u: {2 J8 B6 V$ X: ~        exqueue.data[exqueue.wrptr].data = data;
1 [* |6 p1 i# W1 J        exqueue.wrptr++;' ~- k3 D, }; g0 W+ {+ F- L
        exqueue.wrptr&=QUEUE_LENGTH-1;
1 j2 k8 e/ P0 Y: ]        if( exqueue.wrptr == exqueue.rdptr ) {+ t8 b1 A0 [3 B
                DEBUGOUT( "exqueue overflow.\n" );
5 U9 z' E, @' K/ G) ?$ u. D% t        }) |9 @6 g5 z, z
}
1 C+ e+ B; o( n
9 x! @7 a  I' E0 qBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
- G, ^4 l& R2 W+ y0 q6 D7 V4 a. b7 {{7 O1 A- k* R; q$ D- Q
        if( exqueue.wrptr == exqueue.rdptr ) {6 Q1 F4 e, y* \5 v0 c3 h
                return        FALSE;/ A5 Y" Y7 x, w% X" X$ s
        }
" N( [3 b/ d( t7 Y0 _0 r        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
; o4 M# T% I8 S. s                ret = exqueue.data[exqueue.rdptr];5 R, y7 L3 d2 u) O
                exqueue.rdptr++;
( }6 w" `$ q! f3 f8 u' a+ H                exqueue.rdptr&=QUEUE_LENGTH-1;
  Z, `* m/ X, a# h$ S                return        TRUE;
0 W8 b8 L( L3 a: O! \. T        }
6 p. n! i+ `" U6 a! v: k3 Q: [        return        FALSE;
8 Y8 d/ m; A+ [+ k& U}$ k  ?# q8 R3 a- H/ q

( Y, v; @. K8 _/ {, Nvoid        APU::QueueClear()
1 b6 u& a# l% y: [% p! G: ?5 Z6 i, T{. l: {6 }" Z! i$ {& a& X' J8 ~5 x" f
        ZEROMEMORY( &queue, sizeof(queue) );' Z& P4 [: t" @1 _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' Z  A2 @; F% ~2 Y& I}
6 X  W; q" G9 @' L, G0 b5 y
" O* D! U+ [2 Q: M2 K# I% I( P, fvoid        APU::QueueFlush()# J% l, o+ G. b$ U: v; b+ p+ ]
{- w( G9 N& \/ B( N! F* S. d& D
        while( queue.wrptr != queue.rdptr ) {
4 O9 w' E4 C9 @( e% {                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
+ U4 T/ O# L; I8 a& g1 N/ y7 I) q                queue.rdptr++;, C* n2 B( ~" ^" i
                queue.rdptr&=QUEUE_LENGTH-1;
2 {1 P$ r& x: @0 j8 S8 s6 O        }& i+ T  V7 z6 i0 G1 U6 H
/ b; e! b, @% [- V- X
        while( exqueue.wrptr != exqueue.rdptr ) {5 ^9 \- z$ G& H/ r1 N
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
! p1 Q: n/ Z7 m; y+ I% M3 g: o; r                exqueue.rdptr++;+ C6 v4 A/ Y6 `! ]6 P( s
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 N4 B2 O2 v8 ?        }
" T8 Y& o! a1 W3 t}
9 \" g! v: K" N* u
1 u- v- i# x0 ], v9 s5 a8 H! k6 ^void        APU::SoundSetup()
4 x) `; c# a8 r. U: Y# a{8 L" j6 s' e/ W( X' j
        FLOAT        fClock = nes->nescfg->CpuClock;
0 E/ }- [' O$ N        INT        nRate = (INT)Config.sound.nRate;3 E" Y4 ]1 x& p! q# y3 X0 S
        internal.Setup( fClock, nRate );
0 W* M, I% L, g- C        vrc6.Setup( fClock, nRate );+ H6 G$ Z3 Q, g7 o- J3 a$ O: f* K" w
        vrc7.Setup( fClock, nRate );
" ?' p2 g5 L2 L, n        mmc5.Setup( fClock, nRate );+ S) X' l; M- l5 T6 |! j3 a
        fds.Setup ( fClock, nRate );
& G) x* b" N, K9 y( p        n106.Setup( fClock, nRate );$ ^9 `/ e9 N6 ~/ c* L9 P8 e1 n; a
        fme7.Setup( fClock, nRate );& Y- q8 C7 K1 e' j0 `  t* E; H
}
, t% H5 I( H8 z% j' a. W  A2 {2 u, o8 D: y
void        APU::Reset()
+ c1 v; p, a0 t5 i" `9 L) y{3 I. Q; T' k; z4 z: @
        ZEROMEMORY( &queue, sizeof(queue) );
) k0 g) F, l# O/ r# ^        ZEROMEMORY( &exqueue, sizeof(exqueue) );! d. t9 H  l2 `3 m

" l  X0 C4 h1 x* ]        elapsed_time = 0;
9 x4 T3 K. d- u0 A- B7 w: N+ ]; ~; y6 `
        FLOAT        fClock = nes->nescfg->CpuClock;) @# ?( [* d' ^3 r8 c
        INT        nRate = (INT)Config.sound.nRate;
! {( D8 d  ~+ O- n; v6 d; D/ i        internal.Reset( fClock, nRate );
6 O6 z1 f  B& a8 Y        vrc6.Reset( fClock, nRate );* m! C# V! x5 |4 ~
        vrc7.Reset( fClock, nRate );
5 n# v5 }. x, ]0 ~& o7 m/ d4 [        mmc5.Reset( fClock, nRate );7 f  c3 [( S: _% j; t8 F6 M$ \/ |, c
        fds.Reset ( fClock, nRate );, O2 E5 P! v+ \! j* w; t
        n106.Reset( fClock, nRate );
) ^! y* }$ a% k' X1 I; P  C& K        fme7.Reset( fClock, nRate );
3 o! M' @& b( |& V. ]( ?4 s5 W+ m0 m0 v( J: B8 ^- D
        SoundSetup();
8 a4 J4 h3 V: a}1 O# k3 A. n4 V" q: V
! O7 b6 B5 {: |) n
void        APU::SelectExSound( BYTE data )
& S" {9 }" Y7 W" G. f. |) _{) E9 [. Y# x8 B# a- }
        exsound_select = data;
/ ?# |; r4 |3 o/ ]: U5 N1 o}
) j! c, {& W2 @! W5 `' c* M7 O! Q; H5 k
BYTE        APU::Read( WORD addr )
- Z$ c8 d3 `: g/ H{# i! v2 X$ E* L5 ]5 @
        return        internal.SyncRead( addr );$ \! [' e3 B3 y
}
5 B  W' V# \3 ^7 ^" q# R. v. A0 U( L$ p: q' c. ?+ Y) f
void        APU::Write( WORD addr, BYTE data )
8 P, h2 {& e& V4 I{9 Q4 v9 e8 {0 d2 v1 o/ G( R3 p
        // $4018偼VirtuaNES屌桳億乕僩
: c$ p6 W5 @% k/ T7 f5 _, w( {$ w- v        if( addr >= 0x4000 && addr <= 0x401F ) {5 ]& i  e7 _3 @1 ^* w+ }
                internal.SyncWrite( addr, data );0 H% s* M" x0 @% o* o% |
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
. q' b3 s: v5 m1 x7 j        }! z1 R" w3 j" K  E2 g9 Z
}
6 I2 p! w0 V2 }! z1 s* m+ A
$ Y& {# \4 G; v, h/ _0 SBYTE        APU::ExRead( WORD addr )% M8 i* h& _4 q  U
{# S$ v2 x: C3 K% y+ i: [* A7 S
BYTE        data = 0;6 }- v/ r  W, q1 k5 X! J, `5 ]0 m1 @

4 j- `9 E/ h6 s! H6 e, V+ k8 C8 D: D        if( exsound_select & 0x10 ) {+ u9 }7 U$ s# b* n2 F6 ?
                if( addr == 0x4800 ) {) J0 D1 [$ N( M7 U0 E
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );' @$ G; h( b# J& a6 H- [* e9 h
                }, W7 ^: N! H$ ]& X9 S
        }8 Q0 }( z1 U9 G
        if( exsound_select & 0x04 ) {
% d" a0 E: M4 U# H9 L6 [' j9 ]; m                if( addr >= 0x4040 && addr < 0x4100 ) {
% q3 N: j' p- r9 r' ?. z& b) w                        data = fds.SyncRead( addr );% i) w, ~; E' o/ u; `
                }' r1 E* E. {' g! i  S* G
        }
9 v' F9 ?1 h' S1 O- S- }" `        if( exsound_select & 0x08 ) {
$ l" o3 y  J" D0 o  ]) M# F. u+ `1 c                if( addr >= 0x5000 && addr <= 0x5015 ) {" A# Z, v( a8 o, _; }, T* F3 ^
                        data = mmc5.SyncRead( addr );2 e! f! e6 C  x
                }
  w8 H, d" I: [. S- Q9 W        }6 V# e! w. s3 N4 s2 [$ ]4 w$ U& s- u# ^

7 |; p9 V1 P) Q% J        return        data;
8 b: E6 N* i0 `! o9 ]$ ?) F8 X" T' E5 \}( O  r  |( n! X% r2 G9 b

2 C& A% e8 v# `  p. [5 ?void        APU::ExWrite( WORD addr, BYTE data )8 q" W$ A; |/ h; G. [8 c% _
{
& x$ }: e( @+ Z( C2 `! m        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );% F9 R% j6 |- ^, D$ H+ l5 Z$ v

0 i) s- |" r" ]! K$ G0 ]. a        if( exsound_select & 0x04 ) {: }4 K* G4 [% W# g# I% K6 q
                if( addr >= 0x4040 && addr < 0x4100 ) {
$ h: P7 }: p9 ?                        fds.SyncWrite( addr, data );
8 G/ ^" T5 U+ E. X                }3 w3 B7 J7 U! f' ^
        }; I6 q2 t" U! P! z' g5 h; |

# Y$ N2 M. p* O- _# ^. l        if( exsound_select & 0x08 ) {
6 R$ F( ^" ~7 w5 w0 R) k7 x                if( addr >= 0x5000 && addr <= 0x5015 ) {
  y9 ~$ E6 H5 F& B! d2 }                        mmc5.SyncWrite( addr, data );
0 O& ]: \( B' b0 \: n" K; l4 n                }
0 N% O- I- ?' y% Z        }
4 b/ g$ n0 j* p' u! T" K}& ^0 r  x6 b$ I$ X8 O

& U, f- O! @* Jvoid        APU::Sync()
2 n* H6 K2 e9 V! S( K{
5 o7 T9 x) X% e/ z* \* `, w! p1 h}5 S4 p! H+ r8 F  A6 H) ~

6 H8 `, B! d2 b# n2 j, i+ q. zvoid        APU::SyncDPCM( INT cycles )
4 ]! t' H* R3 ~& I8 H  m5 A* a{0 A! f& V' \  M  g6 d# q
        internal.Sync( cycles );
3 h* X) N- C4 R: T+ W+ s8 L  J2 m. g) C; I% b9 o. O- k
        if( exsound_select & 0x04 ) {6 ?" ^5 e! `9 y8 E
                fds.Sync( cycles );
( V# R+ o8 c0 f0 {6 P$ ~        }; \! u  h6 x8 J, O' X: h; t
        if( exsound_select & 0x08 ) {
3 B* x8 O' [- i6 j* H4 ?5 b                mmc5.Sync( cycles );
6 ~  @8 V$ Z! S% l        }) H& k7 b  w& d; K& K3 z
}" T0 a4 {6 m4 d9 [1 k, {

- O/ M  _4 G$ z2 y# L3 xvoid        APU::WriteProcess( WORD addr, BYTE data )5 }+ X, k$ ^- n1 g% ^4 }$ A
{
! k. k( ]  T5 I$ o        // $4018偼VirtuaNES屌桳億乕僩
' H+ `' D' {, S        if( addr >= 0x4000 && addr <= 0x401F ) {
+ o( ^1 _) Q: R                internal.Write( addr, data );
* f# r; P1 W+ }, d8 q! W        }- \  j3 L* J9 b" O1 e2 u
}" d* w% }" g  O, P& r( z& f& K- ]$ H
8 \8 k' T7 C8 b2 h, D
void        APU::WriteExProcess( WORD addr, BYTE data )$ P  C0 e! p: X; i8 G1 b
{& ^5 o. j; b$ M! Y4 z
        if( exsound_select & 0x01 ) {& |9 K% ]* p1 O1 E0 t* p
                vrc6.Write( addr, data );% |$ v( B9 j6 J1 b, D( u  |
        }
* T. S6 @! R- w        if( exsound_select & 0x02 ) {
" p0 w% v! C' r- ~                vrc7.Write( addr, data );$ k- i! ?, M: w" R* `4 x! S
        }' U: m# W7 a% G0 D9 _" I
        if( exsound_select & 0x04 ) {* U8 }$ |1 u$ I: H: X
                fds.Write( addr, data );2 d9 X7 \5 T0 E- l+ S6 y
        }, q0 p& n) m% R/ ~0 f
        if( exsound_select & 0x08 ) {
$ ?1 C* r/ D- |2 I. C" h                mmc5.Write( addr, data );
5 q) H2 F7 k' P9 {4 @% `        }
$ `; }8 n/ A* f* p, G9 [( H        if( exsound_select & 0x10 ) {0 D* I) l; D6 T
                if( addr == 0x0000 ) {
3 B$ [/ b3 z7 i. e                        BYTE        dummy = n106.Read( addr );4 u+ y3 t% E, G. \
                } else {! j7 o/ g% K2 H( E6 e
                        n106.Write( addr, data );' T+ \7 C" y' s8 v3 |
                }6 G! F; W7 |# G9 m# q! [: _
        }; b! [$ S- ]* a9 ^6 m" F
        if( exsound_select & 0x20 ) {! D# p/ E, N: b+ T
                fme7.Write( addr, data );
: u9 ~) Z& U( y6 K6 x2 R3 h+ w        }
1 U: J6 |8 V' U. O+ B}1 |% E. x% l, w3 H2 b4 |

: C  X; j( Z# x/ M! {: @, E& `void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
6 p8 j* _) U' x7 H7 r( Z! `{8 t. p; ]& l9 D  E; x" V# |
INT        nBits = Config.sound.nBits;5 _0 B- ?5 I6 B7 x+ b! U( U
DWORD        dwLength = dwSize / (nBits/8);, {% Q! e2 \2 _, I. f
INT        output;+ b+ o5 O* k1 [6 ]! i
QUEUEDATA q;3 v7 ]: i" y- J3 M: C( g6 C3 \
DWORD        writetime;0 O& Y7 L( G2 I4 a+ X4 Z  @0 l' ^! u8 H

) @% r; r- c0 d5 ^8 D0 `. T5 m( hLPSHORT        pSoundBuf = m_SoundBuffer;
+ h( ^9 i' B+ p3 d( J2 m: jINT        nCcount = 0;
7 c, b$ w! B! i
) M4 W  g1 K# g- Z1 g* iINT        nFilterType = Config.sound.nFilterType;3 K: L: q* }: M' C
! Q% [) @. Q" `0 m7 r( j" V0 x
        if( !Config.sound.bEnable ) {( P7 I! V3 L% A" g( h7 M
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, D+ x/ Q. ^9 f* [- Z- l                return;
% [) ]& Z% J/ n1 ~        }
) p; N! F' ?: {' Q& W) h5 l0 u6 d3 o" }! f7 ^1 c
        // Volume setup  F7 t/ u( @5 V& ~" b9 P7 K
        //  0:Master
9 a( D$ Q, S% V, |( B# E        //  1:Rectangle 1
  j/ z/ p) Q. T+ w$ x        //  2:Rectangle 24 w7 M" ]" G/ Z9 e* U
        //  3:Triangle
2 _4 h' U7 V" R0 s! V        //  4:Noise) p2 E- C4 \$ g) l6 h8 J5 _/ @5 N8 C
        //  5:DPCM0 ~7 `# J1 p! l- Z7 E1 l" b: p
        //  6:VRC6+ c2 I3 }; l+ X: F
        //  7:VRC7
0 E* d/ O4 V" _: R- H. f8 R2 `. ~        //  8:FDS
% |& ~! D+ n6 N" a+ r        //  9:MMC5, g* b! M& Y! U- B" Y+ t1 [) a
        // 10:N106
! E4 I" b, S+ a6 b. L+ y  p* K) C# A4 ]        // 11:FME7
5 }) R% t# y$ }* |) M6 B        INT        vol[24];
2 o  b7 ~# a& c4 T( ~% [        BOOL*        bMute = m_bMute;' r5 O4 o: B! s0 E% I6 N8 T
        SHORT*        nVolume = Config.sound.nVolume;
8 l/ {% P8 U& c
5 k2 o) G4 g; @        INT        nMasterVolume = bMute[0]?nVolume[0]:0;8 G0 R( W: }4 _
  h" P3 Z, }4 `3 d9 Q; Y( R; c
        // Internal% s% O" z( M3 o+ S3 y
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;) H2 ~( n0 i+ z' J) x4 d
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* H% i0 Y/ w7 S- e- s3 r7 c        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
- _- B+ O& V& x# `8 b5 G        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' T) U/ F5 H# b  c4 s! Y% B$ u        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;1 W& f2 J6 Y( P- N9 ?2 Z
) @' J8 y) L# |. r
        // VRC6
6 [# D' {+ k8 d) d) _  c$ B        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 F( L* k% C7 n9 t6 Y2 j" h& e
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ @: ~+ W  d' t3 n/ Z" j; H' K        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 m: [% D# m6 q
9 g3 n% }, j4 A
        // VRC7
; z$ z3 |; e6 M% T2 N& l. n( w8 j        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 f% W9 C; o, ]

( q5 @' J) k$ P% c* s; I( X        // FDS: r' x: H7 n! c6 B% b2 n7 c: {
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
' o! p* h$ P0 e& G  a1 X
# ~2 R5 W$ I! M+ _        // MMC5
8 T' Z9 p0 S6 x/ R6 r        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
9 z3 B* g1 C* @7 \* E0 @        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* R5 ~* A9 c# `+ d! C' L$ u+ [) f
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! A+ e" p! K; N0 _
% w& Q7 q: G1 V+ g1 g        // N106* d! Q/ l( d5 d- F; g% H% n
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. v4 h& f% n& s, S0 y' [
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 P% U9 `0 o' j4 M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. V. ^0 m5 z  C4 {% U
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 l: C1 @0 q- @2 N7 `$ v        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 M# Q% X' Y, U- c1 j3 b7 M
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& n9 u& r8 y& O" v+ s( _9 W
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- f3 K3 [% W9 E% ?) L  w" T        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; X! S6 Q) D3 ~4 R

  u0 y3 u: `  L$ K8 L+ r        // FME7  `4 o3 `4 e5 l$ |( Z& N9 C
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* \0 ?7 L, D6 o0 h( q, p$ W% g        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" z1 @1 B; C* R! X8 e6 @" `
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 T; [  ?" N+ n9 C* V* q6 C$ ~4 S9 ]2 u% ^2 ]6 L: `
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% [/ q. q& ^+ W        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* ?. k( Z, E& f: T5 H% S3 P4 ]! Y- z) o/ w& ~
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% \/ O: |' h& x5 c$ z        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
) L' o* Y) s4 D/ B) u! o                QueueFlush();2 r- m; T1 Y7 y6 @) D
        }9 n' V9 s# ^) k6 Z* ?
+ n  d4 A# J* _" Q  {+ l
        while( dwLength-- ) {2 U2 Q( ^" z: O/ m% h! a
                writetime = (DWORD)elapsed_time;' p( s1 `/ p5 P7 M1 o

9 B; I. @$ }! M4 ^6 T5 h                while( GetQueue( writetime, q ) ) {
5 O/ H# e6 @/ ^' B$ l                        WriteProcess( q.addr, q.data );
( L+ E7 R0 H! z9 {- C                }0 `+ B" K  N) p' @5 R3 }$ v: t
7 h& U! K# g' d3 ^( R& C+ P
                while( GetExQueue( writetime, q ) ) {% a, b* J9 p3 i
                        WriteExProcess( q.addr, q.data );7 u0 E* p+ D% t/ |% O
                }
. {1 g1 @* ?" x# \+ T/ V' o: C
8 B3 O, G9 |) v                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ |! @* n2 |1 T/ J3 ~* P$ ~+ |, W7 N
                output = 0;( t* \4 d* T  X4 r0 m2 Z
                output += internal.Process( 0 )*vol[0];
7 @2 H0 H- p) I6 Y0 X  W$ i                output += internal.Process( 1 )*vol[1];
+ y& T/ X4 g4 A' Y$ x$ t                output += internal.Process( 2 )*vol[2];
  s# s  z" P0 q& a9 Q+ k5 L3 J                output += internal.Process( 3 )*vol[3];
0 G! a0 A  W; f/ W& i+ d" V9 b                output += internal.Process( 4 )*vol[4];' l! c- J2 e4 [$ }; f& V% t& Q
- a5 ]; P* s/ C. n0 U
                if( exsound_select & 0x01 ) {
. {2 `6 n2 D" H9 I                        output += vrc6.Process( 0 )*vol[5];
' I) \9 O* o( ]& X3 ?7 M# [                        output += vrc6.Process( 1 )*vol[6];
* u. W5 o) R) S+ e                        output += vrc6.Process( 2 )*vol[7];+ h" H: [+ `9 {, J
                }
- ^* C" m  l6 J" s. _                if( exsound_select & 0x02 ) {: J% K2 m* R8 _
                        output += vrc7.Process( 0 )*vol[8];
7 _( o* ?* X% B6 U' G                }1 F. j" b' g# G& u. h) D! |6 O) c
                if( exsound_select & 0x04 ) {
6 E1 @& k( x; M: t, L                        output += fds.Process( 0 )*vol[9];
- `5 ?. R8 q% {) i0 v                }" k( l1 `1 z% O% O, X
                if( exsound_select & 0x08 ) {3 k$ w, d. y2 D( A
                        output += mmc5.Process( 0 )*vol[10];
, l* _- z& W5 w/ v5 p                        output += mmc5.Process( 1 )*vol[11];$ L  U: ]; I# O
                        output += mmc5.Process( 2 )*vol[12];
+ Z9 r; c8 D" H; L* L                }
1 s! t/ Z/ y+ b0 g- S/ D                if( exsound_select & 0x10 ) {) H4 Z4 D7 B  M# N, p, j; W; G
                        output += n106.Process( 0 )*vol[13];, ]) B( y& n1 r3 t
                        output += n106.Process( 1 )*vol[14];$ Q+ K" o  k& z4 y
                        output += n106.Process( 2 )*vol[15];
! h6 b, F- c: ?& L2 C5 e6 R                        output += n106.Process( 3 )*vol[16];( s9 l) U% U# _* p0 u* h' h& A3 T
                        output += n106.Process( 4 )*vol[17];
9 R+ A/ U- c- B4 G                        output += n106.Process( 5 )*vol[18];, a, w4 N( q: T/ ?( x3 K
                        output += n106.Process( 6 )*vol[19];
5 e% C+ e7 M9 C2 {+ o# P( O0 c4 E                        output += n106.Process( 7 )*vol[20];
/ R' z$ o  I& V2 j% {2 r                }
3 {% k6 L' X+ M+ @6 a: @0 Y                if( exsound_select & 0x20 ) {
9 _0 I6 ^% U) }9 g2 v3 ?& T                        fme7.Process( 3 );        // Envelope & Noise- R6 ]! A8 T" {( X' {& j
                        output += fme7.Process( 0 )*vol[21];
3 ~4 M( r2 F$ |                        output += fme7.Process( 1 )*vol[22];4 E7 V1 c9 w1 A! o" B
                        output += fme7.Process( 2 )*vol[23];$ a2 w2 S0 l! Q. _; E" d) M) q
                }6 R- Y8 h/ ?% z5 T: R7 A- Q

1 H7 N! J  n2 t8 R                output >>= 8;
& D) o- T2 C! u+ Z7 c+ b9 A5 m, ~! m  h0 F) A  @# ?5 a2 U
                if( nFilterType == 1 ) {' V+ w2 P$ D  S5 p* c! Z
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
( c$ X$ c- H. `. K                        output = (lowpass_filter[0]+output)/2;8 t- |2 g6 q1 K  t
                        lowpass_filter[0] = output;3 y3 k" p! {  w- T& a4 c+ H
                } else if( nFilterType == 2 ) {6 Y7 B8 d) _. x% V2 v
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
' R6 z# b# h. I9 \( c4 z                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;6 |5 y. k% n. X- w" I
                        lowpass_filter[1] = lowpass_filter[0];
! \1 |% w" N1 a/ s- \6 C4 X( b                        lowpass_filter[0] = output;
" o* C" {! M6 y. t' G. ^                } else if( nFilterType == 3 ) {' K3 ?7 [/ F) p: A' [; r
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ F( v0 F( g" ^1 P' d, m0 g( S9 @                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;: j  o8 Z* Y7 {7 O4 @
                        lowpass_filter[2] = lowpass_filter[1];7 z3 D! a6 t5 K- l  O
                        lowpass_filter[1] = lowpass_filter[0];- S7 }9 @6 ]; J  v. |9 q; Q, ^6 \, }1 V
                        lowpass_filter[0] = output;; a/ A) R! q( L. G& [  [3 f! g0 `
                } else if( nFilterType == 4 ) {! {- j4 f6 q4 N% o/ E3 S1 l6 Z
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ R. e, g6 S8 {) i& w6 I                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
: A3 H- [% A; n: Z0 U# U$ a                        lowpass_filter[1] = lowpass_filter[0];
2 j) H2 _8 s/ G                        lowpass_filter[0] = output;
) u* L, q) n- W  s                }9 @8 r# j  |3 D2 r' ~

* X7 A5 u- C" P8 |3 j. w#if        0% `9 P" w  z1 ~& ^# P& R
                // DC惉暘偺僇僢僩
, j* g* k7 B0 h4 o% D( X: o                {
; v" f% ~' v4 L# R. \. R5 ^. K2 E                static double ave = 0.0, max=0.0, min=0.0;
& h5 L; K. w5 N% Y$ C                double delta;
! r7 p% G% A8 t8 t- S" N( N                delta = (max-min)/32768.0;! `5 g0 c2 W7 F$ \1 L0 h
                max -= delta;
4 {" z% v4 m, Z  _# X: G                min += delta;) L. }6 G, V9 D# J% t, @
                if( output > max ) max = output;
: F; O/ [$ E9 }' F5 f" f+ r. O                if( output < min ) min = output;
/ ~( g( p: p- \9 |( V                ave -= ave/1024.0;
; q  e) Y& N5 n+ V- o; t" I                ave += (max+min)/2048.0;
, g: P  d6 A6 J: V3 ?7 C3 d+ ^& K- [" |                output -= (INT)ave;
: F: W9 t+ r! W% |                }# O  ~. c# b9 Z3 }9 |9 D3 X$ i
#endif
. {) g+ L2 F& B+ r+ a. g#if        1
5 n1 ^% b, {4 f) D                // DC惉暘偺僇僢僩(HPF TEST)
6 e6 l# ]! \, N                {
9 Y( x+ {5 b+ n: [# f; a//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);3 @+ F. C$ j! v( k
                static        double        cutofftemp = (2.0*3.141592653579*40.0);) H+ D1 H2 w+ |0 I7 @9 [/ T: O
                double        cutoff = cutofftemp/(double)Config.sound.nRate;5 n$ q/ `$ ^/ B4 K4 Q4 y
                static        double        tmp = 0.0;9 J' b: W, G0 V
                double        in, out;
7 d( A$ X7 R3 _* Y5 y7 b" T& N3 j2 `! R+ J) n$ i
                in = (double)output;
* V1 v4 b, H" u1 c                out = (in - tmp);) H" P0 X/ R2 A. D
                tmp = tmp + cutoff * out;# H* c; M& p  s% m6 n
$ @) \, C" H" b, S- W/ b2 O6 G% i
                output = (INT)out;8 t6 J7 W# \! O1 `) {
                }
( `& Q% x' }4 d9 x  }6 [4 ]#endif
) N6 g& ]) |9 E$ h- Z7 w$ @#if        0
3 X' n' O5 s, |+ f+ V: K                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)' @* d- _& p" |3 {& X) t5 w# u
                {, d% w9 X, x& d
                INT        diff = abs(output-last_data);
; Q% O8 T2 h: F$ u9 {                if( diff > 0x4000 ) {0 l" l* L5 l! a9 F& X9 b( J
                        output /= 4;( M9 D0 @; s* F" m, g
                } else 1 C  Z% o! T$ y# y8 [/ v
                if( diff > 0x3000 ) {
: {( x$ e. c$ Z. S                        output /= 3;
' y5 \& f( Q" s8 P3 M                } else
1 b9 S- s7 G7 W* b                if( diff > 0x2000 ) {8 ?4 q7 O) `/ c1 Z& I- m
                        output /= 2;- f- ^4 c0 F# @3 N3 L2 Y$ i
                }
. g9 Q, |9 ?" g* h6 q( J                last_data = output;
9 `/ S6 e2 O% y! G* Z. i+ Y' m" R                }
3 b& f. {, `, C+ `6 i% }* H#endif; ?: ^6 z* v7 u9 K( e! g
                // Limit. P& t2 C& S! d: `; _% a, ?- P
                if( output > 0x7FFF ) {  u! v" X) N# w; d; @) h& c7 j$ e
                        output = 0x7FFF;4 z% c" T+ t$ s% P3 o
                } else if( output < -0x8000 ) {
; c; M' N3 K' z. t                        output = -0x8000;) \$ I, Y1 S* A3 ?
                }
% ~9 B' q: x' b: }3 k( c# ^; R3 a8 }  v
                if( nBits != 8 ) {
4 S9 o5 o) P6 Z) D  V, V; n( ^                        *(SHORT*)lpBuffer = (SHORT)output;
  s7 j1 n& ]& H9 U- L                        lpBuffer += sizeof(SHORT);$ O' @/ \& n( T6 X! b# ~
                } else {
9 d/ d8 c, u6 D& Z2 j- H3 l                        *lpBuffer++ = (output>>8)^0x80;
0 E. T7 |6 F0 v                }4 Q9 B$ _3 n5 a' O* q$ |

) O/ i& c7 C. \6 I) r9 Y                if( nCcount < 0x0100 )
2 G% ]0 J' z3 q# b# \) N1 i                        pSoundBuf[nCcount++] = (SHORT)output;- C# n) ~) w+ K4 u1 W" P

8 g+ y7 R$ c+ T9 y0 T+ Y5 p//                elapsedtime += cycle_rate;
; c$ X: t; ?# B# o* s8 U                elapsed_time += cycle_rate;
: k; y1 \  [2 Q8 i  P  K' t2 ]        }
- X4 D& L; Y9 U- w) T* S% ]. u: u* x. T( Q3 h  v
#if        1# g& B! c( ~5 G7 \% d2 `
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
# U$ b* L, @; ?6 D+ v6 n5 B3 z                elapsed_time = nes->cpu->GetTotalCycles();5 H& `5 O2 n* m  ]3 ]0 |
        }- C8 M$ {) m6 v% b$ U- s; S
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
2 l& V  |' B5 N                elapsed_time = nes->cpu->GetTotalCycles();
2 P. r6 J- e1 u* V9 [; |  ^        }
" {( ^; o+ O" a1 D2 m& i#else* G1 I8 P) s$ r, D% R
        elapsed_time = nes->cpu->GetTotalCycles();
7 l, s+ _2 Z9 r; m0 h#endif% S: M3 R% ~% C' [" L9 \- R
}
6 q" w& G4 E! x% h( I) o4 L1 @2 Z  f; f0 z% d$ h' `
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡); M3 u$ ]/ Q, a1 s9 L
INT        APU::GetChannelFrequency( INT no )# M- |0 k( q4 e  \
{
# b; _7 D8 x8 |, X/ S        if( !m_bMute[0] )
2 k' s8 e: P- w                return        0;$ S6 p) u8 Q3 f: [+ q5 D
; F. D, C6 Q) u) G1 N& m
        // Internal) o: x; K$ t) U, C
        if( no < 5 ) {: u% U7 ^% y5 e8 S9 J# v
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
% u# l. i, W, O) P) S0 N; }% A        }
1 O3 W! M1 D. `0 N- f        // VRC6
' ]+ N: b6 i  y8 n: y: Y        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {- m5 e- O/ b2 F+ G8 |& y
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;* i8 _' d. v8 M2 |
        }8 A$ P' {& R! k- H/ e0 K' ]
        // FDS: f6 X& r$ K' T
        if( (exsound_select & 0x04) && no == 0x300 ) {, E) K; j/ ^/ {% k7 }
                return        m_bMute[6]?fds.GetFreq( 0 ):0;) n6 N  ?: [9 B+ a/ d, i& O
        }7 ]. u4 O/ c7 L5 `$ w7 ~. s
        // MMC5
& a# `$ S) K: l4 i; h2 T) S* j0 N        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
. H  S& h+ Z) A! i" [( [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;2 H3 B4 l6 Z* w
        }
5 z  j( H& l' c. U( N; d1 M4 u        // N106: V' ^. u- Z* i- k
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
& y& g- {. I8 E3 D" ?                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;# N7 U& d" g# O" R; R; f/ l7 `% V: }
        }1 U& D# T! r7 S; o# b  N% j7 p
        // FME7
! R( C+ T4 \  }, h- Y7 z8 h1 Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
  j8 n1 I' W1 L$ S                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;1 z  y/ E) M2 M% ?; E- R+ E+ z
        }
0 u6 Q  A# A" |        // VRC7
2 Y  K, F! o2 S+ R' O8 ]8 E; \        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
- }. v$ P( k; L9 J$ c6 ^) F4 Q: V                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;" E" B' |- C, r/ [# f# @5 f, Q
        }
# O0 d2 }  K% A4 K) Y        return        0;7 [- u) [3 b; }1 `. k3 y& H+ ^  b
}
- ?: \" k+ F7 j9 d) n6 k1 B+ W, Q+ r) `$ F
// State Save/Load
1 H' D* ~9 F' O  d* tvoid        APU::SaveState( LPBYTE p )
$ Q' l5 N$ ^" @, P* N7 q) \{7 J% v! `0 V- g
#ifdef        _DEBUG& b; s& w) ~6 l  k# I1 E
LPBYTE        pold = p;4 O4 a8 T0 B2 b% f) Q1 \
#endif2 Q: v; m3 h9 l* m- ^

% w+ L. F" S. x' t# s& Z0 I        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞; m6 a  [! N- B; S- V
        QueueFlush();" N6 o. W" j- Q4 c1 w3 R

- \4 ^% X( `& m- @0 w        internal.SaveState( p );- k/ \9 @. d, ?/ a5 w2 Q, m9 E
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" u) l- l! \+ r5 R  N% M5 j
( L2 V; I  }# t        // VRC6
, ]5 Q& j; x% H) j9 P4 S! C4 p/ D        if( exsound_select & 0x01 ) {6 O" ^+ C: J2 O& R* u, G. _
                vrc6.SaveState( p );! N9 r% v& W* R0 W7 @
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 m5 K, v5 u4 j' L$ d! A- n        }
' @" L! x5 a! T  d1 v        // VRC7 (not support)' I7 H, B2 A) `( m' Q
        if( exsound_select & 0x02 ) {
6 P5 F' U$ x( Y( E: p3 Q                vrc7.SaveState( p );
+ E& C& p+ g3 C1 w7 r                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* y: b9 P" I/ e, y- V, r        }
9 j7 l1 g! I) V" ]: v        // FDS: T" N! b/ y( d$ S
        if( exsound_select & 0x04 ) {
5 l0 H4 s- o, B; j+ n" m/ d                fds.SaveState( p );
/ j1 ~; x. y( R0 B                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ G! P  o7 q5 l& ~        }0 G' B$ ]6 @8 A, w; t+ d
        // MMC5: k. \$ [, @- B! n( w2 M" p, J7 a! L
        if( exsound_select & 0x08 ) {
+ U/ W) u" B: A" s# P/ C; k$ c9 M                mmc5.SaveState( p );! O& x/ n3 e; l+ V
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" M6 l. B$ ?3 T5 m1 ~: \) Z+ L4 I
        }6 j% z) V' \: S# c! H1 ~! W
        // N106
9 J' K$ R0 g' O% W2 ~7 k        if( exsound_select & 0x10 ) {
5 P% ~4 y/ k  M( M# z% }% ^9 l                n106.SaveState( p );2 ?. u' i5 f4 [0 B$ ?4 W% [( U
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" a) ^0 Z9 ~/ G$ b: H        }
6 W7 T0 W& J# ^/ _- \2 \. {        // FME7
* c* _/ p7 |7 ]+ v: z        if( exsound_select & 0x20 ) {
8 D; R* b7 }/ O2 e6 v0 _+ ]                fme7.SaveState( p );) s3 Q- Z9 l% K! O1 b4 ~/ x
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; c# S1 K! ^$ K% ?
        }. c8 k+ L: v" n# F- H
1 B" u4 E* `6 F' f0 q: t* d
#ifdef        _DEBUG, g; H/ J% ^3 C2 ]- a
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );& Z) A. m+ P5 j- T/ H+ t2 R0 K+ H
#endif
: u- Q2 t( }: i. _0 G5 `2 O# J}: l& D7 _1 w: w' r, ?/ a' o; |) N

+ j' F( ?4 B# v9 r  e$ v) vvoid        APU::LoadState( LPBYTE p )' ?6 W7 V. ]: N5 q
{1 z# c+ f! C- H" O
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡* w: j! f( Q9 W4 _' R
        QueueClear();! O* B* d5 I3 N& s" d- S

0 C" o5 z' G  y/ \        internal.LoadState( p );) w# U; g1 H) R% B( E* a
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; O1 H* V+ A+ Y" z: W5 a" p$ j7 B' K- d$ p, R8 w
        // VRC6
: f5 A7 m" d' h& W5 G! x6 r        if( exsound_select & 0x01 ) {
$ E- E8 k; D- f5 t, [                vrc6.LoadState( p );
1 m9 s  u$ G. @7 O4 l. e                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* ^, ], V  d5 }1 d, K6 b+ T3 l
        }
7 t. x2 ?7 x; T. J  e+ k' {        // VRC7 (not support)
% {( Z3 ]) d# M! k$ g$ w        if( exsound_select & 0x02 ) {! n" |0 j: r8 H, r& _/ V( k4 q
                vrc7.LoadState( p );
% e* l4 k; N. {- ]- s' ~% u2 l# U# |4 B                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 g4 C3 H' z6 [* O9 B4 Z        }
* S6 }3 b/ i; b        // FDS
- O' s- ^) K% S' x        if( exsound_select & 0x04 ) {( J- ]/ r" u; b2 Z) }
                fds.LoadState( p );
0 Y5 o! |# d- a- o0 a' ?; i7 @! c) C                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& j  V8 S4 K; j7 k1 I% K% C
        }% Z1 m9 `2 X, O/ [
        // MMC5
" v3 _7 F* z' M; ~! i        if( exsound_select & 0x08 ) {
& U, J' g# A; }3 [0 M9 q, {                mmc5.LoadState( p );! k: M) f9 J* i, }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: p, D' U8 [8 J  [  z8 [5 {) l        }8 ?0 h4 Q5 w' F( f  W& b; P; ]
        // N106
) r* l6 j/ i$ j$ y        if( exsound_select & 0x10 ) {
* H1 K8 q) S, l+ j/ D& V                n106.LoadState( p );
. `; g3 P6 D( K( T) h( i& u! w8 G                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 Y: R* a. B7 h4 q  [        }
+ H- ]& X" k6 Q& u) _2 h        // FME7  ?  A/ t# ^$ A& X" I7 s8 u8 v
        if( exsound_select & 0x20 ) {8 g; F, e; J# j" p# K
                fme7.LoadState( p );  y- i& p% Y5 N: ^  A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 L& U2 ]( P- U% W        }0 E! m3 \" K2 N' W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ M" E6 |' |0 r5 d0 s5 X  C可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. e" K1 u7 ]# `  G感激不尽~~

5 ]' j  J- a! F, F7 e恩 我對模擬器不是很有研究,
. ^, D6 E1 @' |3 V' ?5 \雖然要了解源碼內容,可能不是很困難,
3 K8 M) K, R/ `- u0 H7 f不過還是要花時間,個人目前蠻忙碌的。9 ]0 m9 P  h8 [2 H6 H
# I  M( ?' z  g3 ?6 k4 P) B9 ]
給你一個朋友的MSN,你可以跟他討論看看,- p7 m  a% x! T6 ~) q- z$ o. r4 u: i
他本身是程式設計師,也對FC模擬器很有興趣。) W3 s  d8 d: ^2 P9 f3 I* B
! \/ {# x- L/ z
MSN我就PM到你的信箱了。' ?3 m+ T" ]: e" k0 s5 }5 q

* b8 z( `4 C+ ?希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* g% a1 B* E" y2 F* `呵…… 谢过团长大人~~

- E6 ?, S% ]/ t! M$ ?' s8 T" P
) A5 _1 l0 P/ v. E1 Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 l9 Z9 ?3 c3 \团长的朋友都是神,那团长就是神的boss。
9 c/ |( e6 f# ^: f; i$ Z
哈 不敢當,我只是個平凡人,
% P% T& A9 C$ C7 H2 M% R) w: H要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; m. D/ y* a' N" kZYH2 N, Q1 K$ q+ ]6 b5 O. c9 s+ g
QQ:4147343060 F0 i" l( i0 |; m  h% `: g" O2 [
Mail:zyh-01@126.com1 P& J" [# ^( x9 f5 g
# t9 P/ ]% u# l4 x$ {  d
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 8 @0 U) R5 s- [' o* T: Y4 ?
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ V6 \8 Q/ d9 ?2 L5 X' H" t! U
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-13 09:30 , Processed in 1.119140 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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