EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?# ~6 l8 \1 ~% E3 ^% j0 a5 b# t
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
& Q/ M! N1 N; b* G4 R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
. F* {5 |7 O9 Z$ _这里有相应的模拟器源码,就当送给大侠了~~
) M# N4 ^7 t3 u  n9 Whttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" T2 [5 c4 F0 h& V# T能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 B8 a* ^8 r- k, u" E$ n
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 M( U$ m8 A1 J- @  I$ D# W+ Z( X
这里有相应的模拟器源码,就当送给大侠 ...
: u8 o9 x' W2 {# Y( k
聲音部分(Audoi Process Unit = APU):
7 H+ r5 ^- ~3 z2 W6 J  k.\NES\APU.cpp
3 }+ H; Y7 g" R+ {/ N+ Z.\NES\APU.h( A& ~. L8 p' J+ E- z$ C
" `0 c, }: [2 B
) D8 ^$ j* L9 S2 q$ ?; V# x" w
影像處理部份(Picture Processing Unit = PPU):  g# P. C9 z( m  ?3 D# m" z
.\NES\PPU.cpp# p' t" W# S$ k$ J- r
.\NES\PPU.h  a  q0 C$ `0 B
1 ]6 [  n  o  M- h8 \. i
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
6 S, M' t& v$ l(由于很多专用术语和算法机理都不明白,所以看不大懂……)
9 r( ~% o2 j/ O+ G! i+ u//////////////////////////////////////////////////////////////////////////" r# x9 c" D1 m4 J8 `, n
//                                                                      //& k* }* h( L+ z1 Y% f
//      NES APU core                                                    //! a$ A" k% c8 c1 |' e
//                                                           Norix      //. ]7 D8 j' S1 L( d. W6 u7 P/ b$ Z
//                                               written     2002/06/27 //1 t) A* _/ b; O3 c9 y- s. w
//                                               last modify ----/--/-- //- w* H+ e4 p: c9 T: @
//////////////////////////////////////////////////////////////////////////$ D' X5 z: w1 u) @3 l
#include "DebugOut.h"
3 B0 F: R, }! N6 g#include "App.h"  U, T! w6 n) T" J! y
#include "Config.h"; ~5 b" H2 O5 O& }- A

