EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?. K1 F+ N6 N4 j4 Y' O4 X( R
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' D( ]  x" \0 F, O) l4 Z3 Q' w楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 j# g9 e9 T  p2 h7 h: z4 e
这里有相应的模拟器源码,就当送给大侠了~~+ @* \! T; Z) g! w% ]2 E4 F5 t
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
1 u7 {, b1 q5 w$ `! m  G: `5 R能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( s4 n& \6 E" Z楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) @7 C3 j( U- Q. D0 Q, r2 K
这里有相应的模拟器源码,就当送给大侠 ...

: d3 P2 X3 \4 f! [( F4 w聲音部分(Audoi Process Unit = APU):
6 z: R6 i: {# O% R; ^* E9 J.\NES\APU.cpp# o/ ]) l, w# w1 R  r
.\NES\APU.h( c" ^7 u) P' m& K6 {& l, ~- i1 B. U
9 Q0 L3 q+ d+ y  f  u$ s

9 l" k$ D  r. b* @影像處理部份(Picture Processing Unit = PPU):  t7 }2 u* d& M7 h
.\NES\PPU.cpp7 a' d1 ^1 d2 @" j2 k  N2 L
.\NES\PPU.h0 R" r/ b; i0 E5 N3 N& X
7 n7 g6 a) Z4 l! I
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:0 h( Y' t% Z/ U* U; d4 s
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
! K0 j: I. G# X//////////////////////////////////////////////////////////////////////////
+ \. d+ Y8 S5 d+ r: W! t. X//                                                                      //& c& r7 ?7 t8 n( c6 U
//      NES APU core                                                    //+ n5 T6 [% S1 y+ {
//                                                           Norix      //
8 M8 l8 Q6 l) q3 U: d& l8 H//                                               written     2002/06/27 //- `/ g# n0 Q2 @/ ?9 e% a9 A' h
//                                               last modify ----/--/-- //
9 o( I5 X) I9 {$ k, ~3 T) f9 Z//////////////////////////////////////////////////////////////////////////) X( W. ~0 F0 p9 i6 a4 ]5 ~( E
#include "DebugOut.h"
2 {9 k# `; x. @3 F, s7 h* Q#include "App.h"
; J9 f' s* P- f- b8 D#include "Config.h"
( X2 r4 Q. B; }* Q; e- @  k' ?5 r  G5 w: M
#include "nes.h"/ J2 p- t" o! e& |& _+ z) b
#include "mmu.h"
% D- f% b" z3 z+ C5 K$ _3 F. s#include "cpu.h"4 n- G) j) ~# C/ h! {9 D
#include "ppu.h"
1 }' H) ^6 x( w/ c' S; I* m, o#include "rom.h"8 r8 b; Y: F! ~3 e: }
#include "apu.h"8 [2 i4 O6 P; F, u" r  ]  L( G. H
$ `7 F" G( L6 b4 t, h# D
// Volume adjust8 c* u7 Q) u) w
// Internal sounds! \% S* a; P5 {) }: {; G. ^
#define        RECTANGLE_VOL        (0x0F0)
/ M% }) w& U. _( j7 }; `" h#define        TRIANGLE_VOL        (0x130)
; K* T) T  X- w9 P  [#define        NOISE_VOL        (0x0C0)
4 A; r- g& d- B6 j7 [' q' F  b+ c#define        DPCM_VOL        (0x0F0)1 m. E3 p4 F$ v' f; S
// Extra sounds% {% x* @6 f* H5 _( B
#define        VRC6_VOL        (0x0F0)
2 P* x# R) O( ~5 Q' o#define        VRC7_VOL        (0x130)
# X+ ~# ]) w# o7 ?#define        FDS_VOL                (0x0F0)
4 J) M( F: ^3 s% k/ e3 N#define        MMC5_VOL        (0x0F0)- z) m/ T7 ]0 `: g# a, E6 t- F9 R
#define        N106_VOL        (0x088)
" e) @8 @6 I- C0 ?/ y#define        FME7_VOL        (0x130). u; g0 v2 H, d. o* [: {/ s3 h

3 C5 V; p( C) s# VAPU::APU( NES* parent )- a% D3 \/ \/ h& M
{, w, u* {8 o% G; ?( E1 ~
        exsound_select = 0;! A* |* e% r4 K  O4 z  U
7 {: O# x; d$ T1 E
        nes = parent;# U! F0 a' M5 G5 B% M/ B7 w% ?
        internal.SetParent( parent );
) i) ?  Y! N6 R
+ }; k8 O4 [8 u2 Z% C$ Q        last_data = last_diff = 0;' B- s8 b/ V2 [6 c! I

8 F6 J  [6 o4 R, d        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
7 c: J, O# D, e
( v8 o8 \; N( m- I. K$ b        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );* t" j1 A$ W7 H! A; C# x  B
        ZEROMEMORY( &queue, sizeof(queue) );
2 f  K5 `; C" _2 I2 C" s3 {5 L7 @        ZEROMEMORY( &exqueue, sizeof(exqueue) );0 p- C# B" L- B8 I

) `* x* k" d( i2 i        for( INT i = 0; i < 16; i++ ) {+ E- P. {/ V9 E7 t% T
                m_bMute = TRUE;4 W2 m0 R( V  y" U
        }+ g' R6 y+ K4 k
}9 I& X# C/ o! T2 ?. ~

' B) n* C7 B- R& Y+ s" d) LAPU::~APU()
. {+ M/ z0 Q, \3 A{- f8 |+ \: e4 ]: D
}
; W' ~' E2 O  Q) H% I: f5 r% K' j; p; a# V% v, @! S$ y
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
9 _1 Q. k) g. n2 S( e/ g, Y{6 M1 h( z: G. D- F/ s: X. U1 V0 ]" I# N
        queue.data[queue.wrptr].time = writetime;
0 Y- b! v% y  ?( ]        queue.data[queue.wrptr].addr = addr;
5 U6 N, ]. ?( v) H) F/ y        queue.data[queue.wrptr].data = data;
* m& t1 T. [4 i+ b) B' a; z        queue.wrptr++;
6 }5 o1 F/ f' W4 M        queue.wrptr&=QUEUE_LENGTH-1;0 [% i$ s& E/ b) h' w, p
        if( queue.wrptr == queue.rdptr ) {
4 H: x. T4 @* l! h$ w, y                DEBUGOUT( "queue overflow.\n" );1 j7 t- w7 K; ]2 c* \2 S
        }1 x! }; n; n; L7 n* j
}1 D) x+ C8 o& X: L- [" A* w! l+ [
* s& g$ D. J! O/ S
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
% G; }" L% D+ H8 d+ ~- V0 K. Y{
$ J; o* P% k5 c3 X, O* c9 J3 m        if( queue.wrptr == queue.rdptr ) {  g1 H$ N" a$ [' C( T6 n
                return        FALSE;
' P6 c5 m. a: ?, y- F# E1 ^        }
  F6 W0 c" T, P8 m( m5 r        if( queue.data[queue.rdptr].time <= writetime ) {
) F* }6 `) E0 ^3 ?0 @/ N( j0 @                ret = queue.data[queue.rdptr];: C: `7 W; c, b: C+ f: @
                queue.rdptr++;
  g' h! d& g6 q- G! G" o% k                queue.rdptr&=QUEUE_LENGTH-1;9 J7 H4 C7 n; s* s* E1 u6 w. Q
                return        TRUE;& ~) j6 `& C7 }
        }: s; c. N7 U. N7 W4 R
        return        FALSE;
1 m+ V" v  h* q! R7 _4 A  q}
% V" ^/ Y1 R, ]" N
& k8 D7 x0 O/ |7 \& Lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
; L2 g4 o% l) M( q' |{
0 h9 _7 `- ~  b        exqueue.data[exqueue.wrptr].time = writetime;& [! E* T3 B: _. H
        exqueue.data[exqueue.wrptr].addr = addr;8 `( ~( l$ u& S, C$ f; v
        exqueue.data[exqueue.wrptr].data = data;) {7 f9 p6 ]/ c7 D# S9 B# Z
        exqueue.wrptr++;
, i) M" o) F( P" Y4 c0 t8 N7 J        exqueue.wrptr&=QUEUE_LENGTH-1;7 ]- K5 w- v/ G4 j, V/ C6 T
        if( exqueue.wrptr == exqueue.rdptr ) {
4 O+ K" I! ?! J# B) D                DEBUGOUT( "exqueue overflow.\n" );* p6 T& r, E5 ?' ~
        }# L1 i" i5 W! ?9 ?' U% w
}
, F% b) H* B4 W$ L% G
- I/ S7 t' a! `+ VBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )" {4 o4 q* V& W. j- D! G5 g" R4 i
{  }9 z2 {* r1 }  x0 {9 G9 O6 m
        if( exqueue.wrptr == exqueue.rdptr ) {
6 A1 I+ W3 r% c                return        FALSE;
" g! J8 v4 V( W2 S! p* k" \        }
7 ~1 ^5 o6 K+ Q; q, d0 o1 _0 d' J        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
. u. q5 C  k9 s0 B% s# G4 p6 G, Y                ret = exqueue.data[exqueue.rdptr];) j4 \, s3 w3 K+ }; U" \$ [7 P
                exqueue.rdptr++;
, n1 _5 S1 ^2 v                exqueue.rdptr&=QUEUE_LENGTH-1;; `4 v$ y. u! U& k% f
                return        TRUE;
! y  t, Q3 I/ ?: q        }
& s$ P/ F1 X% |        return        FALSE;
1 o! [4 q8 C/ Q6 Y) b) V}
8 A- h$ e( t4 [( ?
7 h# r1 q8 i, z  U& Ovoid        APU::QueueClear()
2 r8 b/ f* x) w- n% A' d& k5 M/ n{
( b3 o) F- ~  d* \. A+ q: ~4 F        ZEROMEMORY( &queue, sizeof(queue) );, c/ F" F7 U0 H' e) S
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ l9 B' J% E0 U# Z# A" u
}/ A  L9 z$ [5 @

) j1 |# M% G; q) zvoid        APU::QueueFlush()
6 Z7 ^7 r& w- q' D' {{
# W- K; E2 a0 v9 Y, }        while( queue.wrptr != queue.rdptr ) {9 D: k  u3 Z2 m
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: V) n2 z7 _7 d% p2 n, a- ^                queue.rdptr++;& G$ H# _% E/ s/ {0 Z$ y* D5 n6 K
                queue.rdptr&=QUEUE_LENGTH-1;
  v5 L, v* O* b/ k1 x$ ]2 s  U- |, |        }
4 M: q$ a6 B! F' D0 Q" n& B5 q; w9 @9 Q" T, `
        while( exqueue.wrptr != exqueue.rdptr ) {
! y, N% Z% z) A  f; f                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );# G3 n$ B3 M$ T. Z
                exqueue.rdptr++;" I2 P$ {& T; Q* N" r
                exqueue.rdptr&=QUEUE_LENGTH-1;
) @4 {2 j) J9 q        }# m; q, m0 a  K7 Q. a/ t( W
}; S- c% ]. T+ v* r5 A+ ~) H
  p$ U* R$ \; \3 o4 k
