EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。: x' A" K9 ~* S; d: Z  Z% T
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~7 h! A* W2 {4 T9 D  p  r
这里有相应的模拟器源码,就当送给大侠了~~1 V7 X& d- ^, w7 B+ y# e
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
; W8 [0 `: G4 _2 b, i0 @能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 X! C" ^  s  \) B8 l! T楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" f, a! ]2 O, b* d3 P
这里有相应的模拟器源码,就当送给大侠 ...

. R6 v* }( X  V: x0 A( M9 ^聲音部分(Audoi Process Unit = APU):2 `) u. N2 |1 m
.\NES\APU.cpp
4 Y9 J9 _2 b6 j/ h.\NES\APU.h
$ l) a& X3 u! h1 G7 D4 Z0 W! L
* p: j2 M* V& V% g0 h; D5 I6 H( s) h1 a$ G& c( [$ @
影像處理部份(Picture Processing Unit = PPU):
! E$ s/ Q! @% Y: |.\NES\PPU.cpp
& r% U, b% W2 E+ P; _.\NES\PPU.h4 S9 u+ }- T+ _7 @- [. T0 I
  D0 k4 Y5 L/ [
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
3 U( \! L1 ?% E. _) c2 V(由于很多专用术语和算法机理都不明白,所以看不大懂……). R" C  F; ~6 N6 F, k
//////////////////////////////////////////////////////////////////////////' L" _2 h. E: w+ Q( ?  H# ^. b# s
//                                                                      //5 F: r9 W  s8 J
//      NES APU core                                                    //
' d( P4 H# ^) A$ y: T//                                                           Norix      //) l, q3 ?  ]% k5 i3 V4 H: _+ M
//                                               written     2002/06/27 //, [3 e( K$ }& R4 c7 [$ q% s
//                                               last modify ----/--/-- //
% l7 m! W4 m' |  H3 [//////////////////////////////////////////////////////////////////////////
* d6 G0 p; m3 t! K#include "DebugOut.h"9 s  V/ w1 M. y2 Z9 m2 ?
#include "App.h"
& c4 o/ D5 c3 g5 |; f7 \5 t, v6 ]* `#include "Config.h"- H  i- ~% v7 \* K! L; V; [

0 j& l2 Z7 m, ]  a1 G6 h#include "nes.h"
# M- @$ X) \0 F5 H#include "mmu.h"1 ^5 Z$ Q! \: i0 w$ ]' N, a
#include "cpu.h"! T6 k1 p) P5 O. G& w$ U* O) C
#include "ppu.h"
; W& `: O: [; E% O3 f- v% ~#include "rom.h"( V$ M$ s8 j& x6 b7 a0 L
#include "apu.h", u4 O" }' Z3 N6 X: @8 I9 i

) F0 y" A3 H: N1 N// Volume adjust
4 U! c5 |. S/ R& ?3 h5 Q// Internal sounds
9 J2 i) p; A& q4 L#define        RECTANGLE_VOL        (0x0F0)
4 A6 E  s1 o$ e, M& l; G* E, O#define        TRIANGLE_VOL        (0x130)! m, Y  \. A5 c2 Y0 Q
#define        NOISE_VOL        (0x0C0); u& ~* G; r7 D2 H  E& F1 N
#define        DPCM_VOL        (0x0F0)% d7 L  ^2 f2 E  s8 I! ^
// Extra sounds* b7 O, R$ t; ]9 u  n6 S" a: K
#define        VRC6_VOL        (0x0F0)
0 N8 A5 s+ \/ F- y7 H; X* `#define        VRC7_VOL        (0x130)
, v9 U+ L. f7 W5 |5 c#define        FDS_VOL                (0x0F0)2 n& U& W! |3 A- M0 Z
#define        MMC5_VOL        (0x0F0)
0 n7 `7 F' }8 F$ `#define        N106_VOL        (0x088)
. Z8 s; _9 H# X/ _6 n- k#define        FME7_VOL        (0x130)8 J& S1 j/ N  M4 W( ?: v6 o
# b3 P! }7 E, r/ {
APU::APU( NES* parent )$ D7 U# @1 Y$ ?# o6 \  m
{: V. j; E# m8 M& l! v6 L
        exsound_select = 0;# M/ F3 n* C4 Z7 t; k: P

$ ~; L1 D! P9 y        nes = parent;3 m, Y# n' z& A: R( @
        internal.SetParent( parent );0 n( F6 h+ K) `7 @  c- S  e
' z9 A6 M5 W% }2 U
        last_data = last_diff = 0;5 R! ]5 Q- o: L" t: b
: w7 ~5 W* r4 x' e2 C7 |
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
. o  m. t# X$ @- U7 ]. C: @, W( E7 D9 V4 b" e5 G: ]& N0 {9 }- T
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
. Y- y) i4 A9 ]        ZEROMEMORY( &queue, sizeof(queue) );, p0 l2 W7 U# W2 _, o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" Z" j% u% p( K* ~5 P
5 ~! q8 W% _' m6 e        for( INT i = 0; i < 16; i++ ) {4 ^* ?6 M. ?0 Y' e5 b6 j7 ~& z5 ^! h0 [
                m_bMute = TRUE;; h4 y9 f/ _  g2 L4 I
        }. D5 f2 C9 Z& c7 K7 X2 c
}
$ I* y& ~" P! t) A  A& {: O( v! H+ k  s+ B: L" J4 W
APU::~APU()
8 r# `5 }: |. k; ?0 w2 `4 U{
7 u7 b7 U" ^+ o  U}$ d# R: R/ m. B8 K, H

, ^7 @& k1 V) t8 Lvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
; v: u4 V& C$ H2 x3 L{7 |: u: A8 S8 Y3 R  z
        queue.data[queue.wrptr].time = writetime;
0 Y6 y% O6 [" n( O; q& x        queue.data[queue.wrptr].addr = addr;" E$ O. y2 {# {3 ?$ M) P
        queue.data[queue.wrptr].data = data;
: m& s6 f2 ]' m8 {  L8 L/ L        queue.wrptr++;
/ @; @1 P2 |5 g0 p% c        queue.wrptr&=QUEUE_LENGTH-1;" a. V$ f% y$ F0 m! v" t* `8 N
        if( queue.wrptr == queue.rdptr ) {2 U7 B, E2 A1 V% o
                DEBUGOUT( "queue overflow.\n" );/ ~. R/ Z3 v7 [# M
        }
& |( ^2 _/ n* v7 t3 o8 f}8 Y; U* i4 P* A; ]

  z: W8 U  Z0 D; v' l/ Z' YBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
2 @5 U$ Z1 |7 G$ K2 \- T2 P{' F* P+ T: }7 A. \. ]+ B9 K
        if( queue.wrptr == queue.rdptr ) {
6 b& N& I6 s$ r# Y                return        FALSE;
, v! f/ N5 u+ }3 `- C# a& z        }
/ U- B" F% _8 X+ D        if( queue.data[queue.rdptr].time <= writetime ) {  t! o. H2 Q) K: ?) x/ e0 P
                ret = queue.data[queue.rdptr];
' Y) e% B7 d7 `) @% c" V! a                queue.rdptr++;
+ `- r) M8 j  C) \8 k; ]                queue.rdptr&=QUEUE_LENGTH-1;% ?& L5 T& l& K& n) _1 W8 c( B( ]
                return        TRUE;9 [  o, ?3 _6 z5 g3 R2 t& d+ _
        }5 M8 }  M! O; y, L0 Q9 E' _4 X
        return        FALSE;
5 p: m) d2 }# H% L2 F}  w7 z0 q. G# n5 M& W

' Q( E5 {! M& H& ^void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
: Q, N! g( @. h8 q{
, D* |/ @# T. A$ T7 z        exqueue.data[exqueue.wrptr].time = writetime;/ W% l) l' ^& F9 P; Q' }  b
        exqueue.data[exqueue.wrptr].addr = addr;- Q/ Z) k. ?3 }8 Z
        exqueue.data[exqueue.wrptr].data = data;- r. z/ c8 U# r5 N& G0 L: a
        exqueue.wrptr++;3 S. y$ `9 O8 j4 Q+ _
        exqueue.wrptr&=QUEUE_LENGTH-1;( B) A) h  `; i: l7 z2 Q
        if( exqueue.wrptr == exqueue.rdptr ) {. \' i& Z% P+ r; K3 C
                DEBUGOUT( "exqueue overflow.\n" );1 R8 Z* Q6 s0 U5 }7 l
        }
5 ]9 ~; e9 `3 U3 L) ]) i6 ^( j}
' b/ }7 ^1 n$ C7 M1 A# e# Z5 E3 H  S% y
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )0 c$ s7 o% n+ ~2 n; C
{
3 ^4 `0 |. \1 X9 `% V: ?/ P3 W        if( exqueue.wrptr == exqueue.rdptr ) {
9 L0 H, V1 X+ f1 T4 H' Z5 W0 G                return        FALSE;
3 }3 |5 {9 T7 {0 P) o/ w        }
3 m$ Y  g  D9 V% K8 q2 r        if( exqueue.data[exqueue.rdptr].time <= writetime ) {0 l! n/ |' Q, T- R
                ret = exqueue.data[exqueue.rdptr];
- p0 g& f& f9 H                exqueue.rdptr++;
- Y1 j) H- h3 o! `1 F0 u. t                exqueue.rdptr&=QUEUE_LENGTH-1;
9 w, V# }3 ?& {0 }5 s9 U& L% {# D& I                return        TRUE;
* D' M6 Z- k7 N        }8 ?6 B- f5 u4 ~  g2 u# y3 q) S( I5 B* C
        return        FALSE;" z1 x; {( w* G2 z
}
3 v+ X0 o5 {; e# Q3 v5 ?! k4 V- v9 R( C) I' U) N, [3 d
void        APU::QueueClear()- v" K1 m9 C# ?9 i) G
{
( a/ |# a* u# L9 h- |# \        ZEROMEMORY( &queue, sizeof(queue) );
# R: Z4 m+ A: \7 z* J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& }* z, a3 z$ V, l8 y- u8 h* G; I}8 U) t* Y8 x, x4 @! @3 J) K
4 b$ u- ]/ U9 `4 a) @3 M. n
void        APU::QueueFlush()1 A$ D6 n% S6 G4 R% \3 M
{
4 D5 c0 L9 f  a/ |        while( queue.wrptr != queue.rdptr ) {
% n9 M& `9 _1 o, R6 K6 v                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 L: }/ T+ B/ \/ ?) m; R5 G
                queue.rdptr++;! D5 |+ p+ ~$ ?4 |; L
                queue.rdptr&=QUEUE_LENGTH-1;9 B$ Q1 n+ b, F; e. ^
        }
6 [0 l6 A1 @' F) |- s; {( x. @4 y: u: \' s" `) c
        while( exqueue.wrptr != exqueue.rdptr ) {
* L' A) w# f+ @4 H: R                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
$ e- F. r8 S  \, G( [                exqueue.rdptr++;, Q  J( a8 N  K. x1 ]
                exqueue.rdptr&=QUEUE_LENGTH-1;5 K. {  ?0 p) O9 n, d$ T
        }
# b" A! F9 a% O4 O}
2 E( `4 ]. }" m! v' V6 g: M% R. Q7 U. ]' p
void        APU::SoundSetup()
0 z$ u( d# u: ]* P2 \1 {8 Z{
. I9 o' i; Q3 P( y6 s# U5 y        FLOAT        fClock = nes->nescfg->CpuClock;9 [/ A7 m6 q  K2 U0 g
        INT        nRate = (INT)Config.sound.nRate;
5 ~7 N% G$ Z1 o! F  e9 `% P        internal.Setup( fClock, nRate );! T, i8 y. w5 Y0 f  s5 q$ }( f
        vrc6.Setup( fClock, nRate );
' A* u% n1 [( h# S' q# i$ A9 B        vrc7.Setup( fClock, nRate );! u. h) t4 n% H' f( P
        mmc5.Setup( fClock, nRate );# L# g7 s2 c% c/ j
        fds.Setup ( fClock, nRate );1 \: i* T6 g# l5 Z) ^  c
        n106.Setup( fClock, nRate );( C9 v% v- P* i" w" ~5 R$ Z+ H
        fme7.Setup( fClock, nRate );
2 B0 j. U2 M6 I4 W& u+ b}8 m! D# J0 G& ~$ A$ T4 x. m: N
$ P+ B' y, m% @4 _, m
void        APU::Reset()
/ ]$ U0 _6 Q& [, Q0 ~+ K6 U{3 c- P6 }$ k. M8 F$ \# m
        ZEROMEMORY( &queue, sizeof(queue) );- d& }( g4 ^# D) M' q7 r0 _( C
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' @  [1 N5 w! W3 K5 R. g; z) W7 p" V: k  z! C  O% L  @
        elapsed_time = 0;; B! ?# P- s3 P3 u
$ d9 H% D6 p" t% I# e5 u
        FLOAT        fClock = nes->nescfg->CpuClock;
9 V* p9 J! U. v2 q        INT        nRate = (INT)Config.sound.nRate;9 }0 }- u. J- A4 I
        internal.Reset( fClock, nRate );7 S, A4 N2 \" E
        vrc6.Reset( fClock, nRate );3 {9 _" J% j; R, @+ |: u8 C
        vrc7.Reset( fClock, nRate );
- O# w5 p, Q# T) W/ R- M: O& |        mmc5.Reset( fClock, nRate );
& e+ b; }" _* M( m* _5 Z; K( Y$ j        fds.Reset ( fClock, nRate );  M7 ^- L/ _$ b2 Z2 ?5 V
        n106.Reset( fClock, nRate );
  {! r, A* v0 q: ?0 j* z5 r        fme7.Reset( fClock, nRate );4 W3 s/ |, o8 \: L2 w
4 ~) S/ ^7 g/ n& \$ r8 D! l
        SoundSetup();$ B% q( i4 k8 w* o. [
}2 b- U% v' L/ V8 \$ Q& x
  i1 T; x; _" O7 G
void        APU::SelectExSound( BYTE data )" |7 _" S0 s0 \7 [
{
" x: H; Q) ~0 N' O        exsound_select = data;
" B1 t4 ], J6 g+ @}
. _# K% z. k5 r) `. `
/ a2 b$ s- p) Q  G* @6 M: h- @' I  wBYTE        APU::Read( WORD addr )  w3 V! d+ T. I' ?# ?* s% G
{
9 w$ ]3 w% n' u) L        return        internal.SyncRead( addr );
3 `. u5 l7 i6 C}
" }1 H- g& ~; }3 ~. W& u; F2 C9 ]) @5 ~, g9 Z5 R. x
void        APU::Write( WORD addr, BYTE data )
$ e. D2 D1 Z6 B' t3 `4 V{/ p- l- B8 P4 f8 @& S6 L& s
        // $4018偼VirtuaNES屌桳億乕僩3 A; j' A0 P- v: x4 {  Z2 }4 L
        if( addr >= 0x4000 && addr <= 0x401F ) {
1 o( _7 z- {, p9 x; d                internal.SyncWrite( addr, data );0 p" C7 c* A1 W) @8 _- \* ~( t8 x
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
( |. u* Y0 N/ b/ s        }
9 }2 n( u, i6 e: ~' Q- v; o3 k}4 r; ]$ n' _) c$ j! A
+ o" [7 p$ a+ \2 J
BYTE        APU::ExRead( WORD addr )9 d6 _# t4 w% `; D4 N0 h- ~4 M, u
{6 b0 f4 D( O9 ?- c/ b& S0 Y
BYTE        data = 0;' d8 o) Y/ t% d+ w' e7 K+ H1 l
9 p2 ^; Z, o. Y% ~
        if( exsound_select & 0x10 ) {" D6 N- d1 E9 o, K
                if( addr == 0x4800 ) {
) X  ]! t' N, u                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
5 S8 ^% y+ q! P9 |- U                }
) ]2 P/ g, l5 C: T# U) H+ Z        }
  ]4 V" Y0 D" E' _4 X3 T        if( exsound_select & 0x04 ) {1 i. c4 L0 ?% \0 c8 p' q
                if( addr >= 0x4040 && addr < 0x4100 ) {
/ k* M0 W- Z1 [$ X7 y, U                        data = fds.SyncRead( addr );$ N* D+ c8 e+ i) v3 P- u: |/ u
                }3 y- \9 ~3 m8 F+ `
        }) ?; I2 V3 M$ ~. u) C+ c
        if( exsound_select & 0x08 ) {
5 H3 k* h0 D  l  Q                if( addr >= 0x5000 && addr <= 0x5015 ) {) R) i& E, m# F: q5 i& ?
                        data = mmc5.SyncRead( addr );! W2 w" |/ N' {& P$ N2 [
                }
0 ^8 _  Y) _/ i- J: r5 |0 O        }
0 X7 P+ J) |( E: q  h# h0 V
! T- I  d$ B% [+ E, R0 \1 u        return        data;
% P- H: W' z# _& S% j" }1 F& b}
. |% e$ r8 z- l* L
1 D# s1 D( ?" Uvoid        APU::ExWrite( WORD addr, BYTE data )1 B3 ~/ t$ C/ e7 i
{
1 p4 n+ Z( T4 R. e        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );% P3 z* Q' U7 b; x1 A

+ N) d! w0 ?, E) H6 R        if( exsound_select & 0x04 ) {
( g# A5 _8 W9 w/ o                if( addr >= 0x4040 && addr < 0x4100 ) {+ l( M8 S3 g; S# }0 O
                        fds.SyncWrite( addr, data );
1 O/ L8 H. P  e2 Q                }  f5 D' k, [/ H9 J  K
        }" ]1 n4 G8 N# T2 R) e. j, I3 U
/ t8 `+ u% ]) m8 B3 m( }
        if( exsound_select & 0x08 ) {
) n5 \! G! D8 ?                if( addr >= 0x5000 && addr <= 0x5015 ) {
" |1 F# d9 Q: \* S$ h# g  v) _                        mmc5.SyncWrite( addr, data );
) ^) _* c/ H8 B. J6 ~) s                }
5 j7 A2 z$ \0 s; K        }9 D7 w- t/ g- e
}+ s1 k2 W/ D3 P9 F( w; s% q
+ L$ }6 V  S1 x9 k2 [
void        APU::Sync()
* n( Y/ f, |, p# o{
, U, j$ x$ W: R: D2 K3 A! s) C}, b& b6 Z' N* Y  d& d4 T

