EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& s  O# k, |6 h% q5 P! \
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! M+ h- o3 G) B; q这里有相应的模拟器源码,就当送给大侠了~~! x, n+ t6 M4 ?. v; Q
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
( e2 H. t0 `7 l9 j7 ^能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。% Y- [, K, b1 R# i5 X) E7 X6 J7 R
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~0 m+ m- c1 L* {, F
这里有相应的模拟器源码,就当送给大侠 ...
, X  E! P+ y1 b% i1 u
聲音部分(Audoi Process Unit = APU):% f/ [2 S1 }9 N  O, d
.\NES\APU.cpp$ r9 C* M3 U' ^2 F# Y: ]
.\NES\APU.h
' A( G1 N3 d9 n1 F' Z! s+ ]9 ^) B: Y; ]% I& Z
1 y9 x1 d3 d' r3 ?  t
影像處理部份(Picture Processing Unit = PPU):
* Q' A2 G# g: L; Z6 W: ?.\NES\PPU.cpp) Q( I' U8 Z4 i+ Y. u% ~9 O
.\NES\PPU.h
% N5 @) e  b1 G! L
! d6 d5 T+ b5 L) A. P$ m如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。2 Q1 L; N" d* h: ~+ u. Q$ w8 s7 _1 K
感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
: G" f, e  Y0 w  _" }2 t) `(由于很多专用术语和算法机理都不明白,所以看不大懂……)* j: I6 @3 S- ]
//////////////////////////////////////////////////////////////////////////
6 Z2 [. k0 c. X3 U1 ^; ^4 n//                                                                      //
0 ]8 U7 t. D2 |( F//      NES APU core                                                    //* u& |+ g2 K4 A( x* F0 Q
//                                                           Norix      //0 O# Z! R5 q% E" F0 _: }# f
//                                               written     2002/06/27 //
* J: O- Y; m3 v) o//                                               last modify ----/--/-- //) a3 X! s- m5 `( j$ {7 @
//////////////////////////////////////////////////////////////////////////9 z# \: ?' H! Z7 ~/ h- U
#include "DebugOut.h"
/ p, M$ x) {2 [9 C#include "App.h"
1 z/ {3 X) G7 O1 |' `6 C6 s: l#include "Config.h"
7 U( R& L$ s% S% C! e& V
2 D- `0 V/ x$ ^& J6 z# R; M  c#include "nes.h"
: W; v+ A" l& @; f) A, {5 O* L2 L#include "mmu.h"' f4 E; ?+ {0 L1 j4 q/ c1 y: F! b
#include "cpu.h"
, U8 y4 q9 y3 ]/ t) K& x#include "ppu.h"
) {4 _6 Y1 v4 n: m/ n#include "rom.h"
: D, R' B- \0 P/ C#include "apu.h"
8 k, @4 e& ~$ z  i7 n. A- J+ x* R% J7 u, x+ L7 e- m1 B
// Volume adjust
5 B# _' k: X" J# }4 a3 g* ?// Internal sounds
/ k, |+ g& X; _: g9 l2 M" d#define        RECTANGLE_VOL        (0x0F0)' f% P; z  P. z
#define        TRIANGLE_VOL        (0x130)
. {: w, y" Z6 v) P! t#define        NOISE_VOL        (0x0C0), T% q7 ]9 L  ?3 t3 S
#define        DPCM_VOL        (0x0F0)' N4 b8 g' W) e0 }0 y' A' V5 e
// Extra sounds7 E7 _2 h. ]8 P) f5 ?4 ~+ l0 W
#define        VRC6_VOL        (0x0F0)1 N, p9 r; i$ H
#define        VRC7_VOL        (0x130)9 l& R$ `7 K3 F: L( c
#define        FDS_VOL                (0x0F0)$ L' [' B- M% H4 h; F4 A
#define        MMC5_VOL        (0x0F0)  U+ _- H2 v+ I, }9 T
#define        N106_VOL        (0x088)  k$ w# u6 S$ d! W2 j: ?. L+ o
#define        FME7_VOL        (0x130). o2 B' U7 ~, h0 e" i. I5 z

3 L* C+ m3 E" V/ L; v, b; H; aAPU::APU( NES* parent )
" U# N+ a0 g5 o9 G! ]' N7 ?{' {! j( e' S+ V- t: K$ x0 t. C
        exsound_select = 0;) m9 x5 j, t! W- o) }

+ }9 a0 D) @+ N8 M        nes = parent;! v) J- H# E. f
        internal.SetParent( parent );
/ v' t( q8 Y8 C8 b# k) V7 f: h( f) @& T' T
        last_data = last_diff = 0;
/ @# d! ~8 M6 z3 i+ w- u, |, V" h$ A% ]- f8 o, `
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );: E* b. q) u6 [1 Z
6 l4 u- X' m1 z
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );. a2 q- G/ X! u
        ZEROMEMORY( &queue, sizeof(queue) );
# l: u. b, i5 L3 {        ZEROMEMORY( &exqueue, sizeof(exqueue) );% ]8 x. n9 I4 F9 W
3 y$ z- i. z" w, J( i: W
        for( INT i = 0; i < 16; i++ ) {
" g! q4 V7 c7 I# d% k+ T                m_bMute = TRUE;
5 Y& z0 Q5 k2 ~  n        }
# g0 z2 Q$ G' ^) b' l: Z}
4 W0 H. U: |( m
, |- c. H. s: r3 ZAPU::~APU()
% D) `1 G* J3 M" [0 y4 j1 L5 Q{! \+ L2 u4 E8 K  v# J0 o3 g: ^
}2 n+ X+ i) }) t0 w
( F) B3 z0 y3 p9 i4 M, J/ y+ Q
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
2 k+ J& a, \7 P9 F{
! ~: u+ k/ {$ T  }% S$ @  z8 \8 S; N        queue.data[queue.wrptr].time = writetime;! P6 H( v6 e- @# K/ B. Z; d2 ?6 B
        queue.data[queue.wrptr].addr = addr;  G: U/ _6 y5 ?: y  M
        queue.data[queue.wrptr].data = data;
* m* o& O) l# r2 K+ z        queue.wrptr++;
6 E+ L  G, k+ ~" T% D        queue.wrptr&=QUEUE_LENGTH-1;8 D. c' t( ^1 x4 n7 n
        if( queue.wrptr == queue.rdptr ) {
% i& W$ V/ N- ?+ s1 Y' @+ q* v                DEBUGOUT( "queue overflow.\n" );8 F' b" S" `2 e& u& J! J
        }
