EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。# S4 f" N: A( b. ]! W- R, t
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 N' ?# y+ Y( g
这里有相应的模拟器源码,就当送给大侠了~~% k1 l) D& M7 I, A/ s
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 + c" R: N% t3 |1 n: H/ B# g
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。* h5 |# A  W9 f& l5 L
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 X+ j7 V- x1 U4 b; u* y
这里有相应的模拟器源码,就当送给大侠 ...

/ G7 [+ f7 n0 H( [) F) M聲音部分(Audoi Process Unit = APU):. u* c# V7 ]3 a8 E1 q; B5 x( Z
.\NES\APU.cpp
0 D3 x  D2 s, m1 ^& @, g7 u2 M8 S  ?0 ~  q.\NES\APU.h
+ }& d+ I, J  ~& h" Q" p6 u6 M0 C2 [
3 i( J% f1 Y8 i; v+ h
影像處理部份(Picture Processing Unit = PPU):0 X% f" V- \  R( x6 ?
.\NES\PPU.cpp5 \* T5 {# z1 L! ~/ i
.\NES\PPU.h, |3 m+ i* _, K0 U& |* n
; o0 Q: D6 d! _) b1 Y1 W
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
/ _: B$ _" n6 Y7 f(由于很多专用术语和算法机理都不明白,所以看不大懂……)
& ]5 R: X% d: f% ^1 m/ w//////////////////////////////////////////////////////////////////////////" r6 L3 v8 [2 b
//                                                                      //
) u6 X( y" R, d, |4 X6 R. w//      NES APU core                                                    //9 D* m( U5 V# @5 L; f
//                                                           Norix      //
) z- I$ L/ F, E2 {+ |& R//                                               written     2002/06/27 //( L0 |; L+ d8 ?7 V  u# v
//                                               last modify ----/--/-- //; f0 N; _9 \# T! Y/ D4 A: Z" E
//////////////////////////////////////////////////////////////////////////3 a1 i3 k# G2 R0 l
#include "DebugOut.h"
, J- D+ Q0 [  ]6 l9 D#include "App.h"
" X  `8 i  B" T  p2 B#include "Config.h"/ t+ S- b# z4 K7 U& }4 @" G

3 z8 o$ r- V+ [9 |" L' x) z3 ^! i#include "nes.h"
/ a) p# A7 N( R6 I* e4 k' x#include "mmu.h"
- s5 ~4 y* \1 A$ P/ B' b" f#include "cpu.h"
4 A$ ^+ u4 P, O5 J) W8 C#include "ppu.h"
: C- J! J9 W- }- n9 G5 y#include "rom.h") O2 ?/ \; z5 Q1 o5 f1 ]
#include "apu.h"
$ p5 Z# b' I5 Y# `" s
% Z( P' F3 I" g) s2 g" d// Volume adjust
1 P" j: L  g" o3 N  s" L  {// Internal sounds6 q  n' \; ?7 ~' u! c( K
#define        RECTANGLE_VOL        (0x0F0)
2 k- \. ^6 _/ ~#define        TRIANGLE_VOL        (0x130)' W# D, b+ s/ u, }) t( K
#define        NOISE_VOL        (0x0C0)/ n5 Z5 j/ z8 J( ^  a( C
#define        DPCM_VOL        (0x0F0)0 p2 e' i2 {# [' H& ^: d) y( X
// Extra sounds/ U4 P! k5 Q7 e& G
#define        VRC6_VOL        (0x0F0): R; M5 g) B8 m: g7 |
#define        VRC7_VOL        (0x130)
# F; o0 u1 B0 o- D/ ]9 F0 a#define        FDS_VOL                (0x0F0)
$ _* N, ^1 y+ ]+ t#define        MMC5_VOL        (0x0F0)
* F8 x  m& t# l4 N2 Y. X- G#define        N106_VOL        (0x088)
+ ~' E" N' P; S6 q  g  W8 j! ]1 J#define        FME7_VOL        (0x130)1 J9 L+ x; {- W: q" w6 c

