EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?" Z& t7 x0 p) k% g& K7 f
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 j$ s; ?& z) }4 V' h楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, @1 e8 |2 Q" T8 E" r这里有相应的模拟器源码,就当送给大侠了~~) F5 |; H- o7 K! |) g+ J
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # a7 O9 u1 @( M' q6 T" r
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
- B; v6 l$ R+ F+ ^) I% e% O, D楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; X2 u" C3 ^% [8 j
这里有相应的模拟器源码,就当送给大侠 ...

4 Q% Z6 o0 N& Z: @; C  A; M9 X聲音部分(Audoi Process Unit = APU):
  h7 O0 M& L! Y1 m) B3 b! a.\NES\APU.cpp" i" ]7 W  J7 E8 V
.\NES\APU.h# }# U( i5 e; Y2 F, Z$ ]  c

  F4 V8 P3 u4 Y9 i% \& a7 ^% z. c* ~% l
影像處理部份(Picture Processing Unit = PPU):9 n# T% Y$ l" ~1 J% a+ t% f
.\NES\PPU.cpp
/ E- w0 o# Y% t1 N.\NES\PPU.h
7 Z/ d4 ]% k, U' I7 r+ p4 \! D9 q6 v  u5 j( T$ M
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:% c- N& u# b# l% H5 x( x9 Q8 V9 t
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) z$ g* _  p6 x& v//////////////////////////////////////////////////////////////////////////# d, t, `6 L4 n- Z2 i& l% v
//                                                                      //4 s( W- l& \+ r, B6 D' y
//      NES APU core                                                    //
, v! Y# p7 Q+ F0 w' P; m9 K//                                                           Norix      //
/ P- a* ]$ @% G& Q, m: q3 p1 n//                                               written     2002/06/27 //* s/ A* R' W" n: n! Q8 X
//                                               last modify ----/--/-- //
8 z$ b% ?% h, x/ f0 l6 p5 S//////////////////////////////////////////////////////////////////////////
* G* M* o* o) w6 H#include "DebugOut.h"
8 `5 E0 C* e  C- W#include "App.h"  g9 x/ q: A% _+ R6 q% B9 V9 W
#include "Config.h"
" Y* ]) k# k" E! l- b3 D
+ U) m3 B6 `, [1 m" a! W/ i$ k+ P' y#include "nes.h"
; R* s3 {2 e( e) x' v! l/ W#include "mmu.h", {8 [. N! E6 v
#include "cpu.h"
8 \! N) I3 O( n1 V0 M- b5 p#include "ppu.h"$ N9 M8 q* P3 Z0 M
#include "rom.h"
( g0 k) U7 r4 k" A  z#include "apu.h"
  g5 c% v1 ~+ n6 p" a0 x7 S' m. k2 H; O! C5 \8 n0 R
// Volume adjust- n& k4 `, `. J
// Internal sounds
: _" t. ]" b0 H#define        RECTANGLE_VOL        (0x0F0)
' x! g+ z3 q4 |#define        TRIANGLE_VOL        (0x130)
9 ?1 }; N6 l* w' y#define        NOISE_VOL        (0x0C0)
3 m6 ^8 u' n& Y* }+ [# \#define        DPCM_VOL        (0x0F0)" c* r/ s; v  {/ G$ X, F
// Extra sounds
1 M8 x$ _# H9 A2 Q+ m& _; |$ p: g#define        VRC6_VOL        (0x0F0)
$ t- u0 {& y& p) V" x2 i& x% d#define        VRC7_VOL        (0x130)
5 x( m6 G) l" {$ X3 N* \#define        FDS_VOL                (0x0F0)0 Q' I8 y- `: w: d
#define        MMC5_VOL        (0x0F0)7 e8 d/ F) f% m  V: q
#define        N106_VOL        (0x088)
! J& L, }+ D8 l#define        FME7_VOL        (0x130)7 R4 p! {4 C6 y! v3 {$ A

0 e, X4 T' h1 Z: mAPU::APU( NES* parent )/ ^1 h% O1 H' [0 [4 V
{
% Q7 u" B+ N, A5 t5 I$ _: w% s% {        exsound_select = 0;
  E! e8 t3 Q$ C  g- f8 `" h" ]9 @& f4 ?3 C  @
        nes = parent;
3 R: D  j: _% E- z8 ?        internal.SetParent( parent );
. J' q3 E9 }  O! |! n) q, D
( C( F+ G5 Q1 y& E/ g        last_data = last_diff = 0;
$ m" C  ~- O( H& z
/ p/ V7 b7 i/ I. ]5 n        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );' C, j. X+ K# p# ~1 Y; {) L( f
1 S' y" K( n; }
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
" z: c& |/ Z  q% I8 k' ]( w        ZEROMEMORY( &queue, sizeof(queue) );
/ Y: I! A( v' \( T        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 U; T; R3 _: M+ }, G5 [3 y2 }4 v/ D) B; }* l4 C0 m
        for( INT i = 0; i < 16; i++ ) {
# }5 U, _) @- T- V4 k0 ~" @5 ^                m_bMute = TRUE;* q- v: K' T; I  w4 s0 s
        }* E% Y6 u$ o& i. U, s; q) Q
}4 W# q4 M) f: W4 l6 \+ A  W

/ V! h! R# d, o* kAPU::~APU()
$ S" ^, I5 X. j  C{( [4 i0 i% d+ Z6 [5 h5 g
}
0 L% _' L, ?1 `0 }) t1 I4 t1 }3 E9 C, \2 C
void        APU::SetQueue( INT writetime, WORD addr, BYTE data ), Y+ T) U5 v9 a% N2 X
{' V% W% n( ]: _% |& R8 k
        queue.data[queue.wrptr].time = writetime;6 ]& Z8 F# g3 {2 J1 ?7 w+ R
        queue.data[queue.wrptr].addr = addr;
