EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?
* j4 Z: ]. y7 n$ \7 uPS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: ]0 c8 y8 }# C2 Q0 u( h5 u! Z+ u
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  c9 L8 M, l" z5 i这里有相应的模拟器源码,就当送给大侠了~~
# I) L' C9 j1 Y3 vhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 3 F& j. k2 W6 r( \' `
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 w, ^" z4 r1 y6 |/ |3 w3 X
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
% b# c% c- A0 k这里有相应的模拟器源码,就当送给大侠 ...

( }3 \! ~" Y& D聲音部分(Audoi Process Unit = APU):7 D- h/ g, @( u* b3 _& |
.\NES\APU.cpp
" N6 N4 D3 H# i4 U! q2 {.\NES\APU.h7 k% W5 t  t+ z: f8 r5 s
" a: A* l& m% @. [8 D7 o

6 o" f" f4 g( {4 p! u9 N影像處理部份(Picture Processing Unit = PPU):4 I6 S, ^/ T  C: q
.\NES\PPU.cpp
' A, j! x3 w: ?.\NES\PPU.h1 j: K: R3 `- g& N6 S

" e; d8 ]! f! c7 I如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。: }) k5 m' X; a0 \8 b# p4 G
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
7 m: F" P6 {: S) v(由于很多专用术语和算法机理都不明白,所以看不大懂……)* o% X; @' `* ?6 s! g& m. e
//////////////////////////////////////////////////////////////////////////' R; {0 p: s; s: d* G6 W
//                                                                      //
! M( u: [7 U7 R8 Z( |//      NES APU core                                                    //0 s4 L3 }, D; f( N! P
//                                                           Norix      //
$ C5 g& T. V+ [& |//                                               written     2002/06/27 //7 h! C: a/ i; U* d$ L
//                                               last modify ----/--/-- //6 l6 y) h2 L( d! Q6 V7 Q
//////////////////////////////////////////////////////////////////////////
! h5 ]/ F; M  \( q7 p' S( d1 h0 s#include "DebugOut.h") _. I% ^6 ^* n* D3 t
#include "App.h"1 g- P" m  z3 F0 t/ V' _2 H
#include "Config.h"
: h. e+ F: |5 o1 |; ]5 O  m
; C+ @6 i( L9 C7 j0 t' |#include "nes.h"
: \6 T% a7 o9 C, @4 z; k#include "mmu.h"7 G5 o# {, y9 @/ h. Q0 D1 k! l! v9 l
#include "cpu.h": G% q; J" P3 m; \3 L: j' f  g
#include "ppu.h"
! i; z/ H/ F  T% A9 S#include "rom.h"
3 l' V7 T- M- j' E2 h7 [2 h8 e: D#include "apu.h"& U6 V2 C: a  M+ k- t

9 R* K7 a# {) _! l+ p& u. P4 y// Volume adjust
' k6 K3 D. u# Q6 I4 ?! ^// Internal sounds
) \7 |* Q" }* W+ w2 m9 s#define        RECTANGLE_VOL        (0x0F0)0 H) ^4 ?" u$ R4 }8 z. q) C
#define        TRIANGLE_VOL        (0x130)
3 ]5 P9 Y+ h$ @1 j8 K) M$ d#define        NOISE_VOL        (0x0C0)5 Z3 b% i# z# u* ?9 p$ K
#define        DPCM_VOL        (0x0F0)
  y! V7 l1 g- h$ c. g% |4 v// Extra sounds( i, I" t% ~& W  B( z: v
#define        VRC6_VOL        (0x0F0)
: i8 x& ?  e( A. u8 U; h#define        VRC7_VOL        (0x130)3 M% e. a+ k1 {& z
#define        FDS_VOL                (0x0F0)6 \. X( P9 G4 |+ @6 y
#define        MMC5_VOL        (0x0F0)
- u/ p/ n9 o2 d  y* w; u6 o#define        N106_VOL        (0x088)) N2 C+ O8 L6 j
#define        FME7_VOL        (0x130)
7 D! q$ u! B- I, C0 V8 ^" ], i  }" `/ w) X1 }- |7 ?
APU::APU( NES* parent )6 g5 z3 V- D/ T8 `. i: Z" I" T' ]& M
{2 c6 }- l; t, ^9 X9 g! T( Q
        exsound_select = 0;
  m( J3 m/ T; W& i/ g' r
7 R& }5 x# }; g6 }7 K        nes = parent;8 A" _4 S6 U* ^  s
        internal.SetParent( parent );; t7 ^$ _* @: a" Y  p6 R* c
# _1 L2 c: ^1 n! e+ v* F/ i6 r
        last_data = last_diff = 0;
) ?8 I& {2 Y- f4 D
  W2 E( K1 i4 `        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );+ v" y9 u, p; w8 z0 Z( g- y) P

. N" A, v3 B: K7 @7 j        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
- z0 H! f3 q$ H% x3 D0 W* k" ]        ZEROMEMORY( &queue, sizeof(queue) );
5 c4 H/ {5 B4 {6 f: o5 |9 K. Q        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 b( |1 g* v% g" ]" \4 e
$ V% w& x, S7 x7 J
        for( INT i = 0; i < 16; i++ ) {7 Y" d' r+ N/ a6 ]8 S) f6 g3 W
                m_bMute = TRUE;8 p% l# O+ M  ^2 P8 S( N# V' A: U
        }6 T8 e3 `+ g; l, K) N; h
}- E! A9 I: c+ y" ^

% N& e( v9 L- Y' R& G" G& v% hAPU::~APU()
" K7 q) O: K: D# S3 ~% J{
5 O# ~6 J! N5 m8 B}# E9 ]) D" X* u- n& q6 f( l

  p; u& w* f. C3 Lvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )) c+ R% A& f8 e* j  w  n& }6 w
{
9 Z: ~7 Q* R1 k& q. D  x: [% V3 Y        queue.data[queue.wrptr].time = writetime;
0 v1 j# x+ B$ m4 F        queue.data[queue.wrptr].addr = addr;3 w+ a) o% F# `
        queue.data[queue.wrptr].data = data;
: D! d# z1 X( c7 e% B1 a        queue.wrptr++;
: C3 W2 _( r% s        queue.wrptr&=QUEUE_LENGTH-1;+ S+ H$ D& P& p4 o3 f+ ?6 g
        if( queue.wrptr == queue.rdptr ) {; D, u3 y- n) {3 ], s
                DEBUGOUT( "queue overflow.\n" );# E2 |, i; R& X  ?
        }! U+ Y6 ]6 J  I+ j6 z9 G+ t
}( j( J1 m; p( ^# u) h
( d4 C/ M8 \( g4 r. q0 q
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )( x: d* m- z& N! l8 T; @
{
" J( ]) r0 t' D3 Z+ ?        if( queue.wrptr == queue.rdptr ) {; x1 y% q! I7 F3 f" I
                return        FALSE;
- ~4 A9 a4 i& G8 b, _; Q8 J        }" y7 d* j$ O+ D+ w1 ?) C, R: y% G& N
        if( queue.data[queue.rdptr].time <= writetime ) {
1 _2 l; z/ l! m2 O                ret = queue.data[queue.rdptr];
1 m8 c9 w/ Y7 y0 ]( k                queue.rdptr++;
: i  f( c1 l+ E                queue.rdptr&=QUEUE_LENGTH-1;" F7 u. L( d: i
                return        TRUE;
4 b" z5 f2 l) }' q# m        }
5 L& o( K9 o  o5 V% N4 d2 X        return        FALSE;
0 g# r% J: M' f( o( G  Z) N2 @$ H}, V  @1 F9 n4 I  D/ m
" h5 d( y% `4 H5 X; r# V0 \( O
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  ?' d8 I9 c  S/ a7 P, ]
{
* |# y- A' t# m) {# h7 j# f8 k        exqueue.data[exqueue.wrptr].time = writetime;
, S/ h# i# @- U6 L        exqueue.data[exqueue.wrptr].addr = addr;1 X( S8 P6 I+ E
        exqueue.data[exqueue.wrptr].data = data;
5 d: z' T) O6 A        exqueue.wrptr++;
' a. P$ O) p8 x% r) m& Z        exqueue.wrptr&=QUEUE_LENGTH-1;2 @. h) v( B" _9 a* }2 V7 q
        if( exqueue.wrptr == exqueue.rdptr ) {
3 L' s) e  E3 N$ @; q# g$ i3 l6 N                DEBUGOUT( "exqueue overflow.\n" );
8 |. \8 z4 h) _/ J        }
; m8 m% q. @3 N+ r" u+ P5 G6 a}
: l7 i! v- l1 P* n8 j$ |6 _/ C' l5 C/ G1 E5 \
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )8 n8 w/ N* [- n- T% _' w3 b
{
: I* }9 w3 z2 c" A+ |4 v% M        if( exqueue.wrptr == exqueue.rdptr ) {
1 Z: C' |; w4 j& q7 e6 D% Q4 w* C  M                return        FALSE;
6 A. q1 D& s9 H; V4 N        }6 X/ Z4 G1 d& ]
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
1 o  E4 q! A3 W5 i6 ]" B3 w                ret = exqueue.data[exqueue.rdptr];
" `4 Y0 G; P/ ^) x' }5 M3 S                exqueue.rdptr++;2 w( }) e+ d4 Y6 ?6 D
                exqueue.rdptr&=QUEUE_LENGTH-1;, h7 d6 I9 O) g* O0 P' s6 M- L# D
                return        TRUE;# s& `2 O( Z/ x0 G- C/ X: Z2 T
        }& ?+ B; @& I" C7 |5 V; ]
        return        FALSE;
; e6 a  C. ?) r  Z/ o}" |3 h  C2 k! ~/ i1 T

# i: u) L1 b' C+ @  s: N$ H& Z2 Evoid        APU::QueueClear()
8 K9 U( w1 ]7 T. B  C& D7 Q{
( Z8 E/ u0 f  ?: V' B8 p        ZEROMEMORY( &queue, sizeof(queue) );
  I; O3 w: H4 g- M1 V6 I* U8 K        ZEROMEMORY( &exqueue, sizeof(exqueue) );- v" H7 j* q* X, B
}
& M; j1 c( ]  `4 h7 X* k& G& A8 r$ S3 J3 o
void        APU::QueueFlush()
0 _- ]% f8 K0 w! \9 L: {: a{0 L( {5 F9 H9 ~2 w
        while( queue.wrptr != queue.rdptr ) {) r' X4 I- G) `
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );1 Y+ e& t; |! p
                queue.rdptr++;
# q- D' ~* {& k: v+ K0 `" l5 R8 t                queue.rdptr&=QUEUE_LENGTH-1;
' t4 b. Z7 G( L( p+ I1 s4 i        }& h5 k8 x5 h5 q' ^! H, a6 l9 X

: Z" r. e7 _/ f. U. ~2 _        while( exqueue.wrptr != exqueue.rdptr ) {
5 p7 ?( @9 [. x: q# w; \                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
" h/ L# K& n7 k9 N                exqueue.rdptr++;5 Z5 X; T' e3 ^% C- p  q4 u2 n2 P! x
                exqueue.rdptr&=QUEUE_LENGTH-1;! I$ h. e$ N' h% s3 Z6 X0 t5 n
        }
# P; W0 G3 N% g, C' ]}0 E6 `1 V# T  ^1 _

  J) C; y) m, c' [void        APU::SoundSetup()2 x2 q$ o1 u9 N& J2 J/ |% |* S. e
{9 x6 Q  M! D+ F# i
        FLOAT        fClock = nes->nescfg->CpuClock;4 [2 ^. `! X, K& U$ |( Y3 c
        INT        nRate = (INT)Config.sound.nRate;
1 \# O$ p+ ^" ^  N% U' X        internal.Setup( fClock, nRate );* n/ ~) Z, [$ ~: e& U' F, }) t( o
        vrc6.Setup( fClock, nRate );
/ q- m) x9 t1 n9 g5 V' U        vrc7.Setup( fClock, nRate );
! j* o7 [2 e6 c: H! W6 H: d! y        mmc5.Setup( fClock, nRate );
: t. s: I4 w- r, m) `% e/ [        fds.Setup ( fClock, nRate );. V2 z+ o. J; _% v7 |  o( H
        n106.Setup( fClock, nRate );
/ n; o% ]) l+ h1 O; b1 q  i        fme7.Setup( fClock, nRate );& U- h2 o) G; v8 ?6 K$ g2 b  R* t
}  `1 W3 J- c7 Y- P
2 u7 L8 u0 F# b) l/ I. x
void        APU::Reset()) w# Q9 m6 L* p, h, z
{$ ?0 F  r8 U# L+ Z/ Y  F, a
        ZEROMEMORY( &queue, sizeof(queue) );% `% O) T7 k0 _' @0 n# U# E  l
        ZEROMEMORY( &exqueue, sizeof(exqueue) );# N! W0 k/ J! l' L
