EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。/ m1 v* `# a( w  I0 T
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ a: x4 Y8 N. k0 u' |" z! I
这里有相应的模拟器源码,就当送给大侠了~~: u3 Y7 q# [1 b# A" f8 d
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ; [+ J; g* s# x1 a
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
# y9 {3 M  q! L8 E2 M% G楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
+ g7 d/ H! d, d$ {这里有相应的模拟器源码,就当送给大侠 ...
0 P) B) ]: ~" m
聲音部分(Audoi Process Unit = APU):. R- D! c6 {0 A& L2 Q% L- w
.\NES\APU.cpp
5 M, t4 O0 T5 [7 m! Z1 A.\NES\APU.h2 T) v6 H# S' @; B; u

+ X5 c7 V5 e2 l' y, p
" q7 d. X$ b3 B0 |) p影像處理部份(Picture Processing Unit = PPU):
! G) n  q/ u6 f% K4 B.\NES\PPU.cpp1 o7 C, S2 x8 o+ ]# N. l" G4 D. }
.\NES\PPU.h+ ^* E& }" v# U, ?0 ]
% q( I4 V4 S% p  `' V& u- X9 N
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。9 {8 I1 a* h* g& ~1 B% P; l8 B
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 ?6 R0 Y2 a# R5 G
(由于很多专用术语和算法机理都不明白,所以看不大懂……); {8 f$ y5 d/ q- W
//////////////////////////////////////////////////////////////////////////
$ H1 g  K  H1 ?( H( C4 N# d6 Z//                                                                      //$ H7 e) o$ r3 q: s& N8 w
//      NES APU core                                                    //, R& f5 I& ^0 ~$ u' M; r7 G) [
//                                                           Norix      //
5 [7 V5 A- n$ M' }& M. X" o1 }//                                               written     2002/06/27 //
3 o: X) c! S0 L, e, q//                                               last modify ----/--/-- //9 D1 U# n/ h* r9 E/ M+ T( G
//////////////////////////////////////////////////////////////////////////
+ A# R0 |+ D; M- D7 p( W7 |! c! g#include "DebugOut.h": f: t% o9 ]2 G) Z( y6 J6 @% p
#include "App.h") h# t- m5 m# a+ t6 T
#include "Config.h"# I5 j* e: a1 T# y3 U! O8 d" s

8 e- ?8 z" D, A- G" o4 ?) X- Y#include "nes.h"3 ?7 U4 n: n7 W( Z
#include "mmu.h"
6 C: Z4 {& Y8 A#include "cpu.h", f  }; E5 q3 ]* v; r
#include "ppu.h"
9 q+ X6 ~- M$ Y6 o& ?#include "rom.h"8 d7 M. j8 W3 ]) P* v/ w( s
#include "apu.h", A1 |# L" d) C

0 |9 Q$ P; ]* C// Volume adjust* h& n3 m7 U% {/ W* ]  u
// Internal sounds) d( s9 |8 w# @
#define        RECTANGLE_VOL        (0x0F0)% e* y& R+ j# l4 b! F
#define        TRIANGLE_VOL        (0x130)
# P2 N8 V; c$ o8 Y1 Q& d#define        NOISE_VOL        (0x0C0)
. @3 a7 m% F* X0 l2 O6 ]#define        DPCM_VOL        (0x0F0)0 n9 R& t' G+ j% h' z1 \& {2 u( R
// Extra sounds
  l0 w: O- m7 A, w#define        VRC6_VOL        (0x0F0)5 j5 B- v; `8 s! s  i) W5 ?
#define        VRC7_VOL        (0x130)
3 i+ k! k) ]/ d#define        FDS_VOL                (0x0F0)
& ~& z" ]" ]' c; e4 @#define        MMC5_VOL        (0x0F0)
7 A6 u$ J2 E% R% l$ C#define        N106_VOL        (0x088)
2 L+ ?1 s$ N" B7 b0 N; E; Z6 L, X2 c#define        FME7_VOL        (0x130)
* G, R$ ~* [9 c
+ r7 l; b  F+ M* R  h( K! d- IAPU::APU( NES* parent ), R* F! @( N. s) z, S3 a
{2 i2 r8 i2 G- c8 A
        exsound_select = 0;
3 e3 ~6 `. S8 H, |, G3 p6 u
! [; X% X5 ^3 M# R9 f* n8 `        nes = parent;. F, ]( t5 d- x* m2 t" H' @
        internal.SetParent( parent );
, i8 |. U5 P2 T) X* j  X( v
% i2 q) n; A4 Q6 B) Z2 n5 y        last_data = last_diff = 0;+ _4 `0 r" c# A' Z" H5 v

5 j& s7 G; z- h! ~: }        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
3 J( P7 z" `7 B7 Q" V1 T; C# y9 f* G+ m+ V! R+ X$ D
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
5 h3 \2 }2 u4 {) n        ZEROMEMORY( &queue, sizeof(queue) );
" |! K& h" a" X5 f        ZEROMEMORY( &exqueue, sizeof(exqueue) );" `; b' k7 G  M+ t) E  T$ y
! a' |- {( z/ [" z9 l4 {% X
        for( INT i = 0; i < 16; i++ ) {7 T" O* o$ l0 ~, B% ~! ^: ^
                m_bMute = TRUE;
8 T3 v- e$ g. c7 J        }: n1 [" N* C4 I5 K9 p* |$ T
}- U4 r) o  F) \8 e7 O& C

1 X  i1 h" _2 m9 fAPU::~APU()
% y. O8 J* M0 ~; U& M; o* ^{/ X" U7 `6 Q1 d  C% c) n! k
}- x: N* {/ }, v+ l$ E$ M5 T8 q
5 b( K0 u& |& {1 ]. x3 `! ~
void        APU::SetQueue( INT writetime, WORD addr, BYTE data ); F; I  H8 ]/ L7 |% P2 Q1 c4 [% Y
{5 V& s2 G) Z, C
        queue.data[queue.wrptr].time = writetime;
5 E% R4 a( z, N  b; v        queue.data[queue.wrptr].addr = addr;
, f) d7 o  L8 ], @2 i! o        queue.data[queue.wrptr].data = data;* R. p4 c# ]8 T  ^' ?1 P: r
        queue.wrptr++;
& w) z% N7 [. A( n- I2 U        queue.wrptr&=QUEUE_LENGTH-1;
1 D4 p" M5 U  n        if( queue.wrptr == queue.rdptr ) {
" [" S" y) t- n* r* U8 p3 ^+ S1 X                DEBUGOUT( "queue overflow.\n" );
) y1 n! P! y; L+ b. d        }
* @/ T/ E; g, {# R. w3 J, T4 V}% x: U2 v  c$ K" b0 K0 X% T+ I

5 f# U4 `( b2 j" w& {BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) _2 \- R3 q- o+ g* n3 b
{
; o) v: \; h- i6 M        if( queue.wrptr == queue.rdptr ) {
! p$ j9 T% ?' I1 ?: j: _                return        FALSE;% t* _* P# m" w/ b& E# E
        }8 _4 r- ?3 J4 I/ h. w* g4 z
        if( queue.data[queue.rdptr].time <= writetime ) {7 q/ \, q! _' k3 p8 _1 N1 L
                ret = queue.data[queue.rdptr];
- F2 |" A2 U2 \7 {% r5 M                queue.rdptr++;- n5 u" c- t. b8 E: W9 {
                queue.rdptr&=QUEUE_LENGTH-1;* I) Q3 l* q$ S0 z; G- [. P2 m% p7 M) U
                return        TRUE;* K8 ?- S; h; p- J9 y
        }* }$ ~" g8 D' F7 u4 z
        return        FALSE;, E' G3 N3 f( r1 E5 y+ `  u" ]
}
* F, k* j6 I. y% s- }
' w7 h; u/ `* E6 pvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )4 O7 h2 G1 ?5 x% N' ^9 e
{7 \3 _2 _6 [! [. s- O
        exqueue.data[exqueue.wrptr].time = writetime;
9 H0 R  v4 O6 y        exqueue.data[exqueue.wrptr].addr = addr;
+ O- T" W# ]9 s4 [        exqueue.data[exqueue.wrptr].data = data;/ O4 ?) [' t- J8 L3 H8 H1 s' S, C
        exqueue.wrptr++;
8 \8 O1 C) Z, e& U1 E        exqueue.wrptr&=QUEUE_LENGTH-1;
0 W6 v7 v, K2 b/ d- A% {4 e2 y        if( exqueue.wrptr == exqueue.rdptr ) {0 b  n' N; D/ H$ N8 h& s$ Q
                DEBUGOUT( "exqueue overflow.\n" );0 s0 Y3 N' ~. d/ `8 E" M
        }0 h6 L7 G: Q9 K4 W8 b
}( p/ Y, C* Q$ _' U' j9 Q! @

% c$ }$ [  q( j, \! u, t$ @BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )/ `- k2 d# q4 n9 F
{) ]8 p/ P) _6 M2 X5 e$ C% ^' B
        if( exqueue.wrptr == exqueue.rdptr ) {
& e. Z5 k3 q9 c* X8 W                return        FALSE;
9 w' q$ c% S  \; F# G: }" L5 l        }( f& _7 a9 Q& Y) g$ m1 S7 E
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
. ?- a0 N+ W; ~                ret = exqueue.data[exqueue.rdptr];
! _& b$ F0 h' R: o+ R% Y  ]                exqueue.rdptr++;
9 r. N! ^, ?4 g" |1 S( d% v2 e0 j                exqueue.rdptr&=QUEUE_LENGTH-1;
1 j% c* ]' ~* e2 @                return        TRUE;
% }9 X3 z7 `. I4 Q; R4 R& b        }7 B/ D  {9 I) e; Y( y% {( `- [
        return        FALSE;
- C2 i! Y  S" \$ m. C}7 ^0 ?& d5 L% V! T/ U: [. c6 u
, q. C9 `5 l3 C4 g
void        APU::QueueClear()
; R' e2 s& f+ g3 o. [4 O8 n{
% l1 Q7 C; _+ |        ZEROMEMORY( &queue, sizeof(queue) );
& A, V+ e& m3 W+ p9 l6 D        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ }, i" y9 p% G8 c* c6 N  f}
, h- w5 b# \, ?" g7 d. m0 R0 S2 z( @: F, {
void        APU::QueueFlush()$ z# k4 b2 D9 R7 Q
{" u2 X- g# J6 Y& U- x" H) r3 C
        while( queue.wrptr != queue.rdptr ) {3 ]+ L5 R$ N6 [% n/ M; B
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );9 L7 J5 {, c9 ?5 ?; p
                queue.rdptr++;0 \3 |  m) P! r5 l5 W
                queue.rdptr&=QUEUE_LENGTH-1;
3 h: B" i4 b5 j5 h        }
) ~4 u7 i6 L: ?8 ?5 T
# S2 @6 z2 s1 [* V& e' b        while( exqueue.wrptr != exqueue.rdptr ) {
0 f6 o+ d# P" H$ \6 y                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );" h' A) O9 u7 w, z0 J& a
                exqueue.rdptr++;
2 T1 B* H" T4 d! z                exqueue.rdptr&=QUEUE_LENGTH-1;; ^( W3 N9 Z& U( J% P; Q0 {) J
        }
1 E6 Y9 \+ P6 G* e! A) y' b}  E; y* F: [5 Q

% a1 Z+ ^& U3 ^6 w! Gvoid        APU::SoundSetup()
) n7 a: n  Z2 U3 g0 c{  t5 E! ~* a( z3 g& p
        FLOAT        fClock = nes->nescfg->CpuClock;
7 Q; J/ A+ f7 L! Q' `) w. ~        INT        nRate = (INT)Config.sound.nRate;+ _4 R1 G. k8 m& k
        internal.Setup( fClock, nRate );; U. t& P$ F3 L, o2 Z+ {
        vrc6.Setup( fClock, nRate );
7 H& U9 C* d* S) f7 K, R- z- @        vrc7.Setup( fClock, nRate );' v' e; _" c) w
        mmc5.Setup( fClock, nRate );
. F9 ^+ `2 j: k6 g. U        fds.Setup ( fClock, nRate );/ z& ]& m# k6 _* N9 J0 }
        n106.Setup( fClock, nRate );
9 o! [8 O5 Q5 s/ K        fme7.Setup( fClock, nRate );
0 \  I# Z4 J! D/ {+ h}. \8 S( V4 D' x( H
" X/ v( u6 o: I! r( u
void        APU::Reset()
. o9 D: B/ W/ N; |3 l; P{
# E% p8 [7 G1 o6 N! t4 e( L5 }5 r+ M0 w        ZEROMEMORY( &queue, sizeof(queue) );% x/ }( m' J+ m4 K4 W
        ZEROMEMORY( &exqueue, sizeof(exqueue) );8 v. ?+ q" a& g% V

3 b4 t9 E; j$ d& W2 s        elapsed_time = 0;" s& k. X6 Z! {$ N% E; w' t
' B8 M! f( k  r; r7 b
        FLOAT        fClock = nes->nescfg->CpuClock;
" `3 A( U- m2 C        INT        nRate = (INT)Config.sound.nRate;
, c- z; C7 x8 D* }+ T" f) i' H' `$ N        internal.Reset( fClock, nRate );
- Z* e9 ?0 n: n        vrc6.Reset( fClock, nRate );
( M' _- j$ ^! f$ h8 D        vrc7.Reset( fClock, nRate );
& G- s9 o$ C: k8 y/ g$ S        mmc5.Reset( fClock, nRate );
- x9 W$ T, `* `% a4 f        fds.Reset ( fClock, nRate );
7 }6 C: q% p+ v4 l- @        n106.Reset( fClock, nRate );
6 r* r$ d% j& G' y% G  ~: ~        fme7.Reset( fClock, nRate );0 r9 ]0 e0 N8 v( g( ]
! u6 p# i  X8 b- Y8 ?- ^5 M+ \
        SoundSetup();
% C' n# Y( a# P( k}
7 X: Q5 q9 `4 f, y2 X' R
1 _/ x( O' q  w( e& e1 y" G2 Ovoid        APU::SelectExSound( BYTE data )- e7 D$ |5 q3 X/ H
{
* g. m# G  P3 g  s# y* h        exsound_select = data;
; M$ T7 J! M6 I2 v}5 ^' {1 V7 j. }0 q2 Q/ n" ~
5 U+ H" a8 c- Z* ~. T
BYTE        APU::Read( WORD addr )( i2 W) R5 W# o& U1 U& H, t, E+ [+ U
{
  Q% z4 `9 j: [' F        return        internal.SyncRead( addr );- i5 Z# [; w9 X' e  p
}
; R7 F. l6 H0 I- q/ Y* W( r0 U# r5 D
void        APU::Write( WORD addr, BYTE data ): v! z( S6 A) w( y, _
{
& h" M. x- ^/ v7 ~% `3 \5 M        // $4018偼VirtuaNES屌桳億乕僩
2 p& }6 ^7 L# Q% |  j        if( addr >= 0x4000 && addr <= 0x401F ) {
7 j6 }/ N2 J  R$ ^                internal.SyncWrite( addr, data );
* z% n4 C) y: y) O/ _$ T                SetQueue( nes->cpu->GetTotalCycles(), addr, data );, z0 H3 ?3 i! Q8 t5 p( F
        }
# g$ I) V' a' W/ [' G}
( S0 }4 I' H% l/ U6 }3 @- y$ Q, y7 e4 D7 W
BYTE        APU::ExRead( WORD addr )0 ~* c' F. C9 b
{0 U, t2 w) f. E1 i
BYTE        data = 0;
3 S  b1 M1 T( c) Q4 ?) |' U5 {" L3 a4 [  n. j
        if( exsound_select & 0x10 ) {" ?1 g! i; y  R8 U% q& q
                if( addr == 0x4800 ) {: T+ r* Y1 q$ D( b3 K
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
$ X9 n5 G& ]; V1 e0 Z* |                }+ [! f, R* D) c4 s" b3 a
        }) a  ^9 I6 d" L
        if( exsound_select & 0x04 ) {
  |4 p0 d' c+ o* b                if( addr >= 0x4040 && addr < 0x4100 ) {9 y% W9 _& P+ ~. ^
                        data = fds.SyncRead( addr );, _2 d, |" t. s( x0 _, T
                }2 C8 X% T2 O- A3 {% T2 H" o
        }: n4 s- P# F$ }! Q$ ^! Y( Q+ A% Q
        if( exsound_select & 0x08 ) {8 P5 d* a7 l8 |9 c
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 K' F6 h* \/ S/ |$ d" @* V7 p5 s                        data = mmc5.SyncRead( addr );
- E3 d0 t$ q+ v                }- o+ a* n: w! Y
        }0 o+ |! w& H7 O5 q3 t

