EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 S7 @6 Q5 q7 R0 e% Q: H! l, Q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 P! }" X& Z, q
这里有相应的模拟器源码,就当送给大侠了~~9 [# t0 q  i) K& z7 U2 g
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
* M  a9 W. F4 ?4 o/ j& B' O" Q能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
+ M0 U4 g7 C+ a- u) D楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
0 a8 N/ r) _# _# t3 U0 ]: b# q这里有相应的模拟器源码,就当送给大侠 ...

- |. t: o! D- v% a5 Y/ f& ]+ a4 b聲音部分(Audoi Process Unit = APU):5 t+ A# T1 E" N
.\NES\APU.cpp
) n' E7 ]! x% g1 G6 A& k.\NES\APU.h, G! v$ d) b6 S: [5 G0 r3 Z

( @* k1 _8 k/ w0 G
  _. ~1 q/ I  S1 Y影像處理部份(Picture Processing Unit = PPU):' K& q: Y  R3 E$ _
.\NES\PPU.cpp6 R. e: y6 }: {( r! [. Q1 b' u
.\NES\PPU.h3 C: ~9 d% X1 |% u5 v

, f! s3 O& \2 x' Q, M+ S如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
& _. R3 c) r  A3 ?2 P  ~1 c(由于很多专用术语和算法机理都不明白,所以看不大懂……)* a3 m7 G- ^. [. N+ o0 C5 G0 L8 X
//////////////////////////////////////////////////////////////////////////
4 e: R" R$ V7 w# j4 c; R+ D! N//                                                                      //8 C( ^  R- _. d, M; q+ S
//      NES APU core                                                    //
% ]! c1 S! S( L# F! d- U2 @//                                                           Norix      //
+ _( Y& \6 @; W% R5 c2 w- v/ L//                                               written     2002/06/27 //
4 v; w, X8 _3 N$ h& r: f/ ^//                                               last modify ----/--/-- //3 V7 x- M- q0 @& W( t$ H1 D
//////////////////////////////////////////////////////////////////////////# N; ]% w6 Y% s6 F" u; L$ i
#include "DebugOut.h"
+ X3 l5 f) U3 j+ P! B#include "App.h"5 P; w9 |  U" [" ]( f$ D% j
#include "Config.h"$ p  M# X0 W8 V) e) o

9 M+ M# k4 Y2 {  I8 y5 g; _#include "nes.h"* L) S" @% G+ y, \8 g9 W2 V6 Q: q
#include "mmu.h"- Z. i2 E( H9 b; `  `
#include "cpu.h"
3 h* [( ]. e  _9 s1 m  w#include "ppu.h". g( o! i- S" y2 r( T0 \2 z) R
#include "rom.h"
. Z+ p& J& k# V" o1 X#include "apu.h"
2 l9 {+ I# n" y8 F( W' k, r1 ^& h8 w5 [
// Volume adjust
/ _5 \4 L2 J  T9 Z; [, i// Internal sounds
! y5 j% C. \" [+ _* V8 P#define        RECTANGLE_VOL        (0x0F0)1 D; E/ @$ E% i; `# R  Q
#define        TRIANGLE_VOL        (0x130)/ T$ k0 h0 N* I8 q, I
#define        NOISE_VOL        (0x0C0)
  [9 l& q9 ^( C) ]' [& z' c- c#define        DPCM_VOL        (0x0F0), y  o3 b- [# g9 V  n
// Extra sounds
. X9 B+ e8 E' Q7 @#define        VRC6_VOL        (0x0F0)8 S3 m' s0 s- H& F
#define        VRC7_VOL        (0x130)( _( {/ k( @. C, x: e
#define        FDS_VOL                (0x0F0)
( M/ f5 K& [1 g- B#define        MMC5_VOL        (0x0F0)
* {# l$ u% q4 G5 F#define        N106_VOL        (0x088)
# D7 A6 q6 j  ^! h. N  u4 _; `- H#define        FME7_VOL        (0x130)8 n# D. z* u+ `" w! `5 I, u
4 Q0 L" ^0 y7 ?. j+ h" ^1 a- R
APU::APU( NES* parent )
+ F6 _7 I: F$ K$ ]0 D{
8 j9 J2 o' z9 j) ~0 {# O  ^( X        exsound_select = 0;
, ^1 [3 e/ t$ U) e( G- j& r/ D2 N
, j- t' [% A( N/ K9 G1 @        nes = parent;
! J1 x" x" H. I        internal.SetParent( parent );
1 {2 z- t- r9 k9 G" r' L* B2 I# Z% G; s
        last_data = last_diff = 0;
8 I( f1 v! o3 L+ r  b; Y1 f4 G. J! v. S2 H  A
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
5 m+ b$ c( V, E1 h8 s8 o, ^6 d% |7 b; I  k. Z# h, T) u2 `
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; u/ `' J3 W8 e' J6 ^3 K        ZEROMEMORY( &queue, sizeof(queue) );
; p  x" T* @. _+ L- h  w0 k1 J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 [; J2 o1 d: j. @0 Z! h
5 Y" X" {0 p) d% H6 @        for( INT i = 0; i < 16; i++ ) {
# b$ a! |1 v! R; P                m_bMute = TRUE;: j; C9 a: h" g) Z2 k, H
        }
" }& k% }9 R, D4 L8 x1 p}& f! b% q! o  G6 T5 B% H/ e  J' f
5 a1 D: t3 z8 Y; R  x+ O1 |
APU::~APU()
4 }: x0 P* q' ]7 F- C4 K{
! i9 ^6 I% {" z; Z' ]}, L# C; @1 m2 U. R

: ~2 H1 {' Y/ B  g0 T# E- q0 E2 s5 M9 g5 cvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
$ t0 N4 ?0 I7 @# o* e0 B8 K3 r{) m! n* l( i* `/ ], S# m
        queue.data[queue.wrptr].time = writetime;
  l0 U9 D8 w' x& ^5 A. ^4 J2 I        queue.data[queue.wrptr].addr = addr;- S& Z8 H* k+ I6 P, f8 n% c. d
        queue.data[queue.wrptr].data = data;
, f/ P- f/ Z9 n4 L6 u        queue.wrptr++;% v4 e: ^1 `+ Y2 k
        queue.wrptr&=QUEUE_LENGTH-1;. }' j  N9 P* L. g
        if( queue.wrptr == queue.rdptr ) {
0 c6 d3 }6 ~) {6 J* `) {6 y                DEBUGOUT( "queue overflow.\n" );
2 T3 A2 }0 H8 {1 l  q' b        }
8 m/ G/ ~2 {7 k+ X- Z6 Y}  U& D" @: L8 Y8 x# ]; X  y2 g

' t1 B0 I3 |2 `BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
0 M/ o$ M* c' Q; V' f7 j- q( |{
) `5 }+ |  H  m8 B# U' l: v( E: j        if( queue.wrptr == queue.rdptr ) {. C5 V; A2 G  D: G% g& j
                return        FALSE;
6 W4 _+ _: D# x" E        }
$ H/ }, E4 G) H! ?" [5 A& B        if( queue.data[queue.rdptr].time <= writetime ) {1 R# }" J( f/ \: [* p
                ret = queue.data[queue.rdptr];" _! p5 `8 l0 b& T
                queue.rdptr++;
& E9 m; D9 d# Z8 {3 N8 J                queue.rdptr&=QUEUE_LENGTH-1;
- W* B9 @% G& {& B- {- ?8 b                return        TRUE;5 G% ^2 K  ]! t" A8 V
        }6 x4 o4 V2 t' d: i$ X! [9 v
        return        FALSE;& [2 A$ D- ]$ Z3 q. Z. P& N5 z
}. v7 t& ^! L/ M/ {6 v
6 \  |3 C$ q6 t
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )4 j! O, [3 O$ a: |4 g( w( x- d& B
{' i" _0 K7 M1 G5 t; D: m- z
        exqueue.data[exqueue.wrptr].time = writetime;$ \5 M" r4 S" y& d* X/ Q0 B( w* f
        exqueue.data[exqueue.wrptr].addr = addr;9 K0 V! [, f6 {3 S
        exqueue.data[exqueue.wrptr].data = data;* }; a0 }7 H- x; b4 Z
        exqueue.wrptr++;% W- ^( Z* N% a; Z) c! x
        exqueue.wrptr&=QUEUE_LENGTH-1;, U+ |8 h/ _; M: W1 v. a1 U
        if( exqueue.wrptr == exqueue.rdptr ) {
- q3 v& D2 S; M& ]) w2 p                DEBUGOUT( "exqueue overflow.\n" );
" `- O8 `1 t5 p7 e& u        }- _& f5 \0 ^, ]" w1 F8 \: |
}: V( ~& ^& q) m! q, {8 D! t
9 R+ ~7 u) H9 C+ B3 e( @
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 q$ A6 e& ?6 d{
% x+ l5 W: l' M7 q        if( exqueue.wrptr == exqueue.rdptr ) {
9 N" F/ `: A) q) j" B                return        FALSE;
1 w8 ^) B* I( ~4 j        }
5 f( R% _' H& Q( c8 i8 ^- Y        if( exqueue.data[exqueue.rdptr].time <= writetime ) {, ~& R6 ?. I8 q% r* q9 {. I" @
                ret = exqueue.data[exqueue.rdptr];
' L9 a2 @. @6 q+ D                exqueue.rdptr++;
% Y/ h1 r: N" u                exqueue.rdptr&=QUEUE_LENGTH-1;
+ A; D$ H% t2 c; e0 [                return        TRUE;
# O# Q+ f# O" Y& S0 s  M* t        }
* q6 @2 ^/ I/ z6 ~$ b        return        FALSE;; }- o, }8 l" Z2 S7 m/ Q7 J0 Z
}
# ]) E; O7 p9 Y6 U8 L1 y) Q
" V$ L6 m) y% l2 W: ]- Cvoid        APU::QueueClear()
3 Y  T# L* M3 A; g; c{
+ X( [  Z0 @7 ~5 @% g; i7 O- U" w2 A        ZEROMEMORY( &queue, sizeof(queue) );0 ]- y9 g3 R9 ^' x7 X( y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
8 P. r; c4 i2 @- [: ]& E( Q}; R4 a$ I3 p. O. U/ I

( @; H% q3 z& X) q8 Fvoid        APU::QueueFlush()1 d3 c1 u* Y+ _6 M, k/ F1 a0 i& b5 `
{
2 @7 ]/ N. r( O4 d/ x        while( queue.wrptr != queue.rdptr ) {+ u! x4 p3 ~- h! Z1 _, m+ U2 s
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" q- c3 _+ u8 p4 K# b( E                queue.rdptr++;  ~: M0 N2 f& n7 A7 d
                queue.rdptr&=QUEUE_LENGTH-1;
/ k( ^* R: o- m* d* @        }
% k0 u' y7 ^! \  I3 X; v- X# _, y8 A5 [" y8 W$ B2 O
        while( exqueue.wrptr != exqueue.rdptr ) {7 m- I/ }% B) l  Y
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
1 b! G; k4 k. b                exqueue.rdptr++;
- O1 Z! ?, I0 _2 t                exqueue.rdptr&=QUEUE_LENGTH-1;
$ V" p% S8 i& F# E; |- a        }
6 i! O1 ?2 T+ W% y+ s}/ D6 j  j. Z% L& o- Y; x

. D+ e9 O$ `" d$ b# p, [& l4 Wvoid        APU::SoundSetup()
* l. b' q$ a# i0 l( r7 I{
2 [- A  p9 w5 n& t3 @( L        FLOAT        fClock = nes->nescfg->CpuClock;! }. z" w/ V% v$ R
        INT        nRate = (INT)Config.sound.nRate;
! G# b! g" n3 z# [+ J1 C0 g" u        internal.Setup( fClock, nRate );
7 ]: M% r3 B7 Z- S( }; E        vrc6.Setup( fClock, nRate );
9 j' _0 T6 v. F% c0 W        vrc7.Setup( fClock, nRate );
- n0 Z0 H7 T0 B8 F        mmc5.Setup( fClock, nRate );5 f8 n9 a- D4 W& U
        fds.Setup ( fClock, nRate );
- Q; y* c5 I3 s- `1 ]  z' _. d        n106.Setup( fClock, nRate );5 P9 i+ u- N1 Q  Q" _0 [
        fme7.Setup( fClock, nRate );( _# C$ ~5 ]% ]9 Z' w
}- _) Z8 f3 K9 }6 B  Y* |& a
. C6 H9 o1 S' C; J8 M' s
void        APU::Reset()* {% H8 s) @1 U5 A& R! |( {
{
2 ?; S2 g& g. [, S- Z        ZEROMEMORY( &queue, sizeof(queue) );4 s) q" l& l4 w" L; A7 H9 m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 F5 {" j( u* l
& _% N. a; C  e- R) V        elapsed_time = 0;
, g, q( l0 k: U$ s- {, p- j
: \. {; q* D; w* k% y        FLOAT        fClock = nes->nescfg->CpuClock;3 p! Y  t% \2 c6 J  }1 W2 Y
        INT        nRate = (INT)Config.sound.nRate;
7 f3 f& W8 b6 f! l1 Z% S        internal.Reset( fClock, nRate );; L1 B& c  o+ T; r
        vrc6.Reset( fClock, nRate );
3 v7 Y( _8 H* n% d( ~2 d        vrc7.Reset( fClock, nRate );8 _" `7 D; s* G; l/ @1 X8 g
        mmc5.Reset( fClock, nRate );
- F3 _0 ]$ N; N' e8 R' p1 J: ~  @        fds.Reset ( fClock, nRate );' ~% r0 L2 |# I: W) y# F
        n106.Reset( fClock, nRate );& W! C% Y2 ~. Y- K# l3 M
        fme7.Reset( fClock, nRate );! ~  R8 t. r. B  k( C

  T& U6 W; A- H' ~; ?# D, A" ?, Q        SoundSetup();
* h: p: i$ ?" j& L: u1 h  z}
$ F7 o9 Z9 U# s% ~: E5 z: C4 [
7 ?' n5 s: G+ f2 Avoid        APU::SelectExSound( BYTE data )3 a0 N, q& j: @8 q- }' U7 P
{
/ ]% C; J5 \# M; P. C6 }; u& E        exsound_select = data;
9 Y* L9 @9 O( N/ B7 D* p}+ t! B  z: i% N# r9 g

5 z3 _% c' K7 c8 Z- P" o8 a) RBYTE        APU::Read( WORD addr )6 ]/ n- z7 T2 ~& O
{: K4 C" \0 T! |: s4 b1 P  Y, q) ]
        return        internal.SyncRead( addr );! _* x8 K* m0 Y
}/ K  z. H0 f4 U; w; [' j) S

. D! a! [, S4 `' N3 M& Xvoid        APU::Write( WORD addr, BYTE data )$ p9 ^. {, w1 T
{
; O# i. n4 R5 R+ O; \3 X, m2 v) E        // $4018偼VirtuaNES屌桳億乕僩* }7 m- A) {; ~) `
        if( addr >= 0x4000 && addr <= 0x401F ) {
" {& o3 j- B- H0 M% |& J% B                internal.SyncWrite( addr, data );1 E8 h3 V. B" t" {6 i" @# ~* L8 b
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );1 V: S/ O* ~9 I/ `" e
        }7 j- e* I) F: G7 b9 p
}
5 Z7 {+ y6 \$ @( h% Z& b3 E
# W, `8 Z9 i& \; @! [1 x* T$ `. I- QBYTE        APU::ExRead( WORD addr )
# u1 j: R& h* E5 \/ r{- o5 l- P) W* O  ~" U
BYTE        data = 0;
3 y6 w& R$ \" ]: }! ^& A4 |2 Y' v- R" j7 x
        if( exsound_select & 0x10 ) {+ F, `- t1 x2 N: V; ?8 R0 D" E0 B
                if( addr == 0x4800 ) {
( z0 K0 L+ X! a                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
# L; [6 w5 Q* X3 t' W, |                }8 m9 _5 \  ?% G4 f) a1 \7 d
        }
% V' d* Q3 {$ X8 T( r- h; `& f6 f        if( exsound_select & 0x04 ) {  }" F* A7 [7 N- V! _
                if( addr >= 0x4040 && addr < 0x4100 ) {
) P( g8 N; P* n- r                        data = fds.SyncRead( addr );0 @% k. f6 T+ X0 L  H$ X3 V
                }
% r" k5 m( h, V4 ^6 I  A& V        }
9 F. z+ J# m% x        if( exsound_select & 0x08 ) {* `# v# ]. C& t( }) a9 B- p1 |
                if( addr >= 0x5000 && addr <= 0x5015 ) {
7 u) H$ J3 s" ]9 p# y. y8 V5 K. N                        data = mmc5.SyncRead( addr );
6 m* I: ~/ m8 r( x4 U+ L$ Z0 T/ d) l, s                }/ }: q0 m% a8 U/ ~  z# M
        }- ]) \3 z, X' F% Q! |
6 f6 o* _3 v3 c
        return        data;) S) ^; a# G- r: S, l1 S3 k+ r! y
}# J0 G) r! \8 G  R5 Y, V- M
8 Y8 n% u' {2 o& c2 v3 f( a7 y
void        APU::ExWrite( WORD addr, BYTE data )0 t# M( e; y% W6 E7 C2 [7 K5 ]
{
) e) D4 f1 {$ b9 V        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );( K& P9 ^( _1 O( V) A7 \* B9 M( Q
. ^) j5 {. U- X9 I8 Y, L& `
        if( exsound_select & 0x04 ) {
2 P! f) [5 n. B1 Y+ L" N7 g                if( addr >= 0x4040 && addr < 0x4100 ) {
1 ^& @' y2 s) ]: a& P5 |                        fds.SyncWrite( addr, data );1 C. }' D0 ^) @+ Z  L* _% o& C8 b
                }
5 F  K  S' q  ]        }0 i9 k3 n% I+ ^
6 j7 q3 Q: @0 k3 |) p8 j5 N1 N
        if( exsound_select & 0x08 ) {
- b. \0 @- M5 |: I+ q& Q$ ~                if( addr >= 0x5000 && addr <= 0x5015 ) {
( _6 o; Y5 p+ n  x) O9 h* s                        mmc5.SyncWrite( addr, data );
+ c+ D/ t" Y" R6 ]                }$ Q7 z: V# Q3 t
        }
0 ~: G3 u: O+ D- K! }}
" E$ G3 j! N9 u/ U$ {& X$ c7 ^" Z7 c: H) T  E& u
void        APU::Sync()5 j2 f$ M( q+ o% v& X
{
% t4 Q! ?8 t+ ]+ b8 x/ w}
* S( d0 Z4 v2 l6 V% l4 r/ q" O8 k7 X) `7 z& {& Q5 `
void        APU::SyncDPCM( INT cycles )
; k' T7 }6 C4 b7 e& m4 I{0 G/ Z- P4 M$ m3 r, l6 K
        internal.Sync( cycles );0 O! S6 Y' k; ^3 ?6 q
% B3 Q2 {1 K* p: g
        if( exsound_select & 0x04 ) {
+ _5 j9 q8 |* B! D                fds.Sync( cycles );+ \& `! T" b$ B: P& z
        }
- N) L. f& U" ^        if( exsound_select & 0x08 ) {
5 r: p+ E  p2 n* j+ F& K4 q                mmc5.Sync( cycles );6 ^# @3 j2 N+ M
        }: q8 z; Q, N8 p  `2 a& m2 A9 j, B
}# y1 }, P4 J  P8 n
% C, \# a( t% V' [. y& y
void        APU::WriteProcess( WORD addr, BYTE data )
! b, o) F0 t7 x  b! M0 Y{
3 T; j; B" t& g7 b9 b        // $4018偼VirtuaNES屌桳億乕僩9 B# a  @; t7 m: b& C; y
        if( addr >= 0x4000 && addr <= 0x401F ) {6 u/ \. t) W5 i) u3 _
                internal.Write( addr, data );
7 H, Q. Y/ p# a+ c        }1 k4 r6 B5 g' r2 ~0 s' \: M" i* E
}8 u) o/ W: I3 a! {1 F3 H4 F" k

+ j0 D& a7 `* y( |) @4 N. s8 o, |void        APU::WriteExProcess( WORD addr, BYTE data )* u$ ^; N6 l* z( E! ]7 A
{
2 i) n9 y5 U9 R        if( exsound_select & 0x01 ) {0 ]. ~* a3 P9 h! @* J
                vrc6.Write( addr, data );1 X6 L' J) [; h& K& n# v
        }4 g& y. G1 E3 q/ W
        if( exsound_select & 0x02 ) {
. ~" c- }/ @, I+ Q; H3 R$ s                vrc7.Write( addr, data );& X9 X. `7 X4 j0 w# W1 y) [
        }
% e3 B8 ~1 ?2 r: q" b/ x        if( exsound_select & 0x04 ) {' i/ N, {# J# f4 w, B; Y2 V
                fds.Write( addr, data );
: r3 A$ s. ]  J/ y, R        }( o& h  T" f* f$ J0 t
        if( exsound_select & 0x08 ) {
+ Q% X- ^7 G* {6 p6 v0 r" @                mmc5.Write( addr, data );
; h# Y, U5 t$ J7 [0 e- ?. f  d        }
- o' T3 q0 ~3 e/ [        if( exsound_select & 0x10 ) {
1 Q3 ^% m- R4 I                if( addr == 0x0000 ) {5 u* |$ S. S/ `2 u
                        BYTE        dummy = n106.Read( addr );+ |) t1 I7 @8 j* G' f3 i2 m; V- ~
                } else {
/ q& d/ s  @7 \  u: M7 m: u                        n106.Write( addr, data );
: I% X& B$ y4 }1 r. e/ }2 P  l4 n6 Y3 l                }
( M* u5 }/ c  R        }9 X. N0 u- A0 K" t  S) g: {
        if( exsound_select & 0x20 ) {
# G# |3 h. y, E5 O' y7 j# [: u                fme7.Write( addr, data );2 V* O5 z! V+ a: c; m, ?  |# D
        }' d* p% g3 R/ d
}2 Z' u9 ~& |( l* r) }) h/ b
9 q) R1 V; H2 t1 L! x
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). d( X0 E3 i* r- B! O8 F8 O1 m7 H) B
{
4 \/ k& }7 P+ t/ Q$ `! FINT        nBits = Config.sound.nBits;7 D! }' ~3 y# G% E& z2 N7 p$ x6 G
DWORD        dwLength = dwSize / (nBits/8);
: j. N* X9 ]% }! V6 YINT        output;0 t0 E5 l7 X2 [$ T; j0 o
QUEUEDATA q;
9 H7 r2 J: s4 J/ P5 N2 V  K1 s+ WDWORD        writetime;& ~/ ~$ E9 Z/ u7 z9 e9 t+ W" B% @, i4 j
! g7 h6 U% B. ]
LPSHORT        pSoundBuf = m_SoundBuffer;
  R- i# u9 A, u4 `& c* aINT        nCcount = 0;5 a9 V4 g  d$ g4 W. _; }1 {" l
2 o! i9 b2 |( _! q2 U8 Z5 h2 i6 e
INT        nFilterType = Config.sound.nFilterType;
( z. I* w" |7 N2 Y, |+ ^, {% i# k0 K. \' t, h
        if( !Config.sound.bEnable ) {1 S8 X: N* _8 F2 M+ Q2 l( B
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
, Q/ o3 }% X0 l  m                return;
& T  y' W8 u1 H5 Q5 ~        }
  t# _# r5 g& ~( |. _9 F; c7 o2 Q' e1 ^! n' S
        // Volume setup
' K' h  U2 J, X; k6 G        //  0:Master3 H" U7 w5 f# F; F9 r
        //  1:Rectangle 1" _' P/ V( u  I/ P- I
        //  2:Rectangle 2
* j4 `) t: o5 J) I1 U1 @        //  3:Triangle
5 }# L: {6 [0 h5 b$ q        //  4:Noise
" G8 J% a. _4 u5 f/ z2 ^! Y        //  5:DPCM
  d" V/ W: p# m        //  6:VRC6
1 t' h  |0 ]0 c9 T" u% d+ q1 {        //  7:VRC7( J0 t: h6 ?' ?
        //  8:FDS1 Q2 I5 ^6 h7 [2 ?' Y
        //  9:MMC5! v. f! C/ d* V' I, f/ u
        // 10:N106) ]" {; k; i/ r" b! b, z
        // 11:FME7
% ~) i6 l* {0 H. ^9 ^( r        INT        vol[24];
0 K$ E1 P) f0 x% I        BOOL*        bMute = m_bMute;
' e8 y5 d+ v) B        SHORT*        nVolume = Config.sound.nVolume;- Q! G* L: M7 a7 y) \
' L2 Y4 Z- N% O' C# V5 G
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
0 {( b& ^5 I  o1 o9 H2 s! W9 A! K- E+ }0 U0 ]
        // Internal/ u$ b. d. G% i
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 l' r9 z5 O& Z* S
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
6 c# Q4 L7 [/ n) F) Z        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- J+ E  d! T. e9 W* M
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;* W. N2 U: o1 [7 I$ i& l
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
1 M9 B& R% w& h+ U6 o. n2 M) a! e3 H. G& z) `7 x  Z5 s
        // VRC6
+ H+ x, D1 J% R; u& Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, @, j4 q  z. s+ @3 o        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 e9 Z2 S& p, B* y        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 n$ a! K+ i( g9 f5 ^1 R+ t& b8 d& J3 V/ U* w* V
        // VRC7( y. O% D& v( @8 P* `' }' Y, x5 W. J
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% |: a# n, U4 C
: o( a0 W6 g, n8 A3 S5 u
        // FDS
4 |4 ?1 P9 _5 w% p        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, i9 T0 T1 W3 b+ m# f' S( w" Q- X
) E& p# U. W/ j# @) q4 L' {4 D        // MMC58 Z  I* B' c, [/ r" C; P. j
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 d) W9 K! q* J$ Z7 \4 q! y% B        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;* Z) V, f4 z) X7 N7 o# e  Q$ j: p
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" x% }, }# C/ J% {/ t8 {% j3 C9 q% g+ a# t) j- }. N
        // N106
3 c0 j+ i% O' x; y        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: n: `, J& c# }' {( c
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; v7 m/ a- ]5 n" c: t
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" c: s2 z: ~2 B% f
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 W( ^$ d3 n) P4 J1 K
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ^1 t) R. Z! c8 p        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 Y+ C5 r' x, q6 e+ p        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  w( b7 q$ K) v5 t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ `- {2 T  R4 u/ R
: Q: ~4 Q/ m( u1 t0 I
        // FME7
( Q4 `; H% e5 \  \: a        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 |1 G+ c, M6 r. M; D- U0 k        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ ]4 J) f) Z" B6 o' c        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;: j* M0 g# D1 ?' K: V# |0 t3 `

+ T1 _( \1 K3 k& H: o//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 Y$ U: y! p8 D, s
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
5 X9 V: V* A4 d, l& k5 T
1 _$ D; F, y' Q3 G! R1 A. G        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
7 s1 i1 U% u% b0 A2 y$ a        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
' \; j) |* H. _5 j7 ^                QueueFlush();: s) j: X$ M( Y3 g- T
        }9 p: @, q6 C0 M" C

( n; B! d* d7 T        while( dwLength-- ) {
; z7 j  b0 H8 Q; C/ H) y$ V                writetime = (DWORD)elapsed_time;
3 S( Z( X( Y  _6 [! N! {
9 \+ B$ ~+ i  j                while( GetQueue( writetime, q ) ) {
- K* o; _4 h: ^  M/ t+ m4 T                        WriteProcess( q.addr, q.data );1 u" ]8 Y8 X' @. D3 X) w1 O
                }
8 p1 H$ e# K/ t+ d: Q0 T
! M8 z. M( q8 n9 l1 q/ {                while( GetExQueue( writetime, q ) ) {& S& x* V1 B; I; r6 [7 }2 T
                        WriteExProcess( q.addr, q.data );4 B) E( C( H1 N& M$ K
                }: O+ N$ Z: m4 f; U" ?# Y% R6 J  }

! Y8 m) E: R6 y1 \# C- Y! N                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7+ e9 q5 B. d. e  D1 ^1 d
                output = 0;9 m8 z; W. Y1 F
                output += internal.Process( 0 )*vol[0];
5 w% @. [: {: ?% I9 N                output += internal.Process( 1 )*vol[1];
# |1 N6 Z* o% U( Z) c6 R1 |- t                output += internal.Process( 2 )*vol[2];
& \7 r( `4 B) o  A* B                output += internal.Process( 3 )*vol[3];
9 D9 Z& e, S4 U) ]' |- ~7 Y                output += internal.Process( 4 )*vol[4];7 U7 r9 t* ]6 L+ v" [1 u

8 c" y. b8 v( M                if( exsound_select & 0x01 ) {/ u* V9 C0 F* G+ f
                        output += vrc6.Process( 0 )*vol[5];
  R4 g9 w0 }6 B  s$ J' X1 V                        output += vrc6.Process( 1 )*vol[6];8 \- S# b6 J, c% @
                        output += vrc6.Process( 2 )*vol[7];
0 W$ R* i+ b/ f6 r, I% Y; V                }  S4 F$ O# ?- A& L+ z. I
                if( exsound_select & 0x02 ) {
, _4 P  C8 Q& T3 b                        output += vrc7.Process( 0 )*vol[8];. I# v* @  i$ h% i- N: V
                }1 C. n5 P' r3 J5 ~
                if( exsound_select & 0x04 ) {7 O  n2 b4 \( ?8 R0 ?
                        output += fds.Process( 0 )*vol[9];; g7 E/ k2 r3 u5 I: K: n
                }& E$ q# R1 S. L) ~, x% C6 n
                if( exsound_select & 0x08 ) {  N) t1 V& O6 B, H3 y% I$ b6 e
                        output += mmc5.Process( 0 )*vol[10];0 Q; X, B- H' x
                        output += mmc5.Process( 1 )*vol[11];
# T& i8 S: b1 l+ u1 y8 g8 U                        output += mmc5.Process( 2 )*vol[12];
. u, j0 B8 e6 }. s; I" R                }
! s- M4 ~: V: ?, |0 S& s/ w                if( exsound_select & 0x10 ) {; Q) n3 ~# M8 o! q
                        output += n106.Process( 0 )*vol[13];% Q6 F* }2 q) V3 o  O) K2 [
                        output += n106.Process( 1 )*vol[14];  h2 Y& \- X' |+ ]* }4 K! E
                        output += n106.Process( 2 )*vol[15];
8 o5 C7 e4 C/ |9 M                        output += n106.Process( 3 )*vol[16];
- `$ }: g! \1 K+ [4 F                        output += n106.Process( 4 )*vol[17];; \/ ~, m8 W* Y4 d) [+ y
                        output += n106.Process( 5 )*vol[18];: e0 w6 ]/ F2 u# D0 \
                        output += n106.Process( 6 )*vol[19];+ c3 v2 |' ^7 L' t& x7 ]
                        output += n106.Process( 7 )*vol[20];
  ?. \2 f8 G) ?1 R' l                }
2 b/ B" l  b: m1 T& P/ F1 u                if( exsound_select & 0x20 ) {4 j$ z" l1 O% w8 i2 `( G% E
                        fme7.Process( 3 );        // Envelope & Noise
2 `  o3 t9 e- X& |7 l  m                        output += fme7.Process( 0 )*vol[21];% F2 D4 l, u9 u. D; a! X4 X
                        output += fme7.Process( 1 )*vol[22];4 q* R8 G$ |1 ^; p7 @
                        output += fme7.Process( 2 )*vol[23];+ T2 A' d2 J  G( D
                }
% V( ]$ ~7 c3 B" \, X6 K! u% a. ]6 ?& i' c4 `  b, A
                output >>= 8;
/ v. y5 {6 p3 x' {' m
, U8 z! E3 ?( a4 ~                if( nFilterType == 1 ) {
# c8 I- u* J- t2 ~                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
- x3 s6 u+ r6 d, T% Y                        output = (lowpass_filter[0]+output)/2;: P1 l4 i/ v1 K7 t+ b
                        lowpass_filter[0] = output;
. d, `6 O( b) R" M8 n* g                } else if( nFilterType == 2 ) {
1 k- \) M8 J) I- O* h% _" C6 K                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1). R0 y3 B6 K+ n" V
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
  Z% w+ k( g8 e- o$ ]3 f4 s                        lowpass_filter[1] = lowpass_filter[0];
# K: ^, j' k5 Y% f. n                        lowpass_filter[0] = output;
9 }1 h; A' |1 ^4 Q                } else if( nFilterType == 3 ) {
8 {7 x, B$ E$ y- i' k( `7 k                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
! {7 m; W. m0 f8 B" e% c                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
0 F& N' h$ z5 n0 P                        lowpass_filter[2] = lowpass_filter[1];
' O% M, L3 F  h                        lowpass_filter[1] = lowpass_filter[0];
3 ]8 M; ]9 G4 H- W                        lowpass_filter[0] = output;
1 L0 D. m) s& w: s( B8 E                } else if( nFilterType == 4 ) {. C" v0 X3 K! J+ j
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), d; d) Q- r# `) p- x
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;6 t8 O& U. @; |# n
                        lowpass_filter[1] = lowpass_filter[0];
" W  a2 O! O5 A" y) T8 W                        lowpass_filter[0] = output;
  A+ B) `/ Y$ r                }
* V! E2 e. s2 j0 M- S7 Y3 z( L- Y1 Q. ]8 Y" I
#if        0
6 u4 j3 C. O" ^/ e7 I                // DC惉暘偺僇僢僩! x9 q; W" W, [- b$ i6 l8 N6 q
                {
5 B; }; D4 c5 ~. y- d$ c                static double ave = 0.0, max=0.0, min=0.0;
% c( C# J" R. L* |9 t8 g                double delta;
8 e0 N/ ]- I9 m" X2 D                delta = (max-min)/32768.0;7 h7 d* G, C( U1 Q# |4 o1 l9 N
                max -= delta;5 Q3 X; ?# _/ K; |! P/ S4 ?* N
                min += delta;% ~8 m% y& T: P. Q9 P
                if( output > max ) max = output;
- s* I6 m( e& l# r7 {- `0 p                if( output < min ) min = output;
9 M  K6 z# f/ M' S( S                ave -= ave/1024.0;
: y. s: }* X: z7 ?                ave += (max+min)/2048.0;
$ Q5 \( j% J0 Y9 R; z3 }  M% I+ p' g                output -= (INT)ave;8 B% }4 e" W) V; t3 \" |' [
                }7 y& [  X5 i9 D( N! w+ N! \
#endif, c: L; \) @6 n" u; s. u: s
#if        1
- Y# y8 M; D- c8 r4 q                // DC惉暘偺僇僢僩(HPF TEST)
  A1 D8 `& a3 J                {
# S3 ^1 O0 \+ n; O//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. j' [: `7 S- `; w- S0 q* d2 y, @
                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 G) c* A6 G% W5 b' ?& Q
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 _7 y7 K: S. k" y( A( n                static        double        tmp = 0.0;) x) C& V1 P7 `7 L" }% r5 ^% z, _1 v
                double        in, out;- G# f: [, @1 L7 @8 N

& e9 N) E: D9 |8 m& e' p                in = (double)output;+ n- [8 p8 @" |# S, R
                out = (in - tmp);
: l$ j$ y  y6 s# V                tmp = tmp + cutoff * out;/ C* u  e% T0 i+ y* ]# v6 H
4 l; n( |( J; y% g$ V; E
                output = (INT)out;
/ J! m: _2 A; U! Z# R                }
% J# t* a6 `  |4 o: Y# P2 r: l0 R#endif" p, ]& n2 @0 G* P" ]& B) x
#if        0
1 P$ z: Z' y1 m3 I" W6 a# _# F                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 ?; N& u& `: ?  }1 j# i* Z+ b0 Y
                {
! X& u0 X: G. y, F8 u7 d& L" p                INT        diff = abs(output-last_data);! E6 n# J& o  m% b
                if( diff > 0x4000 ) {
$ g' y5 o2 m" ?. y/ b* L8 I- H                        output /= 4;) g. S/ {; A1 R6 t: h5 L
                } else ( ]& Y) t# }' t: S& D$ X1 f! j$ \# p
                if( diff > 0x3000 ) {
% E5 o+ |7 M# a6 ]# S                        output /= 3;, N# G2 P" \+ E: D9 p
                } else: O. e# b4 O! Y
                if( diff > 0x2000 ) {
5 G' I& E; d* t" @, K, k                        output /= 2;& U4 H# S/ G) C* [
                }; D/ a" y7 q8 r: W# w
                last_data = output;: j- s6 ]( k9 U, @
                }: F( W6 u: Y" b; D2 V. f, K
#endif1 S; h+ d% r, e4 z
                // Limit
* ]7 `/ H* g* ]4 m                if( output > 0x7FFF ) {
0 g4 O3 N+ R0 m5 h                        output = 0x7FFF;/ {. p) P% S4 ~! X. T  H' y3 M2 \, D
                } else if( output < -0x8000 ) {
2 }0 e+ {1 U( V5 X. g6 G                        output = -0x8000;
6 v5 p  W+ ^* D8 F1 X8 I                }# _+ i! V' g& S" C; u

! Y8 I) Q% b% o: {/ e4 y                if( nBits != 8 ) {0 S  j- Y! h. m( k
                        *(SHORT*)lpBuffer = (SHORT)output;
" Q0 h5 U" z  b8 O                        lpBuffer += sizeof(SHORT);  O8 n" A# v2 Q: |3 Z; ]
                } else {7 O- U! [. m+ L
                        *lpBuffer++ = (output>>8)^0x80;3 X3 ]4 K. W# S3 C2 c
                }; f- Y% {! |. @8 Y6 a+ o6 |# P& }
+ t( ]7 |- C2 C2 p5 V
                if( nCcount < 0x0100 )
! n; J; }. u$ O$ x3 S                        pSoundBuf[nCcount++] = (SHORT)output;* g+ C6 @& }& e* z4 e( I
, x$ v* |9 h( G. o  i5 @. b0 ]
//                elapsedtime += cycle_rate;
1 @, h1 R8 h+ R4 S& U8 }$ P                elapsed_time += cycle_rate;' E; v( L4 z" Q/ _, P4 Y+ B
        }
' [+ d2 q4 j% C
5 ~; ]* i' G( m0 C6 r- J9 K6 v#if        15 t, f3 j1 o! ]& G9 j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {4 m$ _' l; f) ], N3 [3 H( F5 p
                elapsed_time = nes->cpu->GetTotalCycles();
$ o1 O% Z& S- N" U: V- i        }
9 z4 Y0 a. |9 j. E& G2 r& j        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: W; I8 C1 h& ~: n) l  i/ B                elapsed_time = nes->cpu->GetTotalCycles();
2 [  X% j" i# a$ Z* G        }
4 C' S5 P& x4 V) e#else/ ?; B8 a) u" G: z4 q
        elapsed_time = nes->cpu->GetTotalCycles();
% C" O) v% j7 E5 Q) |* Q2 L#endif
( V# \$ Z) K1 X6 }}4 m. q/ |0 ~# F" F0 L$ m* \) m6 l

/ h' I( }( E( w, h$ }// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)& b) k9 I! G, b: Z
INT        APU::GetChannelFrequency( INT no )$ `' W) I: I% J# N1 L1 |
{2 T; W# m7 C% ~5 z) w! p3 X
        if( !m_bMute[0] )
# s8 P; C2 u+ H9 t                return        0;& d& z0 @* }' e- l/ n1 ^
7 Q* p5 R# D/ L) k- ]% m' C6 C
        // Internal
( G$ Y& d" e7 t/ |' Q/ o6 m        if( no < 5 ) {2 F4 g: y0 ?5 T1 x  I8 n
                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ N2 |+ ]' E( A
        }4 x  o( \' z) B2 T
        // VRC6
* \& k! r  Z% D, {5 ~' g        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {# k& @3 ]2 G6 V9 P3 A' t. O% z' }
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;* I4 I+ k, p: m# O2 c2 A! Q
        }- `& c/ R; e) _1 D) X% ]
        // FDS
+ z; g6 x% W4 o; m+ z+ ?! W        if( (exsound_select & 0x04) && no == 0x300 ) {
) z  y( Z$ r6 t' f# E                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 b, [" I6 N( O6 z. s7 y: ?- a. A
        }
, I" ~; q) W7 M4 \" R/ ~9 q- ~& E+ i        // MMC5
$ ]* V0 P- g9 S        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
+ E/ w* f& P3 f2 ?  n% _: Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 J) D1 N* N; U4 R9 C
        }4 T2 h% Q+ O: J: s. r1 z
        // N106. R& w" g6 g6 |
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 Q3 R( M3 b2 S" n8 N/ X9 L
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;4 M  K( d* A4 K0 W
        }
4 G! W# @  j: S        // FME73 h% X5 j' q  y  M  @
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {2 x) R0 h$ \* o2 p; N; W3 c
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
; f# [4 ~) U3 N9 f        }
- [, ^1 p3 ]- R0 C- t5 {! J5 p& N        // VRC73 n. G# [2 n) j; W' `5 s
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {. y9 \( F/ T7 G! a5 e+ b) J- M% F
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
, Z: ~& D' q$ R9 ~* q. `        }
; x- J; P1 S& g6 e2 a) ]+ Q" s, u2 `        return        0;+ k/ E5 _! c7 ?  v. t- O; t
}7 {9 d2 g. Q( v  v
% X# d6 T" M" F7 _' m' H! H" ^' T2 I7 u
// State Save/Load
0 m! F# Z# }3 U: d7 d7 ovoid        APU::SaveState( LPBYTE p )
9 e$ w2 i, q: N* Q{
; e- z9 _0 E6 y! D  V2 ^% G9 r5 X: |#ifdef        _DEBUG0 X2 f1 O5 Y4 G9 l2 H
LPBYTE        pold = p;
# d' R+ r2 G: ~' z$ Y- i#endif
+ B9 L) f3 v1 L8 u( e$ M
) P  u) @& o5 g2 y6 @$ P        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
4 \( ^* o2 v1 o7 M        QueueFlush();. X. d; L) ]. Z4 r/ W  C+ o1 B
# k0 `. D4 i2 U; j! V# p! z  ?, ~
        internal.SaveState( p );
; }3 P9 Z! X1 t. _, A3 V3 x0 d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
) e' R$ D/ d+ Q9 C& y) s# r9 `" {7 v8 B
* G* Z: \" }0 G+ N, m; a! n; [4 \        // VRC6
  e4 w# }3 F. Z  s: O        if( exsound_select & 0x01 ) {
3 {9 @0 D" K  ^1 j# J7 ~8 h+ z                vrc6.SaveState( p );* D1 D# m. L, M  a- y* T9 S
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ _$ g6 O! q5 p6 ~# v; y
        }# M; \7 Y9 S2 w& ?. e2 M. P+ L
        // VRC7 (not support)
9 {. Q0 ]  t/ z" Y% f        if( exsound_select & 0x02 ) {
0 W8 x6 H8 i" A6 Q                vrc7.SaveState( p );% ]; @: X$ l) f6 |, r5 o
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- \" d9 ~0 ^, D& V8 I1 _
        }
; T" q0 p, A# k+ S6 h/ J" a        // FDS5 C  t. ~8 c( r1 u
        if( exsound_select & 0x04 ) {
; b  j9 T. g1 N3 K0 R                fds.SaveState( p );2 K& m% Z9 {3 M& ]1 D( t, y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
( H+ E$ m4 N/ `' C  z0 u( Y" p  Z3 n        }- ^& K2 S4 U1 N* Q+ w- o
        // MMC5
: B5 k4 n. H! \        if( exsound_select & 0x08 ) {
) \$ E$ r) g8 r                mmc5.SaveState( p );
4 Y2 g# ?, l. W/ }                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 \$ |; \, V# x3 ~" U: t
        }0 ~! X* g0 l0 V$ t7 `
        // N106* U. u# o2 O  D1 `
        if( exsound_select & 0x10 ) {' ?5 ^% b1 M, k. a" P% j
                n106.SaveState( p );8 _6 j2 e. a# d1 }( ^% C; X; z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding" f' w! Y8 v$ x! p) Q; [
        }
' M2 ~! S9 E- I8 m, W        // FME7
( D0 R* i( S3 d( x2 _) U        if( exsound_select & 0x20 ) {" q1 z/ N% b: }3 v* a1 n% a; w
                fme7.SaveState( p );
* c: g& m& B& e" z, R, @3 N                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) T5 J2 v& e% o. S; h$ T( y        }* u9 k+ M% U& Z8 N

3 O  H3 W, r) L5 O#ifdef        _DEBUG
. w; o2 @* y( r& U; o% M, U1 E) dDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );+ B  v, e7 o; H+ L0 P
#endif
$ w, i: m7 i6 P8 G3 G; D& x}
# w! E- O- P/ ?9 q3 F8 M) V/ l0 [% h  s3 d8 e. m+ c) C
void        APU::LoadState( LPBYTE p )
" J( H. u, U. C. U* b{
5 R2 {* ~2 r& ^) U% ^, I6 ?        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
0 H3 T; E5 P7 U* q        QueueClear();5 Y7 T' }/ d& k3 f) Y/ n7 m4 L
/ T& g/ h) i5 T; _4 v3 w
        internal.LoadState( p );' L/ z' J) P% W* T) M& h2 x
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ Z; p$ a' y& t5 O/ d3 _
/ x5 U  |: [5 _/ C5 G/ u+ A% Q. ]        // VRC6: b9 e5 S% x* G+ M1 W; X
        if( exsound_select & 0x01 ) {
8 E, j& ^: n3 h                vrc6.LoadState( p );
1 U$ d6 T5 A5 a9 d9 U- n6 Z                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! m! Z5 S0 i& x0 F4 w& \; r
        }) W2 D7 W, B: l' E
        // VRC7 (not support)
( R, p6 d  a8 y( p! y8 c5 |        if( exsound_select & 0x02 ) {
' D1 N. L8 L! h  O% {- E4 D7 u                vrc7.LoadState( p );% l. z$ l  x9 w7 o( }0 w
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ y( x  i: X  N" a) s/ x        }5 L# r+ m1 b+ \; J
        // FDS
% v: A4 q& s5 s+ ]  k        if( exsound_select & 0x04 ) {$ B! |  _/ j+ p5 y3 Z4 ^, X4 L
                fds.LoadState( p );2 z* ?, c0 v2 @. Y: \0 y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
. X. p$ P# h; U: N        }8 g' k/ n. k8 l6 Q7 J
        // MMC5* A$ d' r2 Z, ?3 v, P4 W
        if( exsound_select & 0x08 ) {' Q0 }4 B4 ^) `/ E$ f, l* t( {
                mmc5.LoadState( p );) M4 i( M1 S! c; R! W5 x: H
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( ]% ]! P4 r" }* S+ R5 z0 p: h        }
* }6 y9 ~* M1 J! v        // N106/ g" q) ]% @3 O
        if( exsound_select & 0x10 ) {( o2 ]" d0 ?1 t* q! y. \6 `% o' `4 Y7 w
                n106.LoadState( p );
, j9 F( H( K3 g" R2 G  t                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 M3 P/ E! C8 L* r& g
        }
- E" y8 X" q' C7 _( [# c! c        // FME7
4 \! Y6 d/ y2 M+ B. \        if( exsound_select & 0x20 ) {, ~, P1 ?8 `4 ^( l8 c! j1 U
                fme7.LoadState( p );: o: [2 U5 w1 W; Y& f
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( Y7 f0 P+ x' ~$ Y! g        }' \; q4 y! F$ ~5 O( w
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
* x( C8 p% C5 D& l+ [可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# t8 T8 d$ [7 h$ U( J* A0 F7 }
感激不尽~~
  q' c/ |5 K- ?2 x9 L! a
恩 我對模擬器不是很有研究,
! C7 [- d9 }6 S: v6 ^6 G) n$ c雖然要了解源碼內容,可能不是很困難,2 ]$ l9 c/ x" j( @
不過還是要花時間,個人目前蠻忙碌的。8 \3 Y/ X' w- Y0 i. d: R. A
8 o9 u$ X, a7 l
給你一個朋友的MSN,你可以跟他討論看看,
$ T* f9 a2 d9 Y4 d他本身是程式設計師,也對FC模擬器很有興趣。
5 e7 Y$ C* \  B8 t7 u( Z4 i( V* u) S' n9 }: |
MSN我就PM到你的信箱了。* [& W2 J+ T1 y5 G& d) S% c# b

5 o8 i8 X7 r( M$ q希望你能有所得。

该用户从未签到

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

签到天数: 80 天

[LV.6]常住居民II

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

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 ; H* f$ _7 X" F  c$ h( Z
呵…… 谢过团长大人~~

% f) ?$ @$ h4 J( F; r; N( d! q9 C$ B5 U6 W: X1 t' W* G  _# L/ g
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ! s6 B: K& `* b: U$ g
团长的朋友都是神,那团长就是神的boss。

; @/ l. z5 B. t/ ~; K" X哈 不敢當,我只是個平凡人,
2 m# x6 K, C) K0 S, U要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙0 c* G8 [3 T+ m, e
ZYH% f2 F& u; X' j9 j, f3 C  b
QQ:414734306
! i4 E" E+ u# w7 h# V& s- r6 tMail:zyh-01@126.com6 }( Y) s0 _# s, _
2 {. i; R. I8 E: E! u
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 / J# k5 i+ L; B/ t
再次对团长大人和悠悠哥的无私帮助表示感谢~~

5 O0 Q% O6 F+ B6 m% s: I* ~  \, j" r/ ]( s不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-9 01:57 , Processed in 1.106445 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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