EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 b& H, m' W9 }
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 F3 L* Z  l4 r* a5 A这里有相应的模拟器源码,就当送给大侠了~~1 \0 k  W. Q8 e0 j2 N, n
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
& k% C# A: G/ I" ?7 b6 V! G. ^" V5 c能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 h' `) c9 R2 u: N( e; Q3 s
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
* p/ K  Z! I' o7 q+ L: w" \8 K: ^这里有相应的模拟器源码,就当送给大侠 ...

& L1 U* x$ S2 l2 A( [( P聲音部分(Audoi Process Unit = APU):7 ~, q4 M1 k; Z0 x
.\NES\APU.cpp
8 h; V2 S1 O, S5 C0 `7 U& D.\NES\APU.h6 }4 A  W3 ?2 @
) W' `: b, f2 t- u& g: J
4 E. h. d, ?6 _* K9 F9 `& H3 w$ I
影像處理部份(Picture Processing Unit = PPU):
& T3 x; X! T5 e% S1 S.\NES\PPU.cpp
; m2 `8 t2 z+ |% S* B) y.\NES\PPU.h
' w8 O& A' A% Q2 O/ A# k
* g9 x+ a8 ~6 O# C1 L( _" g如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:, ?9 U# V0 Y. [- G- P
(由于很多专用术语和算法机理都不明白,所以看不大懂……)+ I/ O3 T2 R: K. X
//////////////////////////////////////////////////////////////////////////
1 K% q+ O3 i" s. R" f0 r( o$ V//                                                                      //. U" f0 N+ j# g& b1 u
//      NES APU core                                                    //; [6 w' A5 e' R6 d# w1 `
//                                                           Norix      //& l) x  E" {! c1 [
//                                               written     2002/06/27 //1 v# h' B( S6 G! T; r8 D8 B
//                                               last modify ----/--/-- //: H3 T" s% z  G% o
//////////////////////////////////////////////////////////////////////////& t, _6 C* I3 e$ D- \! h, ~0 M% i
#include "DebugOut.h"; Y5 e! |) q9 J' u' G% d
#include "App.h"
! h: G" V/ ^4 H7 [" D2 ?#include "Config.h") ~% J$ g* T' J6 P( y

  e& d. l2 L' U#include "nes.h"
- X$ e( ?$ W# e  p#include "mmu.h"7 c; t( k! q6 S
#include "cpu.h"$ z4 X7 ~- m5 L# T6 C
#include "ppu.h"' @! H: M2 h* a" o% X" {, L
#include "rom.h"5 O' ^+ d/ u: r/ V8 l! q- Y5 s1 l
#include "apu.h"
, j4 I4 |8 j4 `
; E8 @* K0 x0 V3 @7 G2 k) \// Volume adjust$ `) p3 H9 H) Y
// Internal sounds
1 k( i3 I3 L, X" A$ T#define        RECTANGLE_VOL        (0x0F0)6 l  k, X7 g% C7 Y
#define        TRIANGLE_VOL        (0x130)
+ q" o' h% }& Q4 U$ \! @$ d1 ~#define        NOISE_VOL        (0x0C0)6 o0 _  q  j* a5 w* }6 c. k
#define        DPCM_VOL        (0x0F0)
8 P& |4 E0 M: }4 A# J// Extra sounds
9 N. }* ?7 {, b6 B# T" _#define        VRC6_VOL        (0x0F0)
$ g2 o9 t& ]; m( S. i, A- x! t#define        VRC7_VOL        (0x130)- Y* a9 ]) K; H5 r
#define        FDS_VOL                (0x0F0)
' A# c4 {5 k- ~' O8 C8 l#define        MMC5_VOL        (0x0F0)
) {" t% c  @% _0 G9 u. z7 @$ G#define        N106_VOL        (0x088)
8 h: r+ ^5 k" X" L5 f#define        FME7_VOL        (0x130)
0 t  ^! W# w: e4 i: S7 x3 Y. ~( ^9 A
  R3 f- \* M& k! BAPU::APU( NES* parent )
& x3 I! V' S) X) t! h- b{5 q* C  x( \0 J. F
        exsound_select = 0;9 M) \# [8 F( _# K8 o7 k

6 v; K) A0 D: q" T5 E/ y        nes = parent;. n8 ^7 S0 n8 A5 S! f/ V
        internal.SetParent( parent );
