EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 W2 u8 p$ |9 M" X# i' s楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! i& @) n0 i' [0 T2 T这里有相应的模拟器源码,就当送给大侠了~~
# }- K# U4 U, c2 `4 b- chttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
7 Z: M7 K0 |9 T% d7 z. P. }能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
3 w2 Z4 J8 U& k' @楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~  {6 m- z0 z( {
这里有相应的模拟器源码,就当送给大侠 ...

- `" Y% b% t4 f9 Y+ Z聲音部分(Audoi Process Unit = APU):
0 i0 u1 |/ S; H3 h( l8 r0 v.\NES\APU.cpp
5 A" Z) u2 n6 F$ p3 Y' u.\NES\APU.h
7 ?/ O" r* O* I& V2 ?; F% U# r7 F) [8 ~+ D! l% L! W6 F/ T

0 w6 E, e3 X/ F9 N- ^( T% B, O影像處理部份(Picture Processing Unit = PPU):0 P9 o+ r; r8 t: Z# Q9 a& V6 U+ G
.\NES\PPU.cpp
% O4 G1 o9 M% K$ j0 C& k.\NES\PPU.h
; V1 {: ~8 Y8 K# T, H/ v, ?- j  S% Z5 d- ]2 ~
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
1 p  t; K9 d9 l& @- q(由于很多专用术语和算法机理都不明白,所以看不大懂……)6 v- Q2 M2 E9 I, |# N- I1 N
//////////////////////////////////////////////////////////////////////////: q  r" b/ N) G% h9 ^8 T5 b& a
//                                                                      //
9 X% K. F: }9 G( W4 R//      NES APU core                                                    //
( H7 M6 f' W* G/ d) ~//                                                           Norix      //
: c$ ]- |+ y; k% j5 u5 g2 k//                                               written     2002/06/27 //
8 r6 i% P7 U4 _( }3 Y' e//                                               last modify ----/--/-- //+ z  X1 L2 l2 a2 X: Q
//////////////////////////////////////////////////////////////////////////
8 M8 R0 K5 l9 r' y+ `$ c( q, z; w& d#include "DebugOut.h", L; }  w1 @! o8 o
#include "App.h". i: V9 B4 {+ {* _, f. B
#include "Config.h"" p6 Z5 p! e, z  Z5 `! |, D7 Q
2 r/ c& j- K$ b8 I
#include "nes.h". q* s; N) |& B/ x' n$ b
#include "mmu.h"# v; {$ J7 V: Z* C+ L' h& R
#include "cpu.h"
3 d6 Y! v5 I9 |' O: W& n) i#include "ppu.h"
5 r( F; E; h4 `9 _3 _- F#include "rom.h") ]! k" t9 s+ a# f5 w" h/ ^. D" I9 P! K
#include "apu.h"
8 i* y' c2 p* u4 f1 ?* O# n$ P+ N6 @( E
// Volume adjust0 K! M" c0 F$ h1 B& c+ q$ U- `
// Internal sounds( ]2 V- P4 {, r6 ^" ]& F5 x
#define        RECTANGLE_VOL        (0x0F0)9 d# x+ C9 X/ h/ i
#define        TRIANGLE_VOL        (0x130)8 h& T# h( S/ M
#define        NOISE_VOL        (0x0C0)
) G2 m# [5 ^8 `, |  w  ^#define        DPCM_VOL        (0x0F0)
9 s* d3 @- k+ y+ ^// Extra sounds
- Y! J7 t) Y/ j& E3 P#define        VRC6_VOL        (0x0F0)) Y4 |8 v! C6 o! @9 j/ H7 h
#define        VRC7_VOL        (0x130)
4 H9 ~3 ]  ?& p8 ]7 Q#define        FDS_VOL                (0x0F0)
. v2 `3 i8 M3 L* p; b$ a$ |- k#define        MMC5_VOL        (0x0F0)* Z9 c" n) S, B# e  @
#define        N106_VOL        (0x088)
: |9 ~  m& @- v% G/ V6 T#define        FME7_VOL        (0x130)
3 z$ R7 g; C3 ^# h3 i( \
' p: f( u+ F8 R  S' u& _8 GAPU::APU( NES* parent )4 g/ v: w, o+ `8 b
{
! j  l# d+ Q5 Y! h9 _' ?+ Z' f1 T/ E        exsound_select = 0;
# q" Z. d/ O5 `3 [" g  ~2 l
  I  j; E6 Z0 v7 C6 n$ C3 U        nes = parent;
; z  [5 J5 A) v/ L% I5 i/ T        internal.SetParent( parent );* e1 S) i" ?& Q$ u# g; L

% t7 O9 R! L1 Q) Y2 g# p: ?        last_data = last_diff = 0;, S/ q7 ^7 _# r

