EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
0 R  I4 J# Z* l楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~! ]: {+ ^) Q. a% X% K* {
这里有相应的模拟器源码,就当送给大侠了~~% X  C7 ]' |1 v3 P$ [
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表   w: X2 s! [, p
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ E- [; O! j, G
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! i2 O- ~6 K; r" {" h这里有相应的模拟器源码,就当送给大侠 ...
+ F# s5 c6 d6 K: X9 }/ t
聲音部分(Audoi Process Unit = APU):
* n* `7 `) c+ {' B.\NES\APU.cpp! J( J" F1 d2 v) G
.\NES\APU.h
: @( }6 @& c5 M" l7 t6 z# V5 D8 I: W$ N: P

& }. K1 D9 J$ [2 _影像處理部份(Picture Processing Unit = PPU):
& ?. E  Q- |( D* x& e% ^! [.\NES\PPU.cpp: V+ I  Y" @& Q7 [" J' T" h  x' \
.\NES\PPU.h
( A) E$ O1 \) l, o+ [8 h6 L- y% B# P
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:* i* F: W( x# \! W2 k8 W% e1 C
(由于很多专用术语和算法机理都不明白,所以看不大懂……)
, {6 K# v7 H$ W, K, g* y//////////////////////////////////////////////////////////////////////////! ]4 ^! _6 e! k) ^6 K! \6 j
//                                                                      //9 {: X/ @' g7 ^3 T+ P
//      NES APU core                                                    //
' p# R$ x0 C! X  c6 b. G( G//                                                           Norix      //3 g8 j/ I" H  w7 N6 |4 s9 Y
//                                               written     2002/06/27 //
) f5 i' N2 C" i//                                               last modify ----/--/-- //
( C9 |  @1 _8 f8 Y//////////////////////////////////////////////////////////////////////////: N( F" s+ }! D4 F5 w
#include "DebugOut.h"5 m2 `% D; h6 B2 D+ D8 X5 d
#include "App.h"- e( T% s2 n. K' R% e
#include "Config.h"
( O8 y  s# ^- W3 L- b: r* i- Z8 J/ L
#include "nes.h"
3 Z& g( w5 q$ L  f) y3 E#include "mmu.h"
0 F/ j& o; ?* q2 n, v" y4 |; ]#include "cpu.h"
5 Q& a9 o8 J2 V8 h6 i#include "ppu.h": ]( S% V, }! Q% N6 P4 o% W  P
#include "rom.h"
$ ^$ y& `) S7 \, N# Y5 v#include "apu.h"
) ]6 m7 r% z% w( @# A$ C( v5 v: b7 O
6 v( g7 h' q6 ~9 J# O: O; `7 W* p// Volume adjust
3 V- R9 Z. H2 Y// Internal sounds
4 m7 |% O. o& n- q' k3 D#define        RECTANGLE_VOL        (0x0F0)* W0 o+ a' J2 n) R- B  W- Z
#define        TRIANGLE_VOL        (0x130)3 {% p7 w1 ]$ P# B9 n5 G
#define        NOISE_VOL        (0x0C0)* i; A/ \9 ?: x
#define        DPCM_VOL        (0x0F0)* n% h$ C/ o7 e9 }/ G
// Extra sounds
. J  w0 j  Q  L; |#define        VRC6_VOL        (0x0F0)
8 \% w8 e+ p7 f: q# O2 \#define        VRC7_VOL        (0x130)
4 e/ }: e% J+ W8 `# y; m5 p/ ?( m& |2 t#define        FDS_VOL                (0x0F0)! F7 s* R' F; y& s7 l, }0 s
#define        MMC5_VOL        (0x0F0)
4 f* P+ f% V1 ~3 b#define        N106_VOL        (0x088)
/ y* F, {5 c( K- p. T+ d#define        FME7_VOL        (0x130)
; F$ r) D* U1 l9 i+ w. o: F  E+ Y- x
2 z7 Z9 {& \0 l; ^3 s9 z, BAPU::APU( NES* parent )  w2 U9 b% H; b# g7 U$ i" j
{
* i  _% [8 J; P        exsound_select = 0;  ^$ g+ E1 l* u) V$ s( s! u
9 C) \$ W& b  V$ E0 O3 W3 Y
        nes = parent;
! U1 M" x2 C. T7 ?8 s; s        internal.SetParent( parent );
. |0 e- G: G- ?7 R# t3 A4 k( n/ Z0 g& D& q( ~& |
        last_data = last_diff = 0;
" N2 k# G* h: E3 ]- V7 H( p, k* a/ A- o: K" g1 P- T: p
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
/ G; z/ D' ]% }" b
+ B# ]1 M8 @7 a2 I* q: {$ s0 E        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
" K; X0 C* f5 R- k. |; q" e        ZEROMEMORY( &queue, sizeof(queue) );
1 t; s/ E) q/ I  w( ~        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: |( _9 n' ~6 O( I6 T4 x
8 R5 Q* h) m" f+ O. _        for( INT i = 0; i < 16; i++ ) {
- {1 a; b/ P  P' a+ A                m_bMute = TRUE;
/ U2 t  I1 c% R; y' c0 U- r        }
; T9 D! [; f' f0 s- l}
3 @  ]! Q7 Q' \# ?) \6 v( D$ |, k3 V4 v' [  s: Z1 h6 u* W! W
APU::~APU()
- d; N8 `1 ]8 d6 Y{8 D" `' ?2 V  j. s9 A
}6 j+ I3 i3 ?0 v, Z; x

3 x' D. ^& V# \+ E( ~void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: k# M9 r; G: O8 H+ W{* {  ^+ M) M; F$ Z: L
        queue.data[queue.wrptr].time = writetime;
" W  X) l+ u4 C4 X: u( v  N        queue.data[queue.wrptr].addr = addr;
0 z, |) X, P8 O% [8 R        queue.data[queue.wrptr].data = data;
, t* n$ ?; r. J6 t& C4 {        queue.wrptr++;+ Q+ W  Z5 X# ?3 \* F4 Q
        queue.wrptr&=QUEUE_LENGTH-1;
, K/ G4 ^  v# w4 |" z        if( queue.wrptr == queue.rdptr ) {
! B+ v2 y; K5 j# }                DEBUGOUT( "queue overflow.\n" );
$ ]* A; v/ Y0 @, i( a        }
; j% ~7 D0 s# y9 A2 Q- U}9 \6 ^# ]# h; S! ?) J/ Q
" V) }9 H5 [- F1 O  ?
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )) G/ s, q: ~1 t  L
{' [' z$ S5 L, N( g
        if( queue.wrptr == queue.rdptr ) {
' y5 Z' z5 g" }) }) ^# Y) v! N                return        FALSE;
/ k- u! ]. p* R  p8 F% `/ o# @        }
" z3 v7 a' o! H* Q6 c        if( queue.data[queue.rdptr].time <= writetime ) {
3 r9 _7 Z5 S, l% `! Z                ret = queue.data[queue.rdptr];; K# K0 w3 ?4 m& }3 k3 C
                queue.rdptr++;$ r! m$ `" S6 ^& u
                queue.rdptr&=QUEUE_LENGTH-1;; U: V) f9 Q/ Q# E5 m8 i' P
                return        TRUE;& T+ k9 |' m4 ~9 X2 {! C
        }5 v, {  L' o# f
        return        FALSE;
0 R0 X0 n. e) Q" A7 o8 A1 }0 ~3 D$ ?}" v7 h3 E+ ?5 L; Y
) I8 R' J1 g# Z9 _+ J, B  H
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
9 Y7 I, i( e3 Y3 J4 ^6 v1 n- X{+ A1 `' v$ y! _7 B
        exqueue.data[exqueue.wrptr].time = writetime;% I. l4 W! n) G
        exqueue.data[exqueue.wrptr].addr = addr;
" k4 s) \  y) D        exqueue.data[exqueue.wrptr].data = data;
# E0 [1 A2 F5 |" K, f& N0 z        exqueue.wrptr++;$ X+ p+ {2 F4 L. W4 A  O4 q# X
        exqueue.wrptr&=QUEUE_LENGTH-1;
7 E1 v5 F1 W6 ~# H+ F" B, B" e% r( D        if( exqueue.wrptr == exqueue.rdptr ) {
6 H3 a+ a: X/ m/ i                DEBUGOUT( "exqueue overflow.\n" );( m6 B& {9 f' c8 D$ v+ N
        }
6 i) I# B0 Z% z( R" i}
% g. f8 y* `. D9 \/ i% ?
/ Z7 u, N" D- A$ cBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
: m; C2 f7 @. A5 h4 M5 b. i3 z* F) N{
- X& \+ `4 i4 R) K* d' P        if( exqueue.wrptr == exqueue.rdptr ) {, `" |6 W) L) A2 O+ T
                return        FALSE;8 K0 ?6 C0 ?$ U8 z, m3 t2 @
        }
  Q/ k' l& s/ }! `9 Z        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
" T% o& O3 i  X4 s: c0 R                ret = exqueue.data[exqueue.rdptr];
& Q7 O. J- }1 r, H4 I: {                exqueue.rdptr++;% \0 k. ^% I5 M+ H9 {
                exqueue.rdptr&=QUEUE_LENGTH-1;
# P. v0 P& f& i7 }' b7 b! c                return        TRUE;
" N. M( O: n4 b6 n        }
3 L" ^& j0 p# {9 _        return        FALSE;
5 g) C  R1 Q' w' i" Q}. g; f& i7 [1 r5 ]2 o
7 x# ^( ?1 [$ \
void        APU::QueueClear()3 x2 ?3 {9 i' C) `) a2 s5 P1 U
{$ Z9 z' o) n9 y7 C
        ZEROMEMORY( &queue, sizeof(queue) );+ @: v( U- ?+ f  P
        ZEROMEMORY( &exqueue, sizeof(exqueue) );2 a! m. Y/ r4 G4 a
}5 E+ W& O* S4 _* W' K0 u% v

7 O/ K6 X1 x8 _5 d4 \+ jvoid        APU::QueueFlush()
9 p! ]4 [2 n' y' l, y{
9 d7 i+ @% ?+ `2 r        while( queue.wrptr != queue.rdptr ) {8 Z" g$ y+ d% X, K
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
8 s  e9 C+ n) e, q: Y0 M5 f4 C, C                queue.rdptr++;0 z. {7 P9 M' @$ K0 h# S/ s) J' }
                queue.rdptr&=QUEUE_LENGTH-1;2 Z& z+ a8 T3 T/ {
        }
3 X$ m$ Q) _3 N& N. N) ?+ x* }+ V3 A! [/ V" o  N0 f
        while( exqueue.wrptr != exqueue.rdptr ) {" {6 _/ g. A' W
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
2 H: q, K; a" H" K& N                exqueue.rdptr++;( Z  Z' @6 `) V; v
                exqueue.rdptr&=QUEUE_LENGTH-1;
! u) M& c( l# Y3 h1 o3 K& a8 d        }) t1 J9 Z, f& n8 g
}$ ^$ Y6 N8 Z6 x- d0 v% t* d. w
4 N' G2 g8 i; h) d* x  \
void        APU::SoundSetup()1 t+ m2 g  i7 T
{
: x. @" }0 P0 c2 ^, z2 }& ?* _        FLOAT        fClock = nes->nescfg->CpuClock;$ {6 ^1 g9 s  O
        INT        nRate = (INT)Config.sound.nRate;' I# C1 ?% C) a. U; P
        internal.Setup( fClock, nRate );1 S3 c0 c3 ~' V# K
        vrc6.Setup( fClock, nRate );
, T$ e4 G* W/ r        vrc7.Setup( fClock, nRate );
5 f- G7 o- {% ?* h( b7 X        mmc5.Setup( fClock, nRate );# I. q- N; U1 B
        fds.Setup ( fClock, nRate );
7 \4 C* R! x2 O' [" w' C        n106.Setup( fClock, nRate );4 h" W) K1 Y$ q% N8 H( N
        fme7.Setup( fClock, nRate );
0 l3 C, O# ~3 A( Q}
$ g% D( K. c) G% I  \0 N6 S/ e  c( R/ V5 T6 C# C
void        APU::Reset()9 P2 ~8 i- ~: z( c3 N4 c& Z
{# L1 W* r- G% M, ^! o
        ZEROMEMORY( &queue, sizeof(queue) );% ~/ g' i, C# `. H1 r1 @& b3 O
        ZEROMEMORY( &exqueue, sizeof(exqueue) );: P! I; [$ ~0 ]1 n2 Q

8 X/ K8 f# u: `" v        elapsed_time = 0;
4 X3 }) |" P- X8 X4 c' q3 \- j( J0 i
        FLOAT        fClock = nes->nescfg->CpuClock;, A  `& w" p2 }
        INT        nRate = (INT)Config.sound.nRate;+ p* H) E5 p4 A
        internal.Reset( fClock, nRate );
  Q0 e' e& U" [: B0 O6 h( z0 c1 T        vrc6.Reset( fClock, nRate );
4 u$ O1 D8 U. f* ]# c. A' L$ X        vrc7.Reset( fClock, nRate );4 Q1 g. Q  s0 _, I% w$ w
        mmc5.Reset( fClock, nRate );2 ]8 ]5 `3 s( w+ h3 Z" d9 S' N
        fds.Reset ( fClock, nRate );
" ^3 t$ ~2 u. ]1 A! l; n( @        n106.Reset( fClock, nRate );3 y5 w( D5 U3 n- n
        fme7.Reset( fClock, nRate );
3 v+ ^4 ~  [8 j& N- H9 z% [' I* p$ q
        SoundSetup();
9 `  e: u1 P* y4 _* k3 j0 v}
. o7 i& g' b0 J8 D& x! u9 }5 l, @. C; q. v0 {3 ?: w
void        APU::SelectExSound( BYTE data )
6 |8 K5 C3 e5 V( b{/ }( n( A) W4 ^6 z
        exsound_select = data;6 @# Y% U) p: k2 [! ?4 M) K
}
+ E6 U+ }  K# b  r3 @5 E& J7 E0 Z4 S. T. E* G1 H' s& A4 @" V
BYTE        APU::Read( WORD addr )( |2 r1 b( f% O  B8 c( a7 v' J
{5 K$ R7 [% `1 n' M5 _
        return        internal.SyncRead( addr );2 ]: j7 m; J+ J) x
}
9 c( w% j6 ]) o$ x/ J: F6 x, N2 |9 Q- Q
void        APU::Write( WORD addr, BYTE data ): ?  y& b* o7 K+ T3 m5 Y$ b+ R+ ]
{5 C) \& L  |  X$ G) ~7 ?
        // $4018偼VirtuaNES屌桳億乕僩
& y! r( P3 D3 M' o1 z0 O        if( addr >= 0x4000 && addr <= 0x401F ) {$ g& l: g1 \) X, z; r. j. @
                internal.SyncWrite( addr, data );
7 {# s  n) T3 S2 r                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
3 k5 t. T& B6 E7 l& |" {+ Z        }
# X; {6 m7 _0 i}' S9 Z/ K: D9 h( L( f/ ~9 z& A* f% X$ C
. V+ z$ B7 N2 H. q" }; \
BYTE        APU::ExRead( WORD addr )$ N( Q' y" N5 e& H8 d3 V+ z. T
{5 U2 h& G! g$ p0 L
BYTE        data = 0;
" z* `+ n/ }, a1 u' E
2 c/ [- @7 @6 M        if( exsound_select & 0x10 ) {
5 O# f5 ]. H; l' P4 g                if( addr == 0x4800 ) {
) i& S5 R; C6 W7 T8 d4 H                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
9 _+ l2 X' x4 X8 _; Q1 |; E) X                }9 B6 I' c- G1 k" L
        }
1 j" U+ X+ s5 k1 k% a% y; P        if( exsound_select & 0x04 ) {
8 x8 ~4 Q, b( T0 G  a+ f                if( addr >= 0x4040 && addr < 0x4100 ) {+ x" Q# l) V6 I8 s5 G- v, K
                        data = fds.SyncRead( addr );
8 T/ h3 ]7 W* H4 t                }" J5 \6 T  |1 d
        }8 J2 R4 d! _/ w7 s$ e
        if( exsound_select & 0x08 ) {: u) \; `! M- u! @( D
                if( addr >= 0x5000 && addr <= 0x5015 ) {- Q2 @4 J3 m! q9 K$ i6 u- @" Z; f
                        data = mmc5.SyncRead( addr );4 J/ K7 e. M: t2 C5 e
                }
- F0 k8 O" z! ?2 F3 y) U        }8 L! K6 q* I: r/ I

# F2 Z2 X0 B9 d1 [- o        return        data;
' v# ]/ e7 K9 u}
# F+ }7 V8 R9 F' a  j) X; I4 i4 V# e( q% v; I- j. C7 _) U! j9 D
void        APU::ExWrite( WORD addr, BYTE data )
8 x  G( x8 }; c1 k' p6 E{
7 @: ~/ r  b' F% z2 N2 ?        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 F9 B2 _. h* d1 G. _% @1 ]% p/ ]
8 ?# l- M$ q) i2 r( g& x        if( exsound_select & 0x04 ) {
6 ]4 p  G6 H8 M% }/ [3 B                if( addr >= 0x4040 && addr < 0x4100 ) {
, @' G- q0 r: J5 \) g* V" Y: ~                        fds.SyncWrite( addr, data );
( W4 O) E6 F+ \. S. N5 [5 E2 y                }
  ^  X" W' z; O# V: }6 J& w. x# @        }
4 v: @  t6 b7 k* m; J/ n, C3 c" Q4 U6 f5 H6 k! T; e
        if( exsound_select & 0x08 ) {# ~: g9 z0 e( M! B6 ^3 o
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 {, n6 p9 R7 h2 J3 _2 u                        mmc5.SyncWrite( addr, data );
: O  b5 s$ `, f' w, W1 F                }
1 Z3 V! s" J9 B# N- O5 w( U$ N0 }        }
9 L) {9 {$ l! a" U/ S) B}) {: F! }, e8 o

7 x5 u% S8 c! h1 M! l1 ^void        APU::Sync()) V% V9 W; X1 S8 k
{
8 O' ^; O! e' Q) v9 Y  ?7 r( }; `}
; V6 n$ e- ^0 X! V# `- Z+ t/ }4 _  l
void        APU::SyncDPCM( INT cycles )
5 \) |! b# q6 G8 G: I{! q3 G) R/ b0 s2 C6 l2 a+ p
        internal.Sync( cycles );
& C7 @1 ]; x5 M) j% ]+ f
8 |; m: ?1 T) f: D8 ?        if( exsound_select & 0x04 ) {' T& }0 ~5 u) T9 K9 ]
                fds.Sync( cycles );% |1 Y  w' P; r# h! k; W
        }$ |* t" D& {( w, D1 ]" F- Y; f
        if( exsound_select & 0x08 ) {
0 e" H6 ?1 M' }4 }- G  ~) k                mmc5.Sync( cycles );
1 T4 O, s% [, N! D        }
" j, t# U* g+ ?$ H" D7 u$ ^}
' v. {1 [( p( u) I- e& ]" c% K& Q  _0 a6 `, Q# s2 m
void        APU::WriteProcess( WORD addr, BYTE data )1 @8 D& W! F4 Y' W
{
1 z  n6 ^, ]" q, k& _% M9 M2 D" W- V        // $4018偼VirtuaNES屌桳億乕僩5 x" o, X8 [$ W- T7 t: G
        if( addr >= 0x4000 && addr <= 0x401F ) {
4 s9 r0 v" k, F5 J                internal.Write( addr, data );7 {- T0 B6 e1 X! t. t( v' F3 ]
        }9 K& c1 o. D- }  j2 Q! W3 }
}0 i! L; ^, n  ]. h
0 a" ^4 M7 H8 L7 ~( F, @
void        APU::WriteExProcess( WORD addr, BYTE data )
: l  G! \! x6 ~& Z{
8 f7 f) t* O2 b0 g1 l* r        if( exsound_select & 0x01 ) {$ D/ J" ?' `3 a) O
                vrc6.Write( addr, data );6 ]5 D5 r! I) v- X6 A
        }. v+ ]1 {; c% R( n' X
        if( exsound_select & 0x02 ) {8 R1 ~, @" ?/ p, n
                vrc7.Write( addr, data );' K+ `, L: T. ]' R8 @  \$ c
        }; h1 o( O9 S! U, y" J4 |
        if( exsound_select & 0x04 ) {+ E/ a- W1 ]( ]# Z" |" k2 S+ M, r
                fds.Write( addr, data );
4 I! I& r& u1 f- M7 O7 s( ~        }% u% W9 q- D3 E" q7 C# o- V
        if( exsound_select & 0x08 ) {9 d* T  k/ H- q0 N' j' ]
                mmc5.Write( addr, data );8 z* v6 v0 |* K7 U
        }
1 G* ~& ]/ d: {- M/ K        if( exsound_select & 0x10 ) {
% d, v) d7 p8 u1 H( {& q                if( addr == 0x0000 ) {
# E- d7 N% G6 q/ N                        BYTE        dummy = n106.Read( addr );
) m5 t4 u2 q  L8 t                } else {
1 Q& t% P) C. O# s0 F8 _! T4 o                        n106.Write( addr, data );5 y  L3 z9 b+ E4 ^$ A. ~1 {; D
                }
- X2 Z- m8 |  G" y# b  i        }) _' o$ a% Y% F7 I8 v' x
        if( exsound_select & 0x20 ) {
, J6 O) D9 k+ Y) W                fme7.Write( addr, data );7 ~6 B7 f7 p- G# a
        }4 l" W7 K! _4 y  U# I; g. g- \
}* m3 O3 G) G  n
5 v* h; R7 T8 \  F0 f
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 |( i# P1 c$ T" M0 a% ]
{" _: }$ c" y+ V, T( G1 @
INT        nBits = Config.sound.nBits;, M: X3 [7 t7 P9 M9 n
DWORD        dwLength = dwSize / (nBits/8);* q, ]+ X* I/ _) V6 f
INT        output;1 {1 ]6 U# v4 X5 T( x3 ?2 y6 }3 N
QUEUEDATA q;4 i; s% s: c+ ~! |; ]
DWORD        writetime;( j+ o  o9 x! ?# g/ G
6 K1 v$ U9 h4 Y; h' L$ ?( I7 O
LPSHORT        pSoundBuf = m_SoundBuffer;
/ }1 M2 J, M: h9 d; z3 QINT        nCcount = 0;6 T) Z) `9 U+ u  k$ n: J- O" I- Z7 ^2 ]

: C( e3 R' D$ j/ K6 g9 r. G/ f% RINT        nFilterType = Config.sound.nFilterType;
. `9 q6 e  g' [" K9 k1 ~0 e# X( l
" S- [+ v0 l/ v& C: c1 M        if( !Config.sound.bEnable ) {
/ s: R/ ~( H8 C/ `& x' n                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );2 o0 J" n% V$ k7 q" x& U  C
                return;
0 h3 f6 i) {- Y- S: K2 o5 V        }# Q1 Y: z4 w0 |8 M9 K3 G
4 p4 ]. F. i% w# X4 D
        // Volume setup6 o# p4 |, y; o: X+ I5 j6 r) a
        //  0:Master/ [* O. }. {! D: |( X7 W1 J0 _
        //  1:Rectangle 13 {# P( F7 a! P/ F3 `3 W2 D) _: w
        //  2:Rectangle 2
