EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
5 C: y9 g; @9 _3 T: [5 V, }. fPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ C! U* S, g! r' h" S$ S  E6 \" i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( k: n0 j- h' I% T9 V3 ?
这里有相应的模拟器源码,就当送给大侠了~~/ u/ W9 Y) d1 D' o$ q" T( ]6 M
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
; p, L" @+ w" M2 |能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。6 _* A& i& U1 ~7 Y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, e# K4 j4 H& |# Z+ L  f
这里有相应的模拟器源码,就当送给大侠 ...
1 X7 ~  {0 u% L& m0 `. B
聲音部分(Audoi Process Unit = APU):6 P1 V8 _/ z) H# h& V/ f1 q
.\NES\APU.cpp8 i% z) Q6 U# D& I! j# I( t
.\NES\APU.h
( C2 T+ K7 t3 @$ B) @* i1 D( G( [/ v( W$ Z+ {5 f
: V! t$ ~/ c0 h6 i3 M8 W3 y
影像處理部份(Picture Processing Unit = PPU):
+ M* R. i* h: G& S( ].\NES\PPU.cpp/ ^, v% O! f  X; Q
.\NES\PPU.h
  t1 Q6 U$ w& Z. ~/ H, U. O! i( X. a1 c' _+ g5 X6 P6 U
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
; m2 }5 Z% l* s& A(由于很多专用术语和算法机理都不明白,所以看不大懂……); z3 Q1 P+ C) L+ C
//////////////////////////////////////////////////////////////////////////% o; M8 a0 v4 E  P+ @
//                                                                      //
& h; r7 c; x! T$ z) }6 L% ?//      NES APU core                                                    //
9 ~/ n- ~1 {8 ~5 J3 R' n//                                                           Norix      //
8 z5 o- K$ F; T- H5 M& {//                                               written     2002/06/27 //8 h+ V4 A) W; j
//                                               last modify ----/--/-- //
2 k1 \" l% Q: T( g  E//////////////////////////////////////////////////////////////////////////
' J( L( S5 N6 e2 c/ n6 B#include "DebugOut.h"" W0 `* {0 b, U0 c
#include "App.h"
9 [& X  M1 L. C5 I! Z#include "Config.h"# W: u: N  y# x2 e8 f7 o& F2 |* _
" I; b) \4 f! T- E( P
#include "nes.h"! M) L: _4 G. R8 n- X% }( _
#include "mmu.h"
* Z% X7 N+ ]& a$ {. S2 p. N#include "cpu.h"3 k1 K! i; ^0 n" u8 f
#include "ppu.h"
. ?8 j, `: F% U! q8 \, k#include "rom.h"5 C& i1 z! V) ]: T' N! v
#include "apu.h"! U) {$ m9 z6 N! |! ]' \& M3 \

0 i/ @: _2 i+ q# O% |9 s& d* G" K- b// Volume adjust* k) y/ i! a) Z/ d/ P1 S" r- u
// Internal sounds
* b. d' @7 @0 {#define        RECTANGLE_VOL        (0x0F0)- b) |; b, C8 s/ @1 c  T; o
#define        TRIANGLE_VOL        (0x130)  M3 K/ J& }0 m6 K
#define        NOISE_VOL        (0x0C0)  P! R$ I' a2 }. B
#define        DPCM_VOL        (0x0F0)
5 a0 g$ E: @* l/ Y: r// Extra sounds2 D( {0 Z, X1 q. T& h' _$ g9 ~
#define        VRC6_VOL        (0x0F0)$ R0 }7 {5 c: ]. }
#define        VRC7_VOL        (0x130)+ y. E  `3 S- v) t: K$ u- h
#define        FDS_VOL                (0x0F0)
9 [8 [9 {( I+ ]. f! q#define        MMC5_VOL        (0x0F0)
0 U2 i8 t  q* ]4 X#define        N106_VOL        (0x088), w; c8 ^4 [# U4 i9 @
#define        FME7_VOL        (0x130): S- I! r( }; x+ i5 A

; i9 ]  l! P8 L+ b$ n. M. |, m0 bAPU::APU( NES* parent )
1 @! h1 \; _3 M% s- B: |{
, |. u% X4 j- `; K- p. C" y        exsound_select = 0;5 H3 ]' N. ?0 ?5 z( L. W& f

1 A3 |+ N0 E. J, l* r        nes = parent;
7 E) f5 Z* s# U2 J        internal.SetParent( parent );
" e& `7 m# d, y- W  ~8 ^4 k1 }6 v0 Z4 F9 h5 s- v
        last_data = last_diff = 0;
4 `) \3 S+ I# U: |' o0 V$ V! Q3 l5 r' s! ]/ v
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 ^/ M6 Z+ }$ D  m) t8 ?7 e2 g5 \. ?/ ], Z6 z+ Q( M& F8 W
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
& \7 q  p& E& z% M, ?$ V        ZEROMEMORY( &queue, sizeof(queue) );& z1 n* Z" P( T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );; I5 U% u% b4 Q$ ^1 s* T, Y: b

8 Z* A6 T  c& G! h- s4 A7 @        for( INT i = 0; i < 16; i++ ) {7 Y* R; t; Z; ~6 S
                m_bMute = TRUE;$ v% v1 w* A. Y" R9 k5 ~2 {  p% x
        }8 i7 h4 O# l. b
}# ?. ^' |/ ]: r9 I0 y# {

5 ?" W' }) J2 AAPU::~APU(). [! p8 Z- G( W1 T1 P$ A3 v5 [, A
{' P) O9 N3 x1 {1 n/ g3 t* ]
}8 Z8 k/ J! @" c5 s3 ?. p

7 U/ j# |2 j% @5 pvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
5 y% w" t9 j& q* M; o# t{, `! U- v% t! P+ f
        queue.data[queue.wrptr].time = writetime;4 _+ C! d& M) c0 I) \
        queue.data[queue.wrptr].addr = addr;" c1 V6 t$ A8 A) J& {
        queue.data[queue.wrptr].data = data;
9 i9 M. H9 n8 A; a8 w" c        queue.wrptr++;
# o5 W# D) ]' W1 J( Z' d        queue.wrptr&=QUEUE_LENGTH-1;1 J$ T$ T; \: {: j0 L% V* l
        if( queue.wrptr == queue.rdptr ) {' S7 I6 g( _! v# b# b, k8 A$ l% V: {
                DEBUGOUT( "queue overflow.\n" );
/ v2 E  P% D7 y5 ^/ l) T        }) N  k8 K" }  N- G0 M
}6 C. Z7 v- m# A& i5 Z$ N