3 F+ `& O  H1 _) F) r% X        queue.data[queue.wrptr].data = data;
3 L" M: h) ]; h% C. r6 c; g        queue.wrptr++;
3 f, Y% g6 s' I. J        queue.wrptr&=QUEUE_LENGTH-1;
8 B0 u, _# W# ]* {+ p        if( queue.wrptr == queue.rdptr ) {2 {4 ]& j4 Y. ]3 B- A6 b5 x6 c( ]
                DEBUGOUT( "queue overflow.\n" );9 R9 Y* N. f) n! ~" u+ e3 o
        }) ]# e6 y$ k, y( ~8 r
}
; C$ Y# L4 X/ G" p% F2 g" ~4 t
' s6 K/ f  Z$ X. ]' nBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )' H. g3 J  q: x) W4 ^- a* G1 Q5 U
{/ N) k/ @1 H( W( H# h) Q+ m$ l
        if( queue.wrptr == queue.rdptr ) {
+ I% n; C* e& Q2 ^                return        FALSE;" J, X. \# o2 t
        }9 m3 [2 @: C! _% S/ y5 x+ E" \5 F
        if( queue.data[queue.rdptr].time <= writetime ) {/ R% G& D! H' E8 q! \" C
                ret = queue.data[queue.rdptr];3 {- q7 G9 z8 w( g+ `. C
                queue.rdptr++;! w5 ^# F' d* C4 s
                queue.rdptr&=QUEUE_LENGTH-1;' _1 Y3 L" w  g2 \) T8 n$ Y4 p, l
                return        TRUE;3 P. p/ n" f4 T6 h* m6 t9 _5 p& P
        }
$ E1 K7 n# ?) n& f% C        return        FALSE;
' v- U" O  X$ I5 _& z" ]! {8 j}* k5 |/ x5 q5 i4 X: \

/ K2 p% O) A8 G! X- s$ ~- b+ o. [void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
) _6 m- |' \: I1 H( c) P{  N. X7 v1 n6 w8 f
        exqueue.data[exqueue.wrptr].time = writetime;! b3 E" f, X# j6 s2 ]" Q; N
        exqueue.data[exqueue.wrptr].addr = addr;9 Z9 J2 ?: F. }6 m  N
        exqueue.data[exqueue.wrptr].data = data;