2 Y" [" ?( _. ?9 i% w' X        //  3:Triangle& w3 Y! {: |5 V( E! A- m  w. x& `
        //  4:Noise- @$ {( j/ k( Q/ O. j. f7 d
        //  5:DPCM; O; B6 x$ v  E# Z! Q2 b
        //  6:VRC6" j( U! v. H5 m5 {( N  T4 O
        //  7:VRC7. E  F( I, C3 W2 y& p
        //  8:FDS
3 Q; _" \+ G2 s) |$ Y0 V& e8 j        //  9:MMC5
2 h& x' z6 t' D- }: s* W) s0 g$ a        // 10:N1069 _' u5 S1 U  h* ^, ^6 z
        // 11:FME7  I* m- X7 m& ]) q0 a
        INT        vol[24];
) E8 P, j; p- q        BOOL*        bMute = m_bMute;& v; d. B1 K6 d+ f7 F$ w
        SHORT*        nVolume = Config.sound.nVolume;
) r* I; T. `4 [' V
: j7 B6 y+ Y5 v8 i8 c        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
3 A7 [- V( T2 \- N9 s" S2 E# |8 ^1 ^0 i  }
        // Internal
3 R- O$ E2 o& E) W" T4 ^9 k# ~        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ `. F" K/ r7 r1 k. h( S3 s# ~# m6 w
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
/ h  d6 G. b6 F6 a% U        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
! y' }1 x$ A0 q& i6 j! b        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
1 ]6 n/ g' N" g/ D" V' y        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
0 h, ]. L; }, Z
2 Y  ~! ]! \: c6 E5 e; l" E        // VRC6% u0 w* c2 p" E
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 |. A4 c" W# q& H( A& Z
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ P& Y/ O9 F! R2 E        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ R! ]9 J3 R# v) ~
+ X- }+ ?7 C: G8 w' j: m5 J
        // VRC7
