EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
8 f0 H+ k; Q! c+ f: p3 Q! i楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
5 c" s. c7 w( H7 e: T这里有相应的模拟器源码,就当送给大侠了~~
. Y+ y$ U2 ]8 |) H0 @6 |0 hhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 7 u4 d" z4 {! T6 w( Y; p2 r' ?2 a
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' `$ q& o9 r) S( z% F' S% G- t楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
/ f9 k' \0 P4 R这里有相应的模拟器源码,就当送给大侠 ...

1 g. O+ v0 F3 v- m  p聲音部分(Audoi Process Unit = APU):6 y  L. ]! E* m) L
.\NES\APU.cpp
0 d5 }# [) H4 a/ g$ c/ X.\NES\APU.h& J" u" n) i" f6 G" j
  r+ k+ t& j$ @" F3 H

1 r' G; x, Q5 k( \影像處理部份(Picture Processing Unit = PPU):
3 o2 O9 A3 K3 ^( f: X1 f/ ~5 d. m.\NES\PPU.cpp5 J, s, i+ e: z) F. c
.\NES\PPU.h
4 W- L1 O: v2 Q# n& z& |
2 S6 X' B( ]0 c" Z) Y4 x如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:/ K. b2 @) m0 W2 S5 p
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
" x$ I4 }6 \) A  j//////////////////////////////////////////////////////////////////////////
  @: Y: i5 R& z1 [0 F/ v5 r8 u//                                                                      //  B* E' M# i/ j* l. g! y: I2 u* f
//      NES APU core                                                    //
  I3 P: ~6 E5 e6 d1 H/ F//                                                           Norix      //0 u" ]3 I4 |1 o+ ^8 x
//                                               written     2002/06/27 //0 J% }) J3 s$ c! m
//                                               last modify ----/--/-- //- \( K# u+ l4 h! v1 R+ p
//////////////////////////////////////////////////////////////////////////" S6 J7 `# F; e" S
#include "DebugOut.h"% R% g' u) S9 v' a( @) `
#include "App.h": @, ]2 ^  }/ x2 n
#include "Config.h"
+ e- A6 v, G6 ?2 D% Q& W! h8 @) f, _
- o, Y( i( z1 k: s, O#include "nes.h"
: S% @  A$ }* r#include "mmu.h"4 T8 F+ \3 Z* A% }7 }3 H$ {6 }+ ?
#include "cpu.h"" h* N2 O- t9 o; A8 g. v7 g9 r
#include "ppu.h"5 l8 {5 m& r4 I
#include "rom.h"& i# U% U8 ?- N# O( d- S
#include "apu.h"
8 b. g  q. ^/ O7 M* n: S1 D4 r0 Z  ]0 Z  K
// Volume adjust
0 z/ L8 E9 y- {// Internal sounds9 e( O4 _8 I  [, @
#define        RECTANGLE_VOL        (0x0F0)
( N; k0 O* G& M$ H/ j#define        TRIANGLE_VOL        (0x130)% O, i! N* j, T2 L1 K
#define        NOISE_VOL        (0x0C0)
$ E! d! @% B. k0 J  N#define        DPCM_VOL        (0x0F0)
( K9 ]9 k% ?1 `9 m/ ?// Extra sounds
; t  V8 m+ z6 N- s#define        VRC6_VOL        (0x0F0); \9 c- G" q0 Q$ Z+ U. B7 P; N
#define        VRC7_VOL        (0x130)% B; R5 h+ v" t8 l& Z: ^) V
#define        FDS_VOL                (0x0F0)) F, P% O4 I5 n& a7 w
#define        MMC5_VOL        (0x0F0)
4 |7 N' y/ {3 P8 e# p#define        N106_VOL        (0x088)' u6 ?# l7 U" H1 m7 z* K% I
#define        FME7_VOL        (0x130)3 Z& V* X* `, K; k5 [# J
3 ]; n/ t7 O  W) D2 j8 x/ G
APU::APU( NES* parent )0 Z8 i6 i3 l& Y8 F+ f
{7 q8 S/ b7 _) ?
        exsound_select = 0;
3 Z! L: N# ]0 H0 t+ L
$ ^7 f3 D  M* X8 Z# j! \% p3 i8 `        nes = parent;) c0 d+ f1 O3 u) t  Y% A/ s5 t
        internal.SetParent( parent );
+ ]3 L& Z( F" ]# S2 ?: ]. [
' z3 _6 |4 C. I, ?3 Z2 Q        last_data = last_diff = 0;" `" o# F9 l, J5 \. c( z  ^

- G* P. `1 X0 ^& P        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );& F2 \( K5 w( u- d6 p; \+ s+ R

% Q( z$ c& o% d$ _' S% M        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
8 T* u( l2 d/ K7 S& a        ZEROMEMORY( &queue, sizeof(queue) );' h1 P2 [% b5 P# D- w' M. ^
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! I1 j% `1 N  l+ K  I+ V/ k2 |
8 V9 l% I9 ]  l% G" d( {$ V- z" U        for( INT i = 0; i < 16; i++ ) {
+ U# W& _* T1 @4 t                m_bMute = TRUE;
$ b  X  L! i; Y* g        }: C% f: V- i1 m9 G4 I  p4 e, {
}/ ?) s; K2 \8 l% y( i+ ^

6 h4 F0 S/ \. a' u1 T9 ]APU::~APU()4 ~+ h% v! _- [: O7 [, @
{% V4 Z2 y6 X% f! G4 b  O: b, u
}9 o. O+ I/ ?6 y; e* d' ^& D
4 `" D  _. d! i# }/ G( h
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' @0 w1 ]6 T/ l# k. {- d  Q{
5 h( l$ ^5 y/ a7 I$ O0 X9 D        queue.data[queue.wrptr].time = writetime;
) r3 z/ M. g5 m8 U, u! i/ C        queue.data[queue.wrptr].addr = addr;
) V: H/ \+ _2 c, z) y5 M        queue.data[queue.wrptr].data = data;
. n" E# T% d- ]& D        queue.wrptr++;1 [+ q1 n+ {8 x; r7 \. r3 F3 r9 H4 J
        queue.wrptr&=QUEUE_LENGTH-1;9 K: x4 Q: c/ {% m) s! F
        if( queue.wrptr == queue.rdptr ) {
$ I% ^. H# y7 h9 g                DEBUGOUT( "queue overflow.\n" );
4 h& l% `" [- w1 z: I6 K  f; i        }
: W5 p7 V: p& k+ J3 u}
8 l+ o4 S: t! ]. v& o1 T9 r4 g. g9 i; `1 W
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret ). W) v0 ^- r) @1 t! q; D2 e
{  l8 ^1 u' j9 [! x; @3 \
        if( queue.wrptr == queue.rdptr ) {* Y/ }+ [3 m) P$ I
                return        FALSE;
/ Q$ k' W$ R( D* `5 D% F) `        }
. @- N- w7 q3 P1 ^; K  B        if( queue.data[queue.rdptr].time <= writetime ) {
! ?" u. m' a, }0 q  a                ret = queue.data[queue.rdptr];
& ]: H( V& V; A% X3 N8 h                queue.rdptr++;
7 n# k3 `5 |+ z2 J. {. j1 C' G                queue.rdptr&=QUEUE_LENGTH-1;: ]9 T; \( i: h2 r8 v- d0 X* E
                return        TRUE;- C3 n: P8 `% H8 T
        }
( ^% W5 b' g& h' H+ W4 z0 X0 u        return        FALSE;
0 x" ^, ^) ~1 ?2 c. w) y}
7 f. m/ y7 F+ Q. l7 J, Y: D8 G/ @1 [8 K
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )" o# n# A+ `4 @. l
{/ G0 j6 m0 \1 Q$ ]% F
        exqueue.data[exqueue.wrptr].time = writetime;, ?- ^- ~9 [1 H
        exqueue.data[exqueue.wrptr].addr = addr;' \% n5 |9 G* i1 V7 h) z, T5 [
        exqueue.data[exqueue.wrptr].data = data;
) p$ z/ b7 t" L! S2 l        exqueue.wrptr++;
1 y9 S0 z% Q, e+ w- |! Q' g        exqueue.wrptr&=QUEUE_LENGTH-1;
, f7 o0 m7 J2 a, k2 S4 s- y+ g        if( exqueue.wrptr == exqueue.rdptr ) {% i' ~: q( {- K( [" N" `. v' ^6 W7 }0 P
                DEBUGOUT( "exqueue overflow.\n" );! ~7 h' {7 a2 M( _$ A% M, l) G4 @
        }
