EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
, O, S. R9 o- R& R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  K+ a- L: v5 ]4 W8 f
这里有相应的模拟器源码,就当送给大侠了~~. T8 J8 b2 Q# _( w5 Z% C
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( N+ ^& p# ^2 V9 L/ y1 z  T能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& Q4 L" z; w$ N8 m. w! T
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  ~4 s4 M( Y4 _) f3 U8 `这里有相应的模拟器源码,就当送给大侠 ...
3 E: U: P# c" Q% l3 z
聲音部分(Audoi Process Unit = APU):
9 _" Q: V8 m' L$ C" E' ]' P4 O5 z% j.\NES\APU.cpp& C  a" n0 o7 G1 I3 _8 t
.\NES\APU.h6 ?8 X2 t  S; O  m( v. {+ w

  z( `6 [1 Y' V- B+ ]1 ^' ^6 E/ }" Z
影像處理部份(Picture Processing Unit = PPU):6 w4 z% |- Y5 f/ ^
.\NES\PPU.cpp
. l( P  L8 G( P% i7 I.\NES\PPU.h
% V; Z' [) ?5 V; O. J. O8 {$ b
$ [, C2 A6 E, c) ~如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。/ g3 Z% ?4 E* r) z/ R: {
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 Z& h- W) W) p. |2 [(由于很多专用术语和算法机理都不明白,所以看不大懂……)
) L* d* _1 d0 N! b: m//////////////////////////////////////////////////////////////////////////
: z  l; _% I+ Z$ a2 K( V8 s6 R//                                                                      //
! M. A  u1 t: O) y; a//      NES APU core                                                    //, c" G6 i* i. T* l6 x0 [
//                                                           Norix      //
" B8 ?  u% y4 J//                                               written     2002/06/27 //" x% O- z5 U! T# ~& u
//                                               last modify ----/--/-- //- j- B4 A* @- c5 i# p! W- G
//////////////////////////////////////////////////////////////////////////
, `% d0 m3 a( N! J+ Q#include "DebugOut.h"
: w' `1 X, u" d- i#include "App.h"$ T. J! k6 y+ \. T. t
#include "Config.h"+ N, f  s. D) B2 H; _
0 P( c& j& A7 I2 {  U* z" Y, U( K
#include "nes.h"
; e3 M  c" U0 }5 O# Z: \( C% J#include "mmu.h"
  y! k: T0 |3 ^$ a+ q$ N#include "cpu.h"( ~  g& B, Q- ^! `4 R; h# e" _& M
#include "ppu.h"" u5 i6 b( P0 g
#include "rom.h"
1 m8 A- T/ G& t* [! ?#include "apu.h"8 ]3 m$ O4 X+ A0 I' J

" ^5 O0 i& w( u" v) n// Volume adjust; B" n* {" ?4 u$ r' l2 {1 B
// Internal sounds
* s2 [# S. u/ R1 u' L5 G#define        RECTANGLE_VOL        (0x0F0)
# f) N- d0 t& P. J1 {#define        TRIANGLE_VOL        (0x130)) g) y8 q  a, h) B0 b
#define        NOISE_VOL        (0x0C0)
) U- J6 c: F0 }. u2 ~* ~: F#define        DPCM_VOL        (0x0F0)# x- ?, I( D; K
// Extra sounds0 j. |) V: K& }" n& z& p
#define        VRC6_VOL        (0x0F0)
: o0 s* Z" _6 Y/ {, G% a#define        VRC7_VOL        (0x130)" M  `* V/ G  m% R0 H, `4 a
#define        FDS_VOL                (0x0F0)
! c+ o; v  i9 G0 A6 B#define        MMC5_VOL        (0x0F0)
, T# @2 ^0 V+ [: G#define        N106_VOL        (0x088)
: P, p3 [7 t4 G+ I1 Y, w. u#define        FME7_VOL        (0x130)
  W* e. T+ C2 b  s: s, T; L
% S+ F" V9 B) }2 Q& V1 kAPU::APU( NES* parent )0 E. W" X6 v8 Q$ L) \* M
{
( g, F1 U; p1 n( Z  f. R        exsound_select = 0;
6 v& I  _- x& P2 ]. ~8 {3 a2 @& ]) G- i7 `* d+ K6 s: w1 k" _
        nes = parent;
) Q0 U* S' g: T; b        internal.SetParent( parent );
! @  j! H/ T+ P! O! R
" n6 q9 [! v8 S% k+ T2 a        last_data = last_diff = 0;5 F( G7 |4 p' I! K, k6 `5 j& r
6 ]# M3 Y9 s* z5 p$ P, R
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
5 m: u: d& k4 s! \1 O0 b. d: ?. b6 c+ h8 R& w- x0 _) ^8 Z7 a
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
1 h$ e" O$ b' a3 n        ZEROMEMORY( &queue, sizeof(queue) );8 N: Z9 K6 b* j6 k# q, r2 z/ J
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ e5 I8 m/ y0 h& `, ?  ]6 T' u3 `  y5 a- \+ ^/ b
        for( INT i = 0; i < 16; i++ ) {
' B. P2 \2 r  y; e5 m% a                m_bMute = TRUE;
( ?6 e4 b( y1 a        }; \% l, {( c  G* O3 N) Z
}
5 c! V( G  y7 [# j5 @& `
, D  u* V1 Y! v: `APU::~APU()
$ b1 y) e1 B; b  j' Y1 J4 T, J{, n9 e9 x2 d2 X; p
}. ?  V0 e( e  H+ }

! y6 Z" a, ~. ]- C( o6 R5 }. Z' |void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
9 y# e5 I7 S+ }& \+ s{2 m& w1 f4 ~4 i
        queue.data[queue.wrptr].time = writetime;
2 j! i3 Z# J, J        queue.data[queue.wrptr].addr = addr;' z4 q2 S, N/ X: B2 f) ]5 U
        queue.data[queue.wrptr].data = data;1 S6 Q- }! A: W4 ]" z) F
        queue.wrptr++;
$ O( G6 ?* |$ a; I: f7 O        queue.wrptr&=QUEUE_LENGTH-1;
* Z7 X6 t8 N- A! X* M/ C( f+ S3 n        if( queue.wrptr == queue.rdptr ) {: h; N% [; U: @$ C  h' [! S( F
                DEBUGOUT( "queue overflow.\n" );1 q5 N- t( J5 P+ m& R# d" f9 |
        }- c8 s% `: q9 W. C. a
}5 j$ u5 V+ U6 P

6 i- x, a3 L/ F  Z8 a8 D  kBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
+ |: o" g, @1 z{' s$ g% P7 j( C- A5 @
        if( queue.wrptr == queue.rdptr ) {& X+ f* P3 Y4 B( R
                return        FALSE;" W4 u) J' n0 u/ l0 ~; `( R
        }7 ]5 R, ?# G5 ^9 \9 f  @
        if( queue.data[queue.rdptr].time <= writetime ) {
$ I; ~0 W, U( T4 _# A! V- r$ C! g                ret = queue.data[queue.rdptr];; ?. ~. X  U6 G8 u
                queue.rdptr++;/ p2 [. |3 a8 X4 a, `1 M2 Z2 X
                queue.rdptr&=QUEUE_LENGTH-1;
. K8 J( U3 N0 P% u' Z+ j5 b7 W                return        TRUE;' l' `1 L( ~1 V
        }
2 D0 V5 Y; N7 t) m9 h$ O  C. D        return        FALSE;9 w- }  J! u: [! }$ r
}
" D1 A& G& Z0 P1 t
, X. }. S% C2 {void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )& B' Y1 k/ @* w4 q) O
{
' ?. \& t* E! e        exqueue.data[exqueue.wrptr].time = writetime;  N) ~/ f, d' I" F# A+ u3 K1 c. x
        exqueue.data[exqueue.wrptr].addr = addr;
& S  A  j, n# H& G        exqueue.data[exqueue.wrptr].data = data;
1 ]7 u$ m  s2 p+ h! s7 e" T        exqueue.wrptr++;
/ v$ C) }# n- \        exqueue.wrptr&=QUEUE_LENGTH-1;
- K3 }- \% r. D) T2 _        if( exqueue.wrptr == exqueue.rdptr ) {' w2 g- |& b0 P) ?+ `3 B( J
                DEBUGOUT( "exqueue overflow.\n" );+ B  Z. Y: W: B, g& Z
        }
