EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' `4 f# n7 y# @7 j楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~) I5 m1 P+ f' T* x6 B* o
这里有相应的模拟器源码,就当送给大侠了~~! @! w) f" G) P/ S& q3 R2 c
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 , I8 A3 C# s  F, {7 K8 m* g
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! F" k& Y) C, P- V3 F( ?楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~. }3 K5 I6 [/ |5 ]  a4 b
这里有相应的模拟器源码,就当送给大侠 ...
. P$ v, W3 w# N7 Z
聲音部分(Audoi Process Unit = APU):
7 ^& h8 h( m( C$ D: |.\NES\APU.cpp
; a- |8 D+ I6 [3 ?# T.\NES\APU.h* h# G1 p$ T9 v3 j2 [

7 @5 ?! g9 k4 V2 i4 V* p
, Y# E/ o# R& H3 {2 Y! U8 Y影像處理部份(Picture Processing Unit = PPU):' W) P2 y. m! X2 j/ r& ~5 m) b
.\NES\PPU.cpp) q' v' l4 Z7 f) i, k& b
.\NES\PPU.h
$ k: w) |  @% V4 B# x
" E2 g0 E3 a: p: g" F! X2 \如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
* f: F+ g6 q4 \- l& w7 R$ I, w(由于很多专用术语和算法机理都不明白,所以看不大懂……)# A* ]2 @8 ]; W( A4 i& ~% w  c% E
//////////////////////////////////////////////////////////////////////////
' l/ Y; I: N8 a//                                                                      //, o9 v, L" m4 Z7 v1 I
//      NES APU core                                                    //
' K3 j+ h$ q' W, W; s//                                                           Norix      //
3 c) R2 H* ~9 I6 a0 f//                                               written     2002/06/27 //* S1 E# N0 J) E% Q
//                                               last modify ----/--/-- //7 P% g. R  p7 @  p
//////////////////////////////////////////////////////////////////////////! T3 N' L' B% r1 X  w
#include "DebugOut.h"
+ n& [4 T; s" q#include "App.h"
& \% P3 S* p: k4 O1 k#include "Config.h"; g/ g6 i/ k! o( W3 m( z/ ]
- x' o4 R; L; p5 b( H8 x# @; y8 {
#include "nes.h"* Q0 ~" L; m% M/ K; N2 B
#include "mmu.h"
. J' ^: f3 O  B; x6 p#include "cpu.h"
' R# @0 D% o; w#include "ppu.h"
) R6 B2 a+ H$ n" Z#include "rom.h"  G6 B+ U, s- X" ~
#include "apu.h"
  }+ m5 G6 t7 _" q+ B& _" b& a! ^3 S; K& B: c- {
// Volume adjust
9 b) Z; T2 P, v6 l3 s9 K// Internal sounds3 W, T8 a; C9 l- f/ @: N
#define        RECTANGLE_VOL        (0x0F0)5 {4 n2 Y( s' y, ~: {" A$ D( F
#define        TRIANGLE_VOL        (0x130)$ \- E' v% n/ D5 t# X/ x5 o6 J# G5 b
#define        NOISE_VOL        (0x0C0)- d- }0 H" U& K; h9 P/ \- J
#define        DPCM_VOL        (0x0F0)
1 o" Q$ ~9 x4 `8 n9 |9 y9 o! g2 a// Extra sounds
0 |5 _# D9 v0 z6 ?#define        VRC6_VOL        (0x0F0): _+ F4 W0 w6 Z3 G; z- @: v; N
#define        VRC7_VOL        (0x130)6 t; p" ^7 t2 f) K2 _: ?* [
#define        FDS_VOL                (0x0F0)
0 G. l: S. D7 d3 }! h#define        MMC5_VOL        (0x0F0)6 g1 U4 w$ A  a/ Z- Q
#define        N106_VOL        (0x088)- V2 s) z5 X" T9 Y( e9 U
#define        FME7_VOL        (0x130)* ?/ w- r+ N4 A) V& i% V: }" N% {
( t7 S% `9 k3 j9 Z& q
APU::APU( NES* parent ): X' A/ k( \! t2 B& E
{: }8 K/ B- D- N* R& O
        exsound_select = 0;
" ]6 v+ G! H! G& G. h2 z9 I% d. r! l0 }0 F4 y3 h
        nes = parent;* j, V2 C+ @" ?& ?$ B. n5 l
        internal.SetParent( parent );: P) Q2 [5 B8 M. q3 ^8 N

7 U0 N* g' K3 p3 l, l) ~$ d2 v        last_data = last_diff = 0;& v% V& }* T" ?' p1 C+ g5 D
- |4 t" z# Q; d9 ~, I
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );. s* i0 z3 y  e0 J

2 [2 A* k4 n' s5 t, I/ L: ?        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );& F3 t1 N4 m3 [! L! }' m
        ZEROMEMORY( &queue, sizeof(queue) );: n8 c2 A8 E; t7 Q$ n( n& a
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& r- y9 k6 T# ]6 ~4 O, y8 `% M0 c
) [/ Q* `' m. G; c$ K        for( INT i = 0; i < 16; i++ ) {2 ?; G) y3 `  r7 L# C8 U/ a
                m_bMute = TRUE;
- U2 r3 T  {+ T' c4 }# N4 L& `        }& S, R$ X% |9 q, c
}. z7 c' x  Q  q( Z" U

" h$ J1 g% u0 z9 Z8 t8 CAPU::~APU()
; G6 B7 J  `! h1 k{& H$ I0 i2 N: m: a
}/ Y% u3 ^+ G, t4 D0 D
4 o- T' N' T1 K9 A/ l# k- ?0 g
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )! G* ]. v5 T2 Y- ^* D
{
8 N) w2 F1 A+ i4 T# F/ w2 r        queue.data[queue.wrptr].time = writetime;3 z5 }+ w/ M6 B* _; b
        queue.data[queue.wrptr].addr = addr;
* p" e( Z  u  T6 b, |, ?( @, y        queue.data[queue.wrptr].data = data;
$ c/ E/ z3 M+ Q8 Z- T- j        queue.wrptr++;( X2 P4 f* K' g/ M9 y
        queue.wrptr&=QUEUE_LENGTH-1;
8 t$ e4 E+ X- ~* R7 I* W  D0 a: t& M        if( queue.wrptr == queue.rdptr ) {; d6 N4 k- Y" z0 G% a
                DEBUGOUT( "queue overflow.\n" );
* K# {; J' M2 Q0 O/ M        }, L$ p" w9 W% A* D" K
}: u/ D1 _4 A4 E8 i7 v9 v

8 }+ K# Y$ s% X' A1 [* A  eBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
% ]% q7 O8 x8 q& b$ Z1 o{. n$ l& Q& q/ K3 Y# o% m/ u9 f  u
        if( queue.wrptr == queue.rdptr ) {
( z" h0 j5 s& ^1 ?                return        FALSE;; ~5 V6 E2 m) M6 q: J
        }0 G  j- D* H5 B: C' V/ \5 ]$ G+ L
        if( queue.data[queue.rdptr].time <= writetime ) {3 E- @( J, T! L5 R! _- D! B
                ret = queue.data[queue.rdptr];  E# p* s+ D: |! T& _- ~7 v
                queue.rdptr++;+ W* I  J9 ~% n: D6 J( H# P
                queue.rdptr&=QUEUE_LENGTH-1;
) c( m! B$ m4 Z( [. u: h" q7 \                return        TRUE;' p, h, _- s! i+ V
        }
& x: |1 M4 L/ A4 P" [        return        FALSE;% ^' M7 K* A. E; w, @$ f
}
& f/ s4 b# m/ k1 E. W8 }: u) ]$ I, \* b$ K) |/ f
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: q: q2 s. U& \; t) n; _* N* ^{
& b2 O# }4 D. }) G        exqueue.data[exqueue.wrptr].time = writetime;* a8 A% e6 S3 _8 w) D3 [4 ?
        exqueue.data[exqueue.wrptr].addr = addr;- N9 [# O! Z# [: F
        exqueue.data[exqueue.wrptr].data = data;' M; L& x4 _  B5 `  ]
        exqueue.wrptr++;