1 P6 S' ?6 @5 i; }}/ O# n# G7 j) A/ u" ]4 G
: f# |* O# _1 \3 _) ^6 g) J6 F
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )/ b! O9 P' d/ G! T
{- Q8 I2 M. L( F2 h
        if( exqueue.wrptr == exqueue.rdptr ) {
1 y9 z8 E7 {; ?% {5 v5 G                return        FALSE;
/ b3 X! `' K6 S- u9 i' h. x        }
5 K8 s9 u5 n( n        if( exqueue.data[exqueue.rdptr].time <= writetime ) {9 \; i- I% _  `3 j# Z
                ret = exqueue.data[exqueue.rdptr];
; ^- P; W4 |% y  m5 {                exqueue.rdptr++;
+ A" F  L+ ^1 q( ~: ^. z4 N9 A& u                exqueue.rdptr&=QUEUE_LENGTH-1;& l# K& I9 W; e) G% c
                return        TRUE;
3 N2 u/ C+ D. i' O, D        }
3 P0 [' I$ S: l        return        FALSE;
/ l8 g; \, m5 U1 l4 d: x/ |6 k}
2 I( ~# J+ B6 W' s6 p, @1 E- P% n# O3 p; B! J8 H- `5 j" l, G: J
void        APU::QueueClear()
0 T7 [) |) F( \# o! e$ x{: z6 ]+ s, r0 \6 e
        ZEROMEMORY( &queue, sizeof(queue) );
2 i9 n* ?1 w0 h' `5 M6 i' u        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 t! M) J5 j2 R3 e( h
}8 j" y& d) A9 c0 X

( \. }: d. b& e4 L1 Kvoid        APU::QueueFlush()
/ b( o+ g! b- N4 P0 u% M{
9 A) ?* C4 G6 I  k- Q' E% m        while( queue.wrptr != queue.rdptr ) {
( s) z1 ]+ N- R3 e; |* I( Y                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );3 [5 _0 X/ q, x5 `3 W: c  U0 w. `' B
                queue.rdptr++;0 V8 l+ r' B( P! C& [
                queue.rdptr&=QUEUE_LENGTH-1;
7 e# _! ]6 G% m2 T& C        }
, p8 Y9 g  ?7 |1 f; ^4 ~# Y
- g  ]* H. }% x4 a8 B        while( exqueue.wrptr != exqueue.rdptr ) {0 @; m/ q9 a& r% r
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );. a3 W$ Q4 J+ V6 E  Y; v2 j- L
                exqueue.rdptr++;: T; b. Y" r4 z1 \! L  q8 f
                exqueue.rdptr&=QUEUE_LENGTH-1;5 o; q* n, V4 D% {
        }0 r. e1 E9 K1 r! E, n" R  R; `
}! R, x0 Z& k% s4 m; Y

. `( q! N8 E2 S; h3 o  T2 ~: }2 y" Svoid        APU::SoundSetup(): \2 q! V" `- g; S- I$ x
{+ F3 W6 p, Y7 j, O
        FLOAT        fClock = nes->nescfg->CpuClock;; u2 Y0 \% k3 [  G+ s* `, i7 j
        INT        nRate = (INT)Config.sound.nRate;/ ?$ s" ?/ @$ V4 J1 f/ u7 T3 |  L
        internal.Setup( fClock, nRate );9 b0 i0 X+ }4 J7 w4 t" |
        vrc6.Setup( fClock, nRate );0 v( I  y$ m& {- p+ t# ?
        vrc7.Setup( fClock, nRate );
$ d1 w' C, G" J6 J7 d1 Y        mmc5.Setup( fClock, nRate );9 R* d; J% s0 s
        fds.Setup ( fClock, nRate );" r) l  o- _% g
        n106.Setup( fClock, nRate );9 c2 o7 L# ?, D4 P) q. Z
        fme7.Setup( fClock, nRate );/ D* h% \& s- P: h  j
}
3 e" W5 i* P6 E2 z$ {  W+ n+ g( l, J# P& X9 a
void        APU::Reset()
6 ~! D/ O6 f3 w{
) _$ V, o) M9 b/ h1 I* y        ZEROMEMORY( &queue, sizeof(queue) );7 p/ [- @% Q0 q# k! t0 Y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: g6 q5 G0 w1 D" N0 P# I* R
6 S) R7 J& g" L: {' u0 b
        elapsed_time = 0;! v# f" l+ Q% x0 n( e. U5 V
& D4 F2 p! G4 F; [
        FLOAT        fClock = nes->nescfg->CpuClock;$ X  {7 R; O% M: V& c" B& k
        INT        nRate = (INT)Config.sound.nRate;8 _1 {5 ?: c' G: U
        internal.Reset( fClock, nRate );5 M+ b* @/ Y3 w  q# `8 ]0 _) C3 N/ T
        vrc6.Reset( fClock, nRate );) \: m+ Z$ g- O# O6 E* ~5 I% |
        vrc7.Reset( fClock, nRate );/ u$ ?1 T$ {' M+ ~. ?3 r! l
        mmc5.Reset( fClock, nRate );; E  S7 D4 K7 j/ v* H- g
        fds.Reset ( fClock, nRate );
3 W' n! c4 O  _; o; A6 v" W) X* c        n106.Reset( fClock, nRate );
2 T0 ~2 g- B* @  |  S: b4 K        fme7.Reset( fClock, nRate );' Q- b2 T) c, _3 r1 H
9 J" Q; J+ _" l* l8 n
        SoundSetup();
& o8 B2 X% W& ~8 v6 Q}
: N+ U" a8 W4 y& f
( B0 r" S- m4 Rvoid        APU::SelectExSound( BYTE data )
# {) h$ w3 F% C2 l5 R: Y- V$ {{
, c, \( _: v/ b% \. h" c        exsound_select = data;8 J: ^/ L* _: h9 f
}
! {; {9 \, {' e# ?6 \9 Z4 t1 [0 G& z# t
BYTE        APU::Read( WORD addr )
; w* X7 }8 }( G  B) ?: `3 ~{
1 O! R( ^. `' V* D        return        internal.SyncRead( addr );) h) h3 U  r2 d* i7 @0 {& l! W+ e
}
8 t" i* Y2 f6 }  P9 @
: e  N6 s/ {! D3 Z! E( Uvoid        APU::Write( WORD addr, BYTE data )
, E7 [  {: S( V: ]% p{
9 C* J, R3 P1 \2 U& ?        // $4018偼VirtuaNES屌桳億乕僩
5 \: p& e  Z0 Y        if( addr >= 0x4000 && addr <= 0x401F ) {4 o- i' c" d$ d' _( r5 V# I( j) E7 t
                internal.SyncWrite( addr, data );0 t  [: w7 c$ j# ^- p2 m: ?2 u$ X
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
9 V- S- N, M3 A  {; q, S* ~        }
1 W- ?' S! T: M3 S}' ?! r# p" n3 C) w$ k

( U% G/ o1 r0 z) p/ zBYTE        APU::ExRead( WORD addr )" y4 _4 O* P7 m4 z' K* H
{8 R- C- l6 q8 x* X1 z  A6 z
BYTE        data = 0;4 h: w( t% ?) W- a' B
9 q- J. S* |9 f- t6 X) P$ u" Z
        if( exsound_select & 0x10 ) {
1 `! i/ Q# e- ~) u1 h+ x                if( addr == 0x4800 ) {" ?, X! G+ U2 R' ~
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
7 \; j( k, p# F  h                }7 H2 \7 Z% ?& E. P. Z8 b# L7 ?6 E
        }* x% i( w7 ]( V6 i/ I: b! T
        if( exsound_select & 0x04 ) {; V  a" [  j: g
                if( addr >= 0x4040 && addr < 0x4100 ) {
2 w9 z0 W* v. w+ U5 z, J                        data = fds.SyncRead( addr );7 z$ p5 x: h' h5 [
                }, n+ i) i5 }4 B+ `
        }5 E- E6 L& v2 t; n+ H# }
        if( exsound_select & 0x08 ) {
* e; o& w2 S, G( U1 }2 t/ O                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 j: Y. O4 Q7 g7 x9 Z                        data = mmc5.SyncRead( addr );
4 Z& {$ ]/ R( i& V: O                }8 u# F# S% |6 z% u/ u9 r
        }' F. A0 B% h  @  b+ k2 U2 Z
; G7 W2 e. j) d. ]8 a
        return        data;  J, i4 e# M& a/ ?' V
}0 z5 ~3 P3 u$ ]! j: S9 p
  ^; O; \$ ]; a
void        APU::ExWrite( WORD addr, BYTE data )
4 r0 C4 o. Q$ y/ Q  X# o. a& X{
# q/ [' M" U9 Q( Q5 r        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );" u5 G, ~' T  p3 g7 Z

7 E* }& I) n8 X' }  ?6 G( M        if( exsound_select & 0x04 ) {
! u/ e, u3 {4 E% X" U                if( addr >= 0x4040 && addr < 0x4100 ) {
1 H; g2 \' F- w- ]( [2 a                        fds.SyncWrite( addr, data );
2 {7 d: y- F8 |                }) |3 x$ b6 v9 a4 I: q4 n
        }1 F$ K" `" ]- I* X+ W

" r8 O4 s8 d! l/ Q8 u# E1 w6 F        if( exsound_select & 0x08 ) {/ _0 C2 D2 H" g: P
                if( addr >= 0x5000 && addr <= 0x5015 ) {
. k6 @" k% j! i9 I# J2 I6 d                        mmc5.SyncWrite( addr, data );
- E- V+ R7 o7 }                }
1 m, W: e$ Z( P        }
0 g+ G8 ?$ g$ w+ g- O}
8 v) i- A9 \( @1 u
0 A2 V$ }7 n8 W3 |void        APU::Sync()4 V  {4 z$ t0 Y1 L) M2 D
{' U0 j: t3 y' E1 E9 C( }6 s
}, I: }) b2 W; [8 y

5 K0 h1 O7 g4 h  cvoid        APU::SyncDPCM( INT cycles ): T9 i& {7 c. {
{
9 c/ I' K$ y. @% Q        internal.Sync( cycles );
- m: w' \) R' B) \$ O' Q4 a3 \
$ f- E1 w8 d* B2 ^        if( exsound_select & 0x04 ) {! q6 `6 p& E$ f" V
                fds.Sync( cycles );
1 g- W/ V5 }: T: L4 }1 S        }2 s& j. O% S, C" v
        if( exsound_select & 0x08 ) {& Q4 m7 d) {/ W4 c
                mmc5.Sync( cycles );! L  O9 ^% {+ d5 [" J7 `: {
        }2 t: v& ~, c$ {
}1 y1 E, h) G2 u$ [+ p, j1 E

! h8 F; R4 ]( a; V( x( Xvoid        APU::WriteProcess( WORD addr, BYTE data )
6 {/ ~! ?5 b) M* r2 m9 I* ]{; ~) ]& r9 X2 g8 D+ ^& s; h
        // $4018偼VirtuaNES屌桳億乕僩
" a" @' g' n9 U! F7 H) t' l- o        if( addr >= 0x4000 && addr <= 0x401F ) {# k' _  A+ H2 U6 l6 l% A
                internal.Write( addr, data );4 W3 ?1 B4 M$ s3 V5 Z' Y3 Y- ^
        }