0 A! e9 r+ w; ~0 k" V: c- g" C3 cBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )" P" l1 L+ |% u
{
3 W4 H7 }/ j4 F2 g8 d- i        if( queue.wrptr == queue.rdptr ) {
( N4 y/ L- Z1 Y! F- Y& r                return        FALSE;% x  M1 w" f9 ?/ T
        }1 C# c& [+ v* l0 t& M. Z
        if( queue.data[queue.rdptr].time <= writetime ) {. d6 B$ R0 C& ?" E
                ret = queue.data[queue.rdptr];  S8 S$ k+ f( g3 L: u
                queue.rdptr++;
1 B9 N2 G5 A# p- R5 ]                queue.rdptr&=QUEUE_LENGTH-1;
2 E# ~, f( T: F- d                return        TRUE;: t1 C5 q( W( r0 \, I. S; C" ]
        }' q- }4 Y6 p6 `8 g6 l8 F) j9 c
        return        FALSE;
7 l: t) q* Z6 D" _: K6 q* N}- e. T: O; E- h* d& r8 }

$ Y' F# {$ F, d0 l2 z# Fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )' r: Q# ^2 t9 `* [; K$ b
{$ J, Z# E1 m0 {* n, c9 e6 j1 c* k
        exqueue.data[exqueue.wrptr].time = writetime;
# o. Y5 l7 v! c0 N0 t; n8 U        exqueue.data[exqueue.wrptr].addr = addr;! w! h! f- [4 @/ k+ {- [
        exqueue.data[exqueue.wrptr].data = data;2 v+ E) }, ]+ P9 t* ^7 E# |
        exqueue.wrptr++;