$ o/ O& _& @! c1 O5 @2 Q}. V- i  b1 o8 O7 ]

3 {# h2 J, q/ `3 VBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )9 N& e" l* r! I6 j+ Z& K- r
{5 n/ R. ~6 T& i. T5 C1 `
        if( queue.wrptr == queue.rdptr ) {" y- h& i4 K0 Z) Y( P8 }/ o0 O' W
                return        FALSE;
; g0 e; k+ Y) F0 j" T: ^        }
( u. v( H, [7 j/ r+ Z) D, m        if( queue.data[queue.rdptr].time <= writetime ) {% Z- D+ }1 {; ~3 U7 E
                ret = queue.data[queue.rdptr];, P, H4 h/ {! X; ~! ?
                queue.rdptr++;
/ e1 a5 r/ `- Q3 w' T, u                queue.rdptr&=QUEUE_LENGTH-1;
$ z2 E  f0 }6 k5 L4 _% c' V                return        TRUE;+ w" ]+ x) I6 }5 m' ^0 o
        }
$ D8 i' G% v& ~6 P, g: ~2 K: J        return        FALSE;& k# Z2 r1 B: g, g" C) L
}6 L" ~# _( [9 G5 Z! ]/ S' B
4 R1 W' t/ m4 Q; l( ?8 K
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ `9 N8 {$ ^8 ]
{2 E. I9 p7 ]) R
        exqueue.data[exqueue.wrptr].time = writetime;" x+ Z+ ?- m0 @
        exqueue.data[exqueue.wrptr].addr = addr;
8 ]5 b, {2 z2 C8 {" z' W        exqueue.data[exqueue.wrptr].data = data;; b# a' h) j1 t- `
        exqueue.wrptr++;
+ A6 J9 u# H( `/ n2 {4 D/ j        exqueue.wrptr&=QUEUE_LENGTH-1;$ r9 ^: {; ^" s) b8 E
        if( exqueue.wrptr == exqueue.rdptr ) {
% G: W) F  H- x& G2 n& h7 C. K. c6 {                DEBUGOUT( "exqueue overflow.\n" );
* t2 P4 ]4 X9 m! S3 [        }7 T1 w2 p8 ]' R' g3 f
}
' q# }2 e) u: d* y. J7 M
) X( x. f1 z9 sBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
5 V3 v; I  o' y: s1 d' s{. A+ ^, Y3 D$ H) N, Q1 Y
        if( exqueue.wrptr == exqueue.rdptr ) {1 B5 U8 D+ u. U
                return        FALSE;9 R3 b7 }. u% H+ w
        }  q- S/ c$ E, k* ]
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
) F' d$ F" F" Z                ret = exqueue.data[exqueue.rdptr];& u5 u0 x2 X; L; A/ o' m* I
                exqueue.rdptr++;2 I5 D, |& n& j* y  L! L: }$ w
                exqueue.rdptr&=QUEUE_LENGTH-1;
( j5 a2 a# S' M. c( |" ^                return        TRUE;
; a' W  Z8 ~7 p        }
" ]. ~# _9 t% @# Z4 F4 n        return        FALSE;
) w7 n. f5 y6 r5 W}; w1 B' u" U. x% d/ k) n! D

/ i+ v5 O3 u9 K6 Hvoid        APU::QueueClear()
) C0 o/ h$ X. N8 D  `{2 w, D" D) j! s
        ZEROMEMORY( &queue, sizeof(queue) );
' b9 n5 I% h- X. g( R        ZEROMEMORY( &exqueue, sizeof(exqueue) );4 ]7 H' ]1 I+ t8 Y$ Q
}' _' e. i! W( \9 l4 b& H: }
2 r5 I5 H0 ]1 \1 Y& u4 h1 E
void        APU::QueueFlush()2 T" L) W% C1 t. p7 E/ s
{& u5 y" `* {5 s9 G
        while( queue.wrptr != queue.rdptr ) {
/ ]. u; z( m/ y                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) r) b/ s" }$ c
                queue.rdptr++;
1 @$ `/ {3 t6 `2 l, M                queue.rdptr&=QUEUE_LENGTH-1;! y7 p* ]0 s% G" Q$ W( F$ k) z9 n* I6 R
        }
/ E! L" b7 k, r+ j. m6 U# e3 l0 M* p" A4 b. X4 h% R/ z
        while( exqueue.wrptr != exqueue.rdptr ) {% M2 F! _# B/ v* z
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
/ F) p; ]( P5 R" a# b& R: s                exqueue.rdptr++;
% v$ X% @6 l4 P: G8 Y                exqueue.rdptr&=QUEUE_LENGTH-1;
! Z1 v4 E+ m% s" y        }) r+ m& w9 @: x/ |7 `' Z4 T$ g
}7 q0 B7 L* b$ O9 c2 b