. q  V; x2 S" O) T; avoid        APU::SyncDPCM( INT cycles )" m! Q% k- a, A2 D
{+ q2 q- Y; b  X
        internal.Sync( cycles );
' r- u; C, F, t0 r2 D
- Z7 k/ J# Q4 B1 J7 w. t        if( exsound_select & 0x04 ) {
) A* G2 X. Z/ `5 n# }7 g3 x) J                fds.Sync( cycles );
2 X1 I8 }0 ^7 J, T9 Y. H8 l        }
  U( f) A* |3 w, i4 Y        if( exsound_select & 0x08 ) {
- O# s: I# s, I# E2 o                mmc5.Sync( cycles );5 T+ H! m% T4 A! n# ?
        }
! W4 @" x; n3 Y" y6 N}8 x# ?1 ]+ W. S2 K
! E  W/ b+ ~8 q( i4 f3 z
void        APU::WriteProcess( WORD addr, BYTE data )) H6 `' E; u" y& @* {2 U
{0 A3 z: Y: I& |% {" o2 x
        // $4018偼VirtuaNES屌桳億乕僩( B& ?# E+ b5 ?, Z
        if( addr >= 0x4000 && addr <= 0x401F ) {
" S: q, w. g) U6 S6 [0 i                internal.Write( addr, data );% v! W: R! ]' ^* Q$ ^. E! g
        }$ G! v9 G# _8 E6 T3 R
}
% q9 t9 u: C9 s$ I2 Z
$ c# h* x/ X. }5 R! G2 K! }; \void        APU::WriteExProcess( WORD addr, BYTE data ): V4 z  \; Z6 }$ @4 @
{* Z+ C! v8 U/ A3 x: }8 @
        if( exsound_select & 0x01 ) {
1 d5 n& o3 ?! n5 `' r; [                vrc6.Write( addr, data );5 q, O# o7 M7 s- _' \& {
        }0 o7 r3 {$ x3 n* G; I) H  t; s
        if( exsound_select & 0x02 ) {. N( M1 t) H. d3 R7 r* ]
                vrc7.Write( addr, data );" _, i9 v/ c( c+ `" l' u9 }
        }
: r, z- K. s# e# _5 {4 u: h* H% d        if( exsound_select & 0x04 ) {
* E: }, [; _9 _" J7 L8 P                fds.Write( addr, data );2 T. Y- i$ G' m' W
        }
