EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 ^7 U  l) Z. y5 G$ U
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% _1 L# I3 V) |2 p$ ^  \
这里有相应的模拟器源码,就当送给大侠了~~5 l4 l/ N3 z6 c6 s
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 X- R5 k; m0 u! a  j! |能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( W- r' z1 d; [7 A/ e6 n楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~, }* ~$ N8 Z) r( D9 l. _' B! x
这里有相应的模拟器源码,就当送给大侠 ...
9 q; j4 p8 |3 G' K
聲音部分(Audoi Process Unit = APU):
. c- f3 o# k- u. J.\NES\APU.cpp1 L' l" a# r( J% U4 K/ c
.\NES\APU.h
. U/ ~+ E1 P' `" ]7 k1 j  R3 n

/ b$ F6 C% Z* X( f/ y影像處理部份(Picture Processing Unit = PPU):* z& s" b0 S! Y0 h
.\NES\PPU.cpp
) x! l: I: k( v.\NES\PPU.h2 |  ]. C5 c6 ?
: C; `' H2 B  S
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:8 c* o& x; g4 g& ]/ H
(由于很多专用术语和算法机理都不明白,所以看不大懂……). P2 z9 Y7 r) s& a  f
//////////////////////////////////////////////////////////////////////////( X% L7 O0 V( k8 O- x
//                                                                      //
: N4 A9 @8 k- t0 Q* t) \* p) u+ I//      NES APU core                                                    //
, ]0 T" E' u- j5 W6 L/ w//                                                           Norix      //$ O3 P0 R" m3 E* G1 J! ?
//                                               written     2002/06/27 //! d' O% m" }0 u1 _% c, q8 b
//                                               last modify ----/--/-- //$ ^' s, g5 |( j- t, X( g& q
//////////////////////////////////////////////////////////////////////////# D: Q1 f0 i1 a
#include "DebugOut.h"
) A$ v) B1 |8 n#include "App.h"! w& _: G( K, _/ y+ h: p- n& L) x0 G
#include "Config.h"+ z+ M* F. i, x6 I! C2 ^/ `
* A  ~( m- x& I$ f8 J' v
#include "nes.h"
6 B* T  e/ e6 B% w" p# B6 v& }4 B5 ]6 D#include "mmu.h"5 E( V7 m1 n+ K0 \+ M, N
#include "cpu.h"" R8 o7 x, x0 N1 z. ^  M: z
#include "ppu.h"0 L' c. {: k) T/ N7 v0 N7 ~: X
#include "rom.h"0 J4 b& r+ v. x& v! F
#include "apu.h"/ Z$ d0 u" y4 _" u7 t8 y. {
1 l$ W8 e; N. t1 a0 [# `
// Volume adjust# ^3 U5 F, B. A4 I
// Internal sounds; s0 ~6 Y! o, `0 x$ {0 D: u  @& q
#define        RECTANGLE_VOL        (0x0F0)
: N) o& y" [+ ]6 d  O1 m#define        TRIANGLE_VOL        (0x130)
# t  O5 t, |/ E( T3 m4 }! T#define        NOISE_VOL        (0x0C0)  A3 w- ^5 Z- }8 m
#define        DPCM_VOL        (0x0F0)% A2 y% V. n+ t
// Extra sounds* l5 S5 U" f7 S$ J$ O% P# t
#define        VRC6_VOL        (0x0F0)
8 j2 [) M& G) i9 ]. g#define        VRC7_VOL        (0x130)1 m) l3 F. j! ^. Z, G! \4 R) @- }
#define        FDS_VOL                (0x0F0)
4 p3 ?' X1 w7 I2 b4 e. @& b  ]" S#define        MMC5_VOL        (0x0F0)% C" m# W7 g7 i4 A' r$ e. |
#define        N106_VOL        (0x088)
* T+ k8 t: }% U1 K; l5 p$ z( J#define        FME7_VOL        (0x130)% E# s" c- D1 m8 u$ [) {

: w3 w( k, f7 D2 @2 E* N( P4 QAPU::APU( NES* parent )
% ]  B# H/ c. U, d$ R9 c{
# @: f& f7 j8 u- f/ r" t        exsound_select = 0;' ~" l5 r# ]+ Y% z6 R* B
, e( R3 e) N7 [7 P' E4 h! M3 o
        nes = parent;# |3 s+ c1 M9 t3 a
        internal.SetParent( parent );  y8 L+ C" R& N4 ]. q
+ z' d: x. o9 C, y6 @
        last_data = last_diff = 0;$ v/ _7 e/ |& }5 D' V) z& ^
; @0 O* t5 ]9 a2 }& O( T
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );8 r% `; \2 C2 E8 x' U8 N/ Q; o

' K/ T) M  T0 K! A        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );( C# s/ Z# v/ q7 B! J
        ZEROMEMORY( &queue, sizeof(queue) );* d+ ~7 Q, }. Q) G% M5 c* ]. G% I' B
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
/ [9 K# G/ F: u% A
' i* E$ s2 h2 R        for( INT i = 0; i < 16; i++ ) {, i* n) k1 `1 [* X, p
                m_bMute = TRUE;  v, W1 G; f, e* E- {6 g$ ~/ R
        }$ v9 _/ Q! k- v- Q$ G) u0 ?
}/ n2 K, a" L: i5 u/ P2 i1 r0 W0 L
$ B( ^0 p7 Z; O# p
APU::~APU()$ U" }) X" T, r' U
{
  V5 {8 x, _! I/ H* t4 O}$ O# n3 a8 Z5 b  N) P5 \

6 }# u. e& ~& }* N$ l9 }. t* E5 ?void        APU::SetQueue( INT writetime, WORD addr, BYTE data )% j* t0 U" i$ i0 {& ?) i# m4 k
{
; _" e3 O8 U  O3 j/ ?" g4 h        queue.data[queue.wrptr].time = writetime;; n; d( b( R7 [
        queue.data[queue.wrptr].addr = addr;
5 q9 Q  Y- n2 l3 E, _        queue.data[queue.wrptr].data = data;
/ o/ x# G2 E3 _. v% f: [        queue.wrptr++;
2 d  A' Q% K* {! L        queue.wrptr&=QUEUE_LENGTH-1;7 p/ s+ Z# c! I- _( o
        if( queue.wrptr == queue.rdptr ) {4 A9 W6 ?+ J8 v: n, x9 Q# K* Q
                DEBUGOUT( "queue overflow.\n" );; V' o8 a, E/ L) F3 }( [2 x' k6 w
        }
, i0 ]  A' e( |/ v) E}0 G( H8 e2 j$ @6 c5 c
% W1 g8 s* x! ?" h5 i! g
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )! Q# o( Z; n$ o3 v# \% B
{
# s3 H3 ]3 Z5 g: J! \" }        if( queue.wrptr == queue.rdptr ) {
6 }& H# ^) x7 ~5 q. \! u                return        FALSE;  [: ?6 m6 B/ k! Q" ^
        }8 i& G  T$ A: y% ]2 P" [
        if( queue.data[queue.rdptr].time <= writetime ) {
# b  Q8 P% r/ l- Q# x                ret = queue.data[queue.rdptr];- o! a, h5 f4 D
                queue.rdptr++;
% x, z1 V+ p! S# c7 F7 W% c                queue.rdptr&=QUEUE_LENGTH-1;
. ]# F* U$ Q5 M                return        TRUE;0 ~9 j  n5 f, X+ |
        }: J: B# H4 b* k% \- b( J  I  \( Y6 q( E
        return        FALSE;5 m5 c8 D) N( m' V5 o5 _
}
/ y: L/ k8 h! x, J
0 G% ]6 l$ V9 L7 tvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
# m7 Q( \  _% s{
# a5 i: [, ^2 C9 g7 b        exqueue.data[exqueue.wrptr].time = writetime;
) m- g! `( Y% _        exqueue.data[exqueue.wrptr].addr = addr;
0 D. y8 s- ?3 y2 B9 T+ H9 o& c  D        exqueue.data[exqueue.wrptr].data = data;
6 F1 j- `, ?- d+ ]$ E7 t7 _- l1 l        exqueue.wrptr++;
4 p5 @/ U; B9 A1 m5 M" \3 B        exqueue.wrptr&=QUEUE_LENGTH-1;
0 n+ x% b) d& j* F( e- u        if( exqueue.wrptr == exqueue.rdptr ) {/ c) B: k- \4 o8 n! b
                DEBUGOUT( "exqueue overflow.\n" );& M# P0 r) c, ]
        }2 x  `3 w1 Q" D; t
}" G( i4 ?& f' @6 o* @

" M/ \# ~. @4 c( B4 h* aBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )5 |* ^1 Q% y* E% a
{6 W$ k/ i8 R6 B! U# ^4 C  t
        if( exqueue.wrptr == exqueue.rdptr ) {
1 n2 M8 _+ D# F; K                return        FALSE;
$ C: a9 z" R; Y9 ^8 @        }
" p. a2 E' u% V8 `/ w6 ^        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
0 H! \2 h7 \+ J- f: S* ~2 e. ]                ret = exqueue.data[exqueue.rdptr];
, K  e, S% a; Q8 O8 z+ B/ U                exqueue.rdptr++;
/ A" d$ l& k0 i" O6 K6 J& f                exqueue.rdptr&=QUEUE_LENGTH-1;- [6 ]- Z1 A& g# x& D
                return        TRUE;