0 l9 M5 s( ?8 o, x/ O}
( N/ d4 V6 o, q6 C6 ~: {0 ~' }& G5 p( h+ V$ l( F
void        APU::WriteExProcess( WORD addr, BYTE data ), s+ k7 X  ~) k4 O
{, \+ R, Q/ v" i1 B* M
        if( exsound_select & 0x01 ) {
; ?8 r# N- D. H8 B0 ^- p8 \- P2 T8 H4 X, X                vrc6.Write( addr, data );
2 |/ u, N# @, \8 U* l# J4 y. _+ {        }
) U, F$ j; r1 C( R        if( exsound_select & 0x02 ) {8 z& c! L$ d* V
                vrc7.Write( addr, data );
% j2 E5 J3 v. q. J8 X+ A% v        }
0 @. W# L- E7 R+ d, `7 y& l        if( exsound_select & 0x04 ) {3 [8 e& a4 }  g3 X0 B
                fds.Write( addr, data );
5 E4 B! G7 A& {! I2 \9 t        }
, [7 T* L- _0 h. x* R( O) w        if( exsound_select & 0x08 ) {: U9 @& M9 z6 K6 @+ [4 b; x3 A
                mmc5.Write( addr, data );
( Y8 Q& p3 a7 W+ \" T5 ^" H- w2 W        }. E/ }7 t4 {+ f& g  _' A# L
        if( exsound_select & 0x10 ) {
, ]1 ~. Z3 |/ I; y4 I                if( addr == 0x0000 ) {6 ?4 \# E. [7 h8 J
                        BYTE        dummy = n106.Read( addr );6 M+ e( O6 M" ?) u$ j
                } else {3 O9 A) A! J( l, Z. Q! E
                        n106.Write( addr, data );
: Q1 B) j, V1 t; S& b& r! k/ K                }+ T5 v) \1 n/ F
        }- L( }; |8 B) p3 J, @. }, l& X
        if( exsound_select & 0x20 ) {5 w+ K+ O+ f' ~3 P
                fme7.Write( addr, data );
" Q  q, O; b( n0 y        }. w: E! O! }. H4 m* V6 a
}
& Z' {: X& I) r% g2 g0 i+ t" I
8 r) }& }; E* M. j% R) n* ~8 Gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), d% Z3 m% g0 l$ m
{
$ l' K' G6 @- Z% kINT        nBits = Config.sound.nBits;1 S# W' w3 q$ C2 h
DWORD        dwLength = dwSize / (nBits/8);2 {0 I; W* u: |1 h( l" G
INT        output;
7 m4 I) T2 L0 F- yQUEUEDATA q;
/ Z' h1 n: G) ^, R4 VDWORD        writetime;
( e) U9 S% t$ |; P$ J' p# D! i3 I$ k0 e; R
LPSHORT        pSoundBuf = m_SoundBuffer;
# Q. _7 T0 [3 w) EINT        nCcount = 0;
+ a) H- N, p, F& u  t* j: h2 ?6 T7 @/ U2 N) Y3 X" }
INT        nFilterType = Config.sound.nFilterType;( k9 w2 S  ]. W7 e; @
8 U! m. o4 m: K: m9 \+ _8 C
        if( !Config.sound.bEnable ) {0 H5 f; X; _' `. h
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );! I8 l. d3 [! i
                return;
6 j3 ^0 Y: u# F; W! G7 _        }
$ r6 e* X; M, M# a& |6 k
4 q3 X! o, l" n- a6 o1 M5 G, i/ u        // Volume setup4 e( R5 n, m; R* s. R- {! t% Z
        //  0:Master
% m. w7 f% Y0 \* S/ F- Q        //  1:Rectangle 19 ]- Q# ^9 e1 h' H% O" d0 w" K
        //  2:Rectangle 2( r8 i2 N4 h9 _5 O0 B# p6 v
        //  3:Triangle
! _: V. p' b' k( p        //  4:Noise
9 h6 N# u" f9 e  D0 {2 [        //  5:DPCM0 _. @3 j1 {1 n
        //  6:VRC6
0 N! A6 L  N# j2 L8 [. V        //  7:VRC77 q4 v2 ~/ w% N# \
        //  8:FDS
. a! q9 n* g& B7 b: g% T1 N        //  9:MMC5
+ c/ w; \; ]8 J; ]1 h        // 10:N1069 L0 Z8 ]2 X# p5 i  ]6 S+ K  |
        // 11:FME77 X  B% l) a; J
        INT        vol[24];