6 C& H6 d8 u9 D
        elapsed_time = 0;% u5 R% t8 B/ j

/ m; w1 u8 N4 _) z3 G        FLOAT        fClock = nes->nescfg->CpuClock;
& ]$ j$ q/ V3 y) Q) E. D        INT        nRate = (INT)Config.sound.nRate;+ X$ j8 T1 t$ w( C, W! y9 H
        internal.Reset( fClock, nRate );
- b# \  y2 J4 i$ q. p' W% J- ]        vrc6.Reset( fClock, nRate );
, P9 z: u1 n- q3 F/ O" M; X; w8 @        vrc7.Reset( fClock, nRate );
1 n  Z0 @- A* v; ]5 M& M- L. E( I        mmc5.Reset( fClock, nRate );& M  @2 G0 d; f) D6 c9 J* j. e
        fds.Reset ( fClock, nRate );
+ o) U6 `3 F+ Z, g0 u7 h        n106.Reset( fClock, nRate );1 h6 z: p. q* E% o# K* c
        fme7.Reset( fClock, nRate );! e; z7 ]* o9 s0 U, O

6 M8 B3 [* u* v! f) r        SoundSetup();
: T+ j0 g9 L- q) A1 b* j. P& c}* h  X5 y1 J4 s. A

/ S. t- Q* ]% l7 s% a3 G3 }7 \- bvoid        APU::SelectExSound( BYTE data ). u; V6 G) v% d8 h1 T7 c$ M( }
{) q# ?: U* t: e7 G5 L" G; }/ a
        exsound_select = data;: o, J" r& b- U
}# e7 X/ X' g0 S% B/ B' q4 R
& K! H% Y) L# N
BYTE        APU::Read( WORD addr )) ?, o; {- v! v+ {+ p
{3 D" l% x( o/ B" J
        return        internal.SyncRead( addr );- N0 z& ^* L) y; J" Y0 E# @# Z" Y& g$ |
}
& `1 ~5 i0 V1 E6 }/ [1 K' W
# E, _! S5 I5 X- z' @void        APU::Write( WORD addr, BYTE data )' m; N. r+ J# L9 |( |" |
{, j/ X2 n/ R5 y: e/ ]- x
        // $4018偼VirtuaNES屌桳億乕僩
6 u/ }1 ]& h  g; b4 G7 h* V0 f        if( addr >= 0x4000 && addr <= 0x401F ) {
0 S7 x" V5 o4 Z: G- W3 P6 r                internal.SyncWrite( addr, data );
; A. W& x7 s+ ?                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
$ E3 ~; |; Q$ t5 F6 }        }7 x% r7 Z" \% ~: o* j% J4 ~7 W
}/ M" ]; f0 V' y) X+ ^4 v4 B: V- O' g

