EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。7 ~* y- n0 L  l3 H7 N! \! [
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* m* w. I! {. @2 u+ T! D8 [: e8 C% z2 H这里有相应的模拟器源码,就当送给大侠了~~5 C: Q' E4 v! A4 S- {+ j, v
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
7 U- M  B1 z9 Q4 Q# e" F/ g能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 r( q" p1 k" E2 G
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 Z8 ]/ A; g; @4 ]
这里有相应的模拟器源码,就当送给大侠 ...

& p% [7 i- m; a7 l2 U- {聲音部分(Audoi Process Unit = APU):
' Y) a$ ~4 g* A$ ?.\NES\APU.cpp7 O' E) z7 j; i( [
.\NES\APU.h- n* t2 d$ N  E) P# ^

6 l  I& M1 w4 q1 c! [
& B8 z4 |7 M; E" [/ h8 P9 W影像處理部份(Picture Processing Unit = PPU):
$ g7 G# Q4 X3 F! u.\NES\PPU.cpp! Z, V) }* L% r# B$ q
.\NES\PPU.h) t7 w1 `* g! [6 C1 E7 Y" G

& s: Z% ]+ s/ K' o2 U/ i- f9 \如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。; e6 w; F; n% M+ X5 D: o, E/ S
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 q6 R; P9 \8 z( P
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
- r3 j/ n- X( J0 Z1 m& w  L- ~//////////////////////////////////////////////////////////////////////////9 @0 X9 B$ y# T
//                                                                      //
$ S* R8 F0 _- R8 |( c  M9 S//      NES APU core                                                    //
9 g0 u( M, f: [! B2 Y( E5 a//                                                           Norix      //7 C$ ?* I3 }& D$ H; q& j
//                                               written     2002/06/27 //" w& Y+ T+ u% }
//                                               last modify ----/--/-- //
$ t* `2 [$ p1 q1 n8 T0 y//////////////////////////////////////////////////////////////////////////6 t/ N/ y3 h' o0 \
#include "DebugOut.h"
* V7 }' N5 }, [7 B- ]8 j0 `# ]$ F#include "App.h"" I! v1 v2 I! w, _" l0 n
#include "Config.h"
/ u( U6 G$ Z2 ?) c$ ~3 d
6 D/ D6 b* g& ~) v8 V#include "nes.h"
0 z* w+ K% r/ E/ [# A6 {9 N) \  R, B  p#include "mmu.h"6 Z2 s6 ^  w! n2 I
#include "cpu.h"
1 m: O5 W: }/ D; z# K#include "ppu.h"& f2 E4 w* M" Y3 W9 n" I. E0 V
#include "rom.h"
4 n. R4 T; s4 t+ J" b% k#include "apu.h"
4 c" y3 W2 n4 J  n. S! v/ t1 D5 x) ~* q3 E
// Volume adjust" `9 D# Y# q. w2 h
// Internal sounds" h9 B/ h, C4 o0 v- H$ f% G- f
#define        RECTANGLE_VOL        (0x0F0)/ q0 e" x$ p8 U' I- C+ \
#define        TRIANGLE_VOL        (0x130)1 a7 `! }0 j* Q& J* q, U/ I- M
#define        NOISE_VOL        (0x0C0)
, U6 W6 z+ V: D; @#define        DPCM_VOL        (0x0F0)
4 @) k% J% ^1 \* U// Extra sounds' {& b& l, f+ s: f9 d3 B
#define        VRC6_VOL        (0x0F0)
1 E# p% z1 ?: V4 v" A+ h# n& E0 i#define        VRC7_VOL        (0x130)
: z, q( M9 ~0 L) y#define        FDS_VOL                (0x0F0)  K1 ?' u. B7 {2 L& U
#define        MMC5_VOL        (0x0F0)0 P4 Y2 A+ K6 @8 G" k0 L2 w$ d
#define        N106_VOL        (0x088)$ G8 N: `( T/ O5 Z, M1 }# @1 {
#define        FME7_VOL        (0x130)( R& t3 E' o( }6 @9 E; D" h

8 K% u# S# k  O) f. UAPU::APU( NES* parent )8 C2 n! H. u$ a, m6 w# w3 p
{3 D; L4 ?- t1 l4 j# p
        exsound_select = 0;: ~# ]( a4 r  |/ X$ j

* t' ]  _# p3 J! I+ B4 }* ?9 i        nes = parent;
# `* ~8 t4 ]: u; `) @6 [        internal.SetParent( parent );5 g; Y9 n8 Q7 s4 n3 p0 a3 g  C
9 V$ |. V, ~4 Z' I) [6 {$ A' k
        last_data = last_diff = 0;  [8 r& Q% C$ l8 w  y

$ P! n/ H% E2 L, A1 y        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
- G% R$ v- W& v" X/ {, l9 r4 w" `6 }1 X0 K
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; o" H( q1 D; {; `  v        ZEROMEMORY( &queue, sizeof(queue) );) D! \% k4 r3 ~: S: g1 d- i6 O& m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );* L4 ~1 W. Q, s) a9 v% ]* j' f3 }