' H( s: I' L* J        exqueue.wrptr&=QUEUE_LENGTH-1;
% l2 O% A* }- m  ?- y: e        if( exqueue.wrptr == exqueue.rdptr ) {, Z) _2 e9 I6 [3 I
                DEBUGOUT( "exqueue overflow.\n" );( @$ |# Z  n+ F1 h1 @- i
        }
( w; c; \- c' ^}  M7 T% q1 k1 K& h# M8 h7 P
% g: H# l3 E# U+ x
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )- e, [7 F: K  J
{) H8 S2 I) S( X  E9 |* q% z
        if( exqueue.wrptr == exqueue.rdptr ) {* u! Y+ I3 s# q# _: X7 e7 S/ }
                return        FALSE;
1 l8 {+ J# g6 @+ a  s        }  c$ k% n& B7 r1 t* T" b6 ^! R
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {1 s1 x( h6 O9 f7 s% u
                ret = exqueue.data[exqueue.rdptr];
* R# d1 P6 B: t+ J7 U. Y( P" f# b                exqueue.rdptr++;
$ k$ J$ v. u( l- s                exqueue.rdptr&=QUEUE_LENGTH-1;
. g; X2 Y: i3 t1 L/ C                return        TRUE;
  h# M% w) Y# z1 d        }; z- a* ]8 l% a7 B7 W3 t+ Y0 G
        return        FALSE;
# y- R, j" }5 Q/ _4 R) d' H}
7 B5 C& _! V9 c' r* Z# q* F
( K+ n5 |# Y! V$ g; Qvoid        APU::QueueClear()
$ X" w+ c3 F" q9 E) m+ b  O9 h{
5 A+ V+ `# d7 A1 l        ZEROMEMORY( &queue, sizeof(queue) );" w/ D, m& H4 m# C$ q9 t
        ZEROMEMORY( &exqueue, sizeof(exqueue) );! X* _6 m* N8 G" C- Z
}  J$ z7 `: ~; T' B) P
6 i0 \8 W4 I7 A
void        APU::QueueFlush()
; n# V. h  E' H{4 o$ `0 K; T$ i3 W
        while( queue.wrptr != queue.rdptr ) {# r' d2 _- Y- s8 m' V9 }: y: @
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );& H0 B2 m& F3 Z" F: v' \! _6 Y
                queue.rdptr++;2 C" ]$ N6 R3 h- O7 y
                queue.rdptr&=QUEUE_LENGTH-1;& \7 w+ _1 I1 S1 A
        }0 o4 c+ {* L4 _) ^
$ X2 C9 A  g, z) J- G3 |& S. c  R) |
        while( exqueue.wrptr != exqueue.rdptr ) {% L# B) s: Y' X; b3 Z
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. o$ B1 u" V, f, P* M4 R, n  Z5 }9 h5 i
                exqueue.rdptr++;
7 v7 z1 Z# q3 a8 h/ Z$ s3 ~' T                exqueue.rdptr&=QUEUE_LENGTH-1;
/ A. s9 T# b5 d- W, p! s/ D* m        }
3 ?( `) a7 V( V7 X; a7 w# G}' v! Z: Z5 q* e- I) Y8 q( M
. ^$ W' w1 @" E
void        APU::SoundSetup()
4 Q) e2 R! J* b% w! E{; D8 w4 a# J# k
        FLOAT        fClock = nes->nescfg->CpuClock;
; W6 L6 X6 j. n4 s6 N        INT        nRate = (INT)Config.sound.nRate;6 u9 ?& [5 V; [2 }* J# S
        internal.Setup( fClock, nRate );
; T! z+ }" G& d9 o0 U+ m8 N        vrc6.Setup( fClock, nRate );6 H# T! S3 Q+ O# r# f: Y. s4 [8 i
        vrc7.Setup( fClock, nRate );$ a# K: b3 @; L% A, V0 l
        mmc5.Setup( fClock, nRate );. \+ y: D; e" H' o  M. n+ W; R2 v
        fds.Setup ( fClock, nRate );( N9 f/ v" |" r7 n$ v
        n106.Setup( fClock, nRate );9 r! l) C8 O, O" w: N' A
        fme7.Setup( fClock, nRate );$ u  f" m% `; Y$ o* A# \0 i" Z5 }' }+ y) L
}4 D, t( @! B1 D7 h6 j. p

$ O$ c( y$ F# Z) U' M! M4 Svoid        APU::Reset()  A7 F8 S! j9 O  w$ D
{5 `. j. B7 r. Q8 C
        ZEROMEMORY( &queue, sizeof(queue) );
% n( M% c( Q. [1 j# N. G        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. c. f2 F/ o% L' A( Y0 Y  r, R; H( ?- ~* q7 O$ ^" U0 F& n
        elapsed_time = 0;
, f9 ~0 T  y7 [0 [2 i; A1 @1 {% p. G. Q$ A1 O6 }/ b$ A
        FLOAT        fClock = nes->nescfg->CpuClock;0 D& S' v& Z3 R) q, [
        INT        nRate = (INT)Config.sound.nRate;
$ H3 B1 z; n1 s1 h& \( C        internal.Reset( fClock, nRate );; O* O7 J: N5 j' H7 R
        vrc6.Reset( fClock, nRate );
( |0 C$ K9 \. s9 c9 x! L, p+ X  q        vrc7.Reset( fClock, nRate );; o3 X5 ^& t3 n0 u. l" P
        mmc5.Reset( fClock, nRate );, W; s9 o+ d, g7 K5 y* C( S3 o: G
        fds.Reset ( fClock, nRate );1 p/ u1 c- E) E/ ^7 b3 f; J
        n106.Reset( fClock, nRate );
% ^  ~/ ^1 ~2 b" T: @" D        fme7.Reset( fClock, nRate );
8 G% O3 Y/ ]% u8 E% x- e& X: Q. r2 u! C; b0 z% L
        SoundSetup();. z) o" R8 P- K$ l& ~& t
}% \  G* G- v2 `* p' Y4 U
. s) A" D( F0 k. [3 e
void        APU::SelectExSound( BYTE data )
2 b' w  r3 j" S# ^) R{
# }$ A' b: Z, C1 j3 c; q0 y        exsound_select = data;; E* z+ ]+ T  t* h  l! H) n# w
}2 _6 o+ r! H& x6 Y! D3 V
6 o# K8 ^; _- a) f6 K
BYTE        APU::Read( WORD addr )0 |& |0 m- y- R
{
3 m. b, n4 \& J. @: l2 ^1 Q9 k        return        internal.SyncRead( addr );# ~( `1 o) H7 `' }9 h
}( A- f/ t- d* }% u5 C
9 ~8 \0 M2 D8 r
void        APU::Write( WORD addr, BYTE data )# `: }& b5 p7 [- ]. n4 z$ {( A; r
{
1 h9 [/ _% v2 [* ]% d: a        // $4018偼VirtuaNES屌桳億乕僩. |1 R/ P5 I+ A) G" d
        if( addr >= 0x4000 && addr <= 0x401F ) {# k# n- W8 ^+ P
                internal.SyncWrite( addr, data );
# ^5 [, H$ Z) w- J& e                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ b- K' r8 L* G. q: W4 y" \7 b        }& C) u$ J8 u: {* r0 B* Z+ R
}: @3 n+ j0 c. C, p
. j" `4 ~2 Q3 L0 v/ C2 A
BYTE        APU::ExRead( WORD addr )4 ^+ u4 ]! F9 ~2 W8 d( ]. \
{* b) _$ s  u4 I* `
BYTE        data = 0;
3 Q* K, m- D6 S5 Z. j6 g+ D% }4 b" j2 E! M" A7 w4 u  m4 I
        if( exsound_select & 0x10 ) {
0 ^8 r7 Y: `$ j( l; ?                if( addr == 0x4800 ) {
3 w2 y1 r) W9 B$ [& h                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
3 |) @& C7 X3 V" Q4 Z                }/ T" u6 w# P9 k4 j  o# }) @
        }
4 G) o0 C& x1 w        if( exsound_select & 0x04 ) {
4 }9 o6 Y* X" n* ^! n% I; U                if( addr >= 0x4040 && addr < 0x4100 ) {' w! D% O; K: V; ]3 U0 @# W% t
                        data = fds.SyncRead( addr );( y& `  y  z4 [( k3 V" B# H2 S
                }
9 O* }% c1 ^3 Z0 s        }
7 l3 d) K; d1 p6 W1 a        if( exsound_select & 0x08 ) {
3 `. z" M( h/ g# a6 n                if( addr >= 0x5000 && addr <= 0x5015 ) {
# F8 @, e" ~: M% |# z! z2 E                        data = mmc5.SyncRead( addr );9 d2 v7 B6 ?$ Q1 V6 a
                }, |% }9 n6 ]2 v& ^
        }
& ]# U: H* d% A  g; F% G5 `4 l; {' b& c
        return        data;. z4 G2 O4 d/ J& `6 m
}
: X. B3 z; n/ p: S8 S8 ]$ o" t  s
- h9 n, {+ Y/ X7 O2 k0 ^void        APU::ExWrite( WORD addr, BYTE data )0 ?' l( G  {# }8 [. h7 q
{/ j' t6 z+ ?, A6 A
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );( N% r$ R/ e0 E6 B6 m' P# k3 u7 W8 q
- I+ s& s2 v4 G; n4 d& h9 W
        if( exsound_select & 0x04 ) {5 O3 \+ u4 t' e" w9 f7 W" w! J
                if( addr >= 0x4040 && addr < 0x4100 ) {
0 ?) }0 A3 s8 K9 n* }                        fds.SyncWrite( addr, data );
9 t% n2 ?- @# b: {: a5 @* ]                }; `4 X( b6 h3 R1 G
        }
  t; B% b) x/ `4 a; ?3 N: J8 N8 \. z- O$ H
        if( exsound_select & 0x08 ) {8 U8 }$ A# D* u6 |, g2 x6 ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" R9 @% R) H- V                        mmc5.SyncWrite( addr, data );% R5 M& R" r6 J, Z5 Y
                }8 U" @' }& m9 N$ [2 S/ ~6 [7 Q' r
        }
( }  C( }. Y$ R- T3 K}2 ?" N2 x! l" c3 D# ]* u+ k4 {
: Q% a! S. C% u
void        APU::Sync()* I% i/ f/ R5 r* @# u1 i
{
2 {' J( N) y4 z5 E}4 z6 R3 R2 w9 k; {$ h/ l' p+ T

2 v) r8 R7 |+ V( M. O" _* Vvoid        APU::SyncDPCM( INT cycles )3 f% q9 o0 a% ], b+ r# v4 z
{
) S  o: ~6 K/ V# P        internal.Sync( cycles );6 b! F0 b' z  P- K6 b* ?7 j9 Y
' f4 A& e* G6 P* e0 i) L$ L+ X
        if( exsound_select & 0x04 ) {
7 @5 l1 y  }) q) e- r; `                fds.Sync( cycles );
: Y* _3 `! S, R        }. Q" F/ Q. J1 b
        if( exsound_select & 0x08 ) {, S( O& Q8 C$ n
                mmc5.Sync( cycles );
9 f- F- C5 L7 \0 t5 Z        }1 e2 c" i- T; S8 j/ k
}: }8 S  a" \$ k. \" w+ B9 {) k

8 _9 ^  h1 @! ?$ {: R4 |% \void        APU::WriteProcess( WORD addr, BYTE data )  k& Q8 A% s, R# F6 ?* {. D# V
{
  b1 D6 a' l4 V- H+ A& ?        // $4018偼VirtuaNES屌桳億乕僩) K+ c" K0 W% C5 C
        if( addr >= 0x4000 && addr <= 0x401F ) {
* s: R* u+ e6 h9 J  i, g% ^& E                internal.Write( addr, data );  N- E/ a! t& X$ Z6 ?
        }
( a+ E, q* I! t) ?9 B}  s3 m, k- F& c- Q

0 i0 O; D! G' E  ?void        APU::WriteExProcess( WORD addr, BYTE data )
8 P% c& B( _! [! a3 E{' t* n$ i( j  {3 d2 x
        if( exsound_select & 0x01 ) {. Z9 `. l+ J4 K
                vrc6.Write( addr, data );6 {8 P+ l1 ~8 z% ~  y" z% b
        }& t) r# k7 L7 ^5 j+ l' S
        if( exsound_select & 0x02 ) {
% K9 B& W9 ^/ D0 x& @                vrc7.Write( addr, data );
; U  g# A- `4 S4 [5 T        }5 ?1 {% S+ n7 ?* O6 T' a
        if( exsound_select & 0x04 ) {% U" v: h2 Y0 b3 E- ^  B
                fds.Write( addr, data );
) [; Q9 P4 f; a! o1 D        }
6 A. i. K0 e9 B4 b2 s( p; H        if( exsound_select & 0x08 ) {
& y% ~8 ?: ~$ J0 {+ \                mmc5.Write( addr, data );5 U7 [# `# _$ Y( h; d
        }
9 ~8 p- z9 k& [9 k        if( exsound_select & 0x10 ) {
6 J) H+ x9 T) r# `% t6 `                if( addr == 0x0000 ) {* A1 F+ Z% A: G  f$ ?: u9 x8 B4 e
                        BYTE        dummy = n106.Read( addr );
4 f3 _/ o: g: C: n                } else {
; i; b" r7 |) i' E+ F" z$ T8 {' P                        n106.Write( addr, data );: o, ~% G3 U# }# L! @% p; e
                }5 e3 i5 M& C  g
        }
/ y2 j( e8 }5 A( o7 c        if( exsound_select & 0x20 ) {0 L1 i4 x: y7 Z4 G: u
                fme7.Write( addr, data );& o1 J; L1 a4 J; }1 e" K. k
        }* o  S1 ?- [, c& ~- m" s
}$ p6 ?4 J* d' ]% ?
' l8 n: S5 B/ b- W
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
+ m5 ?- b: [+ H6 W" i  ~{
# M0 [! W) w: `1 q) @1 L  ~1 ^0 bINT        nBits = Config.sound.nBits;
5 U# }  c) j0 M( T  {: P7 vDWORD        dwLength = dwSize / (nBits/8);
0 ~6 [! D* s5 m) N* C1 DINT        output;& |- |7 z* Q  m
QUEUEDATA q;
8 c1 W, P0 h6 ~# MDWORD        writetime;
3 O& N+ K) |3 I+ T2 c) d8 W" U( ^# J2 p! h2 V! Y& \
LPSHORT        pSoundBuf = m_SoundBuffer;3 X, K% D! l: K  H6 k5 L7 G
INT        nCcount = 0;
+ Z; q) g9 t; f; L$ S* U3 A5 A' b6 m* ]6 X. \6 p# i% c4 I$ j
INT        nFilterType = Config.sound.nFilterType;4 R, A/ j& v# s! s3 h0 ]

. s+ ~6 j% P+ q        if( !Config.sound.bEnable ) {1 k4 y: i5 K! A5 p0 j8 A% m4 |
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
- Y0 g( B9 l0 j+ {( B& [9 V% w2 v" |                return;  Z9 g" K3 L: O- R2 h
        }
# M& G- U  P7 f$ k0 C, d2 B/ H3 t; R) i2 X* |4 c
        // Volume setup7 w: e! P& Q  i2 G4 ]
        //  0:Master
3 p3 w, d6 V  y: d1 w' G2 \9 S        //  1:Rectangle 1
4 n. r8 p9 ?8 Q, o  n! _        //  2:Rectangle 2, Z" J1 C7 n# k8 Q3 {! g" y
        //  3:Triangle0 t9 w+ L: H8 Z7 x( V
        //  4:Noise
6 h9 a9 v% b3 g: D4 R% H& Z1 m        //  5:DPCM
) h4 a3 O: u0 H6 R7 g3 Q        //  6:VRC6
- _5 r( k  b% |" k, v        //  7:VRC7
( j% G; b+ G* `        //  8:FDS
& z$ l( c# F4 G- ^; B3 w2 O# p( V# d( `        //  9:MMC59 M6 ]' e1 \* E
        // 10:N106
7 y$ e5 h  D6 E  r        // 11:FME7
( g' j# u( n! Z$ W; V) Q        INT        vol[24];
3 R* I2 c- Y6 E/ q6 t% Q        BOOL*        bMute = m_bMute;
5 q% R- b) w4 l  Q" H5 F        SHORT*        nVolume = Config.sound.nVolume;- G& _/ J1 \8 e; c+ r/ J
6 v# v: \; a- \; f# ]6 n
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- |7 t2 ?# ^' C) O* C1 y
2 L7 J) i9 f0 H- A; Z
        // Internal; Q7 O  S. I& E. ]* S
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
% u8 O" I8 ]; o0 U( O- m: q- S        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& H4 n' y' }( }! R- ^! p8 c; s0 T        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 ~9 V) ]+ k+ j" K. V
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 N( X* T) E/ a  b1 M( J0 x: v8 C$ n
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;2 Q! Z) c+ {1 f
4 b5 ?0 r( j: r( \" R
        // VRC62 S( T( v) A6 c- W2 _
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: g3 [- ^, I& W( E        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# j# |; |/ \. \" r% c5 P
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* l) Q6 e7 v, G

- E1 B0 T3 s4 P2 f$ F) q2 }: ~6 Q        // VRC7
. ~0 C1 ~, H/ P0 j        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;9 V  y) G/ j  V! K1 r
5 ^3 q$ I) O6 S% D4 _
        // FDS
# Z# e6 k  i# z  H. ]( W9 S5 G        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: }9 O/ v# Q2 o, M1 y2 |. \% |7 l! J* h1 n4 ]4 U7 R' Y9 ?
        // MMC5) [- Y( a2 g6 @/ Q6 d
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 R, v+ u& b, x" H" C
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 z, `9 S9 i% [. Z# b' L4 C) e/ S; Z
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! N( p6 G$ x# V* K- W9 ?4 L7 b% R2 n+ K
        // N106! h- X3 B! }$ D5 E% x
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ m4 U8 }8 q0 z, B" E! ]$ r; u+ V
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 u1 K; [9 e, z# f! R( _
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" N3 G2 w+ T3 R8 Y/ D8 a- N
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ ~# B- z. ]5 r1 v  q4 A        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 a6 T% J: j- m        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 f( m# z8 h8 }/ `. ?( V
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 U3 ~# e4 l) K* z6 r* _        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* L1 y8 e/ c2 w. T* f9 Q' m( c! i# p* ~. K
        // FME78 t& G9 N7 j6 I# v- |
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% {" O* t- Q6 K  K# m$ k
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ s* r1 e6 I+ K3 f0 `4 Q        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 }% K& x$ G# `
$ e9 ~% `: r/ `' E) b" @! G
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;: {8 n8 u9 I: k5 O& E, N
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;& G) f& p7 |8 s- Y

8 a; f9 u' D; [7 M' s* F        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟& [/ _& n# u- U1 o6 N/ {! Q
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' Y# K9 _, W' ]. V' H6 {
                QueueFlush();
% H0 _  t8 @  d  Z# z4 r, k        }
! S- `9 K" {) e
. \2 b/ F3 O! D$ H$ o7 W! s5 P0 }        while( dwLength-- ) {6 ]# P- Z0 g. s% J) s
                writetime = (DWORD)elapsed_time;1 C2 c! i0 s9 y; F1 C. H2 {6 H& k8 n
& ?! z3 z* t) a1 c1 i) [
                while( GetQueue( writetime, q ) ) {
; L- Z; ]$ q* [) m$ |7 r                        WriteProcess( q.addr, q.data );, V1 L  {- `+ A% V( X# j% d* [
                }8 Z- D0 `6 J5 E1 p

% x# Z, t9 f- f0 P& U                while( GetExQueue( writetime, q ) ) {
: M% u6 b2 i) b+ U$ W                        WriteExProcess( q.addr, q.data );. O, c8 p$ n7 g* f
                }
4 r# X: [3 Z. h2 j1 ^: ]
4 L) Y; O: S, Y! _" p8 F1 x                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7, Z4 I0 L: u& x0 k* F; {+ H2 b
                output = 0;9 D+ N  C+ B2 q/ K: l
                output += internal.Process( 0 )*vol[0];' m) y) g" M  M
                output += internal.Process( 1 )*vol[1];
; w6 x/ [  s8 W" l) h% e                output += internal.Process( 2 )*vol[2];. ?' Y4 i) t: k3 f) r+ r2 u7 M& w+ ^
                output += internal.Process( 3 )*vol[3];
4 C# M# z  K1 ~3 B- S, O  x                output += internal.Process( 4 )*vol[4];0 G# y& g9 W; }6 R% m
* Z' }3 T, v5 b( @% K0 K9 z
                if( exsound_select & 0x01 ) {
) ]# g4 H+ z" m) [) y, j8 \( \                        output += vrc6.Process( 0 )*vol[5];! G& L7 E1 v) F3 ?2 a$ X" F/ @- {
                        output += vrc6.Process( 1 )*vol[6];
' P* G# @2 e9 x, C                        output += vrc6.Process( 2 )*vol[7];
* S" M; h; n$ ?$ O# q0 b                }
# g# s* l) J" A- C- ]9 b: B6 C5 P$ [* G                if( exsound_select & 0x02 ) {( ?2 Z3 ]" n' d4 v7 t
                        output += vrc7.Process( 0 )*vol[8];, H# C& U7 R% |/ {  X! u
                }
. p! d' G( i4 c; p: Y                if( exsound_select & 0x04 ) {# Y4 O, v# e% k# C  W! k5 \: w- n
                        output += fds.Process( 0 )*vol[9];
, ~3 G. [5 w) G                }
; h* P$ E/ Q5 x8 s* o% k# w                if( exsound_select & 0x08 ) {" k5 [" u+ K4 i
                        output += mmc5.Process( 0 )*vol[10];: j! z- k, D& Z  g
                        output += mmc5.Process( 1 )*vol[11];
1 ?; U5 i' l6 C* I  ]1 Y0 L                        output += mmc5.Process( 2 )*vol[12];2 Y. z- f$ Z7 \6 l* |/ n+ e
                }: Z) Q9 `0 J1 k: f  z( c; m
                if( exsound_select & 0x10 ) {8 Q+ d* J5 L: d- _; k6 i1 Y4 a
                        output += n106.Process( 0 )*vol[13];
) p6 r$ X5 ~. l- q! Q. i                        output += n106.Process( 1 )*vol[14];
+ p, G: [+ T0 t. j' k                        output += n106.Process( 2 )*vol[15];
) R- h, c( Y, H* V/ l                        output += n106.Process( 3 )*vol[16];
( }) E! A, Z% l! g, r+ ~8 t- I7 f                        output += n106.Process( 4 )*vol[17];4 X6 f; x7 a. t' Y& P/ H( }
                        output += n106.Process( 5 )*vol[18];
1 n$ o/ D1 ^- \7 a3 M) t& S                        output += n106.Process( 6 )*vol[19];! q) `6 R2 O# b; V
                        output += n106.Process( 7 )*vol[20];+ a' Z- [4 y/ p4 c
                }/ [" o; H# O+ O6 e' K5 r' d
                if( exsound_select & 0x20 ) {  i0 o; ?& |; i- W, P& J" }7 l
                        fme7.Process( 3 );        // Envelope & Noise
0 s9 E0 T/ k) t  t' S                        output += fme7.Process( 0 )*vol[21];7 A# {) N( R/ o$ ~/ L( ^  J& Y
                        output += fme7.Process( 1 )*vol[22];
! [; q& q, N# M% Y  o% s                        output += fme7.Process( 2 )*vol[23];
! A, F: N1 I1 k  k& {2 d( G4 n' F                }3 {8 }: s2 h3 x9 k1 k
7 W$ y2 s$ r( U7 ?# {; Z4 I$ o9 P
                output >>= 8;! T: l1 P9 `8 X) \! _( x2 w% i$ }
& R" G; T3 D; S" g3 N; m1 j2 L
                if( nFilterType == 1 ) {
  p" U2 l! I! U5 X4 Q: `/ w                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
$ H: X5 I( @4 {5 Y- E+ O# O                        output = (lowpass_filter[0]+output)/2;
- U. P  Z" J  u) |3 Z8 H4 e                        lowpass_filter[0] = output;! [: K( p) C2 u$ ]
                } else if( nFilterType == 2 ) {1 \2 y0 ]8 }! L7 x) O  v2 _
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)) \& S/ P) `; q( O
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
5 b) B+ l; b4 T; H3 n                        lowpass_filter[1] = lowpass_filter[0];2 ^# M+ W8 _4 h+ Q
                        lowpass_filter[0] = output;# \$ D0 g& T# g6 F1 [  j
                } else if( nFilterType == 3 ) {0 ]5 i, k- b7 R" n5 a) K' H: u
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)- ~3 D7 \7 |0 K( |9 K: y1 |
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
; G/ j' K# R7 \+ w# V. W: b                        lowpass_filter[2] = lowpass_filter[1];
. i2 y: v* b4 F$ c- Y                        lowpass_filter[1] = lowpass_filter[0];: `8 w0 m# _2 m1 P& X7 W! V& I
                        lowpass_filter[0] = output;- L  B1 j* T: M
                } else if( nFilterType == 4 ) {' A0 l% K1 o' c- q) s
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& p# _  q0 [7 l1 L                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
; n/ z' P6 Y% l' _/ }& c( q0 M, G                        lowpass_filter[1] = lowpass_filter[0];, B; F. k' V- B3 g. R. \
                        lowpass_filter[0] = output;
8 B8 x7 [2 \- c% S; n' I                }
2 z, p; g, y6 N) f* S
" s+ M6 l: N+ h2 ~#if        0- _, P- b- K9 `8 [3 V9 M% h
                // DC惉暘偺僇僢僩
2 q( E5 ?! C; T& r8 O  Z* r$ s                {, m5 V) G" V0 R5 |9 S* H
                static double ave = 0.0, max=0.0, min=0.0;; r1 R" r. O& W& [: B6 v3 [
                double delta;) |9 v$ T/ o( Q& l
                delta = (max-min)/32768.0;
0 p. K9 c. G2 N. t+ \- ]5 x                max -= delta;
0 \; s+ B+ o+ |9 w+ m                min += delta;
/ ~3 y0 \  s9 z1 T                if( output > max ) max = output;* Q# R$ N, d( J- Z
                if( output < min ) min = output;5 u  B, P" n' r6 @9 Y: a/ [0 \
                ave -= ave/1024.0;5 R' N& e1 B" g$ v* K  b
                ave += (max+min)/2048.0;6 n! Q  ]6 l, Q' H
                output -= (INT)ave;
  v* b9 w' ?) X' Y5 Q! z                }