! L% y# H/ j5 n' n: xBYTE        APU::ExRead( WORD addr )4 R) [: E7 @/ q5 S$ T
{
1 ~1 E) k  |! S( `0 I" B7 [BYTE        data = 0;6 {$ E4 F4 {# H7 e7 H

' k) @3 R! l- X7 D5 O! v$ x& K, I        if( exsound_select & 0x10 ) {
5 O  g6 m2 h) j9 i9 P                if( addr == 0x4800 ) {
8 R  l( y  \1 p/ P" K% L                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
. Z" w: i$ |$ T) f4 G$ |7 n8 y                }0 C$ B6 m; n) x1 W8 y6 f7 N  M
        }
# _& r3 G+ h7 [! Q9 D0 T2 a        if( exsound_select & 0x04 ) {* A7 Y) P: E/ O, F, |# w) R
                if( addr >= 0x4040 && addr < 0x4100 ) {
/ u5 j/ o  |" Q- ~8 [/ {2 Q                        data = fds.SyncRead( addr );
; |9 O0 q8 Q, G/ @/ c& y& W                }: {3 @/ x5 O0 Z. V3 K% m4 M
        }  d1 P2 |! ~- D& l; w. J
        if( exsound_select & 0x08 ) {; f4 m: d% s7 p) z& y3 Q( X
                if( addr >= 0x5000 && addr <= 0x5015 ) {$ y4 b: H8 e) V1 k  U4 `, _/ B+ A
                        data = mmc5.SyncRead( addr );
8 t9 |' S8 h) v9 E7 c                }$ l0 [0 ?# ]" L! V0 a
        }
& n0 n- e# Q' J9 o1 j/ O* j
/ Y+ C$ B& E, {3 b        return        data;
- ?. q6 _; M% v6 z( {' H9 C}8 t0 V4 k7 I2 e' {, P# W3 Q) v- Q
8 r2 u. n. t3 Y! L1 [! y
void        APU::ExWrite( WORD addr, BYTE data )
8 h1 e  u- k% B{
  O5 j- h7 d8 R! a6 e        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );. G& n& }; ?3 v7 H( W( ^

+ G8 F0 W; [# i( v; p* }3 h        if( exsound_select & 0x04 ) {
9 q1 G6 d( j6 ~/ w6 F9 }7 n8 H                if( addr >= 0x4040 && addr < 0x4100 ) {% t: |, ~$ n( f0 Q7 r% A" F( `5 I
                        fds.SyncWrite( addr, data );2 q  E4 X  ], h3 s+ b1 j
                }0 I4 P1 Z$ v' s! X
        }
. k% h* F* h; ?$ u8 \% Q
7 v" N* e  t6 |3 n% y# Z/ ~* d0 Q        if( exsound_select & 0x08 ) {
5 B, ~+ k6 F' r4 N4 O                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 h3 _( }+ [1 @4 X- V                        mmc5.SyncWrite( addr, data );
/ k# [' C8 D% W- c- v                }
/ q' m* y: v/ H; G9 a        }6 O4 ^/ p/ q8 K
}* u. T3 n! `; W1 O- v
, N, k  n. M! J8 U: p/ V: r1 v% N  a
void        APU::Sync()% A: |7 @( R, `  e' G/ T
{8 t' h, I6 _5 q0 v! ]! x
}
* @) ]  V& J) g1 I( K# D7 t) {* ^
void        APU::SyncDPCM( INT cycles )
/ F# M: B# V$ m( N0 F{( k# a; W; o, J
        internal.Sync( cycles );: q6 r  b- k! b  C" I; w) T

$ n) \/ w1 T7 C2 N        if( exsound_select & 0x04 ) {
' W3 H% X( A, e/ t+ G" p0 m9 ?$ z+ k9 i                fds.Sync( cycles );
+ E) W8 w4 U8 I/ E  f% R        }
# C" ~# \- ~1 p        if( exsound_select & 0x08 ) {4 @) E6 ^' H0 J: ?  z
                mmc5.Sync( cycles );
, U4 s, E' P; \: W5 C        }* i% g+ {, C) n7 x  F
}9 a  q* n% ?7 f

