EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ _' v  P9 D5 G% x1 I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~: I" @# o$ }$ ^$ d: R
这里有相应的模拟器源码,就当送给大侠了~~1 ~+ y$ O0 F2 A8 p3 j- S
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 8 ~  I. n' v9 Y- R, w) ^
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
$ W& @+ e5 E5 I& q& z5 e楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 u: d$ [- I9 }- ~, }7 M) a这里有相应的模拟器源码,就当送给大侠 ...

+ W" J1 t8 @# S4 h& I; j聲音部分(Audoi Process Unit = APU):
7 U. ^/ A3 ^3 U7 V6 P5 t, i2 y.\NES\APU.cpp
8 u) ^3 F  L: V2 w  z.\NES\APU.h
5 m# q! f6 b- N) m; R; W- Z5 e
6 o+ t/ s: y4 Y( I; p
( a& z/ K" }' }( n; g. V" v影像處理部份(Picture Processing Unit = PPU):
2 z! ?. a+ Q7 I! G. @.\NES\PPU.cpp5 C* {3 t9 e; ~! @3 P! I/ F6 w
.\NES\PPU.h
( ]  d2 w  @2 f: O$ o
( J& E& K9 Y& _. o) m如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
8 X2 i7 H! _4 |8 v% E. b(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 q% }+ k7 b$ R
//////////////////////////////////////////////////////////////////////////! V8 `" z4 t: A- Q  z4 S) j
//                                                                      //9 k- g( a+ [1 G  O# Q
//      NES APU core                                                    //! [5 x- {5 d" [5 j( v
//                                                           Norix      //
& S/ T% h# {+ d6 K7 ~# k//                                               written     2002/06/27 //
% i- |( m. s2 t% M; f//                                               last modify ----/--/-- //
( ]& g" D+ q$ W. I/ R0 q2 o//////////////////////////////////////////////////////////////////////////
; `& O4 d- d0 @) K#include "DebugOut.h"
/ ^2 ]0 B* c  I#include "App.h"3 r: K+ \; M; i! {
#include "Config.h"
) K+ J" _) o. L' ~/ w/ o3 ~& ]
& n- }9 }+ p& {#include "nes.h"7 w9 b3 Y- s6 G
#include "mmu.h"
5 @. a, B, n  d5 T( s#include "cpu.h"
& O3 _% q, z1 O5 t' u#include "ppu.h"
- ?' z: l) P4 O) Z#include "rom.h"- x/ v1 T7 L: q3 L* g- @
#include "apu.h"  ^0 s+ L; N7 X7 b8 H; D& T1 h

( h$ \. c8 r5 x6 w+ m8 j. a- f& n// Volume adjust
0 Z" h5 C! E1 {8 N) |1 x. y0 l4 P// Internal sounds( r: [. }! U) o. d+ d. j1 A
#define        RECTANGLE_VOL        (0x0F0)- C2 ^0 g4 e8 J5 `
#define        TRIANGLE_VOL        (0x130)- p- l8 t" b$ |% j
#define        NOISE_VOL        (0x0C0)& p3 O. ^, f0 |# T$ t; d7 `
#define        DPCM_VOL        (0x0F0)% F5 A0 s9 {5 N$ u' c" M1 V
// Extra sounds/ U5 B( X. |6 f( i! N8 K0 x5 C
#define        VRC6_VOL        (0x0F0)4 Q- L. ], ]; B( p* X( W
#define        VRC7_VOL        (0x130)
- q- i3 B+ O% Z#define        FDS_VOL                (0x0F0)
2 @& H  ]6 c- U#define        MMC5_VOL        (0x0F0)
" A- Y8 t- b2 Q) ]4 t" X#define        N106_VOL        (0x088)% y9 @7 t0 |- w  P
#define        FME7_VOL        (0x130)
! a2 z! d& F$ k% {! |9 `% M/ B$ i' r$ J# U4 z& D# R0 e
APU::APU( NES* parent )4 M7 w6 J: N* D+ ^4 S
{! V' K4 Z# }- J" ~: `+ Q# x* \! b, Y
        exsound_select = 0;
( d) h; I* m9 c! {6 {
2 I6 Y8 e' n- M1 u! k' [2 e        nes = parent;# r4 U: C8 v0 I2 f0 r1 q3 g. p) U
        internal.SetParent( parent );. ?' Q- p$ p$ r
6 m% F" I2 H9 A  T2 H3 I1 U
        last_data = last_diff = 0;7 o7 t4 r4 j7 }) D9 `+ w

0 c8 X4 \# e" b& H/ v% S6 @7 U* |' ~        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );  w! ]% J% u# p

0 `" E0 G! O3 O8 P/ t        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );) b/ b; U+ V" O- K, [+ A8 t6 [  b
        ZEROMEMORY( &queue, sizeof(queue) );
3 _. f! C' e* O% }        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ d. v( a1 z- l7 C
; c$ u- M# g6 m& W) r
        for( INT i = 0; i < 16; i++ ) {
$ T0 \& c1 D6 P: j                m_bMute = TRUE;) l' d' H, B! O7 a" K* \
        }
% h# m  r2 c$ v& \! o}& z7 e$ F( s4 g1 l) y9 P% B

" P$ v  k* @5 JAPU::~APU()
. t% a1 ^% G0 W( t4 o{
- x1 w; }7 b* A& y}
3 M8 ~9 e' `$ h2 o5 p0 a& H; `, p% s6 D1 B
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 l( X* E* i8 f. p8 k5 _
{
' Z* h8 ?- e9 K        queue.data[queue.wrptr].time = writetime;5 ]. V% }1 X( e8 g0 F0 k( B, Y# t
        queue.data[queue.wrptr].addr = addr;. `) r" q7 b( J8 F# y1 V
        queue.data[queue.wrptr].data = data;
( u- r; H# L$ ^8 o        queue.wrptr++;
( ~5 L1 o& d& \/ F7 |9 E/ o& l        queue.wrptr&=QUEUE_LENGTH-1;* Z# P" Z9 y! l4 m/ A6 Q( N
        if( queue.wrptr == queue.rdptr ) {2 H& J5 w2 o3 i2 y8 j. Q1 ]5 e
                DEBUGOUT( "queue overflow.\n" );: O% j  f* v0 ]8 u
        }* O9 P1 I4 T9 B
}
, _* H% ?, a6 {; {$ P
3 R& o: m) ?; _; YBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
  `4 w( G/ |1 L: {{
9 {3 h9 W1 S; j/ X% ^        if( queue.wrptr == queue.rdptr ) {* g# m: r' U% f- {2 h
                return        FALSE;
7 ^8 e% v& C+ \  O  D# _        }
$ y: _& W; `( {9 a7 |! |        if( queue.data[queue.rdptr].time <= writetime ) {: B4 m) i( ?# R( H, g9 b2 o
                ret = queue.data[queue.rdptr];  D+ K% @' j. T2 s6 Z$ j4 M4 o
                queue.rdptr++;
$ O) S$ a' s  J                queue.rdptr&=QUEUE_LENGTH-1;
2 O+ j: K$ W) r5 c" m                return        TRUE;
  T' G/ {; c5 \/ o        }
% X1 H& S; m/ w$ w        return        FALSE;1 t& V+ ]6 q5 U# L1 M1 V
}
6 D' ]# Y( O2 K: g( F) H0 A9 L, {
% B6 m; `6 A# ^9 K1 Yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* ^5 |6 F+ \+ z& v{; {% h6 s$ p- T, Y! i& \* t% \4 g+ L6 H
        exqueue.data[exqueue.wrptr].time = writetime;/ B7 i' V7 q9 p# M8 D* x
        exqueue.data[exqueue.wrptr].addr = addr;
2 m5 X0 W/ e0 U: {        exqueue.data[exqueue.wrptr].data = data;
9 s' I+ {4 J+ V7 O9 C        exqueue.wrptr++;
8 J: y; _; z  X# w2 E/ P        exqueue.wrptr&=QUEUE_LENGTH-1;
% N( w  K( G& [# e        if( exqueue.wrptr == exqueue.rdptr ) {
) v9 q7 E. a% ]7 T* M' C/ @                DEBUGOUT( "exqueue overflow.\n" );9 J' c, y" o" n
        }
& y+ _+ `, P/ {  G8 S}
7 M0 G0 V7 t6 |- K# A
; B+ ]8 \1 L  I1 \! y) \( a( H7 F  TBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* z" t) }& I1 A. ^! V( m
{! o+ F) Y! h# N; A: `7 \5 U
        if( exqueue.wrptr == exqueue.rdptr ) {8 {4 ~5 c* d" f
                return        FALSE;/ M& o- Z& o1 b/ j
        }( k3 j- Q- U9 S9 N
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {% [& h+ }' |- l9 _6 T
                ret = exqueue.data[exqueue.rdptr];" c' Y/ S) d% Z0 P; @
                exqueue.rdptr++;1 O0 D, C, n( e8 b; @+ G
                exqueue.rdptr&=QUEUE_LENGTH-1;  ?" z5 G8 u% D( k2 ]/ }
                return        TRUE;
4 g# x5 d9 z( o* V9 ~8 v& V        }4 l! n2 c* o2 m4 \
        return        FALSE;( R8 l/ Y. }# Q% Q" h
}
* g8 M. O' h% L/ z* Y+ P7 Z$ M( ~7 B
void        APU::QueueClear()
+ L7 U; Y; @0 d, H/ b& X{- W9 @' A2 k3 k$ @) f
        ZEROMEMORY( &queue, sizeof(queue) );
2 J( p: h- s8 @        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. j8 s1 ]2 O! f# W* b& m}% m# M: A" O' X. b4 D# l7 J

7 T7 M9 A/ n5 w: D6 {: @5 ovoid        APU::QueueFlush()4 T5 Y+ i4 H9 `
{
! u% ~* n; q  ^6 e/ s* i/ L9 l: R        while( queue.wrptr != queue.rdptr ) {
. B; \, f5 P$ N, z0 v) j/ a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );0 \3 g7 G8 V7 |: H" o. s- [1 z( m
                queue.rdptr++;) i1 \' J+ H& f4 K; L0 o8 G. j# {
                queue.rdptr&=QUEUE_LENGTH-1;
! Q% l' o3 O* ~' o, P        }( Z  b- F* u6 c+ l9 }5 R

) X" t5 ]7 I9 a1 g        while( exqueue.wrptr != exqueue.rdptr ) {! @% n0 w! z' D
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" w- L% L- a# J  {
                exqueue.rdptr++;9 S; k% n- p" {
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 m8 i. a+ @: U2 f& e" G        }
. [8 E! p6 T% p! s- k# j, ~5 E}
. Y' i9 @8 ]! A
/ o8 y* d- y8 O# \  [7 M2 Jvoid        APU::SoundSetup()) p" Y& S7 L5 l$ ]7 e7 g* ?
{
/ h( C- d1 X2 ^' z* T+ y0 u        FLOAT        fClock = nes->nescfg->CpuClock;
& ?9 `# B! U: A+ F: D% B        INT        nRate = (INT)Config.sound.nRate;
2 C- u0 d& B7 _* ]% j  I) x* _1 ]        internal.Setup( fClock, nRate );2 I2 o6 C1 K  y5 V
        vrc6.Setup( fClock, nRate );
# x$ G  u7 Y2 I* o( f3 _) d        vrc7.Setup( fClock, nRate );
: b* ^' E) Y- z6 }9 a. o        mmc5.Setup( fClock, nRate );) r8 v0 S; A: E
        fds.Setup ( fClock, nRate );$ u! [. t& i+ N# I6 B- [  z
        n106.Setup( fClock, nRate );
4 h8 u1 U  `4 J0 ^- w        fme7.Setup( fClock, nRate );
# |+ g) M! A/ |}
; `9 m' B$ M, d! c' Z/ {/ `1 p* |$ J5 d& b  Z" Z" O: j; j( F
void        APU::Reset(): m7 ]4 X' F$ i% Z& [2 @- F4 h. L1 U
{$ y# D) X. G% s
        ZEROMEMORY( &queue, sizeof(queue) );" T) l' V1 ]! n. z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ x3 f2 n! V9 F6 j- l' J$ x/ A' a
, Y2 n3 R" @% x& U, o6 I4 d
        elapsed_time = 0;
, N% ?5 e6 U3 [* g* |/ t1 P4 N5 e, Z& `9 |9 A- i
        FLOAT        fClock = nes->nescfg->CpuClock;
# |( f2 K, L% G4 L, L/ z9 n% b1 B' l        INT        nRate = (INT)Config.sound.nRate;; M* q# I5 q% i7 S, w+ h: g3 o
        internal.Reset( fClock, nRate );5 R7 N5 z; g. s$ y0 K
        vrc6.Reset( fClock, nRate );+ i3 g( B3 Q  L& }
        vrc7.Reset( fClock, nRate );+ Y7 _  m& W# f
        mmc5.Reset( fClock, nRate );- a9 r+ m# P" L) k5 W5 ?4 N
        fds.Reset ( fClock, nRate );2 x( K1 P% a6 W
        n106.Reset( fClock, nRate );6 Z" B1 i/ h7 [9 U
        fme7.Reset( fClock, nRate );  N0 T; H  R- j" s
, w! Y5 @+ V  q/ t" H
        SoundSetup();0 R0 i- r2 \' b% Y& R+ ]; [5 r5 O
}
+ o+ Q3 h7 i# m' e0 S$ S. @, {6 X" u3 a8 I* I
void        APU::SelectExSound( BYTE data )9 e& x* N& S/ e4 p; v! R
{
, l( P+ p8 s) Z6 i5 a* Z# ~- Q        exsound_select = data;
- V, K9 {0 X8 u/ ~}
2 @$ k2 A+ C( _- m. e# g  R2 K* [9 U$ V9 t# E
BYTE        APU::Read( WORD addr )
" c" d( F& a5 ~+ Y{/ s, n% C3 l8 o4 c
        return        internal.SyncRead( addr );/ P) }: d. y, S( l8 U( h$ Z
}
# l2 C+ k* b0 e9 G$ a8 k, ]5 ^6 W' F* a8 U$ d
void        APU::Write( WORD addr, BYTE data )  ~3 E& F( U4 E, L7 D3 p
{4 T- Y# K/ r( z. f7 D" Y$ _
        // $4018偼VirtuaNES屌桳億乕僩
! v* c) ~! S* O  V( `: R        if( addr >= 0x4000 && addr <= 0x401F ) {7 q) F9 m2 r6 {$ H
                internal.SyncWrite( addr, data );5 w5 a" j/ y* X, N* N
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 a7 K9 W$ K5 c' w' h9 \8 E
        }2 }0 f+ h6 u: E% _
}
4 ?0 g+ r. Z! W0 ?+ |' L' [6 o
3 j6 w+ R- S/ m4 }BYTE        APU::ExRead( WORD addr )5 l  C' \% ~3 h
{( e) j* n0 ~4 {
BYTE        data = 0;; {, K8 R( y3 o4 \0 o
* X, W$ X! y. g# N1 m( ^
        if( exsound_select & 0x10 ) {
  M$ A# C" l  o9 ?6 H( Z3 l" S5 d                if( addr == 0x4800 ) {
& Z' Z  ^' N8 d" s( x0 L                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
9 z' }" |" V' y% }                }+ E# I& H+ F- E$ g; B% P
        }
$ f- i7 K6 `4 K' r: }        if( exsound_select & 0x04 ) {
! M( z! J9 q8 Q- _2 j                if( addr >= 0x4040 && addr < 0x4100 ) {: b* E- t, t. F6 ^6 A
                        data = fds.SyncRead( addr );4 ^; O6 H6 y# @7 z) e  d
                }
# _  Y9 H+ q: G0 W" M% n        }
# u' g( k! d, n6 F$ _; s; _        if( exsound_select & 0x08 ) {) Y8 P6 y8 j/ k( s$ c9 R& |
                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 _" z1 z' l. N, Y% ?- z8 b- ^5 ~                        data = mmc5.SyncRead( addr );
8 d# \( N3 v' X2 T# o+ _9 q' d                }
4 U4 ]- m2 V( X. p& |6 J& V        }
6 u' R  @8 F' ~( v1 r" ]" g1 j5 D+ }0 [
        return        data;
; G- G( e6 m& q! w}0 ^+ M( x, i+ Q
: {  O9 W) ?4 C  L2 M
void        APU::ExWrite( WORD addr, BYTE data )7 S  {- `- C6 k
{
9 j4 I7 B. `8 D: H' J        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );7 f) _3 ?$ C+ c
; \7 S9 G3 `$ b2 r
        if( exsound_select & 0x04 ) {
5 n/ e+ p7 T9 d                if( addr >= 0x4040 && addr < 0x4100 ) {. I4 N5 i/ w3 K  e$ e7 o% m/ |
                        fds.SyncWrite( addr, data );
3 X2 S" s! q6 P# q                }
, A% W+ m% @6 h        }
) @  v+ ]$ U5 N- \
1 ^/ c7 D. V$ M7 w6 X        if( exsound_select & 0x08 ) {4 W- d* M: I; c9 _9 B4 m9 [
                if( addr >= 0x5000 && addr <= 0x5015 ) {) Y! A! J3 @" Q% o2 r5 n
                        mmc5.SyncWrite( addr, data );
2 C2 T6 _( u! b                }
$ q' r2 c: X# I- j2 N3 f8 K        }
/ a; \+ z) U4 F: A. A/ H}
- A* R' c" h, s: Q% }
6 {- I& e$ O& Fvoid        APU::Sync()) D' ^3 o! S; {9 z3 o" m1 c
{. T; a$ m* a5 q4 e: V: ?# N
}& q* N% e9 V  ^- O6 {" r
$ W5 ]/ ^' ^- Q2 o2 p
void        APU::SyncDPCM( INT cycles )
( h  O/ m3 j; d1 B1 W/ \{% R" {1 A/ v5 K* n2 ?
        internal.Sync( cycles );
7 Y" I2 ]5 y9 i9 W, W! T+ v
! R0 k+ e+ ?, r        if( exsound_select & 0x04 ) {* z! m' O. r( g2 l9 I0 A& Q2 `1 l3 E
                fds.Sync( cycles );
5 X1 F( T$ K% p  h4 y+ O& b        }! w# |3 f8 Z+ C& ~0 p" Z$ i+ U6 ^1 l
        if( exsound_select & 0x08 ) {; M* Y  L4 G4 S7 x8 h8 i
                mmc5.Sync( cycles );
7 N. c1 j" v7 u        }
& L% o! Y) V6 X4 r}
" T# r3 z3 j8 S  Q  u
! j2 O: S! ~3 r9 k5 a5 Uvoid        APU::WriteProcess( WORD addr, BYTE data ): w  O% [7 V) P
{
  `% b/ E* o# j% P7 J& p3 a2 J: D0 k        // $4018偼VirtuaNES屌桳億乕僩
4 z* _2 Z( [! z5 X( V        if( addr >= 0x4000 && addr <= 0x401F ) {
$ e, r% L5 u7 H9 G4 H4 T* }6 R                internal.Write( addr, data );5 i8 U$ [/ ^5 {9 x1 ]6 j1 `) U0 b
        }
, S) ]4 f9 s" n9 |: M}
3 z$ ~0 G7 F5 R7 W  E
2 J& r5 X) m/ ]- X, q5 yvoid        APU::WriteExProcess( WORD addr, BYTE data )
+ _/ }6 z# _: F2 t, F0 I# z' q{& ?! R. w. m2 b3 [
        if( exsound_select & 0x01 ) {
7 D5 G* @; C: k8 v% h; E3 Z: ]' n                vrc6.Write( addr, data );
6 L, Y8 Y2 j4 @) y! X        }
' ^3 m5 }, O9 G- O' Q& u/ f5 D        if( exsound_select & 0x02 ) {
) h' }4 w' @, m                vrc7.Write( addr, data );
8 c8 a9 A: V' ]3 ^        }! ^+ d, ]4 @5 `5 i/ G
        if( exsound_select & 0x04 ) {; x( p* C, u7 j. b. @; C; u
                fds.Write( addr, data );
" Q; [: |2 P5 N: z* u        }- E/ z; z) V5 }& k- f7 m
        if( exsound_select & 0x08 ) {
  _5 |. Q. Y7 ~  Q9 N# |                mmc5.Write( addr, data );% E1 k, ~$ M. j
        }+ ]8 w$ `. f& o- i6 {0 \
        if( exsound_select & 0x10 ) {" \" `5 J" c5 n  z% B3 k. j. l# X
                if( addr == 0x0000 ) {, ?3 t% T* [( s( H. O* d' W4 X. }
                        BYTE        dummy = n106.Read( addr );
1 D2 g) g" ^- |0 g" W( P8 J                } else {
% \  Z7 n% r* d- d1 G                        n106.Write( addr, data );: M5 S8 S  d' r& q* P
                }
) k& T9 w9 c' k' @+ }        }- d9 [5 _5 i8 D
        if( exsound_select & 0x20 ) {
" e: W$ P% e" m: X2 c$ [; b# U                fme7.Write( addr, data );) E6 Z+ U$ G2 V  M
        }
. F4 K! H% [$ `5 N/ C0 Q% K: _}3 V- i  o3 ~, n/ v
/ p# D! }/ P$ D9 H9 |; U
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), @( A. q5 c% m4 C- Y+ p
{9 [! j2 C: [) b" M+ j* D9 }' S
INT        nBits = Config.sound.nBits;
* A3 q' O. r0 w( ADWORD        dwLength = dwSize / (nBits/8);* T. z3 D3 B. O/ r! @' X
INT        output;
7 E# q' n1 |7 X. ?1 ~8 A+ z5 SQUEUEDATA q;
  ~! f" z& \  h, q4 t# I3 v- s- H0 LDWORD        writetime;
7 L1 O1 Y$ @+ g3 L6 j  V5 X8 Y% t4 r9 t% B4 F7 l; {
LPSHORT        pSoundBuf = m_SoundBuffer;! v$ K! }" v- M& F/ o$ i3 R
INT        nCcount = 0;  e5 ^- Q  k- c1 G

/ k% Y0 A4 L1 q% jINT        nFilterType = Config.sound.nFilterType;
! ^* b# m! j& K- R( }  V3 F9 ]$ z* J2 m& N0 N
        if( !Config.sound.bEnable ) {2 c4 s' w7 a/ g( \0 v
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );3 ^3 ^& [$ y( n% j6 h
                return;
3 w% R/ |0 A/ Q9 N8 M        }
4 I) k& h7 b2 D, s$ Z1 `! ^+ o! o1 e& h
        // Volume setup
( Q2 q$ S% k7 {; o/ y        //  0:Master; x* ~5 }9 S" c4 g) D
        //  1:Rectangle 17 b8 B; x" |* _2 E* f9 a
        //  2:Rectangle 2
) N* T. ~7 B. o+ ?. V& c' Q) P9 q. E1 h: D        //  3:Triangle' q' f" X$ R: a9 n  B- \
        //  4:Noise
) {& c- v4 U: q; N& k        //  5:DPCM
  \. h" ^8 i, O; T) S" U% |        //  6:VRC6
+ i5 B( g* O& i7 `1 p        //  7:VRC7
. a. \1 U; O, W( z( t  E. j        //  8:FDS
+ J% G/ B- L" ?3 i1 n7 j        //  9:MMC5/ B5 o8 q  {0 G& X
        // 10:N106" N+ P7 @2 j/ Y$ k# g! R
        // 11:FME76 ~9 ?2 P) R" m& W3 l, M  f
        INT        vol[24];2 r$ F5 B4 E. @# Y. u0 Z6 {
        BOOL*        bMute = m_bMute;0 p2 g0 Z; \% g- }1 [
        SHORT*        nVolume = Config.sound.nVolume;8 x  D" N8 A7 s* @
! T  e7 a$ a2 }% @
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
0 i/ Z: d7 x8 q& L3 P4 |' _. o& y: X! h3 z" ]+ g3 a6 @( t7 s
        // Internal  B$ X& `9 z" [3 }. v# H& }$ S
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;  B9 x) Y% G* N5 }
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
4 U2 X' W: a/ i/ t: r+ s1 O8 g        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;3 _7 T: @( ]# G' l
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;% G/ j) `  [" `7 R
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' {* Y" v# k/ ?0 i; o* [& z3 E- w/ w! @2 z& i, C
        // VRC6
6 V  R+ M, o5 Z, C# B7 \7 _        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" [. H! O$ p/ J8 T8 c" H        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 A( @* e9 O, m- J5 F- j1 Z' ]        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 p$ l  i( ?2 h2 b, T$ \- D: q4 d$ M3 U# `2 |5 P1 |8 f  a
        // VRC7
! G9 q+ q9 c2 k7 }- {        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( p: z1 A) B7 o/ I( f: a
2 ^( M0 T" B# h: ~% ^8 m
        // FDS
7 z4 ~5 u& N' G3 C        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
9 n1 D3 `+ a$ b; J9 M; ?- S: V' [/ U) G: t9 |
        // MMC5
, {' H# b5 j* W5 I' j' C        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ C# O$ t; z! R- J) z8 W
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
- `0 D# y: w4 C4 x- F        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 M7 h: C7 t" W6 d0 w  h, l
7 n/ m: Z) n8 ]' {        // N106
- d( q: V+ Q- m( t$ J+ A  {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: b" L, \, }+ }  d( g        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 Z  ~0 }& S0 s7 u7 C        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* q2 u% U3 k9 N2 {
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 r: E" S; G8 f1 f9 E$ T' }        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ N8 U) E$ W5 J  S
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 H) e# o4 j: U* S7 H, m" K3 H
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; ?4 L( _. l1 {
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" v3 ^* b% V' r9 m! E9 V  i. s, }7 B( z# L
        // FME70 c9 y8 n% U" A
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 J7 m3 o* N. H6 Q
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 M1 F/ B5 z+ o4 Z, u7 g! n( ~
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
2 I+ M% V) j9 J( }) e. h6 Z8 ~. z3 `* @4 z2 k; v
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;! W- J* h: p- }+ N- A9 ~; k
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
+ ?3 s' U, g4 \' m2 O6 A: a
9 b- y5 _. V0 b- I* {& g        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
; \* Y, x5 h7 P% w8 i8 q        if( elapsed_time > nes->cpu->GetTotalCycles() ) {: B, B; C" u" L% D6 O0 t* F9 ^
                QueueFlush();
8 b, Z3 |6 q2 [- c/ [* s# r4 L3 D        }
3 n! n- W2 E) c; f
6 |- U# s8 B! }: k        while( dwLength-- ) {  Q2 M; d4 X( R! [' [
                writetime = (DWORD)elapsed_time;# @2 I7 V, {3 D& R! h
6 c  l( Z/ w- b( y6 Z9 n1 N# y1 \$ f
                while( GetQueue( writetime, q ) ) {
+ z$ t9 ?4 b3 x9 k! e# H* X5 A                        WriteProcess( q.addr, q.data );  V2 S2 r  j) [! b8 r; k! ^1 U
                }0 U. R6 V' ?' h) T
% r, H2 x" \  E+ U
                while( GetExQueue( writetime, q ) ) {
/ f+ a) f! w) P; Y0 w$ C9 A                        WriteExProcess( q.addr, q.data );: c* y$ F$ g  T) u# l) {- Q, p
                }
% A9 a, m0 W# U6 I$ J2 q! j; [- B: @- L1 q; g: |2 U7 i9 B
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME76 u9 [9 u1 r$ A/ i" L3 X' W
                output = 0;2 ]: m- C  R3 c. O/ \7 h  V& Y
                output += internal.Process( 0 )*vol[0];
. o) I. ?0 j# E                output += internal.Process( 1 )*vol[1];; p8 k+ [9 z5 L- S
                output += internal.Process( 2 )*vol[2];0 `5 i/ T+ M- R$ n3 A3 c# l+ l+ t
                output += internal.Process( 3 )*vol[3];8 Y) T0 h4 b  i- y* q
                output += internal.Process( 4 )*vol[4];
& d0 x% v* L2 Y% g9 @* e6 V% _7 q$ W( h4 }$ \# A: W
                if( exsound_select & 0x01 ) {' N. Y& F3 S7 c, c$ @* r
                        output += vrc6.Process( 0 )*vol[5];
7 ^0 v2 Z) K8 Z; ^                        output += vrc6.Process( 1 )*vol[6];$ ^7 I3 b4 ^( A, k3 `
                        output += vrc6.Process( 2 )*vol[7];
  d* W& b+ W! t/ r6 \: V* @                }7 R  b& B/ i8 g% N) w6 W
                if( exsound_select & 0x02 ) {
' N8 ]5 l; [5 t. z) O! u2 b# i. \                        output += vrc7.Process( 0 )*vol[8];
% D# C$ }7 d# k6 ?1 W( H4 u/ z, ^5 {                }" b( L! W6 p4 ^6 |3 r: S5 f; O8 Q
                if( exsound_select & 0x04 ) {0 [; D9 d" n4 B6 [! L. M
                        output += fds.Process( 0 )*vol[9];
7 I4 B1 D  W# W8 T+ a                }
% \  }' L  o+ t+ S0 l3 y                if( exsound_select & 0x08 ) {
- ~8 z% J4 B4 k9 b! V" v                        output += mmc5.Process( 0 )*vol[10];5 F6 }8 V# h9 U1 l9 k8 o
                        output += mmc5.Process( 1 )*vol[11];
/ e6 @" j: |. q0 o8 J                        output += mmc5.Process( 2 )*vol[12];
- Q$ c8 }# f, b' o- Q) \  l                }& M% E3 [" i. R5 m; E. k: P
                if( exsound_select & 0x10 ) {
3 C& _/ |* N6 }. Z0 ?7 D                        output += n106.Process( 0 )*vol[13];
( B  S- d: T1 M" ^5 _& U: J" y                        output += n106.Process( 1 )*vol[14];
- L# S5 F- Z4 n5 W( E7 c, {' j                        output += n106.Process( 2 )*vol[15];
: V6 u/ O3 w- x1 |4 ?                        output += n106.Process( 3 )*vol[16];
% Y: ?( R, T6 ]6 q* g. h9 J8 |3 \                        output += n106.Process( 4 )*vol[17];
  Z4 @/ n; A2 d* a: P                        output += n106.Process( 5 )*vol[18];% ^; g' g8 m2 p5 ]
                        output += n106.Process( 6 )*vol[19];
3 a- B' ^. Q/ c4 a& \8 f                        output += n106.Process( 7 )*vol[20];
( s& t- r8 N- |) j! X3 U, c                }
% u9 Y* H3 Z9 v- z' l0 c                if( exsound_select & 0x20 ) {
+ f. H. @7 S5 M2 S! G! L                        fme7.Process( 3 );        // Envelope & Noise
3 U7 w4 B$ B9 x- \1 y: e                        output += fme7.Process( 0 )*vol[21];7 ~* }: z. n/ v, q+ b6 d& W; Z. j
                        output += fme7.Process( 1 )*vol[22];
+ n4 U7 z0 j: a4 |1 D                        output += fme7.Process( 2 )*vol[23];- a  Y: K0 Y0 L0 ]7 j) w$ M
                }( ]# V( k/ O, q) S5 V0 `

) C: j! K6 c* E, p& W9 |                output >>= 8;) U4 f! j* D0 A
6 Y" }( v8 ^# p: d+ @
                if( nFilterType == 1 ) {% l7 D3 c1 y" r# h+ ]( v8 l; e
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) n7 X) _$ @/ k+ @
                        output = (lowpass_filter[0]+output)/2;
0 Q& U; G+ W( r7 f1 N                        lowpass_filter[0] = output;
' Z5 g! C9 m$ V" q                } else if( nFilterType == 2 ) {' V* R# d# b4 Z- e! B! C
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
. Z0 \2 q+ T; _  h                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
4 ~  X4 A* o: R/ t3 v                        lowpass_filter[1] = lowpass_filter[0];% c& ]% e" T+ j! W
                        lowpass_filter[0] = output;
& `0 e3 G, J' N1 l                } else if( nFilterType == 3 ) {
, t& Q- n  V! k                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)2 |" l8 H3 i# I- i* j+ y/ Q
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
0 B9 V, N& n* p# C2 M- E3 L                        lowpass_filter[2] = lowpass_filter[1];
; U' r+ n- l! v' q                        lowpass_filter[1] = lowpass_filter[0];7 X% l, B$ n" C1 G
                        lowpass_filter[0] = output;
" j% s2 F" o. h1 ~. ?! {8 a; h                } else if( nFilterType == 4 ) {3 E/ ^" `: K0 z' T# B' b
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)) S5 |. \+ |: G& b1 L
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
. A' s1 C* l# f0 G                        lowpass_filter[1] = lowpass_filter[0];
8 C2 j1 E% n' i* j* U( K. Y; |                        lowpass_filter[0] = output;
. R( Z! B: E/ |4 r9 m0 {5 ]                }
3 }1 ^: s2 M% n( s6 {+ v3 S2 _
7 P+ x0 M1 U2 |+ q#if        0) p+ M2 F  s4 h) F0 g7 q1 S
                // DC惉暘偺僇僢僩
4 `% c& S3 I, P" h& N2 u                {9 i4 l) h. |. [% Q8 y
                static double ave = 0.0, max=0.0, min=0.0;
/ Q* O$ Q; z. c                double delta;
3 X6 K8 u" p& `- K                delta = (max-min)/32768.0;) M, y' I! c( c2 I. K! t
                max -= delta;
  f+ h) p% Q- B% F1 g4 m8 d/ q& A                min += delta;
0 }$ R0 ?5 O* v& A* Q4 [; w8 j: Y                if( output > max ) max = output;
) Y' Q+ z4 E9 c8 _" m" S, W                if( output < min ) min = output;
/ _1 z7 z1 q0 ~/ x$ ]# i6 t2 a                ave -= ave/1024.0;: r) n; G9 k3 L& r# ?6 t
                ave += (max+min)/2048.0;
7 N% J  A' H& v0 |2 r7 x$ g) z                output -= (INT)ave;
( W* v# s' O7 H* _                }
! k! d; L. T0 L; r& t- F#endif
$ a1 O" C9 _1 Y5 C* `7 X' s5 E! m% O#if        1+ R7 [  J; ^  o6 |; K& `1 J) s
                // DC惉暘偺僇僢僩(HPF TEST)
/ p8 M9 t9 o# y) _: {3 n; p                {4 o2 _) u$ k: J1 y: \8 @
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);9 P: h$ n: D* `/ p
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
3 b4 _! s. \8 Z# g                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 j# K+ L* [1 M0 |. w  l/ i7 Y
                static        double        tmp = 0.0;
' n( l9 J9 n$ |: ^, d$ I& W! L                double        in, out;! U: @+ A9 O% b, r7 C7 q' T
1 o" q1 k0 u- Y4 I1 w' r) O0 I
                in = (double)output;
' O/ r' D: O0 {- e                out = (in - tmp);
: \4 U& \' y7 q$ H+ d  r0 L$ O                tmp = tmp + cutoff * out;
, O% H/ v4 H! @6 u6 L8 k- m4 H% C( D2 Q: _2 b' W) d. z2 D# y
                output = (INT)out;
% M4 h- ?* A* a' x  ~3 w( {                }
7 ?0 J6 l+ P5 C' @2 x#endif; b$ l5 Z* l# h+ }5 y
#if        0* @, X& B# _( ~7 R, l
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ h2 w0 w, ^6 V9 ^                {
5 ~0 C  W4 [* O4 S* f                INT        diff = abs(output-last_data);4 Q2 I! D0 A, }4 ~1 V: Z( \
                if( diff > 0x4000 ) {9 R! \. o3 D7 o* |1 P% _* t+ l/ \
                        output /= 4;
2 F$ i$ e( i- k1 W; `0 v, A                } else
9 z' c) `/ F2 ~3 a                if( diff > 0x3000 ) {1 B6 _2 d# ]; Z
                        output /= 3;1 i, [  g7 G; X, a1 J" N4 c( I
                } else
+ n4 t  t  l9 L$ w% B# b& A                if( diff > 0x2000 ) {
; q% ?5 s  I. W1 l( ]  `                        output /= 2;$ l3 I8 J0 R! h, D5 a  w! q
                }
, Z* S0 S# W" T# G2 }  h' \                last_data = output;
) k. B+ C4 H3 f6 T                }6 X- l9 @  l4 l
#endif5 s8 `( ~( x$ ~. z# W
                // Limit
" k* c0 @+ r  v8 [5 Y" `                if( output > 0x7FFF ) {3 W' k! E+ `. E1 v: m
                        output = 0x7FFF;
% d/ h  r4 w/ o; A                } else if( output < -0x8000 ) {
3 n& u0 W& y) i, B# O) a- N. R                        output = -0x8000;  @2 F4 f/ G3 a6 o5 ~7 ^
                }9 d* v- s; V8 Q) \( N0 i' k

4 X" O; |0 D! G. j9 b                if( nBits != 8 ) {7 y# j4 n- ~' C% t$ n, @: e6 Z
                        *(SHORT*)lpBuffer = (SHORT)output;/ ^) c4 _2 S, }+ Q
                        lpBuffer += sizeof(SHORT);
! w/ V( p* m2 F4 J0 e  a                } else {
3 q0 ?: }% f9 {. D* n6 ^7 R1 W+ \7 f                        *lpBuffer++ = (output>>8)^0x80;( S; P: \4 K1 a* a2 s( }/ n4 F
                }
- c$ m0 i5 d6 U* p3 z
$ y4 H& |* B! j0 ~' m& M                if( nCcount < 0x0100 ): A5 w8 L% u+ e0 f& L
                        pSoundBuf[nCcount++] = (SHORT)output;, S4 J; A5 S& Q' j* y  q  g2 y5 \

! f6 n4 }/ l0 S  M//                elapsedtime += cycle_rate;0 a$ s( Y/ n* a
                elapsed_time += cycle_rate;
1 J. B/ B3 _: F        }
# |% r- F4 f' P5 Q3 e7 f3 z! |3 f  C: G+ c; N  z9 K: {" t
#if        1; c, g0 R& c  s  S; A7 e( z
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
' j2 |6 L2 W) u/ }5 c5 V/ U. l                elapsed_time = nes->cpu->GetTotalCycles();
4 a* _+ J% t8 ^; B' ^' L        }5 H7 X, ?0 ~" k# v# b
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {  v8 ~& Y# p: H8 L/ [, W
                elapsed_time = nes->cpu->GetTotalCycles();
3 A+ I% ]& W7 L+ I% w  G# Y        }! a0 \9 I( Y5 a+ y* F: H/ m3 q2 ?8 X  ]7 O
#else; L8 s5 b- N7 Z" X6 u& e8 k+ z
        elapsed_time = nes->cpu->GetTotalCycles();
* {8 V7 v3 H2 L: F#endif
+ j# P! m. @/ p1 ?* V$ q9 p}; v. v# u- R6 U/ A7 o* n# `- _
" K4 W2 m+ y" y
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
. _2 N" q' [! t- c: p, Q; sINT        APU::GetChannelFrequency( INT no )  z3 Z/ ~( w. X8 r
{
- Q6 x: A. U6 ?4 y! p        if( !m_bMute[0] ): N' }! U3 j3 C! z$ [
                return        0;# C) a  A5 e; W' l5 Q

! d9 E  P$ D# }1 e2 B        // Internal3 L, j; |  _) K1 C  ?# c. G
        if( no < 5 ) {% n9 U) C( ^5 X: M8 g
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
8 S* T! Q3 b' A5 E6 G6 e4 _        }
5 |. B# g3 t, n: p        // VRC6. C6 w3 {# P% j
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
+ O  s/ C9 Y" Q                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;. _0 P8 R# q6 g1 ^* J$ P
        }4 D& l9 _* Y8 G0 }5 z9 D6 i
        // FDS0 y9 o8 D, I6 J/ R+ U9 `2 f
        if( (exsound_select & 0x04) && no == 0x300 ) {, g( T8 M2 I. @+ l. \3 I6 l
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; A# a0 ^0 |9 }0 U        }
8 r9 l) a1 `  c        // MMC5
: z% H$ ]+ h( g7 C3 l. ?, B        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {2 s3 p- w  ]' ~3 L
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ i& J( D5 a2 ~" `: s/ n- B5 }
        }
" Q7 W$ J# B5 Q        // N106
  O6 l8 y' {: S; L; V+ K3 l        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' [8 z3 }% W0 _, {, h' O                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
+ {8 X$ D* R! w# W" l        }1 B& {; c; ]6 x6 k! H: J
        // FME71 _: [" c: l$ e
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {4 `. b. i5 X* V( C) z' f2 ]
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;" \5 e4 N, T! w  V& M6 E: m
        }
1 v, c5 g9 w+ p+ @2 Y  e  {9 {3 K        // VRC7" B7 ~* E; F. G1 D9 g$ C
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# J5 i5 m5 q* m4 L                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
* q' T% W8 T8 p5 D        }
6 e& l8 P7 f( \4 z& Z        return        0;/ q* q/ G4 t+ E$ Y
}4 y8 \4 J% o# R# L
" C) A+ u1 t& ?* s
// State Save/Load0 v5 C/ G- T8 z" V( y- a6 W+ ~* G
void        APU::SaveState( LPBYTE p )$ C+ N0 G# n" X% P: ?
{
& Y: X) s; L, F, B! u9 f; t. P6 j#ifdef        _DEBUG* M8 Y8 ^' c5 }8 W* t6 z! I, M
LPBYTE        pold = p;
+ c% W% Q, _4 N% x0 d5 ^' z#endif
$ i6 e4 q5 b9 z" B2 [
6 F5 w4 L3 {1 @# o" L. D9 n        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% d. {# |; c$ n2 ?' K* ^        QueueFlush();9 E1 {4 ]& a  F: I: E
1 r1 @& P% R8 A3 T1 P
        internal.SaveState( p );
. E$ H2 ?# w  ^6 ?8 R        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; B; D: B( F6 ~! s( _% [* o5 Z3 A

1 h; n* N' {+ R2 c# x' t        // VRC6
3 N4 p, W3 J) S/ c0 O* l6 s        if( exsound_select & 0x01 ) {
! s5 ?& P% K3 [4 N$ `* O                vrc6.SaveState( p );/ P/ C2 `" w9 u5 M9 r$ F% W& s1 }6 a
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: G! }4 ?6 s; u2 ?
        }/ B# F% \7 y  V% }  q: z
        // VRC7 (not support)5 W* M- D: s) S( S* \
        if( exsound_select & 0x02 ) {$ z- A  r- c1 ]# j2 j1 l( @
                vrc7.SaveState( p );: E0 R$ J* Q- P" V' d$ r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: a- d- q( B; u- i: }, P" V        }
) F; b! G5 O4 e$ q        // FDS
- e- \% ~; D0 ?        if( exsound_select & 0x04 ) {+ s$ [+ R- e$ L4 m5 d1 E9 w
                fds.SaveState( p );
5 ~  H6 G6 g+ y( K# ?7 u                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
& `( u- l+ r. W3 B        }9 Q0 \& R1 [6 [' _
        // MMC5- C6 V1 d4 y1 h( k; R" d6 v
        if( exsound_select & 0x08 ) {4 e7 N& e+ b. n% H1 L, C, V2 L! R) ~
                mmc5.SaveState( p );  O( G2 P: r: N# _# K, H! x
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* i+ i. d1 Q$ ?: I5 m; j4 z
        }
* i# L' q9 d# L4 J) Q( Y# i        // N1065 L- L: C$ V- r+ L5 }8 j# [
        if( exsound_select & 0x10 ) {4 V+ }& \. P* D, m) z
                n106.SaveState( p );; z' ]0 Q' q' c! d% U
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding9 v7 y" H0 N1 r2 l; `8 a
        }9 a1 T+ E4 a0 w& L0 N; q
        // FME7
1 l$ a* a  }7 a8 j; X        if( exsound_select & 0x20 ) {6 n3 y5 Z! \8 k+ T
                fme7.SaveState( p );
$ f2 c6 Q6 P0 _4 |) {6 ]' a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! y$ |$ V7 J# {4 m* B( r
        }8 P( x2 i4 t; g# V+ ~3 j: z

3 @( d+ I+ R1 k$ }7 D! E. {* w#ifdef        _DEBUG
0 w$ Y" z1 \0 M3 \DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% s. c7 R. k9 `8 s#endif
$ ?0 s# e; M8 v: d' u}" E0 n4 ^* F( a: V# q% L( k/ x) @$ ?

, e. c( b4 P7 W$ Vvoid        APU::LoadState( LPBYTE p )1 p7 ~# H- q1 g, i, R* E/ |2 |. c8 ^) f
{
2 C+ L& v8 b* ?; i        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
1 g: w+ V+ \5 [        QueueClear();
+ p8 g! S. F8 v- C" b1 @" x3 I0 P2 l2 j0 i9 r. @* Q
        internal.LoadState( p );
) t+ t! H. x7 D+ @        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! K. o+ v9 y% C6 a
' D" h" g, s3 i5 c0 {, ?5 A
        // VRC6' ~! \* L4 y+ T$ b7 o4 F
        if( exsound_select & 0x01 ) {
. E+ X6 k+ k8 }9 m/ K/ W7 t6 z& @                vrc6.LoadState( p );
5 y, v9 ?+ y) X. x* [" m. `                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 N$ j5 G; }* Q9 v3 P7 k3 y
        }
8 [4 T9 h* ]  [: D% N) \2 j        // VRC7 (not support)
) l3 Y8 I+ J& E& Z4 b8 Q        if( exsound_select & 0x02 ) {  D; {6 R# h6 B
                vrc7.LoadState( p );
4 a# _/ w  X* a8 s                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 [' Q6 k8 u  j- K8 j& L( g        }2 L6 ^6 f% e  B  a) V% J  l
        // FDS
: \$ T5 N  ^$ @; K  b7 l        if( exsound_select & 0x04 ) {
& U8 \/ y' q8 s- j: c) b; L3 K                fds.LoadState( p );
! c, y: R( |5 X/ t3 D, O                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" x, t: k8 E; V, _; g! V& w( o
        }
7 W" d# f# C. K        // MMC5+ |7 ], r; e4 Y
        if( exsound_select & 0x08 ) {
: a$ w4 S1 u. S. m7 U; O                mmc5.LoadState( p );$ T; Q( n' t- D4 [: U( J+ }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 ~+ W; P6 S  e/ A- `        }
6 R3 W0 n( A, ~3 }" T2 c        // N106# M- ]& x  Y' j' Z6 [
        if( exsound_select & 0x10 ) {
! S$ z/ U, m/ d- I! a6 `                n106.LoadState( p );
( _# Z, }9 P$ M9 x5 B$ y* A                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 G7 \  q# T4 x; k5 e3 X) r3 j
        }1 U0 G$ m+ @. a9 M1 ^
        // FME7+ J! ^+ D. B/ k+ Z7 W' M$ d9 E+ P' ]. J
        if( exsound_select & 0x20 ) {- r  b9 y9 s; w# `# M  e
                fme7.LoadState( p );8 P0 v! G2 [+ u4 e9 O1 q: e/ y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
  L4 {! B$ ^2 s4 C        }
* I' e" f* q9 Y( V3 d}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 . K% M  Z$ D) J  V
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
5 w0 H( ~- [3 m$ ?/ I8 e- n; q- Z感激不尽~~
; L# [5 W1 n8 `5 r6 W
恩 我對模擬器不是很有研究,  p% `  R$ U" O6 U' ^$ s9 r' l0 ^
雖然要了解源碼內容,可能不是很困難,
, R8 ^  D, G0 ]# D$ v9 B7 c不過還是要花時間,個人目前蠻忙碌的。1 o$ u" I. z0 a6 `
. q6 l2 j, Z9 C, R; u, g
給你一個朋友的MSN,你可以跟他討論看看,
2 S& U( o: \0 b他本身是程式設計師,也對FC模擬器很有興趣。+ {* `4 F/ [* e* b* \3 [  p1 O- N
- f; d7 @7 g* ~/ r) Y3 B3 C
MSN我就PM到你的信箱了。" I6 c5 V4 W7 c6 K, t% a; N+ L

$ g( {3 j, R: j希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 2 U( n6 w, k! W( b
呵…… 谢过团长大人~~

+ w/ Q. A7 r0 z6 {- z: z6 T+ X. }) J0 V% H
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
5 x+ G' }! [8 I# x" i# B团长的朋友都是神,那团长就是神的boss。
  L* a  G$ p; P. n+ g9 l' c
哈 不敢當,我只是個平凡人," e2 [; M8 q2 e3 B2 Y/ O# |% X9 o
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙' c9 M6 E( Q4 N' Q3 T( c3 n
ZYH4 x7 s2 R  k- U8 I' }/ a/ C
QQ:414734306
  Q7 _. n8 v. }' n3 n1 f( x4 ?: IMail:zyh-01@126.com5 b" X0 O' b) V7 F7 Y' ^7 d4 B+ p

' x& m/ e: I( z. a" F" R$ z, s% ?7 r他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
4 n7 X5 D% b" R: W/ _% Y2 k* o, s再次对团长大人和悠悠哥的无私帮助表示感谢~~

8 o# T/ ]) W: y* J" q" v不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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