7 ~9 m. H- S4 G/ U$ }        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 S: |$ h; T! Q7 X: p: d
$ I; @) R# ~8 f- N, m
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );7 y# p( \6 l- l  Z; D7 G, @' X
        ZEROMEMORY( &queue, sizeof(queue) );; W  E; w) y- U
        ZEROMEMORY( &exqueue, sizeof(exqueue) );$ f6 q+ `8 k" M$ a2 f
" X4 C0 ^& n2 W2 U( I
        for( INT i = 0; i < 16; i++ ) {  k2 S1 v5 y4 p6 {7 H5 {
                m_bMute = TRUE;
4 U( `4 Q! f* T0 i, ~3 c4 x2 y& @8 r        }, A  h, y- f& j
}5 O' @" m& W8 h  B
, w9 [( A5 N6 y! A9 w2 ]& l9 D9 g( L
APU::~APU()( x) ~; Q/ E3 [/ w/ d5 z" u9 @
{
' J3 u( E0 C( v/ Q. P}& \+ Z: H5 X  G' A
5 u4 [' T$ k& m& _4 G# y0 e& z
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
' b. g6 v4 w& a7 r1 e2 Z{
: w4 w( @. {, L1 R        queue.data[queue.wrptr].time = writetime;% p7 `3 ^; m( A; }* q
        queue.data[queue.wrptr].addr = addr;
! L0 ^: V  X7 Z! h        queue.data[queue.wrptr].data = data;+ N) f2 H* G* N) N
        queue.wrptr++;, w9 }* {1 u- d
        queue.wrptr&=QUEUE_LENGTH-1;8 I6 }9 Y, l9 Y0 c
        if( queue.wrptr == queue.rdptr ) {
3 ~" i% ]2 Q' u6 s# M                DEBUGOUT( "queue overflow.\n" );6 t, ?* N6 Q& Y# _- `( @
        }
7 f) d) W) r5 O# a9 `}  h0 [: t5 z3 K% r! A  ^
6 n, G0 a9 T/ f2 v: M3 H
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )2 o% p) Q$ O7 z- C9 z
{
' H: h9 o. B# e9 s# |        if( queue.wrptr == queue.rdptr ) {
8 Y1 \$ v& i+ n" W# g0 ]9 j                return        FALSE;
. L/ J8 ^+ F4 n: M2 L        }
1 w: p+ N  ^: N; }2 T& r# W        if( queue.data[queue.rdptr].time <= writetime ) {
8 j, `6 ]8 Z/ b# i/ j4 ~8 n                ret = queue.data[queue.rdptr];
  u( m6 M' p3 t                queue.rdptr++;
. Q* R, Y3 b; u$ R1 l                queue.rdptr&=QUEUE_LENGTH-1;/ E) ]5 ?1 D4 f
                return        TRUE;9 ^$ T, H' _$ @4 S% t* }
        }
- Q  s- G" X) [" |        return        FALSE;
; A: L* J3 P* k8 u% C2 V}
- a6 \" h9 M9 w5 |) e$ t- r: U5 k2 c# o& I" f' S- z" ~) G9 z# h
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )+ b. h3 b, i1 [
{( }5 W# k$ y2 L$ `4 R2 u* i
        exqueue.data[exqueue.wrptr].time = writetime;
: }; [9 L7 i/ a! ^1 u6 i. {* x! l        exqueue.data[exqueue.wrptr].addr = addr;; z- Z, k. w* h! Y: N; u
        exqueue.data[exqueue.wrptr].data = data;
0 G4 V3 b) T4 J# p        exqueue.wrptr++;
" R' c+ v5 U% b9 |6 n3 w/ k, O        exqueue.wrptr&=QUEUE_LENGTH-1;, t" u1 q+ Y; |3 j% g4 ^" F% C6 O
        if( exqueue.wrptr == exqueue.rdptr ) {
5 x: K# V: v) j/ |$ f5 l1 e                DEBUGOUT( "exqueue overflow.\n" );4 g. u4 E7 _. d5 m4 b8 G! U
        }
1 Q" ]* ^6 P! n8 B9 S}
. J' J/ T4 O) o2 F! k. q# s( ^8 O  G6 {3 j
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
. F7 L% F+ [7 g0 _{8 ]3 R8 J6 q$ `5 ^
        if( exqueue.wrptr == exqueue.rdptr ) {
3 G" T- O% G# r- K                return        FALSE;: F2 F2 f4 V- N
        }
1 B- x1 R1 [, C! F        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
" B* X0 m# m! q+ N                ret = exqueue.data[exqueue.rdptr];
' j3 j. X2 \0 I# J0 i                exqueue.rdptr++;7 @9 a1 a- z1 w  S
                exqueue.rdptr&=QUEUE_LENGTH-1;
) f1 X+ E# q" _$ U% |                return        TRUE;
7 ^9 T' O/ G& k        }
# M9 `; D2 C. H        return        FALSE;7 m# F" B( o3 x3 L  m) c( `
}4 j) y7 L, p$ w
0 I$ [+ j$ u. v" w3 k& i0 r
void        APU::QueueClear()% Y* x9 k3 Q5 ]8 G. s2 x2 m
{
& X4 l8 h# L; v7 M0 Z5 Z        ZEROMEMORY( &queue, sizeof(queue) );: x, {+ ~* R$ ]& E9 O9 F
        ZEROMEMORY( &exqueue, sizeof(exqueue) );& @" F2 a/ ?2 I! N) \
}' U2 T5 d" }' R: e, p$ k! O' [
# k! u" v8 m' B' s7 m' M
void        APU::QueueFlush()- @( b% w4 u7 C/ @" q! M, M! I
{
; q3 K' I$ e5 U. J3 L: a        while( queue.wrptr != queue.rdptr ) {7 ?6 }3 U2 M- h1 U: h
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ g$ u8 d4 a8 K% W6 g                queue.rdptr++;
" J# p. R! v7 B9 E. h. T6 y                queue.rdptr&=QUEUE_LENGTH-1;6 {, k1 C: J% }4 s1 L( v
        }- {$ ?8 w5 W: J; `3 _. |* w) |

2 W7 Y9 ^# E# H5 E2 q( N        while( exqueue.wrptr != exqueue.rdptr ) {( Q: `0 G3 [- Q9 X) L! E
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );3 C! @, {1 R) d. {
                exqueue.rdptr++;( W7 D# c) x% y$ h
                exqueue.rdptr&=QUEUE_LENGTH-1;' ^# r' w' n$ ^9 H& ?/ t1 H
        }9 Q4 E8 y! d1 {' K
}
( Q5 W( g- Q- i4 ^
  @: {" a4 K. X0 Q" L9 yvoid        APU::SoundSetup()
5 {8 G& F3 z& e: u7 Q1 ^/ C, G{+ M- T- s4 K: D) u3 I, d+ f5 N6 ]
        FLOAT        fClock = nes->nescfg->CpuClock;# J. l4 I% s) R% r
        INT        nRate = (INT)Config.sound.nRate;
/ Q) {+ J9 T; H9 T        internal.Setup( fClock, nRate );3 c! @8 m! A; q3 y8 B$ K# u
        vrc6.Setup( fClock, nRate );. e( {4 `" J9 ^+ x
        vrc7.Setup( fClock, nRate );' O4 }6 i/ g+ I: `$ B
        mmc5.Setup( fClock, nRate );
( t/ g2 Z  ^  |' K        fds.Setup ( fClock, nRate );
4 _" E1 d0 |* Y& h% \  A        n106.Setup( fClock, nRate );
9 m& |; E. V/ N/ [  L        fme7.Setup( fClock, nRate );  D1 X1 i4 `6 @+ u/ @
}% j% J8 Z9 f2 p0 b4 U

+ S7 k: X! m) j$ Q) T% nvoid        APU::Reset()
* S4 F9 y* J! E; o{
; m/ D5 q- [5 {2 m        ZEROMEMORY( &queue, sizeof(queue) );
8 L7 p# Z# }" `0 o0 y' O* [" c        ZEROMEMORY( &exqueue, sizeof(exqueue) );' P7 N" M0 D  ^) D

& j1 [( i7 u( Q5 ]        elapsed_time = 0;0 V8 o/ U7 [& Q, f& k$ r
& D. x" ?' {- _& |, _
        FLOAT        fClock = nes->nescfg->CpuClock;' G0 M1 u, k, W' I4 i0 A, ~% Y
        INT        nRate = (INT)Config.sound.nRate;* j1 N& n4 D  J6 t
        internal.Reset( fClock, nRate );
2 P! V  `5 G! k0 `& \) T9 o        vrc6.Reset( fClock, nRate );0 Y* L" B. M) I
        vrc7.Reset( fClock, nRate );
. c, s" R: B+ U  F& s        mmc5.Reset( fClock, nRate );9 w. y  v& Q  Q  G/ X
        fds.Reset ( fClock, nRate );' R2 Y. K4 h# I' g
        n106.Reset( fClock, nRate );
' j( ^5 q0 m  P. m! h1 m        fme7.Reset( fClock, nRate );
& r5 E  ?9 f% B9 l8 s
8 I- C! [+ V, K6 h! U& L1 R        SoundSetup();
8 K3 N  z: R" y}
/ P" b; M: V' C7 _
) P1 A7 @% F5 Bvoid        APU::SelectExSound( BYTE data )
7 ?9 F* f4 q* R{
& d8 `0 Y7 a5 @1 Z7 Y* x+ _- l        exsound_select = data;
- J& W/ P# J$ b2 D  J}
9 ~+ y  f. _, }, b3 c
& I2 a( D  B6 o2 y! g2 l) @8 ^; lBYTE        APU::Read( WORD addr ). i/ s$ g, V" I& E
{
* Z0 N; Q) o8 x" y/ U        return        internal.SyncRead( addr );
7 Z) M% [% V4 m$ o* ]}
: K* X( o1 u5 B; P7 y( F' l( b9 n# W; I/ ~, {( B9 b
void        APU::Write( WORD addr, BYTE data ): E  Q. v: b" W& @6 b. Z
{7 _6 _( N& Q  Q& a
        // $4018偼VirtuaNES屌桳億乕僩4 s7 E$ r6 E4 A- V
        if( addr >= 0x4000 && addr <= 0x401F ) {
- J6 @: p1 i) p, z" f$ G0 j                internal.SyncWrite( addr, data );
& x% S2 `3 N  p. F$ `9 n                SetQueue( nes->cpu->GetTotalCycles(), addr, data );( W& v& |1 A) o: L) t( u
        }
! E. c5 [& a; i! R0 }& m  R}
. S) Q0 E8 j2 X9 @# b* ]9 t% P4 _: R3 P  W( J; g: ^' Q) ~, }' R) n: O
BYTE        APU::ExRead( WORD addr )
5 P5 A( C+ T+ M% a{2 L% ^  \- M. x( {& V
BYTE        data = 0;
1 b2 X. w5 H# c  A5 i& X( j! I2 g/ c: o
        if( exsound_select & 0x10 ) {
6 d8 c5 t) w, l4 J5 ^                if( addr == 0x4800 ) {
; L" q5 m+ ~+ `0 Z/ p) I& n                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
" q3 e6 O( M, I7 G) D6 v9 C                }- k' I, h7 f% Q0 Z4 F/ t" X  d
        }
; ~! e& y9 P- B) x) j/ y- p' H        if( exsound_select & 0x04 ) {
2 ~9 P; R0 C  o0 W. N1 |. X                if( addr >= 0x4040 && addr < 0x4100 ) {
: ^4 }# d* s( _  @! q6 A* V                        data = fds.SyncRead( addr );. u5 q, j' y6 l) o) Y; [
                }
+ E. Z4 F/ V& Z3 F( ?$ B        }$ S4 @4 f* f% [, o2 F
        if( exsound_select & 0x08 ) {3 f4 d3 x4 P! n$ V
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 R3 ~3 `5 ~0 K- _- Z
                        data = mmc5.SyncRead( addr );
2 I9 S+ d6 ]7 d  B0 [2 z                }( U% \) f$ `7 j, k( G% H  K
        }3 s- \' T8 m  |: Q. ?4 l

9 S% L6 ^5 l# e% |5 q        return        data;
5 {) t+ d* u  q4 M, G/ y}
" k# J( y! ?& K- h2 }+ X# Q2 V6 Z3 i7 g' |
void        APU::ExWrite( WORD addr, BYTE data )" M/ e! a+ e+ d0 `
{
  v& X/ M# x8 P" ^: f        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
5 ~3 Y) x& ^# D4 N0 \9 f5 b. c+ N2 F* A' ~3 O9 }2 Y+ w
        if( exsound_select & 0x04 ) {
& j! E5 G% h4 I1 h" L- Z/ j6 e8 h                if( addr >= 0x4040 && addr < 0x4100 ) {
: v+ ]# z  h0 i1 E8 |  Q                        fds.SyncWrite( addr, data );! T5 z7 R0 |) g' J" H6 J$ T9 S( ?
                }
/ Q, P, a5 ^. d2 P        }. \0 y  g, u& S& R' n8 k$ {

/ Q0 O$ o3 P0 T+ d9 q3 u        if( exsound_select & 0x08 ) {( K1 y6 u" E8 H) h+ n: {4 ?8 K/ o
                if( addr >= 0x5000 && addr <= 0x5015 ) {% _4 g. d2 e0 F
                        mmc5.SyncWrite( addr, data );, E# @9 c3 l6 g9 w% u% P$ z
                }
/ B2 }) F) ~( J  F        }3 D- w" M% K& F( l1 E5 F3 O2 I
}/ o: v* J/ H2 @
9 ?% G" x! m/ I) W
void        APU::Sync()6 x/ s1 O3 ?) H, S. P4 v
{
) l3 Y3 v4 a4 E}
6 g5 D3 C+ [! F9 `! B( s0 t( t2 E7 o; o# m  N
void        APU::SyncDPCM( INT cycles )- a: b) A- x5 b" w9 [% y
{
  t0 V/ O0 B9 N! V        internal.Sync( cycles );8 {; m8 i% J& m

, G. i' m2 f5 ^        if( exsound_select & 0x04 ) {
  ]) Q3 v3 j. G( G! p2 p                fds.Sync( cycles );1 d$ V. ^9 r  m# O5 t: u
        }
3 v1 [, k8 ]  Y6 F        if( exsound_select & 0x08 ) {2 [. d- q3 N( R9 r9 H) ~
                mmc5.Sync( cycles );
4 f) E! R% Y$ G& \+ L% c        }
. c2 G: U9 j9 |2 }2 r}
5 ^% k& G2 ~% m* h7 M
6 J5 F2 Z# U" u9 b* \2 Pvoid        APU::WriteProcess( WORD addr, BYTE data )( D* {4 x) M$ E% p" A4 F
{& E2 q" M9 I) \( C* p+ M: D' D
        // $4018偼VirtuaNES屌桳億乕僩2 `2 g$ w  R. D& J; ?6 J
        if( addr >= 0x4000 && addr <= 0x401F ) {, A5 V2 t! I$ X, p, W% z
                internal.Write( addr, data );
. K' s& C5 c$ e, }6 B        }9 ?  P7 Q- W. _9 ?' n/ X2 u; B
}9 p4 H/ O% I/ s) c1 T+ T0 [- T
3 d* d2 V0 X6 s: X! {
void        APU::WriteExProcess( WORD addr, BYTE data ), H/ H) t& @4 }% c1 n9 X
{
5 k+ }- ]4 E* `        if( exsound_select & 0x01 ) {/ x2 B" [6 {3 Z9 b7 X
                vrc6.Write( addr, data );* J6 r1 m* p/ h1 K. ?7 D) C  B6 m5 I
        }
  V) s, T7 V! e8 r5 E        if( exsound_select & 0x02 ) {. ^  k6 b; q  R- v# Z
                vrc7.Write( addr, data );4 \6 [: r* ^2 c
        }
' U* I2 u( o& v) F1 |; k        if( exsound_select & 0x04 ) {
  b* m7 t; ]4 C                fds.Write( addr, data );
) M( f4 I: [4 r- I* D) B9 ^. F        }: r% o9 c2 ]# q0 y6 J
        if( exsound_select & 0x08 ) {4 V& j. ^2 W& ^+ q2 O
                mmc5.Write( addr, data );" t4 u# o: {) D3 N5 S  [' ~" V& Q
        }
( G" q9 Z! }1 `* v- L. Q        if( exsound_select & 0x10 ) {+ u6 R4 |* l) Z" L2 Q1 P* ?
                if( addr == 0x0000 ) {
" I0 A8 s( D# S- e% K8 C                        BYTE        dummy = n106.Read( addr );
& L. b5 x& C: e  B. g( k                } else {
" h7 I8 U$ x. F; _4 Z; {4 K                        n106.Write( addr, data );$ Z) i5 P5 n) w& S) Z7 v. r
                }
6 I3 [( H  U: [' Z# y        }
0 U9 N$ J4 `  P/ @        if( exsound_select & 0x20 ) {0 ^% P9 q) Y3 I4 A
                fme7.Write( addr, data );
! v, i5 \: Y1 `% M9 G        }9 y" W/ j  p  Q6 @: l
}1 D- ^( w2 M' ]5 ^

$ Y# _' l' b% y, _4 p( ~. T: rvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 ^/ l3 U, M( `
{
, ?: U5 P% {0 V" qINT        nBits = Config.sound.nBits;3 f( q6 t' Z) n, Y
DWORD        dwLength = dwSize / (nBits/8);
; b; p4 f. U- i0 K9 Y4 m7 X% }INT        output;% \4 L& y: W) Y
QUEUEDATA q;
5 W; }8 l/ W) ]% F- wDWORD        writetime;
  U9 P% O& q* K: G8 c  M6 l6 {0 k
7 ?2 w2 I) V1 t* }/ LLPSHORT        pSoundBuf = m_SoundBuffer;
9 t3 P; N0 q$ w) q  F9 bINT        nCcount = 0;3 S! u! {1 E5 C* m6 ?

) J  q7 ^% r6 t3 o& J9 IINT        nFilterType = Config.sound.nFilterType;
1 t7 {+ E6 _4 \2 f- n2 @
8 T4 E( K2 S$ _# D        if( !Config.sound.bEnable ) {
( Q5 j5 Q; J. `1 L, p0 L                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
$ A* A+ P4 M& H4 h                return;( @7 d. o/ Q9 D: @7 y: L! Q
        }6 t0 |0 ?( f& c$ j6 V! e' p3 P

" Z( a- b) c7 X* d        // Volume setup. H9 y0 o3 m0 ]2 ~. e3 L0 h
        //  0:Master8 C& L  O$ h; H7 U! T/ ~
        //  1:Rectangle 1& G& h& V) d0 [
        //  2:Rectangle 2
" D7 R+ W  t6 I; ^# R( e- z, P- L        //  3:Triangle
$ E" ^  I' Y/ {: g- \        //  4:Noise# m3 K+ h7 o9 H, ]* e$ b
        //  5:DPCM
$ I9 j$ D6 j/ ^: }        //  6:VRC6$ b2 j& b, \8 D! _$ v0 H! n; ?
        //  7:VRC7: t2 K4 ?8 h$ _+ j3 a+ ]
        //  8:FDS
6 x( @% R$ _3 F2 ]4 z+ ]% d        //  9:MMC5( n) o5 `/ u9 B0 d8 y& ?% T8 u8 J
        // 10:N106& E# |- M& }, N5 Y. v. @
        // 11:FME7
: G# a% Z, f' L0 A6 }$ d        INT        vol[24];
, ]" y! c3 l3 y% U; b: m! c$ i6 c        BOOL*        bMute = m_bMute;  `/ c1 B9 y6 V. B7 E# u) m
        SHORT*        nVolume = Config.sound.nVolume;
- a2 ?- O' Z( y6 Q7 n% I- x% Z6 m3 D- S" {2 w8 b+ @
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
: v+ P" \5 A4 }: y
* }0 W6 D3 T; V; K5 ?! `+ l        // Internal
: m' t/ W% ~7 J% _7 w6 ?        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 H4 u- G; `9 N. E5 U
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;9 U4 ]# I- y" H7 `: a3 Z
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
! X& e, l3 w6 y        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
0 p7 Q: n' M$ @7 \6 O! |% p        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
' X$ u: `0 ~5 r: U$ d  \4 V( I
: L  w7 ], O3 s7 H- a        // VRC6
& ?% g2 h" h/ B9 \: r% O% u        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 X) J7 A4 c- P1 j6 k
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;: k; z/ k+ F9 @; r% M8 T, V, r" D
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 u# G$ [( Q+ R2 j( x7 c0 H
2 U1 t1 p0 o( f& p' M8 n5 v        // VRC79 @7 f. H* _2 w: B: J
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
5 _2 W' G6 ]% w) n
* @4 U# U0 \/ [: W# @, d% p. c) G        // FDS
/ c, y9 I, ]1 _        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;" a* k2 K' I8 P6 m: J1 M  m# }
) u0 U. R- F% j! j/ Y5 Z
        // MMC5! R+ j" b! P# s+ K) R
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 G! d6 V8 W, A$ l) M
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" Y1 t% p: N: z( q  g        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
" f* O7 ]4 L+ ]7 u
- h7 m  L$ b' M        // N1068 l2 [+ c+ t' D' V2 H% E' q7 w
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% _; h5 t( q- Q8 n  \        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# G9 \0 |3 s/ V6 N" }: r
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( H7 |/ w! a4 T/ h) E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  J3 y" X5 K* {# Y  D/ v
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" z5 a5 a7 G) `* q8 }9 Y, [        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: D( @+ |/ f" `4 v8 A3 S$ h: Z
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 D# e6 ^3 y& N/ L1 T
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! L/ t6 \6 u2 P( h
# f! B; p7 `) U, v  Z. \4 D; M        // FME76 R0 E3 o  A, E, e# n3 R4 a
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 y3 n; e; x0 k% y: i; @        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 j8 [; N3 g. ]
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 U4 _- \: b: x, |# P& S, Y
- P  [! u0 J( J- J& t# b/ W//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
& ^8 X7 D! f# d% g* X% h        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;2 w# {+ ]9 |' O4 J9 P

- i) {  x! I+ S: o$ Q1 D+ f        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
: |3 A* N" j) m& n1 Q" d        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
' J7 k) f" R: g  |* q3 e- N                QueueFlush();  `, ]) M& ~% y) @7 o& G
        }  _7 S9 a6 c+ o+ g+ S- L0 [6 r

' r' O7 B8 D7 t% w9 A2 F        while( dwLength-- ) {1 Z0 A$ \8 w" c: t  \( @% S
                writetime = (DWORD)elapsed_time;
0 r5 Y  E% N6 r9 V
8 @; i+ b9 @4 L/ Q                while( GetQueue( writetime, q ) ) {
% ]6 D0 V0 ~% h9 j, I                        WriteProcess( q.addr, q.data );9 a) M, x9 k; \$ b8 ]5 b6 l
                }7 h3 n0 Z$ r# n/ u$ e  @