% A  W) C. \/ U% Z: DAPU::APU( NES* parent )
% e( A5 J  H% I# w, g. ~" A{
7 k$ k. }8 r1 c; @5 k6 X! `        exsound_select = 0;) B: w/ K9 y" M3 n
1 s6 F0 _4 i- m
        nes = parent;4 {* \! v' q9 _" t& ?( j" P" g
        internal.SetParent( parent );: u% ]2 n' z! t* f9 g

& ^9 z2 R  _* o% `: [' J1 h        last_data = last_diff = 0;+ [0 F+ K. q3 J! ~; g, p' V2 W
8 a. y. X( E- L' C
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );1 j4 Z2 s6 O0 [4 z7 S

" I: k- C' n1 W6 j        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
; P% `4 F- r! x" `: A# ]        ZEROMEMORY( &queue, sizeof(queue) );9 M8 N1 k3 E, Y" G9 T( m  ~: u
        ZEROMEMORY( &exqueue, sizeof(exqueue) );5 f" C* X6 ]- j
8 J; z( ^* Z9 O8 V0 n! H
        for( INT i = 0; i < 16; i++ ) {
6 Y/ l$ |. D. P' N/ [& a9 N                m_bMute = TRUE;+ D7 p0 ^" O  E" n! f2 c
        }. m/ X0 u. g2 ^$ ?+ a! n4 [9 {! J
}" y) q$ m4 b# r: p  ?0 Z3 Y/ y4 P. ]
$ ]+ ^# ]8 X* M/ A9 j
APU::~APU()
' q  l% J) {& u) ?% U{
3 R/ R+ V0 j) N% e6 N  R' V}% n# W" p5 g6 O! ]0 Y
/ c; ^( I9 g" G  f+ g& k# m% a. J
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
( o; h. @0 L, ^) P{
* I$ i( W: l# ]# z$ ~$ l0 V        queue.data[queue.wrptr].time = writetime;9 K5 d: \* ^  m2 _/ O& Y+ l/ o# t
        queue.data[queue.wrptr].addr = addr;9 V) t3 b+ C% N
        queue.data[queue.wrptr].data = data;
4 j- F$ B4 `# r2 V5 l* c/ ~        queue.wrptr++;
% Q! N7 j" _3 {3 R! t1 r1 v1 f( g        queue.wrptr&=QUEUE_LENGTH-1;; d6 N4 [3 y6 [* l4 |. O8 g
        if( queue.wrptr == queue.rdptr ) {
  v( f7 B: y3 L: K4 @. z* N# c                DEBUGOUT( "queue overflow.\n" );/ L$ z6 y# k: k% Q$ W5 t8 z
        }+ ^8 f( o/ O$ M7 S% q/ M
}9 E1 f+ Z0 d7 J. F7 k( F

2 K+ c( Z) j4 N7 Y" ~5 z+ GBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
+ z+ S7 i, o3 L' B* @{
" T3 N# m9 a+ J; f% l( M1 r# D        if( queue.wrptr == queue.rdptr ) {
, |+ x2 p- u& }6 F: ]                return        FALSE;4 p+ o. o5 m" j6 y! E
        }
% I; G! L) p9 S# P        if( queue.data[queue.rdptr].time <= writetime ) {/ K3 P; b9 ?& J- P/ y  N) y4 l
                ret = queue.data[queue.rdptr];7 c6 d3 X. G* \$ k. l" d5 Q
                queue.rdptr++;
& n3 v) a( n% t. C( U9 D                queue.rdptr&=QUEUE_LENGTH-1;, p9 H9 E! G5 ~9 n' d' J) y+ e; D% y
                return        TRUE;
6 c! z8 ~3 N3 F! q+ X        }
% u' o) _) |' G; \2 t$ f6 s        return        FALSE;* H0 K$ c' X9 w% O/ D
}" @0 g% z6 z1 L, o5 G

# @! q  X* x/ Y. j9 H# ^8 y  lvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )6 g' a% c$ p+ Q$ |
{$ T+ Y& X# j) ^# k8 O+ e) {
        exqueue.data[exqueue.wrptr].time = writetime;& w  J2 D# H0 u$ K$ M! ^" R
        exqueue.data[exqueue.wrptr].addr = addr;/ ?& b' i! F; f( G
        exqueue.data[exqueue.wrptr].data = data;
, ~0 N/ B$ P0 _/ T        exqueue.wrptr++;
. X$ B$ _5 ^- b: i# c        exqueue.wrptr&=QUEUE_LENGTH-1;
, v, U9 p0 b# Z% i; `0 w        if( exqueue.wrptr == exqueue.rdptr ) {
% S5 j4 Y4 R$ S; D# S9 u! Y                DEBUGOUT( "exqueue overflow.\n" );  Y2 g% G5 E9 @0 x
        }
; [' e! e& _6 ]. p}8 h& X5 P: y% f% b/ d+ \
  ]' X* m, t3 |$ f" `
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )2 k$ F1 H9 ^9 }" a; r0 s
{
& Z% L+ Q6 A8 y1 f        if( exqueue.wrptr == exqueue.rdptr ) {
' m" Z9 l" @. E8 |. Z' c: L7 [                return        FALSE;* w- m" I! W* ^) X9 [
        }; L8 l8 K: |( Z" [; A7 I
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {0 e- E) |3 }2 }9 r2 M% N
                ret = exqueue.data[exqueue.rdptr];8 i3 ?% R+ G, d. G0 W$ h
                exqueue.rdptr++;
9 B/ D; ^- ~, b! z& {* _                exqueue.rdptr&=QUEUE_LENGTH-1;
9 Q  X, ~' N$ `; E; E$ Y2 I1 Z( V                return        TRUE;1 \( y4 G+ R6 e; X7 H% I
        }! ^! M/ s/ n9 x+ H5 N' h& P* G0 d! k
        return        FALSE;
1 b! Q( n2 J5 K$ O; Y}
1 {! p" o3 B1 E* X& p( [# u- I0 Z5 s3 t
void        APU::QueueClear()
' w. C7 t) V: U* |( l{
8 Q0 }; r; T% ?" C2 t2 R# m        ZEROMEMORY( &queue, sizeof(queue) );
) N* @" t+ c- B& N! [3 m0 C9 N        ZEROMEMORY( &exqueue, sizeof(exqueue) );
1 W7 A& P- t1 n, ~/ i  q0 p5 ?}& B: O) G$ ~+ ?. I. i3 [2 L
8 j$ f! X  z$ _- s1 q/ l: B& ]
void        APU::QueueFlush()
& m% s: G- E: N{
- ]/ x/ o2 w5 N4 S5 y        while( queue.wrptr != queue.rdptr ) {
2 o5 m. {6 c3 }% g7 I" g: G                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );, z, Y& j& x; R$ M; F
                queue.rdptr++;6 H: X. `6 u# R/ m$ ?" v1 P  O. X
                queue.rdptr&=QUEUE_LENGTH-1;
+ w  C+ E+ s% K& O        }4 U) R- R* }& {" j7 K4 O5 T

  `9 {  h8 t. ^- `+ c        while( exqueue.wrptr != exqueue.rdptr ) {0 q7 @  X5 ]  O" E/ B! W
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );- X( n7 `! J- o5 b3 }) b. P; F% T
                exqueue.rdptr++;
/ A  ]  O  L. ?. [                exqueue.rdptr&=QUEUE_LENGTH-1;6 }! b9 W8 ?4 C1 C7 T6 K' B
        }
