EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
1 N8 K+ q/ @7 n9 k2 A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 J; Q& L% G6 P- L+ X( \$ O/ p
这里有相应的模拟器源码,就当送给大侠了~~
2 p; |* G/ _4 u. E2 xhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
8 Y% A! F: g; \8 S' o能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。, D) ?! R  @2 m4 P. i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~; R, {! N/ V$ F  u8 W8 T$ C0 g
这里有相应的模拟器源码,就当送给大侠 ...
5 t6 D9 O3 {, U, i0 o+ L3 A
聲音部分(Audoi Process Unit = APU):
6 _3 @# R3 c. W! N$ C/ h.\NES\APU.cpp
7 r, k  R# K. \9 m9 c.\NES\APU.h
" L* C2 K1 I8 L% N
1 z8 i" R  x' C: q. D. k- u5 l. g5 |) V- B- G8 a
影像處理部份(Picture Processing Unit = PPU):
5 Z& F8 U5 Q5 [5 L2 `. J% e.\NES\PPU.cpp. J' \7 y: F, ]! o$ ?2 x# m) S
.\NES\PPU.h
& B3 t% |$ C5 w* z; E$ T4 `2 u0 t, w# }+ {0 A) {9 C5 W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; }7 ^; p. s, V6 i7 x6 }! ?3 c
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
" i; x( h/ e! L) u8 a" A! |//////////////////////////////////////////////////////////////////////////& l* n* A# F( v; \1 u; w( r% x( i3 R& {- e
//                                                                      //: ~) [0 q  V% _6 _- Y2 ~$ }1 D
//      NES APU core                                                    /// ~4 p- ]4 t: H! i' [% l
//                                                           Norix      //
9 H5 f0 c1 K' j- @$ X% `2 d! C9 N//                                               written     2002/06/27 //* Y; W" l% k# N3 z* Y* \7 i
//                                               last modify ----/--/-- //* c4 C; I5 X, c* W! {1 z3 L6 [- J
//////////////////////////////////////////////////////////////////////////
% u( P% r7 t9 V! W% q#include "DebugOut.h"0 N8 F% P, l2 |/ ]; Z
#include "App.h"
8 ~1 n% _) T( J+ p#include "Config.h"- G6 c+ u% n2 ^9 i; ]* h

1 a$ D& r; m3 {- |#include "nes.h"' a+ `3 \5 ^) E1 d* |' W3 y
#include "mmu.h"$ L! [; Z) D. S) Q
#include "cpu.h"
+ [8 }; ^1 v# i4 E0 A5 J7 c* P#include "ppu.h"
4 s& L6 R3 N) w#include "rom.h"
+ U, j6 J- V' y) x6 B/ p; I+ I#include "apu.h"
: S6 a5 ~3 z: [8 ~: W+ R; r4 P2 F/ ~% ~  \- v7 u- M4 Y+ `# s
// Volume adjust$ z1 W2 Q8 n) C$ c$ F6 G
// Internal sounds
* ?& _! T6 c4 ~* U#define        RECTANGLE_VOL        (0x0F0)
0 Q$ ^! g' E, m$ p. D4 P#define        TRIANGLE_VOL        (0x130)
8 d8 }) |* e8 x#define        NOISE_VOL        (0x0C0)
7 Z4 J' c( {+ ]2 U5 w% X$ y#define        DPCM_VOL        (0x0F0)
" k) |( Z( v, [# k- d8 A9 g! U) r// Extra sounds
9 @- [9 K0 p0 K8 Z" ~8 H- R#define        VRC6_VOL        (0x0F0)- b' a5 _# l; t0 D
#define        VRC7_VOL        (0x130)8 `( w1 u0 R* c  C0 n+ K
#define        FDS_VOL                (0x0F0). ?: U2 D! ^; f2 |: e( Z. p' `
#define        MMC5_VOL        (0x0F0)
, n" Z6 ]7 C, [3 L% ]  Z2 B#define        N106_VOL        (0x088)% l3 _  S/ }5 Z3 N' H
#define        FME7_VOL        (0x130); A1 z/ b  V' G) ~' L) E6 |

) @+ }; g" g* a( N! FAPU::APU( NES* parent )
' s9 v4 G' T" }! b, x{
, N4 f4 D9 V$ n; v        exsound_select = 0;+ U: m) g  ]7 o

1 ?' g$ l$ O5 d- u- \& X        nes = parent;
4 x9 S  y$ U( M' s, r: s        internal.SetParent( parent );  X- a4 K4 G0 Y$ g8 _) T% v
, n8 c# |% U% l& }5 }
        last_data = last_diff = 0;, l% q# b& J8 o9 I: n

( Q6 e( E- Z+ D0 f2 e        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 S3 S/ b, L+ F) g: w' v6 I( Q( v) L7 H1 A
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
/ T$ ]' G( r9 C5 w8 A+ C9 q        ZEROMEMORY( &queue, sizeof(queue) );4 R2 ?% @( D- P
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& g0 a/ Q, i% r, F- q" d2 S# W5 o
% T$ n7 E( @8 j# i* q
        for( INT i = 0; i < 16; i++ ) {
. @* d% l% |" z9 c6 o, J0 U: J8 y                m_bMute = TRUE;* Y. [! W$ W7 R. ^2 `
        }  {- ^& C( j+ k$ m4 }
}
4 q' t6 r6 W) r% i6 S; @8 Y
1 r9 q0 p9 [. Q8 O& d6 ~8 vAPU::~APU()0 Q9 h( L/ u* A
{
. z3 e( B, r  J}, T- |4 e9 i$ ?- l8 V1 ]# @# Y$ g
' w' y6 C; M1 R1 u* a2 d' L
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )1 O/ f. P5 b% E( i1 D5 F3 P
{" a1 [4 [0 ]/ Q
        queue.data[queue.wrptr].time = writetime;
4 @% U. M7 d; N9 B" U% Z5 P        queue.data[queue.wrptr].addr = addr;7 q; }0 y* C! q" T- a% s, d
        queue.data[queue.wrptr].data = data;0 C3 R1 l; y) b5 Z& e. c; J
        queue.wrptr++;' v3 B# Y/ h! w0 c
        queue.wrptr&=QUEUE_LENGTH-1;
2 B/ b9 y# v/ [, T7 Y        if( queue.wrptr == queue.rdptr ) {9 W" p: q+ U6 L* P6 T7 v9 F
                DEBUGOUT( "queue overflow.\n" );1 S, b* v3 @; l6 l
        }1 G# [( [% d0 S  v6 Y- z
}7 p# C1 U5 s! E' h; _7 _
7 L- y7 q6 Y$ R! S4 G. w
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
0 I$ p* W3 A  @0 E; E{& L0 @4 N( |; E/ k3 [
        if( queue.wrptr == queue.rdptr ) {- j: G8 V  }2 Q/ f- t
                return        FALSE;
1 t3 Y8 u4 G  C- _/ k. c        }
) [6 ]9 M0 u' V7 I1 r" H# a" q) D        if( queue.data[queue.rdptr].time <= writetime ) {: n! m2 K& }* p" }0 P0 E/ U  |
                ret = queue.data[queue.rdptr];9 A* ^/ E7 V2 u  @% Z: O# g
                queue.rdptr++;# ?) }1 C! I/ r! M" J' F
                queue.rdptr&=QUEUE_LENGTH-1;. C$ d+ S+ @3 b% s  z
                return        TRUE;
+ g- X, \  }3 A4 d2 b% h$ `        }
0 m- E+ W) Y6 |* Z  W        return        FALSE;
! _( {$ W+ ?# }}
1 Z) X. p2 L! v6 D, C" o- L- l. v. j5 M8 X1 `
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ): {( d4 ?( |* S% S3 Y* S9 V; X
{
& w# {* e. s2 x+ H5 r        exqueue.data[exqueue.wrptr].time = writetime;
. ]1 N" ?: N& a5 m        exqueue.data[exqueue.wrptr].addr = addr;1 ^  i, _- l6 V, [9 k8 E
        exqueue.data[exqueue.wrptr].data = data;7 o9 V( @5 ?0 c( |0 s
        exqueue.wrptr++;
2 ?8 p: q: a* S5 s# @0 G( r        exqueue.wrptr&=QUEUE_LENGTH-1;% \) a4 X; P4 _# I9 s3 I8 w3 y
        if( exqueue.wrptr == exqueue.rdptr ) {9 o6 F, i6 [; l6 J$ f5 Z
                DEBUGOUT( "exqueue overflow.\n" );
# h4 f( Y# o' F        }
6 U: X' l# Y' A$ d2 o}
, b  Y* W2 I$ v- H
/ I+ [/ M3 H8 @6 |5 U$ `BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. l# a8 }3 X8 V& U" a& f( C( R' v& ^% f{
7 d- v6 Y5 q3 c( h        if( exqueue.wrptr == exqueue.rdptr ) {$ ?/ Z* l. k1 `
                return        FALSE;" n8 j: u1 ^  U* \/ z& R
        }
4 ~% A! q) u+ f) h5 T1 G        if( exqueue.data[exqueue.rdptr].time <= writetime ) {* y+ \2 A6 w9 @1 R0 j( U  c, A
                ret = exqueue.data[exqueue.rdptr];& S; y# W7 s' l, X$ ?: ~& Y
                exqueue.rdptr++;
& ^1 o/ w- d* n9 [: Q8 [6 `& C                exqueue.rdptr&=QUEUE_LENGTH-1;
. Z3 R: P5 m7 j; \( I                return        TRUE;1 m3 W/ S. _: h! X- ~
        }
; K$ q( O5 ?$ E# t        return        FALSE;
( r3 i) t  r" Y/ P# t; A9 n- M}
; E& S4 Y5 w- d6 I- [$ @& Z' I  j+ @% m6 ^6 h- K
void        APU::QueueClear()! h( _7 p* p8 k
{% G: W. K2 E! K5 F8 c$ k
        ZEROMEMORY( &queue, sizeof(queue) );
( N2 ^2 b8 ~* m  b9 _        ZEROMEMORY( &exqueue, sizeof(exqueue) );. v0 f! \4 I2 _; K
}) u' n( W+ ?8 F% _

9 A  M0 d6 o: t, {2 v6 rvoid        APU::QueueFlush()
* u  f1 x: u8 M9 f) X/ }{
- ?0 X/ h0 b3 F& Z' g$ X* a        while( queue.wrptr != queue.rdptr ) {
& [' a+ B/ L4 ?% r9 A' B7 A                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
( p' }2 m5 Z) |! W: j" l" m                queue.rdptr++;
; V% _$ ]" k, K3 Y                queue.rdptr&=QUEUE_LENGTH-1;
0 P- f  b- v& H6 c; i/ r. v" R        }; d2 t3 Y/ l; a; q6 |% u
- y$ c# T1 S3 f/ w/ ?6 `
        while( exqueue.wrptr != exqueue.rdptr ) {
4 K* V! Y9 }7 |' R9 a                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. W+ ~# ]% g1 \1 v4 O
                exqueue.rdptr++;
+ [: m0 V# P! Q) O/ h# B9 G% \( ^% T                exqueue.rdptr&=QUEUE_LENGTH-1;
) b  i2 V8 K% s2 J1 n2 E        }5 E9 o7 |2 }6 }5 v8 G
}) O& b7 J  D& `/ K
1 F4 |' ]& B! }) Z; h
void        APU::SoundSetup()
# D" }! X8 E* p+ s/ t( [; o/ y{( }1 G9 f1 l, d% C: k
        FLOAT        fClock = nes->nescfg->CpuClock;+ G0 v! T9 y1 v8 H; L; i  ~* D
        INT        nRate = (INT)Config.sound.nRate;
% J: G2 M1 I% q+ O  f# k        internal.Setup( fClock, nRate );, V. X9 u. l! G
        vrc6.Setup( fClock, nRate );% N) P* r' F- v/ j
        vrc7.Setup( fClock, nRate );6 q: p: d4 {4 T' I/ b5 D
        mmc5.Setup( fClock, nRate );
# z/ X1 X  P" _; p1 X        fds.Setup ( fClock, nRate );+ |' {6 n) d5 ]3 I7 b  k
        n106.Setup( fClock, nRate );
; s  }; N/ @: K        fme7.Setup( fClock, nRate );, `) C& R5 ]: t/ I& Y" X& v. z' G1 e
}5 d. i9 S( p& U. ]. S8 J
, I( [" o: M% u/ k1 {( G+ o& {
void        APU::Reset()1 o( m. s' s$ q' w- H
{5 p! c3 o3 k" q% a$ z, Q. c
        ZEROMEMORY( &queue, sizeof(queue) );
8 Q' o' X; |7 \* V  K& s        ZEROMEMORY( &exqueue, sizeof(exqueue) );) X) D5 s3 N, ]

& I$ d$ o1 r( j        elapsed_time = 0;3 f  P/ `: o* Y2 _7 N3 o
  U6 b- |+ g: n' d7 s! h7 K
        FLOAT        fClock = nes->nescfg->CpuClock;4 g7 v5 k* u/ u' D4 Y8 p9 d4 o
        INT        nRate = (INT)Config.sound.nRate;
! m- R7 o# {& s# {: ]) I5 i        internal.Reset( fClock, nRate );
$ M/ z# j2 e# S8 e4 ~        vrc6.Reset( fClock, nRate );
1 a/ q4 a* f" j# k        vrc7.Reset( fClock, nRate );
1 l- U1 N* \) s: X        mmc5.Reset( fClock, nRate );6 A8 `, J: p: [* c
        fds.Reset ( fClock, nRate );
! ~; }  l5 \9 S+ L0 |        n106.Reset( fClock, nRate );
2 k: p8 j; |' Y3 t        fme7.Reset( fClock, nRate );
  N4 o- `) q+ Z2 }* Y& S' _' Q7 ^" R, g' W4 H9 Z, H1 i
        SoundSetup();
5 L- p& r2 [2 _- r}% O* {8 Q$ e! o( o: v
+ ]; k" H/ N2 E; K  U8 t
void        APU::SelectExSound( BYTE data )2 d5 `5 r7 z: _5 ^$ c
{
( s- S/ r0 X7 x2 [        exsound_select = data;6 M* ^) t( I* Y8 L0 d
}
4 f2 t7 u5 y5 C* z* U
1 d! A6 ~: z* T9 |0 G, b7 B& qBYTE        APU::Read( WORD addr )
' n8 U9 P/ L* P+ Q6 f{
: u' k2 ]  Q3 ?* q4 V7 i        return        internal.SyncRead( addr );
: r  c+ h0 m4 R}4 b' F* i- R  k2 c, Y6 k; z* Y  E7 f" _

/ ^7 r/ b. @" T" a* a1 }void        APU::Write( WORD addr, BYTE data )
/ c5 O7 o) `1 M0 H7 _; A/ h{
/ r7 c" g/ C9 E+ G        // $4018偼VirtuaNES屌桳億乕僩" u: \, M/ e" ~7 T
        if( addr >= 0x4000 && addr <= 0x401F ) {) \" C* p/ T' S- H5 d
                internal.SyncWrite( addr, data );
3 I" c; S) r" p6 B2 Y( ]                SetQueue( nes->cpu->GetTotalCycles(), addr, data );' Z3 P+ [) O8 I2 Z8 A4 {
        }( O, }: X  S: D
}! T4 g2 G0 h2 q/ d6 \% H+ M
& ?  n4 E- l+ `. e. `; k5 L
BYTE        APU::ExRead( WORD addr )
  Y- S( c/ E. c/ U{
0 \+ U* V0 g3 H  `8 c0 z% ^BYTE        data = 0;8 H, v( R, K4 Y7 u- h

5 n2 H7 `' [) Y" W9 k9 p        if( exsound_select & 0x10 ) {* U" S  ]" c& Z! y
                if( addr == 0x4800 ) {) I6 @: y" k0 \* K! R
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );. v0 b9 }* l$ S$ [9 f
                }
( h% |; j! W) N4 x        }
8 y8 e5 y9 e3 H( C' q        if( exsound_select & 0x04 ) {9 Q# U. O% b3 A) h9 y$ c
                if( addr >= 0x4040 && addr < 0x4100 ) {
: P/ Q6 [1 r5 \. N                        data = fds.SyncRead( addr );
8 O% e& `- _3 t                }$ U5 b- T# }' J8 b* Y$ j
        }
: {) `9 D( R9 o' v) c: e        if( exsound_select & 0x08 ) {
6 [9 b2 G$ Q$ C' ~( z& z$ J                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 i6 Z" u/ N& Q/ }                        data = mmc5.SyncRead( addr );  y4 \% }$ H( H4 M& Y0 }4 y7 ~. R2 m
                }
; ?3 M4 k5 F% |& _8 k2 d5 ]        }
3 h2 N) n0 x) E* p& l. M. Q1 D1 P- a
        return        data;
+ _, i2 g; _( ^1 b6 z6 D6 R( T# Z}
$ K% ], q, t2 @0 w, K7 A! D6 Q, N- H# J" M8 h
void        APU::ExWrite( WORD addr, BYTE data )
6 _4 ~4 k: D8 o" N5 O9 {- M6 X{
" T0 T9 {8 \$ g# P$ z2 _: \5 Z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 p6 Z; }# X- D+ s( \! q# P0 Q7 S
9 l% k% Q8 C& R# c. u        if( exsound_select & 0x04 ) {3 F' T' |* Y( d. T
                if( addr >= 0x4040 && addr < 0x4100 ) {3 e1 O1 \. j! [0 i
                        fds.SyncWrite( addr, data );& Q/ Y8 k1 [  \" n7 y6 }
                }
% }5 G7 `' J1 ]4 {        }- x- _0 Z- Z5 p+ g) {% V5 j
& p: _0 A, U/ Y0 b1 k' @- ~
        if( exsound_select & 0x08 ) {& D5 }( c2 U6 J3 \! K5 H% b* L
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 w9 E6 o. W. Q                        mmc5.SyncWrite( addr, data );+ X2 X6 k. i3 Q
                }
0 n6 }0 m5 `$ M- O9 R        }
) s* _( V* w6 j- n- O( l$ |}
; Y; Z: c" Z' [( E& j/ p, i
4 F, m0 Z! E$ X2 ?1 d1 |* hvoid        APU::Sync(); \/ `6 `. R4 s8 v+ I
{
7 x/ C4 R  ^4 {# P' t/ d: p' U4 q}8 c, Q$ g2 V1 M& Q* }5 J
2 E+ O" S+ b, ~) l& z+ T
void        APU::SyncDPCM( INT cycles )2 l0 Y) S  J- t/ l
{
& M% f/ k8 n; D        internal.Sync( cycles );2 h1 n" ?: \, G3 A. \% q
& i) b+ ?) o1 F: i
        if( exsound_select & 0x04 ) {* R6 S/ ~- f. T- I7 R' n
                fds.Sync( cycles );. q' w( V# @/ q. n% J- N% f: V) y( n
        }- M5 {# [# P8 p
        if( exsound_select & 0x08 ) {- P& \; x0 l4 R' _, y9 @1 B3 V
                mmc5.Sync( cycles );
, r1 c$ Y$ n0 J* S9 n1 z8 |        }
- N$ @  N& h% h! |4 A1 m}
7 `+ R# U0 t5 g* ]+ n" J
, w, A- ~- a7 `: _! wvoid        APU::WriteProcess( WORD addr, BYTE data )- I7 k) S2 {" ^. S, Y" g$ u8 K, e
{) D* Y7 J) Q! z2 [, i; z7 F8 F
        // $4018偼VirtuaNES屌桳億乕僩
. U1 a, e# E% ~. ~" {# q        if( addr >= 0x4000 && addr <= 0x401F ) {
+ T5 p+ f! O% ?                internal.Write( addr, data );
' H% P" p( R# w% x; ]        }
; k  A2 x& _9 j- a$ F& i}9 u. Y" ]6 W) `) t) _) z! }