1 I5 S7 I) h; D) E, @3 _# @9 L        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;. Q0 g6 W2 t- }3 _6 K( F2 a* x: o( Z! p

4 k1 i- @2 w! l1 T! y  O7 q        // FDS
% e$ B6 U7 C$ T* S0 r        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
3 ^/ C2 b2 M8 d8 J  A9 O) m6 l, \  T  ]9 [( S! i
        // MMC5
" ?* I( I/ J7 F  P        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;. B: p: b6 L. |, v  [2 O! O
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ W( m& v: j" r* _% u" j        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 N7 Y3 [  |* U: Y0 j' |' r/ \
# I+ a3 U. n- k! P9 r4 b+ O4 q5 M        // N106' x( L0 R1 Q# K* p& f
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, ]9 V- V! x: f( S: N! I: k
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 X. ?: e  G9 V, R1 J        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 ~9 t+ i" _+ O% H6 v3 P
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
: J: ]  v4 \9 H$ x: \+ A0 [( A        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& _* u, f7 i  J  k9 t
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
8 w. H  ~# ^: {5 z- x$ _1 S        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% @% ^4 W' G' [1 s( x        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 a0 c( E/ c) W! p; I6 I4 o' @

9 E0 C' K+ Q- G. U% t! `        // FME75 Y9 E8 F9 y; m) d3 @- g$ E) i7 ~
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ C1 z0 H9 b& u- K2 r6 K
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 b: ^) b$ `/ e& F' ]! q: S
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 k5 z' ^- p% l5 X9 i3 O8 M- c' A) r* t8 E
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;! W; P# K% p; Z* K
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;0 _: `, ^- X; W

1 P4 A/ Q; j3 I1 ]# `        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
7 u6 d. t/ ]; n+ o  c/ w# {        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
0 v; n' q* b/ _( C0 o9 u- t1 i) }                QueueFlush();
9 h+ y- X; L& p5 H) Y        }6 C7 u$ I, f5 o/ |- F4 L  n9 H; O

) c5 v' T# G( D( y) g6 W        while( dwLength-- ) {
. e5 y; z& N, u; S9 p3 @1 t                writetime = (DWORD)elapsed_time;4 i; e' o0 N& G; ~; ?+ o
- u$ s! |& h. y  g; Q, z
                while( GetQueue( writetime, q ) ) {
' J8 E$ v% L# C* q) A: w                        WriteProcess( q.addr, q.data );
& D5 s+ f7 B8 \/ l  y- X0 ^* M                }  d) T: H, e7 V; z
7 m' R; Y" k* a
                while( GetExQueue( writetime, q ) ) {4 `) ~, R" k/ {9 b5 o7 `% D! c
                        WriteExProcess( q.addr, q.data );4 ?' x! @1 o# t7 {8 {
                }* k. B. x) Y' M! N, o/ f
