EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 X( {- j4 V' l4 D2 D& p, x楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
" r$ c/ |& x7 B' F, r! j这里有相应的模拟器源码,就当送给大侠了~~6 m- B% x: D! l7 ^2 l0 D' q
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
7 [* R# O! R* G% F能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
2 r8 X2 h7 {' E. A* ?楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# n/ {! L9 }7 x& k这里有相应的模拟器源码,就当送给大侠 ...
- n9 g  Z* g; }7 n4 }4 r3 f
聲音部分(Audoi Process Unit = APU):9 W0 E& t) P- g& @# `; q) u
.\NES\APU.cpp3 k- B8 Q8 \6 X1 ]
.\NES\APU.h
2 T" f8 [) h+ \8 a+ d4 @
* _3 \& H5 T6 @* h* O
1 n' ]- [' j3 g1 [7 \4 |影像處理部份(Picture Processing Unit = PPU):
' d, n" m; g/ J2 }7 I3 o.\NES\PPU.cpp5 T# L* r6 j' y) j
.\NES\PPU.h+ R$ S& s; B5 X1 H( m9 X! L: g
( O" r  Q' }+ ?# K
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
- m/ m2 w3 J2 A, V3 N5 ~5 l& j(由于很多专用术语和算法机理都不明白,所以看不大懂……)9 x+ h1 W) I4 ?( s1 k; t+ J
//////////////////////////////////////////////////////////////////////////1 F* y$ b0 W5 C& h: V
//                                                                      //! h' a# b5 |* D& W( a6 Q
//      NES APU core                                                    //9 d$ J  {' O" A5 t
//                                                           Norix      //1 b  K. W/ p2 u0 D
//                                               written     2002/06/27 //8 I1 c7 G0 t9 S: F2 o" ]1 F( X
//                                               last modify ----/--/-- //
2 o. p4 U, h8 r: |: z$ C9 g- ~//////////////////////////////////////////////////////////////////////////$ X+ r. B1 s( I4 e( U) l
#include "DebugOut.h"
* y1 K# N' X+ k#include "App.h"3 |: k+ @0 R) Q
#include "Config.h"2 A4 w/ Z5 x3 Z
- S/ x& m; @" ]" {) K, [
#include "nes.h"7 ?5 r8 L$ j6 t0 W- Z; @. V
#include "mmu.h"$ I. R4 t$ _' Q1 b+ t
#include "cpu.h"
+ X% `5 y. H; U2 U#include "ppu.h"7 H" L  F7 n& D8 {& G
#include "rom.h"
$ ^# O% h# I0 O1 }, E- F. c8 D4 ~#include "apu.h"2 [% ?" D- g" o; J, \# K/ @

! h6 O! V& H: I* I" I6 `1 i// Volume adjust
2 N" o- Q' }/ B) u2 I+ V// Internal sounds9 X$ `4 P) m2 I% [! M" s( ~
#define        RECTANGLE_VOL        (0x0F0)
7 r8 _/ g" U8 K) Z3 |#define        TRIANGLE_VOL        (0x130)
( k5 b$ I' w. _# W#define        NOISE_VOL        (0x0C0)
4 Q# ?- Z8 d: r, K/ B0 E#define        DPCM_VOL        (0x0F0)" h# T) O3 j3 i1 d, |# `, O
// Extra sounds8 t9 h% h  u7 r+ O3 P
#define        VRC6_VOL        (0x0F0)
0 t' _* F5 e1 _6 J+ o% g#define        VRC7_VOL        (0x130)9 u3 i/ ]: a2 k8 F+ c7 l& w
#define        FDS_VOL                (0x0F0)
1 q0 \: h) X$ H  q# Z8 W#define        MMC5_VOL        (0x0F0)  k7 {- a2 s! \; V9 s' @( `
#define        N106_VOL        (0x088); Y; v( U( f- C
#define        FME7_VOL        (0x130)
' j) U. j4 }/ c, `( H) [$ Q) p3 e" h7 D+ }& _8 `* P& R# P' F
APU::APU( NES* parent )
4 p6 d* V" {0 {{: t& ]: Q. u9 W# O! d
        exsound_select = 0;
/ Q) ?' S# P4 d, M! ?# N# t) I2 ^+ a# p7 f. u: E, j+ {
        nes = parent;
& R7 V9 C0 H# ], F& T7 \9 e, w        internal.SetParent( parent );/ {( O$ M7 @8 ~4 ~
; b+ {- ?# s, ~9 J
        last_data = last_diff = 0;
9 O& k3 G6 z* Q! c# }
* L8 g! G) c2 V- S        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
; L6 T% x7 v1 d: L7 W
3 K5 v+ r- x. X; X8 M        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );& r1 z9 R4 S" s& U! A, C
        ZEROMEMORY( &queue, sizeof(queue) );2 P; N+ [, o8 q- u6 N% F2 X# Y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
2 r8 z7 s# r' T; i0 w" F8 X0 i; _( Q
        for( INT i = 0; i < 16; i++ ) {7 `' L; _% S. {
                m_bMute = TRUE;3 N% d$ d/ o  S; g2 x$ D) o
        }$ D4 S1 p/ {  j! L7 g! c
}# s; M0 h* `( E; |8 ^( m
0 f9 K9 K8 M$ l9 \# z/ w
APU::~APU()5 ^$ X) p/ y2 w) ~( h
{) n9 x: I* g4 G/ {! s
}
0 i2 Z, G1 p9 Y) _! @7 W
  `  l. O/ _/ j6 K& s  x* Pvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )9 i4 p  Y# \. N) w$ X$ w! n6 [7 X
{
/ D6 e, \1 x4 o2 u) F+ Z        queue.data[queue.wrptr].time = writetime;% P, U: f  o0 r  ?$ r3 Q0 X2 ?/ g
        queue.data[queue.wrptr].addr = addr;
/ J; s$ r  o/ b  W, q        queue.data[queue.wrptr].data = data;
. n- K% i" C7 ^        queue.wrptr++;
: n; |! a0 ~3 }- w2 ]  G        queue.wrptr&=QUEUE_LENGTH-1;. v4 v4 J9 |0 B: ~9 j
        if( queue.wrptr == queue.rdptr ) {! L  b" l" K& F$ z
                DEBUGOUT( "queue overflow.\n" );
( C4 p6 q, ?+ ], ~" Z" M6 \% f        }
8 Y. |) ?8 P  R" s}- m6 ~9 R  ~' c/ J! ~' |* V

; V( R$ d/ h2 z5 Y" ~& c5 d5 _BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )7 O! y: Q' b1 X$ [
{# g( m, r# y$ [* {9 Z0 C% e
        if( queue.wrptr == queue.rdptr ) {  j% W, K& r5 m5 Y  \8 ?* T7 r
                return        FALSE;
, S* {9 m0 V) P' `        }
/ J$ b5 X( j9 l- e5 B7 N& B3 e# x        if( queue.data[queue.rdptr].time <= writetime ) {' H! _) u) x% z9 K9 h- J/ X6 J/ D( g
                ret = queue.data[queue.rdptr];5 |) [' @/ [- x- E
                queue.rdptr++;/ }4 N( I7 I. |5 K- }- q1 u' x, C
                queue.rdptr&=QUEUE_LENGTH-1;
+ z9 r. H- F) p2 Y                return        TRUE;5 P0 C/ T$ J6 j  t; A
        }9 L  T1 K1 w( a' }- k) t
        return        FALSE;
$ I1 g- w6 d: w, b; u% `. b}, V2 t& t3 H. }3 P, S7 `. }" Q

) V% `; ^3 i: bvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data ), k1 D! U0 ~+ s8 z. c) u' {! r& x" U
{
0 i5 X* ~9 Q! O; ]! _        exqueue.data[exqueue.wrptr].time = writetime;6 ^; Z/ u1 C- h- L
        exqueue.data[exqueue.wrptr].addr = addr;
: a3 E* k4 i3 \# }; c! V, b        exqueue.data[exqueue.wrptr].data = data;
) T" P- A: i- W0 V. X# j& n# {        exqueue.wrptr++;8 y& l: a, |  j/ q0 n4 X
        exqueue.wrptr&=QUEUE_LENGTH-1;
% Q) R6 U6 l9 ~( L5 @) y        if( exqueue.wrptr == exqueue.rdptr ) {% o! s* [* H, q
                DEBUGOUT( "exqueue overflow.\n" );2 H4 V; d, x1 ~; |, v# r
        }$ ]2 n9 }% M. l" m& m# c6 m
}1 H* I; a% K2 X7 S+ @
2 k6 E/ Y4 q8 w1 m. d, ?4 g: {
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
* J$ \' g  s3 ]" c, J{% J( N5 v( f8 D
        if( exqueue.wrptr == exqueue.rdptr ) {
. e% }- ^& V4 J7 I/ m9 u                return        FALSE;
8 z5 c) z! A: ^- B7 v+ Z        }8 {+ P! J; }: g! v5 L7 P, \
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {' V4 j0 x$ L  |, e% |
                ret = exqueue.data[exqueue.rdptr];
, d! |2 `' z) t7 q                exqueue.rdptr++;
0 ]8 |+ ~" f4 j9 m8 }) [- j                exqueue.rdptr&=QUEUE_LENGTH-1;
# F& E9 X) z, V, N" N                return        TRUE;
. R8 R) Z" m* _" e        }
3 f$ p. ^* x3 e: R8 v2 h# c        return        FALSE;3 N& ~# E: g7 y, P: i
}: z3 D7 {; ]5 g6 c6 c5 g, l6 F- e

