EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* ^$ o$ w( U4 x
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! t$ Y) }/ H  v* |0 C$ }这里有相应的模拟器源码,就当送给大侠了~~
. B/ B" O. R% yhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
6 }- N: R& H8 a: J3 B2 A, V能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。5 F5 t+ a; I+ I
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
3 |! e) J/ X0 b5 i; g这里有相应的模拟器源码,就当送给大侠 ...

8 u7 L4 l- @& v& W. I5 l聲音部分(Audoi Process Unit = APU):0 n) q- g8 U( g  }' m" m& Z
.\NES\APU.cpp
! B& _! S! C: r- C.\NES\APU.h1 b) J! x- q2 \1 y8 H

% z0 q$ i# e3 H; w5 [4 S! ^9 L
7 n/ ]3 U3 \/ m0 ]影像處理部份(Picture Processing Unit = PPU):  L% Z) S" f  p. x
.\NES\PPU.cpp+ u# j5 |# e5 o" _4 z- \# f
.\NES\PPU.h& C3 B5 X, k& {/ X
- v5 @$ z% T, O; u7 ^
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:5 U" d, V1 p- l' n
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
4 P5 r! P# t7 [6 I, E//////////////////////////////////////////////////////////////////////////0 H- B) j1 e. N
//                                                                      /// K6 L: z0 d' k5 U& ?1 W2 n+ k
//      NES APU core                                                    //
2 }1 L! f0 }4 t& N% H; X0 P; \7 Y//                                                           Norix      //% E; B" ^+ l/ J/ o
//                                               written     2002/06/27 //
  b3 E: {1 \, M5 v. B//                                               last modify ----/--/-- //' e- r8 N9 ~/ ?  P6 X
//////////////////////////////////////////////////////////////////////////! L8 @, I" T1 G
#include "DebugOut.h"
% W' \' \0 A2 B: J#include "App.h") @6 f1 Z- |+ e7 T3 w' G
#include "Config.h"
! r! f% C& ]9 _$ o" k$ W: G9 s% b8 L% C& y4 z' H
#include "nes.h"
- c8 r, [3 K' w+ N5 K#include "mmu.h"
' @9 \- ~6 L. n  R#include "cpu.h"" u7 c2 _( k+ V0 f- Q, e- @* C
#include "ppu.h"
5 n( Y8 C4 ?6 K7 D#include "rom.h"9 k) G5 `9 j- M6 F8 ^1 L8 x, t
#include "apu.h"
0 a# \2 T* o/ b7 L
( V. z: \! W  `% w: W// Volume adjust3 k% i( o8 L: @  e( Y8 D
// Internal sounds4 E, e/ ]# h7 D% x1 n# N5 z
#define        RECTANGLE_VOL        (0x0F0)4 N. K( O7 ?! D4 C4 v0 N4 ^
#define        TRIANGLE_VOL        (0x130)  B# N+ b: U/ K7 W2 \# m' s7 U
#define        NOISE_VOL        (0x0C0)
  r3 _" B: n: Y, `. W#define        DPCM_VOL        (0x0F0): P, p" v; q  ^2 a$ \8 h$ ]+ T
// Extra sounds5 T3 y0 `; g! f, ], J% ?+ H
#define        VRC6_VOL        (0x0F0)
. ]9 S5 P+ }% @# X3 k' Y#define        VRC7_VOL        (0x130)1 C6 ]+ ^# B. i
#define        FDS_VOL                (0x0F0)' I6 ~' e  B5 t! R% o: C% q
#define        MMC5_VOL        (0x0F0)
' p/ u: c; E, X/ P#define        N106_VOL        (0x088)2 o# Z1 l, R% f
#define        FME7_VOL        (0x130)
( p, ^, z' v5 p( E  d! |2 p; z+ x' I  e- ]: q8 T
APU::APU( NES* parent )" T: S9 D3 h+ L# \5 j
{
9 `  ^( S4 @7 a4 v" f( N7 L8 \% B        exsound_select = 0;0 k3 ]  G+ B5 ~& D! ~) i5 f; i

. \% V4 U4 f; u) c        nes = parent;
) S% d$ Q' k) i( `        internal.SetParent( parent );
8 A& [0 c# I' ?$ N' r2 T. S+ c5 k0 C, I- `+ A. a5 S4 H3 ^0 [; I
        last_data = last_diff = 0;# p$ ~3 M6 E5 W8 L2 d
  l( C/ g$ j0 @% S8 m
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );/ G$ i: Q! L% T- S+ w1 G  O& T
2 X' {. g! e( y) g' {) U. T* h
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
) K( C( U0 ]$ J' L& m7 {) }* ~6 B/ Q        ZEROMEMORY( &queue, sizeof(queue) );
5 l4 A: N/ A6 X# n5 x2 w        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' i  ~+ l  F5 ^5 k* w' p: N9 y6 G
; x( [: M8 j; a        for( INT i = 0; i < 16; i++ ) {
5 [- v' E. g. A6 m                m_bMute = TRUE;
. L5 i/ t& V! @) A; U0 I        }: r' D" ~( Z# L: F
}
  Q" K4 T* r( h
, u; R4 ?' h# \3 l; R( v) A" AAPU::~APU()  ]3 R5 ^8 }" A7 X1 z
{
" p$ J  t' Y% w' g}8 j( A# l4 b2 [. H4 X: b/ D$ t+ D
% G) C+ p" I) P* P* {
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
& X  N2 N6 v* f0 f1 z" g/ C{" j0 T! c: h  J/ ]: ^0 w' R; J
        queue.data[queue.wrptr].time = writetime;
2 q- H) [. |+ z5 C        queue.data[queue.wrptr].addr = addr;
9 ?- _4 E" ?& @) Z        queue.data[queue.wrptr].data = data;
6 c* a0 O0 W$ q8 P4 W; f. ^8 X        queue.wrptr++;
* \- ^, C# I8 j8 j        queue.wrptr&=QUEUE_LENGTH-1;
$ H% C: A& r4 g) i9 l        if( queue.wrptr == queue.rdptr ) {( D/ \' ^- [4 H* D
                DEBUGOUT( "queue overflow.\n" );- \9 ]0 {7 L, f
        }
- W) a' G! R0 a# u  o9 X}, s6 t) \  w7 ^. K% l- u
) b, Q3 k! s+ I3 I8 }' ^
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )+ W0 v: F. X' r4 D7 H
{0 S6 Y7 [) r7 F$ W
        if( queue.wrptr == queue.rdptr ) {
9 F% i2 o/ ~7 R3 }                return        FALSE;5 T4 \8 I  v8 p2 q- S& M
        }2 {1 ^. w0 i8 H5 R4 y0 ~: c
        if( queue.data[queue.rdptr].time <= writetime ) {  @) Y) {1 g- b
                ret = queue.data[queue.rdptr];
- g8 I2 t+ J- e% g) Y                queue.rdptr++;* h' z4 E# u/ ~- H( ~
                queue.rdptr&=QUEUE_LENGTH-1;% y1 O7 y1 ?% M0 a1 ~5 v/ F
                return        TRUE;