! V" R; J/ d1 j! b, C. k) r) O        for( INT i = 0; i < 16; i++ ) {; u) ?* k* |  A1 {/ [. c2 W, w) S
                m_bMute = TRUE;, G* e5 H. d; S
        }) R* u/ d: `+ C. Y9 ?
}  Z- k# G& D# Y6 S% ^7 C. B  a
6 U; T; F! ~) ]$ b  h- d
APU::~APU()7 I. `2 |( p! o
{
. Z+ |9 J) |, K! H3 D3 t( @4 T}. v" k/ Y+ c1 O# c9 y7 o$ o
+ y( ]2 J7 {6 r/ `0 O3 t
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )) e/ V5 I3 O7 A( m, _% _8 \- s. P7 J
{/ n! y- O5 s* X4 Y8 f8 r! a
        queue.data[queue.wrptr].time = writetime;& |1 h/ o1 [) X6 K/ I) p% [
        queue.data[queue.wrptr].addr = addr;
% D- z  w, S5 H        queue.data[queue.wrptr].data = data;
, K2 h$ K5 k/ l# x3 l5 A5 R        queue.wrptr++;, l1 B+ k- m- _# j0 j! w
        queue.wrptr&=QUEUE_LENGTH-1;% B  b5 t" N6 t9 E5 E2 |
        if( queue.wrptr == queue.rdptr ) {
; o4 Q8 c$ J5 w- O: Z+ |) G                DEBUGOUT( "queue overflow.\n" );
+ ]% I7 |: [) ~+ I0 W2 Y        }
2 Z3 b  j1 j( g  E0 @7 }}
, z: m* S( m( u, h8 ]! C7 q' R! E) g- X4 Y% t7 d8 g: y
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ z, T4 G1 T' m
{
4 c) r- }  c2 h4 e, `% f% [        if( queue.wrptr == queue.rdptr ) {
+ t! a* R( D# t                return        FALSE;: B2 H9 j3 S6 _! a9 v
        }% h- ]. \" Y( S0 H5 L! M+ X0 }
        if( queue.data[queue.rdptr].time <= writetime ) {
1 h  Z$ O/ }6 y0 N! ^: H- Z- o  r                ret = queue.data[queue.rdptr];
1 A9 P5 g7 G, B5 F3 T- q6 r                queue.rdptr++;
" }% _( D% H& V1 K: p5 `; l                queue.rdptr&=QUEUE_LENGTH-1;2 b2 ^' B: l- E2 _
                return        TRUE;
5 ], w! [8 @- L! F        }
  }3 c& i* ]* v( H0 P; w        return        FALSE;- M. {( t+ s; c9 T* X& L. z8 C
}
9 ?% u6 m6 g3 ^0 `# Q
8 ]1 M( f, b+ _. j$ [- `void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
+ u% i. H: V/ t) e1 W{
0 \2 R2 g3 W( y2 d8 ?2 g        exqueue.data[exqueue.wrptr].time = writetime;) k. W# u$ m+ b/ \
        exqueue.data[exqueue.wrptr].addr = addr;
6 e; d2 I/ s; O9 @, r2 Q        exqueue.data[exqueue.wrptr].data = data;) A# C' h0 W) u, l1 ?
        exqueue.wrptr++;1 O- X! w: Y8 \3 N" G6 D
        exqueue.wrptr&=QUEUE_LENGTH-1;
7 b) W4 W" k* u& n        if( exqueue.wrptr == exqueue.rdptr ) {
- X% }7 t4 P- ]+ K8 `/ q/ S( J# ^                DEBUGOUT( "exqueue overflow.\n" );, G' t* ]4 [8 ^& y& Y
        }
' j/ Y* [' P9 h$ U) I. |}  x6 @, l" y; \) T

2 o; _, n/ e$ P, Z: G- rBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
: k* w+ c) P4 t2 E% e2 U$ ?$ h{
+ M9 x+ S1 q: L* e0 x; r        if( exqueue.wrptr == exqueue.rdptr ) {$ H" h9 i# B' w1 Y) a
                return        FALSE;
% w4 L7 ]7 h; b" E" B        }; r# h" r( Z* A% k. H' F
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {9 l0 Z$ B, Z, u% q
                ret = exqueue.data[exqueue.rdptr];2 N7 `7 ^" R/ w
                exqueue.rdptr++;
; p1 {+ Q* N; e4 I( ]) j# W- r' [                exqueue.rdptr&=QUEUE_LENGTH-1;, e% z5 z7 K) m9 i
                return        TRUE;: q) g. e! Q, T( Z! p3 E! J
        }