/ l; s! W: X) n; j- ^' K& jvoid        APU::QueueClear()
  I% t4 M' ^7 q% x/ g{
9 \8 E0 g( J/ Z1 e7 F; I        ZEROMEMORY( &queue, sizeof(queue) );
" U6 P. f; I9 X        ZEROMEMORY( &exqueue, sizeof(exqueue) );# c. N, f, k6 b& ?$ v: j. G# x* }
}1 S( T+ Y$ v9 Y+ {
7 z; ]; G- n8 c/ J& _
void        APU::QueueFlush()+ Z: Z: g3 q6 c* f' x+ y: S; M
{+ s3 m$ C8 I7 j1 g' g. M  j
        while( queue.wrptr != queue.rdptr ) {
$ l2 k. z0 ^" i" H! K                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
2 o& }$ c: f% }                queue.rdptr++;
, C, U8 }8 M: H% B) G' P                queue.rdptr&=QUEUE_LENGTH-1;
1 `  a! R- h# a& f, m* }        }& v! g6 p: X# `0 m2 w$ V' r

+ A' `: X' N! W+ v7 F        while( exqueue.wrptr != exqueue.rdptr ) {5 d9 Z7 ]) o1 p
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );0 w7 E" ~; D* g( Z  G0 G. l
                exqueue.rdptr++;5 v. K" l+ T2 L0 j1 P0 r) E
                exqueue.rdptr&=QUEUE_LENGTH-1;& l" J% ^4 ?3 J$ W" {% @
        }
