EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( b& c- \9 c7 Z& d" a6 n3 H楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! _; y( v" O  t8 {! o3 h# h
这里有相应的模拟器源码,就当送给大侠了~~; D1 X, Z) t: _. `! _( t5 q
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 2 f# p8 R/ |) |* K, C! _4 v4 S8 @
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; a: U) N4 _" z$ X' W, I. A6 E
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
9 A9 s! L+ ?) B# f) c- i  B* B这里有相应的模拟器源码,就当送给大侠 ...
, ?# M8 |7 I! F  x! O* [7 _$ d
聲音部分(Audoi Process Unit = APU):
1 }6 }+ `/ E. H( s: s.\NES\APU.cpp2 H( A; S2 O3 k2 ?( Z: \
.\NES\APU.h- _2 w0 p, I5 d$ q9 V

( E$ A( e# o+ j+ H
+ p5 Q$ U& {( }( ^3 [影像處理部份(Picture Processing Unit = PPU):
' w; `/ r  j5 W# p$ {.\NES\PPU.cpp- I4 E5 S  |9 i7 A' }
.\NES\PPU.h1 r3 V3 W) r& o
0 w/ b5 P. M( Q  W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:. E: g9 I2 O7 L1 m
(由于很多专用术语和算法机理都不明白,所以看不大懂……); \1 R) B, ?* _' }
//////////////////////////////////////////////////////////////////////////+ i* l4 _! ~' l9 D
//                                                                      //! @6 I4 Q+ o( ?  U9 w7 V
//      NES APU core                                                    //) a5 h% `' ~' x& F" m/ b6 O; \
//                                                           Norix      //
, T: ^" i5 f1 T& {; F/ v//                                               written     2002/06/27 //( u4 L, m+ U- N5 [% ^- C/ v, D: e/ L
//                                               last modify ----/--/-- //8 x. h" p3 v& ]: V: |
//////////////////////////////////////////////////////////////////////////+ @' t$ H3 Q2 J
#include "DebugOut.h"  e) U) m& I( b" M, B
#include "App.h"( ~: a) r0 N/ K# E% k7 G& F
#include "Config.h"
2 A6 t% f1 S! j
8 @3 s; B4 P" _* r#include "nes.h"
( }# ~9 M0 w6 R( a& B  q! R* S" i#include "mmu.h"" F5 M: b: O0 u" {
#include "cpu.h"* }6 Q1 ~5 M# M; E: e
#include "ppu.h"5 N' y' J/ `: f, d' v! }
#include "rom.h"
) e2 Q/ ^8 c* b. H0 Q$ A* g4 b#include "apu.h"4 y' n/ W" c6 c1 M* |
. \$ z9 @7 D9 n- G2 Z; G- v
// Volume adjust
6 i2 t+ j( g( t// Internal sounds
9 j$ P3 u* c3 C  ^8 x' C( s#define        RECTANGLE_VOL        (0x0F0)" e( S2 n) \/ e; ~; ?
#define        TRIANGLE_VOL        (0x130)0 z4 K6 i+ G9 g' N, {/ x5 t+ n2 ^; h* K9 S
#define        NOISE_VOL        (0x0C0)1 T( [$ {7 {5 e8 ?2 ~- f' I( t, q
#define        DPCM_VOL        (0x0F0)
9 F) B; F2 F3 N// Extra sounds* P5 `) K+ q6 f5 L' y. X
#define        VRC6_VOL        (0x0F0)/ B. o1 a! p9 L) q6 I1 E
#define        VRC7_VOL        (0x130)
; V0 j! w+ b9 V#define        FDS_VOL                (0x0F0)
: @* q1 \: O: m5 X1 d#define        MMC5_VOL        (0x0F0)% Y+ s2 `" U" d9 u
#define        N106_VOL        (0x088)
# k" b4 `9 y7 g1 d#define        FME7_VOL        (0x130)
. m. O: ?) b, u! v# `5 Y6 }" V
APU::APU( NES* parent )5 l0 Z3 N; R( n, R. E
{
) O  G0 \% y* D5 c4 H1 y- M        exsound_select = 0;3 z/ ^% P; o0 I! a& b. Z3 @( s
- A5 H6 N% u8 e3 W
        nes = parent;0 ~5 d1 \7 g  k- o; [# i" n
        internal.SetParent( parent );* P: x& ~  d4 ?2 m

% @- @' I( ?: r: P: C        last_data = last_diff = 0;) e1 U& q* S# W) \6 r- B
4 q! R, K1 X1 r& [* Z  B: u* o0 W
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );% W2 M# S" Z2 e0 f) L; a0 w

1 G* s0 a  Q) ~5 B- Q" F  o' w+ r        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
# X- R5 a% o! o; [+ i: u; A        ZEROMEMORY( &queue, sizeof(queue) );
& S0 J  j) M% c5 |2 y4 b4 Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );9 }! e: S5 ]7 M1 i/ J

# Z% V) ?' e% t& D        for( INT i = 0; i < 16; i++ ) {
( P5 T5 R. \; \                m_bMute = TRUE;+ F& C8 y4 x  s% X% e' r' d9 @
        }
# G7 N  [& M2 ?) R}
7 Q+ n. H7 p3 i$ U: U4 X5 f8 N! h
$ B' }. O, d3 B9 RAPU::~APU()
# Q5 i3 w: f$ f/ ?{
' _( ~  |5 D3 j  ^1 q}
0 y! x! k7 a6 w* @* |. E/ d
# s6 a5 P0 g9 ?4 T( ]void        APU::SetQueue( INT writetime, WORD addr, BYTE data )) L: D) P4 |+ X' p' ^, o& @8 r5 M/ B( F
{
! u9 q- S# @& D) U2 A. W1 j- K3 B        queue.data[queue.wrptr].time = writetime;( T6 j4 c. g0 U# d* j4 j7 x
        queue.data[queue.wrptr].addr = addr;  r/ o+ [5 d, A' w
        queue.data[queue.wrptr].data = data;! w$ ^: C, X1 |1 l
        queue.wrptr++;
8 q  ^! ~1 _9 g3 Y: q        queue.wrptr&=QUEUE_LENGTH-1;
% q+ ?/ k, E/ K# X" E2 ]        if( queue.wrptr == queue.rdptr ) {
' y' Z8 ~! Q, k, q# b& R5 _                DEBUGOUT( "queue overflow.\n" );
8 {) A' Z2 W* c( g8 r        }
/ `! C6 A; B+ I, y( e}
% q& f, U# C, A1 {3 Z1 U: ~" k
1 j0 X, }5 `% u: ^6 ]2 tBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )! ?4 h& i" v8 K+ l8 y
{
! `0 ]: b9 L$ n0 j        if( queue.wrptr == queue.rdptr ) {
# d" c* E- w; n6 f- B9 ^                return        FALSE;& Q) s2 [# o- h: r2 B$ L
        }
% @2 B' Q5 Z, X: `+ Z        if( queue.data[queue.rdptr].time <= writetime ) {
/ M4 X' a+ e& o) {3 l$ E                ret = queue.data[queue.rdptr];
5 d, H3 \2 H, U; |# }. v$ A                queue.rdptr++;5 J7 a+ X* K4 r- F
                queue.rdptr&=QUEUE_LENGTH-1;
4 n! f9 W. f" I4 t& `$ s" C5 ^                return        TRUE;
" u$ ?+ }( a: k8 n( i0 u2 s: u        }' I7 W$ ], Z3 a3 a: s3 E& `
        return        FALSE;
& x8 {' D6 t- y6 n1 K6 M% g}
* q0 t1 X7 ^9 b; h# L% \  {
" B/ k& j! U) Q/ t& L& w7 {void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* X: H( U. y! f$ e{
3 D! K0 g+ U6 K( b3 ~! p/ Q        exqueue.data[exqueue.wrptr].time = writetime;/ U2 `" W% [! n5 w& n2 s/ G
        exqueue.data[exqueue.wrptr].addr = addr;8 k: D& ?5 }8 ^7 j3 n
        exqueue.data[exqueue.wrptr].data = data;
. {* C- O' j3 y$ \( R8 S        exqueue.wrptr++;
, H! k) Z$ [! r' i% C        exqueue.wrptr&=QUEUE_LENGTH-1;' F6 D" R5 _& V$ J" d# ]* F$ n
        if( exqueue.wrptr == exqueue.rdptr ) {: o* A: g1 C! @
                DEBUGOUT( "exqueue overflow.\n" );
9 c$ G, \4 _8 y9 X0 [' n        }
. W' v$ n% ^. l1 s( e}
  D  I& ]$ \$ X. a+ r3 C- k7 O7 R6 i  }
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
* b. a% }( x/ j4 [7 m# |, A{5 v0 C, B, ]3 p# y. A& I
        if( exqueue.wrptr == exqueue.rdptr ) {
- ]) D) G( [% L3 B' e4 }4 B6 j# _                return        FALSE;& e8 U/ J: |7 m% W" S$ b: r
        }
# Y. F+ P' c1 u) s4 [# L3 {        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
* W( d6 M9 K/ b6 I' _                ret = exqueue.data[exqueue.rdptr];4 c, i& `6 B' o" ]9 a8 a+ Z
                exqueue.rdptr++;# g4 Y; X; ~* G9 I* M
                exqueue.rdptr&=QUEUE_LENGTH-1;
1 @/ j& Z! h4 u& _$ V+ t, J+ R( s                return        TRUE;
( v; W2 h+ V- B" D        }
3 U7 n$ C  P" U: ?( O        return        FALSE;* H, ?0 L( Y1 M
}
, ^% [+ K: ^: p! |
) p* o$ L6 N3 l& |! Y* bvoid        APU::QueueClear(); J6 @+ [! u: Q! |
{, V! h0 `. @! A
        ZEROMEMORY( &queue, sizeof(queue) );
1 g9 Y/ l' g: L8 e        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 ^" A  O; E2 T& z}) e. _3 w3 I1 S
8 a3 ]' }" J/ I
void        APU::QueueFlush()
" Z" r- J$ T: }, Y0 v{
; Y( E8 R# h  k" w: _2 k        while( queue.wrptr != queue.rdptr ) {; Z7 Y+ R! c* P1 K
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
+ N7 D% y7 [" r) n$ y% g                queue.rdptr++;4 F* c8 V! F8 A" b  Y* o
                queue.rdptr&=QUEUE_LENGTH-1;1 d, `% I4 @" S+ v9 K/ F4 D
        }7 f; [" G/ @3 x4 }  |# ~0 H
0 x3 Z5 ]: W! u: [' A3 T$ h1 M: K
        while( exqueue.wrptr != exqueue.rdptr ) {. N3 M5 O$ B3 j' s/ X# e0 b+ }
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* F2 R* X" d+ W                exqueue.rdptr++;
5 j0 Y0 x8 h+ j                exqueue.rdptr&=QUEUE_LENGTH-1;0 B/ s; ?% n0 q
        }
2 W; C/ R4 u/ J- _}9 `7 q9 n! ~6 t7 C6 \$ @

2 z' d, u, K# {1 s9 Tvoid        APU::SoundSetup()
/ ~$ s+ J) y6 h- c$ M8 U{# e: j. o( Y% m6 [% ?/ f
        FLOAT        fClock = nes->nescfg->CpuClock;6 s/ z7 M2 N8 w8 H0 J
        INT        nRate = (INT)Config.sound.nRate;4 o$ w" ~" a3 l
        internal.Setup( fClock, nRate );
, y$ |2 X+ w$ P+ ~8 N7 I        vrc6.Setup( fClock, nRate );
5 Q& Y, l+ q" ?- o9 H4 q8 \        vrc7.Setup( fClock, nRate );) O  E9 c! L8 z: ]: s. h) U! l: l  k
        mmc5.Setup( fClock, nRate );
' j0 m( n7 Y, |9 n2 Q7 I2 e' o9 F- _; g        fds.Setup ( fClock, nRate );
" g! t' L! @1 j( \+ u        n106.Setup( fClock, nRate );
, y9 K  x+ U' ~$ ~        fme7.Setup( fClock, nRate );
2 s6 ?1 R8 ?6 g% f% T1 Q}
/ z- }; D' R& ~) W
& Q2 m/ U  q3 o5 {3 Cvoid        APU::Reset()$ H- h% T" Z$ `' n: F
{0 ?+ N5 `& I+ U& P  W# `3 L
        ZEROMEMORY( &queue, sizeof(queue) );
1 L* {5 y% p4 r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" ~# l9 q& G- D% \+ e: L7 H! B. M, ~" B3 }! E5 H( N* [
        elapsed_time = 0;, h: {* C1 O( H

0 b# Z" R, @6 ~3 f' e: a- F        FLOAT        fClock = nes->nescfg->CpuClock;5 q" a$ j( {! {  K, \+ k" _
        INT        nRate = (INT)Config.sound.nRate;
' J- r* U" f5 ]7 Y, D5 @        internal.Reset( fClock, nRate );1 q  S2 b" ?; R0 o4 ~6 M
        vrc6.Reset( fClock, nRate );
5 j$ _5 X! ~+ L/ m3 V        vrc7.Reset( fClock, nRate );/ c$ Q# a9 y. h% g
        mmc5.Reset( fClock, nRate );. q0 n- o( O2 x$ W& m  @
        fds.Reset ( fClock, nRate );
/ ?- C9 i! H, ~: ?  }        n106.Reset( fClock, nRate );* B; x5 @* O/ \9 j5 K- N
        fme7.Reset( fClock, nRate );
" a6 g: G! C3 s/ S& @$ m7 Q) g! M+ `" Z9 X3 M
        SoundSetup();
8 T, y( N& [. m6 Q# g" o}: Q! N& R4 D7 [9 g! u" N& y
; M% F9 a2 a1 E% j- a
void        APU::SelectExSound( BYTE data )  T$ N: u  A# B& A4 q) P
{
& Y5 R0 t$ S9 Q: [8 J2 M        exsound_select = data;
: K" U  {: Z4 `  C8 N' `: r}
5 J  l  k) R1 V6 B- O8 C3 z
( Y7 x- o, r+ R- [" o1 CBYTE        APU::Read( WORD addr )
# i5 g) i5 e  A, [5 K3 i{
+ V5 H8 E: P0 @        return        internal.SyncRead( addr );, z# @4 S) U" `% \
}( C- S9 J3 r+ s: o' U; J4 a

% D/ V# [8 Z' h7 c. X! {void        APU::Write( WORD addr, BYTE data )
5 o: ~& _* K5 J2 l" }$ r{' q: c% \/ a7 f, x  p* R5 o7 {
        // $4018偼VirtuaNES屌桳億乕僩) O) B. Z/ ?2 Q. H0 C: F
        if( addr >= 0x4000 && addr <= 0x401F ) {
3 N/ J: E5 P3 J8 b                internal.SyncWrite( addr, data );, S, ?  {+ ^" ^' [
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );+ Y7 w  [, y( V; r0 z  L  I
        }: z0 h  D1 L8 C, ?1 b4 B
}
/ X# U7 Z' D: S% i! u+ S; y+ t' j- A. b( x. I' y' M( p
BYTE        APU::ExRead( WORD addr )9 D$ d. r4 Q' A% t& p
{
! q7 u# N2 E1 j7 m- q' mBYTE        data = 0;
* b4 i. [8 E5 h% E
: d+ ~8 s$ R7 h. ~5 c$ S6 i        if( exsound_select & 0x10 ) {! ~1 P/ Q& q) A' D( A
                if( addr == 0x4800 ) {& }5 P; M6 t4 N; K
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
7 ]" Z: |2 v- c! l4 D  b                }* F, |0 L+ ~/ i: z$ j! O
        }
9 o3 F/ |7 r3 K/ l* B% P. a        if( exsound_select & 0x04 ) {( h) Z( `, p% o2 `6 ~3 G/ n* o
                if( addr >= 0x4040 && addr < 0x4100 ) {
6 O3 x6 T0 g  S                        data = fds.SyncRead( addr );* p, A# T" p5 X0 L9 V* r2 |  i7 q
                }9 }. v) W5 v1 y6 w" t- k: a
        }& t. ]7 b! w/ T7 q% t5 z
        if( exsound_select & 0x08 ) {
, I/ y2 ]# l% T. \2 S0 h                if( addr >= 0x5000 && addr <= 0x5015 ) {
, x5 r. }' E  b9 p4 g                        data = mmc5.SyncRead( addr );
' g5 k9 K) F. }, A$ X                }
# F0 `; {" z% f5 j6 y6 m        }% \7 [7 \2 z. i2 ?7 r
6 |( q. U0 z8 M5 e9 N- ^
        return        data;
" }2 b( `/ w+ L- l0 \" C}6 p9 W" w9 t4 K. n! }

# u7 c5 s7 a  b2 W4 `, vvoid        APU::ExWrite( WORD addr, BYTE data )
1 b% ^* I, _7 |: R7 R{
0 [$ X7 o# C) c9 T        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );1 i) v. V; B( S6 a4 N

! c) k/ H: M9 h" I( u: C" U% [        if( exsound_select & 0x04 ) {4 r/ m6 x5 h) y' n; ^
                if( addr >= 0x4040 && addr < 0x4100 ) {* W4 A9 o4 W5 w) Y9 w* D" @% U
                        fds.SyncWrite( addr, data );0 b' M) p  J# E  ^3 @
                }4 ^% O1 C# `9 x+ Z
        }
6 w2 @, I! X6 @- e- s
$ [- x% K% @2 z        if( exsound_select & 0x08 ) {
0 K! l6 ]6 f* }; c" {. s                if( addr >= 0x5000 && addr <= 0x5015 ) {
: j& `# L, \$ W8 \* ~1 w2 R                        mmc5.SyncWrite( addr, data );$ L+ s8 `# M5 I' N) [6 W$ p$ W
                }
7 v" L$ O& h- t. l& c: ^0 g        }  p+ M& y. w/ n1 ?- l! ^
}
4 O3 ~) `) V$ J& w  a0 u' d
' o* R, u  e- A0 W+ l. Lvoid        APU::Sync()
: G5 o2 p9 \& h0 k{8 `! T1 ~. s4 B# P1 M) O& t
}
! }6 m$ Y/ u5 W) M# x, {# x+ Y
! C$ q4 I% e8 }5 f7 n# Zvoid        APU::SyncDPCM( INT cycles )
2 ^6 H" }% g- w% s. R6 b9 `8 R{
& c' P7 c# F2 j. @        internal.Sync( cycles );. v# y, m1 j' p7 i1 p
1 w0 A: C/ X7 |
        if( exsound_select & 0x04 ) {0 z: w# [% O+ M
                fds.Sync( cycles );2 ?. R( s4 {- T) o, b% ^0 v
        }
) I+ y1 u! d/ [' c+ H9 A        if( exsound_select & 0x08 ) {% Y" w1 J4 l0 F  Q- P6 N1 e
                mmc5.Sync( cycles );  c+ x1 R. H3 w. ~
        }
" G+ N4 K0 K" n* p$ O8 d% p  F8 n}
6 C) n: L6 |( A4 d. A# `3 C: ?( V) l+ z: j; M  V+ _. z
void        APU::WriteProcess( WORD addr, BYTE data )
; C# ^/ k  F) S! n. Q/ H5 R{
4 c! E% O4 k# j7 ~" m        // $4018偼VirtuaNES屌桳億乕僩
* A4 O* _7 x! e& C7 u        if( addr >= 0x4000 && addr <= 0x401F ) {% B7 s9 S  m: v4 P% H
                internal.Write( addr, data );: u% L" `. ^, Y0 R$ \! L: @
        }- i5 J3 z8 C1 R+ {; o
}
6 j( w. R  e( k6 I$ }1 H( i3 T  e9 _; U
void        APU::WriteExProcess( WORD addr, BYTE data )% [! B5 B4 g# |
{  }' ~) d  X  f7 |
        if( exsound_select & 0x01 ) {) Y$ z# g" q' G+ x
                vrc6.Write( addr, data );
; s& f* }3 ?( R- W4 j. e2 e3 w        }
$ |! Y) X  f- L% S" h( A9 m, x        if( exsound_select & 0x02 ) {/ M, R0 E7 [/ J. {- C8 [
                vrc7.Write( addr, data );
' b+ J1 \6 @0 f. S        }, p2 @, v2 Y5 O/ O/ h. q3 m) r
        if( exsound_select & 0x04 ) {# @( M, X! h# v+ K
                fds.Write( addr, data );7 D; F% Z5 U9 k: L8 A
        }
" ]2 l. G% v. H+ I# B. j5 ^1 z        if( exsound_select & 0x08 ) {! P. }; m3 j0 I
                mmc5.Write( addr, data );
3 J6 U2 O  x& \* B% W        }& u7 i" _5 x- {5 q
        if( exsound_select & 0x10 ) {% Z. C! B& |( S0 e8 O) |  T9 J7 m
                if( addr == 0x0000 ) {8 [" M& R- K$ L7 t4 D9 c3 T6 G0 o
                        BYTE        dummy = n106.Read( addr );, r" u- ^2 V6 Z1 _, [
                } else {- P& l3 F5 t5 E8 J4 s6 Y$ A& g
                        n106.Write( addr, data );
7 [# G- ~! U) y; L9 _% J& [                }% j! F- Q( w: p2 r6 a, I4 x$ r
        }
% J' \3 w! |5 A        if( exsound_select & 0x20 ) {* e8 n4 x9 p# Q" o0 {( r7 I
                fme7.Write( addr, data );3 c5 f( m1 T: P) |- b( A9 j
        }
% H. }  z$ u2 L2 K/ m9 @/ c' q* B}
; g; r/ Q; ]! T+ ~7 v2 C& s
) Z0 w: ^6 V. _4 F0 @void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
1 }( X- ]/ g" y. P8 W5 M{2 }. `' f: J! t
INT        nBits = Config.sound.nBits;
" a9 l6 S% v& ?" e: y( h. w$ cDWORD        dwLength = dwSize / (nBits/8);
5 o% F) p. b) ]INT        output;( Q, O8 G, U# v0 \* _1 p
QUEUEDATA q;
6 M# L, b) k3 g4 ADWORD        writetime;
( d- F. t& w" o8 a" C; G$ M* A8 L& ^3 P
LPSHORT        pSoundBuf = m_SoundBuffer;
: B, c) J, l" n2 `: ?, b1 PINT        nCcount = 0;
' a: Q+ \% T/ ^* I& I
: w2 u- [  c/ ~2 b4 r3 [INT        nFilterType = Config.sound.nFilterType;4 `2 q" t# @9 }4 ]
* W) f4 P: h# O
        if( !Config.sound.bEnable ) {
: Z7 _( ~* @* n8 t# `                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 D. q+ x7 s0 \2 k. z( K: W8 b                return;
# b( o% Q5 N3 U" x* N/ y! V# i1 |        }% C5 Y8 e: `( X" a: k, C# }

# c9 [4 h' d$ k% s        // Volume setup
0 ?, ~; r& J% n+ I& ?        //  0:Master
$ @, I0 @6 u" E        //  1:Rectangle 1
, P, v% V; U4 A' a3 [        //  2:Rectangle 2+ R8 u- \4 K2 A
        //  3:Triangle& O, x0 y( j, ?; y' a$ [/ W: K
        //  4:Noise2 e# u0 c/ d0 Q
        //  5:DPCM! n5 {, f* Y( x+ \
        //  6:VRC6
+ o0 j9 Q1 l6 U        //  7:VRC7% y* H7 }8 k# M; x2 H! B- H2 R- f
        //  8:FDS5 B1 T# X* i" g- e
        //  9:MMC5  k. ~, B3 L: s
        // 10:N106
& G( @( ]6 K! `( u        // 11:FME73 d& z) D* |* \0 h) s' w
        INT        vol[24];
& W; m4 f. j% {3 d+ l, Q        BOOL*        bMute = m_bMute;% B5 R! B( W2 u; u
        SHORT*        nVolume = Config.sound.nVolume;
  i" o" f0 A- E; t6 U% }+ ~7 t9 Q* G) F2 m) Z: k0 \
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;& F# b: S8 T, [2 N, T8 F' t; Q

& A( p# }7 W5 g4 S# x4 Z        // Internal
1 u" e! I3 Q: @' E5 F/ `" p        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
$ `$ z4 X/ M. w8 l2 [9 ?        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
) [, [! ?& O% \( F        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;: p. j$ r  ], _/ M
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' [$ k' P) i) x! O$ V8 E, \  V
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
. L9 I1 V$ U' V' _8 Y
2 z3 S: d+ R7 c4 _2 \2 {        // VRC6
3 y0 H3 m, u# T8 E# Y+ g6 ?% m' Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) i( b1 B0 \) q
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;) W& Y% U+ h* T/ f  Q! ^! x3 u& D
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 K& i8 J8 h! Z
7 ^1 [0 \) N; [1 _$ a& B6 b
        // VRC7
+ Y- P: B$ @! s4 J: W3 ~        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 S4 `9 t5 F- f6 J: T; b
* R( w9 P  e8 w' ]2 q0 p
        // FDS
/ Q( J3 x8 g. O- X2 Q        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
; ?8 L9 Z, |- a1 R( f8 m9 }. F3 D8 B5 y
        // MMC5
4 N' P9 r3 S' Z9 f( Q# K. r; P7 u        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ b8 p, H0 b% H
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 D0 A, }/ N2 U  v, @- O( ?) E        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ c# x; v1 z5 T
8 y) C  W' Z0 K& r, Y1 r        // N106
/ B' r/ S& x( t        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;) t3 G7 K* E1 o1 f9 T7 d4 |
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 W5 [0 Z4 t- U# H# v
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; L. s7 C: p6 P# C% F( B4 B
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 x: ]! r9 N# o! J        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% l2 h! ?& v# G  F8 s$ d
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- J6 B, R6 S* v6 P$ R
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 b+ m, Z2 {) F/ L        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ I5 t: a0 C0 V  ?( Q" e2 X; m3 J# @. E: i9 C9 }4 a' E
        // FME7$ L, a/ u. a1 e9 a/ s
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 S, `! [! x6 ?  W( b8 v; L
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- h+ ~. j, x) h
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 B7 X" I3 _5 q3 p& \$ f" U& e  i

1 W+ Y& p/ r1 O+ e8 H( e) @* E//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
- C8 ], j/ K/ O) }* {: R2 h& ?        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
2 a0 T4 c( y( b+ x1 c5 e! f2 T0 B. A# }* i! L: v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
5 q  \6 u, y, O. o4 Y        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 ~1 E0 v5 }- g: g( O( b                QueueFlush();* Z; d% X: ~5 l% J$ w. R+ I
        }
& R2 {! n" I/ j4 L- f( M, B# m& ?! y7 K0 X3 J/ @0 q
        while( dwLength-- ) {! F- P2 Y) N; J! o  d8 W
                writetime = (DWORD)elapsed_time;
( ]0 S: G5 Y/ I$ m5 J( P) U) T: g. L# c# a
                while( GetQueue( writetime, q ) ) {
8 W. p- F- I: V( \# x) o: N                        WriteProcess( q.addr, q.data );) o& T" j) q$ S4 N8 |
                }
: p; R) M1 H0 T' O3 `8 v! V$ ~9 H! z: z5 F% J( H1 p$ R$ b
                while( GetExQueue( writetime, q ) ) {9 j/ x% x! `  v( X7 }* R4 ?2 }
                        WriteExProcess( q.addr, q.data );
7 e. w" D. T8 _                }& g2 @/ p& r$ x; o6 f

8 ?! H$ J( `6 Q* m. h+ ~                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
' f; [- |! o) s; M) n5 ~8 B                output = 0;
9 {- j& V5 H/ ?" h                output += internal.Process( 0 )*vol[0];
  C0 G3 t* z; H% U, Q                output += internal.Process( 1 )*vol[1];
9 ?5 \  U7 T2 o  m/ N: {                output += internal.Process( 2 )*vol[2];
8 O7 V3 F1 g5 y) C. y: O' ?, D                output += internal.Process( 3 )*vol[3];
, \% m" x/ X7 _4 m  P# `) D6 j8 U+ t                output += internal.Process( 4 )*vol[4];+ P! q' d; o+ y- h8 u* I3 }
* |& k! `. a# Z8 ^
                if( exsound_select & 0x01 ) {
7 C& q3 x& n) ^. O1 T                        output += vrc6.Process( 0 )*vol[5];
0 u) I3 t* k' R2 w: N7 U0 w% B- J                        output += vrc6.Process( 1 )*vol[6];/ X# }4 }; S+ Y, I' S) e
                        output += vrc6.Process( 2 )*vol[7];0 J/ k$ M% U. ?3 c
                }9 n5 O( @% h/ T( o4 I2 ~, L
                if( exsound_select & 0x02 ) {8 T: C1 p" }( M+ h! g- |
                        output += vrc7.Process( 0 )*vol[8];) K# h) N# {& Z3 }; A. g
                }$ g  h9 q- x4 N0 n' n, l# f9 u+ r
                if( exsound_select & 0x04 ) {
" j/ ^) F1 T% V, e$ `( g# g3 r, ]                        output += fds.Process( 0 )*vol[9];
/ t$ [) b$ ?+ o+ M, M                }2 V& y, b, P* Q. G
                if( exsound_select & 0x08 ) {
. l6 i6 V$ V; E6 V6 T/ S! \                        output += mmc5.Process( 0 )*vol[10];
0 x& K: {0 M+ M3 S* D' q                        output += mmc5.Process( 1 )*vol[11];, X) F5 S$ E0 P0 {0 t
                        output += mmc5.Process( 2 )*vol[12];9 U) z' Y, D* f; K/ s" a7 A8 Q# h
                }. ]- E: S+ ?! N; H  l
                if( exsound_select & 0x10 ) {% K, K( P" a4 d  ]& u
                        output += n106.Process( 0 )*vol[13];
+ @; m+ Q1 s/ R                        output += n106.Process( 1 )*vol[14];
* [6 Z5 e- v8 A. T: F7 `' W9 {                        output += n106.Process( 2 )*vol[15];; |3 D7 X. R& g! C; Q4 Y- ?
                        output += n106.Process( 3 )*vol[16];# p9 }' f: J2 z8 C( V* a/ j
                        output += n106.Process( 4 )*vol[17];
: O9 x  D5 f5 `* Y                        output += n106.Process( 5 )*vol[18];
+ q! ]7 t2 G) V1 K                        output += n106.Process( 6 )*vol[19];5 b6 |- W8 \, O" s3 k! V1 W
                        output += n106.Process( 7 )*vol[20];- W1 V$ @, q7 g, {$ e
                }' z/ M8 E0 B. ^: S
                if( exsound_select & 0x20 ) {
* @# q$ @" [/ @2 i0 B# `& B8 M                        fme7.Process( 3 );        // Envelope & Noise
9 P1 K7 T( B+ K/ K/ e" Y                        output += fme7.Process( 0 )*vol[21];3 |9 Y: X5 S7 P
                        output += fme7.Process( 1 )*vol[22];
; \2 X' R3 z+ p) ?% R1 n! S' }8 X1 k                        output += fme7.Process( 2 )*vol[23];. ~  P2 R; V$ F+ g' B
                }4 h& f) _7 Z/ a2 h

& U4 r: X, U, |9 d+ g& W+ D8 m                output >>= 8;
3 a8 K8 \3 X1 D- p2 o2 z
! h% f) D* a  W7 ^                if( nFilterType == 1 ) {
9 o. c% m; Y% \# @                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)0 h3 t3 ?8 S" J' p5 I
                        output = (lowpass_filter[0]+output)/2;
# V6 o0 J+ B& A7 e- f9 ?* I                        lowpass_filter[0] = output;$ s; H. c; Q9 v4 e9 O
                } else if( nFilterType == 2 ) {
3 b9 i$ r8 M; P9 `: j, W                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1); U0 `6 X' B3 ?' r+ K
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;3 G- _* E1 S- P0 l0 w4 p. U; `$ j) f8 V
                        lowpass_filter[1] = lowpass_filter[0];
3 ?5 R, D  ?! h# n& Y                        lowpass_filter[0] = output;
+ J2 A6 m8 j$ B* z                } else if( nFilterType == 3 ) {
3 m. Y% S( u( K, X                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
- {* ?! b5 p# I: C+ I1 q) q0 o) p$ n                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;) p/ J7 W# y4 h3 d) b* J
                        lowpass_filter[2] = lowpass_filter[1];
1 I+ l6 |( P$ o, e/ P7 E( T                        lowpass_filter[1] = lowpass_filter[0];3 j  O& R2 e3 d/ ]' ~8 y% v+ ~, C
                        lowpass_filter[0] = output;& ?: g" u3 S9 r$ z7 g
                } else if( nFilterType == 4 ) {6 F7 P7 R8 u& a; X- F
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
6 {( C* x3 B5 c! G# B                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
6 Q' F' Y6 L* `+ p' v( ]: c9 V                        lowpass_filter[1] = lowpass_filter[0];+ S3 G) u4 V3 H, ?& `
                        lowpass_filter[0] = output;) {/ T2 ~% N8 C4 n( b
                }) r& y6 i# t8 g# ~/ A) H

; B" V/ k4 W: v! i0 Q#if        0; r( H  c. z( p
                // DC惉暘偺僇僢僩2 p5 u+ G9 x! _0 M
                {# Y' G7 h; E1 W# _, Q) u5 F% m
                static double ave = 0.0, max=0.0, min=0.0;/ b! r+ }& _$ Y
                double delta;) }  D' A2 ^0 \. C+ C
                delta = (max-min)/32768.0;: d1 J5 A2 h: [0 ~  a  v
                max -= delta;% l: e4 N2 @0 D) E
                min += delta;
( J4 P% k7 g. g                if( output > max ) max = output;  R. J* f( r8 y$ r" a9 ^  w/ B0 p
                if( output < min ) min = output;
5 @) Z2 L& @7 r/ M  o+ ]" U, {                ave -= ave/1024.0;) [  a1 ~. \$ H7 e! Q
                ave += (max+min)/2048.0;
9 P3 V8 Z0 z, N2 @1 ~" F) e                output -= (INT)ave;
7 Q0 S& T, r1 k" q8 d: @! N5 K8 n4 g2 [" Z                }
8 p& Q3 f7 D/ [- q# X#endif' W+ F% j: b5 t, U( a. ~
#if        1+ p* ^1 F! |# d- l
                // DC惉暘偺僇僢僩(HPF TEST)7 ]# J- a: Z% q2 M1 q# @; ^
                {: R3 K5 N# d) `& c7 i" F' A
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& h1 a7 o) h, C7 W
                static        double        cutofftemp = (2.0*3.141592653579*40.0);4 z7 @3 {% |+ e3 |- ?; P6 p+ e
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 i+ ^' n' m+ g2 W4 S: R                static        double        tmp = 0.0;
4 B' C8 t( X- k& a$ J& v* u4 g                double        in, out;) y% `3 O7 }/ L  o
; i. @; [4 C+ L3 c; M! j# u
                in = (double)output;7 H/ B9 v# z3 p* U5 d
                out = (in - tmp);, N$ R# K5 t! d3 i( r1 v) W0 Q
                tmp = tmp + cutoff * out;$ o$ F8 h7 N( \% U

1 X2 s/ o& Q: O  A/ F& n                output = (INT)out;
: |0 _& [% X* }: u7 R+ h                }' o4 ?6 p& o# o) h
#endif0 D1 H. \0 r  {- F
#if        0! S% w  a. m/ k: ?' e: @/ \% y( u! Y
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)4 N) X2 N2 q, F+ f
                {% e6 K2 ?" q) p" p
                INT        diff = abs(output-last_data);
6 M( d4 U' U1 G3 e2 `( o                if( diff > 0x4000 ) {
1 W/ _7 F* |7 k" B, P                        output /= 4;6 s" L* K& p% i; F/ B+ d
                } else
0 }) b% r) @# J                if( diff > 0x3000 ) {/ Z' z0 v9 s" C0 S
                        output /= 3;
" V0 ^: v/ A' a" u0 _1 Q                } else8 N! \- s: @2 ~" d( L
                if( diff > 0x2000 ) {/ p% o% f. G+ I- T5 x
                        output /= 2;1 B7 |' y& G2 }3 L3 E
                }
. o8 W. V( }6 y0 u2 h' g  S7 o                last_data = output;4 Q# q( X- Z; G0 d4 r
                }
: W3 i, }! m0 G' R  N#endif8 E% w- s3 w" K7 m7 x" I
                // Limit) Y$ v; A, b5 q- M, l
                if( output > 0x7FFF ) {
, {% n* q4 t6 f                        output = 0x7FFF;( {7 w% a& m# z8 n/ a
                } else if( output < -0x8000 ) {
0 K2 e1 K! I0 R& ?+ D4 ~7 w: D                        output = -0x8000;; k7 g0 {; w% j; Q
                }' E* c: z+ C, C" `. F
! L: m$ j/ W6 i, _' i* F+ H
                if( nBits != 8 ) {
5 `! H; w- ?3 N( `1 A3 P' v                        *(SHORT*)lpBuffer = (SHORT)output;
+ g: T$ S2 r& O. w' z" `3 r                        lpBuffer += sizeof(SHORT);. q: r8 K3 K9 {: [
                } else {' U) {1 Z8 R$ v- G. t
                        *lpBuffer++ = (output>>8)^0x80;2 |$ x1 e- c# [: D( l
                }
/ r' f( m. L3 C" c4 H0 p( @
3 v( \, E- e) l                if( nCcount < 0x0100 )
. K% |0 Q) M  T& z: t/ I                        pSoundBuf[nCcount++] = (SHORT)output;' U) v* v- [0 E* u$ g
, ]  k( D  |5 \6 I, O
//                elapsedtime += cycle_rate;
7 P5 S8 N3 r2 E4 V0 a& t: l1 c                elapsed_time += cycle_rate;1 K+ W+ ?7 t" ]$ }( x+ G9 ^
        }" ^" l% N# Y4 {( j0 l
) V- D1 \  t* P) s
#if        1
2 |# v0 f) I8 i3 P) s# O        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {% Z1 J$ C" C' V3 V. Y
                elapsed_time = nes->cpu->GetTotalCycles();
1 X0 O5 T) V2 i+ F- J5 {4 x3 u        }1 r; ]) k* a3 d4 j5 l$ K# w) e; S
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 \" B& B# p) |! o$ c: A
                elapsed_time = nes->cpu->GetTotalCycles();
! x' r: c! u$ l& Y+ W3 e        }
+ K: T, }% Q& `' b: f  G: i#else
% {0 Q& K/ S0 f) A. U- u. \        elapsed_time = nes->cpu->GetTotalCycles();
: m( X4 @+ g) r9 f#endif
5 e. ^2 d3 Z& b! @% u- q$ v}
$ e- l7 I# a4 c/ @
3 |6 ~9 u$ m) X( t! Q) [* a// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 W' _* o6 g! Z* W5 PINT        APU::GetChannelFrequency( INT no )
7 l# F9 ^2 l- g) q. n2 v- @, v1 I{
6 D* x" T, X: L0 |$ L        if( !m_bMute[0] )# D+ n9 t" j; B2 h: s+ G( B2 ~
                return        0;
$ ?  p/ v. v) I3 H3 r6 z/ H4 [
+ y3 S( N' {* n) I9 h        // Internal% _0 u% Q/ T+ e8 @8 U
        if( no < 5 ) {
: c4 _( |+ Y0 v8 c) ~% \                return        m_bMute[no+1]?internal.GetFreq( no ):0;. w* R( I3 k: v0 p3 d
        }" l" n# J# q7 p* n  G0 S
        // VRC6
& \2 Q; f2 Y7 u, X2 p& n! Z1 I" g8 t        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
8 N% w' L3 K" r0 k# c                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;+ P# P7 w6 H6 _4 [% i  f2 O" }' ^! ~0 Y
        }. y. D! X8 ]& v& k" G/ u' x
        // FDS. r- U7 g3 _2 P3 \1 ~: b
        if( (exsound_select & 0x04) && no == 0x300 ) {" F% c; V/ u! x: e
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
$ X. }' s8 o$ A& F3 \/ N        }; c, T0 f' Q$ S! L& l
        // MMC5
2 H, b- q  |4 M0 m5 K$ F        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {% ~6 ~$ V0 f5 V4 D- f7 G
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;) J9 l3 f% O; E
        }, `) y( n/ x+ O/ T# C/ a& o0 m% Y
        // N106# ~! r0 r8 X: D* Y- g8 M; C
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
, C0 u9 \' b) F9 r% n1 _! h                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; c1 s+ v- h3 g8 j; d* a
        }7 ^! i7 D0 ~: {4 U
        // FME7! M: z- _" l5 Y( A
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {+ o' d6 X9 E3 i5 u2 V& F9 N6 `" s
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;# r9 c( i8 v, S
        }
$ ^1 Y5 S2 g: q2 C6 p& O        // VRC7
. c4 X  _4 U) Z3 K        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {' Z" I9 M" l( r. D
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
1 s" }9 t, G" y/ y/ V        }
. j0 a' H1 \1 p! z' v7 x" ?( C        return        0;
- ?3 T+ v' Z; I  o7 n, |# g}. X1 M- i' b' N; e' L6 ?

# l% x+ N$ Z0 G) X' i// State Save/Load7 O3 f4 l+ X4 L* a+ l
void        APU::SaveState( LPBYTE p )( C2 {3 ^* }! S2 _0 j
{3 f+ J2 Z# z" t" p; D- Z
#ifdef        _DEBUG
2 ?  b8 {+ r' G( I) I! f6 r* fLPBYTE        pold = p;
3 u1 q; o2 d2 H, u#endif/ Y% y' S, Q8 j2 l

0 C% |4 p, b& E  z) u  P1 M& ]        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞6 b( q2 N( A) J( k" B% ]
        QueueFlush();
$ J/ X* T% A+ D) E! o. J# A; A/ C+ Y1 W5 N7 W3 X- a
        internal.SaveState( p );
. n8 N; S  z7 @3 }3 U/ ?        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  `) L( ]  G4 f7 }$ a2 }* U

4 C) T7 v- }/ U$ L4 j% z        // VRC6
4 }6 `- L, l! g9 G        if( exsound_select & 0x01 ) {& w* e2 f1 c  T! m, t1 s  b
                vrc6.SaveState( p );( B5 W4 V  K# m, i+ p! ~8 r# a
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
  I% s, Y* N+ _        }- k$ z6 h; t5 z9 n
        // VRC7 (not support)
. R2 P9 K/ J) T8 {' {        if( exsound_select & 0x02 ) {
- i( D" Y* n! g% s4 U  I, |                vrc7.SaveState( p );3 M5 a- |: q/ f1 V
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding) _2 Z& g5 W3 X- p- x
        }* ^( I/ e/ G' k
        // FDS$ H# W. ^7 V' |2 m  k* [$ N7 y
        if( exsound_select & 0x04 ) {: e8 x/ }2 `. r- S% i3 c/ G
                fds.SaveState( p );; x3 H) N7 Y* O7 O0 V
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 O) V1 s! @! n; `1 D) f* a
        }' B, y& z' @" ]8 \& ~5 k: Z
        // MMC5& y/ H5 p9 X5 Q2 U: j- ]$ f. \" Q
        if( exsound_select & 0x08 ) {
1 a7 K# Y" j/ ?! d+ S' H) D5 c" P& M9 g$ a                mmc5.SaveState( p );
- Z5 w( }3 Z/ E4 p# M                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# p! S3 o# h! M. S. x) q        }3 i) g$ q: j) D' h4 W7 x
        // N106
  z6 u' r1 @' R# w9 ~        if( exsound_select & 0x10 ) {0 c2 c- ]. c, I" u
                n106.SaveState( p );: a2 M6 s4 ]1 ~: p. p3 {+ [
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
5 T& ~7 X" ?  |9 u7 ]* Q1 U        }/ j# h) T3 S  i# i& m& ]. C
        // FME7
4 J; B0 \, g% @8 }        if( exsound_select & 0x20 ) {' W6 [. b9 u& W3 N3 n2 }3 e
                fme7.SaveState( p );
6 a5 C) Y" A" [3 u                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* X3 q+ `- f5 k# d* l$ ]# B        }
: d. L  ]. R" o' l: N2 V) |! ~' ~. F
#ifdef        _DEBUG: I$ I! v0 k' |( s1 I# K; v7 B1 _
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
" n! d9 h0 H! ^1 C3 H#endif
7 r% ?& z; I4 u6 `% e( u; `2 {}4 N5 d( `; k' |0 X) @
- M$ Z) p/ k7 u5 i
void        APU::LoadState( LPBYTE p )$ d3 h5 G1 u/ |7 C( ^. K# |4 |
{& b" l( _, ]2 n# o( @* w' K
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ r& j+ N* @6 X# l( v& y        QueueClear();
1 n- q. c9 o' s# n- M3 K6 T4 ]* V7 w5 c$ b" T. r6 @
        internal.LoadState( p );
9 L% g$ \2 O) p        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
0 k2 X7 K7 ^4 \- T0 h5 d5 `) |+ g# p. Z6 c+ G+ ~
        // VRC6
& \; e- b8 m' @! u7 f7 m: p        if( exsound_select & 0x01 ) {* _0 u+ N4 k$ Z$ i1 M" x
                vrc6.LoadState( p );
' U7 [! r" l0 R( b$ n+ J" ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 }/ ~) g: ]9 x$ q
        }
6 r+ \) x( ], o. C' v3 ]        // VRC7 (not support)/ F6 s& M0 M& h1 o  p
        if( exsound_select & 0x02 ) {0 t: r4 A8 v1 P3 J3 J
                vrc7.LoadState( p );
" b( o. c# {4 v8 |7 G) ^# Z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# b8 C6 ~2 d4 Q& N" b
        }
7 a- w" t0 s" g6 V: u        // FDS
8 Q/ ]* c, H$ |& X3 X2 R        if( exsound_select & 0x04 ) {4 j- o8 S# o- g
                fds.LoadState( p );
' p# C$ J8 o* W( i/ i  f' a$ U                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% c# i! o0 J) J/ p' {' H
        }
' a2 y5 o7 @; k  o        // MMC58 L- r( y. `/ T0 _0 ?
        if( exsound_select & 0x08 ) {
: {6 p# y! C/ S- h8 b" H+ R$ G                mmc5.LoadState( p );
6 Z8 ^. D# Z; G, p9 a% r; T                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
* t* K! p/ E6 t0 x$ n' a. ]$ g$ C        }2 |# J- {6 j' N6 B# I- A
        // N106
+ t5 x! K. U! b9 w' l        if( exsound_select & 0x10 ) {
3 b- [! e( b. B: X" X4 d* m8 E4 F: Z                n106.LoadState( p );2 g0 N9 X+ d9 {
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding6 x; Y, G. r& e' h+ x8 O
        }
: l0 V8 q  A4 F        // FME78 G% C$ }" t0 e- M" P& G; X
        if( exsound_select & 0x20 ) {3 ?$ N9 o& I, j
                fme7.LoadState( p );
1 R6 A; U" O  r* a                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) _; a: H6 g6 R' Z% [; G1 A        }
0 o7 M5 b* j3 f9 v  I+ m+ V}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 8 B( t" s5 \" k3 e/ y
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
" {) w( `/ i7 z6 R- Z7 J! n$ H感激不尽~~
! z1 L$ n* @: ?+ f& L/ u, h! T
恩 我對模擬器不是很有研究,
  h" ?# c3 G: o3 H/ L, o7 f雖然要了解源碼內容,可能不是很困難,! e% I- A* [8 B' I
不過還是要花時間,個人目前蠻忙碌的。4 M% t0 \/ d' U0 [: \

7 r# ?3 f2 B, J給你一個朋友的MSN,你可以跟他討論看看,( a" C) Y. f$ V
他本身是程式設計師,也對FC模擬器很有興趣。; A2 ~! K/ ]3 B* n/ J" M: i9 O+ ~

: P" f5 P6 B, b3 YMSN我就PM到你的信箱了。" t3 t) f# v- S( b; p

9 G1 ~& v2 @! B. H# r$ ]9 D希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
! x" t, U. U/ Z$ [呵…… 谢过团长大人~~
& l% s9 p1 _6 U# e9 A; l
& L" s/ _9 Z( o: O" C4 K! \% z
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 D- L/ N! x9 j( S) E( \4 B/ a
团长的朋友都是神,那团长就是神的boss。
1 }+ _' i: ~6 L) K% W2 g5 S# F
哈 不敢當,我只是個平凡人,5 ]1 L4 q4 o. u2 o
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
$ N- x# R! b: s8 eZYH8 S" x# @7 X: T/ k# ?4 H" t. I
QQ:414734306
3 H  r: \  d; @" q1 OMail:zyh-01@126.com
. I  E, {* n8 Y8 u) L- H; |9 r
3 a/ P6 o+ c2 B, o1 Q/ n4 ~0 o他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ w3 L6 R8 h8 H6 K" N* P- }再次对团长大人和悠悠哥的无私帮助表示感谢~~

: [6 ?+ e. i, D7 i# I不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-25 11:32 , Processed in 1.086914 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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