- e& Y6 Y3 V* s#include "nes.h"
* p; p+ ?5 L+ e" ]) M: ?1 F#include "mmu.h"
7 L0 }0 J; j! }8 \0 ~3 l#include "cpu.h"+ x$ |: v* h( _3 n& X: p% L  F
#include "ppu.h"
2 ^! E9 j. J5 I4 M3 F#include "rom.h"4 ~+ I: x$ q& o8 u& x
#include "apu.h"
; b& u- R& I1 [3 b4 a' V- N  z% }; u1 [- w0 Q
// Volume adjust7 _" l: @$ A6 |  M1 N3 n$ J0 T
// Internal sounds
3 d$ {$ E  J9 x  ?1 T! _#define        RECTANGLE_VOL        (0x0F0), t( H- }$ @6 C* P4 d6 w, q
#define        TRIANGLE_VOL        (0x130)# _  M% l; s! F9 q0 M2 l
#define        NOISE_VOL        (0x0C0)2 E) N) y# ?+ S
#define        DPCM_VOL        (0x0F0)4 }1 d9 |, V, P4 {
// Extra sounds. h: J& O& B5 y
#define        VRC6_VOL        (0x0F0)
8 R! J# @$ b9 e+ B7 y#define        VRC7_VOL        (0x130)+ ^$ b) k( G6 q. B9 ~$ X
#define        FDS_VOL                (0x0F0)
2 F& j9 \5 K, `, f3 q#define        MMC5_VOL        (0x0F0)9 i+ G9 V9 L7 }! D
#define        N106_VOL        (0x088)2 f, L, F' q: Y5 [" X/ R  M! B6 i9 x
#define        FME7_VOL        (0x130)
+ g' f% t# O8 r; S8 D( }2 `& i: {; _8 o) ~
APU::APU( NES* parent )* W5 \3 E$ i* u% O
{
+ d7 f; g: y0 o, q) U6 c        exsound_select = 0;) z2 X- P6 k# ~7 Z

( W- ^, \* O+ {  {        nes = parent;  ?/ z6 I( d) t( s* t( z' ~
        internal.SetParent( parent );0 J( L, c6 ?6 _8 l0 d( d+ }

& {$ M0 K& Y- C: Z        last_data = last_diff = 0;1 }6 V7 v, |5 U2 s

! _: J- K2 j' J' d0 r1 u        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );  p4 a0 G( q( H6 r- ?, M! c
4 ~1 i/ x2 h) B: A  ?
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
* j8 R8 f, W+ o/ b& C2 l        ZEROMEMORY( &queue, sizeof(queue) );
) \6 D6 Q$ |6 h5 j$ D1 Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );
7 Y/ {4 f% h! m2 E( S& D% K( ^2 i* O% ~4 I1 v% Y; E7 \, S
        for( INT i = 0; i < 16; i++ ) {
7 z& x- E  R* |9 x: R7 z                m_bMute = TRUE;
/ ?; R; Y* T8 w) d" n0 _$ X& T        }
! r. p: A% p/ S4 h3 E2 N6 o- G}
# j1 ]7 l; X% g8 o4 z
% o1 m  Y5 Y+ ?3 tAPU::~APU()' u* l6 r3 {6 i: P& x: m7 J
{9 J$ m4 `8 W; E( H: r9 B0 O, T
}
0 o! v" S- O+ X3 A3 q! u; F5 G3 D: T. J, e  V  @4 D! S
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )0 e) U! ?8 n' ?" s# l
{
! @$ k! T- L) T5 q        queue.data[queue.wrptr].time = writetime;4 b- S# L/ G# {! g
        queue.data[queue.wrptr].addr = addr;* w1 Y0 G/ i$ M5 @( }8 J& ~
        queue.data[queue.wrptr].data = data;: o: y/ I( X, L' \' H
        queue.wrptr++;
& X/ E  X1 |# L, W# i; M        queue.wrptr&=QUEUE_LENGTH-1;
6 d7 c$ h+ z9 G/ u  M  r        if( queue.wrptr == queue.rdptr ) {
9 ~/ \: Y# v6 B. [6 L) g                DEBUGOUT( "queue overflow.\n" );0 G8 {0 `2 K3 c0 o! X
        }
# S0 \8 F  y4 ]6 q}- O( j! d% }) o7 q  f8 T1 Z
% Q% L; J8 u% U% g+ Z+ B1 x) Z1 S
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 N; _( x, k+ x. e
{, U) J% k( n- @" U
        if( queue.wrptr == queue.rdptr ) {
7 K" B( z" |: u8 V* x9 r                return        FALSE;4 k8 o1 {' d! N
        }% X5 x, }% t0 D& Y5 K: N
        if( queue.data[queue.rdptr].time <= writetime ) {5 y) z! ?; d  w+ T7 l
                ret = queue.data[queue.rdptr];
' n( _9 w) B, X3 F4 b9 G                queue.rdptr++;4 H7 f2 w0 g& N, r+ Y5 r# O4 N$ A- F
                queue.rdptr&=QUEUE_LENGTH-1;% U6 J- N$ ~1 ^9 o" q8 n# f9 g
                return        TRUE;& V0 ~: g& t' l% @
        }
2 s( J2 z. W1 ?+ d! w& V' i        return        FALSE;
. @/ K( u9 K& j# h( {+ d}
; q+ V1 I- r+ v1 t+ G0 l. p5 U5 |; U0 F
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
% L) \3 X% Z  K" E$ U/ }{; M6 N" F! F, x0 i3 c
        exqueue.data[exqueue.wrptr].time = writetime;, ?! _. d3 f) O, E$ K
        exqueue.data[exqueue.wrptr].addr = addr;9 I6 P7 |" \+ y. y, B
        exqueue.data[exqueue.wrptr].data = data;
# Q5 R3 Y2 w9 V, p6 Y2 c8 W        exqueue.wrptr++;
1 |* S; t1 h  d0 V. h; p' b        exqueue.wrptr&=QUEUE_LENGTH-1;
3 A/ [- v( A0 s, L3 m( H. u: g        if( exqueue.wrptr == exqueue.rdptr ) {
; I1 V6 R6 y4 X) |+ k                DEBUGOUT( "exqueue overflow.\n" );, y  L1 t7 }: d  z0 p
        }
3 O3 _, X' N' n3 g- f}/ ^% P. @- }) O' V# q

) u! k% }& x) f9 _BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
" K# Q( T+ x" m' D{
1 ~, x+ m6 t; s! t- B3 F4 p1 J        if( exqueue.wrptr == exqueue.rdptr ) {
3 |" _; o* _# T0 ?4 R* ]                return        FALSE;
: L$ t3 L# [/ z# C6 Y( L+ A        }" c2 E% j$ _; I4 g7 S) j
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {+ u% l- @9 c. W) o' i" L( @
                ret = exqueue.data[exqueue.rdptr];
5 Q( p' R. p3 X$ B: Q                exqueue.rdptr++;  b7 R. `' `) r1 {. }3 z* V
                exqueue.rdptr&=QUEUE_LENGTH-1;4 i( l8 w4 I5 Y  B& i
                return        TRUE;4 m0 k4 q# y/ i& Y' C# W
        }4 X3 S& g9 D4 U0 r6 N
        return        FALSE;2 ~) f5 o; U! q: t; E  d
}: O. s' L8 r% X3 |. v

" H- I/ ~, n% L7 m  o; O; }7 ~+ pvoid        APU::QueueClear()
; C0 j* Z2 P  J{
' V: s/ A; A% f: r. t- R0 p        ZEROMEMORY( &queue, sizeof(queue) );
, g. F) K, j9 A8 G8 \( C9 \        ZEROMEMORY( &exqueue, sizeof(exqueue) );; U! n& k7 s8 g
}; q' S/ Y8 h9 O9 {( U

! y; B& T% K5 dvoid        APU::QueueFlush()
! x- T! z5 ^, a/ q( Q9 D{
0 f, b* a% p7 _        while( queue.wrptr != queue.rdptr ) {. r4 m" \( k$ U1 T' i( L: X
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
5 F* F) ~5 g1 u                queue.rdptr++;
, ^( d' L6 Y& o7 v                queue.rdptr&=QUEUE_LENGTH-1;. x$ ?& V. b4 Z& G; [  Y
        }
2 \* G! d2 T$ h5 k" u- A% \$ K" l% t, i. y
        while( exqueue.wrptr != exqueue.rdptr ) {
3 j/ a/ o. Q  E" k' `( }  N                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
- r4 q# u- Z8 k                exqueue.rdptr++;! g" M! @; n! q5 S+ q
                exqueue.rdptr&=QUEUE_LENGTH-1;
( g8 ^+ I' g: M  H, `        }
, D( L3 e8 \! r( x; y3 ]' [; r}4 |$ X3 S* Y3 ~; r* R

* @; Z/ J6 d/ h" }0 V2 B4 L& |' Mvoid        APU::SoundSetup()
' Q0 l; ?; E# G- r0 w8 ?, I7 t{
* O9 `- a2 Z- t        FLOAT        fClock = nes->nescfg->CpuClock;- H9 K" q0 |8 o( Q) z7 J4 E8 `
        INT        nRate = (INT)Config.sound.nRate;9 W: M/ d' c# x
        internal.Setup( fClock, nRate );
2 Y! X1 d, w) V( b; b2 s        vrc6.Setup( fClock, nRate );
4 S% n' l$ E& P0 V* l        vrc7.Setup( fClock, nRate );
6 ^) H! X: f' A. B% i        mmc5.Setup( fClock, nRate );! F# B& W/ X  ?7 b
        fds.Setup ( fClock, nRate );7 T, o0 b/ a" S
        n106.Setup( fClock, nRate );1 D$ N( F9 b  l# L  Z
        fme7.Setup( fClock, nRate );
& s$ S  N2 A. ^/ f. p0 e0 t}
2 c0 s+ O+ o  b  e5 o' [3 a8 ?
2 ^1 n- \+ ]# x% Fvoid        APU::Reset()$ ~3 j0 Y9 {  U- s8 p3 v3 J! E
{
( A  h% [  A1 B) |( u+ j2 `        ZEROMEMORY( &queue, sizeof(queue) );/ q8 D# E+ I, Q* I4 v" y2 u/ ^' S
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, x1 ^8 y, l. K

) Q9 S% O1 }/ e: _/ V8 ?# A9 H        elapsed_time = 0;1 W9 h7 d5 r3 s: ^7 H! `

2 ^/ A- O3 y* T5 g) k/ I# c5 t( v        FLOAT        fClock = nes->nescfg->CpuClock;
% D4 K, |3 Q# Q6 a        INT        nRate = (INT)Config.sound.nRate;
3 Z# u& r: Q/ I  P8 ^4 u5 {2 @        internal.Reset( fClock, nRate );
& w0 ~0 G% @" y7 k! b        vrc6.Reset( fClock, nRate );5 v9 L8 }- v' w+ Z
        vrc7.Reset( fClock, nRate );
$ C, V0 ^' r: a4 s, d        mmc5.Reset( fClock, nRate );) q$ e1 ~8 @! x7 G
        fds.Reset ( fClock, nRate );
! C8 e4 R) o- t        n106.Reset( fClock, nRate );
- U$ q5 U; v( a2 F- S8 w( |& y        fme7.Reset( fClock, nRate );
+ G% v2 D: L9 m5 t- r7 a. d+ ]" p" h- I
        SoundSetup();
) T9 S; d; P4 `; V; O+ n}, Z" p6 G9 V1 B8 }  R) X

3 |) T' Y1 t0 H, H1 T8 G' ~void        APU::SelectExSound( BYTE data )
6 g: T3 f( ]5 Z5 e. Y{
( R% g" r  J9 j6 ], D& v        exsound_select = data;& J: i) t0 @7 o& H
}4 c6 D4 a9 \8 Q% x8 J+ \4 E5 Z
4 [; O1 Z0 A! ]" ]% _- _1 Q
BYTE        APU::Read( WORD addr )2 h9 |2 D1 v% ]' [+ M
{
3 k1 B% W. t! A2 o0 N        return        internal.SyncRead( addr );. W) G1 s/ j8 M' m% W+ @% d
}* ]; A$ G6 A  H  v. D, ^
; X0 t- q2 A) |2 U2 f7 S0 ?9 E
void        APU::Write( WORD addr, BYTE data )7 {/ Q! D( q3 V; {: @
{7 D/ X5 I7 p3 o7 S- e7 F
        // $4018偼VirtuaNES屌桳億乕僩
# d# H, F# S! t8 o1 A; v        if( addr >= 0x4000 && addr <= 0x401F ) {
+ D# {- `6 l) q% Z                internal.SyncWrite( addr, data );5 q* ?2 e0 I; M* ^
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
6 H3 Z$ {: n6 |' [# Z: f        }
! B) c( Y# R/ D4 p9 t}
. h/ Y3 ^: s5 o0 M/ R, s5 @/ O  P( p9 U
BYTE        APU::ExRead( WORD addr ), D, }. Y0 J4 r7 E: e
{
) E2 J" y+ @; a5 \/ x, ZBYTE        data = 0;: H( m. k9 ~8 y5 o1 v7 a

- R2 m8 c( h4 e1 c! ^        if( exsound_select & 0x10 ) {. ^* W5 X2 L2 A' y1 @
                if( addr == 0x4800 ) {+ {' w# z' ^2 i/ s& o
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
, Q# N: C5 f- i* Y9 T3 o6 O8 g                }3 {% t) s  z6 J- L) \: F- {
        }
: d3 V; t+ ^3 n& N8 M, h' V        if( exsound_select & 0x04 ) {
5 w5 v7 q7 J' J' U# i) L                if( addr >= 0x4040 && addr < 0x4100 ) {" p' \0 L; ?% {& C# D0 p
                        data = fds.SyncRead( addr );' D% H" w2 W3 q0 ]
                }
4 P4 p" P  |2 U/ G        }
1 c' I! q1 B* C( a        if( exsound_select & 0x08 ) {
# c0 d3 w; E- A                if( addr >= 0x5000 && addr <= 0x5015 ) {
' x5 ?, h3 R1 G$ U. j# F* O4 D                        data = mmc5.SyncRead( addr );
- R# @4 T4 m+ y  q$ r                }
2 g' L* K8 s. O0 U+ u/ {/ v6 c8 T        }
2 Y0 w# i& ]# N' |7 \. y+ P3 B9 G- L4 S: K; ~8 T
        return        data;
1 s& E/ N: N! P  R/ z$ q" x# i# O! X' \}+ h5 s7 f8 b0 k" I$ f" {* j
# \  ^+ M. k  @2 ]/ ?
void        APU::ExWrite( WORD addr, BYTE data )
0 h6 A# a7 e/ Z6 O0 X1 Q+ m3 D{
& j9 e! k, x: w, Y$ I6 N3 V% O        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
( n+ U+ y% ~/ Q) [% [, O% h
5 ]2 N6 s* |9 m* z, X  Y        if( exsound_select & 0x04 ) {) L6 K* ~# p' Z1 N# K
                if( addr >= 0x4040 && addr < 0x4100 ) {0 G# D4 _6 a3 ?3 K# t
                        fds.SyncWrite( addr, data );
! ^1 R; j& F2 }1 E8 G9 R: l                }
& E* i/ M5 C1 m$ ~! G/ R        }
# I* S1 P- U/ J* |1 H( r! C, l) [; z2 t0 ]
        if( exsound_select & 0x08 ) {
6 N1 M1 g5 Y* n                if( addr >= 0x5000 && addr <= 0x5015 ) {
# R$ i0 J! e  l2 `4 ]                        mmc5.SyncWrite( addr, data );- x) W6 L- I; d
                }
, g% A+ o# p4 c4 v        }9 Y3 K+ I6 }) j' \  l) B! o
}7 q3 m8 P$ ^6 O- l

4 U' F8 B# `' o& E6 Hvoid        APU::Sync()
$ J6 S9 B& H9 u: k{: d2 ~# g4 e/ j# [
}2 k, E) l$ ]! h/ Y% ]$ Q
& B: ]3 z6 r3 l5 U% ?
void        APU::SyncDPCM( INT cycles )1 d; H% q# p* d% Q( E
{( f6 e( L( l! B
        internal.Sync( cycles );' d0 P4 T  K0 m

. F- W; `+ X/ w9 {# {        if( exsound_select & 0x04 ) {
& Q1 t/ h% N: X# l5 x                fds.Sync( cycles );
+ E" x9 }  h& P4 \        }
: r; X  E; B: P, O6 I        if( exsound_select & 0x08 ) {" r5 |6 B& ~+ w
                mmc5.Sync( cycles );
$ w( c/ c5 T4 v2 g8 L$ R& {        }
+ m6 o; ]7 E2 M}4 |+ M; G! _3 r: X/ k% a- x# L

; I- U2 y' f" F- g5 B  mvoid        APU::WriteProcess( WORD addr, BYTE data )
, J  C  [3 U5 S{
4 a  b* E1 j; s9 x% d6 @        // $4018偼VirtuaNES屌桳億乕僩9 {  i  B8 l2 j1 W
        if( addr >= 0x4000 && addr <= 0x401F ) {. m6 k9 X& T( T7 Y& n
                internal.Write( addr, data );
  d9 y) t. E) r, y6 N        }
' R8 M. ~' D. i5 w}& }7 j6 b$ t3 R4 C

3 P' w: \4 x; ~* {: `void        APU::WriteExProcess( WORD addr, BYTE data )3 G9 M- s" G% W  ^/ P6 A. m
{. U" T! J8 d8 S0 D, p- V4 _8 }$ F
        if( exsound_select & 0x01 ) {
) m2 O% @. M7 j9 ?* e* p0 L% O/ O                vrc6.Write( addr, data );
( L# j* A# f+ ?) l1 u9 b( V        }
% c: H; q# b; V0 w2 `- i        if( exsound_select & 0x02 ) {
# x8 D% `; ~6 M% h! ?8 l                vrc7.Write( addr, data );
$ h. w# N5 C! P0 i0 O* g        }  {- k8 @5 p0 o$ i6 x  }
        if( exsound_select & 0x04 ) {' i% N; i; U, Y; N. a7 N" M
                fds.Write( addr, data );
% b- [* E/ v( P( ^9 [4 ~* s. H- r        }
+ l1 h( i) W0 R$ m% M# D& N        if( exsound_select & 0x08 ) {
! Y4 m, I8 V% ?3 o3 J# _                mmc5.Write( addr, data );
+ x( n, j3 @7 N1 Y+ ]; @! {) y7 P        }; x0 i1 j) S) @, {  t: q" R
        if( exsound_select & 0x10 ) {
& x; t' _0 L; L( h3 Q/ X: P5 P1 l                if( addr == 0x0000 ) {5 `/ Y1 B0 q9 r* {
                        BYTE        dummy = n106.Read( addr );+ ]$ S: r; j; ?! m! K0 U  \/ v5 T
                } else {: U# o7 [" e# {+ M) i2 i9 |
                        n106.Write( addr, data );
5 b0 v5 I% `2 @& p- `. J6 v                }9 M5 b& |) U7 O" U" G
        }
% Y  H! I9 q" o/ @" v8 d) d        if( exsound_select & 0x20 ) {
- T/ X9 b# O0 t9 n: n; m0 X                fme7.Write( addr, data );3 q8 p/ r% P9 f& l
        }
3 ^) w* U) D7 c  j0 n- j- b/ v}  o1 H9 x/ l& E' ~( z1 c4 N
+ A) O0 E8 R6 l* ?' R5 t' w0 q
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 ~" Z5 T% c  b% `; _3 x, n* i) W
{4 H$ ^% h+ r: T% t6 n1 F
INT        nBits = Config.sound.nBits;
/ C" U' U5 L. g+ N4 D6 YDWORD        dwLength = dwSize / (nBits/8);
& G8 \7 Y1 l) z( i* F1 cINT        output;; s3 S% M* P: I  c; ]; \: ?6 U) Q
QUEUEDATA q;
# B5 p$ d2 ~) Y1 o& B# B: C, }- ~DWORD        writetime;1 Y; i. Y2 x+ c' M/ V! m# _' G
1 D- s" s' D: B( f, k* K2 E
LPSHORT        pSoundBuf = m_SoundBuffer;2 p, b1 q6 f1 r0 J; X; j0 h9 I( F/ W
INT        nCcount = 0;5 j9 @2 I' w4 [4 Y

& L9 I( z) r' B$ W6 |3 v: N5 KINT        nFilterType = Config.sound.nFilterType;
! r+ t3 W* O8 e5 {' K8 F  K5 p- @
  r. K9 \% `$ F6 V( ^& J" Y2 I5 k        if( !Config.sound.bEnable ) {
2 p* j9 A/ O* \" J3 T( v                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
( c. x% u* @5 g: l+ x7 x                return;
+ ]1 @8 O! @( X3 A& C( D        }
2 d5 ]/ S2 }* @& B, z2 C0 |
# Q& \  T# n! r  _$ D, A# u6 O4 l        // Volume setup
7 H) j$ G4 v. u+ ]6 e        //  0:Master
9 ]$ k$ N4 }" P9 c/ s        //  1:Rectangle 1+ t8 c/ M; w+ J+ S
        //  2:Rectangle 2
* A, @; B) p/ P9 W) y! O        //  3:Triangle% h3 Q, S! ~8 K5 q* M8 j5 ~
        //  4:Noise
& d! i) D6 ]' Z" [& w  C        //  5:DPCM
: Y$ g3 y6 A2 c: O, B, E$ l, q        //  6:VRC6
5 C' E& H1 y. h7 q' G, \        //  7:VRC7% ?9 V7 L3 P- v' G# F3 Q
        //  8:FDS
; P1 @( S! m! t; T$ j        //  9:MMC5" m' R5 X& p6 v  W" {
        // 10:N106+ @8 D$ A9 ?- f) ?/ h
        // 11:FME7/ z7 ^( u, i, U, H
        INT        vol[24];
* q& W, F$ g3 _. q! J: `        BOOL*        bMute = m_bMute;
# C, z; F& @0 D# J        SHORT*        nVolume = Config.sound.nVolume;$ F9 ?( Z" e5 c! ^2 \$ d7 u
' ?, r8 C1 g2 ?# J- n. B
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' @" j* ^! I8 ?- N( ^! b7 b; ]9 X& r9 b1 J) b' o0 j( o- J
        // Internal
: W" |" w2 M7 x4 F  w( {. ]        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
* f" H* ~6 V0 t$ \2 P        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;- y$ X5 H& h! n6 _
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
6 `7 ^+ a: J$ J4 S: W8 y/ f( Z5 I        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;+ m- e0 O' D6 b. {' m  j: {% f
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;' a% {) }, G9 z0 A( t5 P+ E3 v

' `/ }' s$ {4 F3 k2 w3 K7 {        // VRC67 q! P- ]' [; j2 Q0 Z6 x
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% k. w, |! I7 Q2 R8 a: }
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
+ t' W+ ]( c' q( E+ d' [, ]        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. W3 J1 f3 r  [) Y4 k! B+ t
" w* k" b" a6 R# J* o4 K0 `
        // VRC7
0 t) ~  Z" p- R; e        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
. {# {  f! _& _: _" Z- y# I# V  h6 l. O7 A. [+ H
        // FDS0 }6 V* B. J: y0 f, c
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
/ C9 |" E( B  W* Z! {* u6 o4 v; O! ?1 o+ N" @8 m. ?
        // MMC5
+ _/ f$ l& ?9 Z! l/ h' ~+ L        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 @/ u" O. w; ^3 V
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;& @9 U' W8 h2 Z  r- n1 O6 |& s
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& {9 |1 B' A3 w2 e9 \; x! q
! B2 a2 |. m8 A+ q7 v. `  u8 ?        // N106' u7 R/ |8 ?. P% V  R' q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 l: W; o3 d! F" l" ^1 p- F" Q        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) ]* M' B; ~$ ]( P6 Y# F- ^( a. L: V        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 E9 E! I& i# T6 t
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 h: C$ w8 j. l- _3 J! T; i6 Y& l" _        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  q9 p4 P9 b% w. k" k6 m0 S+ q        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 `2 v- ~5 b( Z; A# i
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! r/ h2 H9 S" |( @
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 Y0 }! e7 }, c; n) ^; o: R+ W& P, x* N, M' x; _( i
        // FME7. l1 L" d+ i& |4 ^; ?6 P
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 m, J3 S2 W3 Y6 K; D' F0 d6 l8 d& r
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. h8 S. v5 I  {3 R* m        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
- h0 ^* h2 p% _5 U3 X, c# }, D5 I6 h; O9 o
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;8 i# y! x* ]: [& W) i
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
3 w: s' n9 i& X! F+ j- _4 @5 z0 `( N/ Q: r6 R. _7 p
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟* ?- _/ O5 [0 R' ?, A% z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {0 g1 A* _% ?3 Z" S: w
                QueueFlush();
) ?4 i, L9 b4 z, j- R        }
0 G# {( y; Y$ V! }* `8 |
, }+ R5 r2 n8 Q% g9 y: L        while( dwLength-- ) {
$ V9 r) R8 S' R: g' K4 R                writetime = (DWORD)elapsed_time;
, z4 |) o$ n; U# |8 q' ]8 e2 N% o! A2 \5 q( [: d
                while( GetQueue( writetime, q ) ) {% |2 t6 B' ~; M. U% e. j! e! M
                        WriteProcess( q.addr, q.data );# X) ^: W. m) {  Q" {
                }
6 i! f* _5 a7 b( b: b+ d) B# O! i
6 |% I8 j4 N# r3 v. Q. a                while( GetExQueue( writetime, q ) ) {
/ c/ z* p+ z1 v                        WriteExProcess( q.addr, q.data );
6 L" Z+ f9 |4 \! S4 ?! Z                }* |7 }( [0 J( [3 m, F
9 l$ o( ^" n% o# \$ X- @
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
3 E8 Y" V3 B- V1 `                output = 0;
: I% V  Q7 L% P/ w8 P                output += internal.Process( 0 )*vol[0];
1 c# g2 k7 R$ l  c* B4 ^# I5 _                output += internal.Process( 1 )*vol[1];# B7 Z% i+ ^3 A! _* b  j: R: r, S
                output += internal.Process( 2 )*vol[2];- E* [) M$ p. {6 M& w  m) R
                output += internal.Process( 3 )*vol[3];
& c7 ^* f2 @1 i' v  {: T0 `% D                output += internal.Process( 4 )*vol[4];3 _6 q) |' A. Z3 W1 r) \

% f6 D8 D" \* s# L) N- t1 Y                if( exsound_select & 0x01 ) {$ Y7 d$ e* s" U7 E2 U6 d2 z  ?
                        output += vrc6.Process( 0 )*vol[5];
+ S/ k$ x8 l" ?; c  |$ h& b1 Y                        output += vrc6.Process( 1 )*vol[6];
$ ~# r4 L" _+ Z                        output += vrc6.Process( 2 )*vol[7];
: u, l4 j) [& o$ P- g: G                }
& x" y! m/ B2 m& n                if( exsound_select & 0x02 ) {# q2 J9 Z8 L3 b; h
                        output += vrc7.Process( 0 )*vol[8];' x# ~3 U* s3 i3 n( g, {
                }. V% j. `7 q9 V# ]. x1 L! \
                if( exsound_select & 0x04 ) {
! T9 z( L1 E  Q: Q, Y/ f6 d                        output += fds.Process( 0 )*vol[9];) Q, m) U* S7 [, }6 _8 I
                }
; m9 r- H% Z6 E, J1 Z                if( exsound_select & 0x08 ) {6 l8 l2 ?! ]/ E6 F- D, m
                        output += mmc5.Process( 0 )*vol[10];
" Y# }$ m. ~! n5 f7 s9 \                        output += mmc5.Process( 1 )*vol[11];
, g4 {$ G8 C/ Y/ A) r* x2 s2 |                        output += mmc5.Process( 2 )*vol[12];" Y  Z# O. w9 s# h
                }6 F6 t& E/ W3 V& p: X' D# [# u
                if( exsound_select & 0x10 ) {2 s# T& j. L  s9 P+ s
                        output += n106.Process( 0 )*vol[13];
1 e' L+ A9 H. P6 n                        output += n106.Process( 1 )*vol[14];, x: f0 ?5 n8 P1 j; \8 v, A$ }
                        output += n106.Process( 2 )*vol[15];' S! s* u9 o" ?( ~3 w
                        output += n106.Process( 3 )*vol[16];: t3 v8 a$ {; J
                        output += n106.Process( 4 )*vol[17];
9 G. R9 Y& Y* P' d  z. v/ s                        output += n106.Process( 5 )*vol[18];
) `* L+ G+ [. f( f; t- a  T                        output += n106.Process( 6 )*vol[19];
9 Y# M: G5 E" ^                        output += n106.Process( 7 )*vol[20];
  q  d+ E7 d, b* h                }" `9 y) O6 Q8 M* g9 E1 h( I! p
                if( exsound_select & 0x20 ) {
* Z4 A9 `5 V  N5 H                        fme7.Process( 3 );        // Envelope & Noise
3 g' O+ `- L0 A) {9 F- b                        output += fme7.Process( 0 )*vol[21];1 b  |+ B0 `7 N
                        output += fme7.Process( 1 )*vol[22];$ z* x) R1 @' d8 F( C/ m
                        output += fme7.Process( 2 )*vol[23];
- b9 Q9 B/ S/ N- H) ]0 K& {, x                }
0 Z+ E+ M* \  H2 I! G! C' S; ~7 u  a" q5 `- }8 T% Z7 B
                output >>= 8;* P# \0 N( o  Q( z% O+ f
" ~) ?( A. o# I  K; z
                if( nFilterType == 1 ) {
+ t/ Y6 G3 s/ l2 V1 h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
! l7 Z" c  }4 S6 M* u                        output = (lowpass_filter[0]+output)/2;) \: {! @; V2 c
                        lowpass_filter[0] = output;2 b5 B+ c8 G% P  O- }9 l
                } else if( nFilterType == 2 ) {
+ Q. [* x5 Y: y; j# {5 D. _                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 B/ e: t! G& T
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
# \; j$ _& u# d                        lowpass_filter[1] = lowpass_filter[0];
3 d( \8 H# ?, Y1 z- ~                        lowpass_filter[0] = output;
, A9 P0 w  L1 ~" J! e                } else if( nFilterType == 3 ) {
1 |8 n: @1 ]0 x  w$ H, I3 w6 K                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)+ K- r+ ?7 y  a! U  l- E
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" ~( q& z% e& T. W  J; E* ]# r/ M
                        lowpass_filter[2] = lowpass_filter[1];
8 m9 u0 C) b* n& }, m" y                        lowpass_filter[1] = lowpass_filter[0];$ V1 O2 ?: W: O) u* w! m
                        lowpass_filter[0] = output;: F/ _' B  E% l1 x/ @( T+ n0 E: g) j
                } else if( nFilterType == 4 ) {! y. x! h) {5 [' A2 w+ P4 J
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)" V* d; g- E( @4 C! J8 t
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;5 s) u3 I  ^3 K8 g4 U! K% c- J
                        lowpass_filter[1] = lowpass_filter[0];