; E/ {8 Q" q' }1 }( i" s        }
: @; }% a+ G8 x# @$ d        return        FALSE;4 p  A9 V4 @1 @+ s
}2 [0 G! h; \8 k# d* n- l! b
4 `" e" I2 J  f5 o: a& D  \! s
void        APU::QueueClear()
; @4 u( M" \2 H{
- s$ e7 p1 o- Y1 _4 v# Q+ c0 ~( Y        ZEROMEMORY( &queue, sizeof(queue) );
9 b2 u; C7 U4 f        ZEROMEMORY( &exqueue, sizeof(exqueue) );
, |4 E2 S4 ~# d: I/ `# ~}
, I7 h" \! p. Z* u; [
3 c+ ]2 z0 ^  P/ ~, D! ivoid        APU::QueueFlush()
: u/ Q8 X5 R. H5 f5 `4 g{7 x7 `& z. D! Y- u1 w7 g
        while( queue.wrptr != queue.rdptr ) {
7 ^, m6 S0 D) }% y4 l/ C" A: X                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
; H- j7 v/ ]: v: |8 |8 F                queue.rdptr++;
5 Q; i8 D4 Y" C0 Z7 d4 j3 Y                queue.rdptr&=QUEUE_LENGTH-1;6 i# c4 c' m$ o$ c6 L
        }