0 L2 \; L' E2 m8 G* @* k#endif) K2 }) C( v0 r5 |; N2 U
#if        1  N) j& U8 ~) W& N3 }' i3 t9 \
                // DC惉暘偺僇僢僩(HPF TEST), E8 O8 L) h. A
                {
+ N2 K# V8 \  v9 ]6 S3 q5 ?  j//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
3 R) n" ]8 u1 \! q+ |" X                static        double        cutofftemp = (2.0*3.141592653579*40.0);0 r; ?& M5 e+ k: w+ n! R8 R$ ?' ?
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
1 S5 A+ r9 u3 L  V, R+ V) p( M                static        double        tmp = 0.0;, b' Y# D4 Q% @3 d4 k. ?( M5 F1 e
                double        in, out;
6 \, b; {3 S" Q; I+ I* |: E( \* `4 Z% e
                in = (double)output;: \; c: y5 Y# p+ E# ]; e! W
                out = (in - tmp);( j/ ]1 H0 F% G( X1 E# f
                tmp = tmp + cutoff * out;- X& G5 @3 r, x% P
$ x) l  w/ D' q2 r) d/ x+ o) I
                output = (INT)out;; s2 c% H$ J$ d4 t
                }
" _9 l1 f7 o, m  H) p% X#endif
( T' p, e6 {3 Z6 k% R( \- l0 s#if        0
) ~* g0 w, U4 ~* _                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* B0 ?. n" Q! ], K* N$ J3 W, U                {$ e! ]! ?3 d4 O! W' [
                INT        diff = abs(output-last_data);
* d: R0 C% D1 O' h                if( diff > 0x4000 ) {
6 M6 _; l  v# E5 u                        output /= 4;
" m# q2 o# q+ ^: P                } else
/ C- A/ F* z3 I0 U- l' {$ j                if( diff > 0x3000 ) {* y- `! O( R, l# i8 L
                        output /= 3;. F$ z* N$ c: b2 T0 |
                } else$ t9 V; V- p! p
                if( diff > 0x2000 ) {0 F9 N& Z' M8 X3 W6 _, ^; ^, _
                        output /= 2;
3 t7 k# M6 {" V! j( |                }
! P, E" t. i3 f2 R" ~                last_data = output;
& C1 n7 ?2 f  f/ l% L                }, m# M" I" M1 f( b2 ?3 Q# B
#endif' Q; m2 d( d) M. ?8 Y
                // Limit1 s* t0 U+ w* d7 S. e9 b& S9 g3 ]
                if( output > 0x7FFF ) {
+ ~5 |4 v" s3 `9 A1 x. w                        output = 0x7FFF;4 K3 v. ?, `" T9 e1 B0 J
                } else if( output < -0x8000 ) {) d! B3 D8 m; Q; `1 y
                        output = -0x8000;' N: ~: g% G/ b1 l" g( o
                }; x6 E/ m% r9 b2 X& B/ t! w2 f# d
% \+ \1 V( D0 Q2 \
                if( nBits != 8 ) {. K+ L. p; a# W
                        *(SHORT*)lpBuffer = (SHORT)output;2 X) p0 ?1 P) Q) j! V
                        lpBuffer += sizeof(SHORT);+ p$ p- c3 {0 B! ]
                } else {
3 l' V: }' y3 n% W( a' O                        *lpBuffer++ = (output>>8)^0x80;
7 ]# q" y0 M* @& j2 B. ]; q2 u3 i                }- j1 ^8 i5 Q2 j! Z7 |# y3 n; S6 `
4 _8 T8 g- {# b9 {. J4 L
                if( nCcount < 0x0100 )
0 x. }+ f+ P1 q% f# @                        pSoundBuf[nCcount++] = (SHORT)output;7 @) h) b+ z, s+ L( O0 \) R