6 j0 S5 M& R1 S        exqueue.wrptr&=QUEUE_LENGTH-1;
' c# j5 ]+ L% h4 U3 ?2 E5 T6 k        if( exqueue.wrptr == exqueue.rdptr ) {
4 y8 p# P( `! K  j+ C2 b                DEBUGOUT( "exqueue overflow.\n" );
" h( l7 H( G6 S8 R# X3 ?        }9 l- k: s- ^* s' b( f7 [
}- w. [9 r  G- ]
" T# r. p! b2 u8 @7 i4 B
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. q5 ?0 ]" x% Y: d0 R{; o5 ^6 q. {$ v4 u
        if( exqueue.wrptr == exqueue.rdptr ) {7 B' G) }; s0 C- Q
                return        FALSE;" F& h% W9 K6 j5 I: h) |
        }
; r8 P% [% w3 i        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
/ v1 @" O8 o: I) C; P2 D# q2 a7 Z- O3 e                ret = exqueue.data[exqueue.rdptr];
2 h0 |' u% W4 x                exqueue.rdptr++;: F" N, X- s6 v# w8 \- `
                exqueue.rdptr&=QUEUE_LENGTH-1;
4 p7 I! D6 Y- Y7 i1 Z7 b; p. Y                return        TRUE;) C# N* g) G  s9 R) O
        }
' I; a: Z2 p3 [) `: ^1 \" E        return        FALSE;
+ C+ a/ Y- H4 Z$ Q1 E}
  b7 H# J- D9 y# x; {* \  r' b$ F
3 |; M& @. H- I# _7 z% tvoid        APU::QueueClear()3 J. N' i8 j/ B) A& u% ]% L' I/ m
{
; `+ P( }  o8 a) I4 m2 ^        ZEROMEMORY( &queue, sizeof(queue) );
  {2 o! U: Y' D$ b, b. w' ?# F        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 S$ B& C: g/ m* k* ~' h}
+ H. [! \( s8 C1 p; a" B6 n" {& O6 a
void        APU::QueueFlush()
( F5 P) {/ }, Y2 @+ h6 D{8 y+ {" V5 N" z" {0 h: I" L
        while( queue.wrptr != queue.rdptr ) {
' ^4 C9 N( ?1 p6 A+ Y                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );6 h* `6 G# B3 t% v9 j  Y
                queue.rdptr++;
. F) S' g# ^5 ]' i6 V                queue.rdptr&=QUEUE_LENGTH-1;; s" `" `# s4 W, z
        }$ j+ i) c7 H9 \/ X- ~! Z

% L  }  t' X* o        while( exqueue.wrptr != exqueue.rdptr ) {
7 ~) u! Z: Y5 O+ i7 N                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
$ ^+ T3 k* ]! [+ x5 C                exqueue.rdptr++;
  z, q6 w6 W/ x# {$ E                exqueue.rdptr&=QUEUE_LENGTH-1;
( x8 \* m' F# E  Q+ c        }, J& p5 b& n; \% e# Q, I
}8 `, K7 }$ ^# `9 b

) k2 u" d/ W5 |3 G7 Vvoid        APU::SoundSetup()
0 m& U3 b+ v. `0 m) f6 @5 e% Q1 q* Q) M{  v4 {& @3 g: k5 g  Y" Q5 i- M
        FLOAT        fClock = nes->nescfg->CpuClock;; @: Y% D7 ~+ u$ H1 z' `
        INT        nRate = (INT)Config.sound.nRate;
% p8 Z# c0 f2 z, K9 ~1 U! @: y        internal.Setup( fClock, nRate );
0 v6 M2 n& T1 Q        vrc6.Setup( fClock, nRate );
0 {1 G- n/ I7 D1 ^        vrc7.Setup( fClock, nRate );
" A  i6 y: @% {- p3 w        mmc5.Setup( fClock, nRate );
- o: N' V  P$ o' ]/ v5 N        fds.Setup ( fClock, nRate );# h) I& T1 T% y4 \! O/ [) @
        n106.Setup( fClock, nRate );4 t" ^- v$ C! d5 Z' r7 d& c
        fme7.Setup( fClock, nRate );