$ c& N( o; ]5 e# svoid        APU::WriteProcess( WORD addr, BYTE data )9 @3 @" ^' G( D: N# A
{; p/ f" J0 B, H# a/ y; E! l0 l' [6 {6 Z
        // $4018偼VirtuaNES屌桳億乕僩
5 @6 U! t' [2 `4 v        if( addr >= 0x4000 && addr <= 0x401F ) {6 ~  _$ y# y( _
                internal.Write( addr, data );0 o  t& w4 W$ P; p/ g" @, s% z; E" o- d
        }: S& y/ Q3 x/ _! N4 f
}
2 q- X+ R3 f) b; Y4 `% D% u% G1 u1 I% R; G
void        APU::WriteExProcess( WORD addr, BYTE data )
- }1 m! Q; t7 }, F& N5 D{
3 B4 d; y& ~- t1 K8 @# F, r& L0 a) D        if( exsound_select & 0x01 ) {
8 F* B6 e9 A0 c- l# H2 X                vrc6.Write( addr, data );3 [8 f+ k4 b! A  S1 T
        }
$ N- L4 `3 s2 `, j5 p$ x8 M7 G        if( exsound_select & 0x02 ) {% v, d$ w7 C2 j; i5 e
                vrc7.Write( addr, data );
% D" T( m+ Q) q" W5 \# S        }
. t) y$ n5 `# L) E! A4 V        if( exsound_select & 0x04 ) {0 X& [* ?' \  q7 E. `" e3 g
                fds.Write( addr, data );