' O  m* i1 Q, A5 ]  u3 U* K, _8 s
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
0 Z3 \3 H; |, `5 N3 j                output = 0;
; W: f# S/ a6 z                output += internal.Process( 0 )*vol[0];
- |: C1 F* V; T3 E* B                output += internal.Process( 1 )*vol[1];
4 K$ h* R7 X) k$ x, c, ]+ B/ p5 [                output += internal.Process( 2 )*vol[2];
/ @2 `! e) d" C: F3 F+ k                output += internal.Process( 3 )*vol[3];
5 T& f# Y6 y) }: E) [- Y                output += internal.Process( 4 )*vol[4];
; i) L! y# ?7 w3 _' m- w- V& n! U0 |  p- A1 h
                if( exsound_select & 0x01 ) {1 b" K: I7 W+ e9 q' O8 f, Z6 f5 F* {
                        output += vrc6.Process( 0 )*vol[5];
* y% Y- i  S; Z9 @2 N' g                        output += vrc6.Process( 1 )*vol[6];
9 a7 g. n. W) G- ^2 C" j% _4 V* L                        output += vrc6.Process( 2 )*vol[7];
2 s2 J0 E$ z& b4 {4 E                }3 \% \9 ?9 F1 Y1 X! U5 Z
                if( exsound_select & 0x02 ) {
; |2 z6 k' h0 `) ]                        output += vrc7.Process( 0 )*vol[8];" h% N; S" L" U. Q1 E  G$ R0 j% Y7 s
                }6 t" j8 C# T: G* B" L( I) L% Y
                if( exsound_select & 0x04 ) {
6 c2 V, P0 {8 p2 U9 L                        output += fds.Process( 0 )*vol[9];9 J& ~) ?6 [3 ]0 w+ s3 e
                }
