EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?9 o( F4 F  V# S0 T! Z- h2 g/ ~9 d
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
/ V, s/ o' @  O8 O5 L+ H楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
0 z8 r3 }* b) P9 A这里有相应的模拟器源码,就当送给大侠了~~
% g: G1 U3 P1 r4 lhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( u4 a) b& _6 x2 t6 n# J; _/ C; b% D能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。. _$ j4 z3 P: Z( p7 e) i) ]/ r
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& R9 i6 t% m. S3 o
这里有相应的模拟器源码,就当送给大侠 ...

1 }4 W2 ]4 o& P: |( R& o; c% e聲音部分(Audoi Process Unit = APU):2 R( S! c1 ^% u
.\NES\APU.cpp0 k* I  z( p# i5 D0 B' o
.\NES\APU.h& f, B) w3 X& C9 Q* T) `9 r

9 X7 g7 P. b3 t$ p) n& c2 F0 b6 U( N8 \
影像處理部份(Picture Processing Unit = PPU):* A/ C3 l  {# @  H
.\NES\PPU.cpp
  G9 \4 y' b1 d* Q) h2 _.\NES\PPU.h
' [( `% s9 f# l3 C% A/ o" S- g6 t  k1 K3 J* T0 P& n
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
& r! k/ C: j, G) m(由于很多专用术语和算法机理都不明白,所以看不大懂……)
0 M& a( p+ ?( ^  G9 F//////////////////////////////////////////////////////////////////////////
, i/ ?+ u- h( |' b9 |//                                                                      //1 I3 ^" p2 ~, k; |# ]) f$ x3 Z
//      NES APU core                                                    //% Y% l# a% M' {
//                                                           Norix      //' a+ f9 e0 h: [/ d# j% N) _
//                                               written     2002/06/27 //8 v! l# T8 E% A  W
//                                               last modify ----/--/-- //# {! z+ d  X8 H  ^( o2 A% _
//////////////////////////////////////////////////////////////////////////. U- s, L$ ]; Z9 Q6 I4 s/ w
#include "DebugOut.h"
. u' h  M, @$ Z% f3 d#include "App.h"
, o. o& o; ]: S5 J. r#include "Config.h"$ y/ A6 |  v% ~1 _' |  _) z7 X- W- i

0 C& A" f: @6 C. C2 ?#include "nes.h": l1 F$ {, f: }* G
#include "mmu.h"# p5 _2 i4 E8 z' h3 u3 ~  F
#include "cpu.h"
! B( ^6 k% U3 {9 A#include "ppu.h"0 j% ]/ J  d3 B$ |( ~
#include "rom.h"
, P4 E9 H/ H+ b$ v% x' E# c  Q#include "apu.h"& {) ~. H# S4 b. V  R

& u; @: w$ ]: u4 ^; G. D; W// Volume adjust
4 t4 l% X% p/ N3 Z( B7 Z// Internal sounds' r! Z2 W5 X/ S* B" T  q1 Q
#define        RECTANGLE_VOL        (0x0F0)* [' P% X4 d- F' c+ V+ _
#define        TRIANGLE_VOL        (0x130)% K8 Y' V: W6 O5 Y( }
#define        NOISE_VOL        (0x0C0)9 ?3 |+ H# T9 `  g0 B9 t3 o9 |5 \
#define        DPCM_VOL        (0x0F0)" f) o: M' c- \4 w0 |4 U2 v6 b
// Extra sounds; U& n7 T, l* Q; \
#define        VRC6_VOL        (0x0F0)
* J. y. |/ u1 P& ~% l+ ?/ e#define        VRC7_VOL        (0x130)
# J7 J" Y+ ]- Y, k" ^#define        FDS_VOL                (0x0F0)% g! b$ p" Q6 w4 S* O# |% M5 n0 T
#define        MMC5_VOL        (0x0F0)$ Y! v! v. K8 R7 ~
#define        N106_VOL        (0x088)
& {! ?2 g4 l" C; D! |6 @  j+ ~#define        FME7_VOL        (0x130)5 f( R" D  M5 ~7 T

. l  }; Q' X5 IAPU::APU( NES* parent )
; z6 \. [+ Y" X4 f% I  }, M+ I{9 a. U' |7 z2 `  k6 E8 k8 G3 [* P$ i
        exsound_select = 0;
: t/ Z3 o. y: w$ R5 G4 }2 l' b& q) _- {( l
        nes = parent;
+ A& t; ^! X. o" @$ B5 P. |        internal.SetParent( parent );
4 }3 i, @' r+ L; M
) [- [3 U% B7 D* u" a% O        last_data = last_diff = 0;3 O. R9 Q! Z7 K- Q" w
! k' z# R# P- j- N/ X' M
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );& x( _" w; G! A( Z+ E

2 h9 k( {, v" s3 q+ A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );' m1 G# e: F. }5 D
        ZEROMEMORY( &queue, sizeof(queue) );
3 G$ s2 K# T+ \6 Z( ~! c1 g        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. D/ R4 n2 D. D1 [! i4 N5 p& E
7 g& e& o# \; c& F, `% Y! _3 L        for( INT i = 0; i < 16; i++ ) {9 D. v% n, I- I) D+ e
                m_bMute = TRUE;
3 a( m3 G6 x2 ]8 Y' L- i        }
0 V2 p5 T% K  j5 M9 a}
8 Y( I" l- X$ ^! l5 b# O; A: y3 E9 \1 c- D5 T8 Z2 a" z/ [0 T; N
APU::~APU()
" i: }6 U+ m- [{
# o8 Z% M4 Q# L) M* Z0 o( R}
+ j$ M' _7 w" }
+ r* e  o- ]4 V0 `0 bvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: [" k$ `1 O& ^! D. o: ~7 E{7 I" G- k, [( _7 C$ ?
        queue.data[queue.wrptr].time = writetime;
- m2 J* E$ {' b2 Y5 a6 J3 M1 Y        queue.data[queue.wrptr].addr = addr;
/ T* }0 a$ d% j" W6 U        queue.data[queue.wrptr].data = data;
3 f- x8 e+ c/ f! _        queue.wrptr++;5 ~6 b8 B  c, Y) f; D
        queue.wrptr&=QUEUE_LENGTH-1;
% d) R( E) y# E: u5 z        if( queue.wrptr == queue.rdptr ) {4 d7 y4 w- W! P0 z7 u' M) Z7 q
                DEBUGOUT( "queue overflow.\n" );! M3 _" |- |" }: u' p% p) @; N
        }3 x. ~  N/ s3 C, K) G
}4 f0 ~9 H5 g5 x

3 G# W4 p; E- [  _. _# K& k" @1 |BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
9 \# j6 R  N, Q/ P; U{  E8 W1 B7 B: e; j9 I( G, @$ n. a
        if( queue.wrptr == queue.rdptr ) {
, L1 v% `  K  i4 u$ ]                return        FALSE;
3 g: s2 k1 C3 @) R) D* X  P        }; l. [( [# D- ]3 e* m% o4 `" {
        if( queue.data[queue.rdptr].time <= writetime ) {$ n8 e! g. D+ ?/ h% F
                ret = queue.data[queue.rdptr];' I( Y9 V) ?- U# v( F# }' W, p
                queue.rdptr++;1 ^& T& X; W5 p! p
                queue.rdptr&=QUEUE_LENGTH-1;
2 t  z/ s+ j3 d/ M                return        TRUE;5 R5 d0 x) v+ n# P* i9 B& B
        }) x; b1 j7 V+ X
        return        FALSE;2 Q! u5 v/ y2 r: n4 _
}
( c- b7 n0 @3 r( s- h$ Y9 g; q
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )! E% q$ i) w- v6 R2 J# P
{
! I7 ]6 \- i8 g* M* \: @2 W        exqueue.data[exqueue.wrptr].time = writetime;
. c: \, B6 x3 ]4 m- c1 _: N        exqueue.data[exqueue.wrptr].addr = addr;* r, P( k, k! o% f5 |
        exqueue.data[exqueue.wrptr].data = data;
- q# b( N$ k- Q; C! a, P* x( B! q        exqueue.wrptr++;2 H0 b% Z9 s9 t& U- |
        exqueue.wrptr&=QUEUE_LENGTH-1;
8 L& N8 w& u- u2 {/ F4 c        if( exqueue.wrptr == exqueue.rdptr ) {: r* t; N) t7 n0 m6 Q
                DEBUGOUT( "exqueue overflow.\n" );0 e- P0 a% @, t' r( c8 I( ]4 D
        }% ]' L  W4 p0 f5 c
}
' e( l! Y0 B8 ~2 B; b- ?( A3 B9 r' Q7 k% W9 ~7 _% _
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
9 q, C# c: A; ]* g! G% {{
/ u. O$ U' s# v        if( exqueue.wrptr == exqueue.rdptr ) {
$ n. G$ q* p: d* I, c% k                return        FALSE;
8 w: @) Z5 m: M/ {# c) v# x9 |+ D        }5 B: V# g, F# R! \
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& b" p/ y4 N8 Z3 W) ]( [9 b
                ret = exqueue.data[exqueue.rdptr];8 c  V1 D* g, j+ h
                exqueue.rdptr++;
3 a0 r, h; _- [7 Z/ E                exqueue.rdptr&=QUEUE_LENGTH-1;: R6 d6 [6 t+ d+ R
                return        TRUE;
; \9 G& Y7 p2 w9 s5 G0 n3 l9 ~" n        }
$ u$ }# ~$ E  F6 R1 D        return        FALSE;7 G2 M4 y! F0 x4 V
}4 y! N) x4 z& h6 ^3 [
9 H$ l7 j, b% r+ u" c: V
void        APU::QueueClear()
7 t3 I( A  A6 B4 \" ]: Y{
8 c9 l: v% l3 I& }# |0 W        ZEROMEMORY( &queue, sizeof(queue) );
$ K  T8 w( F; N  s2 ?        ZEROMEMORY( &exqueue, sizeof(exqueue) );; x7 P( H8 {) o0 s3 W) ~* C$ E5 H
}( o9 h: k: _0 @5 T; q

* m# U0 w( V8 D; hvoid        APU::QueueFlush()! W1 X5 i4 ^$ C1 D# H
{
  b$ Y! E! C2 q9 \3 I        while( queue.wrptr != queue.rdptr ) {
; [6 X# E; S6 b                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );0 G# v* V( c  ], Z1 }; l
                queue.rdptr++;! C7 M' d9 r8 V( l, x: Q' ~$ B
                queue.rdptr&=QUEUE_LENGTH-1;2 g  r9 H, r% `% G# v- `4 n7 M7 F+ A
        }7 u/ {3 ~/ t) X0 p3 M6 V

- P$ g* E( G6 E# K- Z        while( exqueue.wrptr != exqueue.rdptr ) {
" f4 V1 n% y3 Y/ ?  p9 ~# w                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% Z1 T: N% V# a# K
                exqueue.rdptr++;
6 p6 |- H) i+ U6 T                exqueue.rdptr&=QUEUE_LENGTH-1;) `7 i- l# U8 |  D# b
        }
% N% z$ M- q0 I' |+ K  N/ c5 A}
" s% u* a0 }" j' f! a% H6 I
$ D3 t  u" w* j  B8 }void        APU::SoundSetup()8 F6 y; _- S9 A! H' o- M
{
$ Z  }7 g5 ~4 z7 f3 w4 c9 G        FLOAT        fClock = nes->nescfg->CpuClock;+ P4 x  c: V- j# E) t7 V/ b
        INT        nRate = (INT)Config.sound.nRate;
% d! S# Q3 D* v( D        internal.Setup( fClock, nRate );
/ Y6 S0 e5 C& y4 P* W+ Y* M        vrc6.Setup( fClock, nRate );
$ N* P7 X& b% X" p% S  b        vrc7.Setup( fClock, nRate );
- M9 `) [, N  R4 z6 P2 T, C        mmc5.Setup( fClock, nRate );
1 b+ y% Y5 m: w' e" _& y        fds.Setup ( fClock, nRate );+ u5 ~( L/ g, N5 M* c
        n106.Setup( fClock, nRate );' \' A* X# U( I6 b. y/ M$ w8 A, n
        fme7.Setup( fClock, nRate );
7 D- p. \# [8 c: O}
* n6 N2 T4 [' e. G. ~% N% X3 D" H) U& x" h9 C
void        APU::Reset()) k* N& o! s3 T8 {
{
3 A* H* g0 s9 K9 Q7 _. J        ZEROMEMORY( &queue, sizeof(queue) );
. C8 l. B0 f* H        ZEROMEMORY( &exqueue, sizeof(exqueue) );' D& E- p% N4 }( \1 A; X
. j4 s, N& v- r) ]. o
        elapsed_time = 0;" c' O4 @* O% f5 }% p6 y8 g; M
4 O; U2 {, _0 r4 Z
        FLOAT        fClock = nes->nescfg->CpuClock;
0 D5 K* d- T' w) q        INT        nRate = (INT)Config.sound.nRate;
8 Q& d( r$ M- h* N( T( l9 c5 w        internal.Reset( fClock, nRate );0 t5 m/ |3 ^' _5 c2 l/ ]. Q" ~
        vrc6.Reset( fClock, nRate );3 X, W/ V( N! w) L0 [
        vrc7.Reset( fClock, nRate );
7 L8 }0 I4 ~. v+ Q( B  P        mmc5.Reset( fClock, nRate );8 T# j; ^. ]0 c9 o
        fds.Reset ( fClock, nRate );
7 F1 u# W8 v& T/ C! q3 _        n106.Reset( fClock, nRate );0 G9 J/ m' c' N; L
        fme7.Reset( fClock, nRate );$ B& M6 J) N  K* @' a, B
. K$ |* F' ^* F9 g1 ]5 v/ t# D$ Z
        SoundSetup();
, O1 T! M. y, S9 F* T) Y}1 d# k; j3 j& m0 f

* Y* e3 h% T7 A, J( kvoid        APU::SelectExSound( BYTE data )
$ R! H: X  P3 S: z$ Q0 c% ]{& r' l$ _! U, h  q7 S+ a
        exsound_select = data;
. D& T" s$ d1 `: F" {: @. b2 C0 _}
9 u1 f7 {2 I# F3 E, M0 K7 Z9 Q% F9 A+ X* L$ E- U& v
BYTE        APU::Read( WORD addr )" i5 s- Z& ^0 e; O# Z
{
$ Q4 g( J2 p4 Y* N) g; i        return        internal.SyncRead( addr );# S) z* A2 D5 ^* p
}; d3 X/ W" j: s" Y& O
. V3 K8 {7 X# Z
void        APU::Write( WORD addr, BYTE data ); o) f# ~( l6 F+ F
{; n, \4 C  z5 M
        // $4018偼VirtuaNES屌桳億乕僩
& P% {; H1 e( G        if( addr >= 0x4000 && addr <= 0x401F ) {  g, b: g2 s- m" I
                internal.SyncWrite( addr, data );9 J/ p7 ^4 ?! Z# s$ P" ?/ i- @
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; g6 `0 Q2 @; {; @7 D' k" k. u9 A
        }
& n' @* b$ x( z, A7 \}
" T8 W! p; c' P& }- r1 j2 u- ^4 a6 U0 Z. D7 z( v
BYTE        APU::ExRead( WORD addr )1 c3 v6 M9 M* {$ G- b1 ?& j- h' l! ~, t
{
0 f" t$ ~4 w$ @* P  q! vBYTE        data = 0;. M6 D! V- V9 ]  _

, \: c# ^0 }, N& s0 t8 O, a        if( exsound_select & 0x10 ) {
- `: `. ]' t" @/ H( F& s7 C) g* {                if( addr == 0x4800 ) {
) R9 A2 A( e* V- g/ q: g                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 P3 h2 _4 Q" ?! l, e* y. l* v                }
) b/ ?% S- n) n) }- A& _2 e        }" t! I/ ]' H, w$ Z! q
        if( exsound_select & 0x04 ) {
  `4 V: J- y9 U& _- e% ~/ k                if( addr >= 0x4040 && addr < 0x4100 ) {
. i, l& g5 L2 h% Y0 s; S7 R4 c1 L                        data = fds.SyncRead( addr );
8 E" R: H9 F3 A- B9 a8 C+ O7 q                }
3 i( r6 {& G7 i& [# V8 ?7 A        }# j, L2 h  b# ]* O: B
        if( exsound_select & 0x08 ) {
! N1 U3 @$ k+ |& m  w  s8 A                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 x0 U* K0 d+ ?                        data = mmc5.SyncRead( addr );
1 U9 F8 _! u9 [: c2 T% L                }
. m  V; ~& G' ^- Y        }: i5 O6 F, R6 p6 D

, Z* e$ H8 _. C        return        data;2 h) C/ d+ ]: }0 N) d
}
/ F2 L, n( i# U2 K+ a
  i7 `) [' R" S/ Mvoid        APU::ExWrite( WORD addr, BYTE data )! c  d- P6 K5 J# e. f
{( _* m' x0 h* i+ Z. x
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 i# j' W3 m% ?% Z6 y0 B5 t# p
/ ?! m5 G8 Y, S        if( exsound_select & 0x04 ) {
, F8 V- i9 r4 G                if( addr >= 0x4040 && addr < 0x4100 ) {  [* D. S# o) j; L
                        fds.SyncWrite( addr, data );' H$ i  f; C7 J. {! R5 b0 ]7 W1 J' I
                }
6 i# R5 Z/ p/ z5 G        }* `2 E& b, J9 P/ e3 U( ^9 H
1 W/ v% N5 @; v) V* n: Q6 U
        if( exsound_select & 0x08 ) {/ Y# I0 \" G, G9 W$ _
                if( addr >= 0x5000 && addr <= 0x5015 ) {2 h5 B4 O8 J0 E8 U/ F
                        mmc5.SyncWrite( addr, data );
% a5 G2 ?' V/ }" b; r" r; Z                }( N, f. O7 e$ d5 T6 d
        }3 K* W5 v. m/ X7 L% {6 {
}
( m3 e0 }5 D+ P/ y8 y9 K$ O
- }' F5 _& k) u/ C$ R$ dvoid        APU::Sync()3 O0 \' A& O8 b0 X
{
$ E5 i# f4 f% W" g7 n5 `}, _# [9 T3 _& y) U- F8 @) m* h0 o

( f. u4 D2 Q- o: Q" U" {3 r! uvoid        APU::SyncDPCM( INT cycles )
: t8 J" x& V/ w. |/ r; ~( O{
7 @9 k" W8 i: G$ B- q& f        internal.Sync( cycles );
7 B( b* T9 D4 @4 W9 ]9 a+ L8 H# j) g% k' B
        if( exsound_select & 0x04 ) {
- ]/ W) ^  ~5 z                fds.Sync( cycles );3 E: Z" q. |# K% ~: M; [2 I& j, A
        }
9 N4 g7 u$ y7 V& e% B( |- u        if( exsound_select & 0x08 ) {
. O3 G9 y: ?2 J                mmc5.Sync( cycles );! a9 w6 i0 P( p1 ~* S
        }# U: O  N1 y) F. k* m
}
; [" ?2 Z6 V. T0 Z# A8 P4 i( K7 z. g
void        APU::WriteProcess( WORD addr, BYTE data )- h$ T% Y2 l* i" z4 u4 ]* J! P! h
{' t; L$ Y* t- F% E% a) q
        // $4018偼VirtuaNES屌桳億乕僩
8 V( {, C# a; w% X        if( addr >= 0x4000 && addr <= 0x401F ) {. ~2 A4 i/ v. [/ w
                internal.Write( addr, data );
3 M7 _/ L, d/ J. R  ~3 W        }
' z) s" Y/ y( h2 g. Q% d( U9 J! O5 [}
' K. `, J) X: ~
1 t$ w' ^8 ^3 J9 yvoid        APU::WriteExProcess( WORD addr, BYTE data )0 p6 o' R, z& [- Y% a) v* _2 T
{
& p! ?5 ]9 R% i3 e' w1 R        if( exsound_select & 0x01 ) {, G+ F  M& P) v7 B$ e0 T
                vrc6.Write( addr, data );$ l5 `& s# _7 W
        }
- p/ c( w) x" ]0 W6 D. G        if( exsound_select & 0x02 ) {
9 e; Y1 D) p0 r                vrc7.Write( addr, data );6 u. G/ Y  l, o; y& E
        }" I8 c5 H3 t/ z& z2 Z8 D
        if( exsound_select & 0x04 ) {
. ^+ E: G% Q) ~1 `; u; Q                fds.Write( addr, data );3 k6 L/ w, r+ z% b( W9 \
        }9 b8 `' Y1 ~# _/ h4 ?* N
        if( exsound_select & 0x08 ) {  C8 L4 L1 }# u) d3 v
                mmc5.Write( addr, data );2 I  g, `$ z3 B) W$ c
        }1 c" d0 }6 ?! M$ X1 Q% p
        if( exsound_select & 0x10 ) {+ W- R0 P" ^& o0 }
                if( addr == 0x0000 ) {" [0 N. s: x8 y$ r( T) L- J
                        BYTE        dummy = n106.Read( addr );1 K+ B0 ?" F/ z. \. h& i
                } else {
$ o5 T7 n# [5 x- y/ Q; k, C                        n106.Write( addr, data );/ Z- R2 ]8 L" G1 E" Y
                }4 @2 e: N* S7 ~8 L# [8 t- k+ k6 a
        }: t" o" v& A/ h/ s& n1 H  L7 g. k! F/ h
        if( exsound_select & 0x20 ) {& P8 {2 `9 J% q8 W  C% T
                fme7.Write( addr, data );
# c: |7 T9 C# Z4 \/ g        }" G. K2 ]. P5 J
}0 y: j$ g3 Q7 R
+ R. I4 E6 d+ Z
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )$ T2 _' I1 {* }# ]% A( c5 ~0 y
{+ o/ Y& v  @! w/ e0 R* Z, J3 h
INT        nBits = Config.sound.nBits;3 l. K: y8 n7 J; q& Y" n8 R8 P
DWORD        dwLength = dwSize / (nBits/8);
; w5 E8 q2 P+ Q4 O7 H9 AINT        output;/ @3 t" u7 x. l8 R- t/ @% c  }
QUEUEDATA q;
, ]1 I; G8 u+ xDWORD        writetime;
, G( _3 U4 K$ U7 M. S7 }9 N8 l
$ l3 X4 h, ?! Y( hLPSHORT        pSoundBuf = m_SoundBuffer;
. m& C8 P- i: F0 F; l6 [INT        nCcount = 0;
* a7 g, p. e0 r. U( u  M2 C  ~9 r9 b0 d8 M( D
INT        nFilterType = Config.sound.nFilterType;/ ?; ?8 v! l# q. K9 J
6 m" d' r7 j5 f5 L. n( a: t) E9 X
        if( !Config.sound.bEnable ) {
: p$ d% e; }& D- L5 o/ @                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
7 N. L- i$ `# i6 v2 s+ m# y% X. w                return;2 C: i% s  p6 f! k
        }
. z! P8 e4 w  l6 I4 ^4 ^: _" u5 S$ k1 F6 L  D
        // Volume setup
1 u  i0 m- s" J( t0 b! i/ i        //  0:Master/ S$ h  j4 i, o1 p( v
        //  1:Rectangle 1
* L8 w/ ]+ w8 a5 q1 c% ?; L9 l6 f        //  2:Rectangle 2
; g7 F1 Q8 L0 u) w, U: n9 N        //  3:Triangle. ^, O  ?- g1 f, a3 C
        //  4:Noise
" I$ j2 H& f; ?& i5 Z; Z/ G        //  5:DPCM
, @- }& h! Q0 N- m3 q6 k& c        //  6:VRC6
7 D) @6 E; e: O* P/ `0 }# z8 d! M        //  7:VRC7" t7 E* s( u" l# b: i! A
        //  8:FDS) k7 |4 K% d1 e& ^( }
        //  9:MMC5
- @7 a( U* I/ G( A        // 10:N106
, s2 K# s  g1 i# L' N        // 11:FME78 p5 p5 N- j1 V$ `4 x
        INT        vol[24];
( `4 |$ n: f+ T# }: H* I6 V        BOOL*        bMute = m_bMute;
% I; @: s) T) A; g. v/ Y# ]/ v        SHORT*        nVolume = Config.sound.nVolume;  z% D; r  \  n4 ^: v

5 s, V* @3 Z% A( \" s- p( a        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
6 h1 A- U' N) z7 _6 c5 s0 {& ?4 ]% z5 {* _- o
        // Internal0 z' h( t) L, a2 F$ i" T
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
8 o9 o. ^0 z& S4 f        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;( M8 C- K+ ?' D8 C; C! Z
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
1 _9 O" [. W/ |        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 L, l$ Q& t4 z+ e$ i/ w/ o        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;1 d$ F! R1 q& m: ]6 W$ q; N/ T+ f5 Y

$ b+ s% x1 n5 a        // VRC61 W8 k# O& C! c7 `* ~  t
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;; [: w2 G2 h* P4 o
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. O1 N9 o" A' z2 b( H! |9 M$ U% }
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& [9 h" U2 O$ C: _) v6 m) D0 |" Y6 U7 s7 s6 t/ [
        // VRC7: ~' W7 ~, u+ |5 e1 T, X4 @
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
, `" |, t3 T' d$ p8 B- U$ L5 i0 v( \# e9 m+ D! k* S* J
        // FDS
( M0 m4 a( q% Y9 P        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
  m# ?7 K7 |# Z# O5 ^4 x; y
4 g  B( v7 L( _# A+ T( \        // MMC5
) {7 F- H& h. k$ d6 o! Q        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 Y7 f; y- m2 v/ E
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;, u. w& z1 x6 ]6 u1 e' q2 `
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
) C5 |& W3 b' @' @( c6 ~  ~2 x2 l- R8 |$ S
        // N106# b# i0 S( ?2 E& f: K# [+ _
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: S# p# ]- q" J) K' @- o
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 s& N2 H  H* @
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; b- C5 V6 c( I( G
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  G- a3 {. a& d& X0 b        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: q( h$ i$ o' N0 @6 o
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 F$ O7 C: l3 w/ z, n2 d$ M- Q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# C( o0 R& ]9 M- a3 L; k  l- {
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 Y# h4 o* S8 {" i! c

! ~! m/ D: R7 o        // FME7
2 G* y' |3 E$ D1 N. C6 E! d        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;) |0 o% [, Y- Z- J& J
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;' S% d- G( x# S9 }. R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 _' j1 i, `' g% y- R1 ~0 }

  z5 Q/ n" X6 |//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
7 o5 `  o2 `1 m7 a- ~        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# E$ ]( z& C( f6 B/ P! M" S# o$ D

1 D5 y  X3 U% w0 z        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟6 b  U  ?7 u" o. C
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
: h% F) [4 a9 ]5 d                QueueFlush();6 r' B* {. C3 K
        }
  s& O, g6 ~* w% `  {8 `3 c, \* l! i$ S/ o5 o+ r3 h+ h/ X
        while( dwLength-- ) {8 w$ s8 b0 t5 }' f$ J4 P, e
                writetime = (DWORD)elapsed_time;9 V( ]' f( j7 Y+ N

% p' n' k$ Q6 B1 g5 x# N8 o                while( GetQueue( writetime, q ) ) {
+ d5 i, w; ]8 x                        WriteProcess( q.addr, q.data );
+ m& r- E) Y7 C6 K6 [- Y" \4 W                }- Y! P/ d7 v1 q! g: r! ~7 ~
; F( g) r* i, U
                while( GetExQueue( writetime, q ) ) {
5 `+ ^# j7 ?  ^  a' y" A9 D) X                        WriteExProcess( q.addr, q.data );
5 F4 [4 v  V2 |1 B: V& \: H                }# q! T: A& {% z
  y9 ]) x8 d1 J
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME78 K( n$ |, Q: E1 l, h$ E$ H4 y1 }
                output = 0;& C8 ]+ M/ M+ q) D2 Q& A0 {
                output += internal.Process( 0 )*vol[0];
! r* {) ?+ L+ d  `: Z* p) J                output += internal.Process( 1 )*vol[1];  Z  T3 z! h- G; P' _$ k
                output += internal.Process( 2 )*vol[2];% j) F5 j) q8 R+ Q  a
                output += internal.Process( 3 )*vol[3];
3 @( n; V9 k; f2 G* Q2 q# _                output += internal.Process( 4 )*vol[4];) {' p7 S# X0 d$ y
! R+ |0 F; \1 P" }
                if( exsound_select & 0x01 ) {1 J7 ^. {/ |3 j8 z# g' m
                        output += vrc6.Process( 0 )*vol[5];
+ c- c# {, s6 b/ `( G( F+ J4 |                        output += vrc6.Process( 1 )*vol[6];' ]' Y' u8 A  H$ B
                        output += vrc6.Process( 2 )*vol[7];
/ {# p4 P/ @% n$ f% \* a                }
& R- Q1 \% _8 s: f# V  x7 X! e                if( exsound_select & 0x02 ) {
; F. ?: r* h) S, `& m                        output += vrc7.Process( 0 )*vol[8];
; U( L8 L2 _1 l3 _, m                }! r5 o9 ~& ~7 c: D: D1 N5 E
                if( exsound_select & 0x04 ) {
) I; s5 }+ N  X, p& Z' H- s1 N                        output += fds.Process( 0 )*vol[9];
) x; y5 B2 a1 j                }2 i8 p9 l7 R0 W' @" m
                if( exsound_select & 0x08 ) {  L' O8 h" S& N' P3 E/ l; t- y
                        output += mmc5.Process( 0 )*vol[10];8 g3 J* z0 G9 z
                        output += mmc5.Process( 1 )*vol[11];) B. P& N. R/ A3 d
                        output += mmc5.Process( 2 )*vol[12];  a( v9 k" x9 s' ^6 D
                }
! a# }+ U- g, H0 J5 c                if( exsound_select & 0x10 ) {
. J2 x- k* w/ [5 Z                        output += n106.Process( 0 )*vol[13];
6 q5 N, P  P" }6 I                        output += n106.Process( 1 )*vol[14];
# p7 b0 B7 K4 H3 ^* w3 U                        output += n106.Process( 2 )*vol[15];4 o" H3 ~6 i1 d& `; e5 i" x1 |7 [3 O
                        output += n106.Process( 3 )*vol[16];
4 S/ Q+ H# _! {9 w2 O0 j                        output += n106.Process( 4 )*vol[17];2 F" F* `. G/ w7 E
                        output += n106.Process( 5 )*vol[18];
. M& Z3 L% y. b, }5 f                        output += n106.Process( 6 )*vol[19];
" _9 o' t  O$ o; {" M9 W) u                        output += n106.Process( 7 )*vol[20];
5 Q# c% W7 n" q, ]                }
/ ^9 b4 G& K" D4 X# o                if( exsound_select & 0x20 ) {& M& v2 o; d) \: w/ n0 [& [" D
                        fme7.Process( 3 );        // Envelope & Noise
& O, U# @, }2 j6 _# l) d% y) K                        output += fme7.Process( 0 )*vol[21];1 V+ L: b# |6 O3 w; l& U
                        output += fme7.Process( 1 )*vol[22];  ~5 c0 ~; I. @0 S5 \
                        output += fme7.Process( 2 )*vol[23];1 O3 i/ U4 w' ]
                }
- A/ G# {. y/ E
3 F; ^7 D$ @+ k                output >>= 8;
, p% G% d1 O7 W3 n, z( s  T: B4 l# u# t. W* w7 e
                if( nFilterType == 1 ) {; z+ k. B' ]9 w
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)* z# N+ f5 O) a
                        output = (lowpass_filter[0]+output)/2;
1 O0 R8 m$ u, p! {  @% ^. u                        lowpass_filter[0] = output;
  u& K0 M" z7 x9 V, o5 J) x4 q; e8 l3 a                } else if( nFilterType == 2 ) {
: }( w& H0 b" d0 \" t/ |                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
; C3 N3 ~* c6 B( j- p. p. S( ~                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;& Q* X) ^7 f& D: }! A
                        lowpass_filter[1] = lowpass_filter[0];
/ d6 S/ b& k) T4 ]                        lowpass_filter[0] = output;
; z! F* ?- f1 |4 N! {  R# D% z# d4 V                } else if( nFilterType == 3 ) {
& w( P: Q) u1 B                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)5 W) X0 D6 Z8 i
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
0 u7 ]. a: g6 H: n7 g& x6 ^" h# q' c                        lowpass_filter[2] = lowpass_filter[1];  S& h, F: ?* S
                        lowpass_filter[1] = lowpass_filter[0];
' E1 ?" l) v5 B6 `! a( S, `) F& q                        lowpass_filter[0] = output;
; ~# \% q. z: _0 b3 @: }. ]# O" f7 ]                } else if( nFilterType == 4 ) {
  l, k( p4 L! {  g( l. A- a                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3); M6 i4 P, v, p2 ?
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;8 u) z- }. }. M0 P+ R; W- v
                        lowpass_filter[1] = lowpass_filter[0];2 J7 x/ r: R4 H9 ]% z6 [
                        lowpass_filter[0] = output;
6 ~: _  d8 Q2 Z                }
3 c$ _% u# t0 h; x2 p9 [& j3 \  D/ ~* G5 Z1 K, k$ t$ {5 c
#if        0" J) C; U' J& A$ U; y! f* X3 I- ^
                // DC惉暘偺僇僢僩
  k! N/ B+ v- v. r$ m                {9 y3 `) ^. s7 g7 ~
                static double ave = 0.0, max=0.0, min=0.0;- B, M4 A% u' k  Q$ k( p% P6 P* x
                double delta;
' N* {/ O; [* G5 A5 s' _& y                delta = (max-min)/32768.0;
7 G" \2 Y* r, Q2 @9 q                max -= delta;& o. Y+ T# @$ |2 R4 M- q
                min += delta;6 ~7 p2 r3 u) W( O! G, [5 m6 g0 V
                if( output > max ) max = output;
. I1 {/ B  P9 x7 u& c+ n/ Z) F: m5 ?                if( output < min ) min = output;
# l5 B* a1 U& E3 M4 ]% f                ave -= ave/1024.0;
$ Y4 s, R$ E/ }' w0 Y                ave += (max+min)/2048.0;
  ]5 ^% @& ~9 r) l9 S$ I% r6 Q                output -= (INT)ave;4 s5 X* d/ Y* i- y# B, i% I+ ?0 ]& P& F; O
                }$ Z, ]& \/ i* @# z- ?" L3 ]
#endif
  u0 L! \5 @5 E3 r; T8 ^! j#if        1# @1 M. p$ e% w( T: [9 e4 _* H
                // DC惉暘偺僇僢僩(HPF TEST)* ^9 `& ?1 g5 g; h" o
                {) c5 G1 X6 S+ W
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);7 t  t6 s7 W) g9 c5 p+ r3 {
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
9 T6 ?& j( c' z5 e  _; K) W$ e                double        cutoff = cutofftemp/(double)Config.sound.nRate;2 i1 C& f# G' S% }$ K0 x7 W! h
                static        double        tmp = 0.0;/ Q4 T: f. Y. ?7 ^! _6 z& i
                double        in, out;1 Y9 i7 \- M7 y; [

2 e9 Z% j1 b0 q: t4 I; }& ]                in = (double)output;
, Z+ f$ P) y% A  c                out = (in - tmp);
' \( f8 a$ h1 B$ ^+ d+ t7 A                tmp = tmp + cutoff * out;0 L$ u- v4 U6 ]7 w8 T# F7 _

3 N, C2 @) X8 O1 S- Y8 Z0 f! A                output = (INT)out;
) @3 t* M8 u6 h* I9 u5 |                }6 `3 k+ q' p' Q) c9 C' l; ?9 g
#endif) s! A# b( v0 T. e( [3 o' d
#if        0* R+ M" ^8 M8 B
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* T' W% t- t- }1 N/ Y2 i& i
                {
2 b; I$ N% D) f& O( Q# u                INT        diff = abs(output-last_data);: z  y: D2 D* j8 |, _
                if( diff > 0x4000 ) {, ?, |* D! q& r
                        output /= 4;
3 c2 ?4 s/ Z! E# t3 p1 M                } else $ h) k* h6 \9 r) F/ Q2 V
                if( diff > 0x3000 ) {( L& X# j- w: R: {. Z
                        output /= 3;; P$ ]& e" m1 C
                } else
; i* o1 J% n' R' ?2 b* W                if( diff > 0x2000 ) {7 g* \$ e: ^4 ]7 G8 b, o
                        output /= 2;3 U  W% T" ~3 _# S. A
                }# N! L5 E! f) H- c7 _" z& \) i
                last_data = output;5 s3 r0 g" L8 Y2 h+ C- Y3 B# V
                }
& L4 c4 E% e7 n8 |#endif$ r+ f  d% m9 Q1 }0 ]
                // Limit' o5 Q/ {6 x- d8 C2 D4 Z9 b
                if( output > 0x7FFF ) {# h/ V+ e* `7 v& P# q/ x, H4 G
                        output = 0x7FFF;4 R. v7 M. U, p7 W6 r0 k" M  [
                } else if( output < -0x8000 ) {
) O- ]( I7 x4 d2 S+ L                        output = -0x8000;/ A* y6 k" d' Y& W
                }
( B$ P" Z+ o* w& h4 X; s
3 J4 _) i  Y' ~* f                if( nBits != 8 ) {
: F) |+ ~  u) O# B) [                        *(SHORT*)lpBuffer = (SHORT)output;7 m$ X  V1 r" o5 F2 F9 [% h, r
                        lpBuffer += sizeof(SHORT);; Y: \" v! W6 w3 n, X/ [
                } else {7 Z, P( f0 |7 X* G
                        *lpBuffer++ = (output>>8)^0x80;
5 U7 X6 o' v- B1 q9 i0 K                }
3 t8 c% d+ o5 Z& w1 |
( A" h# Y/ `5 B$ N, t& r                if( nCcount < 0x0100 ), q1 ~( j8 U0 f: d7 C* W
                        pSoundBuf[nCcount++] = (SHORT)output;
' n/ T0 d4 h5 t( t
* V# `) J2 E' n: k//                elapsedtime += cycle_rate;
7 c  ?: n$ D- @& m) M" ^6 @                elapsed_time += cycle_rate;! ?% J( G) j# R4 t9 t6 Y
        }" h, V; y9 j' i! ?

' d0 F9 |' ]; U$ H, v' r#if        1' J% n( g+ {) J4 J& Q+ n$ E& x
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
5 |' Y! |; Y& g  F! }; y0 p                elapsed_time = nes->cpu->GetTotalCycles();
/ \) U. o& w( i2 Q& C) a+ t: O" F        }
7 x, c9 |3 Y1 T3 h7 c7 a1 i2 i        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {) y  o2 Z0 I/ F3 E
                elapsed_time = nes->cpu->GetTotalCycles();
8 P, s# @, Z/ h; w& B        }: @5 g- C& p2 A( A& H0 u
#else! m* n9 r/ ~5 j$ W9 j
        elapsed_time = nes->cpu->GetTotalCycles();
$ P. w  W2 L; O% S* C5 Q! D#endif4 w  F1 z; x5 u! d% V2 |9 P, T
}1 ~6 w0 |( P) j1 I8 x

0 W: R1 [: a3 n% g) Z# _// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
" }" H" Y2 O' _' O. B! [) B5 `INT        APU::GetChannelFrequency( INT no )/ Z$ M/ j0 s+ C1 H) Y" q$ _, \' i& U0 A
{
& }" {9 L, ]5 O0 G        if( !m_bMute[0] )' }. B  I9 k/ ^* a* d; g# m# s
                return        0;; z  l8 d" i) h5 R
; n6 b; t" P; z' e# k
        // Internal
3 k% L, f0 ~6 w" z  M        if( no < 5 ) {
' e' ~/ L" }) E                return        m_bMute[no+1]?internal.GetFreq( no ):0;, S1 l. n4 D1 I
        }
% h4 g: _4 \$ u5 Z% O0 F        // VRC6! b+ b% A' B6 y8 S* e
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {0 f7 ?+ N, e( V/ d. e
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
; ~% ?3 c) y$ F! b2 ~        }
% e3 a3 a5 J9 l% g/ J& K* g        // FDS; b, i# Z, {, r
        if( (exsound_select & 0x04) && no == 0x300 ) {) B% Q' i. J! }3 S
                return        m_bMute[6]?fds.GetFreq( 0 ):0;: l$ b7 G+ P' W4 }! p$ L) p
        }! q4 K$ U$ W1 a0 r; P0 ?1 _  @
        // MMC59 i+ x" V. q# G8 q9 Y, f7 t' |
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {+ A2 ~% j( B$ j6 F" Y) t
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;2 M$ c) n+ g: a6 K5 R% ]0 y! Y; X
        }% S5 L4 ~! w- X$ X) J& G
        // N1062 }& G4 Z, W/ u: O3 N
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
2 r" f" W, f( ~! E+ d& o                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
9 K: Q; X4 s6 s# u, H) H        }
3 U8 g0 O, f( V& Z" \- m' b        // FME7$ u" E" V/ @& @! j: o  K( l: @, r
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {0 |# W- r6 [4 ]! ]' k
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;" }% X' ^5 X4 B, z  M+ |4 B
        }& s6 `3 K; }8 ?
        // VRC7
+ L4 ?5 l- f! A        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {1 w1 o( V) o  t+ W: [5 a
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;* W% I: o5 g8 g2 C0 M) y
        }
6 B8 F! h' r% U) A' B3 j6 @% e2 W        return        0;; L! f) y1 U7 w+ R  P
}
) k5 D% Q7 S# E6 J/ H8 ]/ ?$ E
. q$ r; e2 X, ?3 f- B, U9 \// State Save/Load
. u* n. D$ v, w. G/ yvoid        APU::SaveState( LPBYTE p )2 A( }3 G# O8 S* X6 |: S
{. g+ [8 J" H5 i$ `7 d/ B
#ifdef        _DEBUG: I8 F# z' W; @: w1 ^- q. f( K- M( r
LPBYTE        pold = p;, F3 V5 P$ \. O8 M" @5 T3 w, C( k
#endif
4 b1 N  k9 [: S+ n0 x' V/ y7 }5 D6 f# }/ S( [" M
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞) l8 U9 K7 v- p, T
        QueueFlush();
7 N2 N  `2 D8 a: Z/ n9 Q: ?* d$ P" u7 m" b: I) Q4 }6 t; M: h
        internal.SaveState( p );
6 U2 v; a* Z; D        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& [5 ]6 L& p4 R5 y
- ^. |* `0 O! V& o% e" |0 p
        // VRC6
+ G/ S5 Z9 Y& }( t" \7 m  y        if( exsound_select & 0x01 ) {/ [1 J4 r! b& [, e! D& v# t; \
                vrc6.SaveState( p );
$ q' ~( J. W" r8 ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
4 C8 {; g2 E: w1 v' b        }1 R2 Y" y) z* m' r# L' p3 f
        // VRC7 (not support); e4 D: K# Y9 u, s
        if( exsound_select & 0x02 ) {$ _+ A! L8 f6 L/ X$ c- U7 G+ O
                vrc7.SaveState( p );
. m8 i+ N( `3 ^' H0 x, V. |6 v                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) B- m" ~, v1 Y9 g; v7 V7 T6 l
        }7 R9 R$ t4 [- w
        // FDS6 ]5 J9 T, A/ k9 Z" H9 Z3 t6 D
        if( exsound_select & 0x04 ) {3 @4 @2 @0 p9 g+ I$ ~" X
                fds.SaveState( p );
3 a7 j6 _5 F- j! r0 x                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% k) c( i# @3 ^" E
        }- E) `/ D) L5 w% s  h( L$ a
        // MMC5
+ i" {# c4 J  z1 i$ |        if( exsound_select & 0x08 ) {
7 Z- [" `/ I, m: `. Y0 q                mmc5.SaveState( p );
1 X, C8 j, f# A0 f7 M+ G2 P' v! n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding2 b3 D# f6 d: v$ j8 w
        }
, e) a& p+ k- n/ s* {0 O+ }) G        // N106
& `9 i' G: i) m. }        if( exsound_select & 0x10 ) {- W) E; c( d9 e8 O9 f3 U
                n106.SaveState( p );
7 f" H9 M5 g6 U& x! O3 H                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding/ e) R  S7 e  ]' D9 E" c8 v1 b
        }
3 w* _- t, T  `9 S+ \        // FME7
7 S% j( u) F4 v* Q7 n        if( exsound_select & 0x20 ) {
3 C" l' j/ v" j. z% J/ K% X! E& ]                fme7.SaveState( p );
3 f3 |' y+ q) Z1 |9 H                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! T' w0 s# D9 {1 Z# v        }: a+ {7 }% R& n& @' D
& B5 c3 {: _0 w, c
#ifdef        _DEBUG
, W1 \$ i1 N, Y0 y/ ~* VDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 H/ }. j# ^1 M
#endif
" r& b5 f9 c$ g; e& A4 w3 ^}% e& K6 [* p* m$ l; j5 T3 Q5 e

5 E/ p  _1 Q9 D+ h6 o- }0 X$ Z( mvoid        APU::LoadState( LPBYTE p )- j$ H3 W& E7 J" G9 Q
{1 ^( U& u& P4 |2 u9 }+ x
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡: q% ]' o! S) Q; m& A# Z! E& f
        QueueClear();
5 R1 u+ ^1 v8 _0 |" C" B6 S8 N% u9 R/ B7 r; r
        internal.LoadState( p );& j* ?3 w" M" U( E& J
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; `" e& ^, h# y, W" C* S8 r1 @  a' u) c- f
        // VRC6
* \9 ]/ N: Y4 }% X4 p5 q        if( exsound_select & 0x01 ) {
8 \+ X9 L% o% V$ O$ Y  H) A$ y                vrc6.LoadState( p );' o8 C8 F: i9 _% n! ?
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
$ S) D* D+ u; F8 ?) _# m4 D        }7 Q! c: r) \- T7 K
        // VRC7 (not support)
- v% b5 O! D% m9 U+ \: h. z        if( exsound_select & 0x02 ) {8 P" K% p3 _3 x; P8 T
                vrc7.LoadState( p );( c( b+ O! V8 A% v" n
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# ~5 G3 _) R! A; o$ X
        }: z; R: R  U3 L9 k
        // FDS
! q0 ?6 ]4 [: Q        if( exsound_select & 0x04 ) {2 S& e( {& R7 r& ], P* t
                fds.LoadState( p );
/ I% S7 ]) D. D                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
% ]8 V; R" W0 @6 o        }2 q6 L( |6 I7 h7 ~
        // MMC5
. B5 Z) A6 f- p& e        if( exsound_select & 0x08 ) {
  d& B( Y9 D" D0 }$ k4 u1 u                mmc5.LoadState( p );
& |$ z3 K$ T2 S- |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 o' p) U! K7 G, J
        }
9 |+ o- w2 A9 @        // N106
( q: P) q& e( D; e! c        if( exsound_select & 0x10 ) {$ B: ^+ s/ q5 S) w, {
                n106.LoadState( p );( ^/ ]0 r1 ^- |+ L
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding+ g/ l; M/ ?4 S4 ?- d
        }' K4 U" C" q5 w* m& S0 C
        // FME77 @! o& I2 S2 l) Z
        if( exsound_select & 0x20 ) {
4 E" D) a4 }! g- s8 o& _                fme7.LoadState( p );* T7 n* n" N' o$ C' u% c. @: ^+ A
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 j" d0 J/ z6 J* }2 k7 v# z
        }9 k- n6 K3 I  i4 f6 R- [
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
, ?" i8 X4 f. K, y8 J: o可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
9 w7 o/ ?* B  c5 w感激不尽~~

# ?7 i/ X" n. [/ D2 E恩 我對模擬器不是很有研究,
9 ~* J' \- G7 l9 ]雖然要了解源碼內容,可能不是很困難,3 I: _9 Z2 _6 }
不過還是要花時間,個人目前蠻忙碌的。) M6 V4 a* @! Z* i" ^* m' P4 d4 ?
- ^" X( L# g2 G$ z% z2 }3 i
給你一個朋友的MSN,你可以跟他討論看看,: {; s6 y0 ?2 a0 j. @
他本身是程式設計師,也對FC模擬器很有興趣。! c% ]1 P' p! N% r
$ y" ]. f6 g" A9 H! }; K6 y+ F7 ]
MSN我就PM到你的信箱了。
& j- n5 l6 U2 Y+ N3 u+ O8 u' }
( E0 a* W: `/ N. U' _" d5 I希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
2 Y$ Q7 R  f0 r9 S: i8 B; Y呵…… 谢过团长大人~~

1 e, U3 e. I3 S# ~
% o4 u0 N0 r, @% S哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
9 |: {9 M/ j* C  P6 \团长的朋友都是神,那团长就是神的boss。

$ Y+ |6 N8 t2 O哈 不敢當,我只是個平凡人,
! l  x, |3 w# B" R4 {3 V3 |) B要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
, Y) ^/ W6 B# ~ZYH/ z- y/ i( B' x% P
QQ:414734306
% r3 |7 u  g4 m' j/ ?Mail:zyh-01@126.com6 U6 O3 n. o, G

2 Y& S7 ]! c6 F& i他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表   q, J6 z& |1 _0 f- x# V
再次对团长大人和悠悠哥的无私帮助表示感谢~~

! k4 Z% k% _8 g' x8 o, v不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-10 23:29 , Processed in 1.093750 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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