EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! V7 q8 J/ [6 V9 l, e( M+ C楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~' [8 ?% K$ j5 l" O
这里有相应的模拟器源码,就当送给大侠了~~
# @9 Y5 b3 G  j+ I! bhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 M) i5 ~' q5 t5 N. g
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
! ~  R- V# y3 a6 L, V楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~" q( D* E& R' p' a1 c
这里有相应的模拟器源码,就当送给大侠 ...

5 q* @+ U2 ^8 R聲音部分(Audoi Process Unit = APU):6 X6 v% Y2 j5 r# V& M
.\NES\APU.cpp
, t+ v, ^* \$ R3 g0 T+ O.\NES\APU.h
7 D; a2 n# J& b1 H
# p% ~' @6 q- g9 K% O7 q+ ]( ~$ ?
: c+ y4 U. t, q/ f5 d  c影像處理部份(Picture Processing Unit = PPU):
* [! `4 y( ^. X.\NES\PPU.cpp
& z6 e2 Z" v4 |6 Y.\NES\PPU.h6 q6 {5 T( s% l1 j' f
6 }; y3 b4 Q6 N4 X. V+ d( m" K
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:  U. F, P0 o* D2 U& m9 {
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
$ A6 E' [# K6 w% O, ^+ h$ e- A//////////////////////////////////////////////////////////////////////////  z1 O7 \, H0 [; b* W
//                                                                      //
1 J3 D' N( p" }3 f" F, q//      NES APU core                                                    //+ R* o7 N5 [6 ~% D( e
//                                                           Norix      //- F$ d: U4 P& r" p6 e9 I2 g& d
//                                               written     2002/06/27 //
$ }  l$ M, E& s6 s//                                               last modify ----/--/-- //* ]0 M9 }% b) H3 R5 ~$ T
//////////////////////////////////////////////////////////////////////////
! i& O) C% v( T+ B3 o, k" R#include "DebugOut.h"+ o) B( A" Y- y$ [
#include "App.h"9 l8 C6 o+ `! ~3 ^$ Z
#include "Config.h"
+ i; N& K4 _/ {$ |9 _2 _1 O2 `5 y1 _" U% v0 r) q3 o+ Z, m
#include "nes.h"& @, O, _# w1 O( z( S0 A
#include "mmu.h"4 ]- c3 n% _) N+ z
#include "cpu.h"- X3 x. V2 D2 Z1 ]
#include "ppu.h"; y1 F- O' ?/ M* _3 U, s4 c
#include "rom.h"; m0 E( X  W( p7 _" s% n
#include "apu.h"; O# k& ?$ i) i7 S# j+ j
+ o9 d2 }% p# t2 E; U; G
// Volume adjust# I* s) C0 r: c  ?, _, t5 q
// Internal sounds( X( W# [( h# }
#define        RECTANGLE_VOL        (0x0F0), \% C+ f4 n- x$ Q7 I  y
#define        TRIANGLE_VOL        (0x130)' |+ y5 ]! |& N7 {9 a5 b* b
#define        NOISE_VOL        (0x0C0)
) d3 U  W5 g$ `#define        DPCM_VOL        (0x0F0)
) Y3 h( j' O/ `& ~8 R// Extra sounds% k/ d3 c4 V% m* [+ G9 h
#define        VRC6_VOL        (0x0F0)5 y4 o2 \: g; ~5 S: I7 b+ T, D5 n) e% `, _
#define        VRC7_VOL        (0x130)7 ]) i4 f+ ?: ?8 ^4 H2 i7 {
#define        FDS_VOL                (0x0F0)
. @( P) t6 ~+ V. y#define        MMC5_VOL        (0x0F0)9 {! q4 i  s6 i- g% M" F
#define        N106_VOL        (0x088)
0 d2 {! |( ~2 S3 g5 ~5 @6 ?+ A( e- E#define        FME7_VOL        (0x130)$ v, F' \7 ^: d0 V5 V

* l# i7 u; b8 I  R1 VAPU::APU( NES* parent )
8 D% a9 B6 U3 I* G. [$ i1 f. W8 h/ F{
" U5 S4 `7 g. O        exsound_select = 0;& z4 R7 o8 z; L( u& b

0 Q$ q5 ^) [% D+ y( W1 f        nes = parent;. f. ^& Z; F5 }! `0 @, y
        internal.SetParent( parent );
/ y, q: M* t/ `+ U% ~( F& c
! \+ w, `" r! D- t7 i$ U        last_data = last_diff = 0;
! ^  `4 |2 b4 N& _* D
# r* w9 p, K2 |; I! m        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );& q# p6 n3 `/ F2 j3 V( g8 _

( f2 z1 M" Q4 l        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );$ d0 D6 H' ?  O0 `. ]0 g
        ZEROMEMORY( &queue, sizeof(queue) );
9 B, `  ?. P& A# {" {        ZEROMEMORY( &exqueue, sizeof(exqueue) );: b7 p9 U9 C! q  V) S, c
6 Y* V( [0 x4 K; b9 |
        for( INT i = 0; i < 16; i++ ) {
( l6 H8 K/ v- \1 G3 Z2 Y7 q: F                m_bMute = TRUE;
7 ^4 i, o( a1 v* D/ j        }7 S3 C" m1 M- V* I2 A2 Z: \
}& R% @/ e0 y: M
' }; B$ c, ?+ K7 u
APU::~APU()
1 R2 Q! y# i6 |: U& h4 @{
2 d6 a# y6 ~# Y2 K7 J! q}
$ |! E1 g# ^) j$ U/ [: l" m! [! v. ^! t
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
- D* U/ h$ ]1 U& X! M4 C& p{- A4 ~+ d% N9 C- @. [$ }3 A
        queue.data[queue.wrptr].time = writetime;
, j& z9 g; S  @3 E        queue.data[queue.wrptr].addr = addr;9 g2 [% Q* M# ^1 ]# X
        queue.data[queue.wrptr].data = data;: c# R" y- s9 Q- L, P3 X0 d/ |
        queue.wrptr++;+ H4 d: ]: O, s: N
        queue.wrptr&=QUEUE_LENGTH-1;, n3 Q5 ^# ?/ ?: E( E  z5 I
        if( queue.wrptr == queue.rdptr ) {
+ T4 q) I5 p6 F8 z, ~; Q                DEBUGOUT( "queue overflow.\n" );
- `. u& F. T( J2 G        }; T) s0 A3 G" o% Z5 E& F% h7 L# M
}
0 |7 q7 s# ]4 e' j) w6 o# x& l$ R7 I; T# k: L
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* q! E, j8 l0 o
{) r. r/ f/ ?4 r9 w) {, ?
        if( queue.wrptr == queue.rdptr ) {5 O% n* Z, K/ T# d9 @0 `. X0 F5 B
                return        FALSE;/ d! K; y4 r$ M/ R8 ]3 X1 [
        }
! G+ r( ?* W7 a& ?        if( queue.data[queue.rdptr].time <= writetime ) {
' R) y3 i% {7 `) g1 D! k3 s, c7 O                ret = queue.data[queue.rdptr];
0 P3 r. w3 b% W3 s$ q7 F                queue.rdptr++;
% }& d" O( m8 s3 L                queue.rdptr&=QUEUE_LENGTH-1;5 P: R7 @; k5 h1 S0 X& F
                return        TRUE;# }7 j$ r( y0 m7 Q6 r' T
        }
* J- n( g( e# ^( ]4 t' w) }        return        FALSE;
) `. q! b6 n: s2 y}
  |) h  {4 w/ Z6 T3 t
8 e& ~- b9 n0 r' [void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
8 H8 P) z9 o( i( X  N6 X3 X{! H7 D( H1 c, ^+ A+ R- v
        exqueue.data[exqueue.wrptr].time = writetime;
5 Y# _( D& e: R/ e+ b        exqueue.data[exqueue.wrptr].addr = addr;
4 Z  o) k0 o; `; D0 W# l        exqueue.data[exqueue.wrptr].data = data;
4 I0 v  Q7 Z0 b; y        exqueue.wrptr++;
9 M4 A; z8 N# l6 P        exqueue.wrptr&=QUEUE_LENGTH-1;
4 F1 @. ?: J5 h8 {% Z& \        if( exqueue.wrptr == exqueue.rdptr ) {, F4 O% ?6 d* T8 @
                DEBUGOUT( "exqueue overflow.\n" );
, T  a- z9 |* F& S' j: K9 T        }. W6 @# b/ D7 L% w* R8 |7 ~" v
}
& T# {0 \, O7 {' A, r& b! _; H( v5 e- p/ v4 h3 A
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. W( Y) I$ U% }# J$ T7 m{3 v  L- l& M9 g+ o
        if( exqueue.wrptr == exqueue.rdptr ) {
- J( Z" M0 W9 b$ E                return        FALSE;
( D% ~% ~7 L; s) l        }
1 s7 O; H3 g7 i        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
$ g1 w3 q* }0 P                ret = exqueue.data[exqueue.rdptr];% \3 a4 ]% y: Y% F& h4 T7 E* f
                exqueue.rdptr++;
9 d) o8 f& N$ Y# ^% U7 |: N                exqueue.rdptr&=QUEUE_LENGTH-1;
" M% w6 R& L! B' B" [                return        TRUE;
" a% L" x6 E+ Y# u6 ?( {        }2 a' o3 s' a. ^1 U# b. w- K
        return        FALSE;
) u% C9 @2 g" t6 R0 p0 M}
; e* m7 ~; I) }
: v) D* U4 C9 t" M4 N; B' Jvoid        APU::QueueClear()& v( ?8 R& N, x
{
9 e& g* u  e0 h- I        ZEROMEMORY( &queue, sizeof(queue) );
2 ^* ^( b0 d4 T- e5 m4 b6 X. v        ZEROMEMORY( &exqueue, sizeof(exqueue) );& o) U, j" D  C8 o, t5 `( y2 t; s- e
}, i5 X# a# J" d' m
0 j# e/ b, G- e9 I& w% l- z; F3 C
void        APU::QueueFlush()3 j9 V* \/ }) a* A4 F, g/ A3 ^. P
{
  u9 M6 h! A0 b$ X        while( queue.wrptr != queue.rdptr ) {
9 H/ n( K1 J) c& m                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
5 `  ?) w- [4 D0 ?                queue.rdptr++;( t8 m4 ~4 w0 B: a+ z
                queue.rdptr&=QUEUE_LENGTH-1;
% L9 [8 |4 x& l% e6 C# _: b        }) Y  H! k5 B* M2 y5 m. @

6 A( a1 b& G* z( W/ z        while( exqueue.wrptr != exqueue.rdptr ) {+ P7 J+ p/ q8 a) ]4 P! q: n+ y* m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 {' x% d# C& e; u- |                exqueue.rdptr++;& H+ i, V7 ]4 b8 p  W! y
                exqueue.rdptr&=QUEUE_LENGTH-1;
6 D/ {, C/ v- a9 A1 I1 L        }5 D6 s3 d+ p7 {; S" D1 h, ]
}
0 F+ l: Z5 N+ n% w
2 L1 e" s" t, `4 d1 x& N2 cvoid        APU::SoundSetup()
  a9 \: T0 O1 w1 h2 ?0 H  C{
! S6 q/ V5 H2 w/ w1 U' c        FLOAT        fClock = nes->nescfg->CpuClock;. j! p  t& O+ f7 P& k2 \
        INT        nRate = (INT)Config.sound.nRate;
! J) R0 o- X  r        internal.Setup( fClock, nRate );
$ k6 V: i3 g" p0 R8 i        vrc6.Setup( fClock, nRate );% l8 |. l- c" o  e8 v* ]
        vrc7.Setup( fClock, nRate );
) O) z( Q7 p7 c/ _% V7 J        mmc5.Setup( fClock, nRate );
$ R) _1 p+ b$ J% B        fds.Setup ( fClock, nRate );
5 J8 @* X: k* ?        n106.Setup( fClock, nRate );
; E9 _9 g- R0 Q! m; h        fme7.Setup( fClock, nRate );
9 g6 R7 a, I& M$ D; A}  D1 k# z2 t" S# v' T/ b! `

  ]4 I- N7 a& F5 c! Zvoid        APU::Reset()7 i. n3 K1 U: Z5 S3 {( G
{+ v4 e$ Z- @9 I
        ZEROMEMORY( &queue, sizeof(queue) );
. w: M; W2 x: U) B4 q        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 j  f* P5 P. j! W  ?7 _

- ]( H; A& k% g' t# {        elapsed_time = 0;: B0 Y# g  `% a* ~3 ], z) M/ a

  a+ B! B& O( j5 e9 q* y! `2 k5 p        FLOAT        fClock = nes->nescfg->CpuClock;
' ]& A( u) Z5 Y9 i- x        INT        nRate = (INT)Config.sound.nRate;: P/ H7 g8 H2 {9 I
        internal.Reset( fClock, nRate );
* t5 o. [/ N. C6 K( ?1 _: L        vrc6.Reset( fClock, nRate );, |+ h2 P- G* \7 Z7 ^" O* C  M
        vrc7.Reset( fClock, nRate );5 n4 n4 a" R; _8 T0 M5 S
        mmc5.Reset( fClock, nRate );  n3 y2 L7 a8 N) `; ~! a
        fds.Reset ( fClock, nRate );
8 C! P6 F4 a! E$ b1 j  A; Z        n106.Reset( fClock, nRate );
- @$ z/ g; y2 K2 f# X8 I0 \        fme7.Reset( fClock, nRate );
1 W4 n0 P8 G! i8 |1 T% R& y% r5 R  U1 d6 c
        SoundSetup();% c8 F. V; ~  |
}
! Z9 e8 k: y9 n! x/ x( u( T/ f3 K, M) ]8 L8 w
void        APU::SelectExSound( BYTE data )
* Q2 h  o" |, A: D{
2 v1 P: Z  s7 k! t) j: ~4 O* w        exsound_select = data;; u5 x6 x) Y4 y4 Y1 `1 X, |
}
7 ^: [9 a: b2 K, D) _
4 ]( A% U) Z  cBYTE        APU::Read( WORD addr )
5 ~! X% ~; h8 b1 A* i{/ S0 m* d/ A+ y" U
        return        internal.SyncRead( addr );' ?4 K' g; Z4 w" f- j, [( \
}
- W! A1 A+ p. e/ Z. @0 s4 L. k3 H- [( G: F  a8 i2 S( a* g( m
void        APU::Write( WORD addr, BYTE data )
% F0 V1 R& b4 i( D+ Z$ c0 r{9 w8 Z3 L4 n% I8 t% G
        // $4018偼VirtuaNES屌桳億乕僩) H7 D% i+ R$ @; E( _- n
        if( addr >= 0x4000 && addr <= 0x401F ) {' L$ [+ N  }4 V! H6 [* d& O; v
                internal.SyncWrite( addr, data );
1 i3 v4 ^8 y# ^6 X; w: b; t* v                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% x4 J! s7 `/ z+ e" `4 [8 ?
        }; A' v/ f  `7 O9 A: h+ h
}# V( s4 ?9 K$ U" N$ Z