void        APU::SoundSetup()4 q: L4 m; @' H# V% j
{  z  t; t9 v, N& m" q
        FLOAT        fClock = nes->nescfg->CpuClock;! h) |. a$ K* ^6 V; D7 J5 J
        INT        nRate = (INT)Config.sound.nRate;: D; e( |" m% {) F# ]$ \3 x9 a
        internal.Setup( fClock, nRate );4 R8 M& F! F' O" E  v4 m
        vrc6.Setup( fClock, nRate );- a! \* y: Y5 l% I
        vrc7.Setup( fClock, nRate );
) J& G8 T. R/ e2 A; }        mmc5.Setup( fClock, nRate );, j. W; {) x' h$ m
        fds.Setup ( fClock, nRate );
: U* E/ p& V7 t4 Y+ U0 m        n106.Setup( fClock, nRate );$ v: C* u( \6 S9 A
        fme7.Setup( fClock, nRate );
9 X( c3 b5 n/ f& w/ C}* l1 h0 j# i# |% Y1 M

- a; \: O6 X" Zvoid        APU::Reset()
4 y+ q0 L" U4 r. d{: o0 b" E; w: C7 n/ c
        ZEROMEMORY( &queue, sizeof(queue) );4 E' Z1 v' B. d' Q( C3 }
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# P$ \2 P4 }9 P- D
3 E' s$ K# r  k1 R& k* s7 p' s% o" r        elapsed_time = 0;
/ w; O* F% Z- d" g/ R& p, K, z
6 \* N; L6 z4 ?        FLOAT        fClock = nes->nescfg->CpuClock;
- r# Y' `  e" o" p6 I: S6 s        INT        nRate = (INT)Config.sound.nRate;
3 I5 t6 O& q6 D/ T  p/ n3 x        internal.Reset( fClock, nRate );3 \8 B- u+ z: k2 a" [; L* }  C
        vrc6.Reset( fClock, nRate );
. X, j; _. y/ Z* x5 l        vrc7.Reset( fClock, nRate );
8 P; f" \0 j# E4 N7 S        mmc5.Reset( fClock, nRate );
! s( t( Y* W4 a        fds.Reset ( fClock, nRate );
6 r* B: U% @! L: p* i/ m        n106.Reset( fClock, nRate );* W) u0 s- c1 z7 D
        fme7.Reset( fClock, nRate );& w1 ?+ _. O$ y0 }* W3 F

! S( S+ a+ a: \. l        SoundSetup();& O; `0 J* S2 U" j
}
( p) }3 \. z7 b/ z2 J
& J! `+ [9 X8 a! U+ K! H, hvoid        APU::SelectExSound( BYTE data )( |* b; O3 ~& ]2 R
{  ^  E: A: o' @% C# u! q" K" n: |
        exsound_select = data;; h& \% P  b3 g. S
}
; Q" D% e5 M+ ]. ~- t8 c9 D" Q! Z$ \5 ?  e4 V$ q
BYTE        APU::Read( WORD addr )
8 ]+ B9 u0 j+ B& ?{1 H% A' o8 X- _) |3 G% k4 K
        return        internal.SyncRead( addr );
( S! [: O& E' P- h}
2 f% M0 ?$ r; C( c; b- _1 R4 Y4 j% d% r* I  j
void        APU::Write( WORD addr, BYTE data )5 D5 g0 G+ g7 e( t% a
{
1 A& u( t2 J4 {' p, i( {        // $4018偼VirtuaNES屌桳億乕僩
( u% K/ Y- w6 L% `        if( addr >= 0x4000 && addr <= 0x401F ) {
7 R" u. _, Z  M0 D0 a$ w                internal.SyncWrite( addr, data );
5 v5 W( ~* s/ H% p% C' ^1 p5 Q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );4 v0 {; u9 P* N
        }
: a4 M9 r) N  n& }/ Q, u}
" B6 b8 F8 J5 m/ m/ c7 L  I
% f# `; p7 n% T8 Z0 P( rBYTE        APU::ExRead( WORD addr )
& P6 X/ E% I0 f5 F9 q4 y  y  E8 G! {{0 M* z" F; R7 q, j
BYTE        data = 0;
1 Q- O& W& q% U. ~$ L
% E- O+ W9 a1 e  M  C  \        if( exsound_select & 0x10 ) {0 p$ e/ f1 @4 p0 \' K
                if( addr == 0x4800 ) {
1 q+ \/ _+ x4 j; g                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 K1 ]+ {! ^, u* c0 o7 Z8 P                }
. X$ A- Y( v- r8 }) v- G        }
; Q# D8 `  @( Y/ }        if( exsound_select & 0x04 ) {
- k3 A; O$ J! ^! c$ E7 O! \  R                if( addr >= 0x4040 && addr < 0x4100 ) {. W. R: D; ~4 d5 V8 g
                        data = fds.SyncRead( addr );- X, `6 y. f2 j9 M
                }
1 }% k' D( p% |3 ^! b$ A        }
$ W+ u% H! Q. A4 ?3 \! m6 w        if( exsound_select & 0x08 ) {
0 y8 u) t& a  N# h1 T, M1 {2 _                if( addr >= 0x5000 && addr <= 0x5015 ) {, u" U0 F8 z. L% k% }) e/ `; E
                        data = mmc5.SyncRead( addr );
3 B5 J8 T  s1 P3 W                }* w1 w% Y! F% x$ D
        }
4 `( D! q  d( n: Z& k: U
4 p; i0 Y$ N* ]1 P( O5 }        return        data;
) Y3 e* U4 d5 t  S% {6 C# O}' j4 U4 {+ b1 [) t/ Y

0 Z: A5 Z- S+ j) b; Evoid        APU::ExWrite( WORD addr, BYTE data )! }3 x+ n2 O6 E: h' {0 F
{
' M+ t' N5 \4 r3 T        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 E3 O* @' C1 \# l6 F1 u+ M
" q$ V5 h4 b" V! r5 O1 z' _        if( exsound_select & 0x04 ) {
4 c7 U1 I3 S; S/ Q9 S7 H8 L                if( addr >= 0x4040 && addr < 0x4100 ) {0 l6 z# C1 l( f& w
                        fds.SyncWrite( addr, data );
" ~8 V, C% K  Y' V7 H' J  f2 c& z                }( V2 |7 d/ h0 r0 C% u2 g  ]
        }
& B4 W) v8 n2 b# D' b+ G9 P0 O
        if( exsound_select & 0x08 ) {
4 i, I9 Z& y  j) Y) z3 e  n. E8 \$ K8 e                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 q! G7 C( I  O- b                        mmc5.SyncWrite( addr, data );- `# i5 k/ D+ B9 y. P. @) c0 M+ Y
                }" g1 m$ R2 u, Z# y  y: v/ F" V
        }
7 }$ n5 W6 g' ~% k) E+ z}
$ o, `; o/ E0 N$ c: N6 j' \2 b: P. p8 h% B6 v1 v! z
void        APU::Sync()
1 [7 u" A; D1 o0 T0 {, M0 O{
; n1 L. A5 {" O* a8 T$ s}0 w) |2 Q; w& o! Q# Z6 t" H0 \
5 t; c9 n; Y9 Q! a& b% q$ y) T
void        APU::SyncDPCM( INT cycles )+ e, d, h; ]2 x. W" x5 ^6 i+ m
{! r7 N5 y  f( i2 u
        internal.Sync( cycles );4 C5 R3 c5 v" i# h: c
: f6 p) S% X+ \: m; {0 l- {
        if( exsound_select & 0x04 ) {
* X4 C" l3 G) @0 q3 `                fds.Sync( cycles );5 m& _$ y% Q9 R5 R1 Y: T9 m
        }
# [/ S9 y3 _7 S9 d6 u. R        if( exsound_select & 0x08 ) {
' h* P& T  v/ i: l' \                mmc5.Sync( cycles );3 B5 Y2 N% t) a; v  x
        }
, q9 I& Y6 w$ @: Q+ K}; ]8 k! m3 h6 q, z2 C: Y
0 q& r. s& c. k  q3 Z( [2 A
void        APU::WriteProcess( WORD addr, BYTE data )( S& u" w; p) c* G+ V$ |( ~8 s) t
{
3 i, T- K, r, P  N5 {7 J- r/ S8 s$ d$ K        // $4018偼VirtuaNES屌桳億乕僩% \  A4 B; H7 @% P1 L0 |! ^- ?
        if( addr >= 0x4000 && addr <= 0x401F ) {
8 m* _  t+ {0 j) C8 u5 H                internal.Write( addr, data );, }1 ~/ p, ]# `* h, d
        }1 u: o3 v8 N' ?, y- g2 m$ q( }
}
/ u8 \7 ?6 A: S0 E/ w) k+ |0 R) u1 ^% d2 [/ ~! @
void        APU::WriteExProcess( WORD addr, BYTE data )
. B3 ^5 i/ w4 K0 B- K8 h# m6 E{
# }7 Z8 U. ^/ k" d) `; Z: f        if( exsound_select & 0x01 ) {8 Z$ E* N+ u' R
                vrc6.Write( addr, data );$ j3 T0 ~: n; b) F* z0 U
        }% V& w$ A8 ~' G
        if( exsound_select & 0x02 ) {* y8 Y: U0 T: @
                vrc7.Write( addr, data );
9 V3 c" w, v4 F4 M1 ~  k, g        }5 B5 N6 l5 g2 o" B8 ~, R
        if( exsound_select & 0x04 ) {( |, q* R% c3 }' [+ L! q. U
                fds.Write( addr, data );
& i6 r* T5 |8 K$ P. i        }
/ W( I1 j. m4 w2 B8 e0 y; \        if( exsound_select & 0x08 ) {
+ h# j! z" s- c+ I- x2 t                mmc5.Write( addr, data );
& n6 l( Y, D+ G, f, O, P        }
. N8 I/ N- {. }1 E7 l3 Q2 ~% f        if( exsound_select & 0x10 ) {
. l5 a% G$ F: A, }4 G6 S  J                if( addr == 0x0000 ) {
0 ~+ o4 B4 i+ q9 Z! C. B                        BYTE        dummy = n106.Read( addr );
' C/ [, S) l" n                } else {; }) f2 S! j2 Q5 T; f5 M# ?
                        n106.Write( addr, data );
0 I9 o6 X- N$ A& @9 y9 p( P, L6 o6 N                }& t) P8 @9 o8 @% B! u/ b( ?4 ]
        }3 ^0 `, k  g% ~2 [
        if( exsound_select & 0x20 ) {7 z2 s" {/ M9 i  a1 }
                fme7.Write( addr, data );% Z  M" b# b0 W9 i
        }: r  J. m5 g; k8 o5 k
}3 ~# z# I- v0 z% w4 _# F

4 N$ i1 }6 x+ G) L2 W  q5 C% o0 r# gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
4 ~1 Q* [9 ^9 Y  o2 U{( C! j1 H" v) u* V; }$ ]4 n2 ~# J7 `
INT        nBits = Config.sound.nBits;4 {, d3 @' A0 U/ ~
DWORD        dwLength = dwSize / (nBits/8);( g9 n9 f/ u& ?% s
INT        output;+ D8 w5 I7 f6 `  ~" l- J" [
QUEUEDATA q;4 K; O: B$ d  K. k3 E
DWORD        writetime;
. d' I/ k/ V3 G. l0 U
% i* U: s0 M, p" {. ]+ b* PLPSHORT        pSoundBuf = m_SoundBuffer;) U9 I) [3 }" M6 j
INT        nCcount = 0;
* o) s5 s- H6 a$ d& V0 d1 E$ ?
' [6 l  P2 R& ?9 C* Q0 r$ S: uINT        nFilterType = Config.sound.nFilterType;' S! `9 y4 [' v0 i1 y

3 ~, g7 u3 k8 P- k/ P" ]. D+ P        if( !Config.sound.bEnable ) {
3 j( ]5 W  U4 K8 j                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 Z& l. G/ q0 Z                return;
7 C# u5 l" o. C& p5 j        }
( D- ]5 ^( }. o9 }0 Q; k* k) d# P! p4 P/ `: }! \
        // Volume setup* z' ?+ g3 h# a1 `/ A! H2 m! f  i7 K+ l
        //  0:Master
% ^% n6 f8 z, K. _# e# R        //  1:Rectangle 1
' O' t2 c; G  `: v9 ?" z+ L. ]* p        //  2:Rectangle 2  N. g' M; h7 }
        //  3:Triangle/ k) N% _4 P) v1 D- t
        //  4:Noise0 @7 W8 z5 Y2 F
        //  5:DPCM, q* a* e+ Y& E# K; E
        //  6:VRC6
3 O5 {# M: @* W9 [& T% a        //  7:VRC7! s7 `/ `1 [2 d1 a' a4 \1 h( f& `4 C
        //  8:FDS
- S# q( R; |" \  c) M+ R        //  9:MMC5
( Z8 y) l! ~* N' w/ _7 E        // 10:N1069 k0 A0 @& X! d% q
        // 11:FME7/ Q3 D1 d1 |$ e7 {( e
        INT        vol[24];
* N/ R+ Z4 v& U  b" M        BOOL*        bMute = m_bMute;
# p- }) j* ]7 ?8 U( l        SHORT*        nVolume = Config.sound.nVolume;/ q0 Z8 K0 \& d  [
! L; a: D: A! n$ ?
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
, w) D: d" L! [/ u- m% b: {, a& c2 ~
        // Internal
1 _0 D; p8 C: M+ M* E6 y        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( y5 O6 ], T0 z- ^& m
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
  B$ v& d0 P7 m. K! o        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: v. A8 f  m# l: z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;- q  b  O" E4 b5 P. a+ M# a
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;; U4 e* z% o& L7 @/ M
; v/ b6 H0 S  I7 g& k
        // VRC6
+ d  r  e" v" f$ L! A. M/ ~) ]        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  f7 V' o" k+ m- [4 ~3 F1 C4 F; z, \2 b        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 r/ ]; H$ i9 R4 I& N; S3 n
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; k$ Y: b% W3 D+ |+ a3 V2 y  m7 G+ y

6 w! L6 n/ m. K) F* Y6 V        // VRC7
. F  t& }. B& M1 J        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 ^" T3 ]8 ]: L8 v
/ @/ V" K2 B. U+ ~3 y2 k
        // FDS
6 J$ E* s3 ]$ I8 O        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
& ~" s# p7 m! J3 _- s' I. u* ^9 q: i; S7 \0 N
        // MMC5' S6 X" b& p2 Z, ]# J# E
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! |; f6 B# z* G        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! _- I: y4 k5 C( K0 Q  x) a
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. K) Y! y+ u: w
- N) y2 U6 E5 R- k- z$ z- u8 z        // N106
' {. Z  f1 e$ P% x, Q; p' j  t4 Y        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( u8 ?' S8 g4 R# L  i. D- c        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* |( Q; f$ G" S8 [! b$ t) v+ ~7 V        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ a/ ^6 |0 G" ~: o1 d        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 o3 I" b# j8 V. D        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 C3 c. @/ i+ {# l: ^
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ T( J/ ]  q; A0 t/ |        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 b( V" L- J! `5 d        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) J" T2 [& I( w; J& {2 M" b+ _0 r9 \' k
        // FME76 L/ ^. P/ ~( V& F" S7 T" I8 a
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% Q) L1 q6 n0 T        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: c5 q; c# t5 N& Z9 U3 ?        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! [) B! s& A& g$ T1 V& S' k0 o6 }( d; r& v2 L9 `
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
: w2 Q, l$ w) A+ Y: m  e3 x        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
; U/ x4 V+ o$ ~; ?% `4 F8 y; ?- ^0 S' d# B& |
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
: I3 E% K) ]8 P: I8 Z  Z        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
6 @/ d* }, d5 e0 X3 {) b$ e0 [                QueueFlush();0 S* M8 K: x8 Q- ~$ [3 s/ N
        }5 N. n: O# J! G: B: S# Y! V
: W3 j. y8 J5 L, Q% e  Z. z; M/ z
        while( dwLength-- ) {
3 c" F9 y/ Q; D$ K# N% T! ?                writetime = (DWORD)elapsed_time;
$ @- A0 @5 _% V7 W/ ~( O7 e6 z$ L( z$ l2 ?6 o- Q: \
                while( GetQueue( writetime, q ) ) {
: y& j7 p0 m2 r$ h" W0 Y                        WriteProcess( q.addr, q.data );
; w" v% e, x7 X1 ?                }
$ [- L0 R! d/ s' h. Y  v: V' G( a0 T; e
                while( GetExQueue( writetime, q ) ) {- H1 @0 ?2 R( `1 x+ e; r7 t* L! A# e
                        WriteExProcess( q.addr, q.data );- y  ~+ q' `& z- ]3 c1 h
                }1 R) R4 p) }  f