! }* t/ x: j# o* B) }4 `. e        }7 }# R/ j6 I) g' x8 z- h  z& K. L9 J
        if( exsound_select & 0x08 ) {
$ B( f. x% B, `& O; T" u                mmc5.Write( addr, data );( _8 ?+ ^% B% p2 a( q7 R
        }" t( A7 H/ Q) l, B5 C
        if( exsound_select & 0x10 ) {
5 Q5 q% ]9 _4 O* F" \% J                if( addr == 0x0000 ) {
; }3 n/ f% f6 _8 F# L# V* {- I( |! D                        BYTE        dummy = n106.Read( addr );3 c( F/ d5 O6 L! z/ N$ }! l
                } else {
' B* O& z! w& ^. Z                        n106.Write( addr, data );# _' ?' }$ j& C: \" L5 U
                }
" x: b0 g6 Y' ]        }
1 I- l& ^/ T1 z+ V9 a        if( exsound_select & 0x20 ) {
! ^- g  I4 Y7 P$ U                fme7.Write( addr, data );9 f% p6 A* f7 F: X1 B7 c3 V" }
        }
! Y4 B9 l% z6 [* P' `" L! ~3 f}
: U% j6 D  C7 t/ {: R  P  x
" a/ H% c$ Z# B* Q% ?" `: }  A' ~void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )7 U" H. ^& k- i9 C, @  j  j2 ^' G
{; O/ y3 o, ]' f7 A! T7 z
INT        nBits = Config.sound.nBits;8 _, \9 V/ \4 n/ {6 Q( F
DWORD        dwLength = dwSize / (nBits/8);
7 A8 b' [& E6 p/ e1 xINT        output;
5 _2 M! S6 x% Z6 w7 mQUEUEDATA q;
& J4 z# k7 H$ sDWORD        writetime;
  d% s$ _+ q7 h% @* V" b% I9 |7 f: A
LPSHORT        pSoundBuf = m_SoundBuffer;# C. |6 ^& G( d. H2 H- s9 `
INT        nCcount = 0;
4 G) `* F3 _$ T" m0 T  D: D
* ^6 J: p$ ]+ T; XINT        nFilterType = Config.sound.nFilterType;1 t% ^4 t4 [" D8 h  G

8 e$ u1 y& y, ^$ B        if( !Config.sound.bEnable ) {
1 Z3 G1 ~* B: K. n& M                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );- Z" X% ~, y1 n
                return;
- Y, C. I/ A' M+ g; v7 x2 y! K        }
2 D3 r3 j4 [2 f! y$ P
# J+ W7 G# [1 A- K0 G( j        // Volume setup9 ]. l6 p# j6 ~: P  W* p
        //  0:Master* e  N% ]: k! V0 Y! a7 \$ M
        //  1:Rectangle 1
9 a5 F# j9 ?7 j8 h8 q        //  2:Rectangle 2
8 g/ Q8 E) K  U8 }$ U$ Y0 R! h        //  3:Triangle/ g0 O6 ?4 f6 B$ x; U3 k& x1 b! G
        //  4:Noise4 g8 m( B* D$ s- _
        //  5:DPCM
, V7 n6 P( d# ]' [; A2 B        //  6:VRC6
3 n4 Q- Z) R, O2 N        //  7:VRC7
) d0 D% I+ D/ H2 {' L2 Z5 O        //  8:FDS$ t/ {( I6 P! w. [
        //  9:MMC5
4 X4 Y. ?& X" Z* C, ?        // 10:N106
4 Q' }) W5 C5 F" t( [( h) r1 {        // 11:FME74 N% g/ {4 N3 K; I4 J
        INT        vol[24];
, y& K2 e3 `8 L2 w        BOOL*        bMute = m_bMute;) T5 y. l& c+ |# b: D! T! y
        SHORT*        nVolume = Config.sound.nVolume;
, h1 d/ f- Y  u6 ]
. L; m0 s8 c1 i7 j' F$ u        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# i; N( H  y) Z" u$ V3 b1 f& ~! s
% X6 h9 `0 l5 w9 v$ j8 {
        // Internal
* E' I3 h4 {* g2 f* p8 Y) P6 f5 K        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;* |+ D0 w% i0 Z* }" v: L
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;' G- V$ R1 Q3 r/ d) _! q
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ g# `, n' s% L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;2 \/ E  Q6 n' C+ u. _( x) W7 u* X
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
& k2 {! a6 ]$ N' Z3 |- z  Q/ c
) I$ Z* \. ^9 l0 f        // VRC6  `8 A0 d! V8 t* S0 h  \6 h
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;" G. b  o; }! f# U5 i' U
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( h; f1 e) S: k. P4 O0 @6 \        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 m  R: ~/ Z0 t/ @. X
" L/ {" _: x8 p+ U* j* r        // VRC7
7 g2 i2 C$ F) b. b- c2 ^: j        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
/ D4 d+ ?, e2 v8 A, r6 v. J& l" X# L9 S5 ]; J
        // FDS; m  E1 [! x. u. m# W* {2 d$ y
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 f4 T) B* H: e( q) K' S, s! _$ D
/ l: l) l1 r9 p9 b        // MMC5& c- }; ^6 q% a% t) e
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, W8 s  _" |0 O        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 V) C4 v- d/ g/ W% a
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 ^  `7 s0 I! ~) b, W

; u- o, _6 Z+ f  f$ P% C        // N106
+ y* K$ m$ @1 h        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# w/ }3 J- x! f  V. P, g8 I8 [
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" o* }( D. ^9 V. l$ i3 E7 W
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; q& K% g4 F) A! }* C        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ a, m# T. p3 b7 Q1 R. B$ t, V1 J
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ N1 [$ i: N6 T( z
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ j  c, q+ E; B( |+ b& h3 F2 c
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  f; ]" I1 p4 e* e5 ^+ v        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& W& G6 W4 ]0 p6 f3 P( g/ V; U
+ ]5 W, _; q' w) j
        // FME7) T2 {1 {4 o8 V" I) s' t
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  s1 n; s9 B. L- K, t; }; L* ~! C/ f        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& ?' F* I! K+ J; j
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& l9 Q& W0 X, w0 h
' c+ I. Q! h0 G: A//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
( c' o- R+ Q( ?: k2 j        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
$ S: a% [" n, \8 X$ z. z' o7 B# [4 ^
7 p0 b* D) `8 U9 d        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟' e5 {" j  y' I1 K6 R) g( i  D
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {; U, D$ l6 \) `$ B! |
                QueueFlush();
" s) j7 |# ~6 q7 ?        }
; ^1 j/ V# g, k& O: ^; m2 m7 v3 m& Y
7 p" f. s- y4 R7 h$ v* a& y        while( dwLength-- ) {: G7 I( \" W; J% z9 R# P- H0 V( f# X
                writetime = (DWORD)elapsed_time;
* L+ ?& s5 m0 N2 Q3 B6 T+ ?3 A$ I  X* y4 A! z) ~
                while( GetQueue( writetime, q ) ) {7 u7 B; l1 p8 U+ t# F& e( I
                        WriteProcess( q.addr, q.data );
3 s% S0 d& i. i8 `                }
7 u/ F' U( u, Y9 [+ a
0 v. Z5 Q2 h7 `; z9 w1 }5 |5 ]' Y# `7 O                while( GetExQueue( writetime, q ) ) {
6 ]5 b! Z: t% b" ~1 O                        WriteExProcess( q.addr, q.data );
8 |( k. D% P# n( r  o: \                }
  c6 s+ Z6 m8 Q8 |0 j: S4 t& T' X% H. F0 d% Z6 d& U# R
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
: T- v; u3 t% r4 N- s" J, |/ b& D5 a9 v                output = 0;
/ r9 C! K$ B( ~" V. r                output += internal.Process( 0 )*vol[0];
: G' T& z# e" n' E                output += internal.Process( 1 )*vol[1];- o$ G7 w% @& X( r8 i( \
                output += internal.Process( 2 )*vol[2];4 h" O' e& T( C3 `" @9 C1 L+ y
                output += internal.Process( 3 )*vol[3];) B( p0 \5 Z% E3 Z+ |- u: W; b
                output += internal.Process( 4 )*vol[4];5 t1 h: o3 G7 x! W, v% b
' N/ ~6 I( ?: S4 G
                if( exsound_select & 0x01 ) {8 @9 y3 `6 G+ Z7 R4 Z# g* z6 Z0 _
                        output += vrc6.Process( 0 )*vol[5];
6 z; L/ O: M- {% c, t+ \7 K0 R8 d                        output += vrc6.Process( 1 )*vol[6];! g4 Z  Q3 {3 T; e( N
                        output += vrc6.Process( 2 )*vol[7];. ?" h: Q6 _9 Z' @) K* Z1 ^# Q
                }
4 r/ b  ~$ k, \# F- N4 Q                if( exsound_select & 0x02 ) {  z+ O: u/ [# L7 v0 g
                        output += vrc7.Process( 0 )*vol[8];
! Y' b3 ~% G  X! f4 I* v                }. w  W+ O* \4 }$ f: S% t
                if( exsound_select & 0x04 ) {
# s$ h% o/ B' Y                        output += fds.Process( 0 )*vol[9];
+ p+ |8 }: k; r) i# z5 a8 M; K                }
/ x8 v7 e7 r7 [/ L; d' {                if( exsound_select & 0x08 ) {
- ^& x% p- V5 o. M& F                        output += mmc5.Process( 0 )*vol[10];" @7 ^: }9 {# V% ?+ G# v
                        output += mmc5.Process( 1 )*vol[11];
4 J' J/ B2 z/ ^* E% C& j7 x                        output += mmc5.Process( 2 )*vol[12];
" {# Q0 z( U: d: K                }$ @# E1 y% x- u: A
                if( exsound_select & 0x10 ) {
& `! f2 C+ r2 a! \                        output += n106.Process( 0 )*vol[13];
  c7 Z  O( s, ^) s% ]                        output += n106.Process( 1 )*vol[14];
! q1 s* u8 ?/ S' T+ O( e                        output += n106.Process( 2 )*vol[15];' \3 r0 ?0 a4 e! F0 v$ e( w
                        output += n106.Process( 3 )*vol[16];: f6 V- N  Q+ q8 }: c
                        output += n106.Process( 4 )*vol[17];9 G7 j' K+ |% d$ Y3 }0 `- {
                        output += n106.Process( 5 )*vol[18];6 j) V3 V, T+ |8 K( T# U
                        output += n106.Process( 6 )*vol[19];; C4 O: X) W6 @+ H1 J. V' x5 p( F! J
                        output += n106.Process( 7 )*vol[20];3 O% f2 A8 _- _. I3 {' H- k; }7 x
                }
* }' n- D9 {7 @( u                if( exsound_select & 0x20 ) {
( P3 P, C4 x! O# c8 s% z                        fme7.Process( 3 );        // Envelope & Noise
7 P( s9 J% |. n1 h$ o- h& k                        output += fme7.Process( 0 )*vol[21];
( j5 C+ A3 n8 d) ~( ?6 ]1 u8 {( g                        output += fme7.Process( 1 )*vol[22];
- F0 Y' \0 _' h' G+ }: e                        output += fme7.Process( 2 )*vol[23];
0 K3 n. }0 w) D$ V: ~                }9 L+ i- _+ m" ?7 B2 k
; t" W, ^) k* h  h
                output >>= 8;
& E0 i4 J0 O4 u' {
" F" V; [/ R3 O4 g( v2 H2 T                if( nFilterType == 1 ) {
9 i6 k1 b" J4 f                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
5 u' i% o3 ?; B$ k3 T                        output = (lowpass_filter[0]+output)/2;4 m! P/ `' n: ^+ m
                        lowpass_filter[0] = output;0 ^: C; a4 D) W" }; X3 A) Y
                } else if( nFilterType == 2 ) {
, B9 N! d& E+ y! U9 u  m( [                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
" N! ^* }4 B( R, L" Z" _* _, }                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% [, h) H9 J. Y5 n) }1 a
                        lowpass_filter[1] = lowpass_filter[0];
, E! \, E7 x4 B" `                        lowpass_filter[0] = output;
8 {/ ]( |/ a! @3 r* p+ ?" H) e                } else if( nFilterType == 3 ) {
! i) F2 T  G! V' T4 D2 `                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)% O- D! ~. _4 {( {5 ^5 N
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
( P* _6 {1 i/ T' r                        lowpass_filter[2] = lowpass_filter[1];, `9 x2 x- s$ k" U/ o% s0 F
                        lowpass_filter[1] = lowpass_filter[0];
* I, h: d1 a# N8 N. \! a4 b2 }$ z# D8 U- |                        lowpass_filter[0] = output;7 a2 f5 y& z' Z3 w2 V. j. T
                } else if( nFilterType == 4 ) {
2 K; p* P$ ?, H/ |, E                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* A) z' B1 H& H                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
% E# ^  o( a0 w, _9 W: P  h+ e                        lowpass_filter[1] = lowpass_filter[0];
. X; z. H3 m; q6 B' `# G( B                        lowpass_filter[0] = output;
5 B/ ^( |& A2 U$ A) O, y3 n/ l5 H                }( f& Z& d# V& f/ N1 y

: G! i9 @9 ]/ j3 s5 G9 N#if        0
( N' \; p7 c5 Z5 A                // DC惉暘偺僇僢僩, K' G- t' M$ _' A- S
                {0 K2 z9 L% }3 W1 b" X
                static double ave = 0.0, max=0.0, min=0.0;- I. h  W; B2 w6 F3 E# l. A
                double delta;
6 B2 s3 c6 K9 t! I, S' K                delta = (max-min)/32768.0;
5 C# X0 ]  W! @2 e                max -= delta;# o  W6 @, N, Q: p- y
                min += delta;
3 ~/ k! D$ c4 `" C                if( output > max ) max = output;
% {) h7 F; l( b; Y" P4 L                if( output < min ) min = output;/ X& M! U. f8 ^& O) B
                ave -= ave/1024.0;% j4 F4 t, Z+ [3 b" b5 l: X
                ave += (max+min)/2048.0;
3 `- Y8 T. U4 C7 q6 d6 G3 s                output -= (INT)ave;( e( F* S. [( o& \& C6 S
                }
* G2 a9 v6 n+ M$ A+ e#endif) D" V2 V5 b, m" e( I
#if        1$ E. I. D$ w; U& q1 q. M
                // DC惉暘偺僇僢僩(HPF TEST)
, G# Z( o9 U. e( S3 g                {" c  k1 i% D4 F
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);' @- L) m; N" f( i/ Y: O  w
                static        double        cutofftemp = (2.0*3.141592653579*40.0);, l) ^) }0 e! @4 H( E
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 |2 U/ q' |+ E0 g$ ]                static        double        tmp = 0.0;
, y* A2 f9 D* e3 o& F- G                double        in, out;
1 R, T- f2 b& i- \/ [4 D" _" \1 r6 U# |& [' s' e
                in = (double)output;4 V' n9 e& S# E" A8 X1 x
                out = (in - tmp);* l  g" G- O! n
                tmp = tmp + cutoff * out;
9 b1 D* G/ q* \$ \+ }/ v
8 L" p2 m3 ^5 i8 c                output = (INT)out;& g% V# x# X, W* F, d" Y: \
                }. b2 z7 x. C; i6 b; l' U6 K
#endif5 c8 K( e$ w/ R* H. y
#if        0
. i" j4 N& {$ x# b                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 v  V# [. F- @/ ^" n
                {
* u, K; L- U& W% x4 `                INT        diff = abs(output-last_data);+ l3 T0 F. a0 z
                if( diff > 0x4000 ) {
( P& v* ~) [4 k- _$ j, n                        output /= 4;
9 Y! K9 `- w& L2 h1 z                } else
; N1 e6 u1 g6 u/ r% D, I# r0 U                if( diff > 0x3000 ) {
) \$ F1 H9 T8 |                        output /= 3;+ a6 `+ ^9 u, z4 u
                } else3 ^4 F/ h. U1 j# F
                if( diff > 0x2000 ) {
6 z  k" ]. U1 ]& Q1 m5 X& ^                        output /= 2;, ]- I8 j, p3 f6 [# r% M4 N* W
                }% q: W5 m  Y, K5 I+ b  \
                last_data = output;
. l* }$ @0 {: a7 S. S                }, a6 p" ]. B, @7 _3 N, T7 }6 f
#endif8 u% ^: |* B9 ?+ _
                // Limit2 R2 y5 A! s" {4 e( r( I
                if( output > 0x7FFF ) {/ A2 |' V. Z+ h, J( {3 m6 k
                        output = 0x7FFF;
# v  `, p8 Q* L* n9 ]                } else if( output < -0x8000 ) {
$ }7 n# T+ Q+ [8 A6 B$ ~  i                        output = -0x8000;
, N. i! `5 Z: t  ?0 P6 g                }7 V+ t: b& G) R# `7 r5 J
7 u3 [3 s9 Z. ~: ]* ^  l: A4 t/ s
                if( nBits != 8 ) {
$ A: R  X/ S& b, x) n2 @1 s                        *(SHORT*)lpBuffer = (SHORT)output;
) X# Q' {( I/ M: r                        lpBuffer += sizeof(SHORT);$ z+ k1 E8 ^$ d9 C- O7 p/ U4 C2 N
                } else {
' Y' \$ z' f$ ^0 \2 F( K                        *lpBuffer++ = (output>>8)^0x80;# _, J7 F( V" m; t
                }
* [" O: G5 \4 E- L! h- v, t! l! O
                if( nCcount < 0x0100 )0 Y2 g3 B5 J5 m1 n4 G( n
                        pSoundBuf[nCcount++] = (SHORT)output;" g% ?/ d6 V- ^4 \

! G: w, t) Q  u0 l0 ?6 s//                elapsedtime += cycle_rate;- j0 |# {6 p) N* l) P- ^2 S% O
                elapsed_time += cycle_rate;" P4 Q! t8 u  Z- D
        }
( e' P5 p" m0 t& ^0 F. P4 x
- N0 H0 U( I7 n" |9 v: f#if        1; ]. i& l" p% y4 p
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
7 Q/ }2 x% ?# {                elapsed_time = nes->cpu->GetTotalCycles();+ x, f' X( j' J: |
        }
6 U7 H  m; M! a! p: A8 ^        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
" r0 E7 l) @  n9 u* b# a                elapsed_time = nes->cpu->GetTotalCycles();
$ _: e- k$ X' k) p  k7 I5 Z% x+ g        }
/ v  ~2 p3 _; u6 P7 C5 c#else( K0 j+ l$ z* V* S
        elapsed_time = nes->cpu->GetTotalCycles();$ y% {; I. L" M
#endif
- W$ w; v, F' G7 \0 O}
% t* z! i$ s4 f- J
& ~2 F6 G) l% [// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 o7 [2 W, s6 s+ N' \# RINT        APU::GetChannelFrequency( INT no )1 `8 H" X. Y  _. J; D- W
{
* O% A" V+ t' D9 _4 z' d        if( !m_bMute[0] )6 v9 x$ ?- U7 y2 T8 j5 ~* S- f
                return        0;
4 k) Q8 v4 W5 z
" ?' f6 f3 _7 Q3 A  T: D        // Internal* v) v& `3 \8 Q5 h% ]' R
        if( no < 5 ) {9 F" ?; [2 {% [2 J  T9 e
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
" U# q: b; [4 n- _( _+ t5 q        }  B5 x0 }. T! y9 X5 ?& X
        // VRC6
$ Y& X* U! |% M  N8 N2 b0 J        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
7 `$ \) |! `" w3 N! f0 x- T: S3 e% }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;; d; A; x/ k! u. p2 q1 ~
        }
! Q3 G7 |  J1 c1 b4 d( s: h        // FDS
$ j  }6 E" b* A9 d) e# ?/ ^; x        if( (exsound_select & 0x04) && no == 0x300 ) {! F+ K- m& }: i$ l# w
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
# l! {. o, J1 H( O; m+ P/ j; a        }
% |. V5 {4 ^  z/ E# r- [  Q        // MMC5
% q6 w* \) E+ G6 G6 Y' Q+ Z: p        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {  W5 J! {$ G8 r9 R( n6 N
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' E5 x  P% w8 ?7 z: A
        }
( [# e! a4 y* Z+ Z& P7 ?        // N106
9 N% X% m  G$ n! V! i  [        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' Z# M( z  {9 y6 ^                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 t4 K; l& m# ]* ^/ z! y, i; ]
        }* ]) Z7 Q/ r4 J9 L* C0 B
        // FME7
% Z" H2 r$ z+ [/ u        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
4 ^1 b! g6 U, S- ?2 Z5 t: N, I: }7 p                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;- h5 V7 I: @" `% I
        }
