EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。8 j% d+ T% n% P6 |
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 U; t% _8 m' n; N0 g这里有相应的模拟器源码,就当送给大侠了~~
" ~% f% I- l: C% H  w5 ^2 ?* ~, hhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 W  m+ i! j2 D6 C能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ g3 N. o7 ]4 S& R" ?( d楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, b* Z' q9 z( \0 B1 z. S: G( m
这里有相应的模拟器源码,就当送给大侠 ...
  y" h2 Q# e/ x" x
聲音部分(Audoi Process Unit = APU):
. v% ?& ?& D/ U  l.\NES\APU.cpp
  |7 _+ Z) n- _+ [.\NES\APU.h
; l+ S, t4 h6 B' i$ R
' W9 K+ F' F* ~4 C) q. _- u; b1 E1 Q  {. t" j
影像處理部份(Picture Processing Unit = PPU):: \. k9 P' R2 N$ ]1 [+ C
.\NES\PPU.cpp
( g( E1 p1 F: J, S, V' u.\NES\PPU.h; U- T& d" b$ k' A- {

3 |) F' j% C9 H  L3 V/ x5 k0 U如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:3 N" D/ [/ b: o  Q/ _/ R6 u
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
% ~  O2 k5 M9 d  x//////////////////////////////////////////////////////////////////////////
3 }* G) s7 [, a" W//                                                                      //4 }8 ~0 v$ O& H0 J3 e
//      NES APU core                                                    //; \; U4 M, C  a0 c" E9 t
//                                                           Norix      //
2 o( a0 M! |; W//                                               written     2002/06/27 //
8 [( s0 T, K: r7 h: s//                                               last modify ----/--/-- //" k; f# m  q2 q7 D+ R/ V
//////////////////////////////////////////////////////////////////////////
2 u. I& n5 U$ b: d; ~! D#include "DebugOut.h"7 v9 l; O' i4 i5 U: D; }
#include "App.h"
: J+ n, X! ?. Z* ~( R# E+ d- j1 ~#include "Config.h"% p% e+ B( v' ^% }1 O
9 N) k4 d5 z5 Z6 r# p% t
#include "nes.h"
" H) k+ D+ u$ p3 W: c. a#include "mmu.h"' [( `, k: C: f% Q( z% B
#include "cpu.h"
; _1 m3 k! w, W. F: ?' l#include "ppu.h"3 `3 U; B3 V. S$ I$ C  p3 B/ h' S
#include "rom.h"
# E% ~- v8 N# n& l) h7 |' b& E#include "apu.h"
$ q9 z& Q/ s5 p9 Z; E) d* F; z, O( _. E
// Volume adjust+ T; |$ g6 ^  X: O7 v/ b/ \6 F8 I
// Internal sounds+ T1 [: F8 X/ ?7 K4 W9 L  [7 M: A+ r
#define        RECTANGLE_VOL        (0x0F0)
( i7 E  E* E1 u9 L$ f& f! r7 U3 q6 ~#define        TRIANGLE_VOL        (0x130)
8 F5 N, K2 f" [2 \. T  g#define        NOISE_VOL        (0x0C0)
6 p# J4 M1 r* ~- V8 R7 h7 ]#define        DPCM_VOL        (0x0F0)
& p* }% [6 Z( J+ I: J4 B// Extra sounds% }/ j  b, f5 ^; o! F# t: c9 _: K2 t
#define        VRC6_VOL        (0x0F0)
! G3 s7 E$ X2 v3 l, k  k( C1 d#define        VRC7_VOL        (0x130)4 M6 L, s$ S4 C, o: G( U- ]% G
#define        FDS_VOL                (0x0F0)' u% t% B- J9 D! \6 Z' O. q1 c
#define        MMC5_VOL        (0x0F0)% N. @! Q* q7 u8 s8 [) Y
#define        N106_VOL        (0x088)
" ^% b, L0 `3 R% u* {#define        FME7_VOL        (0x130)* b- U. y# \$ D5 u: ^
# r: ^0 v5 h; T% _5 B% B
APU::APU( NES* parent )
& l. i0 M3 p% b$ X{4 o# ?% H; d. u8 @( f0 d& |. d$ E
        exsound_select = 0;
% F( L$ A5 [6 F% V1 ?/ k" N6 B1 R) a7 W% v, W7 U" l) L9 W. }
        nes = parent;! s8 s8 `, n4 n5 W
        internal.SetParent( parent );1 o( i% c/ f- O' R

( e6 e# d8 p2 T- C/ a' E* }$ w        last_data = last_diff = 0;
1 x, c% g/ h* Q* I  U
; f4 f3 N& G& B        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );( z- R% R3 Q* b% W, u' t( A" f
* p7 O$ K& z2 ?* i: H! x' I
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );) K8 Q$ X: i- M3 M
        ZEROMEMORY( &queue, sizeof(queue) );
) [, ]; a0 B: e% a: L2 g- w- J        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 ~5 G; ~7 m, v  o$ J
- R' n0 A, P/ r% n2 |
        for( INT i = 0; i < 16; i++ ) {
: o2 U6 U% C1 j5 c/ G                m_bMute = TRUE;
9 I% R% T1 H- u) P- V        }
5 F( l# `) @7 m5 e: ^}
2 g& W# g! W' j, O' J* [7 T. u' ^( J9 K: m3 {3 h! T. P
APU::~APU()
# n* B8 _9 _" c# e3 N{
; H* J! B' V0 \9 r3 v}
  J8 P9 v% B& i
: u- v6 \$ a  H2 W: H7 u2 G6 O0 Evoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
8 c6 u7 X& B% b/ c1 j{
6 u. P: ^# ^$ K2 F- p% n8 `' [# o' X        queue.data[queue.wrptr].time = writetime;8 a: k5 y$ U0 D. A
        queue.data[queue.wrptr].addr = addr;
' L% u2 {0 I) K9 Q# O- ^: G- \        queue.data[queue.wrptr].data = data;
3 N8 M/ p( r; h; i3 `+ J. b7 k6 ~$ h        queue.wrptr++;2 \* B0 l0 R& V% n
        queue.wrptr&=QUEUE_LENGTH-1;  {( j9 u6 O' f1 b; ~. O1 {8 N
        if( queue.wrptr == queue.rdptr ) {
1 G2 \. y* J) q6 o7 i( n; x6 f5 a                DEBUGOUT( "queue overflow.\n" );
) [0 e4 n2 ^9 w        }2 }4 J2 _/ a! ^
}0 B* i5 x5 x$ b* x

2 L" r1 @, m" c, I0 `; ^# TBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ c' i+ `7 I- U- v0 Q- u; T8 L+ r
{0 I$ b2 G6 I+ y- v# P4 m% m( g5 N
        if( queue.wrptr == queue.rdptr ) {, \3 w, @: [" M
                return        FALSE;/ r" W1 H# [8 `+ l/ q
        }
. V) r2 k* ?0 ^! O        if( queue.data[queue.rdptr].time <= writetime ) {
9 y: \) h. d2 p( T4 {: [                ret = queue.data[queue.rdptr];
/ D$ j; O9 n# M# l                queue.rdptr++;
" m( i' p$ Y1 k% @                queue.rdptr&=QUEUE_LENGTH-1;
7 r, O# Z' @- A; U) [                return        TRUE;
: k: ~% N3 \$ S+ s4 @        }* Q; R& |, ?9 `; i7 }' `
        return        FALSE;9 Q$ J% k& k" p4 }" d* }* c* Y
}% ?9 `/ I2 M5 c

, a$ u, w" A, P$ _5 Y" fvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
  R- t& b' r1 t+ n) U{
7 y9 |5 K! i7 \+ k2 _        exqueue.data[exqueue.wrptr].time = writetime;7 q( {7 M2 P! B9 |, o  v
        exqueue.data[exqueue.wrptr].addr = addr;0 e) Z( k% N" T' M# j9 P
        exqueue.data[exqueue.wrptr].data = data;8 P' l) H: ?: `
        exqueue.wrptr++;
- u( F/ E4 X: P- ?" y        exqueue.wrptr&=QUEUE_LENGTH-1;( _1 c7 s* F( q) J/ X, u0 T( I
        if( exqueue.wrptr == exqueue.rdptr ) {
- M5 F  s# o. N: }6 m                DEBUGOUT( "exqueue overflow.\n" );
; |. R- C& v, p# H# b* _        }5 \% W' `& `7 l; X& _1 k# Q' s
}/ f' e( i8 B1 t' E( P* o! E
, ^& t# }% E" l
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 N2 z) d* Y+ L- K* C% _- \2 r
{+ v$ t7 O/ I! [4 D0 j! @, K, A, p
        if( exqueue.wrptr == exqueue.rdptr ) {
" n8 g# B* q9 B3 ~8 ]" P                return        FALSE;
7 m8 {2 H) K9 ]1 z) i# d9 N        }
9 D; ~& D5 Y6 T5 B8 N& q6 g        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 P* v' s4 n: j( j6 W                ret = exqueue.data[exqueue.rdptr];, d3 d; D4 w( [6 {
                exqueue.rdptr++;" c  V; Z1 ?& B6 f% b! v/ B
                exqueue.rdptr&=QUEUE_LENGTH-1;7 }8 L( Q# K( f7 s# }
                return        TRUE;' r* L7 h- d2 \' J# L$ y2 T: \
        }) {7 t" X% }3 q. G: E9 C
        return        FALSE;5 s! [7 x( d2 Q7 _, `0 J
}! S, v; X: }6 L
4 a; }+ Y" i4 K4 I/ q
void        APU::QueueClear()7 o. |& v3 U2 u9 i* A2 d8 `
{* S5 o0 p; ^/ s2 P( @: Q. F% T
        ZEROMEMORY( &queue, sizeof(queue) );7 D7 p& A' |4 x; l* p9 o% L% w
        ZEROMEMORY( &exqueue, sizeof(exqueue) );% T- [0 `8 o" ?8 x  K
}9 R( I" y& G  ^' `  r6 S9 f
  p) V5 Z- o: P
void        APU::QueueFlush()4 q1 _, t+ e( W: h3 P
{
& e. o9 L7 {5 z1 E" E        while( queue.wrptr != queue.rdptr ) {
# ~2 b/ g0 P9 O4 p5 A0 X1 Z1 ?                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );/ _9 f  j! m& k& `1 H9 y# M& V
                queue.rdptr++;( y; x1 r6 K( |8 \
                queue.rdptr&=QUEUE_LENGTH-1;/ a5 `- j2 I$ u% W" V
        }
4 F0 J* _9 r% S; [/ B$ G, C% D; @
% B! [  f+ ]1 G) O3 E        while( exqueue.wrptr != exqueue.rdptr ) {4 {5 v9 H: s7 O. d
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );2 L$ l4 W/ x, y( A, G4 r* {5 K2 V
                exqueue.rdptr++;) E# S, L( @, S; z
                exqueue.rdptr&=QUEUE_LENGTH-1;
; P$ ^* s! E/ V! }# m0 H# h        }; T( @' o9 H/ O% `. ^" u
}
+ |5 ]9 W+ I2 S/ p! @
. H3 T) J  L6 b- Z3 K4 X% Mvoid        APU::SoundSetup()
0 k/ ~9 D: R- s{) u, b* j1 U$ g# Z5 \  |
        FLOAT        fClock = nes->nescfg->CpuClock;
% B. {3 K) k5 f$ B( N1 C        INT        nRate = (INT)Config.sound.nRate;. }0 n8 w5 C: t6 R) |& W' S
        internal.Setup( fClock, nRate );" o# O+ a2 a. O4 n8 q, `+ a1 i
        vrc6.Setup( fClock, nRate );9 g4 [* p4 r& \/ J$ Q9 Q) s% |
        vrc7.Setup( fClock, nRate );7 t# @" E; t! D+ f
        mmc5.Setup( fClock, nRate );
; ^7 _* L0 ]" M5 A        fds.Setup ( fClock, nRate );
8 w7 D1 l" |% R6 I: d+ B" {        n106.Setup( fClock, nRate );
; h2 ~$ c0 T6 {        fme7.Setup( fClock, nRate );3 k  l1 K1 j; O+ D
}% F/ [2 R& W. i% ~5 W/ R
4 m# v) _7 [! j: y; T
void        APU::Reset()0 E) Y9 T" H. M; H5 W
{
3 n  R/ T- I: A5 j1 i        ZEROMEMORY( &queue, sizeof(queue) );
- h$ Q, w5 e* ^9 v9 O! d        ZEROMEMORY( &exqueue, sizeof(exqueue) );  F# L3 G! f# x. n3 _& {
) N. V; I# g9 O% \2 `4 x
        elapsed_time = 0;/ ~$ m6 D9 o  Z7 D& I( Y% d: |

/ @7 i" k( L0 ?  r; P/ A        FLOAT        fClock = nes->nescfg->CpuClock;
0 e* ~9 p% a! S; _1 B: Y        INT        nRate = (INT)Config.sound.nRate;
* M. F8 m4 K. t! L4 r        internal.Reset( fClock, nRate );
" N& {; D) W  `; C9 o! h        vrc6.Reset( fClock, nRate );  j( S5 `# J  [' g
        vrc7.Reset( fClock, nRate );: R( ^  R% X9 g
        mmc5.Reset( fClock, nRate );
  Z4 ]* V5 ]: y/ _/ @        fds.Reset ( fClock, nRate );
/ U5 s$ f" {/ l1 T9 f) `        n106.Reset( fClock, nRate );
4 E: o+ i) t* Y5 g4 z        fme7.Reset( fClock, nRate );
; F/ B8 D+ Y, [4 C8 R
6 |4 {  p( L' ~' \0 }; e        SoundSetup();* ?) o2 j) g4 j: [3 u
}' n1 K( m# f2 ~% v9 I# u. d

9 N* l: A2 Y( j) D1 Ovoid        APU::SelectExSound( BYTE data )% l) S' |& @# Q- r7 e8 K6 z" h1 x  X* r+ N0 C
{0 y1 C6 p! U6 r9 B0 w
        exsound_select = data;- W  L' r1 `- l, ~/ u0 P$ Z7 D* x
}
2 h' P* u3 H% Z8 k
; w; O* G2 Y. c3 _4 R. t0 F& \BYTE        APU::Read( WORD addr )
/ W6 H" d+ h! r2 m) [{' v- _. ^9 x. S& S! w
        return        internal.SyncRead( addr );; ^5 C: k$ K" H& T: t' v
}
4 q: j0 w7 Y! s. z7 F/ U9 O  B9 P
& t7 Y) U. ~* i! cvoid        APU::Write( WORD addr, BYTE data )
6 F( \; L" D) P; U$ U" A+ N{2 J9 O0 k' M, w7 Q- |0 D( A
        // $4018偼VirtuaNES屌桳億乕僩
' u8 _& e# C( C7 z5 j1 X        if( addr >= 0x4000 && addr <= 0x401F ) {9 c) ^/ Z, @* {/ i% e
                internal.SyncWrite( addr, data );; Q2 Z8 N( V& ^1 f) d
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );. E- L( B9 @8 h% y5 r' N' U
        }
0 ^+ S- J6 i) o. I7 g}
3 ]% p2 n9 g4 w( r1 p6 [; ]+ u3 s$ k* x
BYTE        APU::ExRead( WORD addr )
  b7 b8 {4 b2 `* @; e4 W1 F) `' p  I; ?{
$ O; D+ G) b' g- yBYTE        data = 0;7 U. q: d; ?2 }5 C
; ^! S# c9 s0 Q7 }& s
        if( exsound_select & 0x10 ) {4 ~( Z7 a. R- Y5 x( w) b8 G
                if( addr == 0x4800 ) {
! I% v/ s4 q* J* `5 D# K+ l3 M                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );& P% s- l1 i7 s' h# l0 x
                }$ D9 k/ C! a6 G0 Y
        }, K. q. _, O7 c0 f0 t( B, h
        if( exsound_select & 0x04 ) {, W6 u3 J# ]* Z+ e/ V* _0 X
                if( addr >= 0x4040 && addr < 0x4100 ) {* O& i  G! [" Q8 W
                        data = fds.SyncRead( addr );
5 M% Q  m2 d' D2 W# z, O# F0 k. g                }
' _# N1 _8 P4 j6 F, B/ I! g) _        }$ x4 X/ V( P: x/ S% Y& z8 L( x
        if( exsound_select & 0x08 ) {2 x% i  q, g# u! n. r& y0 w. E
                if( addr >= 0x5000 && addr <= 0x5015 ) {& ~1 b& N9 p8 Q5 w, {/ w
                        data = mmc5.SyncRead( addr );7 f. K! |  Z1 g( |/ [3 M
                }/ H8 @9 e4 ~5 f0 R  _
        }
& Z( v4 |7 B% R. `3 S, z* z
" L) F  d( p% D7 b8 @* ~) [; a1 }+ {        return        data;
3 ]6 L3 @2 o* o}3 C. ]/ [5 [9 _0 Q% u% r

+ T) B& o# _- m$ L9 i. b3 f, }6 Avoid        APU::ExWrite( WORD addr, BYTE data )
2 i9 [6 ~3 a  z' `; k  H( G{
9 n$ \2 Y- Y' y# p, }        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 {# V$ ]( y! l: `
7 K7 T) Q1 K  C9 k; ?
        if( exsound_select & 0x04 ) {
" X. X8 G# \7 {' S# B% T                if( addr >= 0x4040 && addr < 0x4100 ) {5 M! q, k$ @* |
                        fds.SyncWrite( addr, data );
- W9 |. k* W8 p! k                }0 S1 M- K' b5 M* k5 m" `2 Y
        }- F8 r- [/ S: B, T" F; X

, }4 B/ p: F, n. o6 c5 O6 H- p( R  k        if( exsound_select & 0x08 ) {
+ E$ T! H( n* c                if( addr >= 0x5000 && addr <= 0x5015 ) {
* w& r! w* v! H! D3 W7 K+ J                        mmc5.SyncWrite( addr, data );
2 o( E9 {: f( [  A                }1 ?! s/ y3 t) L
        }6 Y  j# i) s% O/ F% R% u. ]6 V
}
$ v- V' ]- T4 j% F" ?/ c' A+ j% s6 x( \- f9 O1 p) @6 r8 b$ G2 U
void        APU::Sync()
' Z' d: P5 u1 l8 F! ]( e{8 u: @5 Z: y. G  k% u
}
! Y3 Z$ D6 Y) ?3 z7 D; C$ [! G
# I7 R7 H; F' v4 Q! M6 q2 f$ E+ {void        APU::SyncDPCM( INT cycles )# A+ Z! `& o9 ]
{* |' W1 D/ e: P' [8 K
        internal.Sync( cycles );  j+ t0 M$ l/ E

- _4 `; _4 S( ?        if( exsound_select & 0x04 ) {
3 a/ Q6 H' c: h" Y1 l                fds.Sync( cycles );
( t! ^' Q" Q; c. Y* Q/ @% {& N        }
5 A; G7 o! l/ ]# q0 ?        if( exsound_select & 0x08 ) {
8 P- [! ]* H5 N                mmc5.Sync( cycles );3 Z8 _, r! H; y" ]+ A8 C# u5 g1 ?9 L
        }$ D; R* l; e! x9 ?4 _
}; E* o& ~4 a/ q( a% }
/ c* ?5 [; O0 Q4 n* \- M6 y
void        APU::WriteProcess( WORD addr, BYTE data )
9 U/ |3 h# u8 b% T5 X{5 W2 v2 x: a  w3 m
        // $4018偼VirtuaNES屌桳億乕僩6 y& b% |' x% ?+ C" R0 l
        if( addr >= 0x4000 && addr <= 0x401F ) {
! T+ T$ N9 a7 j! r6 ]2 H                internal.Write( addr, data );5 q0 L  d" m/ ~$ Y! L
        }
$ q( q# P' |% X3 A6 `8 c5 H}
% a( b! F2 L4 `  _
) _8 H2 o6 O2 D4 nvoid        APU::WriteExProcess( WORD addr, BYTE data )
( C4 K: O2 ^, j% K4 o' Y% T* N{5 Y6 U( r  {, k5 x( V* i- ]& o
        if( exsound_select & 0x01 ) {) o% Z( C9 D/ }: w
                vrc6.Write( addr, data );. q0 Q1 h! O- x) Q9 h' k: E0 F8 M6 @6 u
        }
. a  F, u$ w9 f' ?        if( exsound_select & 0x02 ) {
; f# L, A5 m% k' o5 `                vrc7.Write( addr, data );% d+ [0 ^. w+ D3 \# {+ v
        }
3 C( E0 ~0 N: G0 r        if( exsound_select & 0x04 ) {
3 G  I7 W6 A5 Z- R! m* x4 I. M                fds.Write( addr, data );
3 A3 t6 l6 q9 w/ A' I        }5 r5 ]  @$ V" m" ~* k; j! ]4 \/ b
        if( exsound_select & 0x08 ) {
. p  q; m) l5 s/ U5 ~: Y                mmc5.Write( addr, data );, X) I$ i' Q% s# c( j' n8 ~  Y
        }
( z, Y4 [6 b/ [* s. {6 D0 s        if( exsound_select & 0x10 ) {
' H  t/ q8 |4 E: z5 z) P                if( addr == 0x0000 ) {
# ^6 P' Z0 c+ C- y                        BYTE        dummy = n106.Read( addr );
( h& m* K% M/ G9 \! {                } else {
: x: Y! w  ?7 z' l  U" r( v                        n106.Write( addr, data );
- ^2 B) M& O. f/ I' E6 g2 p7 |                }
8 g/ O* P$ ?7 I        }
/ C9 ^1 ~( j% r; ^        if( exsound_select & 0x20 ) {
* D* m& H# i0 M. L6 r                fme7.Write( addr, data );
# V; }1 G* i5 N- R$ P8 z        }, I% G( e+ e+ ^
}" d$ m* J' [; N
/ Y9 [& }+ J1 m
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
# }" n  j: A$ ^, r{
; _+ v  d9 r, b6 f' F, F9 fINT        nBits = Config.sound.nBits;
4 U! u, S; N( B2 f; _8 h- t' PDWORD        dwLength = dwSize / (nBits/8);
2 }) A. `; T; s# f+ _+ GINT        output;
; O# ?7 M& S1 Z) I. i7 H. gQUEUEDATA q;
9 o9 n3 \/ G; @! PDWORD        writetime;6 d+ y! a5 |7 N! _7 @- [# z
4 V! `3 a2 f8 n# |$ i1 q
LPSHORT        pSoundBuf = m_SoundBuffer;
1 `2 x+ H0 l6 H. ^+ N: a! N) QINT        nCcount = 0;
7 I3 _7 U3 _: Q# I) a9 ?% o: ]- G# L8 v' P3 Z) w" `
INT        nFilterType = Config.sound.nFilterType;
( L1 l  b2 d6 W0 B" L
# b. P, m4 C! k8 M        if( !Config.sound.bEnable ) {
7 u% C0 y! ~! |7 k; v  C# U                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
4 [; X, Z0 a6 a0 q- e3 B  I                return;
8 `/ u: u* v% z5 ]% ^. B        }
# o  Q( S* y, l9 x
* ~4 v  \4 }& l1 q        // Volume setup
/ X# W# z5 t/ U1 b: v6 x: E        //  0:Master
5 B5 A8 c' q0 I3 J: {! w9 j# U        //  1:Rectangle 1* p" G" u  [2 M- a
        //  2:Rectangle 2
( v9 \- h+ J7 ~. Q7 [8 h9 a* f        //  3:Triangle5 H8 s3 V% T7 E0 s" m. j
        //  4:Noise
& {: p# l3 d( U' T9 Z: D7 l( j        //  5:DPCM
1 `8 f" F' y) N        //  6:VRC6: [) P8 ~5 t8 H) W* `
        //  7:VRC7/ j# ^3 @0 ~6 X. b  J* ~; m; U
        //  8:FDS# {( n  g7 H6 O8 s( ?2 @- m2 a
        //  9:MMC5
% F, ^( K3 |  r$ s0 g8 `        // 10:N106
" f) |# m* f8 Q2 I) ?! z        // 11:FME7& R! Y1 n+ W4 n% E3 h. j( Z2 n6 W
        INT        vol[24];( O9 H" y( E& r4 y; |
        BOOL*        bMute = m_bMute;- y& X5 R) z+ C# `2 S  x- V
        SHORT*        nVolume = Config.sound.nVolume;
' I" I5 x6 j1 R7 x) U2 W- s! ?
" v8 `* i6 A! y- ]- r        INT        nMasterVolume = bMute[0]?nVolume[0]:0;  k$ G% t9 p! A3 B
& ]2 J& l, f1 z: j% G, t
        // Internal
5 L' U  f) F" x& f" e+ I  ]        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;* o: N+ t+ l1 o- D
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  O1 L1 b0 k# h- v0 T
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;. `9 t5 q) W1 W. o: l9 j& h, x
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' L$ n8 H3 ?# ?4 Z. Q/ Y- ^
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;9 d, R& }& ^: D+ x6 f8 _2 s1 w

9 x7 t9 E5 \8 w, s  J& J        // VRC6& l/ H% U7 p8 \* i1 _% e/ p
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 K& \; f2 d2 J# i4 M        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) {$ w! ?9 H7 e) I; l$ ?8 x! F* s
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" C6 L# n* A" |

5 c! B2 W/ w' s4 U7 t! B        // VRC7) Q: n; a) o* Q. }9 w
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;# b- L4 y/ W1 x' K

2 u! i. p( A, B9 E/ H8 V+ A6 ~/ s        // FDS
6 j: X+ o4 W1 h        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 j% y& {. W# h; _, R' V: n# u0 `
. H& Q, I* y1 {( ^
        // MMC5
5 k+ f# k! j$ O        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 |5 s9 J* w! a, X5 n. ]; O        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) M# y3 n/ B) ^/ k
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* D( z; r3 v" A* A9 g! R$ B2 Z' a& [$ m0 M9 U- I4 ]. t
        // N1065 l! o5 z+ Z" z/ T3 _
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 G$ f4 P. P1 D+ O( W$ `
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ Q% x0 t3 {+ @, J; |7 x
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. C3 x: k# @, n1 A        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% Z! r4 V* b& |9 R( `6 W% }" Q( r        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ Q5 S8 i6 S0 ?, n% [; k; f1 T/ \
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 P6 ]$ w  ]' P        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# P$ h! e6 J( d' i7 t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ ^/ d  Q4 |& w! d# _: x7 @

( g7 W* L, L8 F2 Z8 R) n1 r. [        // FME7
: |. I' t/ e. B2 R) Y        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) q" M1 f* i; t8 v! }4 c0 F
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;+ [4 Q; |" ^7 w( w: z
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 {: G$ ]0 y. m9 f* H
, ~: S- u# }* b. ~* P0 q$ ]
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;" z, p+ u2 z9 U
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;5 |" Z, {; l0 g- U, _

) L# X9 y4 h$ B# h& I        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟# w& i8 P6 i- }1 E! s( I1 ^) g+ v
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {% B4 D4 U2 w+ ?
                QueueFlush();  w' ]: c0 \" @7 V8 h. Z
        }
% m! S/ V" W1 s+ K! h* A' P) j' e; `; \
        while( dwLength-- ) {
5 C( {7 b  w2 B1 E% x4 w                writetime = (DWORD)elapsed_time;- v0 d$ A) ?+ D$ @' ^* O

; S% s+ z6 u% {5 ]2 d' W                while( GetQueue( writetime, q ) ) {+ ]; l4 A- R  ~) ?. F
                        WriteProcess( q.addr, q.data );
! j' d) v8 E9 b% j* _4 c1 I! r                }! a' m, e' e! W) m
. Q0 Z3 e( n4 ]* ?" B: i/ M4 v
                while( GetExQueue( writetime, q ) ) {
/ \, v$ ~& q7 m9 P9 z& P                        WriteExProcess( q.addr, q.data );# X  T/ [# F& k' G4 ]. T/ f
                }
* O6 S. ~1 Y& f0 ^4 K: W: ~) H( G- M4 w! Z" H( \
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
5 N/ v7 [' k5 ]) ?0 W) O% z! ?                output = 0;2 k$ d, C$ |+ a8 ?$ j8 m. H
                output += internal.Process( 0 )*vol[0];. ^% W. U& M+ c8 I
                output += internal.Process( 1 )*vol[1];& k% G8 w; f3 j$ v) G
                output += internal.Process( 2 )*vol[2];& j  a" r0 U" {8 {: f+ h
                output += internal.Process( 3 )*vol[3];
. ~2 s& e' O) L9 h                output += internal.Process( 4 )*vol[4];
  m' I% W: \5 O: V% U  Z/ K) n; K
  c% z( y( j2 D, F                if( exsound_select & 0x01 ) {. t0 _# P3 A' U+ `
                        output += vrc6.Process( 0 )*vol[5];% ?& y* Y- ?0 Z% y
                        output += vrc6.Process( 1 )*vol[6];$ i- k: Q4 @. h2 J. Z  e
                        output += vrc6.Process( 2 )*vol[7];9 @% y& [5 C) A! E
                }
  U! ]3 K2 H( [; |5 C: B8 z                if( exsound_select & 0x02 ) {
$ R/ n6 T% v% r0 o                        output += vrc7.Process( 0 )*vol[8];
" Y1 L9 l& S8 z) j: v+ T9 J                }
  S( Z0 Q9 b+ W+ ?                if( exsound_select & 0x04 ) {
3 M- z& X. W; T" q4 E) o5 `, K                        output += fds.Process( 0 )*vol[9];
- N# Z" P5 Q) }/ ~  _# J- G$ T! N                }
+ U) v: p% i* H% y0 f" Y                if( exsound_select & 0x08 ) {, Y5 s9 L+ ?4 D: J9 ^
                        output += mmc5.Process( 0 )*vol[10];3 O, x" `+ c& y1 U: i1 P
                        output += mmc5.Process( 1 )*vol[11];
* `* r) R, W+ p: b$ I                        output += mmc5.Process( 2 )*vol[12];
3 u% T* M; c$ M, ]& o6 {. F) i  p                }) T6 K, ^$ H! U6 H/ [! o" p; w
                if( exsound_select & 0x10 ) {: Y- S1 F/ C9 y+ Q
                        output += n106.Process( 0 )*vol[13];9 P& v" v% I, B- ]" G
                        output += n106.Process( 1 )*vol[14];. |' f( {& ~( j# j3 K6 S' V
                        output += n106.Process( 2 )*vol[15];0 ]0 i' T0 n. y# k# g( n
                        output += n106.Process( 3 )*vol[16];0 [4 D$ ^1 ~& L' M3 k
                        output += n106.Process( 4 )*vol[17];
3 s  l, f4 d: v) w                        output += n106.Process( 5 )*vol[18];9 `4 _$ s6 D) l( V% O% ]; z
                        output += n106.Process( 6 )*vol[19];
0 B) G" A2 A. f                        output += n106.Process( 7 )*vol[20];
# H3 J7 E3 N% {& M8 h$ g7 @                }' w" q" ~5 |% F" ^
                if( exsound_select & 0x20 ) {4 }! q6 `  Q0 J9 s% p
                        fme7.Process( 3 );        // Envelope & Noise. Z2 M: J' p$ O, Z% M
                        output += fme7.Process( 0 )*vol[21];
6 h- g( R7 b3 x8 K) p+ D- b                        output += fme7.Process( 1 )*vol[22];( r8 E$ ]' ]  Q7 s4 u$ a3 F
                        output += fme7.Process( 2 )*vol[23];
6 n0 e; }! j- |) E3 r" ~5 d                }& n# ^# s8 i1 z0 k

1 B  M# w$ M2 H+ l; t+ Y1 e0 y                output >>= 8;6 f! M3 r( T0 _! s" G+ d: @
" s! c# a/ x# D7 g0 @
                if( nFilterType == 1 ) {
& o7 h: B- u3 w# _                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), d  W: T/ J: c, N# T
                        output = (lowpass_filter[0]+output)/2;/ K6 w4 f& L. T2 G% }2 }6 p4 [0 L
                        lowpass_filter[0] = output;
. `, @9 D9 Y+ }3 ]2 T                } else if( nFilterType == 2 ) {
8 A# A  ~+ G) g                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)3 w! a- ?# h5 f# G  E% a
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
7 {6 z# N* Q" p! W9 e                        lowpass_filter[1] = lowpass_filter[0];+ k4 @: _9 V% o  _2 {' l! ]' Z
                        lowpass_filter[0] = output;! r# o% [$ \0 r6 T
                } else if( nFilterType == 3 ) {
! y  O7 U- `* P8 K                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)$ k9 U. o' y1 }) A4 Q
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;8 U  {/ M) v" p- i7 G# H1 r
                        lowpass_filter[2] = lowpass_filter[1];$ R4 e- G* U: V# O
                        lowpass_filter[1] = lowpass_filter[0];' f& G( t3 M3 K
                        lowpass_filter[0] = output;% P$ C8 h: G7 ^# h; M
                } else if( nFilterType == 4 ) {& |/ y# E0 X9 y$ X: t; r7 n
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)2 ?) A! }1 }, n/ j4 B
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;* h5 d9 j7 ^# q1 }. v" s
                        lowpass_filter[1] = lowpass_filter[0];, K  E8 |. M" p: }  J8 T
                        lowpass_filter[0] = output;. L4 ?7 N* ?3 G% n
                }
$ ^3 A: j% Z$ r, Q5 D/ S: g; h4 Z' e8 C6 W
#if        0
5 v: c- u; D: g9 Z$ m                // DC惉暘偺僇僢僩- I/ B5 y+ B4 Z2 F  D% M/ |
                {
# d+ E4 M6 D2 x; L1 I4 N& m& y                static double ave = 0.0, max=0.0, min=0.0;7 Z6 e0 O& \$ F( a$ Z+ [. m
                double delta;3 r$ V1 C# _+ Y! P) C% T& x% o
                delta = (max-min)/32768.0;
' g: y/ b5 j3 |% t' h0 g/ [3 ]( ?                max -= delta;5 }4 O4 a4 \1 |6 V. X
                min += delta;6 I+ L! N  N4 n) d, ?/ b' M
                if( output > max ) max = output;
. y! x4 W# J; b- t- J' X! p# H                if( output < min ) min = output;, Q0 u! n& N" `; C% J+ _
                ave -= ave/1024.0;
8 a  ]0 g( D, j. W/ |5 R                ave += (max+min)/2048.0;
( {& l& b. Q9 {4 e+ H                output -= (INT)ave;  [8 U( V9 a$ S3 p
                }
' Y  x$ n6 S: L0 c9 ]#endif5 K$ S- {; ]+ f, j1 j0 {5 O4 |) E
#if        1
, z3 W0 c9 `3 a' B                // DC惉暘偺僇僢僩(HPF TEST)
* x3 S* d0 ~1 s2 E9 ^' [$ u+ a  T                {
, n9 L+ C* F% a2 g+ Z# i//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( j' ]7 g8 O: u3 v
                static        double        cutofftemp = (2.0*3.141592653579*40.0);% _! A: Q( v, j$ T
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
* K4 c$ E; t7 z2 G8 j: m% J% o' n; ~                static        double        tmp = 0.0;1 V* ?2 h8 K; S+ M/ R! ~
                double        in, out;
! X. F( y8 l0 [5 o
1 `/ W6 s% p* Y                in = (double)output;9 y+ r9 ?6 T" K% Q- T, Q& t8 ]) H
                out = (in - tmp);
) b  T0 A( Y+ I4 G                tmp = tmp + cutoff * out;
$ @$ `& K/ X! H) ]( f* ?# O) w: p5 Y3 k: N1 O* b' I: p# t' G
                output = (INT)out;) \: ^. l) j4 Z* P  W
                }" t7 }5 b  j: f; e; F+ B& c
#endif1 f0 e+ \1 g+ j4 Q' I$ _
#if        0" i2 ]1 ^6 g) g
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)3 ~  q1 H1 x( ]  g" O) n& E6 A
                {$ W+ L! D: D! H- Y' _9 }$ Z! P/ v. k
                INT        diff = abs(output-last_data);
+ x! }: s3 ~0 W& G4 U  W                if( diff > 0x4000 ) {) M4 B" E1 ~2 M2 d- p' p
                        output /= 4;$ v5 Z- {* O5 j, B; l
                } else ( w; r6 |) i# Y7 {1 |% p( e
                if( diff > 0x3000 ) {( \7 Y9 R1 G* \4 c8 T
                        output /= 3;7 g+ Y/ }, \+ N+ H4 ^" M
                } else/ n0 g4 T. [5 C5 U
                if( diff > 0x2000 ) {. u1 V- ]7 R& S7 q8 ]  n3 R; e# V
                        output /= 2;  C* S1 J+ [0 y  {" I, r
                }; Z0 @  a: d6 W* n+ @
                last_data = output;
5 d7 ]5 l; v7 E2 s; I3 i                }
2 o. j- P6 T; t6 b  u+ \/ `' t#endif' g- j) J' [8 V) w' Z
                // Limit, [  t. [& ~" |/ {! k" @; u+ |
                if( output > 0x7FFF ) {
( g2 ~+ o' P# P# A9 ]9 N                        output = 0x7FFF;- c4 G! @6 A! `+ i, f- l" y) J- T
                } else if( output < -0x8000 ) {
& s. `7 N& X9 X, p0 W4 b0 n$ j                        output = -0x8000;
& o" y4 C4 f5 [3 M                }! B5 X% M& D! B2 _

: |: }" r0 V) R7 S: [9 _& s                if( nBits != 8 ) {% F4 m7 q- Z# `. r5 `; z- j
                        *(SHORT*)lpBuffer = (SHORT)output;
2 t$ k. P8 }+ L, E6 p$ s                        lpBuffer += sizeof(SHORT);
! i0 `+ ]% o8 s. b* c                } else {
/ S# |- G) u# Z                        *lpBuffer++ = (output>>8)^0x80;
1 ?3 D  y2 y# @, c: l                }- Q# D6 |* k0 G: K/ A0 ^

2 F: V( Z7 P+ `* o                if( nCcount < 0x0100 )
) J2 s' e+ g* E7 I                        pSoundBuf[nCcount++] = (SHORT)output;
3 |3 o* }3 j8 s# o& F7 `6 {/ c& w: a) G3 T
//                elapsedtime += cycle_rate;
. `8 p5 D! X. F. M                elapsed_time += cycle_rate;( e) W5 A, u& V" h
        }: Y( ?# J$ `% n5 A0 s, ?

+ ?, q+ P* \' O8 ~$ g#if        18 d( k% {0 l, z5 b$ K
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {! t- `  A0 h* x7 j; _
                elapsed_time = nes->cpu->GetTotalCycles();
% L. T% N/ O% x1 l- M7 h7 D( l        }
! w9 o5 k- A; p. d! f9 A        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {* ]5 B% [# s6 r, T. {9 k
                elapsed_time = nes->cpu->GetTotalCycles();
1 e7 l: \0 u8 U8 D& Y7 @        }6 P' _5 v2 X1 N8 ?
#else4 n4 G. [' y! j! k) m5 w0 l
        elapsed_time = nes->cpu->GetTotalCycles();  K- L% |' g9 r" k" |  T% v. u
#endif! _5 ^0 C( U3 a) s
}
" m* `4 a, O5 c* k
# s; z0 N) z5 B* o. ?// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! y  y! b% ~2 p1 ?9 `INT        APU::GetChannelFrequency( INT no )
7 T. ?! \7 E: ~8 \. s4 h/ x{
7 Q& q3 }& G  A& u4 @; [6 u3 ?        if( !m_bMute[0] )( \( K. `* g; X7 x
                return        0;/ M% ]1 f+ S/ A" B, m2 t

2 F% `. p9 P; @" Q4 W; F1 x        // Internal
' h% v* ]( G6 ?" }9 }        if( no < 5 ) {: m: B& _6 g! w/ h5 h# r
                return        m_bMute[no+1]?internal.GetFreq( no ):0;0 A/ X8 }6 q9 E, L* z
        }  l- i3 I9 C) j* L
        // VRC60 O/ b! S$ v$ K" ~; T) Z) J& ~
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" A0 V& n4 i: @* v' z. i/ L                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 b, R/ g, K2 O) Z        }" v8 a* i" R: `# @* D) d6 s
        // FDS
$ U+ R4 s5 R( i& P& ?        if( (exsound_select & 0x04) && no == 0x300 ) {' S$ j4 m% J/ d& `
                return        m_bMute[6]?fds.GetFreq( 0 ):0;7 {( l5 [2 J& N4 a
        }) |7 f8 T1 s6 D
        // MMC5
% ~, u# F- \+ K$ O) A: _        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {3 ^9 i; e7 K- D; @# `
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
% o- ]) g/ ~# n. @- ^- l, T6 }& L        }
6 k6 E/ o4 H+ p$ l        // N106) i8 d$ ~- t) J0 T( \: ]5 }
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
: ]8 J) m  l5 h; y7 Q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
7 N* n; [1 z; S0 a. B) n3 L        }
, o+ ]7 {7 S* ?; b% Q5 p        // FME7; {# F5 M! ^5 A. c
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {) ^$ }( Y5 p: F$ b# B
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;/ q; c0 ]: q5 e! t
        }+ Z8 M2 B. e& H+ U% _
        // VRC7
% c9 |  F' \  c: _, a        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
3 }" e3 W# B+ x* V4 s9 J5 S' y' v                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;5 O7 ]% [4 {: d  X9 J. Q. g$ z
        }/ a5 {  K* _. p. N$ h' h: i/ e
        return        0;4 f$ l% C% j3 J4 p
}' M* P$ Q" d; ^' s5 G( r
5 j* s$ R1 A5 Q* F
// State Save/Load
0 c9 d. u3 g9 U% H4 G( V+ B  m* ^void        APU::SaveState( LPBYTE p )
/ ]% r- Y8 ]9 B. z8 X+ Q{8 d$ z1 {* O4 P5 b
#ifdef        _DEBUG
$ G( V; \+ O: uLPBYTE        pold = p;+ Z% m* q9 A0 z! F0 V7 k
#endif- F- G8 s0 {1 j% F, G9 P
2 L' l7 h! p1 Q) U! W0 Z- M
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
% ?/ N7 b: f  j# j8 h        QueueFlush();8 l& u) H' Z5 p. u' r1 N
0 z& B3 {9 N' k6 W, }8 A0 L6 {/ p* q
        internal.SaveState( p );" k$ F( O9 r) u8 c
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 _3 p7 Q/ ^1 c5 I3 b, L$ T7 \8 {( O; V8 W+ {( a$ t4 ^
        // VRC6
; Y3 c$ Q# i6 ]) d( o1 ^$ _        if( exsound_select & 0x01 ) {
: j! f( V7 f. C  G0 G                vrc6.SaveState( p );: r& O. F* h- |# E- z  m" b
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 N& Q" C; }6 q' m' a5 Q
        }6 i( V( K" Z2 A. o( D9 O
        // VRC7 (not support)
* U! ?& f5 O- x5 u8 p0 e+ ^        if( exsound_select & 0x02 ) {: ~) P% O. ]' k5 E8 e
                vrc7.SaveState( p );+ ]! H5 H5 H# e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
# E& ]4 Z! A9 [6 v7 c$ ^0 d# M. [! Y2 r        }+ L7 W3 Q3 w, K9 y7 ]/ E9 }" I& H
        // FDS
' j5 u) k( o( o2 `6 F        if( exsound_select & 0x04 ) {# c3 `8 Y8 _- X9 l  x- ~% q
                fds.SaveState( p );- X4 q8 U' R: ~
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. W1 g# v$ N: r. }  I7 K        }/ V9 N0 J& q* L* D
        // MMC5
+ H% L/ a# t6 Z. \5 j        if( exsound_select & 0x08 ) {8 ^2 p# Z& O* o2 F* [+ M- J. k
                mmc5.SaveState( p );
0 q) S  A' d* a                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 \; {& _7 X7 R! v0 Y" ^# f
        }  r  m  u+ l: q- t
        // N106
# s- i( q; T/ D0 `3 q        if( exsound_select & 0x10 ) {
0 [. d7 {: I- {1 N# r                n106.SaveState( p );' V7 `! L. K0 w- W% x7 Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, H- W0 }& i, I2 ?' @9 S        }% l& Q6 b3 |  [7 F' j
        // FME7( A+ D; F1 E. l* ?% s
        if( exsound_select & 0x20 ) {+ l* o! M$ q/ ]/ `" I( g
                fme7.SaveState( p );- @; w- o! d& }. `
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ p( O1 o/ J; ~3 c
        }" u* b) N3 ]" c1 M2 s) j/ O  _8 t
& b# O- [- E: ~* v' J2 z" L
#ifdef        _DEBUG0 i( Y+ R. }* N/ G% `: N
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 u1 S+ D+ U0 Z# y#endif
* y  C3 ]! B; W# P0 Y5 j# [+ Q' Y: n}* D2 {# J, i9 E" r% f

# ~( l- X/ y! F8 \2 j2 s; Xvoid        APU::LoadState( LPBYTE p )2 A: h, i1 k& t' Z3 n, @- \
{
0 @. Y) b  x# [7 W% U  |! a. Z& Z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡+ D9 @1 z" ~4 ~8 c, F
        QueueClear();
5 g" z" O4 o3 A, P+ j, w* L: g7 }9 U0 W4 Z
        internal.LoadState( p );
& g% k- y# c$ ^1 t9 l2 P        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
7 E0 [$ z3 T) e5 Y
9 G$ b1 J; z/ Z9 p& l" b        // VRC6
' V" O; @$ Y8 I4 T, k3 ?        if( exsound_select & 0x01 ) {
. C2 ]! S9 t1 |& Q) _                vrc6.LoadState( p );
$ y4 m9 }1 y+ b. c                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" t% q7 u7 E8 ?" i        }5 @7 @, I6 S0 i& P
        // VRC7 (not support)
: M: G$ l4 S- F# q& u        if( exsound_select & 0x02 ) {8 F( l7 z7 C! w1 v; s: V
                vrc7.LoadState( p );% j! J! z2 V' u- L
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% D/ v% W; j- P  P0 V, L        }
' J0 L) ?9 B% {        // FDS, Z" G; N6 n  M+ ^; @/ n. r8 T
        if( exsound_select & 0x04 ) {/ @! T3 Q0 @4 ~& g& |
                fds.LoadState( p );5 W  S3 I2 U2 B- }. r. g4 C* L! f
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 i: I! E4 C+ ]! D1 a/ x
        }. u+ B+ `* d5 S8 z
        // MMC5
' x3 c$ W2 R' F$ X% ~5 }        if( exsound_select & 0x08 ) {. K; E2 Z/ Z, G* U" M5 i7 j
                mmc5.LoadState( p );
( m0 t4 Q. @# j/ {                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# \7 k: T- M7 @" u) J& _, l2 \        }1 t) l3 ~7 `7 U/ D
        // N106* T5 N: z' Z0 X& l) V; j
        if( exsound_select & 0x10 ) {
1 K! _  e! B% [, l% F                n106.LoadState( p );
* b) `5 q: A4 ]2 O6 M                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& |# g" b4 ]( u# P+ X- N% s, A" M2 {
        }& Z! F0 L. _4 @4 n# t5 b
        // FME7+ U2 [: [" P( g: S
        if( exsound_select & 0x20 ) {
6 x. U* n9 r  g# S7 v  w                fme7.LoadState( p );7 \" x8 ^* E& C
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* f% @# s' o5 ?" G( L6 {* Y0 p        }
7 U- Y5 {& z  d1 v6 Q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + z" W/ I" r( z1 S+ \
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
0 ^8 C2 C: X$ @  _# b, O感激不尽~~

' p% L6 n# [! u0 U6 z恩 我對模擬器不是很有研究,
9 S9 D7 _( ]5 x: E雖然要了解源碼內容,可能不是很困難,
  @3 t( r; t! E0 w9 ?2 M; z不過還是要花時間,個人目前蠻忙碌的。
8 O8 y5 m) O: i! A: k
) e, y+ ], s4 T給你一個朋友的MSN,你可以跟他討論看看,
: \% s* m) o  c7 X. W( S他本身是程式設計師,也對FC模擬器很有興趣。9 U9 t5 G& s' C7 G2 A

  s* P9 [5 ~8 s4 R, Z/ `MSN我就PM到你的信箱了。
3 h; ^- I& {: k$ b) m3 Y; u
2 l6 x2 Z5 y# M2 T3 ?$ A2 ]; G. {希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
5 ]; M: d# v2 h4 Q8 x& o呵…… 谢过团长大人~~
' R6 p: \) G6 x$ P' X  X

- k+ m; f1 c2 O" E3 b# W哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
% T/ k% K; c8 D" ?$ }: O. r团长的朋友都是神,那团长就是神的boss。

* v# p" Z' T" }6 O2 |: s哈 不敢當,我只是個平凡人,
, n" q9 H/ E3 ~( i/ y3 Q$ {( }要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙" ]6 S( g& k' U! d: \
ZYH; @" A6 ]  W3 e  x
QQ:414734306
5 T# b" M: C2 H$ U  NMail:zyh-01@126.com
4 m: V& c6 @, C  {# q5 f
4 `7 D. P; k5 e他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 $ |8 q- Q$ N3 |! E) ~
再次对团长大人和悠悠哥的无私帮助表示感谢~~

9 D) r) |* f+ i& k, q不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-18 07:37 , Processed in 1.099609 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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