EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 v* Y8 Q3 \4 o' o% y# {2 w* h楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ v: Y+ z; k5 v$ K, z这里有相应的模拟器源码,就当送给大侠了~~
% E6 W% g! n9 t0 h, f) F- Z! _http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 1 t/ Z  v& A& _  C
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; ^7 t" ^1 R0 [; r1 _楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 P* i& }+ A# m) c- @$ V这里有相应的模拟器源码,就当送给大侠 ...

% `1 W, y" U. W9 p7 D8 V; {聲音部分(Audoi Process Unit = APU):
; \7 b; H: N8 D/ V/ T.\NES\APU.cpp9 y' D% F  P* c8 A+ t
.\NES\APU.h
0 `% P; W3 X/ O$ F/ x2 ?  G! Z5 x8 N( C  t* ?

7 l) E! F0 ?5 F6 `  ]+ N影像處理部份(Picture Processing Unit = PPU):2 a' V1 g& D+ H, W
.\NES\PPU.cpp9 q; H5 j; p2 s6 h% I$ k8 j
.\NES\PPU.h
; r+ d/ G+ x' N8 z4 K
; E& @5 S7 `, B5 x" P: G如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& A* D2 Q# i& S$ X8 l2 o2 t2 o
(由于很多专用术语和算法机理都不明白,所以看不大懂……)' @3 P/ ^. r: E8 j% Z" G& M" Z
//////////////////////////////////////////////////////////////////////////! n- S& C1 n, ^: m
//                                                                      //
' g% Q% a! }) P9 X//      NES APU core                                                    //
5 t8 T% Y8 D) L: N//                                                           Norix      //+ m5 X( ~$ d. ~- d$ ~* W
//                                               written     2002/06/27 //
/ \: m+ u. ]+ K, B9 f: V6 M//                                               last modify ----/--/-- //
6 V* l& b4 y' Z" D! V) v$ I( K) b: n3 O9 c//////////////////////////////////////////////////////////////////////////
. ~- o3 I/ s5 i6 v' C/ Y% q$ g#include "DebugOut.h"
( D8 U% U$ U$ Z- M) K* L#include "App.h"5 r5 i  n( M: l9 U* Z
#include "Config.h"; P8 o; h% ^! Q; o& C! E, o8 M1 ?* T

6 W/ `  u4 }6 a: p$ `" G#include "nes.h"- O3 _$ B2 q2 a" p
#include "mmu.h"
$ Z# D. x2 w& L# d3 B4 B, n#include "cpu.h"  ~, u# I9 ^. `/ r. z; Z7 y
#include "ppu.h", A# X6 U- I4 M
#include "rom.h"
7 w# t7 w1 k$ |  p3 }8 |#include "apu.h"
; b3 _* D, ]* q
6 j5 J# Z, k2 X3 Y// Volume adjust1 \  n1 l; d5 C5 \. y
// Internal sounds
' ~- X! w2 ?, R( `0 n, M/ F. T2 }#define        RECTANGLE_VOL        (0x0F0)
6 Z: G0 ~4 b+ S  k; J#define        TRIANGLE_VOL        (0x130)$ z; X+ |9 N! U- t+ a* G7 r
#define        NOISE_VOL        (0x0C0)* W) j: X, C8 `! B% C3 y" _
#define        DPCM_VOL        (0x0F0)7 L) @5 S- T6 ^% p" ^' k
// Extra sounds% C! B( K, P: p
#define        VRC6_VOL        (0x0F0)9 Q2 k" Z# o. m, O
#define        VRC7_VOL        (0x130)
8 c/ S$ W4 c5 }2 M#define        FDS_VOL                (0x0F0)% E% D9 i1 i3 z* z1 Z1 _
#define        MMC5_VOL        (0x0F0)
( N$ W& p  D1 t#define        N106_VOL        (0x088)5 h/ ^& v/ b  I8 A6 D
#define        FME7_VOL        (0x130)
( q+ i  h4 X- d" J9 I- @- }6 S- w( f3 G5 q; X
APU::APU( NES* parent )
9 s9 N% Q. M6 _. a# n4 @{
" {- K/ r) T! G7 p        exsound_select = 0;
& [% s$ X- N; P) x- ?' ?& Y" y* t6 y4 i( e: o$ U1 e' n* z1 E/ H
        nes = parent;5 a! H7 W) F/ x/ p! Z1 a0 l1 k; d
        internal.SetParent( parent );4 h/ C* u# ?8 z5 _( }; X
) I3 j' {- h* d% j0 W8 q( |; c
        last_data = last_diff = 0;2 R( F: q# c! F! S% b
' G* M! u5 H) c: X8 D, x, |
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
5 a+ D# ~% z1 W8 Q: V& J& J; z1 s8 }0 r; Y
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );; M3 h. p1 r) E0 ^( v
        ZEROMEMORY( &queue, sizeof(queue) );0 z# g* u( {! m0 p' z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  ~7 H- g$ S# W% T
: o8 _7 w- g1 ]7 Z+ Z! l/ U* @* D7 W
        for( INT i = 0; i < 16; i++ ) {) G0 v9 ^! e4 |7 \- q4 X
                m_bMute = TRUE;
1 q- v1 \  h. A9 o' M8 A. x        }
, }1 i4 d! o9 @}4 \% P3 j0 _! M