9 F: Q% [, l6 I% N}
3 Q5 d. T7 Q/ i: p" ~# w3 {  {+ m* a9 D
void        APU::SoundSetup()* q4 O) k: Q" i" x" A# U9 t4 S" G
{
; S; E; r3 [: @( b) Y7 e  J: }        FLOAT        fClock = nes->nescfg->CpuClock;
4 u: m# a" _, N( p) m: h: w0 {        INT        nRate = (INT)Config.sound.nRate;
( e, I8 W2 i/ q7 Q$ s        internal.Setup( fClock, nRate );7 s. e5 b# g5 N  i+ l6 s% F
        vrc6.Setup( fClock, nRate );
+ s3 A8 F* C" I9 Q        vrc7.Setup( fClock, nRate );
% O( P+ n3 d- d6 w, c& `        mmc5.Setup( fClock, nRate );1 t* @" H9 D) c  z
        fds.Setup ( fClock, nRate );0 {; W  i/ N% [' b/ u
        n106.Setup( fClock, nRate );5 d/ T$ n" ^/ ^8 v. F& I5 }' k/ ]
        fme7.Setup( fClock, nRate );
5 D2 i$ r8 q$ K7 c  a- c1 C}5 s+ H+ b8 T6 l3 D% W/ q

! F. T$ Q$ P0 e8 |' }void        APU::Reset()
+ J* P0 A7 W, U+ r9 @1 l6 \% Q! Q{
2 w6 t3 q, Q  M- M1 p        ZEROMEMORY( &queue, sizeof(queue) );
  W! J/ x1 }  f  Q, P        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 l5 L% ~1 g+ k! x8 \) n) R

: ?& I7 i" _2 X8 W. A        elapsed_time = 0;# n& O( d+ ~* t' B& ^
+ l. x! ]% j) m
        FLOAT        fClock = nes->nescfg->CpuClock;
6 f" m+ z6 j& l4 [, [        INT        nRate = (INT)Config.sound.nRate;
! V: W* A% P- a; z) x+ G4 Q; W  \- j, J        internal.Reset( fClock, nRate );
! k' |, c, F7 l. [% T7 o' p        vrc6.Reset( fClock, nRate );* }, d) m" r3 D3 L4 Z
        vrc7.Reset( fClock, nRate );
* [; X0 Y$ j- s/ Z, k1 [* T  Q        mmc5.Reset( fClock, nRate );
0 U1 _5 w* L1 b6 @+ f        fds.Reset ( fClock, nRate );
  ]0 t7 N$ X) a& x        n106.Reset( fClock, nRate );
- n: \1 C% g- D8 _" @5 I) j  Z4 O0 U        fme7.Reset( fClock, nRate );$ [9 u9 i1 o+ s5 b5 e

" F% s$ r$ M1 a  `        SoundSetup();& a; K6 K3 t/ Y. c5 v! z
}
) v. Z- z2 r1 h, Z& B& _& ~) a2 ]' O, h$ R
void        APU::SelectExSound( BYTE data )0 ?* A6 v/ M' }4 ]: d* A; F& w
{& g. L# |# ~) r2 `
        exsound_select = data;
# T( o1 c$ h' M+ O/ `}' G# s8 ~8 G- i7 w3 e5 b
2 k. }* f- M9 c# \! z, C
BYTE        APU::Read( WORD addr )
. v9 p/ i! @! v+ F: @- x6 y{0 W& ^" w) K& R/ G& `; [
        return        internal.SyncRead( addr );0 X, O" h6 C% \6 F1 o9 o
}
% I) t; y: E9 I* ~. h2 b; ^& N. v. N2 w
void        APU::Write( WORD addr, BYTE data )* f6 a  i8 B2 i: Z, b
{
* X/ W3 X) V! S/ Z        // $4018偼VirtuaNES屌桳億乕僩
$ C2 \& u4 T. Q, ^  ^! f  o9 I6 t        if( addr >= 0x4000 && addr <= 0x401F ) {: l; {- Q2 a, g- x/ r0 H7 K  ]) G, g
                internal.SyncWrite( addr, data );
