EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
  T. @' [  L. G% D3 U; ePS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 x( o$ _2 V5 x' L6 a5 }9 s1 j1 }& Y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, c& P% @0 m% g
这里有相应的模拟器源码,就当送给大侠了~~1 A0 t9 O+ }2 c' H, M; E
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # B) T3 [, f# D, N9 s
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ C. M$ i6 v7 r9 u
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 f" y, F- @+ \, q# [这里有相应的模拟器源码,就当送给大侠 ...
$ ]: r' a' k; U$ U7 t
聲音部分(Audoi Process Unit = APU):
3 u+ B, b& v7 v5 }7 l; [.\NES\APU.cpp
' y1 h) w! J! l8 {/ i% U.\NES\APU.h
8 {1 @, T# J9 o) h
+ g/ v6 q( B; F
& m8 V( n0 \' ~1 x+ }9 v影像處理部份(Picture Processing Unit = PPU):
! m& k- X; l3 ^; ]; k7 u.\NES\PPU.cpp) g7 g) j: H* I: K
.\NES\PPU.h% h4 b( f( S; c/ g: H3 H  W
4 l. {7 ]; Y3 ^2 H
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 h- Q2 C. {. i/ _1 u9 r: x
(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 w/ D5 u/ V, L$ E3 ~
//////////////////////////////////////////////////////////////////////////
$ ^; j$ p; C5 J9 e/ |7 z  O//                                                                      //3 f" C: H& {% Z* ]! f
//      NES APU core                                                    //% b+ e8 @, T' i$ x
//                                                           Norix      //1 g6 @' ^, F2 m
//                                               written     2002/06/27 //  r7 i; A4 f+ ^+ M8 b) w
//                                               last modify ----/--/-- //9 e3 u0 S" f6 r0 Y" ^0 |
//////////////////////////////////////////////////////////////////////////% K  x0 f" o( V+ L, P" W# L
#include "DebugOut.h"
' p* A) k) V$ n3 s) J  [3 k" A#include "App.h"
( h( i3 V/ d# \#include "Config.h"& s7 }" f0 B% h+ [/ w

8 p0 ]1 |+ |& u$ f! e2 m#include "nes.h"! c& |& s6 |& R
#include "mmu.h"
! E( P! m5 x4 ?#include "cpu.h"& L: L* ^, L! j- b2 m- p( H0 a
#include "ppu.h"3 m+ B9 a% }4 P/ p% a$ S3 G
#include "rom.h"
7 n+ b$ V3 }0 w9 Z& L#include "apu.h"
9 Q6 @, q& G0 @9 Q$ a7 K
' d3 U- ~2 w/ Q4 ~0 l, E// Volume adjust4 g4 y$ U% t5 D( L8 H2 ?5 n" U; q
// Internal sounds3 e* u: l3 A: j: a4 }- e9 X; s, y* t) X
#define        RECTANGLE_VOL        (0x0F0)
/ ^/ m/ w& d- O#define        TRIANGLE_VOL        (0x130)' v4 H3 |9 o: Z! g1 N" n
#define        NOISE_VOL        (0x0C0)3 W- ]/ m6 i; b& z* D9 _1 Q
#define        DPCM_VOL        (0x0F0)
3 I7 I/ [. r& B// Extra sounds
" O" \! m& g: P- \# B: X/ b. h#define        VRC6_VOL        (0x0F0); c. X, A6 ^# B
#define        VRC7_VOL        (0x130)
% b5 p0 y  {1 h3 Z! G/ R& ~4 P#define        FDS_VOL                (0x0F0)- E) M; f& ]* R4 n' ^: h0 U
#define        MMC5_VOL        (0x0F0)# ?2 L+ j  o# v9 b8 X
#define        N106_VOL        (0x088)
7 s/ f; q  ]4 p8 G) D5 @#define        FME7_VOL        (0x130)! c3 l& @$ E  J" L6 d

7 l! S2 f, Y) d4 e( x6 WAPU::APU( NES* parent )5 e/ a8 |1 L4 H
{
& n5 B$ w% Q3 u5 k$ n6 p0 l" x* r        exsound_select = 0;- ?1 T' H3 `2 n. G) {& j9 x
' L) c: J; ]' w
        nes = parent;
& g6 D1 A4 K6 c- x; Q; h        internal.SetParent( parent );  |$ [/ F- B& M. l- R

2 v) o+ Q4 g7 m! ]. b. _        last_data = last_diff = 0;
. @6 H  T. Q& {. K; p: K% I6 H9 j; |, e2 o
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
7 j+ l3 j6 N5 t" J% e( L
9 g! t2 B7 s; D$ k; L% K: E2 x        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );9 y5 G8 x, [0 T/ U7 T; H
        ZEROMEMORY( &queue, sizeof(queue) );- U- ?, m$ l* ?0 f. b# {
        ZEROMEMORY( &exqueue, sizeof(exqueue) );' b7 o$ {4 l2 Z

7 U- a/ Z, f2 t) h: V9 s0 c& C7 u        for( INT i = 0; i < 16; i++ ) {2 j1 u+ n5 J; {4 [( i
                m_bMute = TRUE;6 k8 n3 C6 _8 ~' H4 E5 R
        }
$ z1 E# R" b3 d}6 u* \* R- g1 r; T) b" Y+ {

0 `8 Y6 C" _" F0 NAPU::~APU()5 _- d" v$ Z+ u5 x5 c
{
7 M) k1 g' {8 p& \' n2 C# N}
* ^. }7 Y. a. A! n$ ^0 a+ a: w. n/ U; U& o% }, ^
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )8 Q1 K# D" X. M, u5 q7 w
{
( O( f/ M' m& Z% C+ n        queue.data[queue.wrptr].time = writetime;4 A$ x4 G7 P- j* y  i" k" r2 D
        queue.data[queue.wrptr].addr = addr;
" h; W. f* J+ G) D        queue.data[queue.wrptr].data = data;. R4 q1 r. ~: S* F9 a: g, O# y
        queue.wrptr++;" e' V- h8 [1 T; g: I
        queue.wrptr&=QUEUE_LENGTH-1;
/ o) w7 V4 I; r        if( queue.wrptr == queue.rdptr ) {
9 C: C% C: `, X6 S- c/ N9 r4 D7 B                DEBUGOUT( "queue overflow.\n" );; v9 Y2 |4 Q7 c* p; a
        }
( m; q4 ]$ v, y6 H}
' t% C! O, F/ L) m+ K4 p& I0 X5 m. g9 d9 `9 M& l) A1 \# a
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
+ f4 u* e! F) g0 p{
3 H1 b' E7 B; c* {        if( queue.wrptr == queue.rdptr ) {
/ d: ?; M$ M9 r3 o: _                return        FALSE;
% ^* D/ w2 p* R: C( ]        }$ F8 S" l1 X) G! ~! }+ k' [7 U1 z
        if( queue.data[queue.rdptr].time <= writetime ) {# m; }7 q" l' [2 S
                ret = queue.data[queue.rdptr];9 \3 B4 T3 ]. U% }1 A
                queue.rdptr++;
: U8 c' a2 {& u% h, C- F                queue.rdptr&=QUEUE_LENGTH-1;
; I+ U, M8 A/ n                return        TRUE;% {3 t( W6 A0 \+ F7 f2 v- J
        }
  M; y  y3 g% W8 v1 u+ C0 y7 _        return        FALSE;
% r# c! J& W6 I- f4 w- y& v" w6 {}+ c9 D( Y  F- c6 W$ {: w

; v. |" o+ r1 C5 Q3 Uvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  `, A9 O! U. N- I0 i
{
0 @$ |6 P# d+ Y& U- K        exqueue.data[exqueue.wrptr].time = writetime;
: Z1 j9 `0 Z$ T% Z3 j. N; {3 ]        exqueue.data[exqueue.wrptr].addr = addr;
$ J% {3 j# o4 w1 a5 d4 j! X        exqueue.data[exqueue.wrptr].data = data;
- u2 l- D6 I- k  Y4 J* P5 p+ f        exqueue.wrptr++;! f1 Q) K0 I4 T5 v) p5 a
        exqueue.wrptr&=QUEUE_LENGTH-1;
0 H3 \' y- D- p4 z7 ^  c        if( exqueue.wrptr == exqueue.rdptr ) {( i$ Q3 U, P5 q8 a
                DEBUGOUT( "exqueue overflow.\n" );7 h2 e& }1 }- M6 }5 A
        }
# g# @) b% s! O! s) s}
3 `. \6 z4 U! L# M. x" C7 t1 z! S  A2 P0 Y7 n
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
& A0 M# Z. a1 C{- C: w4 @: L% ^9 @4 }
        if( exqueue.wrptr == exqueue.rdptr ) {# H" Z; a7 R- o9 G! n: f5 r- c2 |
                return        FALSE;1 D' [6 u8 @8 |/ O3 i
        }2 \" x# @2 i) _- ?  N- ?
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) a4 _! d/ {1 [3 i0 G, T
                ret = exqueue.data[exqueue.rdptr];
% u3 E( l% ]' L. W                exqueue.rdptr++;8 R- }  a/ A# h2 @0 t& R( G' B2 I& t
                exqueue.rdptr&=QUEUE_LENGTH-1;& x/ l0 c8 \6 q1 Y9 Q
                return        TRUE;+ g- s, o% y6 ^" ~
        }1 d+ u# F1 Y; {7 b
        return        FALSE;
: M, O2 f0 t. h# e}
% P7 T; a# s& v' |) \& l! q1 ^+ C+ I  _0 r3 l8 p0 V9 Y* v" d8 u
void        APU::QueueClear()0 O1 Z. K; k+ W9 K& N& ~7 T
{- e2 P1 Y- m! P. `/ x; l$ ^0 x! r
        ZEROMEMORY( &queue, sizeof(queue) );" F) r7 }. l2 l; l. z3 i! \' K( m9 z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );( w6 v% ^5 y; T/ [5 W
}- v5 P6 |8 T% O/ j1 B. v
6 a5 G1 Z; s/ M: G+ _% {
void        APU::QueueFlush()* b; M7 p! M/ [6 |/ f
{
: Z5 q$ b* T* n: b0 s        while( queue.wrptr != queue.rdptr ) {
( v7 }9 O$ m7 j( I$ ?( K6 ^1 O" U                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; p" n5 s; P$ Q# e                queue.rdptr++;; {7 a% ]& G, n4 x; Q! P- {
                queue.rdptr&=QUEUE_LENGTH-1;
( n/ p5 T8 N5 o' G        }
# l5 Y8 R, t" \6 N$ H5 F5 x; x2 }# v1 b' b* m% O& {7 g
        while( exqueue.wrptr != exqueue.rdptr ) {  z& F  w6 t6 A
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
# E2 \- N- V9 M3 j, ^1 K                exqueue.rdptr++;
7 g6 n6 g" ~" G0 N8 b/ [                exqueue.rdptr&=QUEUE_LENGTH-1;- _: d# g$ R( p) b0 H  \" H# [
        }
6 P( ~) {8 `8 p) i8 M8 k3 _- k}
: u1 z! J- P7 T) Y) k
2 N1 k% D6 |  ]( n- Lvoid        APU::SoundSetup()
- d2 U5 b% G" u! _7 ~) L" L{0 Y$ C% i4 r' z- e
        FLOAT        fClock = nes->nescfg->CpuClock;
. Y2 x, S+ ]  }7 L4 F* ?3 v; V$ ^0 g        INT        nRate = (INT)Config.sound.nRate;
% S' `; i; t: S4 L3 J0 {3 A  U        internal.Setup( fClock, nRate );
8 Q% G0 h  _) b" y+ a        vrc6.Setup( fClock, nRate );
! E+ x/ k5 u" D2 ?' M4 Y        vrc7.Setup( fClock, nRate );
- K* e/ [- X  Z' g2 [# F( z$ ]! ~        mmc5.Setup( fClock, nRate );- h; k0 e6 T/ T
        fds.Setup ( fClock, nRate );
" s0 D  S! M$ _- k1 C        n106.Setup( fClock, nRate );
; G  Z% X* r4 z' \) k' l        fme7.Setup( fClock, nRate );
- [; j% h1 m2 D  x, \1 \& \' x}
. R3 Q( A* ]" w1 F
. H  t) ^/ Y5 L$ Qvoid        APU::Reset()
7 B( i9 y, c' z* k8 o{
1 W, w1 D( ]7 l: J) H8 a$ C        ZEROMEMORY( &queue, sizeof(queue) );6 \0 w& y& S" `( Y1 h
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: h8 \6 w# Y8 B& @. _, e" |- M
, D9 A$ l+ U( B4 F7 z        elapsed_time = 0;
8 f  v3 s9 C- Y1 C2 L  C* v6 l+ g' i6 A* o  R
        FLOAT        fClock = nes->nescfg->CpuClock;
# H1 g/ K/ \; [- @2 g1 ]        INT        nRate = (INT)Config.sound.nRate;# j7 n) ]. S3 P6 g
        internal.Reset( fClock, nRate );9 V2 s3 x( }; ~6 b. o0 r3 f
        vrc6.Reset( fClock, nRate );$ n' }* Y8 P6 h' u
        vrc7.Reset( fClock, nRate );
5 j2 `/ E5 h" o7 W! w& ~" J        mmc5.Reset( fClock, nRate );9 C$ M( N# U& n8 ^. x0 Y
        fds.Reset ( fClock, nRate );
0 v+ |; b8 S2 C) x  r1 A        n106.Reset( fClock, nRate );
2 A1 q8 o' P9 Q        fme7.Reset( fClock, nRate );
/ u  X6 t: Y# M9 H/ j  e  L9 I$ h8 Y' b5 H# J2 p, s
        SoundSetup();
+ l2 g( N; O# p" v7 b" k; U}
/ d) l6 `9 w5 G
4 l2 }4 y- D+ R* \void        APU::SelectExSound( BYTE data )' U2 h+ V3 D( I* L9 g
{! D) j3 T7 G! F7 w8 `5 R
        exsound_select = data;1 L2 m: J1 y& k% {
}
2 E0 W" C' M) O6 V# e
0 k" {0 d# v/ z2 ^, H! m( XBYTE        APU::Read( WORD addr )$ f) h3 l4 _7 `9 A5 [
{! k% H* b; ~0 }. v5 ?: h) l% U8 s
        return        internal.SyncRead( addr );
  w, t; e: @% m% l9 J  Q$ W" g}
- N; y+ Q" H+ r/ a" k9 {. ]6 }6 E& H1 Y2 A* J3 ?
void        APU::Write( WORD addr, BYTE data )
) F2 Z; }8 W3 C0 b  s. S{
3 r3 T- i- L0 d' R! B6 d        // $4018偼VirtuaNES屌桳億乕僩! {" Q2 V- m3 n5 Z
        if( addr >= 0x4000 && addr <= 0x401F ) {
' q4 _# N) \$ q/ v5 ~4 n                internal.SyncWrite( addr, data );; E. C) r" S( s8 x
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );0 N: s! j& X  G+ {! g/ K
        }
$ r# G4 r2 k  q- i1 a}4 Q. d, L: a  Q5 {9 w6 D" k

& [: ?% ?+ E. WBYTE        APU::ExRead( WORD addr ). I% q& G% E3 ?+ D. v$ Y
{
' V3 U! A% B6 E- e9 n' ?' ?4 nBYTE        data = 0;
' Z* |- e; S' Z
4 [4 `( J& A* @# t3 B* {        if( exsound_select & 0x10 ) {
/ s" u* h( O) q, z* A) T                if( addr == 0x4800 ) {
0 ^9 w+ L/ P1 O                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
" E7 @; }  X6 u$ G6 W) Y                }
& k$ x0 I; ~5 T7 \9 i; [0 q0 p/ T        }
5 ]- @6 b/ J# S3 p        if( exsound_select & 0x04 ) {) x/ y. w* {6 n8 q0 p
                if( addr >= 0x4040 && addr < 0x4100 ) {+ p  w& C' A0 q8 o
                        data = fds.SyncRead( addr );8 W1 T% m& o+ N
                }
5 z! [6 e; o. }6 t        }
& L% p1 _0 [; E. L        if( exsound_select & 0x08 ) {; N( q7 m. g3 l. @
                if( addr >= 0x5000 && addr <= 0x5015 ) {
% n; m$ H- D# \( E  Q7 ]0 e2 w0 l" v                        data = mmc5.SyncRead( addr );2 @- n, _* T+ p7 @0 b
                }; l( H: U4 O# A" r' v4 w3 C6 V2 [9 o
        }# |' A/ i; k  P/ r, s& s

# w6 e2 t0 f7 W6 T5 Y, {        return        data;9 y, Q  m. Z0 `5 F
}% G# K% K$ h" N+ \$ n
6 o& ^( |4 {) U  l, T% r% ]2 Q8 l& U
void        APU::ExWrite( WORD addr, BYTE data )
6 E, d" Q2 K) N) U{$ w- e# L- B; f3 [5 x8 |& G) F+ `
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );& O$ y# U  H. g' w/ e

) S* c5 O5 s  ]6 j1 y        if( exsound_select & 0x04 ) {8 D; j4 t: K% |5 s: g; G
                if( addr >= 0x4040 && addr < 0x4100 ) {* p! C) |( ]7 b4 o. W# }  o
                        fds.SyncWrite( addr, data );& }" b8 D# N9 \' t
                }
