EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ |2 s& Q0 k5 b* A. e+ y3 w
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ B4 o- g+ }8 V  S4 C8 Y  P4 {* t1 m( f这里有相应的模拟器源码,就当送给大侠了~~
8 y; g- [: A( o) Vhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 . W! g( O0 c9 i( J  p( ~) `$ o
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。" y. U0 D4 ?. i! e( y8 O
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' G% m( o1 `9 W) D5 l1 w
这里有相应的模拟器源码,就当送给大侠 ...
6 v/ a) g" x8 f6 Z
聲音部分(Audoi Process Unit = APU):
& S) J7 ~2 N  u* r; E.\NES\APU.cpp, P/ w  b* _2 i8 r9 \6 o6 f
.\NES\APU.h7 v0 ?! w2 Z* N
, X% `9 L/ }% R. a

$ F& Q# G2 r+ M/ M. `影像處理部份(Picture Processing Unit = PPU):
6 t0 f$ Q: Z/ m" c- H" V.\NES\PPU.cpp
; e5 ^: X4 C4 F  G5 p* O: Z) [$ d5 g.\NES\PPU.h) X0 T! k, ?4 d
% _+ B1 K* n+ H
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
# M8 @( R5 b+ |4 g/ i(由于很多专用术语和算法机理都不明白,所以看不大懂……)* ?- J0 z" y7 F) x" a; w0 X
//////////////////////////////////////////////////////////////////////////
  N- m& f2 v9 {* Q7 b' H//                                                                      //; Z( |# z3 M5 B3 w$ y  `
//      NES APU core                                                    //3 n: F& G8 F1 ^, M
//                                                           Norix      //) l7 Y0 f. ^, O8 l/ x
//                                               written     2002/06/27 //- q& S* |: C% ]: s& i& L( B5 W
//                                               last modify ----/--/-- //
- n' G) p/ E3 v7 K//////////////////////////////////////////////////////////////////////////
, E) b# j2 z0 V9 w#include "DebugOut.h"5 r0 I# B  _. s# y) w
#include "App.h"/ [$ P0 I1 `- P
#include "Config.h"
% w8 Y# _& k* ]9 J
/ S$ U, ]# D" f7 R& y* Y0 j. @0 _#include "nes.h"7 s, W8 m7 t$ v7 s5 F# z) h
#include "mmu.h"
8 S3 p# \/ f/ ?; @#include "cpu.h"7 j% L3 Y& c$ {" P1 B% l: K, Q/ P: ~
#include "ppu.h"
  s2 B8 q8 Q& T4 h3 Z#include "rom.h"
9 h' p6 l( ?9 K- v+ t#include "apu.h"4 l! x# O) ?9 y6 [* f* r9 [
0 n% R% N; E3 O% G- X9 a2 I0 y
// Volume adjust0 {1 W& `/ g5 b6 J. s, `& ~0 N$ ~/ n4 u
// Internal sounds3 [: o: W( X' x* q1 a9 p
#define        RECTANGLE_VOL        (0x0F0)1 M! F& d* k+ _% g  z: S
#define        TRIANGLE_VOL        (0x130)
/ ?/ i; Z( a2 M#define        NOISE_VOL        (0x0C0)
" ^( f6 a% H, e$ J3 J" k#define        DPCM_VOL        (0x0F0)& E9 J, i' R* S' o4 Z( I
// Extra sounds
, O! [: z* I: V) v3 [7 u, z3 o#define        VRC6_VOL        (0x0F0)" F7 b: M! K. }8 i# V' j, E" r! I
#define        VRC7_VOL        (0x130)
5 s9 r4 |2 p# k, [#define        FDS_VOL                (0x0F0)
) M% m) f- T5 g/ O* P#define        MMC5_VOL        (0x0F0); b- M5 O) I6 I% ~, i2 A
#define        N106_VOL        (0x088)
) A1 U: F# r: V& f2 G#define        FME7_VOL        (0x130)% G9 W+ |1 \& a8 u5 C
, B/ {2 C4 @7 D% R' ?7 u
APU::APU( NES* parent )
" [7 Y0 h9 ~7 e: L3 l: y{6 R7 i- t8 O2 J) |
        exsound_select = 0;
* S5 ]  }. O% |9 v, g, ]. T9 u1 m5 d3 b* k# ~1 e
        nes = parent;; b# \( ?9 Z% S. K6 G; Y4 G$ a
        internal.SetParent( parent );1 s$ f# E- s# b" J4 c. r$ U" B
- g: B2 u" x6 r/ M/ |8 s, y
        last_data = last_diff = 0;2 [( o  d; |, o

2 s3 d" `% z0 Z5 ?0 D# @+ _4 v- l; o        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
, V3 E8 ]1 I" I5 U- Q8 |* m' t  l4 J/ E0 s! }( M  w+ R
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );+ f! K8 r  b) N. H3 H. n8 C
        ZEROMEMORY( &queue, sizeof(queue) );
5 [- h4 M! ]6 F* \        ZEROMEMORY( &exqueue, sizeof(exqueue) );! s8 d+ t, g* }+ A% J6 F

