EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ F2 {6 G# w! T0 n0 N- c; y/ k
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
$ j7 O' G8 E( W这里有相应的模拟器源码,就当送给大侠了~~2 g) e+ ~4 i4 p! k% r  q2 i
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表   b9 V( k  z* O
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
* I, ~5 p6 G! U* h0 y# f楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 j0 C  z3 x9 {
这里有相应的模拟器源码,就当送给大侠 ...
# v2 b6 H6 f% r0 R9 i& c/ N
聲音部分(Audoi Process Unit = APU):, ]" a" q( q) C
.\NES\APU.cpp
- A) I. U/ j  g8 C& b* M: J9 H.\NES\APU.h  }/ Q5 S: }0 y% X0 v+ p. w  j( ]# I  |$ \1 N

& \0 D# N. E5 F- a2 }1 c4 G( A4 ]1 b& N& M0 ]- a
影像處理部份(Picture Processing Unit = PPU):
8 u6 \- w; y, @" [- Z0 u7 h) F.\NES\PPU.cpp
( R* N0 q& o1 v.\NES\PPU.h
* t" s8 y& a8 c7 g4 k) d
0 @4 D( V4 ~$ Z$ y. V+ e: f如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 n* J4 Y. g( u3 V) T; y3 T(由于很多专用术语和算法机理都不明白,所以看不大懂……)
7 [6 [4 M8 @4 t6 y5 ~# j//////////////////////////////////////////////////////////////////////////+ i8 h- Z6 X& p2 H5 l$ y
//                                                                      //
" s3 z2 o& R4 P% b//      NES APU core                                                    //
2 l* e/ w$ z9 T; ]: e//                                                           Norix      //
( I/ M; k' @) q5 x2 Z//                                               written     2002/06/27 //. Y7 h) E% [: y* U; c# V! @) i
//                                               last modify ----/--/-- //8 `8 S5 [5 F* O1 G0 `# j
//////////////////////////////////////////////////////////////////////////
8 _& n( B4 ?6 D* z#include "DebugOut.h") Z+ ]: w1 I8 j' c
#include "App.h") {+ e$ [- Q3 @$ M8 }& S
#include "Config.h"
# _- w) i5 D2 J: k- a. H! i3 p  v7 ~+ L  ~6 g% h! C
#include "nes.h"! X1 y* I2 h7 R$ z! |+ L" V
#include "mmu.h"  {$ M% @9 L) T4 e! W2 I5 r) D3 E
#include "cpu.h"" W& N5 r2 |- e& a8 t
#include "ppu.h"/ w) ]5 _. ]  Q5 H
#include "rom.h"
; d/ N! A! u! w) ~; O# Z#include "apu.h"5 j9 y3 Q5 z' F$ C( B0 e9 o. |

8 _2 m& T+ h( O+ _: \6 M+ J// Volume adjust
/ U* l) r& f; e! e// Internal sounds) a; Q1 m2 C; K: o
#define        RECTANGLE_VOL        (0x0F0)
% k5 z. {. W3 y5 C# {# s0 j#define        TRIANGLE_VOL        (0x130)
& C0 O" ?: k+ ~$ C& A) B2 F  n#define        NOISE_VOL        (0x0C0)* [, F( p6 v* W, B' H
#define        DPCM_VOL        (0x0F0)
* p8 M' y# [4 Y! I0 i// Extra sounds7 J+ f9 H0 Z. i8 ~
#define        VRC6_VOL        (0x0F0)$ c! [4 u0 U" Q/ l/ ]+ o; @
#define        VRC7_VOL        (0x130)9 Z) D5 }, `1 Q2 ~0 S
#define        FDS_VOL                (0x0F0)8 j+ [; U4 i* d7 Y* S4 [! v. C$ F
#define        MMC5_VOL        (0x0F0)' }1 R! r1 g1 E% D: R
#define        N106_VOL        (0x088)
. x$ |- V2 w) M# F$ e#define        FME7_VOL        (0x130)7 X$ S! o+ H, Z$ F  u: o

- D0 x9 T6 C- zAPU::APU( NES* parent )
( E! Z3 X. V! @: V% d; F( W: F{3 D+ W6 |- E7 g# k1 }# [
        exsound_select = 0;
' Z, o0 M6 C  U$ [* K# R1 p" n( g  ?) g$ y' R
        nes = parent;+ V+ ~: W: R8 t1 E
        internal.SetParent( parent );  f4 y- J7 K; ~- c
  H" ]& v* e$ U
        last_data = last_diff = 0;
8 A! B# G1 R: b. @% f( F' Q5 B4 a: r8 R/ y, A( V
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
4 v/ q8 c( ?; A5 J& U8 V
) J- t/ t  H0 b2 w: D( G        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );3 t" U( o" Y; \  d6 D* t% V
        ZEROMEMORY( &queue, sizeof(queue) );
& X0 `1 j' u5 v2 I) |        ZEROMEMORY( &exqueue, sizeof(exqueue) );1 q1 t" d! Z0 F& z
& a1 c) M& P' I: N+ G
        for( INT i = 0; i < 16; i++ ) {" e0 R# I2 ?. ]" H; O7 ]2 f
                m_bMute = TRUE;
4 z( ^% J+ o6 `6 R! z        }% U& ~3 e+ F% }: Q' {
}
# Z! Q  V1 I8 C" `, Y/ Q: a3 L1 W& L/ A1 E) ~$ p$ h4 g
APU::~APU()
) o/ f+ R, f0 c3 v1 L. X{
0 ?/ j' z2 _9 C$ Z5 e' `}! L* [' y; A5 R9 t8 f4 C) r& R

7 C& q1 _2 h) N2 cvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
% G  ^8 T2 \6 R{. u/ Q& K) @* T' _; x
        queue.data[queue.wrptr].time = writetime;
$ T9 \7 m4 d( P1 [        queue.data[queue.wrptr].addr = addr;
: e( Q6 @: f, o8 X7 ^0 K& `) `        queue.data[queue.wrptr].data = data;! z: ~' P6 J! g* n
        queue.wrptr++;0 \6 U2 J4 e7 c6 c# H' M
        queue.wrptr&=QUEUE_LENGTH-1;# P+ S- _! X4 N! @- B* d
        if( queue.wrptr == queue.rdptr ) {
" J8 p& i2 L1 S) F8 |& B                DEBUGOUT( "queue overflow.\n" );) k! O+ s. y3 Q/ |# l- g+ L9 G- Z
        }
5 F( H( X9 M3 t3 k0 P! I}, X7 y: E. w, W5 a! T8 e- s& v' k

! P, N& b7 c# s  P0 p* wBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
2 w! r% y) _1 G# s( P{# W$ w& i# x: P* I
        if( queue.wrptr == queue.rdptr ) {
$ B% O' s7 B) H, J                return        FALSE;4 c9 \8 g* e' m+ i0 ~
        }1 X' P  g: w3 M5 t- H
        if( queue.data[queue.rdptr].time <= writetime ) {* P7 N9 q4 Z* Y. M& A0 F9 u3 y( p* m
                ret = queue.data[queue.rdptr];
; Z- h. d; g2 c2 k" |                queue.rdptr++;
# a7 y9 g" x2 k8 H) I+ O( ~                queue.rdptr&=QUEUE_LENGTH-1;
% V" C5 Z# V  r                return        TRUE;5 }7 ~9 B: `& e- k
        }
  N7 h0 e9 R3 ]1 ], m# i  \. S3 S        return        FALSE;* Z  H7 X4 H, y
}5 _- \) H% s7 D