! M. ?/ m) L4 f& w, I                        lowpass_filter[0] = output;
9 ]9 R; J& c6 }7 L% L                }1 h3 \0 @; K1 J
5 u& e; n5 l0 g2 s% b5 y( n
#if        00 v: B% n0 w8 j. C7 T+ A" ?
                // DC惉暘偺僇僢僩
, z+ D/ C4 u. q% E0 n1 L/ v1 ?. o! k                {* Z# X; n7 d9 J+ }2 B8 q3 }+ P& P
                static double ave = 0.0, max=0.0, min=0.0;4 G: v0 W* ?# O6 r5 v
                double delta;; E2 O9 o2 J8 Z" K! H; u- W
                delta = (max-min)/32768.0;* w4 |- S# X  D
                max -= delta;
2 r9 W- N% P) p                min += delta;- q$ u& B/ W% P, F
                if( output > max ) max = output;1 z8 d1 O3 m1 M: h& U( F
                if( output < min ) min = output;6 x4 Q& \4 S4 s- g
                ave -= ave/1024.0;9 I6 r3 J, l: ?- r9 b* K) _# m& I
                ave += (max+min)/2048.0;
+ s& K& i8 a( V5 s/ P( y) w4 m- ~                output -= (INT)ave;9 ~& Z8 n7 y$ z4 @4 Z0 E/ n
                }/ S/ v+ j) V! N1 c: L8 S