( I) ]6 W( U  D; X! |) U* x( dBYTE        APU::ExRead( WORD addr )6 l% X: c3 W6 b3 _
{9 e: E7 j+ T) S4 E" K5 p0 l2 A
BYTE        data = 0;
# i" K& t/ ~' N! T: O$ p/ Q" b
) k: ]) m4 t6 }% {4 B# [        if( exsound_select & 0x10 ) {6 U% h3 ]! F3 Q! i4 X
                if( addr == 0x4800 ) {
& V0 v0 w) {9 ^3 R3 f                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );! }; i+ R8 E5 n! o) J3 r# a9 |
                }
  k8 N- F5 K3 S" y. _+ D7 J  y        }
0 S8 B* |5 |! E6 A# [. {( W6 t9 Y9 n        if( exsound_select & 0x04 ) {. Q' r8 ?7 g% I
                if( addr >= 0x4040 && addr < 0x4100 ) {2 k7 S7 N) P* A4 T  h, o
                        data = fds.SyncRead( addr );4 j. V' }% I( |$ [- K' g
                }
, h/ k! z/ F# m! J# F  D        }) Y) Z6 b8 N4 R3 H8 U
        if( exsound_select & 0x08 ) {
7 ?( ?% Y. l* i2 K                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ i6 k8 {7 e9 w/ y                        data = mmc5.SyncRead( addr );; C8 U5 w/ Z2 w) R) K
                }2 j: I- Y1 i% y/ }9 u5 D" ?/ @
        }- Y& B7 [, d% i  y$ M
) P# d. H- Y* n; L' U
        return        data;
) H: X( @% L) O7 ]* Y, }3 {}
" P% D  B8 t5 X9 B/ z' B4 l1 h4 E3 N: D5 g& e" s
void        APU::ExWrite( WORD addr, BYTE data )! o  j) @2 _5 K5 G; E- X
{. B4 r/ |7 b# N7 b
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );- n; J4 n% ~- _