: J/ a9 A- s6 o5 _+ F: \7 G                while( GetExQueue( writetime, q ) ) {
- A* A) ]! h( x" A' J                        WriteExProcess( q.addr, q.data );( l( z6 F; B* r0 [2 H
                }
/ E9 ]" O3 Z0 l% ^" f( B. U8 q, l0 O5 p" e- m9 i7 N3 m
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
( w8 T5 M% x% |$ b( _( z. ]* Y                output = 0;
! ~0 S+ s* G4 ^- a, \0 d* D                output += internal.Process( 0 )*vol[0];& x1 z2 T. X6 V- a+ w( }
                output += internal.Process( 1 )*vol[1];1 \* G4 |% i2 l0 J; @" K
                output += internal.Process( 2 )*vol[2];- W% C! q1 |% w, w4 k
                output += internal.Process( 3 )*vol[3];; r2 T+ L8 ]' V! o) ]
                output += internal.Process( 4 )*vol[4];
: C# o: x3 K; Z7 Y
4 N  v  W  x; |6 q                if( exsound_select & 0x01 ) {
9 g0 o/ H, p1 |3 h/ l$ b4 q                        output += vrc6.Process( 0 )*vol[5];) m1 I, v1 |" R; C( R6 e
                        output += vrc6.Process( 1 )*vol[6];+ W" K0 ~0 D0 O( \
                        output += vrc6.Process( 2 )*vol[7];( c# A7 O( @5 @* D
                }2 p. g3 e; l- I- @+ D2 e
                if( exsound_select & 0x02 ) {+ o0 v9 ^* t, u. F5 G
                        output += vrc7.Process( 0 )*vol[8];
9 @8 f2 O& [6 ]2 j                }
% }6 B: l* F% E4 [! ?- v                if( exsound_select & 0x04 ) {
' k) c4 g! V6 \7 d9 ~) ]4 M" J                        output += fds.Process( 0 )*vol[9];1 `4 {+ N: w/ |' c; @
                }
5 G2 e' o1 s. e6 X                if( exsound_select & 0x08 ) {( V( p  S& ^& S8 M
                        output += mmc5.Process( 0 )*vol[10];
, D+ [. p  u6 x; J+ k$ x0 ?  o                        output += mmc5.Process( 1 )*vol[11];- b+ U/ t  Q  g: `4 g$ }/ X
                        output += mmc5.Process( 2 )*vol[12];+ }+ |. u( @  k
                }
7 {* L1 U5 H, T& X8 P9 x: `# B                if( exsound_select & 0x10 ) {
  h  N0 `* G2 b: U, `- j                        output += n106.Process( 0 )*vol[13];0 R) b9 a9 m$ @. b
                        output += n106.Process( 1 )*vol[14];# r" i) x  r" A" J& h; W
                        output += n106.Process( 2 )*vol[15];7 ^; c$ @5 V$ ~
                        output += n106.Process( 3 )*vol[16];
$ w. N1 D. x+ r                        output += n106.Process( 4 )*vol[17];
; ]. Y7 o) ?% X+ s3 f$ p0 R                        output += n106.Process( 5 )*vol[18];
* H& m% `' p+ i' {, y" Z1 V                        output += n106.Process( 6 )*vol[19];9 \5 o' M/ a5 O% [9 ~
                        output += n106.Process( 7 )*vol[20];' M0 C7 O/ G$ J0 N$ Z
                }
' c  B( Y0 v1 X* a3 \# u                if( exsound_select & 0x20 ) {& N& B$ N; N# `1 a3 t- d  h& _
                        fme7.Process( 3 );        // Envelope & Noise; J0 s2 a% Z# a1 B7 `/ Z& u
                        output += fme7.Process( 0 )*vol[21];
