EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( x' h/ C/ m9 P楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
) \5 O! F7 P9 }( A# e这里有相应的模拟器源码,就当送给大侠了~~. ?4 R" H) v4 Z* z4 Y% G
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 $ n; L0 K1 A2 i* j7 v% X
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* T2 s6 k  W# k9 K楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 i* w3 L) ]4 v, ]6 @. R这里有相应的模拟器源码,就当送给大侠 ...
) f5 i6 O5 R1 P" n" d* K" U) r
聲音部分(Audoi Process Unit = APU):' V: s8 y$ P/ N6 ?4 I' i# B8 z& X
.\NES\APU.cpp
) \* Y  t3 E$ T* U  V.\NES\APU.h0 c5 K3 Z5 h6 K" K/ I" L  f* P

; w6 s% N. C% W" ?# q5 }6 e8 o0 k' D+ X2 ]# Z- t& G
影像處理部份(Picture Processing Unit = PPU):
2 Q5 [) E7 Q$ y+ x/ A.\NES\PPU.cpp
* o& C( z% C9 M.\NES\PPU.h( @, q. J0 T8 A
) k3 z. v+ I3 O. v% q% v
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:9 n2 p- C+ B/ u6 g; u
(由于很多专用术语和算法机理都不明白,所以看不大懂……)1 _% U" a+ r! U9 z7 i
//////////////////////////////////////////////////////////////////////////. n6 G- R/ i) Z/ w2 W' {+ c+ Q
//                                                                      //% Z) |9 r$ |1 H* }& Q
//      NES APU core                                                    //
& U) `9 `. @* [% p9 {( i//                                                           Norix      //7 A6 Z7 l/ L- |9 f
//                                               written     2002/06/27 //
7 e3 E2 t+ L3 i//                                               last modify ----/--/-- //* d, l" U4 u" w9 U0 B# U
//////////////////////////////////////////////////////////////////////////" L6 V0 x( T" j7 v+ |9 X
#include "DebugOut.h"$ j! T9 K: n& X# t  q# W: T
#include "App.h"
6 x* f+ r5 X* e7 l* G) L( @8 M0 o#include "Config.h"
/ g/ D8 ?$ {$ H% c# ]  X, ]- K9 s# k- C
5 u" E$ D7 v, r: g#include "nes.h"
+ J' O  v" f4 _) \3 f1 W#include "mmu.h"* h$ b. b2 e) I# _; w1 H( l
#include "cpu.h"* h0 e4 W  [* Z& a5 ^/ e
#include "ppu.h"+ o1 Y" d0 j# B. x7 f4 ?. [  A8 F8 ?
#include "rom.h"
" a( V8 ~( c( o, c& a' E0 L#include "apu.h"1 z0 \! n) n$ s( a/ P7 [

) C# N, i) F* {// Volume adjust1 P% I+ H2 }! }# v+ O) e2 l6 V
// Internal sounds. `. ?8 {6 H0 ~1 P
#define        RECTANGLE_VOL        (0x0F0)' \6 O* ~; P( M
#define        TRIANGLE_VOL        (0x130)  W* I7 Z5 Y' o6 ^0 S) m  K
#define        NOISE_VOL        (0x0C0)# C; I( u( M3 T+ U) G
#define        DPCM_VOL        (0x0F0)) P8 V5 Q' x: y2 h
// Extra sounds
9 A, i2 k* a; x% ]4 {* A9 q. A& R#define        VRC6_VOL        (0x0F0)
. P& R- R8 o1 [- H  g#define        VRC7_VOL        (0x130)
% e% m4 D6 r8 L: ]$ D#define        FDS_VOL                (0x0F0): J7 m% d1 m) C8 N* @  q# ^
#define        MMC5_VOL        (0x0F0)
8 a: [1 S# P# P! R( G, `#define        N106_VOL        (0x088)! l+ m. g2 C' i' D' M& `/ c
#define        FME7_VOL        (0x130)
, Z) w: E+ N9 G; I
* {- y- O7 `7 V1 u- H' XAPU::APU( NES* parent )/ W  _& y: [3 J7 X+ m
{
( ^& F9 n% }9 a( b+ T! S( f        exsound_select = 0;
( Z% U5 @" P4 k: @' B" _1 J7 t  \- f1 i, I( x! e% p
        nes = parent;+ ]/ c9 l9 x: L
        internal.SetParent( parent );
8 F: T3 A% F% g8 t! p" M9 q
/ ], e1 z* o- Q3 r$ B9 b        last_data = last_diff = 0;
% T' Y" P3 n4 C$ N. {- V; ^( x2 S+ m+ _9 I
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );' q) R: o6 t& D+ k( r2 [9 Z

1 s7 |# k1 I' Z$ D8 l" m9 @        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );5 t& @1 f" S# q* P5 q7 X8 V5 W* [* Q
        ZEROMEMORY( &queue, sizeof(queue) );
9 W8 T% ^" i: R9 H' n9 @: x        ZEROMEMORY( &exqueue, sizeof(exqueue) );' `. z! a, R. p, d7 w

/ L+ s3 o* N# z  n. J/ o7 h, a; U. S        for( INT i = 0; i < 16; i++ ) {
' \5 G0 O4 o) }* a                m_bMute = TRUE;
& l  [( I5 ]7 S  J3 a- `. P) ]        }
2 ]* p/ b8 u. H/ R/ K}
$ |% t- a5 n: n/ B1 y+ P: e! K( ?) ]! R. W: ?
APU::~APU()6 A5 D  N# a' e! s- \
{
" D  h, H5 M9 j8 e  @}- ?4 _1 O& d( X1 @6 s/ J( S1 ?, M
4 T% A: W2 U6 W/ X6 k' ^8 g
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
4 o3 p7 T6 X" B: A" N{
/ ~; f5 `6 T9 E* A  u& l: S        queue.data[queue.wrptr].time = writetime;
7 N4 x2 ^% |! ]  e4 f: e, I( ~/ h        queue.data[queue.wrptr].addr = addr;
( c1 T* o* ?7 T, \6 ?; E/ ]9 z4 N        queue.data[queue.wrptr].data = data;
8 ^2 ]: g! h& |4 g        queue.wrptr++;
9 }  q7 U1 V0 p  Q6 Y# y  A3 u        queue.wrptr&=QUEUE_LENGTH-1;
7 z" D9 K- ]2 c0 S) j9 p        if( queue.wrptr == queue.rdptr ) {3 [4 K+ X5 ^( _5 z
                DEBUGOUT( "queue overflow.\n" );
+ _3 A/ O8 x9 s4 s1 o        }0 G& t  V6 c9 _" i& _
}
- D0 w1 W+ a$ Z# J5 I3 K8 U! N/ z. e% f7 [0 H- @1 U2 t
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 x  g& U) X2 |/ ?5 M
{- L9 u* G! @9 \6 {$ S
        if( queue.wrptr == queue.rdptr ) {
! W& m* \+ Z/ }6 O% P                return        FALSE;* c+ X8 p5 n# R4 J9 j" b
        }! C, }# F1 x8 \& v- @/ ]/ d9 _2 T
        if( queue.data[queue.rdptr].time <= writetime ) {
  w) z& r2 b0 W2 Y7 \( u1 [                ret = queue.data[queue.rdptr];
/ T' N3 e$ B) `& d# @' V                queue.rdptr++;
# w: g# u. @* I0 E                queue.rdptr&=QUEUE_LENGTH-1;1 W. i: @# I+ p7 i: L
                return        TRUE;8 A, e1 [+ ~1 A) _2 b
        }/ O9 S9 S/ Q3 w
        return        FALSE;
# \. r7 z/ w. f+ Q8 ^5 e. k* o$ O$ c}
& O, T" Z  B! V% h6 X4 t* [& J
" [( O$ |, N( m# x! [void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ). _3 P  D% B+ v( e& I. J
{8 P* W- Q: L5 |
        exqueue.data[exqueue.wrptr].time = writetime;
% U7 f2 I' u4 L6 e: `" d        exqueue.data[exqueue.wrptr].addr = addr;5 |# `  M0 x* y2 I
        exqueue.data[exqueue.wrptr].data = data;
3 ?" m0 U# }7 `3 N* D* V, t        exqueue.wrptr++;
1 U, }7 {6 b8 H- `- l5 @        exqueue.wrptr&=QUEUE_LENGTH-1;
% m$ @# l1 d/ b  }/ W: ]        if( exqueue.wrptr == exqueue.rdptr ) {
9 I8 `  H2 O: l5 h& B                DEBUGOUT( "exqueue overflow.\n" );
3 F3 F3 i" S. q/ G) t        }# ~6 S8 F# I% w
}$ B7 G6 E& J* I

% r9 U0 B& e0 q- B( Q5 zBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )# ?# p, S. a( P- ]  ?9 g4 B, |
{
3 Q, B! e7 \# K2 v        if( exqueue.wrptr == exqueue.rdptr ) {
$ o3 t* B% r9 b2 y. ~! m                return        FALSE;
; p7 _" G# L! h% v; v6 j        }6 J7 c& r; q7 g/ [: ]" q
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {3 \9 C2 d: O2 v& w
                ret = exqueue.data[exqueue.rdptr];
- S8 b' v" H2 u8 I+ k; Q. ]                exqueue.rdptr++;' S0 A: q' Q- x6 L9 T2 {. x
                exqueue.rdptr&=QUEUE_LENGTH-1;( l2 l% R5 M- H" Z5 u% W
                return        TRUE;1 F2 Q7 E8 ^6 m* y
        }
3 K, N; m  J2 T, n9 C, H        return        FALSE;) X4 V# z) x7 A8 {) |7 R! d
}! ]+ O7 P" F' y, o( v/ z* u3 F