1 e+ O, q" A( U; H4 P                if( exsound_select & 0x08 ) {
+ f' \* p8 ]% M$ \( T                        output += mmc5.Process( 0 )*vol[10];; k4 O& g9 G: i6 t, i
                        output += mmc5.Process( 1 )*vol[11];
4 H. ]- a* ?" I6 e  w2 c4 d                        output += mmc5.Process( 2 )*vol[12];
( z& W" [& ^2 Q, w% {                }
! X/ i& S, Z% V, C* P/ m& ~! V) q3 i                if( exsound_select & 0x10 ) {
* S9 S1 K% l8 G9 R                        output += n106.Process( 0 )*vol[13];7 A% {" g% W2 a% @7 x+ ~1 y
                        output += n106.Process( 1 )*vol[14];6 p, d" c! g" I; X) X. P
                        output += n106.Process( 2 )*vol[15];" y1 ]" X4 W' o# _! L  t+ O
                        output += n106.Process( 3 )*vol[16];
6 W' f. l- [2 n                        output += n106.Process( 4 )*vol[17];/ W. Q4 t/ C/ a' h
                        output += n106.Process( 5 )*vol[18];# ]+ Q) i. U: f; }5 A
                        output += n106.Process( 6 )*vol[19];8 P# v, K6 S' p$ o$ |$ e) |
                        output += n106.Process( 7 )*vol[20];6 D; c9 Z+ ^4 J; z4 J7 W9 E* d
                }