$ ~8 Q5 G- a4 R# n$ }        return        FALSE;# k6 c! `( f3 B) U
}
! F6 }4 g, D7 B" y6 g
( r& T1 @7 m* N7 f& Mvoid        APU::QueueClear()6 z. ^5 \- e+ z' q" Z4 D
{
8 t3 h' l" O. v, _/ ^. b7 r% k        ZEROMEMORY( &queue, sizeof(queue) );
( T- F8 Q* H3 b3 i! o  _5 v2 K        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 z* i" Q9 Z. g9 q  x}
" H6 m# E4 Q0 Z  \( ^8 _  @
0 d4 I$ Z6 f3 x% j! y2 t4 n& z6 {! Evoid        APU::QueueFlush()- Z0 K3 E$ k5 Z' w3 m1 L
{- G: J5 U5 K) K. i- V2 W4 U* I
        while( queue.wrptr != queue.rdptr ) {
6 y# A4 S' `+ P. t                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
" D7 V' I) q! l% U& `6 K                queue.rdptr++;
! F8 E( \9 X, T. l                queue.rdptr&=QUEUE_LENGTH-1;8 l" k' u/ J9 g* E
        }* r( C+ w7 a3 T* ~9 D' G2 |

8 F+ {$ I, k3 V/ h: \+ [# N7 r        while( exqueue.wrptr != exqueue.rdptr ) {
3 y0 @8 H2 {6 B# Y                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
- w1 c7 P9 O4 I+ O9 N2 _+ K                exqueue.rdptr++;4 j2 D: R9 t6 n3 q8 i( k9 I9 ?
                exqueue.rdptr&=QUEUE_LENGTH-1;/ Q) L2 c/ e9 q; o* |! S
        }2 j5 `9 D. |. t7 G0 t# ~: V
}
0 Q8 q8 u, i, o, C; R- \) ~) F% B. o0 m9 ~! ~% l4 V# ]: ?8 i' H- l; H2 _
void        APU::SoundSetup()
; k) P4 v3 ?% r  }/ s{
7 P' J. j% S. Q$ y# }3 E        FLOAT        fClock = nes->nescfg->CpuClock;
0 w5 K) b8 n( N0 D        INT        nRate = (INT)Config.sound.nRate;4 G) m' g# x/ w4 C0 ^
        internal.Setup( fClock, nRate );; N3 a1 |/ B8 p6 q( T3 K
        vrc6.Setup( fClock, nRate );5 f1 o5 a/ E) E- c4 g  C8 L
        vrc7.Setup( fClock, nRate );
7 [* S6 p. z# U: @& V8 O# X        mmc5.Setup( fClock, nRate );
0 M+ Q* _2 s2 B) X: x        fds.Setup ( fClock, nRate );0 L0 B$ J$ I- _) `0 L( V2 N6 k' Z
        n106.Setup( fClock, nRate );
, }( q9 A9 [+ v7 K/ F. O        fme7.Setup( fClock, nRate );+ K6 ~% I- o6 k
}
/ Q# }7 j/ ^) k) l3 t* p
3 Y/ s5 U' L& A, x9 G/ e8 kvoid        APU::Reset()
! v6 h5 h$ K) ]# i' e. L6 q{4 L3 H/ W. C( B5 k. ]
        ZEROMEMORY( &queue, sizeof(queue) );, T0 C; s- ~4 @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 i' `+ y, q# o6 Q* ]5 ]

' p7 R  }7 U6 x4 H0 T/ S        elapsed_time = 0;
3 x' g1 A, h- t: H; F5 E8 R8 K$ {; L9 @) V+ \/ b' l
        FLOAT        fClock = nes->nescfg->CpuClock;/ b# W. w2 b6 Q# N
        INT        nRate = (INT)Config.sound.nRate;
, x7 Z" v3 L' [1 G$ v        internal.Reset( fClock, nRate );
7 a5 o4 z8 A1 R! u- I7 s        vrc6.Reset( fClock, nRate );
0 W5 s3 `# U1 W. e7 Q% y7 a0 c        vrc7.Reset( fClock, nRate );3 E! J5 S0 u, j! ?$ Y
        mmc5.Reset( fClock, nRate );
; R  G0 v) y, G, [& s        fds.Reset ( fClock, nRate );4 L1 J: \. L) U7 [, j
        n106.Reset( fClock, nRate );$ Q7 }- X6 K6 k7 y# Z1 R- i6 k
        fme7.Reset( fClock, nRate );# f% J( n8 u; y

8 l7 d. m) ?  A3 ?) {  o, \        SoundSetup();
. Z2 @1 t& ?' M6 |$ o9 z}
( W- V. J) |5 l  p  u& H
8 k& M! d7 n; @void        APU::SelectExSound( BYTE data )
: P8 ?' C9 Q2 p9 V+ S! t{& [1 g6 K1 `& T4 R! o/ L
        exsound_select = data;
' |; g" q" A7 w$ I6 C}
& `& i- d) l, o3 r8 w! @- S6 V; d4 A+ L* d" F) T
BYTE        APU::Read( WORD addr )2 s% K6 s  ?5 o
{
& g; B  W6 z" k# d8 d! g0 l" g- B        return        internal.SyncRead( addr );
7 u! Y' B' h- d1 y}; c8 N! G1 o0 r( O1 c
" Z- I: t0 f4 J( D
void        APU::Write( WORD addr, BYTE data )2 z8 C+ e) t: e; X% _) A" p0 W7 T
{3 g  W- M& L! E; Q. x6 w0 u
        // $4018偼VirtuaNES屌桳億乕僩
, _( o2 P) e! ^: ~1 [        if( addr >= 0x4000 && addr <= 0x401F ) {# G7 @, ~  g0 w6 V
                internal.SyncWrite( addr, data );
$ i" P! r1 b) i. y* E# L  S                SetQueue( nes->cpu->GetTotalCycles(), addr, data );) I- f3 K. C4 c# S8 o
        }
* U* }! W$ o" O7 i. T: B* _$ }7 q}
. s' z, z7 C1 I8 d. v- j4 o+ c2 \, i/ |2 F* e8 T9 |% F, \1 r/ [- T# T
BYTE        APU::ExRead( WORD addr )
# B: v) e# _' v2 I: A4 _. X! s{
' t0 m, @* C& U2 e! hBYTE        data = 0;
' ?1 [. I) \9 P+ G3 {3 j% p9 M
6 H  Q* m$ L4 `" v        if( exsound_select & 0x10 ) {
' R  R1 `$ O$ B9 k, {5 F                if( addr == 0x4800 ) {
6 r6 I- V# [! ?- L0 Z0 e                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: a' V4 Q' _* O% U1 e" b7 m3 ~
                }
& v4 c1 Y/ C4 N' o% b6 {- E0 b        }
; V! A! E7 B0 [; u. t) Y        if( exsound_select & 0x04 ) {
3 ^9 ]3 f7 T8 {7 ~# m                if( addr >= 0x4040 && addr < 0x4100 ) {2 U" u, x( G1 k' U  e# f6 M7 q2 G. Z
                        data = fds.SyncRead( addr );+ `$ k5 ]% c( ], ~3 c* z
                }+ @, p  x; ?( {) K! h1 S
        }
' `7 c6 B6 [' P! x: ^* g        if( exsound_select & 0x08 ) {9 d6 g; X1 @' Z# b
                if( addr >= 0x5000 && addr <= 0x5015 ) {  ]4 u6 s- L" e: p; [0 @2 @0 L
                        data = mmc5.SyncRead( addr );
+ R$ z. E: J  z2 E* }0 ~; s                }$ L% I! Z6 Y' v, Q
        }# \) C$ _1 |/ z( R

* f, R" v0 \2 ~  F        return        data;1 P2 W: ~, J) {/ s  B) f# G* A
}
/ C5 Z3 D" P# c# ~
! a2 C4 k9 I! V6 u  vvoid        APU::ExWrite( WORD addr, BYTE data )
2 L$ A9 Y5 [( d) a{4 @: r1 q+ |% P: Q& i+ k
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
3 F% h4 d6 v. k# ]8 P. X; H5 S; k6 f# E7 q
        if( exsound_select & 0x04 ) {
# R; C9 s) G% |% m4 e2 N                if( addr >= 0x4040 && addr < 0x4100 ) {
) J* Y9 m% k  G6 P                        fds.SyncWrite( addr, data );4 B% m5 H5 u% T/ Q
                }
& p4 Q& c/ {5 I/ C$ h        }9 [9 n$ N% V  e+ [5 T5 F
8 F$ N4 F; O" W9 e( I% q
        if( exsound_select & 0x08 ) {/ {1 ^% ~6 `9 z9 t- ]( C$ n3 X
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ l% Z% W: p" V                        mmc5.SyncWrite( addr, data );
% R7 M, c% _; [4 }( |) z                }
9 w9 M$ P4 ~- o9 z4 ?        }8 l/ ?' _( h: `. [  p# |
}
. l+ `( H4 ?7 B) Z  A# L& ~8 O$ j" r7 d
void        APU::Sync()
0 @' s; X% @7 j8 T: k{
+ G9 ~' F  h7 ~9 B1 R, f, n}
6 c* T0 R$ ^9 F7 z4 ^. ^6 E' C' o1 s) z
void        APU::SyncDPCM( INT cycles )5 l' X8 |4 {- U& ~
{- Y+ P0 h7 k  v  o" l9 g" K' ~! h
        internal.Sync( cycles );1 P! ^& O: _* T2 u! B  B5 H

9 N; V- {- q3 Q3 R        if( exsound_select & 0x04 ) {# H- x, {' w$ R) ?& L
                fds.Sync( cycles );# I% b% ^0 m% z1 S
        }
/ v( F' ]# c  Y7 G! c5 Z        if( exsound_select & 0x08 ) {6 C7 Q6 E# E* e$ m, b  s. q& l
                mmc5.Sync( cycles );9 \& |8 ~5 S7 c0 c
        }- v2 a- C# q. E" X5 V  F  A
}
$ h. T+ c& M0 c3 {7 `+ N9 v$ M' I4 t. A4 a4 [
void        APU::WriteProcess( WORD addr, BYTE data )
/ I  E/ J% a- J8 x' K7 w$ G6 h{! K( u: ^2 d, \, p+ b
        // $4018偼VirtuaNES屌桳億乕僩# O/ a5 f+ X: O+ H& h
        if( addr >= 0x4000 && addr <= 0x401F ) {
. d3 {( y6 I* A- D& g                internal.Write( addr, data );
. {) P. I! j0 y# ^; ?        }9 A5 c* V& z; [0 Z
}
9 D! t" j/ m1 Q6 \& R6 }& i/ B# `. R
void        APU::WriteExProcess( WORD addr, BYTE data )
. F9 n7 Q1 \- C. ?# J. g; k{
/ y$ I5 |, ?8 f8 Y/ ]        if( exsound_select & 0x01 ) {: N! w# u: t3 I1 v% v
                vrc6.Write( addr, data );
9 x, V$ M' J* B9 j7 c9 N        }
+ b# S0 e( k( ~. W        if( exsound_select & 0x02 ) {
5 ]& A' v& u  k% K# \3 A8 H0 D+ }3 {! \                vrc7.Write( addr, data );
5 M( q. ]7 I3 U        }% n$ S0 x% T* ?: J9 l* C
        if( exsound_select & 0x04 ) {# M2 k2 [0 @3 k8 t
                fds.Write( addr, data );4 |% f: d0 l$ }+ i8 e6 g4 |6 O
        }  p* e6 x; ?0 i, g2 X
        if( exsound_select & 0x08 ) {
6 c; |" v; L1 J2 N, X                mmc5.Write( addr, data );
% k/ W: Y% O) L* B- T        }0 S" `( m6 V5 P- l7 E9 `
        if( exsound_select & 0x10 ) {; `$ _1 _- f, ^* {
                if( addr == 0x0000 ) {# j" ^' @$ V4 g  G' ]4 N
                        BYTE        dummy = n106.Read( addr );
+ p( \9 g4 s& s- X8 W* B- X) b                } else {! U/ h& w. D7 O9 q! j0 u
                        n106.Write( addr, data );% k% Y( s9 j7 a' b
                }
5 h. x4 q* `% }9 A7 I! \. z        }
- ]& y2 W6 ?4 j  u! C( {3 T        if( exsound_select & 0x20 ) {* \. U# [$ e4 Z9 R% b! B
                fme7.Write( addr, data );
  H; K  D7 q; [6 S$ X        }: C! _8 S! Y" h+ p. [" w( a7 s
}% q* ]( q5 C$ M; Z: c% c/ q

% Q, \# W3 f; v$ evoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
, O* n, {9 R/ z5 Y{4 B1 @5 ]) [+ e2 {$ f
INT        nBits = Config.sound.nBits;
1 J% }8 s: c) P6 o. o( ?( _1 A  cDWORD        dwLength = dwSize / (nBits/8);
/ R- \; @9 p' U4 k7 F" b: x7 wINT        output;
% H& z  C. B/ e8 i" n- eQUEUEDATA q;
' d4 u4 m9 @# g% g  ?9 xDWORD        writetime;' ?5 F; x4 x) V
( P: T) [& r2 n( B& i9 J4 k
LPSHORT        pSoundBuf = m_SoundBuffer;
! y" W* P  L$ g; W6 JINT        nCcount = 0;
8 u/ H' n7 c4 ]/ N% s: N3 P
& o' K" S+ a5 {9 H, }INT        nFilterType = Config.sound.nFilterType;
5 @: H1 h. d- Z* b' H
/ {0 u( @6 Z0 I) l        if( !Config.sound.bEnable ) {
  p0 Z, n7 @* v5 R                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
9 `, Z* G1 C' V+ \! t5 l                return;. x0 j8 m6 _* g$ @7 _
        }8 n& D3 q0 P+ @9 f/ I

  s* t2 q( n3 S  t3 L6 O7 |        // Volume setup
/ S) a1 y! w& x- R% @        //  0:Master* a- e& [/ g  A7 P
        //  1:Rectangle 1) j" l5 W3 ]. f
        //  2:Rectangle 2
+ _( G# L: h) a' ~        //  3:Triangle
9 m# ?( E/ i/ O        //  4:Noise3 X# O) v  f+ P9 X! l+ x" [+ L
        //  5:DPCM
! q- @0 M5 D3 p2 t3 f        //  6:VRC6
/ V6 s+ T; ^+ ~        //  7:VRC7+ N4 [  d6 Z+ {
        //  8:FDS+ s0 f8 n* O: B# S
        //  9:MMC53 J. U8 L/ y/ O0 Q. L) Q7 a- t
        // 10:N106
" S: F8 {, I) t2 w% o& t+ l9 C        // 11:FME7
. P& j6 _; ]4 w3 h- e. I: i        INT        vol[24];0 M7 ~6 H3 f, ], g3 `
        BOOL*        bMute = m_bMute;
( M% R% B7 A( R  U. f8 h7 U: V        SHORT*        nVolume = Config.sound.nVolume;
/ `6 T- B6 e+ N, t# W; r) d& n6 j- a2 S7 s0 L/ I6 o: ~8 j
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;* F+ c7 X) U( I0 A5 U% i

6 N6 O& ]$ b. \2 F' Z        // Internal* T# m/ Y- l' w# p
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
) i( E$ G( |0 L. F8 j        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;/ `$ N6 U3 G0 o2 w4 D0 A' }8 _, a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
& F* |- |9 {/ ?0 d* ~' v! G        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;/ N& f( n9 R: `6 f9 M1 n
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. c( p+ Y( W: ?4 ]( s) W, f6 y2 t
        // VRC6( Q* C$ Z4 N2 @. ^& i+ ]" O
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* |# A7 z+ p# K& g
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 y! s0 U& t4 ]0 D& \6 Y
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
! v! |3 s8 `2 U& G, E( W% @9 L! v- R  p9 I1 ~
        // VRC70 R3 d) R9 ]$ s
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;9 W, }$ X6 c( T: W. y: B  \8 N

* l1 f  u2 i' y, M9 v: N6 S        // FDS8 P, e, e. a( D2 h. n5 I: H+ F
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
0 o% w& Q- \3 x0 `, N1 e
# d4 D- G+ d! Q4 B- H% y0 {/ A8 b        // MMC5
' A5 {0 q5 G5 F! a. D, ?; T        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 r. ~9 a0 b  N/ N1 I# c9 T
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' E# [: B3 V( w3 {( b! ?
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# p8 i6 p! d- b! j0 b* ]" f$ D4 I2 j" ]& X8 x3 b" ~, T
        // N106
: M5 |8 J9 E4 L( {        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: _- L0 g, k3 v' i, A        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 o" |8 q4 d5 R- N
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& f6 ^$ Q0 m0 @0 V& W, X        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ N! e" o/ o' r: S1 f0 t        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ V3 t1 _. ?# I$ u
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ S1 x  O$ f' O, G0 R
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) x2 ?0 T4 ~4 m2 j& o$ Y) V0 _        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 c% u3 b6 _9 O; H2 x  }( r
$ c- ^, {' h* i  r' X3 S        // FME7
8 G/ h2 N. z' |7 i2 t" u$ B; j        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: M4 E- w, c4 H* p4 t; D5 p' i! u8 y        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 W# o0 p& E6 b% B! j' a# _        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 U$ w& V  p3 z' X
0 I1 z5 i% w3 L) {' ]
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
/ ]5 X1 o1 b& c  x+ P) ?        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
) T7 a( b1 q, `) x) u1 }! e  P6 p
' w4 y: N# M9 j* f. S        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟% S/ z* L$ E; r& y) A2 |/ y
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {( `% l. e- x( |0 ^) Y, o
                QueueFlush();
7 W8 g. B' {) d6 S% V" s2 N        }
6 E7 i6 T. b; U& p$ w. Y
0 [8 n$ G3 h7 f8 F1 G0 z        while( dwLength-- ) {
9 K! O; L# ?: g1 I1 ^8 N                writetime = (DWORD)elapsed_time;, [+ e- ]. `& `4 ?4 x- Z% |* G* O
' h9 t7 R6 ?* K: C+ s
                while( GetQueue( writetime, q ) ) {
7 {$ C8 d( e: u5 q8 ~9 U                        WriteProcess( q.addr, q.data );
& X7 F  ?% e1 A6 c3 U) @  n                }" R- C# \4 }- [  d; J: T

  w9 s, M. A/ O                while( GetExQueue( writetime, q ) ) {
. h( G/ \$ o4 W$ u- f! a                        WriteExProcess( q.addr, q.data );
, B/ {& d  C. x( R                }6 `" F. P3 Q2 B) q' _3 i% l' T+ s
' P( g  l* J& m: _
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
3 a" H: O, G6 ], C                output = 0;
6 C/ j' n' g' g                output += internal.Process( 0 )*vol[0];: g5 S* i! d2 j6 M* b
                output += internal.Process( 1 )*vol[1];
5 }/ T( `" H7 H$ D                output += internal.Process( 2 )*vol[2];0 ^0 d' ^/ v( q
                output += internal.Process( 3 )*vol[3];8 B" ]7 T! ?8 X( z
                output += internal.Process( 4 )*vol[4];: \$ b2 l! t# [5 [0 f/ q/ e% o

" d1 y; h+ M8 o& l8 A. Z" g# X                if( exsound_select & 0x01 ) {# O5 R- Z3 G$ u2 R3 g; e
                        output += vrc6.Process( 0 )*vol[5];
8 {. R6 P0 w* I5 [- f; B' o5 p% s                        output += vrc6.Process( 1 )*vol[6];
, _4 _3 O( t6 E5 ?0 c                        output += vrc6.Process( 2 )*vol[7];
! i! g7 n( u# t8 O' A                }" P* C) o  O3 W( p
                if( exsound_select & 0x02 ) {7 Q3 X2 i, j* ?0 V6 r
                        output += vrc7.Process( 0 )*vol[8];
0 C" E- C( v( n6 V1 P4 @* T7 w3 p                }  p$ \& _6 [7 Y. R1 C3 g4 z7 H' D
                if( exsound_select & 0x04 ) {# e; `3 Y, M0 H6 V' H
                        output += fds.Process( 0 )*vol[9];
0 a! w2 D" O- Y: f' J6 u                }  F; _7 m: R! a" `/ c! K
                if( exsound_select & 0x08 ) {- R$ A# p1 C0 m- s3 F9 H) \: K
                        output += mmc5.Process( 0 )*vol[10];
+ X0 u' j% n! I' T                        output += mmc5.Process( 1 )*vol[11];( A+ g" A' L! ]. h
                        output += mmc5.Process( 2 )*vol[12];: r7 ]2 e9 R! e2 B" _3 m  n# [
                }
. S) {+ S5 t& U& T+ U7 E* z                if( exsound_select & 0x10 ) {
; n4 h! \2 A; E5 y" ~% m, l# C4 O                        output += n106.Process( 0 )*vol[13];4 a( l' o1 s9 [# K( r
                        output += n106.Process( 1 )*vol[14];
0 I% G# Z% `9 |& E: j                        output += n106.Process( 2 )*vol[15];
! H8 [* J' h# z: N5 b5 P# [  S& u                        output += n106.Process( 3 )*vol[16];
! I. E* y2 L! ^* V- n# P/ E0 Q5 k                        output += n106.Process( 4 )*vol[17];
5 }" ]$ k8 |' H                        output += n106.Process( 5 )*vol[18];
( [% C2 X) A6 f4 v" a  `                        output += n106.Process( 6 )*vol[19];8 O/ W3 m9 u4 y4 n1 D! k" O3 J
                        output += n106.Process( 7 )*vol[20];% H5 V! R% K- u7 C1 w
                }# c0 J9 n. G! S6 f' g/ }
                if( exsound_select & 0x20 ) {  n( f- @2 ^* a' V+ ~) p
                        fme7.Process( 3 );        // Envelope & Noise9 e: r( u9 N9 Z1 V  B. B2 I
                        output += fme7.Process( 0 )*vol[21];; \" H: z6 O  `* k
                        output += fme7.Process( 1 )*vol[22];
$ R6 T( K. W8 {. ^6 E+ m( i1 n% n, N+ k                        output += fme7.Process( 2 )*vol[23];
5 L9 y  Y1 Q* r  c                }5 C5 C$ f/ C, v9 u& E  G8 P% r

3 c! P" n% }! E) o: h                output >>= 8;
7 W! |+ Z2 k0 k$ q* j
# F3 Y' X. S- B: ^( f" K! @                if( nFilterType == 1 ) {
, e0 Q* Q( _$ Y. P                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)9 [, v2 b3 u; D2 G- [) h
                        output = (lowpass_filter[0]+output)/2;; b' B1 T1 z) _' P8 P% w  p
                        lowpass_filter[0] = output;
) d1 a6 [' W* I7 v; s- A                } else if( nFilterType == 2 ) {9 Y+ I" m: w/ N  K1 G0 e, W
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)+ u% M/ y( z5 N
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
1 W7 w7 N) q% r% G; d                        lowpass_filter[1] = lowpass_filter[0];
0 s) r1 j: ?" B8 Q  {, p                        lowpass_filter[0] = output;0 Y3 _: G$ e7 L- A* V& K
                } else if( nFilterType == 3 ) {7 l) X8 f$ c) j
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 i( o$ n. w, Z" H/ N* Y                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
" F% K5 Q& S0 e' Y( T) j1 B+ R                        lowpass_filter[2] = lowpass_filter[1];
9 X+ s0 y3 J% Y1 P                        lowpass_filter[1] = lowpass_filter[0];
) M5 y5 c) a8 }: p  s7 i9 z6 P$ ?                        lowpass_filter[0] = output;
! d. Q6 g" L: d; x9 t# e' P  N                } else if( nFilterType == 4 ) {9 F) N* }- W1 W- A
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)3 C9 k4 \" T  O
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;$ j, Z/ R" \0 r2 m9 q
                        lowpass_filter[1] = lowpass_filter[0];# `0 x$ ~& ~# ^* A7 Y2 e
                        lowpass_filter[0] = output;6 ~' H' S5 [9 ^9 i6 j
                }0 O5 b! n3 k  J& H8 m/ E( A9 p

1 i4 @0 U9 p$ W) ~& ~7 \0 h: W#if        0: U# \! Q- r- V+ B
                // DC惉暘偺僇僢僩5 Y; c  P$ w8 X7 F  j) j3 A
                {  K% i7 `' f& m* e6 l) V+ s
                static double ave = 0.0, max=0.0, min=0.0;
9 t3 S& w0 X2 ~3 L                double delta;
2 S! R  o" w  K$ I4 p. e                delta = (max-min)/32768.0;7 ~2 w0 S( p# @: R
                max -= delta;
$ `1 h! s. V7 Y2 z3 o; ^) W                min += delta;8 [% J/ T( C" U4 ~
                if( output > max ) max = output;* ^7 b, Y/ e. H" `8 x
                if( output < min ) min = output;
6 }" h) k4 ~) x; s                ave -= ave/1024.0;
* D& Y$ L. U% h$ T' |* c                ave += (max+min)/2048.0;3 T% [; ]! F4 Y, V
                output -= (INT)ave;
4 `; l' h, M& `4 ]1 k& o! a                }7 q+ H, I  k# m0 h2 D# [
#endif& y! q4 Z0 E( a. K' r
#if        1
$ _6 E( G1 U$ f6 J! Q& _7 x) ]# M                // DC惉暘偺僇僢僩(HPF TEST)
1 t6 r; {( o  O( R! U  }2 H6 K                {
# v/ d$ E% `+ h# Q  y6 _//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( Y2 W9 F7 h9 w0 Q3 q5 B$ K" a6 `' t
                static        double        cutofftemp = (2.0*3.141592653579*40.0);6 W9 a' R3 o4 t
                double        cutoff = cutofftemp/(double)Config.sound.nRate;4 X' M8 ~  \- p/ E
                static        double        tmp = 0.0;" s+ [" G0 Q/ r6 ?/ A  w! u. a
                double        in, out;
  \! V7 G2 C, u1 A7 ], K- q' H# f: `
3 j* |( r: e$ {                in = (double)output;7 O' x' M, z" g( D# `0 f1 x/ O
                out = (in - tmp);
9 ^# {1 b; x3 A; c! `3 W' Z                tmp = tmp + cutoff * out;+ i" P6 U$ X; E% A  g
3 W4 ?! f' V- q' u2 r2 e
                output = (INT)out;
( p( ^! m3 @* Q$ f, c0 M; h# ?3 v                }
) Y2 j& C+ J1 @. I7 n, q( c#endif, `3 u7 K5 @6 |$ E1 r
#if        0
5 A# r: V4 j, w) i8 C- ^                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
2 \! f( T1 a& K% f# I                {4 t3 v; e5 U  e7 Q
                INT        diff = abs(output-last_data);
5 u' v) G/ q7 v+ ^" Z9 v' ?                if( diff > 0x4000 ) {
. |9 G! f! s* H$ F+ }/ q                        output /= 4;
/ z; H! x5 D* y# x" c$ w/ E( I7 v                } else 5 x# w! p2 T3 [: p9 F
                if( diff > 0x3000 ) {
* O; c5 Z! C/ p; L+ P  R                        output /= 3;% F* G+ S) K' L' q
                } else: @2 h/ ~2 e( O. S
                if( diff > 0x2000 ) {& F5 H+ F6 A9 B7 k6 V9 `/ `# C* T
                        output /= 2;
" z# {  ^' O# V$ B7 |                }
. V8 o$ o1 L! g4 R4 k                last_data = output;6 i# S; v! R! |
                }
4 m% @5 {; ]5 K4 a: r! }#endif
: K# x5 {1 V3 r( \* W& Z9 B5 E7 s                // Limit
8 J, ^* x# J8 @: Q/ X- q# n                if( output > 0x7FFF ) {1 T/ n/ D7 W; y3 Q% C3 g: o
                        output = 0x7FFF;4 j8 D; T( V- {$ W( ^2 R
                } else if( output < -0x8000 ) {
; u. s) v% y. l" W* J                        output = -0x8000;! }/ }3 _* y' W; L# {6 D
                }
) O. o( v' T1 w7 }- u( O' Q7 W4 J- `# ^" L- y
                if( nBits != 8 ) {
7 F0 U! e" [! A1 i. n9 l                        *(SHORT*)lpBuffer = (SHORT)output;
& f8 H# B# `$ e7 K                        lpBuffer += sizeof(SHORT);
% r- [2 L4 Q3 B# Z% J                } else {
/ w7 j* {, h8 a# m6 H" @" d9 |                        *lpBuffer++ = (output>>8)^0x80;0 \4 N5 y! l+ G* c3 l
                }
% _3 ?  I; @0 W7 `# W0 b( y4 _5 O& U( I- z1 V
                if( nCcount < 0x0100 )
8 k: u  h7 f9 I; F$ ?) r% W" O                        pSoundBuf[nCcount++] = (SHORT)output;
( ?5 ]5 `! z) A# M% O4 ?0 I0 Q* o4 C9 Y6 y2 I0 s
//                elapsedtime += cycle_rate;
8 V6 p% z! C) P% ?! L8 r                elapsed_time += cycle_rate;
& R* h' k7 p+ I4 I) q        }0 W7 M9 U3 Y5 t" L3 r
$ q9 d& f0 ]' u) a) F
#if        1
! T4 b' W1 V: a9 ~2 }9 U        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {9 u$ V: o' J% H  R& \# o" V
                elapsed_time = nes->cpu->GetTotalCycles();5 p+ r. t6 d6 f
        }
7 h1 ~: d8 ~/ Y! X/ G! E. N        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
" X* c7 Y9 {1 h9 o' ~% f" j' K7 M                elapsed_time = nes->cpu->GetTotalCycles();
% Y9 j% W/ r5 L$ }- `$ ]- e        }
7 d5 v; x; @* n0 {7 y5 h0 g#else
$ a6 B9 h, u$ a  `4 i        elapsed_time = nes->cpu->GetTotalCycles();+ P: E, u! x! d5 {4 K+ ?
#endif
7 V" V; G3 y$ H# k  y1 C$ y}& \" }! F8 @5 L9 \$ A6 m
. C$ _4 j- m5 o8 F( p+ @8 h
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
( c5 U5 N) ^3 B. c- sINT        APU::GetChannelFrequency( INT no )
) L( k1 i7 I3 D3 Y{  O, g- K3 o6 n5 g$ l0 V( V
        if( !m_bMute[0] )
# w  x' H" b1 \6 E) O                return        0;
: }7 r; J" o9 a" I4 F8 C
. p2 \& I7 o$ B6 I$ k0 b; [2 o        // Internal& g, ?: h  E, `# d3 ^( Y" y
        if( no < 5 ) {" G6 Z, y3 B/ X+ p8 c- V
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, }1 c0 p7 C( Z* k* W9 y- W0 m+ m* c        }
* j7 ^  Z: D& i        // VRC63 S; y$ U: ~+ o& P# ?
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
, |" c/ P- l- V# K: B                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
% W% E; X$ J7 k        }: L  A! v, x5 f; E
        // FDS9 J; {6 }9 _- K
        if( (exsound_select & 0x04) && no == 0x300 ) {5 b1 f+ B% H/ {: Y" a
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
" u. `8 ~0 v% M; f0 [* T        }
; k* U9 ]8 q2 N7 m" M) Z        // MMC5) s5 r( e8 W4 s& B
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
0 |) T! ?' `. T6 \( ]) W                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;8 {& J2 o# F8 |  Q9 ]+ P1 X, h
        }# o+ `7 Y3 T9 l7 v) E2 ^. }" d
        // N106
" f2 S- K# V5 I% g& l, G% W        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
) n; G( l9 y- v, a                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
1 S. c( R5 Y) a2 o        }; G! R% e1 Z: B; y
        // FME7
4 v7 X9 K3 U) _( |1 Q+ a' h        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {$ d, c6 k: {( d" T
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;7 c( v! M3 E' e1 L" R
        }
  V- O& F, P1 |1 l        // VRC7
/ n9 S; A' m' u* P  Z        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
; I  l: h7 c7 R# ~, E; D6 ~                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
4 N, p! l$ r9 X7 b- n        }6 e" w) {. a7 F0 A, c- c' H
        return        0;, a7 |3 K+ n0 O/ n: p
}
8 Z1 r" p2 e/ o6 r, L8 {4 a6 W5 r( q1 |2 a- ~
// State Save/Load1 p9 w' O4 m7 [! s2 v2 \
void        APU::SaveState( LPBYTE p )
0 Z! l# c7 P( X7 N$ S1 U) Q0 W/ r{
, ]7 t' o0 f/ X; J# Y#ifdef        _DEBUG* ]# o# Z2 s! A/ `& w6 _# |
LPBYTE        pold = p;9 C7 a/ f( q  o0 i% u! I7 G
#endif/ f: Y$ a' l# C3 e; Q$ U4 [; x2 h- z

$ b0 W: E0 t9 N+ C: \        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
1 C, W% ?0 T7 [& c0 J        QueueFlush();
! Q; p8 o) @4 k" r2 H
. N- I( h2 l) g# y9 |8 V" e        internal.SaveState( p );
( O$ L8 s- K$ [  x+ I5 U        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( }4 ~6 q- w7 }+ |& R  M) x
' P8 \/ f3 c$ u3 C        // VRC6+ \* Y: ?+ Y( n% w8 b, g2 }
        if( exsound_select & 0x01 ) {
% {$ ]" c' l3 O( r                vrc6.SaveState( p );& @5 V' s5 _+ \" @4 g! _2 I; y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 {, ]5 y7 E( A& S0 q2 q& z; s
        }
% \" {* J+ q! ~) {8 i4 s* f: v        // VRC7 (not support)/ g. P) c* Z  F# N& W+ v0 u, F
        if( exsound_select & 0x02 ) {
5 O. u: P9 M3 a                vrc7.SaveState( p );* O# l- I' q' `) n6 N3 I) ]- |
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 A3 E& V6 g7 `3 x# @# r4 x        }
8 {- H3 p# ^4 ?/ `5 c        // FDS
" G0 ^2 `3 E; R) ~        if( exsound_select & 0x04 ) {
- n9 o" a4 O7 F                fds.SaveState( p );* Q, M+ Z. Q; `, ^1 a+ W2 e1 g* Y
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) v/ r. G! @1 p. F1 _        }
7 M" b  R; C; L. C( C* i* R3 g        // MMC56 b) [" G+ X" c1 I% @
        if( exsound_select & 0x08 ) {
; D7 K3 M$ ]) F  {. f; N                mmc5.SaveState( p );) L7 ]0 f4 _7 h3 V) S, }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* ?  {2 ?' N1 s4 L, K6 \
        }
3 I) C: e9 |4 `5 _        // N106
$ s% _( _5 ~. _: W) P+ ]        if( exsound_select & 0x10 ) {5 m0 \' I( R  d+ ~* {4 Y
                n106.SaveState( p );
6 Q/ N. n) F8 R- C" v                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
* u% J9 y' w: U( Y& @        }, N2 J; b7 I3 c, @
        // FME72 S+ G& b; U$ V& m5 a
        if( exsound_select & 0x20 ) {
9 y6 ?. e% O+ r( S6 Y                fme7.SaveState( p );
( o, ~2 ?6 ^/ L! B# Q7 U                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: K; j; W7 D' g, {0 p, I        }
- W/ q5 U  A1 k$ w, F9 A# u) u! `: _, p: K# _2 }6 ]1 I& \1 g
#ifdef        _DEBUG8 C9 S3 V- |* H! E8 L  w  `
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
0 u  @3 W7 q/ z1 G; O: ]#endif9 }" H) Y; X) ^
}- g. A# S) c& ?$ K/ N+ W! Q0 y
0 r/ R: y+ _: K$ t7 S8 g# k! x8 I/ W
void        APU::LoadState( LPBYTE p )# f8 g& a% q+ l5 p
{5 [; q* C4 a4 s: b6 h  o
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
) V* |7 d( y. _8 @& {  F        QueueClear();) n- ?/ n0 |- \( I

, q7 t; Y# b0 S% A6 t        internal.LoadState( p );
& f0 p7 h' D+ U3 q+ J- i        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding1 H4 W+ b( E- l# ^

& t( z8 q0 y: v: p        // VRC67 |! k% G( L* |' X. j$ _" |
        if( exsound_select & 0x01 ) {
+ o. }8 H; {2 i! C& B                vrc6.LoadState( p );% J7 Q: m: y1 F; m7 P7 w$ s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding/ g% {, q7 g/ \5 L
        }
. F7 _% b6 g. k2 x        // VRC7 (not support)
7 Z3 \3 j& P. i* ?  A1 t        if( exsound_select & 0x02 ) {
4 \3 E5 U% X* b2 R                vrc7.LoadState( p );
! K# ^3 ~3 p* s, l$ K                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
+ D0 m7 m; j+ ?" Q        }' ~, ?! R- S# P& q6 n
        // FDS$ ^+ @* n  X8 n3 g$ C/ C  X
        if( exsound_select & 0x04 ) {$ Q: E- f" v9 T( o3 B5 u
                fds.LoadState( p );
- j+ L/ m9 V! r6 H                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 y* j; L( b" P7 x        }
- a9 {- i  Y6 R" P# Z0 R        // MMC5
# ~# G3 \5 n+ ~" W% V: G! g( r8 T        if( exsound_select & 0x08 ) {
% y2 @& W' K+ G/ l4 I* y- P1 g                mmc5.LoadState( p );
# a" g9 d# M( X                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
3 j' N$ K. f6 J( ~2 `- `- V        }
6 q" q$ B9 k# o  l% j        // N106  j9 X" ]- o$ ~1 W
        if( exsound_select & 0x10 ) {
$ s* L! s& a/ u4 L5 ~                n106.LoadState( p );1 L2 t! A+ a2 R4 ?% ]
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* `+ m3 ]$ _% ~: Y3 S
        }
; n0 Z. ?, s1 _7 P3 H        // FME7: E' m+ I+ p* ]. P9 y
        if( exsound_select & 0x20 ) {% x8 R+ z) F8 W5 u$ g
                fme7.LoadState( p );
9 n* A: \; E) `& a7 p                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding! q! ^6 y; e8 |' u0 s$ ^
        }
& g# H# g4 o! ~  ?/ t6 {, [}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 3 o6 |) y$ P" |& o: Z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
( }3 n6 ^) w. u0 E感激不尽~~
; e! a2 S* S" w9 ~  O, J# u) ]1 t; T
恩 我對模擬器不是很有研究,7 R& f9 z- L2 H- u6 i
雖然要了解源碼內容,可能不是很困難,3 h1 ^  f' H) r' [2 ?4 Z8 c
不過還是要花時間,個人目前蠻忙碌的。
* O! W5 C3 I% b) B# `+ k. _% Q
1 ~& T( T9 g$ S: a' S給你一個朋友的MSN,你可以跟他討論看看,
1 m/ B2 P5 B, T# `5 @. ~他本身是程式設計師,也對FC模擬器很有興趣。
. ~' R* a4 G! V" h/ y" n
7 H0 P3 \7 }4 |$ _MSN我就PM到你的信箱了。6 Q5 [3 r7 e; E
* O' L; D- u( F. A" k5 u
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表   ~: t2 [( P5 e5 ^; U# ]& M
呵…… 谢过团长大人~~
$ y9 U8 U2 D6 ?8 p! S/ N

1 E# J# v  a, H7 n哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 % o, R0 L. V, G, x/ A9 k3 }
团长的朋友都是神,那团长就是神的boss。

" W- c0 Z! F8 G' O哈 不敢當,我只是個平凡人,
- I6 w( T1 y! |3 z- c2 b要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙$ a9 o' }& b0 H, `" y9 M, b
ZYH. W7 x% [; b7 h4 z" Q
QQ:4147343064 {( H, Z7 c" G  Y; C' @
Mail:zyh-01@126.com
5 t+ z% [) n) S
" A! \7 O, w( t; Z4 E他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . O$ U0 h9 W( {% ^7 ~$ k! v
再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ N) P' K+ ~3 f
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-30 00:25 , Processed in 1.138672 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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