6 g$ u2 k$ [; h. F        }
3 L! N4 @5 D6 ]
" B5 N8 V$ I* p3 ~! K, T( t        if( exsound_select & 0x08 ) {
' @2 o8 ~9 ^; u; S. f/ ?! \                if( addr >= 0x5000 && addr <= 0x5015 ) {% x+ D% [0 K" u6 e& G( q
                        mmc5.SyncWrite( addr, data );& p8 b& _4 G" D/ v4 m4 l
                }
* I1 O+ `" ?+ _0 G: z2 R- k        }
$ H" `, y4 }& N6 ~  K- Z- y}! T# C5 |& l* H1 b2 |

/ c& T2 ?/ A1 Ovoid        APU::Sync()
- Q# c8 Y' O4 i1 q4 a+ H{* S- y* s7 {' B1 I) X1 {. G2 ^- T0 v
}
( A: S# _7 m- z9 [- b9 d' r% W8 H4 {- h1 X; Z) W
void        APU::SyncDPCM( INT cycles )
$ ?6 h" `8 {6 H8 ]2 G{
: [0 a8 Q7 J3 |6 B8 L        internal.Sync( cycles );
7 w7 K# V6 a( ^9 r, ?/ Q
( q5 R' Q2 K* D/ ?7 x" v        if( exsound_select & 0x04 ) {* j* \* I9 w6 U( r
                fds.Sync( cycles );
9 U3 s4 _9 w4 i5 u, A        }: V2 h. {  D$ |9 i% _6 i
        if( exsound_select & 0x08 ) {9 T/ M* U; P: U% W& q% p. j
                mmc5.Sync( cycles );' U: ^2 C9 y% c. s+ w8 ^- k2 ^
        }( B. F9 h% {% {1 N6 ]
}
) ?/ L" j" K9 z# |: `! Z
3 B* w) ~. B6 o" {1 Cvoid        APU::WriteProcess( WORD addr, BYTE data )
0 F5 w6 z7 e. T/ F9 F! \{3 ~6 r. z, w( c  |/ [7 z
        // $4018偼VirtuaNES屌桳億乕僩
- W4 O4 B! m3 G* F0 V, Z: S        if( addr >= 0x4000 && addr <= 0x401F ) {! v& ?" w' h) a. `7 T
                internal.Write( addr, data );
$ z: W, X5 G0 T! e4 b        }( d" m8 h# C# s! n
}0 I# s. G6 X) T1 h( x' s$ [

# F* A2 m( E' V' h3 u3 Evoid        APU::WriteExProcess( WORD addr, BYTE data ). m) Q6 g' W1 E2 ~* y
{4 ]  |1 t5 }" V1 V0 }
        if( exsound_select & 0x01 ) {
' m* f% X4 k9 ^. X. Y7 n5 ]& ^& G1 x                vrc6.Write( addr, data );
8 W! y4 {( B6 p* [5 Z        }
( D- ?5 W1 K  U3 V1 N' h0 U: p        if( exsound_select & 0x02 ) {
( n9 W- U. X5 D( M                vrc7.Write( addr, data );
8 R% Y" K* k9 I$ |3 y0 A, `) ~! P0 R        }. P1 v! R/ P6 m0 s5 n8 s. x" q; _
        if( exsound_select & 0x04 ) {" W7 z4 y* N5 _( H1 B4 p3 W
                fds.Write( addr, data );
' J, C0 N0 f9 q- \' H- u; a; s( I        }
- |/ i& A; t' j" l* O; z5 {1 K! W        if( exsound_select & 0x08 ) {3 b$ C9 C& q0 S* W; ]
                mmc5.Write( addr, data );
! A! B% x: k0 o0 k, e/ w; B; t        }
* k2 o* p+ v' X3 \* q: z; |        if( exsound_select & 0x10 ) {& i0 S; u2 W, {+ h2 a4 o
                if( addr == 0x0000 ) {* B# x3 ^& b: ^0 ~( Q: a% a
                        BYTE        dummy = n106.Read( addr );0 E. h+ k; |" |" ]- Y0 [; g! K
                } else {0 d. S8 k) f. S3 M6 u$ y
                        n106.Write( addr, data );9 i( g* t4 E. }& P- ]
                }5 m- g5 K& l5 M  s5 r" ~
        }
# N. q, J: `( K+ t% t. X1 |* Y& ?: P        if( exsound_select & 0x20 ) {+ X" K7 U( f4 d3 d7 J2 f  F2 g' }
                fme7.Write( addr, data );! y, |% R1 Q, n$ ^6 v; _
        }7 o, J0 ]! i0 H( X4 E
}
7 N5 c* g/ F6 o/ V3 A7 g0 v. U4 D' T; d2 H0 Y# E
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ v7 ]: F" t" \7 z5 v9 x3 ]{
! v6 t% ?7 r( o5 W% ]. EINT        nBits = Config.sound.nBits;2 Q' ~# n0 x* _
DWORD        dwLength = dwSize / (nBits/8);
" }- d" N, ?. w, ]; K& \% S- gINT        output;+ c4 f7 u& Z& ?7 I7 I* @5 k
QUEUEDATA q;# S# K0 E; P# D3 P6 g) i" O
DWORD        writetime;
! U: K9 p5 ?) |
* W5 p0 B( Z/ [- {: b. u7 ?LPSHORT        pSoundBuf = m_SoundBuffer;( q1 d) |" g" b3 E3 T( z; f6 p! I2 m
INT        nCcount = 0;( c& r; o7 r* i4 q# D+ v

  E% L& d* t- h5 oINT        nFilterType = Config.sound.nFilterType;
+ E3 q; V4 c& q/ O, \8 ^9 ?5 ~4 M  @6 \4 q' _9 v" q. w
        if( !Config.sound.bEnable ) {; Q& v, ~5 ?* {" S2 j# Z  ?" l
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
9 a4 g: T4 a/ x                return;8 t' y5 w3 J, j$ P5 R
        }
: i: K9 a) y  t0 `2 @4 m
( T# m& W' ], N        // Volume setup1 m2 W. S; z+ @# b
        //  0:Master
! j9 L  L" }; p2 F: b  @5 w        //  1:Rectangle 15 q) I! ^8 ^! Q5 S5 X
        //  2:Rectangle 2
8 W/ d' y9 [, F! X( h5 L1 a        //  3:Triangle' G8 I4 F! O- L" i% J
        //  4:Noise3 I6 L% [1 @& L# U) B! ]
        //  5:DPCM6 `$ h- B  ]5 X+ U8 `
        //  6:VRC6  i( Q- p9 n9 q: c+ r
        //  7:VRC70 a" g* X0 B. j0 o
        //  8:FDS6 M$ L5 g, m+ Y, Q, P( N
        //  9:MMC5, E* u$ Z4 n0 g3 Y$ {& s$ ^  x
        // 10:N106! ~2 u! ?, A. v% w
        // 11:FME7. j- a; v$ x6 M& k8 d
        INT        vol[24];
7 k) ?* O+ V1 j3 K) I2 G# ]- K        BOOL*        bMute = m_bMute;
' I2 t- s; [  g& l5 _4 W( z4 ?1 L        SHORT*        nVolume = Config.sound.nVolume;
3 ?: y: \( J! m: P' U1 R/ U" |' h- a9 B2 [, j3 w. p
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
) p/ E" l. X& A
- O* y2 \' y2 a6 X        // Internal
. w" L. c* ~2 h' f2 S9 E( f        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
' Z2 U6 W9 s8 y) k3 R        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
( i* H' M! a; ~7 H- ], u        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;4 A& D$ y' v" j) L+ x# ?9 l
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
$ `, O, I  s; x( Z        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, U4 ]+ Y% x0 ~3 u

) c: N) J# H$ R; z3 G        // VRC63 A$ ?( o% e  Q) t1 c
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
9 T8 h' [! n. Y% ^        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! U4 ^6 J! e! l* H8 P' Z- ~- i0 P# X
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! r- A6 A( X( R, F9 M2 |8 _

4 X) ]% ?8 s& c! k# Y9 y        // VRC7. m8 J* m- T9 G0 S
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
' z: Z( ]3 M# f' G, h/ ~& \0 ]- U! e3 x/ r) d
        // FDS8 [, v7 x) f, J/ h: p: Q' W
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
4 q9 D( e+ [: ?* G4 ~) q5 `/ o# G5 i7 j) v
        // MMC5  [1 c0 g" l2 ?5 s2 b1 e+ V
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 E8 i! v" e7 B1 m6 W7 U        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 |& k" T# X  Z
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% `( u7 e& m4 l/ }
) h5 ~9 j: k9 b% V        // N106
+ R+ r# f5 ?& i# E) J5 H- K        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ _) z9 K  E2 F! p  u# N0 W
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( b# f! }' G+ Z9 h9 B        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, Z7 z1 v( _+ `9 N/ `        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* l& F; m( w! m9 n4 v
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) M9 Q4 |" r( ~% y1 X
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# Q2 e. l/ t# y* N5 V5 E) U        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 J! C- Y8 f8 b% [3 y
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# @  v! y1 M; {5 A4 V

, e- E& D/ R! P4 M& X1 e0 O5 ^) i        // FME7
+ A; g( c. M  f% t) x! @$ k        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  ?8 @- [2 q, ]& K& r! J) Z/ N; U        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;. \- Q, M9 n  J& J7 E/ D. H
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! O( m' C$ j! ]" v3 o5 g/ b, }

2 s0 e) V1 u5 o% \//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& }# W$ g2 g! z        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;8 c; M7 |+ z7 P3 ^# i5 v

