EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
. [$ L3 J5 {- @# `. O楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~( V( Q3 A: b- `' d* O
这里有相应的模拟器源码,就当送给大侠了~~
5 e5 ]3 i% Z; R( t0 y* l% ^3 Khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
) s, t9 N3 [0 K. E' E# [$ L9 o4 g能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
: `- e6 K) \" @5 N0 z* o楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
/ U& X* [/ m, }3 k# r! H这里有相应的模拟器源码,就当送给大侠 ...

1 ^  x% x$ I$ A  Q0 p& j' Z聲音部分(Audoi Process Unit = APU):* L: g  h- I( t
.\NES\APU.cpp
; ?+ {7 m: b; b* V9 Y" k% o.\NES\APU.h
6 ~( @/ R$ b0 @/ H$ }' k* e
& U. d6 v2 ~) M7 Z6 \
/ O; W7 N3 Y6 C( v. N影像處理部份(Picture Processing Unit = PPU):
* w& ^, E2 ^* S* p.\NES\PPU.cpp+ x6 n" C" q+ f; ?( N9 g* H
.\NES\PPU.h0 K: e! n7 @6 F# Q
4 ]: G" q! V& }2 R! L# M( q
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:; V- m. x/ f+ y( c0 J' h3 x/ y
(由于很多专用术语和算法机理都不明白,所以看不大懂……)- ]- [9 N  `9 A& M8 u, a( d
//////////////////////////////////////////////////////////////////////////
9 O5 q  H/ Z. S! T7 o4 W1 o//                                                                      //
- ?9 X1 \+ i7 q+ {- f5 A+ T& r' U0 f# ]//      NES APU core                                                    //- u& U0 E  a* Z( d4 t- K
//                                                           Norix      //
1 {( B; a4 e$ N% e//                                               written     2002/06/27 //
7 x& S, U# o/ p//                                               last modify ----/--/-- //
# e/ z$ e. A. [! b//////////////////////////////////////////////////////////////////////////
$ L* o! b% a7 M. I#include "DebugOut.h"
7 e! J- v7 q$ u) U% |#include "App.h": A: X# _! t. m
#include "Config.h", |4 E; ^5 q- k/ l$ u

: b0 |# Y# f& F0 J2 q( X3 F% i8 [! C#include "nes.h"
, O. M2 E  h3 y& n; Y+ L#include "mmu.h"! w0 a  c1 I$ J6 r/ Y
#include "cpu.h"
6 {+ Y  L$ \8 t! V4 [" o#include "ppu.h"& c. G' v' y* F1 P& f
#include "rom.h"
7 G/ Y! a' s0 p1 |#include "apu.h"
' O4 }6 n, y- d4 O) `$ |/ i$ ?/ A* b; h9 \5 ]7 A9 q; ?
// Volume adjust
* n% ^: t* m1 r1 n3 y// Internal sounds
, i, l  g( c* v& g/ R; n/ i#define        RECTANGLE_VOL        (0x0F0)
8 \# ^" D6 h+ {; `  J7 i/ ]#define        TRIANGLE_VOL        (0x130); S0 F- \% V+ q, ?' d' T
#define        NOISE_VOL        (0x0C0)1 C5 z; i' ~( G# q
#define        DPCM_VOL        (0x0F0)9 C6 w. ], o7 b, v% W
// Extra sounds
& C, l% C3 c+ o#define        VRC6_VOL        (0x0F0)$ j" T5 D3 u% M
#define        VRC7_VOL        (0x130)! l/ e( ^; x; L7 n2 w! ~
#define        FDS_VOL                (0x0F0)1 M4 X0 ~, i6 g" J2 t5 D, N
#define        MMC5_VOL        (0x0F0)
' L0 u, ^: s; Z  ?#define        N106_VOL        (0x088); z4 S; g2 I5 l4 I& }
#define        FME7_VOL        (0x130); P2 o0 ]* E; ?. A( j/ r* O
# ~, T7 ]& h' j: S( }1 o
APU::APU( NES* parent )
& ]: z# Z# ~" [! Y{
$ R3 r# d* q; D' K7 l1 k* @0 i: u        exsound_select = 0;
4 [( V! E' ~1 S7 D+ b, i2 }$ Y! m8 e2 B. i; @6 s% g
        nes = parent;) _; A3 p' U# q9 a- G: w5 L6 h
        internal.SetParent( parent );  O5 V* J6 F7 n7 B6 X+ b( V# N
6 D( d% b4 a( \4 K
        last_data = last_diff = 0;
( S3 P& H& ?8 L8 J+ g
+ E/ W3 r% x6 ^/ e1 |        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
) e) D, \/ L' ]9 f! Q4 o0 C" o
6 P: @' A; @" I9 A/ Y: W4 B7 U        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 I3 ]8 w, {! J" O1 o3 K8 ]4 q* G
        ZEROMEMORY( &queue, sizeof(queue) );
' A% l* B0 H$ q        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ V# A# p7 P. _  S
+ x  _& I4 `6 {" v9 n        for( INT i = 0; i < 16; i++ ) {
/ j3 ]; C/ i+ Y) S9 h- D" S; b3 B7 }                m_bMute = TRUE;
3 @" b3 e: E) y        }# F4 z5 C, M7 s3 r. n  s
}
3 ]& c% d. H: p) _7 t7 t# ]; }  B% W5 C# F
APU::~APU()7 @0 i, W9 W  f9 Q' Z# A, i, |
{+ u9 x: k6 ~+ y7 g
}
) ^7 ]5 X3 C/ ~( s  a6 ~7 o8 J" E, z3 Q4 u  H& A
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
8 u2 n3 K$ k1 N6 B& M# O& H2 K) A{; E2 h4 H* O" g* x; h$ X
        queue.data[queue.wrptr].time = writetime;
, t) `' G0 f: k( G# T+ t' M        queue.data[queue.wrptr].addr = addr;
, X7 O1 r/ l" T$ [' S        queue.data[queue.wrptr].data = data;
( N3 x7 y, n) B% u# E$ k+ l$ B: J        queue.wrptr++;
) S8 |' s3 V# U2 }        queue.wrptr&=QUEUE_LENGTH-1;
$ s. A( l  i8 T# u  M+ s9 Y4 Y        if( queue.wrptr == queue.rdptr ) {
; u" j0 v, {1 r, a  O8 E                DEBUGOUT( "queue overflow.\n" );! b9 [5 V* e# M. h% I0 G9 c
        }" [1 \9 a. y9 v4 c4 @# K4 {
}1 c$ I$ i# J6 y5 B- p$ @6 j# `" m

; L* e, X* @. P, Q/ A4 OBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
- m, I. L+ D# T- v: A' p$ s{
9 l' d- p. u) }; ~* d# H  C8 F        if( queue.wrptr == queue.rdptr ) {. ]) T0 b6 E" B
                return        FALSE;
1 y' |4 {/ t! u0 T1 [5 o+ q3 x        }
) i( D9 M# H/ O  k0 o        if( queue.data[queue.rdptr].time <= writetime ) {
. y. L5 q+ P7 F                ret = queue.data[queue.rdptr];
3 W5 {5 y- R9 G                queue.rdptr++;
/ I7 P  d8 U" h. \$ t5 I) P: e                queue.rdptr&=QUEUE_LENGTH-1;
( A' X6 M4 C. |8 U- ?                return        TRUE;6 c- M! q1 K) b/ c2 o# |! r0 E8 U
        }9 m! y1 \( I, z! x4 Z7 [5 Q8 K. e
        return        FALSE;) B- Y$ F& I! U" F2 _$ u
}
0 ?) f/ X* V) F# F
  Q! j! u8 M. ^, m- g+ k  evoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )' r. n; c) d! O6 h+ `
{
- i# Y+ I  j" U. v& J. ]        exqueue.data[exqueue.wrptr].time = writetime;6 O& T6 Y" ~# G0 N
        exqueue.data[exqueue.wrptr].addr = addr;+ U0 T, Y& F* a. z8 G) d4 u
        exqueue.data[exqueue.wrptr].data = data;
7 Z0 O0 c+ F5 a1 E! r" b$ c        exqueue.wrptr++;" ]  {; H' ?+ f& |
        exqueue.wrptr&=QUEUE_LENGTH-1;& A1 |1 q4 J6 P: A8 f0 b# D
        if( exqueue.wrptr == exqueue.rdptr ) {
. F1 w/ x' V( q0 z                DEBUGOUT( "exqueue overflow.\n" );) Y* F' x- K5 J3 S* [; c- G
        }
7 j9 |( s2 `2 b( _& u8 R! u! q}
/ B. C. a) [/ L4 O
! E3 `: y( |1 Z1 h1 p2 N8 p, I  [% tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
- s; }  x! n. M0 L# w) F$ k8 h{( G4 C1 G$ u. Z; H
        if( exqueue.wrptr == exqueue.rdptr ) {9 I* n. ^" V* x3 p  m8 s
                return        FALSE;3 ^& }3 N+ Z# L
        }
- a7 U& d. q* ^+ I( R        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- A# z# _8 p) ]% _1 c  H  \
                ret = exqueue.data[exqueue.rdptr];
" A+ S: j9 J+ Q8 ~' B/ P% u9 o                exqueue.rdptr++;' _: v- S$ C( a% p
                exqueue.rdptr&=QUEUE_LENGTH-1;
3 G- V1 M; t) A9 _0 Y0 h                return        TRUE;
3 R4 S6 ~# f1 a& k0 a/ i  Z6 _        }
1 G; \1 \# \# w8 k" ^; X        return        FALSE;
. D6 _) `% i+ e5 H) }7 P  R! X}- W  W  A& M- I) |1 u
7 E" N: {( N1 v/ x8 J
void        APU::QueueClear()
2 M& J5 }+ q$ j3 I{
. r9 T$ f9 Q7 u        ZEROMEMORY( &queue, sizeof(queue) );, [5 V! c& f/ a* J5 z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' J/ a$ O: f& b, t5 Q% @}# c7 Y# O; V4 f* K9 l7 M% l( _" ^( e
% J5 l) O5 \6 G* ]6 u$ Y8 L
void        APU::QueueFlush()2 p7 ~; p; U, v% v6 I( d
{
& C, v5 O3 i) Q9 ]- f/ O        while( queue.wrptr != queue.rdptr ) {
' q7 @- n& Z9 b0 K1 A                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );1 E% C0 \3 o# r, D# {$ ^
                queue.rdptr++;
  P* h4 s$ @4 Y6 ?$ G5 L                queue.rdptr&=QUEUE_LENGTH-1;! i6 D4 L) ^7 }) j3 f/ u8 A$ v) t
        }# P  ^0 t4 W9 b0 ^+ s

! s  S0 w5 o: b% n( ~        while( exqueue.wrptr != exqueue.rdptr ) {+ Z& J: R1 U( _. t! V
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 ~  |3 Q5 ]5 o- j% {
                exqueue.rdptr++;* {" |3 s3 b) _. ^
                exqueue.rdptr&=QUEUE_LENGTH-1;0 @& R1 c( L9 t3 N" Q
        }
: p1 K3 Y" E  f1 R2 d, @5 ?3 t}: D' D5 k, P' t8 T( I4 I
0 h9 t% D$ B% F/ P+ f& O, ?
void        APU::SoundSetup()
: k1 M2 Q7 N5 \6 v{
+ l6 s9 h7 w+ ]% h0 [7 |, b) j        FLOAT        fClock = nes->nescfg->CpuClock;! m( J( E" E1 h1 v/ K
        INT        nRate = (INT)Config.sound.nRate;4 d( _- ^+ \9 `
        internal.Setup( fClock, nRate );
; C$ \1 h' K1 u" x; o1 ^        vrc6.Setup( fClock, nRate );1 A9 b1 W" n  s
        vrc7.Setup( fClock, nRate );
. a! {0 G9 c; g! l+ @! Q/ V        mmc5.Setup( fClock, nRate );
9 Y. J. l  k  l0 q/ H. j: y6 v& c        fds.Setup ( fClock, nRate );
% y9 {/ c  X* Y5 k        n106.Setup( fClock, nRate );
' _/ E3 w5 B! l! ~# x        fme7.Setup( fClock, nRate );, K3 v2 T+ M( ^/ {
}5 c& ^* r1 r' ?. [& ]) @( N. v& L3 D

2 w& L9 F1 m4 v# Zvoid        APU::Reset()$ h; p0 Z# t9 w: q* ~
{% ]( I  b4 K' O# o  N
        ZEROMEMORY( &queue, sizeof(queue) );
3 }# c8 \) k" ?3 P8 J        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, Q5 A% [# J1 e/ W+ k. y3 {
+ c+ }1 e0 J% G- f' T& Z: x) a        elapsed_time = 0;
9 A, V6 N( b* @( P2 ]0 y% j$ i( K! O, b1 }) \, [# T" p
        FLOAT        fClock = nes->nescfg->CpuClock;
$ i9 e* q  ?. T# D" C        INT        nRate = (INT)Config.sound.nRate;2 W. `8 G/ K/ u# ]
        internal.Reset( fClock, nRate );
3 E1 o- L. |; P0 z: {$ G" Z5 @$ m        vrc6.Reset( fClock, nRate );
( S. |. n: |7 }        vrc7.Reset( fClock, nRate );
: k' t- Y4 W+ B/ b2 l' e8 ~        mmc5.Reset( fClock, nRate );6 \& u( |, v. b
        fds.Reset ( fClock, nRate );4 v2 v* ^$ g4 E( q8 ~2 w
        n106.Reset( fClock, nRate );
/ C3 I5 r) W# w' d        fme7.Reset( fClock, nRate );
- a) _4 e# m/ H0 M7 j: r7 x' g' ~, Y, [; Q- o. i
        SoundSetup();6 t3 }8 `$ D; E  D5 P+ B
}% ?- T6 N( P  R% d% }
4 ~/ m3 K% @1 o# T: t
void        APU::SelectExSound( BYTE data )
( h* O1 {6 x4 B0 J- n{# q3 ~; S3 w- C: s
        exsound_select = data;5 d; ~8 r4 i3 z! G
}
, S  ~, F  B/ k
( ?( u2 W4 R; O1 x7 X) p6 [BYTE        APU::Read( WORD addr )- q) V; h. z9 [0 `2 O1 ]
{/ `; f6 l! f! @' P
        return        internal.SyncRead( addr );
$ J4 N: |( u0 P3 K7 S5 r2 k) \4 Z}1 M& Y) n& U) ~' \/ `
; F* g: G7 p- R' t
void        APU::Write( WORD addr, BYTE data )
& E8 a# G$ Q- ^! u; }" Q{. C& q( b/ h/ A1 P9 V, {, H# U
        // $4018偼VirtuaNES屌桳億乕僩7 l9 @0 Y  t1 B
        if( addr >= 0x4000 && addr <= 0x401F ) {) D1 S: C" L* h7 s. s
                internal.SyncWrite( addr, data );: l/ d; m$ B* ~9 I( n0 Z5 u
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
) I! d0 n* V9 [7 @) \0 e        }& I" r+ S+ n* L: w* u; y
}
' Q0 O  u7 a: h( [" F# ^0 P5 N4 _& q8 D3 B) R1 r! f
BYTE        APU::ExRead( WORD addr )6 {" ^$ I# `; V, q' O3 k
{+ s& |5 a4 P' _$ s3 y' h, r
BYTE        data = 0;
! S8 \1 c* L* h* M+ \  q& i/ G# l. `0 t1 H3 E
        if( exsound_select & 0x10 ) {% W' J8 @: U7 i4 ?, u
                if( addr == 0x4800 ) {
$ ]& T# I5 Q7 Y& Q$ J                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );* ~; m( F& `/ e
                }8 F. v2 h. I, i2 {: r6 e$ @
        }, ~5 Y" s9 b% ?' x" X. _
        if( exsound_select & 0x04 ) {
6 ~( P9 Z" y# E( a# ]$ E; U8 H3 Q                if( addr >= 0x4040 && addr < 0x4100 ) {
+ `) _) e. W/ R                        data = fds.SyncRead( addr );: t; m2 n  T, U0 e, r
                }  g+ f3 @& |) r9 d) H' ]. o
        }
: }+ S# j5 H5 H        if( exsound_select & 0x08 ) {
) U, n4 }) a6 L5 Z+ q8 x                if( addr >= 0x5000 && addr <= 0x5015 ) {$ _7 F, b% [# R5 v' F% y! n+ |
                        data = mmc5.SyncRead( addr );
! w0 m* Q9 ?" k5 z9 [5 z                }9 Z# l5 @  i( S5 u8 ]: H2 x
        }
$ ~6 n+ J, E; e& I; o; t
/ F* `3 h, |5 ^) ]6 r. V        return        data;
) M' I3 I4 H) F2 i0 @}4 N' I; R9 k1 p& P1 f. i; Y& u4 ]

: r: y# m: H$ }void        APU::ExWrite( WORD addr, BYTE data )0 W; f/ [, a" \% U4 B* y
{
* M9 }7 n  z( A/ y- |' ]        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
% e2 O6 q' L9 k1 X- m: W1 P
7 f2 N: R& o/ e* F  z        if( exsound_select & 0x04 ) {
( `9 V) Z1 j9 P' l. k! S                if( addr >= 0x4040 && addr < 0x4100 ) {
( L- @. D5 m  w* v' \* s                        fds.SyncWrite( addr, data );) G% E3 Y/ N" s* L! L$ y
                }
: z( Z) j( F# C+ |        }
, [* A9 u6 h% l$ E' ^. U3 E
  v* n# z/ D7 A* u        if( exsound_select & 0x08 ) {# J, ~! d) S' `) K
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! n8 |- i# c& m: ~5 a/ u                        mmc5.SyncWrite( addr, data );2 k% H5 R1 B+ g, i" q2 k
                }
& o" m( C: x2 `" q        }4 P5 T) Q8 p7 g% y4 l4 z* e- [% I
}7 N5 Q* b: G; c9 |; j" W! j& s* ~
7 |+ T/ }* x$ r8 A; p
void        APU::Sync()5 ^' m; `% E  z* N- k. l4 z" t" {
{2 @1 H; U3 q  G
}
2 q: E* ^# A9 t2 e0 ~7 ?9 p3 K7 C- l$ X
void        APU::SyncDPCM( INT cycles )
& ?8 ~" Y1 a3 ^{2 E- k- p( r- Q. z8 W
        internal.Sync( cycles );% }) B" Y& q7 ]; b

3 f& \7 [" K. E( F! [& `! e0 G  E        if( exsound_select & 0x04 ) {
. k) J) x8 _! u! S  y* y) T                fds.Sync( cycles );
7 b9 `* _7 ]6 p( @        }/ j* D# F2 d0 A, ?3 X- L2 O0 x
        if( exsound_select & 0x08 ) {
, p8 @; @1 P; H1 j1 l9 z                mmc5.Sync( cycles );
+ ]! q% c1 m, |7 _, m$ @0 j' g        }% v% i% z( x' c, K7 b( g! |: ~2 l# y
}: w6 J6 A6 d. K
4 g  [1 _  c( ^9 I' t
void        APU::WriteProcess( WORD addr, BYTE data )/ E1 E" ~* x6 O8 k
{& x& }9 d' O- e( ^. x9 u
        // $4018偼VirtuaNES屌桳億乕僩" L9 m3 d! f0 ^& N( A
        if( addr >= 0x4000 && addr <= 0x401F ) {
. m$ j! ~, p- q" r9 N. A0 _4 A8 I% Y                internal.Write( addr, data );
: Z8 }( W6 m* {& w1 A        }4 v* b0 a3 |9 @
}
8 t# n! K3 m* H% g: f
- @* v% f; D* D5 o7 d% B  ^# l4 }void        APU::WriteExProcess( WORD addr, BYTE data )
9 V! u8 S& Y. U! q) i$ Q* i+ K{
7 x& y. K' ^) w; K        if( exsound_select & 0x01 ) {
4 ~. X) v' i9 {. Q2 v+ e8 U                vrc6.Write( addr, data );5 {4 Y; p2 n! q6 d9 _5 Q0 }1 }6 t
        }1 i- D, Z! x$ a! A
        if( exsound_select & 0x02 ) {2 I6 o) @" G# F9 {2 d
                vrc7.Write( addr, data );
! A3 C& B/ w8 P# B        }
& f- `& w0 A2 F; h        if( exsound_select & 0x04 ) {
, [% B, ^0 C4 x8 i                fds.Write( addr, data );. Q8 h3 k9 e) n: y
        }1 x, {# L$ n; a: q
        if( exsound_select & 0x08 ) {$ Y4 n/ z% V+ \2 F: v0 _  s8 @
                mmc5.Write( addr, data );# G9 A9 w" m5 [+ K. s
        }. M+ {5 n4 v9 V3 ~5 f0 t
        if( exsound_select & 0x10 ) {
# @6 c8 {# M2 R& Y) X                if( addr == 0x0000 ) {: x9 Y" t- ^1 H: p
                        BYTE        dummy = n106.Read( addr );* f; B! d" Z. z2 T# r
                } else {% m) I5 M8 D" A! m
                        n106.Write( addr, data );
& g) Z4 b3 f8 c7 W: L                }8 a: e: s$ l% k& @
        }% y9 s- G4 r8 A( c
        if( exsound_select & 0x20 ) {7 `) }# X1 Y) W3 X1 e
                fme7.Write( addr, data );0 \6 i7 Z% M" l# ^
        }
( z% F# Z+ a/ T4 E$ C}8 Q; P0 K( N3 _  p2 [& |8 o: x
. d# T4 `" X0 ?" c
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
' b) q/ ~' o' Q! H# g{
# @1 m3 b% ~) y% j6 v& B, cINT        nBits = Config.sound.nBits;
1 }0 m5 i- z$ O$ NDWORD        dwLength = dwSize / (nBits/8);
) s6 _8 F- b5 m& k6 {* NINT        output;
2 G" u$ S; v% y9 P* a* m7 M! Y7 iQUEUEDATA q;; a) j# O8 d4 F8 n/ }# s
DWORD        writetime;
! f$ a) L9 a) m! ?% r! R% `& ^1 \6 `( \2 X& z( b9 Z9 ~
LPSHORT        pSoundBuf = m_SoundBuffer;' K1 U# k% G4 o  H" _
INT        nCcount = 0;
2 F$ K0 P0 y, e' n; [4 l
5 `, S4 U! r7 s8 }4 s5 y1 ZINT        nFilterType = Config.sound.nFilterType;
7 U- E, G" L3 Y9 j$ z: m) o$ j3 H( k- ~. c8 U
        if( !Config.sound.bEnable ) {, B8 g- [1 \+ ^' M! p, k# I2 o
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
2 q8 Q7 ~5 l, D( b  F4 w                return;
6 K3 ^5 T* b2 R5 L        }
2 b8 t& T- O; n# n) T3 h  x) r2 L. A/ m. I- h
        // Volume setup7 ]" @3 `. K/ d
        //  0:Master
& q$ p0 Y; o2 L7 @2 E5 j" R* n        //  1:Rectangle 1! _+ W$ Z8 {( i
        //  2:Rectangle 24 ^% P0 h$ q9 }8 |
        //  3:Triangle
) y4 J0 y1 c: d  F' r        //  4:Noise% j0 M# j  N+ @/ I4 @- h
        //  5:DPCM
" P2 m! W; G  A8 U" z$ Y" @4 f        //  6:VRC61 E) V+ T5 Z) K
        //  7:VRC7
9 u, M2 f8 Y+ ]3 B; W        //  8:FDS
4 R$ v; l. q) k  @        //  9:MMC5
' c+ `( t! X! x        // 10:N106- u" j2 e% H# l7 D+ k0 _, [2 k/ f
        // 11:FME7