! O$ I# S: d# Z: x  O( p! ^        if( exsound_select & 0x08 ) {$ v+ n7 B* s' d% S& q
                mmc5.Write( addr, data );
1 n! n9 {& W) ?        }2 b) B9 B1 ^' _9 K) p5 T3 r$ O) _7 f
        if( exsound_select & 0x10 ) {$ j5 y' B' i$ ^: Z
                if( addr == 0x0000 ) {: S& j# Q9 k; I4 c3 D/ y0 g$ O! {
                        BYTE        dummy = n106.Read( addr );
: N0 C! X* f6 G/ q* i3 q" o* N                } else {
- t* V1 t4 U, O5 P                        n106.Write( addr, data );2 m9 B' |7 _% ?1 _! N. g* ^, u
                }( ~) c) u7 c0 W5 G3 S: [+ P8 R
        }
5 B, H" u' F1 r        if( exsound_select & 0x20 ) {
! T' T; h; q9 N5 l                fme7.Write( addr, data );
, N8 x$ L. S8 n$ F, l        }
+ a( T- }& U" N}( H  |2 |6 [" D3 z- ^4 v( J
' I3 |8 M1 @; s" Z1 I
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )1 f2 |2 p+ i6 X3 |7 O
{( r6 G. d& c+ Y0 W3 O+ \+ K/ e
INT        nBits = Config.sound.nBits;
9 t. v' @8 o4 z/ cDWORD        dwLength = dwSize / (nBits/8);1 q4 N' g/ [7 d
INT        output;
& B4 u* C7 K4 y" GQUEUEDATA q;
" N$ i4 T# Q7 D, Z7 H$ N3 U' ^. F- n+ K- sDWORD        writetime;
$ y; X" S8 g2 A# c+ D7 f& e) i# f4 Q( d( H- {
LPSHORT        pSoundBuf = m_SoundBuffer;. d: r  h' B* u5 M' r
INT        nCcount = 0;  s0 g1 m1 I% O  y8 R% H4 u( L

6 ?2 |  A  s$ V: x+ _INT        nFilterType = Config.sound.nFilterType;8 v) k. T* y0 V! j$ ?% E) h
. h! R0 E" T+ d, w
        if( !Config.sound.bEnable ) {0 {3 T* Z' l6 a- }, n; F
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );0 A# @0 f7 ?; @/ V
                return;% N2 J) X! h# ]8 \2 ~3 I, p, F
        }
' C8 D- {9 M/ _: t& p5 j  L. ]7 [9 w# z7 k/ c4 H9 j; f
        // Volume setup
& n5 U- i0 A1 A1 ]( Z2 k        //  0:Master
( D% X4 e& J) I        //  1:Rectangle 1; ^- u0 _% e$ ]0 A3 F9 M: M9 h
        //  2:Rectangle 2' i6 H2 ]9 j- h0 G3 e0 r
        //  3:Triangle5 E, y1 l* o$ j, j( k
        //  4:Noise
( d# T8 f5 c5 p( r2 ~% m! V1 S8 t        //  5:DPCM5 |* x2 T; Q5 Z2 ?6 r: N
        //  6:VRC6
) k9 y) t: m* S+ x0 j        //  7:VRC7
6 D- [" ^5 w  S8 ]/ m: p- J& k        //  8:FDS
! {0 w6 J9 o; g/ M! [2 i        //  9:MMC5
( {$ @! ]2 ?" T* L  |        // 10:N106" a9 K8 o) J, G; e7 ~4 ^
        // 11:FME7
. G! L8 i& J6 W+ }; D" R' H        INT        vol[24];
4 ~  n# g: G: ~        BOOL*        bMute = m_bMute;
8 g' K9 E$ g7 h* [6 C& X% ]        SHORT*        nVolume = Config.sound.nVolume;
  p# a& v5 @7 M" g2 g8 J
% z, [+ C( Z4 a$ T: _9 x+ B        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
+ i5 D6 C6 a8 W7 r/ Q# n1 j% z$ [. T0 ~: k
        // Internal
8 m4 A: S9 G) Y3 w; W) r7 ]8 ]        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* J7 F2 i: i8 |" b        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
* I+ q+ x# E5 l6 m        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
9 Q1 u* W& x: p4 u! J1 h        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;6 B. [- _! Q' {) e$ V6 T4 h
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 i5 E# n: I+ c1 g; v, u* D: L8 O4 L4 P' i3 O
        // VRC6( A+ m/ P9 P& y. A: R
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 w6 K6 b4 y* g8 F% S        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, [9 C, a/ n5 W- ^; n0 e* i& ?( P        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% Q3 ?+ ]! ^6 l# n" ^  C* c: u& f+ p  b5 [& t% i
        // VRC7
5 T. d  `" y) v9 @9 m7 N7 L        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ K" ]' t, m1 @1 Q. C* `0 N

# Y( W% v5 Q1 c: E: S. a, E        // FDS. ^* ]. O* Z( v3 C7 P' J6 x( h3 D) H/ y
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;+ T) G$ U1 {0 E# B; \

# X5 R* z6 {0 N/ e        // MMC5' m5 y8 [4 J- w# [- h+ R5 W8 ^- K& S2 @
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! E% P) }; L$ y) a' `& |
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
8 l9 t( R% i: z5 G$ ~/ v( i- u" s        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; _' I5 a. D6 J

" [5 f0 |& M  U, m        // N106
& g0 k. a0 M$ x5 E        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! V- w( v! |0 D- p; @9 d
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( y  A% s& ?/ C& e+ `8 G
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 r- R1 q, t4 e) Y1 t8 H8 z        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  X$ ]; w! O( `; X" d8 V4 L! S
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 u4 v: z3 F6 B' x* t: {+ C& n! q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- a9 t: q, e# _; N. D: K, R
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 M( a/ X- |( T1 |2 H; F) Y- m        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& B+ ~9 }9 J/ Y; u8 K& p8 t  t# Z; p5 i4 P; g2 C
        // FME76 M. l! O7 \7 O' E9 v+ U  i4 l0 ]* n' E
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& @1 n; y7 V& T
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) z0 s5 V1 l) I+ Q# y
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ s" e, ]3 g$ F; t+ N' W. Q" N7 a! I8 W9 [9 u
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;4 V+ L5 ]0 u% o+ x6 b
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;  u5 m$ M; n7 D+ }
( }; S! K$ j4 A+ w8 `, \' y& M% H+ ?
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
5 H& Z( O9 \! K        if( elapsed_time > nes->cpu->GetTotalCycles() ) {! g; Z& Z2 t: l! \( U2 _
                QueueFlush();
, w; B* D% K! ?6 n5 I; X6 S# V4 g        }
1 I7 P" R& O' N1 h
' N; [& Y  b; j$ Q        while( dwLength-- ) {
5 e* w1 i' o& v. x' l6 y                writetime = (DWORD)elapsed_time;
( x9 ^5 \, Q7 p6 P4 A) j& x% G. t6 B6 \
                while( GetQueue( writetime, q ) ) {
# M* i; k* V+ c- ^                        WriteProcess( q.addr, q.data );
, |( q, O  }# c$ W7 H                }
/ [0 T3 J& D& [! @4 X) E! W  j& {( n9 U1 H4 {6 b; t
                while( GetExQueue( writetime, q ) ) {
8 @/ E1 ~6 C7 |8 f                        WriteExProcess( q.addr, q.data );& n0 p6 \' @" O4 R  g
                }# z: l( k4 n; R, E) `( _3 q

) G! [( R2 w( }" g- q. C                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
0 m, q: _5 c( t; }5 e: ^                output = 0;
: B- V0 B- q' s( ?: n                output += internal.Process( 0 )*vol[0];6 A/ t* |9 m4 I8 A6 g. g
                output += internal.Process( 1 )*vol[1];* j2 Y( J: Q0 j% x
                output += internal.Process( 2 )*vol[2];3 }. o: R5 j+ v, N- J3 R# b
                output += internal.Process( 3 )*vol[3];
( s9 Y, S6 F' p- @2 E3 Z                output += internal.Process( 4 )*vol[4];9 t+ i7 A- ^. X: l; k
- x: D0 t6 b$ x
                if( exsound_select & 0x01 ) {
; B& R0 Z; P' m4 r' Y, X( `  r) R/ E                        output += vrc6.Process( 0 )*vol[5];  I3 Y3 j$ t7 N* [0 N/ j
                        output += vrc6.Process( 1 )*vol[6];9 e6 |2 {- j9 d) c' ~
                        output += vrc6.Process( 2 )*vol[7];
0 l4 g5 K9 U9 d5 V" w                }
5 b$ m+ i2 C, t0 D- n" q                if( exsound_select & 0x02 ) {
+ t7 h! b0 g/ \# L: _* W                        output += vrc7.Process( 0 )*vol[8];4 D) D1 L9 @/ }- f/ W% o6 s6 t* P
                }
3 Q8 Z6 H' [2 D                if( exsound_select & 0x04 ) {
( C, J3 y" Q! k) \1 Y. q8 z- ]$ g                        output += fds.Process( 0 )*vol[9];# I( Z# V2 }+ C3 P  F
                }
/ s9 J5 E2 K. T/ t; _0 C. t! U; q                if( exsound_select & 0x08 ) {& |, B) N. u$ M$ |5 ?8 b0 y
                        output += mmc5.Process( 0 )*vol[10];
2 V& I3 K; U, p                        output += mmc5.Process( 1 )*vol[11];. j( o0 w* v, w9 @8 h
                        output += mmc5.Process( 2 )*vol[12];, l  B  v2 t" q0 l; d
                }
' d6 ~4 M. X) ~5 z0 X; q7 u                if( exsound_select & 0x10 ) {# s' R* [4 y+ Z
                        output += n106.Process( 0 )*vol[13];3 p8 D( g2 A- j3 c+ Z7 j" J9 V9 ~* H# R
                        output += n106.Process( 1 )*vol[14];- h" m3 p" j" W+ C. q, h
                        output += n106.Process( 2 )*vol[15];
% Q& g+ |! Q5 [% j; m                        output += n106.Process( 3 )*vol[16];
. d8 |. N$ d/ J5 y5 r! b                        output += n106.Process( 4 )*vol[17];
8 Z% w+ w1 T! D( o                        output += n106.Process( 5 )*vol[18];$ d/ F# v, V/ i) R/ c2 T. m: Y
                        output += n106.Process( 6 )*vol[19];; T% K" g3 }4 M+ e, k4 D. `
                        output += n106.Process( 7 )*vol[20];1 k, N7 k; }$ a# w8 X( ~
                }
9 h' L+ G% U, T                if( exsound_select & 0x20 ) {+ v0 {1 C5 a9 P
                        fme7.Process( 3 );        // Envelope & Noise7 T0 b+ W# N' F! K4 ^5 ^2 E3 Y
                        output += fme7.Process( 0 )*vol[21];7 H$ D# A+ g, T9 W# _( X
                        output += fme7.Process( 1 )*vol[22];
4 O/ O( n# E4 }; N                        output += fme7.Process( 2 )*vol[23];
* A4 b$ s* k4 \+ J                }
4 r; r+ W; P' r' {2 c4 ?! p( x3 v$ G0 C2 q! O
                output >>= 8;/ X% e8 u7 H9 |$ p% n/ K9 F

' ^7 f* W7 B! U3 k$ [, Z3 Y                if( nFilterType == 1 ) {
( R( K; q3 f( C                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
4 m  V5 Z9 u7 b( i8 S                        output = (lowpass_filter[0]+output)/2;
5 I- G$ \7 t4 ~' Y, i6 J8 j                        lowpass_filter[0] = output;: L* B( r' b, p: B4 J( _
                } else if( nFilterType == 2 ) {7 ~* w7 d, l7 \4 e* q. v
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)8 O, ]+ F+ Z+ \5 D
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% d! n& V$ e2 o1 N* L. W- S
                        lowpass_filter[1] = lowpass_filter[0];
; U6 X) N" ^- L% H" f6 p                        lowpass_filter[0] = output;
! d1 Y$ M* V3 g. {                } else if( nFilterType == 3 ) {% B5 z! s4 u, b. a5 W
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 G# Z& j5 }* W1 b" R' u; C
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) A2 A" ]. \7 h: F
                        lowpass_filter[2] = lowpass_filter[1];
- \: _) h, H6 `' Y1 A7 W. G) G                        lowpass_filter[1] = lowpass_filter[0];
- x" N  R  w  l+ x. `3 |                        lowpass_filter[0] = output;
1 m# O* }: b1 d! e8 E# O# D3 g                } else if( nFilterType == 4 ) {9 w# X% h9 A4 p1 b7 A* \, I
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3), _0 @" R4 w5 v' ?4 c
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;0 D( a% p7 R  N! Y3 h1 C
                        lowpass_filter[1] = lowpass_filter[0];0 J. q& `# x# d2 D3 M6 z
                        lowpass_filter[0] = output;( C: ^: ?3 t/ q6 v% I7 K( i
                }) M, Y6 q0 E8 J
$ R6 I4 a5 m* k4 ?# Z
#if        00 p/ x, B6 f9 [
                // DC惉暘偺僇僢僩
" }  o. @4 J) u- K& W                {
: h; j: u: o" N! }+ j- k5 w                static double ave = 0.0, max=0.0, min=0.0;
9 K. v, t- u7 A                double delta;9 Z! s& u, r- h! y, R. X9 o' b
                delta = (max-min)/32768.0;
8 S0 J" `! X  F( ~                max -= delta;
8 @( I) x8 r3 D$ d  L7 P% j5 g                min += delta;
! E& K) e1 }# ]  l9 r- c9 e- r+ a                if( output > max ) max = output;
0 G( `) N: W. s. ^6 v  x  [1 X                if( output < min ) min = output;
+ E1 i* u" C7 s& G6 c* e: O; c                ave -= ave/1024.0;
, |* t3 X8 g, _2 U                ave += (max+min)/2048.0;
5 r1 T, a( s) n1 R- V1 h                output -= (INT)ave;- H( M8 ]2 I  x- r/ q& a- Z- z
                }8 i! B) y4 h" J% t$ G
#endif/ z! V% z+ [/ v* V7 k# J# S" a& [  k
#if        1& ]2 f5 E: A: S' P6 M! |
                // DC惉暘偺僇僢僩(HPF TEST)
: g+ c  {7 f1 f3 {* @                {) F. D( N# Y2 U+ T/ B
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
5 [; C% T2 R1 w  i) p. R; o" @                static        double        cutofftemp = (2.0*3.141592653579*40.0);
: Y! Y5 e/ X$ A9 B0 h, t5 `6 {7 z                double        cutoff = cutofftemp/(double)Config.sound.nRate;
( R4 f% W  p3 S$ _5 N                static        double        tmp = 0.0;
+ }7 s5 K: M" d( ]; D: I                double        in, out;& a. J& U( ?6 k
/ L5 |( D/ R  y5 o
                in = (double)output;7 z" p8 e. \9 m2 w, }
                out = (in - tmp);% J( S4 z% h$ I" ]7 R$ H4 c
                tmp = tmp + cutoff * out;
% M4 ?: k8 w1 P, g. m7 \9 S; m4 d" ^* R
                output = (INT)out;/ `  U- O/ h, |
                }7 D) _+ r4 ?/ a3 \+ s, p9 y+ Z3 A3 m
#endif( P. s! I$ ^8 [9 C, ~- \* a$ }9 h; e
#if        0
8 r& n4 n8 j) _; K! _9 _                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* [% [) o" e) q+ I$ |
                {
8 n, u( K& c; G1 V                INT        diff = abs(output-last_data);
- a; J7 F5 Y) Y; t/ B, Q  i6 p                if( diff > 0x4000 ) {
& h4 Z: q& o6 _' z- J6 r8 F. h                        output /= 4;( N6 e5 W7 D- E  k' A+ G: }7 d5 j
                } else   {4 h" e0 V) _2 M
                if( diff > 0x3000 ) {* \, d4 R  E1 B+ e/ s9 S. M
                        output /= 3;/ S! y" M: H% U) y& a
                } else
  m& N; ]; {1 r                if( diff > 0x2000 ) {% T; A, e) _/ K0 i, ]$ U
                        output /= 2;/ K" q4 P" z7 h/ s6 W
                }* O" m8 Z# X" I
                last_data = output;9 c0 y6 X$ V6 n6 D2 t
                }2 K7 \2 u, ]1 X& \" w7 t4 O
#endif
$ w/ ]+ t/ V; b                // Limit# D8 B% i/ Q+ S1 _0 H
                if( output > 0x7FFF ) {/ \& }" Q) s) p3 N8 n  V8 d5 q
                        output = 0x7FFF;6 l8 R7 S+ @* Q6 N+ U. ~+ T4 ~
                } else if( output < -0x8000 ) {
8 [% D! r8 [$ Y/ O: V                        output = -0x8000;
- p6 i6 X4 c7 Y: n) `6 }                }
" V$ c' U/ l7 G& F# K( v" G5 m
                if( nBits != 8 ) {- U+ k) n. F: N9 p: c) }4 ^
                        *(SHORT*)lpBuffer = (SHORT)output;# h- |4 ~9 n9 y
                        lpBuffer += sizeof(SHORT);- n6 {2 p$ A1 B( R; W
                } else {' a+ v: o- O+ l, l3 G7 D8 J" `6 w0 W% q
                        *lpBuffer++ = (output>>8)^0x80;
; Q3 h5 Q* w+ o- R4 K) ~                }
$ q0 [9 }# d3 M
* a. ?5 b. `/ b                if( nCcount < 0x0100 ). n3 H8 Z. g5 z/ C" ^1 E
                        pSoundBuf[nCcount++] = (SHORT)output;: [: P& M; B, @! G7 L$ F  @& ?

2 i+ G: H/ k  h& O//                elapsedtime += cycle_rate;8 {* l# v/ B' a& l  Q% c8 s
                elapsed_time += cycle_rate;
0 N3 `2 I/ m/ R9 I) I9 z) I        }5 F! Z* U. Q' P3 B- k) m

1 x( ~/ |8 A# p+ _4 s  x, @3 G#if        1
$ [) z% O3 L8 y, C& u" Y& [        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
  k" x5 o! Q* s/ Y                elapsed_time = nes->cpu->GetTotalCycles();
( K- O5 A' l$ R        }
# E( \  p0 G6 |2 Q. |        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {3 Y$ ?# H* E$ }, B7 W4 `1 X% T
                elapsed_time = nes->cpu->GetTotalCycles();. p* p! h7 n* B" `  L
        }
# a5 O" z! r) |9 t! K" p6 @) K8 K#else" W" s3 e' T- u% s
        elapsed_time = nes->cpu->GetTotalCycles();
! V/ j1 g, e0 r5 `* W* h#endif
: n, K( i4 `- Q9 A( m}
: z, K; K5 d2 X  J+ h0 B4 J6 q( ^$ t  ^4 G# j
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
9 `; `: w9 Q9 |) d4 C' s; PINT        APU::GetChannelFrequency( INT no )' k: e6 D+ @( @' J( C7 P
{4 z2 P2 N% ?* P
        if( !m_bMute[0] )# O; `$ v4 |7 [5 a- D) s
                return        0;3 D8 N- N: f9 w9 K

. I9 q9 p$ }7 S" y        // Internal4 W8 r; }, W5 L& R
        if( no < 5 ) {# L" u' X: m+ x' H
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, S7 h; O( A. G6 i/ h: m# F. h        }
* t9 Z0 n  _) M& f        // VRC6
4 o+ g2 p6 d+ P& @* x        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
# L# ^8 V( H7 o7 _, w                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;* A, h. T" g) Z7 ?6 y' v( R
        }* {- g( |% Q: a; `. Z
        // FDS
4 y1 {& {2 t& v        if( (exsound_select & 0x04) && no == 0x300 ) {
) r: e# h# Y) r  ]0 N! Y8 q                return        m_bMute[6]?fds.GetFreq( 0 ):0;
  m) s- W2 n3 c# w% x* `$ C) Y9 C        }7 a, K2 X5 k& z' o0 h* Y
        // MMC5
0 P1 `8 R! S+ R& L( t        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) {! ?7 ~( Q8 w2 A0 R( C- C
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;( b0 m* m0 |8 Z- f3 |2 X& s0 I
        }4 L  p4 J2 f% @0 R9 z
        // N106
$ p1 c" g" z9 `: S7 C* \        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 r# |6 v+ L' v9 W& \( K                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;- b7 |8 p+ U- z) c+ L
        }
* g5 X4 r3 x- R. c7 u/ H        // FME7
% i5 n* M' H" e/ |        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
- {: _1 W. y# ]/ V: p! R2 S: Y                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;. P7 [2 {5 S( N3 w
        }
/ h' L+ ?% l. x1 E) z        // VRC7: C6 }6 y) ~9 @" I! t4 E* N3 C
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {8 K. W; L/ P2 l* n
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: E. v8 a% c! c' Y; |0 k5 Y        }
2 T4 ~; W9 I0 l& l. G: I& k8 L" R        return        0;$ X/ B5 p" |9 D- U* h
}+ a  t! [7 T. R* v! @  c4 \, U

! Z9 u$ X& k' k1 g& V' o! _+ ?// State Save/Load
: L3 a9 l) ]9 r& Z& _void        APU::SaveState( LPBYTE p )/ L/ I' I! Y9 ^2 c# t5 v
{
' m7 ~+ c2 y( W) m! i! P. [0 E6 E#ifdef        _DEBUG0 B  W2 Y4 L2 a4 s. `! `0 A+ q
LPBYTE        pold = p;7 d% c2 t# _% h9 S/ o
#endif
9 ^8 x' n6 v9 X
8 U- P( p$ a& i' p. `        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
; Y/ m* h# I! c/ t! Q. I/ V        QueueFlush();. b3 d7 L% v5 O4 ^) }
6 v6 Q  J. c1 k5 W) \; E, Q+ Y* D. [
        internal.SaveState( p );
5 q% J& z' ^9 M! c5 }3 M        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding4 R/ \2 @+ [7 o0 f

6 d. m, ^& s" R. a. M        // VRC63 P$ N4 f# W6 G0 i. a
        if( exsound_select & 0x01 ) {8 n  ~7 t  h, @9 U# C
                vrc6.SaveState( p );
5 c) ?* J) v* L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  b5 o" e% h6 V  t; n
        }1 A0 D2 k) i0 W) H% K) A1 k
        // VRC7 (not support)