- e* d5 `7 ^' Z                if( exsound_select & 0x20 ) {
# f) J& T! A- D2 E6 L                        fme7.Process( 3 );        // Envelope & Noise  Q7 M0 a  z- b
                        output += fme7.Process( 0 )*vol[21];$ u1 |# R/ ?& [( e; O
                        output += fme7.Process( 1 )*vol[22];
, C( r) W- E0 f2 S+ y$ d6 H2 \                        output += fme7.Process( 2 )*vol[23];. U6 v" m2 O1 }( {  E
                }
; C3 q, X3 Z9 `+ u/ [6 T' o6 H/ S! _% d9 ~
                output >>= 8;
* N1 r7 E1 H9 F3 Y, s0 m' a5 u8 [, L7 d/ t. C) c- i; @) a7 a
                if( nFilterType == 1 ) {
% Y, D/ m3 A$ X8 i% d                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 ~# U% V: C! ~0 \- O$ K$ B8 T  p
                        output = (lowpass_filter[0]+output)/2;
9 g" t4 }9 h- ^4 D3 d$ w                        lowpass_filter[0] = output;
) B2 ?6 T  K! n/ b8 q                } else if( nFilterType == 2 ) {1 ~4 E8 ]* X# {2 ]
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)$ `0 P* s9 L1 K% [  R
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
$ x4 V8 C" N6 m! M! I                        lowpass_filter[1] = lowpass_filter[0];/ |& @0 i6 U' J- O" L
                        lowpass_filter[0] = output;5 F# G+ ^1 x( E' k7 [
                } else if( nFilterType == 3 ) {
5 d7 J0 T5 p1 a" _% ]                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
% W; z- o- I$ L. W$ T5 l+ `, ^                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
$ b  Z( T0 Z0 S+ R3 p0 e  L0 |" j                        lowpass_filter[2] = lowpass_filter[1];
0 v) P1 K. @8 X/ t. _5 B& n# r                        lowpass_filter[1] = lowpass_filter[0];
0 \  W) b( p1 m5 O/ f! m0 ?8 q                        lowpass_filter[0] = output;
7 Z2 g8 e0 S( Q/ P& m7 x2 U                } else if( nFilterType == 4 ) {4 i6 G+ Z5 L$ s" X8 L
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 ]% a9 H2 t& }                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;) K8 s, B4 `8 V8 w* D
                        lowpass_filter[1] = lowpass_filter[0];
$ H7 G, a/ u+ S5 h* i6 |1 t* T# m                        lowpass_filter[0] = output;& Z$ Z  P, U' U$ E% L; I" o
                }4 ^$ {$ ^0 F+ u
7 S0 a) P8 w4 h, |$ a/ N8 T
#if        0
( D; y% X9 ^4 x% U! t3 D                // DC惉暘偺僇僢僩, H) s# R3 i) N7 C
                {* w2 [& W, A! q; |( n  l( o
                static double ave = 0.0, max=0.0, min=0.0;1 _2 S2 o% [9 u
                double delta;& ]  D) |5 q3 b0 ?9 G/ Z( @5 P
                delta = (max-min)/32768.0;1 O  Q- Z+ i2 |) R
                max -= delta;
0 ?/ \5 X( N% u0 b! l                min += delta;8 g! p2 {" P% Q, b4 X/ c9 i; F
                if( output > max ) max = output;9 h9 U- z; R$ y9 G6 s
                if( output < min ) min = output;
& b) O6 r% n7 i# G6 e                ave -= ave/1024.0;$ b: [6 Z. u' w* [" }/ e' Y! ~- ?
                ave += (max+min)/2048.0;
9 K5 o3 n0 i" A  [- M, q! w                output -= (INT)ave;6 z; \! ^3 P5 Y, O
                }/ \& k+ w' W/ k0 @) M* S
#endif, h( g. Q2 o$ K" s( @  b
#if        16 \# J: ?( b- d& f2 J
                // DC惉暘偺僇僢僩(HPF TEST)
# W4 d. K4 d1 K* R' o                {
0 v/ e  Q4 X* q# i: s5 {//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
/ Y1 o8 F8 F: \" J" \6 {* Q                static        double        cutofftemp = (2.0*3.141592653579*40.0);9 Q6 |7 \9 P3 [1 M8 x
                double        cutoff = cutofftemp/(double)Config.sound.nRate;' n+ d/ q. \6 a- {9 s( u2 q
                static        double        tmp = 0.0;- B" j: U2 Y; s) q
                double        in, out;, t/ E* p' N+ r, X
" p: ^* ]9 n, a' M7 f. `
                in = (double)output;
  m$ p& L- e" ~3 b' {$ D% R" Q                out = (in - tmp);: _8 q# s8 k7 g' c4 W6 d$ D
                tmp = tmp + cutoff * out;
$ Z. E+ F- S0 O9 O! Y1 ?; |9 N) _& F5 B! L+ D/ k: e5 g- ^* \! t' l
                output = (INT)out;
1 N8 O+ `3 D- o) q                }
1 n/ y& ?4 @* v5 A& I; D4 k/ Y. h#endif
7 e( M! F# W0 g, m$ Q& K: O' G% a/ \#if        0' r& v7 {0 ^9 O6 V5 ~: o5 U
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
9 a2 y+ T: M8 Z; x8 j                {
, \0 \6 S6 g/ k                INT        diff = abs(output-last_data);
3 i% C5 J; `7 U! f                if( diff > 0x4000 ) {: R$ L4 V  s1 L9 R
                        output /= 4;
7 P& T" Z5 Q+ P  y  y3 [                } else 5 \5 q- M- y: m% A" q
                if( diff > 0x3000 ) {
9 @5 `$ O( u% y$ Y3 r$ N" R3 o                        output /= 3;
. P/ w5 `  C5 b  }8 U                } else6 B: K' B9 h8 s  {
                if( diff > 0x2000 ) {; q2 q; z5 k! M' ]. @! b: y
                        output /= 2;
: A# n! v' N! K5 O# o) W* ]: c                }
) ^7 C1 n' W& P; W                last_data = output;
0 j0 U9 a3 x. l  q/ i$ `0 M7 K                }# f/ U9 S+ {, h5 ~: {
#endif8 _  m8 L& _$ F9 Y: o
                // Limit
8 e7 ?1 m7 `) Q, ~4 u                if( output > 0x7FFF ) {; E2 F1 N  A/ z' v8 f
                        output = 0x7FFF;
: ?& N2 q: _. q6 B; h1 _2 a: s                } else if( output < -0x8000 ) {) i+ j6 z9 F1 h& j% x, R, L9 x
                        output = -0x8000;
