EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。2 P2 _8 l9 `8 C
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
; M; r' h' m9 N8 j) c  x这里有相应的模拟器源码,就当送给大侠了~~
, W/ X3 R% S/ I, \2 Q5 ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
+ Q& N2 d- u  P0 N* z! a! d5 _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
- m# s. K: `9 s  |楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% `: p  \+ C; D0 J
这里有相应的模拟器源码,就当送给大侠 ...

$ ?$ q. ~% g# [% i聲音部分(Audoi Process Unit = APU):9 ]* X' t8 G- B! {
.\NES\APU.cpp
) x0 x9 L2 j' K( x) D, Z* K. a* v4 e.\NES\APU.h. F" i# y3 |# g4 }0 \7 `- k) n7 ?

- z' U8 H) Z1 N- {: ], \
/ e: p: ?6 Q, L9 k# T影像處理部份(Picture Processing Unit = PPU):
% {; N$ A0 q8 R' x! X" }# r.\NES\PPU.cpp
2 D4 H( x* B0 i$ u% Z6 E3 R+ |.\NES\PPU.h8 J: u  I  m! Y% ^2 v! u! h0 K' r3 Q: O

& @+ y# H8 S* X& x& K如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 H0 z  {2 u6 [8 a6 p6 w(由于很多专用术语和算法机理都不明白,所以看不大懂……)
2 D7 ?7 p. \% f; l% Q- Q//////////////////////////////////////////////////////////////////////////5 P! `( B3 B9 l! W* A7 L- W7 J* w
//                                                                      //
& c& |, X, ^4 N/ K* Z//      NES APU core                                                    //7 d! z) y1 A6 S3 }2 W
//                                                           Norix      //
& \' d2 ~( B! v0 Z# A7 Y7 Q$ a//                                               written     2002/06/27 //; H; Q& P0 j$ ~/ I  u. X
//                                               last modify ----/--/-- //% R+ h/ P! o" n9 D* b5 @1 W
//////////////////////////////////////////////////////////////////////////- t) y2 ^7 ?& z, @$ g# ~% h+ w! @6 K
#include "DebugOut.h"
) [) n. u8 `1 w3 m5 j#include "App.h"/ D0 s0 u" M9 A) F( m
#include "Config.h"4 i, o9 Q+ h+ h

  Q$ X0 C" J- L$ n) O#include "nes.h"4 w+ P" g" ?' K, [: }
#include "mmu.h"
+ y; H7 x  Y+ c) L. v1 ~! q#include "cpu.h"3 R) |! g3 ]$ V' p% p
#include "ppu.h"8 B: Y/ ?* p7 t7 i- ]4 F) S* _: p
#include "rom.h") E3 g4 \- x7 s8 s+ L
#include "apu.h"
9 h' ~# F+ q( Z9 D, O( O" A' O6 @' ^) P8 o2 y! a
// Volume adjust3 A" l7 O1 x3 |4 ~6 b6 P8 f4 Y9 v# c4 ?
// Internal sounds
  e5 l$ A( j7 t#define        RECTANGLE_VOL        (0x0F0)
% Q% R! x- Q+ E/ r+ }4 r#define        TRIANGLE_VOL        (0x130). r" c5 X0 Y$ Y5 w
#define        NOISE_VOL        (0x0C0)1 H* z% J* O7 C
#define        DPCM_VOL        (0x0F0)
0 C- t( W& y* M+ o" n// Extra sounds
$ j2 B) U8 N2 Z8 `8 h3 B5 ~6 T) R#define        VRC6_VOL        (0x0F0)
! l. o; Y/ X4 J5 l/ j% L- V0 _#define        VRC7_VOL        (0x130)" Z  @7 w8 z$ }$ f3 l' ~! k
#define        FDS_VOL                (0x0F0)6 O0 v$ p% x* a( T, M
#define        MMC5_VOL        (0x0F0)
* G! a. v: i8 G9 b0 |$ u#define        N106_VOL        (0x088)" V; I9 i3 l2 q0 Z; ?
#define        FME7_VOL        (0x130)
3 y( L8 \0 R. R) m5 a
+ R8 _! n' G4 h, O+ e, ~0 IAPU::APU( NES* parent )5 U3 d/ `  ?. ?) G. v3 r# F
{
5 E% b" {) M; M. Y8 x+ R        exsound_select = 0;- n' n8 ^; b4 _8 p) Y

+ o9 p& ~! P6 ?/ j- R3 ~5 j        nes = parent;) s" {5 D: t$ r/ B+ @0 A  V. z( @
        internal.SetParent( parent );1 f; R1 [) S; s' N4 S$ P

0 q1 B$ r% T% C7 ?! e! ]        last_data = last_diff = 0;7 R' \7 n: P; Q5 Y+ F% O1 z% z

1 |  b; t% y6 a3 W! z+ C/ Z) L        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
- C$ j; g2 g9 t0 p3 d+ ]% J6 y
" w& v+ q& H; }9 A) i' E        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- F1 L( i  Q- ^; t% P) l        ZEROMEMORY( &queue, sizeof(queue) );
$ r% z  R, n/ x3 p! M  W9 c        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( ~8 {+ x: W7 T2 ]: e: H' Q0 Y6 [2 s$ Z0 \
        for( INT i = 0; i < 16; i++ ) {) K/ ?  c) c" o6 f  g- Z. G  j
                m_bMute = TRUE;
$ K9 v) K8 \! z6 n        }
7 D- {* u% U6 [7 A, W( q& ]7 F+ ]; {8 G  r}
" E9 ?, p( k( G1 L8 T7 s. b; ~# g
: u, \! @) V6 M. `5 yAPU::~APU()
6 W  a7 M, V" t# t{
# v0 @+ R. I; {$ H. o9 w}# L1 J! r- d9 K6 X8 \* v- ~2 X5 g
6 h$ ^0 X4 c) M% Z$ T
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )9 Z# ^' L0 j/ v& x
{
. V/ c7 k: |$ r: y% V) O        queue.data[queue.wrptr].time = writetime;) ?- o6 E/ }0 `- J+ O" s) p6 O" d
        queue.data[queue.wrptr].addr = addr;
) P* v- N4 C+ ^7 G        queue.data[queue.wrptr].data = data;
$ u! P: q/ M* d        queue.wrptr++;% o" P8 N$ n5 W. c( x9 F0 X1 g
        queue.wrptr&=QUEUE_LENGTH-1;: a4 @# {3 p) S- b, ^3 m3 D
        if( queue.wrptr == queue.rdptr ) {1 ]1 k1 Z. ^. y. S, K# S' s
                DEBUGOUT( "queue overflow.\n" );