. U/ S9 O! i! e+ }( A: n}
8 j1 }3 S; ?9 W3 }: E. `! I5 @1 Q9 J7 `8 j  w+ v
void        APU::SoundSetup()9 J- H( ~9 x4 q% W6 b2 E, {: O
{
; i" y) g0 ?3 b) l        FLOAT        fClock = nes->nescfg->CpuClock;
  Z) S3 \. r! R$ @) ^        INT        nRate = (INT)Config.sound.nRate;+ P" c$ N% B5 F" a
        internal.Setup( fClock, nRate );9 T$ q+ ]) D% X( O% Y
        vrc6.Setup( fClock, nRate );
+ c* `5 h/ _5 ]" V        vrc7.Setup( fClock, nRate );( Y" f2 }6 e* e8 e9 x1 m# s2 \- r
        mmc5.Setup( fClock, nRate );
: E- o- Q2 w" x7 M& r* m        fds.Setup ( fClock, nRate );) X. \3 q% b$ E- f
        n106.Setup( fClock, nRate );
8 A# n2 U* S5 a$ m        fme7.Setup( fClock, nRate );% ^' A7 R1 j0 K; H
}
% `: A& \. ^8 |. y9 B# Z) f/ ]6 A
$ K1 f2 _) e1 `  |void        APU::Reset()
7 O5 ]8 g1 a" w{
; q( S4 \* m3 o' U4 `( ?. Q        ZEROMEMORY( &queue, sizeof(queue) );
9 M! r" U1 C# w; `' S        ZEROMEMORY( &exqueue, sizeof(exqueue) );% v! m) V1 U; u$ L4 X

* \2 E3 i+ K7 @9 a/ P. \# z9 \7 l        elapsed_time = 0;; j8 ~$ D& A8 x6 S8 n4 ?
. d, Z+ T6 n* @3 r# h
        FLOAT        fClock = nes->nescfg->CpuClock;3 T9 e* f. z" T/ w
        INT        nRate = (INT)Config.sound.nRate;
9 I$ b( d' S! ^, ]        internal.Reset( fClock, nRate );) ?" O$ W2 ?' g+ }
        vrc6.Reset( fClock, nRate );
6 V" J# M7 g1 n5 d7 d        vrc7.Reset( fClock, nRate );
) ~+ `: y' K* u9 _6 k        mmc5.Reset( fClock, nRate );
! {) O  ?) k9 I2 ?        fds.Reset ( fClock, nRate );- H2 ?& Y4 N) S4 \3 W+ Z
        n106.Reset( fClock, nRate );  ]3 n! {3 b! ?
        fme7.Reset( fClock, nRate );
; G- H% h% |$ a, f! U, S
7 V; D' I/ r# a- G' \+ i        SoundSetup();
: q: w" m. K+ V, g}, B2 C! {8 c8 Z$ `) x2 ^