1 V9 c' k" U% i/ H0 l7 A  s. H        INT        vol[24];
& `7 V& z5 i+ |" T' C7 i( [( w5 ]        BOOL*        bMute = m_bMute;% K+ l$ ?9 Q  _) \/ U  X
        SHORT*        nVolume = Config.sound.nVolume;
5 a5 e# p: ?5 Q- n# C- r. R7 l; V0 @4 }; K# _1 w! a1 R
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 t7 I* z2 K! Q
4 m+ }& Y/ c# R0 P2 T5 D( u# @        // Internal
# p, k, ~- d$ C- M/ w, E        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;; I) b( w3 u3 F  b) J5 F6 f
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
+ A2 ?) W5 `5 ]% O4 s" t        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: S; l/ j- m: |" H# G
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
6 l7 ^/ l% ?) M" H' \        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
% U& z- [1 d) w  y! m- d" r4 H; m1 e6 ?) t& N. Q
        // VRC6
) B, d: U9 ^6 Z8 \/ e6 X/ p        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;* d, k4 t: x+ ~" S7 y1 C
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 y' z: W' E1 ~2 a0 S% r# k9 z
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ e1 r  {  Y0 c2 V3 u* \

& _' F+ N/ t5 ^  M        // VRC7
% `: [. M8 \4 b, x$ Z' Z        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;% }9 g$ y7 V0 T8 A- g4 V& R
: h: d$ @3 q) V+ Q7 o) U& p! H) D
        // FDS7 [8 n  i2 l( r' U+ _: Z5 m& g
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
" S0 D4 k- A- ^/ L3 d1 W8 ]- g+ M/ e9 S5 f& M& ]8 [. w
        // MMC5) _/ m/ F1 a8 J
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 m. y6 ^# Q8 d% P- o3 J        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% r/ h+ ]* L4 r0 C        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
6 X! j: L0 s5 a/ o6 J( F0 D
$ x* [0 Z+ X  C1 U) p( G) c        // N106) Q# p3 X6 ~8 Y# I5 Q" H; K. O+ E
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" y4 }* k( v7 }+ Z  q
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ @4 A* O1 A8 e# O! u        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ F( r5 m; r2 w4 D3 @- L
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% O' E, ?8 `- w3 \3 F, g; J        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( b: L( @1 W# s" V
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 f) m) ]9 q; Z4 f        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ y) z1 i7 F$ a, ^, D# h
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! c# F8 S0 f/ V  t5 ?5 j7 W3 B# G+ g

