EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
# h+ |! l% S1 g8 o5 @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) E8 I- ^: ?) J4 E9 @这里有相应的模拟器源码,就当送给大侠了~~
/ I5 P+ Y% o8 u3 Mhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" N  }) G5 Z; }' _9 g/ \7 e2 |能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# M* N6 q4 ^* w( m# F
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  v: u& n' X1 E; `8 @: w( u5 d
这里有相应的模拟器源码,就当送给大侠 ...
( C3 ?# d& z/ Y
聲音部分(Audoi Process Unit = APU):
1 s2 u+ Q- c# D  k& U4 {.\NES\APU.cpp0 M0 E0 I' z) B8 G& W' O+ q4 @
.\NES\APU.h+ b% |' J. p; E  I2 c) H4 r4 ?* v/ H
- B$ y' H" s+ Z" r! U- Q! |/ I
; f  j# G  e4 P. \- c
影像處理部份(Picture Processing Unit = PPU):& _+ T, T* S. H& X; r6 m
.\NES\PPU.cpp
7 w: e$ H, E8 ?8 T4 e( B.\NES\PPU.h+ a0 k: d7 U3 [8 w% z/ S$ ]; m6 b

. M7 W: U/ o. }" x如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
' Y- u) f! v; E  M% I/ U7 W/ `(由于很多专用术语和算法机理都不明白,所以看不大懂……)2 u/ s/ ?/ P( v" `! {
//////////////////////////////////////////////////////////////////////////
+ ^( C& i7 e  W$ W3 H1 w) q" H//                                                                      //6 h* m) K" ^! D9 [% I
//      NES APU core                                                    //
5 |2 o: c( ~$ A7 R  g5 ^//                                                           Norix      //# d5 X2 }% R  Q- o
//                                               written     2002/06/27 //0 r# w5 g% k. Y9 q
//                                               last modify ----/--/-- //( Y1 S+ x* J9 \2 T. \! ?$ |
//////////////////////////////////////////////////////////////////////////
' {& g" @- n6 J: ~# r2 r+ L#include "DebugOut.h"
* x. _7 G* h2 S#include "App.h"
/ o" K7 G2 }# L0 S/ ]#include "Config.h"
, u: K+ i' g1 V' U+ t5 v9 g: _5 @" e+ L
#include "nes.h"
! w5 y7 L* j5 y! ~: x0 N#include "mmu.h"
7 C$ ^3 z( A" K5 |#include "cpu.h"5 ]( V3 Y) G' n/ J' X; W$ B* G* S
#include "ppu.h"9 [/ ?) }- D7 J* }
#include "rom.h"
: [, y$ k! \; Q#include "apu.h"4 o9 Q7 ?; j$ k; D
0 r! {+ @  S" d" ?$ l& X% p% G
// Volume adjust+ f1 w/ I! `8 c  c' ]9 G# Y3 }: C
// Internal sounds
- E# ]" _& y. M  C) D4 A+ j#define        RECTANGLE_VOL        (0x0F0)
, ?9 G- ]2 r3 s% J: }1 B* h#define        TRIANGLE_VOL        (0x130)
. E  u% x% w6 l" h: f# J#define        NOISE_VOL        (0x0C0)
0 H+ S' C8 E3 o2 W! a. z#define        DPCM_VOL        (0x0F0)
6 x0 J0 i' E7 M# u$ B" ]0 O7 E// Extra sounds
1 ^' ~9 W2 o* v" Z7 d2 ^4 ?- ~) ]$ E* V#define        VRC6_VOL        (0x0F0)
7 t& G* P, O: h8 L#define        VRC7_VOL        (0x130)
6 O, z+ Q" |$ y. J+ ^+ O#define        FDS_VOL                (0x0F0)5 Z! F- c- z2 Q9 j
#define        MMC5_VOL        (0x0F0)
1 S' p8 ]  [- L5 J3 `#define        N106_VOL        (0x088)
$ l, h7 O" u, |( Y#define        FME7_VOL        (0x130)+ k$ U* D) j3 d& b9 J( t

  l" c/ `  W+ NAPU::APU( NES* parent )
* }. I& M4 N7 C- O8 |$ a6 L{
1 l& F3 p4 m2 [) q0 o6 H        exsound_select = 0;
( |% Q9 n' \- {: p! v; A+ f; L/ ?+ t2 {
        nes = parent;1 h! o8 n$ |6 X& B! {% P
        internal.SetParent( parent );7 N9 l' @8 ~: Y2 ?1 H) B0 U- W0 O

" @6 a+ e- u7 D* n0 R# c        last_data = last_diff = 0;
4 J1 k$ ?5 c0 C, x$ `; m4 u  D) g4 {. u* C+ {$ x, ~
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );* G. _8 O3 W; e, S* Q
, c& b& N% g  X* D7 B
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# Z) g+ j" `6 k4 p* U        ZEROMEMORY( &queue, sizeof(queue) );
1 l. q8 L% G1 X( A0 t$ L; `        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 q1 r  D- E0 m
' v, p' ]" `" l9 [! x' a
        for( INT i = 0; i < 16; i++ ) {0 @6 L5 U. A) H3 ^: K$ N8 V
                m_bMute = TRUE;1 h) \; d: ^7 W+ Z
        }+ q9 o* R5 O$ P6 S
}
1 V/ V; D5 h& |9 s6 L/ ^8 S& ?8 }9 Y6 i$ y  @, W* ~
APU::~APU()$ u6 V) q: D$ {+ ?
{( W. d6 x$ u# d" R( `. E( ^  v7 N
}: Y7 u$ F# U( V# h3 B5 C
$ l: P2 W+ }) o* D
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 y5 M3 p% N1 L1 K: L
{1 [- q6 X! Y- Y! z
        queue.data[queue.wrptr].time = writetime;
1 ^4 Z5 ~7 B1 G. e- ^" N        queue.data[queue.wrptr].addr = addr;
( @% e* w! K# I8 O* U% T        queue.data[queue.wrptr].data = data;" ]1 I& r/ H4 v8 ~. V
        queue.wrptr++;
9 _1 L$ A4 @  a; G  J        queue.wrptr&=QUEUE_LENGTH-1;$ P+ S4 U, x6 d% J- ^; i- C2 b. Y
        if( queue.wrptr == queue.rdptr ) {
6 f$ u4 Y$ {, l. U                DEBUGOUT( "queue overflow.\n" );5 a0 a8 B( R3 L+ G7 X1 d
        }
& D+ M# Y( Z  G; {}# ^' S# r* r; m( @7 y( |
  R3 G7 X3 X. e  M! X: z
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
/ m: f& E1 {7 H- G. A* U{
. u, j3 D3 `- p) H+ W, v; A7 n        if( queue.wrptr == queue.rdptr ) {: l7 d3 G) j( h) ]5 I) i7 J/ D; H
                return        FALSE;
( x- k8 |+ k$ w: }        }0 u6 F' E2 d/ |1 e9 a7 g! `
        if( queue.data[queue.rdptr].time <= writetime ) {; e$ w, _3 W  Q9 E; k( D( \
                ret = queue.data[queue.rdptr];
6 N) p; f3 W! n                queue.rdptr++;' N; o1 ^" L" D6 r% j  m
                queue.rdptr&=QUEUE_LENGTH-1;
. f+ X" r! o$ x8 ?- W3 f                return        TRUE;. e9 T# S8 S* E
        }
/ z4 e9 d! `' O1 z# e9 S  R, E        return        FALSE;
$ Z0 y; b; d1 {}
7 C, k5 H, S6 S. q
7 ~' T& Q) g& a) vvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% \6 k  m% P& [3 s3 c' I0 s
{! C0 V3 N$ Q0 |6 d+ o5 Z* \
        exqueue.data[exqueue.wrptr].time = writetime;" h& i  t$ o1 g0 q# l+ J
        exqueue.data[exqueue.wrptr].addr = addr;' C3 b$ ~1 @/ h& F) @) J8 u4 ]. m: a
        exqueue.data[exqueue.wrptr].data = data;
+ w, v% I' d! \9 y3 j6 h        exqueue.wrptr++;# ]) ^) x# V$ k3 I$ p
        exqueue.wrptr&=QUEUE_LENGTH-1;
. a# X3 w6 m- ~# K  _+ k; R7 p        if( exqueue.wrptr == exqueue.rdptr ) {2 k' h- x2 M  ~' d
                DEBUGOUT( "exqueue overflow.\n" );
/ I& J1 i: G  t. {; G+ M- N        }8 b: t& O& j, V2 n& \* I3 W8 N
}
' f& E2 A. U& ^0 j# W2 U" [0 L. }$ ~5 {6 Y* w
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
$ s0 i# g- ?! \- T: X{. s& }. v: |8 n! O, J2 e
        if( exqueue.wrptr == exqueue.rdptr ) {! z; x0 X/ H4 E
                return        FALSE;
+ ?2 T1 x6 O: Y! t, z! y$ h        }2 v1 k# K, `/ t0 c
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {" @+ u/ j" s% f0 V
                ret = exqueue.data[exqueue.rdptr];/ V; b, M$ |' L9 g/ T2 y
                exqueue.rdptr++;
# o0 r. P" B3 ?                exqueue.rdptr&=QUEUE_LENGTH-1;
: c7 h$ b' n  s6 I6 m                return        TRUE;" a2 L! p; M2 f5 i, C8 _# T" h; E
        }
% C9 F  `; R+ Y0 p6 h        return        FALSE;
8 p- u9 n2 ]# s: L1 b- d}
' q6 p) Z$ B' p: x; p
. X4 p1 [+ v; \  c1 R5 Q8 xvoid        APU::QueueClear()
, \2 [- M$ P* H{9 g4 p7 E; J2 z5 d, U9 s# _
        ZEROMEMORY( &queue, sizeof(queue) );0 ?" M& D& E, F4 J$ V7 {; Y" j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ D$ `& s: M1 R. T- e
}, \. c$ X: _( m: E# J" P
5 w1 d9 E" r$ {8 W& @
void        APU::QueueFlush(); a" {8 _6 c! K# j2 H6 v8 q
{
1 a" q! {$ }& y4 A" f        while( queue.wrptr != queue.rdptr ) {
  l3 l( e7 y9 l5 D8 o7 a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
# R: x; ?! J: w7 H) n3 o                queue.rdptr++;
: _- i( }) @2 D% T# A                queue.rdptr&=QUEUE_LENGTH-1;
; u+ K7 T( J1 s- M5 u        }8 M2 e2 G# i; G, H/ i* M/ s  w

2 C9 e0 P, V; A  _1 D- d4 |( w        while( exqueue.wrptr != exqueue.rdptr ) {7 E. y8 C8 d' E4 }# a, F
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 \, O- G7 H# w- t                exqueue.rdptr++;8 l3 p) F7 e9 G
                exqueue.rdptr&=QUEUE_LENGTH-1;2 z5 V# n4 v8 k  f1 w+ {. r
        }
7 R& h% S7 }4 C) M* c}
( ]% K7 R1 |( k( Y# P( w, {$ \  @* R2 R6 I5 i  G8 z4 ?
void        APU::SoundSetup()6 `+ i* ~/ h* |2 N% T: b) I  y
{
* F+ |; A. ?7 g, a        FLOAT        fClock = nes->nescfg->CpuClock;
4 O1 u0 p7 N5 G5 ~2 Y        INT        nRate = (INT)Config.sound.nRate;4 j9 G( ^5 H; {$ ]+ x# k
        internal.Setup( fClock, nRate );0 t- y7 A9 J4 x) X! m3 {( H
        vrc6.Setup( fClock, nRate );
* g' L* X7 m) h( w# c        vrc7.Setup( fClock, nRate );- b! V, x$ E! T0 K
        mmc5.Setup( fClock, nRate );  L! J2 D: w7 l+ y
        fds.Setup ( fClock, nRate );
& C5 |! C! _! P% ]# z) P" F% l        n106.Setup( fClock, nRate );
3 x, c- L5 c4 m0 S; B        fme7.Setup( fClock, nRate );
0 j* l1 `1 f5 D* _5 F}6 x* Q5 L  C- I6 c
5 S# g2 X, U5 Z8 A$ {: b
void        APU::Reset()
7 d4 n. x# ]# l2 T- e. @/ }7 e{
" c0 `1 ^; u9 n1 e        ZEROMEMORY( &queue, sizeof(queue) );' q7 e* c5 n5 \+ N
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! u7 N$ s" {* M9 s, n; [7 x( u% V1 [" g' J! y: e# h4 `8 `+ L9 H
        elapsed_time = 0;( A- J4 ?  f$ ]& Q( E2 k' ]! W2 @

. k+ D! Y$ R7 F0 G1 l        FLOAT        fClock = nes->nescfg->CpuClock;
% W5 g; \& T% b        INT        nRate = (INT)Config.sound.nRate;
( I: ^% G3 D+ k6 j( w        internal.Reset( fClock, nRate );+ V; C6 V% _& E' q3 b& K! C- m& k
        vrc6.Reset( fClock, nRate );% t- Z& S* Y0 M! K* z4 x- ~: V/ D
        vrc7.Reset( fClock, nRate );
5 H0 X# D; s1 t' H. K$ H        mmc5.Reset( fClock, nRate );
. W( k9 B6 A8 V( j) c. ?2 t& R6 I        fds.Reset ( fClock, nRate );* E! f( C6 T! I% ?
        n106.Reset( fClock, nRate );* V3 G  T( b, P1 J% O" L
        fme7.Reset( fClock, nRate );& n& N' q& ~7 b, m7 L2 z1 G
6 A5 W1 B- B8 `8 z& G. d* C. b
        SoundSetup();" b2 H  ^0 _- C1 [/ z  q( m
}
4 f% H- D" j& k
0 I3 I% C0 q! Ivoid        APU::SelectExSound( BYTE data )" i# b  ]* V- z2 p& p) `
{
8 O2 n) i3 [# M! D; _/ b        exsound_select = data;
6 f- q4 S. y/ x6 h% ~8 j6 C}
* B( [6 G' `! i+ c" U% |. w& s4 x' z, o
BYTE        APU::Read( WORD addr )
2 r1 G. k3 w+ }6 C3 D7 `  m{
' z+ J, a2 ^7 T2 n, H, O        return        internal.SyncRead( addr );
# }9 z- I1 |/ j& k* T}5 O* i0 Y) V3 d& N" e7 k/ s5 L

4 }  V$ O% V6 W; C; `: lvoid        APU::Write( WORD addr, BYTE data )
. j# p( k2 P, A3 f5 Q{
4 T6 p9 B  B! R& [        // $4018偼VirtuaNES屌桳億乕僩
* }( f$ X) Y+ w1 a6 O4 e' W6 |        if( addr >= 0x4000 && addr <= 0x401F ) {7 J- M# S3 w9 a! `" b
                internal.SyncWrite( addr, data );
6 G1 i5 p2 {' V6 s                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' X$ J5 [9 h2 C: {* x9 Y        }1 b7 p  Z# a" Z  D
}
. i  Z/ e6 g% x7 X* u, _. X
( E7 V% J  a, k4 n8 o. yBYTE        APU::ExRead( WORD addr )
, H* {+ b5 ?+ z9 p5 R{
* J3 J5 ?2 L! ~2 c9 Z% Y, LBYTE        data = 0;
# M- h* ~8 \4 G: l8 R
+ N- R/ t6 A; x8 }) z8 Q) _* C4 Z        if( exsound_select & 0x10 ) {
# c* e/ |' w) ]; m% p                if( addr == 0x4800 ) {
: M" _0 F: B- ?" V4 _. ^( c, ?                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
4 T2 `3 Y# K, F5 @* \, ^                }
- X# Q- S3 Y' `9 p( c' ~7 g        }" s8 ~! Y, z% b: f# D" ^9 Z6 I$ I
        if( exsound_select & 0x04 ) {' l- @- A6 _8 s) c7 ?
                if( addr >= 0x4040 && addr < 0x4100 ) {! }' H5 f: P. t1 |# N
                        data = fds.SyncRead( addr );
. f; M5 i% @$ ^9 i' x$ @6 {                }
2 ~8 E, Z0 }" f# R        }; B9 a( T# }7 T
        if( exsound_select & 0x08 ) {4 T; r5 V8 F, t& N% d
                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ ^, y3 V/ ^/ X) g  S                        data = mmc5.SyncRead( addr );
" K5 z2 }$ ]( E. S) N0 m                }
- l+ ?3 @4 B! a) {% P        }
; f$ z. h$ L7 d( _6 [5 C1 e9 t5 e8 G0 K3 X: x1 l
        return        data;7 T, ~8 j0 y7 }
}
, _5 G5 h+ m. V4 ~
6 i' e: y* P( r9 o0 x  Nvoid        APU::ExWrite( WORD addr, BYTE data )& \1 P9 c( @$ v, H1 h% ?9 n
{
# N7 g, z4 t. v4 r+ e% d3 A        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
" e6 G1 M3 V6 d' l
4 V5 y0 U/ e5 ~        if( exsound_select & 0x04 ) {' f& n( V7 t. A3 b; ~( e; W
                if( addr >= 0x4040 && addr < 0x4100 ) {
8 O' r6 @( i2 \$ K; Z( y2 U/ J* N- f                        fds.SyncWrite( addr, data );5 m6 p5 M- f2 h" s& `" B
                }2 f4 A# O) U  O3 r. A& ]/ e
        }8 z7 Z2 L% q2 E6 G4 w& X
) \0 [0 p2 U3 q1 Q# i
        if( exsound_select & 0x08 ) {
6 W  W$ k8 F$ j( M. a& U4 H                if( addr >= 0x5000 && addr <= 0x5015 ) {
/ F+ D/ q' \3 f* s. L7 a                        mmc5.SyncWrite( addr, data );
+ V9 u: L! |9 G1 J; F9 w( v                }
" a) [4 @1 M6 P+ e: J$ S3 l        }" S5 n) z0 ^4 {
}  c# E& I0 h  N. h' x7 J

4 R) A: P# }. s5 Y* E* }- Vvoid        APU::Sync()' {* ~& k) O- q1 G
{
) }8 [/ q& `4 ~, Q" H5 [}
$ i" [, `( G% h1 y. O2 F" B
4 u; F& y1 d7 R, q7 u/ Avoid        APU::SyncDPCM( INT cycles )
$ s! o/ x# T6 ^# o9 j+ c{
9 D( J/ w$ U+ a$ {7 J7 C        internal.Sync( cycles );
2 K' t0 e* }) x0 Y- @! ~$ A6 @7 m3 g
        if( exsound_select & 0x04 ) {
- J1 v- A4 h9 }' k) \. @3 P% r                fds.Sync( cycles );
$ Z( W/ w% w# T6 \        }, m; m* P; H/ F9 U  K5 F' P
        if( exsound_select & 0x08 ) {5 ~* {! \/ p0 ~6 I& B
                mmc5.Sync( cycles );
. v2 J9 C( J7 T; T* B* o% q6 @        }' u" I1 E# t, r* P
}
; B/ Z9 ^' k" \6 r6 R3 L$ }
$ x! c, c* t6 S. g4 l; Mvoid        APU::WriteProcess( WORD addr, BYTE data )0 Z0 G9 c  e+ ~% L7 M- B' W9 K
{
# M- u3 S/ C. d* r. U( C        // $4018偼VirtuaNES屌桳億乕僩" }0 |: Q" x2 W7 ^+ [$ Z
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 e- l6 E% g  @+ h                internal.Write( addr, data );
) s! y' a2 l. \! _3 _# `        }
9 n8 k/ p" ]; t+ p}
: ?' }$ `' ]( j, r/ t% j* ?0 m' \
( h4 j- n- ]: }9 z$ Lvoid        APU::WriteExProcess( WORD addr, BYTE data )
2 q! B: f( G% ^! X2 \1 O! I( M7 A. _{; i+ {  H3 R; a2 O0 A- x
        if( exsound_select & 0x01 ) {
; Q* y% y$ X% J6 }+ g                vrc6.Write( addr, data );3 t( ?) ?' ]; k( J* k. r/ g- T
        }4 n, b( E! f6 G, P& _
        if( exsound_select & 0x02 ) {- ~/ u% A! O: X4 o% H
                vrc7.Write( addr, data );8 ]1 K% J2 v# k( P) `, N7 g8 e" T/ `* y
        }
- N0 B* V  i; w2 u8 B8 j        if( exsound_select & 0x04 ) {
; f4 X. {6 n$ A& E; I. n                fds.Write( addr, data );& J% N  i9 d  H' D7 j
        }
2 x" x7 |, K& x3 P/ {- N        if( exsound_select & 0x08 ) {6 M: ]1 |# ^) |& q% I
                mmc5.Write( addr, data );  B4 O) f# |/ R# L
        }  f- a  ~+ H; {* z5 @9 M
        if( exsound_select & 0x10 ) {
) b' u. }0 F0 K0 ~, H                if( addr == 0x0000 ) {
$ t0 c5 V3 z! T& n: y. {! `                        BYTE        dummy = n106.Read( addr );: U2 s4 A/ {( j7 X
                } else {3 G  w8 V# y) E2 \+ E
                        n106.Write( addr, data );% r# d7 s3 y+ q
                }
2 P$ {. e7 Q. K' H  y/ O        }
9 w$ K$ n. d" {9 D: v  ?1 W        if( exsound_select & 0x20 ) {
! s6 `. w, C6 J1 ~- n1 T+ B                fme7.Write( addr, data );% T- c9 W9 d( o/ N8 i
        }
2 ?* g* D! V9 ?0 Z6 v$ T. s}
$ n3 Q! h1 p7 |, _  a
2 ]/ ~, Y2 c9 Y, [6 Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )5 i& A. |8 ~5 B$ ~) T( c! g3 f2 M
{) k% i, q+ E' G- j. p  c4 @
INT        nBits = Config.sound.nBits;
8 O* w8 z" _5 Y# _DWORD        dwLength = dwSize / (nBits/8);/ G, b% y* a* M
INT        output;7 \, w) S0 B$ b" `7 P% M' @
QUEUEDATA q;  m: O% w+ Z, k
DWORD        writetime;
4 c. F0 R, W) r) p) d1 Q
5 F+ y# A( ?7 c5 v* H! P, R  oLPSHORT        pSoundBuf = m_SoundBuffer;
( p0 p* i, ]2 J8 aINT        nCcount = 0;
. ?/ E2 _$ m) C9 [7 O1 n
0 @7 E) `4 v3 e( t, h* U. j* wINT        nFilterType = Config.sound.nFilterType;
; I& |: S+ R' t6 ?+ `6 ]& _' s8 F
- C" h4 s- Q6 b% p' A+ y        if( !Config.sound.bEnable ) {9 M: L/ l0 l$ h5 H4 a( n
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 l/ R) B' Y0 k" p$ r7 r                return;. _* C& J2 e2 v2 g
        }
9 t( y  X" P; q
2 v: q( a6 Y4 N4 s: }8 r7 K        // Volume setup
  G% L, s: {; ^        //  0:Master$ j" e  o3 n! Q6 V
        //  1:Rectangle 1
: h( t3 O- t; a  {; |4 @) R        //  2:Rectangle 2) P8 \! \1 O( v
        //  3:Triangle
& @; h- w' R+ _: v  ]' g5 m, l        //  4:Noise4 @' n5 b& A4 O$ H1 H
        //  5:DPCM# i# S: R  H9 q; b* J# V
        //  6:VRC6
+ C: p0 q. u6 }/ H        //  7:VRC7
5 C. K8 R  h; w. b; B        //  8:FDS; F* y$ V% |; K7 k
        //  9:MMC5
) y1 [  E* S1 H; W        // 10:N106& }( u% m6 [0 d/ T3 o) R4 h+ c* b
        // 11:FME7* n+ J( e9 L7 x/ M1 ]3 u$ s4 r
        INT        vol[24];
+ j& d) B0 ]9 V5 z( x        BOOL*        bMute = m_bMute;
  h2 A4 ]! J- [& `/ y        SHORT*        nVolume = Config.sound.nVolume;8 C8 l; P  B$ F) p( E
% k( j6 Z8 q9 x( C) Z& \
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; S4 x7 _  w4 E3 H4 L# v
; B1 @6 P6 @0 |) q! e+ \8 ~
        // Internal
# Y, e* `3 {, p+ }- n5 v* w4 g        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( @' o7 n& C0 s9 O9 m0 _        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;4 i# S: l" L$ @% }, E( ^
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 G( u% U( ~. X7 h        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;& h9 x6 F2 V8 \9 b  B
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;6 j% Z  [3 |$ c# H: l5 [8 f

- E; Y7 Q# @3 y8 F& J% k5 j        // VRC6
$ Z' `: ]4 m2 E  a) S        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 l/ P% R4 A! f, t" E! C* [& o1 o
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, E0 e4 n0 B9 j7 Q' a6 c
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 D% \! Q7 S. R9 X7 h: S9 C0 b, [
5 d! ?: i7 f6 c! l' L) _
        // VRC7
, P* K; f& H3 I% d5 B+ Q( d        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
4 }' v, R0 z2 O3 a' A6 O, p! E! p4 Q* {
        // FDS$ J  {- h2 }4 [$ U% A
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;: W1 b6 n6 b: i, r0 q; B! I9 [4 [

- J1 g7 e1 S" O$ B) g        // MMC58 y# v1 P8 Y" ]4 A* w$ {
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 a8 C, V; u4 c/ W) i7 m7 V9 R        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
0 T9 j" A6 g# u  Y+ A. `6 o0 s        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. U7 @( q8 M$ W9 d# k! _" R

3 j' [# ?% w$ B$ M: K        // N106
/ X6 R8 u8 I) ~9 ~" n        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 n+ m/ G% i# S7 U0 e9 _! j        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# F/ w0 T2 t7 `2 \, u" M9 m" F1 s        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 ?0 G, D" U5 H6 O+ u4 X        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) v' [3 d- j) ~$ J- Q( ]+ X; z4 o        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, r( y+ C7 @5 \# e5 [$ s3 M, S; m8 a' ?& W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) y. x4 V- h5 \) q+ F" ?, o
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# t  b  @' S/ p* x7 |        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* N3 j* U' R& n
5 B; }: }/ c6 E& V: `7 G* e5 f        // FME7! ~& ]: i2 u, \( ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! F7 }5 H2 n% N
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 W# w9 h* {& ~) P        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! m: h+ _, U( Z
  y- t; j# |# l! c# @1 H//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;7 W* d4 q' f2 p. T  \/ w
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
* L! l; T! H" c$ Q! P& J% x9 ]6 b2 d. q
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
; S4 B9 G  S) M; `% R        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# v* \, B- T( V5 \: a
                QueueFlush();" f$ M# l, _, G% d6 h
        }
2 E2 e' }$ ^  Q1 z
' X6 E$ a9 y/ s0 k        while( dwLength-- ) {
8 Y/ m" G/ t! a6 \; ~8 n( z                writetime = (DWORD)elapsed_time;9 q  w% O( v$ U4 y, b# v) f# `! C' J
8 m  e0 e' e4 M, m/ W/ q1 S
                while( GetQueue( writetime, q ) ) {
: C, C: {3 {) \* |                        WriteProcess( q.addr, q.data );
7 |, b8 f0 w4 X9 D9 z. ^8 x3 E/ h                }
- c- W" F+ k& F7 B2 I# o- C  \3 Q! d1 k( y" X+ ^1 W. `  V
                while( GetExQueue( writetime, q ) ) {! [1 x$ b; m/ I7 w
                        WriteExProcess( q.addr, q.data );9 ^2 y! l3 d1 |
                }
3 u7 v& l& n8 b# N% d
3 j' Y; b( y* `+ y4 |5 J  W                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" O2 o0 g' U$ Q" X* W- G* w
                output = 0;+ i8 X! l1 S' c& t3 q9 r
                output += internal.Process( 0 )*vol[0];
- `: A8 y6 n$ k' f; f) s1 }; L                output += internal.Process( 1 )*vol[1];- P1 y: t6 p+ C  ^+ U2 W, e
                output += internal.Process( 2 )*vol[2];
% t- U5 H( C. t% D- N+ M$ N                output += internal.Process( 3 )*vol[3];
* `8 q) E& v# N* @                output += internal.Process( 4 )*vol[4];2 f' i1 m! O0 c
8 S# G2 z2 r5 U; i( p/ i3 f
                if( exsound_select & 0x01 ) {
$ @* i4 T  F5 b  `                        output += vrc6.Process( 0 )*vol[5];
7 A9 ^$ j3 w* u4 ^! {. B                        output += vrc6.Process( 1 )*vol[6];
0 I1 b0 m* L3 U$ U% }8 l2 C1 D                        output += vrc6.Process( 2 )*vol[7];6 g1 F( z+ _& U( u
                }
2 d8 }  ~; \- ?  L/ X+ e                if( exsound_select & 0x02 ) {
! K( A8 u) `( o- t! [  a                        output += vrc7.Process( 0 )*vol[8];8 K  J) p0 R& j
                }
2 v' x+ F- ~  W4 f                if( exsound_select & 0x04 ) {
3 t+ \8 J% \/ L! `5 Q                        output += fds.Process( 0 )*vol[9];
* j. i2 p' ]. s  [" M                }
" U& t8 j* \. f- n7 u4 ^1 O9 ]' @                if( exsound_select & 0x08 ) {& n3 q! t7 d  @+ F$ {
                        output += mmc5.Process( 0 )*vol[10];* J" |) u7 G  K# ~
                        output += mmc5.Process( 1 )*vol[11];+ w/ _; ]$ p# A
                        output += mmc5.Process( 2 )*vol[12];2 x5 q% i, K! G8 N
                }
7 ], W% \. R3 ~& w                if( exsound_select & 0x10 ) {& {; F4 f/ G3 V6 R
                        output += n106.Process( 0 )*vol[13];$ l( L1 M& s6 G/ M6 v( m& B
                        output += n106.Process( 1 )*vol[14];
) e5 }! ^, z+ @% o6 L& |$ G/ s  p5 F                        output += n106.Process( 2 )*vol[15];! m1 T! W# R, w
                        output += n106.Process( 3 )*vol[16];
, F  a0 E1 v6 g5 H) t* v+ e5 [, ]  m& q                        output += n106.Process( 4 )*vol[17];
- _7 t$ G+ \" L% p5 `                        output += n106.Process( 5 )*vol[18];; P5 A, @8 }2 |
                        output += n106.Process( 6 )*vol[19];
3 K% l# F: w9 X# O2 y                        output += n106.Process( 7 )*vol[20];
  Y4 f1 k2 l, U3 p                }
& M' F( |2 y% G7 w0 p& }                if( exsound_select & 0x20 ) {
: A4 O; i; @& q( _                        fme7.Process( 3 );        // Envelope & Noise# K; \( a5 ]$ e  e! q
                        output += fme7.Process( 0 )*vol[21];
1 h2 u  [2 q  K                        output += fme7.Process( 1 )*vol[22];6 j$ l  k9 t' {  n, u. I0 l7 }
                        output += fme7.Process( 2 )*vol[23];3 L. @6 R) l$ _# F+ x& L% K3 _
                }# }+ g2 G0 d4 l
; ~0 r  n" L2 p4 ?: `# \) N& m1 B
                output >>= 8;
' v. l! X5 N2 T" c# L5 y
1 \; q9 `" O/ g0 B7 `$ `                if( nFilterType == 1 ) {8 \% E, f- V" `# r2 \+ G# I
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 O9 F! R7 z7 t
                        output = (lowpass_filter[0]+output)/2;6 ]6 u8 n) k" u0 x: k+ Y
                        lowpass_filter[0] = output;% ?1 U& k, a* ?$ ~, P
                } else if( nFilterType == 2 ) {4 @( s3 ~' \9 |9 K; g
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
0 Q3 x. c5 b% }, `/ d) X                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;! {9 |' h' w" Y9 \9 Q. Y9 l* S
                        lowpass_filter[1] = lowpass_filter[0];# T1 t4 D; _( n; @' @
                        lowpass_filter[0] = output;4 [0 ?/ e' N6 ^4 n
                } else if( nFilterType == 3 ) {
3 x- M5 W, h$ @" {  R, E0 L8 m9 r                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 @7 P5 T/ p# E3 [9 l! W
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
3 B! l' H1 A6 l( A2 l% S                        lowpass_filter[2] = lowpass_filter[1];, k9 O0 V$ ?3 j
                        lowpass_filter[1] = lowpass_filter[0];
$ V& i$ S5 k' Q( n: V( H4 q                        lowpass_filter[0] = output;
+ p3 c) F) Z9 q: N  {5 Q1 r1 K4 U: {                } else if( nFilterType == 4 ) {
6 s. x1 w  j) l* e                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
9 M! P* {! I4 d4 A+ {8 T1 E, c                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 K) Y% z4 ]( b% P( [                        lowpass_filter[1] = lowpass_filter[0];
7 N2 s: d6 e: h3 _7 y                        lowpass_filter[0] = output;
$ o; F: p- m0 |, t! t% r9 [                }9 u6 K8 W* z# z( U
9 X! Y# z6 ^- R9 M0 ]6 b
#if        07 J1 X: _5 h9 c( {  N4 z, h( `. L
                // DC惉暘偺僇僢僩4 R  h  m& X( I+ b1 R
                {# I. w, O! t* O3 w# K
                static double ave = 0.0, max=0.0, min=0.0;
. f7 i1 k# J5 i  q! T; R5 @  {                double delta;
( W% F* X6 `4 T6 R" c+ p                delta = (max-min)/32768.0;
5 U# A) \! p# o                max -= delta;
+ L" `) m* }# V+ T6 N- d2 S                min += delta;9 P$ J0 @# X& x2 K& q9 H- q5 I. w  P
                if( output > max ) max = output;
, {" p) h, }. n" I/ c' F                if( output < min ) min = output;
% c8 x3 ]/ Z, f' g0 [6 |                ave -= ave/1024.0;% M% p' z& R" B' c
                ave += (max+min)/2048.0;: o4 o; V4 d7 X2 o7 Z1 P8 F
                output -= (INT)ave;' V) {! ^  \- v
                }
3 c- t1 u+ z% A7 X! C1 W, m' `' W5 d#endif
0 r$ n* y0 D$ z#if        1
8 J. L, B( S, s+ R5 y' ^                // DC惉暘偺僇僢僩(HPF TEST)
6 m' M7 j. C# K+ C                {
$ X& }  E8 V6 k& B1 Q% G9 w5 a//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
( ]$ D4 P$ f6 Q! ~1 l                static        double        cutofftemp = (2.0*3.141592653579*40.0);
" i1 o1 k  @: Z( x; Q7 J7 k, N                double        cutoff = cutofftemp/(double)Config.sound.nRate;, ?4 o* w% E. N& _" ~% c& g
                static        double        tmp = 0.0;; ~! G9 h: T& \9 \9 O2 N7 i7 H5 y+ Z
                double        in, out;
7 S( z* A- ^3 Y3 ]! [5 w2 d. x, z* }7 U5 d' Y0 z
                in = (double)output;0 z( K8 K' o6 w: O$ r: T1 c" f! i3 Q; U
                out = (in - tmp);
- m& z" z' @/ o, J9 y, P                tmp = tmp + cutoff * out;
( ~0 C) W5 n4 ]' D
2 g# Z* o% ~, B. j                output = (INT)out;
7 b! C+ b( s) s+ x# s                }
* t2 \6 V" h% R( |0 U$ s' }#endif
0 \" }8 d* k: I7 t1 y/ Q#if        0
: X$ Y2 a* B8 `% T2 G                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)+ l# R8 U8 y+ f+ E& _( w! {+ w
                {0 I) g* X$ g) I- Z- ^7 l. H
                INT        diff = abs(output-last_data);
. c& [( q; J9 U0 Q. f                if( diff > 0x4000 ) {2 L' ?+ i; c) W
                        output /= 4;
3 O" G- z) r0 ^9 y/ t  T! y                } else
3 V. z; j' z( E: I: a# n9 ]# T8 Q& h                if( diff > 0x3000 ) {
1 L# c  _: {( @9 h8 i% ^4 J                        output /= 3;* O8 H7 s0 k: Z4 J+ a
                } else8 `7 }' s+ ^& I2 _6 a5 n
                if( diff > 0x2000 ) {3 }' b/ e1 ?& X' q, h) G& l
                        output /= 2;( p$ O; |3 d' v/ B
                }
& e( A: O& O5 h, ~, F                last_data = output;
" s* m2 v: F1 v" i3 U7 a                }
- f+ J9 I9 J2 ]- k#endif8 i7 K* c) f/ F9 Y& p) @
                // Limit6 q1 J3 f+ d0 X' M8 I! r+ W
                if( output > 0x7FFF ) {
4 m% P# l( W2 f* s+ m+ l                        output = 0x7FFF;
3 {: z1 C9 M' N/ J) y! K* f2 D                } else if( output < -0x8000 ) {
( Q) I) P* b2 q6 U0 X$ P0 c$ p                        output = -0x8000;
7 l3 X6 ^+ m' Q$ K+ G$ N1 B2 r                }
+ j; o5 f* o3 w+ Q' d4 w
! H0 g( |; u# H1 m& a7 k                if( nBits != 8 ) {0 {/ y- q- T$ r+ |. Q8 u
                        *(SHORT*)lpBuffer = (SHORT)output;& o" J& `) y/ k4 ]/ P# Y! P
                        lpBuffer += sizeof(SHORT);
' Z6 ]) ]. P) G  i7 V                } else {! E% o# ?' X/ Y5 d: J/ @4 D
                        *lpBuffer++ = (output>>8)^0x80;; s* G4 z! [; `. ]) K
                }: x" k! H9 S1 H1 Y6 U3 {
! F& |: W, d! l; l7 O: c
                if( nCcount < 0x0100 ): `& ]2 E% W' W2 @* ^5 I
                        pSoundBuf[nCcount++] = (SHORT)output;8 S' a- [* z; K3 R

" \% i1 R2 C+ d//                elapsedtime += cycle_rate;
  V- e5 s2 v6 N6 h, r                elapsed_time += cycle_rate;
# J# R( Y7 _; ~. O/ N. i. X) T        }
0 t2 D. `% I' i, K2 N# i0 h- ~5 J* k, l/ w
#if        1
/ g4 y  _( \. n/ k# K2 H& R2 ~        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {7 _# s% Z  q4 p3 l! Q5 k) `
                elapsed_time = nes->cpu->GetTotalCycles();9 e) s5 [4 t% g5 ~' e7 ^
        }
: O$ Z7 h( O. O5 l! J/ N        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {1 S5 z& y2 i4 u; E1 a) |8 z
                elapsed_time = nes->cpu->GetTotalCycles();
0 Q5 t2 I' u& R6 w1 h' |! m        }7 X8 e6 A4 r5 C" ?4 L+ |2 ^
#else
* v* t' J2 g" f% H/ |+ L        elapsed_time = nes->cpu->GetTotalCycles();& k2 ?/ W& [4 y; O; m8 b; \! J" o
#endif$ n0 `7 h. j3 J; `# v8 h2 d. G
}3 T3 y/ ]0 j! G& ]- k

$ x6 n8 k" W: h8 W7 r# c// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)8 Y, U+ r0 g2 J/ y% Y9 P( i! s
INT        APU::GetChannelFrequency( INT no )
: w4 {; y* F5 z: l{
* t; b( \& H: g- }) @        if( !m_bMute[0] )% {; u" e6 s4 _
                return        0;' a( m- S  _6 f8 F3 \$ z

& B) u) }( ^0 @. l( L4 B) V. D        // Internal( s' S# g, M2 k6 e3 V0 j* b' ]
        if( no < 5 ) {9 a; A. L' J1 X5 i8 q' @
                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 M2 J" L! b( U/ ]- T
        }  Z: l1 _( v* x5 |
        // VRC6
; ?2 @' U% A! _1 L        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
) C  X: L% A0 d* G, x% x0 E; X9 Q                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
$ z, H. g5 G) M# Q6 A        }
/ s( }3 M. W! z6 p4 [8 w        // FDS
" m5 H% ^9 r5 r  B" [        if( (exsound_select & 0x04) && no == 0x300 ) {5 V* v7 ?4 L9 p- \3 r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;  e3 d! M& Q& R% q: W
        }
1 F1 Q0 c# Y- F2 B        // MMC5
7 f* J! b6 g+ i5 J        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: |9 ?/ K9 e# t8 u
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
: N" ^% I9 ?8 U, H+ k        }
. I, v/ a' Z* [* I        // N106
7 S/ J4 p9 W; |' ]" k6 @        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {$ l3 R" k$ S( q9 d( s# _
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;, u0 `) u2 A$ s7 Y1 r+ f
        }8 H) H; J6 B$ M
        // FME7
2 P5 X* \/ l( [3 g7 n) j& c& K        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
) k! [! x3 N7 p3 y+ x                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;8 R: Z% E' t) b3 b
        }2 p# Q  L# D# R2 z) c$ D* A
        // VRC7* _6 z6 p, ~" i- j7 g6 p0 [( |
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {4 u2 C( ~, C4 V9 r- N" C- C
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
1 I  X, q+ S3 w+ h        }1 R$ }/ M4 J6 l% x
        return        0;
: H9 Y# m( `7 F# B. {. A) g}$ \5 {" T' G  c8 v4 k- O
$ `0 z! w& ?( W5 [/ f7 Q2 ~
// State Save/Load
' g/ E$ r5 v/ Y* ?3 ?3 Nvoid        APU::SaveState( LPBYTE p )
, W, Z. v2 i- _% |8 d{+ Z( y* a2 o5 O; _
#ifdef        _DEBUG
# J0 Q8 ?/ R; G6 OLPBYTE        pold = p;( R8 @+ X5 C: c# ^# \' _9 _2 x, G
#endif
) \6 T2 j2 h  Q& G+ y  M& ~; R( E8 _* O5 B% ?; _" r) L# D
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞. M* T- l! \! D% a/ J) f$ U
        QueueFlush();1 _" s/ u' \# f

" z% z0 L% j/ W3 ]9 u        internal.SaveState( p );
2 L* i) C' \# x/ L6 J* i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 X4 a- U/ o3 T; ]) _9 `/ ^# [- T( N% V5 W
        // VRC6
: o# a1 s; O, D4 {& q8 G5 j        if( exsound_select & 0x01 ) {* C' E! Y2 X  Y* ^% \5 ?( y7 f
                vrc6.SaveState( p );
* @. t% \' g9 r: S5 F                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. h; I; |& p' ]4 i: a- y. L+ L
        }% u" e8 d; n) k1 n0 ?% V
        // VRC7 (not support)
: _; ^3 @3 u+ Z7 w3 z; l        if( exsound_select & 0x02 ) {2 C9 n1 p  M7 @3 }6 O! j
                vrc7.SaveState( p );& t8 r3 f+ K9 P/ h
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) @% f9 x  A! Z+ Y% T* ^
        }1 j4 t7 O9 ]! e3 i
        // FDS  }, J( l3 e$ b, k+ c  S
        if( exsound_select & 0x04 ) {
  a2 Q3 u4 z% F( y7 e! R                fds.SaveState( p );1 x" N5 Y8 `4 G% X0 b2 w
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) f5 A$ s# p( t& r        }
8 C8 p6 j8 b& x. E        // MMC5
- y# r, |6 c( u# d9 d        if( exsound_select & 0x08 ) {# R. E" m9 n+ P; x2 \% v
                mmc5.SaveState( p );
! c1 J" X+ M0 C                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 u: D: v2 r/ h; O        }
/ |3 b( r* }7 O' r2 B) `/ u        // N106
$ C6 z- f' }. l$ i/ W7 U        if( exsound_select & 0x10 ) {/ y3 |( r! X/ }: m9 {
                n106.SaveState( p );% i+ O( [+ x/ I) d# r
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
# R3 h5 a# T+ |        }$ P1 D1 b2 t7 s5 E# {
        // FME7. T! S+ L- {$ z
        if( exsound_select & 0x20 ) {
2 B% x: J1 N1 M0 {* t/ v                fme7.SaveState( p );
& t0 k8 r5 d3 B- p+ `" A" R% \, {                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' {& a0 h. w! ]. K6 l& X& F, T$ l6 u        }- T: F# Z4 i8 J- U* m' R

( r$ X) C3 k9 P; X5 s#ifdef        _DEBUG& {  P2 y, K# A% R8 C) g% s
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 n/ K' f0 X0 X#endif2 F8 E# ^% C3 O& \) _# F: U, C
}
  v% Z8 A+ _: G8 Y2 |$ m1 |$ l5 w) b2 H: L
void        APU::LoadState( LPBYTE p )
0 b1 D! X: n) Q7 ]* f0 M1 [{
3 X: Z3 g- a  b% F! u  @5 z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
( E) m8 Q- y6 I6 |* D5 M        QueueClear();$ _8 ~6 T1 X2 I5 s

6 t5 X+ H+ t/ u+ u        internal.LoadState( p );
3 t) h$ O) e$ ~' |4 r        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding' j8 Y5 w9 @! a8 H) Q' N" ?- k

- ?" h! Q/ M  i' l/ p& s1 p        // VRC6
. i* e# f4 o- c; _        if( exsound_select & 0x01 ) {
& q! k9 E& c# L( a" S1 A                vrc6.LoadState( p );
4 X# {" j# A. `, {+ U# H! U0 }2 F( D                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 {6 ?8 @% N' z9 y/ I5 Q. P        }, ]$ `5 }$ q4 R2 @/ C& f
        // VRC7 (not support)
: ~. A& A* \/ f8 j* r2 z6 ]% w        if( exsound_select & 0x02 ) {  m) F+ ~4 Y! k
                vrc7.LoadState( p );
! E& U5 T4 C0 q# l' G# G) ^' N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  ~# G- A- u+ ?$ A
        }
' g' R2 a% f- u- K9 C" Z5 O9 ^9 w        // FDS
# \6 p; X! Y2 H4 o        if( exsound_select & 0x04 ) {
) @! _; V: g0 m. r% f) [; H! x                fds.LoadState( p );
3 L( ~/ }  b( E6 K9 s5 C% A                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding# U' i. Y# Q9 Q, P& U) M2 \
        }
  P' s  X: D! Z' f: t# |& e) ^        // MMC5
4 l4 A0 ?7 V; T1 ~& @& e; ]4 s        if( exsound_select & 0x08 ) {
- C5 a5 P. Y( E& Y7 z                mmc5.LoadState( p );3 L6 ?7 b. ^7 h" u4 ~0 Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ b, d$ g" n1 `4 A5 d5 L6 _        }
2 O2 v2 ]6 S! g$ @2 W        // N1065 U5 G" z- B8 b/ y
        if( exsound_select & 0x10 ) {
) L. k7 S% {. G! W. k2 U                n106.LoadState( p );
; b0 Q7 c* g# c* m$ Y8 J                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding8 x2 d( m3 W# b# G' C# K1 ^
        }
( Z3 u0 V. z* Y% e! {/ O        // FME7
  V2 j# O2 D# e" O        if( exsound_select & 0x20 ) {
+ M( T: e' O* x6 r. J                fme7.LoadState( p );# ?# U/ Q) @$ v' \; \
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- {/ h, ]- M4 B5 K8 ]        }
! h0 n" y  q  h" a& P}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
/ B: [4 X% f9 P可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 [: H2 u' n6 j' k% m感激不尽~~
5 m* }6 H# y3 R! K/ j4 ^
恩 我對模擬器不是很有研究,2 l8 A8 c2 Q8 [: L3 q6 m0 U+ S
雖然要了解源碼內容,可能不是很困難,, A- t8 H4 ?. }
不過還是要花時間,個人目前蠻忙碌的。
, y- k6 _, M( b$ y# ~( {. N: C2 T
給你一個朋友的MSN,你可以跟他討論看看,
* j/ a, K5 Y8 _+ M) V他本身是程式設計師,也對FC模擬器很有興趣。
9 N4 P9 O2 e6 I: k: [4 y
! t+ C, n5 I: O7 P% I- A0 fMSN我就PM到你的信箱了。
3 D/ z/ |% c9 {
- H; f" I2 P7 K8 J. K希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
; G$ r7 B" Q7 q' [呵…… 谢过团长大人~~

+ @# l, D' ^, g' a8 M; z8 M' c/ y6 _6 ~8 @6 D: R* r
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 c; N- [0 [% J/ H
团长的朋友都是神,那团长就是神的boss。
8 k/ p% u6 @8 J' o2 s6 C6 H2 @
哈 不敢當,我只是個平凡人,/ n2 u, V1 f" q/ r. M4 ~" D
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙5 b2 Y( K" T* C' k/ D
ZYH
7 O! B4 \1 q2 k; X$ {QQ:414734306
: S1 I  \; x/ s' e( X. w4 DMail:zyh-01@126.com9 x; Q" ]. b( P0 ?8 K5 ^5 v
" H; r# B5 g2 @2 s9 G
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 : {* |( [+ Z0 m" `: _3 l( d
再次对团长大人和悠悠哥的无私帮助表示感谢~~
. p+ H& n4 f' N) K+ q5 \+ C- H) q" p
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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