2 `' ?) D, h8 O/ e9 g4 i}
  l, a. M; h* a7 y
4 ]4 d$ E2 E+ |# |# u* i- SBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )6 k* y) Q! g7 m' K
{# X( A2 @3 i) {7 h4 Y3 ?, y6 q
        if( exqueue.wrptr == exqueue.rdptr ) {) O; y" j( I: ?. Q+ l2 F
                return        FALSE;* C& D- k" n1 ^3 m7 b& s5 E
        }
! i$ O4 j; L) n        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
) @2 T' g, s% y+ ~% ^" V                ret = exqueue.data[exqueue.rdptr];. |( `2 u# F; e: L' h
                exqueue.rdptr++;% T: ?7 e' D1 Y& c
                exqueue.rdptr&=QUEUE_LENGTH-1;3 ]3 c) e/ ?( ~$ U: z7 e, Z2 G0 X
                return        TRUE;6 S/ {8 n7 B9 P2 _5 e
        }2 T9 h3 N3 L/ O$ L2 h( X6 G9 \/ T$ r
        return        FALSE;
/ W% ~7 ~1 H8 i4 X2 c}' ]9 {4 K. m( d- U) z* O

+ Q: v3 ^  ?5 t. X! Hvoid        APU::QueueClear()  y5 P( A& V  e4 e! Q1 x: K5 E
{- B8 I+ z( V/ ]% {
        ZEROMEMORY( &queue, sizeof(queue) );2 D. T8 S2 S* [" r4 L
        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 Y" F0 [4 j' S
}( Q. q+ u, @& P8 h* v3 i
% z& I% ^& a9 C8 D5 `& Y
void        APU::QueueFlush(). E/ H+ g% Q# n  v2 o  _( [
{
& s; M) w0 \' A- ?8 r9 t        while( queue.wrptr != queue.rdptr ) {% M3 a+ Z# k! |! a8 ]  d
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
& ^% g" g! p6 H' Y                queue.rdptr++;
8 W+ x1 l( h4 @1 G% H4 [% j* c/ P" P                queue.rdptr&=QUEUE_LENGTH-1;( R' g, [) A* i% O2 \" s
        }8 w$ U3 ?3 m- e! P$ @# p9 P5 ?
  @2 C( H3 ^5 l$ P6 i
        while( exqueue.wrptr != exqueue.rdptr ) {4 ]! I( B/ e- {4 G
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );8 U7 y7 U, K5 v! a9 L. K, v" Q
                exqueue.rdptr++;
: c/ u; M) f  u' y0 I: I9 r                exqueue.rdptr&=QUEUE_LENGTH-1;  p- O" X1 Z# t( e4 t) Y! P* j. |
        }
# ~4 Z6 `8 l& h7 g) U% j}  C! ^( T& W, O" {
. M. j5 x8 s9 s) R5 d% d
void        APU::SoundSetup()4 F6 D2 V( S0 j( w9 l
{
8 q# X, O: c8 z* Y& E8 |8 C        FLOAT        fClock = nes->nescfg->CpuClock;
( m  L1 q* [  u: [        INT        nRate = (INT)Config.sound.nRate;
/ K/ j2 k9 H  C- W. s        internal.Setup( fClock, nRate );
: }/ X0 ~- \+ ?; s) x        vrc6.Setup( fClock, nRate );
/ i$ m2 R: e  ?( y8 K% s/ I        vrc7.Setup( fClock, nRate );4 i/ h; f& p  p8 R
        mmc5.Setup( fClock, nRate );/ _4 H7 [4 d6 O1 I4 p
        fds.Setup ( fClock, nRate );- N# @% P+ o- K, W& x# u! m+ Z( Y6 r) ?
        n106.Setup( fClock, nRate );
" C7 L% T+ U7 I( n3 O        fme7.Setup( fClock, nRate );0 I5 Z: ^- ]6 D$ ^
}
7 F* i" B) V/ |' S4 u0 Z6 F3 I5 @- ^/ d5 N; ]6 g# |6 L
void        APU::Reset(): U. b! _: T6 \1 f9 m0 U
{
2 L) X3 L4 p9 B- h, w        ZEROMEMORY( &queue, sizeof(queue) );
) ]3 x4 M- [+ X2 a* v. e2 M! a        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 S3 P+ F% D8 o% C
% z) w: f# H: P# [        elapsed_time = 0;
: _) C4 S  U+ p& y6 X# I- k, _$ ]# _; d
        FLOAT        fClock = nes->nescfg->CpuClock;* @0 P6 @, }2 \( X% U4 L) x/ Y
        INT        nRate = (INT)Config.sound.nRate;  z; K  m0 G4 |& r
        internal.Reset( fClock, nRate );
$ x% N: Q; {; j1 M6 K9 |; l        vrc6.Reset( fClock, nRate );
* C! l& z6 U6 d* u& Z        vrc7.Reset( fClock, nRate );
9 I" ]3 r! g6 B5 X% X: C        mmc5.Reset( fClock, nRate );6 }6 h& y0 Z. \$ e; p: f) s* n
        fds.Reset ( fClock, nRate );
% p& E- x8 r* `* K- ?        n106.Reset( fClock, nRate );
- z- ]4 W9 r+ A/ H% q3 i& b! M4 Z+ l: f        fme7.Reset( fClock, nRate );
; v* |, v2 b0 q+ J# }! n' M
% K' P8 l2 [1 u# P2 c! e        SoundSetup();' x( c% J7 t) {5 R( M( d( i
}
$ h5 F0 F' J' t1 H* q& ]) l! \2 O- L+ W- ?! Y
void        APU::SelectExSound( BYTE data )) u+ K, k/ T; s7 H* j
{
% F% P/ ~$ o3 a- k! w        exsound_select = data;
' Z. ^) k4 S5 c- h, e2 D}9 H2 Z4 C7 B' j, g( F6 |+ o
8 ]9 r- [- N+ A1 y
BYTE        APU::Read( WORD addr )  B/ G- m/ m4 V9 A, k0 |) ^4 ^; Z! ~
{' E" @8 {4 N8 R) U7 T5 {+ w, c0 \
        return        internal.SyncRead( addr );
$ c7 h% L5 F8 Q/ ~1 T}
$ @* i: T$ i, L# l' m
, F) H4 J" k1 t9 d6 C* h4 P- ?, dvoid        APU::Write( WORD addr, BYTE data )
8 E* m: c, B& \% B- l% ^! {& z9 S{! }* |/ T. C5 P' T5 A' q2 y; H
        // $4018偼VirtuaNES屌桳億乕僩
9 `4 ~- [* f) z/ L; H        if( addr >= 0x4000 && addr <= 0x401F ) {
! p2 e( v7 q% v                internal.SyncWrite( addr, data );& m( b3 N  [/ l, I) n- u- C6 Q
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
* D( o3 e: e0 F        }5 h$ X7 n" G- w0 ^0 \
}
0 d! Y4 q) B" D" i. a9 ?! ?  O% v3 b& u( t6 X  @+ Q, c
BYTE        APU::ExRead( WORD addr )4 ~- h0 k) f1 S% @+ {: `
{
0 g- P! r8 R- I2 DBYTE        data = 0;
1 N4 c& I' T3 ?7 J5 O! S( x5 T0 n; a4 ?
        if( exsound_select & 0x10 ) {( H3 M$ U% _2 |: |/ o2 s) v1 b
                if( addr == 0x4800 ) {8 A4 I1 ]# l# y+ `
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );) G* g% S+ m# \8 I; f1 t
                }+ S3 i5 Z6 L9 D& @
        }
0 z: c- ~9 s$ X  N        if( exsound_select & 0x04 ) {# T/ W' ^4 q# o- `3 I
                if( addr >= 0x4040 && addr < 0x4100 ) {8 N! |, x+ {. a' g& Z
                        data = fds.SyncRead( addr );% w5 ]% m: q0 n5 n9 k2 {' `
                }
" u, v* r4 W' q% {0 J6 J        }
: i8 g7 d+ n/ N9 Q& F( o& e        if( exsound_select & 0x08 ) {9 X& c) L; g0 U$ \. o5 H. O( G* l! @
                if( addr >= 0x5000 && addr <= 0x5015 ) {
# b5 y2 ~( r& r2 O. J! i& J                        data = mmc5.SyncRead( addr );+ R* H* b. z( N: N
                }; E; O0 v" T0 ]1 |" k! _3 e; D( i
        }
, o9 S" I' |+ T& A
. _$ E& ?& p' t. r2 g        return        data;5 E" G. H& ~# O' D  U
}8 _" M0 u( }$ N7 S
- F- g/ h; J. I" o
void        APU::ExWrite( WORD addr, BYTE data )
6 @& m4 _" {1 Y2 |{
+ M0 g* `( b6 i6 }        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 A7 o6 N7 r4 x1 x* v7 O, ^8 p' w( B+ u5 D2 D; i: z
        if( exsound_select & 0x04 ) {
  W; ~* n+ a' o# r1 P% b                if( addr >= 0x4040 && addr < 0x4100 ) {
5 L1 |( |/ h$ f! r4 D/ U0 p7 C4 r                        fds.SyncWrite( addr, data );/ b" {2 o+ e8 a  o3 s
                }
9 l. v& t. y1 q0 q" N; q$ R        }
1 h# h6 y9 I5 x! ]7 |, s! ]! c
- m, D# x) _/ ]0 e9 l- P0 p        if( exsound_select & 0x08 ) {% n! \7 L7 c$ y! ]4 x1 `1 _
                if( addr >= 0x5000 && addr <= 0x5015 ) {" c/ D/ h7 A$ E1 T4 ^
                        mmc5.SyncWrite( addr, data );, e; n  @  x5 p5 {
                }# a- X0 ~* B# ?6 ^$ W
        }
' J0 i5 q. g3 m6 q& \}
2 ^! t8 {! r. H8 b9 @
7 j$ }9 B- ^; z: s- x! y. Q$ `$ Wvoid        APU::Sync()
8 o! V3 J4 d' m" y{& W4 M) `. {1 {
}( H( t0 g! ^. a% A1 Q( h4 Z0 z

+ Y  i+ Y4 H( n4 Xvoid        APU::SyncDPCM( INT cycles )
+ v+ t2 N: M; u& w) w+ N# I{) p9 t+ O& \2 I  i# }5 J1 `1 {
        internal.Sync( cycles );8 r4 t9 M3 V: }0 s+ ~2 h5 }  Z, D1 F

1 z$ x, ^- z- u* L1 y5 D        if( exsound_select & 0x04 ) {( U) p; D: h) V# d: u
                fds.Sync( cycles );
0 O/ y( t  T3 S3 W1 ~7 z/ n, s        }, |& C+ j, Q; _5 B
        if( exsound_select & 0x08 ) {
" P) [; f& [$ y) F, [0 J                mmc5.Sync( cycles );
8 F1 Z6 t. J  l, ~$ r- m$ X        }& U+ l4 O7 k' w
}
" D" S5 L3 [- D7 r% W5 p% n& i8 O3 q0 N- Q/ s! c5 a9 R5 S* V
void        APU::WriteProcess( WORD addr, BYTE data ), Y. b8 C+ J$ @9 m0 [
{2 h7 r9 d* g$ \6 N
        // $4018偼VirtuaNES屌桳億乕僩. _8 }" @0 `4 i* J* Q
        if( addr >= 0x4000 && addr <= 0x401F ) {$ q/ X( m; m) i  ?& E. K
                internal.Write( addr, data );
- v4 I. @" A& g. M8 X# i% `        }
8 l1 l" S7 L6 ]7 d+ {7 F$ F9 `* L}
4 L/ g4 F: j% g0 K+ s3 \6 X. F
. i0 f( I0 q' n& ?void        APU::WriteExProcess( WORD addr, BYTE data )
! |# G. G4 \) Y2 V% g, I3 T$ `{' e4 C, @+ G0 e
        if( exsound_select & 0x01 ) {
$ v) P% P+ f8 |% R. i                vrc6.Write( addr, data );
) d1 ?  ]  F- V- I* i8 o1 z* M8 @        }: d9 y, f% n5 @) T! d3 z/ o
        if( exsound_select & 0x02 ) {* E6 R- d6 @+ u% l
                vrc7.Write( addr, data );' v: I) L9 t7 H( w
        }/ q) U8 g& z) ?
        if( exsound_select & 0x04 ) {; H5 Y/ l& ]: p! e) I
                fds.Write( addr, data );) p( _5 }/ h8 {* {8 J
        }
7 b$ n: C' w; z* |( V0 C6 N- _$ }        if( exsound_select & 0x08 ) {
3 q% [7 x" k3 i* O                mmc5.Write( addr, data );* p& _; O# A2 ~, I/ a' ~' C
        }
  S- f; O9 B. \5 `        if( exsound_select & 0x10 ) {6 `" ?/ h9 C4 V; ]
                if( addr == 0x0000 ) {
7 L! k7 P4 [' F7 v                        BYTE        dummy = n106.Read( addr );3 }* Q; U/ e- U3 n
                } else {% b! r# ]( S5 r
                        n106.Write( addr, data );; G) a. j9 D) X2 |. `6 N' L+ g' H
                }
  q: B; D, t" c1 Q+ J: H' ~! K' S* }$ N* P        }
0 d- b9 h1 x$ I2 v  j2 q4 n        if( exsound_select & 0x20 ) {
+ h! ~, x- H+ n8 k, d8 C) p                fme7.Write( addr, data );
* z: C: y5 P- m        }9 l8 m. l2 x; D8 t* H' E4 C( N
}
. r  W! H1 [" {, F1 d, I% o3 Z2 L; _
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), i$ d  Z% u  e, w
{7 O" ^3 |+ s2 b! u( x) r, W
INT        nBits = Config.sound.nBits;) e' @. x* B  e- g+ a- F
DWORD        dwLength = dwSize / (nBits/8);
) X/ |" g4 o! x9 r! m" jINT        output;) G) W9 V; A1 \6 o$ q% D8 X  f3 C5 o9 |
QUEUEDATA q;2 z- D+ f& \+ e5 O- Q  s
DWORD        writetime;! O6 M# e8 L# S: u
' b3 _  A4 w1 K1 p+ _" z( b% A: C
LPSHORT        pSoundBuf = m_SoundBuffer;% j8 k& [% K6 ~! b, X9 q) P! P) _
INT        nCcount = 0;) D. H$ s+ X4 R7 z( o

0 }0 _; Z1 ]0 [5 vINT        nFilterType = Config.sound.nFilterType;
4 |6 T) y5 S* S" p& P2 m: j/ i
7 v% v  K  u' ^0 [6 _        if( !Config.sound.bEnable ) {
& s0 _9 k4 @9 }- {3 u6 P                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
4 @$ p0 r' k' R3 m2 l                return;7 ?6 H) d1 {6 f: A/ q
        }
5 _) g; i: ?( l; ^( X+ L
" l, u$ D# v( }" V4 u* t        // Volume setup# J1 l3 D4 C: a% z5 a3 @7 R+ d
        //  0:Master
% c$ @+ R  X7 g5 B4 f5 v4 ^        //  1:Rectangle 1
  ~& t3 k$ k* P) c% S        //  2:Rectangle 2
5 R) r; D, T1 V$ K+ H4 _8 c, i        //  3:Triangle
+ y( ]% z+ a  r6 F. v        //  4:Noise; V6 d! s, A! X) U/ ^0 z3 c
        //  5:DPCM
0 J$ ~! \' [0 J; ]) @% b( V        //  6:VRC6
0 h& a' }. R2 j# |9 N* q        //  7:VRC7
+ d; @  e9 w  Z        //  8:FDS9 Z0 J* f5 D% C% g+ o0 Q4 m5 y
        //  9:MMC5
( K$ |& H4 `, }: v        // 10:N106. v3 N9 _, \# E9 r  z
        // 11:FME7
' \5 s/ k( Q- [% ?        INT        vol[24];' R9 W5 D- K5 D$ M& J
        BOOL*        bMute = m_bMute;
1 i" f* c! D$ g7 C* C        SHORT*        nVolume = Config.sound.nVolume;
; l  W; W, l' N1 }7 t+ i
2 l/ w7 u$ ^* h2 h8 d8 n6 {        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
; W9 k2 U4 _- u! p" c" x- V  o9 {: f
        // Internal
0 P$ `2 O; ?+ n" e' U        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& }* V. q1 c1 v4 Z4 ]& j& d
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;5 S# }, r& E6 X2 W1 V5 W: e9 x
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
5 o; b5 E0 z; I" Q# b  }6 {0 Z        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
! f" _3 N; c0 P) b        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 p+ {; T( v, v% c! a6 V1 d# G3 i
" \$ e& q  `% n        // VRC6
' ^5 h2 ^/ H$ ~, N; B# `        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
3 J# S8 a: y5 h* x        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
4 Q) V( P& N! c8 f9 b* F3 E        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: k: B2 G7 o) f3 t& g3 K6 M
0 p! U* e* t. ^  Z% ^% e0 S
        // VRC7
( N( J5 y4 j3 Q$ e2 |) ?        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;5 h; K+ j% c5 y2 [4 `

6 [2 s2 m) n2 w8 V7 I3 H: S8 ?; b        // FDS
3 M1 Y" p; S( C  V( ~5 o% n        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
- K* w, d/ w3 z% V: a' ^" m
& X$ r1 X+ Q) ^0 J, ^+ g" g2 `        // MMC5
! Y: t' @. s0 t+ A) |+ _0 G+ d: N5 f        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
* O! G5 ?7 ?1 |/ T6 a        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& c# L% _0 ?1 K% ~        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 e+ k6 A! z, h  a& x  Y9 J; a; J1 c' ?9 T- Z
        // N106# A8 ]. z. c# A3 Q5 a
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, ~( C- R1 I9 }9 T: D* H! _        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 M  @% p) F" I9 W. k        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 z- ~) q+ r0 p9 l! [0 q2 z: K
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. t# c. [+ S9 ]6 R* A$ b( Z( W
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 D; I4 ~  p* x" V2 y
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) @) w0 O5 u2 G0 u. e% [0 s
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 r" F0 {; W8 J) B$ b, ]        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 X  p( y. {! p8 ]
2 r- `4 i1 J$ ]$ l1 |  K        // FME7# O$ }1 Q6 w) ~* X* Y
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: |, x% _9 k, L$ d% A        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' x, l+ I* ^7 h        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
# r8 t' H" `8 M
( m2 P$ _' U& Q& l: r/ Z0 S* w//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;0 E0 w5 Z3 x2 F- k0 ~, j
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
' B4 ~! t) H; M  f* ^  F: e7 [6 P3 h4 e4 s/ e. p+ Y# n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟- O. N# G( J. A( u
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 H9 }! N4 r8 q
                QueueFlush();5 j( H: M% B4 ?( b. M! p3 J
        }
. }5 \& ?% T/ Z8 E( E* M
) @& X: M7 {5 B$ \/ E        while( dwLength-- ) {
% i7 {- H6 V% H) [( w                writetime = (DWORD)elapsed_time;
  A  \4 s/ E- H% }1 x6 h* v
- d% W- O$ C) \                while( GetQueue( writetime, q ) ) {
" b% p+ z. }# x. l, C                        WriteProcess( q.addr, q.data );/ m7 W! K' @* y" M* [
                }+ k- g5 b4 g: `1 G2 x# ~4 n/ r7 L
7 _6 C' p1 W- P! Q$ M! L" C
                while( GetExQueue( writetime, q ) ) {6 |# v( A: ?9 Z& Q
                        WriteExProcess( q.addr, q.data );
" L7 {' J8 z# M4 h7 p1 i                }' R* `; T$ `" [6 J

2 K% h% C  v+ x0 [4 p                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7; K" C& Q6 g# Y7 v: u
                output = 0;
% q; ~3 R$ E( T$ e% d                output += internal.Process( 0 )*vol[0];( |- l1 Z* J" P- A5 N* i. i; D
                output += internal.Process( 1 )*vol[1];
: k# Q# m0 M8 E; L2 Z* H4 l; e                output += internal.Process( 2 )*vol[2];3 `: {; @3 z# a; g* a+ ~
                output += internal.Process( 3 )*vol[3];
# |. e$ p* D6 p9 r5 W. y                output += internal.Process( 4 )*vol[4];
+ X  |$ S0 g# l4 W0 U2 u* l- ~! S8 Q# p9 a3 g7 o7 u9 _
                if( exsound_select & 0x01 ) {
. N9 Q+ _1 x6 T  i$ w' H                        output += vrc6.Process( 0 )*vol[5];& o6 y1 |4 z3 U" J# l/ H
                        output += vrc6.Process( 1 )*vol[6];: M8 k& c6 h' l% w6 A% Q
                        output += vrc6.Process( 2 )*vol[7];$ g7 Q& T+ a1 A) }9 Z" j
                }
, C4 w" w1 x1 K4 o# I  i/ W) }% E3 F                if( exsound_select & 0x02 ) {
! ^9 I! j% Y3 `; G$ b: M0 s% v% u5 H4 W                        output += vrc7.Process( 0 )*vol[8];+ E- Q7 c% i' i) k! s1 M
                }
" S1 r' `2 V& r: e* e9 P  Q                if( exsound_select & 0x04 ) {
. [$ K+ z, I- ~% k8 L                        output += fds.Process( 0 )*vol[9];
+ V3 v4 p. {  @) o# ]) Y                }5 h" S5 v, C, d" ^
                if( exsound_select & 0x08 ) {# j- i) x1 t( N5 L3 X
                        output += mmc5.Process( 0 )*vol[10];
: h7 `7 G: c* f: d7 Q                        output += mmc5.Process( 1 )*vol[11];
' F) ]0 l2 H+ }1 @8 N                        output += mmc5.Process( 2 )*vol[12];% }# |9 S) n" X9 c: N$ M: E
                }5 Y8 W* i! u7 w' _9 z# F0 n& _9 ~
                if( exsound_select & 0x10 ) {
# w, ^0 O, m) L- q# }  x  r& ?: y                        output += n106.Process( 0 )*vol[13];
9 }, E; v2 n% }% i" \) I% z                        output += n106.Process( 1 )*vol[14];# n9 ?) ~. s% M6 r% w
                        output += n106.Process( 2 )*vol[15];
7 g3 j+ ?0 y  a                        output += n106.Process( 3 )*vol[16];; _7 m% T$ ]/ B$ T
                        output += n106.Process( 4 )*vol[17];# q  O/ [: c# Y6 |
                        output += n106.Process( 5 )*vol[18];
5 ~% D. n  k  U, _                        output += n106.Process( 6 )*vol[19];
9 L5 C- \2 A' \  o+ N! a                        output += n106.Process( 7 )*vol[20];
, v/ X, Q% Q' ^                }/ M1 L9 h- s+ H1 A! T
                if( exsound_select & 0x20 ) {
/ D$ l8 Q! G- r* [' x$ X/ C                        fme7.Process( 3 );        // Envelope & Noise3 I1 t- D8 q5 h6 U. B# U
                        output += fme7.Process( 0 )*vol[21];/ T* b- q9 g6 }0 W6 r
                        output += fme7.Process( 1 )*vol[22];
7 T7 U; d  ^, ]  d+ X! l0 L                        output += fme7.Process( 2 )*vol[23];. G7 m& T7 h( x# ^* v
                }
" L+ A. t7 C4 s* h8 @* N' x% o( j/ p8 ~0 D& e+ I
                output >>= 8;
$ R# T5 b6 B( i+ y2 V: ]1 v# y4 i7 E
2 ]+ F5 L4 D5 J5 D; O4 F# r                if( nFilterType == 1 ) {
  R7 Q. z! ~  U                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
: w6 f" L: b5 C# F0 P                        output = (lowpass_filter[0]+output)/2;
6 P' f% F5 H1 Y( q; Q" K0 q/ z: ]& a                        lowpass_filter[0] = output;
9 ~% V" \; i6 V: O                } else if( nFilterType == 2 ) {- L8 f+ r$ W( O8 `, ?% Z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
$ \% |  z# A4 r                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
+ r  y) ]; i' }1 g5 q6 J2 P                        lowpass_filter[1] = lowpass_filter[0];
- N; b3 y8 _" l0 J( ?                        lowpass_filter[0] = output;
4 o' ]3 S5 N$ K                } else if( nFilterType == 3 ) {; s( h( Z( ]+ `6 j& H
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)2 w+ i1 C0 B2 H- i
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
% s3 Z8 @+ X6 l                        lowpass_filter[2] = lowpass_filter[1];$ A6 L4 o5 i7 f: y( X  Q
                        lowpass_filter[1] = lowpass_filter[0];( E  g/ E' t/ F, F2 v; T: l" q
                        lowpass_filter[0] = output;
+ P/ h( ~1 t( T, t2 Z' p$ K                } else if( nFilterType == 4 ) {
6 F8 p2 r' U9 _6 B1 P( F9 N" m                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)8 Y1 D0 {2 V' P) `
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
$ {& |5 u$ ~- F& a) m9 N2 s7 I% T1 w                        lowpass_filter[1] = lowpass_filter[0];  Q& }' K' M1 |  l5 W  ?
                        lowpass_filter[0] = output;
" o9 r- B1 b1 [. U  I) @. `# A                }
5 t# |; F/ {# S/ g7 j9 m5 ^
7 t; y8 z5 H& a- I! q( H#if        0
: [5 C# w: {! ^$ j4 A) X/ p8 I                // DC惉暘偺僇僢僩: a( r) [8 T8 A7 S, K) Z
                {. ^# h" n* E1 {3 p8 c9 _! E, Q6 g
                static double ave = 0.0, max=0.0, min=0.0;
2 [  y  }0 U2 I! q5 f                double delta;; N$ u9 b2 p8 b. ?
                delta = (max-min)/32768.0;# o0 |& P/ @' i% q+ W
                max -= delta;
1 Y- Z# ^( h2 J9 g/ I                min += delta;
2 m: g, Q9 b$ ~                if( output > max ) max = output;* c- @9 [0 x9 S- b
                if( output < min ) min = output;: o% `. Y; C# w" t! Z
                ave -= ave/1024.0;! m  v# i3 o9 G2 u# D) W
                ave += (max+min)/2048.0;
. O# [/ l+ l# v1 D: Y8 r$ x7 I                output -= (INT)ave;
1 X$ h" A4 z; `                }! G4 U( y! R% Z2 Y% u! b1 \( h+ m
#endif
+ z) t8 u; n' B; G( O) Y#if        1
9 b9 I' F* b/ Y, T( r5 J                // DC惉暘偺僇僢僩(HPF TEST)& J( A0 @7 D* w  J! B2 Q
                {! k3 U& j& G1 n( Y' n% V. d( y, _
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" _' H0 c) O, s& k# n                static        double        cutofftemp = (2.0*3.141592653579*40.0);6 j$ _0 b) G* x5 J2 Y" {' e2 [
                double        cutoff = cutofftemp/(double)Config.sound.nRate;8 \9 E. H7 E3 L! L+ C# O9 Z/ J/ }
                static        double        tmp = 0.0;" b* \7 _$ ?3 D9 l. \; X
                double        in, out;
) }# d' ~& P0 v6 Q! h
, `; e* ], U. x                in = (double)output;
) H4 [/ U, O* y: w& g                out = (in - tmp);# q" L0 z* P5 F5 Q9 r" M5 r, E
                tmp = tmp + cutoff * out;0 A6 J$ b; i5 O
- ?, c' ?; t3 \3 t% M, q4 p  ?! Z
                output = (INT)out;  Z1 O* }& ]" L4 J
                }
9 Q9 U5 G6 k* E% Y#endif* {: M. l2 z' _6 E! f
#if        0, \' @" m3 [! _& Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. u7 s1 l& K# a& @. `$ k- _) O, ]                {
' e) a+ m% |  x* X- r                INT        diff = abs(output-last_data);
3 E" g5 l4 s" m                if( diff > 0x4000 ) {7 B$ ~+ [2 `% D4 Y, u1 Z
                        output /= 4;. A/ l# X/ k# f5 n. P
                } else 6 O9 a& ~5 a6 s) R- D1 z) W3 B
                if( diff > 0x3000 ) {
3 g2 K: }' R; q3 X' }) }* h# Y                        output /= 3;
* I. U  C! R9 F8 N2 D. F1 {                } else
. r4 }3 ~; [8 G9 N( }  U# m: J                if( diff > 0x2000 ) {, N' V% H: f! C! N
                        output /= 2;
( o# ^, }6 [0 S                }
# z3 W- \- ]9 k6 L" q                last_data = output;7 P; v, }8 \8 H% n' h0 v
                }
6 B, d2 E+ e) z% ~7 N- ^#endif( m. r8 S/ H* i
                // Limit
) D" @1 x3 S) g  o) X6 w                if( output > 0x7FFF ) {
* F& @/ s* D1 Q5 X                        output = 0x7FFF;
7 v3 l, y/ @: v2 }6 q                } else if( output < -0x8000 ) {1 y3 j# }% e/ ~. Y. @
                        output = -0x8000;. z" t0 |7 }' P- B6 o
                }
8 B& A1 U* q- l5 R* E$ @- k
4 O/ Y8 {; ~0 k- [# T* F* E) A                if( nBits != 8 ) {( j# H, W6 N5 Y0 m5 ~
                        *(SHORT*)lpBuffer = (SHORT)output;
$ s; |9 ]: J! N  v+ m                        lpBuffer += sizeof(SHORT);
! A- f$ K" A2 C% T2 @' e7 F                } else {
, u, \3 c0 w& X% d1 A                        *lpBuffer++ = (output>>8)^0x80;. Q) ~6 S' w6 _4 ]
                }+ j2 w5 A, [% q) ]  G" w7 i' C+ X
; s+ u  a( n7 z: m- k+ F
                if( nCcount < 0x0100 )
, W, `# v7 e  [" w" T; X                        pSoundBuf[nCcount++] = (SHORT)output;$ W9 Q4 }% i+ m2 k4 `; j6 h# [
- z8 z2 q' S9 d6 |8 H
//                elapsedtime += cycle_rate;
$ t( R7 S+ }; U8 |4 G& W* d                elapsed_time += cycle_rate;
' y' }! `; G9 w# ~        }6 \1 M( `8 X% n2 F( K9 w4 i
, }9 m  z" n+ i8 w: n3 e) V
#if        1
0 ~- i* S9 C& q! P- v        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
4 [4 e' d) I1 U* Y7 k, V/ E                elapsed_time = nes->cpu->GetTotalCycles();5 r( i0 N7 W; L- m  U+ U
        }
/ U9 |7 ]* _6 I9 R0 \( C2 h        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {( W! w& d) L% B2 A" e2 w3 d& \
                elapsed_time = nes->cpu->GetTotalCycles();
6 A, F0 {: P2 _9 a: @7 v        }. N9 N" K6 B' b  X) T: s
#else
: g- [" J4 L: h' C9 j; {* o. A        elapsed_time = nes->cpu->GetTotalCycles();
4 k2 i5 l) d$ E; j" [! d. ?( i#endif2 L6 p% i5 @* p& N, l
}
4 s; d6 n1 \- n" o  t% U1 w3 {" S8 N7 e9 Q8 i) u# z6 s
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
2 \: U% w; O/ R. J' S9 OINT        APU::GetChannelFrequency( INT no )
  D: i5 g2 x) A* I& T{
4 L' ?  z1 W2 w9 Z3 J        if( !m_bMute[0] )
$ H% d9 F, S3 v) @: {( H7 t" O                return        0;( l" q' g* R) G0 d3 n0 \
4 ?1 }& F# `% @" U
        // Internal) `% P& O; Z  O, E* l  x
        if( no < 5 ) {$ v6 k8 F( f! @; x  n
                return        m_bMute[no+1]?internal.GetFreq( no ):0;" n- o- Q3 u: M2 j. J
        }9 u% R) d" U8 i2 F
        // VRC6- ~- N! p! s' r$ x- Y3 O
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
/ k- Y, d- Y5 ]% @6 ~                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;- q1 p+ l& e- ~; S& I$ t
        }
4 F3 ^. N3 J) V* H! B7 v        // FDS
$ T; t9 s9 G/ H) s  _8 r- X7 {' {- @        if( (exsound_select & 0x04) && no == 0x300 ) {
4 E7 L( J: I/ i' `5 N                return        m_bMute[6]?fds.GetFreq( 0 ):0;
/ F( |5 Q% B, W2 b! B9 ^7 w        }
: v3 p8 m4 Z9 o) F* X) U        // MMC5
/ h1 [9 G) g4 C& ]8 q& f  ?        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- I+ R- N+ t" }7 [8 y                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
; n% r  W) D3 [2 R6 d7 g, T        }
' p1 F  z7 }- ^% M9 Y' }# `        // N106- T5 e! F8 o( x8 q& q3 n/ _6 W0 q
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
3 v3 y/ v' x$ Z+ o8 J                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;0 F2 y( [" H. i8 D9 q4 @9 `" R9 V
        }+ {( P" r& h) I+ f. N9 k
        // FME7! R( ?& J+ F+ E- }2 f+ U
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {- \9 X. L" |( i$ B' D
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
0 o2 R. v" J6 M        }
8 B- c5 c6 R  T- F        // VRC7
- f, ^( h8 j8 ]. J; Q2 A$ L        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {& }6 S  z6 ?9 @
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;# I, N- b: K. G( i# ]) ~
        }. V0 p0 A. w- p6 U' ]' k5 M
        return        0;3 @% i  ^+ v# j6 X$ M" D- g
}2 m8 v1 c/ R7 A6 b& s
9 P0 j4 B: u7 }3 j6 K9 l
// State Save/Load% Y% o( X2 z. G/ X/ I; T5 W6 b2 ]* v
void        APU::SaveState( LPBYTE p ): |0 y/ S- z* B: L
{; f& w8 ^( D6 I6 S' G8 W
#ifdef        _DEBUG6 p5 [' q9 ?( \5 |) Z
LPBYTE        pold = p;- b, m3 q! }! ~1 T- F" Q) {# \/ l
#endif
9 s0 J# o6 b/ b) h7 ~/ C! E. E2 e  q; @0 a: o
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
* r; R' g+ e' z6 G1 V        QueueFlush();
+ u4 M% V) _5 u# h! K! p4 T
; |# o$ y9 O8 c3 v8 k9 C        internal.SaveState( p );
5 F! S( k4 E. l( B        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; n$ Q) |7 J1 {* c6 x
& j! U" v% ?, T# J6 x* N
        // VRC6
! o) {5 ]0 b8 K1 b# E4 K1 U        if( exsound_select & 0x01 ) {5 ~' G4 G: k! j+ J- S
                vrc6.SaveState( p );7 l5 K" N( @: l4 u
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding: c4 T! R- E3 `& a3 w4 d/ C' x
        }
0 [2 t3 f3 ~2 @! H        // VRC7 (not support)8 ?8 V: [$ X' H' K& R
        if( exsound_select & 0x02 ) {
! Y4 O' h, J5 y( K4 u                vrc7.SaveState( p );: o4 e2 _- H4 E' y* ]% l$ I
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
- e8 Z9 ?, ~; T6 v$ b. J9 ^) z2 t  f        }
1 y9 w4 b: m, G; w        // FDS
" I- d, |: k, ~        if( exsound_select & 0x04 ) {
7 ~3 n- d& i4 V- L8 d, K                fds.SaveState( p );$ o. _$ x$ ?4 t# [) {- R( `
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
8 c/ s5 E; q% e( B        }
: {9 z% c( y! Y) h        // MMC5
) q, S" e: p) x) H! \3 P8 w        if( exsound_select & 0x08 ) {( U# ~6 L& j' ?% H
                mmc5.SaveState( p );4 O1 |2 d2 s: m! J% }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' M, ^; C9 N2 ]; V4 M. [% K/ G6 a
        }
0 a# ~- l; W) |* b6 \$ O        // N106( [( d- r' Y/ |3 }
        if( exsound_select & 0x10 ) {* P7 \6 o  O! f* T% R0 _4 K
                n106.SaveState( p );, V6 k+ w6 D' n( K; g2 s) o
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 i5 e2 ~" H3 H& n* j$ u
        }! s) R. `' B' }3 S( U
        // FME7
2 O6 ?2 l. C4 a% S+ j% Y( m: W, b        if( exsound_select & 0x20 ) {1 Y( O- ?. b- |
                fme7.SaveState( p );
$ b% y% }( N, B0 h1 c% W                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
/ b. @0 W% X* c* ]        }9 }* W, q8 m& R4 \  _
# m7 L( H, m4 @! |$ {$ k2 @
#ifdef        _DEBUG. y. K( e( b, ?4 S  v
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 z' h$ J0 X8 _# E0 G% V$ G. J#endif
0 ]& \8 x' T4 O3 `/ _& P8 a}
& ^" w1 x8 E  X& i; e
, d8 s! n8 E! t  }8 V+ w* uvoid        APU::LoadState( LPBYTE p )
3 p% [1 v2 ]& e# e6 A; u, v4 ~6 W{
0 j: Y( P" B: Q- z& x        // 帪娫幉傪摨婜偝偣傞堊偵徚偡& D9 c! S$ A' T7 h# M, Y' i8 y. h" s2 n
        QueueClear();
% O' Y' }; O* E" ^; z: \: c5 s! v9 l. h
        internal.LoadState( p );
  k* \3 j0 T, G8 p) X& X        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
( x7 M- `3 h. m8 |4 D2 f
6 k0 U6 V% r" A5 P( S8 X9 }; Z4 }: e        // VRC6
5 ?0 O9 [- S6 i1 v$ y        if( exsound_select & 0x01 ) {
' ]" Z5 r8 ]4 n, N* \                vrc6.LoadState( p );' b5 J7 r7 s4 Y2 S& `6 z
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding5 X: T6 P( U2 v6 i. r0 `
        }; a, z" D! y% t6 j: y
        // VRC7 (not support)
0 p- b: {) S4 h( _        if( exsound_select & 0x02 ) {
, i! B6 ^3 |! V0 c- K                vrc7.LoadState( p );9 p4 O7 {: ~+ @6 S' D4 W
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 t; R$ ^# u! Z* ^+ F* @9 A
        }2 H7 r& m! b/ z/ J! t
        // FDS
. G5 n! Y( m7 R* \3 u        if( exsound_select & 0x04 ) {' p! _4 s8 L3 i# `1 i
                fds.LoadState( p );
% T" g8 I" i! Y$ `1 V3 S$ |                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 X: V, J7 [7 r2 h9 K: G$ d! c        }" R  j/ ^4 H% {7 [6 B2 J
        // MMC5! I! f8 N: t: _' ^0 v' R) t& q
        if( exsound_select & 0x08 ) {8 c, z# n( Z+ f  A7 u& j
                mmc5.LoadState( p );
$ s1 F! F" g( |5 r; p; |; O5 `9 l                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' \0 s, N6 o1 _4 I$ `0 N
        }
4 b1 o- x. F! A* R        // N106( B  {) m1 p. w
        if( exsound_select & 0x10 ) {+ C- k- o. M  W7 e& S* |
                n106.LoadState( p );3 y( z4 v) r3 b' D6 ], |
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
7 k' S+ Q2 v( k9 c        }( f- n( r, B! f
        // FME7
: V  c8 |- w' K; E7 x        if( exsound_select & 0x20 ) {8 U# `: I4 u, @* |% c* `
                fme7.LoadState( p );
8 P+ R1 _5 c  M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding' \% B6 R- K+ ^3 g7 f8 Z
        }: a4 R3 b2 z5 t% K1 E
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 / m4 c0 Y7 f0 d* D5 i& ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。& M, k7 ~1 r: u- H" J" h, ]3 G  G' |
感激不尽~~

9 @1 H4 _  w$ w, ~( e5 l' P" a恩 我對模擬器不是很有研究,
8 r' t3 r# z8 y! l4 O3 s雖然要了解源碼內容,可能不是很困難,- F7 I4 V* G! V* u. U, d2 U, x
不過還是要花時間,個人目前蠻忙碌的。
4 |3 l% K' u0 j3 ?, D  _8 G" s" O+ S" Y, e5 V: h* Z
給你一個朋友的MSN,你可以跟他討論看看,! U: ^/ c, z1 {* F6 j
他本身是程式設計師,也對FC模擬器很有興趣。
3 ]# e! R0 v4 b. ^$ O: @# G
5 H9 ]! |  L9 i+ D" l3 B8 nMSN我就PM到你的信箱了。
, }3 E$ M! c7 d5 ^! y- f7 H* k
9 R  v: T2 Z1 C! U( X/ K# K5 s希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 , u) p% _; i7 k# Y: Q+ w) \2 b9 y0 P( b4 @
呵…… 谢过团长大人~~
$ J" k, J3 d& g4 o1 W+ N+ V

: I' C; E0 l% W% Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
4 U) C, ?% }2 Y5 m! B0 Q团长的朋友都是神,那团长就是神的boss。
" V; L5 `6 K  a* j
哈 不敢當,我只是個平凡人,/ L4 m+ T5 ?% D. P) u. L
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
0 w. N- ?  i" D3 n5 `* _: d9 WZYH$ F4 g& ~. M1 n* J
QQ:4147343062 r- H( J7 z  Q. g* O+ P5 J
Mail:zyh-01@126.com
" y( b' O( {  f* v* t" x1 _+ Z* s
" G6 E# L1 B2 d% J8 h他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . {) j2 Y# F# n. _( u6 n. ]
再次对团长大人和悠悠哥的无私帮助表示感谢~~
! J  _9 q) F6 F& }2 ~+ {
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-29 14:39 , Processed in 1.079102 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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