- N6 I* Q0 d2 jvoid        APU::SoundSetup()& f6 G$ q2 ]5 @8 }6 A7 |" Z0 O" l& H
{
& Y' V5 g3 r# t8 m% L        FLOAT        fClock = nes->nescfg->CpuClock;0 e# \/ j) _  L  |7 o
        INT        nRate = (INT)Config.sound.nRate;
$ D4 Z! E3 p. E( V& c( J        internal.Setup( fClock, nRate );! ?' [& ^1 b6 o# B/ q
        vrc6.Setup( fClock, nRate );/ K5 e4 g0 S" ^( a8 F7 v! _
        vrc7.Setup( fClock, nRate );- t; B, w5 x$ }" D8 ]
        mmc5.Setup( fClock, nRate );
. u8 Y8 Z. U' V9 C# b        fds.Setup ( fClock, nRate );
8 Y  P' A% A, n! I3 D% @        n106.Setup( fClock, nRate );, `- S# h; e2 r3 ^1 O+ B
        fme7.Setup( fClock, nRate );0 n9 E8 h. D4 N
}9 I2 I0 N3 K" J' [8 |3 D0 c0 W

4 U8 @, C8 F# s" ~void        APU::Reset()7 Y) T6 H6 D  `- r3 [5 R
{6 f* \3 o) }0 p! ?: S
        ZEROMEMORY( &queue, sizeof(queue) );; [$ w4 B6 w5 y5 Y1 {
        ZEROMEMORY( &exqueue, sizeof(exqueue) );/ ~3 H) Z6 m$ i. R- U2 {

- ^  a2 A( \1 h% u        elapsed_time = 0;' x: [; K0 y! e
2 D% a8 {; d4 U. ^+ g9 {0 p
        FLOAT        fClock = nes->nescfg->CpuClock;
8 t/ b  `: p+ ]5 R        INT        nRate = (INT)Config.sound.nRate;) _- ~( u2 z+ t$ u7 W9 r
        internal.Reset( fClock, nRate );
, L8 L  }  F& V+ w        vrc6.Reset( fClock, nRate );$ A3 O' |7 h+ r/ A
        vrc7.Reset( fClock, nRate );9 C3 z( Q! I) q) y5 F8 g) q
        mmc5.Reset( fClock, nRate );" P& l! t* P0 A+ c. m% z" w
        fds.Reset ( fClock, nRate );
9 u; t$ m* w+ _% _        n106.Reset( fClock, nRate );6 B4 h- f! d1 ^- P( h% x
        fme7.Reset( fClock, nRate );
, G1 a3 I! L7 c! L: _- v* T* x6 g$ U! x
        SoundSetup();
8 S% _- {- V- `}# D1 [' X( b3 h" Q* {2 g

' b' V! T' u2 ?: Dvoid        APU::SelectExSound( BYTE data )
2 |  s  ~9 M1 S) t4 Z# a, h1 d{
0 }" \  F6 O3 q' ]- d/ y& Q        exsound_select = data;
. ~3 P/ u: c! D& _/ w}' B6 i- m# t5 f5 w

2 p; ^$ {8 ]  RBYTE        APU::Read( WORD addr )/ O* ]0 `: h& W! K5 i
{1 a6 v( B6 H# x3 s' H* {" }: ]# U5 B
        return        internal.SyncRead( addr );
# X% R2 p8 \% O, A$ W' x5 P}
: a; _& T6 n2 N% Y7 ~
$ ~# t( N) C9 z' \8 fvoid        APU::Write( WORD addr, BYTE data )2 m7 e9 Z& g, {3 F# v  \
{  X1 O( K- L; ?" K, x
        // $4018偼VirtuaNES屌桳億乕僩
( c& w* R: A. T& l" ?! c        if( addr >= 0x4000 && addr <= 0x401F ) {0 z1 B- x) Y3 ]" g
                internal.SyncWrite( addr, data );
8 i$ H7 n( g& u* j0 o: A                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
  u8 H4 c" E8 L0 x% r" Z+ P3 D        }
* X- W; a  t0 X8 U; [0 V}
6 h! q4 ?6 L" S9 y4 f" n6 O
# y) I7 Q$ ^6 T. Z9 g/ T; k! hBYTE        APU::ExRead( WORD addr )
: V7 @* J1 W3 m: f4 @{" t! T7 W# {! I5 q/ j
BYTE        data = 0;6 j0 K% Q8 L" G: i

% B! ~! K/ \$ z: \0 ]1 V1 E        if( exsound_select & 0x10 ) {
3 V4 d* o& {" F2 m- A7 n6 s5 {( n                if( addr == 0x4800 ) {$ D: o3 j! q7 k$ {3 ?
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
0 B0 z6 G. x( M2 b                }8 m3 W4 Q/ W' G9 Q4 L6 W
        }
, h8 A; N: b5 A        if( exsound_select & 0x04 ) {
  `* l5 E: P9 b8 t3 T/ E                if( addr >= 0x4040 && addr < 0x4100 ) {( e, {+ [3 x4 e1 q' ?( I) B2 N
                        data = fds.SyncRead( addr );
& j- ^) S0 s( h4 Y" ^$ n                }
5 m4 f8 d; W* r) {        }
8 K3 M4 ~! I0 |- l1 e1 b        if( exsound_select & 0x08 ) {
3 C$ Q: f: v. @! l5 v6 Y6 L$ U                if( addr >= 0x5000 && addr <= 0x5015 ) {
  {5 q+ i9 f3 k" M                        data = mmc5.SyncRead( addr );
: _: H+ ^1 @, O. S1 k                }  @( m1 x# a- S3 A7 \' }( K
        }8 ]0 H7 E/ T& R8 k, S; g( ?

9 d9 x6 H  T" X        return        data;: E1 j- x# C$ }  r0 i9 S2 s
}" g/ n+ A4 o( U  I' r
5 d2 H* ~/ T3 k" q2 n
void        APU::ExWrite( WORD addr, BYTE data )
- p& H* {6 {5 L, c9 K{
8 `) g; [* h& O+ I' g        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
, m% x9 ]8 h3 l: K
! v. K6 n( a: m, }7 C8 W        if( exsound_select & 0x04 ) {
5 C& a, W4 @- s2 N+ F! }                if( addr >= 0x4040 && addr < 0x4100 ) {" s6 \- L' y; I
                        fds.SyncWrite( addr, data );
0 G1 k* ?5 g+ ~' o7 g                }
; h# n  F4 K( A        }
- f! l& P; _2 \1 D( A9 x+ p0 T
) g* Y4 E& b  [/ D9 n" I4 L# [        if( exsound_select & 0x08 ) {
8 U" ~  C: t* C% e$ i( m                if( addr >= 0x5000 && addr <= 0x5015 ) {
6 c4 k0 S2 n- H# f! \1 |- x4 e                        mmc5.SyncWrite( addr, data );" h7 q3 ~# U' a0 p  I
                }
' ]2 E) f; o+ B- B( `        }
* X* a: T2 Y& S: L0 a) P}
1 s! ^3 y, l- L. f6 a, F3 F0 l) w8 O, e6 j7 c6 E
void        APU::Sync()
' K9 d' i% _; }7 \# M) b{6 g1 n# F: l3 B# w2 z
}
: V) a9 W0 e' S
3 a0 S/ R8 `% u2 a( }4 @2 Ovoid        APU::SyncDPCM( INT cycles )
: N5 s0 t, ]: A7 t/ u$ e{
, {9 g5 ?; e$ Y% n, u  O        internal.Sync( cycles );
$ s. M. |8 O5 g
# V$ `) a+ k2 z, J! M; @        if( exsound_select & 0x04 ) {  [3 L& [3 q7 F. j3 f& ]) Z
                fds.Sync( cycles );4 b, B4 n5 y! P, d
        }