9 `: ~* ?2 t, h" @void        APU::SelectExSound( BYTE data )
7 m& m. T: t  r2 H, H{
0 u1 \$ C+ Z3 |3 U7 |3 s8 g+ O        exsound_select = data;
3 I- N' O( |( v}
' U* I! K$ ~" Y+ P
6 m0 {. _( ~) {0 mBYTE        APU::Read( WORD addr )4 P% v. X' |7 Z
{
9 Y2 s7 L6 Y+ ?, V        return        internal.SyncRead( addr );
5 h, L* b) [) {, g}/ _0 a2 X( W0 `9 p( q* i
: K! o( S# U6 y' _6 V
void        APU::Write( WORD addr, BYTE data )- ?0 `$ L8 k# V
{5 w2 T) W. F' q5 h5 K/ t( B' k' b
        // $4018偼VirtuaNES屌桳億乕僩- M" S% F/ R% q4 y! t
        if( addr >= 0x4000 && addr <= 0x401F ) {$ [$ b: R: e8 H* e1 T$ z
                internal.SyncWrite( addr, data );
% L! u7 a3 Y8 B/ s0 N* j# `                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
) W9 q4 ~! r1 o! v, ?* ?% p        }
7 _# z( L, [7 Y- a}
7 O) c' X  R- M$ o* _- h. G& @7 U) ^! u4 A# L2 ~
BYTE        APU::ExRead( WORD addr )
# C+ O8 _" x" X; h{
+ v3 Q+ N: s6 H; `; J2 ^" v- J5 I6 @; wBYTE        data = 0;
3 k+ s6 k& H; o5 e& h! K! s5 F$ }. y# H# L$ i: a
        if( exsound_select & 0x10 ) {
& B# |5 P8 s+ {- J' Z8 M0 l                if( addr == 0x4800 ) {$ m% k$ o& f4 A5 N
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );, G# k% P5 U$ Z' q
                }. U7 F5 v8 i* q3 ]6 l* @! W( L; A8 m5 c
        }
8 c8 v" V  e& m6 N        if( exsound_select & 0x04 ) {
  x, @; i" x0 b# d5 A% [: n                if( addr >= 0x4040 && addr < 0x4100 ) {
9 q, Z9 g  J# N1 [. G                        data = fds.SyncRead( addr );0 t, p* ]  a( ~' a# ~5 {# f; t
                }; r" A  T$ l' H) |8 f
        }7 z. [5 e& `- m) f
        if( exsound_select & 0x08 ) {
& v0 N, Y3 n4 u1 z; a- H! u                if( addr >= 0x5000 && addr <= 0x5015 ) {  U4 x; _' d3 g2 s' p5 ?
                        data = mmc5.SyncRead( addr );$ U+ i' b! S8 [+ @
                }
" F7 N6 @  s6 l0 T: C        }. N6 I  ~5 Z  E

' H" ~/ R4 H) `4 R- v2 b: C        return        data;3 @0 P/ g2 j- X1 F7 ^! d- `) p; C
}
9 N, {% i+ {' d% w6 ]
" R& J# E( \, m6 J) ^void        APU::ExWrite( WORD addr, BYTE data )' o" F5 T. J" x) I6 ]+ o
{1 V" S1 z% e5 i( a+ {
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
. t9 F0 E; K$ L, C% O3 {6 i' k# R* \# I4 B$ Q
        if( exsound_select & 0x04 ) {
7 q  ?: b1 e4 r$ `! K8 S2 W9 q                if( addr >= 0x4040 && addr < 0x4100 ) {8 k2 |& {% f% G5 Q
                        fds.SyncWrite( addr, data );
0 I3 Z0 l- ?& \3 ~  O                }  h" Q. y) p" Z5 @0 A4 D, ]
        }
- F9 [' N' t! g0 V# k
% J* V5 p: d1 Z# R: l        if( exsound_select & 0x08 ) {
; ~( S. J: ~+ ^& z5 T                if( addr >= 0x5000 && addr <= 0x5015 ) {4 M) _9 |0 }# }$ P0 s' ?& S
                        mmc5.SyncWrite( addr, data );( x) \% N# ~8 u3 x. m) ?8 @
                }' z' r$ a- F9 |. x' J
        }
  {. X1 K9 o, n5 x+ K: {; ?! n* j}0 X/ E- Z7 [; H, V/ U7 t
. Y- {+ z" z. c6 N3 a- b  h% U- J
void        APU::Sync()
( c) E/ q+ ?5 T. p$ w9 m{+ I# P. E- ]  Y$ x1 ], o& N
}
) e; J  Z, k2 [
8 h! t: S) s+ Lvoid        APU::SyncDPCM( INT cycles )% p5 T" j% g4 V( J
{7 [1 U. D6 \! ?9 B# d2 i
        internal.Sync( cycles );
- e2 V& a% |3 e% _
" x/ e! \7 b3 N/ W) U' K        if( exsound_select & 0x04 ) {6 X$ w) O! @* n* }* |3 y4 \  \
                fds.Sync( cycles );2 \1 j% A& X( I9 I3 V/ a
        }
4 `: ?- p1 ~. n; j. l, J6 v        if( exsound_select & 0x08 ) {
) p: E0 K% _# J' z                mmc5.Sync( cycles );
. I" D  K6 s2 x8 ^, F: X* M        }
; i* L- p! T- T9 Q% k7 ]0 [}. d+ Q& h" J0 C& |  x% ~

, b7 Y1 N# S9 w3 Pvoid        APU::WriteProcess( WORD addr, BYTE data )7 B* M8 C9 C% i4 b; o$ z, C1 v
{
* f, I$ I9 w( Q1 e% X9 T5 X        // $4018偼VirtuaNES屌桳億乕僩% u! I4 \( z& c0 V/ W  n
        if( addr >= 0x4000 && addr <= 0x401F ) {
2 n" p% P) R9 x' C3 J4 X5 M- S6 B                internal.Write( addr, data );
& R# p& _3 K" L; @5 m1 n2 \        }3 o& v2 \* j) A0 B8 J
}
& O0 {, {+ |& j, ]4 B
" C6 R$ W7 ?+ I9 @# s6 R7 Pvoid        APU::WriteExProcess( WORD addr, BYTE data )
) d% t5 G# Q9 [: w- M1 x{
1 }2 Y2 G% j5 l) y! n: N7 K        if( exsound_select & 0x01 ) {
- {$ {8 r5 d* D" ~- U( E0 \. ^                vrc6.Write( addr, data );8 P( m0 Z6 n0 }; w! D8 o
        }' }; ?: @, b' y6 {9 m  H. b
        if( exsound_select & 0x02 ) {
5 k/ T/ l) p! S4 I$ q                vrc7.Write( addr, data );. J4 T1 A5 _4 R" Z5 g
        }: X; R) a9 ]0 \( X2 d0 K7 A& K
        if( exsound_select & 0x04 ) {
1 n& l* ?9 X" E. |8 y$ v                fds.Write( addr, data );/ f4 \6 L8 j2 w! y. R9 b
        }
- d8 l& |) X8 u1 _8 Z5 p7 c        if( exsound_select & 0x08 ) {
1 W0 J$ d; F3 M- O+ t% T3 X                mmc5.Write( addr, data );
0 p4 f8 ?6 E  D9 {& E* E# h        }
2 Q0 I2 g, ?8 p) T6 @% l        if( exsound_select & 0x10 ) {
* t6 P/ s5 F1 c: x. G8 T& K$ p                if( addr == 0x0000 ) {
8 c) M0 o3 X  B& O9 ^- C( ^                        BYTE        dummy = n106.Read( addr );1 m* P* i, \  m0 t: v
                } else {+ Z% e) L/ m5 [/ \% W: F' W/ \+ q9 \
                        n106.Write( addr, data );
1 r+ `! h! Y$ o0 a                }
7 Y0 r6 f, z% _# j* V# K. N) ~/ s; i        }
0 }) \3 _1 i" g$ W        if( exsound_select & 0x20 ) {# d" V3 v' A1 e$ S# f# ~" k
                fme7.Write( addr, data );8 Q2 `( W/ w, Y  _( `
        }/ O% r4 E8 [' C% N) z% r6 q
}
; ]: ^; r$ ]7 K. m1 ]( v% F( N5 y( i6 b# A2 T, `
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )# s# B, r+ l2 j- ]
{/ J! Z: ]$ _9 x  e" F6 c
INT        nBits = Config.sound.nBits;( X! W/ F( W7 o" _
DWORD        dwLength = dwSize / (nBits/8);
, y! w8 u6 L# ]INT        output;
0 e: F$ @, J- R7 y( ~5 AQUEUEDATA q;* o: R, q0 u$ E$ l' g- H, F. S
DWORD        writetime;' r) R) Y5 B6 r/ E8 X% P/ ^
) D# s$ O( B4 g& K' W" K7 o# o
LPSHORT        pSoundBuf = m_SoundBuffer;
) b2 J5 W# c4 T3 r/ E) RINT        nCcount = 0;# ~, `5 x% r& _+ T' ]& V
+ W* H. H: c/ b% ^
INT        nFilterType = Config.sound.nFilterType;
: C6 Y' `, a* D% T) X- N/ j5 d/ a7 A& g/ n; r) b7 O
        if( !Config.sound.bEnable ) {
- }# t# t1 H' [                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );9 L# v- @7 R: C
                return;" D4 P( x5 D8 r
        }
* \. T' k6 |( s' n1 F, B4 r
7 c! m* S0 V" f& S" g        // Volume setup! l4 _# Z" q3 Z3 h1 @1 {2 M9 D5 V: T
        //  0:Master
9 d6 a7 K, X! O. Y7 U& T' Y; u6 S        //  1:Rectangle 1" ~( h$ t' d' ?! Y3 }$ L
        //  2:Rectangle 2
. w3 G4 ?0 Q# d- E        //  3:Triangle" N# `. F8 W# t$ K
        //  4:Noise
$ W. J* D) ~2 G5 V' u) A7 n! a  A        //  5:DPCM; D( ^( Y- B0 T
        //  6:VRC6- q" I2 w, I5 ?( {/ a, ?: G
        //  7:VRC7! D, q8 H% W$ v! _7 }3 A
        //  8:FDS* y/ Q5 \# ^- G1 d  z
        //  9:MMC5/ o% g5 |. [/ ^& |7 [' l% J
        // 10:N106
6 R2 |/ r+ }! E0 ~' x% D        // 11:FME7
8 a; k8 z$ ?$ M        INT        vol[24];  u3 L4 X- M' f
        BOOL*        bMute = m_bMute;
+ l0 G& ~; R: z- D        SHORT*        nVolume = Config.sound.nVolume;
$ s& |- M7 z' P: o, i" @
, @7 F% N& ]0 Y2 j( K" ~8 h/ }        INT        nMasterVolume = bMute[0]?nVolume[0]:0;# k; {0 v" D4 G; M$ ^
$ a% Y3 H* M+ R. z0 d, H2 M
        // Internal" v0 Z# X3 G3 `9 y' G
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;3 l1 x$ i5 r9 E4 X* F% Z
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
! u6 ~7 g# T3 b/ f/ c  N" P        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;+ \% q+ u) p2 w  q: L
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;- T5 V+ Q# t% \# r* s& F
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& U! L0 r6 V* t$ D6 Z% D$ X( }) g
4 r% Y0 f! r3 ], l1 d
        // VRC6
$ ?2 \4 Z! p  Y        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;2 m$ _' r1 B2 F- n  c
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;9 ~- X4 g4 C! P0 F- e) J
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 k. T" A- a1 s, t6 |5 \$ C
$ [% Z1 M3 J! Y% T( ]& E        // VRC7
: o: K. Q( k* y% k% E" E6 H        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;2 G( U; S4 ^. [0 @3 ?* B
" |5 ?4 G2 F/ r
        // FDS2 d# t8 U/ V4 D% _+ Y! f, N2 Q) i
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;# |7 K7 F5 b0 J: q" K8 w

( A" \) r6 P4 E, U: Z0 A# k- B        // MMC5
  a+ z; \; o. @        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% i/ N- }1 K0 L& v' t1 S" M        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 S) E- G0 h1 V1 c. p$ K        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
# g% \7 a6 H. z0 c' }5 k
: q8 G. b$ B1 m* N0 E        // N106
& [# P% s( M- F1 t7 Z' ?- I  L3 I        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 l% T% c. S) w/ k) @1 h/ v        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" p5 C8 C5 k" r6 s% |        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;2 Z' U* ]- v0 p+ B% ~
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; y, P6 ^/ p9 e9 R
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;( X4 ^6 B; R; `% X6 W
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 `0 X+ B$ @9 f, m  t        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! h9 ]/ b7 ~* w7 N
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ l  l! b# e: K2 A" e

  T. m/ c) r  ~% A0 N, R7 \        // FME7
! L' ]9 G8 I. T  _, i        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;9 W1 _8 m, x- `* z
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 D; n4 r+ I$ A* v# O: _9 ~        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;" S( ]9 e+ d1 D' I5 @8 f# `5 Q
5 ^7 L. U3 P! v$ d
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;( G  e' `6 o# X
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;1 M/ Z- r8 Y6 Q. U
9 r' l2 P, f2 Q; P/ o' S4 q
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟, b8 V* T) b) {8 Y( X7 X+ U
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
0 R+ b- x  P/ B9 c                QueueFlush();
2 B4 f  `# m2 f( e& X, x+ H9 E        }
/ \+ y% S9 ~+ m. O% W2 d# n# [6 _4 C7 o# a
        while( dwLength-- ) {3 W7 Y* @( t7 f- f" M1 h- O! S% ~6 T
                writetime = (DWORD)elapsed_time;
1 D2 o5 U$ F: m, Y2 I) c+ M! \- e: b, R6 B
                while( GetQueue( writetime, q ) ) {$ }" J# Z2 }2 X# s" Z- u
                        WriteProcess( q.addr, q.data );1 a' k9 l  H: W! ]/ S! Q8 P5 k
                }2 ?9 ?% g/ i7 p% `$ L0 m% V
3 O5 [/ m' c1 J- o' x  {
                while( GetExQueue( writetime, q ) ) {
2 B/ _4 }, B: P% g. M; K8 P+ L                        WriteExProcess( q.addr, q.data );6 Q9 ^" L( B: m6 g
                }
+ ?; N6 ~* g$ B
0 ?( C* F0 _; v# \( m1 H( T  Z" j                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
! D# ?  V# j5 ]4 L4 y                output = 0;3 f+ R) F! A$ z5 k& E/ [5 F6 x. T
                output += internal.Process( 0 )*vol[0];
/ D3 |; d$ V3 J                output += internal.Process( 1 )*vol[1];) Q( ^/ N# O7 ^# `' n( M/ y
                output += internal.Process( 2 )*vol[2];2 ^- F+ i* U4 Q- ~) y
                output += internal.Process( 3 )*vol[3];: ^$ h! |# I: f/ w; i5 Q
                output += internal.Process( 4 )*vol[4];4 l- }4 f: N, E$ x6 U6 ?1 P' Y

7 i. L7 p/ D5 V, H5 c: _0 D- c                if( exsound_select & 0x01 ) {
, X' N8 R# f8 G, `7 D                        output += vrc6.Process( 0 )*vol[5];- ~9 g; [1 `5 R& |- q
                        output += vrc6.Process( 1 )*vol[6];
1 V6 _9 w# N; T( s" m7 S                        output += vrc6.Process( 2 )*vol[7];
5 j7 e" x  U9 o, B0 |; o0 q1 T                }
( p) f* q+ w1 [3 i* q                if( exsound_select & 0x02 ) {
- Y  W; `+ J6 X/ g: J5 ?# Z                        output += vrc7.Process( 0 )*vol[8];6 L$ ^# i* ?; G
                }/ j$ i; ~' f9 V- y
                if( exsound_select & 0x04 ) {3 U- F. J( u* W+ t" L
                        output += fds.Process( 0 )*vol[9];
7 x, R' f) C8 u' ^7 `                }$ D- u6 E: \6 W- F
                if( exsound_select & 0x08 ) {
* A9 y' w" Z) f  q  H& Y' t" e. w                        output += mmc5.Process( 0 )*vol[10];
& U3 W$ \2 a% r                        output += mmc5.Process( 1 )*vol[11];
$ Y+ o7 h" a. s& L' G                        output += mmc5.Process( 2 )*vol[12];
7 \4 }  I8 Q. J7 Q3 y! f                }
- {7 j; ?8 l) u5 R5 Q, n6 x                if( exsound_select & 0x10 ) {7 |; s! T8 b9 Z
                        output += n106.Process( 0 )*vol[13];
! O5 O7 a# M# c                        output += n106.Process( 1 )*vol[14];% c5 ~/ ]2 t: r% L! d
                        output += n106.Process( 2 )*vol[15];
$ ~. a) q, A: W* r# B. ^                        output += n106.Process( 3 )*vol[16];. C+ E/ e" w2 V7 K2 \* s
                        output += n106.Process( 4 )*vol[17];
$ g! }$ ~" v" k) S                        output += n106.Process( 5 )*vol[18];
- {; A. N( B! j' C" H                        output += n106.Process( 6 )*vol[19];
  L# L5 e2 k- [* [                        output += n106.Process( 7 )*vol[20];
2 P* l3 k3 a( t$ P                }4 s7 G, J6 i; g) i3 ?" @" q, K2 z
                if( exsound_select & 0x20 ) {
$ o; |8 q+ s2 F1 Q                        fme7.Process( 3 );        // Envelope & Noise
) ?6 Q! t0 V6 }8 D+ K; R) {                        output += fme7.Process( 0 )*vol[21];
! O* Z2 T- ~7 ?. z) g2 ?$ X3 ]: A% G                        output += fme7.Process( 1 )*vol[22];' j2 }: \# V* u/ y; \, J
                        output += fme7.Process( 2 )*vol[23];
$ Y8 c. H) f' o% u0 M                }0 V8 m! h# a2 a8 Y

1 ~4 Q9 g* r7 |: k' C                output >>= 8;
8 V* K1 ~1 ]7 }5 W% ?
; K6 A. z4 G! w( K6 X! `0 y                if( nFilterType == 1 ) {# T& k: B8 @" F, C' {
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
! S, r" K* @* L- t1 Y, r1 k- y' X                        output = (lowpass_filter[0]+output)/2;
/ u: E6 B3 J( \) G9 x' I6 L2 [                        lowpass_filter[0] = output;
2 p: T9 Y( p1 H8 S( \0 b7 U( h                } else if( nFilterType == 2 ) {" _' ^, S/ m$ Y6 x  z
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
/ v4 G+ |8 x; e& R+ H                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;/ R  V9 L, B3 c5 S' r0 r
                        lowpass_filter[1] = lowpass_filter[0];
$ l5 V6 E4 b5 Z  G3 P" q                        lowpass_filter[0] = output;
' Z& J5 ^+ n( Q% e                } else if( nFilterType == 3 ) {
  p. G/ b$ A0 @$ G0 X; W9 q                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)% r) m8 p, Z# N4 x
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;7 e! L0 S  F* {- x
                        lowpass_filter[2] = lowpass_filter[1];
, f  U, h- V0 {                        lowpass_filter[1] = lowpass_filter[0];
$ N; V3 {2 n1 R2 F% o5 N$ T) C3 O% B                        lowpass_filter[0] = output;4 f9 u) `2 c3 `# q8 U; S
                } else if( nFilterType == 4 ) {
& E; A# \/ k; q) S, W8 P& z                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
5 n& Z% b& ]8 X1 u9 |: k                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;6 H( M4 E5 ?8 R0 s: I' k( l: w
                        lowpass_filter[1] = lowpass_filter[0];
* |  v5 M. z: Y                        lowpass_filter[0] = output;
8 m* V/ n, P% v                }
4 \" A9 j6 w* t+ a
6 {6 z5 a* e% W0 f- \+ l7 N) g#if        0, V+ G+ ^) j) s* i5 w8 x* h
                // DC惉暘偺僇僢僩# U" y. ^) W6 \; b
                {. H/ p& H$ M) U) R: L# j; g$ J$ m
                static double ave = 0.0, max=0.0, min=0.0;% ^3 a/ @$ t! L) ]) i1 Y& i
                double delta;# Q. e/ I4 G$ o  o, T* R
                delta = (max-min)/32768.0;! J" v9 N4 j) V6 H: c1 J9 \: j1 q
                max -= delta;
& t9 u9 J  H! G% T; r5 |5 c                min += delta;
- Y* u# N2 X( b  q6 g. @& r0 U                if( output > max ) max = output;
" A) A8 ]& K1 c7 q0 c                if( output < min ) min = output;% G: L7 U0 n  n1 h5 }" X  O! ?
                ave -= ave/1024.0;
. G6 ^3 U5 x& d) }- `2 Y                ave += (max+min)/2048.0;
% Z; t4 N* z) x9 D8 j+ ?                output -= (INT)ave;8 _" ^6 c* ]! n; C" M
                }