#endif
4 z, ]& ~4 ~' Q3 s" [( L2 H. r' U! D#if        1& I; g! J" O# k
                // DC惉暘偺僇僢僩(HPF TEST)
+ u* l! g4 S$ N  s' i  D1 {                {
( c7 \- p2 d, v  U: X2 V) T/ q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);7 E  w/ N, m: Q0 y7 n9 C1 K) P
                static        double        cutofftemp = (2.0*3.141592653579*40.0);2 Z9 E9 ^2 s6 o) T7 U* ~5 k
                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ u0 H2 A& w! S: I& `# e
                static        double        tmp = 0.0;  Y/ R2 j% m9 B' \
                double        in, out;2 }& `. S( k2 o: Z) k

% k' o0 m) X) B+ \. F% P                in = (double)output;
+ Q6 i  m1 w3 j                out = (in - tmp);
$ B* D" h# T/ S                tmp = tmp + cutoff * out;1 K* p( k! p& L) t% m3 C

( |' Y) ?4 b: `$ Z, L' K" }- }# ?                output = (INT)out;
/ ]# F: E; @. H, A& n9 J                }+ u* H$ y# P# L, }! O/ ]
#endif$ Y+ \$ e; w- D8 M1 G# G
#if        09 W  @# `: D& m) ?9 }# K4 `0 ~: G
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ S  t& z$ a: o7 b. x) D                {
% J  u9 B, {7 p3 O# [0 ^                INT        diff = abs(output-last_data);
, W; C8 f2 ]+ `& j) e$ R                if( diff > 0x4000 ) {* k/ @3 g: O6 l5 b
                        output /= 4;
% X, R2 t* B( b. K. |- E) m                } else 6 c; v' n3 k# [  w% _, V( t6 M! x' Q
                if( diff > 0x3000 ) {
8 y- o& K0 f9 |/ q  A                        output /= 3;" M6 `) G5 u  s
                } else8 O5 u  }. h, m( B
                if( diff > 0x2000 ) {1 ^5 S! t3 \- e' }: X7 w
                        output /= 2;: {" y8 V. e! r' l8 g: r
                }
5 K9 h0 M$ G1 a+ Z3 Q5 G                last_data = output;
& H0 \) j# S. w1 \6 i) T                }" x( [" P+ H! U7 Z1 r, k# F( d
#endif
! k$ d; R; R7 E2 n' T! U                // Limit3 P& C* N- H1 r( R% Q
                if( output > 0x7FFF ) {% K7 \6 F9 Z% y
                        output = 0x7FFF;
2 \  M3 c! N( g' i                } else if( output < -0x8000 ) {( d7 e$ w9 y) |  V8 {
                        output = -0x8000;
3 ]& e; R& @5 H& G) d/ M! T                }3 E2 T' m# X# Z9 M: o, J