+ L1 V( B7 H7 e2 v, B" Z1 y- x        if( exsound_select & 0x08 ) {3 T  T8 K* F% `
                mmc5.Sync( cycles );4 |: y. |$ L( m& F4 N- N( a. `9 t$ x
        }, H) f$ Z  V# B7 T; f
}
; _5 h3 r+ p: j$ k6 o+ v  [! Y* X4 y8 I. P" w( H' @
void        APU::WriteProcess( WORD addr, BYTE data )
9 g2 j2 L' W9 A+ _( r{/ }% o4 D/ W+ \" w% n0 |" {8 [
        // $4018偼VirtuaNES屌桳億乕僩& r* E9 y+ g: L0 t# G5 _6 i
        if( addr >= 0x4000 && addr <= 0x401F ) {
, M# g4 Y" K' h; G2 q                internal.Write( addr, data );& O% e( Y4 g6 I! b
        }
$ u+ ?" O) r# m0 p8 a; u}
4 c1 h2 k$ F  K- _  }' F  Y8 N/ I, L- S2 [+ R+ f
void        APU::WriteExProcess( WORD addr, BYTE data )
9 C% Y! |6 e, h5 S- m0 x7 m{
, I# L, ^3 U, I! ]/ K! ~" ?- {        if( exsound_select & 0x01 ) {
  f* P" H3 L7 h7 s8 l3 S                vrc6.Write( addr, data );
. D$ w+ f. V" m        }
$ Y9 ^  J( J0 R7 w5 K        if( exsound_select & 0x02 ) {
, S; L  Q4 m' V- d                vrc7.Write( addr, data );7 `+ u: w8 n4 {* Y# @
        }
" t6 R' ]- a3 u$ G+ v. O* _        if( exsound_select & 0x04 ) {* X) Q. d- K0 B3 R: R
                fds.Write( addr, data );
2 p9 {5 m, E( `+ P8 ^        }
+ j6 P1 [* M- L' \, S        if( exsound_select & 0x08 ) {( e8 h8 n: m# {, I6 w
                mmc5.Write( addr, data );* p* P- `/ V' a, D
        }
* k+ ?1 R' g# y+ q2 E3 u9 `% Z; p        if( exsound_select & 0x10 ) {. |4 i; s; c8 k. `7 ?$ v! B. E
                if( addr == 0x0000 ) {4 {, g, ~6 B1 b3 L! b) U) Z) ?1 d
                        BYTE        dummy = n106.Read( addr );1 B9 f3 ]6 S. h! a6 N
                } else {4 _8 B7 D1 j5 o! I7 O! H2 `$ ?
                        n106.Write( addr, data );
& M+ T; P. ~6 o                }
% W7 B0 O, ?" P* ^- g        }
* s3 D' Y6 t( ~9 o        if( exsound_select & 0x20 ) {" o( {6 l% p3 ^, e: I3 o) X
                fme7.Write( addr, data );" F+ T- W, P; N1 k9 {" {
        }: |. ?/ M) w% f: Y0 G
}' o3 z& x6 Z: J: A. Y7 L. Z6 I

7 o# N- J" c$ Fvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
/ l' r5 ?; c, I1 b, {" w{
" {/ E# M$ t& mINT        nBits = Config.sound.nBits;
+ u) y# s, `1 [1 J2 N" F" P, kDWORD        dwLength = dwSize / (nBits/8);) Z* M$ s7 K4 [, u5 D6 {* J4 q+ I  K
INT        output;0 |8 I- Z" r& [
QUEUEDATA q;
" g  _9 Y& t- C. z4 A) z1 _DWORD        writetime;9 q1 L6 Z# z: t9 n! A# N% `
* O, R8 j# A. U$ \# a8 {
LPSHORT        pSoundBuf = m_SoundBuffer;1 J+ k  [- `8 I% R
INT        nCcount = 0;
( {7 U! }6 n/ M- Z; u- |1 U
" a8 t$ Q) R' E0 [- X- @- f7 bINT        nFilterType = Config.sound.nFilterType;, }' g7 z8 U" Z7 {

4 W, R  \, V$ A* |4 x        if( !Config.sound.bEnable ) {  d6 G2 I) w/ e0 [
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );2 L7 j, z  U$ A( A, Y+ |) C, M
                return;
5 \6 Q; _5 ]3 k        }- p1 m* G; a0 x& H! s

& \1 @, Y8 f" g4 i" b        // Volume setup7 K4 O" P0 `) A  j: W
        //  0:Master
# H* A4 m( \3 r; D' R4 q        //  1:Rectangle 1# Y  J' z5 l1 u6 }0 Y# g
        //  2:Rectangle 2( u6 Y4 \# x& r  O. m' r
        //  3:Triangle
* `. S5 [% s2 J/ R& V        //  4:Noise" }, E# }; T8 f# S9 ?$ L! l
        //  5:DPCM: \* v( q+ Z- }* d/ f0 }. {
        //  6:VRC6& r. \+ o% ]; r7 P
        //  7:VRC7/ B+ E- _2 b+ L
        //  8:FDS
" R% @7 [5 h8 z1 e        //  9:MMC5
/ r8 k% h& C/ S6 s        // 10:N106
: E8 r- p$ w! e/ }9 G% R8 i, W0 D        // 11:FME7: U3 d+ s5 [2 r, u6 q: f
        INT        vol[24];2 ?0 j( H. y2 I
        BOOL*        bMute = m_bMute;
( h, D* w* I1 ^' R. \2 U        SHORT*        nVolume = Config.sound.nVolume;8 d$ W2 [8 `( Z: S  a

9 s+ O1 z  E% ?# Z; ~; _        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
4 \2 G, V1 }% F0 f; ~$ ]) B5 Y: x6 q" {3 i6 X
        // Internal2 J6 s- u# P* o
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
+ u# T# M- E, s( u        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
0 o% I3 Q& A2 q5 ~# @        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
6 w1 \9 d& K* k3 O) I; h/ H        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;8 D* R# {+ T7 ^. T. ]
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
- p1 Q1 S; g3 p' S- O5 w) m; H! K" n4 w4 v( i
        // VRC6
5 r: a5 e/ i/ U/ j% ?: a8 m6 t        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  _, H- g, u- e# Y: |7 d9 u        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 j8 ^: m- K) j: }9 }" D$ l        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 O# c; v3 q7 q. k2 p, L* |) v7 g
) b1 n( U2 `9 d
        // VRC7
( Z/ q+ h% Y; L- ~' k* @6 l        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;$ j; W- s6 {* r! W) }+ @7 m3 K

8 O! r1 n. a9 c: ~: C3 G2 A        // FDS
. B( q9 z: d$ [( C: g8 T        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& p9 L6 L% P( B
1 k4 y0 ]: R8 g9 k: c6 n
        // MMC5
( {2 J) n" x- t- ?8 p) w! C8 @        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, A) w1 v) l: D  _3 M9 v( }) m        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ c5 A# Z6 I; f
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
1 r/ L+ M$ F# ]; c2 I- c
: t; u6 ?1 ^8 H1 R, H& a        // N1062 S( a7 e! O; B1 q
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 }, }- g8 X, I+ z$ h
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 N5 z6 M0 e* ?( F- g+ t6 u* F
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ L! r% G9 l5 p! I6 N
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ x& k" g0 z, r6 [  e8 P        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' c4 S2 Z0 k4 a7 r$ R) ^4 m5 ~
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& z$ [# j. {! T$ M) ]        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, b% ~! Z, b* Y; o4 ]  w% H
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% C8 o% C( A! d  L
2 q& b) p6 F6 l' @& R
        // FME7- p: }3 ?* @; G/ K3 Y" `+ u( Z( v
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;; ]  ], z4 ?" c) V) e2 Y7 @
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;& C  d* J- {) B2 [) B
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  Z1 H* Z$ o' c

/ |8 q! c' u  x//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
. h) b+ V/ G7 u9 \        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
7 Y4 D" a& q1 \9 y9 w. L; T8 k  f$ k) O/ w) o" \
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟6 P  G0 ~' R- O; b( D  ?7 [9 ~+ W" k
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
. I8 d! t8 `8 Z+ T5 x" ^4 s                QueueFlush();, S) n  P, K3 g: s
        }  o- w/ k! z9 F' _8 Z8 z
+ t' a# b2 s& E( V
        while( dwLength-- ) {
5 i7 E' G5 H4 q7 R. n! o8 I                writetime = (DWORD)elapsed_time;& r3 m( b6 n2 h" d) T- l) ~. |

* h+ D" a7 x7 _% w7 X" p0 r3 d                while( GetQueue( writetime, q ) ) {- s2 E7 s) r0 v
                        WriteProcess( q.addr, q.data );
- n  R# Q& [1 W; H  k                }" M% x& O" {( c( _4 X- m% N2 U4 M5 n  j. ~
0 }: O! s/ f" E
                while( GetExQueue( writetime, q ) ) {! m8 E, H1 E7 ~# `) ^, X8 U, S
                        WriteExProcess( q.addr, q.data );
