EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?+ H5 K% e* d- R. d6 [% G
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 D2 K- J! M0 F3 t9 l& f  A楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 W2 B* w" d# z- `0 |5 M, T) K  k
这里有相应的模拟器源码,就当送给大侠了~~
4 I: d  g4 R& D& `$ T" ~http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
9 F( V+ k' `* E1 T- E能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. H6 P" E7 _+ V; D9 Z  G/ l# r
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( i* Y2 M! m3 ^$ }0 ^$ x这里有相应的模拟器源码,就当送给大侠 ...
& }$ `4 L; G+ {2 ^* s1 F
聲音部分(Audoi Process Unit = APU):
0 W; `& _  J4 z.\NES\APU.cpp. W) {. ?! B+ w1 s( c$ J
.\NES\APU.h8 M: n& K* j2 V3 r2 u* b% f

& Y8 C3 T& n. e# Y2 S
$ w! I6 c8 x9 z# S: w7 d2 a影像處理部份(Picture Processing Unit = PPU):
; ?& y% o6 d- n.\NES\PPU.cpp
4 V& U7 H% X% u.\NES\PPU.h# t. ^; f8 a* y, H7 f* M. e( S1 {; y
: d" w9 K' b! e# u. t
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
+ A7 b  I4 z0 U+ f" N(由于很多专用术语和算法机理都不明白,所以看不大懂……); p2 C, Q. D2 u8 _
//////////////////////////////////////////////////////////////////////////
) U9 X$ g6 q. O( h4 Q//                                                                      //1 \5 a8 S3 s% C* ^; ^, g# n2 }4 N- J
//      NES APU core                                                    //
9 F, p! a& t6 Q4 G1 p//                                                           Norix      //; F8 G# a- |- j8 n) X
//                                               written     2002/06/27 //8 |8 J5 U4 ]. A+ K- k
//                                               last modify ----/--/-- //: Y: ~8 x, Z7 m% U$ g( g
//////////////////////////////////////////////////////////////////////////* d0 D; j! n' c- i2 T! V
#include "DebugOut.h"
5 l7 D: x& i& w5 `: c  |# I  |#include "App.h"6 u! h3 R  K5 H( P3 C8 _0 O" i
#include "Config.h"/ y) \: j8 L: b
6 {1 w& m) v9 Y( Q1 R. T
#include "nes.h"7 N5 q0 y' g* _- e2 K3 {# W
#include "mmu.h"
. v$ s% X7 k6 }; G0 o$ p#include "cpu.h"
# \6 F" `0 l  h# j& I3 r#include "ppu.h"# E* u& c& t0 F
#include "rom.h"
+ ?( \) X. I+ m#include "apu.h"* ]0 \* k2 D8 [  L  f0 N9 N3 g

5 _1 h( s. {2 X  r: f7 x1 c// Volume adjust
; T* u7 u- C4 d' \5 Z1 [5 m, b' M// Internal sounds
, N8 e  ~0 f3 c6 k* D7 {* M8 l; S( x#define        RECTANGLE_VOL        (0x0F0), Y: w) W+ k/ D* l/ H/ h  l
#define        TRIANGLE_VOL        (0x130)! N% c2 S* H: v& n
#define        NOISE_VOL        (0x0C0), c; b; G2 `  W  o& @7 V" u& R' A  @
#define        DPCM_VOL        (0x0F0)* a3 \3 l7 F9 `; E4 s% z! C
// Extra sounds
5 t0 z  y: V* n' d#define        VRC6_VOL        (0x0F0)3 _8 W5 |$ ]. ?: J" N4 C, Z: f
#define        VRC7_VOL        (0x130)
7 a. D% I' U4 W. u) S1 Q#define        FDS_VOL                (0x0F0)
9 h8 S4 n, W! R% Q& G2 `, Q& ~/ T#define        MMC5_VOL        (0x0F0)" p! X$ r" A, q/ t5 J- t( o: b9 d
#define        N106_VOL        (0x088)3 M. G$ B* v. C. }; {' g
#define        FME7_VOL        (0x130)
0 X% Z, }- l! s! C2 y
# F: P3 E3 y! B6 AAPU::APU( NES* parent )- `; k$ A6 ]  i2 u/ X- b
{0 J$ a/ O3 W0 s( [0 I% R; o( X
        exsound_select = 0;
9 ]; [. |. h8 s
& l# c  _1 @- t. N% i        nes = parent;& m3 G, Y9 R5 m) ~/ d) e8 J
        internal.SetParent( parent );$ @2 ~7 w3 G' ?; S) v

; s$ ]+ D2 m3 H0 _% b7 q$ W5 S9 `3 \        last_data = last_diff = 0;
# Z- u; b6 E5 K/ S  ?
. u& {+ i; x9 }1 ~4 b$ D/ u1 r        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
8 _. P6 ?9 |+ u! U% [- u# G3 D
/ M: R( g3 B+ A, _4 Q        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ J& r" e( F$ {
        ZEROMEMORY( &queue, sizeof(queue) );
9 \! ?9 Q) n  ?! t0 ]# m        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 t' [" c2 P, J" g: }
7 T% V. A( ], {4 u, @        for( INT i = 0; i < 16; i++ ) {+ q1 O6 m- v  Z5 n1 ]2 q5 x4 P
                m_bMute = TRUE;
+ F) b( Q1 A4 I# h. q0 ]" `5 H8 ]        }
; n  }+ |7 S6 `( @: r}6 v$ y9 W" x  K1 ^: Y
; j2 J6 [7 ?) C1 b* Q- U+ {4 K4 G
APU::~APU()9 T& x, F; {3 x+ A& s
{% X8 y" i/ y# O% z  x
}- U7 u6 _1 H: s: }; |3 k( a( P9 c

! t7 F8 ~) y$ A8 B2 Xvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )9 m  J. I7 Y- X" A' u
{0 l4 f$ F8 p" V. i
        queue.data[queue.wrptr].time = writetime;0 R! H: {$ y3 v# e4 w$ h
        queue.data[queue.wrptr].addr = addr;' I* _6 U5 j/ Z2 T: ^# Y
        queue.data[queue.wrptr].data = data;
, Y6 j  p0 f' z# ^1 |& o        queue.wrptr++;  O2 c) \" V, _$ e, Y, m
        queue.wrptr&=QUEUE_LENGTH-1;
0 _, ]$ x. _( t        if( queue.wrptr == queue.rdptr ) {
1 j4 V! t: x+ L7 e; j: y  r                DEBUGOUT( "queue overflow.\n" );
' ^+ T  x* v7 {6 a; C        }
0 O' W% ]/ S7 u5 N5 J& {}
, \+ ]0 I9 n2 x. A. m8 W. c# |* U2 c3 H8 G* F6 I# r. t* S
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
! n: w$ ^; Q; s; [( N: G{; V% P( q; f. [* |  m
        if( queue.wrptr == queue.rdptr ) {
/ t: h. u" t8 l% @- X/ ^+ P                return        FALSE;
; T/ h3 {! Q$ S% ^/ y& w  ~. _0 W& ^! R        }+ \0 q) g) n5 ]% \  O
        if( queue.data[queue.rdptr].time <= writetime ) {
6 f" e* L. w+ W' E4 }                ret = queue.data[queue.rdptr];
* N; N) Y2 q3 [  X4 s                queue.rdptr++;  G( j2 X# a2 z& z
                queue.rdptr&=QUEUE_LENGTH-1;
" d) Z6 T" j, v5 C4 Z5 @- K                return        TRUE;9 q7 j9 u, d5 d! L
        }) m! `5 K- ]1 L9 e* Z
        return        FALSE;
9 Z& J" n7 w% v& h0 ^}2 a/ v& W1 J3 c' |+ H

0 r) D/ Y  n- D( `6 F4 }. gvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
' s" A8 D7 g2 t$ Y6 T5 y{0 _8 i) f# K! O: v! n4 g+ Z3 ?
        exqueue.data[exqueue.wrptr].time = writetime;! T) K4 ?/ l3 ^, Q
        exqueue.data[exqueue.wrptr].addr = addr;$ ~) T$ r8 K) {  F1 i
        exqueue.data[exqueue.wrptr].data = data;4 k& U( t  g0 z
        exqueue.wrptr++;
. c: }1 A1 N# z3 \        exqueue.wrptr&=QUEUE_LENGTH-1;
; L/ M: x1 b) g3 @# @) P        if( exqueue.wrptr == exqueue.rdptr ) {
: L0 M' p' \6 D2 _/ Q                DEBUGOUT( "exqueue overflow.\n" );/ P. q9 K/ @$ W6 m) J3 k
        }1 N7 \8 ]( Y2 Y0 j9 _( F
}
; N5 |  u1 K. g6 Q$ d
5 f# I7 n* T/ Z+ j, UBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
- M. J" T$ V# F0 {{0 p% V0 S  P9 T% ?  F7 w/ @
        if( exqueue.wrptr == exqueue.rdptr ) {
; W4 ^9 F; t3 F                return        FALSE;
: a4 u7 d6 i. m4 w5 H. e        }" [' H& }# P3 M; V, ]% L; j: `3 p
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {) P4 M+ C1 e6 I2 Q: x& d: T! t
                ret = exqueue.data[exqueue.rdptr];
  _- Q4 \" `) k1 d5 N2 T$ j1 [! R                exqueue.rdptr++;
; F( }+ N: ~* a, J, m* F0 s                exqueue.rdptr&=QUEUE_LENGTH-1;
5 F* v$ s/ ]/ j2 J* f                return        TRUE;* Z' j3 K  b, c. B
        }
( B0 j* ?" i; z0 m        return        FALSE;
% o. m+ t: [" e4 L5 t}
8 c; |% Y' U# x. |. B9 K+ U
% \5 n: B. a. D1 V, V& a! cvoid        APU::QueueClear()0 G* P* |8 f( q. P" T) q" b7 z: l
{* l; \; g) t9 G
        ZEROMEMORY( &queue, sizeof(queue) );0 l: b1 t4 s! O, V
        ZEROMEMORY( &exqueue, sizeof(exqueue) );  Z( X" _# X3 |& W* K
}# {0 o( p$ t0 n  O, u2 P0 G; ~' Y
$ r; b) x( j  M0 `( P  r  ^% i
void        APU::QueueFlush(). E3 u% b5 [- B
{; J% f4 [( r" r
        while( queue.wrptr != queue.rdptr ) {& W% p: U: F9 }
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
  Y! C6 l. {$ r7 V0 l                queue.rdptr++;% h, M7 P) x  X6 i/ m2 A
                queue.rdptr&=QUEUE_LENGTH-1;
9 n; p  T2 S+ ]% r4 L        }
; S: d8 f& i+ _& i
2 @4 n6 o4 U  x4 x. N1 M/ ]        while( exqueue.wrptr != exqueue.rdptr ) {
5 d7 O$ m) |/ B) s                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );& ?9 P# a5 B( E  n
                exqueue.rdptr++;, z1 o  q' w  D* c
                exqueue.rdptr&=QUEUE_LENGTH-1;' ^+ o+ ?3 \/ u* K5 `# F2 C1 w
        }2 {1 |) N; z0 e/ \& _0 D
}. m8 N% W1 u  K/ c" P& H- p; k( c

3 c9 u/ k/ ~+ a9 uvoid        APU::SoundSetup()
- b3 i2 z2 Y- A0 j+ U{) W3 p! c6 M( x" V/ R- v
        FLOAT        fClock = nes->nescfg->CpuClock;' N/ S: O* j) Z8 {+ |( x/ l3 V
        INT        nRate = (INT)Config.sound.nRate;  g0 m2 A  ^. b* Y) r" L2 h/ K1 g
        internal.Setup( fClock, nRate );
, ~- H& t* Z. k3 M" t- v        vrc6.Setup( fClock, nRate );
1 @6 |& A# S4 b) \6 O) l        vrc7.Setup( fClock, nRate );
0 p' [1 m8 l) q& u: W        mmc5.Setup( fClock, nRate );
( v  m# m/ Z' U* L$ L2 T3 U        fds.Setup ( fClock, nRate );
  p" g5 P) j2 s  G8 h        n106.Setup( fClock, nRate );8 E. v& Q; B# W; i9 s
        fme7.Setup( fClock, nRate );
+ {! C1 q6 g* {}0 B9 W* e* a0 H" R4 ]7 l

2 w  P# x$ o5 o  }void        APU::Reset()/ R, P3 i; B( z- l
{! z8 @- J  a7 |% A
        ZEROMEMORY( &queue, sizeof(queue) );
/ f. y3 S% Y: N% n1 `        ZEROMEMORY( &exqueue, sizeof(exqueue) );
) m2 ]1 A) `. L# K4 D; ^) q- m
& S, u% i) K8 C1 ~. a, u        elapsed_time = 0;
5 @9 M# J9 ~  c, g. w
$ t$ u/ A0 Q. _; ~, p" N        FLOAT        fClock = nes->nescfg->CpuClock;
3 H  n' W+ t: w- l        INT        nRate = (INT)Config.sound.nRate;
' {( q4 i- U! O) @        internal.Reset( fClock, nRate );
. c: Q3 F3 X( ?" u        vrc6.Reset( fClock, nRate );; X' x. `9 j" i5 o% Z
        vrc7.Reset( fClock, nRate );* A+ j- A$ Q! ]' K) Y  v1 d/ ^
        mmc5.Reset( fClock, nRate );
/ S% e+ F, g  i0 C0 \        fds.Reset ( fClock, nRate );$ K5 U# \! c3 ]! J2 c
        n106.Reset( fClock, nRate );
5 `0 J# P' k* E% E# r        fme7.Reset( fClock, nRate );, `+ z$ y# P# o( E7 I. g0 G; x
$ f: e$ I  f" E& d1 _) r
        SoundSetup();* d# e! x/ i7 m3 e. Q1 Y9 [( T
}3 t: |# x! _( _# t2 D6 j" `* Q) j7 i

* T. ~6 u& m0 F) l3 zvoid        APU::SelectExSound( BYTE data )/ I9 h0 S" ?  s4 e/ i5 Y, v, f
{2 H6 l% {- V4 T1 @# E
        exsound_select = data;
* L4 R4 D" _+ `/ ?' l* M}
# Z# ^* H7 R' w% H' a& [
+ ^1 s5 y" l' O& Y% UBYTE        APU::Read( WORD addr )
2 A' q7 ?0 Q, s& X{
9 s4 o8 R$ G9 K, F* o) e! S        return        internal.SyncRead( addr );# @3 {4 e1 x; j6 B6 E2 U: z
}. U: Q* A  C! M: u5 r
% x7 ^! W5 V0 N$ B5 }! r1 D
void        APU::Write( WORD addr, BYTE data )+ Y) s8 d# R, y  U. m+ s2 m0 I
{
# @0 F1 ~9 S1 {        // $4018偼VirtuaNES屌桳億乕僩3 q* L8 G: g: o
        if( addr >= 0x4000 && addr <= 0x401F ) {0 \5 W- n, E/ F+ {  N
                internal.SyncWrite( addr, data );$ x8 m" z8 i+ t: A. t- ~1 R
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 Y' g1 H* r/ B& V" n! z2 O" ]9 u
        }$ Y* w) _# h" |  F& A2 f( v
}
& Y# W) G) Z8 N, n( f
4 q2 m1 G% m! _( ^BYTE        APU::ExRead( WORD addr )) h2 R0 n9 H4 F; a0 q% C$ M
{
3 r: w3 Q" Z2 G) R8 ?7 _BYTE        data = 0;
- V# G& b& |  F' {' v! u# M0 H$ A; R3 ]! [5 X$ ]0 q
        if( exsound_select & 0x10 ) {, v" o0 Z( a8 W
                if( addr == 0x4800 ) {% E3 ]1 C" N1 T- Y( ^) p; j5 k8 T
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 B; K) ?- k  D1 L- |                }
; h2 g1 ~" B+ p& L6 ^( B        }
1 U. P: H5 m4 V, O* v- l! r        if( exsound_select & 0x04 ) {
' K( a7 y5 t9 b# l                if( addr >= 0x4040 && addr < 0x4100 ) {
3 O8 H  Y, N( L7 ~                        data = fds.SyncRead( addr );, J5 @4 b8 T9 W2 _- Q0 f
                }  G( O' u7 X6 k* v3 B$ p7 l4 m
        }
8 ?3 O, I5 v" X! y/ j4 R5 ^        if( exsound_select & 0x08 ) {
5 R  W, Y( [3 q& v                if( addr >= 0x5000 && addr <= 0x5015 ) {
( G9 T  U3 `8 p! m                        data = mmc5.SyncRead( addr );
$ L0 }3 M5 x9 R6 b# p5 g6 ]$ c                }
6 \4 o" S, R5 `6 R        }
  U. \; k4 p5 l( K' @$ {  J4 S; e% W7 m9 }" b
        return        data;
0 h0 b! |* U, b, q7 s$ s}
. T5 y6 `+ h# t# Y5 h4 P) m; L9 K3 f! f, t6 T/ Q! N; Q
void        APU::ExWrite( WORD addr, BYTE data )
, I( G2 |+ }7 ?; j6 e  }{  n% S# r3 O. K) L4 U
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );( b% a% ]; L0 y4 R

/ ^7 `8 B4 r; D# e1 G        if( exsound_select & 0x04 ) {0 y; ~; t7 V! e
                if( addr >= 0x4040 && addr < 0x4100 ) {# W/ j: z* U6 ]8 P/ U& w
                        fds.SyncWrite( addr, data );
  y+ N- _! _  Y3 l* G8 d# X- z0 L                }5 |: _- l% ^1 V6 l5 D
        }
! h; W: @7 W' K' B; k& S; n% o
' f$ ]; @! q1 _9 C' F" y        if( exsound_select & 0x08 ) {
( G* I6 O6 |1 }% o( W. i" V0 R$ q, q: a                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 z: s! q. `% R; s. a) {7 e                        mmc5.SyncWrite( addr, data );
" O& C+ ?) W' A4 Q) C! n# z                }
5 w, k& X. B. b+ \% }" I        }
& J- K3 h1 }/ W9 O2 e# r$ j2 Y}  v( m0 I, L; J% N5 H  h5 U4 u$ A

  f/ @6 u- C  v1 G, _& ovoid        APU::Sync()
6 b& H' b1 t% l8 v+ m{4 G# G6 ~) H# P
}9 w; L4 o2 X/ \- v7 v1 q
0 v8 I; r. N8 z4 a. _
void        APU::SyncDPCM( INT cycles )' [6 Z  d2 o1 p. L7 n, O
{- N/ x. X) |; y
        internal.Sync( cycles );- V) W, c! m, `2 s* w* N+ {9 h( Q4 N5 A
- G' U5 \+ d& L1 k. k) M" c
        if( exsound_select & 0x04 ) {
1 d6 }' S# k+ p0 v  F( \; i4 B                fds.Sync( cycles );
: ^# |6 k6 t+ L* G4 |7 r" [        }. d! N- J* m. y' ^% g
        if( exsound_select & 0x08 ) {
" f8 j3 a& ?" N, l  N8 R$ a$ d1 J( _                mmc5.Sync( cycles );
, n# c- |  K3 s% B8 s) F8 h        }
# _$ e- h$ G1 @* E/ e% v}
' [5 f- U! @' P7 `
( p6 p5 ~& x& i, xvoid        APU::WriteProcess( WORD addr, BYTE data )
, p3 l8 G" a! Y' G7 w# B{
5 F' _; o% l+ R1 c) p  h3 F        // $4018偼VirtuaNES屌桳億乕僩
+ E6 \* e& O. X( E4 M: ~( A        if( addr >= 0x4000 && addr <= 0x401F ) {3 w1 S3 E  F' b/ c
                internal.Write( addr, data );
4 r  d( l& Y" ?, o8 s        }
+ i0 `, A8 [  G& E# M* e0 j+ Y: E}
/ {0 j% y6 c+ X! w9 G6 ^
6 f1 H2 \0 V$ o' Tvoid        APU::WriteExProcess( WORD addr, BYTE data )
6 M3 |0 r2 d4 h  n1 z7 I3 C4 E/ u{
* b: ?3 R( z/ k" a( D% |. D+ o        if( exsound_select & 0x01 ) {9 s) e1 T! g, _( P5 y
                vrc6.Write( addr, data );3 ^! f1 l( V  P* y
        }+ D# n' _& ]  @7 Z
        if( exsound_select & 0x02 ) {
' n, m+ K. c( Z. n) F                vrc7.Write( addr, data );4 J# b; b, [  U
        }
. |2 p7 g* l2 I  y) |7 l        if( exsound_select & 0x04 ) {. {6 i8 Q9 K6 F1 Z# E  K' x
                fds.Write( addr, data );
- ^) B% w# Y) J3 f' F, L        }+ h4 u- R) X; z; P
        if( exsound_select & 0x08 ) {
) X7 m9 H- q) S- c+ F2 W0 l                mmc5.Write( addr, data );# u6 u, e. f. p3 Z* i7 M7 G
        }
0 Q7 G- ?; }3 n1 {, Z# n3 s' I        if( exsound_select & 0x10 ) {
9 I% Q% C" B7 v1 v: o  Y- V                if( addr == 0x0000 ) {
- Q# @- F% z! Z1 J3 k5 Z                        BYTE        dummy = n106.Read( addr );3 K  L1 p8 y! Z6 X- x3 D* c
                } else {9 U& R5 y* u) y0 g
                        n106.Write( addr, data );9 f. [8 t- r5 e2 C) e
                }
) j) @* y$ }# w  B( S2 t( ~- {# V3 h        }
2 P! r: F# Q5 B) b        if( exsound_select & 0x20 ) {
" e" P  R" L0 x! G% W5 ]3 \2 k1 e                fme7.Write( addr, data );7 A8 \+ z( @3 j3 i5 D
        }
$ A; c6 i# M0 a7 x1 P% i}0 k* O- {0 `& `! j% u( a/ w

: K! o4 D2 _- s3 I' P8 Avoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )) {3 T8 S. q# ?
{
0 D) j. ^2 {& V+ I" dINT        nBits = Config.sound.nBits;. I1 R7 w0 |6 O1 W+ v4 n
DWORD        dwLength = dwSize / (nBits/8);
( a. x5 l3 N* @) k( S& V  LINT        output;% ]/ O$ ~: S' e$ t* Q% q& f; \
QUEUEDATA q;
2 T8 p, D) M+ w; t  xDWORD        writetime;
# e- b7 r9 f: Y! F. B; I$ \3 p9 U! s
* v% n+ v, e$ y! TLPSHORT        pSoundBuf = m_SoundBuffer;
' O5 k8 s' ^: |* d* C* WINT        nCcount = 0;; J# C" ]. E6 c! x8 {4 F0 a2 Z
* A1 l& J8 i( S5 O
INT        nFilterType = Config.sound.nFilterType;6 Y# w" o$ b* q

$ n& j- M0 J: p) D$ ^9 U0 B        if( !Config.sound.bEnable ) {, b5 Z* d+ b0 |& m7 M+ i* S
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* A: S7 R6 m4 y. E8 R: j                return;, t9 h# f' Y3 Q! E
        }
) D) e. d( Y  i( A; O, A' V# \$ q+ L0 w
        // Volume setup4 S1 U+ T. q& K" z; {  a3 P  ^# q5 @
        //  0:Master, {% {6 P. V- i
        //  1:Rectangle 1
$ A" \; J2 A* P        //  2:Rectangle 26 _- @! R  m0 V5 s
        //  3:Triangle
: S6 k8 }; h: ?1 C* n2 y        //  4:Noise9 f* i9 r6 Q# D( C7 Q
        //  5:DPCM  M: C: d5 D+ y- M3 W- P
        //  6:VRC6; v/ Z6 e0 y! ?! V8 W! X$ z+ S
        //  7:VRC74 {( T( X8 p# s! H. ~9 X
        //  8:FDS( ^; m! x8 |3 G1 z: c
        //  9:MMC55 I3 G* ^: D% ?; \( x0 r
        // 10:N106# b2 z& p# r- I! U( m1 P7 G
        // 11:FME7
+ M" O; y& D7 w: ^" J- l        INT        vol[24];6 r3 G$ c# P  c' F
        BOOL*        bMute = m_bMute;" X7 T! C8 A+ X" U+ Z2 H+ @0 {
        SHORT*        nVolume = Config.sound.nVolume;# B2 w1 e. o: z* S& M' P

. s: r/ `* }& Y0 @' Q0 C        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
4 ]( k. y: o9 Q$ Q8 p1 B
8 y$ C/ F8 A3 N' ?, N2 d. B        // Internal4 B) r7 u9 W, v% }
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;7 r+ I4 V0 {$ M, W
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;7 x- w$ w( x. {! m6 T
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;# P+ j3 {/ V7 f* N$ P0 I
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
# N( r6 f- ^5 {* ^4 i8 N  H' C        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
+ v) v; _2 @0 C) v
& y: x! k, Z! Q: f        // VRC6( }: c% J) n' d6 A% F
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 S, r& T  f# b, H0 n
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% \; d/ I2 v) ~        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 }7 j, X3 _8 p% g3 \
" e+ d5 z. r5 O/ g* ]9 f, F        // VRC7
( U( J! _. F. U$ P; ?' j0 {        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
; _; E6 E2 R2 v2 Y* c
& C5 N( P: [; S0 Q( B        // FDS" K2 y8 j1 K' \; W$ |$ a
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
7 o8 U+ a* |; e5 M( D& w  B3 }# x4 ?4 f
        // MMC5
+ d. O3 [4 G* p        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, q. ~; r$ r' W" K) U: {' }% a
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ ?1 G. Z- f. L        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. v1 H/ d: U# t7 |
. `8 ?8 L4 \6 \" d0 M" Y
        // N106
; t' a$ D+ q* _8 b6 v' j        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* c5 ^; u& b" J8 _3 g! T9 L! e
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' N( c% n* }& A1 }        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 o, m5 z! e% p% P+ X1 ]& a
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ m" [8 |8 [. A0 J        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ B* |( B. X* I7 J9 ~* ?7 f
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 z4 u! Q1 w8 Y. S        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 Z4 a$ {8 S4 H$ N$ ?& [        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" J! f+ S" t  ~# u! W7 p) q" m. F& W* Q0 P8 T
        // FME76 R( \: W% L+ C1 p/ M3 o
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# E( E0 p& h) [! ~        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! H" R: @: N. }        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# ?9 _" I% \: p; E7 G. Z( ^
! ^; B" m- d& H7 B6 H1 k9 L& Y//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' l1 U+ U9 N$ ~+ y4 @        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;% a3 O3 k( `$ ]
+ u' R* l- i  x
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
/ i; W$ o# r1 G6 r$ f        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
0 }: [3 U, t5 i9 e6 z5 {5 t" E7 ~                QueueFlush();
4 J, |4 T4 G6 s" C) w% F0 c        }# W/ }$ G: @. b

7 c# g/ E+ Z% Q0 c1 W# o# q1 M# B        while( dwLength-- ) {% m. V4 v  ~. ~& ^0 j6 P: b$ a
                writetime = (DWORD)elapsed_time;
& `- }" S2 b: a
  w. ?4 X. t6 u) e                while( GetQueue( writetime, q ) ) {0 ^% g0 M; K' v
                        WriteProcess( q.addr, q.data );* U# f0 Y  J( Q3 n2 P
                }) [) ]5 W$ l1 i8 {, g, [
- A' `  U1 M/ A+ V7 r; |
                while( GetExQueue( writetime, q ) ) {& L% M+ |1 e. g4 Q) D8 V* _0 z% b
                        WriteExProcess( q.addr, q.data );  u4 z% A2 n; }( w, n) d
                }
5 w( L1 k! H8 g" H7 L& M7 {3 H! d( t$ ?0 E7 e' a3 `5 y0 d) q
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
/ C2 _/ n& L- ^9 @8 W. X                output = 0;6 Y9 L( i' A+ B( V# X3 a- j+ L
                output += internal.Process( 0 )*vol[0];
* ~( I& d. x, \, |& P7 F                output += internal.Process( 1 )*vol[1];
+ i+ x( M; k0 D: w; l0 \                output += internal.Process( 2 )*vol[2];% X. I( p: B3 V/ G4 k# F- V2 ]# h
                output += internal.Process( 3 )*vol[3];/ r3 y9 a4 Y) Z$ b: T6 m3 q
                output += internal.Process( 4 )*vol[4];0 X) {& o' A  {! V7 d

3 K& s- g6 Q9 f! J( p" S                if( exsound_select & 0x01 ) {3 ?5 A& ^2 e' {
                        output += vrc6.Process( 0 )*vol[5];
9 K- ?" B- L1 A$ @8 _, `) |: w) R                        output += vrc6.Process( 1 )*vol[6];" w3 t, Y2 h7 `) T9 M( ]* ^
                        output += vrc6.Process( 2 )*vol[7];% @/ O$ s$ q) h2 w- o: l+ Q. y
                }- [1 ?6 N" y2 K7 G
                if( exsound_select & 0x02 ) {
& }& H3 O1 e5 {                        output += vrc7.Process( 0 )*vol[8];
, c; d& m7 W, A! I                }
) `0 E+ h9 [/ r- W                if( exsound_select & 0x04 ) {, g: O5 A6 g4 p8 K
                        output += fds.Process( 0 )*vol[9];2 C( J5 t+ s/ \0 Q: R2 `; E
                }
- r. |7 |% d4 n. Y                if( exsound_select & 0x08 ) {5 |" n7 F' T8 n% H' ?9 ^
                        output += mmc5.Process( 0 )*vol[10];2 c0 L( {* y2 [: _
                        output += mmc5.Process( 1 )*vol[11];4 c# Z% H, o; j" m, e
                        output += mmc5.Process( 2 )*vol[12];
* |4 b0 o& z, |/ f8 ^                }: s' R0 Q/ \3 z8 m" e1 o: C( c
                if( exsound_select & 0x10 ) {
$ i8 C, I1 m' r                        output += n106.Process( 0 )*vol[13];
2 `7 }  z8 u' R) A                        output += n106.Process( 1 )*vol[14];% ?3 z4 }. k7 n- K, H! l# G  u( b, z
                        output += n106.Process( 2 )*vol[15];. ^* W5 ^( P! B, u
                        output += n106.Process( 3 )*vol[16];
" B7 B, g; s. i5 E. o                        output += n106.Process( 4 )*vol[17];
- ]* q) c  g" ~7 x6 g                        output += n106.Process( 5 )*vol[18];. r" O  s* F0 @
                        output += n106.Process( 6 )*vol[19];
8 i8 n& v  y7 s) E; i                        output += n106.Process( 7 )*vol[20];1 Z8 J# U( `  ~$ H: C9 A9 W
                }& p& S, u" ~8 T8 Y" u: j: g5 {
                if( exsound_select & 0x20 ) {, h: ]9 w7 F# N0 ]% ]
                        fme7.Process( 3 );        // Envelope & Noise4 R$ G1 F& w1 U. _6 j, m" h0 u
                        output += fme7.Process( 0 )*vol[21];
% E. p% u/ M* L. x) |' W  l3 o8 i                        output += fme7.Process( 1 )*vol[22];
6 j  C# {9 l6 O/ i, @5 [% [$ t                        output += fme7.Process( 2 )*vol[23];! V5 [' O, ?. U
                }
0 y% ]; m# R+ V8 M9 H; ^
7 e' G- I4 G. d3 q  ]" Q; `1 A- D                output >>= 8;- V4 ?' G2 p1 M, D9 Q* d
2 P4 e% w4 W$ ^; e4 p4 M
                if( nFilterType == 1 ) {# o3 z# E, B! l/ M/ l! d8 n5 c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)) R1 E+ [+ g, y; Q6 i1 x% ~
                        output = (lowpass_filter[0]+output)/2;$ Y0 `9 `4 j. n/ q* s; n# _
                        lowpass_filter[0] = output;1 h0 q' z% V/ D6 x1 q$ ]8 M. E8 \9 X4 k
                } else if( nFilterType == 2 ) {! [0 J+ y' t  D0 \
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
! c9 i" \2 H& D3 L. J. g0 Z( E7 \  {0 s                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% U2 W  x/ V8 p
                        lowpass_filter[1] = lowpass_filter[0];( [( m. \7 f6 q0 K8 Z0 D& |( }/ [
                        lowpass_filter[0] = output;
! Q0 V5 F5 ^3 k8 O; k                } else if( nFilterType == 3 ) {
9 @. [1 t2 S, s8 L# F                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 [' j; \0 I8 H                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" x# h$ H0 e# P3 T2 g# V& _                        lowpass_filter[2] = lowpass_filter[1];
2 c- V' c" e. y% n( Q+ ]2 c, n                        lowpass_filter[1] = lowpass_filter[0];
6 W; M+ l8 r* |# O  [% O0 O! k                        lowpass_filter[0] = output;* M% s! ?6 ^: h) V/ m$ {: H
                } else if( nFilterType == 4 ) {4 N+ c9 c( Y- b3 F
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
; X$ Q# @7 k3 o& t8 Y$ L5 x                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;8 X) R6 Y0 r+ _* |! Q0 s: m
                        lowpass_filter[1] = lowpass_filter[0];8 M! x1 t1 Q/ z
                        lowpass_filter[0] = output;( N* W8 P1 W5 ^/ b! W
                }
, ^! H& j8 Y& e! Q: N
& `6 J# x$ V+ i#if        0
# O; P# {! J5 E! Y5 n' x                // DC惉暘偺僇僢僩% v& d1 U# L% s7 H" m- u+ o
                {4 Q( |+ k, v0 o
                static double ave = 0.0, max=0.0, min=0.0;
' J$ o* Y" h2 Z8 }                double delta;% W: I& k: p/ A
                delta = (max-min)/32768.0;
+ q1 C+ f. K  ~* d+ C                max -= delta;
/ L# K- e. [$ I/ H! W4 \$ B6 r8 ]0 G# G                min += delta;! v/ M1 y9 J- U
                if( output > max ) max = output;; h+ _/ ~% k% @! r5 O5 o
                if( output < min ) min = output;
# w4 o  F$ A; e' ^% |% r                ave -= ave/1024.0;0 `# s9 ]8 H" N2 O, u4 R
                ave += (max+min)/2048.0;& N: t9 X& d# h" ?
                output -= (INT)ave;
8 S5 G; V) w2 _0 D                }
/ G' R9 R% G$ y$ K2 E( ^3 `#endif
% u) g7 l: t% a# c4 U+ ]" x#if        17 n, b, r* W' {  s
                // DC惉暘偺僇僢僩(HPF TEST)
- z2 h" f- M. ~! n5 e                {  q' U6 e( q( w8 i/ j. C) p
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( a8 Q; h% b0 r  \; F
                static        double        cutofftemp = (2.0*3.141592653579*40.0);7 e1 N5 E2 l* }* ]. v' G6 g: b" m
                double        cutoff = cutofftemp/(double)Config.sound.nRate;$ x; r: Q+ k9 F
                static        double        tmp = 0.0;! f5 C/ t- w4 e9 J) k6 c5 j
                double        in, out;. ~! j( T# \) |. n& ]+ R

* f& f9 N& g' T/ P) u% C9 v+ K6 ~                in = (double)output;
( O( C9 T" _+ ]/ h# p- [9 O                out = (in - tmp);2 ]% B+ S  T6 _' ~7 ?
                tmp = tmp + cutoff * out;
% M7 Y5 V* [7 P
6 u8 @9 _  K- P7 z8 l" Z* q  g& G                output = (INT)out;& \% h6 A7 w0 w  J
                }
3 n5 V/ C: j: v/ B+ z#endif" |3 K* h" D) ]6 z! C- C( q3 q# n- e
#if        08 O2 y* W: \" S' o6 k9 ~: Q
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 T5 g) I5 e- Z: I7 F                {
! A7 P: o5 S5 `  y0 k  P2 E                INT        diff = abs(output-last_data);
% l" w, o2 T. u* |/ w* c                if( diff > 0x4000 ) {  [! J- o  @4 y! v  d5 q6 h$ @
                        output /= 4;
4 l3 R" Z! L# d4 v0 t1 k* X                } else
4 ^' [! v; @& I' i# f                if( diff > 0x3000 ) {* R- N+ }7 K2 ?! N8 G7 }  T
                        output /= 3;
" C' m% ?% v: p; f  D5 E                } else8 B( p: ^5 Z9 t, t8 T
                if( diff > 0x2000 ) {
9 p( N' g! h7 Z  @, n                        output /= 2;
, Y* h5 Q$ \* D% x                }
5 x( n/ b* N# |3 s0 Y/ Y                last_data = output;
$ z/ H' l1 l6 m" F, v  K% W0 @) ^                }8 L' |+ R; d" H1 n8 A5 V
#endif$ b& _0 t5 p) @2 R2 U# U# F  R
                // Limit
. Y; z2 H8 C- R  l/ {7 X8 d: ?                if( output > 0x7FFF ) {
& f% ~: Y: {) |) Q                        output = 0x7FFF;
& \) A8 w1 e- e                } else if( output < -0x8000 ) {& [, {' z5 Z* p* Q* w6 X2 F
                        output = -0x8000;: Z" l8 B. P$ C3 G+ X5 c
                }) w0 a% {" I! r( y: h+ i

( Z) X' V! r% h, X  Z" y! `6 n                if( nBits != 8 ) {
+ J5 w9 J, X7 O$ ^9 v2 H  a3 g- x                        *(SHORT*)lpBuffer = (SHORT)output;
# H* M4 j) S3 W; i1 G2 s                        lpBuffer += sizeof(SHORT);
' u/ D$ m6 W  v. u3 p6 r7 I, i                } else {7 y  z+ h7 ?) |
                        *lpBuffer++ = (output>>8)^0x80;
6 |3 P9 \7 r) E* H+ ], ?                }; H! e! T# D# e3 N$ i+ G
. e" }* @: a( n
                if( nCcount < 0x0100 )
' a0 D0 m- L. v3 s; ?& A0 s                        pSoundBuf[nCcount++] = (SHORT)output;
% K; o- U" J' ^% N, E* L" T% Z9 `# c0 @/ H! d" c, h
//                elapsedtime += cycle_rate;. {; \; T7 W5 O  N$ y; z) n  O
                elapsed_time += cycle_rate;
, C+ t- h$ h7 D% `        }6 H- p, g: @7 O4 }% l: H  a

7 w' p6 J, H! F#if        1
2 \+ O. t/ z0 }; A& D' j        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ h2 ]5 E2 h. E, [/ T" ?& f                elapsed_time = nes->cpu->GetTotalCycles();
" H1 d- k; P4 N5 G& d* _2 k% S4 @        }
' D; s, |3 j8 f. y/ c# N4 x0 [* d: G        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {4 k5 l- l8 g7 K' _- S, N8 l
                elapsed_time = nes->cpu->GetTotalCycles();. v4 X, x& A. g4 X: e: J. d$ I
        }
! [6 a! w& Q& U& d% m#else
$ f9 u" U$ w6 i/ |2 K$ E! c  ?% P        elapsed_time = nes->cpu->GetTotalCycles();3 W+ |+ E" P' T8 T. S1 J
#endif. [9 c. |' a' _) G
}
1 t. Z# L3 u, d% a6 J$ t( _7 h% F$ J! v. c$ I
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  D7 a0 |6 G* `2 Y) E( G
INT        APU::GetChannelFrequency( INT no )1 g2 G+ G+ g7 ?& a
{. v6 a( Y) c4 l
        if( !m_bMute[0] )
, i0 @0 z) f; a2 @6 F                return        0;" `- Y- A, b; b- O
, \$ U2 x* z4 @, m
        // Internal
  b& J, E3 v; z$ Y+ {; L        if( no < 5 ) {! N# m  S1 {% J* p5 ]9 T9 c
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
& y2 H" ?. s, V  C4 E        }: Y! ~7 l- v+ F/ A1 r2 I) u5 \
        // VRC6
( o; Z: N5 D0 f, u        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
1 v) a0 n6 ~0 h" Z" d2 u' B$ B& Z                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;& ^6 s1 K! k0 s
        }
8 y. F0 |/ I- E' X$ C        // FDS" }3 c' @7 I4 P! K0 {& b* K
        if( (exsound_select & 0x04) && no == 0x300 ) {+ z3 z. C, r) V- s( U
                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 H6 z' s# x4 C, p! J2 N9 d
        }7 @( I* W4 s4 G, l% J% R) ~5 N
        // MMC5
* g% X1 o3 }1 |8 d- V6 w        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
3 Q3 |" q$ r6 q5 L/ L                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;0 L# T" m) B3 L9 V1 R
        }/ y; L* o/ K+ |8 Y/ \
        // N1068 k" B5 `4 Q2 |7 A
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {& @  O/ t9 K" @
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
* V8 N, P6 A# G9 x5 W$ a        }( Z* {) v$ B  @3 ^# _2 H
        // FME7
2 s2 O- K& a( i) I8 ~( n        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {: ?/ J( V- ?" S$ E+ {
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
% t$ x- k* m9 L0 d- r' u# |        }
9 o* f6 F! i0 _, H% C! H        // VRC73 _, h1 w# X/ q2 J! h
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {  I" k8 \# i. O9 a4 i: y" w5 r
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;# S3 U7 o. F: F- \1 P1 A
        }
1 Z+ v- E: h$ w/ ^5 s; `. r/ ~! }        return        0;
, o' p6 I9 a. v6 O/ M}
0 k9 {9 v& c4 E* y4 ?! f& y) \1 h9 W# Z/ u* q
// State Save/Load
, B) v# u9 \/ g( ~# Ovoid        APU::SaveState( LPBYTE p )( m/ B# v. p$ O, b
{
, P9 I/ j; ^/ J" _9 ~#ifdef        _DEBUG3 E: G9 @, x$ j, R% `& Z% S$ Q, w
LPBYTE        pold = p;$ @# K) D+ ~: r" q1 L" D
#endif
; n: o3 L1 d5 P7 C( j6 h$ V2 P9 B2 u) X9 B0 B$ \' j1 Y* v
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
6 X' }! Z- ~- y1 e1 d        QueueFlush();
. A5 F/ ^2 y/ `& z- ~& D. r) C6 ~. V- J9 `& w  Y" _& b0 B7 z
        internal.SaveState( p );
5 y# L1 c1 S$ u3 V9 x  t/ h$ p/ [- h1 U        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( G5 S1 n; X) v6 y  e0 }
+ x9 L# B  H' @: d5 `        // VRC6- C  o, l! A+ g8 P, N: O# N7 z
        if( exsound_select & 0x01 ) {% y# \# j- e4 f1 p5 O
                vrc6.SaveState( p );$ b4 C+ Y5 V, l
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' q' h, v! E" V" Q4 G4 }        }# h9 Y+ e7 k1 P1 d; z% {
        // VRC7 (not support)
' h+ w! g7 @3 [8 m1 ~1 h        if( exsound_select & 0x02 ) {
( r' ?& S& i5 V7 N5 g4 b$ k2 U% ]0 }                vrc7.SaveState( p );
2 E& {+ Z4 P. U; s) u. k5 m2 q) A9 {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- a  n) x% O+ D* c; z" E) @0 E        }* }: a$ G( e; d, {
        // FDS, i/ u9 O2 j: [, P! e. g' H
        if( exsound_select & 0x04 ) {3 T8 @8 V0 C. b* B( S
                fds.SaveState( p );4 d0 e5 ?! Q* `+ x
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
6 x, A$ i) `  j% z& s        }- u/ m8 y1 I% B% O% C( s1 E) Q1 G: N
        // MMC5* f+ K( D9 ]' {/ J% c" P
        if( exsound_select & 0x08 ) {2 L8 q( r! h6 C6 A
                mmc5.SaveState( p );. P/ l: V" ~7 l/ ~1 K$ d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 V* N, K' c$ W2 K, _% {0 Z
        }) ^# t0 [" g) I% J! i) N4 ]
        // N1060 e* F; D5 s; h& f; a3 s
        if( exsound_select & 0x10 ) {$ [' f2 W+ u3 J7 j% ^! s4 z' v
                n106.SaveState( p );
% Z' z# O+ u& f! _: f                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding3 O+ D1 o# F! I; K5 j
        }2 y, o, I' l; c% V
        // FME7
5 f( w; m3 E, D6 z+ F        if( exsound_select & 0x20 ) {
1 P6 j5 D4 m5 E' ~0 J6 l2 z) ]                fme7.SaveState( p );3 F' ?" \  M+ \4 U/ T/ W! R
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! \% n4 b/ R( o, x! r5 |7 F. L( h% w+ N" i        }5 I% p( G4 a' D* J

  K# x0 j7 O; g& Q/ z3 P#ifdef        _DEBUG
' x3 t3 P% e- V& l6 VDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% p0 o4 B: U; D* n4 A* A; Z#endif
3 I" N, W  z$ T8 R* C+ B}
0 P2 }% P7 l4 X
6 ?$ g8 \  b# K5 P9 ^/ zvoid        APU::LoadState( LPBYTE p )
1 D1 R9 \2 h9 W# J{
, v3 {' E0 Q( n4 [        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% N6 R3 R  F. E* k" L" `* R' W* C% {0 J        QueueClear();5 ?+ C9 Y+ K6 I. ^. f

7 g( `' E( [8 k' k* r  g        internal.LoadState( p );) k1 E5 c/ z5 ~: j6 p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding5 V% _0 n4 S" ~' e4 X7 f2 ^
- b3 X+ G% x3 j
        // VRC6
# J" ?8 p7 p2 _/ ?" j        if( exsound_select & 0x01 ) {4 M" v# P  B& J8 g( W
                vrc6.LoadState( p );% {* H$ m8 l- q+ d' ~' b2 d
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' U' ~& i0 y1 b# f6 W1 G        }) p" @( f( Q4 ~4 F  |' |" A
        // VRC7 (not support)
& m+ u9 g: k5 ~5 H0 O; c" o3 m# v4 `        if( exsound_select & 0x02 ) {9 {2 M  i$ Z) d+ J! v7 ^
                vrc7.LoadState( p );$ J2 b3 A$ s7 G: a! B
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% a! q& M2 h% ~" c0 n        }7 g* K) e, ]$ @3 w
        // FDS2 D; k2 t$ e1 ]  l  g  e: U5 _
        if( exsound_select & 0x04 ) {) k" Q4 S' w' p& L* s! e" X
                fds.LoadState( p );. r1 u; ?% [9 M& N/ v$ K
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
4 g" y8 z% {) Z6 m2 a        }
* c$ i' x& P1 W        // MMC5
% K. A; [3 O. Y: G9 B/ ?; L/ t        if( exsound_select & 0x08 ) {' u* N' f9 ^) z0 e
                mmc5.LoadState( p );5 @7 K2 o' J* I. r  h' X
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
" H2 B# C+ l6 {1 H9 ]. i        }
0 M" I5 I! O0 ?: [: h$ L        // N106
$ V9 j7 m" C6 `) i. y3 {        if( exsound_select & 0x10 ) {
: _( v4 X2 n; R1 ]                n106.LoadState( p );
8 F; V# o" H8 c                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 ~( R9 Z! M3 z8 u; l
        }: ?) F& \) f5 h/ j
        // FME7
8 I; ^5 ]0 p8 o0 _* ?9 r8 j* q        if( exsound_select & 0x20 ) {
6 L4 i8 S2 B1 ?: a                fme7.LoadState( p );1 r  s( E0 f0 ], K4 K. ~8 W. o1 }
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
5 i- W+ Z1 c* t        }
* A- k( n2 _+ h" J. b1 ?2 o& ?}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / J* h7 k/ ]& I  N/ c
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
& o' Z  d5 u, Y$ @4 ~( l8 n% _感激不尽~~

4 Y& _% f& x$ @恩 我對模擬器不是很有研究,
7 S, p( m9 x- j$ P: T4 z' \" J雖然要了解源碼內容,可能不是很困難,
2 r- q7 r; N1 d- N不過還是要花時間,個人目前蠻忙碌的。1 Q, D% k' `3 a3 f  E
0 p3 e6 W8 F4 y' l6 ^- \
給你一個朋友的MSN,你可以跟他討論看看,
) u' b0 m7 I) g: Y8 d0 H$ |他本身是程式設計師,也對FC模擬器很有興趣。
- ^1 h; K: _  E; H7 C
4 _2 H% x& ?2 ^+ C) W# T  C/ I6 wMSN我就PM到你的信箱了。  h& e$ z) I0 T8 s1 ]

+ z6 F' V/ C1 z; m$ i希望你能有所得。

该用户从未签到

 楼主| 发表于 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; U5 K; I9 G3 ~呵…… 谢过团长大人~~

  w* r  i$ V" h1 H
2 H4 @& n7 a  V2 p9 y4 t+ Q5 }哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 `9 q$ R$ `+ `: R& j  V7 R! y, B团长的朋友都是神,那团长就是神的boss。

* G1 ]9 c+ A4 R: n哈 不敢當,我只是個平凡人,4 n* ^/ ?( Z' d- L
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
5 ^, m2 t' j4 J: X- `( GZYH' ~- l# w! N6 O: U/ N
QQ:414734306
, Y% y& G( F! mMail:zyh-01@126.com3 z2 H& b0 |1 B. h2 @5 }

" R$ K; P) s1 K5 g5 I0 U+ W/ v他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ r8 M9 B+ h" I再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 T# R# _2 r1 t# R! V* [
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-27 04:13 , Processed in 1.134765 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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