5 P8 Y9 H' B. ~1 p/ j8 VAPU::~APU()
- z6 u  K! X5 V{, w/ g9 Y7 G8 H1 ~& V' T
}- f9 x. c0 \0 t+ c* f' O; |& g
( q' r" v8 i1 P0 w, I
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# m" Q9 \; ]' B  E( t0 t9 W{) s5 y' `) [. d
        queue.data[queue.wrptr].time = writetime;
- J# T# H" X0 W4 ?1 ~) ?- y        queue.data[queue.wrptr].addr = addr;; ~: V3 j( l& g& l: ^" B. X
        queue.data[queue.wrptr].data = data;
  ~  w1 ?5 s6 m' H7 j; d+ ^" ^        queue.wrptr++;
6 V5 g# Q7 B5 D6 G" ?8 H  |5 H        queue.wrptr&=QUEUE_LENGTH-1;
3 a: u7 ]6 x: K8 y        if( queue.wrptr == queue.rdptr ) {0 l+ {: ~7 V4 U+ t: |( p% w8 y
                DEBUGOUT( "queue overflow.\n" );* A1 O8 H8 }% [
        }
8 ?' K" Q9 G! q. D" L7 s}
7 {! o- h8 G7 {2 f3 L0 k* h- t
9 O9 N9 r# |% T+ V# ~# t# x8 vBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- {% V0 C8 ]1 p2 v1 N0 \4 N- @{; H+ m1 r: z5 `) l  U6 `
        if( queue.wrptr == queue.rdptr ) {
: B7 W: v; D) ]5 `8 I8 g                return        FALSE;
1 ?) [( N/ I; \' k        }
6 r$ W% N3 i' e2 T( h' K        if( queue.data[queue.rdptr].time <= writetime ) {
2 l5 U9 R0 G/ l4 P                ret = queue.data[queue.rdptr];( t& K, w5 o" s( |) e3 ^( P
                queue.rdptr++;
9 i( v0 T. m! W  C6 M4 @                queue.rdptr&=QUEUE_LENGTH-1;9 D' Z$ }& _$ B0 i' g
                return        TRUE;) B$ M* ]0 d$ g. Y* U( m% R5 C2 c
        }
" h+ ^7 C) l: c% i% A( U* o6 M* U9 O        return        FALSE;
1 e" Y6 H% a( m' m6 m5 d/ m}
( C3 }) V- k0 \  Y& Q
; t: |0 f  f1 t& X% S, p' pvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); s4 s) V; Y( m& V# \+ y4 A1 {
{
1 O2 h5 h# z2 O& v9 m+ }: g1 D. G' _1 P- V        exqueue.data[exqueue.wrptr].time = writetime;
: V% s* {: i2 x- Y0 q1 w4 ]1 |        exqueue.data[exqueue.wrptr].addr = addr;$ x6 T" [1 k3 o/ U& H/ k
        exqueue.data[exqueue.wrptr].data = data;
6 E8 I$ U! F' S2 `, B( t        exqueue.wrptr++;8 v! `1 D4 Q7 g5 w1 e( y
        exqueue.wrptr&=QUEUE_LENGTH-1;
6 e0 C. Q% D: ~4 X2 y        if( exqueue.wrptr == exqueue.rdptr ) {
% @9 f& U5 W; v/ ~                DEBUGOUT( "exqueue overflow.\n" );5 v& M0 c2 ^# b$ a0 F
        }2 e% T  y5 D2 n3 a/ K6 U
}
+ ^+ I! i% S" b* G% N1 n# @2 ~
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret ), t0 `. |. Y6 s0 \) R( h4 a" d
{
% U; Q2 r  V5 j        if( exqueue.wrptr == exqueue.rdptr ) {: q- ~' x6 f* N; t
                return        FALSE;
' ~( I* z' F7 x        }- X/ A; q/ u3 v$ d, p
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
% i2 m- M$ H, e2 {                ret = exqueue.data[exqueue.rdptr];
" b0 H/ p  t, q                exqueue.rdptr++;% A: H+ h1 S. ^+ a
                exqueue.rdptr&=QUEUE_LENGTH-1;
8 F4 K/ z; p, E( r( f& {7 P4 j                return        TRUE;1 K9 w2 W4 q  h% V5 V# d
        }$ n8 @8 F. k0 y* f/ D
        return        FALSE;2 Z! k1 S: Q% ?# y* w2 q
}
2 X9 `# ~: h: J/ K, ~1 }
$ @9 u) v& O6 D/ E6 A( D& Avoid        APU::QueueClear()+ ~' M! A  z6 U6 j
{
3 s, Z0 q) Z8 t) o0 I* ]        ZEROMEMORY( &queue, sizeof(queue) );- }% g- l0 J2 e
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# \; F. O0 G- ^7 E( C; z% R}
3 r' v4 {! F0 b/ i3 S% Z8 b0 d3 P; N6 W. ~% }6 y* ~
void        APU::QueueFlush()
' g4 o: E3 Q( A+ T) r{
$ d5 g# T9 ?0 h- h$ n        while( queue.wrptr != queue.rdptr ) {! m- {* r! ?7 i! ~
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 Y) r$ |0 F! G: v9 {; M                queue.rdptr++;! K1 s( V# s6 T( u: F
                queue.rdptr&=QUEUE_LENGTH-1;5 b: ]/ w' G: k. ?7 n9 o
        }* K7 V4 {8 p2 O& v

8 }4 c  g# g# |& y! @        while( exqueue.wrptr != exqueue.rdptr ) {( A4 m* B% [9 i2 @  I# Z
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
0 o  Q5 s: A1 N6 @' f                exqueue.rdptr++;$ _. m% a4 |. p! e
                exqueue.rdptr&=QUEUE_LENGTH-1;2 D3 N6 Z4 j* j0 d8 m) ^+ G
        }' f8 q, {" R, O4 ^3 ^+ T
}2 g+ j# s! X: {- X9 Q4 Z3 B
( m& T$ d* M$ F* l5 Q8 l
void        APU::SoundSetup()
7 a3 t& ~& \+ w! v{
# e$ I8 U. ~5 x1 E1 k5 u# n        FLOAT        fClock = nes->nescfg->CpuClock;9 K5 G1 @- H$ f6 \: J6 T1 ^
        INT        nRate = (INT)Config.sound.nRate;
3 K0 C6 k. w" S; e/ L        internal.Setup( fClock, nRate );
) W$ b$ F" ]3 P$ X  t1 Q9 {        vrc6.Setup( fClock, nRate );) M! z9 m5 [! ~# E
        vrc7.Setup( fClock, nRate );* P6 W0 d% O- \. b" O! x; X$ c
        mmc5.Setup( fClock, nRate );4 Z; |2 ~/ X/ `* k. o
        fds.Setup ( fClock, nRate );$ D& N  C, L. G3 W
        n106.Setup( fClock, nRate );/ K& u7 t8 g: f7 l# L
        fme7.Setup( fClock, nRate );/ w4 R: V8 H' V. n2 m
}7 k. n- k* T" i% S

' U& E9 G* h4 z' evoid        APU::Reset()2 O+ f2 F# J1 K+ W* o$ e# m
{) i, L5 n" s" b* H5 d
        ZEROMEMORY( &queue, sizeof(queue) );
& w1 l; m$ ]* p1 j2 N& b        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ B& V* e) |% g6 C' ^+ m

3 a* M7 v9 ~4 ~1 q; p! \6 k        elapsed_time = 0;
5 D: `. }7 w) z  K0 M0 U, S2 y  N" l$ B
        FLOAT        fClock = nes->nescfg->CpuClock;" R7 L+ c$ H5 n# |9 A
        INT        nRate = (INT)Config.sound.nRate;
; K  w8 w/ p# U9 ?( M( O        internal.Reset( fClock, nRate );
/ T/ I. ]+ W  I, O        vrc6.Reset( fClock, nRate );
6 N. n! p4 W! O0 n% N+ p/ i9 o! v        vrc7.Reset( fClock, nRate );! w% z: F2 F0 ]5 i# ?8 I
        mmc5.Reset( fClock, nRate );# E; P: y* \/ a, E
        fds.Reset ( fClock, nRate );# T/ L" ]& f. v3 m( G$ r# L
        n106.Reset( fClock, nRate );
- S3 d6 h7 S- s6 p: r' l, G5 D        fme7.Reset( fClock, nRate );! r2 _' T5 o7 G8 ^) B0 ^& O
- P2 r6 V; m! }2 ?
        SoundSetup();% D5 t2 Y2 z2 c/ S3 t1 ?. q
}4 l0 b# F! b! z

7 S5 K; ?0 K7 ]3 d8 U# evoid        APU::SelectExSound( BYTE data )
* V2 h9 v+ J# f# e% _# |{
: y% L# }* D- i' f7 Q        exsound_select = data;1 N4 L+ f7 O  Z. n0 h, o6 D
}
, {" A$ J! \- W
# M: l% P$ C7 ~BYTE        APU::Read( WORD addr )+ M" c/ r1 t! [
{: f* p5 q5 u: P6 S4 J& |" Y
        return        internal.SyncRead( addr );
% Y, _' u1 J7 a; b/ t- v8 `}
; I. T1 U8 w7 \  g" ]1 b- @1 J. v8 h8 W, C) q! i, ^, Z4 j
void        APU::Write( WORD addr, BYTE data )
# d# p" i' Z% _- Y3 K  \$ W{0 O: O7 j" T2 T
        // $4018偼VirtuaNES屌桳億乕僩
# g0 o, ?: t; x7 C        if( addr >= 0x4000 && addr <= 0x401F ) {
. S+ a' h7 E, c5 n- m  a  U                internal.SyncWrite( addr, data );6 `  p) _: t/ U; P
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ o" e- H) J8 }, C% P& ?0 ^$ O! F0 ^! y        }: g' O9 K; N5 M0 }* d0 A; f
}
0 D) ?5 ?! P  t( x$ L5 Y8 W2 ~
/ k$ x$ E! |  g8 h9 w+ |8 @BYTE        APU::ExRead( WORD addr )
  B3 C, k& ?) X/ X{
7 f7 ]! }7 I; {9 a4 iBYTE        data = 0;3 }( |( w$ C% D

2 w4 J2 e- z% ~- O        if( exsound_select & 0x10 ) {( _4 f: }% [) \: a$ B6 _# _
                if( addr == 0x4800 ) {
6 [5 S7 s7 V& O* k3 _                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, b  u( [9 C( @: t
                }* l4 N9 ^1 L: R& p- S- h
        }& ~0 M% l! r  N4 H4 k
        if( exsound_select & 0x04 ) {( I* b* A* P' \7 A, d' T$ m: J  N$ |
                if( addr >= 0x4040 && addr < 0x4100 ) {
; f: ?5 c/ j2 Q' O8 @/ H! ?                        data = fds.SyncRead( addr );
* _' N& ?' a6 l* Y0 t3 }                }
8 i; g$ T! I, R7 O1 b        }
8 u2 I; c% C* h' w- y; M        if( exsound_select & 0x08 ) {; [" G0 ]9 c& Y+ ]) x! o& B% U
                if( addr >= 0x5000 && addr <= 0x5015 ) {# t4 L: z6 w5 a$ h* E! q
                        data = mmc5.SyncRead( addr );
2 \/ {$ u7 B/ r2 R& m2 N% ~# w                }
( r& B! X& m1 D% O3 j% J! k+ R        }9 Y9 z& [. L; _3 p1 z
, |' N5 O; z+ d2 w
        return        data;/ v$ }: ?& o3 X+ @5 V' \
}
* v0 M1 }/ y, M. Z' y2 z% l. G- F7 C' I) ^7 ?6 l* W6 F4 M, r, r# s
void        APU::ExWrite( WORD addr, BYTE data )
- t1 B) m. k/ s2 @{
6 S- J  W) h; m6 ^& l, Y        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
$ A8 |& Z3 K3 O, a6 Y, V4 U! q( s+ T% W: e
        if( exsound_select & 0x04 ) {
5 }. c- g4 v2 w                if( addr >= 0x4040 && addr < 0x4100 ) {
, E0 d( s7 v6 U& g  f# s0 s/ f                        fds.SyncWrite( addr, data );
$ K" X0 V9 z8 [8 ~. q                }: y1 {9 \1 }, ]/ z
        }8 Z* u" e- F4 e

/ t; ?$ s" X4 E, Q8 |        if( exsound_select & 0x08 ) {" z8 E& ^% x, y. d% ?$ r
                if( addr >= 0x5000 && addr <= 0x5015 ) {. a$ o3 ]& F7 x: `) l. Z1 N, N, t; o
                        mmc5.SyncWrite( addr, data );
5 g0 Y& O4 e) w7 ?' h# K                }! q3 X# w2 |0 d1 o
        }
1 [2 h5 p% V7 |) L}
0 Q1 B/ d  ]+ l1 ~6 l
* C3 ^3 _2 t9 N3 d! j; pvoid        APU::Sync()4 F) h5 [4 L  n8 x4 o, M2 I) }/ \
{
9 C: o3 h% r- z- a6 u}# y6 l. _' U6 a! S

' ^0 W& Q& f8 X% m2 g# ]+ cvoid        APU::SyncDPCM( INT cycles )
( y" f0 i, a1 i5 j{
! X/ [1 B5 ?( o+ n! K        internal.Sync( cycles );! M/ `  g- I4 I: P. v: |
) J: f- C/ E$ G6 A5 E) m* N
        if( exsound_select & 0x04 ) {+ Q4 `9 B2 U2 y) P+ U
                fds.Sync( cycles );
) }& {9 u1 q5 S5 i        }
- Q, s8 T5 [1 a8 P5 T        if( exsound_select & 0x08 ) {
/ z. Z8 z. ~: Q                mmc5.Sync( cycles );0 Y2 }: E" J5 o) m' [& P6 _1 K- b
        }$ _; `2 s8 u# ~6 ^% o
}( U2 q/ `" {6 r( w  a

5 D  C1 c2 [  e( s7 Z# I/ uvoid        APU::WriteProcess( WORD addr, BYTE data )
2 p( i; {9 G- Q0 L{& r1 V" g* y' ~# D
        // $4018偼VirtuaNES屌桳億乕僩: t* k- c" ]6 S0 ^8 z0 T5 l) {; v% h
        if( addr >= 0x4000 && addr <= 0x401F ) {$ n* V' i; e4 R; F# J
                internal.Write( addr, data );! L+ O( i; {; p+ q& q2 ]0 \1 @
        }. `, J( g; b6 k  f' J3 @
}6 \# t. ?% I: k0 e. _

$ j/ C4 `' j1 r6 o6 }! M" ivoid        APU::WriteExProcess( WORD addr, BYTE data )( n$ N/ V" z6 Y
{
2 f0 _$ s# K/ K! p" x( E        if( exsound_select & 0x01 ) {
3 e, l, i0 O. n. I  |; r! D9 i                vrc6.Write( addr, data );
" |  K1 l7 f! }. D  T        }% v# F9 ^. x! C3 |" U7 ]
        if( exsound_select & 0x02 ) {
6 A2 i; U" e. _+ b& ~( o! n- m/ A                vrc7.Write( addr, data );5 w  _- J) o3 {1 l
        }. d, E6 {& U/ _* D. u- P3 p
        if( exsound_select & 0x04 ) {
/ X4 Q  r0 t: [. o+ S                fds.Write( addr, data );
7 Z# n, m- h, w        }
) ^  z. j$ K; b# J% w+ n: w        if( exsound_select & 0x08 ) {
0 u" `3 f4 A% ]- V% Y                mmc5.Write( addr, data );  \7 H) D# E8 R: o
        }: ]$ N6 i! A$ U; f) j  [
        if( exsound_select & 0x10 ) {  b, W3 Z6 [. F
                if( addr == 0x0000 ) {( |- J# V, w" O* a% x# d6 r
                        BYTE        dummy = n106.Read( addr );: ^) P0 V( j! l  Q! F
                } else {
) M" d  l! |+ y  o; g                        n106.Write( addr, data );
2 q, m: t9 Z% o& S                }
6 N/ t  B- X) M& p        }
! J% [) \+ M* h6 T7 w  x        if( exsound_select & 0x20 ) {: ?2 `6 x' \4 c* |; u' l1 u
                fme7.Write( addr, data );: v& Z  r" z+ z+ c6 a
        }% @6 T* d7 S9 ]8 K2 r3 E
}* H+ A! |+ O* N) W/ r% s

* t/ n) V9 k6 ]9 X. P0 J' _: O6 Lvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )+ r, s2 A3 m3 N7 @
{+ l1 a% L. o7 u
INT        nBits = Config.sound.nBits;
- k& m& B$ G( G( _7 IDWORD        dwLength = dwSize / (nBits/8);/ F# U. `+ ?, F" X/ B
INT        output;
' Q4 [5 T$ {# M) N% ^0 F$ u) V7 G5 aQUEUEDATA q;' y* Z1 i; [& L8 P: J8 V
DWORD        writetime;
& ]' A9 P5 }7 K$ [  t  k" A9 M: G1 A/ ?
LPSHORT        pSoundBuf = m_SoundBuffer;4 I# w. J) s- C* N1 l) k: ^
INT        nCcount = 0;
) P- g: o5 V9 B5 i6 s) ]6 N
# a1 X  A9 l. c# i/ l- I' z9 f% Q: kINT        nFilterType = Config.sound.nFilterType;6 t9 y0 [8 e) V5 G' r1 B2 o