4 f5 ^; x$ A2 f0 g/ O6 g% v        }4 l2 W! s, A  \  o8 O3 T$ g) `
        return        FALSE;
4 T: {. K: }' I) J" D8 Z+ ^}0 J9 c; @' E( B! _" {8 E, s3 Q9 B
9 t  A2 ~* Y. G3 k2 @% [  C
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
$ @# v2 q& |5 b6 \% m$ o{
% Q% b  W% v3 X; B+ N" s        exqueue.data[exqueue.wrptr].time = writetime;4 B' W7 o, Q4 p, Q' O
        exqueue.data[exqueue.wrptr].addr = addr;; j  d8 Y$ \, Q6 u. }
        exqueue.data[exqueue.wrptr].data = data;
- m6 S9 J( Q3 M5 Y; ^) `        exqueue.wrptr++;  t! }& m! @8 ~$ p! `
        exqueue.wrptr&=QUEUE_LENGTH-1;
2 Z! S. n4 L0 Q        if( exqueue.wrptr == exqueue.rdptr ) {: Y+ c- j) g& N$ m" D7 }7 }
                DEBUGOUT( "exqueue overflow.\n" );
: x% ?" |# u6 ?        }0 b0 q$ f7 {4 @# L
}+ w$ y7 c9 q1 [

3 r, }( L: P0 u$ q' s' r4 bBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
2 m- b. h7 q4 M8 X) q9 h3 T6 s& W{
7 Q. g& l  p9 m& H- j        if( exqueue.wrptr == exqueue.rdptr ) {0 O% I8 P+ }; L0 R9 H# l7 V/ P+ T7 Z
                return        FALSE;- m1 a, X& E# R5 R2 ~* y3 g! f. I
        }
0 O$ |. j: `# F1 l9 k" z) Q        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
9 i0 B9 f3 h: ]# F; m! P                ret = exqueue.data[exqueue.rdptr];
1 ^( Q: ]6 x; K$ h8 h2 W# F# D                exqueue.rdptr++;
3 \6 D* Y+ q/ _9 z' y0 S                exqueue.rdptr&=QUEUE_LENGTH-1;9 V' A/ L. P6 ^* g$ z
                return        TRUE;
& ?4 U0 ?" H# v        }
+ M8 E* F( o: K; f* X$ O; l        return        FALSE;
9 C+ Y! _8 L8 V4 q8 z$ P# {}. J9 f/ `& A) V3 E6 v# d

0 J( \9 d. b* v5 f1 Ovoid        APU::QueueClear()
9 C  y# l) f* F9 f$ l8 }: P2 q{8 P/ r$ l1 k: |  M- J# F# T
        ZEROMEMORY( &queue, sizeof(queue) );
, l8 q+ e* r( C3 c2 F        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 l) p. e# }6 y}
2 b* L! K) |0 ^) m
) T3 l. d' e1 m9 w( y4 G: \void        APU::QueueFlush()
3 J6 f1 H, ~% R" G% n8 S{" S; U5 n+ q. ~8 S
        while( queue.wrptr != queue.rdptr ) {
5 L: {) C4 u8 X4 F                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, b/ I  u& k+ N2 ?
                queue.rdptr++;" @3 v3 S+ ^8 o4 U' o
                queue.rdptr&=QUEUE_LENGTH-1;
3 Q7 N& O; P) X0 W' H        }2 e9 }9 b- O1 |7 C! T0 h$ D
( r2 h! }4 O; X1 P8 r7 U8 A' z" R3 }
        while( exqueue.wrptr != exqueue.rdptr ) {
  j. M( C/ A. G- Z) H' c# t6 s- A                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 b& n; g/ ]6 w, c2 Y
                exqueue.rdptr++;
3 B: B$ `+ ?) t0 t; X                exqueue.rdptr&=QUEUE_LENGTH-1;" z6 y" v8 _7 i" c$ s- ~
        }# g8 z6 p' {; F9 Q/ B
}
8 b9 l4 X+ j9 N7 L7 h+ ]: f7 |. x8 h$ Y. V
void        APU::SoundSetup()3 G, K( a7 r4 d+ j* h- g5 i
{
, }( T' \7 C* t* L: A        FLOAT        fClock = nes->nescfg->CpuClock;& z4 ]. H, D( t6 {  W
        INT        nRate = (INT)Config.sound.nRate;8 a) b& ?+ o8 e& C
        internal.Setup( fClock, nRate );
4 P; S2 X  U9 Z( I, J$ t) A7 W        vrc6.Setup( fClock, nRate );5 n. `! H  K) }- ^$ [6 T5 J8 }3 R/ }1 z; Y
        vrc7.Setup( fClock, nRate );
( G) t: S4 L% l/ x' H* i9 g        mmc5.Setup( fClock, nRate );
9 ~4 ?. l8 t6 v# e4 q. [        fds.Setup ( fClock, nRate );
) H1 {7 u: a9 r+ ]        n106.Setup( fClock, nRate );
- |8 j* W& ~8 s        fme7.Setup( fClock, nRate );. ], w9 L; P) F8 c8 c1 W" O2 ]
}
* ?" u! ~' h% M2 a/ l6 E+ w+ Y4 f7 [
6 j+ b9 D# @/ I+ E) b7 B$ Rvoid        APU::Reset()" N5 i# P" `% {  a! ~0 C0 z( M( V* b
{0 Q, h6 b- e, }5 s8 o
        ZEROMEMORY( &queue, sizeof(queue) );, W! f; _/ n3 ^. j+ q5 U5 S; \
        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 h7 t# v. l; U