* w' Q: t. w# P2 {  n6 H+ K' ]        exqueue.wrptr++;
1 \* v; r3 D; l; d& ^        exqueue.wrptr&=QUEUE_LENGTH-1;
& i( o% {2 I! ?7 |' J! I        if( exqueue.wrptr == exqueue.rdptr ) {
! B1 \2 x4 X- m: q7 b0 k7 G! [  c- U                DEBUGOUT( "exqueue overflow.\n" );& ^7 I% K4 L" x; j3 A
        }
9 e- I: Y- w1 k( ]}
9 W* c8 {5 P3 R) \$ b% e0 {7 G$ u4 _# j: w. I% c! a0 @$ v
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )4 O& _1 Y/ ~$ W$ p
{- x# L. Q  A. S, d  U; d
        if( exqueue.wrptr == exqueue.rdptr ) {
/ W+ p5 n) D3 [' T: t) v: `                return        FALSE;
2 }. |1 n6 t) K) f2 Y; q        }  V8 p. ~: v( \1 l
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
5 v4 M  t, K; r0 e# t4 v3 z                ret = exqueue.data[exqueue.rdptr];# b1 v3 V- X! |  s, \& a# ~) M
                exqueue.rdptr++;
* v7 |8 v9 U& [) \: q: g  A2 C: \% A                exqueue.rdptr&=QUEUE_LENGTH-1;+ v4 P! d: r" `: C% l" w
                return        TRUE;
" X+ Y* r8 G. T  W5 l        }. q+ x4 j* F0 S9 ]8 Q
        return        FALSE;
5 }' }! K7 c  i}
# Y! j9 Q& ^( K; D# W+ ^" u7 z+ b9 |5 K# S! \/ D& o  ?& [
void        APU::QueueClear(). R: ~) x# N9 W- Y- ~
{
! m2 K$ @3 F7 s# X* {        ZEROMEMORY( &queue, sizeof(queue) );6 b! @& h. X2 U* V: m8 Z$ d
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( K& H0 k! i3 T3 C6 ?
}
) D- O( c+ g! V* J4 P7 H2 o0 F8 R( l% o" O# r; x$ a
void        APU::QueueFlush()
$ w4 `5 @' B0 d+ j$ `) }{# }. Q8 W9 }# P( h2 F4 d% c( q
        while( queue.wrptr != queue.rdptr ) {
! i( k9 {0 K0 ?9 j. k                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
/ p  G, L' C6 N6 d. n; M8 K- h                queue.rdptr++;
6 J* K7 V5 G3 F; s! V. ?                queue.rdptr&=QUEUE_LENGTH-1;. r! B- i9 u" q& |+ q4 {% Y
        }6 u- w4 }+ }; f3 P" ^: E) f

1 C2 k$ r% d% b+ K9 k  ^/ N        while( exqueue.wrptr != exqueue.rdptr ) {% V! Q+ t- q" H6 \9 {/ ]
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );: G5 H) P" i! A4 p% s; }: R; i# M
                exqueue.rdptr++;% i1 ^+ P- O6 Z" c7 b- O# s
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 Y" H+ x! E7 W0 \' U        }4 @' w: {+ i0 u. |. D
}" H1 _' T' S" O" G) e1 L
- l. B  s4 H0 F2 ]  @
void        APU::SoundSetup()
! S5 f" c2 ^% X1 i) t4 i{: F2 I8 p$ ]: M7 T0 X1 T. k
        FLOAT        fClock = nes->nescfg->CpuClock;
) s( [7 r5 k1 b! {' u4 \4 m( k        INT        nRate = (INT)Config.sound.nRate;
7 a! G# z( U4 t4 o        internal.Setup( fClock, nRate );- [2 q1 r% z3 v! N
        vrc6.Setup( fClock, nRate );
' Q1 {. q8 y9 Z: H        vrc7.Setup( fClock, nRate );
# J" v6 a1 L8 u, r        mmc5.Setup( fClock, nRate );
% M' m  ^% Z' z7 r        fds.Setup ( fClock, nRate );* ~" R! z% v0 m6 Q% D
        n106.Setup( fClock, nRate );5 `& y/ q5 H+ \" @) m
        fme7.Setup( fClock, nRate );6 ^. D$ ^2 E  D, V+ _' Y, x1 a
}. ^: m/ L/ }: f! l4 m

0 j: k1 r3 `0 ^4 K; L; Mvoid        APU::Reset()
, C6 E, }& _8 v{3 ?7 F+ E9 Y. y% G5 i4 \3 r1 V4 ?9 R
        ZEROMEMORY( &queue, sizeof(queue) );
6 ~9 I8 }% t, h: E        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# S, V* q8 Y% [8 j. e* o5 Y# A: D4 _% ]. ?1 c( p2 X
        elapsed_time = 0;
. K+ J" B* R3 X+ X$ x9 g) \' M$ ^5 R+ M" ^' R1 W# o* r
        FLOAT        fClock = nes->nescfg->CpuClock;8 z5 n" h, f& l2 i9 D8 ^1 ?
        INT        nRate = (INT)Config.sound.nRate;
$ h8 p" H  q, l7 k3 B        internal.Reset( fClock, nRate );
  P& N: ?- c0 W  I! E        vrc6.Reset( fClock, nRate );
) ^2 h# @8 ~* c# ^0 Q        vrc7.Reset( fClock, nRate );+ H! j1 y' l" D% }  H8 B6 U" N
        mmc5.Reset( fClock, nRate );
( k! F9 @+ Z) v8 p! M5 m( J2 ^        fds.Reset ( fClock, nRate );
" z4 Q7 L  T) }  O9 {        n106.Reset( fClock, nRate );5 e3 C+ [0 X3 Z7 s; Q
        fme7.Reset( fClock, nRate );# ~+ V* i# W4 T

* e. E1 x6 P  {, x, f        SoundSetup();
$ A# f& G8 O: q) Q9 Y) S8 V, S}
2 G% V" F( K  r$ l4 {3 p( Y2 N9 s6 c6 A( `
void        APU::SelectExSound( BYTE data )
. h, G+ n/ K# c& \2 x8 B{* Z" {7 ~' K1 w3 c/ @  k- ?
        exsound_select = data;8 O8 E( F; y8 L8 J( S
}( b$ S; U8 T5 l  {2 O; ^

9 U) V5 E+ U0 t* gBYTE        APU::Read( WORD addr ): i: s  _) Z' s: D# g/ z" r
{* R+ ]7 p; f9 E! {
        return        internal.SyncRead( addr );& |% p; H- M# a& B" @( T" _! G
}$ W1 j6 R8 O; t$ q3 k7 z) {" R
9 O1 ?( J% s8 I- s( T0 j5 k
void        APU::Write( WORD addr, BYTE data )
# W! }. n/ u" J1 c! N4 L/ Z  \{: E1 ]: Y! n4 x2 w0 M
        // $4018偼VirtuaNES屌桳億乕僩  Y4 @! t7 i) }3 N
        if( addr >= 0x4000 && addr <= 0x401F ) {
: H/ Y4 z7 K& k* u- r1 m                internal.SyncWrite( addr, data );
0 x- e; u4 P' Z/ y4 ]                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; Y% ~; Z6 X- B) M# C" m. _
        }
# N& ?- A$ ^& z& f, A}) c" c: r. P8 w: w! a) u, ]
$ {% P9 Q5 q: D0 F
BYTE        APU::ExRead( WORD addr )) q: Q8 D+ o( C# s2 |; B4 g8 U
{8 E0 i2 h$ _6 |. m. F
BYTE        data = 0;
8 c! o+ Z7 z/ k3 G/ b' Y4 D$ N$ F& L; X) c
        if( exsound_select & 0x10 ) {
/ u- j! L5 q: g$ w/ P" s7 J                if( addr == 0x4800 ) {
1 F( _5 Q- z% h/ g2 K                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
* A0 c5 y! l  t2 R8 \& i# W4 k* R                }
6 y% r- e8 k2 ?0 ~        }
; M2 F+ c8 i5 t# U4 p" X+ ]3 ?        if( exsound_select & 0x04 ) {: n/ |8 i# ~' u6 i  R
                if( addr >= 0x4040 && addr < 0x4100 ) {) Y* a/ v2 n; t3 \3 F$ K4 h/ h
                        data = fds.SyncRead( addr );
/ e% \7 R/ a$ w                }( ]: T. f1 p/ F* r# |* a# @
        }2 l" n( F5 u' [* W
        if( exsound_select & 0x08 ) {
* D  ?1 y1 W1 b1 G3 ?7 p: W0 U                if( addr >= 0x5000 && addr <= 0x5015 ) {- E& Q: `2 U; p: b
                        data = mmc5.SyncRead( addr );" y) u  g# b% k4 s: B
                }
# ~* B! C- h5 l        }% b4 ~& k" B6 }4 W* o

! E6 A9 U1 R5 i! M9 Q        return        data;6 L! N3 f0 b2 r$ x
}2 c# ]3 T4 a+ }, B; x/ m' K

7 z$ Z" J4 B8 E( bvoid        APU::ExWrite( WORD addr, BYTE data )
" j2 J+ `6 [+ I3 N1 @{
, j( ~! z. P7 N$ {, M        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );6 i4 F9 ]; h/ C- G% K- k& K
8 B! A/ v) d; k! V4 R
        if( exsound_select & 0x04 ) {
1 [' D6 u" y/ }1 I$ s/ M, u( a                if( addr >= 0x4040 && addr < 0x4100 ) {  }+ d# u6 c# O. Z* [: A# ]
                        fds.SyncWrite( addr, data );
$ H2 G8 K& w, p$ ~# {8 _; z3 q- T$ D9 ?                }. R+ ]) z' k! I4 d4 l
        }
; v( q. J( x9 X1 |4 c
- |& L$ o) b' y+ n6 e7 M        if( exsound_select & 0x08 ) {
$ ]" d" t! W0 R5 `% l0 E/ g- X                if( addr >= 0x5000 && addr <= 0x5015 ) {
8 {' }9 S! @$ s* r                        mmc5.SyncWrite( addr, data );
2 N( x1 w/ y8 K2 {2 D                }, ~: ]# p4 ~  R# `
        }9 \; V6 |) U* ]. B! K
}0 b2 |  Q2 g, E

5 i9 ]& t2 i/ B& w5 j' pvoid        APU::Sync()
5 O& o  y* F3 ^- M7 B{! u0 i  z& p, Q5 ]" U
}
/ d  W2 {9 J# P+ B6 ~% J0 S* n* O' _# D7 i9 i; s6 s
void        APU::SyncDPCM( INT cycles )5 H8 l" V1 b  {/ @$ }
{2 V& i% z6 t# ~- w( T) M* p0 `' |5 D
        internal.Sync( cycles );- ^$ G& z. a' s, L+ ^' Z5 m

; m/ v+ n8 t2 g" O3 q        if( exsound_select & 0x04 ) {0 l4 s1 Z& h5 G1 r9 T, L* H) b( _
                fds.Sync( cycles );
; I8 g% T. `" d. a8 N; j        }7 E) h5 r( U3 W
        if( exsound_select & 0x08 ) {
* P6 X% M0 t# ]) t7 ?                mmc5.Sync( cycles );+ H# o& {, c1 T8 G- V5 _
        }( b0 r% W. V, O+ C
}
$ l4 M- J2 u& E% i- ]2 B# M# D8 A! S7 x, l
void        APU::WriteProcess( WORD addr, BYTE data )
0 i: f0 P( ?  Q+ O# [& p$ Z{
9 [, Q" \: r6 P        // $4018偼VirtuaNES屌桳億乕僩
& E) A2 T5 N5 {$ [' a        if( addr >= 0x4000 && addr <= 0x401F ) {
& a0 D8 r  a9 V: P3 Z; u% t) H                internal.Write( addr, data );9 }$ S  S  g6 }( Q1 `! T( A
        }3 h+ ^, _0 _1 l' S
}
4 D: a7 M4 o8 f+ ~! [' p
% w, u2 F" M9 G& \" e+ c$ [; Evoid        APU::WriteExProcess( WORD addr, BYTE data )" ]3 {. m3 V9 Y% `
{' p- p6 L3 f! C1 D( [! ~- W+ K1 ~
        if( exsound_select & 0x01 ) {6 p- ?* m/ L8 }1 ]
                vrc6.Write( addr, data );/ r& Y& f+ I) p. ?
        }2 z+ i5 K" h  h8 }# e
        if( exsound_select & 0x02 ) {& C0 t: y( T( d  \7 d
                vrc7.Write( addr, data );% ~& ]8 V4 ^! |+ Z3 @
        }
1 E# a+ c! ^0 b. N        if( exsound_select & 0x04 ) {4 ]; g' O* V& \
                fds.Write( addr, data );
2 M+ k. |( o% g/ }- [! X2 ^        }
( V4 v% C1 E" X7 M        if( exsound_select & 0x08 ) {* d7 n1 J# r  q% Y8 b, z- z! l
                mmc5.Write( addr, data );
" D, x- E% b5 N' @8 g        }
% S- c, P' t3 d4 y6 x* N# [        if( exsound_select & 0x10 ) {
* a" X0 G3 P$ n6 Q  u                if( addr == 0x0000 ) {5 R% g5 e: o: @: n) v. K/ V( O
                        BYTE        dummy = n106.Read( addr );4 ^8 L9 ?" w# O/ `% e; C# p( \
                } else {- B& w5 c- y- x  Q! ?
                        n106.Write( addr, data );
0 V4 z2 \. ?1 C4 E& r% Z8 R                }/ K; W; }! G) H; P. Q
        }3 S  p' g6 `8 k' u0 I: Q* O
        if( exsound_select & 0x20 ) {
2 @9 }3 V3 ?0 V& I7 G                fme7.Write( addr, data );$ E* t8 U1 ]4 L6 y' A+ U+ t9 h! j! _
        }" v2 Q: U+ X7 H/ L, r) t: l0 T' J
}
" _% [* J) k% H" |6 d. y2 H% I  M' I1 o
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ T7 h0 W- O4 G{
6 d2 K4 P  T7 Q- M( O5 PINT        nBits = Config.sound.nBits;
9 M8 c2 }) k3 T; d9 }+ t6 e, YDWORD        dwLength = dwSize / (nBits/8);
0 I: e% {3 \: p( BINT        output;
$ V/ W6 V6 Y& P! _; Z/ f0 B& E3 U7 SQUEUEDATA q;' F+ e" ], z6 ^
DWORD        writetime;3 e. o1 I3 X" k3 u8 {3 l# E
) d- P5 t4 J) j. d9 i8 r# Z
LPSHORT        pSoundBuf = m_SoundBuffer;
3 _: h1 G* d. {$ Q! o! O/ cINT        nCcount = 0;
5 h0 F  o0 B) R" s; c) v
% t( o0 w- F" q, n7 l8 R9 pINT        nFilterType = Config.sound.nFilterType;
, b, D# ~. Z& R+ e9 Q) D  F+ z- s: T# E% \. l6 L* \
        if( !Config.sound.bEnable ) {
/ E, ^. t+ A' @5 ]8 T                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* g! p; k: y" Q& l8 d* l& K- }' `                return;
# u- C  N, ^5 K        }/ S  S# X; l8 f4 \$ U( A
% r% B  S( P  w4 i2 C
        // Volume setup
; p8 M# m  N5 n8 b( i* ~0 a        //  0:Master
. @8 b* Y/ W5 N( L# Q        //  1:Rectangle 1& {: K- g& p, Q( b
        //  2:Rectangle 2" a$ S' E; |- T4 N' f6 G
        //  3:Triangle, |, |7 n1 D6 \4 _& b
        //  4:Noise
- m8 h7 i! }! J- U" p        //  5:DPCM
4 x) E/ i0 w; D- j5 M1 j        //  6:VRC66 D; }% x  Z. h
        //  7:VRC7: ^, Q6 \. v5 k& Z. s: `
        //  8:FDS' i( k) {) Q( p& P' q
        //  9:MMC5
9 J: {! [/ U; U- Z8 W        // 10:N106% G8 C( X) S: i1 T
        // 11:FME7
+ b! j4 ]% E, }, y! K9 u8 C3 U        INT        vol[24];* x1 `2 ^: s/ F7 \4 I9 I7 Q$ l" a
        BOOL*        bMute = m_bMute;
) k/ E2 a; R$ x+ h' F/ }  R3 ^        SHORT*        nVolume = Config.sound.nVolume;
7 o) X( h' A& {* }- }$ E& W) s0 k+ E/ ^& u+ o: g1 z
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
7 M0 Y. D' z" u/ i2 Z$ j4 T8 W! N
8 C  e3 b2 f& ^0 u+ V        // Internal
* s) p, K- ~3 }( J" a        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;  H8 T8 N9 {- }' I
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  }! }+ l& n1 j5 `0 H
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ d5 ~# t2 l' e! u) a7 {
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 I2 k" G5 R4 ^9 N$ ^6 Q% w        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! e0 Y7 S% e# {0 }
3 s9 T3 e# C/ ^, ]$ m, P) J1 j: }        // VRC6
  [) c6 }$ P/ A. U7 q+ V        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 z* a: r7 r; s* ]        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, N& i5 ^* R2 C) D" Q" T5 k
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 \/ \) ~  \. b2 S9 s
. z( P% U- J1 w9 n% h
        // VRC7  f- ?# ~/ q+ ]1 a8 W
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;" q+ H% d9 K3 ~+ o6 I

; w) B) P  g+ b' ~: n3 ]  k        // FDS
+ e0 Q( ^( g9 t        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;0 S: e+ ?2 k" U  h/ e% R
1 v' }% Z- P; c0 u
        // MMC5- Y/ w4 P+ z" W8 ~3 t, o) \: K
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 l" ?, W$ g: }5 ^9 e- c% A$ E* \
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! H% V$ M. h4 |% F% E
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ g& F- c9 v' k/ B" d" U- S) Q

7 g+ O' a: S  P; m- U1 P4 w        // N106
$ t3 \& F1 Z0 n3 r% D        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" l% `4 K! w% L# s. E        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; V4 d. T9 @2 d+ q6 G1 N        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  N) ^3 q8 u+ |( d        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  I6 c3 h) J2 _6 u; w
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; B+ w) l, ]$ I$ i4 y/ M
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 H9 E, c; _- W
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 c% ^+ A' l. g& T  l& M
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* e4 d2 `/ O& i! j9 i1 G; p5 L
, x1 D( H( c5 E& L) ~$ z        // FME7
. V/ i$ {0 T3 ?/ ]; |- D        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ O, M" }+ z) Q
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 e- u" e; v: g( l  W4 Z) A; @        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! O  G  M- S7 p

1 U! K4 [% u/ x) `. ^8 l//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ y( [. P6 {  B7 _1 U0 q( H* M  [* g& c
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;6 q- K1 d6 S; G. ?% b
7 r6 C& N( }  C9 \/ [
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% J* |6 J! n9 y        if( elapsed_time > nes->cpu->GetTotalCycles() ) {* q0 ^' A6 Q& j# `' ]7 U4 V
                QueueFlush();
1 E$ ^$ r  F6 z; ^, b        }' Q7 m1 N; R, D5 u+ v
; _: C, }% s+ v% G! _2 A4 L; ]& o8 Y
        while( dwLength-- ) {# W% R1 ^2 O, g) ^8 y: F
                writetime = (DWORD)elapsed_time;
- E9 b2 \$ T& _+ z9 T, o! Q
% V% H; i) T* Z# w                while( GetQueue( writetime, q ) ) {! ~0 U1 E' R! H! l" Z( M* h
                        WriteProcess( q.addr, q.data );