1 M3 `9 }. \, ^+ M% s
2 T3 `8 g) A( H$ u7 T' m        while( exqueue.wrptr != exqueue.rdptr ) {
& A* `7 s" j5 a% D8 |$ x                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );5 |4 o7 M- k1 T
                exqueue.rdptr++;9 ^9 b; n& ~/ n% h# b
                exqueue.rdptr&=QUEUE_LENGTH-1;  B+ p/ a3 A% I6 G% o& Q2 G
        }8 z$ P5 J( P" [2 R5 M5 t& X
}
$ w5 B( w" D! E6 C5 F" j
% X' C' d; R7 q. ~' {3 q' jvoid        APU::SoundSetup()+ ^2 T' D% [# g7 d( f+ W
{
% h! F/ O7 D6 u+ O7 P        FLOAT        fClock = nes->nescfg->CpuClock;, S  \0 G; I& l, \; s' L
        INT        nRate = (INT)Config.sound.nRate;" A. i# Z' P- e0 ?; X1 ^# m% Q
        internal.Setup( fClock, nRate );
; `$ R) J6 J! `+ ]& j, D# p        vrc6.Setup( fClock, nRate );# B. L1 [; f. q$ i' x6 I
        vrc7.Setup( fClock, nRate );
" [7 N6 l8 R! w; O: f6 V* O7 E# i, ]2 a        mmc5.Setup( fClock, nRate );
6 `& A: ^, B" W) b0 X        fds.Setup ( fClock, nRate );" @: }% n2 V# W) M0 f
        n106.Setup( fClock, nRate );+ U4 ?) i+ f5 k3 H( w
        fme7.Setup( fClock, nRate );
) s4 p1 E0 Y* M# Y) }}. {7 w  f+ w3 X& `1 w9 d3 {( m( C
4 \. K: d+ P3 Q% Y8 M. Y
void        APU::Reset()9 i$ K% d+ y# C4 z* b
{
8 a& |; D0 x# R6 M: M& n& q        ZEROMEMORY( &queue, sizeof(queue) );8 C3 g4 c* K7 X: [; _' {
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. t: h- o# H0 f0 f! h+ d) a

$ m4 \# L5 H& n4 a        elapsed_time = 0;
& J! _7 |5 K+ l4 z
5 L0 s* j, e+ R3 O6 M. K* k* m        FLOAT        fClock = nes->nescfg->CpuClock;2 @' l1 N9 Z' h% Y7 O
        INT        nRate = (INT)Config.sound.nRate;
2 L# t5 F8 z- J/ n* ^        internal.Reset( fClock, nRate );
5 _  @- P) _+ i/ j% g        vrc6.Reset( fClock, nRate );
9 c7 C! P. o6 L) n9 d        vrc7.Reset( fClock, nRate );; L% _4 X% K" M3 Z) q# N
        mmc5.Reset( fClock, nRate );3 J! [/ T9 k5 ]* a. d4 p
        fds.Reset ( fClock, nRate );3 s( {! S0 Q3 l
        n106.Reset( fClock, nRate );% T: A" A, N/ y4 I$ c1 s* _' E
        fme7.Reset( fClock, nRate );
# Y" i3 W  r/ Y3 [! g
$ c; w5 x0 u7 z3 ^) g# U        SoundSetup();
  r2 J9 b$ b- c- x- P* r' E}9 d3 n2 |2 c* M" @4 V. S8 Z& M

% i& H, ]' v3 T4 svoid        APU::SelectExSound( BYTE data )
/ O: {. a9 N' g& s$ M/ Q% H{
3 i: v# a) @7 F  g6 u/ k4 Q        exsound_select = data;) ]- F( |9 J' d/ }$ n' u( ~
}
: z3 E* t9 H. y" k4 Q3 M9 W) C( Y3 x; x$ w( b, [2 w* Q
BYTE        APU::Read( WORD addr ); q! a8 v- S  ^# }/ g
{& {2 Z" o. M9 n
        return        internal.SyncRead( addr );
0 t& |6 ^: U. D}) p  x& v& S4 Q6 h8 E$ F' m% j
: q8 i( R9 {9 L4 e  b
void        APU::Write( WORD addr, BYTE data )
; Q! Z0 G# j" ]( t, ?9 _{
/ }, K. R( @8 \0 C+ D$ A# u        // $4018偼VirtuaNES屌桳億乕僩6 K: K, i+ \6 C: L! c
        if( addr >= 0x4000 && addr <= 0x401F ) {) E" C: w3 J+ v, ]. y3 \
                internal.SyncWrite( addr, data );
3 z4 [. i# ^* `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );" l, \  U& Z9 _! {( h& _: I
        }
& W* j6 {. Q/ Q% u}
$ H! C: W- p3 R; m5 w
! ^! B' W: y4 G4 m. ]BYTE        APU::ExRead( WORD addr )
  ?5 B) ^3 `  y9 ?- |{& G& u, z% P: o1 T
BYTE        data = 0;
" t% A% d$ i; _/ l9 [/ l9 u8 \$ h9 q- M
        if( exsound_select & 0x10 ) {
& u" I( e0 u: ]% b' _2 k' n& _                if( addr == 0x4800 ) {0 K" X- ~. g. A! {: E6 B8 q* j  }
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );: D3 m1 `/ l2 S: |
                }; r9 E! d9 b- l! Z' L. y
        }8 B% p8 w! `5 y2 ?
        if( exsound_select & 0x04 ) {
- n6 I. X! H# `* x, ~+ u: C# h                if( addr >= 0x4040 && addr < 0x4100 ) {
5 C. B7 N( e9 L2 Z                        data = fds.SyncRead( addr );
) Z+ G, Z7 x$ q0 s2 ]2 [                }; c+ V" K: z* T: m' a
        }
, s  b# ?5 K/ g/ B8 a        if( exsound_select & 0x08 ) {) q, f0 y/ g, Q' d! ]+ U0 K! |0 l
                if( addr >= 0x5000 && addr <= 0x5015 ) {
+ e; a" e" ^) t6 T% B1 I# k                        data = mmc5.SyncRead( addr );' G3 L4 i# \* |1 l& m$ C+ ~, p
                }4 N) h4 b. m; P& |2 n
        }6 e5 Y7 c! z5 W5 ?3 b; ^3 I4 P3 J

7 m3 A+ p  A1 n' y! P! f$ k        return        data;
4 e2 U, z/ d8 y7 L' N3 b}
4 D5 a" s$ v% Q1 p/ L) S% P9 q1 t" ?% V/ S* A8 _
void        APU::ExWrite( WORD addr, BYTE data )* ~+ L! t' F% g' \1 M* U- O. D8 T
{
3 T; k# b% \$ d7 O0 z        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
+ K8 M: R+ j- b& }. e1 o4 x
! M5 K+ s9 F/ G+ n0 C( s" c        if( exsound_select & 0x04 ) {
9 X2 u2 ?* j7 ~2 D8 M+ n6 i" J                if( addr >= 0x4040 && addr < 0x4100 ) {
) R0 f4 g; V, K1 f' z                        fds.SyncWrite( addr, data );6 W6 |6 b2 h- o4 c% \9 S5 F6 `8 Y; i
                }