- P" o! r- ]& j# f/ g2 E                if( nBits != 8 ) {9 V* f) `$ \3 `& j- d
                        *(SHORT*)lpBuffer = (SHORT)output;
. `1 \  {) d# M( m4 k% n                        lpBuffer += sizeof(SHORT);
! A2 R5 @+ I8 ?% u                } else {: [5 L# Q( D+ [* Y/ T
                        *lpBuffer++ = (output>>8)^0x80;3 j2 l) a  h2 G) F* @% n* [
                }' I* i& p" g0 {6 s% c! Y* C

1 c$ \% r3 e3 f4 y                if( nCcount < 0x0100 )
1 T3 p8 w$ u0 o                        pSoundBuf[nCcount++] = (SHORT)output;1 `4 H: }% n  P0 F2 K% X
7 p4 I) b/ k* w1 N' W! P
//                elapsedtime += cycle_rate;1 f3 X% T  v9 o$ i
                elapsed_time += cycle_rate;
  F, D0 Y  T3 x/ [+ P  @  |6 T) F        }% r5 T: l7 K" M5 ^& }, E( x
: L2 O' e; e, @% U7 ^
#if        1
- x! f3 \- A6 f* J0 ~! W        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {: i' [# \' k: U9 }
                elapsed_time = nes->cpu->GetTotalCycles();4 A) d& N( `3 G
        }1 T9 T5 P* k2 ?/ @& z7 V
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
. @) ~( T" F$ S2 v                elapsed_time = nes->cpu->GetTotalCycles();; D+ Z9 t- k9 Z/ Z5 c
        }
. x* C" ~* L$ `8 b4 H% y#else0 d0 ]& Y2 K0 T. A
        elapsed_time = nes->cpu->GetTotalCycles();. B- v. y1 K6 t  g- [
#endif3 R9 ]4 h4 F: \4 k
}3 q  q% m' {& d/ R7 A) ]' S% _
. a! r+ i4 y) K
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)/ m; ?% o6 A# F
INT        APU::GetChannelFrequency( INT no )1 `& k4 O% ^( h/ B/ N" A
{( r+ Z! Y- V' N
        if( !m_bMute[0] )% }) G9 b1 `, Y/ X3 F5 g9 F) x
                return        0;