' M- ?5 J% g( ?1 X; p                }2 J* W/ J, I0 I' C6 Z: `, q9 s# L

  l; I8 G4 r/ z4 Z  j: Z                while( GetExQueue( writetime, q ) ) {
) I  \/ J! a( _) B! K% k9 [                        WriteExProcess( q.addr, q.data );3 h# B  l/ |5 J. f2 I
                }
: V' |3 b( B+ l% i, N. x! U
- m. {' N/ C3 ^; g                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ ?/ y* J: j6 j; @4 F                output = 0;
; v1 f4 w# x- _2 W# s# B1 Z/ H                output += internal.Process( 0 )*vol[0];
/ v8 m  e/ F* Y( d                output += internal.Process( 1 )*vol[1];  d0 D4 F! ~( k: k1 K
                output += internal.Process( 2 )*vol[2];3 c- {  h6 ~/ p& h' o: P
                output += internal.Process( 3 )*vol[3];
* q+ ]( o; V: |                output += internal.Process( 4 )*vol[4];3 f3 H; F/ @# s
: Z( r2 h4 L4 {! O% _
                if( exsound_select & 0x01 ) {
9 S( E( `) |6 E! U& R. ?                        output += vrc6.Process( 0 )*vol[5];8 Y$ R" l7 |$ m2 d
                        output += vrc6.Process( 1 )*vol[6];% h0 I6 E5 A) q* n" g) ~2 x
                        output += vrc6.Process( 2 )*vol[7];
) t9 S3 R- q7 v* g                }
, j1 G3 h; V, L$ y                if( exsound_select & 0x02 ) {
$ J6 f" q0 j. t! i$ S. P                        output += vrc7.Process( 0 )*vol[8];
- |. j; U6 F* o8 S3 L                }
5 V- |/ ^5 t2 J% h7 `, h                if( exsound_select & 0x04 ) {  F3 Z5 d3 ?6 B1 }3 \" P% ]& }
                        output += fds.Process( 0 )*vol[9];" W6 K0 n7 ~, t# I& o2 r
                }% R# u* }0 ~" N
                if( exsound_select & 0x08 ) {8 @+ H0 @5 d) V! g
                        output += mmc5.Process( 0 )*vol[10];
* e9 {0 Q0 h( a* U                        output += mmc5.Process( 1 )*vol[11];
5 Z/ ?/ A; Y9 m. x/ |6 ]                        output += mmc5.Process( 2 )*vol[12];
8 ]* e+ V* q: U" u! T" P0 P                }
0 m* D( e+ U# z, J( I3 \& {$ E) W3 ]                if( exsound_select & 0x10 ) {
- X' M' J4 ^& `5 r- O$ q9 @: T1 x                        output += n106.Process( 0 )*vol[13];
+ H/ l) Z% L0 R                        output += n106.Process( 1 )*vol[14];
) x/ {, m& Q" p  w( S                        output += n106.Process( 2 )*vol[15];" a4 ~& _' v1 [. X/ v& q
                        output += n106.Process( 3 )*vol[16];% [/ _4 d) N5 W% V
                        output += n106.Process( 4 )*vol[17];
( T7 X5 w- P( x8 N                        output += n106.Process( 5 )*vol[18];# ]; Q: a% U: ?& M9 y  W7 R* e
                        output += n106.Process( 6 )*vol[19];0 n! {) J7 _6 V4 A$ t+ }; k9 v
                        output += n106.Process( 7 )*vol[20];
; l+ t; f4 D# W& d2 T6 G                }
" Z9 f( D) U: E9 W: l* B0 }0 A- j, f& J                if( exsound_select & 0x20 ) {( P! ]5 p2 }% M. q. X$ Q; a1 w2 o
                        fme7.Process( 3 );        // Envelope & Noise4 \8 J8 S8 p6 t
                        output += fme7.Process( 0 )*vol[21];
- j# i4 @8 w& l; j; J, p, T                        output += fme7.Process( 1 )*vol[22];
+ h# D2 m0 u7 u  y/ R: r                        output += fme7.Process( 2 )*vol[23];; v1 e- u9 T3 X: H: g0 T# \
                }6 E. U9 H2 G3 K$ E' d; T  U
( i% V/ y" E8 B
                output >>= 8;4 b9 D1 ^: S- W/ C
: c* R" U2 A; T) a, \4 m. P2 O" V- O0 L
                if( nFilterType == 1 ) {
. ~4 H  w% C! A" k/ \2 g                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: W. ~# o9 ?, @* x                        output = (lowpass_filter[0]+output)/2;
  v$ P: x. c$ i6 c& m& ]7 ^- O6 _  _                        lowpass_filter[0] = output;
( v) e1 i; c: e# m" Y6 q/ w7 J                } else if( nFilterType == 2 ) {
, T0 U0 n- m+ e; _2 ]                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 W5 x7 h7 ?8 u" T                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;0 E. y6 {% v0 l' w, S2 {1 d
                        lowpass_filter[1] = lowpass_filter[0];
2 |6 V  M% h5 u: ~) o- A, f. W6 j/ Q& b                        lowpass_filter[0] = output;( m$ R- C, d0 b8 `
                } else if( nFilterType == 3 ) {
& F' T' G' a2 m8 [0 ?: Q1 C/ _  T                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2). }/ q+ o( c7 y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;. O: g& c, U) Q( _8 D) {5 N
                        lowpass_filter[2] = lowpass_filter[1];' A# }2 b% A) N% c7 ]: J
                        lowpass_filter[1] = lowpass_filter[0];
6 g! t: W/ V( ^8 B                        lowpass_filter[0] = output;
8 ]. m. Z! H$ b                } else if( nFilterType == 4 ) {
! Y; J9 D( u& o5 v* a6 A& y# s                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)+ n* M5 m0 Q0 t9 F( X9 Y5 {- B
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  y# I, `  v' \% v
                        lowpass_filter[1] = lowpass_filter[0];! |  V/ m* z6 @4 a
                        lowpass_filter[0] = output;! [% G9 G1 t, m; [) }* @! N; J
                }6 H( R7 W9 t  w7 {

0 T6 P6 r6 O- y#if        0
0 B. o3 z$ u  u. k7 W7 N                // DC惉暘偺僇僢僩
6 e; z' T7 u% P# ]2 Z; ^2 ~5 u* C                {% w! d  L* ], F; F- \
                static double ave = 0.0, max=0.0, min=0.0;7 f" S1 G/ z& Q+ G
                double delta;6 t( a. c8 e( W0 ~: i
                delta = (max-min)/32768.0;" p+ W$ F* @1 \& L- Z# Y2 W! e) |. `2 O
                max -= delta;3 V4 f. G2 o$ ~" m; S9 V
                min += delta;4 @+ Z: O# }& O% p5 r) q3 }* p9 O
                if( output > max ) max = output;
' B9 l* w+ c+ N4 }: Y, O5 i                if( output < min ) min = output;7 P/ @- k! a4 N% Z8 k
                ave -= ave/1024.0;- c/ W3 z, j' y1 }( F
                ave += (max+min)/2048.0;& F( o( n% f  i. m
                output -= (INT)ave;; y2 m5 X2 X/ y0 [" I
                }2 B  l2 M# W5 |. |7 y" O7 K
#endif
8 r2 c$ h/ v9 u# _3 f#if        1
/ v( u/ |* X$ m8 U6 d' E: S                // DC惉暘偺僇僢僩(HPF TEST)
. u0 n& o1 x' x% X7 u# l                {
: t) |8 t% t) e8 {5 t+ n/ X//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
% R( N! P1 Q9 B& |4 z                static        double        cutofftemp = (2.0*3.141592653579*40.0);
; d& ~+ r) }" \' J, t$ Q  t& ]( ?                double        cutoff = cutofftemp/(double)Config.sound.nRate;
4 R" \; n) w1 Q. s: M0 `  |                static        double        tmp = 0.0;8 y% t) ^' @! A' [+ `
                double        in, out;
1 e$ a4 x% _' [9 L: {$ N3 L0 _& B: H! z$ Y% `4 b
                in = (double)output;2 w& \8 v7 n1 w2 r7 l, S  H
                out = (in - tmp);
4 H! a  _8 F* y" N1 E; H* q                tmp = tmp + cutoff * out;
! [$ ]& T% C" V( }- F/ y4 F. c7 g  R) o% J& w) ]
                output = (INT)out;! i; H4 U" ]3 j; z" \
                }" F  l+ ^9 [) a7 Y* H
#endif8 p0 ~- q8 I# H" D& y  k
#if        05 C$ q' M( N7 w# t, O
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 Q4 O4 e) g, L4 y
                {6 ~3 k0 u9 V! U1 ~/ b6 F4 v  V
                INT        diff = abs(output-last_data);
+ f  }3 x( V% I* A2 r5 Y                if( diff > 0x4000 ) {- Z; o( W1 E8 J& Q- z0 ?
                        output /= 4;
. M- n! z4 P8 U                } else
9 H- H+ ^/ I! c% k: ^                if( diff > 0x3000 ) {
% T( N& z% A" \6 q                        output /= 3;8 D2 `% m( X0 d& X, @) x/ j
                } else
  w, Y* y% s) ]7 v, X                if( diff > 0x2000 ) {: Y/ {" l8 \" x8 L  g* W* w
                        output /= 2;
" O6 Z% X. I, ]/ p3 k2 l                }) L- I+ y* M( V4 j, S' e
                last_data = output;0 M% T, s+ i- L! z3 e" v7 W4 z
                }$ w$ o0 E- a" j3 u9 K
#endif
/ E- {- M2 o, Z& R! N2 n                // Limit, `+ i/ `3 u6 h0 S4 g. }
                if( output > 0x7FFF ) {" Q& o1 Q0 P2 a
                        output = 0x7FFF;
2 A! \! l# v9 N                } else if( output < -0x8000 ) {
. r8 Q. F  X/ n) R                        output = -0x8000;
- \4 H4 R; ~. j1 T6 `# L9 O                }, H2 f1 R8 b% Y' Z
6 K3 W6 `" l& l7 @2 k) T6 ^* Q
                if( nBits != 8 ) {
& r7 o0 Q! ^. H; R5 ]3 j' w  R                        *(SHORT*)lpBuffer = (SHORT)output;
6 d& u6 r5 s' d+ g- k* v" _7 F                        lpBuffer += sizeof(SHORT);
' c! C( p  u6 I, f$ @  V                } else {
# Z0 c; r; h: |, m# A                        *lpBuffer++ = (output>>8)^0x80;
0 }7 D% z$ y# j0 W; v3 G0 g                }
% M+ G) S3 H4 D# ]
0 U+ {8 P4 z$ x- @7 ?                if( nCcount < 0x0100 )7 I8 |! @  g4 j
                        pSoundBuf[nCcount++] = (SHORT)output;! Y* s8 ]3 _+ W" p
" V# v( ?' `7 v- F( Y. X& h6 V
//                elapsedtime += cycle_rate;2 I' s( O& t4 L2 X4 O4 O
                elapsed_time += cycle_rate;
' ~) e4 ]' g* C* h% h0 O# K! L/ Q        }. o  R8 @+ p$ M3 [# s, e3 i
4 ]5 }" H& F3 G$ P$ t. L! }
#if        1
9 ~4 A, I* b8 q* S5 h        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {) z7 j1 u1 ~" }) c% k2 E
                elapsed_time = nes->cpu->GetTotalCycles();
5 l1 _9 f- W- i7 c        }
4 @& e' T7 Z  [7 J6 |. I" n        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
' J; s# {. p+ S) \9 h9 Z7 {                elapsed_time = nes->cpu->GetTotalCycles();4 M) L5 z& q+ K) Q: l# B, [6 T
        }