" _2 l: C4 Z) L7 M0 C: X! ^
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME79 ]8 b! s4 f5 k- V0 l
                output = 0;
$ |1 d* S( t  \1 R9 C$ b                output += internal.Process( 0 )*vol[0];% @" R9 l& u+ S. z9 c. A" ]
                output += internal.Process( 1 )*vol[1];
* _" h5 B! g6 Y4 H8 E* v, {                output += internal.Process( 2 )*vol[2];
$ R# ?2 v& C7 N) f* h5 o                output += internal.Process( 3 )*vol[3];# ~7 {6 w9 L7 \6 g
                output += internal.Process( 4 )*vol[4];$ s; w( [5 R% B6 `/ r1 T) x
0 z# ^5 i4 `4 K: I9 L
                if( exsound_select & 0x01 ) {9 t3 E% e, t  T
                        output += vrc6.Process( 0 )*vol[5];
# @2 u* L' A0 L( f7 T                        output += vrc6.Process( 1 )*vol[6];
; n( h& r+ `8 d0 e/ _8 A                        output += vrc6.Process( 2 )*vol[7];
5 K4 }/ x) n6 t1 P2 d                }
7 R' w! S/ N9 s5 j# \- N  G, d$ d. j                if( exsound_select & 0x02 ) {
. {4 t+ j/ s7 S* p. ?& U                        output += vrc7.Process( 0 )*vol[8];
: o  T* |/ w8 I8 p( X% s  b( ?4 a0 R                }- X3 e3 s) g; w! F
                if( exsound_select & 0x04 ) {( J! U8 n* r, w1 R( e. v7 i
                        output += fds.Process( 0 )*vol[9];
) B4 r# j: T% Q) v, A/ Q9 g2 \                }
. d+ `3 V/ C2 n+ p( Z                if( exsound_select & 0x08 ) {
* R0 M5 I% e7 K: D; }* K                        output += mmc5.Process( 0 )*vol[10];+ F( T0 c% c+ n) G
                        output += mmc5.Process( 1 )*vol[11];% [9 b1 d/ G& U$ ?) P
                        output += mmc5.Process( 2 )*vol[12];
4 b3 Q& r" @7 d0 g7 U6 A; O                }  [; P7 P: b5 R3 R; W7 L6 n4 J
                if( exsound_select & 0x10 ) {6 L, r* r+ R# |, b/ g8 s: n* x3 m
                        output += n106.Process( 0 )*vol[13];! C1 T/ @# n$ i. z6 m9 l; U
                        output += n106.Process( 1 )*vol[14];
5 t1 S) ^2 E. c5 _& F. i                        output += n106.Process( 2 )*vol[15];9 I( g8 C4 x' D
                        output += n106.Process( 3 )*vol[16];, D2 _1 s9 X) R$ S7 B& Y0 h/ |6 H
                        output += n106.Process( 4 )*vol[17];' E! m! W% Y7 a, z. _6 \& _
                        output += n106.Process( 5 )*vol[18];* }1 f* n/ U$ r* r- X/ M/ i* f
                        output += n106.Process( 6 )*vol[19];9 ?, U, L9 j4 q8 ^* V
                        output += n106.Process( 7 )*vol[20];$ R, a3 _. X4 q) g" l) J) Y
                }
5 V; C8 g& L: X3 A( T                if( exsound_select & 0x20 ) {
: p9 j4 V) L1 O3 A% G4 ^                        fme7.Process( 3 );        // Envelope & Noise
$ Z7 \+ S' Z2 ~: }                        output += fme7.Process( 0 )*vol[21];6 `; {/ k( Y! V" A3 F* w
                        output += fme7.Process( 1 )*vol[22];
8 V/ m5 v& [/ h( q+ K' m  C: i* T                        output += fme7.Process( 2 )*vol[23];( W1 L, e& W2 o6 V
                }
" Q4 {  X, q/ k! p& T9 L5 j
4 V1 Z' M4 ?7 A* A- _& C: Y                output >>= 8;6 F, p7 h7 O: R- I; [
+ l$ P) N0 P* u$ K# s) f
                if( nFilterType == 1 ) {5 j' c+ F- z' `6 r
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
3 |% X) _. p: o- T' ?                        output = (lowpass_filter[0]+output)/2;( e$ |+ R6 W: w- q; u5 l' S7 d
                        lowpass_filter[0] = output;
% R( _- o' U1 |                } else if( nFilterType == 2 ) {8 J# h/ g  b! f) Z, m( D: v/ h4 Y0 j
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
5 j& ^5 T' ]. l% Q                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: X! m; [: X9 d                        lowpass_filter[1] = lowpass_filter[0];4 G) ^0 Z: R( i6 ]8 D7 \# {
                        lowpass_filter[0] = output;
: ~7 l' `5 T5 D6 _1 o                } else if( nFilterType == 3 ) {
/ k: p; R$ F4 ]0 r' v( w                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)* k3 W) @, J! ]8 Z  T' T7 Y
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
- x) r5 N5 g& u                        lowpass_filter[2] = lowpass_filter[1];
1 j' J1 r: h2 W6 q$ P2 d                        lowpass_filter[1] = lowpass_filter[0];; I. Q' H6 ]# {2 ^
                        lowpass_filter[0] = output;% |* r9 g. r+ I# x0 c
                } else if( nFilterType == 4 ) {
2 [5 v5 \4 d/ E; G. n& ]                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)1 H5 e5 ~. S4 u2 ^; w! R% `/ P+ H2 p
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
+ J1 V! o* X% Y) a3 L: b                        lowpass_filter[1] = lowpass_filter[0];' N/ E: R8 P) y7 z8 l3 E
                        lowpass_filter[0] = output;0 r& G& e; P6 e/ ]! b
                }$ E4 E' @& E% I# u$ i
7 w$ I5 X8 R3 U; z- ]
#if        0
; L' L: L4 u! f                // DC惉暘偺僇僢僩( ^1 `% p6 m2 ~$ w9 ~
                {  i: x, Y5 s  `: w+ T& d; y- T" l' k2 u& S
                static double ave = 0.0, max=0.0, min=0.0;. L  H6 o" Y( R' v) W
                double delta;, \& Z! n* Z% |; R8 X( O% c
                delta = (max-min)/32768.0;, ]9 @) m% H+ u- C, I5 x4 [1 w
                max -= delta;% r0 F7 a# r3 K& A, Z% g) @
                min += delta;1 N2 H; F  m3 P) c
                if( output > max ) max = output;% }- M9 A! Y$ s
                if( output < min ) min = output;
) F1 k' O$ J7 x9 x6 n8 K; B% V/ w                ave -= ave/1024.0;: x: U+ C( b0 C6 Z* n" D% A
                ave += (max+min)/2048.0;+ P: _  r; ?" Y  L
                output -= (INT)ave;; j* @( r! x, d, {+ {- [
                }, A8 i6 j' U0 E6 ^1 t3 a) \
#endif0 _& K1 H  d7 J- |& A! ^" a2 S* ?
#if        1
8 \# Z5 F* g2 {0 n% B# V                // DC惉暘偺僇僢僩(HPF TEST)! w  H; k1 A+ _  U4 O0 C
                {
  Z8 u5 J  T( W2 V" |//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 H; e7 |' ]2 |' ?. T9 R
                static        double        cutofftemp = (2.0*3.141592653579*40.0);! J  u8 [% }5 @- r
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
5 \# H, y6 y8 }  S3 M                static        double        tmp = 0.0;: K( I8 x) ]" ~! V
                double        in, out;  C; F8 |! c9 z6 H

: U0 Q# M: }+ b4 \( p, K                in = (double)output;
: ?8 ]- j( j/ S/ X3 a; a& z  |                out = (in - tmp);! q3 v* Y0 K$ d' L* m; W* }+ H, A
                tmp = tmp + cutoff * out;1 u7 `1 m- a* w! E
% f+ p% n0 M$ O; V5 Y. ]8 M
                output = (INT)out;$ i9 z+ @$ s- Q% T9 m
                }& S. q6 f8 Y9 i) @$ P' v1 w