9 u* u3 K( d0 a/ z7 E        }
1 M7 F+ q5 a5 h0 Z- x' y; |
( f3 H( u: {  }: o) i% v. m0 Q        if( exsound_select & 0x08 ) {
8 N  r& k& r( C/ S- @                if( addr >= 0x5000 && addr <= 0x5015 ) {* E3 {0 S( D! P6 \2 L
                        mmc5.SyncWrite( addr, data );1 W9 V2 U7 \7 U. m1 x
                }4 A, ?( R) B* F4 g2 y  L
        }1 h8 t% K6 z7 v. D5 G! R
}
6 w3 i# T1 Y6 a  V5 J
% ]0 N% t' A, [8 d7 U/ }* ovoid        APU::Sync(), {3 h  t, A/ |9 {; B1 Z+ O
{
0 M& f% o$ x: S4 f# e}' @( K* X  ~) j* Y

6 B" N( l$ k& ?& `void        APU::SyncDPCM( INT cycles ), w# e- z! y8 p# l* N0 p
{- c5 r' P1 S+ l& A; d: r
        internal.Sync( cycles );
7 E; P" H$ v) s  ?2 X, }& W; l* a4 f- e# {  [4 k' v9 u
        if( exsound_select & 0x04 ) {# }' Z! @$ l* L1 Q' Q# z
                fds.Sync( cycles );
; U& \1 l, ]. I. j/ V        }+ B% l& E' K* b+ Y  D8 G/ p9 R8 ~
        if( exsound_select & 0x08 ) {: b2 c8 Z8 D  I; n2 d# O
                mmc5.Sync( cycles );
( \5 `  ?) ?5 `0 v8 K        }
* A1 h. Y9 f' N}
% v. Z5 |6 {9 O. k* E' g( G- E3 l
void        APU::WriteProcess( WORD addr, BYTE data )
9 b, i+ H4 _: G{! o. T" k+ O5 M$ u2 D7 X5 K
        // $4018偼VirtuaNES屌桳億乕僩
; l. z2 T3 P* Y1 b% D3 N/ F        if( addr >= 0x4000 && addr <= 0x401F ) {2 R4 l( ~* f$ k' S) ~( y# A
                internal.Write( addr, data );
% E4 x8 S. T% _, x) S# a5 F        }
* O2 _3 }( m( f* k' }& o}: [! Q- E- A2 B9 L: B+ R

, U% y6 d6 i& s0 h, wvoid        APU::WriteExProcess( WORD addr, BYTE data ); [( _$ d" F1 W# s: ]7 l
{$ `7 m& `6 b+ J% Y- M: }; h+ Z
        if( exsound_select & 0x01 ) {' u! @' {2 n% R5 G8 H+ _" f4 g
                vrc6.Write( addr, data );# [, B* a. |/ `8 g: f
        }
3 [0 ?6 p- [4 y3 z) ~4 S8 ]- B; y* W        if( exsound_select & 0x02 ) {
* K, v! \/ T. P0 d% H* ]                vrc7.Write( addr, data );* ~1 a3 ?/ v6 x0 d! R/ ~
        }# D* F6 x. K( B, d, S7 }
        if( exsound_select & 0x04 ) {) y6 r* k* k2 @
                fds.Write( addr, data );7 B/ I( z7 l# f( |
        }
" l1 ]3 V2 H8 Z        if( exsound_select & 0x08 ) {7 w8 P$ m: P3 k, Z4 ]: r+ b" O! }
                mmc5.Write( addr, data );
( u1 I) W: m+ N2 S        }( t) G; M* Z3 n3 x/ J+ D3 R
        if( exsound_select & 0x10 ) {: d1 E' Y4 q# W7 e5 d
                if( addr == 0x0000 ) {
" O0 T) l1 |( g                        BYTE        dummy = n106.Read( addr );# |5 B$ a( j7 p, y6 I6 }
                } else {/ V, W: U2 ^( H1 h6 o. ?+ O
                        n106.Write( addr, data );0 O. }7 \( d% C# _1 D- y: ^7 _( Q
                }
+ G( t7 w9 [2 t0 d% l; {: f        }
1 w9 u! b6 ^# j2 N" J9 J        if( exsound_select & 0x20 ) {
2 b  W% V  d- X: h, f                fme7.Write( addr, data );
7 @1 y  l6 A* P        }$ a% e! f- q0 S, ~
}& N2 s  u/ X! }

8 s- G- a) W2 d' K4 y0 Dvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
. j3 e1 ]% y& G; x& X. ~+ p( r- J{
* q( u$ W  R( `( aINT        nBits = Config.sound.nBits;$ p  D0 o  p% R& n7 {& {
DWORD        dwLength = dwSize / (nBits/8);5 y8 U: m- O, j  Z& [5 g- W4 S
INT        output;0 \8 z6 e! a( Q. r' f# z
QUEUEDATA q;
, X& a4 ^4 {) A# v4 V- h5 KDWORD        writetime;0 e* o" i( t) k5 v4 j

' F/ W& i% V  i$ N' PLPSHORT        pSoundBuf = m_SoundBuffer;
, p. u4 h* V# E. F/ Z7 E9 i' HINT        nCcount = 0;
$ T* ]' U! r3 o, }- {( W( }( b3 ], H' f7 N( x1 l3 f7 }$ `2 I, I
INT        nFilterType = Config.sound.nFilterType;
. X; Y7 f7 @: {
. }6 Z6 c: y, c* y4 E- J# `0 G        if( !Config.sound.bEnable ) {
( \! c: K( `7 I                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );, g6 @! y8 f4 C: {% L0 V2 V
                return;. b! a' ~7 l- I8 L: z$ `- p
        }+ d( y& r. N+ N% {, m& {4 `# e
- d( c" T+ G2 d, ]5 ?* N: g
        // Volume setup
5 X' c5 @1 X7 c: j7 N        //  0:Master2 k: K4 S# `* r
        //  1:Rectangle 1
9 N- L0 V: Z2 Y4 v        //  2:Rectangle 22 H1 ^- p+ f/ `
        //  3:Triangle4 O1 x& z1 F  n
        //  4:Noise
% V$ {& b$ \% I/ n$ v& N$ [! U        //  5:DPCM' w9 `0 c# J$ E- v
        //  6:VRC6
( ^/ v! h" e- C. f& Q. i        //  7:VRC7
9 X* @# t9 ~* e) t) k        //  8:FDS9 t6 t% ~0 v: l# M( a
        //  9:MMC54 O" S! z* }, ~3 V8 n* e! Z
        // 10:N106
$ e( C3 t7 |# ~  y- T# T7 ~        // 11:FME7
1 l/ K3 A$ |  f( ]8 R7 }        INT        vol[24];+ Q! o( p. M( t- u3 o8 y' Y& n# n
        BOOL*        bMute = m_bMute;/ I, E2 c; L. A1 [% U$ j
        SHORT*        nVolume = Config.sound.nVolume;, a& O3 |# h& c0 F* B7 K

$ S9 e$ \6 J; ~8 @        INT        nMasterVolume = bMute[0]?nVolume[0]:0;1 ~4 @6 G2 \" c
0 J' b8 d( `" S1 Z! v6 T
        // Internal
2 f0 q+ M) G+ i        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! H; s! K, b! L, `6 x        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;$ x5 t5 j& r5 b! |; h1 ^5 D
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;% h2 W. p+ u$ |
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
  ]0 p' E+ ?; u. n( F3 k4 I7 R7 s        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;+ H) {: Y8 P* A9 L+ W) u/ H

. S( z0 B8 m7 Y        // VRC6
: G$ D- m) k" {+ o/ d) ]        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 R. {, D3 V3 W; j8 |, s        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 ?/ y0 J+ G1 u" p        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;. B& l2 k7 [2 O$ C% I

# u; w" h4 d! c5 d4 j6 V) p        // VRC7
1 V! k3 E9 B. h; R2 y3 g. M        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
0 e! ~+ E  i; Q* J3 j
9 H) Q4 o4 }- V" n        // FDS1 V3 X  n5 j5 A
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;; h( s; Q4 I: @# t7 y3 C

: |$ C7 o( r/ p5 A9 T$ j2 \        // MMC5
" C1 d/ G; [* j( C3 }' ?% t7 x- P        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;( k4 g, q% }  N8 F
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# F/ _, m. P3 q3 Y        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& ]8 K3 G3 h0 _) i7 v
" B) K$ V9 J2 ?- X6 B        // N106
/ h+ b& B! X! ?% \; Z* L! [' _        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' n; F& ]& \5 _/ A+ W1 W5 y+ g! E% W
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 E; q) Y  g1 D$ V0 ?, E
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ @/ q3 p3 o& U
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 V2 C/ w- v: H2 [5 M        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 Q6 O1 U9 N, H  d7 g        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;8 F$ h5 N- ^3 G
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 x3 ?7 [( i* F; f        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ D! \% n- z; s% T$ r

4 K( k" A9 B4 P; h% w) ?, w        // FME7  L2 z! D! i+ B4 K
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
+ s8 |! F, Y, T" W# A: n        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- n0 F( K7 P2 y5 m- K/ o
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;6 Y$ C# B* G' m$ C! R5 g. i

, v  t0 e  n+ Y& a: T# y" j//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, I3 ~8 @: j4 g- W" n" @
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;' _! N$ |% w* ]& M2 [
; V2 m. L6 ~- V2 ~( a4 h1 r, P
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
0 V# ~* D! l' s        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
, Y; p5 {- K. f7 T) c1 G                QueueFlush();
/ ^$ O# r$ _- F! |+ `        }
- e2 U: C; R% |7 l3 `1 S
' d- ?$ f% x! u- h8 D2 J        while( dwLength-- ) {  G( L. A4 c4 v$ z2 s0 r* }6 l
                writetime = (DWORD)elapsed_time;' n7 v. \7 }7 ~/ M, U9 \
( l- _1 t7 @) S; g2 }" L* Z
                while( GetQueue( writetime, q ) ) {
& u+ V$ C' m9 a9 E                        WriteProcess( q.addr, q.data );
- ]: E( e7 u2 Q5 U8 H( h! Y+ f                }
) \% \9 C$ W9 z7 ]9 w  J
0 R4 I9 z8 J  B/ ?9 w                while( GetExQueue( writetime, q ) ) {
8 P3 `! N" J+ u+ T3 C# i0 g4 R7 M                        WriteExProcess( q.addr, q.data );
5 d% Z/ ?& z7 ]9 u: _7 ~+ L                }5 V* k7 Q/ d+ p5 l/ T9 E3 D9 x1 s

. K+ g7 O' S2 A                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7( b" ?  L0 V5 d4 J* @
                output = 0;
) O# }& n. Q0 Y( H/ y. d                output += internal.Process( 0 )*vol[0];
9 @6 c; `: E- |# x  V" }                output += internal.Process( 1 )*vol[1];$ \. U- Z/ D5 a6 Q* x! [4 L
                output += internal.Process( 2 )*vol[2];
- E7 m- v) ]3 F; c9 ^  |                output += internal.Process( 3 )*vol[3];
. \, w' ]' [; ~9 @" x2 i& h                output += internal.Process( 4 )*vol[4];
& d, S$ i3 O, ?8 P! V; _9 }
  j- g% Q+ E+ A& f$ u. X4 E                if( exsound_select & 0x01 ) {
4 p) ~2 x$ p- O                        output += vrc6.Process( 0 )*vol[5];
, z0 K6 y4 G+ F& t0 ]3 l4 v$ u                        output += vrc6.Process( 1 )*vol[6];! K/ Z4 C; `# l' a. f1 q# S5 z
                        output += vrc6.Process( 2 )*vol[7];% H5 F: t# D; @! {/ \) U
                }/ n6 @2 Y8 I! D( F# y- W
                if( exsound_select & 0x02 ) {) f! ~& `2 @6 Z6 v+ v
                        output += vrc7.Process( 0 )*vol[8];+ R" c! f' J3 v1 G
                }
/ d9 H/ s' I" a                if( exsound_select & 0x04 ) {
! K( {/ f3 D0 d: q                        output += fds.Process( 0 )*vol[9];
0 G2 L3 U7 F7 d! Y% U$ {                }1 @2 `1 Z6 ?3 n$ w2 {. I4 q
                if( exsound_select & 0x08 ) {
' X4 ~" ~. C( l5 Z; G5 w2 A8 q                        output += mmc5.Process( 0 )*vol[10];
. |6 n' n& K8 h8 `1 v( J6 W3 b$ [                        output += mmc5.Process( 1 )*vol[11];- ?1 g! Z0 O5 U
                        output += mmc5.Process( 2 )*vol[12];
+ V2 U) W9 q: m/ B9 {/ V                }
5 M  C, w$ P4 l! o# h                if( exsound_select & 0x10 ) {( O  w' h! R% \. }  Z4 T
                        output += n106.Process( 0 )*vol[13];4 O  i* C1 P3 ~1 O8 O  W1 @, c; }
                        output += n106.Process( 1 )*vol[14];
" P8 R, G" F: w) a1 C5 F3 T/ M                        output += n106.Process( 2 )*vol[15];
4 P$ y5 q% k4 ]                        output += n106.Process( 3 )*vol[16];
3 e* c0 P' x- Q1 z" _8 J6 c                        output += n106.Process( 4 )*vol[17];5 c# e( m& j4 x3 B% X
                        output += n106.Process( 5 )*vol[18];3 w- @# K3 P8 `2 x; H4 j
                        output += n106.Process( 6 )*vol[19];
, r) o( E* k, d7 W7 f4 B$ k                        output += n106.Process( 7 )*vol[20];
$ ~+ r' q$ }$ o# z! c! G+ c                }
# U) j7 [( o# d2 I4 a" h                if( exsound_select & 0x20 ) {  G+ ]  ?( M5 t: z5 @
                        fme7.Process( 3 );        // Envelope & Noise
" |) R, c2 c, \) x. X                        output += fme7.Process( 0 )*vol[21];9 d% u. ?1 D! y# T: M6 `$ _  f
                        output += fme7.Process( 1 )*vol[22];
. Y/ A. H1 o4 X' T) p% K% E# M+ A                        output += fme7.Process( 2 )*vol[23];
6 n! z' l9 ]; L+ Y6 T                }
( r2 n: s: Z% v7 T2 t5 T' B- G! k$ @' x7 C3 U, R3 c
                output >>= 8;
0 P- d, G8 d7 A4 ?2 }
. J1 R" Z. o/ G% }6 E                if( nFilterType == 1 ) {
. ~) w7 S7 k2 l* E5 M8 g) W3 R* D                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
0 \1 d5 Y) u9 W                        output = (lowpass_filter[0]+output)/2;
' H+ _. S- }- ?+ Z, U, {                        lowpass_filter[0] = output;- {0 C. j1 e: |: m5 k$ R; Z
                } else if( nFilterType == 2 ) {% \! r5 F9 n; k" c5 Y$ e3 h, k
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)( u, T6 {; t# `' V* a; x
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% {* \0 [/ r9 o9 W& Y3 z! i
                        lowpass_filter[1] = lowpass_filter[0];
  c5 Z  H2 ?6 \: q* p6 M4 }0 h                        lowpass_filter[0] = output;0 c! R) T8 O" N
                } else if( nFilterType == 3 ) {
8 p* k$ X( t0 ~9 Q% t0 z                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2). i+ M1 i" ^0 Y" E' E& u+ b3 ?" d
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
. B, Z8 X) @" D/ g" ^8 R                        lowpass_filter[2] = lowpass_filter[1];
7 L. I8 @" \' T; x" U; d                        lowpass_filter[1] = lowpass_filter[0];
- U* C% ~( }. a$ j                        lowpass_filter[0] = output;
2 R. l- K" D1 H# h( D# V+ B5 ?                } else if( nFilterType == 4 ) {
& R* r0 C' s  j9 F: W* F                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)! B. d' P. h( q$ V
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
" k. o; K+ ^9 T$ ^8 V                        lowpass_filter[1] = lowpass_filter[0];4 V3 B0 t  m) b' h
                        lowpass_filter[0] = output;4 Z  r" w, \0 w1 ?; o" t
                }: J1 I% L. J/ i- f- Q

9 p. A# J5 U/ z7 f#if        0) y9 U3 z& T% q6 p
                // DC惉暘偺僇僢僩
$ i. M. u( i, K( O                {; Z2 R. \) N/ Z& j
                static double ave = 0.0, max=0.0, min=0.0;1 x5 a; }0 O0 P0 o2 {, E# Y) G
                double delta;  a) q+ S& I- n6 T
                delta = (max-min)/32768.0;
1 @& P3 J) U" `9 o                max -= delta;
! m( x- p  ]1 G. O$ Z. _0 l/ w# ?                min += delta;
: r  W  E2 f% [* u* t8 `% B                if( output > max ) max = output;/ B! X' j! p# Q) C' y2 \) F
                if( output < min ) min = output;
1 b  }) |" r" {2 }0 ~% l                ave -= ave/1024.0;
1 \) o6 Y3 A6 L* o: S                ave += (max+min)/2048.0;8 j2 i5 ~/ o3 \! p) i0 D
                output -= (INT)ave;
0 M8 \7 R1 o! `7 a& x* Q9 o                }# H* x; \& Z  f# i3 A6 X
#endif
+ s) t' t, d' ~4 M4 L#if        1! V0 x1 P; {* K6 z% A4 v
                // DC惉暘偺僇僢僩(HPF TEST)% n5 v9 Q/ v& W3 S3 o7 k+ z
                {
* ?/ X& l# J, y) r8 u8 z6 q- x//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
' C% a' P( G* k- `4 k                static        double        cutofftemp = (2.0*3.141592653579*40.0);' P: m3 N5 }* t. b2 X$ W6 V( z- p; M
                double        cutoff = cutofftemp/(double)Config.sound.nRate;& i) k5 l* E8 E' u0 Y4 w5 r7 m5 F
                static        double        tmp = 0.0;; @* h2 I' g  D2 _$ o+ E$ U& N
                double        in, out;
$ o  }, R( t; F  C8 ^3 E5 G3 X6 j5 r7 J+ z$ k; d( s1 y
                in = (double)output;: C1 s# `, ^( {$ @- i6 K0 ^3 s
                out = (in - tmp);& l6 f6 D# A7 [& f: ?8 f( [$ [, F
                tmp = tmp + cutoff * out;
# ?" d& }* I1 x: l3 Z
+ Y9 M( v% V4 h) n4 L# \% }/ z                output = (INT)out;- K+ ]2 Z. s* ~/ t( H
                }/ E  M/ L) j5 x3 j
#endif
. O+ h- E* \" a0 n#if        0" n9 ~+ J; ^+ @
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
& g9 v/ t) ^9 g  O9 {/ |2 E                {( I* o5 u" S+ r# ^) q+ Q
                INT        diff = abs(output-last_data);7 L' ~0 a, @- E* A
                if( diff > 0x4000 ) {
7 \- X) ^. ~1 {+ I5 S* P! R1 A                        output /= 4;
- Z) S! r# i' |) q8 M                } else
; K5 j! v+ w& \5 A( a4 w                if( diff > 0x3000 ) {8 Y' b$ e4 ~/ |- m$ ?- J( |
                        output /= 3;8 x) f* o( K2 N% I3 `2 t! Q
                } else
9 z2 j0 {1 K. P7 N1 \                if( diff > 0x2000 ) {* r* z3 h; E3 Y9 q' `* u; @
                        output /= 2;/ ^0 H1 Q- |8 Q) j
                }
' D. S9 I, e! Q                last_data = output;
$ F0 Q/ f+ E8 m# }, K: m                }
/ E! N, \5 W3 w* {# d' e( J0 e  u) h! z#endif
5 R" M, J% v5 f0 H                // Limit: c0 O, w6 P" W! K/ \
                if( output > 0x7FFF ) {7 A) A1 }$ c* X% o
                        output = 0x7FFF;* b8 i; N) M& M
                } else if( output < -0x8000 ) {/ w" N0 ]) R/ x
                        output = -0x8000;* \( n+ X. d# L2 U
                }- ~  T2 P* {1 m1 g

' S9 `& N0 Y/ q                if( nBits != 8 ) {
5 r' N8 s5 ]9 a# I8 o* k( J5 q                        *(SHORT*)lpBuffer = (SHORT)output;
1 J; S* G; c+ D7 `4 a* g0 X                        lpBuffer += sizeof(SHORT);
& x2 M; G: @* S                } else {" {2 m( k* }7 O* w/ P
                        *lpBuffer++ = (output>>8)^0x80;# S. P4 N% q& r& C2 y
                }* S4 m1 P0 G+ G; V; x  G9 n

/ b2 B! K# d  Q' Z+ W                if( nCcount < 0x0100 )
" ]! ^9 e/ Y' J                        pSoundBuf[nCcount++] = (SHORT)output;
& n" }# w( Q7 j9 i8 W" U' S- M7 x4 w! U# t7 f" Z, p: [
//                elapsedtime += cycle_rate;
3 g! H9 P* K9 {" ^                elapsed_time += cycle_rate;  z" P# w, s! p+ T! Z2 e' \
        }2 u. d( T* L! N: |+ }. L6 Y  ]
7 q+ l; F6 o5 S  {
#if        19 O6 G3 L) a/ j
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {, B1 Z. \# ?5 K; r' c7 n1 ?" t  i" m
                elapsed_time = nes->cpu->GetTotalCycles();
& h: ^% O2 D2 r: n# k' G        }
9 j6 i9 b% v: {) c        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
: @6 o: e3 S% R+ ^: C7 B                elapsed_time = nes->cpu->GetTotalCycles();
+ E1 c) k& |+ E7 E) J5 J( R        }
" i9 K4 r/ |/ i' H7 K0 d' w#else
: ^* m9 M* y7 N- g5 X. g) L2 C        elapsed_time = nes->cpu->GetTotalCycles();. f. Z; Y' Y( z5 }6 [' @9 H, |0 Y
#endif2 D1 M4 l7 P; R5 @  O" [+ C& P
}
" s( A- u, O+ ^! \7 F- o  v9 g# F0 |& w! E1 y
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
: a9 j/ F- h* i* V! ]+ T1 OINT        APU::GetChannelFrequency( INT no )
" L* ?4 p* J2 q4 O{
$ k: W* \# Q& R( }( S: K& a        if( !m_bMute[0] )( v) X5 Q2 N. i( A
                return        0;- L& r. g/ Z+ G7 V
" Q; Q& T0 z  u, G! P
        // Internal
2 J/ Y1 w, @( u8 j# d        if( no < 5 ) {5 p0 u! Z  P' U4 F
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
& N8 w, C' y* X6 Z        }
+ g# j4 a: r, y$ h        // VRC6/ b8 v1 p$ `8 H. i* W( X* F  o
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 |) u5 F4 N  M
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
& a. S- M  C4 ^" L/ S. D% p' u0 i        }
; r5 h8 }* l7 X3 @/ Y3 l- M        // FDS4 ^! H% N9 {3 [7 n
        if( (exsound_select & 0x04) && no == 0x300 ) {( t* y( ?) S4 h$ F; k* i
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
# ^6 Z- d3 V) g2 f  A. O$ m        }
$ l5 g+ o0 D3 d% |        // MMC5& A1 w. S& Z, ]
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {* x4 J3 o" Q; l  Q, w( v
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
, l+ e8 D% \# W3 W5 M        }; g$ n, y9 H, r; _8 P; L, y; {3 _! R
        // N106
5 U. H4 }( r" L1 w* b3 V1 D( ~; Y2 m        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
8 O! V6 B/ D* ]+ c5 q                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;! K' q0 S) y) ^& i( V
        }
9 ?. q! n, A1 J6 q% q        // FME7
7 U+ _. |9 N& G+ m, w7 `7 S( Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
+ p4 k5 ?( [  F6 t/ f4 V& u7 u                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;. L9 t4 z( N0 N5 n( s8 d
        }( d' h6 R# f# x
        // VRC7
' X6 m7 O' v  k- v        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {8 t& `3 u5 x" a* A2 N; g
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
6 ~, h5 ^1 j# E6 w        }
, T4 E9 q$ V4 i' H: R6 R        return        0;. h& U) F6 ^1 z; @# Q
}. p4 W/ ~* W/ u6 w

8 n  y( y7 i( X// State Save/Load: `8 h+ E: l$ \1 i) i8 {
void        APU::SaveState( LPBYTE p ), m9 Y4 F9 T, w7 {
{
* W, @' G+ W$ E: J#ifdef        _DEBUG
# f$ G8 n4 q1 g& \# d0 tLPBYTE        pold = p;* K* b2 m  W; D- \
#endif
; U: R( F" T  \8 x3 T( M  l0 L2 B2 T$ A4 z9 A& ~' j# m  G
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞2 p: t1 ]/ `+ E1 _; a* I6 @
        QueueFlush();, w& w) p. d3 q( j3 k; r- y! n  l
0 T3 K1 c/ V$ u0 ?# B& O/ e3 c
        internal.SaveState( p );
1 e& b4 V( B/ P( c        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding; i6 R  a' w+ E$ l9 u  s
  A5 q) [  S3 y
        // VRC6
9 f3 J, `! y) v% n5 B$ o0 Y$ r        if( exsound_select & 0x01 ) {; |$ A" I/ [% ^  i( X! h
                vrc6.SaveState( p );; O* d2 t- \, m7 a: t, b& u
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
" m4 B  J5 g# J6 o9 H  l        }9 G+ M9 y$ L) h" k
        // VRC7 (not support)
$ ~( I4 f/ q# O* [, W        if( exsound_select & 0x02 ) {$ X; H: ]$ Y1 @5 m! L, Y
                vrc7.SaveState( p );
+ D2 q1 h- h- [                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding' }5 Q0 Y. ]) z6 K" J4 t; d, I
        }$ J# v0 N, S6 R/ c$ O  \/ h0 h
        // FDS' u1 P- j4 R" s
        if( exsound_select & 0x04 ) {
( w* ^2 u) m" f! D+ n' o$ L                fds.SaveState( p );
- q% s1 Z. Y2 |0 Y( r; H                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding/ b) D3 [+ i2 K9 ^4 C% g
        }' t$ p- C  u' }. `$ l! L7 U6 T. `  B
        // MMC5" o9 d3 J1 ^/ Y2 G# x' q# b
        if( exsound_select & 0x08 ) {, u1 I* I8 T  t! N* u& O7 Q- T
                mmc5.SaveState( p );
- e' T5 Q/ U0 \                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding" f5 {2 h4 ^4 u! L+ [
        }6 l2 Z: J7 r& {# P5 y- Q3 e
        // N106  p' {3 v) @0 _! Q
        if( exsound_select & 0x10 ) {4 N$ v7 L$ b/ i' M
                n106.SaveState( p );. m! q3 M1 Y) H. l) M; I! y6 Q' n& c) E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
" P" C3 ?1 N+ f5 W' E" O        }5 B% E- s7 o6 X& X& j
        // FME7
0 T7 |% Q% I( p, R        if( exsound_select & 0x20 ) {
/ ~6 o$ p; t4 }( R; O- T* w( S- k                fme7.SaveState( p );
) d) O, _( {$ i/ V0 n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding+ |0 X8 S2 j) \1 _* e- X/ _4 b% Z
        }
) E% a6 }% m* k# O! E
% ^* Y  B( F: b, j$ }/ L9 ]#ifdef        _DEBUG  O) R1 Z( R) y/ ~3 e4 G! o
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
. x. v: \, c2 W6 u# X#endif8 O1 g9 m: P8 p" u" A
}/ s; B, o* T) C! O1 _* T

& E/ }+ Y6 ]$ `/ q- _6 m4 Avoid        APU::LoadState( LPBYTE p )
8 P# r, B6 `0 H3 U{
# |3 J: a  m4 D% a" H% l! ]' c" z        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
2 I1 L( U) ~! ]3 u& U/ p4 q        QueueClear();0 K) B% |. i- R! U" J9 _  l; n

- l) [! }0 j. Y( y8 E, j/ d/ B        internal.LoadState( p );8 y( c' ^: M9 d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding3 e7 p+ u# L. ^; P# D5 `7 ~1 J
1 Y: p3 D1 D/ v+ w! z
        // VRC6
9 f6 x: p. G! C        if( exsound_select & 0x01 ) {
4 ~. P2 r9 b4 N" Q' h. x7 ~                vrc6.LoadState( p );5 ]1 [9 Q9 d: W1 N
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 w" T# d: J: A9 v
        }7 R& H0 \, o2 H) ^- a' z/ c
        // VRC7 (not support)1 m2 G, H8 F7 w) s4 |3 e$ D( }( E
        if( exsound_select & 0x02 ) {6 t6 q: P8 f8 |6 {  g
                vrc7.LoadState( p );
/ l2 H1 R( m  B, W6 y. n+ V; j                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
3 ]) K+ c7 d/ u3 L, ~        }& J; @. F% {/ n- M8 G* |8 l
        // FDS3 f4 |0 U: G, D
        if( exsound_select & 0x04 ) {) d" [, b. ~+ i& E3 C3 o* r6 f7 `
                fds.LoadState( p );- L$ k/ p9 B% ]8 B3 S
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
# k2 K$ b/ z) d0 @        }
$ x7 Q9 Y+ U4 ?7 `0 {/ J        // MMC5
# Y( i7 ~1 s; t! A6 Z3 ]1 E6 ]5 m3 h        if( exsound_select & 0x08 ) {7 Q! k5 ~, q$ {' t+ A
                mmc5.LoadState( p );
) x' ]' @* O1 A0 X' {                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding# |: p8 e  c8 G2 F( L( Q
        }( y$ e! o; P' P2 w7 ]( Z
        // N106
* L  y) s( ], }3 o  ^        if( exsound_select & 0x10 ) {
6 `8 a! y% x2 k, P. p, {                n106.LoadState( p );1 L6 q/ o, l* v8 z0 R' s; V
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 X: ?, O2 k5 U8 O/ l$ y- X
        }
1 l- t% a. U% g  {' ?( l        // FME7" o) D: U. U* N+ j# v" v
        if( exsound_select & 0x20 ) {7 [, s$ t4 u/ L% M$ r$ a; _
                fme7.LoadState( p );9 w6 t! J- T% D7 h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& z6 e4 C3 n" U        }
' ~* ?& I2 ~, y6 l# _" Y# O; @0 h}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 # H/ }" k3 E- r) u  V
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
+ }+ Q2 j0 |1 G1 q( z# Y; N感激不尽~~

  c0 A: n4 ^5 H. H恩 我對模擬器不是很有研究,
( }8 j, b1 z* X/ a8 n雖然要了解源碼內容,可能不是很困難,# T/ L/ e, G6 W% v
不過還是要花時間,個人目前蠻忙碌的。# }- R. g% a0 S- U( P

, T# S7 _- @2 x. Z) w2 j" I給你一個朋友的MSN,你可以跟他討論看看,
, p* L  f4 K; V4 z8 ]  D& ]他本身是程式設計師,也對FC模擬器很有興趣。
# }: y& Y  S8 ]: z2 h3 y
% @* ?0 _. |1 F6 b" W! B( dMSN我就PM到你的信箱了。/ @8 B1 H: f4 q

; A+ ]/ H+ A+ o* ^7 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 发表 ! S: S' a0 T2 `6 S+ H( s
呵…… 谢过团长大人~~

+ t! s) g; I: ?5 I% T3 w
+ f) G( j" o0 W  p6 T8 J哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 6 v- v  n+ |9 O3 |: L% {
团长的朋友都是神,那团长就是神的boss。

8 J: C! U- b5 B! Y# }& ]* T哈 不敢當,我只是個平凡人,& x0 N/ y) L. g/ e: w* r( E
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙1 i: m8 N2 w9 Z- O
ZYH4 p. H  x# j7 ~5 M' \! }9 z
QQ:414734306! I  F1 f, M: h- Q
Mail:zyh-01@126.com/ W0 r3 r+ L" k3 n) [- o* k

0 Z/ u  d% K9 V  l" l/ u他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
& t8 E' e+ |8 y- Q0 m4 _' ^- I( x再次对团长大人和悠悠哥的无私帮助表示感谢~~

2 K; n: U. O& v7 ], x, X1 w# R不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-2-7 11:26 , Processed in 1.128907 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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