. Y  v2 Q+ d1 j& n9 z3 `
4 M  ]6 b" @( |- {& h3 d        last_data = last_diff = 0;, C' d* ]. A* w( i. n

( d$ `  N" a) r9 G* n        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );" {2 @" c5 }' y0 @: Q8 g# j/ y
4 P: t7 p* t: K8 p* ~, L3 ]
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
) s9 s3 `1 Z% q# a' r  j        ZEROMEMORY( &queue, sizeof(queue) );8 l' f  B: w$ {9 |6 j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
8 b- l8 H: j6 Y. p$ n, A) a& o' K
        for( INT i = 0; i < 16; i++ ) {% g; S0 B2 |/ ^0 b3 T
                m_bMute = TRUE;
2 e. c! _( V( c        }& L* s" V1 ?- N$ s8 A
}! z; z" U  H; [  s
6 k+ R9 E; H& h7 l6 N! [5 I  ?/ K
APU::~APU()
8 \1 K3 Q4 H  C{
* L) L% B3 ?- B) }$ K3 N/ [}2 t3 M; _8 m2 \# Z8 ?! l9 ^
( t  p- M+ a: j1 o- n
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
; r. `7 \/ z) U) f% b{9 ^! o9 v6 W2 H# J+ H- T
        queue.data[queue.wrptr].time = writetime;$ m( ~- a2 x: B, a
        queue.data[queue.wrptr].addr = addr;8 U# A' C; M9 R; [: v
        queue.data[queue.wrptr].data = data;3 v+ G" k/ y6 g# W$ b
        queue.wrptr++;: [6 k* U6 X! l' T: }6 B8 Y9 r
        queue.wrptr&=QUEUE_LENGTH-1;- g0 F  D! s: E5 i! f
        if( queue.wrptr == queue.rdptr ) {, L2 `) g# C" H, h
                DEBUGOUT( "queue overflow.\n" );  w. I; y( N8 L' {
        }- ^' I( E. R7 A, ^! V
}1 `: k) y2 \( z5 r, O& t
# }6 L& l$ f$ l, V1 i4 s
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
. H# _: q# X) T) H! b{/ x) W6 t* a+ ?( t
        if( queue.wrptr == queue.rdptr ) {/ U) B; F6 |4 L1 m( n9 `( Z! p, Q
                return        FALSE;
2 i( d9 z1 M: E3 c& f1 A        }; S% P9 y# x! s  r5 r
        if( queue.data[queue.rdptr].time <= writetime ) {
3 p, Z6 L( z! g7 P% u                ret = queue.data[queue.rdptr];
$ {# {1 s8 o% y' [& Q( ]' }                queue.rdptr++;
/ g& J! [1 g1 j+ _# v% `7 R                queue.rdptr&=QUEUE_LENGTH-1;. e+ x; |2 C3 x+ }1 l- U$ m7 P! w
                return        TRUE;
" e0 z+ j  _9 ]* p" b! G        }
5 i+ f$ w8 w  N6 ?3 T5 f        return        FALSE;
: @7 a' g! P3 @) }0 `+ F}
9 K- ]5 S# q* w& j+ n7 V# }) T1 s5 i% I: G! B
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )0 m$ h  a, O3 s2 f/ w% w" L, t
{
5 i0 J+ W+ u, A4 [: c- `        exqueue.data[exqueue.wrptr].time = writetime;; k; I' c* L2 C* F! k' V! k
        exqueue.data[exqueue.wrptr].addr = addr;# o* P6 [, j' S1 x
        exqueue.data[exqueue.wrptr].data = data;9 [: \8 d0 F) U7 v5 X$ t
        exqueue.wrptr++;
) g; x, z5 J2 {$ L" Z  n        exqueue.wrptr&=QUEUE_LENGTH-1;: U$ Z" s- u5 F' `. l: Y
        if( exqueue.wrptr == exqueue.rdptr ) {
, u; k. X5 G& b5 h+ `0 l2 ]                DEBUGOUT( "exqueue overflow.\n" );  `1 p* [. s2 j/ x. w: ^" N
        }
; h  m' F7 H4 N/ A& y% p- i5 ?}% b" X# \. ^' Q3 f" ~8 O
4 q; _2 U0 _" s6 w
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ f8 z9 C" n$ ]{
! S3 E7 i) z$ Y2 f        if( exqueue.wrptr == exqueue.rdptr ) {0 H8 x! p- ^" d8 h9 B" u% J
                return        FALSE;
# T+ k# i) k: E7 k7 J        }3 E/ w2 z1 X1 A3 I
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {6 c5 v; k0 {) H3 }5 d5 U
                ret = exqueue.data[exqueue.rdptr];
5 U) }( y* D# E                exqueue.rdptr++;; \! s* t7 c+ z. Z
                exqueue.rdptr&=QUEUE_LENGTH-1;9 L# t1 J$ B+ h* a
                return        TRUE;
0 Z/ M) W3 h" R! N* w7 s        }8 h+ v( s( M( [, Z) ~
        return        FALSE;3 e0 e/ I& o4 X; g) e% |
}
5 \& `1 y" I6 z' }% l
" Z  S& W# x$ ~; c7 pvoid        APU::QueueClear()$ d9 |2 i0 r; m# y- i% j
{( S; j. ^+ C1 X* |, ^( U) Z& k
        ZEROMEMORY( &queue, sizeof(queue) );) g- X; }& ~/ z, @- @
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
6 M1 R+ a. N  _7 V}
# Y% {2 r% v5 g4 Z$ a* U- z0 R: x" h) d5 ], K6 |' ?
void        APU::QueueFlush()
( u3 h, q) G. d{
( F: b4 c! \5 S2 o+ h        while( queue.wrptr != queue.rdptr ) {
. l/ g" q' F& r/ f( {4 E# }' V4 {                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );# q, V8 m4 Z% q/ L4 U8 p2 K
                queue.rdptr++;
4 Y4 M$ U8 L* Z                queue.rdptr&=QUEUE_LENGTH-1;$ l- k& X* @- s" b, U
        }- {6 l% U: d) D; {

& [+ q- _! g# e1 g        while( exqueue.wrptr != exqueue.rdptr ) {
8 }) X" `9 K5 t) t                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );4 J" S0 w; P7 B  c
                exqueue.rdptr++;5 \9 P- Y1 k5 k) I9 U( ^9 l$ f/ u6 p! O
                exqueue.rdptr&=QUEUE_LENGTH-1;, F, A( A% F! M# z1 l' A1 S& K
        }
; j6 U+ ]# \- F. j& Q. t+ d: l' B. h}4 c# k, H4 b# f; M5 Z# q, m

7 {6 x1 n; |! C8 Z+ k8 jvoid        APU::SoundSetup(). G9 h3 l8 Y. `* i7 I0 s3 x% ]
{
; H1 O. c* u& D& T1 `% c) p        FLOAT        fClock = nes->nescfg->CpuClock;- i( B5 T+ W  R1 _% k. U1 x
        INT        nRate = (INT)Config.sound.nRate;6 N: ?& }1 O9 o& o
        internal.Setup( fClock, nRate );