' A: `' w' k  qvoid        APU::WriteExProcess( WORD addr, BYTE data )9 i+ C% [' A( T5 b9 g3 ?4 S; [" o
{
* y7 d+ \. q% v" ?* t& W  n5 E$ G        if( exsound_select & 0x01 ) {
5 A) }$ l- S# x0 F8 B! F1 E1 ^                vrc6.Write( addr, data );8 _6 n2 W0 }+ d& |9 g% Y+ P
        }- j" U& r: @/ l1 u7 C! w: c
        if( exsound_select & 0x02 ) {8 C" M* s1 o' y) g& z" S
                vrc7.Write( addr, data );7 Y7 A* f% w  y' n1 u
        }! ^# V. a6 N5 h7 f; u
        if( exsound_select & 0x04 ) {6 G' k: M* E. I8 t
                fds.Write( addr, data );! D  i: S$ o2 d7 a, Z2 \! Q- K! y
        }
! L7 C/ z( U$ N+ q/ r6 G        if( exsound_select & 0x08 ) {
# g# u$ p& h* d                mmc5.Write( addr, data );
5 d' @( A. G" f5 R* R2 L/ V5 r( R- U        }
( A3 b- Z) J2 S) e+ }        if( exsound_select & 0x10 ) {5 u; V7 `. T+ q; R" h& ]1 {
                if( addr == 0x0000 ) {# c+ {3 t2 v  v. o
                        BYTE        dummy = n106.Read( addr );+ j0 f! {6 i% B- K% I4 B+ v/ }
                } else {
6 n3 {  V# w' Y1 @1 S) @                        n106.Write( addr, data );" x5 G" K+ p5 R1 t  l
                }5 F5 \  F( Y! V( e6 ]" C
        }: K8 w' B  U( k, E, l/ R- |. u/ k
        if( exsound_select & 0x20 ) {' ^6 b/ a- J. g6 @- G# `, M4 h) m
                fme7.Write( addr, data );