6 ~1 U) b$ `' e% b% |" M        // FME7
8 I/ @7 H/ h: q& H+ N. B% Y7 i        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;3 w: ?0 t6 I: l& e
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; v) ^* x2 M& g% R! j  M4 O8 a
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
* p* n% [. f3 a: g3 ]1 N3 X( x! b6 T  k
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;' s3 D+ c" \+ p/ l- C, q9 k1 g5 R
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: Q1 Q% Q: P  _1 s. f

! X9 M: z3 g% H  U( d: ^6 Q        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
# }# C7 i* `$ R6 g        if( elapsed_time > nes->cpu->GetTotalCycles() ) {5 M: F2 ^8 E, S- G$ Z& `
                QueueFlush();
" {7 ~! v& J8 q) h        }
  M( j5 I* C, i  L1 n4 _
1 b+ w( W+ P: \- ^! o$ l6 e        while( dwLength-- ) {# l% D4 `7 [. l. D# K1 A0 C
                writetime = (DWORD)elapsed_time;
' t0 e0 R3 p- ~7 j) h$ c! @8 ~+ c# z+ w) Q
                while( GetQueue( writetime, q ) ) {3 P( w6 S! i  |- X7 h9 `$ ?; k7 \
                        WriteProcess( q.addr, q.data );. B3 Z, T; H) Z9 N9 y3 \
                }/ r1 z8 P) ]/ o( ?! l& i% ]2 Y
9 u" A2 a( x+ ?, ?8 O$ a
                while( GetExQueue( writetime, q ) ) {
* _2 U$ K- Y1 _8 p/ V: g                        WriteExProcess( q.addr, q.data );7 y7 y1 T# I: H  g$ k
                }
  x( T4 `4 B8 _5 u6 J" m( i
" {, m1 `) G6 a+ E                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7- Z: \  ~8 Q2 A1 Y  F- C8 l
                output = 0;
/ A1 I+ r8 w- K! ]4 F                output += internal.Process( 0 )*vol[0];. f* o5 j/ _, _# V7 K. Q8 ?
                output += internal.Process( 1 )*vol[1];1 D; U! i/ x' ?7 _9 r
                output += internal.Process( 2 )*vol[2];
* k* x; d  w" a% }1 A, H; D; a                output += internal.Process( 3 )*vol[3];/ P: g' {- ]$ Q1 q
                output += internal.Process( 4 )*vol[4];% ?1 S) N( b, y1 A  n. \. y
! b  m* [, t, X# U
                if( exsound_select & 0x01 ) {) L; `/ j: X* J: `2 g* {
                        output += vrc6.Process( 0 )*vol[5];$ o/ K, O' l* e5 \$ A1 E. [
                        output += vrc6.Process( 1 )*vol[6];, i5 s0 U$ }+ c
                        output += vrc6.Process( 2 )*vol[7];
5 r; H5 D$ I$ Z4 k( S' T+ y                }$ \6 a' k2 f* |9 O- o& }0 J5 q+ @
                if( exsound_select & 0x02 ) {8 I, h! a6 S8 e8 _3 h( V8 }
                        output += vrc7.Process( 0 )*vol[8];
# a% b* G, G. t, N5 w4 f$ ^5 Q                }) L, Q4 k; @( o1 O
                if( exsound_select & 0x04 ) {
2 X/ X- S: @; c/ q. j* z                        output += fds.Process( 0 )*vol[9];
6 _3 C- E, K7 M- W& n0 R5 k                }
( z, ^. }6 Z. p- R" ^( \                if( exsound_select & 0x08 ) {$ c% _5 \. I# }; _
                        output += mmc5.Process( 0 )*vol[10];' W1 x1 F+ d8 e5 j" d
                        output += mmc5.Process( 1 )*vol[11];! `( m( U* u! Q9 v' F
                        output += mmc5.Process( 2 )*vol[12];
' x0 \8 H' t9 K9 w, p                }/ d" I) V/ `& |) V
                if( exsound_select & 0x10 ) {
3 A+ o/ r$ S: Y1 O  X/ N                        output += n106.Process( 0 )*vol[13];. v" e5 B% L8 T, B, l
                        output += n106.Process( 1 )*vol[14];# l$ Z. N: H2 u0 X' F
                        output += n106.Process( 2 )*vol[15];/ t  K2 P7 U. W/ Y
                        output += n106.Process( 3 )*vol[16];$ w8 E: X0 M7 _$ u
                        output += n106.Process( 4 )*vol[17];/ L; Y( |$ r5 N( V. _/ Z: s% W
                        output += n106.Process( 5 )*vol[18];! @0 _* X; L# t: s
                        output += n106.Process( 6 )*vol[19];
' \7 X- \) `$ K1 }1 W                        output += n106.Process( 7 )*vol[20];
# j4 Q- h5 V# T0 y" P/ Z- X2 e                }# V( T/ @7 L! \, z6 J
                if( exsound_select & 0x20 ) {
/ o3 L: `4 \. A* x1 ^& H0 f                        fme7.Process( 3 );        // Envelope & Noise
9 k* a0 q" w2 i( W- Q8 H                        output += fme7.Process( 0 )*vol[21];4 U8 w; m. f1 c  q* j/ V' R# X: _
                        output += fme7.Process( 1 )*vol[22];
2 v; A# k- O2 Q/ K. a; R3 ~                        output += fme7.Process( 2 )*vol[23];
- T- v* n% ^1 E3 L5 X1 F                }! W  J( ]1 I) Z5 F* e

1 `9 E4 C. k2 c5 m# w                output >>= 8;# Y! }& S2 P. w# o( U% i% a) Z
/ e% i7 X8 R) x% T( c1 R  r" ^
                if( nFilterType == 1 ) {( _$ K# K3 N1 f. a
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
2 I# {4 N2 l# D0 h% @  H0 i5 s# P                        output = (lowpass_filter[0]+output)/2;
1 e# R8 \6 J& q/ t9 r; f                        lowpass_filter[0] = output;
  w8 W$ v0 c3 R+ C                } else if( nFilterType == 2 ) {
# O* ]6 f, b. P4 E, q* N, p/ f4 M                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)0 l' `4 Q9 F0 V% d1 ~2 u# X% l
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
8 P- ]# F% J3 p9 P, q- `                        lowpass_filter[1] = lowpass_filter[0];
4 X8 H  V+ a3 w1 J3 r  W6 w+ M                        lowpass_filter[0] = output;
) q. R1 F# n" S) e7 s, Q5 Z                } else if( nFilterType == 3 ) {
/ O' i4 _( B9 P" S                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)  f2 g" n, T0 J2 p9 c: }0 `5 K! d
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
. z% m$ w/ ~$ z                        lowpass_filter[2] = lowpass_filter[1];. R1 @+ d  W' ^3 x1 y2 [& I
                        lowpass_filter[1] = lowpass_filter[0];1 \' M0 K. e9 z9 i8 X/ r
                        lowpass_filter[0] = output;
  E) ]% ?' V2 |* u' z                } else if( nFilterType == 4 ) {
! e/ i5 |6 s% C6 Y6 O6 j                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)* `0 s, D+ v- o4 p3 O3 M
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;2 y0 \1 C0 n, w6 u, L3 z7 G4 h
                        lowpass_filter[1] = lowpass_filter[0];
$ Q$ p3 C2 h- A8 ]( m                        lowpass_filter[0] = output;' u, \' ?# j2 L5 C% n
                }
8 p9 o5 N4 O5 _
1 z' g* n+ h0 f#if        0
# [* p5 f# J# C+ F1 b2 g                // DC惉暘偺僇僢僩
9 Z: f2 I2 Y: D& q( X/ P0 k2 f                {
% t+ a3 b/ f  w+ S  s                static double ave = 0.0, max=0.0, min=0.0;9 u- C' G  n/ C4 T/ Q$ F
                double delta;
; y) N  N( x3 x2 z                delta = (max-min)/32768.0;5 u8 q1 f( i. m. c1 \2 z" Z
                max -= delta;( ~1 s, `7 g6 [: v) h' P
                min += delta;6 p0 W" Y+ D5 ^
                if( output > max ) max = output;
' g4 a" Y& l! o                if( output < min ) min = output;1 }6 Z$ a5 G: _% @
                ave -= ave/1024.0;& F/ ?6 g* O0 h" p4 X, v
                ave += (max+min)/2048.0;
* v4 q  s1 T2 K+ r2 Y9 N                output -= (INT)ave;; C6 U. G' w. K3 ?& ~- P
                }8 q. E# r1 a# L5 U; L3 W
#endif
1 `+ j2 _8 r$ p( D/ Q/ Q#if        1" l  L) E" ^2 B; R( j7 R* [# @. t
                // DC惉暘偺僇僢僩(HPF TEST). `7 [' L+ Y  w* g. d9 S
                {
; ?& r1 X6 \/ `, i1 j//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);* t: l0 {6 N9 k7 X
                static        double        cutofftemp = (2.0*3.141592653579*40.0);7 S" p) Z' \, e5 U9 Y
                double        cutoff = cutofftemp/(double)Config.sound.nRate;8 \- ~: J* _5 u: ?# x
                static        double        tmp = 0.0;
4 g* _" z# }! @                double        in, out;& W6 q' F7 X+ T0 q
+ G; u" R- ?7 r* I
                in = (double)output;. [  v4 K8 q  e7 o; Y1 g
                out = (in - tmp);4 w  Y( K1 e3 i% t
                tmp = tmp + cutoff * out;% D8 f) s- D3 s5 o) Q  b
+ z: |9 O; I+ F2 O
                output = (INT)out;( R. E0 W' l; d/ p) V9 e
                }" l  K3 w" \- g% q* X2 l
#endif4 v9 V. A. T) {6 ?
#if        0" N: B- x5 d+ B( |2 y0 q8 B
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
- b/ X2 p& G$ L) V; i( {6 ]1 S                {
. ]' q0 y: a  u+ C7 G                INT        diff = abs(output-last_data);
7 d" N. C+ i  @- W                if( diff > 0x4000 ) {2 V/ Z7 H* _' ~( f& W  `
                        output /= 4;
" e, m4 A" y" b5 |                } else , \( C+ y* ?( D; V  `
                if( diff > 0x3000 ) {$ k" J! J% I9 E! m6 c6 M" \
                        output /= 3;
" C/ S$ z4 M  i                } else
+ \: |' i2 Y, t2 G# T, w                if( diff > 0x2000 ) {
3 H0 N% A3 F( P2 X/ E                        output /= 2;8 P& T  ?  _9 g8 a9 W4 ~* ~6 M
                }/ ]8 \. h7 b8 \" F; y7 E7 s
                last_data = output;& y5 P1 ~  U$ p" k, t% `
                }* i8 E- W" Y3 g9 a/ ?
#endif* O$ L- C# J$ r5 k# z& N+ r
                // Limit
7 {  q& k; L: j- P  [$ m& \7 d                if( output > 0x7FFF ) {
/ u/ N* v+ M( K! _  _                        output = 0x7FFF;
$ f6 E  ]: v/ q$ [* s6 D                } else if( output < -0x8000 ) {
' h' v. A6 u/ {+ ?                        output = -0x8000;2 W1 X- a0 E6 L4 V, y( P
                }
* a+ w; e; C( [0 o: [$ D8 N  b' G; G' d+ X$ n0 c0 A
                if( nBits != 8 ) {
# i1 O# j$ M, s9 T& x, o                        *(SHORT*)lpBuffer = (SHORT)output;
" H, u  G6 i% Z                        lpBuffer += sizeof(SHORT);" I( Q% @( i% |  \  Q
                } else {! {! v: p8 t, k: z) P
                        *lpBuffer++ = (output>>8)^0x80;8 e' E' [3 R/ `
                }0 N* W, A) _4 O9 {5 u. p

) K8 E/ X8 p1 `, F1 {2 ?                if( nCcount < 0x0100 )% D; E% ~) [* u7 E
                        pSoundBuf[nCcount++] = (SHORT)output;
9 |" z' ?& b5 k3 Z& E
4 ^. s1 c" A/ t9 B//                elapsedtime += cycle_rate;
% n7 l5 t' O. V* P* i2 g+ n                elapsed_time += cycle_rate;9 }7 [% V( j2 j( v' `) k6 X
        }
' y+ b5 s" ~  Y* d% r  ^0 |# D# ^. F/ U1 C( V5 ]) v
#if        1
7 y! u$ @6 `0 p8 B$ Z- @        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
- Y3 w1 M! P' Z& k                elapsed_time = nes->cpu->GetTotalCycles();
. J( p. o1 O! D$ ?* @* U- N+ Y( m        }$ K& X0 y/ v& [* {1 O9 x6 x; N
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 [1 c( P9 F. n4 ^; Y1 F
                elapsed_time = nes->cpu->GetTotalCycles();2 R. d; i6 g5 j5 A& P' b
        }
* r" r' L  n2 R- F  Z3 E$ m#else
6 t# e4 m0 }2 I  N# V2 ^3 _- S+ r8 f        elapsed_time = nes->cpu->GetTotalCycles();
% ]  [* Q; r) O2 x8 F#endif2 L+ L* ^* ?( g' Z! }
}- W9 E7 j; \6 n4 o  D1 }

6 T& V! Q- R8 I// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
" ~; D# U0 |! g* ?* B. I: vINT        APU::GetChannelFrequency( INT no )- z! \/ b& |5 U% x: D! P( ]
{$ C9 j5 J0 V8 R$ {- M, `0 T2 l7 s
        if( !m_bMute[0] )5 U- H& g7 |3 [0 w* h1 y$ _
                return        0;
- E% b1 @3 }! s
% D2 w& F) ~2 f, T        // Internal, b: q- ?8 V' K+ u& t1 C
        if( no < 5 ) {6 B! w0 V/ s# M; i
                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 S3 Y7 C, q# C" G! L. K
        }) q' D( n+ @  Z& E
        // VRC6
6 `* r, U* A: a2 @        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
; n: S# N. A2 W' @, h( r                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
$ S- G  k# \% I' N6 q& `        }
/ U: u& ?8 Z& U) l2 B/ u1 W4 c' e        // FDS- j0 S) T- _, Q" |5 B: y
        if( (exsound_select & 0x04) && no == 0x300 ) {0 s0 x5 W/ n4 g! S
                return        m_bMute[6]?fds.GetFreq( 0 ):0;3 }$ _. d; O2 |' E! c3 i3 O
        }/ ]( M) J& m3 _0 T2 L1 R. h4 a
        // MMC5: u- x  a7 A+ a1 R7 x
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {( u" f- C" Z% n7 \( q
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;1 G% J% @- l% N8 T( ]4 w
        }
" u/ O2 K' m! G        // N106
" R8 Q& @0 \1 o- e" l1 v        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
$ _% \' n: j  }% _1 f  Y5 n2 B                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;$ e! Q4 g! e; C' U5 r, t% y- q2 _
        }
$ G6 q9 ~0 k# ~        // FME72 j% g3 B4 M+ R; M- S) I3 A) I: ~
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
: k0 F/ j0 L) V" @                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& {5 y) [: u; U! ^' z        }. N5 G; t5 s1 r9 I1 \" o
        // VRC7' J  |/ Z  w& i+ Y* S
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 K0 h0 b! h2 P' t
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
' c$ U: I2 q! S0 ]3 y& d        }& T) N( q' n0 l: o
        return        0;' _% A3 x0 g& ?! s
}, ^: A; ~( E4 }, _$ f# o
, d" @+ S7 @, m) T  c
// State Save/Load
+ Q( `% Z6 `& S5 y& D; `" cvoid        APU::SaveState( LPBYTE p )
; |5 @0 j; ^: A0 |  D) q5 v{# z6 v3 ?) L2 \1 ]* \1 [
#ifdef        _DEBUG
! v% _, A" _7 C9 a( l) @LPBYTE        pold = p;6 R( T  h6 j4 |; Y
#endif% C1 V. P0 }2 V0 o. L

8 ~. f8 R2 `- r( P# H$ w' _/ m        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞+ _* O' d, s# R5 r* F
        QueueFlush();2 w* q" C7 s$ A: O! [
9 b' z1 J: Z2 S7 b) D
        internal.SaveState( p );: S- Q2 y' C4 Z) x* X8 R$ i
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, e$ y* A5 \1 T9 }: N! @4 U
  u5 x5 z+ e/ s$ |* Z0 F, j  ?+ X, W
        // VRC6
# o3 z% E4 g- G6 d/ Q        if( exsound_select & 0x01 ) {/ e  z& m0 o; `3 d4 ^6 I
                vrc6.SaveState( p );4 G0 m# W  x% s
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) Z: z5 o* ]7 p# ^2 u- H        }
+ R4 a/ g5 k- X, u2 @- x" q        // VRC7 (not support)- ?5 B& S0 F; P* E" i0 D  s
        if( exsound_select & 0x02 ) {6 ]* m% S& S4 @/ E" \* k) s
                vrc7.SaveState( p );9 J, B9 J3 k* C, Q9 G( x% W
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
* w; Q) L  J8 a4 b& Y        }
1 Q" n& T% e: [        // FDS- `% c' S( m3 w% o6 {3 x9 H
        if( exsound_select & 0x04 ) {9 i2 q& V- E/ l
                fds.SaveState( p );
) Q) D, m, X8 X  [# J                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' n* _6 Y: Q. [& V
        }. F$ H0 Y; T- P" k  o; O) N
        // MMC56 l& o9 j# T0 M, b+ m8 M6 O
        if( exsound_select & 0x08 ) {, t8 c! Y4 L- L+ r
                mmc5.SaveState( p );
1 Q& j2 g$ V. p* G& S) P3 ?                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& ]. H3 H" i  _6 }3 j$ a3 Q) s. b
        }% S9 ]# D1 J* |0 n% l
        // N106
5 }2 Z8 r3 i2 q% {        if( exsound_select & 0x10 ) {
; Y' q1 K; J1 P) Y9 C# g                n106.SaveState( p );
' B4 O/ V; ]6 @: c. z                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  i- ^" G$ ~  l3 D1 r% t. H! y        }0 L" T# H% K3 J: g5 k" t9 F. \  }# W
        // FME72 P: n$ o* f  M! @4 r( M. t
        if( exsound_select & 0x20 ) {5 `5 c7 r" n3 A& v. \( ^/ b! F- s
                fme7.SaveState( p );
# f, n: J7 f3 S* \                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding% @- g/ {3 Q8 I& K
        }/ U3 F4 B0 \5 d: o' a8 ~) @0 j
6 u0 Y* k9 K/ i3 I! K+ }4 g/ [- _
#ifdef        _DEBUG
: ?" N8 A$ @" M6 {5 ZDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );9 R0 Z; H7 J% J; Z
#endif; Y& y6 Z% X+ o! e6 \$ {7 C
}
4 |! H- Y% U. v& K0 E: r' z$ O' k
" C0 ]4 H3 f7 w8 H: E0 t+ n8 lvoid        APU::LoadState( LPBYTE p ), {2 y& t4 D4 d1 ]$ v- `; ^: b
{" c) d: D6 H# d0 a' h( s( h* M
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡5 V8 z1 ^  N+ }( \- J; e: G
        QueueClear();# _- k. s8 x1 k$ H) T) X

  d) m6 n# n( r/ S$ ?* M0 ^; G        internal.LoadState( p );
$ h. q$ x% m# y9 X8 ~1 S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ q6 e8 L( r4 W$ G& W
( x+ Y, t* M2 I$ d( Y
        // VRC6
* k0 U0 B; T1 {' t' c3 I        if( exsound_select & 0x01 ) {& A3 @2 }; L( M/ |
                vrc6.LoadState( p );+ c2 X1 b& G  Z: q. i" p
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
! k4 J, C7 i7 g+ A3 _# p# G. Y+ B        }
4 i- V7 O$ b$ J9 W. {        // VRC7 (not support)
4 A1 d" ]3 q4 b3 b        if( exsound_select & 0x02 ) {
( A- c9 T. p+ b: q5 b                vrc7.LoadState( p );
' }4 J6 b& U. _! C+ U                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) l8 f( C/ _2 f5 z1 n
        }
0 u$ x7 D  c. U, x: g5 R$ r        // FDS
% w$ y9 c8 W) d  [" G. L1 I/ d        if( exsound_select & 0x04 ) {
( O4 M. q3 t& p3 G  ?                fds.LoadState( p );$ ~3 H6 o- n& o3 t: i- S: H8 C) \
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' N$ D1 Z, ~* J8 S* `( D7 t9 p        }
4 r7 K; t/ Y# f# ^3 w) |0 C- z        // MMC5
) P7 o  w1 r2 g" e. l5 @/ Z9 ]        if( exsound_select & 0x08 ) {6 v2 f  l' p+ r  B9 y
                mmc5.LoadState( p );' s6 \+ m9 G2 e/ f" v. g3 [% a" F3 f
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding  N* h6 Y$ R2 \; x" H
        }( }+ z( a& B" }; y3 M  M5 p
        // N1064 a; f4 z8 @, t$ H
        if( exsound_select & 0x10 ) {. T; }( D1 ~% F2 \
                n106.LoadState( p );
' F1 y. _6 c9 O/ f8 R                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 d1 C* l; C, {        }0 j; S, i$ T$ r5 r
        // FME7
7 p4 _1 Z/ ?/ y0 u! d; s1 k        if( exsound_select & 0x20 ) {. s/ M5 d) u- }( l. P% [
                fme7.LoadState( p );1 A, T  |; S& G
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 S9 }2 I/ E3 f* X& y+ |        }
, S4 q+ E* V, T, _7 N}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ) M, E1 t9 v& P0 }* \1 g2 t1 p
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. d* I; w5 h6 o* n; H4 `" W. \+ B( @感激不尽~~
6 ]+ N; e: K# a/ ]2 |0 e9 J; v
恩 我對模擬器不是很有研究,2 Q6 z0 p# t& q$ G) D
雖然要了解源碼內容,可能不是很困難," {7 Z0 H, V6 U# L/ O
不過還是要花時間,個人目前蠻忙碌的。
7 V: u6 {! u9 O2 a. q# m
/ I, _: |6 F* J1 g) Q1 f( x9 y給你一個朋友的MSN,你可以跟他討論看看,0 e( o, o7 S8 E1 n
他本身是程式設計師,也對FC模擬器很有興趣。. t& ~2 }. j/ K" ^

% d$ E/ `, {- L  D& o1 hMSN我就PM到你的信箱了。. j" P: _$ \( b: R  M

& ^4 E8 @0 ]8 N+ j* @" }' m% C; C希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
& P& f0 _9 F7 o1 A9 X+ Q呵…… 谢过团长大人~~
9 p$ k& T: N  i' e, f/ E  g

' c( p  w3 C0 z, f7 j/ {1 E# k哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
0 G: W" G& ^, }; M' D团长的朋友都是神,那团长就是神的boss。

8 ~  p1 B0 q) H0 |7 I: X8 ]5 A4 Y哈 不敢當,我只是個平凡人,0 F$ O( N: h3 G3 i
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
, i% P% w& l( O2 yZYH2 i  V/ T2 L7 `% {
QQ:414734306
. @4 O5 q3 r5 i3 d9 R/ A8 O$ IMail:zyh-01@126.com" N6 p$ K5 k% U# Z5 D& @9 }$ J

1 I1 j# u3 V3 C9 ]# p# m# ?他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 # p# ~: ^+ a3 }: {5 c& C, q# N6 D; h
再次对团长大人和悠悠哥的无私帮助表示感谢~~
# t4 ]1 G  S% e! V; P: D
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-2 22:17 , Processed in 1.090821 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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