- v% {( C9 j5 x+ ]! v9 j. v#else
; v' K5 Q  G& n* e3 W        elapsed_time = nes->cpu->GetTotalCycles();1 q$ o+ ~" V8 r# {! o6 Y; I1 K
#endif
+ }2 m; e* \4 o, X}
# Z1 D" f4 j- B2 S# j1 K& P9 \% S9 K& J% c! |  w% c" {7 A* `
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 ^; `: P9 F' V4 Y5 h$ r, hINT        APU::GetChannelFrequency( INT no )
6 Z; t" `  u, C% Y1 C{2 a& z6 c4 X/ l9 |( p  o2 g2 \
        if( !m_bMute[0] )6 p, d# [! u% K5 [, p5 i7 F
                return        0;
4 D# H( M. r. x1 y& G6 j1 _. a1 O4 v& v( a) f1 S
        // Internal6 }$ }) `$ o, X8 V3 m7 @- v& @
        if( no < 5 ) {: Q' C/ r6 E, K- K: v6 ~
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( A7 O4 f) @# t, Q& R        }
0 x; m/ @6 W0 ~; O2 a1 ]  ~/ }        // VRC6( u: C3 [0 \2 M/ B% v$ i( f
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ ~/ W3 V5 {* |; C1 r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
: x2 y' D9 i; h  g6 e        }$ x# k( ~( o; M8 B& X* M& U1 Z
        // FDS* G$ j4 g, E, t/ g3 a6 p
        if( (exsound_select & 0x04) && no == 0x300 ) {
6 V- H3 P# |; X5 h; B                return        m_bMute[6]?fds.GetFreq( 0 ):0;
( B+ S6 O+ b6 |5 R/ S        }
4 u1 ~; F/ M$ Z3 G3 }        // MMC5' V) @# h; h2 M, ]% e" b0 E
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ y5 k% `" h* J- d                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ d( o, D& Q( _
        }
: x5 @; @% b& k; [3 \5 Z        // N106
( Z! u  f0 y) _  G5 R4 q! e        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) A$ L/ J4 Z1 O5 O
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ q  O6 D% s& d  l. P- {; I0 a( P        }; {5 k" c% J6 X' I/ U
        // FME7
+ s; w; u; G7 P8 {8 m+ }        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 ^- r6 P+ M( Q* n, X7 @1 Y                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;2 {3 y3 |2 |5 W
        }8 W5 ]" U5 j! |6 p1 c" _" n
        // VRC7
; o5 a; O5 V1 F1 N$ u0 V1 L        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
6 U. c3 t2 ?0 n8 l                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;5 `% J0 r8 l5 s0 T7 ^) s! \5 F
        }