" M9 H2 E+ i" a+ }+ ^}
/ c- V- N/ ?3 f2 t9 @& P: w* |) D; T8 m# Y; [8 ^& G- o
void        APU::Reset()
: O; m, f, {' \7 `$ K6 I$ w' Q. R{
3 E2 I( x( x' l# D: A        ZEROMEMORY( &queue, sizeof(queue) );
1 ^5 w# m! \$ H4 Y: `0 Q1 P3 G- `9 }        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ B& O7 i* z( k8 k$ K& a, i

9 c  q6 Y. O' M        elapsed_time = 0;
) W5 o( d2 q/ T8 S. I  I: T, o. m/ ^; Q+ W& h: F
        FLOAT        fClock = nes->nescfg->CpuClock;: t: j$ a2 W! J6 [0 s( u1 v3 f* g1 o
        INT        nRate = (INT)Config.sound.nRate;% w- A" `& m9 _6 p' H0 k  T6 z
        internal.Reset( fClock, nRate );, l# `8 v! P8 _/ F: K
        vrc6.Reset( fClock, nRate );
' N, a" T4 m% ]5 `! T! r        vrc7.Reset( fClock, nRate );9 W) {0 i( X4 K2 K6 F: A# `/ D1 N
        mmc5.Reset( fClock, nRate );- P# I  V* Y6 H! S! b1 m
        fds.Reset ( fClock, nRate );
8 j$ @* x0 x6 Z2 n        n106.Reset( fClock, nRate );" h, P0 R* ^3 ?8 Q. q# b
        fme7.Reset( fClock, nRate );- ^8 ]+ a: c% ^  b

- \% a% n5 `- Z: E  v# f        SoundSetup();
. |" Y: ]1 S! Q+ D8 E8 Q}8 }* `: t( F+ ?
/ k/ Y( l+ x( I9 F- _
void        APU::SelectExSound( BYTE data )1 f9 B/ v6 ]# Y& M
{% k- Z+ H5 j( n2 A# y8 N: a' H7 i
        exsound_select = data;9 a; z1 \! Z: h% i+ c% I" s' g9 M
}
" X1 F" B- B, V7 S3 D& T+ `& `/ N' o
BYTE        APU::Read( WORD addr )+ i7 K& v: x5 p- T* T
{
$ `& |8 d0 q0 ]0 v- [        return        internal.SyncRead( addr );
) G; v- n; u% p4 M5 H; b0 {}
: `9 H3 k  E; [% p+ a1 z6 u6 R3 |7 H$ M0 p6 s' ]% f
void        APU::Write( WORD addr, BYTE data )
9 ?- h5 a8 L% u; K+ N: |$ w1 k$ k+ w{
: F% ^* j$ a2 p2 \( R  i! N        // $4018偼VirtuaNES屌桳億乕僩& T: [$ T. r+ V. f1 G9 |& @$ |
        if( addr >= 0x4000 && addr <= 0x401F ) {9 E5 B* m: Z4 m- v& I+ f. a' x8 r7 s
                internal.SyncWrite( addr, data );6 }: W0 `' b' x
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; J; ^6 [/ [' Y6 v% e6 A$ h6 b
        }7 o2 O6 O: ?% t: O; Y# H
}
" U% a; h/ O& C, e" A5 H' S2 W/ A1 ]
BYTE        APU::ExRead( WORD addr )
1 Y. Z) {* U) }6 G# m. `{
# m2 K$ L2 ^  L; H/ c2 CBYTE        data = 0;) o0 v; c: l7 m$ b3 a3 Q

9 t! _! K; G. v; P1 F. E7 X        if( exsound_select & 0x10 ) {9 c% j' r2 {7 }/ a: \2 E8 G- O
                if( addr == 0x4800 ) {
0 }9 }* D( m2 [+ Z0 u/ `- L+ R                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
  B2 H# k; ^  N/ T                }; t7 V+ i" s. `8 q1 g
        }
$ W( J, t5 S5 A+ y) V: s4 a9 r        if( exsound_select & 0x04 ) {5 q: R9 I4 v, w) I2 X
                if( addr >= 0x4040 && addr < 0x4100 ) {
4 v. ?8 h( [; n. h                        data = fds.SyncRead( addr );
8 \! Q- ~; a9 b3 V                }. V1 p+ V+ o& n# ]4 I9 |- {% P
        }9 z1 L' f; l$ u6 a" Y% q; B
        if( exsound_select & 0x08 ) {6 H' Y' X+ G. U4 E3 s7 G4 P! {1 V
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! F- ]5 l  Z' G0 H! K% V                        data = mmc5.SyncRead( addr );6 g- O! ~# P* l2 ]/ P! M
                }4 S8 M# V$ M3 D* Z) ^! N  t
        }
" t% s9 j/ ?# i3 P, |3 @$ C$ Q& H( m
* q2 w8 |& e# i- ~) o; C        return        data;0 Z3 F8 c1 \: h, o6 Z% I
}
7 x9 O( s' y( v7 {7 o) _3 h
* Y; M( r9 }$ Q' fvoid        APU::ExWrite( WORD addr, BYTE data )$ A$ u9 Z  ?" ?) o4 Y+ @; R% e& Z
{
  x' i0 Y) i+ w* R, T        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
& p1 p: @$ a6 d) s* A
' x8 u2 V+ G/ ^0 i% u5 H6 a5 s        if( exsound_select & 0x04 ) {! D/ S+ i+ q" k" m
                if( addr >= 0x4040 && addr < 0x4100 ) {& a( a6 _/ A: M" _1 n
                        fds.SyncWrite( addr, data );
' S; m+ l0 W- \7 Y                }
# ?  j7 `3 a& w4 J: I$ {6 ]        }' \( K) o% q& e2 l' @1 u; d/ k

6 F* H' K- a1 M9 [        if( exsound_select & 0x08 ) {
7 R. A/ I" c9 ]8 _                if( addr >= 0x5000 && addr <= 0x5015 ) {0 M1 ^, r, W7 H4 g
                        mmc5.SyncWrite( addr, data );0 r; V, L5 x1 V! J, l
                }
/ n8 ?. j& a8 O  n, s. B" a        }- {6 b+ O. z# f7 D" d- G8 B; M- H
}
" {* J! d% |! @1 X/ [1 p" g* N! K5 b$ S% n$ `
void        APU::Sync()
7 \4 D# a0 q+ l{
& c# D0 j' d8 a0 P3 `- b* v}
' o& `: `& S( Z7 [% _% D, [5 B
6 o* f( A* |! L& ], s) W! Cvoid        APU::SyncDPCM( INT cycles )
8 G. r6 w. e& W0 m0 _  D0 k{& X$ Z" V- v' q) u
        internal.Sync( cycles );
, H4 T) g! ?" ^% v" e! ]. u, _% ~: b; [" _
        if( exsound_select & 0x04 ) {4 @, y8 Q/ O( ^2 ^1 |) J) R% @, Z
                fds.Sync( cycles );# s4 i6 T/ @$ B
        }9 }) J* c# B0 @! o0 d
        if( exsound_select & 0x08 ) {
, i5 G5 Q, }  B5 n                mmc5.Sync( cycles );  i! d4 I- l7 U# x* w8 s$ [) P
        }
7 Z( f( f  R3 t* X. u+ o1 k) h}
  H& b6 n0 z6 S* H  z- g3 M2 c! |9 L# _2 j" F4 M
void        APU::WriteProcess( WORD addr, BYTE data )
, l3 h3 D' i2 `! p{; m' V" u2 p' q" w  l9 U$ P
        // $4018偼VirtuaNES屌桳億乕僩$ R0 L( K+ k3 d, C. q! R6 t
        if( addr >= 0x4000 && addr <= 0x401F ) {0 q9 O; A% v5 T4 x
                internal.Write( addr, data );  m+ P% h) S3 x$ h3 U0 w9 s- A) a
        }
: j& Q9 F) I4 [  W! j1 p* e}! b) b  y% J, s+ Q* g( g
( g3 q- _( k. a& `; ?
void        APU::WriteExProcess( WORD addr, BYTE data )3 |; P! C& A  m+ S
{
+ {4 I# n2 H: w4 o- g  w        if( exsound_select & 0x01 ) {* ?* ~) _; A; d8 E  n0 Z
                vrc6.Write( addr, data );
& k7 Z# h& b6 g3 @, K' p& A3 E1 ?        }$ s) {( j( F( p& m3 ~& v
        if( exsound_select & 0x02 ) {
+ }/ V+ Y3 R% n& a                vrc7.Write( addr, data );1 s& b% n7 [3 C% a: x* R! K1 X0 F
        }5 ~' r" f) h( |, Z6 ?& j! N+ m
        if( exsound_select & 0x04 ) {# \' F9 N4 `& J! ^0 F% ^, {  Q
                fds.Write( addr, data );& [9 z4 _. Y; i6 @: l4 `: W
        }
+ q( q3 E1 w; F* y        if( exsound_select & 0x08 ) {
0 R8 x& J$ T3 e5 A. W$ M                mmc5.Write( addr, data );
8 X5 F! ?0 S6 z& Y        }
1 ~3 O* ~) z3 W9 b+ ?9 Y0 W        if( exsound_select & 0x10 ) {1 H4 U4 g8 ~7 R$ {* M
                if( addr == 0x0000 ) {7 A" ^' \; z* D" @
                        BYTE        dummy = n106.Read( addr );
0 r7 T7 ^9 y' {5 Z                } else {
9 t% Q0 K" g. [/ y                        n106.Write( addr, data );
% L1 P: V7 }) X# D2 n5 Z5 z* ^                }
; t  U+ Z8 S. E, g, |# R* l        }8 j7 v+ X) G. X& y
        if( exsound_select & 0x20 ) {* a2 C* s; ]1 `) T6 [4 \
                fme7.Write( addr, data );) y5 f$ u4 L! L: x
        }$ Y8 l' b- e( m$ w; p
}/ g. Q& P) W+ p; I

' @/ o+ d" Q3 J9 Z! P: rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
8 A- \# `+ ~0 ^. w/ k{
* k) s, h6 H; T3 IINT        nBits = Config.sound.nBits;
, N+ ]* o. ?/ ODWORD        dwLength = dwSize / (nBits/8);! b; y7 M& T9 D0 O8 n# `8 ~
INT        output;- p2 C& U/ C' B! q( P
QUEUEDATA q;
; }- g% f5 G* }3 w9 |9 @1 WDWORD        writetime;
' F$ F1 Z  S  c
* _2 d# J7 M' T: E( g$ @, l% E2 u4 qLPSHORT        pSoundBuf = m_SoundBuffer;  D! t" n. X! S: U* ]% `1 U# \2 z
INT        nCcount = 0;2 c) @0 f- B+ G) k/ V