#endif" Y7 y- ~+ c, R
#if        0% o9 T. r+ @: i) @& d
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
( s1 B, z& }0 m' Y( F7 l! }7 T                {
. D, P+ c; K( b* h                INT        diff = abs(output-last_data);
7 a/ R# G4 y8 {0 q                if( diff > 0x4000 ) {
% t& O6 J/ i! j0 Z9 I: n0 c                        output /= 4;! ?6 o& R& a( R" p
                } else
' ]0 ]$ f" M# d( p% V5 s8 P8 S2 f9 w                if( diff > 0x3000 ) {
2 m( F! {3 U, `/ H: }                        output /= 3;
6 e+ I* g$ _4 D                } else
- I, a: X% ]" H5 [; \- f- M                if( diff > 0x2000 ) {
, V9 f. u$ H6 o+ }3 @                        output /= 2;
! d6 I6 J; G2 }) b" C                }
/ g1 m; @4 v7 K. k0 }) V                last_data = output;* p6 i, l! {! X; V. V, p$ _
                }( g- F% I& |& C" K1 i
#endif( @- a5 e2 w8 h7 Y; n: j# }. V8 ~
                // Limit4 U: T7 k' K; |% m# |" ?8 q
                if( output > 0x7FFF ) {
" P) ~2 ^) d6 p% K8 b                        output = 0x7FFF;  E' ^% r' f3 J- m
                } else if( output < -0x8000 ) {6 @, ~, a5 j' }$ o1 z; b6 B
                        output = -0x8000;
( s4 |2 Z. E: h                }$ q3 L4 H" L6 {; \! A4 W" X# _

) C5 O) I4 ?' |5 R  k- m3 q/ I$ k                if( nBits != 8 ) {
) l4 T  p! t* n$ ?                        *(SHORT*)lpBuffer = (SHORT)output;4 A0 ~- h& g0 D
                        lpBuffer += sizeof(SHORT);
: G) Y" f" R. k0 K( J                } else {
6 Z* T$ h# g$ F8 o3 @5 _                        *lpBuffer++ = (output>>8)^0x80;
6 N, c7 ^1 U+ T2 R5 C, z                }1 b7 v3 W( N& E: M
6 V4 T7 L  v, v" ^6 e/ E+ b
                if( nCcount < 0x0100 )
, e, A$ o9 n4 ~" `) O: _) v; j                        pSoundBuf[nCcount++] = (SHORT)output;
& c2 H# d3 d6 x; _! g1 x8 M7 s+ o9 k0 L' Y$ a$ R+ w6 E
//                elapsedtime += cycle_rate;  s: _; J8 h2 ^# Z" J- V+ r. y
                elapsed_time += cycle_rate;8 @6 @5 ]$ l9 X
        }
) h; v8 F7 A# Q2 N; }9 p* ]1 q. }$ g8 l- b3 P
#if        1( k: U( |& v' X
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
' |5 b. E) M  x2 B                elapsed_time = nes->cpu->GetTotalCycles();
' o$ E# ^# d5 R& t        }
3 x- B- @5 Q' L  m# T        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: _8 E0 f' F2 t, ~                elapsed_time = nes->cpu->GetTotalCycles();& q. V. j  s' ?+ T3 R, {
        }