& y3 S4 o+ T4 K/ a, x        return        0;
% T0 ?- q& W$ m}
- B3 p8 f. X- |, ?) q# i8 n) ~
// State Save/Load/ H8 E( P$ e: z8 b1 Y% x
void        APU::SaveState( LPBYTE p )+ Q' C1 `6 k1 r2 _1 ^* W
{; A% t, j# @- U8 ]& w, _; F& x% ]
#ifdef        _DEBUG
* d$ V. _' ^  Z6 jLPBYTE        pold = p;
' z6 r5 ^8 I% \8 `# i; t+ g#endif
4 D# o4 U, F6 V. D+ }- `3 y) t& ^0 q8 O4 C" W; h% u  F  y
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 i+ W5 J1 x  e, s+ L9 D) x4 H  n        QueueFlush();
3 O3 }3 D1 L# C8 x$ r6 @/ a& d1 z7 Z* l3 w+ b  A6 M, a# A
        internal.SaveState( p );
( T3 c& ]8 T3 l* }0 \        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 Q; p& T- @3 |6 m2 S
" d9 f- U9 [$ I5 p
        // VRC6/ H. E0 [! q9 R. t1 d
        if( exsound_select & 0x01 ) {
& _4 M1 ^+ q  J- w" z8 y. q                vrc6.SaveState( p );- p' q5 w5 T. W; p5 ]) L; R
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 \5 \% }! v/ v+ U4 i* _0 D
        }