1 J& U6 }# ]" w  G# `+ E! Cvoid        APU::QueueClear()
' {: \' X" L" U) O{* d, [/ M' g# f
        ZEROMEMORY( &queue, sizeof(queue) );5 b# U+ n5 O; a. A% y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );6 }" S) K9 I9 G  C$ O
}* W0 ^, t' H# w1 s/ ~, x( ]' @
' I3 m* r* u. b+ l1 |
void        APU::QueueFlush()
9 C2 T" G: a: J1 i( H+ g{
' H) Y, q, a0 H! U  ]. y        while( queue.wrptr != queue.rdptr ) {% k# b2 _# ]0 W) {2 l
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; h9 e5 Z: a& D" g7 |+ l# J5 ^                queue.rdptr++;
3 p0 K. B/ F' `  I                queue.rdptr&=QUEUE_LENGTH-1;$ W9 q/ ]; r1 P4 W6 u
        }( [& K* X" P8 z( c% w
. e1 [) {! o/ [  e, W' m
        while( exqueue.wrptr != exqueue.rdptr ) {
( a; U! |* C" i5 o( E  ]1 Y" _                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
4 K0 d" g' X' w' A, x4 k                exqueue.rdptr++;
" t2 B" J5 |& n0 P/ |: @                exqueue.rdptr&=QUEUE_LENGTH-1;& N  a* H$ Y5 x# i/ p4 i3 O/ X
        }
2 e, X7 `/ n4 d, W}
- n. A+ i  s' {6 }% e9 g
1 {+ {4 H4 t6 w" x% x+ s: }: @void        APU::SoundSetup(): T1 y! `7 f# S7 ?
{
! b8 ]+ |4 S) W% A& a        FLOAT        fClock = nes->nescfg->CpuClock;# Z7 I& ]! E  K: s8 a
        INT        nRate = (INT)Config.sound.nRate;
; l! i9 [; z4 X        internal.Setup( fClock, nRate );% T5 _- f3 c7 p1 s' a, Y. P$ _
        vrc6.Setup( fClock, nRate );. O% Y/ c: o, g
        vrc7.Setup( fClock, nRate );  N( N( L1 {- o" Q9 B
        mmc5.Setup( fClock, nRate );
7 \) s0 U% P6 H8 `; k2 I        fds.Setup ( fClock, nRate );
! l' h6 ]8 {6 ]  ]3 T        n106.Setup( fClock, nRate );
* H! p6 ?1 n- j' h1 j. R0 j        fme7.Setup( fClock, nRate );
" q& \* i" _6 v7 I  @( g1 s. r}2 U% G: K, N0 t$ m1 D
% g2 L7 I" J1 u2 r$ a
void        APU::Reset()
! |5 K$ p: b: i# h, d* o{; h) d2 y/ C; p+ r) j
        ZEROMEMORY( &queue, sizeof(queue) );7 N! M. k  l% l8 t! n! i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% |+ |& n) {& N" z& b
+ a' {6 W2 P* I& B4 ]8 W        elapsed_time = 0;
* s! ]; B  N$ B/ D" P5 K* y. s; U, ^; C: f' L* a7 e/ Z
        FLOAT        fClock = nes->nescfg->CpuClock;
" H  ~( ^; b& L9 [  T        INT        nRate = (INT)Config.sound.nRate;
* ?3 b9 y5 r/ H! X7 @( l        internal.Reset( fClock, nRate );
& F* X  y6 q( u% u: s7 x1 b        vrc6.Reset( fClock, nRate );
7 F* \: x+ Z9 {; L2 A. r- ?$ u        vrc7.Reset( fClock, nRate );7 L% r: l+ z# r9 t
        mmc5.Reset( fClock, nRate );
6 k" f& {1 D/ z' N+ l        fds.Reset ( fClock, nRate );. R, g7 O; g! I5 w/ S$ R
        n106.Reset( fClock, nRate );# o$ R) S1 N+ C6 K# u
        fme7.Reset( fClock, nRate );
% \' A! T, a& F4 y/ S& _% c3 }4 ^/ y/ w$ h# x4 T- l2 z
        SoundSetup();
0 S1 E" g' B5 _* g}9 X, U% p/ T& F: H% f8 l5 y
8 W* v1 A* ]! _  ~: `! P
void        APU::SelectExSound( BYTE data )1 |, J# B  ?! b" X. ?, s* N( E
{
# z$ ^) T( @! `; `5 ^        exsound_select = data;/ ~' H) v/ i; I! L, ?8 n
}
- L2 G; C4 N+ b, `  V( T7 F, V- k9 v" C0 Q  f
BYTE        APU::Read( WORD addr )6 E3 u- b! L8 {. {% g+ Q% p
{* f2 B& j; l( u3 e
        return        internal.SyncRead( addr );
! `+ h- D$ L4 ~# n+ I}
# @# \- O  H8 i! o6 b7 |7 m0 T7 c+ C) z% i- h/ {
void        APU::Write( WORD addr, BYTE data )
) W. h+ c! K6 C- b2 A; h+ n+ F{2 M  c" ^; D2 }& B. V; d6 p
        // $4018偼VirtuaNES屌桳億乕僩
; O0 D5 f% a2 q6 v# w0 `        if( addr >= 0x4000 && addr <= 0x401F ) {) v6 f; w6 s  d2 b9 ^$ c3 s
                internal.SyncWrite( addr, data );
! X; E" V0 E# Y0 \8 M4 M5 z                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
- ~0 `1 W6 |  W0 ~        }
" Y5 [2 a1 p; X; g. b* O% e) F4 ~}
9 Y" D; n5 ?0 s$ ^7 h; t
3 @/ j0 O8 I+ k! ABYTE        APU::ExRead( WORD addr )
. r9 a' t! o7 ^) y! F9 g{
0 I2 H5 s, e! n7 z2 @' a' dBYTE        data = 0;! h# B7 v% W0 ]

/ N7 J, X) d! T  ?7 f0 s        if( exsound_select & 0x10 ) {
; q% e" h$ V$ |* y. e3 F                if( addr == 0x4800 ) {$ i# ?0 L) t% j% L$ T+ [
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 m3 }3 a* I' @8 f% p# h; ^) ?                }7 Z# w; E0 h% N" ?/ K
        }& x9 Y' D: m$ k; Y( r6 I
        if( exsound_select & 0x04 ) {; D0 h" k- w- K8 B2 s; l. M1 R
                if( addr >= 0x4040 && addr < 0x4100 ) {" y8 E1 t, ^; E- ?5 v
                        data = fds.SyncRead( addr );5 |, X8 X* N! ~1 k) d( Q
                }1 O6 V* @  ~# z# l) g" R
        }
: }4 D: M5 H5 f6 S4 k        if( exsound_select & 0x08 ) {
# v, @! l# O+ v; h5 U                if( addr >= 0x5000 && addr <= 0x5015 ) {
. O! ]' ^) `9 z0 R1 X# o& ^                        data = mmc5.SyncRead( addr );5 N0 w9 m+ ?5 M1 i+ m
                }
9 l% u3 u9 k. d+ X( h! R2 U        }
2 s- @* ?. H* z( D; s
9 }. W1 e8 b; G0 m* L# O4 `        return        data;
0 K1 ?  V0 s0 e( A% @0 B6 J4 U}9 x2 ^6 V% d* J* d$ O* J
4 |' s) f5 F  n$ N, ]+ W, c
void        APU::ExWrite( WORD addr, BYTE data )- b( b' W5 a1 x6 T! i$ O
{
# M7 Y) W. |+ `: T; S+ ?$ {        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
8 I& `3 d# G+ d! d) y' {9 H
7 _+ L9 g( T7 _% j        if( exsound_select & 0x04 ) {+ u5 @( x. J) J+ x6 ~# Z& y
                if( addr >= 0x4040 && addr < 0x4100 ) {9 @- c" h. ^6 {7 @
                        fds.SyncWrite( addr, data );+ A$ u# G! c6 V( L! @
                }7 [8 y: ?" t% j( Q6 i
        }2 C/ E% ^8 W* ?6 `$ V9 v' T

1 v$ K% m6 S/ y8 ]3 U; n* I3 m        if( exsound_select & 0x08 ) {$ D) e% \) V4 o
                if( addr >= 0x5000 && addr <= 0x5015 ) {, N+ t" u* |8 T+ A$ O& N
                        mmc5.SyncWrite( addr, data );2 M- g2 ~- U  a& ^% S$ C! H
                }
1 Z3 a/ D2 k0 H* e2 Q) \5 D+ v        }
4 t2 y7 ?# Z6 x}
. n- c( X7 B. `0 d
3 p' N+ \: {; Tvoid        APU::Sync()
& c, g) r3 b4 h4 l" Q! K/ q' [$ i( u) b{5 G$ [. T. j& l+ f
}
5 H  \: |# R/ v5 D5 F) s: Y) t- G5 T$ S9 P. b5 b
void        APU::SyncDPCM( INT cycles )
) W2 F* u8 g) l  @- W{
5 Q0 `" \% f/ H3 Z& s        internal.Sync( cycles );  b6 {' V4 q5 U5 F7 W/ L& f( u$ F

% ^2 |6 Q8 r/ p        if( exsound_select & 0x04 ) {
% F9 t9 s2 V& C7 n; v' Y3 y                fds.Sync( cycles );5 p4 f# X9 B( y/ q4 q
        }6 g( F7 W& F6 z2 c) W% f1 Y
        if( exsound_select & 0x08 ) {
1 s( S3 y% N$ n8 H6 b& z                mmc5.Sync( cycles );2 X: B) E) @7 _, \& x% x% L
        }
' L8 _6 A6 ~7 f  j' h0 [}6 U! B( h) f" i$ d& V/ {) C
1 s+ Q$ a1 N5 x
void        APU::WriteProcess( WORD addr, BYTE data )' p" l9 K3 y; y% _
{
  G) x; B' h) h: _  M        // $4018偼VirtuaNES屌桳億乕僩
5 C( H1 b$ T4 M        if( addr >= 0x4000 && addr <= 0x401F ) {- [7 g* c- G  O5 X# z* e
                internal.Write( addr, data );* ~% N$ r. o$ c1 j- c* k8 [% o
        }& C6 w( Q( q) Q* T% @. g
}
# ^8 s0 y- U$ ^( G) j! d* L3 T# H1 s2 X* r: }$ t3 S9 t
void        APU::WriteExProcess( WORD addr, BYTE data )2 q7 T7 }. [$ O) J
{( j7 m2 p5 {, e5 [) r
        if( exsound_select & 0x01 ) {4 w3 @, r8 ~/ t3 Y
                vrc6.Write( addr, data );( W" c$ D( V1 h
        }
" {# B. o( d) Z& f0 }! Q        if( exsound_select & 0x02 ) {# Z( ^, h; D6 \3 Z8 S
                vrc7.Write( addr, data );7 f0 L7 `' }; W0 G: {5 s% @* S
        }' H5 |  J7 v0 L1 n) a
        if( exsound_select & 0x04 ) {' }0 n  x- J  O- j
                fds.Write( addr, data );7 Z2 r& s7 Q& }3 u$ E9 U4 ^- }8 r" h
        }( J1 E/ C6 X" u4 z; e" I2 ^7 K0 q
        if( exsound_select & 0x08 ) {
! q/ Q, W( u( ^# {0 _3 p3 b* @                mmc5.Write( addr, data );( u0 S" B8 E7 g6 D( Z
        }: x1 L$ d3 \6 m; v* k  `' _5 H
        if( exsound_select & 0x10 ) {
) N( K: X  x0 x2 p3 a4 _9 ]                if( addr == 0x0000 ) {+ [+ s( E) m6 W+ o
                        BYTE        dummy = n106.Read( addr );1 v9 L# ^, _  e$ J0 @
                } else {
) Q  ^9 M1 y* U1 g  p1 g0 t$ D                        n106.Write( addr, data );& H4 y7 Q" T/ H( m
                }
! ]0 h5 G& T, |2 z% D        }3 y; i) U$ g" a1 Y! g
        if( exsound_select & 0x20 ) {
  v" u* q( x) M8 y" J- d$ t                fme7.Write( addr, data );# ]3 V3 W: Q% a# P. w
        }
0 `: }! K2 q! N) ^}
% y2 N( l3 J' Y# ~2 b  ]6 B! _& W2 y  q- E' D6 ]
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
2 G: G# r6 T7 y0 U) W$ W{
8 k4 T, j( s# |$ O" b7 EINT        nBits = Config.sound.nBits;
- H/ J4 @) R1 B/ `DWORD        dwLength = dwSize / (nBits/8);8 o# k( c) U/ F+ ]( b/ x$ _* c
INT        output;
! `' b& p: e& e! ^4 G4 I  ?2 NQUEUEDATA q;
$ ~( l1 E, A! U' N; t# j, _. vDWORD        writetime;
9 J; X" ?0 N' X) {7 I+ l) W6 Q' A% b3 k; L9 Z# q0 B& q
LPSHORT        pSoundBuf = m_SoundBuffer;
, w7 {$ w. L: T) @- JINT        nCcount = 0;
& c9 w( c! B# |2 \  ]" X
9 `  m2 W+ `+ v* |INT        nFilterType = Config.sound.nFilterType;8 W9 m& F$ P3 l8 y/ E; }

) R) y1 f5 S) r+ Z$ |        if( !Config.sound.bEnable ) {
/ ?; z7 [1 x. b$ r: ^8 i                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
9 r) n) V1 X) q/ K- e2 f. Q" I2 f; \! c                return;
( W8 j8 N/ z# P7 u: V' g        }8 R; i( @2 H. Y  r& b# G

2 [* N" C% D  _5 [, d3 b- e        // Volume setup. i* }6 {' i8 T+ y% m& C
        //  0:Master7 E# s# Q9 C0 O; W- r' M! X3 x
        //  1:Rectangle 1
/ V( F) Z5 }9 x8 N; x        //  2:Rectangle 2  ~" ^- q+ Q6 t4 [. A
        //  3:Triangle2 i7 ~( I: M* Q2 }6 H- @
        //  4:Noise
5 d8 B- @2 Y4 d, [; @& R        //  5:DPCM$ y) ?: \% l" F/ G! C, r* G
        //  6:VRC6
. d* |3 ~. h# `( W6 U        //  7:VRC7
5 j# s+ `: x' N5 q8 z1 J        //  8:FDS/ K& Y5 L8 Q# v# J5 m) h' N2 j
        //  9:MMC5# F2 f- S" E' W% i( y, k
        // 10:N106
' j" t8 V, S8 A  m7 `& |9 L        // 11:FME7! C3 }9 r$ l3 D! x3 G, V9 J
        INT        vol[24];
& f# B" x2 ^) K0 I5 u  F" k        BOOL*        bMute = m_bMute;! d4 |; t5 D' Z6 g+ y3 B$ l
        SHORT*        nVolume = Config.sound.nVolume;* }+ g( o; M( ?! s9 G

2 Z4 X% u6 D% r: b' \        INT        nMasterVolume = bMute[0]?nVolume[0]:0;- I* |/ a% l' m
6 R: H7 p$ v7 v- A; l' b
        // Internal" j: F3 l6 e" ]2 ]
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;: _& c( {9 S$ G% o  H- i
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;0 [2 U) O, f7 n
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 d9 U/ w% Q6 Y! S5 I1 O( u        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;4 W5 \5 M! }( ?% N, X: k
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
4 [* ^8 l: S& p$ c2 L) \
8 C9 Z% C# K7 U5 m; k  |  F        // VRC6
* q7 G5 C3 O- p) M+ l6 J0 V) ~        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  {6 [* i8 E' a3 m% ~: O: c
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;4 t9 k! {- _3 h  a6 e& C( I7 k
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 ^7 Y$ h9 |" a! b' r4 ?4 e
0 x* F8 t" H( d& D2 p; f. n8 S
        // VRC77 `0 U+ R3 a& E; V! @& N
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* r* L) c  D; \) T" L0 h
! b; _! Z. h% k& Z5 K" A        // FDS
  g0 Y4 B' n$ o: h! {& U$ O# d        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
  U( ?% |0 \+ j4 J; m$ C6 ^
  r) S& r7 J  [: m) ^- ~' Y/ A        // MMC5
1 l% S1 l# S, f, n! G+ e4 F  g        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 }# j2 r5 m( k/ X5 {        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( D! {! V/ g+ Y1 \% S  j  n
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; ^' Z1 C  \' g4 Q9 i1 Q
: r7 M( O0 R7 B- Z# ~  V
        // N106
: d% {( G, q: n: |" x5 e: g) D        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 \+ e5 J4 i! G) A7 P+ z        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 p9 J% {: ^7 @. c( `2 Z5 J) q        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 ?, z5 {" s$ }1 c        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, V  Y% C& l  u5 d/ m  ^  U
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  |  j( V( g! V: L4 j9 i  `$ A! h        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- t" T/ ]+ a- c# r$ t( w% n) i        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 |& s: Q5 {8 D/ Q        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! m# D5 f+ h: L7 C

) Y; x* z7 {0 q# g8 y7 Z; m# y        // FME7
5 e+ u- Y6 z/ H) t2 Y        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 b" o- c7 c7 w- D1 _8 c1 T# \        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ n  R3 E" K( h# v4 h        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- I4 F) K, F0 a, D; i; K* S/ i
  g) K, U, h  }/ k/ h: ^- B. D0 X//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;! N* J4 L4 x8 T" R- z, X" j
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;' B# ?1 [* h* y' j. B% q  p4 T
" D0 d, C* d; k& P
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟' K) w* k5 f7 J; j' d
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {2 O- D8 [' c$ F- Z5 F- e0 h1 y
                QueueFlush();( h: F0 h6 O1 V
        }
" s4 b0 G( ]( Y2 }& R9 D
9 j) v% {' x5 u! w0 M        while( dwLength-- ) {
6 i2 c8 C/ \, |9 J5 M                writetime = (DWORD)elapsed_time;
" u, H0 c. R( f3 n- K% w6 y( K2 E" s! Z9 \
                while( GetQueue( writetime, q ) ) {
5 p( I. g) f6 _: ?- |                        WriteProcess( q.addr, q.data );" E6 |  ^2 r" [  ~8 e/ v8 R
                }( e; t" g; e: }( O0 v0 O5 m

' p$ b/ u) I2 }- u3 ?- J/ J                while( GetExQueue( writetime, q ) ) {- ]0 k4 k" S0 W
                        WriteExProcess( q.addr, q.data );
5 n3 D6 G& J* v3 A7 K- I                }
2 t, F% n9 |1 @6 f4 C% B$ c* V: }
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME72 @: v2 s6 y( B; i* }
                output = 0;6 }) S7 K/ J8 v/ a% }
                output += internal.Process( 0 )*vol[0];/ q* e6 g- ~, u; {+ p/ Q
                output += internal.Process( 1 )*vol[1];
# g( m% N' V: e: k; Z- K                output += internal.Process( 2 )*vol[2];8 O5 c' O9 P% d; N# t
                output += internal.Process( 3 )*vol[3];
) Z8 o& O. G' j+ k                output += internal.Process( 4 )*vol[4];
7 m  h' }- p3 p+ g3 `( J# f# N! `
( _0 b* W/ A9 G) `8 ?0 o, |                if( exsound_select & 0x01 ) {
6 Y% Z) \5 _3 K4 b4 V2 }- p                        output += vrc6.Process( 0 )*vol[5];2 H% B0 U+ _/ R4 X
                        output += vrc6.Process( 1 )*vol[6];
; m# H! z; m3 [+ l1 B0 V  N- x9 D                        output += vrc6.Process( 2 )*vol[7];% s$ m! q1 T7 S4 S" z9 Z
                }. d) m) o/ c( {) r4 y7 j
                if( exsound_select & 0x02 ) {
  f9 x% G0 r, C9 r                        output += vrc7.Process( 0 )*vol[8];
' x' G: n9 M( v- I" p) X5 {2 R                }6 [: T- t4 h) v$ C
                if( exsound_select & 0x04 ) {
% ]4 k$ G' E% Z$ r3 e                        output += fds.Process( 0 )*vol[9];
" w8 b* |. D" M" O' J8 A                }  r" m& v- e, \5 C- l
                if( exsound_select & 0x08 ) {
, P# C) y6 ]8 c( n( w3 C! h                        output += mmc5.Process( 0 )*vol[10];# r, Q8 e% a( W5 l( s
                        output += mmc5.Process( 1 )*vol[11];
  E& S! j7 R( o                        output += mmc5.Process( 2 )*vol[12];2 l3 W+ \/ x0 |8 \! U
                }; c4 F0 C2 m" Q+ f# o( W1 r
                if( exsound_select & 0x10 ) {3 l- K5 E3 k- n' `6 Y8 S' d
                        output += n106.Process( 0 )*vol[13];% a( o5 [0 B0 ?9 K
                        output += n106.Process( 1 )*vol[14];
) r: \. H( K: t2 U7 e8 ?6 U2 p                        output += n106.Process( 2 )*vol[15];
3 s( G, D+ N% F                        output += n106.Process( 3 )*vol[16];) Q" R- S% u& |1 a' G5 ^  G
                        output += n106.Process( 4 )*vol[17];) C3 }, I0 b% m. O; A' m  `" g
                        output += n106.Process( 5 )*vol[18];
$ q9 J" ?, f- |' E& L, J                        output += n106.Process( 6 )*vol[19];3 P# V" f) }( S
                        output += n106.Process( 7 )*vol[20];
7 S4 h0 e" E9 R* f/ J+ L' K9 P                }; c$ ~' b: {' Y- \; _% K
                if( exsound_select & 0x20 ) {1 _1 `4 `* G- u% o+ E4 Q
                        fme7.Process( 3 );        // Envelope & Noise
6 ^( ^; F8 e: y, a& Y: O6 \                        output += fme7.Process( 0 )*vol[21];% f9 e! \% ]0 P% t* b+ ]
                        output += fme7.Process( 1 )*vol[22];. Q7 V2 l7 Z+ I* _+ M
                        output += fme7.Process( 2 )*vol[23];& d2 k0 W# N: A4 W" G% ?: x4 E) F
                }
4 n9 A8 q% O/ D" \" }6 b3 Q. Y' D
8 |, j+ y) q; g                output >>= 8;% m- e1 u. _5 A5 U/ h

/ j+ l$ V$ v. h* B! v* O% W0 i) \                if( nFilterType == 1 ) {
0 I* z/ R7 N! n9 c                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 P6 i6 y4 K7 X3 k/ N, w                        output = (lowpass_filter[0]+output)/2;6 v0 f# k! |$ H/ w5 P0 L* @: E
                        lowpass_filter[0] = output;
8 e" ~3 T8 v) _5 }' X                } else if( nFilterType == 2 ) {
- p3 F, e6 ~5 T. X5 o1 \  z/ V1 C- o                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1). P; Z: ?1 n) {7 J1 q
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: l$ u8 S5 E& J/ N1 f                        lowpass_filter[1] = lowpass_filter[0];  I+ k. i7 G. f+ y3 M* g: S
                        lowpass_filter[0] = output;
/ Z/ m- ?" z! i. P                } else if( nFilterType == 3 ) {, }: J7 @% `7 I
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)6 p7 P, X) }( V* L& }. }- T. c
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
, f! Q  C, q4 t% ?                        lowpass_filter[2] = lowpass_filter[1];
# K+ X1 n8 i' a0 ^; z9 x                        lowpass_filter[1] = lowpass_filter[0];2 f" M+ M( o# b0 E6 L
                        lowpass_filter[0] = output;- ?! ^5 q1 S" w6 [. k, e
                } else if( nFilterType == 4 ) {
9 l9 w# o$ ~' k- E3 A, g/ }                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
, I9 O. ^, R- P                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
) t* M% I2 k5 [% L( j" J                        lowpass_filter[1] = lowpass_filter[0];
9 q/ C. e  N6 W5 J. @( C                        lowpass_filter[0] = output;$ x; C* g8 e3 e* p: t6 h0 l
                }
# U5 d& `, P& F/ X  I3 V/ r# T5 |; B: i$ g+ B  X' [: H9 Z
#if        0
6 l; x7 J8 p# ^0 b. _                // DC惉暘偺僇僢僩
1 M: W# a8 \% X) c; v8 d! C- C                {
# p6 W* P" }# p0 W4 Q$ y                static double ave = 0.0, max=0.0, min=0.0;! N! x0 Y9 E- j
                double delta;1 P' w! Y- L/ G: O+ L3 Z7 d
                delta = (max-min)/32768.0;
/ W% D3 o  X7 q0 S. D+ Z                max -= delta;% u, L" U5 `+ T
                min += delta;
5 \' O1 C- |# T  H% C  i                if( output > max ) max = output;
: W1 @4 V. \( q' H                if( output < min ) min = output;
8 S( t' V8 l! [  t- l( T/ E                ave -= ave/1024.0;
, D! ~! b$ l' `( @0 q' M3 `                ave += (max+min)/2048.0;
2 S- `1 D2 \/ B. R$ E2 k                output -= (INT)ave;" `& T: g. L# {: w) r
                }
) M" _" t, I0 I3 ~# X/ z" V#endif, I, O. t9 T& i) {3 T
#if        18 w+ F) c/ l8 A. B  P& |, I: g0 f
                // DC惉暘偺僇僢僩(HPF TEST)
9 h1 S5 A% _! W; |- b                {
$ f  }6 d& l5 t$ w8 L1 ?6 `//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
, u% O- B3 p& p$ `( X. y# L                static        double        cutofftemp = (2.0*3.141592653579*40.0);. @1 s) e6 l0 M% g0 q* e
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 @- f+ y) Z; u- u( }! O* T5 q                static        double        tmp = 0.0;' T4 B6 H/ e! K" @
                double        in, out;
: Z; n2 I+ k6 s5 K8 v9 b. X  s* ?: F* K; h& s9 [0 l+ i; c
                in = (double)output;' ~' F7 T8 R7 g* @) K6 `. q
                out = (in - tmp);; P- u8 O0 f- ?" n
                tmp = tmp + cutoff * out;! g: l3 `1 F3 o' K/ Q
3 u7 g' M! G$ T+ w1 l: W3 b
                output = (INT)out;" F8 e( W7 c; Y# h
                }
! L7 z  x7 B- F$ Y9 h#endif) S, z  _/ y8 P, w* d- N- z0 k
#if        0% B2 c) A3 I4 q6 z7 {
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)2 {' ^  d# c* s* k' n; g
                {. [+ H  _7 ]4 ~  a: I
                INT        diff = abs(output-last_data);  V' ^: l. k1 r5 ~
                if( diff > 0x4000 ) {
# B" `: ?: g4 m                        output /= 4;* ]4 o4 A# ~0 O# A: p  E2 [
                } else
6 r4 s. [; m2 \$ y! h  ]! e& x9 z                if( diff > 0x3000 ) {& J* U6 R. F) Y  x1 Z- V/ {! Y
                        output /= 3;
, a: `  |) z. W( f+ e/ S                } else; z7 J" P& U6 R& i* O0 y3 y  {
                if( diff > 0x2000 ) {
/ u- R6 `* z5 K& J: U) ]7 i9 W  q                        output /= 2;: z0 }) p% J  e, [
                }* k) k% r' w$ ]- _
                last_data = output;
6 ]. F6 L4 G" |: }6 u4 j: @. j5 b9 }                }
5 G: L! t  N6 T' o4 l#endif2 g4 W) s4 u- ^5 d
                // Limit
. D: @5 [$ F3 Y6 y" U9 [                if( output > 0x7FFF ) {( S  z! W6 A1 l' d# d
                        output = 0x7FFF;! j; F7 l3 z+ S4 h+ W4 A! E
                } else if( output < -0x8000 ) {
" _- s5 d/ t9 N  s: b4 C6 R                        output = -0x8000;2 |5 W+ J. A  l3 K: o5 J% @" L0 t" h
                }+ w8 C. h# L6 X6 ]0 |

$ v  D8 d( o! X5 z8 p+ i9 s                if( nBits != 8 ) {- D. T+ Y3 A( a6 @
                        *(SHORT*)lpBuffer = (SHORT)output;
) {  u. R7 X6 Q" Y6 t! j1 H# I                        lpBuffer += sizeof(SHORT);
+ P+ c( o: t; s- ~  ^                } else {9 C( |5 ]2 O/ d! b. Q! ^8 i
                        *lpBuffer++ = (output>>8)^0x80;7 V2 v/ m+ Z# |" L' _3 p3 Q
                }
( e5 [0 X, u2 T8 q7 @+ J% ~& X$ S6 l, t% y
                if( nCcount < 0x0100 )6 S) @( R3 ]* ?: l6 g7 A& f
                        pSoundBuf[nCcount++] = (SHORT)output;
: J0 a; ~7 O" g- A
1 T+ ~' P: I+ V1 c+ u//                elapsedtime += cycle_rate;
; v1 a" g) ^9 u; ]5 R                elapsed_time += cycle_rate;
2 e9 ^1 p/ X3 `  |: M* b        }
, k' z( _$ j$ v" X& O( g. H3 b3 Y: _( r
#if        1
1 k9 x0 E% y( k* I  U. u6 N$ W        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
2 m/ z2 Q6 j/ M$ D                elapsed_time = nes->cpu->GetTotalCycles();  C! w" C9 q& W
        }2 d$ Q5 J# {" o3 V; W9 F4 h
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
  Z2 y9 D4 s6 k  s0 d, s6 H$ S1 x                elapsed_time = nes->cpu->GetTotalCycles();! W% A4 K' |' I* x6 D
        }
( {5 f. a& g* D#else, A! O7 p& n  R0 w
        elapsed_time = nes->cpu->GetTotalCycles();
# Y' q  o- D- K5 Z* d#endif0 B- i( q9 r5 Q! v. N
}1 g4 f2 w- L, {$ F
" y6 h, C0 z% u* {, J1 p, B  Z
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡), x& A/ z; s: q! _& s
INT        APU::GetChannelFrequency( INT no )- l+ ~" T$ C7 h9 [2 i
{) o. G0 `! j! r0 W
        if( !m_bMute[0] )5 }+ Y2 T- M& I, }$ h7 I1 D3 ]
                return        0;
0 v* v( A8 Z) ]: E( a( ~$ W, ]7 a3 _# b5 e
        // Internal$ G0 n( t3 Q# O: ]; l% D
        if( no < 5 ) {
! r' {  W% v  G/ @: B                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) O& _! I' O! R4 q5 z  U$ E        }
6 q8 E0 I* w0 e( r- z        // VRC6
5 h# t6 L. q- G' `2 G/ D4 E        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {" x. ?7 T7 @2 K% j; \7 l  G! `
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
/ Y; k5 f% p, Y, |        }  w( |) _) z! k, x2 M7 V( s
        // FDS1 F" u$ T# `% H3 F2 i# Z$ ^
        if( (exsound_select & 0x04) && no == 0x300 ) {
7 `$ H# @/ u! y' i8 S$ T' I* c                return        m_bMute[6]?fds.GetFreq( 0 ):0;
* z. n" L5 p4 A8 w) ]3 P$ b        }
! i$ \4 X3 r) W9 N. a) C% I9 q        // MMC5
  |5 M% |0 `! v4 K4 [        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 S9 q* I2 g; D                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 L- ^' h9 C" o- w* a
        }
$ }& P  b5 d- S* A- |6 O        // N106; N# {7 S* H9 _( z
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {! \& |5 U4 ]$ P
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
& a$ [& M4 e2 R7 T5 f        }; z$ N5 q9 h; U8 e) o
        // FME78 ]7 c" p1 E/ k" O  r" I, R# r& T$ K
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
( Q% u* x2 U+ N1 }9 j. ~& y: ?, w* V                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;- K& a; I: O$ J0 n) g& Z
        }
3 E5 k2 [& G& S6 l8 N  e4 B# ^        // VRC7
) v7 \' @: W: \        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
9 J$ [- Y7 h7 [5 m8 Q+ a2 ?                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
( ~, }5 a; A# H6 c6 @6 j; i        }( t; c) P- z! a+ K+ ]+ I7 M3 \) K5 b( t7 U
        return        0;$ ]& r0 x! A/ D8 m8 j! ]3 v
}
9 W% X: u- l+ T% p& z1 ]) t' V
6 N  t1 J3 N+ {1 X3 T+ x/ V0 {// State Save/Load
4 l: w  F0 i" ]. F* Gvoid        APU::SaveState( LPBYTE p )# z- Q3 C/ a2 D3 `% H; g+ R, j, D
{2 W9 m5 ]5 K4 l$ E) n
#ifdef        _DEBUG
1 G% L) O$ w: _. b# r. ]2 @LPBYTE        pold = p;
8 q7 ^, z; s# c#endif( D4 l7 @( T) x' c
* p/ q0 T7 g! S" d0 y& L
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
) u" A: j9 c# E; Z3 f) i! C        QueueFlush();( O5 q! A7 P* a1 {$ U' J
  u( o0 m5 S2 v; n, K
        internal.SaveState( p );1 N, [; u  j* b( d. \. b: K
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding% z9 L! G6 r* S9 u9 E# ]* K

4 X! O. T- Q% n0 F7 O  I6 t        // VRC6: ]" ^5 e6 |/ t
        if( exsound_select & 0x01 ) {6 O0 j7 ^) m7 p# |
                vrc6.SaveState( p );* M3 q: O2 i& b8 C9 Y' t' R% s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding, a1 Q0 |2 O# t4 a: E2 _1 k
        }
  W* K% f. h1 L/ `* n1 L        // VRC7 (not support)
0 D( `) ^. q5 ~- ]8 x4 `" a4 }        if( exsound_select & 0x02 ) {
, J6 N- \! L$ s2 _                vrc7.SaveState( p );
9 J: }: g' s/ Q! x: C; ^                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding% U/ ?- P7 s7 z/ P# S! J4 q
        }* Y/ Z* E$ o: u6 V' x
        // FDS
6 q- z4 ]1 P* Y        if( exsound_select & 0x04 ) {
0 e3 u4 n5 S" u& f8 @$ {4 I$ Y! `                fds.SaveState( p );
, y( ]% r" ]& u( f) n; j( q                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 Q% e$ m7 V+ k6 L        }
+ T/ L7 M0 c- [! z        // MMC5# r. v! K) K# `$ x6 w% R
        if( exsound_select & 0x08 ) {
0 I- V8 D8 A/ |& s                mmc5.SaveState( p );% e( v0 ]3 b* x& L1 ^, z# ?8 k) b
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; l4 Q* V: ]1 P0 E
        }