4 ?. Z4 d- I2 x        }
$ ]6 G6 {! ^" T$ G}( B* D: i. W9 _! N! Y5 B

* m8 q7 c4 o1 j8 i. ivoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
* J) m" w5 M! Z4 C2 P{
3 y9 K, b2 P5 k$ ~* k2 XINT        nBits = Config.sound.nBits;& B0 q1 [5 }- n" r% X
DWORD        dwLength = dwSize / (nBits/8);. w2 ?# ~) y% G" x; Y  q+ H
INT        output;1 m# \# `! c5 H1 a' B  u& A
QUEUEDATA q;
, |, x3 Z! N; C# m  ODWORD        writetime;
, E! h' \4 w5 h* k% R6 K/ t4 L  m7 A# b' }* \  v0 c  n& Y6 A
LPSHORT        pSoundBuf = m_SoundBuffer;+ ~. w6 |1 f* Y$ Z7 b: Y8 D
INT        nCcount = 0;) |$ I( f6 R$ c' _  l7 w

; _1 g% F' e: |6 ^! Q( g! @8 q* pINT        nFilterType = Config.sound.nFilterType;3 J; @) S4 ^$ n# _9 y5 ]  Z

& }. a5 \# U0 f/ \0 m$ ]8 J        if( !Config.sound.bEnable ) {2 N0 `5 y" u8 G0 Z2 l/ h, B' X
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );% B  B: a# r& D
                return;2 P1 o9 S. j0 e
        }