6 r$ k" q2 X4 U( D6 N2 k                        output += fme7.Process( 1 )*vol[22];
/ @. t* N/ \8 S9 q2 g                        output += fme7.Process( 2 )*vol[23];% [- x/ T; P  q
                }
" p# f) e# q. ~* q9 H) v
) x7 {) q/ Y+ W. m$ u. D+ }                output >>= 8;
1 R7 v4 `4 Q# C  i  W/ u4 T2 b6 {  x& ]' f
                if( nFilterType == 1 ) {
# t0 T3 s; `7 a0 i3 l1 M                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)6 l2 d$ R( M$ K- X0 o
                        output = (lowpass_filter[0]+output)/2;$ ^9 }) g6 y, w4 b5 ^, \; z: ^
                        lowpass_filter[0] = output;2 ^* o, j& X/ l/ s! j+ T3 r
                } else if( nFilterType == 2 ) {
" C3 J5 i7 J0 z. u; Y                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
) c, }% A% A) Q" F; \) ^& ~                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
9 y; _. E) [7 N; r( @( K/ p. E5 \) G                        lowpass_filter[1] = lowpass_filter[0];
2 F. q, h8 m( G3 w                        lowpass_filter[0] = output;, u6 J# p+ Z5 |# M$ l; C" L
                } else if( nFilterType == 3 ) {& F* H7 ]) G1 A, ^' h$ ^8 N
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)) e' ]. x3 @+ Z5 L
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" m6 \6 i, p/ ?& N. f2 L
                        lowpass_filter[2] = lowpass_filter[1];1 e6 E* I) l8 y, g* Z3 Y
                        lowpass_filter[1] = lowpass_filter[0];8 |& S! @: U/ p1 o  V5 N
                        lowpass_filter[0] = output;