( |, F0 b( |1 R  I0 u; g. J* G$ M        for( INT i = 0; i < 16; i++ ) {6 e2 j1 F6 d" b0 e5 H) a( a$ o' f
                m_bMute = TRUE;3 R$ Z2 A$ V& L
        }  p6 \. _7 x: u0 I5 b: i+ j  ^5 Y' ]  B
}) Y5 B8 C- g3 F4 ]6 c4 }) P1 m
7 t/ A$ }) O/ Z: N! s8 a2 E
APU::~APU()
0 e7 n4 Q4 v, D1 M{
( e6 B( l. q4 [1 V- n}8 `6 d* Z; x2 i. W- X2 Q  O8 ]$ F4 e

/ U0 g; ]8 e1 f( o9 ?void        APU::SetQueue( INT writetime, WORD addr, BYTE data )( ?* H5 Q' h$ M3 t- {. t+ A* _
{) D& c* E  G1 o( B% M
        queue.data[queue.wrptr].time = writetime;" {* Q  {! J) n, a  l
        queue.data[queue.wrptr].addr = addr;% ~6 P; G7 u, {! u: v% r  x
        queue.data[queue.wrptr].data = data;
, [9 H2 P. G( k5 r! D! I  n' Z        queue.wrptr++;
9 E( A- b, }7 L# J        queue.wrptr&=QUEUE_LENGTH-1;
: |; i* i9 c3 N" q& F$ q        if( queue.wrptr == queue.rdptr ) {; S, g3 `: v% ~8 ~
                DEBUGOUT( "queue overflow.\n" );: d2 P8 x5 d) l0 s; M: g% ^- B
        }) n1 R4 H" E9 `: v* W1 L1 j/ w
}
% P" ?  t7 U$ z! C, A! d- l. i- F
9 }9 O! E3 ]8 |0 IBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )  }* ^& i0 v+ Z5 M
{; L$ c2 x" L. V! S* R2 L
        if( queue.wrptr == queue.rdptr ) {" t' `5 G: I/ k5 F
                return        FALSE;
" }% f) u3 K) I+ B        }# |$ b+ e" w9 K5 R
        if( queue.data[queue.rdptr].time <= writetime ) {/ A+ X6 g; f1 y: |# U: S
                ret = queue.data[queue.rdptr];; x5 m/ p$ ^1 c" t: |+ x
                queue.rdptr++;# K% l6 a( o9 a) a( {
                queue.rdptr&=QUEUE_LENGTH-1;
- T( ~$ y3 \1 t2 N9 h, P                return        TRUE;
1 w$ p! l+ B; Q" X; w  v5 e5 L        }  _, s% G$ p9 m( S! j
        return        FALSE;" e" x- S! m4 r" j" P1 e
}2 D# U3 [, S6 J) z% H7 g

3 q: i6 ^: l8 C% j( a$ D; F9 ovoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )( A2 `8 ]' d7 `; ^' D: \; p) Z
{
& X0 f# P3 N; A) @1 m        exqueue.data[exqueue.wrptr].time = writetime;; ]" r  g% w/ z' U# m6 s9 X+ Q
        exqueue.data[exqueue.wrptr].addr = addr;
. R3 w2 U) W+ Q. w. L! L4 m        exqueue.data[exqueue.wrptr].data = data;
) j9 B3 ^& U3 i" u# I        exqueue.wrptr++;4 [& O" _% B# ^2 E, Q) z# K
        exqueue.wrptr&=QUEUE_LENGTH-1;' v8 \. c' e  p: R0 @3 J
        if( exqueue.wrptr == exqueue.rdptr ) {
+ F  ~& p, {4 p5 g4 C; j0 y$ m                DEBUGOUT( "exqueue overflow.\n" );
. G8 H3 v4 N5 b5 t        }
4 P' `" G+ _* m5 F. n}
+ h: F" X- y9 W
+ g- h; u/ n' S( ^1 O0 sBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )  ^+ F, a, ^' F- p# F
{+ h# Z5 x; o6 q
        if( exqueue.wrptr == exqueue.rdptr ) {
$ G( v3 M4 {$ O( X                return        FALSE;$ a( \$ L- u. s7 p
        }$ z3 \( M/ L, l$ b, L8 r  J+ A
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {( Z8 s" r5 F! _) e- i4 P" Q
                ret = exqueue.data[exqueue.rdptr];
0 y" C1 Z, e! H8 P3 c                exqueue.rdptr++;0 \0 R- }1 P; v3 R& k6 t0 F
                exqueue.rdptr&=QUEUE_LENGTH-1;; w4 S: v* P" c3 ^8 W* b8 t& S
                return        TRUE;
+ x8 `4 W2 c6 g: S- U  _        }9 A/ x4 k- O* U( F' ^) g# J0 _
        return        FALSE;
4 R3 p8 s+ `, F}6 ?/ P* }7 d- f
. @8 y3 q7 E5 Q% t; Q
void        APU::QueueClear()
( D0 P# z( n2 g3 h. _* x{6 L; @  e& \. _  ]/ {. S
        ZEROMEMORY( &queue, sizeof(queue) );
' f3 I0 z4 q7 T        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' G& @, G6 d6 q8 Q* V# Z}9 |) `$ @# l5 j' G

9 ]- u# J: w) jvoid        APU::QueueFlush()! X6 X4 x5 M6 X8 c( o. V, |
{5 m7 H6 ~/ M, K
        while( queue.wrptr != queue.rdptr ) {* U* t$ D$ `% S" D
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
9 Z4 o  n1 O) W" ^" \                queue.rdptr++;# ^! l: h8 \$ Y' @$ V
                queue.rdptr&=QUEUE_LENGTH-1;
+ z7 J) M) u/ `# f1 h) G( s        }% q. |; b  p( d4 G
1 K  c3 F3 q1 i' j9 H" B& {
        while( exqueue.wrptr != exqueue.rdptr ) {# h9 P- s0 Y% ^" B% R/ \+ ^5 C
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );# o5 a9 o" H$ I5 c! i4 |
                exqueue.rdptr++;! m$ j; }$ T8 a, D: F
                exqueue.rdptr&=QUEUE_LENGTH-1;# z/ s' V( Q; I/ d$ J
        }, `1 `  H0 i; g: \5 T) C- i8 L
}* s# S( s8 ?5 N- z# {5 W: T
! b8 C/ J7 ^/ L$ h5 }1 ^
void        APU::SoundSetup()6 e- |2 D( T: M" @
{+ {+ a  Z! v% H. Y$ L/ K- Y" ~
        FLOAT        fClock = nes->nescfg->CpuClock;  _" Z  K0 @' S( }- b
        INT        nRate = (INT)Config.sound.nRate;2 \; E; D/ j' [+ J' S
        internal.Setup( fClock, nRate );
- O% s9 l7 m+ m, @% I        vrc6.Setup( fClock, nRate );
3 C( z: u, S8 A0 K% n- g2 |: D- O        vrc7.Setup( fClock, nRate );& b  L3 `- p5 K
        mmc5.Setup( fClock, nRate );% j  _/ z% n: u/ H4 b+ C( b
        fds.Setup ( fClock, nRate );
/ p. p: J1 v# U        n106.Setup( fClock, nRate );4 i# S( J+ ?8 K$ Y
        fme7.Setup( fClock, nRate );! g- G# @6 C5 U0 X0 e# A* ], b
}7 w) z1 J/ r& S. @' F# k
) S2 J) a2 c, P" d: y& Y: n+ ?' E
void        APU::Reset()" {$ N4 }0 Q# n, M( ?; W" ~; r
{
7 e) r1 Q* _, O* ~! p0 {* B& q        ZEROMEMORY( &queue, sizeof(queue) );
( D( T& q- q6 b$ i0 F$ K5 t        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 q  z$ Z0 z/ @! P- r3 E
9 n" L0 e3 B$ H- L- F6 D8 @3 Y        elapsed_time = 0;
8 ?. r0 M: h  g1 b# ?; P1 R& e4 Z- N
" h# E* |" }( F  p5 E, L) Y        FLOAT        fClock = nes->nescfg->CpuClock;" R1 E5 m8 E- h
        INT        nRate = (INT)Config.sound.nRate;
9 e# D0 @8 P) t" e        internal.Reset( fClock, nRate );
0 E0 g+ p7 g& `: O1 z: N6 [6 J  R        vrc6.Reset( fClock, nRate );! j* v. g2 u; X9 l% v
        vrc7.Reset( fClock, nRate );% d& l1 N: F, G7 Q  `
        mmc5.Reset( fClock, nRate );
0 Q  m9 [& p1 N0 A- U        fds.Reset ( fClock, nRate );
, t9 _8 h. u% S1 X0 p4 i        n106.Reset( fClock, nRate );
" d. k# C; S& L: |# j+ {" J        fme7.Reset( fClock, nRate );
7 K6 \8 K1 [; }* `
' O% V2 a" J( c# G: `        SoundSetup();
+ ]# e2 _/ l; ]$ h}- u0 J# z& c$ g7 }) v  x
! a$ i# ]( s1 r* y/ n
void        APU::SelectExSound( BYTE data )
9 I4 K) X% x; v% Z* M{' e9 w3 Y! n7 g  z" n5 a, ?) d
        exsound_select = data;- @6 j3 S5 d% Y3 P, z- Y! N
}
% a, G" U' `$ G0 ^4 \* M2 E
9 m% T' N& \# l8 ]8 ?/ l( V3 D) SBYTE        APU::Read( WORD addr )* u. j  D+ Q9 K- u' D8 W
{  D3 d/ z! E2 S% q! d/ R% ?
        return        internal.SyncRead( addr );0 W' ]$ D! Y! Z6 I( {1 r. w( W; E
}6 Q  ^( [- r) ^8 q: a
* J' s5 X, }* K7 X$ n+ F
void        APU::Write( WORD addr, BYTE data )/ |! b! H+ ]1 E
{
- S, V* G9 W( u7 E5 p6 |& H. L        // $4018偼VirtuaNES屌桳億乕僩7 k* h/ ^5 _: d5 T. d
        if( addr >= 0x4000 && addr <= 0x401F ) {
: o' Z. ~" Y+ [                internal.SyncWrite( addr, data );
+ j0 p) L9 b0 I                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
) M1 M+ d/ |- @- k! i0 W8 [        }; g3 `# M7 `$ }3 f9 {: R6 D2 l
}- Z+ d$ _, I6 a
9 T) r) h) ?+ P& i
BYTE        APU::ExRead( WORD addr )
7 e* n3 W7 b1 i{
1 V4 I, B: \/ j! `# ], T7 wBYTE        data = 0;
8 P8 ]& Y* z3 g4 b2 \/ M- L2 R# `3 R. H& U5 I9 W" |- C- P
        if( exsound_select & 0x10 ) {% K7 _1 Z7 |4 }! \
                if( addr == 0x4800 ) {5 s; g2 x% X" c& C8 t/ z# r
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
$ H7 y! X1 l2 Y% d                }
! K* u$ K5 A: c- n3 Z3 z; M        }
9 C) u" l3 g) k: {9 G; V" T. H        if( exsound_select & 0x04 ) {
7 H# O+ @7 E  g/ j                if( addr >= 0x4040 && addr < 0x4100 ) {% e( C- v3 E% b& u
                        data = fds.SyncRead( addr );; T( i/ \7 ]' H( d! O6 N3 W) {
                }
3 \! W! V' L+ l! _        }
3 C0 f- ^2 ^+ m* l" O        if( exsound_select & 0x08 ) {
$ h- B- V; N0 _                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 B; s" b+ l, e- u$ ~: j5 U                        data = mmc5.SyncRead( addr );5 r6 C: j. l: ^; |( N
                }
# @5 y1 b* d! M" X        }0 [% \* E6 n, S# c2 ?5 b

& S6 H1 @6 I& x4 z4 |0 H" Z' k        return        data;" H9 k4 A5 C' j. u( o9 r
}5 o& T  Y' n0 U- l

8 p0 m. ]% e) n, \0 d4 V7 t4 gvoid        APU::ExWrite( WORD addr, BYTE data )1 O2 _8 S" @1 x% @$ G' q. S
{
1 w. n8 J3 V" ~# [. F$ E$ l        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
1 t; L+ o; ?8 m% H% n: o* r( X% I
        if( exsound_select & 0x04 ) {
* O3 U! Q+ V6 V3 }  X                if( addr >= 0x4040 && addr < 0x4100 ) {$ H) R* l+ e- J3 P7 T
                        fds.SyncWrite( addr, data );; V) `# z6 j+ u* D5 R7 J9 |
                }
# W5 `/ |7 C! E8 p/ E* y        }2 E( Z/ I: a( ~6 I, G
+ p( e" {) x3 K1 U: z* D3 j# p3 U5 F
        if( exsound_select & 0x08 ) {
+ I* R4 p8 M9 A1 L$ C1 D8 A& J                if( addr >= 0x5000 && addr <= 0x5015 ) {! C# o0 a6 x4 s! T
                        mmc5.SyncWrite( addr, data );& R) @2 v; b; L( S" C6 p
                }
9 \9 q+ b, M6 W" H8 x        }
* h$ d3 Z5 }" d+ F3 C- S8 U8 Q}& d( J3 p1 ]. x% b* j
6 {1 M/ Z6 u. S9 w! o/ q5 V  \
void        APU::Sync()
  G, K3 Y  z, n/ J# I9 N3 @% b{+ @: }2 O& b- L
}
0 p. V9 ^: k" K* ]
! L9 W" |+ E/ |8 A9 l3 W) Lvoid        APU::SyncDPCM( INT cycles )
6 q- P; J' L& o0 A) A* [/ v- J) P{
; ~5 T7 x( Y3 W" O" [8 a5 ~- G# e        internal.Sync( cycles );
2 _; e4 y+ x+ h7 i
6 Y; F! h4 D- m! e        if( exsound_select & 0x04 ) {
# P6 @- q% _4 ~0 O                fds.Sync( cycles );
, Q) A  ~' q) N        }' {$ }/ l1 I+ O5 ]/ I
        if( exsound_select & 0x08 ) {
1 G. ~+ b( L# E; ?) o3 j                mmc5.Sync( cycles );. i0 N$ C0 Q8 }3 ~+ k7 V5 k0 [
        }
5 @0 k9 R1 R; j' p- w; H2 J}
+ b5 t2 V$ M. @9 d# s! W. q" F/ o* h
void        APU::WriteProcess( WORD addr, BYTE data )
6 a( ^8 G) ^9 o7 Y{; ~6 p! s3 {3 ~
        // $4018偼VirtuaNES屌桳億乕僩
2 x' m" V( i5 J5 I. D) s1 Y        if( addr >= 0x4000 && addr <= 0x401F ) {" d0 q# u' A& v3 H5 F
                internal.Write( addr, data );( M: k* g" U5 z
        }
3 }* G2 b7 J8 U2 x8 t! t% L}
. D  {6 ~! d2 p" T9 \! N/ A7 E- g* c- ^
void        APU::WriteExProcess( WORD addr, BYTE data )
- _2 B, ]6 r  Z; r{
! i8 S6 y+ n  M5 s" y6 i7 O        if( exsound_select & 0x01 ) {4 s$ ^3 f; C) U, n2 p0 W& ^) s3 m
                vrc6.Write( addr, data );
9 L- n1 p, j& K# b        }$ y1 v8 P! e5 Q( T! }0 f* k# R' Y
        if( exsound_select & 0x02 ) {
" |5 K+ Z/ \+ o                vrc7.Write( addr, data );% `4 J, f! M# j
        }
7 c3 E( Z3 z3 S        if( exsound_select & 0x04 ) {& k8 O8 E5 C/ s& z6 T# \- Q
                fds.Write( addr, data );7 \) ]( _/ U( H
        }: L, S5 p& }; O; S- S  B% X
        if( exsound_select & 0x08 ) {
! j! L& N' V- G' l) A5 r9 }$ u7 O                mmc5.Write( addr, data );
/ c7 @7 M) W. \3 i        }1 p5 H& e, k9 A
        if( exsound_select & 0x10 ) {
. O- I2 C' v7 u7 E6 D- z, ]) ~7 M                if( addr == 0x0000 ) {- M* }% E( k9 Y* R) q
                        BYTE        dummy = n106.Read( addr );
& r; ~2 v6 V+ T2 o                } else {
+ C2 Y: E' C  B1 d/ }7 s4 f( O5 g                        n106.Write( addr, data );
% ^- B/ u3 T# A& q# K1 w0 b8 r2 g                }% F. m8 O4 b/ R2 }; f+ p2 J2 @
        }
5 O( d/ z  a+ }. n        if( exsound_select & 0x20 ) {  }4 ^, P3 i& f: `- ~# I
                fme7.Write( addr, data );
+ X$ ~4 K4 m. c% t+ J        }
  I1 B0 p! T' C2 ]8 Q: U}
+ S9 T/ q! r( q
& g  b' C& U$ W$ d2 Jvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
1 M7 }5 D2 n  j2 Y' [{
* X* B$ U1 ]7 ?) U' ]8 t4 L- {INT        nBits = Config.sound.nBits;
- A# t: @& L' c$ @: W- cDWORD        dwLength = dwSize / (nBits/8);
9 Z" F# N# w6 C, t  nINT        output;2 n: @; ^5 t* r  T
QUEUEDATA q;# I+ S% a' v. ^6 ?8 I
DWORD        writetime;
) n# F" \6 _) \7 F: O  a" v% J
& `# q0 S( ^' p% e6 D$ gLPSHORT        pSoundBuf = m_SoundBuffer;
" M4 u" W1 P8 t+ zINT        nCcount = 0;
+ D* K$ w  r4 N5 ^( t9 n( u/ W
. r$ B5 c7 g) T  F% pINT        nFilterType = Config.sound.nFilterType;" M, C& g- @2 r% s. ~6 j
6 }* e4 H6 f# Z) I6 J
        if( !Config.sound.bEnable ) {
1 Q. Y4 e; e+ d& n* _" `                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; T/ g3 \8 W- H6 ~4 H
                return;
- `( c8 ]( |( F( I) f        }& l; b7 P6 [( `+ N

+ H4 M0 ~! {% s: `5 n, l        // Volume setup
3 h4 P/ s. }/ y: E% C        //  0:Master  B& X, }7 Q$ W; P
        //  1:Rectangle 1. c/ w! h, N3 I7 s
        //  2:Rectangle 2
1 E4 T" R0 I# p; x        //  3:Triangle
0 L9 Q8 c) |% ~        //  4:Noise& L5 @( ^2 z) l3 |8 W8 |/ F
        //  5:DPCM
6 F- p( {8 p  g9 w        //  6:VRC69 N/ J- l+ {" L2 }2 V1 {
        //  7:VRC73 I# a+ Z! J4 [6 H
        //  8:FDS
. X: Z2 P4 r4 B, V( Z! u        //  9:MMC58 W( T6 J2 @$ l$ T) {
        // 10:N1068 e9 m  ?- M3 F' ?1 ^9 V7 y1 K
        // 11:FME7$ k. P( g1 h7 H4 ~& s
        INT        vol[24];+ E8 j% Q/ ~$ [( l
        BOOL*        bMute = m_bMute;* T4 R+ ^; n' l/ @1 }/ T; R; I
        SHORT*        nVolume = Config.sound.nVolume;4 E: U% t; j' I* z) b) F, E6 Y

- O# B: f1 X6 ?- f, \6 |8 m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
9 r* M7 @% T' ?( L8 b' X- a$ ?+ \! Q, h5 l
        // Internal
- {$ l- O6 R( r* D/ d+ H        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, m4 U+ G. ~* j- v        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
) n( i1 P6 @. c5 j4 e6 a        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;- C+ G# |8 ]" b
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 y9 N0 y. C: C        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
% J7 X: c7 ~" n) n
1 K; e- y. U4 K: Q/ ^. [& a        // VRC6
) q( E% [- ?) y3 M0 z  A4 D        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ x5 w9 n% ^" _9 @! Y% A5 W        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
, F2 _) }# r$ u# l* A        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. i( B3 ^1 V0 @9 |

8 e7 v5 U3 l& o3 ?$ N  G8 b! |        // VRC73 A, U! ^  v4 j) d: K2 y8 W
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;0 G, V* N) Y7 z  i4 k

5 j5 N' |# K* v5 R: m, Y- N) }6 J        // FDS
7 u3 N8 U: Z/ s$ B        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;5 @+ v6 l2 t$ x2 H  i' L

: R: }5 e% O4 p7 A1 X$ }0 f% O        // MMC5
2 `$ R) F0 t- q. S) u/ ^        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;" j+ S4 E) K- w: d% k( J
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 Y) S/ S4 }6 o& \
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 Q; ]- ^$ X, C- v# X; C6 x* R

' g( w' J! P1 S  g) v        // N106
0 m( L! w6 }. s% v, s3 q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" A7 j3 Y" s5 G/ A' q; n% J$ _        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* f! G$ g1 x% c        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: W1 Z0 k& a' q3 ~* x7 o+ E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, i& u" D5 I8 Z5 ~; _
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; e3 A- b3 y1 d
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; I! V2 ?! h  j' i
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 s- q8 j5 p) Y1 ^' J        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( o% C- R) M+ w. h$ k* a2 J* o
& Q8 c4 x. E  k* @- e
        // FME7