2 J, L, B. {, |- |: u+ Y- g) X                }
7 H& G! u! N' l* C, o
& |# o& Z0 `7 C* x' T: \                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
% A3 d/ r' w3 \) \+ B5 O4 c$ W1 ?                output = 0;
# |; n6 |+ f2 @% _6 Y                output += internal.Process( 0 )*vol[0];& w  _1 I  }# V* J5 C4 X* }
                output += internal.Process( 1 )*vol[1];
# Z) d: S1 q, S' _                output += internal.Process( 2 )*vol[2];
. k. Q& i6 O/ M! f+ H: o& J                output += internal.Process( 3 )*vol[3];: a0 `1 c( y5 b( X' S$ w
                output += internal.Process( 4 )*vol[4];
- a) {1 c2 P; c1 d# P% S2 y. p1 n% f, [5 w* a5 ]- u+ E5 A
                if( exsound_select & 0x01 ) {; x- g. _, v+ R* I  k' D; [- Y# {
                        output += vrc6.Process( 0 )*vol[5];
0 ]9 b7 e0 [8 [. a$ S& H# D6 t                        output += vrc6.Process( 1 )*vol[6];
" _$ t6 B" j+ C# }6 N                        output += vrc6.Process( 2 )*vol[7];
" `6 E1 u; \7 _* l1 k2 t" M; R                }
# a% J( S$ p* g- Q/ }- A4 ~                if( exsound_select & 0x02 ) {
+ T* ]  O# U; j; Y/ K                        output += vrc7.Process( 0 )*vol[8];: F6 F; F. A, E1 ~, _9 Q4 B
                }3 G% i  ]; j7 O( V+ A0 S( S
                if( exsound_select & 0x04 ) {1 \9 n2 r6 Q4 W
                        output += fds.Process( 0 )*vol[9];
% K7 X( X: z1 y9 Z' x3 j# r                }
4 v$ h; B* |: ?% o1 T3 y                if( exsound_select & 0x08 ) {
( z5 E3 X9 u8 i1 ~                        output += mmc5.Process( 0 )*vol[10];
& @) j7 S. o( V8 h$ c; ?                        output += mmc5.Process( 1 )*vol[11];! p) t. e! [* D' ]% d# Y+ L2 z  D0 j
                        output += mmc5.Process( 2 )*vol[12];  |) E. D& M- w: q( O# Z
                }
5 b  J* Z3 \  \  c                if( exsound_select & 0x10 ) {+ k$ K) q; g5 @  G* }
                        output += n106.Process( 0 )*vol[13];
5 M% A. k0 g2 R. A) R* G& D                        output += n106.Process( 1 )*vol[14];
$ e9 j* u- Z, j8 m0 Q4 `                        output += n106.Process( 2 )*vol[15];# M2 Y1 M# Q/ H+ j" B+ W& ^# K/ {
                        output += n106.Process( 3 )*vol[16];
9 p- U; p! q- g1 n  h9 ?5 k                        output += n106.Process( 4 )*vol[17];
9 Y) j4 ^' |5 P8 V1 J( ~7 J' p- }3 v                        output += n106.Process( 5 )*vol[18];4 B+ ]6 F2 v2 G/ _
                        output += n106.Process( 6 )*vol[19];
+ `5 c% @( w/ z, [. h9 p6 k9 v) O                        output += n106.Process( 7 )*vol[20];
: e& z0 d+ _/ _2 K6 p5 w3 |& K                }
5 a9 h# I4 X2 d3 F+ s- L; Y                if( exsound_select & 0x20 ) {; z& z3 @* E* H1 Z
                        fme7.Process( 3 );        // Envelope & Noise
$ P0 y* w# n, \& N+ O4 f+ M                        output += fme7.Process( 0 )*vol[21];
' T$ o% W* B! w. l0 S2 f  K! s                        output += fme7.Process( 1 )*vol[22];- G' A* k8 t% Y- Y: y5 s1 {
                        output += fme7.Process( 2 )*vol[23];# B; P, }3 J9 q' [+ X) S
                }( d5 Q2 M& b% [. G! J( Z  \
! f4 `5 j0 p7 B( X3 w
                output >>= 8;
8 j8 k, M5 E" M" F0 `; O! P  T8 o" G. J4 ^. k
                if( nFilterType == 1 ) {
% ]  I, k7 B7 n0 y  c' h                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
& d* g" U3 B) Z7 J9 C0 d                        output = (lowpass_filter[0]+output)/2;' d9 i7 d* f9 O; M' {5 {
                        lowpass_filter[0] = output;
% c) T- a  ^5 R% M- E- ~                } else if( nFilterType == 2 ) {
: n# M6 r0 E* K+ w                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)1 q' [6 j( X7 }
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;" S: Q* ?, L4 Q) L5 F
                        lowpass_filter[1] = lowpass_filter[0];5 l: i: ^3 V0 {; F$ @" K  h
                        lowpass_filter[0] = output;
8 ]+ E, A3 j" \9 z9 p% c% _5 T                } else if( nFilterType == 3 ) {. g, b. @. z% a+ E
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 b6 D8 x* _6 q/ g                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;9 H0 r8 I2 N( }4 t# |
                        lowpass_filter[2] = lowpass_filter[1];' b' Q  W8 o2 T7 `( a6 Q: k
                        lowpass_filter[1] = lowpass_filter[0];% R- e6 E( i: f/ G  G
                        lowpass_filter[0] = output;
9 o/ @# t7 H0 B  r                } else if( nFilterType == 4 ) {* m+ ?& v9 h* C8 z9 D1 G
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
# _# b2 N; D" F1 t, S0 X2 Y; S5 u                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
. t: N4 ?0 U0 {) o1 I3 o( E7 W                        lowpass_filter[1] = lowpass_filter[0];
. y& c, K5 T1 t' B3 r                        lowpass_filter[0] = output;
4 b: p  ^/ }5 c& Q% @9 z  E- C9 m4 v                }
/ C6 W* C6 w% V) n5 j! I9 m  |( l5 v2 s2 R3 j2 _# N3 O; l
#if        0
! H  @# [7 u0 p8 ^# U                // DC惉暘偺僇僢僩
: u) R! p. ]" n% p: {                {
0 `3 n2 Q% R- Z* r, e1 b, `                static double ave = 0.0, max=0.0, min=0.0;3 I5 l8 g) ?1 O) X% z, a( s
                double delta;/ ]" u) a& \% V9 K1 L$ l/ I0 C
                delta = (max-min)/32768.0;
  Y: }# J& u& B/ q                max -= delta;
4 M4 Y, B$ q7 g                min += delta;/ ]6 z6 v* b& G
                if( output > max ) max = output;- M6 L! X* {0 L' F
                if( output < min ) min = output;
7 L5 I' T4 ]& i8 \                ave -= ave/1024.0;
) r, C- M6 j+ C6 Z: W! L6 q                ave += (max+min)/2048.0;" I5 `# r3 I. z4 r% d
                output -= (INT)ave;, V  w  N: O/ A$ e' u' K  M# s
                }
1 Y- D1 d) C' H#endif( K6 S8 ?8 r* F) A! J6 U$ ?
#if        17 E% J& [2 e' w# C
                // DC惉暘偺僇僢僩(HPF TEST)  P! }* N+ g/ G( @$ Q
                {
: y! m# l. S) r4 e/ j9 e! n//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
( b+ Y, c  Z- E  J0 W+ |, D                static        double        cutofftemp = (2.0*3.141592653579*40.0);8 T+ v. J: d6 i+ ]9 x
                double        cutoff = cutofftemp/(double)Config.sound.nRate;: _, c& R- q/ @
                static        double        tmp = 0.0;. q' B3 U' |( M, @! g
                double        in, out;1 p; d7 I4 X, f6 m, @' {
2 _! [7 x0 x+ u3 ^' m
                in = (double)output;  u: T" q, R+ m* w6 G
                out = (in - tmp);
0 S. r6 E$ V' y  d7 `9 \                tmp = tmp + cutoff * out;
' d+ \. {# S- }& Y/ b( k. Q
8 X5 k% }9 m: o5 n                output = (INT)out;
- O: R) G+ n  s) `) @                }
/ m5 d% e' @$ b$ {) V5 [0 l6 c#endif7 k# U3 V+ y0 P+ f5 I& d
#if        05 c, ]1 r" ]. P& f0 A
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
8 o1 b3 F3 k# x) \                {2 g  X) {. O4 _! c! }8 F
                INT        diff = abs(output-last_data);
, T6 `# U$ D: `' G3 a                if( diff > 0x4000 ) {7 _5 ]/ g3 I& F/ r2 s# R8 ]
                        output /= 4;5 i* B# ?0 f2 `3 k- ?  @
                } else
: Y, h( F  V' I3 ]                if( diff > 0x3000 ) {
# h  l& y) l: _" P9 v  _                        output /= 3;
& s' \1 k% P) V2 \5 U                } else4 r% a9 Q/ r: a' E- y7 v* b
                if( diff > 0x2000 ) {
. s* n5 Y/ G& W) f* [, @                        output /= 2;
  f' F+ q, f( L) G                }6 S6 V" ]6 k! C( z) `
                last_data = output;6 ^8 }9 L1 B/ r) ]$ b7 |
                }7 p6 ]# F* |" @, H( g7 w; ]