/ O* J+ }& G$ i6 A0 n& S                } else if( nFilterType == 4 ) {4 {/ S( \' U, B
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
+ N+ i# z7 q1 M; b                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 V# B* _" F! e+ u: l
                        lowpass_filter[1] = lowpass_filter[0];- `. q. \$ F$ N: g, V* ]
                        lowpass_filter[0] = output;
) M' H% a$ p# N6 M                }2 z/ i8 [9 ]" A# v  N+ I

6 X  @+ j1 z- }$ s$ v#if        04 s2 T& I& E+ D+ r, u
                // DC惉暘偺僇僢僩
$ C- Y4 N8 d8 W) B                {( c( y8 R# z4 K+ A# x0 O# b. L
                static double ave = 0.0, max=0.0, min=0.0;
' S; h3 Y) c2 `/ M; v                double delta;( d7 [+ N  z1 G. o. ?
                delta = (max-min)/32768.0;0 i& I0 s9 R6 Z7 m. k
                max -= delta;
* {( q- }; U( R) D5 G                min += delta;
2 `6 T) Q! W7 o                if( output > max ) max = output;7 p0 ]2 t9 m1 S6 u2 t' f1 A" U
                if( output < min ) min = output;
4 }; Z/ w4 }! F# _                ave -= ave/1024.0;
7 [9 J$ n* k  D                ave += (max+min)/2048.0;, W& O+ W% o2 e# |4 _; P( k- p4 t5 T
                output -= (INT)ave;
4 e# e$ @" _8 N1 U7 ^, T                }1 v7 [) w: T) ^- T
#endif2 @8 Y$ ^( E7 ^* P3 r2 ?! s4 K8 Q% p
#if        1
0 `+ f- f7 t, y2 P5 C) {8 i5 }( q                // DC惉暘偺僇僢僩(HPF TEST)
+ G) j# C6 g1 M) z8 i                {, E9 ^/ |+ i3 U, z0 z# H; M
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
& J- X% q" @+ R- s! O  {9 v                static        double        cutofftemp = (2.0*3.141592653579*40.0);
0 u( i8 d5 o# R. u% }                double        cutoff = cutofftemp/(double)Config.sound.nRate;  k2 }/ I3 Y/ V3 h
                static        double        tmp = 0.0;2 F/ C2 I1 w9 Y
                double        in, out;
# `% \' d9 b1 A' g+ u+ ?( G4 m* `4 L8 g1 y+ @$ S% h8 R3 C
                in = (double)output;
6 d) w- S8 E7 c9 h                out = (in - tmp);
3 z2 s1 i1 H4 E& k                tmp = tmp + cutoff * out;
$ K0 j- r8 {7 ]8 f/ f
3 ^1 O. S: r8 D                output = (INT)out;
' |" W+ ?' m- E* P/ ]) w                }) Z  a6 H5 K/ h( N# S
#endif* x( J5 q6 F" ~$ D& b3 t
#if        0
# J2 S& m& k( A7 r3 N                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* x: }6 G. k) U! C% i# t4 |1 ?6 H) A6 i( u                {
( F/ u! y8 P1 T( T7 o( x                INT        diff = abs(output-last_data);
  G. B+ K$ p% [4 c0 h# c8 ]) D( V" S                if( diff > 0x4000 ) {
7 I% }0 k* Y9 [- j' c                        output /= 4;+ `, ]. h4 P- U
                } else
! f& N5 R9 G& Q$ |& g                if( diff > 0x3000 ) {
$ j: r4 c* R3 f0 ?' q& O. u                        output /= 3;; r1 K5 B$ V3 t: a0 O- a  K" c
                } else2 P1 N4 N2 }0 E# V; E
                if( diff > 0x2000 ) {, y8 e- G* B! m$ H# Q, f# X1 P
                        output /= 2;
# r5 P. t0 S7 N" o7 k% |! C* C                }# J5 }( `8 F/ {3 w5 s9 N
                last_data = output;
5 q  o4 Y: s% l3 O                }6 E4 E! P& b: ^- y
#endif
* W2 c! f, l; w                // Limit
) g- P' b1 Y" P3 X" w1 d, J1 ?) b                if( output > 0x7FFF ) {
/ m& y. Q6 Y3 J( I) _( x) d) E                        output = 0x7FFF;
. z' a/ J+ b& Y7 ^8 N5 t                } else if( output < -0x8000 ) {' |! ~1 S; V' M/ A4 \+ _
                        output = -0x8000;
0 K  F1 _, f/ K; |                }" B1 E7 O' L4 g3 l, X: U  @+ P4 E
6 A) b& g7 x: K% Q+ H5 T
                if( nBits != 8 ) {" z) q1 N  @6 @' `" w' W# n! q' V
                        *(SHORT*)lpBuffer = (SHORT)output;
* g% O4 i9 E/ ~; k$ T0 g$ i                        lpBuffer += sizeof(SHORT);
1 p6 ]; s! s4 J; \: j                } else {
! g$ h; a# C8 B* @$ a7 V                        *lpBuffer++ = (output>>8)^0x80;% _: ~; ]+ e# |6 d
                }