3 _& N* g! E9 ^% j' r; k#endif/ c$ G% t4 H% j# `( a! s
#if        1; `0 c6 O9 ?/ a0 w* A
                // DC惉暘偺僇僢僩(HPF TEST)+ y. u; |# F- [3 ?( D7 g/ B
                {
' Z; b; ]: z% F% _7 p  q//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);! H5 g9 Q7 A& g# Z5 z
                static        double        cutofftemp = (2.0*3.141592653579*40.0);# Y; {& e; Z3 r9 A& @, Q5 G/ I
                double        cutoff = cutofftemp/(double)Config.sound.nRate;0 n$ p) _% |8 a+ {
                static        double        tmp = 0.0;+ {0 |. C2 B( p5 \
                double        in, out;
7 M  x* C, w  p# e* g/ d7 o8 R; K( c  W! U. n0 P6 m
                in = (double)output;
4 M  ?) N+ d) y5 V                out = (in - tmp);% m3 `( t' B; H+ ?4 Q# B$ K! X
                tmp = tmp + cutoff * out;
% s6 T0 r# u1 q. R# @, S! F' K3 p
                output = (INT)out;
5 E) T* o/ K9 m' o                }
' t, \6 w9 i+ `& \: X, ]! y8 ]#endif2 U, R9 N* l3 ]  M3 h
#if        06 z2 d, }. H9 H' n3 D
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
, P' @! T* n8 f                {
7 \8 p3 D  L& i) n% J8 u2 t4 Z                INT        diff = abs(output-last_data);
! r' K7 `6 {, p                if( diff > 0x4000 ) {
- ~0 x8 R( T& A& P5 e                        output /= 4;" t+ u. c9 `2 H$ k5 O
                } else - i1 ~# j6 |" }1 B% D
                if( diff > 0x3000 ) {
' I8 ~, j+ Z1 o                        output /= 3;) p3 I1 B; T" i5 Z  _
                } else