0 B+ g& y& a: S! C$ T        // VRC7
+ l3 X7 W0 X2 W/ q1 [1 k0 e/ @        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! Y$ _2 d2 V. n$ j% e% ^( ?6 D. F
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;9 P0 R; ^: w3 L. E9 O
        }; E/ H3 J9 V) V3 R- y- {7 U
        return        0;
: k* a! q) E6 B}
5 |) P% l" q% D4 b- e0 X
& F6 E; ~2 d1 D( Q. v+ a1 T// State Save/Load/ |* G# _* F/ t* k3 @
void        APU::SaveState( LPBYTE p )* j+ h& \0 Y$ g# E, E9 v  j
{. n; H. S& ^1 d' |) Y$ v5 E( G
#ifdef        _DEBUG
9 f: F0 t2 X+ q* H  p8 O' ]5 z3 lLPBYTE        pold = p;
5 P. ]- K8 V. I) A- M/ W) o#endif# L  l4 P8 v. R" p

  a" Z' Y. O- H( K7 X        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
  j  p' Y/ W4 B! |        QueueFlush();
- j" ?# }: @8 T. f  k7 v3 D* W. ?1 c7 w
        internal.SaveState( p );3 T1 F2 b$ B! K1 Z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 X9 @: G- n  o3 S" m2 M" d5 ~% X