1 f7 S; X6 _0 K#else
5 W* H/ h/ C) L        elapsed_time = nes->cpu->GetTotalCycles();& y8 F, I- `( }+ P& X) }* k
#endif
$ Q/ E; p8 i$ Q" E- h7 E}
4 r4 Z3 I. ?. m! w* r8 ~( ^0 ?) r6 u- c# Z8 u
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* v& \9 Q" \. Q8 B. s0 {; ^2 Y; L5 N
INT        APU::GetChannelFrequency( INT no )' I: }7 Q! x2 J3 r4 w: i
{
' l6 L4 d, B, g# A2 \9 s        if( !m_bMute[0] )' E7 s1 [) N( @9 f6 S/ f
                return        0;
* g+ h% o- ^9 s: P7 r) v+ B; t( X1 L2 O6 {( @
        // Internal
0 @/ @! \/ d4 L3 `4 ^& |% I7 X        if( no < 5 ) {
; x# R& [6 u% I( f& p# K. w                return        m_bMute[no+1]?internal.GetFreq( no ):0;7 M' L* A6 S. ?2 P# `
        }" d3 G1 ~$ b& W( Q
        // VRC6. {) }0 C; i! q) W" @9 j8 |0 \
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {5 {6 s% Z2 H7 S. l
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
. H8 q% J% K4 ]% t        }$ r1 W1 q! p, Z% J5 F$ u
        // FDS1 M& Q9 U, |0 J8 G- k$ W' y
        if( (exsound_select & 0x04) && no == 0x300 ) {
9 y1 S! s! Y. z3 k6 X: B. n                return        m_bMute[6]?fds.GetFreq( 0 ):0;/ c! w* K; B' u
        }