' @( w* H; A7 i& c5 S0 p3 f) _# O! A; z) F
        // Internal
* I, J8 A7 X' ^! ^8 _. p/ l        if( no < 5 ) {
& w* {0 L7 U' ?! y0 Z                return        m_bMute[no+1]?internal.GetFreq( no ):0;
, J' h, g# l- @5 m1 z        }
% q& j0 g8 c! _7 _( W9 C        // VRC6
6 q' r% [6 Z, }        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
( a  T" M  L& s; I                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;" M: t; T5 _4 B
        }
; j' X+ P9 a, Y) w; h, B        // FDS
' I! f+ i$ K" j: t: P        if( (exsound_select & 0x04) && no == 0x300 ) {. M7 J7 g$ X. J  @$ A
                return        m_bMute[6]?fds.GetFreq( 0 ):0;* q9 [: A4 z# @
        }
9 J& n) c  h# {2 W9 Y; D        // MMC5
* k- s9 \# Y) c4 M/ \2 ?/ |        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {9 f( J  F* t, l0 Y
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;4 s5 W, t6 C, `! i# R8 K1 D7 b
        }
* B  t6 y6 m' t4 D; z2 e  v" G/ _- `        // N106) S- I/ M; O1 Z" ~7 ~# L- T. K' c
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {+ Y* T: G( T5 w
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;% [' D" K1 d5 E$ S! ?5 w) |+ e( ^
        }
. e$ y8 C5 g5 u/ L1 D8 |1 u* G        // FME7& p9 h  E; S/ R6 h* [
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {$ X. }% K# _6 m
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;0 }' o5 k7 R- W' |, B- v
        }+ @1 J, q( W  L5 m& R( p" X* P
        // VRC75 ^7 e  u9 D# k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 F9 @& w, `" E; O                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
2 E  V; p4 |( R' U: A7 H        }9 D7 d- T' F/ ^. f0 U, S; L& _* N; a
        return        0;$ b  K* V: q9 R( z
}4 ?* K) R) l& }) K, d