, P0 \7 ^, d! X% }  k        // N106& I3 k; ]+ q' W0 w
        if( exsound_select & 0x10 ) {
' r8 {2 h( V$ p2 {* R/ R) R3 o! f                n106.SaveState( p );2 Z* a$ C9 }( G% q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
' S' R& `8 l. P- E2 R* j# Q3 S9 \3 t* S        }9 h8 Y* }9 ?1 |/ P8 Q
        // FME7
' q/ H& {4 l- ~5 w        if( exsound_select & 0x20 ) {
2 q& _4 `3 d7 N1 Y                fme7.SaveState( p );
- H+ g9 K% \+ Q; O: |( ~! K                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 s6 Z% ~& x6 f! Q# W
        }
. p5 d1 p- _! X. R8 Y# X' ?) G8 ]2 _! P+ c3 n
#ifdef        _DEBUG
- \9 W- @  W2 D/ C3 ~' @DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );+ o! |. I- _) ^2 }7 x7 D6 \, ^8 X
#endif
5 ]9 @3 M  Q; i}0 R. W7 A9 E7 C' R
1 }4 r2 r5 y* O4 ^4 I
void        APU::LoadState( LPBYTE p )
& s% r4 C6 W* D* C% m3 H3 ~{0 C6 v3 ^6 x# e
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
* b+ L! Y# E' i) J        QueueClear();
8 }2 y. h' B6 v: v9 @
9 |( v+ u0 s! }! P( J7 e1 u8 B! i        internal.LoadState( p );" f5 u6 b! Z6 ~1 i5 L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* u- ]1 @6 |! i# [- q" ~4 [( J2 L4 y9 s5 |; a5 r
        // VRC6& @- @/ ^7 n  X0 T  o
        if( exsound_select & 0x01 ) {
  O! e# b4 S1 Y4 b) K$ K                vrc6.LoadState( p );
  A: m7 O9 E2 l# Z( R* m9 z. r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
: e, `+ `7 g, Q4 F* C. P1 Q5 c        }4 Y' }; K8 H/ a% p  O& G! D$ L
        // VRC7 (not support)" ^7 U" N- W- T! ^$ V2 N
        if( exsound_select & 0x02 ) {" `7 N" r  J% U" ]
                vrc7.LoadState( p );9 h0 K; q1 F+ ^$ x) D" d
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) T7 ]7 [+ M6 F& m        }
, z, {/ |: a9 [0 h' Y. Y1 ?0 }: C        // FDS
- ^$ e. b  \# C        if( exsound_select & 0x04 ) {- e2 n. h' k6 H3 h- Q
                fds.LoadState( p );
( t% w! c  B( D* S& I/ j$ ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding9 R; _% u1 U+ ]/ S
        }
1 f( |- p$ X: [) V8 F' |        // MMC5
/ J2 N( E- P" k/ X8 U: g2 l, ~        if( exsound_select & 0x08 ) {9 j! r  d# I: I0 r: q0 |
                mmc5.LoadState( p );
8 H0 @& a: O0 p9 w- I. X2 U                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; W- M' v: I& y, C
        }
- f- u2 z8 s/ C& d( F" q. s        // N106
: }. Y: H- ]' x- c+ F4 H7 _0 l- I! P        if( exsound_select & 0x10 ) {
8 I( _7 g( B2 d- I( P+ h                n106.LoadState( p );
3 `- i# l' [' s3 ^                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding0 m$ d  N. [$ D" M$ \
        }
$ P& _) P! v6 Z" h6 ?, |        // FME76 P1 Y) e0 c- t1 n7 [% Y
        if( exsound_select & 0x20 ) {
6 _4 u0 t' L) h1 h                fme7.LoadState( p );
0 v$ G3 q5 S) P! \5 D                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 l4 s, x0 S; p/ N
        }* j& A7 u9 X1 @! o8 `2 @% W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 * L4 Z) q* T; L0 C/ Z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
; [2 [' s, W* X) e! S5 {感激不尽~~
! h) n) l+ Z9 m1 ]! _
恩 我對模擬器不是很有研究,
# h3 }- G: w5 Z  I) L雖然要了解源碼內容,可能不是很困難,  R7 D8 \6 O9 G9 u* B3 I
不過還是要花時間,個人目前蠻忙碌的。
5 m1 C* K+ U7 d" t6 u! t; y6 F0 q5 E4 O& k8 E+ I7 o9 @/ y
給你一個朋友的MSN,你可以跟他討論看看,
, O) X! `0 Q. r# [9 A他本身是程式設計師,也對FC模擬器很有興趣。
% {$ Z4 S3 w: R+ H" `1 R5 K9 Z
9 G  a/ j0 o5 U1 v8 ~MSN我就PM到你的信箱了。
; U, r  p& Z# w4 [' U) h
2 ]8 b3 `: B8 K+ |# n$ Z6 p希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
3 r$ M- K5 w- U4 ]" n6 Q, f0 X$ _$ Q7 h呵…… 谢过团长大人~~
" @- U8 @7 z7 s; c
% l0 m3 S% E) I5 b. z
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
! ~- g0 j  v0 X+ Y8 O# q7 ?团长的朋友都是神,那团长就是神的boss。
' Y' f% |1 L/ l) Y
哈 不敢當,我只是個平凡人,
1 X" M! b9 O5 F' i要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙3 s0 V# w4 j$ K6 h% P& q0 R0 a0 y' j3 x6 l
ZYH# i* t& z. j7 @. O4 R6 x4 v7 H# u
QQ:4147343069 q: B, r" h; t  B  a
Mail:zyh-01@126.com0 @, {1 p+ Q% A  B% n) l0 W) X
) l# S: o( E/ b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 # ?* d. B+ u/ @  \3 A7 j) e" {
再次对团长大人和悠悠哥的无私帮助表示感谢~~
: G. w0 s9 R! \/ ?
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-18 16:53 , Processed in 1.123047 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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