, V4 R' B- Q5 t9 V- @//                elapsedtime += cycle_rate;
* J% j4 u1 Q! v% U; L2 c1 A% e  G7 k                elapsed_time += cycle_rate;
+ F5 B# E" R9 ?, n        }
4 u3 r3 F# k: B' D3 X* s! r/ \3 K$ _, u% H# D" O+ v
#if        1
  I- b* r: S) g% Y% Z* F$ J        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {) }/ N/ g  o+ e2 ~
                elapsed_time = nes->cpu->GetTotalCycles();
; P; k: g% x" p/ y        }# _& h. v' x, I0 h' O& G  {
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {' K2 A: [" M) n. p5 ]* d; L4 \; S
                elapsed_time = nes->cpu->GetTotalCycles();9 M) X9 g6 S0 F0 |8 Z1 A
        }
9 s! V) u3 a& j6 o* W% ^% F( K#else
. @( @; u2 v) ~% G7 F/ w1 D        elapsed_time = nes->cpu->GetTotalCycles();( a/ b+ _2 C9 v; d; W( Z  N
#endif" y$ \6 s! Q( {" W- Z
}
# ]7 s+ x( p. A$ M- f( V% H6 F  b  b1 z, g# M
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)" M$ `% C8 F9 n" d5 n- P9 J- n
INT        APU::GetChannelFrequency( INT no )* r, g: C1 Z: M9 y) {7 n
{8 w" k! ^0 J7 o* ^- s7 p, y
        if( !m_bMute[0] )0 Z. X7 C- D- I+ s8 u) f0 I
                return        0;) [0 W" I, a9 L
9 [* s9 n6 S$ F. P$ a6 d- N
        // Internal' B# }, c& e. e. U' {4 J' `  B
        if( no < 5 ) {$ \" P9 S+ v6 `" Z4 A1 h
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
/ }4 u' o. L9 x# ^6 M, Z        }8 G$ J8 D  E; F, y7 S5 C/ ~
        // VRC61 B. z& F5 y) }" \  J* s  U0 G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {& U* g# m9 i6 G# i8 [+ n5 ~- C
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;% h( O/ m% a! R7 `% }' `1 A
        }
, \- g0 k' b5 k8 A# x4 v/ K: n        // FDS  t+ j- n8 Y% F1 Z2 U# O
        if( (exsound_select & 0x04) && no == 0x300 ) {
. y5 q( l! e8 `. E- P$ ~                return        m_bMute[6]?fds.GetFreq( 0 ):0;
; L! O' n& Q) Y; J) \) E2 r* q        }
8 X* m% A  I! A0 R: f" p: ~8 a        // MMC50 }) L' Q: T) Q9 B$ V+ B/ B8 j2 N
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, E# p$ `& H9 i, R+ k                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
3 d- Q* \0 Q" d% W' E3 B        }- ?! L) A  l" D3 _& S
        // N1060 `# S7 F: G3 u
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) {, V3 m' |9 I! i- N! T
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" E4 D2 G# c) P; Z8 N5 p; v        }; T  }, l  P% P8 [9 V" G& y
        // FME7. L; ^1 z3 {5 d7 q( |
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {  E! g. N# C4 Q+ A
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;/ E5 s8 @5 K8 t( w) o2 s
        }
9 L) i7 a. e% J9 r$ j        // VRC7. g  k. P7 V% }+ t' L" J
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
( Q" g8 n3 b" U* x- @% K! j                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
, B/ N$ ^- y0 A        }
# j! s5 ?' d+ R: F2 A        return        0;/ j  c) g. t4 v' w
}2 F" h/ h/ i( I( I4 r3 l
# G" [' h$ K3 _5 y
// State Save/Load/ b( y" Y' f% S5 a  O  f" O
void        APU::SaveState( LPBYTE p )
4 N2 F* h! v; G" p, D3 S{
. T3 \+ h; w* {( ~#ifdef        _DEBUG
) B' k( d; t) r" K# f4 GLPBYTE        pold = p;
  a% b# x5 Q6 }9 v4 D#endif
9 a, e% a1 l' P  g7 w: u6 V# h
1 a6 F& q+ `# t  v        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- v1 N5 d5 u$ n$ [& M
        QueueFlush();- h) R% R8 e5 W# W+ w5 h, b5 T1 C

% D7 B! W8 O- x1 j( p' j$ z( `2 Q        internal.SaveState( p );. X7 N! Z, c, t+ z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  W' I0 q/ B6 z0 D2 E
' I8 ]6 x; W( h2 H4 j        // VRC61 }) j# X" G0 K( {. q6 h2 ?
        if( exsound_select & 0x01 ) {
# r4 [6 ]0 v) K5 b$ y# L, W                vrc6.SaveState( p );
" J2 t0 E1 l8 r- {                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 N8 K( ?0 G3 V0 f6 C1 I- L# E        }
7 V$ W) x/ k* [( `8 K6 }        // VRC7 (not support)
, n! j# R8 a2 V7 N, }        if( exsound_select & 0x02 ) {
' V; X  z: a. h7 H% ]2 _. S2 R                vrc7.SaveState( p );
( v* D* w9 V: I5 a% X9 U                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% t/ i& `5 L( c        }4 I/ k2 e/ k) N- y6 Z7 p
        // FDS
/ |! F* _+ Q9 `- T3 v* W        if( exsound_select & 0x04 ) {
' S3 e6 }: H7 e: a                fds.SaveState( p );4 p/ Z/ h8 ^, C1 l( G
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding$ \7 ]% w5 J: Z3 b
        }$ `# @  ~" G+ W& y& O9 B
        // MMC58 d: X+ \  A. o* v4 E, }
        if( exsound_select & 0x08 ) {
  P" o, V/ ~: p- _" D1 V8 K                mmc5.SaveState( p );4 g+ X+ G* l: c2 ^# t
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
0 s0 H& i6 x+ X) ~# o$ P        }9 [4 r% h6 S% I8 K
        // N106
: u! p) M; J$ K& S( z2 ?- s        if( exsound_select & 0x10 ) {
+ b3 d3 [$ V, Z: q6 M. ^                n106.SaveState( p );1 r* P$ f# E8 l' r* [( t, L6 a
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ T, F! m0 C  n) Z. y
        }6 d2 D. O" u1 u/ I5 v. ^9 u
        // FME7, t+ `1 a. `  J2 B0 M! w
        if( exsound_select & 0x20 ) {
2 S. W1 `5 ^/ H/ ~                fme7.SaveState( p );! l1 l$ Z1 ]+ M( K0 H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding- u* A0 j" i$ S, D
        }8 C% x, f' I& G) X
# M+ }. x! @* d
#ifdef        _DEBUG
. w. C* ~: F8 x$ ~2 U6 y7 n* @( jDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );" T. N$ q0 _" `
#endif
3 H6 T$ D7 l) d+ i# C* o}
5 Y! i  b6 @' A" m! X9 i. ^4 C9 r& L$ V# g2 Z. L7 w  Y) k
void        APU::LoadState( LPBYTE p )
0 m6 L' X8 Y( \3 e{
6 Q2 j6 p' q' Z9 ~& S        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 M% B6 T6 p8 [- ?, ]4 [- d        QueueClear();
% U+ G) Y" \6 |7 ~5 B1 V
, o3 Z* s, K8 ?% q( ?/ D7 x& Z( c        internal.LoadState( p );
7 o+ b+ g3 R4 C1 e8 ]9 _  }! N        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding8 @+ u8 \4 T1 ?! n
( e8 D; B& X1 `; @' D* b- S
        // VRC6
: [2 s& t- q; M3 F9 v        if( exsound_select & 0x01 ) {3 I3 a: m( d5 @7 {
                vrc6.LoadState( p );
4 {: |! t1 E7 G/ W8 t                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
3 j1 T% F& j0 v) E: O        }
! K& g+ F. i! \* a3 P# n& b) ?+ E6 X        // VRC7 (not support)2 B- r2 l9 x/ q4 G# g- c
        if( exsound_select & 0x02 ) {
  A3 v2 k, `+ }2 h2 f                vrc7.LoadState( p );8 O1 }5 P6 A3 ]
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding; P  A% v2 b% Y
        }
( y( j: Y& Z5 m( c' |        // FDS! a4 l) x/ p# Y! t( G& g7 ^! f
        if( exsound_select & 0x04 ) {3 E$ D5 [4 U# I; _" z" `
                fds.LoadState( p );- X6 q% B5 N8 W" b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% k( ]/ C+ S: G& w& v+ {2 v( g4 ?
        }
$ \- G- e. w0 [( F4 s        // MMC5
$ J5 A& L* l% e' z2 e! K9 Y5 Y% ?9 b        if( exsound_select & 0x08 ) {
; g9 O" r2 J" ?4 l  S/ K                mmc5.LoadState( p );# F, s# D( A, y6 ^3 v
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 o! u6 |, P: e/ @2 i! F' i! B        }
: n! y8 m# h9 \+ m9 U2 `: ~7 B, X        // N1066 `( a1 h+ l& V+ D7 v( ]
        if( exsound_select & 0x10 ) {0 D( }9 B/ R1 P7 Z
                n106.LoadState( p );" N+ Z% {% V4 S8 R3 L
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* e; u  H2 p& w5 F        }
' q7 S* j" o' b; G& b) v6 X        // FME7
2 S1 B7 k! C$ L) G" i/ m9 K" B- A        if( exsound_select & 0x20 ) {& y) U, R# I1 U; C
                fme7.LoadState( p );
7 G* ^( n9 B7 h6 v/ ]2 [' `                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 K. Z# v/ L, n& A7 ?) G        }
* c5 @% I2 C. ?5 ^& K, E2 |}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 3 C, X, @% [5 ?) }& U! f' y  ~
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. u% E. \( I' Z. f感激不尽~~

: O, D9 I& E- v/ N" H恩 我對模擬器不是很有研究,
7 n2 }3 E# B( m9 p雖然要了解源碼內容,可能不是很困難,& q* B, Q5 Y, l' |
不過還是要花時間,個人目前蠻忙碌的。
6 y* A2 Z) f: e+ }  c
5 q7 A2 I3 O/ k# ^& h8 M! w. i* e/ u8 i給你一個朋友的MSN,你可以跟他討論看看,
  r- s/ i. T0 n5 V他本身是程式設計師,也對FC模擬器很有興趣。$ C: Q6 |- x9 l  H
5 |' Z* W( k% c# p5 I5 |# x& J
MSN我就PM到你的信箱了。% X$ e% ^8 @3 K
+ S5 y* ?  J7 A- G' Q' \
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
- S' R& M, Q; J) F5 T1 q" F呵…… 谢过团长大人~~

- a5 k6 u% |& [
. }" m7 y2 {3 t哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 U' j9 |8 s: v: _  E团长的朋友都是神,那团长就是神的boss。

' Q& t$ F) ^6 p1 G% V哈 不敢當,我只是個平凡人,
7 A: f" R6 U9 A( M2 Y. E2 u要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙. h- P3 P0 J7 `$ l6 M- O" {7 x" s
ZYH
& C' _5 X" m# H5 j. U" C& ?1 J) T9 ]QQ:414734306
; d$ @! P& @# r, CMail:zyh-01@126.com
; G& i$ q6 M4 ?: l( D  ~
$ t. C. ^0 g3 p/ f8 ]他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 : m" I/ E5 l, Y1 r8 A
再次对团长大人和悠悠哥的无私帮助表示感谢~~

: v) i" L, F) o% W1 E$ l: |0 l2 ?不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-3 15:18 , Processed in 1.068360 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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