* `: d/ d$ l' l: J// State Save/Load6 N* S1 y$ n' y4 b
void        APU::SaveState( LPBYTE p )
  B& j* H- e9 s{
- A6 f0 `6 N9 E#ifdef        _DEBUG/ j) h9 C. `3 q+ A" G
LPBYTE        pold = p;$ _, R5 p/ P! l4 `5 H
#endif. ~6 ^& I6 V$ C9 K' i8 v

9 t, E0 x) B- u: k$ }" a        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞' W$ `: G/ t% V, Y3 i" q3 X
        QueueFlush();8 ]6 k1 z" `  B7 z% {: R4 P
' r* ^2 x: t- z
        internal.SaveState( p );& u7 s0 G4 D/ |. B! V
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 _' J0 E0 @) {
; y& M+ P2 w) Z8 V! a- |
        // VRC61 b- P0 S1 u. h( z+ P' i
        if( exsound_select & 0x01 ) {1 I+ d% {4 V$ S
                vrc6.SaveState( p );
0 {- J( n! G, F' s4 I7 K* u, T                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' P( {7 X" ^- }7 ~5 L" ]1 W. F; }        }2 P8 W. g$ ]$ A  t) z$ o; }5 s
        // VRC7 (not support)
6 g8 l2 T- U& i        if( exsound_select & 0x02 ) {
* ^/ a; Q; l5 ^' ?$ }  w                vrc7.SaveState( p );
% d, L1 ~" A9 s! t% p  W                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, ^6 [) ~5 s% S) V! I; o5 x        }7 `* @' V4 C* X7 G- V
        // FDS( z& ?4 [6 A& L) @7 }0 E8 y8 Q
        if( exsound_select & 0x04 ) {
7 ?; z) @7 i( l! b7 [! g7 S, q                fds.SaveState( p );1 G. |. y/ }; R. R0 @
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 Y& h7 P, m( G; E& |3 c
        }
' @* b- Q6 G; i3 N        // MMC5
' \* h. x1 s* A8 m" ]/ l) }4 s' m        if( exsound_select & 0x08 ) {
" O7 k! |+ F4 \( |4 I- {                mmc5.SaveState( p );
4 B. b8 r+ K# t6 m+ g% c2 u! G) _                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
' F# A% @* q$ U3 k8 T        }
. Z8 u$ K. X/ B) {1 F8 b2 x. Q4 u& Q        // N106
! B- ]2 [; B! h        if( exsound_select & 0x10 ) {, Z# E/ _  @) l
                n106.SaveState( p );
' ]* U+ W, y# H; Q$ T0 @                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 E' W' x, `- q2 }# \: L* k( z
        }, o( r' p, j  O0 G! Q
        // FME7
0 ^0 m4 G4 R9 ]. \; T' |        if( exsound_select & 0x20 ) {
$ Q" m+ B2 j, y0 ]# V5 A6 m+ O8 C2 F                fme7.SaveState( p );
4 G  T: ]- ]1 O! r                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 q* C1 b. o, H+ \* r
        }9 b2 \1 X9 X. a8 B' h