( g/ q9 d. t. X" o        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" @; l: ^) [, l0 a7 u
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# G- |4 `! p9 `0 R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 B: p" n  |4 S0 l, Q7 ^/ r% x, H* w4 T3 {6 w" K1 m/ k
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;; c  ?' T. P# q/ R- a) O
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
9 z7 v" b' [* V, @
+ a/ l* {  L7 u0 c; H% J        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
8 K; H% i* ^% {0 V) j        if( elapsed_time > nes->cpu->GetTotalCycles() ) {' A/ m4 v! F% {" q# S: m) U
                QueueFlush();
: q: @9 L! F- ?6 i' Q- j        }$ r8 e: A1 f# L" m2 Y1 o! B
$ S& T  J% K$ f3 [0 U5 O
        while( dwLength-- ) {
6 ]$ q% l5 O; n                writetime = (DWORD)elapsed_time;
2 `) @$ L3 j8 [' g5 l5 x1 u6 p# b" ?" m5 X* d) k9 U
                while( GetQueue( writetime, q ) ) {
) w/ f% b+ X+ t                        WriteProcess( q.addr, q.data );* l  r' Z6 G, a" \# D# ]5 x
                }2 L9 m. q6 |' d6 Z! r, i

; b& O5 q* ~) F  X                while( GetExQueue( writetime, q ) ) {. L! B: K& Q& u/ M
                        WriteExProcess( q.addr, q.data );% T1 d0 G' H/ R5 U
                }
7 m8 a8 I5 o% \1 I, w, j* J( r% S1 N" k( b+ d$ T
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ {5 a4 c2 X. a# S9 K                output = 0;
$ L6 f0 a0 X3 O' `6 T5 W2 I2 W$ G                output += internal.Process( 0 )*vol[0];/ v" c% t8 F8 O: F
                output += internal.Process( 1 )*vol[1];2 U0 o8 Z5 R% ~9 n7 u/ a5 f
                output += internal.Process( 2 )*vol[2];
  z: Q9 v) K, [6 _                output += internal.Process( 3 )*vol[3];& t6 t" z; w. L4 v, ^% B* h: H
                output += internal.Process( 4 )*vol[4];
  W, [1 K$ K1 D& o' ^; Q* o& l0 k' Y/ O2 r4 v- d. X" W( M8 @
                if( exsound_select & 0x01 ) {
1 n, j/ @7 Y* s6 g6 E) q( _1 x. F                        output += vrc6.Process( 0 )*vol[5];0 N5 W  A$ S% O# D" t7 z
                        output += vrc6.Process( 1 )*vol[6];& G4 M4 O& @+ B( T. \. `+ d
                        output += vrc6.Process( 2 )*vol[7];+ Z7 `0 m" V) ^9 e/ t1 I+ z, N
                }7 \$ y6 w, V+ V/ Q% H5 i# }" F
                if( exsound_select & 0x02 ) {) f1 W3 R* }3 K8 S3 {/ @- F( h# X0 f
                        output += vrc7.Process( 0 )*vol[8];
) }+ n, T' i2 i6 p8 x- o" {                }
- i$ f( L! L* _6 D' Q" n: T                if( exsound_select & 0x04 ) {* d/ b) B! p% \+ R/ h0 k
                        output += fds.Process( 0 )*vol[9];5 n; A7 S) C' N  X4 u$ x* Z- ?+ d
                }' S* v  l8 A! p# e$ N9 X
                if( exsound_select & 0x08 ) {
+ N& c- r1 m) `                        output += mmc5.Process( 0 )*vol[10];
7 s! ^4 g. r- P                        output += mmc5.Process( 1 )*vol[11];
: k9 O* L. k# v2 M  |- B                        output += mmc5.Process( 2 )*vol[12];
. v" z; m. Y& R  w- \  q                }
5 f% A1 K6 F  Q                if( exsound_select & 0x10 ) {
$ I( \3 h0 W+ o' Z; u! ]4 |: T                        output += n106.Process( 0 )*vol[13];
& T3 b+ g! y* o1 B- `1 f" u                        output += n106.Process( 1 )*vol[14];8 n2 ]2 r! R7 H! d3 X0 V
                        output += n106.Process( 2 )*vol[15];1 t4 I! `. \2 f: o1 E
                        output += n106.Process( 3 )*vol[16];/ l, {6 W- S' Z9 J+ v
                        output += n106.Process( 4 )*vol[17];4 d1 Y% j4 l9 V& [! L: t. q9 x
                        output += n106.Process( 5 )*vol[18];9 }' k8 B9 n* H  p$ P
                        output += n106.Process( 6 )*vol[19];7 }+ _; W3 x+ g0 M( Y, k* n
                        output += n106.Process( 7 )*vol[20];: [% }* p5 b' i
                }9 i5 e5 b2 V0 H. M
                if( exsound_select & 0x20 ) {7 i& A6 r+ p& ^& j9 ]' Y
                        fme7.Process( 3 );        // Envelope & Noise$ O( p3 v( Y% _: b5 Y4 M
                        output += fme7.Process( 0 )*vol[21];
; R! @. d7 }. y                        output += fme7.Process( 1 )*vol[22];
. ]# p. o  b1 K% c# U; g6 |                        output += fme7.Process( 2 )*vol[23];
/ r$ x  ~1 C8 c9 Z0 F) r. M1 _                }
/ Z, ]% p& K* f, \, j& x# @5 q2 M4 M* h) R& s
                output >>= 8;# V' m2 g5 \9 M% w$ l4 E& G

# @3 p' p0 Q" u# F9 J                if( nFilterType == 1 ) {) k5 B# N( {: z$ `1 z1 E5 P* G1 B# _8 c
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)# g$ B' a: \& V  Q1 A! Z! ?
                        output = (lowpass_filter[0]+output)/2;
' v/ }! X$ D0 S, D0 w* q3 E8 W                        lowpass_filter[0] = output;$ }8 w3 }7 J+ `. I5 e; D
                } else if( nFilterType == 2 ) {
/ r6 l: x/ `! J% R8 C% ~2 ^: m                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)( h' R/ W) N5 i
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
, C8 u; }: G7 b0 t. e' B+ @                        lowpass_filter[1] = lowpass_filter[0];+ z0 ~& F( ]" h" ]6 Q0 H& |: L, M
                        lowpass_filter[0] = output;; [( k2 l; h; I2 G$ W. l& `
                } else if( nFilterType == 3 ) {
1 E; O( B' h7 t% U1 [3 |. A                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
" v6 [, @( S% x& e! b  u' Z2 ^! w                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;5 Z5 ^8 Y, ?6 E1 ]' I  \! N
                        lowpass_filter[2] = lowpass_filter[1];! e& e# `: C6 _0 j
                        lowpass_filter[1] = lowpass_filter[0];
  \  V! h2 U: x# f" i                        lowpass_filter[0] = output;
  F0 C9 u" T4 g6 V1 l                } else if( nFilterType == 4 ) {
  a3 \9 J0 p4 z6 B# `- V  z# ]                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
' q( A4 T- E  N+ e& v  d# }                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
1 H( o: j9 j; L+ r+ f- ]% L3 z$ y                        lowpass_filter[1] = lowpass_filter[0];
8 d' O9 P' t0 w                        lowpass_filter[0] = output;- [; B, O. L# J' q. Y7 t
                }6 Y  o: u! Q! z* `
# b3 d: J+ o9 }8 k
#if        0* H3 X3 V% ?& ~+ g6 M% v0 G; a
                // DC惉暘偺僇僢僩
0 ^, F% N( C( Z9 M3 d- w                {
- q; E# g4 u6 ]/ Q7 C& t; q0 @$ V                static double ave = 0.0, max=0.0, min=0.0;* ~5 W$ ?6 r& h; {/ ^, H
                double delta;7 i* {% @' \5 _: e7 o
                delta = (max-min)/32768.0;1 ~* v  l; _/ R- n4 H1 h% t: {2 M
                max -= delta;
: B7 e! k4 \' p& Y                min += delta;
- |5 Y4 Y1 B2 P: N                if( output > max ) max = output;
. S) n4 i7 `* n9 o% V/ g6 A. `                if( output < min ) min = output;1 y& \  P' o( M. i" t$ i
                ave -= ave/1024.0;
2 j' \$ e) r# [: ~  y                ave += (max+min)/2048.0;1 T2 F) `6 A# M: H
                output -= (INT)ave;
* @' ^7 M) b8 |0 X0 q6 ^: q                }
0 x! I) T+ a; R) p3 x- r#endif* W+ m; g+ A7 ]  L. d
#if        1
# O0 Y5 j# M2 L                // DC惉暘偺僇僢僩(HPF TEST)
/ \% K) E: B2 z. F" `/ E1 S1 |                {5 I8 L' ]! J' Z. b5 A
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);9 o( W9 X) ~0 Q& s4 G0 }0 z$ E
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 C3 C" ]3 m( \# r- D) w# d                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 ~+ ]5 |$ h& [$ W* N
                static        double        tmp = 0.0;