0 L4 Z  D% Z2 n. a. j2 c
        // VRC60 A0 |" ?6 a1 [
        if( exsound_select & 0x01 ) {
; l+ S  b8 Y5 ^                vrc6.SaveState( p );
9 S- D3 y8 ], w                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 k. V% V$ V( F" x% h9 b9 U" C        }
+ J. ?/ f1 {' s2 \. B5 K        // VRC7 (not support)
4 `1 B% X( d: W  R6 d3 V+ E        if( exsound_select & 0x02 ) {
( P+ X. n' m' v9 t8 L                vrc7.SaveState( p );
* T# ]. O- N; L9 _0 I$ d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding5 `7 N4 X! F7 f' W( T5 Z
        }
  o7 I7 E& z: c! c        // FDS' M5 q4 Y, E) T5 d; u1 k9 _
        if( exsound_select & 0x04 ) {
. I1 o$ i5 x; L0 l8 R; _0 t                fds.SaveState( p );
  R. l+ r  e+ E8 B  J/ Y) D9 Q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
- t9 H6 Q! |6 N1 ^/ ]        }
6 t% x! o( ^, H- t+ c+ f, S5 _0 a, f        // MMC5
6 V8 w( J, {* s& s# C2 l        if( exsound_select & 0x08 ) {8 e- a. ~0 ?5 P
                mmc5.SaveState( p );
: O! f1 `, A3 B3 U1 ?* o                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 R/ h! s1 i0 j8 N4 o! i) f3 h        }5 ]7 |* z  n- ^0 M# T+ Y7 X
        // N106' Q( S( _, q2 r
        if( exsound_select & 0x10 ) {, w/ Z* z' V2 W5 L9 C
                n106.SaveState( p );
' X1 i: R  D, O8 r" p8 T2 J' v' a                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  m" A9 c" @  v+ x3 T+ o1 }+ Z- S
        }
, r/ |( O4 d/ @# J; g) A! X        // FME7% R, ~" A: L; I6 ?# J* d7 P5 m
        if( exsound_select & 0x20 ) {
: y6 Y& X  H2 P' O  d( b9 \                fme7.SaveState( p );
& f+ b: z3 P8 S( c3 S0 q                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! n9 B0 s8 Y" k$ c$ Z6 r" Z7 |
        }
( V9 P% l0 E( u0 x' u: x* m/ \+ `8 M
#ifdef        _DEBUG
+ J) S+ [9 |- }* MDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 j" _8 e; u4 G! u; T1 g. a#endif' L/ b9 P/ ^# d
}' i8 E) l3 B& x- Z9 D5 O% |; ?
0 W: o- D* c/ h( p  `
void        APU::LoadState( LPBYTE p )
6 G& r; B4 w- g6 ?9 b6 P- I* }( h{5 U% u( F, D+ w; V9 _# w6 l
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡: f$ _; p) L  n( e, U; a/ l" `1 v
        QueueClear();
& n1 f7 f) }, `3 ?7 b
- g3 V+ G8 p1 H" P: L5 k0 V        internal.LoadState( p );
" f( s# x9 B. i% Y, @        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( a& D# K  @& T% E4 {- x$ p: e" O. W) s6 b: R6 F
        // VRC6
' F4 x% Z" O$ B6 B& W( Z        if( exsound_select & 0x01 ) {
: Z* s- `& d( L, P3 i) e7 `                vrc6.LoadState( p );# p% Z6 P2 A. ^8 _- o0 ~+ s/ l  B
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 p$ A+ q" t, ?( ^4 m, G, z. b& V9 h
        }
, i5 D4 {- {/ J2 g        // VRC7 (not support)
% s. T- Z1 b7 @) }1 c2 O+ w  m        if( exsound_select & 0x02 ) {3 h( @; U1 f! X5 X
                vrc7.LoadState( p );
4 @+ M1 Y  s' F( z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" |9 T- [" A& h* X' Y% j
        }; ^# J" K7 w! H  M, I
        // FDS" w" z* t8 X8 e- D. A7 }
        if( exsound_select & 0x04 ) {9 [/ R+ W) d" n4 C
                fds.LoadState( p );
3 \" {2 D6 j( ^! |! k                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 H5 s  e, _0 b' M' X3 P5 @
        }
  t" B5 B! r" Y$ g- s4 g' `+ e        // MMC5