& C; _9 {$ t, d1 ~$ c7 @- g        return        data;/ P1 Z, e- J. E& \
}
6 v. B% M! ^+ a7 s& r+ d( c3 m
8 M! v& y$ x4 A" wvoid        APU::ExWrite( WORD addr, BYTE data )
* v9 ~- T. Z: y3 X{
- E' h* q1 l' ]  H4 F, T0 _5 u        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );: a# Q( \7 J5 A% M5 q6 J$ ]

2 P! f' n) L8 R" L1 O        if( exsound_select & 0x04 ) {% \2 P7 x$ n1 s
                if( addr >= 0x4040 && addr < 0x4100 ) {
7 e# W2 p) f- A! e9 w6 E                        fds.SyncWrite( addr, data );2 F8 U. i4 T: e( Y& }2 E* a) V  ]
                }
, Q2 }  G% t/ N        }
0 _! _" f7 ]- w0 \* E# D! v
+ s9 K' y: |& [2 P4 E* Y        if( exsound_select & 0x08 ) {8 e6 z! e( b. d  C" N8 [$ @, E- e: ]
                if( addr >= 0x5000 && addr <= 0x5015 ) {
% @6 }1 |% F; E, B  b                        mmc5.SyncWrite( addr, data );
3 I% E5 q" s# K, \. E+ k# d                }
+ l- u# z) n: y9 p$ @        }
  _: ^. o* Q+ V9 V( v9 [}- I+ m  [3 u- H, k
" D" I7 C/ v. @4 H5 h* _$ _9 m
void        APU::Sync()( K$ r: q* J: `5 x& u* Z# `
{2 h* Y! C* {7 m/ a7 Y9 y1 y
}2 O" z& C' s$ C) Y/ l
4 w0 ]1 ^8 Q6 ?5 c
void        APU::SyncDPCM( INT cycles )
/ T" r2 o9 V  r* z  l{. j+ V9 n0 M2 Z- h% s$ p1 x, }
        internal.Sync( cycles );
9 {, T0 U2 p9 T4 U* j  s7 Z2 h# o0 V1 C2 L5 z
        if( exsound_select & 0x04 ) {9 ~1 |: T) m  ^: E& {, a. i9 t
                fds.Sync( cycles );
6 {; b1 u- y; ]0 C        }
& S  E! R- w  c/ b        if( exsound_select & 0x08 ) {! F$ J: s  @* M) s2 x
                mmc5.Sync( cycles );
$ z. P$ y7 j/ P4 a        }
5 A6 _# J# i3 U}& b9 d/ N0 c, |2 S& h
' i; M+ J% g( @+ G( ?/ I
void        APU::WriteProcess( WORD addr, BYTE data )! }; f: z4 Y& q* t) K4 c4 P
{
1 P$ e. o& ^; C& ^. l! q$ B        // $4018偼VirtuaNES屌桳億乕僩7 w" Y6 ]0 N% \& L+ t: y1 c+ I" \
        if( addr >= 0x4000 && addr <= 0x401F ) {
) a0 x% x/ X- `* h6 [  }& m                internal.Write( addr, data );
+ x2 {3 F4 c7 o7 m        }8 r0 b9 n9 V' U1 A  w
}
& ?$ N& R/ w) O, k* @
( q# i& x( E% Z! k; N& Ivoid        APU::WriteExProcess( WORD addr, BYTE data )
' q% k7 y. o  ~7 f1 M{
# b8 U( Q: ]( u, U3 y5 o4 j        if( exsound_select & 0x01 ) {$ ^2 d; h; V, R
                vrc6.Write( addr, data );
6 B4 k& e+ R6 g        }
( L. [0 W: F& k+ T, A        if( exsound_select & 0x02 ) {4 D. B$ M8 W  ?; o; }
                vrc7.Write( addr, data );; D( K1 w( H! T  ?; r
        }- V. y' }8 [+ M
        if( exsound_select & 0x04 ) {% D1 E$ v7 x: o1 O: a5 V
                fds.Write( addr, data );
! w3 \, O; L% }* Z. E' c! l" Z* S6 e% ~        }
- Z% {6 f4 A8 o2 e        if( exsound_select & 0x08 ) {
2 B' d6 [! r7 g9 |+ q9 p: Y                mmc5.Write( addr, data );* x! O2 C( Y! o9 U0 R
        }# a  h1 K& |9 `# j
        if( exsound_select & 0x10 ) {
! j0 k! D# J+ l3 h; ]9 ]4 i  h                if( addr == 0x0000 ) {, k5 O! R8 @% |& w5 k' ^- r9 t. h
                        BYTE        dummy = n106.Read( addr );
7 k# z# k# q$ [# ~                } else {
" R# t! e) I0 M3 `% o( F                        n106.Write( addr, data );- s2 J+ y* s+ Q8 T0 t6 `3 w& l
                }
& K9 x  P+ {& l! s; ^% {        }% X  s8 a0 f( A( p  u: H0 ^
        if( exsound_select & 0x20 ) {8 x+ I( L7 h0 D/ L  \
                fme7.Write( addr, data );
. R/ l; g& e( x5 e  [4 S/ [+ V* \        }$ O7 p$ ^6 L% ~, V8 v
}
9 z/ K, i) _) }5 i& H* }/ f
4 G- \( j$ g8 c# e  k6 wvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize ), P) I* g+ z$ l" ]' p
{. B2 {, |" t5 `' W) z" ~' M! x
INT        nBits = Config.sound.nBits;
( v/ L$ K$ R, H9 @DWORD        dwLength = dwSize / (nBits/8);  g8 ~/ }$ q# E) R+ l1 O& t
INT        output;
6 U, L' Y5 T, q) WQUEUEDATA q;; r* x0 ?- h0 [" m9 s5 Y& E
DWORD        writetime;1 P( J. l! O1 ^* ?" o: F- c. ]( O

" X9 W( t9 B& Z# J, q% CLPSHORT        pSoundBuf = m_SoundBuffer;+ c2 u$ h4 l  P# Z& C, B4 v
INT        nCcount = 0;
6 K2 z; w5 ^2 w3 p! O% s: q/ k( |9 j( S5 j; e6 E
INT        nFilterType = Config.sound.nFilterType;9 W, z6 ]  o5 O1 j3 B

3 N) V* N$ U% F# i1 P6 X% M( u- I' s9 U; v        if( !Config.sound.bEnable ) {
# L0 q3 r* o7 H  L0 ]" ^7 m* l8 a                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
& l5 ]& y( _; n                return;" g' i4 E# F+ F+ M" d1 v
        }
( J1 _# M3 I! h! G3 f% W
% n9 ]! f) ?5 }5 [- U0 p        // Volume setup
$ t/ `% t7 q& R        //  0:Master
8 O8 Q' y8 d5 ~& D; e7 C, N  ?8 }        //  1:Rectangle 1
' d' i/ z& u0 T( g; @% e        //  2:Rectangle 2
5 o% {7 i+ {8 D3 q        //  3:Triangle! z: l5 ?* }% k
        //  4:Noise0 T3 s& I1 P- `
        //  5:DPCM
) S3 t- o$ h3 `  ^' a& P        //  6:VRC62 h+ n* _  E8 m3 l
        //  7:VRC7
  x6 c, [* W) w0 @2 q% |. {        //  8:FDS0 Z* G" @, [. b% q
        //  9:MMC5& Y+ v1 y) b- a- l
        // 10:N106, f4 K/ Z3 `# u1 i! L% f
        // 11:FME7( @: d6 H% t- V; _
        INT        vol[24];
/ N, G2 t$ _0 D/ b5 U9 _        BOOL*        bMute = m_bMute;: V' B2 a: m+ a% x
        SHORT*        nVolume = Config.sound.nVolume;
  T; }6 J4 d6 l* p
9 H" K! Y$ a. I        INT        nMasterVolume = bMute[0]?nVolume[0]:0;* h; ]  x( w- @
3 C6 X/ ~- c  j8 j8 @
        // Internal3 _, p8 G: d% o' G
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
$ W6 @# f( U# O- L0 b# f& `& N2 S        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
# Z8 {$ t( Z* ?$ b8 @# V        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;0 w3 S) p/ m& N; `
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;& D' O3 Z# h4 x3 {; k
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
) o" A, J$ Z1 B) F- n% Q. {& }2 K1 U7 v1 C
        // VRC66 q/ g! K4 E; ]+ z! o4 u
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) D" T9 w* y7 x2 ~        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 K. A5 i8 g# C" P/ |; G        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;( e6 W5 C/ r) [
. O0 d  F. D! @; s% B) |
        // VRC74 }6 c2 m3 @8 @* L. n
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;+ M' B3 u* C1 z2 b6 _
4 A" Q$ L. q2 H1 H8 j7 [* Q
        // FDS
/ \/ I; l1 X3 n, e' ^& c* y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
9 q, E" r& A4 N7 ?
5 S9 M# F6 V2 \8 }4 u8 i        // MMC5
2 b$ b3 _! M6 b8 q, z& b+ s        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
/ @1 _6 O# R$ c3 G  Z        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;) a& V9 M2 H. k. X* s9 X, G- l0 ~
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;: m. N, _( t! L" i
' E3 k7 d! j( ?' Q# P) X( u. ~0 `$ j
        // N106$ F5 r6 ?, u8 U0 J" k6 N
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 K3 T8 K3 u/ V. K
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; I( K2 N" `5 a0 F/ G" X        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 m7 s3 M$ i; ^  K( H/ S% K+ F* R; E
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" R) B# J9 }9 \$ j; \0 N, A
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: N% ]8 J6 w: ^* A& t- L
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 Q% L" M, {/ Q9 Y1 i4 X        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, M6 M9 i5 {, q, I+ s6 _        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, D, a- x1 j* }6 `7 q/ t. \% }. B, r1 |+ F& i# g0 |2 G
        // FME7
2 x: \4 o5 P. o. [        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ h! x- a: f7 I        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
' ?5 h2 F5 \# ~5 ^9 L        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ n, ]* ~7 s5 _1 v

2 c  `1 }. c: J9 l8 c//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;) s2 H8 ~2 W7 ]+ n$ q$ l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 [: ~- e* [$ U/ ^4 J

* [0 w% R0 i0 C3 X; j/ w3 i        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟8 r! d! Y3 `( `& Z' E# }! G
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {+ f5 I8 d: h/ X8 h) U
                QueueFlush();; e0 p, J& A" f8 o  I# h" l
        }" E6 I& p$ Q$ i) Z
  m; R3 t( h2 j. }) x% w4 j
        while( dwLength-- ) {2 W5 ?& m. z8 R
                writetime = (DWORD)elapsed_time;1 b8 L! j. V( o3 L

  L$ {2 z) p( i! O- c                while( GetQueue( writetime, q ) ) {7 w" E. \( b9 E( j
                        WriteProcess( q.addr, q.data );
* U" I1 ^5 G  h! S; V0 O9 V  j                }7 A  N9 P2 W- v7 y( `2 C
' }( a! H6 t. }: Q6 T, U
                while( GetExQueue( writetime, q ) ) {
) j/ r% _7 _4 _% g" \                        WriteExProcess( q.addr, q.data );
, d2 P- O; R; O) _# J, y. h6 k                }9 r' Z5 Y) l! x9 X: F
% {  P; _) Z$ a# Y1 _% {
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME70 ?/ S$ p% }6 L
                output = 0;
  i: f' W' v; J5 K" y: ^' g                output += internal.Process( 0 )*vol[0];
# F7 S( p1 U9 C! p8 F                output += internal.Process( 1 )*vol[1];, p; T: T) E+ E$ {, M. t+ ^9 A
                output += internal.Process( 2 )*vol[2];$ Z' O% q8 q# m5 H3 ~1 }
                output += internal.Process( 3 )*vol[3];0 T! \$ `5 Z! ]8 E0 |
                output += internal.Process( 4 )*vol[4];
( G# [3 w# g# {  F9 P8 _8 r3 l9 ?2 p" [$ L6 N. L5 P2 @3 }
                if( exsound_select & 0x01 ) {
! R, k; U, U' [: r3 S, N                        output += vrc6.Process( 0 )*vol[5];  R6 M; I+ E8 F7 U0 i( z  ?' W) q
                        output += vrc6.Process( 1 )*vol[6];
& x" y2 r3 q/ a1 t                        output += vrc6.Process( 2 )*vol[7];
1 G) h: L: k9 ?. ]( c                }' Y) ]; i. M7 F  {( `1 D/ m+ V
                if( exsound_select & 0x02 ) {
4 N, a- G9 b5 U+ u$ Q! W* [                        output += vrc7.Process( 0 )*vol[8];, O( P4 i: u0 }- _: K% S
                }
3 W% p0 n  i+ S, y' n! v8 g* T                if( exsound_select & 0x04 ) {
. p+ L( c, Y  W8 F$ K: D' H                        output += fds.Process( 0 )*vol[9];, }/ Z1 ^9 e( C, w) W
                }
$ D( S7 Q0 B4 t8 X$ t8 ]' o. T                if( exsound_select & 0x08 ) {, A- D6 @4 [, k& Y: R1 p1 M' h3 i5 b
                        output += mmc5.Process( 0 )*vol[10];
9 {  \; g$ M6 p$ x8 U                        output += mmc5.Process( 1 )*vol[11];
6 W) V0 E% E  V3 U) H                        output += mmc5.Process( 2 )*vol[12];2 G# i( F4 Y; e; m2 B  c6 X7 [: A7 p
                }. ?/ w# w3 J" \5 S) }0 E( k. n4 j
                if( exsound_select & 0x10 ) {! J- i  s+ K9 }# \, H5 u* p
                        output += n106.Process( 0 )*vol[13];: p) T, ?" j# v2 F7 W
                        output += n106.Process( 1 )*vol[14];
  @: k" ~. Y, w- U- }7 }                        output += n106.Process( 2 )*vol[15];
. F" S8 \0 l, e0 p. c                        output += n106.Process( 3 )*vol[16];% c$ W8 E' \  {0 V8 G4 w2 |# B
                        output += n106.Process( 4 )*vol[17];+ t; q! R# j. v3 ^' j
                        output += n106.Process( 5 )*vol[18];
% K, h( q' O) s; _) n) s                        output += n106.Process( 6 )*vol[19];
+ j4 ~6 ~7 e# V* i! ?. P" F" X8 j                        output += n106.Process( 7 )*vol[20];
0 l. R$ ]; C2 z2 v+ ]                }
, {- X, g- C5 z! m$ R                if( exsound_select & 0x20 ) {
( H- G$ X. Q4 L( f                        fme7.Process( 3 );        // Envelope & Noise1 ~+ x* O& T1 I( R0 n
                        output += fme7.Process( 0 )*vol[21];% K4 c1 u& P& c
                        output += fme7.Process( 1 )*vol[22];
; a3 H3 c7 k: T- Y6 P2 g                        output += fme7.Process( 2 )*vol[23];
2 I# x+ K# c$ v, p9 K1 T                }& H8 ?' H- @% \/ X1 L. p+ N
: p- _9 x1 s9 f3 _" p
                output >>= 8;8 ^+ K7 U& |9 F, ]# I2 m

, ]% H7 S; r: V1 u$ E" `                if( nFilterType == 1 ) {: Y9 T6 @5 X4 E' T0 g0 b
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
8 C/ y0 C7 r- t  M' Y$ W                        output = (lowpass_filter[0]+output)/2;
2 U4 y' h: v4 @3 ?" Q                        lowpass_filter[0] = output;
. a) w$ a7 b0 @! g4 n, u* l1 x9 v& y2 v                } else if( nFilterType == 2 ) {3 W: @" j' m) ]( h% L; P* V
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
  B. j* W3 y! U* j) @' i/ A                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
