EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。8 I1 H  y9 ^5 s8 ^1 Y
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 R$ I% V) X3 f% X8 l& F
这里有相应的模拟器源码,就当送给大侠了~~* M6 ~# J1 ?! W* b* R
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 & O4 L+ O& M4 W! v% S1 J# m. K
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。7 J' R* c, u. F+ Z6 H! \
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
( R% m8 W) M6 X; Z( Z$ ~. D这里有相应的模拟器源码,就当送给大侠 ...
4 ^+ P1 v% ]8 a+ e3 c
聲音部分(Audoi Process Unit = APU):
; [# }( x' D. U4 @$ v.\NES\APU.cpp0 t5 B! ~) k# L' [# }; t
.\NES\APU.h( K/ U# D$ ?) t& Q- `
& A$ K5 W6 W3 x' h# v/ Y
$ B; W% }6 h$ l; ]& |+ H
影像處理部份(Picture Processing Unit = PPU):% G' W( {& x2 J" P6 Q' \
.\NES\PPU.cpp
( [7 p# [$ y8 Z* t" K.\NES\PPU.h! q/ E2 J- {* T; d4 t, M

2 @9 s& F1 I" Z" Q! f如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; K! I9 E/ `) e3 e0 K8 b2 i
(由于很多专用术语和算法机理都不明白,所以看不大懂……)) ^8 ^4 Z1 Q7 q( L( E/ O9 ]: E' ^5 U
//////////////////////////////////////////////////////////////////////////7 r& |5 m$ d/ R: w1 c0 \% k5 \
//                                                                      //0 F3 x2 S8 o! E9 b7 D  c
//      NES APU core                                                    //
1 J: p/ L+ \4 T//                                                           Norix      //% O7 F! v" G& a, \2 _
//                                               written     2002/06/27 //5 s* L7 R' A+ N) }. @" d* @# {& O: r8 v
//                                               last modify ----/--/-- //
4 [  K4 a: \" A/ @//////////////////////////////////////////////////////////////////////////" e! M$ I# F$ ]' G! e1 q, _
#include "DebugOut.h"
/ w4 F' m  ]2 m% j8 u6 @' q#include "App.h"! d9 U  I! p* E; I& E: [4 z
#include "Config.h"  G! f# }3 f3 y7 _6 I
$ s7 f1 e' d% _: |" X* K
#include "nes.h"
* A' c. W5 ~" R' z#include "mmu.h"5 r/ ?' _- m6 y9 H; ?4 p- p+ k
#include "cpu.h"
; \* n7 V, }% z# J+ n& a2 C7 y# s#include "ppu.h"
) z( {4 L, W5 B* R+ i" _#include "rom.h"
: d0 K( u5 Z- M6 [& }, N#include "apu.h"
& a2 F" L% L# j$ X  z, @+ K/ v7 w- V5 \* D9 e" w8 ~  P: Q6 u
// Volume adjust
. b$ h! A) D9 @" P* y// Internal sounds- v& Y% n1 W; O8 C  V: A: j
#define        RECTANGLE_VOL        (0x0F0)
) D/ S7 r$ F2 l( R' U* F#define        TRIANGLE_VOL        (0x130)
: m- e: v" @  h) o# S, A$ Q#define        NOISE_VOL        (0x0C0)
- N2 Y  G! U% s. q#define        DPCM_VOL        (0x0F0)
0 L  f. k. t. R+ V: h- K// Extra sounds
7 p3 H8 a* e1 H) h8 V#define        VRC6_VOL        (0x0F0)8 s2 u" u2 A" [! d! P* ~
#define        VRC7_VOL        (0x130)4 M: g8 w9 s, n) \+ v
#define        FDS_VOL                (0x0F0)
  f& v3 m7 F  Z( \* o0 Q! _#define        MMC5_VOL        (0x0F0)& i  f' _- F1 w  N% L% p6 [
#define        N106_VOL        (0x088)
; q2 X- e5 s' l" d0 J6 G#define        FME7_VOL        (0x130)
. I; F6 E' Z7 N5 r+ n2 W( V
- _* U( F/ r- b9 ~& IAPU::APU( NES* parent )" e, [) w/ T! C! L7 b# R3 ]9 c
{
. P9 k% o# Q7 F4 w* q5 y1 r        exsound_select = 0;
! Q3 Y; W$ W7 C- l# f$ \, J8 `5 m1 _( U# F7 @: j- b$ r" e4 R( g
        nes = parent;
' w, K9 }0 F6 S, V% f; Q0 f        internal.SetParent( parent );8 d& R% b/ s% C7 k  K) i  G0 G- o
* ~( s8 p) S/ K$ t  o* A( L
        last_data = last_diff = 0;) X2 e' q/ D+ r

7 {% ~3 O% L1 F: E+ y        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
) \! k, A8 w$ A9 l$ Z0 o! h! E
' v# e5 A) S& S) H7 D1 D9 S  B! D, V        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );4 `9 u% `) v7 a8 D/ c& T
        ZEROMEMORY( &queue, sizeof(queue) );
8 s) s; `$ e# F! R) S) M3 a        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 v  R+ r% M* z+ b$ Q- |! w
; Q# a5 `2 N( N8 K7 Y* P6 t
        for( INT i = 0; i < 16; i++ ) {
8 ^% f4 \" }8 x. x7 r# H& v1 ]                m_bMute = TRUE;; ^7 X4 _" r& a& f7 a
        }0 H/ k( N$ i/ O  i6 `1 k% v* V
}2 [# S; Z- Q' q0 E/ o

, l6 M5 g7 u8 b  J# q4 oAPU::~APU()+ O  t5 n4 Y( l
{
. P. S: W( \( R& s( D, u}
. Z' h! U8 w$ t9 Z' N$ r, b. {
0 N2 V+ S1 a. n( n: O( v4 M9 Bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
/ d9 h' O0 N7 u, M# J{
1 i( x* `' E2 W) a/ D1 [8 ?        queue.data[queue.wrptr].time = writetime;
  ~% K6 |* i- u  ?' M& U0 D        queue.data[queue.wrptr].addr = addr;
( Z2 f( L: \2 Z) X        queue.data[queue.wrptr].data = data;
& H9 C+ \, o* {* U* H        queue.wrptr++;) p% B8 {* q# G" e* ]
        queue.wrptr&=QUEUE_LENGTH-1;
6 C; }5 }" M- J. ]1 e        if( queue.wrptr == queue.rdptr ) {8 t3 p, X8 Q: ?0 |0 k
                DEBUGOUT( "queue overflow.\n" );
- t& K& j. I1 V$ h0 c  m        }
5 z3 J2 {4 m: s: n  L3 I7 P}( O  p+ K7 j# O! ?

% @" \. }8 o7 s7 }. U# qBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )1 o, [8 G  \6 h2 B, W7 a* h
{
0 h( {! ?8 o1 r+ W! R( `5 a        if( queue.wrptr == queue.rdptr ) {
( y' ?5 K3 D/ g                return        FALSE;6 i$ [# c2 ~, e. F
        }! I" L$ M  ^& `$ o
        if( queue.data[queue.rdptr].time <= writetime ) {+ ^7 o9 a$ k+ _, n  `
                ret = queue.data[queue.rdptr];
# O# V" J# L2 ~2 p  p                queue.rdptr++;
5 h; X9 {1 C! @9 Y9 Q6 b; _/ U                queue.rdptr&=QUEUE_LENGTH-1;! C! A7 \& ]4 ~) U
                return        TRUE;
# p7 g7 a) x/ r! @6 R        }
( S1 J$ k4 D3 f( A2 Q1 {        return        FALSE;9 a! h$ A' g5 Q/ v1 y; E: }& W! l
}% n0 M4 s$ X: B( @; Z
" _& [4 P! u2 J# I8 O+ F
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )2 m2 W  Y& [5 B0 T; l
{+ ]/ b, V& _4 P3 i  g9 u$ z
        exqueue.data[exqueue.wrptr].time = writetime;- f3 |. Q7 X# S; r: M  a0 E, U
        exqueue.data[exqueue.wrptr].addr = addr;
) }+ m1 O" \9 N/ c" Q        exqueue.data[exqueue.wrptr].data = data;7 m) U% y- T3 O8 u$ X, ?% e+ \
        exqueue.wrptr++;. z: ?" [( L- P
        exqueue.wrptr&=QUEUE_LENGTH-1;5 L- u% V2 O& x& U  t! R2 s5 F
        if( exqueue.wrptr == exqueue.rdptr ) {
4 ^  c5 O. N5 v! S- v; U                DEBUGOUT( "exqueue overflow.\n" );# v0 Z8 P* l0 z! `
        }* `5 X# R3 W: }1 D5 `5 Q: }) z; p
}
5 o1 N1 O' ^3 b' ?0 q8 S5 d. \7 h4 a
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )7 z( U4 g1 U- ^
{
0 N8 z# r+ V3 B        if( exqueue.wrptr == exqueue.rdptr ) {- ~9 ~( _7 u- x
                return        FALSE;
4 i: K5 l* u" I/ N$ p( _7 ~$ ^        }
( u- L% v1 U9 ~0 u# L3 C6 d6 x( {6 b        if( exqueue.data[exqueue.rdptr].time <= writetime ) {! S0 [) s9 V: t/ x5 J
                ret = exqueue.data[exqueue.rdptr];
1 G& e$ R+ d( _5 U8 W1 X! F- e                exqueue.rdptr++;
8 X1 ?( V' e8 P                exqueue.rdptr&=QUEUE_LENGTH-1;
0 Y% i, l% c1 x2 a: f                return        TRUE;
: z5 _" H8 u0 w* v; U) F        }" H, T3 h7 q5 y, c' `
        return        FALSE;. p/ K9 S$ ~2 K  n! |
}
& n  x8 [) y, G3 b# I; X* h3 W" o* \7 i4 G
void        APU::QueueClear()' _/ H8 k# F2 u/ \9 Y' N
{
$ c6 I6 A4 @" W/ U9 c- m& S        ZEROMEMORY( &queue, sizeof(queue) );
7 d& f; h4 }9 _7 |( ^/ I! M' g        ZEROMEMORY( &exqueue, sizeof(exqueue) );
$ m, K% @2 u; E% Q0 M" g}
/ q" f% x6 Z  C7 z$ e: k# X/ R: }( ~8 A# ~# Y2 c
void        APU::QueueFlush()
  {& [& z( Z+ M$ q9 Z{
5 l' O' j; Z: J. z; z% Y0 u( i: X) b& Q5 m        while( queue.wrptr != queue.rdptr ) {7 Z0 ?6 a+ T9 O- e, ]  s9 }: @
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );6 \6 h& N) B  z1 O( a' K0 T
                queue.rdptr++;
0 i/ J# X" M6 ?4 s                queue.rdptr&=QUEUE_LENGTH-1;
6 `: x) s8 x& F+ Q        }
7 k. a9 z: Z8 r* B' }% g2 m' s- ?. }, X+ q' `2 ]0 `$ R6 s
        while( exqueue.wrptr != exqueue.rdptr ) {: g4 ^4 G0 ^: u  ]+ W
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 m/ {5 f. [. c$ o) E- p% L9 k
                exqueue.rdptr++;( [: Q; N3 m. R1 Y
                exqueue.rdptr&=QUEUE_LENGTH-1;+ E( F5 [( N6 H, p4 k" O  c
        }
9 k+ G# ?/ q& b2 E9 R; M" x$ k}6 j; W0 V6 S' |" R

6 Q# N+ L! U3 `3 O  m, P' f: dvoid        APU::SoundSetup()
) _% p/ W) o* s5 F{
9 Q5 n5 B7 |" g  A        FLOAT        fClock = nes->nescfg->CpuClock;
; w& J5 y  r# p1 x4 B% u        INT        nRate = (INT)Config.sound.nRate;: L  Y7 u2 `7 v: F, n. N$ M
        internal.Setup( fClock, nRate );6 T- E* }4 l4 m$ s6 K0 C( u6 a- B
        vrc6.Setup( fClock, nRate );/ K6 D. _- }0 P
        vrc7.Setup( fClock, nRate );; c; n; K' u6 p' z9 e0 u2 g9 {% {4 l
        mmc5.Setup( fClock, nRate );
4 f: Y6 ^5 Q( a, }; R* P0 c) v        fds.Setup ( fClock, nRate );
1 ~- t; I6 }# k6 _! ]# C        n106.Setup( fClock, nRate );
4 P( _  ?! L; O: g! d        fme7.Setup( fClock, nRate );; t' s( g, }8 Z% l3 @' [* s7 f
}
7 P8 N7 E* |# o. `2 b$ `7 E2 c! y
void        APU::Reset()
7 x# R5 {- y9 a{0 V* ~! \* q! J) I, B- ^
        ZEROMEMORY( &queue, sizeof(queue) );" _. {; S; y' t9 g4 k  I+ p  `# _
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 E) P% X; o# F# |% z" Q! P8 ^4 j8 Q3 K
        elapsed_time = 0;7 O% b3 ]; `' F1 [3 L3 B) R; ]
0 n; y  w- F4 [4 a
        FLOAT        fClock = nes->nescfg->CpuClock;& X. A# q2 |0 k4 [& \
        INT        nRate = (INT)Config.sound.nRate;
. L+ R' [" f' f! T3 f        internal.Reset( fClock, nRate );( g* _  X: ~0 A2 u) H$ ~5 k5 S
        vrc6.Reset( fClock, nRate );
1 Z& l2 a( g* W9 V, H: _$ S" U- }+ p        vrc7.Reset( fClock, nRate );, p% m# X2 j' b
        mmc5.Reset( fClock, nRate );, P$ ^: g6 v" {
        fds.Reset ( fClock, nRate );0 @6 m/ J0 g$ V, R
        n106.Reset( fClock, nRate );6 O3 ^7 p: j; f1 N4 t. z
        fme7.Reset( fClock, nRate );
8 X3 m$ `% v2 y& U3 p: z
; b8 J3 F: H" m        SoundSetup();
7 N4 m! Y9 @0 I2 |' C6 g0 `' ~& H}8 q$ g* n( x8 {+ L4 n7 t1 h% m
8 w1 {+ E: q9 z7 O
void        APU::SelectExSound( BYTE data )
! G) }/ l4 f  _+ w; ]{8 J! s* g5 w0 C
        exsound_select = data;0 q$ O, R, H8 a  P# X
}0 P+ i- s& P( R$ p) D, k7 m

2 L" E' Z! R$ v. }) l4 g1 yBYTE        APU::Read( WORD addr )8 ]; u* h6 W. Z' x: L1 f
{! R" J6 ^7 H0 t0 h
        return        internal.SyncRead( addr );* ~. t, x- G$ j- F
}5 v0 n+ n2 v; y) |; g; o0 u

/ U# t% i1 r1 z# Vvoid        APU::Write( WORD addr, BYTE data )
) s/ x- k% M( b5 f$ d& Y* I9 C{
: N' z; _* l" l4 ?4 |" p        // $4018偼VirtuaNES屌桳億乕僩3 F# x3 H$ _: k
        if( addr >= 0x4000 && addr <= 0x401F ) {8 _- S8 n/ u/ ?3 _6 c! l6 K1 R
                internal.SyncWrite( addr, data );3 a& U) B& s4 A
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' X! S. Y9 y8 f" c        }* i1 e$ y/ |: \9 a
}8 R. w) W3 A, v+ e1 c( ?
6 N7 d( n" |: @6 P2 o
BYTE        APU::ExRead( WORD addr )
$ [' m( n. P6 b$ g{9 C( h6 i: ]  H2 A8 K, E
BYTE        data = 0;8 r* [6 {; ^/ U/ i

, {# ~. u) s. M4 f1 O        if( exsound_select & 0x10 ) {1 |: e1 r, [8 m) U% u! V2 r
                if( addr == 0x4800 ) {( h; H# i  t) w. Y& |
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
& y4 @/ ]% v" @. M& A* }' {& V                }' l& _3 A$ ~0 e, B% y! `6 t0 f
        }
5 I/ {2 G; i0 L9 y: D5 \( W  _        if( exsound_select & 0x04 ) {8 h" M+ O" d, X! J
                if( addr >= 0x4040 && addr < 0x4100 ) {
8 i% g+ z( O5 d+ x. V                        data = fds.SyncRead( addr );. i2 ?( \8 o- y8 V( {3 t
                }$ S' i  P1 _/ Z& y
        }
0 z9 H- b2 b2 R- m4 M4 t% D        if( exsound_select & 0x08 ) {7 W8 @$ {7 V8 |/ k# G4 t8 I$ G
                if( addr >= 0x5000 && addr <= 0x5015 ) {
) v, {- w4 Z8 d" ~2 m" o5 J7 e& \                        data = mmc5.SyncRead( addr );4 \" \( r6 p5 _% g8 ^" d
                }0 f6 C9 c+ D! P! M* m$ ^, g
        }
5 i2 Y( r1 n; f8 n1 H% E2 w$ O
1 C$ `# N3 Q8 v! [% ]        return        data;# v: W( d; W3 K) X4 D
}, Z8 z2 z; W4 E9 `
4 H0 u  f3 S2 B  j
void        APU::ExWrite( WORD addr, BYTE data )
1 e2 G6 u& X7 U- l: n) a- k3 t{
3 E6 G, \' @/ j" H7 c8 W        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );& \! a" [' z, V
" N# x) ~( }. K( ?- }6 V* E3 t
        if( exsound_select & 0x04 ) {
7 G  {, b% i1 t# u( {: d2 q                if( addr >= 0x4040 && addr < 0x4100 ) {5 B$ P( q" ~+ X. i1 H: U
                        fds.SyncWrite( addr, data );
) O2 R4 \( ]5 R$ G                }" v. g: s" r6 |0 _
        }
1 g; i8 T6 @0 l6 P+ Z& z! u+ P2 ]; q# v6 S# `) m/ i
        if( exsound_select & 0x08 ) {. {0 H6 j5 w: t% p$ r% U0 f% U9 E
                if( addr >= 0x5000 && addr <= 0x5015 ) {6 v  q# l7 s. S" V3 }" y, ~
                        mmc5.SyncWrite( addr, data );" f2 u9 Q6 t. [" Q9 r. t
                }, Z2 J. _  D* R9 t4 n( d
        }
6 R" f0 E( L/ R2 k}" ]" w* ^. G) k! B, F
6 U' ~: a- z: X. J1 v
void        APU::Sync()
7 ^. D8 j) o) \6 Q: E{+ d5 a$ B5 a  m! S4 ?
}7 a- J3 ~) {! }5 j/ K9 t: [) T

# |: z) K* o$ F8 M2 svoid        APU::SyncDPCM( INT cycles )" \- ?7 W+ R$ _
{
, C3 `# g4 L# [: j% ~! g0 o        internal.Sync( cycles );
; P. B0 p/ W3 ]0 m
1 k" o' F' d. b        if( exsound_select & 0x04 ) {0 u: T# k$ ~% L9 f) [* E4 U5 O( t
                fds.Sync( cycles );  e0 x3 P' O9 Z& u
        }
& \( j" v2 |1 z4 T" O" B! Q3 w        if( exsound_select & 0x08 ) {
5 M& u3 T  ]0 K" R0 C( Z                mmc5.Sync( cycles );
* R9 Y+ G. ^! Q6 ?& y, D2 p        }
4 ?- i) J, O0 g2 i) y: C# y) I' ~' f' L}
: I' ~$ w0 K! s, h/ N! Q
2 h% Z: O$ Y) }0 kvoid        APU::WriteProcess( WORD addr, BYTE data )) Y4 W8 @' D" Y5 ~
{
) F4 S6 ]% h. E        // $4018偼VirtuaNES屌桳億乕僩
) E( A& Q6 i$ a  H8 ?& L; H# F        if( addr >= 0x4000 && addr <= 0x401F ) {
9 M! v0 R! r- w) T5 [                internal.Write( addr, data );& Y) Y- ~3 I& i) K
        }0 D1 K& P$ \( r# `- G% z
}
% w. H5 J6 h* ^+ ^( ]0 h% O- G4 k$ ^3 P) c
void        APU::WriteExProcess( WORD addr, BYTE data )
% m7 n) j- Y. o4 V0 M8 H) G* q4 n3 _% D{
6 ~9 y" i1 s4 E5 i# R        if( exsound_select & 0x01 ) {
8 ]. `; W5 L2 \; b# Q                vrc6.Write( addr, data );
9 @& R& c- e+ \4 B        }! t, ?! W5 M; c: Z/ T8 J
        if( exsound_select & 0x02 ) {
+ `# G0 z' C; N                vrc7.Write( addr, data );- y) w% C1 |2 g- \
        }& {. v( v* K2 a7 b# i$ t- w
        if( exsound_select & 0x04 ) {, @" |- O  e9 q, E
                fds.Write( addr, data );
$ z0 K/ I" t" \% M        }. Z8 H4 D# }9 R7 q6 k: Y2 ~
        if( exsound_select & 0x08 ) {
& M; J% \3 z5 P" I, S- L/ `! I                mmc5.Write( addr, data );
- q- |8 [* a7 Q. c        }
; ?0 y$ \& V$ r: @1 a. o* u! @        if( exsound_select & 0x10 ) {
! ]/ ~% v, j( {6 c# V9 k                if( addr == 0x0000 ) {
! [5 {4 s! V9 h                        BYTE        dummy = n106.Read( addr );% h# N. N% }# \$ k1 c
                } else {
, n) L8 o  }8 }                        n106.Write( addr, data );; ^9 {4 ~6 S2 I+ e' t6 e7 g* W3 K
                }
) r1 ~; D8 v, _1 K$ J( g  a$ J        }
2 w" ]+ u: f( @$ J+ t* p$ L        if( exsound_select & 0x20 ) {
& I3 n2 l0 }% ^8 o$ |2 r4 c                fme7.Write( addr, data );
( C/ j7 y0 y' i9 D8 O        }. t' J5 y2 g7 ]% W3 d7 p
}
6 U6 L- g! Q3 n0 {% i6 _1 y5 H" q$ @, i1 P9 D& |" N* d; _( o
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
; v8 h' v" _$ X{
  y9 s* f2 Z5 v2 Z+ B8 [! MINT        nBits = Config.sound.nBits;
' _& o& W0 O! {. E. m9 bDWORD        dwLength = dwSize / (nBits/8);
% C; V' H( O! y  @5 p6 `INT        output;: j9 c  N9 o, A$ v# k4 `
QUEUEDATA q;- b/ r% X  R7 ~$ r! }& }7 N
DWORD        writetime;
1 {# g7 _5 \( i. e$ e% ]8 Q1 X  X4 o6 b
LPSHORT        pSoundBuf = m_SoundBuffer;
. {5 P) N6 J9 x: U0 q; ]INT        nCcount = 0;
& ?/ Q' n6 U' e  |) f. b! x4 J3 R4 H* E
INT        nFilterType = Config.sound.nFilterType;* _4 e* A9 \. ]' y$ v% _( c
" u" E) I/ x: k4 F3 x3 l9 p+ n
        if( !Config.sound.bEnable ) {. q% x" h: u, I5 J+ r( v: m
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
: Q4 `% f# J) J# k3 w( N, L# k3 h                return;
9 O5 Y1 ]; y* D* `8 b        }6 q& X; S  g5 a4 o, I  q5 [* x

; g, j; d9 Z! L% G2 w        // Volume setup$ u" Y) P3 ~& @; V
        //  0:Master5 e! }6 M. C6 R% o& I
        //  1:Rectangle 1
4 t( M* y& |- H! f; _6 D' U        //  2:Rectangle 2
* N# q0 a0 _/ a; K1 r( M. N        //  3:Triangle
0 t/ p1 J3 r  x* X9 S6 b% k        //  4:Noise8 `  a% H9 \$ R: j
        //  5:DPCM0 x% i# U% I. p8 @/ O) a. d
        //  6:VRC6$ i3 _: v2 s( ~# E  `
        //  7:VRC7
- M' a% A- R: m+ j' h2 M+ v5 z" w# X        //  8:FDS
0 s$ y7 e4 |$ x9 W        //  9:MMC5
" B% ~4 N4 ~/ U! W  e: {& n" G# ^; _        // 10:N1064 ]/ x( G+ {7 F% h1 q' K
        // 11:FME7
3 R1 y' K9 F% |2 N        INT        vol[24];
% e4 y$ h) j; n/ h+ j: M        BOOL*        bMute = m_bMute;
5 r4 x3 Z! f4 J1 ?6 Z& K+ c3 w        SHORT*        nVolume = Config.sound.nVolume;- F1 c, G5 C! S$ w# [0 e

1 f" q" d: V! ]8 E, c8 A& A        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
5 C2 C1 M( j2 x3 r. l% x2 s
5 R; a+ ]9 p1 x% V6 w2 s; b        // Internal
. y$ m7 X5 Z' N) t4 t: S        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; |) _- P. b7 y/ r9 ~4 d+ L; V
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
! R/ T  w8 h" }( {        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 i8 ^6 g9 D. H- ^        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
/ N0 j( K' a( {  T7 [3 w        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 M, m2 u+ t; B6 E$ W# I& K2 n, M0 F( x9 p* r
        // VRC6
, K7 R$ d8 W+ y/ g) q% d$ X5 B        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' b; I6 }6 }$ w2 O* x  X        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
* J4 @$ d' p0 g4 D+ c  q1 h5 P        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;, P( K, \) o6 U  w7 ]* W
- k# A2 |9 d& n3 S$ O
        // VRC7
, }# W  c1 P, w* h8 O        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;  H$ E% f! M7 v! ]3 W

- e- K' s* C: {        // FDS. z* N# J. ^* v1 k& x: v8 i
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# p9 n$ U9 x$ H: c7 a
( X5 w/ `1 W( H8 e# T        // MMC5
% _* s8 q* A$ \6 z$ A; w8 W        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;5 n* p5 s$ D' o5 }: \
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  u( y# u. `3 N& ?% M% `        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 A' b+ A8 h* A
  f9 m9 w9 a7 X8 A5 L" s  ~& Z9 X
        // N1068 ~' v3 n, A4 ~8 g) e0 y
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 b( B$ ?* i( o1 D  ]$ B! P
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 R0 h% a6 p" k1 z$ A( Y' i* p        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" j5 b" C0 Y. u8 m' p- G
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( s0 i9 Y# O* e- F6 C        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% _9 z* t' q% ]        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 g4 O) C4 J9 I0 B1 M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 x, d. k% T3 s# f, Y8 }
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% ^/ B4 c( `, i  Q6 J! q/ W2 k7 V% F6 G9 o4 |1 j* z9 u, ?
        // FME75 s9 v: c5 t/ U; i
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& ^; k" |8 a+ n! w: l        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* q! A* D* o6 q' ~% S        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. Q$ y5 Q: V8 z! Z/ G6 B4 e1 H
/ V7 {# w0 S* q//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;. l  f, T. S& h( l1 @* J
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
  x' t# S; Z- b5 B7 f0 }) k; m: @- b. c
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟, Q$ v  ~2 \8 M6 x5 @8 h, U) q5 j
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {$ e$ `2 a9 N, R1 Y
                QueueFlush();5 l5 `& B4 ?3 r. ?9 G' ^3 J4 \% U* e
        }" k# u* d4 H# I( V3 `* R, d
$ n: }5 Y2 G& q% Y- C
        while( dwLength-- ) {
! O3 w- i- N) k                writetime = (DWORD)elapsed_time;3 p8 y/ e& k. f7 k( l) S1 r3 R

* i7 A1 {7 B5 n; J                while( GetQueue( writetime, q ) ) {
' x: k! g# e9 H: l$ o* z0 Q                        WriteProcess( q.addr, q.data );
# L/ E9 v0 `" u+ h                }
- _, v4 m) x2 v3 \  U* M- b; m
7 ~6 N" B. B6 {; J6 t$ N; K                while( GetExQueue( writetime, q ) ) {5 `, N2 S8 T2 K% {6 Z
                        WriteExProcess( q.addr, q.data );" D9 L1 c+ G2 F) Z" t: d: E
                }9 O% q9 f- a/ X  x0 K+ }% u
+ J" a3 N! n4 a5 D2 O+ A" e7 o
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7" K% L: [% Q9 k* P
                output = 0;
: e1 J' ]2 r3 b* r9 p                output += internal.Process( 0 )*vol[0];. q5 r* y" J3 r2 u; j3 @- ~
                output += internal.Process( 1 )*vol[1];
5 p: v2 ?4 t) F  t  g8 k                output += internal.Process( 2 )*vol[2];
/ D! p) D  i+ i" s# ]( Y) |                output += internal.Process( 3 )*vol[3];, r; A  ]0 H7 p9 R
                output += internal.Process( 4 )*vol[4];1 }* C: }% Q2 h9 u) T2 E( Q* ~
# ^# ]4 D4 Z& x! A1 p# t, O$ V
                if( exsound_select & 0x01 ) {& H& j( y. E# E0 g* ]$ g
                        output += vrc6.Process( 0 )*vol[5];
0 h, W( h& C" p$ |6 L                        output += vrc6.Process( 1 )*vol[6];
7 `2 `8 q" [5 Y: {  F& Q/ n                        output += vrc6.Process( 2 )*vol[7];
2 n' }, [+ B9 x4 ~- ?2 f                }; [  G; E3 S7 O4 p$ B
                if( exsound_select & 0x02 ) {' v- ~8 f2 t* q4 b
                        output += vrc7.Process( 0 )*vol[8];1 d, F7 v* h5 p$ {6 l
                }
. `+ H; l/ R* C2 g- ]                if( exsound_select & 0x04 ) {5 O2 ]  c, R/ \, z& ]
                        output += fds.Process( 0 )*vol[9];
' y8 v8 S  G+ X& G5 \                }
% l* X: T) U- ^. A9 I; ~. W5 s                if( exsound_select & 0x08 ) {
! |* G+ |( v: K                        output += mmc5.Process( 0 )*vol[10];
/ \: Y5 G5 r8 W7 a- i                        output += mmc5.Process( 1 )*vol[11];: J6 n7 D* W  ^0 n9 l6 e* o
                        output += mmc5.Process( 2 )*vol[12];- a0 N+ o: ~9 h& @% Y, H
                }) ]2 Y% _9 F8 u! @
                if( exsound_select & 0x10 ) {- |% N% H$ [' s9 ~- w
                        output += n106.Process( 0 )*vol[13];. Q! J- m  o  i- r' e: ^: J3 d
                        output += n106.Process( 1 )*vol[14];: \! r3 y8 b8 p4 _( Z+ r- \( H
                        output += n106.Process( 2 )*vol[15];$ g6 x: k. x/ h) Y
                        output += n106.Process( 3 )*vol[16];
, e) X9 ?3 [  B$ w: z& I" @  [; E+ I                        output += n106.Process( 4 )*vol[17];+ X* @5 ~* e; `/ f
                        output += n106.Process( 5 )*vol[18];2 N) h2 f/ d, L8 x9 [
                        output += n106.Process( 6 )*vol[19];
! H/ L/ r' k6 }: o# U                        output += n106.Process( 7 )*vol[20];) B  E% U! S: a2 C% H% A
                }
0 i/ }6 S* F* V( L4 C8 E% i' q                if( exsound_select & 0x20 ) {8 P! a# y9 X( P# b
                        fme7.Process( 3 );        // Envelope & Noise
# M( A) E- y4 m2 G7 \                        output += fme7.Process( 0 )*vol[21];3 F$ b8 o* n7 B* U" {( q1 V4 ]
                        output += fme7.Process( 1 )*vol[22];/ j. X0 ^5 j; ]3 [
                        output += fme7.Process( 2 )*vol[23];" M$ o% f9 k. ?8 i# ?- H
                }
' r& j# V8 l% O& Q% ]) e4 ], H+ P& O5 e* B5 s- d: T7 m. S
                output >>= 8;- b9 d- l. @2 P# N% f; {
- {$ ]7 N( N  E% T% _0 z) w
                if( nFilterType == 1 ) {; {1 K7 L4 k; ?% U) ]/ }* ]
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)4 ~  [# J& h5 I0 V  l
                        output = (lowpass_filter[0]+output)/2;
  W7 T1 e+ u& j5 R8 P+ a                        lowpass_filter[0] = output;9 f8 M5 A% n. \# ~$ j, A
                } else if( nFilterType == 2 ) {
1 w0 k5 ~2 E+ W5 U2 R                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)4 H4 x- u5 [  X5 D
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;5 l- h3 r2 Q9 v- [, M
                        lowpass_filter[1] = lowpass_filter[0];
$ q' J  j: i% T: |0 s                        lowpass_filter[0] = output;/ a0 Y: q# w' `( Q& P
                } else if( nFilterType == 3 ) {
  b$ c9 G6 ^5 s! z& P                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 `# w' N7 D. H5 D: @( ~6 S                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
/ c- F* A( z- M  w$ t3 a                        lowpass_filter[2] = lowpass_filter[1];
# o! ?/ N, k4 ?* n8 Z5 w) b+ w9 L                        lowpass_filter[1] = lowpass_filter[0];
* Q6 {$ H0 ?9 |6 p$ _4 q% [! {                        lowpass_filter[0] = output;" Q" `' ^* h" S7 y
                } else if( nFilterType == 4 ) {3 d  ]! g& P+ M" U
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)# J% i: z, R) t+ v( z& L
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
, Y6 }2 h+ N( n" K7 i                        lowpass_filter[1] = lowpass_filter[0];, x) e% W* e! c5 L
                        lowpass_filter[0] = output;
& P9 E1 `' ?4 c                }
1 C4 j# X  ~5 \) P$ ]7 G4 m# B" v, X' Z# G* C% C# e5 u
#if        09 S% E* |& R5 \: H
                // DC惉暘偺僇僢僩
& Y% ?( q" N4 O3 L, y' C                {
+ t' R& G6 S6 d; p; d6 ]8 f+ o                static double ave = 0.0, max=0.0, min=0.0;" m* N+ Z9 l0 o0 Y7 ^. ]$ ^7 x
                double delta;& F* x: Q, Z& b3 R
                delta = (max-min)/32768.0;' V3 L* g, @# i; A
                max -= delta;
  \4 D/ b' H7 G7 W, N5 i- M                min += delta;7 `3 k0 f* h' v7 R1 L# Q7 K
                if( output > max ) max = output;) C8 c7 l: C  @
                if( output < min ) min = output;& D4 d4 Z$ F9 @4 I
                ave -= ave/1024.0;
) p( [5 r* a$ n- _, r                ave += (max+min)/2048.0;
2 f. y) z$ V3 [  b                output -= (INT)ave;
2 l( G+ v# b! Y0 X5 t# ]                }9 X3 W: s( K8 V: R8 K  Z( G$ ~
#endif
. K6 z% A- q: |4 q# s#if        1
: e6 h0 n' U. O$ J                // DC惉暘偺僇僢僩(HPF TEST), {/ P$ U1 W! Q7 o; m: S: n
                {2 t" P: i- E: C: a1 K9 @3 e
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);' D7 ~+ J- i# i; Z
                static        double        cutofftemp = (2.0*3.141592653579*40.0);- l1 h3 d6 V, a2 J: c
                double        cutoff = cutofftemp/(double)Config.sound.nRate;' U2 E, u7 G- N( t8 X
                static        double        tmp = 0.0;
4 c. e: E0 W3 U1 b# T0 z7 _                double        in, out;
: q6 P, G! j  h" d- n! Z3 h8 h; _5 A  i
                in = (double)output;9 R/ c0 r% d$ J, }0 ]6 i5 {
                out = (in - tmp);
7 n  C% c9 `# B& O, p                tmp = tmp + cutoff * out;
1 t5 N) G2 g% `0 N& w& M: F; {2 x# h: I
                output = (INT)out;6 R+ S0 _( D$ b) l6 T$ }/ E1 ^1 K
                }
& \" k* e+ i3 p( W( O+ `" t#endif/ {' I  b5 [  t) f6 ?3 s& q/ z' a
#if        0
. u) v+ g! p, J0 a) b! E' T                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
' p+ b; c/ q  Y4 {: v' B                {
8 g& B$ `3 [5 e. e! H* K                INT        diff = abs(output-last_data);  p5 T+ ]2 i! r# `' v! ~& v
                if( diff > 0x4000 ) {4 }+ b; u' S9 p2 _. ~9 e/ `$ w
                        output /= 4;
( R* L! Y/ O7 h6 |; ?. Q0 q5 ~" m                } else ! R8 ~- u, F% y  m
                if( diff > 0x3000 ) {
1 `. v' l! i! g                        output /= 3;/ n' s  w% o" \, w; D1 m9 I: x' {5 b. y
                } else! [9 Z  k- I8 g# j# i1 g' F
                if( diff > 0x2000 ) {
! A5 ^1 j( N# J% t3 Y                        output /= 2;  ?2 _8 b. o  Z$ h8 }
                }+ Z5 |! I; q7 Q( X
                last_data = output;5 z/ j# `& e6 q
                }
) f$ S% ^  g' b% b! F  A#endif
* q2 A# u$ p' M% U! W3 [4 F9 T                // Limit2 C/ I# L% f! x9 h8 u1 N" l
                if( output > 0x7FFF ) {
6 G- q" A3 c/ M& M5 X. {                        output = 0x7FFF;7 X1 ^6 p! m1 O+ H& t1 {: o
                } else if( output < -0x8000 ) {5 _% X6 L: J8 i  i% P! K
                        output = -0x8000;
" I- i; P% Z% R8 a                }6 ^! p' Z  ~9 ?7 A: S3 b4 k! B; a

6 J$ H" H3 H( K& N4 v; K                if( nBits != 8 ) {6 o7 K0 ]# u2 r5 {+ H) a
                        *(SHORT*)lpBuffer = (SHORT)output;
3 s6 n! C- P( e5 r                        lpBuffer += sizeof(SHORT);/ q2 O: a# l! m  h4 C
                } else {
7 j, p. X# E6 J6 y                        *lpBuffer++ = (output>>8)^0x80;
0 P( n$ P6 F3 L  C+ u7 Q# Z$ Y                }
2 _1 @5 X/ Z* ?- `
# X" g- y( i' z+ a* ?  P& B7 m2 P8 u                if( nCcount < 0x0100 )
+ D0 S$ ?. J( @& v: o                        pSoundBuf[nCcount++] = (SHORT)output;: X: v) C% q1 i- k+ b

2 J/ }' r/ N7 i6 p+ ?# ~//                elapsedtime += cycle_rate;
6 \: x3 H( G8 }9 Y& P                elapsed_time += cycle_rate;
. ~2 i- j$ V6 ]- C9 U3 q9 Z        }
! {* T/ x8 @, p& n/ U' Y+ U. }0 z  @! F. m
#if        1
, h5 ]" }- O/ C$ k- R        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
6 B4 A. p. q1 o; f+ g                elapsed_time = nes->cpu->GetTotalCycles();2 n3 |: c" j2 u' z9 a. f
        }
8 i. c, K& J0 ~' L( {7 u8 o6 u        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {+ n2 ^% e1 M7 W( x: d9 x
                elapsed_time = nes->cpu->GetTotalCycles();
0 E" x. g) ~' p! s6 i7 A6 i" ]        }6 R8 g# ~0 |2 O0 \% t% R. |
#else3 j& {6 F$ b: I7 _! u
        elapsed_time = nes->cpu->GetTotalCycles();; m6 ~) u7 f( g5 h$ _
#endif
* u2 @' L6 P, j9 ~$ d  r  F: A}
* b( k- ~& S/ {5 Q0 O9 d" _# x/ ?( r
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 G7 ~6 T& v2 a8 wINT        APU::GetChannelFrequency( INT no )3 F# p$ c& M1 \4 F- t. S% j
{' u, {/ X7 V! ?! n; z5 I3 F
        if( !m_bMute[0] )
! P, a7 T. E$ P" M( [& \( c+ m. U                return        0;* K$ @! I/ f  S  u  U
. p: E  i$ x7 f; A2 z( d
        // Internal
3 G" U* B7 x9 @6 s/ M3 d        if( no < 5 ) {
3 L* P" t* M# X. F% D+ r0 o. c- ?                return        m_bMute[no+1]?internal.GetFreq( no ):0;
" s+ @6 j' C( Q4 q& n, k4 P' F        }6 R& @' [. L" c
        // VRC6, y) i/ Y; [1 G; H2 _  g
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 ]% S& [" Y- T4 K$ }
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
4 F1 T2 A$ Q  _$ ]5 \9 v        }2 Z3 ^  G' b; }( u, |9 N# G  V% J
        // FDS
3 z5 U/ I2 p% N" o8 `+ u- b        if( (exsound_select & 0x04) && no == 0x300 ) {) A0 {1 c6 X# K; z6 b4 ?
                return        m_bMute[6]?fds.GetFreq( 0 ):0;6 ^- U3 v' x% R  u
        }, h; h. Q: i. Z6 o  R
        // MMC5
1 K2 h8 W/ I* B: F        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
1 \. U, g: d! L+ T                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
! O. I" P: V  e4 @" E        }- |/ J# p, }5 Q  f  v8 E% a
        // N106% k1 v3 y5 I- \: V5 p) q: B
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {8 |/ z+ v+ j) H7 Z
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
# p' j4 J5 h) h, O; \5 S! X+ N! ]        }* _5 q- `$ ?1 R7 E2 D: A6 q
        // FME72 M; j4 W' B% v/ L5 D5 B
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {4 T7 N- |* g! K2 M# b) z9 E
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& o; J6 H$ n7 p7 o        }
' n$ d  P1 B) H% V; m        // VRC7
% N) E& W+ Q1 C9 K: C9 z% D- t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' p3 X: y0 p* L  u3 o
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
' H% a; j/ b+ P        }
) c" a+ R$ Q) @        return        0;
' s, x1 r" P7 H2 `* y8 F1 v4 d}% P; m8 ?" V1 @% h( Y/ J
7 j& c( m1 w6 Q$ l  S7 D" g' _
// State Save/Load
, C: U  F( M' F, ?, D& W  e: Tvoid        APU::SaveState( LPBYTE p )
2 T) G' J  a0 |' s5 q{
5 j% s* P7 A5 T2 o8 {#ifdef        _DEBUG
8 L: Z6 |  {  j2 U7 @; Q( E7 s, {% XLPBYTE        pold = p;2 j3 A: J. y! `7 z8 h, u
#endif5 V) u) p3 g; n, ^
! W# d; Q8 z& F" q$ F
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞: I$ ~. y, p; P" c# R( _6 t! B& C+ @0 ]4 p
        QueueFlush();8 n, X' H5 i2 t
/ l+ x' j( ~* ^
        internal.SaveState( p );2 T( g; ?+ I/ x* R
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" A$ t2 w+ F5 r, \' E8 N8 {3 v& L
        // VRC6
- J) n/ h$ a" f; X( u0 w        if( exsound_select & 0x01 ) {8 d9 B7 }1 Z# X4 c. e5 E
                vrc6.SaveState( p );
# W7 \: I8 ?: _2 C4 n) ?+ k                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! C9 u: o5 S  t0 |
        }
6 k% T; ~: m% S        // VRC7 (not support)
7 Q" e$ l0 T$ ?* u, }4 |        if( exsound_select & 0x02 ) {9 s" P7 z0 Y( M: w5 @
                vrc7.SaveState( p );' E) g" c* X# [$ F) K, L+ a
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- T5 r1 ^; B$ x: T        }
! `8 s* q# R6 I! \) d7 a        // FDS, C2 ^2 h( [8 \. B- M0 X
        if( exsound_select & 0x04 ) {% J( n) |5 Q. a+ U3 d8 M: s. i
                fds.SaveState( p );
8 X) U: V0 ~' O                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! V  _7 k/ G9 c' ^. a7 c
        }6 w1 @! o2 f& L+ V# S9 \5 J, T
        // MMC5
1 y% K* }  {- s$ d  l        if( exsound_select & 0x08 ) {- k0 h5 g# [, R) D% [/ b& d- D
                mmc5.SaveState( p );
. x. d* P+ h3 v                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding6 d# H9 s5 G  W9 }; O6 n4 O9 @
        }% Y& C) z1 g, {6 W
        // N106
, M. ^4 ]7 J) y( @2 I        if( exsound_select & 0x10 ) {
0 b# |! w8 G: X* K; e                n106.SaveState( p );$ i1 p) c! Y2 |) e7 I
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding$ g% W0 s1 g0 P. w% T& o, s2 e
        }2 [8 o$ `1 C! V) {% @! y/ e
        // FME7; {9 ^4 e7 @& i0 w$ _3 ~% H
        if( exsound_select & 0x20 ) {/ o' j* [9 ]& b
                fme7.SaveState( p );$ L5 T- {4 o) Q: p3 l6 d1 H
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' Q$ O. H; [" |0 n4 U2 |6 B$ M7 p
        }
: N' s6 K: m6 n0 e. G+ I+ {8 O  ^5 j% T9 H  _* Y6 s0 \9 U
#ifdef        _DEBUG/ c5 `" d9 B" {/ N* x( K% B
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );0 x& m5 Q, _! j  ^
#endif
+ h# V; x* z" O2 [' z2 @8 H5 z}! J& W+ I  q+ n; I
, p* b2 R& @# Z7 f
void        APU::LoadState( LPBYTE p )
( `6 Z. s' V% n+ J. F# v, q{5 B0 o* T. k7 ^& q7 S0 l0 T, y3 F
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ U! j. L$ @) v- w, K
        QueueClear();# V; E- ]' d0 J' _5 T. o9 _

; t/ E1 N+ g/ g% l0 b9 Z1 b& c5 h        internal.LoadState( p );1 A4 c5 Y. H4 r- E
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ Z5 B4 M" j6 R; k& Z! k: {' P% \* N! c1 E% a
        // VRC6+ Y5 _: C* X! P# C% p
        if( exsound_select & 0x01 ) {5 q8 C* H/ V! l$ {$ ^- w! V- L; c
                vrc6.LoadState( p );
8 h# V" \) w/ @; g# M                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding/ F3 j% R5 e7 l( H! k; t
        }' D) w5 a: U" @; m+ N" m
        // VRC7 (not support)
" v; t: N2 ~. B* S        if( exsound_select & 0x02 ) {3 l) g) X, N( K
                vrc7.LoadState( p );/ @) D% y4 r2 a
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. E! \' k0 G+ ^0 O6 Z        }
2 m; `6 `3 Q' N8 H" @        // FDS- }# s3 X( A- Y) w) a: g
        if( exsound_select & 0x04 ) {) N5 k. m0 A; Y, ?/ h) u% t1 H+ Q$ ^
                fds.LoadState( p );* E& A: e# i* `5 u) g" Q2 f
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! z: A5 G4 T4 r+ }/ q0 W        }* V/ s; P2 v0 i/ G+ Z
        // MMC5" X6 A+ B6 l8 S3 r
        if( exsound_select & 0x08 ) {/ Q: o5 y, ~, T# u' T* M: O
                mmc5.LoadState( p );, X9 H4 A- u) s
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
. _+ F1 O* Q/ \/ ~        }& M# Y! m4 m" g9 V
        // N106
# O- s, T1 Q. I, Q9 w. T        if( exsound_select & 0x10 ) {
1 I9 ~( d! o8 k                n106.LoadState( p );1 {# o; }9 P3 [' h
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding; j8 I# {: K4 ]3 F
        }
% l7 h+ K& @" l1 i/ k* g( d1 i" _* D        // FME7
: q$ b8 }1 b& w# O9 Y2 s/ o0 M        if( exsound_select & 0x20 ) {
# J1 U- w7 d, Q! Z4 s                fme7.LoadState( p );
0 o" O8 ]4 k4 U8 P7 g- ^                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 ~6 A# a( J+ }" F6 q9 p7 H        }
5 x+ p- B. y/ Q3 f* E+ Y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
  t: O5 C" k) ]8 O2 d. E7 [: L6 a可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。* K9 _8 |/ w# o7 i2 \
感激不尽~~

  W: M: R2 R2 T- K: u  C  K( @# b% z- T恩 我對模擬器不是很有研究,* V$ e# n" E! O+ j0 A# @
雖然要了解源碼內容,可能不是很困難,
+ [- B2 B/ k" |$ I不過還是要花時間,個人目前蠻忙碌的。
+ n! W1 d) S( J- ^8 a3 `0 V3 V
) j3 ?& J. N+ _# ^3 j5 A- C3 P& a給你一個朋友的MSN,你可以跟他討論看看,
; v. H% N2 ^2 q他本身是程式設計師,也對FC模擬器很有興趣。& y# A6 A1 U5 s) F  r1 m8 l1 o

! ?$ l/ W" Y3 y& {" gMSN我就PM到你的信箱了。$ c* R* k* E7 [; u3 n

' [3 [) ^$ X, O! V+ _- D2 X希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 " F' a5 t( [6 G" C
呵…… 谢过团长大人~~

' j. W- g: k+ R* u; j' M# o; C8 o# x" j1 \+ L3 ~$ W
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 4 O# Y$ I  [8 y8 b  s  m2 d# t+ m
团长的朋友都是神,那团长就是神的boss。

& ?& J8 H4 U( H2 v哈 不敢當,我只是個平凡人,
- {2 e" t3 `: j4 q) a  e+ k" v; R要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙5 {' X8 p' ^- l  M. c1 w
ZYH
7 o: S  X2 q, C' u0 }2 F9 AQQ:4147343067 h9 |5 x# Y2 k8 I5 O
Mail:zyh-01@126.com- v/ X& i; T) n, @! A/ a; P- r4 g
+ p" ?+ m  |! @& b
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
, M, C' }+ g% n$ U" M( F0 ^再次对团长大人和悠悠哥的无私帮助表示感谢~~

  G$ x% {! G- W不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-29 07:23 , Processed in 1.128906 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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