. s$ O: B, j$ S) p/ b2 r        }7 R( ~- I& k8 w: T
}7 {3 x  \! I- M+ |0 Z: m; p- c+ M6 k
& w' M9 B: s# `6 m. m* R9 M
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ p! u% U6 w$ k
{
; e$ M% V( [) I( G/ ?% _        if( queue.wrptr == queue.rdptr ) {( T* e3 x# M* U1 n, R5 F. C
                return        FALSE;
& O; W# w4 Z" c/ R& W        }
# H6 f  }) ^1 u7 `" ?        if( queue.data[queue.rdptr].time <= writetime ) {& J$ f% [$ W& A6 h& L1 x
                ret = queue.data[queue.rdptr];$ E* C+ H* q5 J$ Z, p4 u
                queue.rdptr++;$ S6 k! a* ~0 r$ v0 U. t6 s
                queue.rdptr&=QUEUE_LENGTH-1;
3 M0 g! i) f% Y# }& b* a5 t% _                return        TRUE;2 Y! q% H7 h$ D9 {6 |
        }- w9 v% S- U( K% k' e: c( S& ~
        return        FALSE;
+ v: q2 f  o; g1 H}2 {; t% C  p# t0 u, ~. o' x
+ D1 y2 A1 j0 {1 L
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )/ {/ X* s& Y3 @" D! v
{% Z; s% G/ ^7 n( Q, p
        exqueue.data[exqueue.wrptr].time = writetime;
0 `3 C6 v" q+ k! w; T  W+ o( t        exqueue.data[exqueue.wrptr].addr = addr;
  U. U7 V4 x' j1 d/ g        exqueue.data[exqueue.wrptr].data = data;
2 \) V* S" X, ?6 J7 v/ V. ~8 D        exqueue.wrptr++;. g! a+ |9 @% ^; Y+ J9 m5 d5 k
        exqueue.wrptr&=QUEUE_LENGTH-1;3 S1 ~- \2 ^; _9 c+ J! l3 u* J
        if( exqueue.wrptr == exqueue.rdptr ) {6 \& u( j5 a5 L% @; V6 Y
                DEBUGOUT( "exqueue overflow.\n" );5 Z8 D6 n- Q! w1 L- [1 E
        }5 ?0 I& h: c- a& W
}7 k+ w$ e. M# Q6 F; X+ O
  x4 y- K8 A0 b; R; C
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )2 G2 V7 [; r% r- C; f0 F0 k; P
{
+ F8 S; n/ {+ k8 \9 ^        if( exqueue.wrptr == exqueue.rdptr ) {
; Z# I7 h: j# }7 E                return        FALSE;2 F- X9 G$ M6 z* ]0 U
        }
$ Q& x$ B" y- Z, _* n- n1 H        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
  a) y! H8 V3 S) j0 D                ret = exqueue.data[exqueue.rdptr];! X/ R- ~6 E2 b8 {! F
                exqueue.rdptr++;% \( b2 Z& ~3 p: J
                exqueue.rdptr&=QUEUE_LENGTH-1;
7 V6 i9 _4 F: R1 [) L0 I& l- O, z5 @                return        TRUE;" t. j  Q9 }( C- e7 Q' H% f- Y
        }
  n3 `8 j- [/ i) o        return        FALSE;
& [) \8 H% J' U  [}$ K7 d: }+ }  c2 r5 Q$ E& w/ p
7 T  W  D9 x2 N: X' C0 B8 x. _
void        APU::QueueClear()
8 l/ E+ }( E; |& x{
$ G' ^* [' ]- ]- q* ~        ZEROMEMORY( &queue, sizeof(queue) );
0 S8 h0 I( W2 J9 I& z0 H        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 G' L" Q( e. f) E+ \+ H5 g) |}
' _# Z9 Q( ]4 j4 c1 V4 @$ Y! X
* p* [3 e* d1 `& N( {) J/ s7 jvoid        APU::QueueFlush()9 g! p) {6 V- o: L) K) A" ^
{) l( y. ?; ]3 W
        while( queue.wrptr != queue.rdptr ) {+ G; B' Y/ p4 v; o7 s1 a2 a
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );( k8 F: a: q* h  u& B8 H
                queue.rdptr++;1 H# O, b0 ?- U" |- q
                queue.rdptr&=QUEUE_LENGTH-1;
, Z. c0 l3 N# R        }/ O, L1 h2 {. ~4 K7 c5 b! V6 O; O
, \" ^' o4 L% r; b& C0 y
        while( exqueue.wrptr != exqueue.rdptr ) {
$ W, |/ f5 v4 N! C                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );* d, V  I' K2 Q3 f$ I6 ~
                exqueue.rdptr++;) x9 X0 F" n5 `6 T
                exqueue.rdptr&=QUEUE_LENGTH-1;
/ z; v! o- h) R# h% x        }
7 \4 M, M* `, C; L' V3 [1 B}
+ Z6 E0 W* K: ?& G/ I9 u8 m6 s2 R( h! _3 o
void        APU::SoundSetup()
; W  a6 c7 X. y" X9 a{8 ]4 h4 v7 u5 f( u
        FLOAT        fClock = nes->nescfg->CpuClock;
6 F& I( A# Q- e' u        INT        nRate = (INT)Config.sound.nRate;
3 ?* W. q. n$ w9 _7 P1 x/ e        internal.Setup( fClock, nRate );
% Q& Y( a8 x% l$ J' [- T4 p/ _        vrc6.Setup( fClock, nRate );" Z3 F' [* e4 u: n1 T: |
        vrc7.Setup( fClock, nRate );' E/ G6 f+ Y/ a+ b2 F) ~% Y# t
        mmc5.Setup( fClock, nRate );
- T; g, a; `/ n, s        fds.Setup ( fClock, nRate );
8 R! o8 c) p0 E* ?& ^; f        n106.Setup( fClock, nRate );
2 ^  v( I" Q3 [  X        fme7.Setup( fClock, nRate );3 x1 |9 v0 M5 ^; w  J+ J3 g# L* @4 q
}+ n' h/ r: m: f/ j; u
: y  X$ o' \" }
void        APU::Reset()
1 C9 _- I4 F/ D3 W; O3 n. {* C{
, y' i6 y  @, X' \4 t9 F, i/ |        ZEROMEMORY( &queue, sizeof(queue) );
" o+ a+ O' x" y        ZEROMEMORY( &exqueue, sizeof(exqueue) );# |- X, k6 n% A7 x0 l5 V
# u  ?+ d, d  F' ?# @7 ]5 Z1 @
        elapsed_time = 0;% V% x5 w; w( W$ L7 k# e8 q9 n! [
( v+ g4 e7 E9 I: q: F- Z5 T5 Q, w
        FLOAT        fClock = nes->nescfg->CpuClock;
1 X1 O& j' d) V9 v( A4 o        INT        nRate = (INT)Config.sound.nRate;
6 k: ?  s( g8 O/ }( O        internal.Reset( fClock, nRate );0 ~& [" u0 _8 D! w& d
        vrc6.Reset( fClock, nRate );& x. e& [, U4 ]
        vrc7.Reset( fClock, nRate );
5 U2 p  v6 [8 x8 h, O6 b# Y( S) Z+ s4 D        mmc5.Reset( fClock, nRate );5 ~) t/ G- ?' O% T' O' \) {& b
        fds.Reset ( fClock, nRate );' k( n8 h3 V9 |, L$ F9 s
        n106.Reset( fClock, nRate );7 s% L( n# d1 m. N) E$ m0 V
        fme7.Reset( fClock, nRate );- B- ~- w0 |0 A( R+ \- l2 ^; p

( h7 ?' l+ h6 k9 C+ _4 y        SoundSetup();; ?, N, U4 b% Y1 e7 M" D# |
}1 I  N# d2 k% A5 P1 A& O; ]
' X; D7 K2 `( Q9 y3 z
void        APU::SelectExSound( BYTE data )
' L, _8 `3 q+ K: E: H{7 u* c2 M8 T* r: G: O& j; y8 R
        exsound_select = data;! a1 D' M# Z$ P. ^' i% V& n; O
}$ r. @. _/ m6 y

, U9 J7 x, Z7 U  r& V4 O2 WBYTE        APU::Read( WORD addr )4 _% K3 t1 t* e( D! J6 Y9 G
{
0 p0 {+ I8 Y! h: g) {! @" u        return        internal.SyncRead( addr );" I( \2 ^0 l! ?! |5 Y/ L
}
- U" a  T' i2 n9 o9 k/ O+ k# e0 g% [: U, R' r3 i. l3 _: ?# @: U5 a
void        APU::Write( WORD addr, BYTE data )0 `2 f  t5 Q) Y+ x0 A& [. D
{
4 I) }- o! E% g  j) b" S        // $4018偼VirtuaNES屌桳億乕僩9 F; C# s& Y& r1 f8 P% P
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 [* q, A7 `9 Q2 s7 O2 W! l                internal.SyncWrite( addr, data );
* r2 T" L! @9 I9 A. L                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
1 B! ?- o2 W& h; O, o9 @        }
: I7 j( g' c- @- V0 ]}
6 d1 |) p. s' t
- L' f0 ]6 @. `BYTE        APU::ExRead( WORD addr )- S3 R, s: U, N: l+ C9 o
{, [# c& D+ x7 U" r  M. d
BYTE        data = 0;
; N7 p& \# |9 @% J3 J6 z0 b- U  B4 x" e4 g# G# Z, _
        if( exsound_select & 0x10 ) {. n1 p' ^. z' Y
                if( addr == 0x4800 ) {6 N7 L; H9 |; N8 l" r5 P) l
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 V4 @. i- k( [4 u- o1 |- t- T                }
5 \: i- z! z& S* v! [# }        }/ U+ G- N) ]/ s. m5 k
        if( exsound_select & 0x04 ) {8 q/ T, C  Q' F, w8 q' B' N
                if( addr >= 0x4040 && addr < 0x4100 ) {# D; S+ I& b, n  b5 ]' G% a# `
                        data = fds.SyncRead( addr );
1 c1 S* b& J" V* h9 J3 ^& E# }                }
, g$ [+ A% ]% g6 j; _  e" M+ w# [) L# a        }6 s5 m3 R2 U) O8 f- ?8 z+ _
        if( exsound_select & 0x08 ) {
0 ?8 Q7 u. S" G& a                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 M0 K9 h. [4 v6 h                        data = mmc5.SyncRead( addr );/ R! M' t1 a6 p
                }
. o" E0 ~/ e4 U( Z# C$ K* C5 t  l        }, k  t9 D, Q. i0 T) B
  M/ t/ I3 ?, g0 Q
        return        data;
( Z1 o7 a7 p6 d! m}
6 K/ k/ B- y4 @& \5 `$ Y8 a' b; e  d) Z. N
void        APU::ExWrite( WORD addr, BYTE data )* o& m0 I& W" M# h( H# V
{3 d9 s7 L6 J* o1 ^
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );2 @2 j$ N) M5 n. ^/ t! y

- D! ^4 y& u( {& }1 s% `        if( exsound_select & 0x04 ) {
- E/ U0 c0 W4 U, N& C                if( addr >= 0x4040 && addr < 0x4100 ) {: B* n3 f+ k* T$ f; _9 T
                        fds.SyncWrite( addr, data );% l) @" F  @/ ~7 k
                }7 K. {0 @) k3 B3 V! F6 }5 _1 R" W
        }- K% G2 z# y. L+ ?
7 Y4 z( E( D; F' \9 ]2 [( [
        if( exsound_select & 0x08 ) {
2 Q' V* n( J/ [- a3 \                if( addr >= 0x5000 && addr <= 0x5015 ) {
: t5 ^, ?; F1 z/ p0 C                        mmc5.SyncWrite( addr, data );# k/ {2 G" t3 x1 C& K2 c7 S
                }; c* b* i: _3 z1 B2 ~
        }+ C. O; b( e# e' }6 _
}8 @- p6 G1 C: e
7 s0 B! ]/ V% X
void        APU::Sync()
7 x$ i4 ], N' {5 v& o9 n{
% y8 t: V/ N# C  ?, n) Q}# x8 a0 O! |% c0 S. f3 ^  h
0 C# @: W* V8 P' b: h: r9 A
void        APU::SyncDPCM( INT cycles )1 q! j+ _7 @, J4 K0 Y1 Y6 d6 S
{. K! E3 [) Y( N% C: b
        internal.Sync( cycles );
- ]" j+ t7 `2 U/ d) Z  P5 {! W' j
( V6 p$ `! a; m' k        if( exsound_select & 0x04 ) {  E7 _( A3 |" m, T* V0 P: h
                fds.Sync( cycles );# F' K: C* _- S) P
        }3 u1 j( B, ~, E- Y) ^- @  d) v
        if( exsound_select & 0x08 ) {
- C1 m# ^' V5 N8 z* _9 f' d6 z                mmc5.Sync( cycles );- B+ x" M3 {, ?7 k8 n
        }
. M5 }! P& O. I2 t* g}2 s1 J  r' Z2 ]: }0 D6 n1 J( T4 ]& n
* \+ Z8 G/ U) D3 L6 L; [* ]) K- K
void        APU::WriteProcess( WORD addr, BYTE data )3 B4 v" N9 N: r! M/ Z* `
{
5 ]4 {$ Y6 o  X) b; _        // $4018偼VirtuaNES屌桳億乕僩3 h; _8 t4 ]" k' w0 \# {2 m* h
        if( addr >= 0x4000 && addr <= 0x401F ) {
/ E; k# p# H/ P9 @, x                internal.Write( addr, data );
/ x% A$ ?2 O+ A        }
0 Y4 U2 b: C& i% n}* k' K) b& V# V8 R; a

' w7 Z' B+ K" F5 q; xvoid        APU::WriteExProcess( WORD addr, BYTE data )
% {, C( }, M) r# ?& P* w6 E{" I3 }& x+ l3 Y; C! |
        if( exsound_select & 0x01 ) {
7 c# U- R# v0 @- s                vrc6.Write( addr, data );% u: k0 v! d) Z' c  B. e+ O4 j2 h, `
        }% p3 x: [. o8 s1 K3 o
        if( exsound_select & 0x02 ) {
2 j8 n$ _5 r& o6 x( q6 B                vrc7.Write( addr, data );/ q8 [3 I) Z8 x
        }
7 A& ^$ f5 Y* G. V4 F; R' @        if( exsound_select & 0x04 ) {/ r: @4 [! ~4 |8 g( c7 r
                fds.Write( addr, data );
! j4 u/ K: O9 j0 p        }6 E+ a, x$ y- `! g. q% N' i
        if( exsound_select & 0x08 ) {; }# y, B9 L1 S5 w/ [
                mmc5.Write( addr, data );
3 e; ?3 S9 J; k$ ^( U, I) C        }
$ a+ R4 g9 }# P  c) F  v' s; i        if( exsound_select & 0x10 ) {
3 ~! |1 N8 V2 n' ^( k2 e3 l+ N                if( addr == 0x0000 ) {: |/ o3 H/ H. X; s1 I$ E& [
                        BYTE        dummy = n106.Read( addr );* y0 z, }$ T8 Y- k- G8 t0 M, F8 `
                } else {
8 _) Y: ^$ A/ F8 M' \. ?" A                        n106.Write( addr, data );
3 J9 F! U) ]6 ~/ Q% a                }0 ^. I/ {! t0 u$ Y: [
        }
/ }/ K3 d+ h$ w' D2 Z: M        if( exsound_select & 0x20 ) {' T6 j, _* [: i. x' `
                fme7.Write( addr, data );
8 j0 Q; o6 o( `" h# F        }+ z' h' I  X0 F3 e2 B1 M) ?1 E
}, p6 [$ w: s) c5 g. P2 G

% M/ y8 z( _) I  uvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
( Z6 p" D) a3 E& d+ v+ L( `5 t{
8 r& n" l9 l9 @  w' IINT        nBits = Config.sound.nBits;: s6 k2 Y2 M: ~( {1 l
DWORD        dwLength = dwSize / (nBits/8);
: x" d; U5 b! j# rINT        output;9 S5 _! g( F6 D! i2 ?1 ]
QUEUEDATA q;* Z: G0 j' m0 I+ m# r
DWORD        writetime;
: o4 `5 p, Z. P- r; x# K6 N- v& V& s5 D, R4 z) U+ I* k8 Q
LPSHORT        pSoundBuf = m_SoundBuffer;
; ~. p/ ]% f, C) ]6 GINT        nCcount = 0;- W" M& u2 W) h- f) k

+ m: C1 W( g, d5 C" ~% V! ^3 EINT        nFilterType = Config.sound.nFilterType;( [; g; c& L8 C- a

7 v# u* T9 W$ L' E: y, a7 `        if( !Config.sound.bEnable ) {! s0 B, P- {1 A
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );4 x) x2 [+ m" U; Z. ?" e8 ?2 \
                return;% E; C3 G! `5 R
        }& L& }) q$ a% b1 N

$ W& i; e7 k$ Q/ U        // Volume setup( L. e5 i( a( e6 Q1 M% e' z5 r" Y( Q, S
        //  0:Master
7 F/ e5 d9 ]* q$ s! t+ ~, }        //  1:Rectangle 1
0 o) _9 k& I8 N        //  2:Rectangle 23 D, h0 [1 ?# @8 i0 Z- R) c
        //  3:Triangle
- ?! B3 G' W' L( ^0 `        //  4:Noise
( H% L  q5 c+ t) `        //  5:DPCM
$ r/ |  }! V/ B5 ?        //  6:VRC6: Q( h) }/ y/ q1 c
        //  7:VRC76 O) C+ E: T: A+ u  S' p
        //  8:FDS
  p2 V4 P% R% K& D5 g# b) A* }7 i        //  9:MMC5/ ^& s* v1 t  X1 ]9 d
        // 10:N106
  v, f/ E8 [/ Q% h, F& f( p        // 11:FME7) y+ t! u3 |2 B2 [  d3 m
        INT        vol[24];
7 O& z$ Q# v9 ?' O        BOOL*        bMute = m_bMute;1 P' ?- _2 C5 f6 j4 ?, D
        SHORT*        nVolume = Config.sound.nVolume;/ h, G) W. L0 f; ~0 X- B
7 `, E. N( ^5 s  J4 f6 U" K
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
  c7 Y+ S5 C: m
* f' I: |4 h$ X0 K( F  h        // Internal
7 f3 m+ {7 v* G, B        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 s: O4 ~: d2 o* d0 k) g
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;2 A$ C3 c; [9 E& D' @( ^: V4 P  `
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 L( L( c6 ?- C& a$ ]3 [
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;& N8 V9 _8 s" U! G
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
* z# a, Y6 E3 O/ i0 e2 V7 w
* c% j. S4 w+ y/ y        // VRC67 z+ g$ S7 M8 [* g: _- u1 d
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 ~# I( s- Z  E9 e, |  H" f        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  T3 n8 s' p" D: l5 `! T/ W        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) \. U) B- l4 ?3 w

5 `& q) H, A7 h' \2 e: d7 N        // VRC7
1 `2 N8 w3 E7 X9 \  H# h        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. w2 O, S' i5 L0 Y- g! b9 U
9 k4 t; w. y/ @$ ~
        // FDS
  d/ y2 d2 F6 O' t        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;( v2 t! l' h! @2 R% G( n
3 }' ~. c4 l; b* c7 ]( z
        // MMC5$ w1 b+ w1 w8 ]* ^5 z* X2 h2 F$ l
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% Z" y1 c! |& e        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) g* r  l6 }4 M$ t+ ~        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, e: W9 e; S+ e8 V) E! Z
  C: V! P& q6 t3 t. e7 z
        // N106* w3 q  P* E* C5 C/ F: Z' c, `4 I% z9 M
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 a3 J- T, p* G$ q+ u  a( J        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 K1 `8 x$ Z* ?/ Z, }        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& ^+ {" Y7 c# v+ P; q5 w. H' x  ~: w        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 g+ i& F5 _/ {; _4 }1 c! S8 ]$ Z        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 v: L- B! T2 c; o: z* b4 g
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: y+ F. C$ w9 O* N, G1 j
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: t$ ^; A) j, l: |        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 G/ q: p( ]: ]5 u$ _8 ^6 r' `' K
6 y& k/ }* `' z4 y/ I+ x: `
        // FME7
/ }5 i: E  p' I% G' y$ L( d& L        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) q9 l, q, l7 L/ S        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 B9 ~9 S5 W  I        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
, U" `1 J7 O6 h
% K  c1 ]7 z) B' s//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 s& C: U. B- {2 V/ A! Q; f
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ _4 \6 y" o3 n
! Y" A3 S* A1 S; ]( q& n        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
1 t6 J9 D! e/ h1 s- X4 \        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
7 K! D/ p4 S  F+ P6 w0 e                QueueFlush();
6 S3 h3 J- h% q        }3 o9 H: P* d. P. C6 P% ~
& e. |. P3 a0 g0 D% j" z
        while( dwLength-- ) {9 \/ ?& v/ R" _, x# o+ y6 d' E
                writetime = (DWORD)elapsed_time;9 M& i5 k" |8 H* o0 h; }
! q8 k/ d1 o3 W, S0 ~; _
                while( GetQueue( writetime, q ) ) {8 H) a, G. j0 W6 Y1 P
                        WriteProcess( q.addr, q.data );
4 r! k& B6 O, [% p# u2 r6 M0 b) v  ~                }
/ I5 _' M1 Y9 v. l) u4 A7 K( g$ S9 ~. J9 Z7 H- `% y
                while( GetExQueue( writetime, q ) ) {! l, j0 ?* k  F( O( E5 j4 _
                        WriteExProcess( q.addr, q.data );" S6 Y4 V: K0 V
                }
2 X7 C% w- D3 y1 S
2 U, V% j* f) x8 m( i                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7! O+ n4 _3 g2 l  v
                output = 0;
3 h; @2 x1 y9 h                output += internal.Process( 0 )*vol[0];! d7 c% n, K% C
                output += internal.Process( 1 )*vol[1];
+ M/ N3 e! d9 X                output += internal.Process( 2 )*vol[2];$ @5 e3 E7 T- |, O, A; v
                output += internal.Process( 3 )*vol[3];
0 K7 U( ^8 w) T8 [$ o/ e9 e                output += internal.Process( 4 )*vol[4];
8 s' ~+ [: e; Z+ \$ m3 m
4 M/ d: b/ N* e' x                if( exsound_select & 0x01 ) {' ~6 I; _8 ]/ p; s  n
                        output += vrc6.Process( 0 )*vol[5];! H+ R% |6 g0 C
                        output += vrc6.Process( 1 )*vol[6];
; m$ K# r' C5 Q                        output += vrc6.Process( 2 )*vol[7];( o; m" }$ X$ m* }, F3 y
                }4 W1 W9 P" ^0 S: y
                if( exsound_select & 0x02 ) {4 F: V3 y3 d9 @- b$ Z+ u0 Q/ m3 q
                        output += vrc7.Process( 0 )*vol[8];/ J- R# h1 Y4 N: n% g
                }
( |) ^% N! o0 i2 y2 ^+ B9 ^                if( exsound_select & 0x04 ) {
7 i# D$ L$ V* V& Y, ^7 E( j6 k0 d                        output += fds.Process( 0 )*vol[9];7 T" q0 I0 R$ V. v0 Q5 m' U* j
                }# \( O) L1 W  ]5 J- o
                if( exsound_select & 0x08 ) {4 @7 |# L3 d" A* r4 |8 Z
                        output += mmc5.Process( 0 )*vol[10];" O* z# h5 A  C# `
                        output += mmc5.Process( 1 )*vol[11];
! T: [- o! d. W                        output += mmc5.Process( 2 )*vol[12];
2 |& P! T5 g$ I% Z( U                }0 d, |2 K5 o( t( e8 \: B+ `8 Y
                if( exsound_select & 0x10 ) {0 n$ O/ D1 m  i5 \0 f5 t  A
                        output += n106.Process( 0 )*vol[13];2 N0 y8 k8 L& G8 S5 z% G
                        output += n106.Process( 1 )*vol[14];6 x+ o  F5 k; Q4 h3 n# t
                        output += n106.Process( 2 )*vol[15];
5 r- [6 _; s: b                        output += n106.Process( 3 )*vol[16];
2 N1 ?1 f# C& R                        output += n106.Process( 4 )*vol[17];
' T; k5 j7 I+ A) Q                        output += n106.Process( 5 )*vol[18];, z( ?3 t9 i" S( I
                        output += n106.Process( 6 )*vol[19];
; R7 `5 I) O: m3 G3 G& k! ~                        output += n106.Process( 7 )*vol[20];3 N4 s4 {* v5 ?
                }1 c* V! e8 y4 o$ o- y0 v  g
                if( exsound_select & 0x20 ) {
* z' ]& |, v5 E  H1 @                        fme7.Process( 3 );        // Envelope & Noise* R' c6 s6 S1 }' R; {
                        output += fme7.Process( 0 )*vol[21];, e! u: [0 f$ ^3 [
                        output += fme7.Process( 1 )*vol[22];
: C! Y% j  L+ z3 u7 t  c. F                        output += fme7.Process( 2 )*vol[23];' `6 q5 U- S0 r7 j; ^: l
                }
: W: ]& B0 y$ B
# m# R/ w1 _+ c% R* k                output >>= 8;
+ e1 M0 i" c3 Z( h; o
! o! j* z1 b6 f' g                if( nFilterType == 1 ) {
) u9 z$ J1 f# a- t% Q  n. O                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 E0 I6 F0 v1 V
                        output = (lowpass_filter[0]+output)/2;
5 J& E9 q3 S# \8 u1 `( u                        lowpass_filter[0] = output;
, c; k: t7 n: p) N% _' S                } else if( nFilterType == 2 ) {
7 e" G6 h( }" e" j, P( c. M                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)' Z2 H" E5 c" ]
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
' x! \6 J' O6 n3 ~                        lowpass_filter[1] = lowpass_filter[0];
2 p' C/ {0 R5 j                        lowpass_filter[0] = output;
8 u) c+ j/ l2 o! C( D% i1 k                } else if( nFilterType == 3 ) {
- R) f/ D; C& }' s+ b: Y                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ H# u- }1 s  p$ S5 c( Y, t: J1 ~$ H/ {
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;' ?. A2 @" K0 e4 J! k- P# ], f6 f* _
                        lowpass_filter[2] = lowpass_filter[1];
% m1 T4 z$ d9 V                        lowpass_filter[1] = lowpass_filter[0];
/ O' c& u0 I7 w3 Z/ {" X' A                        lowpass_filter[0] = output;
- p/ w9 ~" T+ \9 K9 j' b+ u9 l                } else if( nFilterType == 4 ) {/ A9 `- e% |) O5 T
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 y- Q' ?8 e) S3 y+ P
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;3 W& O, U: f% a4 l& E5 w" C: z
                        lowpass_filter[1] = lowpass_filter[0];
+ h1 e; y1 Y4 {  |* \3 `( J                        lowpass_filter[0] = output;( H, g$ ]' c" Z$ X  _
                }
1 a$ }0 ~2 Y5 Q2 i, |0 M! o5 p( ?8 E$ j8 W) J
#if        0
1 Q6 d) f' I3 R' [9 Y6 M                // DC惉暘偺僇僢僩
( m# `! y5 F8 M4 L% j                {: L6 V% }5 v( k
                static double ave = 0.0, max=0.0, min=0.0;7 I& I1 ^- E" [' H
                double delta;: K/ I) p, r2 [% `. V5 _
                delta = (max-min)/32768.0;
4 X9 K- G8 r' t  t( w& X4 U0 Z& b                max -= delta;
% j) P) u9 K7 s/ o# b) ?- J                min += delta;% l1 i+ E8 @8 b4 a
                if( output > max ) max = output;
3 k! X% [  j% Z2 x: i                if( output < min ) min = output;" n% c# I, A/ s% O2 Y* r, G
                ave -= ave/1024.0;
; W9 v' t9 I1 u  E                ave += (max+min)/2048.0;
5 X, |& ?$ O; f1 Z                output -= (INT)ave;
1 R2 M3 `8 y3 K1 g                }# ^# {2 I1 t- i
#endif4 N+ T' S& D) r" c
#if        1
0 [# S! ?% y7 s. w( _- {; F- ~                // DC惉暘偺僇僢僩(HPF TEST)/ L) E) p* h  b  V
                {
- [- T, k5 I' I//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 E4 U8 i$ Z/ Q/ Z# H# d                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 f' B6 q) {; ?4 w( z/ X7 h
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
2 b' b* K7 J, a0 J1 b5 [7 G& \% a, A% V                static        double        tmp = 0.0;
+ y& W! R% k! V" d  X! e                double        in, out;
0 D3 n) X9 V& M. X2 W3 M' }8 B. T
% w* Z  M4 @4 I, R+ f7 B                in = (double)output;9 p# S/ ~+ q* p* i1 E6 R
                out = (in - tmp);1 L# E  K3 i, l" O
                tmp = tmp + cutoff * out;
# G) g0 W" m: k
1 Q8 Z" K7 c0 H- n9 X  [                output = (INT)out;0 Q3 j& {: X# Z6 l( U0 T# s
                }4 T# G6 q6 b; W. ^9 H6 H
#endif! m% B( T: C6 C  d
#if        0: H; n( ~( V# o- K; L, t/ U! p: O; B
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
% V2 _- Z) l/ P/ i% k+ B  w& x" {                {# J# r+ p7 U5 l4 S2 r
                INT        diff = abs(output-last_data);
: ~2 d9 I. e* f$ c                if( diff > 0x4000 ) {
7 `! T  g- k7 i8 F7 G                        output /= 4;7 _5 C4 M, e9 S5 @% ?
                } else
* u8 \( ?: g) T7 X                if( diff > 0x3000 ) {
. G, o2 ?4 W& w. P+ s                        output /= 3;
0 z, W& A; o* d1 i                } else
0 z! i! B) L; \. o- W                if( diff > 0x2000 ) {6 j9 V' R" C5 U2 A
                        output /= 2;' a: n" _4 P6 J
                }
% ^" l; B' u" q, f/ n2 y% K6 j                last_data = output;* w! U0 F8 }) q9 H
                }
8 K+ C* n1 m, R" U3 v; P. S#endif+ G; l1 A( V/ V2 @2 h' m
                // Limit
6 h) `5 r: U1 J/ J; S; m                if( output > 0x7FFF ) {5 g) n2 w- R, C( I- O( Q/ k
                        output = 0x7FFF;
" n, ^/ n$ m% U" N- ?% N: k! Z; ]                } else if( output < -0x8000 ) {0 P. v6 w& x, |3 H& M! N+ _3 `2 i$ k
                        output = -0x8000;
/ x9 V. k4 z2 G& K                }
( Y6 T  p9 ~2 R; F- `: J
: B  v- ]3 g. @8 b! [- A                if( nBits != 8 ) {
9 W/ C+ G, C! C% }1 n6 Q& r9 u                        *(SHORT*)lpBuffer = (SHORT)output;
% ]: u6 D1 c1 T3 f* u+ w                        lpBuffer += sizeof(SHORT);
+ b" M; F. c9 P) l9 w                } else {
0 t/ \$ N: {) s7 s6 \: c                        *lpBuffer++ = (output>>8)^0x80;7 ~3 N! W9 b8 D/ E
                }
" Q8 T' A+ n. S" q' ~/ o+ f: S  m+ M' O+ J" c' I5 a+ I
                if( nCcount < 0x0100 )
, Z+ w* e, C/ T                        pSoundBuf[nCcount++] = (SHORT)output;
9 A& k# Z# k3 r6 ^
. I6 B1 ?7 l5 L- P//                elapsedtime += cycle_rate;
. r0 n* {5 i1 `. S" p+ `3 }7 Q                elapsed_time += cycle_rate;, \6 z/ T  S& I* t$ A$ i
        }
9 W# t4 r. n: l, D* @% l6 d9 L: B6 D  J& n$ O# f7 H% ?$ J
#if        1/ w/ ?- s6 s, G7 J+ [/ ^8 A; V* h
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 O& i+ y- C( B# ^0 `                elapsed_time = nes->cpu->GetTotalCycles();
" L' b! X! ?- G) r        }, h' T" A4 |; K
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
5 \. f+ k, }2 e+ a% ?7 f                elapsed_time = nes->cpu->GetTotalCycles();0 [  T9 _! D+ w$ s1 G4 s8 [. D
        }
. I. P$ ^" a( a' t#else
, I' p  Z1 E7 ^& \3 X) @        elapsed_time = nes->cpu->GetTotalCycles();
5 a8 ?$ |* A  S: ]#endif
; {- j9 t# h6 `; C. X* f' T}# u; I/ O( _2 j% [. S3 V" V( P! h! n
) k! w% K5 a: \- R+ s; a0 Q7 n
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡): |% p  A8 E4 P
INT        APU::GetChannelFrequency( INT no )  Z) X6 x# E& S" A- D: z1 C0 E
{
6 N  I4 O& ]# n! f, M$ H        if( !m_bMute[0] )
! m8 E0 P5 t. h- F+ m' X, p                return        0;
9 c) ^+ b# j  t9 `
2 b$ N8 @& t! G        // Internal3 v; I: z1 T# a: ]$ X6 N% w9 Y  p
        if( no < 5 ) {
! y1 J* ~2 G0 E5 u+ N( R                return        m_bMute[no+1]?internal.GetFreq( no ):0;
9 y3 H% u8 h. w1 b! i& p; J        }5 c; O- X6 [+ p* {" v* b
        // VRC6
$ e. k* S( L! F2 W/ q( |6 \8 |        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
3 S3 O& y4 B( ?+ R; h; v; I                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
  {' `, B' z5 L" n5 B        }
! A$ ^" x: @3 i$ x" R        // FDS
9 ]7 e+ a2 G4 l; H0 y% L        if( (exsound_select & 0x04) && no == 0x300 ) {0 e' ?9 q2 Q  h$ r3 \1 T
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
3 ^6 e0 y) c* D$ E$ U' `        }4 `! N# m+ g9 q& p0 T8 l
        // MMC5# D* k7 r8 p7 }, k4 j
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# w+ G% @; l) M, k$ g                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
2 G" J/ [( Z! S( p        }
1 s. \4 y8 k0 x+ b2 i% Z        // N106, w1 m" S5 f9 h8 ^- l$ @& K3 }
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {/ }" h, ^4 {) H9 Z/ _1 A( X# y1 K/ Q) q
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 m* c, o7 H& l( @
        }. Y( z5 T$ [6 V  Z# M& f* Z
        // FME7* w/ g& H! j! K0 ]3 @6 V2 L$ B
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) z. _' N$ p) g
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
9 Z. }1 U! W7 b! i( n8 C        }
. B$ u" Z: N- s" d/ q2 w+ y  P        // VRC75 h) G7 V8 n0 ?7 `$ C6 H7 k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {  t% _$ k9 H3 @/ J( M
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;( x+ Q% x) D& x) ]/ p! C" m
        }
7 W, `/ I5 X1 J        return        0;4 B; d) c0 r2 p$ L2 c) W) ~2 X
}" _) e; O/ X6 E6 N

$ v, k0 W4 W. q9 u0 W( h+ h// State Save/Load$ }! ?9 L; g' h
void        APU::SaveState( LPBYTE p )
+ G% t$ X9 @7 J! {. J9 o{0 }5 D' ~, @  I& J9 A( }1 \
#ifdef        _DEBUG
3 |8 G! G, V+ xLPBYTE        pold = p;
$ C. M1 j0 n! e. X. C& M#endif
0 c# o, B( P% a& ]# g7 X( t  C; |4 u8 x' w* `" Z8 i  n  L  @7 P
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
" K+ |7 B$ b. _" p# o. L; w# q0 ]        QueueFlush();
+ k0 O' U. }* j  i4 ~  w4 J( D# Z$ K# p
        internal.SaveState( p );; N- i- O, A) y9 w
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ s$ O- u1 y- b4 G& X- y! Q( {
. Y$ A% Q4 v& E        // VRC60 I9 H4 s' {' C5 S0 I9 N% j. G
        if( exsound_select & 0x01 ) {9 |- z( \, h* N: D1 K# u' P
                vrc6.SaveState( p );; ^# U6 P& a2 f0 `/ Z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding) C. {9 D: i% @. W( X+ y2 E
        }% W  a5 g7 V) [) ]
        // VRC7 (not support)5 V. x3 o8 T3 J* j
        if( exsound_select & 0x02 ) {9 y1 W! l, @6 l, \3 U2 H. V
                vrc7.SaveState( p );$ u" e6 e- g" a$ T- a# z
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% q3 d9 S" ?) N3 [  A" b        }
4 P' X4 y' a- A6 I' u' U        // FDS* A) u/ g! q5 i  X/ p! `* ?1 \# N
        if( exsound_select & 0x04 ) {
! i# i0 @* m# e! n/ H' p) I                fds.SaveState( p );, L$ n' {( |1 |" X, P7 v
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding5 v* ^9 |2 {0 Q, r; A$ S! D
        }) D1 c3 m; ?/ f7 \) o2 B4 j1 |
        // MMC5
' ~9 f  A, v' [0 n4 N        if( exsound_select & 0x08 ) {% I% `, Y0 ]6 r
                mmc5.SaveState( p );
8 v& I7 J' j7 O  r1 k                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 z# o7 ?- d1 A        }; G9 g, D# h* @' N0 f) s
        // N106
+ V* H( `6 X! |' I7 D# r1 p        if( exsound_select & 0x10 ) {& d1 J1 {, ?5 d0 r5 }
                n106.SaveState( p );4 g( I1 i/ d/ K& k' M1 H
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 }: Z7 f, \1 Y0 }6 n
        }
: u" O# G) ~3 _( m9 ^1 h        // FME7! o8 s$ N+ z( B- Z! u% w
        if( exsound_select & 0x20 ) {' X- `( `, m) T- e8 z$ T* H4 J2 ]+ h
                fme7.SaveState( p );" p' `+ n+ k) x# E8 }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' y' S  H5 O& R8 ^
        }' W1 k5 x- Z1 `# b% \6 I: Y

# e1 i: Z8 T) C+ J. F#ifdef        _DEBUG& e9 P! s  E8 q) x$ L
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 b# C' H( u. d% ?; P  x- C#endif
( m& W0 C! Y2 a- \2 I5 b4 c}) u0 O/ ]4 v' Z, K7 h2 I  z- I

' w; p- h: Y( ]- e2 U/ K% q" lvoid        APU::LoadState( LPBYTE p )
) A( @9 b/ v# B+ {{
, y# j! }1 y3 K& K+ M* J        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
- L) o( ^& D- x% j8 V# C4 S: }2 B        QueueClear();
3 J5 J4 I6 Z+ X& l" y  {7 m9 t8 d2 m1 G! T& |3 J$ X2 ^0 _  k
        internal.LoadState( p );
5 d. j* I4 O+ z1 L0 o0 Y        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, N* L, `$ D$ f, K; V/ C- D! n# }5 H, x4 l+ U% q, x" B4 N
        // VRC6
! ?+ L& G+ X" c# G9 m, {" J! D4 h$ d        if( exsound_select & 0x01 ) {5 S. ?: }$ M& ~0 s# V* W2 P% j$ |* H
                vrc6.LoadState( p );) V2 z9 [/ F! f2 k( [* T6 B: z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
0 Q. u0 t* w' F. ~: s        }
5 n- A5 w4 o. D. ?  q( \        // VRC7 (not support)
# ^; b' x' v" P( k: `" ^, H% v, d+ l        if( exsound_select & 0x02 ) {7 x' y* ]4 e3 @0 Z) B
                vrc7.LoadState( p );
$ P/ g& d( i2 w) d6 y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding& I; o- Z7 x- C' {
        }
! i/ I) a0 M5 W: V        // FDS4 y- R- D8 z9 u3 d3 X6 M
        if( exsound_select & 0x04 ) {
. Q, G: z% i/ c# ~8 f                fds.LoadState( p );
2 ^2 Q: w0 {, C* r8 @# J$ S                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 Z/ T+ v' o9 [" g6 I1 p# H
        }. s' z8 {% i0 k$ @- e. n1 V6 p
        // MMC5% X. ]) ]& q& t, X- ^7 g+ D
        if( exsound_select & 0x08 ) {
1 |. ^3 l5 g1 e+ k7 U                mmc5.LoadState( p );
; h6 l0 Q* ~. I0 ~' p  s2 t& ^6 _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
, f; f. A) I; i/ }# _6 C        }
! b9 p& x" G  L        // N1061 c$ J8 l2 X. b  [& r; S
        if( exsound_select & 0x10 ) {
  E+ x. R( ]3 o% c7 r& `                n106.LoadState( p );
1 r" u# q* k) h/ q                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. ~, O( ?* r, u$ E( l  S0 D, ?! N$ r. w8 O. A
        }
) y8 k4 Q2 S! Y8 C' R6 X& D        // FME7
% A2 x0 _! Y9 v+ o8 ~        if( exsound_select & 0x20 ) {( O) x4 A3 q8 T2 V, J
                fme7.LoadState( p );
9 Y% N3 L/ \' C: Q: p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' [+ e  E$ V! i* E3 [( L* B        }
& |* Q# _! D: j, U" X}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
4 |: `# v4 ?$ W可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。. a1 v' b4 ~! A2 ?& Q
感激不尽~~
: j" y8 A: D2 f3 c$ a  g+ |
恩 我對模擬器不是很有研究,) u" H0 _: E) Y9 V: y8 x+ s' K
雖然要了解源碼內容,可能不是很困難,
+ f, r$ d6 O6 u7 G) N不過還是要花時間,個人目前蠻忙碌的。
! v/ x* B3 O  K3 Z' t  e$ z( w* @( S# G5 G! z
給你一個朋友的MSN,你可以跟他討論看看,
2 ]& w4 G, A% W0 u) i0 ~他本身是程式設計師,也對FC模擬器很有興趣。1 h8 f! j1 _) S/ R/ N: f" q/ J2 D
/ S- ]8 q3 W5 E" M) ^4 ~
MSN我就PM到你的信箱了。1 n( v" A6 j+ {, C# J" [/ s
2 E; g5 Q3 i( D5 g; H1 ]/ Q$ b
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' b( z/ `7 p. t/ B& V
呵…… 谢过团长大人~~
3 ~& D0 p7 b6 F

% m$ z' S: X$ g8 J% O' P( C哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
) v; D+ f/ J  @  i+ v团长的朋友都是神,那团长就是神的boss。

2 X3 F9 ]  D8 g8 y8 |# e哈 不敢當,我只是個平凡人,2 o8 \' f3 E- R. z$ r3 i
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
# X! Z3 ^* z) X2 w& n$ |8 SZYH
& Y+ a& c6 [8 tQQ:414734306- d& c; k4 U4 }9 V4 m
Mail:zyh-01@126.com
# b" }! p% x/ x) q
' t; j" k: l4 A1 \他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
- Q% Y. g+ e7 W9 B2 `- D5 Q再次对团长大人和悠悠哥的无私帮助表示感谢~~

5 W) b: a* J  l: P5 Z2 T不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-8 06:25 , Processed in 1.106445 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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