: u/ k8 J& @% y+ I( _+ b" iINT        nFilterType = Config.sound.nFilterType;
8 g2 O* N0 E$ p& d4 [
9 [; u* E4 I- d3 D        if( !Config.sound.bEnable ) {
, R' A' s% J* d$ d                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );- q2 [, z8 g  Q
                return;
' v& O5 V. |, D3 K: T9 Z        }$ V# Q2 Z& b7 f$ m4 R& f- f

3 G$ e" P' Q- v' \' A1 d        // Volume setup
5 K) S" N1 e8 R- z/ ?        //  0:Master
1 ]2 R9 P/ V: @* a9 @3 f( n        //  1:Rectangle 17 E  J* u8 i4 f6 n$ i* @
        //  2:Rectangle 29 c- F1 k: r$ ]0 l
        //  3:Triangle- c, f4 b& o+ z( O1 R" T* [. {
        //  4:Noise
, }3 g' \! W0 Y6 c6 z" M        //  5:DPCM
. F' s9 d( K# [        //  6:VRC6
, M9 Z5 U  A, n+ T# J$ J0 m        //  7:VRC7
2 L  l' w2 ?; z. Y        //  8:FDS1 M, ^% v9 Q& k. G2 a' n# o& k# A$ W
        //  9:MMC5
4 d4 f+ V0 K. }# P( D' d        // 10:N106  U/ {6 c- N! C* c. y) |
        // 11:FME76 y1 S/ X+ K9 N& p$ [# g4 ?
        INT        vol[24];/ T8 Y- X9 B4 H' ~9 [8 j" _8 v; Q
        BOOL*        bMute = m_bMute;( M- P. c6 `$ s7 t* {6 |
        SHORT*        nVolume = Config.sound.nVolume;* A! ?1 i- ]8 ?( f. x" W

* M# N+ o; k4 L3 ?, m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;/ ?. F% r5 F" T" ~: p0 M7 o  }

( V) s5 J1 G' j* L7 l1 \        // Internal5 ~/ B3 p$ U  b0 R. s4 L
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;( [5 Y! e3 f& f4 G
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;, }. \) M! o+ Y7 z
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;2 D* v  V, W6 s1 z: S9 [
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;9 R' H9 F3 g+ v& v& ~% X+ x  p
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;5 C; L& m7 f# U7 I' x8 y

+ t# [) ?( d) K* z" z/ H6 ~' f        // VRC6  [& g2 j% ?+ D4 l' Y! |# w
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 h, q, n# }2 Z        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. V. H# ]/ N6 Y( d$ H        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 U9 H3 _; X6 U& |  k
/ w  o1 n2 Q/ M0 |+ P
        // VRC71 [# a4 \; J$ x$ g
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
" T, A" m$ \" S2 q* @: @8 c# J3 l9 h
9 V* n' N% e' w$ P/ E! o1 W" X6 M        // FDS; |7 D. c. |' m; _
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
+ p7 H$ {$ @+ R3 e0 ~8 e& q+ I& G2 o$ ]) Q2 x. W. P
        // MMC5
0 U7 Y' c% ^+ B! k& F$ u4 r3 C        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. ]5 d+ J- f; U! [        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 l! }+ |3 p1 R9 u
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  T7 Z3 k" |' l* H+ |! c) u
6 x& F: ~% \  Y* s        // N106; o9 Z3 Z0 p" [
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! Z& X8 h9 M8 k8 {5 t5 I$ B
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ v; m0 x# s7 A7 |. x4 p
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) q7 s7 T) {! }- p( c# L% q
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ G1 b0 P7 i. z8 m
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 {8 a. c& S6 e8 a        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: i: g& v6 x7 k' f( u) U/ g
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 L8 H0 n! j& H# g1 ^& G+ k
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! X8 ]0 \+ t  Q4 H  p6 T% r" n+ d! Y
        // FME7
: M# ]0 m( I" I' b6 n* n) J2 o        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 h8 a) [; R( ]* U
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
7 ?5 r! q' N4 Z        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% c; d  m9 G% X5 _
( q: F" T* {) u0 q7 H% k& W//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;# q. l2 N: ?( p% f6 f: w* B
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' @: c+ t5 q& A6 k; W7 ]. Q* J9 w* Z' V- x- m
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟0 z7 f; V7 ]* z' m5 I
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' D! f: N- V0 ^8 U$ c9 X9 T
                QueueFlush();5 b! J7 V  y% U) E5 T% W2 o
        }% i6 d& c4 n: r" ?6 N

+ c& L! b, q" H3 [- s6 X        while( dwLength-- ) {' v* ~/ a' }. r- G/ a" l
                writetime = (DWORD)elapsed_time;
% d3 w) d; }- ^1 s3 G# e) d  N1 H7 y7 {( }: R( v; v$ x. S! `4 {
                while( GetQueue( writetime, q ) ) {
# x. J  N; o- q0 H                        WriteProcess( q.addr, q.data );* I* `  X7 h; i+ o& S- b0 P* e2 w# @6 k
                }
/ |5 j2 G; q% n/ r, d1 z# B1 u' X* u% L
                while( GetExQueue( writetime, q ) ) {2 U. ?7 D( u1 V9 r; G' m/ _
                        WriteExProcess( q.addr, q.data );) ]0 |7 J, @4 F: `2 i! |0 j) E
                }# E! O7 U3 w& e  Y/ H4 o3 O

- K0 h: M* E7 p0 u; j/ |4 U- T                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7/ @# s7 v1 x, b/ E
                output = 0;  Q7 J3 u! U# s$ ?7 d' W* C) m
                output += internal.Process( 0 )*vol[0];7 z3 F" p% K5 h% H2 M
                output += internal.Process( 1 )*vol[1];
( O8 p6 k" I* y: ~: C# G                output += internal.Process( 2 )*vol[2];
& [- ^7 E6 s* N0 r8 u                output += internal.Process( 3 )*vol[3];
7 y% w, x/ D& w, K                output += internal.Process( 4 )*vol[4];: _; U1 z+ Y5 a0 P. G
* F" b" F- D4 _" c( e, p1 Q' X
                if( exsound_select & 0x01 ) {% [! w/ y* L) q9 D
                        output += vrc6.Process( 0 )*vol[5];% a& S6 S: n" m( E
                        output += vrc6.Process( 1 )*vol[6];* Z, c4 v' K* y0 _5 f; S
                        output += vrc6.Process( 2 )*vol[7];* P# b# F8 r5 p9 u* c
                }) ?6 l$ f2 ~( K( s# O1 |
                if( exsound_select & 0x02 ) {/ h: `& l/ ~4 Z6 G6 j) E3 z
                        output += vrc7.Process( 0 )*vol[8];
5 g! F' p- h% l* t- i; l                }. T) [( F4 h  K
                if( exsound_select & 0x04 ) {& C% Y9 H- V  R0 F
                        output += fds.Process( 0 )*vol[9];0 i: A. V1 w5 [
                }
) r9 P+ H$ x) m3 i0 ?9 q                if( exsound_select & 0x08 ) {
# U7 a9 l+ c, B- K2 c                        output += mmc5.Process( 0 )*vol[10];
& v5 y. i2 B7 C* y, J                        output += mmc5.Process( 1 )*vol[11];& [% R  j5 t, t- a+ f( c$ t3 Z
                        output += mmc5.Process( 2 )*vol[12];
7 Z" ^' h0 ]5 u                }
5 O5 I! I2 K, i+ n( a- w                if( exsound_select & 0x10 ) {9 T  V' ^  M+ w$ Q
                        output += n106.Process( 0 )*vol[13];
: x6 w# x" M3 t$ t                        output += n106.Process( 1 )*vol[14];; m8 M9 c; M$ G2 [8 f
                        output += n106.Process( 2 )*vol[15];
* k! V0 ]/ Y( Z                        output += n106.Process( 3 )*vol[16];
& F7 U! e$ O3 X% N                        output += n106.Process( 4 )*vol[17];
0 b$ M. f$ n3 t" y6 \' S% |                        output += n106.Process( 5 )*vol[18];5 ~' i' L, a& O$ r: u% b+ L
                        output += n106.Process( 6 )*vol[19];
& ^" ^. R/ A9 P6 d$ o6 O1 {                        output += n106.Process( 7 )*vol[20];) V& g; _; V% n  I1 O' g6 K
                }8 _5 R4 F, ?" A. ~6 P3 |3 b
                if( exsound_select & 0x20 ) {7 C% j6 ^, q& b! @' M" V
                        fme7.Process( 3 );        // Envelope & Noise9 B2 N6 a$ v' u* f: q, P
                        output += fme7.Process( 0 )*vol[21];
2 I) {$ i5 j6 w                        output += fme7.Process( 1 )*vol[22];
; u9 a/ }6 Z4 o0 j2 [6 }3 r. S                        output += fme7.Process( 2 )*vol[23];. a/ s# g1 t% a2 q( a
                }7 |5 ^4 ?9 q/ ]+ S
: B/ A+ Q4 `# k
                output >>= 8;
! O$ j( _" _9 _
8 G1 r  c/ a6 S                if( nFilterType == 1 ) {+ A, }& J1 b' @
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
  Y, ]7 L8 H+ r: _4 U6 T                        output = (lowpass_filter[0]+output)/2;' q4 u, }, L6 G. Q0 e( M
                        lowpass_filter[0] = output;# n  K3 F. S/ q3 Z
                } else if( nFilterType == 2 ) {& |2 y# p3 E- Z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)! w9 u, S7 M6 O$ o, z! E( z% ^# x! `
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;8 B: S$ W* G  q4 Q4 j
                        lowpass_filter[1] = lowpass_filter[0];- v/ h- n5 L$ \
                        lowpass_filter[0] = output;
# s9 C4 ]5 n0 J7 K* N                } else if( nFilterType == 3 ) {
8 [7 A( b6 m. F6 g) Z                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 D; E' L" B: O$ s7 S& ~6 z3 c& g5 T7 n1 {
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;# m% m( T5 I4 A& T9 p0 Q7 N
                        lowpass_filter[2] = lowpass_filter[1];
1 ?5 D. g5 y0 O, T+ ^  e2 j- N                        lowpass_filter[1] = lowpass_filter[0];
5 T2 H1 n, q+ G" I; M5 C4 ~( u                        lowpass_filter[0] = output;
/ A+ M( p( z/ n4 K! T0 y) H                } else if( nFilterType == 4 ) {
0 C# ^8 R, U( b( v, o" X! x                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& x) M6 t3 }8 L; }8 \- l                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;, i# q7 k* ^0 |; A! a- p. ^
                        lowpass_filter[1] = lowpass_filter[0];8 b: s1 U( K# R1 V5 L% S% o6 Y
                        lowpass_filter[0] = output;, P# s' T$ c+ O1 S4 l9 e1 l! u
                }8 O& Q* v+ N; U+ F9 Z' E% p' P

3 W/ I' b& [. v# f+ R#if        0
" J: H2 J2 ^( j0 t2 e- j4 o                // DC惉暘偺僇僢僩
( m4 o& j+ a; H- s                {/ x. E  e/ Z' J4 x& Q& E) f
                static double ave = 0.0, max=0.0, min=0.0;" l  g+ s! y8 X, F) N5 A$ `
                double delta;
* l4 I3 L6 Q( S" B' b6 Q# a! ^8 J                delta = (max-min)/32768.0;5 S- N8 ?/ k  {1 F! E- S" w% u
                max -= delta;
! c. Z- J7 Q& ?8 D. ?                min += delta;
0 n) i' _8 @8 h, B, x' k                if( output > max ) max = output;
) ]% E9 b' D3 h) f# W9 \9 k& m                if( output < min ) min = output;
& D$ a: N+ _7 J' `                ave -= ave/1024.0;" t  j3 B6 C8 `; i3 ~4 v
                ave += (max+min)/2048.0;
/ O6 H$ f$ a" d( e                output -= (INT)ave;# l  D, Q4 G0 r( o) y, s; \
                }
5 t% e$ `8 G2 r; q. ?9 a#endif
4 ~, D3 L6 w) D# b& [5 `#if        1
% [& [6 M) h, E0 i4 ~+ g                // DC惉暘偺僇僢僩(HPF TEST)
$ [. V3 r) R: H' c+ I1 m5 n                {+ l4 H  f1 X% x6 k% a" X/ i
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
7 `# d, G, n. c4 P2 A                static        double        cutofftemp = (2.0*3.141592653579*40.0);" J; \/ G% V3 d6 H% K/ j
                double        cutoff = cutofftemp/(double)Config.sound.nRate;, I( }0 D4 y" V2 j, Q8 P
                static        double        tmp = 0.0;  P9 `; R& T" F* O
                double        in, out;2 Y$ I2 z2 ?/ h( }4 J* A
- c9 b1 D1 B' B5 Z" k% W, e' X, f! N
                in = (double)output;
/ }7 e0 L6 N4 L5 j/ f- {5 m, f  o: v6 U& C                out = (in - tmp);, B- v( [; A5 o; u7 G
                tmp = tmp + cutoff * out;
* c0 P5 p9 ^( B% p' I
0 v5 k6 d$ W; ~( Z6 J" H                output = (INT)out;
& Y' J* w3 h/ y, Z5 B                }* b- o9 E  J! y7 _8 \
#endif7 I4 G9 i' U$ C7 a/ p& j
#if        0' K( }: e: p8 b* v/ d
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)& n! g4 J1 F3 o5 t
                {
+ Z2 f+ a4 ]" @5 r  Q  i$ o) _                INT        diff = abs(output-last_data);
% h8 S4 ]! k, H: g) Y% `0 l7 ?                if( diff > 0x4000 ) {
5 U+ t3 F: P- v0 P) P0 a2 N) H0 m. j! P# {                        output /= 4;! k; _5 A9 X5 G( |( D! e; a
                } else
7 P& X8 I5 `' l* Q* A. F                if( diff > 0x3000 ) {
  j3 f  v6 o; g0 }, c                        output /= 3;
1 m3 B* J) y7 `, N1 D: u/ y- m" n                } else/ H' |* V7 U; p. F1 V4 x6 l9 I
                if( diff > 0x2000 ) {) H3 G* R7 A/ Q; @
                        output /= 2;
  I9 K0 R/ S/ v3 {+ M                }  g/ f( j: C* l; N6 F6 D
                last_data = output;& w. H& F" u( I% o' @# v
                }
! M8 ~0 V. j* O% h# r#endif
% |9 _( m3 ]/ c; a3 W                // Limit
4 y* `0 @2 e6 ]. a; C                if( output > 0x7FFF ) {0 Q; @- i/ n: S: M2 y$ C- s$ O
                        output = 0x7FFF;
; l; p. o) I3 h7 l$ ]6 |                } else if( output < -0x8000 ) {5 i4 ^7 m( a; }/ b
                        output = -0x8000;
9 E& X, H( d* \+ v+ j9 h                }' L" h0 S6 e0 ?/ z) P1 F: |2 |

8 N" c/ o; A, w. _                if( nBits != 8 ) {- ], Q. A3 s0 N  [3 b+ G
                        *(SHORT*)lpBuffer = (SHORT)output;
2 |% I7 a- _( A- k, B+ L' h/ X; x; _                        lpBuffer += sizeof(SHORT);
4 q* v0 a: }+ v, k& d: a- W  Q                } else {; q6 l( n. D  Y# a& n
                        *lpBuffer++ = (output>>8)^0x80;( s+ C* H( j+ x* B2 c
                }
9 K+ Z) ]3 r6 }4 p/ _/ Y' B7 H6 s) c4 v  P3 N# R* ?
                if( nCcount < 0x0100 )
* g/ {( u/ }) a, N                        pSoundBuf[nCcount++] = (SHORT)output;
) g: X7 r* I. k4 V  y0 }
- I$ h& K* O: w  ]//                elapsedtime += cycle_rate;
6 [% d7 a* ]6 _# i                elapsed_time += cycle_rate;2 I+ k( u/ Y$ u& m$ A0 }! ?1 `& D
        }
) t& o) t% t# P2 e  J8 ?4 c- V1 L' q1 M0 A
#if        1# r! b6 A, `4 v6 ]1 p6 V
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
+ L& G& Y$ T1 t% o' h8 k: t$ v- ^9 B                elapsed_time = nes->cpu->GetTotalCycles();
* K2 a- q; m- d! L        }
, [9 @2 d0 O; }# u( p, C        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {& K& J* j3 d0 r# u
                elapsed_time = nes->cpu->GetTotalCycles();