, A! H& B5 n# X, y        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟- k1 f4 e8 X- e. {5 r0 J
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {$ _9 m5 D; V* b6 l8 Z7 m) z5 {
                QueueFlush();
/ z( r( E! U+ p0 M5 m        }% |- j5 J+ ?) V

8 }5 K1 p* E% @3 t6 t  `1 w8 D7 s        while( dwLength-- ) {4 Q1 G" I9 G2 k* Z5 M- {: `
                writetime = (DWORD)elapsed_time;% [/ T* ^6 N2 z5 a. S( D' V1 m

( U* k6 U) g1 d  G5 E                while( GetQueue( writetime, q ) ) {2 [# \, V- N8 h6 m9 }$ G
                        WriteProcess( q.addr, q.data );
% Z8 x: l% f$ O. b- Q4 T7 `* |                }
7 U" D1 c9 w8 q* y! S+ g' k
/ C) Y3 K: P! y% P, d: ?& T  D4 O                while( GetExQueue( writetime, q ) ) {
2 P- S* p; T% K" i" W9 Y                        WriteExProcess( q.addr, q.data );
& R) U" R" d# c6 e! ~0 }                }
: O) Q$ `, H$ f5 L0 C( v+ R7 }5 W0 c' f* O7 f
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 q# w% c- M: q- S( `, x1 c                output = 0;
  |0 i' @) F+ F1 g6 e                output += internal.Process( 0 )*vol[0];
! l: P  W% t% v. w) [! u                output += internal.Process( 1 )*vol[1];7 h% o# L7 _, i# b& p  X: @) O# B
                output += internal.Process( 2 )*vol[2];
5 H0 I- y- N. z+ G9 a3 x7 |                output += internal.Process( 3 )*vol[3];
% z/ d. P! Z) |9 b9 k: l- C                output += internal.Process( 4 )*vol[4];; f% B! q) l' g- X- I0 ^$ \

2 C; N- Q# {& n1 _                if( exsound_select & 0x01 ) {
3 g& W; S5 S; q5 N6 S                        output += vrc6.Process( 0 )*vol[5];
* R! X# N4 d* T1 a% }% k                        output += vrc6.Process( 1 )*vol[6];. G1 k, M, U( l+ C' |' i
                        output += vrc6.Process( 2 )*vol[7];
" m. R5 O' L# X& |. e) v9 d                }, q, r. o3 F) c, o% _( Q% Y8 \
                if( exsound_select & 0x02 ) {- n3 {8 _( P/ M! q, J7 Y7 a
                        output += vrc7.Process( 0 )*vol[8];& R4 q  e* \8 R' Z9 k
                }
: p9 {9 P+ q9 b                if( exsound_select & 0x04 ) {2 U) K" j0 [( D( ]. W+ t, X
                        output += fds.Process( 0 )*vol[9];# R( P2 z; p, V1 ~, Z
                }1 J5 a' g0 @2 Z
                if( exsound_select & 0x08 ) {
. B5 b& G) Q/ s$ F& E/ K+ L                        output += mmc5.Process( 0 )*vol[10];& Y& s& e+ @  C- |8 w* N% B
                        output += mmc5.Process( 1 )*vol[11];# q! Y8 s0 C0 ~# a( |
                        output += mmc5.Process( 2 )*vol[12];4 X" t9 q3 A# p$ u/ j/ V( Q
                }/ V. K3 a' ^3 s- |$ k
                if( exsound_select & 0x10 ) {# V9 I& j5 p4 p& o
                        output += n106.Process( 0 )*vol[13];' n$ B" W2 B. U2 @
                        output += n106.Process( 1 )*vol[14];
! R: c; F5 Y/ ^                        output += n106.Process( 2 )*vol[15];
* A7 t8 Y- W6 i" F1 W: p, @                        output += n106.Process( 3 )*vol[16];* ^( m5 c$ r/ @
                        output += n106.Process( 4 )*vol[17];
) Q  o$ G# p* `0 ^" i. c6 g                        output += n106.Process( 5 )*vol[18];: k1 g/ S; M  |1 e8 k
                        output += n106.Process( 6 )*vol[19];9 i) W# q& f$ r  U* b) V! f; y) |* A
                        output += n106.Process( 7 )*vol[20];: s  k: G: [+ `( R
                }
  ^' N0 `( l0 b5 C( o                if( exsound_select & 0x20 ) {$ E/ ?1 v0 o8 v* P+ H9 w+ f
                        fme7.Process( 3 );        // Envelope & Noise8 q/ z: S5 f' J4 _
                        output += fme7.Process( 0 )*vol[21];1 f! l. |1 U: A9 c! [
                        output += fme7.Process( 1 )*vol[22];" X, ], e1 Y% n) D/ Y
                        output += fme7.Process( 2 )*vol[23];
' q6 e6 c; Q3 n6 j0 ?$ _2 g" A                }0 G( F3 P- v; y/ j) N7 ^
6 @& P/ p( T; `# h
                output >>= 8;
" x' k  s# E* q7 q9 ^1 c0 t: a
1 Y9 L& X( `8 W! k# j) r1 I                if( nFilterType == 1 ) {
5 |1 R2 T( {4 y                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 K2 @2 z' h1 M) Q
                        output = (lowpass_filter[0]+output)/2;
- v6 M. f# |% _% `* k+ N  d                        lowpass_filter[0] = output;1 c, X0 h4 M  b2 B: W" q: w
                } else if( nFilterType == 2 ) {
8 M' I" Q  O: z% f: L0 w4 M) d                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- X+ z. O8 Q5 X& x
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;" C4 M. d9 J1 s9 q
                        lowpass_filter[1] = lowpass_filter[0];* B: I$ D( D7 ]0 z9 b% L# M
                        lowpass_filter[0] = output;
  n8 O: @$ {6 w                } else if( nFilterType == 3 ) {
2 o/ }' R/ D4 K) x                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)' X: I* i# `3 Y" Q) o! O8 d$ [
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;1 Y" v8 z4 `8 O% _, x/ J. O
                        lowpass_filter[2] = lowpass_filter[1];
( ]3 ]) V' X( V; {. G                        lowpass_filter[1] = lowpass_filter[0];
: h4 {9 G0 p- E9 {                        lowpass_filter[0] = output;' X# Y% X0 P/ G4 d" Q
                } else if( nFilterType == 4 ) {9 i. b: n; e: w. U% Q
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)* Y; ?  R$ q! q( d$ m
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 T# y; M! s8 [0 C                        lowpass_filter[1] = lowpass_filter[0];
1 ]2 Y3 c+ g6 S9 L; `. ~                        lowpass_filter[0] = output;
. z: j5 B4 q4 ^' O2 X                }2 U' ?$ H3 I, O
' R- F& \0 B$ s" H) s) N; Z
#if        0
, l. M* v5 N; h6 A                // DC惉暘偺僇僢僩1 [% S" Y7 ]- I7 }' D/ ]: n( F$ ]) a
                {* J8 \* S- y+ G5 {2 E2 d
                static double ave = 0.0, max=0.0, min=0.0;
1 w& z7 L1 {/ y$ l3 m/ H/ S: P                double delta;* g. u  L4 m0 M1 I; K
                delta = (max-min)/32768.0;
1 Q/ u: r6 ]2 y1 o, o6 w                max -= delta;
4 _7 G& H- y- Y' p* [                min += delta;
- L9 ?9 u2 _9 d: C: @( ^4 a# Z                if( output > max ) max = output;' n7 z6 ?7 `. b4 O' k
                if( output < min ) min = output;
. z0 Y" q0 Q& Y1 y# ?% V                ave -= ave/1024.0;. H  N  ]* u) o  z$ h8 ?
                ave += (max+min)/2048.0;% [) q% _; x) h% n  n: ~
                output -= (INT)ave;' y7 x% G. O7 c4 M1 K( z
                }
1 m0 m* K6 S! L- ]% X! E; s#endif" `5 T. n6 Q) u
#if        1& i0 ^' u+ y! U) p. P
                // DC惉暘偺僇僢僩(HPF TEST)2 [$ o; D; ?4 H7 n+ M$ O  T& V
                {
+ Y  Z+ e+ p2 u3 b$ t; d! ^//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);" z. c# F, p( v( `/ T
                static        double        cutofftemp = (2.0*3.141592653579*40.0);4 a4 i& l5 J: I, w1 P8 q# `6 Y
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
" R. {  e- J" _9 [8 _8 a                static        double        tmp = 0.0;
3 V- a; }2 U" Y/ @7 \( `% u" M                double        in, out;8 ~  X) c- A! H! n

3 q: s! x0 B7 \! m; X! U# y" r1 ?' N                in = (double)output;
+ {- O& a2 t1 P# u                out = (in - tmp);; W1 h( U1 |$ n0 }
                tmp = tmp + cutoff * out;& [7 H" m( y0 ^, y* E
  K$ e1 c) L. }9 Z  _- X% P7 @
                output = (INT)out;
3 I9 p& b% q# M$ d( q5 Y/ g                }: `, D( d+ @0 E* O( g4 O% P) f
#endif# L! n5 X: k) }
#if        0
0 b, z1 H$ j, F8 [4 J9 D7 `* G                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 |5 P. k# m2 f1 _, D2 O; @
                {
; D' `7 Q0 b9 ^- f% K5 p! K  s5 s                INT        diff = abs(output-last_data);4 f2 Y8 Z7 D- f5 Z1 O1 c7 p
                if( diff > 0x4000 ) {! \- Z' j# Y9 D3 j7 w
                        output /= 4;( `+ [! ^8 R1 H  P
                } else
8 P5 ?' H2 k# H: `) K: y0 k3 E                if( diff > 0x3000 ) {+ I! k* z2 k# }) L3 h
                        output /= 3;
" k: f3 `3 ]7 V0 o1 h                } else
5 ?: N4 {5 h% N+ o+ s- ?                if( diff > 0x2000 ) {
1 C& w5 a. v* r$ s& F: E: g                        output /= 2;
! f# U* y  X$ a8 T2 Z                }
, [+ v9 Y, d4 c6 t. S                last_data = output;7 y& Q% ^7 z0 Z! r
                }
( k' j$ X  }# _$ f#endif
8 t0 A$ T) X; f                // Limit0 ~  _1 J+ w% A+ Z- ~3 t
                if( output > 0x7FFF ) {
9 s2 P1 m* P6 `6 w" Y5 N# Z                        output = 0x7FFF;, S; A' x# v! i+ T8 ]' h
                } else if( output < -0x8000 ) {' R$ C, {" q4 o; a' }; ]8 z
                        output = -0x8000;
! y' o3 D& s% X$ F                }
$ Q6 k( a9 F( U4 I! G, C  I
# t6 Z3 k, I3 n- }& c. f3 d                if( nBits != 8 ) {/ g; s+ ?( S5 z! ^
                        *(SHORT*)lpBuffer = (SHORT)output;8 B, T7 T# i; e5 G# \: r6 N0 y
                        lpBuffer += sizeof(SHORT);. l& e" t4 }) @1 k7 G$ F# ?6 `
                } else {
7 d9 o9 G9 w. }2 w" L) f                        *lpBuffer++ = (output>>8)^0x80;
: D5 T2 t1 x' [; [/ P                }
  K9 i% f2 R' U
9 L3 k& j3 w, y3 `$ @3 l2 `' l* C                if( nCcount < 0x0100 )
1 p6 [/ f6 ]& J' _0 k3 c/ l; }! c                        pSoundBuf[nCcount++] = (SHORT)output;4 f) i. _7 ?) a8 h  u

5 k: Y: I/ A: U: U' t//                elapsedtime += cycle_rate;
8 h" \: e' b; g. B  O( a. g2 J% T                elapsed_time += cycle_rate;
% ^7 w2 h6 [- C% N; m" Z* `        }
+ C- W! w. B& {& E: ]  s4 S% D: ]# ?: V: j0 v6 P; S) U
#if        1
' W0 a1 U" B6 _, H2 f% J! a        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
0 B3 B6 Y4 B* F  u# x                elapsed_time = nes->cpu->GetTotalCycles();5 L, m( p2 _: u7 L# c" Z
        }
( n$ _2 F6 I( O; L4 `/ Q        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
4 O5 x9 H3 e% E, l* i8 e& A3 g                elapsed_time = nes->cpu->GetTotalCycles();8 ]( f0 {. r5 X: c( w2 z8 G$ c- h3 J
        }
! |8 {& y+ M. u/ Q! ?* W5 a#else- p7 n3 M8 w( B5 q3 s; b
        elapsed_time = nes->cpu->GetTotalCycles();
7 o; E4 Q% E8 G7 [6 S  C#endif
+ n# W5 U/ Y8 ?3 ?  L, W}" d! ^5 {* v$ l! C/ G

2 ]  W, U) F, A' V// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
7 e- S/ T* f$ q& {! v; zINT        APU::GetChannelFrequency( INT no )/ K3 i/ ~+ k+ i* i0 o, [
{. [8 S, l, P8 _* [1 C% X" Z- G
        if( !m_bMute[0] )
+ J" V' ]$ K( r: E8 s$ U! Z; Q                return        0;
0 X% c- \. `1 D) u% Z) ?# f2 Q# @" Y; C
: y' [/ j$ D$ }3 ]' o5 g. C" }        // Internal: H- o$ z: J5 r: c# r
        if( no < 5 ) {* w. p* ^9 D% c4 o# H
                return        m_bMute[no+1]?internal.GetFreq( no ):0;: K$ h% r7 A% o6 p- N
        }- e- `5 f6 h" [2 ?, E  s8 f$ J
        // VRC66 _/ j) w& Z  G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
6 ?) a# j+ f+ {: v' @, c9 u. R                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
" e. K9 _, y: h0 g        }
' V$ H0 U1 |! x        // FDS6 O. j% B) p1 l3 \: P
        if( (exsound_select & 0x04) && no == 0x300 ) {
" Z- \" w$ ?* B# o) C" d' t                return        m_bMute[6]?fds.GetFreq( 0 ):0;& p0 n  W: K/ R
        }% _; B0 E3 v9 N( |# B) F" ?4 v5 b" l
        // MMC5' |" i4 {% |; ~; U9 v4 C5 K# v
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
* a  y' Y: g$ [" ?                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 h  F) [* o( V) f        }
$ p) Q  Z- O. g' G9 J+ W4 o        // N106+ M$ u7 z5 Z6 l. \# q( Y8 }" L2 L. a
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {2 V7 `! ?/ ]1 \
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;( ^/ d9 J* {- U, x8 e3 W
        }! K- F0 r4 _. B, @& D
        // FME7
. C1 O; r/ U/ ~. f        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {7 H. z5 l& {# w& L5 Y* N% F0 [
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
* S2 F# s. y2 N. D6 \# U: n        }' c3 U, Z+ r; u0 O3 E& u8 ~9 R
        // VRC7
. g# ]6 H! b* x. s5 u. v! Q        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {* g/ W1 P  b. l  Y" W4 K" I6 |
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: [8 j: T6 P6 W# Z1 k) r& M% H        }
$ l6 z3 W  s. r3 v/ t2 f9 b" P        return        0;4 O* V& f# ?. o; T& |
}5 J" D( `! z0 p, A# @) t7 u' p( @+ q

) d" I% `) t( w// State Save/Load4 |6 k4 }) Z+ P
void        APU::SaveState( LPBYTE p )# C* m& N7 U& f) y/ C% j
{
3 k1 o7 C! N1 v" d% B: ^2 t#ifdef        _DEBUG2 @7 T7 K: D4 A
LPBYTE        pold = p;9 J3 D9 X. ^0 w' ?. }! f4 I: J
#endif! R8 f( |* G+ n, L$ s* U& v
$ {1 L+ H- ~' \/ h6 u9 Z6 j
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞) e* Q% H. o% N3 A6 C7 j6 F7 }- i
        QueueFlush();
0 N4 c; E1 C. [' r3 @0 z' q8 N0 {. J+ a  ]- b) g2 B  `
        internal.SaveState( p );
: c# R7 f1 b* a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: Y( u% D( y. c% `% P

! `! S" t. P/ }4 l3 ~        // VRC63 O# z4 W; |3 i9 W/ K! F" ?3 R( y7 r
        if( exsound_select & 0x01 ) {
" K* P% Q" t3 w7 R- Y! k                vrc6.SaveState( p );
1 j3 b" |1 e" p                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: s- B: G) L6 }9 }  Y  r
        }. H" m. z; {1 l) f, z# Z1 U
        // VRC7 (not support)$ c# v& B# J, k4 T# t5 M7 r
        if( exsound_select & 0x02 ) {  b$ Z5 {* r) ^
                vrc7.SaveState( p );$ ?1 n' S6 y8 E! s! U* u0 a. s
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, Y# A4 A6 y- H+ `        }0 a: o2 H9 [: a6 A
        // FDS
3 r2 P3 i+ n! }# W. N9 b* h        if( exsound_select & 0x04 ) {0 i( o( ^$ o$ \0 A$ r+ Q
                fds.SaveState( p );
+ t  K) p. f" C1 m4 N) h% A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ y' b) b# F0 j/ |* V3 e; h8 Y
        }( T' O7 t& I' V8 \5 t, a% I
        // MMC56 J% G9 d& V! T$ b  I
        if( exsound_select & 0x08 ) {
- X* T) Z! b, s  j, \                mmc5.SaveState( p );) i8 c* V# e8 {2 c9 o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  |6 P- j* @- ^1 Y0 l2 c$ j! r
        }
/ a2 X( |4 n& K7 q# V3 ~        // N106
0 g/ g5 F% D, P# `. ?        if( exsound_select & 0x10 ) {
( T* ~2 Q- g( z7 v                n106.SaveState( p );
+ M1 O( ?% z$ G1 z) J                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 r. I' N+ ?6 Y) l$ f  m( b* ~0 w        }
" V% N1 m$ S; Y9 f5 r5 s7 B        // FME7
) ^4 v; S/ y/ l7 \) J) L        if( exsound_select & 0x20 ) {
% c0 }, k* f+ A( {$ Z5 b                fme7.SaveState( p );; C4 C$ O! M. z. h: Q8 ?, E% X
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ g6 }  t* p! N        }/ i" x$ L' V; }0 W! u

- u  f% C- w3 z% j#ifdef        _DEBUG6 N: y; M$ p6 x* V
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );; V0 i) v9 V. a
#endif
: [; n5 ~/ h. F/ m7 a}, x! _2 C" l6 Z: d1 N
. C( U+ X8 w2 I* h. B
void        APU::LoadState( LPBYTE p )
: k% ]+ F. F5 R- N{
) Z4 G3 n) _' O        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 X! ^- x& S5 Y
        QueueClear();
* t) H  y- C4 ^. R) f. m
$ V) S; A/ n# j% j& }/ m) U, U        internal.LoadState( p );
) W* F- L1 m* v3 Q& q/ j& ?        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 ~% E0 {& w8 h0 v. Y! a% }( o* h

- p4 H6 Z' v0 m& c        // VRC6; @. b' r8 E! j$ Y
        if( exsound_select & 0x01 ) {
6 H+ r  M4 i3 P% t                vrc6.LoadState( p );5 e. Q8 J3 f( I+ U6 o  C
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. Z! @7 ^) C1 Q+ ~% C, `+ ~  ?
        }' b3 U+ ], G! ~' r  R
        // VRC7 (not support); R) t4 ~, W: O/ s5 d5 S( s  c
        if( exsound_select & 0x02 ) {
( G4 @+ f/ o. ?. F2 S1 T                vrc7.LoadState( p );
) K1 f4 J( y3 Z# x+ _2 f9 [, `: @+ y3 n                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding& i( @$ S4 `" O
        }& O7 }$ x4 [# d" ]# d' V
        // FDS
! l  ?! {6 |  t2 b7 M        if( exsound_select & 0x04 ) {
4 B) d- a1 u) ~  g                fds.LoadState( p );; z7 c# k* Q/ f8 w; ^' s( }) F
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ }5 @, W$ b" U7 s. f
        }4 [- x. m( c  h. T3 A1 G
        // MMC5- A, C8 [: K3 z( L
        if( exsound_select & 0x08 ) {, d  K" l! Q* A7 b
                mmc5.LoadState( p );
7 V; V" `: t$ J" a3 F0 r                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 ~5 K4 {+ E, w4 P: ~
        }$ d" N2 o, a* K2 P/ ]  m
        // N106( f- m. w" ~6 d
        if( exsound_select & 0x10 ) {
% I5 J0 y) J. H- d/ G                n106.LoadState( p );
' N" f& }) P6 J  H                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 C5 F% m; c/ e9 [. l. o- b
        }5 q; |* f. m( i- \7 l9 a# n
        // FME7& F. L, l' `5 m5 B
        if( exsound_select & 0x20 ) {# s+ d* c7 `1 O: c- ~' Q/ f% `, C
                fme7.LoadState( p );* @9 T: E0 [7 a& h  o
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ B9 g6 }7 L9 ^- k* Y        }
: y, L$ M+ ?- d2 N( h}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 " A2 e8 f) q9 a6 G" I
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。6 [, [5 L: E- z6 [; A4 B; Y  y
感激不尽~~
3 \9 U& t" i) E3 ~, ]0 g5 P
恩 我對模擬器不是很有研究,
1 e9 w: H8 s: d  y" P) p4 F( F5 ]雖然要了解源碼內容,可能不是很困難,
' g3 Y( `! T1 I7 [1 b不過還是要花時間,個人目前蠻忙碌的。4 s5 Q3 x' Y8 ]6 s( \- B2 i
  w) k, r! g& K. I- k+ O3 L
給你一個朋友的MSN,你可以跟他討論看看,, b" {$ l' u& v3 i6 H
他本身是程式設計師,也對FC模擬器很有興趣。
* H6 J6 _$ z3 d4 K0 q
  G0 P) [; u3 Y& BMSN我就PM到你的信箱了。) E5 s, D5 _# Z$ _7 \7 {. p$ I- G

/ d  [4 b, H7 m  ~/ r) P希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " F  a  {9 }1 C* U9 G+ I8 m
呵…… 谢过团长大人~~

  S7 {1 @4 E3 B# V' B9 g
! i7 M* z( [! t6 f5 M* m哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! P' l$ {# w. D; b
团长的朋友都是神,那团长就是神的boss。
* a9 n* r. m6 M. ~
哈 不敢當,我只是個平凡人,$ y: r8 l: j! C1 ^4 G
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
8 F: M4 y. i8 V2 z/ J, lZYH# N  d5 o7 C* M1 ~9 u" S( |
QQ:414734306
! m% ~8 R6 R1 Z2 U& NMail:zyh-01@126.com
1 x4 y6 }) B6 l# i3 o7 A* V' Z! A2 `# v# F6 ^6 ~
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
9 L4 K5 ^0 ~' M: ?  R& \* G1 l再次对团长大人和悠悠哥的无私帮助表示感谢~~
. F( W3 ~0 ?; Q1 Y9 F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-7 13:47 , Processed in 1.077149 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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