3 l  O5 w) k( _/ B/ [        if( exsound_select & 0x02 ) {
: M8 o4 V9 ~; }; w0 q! X3 B                vrc7.SaveState( p );* a' Q0 [5 B5 ?# {( r
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 N  F4 E9 \6 A- K# R, s        }, t  |6 W1 S  m' g
        // FDS
9 t/ L. g1 [: u6 k1 p* C  a% o- ~2 s        if( exsound_select & 0x04 ) {, b3 g6 u* @$ \+ f3 ]
                fds.SaveState( p );2 A" ~- K7 k' q& M/ M1 S
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 R* w; g2 ~! e
        }  X, M8 q0 @" [/ `
        // MMC5& n' {4 j# L2 ]0 Q3 B
        if( exsound_select & 0x08 ) {$ g% l6 }! i$ X! |8 p2 ~- O
                mmc5.SaveState( p );) b7 B8 E! d  v! i  K. n
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding; K/ T' s2 G+ m! `
        }
, X1 \/ O& U+ A: W6 S" n        // N106
4 M7 R6 M7 ]* P0 z1 c6 Y" E        if( exsound_select & 0x10 ) {% x8 M( H3 p! g& D
                n106.SaveState( p );
2 G8 [1 t( N0 U, q3 S' g$ }$ o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 D7 G# P8 ^$ N. V3 X
        }+ N0 q) ?$ U+ ]" c. ~
        // FME7% `6 g- K9 z# `$ \1 q, z' y
        if( exsound_select & 0x20 ) {9 K& v0 f9 J- {/ d
                fme7.SaveState( p );# Q* c/ \9 u0 E  p/ n
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
2 u* k3 j) O$ F  P) n3 O        }
, v1 z" d% U. u  m
! ]3 A7 j8 A" }#ifdef        _DEBUG2 n( G- ~; A5 b: r7 R4 J& A
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
/ i8 j2 z1 w1 U7 {- d( B#endif! N# o$ U0 S4 _7 ~& V. H
}3 G) o) O) p5 p- `: G
+ p' `/ ~$ y6 `* R7 X
void        APU::LoadState( LPBYTE p )
  R1 M+ q& C5 b{
: C) U" i/ g, i3 r4 m        // 帪娫幉傪摨婜偝偣傞堊偵徚偡0 [+ S( v9 r( H! Y2 h+ G. p
        QueueClear();" B# o+ g0 V& r" i: z1 F

2 {, _" q  K& r        internal.LoadState( p );
, V# O5 a) a/ a9 f1 O* l( ^: L! x        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
  s8 u& E+ [6 O/ w( q
5 t0 a3 P1 h5 e8 V6 R- \        // VRC6
( r& V, _7 k/ s. ^! a) A# H6 k& Y3 l) Y, G        if( exsound_select & 0x01 ) {+ l2 }0 W1 Q1 c- l: D
                vrc6.LoadState( p );
: z0 E" R( n2 K" ?( p; k                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 v/ x2 G2 j  N2 s% I        }
% A, C; q& Y; x/ J7 T        // VRC7 (not support)
; E' X* G- K4 v$ K        if( exsound_select & 0x02 ) {
% l+ A( j4 S. T; o( ~                vrc7.LoadState( p );
. Z& e: ~, w/ R7 h7 k2 Z. N                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
2 ]1 g. E" t- ]7 e1 ~+ p& r* Y# N        }; R- s6 H5 L) k2 E: s* h
        // FDS. k! ]2 A' i! h
        if( exsound_select & 0x04 ) {7 d7 ?6 F$ L( K+ m$ t. J$ O8 v
                fds.LoadState( p );% ?4 I) W! {7 i% i; [
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: _4 A6 S9 i# \  N$ U* d
        }3 s  _' r! p$ ]* p& J" A
        // MMC5
$ ]6 e2 J" a1 [% H: @        if( exsound_select & 0x08 ) {
, [; j# N7 |, ]                mmc5.LoadState( p );
6 z& D! g% R* @; y3 B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* K: n4 m/ @. p% W$ f8 v        }
( B% |  \  L8 g6 T* z% H# f        // N106- c4 ~% I7 h' r* I: Z  b
        if( exsound_select & 0x10 ) {
7 f2 V6 V- v+ d2 h                n106.LoadState( p );& c" s9 F3 S5 |' I
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' K9 O: N) L# _# M' b3 D  h5 Z
        }
8 H: m7 l9 x6 ?+ N% N        // FME7
2 e" l+ u5 z) ?5 C        if( exsound_select & 0x20 ) {
3 U- }+ y* X6 V5 ^                fme7.LoadState( p );
8 s; E- |( G5 W& {                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& z  N& p' g; a, e& u        }; h* {4 K1 v/ E; o4 U5 C) c% f
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; G8 z  K3 T. u* W
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
) r" t* u2 |6 [' _! u感激不尽~~
+ B5 L- J8 h4 Y' k
恩 我對模擬器不是很有研究,
' \9 T. _7 W- g4 W2 Z雖然要了解源碼內容,可能不是很困難,
: J; L+ K* Y1 A4 x" t不過還是要花時間,個人目前蠻忙碌的。
4 h" }/ ]& k5 i9 ]! n' ~6 |" i5 G* q
給你一個朋友的MSN,你可以跟他討論看看,3 u, V9 J& f5 |: {" v4 m
他本身是程式設計師,也對FC模擬器很有興趣。
: s( y; x" r- L' o: b7 g; Z( m: |7 \# P$ Y3 z4 w
MSN我就PM到你的信箱了。
% x4 J& E" ^2 N7 b# c4 d8 s/ {  Q
' m- Y7 z% Q7 N( u1 ?, q希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
. b" M! W/ c. a呵…… 谢过团长大人~~

5 D( \6 [1 v9 x1 V( _8 I# o9 s3 m+ U) [
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
+ V4 a8 X% h1 C3 I: ?: p4 P* q$ N( |团长的朋友都是神,那团长就是神的boss。
7 z4 B/ @4 l# ~
哈 不敢當,我只是個平凡人,* i9 w7 H$ u- `% f* B
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
! o+ \( ~  e+ d1 W# K; iZYH* O; v$ j* ~& ?8 M- x. v
QQ:414734306% C( t9 d# x6 g+ d
Mail:zyh-01@126.com5 u) }% e- a# I  k2 e

/ l! _( }, a9 B9 k, V$ s' O% s+ @他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 % H- i- u$ f/ M! {
再次对团长大人和悠悠哥的无私帮助表示感谢~~
* Y  L* |! [5 ^, Z+ Y% c5 q/ V7 h
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-12 11:09 , Processed in 1.106670 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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