/ ^6 U1 ~5 n- P, h0 S& Y5 k" F  E        // VRC7 (not support)
; j- K, u7 C, F9 W        if( exsound_select & 0x02 ) {
' A. U0 `$ z; ~3 `                vrc7.SaveState( p );
% Q( Y2 Y  R# k                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: l% Q4 f4 |- N1 K        }1 M$ X3 k& @; m4 {( B7 n1 c8 _
        // FDS
* [* b% Y* A% X        if( exsound_select & 0x04 ) {0 _0 s, h/ d& |- ]/ [9 O+ U
                fds.SaveState( p );' g% L. j* r! \1 A: A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 A2 O' [0 c, A; q' ^        }
1 {5 J" K" G. `4 `3 w        // MMC5( i( o- q. m! S7 W3 }
        if( exsound_select & 0x08 ) {
. O" R% c% I/ ?                mmc5.SaveState( p );
8 e  ?: s' R6 n/ l& ]                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 x8 Z% ?5 v9 c$ ^        }+ ]' v: b- r. e) F( Y( `- U# p* i7 L
        // N106; L9 _( M1 a5 B+ E- C( ~
        if( exsound_select & 0x10 ) {
. k9 ]$ u* d9 m* v9 m6 ^! y                n106.SaveState( p );
" X. J+ }; w9 l" {& X! ]  b                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 s$ a; n5 a; \, B# ^, ^
        }
8 Y- u, g9 q/ U7 E# K        // FME7! }. Z* M+ _# w/ Z3 j+ U
        if( exsound_select & 0x20 ) {
+ b; ~) z1 e7 Q9 Z                fme7.SaveState( p );
7 C$ l9 X2 O5 z2 F                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding/ g# p8 v6 b; P& h/ s0 b: ?9 ~9 o; [
        }5 x0 b0 u% q. R
; S; K; h& G. ]- U
#ifdef        _DEBUG6 W- @) L' F- b, a5 O2 x
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! n  H0 J0 a- S#endif
( q8 t2 a3 X6 Q- C}' f! Z* M3 ~8 G7 Z- a: h! p4 @) f
% w, B! q4 N0 c$ m) k# k
void        APU::LoadState( LPBYTE p )
# x7 z! r0 O+ v) W{. W! t: L, t" d' A  ~
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. F& L* r  c5 h6 V: {        QueueClear();
5 w9 v3 [2 C) z/ {: P$ j1 P1 ^- ]2 M) a$ t+ P, f8 B
        internal.LoadState( p );" u' w# ~# D8 {: T; b7 P7 C
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( X4 `/ n  X  I+ J$ r
5 v, L; f+ y0 A! L' Z- R! }! f  C        // VRC6
0 V5 Q4 k; |' I# T' X& c) s        if( exsound_select & 0x01 ) {
7 z7 a0 }+ s! e: T$ d% e                vrc6.LoadState( p );
0 u1 M: |6 ^6 ]2 {0 ~: A$ T3 B+ S7 A                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) {; t6 T2 y. ~8 `5 q0 R        }
/ j& Q: B9 W# ]7 G/ z; [5 j        // VRC7 (not support)
; T3 J, _* I; V; c& A) ~, M        if( exsound_select & 0x02 ) {
0 o+ s: T+ L, B3 l$ E/ W& I. D, @                vrc7.LoadState( p );+ R/ H7 N: |& ?
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
' ?0 q0 s4 D' g# B1 q        }2 x1 y1 U. U& X; v& @5 p( D
        // FDS/ O" V  L. q! X% O: k/ G* n' w
        if( exsound_select & 0x04 ) {, `8 v1 \, O2 W" C+ @" L5 k
                fds.LoadState( p );
7 e% ?5 S, Q  m1 K) l. R                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding3 j& q( ^3 ]8 {% N# U) P: B: G5 _' F+ g
        }
9 G+ \" p* r6 F2 r1 p) y' E6 A        // MMC5
) L) m$ c: |4 b$ |/ J        if( exsound_select & 0x08 ) {
1 f! W* g7 ?! P$ Y$ a. q( o2 y- p; Z                mmc5.LoadState( p );
- f  o1 {1 q6 z. A0 X& Z3 F                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
/ \, X* ^& X& s9 n: K9 c- U2 p        }
4 p  |; ^" u0 \! h8 M8 T" k        // N1063 }2 C. U4 ~+ n  m/ l0 F' ^
        if( exsound_select & 0x10 ) {
+ T( ^3 r/ U! V$ G3 B                n106.LoadState( p );
) `- ?4 Y4 Z0 Z4 y$ O6 K, o; }                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 T3 y) A  ^7 I, p        }
' N# u% ?- n% ]% ^        // FME7! P# W; ^7 c' x- O' @: L# Q
        if( exsound_select & 0x20 ) {
- h; D7 O9 b! _  {, L& W8 Q3 V/ z                fme7.LoadState( p );2 L% X. f! S  M* j/ K
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 n, h% t5 K7 Q; H' \        }, x& P: i% o. S  `! w1 d7 ~' {
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
: c+ ?$ d) O- O2 Q' _* J可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。) {1 z1 K8 B$ d
感激不尽~~

* Q# U$ _% l* i恩 我對模擬器不是很有研究,; u+ ^* D: X$ b. }& k" C
雖然要了解源碼內容,可能不是很困難,
7 T7 P/ u0 \/ {# {" s" @: p% q6 u* f不過還是要花時間,個人目前蠻忙碌的。
& H" ^2 t4 o7 c. ^) M: d) y' H% m+ M- \
給你一個朋友的MSN,你可以跟他討論看看,
# f( N: T' ]* H# J) s. @+ ^, P他本身是程式設計師,也對FC模擬器很有興趣。: z8 U" u1 [& D0 H5 D
3 l5 W8 a2 r: g$ f& c7 e
MSN我就PM到你的信箱了。! _: e5 F/ C2 l& H

' w2 a" I+ R! i0 g* 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 发表
+ }9 w: U( Q/ m/ w% G# |呵…… 谢过团长大人~~

" O6 e* x4 |- v2 v5 B8 s
3 O4 e5 Y' M, u4 |$ _哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 d4 c$ W2 ~# |. g) {6 N团长的朋友都是神,那团长就是神的boss。

1 b9 X$ a+ W* r哈 不敢當,我只是個平凡人,; P) [2 d; l0 U( E4 G
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
! q( Y6 T  v/ K7 ?! J" {- B; Y- MZYH
' g3 V6 C9 h9 a" vQQ:4147343065 Z. k) s3 c4 E# w
Mail:zyh-01@126.com
. Z# h+ |2 i5 }% e3 G0 J/ e
  q4 _2 [0 s9 c& @0 Q& w他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 # A+ }& |7 ?1 `9 i& q8 H
再次对团长大人和悠悠哥的无私帮助表示感谢~~

( U3 X5 w8 c" |. W# N不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-22 23:32 , Processed in 1.125977 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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