#endif
$ t( @7 v- l9 ]+ H3 J" Q, U                // Limit
8 T9 ?2 r$ E- H1 V: j6 F' G1 K                if( output > 0x7FFF ) {
- f# |4 W+ h. |& r                        output = 0x7FFF;. z# \- E& H7 M
                } else if( output < -0x8000 ) {
$ G; i1 Q" ?. z/ A! ^                        output = -0x8000;
3 |- i  p. h# V$ j- L- H                }
. c/ R1 f# V+ M$ B' a
) w, H* [; J# Q                if( nBits != 8 ) {
2 v1 ~- j0 U. c1 {* ]& \- }5 c8 F& S                        *(SHORT*)lpBuffer = (SHORT)output;4 \- S! \8 C2 m8 p# `" f
                        lpBuffer += sizeof(SHORT);
1 |; V# P, c, A. s1 P; f- ~                } else {0 Q$ p; w  |- I, D
                        *lpBuffer++ = (output>>8)^0x80;
- _7 v3 V3 o. f* {8 S2 u                }# Y. B* b! S8 b
# V. F% I. d& j& Q: a5 V
                if( nCcount < 0x0100 )
) B0 l% }( `' I7 c$ P& i                        pSoundBuf[nCcount++] = (SHORT)output;
* E, W' \  ~3 [- P! i1 P1 s
9 G, o1 L) t7 ]9 b//                elapsedtime += cycle_rate;& E' E/ p8 u# ]2 K+ x8 n6 R
                elapsed_time += cycle_rate;
5 v& H8 j% o! }- {9 n        }" p5 [$ t7 q" @* _" U) A3 t7 n
) D2 b# y) A( V& F0 S
#if        1+ n4 q1 N6 \3 m8 |, o
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
2 O0 G4 I  I8 Q. Q                elapsed_time = nes->cpu->GetTotalCycles();" ]+ C7 ]  @2 d% h# {% U# w0 I7 b
        }
$ x/ K" T; U9 R* V$ l        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
! h; p+ S/ e7 S5 I4 l                elapsed_time = nes->cpu->GetTotalCycles();) @4 A. v) d! A" S! E0 @8 b" K
        }$ ]$ O& i# i, `
#else
9 Z: m3 M8 C' h( @: @. j# X$ F        elapsed_time = nes->cpu->GetTotalCycles();
' y& Y8 E* p) D7 n3 R#endif) [. w. V4 }0 [3 V/ j" U
}" t' v! O+ {9 I( d% T