$ x$ @& o1 l6 y" u: y4 x. }        // MMC5
5 q+ s* s8 ^2 O, h- u: m        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {# Q. u7 j: D8 u/ b
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' q4 e- s* P# l5 [& N" u; u( }
        }
! l6 m: w, t1 `( n" G. Q- t        // N1066 q9 K3 D  A) l9 w/ G3 h
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
, [& e) i) I& y) e) b( A                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;/ O  [* J( L2 d, _6 M
        }
, }& h) x5 A% r        // FME7' A: Y3 X( R2 j; s
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 o: e  p( n4 z) N2 [6 a: U7 F
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
% S* O# {4 C, p9 H. K; [+ Y        }
* P. b# v. x/ Y, F        // VRC73 _- e. C  a# j2 \5 G  B
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" G. w7 n. @& W5 m' W                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ m% M" w0 Z- r  U2 U- V, @
        }) Z7 F0 S6 `% \6 B2 M6 t
        return        0;
" p5 ]- l% y( o' O0 K1 u4 H}
% d6 @. v4 [$ R- u" Y5 T1 ~( \! T1 T- g; _2 Q, e9 \
// State Save/Load
# s4 L" v* ~/ K! G9 w8 bvoid        APU::SaveState( LPBYTE p )1 J: `7 @4 z' x1 H
{
/ B& l  d7 i% ?  F/ j' w#ifdef        _DEBUG. t0 Z+ I( [4 \$ |- ^
LPBYTE        pold = p;9 Y# _2 [4 L$ w' W2 s' T
#endif
+ n3 A1 e% K. p9 ?7 \- l2 q$ @. N; O7 w# u# U3 n
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ v' e% u$ p. O9 y6 Y
        QueueFlush();
8 R5 }; ^5 {: f) S: f. E7 ?0 b4 e$ e/ B2 t+ J  T, L( p
        internal.SaveState( p );4 u$ E+ G/ d* t# L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! f) A' }. r! U" D8 L- r; K
5 D" U" i3 ~+ b) @8 |$ L2 M. X        // VRC6' K2 ?+ r1 ]% ]! }1 p1 M
        if( exsound_select & 0x01 ) {' X/ g3 |4 B- l8 I/ u" `) E; q, g
                vrc6.SaveState( p );
3 n- W! P! |3 }+ J                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ [2 U, q, k8 g6 X0 F0 f
        }1 r# a# f7 W: i
        // VRC7 (not support)
# r3 K9 C% S( H' I! Q        if( exsound_select & 0x02 ) {6 a% M) {  G+ j: R/ _4 E* s
                vrc7.SaveState( p );
% T+ @( l5 M" R; I                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding6 t! B* A! H. F" z" H
        }
  ?' X8 M0 s% D4 Y0 I- ]5 Q0 ^/ D        // FDS
0 s& O# @4 J. r- M1 R  V& Y0 V        if( exsound_select & 0x04 ) {
( W( v) z. |0 f4 G4 f                fds.SaveState( p );
; P( g4 E# s5 {+ z# v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# D+ `, M) J, O/ r9 G        }+ h$ u( W  k8 r/ `% M5 }
        // MMC5
/ Q/ @" K8 h4 Z3 O7 [. ^7 _        if( exsound_select & 0x08 ) {
, F- i# |  x. D& n' A9 k8 V& [  L8 K7 ~                mmc5.SaveState( p );
% V+ S- [' r4 S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" C  n  o/ ]9 V9 g: r
        }& C" `2 J6 r+ V# i
        // N106$ M9 y, o+ ]' h; S9 ~
        if( exsound_select & 0x10 ) {
8 N1 F2 M& v1 X- [8 [# I) R8 q                n106.SaveState( p );; R% n' h5 R  q. m) f& O
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: ~; b3 `  @0 i- D& d        }2 q4 o% |8 _: g. n& ^& U
        // FME74 R& i6 d! [* t
        if( exsound_select & 0x20 ) {
* F- C/ j/ Y2 p5 [6 O                fme7.SaveState( p );
" G; G3 F; _$ Z" q- b: J2 i                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  @4 Z; |( ]- z; w        }
& n0 H6 N) L; `* @- G+ l% C
# v- Q- q3 t, k% P8 Z& j3 \#ifdef        _DEBUG* _. w$ f! ~2 L( M& z# w" l
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );4 G' v. X7 \7 l! W
#endif
; ~8 ]" s5 C5 a0 N}$ D8 ?. g2 R: V( ?# R, T
! v3 m) I* R( ~
void        APU::LoadState( LPBYTE p )5 K# N+ w( e9 M8 Z( k; K# x! Q1 W
{
, M; W5 q& `% |1 X        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
# T. W8 k' d" o" B0 X( V        QueueClear();+ |" L: C; R  D7 _& d' f

6 _" G: T! V* b6 X5 c" L        internal.LoadState( p );
6 l" |' Y7 h* a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding" j( h8 l7 [0 q# w! d" l8 U3 L
4 p0 {8 R% U; |: n9 i
        // VRC6& b1 s5 v3 _) u6 e7 l' \
        if( exsound_select & 0x01 ) {
" i, f- e3 V: t, k. F5 [                vrc6.LoadState( p );
+ d# W, m9 A. s# d( ~                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding. b4 O% n/ Z% Y9 h) ?$ s1 I5 z3 \
        }
3 n0 f* K! i; N9 a/ Z        // VRC7 (not support)- j9 x: t; Z( h) x% K
        if( exsound_select & 0x02 ) {
( b! y8 S7 p  q0 v( _0 U: ]! ]' W- ^                vrc7.LoadState( p );  r; S  z% G+ A6 L
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding8 L2 g2 \7 Y0 a3 c+ `3 E* t6 g
        }
2 Y! q* d3 K- p6 u: S. M! \        // FDS
" `; r' F# g. u# T        if( exsound_select & 0x04 ) {8 d6 g$ f& [+ a" x
                fds.LoadState( p );
$ `7 E6 Z- }6 U' u, Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 I9 {7 g. e% x8 m        }& R; E* f4 A' c
        // MMC5
* W+ @1 f% T8 T6 ]) a$ }& a        if( exsound_select & 0x08 ) {
% x/ O2 d# [3 M. e5 }( y                mmc5.LoadState( p );, s: }' F$ O* w5 l+ k2 f
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" j1 L# ^% Q) E7 A! U
        }0 Z" O1 S6 e( e
        // N106. Y  p, S5 J5 w
        if( exsound_select & 0x10 ) {) H1 c) ^3 t' g% k% {. n
                n106.LoadState( p );( j3 ^, Y4 M3 D+ t$ L+ `( V3 Z+ B
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* a) n& X: D+ K: W, U
        }
' W# `* q3 O( }4 T4 L# P        // FME70 l# L+ e3 j8 J* T& ?& x
        if( exsound_select & 0x20 ) {
1 V' `/ ^: ~0 H' {) Z                fme7.LoadState( p );
5 w7 W+ A5 k* k6 V3 L3 Y. S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
# _: W: V0 a' V' B3 P        }
4 g' f% q( e& j9 V6 X' y9 E7 {* Y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
. ^; }# F# H8 e3 R+ O$ n+ |可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
: F4 B; F* {0 ~* D% U4 S9 o感激不尽~~

8 b6 t! v* ^2 o* V; ]恩 我對模擬器不是很有研究,5 o  g8 F) |* x& W1 l2 L
雖然要了解源碼內容,可能不是很困難,
& G0 @5 x. b4 ^* n不過還是要花時間,個人目前蠻忙碌的。! g6 L% d. w! ?! k

" y& g4 s+ e( i  Z1 a8 P7 ]給你一個朋友的MSN,你可以跟他討論看看,
9 V: o" K% {  B( O( n他本身是程式設計師,也對FC模擬器很有興趣。/ O* R& E+ \' [  \+ H0 [
% ?# k% w8 |0 r& z; i) J
MSN我就PM到你的信箱了。; I0 [+ V, W! E2 Z  n8 G
8 O4 y# n. Q3 k% Q. ]% Y% }
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
# g3 Q/ _0 K2 I- b% i/ s3 b1 h8 [. k% D呵…… 谢过团长大人~~
5 c% k5 N* E9 v) j. r5 ~

% V/ n( ?0 D' u4 l" i3 [' M哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 j! `( I: k& m; P3 {+ v团长的朋友都是神,那团长就是神的boss。
# y* g1 s5 z# a; ]
哈 不敢當,我只是個平凡人,
" q; p! u* c6 \; H要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& |( }4 J. n# ^  P
ZYH! s6 D8 X4 G1 D) R4 k' X
QQ:414734306# K1 T0 N- z% S; M' `" J
Mail:zyh-01@126.com
, w- v' M- U8 G0 k3 {6 j* D7 U3 I0 ^( L' q
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 ^, ?0 ~0 T, N: V5 z0 y
再次对团长大人和悠悠哥的无私帮助表示感谢~~

/ q, L. p0 |8 C, ]3 }1 A不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-30 08:59 , Processed in 1.083985 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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