, r! A2 x( |6 C4 v' \
6 v' F: N* V: d$ ]* h' G        // Volume setup
( j3 a2 a1 g/ k' R1 k4 b" h; g        //  0:Master: j2 C: |/ \+ I% \, t( _8 M
        //  1:Rectangle 19 e7 q  ~" M. f' d' Z' T. }
        //  2:Rectangle 2
& T* }; E$ r0 b' t4 w$ L        //  3:Triangle
  a9 w  I3 K( V- m7 `# h9 Y        //  4:Noise
, Y6 u& p# m2 s' R0 `. E( H: l        //  5:DPCM
, l1 g" Z$ F6 l        //  6:VRC65 b. ~6 C% m$ w
        //  7:VRC7
& r" U1 S4 v7 Q$ k        //  8:FDS, A5 _. @5 s$ D5 O5 D# z# A
        //  9:MMC5$ Z7 F& l6 T) {
        // 10:N106
1 e$ e! k  w0 k9 Q' z9 ~        // 11:FME7
( y0 O6 C8 D) f# C# q$ m4 q% Z/ f% R        INT        vol[24];/ y, B2 \  T& m, d* O' x
        BOOL*        bMute = m_bMute;* R/ y& c+ c/ c; p" E3 {
        SHORT*        nVolume = Config.sound.nVolume;6 O& y% T/ O8 H3 n+ {
4 L6 J* h% B* u2 J- y8 x) K. }
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
" W- s" o, @' B5 P( C" S  q/ t! X: ]" Z5 R% M2 O! y
        // Internal# |" D; i1 q, c' P
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;0 n; Y# Z2 D0 [9 r& _3 z
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;8 r. J# I$ K& z* K, D+ H4 A
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;4 c3 J$ q# m7 Y* a
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 f! g4 k, u- I
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ ]" r+ }  n# Y  G