& s5 c2 E) P" f/ n" J& Q
        elapsed_time = 0;$ m8 x1 l, x: r. g9 M- Z. x( ?

  q  q2 c3 y( z2 o- y        FLOAT        fClock = nes->nescfg->CpuClock;% l! w+ L& T8 z, ~8 t9 j  I* W9 c8 Q
        INT        nRate = (INT)Config.sound.nRate;7 y! b6 E9 K% h% F
        internal.Reset( fClock, nRate );
0 Z5 t, V. P  e* v. O9 o. u1 c* l% q        vrc6.Reset( fClock, nRate );" V+ b  t* K! M" g5 Z
        vrc7.Reset( fClock, nRate );
( z- q% P& s8 c7 k: y8 v        mmc5.Reset( fClock, nRate );
) n1 H( {0 ]8 H9 n+ [3 v5 n        fds.Reset ( fClock, nRate );
3 y( E" L' o! p5 M4 a  b% L1 M        n106.Reset( fClock, nRate );
( Z4 t9 `& E$ M4 a1 a, y        fme7.Reset( fClock, nRate );
7 S; k0 w+ W$ s" [# k  N
. ?! @5 p2 v1 U& s        SoundSetup();
9 R7 w; x- Q0 B, c; N: E/ w/ a}
9 k% p' `0 K7 {+ J8 O9 ~0 z
2 @: s: b! T) u* Y/ |void        APU::SelectExSound( BYTE data ): B* x" Q' Z! C0 b, l
{$ q6 r$ _- |% O
        exsound_select = data;( E  I. ~6 Z5 r, `) Z' X( e# G8 I
}
7 O/ b4 O% n% i
$ d) g& a" [$ W; c, SBYTE        APU::Read( WORD addr )
; K7 D, I1 r4 z( x' S4 R{
6 Y  Y9 P! p9 x" j4 ]! }) X' X, H' G        return        internal.SyncRead( addr );0 N, o3 Q- q- w! h4 U. r
}
# Q; ^+ M$ i4 o' p0 X' O  f6 F' Q& A- ?
void        APU::Write( WORD addr, BYTE data )
. S9 N/ y9 u9 A# S% G2 I{
) n8 e4 d; W$ [2 _" o4 N( {        // $4018偼VirtuaNES屌桳億乕僩
$ C6 l  c  \" i        if( addr >= 0x4000 && addr <= 0x401F ) {, z: Y( C* ]$ `, @
                internal.SyncWrite( addr, data );
; n- b# s$ s1 P! I                SetQueue( nes->cpu->GetTotalCycles(), addr, data );$ I5 d4 M2 S0 v8 E6 K$ f# B2 I
        }
* `, ?- Q( z- y9 r& d}
, u2 [3 v  q, Z( x  u9 u. O: h6 {! @  |, l8 o% X+ R5 @
BYTE        APU::ExRead( WORD addr )3 P/ A* p& `' b
{7 r/ w! K! R: G$ A9 H1 K8 A9 L
BYTE        data = 0;8 r, b& E, T: U/ c1 T( q

' Y1 a% _" t* r9 W        if( exsound_select & 0x10 ) {
0 k! H% c8 F2 }) U2 L                if( addr == 0x4800 ) {) c& c. V; m* s) `$ u0 \
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: G8 n7 }$ o7 N0 N7 b
                }
$ D. @5 Z1 w! e/ _        }* n0 w1 w1 w8 J- o7 f, Z6 Z/ B7 X* U% _
        if( exsound_select & 0x04 ) {
; U. C& b8 c. T) {: O  y                if( addr >= 0x4040 && addr < 0x4100 ) {/ M) I, b/ r; O' q0 j
                        data = fds.SyncRead( addr );
  x  C3 u" I3 P9 T                }8 Q6 W0 F) z% D# a5 I- z( H
        }
2 s; ?/ O( R, |) `1 {        if( exsound_select & 0x08 ) {# O' G; D; a0 @0 W9 [
                if( addr >= 0x5000 && addr <= 0x5015 ) {
, W4 ^) V( z4 v                        data = mmc5.SyncRead( addr );
5 N3 H# P/ T# }6 m0 Z                }
1 Z& m: w: G* \+ ]) N        }4 N6 S4 j: Y  U, r( e8 l

: U! U; h3 `2 N5 E# ?9 A        return        data;
9 |. e: G% m: g& G# _/ l}) ?' e3 M" y: @- b* a
( r# L: Y/ X1 s
void        APU::ExWrite( WORD addr, BYTE data )
+ m: B# L6 z" b, T{
( c. ~' E% r0 p6 W& ]( m! ]  j4 U) X        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );5 k# o# F) }& @; H# a/ T  Z: F

4 }6 t' j: y! w* p- \' k        if( exsound_select & 0x04 ) {
) U7 a, P4 [8 v1 V  x                if( addr >= 0x4040 && addr < 0x4100 ) {
5 q" S8 |! }0 h) N& }                        fds.SyncWrite( addr, data );
3 A/ n; C; e. j                }" _" Y8 U7 b7 B4 j: B
        }
+ p; d$ F2 w. K9 C$ t3 u& c1 a1 C& t/ N% O' l- q; U
        if( exsound_select & 0x08 ) {- n8 D# e% I+ i
                if( addr >= 0x5000 && addr <= 0x5015 ) {* a+ V3 e8 l  A! `
                        mmc5.SyncWrite( addr, data );1 X6 R# x) J" |4 C4 z3 Q
                }8 N7 \) R+ j! i& o) h8 {) m' o
        }1 R& r2 X: f& P9 y9 t! W4 \
}1 Q! L) c4 p- w
: |# i! Y* p2 F6 U% d. _
void        APU::Sync()
+ ~6 R( j8 Z- R& C, D- L0 g{
# W7 e8 }2 x: U$ L& H3 Z}6 X) L% w  T; _7 e
7 G' D% _* B- I" D
void        APU::SyncDPCM( INT cycles )
# [/ b5 |5 A: t' y- P{
6 S0 U) i- n; L. \" d, g8 c        internal.Sync( cycles );' Y. ^) |  [6 i3 }* W9 v! \9 ]

1 L5 O5 O1 C/ R+ ]8 l7 Y! s        if( exsound_select & 0x04 ) {
. [# u! C, O# ~6 P+ q7 A                fds.Sync( cycles );% j/ E( z+ z5 B1 H, A$ @6 b( W0 I4 j
        }+ N3 ^, l9 D( v7 l) x! W6 q
        if( exsound_select & 0x08 ) {7 {1 [4 d: N: z( l' C5 @) n
                mmc5.Sync( cycles );
6 j% U& ~/ v  [$ d        }
/ B5 k2 l! x6 [}
' d9 v. c& F" R* I) q5 T
- {& X: C4 }! O, o& e# `% Yvoid        APU::WriteProcess( WORD addr, BYTE data )) c: a, w% ^& t$ P9 u  Y0 P
{( _4 K  }1 a) F( B0 a3 b
        // $4018偼VirtuaNES屌桳億乕僩/ q; V6 d  l" M  V; M$ n
        if( addr >= 0x4000 && addr <= 0x401F ) {
- x) U9 @: Z5 G                internal.Write( addr, data );* P2 w9 K% t$ h* t* j+ t9 W
        }; Z* ]# W/ c/ |( u# Y$ m
}
" D  b/ I) K6 V% s4 e
+ Z, T6 S- z, j3 K; svoid        APU::WriteExProcess( WORD addr, BYTE data )5 P- V- v) K" n4 q0 ~3 m1 X
{% I% u4 |; F3 X; u  j  {
        if( exsound_select & 0x01 ) {$ `! c- G7 w$ a/ e% k7 T
                vrc6.Write( addr, data );! n' {% t$ V& |
        }9 D0 n9 X6 D/ _) ^7 N
        if( exsound_select & 0x02 ) {& T( ?* i  O5 M. {  U) p8 W
                vrc7.Write( addr, data );7 U# q) [/ E* E: d! \6 I# B
        }
9 E! z: q' ]; `        if( exsound_select & 0x04 ) {* c' r" `+ U! f3 C8 U+ W2 H* T
                fds.Write( addr, data );; c0 O1 r+ e: d, m3 Z1 I
        }3 q. B0 {  @9 Y% }4 w
        if( exsound_select & 0x08 ) {, z2 m. C. k; x6 z
                mmc5.Write( addr, data );
: x9 l' E. `% u: ^5 ^5 P        }
2 `, @+ t! Q% j: r- }5 y5 n/ q- ~        if( exsound_select & 0x10 ) {
' E& @( E) w0 N* V: Z( J: |; _. k3 ]                if( addr == 0x0000 ) {
- C# t* d. P  K4 s- G& Q                        BYTE        dummy = n106.Read( addr );
! S% J: p6 T  ~! _! p# ^1 s" J9 F                } else {. \1 F  q! J: G
                        n106.Write( addr, data );
5 X9 ~! k& S0 n+ v5 g$ k" D6 U                }
, G( T) D( E9 i4 e: R; c* J- Z+ G        }
. ~/ L! i" y+ M) @/ p2 N8 [        if( exsound_select & 0x20 ) {
4 h0 S8 m5 e, b- t* v3 [' k: [) s( }1 J                fme7.Write( addr, data );& f$ @2 v1 X! T4 \0 p
        }
1 C& H3 C. S8 k& D}+ L6 a& I' d5 z$ O4 i

7 r  U" k  W/ ^2 a  [" Gvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )6 e2 U6 v! s. t' @! P4 F: N& a( |
{+ B' g, L5 {* u/ X2 F  t/ R/ B
INT        nBits = Config.sound.nBits;; ]9 \3 g, ~4 A. N7 X/ ?9 W! u, E
DWORD        dwLength = dwSize / (nBits/8);2 J3 ^( J3 i9 A7 O: `
INT        output;' e! l% D- Y3 e7 N
QUEUEDATA q;
' D  A3 [" x- |/ Q7 a  M& JDWORD        writetime;) _, N3 G5 G- h8 E

* v( H( |& T: V' T4 \+ s" ~* sLPSHORT        pSoundBuf = m_SoundBuffer;
! z9 O! {; ^7 H: t$ cINT        nCcount = 0;4 r: `0 s+ ]: e6 u
4 R( |" }* s* @$ E+ E1 \
INT        nFilterType = Config.sound.nFilterType;
5 Q3 e4 s: g5 `3 |" T
, P& e6 G$ @/ M6 C& d        if( !Config.sound.bEnable ) {/ a* l4 s7 z; G1 P* S3 O0 f
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
# y9 j5 Z8 a( Y& l! u  h1 c                return;
, ~5 a7 Y3 z" g0 s( N$ j        }
. q# Z- C7 J+ P3 Z4 R
# ]7 V( m. {9 f  Y3 O# j        // Volume setup7 c+ N# i# l& J9 ]% ]9 m4 v
        //  0:Master
0 k% T. |2 i: p) S; o+ i# p        //  1:Rectangle 1* v2 d0 D% u; Z2 }
        //  2:Rectangle 22 s6 X6 _$ R8 y
        //  3:Triangle9 i( \/ X$ L3 x: y3 s' e
        //  4:Noise7 O* n" R' v/ E
        //  5:DPCM
7 \0 l' a, ^9 P) R        //  6:VRC6$ [7 A" [* ~* U" W# ^
        //  7:VRC72 f, [2 e! R0 y3 P6 s2 T# n
        //  8:FDS( F1 c3 y4 E1 X* k/ n+ E
        //  9:MMC5. y# y1 q1 l7 c2 ?! q
        // 10:N1062 o# K4 M0 W% B6 {# O
        // 11:FME7
* }7 }7 v( A1 l: U. Y1 n' D) h& ^        INT        vol[24];% c# Q6 C1 B  p9 v+ a% r
        BOOL*        bMute = m_bMute;
2 N8 \0 G' E4 d/ |8 Q& c        SHORT*        nVolume = Config.sound.nVolume;
, ]' F  [1 s9 }, ^: }3 c% r" |3 E3 f  b5 `; A" z% h: h" C* \( o
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" m# F( d+ o# {% L, ]" H9 h  f, E

$ X  h8 w' j9 E        // Internal
3 X# G2 }8 ]7 I# X- s% m1 k        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;1 T4 g" R" U& j  U; L* a' W6 M+ s7 h
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
, C$ q& `7 S, W8 s5 Q        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
+ F" w$ u4 `5 l/ i9 w        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
9 W  y* F+ |1 {& c" @$ B3 p/ J        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;, k! X/ [% f, S. q/ g# h
0 f% v6 V2 c6 n: m1 s1 b& E: ?
        // VRC6
: A% P! N% C6 n- K        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. ?) v- k# J! J4 `, W0 W8 R
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( q- p( {" D# s; t2 c        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
" w+ P; T6 Q' ], Y4 u' \+ `9 A8 S: `
* D5 ]/ i+ r5 `8 f        // VRC7
7 p) r/ K" v9 ^: a5 [        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
9 X! i3 X  U) F' S- p5 a3 N2 Q# e) }
        // FDS
7 p" o4 M3 _; ^/ f, a$ \        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# q9 L' Y! L2 p6 I  E+ P. V; M6 p+ {: h, n: Q& r0 c
        // MMC5
* q7 b) P  E6 i. ^2 u, l        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 ]; \4 i& X# W, ?$ `1 k7 A# X6 \
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 Q$ T. g" _& _" ^+ G( F# S- t
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. L; F- ?9 H9 W7 C/ S- S* D. \& W8 ]1 V1 D$ r) ~
        // N106
. x9 G6 w8 M0 g" ?& R9 }- T) Y- u        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  o' Y) j9 O7 A. _, I        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, m) u8 _0 F0 B6 j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( V3 Z0 v7 d; Q) L" _+ T        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( u$ @9 b' X! a& e; R
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 h4 g, n% e- [& C3 i        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( E8 H; ^+ T% `        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 T0 ?: J$ S% }6 }        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 t& R9 L; w8 Q1 x7 h$ C% r% a

- K* f6 U& B2 W! c# f        // FME7
' B/ z5 J. z* t8 M+ C        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;1 ]) l% {7 y2 I
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;8 x7 T1 M$ s% d/ k
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
1 F  n& r+ _  C. M1 c
2 B( D0 e# q% C3 w( `/ F//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;1 n+ K8 @  J- `) Z( p) ]7 G
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
6 d* B# z; w% S5 P7 C. k
2 L: D  [" w/ m& B        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
3 U& v' t) p4 K; @/ v3 P        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
! _+ q2 N) l1 h' K- N3 x                QueueFlush();
+ E/ |& S* c1 M+ a$ [! P/ F' J        }! E; B" ?: h6 O7 E+ y2 F. ~0 I  Y

4 p8 E8 ?. J  s4 H        while( dwLength-- ) {: c2 S8 E. \: D8 z3 Y% o( o, V
                writetime = (DWORD)elapsed_time;6 k  g! P" x, Z8 o

) I' @: J" H5 _                while( GetQueue( writetime, q ) ) {9 \0 E" z+ y) ]9 O. J+ l) v
                        WriteProcess( q.addr, q.data );& W8 x, G9 V" Q
                }
) c4 c; N: w. l, C8 S. S% [; J1 }* _4 I
                while( GetExQueue( writetime, q ) ) {( D" ^% [) G- ?' F$ P
                        WriteExProcess( q.addr, q.data );
2 ~$ d" A$ A" P. G- y% }                }4 E' o, C4 _; h6 c

  K! s3 X4 {7 L4 l) k' S$ n                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME76 W4 O7 E, L3 l) h" Z# i
                output = 0;2 l$ I: E, K  f) \
                output += internal.Process( 0 )*vol[0];
7 l, j2 J* ]4 C1 Q3 g" Z9 f. I. n                output += internal.Process( 1 )*vol[1];
" V+ _8 Y6 h' Y# }$ [. l. G3 s' Y                output += internal.Process( 2 )*vol[2];
5 S: @3 K! Z, {9 ]* A                output += internal.Process( 3 )*vol[3];$ i2 U% i8 ?+ c( \+ f( L
                output += internal.Process( 4 )*vol[4];: q, y/ ~5 ~1 `& G2 d) G

( C# s. V" u1 K: W+ W9 {+ G- a                if( exsound_select & 0x01 ) {
7 v* d5 ~6 x8 o9 ~: [  m. o! J4 f! Z9 F                        output += vrc6.Process( 0 )*vol[5];, ~4 @3 K, i/ {
                        output += vrc6.Process( 1 )*vol[6];6 f2 U* y; }% w, h* ?) ?
                        output += vrc6.Process( 2 )*vol[7];: ?+ D- T: d3 j% E# X% s
                }3 ]2 ]& R) Z% u: h  @* N& Y# w2 f. ]
                if( exsound_select & 0x02 ) {
7 ]# g  w, b) x% i2 C                        output += vrc7.Process( 0 )*vol[8];
0 _% t% |; s* l' @! J6 Q( }                }
/ x' b- t4 V/ s3 v6 k, j6 a' Q                if( exsound_select & 0x04 ) {$ o; K  q3 `: }& M9 @/ h& @* W
                        output += fds.Process( 0 )*vol[9];2 l, _+ W6 _* n  w% w4 c' P5 }9 u
                }
1 y+ i4 D  U5 G# v* X/ \. j+ u                if( exsound_select & 0x08 ) {6 L" ^" F0 q# \  B5 S/ H( f: @
                        output += mmc5.Process( 0 )*vol[10];
5 i+ I8 {8 y6 p8 B                        output += mmc5.Process( 1 )*vol[11];7 h8 t* W% M$ ~6 X9 W
                        output += mmc5.Process( 2 )*vol[12];
# x' v0 W$ g6 p6 f0 ~3 W                }) E. [# z+ `, @; }, U$ `$ A( w3 C
                if( exsound_select & 0x10 ) {7 w% V  h& o( G6 d1 D: \
                        output += n106.Process( 0 )*vol[13];8 d. ^4 K" t0 z
                        output += n106.Process( 1 )*vol[14];, ^6 z* r& C9 n8 ]+ V  y
                        output += n106.Process( 2 )*vol[15];
; U0 S/ N. U- u                        output += n106.Process( 3 )*vol[16];3 p6 E6 U' ?# Q! j
                        output += n106.Process( 4 )*vol[17];
% s6 O) ]& U, f" H' X' E& |; \0 }                        output += n106.Process( 5 )*vol[18];
: m( T" z+ ]# H7 g6 d& ^                        output += n106.Process( 6 )*vol[19];( }* c8 X% _5 b2 _
                        output += n106.Process( 7 )*vol[20];, l8 M; F+ e' k" u9 u+ B: V: [9 |6 w9 D
                }
. E- `! B+ T2 ]* p1 U& X3 u7 k5 R$ e9 v                if( exsound_select & 0x20 ) {
. C5 P( F8 d; b0 |4 c( ^3 b                        fme7.Process( 3 );        // Envelope & Noise  q0 k$ z9 v5 ~8 A7 j
                        output += fme7.Process( 0 )*vol[21];# B3 F7 i  G4 h, q- ?4 ~
                        output += fme7.Process( 1 )*vol[22];; _0 r! ?; j7 d, v
                        output += fme7.Process( 2 )*vol[23];/ s( ~% X! ]( q; ~. u" A# X5 ]; C
                }0 f6 R$ M9 P2 X5 e

- v! A6 E3 I1 y7 t: H7 Q* Z                output >>= 8;0 _& }9 c: N. P( r% O* a
8 p' y3 U+ v& \( w; s- B
                if( nFilterType == 1 ) {
% M0 `6 Q3 G/ q  J: Q: f% R/ n: V                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple); Z/ B4 R5 z: ^) ^2 H
                        output = (lowpass_filter[0]+output)/2;
. K! R  Y+ ]; _' x- y- E0 A- K                        lowpass_filter[0] = output;
( q  f  z: H2 C                } else if( nFilterType == 2 ) {
) g  W/ M4 k5 J5 c( j                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)/ H6 |/ |3 @/ I) s7 j
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ C( t' J. M( U2 a" M7 o# s5 T" @                        lowpass_filter[1] = lowpass_filter[0];
4 x% _5 j: U0 S$ [0 p  A/ d% d                        lowpass_filter[0] = output;
% S7 z7 W6 }) v- Y/ q2 J! Q- Y8 [                } else if( nFilterType == 3 ) {
# L8 F9 @1 f7 I6 s                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* i7 P3 l3 B+ {7 P& d* \                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# j* e5 `' m8 e* B, O  Y1 q                        lowpass_filter[2] = lowpass_filter[1];
" E) B& @) f( R' w- N# U                        lowpass_filter[1] = lowpass_filter[0];0 K7 F$ ]2 y( E) U8 C/ t3 J) Q
                        lowpass_filter[0] = output;  M% A1 X! ]  c# Z
                } else if( nFilterType == 4 ) {
- m/ d0 P( o2 \( k                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
# ]( L) r/ {2 @, G                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;* r* Z7 |- V7 g* a/ a9 p- C
                        lowpass_filter[1] = lowpass_filter[0];8 K+ Y; D7 q+ q3 d& H
                        lowpass_filter[0] = output;
4 d8 y1 J7 ~1 e6 R                }
: Q3 C& A1 ^% A
% [- b+ J# @* p2 @8 Z$ i. i#if        0
1 F! d3 w1 D4 m& d( c' `) v                // DC惉暘偺僇僢僩
( ]- G9 x. J* J                {4 F* h: w- T/ Q4 N$ x+ N# r& ^
                static double ave = 0.0, max=0.0, min=0.0;
* v3 K* h' o& ?7 t5 u                double delta;( b8 i& D  P( ^7 M, ~
                delta = (max-min)/32768.0;; o5 [5 Z* k2 {  y) V$ \1 f. Z3 G
                max -= delta;) D; D) ]' B9 J% o4 S
                min += delta;
* W0 K5 ]1 U. k4 x/ ^. y                if( output > max ) max = output;) @  }* {+ A! s. n
                if( output < min ) min = output;& u. Q: Y9 D' X# U1 U  I
                ave -= ave/1024.0;' ]9 y% Q& ^# y7 z( l
                ave += (max+min)/2048.0;9 j. _4 I4 q0 K6 ?: j
                output -= (INT)ave;3 M& R4 |# x7 i+ \9 D! A9 f
                }
" L1 M5 k" U8 w#endif
0 l* x3 Q, t9 Q2 b( j( }, B#if        1# I- @0 o6 y  H9 K( ~9 D! y& }8 v
                // DC惉暘偺僇僢僩(HPF TEST)9 x# o; D+ a- a
                {; h* w; T5 s; Y) u# ?6 v  ~& O
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
8 y+ K. J5 R! \* q- Z: m                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 ~6 W1 u9 |2 C0 j                double        cutoff = cutofftemp/(double)Config.sound.nRate;% V5 |6 W$ \7 ?/ `3 X
                static        double        tmp = 0.0;$ z) z$ q5 }  {; o& D. v
                double        in, out;! K( k7 z! P7 |8 \  R/ r

7 h* {7 X; Q' i8 D                in = (double)output;
+ _1 L5 ], O( w7 A+ l4 V/ I% O                out = (in - tmp);( D; }& f- ^6 [1 w1 ~" t$ p/ b; K
                tmp = tmp + cutoff * out;
" \) u6 ]6 d( ^: D" z  D/ q; h5 t) D8 `. b; M8 k' |
                output = (INT)out;
, L+ ?$ x& p4 L5 m% b* m                }
! X% P/ k: F- y9 G$ w/ t0 D+ r8 Z4 R#endif) t( F; W2 S3 u5 D3 _1 v4 E
#if        0
; t5 W: O5 `8 E1 |. s                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 t; ]2 I' N4 i4 a8 }  K                {1 H& z( b8 E0 l! ^
                INT        diff = abs(output-last_data);/ l+ s& X! a; \4 `. H
                if( diff > 0x4000 ) {
" r9 J- E/ P! V  K                        output /= 4;
9 ~6 O/ M1 [6 `7 F5 z                } else 4 Y, p8 |1 w3 ^0 `, r
                if( diff > 0x3000 ) {
1 r0 j) P  O. T) T" E% _, i                        output /= 3;
5 ^" B( Y. U$ X$ v( f                } else
8 H5 ]. I& f5 L. D                if( diff > 0x2000 ) {; `( ]. e. B; f+ I1 ^* H
                        output /= 2;* s# m) t# W# b
                }
& D. s+ y' I( i8 j$ y% c                last_data = output;
- P! C. j/ Y/ k% p7 V2 l5 ~5 j                }+ ]3 P0 t6 u' M$ v. d& A+ s
#endif2 q  c# }7 X# {& D
                // Limit
5 X  V: y9 r2 L2 x; J! f& M                if( output > 0x7FFF ) {
0 {! b0 ~  B" T                        output = 0x7FFF;$ u. s1 D+ ]: S4 u, Y; C# A
                } else if( output < -0x8000 ) {& s( E! H' P# w* x! g
                        output = -0x8000;( i: n& h/ l: d. K% C0 Q9 s
                }
2 u. J  s# o' F4 q% c; Z5 j9 {8 z% e# k0 M- a, J
                if( nBits != 8 ) {
# V5 w: e( }1 d8 y' J  M  e9 I                        *(SHORT*)lpBuffer = (SHORT)output;
- K! |7 Y" f( f* ]                        lpBuffer += sizeof(SHORT);; U! C3 Z/ A6 T
                } else {+ P% |% t8 C4 ], |6 J4 d
                        *lpBuffer++ = (output>>8)^0x80;+ F- W9 e. A9 t3 ^) o: O+ h- N- {" e
                }
; I5 L# D* D2 {' Y, T! G8 o& O2 Y6 e' v; K5 E8 Q
                if( nCcount < 0x0100 )/ k8 d5 ?: y/ v# o8 \$ D4 m  U
                        pSoundBuf[nCcount++] = (SHORT)output;, }. g) D/ g: C+ |: d  w( ~
1 H' w  q6 \) z
//                elapsedtime += cycle_rate;6 Q4 e- K7 X3 y* N+ y- J% W; j, t
                elapsed_time += cycle_rate;
" i- K3 i4 a. @6 {        }) p7 B  H5 l# L( s& H2 I

1 S  W) ^3 C2 ]% V" B4 ~) m( {#if        1/ y# @/ m* ~. [% _4 h7 }' I8 Z
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
+ I2 j% o: b' h9 @" l9 g- x; C7 J                elapsed_time = nes->cpu->GetTotalCycles();1 r8 S) W6 ]3 C1 b; V: ~
        }
  j6 {7 n* g/ \# Q5 F* S. `3 o6 U        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
+ E( w: I' X# F% B" K. I: n; q- ]                elapsed_time = nes->cpu->GetTotalCycles();
! ]) @6 Q' L8 x) f3 p* F# |        }5 q: U: x5 L$ r. [  W' f
#else0 o3 s1 K- j) ~5 S. y
        elapsed_time = nes->cpu->GetTotalCycles();
$ |; V9 M3 b: C$ m, l#endif, W+ w' x4 Y5 P& u. I/ c. N: X
}
1 }; Q; L* Y6 r* ?" B9 l' |/ v) M5 S" O$ t; B2 P/ r6 ]9 F
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
- B8 {& b; m& @INT        APU::GetChannelFrequency( INT no )
$ m- h" H1 V( m/ z9 S: Q{. O3 q# S7 r+ u" B9 @
        if( !m_bMute[0] )
: h+ Z* P0 P- q% N8 |                return        0;6 u8 ~+ @0 i- n1 X6 S

$ \0 S5 I, k0 m6 S2 c, B, A        // Internal
2 v: Y9 q4 B' M4 s" F- R/ ?        if( no < 5 ) {  H9 A6 Y1 `' a; ]+ Q' }5 ]' d
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
  j9 X& W' R. j) E$ y4 |        }
/ N; S- S0 s1 f3 U6 ?' ]- r        // VRC6
! z5 i, s6 z0 }  R! p6 a, u        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
9 b) S2 l3 b# ]( f  E3 }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;/ U4 U9 d$ [) Q9 k
        }/ E% l' g$ g* U
        // FDS