1 @) D, W1 N) h4 Q" p3 D#ifdef        _DEBUG* ~! U1 T3 ?0 [+ \: R8 P) S, C* l
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
  O% L- Q- ^0 R4 X& Z$ {9 e% B#endif
% i/ Y( [, X) h}( p" J  q. \$ A4 }
$ J; ]: P% x$ ^$ v6 c1 K
void        APU::LoadState( LPBYTE p )3 s8 `$ H% `; O( e
{2 ]2 E2 I/ A$ W0 u0 D" @  a+ @1 b
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
4 H, M4 \' O* r8 p        QueueClear();% ~9 `0 W& V' ~4 D$ `+ a
; t) L, Y. h1 X& |9 H
        internal.LoadState( p );9 N7 u/ \! r3 s/ M% O; I6 c: ^
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding& c6 p9 N5 s2 s& M  p& ]" Q/ }

3 x  v/ Y2 X6 p2 y9 l        // VRC6
; m- l1 L0 A7 {% U! l" O        if( exsound_select & 0x01 ) {- ~" g0 S5 d+ i; a: {; u2 ^
                vrc6.LoadState( p );& P, a* o6 y) H5 K* a0 K0 X' C
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding* [# w8 |6 q. b( M/ B! @: {: t
        }  D* F  A: v6 Y- M) J+ l
        // VRC7 (not support)1 a  N  S$ Z  T1 C3 C
        if( exsound_select & 0x02 ) {0 C# R& t8 o* g! C
                vrc7.LoadState( p );
# D3 S0 m- @) b8 m6 }8 h6 j/ Z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding0 e$ `1 P, ?, d) F/ E
        }
# T9 T* v! X# i- n        // FDS
; t& X+ P% D- z  C        if( exsound_select & 0x04 ) {
- B/ P8 ~4 x* H2 u9 y                fds.LoadState( p );
0 C/ g% c' s# K" z) g                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 l" F/ n- R1 {/ A/ b
        }
- W- W! d  L. Q) n$ A1 @        // MMC56 _+ p! u& X( m! `# V) L7 Z
        if( exsound_select & 0x08 ) {
; ^/ z) X  L" T0 ?9 h: t. h3 l                mmc5.LoadState( p );- S9 }& ^' C8 G9 W7 v0 c
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 U$ J1 \9 }) ~9 ~
        }3 l) L5 @1 D3 O3 m/ B' C7 Z9 D
        // N106
/ J1 Q* Q* C2 J- j. D. f. z3 Q6 @        if( exsound_select & 0x10 ) {$ F0 j: S1 }' U$ f
                n106.LoadState( p );1 s7 a/ i" R9 |0 Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& a) I8 _3 a3 ?- a: N2 j, |
        }
; E( w0 t( j  Q        // FME7, \6 H% Q1 N; W9 ?) S
        if( exsound_select & 0x20 ) {
8 P( j3 W( N* K                fme7.LoadState( p );3 k3 g: S/ }+ s7 w- M
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 ^/ U1 |' k% K% R. E' S% J        }. g0 j0 H4 K, q2 b1 ^3 s
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 % S$ p* Y( f- @+ P. Z, t8 B4 z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
3 V( G, {" c& m1 e感激不尽~~

. Y1 `  h" E5 b2 s2 ?+ \! c9 B8 o恩 我對模擬器不是很有研究," Y/ u% R! ^1 E3 y; B4 P
雖然要了解源碼內容,可能不是很困難,' [0 N& x2 |0 ]; V$ |6 d
不過還是要花時間,個人目前蠻忙碌的。! K+ Y- p. q' U
- g7 ^/ }; T5 b  r7 @9 u4 i: Q, [
給你一個朋友的MSN,你可以跟他討論看看,
+ [4 X0 K' Q) i7 F他本身是程式設計師,也對FC模擬器很有興趣。- c* a3 c: e, M/ I
" b3 H) A6 \, Y8 z; |6 o: \) U  E
MSN我就PM到你的信箱了。3 T8 L, `0 I. |3 U+ j9 h% I) A

: F9 O+ A- ]" H$ N6 V' x! H希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 0 t$ }, r" _8 `: y# c0 A6 _
呵…… 谢过团长大人~~
; e- w% O9 {! U, v  f5 Q
7 Z0 n; A* I$ }3 z# M$ Y0 H" p9 Y
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 2 w: ?& G9 a8 S5 N: h
团长的朋友都是神,那团长就是神的boss。

8 _# E  y' T9 W8 x哈 不敢當,我只是個平凡人,% |( X. U* f! J% `* K
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
9 ^& z& r2 h" J! N* HZYH% `' T( w3 U2 A% C" L
QQ:414734306
1 B) U$ Q& W/ wMail:zyh-01@126.com
0 F- @. ~) Z6 b3 u/ m# q2 X& u6 O. o, u$ W8 a& w1 E
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
4 b/ p1 Z; n) K( F/ f* R8 F4 k$ C再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 Y1 b% |% g& G, O; O- S' `
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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