; L" j1 h8 s5 x( K8 r        if( exsound_select & 0x08 ) {: ]4 e: }5 ]9 H+ b9 v% V: Y
                mmc5.LoadState( p );
! g- \6 T/ C- n) u: l: @3 g5 F3 a/ e! o                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) a, V" x8 |/ U$ y( [, Y" m8 |9 [        }" x5 E- M6 q$ I3 a/ |$ X
        // N1069 J, h* t' R5 U3 x3 S% y8 N/ S% N3 m
        if( exsound_select & 0x10 ) {
7 q3 p) N, R* Y% f                n106.LoadState( p );7 L; S6 ~" X. S5 a4 h0 L2 M- P# n3 U
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
. a* s, z- |8 D$ W' |; u9 Y) Z        }1 @+ c' P8 f" E# a
        // FME7
; h% k9 d8 C. Q5 A4 X5 i( l0 e- s: H        if( exsound_select & 0x20 ) {
5 H0 |, Q; h6 h7 I& O/ `7 v                fme7.LoadState( p );3 G( p2 S6 y& e% @$ e) Y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( L+ e3 l0 O. v( f0 ^$ e) d/ [        }' Y9 C" H" M7 Z6 i/ g, C( x/ Q7 [
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
% _3 f' B& j* A; H4 L1 i3 n可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
/ @1 M5 @, b+ V0 B感激不尽~~
7 \5 p6 k6 y9 e9 Q: l
恩 我對模擬器不是很有研究,
- X) F( p9 i# X" w# _0 D雖然要了解源碼內容,可能不是很困難,) Q* M8 ^7 d9 K! h4 E% d+ n% x3 `
不過還是要花時間,個人目前蠻忙碌的。5 f8 |$ j, h* t/ v" l) h

- C5 K( }: p5 @# U$ _' o給你一個朋友的MSN,你可以跟他討論看看,; b4 B7 e" n0 u% ]( T
他本身是程式設計師,也對FC模擬器很有興趣。
; p* b, ?8 n9 |- Z6 v% [+ A! ^9 x  O9 I, Y  f3 n7 |/ K' z
MSN我就PM到你的信箱了。1 ^; U: T8 [' ]! C; J( h( e

  a8 a/ E9 ]  g! H( ]0 n希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表
, a" a+ P9 L/ j$ W  M* S/ m% m呵…… 谢过团长大人~~
. o( f9 l5 Y  {7 I  h

/ n$ R! M, V5 \哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
% s, Y# ?# s9 C: O团长的朋友都是神,那团长就是神的boss。
) E9 l. I6 M8 {4 W
哈 不敢當,我只是個平凡人,# N, l1 ^! C1 a! G
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
* s4 B( i" V* w% }ZYH
3 [4 _5 W" l. g# Q4 H; E) bQQ:4147343061 B0 S# }0 q' O8 ?. I
Mail:zyh-01@126.com
* v: W) V) \2 h5 L* l. z! i" H2 ]" Q; M8 _0 g, b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 + F4 I3 Q: R/ S0 K" {6 l
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ c( M4 @$ m* `8 O9 r+ h
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-30 06:02 , Processed in 1.070313 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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