; G) N7 K) N8 E+ J! t: ?1 G                        lowpass_filter[1] = lowpass_filter[0];
$ ?0 {' o* k8 g7 c  l                        lowpass_filter[0] = output;
; ^$ T4 {5 X: a5 X+ C( P/ l: K; a                } else if( nFilterType == 3 ) {
* C5 x/ ?" k1 k! G                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)( W" k8 f% `8 f$ W1 G  F; a
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;- }  E7 D% I2 y8 M: Q% l+ ^
                        lowpass_filter[2] = lowpass_filter[1];
/ |7 S) Z3 W# h                        lowpass_filter[1] = lowpass_filter[0];" j% t$ n+ z* o; }/ f' e
                        lowpass_filter[0] = output;+ s- J/ m+ L0 _5 b0 ~% e1 d4 V
                } else if( nFilterType == 4 ) {/ f4 d& M( d9 x4 W' N* g& E0 h
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)4 ^7 M' f6 T0 {
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 ]+ w( j2 U- u( H
                        lowpass_filter[1] = lowpass_filter[0];
) K: S  e: Y* _" R" t                        lowpass_filter[0] = output;
' N1 V4 v! |1 X* {) g$ U$ y                }
  y5 u9 s, x/ [  ~1 F- l
6 F. M8 }8 I" I, s1 k7 H" x#if        0% X7 Q& x5 G, r
                // DC惉暘偺僇僢僩' k) k+ K/ u( i4 @
                {0 x7 g- U* q# J' ?6 C5 u$ k
                static double ave = 0.0, max=0.0, min=0.0;, h) e/ J" E  `  M. |. R+ A
                double delta;+ X# Y, x( x3 I" r2 N" }
                delta = (max-min)/32768.0;
0 U" j8 P2 K, U4 E+ t                max -= delta;
& U- ?- a: c* K* D                min += delta;' ]7 ^5 M/ H: G) s+ l3 @3 X0 d5 [
                if( output > max ) max = output;) A1 Q4 |6 g& y9 l* O! t
                if( output < min ) min = output;1 _* v- K, q9 {# o
                ave -= ave/1024.0;
3 V, k6 k% Y# t. w6 X                ave += (max+min)/2048.0;
4 ?; D5 m3 @0 t  P6 Q$ b) X                output -= (INT)ave;
7 U% O- g% _2 j9 n                }
7 |, f- _) ~4 a5 w; W0 q#endif: e; o0 w2 \. t, y0 T2 u8 [
#if        1
: L; t+ X; o" a9 q                // DC惉暘偺僇僢僩(HPF TEST)
3 \4 |6 r" L# n6 H9 F. ?9 q4 j                {7 i) ~: Z8 l5 x0 R  F3 V2 |, @. O' i
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
7 W- U% C5 F& V- V4 {9 O* u                static        double        cutofftemp = (2.0*3.141592653579*40.0);
& y+ U% d8 Q- D! T& H                double        cutoff = cutofftemp/(double)Config.sound.nRate;' `/ |6 {7 {1 z7 f
                static        double        tmp = 0.0;
5 R5 x8 B# ]$ \, L0 [                double        in, out;
* n, \! i2 Q- G9 D. E1 P0 ^8 a% D. b5 @# @1 q! P
                in = (double)output;
5 N; Q& o3 s2 a- s; n                out = (in - tmp);0 f( V  E/ r4 e. m- c  x# f
                tmp = tmp + cutoff * out;
* c" v4 v$ b. r: a9 x
$ |, |7 m& H6 V# p6 n, [: ^* O                output = (INT)out;
+ V0 o& w3 K" a; ?4 S. j! p                }$ p& Z5 z# _) U- f5 `, ]3 I
#endif: m5 p- p# H4 D
#if        0
1 A. D" j( k. V) q8 A                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
2 W: ~; m+ B+ Q9 \6 \+ g                {/ H$ D& _& g/ x8 G+ \6 m8 ~. o0 F4 ]
                INT        diff = abs(output-last_data);
! t. T  p/ r6 g) S                if( diff > 0x4000 ) {6 }  H# D6 O  ]" e
                        output /= 4;  R/ ^) J8 S1 ~# `' H) g
                } else 8 F" V$ Z" o* g
                if( diff > 0x3000 ) {
1 Z: h7 j5 Z& ?                        output /= 3;
+ }8 u- J+ f/ {( L9 e, K                } else, l+ e0 {5 m+ u& s
                if( diff > 0x2000 ) {; L% _2 J( f! b4 G) r8 X, e
                        output /= 2;
% e& c, P( [0 g7 y: _6 C& p  U                }
! k, B; y( }9 a, l                last_data = output;
0 [( G& ~4 Z: D4 k# ?* ]                }
1 x: H1 j4 X% L- m#endif; M0 k0 g3 T2 w
                // Limit
: I) j7 B9 O4 K                if( output > 0x7FFF ) {
% M. d+ v& b; N7 h/ [                        output = 0x7FFF;
+ c7 ?9 g4 a  t0 J, ~9 @( ?7 m                } else if( output < -0x8000 ) {' H# _- J) w' g( H* x
                        output = -0x8000;
, W1 f. _' J7 g# x6 V1 `                }/ h: g0 R9 f' r  p5 p

9 v5 r) k, x; R  Z. c; p                if( nBits != 8 ) {0 b. ~9 o, C0 W; _
                        *(SHORT*)lpBuffer = (SHORT)output;0 c( {0 J4 ?2 K! f- s  g9 o
                        lpBuffer += sizeof(SHORT);" S+ {; f' \! ]% o  a
                } else {
0 s8 x# }. \2 d, ^) |1 r                        *lpBuffer++ = (output>>8)^0x80;
* u2 J; |2 I7 N, {. @                }, U9 H' `* Y7 y& `
6 [7 S% U# d! Q4 O+ t0 O* i
                if( nCcount < 0x0100 )
8 q/ U, B+ N, N) S7 Q                        pSoundBuf[nCcount++] = (SHORT)output;
. u* E+ ]* y9 b
; ?; r0 s/ o" l//                elapsedtime += cycle_rate;/ A/ h+ u! W' r+ T4 [
                elapsed_time += cycle_rate;
' k* A+ ], m. ^. f" M        }2 |5 y+ M; X8 ^

& d& R7 M; h9 B8 o; _# D#if        15 R+ _& I) T- j6 w4 {0 V& y& @1 i
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {/ m" z  f' V6 w. S0 @
                elapsed_time = nes->cpu->GetTotalCycles();5 d+ a! R3 Y4 B! v+ U- I
        }
5 {% x$ e" m1 w' u. Y, o        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
% p8 p. _* X# m9 m( T; w                elapsed_time = nes->cpu->GetTotalCycles();$ Z* u+ }; [6 a. }, i" j6 `2 y* ]; T
        }
# v' B# E) f+ C- c! j1 [3 L#else; s0 w  \0 M% v- |8 e6 M+ _
        elapsed_time = nes->cpu->GetTotalCycles();9 B# T3 d& u" |7 n+ }& J
#endif# }& l/ ^9 `* j
}
7 H5 R" D5 `2 A) L
6 G0 [& x- ~5 }" T& O// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)3 A3 O, V! ?* j. k% Z* `$ h
INT        APU::GetChannelFrequency( INT no )3 s8 @: h+ K0 d0 t- U
{
6 z' _) \. {+ l: i6 O0 J        if( !m_bMute[0] )4 a; K3 R0 X3 m- ]# |1 o
                return        0;3 q3 [% x. N, `$ N: i

, H; p* J! m8 u/ P9 g) i        // Internal
" j, s5 t/ X, w        if( no < 5 ) {
" W+ z% n9 |. n8 A" b& K3 t& N0 r                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ O6 ?7 N- e+ M; z' q, _
        }
/ ^2 s5 @8 ]; f. W% C9 \8 [        // VRC6
9 ~( X# R6 t6 t' n8 X" I. o/ Y( a8 r        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {/ x/ Q4 Y7 }2 M+ X! b5 T
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;, {5 J' J1 F+ f/ L: l* u4 t' ~; o
        }
" [, M) f- z3 V' p2 c) Y        // FDS- w; N3 @" ~3 y
        if( (exsound_select & 0x04) && no == 0x300 ) {7 z# s  ^, b3 W4 L4 I
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
+ h) Y* i1 {+ y4 W7 b7 y        }
$ d# K; f; R$ @- _        // MMC5
" A# _! _' J: h1 i& T        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
& {$ t  w1 \; D& ~9 o( w                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
- C' z6 U! f" f) F        }
9 B) O& ]! j7 G0 T        // N106
) n5 j& s# t$ n5 q0 F! @$ c        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
  Y8 l( H( w; E' f: l7 a2 c  J, ~$ x/ j                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
9 d; C2 n) a- v        }/ S7 K; H* B& i  P9 {) O  o' j
        // FME70 I  \; u" h: F
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
+ F0 W# F3 R& M" C6 M# q7 L% Z                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;: ?1 H- B2 |9 `7 K
        }, i8 ~) x8 G# |( {
        // VRC75 i* m4 h3 S; p
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {" R) n7 {  r. W. R0 [8 y
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;; O7 Y: K; W4 g' q
        }$ I+ C! ?& B7 \2 h+ e3 Y  x# o/ U
        return        0;
# T0 b& ^; C1 B" o! T}& h& B0 M8 A* M3 m( _" j: m

5 o, `$ V6 ^. M( U8 V' B" ?// State Save/Load2 c: D0 e, u, A3 F# o* X
void        APU::SaveState( LPBYTE p )
9 r8 t" h, S, i+ p{
* I, O8 l! \# ?- B& x% I3 j#ifdef        _DEBUG8 \5 d8 M1 J" F0 Z' \% P7 M) P
LPBYTE        pold = p;
! t+ s5 S/ B6 i. x, g& Q#endif
, w3 t: j, \8 I3 Q9 U6 \, ]1 r
0 D3 T0 Q2 r+ W. g& L        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
. c( N4 S- ?3 Z* T8 V        QueueFlush();$ _# J+ V. D0 k. _

2 F% G9 n2 S* ~        internal.SaveState( p );
. Q, U0 S0 ?$ O+ g* c3 K& n        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding) v7 S. P# k' p3 g' H1 ]

" ^# P% b+ ]+ a        // VRC6
0 `4 R0 O6 z0 a5 b% F7 T7 `        if( exsound_select & 0x01 ) {
1 @( Y5 l2 e) l; _$ \                vrc6.SaveState( p );
$ e1 q/ g! }7 N  t                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
+ b" R  |3 Z2 `/ M. O& }        }
$ [  i' y% p0 A6 S2 K1 q        // VRC7 (not support)- L0 q* P7 N! b
        if( exsound_select & 0x02 ) {. A2 v' n8 ]7 c
                vrc7.SaveState( p );
0 v; P# v' k. f1 f                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' l) H+ t! U# D+ X+ P
        }$ ?) P; k7 ]$ Z+ O# a  b1 G5 h% b# H8 P
        // FDS
1 t: z, ~* H$ r+ |% ^4 X9 F) U* A! j        if( exsound_select & 0x04 ) {  i, M5 E$ N0 j7 m  E
                fds.SaveState( p );/ a  l! j1 ^1 V( b/ i+ g& y, k+ i
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ }, m& V% U7 V  a0 g        }( K+ w  v$ i' D. n; ]# A& X5 u# T
        // MMC5; S6 q+ J, \1 H- R  y; D
        if( exsound_select & 0x08 ) {, v. J- p* J5 U( M/ u8 \
                mmc5.SaveState( p );! S: [# d# R( b7 N& B; @; ^
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
" Z1 ~9 f- i5 a  `% H+ T        }
+ x" ^$ N3 e( h4 X/ D, K# ~        // N106. a# ]: V; s0 E0 R% r2 N
        if( exsound_select & 0x10 ) {! X% b+ x1 R5 d1 E
                n106.SaveState( p );3 X8 }( w& r% n1 _. p
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding1 h; @$ {$ Y5 c% L2 ]3 Z
        }
9 X* [" N  j/ H        // FME7- c+ Z' {2 S' q1 {! ^
        if( exsound_select & 0x20 ) {
4 ^# n7 X. ?& l* O2 E7 s( I2 P9 R                fme7.SaveState( p );
- g2 F7 m: O# d! ~                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
* o; j# y, }1 k4 |5 t* G        }0 X7 @* U8 x, n" }1 V
- m5 T& x# h9 Q5 q; x# {( n7 ~4 k  m
#ifdef        _DEBUG4 K) m% S% G) P: D4 }8 ^' `5 I: Z, x
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );7 I$ N% k# M8 O3 O9 L
#endif9 ~# M$ {5 q) x8 X$ G& m
}9 c9 y: }$ b0 J2 f. R
5 a3 W0 L+ l& j  d, g7 d7 a
void        APU::LoadState( LPBYTE p )
# a) n+ [- |' s1 O8 L  D{
5 g! i/ H1 a7 v0 E3 D        // 帪娫幉傪摨婜偝偣傞堊偵徚偡5 @7 I, v& u- @7 |  a
        QueueClear();
. D* W* C: P* w6 E" g; h9 j) e
) z5 G, v/ W8 _* w; K5 S        internal.LoadState( p );
4 e( k( y! h1 `2 l8 w8 `        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: Q# `3 }$ D, n8 D# T
2 o: E9 S7 d, S9 B% \. V" ]
        // VRC6% o& N, Q/ ?- t8 |  u3 A9 G6 ~
        if( exsound_select & 0x01 ) {2 t  T$ S: M+ m% U
                vrc6.LoadState( p );+ Y$ u3 F4 z( g% F- l% N" J. N
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 q' o1 P; Z& P3 C) H( M
        }
0 Z3 ^0 f; M, F& j8 G        // VRC7 (not support)
. z( \8 r; a! x7 Q5 X        if( exsound_select & 0x02 ) {( E: n. o* w) j, V' @8 U5 s
                vrc7.LoadState( p );- r9 M" }1 o0 k
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 Z  p1 s$ U1 o/ p  M        }
1 W. _8 w/ x+ K* `! r/ o. m2 ~2 p        // FDS" |" Q8 `" W/ m; t% k
        if( exsound_select & 0x04 ) {% P0 h% v4 f. C1 ]. s  e: ^
                fds.LoadState( p );
$ v+ c6 q  H  \1 Y                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
) A$ U5 I4 I/ a8 {$ q1 t- t: T        }
$ g! u$ l8 Y6 D& H, K9 {6 ~( Y        // MMC5$ {+ n* ]% V, b$ p3 A! s
        if( exsound_select & 0x08 ) {0 V8 a& `( V8 _7 p5 O9 g% y
                mmc5.LoadState( p );
8 ~3 `9 ^; `; ]% D# e- B                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 Z" g( v4 J' P* m- G
        }
0 g5 G" Q$ D' z, @$ U: F8 i        // N1060 t+ G1 t: }0 z5 j+ e
        if( exsound_select & 0x10 ) {
5 F3 p# p7 q$ M( N                n106.LoadState( p );, I5 ?" f+ i# h, O1 e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding7 r6 d! D; Q* z) v; T, U  m( m9 c; V
        }
, L. O- _: E4 }- I# y8 n        // FME7' H3 y5 k! t( W8 A9 \& S$ }2 Q
        if( exsound_select & 0x20 ) {
- M. _& W  Q" s9 m2 {                fme7.LoadState( p );& U) v. P0 ]' t, X1 O: q4 x: Q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 J9 t, X9 n/ J! Z! W        }' E" _: ~# k% v3 A1 m
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 : t( F7 L% `6 X) o& D. }. \1 |
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
/ I5 h. l4 _2 {- S* `" a6 n" d2 g$ j* j感激不尽~~
! U. D  m4 f3 G" v7 n, ^+ i
恩 我對模擬器不是很有研究,
' q1 F- c2 V* o) K( v雖然要了解源碼內容,可能不是很困難,5 F" F# W4 w3 r# n5 A& w6 L; C- s
不過還是要花時間,個人目前蠻忙碌的。5 {' p: i, z. ^: Y/ L
; d, N# g$ N/ e  B% L1 V
給你一個朋友的MSN,你可以跟他討論看看,
' i) W9 x  P& e) ]1 x他本身是程式設計師,也對FC模擬器很有興趣。
7 h3 _% R5 f1 Z1 i# |4 I' R6 X7 i( w5 F2 F* t
MSN我就PM到你的信箱了。8 }; T7 Q- g2 _  Y( E8 u/ T- _
  H2 G' Q/ Q  t3 y5 {
希望你能有所得。

该用户从未签到

 楼主| 发表于 2009-11-9 13:23:59 | 显示全部楼层
呵…… 谢过团长大人~~

签到天数: 80 天

[LV.6]常住居民II

发表于 2009-11-9 16:02:29 | 显示全部楼层
团长的朋友都是神,那团长就是神的boss。

该用户从未签到

发表于 2009-11-20 13:13:25 | 显示全部楼层
原帖由 独孤残云 于 2009-11-9 13:23 发表 2 C# M# h  Y; S2 \$ D2 Q
呵…… 谢过团长大人~~
4 b& M0 Q! N- G6 M, Y5 S4 v

1 }4 `: |  g2 m! r% _' W哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , x% h0 C5 `) F- K8 ^
团长的朋友都是神,那团长就是神的boss。
9 K& H+ e9 P$ n" @$ ^: u
哈 不敢當,我只是個平凡人,
" x$ a% R; V4 J# E. ~1 m要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙* @8 A" ?' C. n8 ]. B7 Q
ZYH
$ S) N; |, |! Q* wQQ:414734306
4 {1 _1 {/ Z# K; k) }Mail:zyh-01@126.com
% x, z$ ]* O% T0 l( `9 ]0 A" ?0 W  T; q. K/ V+ z
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
  L+ B* M; j4 w1 O! q# c! \再次对团长大人和悠悠哥的无私帮助表示感谢~~

1 O( X0 i, U4 z' x% T8 j不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-15 07:51 , Processed in 1.093750 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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