# K# o2 F8 B* t        if( !Config.sound.bEnable ) {# K# E( J1 f+ [9 @0 A+ x. }- }/ \: e
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 i' P3 {% o( P
                return;
; M# A1 ~1 J& }1 m        }; A) f' y- `2 o. U1 Z

, B5 b" r; Y6 r# \6 m+ y* H6 C        // Volume setup$ l9 I+ d; l( [, T) Z; M
        //  0:Master
; ]! L% O8 f$ D9 {( P2 u        //  1:Rectangle 1
4 L' |/ ~; ?5 |4 S  r4 t) D        //  2:Rectangle 2
! j/ {! d/ ]/ V2 o: u. {        //  3:Triangle
; k+ o3 l' @5 n; O' A7 p        //  4:Noise+ r8 N$ B1 k& M  a( M
        //  5:DPCM
, t' F% T1 v! B$ {7 m, l0 m        //  6:VRC6# i5 U$ P) H' h( I2 h3 o; \5 V
        //  7:VRC7
  O3 b- B( O2 @- K1 f2 w% o% `! P        //  8:FDS2 |, u8 F6 x0 c& @& c5 A
        //  9:MMC5
+ J% Y# v  g: K$ v+ {! s        // 10:N1068 ~; o* y. x- ]$ l4 ^5 l9 ^
        // 11:FME7  H( z0 k3 J+ R5 M( R
        INT        vol[24];
% Z; T/ v/ A) P  B: W& r  c        BOOL*        bMute = m_bMute;7 ^( U; D! n( k+ h, c
        SHORT*        nVolume = Config.sound.nVolume;$ E: b5 B1 k5 r) Y2 a
$ |: r0 Z; ?& X/ Y! f/ H9 Y8 `; E
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  ~, Z! C2 C  d2 r
" @$ p7 @2 O" I7 |
        // Internal, b2 F0 W# q8 I. x; Z' e
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( q4 C- H& C9 `        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& X& w: N/ i: U- R  [1 Q5 ~        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;* s4 l' v. y# d9 B% r
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
, |+ j5 C4 s; w$ g6 q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
( |, W6 R4 b! {0 c( t$ {7 i3 F7 s3 r) ?0 v! J' p$ m- i
        // VRC69 P, [$ N6 |% y( b
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 d- `+ O) S1 F8 C
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% \7 U7 Q: M' X6 h        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; h5 E6 s- p" }4 w8 n) i

* |4 [) P2 S1 G7 u        // VRC7
7 ]- m/ M% y8 L( z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
  W! A# o6 |# J  [/ Q3 C- C. d' `: y: F3 F  V1 R/ w3 _/ p
        // FDS
7 d9 a9 @. j; h" X3 P        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
6 t1 b# ]9 O, z3 @8 I  F8 x2 H
/ P( ~+ P9 f2 y6 n) x( Q' U) |        // MMC5
& M6 b8 q  o& @! T/ k' s        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 a4 m) K! Y2 \        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ ^4 y/ ]7 q: [        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. t' B. \$ |6 c2 U. ^7 m4 G. w# {
$ `% h, m" A' R
        // N106
" o. i, ]1 `$ T( s8 F        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) H1 t8 M% d/ J7 q
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( g& }+ ~. D6 U
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# _, y' ?4 j6 z3 u+ e, J1 P) N
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* }' ^' I/ S; ^3 G/ _1 T/ j        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  n+ q1 G6 f! a" B        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 x! s! s8 m) a0 q2 }9 j) q        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 W; o1 t' G+ e4 ?, G
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! _6 C1 q5 `# ~: ?* z& G
* u& p4 [0 k: P  D, _+ Q. H2 F
        // FME7$ _/ A$ H( S# s* r& [5 w
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ V! o6 E* n! B+ P. I1 c5 a: g
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 L1 [7 Y3 i* J        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. t" @. l! q0 q: A2 r
, S* i9 l/ W/ [6 ~+ d//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
* u4 d7 m% O$ c5 [, ]* P; U        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# {7 G: B/ s& H4 I
6 A8 W0 S6 V8 X. t: v, F5 N  X
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
$ S( m7 u, T3 I7 J" C        if( elapsed_time > nes->cpu->GetTotalCycles() ) {9 u( D) S, B6 N9 x* o
                QueueFlush();! C9 G* W  i! W5 P
        }
9 \5 Z) }7 {$ \5 X: Z/ c- V, k4 J/ U$ m, V; F( x" m- S
        while( dwLength-- ) {1 J4 G1 R& @2 \: I! T
                writetime = (DWORD)elapsed_time;2 g) v6 c! }% J

% ~' U3 l; {7 H( d- d                while( GetQueue( writetime, q ) ) {
$ D: I7 x7 B* P2 \* a9 f# k6 j                        WriteProcess( q.addr, q.data );
" H. P; V! d! C6 t  p3 `- }                }
# f* x) b6 B! P9 D( |- b
, ^* o* F3 ?% ]5 X7 v7 Z" q- n                while( GetExQueue( writetime, q ) ) {* e) j5 ]* _- v# F! g# Y& m8 x3 p: J' A7 D
                        WriteExProcess( q.addr, q.data );( v% Q" w) P' o4 k' c
                }( F" j% L9 h8 N) a

7 a" T( ~7 k/ u8 {0 ?  `& @7 B                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
4 w0 q* Z8 `- U5 k& ~                output = 0;
  c' z1 o; b0 T9 I* G* d                output += internal.Process( 0 )*vol[0];7 s) }* l# J9 V% o1 C6 |0 u2 z% Z4 C
                output += internal.Process( 1 )*vol[1];% \* A( `" [* K1 q& \
                output += internal.Process( 2 )*vol[2];0 @- X6 m" @9 ?" Q
                output += internal.Process( 3 )*vol[3];
3 X  |+ W$ x8 w4 z                output += internal.Process( 4 )*vol[4];* Z& c/ g, C! Z, e- k, h

6 Y2 h! y% F6 r- z                if( exsound_select & 0x01 ) {
$ c7 l' I  E3 p8 ?* g& z                        output += vrc6.Process( 0 )*vol[5];) ^' s# b$ E. O/ A% T3 g
                        output += vrc6.Process( 1 )*vol[6];; f+ c. E/ T  s4 d  h0 {6 H
                        output += vrc6.Process( 2 )*vol[7];
$ n% f2 f+ ]" O; M2 y7 X0 F+ k; E: w                }
* w8 k3 i: ~! K% c, I% a6 ]1 w                if( exsound_select & 0x02 ) {
# {# ?: V4 _0 e( W& z; O                        output += vrc7.Process( 0 )*vol[8];
9 O% }8 N1 A' ^                }
3 E+ c; f! h8 p2 x, j  l                if( exsound_select & 0x04 ) {) q( B' r5 e2 ]; g' _
                        output += fds.Process( 0 )*vol[9];
/ R0 t4 q1 s" U+ O9 b5 C2 U                }
  `" b9 h: a% P' l. j                if( exsound_select & 0x08 ) {& I( u' r* l2 Q6 ^
                        output += mmc5.Process( 0 )*vol[10];
4 E, n  }" J: X/ g, U                        output += mmc5.Process( 1 )*vol[11];4 e( c) _" h# j
                        output += mmc5.Process( 2 )*vol[12];
8 `6 h( w$ e; A" ~( L                }
3 }# C# D( }. A  P9 w+ ^0 Q                if( exsound_select & 0x10 ) {
; B- R( p6 p8 u1 n3 g: N                        output += n106.Process( 0 )*vol[13];7 c- J. I: |2 u% l
                        output += n106.Process( 1 )*vol[14];$ k& K3 g4 {) Q8 v! w5 l; i
                        output += n106.Process( 2 )*vol[15];
0 Q1 t3 T! ^3 [2 c! q# j                        output += n106.Process( 3 )*vol[16];0 A* w% |3 S& W! x+ U
                        output += n106.Process( 4 )*vol[17];
: Z9 E- W1 {2 t& e! r                        output += n106.Process( 5 )*vol[18];# p8 `9 `7 `* j# w3 m3 ]; ?
                        output += n106.Process( 6 )*vol[19];
  M! o- L! Q- e3 |. A3 b% O                        output += n106.Process( 7 )*vol[20];
% d8 G8 u* P0 N- A                }
+ f6 \9 w. Q' ~, C  C, N* B                if( exsound_select & 0x20 ) {: N; ~! i. \3 y% g0 C) `% X
                        fme7.Process( 3 );        // Envelope & Noise
* O" h8 Z) }' {  ]8 G* T/ Q                        output += fme7.Process( 0 )*vol[21];1 p' O4 p9 Z4 X/ e, t4 @3 Z( k& X  g+ g
                        output += fme7.Process( 1 )*vol[22];; X% C- K* Z0 q% r5 c
                        output += fme7.Process( 2 )*vol[23];
+ I3 p0 b6 Y0 H1 C                }) `9 @# G. K! d
' M# s( Z0 K9 {* h+ U! }
                output >>= 8;. |1 E* [5 l* q$ M

$ \$ {+ `2 L- e! V+ C- ~& L                if( nFilterType == 1 ) {1 }. S: I1 Z" y
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)( A* c: v) X5 u7 ]* D
                        output = (lowpass_filter[0]+output)/2;
" l: K3 e' E9 D0 U3 [6 @- s                        lowpass_filter[0] = output;% p; C& C5 Q' L
                } else if( nFilterType == 2 ) {# u) k" [' O- f, u
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)7 ^1 }( [6 i+ v8 X" f
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;& X5 G7 c4 h7 P- V
                        lowpass_filter[1] = lowpass_filter[0];
4 K7 @9 v5 u# Y. O5 J; Y" X" G5 `                        lowpass_filter[0] = output;
& u  ^1 Y* y* u3 d7 |8 P                } else if( nFilterType == 3 ) {
* J" T2 y; @$ k. z  r& v. M                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
$ _' U! K# S8 \                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
! G2 X& J9 O1 v( y9 \2 T                        lowpass_filter[2] = lowpass_filter[1];
! e* u$ p; W7 W6 b  k9 l$ Q' h                        lowpass_filter[1] = lowpass_filter[0];/ F: ~9 N2 w) K9 L" d
                        lowpass_filter[0] = output;
' e' S* u4 Q* X5 t, f: r                } else if( nFilterType == 4 ) {
5 Y0 `* _4 f- C) w                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
0 |6 c- X5 s; A                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;' I1 |7 B, r6 q& n' a# K+ S
                        lowpass_filter[1] = lowpass_filter[0];
' h: a& O9 e# Q1 y0 v' {+ P                        lowpass_filter[0] = output;
3 X3 F6 ]  X- k) ]' |% y# z                }
0 Z; k' g7 n( s' Q! H# ?/ L+ n0 `3 I6 H7 d  g2 i1 Z
#if        0
  J# G  F$ |+ |1 y6 I5 U7 V" s: ]                // DC惉暘偺僇僢僩
7 |" ^- N! {; \$ u# \9 n                {
) {: m: B2 K' t# I0 b; I3 w                static double ave = 0.0, max=0.0, min=0.0;- J$ p: t* D; F) R4 ]5 [
                double delta;
: @/ a; L/ n) f! E                delta = (max-min)/32768.0;
# @  ]! j5 T, O8 i                max -= delta;
* h  g; A1 D3 c4 s6 b7 k& e                min += delta;/ N1 K3 y1 R) v$ G0 o! a# G
                if( output > max ) max = output;
" R* Z9 [  R: B7 I                if( output < min ) min = output;0 p1 C3 B: q8 |. q) d9 `
                ave -= ave/1024.0;+ u' B* B( Y# ]) p5 V/ w
                ave += (max+min)/2048.0;9 j7 ^' g, w7 j' N# F
                output -= (INT)ave;) d. {' @$ K% @/ r/ K1 [) Y5 \
                }2 a1 t0 b4 z# M$ z5 u# t
#endif7 U! k- i  O+ I& j9 z0 |& }6 i6 m
#if        1$ \) O0 o8 ?' V" h( A! c
                // DC惉暘偺僇僢僩(HPF TEST)
* o: x! {6 R/ T                {# I% P2 q# w- p  ~) x7 a: S
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
: q1 _; R7 T5 |& k9 s/ S                static        double        cutofftemp = (2.0*3.141592653579*40.0);+ Z9 Y0 d5 a0 X. b0 r
                double        cutoff = cutofftemp/(double)Config.sound.nRate;( i. w! Y6 B9 [" ~& ?" v8 r% t/ K
                static        double        tmp = 0.0;8 T6 m  v( d- m% W( c! R2 b, S
                double        in, out;4 s9 N' s: q1 M& U3 o8 N0 l6 p
3 A7 O$ d/ S& ~- A: F
                in = (double)output;
7 x3 K/ s8 G: P% U! @                out = (in - tmp);3 }' `! G, j5 a1 k" c# w* R% {
                tmp = tmp + cutoff * out;
: b9 F# D* H# U+ V0 P& x! @: x; _& g
                output = (INT)out;
. ~+ r2 b( }5 s. r2 _5 J0 u; j                }
7 I  Y& O" @6 k3 [3 J- F#endif
4 k; r1 }! g& z. u#if        0
) h; Z5 W  m8 j: n                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)1 ~- D" t7 N$ a' \# X# {/ }8 \
                {
9 T: R' b% K6 {) I5 F                INT        diff = abs(output-last_data);
$ v/ o( Y3 H( A$ j. d2 J4 H                if( diff > 0x4000 ) {! P, Q" ?; Z( r
                        output /= 4;: Y; {  x5 v8 A1 @+ K
                } else * D! k* h+ r! ~# _0 p" L. e, a8 I
                if( diff > 0x3000 ) {
3 O. X, A8 l! a# b# a& s7 C! u                        output /= 3;% E' G- y( n% r1 S; a5 Z# r0 ~& L
                } else
& X( b; J" i% E7 _                if( diff > 0x2000 ) {4 \$ H+ S# o# R
                        output /= 2;
& x( {& I) k5 r4 |                }
8 {/ Y- p6 r% K* V8 P3 C" p                last_data = output;/ u* Q3 A, ?5 H0 Q' G# k5 ]9 S' D
                }
' r* U; A1 R4 Y4 P" a1 L" z' s#endif
9 h. w5 ~8 C. B0 H                // Limit6 ~2 n: r8 ]: a# k' k
                if( output > 0x7FFF ) {" |  M. H8 d3 R  A7 F
                        output = 0x7FFF;" {$ e. ^$ `3 L; W/ H  q
                } else if( output < -0x8000 ) {8 f# b4 A$ x  R& ^2 J) @
                        output = -0x8000;; a# X( x9 @2 P: w( ?! @
                }
7 m' s* `% o) I6 Y4 o* \0 M
5 W4 U8 {6 H( R8 A& t: m% K# N                if( nBits != 8 ) {
# Y/ U9 O8 s& [$ w0 o+ G9 f                        *(SHORT*)lpBuffer = (SHORT)output;
9 q* `) V" c, @( N$ ?2 ^, W! m- n                        lpBuffer += sizeof(SHORT);
; }: {5 c3 q- A5 V0 G; H                } else {% t) \  b5 ^" B4 }5 Z( E0 }
                        *lpBuffer++ = (output>>8)^0x80;# L; u/ H+ M* j0 O4 s$ f6 Z
                }9 H+ F7 ^6 c% Y! |7 i
! d- N& w: x4 s! ]. i% e
                if( nCcount < 0x0100 )
6 N- V: D4 J8 `& h8 j                        pSoundBuf[nCcount++] = (SHORT)output;! _( K0 E8 d! o. p5 S

2 _! S! Y' K$ B3 e6 X& q( W/ h//                elapsedtime += cycle_rate;! J! C& h$ N( D
                elapsed_time += cycle_rate;
; c$ R6 p/ `) y% g! X; u        }4 U3 v6 w) A' c5 d4 x0 y

) r/ ?9 }/ P% Y; I9 W2 H! e/ Q#if        1; y2 K/ _& T1 H! M- \8 |
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 @+ E; T# S5 c8 Y' l0 I* q                elapsed_time = nes->cpu->GetTotalCycles();! Y& O% g. Z  r5 L5 e/ U7 K
        }4 f# c  R  k& q0 m' _; C: I
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
6 e8 k+ K  u# `' R                elapsed_time = nes->cpu->GetTotalCycles();; h) ^0 G7 ~& Q: Z4 R1 j& C
        }( h2 r: W1 U% O) h' y
#else
  v& S: b* `# S! [7 ^3 P        elapsed_time = nes->cpu->GetTotalCycles();
( e3 f5 _8 _  k9 Y#endif
. w# |5 M0 u( I& N}$ J" O1 c6 M% g" V$ R

# J7 y# y6 H% |6 x// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)6 F: Z/ I: ^! s2 [  y! l; `
INT        APU::GetChannelFrequency( INT no )
! F7 @; U& d0 E: O{# p/ A$ C. n# C; m/ s0 T5 `
        if( !m_bMute[0] )
( |$ n8 T) f- W9 @  B                return        0;
# q2 f9 T4 `  }+ L  i; ^# R  p* ~! [1 Z% t3 J6 Q5 q1 u
        // Internal
9 L% h# q5 ?1 P* c. l, }/ d        if( no < 5 ) {
/ J! r7 }7 V  g+ ~2 `                return        m_bMute[no+1]?internal.GetFreq( no ):0;
2 D4 M9 z4 X% [3 K# t/ g        }; X3 L* d; Z+ B6 x0 L
        // VRC6
1 F. g# r1 n5 K! r$ @        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
5 F% M" Z6 W  K- d3 d& w1 i8 s* H6 Y                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
1 ^/ |5 }. v$ o4 u" ~. Q        }0 t) e* ~4 i2 |/ c
        // FDS& ]  v- M5 d6 a0 e# |+ @. k
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ j" ]6 S( X5 e2 i( p3 E                return        m_bMute[6]?fds.GetFreq( 0 ):0;8 ]2 m" E$ V7 G
        }& D4 [. i- g2 s( j# G, |
        // MMC5
$ t- p& |! Z2 x7 r* Y9 ~        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- d/ l9 S5 F; q6 {1 B7 {- M                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
2 O* s* _1 @) Z8 R' _" e        }/ G- i/ R; n( A0 p  F  }6 C
        // N106
8 R. Z/ v/ e+ ~( G/ y        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {; ^% X1 O% w* E* }8 `9 H
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
( K" B3 F- |. ]0 R4 R; G        }& t# m& N1 S" W
        // FME7
! p3 s9 S/ b% |6 Z1 h) e6 G$ N        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {, w1 ~' x/ g, k$ G  \
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;0 x2 w1 [' d% U& O  G
        }
& b$ M" r2 q3 o& R2 `; u4 @        // VRC7
3 z9 J7 I- X; S9 g1 t( ?  P( x. E8 j        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {4 E$ e; i1 V& w8 v: R) W& h+ p! P' B
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
& |( C. K: a  u- o- Q        }
6 [( Z, L. X  Z$ V        return        0;
7 @" S4 K2 M7 W. ^. ^}) h& _. W, M' k' M  Q" ]
) _" }' r* V( P$ s1 L
// State Save/Load; X$ L0 Y4 A; b7 `; _
void        APU::SaveState( LPBYTE p )
5 ~- v8 Q0 H! g& J{/ l$ _+ z6 {2 c
#ifdef        _DEBUG
( d( R" @4 V) t* i1 k; [7 z# ULPBYTE        pold = p;4 E+ X1 W# s8 b$ U% m
#endif" q3 [* t2 o6 v- L1 F, t' |
0 D+ }, {% C8 @! d0 q4 u7 _
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
. c5 F* L/ C% ~& d        QueueFlush();7 c+ B9 |" y% w$ f% L1 r
  |& L1 U, H. p& \
        internal.SaveState( p );$ E9 M) j3 ]3 @$ s" q
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. k- t2 I$ V: G- [- g  E) s! _' X6 F6 L1 R- l3 i- K- ^
        // VRC6( l3 o3 S" g& R7 E" s8 f
        if( exsound_select & 0x01 ) {
% T! \: [0 Y' m' {7 d4 j# Y                vrc6.SaveState( p );; Q1 m# W0 C# K. v/ S
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( N3 G+ B8 J5 g% `1 v. I) F
        }: ^' @: I6 R' y' P& F# W. G9 W
        // VRC7 (not support)" i& O# Z4 h! D, W( n) d9 C
        if( exsound_select & 0x02 ) {
7 k8 b+ `, L+ V9 A' n                vrc7.SaveState( p );
8 N: J) U& E) ?6 t* u                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 T) y" ]& g8 w. H; l& [5 h  ^        }# S* v7 s1 A7 H' g6 N+ ]. r" e
        // FDS
1 M# J3 L2 G* V$ ^. S7 Y5 ^        if( exsound_select & 0x04 ) {5 n  c+ ^! R( Y, l% K# h6 d6 t
                fds.SaveState( p );- f) O# Z( G  r* F: B: {) Z& [
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& R5 F/ ~9 `2 ~, @4 v
        }
, ^6 W, Z( k, _; m* n2 R1 `        // MMC5( h7 `2 K3 l2 r) t
        if( exsound_select & 0x08 ) {
4 S8 ^2 C: c$ B1 O2 ?                mmc5.SaveState( p );
7 }) `; N; ]" o( `; ~' j: o5 S* s                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- G% {; G: r! o( g& m' F) h        }
1 _1 V6 E5 i1 R; c: Y# S$ [        // N106
. ?6 G# P, a+ N1 V+ R        if( exsound_select & 0x10 ) {. i; d- a) s; m( W7 k
                n106.SaveState( p );
2 T4 o' A7 u' y                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 Z/ `5 b( s" \- I        }' c  {- z7 _" u: A7 n3 t
        // FME7
  @* _* a9 |- w6 j  _- _        if( exsound_select & 0x20 ) {
+ V/ ~6 V. G# G( p7 ?  L                fme7.SaveState( p );
: D8 G. }8 _4 U4 t% K9 p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
% B! V7 T' a$ B" ~8 g0 l* d/ X        }
+ U  k- ]! l+ z# `; [+ y" {9 i% b& v% n
#ifdef        _DEBUG! _" ?, X" E. E6 G) A' @! _
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
. t6 k7 @' b3 B* M#endif
0 \6 r& ?' W; W}3 H' }. ?  \5 `, C+ K
5 e. V* Y! {" M5 I: l  v4 i
void        APU::LoadState( LPBYTE p )
+ ]. j$ S" A. y{7 g  u8 |# _5 u  I  a
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! @1 N! Y& u9 e, B" H$ d1 ?5 H/ F( h        QueueClear();) T$ q( o! V7 \, T8 T, k7 m
4 Y3 L; n- \" J8 h/ q
        internal.LoadState( p );
7 H% k4 L4 h! I3 O* I+ P        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
. V$ z/ b: R' Q9 a1 X% A+ z3 w/ \4 _* B( q6 ~
        // VRC6
7 \9 M3 ~' D* u0 b% d- w0 w        if( exsound_select & 0x01 ) {
8 k5 c! b. ]4 ^) c7 Y  i                vrc6.LoadState( p );
' E6 k3 X& f6 L0 m8 B$ Q2 x# a                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding7 m# w" K; L$ s4 D
        }
( ]* M: D% k* k& f        // VRC7 (not support)
# l3 v0 J6 Q$ c/ k, M5 ~        if( exsound_select & 0x02 ) {* p# d" Z/ ?/ U4 K" z$ l
                vrc7.LoadState( p );
, k- Z, H  r/ T7 M6 U                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 a+ A+ ^2 V: \
        }7 ^6 _: [& x) U5 E% I! v
        // FDS" e) q& {- o( g7 ^, ~$ K0 M/ I) F1 ^
        if( exsound_select & 0x04 ) {. K4 h$ A, p: l; v5 ?& K
                fds.LoadState( p );9 Q' V2 Z& i! n8 ]- t+ X
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* V" O: u7 N0 ?. @" v% M5 b: {( Z        }
" |. ^4 ?1 a% e! T) Y- a        // MMC55 G) b4 _" X+ B$ ]$ U
        if( exsound_select & 0x08 ) {
, j  Y. V) U6 \6 x                mmc5.LoadState( p );+ n) z5 B0 Z; @" R
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 n+ \) r  U9 n: C4 [7 V% s
        }8 k" u) L4 Y9 [0 [$ m( B) Q* |
        // N106( N# o1 m) O, J. K7 K
        if( exsound_select & 0x10 ) {' g9 Z5 O& n" s* O) R
                n106.LoadState( p );1 l- n  Q( }8 [4 {9 V" B
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 r& r; z. Z3 Z
        }1 j4 K+ k7 A9 e
        // FME7% q1 B+ B8 q9 M( [: U
        if( exsound_select & 0x20 ) {- z2 o! f6 F0 N  C
                fme7.LoadState( p );2 a  y4 _: p- H1 e+ C
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! k4 ]3 ^+ h$ N4 l; @        }
3 U1 g1 `% c7 w+ u1 Z1 ]}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 5 Z" v# T! ^4 U. A# N" G; f
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。7 k1 A) j. w' e' R+ g4 I4 C; O
感激不尽~~

; y  J; S' U% h6 X$ B7 f恩 我對模擬器不是很有研究,6 u' c- q4 r5 C* K* ~
雖然要了解源碼內容,可能不是很困難,$ D0 d- C; j2 I# Q
不過還是要花時間,個人目前蠻忙碌的。7 F9 i9 F" ?& l( x
5 B" r- f" ]; Z' X5 N8 K
給你一個朋友的MSN,你可以跟他討論看看,- x5 `7 c+ C+ L5 U9 G/ s* J
他本身是程式設計師,也對FC模擬器很有興趣。" L, ?4 x; @. q8 A3 [
/ T, b' w4 d0 s
MSN我就PM到你的信箱了。0 X6 O3 Q% ]0 w2 Y8 v" @

3 U. V0 E' s$ n7 X3 i$ n' d希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
* J8 c$ b  M$ C) U) w, _; \呵…… 谢过团长大人~~

9 h# z4 G$ M& g* g3 Z/ n. v  {0 s
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 $ k& ^2 j  u9 A# p4 C; k9 Y6 x
团长的朋友都是神,那团长就是神的boss。
2 n8 V' P/ l+ f: e/ p3 g
哈 不敢當,我只是個平凡人,$ g' F# x$ B3 D$ b/ w; T
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
! h! ]& F2 H/ p1 RZYH
# n- D" S/ y# Q6 A1 LQQ:414734306; Y$ S1 ^( Z# `, F# W' k5 F
Mail:zyh-01@126.com
% h& j9 z1 F# J; t0 i3 @5 |
, L* {- i% X  {; b: B他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
( Q) S) R2 M7 f4 u! `; Q; @再次对团长大人和悠悠哥的无私帮助表示感谢~~

$ ?6 ^- Z* b! i# L- ]/ _4 o不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-12 23:35 , Processed in 1.101562 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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