! e0 u& w' z3 l8 l& @2 f        vrc6.Setup( fClock, nRate );
, a# I2 C0 [+ e! E/ ?9 ?* l9 b' d, Y        vrc7.Setup( fClock, nRate );
$ r1 j2 T" K2 @7 t5 b        mmc5.Setup( fClock, nRate );
0 {! F) N$ o+ u- @6 p9 f        fds.Setup ( fClock, nRate );
" n* A' [" T) }- b; a        n106.Setup( fClock, nRate );- M8 x! u2 H, H: a  ?+ g0 i+ L
        fme7.Setup( fClock, nRate );  Q1 ^1 e: Q4 H# p- \
}5 k" C2 A+ ]$ T
0 ~3 f7 g$ W% `
void        APU::Reset()+ Q0 i4 R0 e5 B$ L, D. Q  h
{' ~. W; G. W( I, }
        ZEROMEMORY( &queue, sizeof(queue) );" t8 g& o) s9 ?
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& O- B+ z  ~8 [; f/ d: G2 m' s4 ]/ p
9 \. C! p) P0 o4 d0 m4 c        elapsed_time = 0;
; ]( `: C; N3 \/ Y" x4 B" y- A  Q1 @, E! R" ~* _4 C4 t
        FLOAT        fClock = nes->nescfg->CpuClock;! I8 U/ Q( F- s! |; Z2 a& a
        INT        nRate = (INT)Config.sound.nRate;
+ Y8 T; W/ m; ]3 D; P) D7 S* w        internal.Reset( fClock, nRate );
1 s% [! W0 d- I: L        vrc6.Reset( fClock, nRate );& X% S7 P% t  d
        vrc7.Reset( fClock, nRate );
' s- x* v) V/ ~" N/ @3 D" {4 `        mmc5.Reset( fClock, nRate );% c0 F3 `5 D5 t+ n, V( W5 Y/ a  ?
        fds.Reset ( fClock, nRate );  x8 ?1 e  V  _( Y" D$ ?8 G
        n106.Reset( fClock, nRate );3 h7 L3 p- g4 [- `
        fme7.Reset( fClock, nRate );; w, h; c  r, x1 j. ~

1 b& V* @  q0 s$ u8 }$ v. M3 L        SoundSetup();
/ b% J8 ~  l7 d6 j}$ p: y( }- m4 S4 o( i+ t" q! r

2 B; A- q+ d0 T5 o  |* ivoid        APU::SelectExSound( BYTE data )
5 a, W+ Q2 f0 [2 U! H3 d{# f5 y1 A* [- ~
        exsound_select = data;  s) {( V7 @5 ^2 J1 V, X; V% }# I
}
  ]! a- ]" G6 w4 {% z) ^& v
2 F* `+ U9 G  ?6 a/ tBYTE        APU::Read( WORD addr )( A$ f' Y; ?/ G5 M: T
{4 e3 B! F& x, k7 b5 k* Y7 H
        return        internal.SyncRead( addr );/ L% X" Y3 n% a$ {/ q0 l/ o! F4 u
}3 h: ?/ {$ \# f8 a) ~. ?  B
" P( S7 l  e8 T0 A+ y" c8 T$ O; Z! A
void        APU::Write( WORD addr, BYTE data )0 R  M0 u/ B# b
{' _" G& ~1 Q- }4 W
        // $4018偼VirtuaNES屌桳億乕僩
3 T) r8 a, ?+ i5 g        if( addr >= 0x4000 && addr <= 0x401F ) {
4 _/ S7 R0 W7 Q/ m                internal.SyncWrite( addr, data );
% d, ?8 C4 F2 e. }) Z                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
. e8 }3 Q# @4 l$ j7 x        }8 {+ k: T+ x/ n! L( |+ X6 J4 w
}0 }) e" ]* ~8 ]% C! ~$ D

$ p0 S! S7 k# j: U0 g- aBYTE        APU::ExRead( WORD addr )( d& M. z( q3 C
{
- ~: Y) y4 s9 SBYTE        data = 0;! k1 U: ]' L7 R  e. k6 O% x7 \
6 T5 d- {/ }4 D1 V8 u( u( ]* n: n, }* f* }
        if( exsound_select & 0x10 ) {1 Z  R" ^5 Q. e' w
                if( addr == 0x4800 ) {9 q8 n, r; Q2 E) i3 V& c
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
; v/ T& k6 R! B                }3 P8 u4 V$ ^4 S2 |- d5 v
        }9 }+ C5 u+ U$ E
        if( exsound_select & 0x04 ) {/ W* q7 S! H) o- y4 d
                if( addr >= 0x4040 && addr < 0x4100 ) {# x" N* M" d5 k9 G/ @* L0 G
                        data = fds.SyncRead( addr );
& }$ ]- p; c; J% y                }
* J) Y7 ]! _' A        }/ g' x1 `1 ^2 w( V! X& q& s
        if( exsound_select & 0x08 ) {
" r+ Q- B# O( k% Z                if( addr >= 0x5000 && addr <= 0x5015 ) {
- \  R8 \2 H0 T  T* a4 ?  j                        data = mmc5.SyncRead( addr );- I$ h" X7 o: @2 ]9 l
                }
; o1 Z; A' M$ n. e: ?        }
4 [! T4 c2 \# a1 ^
$ L9 @8 X: ?# M2 f/ k        return        data;. k" X  `0 C& L. {! I) l! w, A
}( g/ |" L- f! g. T/ w) l: ^7 I  \
; |8 f9 [. g" w% F- e) R9 v0 ^  U# H$ @
void        APU::ExWrite( WORD addr, BYTE data )- I1 M% ^, J: H9 b
{
7 _2 H3 A* x" G0 h% E        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 ]# g: Q9 F/ I4 s6 q- W' r' b9 D. G4 `3 u- _1 A; m$ G( t/ k# h
        if( exsound_select & 0x04 ) {4 ?6 Y* F0 N3 @' @  k& `
                if( addr >= 0x4040 && addr < 0x4100 ) {
7 p8 S1 y, a; g5 w- _; v                        fds.SyncWrite( addr, data );& I; @; h% y/ z( H* A! Z5 U
                }7 a: }7 E0 }: d+ c( w4 A, U) n! c
        }
  a1 H) ?% R+ `- d' \3 n! k! U0 X% t- C8 B; [
        if( exsound_select & 0x08 ) {, t$ ^* W1 u  ~2 ?5 D  j- O$ M
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! X3 S) @  @: q* Y9 s9 A                        mmc5.SyncWrite( addr, data );
- K$ W7 k) t- S( C" ?1 J                }
3 C8 T5 g+ c5 v5 k        }
% M7 ]- f$ e0 H: C& ^# S' m  Z}
2 A5 ]$ e& j7 f3 s# l6 A. S) \. B
, o9 R7 ?& B* e  d) C# I7 H% ]void        APU::Sync()
' @1 C8 A! `' [9 b8 O3 ]. n! u* [{
8 `4 x0 r9 J/ x}% p4 q$ G+ e" h1 b

+ z6 y, B) L) C; ]void        APU::SyncDPCM( INT cycles )
* {  K+ e0 K+ Z# d$ U{
  o* X& H0 E; S) p- Y! v. H2 P! U7 {) M        internal.Sync( cycles );
, T) \% X9 ?2 t; Z
; j* l- J% ?) g% J        if( exsound_select & 0x04 ) {
% ]/ v) t, N$ T, T$ @0 I                fds.Sync( cycles );
1 Q' b; x/ e# w' z# Z        }
0 _; M4 |6 B: i8 ^. G% C        if( exsound_select & 0x08 ) {
" I, b2 I8 H( h1 U1 f) b! t                mmc5.Sync( cycles );4 c! r! ?8 y7 Q/ y# o
        }3 N( S- y, ~% a
}# x' I. [$ N) j/ I* ]. z5 Z

! e% ^/ @+ Y# L( ovoid        APU::WriteProcess( WORD addr, BYTE data )
) M7 ?0 M3 i* _& O: B" t& Q{7 A* j: F& s: A6 ^! F
        // $4018偼VirtuaNES屌桳億乕僩
. Z% M$ X' F! e$ y# W& c        if( addr >= 0x4000 && addr <= 0x401F ) {
: m8 N) f- `( Z! l! ]" K" w                internal.Write( addr, data );4 I. N: E3 L& m
        }, S% d/ J2 q+ y
}
2 O5 z+ y0 p. W
  B: ]" L9 D& J4 z( x1 ?void        APU::WriteExProcess( WORD addr, BYTE data )5 J" a" Q6 G, }9 A( i' j# c7 [
{  k9 t3 @; _4 F) d# X: G
        if( exsound_select & 0x01 ) {
8 N: I8 b4 Z$ A1 h& }" z                vrc6.Write( addr, data );
4 \5 s* O( h  P. D" X        }
$ T0 ?* m% L0 h) M" N        if( exsound_select & 0x02 ) {
3 |5 v& S5 ?9 j" z2 c' ?$ o- M5 E                vrc7.Write( addr, data );) X$ H# g' y& b2 B, i2 l6 p, v4 _. j
        }- h# M6 R0 |8 M, F) h
        if( exsound_select & 0x04 ) {
( P1 [5 m- c2 F# r$ S                fds.Write( addr, data );- a3 y' ?5 v% P% x1 v) a
        }) N1 @( T8 y# N' s. F
        if( exsound_select & 0x08 ) {; |* s3 _/ D% K; }6 ^) Z4 q
                mmc5.Write( addr, data );
' z. B' p8 f, h( @6 ~7 C        }$ z1 Q* I# F) r) ~/ c' ]) V* \
        if( exsound_select & 0x10 ) {
" \( Y; i9 Z: {' k+ Y0 V                if( addr == 0x0000 ) {
; L1 X) n* \( ]                        BYTE        dummy = n106.Read( addr );4 a: a  ], O+ F# f2 d- Z0 L! {
                } else {
) E' I7 r# i8 G# M" ]                        n106.Write( addr, data );# U7 s# E; K* }/ M: p8 U
                }