2 ]. Z6 E' `; ?: G                double        in, out;0 N2 a& k7 _3 J) [$ r  y
3 a0 r/ ]5 I0 S# t# S' K
                in = (double)output;
7 b+ C+ d% z4 t, ~$ v                out = (in - tmp);
* K& r* I- v. W' ]9 |$ \* [4 E                tmp = tmp + cutoff * out;
: X/ j0 O( [% o1 R- n- I$ L( T, Q
. F  U8 R# S8 b2 A" E1 g                output = (INT)out;9 e  M9 n: b; m# j3 {
                }
8 u/ E& d8 ~  e9 H7 v0 |1 ^) D#endif
3 H# ]4 F1 i9 i  N8 i#if        0
2 `8 |4 o+ E7 y5 ?                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)7 ^! }% b& Z8 r$ W; k* W0 y5 S
                {
, O5 I% R) z$ f4 `' K                INT        diff = abs(output-last_data);
) {% Y- A( @/ R. [                if( diff > 0x4000 ) {0 Q0 t: z2 D- W
                        output /= 4;
, @! Q, L9 b8 e0 j  X' G                } else
( C0 |: t: K( r- M                if( diff > 0x3000 ) {: E9 X2 [$ n+ u
                        output /= 3;
4 u3 d$ E5 y% m; W2 `1 D; |/ K                } else
; K. Q2 ]( S6 V                if( diff > 0x2000 ) {& k; V4 x* I3 t; @3 H! k
                        output /= 2;' v, [0 L. a  I" y7 J% X
                }
; f; G+ [5 f# s                last_data = output;
- Z1 X: U- m' K3 G: u                }
  ^" `! B3 a, K/ X0 o" W7 r#endif
6 {( E" l( d0 _( \/ p                // Limit4 \/ Z! h$ M( T& P8 k! D3 ?
                if( output > 0x7FFF ) {& k% S3 t) ~" z* F* j& F
                        output = 0x7FFF;1 f' _$ Z/ x0 {$ S) ~
                } else if( output < -0x8000 ) {: C9 Z* q, @5 Z. t/ m
                        output = -0x8000;
$ i' I8 T4 P/ {$ ~0 F                }0 v. |# Z* V) q) L7 a; z
- \2 e6 c" m4 M9 ]* t
                if( nBits != 8 ) {
9 _3 B1 E: d* E1 c                        *(SHORT*)lpBuffer = (SHORT)output;
8 H: `5 \( ], D; G9 g$ M, {% U                        lpBuffer += sizeof(SHORT);
; R8 W, p0 C: x# v- t. H                } else {1 {% q/ S, ?6 w7 C& K: L' E8 V8 s0 l
                        *lpBuffer++ = (output>>8)^0x80;
9 P" [7 N8 r1 {                }; e5 V! P/ G7 ~' l$ Y) L$ v2 L

, |& W% ~, ^' ^( j9 k                if( nCcount < 0x0100 )
- ~& I9 g2 o' s; Y) k                        pSoundBuf[nCcount++] = (SHORT)output;
  M; g4 `/ U, U5 ]! k5 N4 b' B" N! \' C$ l9 C9 {6 k; Y  W+ A
//                elapsedtime += cycle_rate;
3 ~- E3 N' x% j4 \- E, |& ^                elapsed_time += cycle_rate;
* y# e: Y/ V9 s! @& ?/ p; F        }
$ X% u( v9 f" |3 r  d% E4 S; ]  U% |
#if        1
4 ^3 H5 t; F: D& s% o. u        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, t- D' K; F% n  ?% `! r
                elapsed_time = nes->cpu->GetTotalCycles();& t9 ~9 L: R2 u& ?* L; l
        }' M; L! x% D: o
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
* i% T* f& v& _; R6 [* x                elapsed_time = nes->cpu->GetTotalCycles();
& Y4 g8 \$ t% ?( E- l9 E        }
$ d1 y/ I4 Y8 z& T* @% D1 p#else/ s$ I' N+ h1 l/ h
        elapsed_time = nes->cpu->GetTotalCycles();
  ~/ t4 _+ m9 z6 R; B# c#endif9 y  J5 F5 `: K$ _$ c4 h$ @7 d
}
$ v$ z. `6 K$ c3 X0 \) D, K
/ _7 G4 m% _& e& D$ l7 a* l7 g6 F// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)  _5 V! T8 b* C. C; R
INT        APU::GetChannelFrequency( INT no )* J+ V6 m* G5 J1 F
{
. G6 Z3 G  |" N        if( !m_bMute[0] )- x- b# q/ Y$ ^$ B: B3 f# ?
                return        0;( z+ F3 r$ m! O2 x

* h! @# @6 B* Q+ R6 ^6 B" i% R. f4 n        // Internal
+ @- i( m: v( @        if( no < 5 ) {
: S9 L8 ]$ r% B" m1 l3 p: }! q                return        m_bMute[no+1]?internal.GetFreq( no ):0;5 V; S7 W; ^6 M8 J
        }
4 [; I3 n9 D4 N# f6 s. [+ [        // VRC6+ N' W3 k+ s8 V4 y
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 Q9 e% ]4 R+ u5 D$ w/ E
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
9 K; P7 y7 I( i, F6 T        }
+ |# K& y% P# V        // FDS
; ~; D+ g  b2 \0 H        if( (exsound_select & 0x04) && no == 0x300 ) {; ]" x$ f6 S& B7 W8 Q8 C1 ^: W
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
& d" m# ^( e( n7 _% e3 n        }2 T) d6 j: x; y" t4 L% D4 q% }0 `
        // MMC5
" K5 e9 K* h/ g/ N        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {$ X, V6 R, _0 j( y" p
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
7 a" A1 z* W; W/ M3 c) U3 F        }2 |  W6 _3 b: O
        // N106
; Z/ V0 O% A5 Y( C5 {, L        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
# s6 S3 W, B' ?- z% x                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;9 r; C7 E6 R; u2 Q/ G: c
        }
1 A& m8 G0 L' ~4 k# |$ a" C        // FME7% z9 B6 m5 R) ?, B  {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
2 T6 H1 k2 t) Z7 x                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;; N/ J+ v2 f& @0 |2 G! y: M7 {1 s
        }9 b0 f* H9 @5 H' Z" Q! w
        // VRC7
  C( I& n: K3 J* O9 I/ `8 h4 F: {        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' H6 i* |/ |5 r$ K; z8 z9 k) Z
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;: S, L/ f) ^% K$ |
        }
2 I% ]' g6 }% Q: v: \, c' t: L4 d        return        0;
3 q0 L1 c2 s, m; X' t}% q  c: g+ \" U' g6 ?$ ]. K' B/ s& J
! a% e+ j7 l! E/ x: |
// State Save/Load: @; r$ J2 Q2 l/ l0 Y) F4 u
void        APU::SaveState( LPBYTE p )
) P* c1 S( t7 F/ p7 _0 S  {5 x{
) O) Z  S) v6 L8 }8 t#ifdef        _DEBUG3 K( T7 m/ e9 d+ |, ^
LPBYTE        pold = p;' n. G2 S0 M% q" k% j& l$ Y! z; [
#endif* N: y3 I4 i; C" X% q6 c

# x& a# L7 S  a; f+ Q& U6 u        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
' A# ]( E2 Q( H3 b. U3 f        QueueFlush();
% l' z4 ]0 M$ e! J5 c9 k+ e6 [6 Q; P
        internal.SaveState( p );- u  u8 U+ A9 B7 S' B  w6 N
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 h% p0 m8 f5 p8 G4 I; [0 [$ Q1 y; H7 {- t
        // VRC6
$ D( Z* c  I" h+ j+ j        if( exsound_select & 0x01 ) {9 @- j6 j2 \8 p+ v6 N4 K6 K3 K
                vrc6.SaveState( p );, i( {9 k2 r# @
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
. R# y! q5 l. |* Z8 @( B        }
5 z; C5 X4 \6 C3 W: l        // VRC7 (not support)
" ~! S9 x  Y! o: {& F        if( exsound_select & 0x02 ) {' p! H+ ~7 J8 I2 e) j* }* V
                vrc7.SaveState( p );' @/ ^: o1 }, T% T
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# T4 c! r6 e5 u2 T3 V  y( A: J
        }
) T; [; d, {% f' @2 `. B6 Z        // FDS# _; S+ i! a( Z1 k
        if( exsound_select & 0x04 ) {
/ c+ \  q/ t& j$ h, q) ?0 H. g7 V                fds.SaveState( p );# v* k  y% l- C# A' U
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 k* R; V' h  s1 ?, Y
        }
  x( ]# e( A0 d) |        // MMC5
/ m# s$ H8 a4 w; s/ [' ]8 N0 D- t        if( exsound_select & 0x08 ) {0 E/ A/ g2 B7 r# k2 j+ W8 l7 d
                mmc5.SaveState( p );
+ ?- j2 v' r3 |2 B4 R                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" D5 |# @0 f$ g! @( u
        }  k5 O0 Z* m- N* }# _" y9 q$ W
        // N106
/ c0 N4 P" s  R' r        if( exsound_select & 0x10 ) {
9 k( o8 R  f6 I4 R                n106.SaveState( p );  |$ u, u+ U4 [0 I+ \$ j
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 ?/ E* O3 {# R. j2 D2 S2 F
        }
( \2 y0 k) p; ^7 ^5 A* c; W7 s        // FME7
' o: G, W# K1 {, C4 V        if( exsound_select & 0x20 ) {+ F; c. P! v; N# l5 ?+ E  z
                fme7.SaveState( p );
9 Q  U7 y0 }0 Q+ w( ]# K                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ e. Y% W+ c* d        }4 S7 R/ E9 F3 e$ ]; K* l/ R; o! _
2 [* B8 \8 M* g# Z
#ifdef        _DEBUG
( B, s4 y) }, ^$ _DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
+ w3 n* P+ L  Y) V9 s: X#endif" P$ ^. b/ c2 p0 ^4 o0 }
}
7 w% [% Z# l1 W) z* e5 s/ |
1 g/ ~2 \* V$ K! t1 e' A  R: ]void        APU::LoadState( LPBYTE p )5 z  R! _4 S$ o; Q; A: v5 w; ~( I
{
4 e# D& ~0 n: D* v" Z& M- s4 R        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% }* _* p0 h, x( C5 L; \/ I        QueueClear();
! Y! G) P' K3 z/ O4 M
* }. r* W4 \. r+ b9 B0 i        internal.LoadState( p );  w# `- }: w  w
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' r3 @+ A1 u+ a: ?6 f$ W8 E# F& K% S* X+ h
        // VRC6
" r. C# z& A3 ^' z' l* ~$ u& `4 x        if( exsound_select & 0x01 ) {2 K2 L/ @( }- }6 I
                vrc6.LoadState( p );
6 f  V: }4 @; N: J, N                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding' A# P, m' M& T0 y! H
        }
7 S6 y9 u! p, w& |) m5 t8 ~        // VRC7 (not support)
) U/ X2 U9 Z' X: q$ u$ A1 e$ }        if( exsound_select & 0x02 ) {
( {) {/ U3 ]# Q# i  ?                vrc7.LoadState( p );
# r8 ]7 e( v. F! I' ^1 f                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding4 m; G; `0 C, u6 v3 o' a8 |& J
        }' _% b+ `. w1 a* L1 o3 M- F
        // FDS
1 W/ Z- p9 `' U$ E        if( exsound_select & 0x04 ) {. u8 z. N3 n/ e
                fds.LoadState( p );
6 L, A/ l4 H' w0 C                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 z8 _0 g3 @+ F( T3 R  q2 u" i
        }: b0 M9 u8 `' J/ j8 q! ~. v
        // MMC5% }4 O( C! ~. \2 f% Q. X
        if( exsound_select & 0x08 ) {8 N1 p( u: K; ?5 j6 n8 L
                mmc5.LoadState( p );
, h; y3 a0 [) j% M4 h5 _8 Y4 z                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding* U7 V/ Z8 ^1 c$ \, g7 Y5 I
        }7 D* z7 K$ x! B; g& Q8 R, C
        // N106% [: c6 k8 Y- C0 _1 w
        if( exsound_select & 0x10 ) {- Q& Z. ~! ~# e! q8 S* C
                n106.LoadState( p );, K5 Q+ \1 L( ~/ m9 }3 a
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding5 s& B7 r, u6 E# Y4 D% k
        }
# Y- I- w# @1 E: ]; I        // FME73 r0 b2 R% A  G8 G1 J, \
        if( exsound_select & 0x20 ) {! [3 W$ r6 J+ U+ k- N
                fme7.LoadState( p );' ~* v9 a, ~3 t( h8 u
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 f2 H& ^( {, M1 s& i
        }
/ f0 ~: p9 q, _/ s4 g) t$ u: y}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; u- p. F3 D4 s, L6 |7 ?
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
( u6 V5 f- _( v! y- \感激不尽~~

( s3 H2 o8 v' L6 M恩 我對模擬器不是很有研究,% y7 [7 W8 ?) V0 ?
雖然要了解源碼內容,可能不是很困難,2 s0 T( m8 V* p- K
不過還是要花時間,個人目前蠻忙碌的。
& \3 K) K) S; V, B' d; d$ u' d, P1 m" s, {# ?- J) {
給你一個朋友的MSN,你可以跟他討論看看,! r5 i7 @  |/ c2 G
他本身是程式設計師,也對FC模擬器很有興趣。* J' Q* v( f- S  j

- K% e7 I" v- h. hMSN我就PM到你的信箱了。
  J- N" i8 q/ ]- V9 Y$ F! n8 p1 p$ ]8 K) Y
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 # X* Q" m" G# p' V' N  o
呵…… 谢过团长大人~~

9 s5 u& i  Y" b" Z6 I3 D& ?( }7 B! y6 s5 [; R9 k9 R, y8 O
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
. d, a- w8 e8 h& ~7 H  X0 V! @7 A团长的朋友都是神,那团长就是神的boss。
: `) X/ _/ I3 e8 _3 p! y4 P6 K
哈 不敢當,我只是個平凡人,0 ?% b2 L2 `  i' w4 z
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! y( B! ~# T) H' s. _  j
ZYH
. N# Z9 B% X5 L% a" H; Y) s7 rQQ:4147343067 V# X6 \( ~( a; k. T2 C
Mail:zyh-01@126.com0 o( }# w7 {/ L5 Y1 C6 p. r' U: f6 K
3 `7 j+ \7 d9 l$ H; j; j
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
. c" J8 t  _* x2 t" A7 n7 A再次对团长大人和悠悠哥的无私帮助表示感谢~~

; Q' Y: r' b( _! v不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-3 06:22 , Processed in 1.068360 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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