EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。( T2 Z6 X% ~0 T& E" `1 \
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! }  ^  O/ B+ O% n
这里有相应的模拟器源码,就当送给大侠了~~
' o6 I/ R1 \: Mhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
% ?0 D$ c: t. b能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。- R( f( h& m; ?' O- i6 M* l
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
5 q9 q. Q2 ?7 H) e, Z0 T( [这里有相应的模拟器源码,就当送给大侠 ...

$ s* v9 k, t+ {; a: x聲音部分(Audoi Process Unit = APU):4 u5 A3 {+ O, ~  R( d% }
.\NES\APU.cpp
, K1 s) d" C, j$ `0 w.\NES\APU.h( u6 \  Y" s, [2 b6 _

9 e! u$ K. A. ^, X( S% F+ o1 X& @& i! G! ^2 G: c; [, i3 ?/ |' L
影像處理部份(Picture Processing Unit = PPU):
. E$ H! k( h3 m0 g; L4 x" b.\NES\PPU.cpp
' F0 }# I% l3 S% G.\NES\PPU.h, P3 A# Y" I7 n1 v$ V7 M' q* p& [

! u+ {- }$ t& J2 o如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:1 b. K5 ~* s/ o; G& L* _3 R+ O* }5 M
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
( F0 A( E# P" C. m0 R//////////////////////////////////////////////////////////////////////////! S* U1 O/ ^& f! M
//                                                                      //
2 G3 I- f( ^: z1 Q' q, i% c$ e//      NES APU core                                                    //6 t# d  `0 }6 M& g. V; A
//                                                           Norix      //5 _5 |/ B. k( q; ^$ V
//                                               written     2002/06/27 //' c0 Y: v; J7 Q% z
//                                               last modify ----/--/-- //2 T) P* R3 y6 f, Q7 g
//////////////////////////////////////////////////////////////////////////
2 E9 \- ^  \4 @# e' D5 b#include "DebugOut.h"9 _6 {( X0 C6 A# y
#include "App.h"
* K; s$ v9 w8 X# P& K# w7 z' G#include "Config.h"
3 f9 C3 [% {8 f3 I3 }5 k
  T- e" }7 g3 K/ m) n4 w' B#include "nes.h"& T" X: T, j# ?7 W, ?
#include "mmu.h"
' i; k! `  |% D#include "cpu.h"
2 _9 [7 B' W9 |. D- u#include "ppu.h", |/ a9 y: N( T3 I  S
#include "rom.h"  I2 O6 v- J9 i5 L# q
#include "apu.h"' {+ }8 }* K  r" y& E

. Q# ^; W! R; ~- b$ q3 Q7 [# [) A// Volume adjust9 ^2 [. V! F/ q0 G" f& \1 Q
// Internal sounds; ?+ G; N7 e; r8 t! }1 K: ]2 g
#define        RECTANGLE_VOL        (0x0F0)2 T7 b' X5 Y' l
#define        TRIANGLE_VOL        (0x130). K1 P- `! f6 ~: h4 d- q- ~" N
#define        NOISE_VOL        (0x0C0). f' x/ N8 R3 B( j; _. n- F
#define        DPCM_VOL        (0x0F0)
. u, {  }- f7 |& o- W. b+ _// Extra sounds7 [1 C/ Y4 ~1 ]" K
#define        VRC6_VOL        (0x0F0)
: G4 H: Z+ {& P) B#define        VRC7_VOL        (0x130)
2 n% D% U* z) N2 r" r1 }#define        FDS_VOL                (0x0F0)3 _1 H' T2 H* T3 T4 b$ D
#define        MMC5_VOL        (0x0F0)
. w7 @' n" g+ }: Z& z- _7 j& q#define        N106_VOL        (0x088)
& e6 L) q. N) p/ B; J7 @7 F# ~#define        FME7_VOL        (0x130)
4 \% P8 `% s2 S8 }
1 F; |& G+ `6 v7 k  [2 FAPU::APU( NES* parent )
8 @/ w  s& x4 b' w! \  c{
* o* `8 `3 z' I4 r& B" n5 X0 d        exsound_select = 0;; _/ ~- m# m2 a, C- @+ t

: j) n$ y5 ~% ]  S+ u        nes = parent;
! N6 F) q' d1 l6 G, v* {+ q        internal.SetParent( parent );
5 E: {$ i) @8 [2 @3 Q
* S# m- U# D8 ~% {' B        last_data = last_diff = 0;- A- K2 a" y! w) h$ a

9 `2 r" V! R, z8 I: @5 Y0 `        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
% C, u4 e; e3 F* B: U# ^7 u; I8 f9 y& s3 {6 i6 Q5 C: I' q
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
9 _8 X; A6 o8 g1 s. L0 t( H        ZEROMEMORY( &queue, sizeof(queue) );$ b- N3 a" z& Z5 i8 |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* l" l5 C8 S' `0 H( G2 ~
( s; T  y+ K) D( `0 S4 C
        for( INT i = 0; i < 16; i++ ) {' C0 V  j4 A! v3 c0 z; s. i
                m_bMute = TRUE;' U4 ]. s5 f2 A& X0 m
        }
8 M4 g9 q" G' x& D, |" I  Q) |}
. Z# b4 p* l& j( j
- l' _3 f" W# g1 E% A# D3 L  xAPU::~APU()  a/ J% ]! g$ f/ j! u, |* ^
{/ k. m, u  w9 Y, V+ Q
}
$ F* }; @  R* C; H3 j3 ~" k* G# F- s+ Z; o0 G
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )5 ~6 H8 K. u! k& M8 e
{# v3 ]% D. z  e8 s0 b
        queue.data[queue.wrptr].time = writetime;
1 C+ G7 n) j' a. e        queue.data[queue.wrptr].addr = addr;2 g4 t* J! `8 F, P4 Z/ ]9 Y
        queue.data[queue.wrptr].data = data;% w/ E8 v, u9 `( m  l: h+ S: x3 K
        queue.wrptr++;; {/ ?, k# E9 b% N; r3 l& T- Q
        queue.wrptr&=QUEUE_LENGTH-1;/ T/ |  L/ N$ G7 j* a. A
        if( queue.wrptr == queue.rdptr ) {; C1 T1 \# @: f* C! h& S
                DEBUGOUT( "queue overflow.\n" );  N$ @1 W- g3 ^
        }
, F7 c. O# N2 _! c* H}3 A+ {  b: c& `) V7 L" G6 P. R
* y& G) y1 S# a
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
$ [( I" T5 c; [0 R{
) `1 Q: G: ~# b        if( queue.wrptr == queue.rdptr ) {
% v; W' V( I. P                return        FALSE;
- J! i: v8 K: C" T( H) C6 F/ c/ |        }( N  r$ G+ N; @' o) M, `" E" K
        if( queue.data[queue.rdptr].time <= writetime ) {9 x! e) B4 O; U# V% l7 J$ n
                ret = queue.data[queue.rdptr];
- D* Y- Z: e) j- z( H" i6 v                queue.rdptr++;; @, ]* x7 J# }9 J/ i# `4 Z
                queue.rdptr&=QUEUE_LENGTH-1;
/ Z- B/ Y: ~7 J9 h7 m: @- N                return        TRUE;
2 W4 u8 o2 _" {0 g1 r7 O% u% z6 z        }% E3 y0 V8 G' V# F
        return        FALSE;8 g: s" l2 O0 c( ?$ |/ u
}
# K) s7 m3 Z; [5 N, Q: {  t) y/ T1 S, d7 K
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
& x! h4 y, B! ?3 C( `) K0 H& d# i/ |{% k: _8 s9 V9 p8 Y  B% Z4 a
        exqueue.data[exqueue.wrptr].time = writetime;
5 i7 @! h- u' I0 I: g, ^        exqueue.data[exqueue.wrptr].addr = addr;
3 Y9 P1 B( h' Z0 R  V6 Z2 W        exqueue.data[exqueue.wrptr].data = data;
5 w; B0 H5 G+ W# @        exqueue.wrptr++;6 Y% C" `0 ], X4 S$ h
        exqueue.wrptr&=QUEUE_LENGTH-1;
+ W, L. @( Q9 v8 H1 J8 C3 L2 ]& W        if( exqueue.wrptr == exqueue.rdptr ) {# p$ F- i1 J8 n7 Y  X/ O
                DEBUGOUT( "exqueue overflow.\n" );
/ m3 [* F3 \+ o! }        }
# V9 {, r) q( s4 _, I" l}
1 R0 p! V3 |4 Q% V7 y, s/ O" o( O. c/ r% h3 y
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
' F% Y8 z3 B3 \3 \) ~{; ]( ]0 Y+ O3 B4 U4 Q
        if( exqueue.wrptr == exqueue.rdptr ) {+ {: w* w3 `3 e
                return        FALSE;, U1 p8 [' K. X+ I5 {  G0 `( c
        }
2 S; @4 V$ x/ Q6 H0 r5 p        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
& g" {% J2 d1 M                ret = exqueue.data[exqueue.rdptr];
* d6 {( v6 d: C6 F4 U                exqueue.rdptr++;
0 H; K" g1 [" D# F5 B                exqueue.rdptr&=QUEUE_LENGTH-1;- Q) q7 K5 w5 X) u
                return        TRUE;
3 k( v& R4 ~; I( i% ]9 X' f) D, r9 n        }
1 i1 Z  O4 t6 p3 l# L. H        return        FALSE;2 X1 f$ ?- j  F8 ?' Q4 t8 ?* T
}
6 X0 [8 u% l/ J& w- T) {9 ~4 ]
3 m* _8 X& a! R6 Y6 h* evoid        APU::QueueClear()
# M8 @, P1 Z* s* f0 i# f{5 O9 A& E8 t4 X! y+ b2 k# W7 X) _% z
        ZEROMEMORY( &queue, sizeof(queue) );( v7 ]: N; b  V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 o8 {1 }4 t' d: z4 I% `4 l- r
}
7 D0 M/ e. o; ?0 I
; Q. s) M, e4 Q2 t/ }& A/ wvoid        APU::QueueFlush()
. C1 R/ O* i+ \% ]{
% L+ I) L0 [( e1 H        while( queue.wrptr != queue.rdptr ) {
& G0 y! l% t: f                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );% T" l* D- T6 D/ d0 d2 P) L
                queue.rdptr++;) l  _% R' C# `' t, w2 E3 {
                queue.rdptr&=QUEUE_LENGTH-1;
5 Z$ b+ i, T# h0 y  {. r        }& z6 s0 O2 T* w" Q4 P0 r* j8 r' o
+ l: x9 u9 C3 N# `+ l9 U! ^, f2 B
        while( exqueue.wrptr != exqueue.rdptr ) {$ \7 D. \  d0 d# _6 x% F
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );' q1 R, R* `5 S9 v% z
                exqueue.rdptr++;
% \* N5 g* y( P; e0 Y  [2 ?& B) u# q                exqueue.rdptr&=QUEUE_LENGTH-1;9 Z8 h7 Z3 O( B. i
        }" g4 x! [, [* g; Y
}- R* p2 j$ w$ v4 G- h
* H; }7 o$ I% _
void        APU::SoundSetup()7 j6 i$ B- y( I+ N6 V, w4 E& s' f( q
{
8 t8 }3 ?: R! Q        FLOAT        fClock = nes->nescfg->CpuClock;
8 x* E1 a* p. `8 z        INT        nRate = (INT)Config.sound.nRate;4 D1 B! k& _3 d" E% c& i0 |
        internal.Setup( fClock, nRate );
' Z: T# T# V6 q6 L        vrc6.Setup( fClock, nRate );8 b* h5 l( f3 F# [% w+ x) c7 q
        vrc7.Setup( fClock, nRate );
9 D. [/ j# w1 s( s$ z1 q; P        mmc5.Setup( fClock, nRate );7 U5 h6 ]. W3 ]' O7 D1 S8 A
        fds.Setup ( fClock, nRate );
6 V7 h. p, M' r+ n! K% M        n106.Setup( fClock, nRate );
. B+ w  s; u  N) c. b. [1 }! m  l        fme7.Setup( fClock, nRate );
( g' G) g2 B/ F1 r}
, ~; x: X: G- n& w
- ~" P" j& h* N5 cvoid        APU::Reset()
& n; e8 w' |+ i$ }{
1 [. Z& L: }5 V0 V( S( p        ZEROMEMORY( &queue, sizeof(queue) );, E0 X. g* q( a7 J4 Y% M
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ W1 C) f$ o& w5 d5 T! {- v% f
- o" y+ b0 W$ x2 X- ~) t1 t        elapsed_time = 0;. h. k$ f; x5 t6 r# u# Q7 L* w
- p8 L; c3 s5 m2 M! ^0 A
        FLOAT        fClock = nes->nescfg->CpuClock;
2 @. W. M  p7 ]6 {% ~( h6 i        INT        nRate = (INT)Config.sound.nRate;
; [8 N4 n3 t/ F+ G( m        internal.Reset( fClock, nRate );
3 [5 U; ^* X( M* J+ S# E% n        vrc6.Reset( fClock, nRate );
! `( [& G( p& v* I! L2 M7 t        vrc7.Reset( fClock, nRate );  {6 K  W* r) t8 V2 N9 L+ W3 Z$ C8 ?
        mmc5.Reset( fClock, nRate );; x, Y3 g7 W) L% c% {* E0 R
        fds.Reset ( fClock, nRate );
! Z& Z( L( p, q! w8 a        n106.Reset( fClock, nRate );
- `* @; v* f/ H/ u2 L2 \5 J+ a1 t4 }        fme7.Reset( fClock, nRate );
  I9 G& L% r0 Q4 d: [9 G; t
' ?* @9 k. r- G( _        SoundSetup();
! L; F  x6 u# Z}" A8 ]6 Q- D: L6 e& T( A
/ G. J3 A% q+ E" F- |  J" {) a4 d
void        APU::SelectExSound( BYTE data )0 o. X% J5 q# |! Y; j
{
  j6 ?) V! j; A: c& }  c4 v        exsound_select = data;( l& g2 w$ K( i  `9 l2 L8 M4 C+ \
}# x0 M+ G7 F1 c( V' V1 _; p3 P# S7 I
: ^% W) {0 A  G+ @* H. m
BYTE        APU::Read( WORD addr )
( p/ \- {  H$ W" X: I# z{* ]* p2 X& G' E+ Q% F- }. n- b
        return        internal.SyncRead( addr );
  |0 z7 b# d* B3 ?/ w5 E}& _) [8 M7 Q' w2 }- A+ q" l
$ h4 S( @$ S; i+ Q2 v
void        APU::Write( WORD addr, BYTE data )
/ B7 U  ~' d2 e. n6 M3 b  P- [{* z8 K3 p1 [+ w; u& t2 J: S' ]2 W
        // $4018偼VirtuaNES屌桳億乕僩
+ ~3 @7 B4 [" I# r! Q6 o# w7 m- A        if( addr >= 0x4000 && addr <= 0x401F ) {
! x' O& e7 Z7 t* G5 c                internal.SyncWrite( addr, data );
) O5 R% W* l5 U2 u& d' T7 e! i                SetQueue( nes->cpu->GetTotalCycles(), addr, data );" x7 O0 L) ], I6 a2 w0 b/ S
        }! i2 @# Q1 a. B+ o2 a6 L- n
}
, h' T- i4 U* p
( F5 M+ {, O: J9 |4 @( KBYTE        APU::ExRead( WORD addr )5 S4 \! m5 L& T( Y% P! S! V
{
. a, N* C2 R/ \* ~BYTE        data = 0;
/ n! f9 [" R0 h  H( J) _+ A( ~) C3 O7 p4 W. A$ T
        if( exsound_select & 0x10 ) {
, F7 a$ \8 L* F. V                if( addr == 0x4800 ) {6 m3 b; _# F3 `. M0 o
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
0 ?9 P- {/ p! J4 Y" k                }
/ u3 l7 k+ i% a& b+ G2 n) r, a3 W        }
1 }3 T2 z+ o) ?  u' O. G$ i& K: e: e# U        if( exsound_select & 0x04 ) {6 I. T7 D  @( A$ G1 w8 X2 q
                if( addr >= 0x4040 && addr < 0x4100 ) {
: O. x: m% n& s! t                        data = fds.SyncRead( addr );7 ?3 |; P( @. n+ n6 b) I
                }
+ ?" M7 z/ p# H( C        }( w0 _2 L0 |  p+ [% @; v" r4 ^8 _0 k
        if( exsound_select & 0x08 ) {. x- ^/ D1 m4 w/ o" E: t; }
                if( addr >= 0x5000 && addr <= 0x5015 ) {. N- i6 E, B: Y2 c
                        data = mmc5.SyncRead( addr );- m  m2 W0 N3 ?) O9 {1 j, l+ h8 w. A
                }& p4 U8 u! u2 S- q) T& ^- C) e; L
        }, K0 y5 }7 k1 O- ]' [
7 d6 b/ A8 d$ N1 U' `( R
        return        data;
9 B- j6 m' A9 C}8 U( L1 Q# A! j' D/ d0 n
) U8 d% `& h, l; m/ ?, B
void        APU::ExWrite( WORD addr, BYTE data )
4 T& V: g0 V1 y{
+ F& m# z1 v& `$ m$ ?) ~        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
# p9 l6 ?& T; G  O& R
1 q. A+ H; q8 J+ b4 n        if( exsound_select & 0x04 ) {# n/ i! ]2 d/ o! ^
                if( addr >= 0x4040 && addr < 0x4100 ) {1 t6 q, R0 B# w3 d
                        fds.SyncWrite( addr, data );
8 P3 i; e3 @9 \, h                }
, v9 g7 S2 c) W' t        }
$ U1 B! v% n9 p. q0 L. H- h. {7 c! B
        if( exsound_select & 0x08 ) {
+ j5 H% k$ y2 O& L! r! P" R                if( addr >= 0x5000 && addr <= 0x5015 ) {  n# F; m* w  _" ]. ]/ t
                        mmc5.SyncWrite( addr, data );
8 v5 L  G+ }( l) s                }3 A0 w/ r& ^4 N' h9 {) \
        }
  b& w% ~- c+ W}
4 c$ _2 p6 v# k% K- k1 C
6 L+ d/ K( H8 D( @void        APU::Sync()
1 j9 m% F. `5 @; Y' L/ E6 ^+ M! X{5 o. x3 _# g* L
}
, o. ?5 d2 O5 ]+ Y9 v; h% h7 \9 W, b" l. T
void        APU::SyncDPCM( INT cycles )
* |5 L, O- s  \# v* b9 ?% \{7 }( `8 }! `7 d+ `
        internal.Sync( cycles );0 B0 N  _3 q+ J; a) y7 v& z
/ n+ \6 a. ?' m; Y  J
        if( exsound_select & 0x04 ) {
! B2 U( D! r1 |+ Q# |                fds.Sync( cycles );
  x9 K( }8 b. N/ m% V, G        }1 b! a) J8 A" [+ L2 Y, b" u
        if( exsound_select & 0x08 ) {2 c0 x& ?0 b& U+ y' V% b4 N
                mmc5.Sync( cycles );  L! p5 _7 W' B& H
        }
$ H" s" c8 v* M$ Z( F  M( u}2 r! Z( F  @" m
; }% d/ p4 d; M! _% b/ ^9 m
void        APU::WriteProcess( WORD addr, BYTE data )
. K4 X9 [/ B7 _3 U6 f{$ i8 r2 O- e# T
        // $4018偼VirtuaNES屌桳億乕僩0 a5 L: B. U/ C, f- f
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 {! ~% t4 G9 K( U4 R                internal.Write( addr, data );% y6 i; V% `0 X/ u
        }
8 I/ N" X: C8 `4 \1 b. ]) y1 w}
, ?* K# a# m/ j  t7 a% b6 r& O0 V+ O8 i) R
void        APU::WriteExProcess( WORD addr, BYTE data )# d* C' x+ b: Z  H+ H
{2 J  O& I6 t* C, n' Z7 F
        if( exsound_select & 0x01 ) {
: Y! R* n, v$ Z- W/ g6 E. g                vrc6.Write( addr, data );
" l7 Z0 N0 @4 ]3 Y5 E5 R        }# q. Y8 ^' N( U
        if( exsound_select & 0x02 ) {3 b* ~! k' f9 y1 J* z  H
                vrc7.Write( addr, data );& C8 q* I" p, u0 J! {8 v! y4 F
        }3 t9 T( w! x* Q( {
        if( exsound_select & 0x04 ) {
8 H. ^# [+ o9 S" m+ P                fds.Write( addr, data );
9 R  j1 e2 @+ o# K6 \- t) Q" a. h! t        }
- a+ W  F4 m* M1 g& P7 k  {        if( exsound_select & 0x08 ) {$ B% z9 f: U: ?, r
                mmc5.Write( addr, data );+ a6 E) C  f$ D
        }% X1 e8 L3 Y( E
        if( exsound_select & 0x10 ) {  J1 L  G6 k# G: l
                if( addr == 0x0000 ) {
  N8 I8 e1 G7 q  j; s7 s                        BYTE        dummy = n106.Read( addr );
6 ?0 z; F* m; A9 ?- I                } else {6 M9 ~9 V: f6 r8 C* d
                        n106.Write( addr, data );; j6 E/ N! G. {
                }
6 h5 ^; L+ A: A( q' q        }
( M, T1 G, U/ O! P        if( exsound_select & 0x20 ) {0 b; v8 O' `5 {' h+ B( s* ^4 `- `/ R5 f
                fme7.Write( addr, data );" w* \% z! j* ]* w  J5 ?- F- a3 [
        }) @% X" Q! l# W
}
, @0 x2 |4 L( h% t, Z
: K5 X! g$ }% f3 o. r3 Nvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )4 k4 n# N+ A8 [) ^" H% F- n
{
' O5 u! j' ^( XINT        nBits = Config.sound.nBits;
1 O1 d! Q( a9 u9 [# W* r7 QDWORD        dwLength = dwSize / (nBits/8);, u  R# g3 d; q6 J8 Q) [; W( l
INT        output;0 i6 I% B8 @* u: Y- q% Q
QUEUEDATA q;5 R! ?- M, A( I( e- ?" P( h6 p# D
DWORD        writetime;
+ n7 b6 f2 j- ?* W5 j& G$ Z2 t. {" `7 q0 k, Z1 s. Y
LPSHORT        pSoundBuf = m_SoundBuffer;" u) E( g/ B% @- _$ c* P( ?0 z
INT        nCcount = 0;
# W; X+ z6 I4 G: I- I6 S) ]* O1 v9 J; a; ]' S
INT        nFilterType = Config.sound.nFilterType;
2 W3 u1 E6 U& E# A; l8 W2 H# Z
% B. q$ j0 Q) L3 R, U        if( !Config.sound.bEnable ) {
7 y7 k0 g4 J. b$ ?  b                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 Q) \6 v8 z0 m) }: o                return;
5 ]0 v! N/ S' _$ C, a- Z        }
% t, X* U, m5 I+ {2 k
, W" m/ q" T4 l5 W* P! P        // Volume setup
) g4 P2 O) A3 ]) ~* s        //  0:Master2 F+ @& h$ F0 ~
        //  1:Rectangle 18 Q: Q  O( L4 O
        //  2:Rectangle 2
/ l) S, {" ?3 D& @( F( Z4 Y        //  3:Triangle: o5 L& _. C& G( z1 `5 `2 @, F
        //  4:Noise+ W3 z. Q$ L6 }  N& A) Z: y
        //  5:DPCM5 u: U, f  S" G" F' ^; ^, ~
        //  6:VRC6
7 G4 B. E4 x: |% N/ f        //  7:VRC7
. ?8 b8 q% s6 C# S/ K. @& Z! t        //  8:FDS
; G, e0 I2 D6 F6 I        //  9:MMC5
# T1 R2 P2 z8 S4 D/ }: f        // 10:N106
' u: f+ `' F. _2 ~) ]0 W        // 11:FME7
3 p0 R# z9 X+ ~, c& J, }3 E        INT        vol[24];6 o# @1 V. s% M, i  b
        BOOL*        bMute = m_bMute;  k" k) u3 |" b/ s8 {+ ^
        SHORT*        nVolume = Config.sound.nVolume;
! n# j  q2 F  n' _* ?
7 C" a7 b. W* i4 {3 z1 Z3 g        INT        nMasterVolume = bMute[0]?nVolume[0]:0;6 C8 \# H! d5 P$ G
5 E! l4 J) |2 I* y' z
        // Internal
, u  L0 Z# X- c! m# b# @        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
2 Q: Z2 L$ i4 Y  c: L$ r  ]  y        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;4 q. V5 e& j! T" Q
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 \  s  z. @) ]1 ?. i  x& j( A
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
9 S2 p/ W9 C) E, v: U' \        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;8 T" t! Q( v) S/ `$ d
& e3 |7 M% o7 {* I5 o* E
        // VRC6% I/ n, M! u. ?. d3 t
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 c  E/ T' h; T. p% B  B        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% J1 q6 L! y8 ]4 i6 @
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, Q7 y8 Z, R# y  c# O
6 e, C" |7 {- Q' G
        // VRC7( Q. e; k# h: d
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;  j) x9 [( D+ N" D0 _0 E  ^; Q
2 n( e, ~1 ~( I" c2 m
        // FDS' X9 K+ b" e4 o3 _  k
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;0 l3 \3 G3 d; n6 S

' f+ {% ?% K: e        // MMC5  t8 Y3 A( F* B: E5 Q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. d+ B" V5 f# q$ D
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! Y2 B5 U) a& P; R+ ~! @+ b7 G
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: R& h4 y" a- J
0 a+ K) `: {1 a% Z( p0 ]
        // N106
- c% d1 Y& A) F& Q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& M; n. A8 Q( G# o# F        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( N1 H7 J3 u" `; S        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. x7 O+ V4 R2 S/ l5 \7 I5 i        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" U  s, K9 _% n; b) G) ?) k        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- F" x& i0 J1 j! d        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 {" l* S# L& P+ U( u        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 t) Z0 [) N5 K7 N        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: u* ?2 A' w) s* ?: F! n, R0 v
) B4 i  {  Y) b7 V        // FME73 p: D6 ~9 H/ v- y$ O
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ A5 L' v1 m1 S" q  G        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 [- y' v1 d; C+ H
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ n: M0 Z1 g0 d+ w" ~, d" ~# H
, y( N0 b/ k, q0 t
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
2 D: G$ `" ?+ t2 @        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
# |, v" }/ g: _. d6 C- E+ y8 w  i$ O0 Q9 G) [3 {8 {  a: J3 C4 M% E
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
( J7 n: f- ~$ l" I+ X- g2 y( p        if( elapsed_time > nes->cpu->GetTotalCycles() ) {, _- m2 e2 `- C
                QueueFlush();4 M1 U& c$ r; ~2 @
        }: p* c6 `' i: y) H

+ |: N6 u& [* L: z5 m# t! |+ H( R        while( dwLength-- ) {) Z1 q9 }4 C8 J4 L: j4 a- R
                writetime = (DWORD)elapsed_time;6 E+ J  d6 O* I

6 P" v) \( n! i" |' r9 T                while( GetQueue( writetime, q ) ) {
; f1 B1 M' d* q3 y                        WriteProcess( q.addr, q.data );
+ v( u/ h" d1 \$ c1 n0 ?                }
2 ~( J( N; \0 d7 l
5 B( M& M  Z2 ~, {                while( GetExQueue( writetime, q ) ) {
+ I" p2 Q5 G  ]+ C                        WriteExProcess( q.addr, q.data );& @  Y+ r) y" H2 X
                }
) x# h) c" }  G. B" e  X) ]
6 M  v, M3 I& y) K( k* H                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME76 t- T/ F) m: B! g& k- r3 C# \$ I6 F
                output = 0;
! C. R7 k& C9 z  m8 L- c7 Y                output += internal.Process( 0 )*vol[0];
/ x4 |8 M5 D$ m: g/ }; H7 S                output += internal.Process( 1 )*vol[1];% x% u1 S7 L6 K* }( V
                output += internal.Process( 2 )*vol[2];
1 V" T* f) C* Z/ h  @- @                output += internal.Process( 3 )*vol[3];: A$ Z& L3 A  v" ~$ q1 o, W: O
                output += internal.Process( 4 )*vol[4];1 b$ ~1 z- x* K! W0 S7 O

0 \9 n9 g) V2 n                if( exsound_select & 0x01 ) {
5 @# i. h& a- s- f4 X2 ^6 F7 ~                        output += vrc6.Process( 0 )*vol[5];
7 b( N6 E4 V5 _3 r; S& c3 b                        output += vrc6.Process( 1 )*vol[6];" b' \4 c# [, ]: ]3 M5 y, [
                        output += vrc6.Process( 2 )*vol[7];
. }2 e5 ^0 O% T4 @/ ?! a; r# M                }
' Y. I2 {# Q3 n2 i/ ^( V                if( exsound_select & 0x02 ) {
, R4 V' D& C4 e- D' q- a/ E                        output += vrc7.Process( 0 )*vol[8];
7 o& W1 O/ l' z# ?8 C                }
) I& y( L. S( E* O                if( exsound_select & 0x04 ) {* b; V8 A# r! j( Y) B8 T
                        output += fds.Process( 0 )*vol[9];8 ?6 H# m7 T! D8 N4 ~
                }0 k" ]0 x. b" \3 o
                if( exsound_select & 0x08 ) {8 u! u5 c, G) _2 x3 o
                        output += mmc5.Process( 0 )*vol[10];
% k7 }! b4 N, K2 D8 H& ^                        output += mmc5.Process( 1 )*vol[11];
/ \2 v! m3 Z% w& [3 k9 ?                        output += mmc5.Process( 2 )*vol[12];
- r" `$ M3 c, {1 A                }( s0 U$ d; p, `% h; Z
                if( exsound_select & 0x10 ) {
% @3 J3 T$ E% d6 w* [4 O# X                        output += n106.Process( 0 )*vol[13];% ^: v* ]2 F$ i5 J0 {  ?" t9 j% z
                        output += n106.Process( 1 )*vol[14];
7 P+ \9 d5 w- K1 [" c( q                        output += n106.Process( 2 )*vol[15];, }  |3 q# x4 S" w0 _4 O3 W
                        output += n106.Process( 3 )*vol[16];
  R% w$ V; H  [% o* y3 e                        output += n106.Process( 4 )*vol[17];
; M" n. @) I! o$ _! [9 @9 K                        output += n106.Process( 5 )*vol[18];& f! b7 u" h& e0 l% N, a1 {. D
                        output += n106.Process( 6 )*vol[19];
1 }6 K9 P: s) R; x% j% A                        output += n106.Process( 7 )*vol[20];
  r$ ^4 T" {) j" D" p# T2 b2 M                }
/ i$ b5 a" O/ i% b+ B! U0 r. M                if( exsound_select & 0x20 ) {
) ^4 q! U- {4 P" l                        fme7.Process( 3 );        // Envelope & Noise" C* W. d. j' F) h  @3 X- y
                        output += fme7.Process( 0 )*vol[21];
; S! }5 [+ `- m) v& D4 S* F3 U" {                        output += fme7.Process( 1 )*vol[22];2 e; x( u3 M  F# q2 B: J
                        output += fme7.Process( 2 )*vol[23];
  C8 c- q, |7 w- |) T" j5 h3 \                }
: x( \# W, ~6 w, G$ r3 F' C  B, ]6 t2 ^; b4 G4 \5 ~/ J; w
                output >>= 8;" Z- C$ t2 d) F1 M( m

* R2 F; C/ w. [5 ?  F$ Y/ R                if( nFilterType == 1 ) {& r5 ~3 p3 c5 b4 p' G
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) ^  K5 |+ z& T, `2 l% s1 }$ W$ Y
                        output = (lowpass_filter[0]+output)/2;
' g, m8 `0 y. b% g( K                        lowpass_filter[0] = output;
. \) ~* g( W! Y( B0 d                } else if( nFilterType == 2 ) {5 s& c  j9 _- a* I2 B9 H
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1), @$ D+ @' }9 ]$ D+ Z5 _# Z+ o
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
4 Q! F. x/ q# d# {                        lowpass_filter[1] = lowpass_filter[0];; I0 d6 X: x  }# B- p6 l
                        lowpass_filter[0] = output;
5 a) U1 k1 U' u2 s! n                } else if( nFilterType == 3 ) {
; c% v" u' I/ E% P                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
9 [8 D( c$ r8 L' k5 z$ ]                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
1 b2 y& L* c( @6 B0 B                        lowpass_filter[2] = lowpass_filter[1];+ |9 `$ g+ Q0 K8 j; l/ |3 y
                        lowpass_filter[1] = lowpass_filter[0];
0 G* s8 n# ^4 ?& i$ V' I  n                        lowpass_filter[0] = output;9 o2 q6 L! {! p3 _& p8 l1 D
                } else if( nFilterType == 4 ) {
0 ?9 k2 M) `  n5 W7 W* @) n6 B  g                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 l) d. W+ ]; ^! b5 U& W                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
8 F8 z, A$ D+ K) q                        lowpass_filter[1] = lowpass_filter[0];3 B, ]1 r. Y: b7 w
                        lowpass_filter[0] = output;0 K' |) ?  |: B7 ?+ a
                }
+ f% w/ l$ G; [$ }# _8 \5 k' k1 S( g0 m: e9 X) V& p& |4 m9 L/ F
#if        0
6 T; {: v4 I/ i& O: w3 S1 I# X                // DC惉暘偺僇僢僩
; x2 a* @$ u# b$ {6 E5 M                {5 R# {% t% z1 \, S' C! k/ o
                static double ave = 0.0, max=0.0, min=0.0;
- q$ i) _& @/ }                double delta;
6 o1 A; I/ |# v, G; Q3 r% P                delta = (max-min)/32768.0;& N6 i% i& I3 F3 R! n! a* `
                max -= delta;# ]: i% y! \$ t
                min += delta;6 B# K4 |! Z6 D  ~' o- U9 F& M* i
                if( output > max ) max = output;
: }, W8 e$ J, A' v4 S! T- g0 @. L                if( output < min ) min = output;& M! c. o; d% \
                ave -= ave/1024.0;, p6 ^5 X7 ?0 F) s7 j" d6 m8 @
                ave += (max+min)/2048.0;
9 L. ~4 D% `& n- N# O0 ?5 G  T                output -= (INT)ave;
$ X! Q/ K- r' f- P  R% _                }7 h  [$ q8 R' ?+ _8 Z: e* [
#endif4 q' d! q% D/ [. w% P( Y" c
#if        17 x6 L, W+ w! t. w
                // DC惉暘偺僇僢僩(HPF TEST)- f' ~; y2 D4 h' k" ]  }
                {
0 v$ d* U. u# C) p//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
9 e% A. `1 D3 e. t9 m( m* Y. k) ?8 x                static        double        cutofftemp = (2.0*3.141592653579*40.0);( s$ `! |1 [0 X* x# k
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
# L# O8 `" ?% V5 ?9 J5 N                static        double        tmp = 0.0;- v* k3 l! v4 r3 R: z
                double        in, out;8 z9 ~( {* ?5 S) I/ k! H; R5 \5 P

& f& H$ @* J, O1 T( Z5 o+ D                in = (double)output;
, c4 ^& [( p1 W                out = (in - tmp);
4 g4 N! |% |+ _3 h' P                tmp = tmp + cutoff * out;
' \4 P- Q' d# X% U7 }2 r- z, n5 m1 \/ i% g2 I
                output = (INT)out;
' n; L# U6 g8 B5 s9 O0 b4 o                }
; L1 i( H. P1 {$ ^( a7 ?#endif0 @6 h* a9 L* a( o4 w9 p/ D: u3 F
#if        0$ h* Q/ x( T: {' D2 l. v5 _
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
- Y  V& f5 [! M7 [                {9 R7 c& g1 O2 t, Y0 k( Z
                INT        diff = abs(output-last_data);3 i, w# t/ Z9 s( c
                if( diff > 0x4000 ) {
6 S9 m4 A5 F( y" ~0 C/ Y4 ?                        output /= 4;* }9 O: i& \$ z, v2 m( r: |5 K2 w
                } else
; d- q* \, ~' x* w; q                if( diff > 0x3000 ) {
! s4 s( a) t! g+ E/ Z$ M                        output /= 3;3 W0 }6 y7 D' l$ _. \% v4 u7 ~  a9 p
                } else  E% H) M0 r8 y, F) _
                if( diff > 0x2000 ) {/ D# C0 K4 ~1 i) f2 J
                        output /= 2;
1 E; f) n3 F# C& v. I5 ^+ Q                }8 z( u/ D. V# m& K
                last_data = output;) s3 Z; t2 A5 L; t, u
                }
( v& ~: {2 d, L+ G; h6 a; i#endif. J, x8 ?9 V: h* j, @
                // Limit
6 A+ j! h$ Z  R                if( output > 0x7FFF ) {. t1 V( {- A% G( M& i8 Q
                        output = 0x7FFF;
8 w) O9 o5 b! t% p* Y                } else if( output < -0x8000 ) {
( w8 l. X+ G: G; d* z; m                        output = -0x8000;
5 z( D3 P" }2 r& }3 A* ]! z; x* ^1 B                }
/ Q! Y8 U2 F3 `) C. {! I  }0 Z4 B
% t- _  [0 y2 |% a! u4 G: X                if( nBits != 8 ) {. N4 t+ D( k  y* I
                        *(SHORT*)lpBuffer = (SHORT)output;
7 p+ `4 G! S. Q0 w                        lpBuffer += sizeof(SHORT);
4 Z5 e8 Y* m, a                } else {# N* E6 I3 |, C, Q9 h, c
                        *lpBuffer++ = (output>>8)^0x80;( Z6 c  p% O6 [1 j6 D0 H3 }
                }
, e" G# C" I6 h8 M) D, P: t' k$ q+ ]0 N( c
                if( nCcount < 0x0100 )8 o0 A2 O6 b( b' Z
                        pSoundBuf[nCcount++] = (SHORT)output;  L  Q! o& ~  T$ T" _
  e+ g$ e$ {! G' N! }
//                elapsedtime += cycle_rate;& _5 p' o. l! q( o
                elapsed_time += cycle_rate;: @! R9 d/ _% x
        }
: u0 D7 o$ o8 e6 W9 A, a; n! v3 M) H, z
# O2 ^/ i1 O7 E! N! N  U#if        1
( i/ t& m$ t2 O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
8 p5 d0 E4 P1 B: Y) s                elapsed_time = nes->cpu->GetTotalCycles();
, F4 I7 s6 ?& q6 J! J$ T8 V        }
1 a4 t. Y! i6 r! ]$ Z. \/ H        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
; |  h7 L* j- d3 k. G0 V7 ]0 S                elapsed_time = nes->cpu->GetTotalCycles();
, E  N6 W& S5 J' k/ |; O- ~: Z        }
2 e: D$ E/ c. i. X2 G#else3 d8 x1 j( D& B: c% C1 Q' l: d
        elapsed_time = nes->cpu->GetTotalCycles();$ V# H) s9 q0 n" X; e4 O2 u
#endif
, Y2 \) x/ Y. E: I+ A) [, C' U}5 l- A3 o. H: h/ Q4 I
# w) N# X9 P8 A1 m! u0 }0 q9 J7 o
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)4 O+ @5 `" z1 e/ e
INT        APU::GetChannelFrequency( INT no )2 u% p2 _7 e; h+ b
{6 V/ R# V; W2 F% Y0 H2 }5 G
        if( !m_bMute[0] )" Q  @$ v# }/ v* a4 f. }$ R  C4 O
                return        0;
) c/ \. R; ]4 [/ f* r' Z& r* T2 L( B9 m5 T, ~
        // Internal
6 ]' E/ G# v- J        if( no < 5 ) {& {1 }, }% a% {! H
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
# ]$ ], u- v- q" [$ e5 f* K3 B  V4 R* \" v        }/ ~1 s; V9 [: G' [* U# m; _
        // VRC6
( k" C) |7 F# }. J0 ?        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* C5 G4 k) e$ ]+ k. z3 P, t                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;- C" z4 c$ i8 h
        }5 J4 e5 ~) p# Y: V5 t  g
        // FDS
# u' g1 [3 s) w9 H        if( (exsound_select & 0x04) && no == 0x300 ) {  B% s8 b4 h$ M' \& l) h: v
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
, \' U6 L" S  t, ]        }
8 @1 }7 T: _4 t  i+ e4 t        // MMC5
3 w+ P0 [3 c; D0 q        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
3 K5 F( [8 m% }                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
( `+ ?4 r4 F$ Q* W) J; n# K        }) i1 W4 x/ g- K8 p2 C* P5 @
        // N106
) a) X$ C4 F/ e, r  _        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {& M1 `& g2 ], J8 n: `
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;& W; b6 l  e7 k% }! a+ }- e- D
        }& }; E$ [' Y/ ]. p7 s0 J# @: u
        // FME7$ G; n+ f) Y8 N4 P( E% j/ b
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {+ r! N8 J# w. Q5 h- U
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;# b0 ~5 Y7 P8 O0 X$ s& h( d
        }
0 X, y9 g) b0 z6 A7 J/ p        // VRC7  ^8 D$ y. r8 x& R. T5 L- y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
8 a, y9 ^& _* h: T& A                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
7 j) w  w# z% B3 H        }
7 D; s$ |. K% {& i2 O        return        0;
- S5 A6 ?0 B1 }. b5 u- S* D}
  }$ A5 i0 C% B3 g% s4 F# J$ |; Q9 z6 C" W7 u3 F& {8 X
// State Save/Load% w2 c' P) s! D* N. k( D% ~2 b
void        APU::SaveState( LPBYTE p )
1 I* k9 T. G6 W6 A! b4 s1 ]5 `{
: c( q( z, _4 Y) T  E6 s#ifdef        _DEBUG
8 n4 _/ _% l, ?+ cLPBYTE        pold = p;6 W0 l- @1 M" H9 @. }' x8 g$ Y
#endif7 C" ?5 N2 r; }

3 @( J' J" @6 j5 R( M4 s8 X2 v$ [        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞: i: |( ^. w" F( {% A1 l0 S
        QueueFlush();& n4 c% d9 Q9 E- Z) e# v

  P" \0 E+ ]( k$ ?* M8 H' R        internal.SaveState( p );+ M0 [  W- z1 s4 X, M' M# @
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 J* Q9 m" Y" l3 F9 v& W

* u& h  S; r( T/ i        // VRC6
4 v! R) r  Z2 m' t# X        if( exsound_select & 0x01 ) {
2 ?+ }# K+ y4 @- Q% k+ v                vrc6.SaveState( p );% A7 t% }: T7 J" }2 P' ~) o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding% l9 r5 j, X# O1 W+ @
        }* y' j+ A7 L+ P/ d" X, q. L$ b* W7 D
        // VRC7 (not support)5 [# c. C' [. o0 Y; ]& ?
        if( exsound_select & 0x02 ) {7 B) o5 t& d- X
                vrc7.SaveState( p );
+ O+ {; H2 x2 n# n7 S9 n* q                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
$ w4 v+ G, M' e' _. T# Z, A        }
" h1 B: L4 O5 g) v* E3 P  B( ]9 W        // FDS
3 f& w' U( {- [' B9 S3 H        if( exsound_select & 0x04 ) {
/ b+ n1 A! ?2 V. J                fds.SaveState( p );
. r% w: D& j. T- |# n* [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 c! j+ o  h% c, v  z
        }; s3 ~5 p8 V5 F, ]" `4 Y" V* k& u
        // MMC5
* L3 |+ ~6 A" o2 C3 z' B        if( exsound_select & 0x08 ) {' T5 \5 i* h6 P
                mmc5.SaveState( p );
: n5 Z& y' x: C, z0 d7 |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( Q1 m! I( v; `6 Q- d9 l+ n* m        }
) l* x/ _9 U6 q% W        // N1066 a) G) D* p- P# h
        if( exsound_select & 0x10 ) {/ [0 c5 I% E, u
                n106.SaveState( p );
' X4 F. p2 k# ?( M6 ~) ~7 Y/ F$ h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  F7 P7 r/ m8 ~$ a  O' \
        }
5 t2 J# x- W* v, W; X4 b9 O$ {        // FME70 k0 b4 j* p0 x# u9 \5 n) `
        if( exsound_select & 0x20 ) {7 {( `" b9 A: Z, O2 N7 w
                fme7.SaveState( p );, p! s3 d9 K: g" d
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* x! k4 l# ^+ V7 X& D. ?        }/ m% q+ B4 @4 i" Y- V5 |

/ d3 m+ T7 _6 b  C#ifdef        _DEBUG
7 h7 }$ t2 }- h4 M! E6 `, {' WDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );6 D+ K( z( w5 V8 s; ?4 b
#endif6 v6 m9 k" w; c" ?# O+ X+ l. [
}
, [! [  B& a# p- w& U' r& L; c* e
$ D5 v: O& }1 Cvoid        APU::LoadState( LPBYTE p )6 ?5 q% P* D  w! r6 D# s
{
1 c- y6 X$ H/ Q* C+ K6 v        // 帪娫幉傪摨婜偝偣傞堊偵徚偡  `7 m7 m# r6 n
        QueueClear();/ C/ \; s5 G; H- A3 d% z

2 F& _+ \5 ~6 j5 ~* K$ a* @        internal.LoadState( p );4 P2 i: L' U' y$ Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding0 F! y- Z, T- J, Q( e

7 s$ d) f5 g: F& o  f& J4 m# n        // VRC6
1 r8 ~+ l- u0 _" t) t        if( exsound_select & 0x01 ) {
  @" k0 a5 D. B2 R9 w! C% Y$ Z; Q  S- g                vrc6.LoadState( p );: O5 R$ |' k2 y6 t8 r
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) g  x: @# U8 D9 V        }8 k+ |6 x: }1 u- i7 v. n
        // VRC7 (not support)
7 i8 |; ]1 @6 e0 d        if( exsound_select & 0x02 ) {+ |% ~# m0 _; C3 h3 l' R
                vrc7.LoadState( p );& P  B' D! c7 m
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# I. [' D& R8 h0 ?( o& W. {# C8 n
        }
$ {7 [7 i  g. }6 P( |! d        // FDS9 @) C# y) d  q7 t3 n
        if( exsound_select & 0x04 ) {
  D1 m7 l' I( `9 o$ f0 m8 ^                fds.LoadState( p );
; N% w/ @- `+ {                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) ?8 q  H& J& ?        }% C4 i# I: w+ Z
        // MMC5
' h" k1 d8 y2 t8 k) _- ~        if( exsound_select & 0x08 ) {
8 i' J/ I: `( ]! Z' [3 D                mmc5.LoadState( p );; R5 o+ H0 ~7 G6 h" c  V( @
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
4 Z7 t* I0 J; L3 W5 z& o/ b/ O        }& t  Z+ C- M2 C  v2 X' ]
        // N1069 S& F; y! K7 ^1 f2 _! p
        if( exsound_select & 0x10 ) {0 A, }3 R3 ?1 g8 C
                n106.LoadState( p );/ f. ]6 ]$ W  T/ j7 g
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" c3 J" p8 p+ q8 _1 [! K6 @        }. X+ F1 N7 \+ J/ m; H) c
        // FME7
& t/ x- q. B) h- H        if( exsound_select & 0x20 ) {7 W  Q& t. D# T# M/ f. v- O
                fme7.LoadState( p );
5 e' n' d2 t/ ]$ i* W' w7 M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding( h( K  l" E0 b# E- V3 L' X3 }
        }8 O) V. K6 q6 I2 Q. y, D) |# x
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 & c5 U* \, t( T: d& ?  q8 \8 c
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。' j: d2 D( G" m$ P
感激不尽~~

2 h2 f2 I9 B" C恩 我對模擬器不是很有研究," D7 ~. f! T% a% v; S- v; b$ w
雖然要了解源碼內容,可能不是很困難,
# H6 U- O2 v& L5 N! Q- s% z# Y不過還是要花時間,個人目前蠻忙碌的。
6 q: l3 c$ Z$ W% t% H5 F0 d, G( u9 E  [1 ^; G( J" @
給你一個朋友的MSN,你可以跟他討論看看,9 Q" E' `$ V5 s* G# q& E+ f
他本身是程式設計師,也對FC模擬器很有興趣。
! O2 n  C8 X6 Z) z) j! h3 X0 ^' g3 ^/ u. ]0 C" I
MSN我就PM到你的信箱了。
+ v! r9 J3 d  ]+ w% t
+ S2 v! P2 f  W! c. x, H, ?希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
- J6 J3 `7 w0 m3 |# m: c' a0 q呵…… 谢过团长大人~~

2 o1 e2 q5 q2 Z6 {5 J
/ A* m9 ]  o$ ~- o哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 Q( z" C; ]7 ~; y0 A: j团长的朋友都是神,那团长就是神的boss。

( s3 B9 H: e4 L: g& m5 r9 W! N6 d哈 不敢當,我只是個平凡人,5 F0 }0 I  \; |" ~# P% Z
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙" ^8 i% Y3 I. M6 Q
ZYH
( X; n) S  S: J; f. n* j1 V: DQQ:414734306$ q; _4 J4 z$ l# p( w
Mail:zyh-01@126.com
1 w. _# H3 U; d# Q: q* x: w; p7 f
$ ?6 ~1 d( j& j: G% \6 ^; J  r他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
# I+ k* }3 A* w, B/ C再次对团长大人和悠悠哥的无私帮助表示感谢~~

( F' J$ ?9 Y, t$ J1 f不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-24 06:24 , Processed in 1.096680 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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