9 L! [& Y  N0 b- w6 M7 J- Y                }
7 z9 e- i. `+ ~  w+ }' B+ S5 p- ?. T+ x3 Y0 x  J; w
                if( nBits != 8 ) {% J; D: n2 k" R4 E% s& ^' X
                        *(SHORT*)lpBuffer = (SHORT)output;
. O% s/ h2 w: E) n                        lpBuffer += sizeof(SHORT);8 `6 i2 l! u+ O1 }* `
                } else {) U0 |. J" ~+ N* u% P6 _3 ?% G
                        *lpBuffer++ = (output>>8)^0x80;
3 U0 y2 n, q/ }0 T                }9 K5 ?8 |6 ]) E* \
  G3 ]* K1 Z0 B& p+ J6 `0 U$ k
                if( nCcount < 0x0100 )
: r' e2 I7 @! d                        pSoundBuf[nCcount++] = (SHORT)output;0 a5 [- ~# x. |
& c  \9 M" k- p8 k
//                elapsedtime += cycle_rate;
1 T2 w4 f2 b. h9 E                elapsed_time += cycle_rate;
: g% k) k5 B% F  j        }
& n+ }, s* _4 ]4 W( U
: H, S$ i+ j" R/ m! \#if        1- @" Q; l# c5 v( t- c
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
# T, h2 K7 \# e- N6 i) ]0 t. J. o                elapsed_time = nes->cpu->GetTotalCycles();, Z, e4 k( f% q7 A
        }1 L) O; m( _, H
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
1 O0 ?9 w6 y! d* A/ x7 k9 ]& P2 E                elapsed_time = nes->cpu->GetTotalCycles();9 s6 q! ~" B" k9 H
        }4 u: w1 V: C4 @- X( \# r8 w  ^2 ~
#else+ _* D( V! H( R$ u$ ?
        elapsed_time = nes->cpu->GetTotalCycles();
: X) j3 u+ u7 P, ^+ e8 ~: S#endif% F; A) U2 V& o0 ~- C* i! B
}
# n( ?* S% i8 [. i# X" \7 i) D# @4 r
1 z" j2 c7 B1 ~// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
( m. K9 d# r5 CINT        APU::GetChannelFrequency( INT no )
$ G  W/ r% J4 h" H, Q{* @, i6 v/ k4 G& [, y8 V# y' w/ P
        if( !m_bMute[0] )4 q: j! r  W2 I" R7 r0 p$ K
                return        0;% M( v4 h% F4 g9 T* B. R6 D) g6 j+ f6 Z

. v9 K7 X2 C$ S: n& k        // Internal
7 ]! l* t( R) Y# T  O, a2 C        if( no < 5 ) {. X6 D, I# ?6 c4 |2 h4 B9 J
                return        m_bMute[no+1]?internal.GetFreq( no ):0;/ N/ E7 P; Y" e) l# G! W0 H. ^
        }
( U5 F( C& U3 |7 u+ [- y        // VRC6
: @+ I3 l# w9 O; \, X        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
. [- B! o) ^2 N                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
' P, o' w4 |* h2 C, H        }: [! C* u# }; f4 O' `# V
        // FDS
+ M$ S+ {7 V- l7 ?. d        if( (exsound_select & 0x04) && no == 0x300 ) {. F2 M2 u# q. p+ a+ e  B5 u& f
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
% I/ F0 ^) D' M5 ~" }        }3 _! C& v5 b4 C$ V7 h9 t
        // MMC5
- d2 y2 A# }, Q! ~        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {; k( m1 ]: U! w  }4 o! I$ Y
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;+ P2 a+ u4 E; a( ]; z& B
        }
1 F4 e3 v; ]) B        // N1065 r: c& V* ^0 O0 @: y2 s
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {0 f, t$ Z! I* K/ s% `
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
- }9 M7 X0 i( t! Z8 K8 Y- U        }
  K" q; W! X( x/ J: b7 O        // FME7
. H3 T7 v9 Q. W* Z& i, A        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {! S% T2 ?, m- `2 ?, R" }
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;( K: l+ t- j1 }9 m# g
        }* j3 F& o& }+ c- m; ^! n( t! W4 O
        // VRC7) F( }5 T3 `0 k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
( }3 F$ _  M0 @) D) |  e                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;- ~/ j. o$ K. V: ?
        }
, M9 C6 u- ]" F        return        0;" x- E' ^6 N5 f8 Q6 m; `0 W
}" G- N( C. u/ _/ f! R( o& h/ V" \- q

, L* T' V0 g- A2 B. N! J: Z& s// State Save/Load* G7 b- Y. s1 d' w/ `
void        APU::SaveState( LPBYTE p ): P! Y- M" r- y! o) \) v
{6 O. J$ G$ L6 y# r: \# @+ E5 W
#ifdef        _DEBUG
# ^" ]9 ?6 _7 b1 m4 MLPBYTE        pold = p;
% o5 U7 r; y3 j/ P! Z0 a7 R#endif) p2 r' R0 E/ |- M3 m

) s- v9 M3 m* f* b        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 u  }+ x8 t5 q7 b        QueueFlush();1 z1 L" }3 `0 f' o4 b) c6 ?

: ]: [$ P' q5 O/ h/ m4 p        internal.SaveState( p );. L' r. u4 k( p1 q0 v, ~$ p
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding7 ^5 q1 t) J+ q9 V# u+ W

! H: G! f; K8 P- |) I0 T        // VRC68 U/ Q: V! N0 B- ^
        if( exsound_select & 0x01 ) {6 _0 |9 U9 n8 i1 H7 h6 A
                vrc6.SaveState( p );
. h3 ]* m4 b+ d5 g& f                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 b4 P4 ~! u! a
        }  A. h: b* d  i( @
        // VRC7 (not support)4 o5 v' W2 A! v' z5 H5 A
        if( exsound_select & 0x02 ) {" N. |% A2 j& K
                vrc7.SaveState( p );, _0 }8 S  c  v4 E7 [
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding$ K" P0 L8 Z! g5 I
        }, u" b' g( d4 Y/ u  n
        // FDS
2 ]1 L3 R* Y% d        if( exsound_select & 0x04 ) {
- l' M3 r5 ]: N- f$ ?1 o3 T                fds.SaveState( p );# \' Q9 X  w: I3 h5 e
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
9 B6 w; ~9 y  R9 ]2 f; b9 h+ Q        }, R  J# A% B# t5 \, n2 ~+ x
        // MMC5