/ j+ v$ Y' K9 s        }
5 _4 H4 ]/ Q' W: \! `; s! N% s        if( exsound_select & 0x20 ) {& |( K* H+ Y' g! N9 `
                fme7.Write( addr, data );5 D5 L# @4 P2 y4 u+ t
        }! W- E  ]+ Q1 E5 {* m
}
# O; }6 y3 ?; p: x8 V) `5 y% n) [5 x: [: x
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
9 }1 T6 d% j& ]8 y$ n3 w{8 |- J1 o% M( h6 F- s; P
INT        nBits = Config.sound.nBits;
7 N/ s+ q, A  p' _DWORD        dwLength = dwSize / (nBits/8);9 g2 }: Q0 n/ _& @6 Y# H
INT        output;
' b/ T$ \$ t5 p0 p$ {/ x8 \7 KQUEUEDATA q;
& A6 H5 z1 i1 p' U! `DWORD        writetime;3 S0 m9 E$ r: Z8 B7 K) J

* s! C8 ^5 e% k6 sLPSHORT        pSoundBuf = m_SoundBuffer;
, r$ U! Z! t6 F0 V4 V/ oINT        nCcount = 0;
7 Q& M! v; Z/ V  A0 C+ g! A! U( m7 ~& @  t& R' b, P& I
INT        nFilterType = Config.sound.nFilterType;  [: o/ e4 l8 C8 }
6 }2 m& o' W/ J* R" f. u
        if( !Config.sound.bEnable ) {
1 p9 m; l+ F: u+ ~5 C5 _, F  T                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
* E0 L8 \+ H( |7 n( h                return;/ L5 j* H, R2 d
        }
( U& E; g# K3 M9 K9 L* c0 ~
+ A* A# p3 {0 D2 q+ e        // Volume setup
( v. j+ O9 \" f2 H1 C2 y0 t        //  0:Master4 O  N1 l- C8 f9 _" y6 u/ m
        //  1:Rectangle 1" k/ N$ n( e6 o
        //  2:Rectangle 2
5 f6 m6 ~: N8 z% a* q- }- w        //  3:Triangle1 U& a/ A6 G$ P1 A5 r$ U
        //  4:Noise
5 v& G3 N1 q/ u% v/ {5 B" R' a        //  5:DPCM
& [3 H' d, X7 }7 @$ A        //  6:VRC61 ?. u* v1 V0 a4 e8 s) [2 c% F
        //  7:VRC7
( Q% @% L& y+ F8 p( O) a  B1 {        //  8:FDS) d# f8 e9 Z8 Z5 ^. l8 _* V: O4 g- [
        //  9:MMC5* S8 @1 s7 u% P9 v$ K$ i6 K
        // 10:N106
+ z4 H% n! I& Q% Q& ?. t        // 11:FME7: T  Y9 |5 p& v2 f' t- {
        INT        vol[24];
. S0 O- Z8 `5 W8 g6 d        BOOL*        bMute = m_bMute;. D" Z; d7 \% F- ?. a
        SHORT*        nVolume = Config.sound.nVolume;8 b% D; \7 z6 b2 N9 j9 ]6 u1 @
' c% Z5 \. O' X. }. r, S& ]7 r8 y
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;' x% d" a5 I% b1 o

; U& {8 V3 G4 l+ i- ^        // Internal) d0 z+ ~2 D- Y2 u# r( Q
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 e0 X" U6 B) f4 i& `4 s: N
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
. s. `* k1 o% l        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;5 s4 P9 X0 C/ b) \- F. R
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
! }; V  n' y2 @        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;" n' O: z, C/ h8 B$ V6 p
4 Z1 u2 r; U$ h2 n# R: D
        // VRC6
5 s* |1 H/ c5 x( J        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
5 c% W- ^9 K# S1 \/ r% r        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 z7 F/ B8 W- K# g- n4 ^8 z        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& Z& l. n$ j9 {' k; s  J- b

% F) B! U* F3 v8 B" m        // VRC7
( x! |# S" N- H5 r$ C2 w/ t        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;( S1 A8 n# E5 }! O2 ?

( V. Z' o. i" i1 p: ?! H/ j        // FDS
6 N. F% Q( u0 ^! Y        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
) Z0 F$ x6 Q) `& v( s
" R- P' E, c& H        // MMC5
( e, a# \% [! ]7 Q3 _( m8 b! f        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;6 S2 y( h+ r! x3 @0 k1 Y& ^$ B0 i
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% O$ O/ x1 Z! u) o/ |$ X        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 K( D. }2 x' Q/ y$ v1 I

: b7 @) L6 u1 p! D5 e$ E9 q. Z        // N106
% I, n3 C4 v) y2 T+ v4 h        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( \2 K; W9 G. o& }) h
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 L. R. W1 Y9 c; x; g        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 p# {* f$ t# a/ L& R, z4 A        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 I" d" |1 e+ i, X6 }5 @; ~& N
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 q6 w  o$ C; R* q8 ^+ Q3 u
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 g/ T7 ~3 Y$ m* w, P$ S        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) N) F4 m/ W% C' k2 ]        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 `% u5 _. k' K: N( u$ ~+ B4 W* Q7 p
0 c) G: @7 F" a" T# \
        // FME70 n2 X5 \8 d2 I% h
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;% F/ y% q6 M5 c, N$ |" ]" {  p
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! e' l' f) {  P! A        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, O/ y& M. ]' i1 }

' r5 [5 z; D* O5 f//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' N* B  `, x+ w7 k  j6 R        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;7 w/ N! K9 I0 g  f$ f
1 [% _- f( H. A% Y2 n
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟) t- f* {0 T, g* A7 a
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
5 ^7 C  c6 [7 g8 F- M                QueueFlush();& r1 g" n; f9 S6 I& d$ J
        }
) z- Z# M/ i' B) Z& t* I
3 Z8 o' n  K" K3 M) g        while( dwLength-- ) {- l! A$ l# y# m- O  H! X; n
                writetime = (DWORD)elapsed_time;
) h! ^8 B1 ?, q4 I( L6 Z3 f5 M3 k, g! R# D0 H. B
                while( GetQueue( writetime, q ) ) {# w2 i; `4 U5 ?
                        WriteProcess( q.addr, q.data );$ x( |+ \5 n& W" A
                }2 [+ Y' O! T! d  h& `' D; r1 y

% q. P" p5 z! K% c) ?( \( S) w                while( GetExQueue( writetime, q ) ) {' Q$ K3 l. [2 `6 w$ d' L
                        WriteExProcess( q.addr, q.data );
# `  U5 l) a5 G, k& S                }
* _2 |5 `0 C1 m! ^( q) ~! i! E* ^+ L
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7% j- E- R7 {  P) }4 C
                output = 0;
- N* n; |) [* t4 C                output += internal.Process( 0 )*vol[0];  V! J& y: F+ r2 G7 R4 r" [, Y, N
                output += internal.Process( 1 )*vol[1];/ c. y) Y1 k( L0 m7 R8 o' s; n
                output += internal.Process( 2 )*vol[2];
9 P# u6 y) ^1 J: n2 }                output += internal.Process( 3 )*vol[3];* X! d( ?, w& R3 [, G* V
                output += internal.Process( 4 )*vol[4];
2 i# z0 S) k! R6 c8 `# }4 C+ O9 m# h  ]1 W
                if( exsound_select & 0x01 ) {- G3 A- N/ L" W4 _0 g
                        output += vrc6.Process( 0 )*vol[5];6 c) W; u; \$ w
                        output += vrc6.Process( 1 )*vol[6];
8 J( j8 w. f/ _6 d4 B: \                        output += vrc6.Process( 2 )*vol[7];7 m( U/ l1 X2 w. T9 H
                }3 u$ G+ F6 ^* z$ k
                if( exsound_select & 0x02 ) {
% K/ o! T5 ~1 z& l8 |                        output += vrc7.Process( 0 )*vol[8];/ Z% p. n( d3 A& K, p5 g- p  y
                }! N( B: ^3 u. X4 b  n+ S0 K' ^  h
                if( exsound_select & 0x04 ) {
4 Z8 u# T# c7 N) s- p4 M! v* y                        output += fds.Process( 0 )*vol[9];
7 N6 S7 R% z& J                }
1 `$ l4 U4 T" L0 w$ M) T2 }                if( exsound_select & 0x08 ) {
3 Y2 W+ ^; x* y* H                        output += mmc5.Process( 0 )*vol[10];) c6 b0 h+ o, i- J6 ~1 Y9 x
                        output += mmc5.Process( 1 )*vol[11];
1 A4 R! K0 G5 u2 O                        output += mmc5.Process( 2 )*vol[12];  Z6 u6 c9 F6 b
                }
3 u. {: L2 ?2 [+ C                if( exsound_select & 0x10 ) {3 w1 X4 B; {0 u9 H( c
                        output += n106.Process( 0 )*vol[13];7 c/ T0 x. u  S
                        output += n106.Process( 1 )*vol[14];
. f9 d' A# R3 T) u                        output += n106.Process( 2 )*vol[15];2 ~) M4 U3 H$ t. |$ \; u
                        output += n106.Process( 3 )*vol[16];/ i! f* Z  \: T0 i
                        output += n106.Process( 4 )*vol[17];( B% ^6 C$ i( G5 D
                        output += n106.Process( 5 )*vol[18];" _) D& ~! I1 v2 h
                        output += n106.Process( 6 )*vol[19];
% n3 o% \3 d) [$ m4 L, w                        output += n106.Process( 7 )*vol[20];1 U. L' m9 R6 g' U7 h9 c  q
                }- E0 K- l) v' ]  @& R- b
                if( exsound_select & 0x20 ) {7 \8 Q8 N+ C3 E
                        fme7.Process( 3 );        // Envelope & Noise: ~8 O+ K8 E0 W0 `: V7 r
                        output += fme7.Process( 0 )*vol[21];
; }* _; g4 J) E2 ?5 k& \                        output += fme7.Process( 1 )*vol[22];
# Z0 C! z: H$ e                        output += fme7.Process( 2 )*vol[23];
( |/ c2 w# e% Q, v. N                }2 ]% g- w& I: N& |

+ `5 T- m5 R5 w' F$ I( [                output >>= 8;
: m' v+ n& k' h- ^3 O8 v0 \7 n- A; q( g$ k
                if( nFilterType == 1 ) {. e2 x: X' f7 `3 U4 e
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
* M5 h0 X* N9 V                        output = (lowpass_filter[0]+output)/2;  ~, ?4 d5 g& `) b/ Z
                        lowpass_filter[0] = output;! F3 q+ V7 i" [6 W
                } else if( nFilterType == 2 ) {! f% B3 ]0 q6 y
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1), j5 ^/ {% N5 t  ^3 f
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;# i  O  d: y' q) {  @& E
                        lowpass_filter[1] = lowpass_filter[0];; @9 H5 V8 P- j8 O; H8 e  Y
                        lowpass_filter[0] = output;
& C) g' p! l; P; o6 z                } else if( nFilterType == 3 ) {
) Y* N7 F, v% e1 o+ R- ~                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)8 X& {6 D4 S( Q1 F
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
8 x/ g9 o2 T: K9 u1 t. J                        lowpass_filter[2] = lowpass_filter[1];. p) x' I' @* E9 a0 B6 _
                        lowpass_filter[1] = lowpass_filter[0];2 g! r# c! l* G0 S$ W" D; Z
                        lowpass_filter[0] = output;
! g- H1 s9 _& ]3 T; F# w; F& c& L) x                } else if( nFilterType == 4 ) {
/ b9 j+ P$ D- p                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
: }; o5 H: E" c% g/ F6 ^                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;( A  u9 Q" N8 c5 L
                        lowpass_filter[1] = lowpass_filter[0];
3 k; W# Z. n  r! j% w& t                        lowpass_filter[0] = output;$ V1 M. `+ }- `( E9 _& d
                }! M7 O5 d. _' Y
2 Q/ d& z7 h4 G& @" {
#if        0( y1 I; q- \# v. r/ c$ K
                // DC惉暘偺僇僢僩) k- d* ?- K# L+ X- D' ]
                {
$ F# y$ ~3 D/ m& Q& ^  U                static double ave = 0.0, max=0.0, min=0.0;
! G' U# O2 \% @4 r( e5 G  }                double delta;# Z% {" F: ^5 q, T# o3 r
                delta = (max-min)/32768.0;
1 _% D# P# `2 S! l                max -= delta;+ q. J/ h4 y9 D# @3 Y: S
                min += delta;2 [$ a$ W8 {* Q( ^, _% L, W
                if( output > max ) max = output;7 _8 {: j% U- I- Z
                if( output < min ) min = output;; |  D+ p/ w, J' ~
                ave -= ave/1024.0;0 S0 L! ~' }: W- ]9 a: `8 V: x
                ave += (max+min)/2048.0;8 ^# j, V. H) G3 Z. F! V
                output -= (INT)ave;
# X+ o/ }/ a: N* o                }
! g2 R; m5 e1 T( B#endif
. d; M: N/ W$ h4 l* h( i#if        1! Q6 O; }3 ^8 E9 C( _" t
                // DC惉暘偺僇僢僩(HPF TEST)1 k; x9 _1 o  V6 P
                {
6 f2 V8 P( A, P5 ?6 r; {8 Y8 Q" T. V//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! A# ~5 |4 d, ^& ^: c) ?                static        double        cutofftemp = (2.0*3.141592653579*40.0);* _5 ^( Z9 o5 W2 R. b$ C, P; g
                double        cutoff = cutofftemp/(double)Config.sound.nRate;" v9 F$ n* D! K3 b
                static        double        tmp = 0.0;
' q& K" ^9 R0 z  i                double        in, out;
, C2 |$ ?' F  H& |2 q% y# S: R$ p; c  h# T# t
                in = (double)output;8 G2 K- c; C) Q# N3 Z( W
                out = (in - tmp);. {; \. b, C0 R& I
                tmp = tmp + cutoff * out;
  a0 E$ v. r7 K3 i$ g, a
5 i9 r" n$ T/ N6 X4 w( Y7 O1 w7 X                output = (INT)out;
. r- _& B" H7 ?  [& ^                }/ |. D: g6 t' M% j2 s* X1 f
#endif- z( d1 H( S- X6 K8 H* y* r2 {( \
#if        0% L4 c8 u5 z: R7 ?. o
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)* o; g- v) r: g- H2 L4 }
                {
: g: s; L2 H" K* }0 Z! G                INT        diff = abs(output-last_data);
, y+ j4 |6 w2 B# C& d8 z                if( diff > 0x4000 ) {
2 W+ i2 ~% l: X$ E' Z$ B, U. d1 k                        output /= 4;4 D, C$ {* z  d( J4 M, m1 c' V
                } else 3 j- u& e! E0 R( i
                if( diff > 0x3000 ) {
& c6 q4 f8 n6 n/ c                        output /= 3;
4 r2 ?3 c- u5 x" A) {, ~, n; B                } else- P9 t! p7 I! y. t, F3 p5 x0 w
                if( diff > 0x2000 ) {  }# Z) x6 Q- S' Q
                        output /= 2;
/ w4 @! X+ o; G4 g2 B% c                }
  l. _3 E8 b# g, F6 |; C) J                last_data = output;
: A9 B) B7 p5 }                }( }8 v7 C+ x" C# y4 ^% p) f$ s* ?
#endif" y# U4 l: [/ a+ \, R
                // Limit
' j+ L+ w" ^  {0 a                if( output > 0x7FFF ) {
8 |: g% I# i- G8 y! P                        output = 0x7FFF;
. I( \3 u1 Y6 ]7 L( r* R# Y7 R6 k% ~                } else if( output < -0x8000 ) {2 r0 t" S# E' M. j* y" A% B/ u
                        output = -0x8000;
3 O* k/ O8 ]3 `8 ?9 p  F                }
/ U: w5 Y- h% Z9 E# j/ ^0 N% z1 c( L1 M1 H" y, Q
                if( nBits != 8 ) {9 w$ W. F5 ]5 l$ a
                        *(SHORT*)lpBuffer = (SHORT)output;
, K# z; U% r+ L                        lpBuffer += sizeof(SHORT);
' F" v* f5 x* U7 o- \                } else {$ J8 j) x0 \$ ^# v5 w4 A0 f
                        *lpBuffer++ = (output>>8)^0x80;
; `# ~; M$ ~! t$ E/ ]9 c                }
+ f8 }! g7 Q- e0 w. r
* x, S2 N  Y/ {. q) l                if( nCcount < 0x0100 )
( T, w, y4 Q' b3 Z/ U( L                        pSoundBuf[nCcount++] = (SHORT)output;
  B" S+ `, U2 _. }) m" ~2 x& K! r% I7 `2 S) b; n
//                elapsedtime += cycle_rate;
" ~6 b& f+ |' n! s5 A# `/ V                elapsed_time += cycle_rate;
' }# K' ]# w% ?; v- h6 }" S        }! T8 F9 G7 E4 ]# n- o' n

3 N; Y' e- D, E+ U  ?#if        1
, K. w; g6 ^  l" ^, `2 e        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
) }' Y, f/ j: A% J1 V1 T                elapsed_time = nes->cpu->GetTotalCycles();
8 S6 |0 a% ]' o5 A4 n3 i+ w        }/ b! @9 o  ^5 `- i
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
9 b. P# _/ i" j( a5 u3 U  x# Z: z7 |                elapsed_time = nes->cpu->GetTotalCycles();+ d' D3 N  T0 D0 W
        }
6 ^" g4 N$ |% m5 ~. M" L) H#else
; y* x! ?% O/ u2 i' u+ o        elapsed_time = nes->cpu->GetTotalCycles();. b! |$ n( {2 M/ E% f( _: B: P
#endif
9 S3 Y3 v) _0 u$ e, S6 g}
  X: A( j/ r/ d  {2 t. c+ B% e6 ]# ]8 L
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)/ v! e" S4 W" h2 p0 O4 f
INT        APU::GetChannelFrequency( INT no )
: c: n' G5 G% Z6 z$ V4 X9 k) ^{
3 ^+ T1 U- S7 h$ P* ?& {        if( !m_bMute[0] )+ K6 Q# N6 R1 d6 Q/ ?% O# C- w$ H( y
                return        0;
" C' O' h9 @1 h0 H4 n% W2 q* f: z' F
        // Internal! Q9 B7 Q8 t. J8 ~8 N. m. C
        if( no < 5 ) {6 g8 U! a: I" b8 M( k
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
( x# H) U' q% _' J9 b! E+ n( w        }# ^! ]4 ^, `  w( O$ o. v' `
        // VRC6
+ Y% r6 @* I7 N8 U$ B) U        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
, Z# s2 [, i2 {( |0 ^5 g* l                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;1 _3 o: C* c5 C+ v- S
        }
" ^) E2 h! K4 P7 I! C+ {$ @, x/ g        // FDS$ f: p1 @. u; O0 t
        if( (exsound_select & 0x04) && no == 0x300 ) {9 v5 u$ r, B! J) R) M5 q. d, o
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
" v3 V8 K9 D6 R5 H        }4 A; v" |1 w! o* a6 k* p1 E9 k) G
        // MMC5! W( G0 H  ]/ }" A& i& t: ~/ Z4 W+ Y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {! O0 }: G/ z, |0 I! F! w3 v7 L- ^
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;; g: }3 t; c4 ?( q! t
        }  {6 Y: @/ U* R3 j7 l
        // N106
# ~6 Q3 x! C. E0 `/ U( j        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {+ g2 m. {$ C& j: V* }7 t
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;' r. |/ _& d+ N' V" n
        }
! N  P- B& T; L) i0 ~$ Z/ F: `        // FME7
, }+ {( c1 c4 l- I1 R& k        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
: c/ q) y) l4 \2 ?# y                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
& }9 {$ G& S! E5 \4 B; J* P        }
5 X" g- K  l4 x( `% e        // VRC7
- ~* G' b, |6 M        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {" v% A/ c0 Y: y# s* _4 e
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
( y+ M7 a  ]% k        }
! ?  U5 |2 l/ A2 o0 a& @$ n        return        0;
6 _: p! Q- D6 {" c, K, X}" l" A2 B* S; G4 J
, {" L. t$ T+ ~/ B+ n" A- Z
// State Save/Load
! L) U7 l! y. o" X- n3 n' C$ y* p6 m- tvoid        APU::SaveState( LPBYTE p )
7 u: o% f# T8 U( X2 j4 N; `5 _{
' W; A; m& P; \" H* O6 ~#ifdef        _DEBUG8 h5 X5 e$ S7 t5 l  o
LPBYTE        pold = p;
) k5 ]( ~" j3 Q* Q9 X3 p( b3 h#endif
) s/ l3 v3 N% C- e; z$ ^0 t% P4 S& U8 \. [
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
9 [2 k' W, a" D1 b8 }        QueueFlush();" t# R6 V6 J$ }" ?2 Y- s
8 l' I% `9 t) j. ]& m$ q
        internal.SaveState( p );
/ Q* \4 J+ }3 w0 E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; a0 X, h6 U1 E5 A' r

, q7 s1 R" P" O5 p7 [( A        // VRC6/ w  v! t' G+ E2 a
        if( exsound_select & 0x01 ) {
2 G% m5 H$ W$ Q+ N, C' A                vrc6.SaveState( p );
8 n! K: [8 w3 E% ~0 |# A" c9 Q, c( n                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding6 W$ X% G  d& [4 n7 R  p# m  W
        }
. C1 c. d1 w+ m; T& R        // VRC7 (not support)8 S6 H1 n$ H4 A
        if( exsound_select & 0x02 ) {) q2 j  E' [, l0 y
                vrc7.SaveState( p );
% W' _6 }7 e' a- X) _( h                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
" \& j4 y6 [. b        }0 A2 X3 e/ o3 z" \/ A$ u
        // FDS
# d2 G" n& m2 w  `, \, a, ?# y        if( exsound_select & 0x04 ) {8 H4 Y4 z5 J: {0 X
                fds.SaveState( p );
2 b# P+ J9 z! Y9 r8 @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding' [( h* N" V' n& g( j2 c; \
        }
! }- `* ~5 g5 ], M8 z! {( H7 H        // MMC5
8 h* k/ |+ l+ ]1 ~        if( exsound_select & 0x08 ) {3 ^" j  L0 M5 w& Z( J
                mmc5.SaveState( p );& C3 A5 \9 r( T2 A& |: D) i) }
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding0 V4 R$ I& L3 o
        }, E8 x3 Q4 @: S! \% o# e; z3 f& n
        // N1064 d7 ?3 L9 b( e/ B7 v+ `  M1 g" }
        if( exsound_select & 0x10 ) {  c! D( f- l  R
                n106.SaveState( p );. {8 N0 x* s! u' `2 H! K
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding! n/ G1 f/ {9 }, p3 y. h* o4 K
        }5 G# s# B2 _2 e$ L7 [! ]
        // FME77 O: M9 [& \* l1 S9 A' F( @
        if( exsound_select & 0x20 ) {) `# P% u) w; h: l
                fme7.SaveState( p );
) {; m5 C1 G. v/ E# N8 T  J: S, A- t                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
0 k1 U% x0 R* M$ s        }5 W4 w8 [) \2 T3 {( D, O
3 W2 [* o2 a' \
#ifdef        _DEBUG/ ]- ^0 Y1 j7 v+ T/ L
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
0 M$ b5 C/ _+ o2 B4 D8 O#endif
3 g: }2 M) ~! J+ u0 e}
7 g* p' Q- F8 n1 V+ @
" |9 @5 Y" T; ~  a$ o" ~$ a& a/ avoid        APU::LoadState( LPBYTE p )
8 _! a8 P0 W8 h: D+ e{
2 h0 m- K# Q, k  F6 R  T9 g        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
% {2 U4 E# Z8 @1 t: ^        QueueClear();  ]8 Y" D) ~: X" j

- Y6 o9 X8 N7 V8 D8 c; D; N        internal.LoadState( p );
, C) A% T5 H, v6 i7 }' F        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding$ L5 c% H& e- f1 Z, Q; a/ Q
8 {; K8 n5 o5 H5 {) ]8 ]
        // VRC6# k; D! a" L' m5 G  p2 L
        if( exsound_select & 0x01 ) {
* j6 T- J' v! e                vrc6.LoadState( p );
" F" s8 P+ v# e& [7 h                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 u( U, J5 A" F) g3 [/ v9 d
        }0 J4 z" w( k; p+ Z6 k" i% h
        // VRC7 (not support)
# I- x  w& x# C* @+ t: P9 G* c        if( exsound_select & 0x02 ) {
& n: ^3 U8 o% B, n9 a; {1 S2 ?+ ?                vrc7.LoadState( p );: \: i$ ?" h, y/ Y! c
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ p0 H8 Q, R/ R1 M# y) V6 E! q
        }9 ^: }9 N, `0 x! R! ~9 k
        // FDS
, Q2 C% V/ c9 t* B" f        if( exsound_select & 0x04 ) {0 F3 z3 q1 r8 v) W6 e/ b
                fds.LoadState( p );
' z5 C$ f3 @3 k. l                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 H7 l* V& G# u5 l9 ]
        }( n! j4 f: @' \, \+ ~
        // MMC56 a! P6 ~' W- r) _
        if( exsound_select & 0x08 ) {6 C  i! o9 l9 S& t' a1 n
                mmc5.LoadState( p );
& c! @" O! T; D                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& ^, j* H, b: p7 w- X6 i6 l* A
        }
2 c: t6 ]2 a# V1 r        // N1064 q+ i. D" r  a4 j5 t: w
        if( exsound_select & 0x10 ) {$ q( k- N, N: Z6 `& ^% m9 u3 u
                n106.LoadState( p );
* `6 a) |2 C% A) c% K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
, r8 I/ o, ]( T+ W3 @4 M/ \/ Y6 Q        }
& u' \9 ~! Y" T4 `8 a- b" }        // FME7
0 \. f3 U+ f) e, J6 k        if( exsound_select & 0x20 ) {
* Y$ s5 R7 S7 ~. _  f                fme7.LoadState( p );
" v8 ^3 ^$ Y* T1 F1 h                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
, U6 Y- W" Z4 c( n( M. J4 T) u) V% v        }
+ n% G) d9 X+ M4 y2 i9 U# R6 _- q}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 2 i+ Y& f( b6 t4 Q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。" h# Q  \, E! L3 u5 f: @" C
感激不尽~~

! u% |) r; M1 E恩 我對模擬器不是很有研究,
4 g8 `. f! F2 L) |/ V) m; w- L雖然要了解源碼內容,可能不是很困難,
  C( W. U8 N" e不過還是要花時間,個人目前蠻忙碌的。
3 g  w  s, a2 b! E  R5 h! o, H' ?/ L( A# n
給你一個朋友的MSN,你可以跟他討論看看,2 T: K/ I4 M" I& ~3 ]1 n
他本身是程式設計師,也對FC模擬器很有興趣。/ ~* d) X0 C/ q, N7 }% E! F
6 k% N. D4 w$ a. d4 M  n
MSN我就PM到你的信箱了。4 v1 O/ u# d/ R7 z/ t+ d: S
: e: ?9 B# \0 T3 e# T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
% q9 J* G, |* }; v4 j. e呵…… 谢过团长大人~~
! ]7 F, m- @- b* F7 ?& N6 W

+ I7 R0 j1 q6 Q7 m1 z# Z哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 * q- K& z0 W9 s8 g# \  H
团长的朋友都是神,那团长就是神的boss。

; h# c4 r1 b6 P. a& \哈 不敢當,我只是個平凡人,7 m8 e, K) W4 a( z) j
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
7 i8 p5 R0 _7 cZYH
) F7 F1 x, W9 K4 wQQ:414734306
9 A6 z8 y. T( U# ?Mail:zyh-01@126.com
5 a/ K% W# {: ~$ y/ H) f, e+ I
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
9 X, P! j/ R- i9 v1 h. K4 s再次对团长大人和悠悠哥的无私帮助表示感谢~~

* |. e" B( |3 c* f$ n不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-19 04:18 , Processed in 1.115235 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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