' e2 u( v( D# ~) G                if( diff > 0x2000 ) {
- h* U3 }- D& o) K0 g                        output /= 2;9 E. M3 U  C  }; t. \% \
                }
& L/ H/ Q7 ^* Q% V1 V: L/ _                last_data = output;2 I# T' k$ Z, O; a0 W( s
                }
) I0 r, L! _: Y, A1 U, Y#endif
1 p9 Q2 b1 t& p" i                // Limit
+ E- U. r5 o( c( p' F                if( output > 0x7FFF ) {* x' R; S0 M: D9 ~4 e
                        output = 0x7FFF;3 A) a6 b* q& F% x7 [" C, b. G
                } else if( output < -0x8000 ) {: z1 }0 e& n! v: D% v6 E- }6 g
                        output = -0x8000;3 e0 |0 b1 D0 C: _1 Z% N3 R
                }
. V. w% l7 n2 t% R2 f* y5 Y( N
9 a8 p! W" K% M7 i3 }                if( nBits != 8 ) {
4 J3 X5 q/ R+ W$ {% p; X                        *(SHORT*)lpBuffer = (SHORT)output;" t  a. p& i3 b0 l9 W+ q- @
                        lpBuffer += sizeof(SHORT);/ |3 q6 b8 t- n1 K. y
                } else {! c' ^7 N- r) N0 k4 d: s! M/ z
                        *lpBuffer++ = (output>>8)^0x80;5 L8 {/ u& |1 i. F
                }* l) G. K- C" M4 h
( y+ k4 ?! t) v5 A
                if( nCcount < 0x0100 )
9 \5 O! E4 O7 S$ ~$ e                        pSoundBuf[nCcount++] = (SHORT)output;- `- n- F7 i) `5 S- ]6 c# Z7 N" V
* ]4 l: X( w5 Y/ v0 T$ r* q- E$ G
//                elapsedtime += cycle_rate;+ L: w' G7 T  Y3 d0 l7 N8 f
                elapsed_time += cycle_rate;9 X, o. N! |" N% \: i
        }; m) _; c9 F' M  O& x8 z