2 S8 u, Z4 {5 x# ^% U        if( exsound_select & 0x04 ) {. j8 r3 R' p: t1 n
                if( addr >= 0x4040 && addr < 0x4100 ) {
& ?7 U9 N7 a9 U/ Q- m9 F2 J                        fds.SyncWrite( addr, data );
: ]+ w$ {! ^8 u( H3 q) k                }
0 j; @* E* n; y( V$ ~        }, e) ~! y+ _0 b9 D# w7 [
: w, q( k! Z; G; z+ c) G
        if( exsound_select & 0x08 ) {* I' g- ~8 W# f' T: I! a4 Y
                if( addr >= 0x5000 && addr <= 0x5015 ) {" Z, u  t0 d6 e# {4 ~
                        mmc5.SyncWrite( addr, data );* q' [5 a/ U" ~9 x. c- N
                }$ o  `  Q2 E1 ^# k- r4 y- w
        }
- l5 g' x7 a$ J1 f: E5 S}
' ~- S0 [8 n2 Y
. e# A- B" P+ j; A' e% Wvoid        APU::Sync()! f( X& y' P0 w) f; `0 x  G
{5 A( J! O8 I' M4 F0 v
}
2 J2 e8 B# m" E( o
/ p/ d4 ]5 ]7 y1 Tvoid        APU::SyncDPCM( INT cycles ). G# o. \2 O2 O+ }. p. B
{* ^& p& M. V2 w! x1 o% d
        internal.Sync( cycles );8 J6 {: h' q( K

" k& D$ `3 N3 ?" E: _        if( exsound_select & 0x04 ) {
/ v3 y2 s) y; b                fds.Sync( cycles );% S) H2 y1 O6 W' g" \/ T
        }& d$ E4 {- q# V! U6 Z2 _
        if( exsound_select & 0x08 ) {  y* {' B& B3 B  e) E
                mmc5.Sync( cycles );
6 c$ E/ ~- b* U2 p3 E( ?        }
4 X  z3 |. A: P! M}
! x2 p5 j3 B- _$ ^' i3 M0 \8 M  r/ Q% R( |- @0 y; B: V& C5 S+ x
void        APU::WriteProcess( WORD addr, BYTE data )6 }, l* M8 F" M: O- J" V
{
8 V$ u, S6 t/ Y        // $4018偼VirtuaNES屌桳億乕僩) A: Z/ Y6 s  h
        if( addr >= 0x4000 && addr <= 0x401F ) {
/ D( ?' p- N1 C; h: T                internal.Write( addr, data );
2 C; m. b! A3 t! a        }( q4 Q2 U; h( q2 l8 n" t  ^
}+ d" \7 h! u/ A9 b9 Q& N

, U8 u1 A, f/ ?5 y3 _; r; Mvoid        APU::WriteExProcess( WORD addr, BYTE data )( |. e/ {; x' h5 g3 Y& a1 I* N3 H
{8 j, M+ q8 c/ P7 g( x; J
        if( exsound_select & 0x01 ) {
" u- }) [$ X+ f5 `                vrc6.Write( addr, data );  n9 w& r5 \5 b0 Q( F* E- v5 M
        }
" H2 q/ H! I1 t) x2 w( E        if( exsound_select & 0x02 ) {+ \8 d& s& Q0 C* b* j+ L& r3 n
                vrc7.Write( addr, data );
4 u  p4 W3 f8 E) p        }
7 Z2 J! \; p. ]! X        if( exsound_select & 0x04 ) {# M) w* z, u! j: t4 O) T# t
                fds.Write( addr, data );1 L" G8 d9 ~! ]# d# h# w
        }8 t# [4 _0 [. Y0 @) x
        if( exsound_select & 0x08 ) {6 Y# @: W. ~: d  B0 r
                mmc5.Write( addr, data );
( H. R% E. w- ]        }
% g6 Z% q" X# ?; G* L, S4 W        if( exsound_select & 0x10 ) {% S+ @! ^' l* n# d7 c0 B) H7 a) o
                if( addr == 0x0000 ) {
* y0 }6 G6 G! ~1 w4 f/ b3 Y                        BYTE        dummy = n106.Read( addr );
! f/ J( q. a: v% y/ k  ^                } else {
+ s/ w. A2 @6 b2 k# d                        n106.Write( addr, data );
) W# d- @1 C" f) Q5 q' |3 I, ]                }
. L- x. J+ D# D' k& _& R        }$ I, V  T4 @% z  e
        if( exsound_select & 0x20 ) {5 \, b% a  c* G5 X' u$ \
                fme7.Write( addr, data );
. G* v! \( L$ {        }
! S: g  f, K. _}
  |3 `* [- d. L: Z# x
& c7 F1 Q( T1 A$ Yvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
3 F- T+ v3 ]$ h* Y. m2 P. U{
- L/ d: d) p% T# \9 u5 \1 PINT        nBits = Config.sound.nBits;! R0 X! n/ [: Q) t# U
DWORD        dwLength = dwSize / (nBits/8);
: f" W: |# a  C3 NINT        output;
( x: ?$ P" y! s* D7 |2 GQUEUEDATA q;
. w  @% |  q; ?7 G( h( i7 GDWORD        writetime;* j5 g: H/ v5 p2 r/ x# Z/ }( U- F" C

; Q/ w) w+ M4 C" R6 Z) tLPSHORT        pSoundBuf = m_SoundBuffer;
" t2 Z  S! [  i  vINT        nCcount = 0;; ^% Z, [" m/ q6 j" K/ D0 p  c9 M5 q

9 ]% w* x. ^, N/ _4 X! S7 aINT        nFilterType = Config.sound.nFilterType;0 H" M& m; e, J1 w5 E2 O0 }
# f) c. `; Q7 j1 l5 q, w
        if( !Config.sound.bEnable ) {
9 N3 U. k- W) v  o9 Y                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );& h4 j" S- t$ x9 C$ V1 }. w' m' p6 @& n
                return;
- I3 b. f6 r  q+ v3 T: W        }
0 i. p! r6 W" p  {
7 n( ?) \/ {! P( r        // Volume setup
, r8 {8 V7 |$ U9 X        //  0:Master
6 h  Z8 ]0 I6 C  o4 z  w        //  1:Rectangle 1
9 b6 Q- O) y0 i  B        //  2:Rectangle 2
$ d  }2 d3 T+ n5 G% B        //  3:Triangle! b5 Q( t! C. ?& |, j# _+ U
        //  4:Noise
0 O4 W$ K) r/ I& O, I        //  5:DPCM
# i2 L* G! r' S' R        //  6:VRC66 V. v, ~! P! d+ z+ x( ~
        //  7:VRC7
1 y% `- G( c: q" q+ `        //  8:FDS8 ^: ~* F) _" m4 A2 w
        //  9:MMC5# S; ^$ p* r$ ^5 k+ V$ v( Y
        // 10:N106
8 c- k1 Q3 i; K8 h4 h        // 11:FME7: Z2 W" {" f: M3 h6 a1 l
        INT        vol[24];
& @2 X# b0 Q* h  Y. _  p        BOOL*        bMute = m_bMute;, o5 W. o- y% q. [- C8 [; m
        SHORT*        nVolume = Config.sound.nVolume;! x. u$ n$ U" Z: S
: Z4 P4 G4 `6 G  {& E3 n1 H
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ I3 t7 U7 O4 O# c+ z, @8 c3 ?- M% e* ^% J! r$ T$ u9 y, Q+ a7 o
        // Internal; N# }  `7 s4 h% [
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;! B, ]1 d3 {! p/ {- u1 T. i* g: J
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& i, d- _8 @% [, p: }        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;) U! N4 g$ d1 ?
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;$ N- z$ X  V9 b4 m2 z
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
6 W! m9 g+ o! `; `6 [2 I2 q# X5 E6 [3 H
        // VRC6
  {& K5 C5 k% }" Z4 B        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
- y- ^' f8 S$ Z* x        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 _" V5 n9 M3 v7 J0 l* O: E9 a
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;0 G3 n+ o) s. k% a
/ x. S  x* ~4 ]) l2 \& o! v. I& P& q
        // VRC7& F9 K: F$ S% W- V! U, H
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;8 y& {4 r) I0 Z& U. u1 T* B

0 E7 d1 _( D; V( k        // FDS- G9 p& H2 D9 x( {  j* X
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
, ^; j* Z* ]* r# @
2 x$ y4 H% E# }  {) x1 M! o        // MMC5+ t. O# m4 |# |: `
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 l, d$ q, x1 ?' u2 o6 D8 r% p- T" V9 P
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;9 j5 h. M/ `9 b0 P, @
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 Z) s0 G" g# w; r0 S
$ a  f3 `! N1 J/ b6 t1 ]1 r) P
        // N106
; C7 S' \7 N0 T% z; x        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; j8 ~, c' B; {% X        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 G3 ]0 y# v( x. k& i# ]. t
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 Q; g, m9 K1 `$ r/ r1 _$ C        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 K/ Q) _  {* g
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; p9 ~7 ~- D7 ?) b        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( D) {6 f' q2 n! U' i/ `3 j! {- h
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 ]9 o. U' G6 |2 m2 r% |; J) p        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 q5 c1 L8 n9 V* a/ ^$ a: G2 p

/ i6 ?. b1 ^0 R; f/ m        // FME7
& M9 }9 s9 ^) X' k        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
) T- t% W* g+ F        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( D( b% n3 w: J( [; n
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' B. Q; ~6 {' h& l1 C6 }

6 V  r9 u8 s/ u//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
) s7 w1 \6 E0 B  C$ T: S/ k        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
: ^  W* u! n9 x6 i7 m+ i( l& h5 T( Q0 g+ O1 I: M6 J; h
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
/ _. Z5 t7 k5 d! u9 z: J        if( elapsed_time > nes->cpu->GetTotalCycles() ) {) C2 e/ z, V" I) {5 [+ y
                QueueFlush();
9 V6 V" ^( T! e! m) B2 A        }$ b$ [# P# i: v- E3 X  R- y; |

$ X5 K6 @: S' t        while( dwLength-- ) {
+ A/ y( `! X" J                writetime = (DWORD)elapsed_time;
0 `* ?- Y0 Z  g( `# f& ~" j
5 C% N/ e8 k1 r  a, Q; x                while( GetQueue( writetime, q ) ) {' w& F/ D& b) a( S5 o
                        WriteProcess( q.addr, q.data );
0 X$ j3 k3 C% `: O* Z                }) z. B" y( y  u, y9 E% P4 M5 \$ w% `

- m8 M: ~! ~# a+ G5 h( B# Z9 M7 `                while( GetExQueue( writetime, q ) ) {$ r7 c" _5 B0 P5 k" F* Z  p0 x- M
                        WriteExProcess( q.addr, q.data );( E  V/ P. m1 }# z
                }% V6 E$ d+ J1 B) u

0 W% O# |1 N! d0 K                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
2 |4 B+ X1 X, A# v                output = 0;+ c& T% w5 S, n" J, K+ N, P8 D
                output += internal.Process( 0 )*vol[0];- I  z2 e2 Y% a9 o# Z2 h0 {7 e
                output += internal.Process( 1 )*vol[1];4 K' E& w4 x- I: U7 B$ a
                output += internal.Process( 2 )*vol[2];
7 q. q9 B1 `, e9 X5 {3 h                output += internal.Process( 3 )*vol[3];' i) A. I/ g$ [0 T4 I, m
                output += internal.Process( 4 )*vol[4];# N5 K2 G4 u# e) f9 @/ W9 |
% j; ]! B' `& ~. d4 j
                if( exsound_select & 0x01 ) {+ V$ T6 A4 a3 v8 F# U$ H, _. W
                        output += vrc6.Process( 0 )*vol[5];
4 R/ i8 ]5 i1 e$ q                        output += vrc6.Process( 1 )*vol[6];8 u1 \( q  f* S5 j4 [
                        output += vrc6.Process( 2 )*vol[7];" m9 ]" [, k4 @5 }
                }6 n2 Y4 _4 Q5 M% o6 w  G, H
                if( exsound_select & 0x02 ) {2 {$ w* |. ^! V/ w' U: U6 g6 i: r
                        output += vrc7.Process( 0 )*vol[8];3 l) o/ |, W7 j3 z  \
                }5 o: ~" D! J4 Q* E# }6 f) n
                if( exsound_select & 0x04 ) {
' p( ]2 N, A7 g, K! n- ]$ G                        output += fds.Process( 0 )*vol[9];2 h! ?2 i& s! [- P* K4 _1 k
                }
3 Z6 S5 R' Z9 [) L  z, c3 \) C                if( exsound_select & 0x08 ) {5 N5 j9 F  s* X; W. ]: B( M
                        output += mmc5.Process( 0 )*vol[10];- L1 R, s! p0 z3 t  W# W* k
                        output += mmc5.Process( 1 )*vol[11];
/ z* J; p# P) k+ u7 S) y/ h4 R1 r1 J                        output += mmc5.Process( 2 )*vol[12];( k8 ]5 f: R* p, _/ T$ U
                }  a5 d9 W& v+ f+ _
                if( exsound_select & 0x10 ) {! B+ e: E' [5 l3 `% x
                        output += n106.Process( 0 )*vol[13];
* o1 L+ _* b/ @                        output += n106.Process( 1 )*vol[14];6 ?: V/ o- r7 Q- [$ ?4 Q8 `
                        output += n106.Process( 2 )*vol[15];
, X/ m3 i- @+ s& e1 |) b                        output += n106.Process( 3 )*vol[16];2 `  A6 M: a3 h$ @& _
                        output += n106.Process( 4 )*vol[17];
6 t% p! }8 @6 h8 m7 a                        output += n106.Process( 5 )*vol[18];
* V, t$ n1 c2 _9 l( [9 a9 {! E6 e                        output += n106.Process( 6 )*vol[19];& k. D- k. Y3 I+ b( H) c
                        output += n106.Process( 7 )*vol[20];$ Z0 K% i2 l  V% z4 ?7 g. K
                }
2 \8 i! ?5 W, U+ M3 p% _                if( exsound_select & 0x20 ) {
: [0 k, }& y4 G- r: y  {9 Z                        fme7.Process( 3 );        // Envelope & Noise
8 u5 c, ~/ L$ a                        output += fme7.Process( 0 )*vol[21];/ F: i; `% k( N1 C& w" r& i7 U+ Q
                        output += fme7.Process( 1 )*vol[22];
  f5 @* j* D! M/ B* |                        output += fme7.Process( 2 )*vol[23];
: n2 |* c. l9 D3 |2 T                }  d/ O; H$ e. M& t: a# e

6 |) |8 \  K$ f                output >>= 8;" F, j: x3 y* _+ T

# P% _. z* x: p9 z3 Q1 j( ~9 F, ~                if( nFilterType == 1 ) {& A! f0 k/ L, [( A+ i+ }
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& q: W2 S4 S. x
                        output = (lowpass_filter[0]+output)/2;
0 ~5 r% G* H: V/ z                        lowpass_filter[0] = output;7 d& ^' T% ~7 ]
                } else if( nFilterType == 2 ) {( w/ F' P  d0 |& A, ?8 l  a
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
+ U  b& F, W1 D8 O- m                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;) |6 Z* P5 R! {5 ^& _
                        lowpass_filter[1] = lowpass_filter[0];
: R! A- ^, B4 |8 v& P0 C/ J                        lowpass_filter[0] = output;
, x1 f- ?, R4 ?' Z  r6 B                } else if( nFilterType == 3 ) {
$ w+ y6 t8 W$ P* X0 r) O) f; i                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)4 L9 W" t0 `0 U: e: C/ A8 C+ j  m
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
# f( k8 n* |- g9 m                        lowpass_filter[2] = lowpass_filter[1];
4 V& [0 L+ j7 J# G; x' J                        lowpass_filter[1] = lowpass_filter[0];
6 y0 W$ @4 O3 s' o/ d: }; S+ l                        lowpass_filter[0] = output;: K8 [* i& r" u* P
                } else if( nFilterType == 4 ) {. L: o" v2 E. i! |9 n! z8 R# q+ X
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 k2 h: i$ N0 [+ E) c0 X: k                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
" q0 L' W7 s4 g2 u9 x' Z                        lowpass_filter[1] = lowpass_filter[0];
5 {, T. B) s5 z% G# ]                        lowpass_filter[0] = output;
* Z) T3 _5 }$ i5 |+ ~. e% F7 V7 `                }- I$ L! B" k7 o$ h: k5 i/ Q
. p% e3 ?+ A) X, @- F
#if        0
$ f" u: Y  O1 [1 M' A) K7 J5 o4 T- A                // DC惉暘偺僇僢僩
# d9 U3 w* m5 J* K$ d+ `0 ^                {
& P; O7 e* K" N5 T8 x0 L4 G2 }                static double ave = 0.0, max=0.0, min=0.0;
. N* Y3 p* {" {# O2 j- }! y                double delta;
% C) [4 X! f9 [- d( K                delta = (max-min)/32768.0;
  q! o3 H( a' w! d2 ~6 n' T1 U                max -= delta;# @8 M) m: z% u" ~$ w$ k
                min += delta;  L: K' A3 b% M  i: a  b
                if( output > max ) max = output;1 r$ f  {5 m/ _( X9 Q
                if( output < min ) min = output;
! y( x. N* G  e7 ]* S8 @3 F1 P                ave -= ave/1024.0;
# }3 D5 B. a0 w: H) z  c2 o( G                ave += (max+min)/2048.0;; {( J6 o) ~$ K% ]2 F6 b
                output -= (INT)ave;
; H/ I( _+ U+ T                }5 m  o6 M8 z9 r: d8 s
#endif
* I  \# H. j2 x# u% `( E" Y#if        16 E$ k7 d9 l3 _( Y+ Z% t- g# n7 M
                // DC惉暘偺僇僢僩(HPF TEST)1 `' |9 Z# Z4 M+ I9 g( ]
                {
1 t9 e9 z0 {" F: F8 }//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
- Z+ G; z. t; F/ A# l                static        double        cutofftemp = (2.0*3.141592653579*40.0);
  G- c$ x. g2 q# [6 C                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 |% R4 q4 ]% G  b- f8 X0 v                static        double        tmp = 0.0;
3 d2 T' X2 @8 U4 B! o. q, B                double        in, out;0 g9 q$ Q9 {* \0 g5 H1 D& [
( c8 F. G) f0 V4 m0 H/ y* K. U. _
                in = (double)output;3 |$ y* L) W1 |# C" v
                out = (in - tmp);
. _2 f- N* E' R! x+ X                tmp = tmp + cutoff * out;6 a! K2 B9 |; X2 f5 ^7 B8 T# o# i

- q  L6 E4 ^& t* U7 h% L                output = (INT)out;. v. ?6 i) \* N, P" Y6 Y9 f0 U
                }
; e1 v4 D" O; X$ Q5 m  T) \/ f/ ?#endif
6 Q% t! k9 ~# X( n#if        03 l  k  G6 D  Z8 [" X) D( I3 Z
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. D9 J. p) V! a$ {) K2 r0 ^: O                {: g4 D# h2 b' @- q) ^
                INT        diff = abs(output-last_data);( M. r6 ^, U" q
                if( diff > 0x4000 ) {
: p) O9 n0 ^* F# v8 u                        output /= 4;
4 ^: {' w* s5 H5 v  z& l6 i                } else
3 i" j2 Z5 T- p& s) {' s' z* m/ w                if( diff > 0x3000 ) {* K! H; l2 e( c* Y; A
                        output /= 3;
7 H5 x' j- d" a" U/ C                } else+ N7 ?) i( O. D" X! H) x6 w2 X
                if( diff > 0x2000 ) {
3 i9 f5 Q0 q+ [/ w1 L4 I2 @6 f                        output /= 2;
* `% |7 _" d4 }1 b% B) J% _- r                }
0 Z1 p3 Z1 S5 t) Y" D                last_data = output;$ B* B2 n1 w! b  \6 R
                }
- ~) s! b2 m3 v! A! v  S4 H#endif
1 t6 O! [, L+ w7 q/ F4 @  {                // Limit1 D& A# y0 ^8 d4 p) f% v. H6 ^
                if( output > 0x7FFF ) {8 m1 {) J  `$ R! _( ~* g
                        output = 0x7FFF;/ C# ~* S2 k7 k7 }- C
                } else if( output < -0x8000 ) {
9 z  j0 @4 j' z' A                        output = -0x8000;' f3 c! q, F, }5 b! h
                }
( ~% y4 c  G! }6 P/ ]+ Y$ u
) V  [7 g3 R2 L8 A2 I; x* l- x                if( nBits != 8 ) {  Q* f; u2 e& v& v$ C  R
                        *(SHORT*)lpBuffer = (SHORT)output;/ s8 t% x% ]' i4 F+ g0 _" x5 {
                        lpBuffer += sizeof(SHORT);# c/ ^$ Y" _7 h6 }  R1 Y& c2 n
                } else {. A, s$ J: @3 ^( U( m: b
                        *lpBuffer++ = (output>>8)^0x80;
8 ]7 e% Z( H0 f( `8 W3 L                }* c/ R: Y/ V+ G
- @; }, p5 V" P) ^8 H# g0 u
                if( nCcount < 0x0100 )  T- Y8 P' i$ @$ Y
                        pSoundBuf[nCcount++] = (SHORT)output;$ O/ A; e7 V6 W4 l3 Q
; U* m" Y7 f# p9 C) F! a' G
//                elapsedtime += cycle_rate;, A4 R  q* p8 M0 u
                elapsed_time += cycle_rate;
8 e1 V+ q" _) k) l2 s        }6 R7 s+ g& A4 x  Q+ _$ Q

. \' J( K5 R4 F" E4 [4 B5 e7 g#if        1
5 _8 ?6 G4 Q9 O8 s6 e2 C        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {$ `3 @5 C- v/ f  }5 b: m. H* q# N
                elapsed_time = nes->cpu->GetTotalCycles();
6 Z2 o* C, s# z, N        }' d+ J4 `2 o9 X8 j- |
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {$ n# s7 ]1 [9 V' C0 e
                elapsed_time = nes->cpu->GetTotalCycles();
! q+ |5 j( d+ o2 q        }
- B: u2 Z8 e+ c5 g/ w. \#else# G0 z5 Z/ C0 `/ G
        elapsed_time = nes->cpu->GetTotalCycles();7 ~! G$ I% m+ V% D, x
#endif3 c& R* R  e3 |1 G& X1 ~1 c7 v8 W
}
! P9 g  G, `5 P/ b
) M# Z% I3 P& |. ]! t. F+ U: ~* |// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡): Z7 m6 B' e4 l, L7 {) D, s5 v
INT        APU::GetChannelFrequency( INT no ); r- Y) P4 t4 ]/ v8 V
{/ n/ i; J2 l7 b7 I1 g5 M' E
        if( !m_bMute[0] )2 m) L" a; a8 W) @
                return        0;8 c6 K- l1 v( U8 i2 h; T
5 O, A$ \4 ~5 O# m; n) X! q: j
        // Internal
6 \) d+ `% R! _        if( no < 5 ) {& W5 l# }: K# G0 ~& [# U
                return        m_bMute[no+1]?internal.GetFreq( no ):0;& A$ ?' \8 \( t; Z: h
        }
% {) e6 u2 k& b- B  E/ J. v        // VRC6- g1 i0 p' b6 z- Q& i
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
- j, l# y2 ^7 g* _  M" e$ U' U                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# Q* W* f* b7 k
        }7 C, ^4 F2 p* H% m+ n9 s
        // FDS, A) _5 y( p, _+ c
        if( (exsound_select & 0x04) && no == 0x300 ) {( E3 }! ]1 Q/ v( N0 r/ b; a
                return        m_bMute[6]?fds.GetFreq( 0 ):0;  I( x2 M6 z; c4 O$ h
        }$ Z+ h5 r* D: \$ g7 t0 q5 F3 d3 _
        // MMC50 Q9 H6 P7 C1 f5 j
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {- @9 Y8 e: `. n8 ?
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
, P6 R7 R3 V" P3 r: u5 K        }% f$ {- m+ q, E5 c
        // N1063 j, c# Y; ^+ b* T: g5 L& P- d
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
/ s; W: ~/ o2 E( z                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: x5 T* ^$ M; u3 t
        }  P( K: Z. b  ?2 }8 p8 |
        // FME7
' U- v" _) z8 ]/ O9 t; E. d        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
# e2 r$ E. Q( y1 ?: H                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
( p. F( H4 R3 Q        }( R; [9 ~* H8 }1 R3 z
        // VRC7. ^/ B. |8 H% R9 l5 b) m% k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {, h5 ]7 d* A+ n1 t( i6 }
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;' ^" d6 c  ]: T- K6 j
        }( Y4 f* W0 o+ Q/ b# o7 o
        return        0;9 s$ S2 D& `1 l
}! }, B. _4 r, @# T/ k% _3 b$ p

6 @* Q* n, l7 o// State Save/Load
9 Q0 F$ [" s3 z. }( h$ @void        APU::SaveState( LPBYTE p )/ i: l; K( C! f; ?8 W) F
{+ K. z' z. `2 c3 n
#ifdef        _DEBUG. h: F5 h& T& K6 u9 u3 j/ Y2 |
LPBYTE        pold = p;/ {" K0 D% Q9 {% N( O; h0 [
#endif
2 [& X; H$ V( Q- c& f8 s5 z! Z! l* Y- q# T8 v9 H4 H2 t
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
! `0 u7 k2 F% T# V, P% ~        QueueFlush();' V3 L( B9 P" s4 _

& G( K3 p3 r! _        internal.SaveState( p );( k4 u; x8 X' E! g
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' R' h' B* ^2 g8 ~- X5 ?' u0 p( ~+ `; M: Z5 H
        // VRC6  C+ K' Q0 @4 u4 f4 C5 w. P
        if( exsound_select & 0x01 ) {
$ ^9 h3 S  X, J& |                vrc6.SaveState( p );
7 p+ L7 c+ C, z5 q6 Y& U5 F; o. P! l                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
( [4 Z0 n1 g2 G. _% r7 t+ }# D" b        }
+ t6 V2 I, m( |: H" F        // VRC7 (not support)& w4 [, X7 Z1 ^* P6 T8 q# Q
        if( exsound_select & 0x02 ) {
4 {  ?' s7 x$ H3 |! m                vrc7.SaveState( p );
0 |/ |. L; H6 {, Y$ v8 o                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding3 R1 o* Z% U) B
        }7 X6 m1 N9 `5 C& }
        // FDS
( Q1 \' T. k! ^2 {- p        if( exsound_select & 0x04 ) {
+ k, E1 k# h/ k/ i6 y* Y8 c6 o, o  @                fds.SaveState( p );! b- z4 J5 N; m. t/ C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
0 E2 T! W# ?6 _. I        }
% C9 V. A1 u: [# }4 S( _        // MMC5
8 U% u9 c; T5 A        if( exsound_select & 0x08 ) {
% W3 {( K) D  C3 V/ V                mmc5.SaveState( p );) H9 p: f, q0 ^# z( A8 d
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' p6 \& F# D2 r0 Y- B+ f
        }
0 X& r% R9 b  ?7 N, D/ I" d        // N106
: C8 x" h9 A) r: A7 L' G) i        if( exsound_select & 0x10 ) {) ]: g: D( }6 z; y: r- [
                n106.SaveState( p );
  u, B9 d7 i$ F0 ]- l+ \                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 T; l+ s0 j1 X  `. E( x, `9 ^+ q        }
" j) e" V6 I# D: }        // FME7  J* h% H& Q+ t1 B4 X! p
        if( exsound_select & 0x20 ) {
& R1 b  \2 Z; e% J                fme7.SaveState( p );
9 s' x% K2 r5 d  B9 S6 p4 x. I- M                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& @! B& ?9 G5 M$ c: K) z7 P% J        }
/ `, D. Q6 [2 s% T# I6 ~: i& b* }
#ifdef        _DEBUG- N; i8 W* t4 S& K; R4 a
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 a5 W( T& }% f0 x6 Q( A#endif
/ c4 M8 ~# @: `) ~}
. Y4 F5 `, `7 q, F# Z+ E1 R0 r" I6 F7 I* e+ H
void        APU::LoadState( LPBYTE p )
: [9 {! t# k$ ~- \: `8 t{
) a7 P+ @, w0 o2 e3 q        // 帪娫幉傪摨婜偝偣傞堊偵徚偡1 M) O* f/ @% P' k6 K
        QueueClear();
- ~" u6 V- d$ E
1 Y) |  o" T4 h7 Q& B        internal.LoadState( p );- X: e; J& r& W5 N, i: P$ I; H
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
5 ^) k* r7 y& Q! \3 @9 e* a( M1 P4 r- \3 g) i% |0 _& L1 W) `, O+ X
        // VRC6. k6 J/ P# V, x% @/ z( ^' c! v4 ^
        if( exsound_select & 0x01 ) {
  S! g+ S5 C& h; ?) G                vrc6.LoadState( p );
0 A1 [1 f! A' u. }5 z3 o: D1 ~                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ ?, W. W% Y& v0 O8 u; d        }- _1 n  R! t) l+ |* D- G
        // VRC7 (not support)1 N0 ~3 @% Q& g6 f. T! n! s$ o
        if( exsound_select & 0x02 ) {5 H5 [. H: g3 N  w( S9 k
                vrc7.LoadState( p );
' ]8 s! ?% K3 ~                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 D. O& {! a7 k+ J; s
        }
! \) S: L. [/ r( @+ q/ E        // FDS
5 L2 z. a- r8 ^, L; t- m        if( exsound_select & 0x04 ) {+ h& ?3 A( q! H7 v4 y
                fds.LoadState( p );5 i1 ?: K* b, Y$ h& a8 b
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" S) z. a! v2 J9 L% ?' D
        }& P6 G5 T9 q# f' `. a
        // MMC5
/ P7 _, G: Z1 l- _4 U        if( exsound_select & 0x08 ) {
9 y) c, \) n4 {+ E! }                mmc5.LoadState( p );4 n6 z& ^1 I0 y3 w5 k) f! M
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding: i5 f9 i) _9 l$ M/ g3 L" w; G
        }/ F1 Q" Z* {. y+ M4 K( Y
        // N106* q3 B/ z) V) J, O. ^& z0 `
        if( exsound_select & 0x10 ) {& @6 O3 N! m5 \1 J  p$ e; Q, J1 ?
                n106.LoadState( p );
0 Z" b& Z4 w6 V, }$ y& ]                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 r: i5 r% h9 H  N' n5 \
        }& S: z. w8 S% a0 N7 _& H0 m2 M
        // FME7* q( [) `/ z: h0 J7 ]' W
        if( exsound_select & 0x20 ) {
4 r! U  F4 t1 K/ e7 [$ w1 r                fme7.LoadState( p );: y! N: E5 k/ P1 z7 b
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 k: `. X" M; {2 D1 `        }
$ s& g, F' F3 K8 V9 v2 D}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
! H# ?4 a( H6 C/ M: n1 {7 q可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
- J9 D5 s  v# X4 K/ d9 h* I感激不尽~~
6 B9 j0 L  q# n
恩 我對模擬器不是很有研究,
+ w5 K: m7 ~( v% F雖然要了解源碼內容,可能不是很困難,  ]1 T7 h! e; g  ^+ H+ b
不過還是要花時間,個人目前蠻忙碌的。. Z) Y' O" p4 ?- Y  V' E$ E: x

+ t. F& Y% p; }0 a" F* V給你一個朋友的MSN,你可以跟他討論看看,
- L: Y& ?8 I5 j. S- E他本身是程式設計師,也對FC模擬器很有興趣。
+ r, E$ j  ]9 P, \" {2 o( l0 W2 t' X! W2 g. l5 _
MSN我就PM到你的信箱了。
8 H1 J) |4 |; H( c4 W# C8 I) I" p* \* |% z
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 . G- z/ `# r' {, m" ?0 v5 m
呵…… 谢过团长大人~~
1 F: }8 ^8 E$ p% V& V' o
+ Q, X1 @/ x4 C4 M4 T
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ; w; Y5 H5 m2 R, }, `
团长的朋友都是神,那团长就是神的boss。

3 z# d6 C% J0 e' }1 d1 X2 V8 }哈 不敢當,我只是個平凡人," b, R  _- v( i$ \( B
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
( B8 u& K, C( N. t( B- IZYH0 D! B% ^7 `+ Y5 G4 [
QQ:414734306/ a5 _9 e  b! f) x1 v' v; l/ h: D$ b
Mail:zyh-01@126.com
$ U5 G: q0 F0 O9 g* E
8 |& j0 `% W. c3 [9 o他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
( K4 |4 d2 ^8 {再次对团长大人和悠悠哥的无私帮助表示感谢~~
  y: `5 T$ R2 ~
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-5 23:52 , Processed in 1.113281 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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