1 ]. n0 T2 u# Qvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
2 K9 D+ n, h  @0 k& Z# @* }{
1 h  r- V: n+ _6 Y        exqueue.data[exqueue.wrptr].time = writetime;  L, b" C1 X0 _$ @& J& ~4 g% a
        exqueue.data[exqueue.wrptr].addr = addr;
0 F- w8 q. W5 j6 _# [        exqueue.data[exqueue.wrptr].data = data;
! k2 L4 ~8 i" B        exqueue.wrptr++;% j7 v9 W; b5 D* b, P
        exqueue.wrptr&=QUEUE_LENGTH-1;; j8 [5 c( k0 x  F
        if( exqueue.wrptr == exqueue.rdptr ) {
" i( \, s. {  O% Y$ r$ e  L                DEBUGOUT( "exqueue overflow.\n" );/ L/ i# y, N  @
        }' t/ k5 w% l: e& F+ E
}  W( M$ ~  r* B2 N4 L% {$ r( c9 |
" M& ~  I# \% @7 D
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )( n  y+ o% l% E9 x' z
{" V4 S' ?3 o! b, z5 D; f" F
        if( exqueue.wrptr == exqueue.rdptr ) {; k1 _5 ^' A, Y" t( U
                return        FALSE;
5 i' ?8 m  v$ l3 R* @        }
+ Z" ^2 j6 \  i% i. C6 Y3 e        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
, {4 b4 w  i. I  B) ], @                ret = exqueue.data[exqueue.rdptr];- Z! p$ Z- V: C' d, N
                exqueue.rdptr++;
7 h3 T* X8 E- @5 I& H8 S                exqueue.rdptr&=QUEUE_LENGTH-1;0 U  x* e$ W2 G) N& R
                return        TRUE;
1 m7 _/ L3 r' h) T: o        }- f* `0 s$ j' O. f6 H  P
        return        FALSE;
, f, R: ~2 |4 Z4 _5 K5 e9 o/ l8 s}
; E0 E5 @1 V+ W) Z& K7 O! q; ^. t  ~3 Z! \5 d1 L* w7 ?
void        APU::QueueClear()
7 r! p  ]/ K7 o1 f5 H% g, P{
, Q3 c/ D$ o2 h- {        ZEROMEMORY( &queue, sizeof(queue) );* C9 a4 T1 q0 ], w6 b' v! p
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ ~) W* K: @. Z; ]' |}
6 U  R+ J4 ]" Z, v. ~
! t& `# E; |8 `+ o' z# Rvoid        APU::QueueFlush()
# A. z% P5 O, V{+ j3 H% L& y, m- \# W. Z
        while( queue.wrptr != queue.rdptr ) {9 A+ u6 e5 N( Z; e' k! \
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
: ]% S9 F; e: T1 n, R% h4 o                queue.rdptr++;7 |( v. S, B4 l
                queue.rdptr&=QUEUE_LENGTH-1;
$ H* D7 m2 i3 n( r        }
+ J0 g3 n% w9 c# ~0 `4 ]$ N( D: ]! ~. P9 w3 s. p
        while( exqueue.wrptr != exqueue.rdptr ) {
3 \$ T% |1 K8 d                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
5 \3 U  C; X2 I; S! d                exqueue.rdptr++;+ q, _8 {( p! L7 U  W/ O
                exqueue.rdptr&=QUEUE_LENGTH-1;
: w9 u) K! ?% j8 ?+ ~4 T        }
5 D2 P) s; p. F, a2 _, c0 \}( E1 x7 q  w, y' ^

- G2 ]( \- S' U7 G* cvoid        APU::SoundSetup()
2 @  b/ W( h" w8 q& H6 G{5 ^# ?" b# X1 r
        FLOAT        fClock = nes->nescfg->CpuClock;
$ c1 w# |; m" C0 Y8 C        INT        nRate = (INT)Config.sound.nRate;
5 P( w; Y4 t; [5 c! C7 u        internal.Setup( fClock, nRate );
/ s$ s2 ^% v6 ]) `/ O( Q! k0 g. x, y        vrc6.Setup( fClock, nRate );
+ C2 L' w; i$ Z7 F        vrc7.Setup( fClock, nRate );# q* n4 v. ^" ]  U# }9 H% R/ {
        mmc5.Setup( fClock, nRate );# d( V7 _5 ^: T8 o0 e# y# Q
        fds.Setup ( fClock, nRate );
% q* w6 j5 z( k6 ?        n106.Setup( fClock, nRate );
: {; p5 K" @1 Q        fme7.Setup( fClock, nRate );
! C' `# x, P2 o8 A& Z}
( {4 G* N' V, }; m1 K/ z, C7 S
, t" d5 ]( d, V* ]# G0 [void        APU::Reset()% _+ E# p# d% o6 K2 d6 a5 U2 Z1 s# X
{
+ V6 i& `8 @/ ]! _9 _4 Q        ZEROMEMORY( &queue, sizeof(queue) );* G# M. F7 R2 q- k3 ?; w7 p# x
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& {$ S7 j: y: e" C+ E$ B
* T: J) N9 }1 K" n9 w) s( I1 m( ~6 p
        elapsed_time = 0;
3 N/ O$ }- n; Z, q/ V, X
  k. f! T8 z" y; g' c        FLOAT        fClock = nes->nescfg->CpuClock;1 a! f2 `% R6 U# |$ M8 V4 B, [
        INT        nRate = (INT)Config.sound.nRate;& n* Q* w* E# U8 g) [; Y  i- ?6 ~
        internal.Reset( fClock, nRate );* h( C1 J9 A' y, }  B) D+ S2 p( \
        vrc6.Reset( fClock, nRate );
) @- G  e1 g( M, ]5 t$ O        vrc7.Reset( fClock, nRate );9 X- [2 b- A* T  X* ]/ {1 m
        mmc5.Reset( fClock, nRate );
$ `) f/ ^+ P* i, P4 {3 s, h        fds.Reset ( fClock, nRate );" h  r* Y+ [8 l
        n106.Reset( fClock, nRate );
! ?  {: F8 S1 F        fme7.Reset( fClock, nRate );' i  l! @+ e7 B% U. I' i  Q
2 D% n  U+ D* d! T( Y4 @# W$ C
        SoundSetup();: {# O' K  Z9 Y) M* W3 E
}
. u5 J( N+ Z4 Y3 \9 |) t" Q
5 m3 f  c' {2 v6 A" wvoid        APU::SelectExSound( BYTE data )
5 Y& u. W! k  d$ o& ^{
0 ^  }1 m5 H2 w& M/ F        exsound_select = data;, C8 h7 {0 e0 Q2 Y# b4 @' b
}
) q  B: B) \6 n
7 ?7 s# G/ M" c; M1 U' [. N8 nBYTE        APU::Read( WORD addr )" ~( f* |: k% y& H% d( `7 j# A
{, c, a* A+ o) Y* t5 k* b0 f/ u' g/ {
        return        internal.SyncRead( addr );
; f- w( M5 ^" ~0 Y}0 P4 N  Y3 m5 {# _9 G

2 i6 {' g1 ?( o( Gvoid        APU::Write( WORD addr, BYTE data )" p; }' q; m% B/ O1 P
{5 v& \% @& l- H
        // $4018偼VirtuaNES屌桳億乕僩
- W" _* t. A3 C) L        if( addr >= 0x4000 && addr <= 0x401F ) {. q1 _$ a2 _# F7 i
                internal.SyncWrite( addr, data );
" Q- M5 d7 g- y                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
& C( t0 Y( u% a  @9 Q        }
- [, v; A0 R3 o) z, k2 \}$ [6 C/ v9 y5 u1 t

' A) q0 X- X. R+ i3 a4 eBYTE        APU::ExRead( WORD addr ), G3 d4 v: n5 U; l
{3 ]# ]: q$ y4 G
BYTE        data = 0;/ D7 B# C0 m- z1 r' m% q$ h
2 b! w  f, y( s( l8 Y  i* A
        if( exsound_select & 0x10 ) {
: x/ {- @/ \" d" z% R9 w0 P                if( addr == 0x4800 ) {0 C, p9 Z- Z/ D( p0 e3 z# w# H
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );# q$ i+ g6 o8 c' M* V' i& J0 ~( J& @
                }
/ O. o; A% s# ~3 W# M        }1 E/ l; e4 a, J5 g" C4 \+ S% [5 q
        if( exsound_select & 0x04 ) {5 Q* z1 l; ^5 D, {$ j* D3 b
                if( addr >= 0x4040 && addr < 0x4100 ) {
# ?2 n4 b- ~6 [2 h: H( M1 Y+ m                        data = fds.SyncRead( addr );
" u# X( \' c0 a1 h                }" ^  r+ t/ I3 @% }
        }
% s+ ?1 e2 Z% X7 o/ n2 C/ {        if( exsound_select & 0x08 ) {) R8 B; H8 D  H9 R$ t8 Q; ^
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! h$ T: S+ E2 r                        data = mmc5.SyncRead( addr );
/ k  _* R: f- I" `# ^0 s+ q                }; E3 K5 C8 V% t6 m* X) h
        }+ }, B, B/ a* v0 z

1 {- n: P+ b% B: u1 f        return        data;
4 u: t& i5 M$ E0 a}
. {/ h- B# a7 h6 D' |/ V4 T! T
. A) K' J3 X% _7 f- m! tvoid        APU::ExWrite( WORD addr, BYTE data )" R7 ]& D1 v2 R5 w  p2 ^
{
; w. v4 o( s  J- \) V" `: s& G        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
; y  H0 @; l6 ^  a3 ]1 s% B% A# G5 @6 _* H
        if( exsound_select & 0x04 ) {" f6 ^5 R8 Z. o0 A2 ?  O. {; K
                if( addr >= 0x4040 && addr < 0x4100 ) {
4 N$ q4 @! n: d- q" f                        fds.SyncWrite( addr, data );; h. r% E+ C+ r* a: W4 ]- ^; z
                }1 i& p( ~+ P! T! S/ l* N
        }
* C% C+ e. @% s: B: ]2 j8 v
  w5 O' A- `) X& z, [% D9 y* `        if( exsound_select & 0x08 ) {  k8 r1 o0 [+ K9 k5 Q
                if( addr >= 0x5000 && addr <= 0x5015 ) {
2 }9 S* @) _, h- p4 W! t                        mmc5.SyncWrite( addr, data );$ F, X0 y; _& l9 S0 F/ u7 H1 e. i
                }- N8 [8 O7 \% {) k' A& Y
        }
1 C) H* f( C$ y% R& g}) O, r/ M1 Y) h

: m+ u+ p2 @" e" u5 Q0 x9 f2 jvoid        APU::Sync()
2 ~3 r& O9 z" i4 I  r; Z{& s5 V/ y" t' C: l
}# _3 F3 F4 @1 j4 K
. q) V+ A+ e1 v' @9 b
void        APU::SyncDPCM( INT cycles )0 |4 R$ U7 n$ Y
{  @" L+ r/ e5 r4 }. S/ [
        internal.Sync( cycles );
% N1 v  g& K7 i0 v& ]
3 }/ ~# ?  ?+ z2 l( d9 s' d" S* Y        if( exsound_select & 0x04 ) {# L, ?$ \" I7 E2 L, w/ F% T
                fds.Sync( cycles );
# j, Z: [  b) p: M( @- ?* w        }
2 R& {# n/ O6 t+ `0 u) \) i7 Z        if( exsound_select & 0x08 ) {; T- B0 L* b# k) _! I
                mmc5.Sync( cycles );- W- f1 a" a% t9 ]% z
        }5 R: j! L. q3 x7 \2 A
}/ |6 Z; B7 D/ u

2 ^0 Y1 D8 Q: S, P9 W5 `void        APU::WriteProcess( WORD addr, BYTE data )
8 K$ h! l) {. p$ j{
; {6 x+ w0 A& ]' O+ h& E& i" L, `        // $4018偼VirtuaNES屌桳億乕僩' @9 h# q5 Y  I5 W7 F. P! [
        if( addr >= 0x4000 && addr <= 0x401F ) {
5 \7 c/ p* d1 ^# V                internal.Write( addr, data );- s6 n7 m0 o  j- e  d- K0 o# |
        }
" _6 G/ I+ D' U5 [4 f; O( K}- y; A0 V. ]2 e1 P8 C

8 Q! Z, p9 b' v. hvoid        APU::WriteExProcess( WORD addr, BYTE data )+ o: c. U1 @  e& U+ ^- }
{  b5 T# S) G1 q8 l4 W0 t7 f8 o
        if( exsound_select & 0x01 ) {
2 ~0 i* W" A9 @* x8 l                vrc6.Write( addr, data );
8 |& f8 U( \* b7 i2 _# e" C        }' o3 B7 z( P; D
        if( exsound_select & 0x02 ) {6 A; g; r) W: W! b6 @6 K5 E8 ]
                vrc7.Write( addr, data );
. I/ ]: k* \; ]: b) J; z        }
+ X- [5 a/ ~$ Q* S7 Q        if( exsound_select & 0x04 ) {
9 s& v  ^7 c( v                fds.Write( addr, data );  `- [* K" h% Q9 }: B- x
        }; b: p1 E$ R4 n' C0 ]: f
        if( exsound_select & 0x08 ) {
. _* E, w$ g/ Y: F. t                mmc5.Write( addr, data );1 P& [- \' N8 c+ l
        }3 @% U3 b6 K9 ~. b) O6 A
        if( exsound_select & 0x10 ) {" o" {& z5 i2 C( i5 i
                if( addr == 0x0000 ) {
; u7 w' o/ i6 Q" b: P5 L3 z                        BYTE        dummy = n106.Read( addr );
, X! g4 O# Y& S- |( n                } else {
5 g0 y8 l5 [) x$ d                        n106.Write( addr, data );
' A4 T* Y  W- G2 F                }
7 m- |" |: K7 \( A; _! n, @        }8 O' |) \) `, C/ {* n
        if( exsound_select & 0x20 ) {9 h6 F* \  g7 |
                fme7.Write( addr, data );
6 y- N1 Z6 D2 s' J6 z; A+ t        }7 F0 ]8 Q- l" z( D+ O! |9 J; B+ X# v
}. ]- f) _$ M2 ]% I2 m7 |! B

% @2 F& ~, Y+ I9 B# \void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )3 X* l5 ]3 W5 y6 }8 ?( E
{
6 c1 |+ t6 O( h" a" `INT        nBits = Config.sound.nBits;
: ?- G! |1 m; @/ w( rDWORD        dwLength = dwSize / (nBits/8);
: e- B7 Y' q2 n& }INT        output;
6 ~. y; u5 K" t+ @( ~4 j2 F% W) fQUEUEDATA q;
+ W$ Z6 b# C2 E0 ADWORD        writetime;
1 k( ^( }; q/ P& I+ F0 d+ a3 q- a/ O, I+ s# A) w' H
LPSHORT        pSoundBuf = m_SoundBuffer;; C* `& U- I6 V
INT        nCcount = 0;
* E  J( z& X5 w( V+ q/ e( S  X2 p" `5 S: ?8 N
INT        nFilterType = Config.sound.nFilterType;
, j+ n& d% s1 c3 o7 b
0 f5 y4 y4 t8 o        if( !Config.sound.bEnable ) {' j) ~5 e4 f5 M) S& E
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );; Y: s4 r) x2 k+ F' c5 G* z- t
                return;
# g, @  f: I! {# b  x; ?# ~, z        }
3 t, u  o+ o& z7 R" k! }
$ V9 K) x+ @1 T$ t, j1 I        // Volume setup
* u" `  W' d7 L        //  0:Master
9 W; s* C/ j1 M0 @        //  1:Rectangle 1
% x" o/ K6 h) R3 m8 w" v$ ]% u        //  2:Rectangle 2, ?( v/ S1 y5 y/ Q  Q2 ^' r
        //  3:Triangle! n( Y1 d: b% o
        //  4:Noise8 K% _. \+ S% o( b0 J
        //  5:DPCM
8 o; Z2 b& L- c3 s+ |# i        //  6:VRC6$ V$ G% x& d2 e4 i6 W" {" }$ M2 Z* \- g
        //  7:VRC70 [% B4 o+ a! f0 `4 {
        //  8:FDS0 T$ T# |9 v7 |/ c0 T6 y$ @
        //  9:MMC5
+ M- O! \4 q/ {8 C3 b        // 10:N106
: {, X9 n; ?; U# n5 E        // 11:FME7
" H3 l9 I" Z( q" F        INT        vol[24];/ L7 |9 O( t6 O0 E2 `' I8 q) w6 n3 j+ S
        BOOL*        bMute = m_bMute;; A7 l' n9 V3 _; p4 U
        SHORT*        nVolume = Config.sound.nVolume;
: x5 n" @* G  o  h- M1 }4 l
# Y* u5 x5 m& L0 {& M; ~; W        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
8 x- h6 F0 B! @5 T! [$ ?
  j6 h5 ]- `/ [0 S$ [3 m" E  V4 [        // Internal+ O+ M8 J9 ^2 i( b" a1 F
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;8 I5 {( @$ y1 ]: s# y: D8 q
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
- K0 d0 M5 Q" x; M& `        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
$ c9 @* g- W7 ]4 x& w* S        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;5 J0 v: A& h& S5 `0 M" y
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
! k8 O2 Z: U" U6 \( {2 x1 Y: Y" z# E
8 _% o& W4 N. N, n1 i/ _        // VRC6, w6 Y# p( g- |! w' n
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ R" Y1 x; E" y
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;% A( Q& y! L$ _' i# j! {9 F
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;/ ]7 M5 a8 X' U* }* l0 C
6 L1 O5 Q& ~% V
        // VRC7
- `6 }8 H( @2 x/ u; r        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
5 R; ^3 ^0 @$ L% E# a' T8 u* w6 o2 _1 H! u
        // FDS: i1 \* Q$ m+ A$ O2 `. }; {) d5 |
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& G! }/ T: ?, }1 j& Z

( Y0 o" B9 S2 E8 {1 ]8 V        // MMC52 c, p/ Z# F- V* b
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; F/ k  L6 y  C- H" k; v& \! g
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, _) Q5 d  o) G( J0 j, M        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. j3 e# F! N0 o0 V
, I# j* `) N9 F( A        // N106% [1 x* `: d* [: ?$ _1 L
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; Q% u9 ?: y/ ?+ {4 v- @/ m5 _
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 o7 V* `6 e% {5 u7 S        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 s/ P1 w1 D6 Q
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# \$ U$ ]- K5 n4 }2 M- i/ W- W        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- T* S, N; `' [/ i" F
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;% W% P7 J6 q! n5 L0 X+ j: Q9 z8 C
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 T7 T9 C3 o' a; C- \        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: c1 k& k) @& M) L* `, B

8 c" V  _% K9 q& ?! M* x( ^; B        // FME7( a% E: e% H; p
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;! e( z/ ~" a# k6 G
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 z8 S8 F& I5 r+ `- H
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 k* R( U8 `% {2 ~9 R8 Q& J7 H) o0 {7 j4 T7 p/ A! l  I0 s  z
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
1 G+ W1 L+ P: _        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
0 y' L6 E0 J7 o. I5 ^" A4 U7 z* s0 t
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
& J9 ]6 k2 ?( Y& M# A8 g% v' I! ^+ n        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ Y6 q* f9 q0 Y6 }# A7 g                QueueFlush();
1 T/ j" B' k+ s# \6 M6 w2 n' y( t        }) x/ F( b, p4 L+ a! m: f: b

! f" ^( d6 r: x( k' F' f3 ?% y        while( dwLength-- ) {8 n9 W4 z, l( V# Z- j" g/ F! G3 ?
                writetime = (DWORD)elapsed_time;
" ?. L5 E! Y9 L1 e$ a  |+ k2 ~+ a4 w9 ]8 r  d* u' q  i
                while( GetQueue( writetime, q ) ) {; v9 P0 f$ q. f- e
                        WriteProcess( q.addr, q.data );: {/ i- @- i$ L  @8 G2 n' o
                }
+ A+ e& G/ Q/ h8 Z% d
" k" n* ?6 F& W                while( GetExQueue( writetime, q ) ) {
5 l$ X9 B# e5 d4 _. N' ]+ {                        WriteExProcess( q.addr, q.data );
3 m: D' ^6 w8 S8 O! e2 x0 S& A                }
! a! w1 C4 a% k& W# _# b) Y9 ?- d8 G7 V( U4 Q) Q) m& C
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME78 Q  y5 e9 z: h+ }, L9 V" B
                output = 0;
8 t2 _- ?. P7 `- z5 v- }9 h                output += internal.Process( 0 )*vol[0];
& n7 r5 r* o2 U$ s' A" a                output += internal.Process( 1 )*vol[1];) W5 `9 ~  J8 F: F8 K/ `, L( B7 }
                output += internal.Process( 2 )*vol[2];) O: q) s0 T: B! k7 n# S0 u! F: ?1 e  r
                output += internal.Process( 3 )*vol[3];5 N! H  p& X- i4 `7 D
                output += internal.Process( 4 )*vol[4];
/ i4 r$ H9 L- L7 R0 y$ L2 i6 B* @
                if( exsound_select & 0x01 ) {
, {; H2 H+ O$ b                        output += vrc6.Process( 0 )*vol[5];
9 y7 @9 u2 t; v                        output += vrc6.Process( 1 )*vol[6];
4 M# J7 J' l/ H  R9 B' o. @6 U                        output += vrc6.Process( 2 )*vol[7];  X& K. x( U; r/ L7 s
                }
, x' D4 B# b# L                if( exsound_select & 0x02 ) {! \& l' j, @. m
                        output += vrc7.Process( 0 )*vol[8];* a, q( ^! N  A+ B
                }# Z# u- Z% j2 Z) ~
                if( exsound_select & 0x04 ) {
" Q7 K4 e. M4 H% Q" W: [7 }3 L' E; E                        output += fds.Process( 0 )*vol[9];3 u5 p7 R9 }( D5 @
                }4 X7 S0 d: _3 D$ q" J$ [
                if( exsound_select & 0x08 ) {
2 r; m; z' V; o                        output += mmc5.Process( 0 )*vol[10];% a5 _1 W0 O! G
                        output += mmc5.Process( 1 )*vol[11];" l. _. |) ], T
                        output += mmc5.Process( 2 )*vol[12];
$ i: ^" [+ c* N+ `                }# `5 B$ z; f+ l# x# E
                if( exsound_select & 0x10 ) {2 p' V0 T) O+ v* j2 z2 X# ?
                        output += n106.Process( 0 )*vol[13];
5 P  e1 b# U! l* `" {$ O3 D                        output += n106.Process( 1 )*vol[14];
) x4 ~; p: ]5 W' C; \. ~+ c) g                        output += n106.Process( 2 )*vol[15];4 a4 l4 s% V7 {- }5 @5 n' c" X
                        output += n106.Process( 3 )*vol[16];* ^6 U% r' X3 k) E# s& J7 i3 E
                        output += n106.Process( 4 )*vol[17];, \3 g  A$ Y" f
                        output += n106.Process( 5 )*vol[18];
0 o$ u7 E. p4 ^1 G2 x. G8 M                        output += n106.Process( 6 )*vol[19];; \1 g  ?% d" u0 O
                        output += n106.Process( 7 )*vol[20];- Z8 [) H& k3 [* [0 L4 a; a
                }: V1 y. A0 b0 W6 s: x
                if( exsound_select & 0x20 ) {9 Z9 N% ^; {" l+ l$ w
                        fme7.Process( 3 );        // Envelope & Noise& ]& k# a9 e( m5 c& ^- t
                        output += fme7.Process( 0 )*vol[21];
) d! h6 ]$ @7 |( h  }: t                        output += fme7.Process( 1 )*vol[22];% |2 ?8 T1 b* a1 Z# e% j8 C" T/ m
                        output += fme7.Process( 2 )*vol[23];' e7 E% C( o! u
                }' j' [2 F7 P" r

+ }( M' K1 g4 E                output >>= 8;* @- s# W+ O; T2 n" J

9 l, e- F+ ^8 @' b                if( nFilterType == 1 ) {
  s4 l# |+ A1 N( M; N                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. l/ c& Q$ `7 ?( }                        output = (lowpass_filter[0]+output)/2;
  Y& O4 c- C5 F                        lowpass_filter[0] = output;
. c) x1 F. n8 k0 g* h/ Q7 u# o8 b                } else if( nFilterType == 2 ) {% w, _9 u5 B( @( M" o
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)+ V/ _( T6 e! c9 _8 N+ F7 c+ o% {
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;( U+ s' h1 X; q3 n$ K. S: Y  b
                        lowpass_filter[1] = lowpass_filter[0];9 ~6 A# ~! b) S, s  M3 Z: B7 J
                        lowpass_filter[0] = output;% f* R+ K, [3 k8 V7 I
                } else if( nFilterType == 3 ) {* N' W/ o$ j8 E: U
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)+ ]6 o; l4 J" Q
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
0 K) K" V2 F( R4 m  J& W. j3 T1 _; i                        lowpass_filter[2] = lowpass_filter[1];
( n+ _- n' v) }( T* D                        lowpass_filter[1] = lowpass_filter[0];% E/ S; f7 H" E- N  N
                        lowpass_filter[0] = output;8 Y3 ?& q0 m2 S7 k! J
                } else if( nFilterType == 4 ) {
, c& ]; R4 [$ M5 ^+ }" b" K                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
1 B) i; r4 o, v% E4 j                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;0 u2 H: m* ~3 k
                        lowpass_filter[1] = lowpass_filter[0];$ m7 F+ N  b: r+ o1 t0 V# S/ c" i6 p
                        lowpass_filter[0] = output;/ t- X2 z7 a, V3 h- e( d$ `
                }% o: Q6 G8 c+ q) q. Z! W7 D1 y
- J$ X# b" o) f, R
#if        0
8 N) ]4 w' o5 R+ t6 @4 _" {- ?6 b                // DC惉暘偺僇僢僩1 y+ \/ O, t3 F$ D! }7 g
                {5 o# U/ A: P; Q
                static double ave = 0.0, max=0.0, min=0.0;) O% F, p1 f8 q* t, {9 s$ Q
                double delta;! a1 O2 {$ _4 y( Q; @# c: q
                delta = (max-min)/32768.0;
( L, [  p( X- m$ W                max -= delta;0 B0 Y$ _5 k7 K7 K" g0 |$ `! K
                min += delta;- v: S/ g8 L0 S% B- ~% J3 w
                if( output > max ) max = output;
# l3 U% Q0 A" n. G                if( output < min ) min = output;
. W9 E6 g9 b) {) p                ave -= ave/1024.0;
' o: p; j7 Y; U  b                ave += (max+min)/2048.0;3 i9 O+ i4 d6 ~- g. q
                output -= (INT)ave;, U: }! P; f. [8 P4 S. M
                }
  _( l& c; _4 E#endif
: l; X/ V5 q$ J% l#if        11 q- D/ v2 X' s7 _. s+ F2 U- {
                // DC惉暘偺僇僢僩(HPF TEST)
. J; F- ^  @  h2 c' q5 A                {  B- b" d8 Q( P/ s; C1 X
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
! Y0 {$ W" N0 x7 W1 g                static        double        cutofftemp = (2.0*3.141592653579*40.0);+ X. h" n- G' f. @
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
0 Y& S2 t& \  _  `                static        double        tmp = 0.0;
. R0 U7 U4 o2 S; Q) K( K! @                double        in, out;
! K9 d% W# Z1 o! f% O# ?' o' ]
6 x2 _3 a' I5 d+ T' G                in = (double)output;$ g/ b; J3 f: @' q
                out = (in - tmp);
) U0 x% I2 n. d) H$ @                tmp = tmp + cutoff * out;( t0 u. T- b. J" ~$ x
$ H% q) a0 Y! f. H% p
                output = (INT)out;
( p5 Q# g# ]& Q- z                }
  O- U' C/ g6 m. ^6 y#endif
2 ^' O/ T! D# T9 X8 R; j#if        0
" U! i4 C; }$ W  v/ B% [                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
3 V# y% F: I" h# f$ J8 V2 U6 j                {
; k+ U8 X( }- Z+ `                INT        diff = abs(output-last_data);
8 Z# q& a* D* \4 p; j, \                if( diff > 0x4000 ) {; l, I6 R1 A/ k5 Z5 S. d2 B
                        output /= 4;
8 u. }: Q, O; i: _% W, R! u                } else
4 P. w- F/ Q( L                if( diff > 0x3000 ) {
" c" B$ @# i) l7 x; K$ S                        output /= 3;1 Y  O1 r7 U5 T
                } else
6 M6 k$ Y* t" t: J4 K# I: T                if( diff > 0x2000 ) {
7 t4 ]+ C. I' t2 r+ d                        output /= 2;! [: Z) w: T! q( ?1 u
                }! E' I  Q  F7 c5 V0 d9 V
                last_data = output;" n% r( o  [. [! o! `
                }7 U& ^9 Z! o. q- L
#endif
& [3 t. h# R; f% W% @0 a6 ]6 S                // Limit
, [9 H; r0 q( q# X6 R7 y                if( output > 0x7FFF ) {
% ?$ V' n; W( Q1 a) ^9 ^                        output = 0x7FFF;
! J: E- `% _+ a                } else if( output < -0x8000 ) {
9 n& |0 k, D- H& t1 {                        output = -0x8000;! Y, U2 a4 U" t1 f1 l2 g7 W
                }
- O0 x# K2 V& |0 ]
. j$ U2 O1 {* j% `                if( nBits != 8 ) {
. O+ o8 H$ h1 B: I( j/ z, E                        *(SHORT*)lpBuffer = (SHORT)output;# Z8 w9 W& F; t1 ]8 v
                        lpBuffer += sizeof(SHORT);5 F- n! ^+ v/ l' x, Z. F
                } else {
" h- m) E9 ?8 o! ], I* M$ g  P                        *lpBuffer++ = (output>>8)^0x80;
# o! |! L% E! O- {                }! D4 \% h5 b, {( Z# Z) u

0 S9 D& p7 @7 p                if( nCcount < 0x0100 )% _2 `" L6 a/ I
                        pSoundBuf[nCcount++] = (SHORT)output;" i& W+ d5 z- B0 \' w, F7 |; j
+ A% p4 z3 J+ [+ Y1 o- B. H( ?
//                elapsedtime += cycle_rate;* O! j. h5 ]" r1 N
                elapsed_time += cycle_rate;2 ~* F- W! Q5 o( ^1 V# k
        }
6 |2 o2 b, D* w8 P: g$ _* U! E, X5 A6 @
#if        1
- m3 D  g: f9 W* ^        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
  F. F/ N6 u1 z1 ^4 |                elapsed_time = nes->cpu->GetTotalCycles();
  H; w" J# ?) ^& [        }
5 h' {4 }0 p8 ~        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {2 Z6 x: h. C" ?  M3 ?
                elapsed_time = nes->cpu->GetTotalCycles();# `3 [- S9 W% f: K, C
        }
% m. L2 v: m7 N2 i9 g7 ]& @#else
8 O* i& f5 Y) T- m        elapsed_time = nes->cpu->GetTotalCycles();
! i8 ~! {7 T" E" G#endif' x' u$ l, \" l) w( U/ v6 ?, G, L
}
/ K6 w& _! _4 W! n- H( `
' Q) A  F" f* {# y# q// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)9 z7 |. ?% d8 C6 l) w' |  W
INT        APU::GetChannelFrequency( INT no )
( h6 Y' M' p' ^{
/ I' n- s3 r' ?* z        if( !m_bMute[0] )
4 _" D9 M, T) g                return        0;, Q8 N0 @, ?' R* H4 u+ W4 D
% A; |$ V) }/ j0 U
        // Internal) x1 Y& s; S7 {  x( v
        if( no < 5 ) {1 u7 H: U/ W4 d! \3 R2 i
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
; |* R; j5 p& Y+ _! P+ K: b        }: Z8 `" D. c3 E! D' x: L
        // VRC60 o( y. w3 W& K. a5 `4 G0 G
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
* X) D' j0 {+ I/ c! Y                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# U* y8 K0 x, K# M7 u6 j
        }
, \  ~5 k3 t. ?" r) |        // FDS" M; ?, X- _" |
        if( (exsound_select & 0x04) && no == 0x300 ) {
+ `% t1 H9 o/ W/ g8 a/ a/ o                return        m_bMute[6]?fds.GetFreq( 0 ):0;
- v1 i- {- T; K3 `' `        }2 D# v9 q4 t- Y" B
        // MMC5) k" K& \* c; B$ {: f9 a/ H0 E/ M
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {  b  F1 z2 T! e, \
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;/ K% R8 W5 K& z8 O: D
        }
/ S# A8 G+ I% l# c+ {  |        // N106
+ y: o4 L0 `+ l0 I$ C        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
; G( s! i0 V; o3 H6 k4 S' T0 M                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;$ P. y6 p% i3 a& L, M( e; g5 n
        }% ]: _: A" E5 c
        // FME7
' q9 b. I% `! e$ Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" N9 E0 j# N+ h. u                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
1 {4 H+ x. W$ D1 q/ s        }0 B4 k2 v  l4 M9 D5 N. s
        // VRC7
8 ?) \6 L9 X+ ?2 G+ n' e8 J- j5 b        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {- V, W1 h5 G8 O% T
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
: I9 O/ e, x* k        }
8 L, D: V9 m2 q% m' P) @; L        return        0;
* y+ q- U* y  ]2 B) H7 d- U}( V# h. c  ]/ a8 n/ j6 _: g5 ~' J
8 f& B6 M( ^! w1 }4 T
// State Save/Load" J) q7 i9 U  \$ P
void        APU::SaveState( LPBYTE p )7 }4 J. U# @/ ^5 \$ H: d
{5 R4 q9 |& W! h8 S$ C
#ifdef        _DEBUG* n; y7 _9 a6 H! M) _- _$ U. L9 \
LPBYTE        pold = p;
' M) }' Y! h  @#endif
; F" q: {( x' T
4 c0 N* _% H+ f# t        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
0 T; U  X  J' N1 D        QueueFlush();, M+ a9 a) B$ {& X( `

  O/ d. x0 G5 N; F        internal.SaveState( p );
3 e8 E( f( \9 ?; J' h        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
/ \- |( l3 \3 N' ^
# c; h& h0 \# F$ X  J/ z7 S3 W        // VRC6" Z5 K5 g/ z; E
        if( exsound_select & 0x01 ) {& k) U- b4 x; o& j& {& |
                vrc6.SaveState( p );2 v& b4 b. e" X3 D8 x* Q+ d6 [
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
- z0 @6 ~$ Z7 \$ B        }
( Q) D  B8 l$ n4 d( o        // VRC7 (not support)- X, y$ e. q  @8 y7 v0 V
        if( exsound_select & 0x02 ) {
0 [+ j# T0 l9 F; V                vrc7.SaveState( p );
8 D" d. I- C+ ?* u6 c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ Y! U# D  K! C
        }/ u! f, U$ C9 U2 k4 W( i  p
        // FDS  W+ U- M9 ^9 d- p# R+ V
        if( exsound_select & 0x04 ) {1 _8 ]1 b" m6 }
                fds.SaveState( p );
; L% k9 O, s" N9 S/ H0 \3 v" {3 N                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ I5 x9 Z* S* F6 V! a
        }
0 v2 p3 G: L5 X- M+ u+ z  h: a- i        // MMC5
$ e9 J0 j1 c1 [        if( exsound_select & 0x08 ) {
- v+ {3 O& ^; m/ z1 L3 X                mmc5.SaveState( p );
1 P( W5 i5 ~, F  r' ]9 Y                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- \7 O- N* N! m        }
1 r1 B. v: b" E' E3 x8 `& r        // N106
7 q8 d7 H: t( `5 q) Z3 X        if( exsound_select & 0x10 ) {( J2 o! A, `) b& K7 D* z
                n106.SaveState( p );
6 t# k5 c) u( p" y" k                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding4 V) g0 p9 n4 z7 E# ], z
        }
2 O" A' R0 }  ^  v) k        // FME7
  C; N" t4 P" j) [5 T8 R        if( exsound_select & 0x20 ) {* @! L9 k7 f1 @: R/ C
                fme7.SaveState( p );" h( E9 P/ A; r: \" T
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding9 e5 U! g5 B1 w
        }9 N% E7 j) W5 r0 Z2 t5 ^2 A) |6 c
* E' V, @( C5 i+ u& B( B
#ifdef        _DEBUG
) x! z6 F  o( S0 X" t: NDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
$ y; s5 n. X# x( @6 D. b#endif
" w; L/ H6 k2 m: n3 f2 }+ s}
9 J+ `8 y, @2 s8 c1 p3 j
8 l+ P' g/ s4 f( l+ wvoid        APU::LoadState( LPBYTE p )5 Q; k$ r9 j, s+ a0 r: Y# ^
{
* \2 U, [) z( t. j) v7 x0 k6 k+ a        // 帪娫幉傪摨婜偝偣傞堊偵徚偡- c8 t; m  [/ p) `
        QueueClear();
' \# E) k: U4 s( z: X. e8 G
" u. I4 T9 [9 s% j$ @2 z# P        internal.LoadState( p );
2 e: u" X8 P' l        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' H4 @8 ?& U% V5 M
6 \* C( p$ K: r+ S  b0 P# Y        // VRC6
8 `$ t7 p( c9 S0 I2 ~        if( exsound_select & 0x01 ) {5 Y# N0 @/ o$ i* g3 e% d
                vrc6.LoadState( p );+ S2 g# ^; R$ c1 m6 o
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ i$ j, B( k; r6 W
        }. C) x- `4 ?# _- a
        // VRC7 (not support). c; O* s; D5 B" D( k8 d$ f
        if( exsound_select & 0x02 ) {, Y7 B4 x; R! x* f; i2 ]9 M2 \
                vrc7.LoadState( p );
+ [+ Z, }9 H3 A; H8 c0 d                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
) N$ D1 o( ^+ B' ?        }. X( v  X+ ]1 j' C; ]: P6 J: }
        // FDS: o' L# z& Z" I4 k4 }6 ?
        if( exsound_select & 0x04 ) {' e, Z5 J) y, J' ?$ L
                fds.LoadState( p );9 G* H% q. [, r1 k7 h, F) P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding. J2 Q+ Z3 }* ^0 C
        }( K3 K* U, r. l2 N% _
        // MMC5
; i. H" C# d+ e! o0 e4 `! [        if( exsound_select & 0x08 ) {1 i9 a( Z: l# W" L+ i2 z
                mmc5.LoadState( p );  l  B% P5 X/ _9 t* u0 U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding3 D' L& J$ h! U' {+ e
        }& N, b% f$ h9 I* l# }, q) i
        // N106
* M) M! Q2 w  Y6 Y# D) a: A        if( exsound_select & 0x10 ) {9 F. Z4 x0 L' H3 J+ j; a/ g0 d" @
                n106.LoadState( p );: Y; u$ S8 k: ]. U/ [8 D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding! R+ f' c. Z! Z" S, k  R0 O
        }
8 D- g+ ^  \* I        // FME75 P( G3 v' _3 b# A( C
        if( exsound_select & 0x20 ) {' G8 ?, Z5 \( }8 _
                fme7.LoadState( p );
# N% D5 `! R6 n% k& S                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding$ |  v5 B$ y' \1 p/ v
        }
* x2 Y1 T* j  K3 h) y  y3 V0 Z}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + y  G: q7 }- q
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
) `5 T' ~" `" [2 k感激不尽~~
4 v: C* \0 U: Y8 |( C: b& {! [
恩 我對模擬器不是很有研究,
$ e* X3 p: W& X5 t2 ^" Z1 J雖然要了解源碼內容,可能不是很困難,& z3 P7 C( f( M$ d) L
不過還是要花時間,個人目前蠻忙碌的。
9 w$ m  l9 V# R( @, }
; h: E% @5 r/ ?" F3 e& R  M: l# e% y7 @給你一個朋友的MSN,你可以跟他討論看看,, k# \& \7 i* i& A# Z
他本身是程式設計師,也對FC模擬器很有興趣。  j* O( d' o9 j3 ]$ Q7 O9 M( D. Y
% P: P1 b  t) n3 e) |; [" I
MSN我就PM到你的信箱了。
1 m' m$ x+ [+ T# {7 ]. Q) i1 _  i2 f/ k$ D. X8 l0 _, A5 K
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
9 ?& P+ E$ `$ C$ v* a1 \) m1 L! _呵…… 谢过团长大人~~
" D5 \' R+ W( m) V5 @& L4 ^

: ?4 X, ^" J0 P) A; a+ X; ~哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 / M& K3 x$ h1 x
团长的朋友都是神,那团长就是神的boss。

2 x8 E6 h( _( i& j2 g8 y  u- O* U哈 不敢當,我只是個平凡人,
+ M+ s9 \- T  ?$ y要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 _- M8 u' T0 o' L6 B/ _ZYH
; A# Q1 G9 Z- }- s7 EQQ:414734306  l% d' d: T. x2 E3 [2 K
Mail:zyh-01@126.com
, V3 v/ `( r/ j5 r9 ~) Y% O5 C) P* _3 h8 }+ G- W  d$ g
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
1 j. U3 S. d4 v1 w再次对团长大人和悠悠哥的无私帮助表示感谢~~
+ d: s3 y0 p( c# }
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-17 07:21 , Processed in 1.082031 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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