/ Y3 d' e: {1 R) E        }3 W* m8 v3 b' ^7 Z$ T
#else- y; l2 |0 A7 V6 J8 W9 M2 F$ Z
        elapsed_time = nes->cpu->GetTotalCycles();
0 l& A+ D& `; l0 X4 X#endif
5 Q: S. ^9 ?1 B5 D: _5 W/ I}7 b$ x0 ?$ x( U% I! S6 S

& |5 Z/ W& k" L7 Y3 b8 u8 g// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
+ _. w! S! j# _INT        APU::GetChannelFrequency( INT no )0 ]. o' m/ X( i% x! y. a' ~
{
8 E' C) ~# a7 c, N; Y6 ^/ d        if( !m_bMute[0] )) Q( h3 S: U3 s2 ~/ |+ c
                return        0;% s; J' w% K- Q* p
& r& l2 _$ e6 L& z5 n0 ]
        // Internal
" b8 [$ D5 w$ d( J' V  M        if( no < 5 ) {
! }: c8 A& E6 @/ Q1 s1 _, l                return        m_bMute[no+1]?internal.GetFreq( no ):0;6 i& o$ M* ]# h% A
        }  f* Z# B* n' `( N
        // VRC6, @' h6 `5 T+ n* v# n0 [
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
" R! W: ]+ X. b% d" C' f                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
/ e% V& p5 M- i  {& k: Z( T/ F        }8 ~2 O" g  t) s+ b3 @. m8 s' Q
        // FDS
; G& `: J$ E" Q( J" f+ l" m! A9 r" B# G        if( (exsound_select & 0x04) && no == 0x300 ) {' g9 N& q0 g. f" Z7 u& h
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ V' L5 i& J& e- t4 F( T        }- N$ ?+ E1 V, ?, U/ X& n
        // MMC5
: F7 ^9 R  J" q) P. E1 F( J        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# U& N. m, ]& l- [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
8 J# I3 i9 o; N/ @6 O5 g* H$ t% ]        }
1 C% n! Q- y: f+ l( u: o) T        // N1063 Q1 v0 }( ]* g; f
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {4 H' e, \' z6 ~8 `4 T3 m
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;. u) L1 e8 Q5 M4 j) Y
        }