/ N0 D( T9 F" Y                SetQueue( nes->cpu->GetTotalCycles(), addr, data );% C  B$ q# R" u$ I7 m0 N) @
        }" t4 p+ x1 \0 F" h
}
& C+ [* a+ C  ~) l2 R% V( H( _% P& D- L2 V; ~2 A  L
BYTE        APU::ExRead( WORD addr )+ B) p( K# Q7 \
{4 Q% C8 O  w; Q1 V. b+ u
BYTE        data = 0;& m$ R$ p) K. h6 U0 e: x
0 ^6 `' {9 S  K6 D$ p
        if( exsound_select & 0x10 ) {: R/ w) O9 q% _- A
                if( addr == 0x4800 ) {
6 S3 o( L8 ^) e. C/ a! V                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
2 D0 q; I1 G* V; p5 e& C                }( G, U7 q- Z3 M8 q5 T6 @
        }
. I' N0 |# V: h3 z( e& g6 M        if( exsound_select & 0x04 ) {
" }# r! M6 M6 P& y                if( addr >= 0x4040 && addr < 0x4100 ) {: Y$ m0 i2 F4 x
                        data = fds.SyncRead( addr );* X$ z1 a* _. r' I
                }4 Z- `6 q9 v0 X1 F! q& i, o
        }
; i" u& o& i0 X" d) J  P) t# W        if( exsound_select & 0x08 ) {1 v, M) {) k' g9 s- V* d
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 E! ^* V. g% {  ^0 G8 I, r2 Q* p
                        data = mmc5.SyncRead( addr );
' U4 Y" i% z. O4 L                }
& W+ {6 {, e" A  Q% I$ o$ z3 Z! i        }
- d3 |8 G! E" w& f' Q- G
2 h# j$ |: w3 s+ e& ?4 ^        return        data;
) q+ q+ c% Y  P6 q+ a5 Z  ^8 w) M  G}' ^$ T6 d/ {5 m& x& r
5 R' z; f- f' L6 V
void        APU::ExWrite( WORD addr, BYTE data )
8 U$ d1 Y2 s7 `; r{6 f9 N( h8 |/ K8 p! k' H7 N) u
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );0 Y, r2 C/ Q* o7 I7 N
9 V* G: A2 O3 h! T" k
        if( exsound_select & 0x04 ) {
! N; w9 c% n; L' |! b                if( addr >= 0x4040 && addr < 0x4100 ) {
; ~$ s' v6 ~% W                        fds.SyncWrite( addr, data );! k9 Z6 A, {- ^
                }0 G# b& Z( A# T8 y1 l1 k. z
        }" [1 o3 N7 ^% x
3 {3 W7 |  G  N  u  G6 L0 i5 `
        if( exsound_select & 0x08 ) {
8 ]) h- m- x! u                if( addr >= 0x5000 && addr <= 0x5015 ) {2 u* t- W. x5 t3 Q8 ]- C
                        mmc5.SyncWrite( addr, data );$ d+ J' T- W3 I. k, ~% ]
                }: ]+ t& L+ k6 T% r  J, h  b- I
        }) A! s4 T) V1 d* O3 S% i  D
}
5 r6 Z! c$ ^% i1 A8 q3 P! ~
0 p4 {! W1 Q# [, ~* G1 Ivoid        APU::Sync()
. v2 i* D. G, {# s- b8 s4 V& G{
3 n( s9 [  f* {/ q; g}3 j4 u! t3 E# G5 T; W* {) M. f

& z+ A8 \; s* }0 ~0 x+ avoid        APU::SyncDPCM( INT cycles )9 ?0 c' k7 e$ ~8 @! z: D
{6 F- M6 {- x8 t0 O) A0 c
        internal.Sync( cycles );
, d- F/ D, n9 J) I% A  W
7 i5 Y+ c) ~; X8 E  y3 ?        if( exsound_select & 0x04 ) {4 w: d( u/ _# l+ J
                fds.Sync( cycles );1 r8 g( X! D3 G0 [$ M
        }! P9 }0 W1 E7 ~
        if( exsound_select & 0x08 ) {
& J! V: N" {4 R; S                mmc5.Sync( cycles );
2 _4 p& n* {$ l0 `0 }! I0 X1 Y7 P) ?        }; c! E. m; g% {% ]; }
}
3 s, ^& l' x0 w1 I' r2 w  z; X5 M  y% B- V, c
void        APU::WriteProcess( WORD addr, BYTE data )9 e( {) v6 J: W5 R# s' y+ R: o
{; W$ e9 J7 z" B$ ]
        // $4018偼VirtuaNES屌桳億乕僩
# g. O- ~7 ]3 c& y: ~        if( addr >= 0x4000 && addr <= 0x401F ) {
/ W  W( S, `6 J( q0 k) Q                internal.Write( addr, data );  R$ }0 o% @% r) D
        }
2 m) k# {! J6 f! d) ~5 N2 J! W' e}" J; o9 R' D/ r- U! p; I
0 \  e1 R3 ?4 C& w2 U
void        APU::WriteExProcess( WORD addr, BYTE data ); b$ j+ M2 I: h
{6 s" O7 ~+ `& R4 \3 B. s  U
        if( exsound_select & 0x01 ) {% ]1 `7 b6 h  Z. G
                vrc6.Write( addr, data );! J0 \9 `' J) p6 r6 J/ H9 k
        }
- A! t0 z2 ^$ o' }9 `5 k  W        if( exsound_select & 0x02 ) {
0 S4 u$ W# b' r* l1 A  [                vrc7.Write( addr, data );! ~  |$ R8 Y# D$ `; n
        }% c5 S* j( v, S+ X$ @3 ~  A
        if( exsound_select & 0x04 ) {
, {0 E7 y" e6 U8 ^' V' M                fds.Write( addr, data );! t( t( W% D+ U) Q% {! f
        }. R0 O+ m3 C5 t
        if( exsound_select & 0x08 ) {
& ]4 u" C- w9 e# W! c6 U% k) T                mmc5.Write( addr, data );
. D+ H8 A6 j7 x+ ?% t- B        }
# P5 O2 Y) }! x, N, ^        if( exsound_select & 0x10 ) {( @6 L* ]" X+ q$ l
                if( addr == 0x0000 ) {( |* i6 {6 m  \
                        BYTE        dummy = n106.Read( addr );
% Z8 J3 h% y( f7 J                } else {+ O6 }6 x3 ~5 M" P; o
                        n106.Write( addr, data );
9 O/ e4 [5 \" e' J( s7 L                }( O/ G& b% s# w; {0 R
        }
2 k3 z' b9 q0 d: ~  Y        if( exsound_select & 0x20 ) {
" R  R! @: Q8 E9 M; X                fme7.Write( addr, data );
' T% s1 `4 `* ^6 ?8 H        }2 c" r! E- H5 w9 d
}
  g' o  c, Z! t7 l0 e* @3 N7 P* b9 M2 v! n# H- o. J- x% q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
) S4 N6 o$ Z; a9 B+ L{$ }. x4 [2 _2 S8 J0 M8 `! v+ l, e
INT        nBits = Config.sound.nBits;
$ o9 N" y3 x/ |9 j9 MDWORD        dwLength = dwSize / (nBits/8);" x3 _! V+ ~( s% v) I
INT        output;
& o' }% Z, R# o4 v- p& WQUEUEDATA q;
) c8 Q1 Z8 [* h2 Y. v. sDWORD        writetime;+ R2 `) o1 f6 n6 V. i

! @( g: a2 ]4 g$ n  R1 A5 V. rLPSHORT        pSoundBuf = m_SoundBuffer;
7 o$ L6 L& w% @6 T% v  c% bINT        nCcount = 0;
3 |9 Y; Z; h$ v- \$ H% M1 Q1 s* q: V- V2 B! A& F
INT        nFilterType = Config.sound.nFilterType;
6 \6 O1 h: F% w3 w. C( U/ o; V! X" K' t, {7 w
        if( !Config.sound.bEnable ) {
1 u: O5 n% `' z5 |5 B& K                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
) b7 C' J$ o+ B/ p$ D* |+ T                return;" ^0 \6 C/ V& U" q( c0 `
        }- y, I9 Y6 k! m( f1 z3 {
4 J+ S& }3 @1 m& P* ?) v9 M
        // Volume setup" k# k/ G8 l6 z" Q+ N' E
        //  0:Master0 L: d& k  B9 c5 l5 F
        //  1:Rectangle 1* w: C  A5 y: h0 V  ]: U
        //  2:Rectangle 2
' B  ~* l- G, @$ ]+ P4 k* S- T( C        //  3:Triangle; @* \2 ^# A$ G! r
        //  4:Noise* E/ T! f3 i* w  l  I1 k
        //  5:DPCM5 @. l. H% P" q
        //  6:VRC6
( O$ Q6 r  L3 W+ D& H/ Y5 U% {        //  7:VRC70 w9 n6 A. j  A  d0 P" q
        //  8:FDS
0 |1 T  m* e0 a4 D        //  9:MMC5- w* K' m8 t6 W. g2 V! v& h
        // 10:N106
( n1 j. b: y4 q& \& n. B1 ^* \9 t        // 11:FME7( j( h4 V( ?) l5 n  v
        INT        vol[24];, Y" K- e: E6 N# \0 R. x
        BOOL*        bMute = m_bMute;$ \  r1 s. V7 l2 `' W* `3 h. e9 S
        SHORT*        nVolume = Config.sound.nVolume;
5 j- g" Q  F6 ^# a! `( x1 X, A2 U  d
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;) g/ l. ~0 p9 C' B
  G8 X% Z: J, Z! e8 t5 ^4 [
        // Internal
# `+ {4 C- V/ p0 w9 D8 o* Q        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, Y% o3 c  n: n: d+ I2 ?! i; P        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;$ k: W* B( G  l  O) k
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;1 [6 i8 a* l: X/ b# k
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;: {( `$ q* T4 g! X$ E
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;  D! {( w8 W8 C6 ~
) m, _7 G+ T  ^$ O
        // VRC61 w! B0 O8 N; c/ ^/ P& V
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;# [0 g: P1 t9 s1 B1 K$ ^
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
; I% T8 E! Q% d; M5 f. c        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# i) P" I/ W2 Z
! |: `, s  v9 f" z7 K! ]; T5 `4 k( w: V        // VRC7
/ G8 |* h9 `5 ^, _3 j: W        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;7 K2 \+ f. J0 V' K6 h, I
- Y5 H# ]/ {0 |, _% k  p
        // FDS2 R! _& i- M( M' i' b$ ?' e  b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;. X4 {( ~; a0 p/ n

" R6 l. Y/ I+ j; _        // MMC5, W7 x1 D3 b9 Y! T3 y0 x2 H
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 S% H& T" l$ L! s( h' L$ h" a
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! @7 J1 z3 w4 V
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 L+ J3 }+ m$ ?' {# D

  p2 H3 T+ ]% w  T9 a3 o+ J. r( T+ ^* W        // N1069 t" V& `) e- w% g
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: e- b' w6 S6 B* a8 ~& w" [        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 L5 ?, J+ {- [9 }  }- ^# J
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" h! e6 c0 D% f4 g        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- t; [6 N9 ], [        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 D9 _$ y7 ~& ?6 N" i
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- L5 _5 `! J7 Q6 w6 V4 Q: a        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( i2 H1 Y% H$ Y- w        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 d( d+ M- c" d! z
% A9 d( Q. J. t) v5 M        // FME7. p, L) g4 }9 G
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% ]" l% {% S' ]$ |1 d! e7 v/ v7 K        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  @; O( {% s/ C2 z: |( @( B        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 X& l+ l# s) z* n" g( R
2 ^$ h7 \% `1 y* G# E) o, I% A
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
1 A" l' D5 u4 Z# r5 Y        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
. }2 U' `1 @. V% u# L
; t% |+ ?  {; e" e; g2 f        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟0 J5 S- x% _  }: h/ e
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {6 @8 l* E% a6 I$ r! U  G" d* D. [0 T
                QueueFlush();
: Q, v, W: M" {1 E1 n: D  ~        }
9 l' W" e2 t% a! k; Z' l+ u, m, C
4 H7 }8 D  V' b  l/ I; r        while( dwLength-- ) {; J: t, d( r9 [
                writetime = (DWORD)elapsed_time;
/ `8 ~) J2 q. E5 U2 t' n0 _. ~. K& E$ a( n% ~( ~" a4 |
                while( GetQueue( writetime, q ) ) {
# o8 m" t7 w) M                        WriteProcess( q.addr, q.data );
9 ?9 b$ h) n. A& e                }
* p6 l) s  X- }; t- W# L8 p
( N, l1 j$ r' D. n3 c/ D                while( GetExQueue( writetime, q ) ) {1 f7 k( K/ E, K0 p5 r. a8 i# X
                        WriteExProcess( q.addr, q.data );
3 G) F2 P1 s0 _5 b2 d& e! x$ D                }
; o$ F% Y% M( C
5 `. N2 ?! h* M2 K) }6 I8 r( v                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
) r( e9 c+ t9 z  @0 P- c/ d                output = 0;
8 n; F  i: n- E6 W2 D4 ?                output += internal.Process( 0 )*vol[0];+ {- G" B7 K5 B* X) X9 O
                output += internal.Process( 1 )*vol[1];4 E" n( z: U3 {' N- j
                output += internal.Process( 2 )*vol[2];
2 H6 H+ I# H3 W; z- J+ F; U                output += internal.Process( 3 )*vol[3];
7 F' I( A+ G& @2 n% S                output += internal.Process( 4 )*vol[4];
6 q# N, ^" p! a5 ^
8 L. w. q1 Z$ c5 K                if( exsound_select & 0x01 ) {
7 T& Y2 ?7 N7 Z! A- b% S                        output += vrc6.Process( 0 )*vol[5];
+ `* y+ E5 p! h$ @. u0 l# P( a  b                        output += vrc6.Process( 1 )*vol[6];
& U2 l" W# C5 ?6 l/ ^0 `4 x9 o                        output += vrc6.Process( 2 )*vol[7];& Y/ r; v# N! _& u, m
                }8 }% n; J4 `  J1 g! X! I8 q
                if( exsound_select & 0x02 ) {
) _/ ]) R" W) y2 ~; M                        output += vrc7.Process( 0 )*vol[8];) o' ], ^5 L3 U# `) D
                }
. m. i  B8 A* Y5 x                if( exsound_select & 0x04 ) {
0 W8 i/ k, r& x7 {+ I! }+ q+ G                        output += fds.Process( 0 )*vol[9];
* q5 @7 Q$ E& y+ m9 U- h( k: x                }. K( b2 ~6 q, [" A& a
                if( exsound_select & 0x08 ) {' g: g( Q0 U( b$ _% {4 U0 k
                        output += mmc5.Process( 0 )*vol[10];6 j* \3 E& v2 v9 ]3 y
                        output += mmc5.Process( 1 )*vol[11];: c( O& ?0 l, j) m+ U( v) S6 m
                        output += mmc5.Process( 2 )*vol[12];
! C1 N) ]- s. i( I6 C+ @7 R                }
9 Z, G& o/ w8 q8 v                if( exsound_select & 0x10 ) {
7 c1 q; ]# Q! I1 I% X4 P' O  o                        output += n106.Process( 0 )*vol[13];( @. T0 K8 D* G6 n' N+ J% |( Q) Q
                        output += n106.Process( 1 )*vol[14];
' g; d% ~/ ^  z- W# U$ K                        output += n106.Process( 2 )*vol[15];
1 e3 k5 g: L" r. u                        output += n106.Process( 3 )*vol[16];5 H: d2 T" L6 [8 Q
                        output += n106.Process( 4 )*vol[17];; W! \+ p  b/ u! D% @- R
                        output += n106.Process( 5 )*vol[18];
8 {. Q5 q7 d2 J( _( Q- X, i                        output += n106.Process( 6 )*vol[19];. \# H0 p; p! M$ Y7 x$ x$ C& n* a0 Y
                        output += n106.Process( 7 )*vol[20];/ E  [8 ~. `) B
                }  H& w! ~" l% k
                if( exsound_select & 0x20 ) {$ j! K8 D: M# {9 [, j3 u
                        fme7.Process( 3 );        // Envelope & Noise
/ q% E* X; \9 A7 N2 v- ?                        output += fme7.Process( 0 )*vol[21];) c$ z, \; Q5 v8 \- f+ T
                        output += fme7.Process( 1 )*vol[22];9 ^4 K: V" H3 y8 A" v: a
                        output += fme7.Process( 2 )*vol[23];5 m  V6 v+ H: p6 _+ M% s+ ]
                }* S2 [; A/ g5 Z4 [" I6 m

' o  f  r; p( v1 ~5 g) q                output >>= 8;
- Q- N' S6 h7 Z& u$ j/ l  z6 M
5 l3 c3 ~1 }2 J  c% K* P                if( nFilterType == 1 ) {
  X! E; Y! d* Y- n1 D' y                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)+ o. d9 L7 v. o
                        output = (lowpass_filter[0]+output)/2;
+ k5 Z' ]$ f  [& V9 p  C                        lowpass_filter[0] = output;& d) ^- O% K& _$ ?1 i$ k* x
                } else if( nFilterType == 2 ) {
. {$ p. d$ ~2 C1 Z, g                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)- `; u7 z% Z( T1 f
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;- C2 {- \( u3 V5 }; l
                        lowpass_filter[1] = lowpass_filter[0];
2 I% X4 |& U1 E+ Q0 U                        lowpass_filter[0] = output;
) V' P% n/ S& _- a% ^% t2 e                } else if( nFilterType == 3 ) {2 M3 i( E) T8 P% g9 |& M0 ?
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
; V8 @! a9 c: G                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;( w7 O7 p6 k2 n8 i8 G: t
                        lowpass_filter[2] = lowpass_filter[1];) v9 _$ E' H6 w: L$ o3 s$ n% `. M0 m
                        lowpass_filter[1] = lowpass_filter[0];0 e/ ^0 q$ H$ L3 g; }8 \6 M' o
                        lowpass_filter[0] = output;( c$ r) k& m+ j
                } else if( nFilterType == 4 ) {
. W+ i6 ^3 K5 |( w                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
& o  w( c- S+ u1 h+ f+ I% ]/ o) M                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
9 i; ?2 Z# Y7 T2 @4 B0 \                        lowpass_filter[1] = lowpass_filter[0];/ K2 n# _( Z5 o/ l2 v, v7 I
                        lowpass_filter[0] = output;! Y# o0 ]: p: _5 V/ k& r! \/ K! i8 K9 {
                }
1 B3 Z4 J$ f" l$ F+ L- P; u$ |( B% T! y
#if        0
, h( u! w! g& J' d0 n8 Y                // DC惉暘偺僇僢僩
1 M- X$ T: E+ x; f: n6 e                {
2 f: h* Y9 b1 r# r5 y8 X! C3 ~                static double ave = 0.0, max=0.0, min=0.0;2 ]  h/ O- h/ z4 {! `' c; T4 F
                double delta;/ g4 `; Y. L( K% ^: T
                delta = (max-min)/32768.0;- X/ y. {* I- o+ v
                max -= delta;4 p2 A& _" D5 b$ n- r! X6 d- }" q
                min += delta;
- x% S3 I' n6 |; E' d' R/ a5 |  i, n2 {! z3 r                if( output > max ) max = output;8 E4 c- q( m: G* ?
                if( output < min ) min = output;
8 ?  }( f8 i& a; }                ave -= ave/1024.0;
* Y* u! @% T9 c: t( y                ave += (max+min)/2048.0;
! x6 J6 H! G% @' u' s3 X: P                output -= (INT)ave;% I4 c7 R9 I2 ^
                }6 y; `( f( K1 H" n+ a
#endif
. b0 T0 g: C4 ]#if        1. }% d! s; P  |6 M+ I
                // DC惉暘偺僇僢僩(HPF TEST)
  z) d8 e- m( I2 x) x                {( c! _( i# K: x# b0 p! q5 {/ C" d, @# R) A
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);4 P3 D5 X2 U* I+ ~9 Y
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
% v& S6 q0 `4 c3 |. q) A9 U3 x/ q                double        cutoff = cutofftemp/(double)Config.sound.nRate;& Z0 E. V! @2 _, P7 A" X* S. T
                static        double        tmp = 0.0;0 O4 K; K* P/ n
                double        in, out;
3 W; l& f9 |0 _9 K- f7 v+ x( A; z+ C7 K" A! ^3 E1 {) @( j7 X- |; }' a0 P1 n0 ?# H
                in = (double)output;
8 `! {  i* X) p& v( ?5 f1 H                out = (in - tmp);7 Z5 T  b4 |# O% n/ c2 H6 |
                tmp = tmp + cutoff * out;, ]- a. S8 D1 w; ?3 b
6 a2 _' g/ U2 F& K+ d! y
                output = (INT)out;$ {+ g" M! x0 E6 ~
                }
* V' _6 m# ?& I3 v5 B! Z#endif
: p2 Q# o; z2 o' z#if        0# W5 [1 ?* L/ t) ^* n
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)$ u7 [8 D: v% k! X, j3 H) {* \6 S/ o. l
                {
: ], X: u- G: @3 O                INT        diff = abs(output-last_data);
  i! U: r1 Y4 x/ L4 I/ Y' C                if( diff > 0x4000 ) {1 _7 J  h  R9 M
                        output /= 4;
9 J' c& T8 m! o" n% ^- w                } else
+ @1 Q* A! s' w+ D0 h# F- ~% y9 R' L  I                if( diff > 0x3000 ) {
: P8 ]! p; T2 T- E                        output /= 3;5 @8 Y: Z( w5 W+ ?
                } else, Z4 H% ^% c/ N& b6 l5 X4 D9 z
                if( diff > 0x2000 ) {5 s1 D& I* r" ~( |/ z. N; t
                        output /= 2;
$ L2 `9 B# C+ X' |7 M; G                }
  h* a. [7 d. S3 {$ M                last_data = output;$ {1 R' ~: i3 |2 o  M
                }
; y+ Y. m8 G# _4 ]: {* N#endif$ [" n1 _2 Q% n8 I0 D$ p! L
                // Limit
$ O- g7 V& z! M, u' F                if( output > 0x7FFF ) {
) E. ^+ e4 m/ ]' ~                        output = 0x7FFF;+ l% j+ }8 H) P2 N9 u; \% s
                } else if( output < -0x8000 ) {
6 R1 X8 a4 L8 A9 z$ y                        output = -0x8000;' X5 w; |* H, g4 x7 l4 Q, A$ R  c
                }. ?0 i0 a( m9 {3 y, S0 j

$ b* u! a  C3 E                if( nBits != 8 ) {
& E( q4 I  E2 x+ r) A* @                        *(SHORT*)lpBuffer = (SHORT)output;
& J& M$ K- j9 a$ v6 J                        lpBuffer += sizeof(SHORT);
; _: f# H! g( Z6 }. I0 k8 h! G                } else {  S% z! E) S9 ~5 }- X$ I
                        *lpBuffer++ = (output>>8)^0x80;: H9 K7 o0 C3 n* ]3 ~
                }# k4 I. h7 A4 X) m2 N# _9 d

* a2 _* E9 s6 b) t$ ^                if( nCcount < 0x0100 )
9 M* l; Q6 N: F; ]4 k3 I                        pSoundBuf[nCcount++] = (SHORT)output;
- }' ?6 Z# E: q
6 E1 g5 X+ m+ K5 B9 ~0 W* F( ]//                elapsedtime += cycle_rate;& ^. Q4 k% n& |: b
                elapsed_time += cycle_rate;8 A6 v5 }/ m0 ]6 s+ H5 `. t' y
        }( x  w$ `0 S+ |: G. C  r  J+ x
1 e' i% `; p' A3 P# S% |
#if        1: [- M; \! z% c5 Z+ |3 ]
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {1 m% U* Y4 ]+ B. ]: Z; e1 Q, R$ n
                elapsed_time = nes->cpu->GetTotalCycles();
8 F; F% `+ x8 w' q9 D6 y% {        }6 S3 O4 q2 I4 Q( Y* t9 ?) g- r7 v
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 E; L& G2 w. `* F( E' a" U9 M+ |  A4 d                elapsed_time = nes->cpu->GetTotalCycles();
( h  l" @1 o) c* z/ V) q" x) U        }7 m6 [3 U+ [; u6 c+ _
#else
% B- I5 O2 u" _# M( M1 ?( k        elapsed_time = nes->cpu->GetTotalCycles();
& `- k8 G  j+ k: n#endif
. H% I7 f4 B; l3 Q5 H}) i/ g6 Y  @( v, n' H

9 k! e5 V8 {0 L5 d: ^8 l7 n0 w2 {// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)6 N& [6 i' O! L9 g' z! t! ?, k
INT        APU::GetChannelFrequency( INT no )
6 s5 O- j# U) ~8 ]{5 J8 w  |9 R1 C' _: u9 h: T
        if( !m_bMute[0] )
6 k/ U( s5 h" L: a: y9 D                return        0;
7 w$ y1 G& j5 B* d2 t
/ x& h% y& B3 @& I% h* \        // Internal
9 v3 q$ e" X$ |: m. o8 k        if( no < 5 ) {
# _0 ^# H; H- z2 b' Z                return        m_bMute[no+1]?internal.GetFreq( no ):0;* k% ]9 R7 ^; B/ a* p3 v
        }0 a; W# l4 j8 \0 r5 J( Q3 i- f0 {
        // VRC6
% E- b5 z+ D2 b1 q$ A! c        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {2 r6 v# r/ i& G  K  J
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
- R3 U/ E5 {9 C8 G5 h8 h        }
, o: t1 W2 B# g8 \4 Y/ C        // FDS
) B- t2 P/ n7 F$ k# l        if( (exsound_select & 0x04) && no == 0x300 ) {; _: i4 `1 r( s  C
                return        m_bMute[6]?fds.GetFreq( 0 ):0;. n5 h1 v7 c2 q3 F' U' l3 D  D
        }
0 b) U7 I3 {# s. v7 c; `: ~        // MMC5
8 h1 i5 L8 b+ T2 f' B; X' B0 ^        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
& o, J8 s+ Q: v                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
9 ^& B$ z( d! T# j4 J% h& M: w        }5 ^: F0 H+ S; M$ y$ E
        // N106) Z, O8 X) |5 @, y' ?% W9 M7 g
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
' f! L  w: @* g; O                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; b: B. ~- W1 t2 V3 T' @. ~! g
        }2 [) E% A6 a$ k  t+ v! n6 z# |
        // FME7
9 `# v, q/ c" o7 b6 W' D: R        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {# l4 E0 D: o; V. L( G$ p
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
( P+ O7 G2 ]. n: v        }- h' ?0 Y7 t6 l  y7 v  }/ |
        // VRC7
, s6 U+ j4 z) N; B        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
/ M2 j+ Z7 B, `' \6 t' p) ^3 B: u                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
$ W5 p! P+ N' }        }
* f9 m* F! c2 [8 R7 O- J# g! {        return        0;
; A7 A0 H/ y" ?5 }}
* ?: t- m5 k# w+ t. o
5 F; r) n8 S8 f+ V// State Save/Load' \3 C8 K9 F" U* L1 W7 {3 |+ T
void        APU::SaveState( LPBYTE p ). q3 Q  {+ k8 `6 i! C
{) P$ E1 y! S- t; ^" s
#ifdef        _DEBUG
) }& ^2 E1 H" j+ f8 w% GLPBYTE        pold = p;* |- f6 K0 v. H
#endif
0 ]2 k$ K; [  n/ w1 S0 Q( k. s7 t$ g* Q+ G2 @
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞! @1 ], {6 v* ^, \
        QueueFlush();
; \) `1 f6 n4 u9 Y
, J  B* j" c/ N0 D, q        internal.SaveState( p );
/ N9 b) i- J6 q, X. y! W9 x( j        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; ], M; h# ?, y4 R  ?6 V

6 t5 t" T. u, d& i1 D        // VRC6
8 W0 r' Q5 H2 w3 q        if( exsound_select & 0x01 ) {
$ X2 `' h4 W7 w$ f7 ^                vrc6.SaveState( p );' R5 w' f( s( o  N
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
* J: B, m% _$ O; J; p7 Z% U5 H        }; d: Z0 V! g! m) d. u: }0 J3 I
        // VRC7 (not support)
# x$ _' B2 p$ m4 ?2 d) R' x( A3 a* C6 u        if( exsound_select & 0x02 ) {
: S! N4 n, A. o3 g                vrc7.SaveState( p );
& C# t2 I$ R. u; {                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 D3 e. B, `$ [6 v        }& O" t  n  v6 V4 P$ J- ~% a& i
        // FDS
; t# D: Z2 h* }# M9 x0 f8 d        if( exsound_select & 0x04 ) {
/ `+ a  Q8 ~4 q! [                fds.SaveState( p );
  |8 `$ P5 r& z1 u# O5 t                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding, i5 u+ j6 v$ v: G
        }
* M/ D* \& h) `) f3 {# b. E        // MMC5# Q+ ^6 m1 M& w# ~1 c; w
        if( exsound_select & 0x08 ) {
0 O5 t7 m( M; B/ u0 m                mmc5.SaveState( p );
" T' \" p, @0 \9 S1 F. a0 M, s                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
: o( p! W+ ~! |9 `) [# A6 T        }, |3 H) O" |$ S: \3 J& T: ~
        // N106
. @4 N; m0 a- W        if( exsound_select & 0x10 ) {& l) z! U: z; j/ c
                n106.SaveState( p );
2 {' \4 `7 A! @! u" u) T8 K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
) m6 n. E5 x. I3 P        }1 p8 q/ I, j/ i3 z# Q; @) c& v5 K4 v
        // FME7$ |6 n2 I5 g& E/ {; J
        if( exsound_select & 0x20 ) {4 y2 K' Z7 Y3 j* D
                fme7.SaveState( p );
! q: z. V! |3 [( U4 p/ N; w/ S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding# [  }+ T* u( Z% W/ U+ d
        }7 x" P9 [+ N. ?! d' V. Z
. o' ]" b4 O8 f, X$ o
#ifdef        _DEBUG; A. l. n" u' R7 n6 K
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
1 q) b# M, g9 ~8 z$ I% c' A2 k#endif1 A' u& F( a: e0 Y1 T( f' J
}8 t! C9 d$ P7 e
( g0 z' j0 R' X. X) |/ @& E
void        APU::LoadState( LPBYTE p )
1 z6 K; f# c( d1 A/ C{9 `2 ?- Z, Z4 r/ P0 {6 J4 X% n
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡2 |( f( @$ K" S/ {2 W
        QueueClear();8 J2 ?8 b$ |) b! z1 W) j* U$ e% k
, M3 F7 b  Q4 m; h/ G; Q3 H" @3 H
        internal.LoadState( p );
$ ^" d5 R( H2 f        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
" Z) F+ u3 W, B0 |# B
6 j& X9 K! a0 v/ W4 y# S; h        // VRC6
4 L2 D1 I" V$ B" T- s        if( exsound_select & 0x01 ) {; b5 ?  i0 u" g- d. r
                vrc6.LoadState( p );$ g) U1 t1 r/ A4 ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* g; D5 i4 V8 U" j5 Z) p
        }
, ^8 u, w1 H- U6 j: C        // VRC7 (not support)
8 c/ c  h- Y2 e- C        if( exsound_select & 0x02 ) {/ _7 n3 e/ P3 c! l  P( C0 f8 q
                vrc7.LoadState( p );
3 G$ o8 d( G$ W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 ~8 w0 I4 k  `' n3 o
        }% n& K2 E% O) V  L
        // FDS  [' |4 H& Z# L$ d3 c
        if( exsound_select & 0x04 ) {
' J( t8 Y) Y& ]6 L- v! ?                fds.LoadState( p );
9 ~# m( F! _5 V0 \9 \8 L                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding- g+ P8 B- S, ?# g; J. T
        }
) h) G* X9 i, l5 N        // MMC5
3 l- y0 g' G9 D# f8 e% b: P. w        if( exsound_select & 0x08 ) {0 D& j: K: p. T" x8 v  N# k
                mmc5.LoadState( p );
8 m; U% ?( ?3 f8 ]                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
1 H, X* j8 _/ x/ N! B# g        }; J; W7 z; R! e, F0 H  R+ {3 f! F& l9 {% m
        // N106
8 [& @2 a6 M: I1 ?; c        if( exsound_select & 0x10 ) {- f+ W: y: W) A* ]( I  N  n# @
                n106.LoadState( p );7 E7 ~- E2 x! M6 @+ e5 e( P
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding3 R3 S; E# b( U  A! a- }
        }* B. B8 ]; c1 \3 c4 |) }
        // FME7) U0 w2 i2 S" Q, b- e
        if( exsound_select & 0x20 ) {
& |. {) g# W, h* A: c* F# P: n                fme7.LoadState( p );
/ o/ w- _% B' b1 i                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding: ?3 {& O7 ?. ^
        }
! _4 }4 q/ a. _. z- c}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 8 d' v9 g4 k8 O3 f% h; Y
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。. I# q6 ^* R( ?) w
感激不尽~~
) B9 O+ V; i' N
恩 我對模擬器不是很有研究,
, W# Z7 \8 s- b( [9 N2 ^雖然要了解源碼內容,可能不是很困難,
3 \+ F0 l& E; M' {不過還是要花時間,個人目前蠻忙碌的。
; q; }$ T5 b2 p
2 I7 {! F5 ]: `) J給你一個朋友的MSN,你可以跟他討論看看,. f0 N6 @$ \5 B% a( ~
他本身是程式設計師,也對FC模擬器很有興趣。
& b8 O- e  N8 ^! n) l5 D* _* v1 B2 ]' f* M' \: w3 E1 U6 a; s. M
MSN我就PM到你的信箱了。
: \, c* G* [# z3 B0 M' v5 V8 n; H3 L5 Z! E7 O3 O
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
9 a0 b3 J; t: E4 @8 u# S4 ~% U8 W呵…… 谢过团长大人~~

( P5 V4 ?0 y2 D+ J! J7 y, a4 ]- o0 f! n4 }
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
( L  y& ^7 z6 T! n3 q团长的朋友都是神,那团长就是神的boss。

4 R% k- ~7 Q6 o7 ~! d. k7 Z哈 不敢當,我只是個平凡人,
0 @- y; e2 T! \* W% B要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
5 _0 K' k' L& K8 r% x0 ~) xZYH
9 k3 a  J; z  E+ C2 [, yQQ:4147343064 \& e5 [( X) o/ t! Q
Mail:zyh-01@126.com
" J4 o# F$ z1 g4 v  U0 k
1 _7 x5 X2 K% f+ l: {1 ~他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 9 e4 R8 L$ a! X* h" w. q
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ ]  ^0 O& E7 y
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-27 13:11 , Processed in 1.075196 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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