/ U4 g3 @" |; D5 a6 V1 {        BOOL*        bMute = m_bMute;
5 b  L/ ?7 m  C' z* _6 d' m        SHORT*        nVolume = Config.sound.nVolume;' U9 |! ^2 _9 ~: w' O' J
+ e. {9 O& x% n; D
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;6 s3 i7 X5 C. A7 @+ J% O$ ]
( B, ^, R' H5 \
        // Internal
7 i; U9 r( f" [# y        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;' Y6 R8 o  j, Z# b8 t
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;" G3 A4 [# x6 h
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;' C7 q' i" l. k# |% ~' p8 T7 _
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
, \7 _+ Q& v  `/ @1 K* V( s: H; w* d        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;+ R7 Y* G2 [: ^% l7 f+ f" [

: V) L4 U1 m" h( {        // VRC6: ]: p: @& v( l) ~: J
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) i6 q% ?4 t% b; p
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! C' {9 J1 Y: g9 {5 \! E) B& @5 c( ]
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ K. z7 C& s8 T$ C) W' I, i0 x
. R7 w8 I. o! M8 Y5 j( \3 L  h
        // VRC7$ q) C0 H3 K: u  B: E6 P
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
$ K1 n3 R' C8 A  j+ x" [: w0 b0 j' S
        // FDS1 ^2 A8 I* P6 U  h% S
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
- D/ ], A% P8 t4 [: G) Z2 ]: @7 d0 g5 W  Y, H
        // MMC59 [2 O. y: Q( o0 b; R" O; P, ?0 i
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) e  J' ]+ H5 u$ q
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. C* N. k: J. ?! Q8 g! e5 o7 n
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;' j. I# `) |% |8 \! t8 v; b8 z

1 J% @7 y* }, {% U        // N1064 ~! f7 p/ U; p- h8 Y
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% ~1 w% {3 ?3 u+ u
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" S7 l! @! N1 I& U        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 D" R" l  G4 R        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ V4 T4 B! L# U0 I7 K* \) J5 }$ s        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ G9 h2 A0 ~6 C/ i. T# G- r
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' m- d% K- d+ a& ?2 `. H
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ b4 q! E9 _+ r2 n/ C2 x7 l        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# X& T, e. C2 c6 [% b# ?8 W8 R* `2 p/ A! i4 \/ Q, E  E
        // FME7' t' W7 B2 d" b
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ N3 G9 \2 i8 d0 u: p
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 |7 P1 H; Y# q9 I; l: \        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- K0 T& m/ O% H. y
" E$ J4 }! d: z- i) ^
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
( B$ \8 K' A. A3 j- r        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
2 V" l7 _: {, l+ [# d  I! x. E/ V0 z7 ~2 n6 i' t0 o. e+ M
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
- G; M5 x5 W1 l2 P* l$ G        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# h8 @& }# ?) r  W' B6 S
                QueueFlush();
' E5 b  b$ g: e2 I+ W9 g" @1 q        }
7 l* x. V( [1 j' o+ {% @+ F2 @6 Y; ^' l# N
        while( dwLength-- ) {" q) D0 m2 c- C
                writetime = (DWORD)elapsed_time;, v- w# F+ }  }3 M$ g  F

( R  f" p4 j2 |" Z                while( GetQueue( writetime, q ) ) {
6 F+ }$ s* r/ N                        WriteProcess( q.addr, q.data );
- n( |3 H  \" x/ i8 s                }
: _& Y) r1 p7 r  O- g- p/ x  }# Q" h) ^  t
                while( GetExQueue( writetime, q ) ) {9 x4 w, K& d/ s* K2 G0 Y7 Z; B7 {
                        WriteExProcess( q.addr, q.data );. A, |) K8 v. G1 y- T+ M& {0 Y
                }; q$ ^; q0 ?+ z2 l0 L4 j

4 l1 S# J  F! z$ f( ~2 N+ {                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
" \$ u# [5 N* {, Y* D8 j- h( W9 r; b                output = 0;
( L+ T6 i! I9 X                output += internal.Process( 0 )*vol[0];
) G% E7 Z! x# H( n9 z                output += internal.Process( 1 )*vol[1];% d& a9 d* X1 K+ _  F0 E
                output += internal.Process( 2 )*vol[2];
. p" [$ U1 [7 L                output += internal.Process( 3 )*vol[3];
3 O3 `% n6 [6 j8 x# c8 V5 i" l% C7 F6 @                output += internal.Process( 4 )*vol[4];
& e; x/ U& Z" Q5 {. B
' ]+ U9 B9 V5 |                if( exsound_select & 0x01 ) {
2 G, H) V# \0 o7 T! H                        output += vrc6.Process( 0 )*vol[5];- f" F& [" W/ @& Q- r. T" i/ X
                        output += vrc6.Process( 1 )*vol[6];% \  h1 H/ Q: }% o% _
                        output += vrc6.Process( 2 )*vol[7];" B: j; R: p  Q- ]4 D1 c* y
                }" X( h. J" r, V6 \1 G  B* Q! O
                if( exsound_select & 0x02 ) {; Z" L4 g& s! i+ @
                        output += vrc7.Process( 0 )*vol[8];
& k3 k$ n  N$ D+ r8 |% W% |                }: v' N2 p; \- V, T
                if( exsound_select & 0x04 ) {7 h) a3 `/ u3 R7 f1 \
                        output += fds.Process( 0 )*vol[9];' P6 ]4 X: r* U7 K/ \
                }
! G7 j/ s5 z2 v: g% P& W7 j                if( exsound_select & 0x08 ) {! W4 Q7 o3 o; |* d' k
                        output += mmc5.Process( 0 )*vol[10];, p1 ~/ f3 z5 }% o5 x4 n$ k
                        output += mmc5.Process( 1 )*vol[11];
! d2 F* [4 ^+ {- h: ^. j; x+ _                        output += mmc5.Process( 2 )*vol[12];5 N9 D$ w( G) c$ q5 N
                }" D2 K) ^$ h/ @+ z3 O
                if( exsound_select & 0x10 ) {& F: r/ y" _, J# u( J& i
                        output += n106.Process( 0 )*vol[13];6 ~1 w# v( \* M) _% U( |# m* h
                        output += n106.Process( 1 )*vol[14];
* ^5 g$ ?1 G6 U+ m" R                        output += n106.Process( 2 )*vol[15];* Q" Y& F, S1 E; e
                        output += n106.Process( 3 )*vol[16];# O  ^" H6 }" t$ |) x& q
                        output += n106.Process( 4 )*vol[17];5 K, V7 N$ D' }; Q' W# Z. `, }
                        output += n106.Process( 5 )*vol[18];
$ Q9 I, g& ], Q4 N' |                        output += n106.Process( 6 )*vol[19];3 b2 d1 u$ s( a# z* @
                        output += n106.Process( 7 )*vol[20];7 p7 E/ g4 R: I. A
                }- _8 G1 B& a6 `2 v" i
                if( exsound_select & 0x20 ) {# B# x, _# d. {* D8 d8 f2 L
                        fme7.Process( 3 );        // Envelope & Noise
* R2 n+ F1 l0 {; U                        output += fme7.Process( 0 )*vol[21];4 S& L  _8 ~/ v8 h: ^* k
                        output += fme7.Process( 1 )*vol[22];
9 ]( j( \& s8 i) }3 E! d                        output += fme7.Process( 2 )*vol[23];
+ ~5 R' H+ z$ l  h- v                }
( T/ {5 ^" F  y# K" F5 Y
. A$ U% B+ `. K$ p1 _5 G) e                output >>= 8;0 T% j+ r+ z) b
; X: }& [5 j. q, U: a
                if( nFilterType == 1 ) {% |" M& O5 E/ L$ M& b' x* e
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
3 N) S$ Z. I6 E. T  L; W; k- \7 N& [                        output = (lowpass_filter[0]+output)/2;0 M* Q; P2 B; q% B! l4 x- y; c
                        lowpass_filter[0] = output;* k& z% z" H0 a
                } else if( nFilterType == 2 ) {
6 R6 d1 `* b- ?! Q% x5 T3 h# o                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)" E" ^1 H1 l/ a; O8 ]3 r
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
' X, G# ]* _% m8 X+ w  y7 v) v                        lowpass_filter[1] = lowpass_filter[0];
! ~# y( y7 U) C5 r1 h& |) w' d                        lowpass_filter[0] = output;
6 Y- P1 s9 M  c+ h" x) G8 F                } else if( nFilterType == 3 ) {* V1 Z% C& Z* J# i' R# P# Y
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
6 ]* [# I6 j" ~6 D) F7 Z                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
7 N* o" G+ @6 X" [                        lowpass_filter[2] = lowpass_filter[1];
/ z& o$ d, j- T! M! b) c                        lowpass_filter[1] = lowpass_filter[0];# N' @: M: U* J5 \) ^% Z& j5 z
                        lowpass_filter[0] = output;: M1 {- n4 [0 [: c, T! p1 O! d3 H
                } else if( nFilterType == 4 ) {
1 j4 n$ V* H/ s1 V                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)4 q% O% [4 N' _! X) `
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;  ?/ j( h& Z" T
                        lowpass_filter[1] = lowpass_filter[0];
" D5 v6 X% \- @9 U& Z                        lowpass_filter[0] = output;
8 j! A6 N" \" V) q3 h; u; _% ]' e                }
8 l9 K% u; t+ Q" h5 A" k; H. x" P- G- l3 S8 M  P
#if        0
6 @- z: u: C/ U( D& p4 c                // DC惉暘偺僇僢僩
% e3 J' g. x3 z$ m                {: m0 J! k1 L4 @7 l' ~! ^  z! }
                static double ave = 0.0, max=0.0, min=0.0;( \9 Q& d( r! G, H+ L- F1 }6 v9 K) u
                double delta;; c) ]( x5 ^& Q' ?
                delta = (max-min)/32768.0;
( K6 V' E% ]4 L2 ^0 r  O9 R# [                max -= delta;3 [/ z. O/ r, B3 T2 @! [& O9 R
                min += delta;
& o8 {1 D4 A8 }/ T' e: W                if( output > max ) max = output;& `# r0 ]' T; |/ |8 y) p% l
                if( output < min ) min = output;) [- H* {, ?, G5 R) b
                ave -= ave/1024.0;
7 Y9 Z" A1 l4 g$ G8 p  m. V, n$ `* y                ave += (max+min)/2048.0;% P8 F' K1 V+ r" E7 Z, s
                output -= (INT)ave;
# u5 z- l3 U1 {; W4 s                }
2 x* }# {9 s4 E' S, \. r: j4 g8 X9 s#endif6 V' g( I# H& @& J
#if        1
' u  m4 Y9 y. r3 G" s                // DC惉暘偺僇僢僩(HPF TEST)6 R3 |+ g2 s3 b/ G/ S, D
                {  _( O. X( i! b% W3 J- Y
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. y7 `) I" E5 H3 q1 a% O  F, u* A$ \
                static        double        cutofftemp = (2.0*3.141592653579*40.0);. c% R6 o2 w2 P- f! N; u7 u1 i0 r
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 y/ P  |% N1 L/ B: A! w8 v                static        double        tmp = 0.0;/ _) T9 @" U4 E. f1 w
                double        in, out;% K, [& f& J8 g+ p# }; x$ b
; T, F2 E9 v- R5 X
                in = (double)output;- ]4 }$ Z! k! U, f
                out = (in - tmp);
. p% J/ W; X3 e0 V                tmp = tmp + cutoff * out;
& b; p! A) r8 o  V. p: l- P$ a2 X$ t  Z- N) w) v1 \
                output = (INT)out;4 Z' t# f0 Q* o7 s
                }
. i) I' v' \0 D' s1 A1 j#endif+ G4 C4 D/ ^0 N* g& A
#if        0
  p5 _+ d4 r+ l                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST): }9 E6 E( S1 g2 d- e  t/ K
                {: X+ t+ v( ~! h; E
                INT        diff = abs(output-last_data);8 ~8 @( m- o6 u, ^& i" u+ c
                if( diff > 0x4000 ) {
; A. {. H# C4 G: Q7 }4 D                        output /= 4;% q( ?. X% Q& a9 _
                } else
' r& ~8 p# a- }                if( diff > 0x3000 ) {
: D; Z2 z: _, X, j4 l! s# W+ }6 L! d                        output /= 3;
% E: F& Z2 }7 f. ]                } else- v6 A. y9 G9 V# `
                if( diff > 0x2000 ) {
- {% B" G" j7 n  m+ d                        output /= 2;
9 o1 Q% |* d9 V: ]                }
' k/ {0 ~4 _. ~" ~7 C8 T/ e" ]& k                last_data = output;: }* y0 d$ l& |. c  t( B
                }
& Q+ F; Y+ [: |. i: C0 |8 W#endif
' i! r" M' Z) ]( B6 I                // Limit% m7 y& F  u: D% \- j4 K
                if( output > 0x7FFF ) {: n; d3 a% g4 h/ A- f9 U- {; u
                        output = 0x7FFF;
5 N! @/ P  y# C5 [; ?                } else if( output < -0x8000 ) {1 M$ E' ^& y: O8 O
                        output = -0x8000;
8 n2 y% a  j6 L. R  R, k4 J                }
  k/ N/ ~( W% t+ X) _% L2 W. [" ?) g
                if( nBits != 8 ) {9 f" Z7 p( U# D3 Z% ?% a
                        *(SHORT*)lpBuffer = (SHORT)output;; }; i5 s$ t) }
                        lpBuffer += sizeof(SHORT);
6 ?0 Y  o4 K0 H9 }! n9 {. Z                } else {: E' H' f' s7 B4 m! T& g" l7 s/ ^
                        *lpBuffer++ = (output>>8)^0x80;% [1 D+ D- ^( J% ?  |4 }
                }, s$ p$ f9 R3 O2 r3 O! `9 n, q
4 w  B/ Y7 J+ u
                if( nCcount < 0x0100 )) ]& V  c- C9 w% D2 x& c* E. ]
                        pSoundBuf[nCcount++] = (SHORT)output;
) Y9 V# F5 }) h
% ~2 ^  h2 H: Z) j. R8 }//                elapsedtime += cycle_rate;9 v% ], z1 N! i5 q3 _
                elapsed_time += cycle_rate;/ X5 c4 M1 r  F6 [, r
        }
6 @- H* F. _6 P  d- c7 _' _/ S4 i9 |1 l, D5 m
#if        1' W& U9 p6 L8 I: ~2 c
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
& {6 H0 q' {; f2 Q. Z                elapsed_time = nes->cpu->GetTotalCycles();
+ _. H! h. d! |- l/ t4 v        }! [" n) H2 U: p% n8 A/ P
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
7 m7 Y! y2 L3 B3 X                elapsed_time = nes->cpu->GetTotalCycles();9 g) v7 _- _/ s' w! R0 K4 C$ j
        }- k" h+ J8 h3 y; M
#else
; u% Z7 O/ A- h) s! i' }# B        elapsed_time = nes->cpu->GetTotalCycles();9 G8 Q1 {% v7 `2 m; c3 C
#endif) m+ U( }% ^: Q; E8 M. I' ~$ o
}' ]4 r' M8 K; f  g, m

5 Z1 B/ k7 w4 d// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
1 h% m7 J- F& h5 L3 GINT        APU::GetChannelFrequency( INT no )
* i% j5 M! {  G* G  I" H& s{% V( v) J8 _1 c3 i0 ]
        if( !m_bMute[0] )# u) A4 _/ M9 C: C* D- G' Z
                return        0;
- W8 j8 N8 _9 a9 g% Z
0 H1 K. B# P3 f. E/ e        // Internal
6 H. m% L7 E! V' n/ T        if( no < 5 ) {# j7 c1 U' n% ]" g+ ~/ L* h) v
                return        m_bMute[no+1]?internal.GetFreq( no ):0;' S* t0 ^6 |4 G) J2 g
        }
& f+ F$ s: j! B' |* ~        // VRC6
" ~. j9 u8 K' \9 l- {' }' P! E        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {+ F2 V( d2 G* M$ g
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;, i$ p6 o; |2 `( e) Q9 H8 b# C" X% S
        }% W9 R  g) C) i
        // FDS7 C5 H9 @! o4 \- F" N
        if( (exsound_select & 0x04) && no == 0x300 ) {7 Y3 M4 N2 f! Z, [# }# n& V* |9 r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;/ h! \% v/ j2 |! j, r' O
        }. Z" f6 i- r3 u1 L& I" x
        // MMC5( h" ^  N6 N( J; b+ r6 R
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
" Y3 [. ~" J" `# a7 u, L, G                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ ^" [  B  j: d1 `5 F, L6 @
        }+ r: ~2 [- B' d' G
        // N106
. [' `3 `9 q# h) t+ Z3 A        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
5 j1 m+ H( u. }! F                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;2 @# u! r- a$ i7 ?5 ]
        }
% l6 l  H" Q1 \* p5 A3 \& ~4 w        // FME7
2 x( a8 o, H$ `6 l. |        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
! D( _& C7 k% ?- l                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
- a5 b2 ^/ \4 j+ }( I: P. s9 I& f5 ?; h        }: I: j+ W4 Z* e  `. y8 j
        // VRC7
& |) e: a5 h$ r8 @8 Y6 H        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: N8 k; e; N. w- Q- \* U
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
9 ~+ A9 b" ], Y( Q" b        }
3 C/ [+ |+ c: E: ^) y% S) {        return        0;
' T3 P+ N0 o0 ^) ?+ s, d+ r6 H$ |2 i}
( j2 n+ d! {, O! K
+ \, V# k. q5 r% m* J// State Save/Load
$ o9 @2 j$ E. |( V3 x9 ^6 }void        APU::SaveState( LPBYTE p )
8 m; {- y6 O: l" c{* c4 g& v, T: L, c- K* X: H$ n
#ifdef        _DEBUG
" M& t, i  D) r, O- }2 rLPBYTE        pold = p;  Q* s/ R4 J; \* f
#endif
" \; T% T2 P8 m) v5 f: j5 h! m. c, R0 \* \! R6 [! ~
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞. M4 O  G1 h6 T- d5 [2 A
        QueueFlush();
3 X7 j0 y8 H% [. P8 R
+ j5 k& V4 ?) u8 x7 r9 m        internal.SaveState( p );7 x& k+ Z- J! g& x- w  T
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 R) h. k: `* }- P0 _+ ^! @! {5 H
        // VRC64 X1 y0 H) b, Z5 z" ?% i: K
        if( exsound_select & 0x01 ) {
5 w  }0 H4 x7 E3 _) w7 r                vrc6.SaveState( p );
+ |  Y& ]) |3 m7 ~6 h7 ?3 r5 W                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding9 o/ R& p0 z: f* u. n/ J7 d
        }2 E9 N" g9 W7 g' [
        // VRC7 (not support)7 j# d+ m7 E8 X4 f
        if( exsound_select & 0x02 ) {0 O; q4 J/ ^9 @% H" S! J( Q
                vrc7.SaveState( p );
  ]/ z; `2 E7 P- i  N: I                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
. Y' A& s( e- T        }4 a# g, t9 ?3 o4 I. z
        // FDS8 `7 G4 s0 W+ x4 x8 T% d
        if( exsound_select & 0x04 ) {
/ r5 r1 ^* ]7 b  i# {                fds.SaveState( p );/ n8 P- R; T3 g
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 o* _, o8 I+ |+ I0 H& w1 V+ \
        }
; J% x+ H" H  \! v& G        // MMC53 a: U+ O  q1 m# ]
        if( exsound_select & 0x08 ) {
% D9 {# \1 W0 t0 B2 J! T                mmc5.SaveState( p );
8 s. s5 U: T3 [# G" K                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& w  A8 i/ p& F        }' r, K! B2 W: Q4 s. T' ~" C9 q$ g/ ?
        // N106, L! _# P' u% B8 p# v, z
        if( exsound_select & 0x10 ) {* ~4 }& V5 U% z% y  Q" D; T
                n106.SaveState( p );
' f+ f& V& g) k1 {3 R+ l3 L! G" n, g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
6 J$ J" J) g  k        }+ P0 K% Q) p4 o: H: T0 i8 P1 K
        // FME7
. \+ w7 ]3 B+ c7 l- D. [        if( exsound_select & 0x20 ) {+ Y5 f, h9 }/ K. b) n- M' \- u
                fme7.SaveState( p );$ @7 p; @- D# n6 V, p/ \$ i
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding0 w" X# g; _0 G" }/ U/ M" O
        }
& w5 {# C6 o; z0 O' K& Q9 i* O6 q% J  `6 y. N, S9 j0 f& c: S; E
#ifdef        _DEBUG
/ P: K& h# b8 {6 e4 [DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
2 B% S% k* O* }7 W& a( O8 U8 _- _5 h6 V#endif; Z% X* h: @& s
}
* w- j8 s( q3 p6 B! l: a! P  h+ V- ?% O9 K
void        APU::LoadState( LPBYTE p )
) F* \7 U& f5 I% X7 V8 ]{
1 d* N: L/ ?- `1 {        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
/ n( Z. Q4 f; y9 O% e        QueueClear();; e8 s4 I* |! b  D+ ^& ^! q) Y( B" ]
$ }/ ~- H! y8 f! @8 C/ `- H$ ~6 L
        internal.LoadState( p );
$ _9 ]" F; @* e' |6 d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; z! v) z. i7 U
  v2 S* O' x7 b
        // VRC6' w" [9 o' P4 P6 n) n4 j" ~0 Q( t( Y  |# u
        if( exsound_select & 0x01 ) {4 Q$ ?! h# O5 o. n
                vrc6.LoadState( p );7 F7 j+ j- a* K
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 b' n# l5 f  [% {) o( Z
        }+ E+ ~2 G7 g& J
        // VRC7 (not support)
$ ?! i* d; S; C2 c        if( exsound_select & 0x02 ) {, J2 n. N+ q- t) n) v! z+ y
                vrc7.LoadState( p );. K- A9 h4 `) l+ F9 U4 I
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; I- L1 ?  K% e9 d: A  O        }6 G. E# B5 X8 [6 b& `0 R1 X) L
        // FDS
: e+ V6 e# [* Z- o        if( exsound_select & 0x04 ) {
$ }7 G# f* l2 E% ^3 T" o                fds.LoadState( p );7 j' X6 t: J4 d3 C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! d9 C' M  B# X- p% |+ Z
        }
  b, i. ^/ f0 G3 t+ R4 A; q) v% `        // MMC5
& I# N* f8 V  W2 R        if( exsound_select & 0x08 ) {
& }1 Y8 I0 o$ S: i0 u& |                mmc5.LoadState( p );' g% m7 n; z6 S' t& n9 W) G
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 n; o5 Y7 P! P2 |$ J! p
        }+ o' K9 K; P7 y+ H. A" L
        // N106  _# B7 F/ f- x7 i; m- \+ {
        if( exsound_select & 0x10 ) {0 d0 p) R: H. S+ u9 I: W
                n106.LoadState( p );: E4 y! U/ Z" a7 e: G3 h: I" N7 E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding% m- r5 k6 I! a; b4 y& \" K
        }, I. q& L" P: s
        // FME78 w3 y! L* P; c- k4 q
        if( exsound_select & 0x20 ) {) J0 }& m! h- R3 n+ x
                fme7.LoadState( p );
8 H% w* n3 D) P2 B2 M* r5 C                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 b+ t0 J0 u6 {- C$ C/ ]6 h4 r        }
2 S5 l% h( T( k& e$ E$ l}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, t( ?% \' R7 E* N/ B可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。# P, \3 @" k& E
感激不尽~~

, {2 D! J7 l* y, v' m: Z* F# B恩 我對模擬器不是很有研究,8 E) K+ V- I5 I& Y: d& D( m
雖然要了解源碼內容,可能不是很困難,
& }& W' [6 [3 M/ d* R) _不過還是要花時間,個人目前蠻忙碌的。  p: \% F  d! f4 L

+ b; Y4 x# V  j! s給你一個朋友的MSN,你可以跟他討論看看,
0 v6 L$ p5 W" `他本身是程式設計師,也對FC模擬器很有興趣。5 x/ Y  y. [6 S. u9 Z2 d$ g
  f/ L- \( g) M7 \/ R  W; W
MSN我就PM到你的信箱了。# u( E2 P* S) b
0 {0 u6 Y( @2 b2 T' S2 D. q6 |
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 8 I  n6 n$ G* c7 Y6 t  _0 d/ v
呵…… 谢过团长大人~~

9 m$ [- ^, V. D) h/ m
; z/ W' e0 ?5 O1 }3 M0 n哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
8 v1 }5 F! N# l5 O8 i团长的朋友都是神,那团长就是神的boss。
: e' ?; n* A  t2 q" n
哈 不敢當,我只是個平凡人,
/ H6 L- G$ c$ Z1 \, n4 G要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 u9 y! B4 X  z% C7 g4 O! X% dZYH# a6 ?# {" B" i8 c1 W
QQ:414734306
+ O5 [8 \" P% {, _Mail:zyh-01@126.com
9 ?1 T+ Q8 \+ E
  ]. F' J3 l7 z5 z, g4 G# p他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 9 w5 `# Q- I$ Y. i5 m* ~
再次对团长大人和悠悠哥的无私帮助表示感谢~~

7 ~6 O- m7 N8 g# c+ A, j' {不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-6 23:56 , Processed in 1.090820 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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