4 V/ R2 [4 h4 x        if( exsound_select & 0x08 ) {  C0 ^0 O. V7 Y. P$ |
                mmc5.SaveState( p );. W4 W0 {- ?9 j- l2 U6 p# T
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
$ }  n  p& S% r3 c6 w        }0 f( I1 E# C- x% }( m
        // N106
2 J6 G9 ?& Q1 A# e        if( exsound_select & 0x10 ) {
; _0 {. D6 g- K% V                n106.SaveState( p );
$ a3 w1 u' l$ I9 o# d                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& ?  x8 ~1 ~% C% c' X1 [+ E
        }
4 i" _2 U, ]) a/ l: [- X' L        // FME7" |. e# K0 U* p; I( P# f
        if( exsound_select & 0x20 ) {
6 A+ F, d# j7 ^. W                fme7.SaveState( p );$ F# A4 c, h. a3 j' c- e' |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 F+ d( H1 B# m, t. |
        }. [" T7 ^" O! u" b5 U/ F: j* Z
4 C6 D0 K: b5 x1 D; \
#ifdef        _DEBUG5 j$ n1 E2 Q% v0 b- E
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );  }/ H! O: i( d/ L4 r
#endif- x; H/ Y$ U( y: V$ M$ h4 i5 k
}9 A" _8 G: A% ~2 y, F; u

3 a0 r3 D- x0 w0 Dvoid        APU::LoadState( LPBYTE p )
* N- P" b9 T: k- B{6 R8 i5 u: [( v5 p: {) C  U/ e
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
. g/ z( f& |3 l3 d2 X3 S1 \        QueueClear();
. N/ M/ C  `3 Q
) @7 n( b5 P4 B# C$ [1 r& U2 P' @        internal.LoadState( p );
* g" {! W5 g9 k0 c8 t6 c        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding" L8 {3 P% k, J& I
  W3 @9 @+ A! _2 ^) E5 o
        // VRC6
$ V+ V# G& W( a) o# ~4 V        if( exsound_select & 0x01 ) {
) G( K0 j# ~! U+ C                vrc6.LoadState( p );. ~3 X0 h! |0 ^
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding0 d: g- y* |# N9 {3 F
        }
. ^% ]! b5 V+ ?2 E2 N        // VRC7 (not support); `$ @4 j. C; L5 F5 H% i/ F
        if( exsound_select & 0x02 ) {+ ^8 t% C( I" P  i
                vrc7.LoadState( p );/ W0 o; S- C. H8 I$ c8 G5 g
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! I( L+ z. G9 O5 x        }
0 D& y% \  w' W  d, e        // FDS0 [1 U1 ]3 A/ D  s6 G
        if( exsound_select & 0x04 ) {2 T( A2 h  u# g8 P: {1 o1 ?; s
                fds.LoadState( p );
" z+ [) Z$ a, N8 k5 o5 [                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! t% H5 @* e& }6 y% b; E        }/ o/ v0 Q8 H' _3 h2 T; t, V
        // MMC5
, S; N/ B* P. I8 G+ `% g( k6 p4 ^        if( exsound_select & 0x08 ) {9 Z+ m2 ]2 }5 l$ t/ `
                mmc5.LoadState( p );
9 M2 e* C6 p1 A0 V8 g. u' Q& q" I                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding1 k; Q. P  }1 ?. S- G. P2 @
        }
& q% \' m& j# R7 V  W        // N106; u" Y- R; I( }- j6 m
        if( exsound_select & 0x10 ) {( c' b1 i: ]0 Z3 k0 x3 K; t' V- T
                n106.LoadState( p );- W. D& H* V' c3 A& Q7 f
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding  f7 e$ t/ g+ p
        }0 _( f& |. G& ^4 k# f0 m
        // FME7
  J9 Y( |" T5 X$ Q' N        if( exsound_select & 0x20 ) {* x$ e3 g: Z4 v$ j& ~7 X" B
                fme7.LoadState( p );/ s% V* F7 `6 `, l  k2 a
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
9 o0 f0 x2 A% m2 w4 `) X        }' {4 x' O3 X! J( Y1 v+ u0 O
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + p0 d+ h# V" P- M/ ]4 {+ ?& ^
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。, `3 s0 v( ?% j2 S% g! G6 z2 b
感激不尽~~
% V5 Q" A' j: k
恩 我對模擬器不是很有研究,
  N  w. }4 a# l! R( w9 Z' T9 q雖然要了解源碼內容,可能不是很困難,4 G/ Z* W8 G% t  ?9 @5 P1 o
不過還是要花時間,個人目前蠻忙碌的。
; V( W. |4 F9 V  Q. M- V( N
1 W) _5 ~4 t1 e( Y4 }給你一個朋友的MSN,你可以跟他討論看看,
2 g! x; s# F+ U, f& W/ ]他本身是程式設計師,也對FC模擬器很有興趣。) V7 f. @9 N2 a: A) e8 H3 U2 w
$ B+ L8 y* J. ~& Y, ]* ^
MSN我就PM到你的信箱了。' S: T! c. z. x  a- Y# x7 F

  ^% v5 l! F8 d! X$ E7 y! p希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
! \$ ^3 o6 n% [* ^1 ~2 b) a呵…… 谢过团长大人~~

" M: K3 D( K2 q  h
' j" ]5 ?, w* E哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
$ x" ]) {' p7 l3 w% |9 Y" t  n团长的朋友都是神,那团长就是神的boss。

4 l. l, M( m; C9 |0 w* @3 a- k哈 不敢當,我只是個平凡人,
( d$ W/ N! V/ a2 o要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
6 r8 h0 x1 O( ]# U! q9 j: k8 }* NZYH
5 e- U: i9 L, R; D* g! T* aQQ:4147343068 Z3 }2 J2 h6 `; `
Mail:zyh-01@126.com
. ~. f. D( E' s. ~& J, v
3 e. @8 |% I1 ^1 A他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 * Z" P7 l/ b, @: W% I6 X4 V" X, N
再次对团长大人和悠悠哥的无私帮助表示感谢~~
0 n0 R; S1 k( @( X
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-13 06:11 , Processed in 1.111328 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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