; l8 J6 X0 g: v  k6 L* ~* u
#if        1; i) V" h8 Y! w# {' H
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
" C- J) ?. e0 _, M  x                elapsed_time = nes->cpu->GetTotalCycles();' O3 J2 g3 f& S3 |, n( Y
        }$ Y+ \9 r* t! g  g  D
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
( W, |1 M# {' o7 i3 _) T1 t                elapsed_time = nes->cpu->GetTotalCycles();, J' H. Y  w6 o5 u* }* u* B4 c
        }
, a* Y3 ^* N0 b. `6 w# y9 a#else
. P- A! i! n, {" t1 ~        elapsed_time = nes->cpu->GetTotalCycles();! T& [: S9 L8 B# A& k  a
#endif' n$ _0 Y* F  [7 a$ d
}
% }! R* [2 C( [3 X
( a7 A5 ^) \/ C- g// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
4 P. n' b6 e, e# @INT        APU::GetChannelFrequency( INT no )3 b8 k5 c3 _3 J& Z* I! w" P
{7 T% z( {, A/ T. ?( I% y
        if( !m_bMute[0] )$ g; h. e+ P' x9 o, q2 e8 |. I' [' d* Y
                return        0;0 z; u" \6 v. V

, j, ?  _7 T# i( }4 e  n3 i+ m: F        // Internal9 F, e$ d4 E& c8 S+ Q
        if( no < 5 ) {  ?1 c* ^6 r' M2 q9 i8 ?( B  X
                return        m_bMute[no+1]?internal.GetFreq( no ):0;' N5 g/ b  @9 D& |" @
        }
' B6 \4 r4 M/ Y( w- o* {        // VRC65 K5 E% u3 {3 D" r
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
7 E+ g8 A8 R7 m- H) R; g1 I" W                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;+ m: V+ I# F5 K/ j7 q/ L3 g# B/ r
        }! H: z) z5 Y- n& R
        // FDS
& @5 N" g$ v0 K, f$ Z2 Y! I        if( (exsound_select & 0x04) && no == 0x300 ) {. \; u9 x1 D$ o2 `
                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 u" R& j8 g2 s/ c
        }& T! V  o& e4 _' k0 U9 o* A, z
        // MMC5; F; m" z$ E, X5 C/ `9 U1 h
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
: E) b, `1 u2 o4 T/ X                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
! Y: ~8 C- @  t. j% n        }/ |/ d' ~5 {/ c9 Y, E; z: j
        // N106
4 j8 b, i8 j5 Y, H) [, m        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
0 `, J- g) \7 `, e- f4 @- p                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
8 D5 s1 E7 n) W5 T# I/ b- a        }" U" c; S# z" E1 P
        // FME70 j! \8 z7 J/ d9 {
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
" W7 p; R# g9 j( o9 N                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;- R% D3 Z& J! ^: u: o6 u
        }3 f8 Q& T& v2 e! l. v( j) `7 ~: l2 F1 m, U
        // VRC7
: n# H& h& S2 M) m8 T5 B* I' T: p        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
0 [* [5 i; T$ |; S                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
0 g, Z6 L" r, }! R9 E4 L5 M        }3 e  B# s- k  T( S: v4 _" ]6 Q
        return        0;
+ I7 v; W4 T) X) p1 M}
* T: k5 m& h  B5 g) m  x  K$ B1 p3 I& h% `% t0 K
// State Save/Load
& _6 v% @' o3 g9 Tvoid        APU::SaveState( LPBYTE p )# K9 c0 v$ I; x) e: M6 ~
{
& v1 `9 Q' l0 t6 j: U( {#ifdef        _DEBUG5 K7 v: P+ ~6 I: u# ~; u0 s3 d; B
LPBYTE        pold = p;. q7 q9 d# \; p% ^7 F, @
#endif8 I% z  o* o5 q4 @! S4 W' L

* y) K$ @( B# Y! A* W  Z% u( A8 e        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
& o9 P! U4 y# }7 N4 m        QueueFlush();
! n2 E5 T& ~/ m/ ]& g
: L) T3 Y8 ~6 F        internal.SaveState( p );, n' {4 a; @' T! T
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
8 W2 s9 W9 I) ?" J) O* Z) Z" x6 P. v: E+ C# h
        // VRC6