3 a) M$ k/ l7 v1 X' @+ N) {// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: ]( N7 X  i0 ~  J( V& Y0 t9 mINT        APU::GetChannelFrequency( INT no )6 S1 O5 y' o' X3 n0 Z( B
{
6 O) V% P7 P' M; F4 m% m- d        if( !m_bMute[0] ). ^4 S$ N) w& h- T
                return        0;' {! b' Q1 d; {4 I) a( }: B0 M

3 A& ^5 M, O' ]1 d% }        // Internal. }, u/ b  P( W8 E: w! Z2 z: O
        if( no < 5 ) {
5 y0 M) [6 d0 `                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 g7 t" L  C. F$ H8 h        }! `+ p- q. r- u' d# a
        // VRC6
( U! k" m% i4 V2 [        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {* A: n8 B" [4 A) ]) v
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
6 ?. s# \, g# D; d, S0 w7 Q        }
7 p7 m4 Y( C6 Y" B        // FDS5 b6 ^: ~, I5 S, H
        if( (exsound_select & 0x04) && no == 0x300 ) {( N8 V9 {8 p9 e, X" C+ r
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
7 k. F* S/ d6 k+ ~8 o+ `        }/ o: Y, R# U8 R+ O
        // MMC5
9 O; U  E! p) O( b8 j( B: h        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {6 _' w3 X- H7 Q, n
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;* h7 r% M: m$ p4 _2 a7 j' |
        }9 p- n: [. S9 @) ~
        // N106
2 u* j6 i* w4 U  C8 G6 ^/ G/ H  S        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
! b9 P; c2 C: e8 \                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;: F3 u8 c& t# R7 \0 q( {9 p
        }2 Q! l' \6 G; G9 [1 _9 z& u
        // FME70 _  v5 S1 l: j; \
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
. u- f7 O9 L; H0 \) M                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& R6 `! v' ^$ @0 H/ z+ \6 h        }4 {7 I, h  d# R$ E
        // VRC7
. l9 A- ~3 M" P* D) k/ k        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
3 v2 C% I5 H8 E5 c                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;5 D% }- X% `/ Y
        }
3 z, K( C" {  k3 u) w        return        0;
! p8 i2 p/ L% T}& W5 C8 x/ G1 r* f. t. ^' ^
( `  h1 n& g1 x: n! J. G
// State Save/Load2 o1 c; e" G5 Y* A/ B8 {9 I
void        APU::SaveState( LPBYTE p )1 k" B7 Q# m6 S3 P
{
: B* l& J4 k7 F/ }1 Q" D#ifdef        _DEBUG8 b; R4 Q) c) N* ^+ a& Z" _
LPBYTE        pold = p;' b+ }. F$ F% L8 `3 ]! w6 R
#endif
# ?2 L( B3 y1 K8 n8 B( m
* T: `5 W1 R* }# b7 u: F        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
7 A/ M2 c+ S/ T- K# L  ?2 O* Q+ a        QueueFlush();  |; s" [3 P  @- B  F' G7 ]

  U/ P0 U) ^0 u, l  m) ]        internal.SaveState( p );" n/ i% ]' d" y7 Q& W
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
3 O( K0 V! M# \' g
3 N; a9 F( g! R, w        // VRC6( V7 _- D0 }- |5 `( w% O
        if( exsound_select & 0x01 ) {9 \" b% @5 X2 W  P2 ^! f
                vrc6.SaveState( p );4 F& B" {4 i) N* Y" p2 Q: N: o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; p3 X. m% S/ ^4 c9 J7 b# A; y' z& d
        }
& l; n& |/ q( }; `% C        // VRC7 (not support). g$ ]& V" d" {6 G' V& I, r! p
        if( exsound_select & 0x02 ) {1 p2 }4 |0 V; Q  V& o2 E1 O
                vrc7.SaveState( p );
: I  P, Y3 o3 K                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding& g  N* _: G# Z
        }
' v3 M: `* f8 B- }) B7 Z) w0 v        // FDS5 L/ k! w/ k( H8 B; Y) ^
        if( exsound_select & 0x04 ) {
' N9 {+ T+ d! u1 K+ r                fds.SaveState( p );
7 |4 T6 ?3 k$ |; g- o4 s                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ w3 h% T% d6 |, N! t        }
! {. d1 t; O+ R) ^6 ^/ c        // MMC5
* ~0 L6 c' v9 `1 U. l        if( exsound_select & 0x08 ) {
- K, L! [& N1 \, a& v; y                mmc5.SaveState( p );3 h+ [& L- {; t2 z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 P8 @2 `% F6 D  l9 e        }3 I/ c0 Y/ Z' n% ~1 x1 Z$ [0 k, L
        // N106
3 f1 i8 Y- B0 O        if( exsound_select & 0x10 ) {
8 U# U0 `# F5 ?                n106.SaveState( p );
% b2 m4 Z: G5 s3 a8 L) J- w                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
3 d+ e9 Q3 }- v8 d9 G        }5 ~) F  @: X7 E
        // FME7