1 c) c- ?  R0 @6 I& ]6 I- C        // VRC6
, L1 ]; b& {' C9 ?+ A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 s4 l0 }& Z  [, U, i+ ^, D
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: z2 B5 [$ T+ G/ B
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# s: {+ ~! u2 v# F, P9 Q: s& X9 n
1 ~  Y4 a  A" K! c        // VRC7' U9 k& }3 {! X
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 s0 c1 _6 X3 c7 K8 H# D' k9 }
( U6 y/ s( M- P# S5 l8 d( u        // FDS
, q! E4 o( B: n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
2 n1 i5 ^' Z; w. z/ e4 z$ a, F9 w% N
        // MMC5% k  q9 x% C; i- q; J8 v6 g9 ?( P, d
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ z4 Y  |" N3 F3 ~# l) M
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" X& z3 k; @1 f7 u5 ]2 q; W' G        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 n% V& C: s! B8 G; F2 S

% o( d+ R; C% j6 I! E+ h        // N1065 M3 z' i9 c3 J- G, q  ~. v
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 J3 V% H% \9 Z* I3 S        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" b, C) Z8 R* ]; D% s" i1 @6 ?: i        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 J* `# u. I2 u  d% }, b        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 g. j( d$ b5 n& u* k$ z# y/ }
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) d( p: o8 s: T! x        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: L5 s/ m. o) Y% p' i
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% F, H, o9 N+ w! x        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# G: y) F: u' K( a! L: M: K% L
: v; \. a' p. ^- i2 ~
        // FME7
7 S. ~3 v. s! R4 t+ Y: b        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ X8 r% Z) m* t& ~8 A$ ^3 X5 C; I
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;* b) J$ K# G6 t0 ^% R4 q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& ~- Y+ N. J7 b8 `$ X6 B
) z  {. i+ Y2 X' _//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 `) `' x7 `1 l4 L( k3 A0 I5 b
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. v+ w0 C4 {- t1 ^/ j; y- a
/ C( D! b& l/ e3 J        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ M$ h( Y% K+ S) }% ^
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {8 q3 A  F6 K1 o( Y" g  \; a
                QueueFlush();: y; |# B  Q& Y; X: @9 \. F
        }4 Q" `- y: x- l

% b1 m0 \* U- a* z! F        while( dwLength-- ) {% ^6 t% t% p8 e0 B/ h5 B
                writetime = (DWORD)elapsed_time;# G; @0 \9 H) ?

5 K+ U6 V" y: m! W/ \                while( GetQueue( writetime, q ) ) {" l: y$ f/ S% z, }
                        WriteProcess( q.addr, q.data );$ p/ g* w  n$ t) b# a8 }
                }
0 V0 \1 V( I* {8 h/ C. y& I
9 o. b  S: O( Z* [  Y                while( GetExQueue( writetime, q ) ) {# |1 N& s) J* {) I+ a$ u0 m# i4 X
                        WriteExProcess( q.addr, q.data );
0 S: o- I/ \! T$ h+ x  v                }+ \# O* w" u3 ~4 J# ?3 ^* Q
2 S6 ]: _7 v6 A
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" a; I" J' g( [" J  L
                output = 0;
" {5 a% w) r. h3 o8 {$ }4 {/ v                output += internal.Process( 0 )*vol[0];. X4 |2 c9 T# L
                output += internal.Process( 1 )*vol[1];
/ F# R8 `% s9 q$ X3 P; A                output += internal.Process( 2 )*vol[2];
9 w8 N1 |! v2 [; _+ Q8 \4 w0 r                output += internal.Process( 3 )*vol[3];
, E7 D6 s' |$ C" E; u' F                output += internal.Process( 4 )*vol[4];
% g4 @1 v9 {$ z5 U. k( L% p9 \8 b
# ?; C0 ^$ L) H' s* {! z! F# e# @0 r7 z4 e                if( exsound_select & 0x01 ) {" z- ~  y/ l, G
                        output += vrc6.Process( 0 )*vol[5];
1 S  M4 d# h9 `8 A7 m' Q# M  G3 h: _                        output += vrc6.Process( 1 )*vol[6];
) L+ f" o6 M0 l% z2 i                        output += vrc6.Process( 2 )*vol[7];9 G, }2 s  ~8 G7 z1 X2 Q9 `5 K
                }6 ^5 P; t- M' D: _" i
                if( exsound_select & 0x02 ) {8 ^/ Y3 u% M7 p# e# q, p
                        output += vrc7.Process( 0 )*vol[8];
: m! C/ @% s- k" G$ k' }/ D0 ~3 d! ~                }, M. F) I( M* ]) O7 T8 S
                if( exsound_select & 0x04 ) {
8 M2 w6 u: B, p                        output += fds.Process( 0 )*vol[9];  m9 L8 C7 O7 {$ Z4 a- Y  l
                }
6 q. `  ^  h; j" V, Y+ G, |6 r6 S                if( exsound_select & 0x08 ) {
4 s; ^+ R; f- H2 `, @/ d4 k                        output += mmc5.Process( 0 )*vol[10];; O5 S0 G0 J' z
                        output += mmc5.Process( 1 )*vol[11];
# P! \+ T6 P: A+ U                        output += mmc5.Process( 2 )*vol[12];' l1 _1 J, v, i
                }' Z5 l( t+ e) O$ U+ {
                if( exsound_select & 0x10 ) {
+ `+ t, N6 |5 ?( K                        output += n106.Process( 0 )*vol[13];  ]$ W3 r* O  y. s* ]
                        output += n106.Process( 1 )*vol[14];: n' o+ d% a- J5 Y
                        output += n106.Process( 2 )*vol[15];
! b$ S2 p5 ]; y* L3 n! I# m; E9 l) P# R                        output += n106.Process( 3 )*vol[16];' a' B3 [: e) y: U) o) }- w
                        output += n106.Process( 4 )*vol[17];* J  W* O" f3 `) `' P
                        output += n106.Process( 5 )*vol[18];
' T# ~* Q# g0 s' a* F                        output += n106.Process( 6 )*vol[19];
, w0 A6 F  P$ t, h: Y4 T                        output += n106.Process( 7 )*vol[20];9 N+ i9 C! V$ g1 L0 _
                }/ O4 Z: I  H, Q9 {; ?/ \
                if( exsound_select & 0x20 ) {2 n) i6 o1 m, ^2 f) ~
                        fme7.Process( 3 );        // Envelope & Noise& D3 J( c! {$ X) i
                        output += fme7.Process( 0 )*vol[21];
/ N& P# H1 p3 z9 m/ y9 K( h- D                        output += fme7.Process( 1 )*vol[22];0 ?0 h6 K( A$ J3 N2 m) Q
                        output += fme7.Process( 2 )*vol[23];
, U$ c- t* B) K7 T, W                }% x: {0 W0 h; B% o2 ]
9 v  j) \* F5 E, ]) w  F
                output >>= 8;
+ L0 ~. x5 m: P. H/ Z8 J
, Q* N9 [" U* _' f+ X+ Y                if( nFilterType == 1 ) {
" |6 A5 D! Y! w" k0 U$ T                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
; k8 `; U/ l) \                        output = (lowpass_filter[0]+output)/2;
1 c1 X$ o) V9 T5 H% y4 x                        lowpass_filter[0] = output;3 N( Y; ^1 d+ Y' n2 t
                } else if( nFilterType == 2 ) {
0 N3 J: g" A3 i  [$ n( V                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
, r- l7 A. a$ w                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: Y' c5 J6 ~, \8 q* F- r/ p                        lowpass_filter[1] = lowpass_filter[0];
6 M) b" A- F) @. a6 _9 Y                        lowpass_filter[0] = output;; c3 I) _: c1 W- E& G& D  k+ M
                } else if( nFilterType == 3 ) {' N7 f, ]) p2 J8 T
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)9 r# f6 ?5 t& N9 y6 ~
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; b* s% `9 s& j2 x1 U                        lowpass_filter[2] = lowpass_filter[1];9 ^! x* _1 h4 Y: L* ]6 k
                        lowpass_filter[1] = lowpass_filter[0];
) N/ T& [: x& H% [                        lowpass_filter[0] = output;
' E( k$ Z$ o' |: u7 j7 m# b                } else if( nFilterType == 4 ) {
; q, M4 G! W! D( p: c! u& W                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3): Y+ R: ?0 ]0 U, Y0 m
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 {0 y: ~3 S% D" y
                        lowpass_filter[1] = lowpass_filter[0];* n; Z3 W/ m/ N$ w) r+ K9 M
                        lowpass_filter[0] = output;# U8 A: z2 J! h# ~; v" V$ K
                }
) M! a  ~6 L9 H* M1 x4 g" ~1 e# z+ k8 w5 K  u- j. p. d9 N7 Y
#if        07 g; |+ u% d' a" A0 c/ `( F
                // DC惉暘偺僇僢僩1 Q$ Y6 t6 k9 s" X* e
                {: K. s4 d- p; P! b. r) P
                static double ave = 0.0, max=0.0, min=0.0;$ }2 C- l' ^8 f8 v" }. M
                double delta;1 `* H) m7 c" ?3 {8 {. q+ y
                delta = (max-min)/32768.0;7 }9 j! p7 h. k- }
                max -= delta;) W5 D- U$ l" n" g
                min += delta;
; D  A6 x" z! h                if( output > max ) max = output;0 j9 }* _( L# h. p, I% l! r2 P
                if( output < min ) min = output;+ a3 P( h/ \' a) Z7 s
                ave -= ave/1024.0;* V, s6 L& ], ?8 i" a- Z* q4 L- S
                ave += (max+min)/2048.0;
9 L; h5 \1 W( |$ @& l* D* o/ }                output -= (INT)ave;
5 G+ Q- g1 g5 {                }
" S# e" v0 P4 T$ D7 G* @( R#endif  u# h: l! ?0 c8 M7 k
#if        1
6 N& a. G  U6 v6 T2 N5 F# p                // DC惉暘偺僇僢僩(HPF TEST)
  d& }1 G8 e% v4 D' `! \                {
& t! m5 V3 T; ?& ~//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& y! W' Z# x/ @6 Z- f                static        double        cutofftemp = (2.0*3.141592653579*40.0);2 r( b: P- |! k. S- A7 L
                double        cutoff = cutofftemp/(double)Config.sound.nRate;. F% }" J# Q3 p' C; ]$ E
                static        double        tmp = 0.0;5 I7 Y" [( N/ e' c, \5 F' K
                double        in, out;( O5 A7 ^/ W: M1 y
4 m: H( c( c- T- W0 j- V6 H  a
                in = (double)output;6 Q9 o4 w+ i$ v+ ]* l# i
                out = (in - tmp);
9 J/ L5 J7 c  A* B* G- R                tmp = tmp + cutoff * out;  l  T! v7 Q8 j6 L" D, Z

3 o$ y$ C* j6 u                output = (INT)out;
( U% f, u: S+ x/ i- w2 P. s1 E                }& H  V. _; ]5 x% Z: i( U" h- {
#endif
& V  H( M* L  f! T- ~#if        04 J* b: W9 i- `0 B, J) g% z9 G$ y; o
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
: F. w: q. S* u0 E, a8 f; p                {% I) J" [* f( a5 y) B1 H
                INT        diff = abs(output-last_data);3 S% C# T& p2 B8 ~8 Q: X
                if( diff > 0x4000 ) {
1 W" \1 b% F! D9 ^3 d# A                        output /= 4;# b# D# U) D4 w- L/ s! k
                } else 0 ^6 I) n3 z9 |* X" q
                if( diff > 0x3000 ) {
+ w/ @5 E8 r9 @* ?* z: X                        output /= 3;
" `- ~% A2 `) X. H                } else4 M- `9 e/ e# K' }  P9 G1 c
                if( diff > 0x2000 ) {+ h$ l4 g: x: M
                        output /= 2;
) ]2 _& O! q* g  i3 j8 w                }/ S2 c# R( f6 f0 c1 b& k
                last_data = output;2 n# ]9 R  H+ ]$ {! v
                }9 \0 x  t. G2 C" x- h
#endif* t7 j, \8 p2 \5 [; f" F: a
                // Limit
* `4 G* ?5 Y. |' f& J                if( output > 0x7FFF ) {+ x) L# m. Q% {* y1 J
                        output = 0x7FFF;  I/ `  ]  b* s% ~" [" I1 f# t) }
                } else if( output < -0x8000 ) {" R* x  a4 v7 o
                        output = -0x8000;
) ~' @/ r, a! k                }/ d) u7 e3 ~! \. b+ u7 i

$ O# }, g7 S0 t5 v2 y7 }5 g                if( nBits != 8 ) {) H( V$ P' D3 H2 I& b
                        *(SHORT*)lpBuffer = (SHORT)output;
; S$ e* M, H  j, d1 U4 d  N                        lpBuffer += sizeof(SHORT);! ]6 l+ ^6 C1 R! @3 X1 N  j
                } else {
9 Q. O: f! k+ B* w8 o                        *lpBuffer++ = (output>>8)^0x80;* i8 E+ p/ U9 Q6 R! p. e
                }
8 i. E7 J' n* R) Q! P8 o4 E8 u% j' N+ D( |+ N8 D9 b7 [
                if( nCcount < 0x0100 )
' N8 Z0 m+ k9 O2 X+ a                        pSoundBuf[nCcount++] = (SHORT)output;
& \/ a: G3 i7 x( ?# ]4 R. d7 p* ^. b
//                elapsedtime += cycle_rate;
8 K6 `+ r; U5 t& F- A                elapsed_time += cycle_rate;3 }& W' K5 V$ ]3 e5 g2 Q/ e' L2 A
        }
# O! w. o. }, S  q3 T* h
+ e5 g7 `! G+ n& d; V#if        1
9 ]( S# M; V5 C6 k! u        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
! k) Q( {0 R# R3 j/ H4 ^                elapsed_time = nes->cpu->GetTotalCycles();" q( a& m  N4 F* Y& _
        }( G6 m' M% W' J$ I% x
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {' ?  t4 N  Y2 |& o- k
                elapsed_time = nes->cpu->GetTotalCycles();
* |! T" `4 d4 L! p4 d0 \        }
1 D5 E  S2 d5 z#else
1 ?  p) e& @7 v( z        elapsed_time = nes->cpu->GetTotalCycles();
7 h& o5 _' F: h  d* u4 W#endif
7 V3 N. G( A) V% x' `3 d2 z}
- K) v9 M, l8 F9 D- u/ q8 A; v( D* f5 S" S1 F
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
& m0 n! ^) Q  z7 O: @INT        APU::GetChannelFrequency( INT no )+ Q- Q. S4 E0 H3 y/ ~4 f
{* H; ^0 @9 ^' h* O8 f/ U" E
        if( !m_bMute[0] )
/ ~: x- K! T, C& e- R( s                return        0;" }; S5 z2 e/ a! A* L6 Q; G" y( [
# _0 F+ w5 ^9 z3 }" `
        // Internal7 e; A+ s9 {+ n/ l0 M
        if( no < 5 ) {
, u/ P3 A# [7 b% y; c& e                return        m_bMute[no+1]?internal.GetFreq( no ):0;
6 d/ [. F, d+ `9 I8 q        }
+ y4 }+ `/ z- A8 ?- P        // VRC6+ a0 z- t, R7 W
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {0 |$ E. L& V, g
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ X. a  {: Q( r7 C" r- k* O% ~& C
        }
( Q& q) g/ J* R& x2 n3 p9 u! s        // FDS0 }% W" N  u# a8 E! A
        if( (exsound_select & 0x04) && no == 0x300 ) {+ m7 ]8 P# h' D: E& L
                return        m_bMute[6]?fds.GetFreq( 0 ):0;* E  l. N& I: q/ D3 c+ m
        }
5 j, v% s# O2 ~; H4 S        // MMC58 k0 k* O9 E, b' }- _
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {$ m2 \6 O2 S" {5 [! A$ v- a) h
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
/ s+ J# M* d" P        }) v, w( G, O! e. t! \) i7 k( b
        // N106
1 w3 r) A9 b0 _, n        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
5 J; Q+ ~) M1 g- r/ y( E! b                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
3 k8 W) l; W4 k+ K3 r( r        }
7 N" H9 s6 S# z8 ^, B        // FME7
% L6 B, _" @$ d9 l2 X        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {3 J& v$ @, X9 X/ w, S( ^
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;7 K, p8 o* S; E3 r, F
        }
; m4 m4 \/ P! O/ p0 k4 {6 M        // VRC7
1 a8 u1 m1 _. S* y        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {# v6 a9 X# w9 H5 n; Z9 Z
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ W5 i1 U9 E6 ?* R
        }. z1 c9 \) d. l6 V* \, f- ]
        return        0;* q# f  @& B9 |  Z- H
}6 I. i- C8 Y1 E$ |5 ~: f

- G8 s9 l# a9 V7 ~// State Save/Load
4 C! O( H6 u0 \void        APU::SaveState( LPBYTE p )- ~/ b( c" `: ?2 x$ p  m9 ^
{
0 _2 y. j: d0 W5 a. w: ]! w' O$ t#ifdef        _DEBUG
" X8 Y0 p) u: ILPBYTE        pold = p;! f2 D) B- {6 K# @# f
#endif
  M' o$ v; D$ r) V" P. Z1 R1 ]% T5 ~3 Z$ x! q
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞# Q# i3 M+ D  Y+ d5 w
        QueueFlush();
, T/ N, q1 B! t( s# b$ B. {8 N7 l( g& l& U3 @! U
        internal.SaveState( p );
! X* R. |$ Y. Z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding6 F+ g. X5 [! w( a, Q! P
- m' {+ E: g0 n' B+ n
        // VRC6
/ X: y8 b6 p; _, o3 t' b% _        if( exsound_select & 0x01 ) {9 z0 r* N6 B. P
                vrc6.SaveState( p );" \0 S+ h2 s1 c
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! @, q# E. [$ b5 J5 z: E% x        }
! K" t  f4 x3 ~! y  Y        // VRC7 (not support). g/ R+ k! A/ j: ?
        if( exsound_select & 0x02 ) {
! d; T/ n2 [4 r1 L) q2 y7 J+ b0 h                vrc7.SaveState( p );
1 k; U  o5 E5 ]- C9 h0 r% F$ `4 d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 N8 c" t6 Y- f" U3 z- k" G, B% f* S& n
        }4 s% d* [* _* f4 F
        // FDS
+ \) [- d' f5 i- p! q0 ?9 f- z        if( exsound_select & 0x04 ) {5 U9 P4 N5 e* W- b& z
                fds.SaveState( p );  y' t0 {" U' C( t2 A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 C' t  F! U$ r+ R0 ~4 M. C
        }& h- E% r$ h# @
        // MMC5
  z5 `8 R5 ~& @        if( exsound_select & 0x08 ) {
8 q0 r5 V8 \& F0 v: s/ C                mmc5.SaveState( p );
" W: j! C/ i; ]1 [                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# |+ k# d' b* Z
        }
) s" n% `+ ^5 X        // N106
+ p) f5 w+ g( g# r, n        if( exsound_select & 0x10 ) {- x  q$ h) s5 {/ C: Q3 _
                n106.SaveState( p );- t4 b+ ~* t5 N5 F" S
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) a" b- b# k8 ]) d
        }5 Y3 [% W' g! \& N
        // FME7
# Z: x! B6 q) Q7 y, X3 ]        if( exsound_select & 0x20 ) {' ^' s" X) P' n# `5 |  d. ~; y
                fme7.SaveState( p );
  A$ x$ H2 _! q5 Z1 l; d& {                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' z0 x! h. u/ r9 e$ G
        }- [& F8 |" N: H/ U* l
5 Y, D: X3 u; g8 N+ t  A
#ifdef        _DEBUG
  }: @: c4 J8 W; H. lDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );; B9 i) ]" F' F; i
#endif
) e( B+ f$ p2 n# C1 A8 m. O}8 _; m* |" ~; s+ ?  X# Y# Y8 ~
* H! b5 i7 A* A2 C# ^8 f* ]
void        APU::LoadState( LPBYTE p )8 c  b# n6 ~) }' D3 B' f% \. }
{
3 Y& a* t( \( W# n3 t9 j        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ s% Z4 G) m; e$ b6 @% T
        QueueClear();
( Y2 h" s3 J  P& f$ _6 ]$ U# ]& U, B
9 W6 K( u" }" j1 E- `$ S/ _9 u: j        internal.LoadState( p );0 ?* O0 \" c9 e+ g1 P
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 w# J; P) b) V& ^6 G1 ?1 L

* Y( ?  T; q4 C$ D& L        // VRC6
( @/ @) J* J. [        if( exsound_select & 0x01 ) {, R& R' b3 ?2 e/ U! T9 E" O
                vrc6.LoadState( p );
' ^5 @  m5 f- L- ?( w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% i& `- J- w! D' R' e, q# q
        }- l0 V+ T, ~6 ^) J
        // VRC7 (not support)
7 Z7 d0 @8 ]1 c, Q' k' L9 n$ C/ x        if( exsound_select & 0x02 ) {
1 J! R, w- s# A1 G6 v( Z/ G                vrc7.LoadState( p );0 J# a( M4 \" i4 n) B& P
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: d! E. q/ |  O& D
        }- u0 s5 j8 c8 t& V# x- {' M
        // FDS- E7 A5 R4 _. |6 P
        if( exsound_select & 0x04 ) {4 K/ H& _: |5 f( q
                fds.LoadState( p );* ~; p% e( |' e
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding& v2 i* N* d: Z3 a* p
        }+ V5 R# h9 i; ~! H. z, h/ U
        // MMC5
. p, w$ o& g/ i, O) q  x        if( exsound_select & 0x08 ) {8 H* R# t/ Y3 v: w
                mmc5.LoadState( p );& g! V/ C; L0 O& I# ^
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& J0 t# T$ E& g9 A  E
        }0 ]1 o( _) D- |
        // N106
# [# O. x% E' a* |3 T! P5 e        if( exsound_select & 0x10 ) {
- e, h# P4 Q  r3 `. u% f7 C  ]                n106.LoadState( p );
5 [( L" M9 g- w5 _                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ P3 ~& B1 h$ W4 L/ E7 E- g        }) z9 `( p- m, b9 l$ q8 Z, P
        // FME7& d* U& ]( s3 T. M( G( R+ o
        if( exsound_select & 0x20 ) {
1 n: F6 [( C' a                fme7.LoadState( p );
2 W  u6 a, \+ W# V& h" B. h                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding7 T( W+ L7 @% O0 K, a
        }
5 }( `& [9 k  K  g}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
5 o3 a4 X# ~; R可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
, m: |% }, B9 z感激不尽~~
) ^: `0 B" g; d$ T  h" {0 F
恩 我對模擬器不是很有研究,
4 s" y2 X0 [% y3 \6 y, A. M5 Z雖然要了解源碼內容,可能不是很困難,$ T. H# E" h: D" v2 o( u; Z) _
不過還是要花時間,個人目前蠻忙碌的。
9 k, q& j4 Q. l& ~" _9 p; \+ S( a7 {0 D  d2 `; r1 |7 j
給你一個朋友的MSN,你可以跟他討論看看,
4 _. R6 ?% W2 m他本身是程式設計師,也對FC模擬器很有興趣。
( Q' o' W' _9 I; J4 d0 [& G1 t/ ?* W5 J' s, @5 H, S7 ~
MSN我就PM到你的信箱了。! e- D0 [8 `  {, Q1 Q+ P

" Y* L# p5 d( J5 T3 T" t% r7 n希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
9 D8 d8 g5 u( K% G  O+ G  W# w呵…… 谢过团长大人~~
* C, r) ]5 S6 w+ k# ^

6 @0 w" B0 C+ u/ c3 P1 R; E哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 & L: ?" `; ~( @* V. ?. x
团长的朋友都是神,那团长就是神的boss。

+ E5 k( ^. l0 M' k哈 不敢當,我只是個平凡人,% Q! d! k; J4 Q
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
; y: Y1 K; q. h4 {( Z1 f: O1 g6 S+ lZYH
" i. D! O9 \6 ~$ CQQ:414734306
7 B" }8 k# F5 Q* V7 NMail:zyh-01@126.com" P; l) A) B2 o- H+ u# E7 u& h% y
7 L/ M* k9 H# N2 u% ~+ h$ t
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 E7 ~9 P8 U; Q4 Z再次对团长大人和悠悠哥的无私帮助表示感谢~~
& j4 c) ?$ n2 D, P* b3 f: `
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 16:39 , Processed in 1.076172 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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