! I: b- J* |: ?& l5 [5 Q8 R* {
8 n6 f1 t5 i9 T1 p5 I3 L0 O5 k! \                if( nCcount < 0x0100 ); ?2 v6 y7 D3 \6 Q/ i
                        pSoundBuf[nCcount++] = (SHORT)output;
: O6 X0 X5 K( s8 i4 l0 L% D$ p' z; J1 Z" t9 e: |
//                elapsedtime += cycle_rate;
- c+ ]$ j7 `2 `  L. c                elapsed_time += cycle_rate;: u6 n/ \7 i- Y* y+ f1 z
        }0 V, [: f" ~; n) ^, }& B
+ v3 n" Z+ A5 L* V$ Z
#if        1) Z2 `- H8 H- N7 Q3 |7 v6 @8 D6 j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {* {2 J$ }; v5 t# ?
                elapsed_time = nes->cpu->GetTotalCycles();
( ~$ g6 |+ `) \2 r$ B        }- S% K/ ?/ o6 V( N
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {+ i6 f1 E6 R! w. c
                elapsed_time = nes->cpu->GetTotalCycles();
' W  O: F9 h* ^6 H        }
" W  V1 ?. A/ }: D#else9 E6 [+ |- ]/ L# c6 T$ B) [  v
        elapsed_time = nes->cpu->GetTotalCycles();5 X) Y7 }& ?) e, `
#endif
& W# a! s2 ~- t) q0 U}
1 U* k! s+ v( r) X' B9 H5 t1 c: l' r/ s
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
! d. t+ s* J0 ]0 F  u" vINT        APU::GetChannelFrequency( INT no ). V5 Z" ?$ J0 x
{
/ C+ C, g& t& u        if( !m_bMute[0] )8 Q: J" ~) S8 u3 H5 n2 N$ P" P
                return        0;% H9 E3 n" \/ j( h& V3 d( r2 B% S

1 j* L' D2 M4 H        // Internal
% m* W) O* W; c0 [0 K+ T5 A        if( no < 5 ) {
! _" I) C) ]" V6 g* x                return        m_bMute[no+1]?internal.GetFreq( no ):0;
# l5 P% o" j5 G7 X6 S) ^        }
& w) G. |6 z8 c% N# g! h1 t3 _  J        // VRC6
+ ^3 J3 S$ ~" m& W% v        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
& y4 n" F" f* L& z* l3 }                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;9 j* j  s. u8 x# K6 z
        }( _0 h* ^2 A+ C
        // FDS! F  Y, q6 v; L. p, s
        if( (exsound_select & 0x04) && no == 0x300 ) {' K' `7 X- l0 h" I' L
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
  R+ Z% Z' P% U4 Z' H        }" r0 R2 ~3 L+ Z  @8 S7 E: u
        // MMC56 N! f9 \3 A; W# Z4 j- w
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {  w( R) W1 K, R2 x" u
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;5 ^1 N) B" B( I8 o/ G1 o( t8 ?
        }
0 a8 d5 G  q: e* `: c, r# i        // N106
0 k' Z) H6 c2 {) h0 o& U        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {4 }1 i8 ]" S9 ?; [3 g$ t1 C- e
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
& c& N( b1 U* B: R# C* I& k        }8 [. \' `) J$ b' v2 R5 C" l  v
        // FME78 q5 s- j5 g- U! O/ U. n
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {4 h7 U' d5 i3 e: K/ o7 T1 a) D" i
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;" Q+ X9 ?5 @: {2 D  v  t+ U* s
        }+ e; C. G. f2 _9 X$ o3 h) O7 w- `
        // VRC76 ]6 A, ?1 H" J& y" k9 s/ M
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
# @: s6 T( u8 Y: r  R" @, G# s                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
- D9 z( W7 }4 ~- `        }
8 U# R" L# M# `7 o) r        return        0;: P) H6 D3 Q# z
}. Z+ ^5 `/ i) e# |( Y6 j. b
7 d; Z- ]: X; e5 \# b
// State Save/Load: n* g3 \: J4 C4 |! _+ F
void        APU::SaveState( LPBYTE p )
! H( y. ?+ g' ~: f5 c) v$ Y{4 O" O* K" |0 N6 A0 }5 C" R. @$ j
#ifdef        _DEBUG
3 \! m9 L: T/ N; M4 H  H$ ILPBYTE        pold = p;; M& w1 o) G9 H& `% k* D  U3 i* D1 ?
#endif
; S4 Y; b5 D4 G5 D  N2 K" ]1 Q; f5 a6 h
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
+ m% M% h3 n/ C7 N        QueueFlush();* i  \% N% P( c0 r

' V( \% g1 r9 Q* U        internal.SaveState( p );  j! M# z9 T( r
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
% J$ a/ \  l( Y
7 V! c% V) C  H' p% ~        // VRC6
, e; I1 p9 d1 Y$ d5 X1 d        if( exsound_select & 0x01 ) {' S5 q5 O: D# w  Y. T' ]8 u9 M
                vrc6.SaveState( p );0 h  g  |/ o& g
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 a0 ]; v  A8 e, a$ ]7 `1 O! `, I( B# q
        }1 s* x* T( c7 z5 P
        // VRC7 (not support)
. c% v& o" f) P2 J        if( exsound_select & 0x02 ) {
* s/ o& z" ^, v% I                vrc7.SaveState( p );
% b: H! h( J; `$ T. A                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding& r0 a3 {0 N% N$ f, _( I7 k
        }
8 g8 V$ \9 a# T" V        // FDS
; L3 d; C, B2 {$ I) B/ g        if( exsound_select & 0x04 ) {
7 s- c$ |9 c0 U                fds.SaveState( p );
. U+ L$ l2 I% Y4 z/ W- |                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
/ M6 f  r6 }/ i' C. V+ M4 O* p        }
- }4 H$ `; i2 U9 k8 ?        // MMC5
' z" Q9 ]1 _3 t) f        if( exsound_select & 0x08 ) {
) w+ T8 _0 a$ g7 v- G                mmc5.SaveState( p );
5 `% t, W) j6 j                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
5 V+ T+ T9 n; T; k% v        }5 s0 O, q4 W) |* ~) J
        // N106
0 Q. i/ Z8 T8 D        if( exsound_select & 0x10 ) {* Q! A. F$ Y$ N2 L$ w
                n106.SaveState( p );; a: u' P% V1 d5 p; M
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( f2 j4 X1 ]& I" e9 e* v' {8 w0 b        }' [9 f8 z  P" A' B; X
        // FME7
2 J7 l) [. ]# O+ o        if( exsound_select & 0x20 ) {
+ s8 B, W6 S  K) V" g                fme7.SaveState( p );2 w8 r8 X" m$ ]' b7 L! ~$ d& L% U
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
$ v1 S& l9 C- n1 y6 H2 c        }
3 z' a$ D+ }7 ~& N: t% n7 E
" d& R) [) b# W) _6 b/ q#ifdef        _DEBUG
* T; ~0 P6 x1 W& |DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
1 G( @, b( a$ F#endif8 M6 B; ?3 R/ D$ i3 k
}
; I3 D5 ?" g4 e- f- f. n
1 J; _7 ?. ]7 Y' |void        APU::LoadState( LPBYTE p )6 [; g8 q' u6 X; Z- N! x7 j- W
{# `% z7 L! Y+ b5 T% r
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡3 h+ D1 W5 B, R5 i9 m
        QueueClear();9 A& A% q- l, a

3 v% R2 y4 J  k! X- G* W        internal.LoadState( p );  y! m2 s0 N5 ~
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
* C* t& D' r$ k2 E: s$ g* W4 v) S0 |& r9 a2 U
        // VRC6; L7 U+ R# n" d- }& M8 r
        if( exsound_select & 0x01 ) {
( v( i9 r0 G- Z6 R/ H$ U0 n                vrc6.LoadState( p );
* @( o: `4 w$ C1 F3 v' P% e                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ J, H1 M& Y- v" S+ |: Q
        }
! X$ b' N7 ~6 D9 o8 d        // VRC7 (not support)
: I# R& p6 X' i, S% l% u        if( exsound_select & 0x02 ) {' t: Q2 W9 G* X% u# P5 O5 ?) m
                vrc7.LoadState( p );/ H: \6 D+ `! `: P! l# S
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 s9 F  ?( t" q4 F* r
        }+ O  z3 S; Y6 Y# s3 [
        // FDS
" ^& e# i' m8 v5 R        if( exsound_select & 0x04 ) {) y: N" j# v5 k, }$ {7 Y8 X9 ^
                fds.LoadState( p );
' G- j$ g- u, w) n                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding0 v+ \' N0 f! I% V3 y( Q  u; ~
        }
# e6 @9 Y5 E# T: d* N/ I        // MMC5. E0 ?! H  j+ y% q! y/ I
        if( exsound_select & 0x08 ) {
) F- T# u8 q! C) i  c6 v                mmc5.LoadState( p );  a+ X) w1 n$ [$ l( _
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding9 Z) U, m7 o: D0 w
        }
- \2 {2 f$ H# j/ ]        // N1065 Y% T. A$ e, b7 j& B/ u: T- t5 z7 v
        if( exsound_select & 0x10 ) {
, C8 c" v4 b  H; E, k1 D                n106.LoadState( p );& [; e/ u: \' a' M
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ R& A% `8 s% c! X: ~' N; ^( _3 E( U2 d        }1 U3 j4 h! @4 ?8 Q/ Y
        // FME7
* z) t/ H8 a! F4 J% D1 l7 e        if( exsound_select & 0x20 ) {4 J0 @1 c) i& L1 f
                fme7.LoadState( p );, y3 p5 t- b. Z+ O, q7 D
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
4 Q. L9 I) G. J+ U4 i  i& e        }/ o; Z2 V8 l/ |  l) G9 a0 h& A
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 & i% g+ H6 n# S) v2 `+ k- |* W- A
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 [* }! M' T7 d; X6 Y/ @' r, k  L
感激不尽~~

' r/ z$ D# q" b" [恩 我對模擬器不是很有研究,/ d2 d2 W0 m0 `
雖然要了解源碼內容,可能不是很困難,
& }" X6 V- W% L# R不過還是要花時間,個人目前蠻忙碌的。
9 i- R  `8 [5 o/ U- h' K% Q! S" i6 P5 l# P
給你一個朋友的MSN,你可以跟他討論看看,  j3 u; E! o0 o5 w
他本身是程式設計師,也對FC模擬器很有興趣。' j! h: _9 C: U+ A# a

4 N7 m0 K) v/ y! B  W& g4 CMSN我就PM到你的信箱了。
8 s2 f9 p# Q/ d8 I6 O" U, }3 Z7 q' j1 A2 U/ |- 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 发表
+ g1 y5 e8 h; q2 o) F% Q0 x* m呵…… 谢过团长大人~~

7 z& q) k1 ?6 t8 K, I* f  s9 I& f. J, L
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 , @5 Y- N" ~8 ?* O) K1 W9 h6 f
团长的朋友都是神,那团长就是神的boss。

7 S6 b8 s2 ~8 _( `( ?哈 不敢當,我只是個平凡人,7 V# o7 d9 d7 I5 T; E" l! N
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙3 C7 m6 V: h1 O( ]2 n
ZYH; i3 O2 i8 X& q# ^$ P3 ~! ?4 P
QQ:414734306
  J8 E* d/ ]3 UMail:zyh-01@126.com
( j# [8 k# }5 T5 \) Z9 E3 y
7 u% t5 \- k# i) g* E他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
+ w0 \' }/ W: }+ ~再次对团长大人和悠悠哥的无私帮助表示感谢~~

% A* I1 {# x( t不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-20 08:55 , Processed in 1.097657 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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