- C" n: ^* n  M        // FME7& g" C# q( n+ _
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
0 v' R+ q1 |5 Y' b7 a                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;* R" L3 h" U- e2 ^% s
        }% J" Y* r- I' t
        // VRC7# I$ G4 J+ e2 z( q
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' T4 S8 E! G- L# H) z3 e2 E
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
+ R% r0 O8 K. c1 z        }, K8 E6 s( n% k# ^& H! L
        return        0;
, g/ Q4 T4 E% v- p8 R}
2 q" k, Z( e2 `5 D# n1 c! b* P5 a
// State Save/Load* I6 ^* n) a. B$ {) z! e2 w6 ^' o
void        APU::SaveState( LPBYTE p )6 a( Q0 o( N5 r2 r- _. G
{
1 z1 W" c- `6 @  s# m9 r0 U#ifdef        _DEBUG3 m/ D: t% b3 d+ n
LPBYTE        pold = p;
: X( `7 X5 z/ }#endif
; |7 w1 L. V, M: T3 ^. _" h
* R3 L3 u: K. J6 `        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞! b' i& x: j& B+ Y4 y9 b& y
        QueueFlush();
% H# K* _7 g$ \9 }' I
5 m1 ^$ t' ~( }2 w2 S3 o        internal.SaveState( p );
+ ^7 y6 U) }2 z/ y5 ?        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# ~. p2 M8 g- h: `
8 T7 D9 f/ \# D  G. k        // VRC6
5 B) G4 V3 V( U6 ?        if( exsound_select & 0x01 ) {
" o# R3 B) h: }% E) Z                vrc6.SaveState( p );  G% r0 E) H2 ?! U
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 b, k' \- `9 Y0 p7 \0 t  I  j
        }
. G; |% N6 K5 x, q3 L" g/ z        // VRC7 (not support)
1 t; P0 i2 n! G* y        if( exsound_select & 0x02 ) {
. s# C5 N2 R4 i                vrc7.SaveState( p );
. r! n. M3 U+ f# p: z) {7 y- \                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
4 R- p! p2 z2 ~; t* B        }
  h4 S3 M2 Z9 Q) l        // FDS
2 V5 ?" M+ B# I7 T0 l        if( exsound_select & 0x04 ) {
6 B7 r# Y# ?" L+ m# {                fds.SaveState( p );. t0 `" `7 V: P8 {0 O
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding8 u. A5 R, _2 {
        }2 {5 s9 w& M7 S7 T
        // MMC5
" \+ R( ~) G) t        if( exsound_select & 0x08 ) {9 t# t. `7 |, \% L# Q6 d
                mmc5.SaveState( p );
# j7 X2 k* ^9 p  E) y& {- o% U' e; j4 `                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding+ Y. u+ h+ A) o! U" y# ]% l
        }! `' u; t' {: f" B
        // N1060 A3 p  d% ?2 X" @1 q" X
        if( exsound_select & 0x10 ) {
# h" D5 g# m# ^: n& |6 Q6 R                n106.SaveState( p );: h& m* G3 l/ p; z8 j# ~5 w
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  h- c( z4 Z4 E0 R- G5 d        }
2 m! x6 o$ i1 J2 B! U' ~        // FME70 [5 Y  x6 ?  c/ i$ |7 T9 X4 D8 [
        if( exsound_select & 0x20 ) {
, C, K* K' y+ L: C" z& W$ q                fme7.SaveState( p );
% [& N5 y( M2 s: {4 }) t4 x# O% v                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' o/ U' g, j$ V6 q& x        }. p5 ?' h6 w  m& c" `( @8 i
# y% }- Q( ^+ b3 A5 F7 j* M
#ifdef        _DEBUG! Y/ w! b9 C6 b, y: Q
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 W  O" r' O& C" u  g$ A& c% g#endif
: N$ R& b8 O+ a7 p. M. A$ j, S2 j}
4 L, m% O( J. O7 K. i& o: P* y7 r5 ?5 `& |2 ^7 x& ?
void        APU::LoadState( LPBYTE p )
; z3 V% n" k  n( v, G{
9 C2 D4 z! P4 f3 w' O  u3 ?        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% d, f7 K2 B6 Z$ ?+ f$ z7 n3 Q        QueueClear();
: b# f/ |; r" ]3 A' s) K
" q! b- D; N+ u  {        internal.LoadState( p );- D# ~+ M* N" Y3 p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 ^% P, \6 h3 r; i3 U' S

, r6 _; W. o" O: G8 V% z  H        // VRC6; k# ^1 T& ?4 L) z+ j" Z6 C
        if( exsound_select & 0x01 ) {
1 j; Q5 ^4 v) r                vrc6.LoadState( p );" o' o, y  x6 C3 b9 Y5 S
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
1 f# ?7 g; @9 x8 U8 w2 l. I/ P        }
2 _1 j* Z8 H1 l% s- Y& Q- t  q2 ?, H% o        // VRC7 (not support)
2 {2 P( k* ]3 f9 p* B5 o/ L        if( exsound_select & 0x02 ) {
9 ]& l" y: @' |, s                vrc7.LoadState( p );
+ m5 Z# _8 L1 t+ ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding- a$ Y* V8 W) |3 j2 [% g& S8 M1 i# P
        }
* L# K7 M0 Z6 d        // FDS5 T; c3 [! O* S4 ]5 r
        if( exsound_select & 0x04 ) {$ ~2 M; r) N1 n1 C6 a# @! `4 C
                fds.LoadState( p );! V& N2 }' B/ M( R
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
( e5 a# P: e; \, v( s        }
2 g$ T5 j9 _8 H. v1 |$ U) }4 W7 f% m        // MMC57 N) Y- y* D: v( u3 m' F2 N
        if( exsound_select & 0x08 ) {
4 ^9 P& Z; _  p% O                mmc5.LoadState( p );4 m$ B7 u; J8 x9 T  n
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 G$ n0 T8 u0 w: \        }$ e3 @) v$ n/ s  L% g' R
        // N106
  X- n  U) h7 R* g% ]: {) ~        if( exsound_select & 0x10 ) {* s1 r& J% J; k; p% l+ A
                n106.LoadState( p );
) `5 i4 _8 c4 c! p, V( `                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding$ x  N! {" y8 ]% X* V$ E
        }