2 {$ R% B* v+ t1 h3 G+ Y  W; ~* u, l% y        if( exsound_select & 0x20 ) {1 ~1 n# X6 Y1 y1 V& X: R% I
                fme7.SaveState( p );9 ?* T- d, U- `$ w3 K+ w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& M$ |# h" [% d+ K2 o        }
7 f- B  b  y0 ~3 B% F+ ]) |5 F2 r: R' z8 q
#ifdef        _DEBUG
' u" I) o, n$ m: `, T) cDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );2 `0 [) k- J+ K3 Q
#endif
1 i3 Q/ u' J1 N) L+ V}& ~/ O0 ?/ x: d: M, m% M

* Y2 O4 Z" M5 e3 c: lvoid        APU::LoadState( LPBYTE p )! D/ U% E) g, T; o0 B7 \/ {0 J
{' J/ G: u! x; d5 }; c' }
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡4 C0 x# I. K' w4 F3 G1 L( Q+ p
        QueueClear();; {0 g: ?4 i& D( O. ~
5 M5 L/ [9 e4 w# ^& v7 D# p8 U
        internal.LoadState( p );( y: w% i- i5 p/ ^! L
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& C' R; D7 T) k8 s6 z3 {; j# }5 A, i+ G0 Y0 I1 c7 }
        // VRC6
7 Y5 ]! Q( X8 ~. P) [- H" X        if( exsound_select & 0x01 ) {
+ g* ]! q3 J$ a" M                vrc6.LoadState( p );
' l6 h; g* L  `8 X" N( i                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
' s. f. D( @# [. W" y        }
3 t1 _1 q# P" W        // VRC7 (not support)
* I+ Q$ i! L2 V( s        if( exsound_select & 0x02 ) {
0 C: n1 E  F. e- f                vrc7.LoadState( p );
% p- \$ |$ {8 o; v                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding  }( z! S+ `* u
        }7 ]* }) ~* \6 ^8 K: h  t6 \6 t/ ~
        // FDS5 C9 r  I6 I" [3 C5 R
        if( exsound_select & 0x04 ) {
! K( k4 n& q; b                fds.LoadState( p );
, ^/ K$ {1 B2 l2 R! V+ ^( Y9 B                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding: D; v  U2 x, b0 `  _5 D
        }0 W: |- h; w$ ]+ y
        // MMC5
- ?+ K1 [# {3 l9 |# }5 }) c' N2 T        if( exsound_select & 0x08 ) {
! e( p1 L8 s2 v* ~: M                mmc5.LoadState( p );/ h* u: n1 i* ^+ F, s+ [* a$ ^! b
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 B0 O% I, x  N7 P
        }. _4 w' v0 F* C2 K& C" y- Y
        // N106$ f. p: h% c/ S& L, X: B6 j
        if( exsound_select & 0x10 ) {0 Y" b& v7 X+ F- T& R, H
                n106.LoadState( p );5 g# {8 j0 C7 h6 `" h/ H3 D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 q* c7 O5 q* L3 c  ]4 \( p
        }- R- H1 _7 V8 m
        // FME7; ~( \7 `* l$ M( x
        if( exsound_select & 0x20 ) {
7 W$ k. N% [2 F4 K9 e) v4 g                fme7.LoadState( p );, \( l& e, O9 ?+ b( w
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding" P3 Q) h- Q0 y+ a2 Z
        }. ^# J7 F+ l! t1 v
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ; o  `7 n4 b- g4 S2 y
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。- A; }. i$ a3 E/ `
感激不尽~~
/ l6 _; S: T, E9 R
恩 我對模擬器不是很有研究,# k" A' j) b7 X5 X( d1 v7 l
雖然要了解源碼內容,可能不是很困難,' D" t: A8 x: ^  B
不過還是要花時間,個人目前蠻忙碌的。9 L$ }$ }$ W) V' R
% H; L, M1 H4 n& q( L( O8 U
給你一個朋友的MSN,你可以跟他討論看看,9 C$ C! S* L& R4 b; u' d
他本身是程式設計師,也對FC模擬器很有興趣。
: m0 H. j9 ?  y3 y+ ?7 y# _. O8 g  {, A1 ]
MSN我就PM到你的信箱了。" A0 G& N  Q" N+ L- m
  ]' I5 v; ^+ c3 `: ^  ^2 d# 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 发表 ( p  [+ S8 E$ e2 Z$ ~9 p
呵…… 谢过团长大人~~

) F/ ]2 x" {# f* h; v' T0 _6 }4 Z0 k3 s: d9 r1 j
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + b% i" `: Q7 V9 m
团长的朋友都是神,那团长就是神的boss。

4 c7 H( \/ x! b# p: h哈 不敢當,我只是個平凡人,
8 {/ P; A2 J' S4 R9 z要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙! M; G+ h8 w5 f; g& L
ZYH
" c; B! ?: A9 Y/ G  GQQ:414734306
9 x" T4 g1 U; A. M0 R3 I! @Mail:zyh-01@126.com+ N) C& v7 U& Y$ m
. v! P% Q, }# ]1 X4 _
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ' w2 o5 r8 |9 Z# B
再次对团长大人和悠悠哥的无私帮助表示感谢~~
2 z. m) S% h7 P+ ?8 a. J2 }
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-19 07:05 , Processed in 1.173828 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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