9 B. T$ p. O6 i. V$ ^, u9 G% j  y        if( (exsound_select & 0x04) && no == 0x300 ) {* T. w; L' z$ ]3 K) b
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
3 C) D7 E3 @- Z* Z5 {# |        }. ~  W; _6 i) ]1 a; a" N  [
        // MMC5" F, y# s7 r$ W5 q
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
, @  W5 ~, }6 f                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
' R: u5 t3 V* |; }        }
* \5 q, U- _* N+ d        // N106
! ^; \+ ^1 D' ~# N7 c' I( \        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
6 x- l: t. z1 ]! o! O                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 l. o+ r1 c4 M* K! s- G
        }$ t' [- l$ _) T/ \/ ?% j* |
        // FME7, e4 Z# ?; Y  {% W
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {8 b1 I3 U+ X! `. A4 y
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;; D+ p8 j) @0 P7 N
        }( O  m0 v$ V; K# e% I+ g& r  d
        // VRC7
* w% J( A6 |. [; M" }: B        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {0 w& U% `9 |, Q
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;" V1 n8 o5 r8 W( E; M5 j
        }0 h( a1 N6 |7 }0 P9 h* @6 @
        return        0;& ^. Q" B( l& D2 H+ P2 L
}
( j9 @4 S) d8 F) ]( p$ T! }- d+ R- k
// State Save/Load
7 k! g" \2 K- n# f1 a4 uvoid        APU::SaveState( LPBYTE p )
- E- m1 }3 Z7 ^: n! p% y5 y{" c* k7 D# }# g0 [
#ifdef        _DEBUG; n* M; h- u7 w" z/ ~
LPBYTE        pold = p;) B6 O" ~6 G& |' C' B1 Y! z# Z/ ?
#endif& j: e! b1 `% N9 B; T: i  ]
$ {8 @! Q" e9 a% v- X  _
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞- W3 D- w8 [/ c; |  G
        QueueFlush();
" \5 x) ~+ e. ^2 a1 E; o& l
3 a+ G/ L( c; y- d. \" a7 w; z        internal.SaveState( p );4 Y4 x9 F! Q' R+ Q" x2 L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# l- H( `1 v7 ~( D0 h# l7 d% d9 q2 U6 v3 g
        // VRC6) q* M8 ?3 I( n4 B6 `  I' R" Q( |
        if( exsound_select & 0x01 ) {3 R% }# f# z/ J
                vrc6.SaveState( p );
2 T0 N8 S* A% G# i5 y: q7 W                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 x" V1 E- s+ V: A* K+ Q, F        }7 i' @7 \+ ~( b0 r3 d
        // VRC7 (not support)
, x; I# u7 C& u7 t' z/ P4 \2 `        if( exsound_select & 0x02 ) {3 e; n  ?' i: s( L# a9 H
                vrc7.SaveState( p );' \! p; z5 {$ `: Q( }$ r" J
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& v" P9 X; H, A5 u        }6 @* {' m2 F1 B; U7 |- z
        // FDS, B. W( H/ h, ?( i( s$ X. F
        if( exsound_select & 0x04 ) {0 l9 L# h+ }1 N' p' N: U
                fds.SaveState( p );
% r, ?, V' e! B+ N  m# F                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% R( @5 j+ Y' a3 g& @' @0 Z* t        }+ p' \7 W4 W* c1 A( p+ H$ ~
        // MMC5
  i7 H. D9 H9 H1 I' y. S+ f        if( exsound_select & 0x08 ) {
# A3 H$ ^, m  p& F                mmc5.SaveState( p );
8 P4 R4 N' o3 D: y- C4 F                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
! d& u6 H" ]8 i0 e2 m' b        }7 x, s+ x5 M* L: b; t$ J$ w
        // N106; L5 j9 O5 d' r' T+ r8 i& Z5 `
        if( exsound_select & 0x10 ) {
' v7 A; V- E3 _( q# V                n106.SaveState( p );% u1 R8 ]5 _  |! v. i
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding. ?( N. S8 g7 Z2 U6 T# o* b! f9 B
        }% B% o1 }9 S5 _' ?$ E8 X' ]; F
        // FME7: m, p/ D& b/ G
        if( exsound_select & 0x20 ) {: ?5 c$ z7 `; K$ @' e. j
                fme7.SaveState( p );
/ m& b2 _0 ^" X# k' X                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding5 r; S2 N: I# ]0 X7 r5 L
        }5 J% z. o9 \( v; F( k* G

! b8 i+ p8 q& j/ D) S/ j( B#ifdef        _DEBUG
3 o& }5 [+ H: B' P5 P, kDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
9 i% H( i6 D4 n+ g3 R. j* b#endif8 R" S9 r: U5 V6 @- _8 i
}
- @* [( d* H3 e( z
% J# @' o/ U; |6 ?$ q% Kvoid        APU::LoadState( LPBYTE p )3 t2 b( A- u, e3 F9 ?2 I
{
7 ]+ q) @# m7 X& X) {( k3 _' X        // 帪娫幉傪摨婜偝偣傞堊偵徚偡8 M  h! \4 u# i) L8 b
        QueueClear();5 m  @& w9 C7 M! [" [. s6 Q( C
( b3 o% f5 K2 t' i
        internal.LoadState( p );
% T8 I9 V" H2 Z' ^) h; l0 U4 p5 I        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' \0 w5 U! U4 M$ t4 H9 Y/ v/ u
1 ~  i1 y2 |7 v7 ?4 M( p* Z        // VRC6$ {  s4 c2 H% k" X+ A3 j  S
        if( exsound_select & 0x01 ) {
+ @; v) ?( s4 R) z3 P+ _7 f3 ^. O+ y! L                vrc6.LoadState( p );8 a6 E) f! b; E. Y
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 V; e0 k# h! D, V! J7 _
        }
4 c# i$ a$ l1 E8 C7 L        // VRC7 (not support)
/ A1 b8 g, u! f5 p        if( exsound_select & 0x02 ) {9 U7 T3 I5 {3 R2 ]6 K! B3 L
                vrc7.LoadState( p );* z$ Q* n7 t$ g+ O; E
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( B0 B( G) ], l$ q$ V) e% T6 Y" \  s
        }( O( K2 H- X) Q* S! D! D
        // FDS
7 m" n- i4 A# V- q, y        if( exsound_select & 0x04 ) {+ e$ o, {- Q7 V' t& ]5 P
                fds.LoadState( p );
. D0 L& Q5 P, A3 `0 ^+ b                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, h3 b/ @9 L, O. l: Z        }
( s5 ?6 e7 M; Q* \$ x        // MMC57 w* x+ s8 r6 D+ K# i2 G8 V& h4 l
        if( exsound_select & 0x08 ) {
- w* E& h. V: C: q- b                mmc5.LoadState( p );
( |* e* _0 T  ?& F0 K# O+ g                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ H) @" f2 `7 S( F        }/ A3 e, X/ X- ^  V3 W& @* ^
        // N106
, M! w$ r4 Z! }  M% R        if( exsound_select & 0x10 ) {) g3 D) B0 P& q) z. L
                n106.LoadState( p );
" H! e1 \, J7 S                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  V! s( D2 F% H9 _" s4 Y
        }9 n9 b% g0 a# v6 e7 [6 K
        // FME7
( R# a2 T1 E6 X4 [7 f4 w6 t) v" A" L        if( exsound_select & 0x20 ) {% k$ C: h3 z0 a
                fme7.LoadState( p );* n3 g# s2 q0 G  U6 t
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
( M2 m1 j4 V7 f        }( v( [3 A# D% o+ |
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
! L6 n8 {3 l! f2 e3 s- B7 s. y可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。2 }& b+ x6 N/ Y. z7 l
感激不尽~~

2 Z" i. N9 p, U7 I9 d恩 我對模擬器不是很有研究,
+ n; v* w* K0 |0 T$ e9 k8 C雖然要了解源碼內容,可能不是很困難,$ [. \7 e- I3 T+ @. u
不過還是要花時間,個人目前蠻忙碌的。9 k" i; A; Y2 e# w+ G! c+ U% z

/ E  f0 w/ t0 s0 r! l- S給你一個朋友的MSN,你可以跟他討論看看,
* x4 p( x* @% B' o% H5 P0 l他本身是程式設計師,也對FC模擬器很有興趣。# o) i% }" n& U1 D' y
. t& _6 }: Z% n' v  ^, n- K
MSN我就PM到你的信箱了。3 V* K$ Q( Q. ~; F/ q; N( e

7 \% L. L# e4 s6 \希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 8 X  S" E4 R* Q- P
呵…… 谢过团长大人~~
2 i; u% p9 ~9 o% ~
* L, k6 n% o1 u- G# m7 g# C  G6 b
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
7 q% Q! r1 A9 |! z6 [- l团长的朋友都是神,那团长就是神的boss。
+ k) I. P$ f- Z% {3 ~9 R2 |* }5 B- l( ^' \
哈 不敢當,我只是個平凡人,7 Q: m5 N2 q1 W& U
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
8 e( X: P% V) tZYH+ h; z: t4 C8 f
QQ:414734306" K8 S3 j9 g$ a* I; S6 k  |8 ~8 k
Mail:zyh-01@126.com/ {; D8 ~0 O; ?7 L8 d, R$ ]- T

) T: |4 o+ U$ j他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 7 Z6 h; c) _$ w# @, o3 R# J; c
再次对团长大人和悠悠哥的无私帮助表示感谢~~

0 S! c6 @: S4 l不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-18 17:16 , Processed in 1.144531 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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