$ I+ `0 p' F- u. u0 M        if( exsound_select & 0x01 ) {
$ l5 A: d3 f: c  e1 D5 ]                vrc6.SaveState( p );
3 O: I% J! D/ b+ u+ {1 v! V                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding7 W4 d' n7 X/ J# K& t2 n
        }
3 o* R& c0 L% O% K7 i4 W        // VRC7 (not support)
, t2 Q# q6 b2 V, u: ~/ W/ w        if( exsound_select & 0x02 ) {' C  V4 F/ B3 E+ e0 @, `
                vrc7.SaveState( p );5 s& f( V- r7 E/ F* P
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
, ~! {! l9 w9 o9 c# h# i        }
+ d& H8 r8 X' \4 r6 x        // FDS4 F* h. i  f. l
        if( exsound_select & 0x04 ) {( f5 p" T* l% K/ R" V
                fds.SaveState( p );
7 F; u7 f0 u  Z6 M4 E5 I0 b! b                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 u0 ^8 d% u, r$ E1 V7 `5 O& b7 S        }7 v7 \6 m! K- F$ I5 K
        // MMC5
8 ^7 _! e( {; E( i* u& f7 J0 [        if( exsound_select & 0x08 ) {! O5 }9 b- g6 m9 P. k3 y/ o
                mmc5.SaveState( p );
# u* |& W; P' z- y  i/ _; n- |                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
( @& T, q% N0 T3 t+ V        }
0 A, e& `( _1 \! t: {  `( b% e4 ]        // N1063 j( J/ \7 A6 }' w% |* K
        if( exsound_select & 0x10 ) {
, T+ N  ~9 T  P9 t: U                n106.SaveState( p );
3 q/ m( ^* U& X                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( \& o+ M3 m/ u: T& a
        }
- y" [/ |, x: h6 o6 c( P) z        // FME7
$ y8 r( a5 T5 |& H$ M2 ?- r% p; v        if( exsound_select & 0x20 ) {
! B$ K' D' X/ S- V' x                fme7.SaveState( p );
0 {2 J8 m  r# D' `8 b! [' t                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: W. R8 z1 L! I        }
: K' _$ U+ F. d- t! I: ~6 ]
, k0 J! P/ U$ ~" b% E6 N, w#ifdef        _DEBUG
2 E- t! ]+ m/ c! ~6 n: f! CDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );6 C3 }" C+ d5 b% h$ n
#endif
9 g3 a3 F; C/ {& @, Q+ Z}
, P: [3 ?; W% ~) y, n. i+ t7 S  u. n- }
void        APU::LoadState( LPBYTE p )- z) R4 R- P& d# H, Y$ \
{
$ l* x2 l) o0 n6 s2 h        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
! h- @1 l! @+ M" D        QueueClear();9 z8 j( i1 R  V8 O3 c! s5 S
3 V! T8 t6 J# d6 e
        internal.LoadState( p );9 _7 V" l8 C7 u
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! w4 Z9 i1 |! B) W* N9 J6 o
5 ]' d$ e3 V3 l9 N
        // VRC6' `* q2 O6 m% z! ^1 ]. |2 n
        if( exsound_select & 0x01 ) {8 B, E3 I" M" H: z, j6 e
                vrc6.LoadState( p );
% l4 V. |9 J! u                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding2 `7 k0 {+ Y( X; J$ s
        }' _% X# j; A+ O5 P0 c4 S
        // VRC7 (not support)$ B  `; k2 d0 O6 x9 O, _. b
        if( exsound_select & 0x02 ) {
% q1 G3 {; w/ w$ f/ O8 s$ D% ^                vrc7.LoadState( p );, ]& p  \* `1 x$ \2 }1 e
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
% F$ u9 D7 v6 `. N) B7 S        }+ s$ d2 [" F( ^# G9 ^+ |0 F5 s: ^9 e
        // FDS
. w) F* a2 C& x. L7 o        if( exsound_select & 0x04 ) {
% O! ?3 Z( @% P( k                fds.LoadState( p );' L* g' n& t: S+ r/ Q4 H1 E
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
' x1 F  o4 w- @0 A  g        }; ?6 X" u0 g  n4 C
        // MMC5, D4 L7 o) E, X4 L& ]+ x+ r+ F3 ]. }
        if( exsound_select & 0x08 ) {
/ }3 z  I/ s+ q8 ?                mmc5.LoadState( p );  i/ M: c( O9 r! h  u
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding5 |1 k5 H7 a- y5 Z/ b
        }
! W1 V% U+ e) p# V% r2 _        // N106) ^( d: w1 O) A  N, ]( a5 g$ P$ I
        if( exsound_select & 0x10 ) {
% a0 F7 s+ w. g% ]( j                n106.LoadState( p );
( _+ b1 c+ n4 Y' o7 A% Q                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* b6 {+ }! m* L2 W9 v9 Y
        }
2 p9 J7 S0 o6 J% C        // FME7! t7 _3 X) v1 w6 Y) j
        if( exsound_select & 0x20 ) {3 P5 e, w* T" ]* f* m7 u
                fme7.LoadState( p );
0 H# q2 P: n* H                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 v5 O0 `# M: }0 a  F( e        }. L' V2 u8 u6 K
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 6 v& D7 T3 U1 t: _
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
7 E" e. U  B5 h6 F( g感激不尽~~
/ h# b( o0 n2 _1 s
恩 我對模擬器不是很有研究,
1 x- t9 u$ b' x雖然要了解源碼內容,可能不是很困難,% X( l8 J1 \  X# T8 g
不過還是要花時間,個人目前蠻忙碌的。: d6 A, T7 N* N8 f; O; ~$ ], w

+ s- W9 @  Y) ^. z給你一個朋友的MSN,你可以跟他討論看看,
2 X- E5 g# m% O( h+ Z% b, {2 {7 m他本身是程式設計師,也對FC模擬器很有興趣。
# w6 k: T0 C: O+ d: v' A. G- y' G0 G% \% ?$ Q" G
MSN我就PM到你的信箱了。8 h$ l: t+ S* N. S2 B2 c5 m* x* n

% H8 T0 V9 L& [* K( F3 R& q' Q希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
- L. C( X* }/ x1 h4 g呵…… 谢过团长大人~~

- A1 m/ H1 j' z& u& j
- G& U4 ^' [5 m% C* f" S哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + h5 |, ?. h; B# q& l+ i- X4 N0 f. c
团长的朋友都是神,那团长就是神的boss。

6 t9 ?9 d. J6 u: [4 {) ^5 ]; x9 W4 R6 p哈 不敢當,我只是個平凡人,' H3 _" f7 G& `( K8 M: T2 |
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙: \) b+ y: g- H& h; T0 Z: Y
ZYH
" |* a. E8 ?5 WQQ:414734306
* w- M3 ?4 D1 V2 R; dMail:zyh-01@126.com5 m7 r: ^1 x+ U4 F# r, m2 s7 A
% z7 S3 b, c# D" U
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
/ S9 r$ G4 _) X5 Q再次对团长大人和悠悠哥的无私帮助表示感谢~~

6 m% }/ N8 O7 z* Y# M  @不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-11 18:17 , Processed in 1.072265 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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