+ B2 B" V# ?: F' h2 G$ B7 z9 b        // FME7
6 u4 w8 ^! G, f( ?* R+ ?+ x        if( exsound_select & 0x20 ) {
$ \: {! l9 R. P; j3 ~4 ^( c# X0 y                fme7.LoadState( p );) B2 M- r! ?. @) A# Z' G
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: O) c; O% h3 |- y9 E; ^; L4 n
        }6 w2 X4 V3 l8 s5 k7 A8 \
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 0 `8 S) R& e4 Z* R3 S3 I
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
0 t3 T! ?# N2 H5 S, z* \感激不尽~~

+ ]: s( U1 P; m: }) T恩 我對模擬器不是很有研究,: j. O) F" D8 h% c: ?: B* |/ x
雖然要了解源碼內容,可能不是很困難,
' P$ }* f  o# ^3 j! I不過還是要花時間,個人目前蠻忙碌的。
7 x4 k6 V& K8 E4 @8 \/ R9 w" W
給你一個朋友的MSN,你可以跟他討論看看,6 X4 h! I" p" ?" r
他本身是程式設計師,也對FC模擬器很有興趣。
' J8 a! Q0 F; e; l+ H9 C
+ u! Q8 T5 ]1 l% }. H+ G# y' JMSN我就PM到你的信箱了。; b* S8 {! t- E
8 A  }0 E! X5 C9 V* X% K
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
9 X3 s% o2 b( H" k+ z3 `呵…… 谢过团长大人~~

$ E; q! E+ f! L# V! [; e3 B2 }6 @" M, g" R5 l
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 * q$ A& ~# Y  g3 S! Z% Y
团长的朋友都是神,那团长就是神的boss。
+ t3 C* |4 |, ?7 B9 ?/ n
哈 不敢當,我只是個平凡人,
; b0 W% s( C7 C$ {4 h8 _% r) ?要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
& }( M! _$ Q" m  c+ G. OZYH* {2 R0 O, |, m- ^" \
QQ:414734306
1 i6 I( |0 t. ^- R" X0 |6 iMail:zyh-01@126.com
$ G3 s  N0 q2 G, B* e. q2 n
9 U; y' d6 N0 Y9 k) a- K, Y' [他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 \- y7 o9 X: E; o. P  q( I再次对团长大人和悠悠哥的无私帮助表示感谢~~
0 H* t5 i' b$ D- M$ r
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-2-19 06:26 , Processed in 1.119140 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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