EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。& E3 m$ @- e! `2 J
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
  _8 h- \2 o: X* N' }7 u, \这里有相应的模拟器源码,就当送给大侠了~~! l+ \# B; b0 A2 K
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 " P0 a9 ?& j9 G* `7 N. X3 d
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; s. b3 l$ Z% M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 P3 A' n  Y; v  ~( w3 r. S这里有相应的模拟器源码,就当送给大侠 ...

4 [3 W( o8 _5 n$ D2 T( a: `聲音部分(Audoi Process Unit = APU):
  c3 D6 Q. r! ~8 k- m) m! B+ g6 d& A.\NES\APU.cpp
% J$ I) ]/ z' |+ z' B/ n/ }8 k3 V1 M.\NES\APU.h0 U) E- U# b! ]- T# U, Q
% J, o; m4 A" F5 Q4 E
2 E5 O: N4 a4 l5 w( h+ {# y- Z
影像處理部份(Picture Processing Unit = PPU):
3 f& l" e; P3 H) k3 g.\NES\PPU.cpp. P& L% V" L" j& r: T: k
.\NES\PPU.h
3 c2 s3 O7 ]( o; Y0 F! D% Z' @# R) y% `3 }
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:& ^5 x/ h" I0 H3 k' ~" h
(由于很多专用术语和算法机理都不明白,所以看不大懂……): @& L, J6 v1 p+ P- f
//////////////////////////////////////////////////////////////////////////+ S3 l/ D9 k( n
//                                                                      //; c5 ~+ ~4 m' B* u- ~4 k1 o
//      NES APU core                                                    //; c- o1 Q% A% Z1 W- Q
//                                                           Norix      //
3 y7 `. a0 z/ V/ S' |//                                               written     2002/06/27 //
6 L/ ^; H8 _8 |1 D7 v& \" z' q//                                               last modify ----/--/-- //- C, h7 P  p: p9 A
//////////////////////////////////////////////////////////////////////////3 J. K4 X1 v" z4 p; ]2 E, A! o
#include "DebugOut.h"
' f9 O. p- n3 F% c! K#include "App.h"8 d4 e* x4 b: s0 a% B
#include "Config.h"
9 N% R" O( N$ h3 z) n
! [& I$ c  P. w0 B4 \9 q' k#include "nes.h"
' z+ |- i' y. G' {/ I$ A5 w#include "mmu.h"" [8 t' F3 [6 `; f& h+ `- X
#include "cpu.h"
7 q3 I- t2 T5 `4 Q1 r( D3 }' C: B#include "ppu.h"
$ t2 i" x$ z$ e# e: O  ^4 k  C" A4 X/ Z#include "rom.h"
2 W" R# H+ T/ }#include "apu.h": \& b; ]6 Q, G5 h/ o2 r1 K
. t: `$ A6 B$ w. O
// Volume adjust  A5 `" O* W; k
// Internal sounds
" S3 }" y  A9 K8 O( a( E#define        RECTANGLE_VOL        (0x0F0)! W- @% S- l4 @5 d4 K% w/ H
#define        TRIANGLE_VOL        (0x130)
4 e  e& M0 j5 r4 j" S3 K. E#define        NOISE_VOL        (0x0C0)$ ^( U$ x, M$ K& ?- C' E0 Z3 [
#define        DPCM_VOL        (0x0F0)
# f- a1 h8 {7 I4 A4 s. \* h% s// Extra sounds, l/ \& l+ q5 `9 @2 R
#define        VRC6_VOL        (0x0F0)
% ?9 F2 F* }: J; x/ E3 q! }#define        VRC7_VOL        (0x130)
' {8 v; l' v! e8 j" o) X/ I. G#define        FDS_VOL                (0x0F0)! F7 ?9 U, K- ]: U( b: u3 T1 \
#define        MMC5_VOL        (0x0F0)) X/ h6 `% s/ k6 t
#define        N106_VOL        (0x088)
5 T4 W) p. Q! f9 `#define        FME7_VOL        (0x130)
( W0 E5 V9 E3 q5 ~. M# S. s+ k0 m4 Q; Z
APU::APU( NES* parent )0 }! V! ?% Z5 v) g# _, l
{
, u- x8 u# v7 _        exsound_select = 0;
8 C+ [% ~. ?& W/ k. ~: ?6 U. y
! s1 m# @4 H; L. d2 ]3 v        nes = parent;5 o% m. V2 k# g) H
        internal.SetParent( parent );( |& N# D4 K6 y/ h* ?3 u/ N
9 |4 h+ C- L: g2 A+ P! r
        last_data = last_diff = 0;1 i8 H2 Q' x6 U$ d
9 K  U1 B: ?8 k. W' S
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );+ d- z) A/ X5 }. Y0 o
1 B6 U# C$ P, M. \2 `" D
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );" l( ^. l1 ~5 S
        ZEROMEMORY( &queue, sizeof(queue) );2 Y4 o9 q$ ^, `% b5 [
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
! H9 u- {' X" A+ S3 `2 @; Q+ f1 F. M- r9 X6 Y) v
        for( INT i = 0; i < 16; i++ ) {
/ }$ ]& c" g6 v" C' m2 F; i2 H                m_bMute = TRUE;
6 }" g$ U' e) s) P& Q        }
* w& b& P/ I/ [}$ ]0 w% F! r, t2 {2 D! f

8 g& }$ n1 }3 ?, GAPU::~APU()/ S7 w. F! s* ~, O2 U
{
( F$ ]* b+ g/ X  z- D  X( D}
- O/ r. @& l" ?7 s9 R# [5 w, A/ c( u; m' x0 w
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )- c- M5 L' c7 t
{5 a( p0 G; d. a/ q  c$ b
        queue.data[queue.wrptr].time = writetime;7 H- @; r( b! K# k0 ?! o( i: x
        queue.data[queue.wrptr].addr = addr;$ c. V2 j  M, z+ H% j/ [) ^
        queue.data[queue.wrptr].data = data;
1 ~7 J/ j. s7 Y        queue.wrptr++;
5 d+ y' w+ E0 k/ k8 R* v6 Z        queue.wrptr&=QUEUE_LENGTH-1;  h6 X1 q  v% r4 G; _/ ?8 K6 }
        if( queue.wrptr == queue.rdptr ) {/ F7 I$ m5 h: }% J4 v$ b
                DEBUGOUT( "queue overflow.\n" );
" d: p/ `9 z0 H7 A4 x% T8 o, R        }
3 c9 }( `( B0 `}, p* _0 y  S8 P# R0 v
) x. a; ]2 J, `+ f0 x
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ H  I2 m' }, ~" i  B  n" M. K5 P+ `
{
( ]* p$ o, Z4 \( I        if( queue.wrptr == queue.rdptr ) {
% ~3 U; R) P5 D# ]- P                return        FALSE;) v; B+ E0 Q0 o
        }
* T8 q/ g. c% p% N8 E& T$ B, ^$ T        if( queue.data[queue.rdptr].time <= writetime ) {5 Q7 c; J( |  s1 s7 A
                ret = queue.data[queue.rdptr];# n. G# i$ Q' I  ]
                queue.rdptr++;6 N$ n% s+ r$ {9 V6 X
                queue.rdptr&=QUEUE_LENGTH-1;
0 q2 G0 L& h% C; b3 H                return        TRUE;. z, p7 p  A5 x; }6 q
        }
5 t5 _" N- [& Y& {, h' L        return        FALSE;
, \0 B; T: B4 `}- n# W, j' \8 o7 u8 M) q: z

' {7 [+ C" h7 Yvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )5 T+ M& S7 {! D5 F. [7 s
{
; h6 R3 p6 o( Y  i6 ~  W: |4 p        exqueue.data[exqueue.wrptr].time = writetime;+ e& Z, @9 z; x! f8 [5 ^4 T7 c4 C, T
        exqueue.data[exqueue.wrptr].addr = addr;# |; Q+ d+ s1 F* j
        exqueue.data[exqueue.wrptr].data = data;
: X2 b: F) J$ o1 ?1 L        exqueue.wrptr++;; `5 ]! o# w" n* p' \, v. \$ o+ V
        exqueue.wrptr&=QUEUE_LENGTH-1;# c- r* D5 {' R* |; ?0 S
        if( exqueue.wrptr == exqueue.rdptr ) {- G4 d: m: ]- X
                DEBUGOUT( "exqueue overflow.\n" );
0 m6 ^( O) w+ L8 O( u        }5 ~& t# ]3 c' Q7 A4 P; m6 z
}- B9 }& M% G/ g% D) T. ^

0 w/ s; o* A( Z; u! f* ~: ZBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 B7 k3 }  y0 K$ V6 K{
% K$ y% t3 Z, ~  V0 k! w        if( exqueue.wrptr == exqueue.rdptr ) {
; V( H9 ]% a' v. C9 d  f                return        FALSE;
3 [$ ~% k1 L& {/ e) J. r        }- p* }; N& G0 I: }  a" ~
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
% Y9 Q6 c8 [3 {' H                ret = exqueue.data[exqueue.rdptr];# @- p) }) t: J& Q
                exqueue.rdptr++;/ Q. A* _4 S# @$ M! n
                exqueue.rdptr&=QUEUE_LENGTH-1;
# H; b2 x* F6 z+ k                return        TRUE;
  S1 Z* e$ A" c" a        }
( m2 Z4 O+ u; |$ U. a        return        FALSE;
6 t% }" x& k) J; ]}
9 E; n- k+ n/ Y  l. J% g0 V) R$ ]/ I; A  w* O
void        APU::QueueClear()
! D' h$ f4 X  Z' u7 z, B4 G, _# w{" S( ]. O& d* R7 C. q4 y
        ZEROMEMORY( &queue, sizeof(queue) );: G6 ^3 E) v/ z
        ZEROMEMORY( &exqueue, sizeof(exqueue) );, {, S" f0 B9 W9 y) b8 g: Z6 q
}8 m7 {1 f# ]; k/ _7 Q
+ z! k) I/ p/ K) E, X' G- I8 R
void        APU::QueueFlush()" }2 P: |, F0 E& q; A8 [
{; K" {8 ]7 X, k; p. }* ]) _  w' w; R$ t
        while( queue.wrptr != queue.rdptr ) {$ A4 z6 i: v* C1 ]: K) F
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );5 O$ j( r3 [! G: Z2 i! Y
                queue.rdptr++;
" H6 C- n/ @) m' P9 l$ Y% w                queue.rdptr&=QUEUE_LENGTH-1;# g+ x2 ]' e% E/ r5 i0 N% ~; Y0 ^
        }
4 d" l8 _( K- T4 i: \
1 ~7 q$ {/ I. c3 P" k; ^, [        while( exqueue.wrptr != exqueue.rdptr ) {
4 J, A* L9 `" Y$ g                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
9 |) i" s6 a) ]* R+ b                exqueue.rdptr++;! B  C: H. [  \, D9 y: r. C. [
                exqueue.rdptr&=QUEUE_LENGTH-1;  a' r( z7 M- G  q
        }% v6 Y9 k4 t0 I' _- C7 \3 u# }, b
}
5 r4 t/ i, a; O2 P! }4 E( D, N  z: ?* z0 |5 |
void        APU::SoundSetup()& s' U/ Y% O3 s4 {8 M& z  r
{
$ z( y$ t! C* ?6 M/ j- y5 T- N) M        FLOAT        fClock = nes->nescfg->CpuClock;
. j& w6 d5 @$ Z1 }  }, Y) L/ d        INT        nRate = (INT)Config.sound.nRate;
/ |, B( E  Y, X! k8 x        internal.Setup( fClock, nRate );2 M  n1 Z& e8 ]7 ^& Z1 N( v
        vrc6.Setup( fClock, nRate );- ~" X- a) M! v; S/ b8 j
        vrc7.Setup( fClock, nRate );
5 D# ~4 S2 l* B        mmc5.Setup( fClock, nRate );
) ]% l% @' y& n        fds.Setup ( fClock, nRate );1 \# i$ ]- i; b3 u6 a: v
        n106.Setup( fClock, nRate );* O- i3 f. B0 n0 v& ]: K' [
        fme7.Setup( fClock, nRate );$ J- b! i* A" I( X" P
}2 q1 `0 ~" N. G* r/ R9 r0 o; M
' T# E. W. @2 t6 j% g3 U# a* D
void        APU::Reset()% s$ Z) v& T7 W+ k+ t
{
  a7 v4 U1 V( a        ZEROMEMORY( &queue, sizeof(queue) );
$ ]/ |! F8 n" B; X* S( z        ZEROMEMORY( &exqueue, sizeof(exqueue) );
" t6 I% u; u* ~$ W8 Y9 Y! f& h' y) p0 g8 \7 w/ e7 P
        elapsed_time = 0;
# ]& W$ r" T3 a* j& l/ }: L5 U0 \+ ]. g' Y/ P
        FLOAT        fClock = nes->nescfg->CpuClock;0 |  g+ j0 q8 D: _
        INT        nRate = (INT)Config.sound.nRate;7 J% m, u& V! [
        internal.Reset( fClock, nRate );& q& ^* {5 J: t/ \  N) y7 F) }
        vrc6.Reset( fClock, nRate );( o3 I, V1 k! P) e" t+ T
        vrc7.Reset( fClock, nRate );  v: M, R; a" ^8 n5 ~4 X& J
        mmc5.Reset( fClock, nRate );
' C) `5 X: R& {- i7 b        fds.Reset ( fClock, nRate );9 o3 ^% @6 k; }3 u( _
        n106.Reset( fClock, nRate );9 P) c- y' `7 W% p: A1 D3 l
        fme7.Reset( fClock, nRate );
  v2 \0 ^) G- ~3 Z( L! {" I0 r
8 Y) \" d% P, v& M& r: k        SoundSetup();
+ b+ s1 F: m4 C: F, u}* C; I  ?( S. M0 p2 \9 V7 Q

- E* ]" M" m) i  `void        APU::SelectExSound( BYTE data )
' y/ j0 B+ U/ `8 P1 d+ L' M8 c, J{
& x0 q6 L) U0 l        exsound_select = data;
# c3 I# ~- m9 t7 V4 ?; ]0 i. c}4 ?" n# e* e* G, s8 o: Z' x9 X4 D
# j+ M: P5 ^6 t1 B1 ?
BYTE        APU::Read( WORD addr ). E! z5 [( l2 z, L1 U$ ?
{8 d2 F# V4 i3 n2 M
        return        internal.SyncRead( addr );
7 J4 `  Y! P9 `  N}1 ?9 Y6 _) g, g4 Y

5 ^2 K& m: d( b9 h" wvoid        APU::Write( WORD addr, BYTE data )
9 \+ q* G% }1 e) d2 ^  W{
! C* S; F9 g" N+ ^5 C4 y, S. y        // $4018偼VirtuaNES屌桳億乕僩
! y* }1 W  j! t        if( addr >= 0x4000 && addr <= 0x401F ) {& `+ v. Y3 p6 ~+ J' v' K7 _2 @
                internal.SyncWrite( addr, data );
+ K- \& \$ C/ C                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
! I' k7 y) M( p- |! p$ a        }
1 f/ \. Z7 U3 b9 k. T}  \) u6 i" f" O1 @, V
4 P3 s) |  E" x0 L
BYTE        APU::ExRead( WORD addr )
" t4 ]* A. n& O, T& A  d; e  U{
% q0 H2 {8 P; t0 o  C+ H/ j+ WBYTE        data = 0;
1 o" c* d  p5 E/ b6 `6 c' T' {( B4 }# t  Z, }, v1 \' n+ r7 X: Q4 ?
        if( exsound_select & 0x10 ) {
6 |: b$ }! z5 s1 Z0 V0 V                if( addr == 0x4800 ) {
4 T' e% r+ l2 u, j, I                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
; I8 ^/ f: x* N, ^                }- K, D- {! f1 \3 p) g* u
        }
3 K7 |. U6 M# B        if( exsound_select & 0x04 ) {
* D5 [6 r# N& h5 O% _4 n                if( addr >= 0x4040 && addr < 0x4100 ) {/ {& t0 x% t1 ?. T2 Y1 l
                        data = fds.SyncRead( addr );' M( l8 q" z/ V1 a1 M; ?, F0 e
                }% c. K/ i- x' d( R' F- I: s
        }8 Z$ x1 I7 D- A  }0 O
        if( exsound_select & 0x08 ) {
8 \2 w4 P/ l2 L$ U7 Q                if( addr >= 0x5000 && addr <= 0x5015 ) {" t2 G8 l+ w$ `" A( L( d
                        data = mmc5.SyncRead( addr );
- z/ A+ Y2 k$ J; H& S: d                }
+ I$ c4 C* h2 W" `4 V) n        }
7 }8 l1 l; M& s- \$ V3 @1 N% ?! ]) g# I" U
        return        data;
0 q. i! {( ^; |5 `) o2 O4 L}; B/ \2 }& l! q/ r' C. }% |

, l4 _* o2 f2 }void        APU::ExWrite( WORD addr, BYTE data )
6 m/ z( ], V! Z; w{, l. l; r% m( {
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 x% |9 D& \. O  Y. o4 o  T+ d  c

0 c2 k* k5 ?) ~& o& _1 f# s        if( exsound_select & 0x04 ) {
8 h. P' I  N' E" X                if( addr >= 0x4040 && addr < 0x4100 ) {
8 r! Y; F. t1 h5 D: P8 G  a                        fds.SyncWrite( addr, data );* r1 U: r. E) J2 _! `
                }/ [0 Y3 ?" A. S4 B* z$ d. j1 ?0 r  S6 L
        }
1 C& ]6 K3 B* v* P6 B7 s( b
5 n7 O, E5 ]5 _        if( exsound_select & 0x08 ) {
$ a! }, I- w! X4 W9 k: c0 `% c6 M                if( addr >= 0x5000 && addr <= 0x5015 ) {( Z! M+ r( F# N, W% m/ C( M6 g* ^- y
                        mmc5.SyncWrite( addr, data );/ ~: O7 W8 ?- X2 T" l9 D6 {4 @2 c
                }& M5 N5 i8 V9 u7 [1 m# |/ \# Y2 p
        }
( ?3 w3 y" r1 ?2 R}6 V, d8 ]7 Z) r
# @* l+ ~( V9 B  u- }' D
void        APU::Sync()
4 ^- ^( l* H$ b' q: |{/ ]6 Y5 ~8 A# N  @/ N* P; B4 E
}
, Z! X. @8 r/ W$ {
. ~: w& q! V2 s0 }8 Z- |; \2 H4 X. [4 f9 Vvoid        APU::SyncDPCM( INT cycles )
5 Z( H, ]. N( w5 Q{- k$ U9 w! f' `# k
        internal.Sync( cycles );
$ n: h1 E+ K: t  L# a
8 M# {/ L* x! p/ |6 R! ?1 l/ s        if( exsound_select & 0x04 ) {6 b- K- K) u. Y5 b+ I
                fds.Sync( cycles );1 ]4 o2 A8 I' g
        }( R2 f/ _4 Q: W/ H/ s( D7 B
        if( exsound_select & 0x08 ) {
% u8 }5 n: d/ w# b9 M                mmc5.Sync( cycles );2 \# M1 ], q- \1 U7 e% ]* o9 |
        }
( X& T9 m6 [! z# a2 c}
6 M$ [! Q1 U9 m. r9 Q0 @3 j) o$ o) Q0 Z. C7 b! m/ V+ }! z$ c/ J  a
void        APU::WriteProcess( WORD addr, BYTE data )' m# z9 b" P5 E4 {, e; M9 K+ ^6 F
{3 o' H6 b" m1 {5 i) g
        // $4018偼VirtuaNES屌桳億乕僩( ~- z0 ]# D4 \8 u, r
        if( addr >= 0x4000 && addr <= 0x401F ) {
' `: ^  u; _4 L                internal.Write( addr, data );
: `$ o) J7 I. O; t        }
8 C3 J3 l8 \% O) N$ i7 G; I. x}+ C4 ~' d. I. G
$ I7 J" g1 ^) Z) H. s3 Q! H) y
void        APU::WriteExProcess( WORD addr, BYTE data )% y) F/ B  w/ C( u
{
* B* ]& ?9 Z0 n4 }* C. G        if( exsound_select & 0x01 ) {$ A. p5 Q  r' p* \
                vrc6.Write( addr, data );" A" K: ^1 H: H6 Z
        }
4 t3 j9 R+ G8 C6 e% P        if( exsound_select & 0x02 ) {
" ~$ |' G* m# g: R6 K8 H/ ^                vrc7.Write( addr, data );
$ Q8 }$ W; ~4 h8 v        }
! p, `, _0 [) C+ X; `        if( exsound_select & 0x04 ) {
  q1 J0 }" V# D$ i                fds.Write( addr, data );& Q0 n" ]1 F$ e$ C7 ?% p
        }& l6 P+ Q' \: Y* x( H  y, E
        if( exsound_select & 0x08 ) {6 E0 M' \! z, G: ]
                mmc5.Write( addr, data );
7 J; i; X! Y, Q, K" W& i1 E        }
$ d" a, t& C9 P0 T8 x* v8 ?! y        if( exsound_select & 0x10 ) {
( c' A4 G  n0 l                if( addr == 0x0000 ) {% e, M5 B. r1 p/ j0 o
                        BYTE        dummy = n106.Read( addr );; e6 k+ v5 Z. M+ E
                } else {
4 _: _5 p3 z/ f( r                        n106.Write( addr, data );  V" {9 \" B7 Y$ {. m# o* G2 K: \6 A
                }
6 M6 E4 s0 h& g4 n        }4 T1 X! \3 A. W, ]6 B5 ~" y
        if( exsound_select & 0x20 ) {, D  m9 F- Z- n
                fme7.Write( addr, data );
8 P7 M! j4 o! i- A$ G        }6 W" Z3 F# x4 ~  q+ w' s
}
% ?) M! h) S" E# m6 L0 S* C: U3 [5 [  t, ]- k' ?; I5 i
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
* c" p8 ]. V! B+ ~8 S{' `  j% d6 J9 Z: G
INT        nBits = Config.sound.nBits;. G$ t0 b4 g0 }& y
DWORD        dwLength = dwSize / (nBits/8);
- {( H0 T: k; yINT        output;
4 `* h1 `! u, l, U4 OQUEUEDATA q;
/ z3 k9 Y4 Z- EDWORD        writetime;4 [0 K' Y& n$ `0 e" b2 T" x) Q$ j! ?

8 F0 E1 b" x* S1 S( d- gLPSHORT        pSoundBuf = m_SoundBuffer;8 G& t5 I& J, b( @7 m
INT        nCcount = 0;! Y+ L# ^- u" q- z0 u

! u! X# k( C# v  L$ DINT        nFilterType = Config.sound.nFilterType;
2 A+ s! @( F, u: @& D' u, R" E% n$ \
        if( !Config.sound.bEnable ) {
* l& h8 u. d; e" R. Q/ S( v1 U                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );7 Y; w( H! X+ R5 i
                return;
  C: o! d, t, A* s" R! }% |        }9 T  b  x$ v: J" R

2 v) A# M) I6 l0 z        // Volume setup1 ~, Z6 p3 w+ R6 u8 B. ^
        //  0:Master
6 e) `: L" ]( H- ~9 ?+ i; ?" Z        //  1:Rectangle 1
% G2 \+ l0 R+ A8 s% Y* P        //  2:Rectangle 2! ?: }- a% Y: ?+ n" n5 h
        //  3:Triangle
& ^8 W* g& b3 S, L3 g        //  4:Noise; t9 L; H" z2 N" y9 Z: G& H
        //  5:DPCM
/ U) w7 a$ a  S1 U# Q- h) l6 p        //  6:VRC6. b* |; W1 b( u/ T% _9 q- a% H
        //  7:VRC7
# P7 x% D) w, F        //  8:FDS& I, L# E- e, g+ i6 M: p; C" d3 ]
        //  9:MMC5
* s4 i7 l2 l' R& p* F        // 10:N106
: n7 O; G. \# a& A& i, _; i        // 11:FME7: C2 D5 h7 K% X5 N; w/ `/ z
        INT        vol[24];. K9 D6 E0 ^! [& ?
        BOOL*        bMute = m_bMute;
. G9 V; V% ]: i2 [& g* L9 ^' Y; ^6 B# v        SHORT*        nVolume = Config.sound.nVolume;4 B+ O  ]& L0 R4 y5 _5 }. B& u
% @' V: }; X. X2 ~
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" O% d9 H& S" c" l
" f/ a1 O2 Z% P1 _7 h
        // Internal
0 _5 p" g8 p$ s        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
, p( \1 d0 N6 P! `4 Q        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;8 E6 F# D: R4 s0 t& a- g
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
( ]: |& L* m/ M" Z. M9 |        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
' R5 T5 [- h) w2 J) I        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;! p9 b' g2 |2 k

& t3 _1 F( w: }        // VRC63 b' Q. K1 Z' Y% U# D
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  E( k. j1 z3 b+ s( S  v& U
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# n3 O0 L2 c% p6 ]. ?        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
. f+ A+ P' Y/ g1 U7 @( M3 m" J, l& p3 \0 S' P3 w; R" \
        // VRC7( m# U8 R$ {- p! h0 Q
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 m2 T; z8 f# K  a5 r
- }6 U/ }. N& V- W
        // FDS
- k. U- b2 v$ o  f        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;- T* v# e3 w: w$ E! U5 l5 ?
; b: ^1 m; P7 D. E  N: g
        // MMC5# M4 g/ S" Y9 W1 A5 \; F
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& X" @: H. L4 z" Y* N! i, P        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; }# ]4 H! D- Y* `2 r( a/ K- d        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
  h/ U1 q$ C# ?7 B! x
& ~& O) F: N; b' m3 K* x        // N106
% j. s2 P5 p4 ]/ C2 z9 ]        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;9 m( J1 ~& F4 d; H" ]3 Y4 ~
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 e# v( ^. E. M, h+ g" j
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ u% s8 p+ P4 b4 O        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 F' L; ^  o" d4 k! \
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; I% y& g, N  n; b* N9 R  o4 v
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
5 f0 P. l% S7 n5 K8 s% d$ Y        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;- w/ I5 i* M1 C5 J7 q: q' _# K
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
* K9 n' Z3 J& a
- ]- S1 O* R; S! k, F4 ]7 B        // FME70 z* {$ E' ]! ?) n. M* y/ q  h
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 g8 V" S2 d5 f+ A        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;$ I* p* p' q4 V
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
/ x: b* u. b+ f, ?( d7 t0 s
+ A4 ^. [) y  _7 K2 F  q//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;) }! b, V4 E- a) m
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
4 A' W" W: x+ l4 H! a$ Q- x% g& T: Y* ~4 L2 W- K
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
( E! ^0 X$ n! x( e1 B        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
! I- n# d1 y8 H$ z. P; H3 \0 J" ?. f; Y                QueueFlush();
; o; u4 q+ W/ n# r# ]5 k( E        }$ X7 o3 _+ N& z) m, T$ ^% K

* g8 p) {8 K8 a( W' i/ v# q1 C        while( dwLength-- ) {, F, ~) Q( t8 b
                writetime = (DWORD)elapsed_time;
- z1 E4 Y0 @) B" o6 }, {  Q9 a1 B4 H: X9 J, V8 W
                while( GetQueue( writetime, q ) ) {
: y$ X7 x& q; z' r: t                        WriteProcess( q.addr, q.data );& U1 a; i% w- e* L8 ^
                }
1 [! o8 J; D' w' U5 [! \" S) z/ b, U. I; E
                while( GetExQueue( writetime, q ) ) {
' I; ]) }2 B7 ^  F- ~                        WriteExProcess( q.addr, q.data );3 d* M9 v3 x- D  x; J
                }* ^6 n+ A6 f  Q9 z- T  ^
: M) f% S( C0 H5 C$ r
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
  O0 F1 D3 Q2 I0 H) ?% y& m1 }; Q6 P                output = 0;# O3 r3 F3 q  K' N' O4 I% p
                output += internal.Process( 0 )*vol[0];
* X7 b* t8 _+ L  y1 c                output += internal.Process( 1 )*vol[1];& D1 m) h: H9 ~+ l  i& L
                output += internal.Process( 2 )*vol[2];9 U2 q! E% ^( q5 p8 J9 z3 m- z" Y
                output += internal.Process( 3 )*vol[3];4 W; d0 }* ~+ Q+ W* P
                output += internal.Process( 4 )*vol[4];
1 r5 w* U4 n% Y' H$ F
# u8 C& p: ^6 P+ U( |3 J4 f- n                if( exsound_select & 0x01 ) {+ O+ l7 }4 M$ p2 V0 h7 ^
                        output += vrc6.Process( 0 )*vol[5];; n: \' H/ j9 w2 a5 x# Q
                        output += vrc6.Process( 1 )*vol[6];
/ [7 }' V* G- }& U, o! |2 i                        output += vrc6.Process( 2 )*vol[7];' A; O. v" K2 L* q
                }
0 p7 ^+ K3 ^0 b, N+ d9 O% R                if( exsound_select & 0x02 ) {
) V' r8 M3 D/ Q3 c& I! v0 o                        output += vrc7.Process( 0 )*vol[8];
2 g& q/ J( o# |5 `/ s/ W( F$ }+ |                }! X% G% \- K& Q; U: }! Z
                if( exsound_select & 0x04 ) {) y6 S/ m9 O: @! i- e* k. S
                        output += fds.Process( 0 )*vol[9];0 J# P  r: o4 {, x# H8 s
                }: _, W7 `; g3 D5 u% |  Y
                if( exsound_select & 0x08 ) {% |+ ~7 Z' q, P+ [/ r
                        output += mmc5.Process( 0 )*vol[10];6 I: p: F  l/ @2 o4 l2 ?
                        output += mmc5.Process( 1 )*vol[11];
3 [( E& r: w$ ~" M" A) k                        output += mmc5.Process( 2 )*vol[12];: m' @9 Z4 T* O: H
                }
! @  o, J& p* d  y/ R2 M5 T) b                if( exsound_select & 0x10 ) {
) n$ A/ r0 m( d$ {+ U! p5 c6 J                        output += n106.Process( 0 )*vol[13];
8 M2 c; z' W8 o4 Y- M( B                        output += n106.Process( 1 )*vol[14];
/ q  }; Y8 Z) H: G                        output += n106.Process( 2 )*vol[15];
) l  C+ ?) m( [. M* }                        output += n106.Process( 3 )*vol[16];. M4 q; z% U/ Z, V& J) R
                        output += n106.Process( 4 )*vol[17];0 S+ s9 N& K+ \0 T
                        output += n106.Process( 5 )*vol[18];4 g7 ?" q5 {. U" N6 D
                        output += n106.Process( 6 )*vol[19];
7 `" y8 w/ B# o4 s                        output += n106.Process( 7 )*vol[20];4 B/ x( F# O5 l
                }7 a- f' t1 D( f0 k
                if( exsound_select & 0x20 ) {
! P6 J; {( X/ \# u4 `                        fme7.Process( 3 );        // Envelope & Noise: ]7 E) Y2 o1 T$ O5 I! W! J% h+ [
                        output += fme7.Process( 0 )*vol[21];. l3 y. `) V9 W+ `2 H" _
                        output += fme7.Process( 1 )*vol[22];
3 n' q" Y0 v4 l  k# ^2 l% y                        output += fme7.Process( 2 )*vol[23];8 s3 p! e8 x* T. w* r
                }
3 f) U+ q9 b, T$ k
6 E2 P% L2 {' h5 t+ v9 }6 b; a                output >>= 8;
) v( U# C, Q  [# s  M* m( _; W' f: |: L
                if( nFilterType == 1 ) {
' R3 b# H8 d# Y  j                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
- G/ S; s3 k4 R                        output = (lowpass_filter[0]+output)/2;
: u: m+ J/ M( v0 U: ?                        lowpass_filter[0] = output;3 x1 }# `& f5 Q5 w
                } else if( nFilterType == 2 ) {4 O/ z8 ?. ?( I. s+ v
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1). n9 t6 w5 H2 Y9 e
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;6 D/ _6 q# `8 z; Y0 w6 B
                        lowpass_filter[1] = lowpass_filter[0];
# `# t) x4 f6 B) {  Q' I8 l                        lowpass_filter[0] = output;+ p3 v# _3 N0 c6 z
                } else if( nFilterType == 3 ) {' k& T% W7 _8 c& t% V- }
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
8 K% A% ?, u" r, [/ T/ x                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;( U- \8 F2 ]2 i' d7 V9 a
                        lowpass_filter[2] = lowpass_filter[1];+ Y# M- J$ i5 A, W% B
                        lowpass_filter[1] = lowpass_filter[0];
3 a( I$ M4 h9 V; u" a: g                        lowpass_filter[0] = output;
( V2 z9 d1 h; m( ]9 C* X                } else if( nFilterType == 4 ) {
# H0 J; |: F% B: _                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* M6 U. w- h. b) |                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
5 z0 C: ^. y) D* T. Q$ j6 e4 {                        lowpass_filter[1] = lowpass_filter[0];
  M9 f3 Q4 s% w6 J8 O2 D# k                        lowpass_filter[0] = output;6 m! u  ]2 t. i) N# ~4 y/ `' Y
                }
& g1 D# @) r5 |! p, o1 }/ R; c/ U9 C
#if        0* r$ G) W! v6 ?
                // DC惉暘偺僇僢僩* x8 S5 O8 w' [% L& W. J7 r
                {8 G# V9 Z" O: r+ N7 `4 p( l! p* r
                static double ave = 0.0, max=0.0, min=0.0;/ j3 v# W$ T! e8 ^6 \+ f
                double delta;
. Y$ z, E0 I7 U6 O$ b                delta = (max-min)/32768.0;- c9 a: ]4 b; R" V: J0 Q1 S
                max -= delta;
' o$ V/ i& u6 `9 x3 m                min += delta;$ ^% P' h' U1 O! ?
                if( output > max ) max = output;4 f! P4 Z; f, I: D7 e& X
                if( output < min ) min = output;
& x/ V* C8 Q& {' T; T8 h! B- a                ave -= ave/1024.0;
# O! \) d7 l* }) ^& f. L" I                ave += (max+min)/2048.0;
9 {- ?2 g3 v) D                output -= (INT)ave;
1 @. k9 s* S; Z& }9 t' K' j4 D  c                }
% E8 k; L+ p; k0 j% {4 _#endif. H, }5 U/ S! o( C/ P
#if        18 p2 }1 G+ t1 h* |8 i* w8 F* N1 _8 j
                // DC惉暘偺僇僢僩(HPF TEST)! j  G' O' D' ~( x! ?
                {
' I" N& \/ ^) ~5 n//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
+ v. ^( i1 ~& ?0 p1 k                static        double        cutofftemp = (2.0*3.141592653579*40.0);) ]7 o$ j8 }( @- W( p  X0 k+ b
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
' Q/ ?; y( o1 ~6 Q                static        double        tmp = 0.0;
, b( A* q3 @2 H6 `9 `: s  r9 m, [4 [' u                double        in, out;
& F6 Y' |4 h1 f2 B9 a8 \. H
" @6 m" @7 |& w7 k' |5 Z6 s9 N                in = (double)output;
7 c# j$ S5 Y, p1 j8 H6 V                out = (in - tmp);
4 R1 u8 x  P7 ~0 o( ?) F                tmp = tmp + cutoff * out;
$ v, x0 c  A4 P4 X3 ^* W4 `6 d  j4 H! p9 Y
                output = (INT)out;
( w# A$ k4 s4 h3 \                }
  B, K! X! o; \0 V#endif
( K' h/ A3 G- s$ f/ A#if        02 |/ S& h8 @& D% `
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)- D6 a. F- J; \: i9 o
                {
7 X4 o& _" F% T6 C                INT        diff = abs(output-last_data);, S- g! f1 @+ U5 @+ W6 M
                if( diff > 0x4000 ) {
% e6 I# ^: {& `, G7 S; O. }                        output /= 4;
% l$ W3 k: A2 N                } else $ a$ N$ X2 r" r! z; r2 S# r# P
                if( diff > 0x3000 ) {
9 F4 r. r* m: d" C, x$ P; p% _# c( g+ l                        output /= 3;5 l8 y, H7 @9 e9 K/ d, ~
                } else
" r: f" d! ]9 p6 V4 v7 P0 M                if( diff > 0x2000 ) {
$ h- e% S" N" ^  l# X5 G                        output /= 2;
. A. J. {5 h9 x7 g6 a* G                }
; p4 e9 D( j8 x8 q% q                last_data = output;
5 j! W" R) r6 g& Z$ B+ l7 k                }9 C$ ^! D1 [7 M, L: j5 y
#endif
" V  d8 m+ W2 U* z- i                // Limit% \+ [2 O) b# I, O5 v1 N9 m: f
                if( output > 0x7FFF ) {
, ^: O: F# R5 ]0 K                        output = 0x7FFF;
0 R$ k2 [) ?# a8 Q7 y7 L1 l2 f                } else if( output < -0x8000 ) {0 j1 u7 [2 c+ r. |% P7 J% n  \4 {/ Q
                        output = -0x8000;
" ?. [: H" F# a/ L+ k0 f                }
8 q" ~$ G9 x; C% o8 e* c
% \& _) ?  E" L                if( nBits != 8 ) {( q9 n! G/ L! y" ~% d
                        *(SHORT*)lpBuffer = (SHORT)output;
# ~% s- q# a; v9 ?9 r# t9 ~6 R% s- A                        lpBuffer += sizeof(SHORT);; B! e% B, V+ o) i/ \
                } else {
& f1 R8 E( B% G# E2 H1 D                        *lpBuffer++ = (output>>8)^0x80;/ {9 C4 C$ W) E4 X
                }) i$ u5 o8 a% d( |
0 ^6 I& \6 v4 v( `0 R
                if( nCcount < 0x0100 )7 d# v4 X" l5 R. G
                        pSoundBuf[nCcount++] = (SHORT)output;
+ o- s- b( Z# n0 L
6 L, C# B  K$ B& b" K//                elapsedtime += cycle_rate;
+ @! J2 _1 ]; j  t                elapsed_time += cycle_rate;/ P. p' i- V6 X" H- G1 H5 h
        }" B, w# y7 c; a7 A( q3 m6 u
0 C8 e! x! L( Z' {* A' l+ y" N2 G
#if        15 m6 {7 U0 |0 z+ f. I) I2 a+ R- Q
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
' Z- G. P7 p& B3 X                elapsed_time = nes->cpu->GetTotalCycles();
1 P9 i! v; W4 z        }
+ V- N0 C) A! L- {+ m+ `        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
$ F8 e* L$ N7 \$ E2 k8 y                elapsed_time = nes->cpu->GetTotalCycles();+ j1 T% u, h5 U% ~, w- {2 d
        }
' x1 P, o4 z& z#else
9 `, h  a6 K4 E' o9 c2 j# L        elapsed_time = nes->cpu->GetTotalCycles();' i2 ^. J) u* p1 y2 R8 B9 F% Y$ P
#endif
! E! O& X% t, X+ U; B( s) k}1 j4 d4 E1 D" Q. [# B; C, P
& n8 v+ _$ C: s) D
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)6 T- O$ Q" B. M7 T, E- o! A1 Y
INT        APU::GetChannelFrequency( INT no )# T+ u5 W+ \# L! I
{6 q* K$ l( @+ _$ ^
        if( !m_bMute[0] )6 f( @6 ?7 J/ P2 t, o1 _# {! D
                return        0;
+ J+ E  l' H5 _  Q# u
/ G% q2 V; O6 L, `1 D% Y        // Internal
$ n4 [6 G$ P. l1 Z        if( no < 5 ) {& _/ x9 n6 p' C* T9 m' c8 `6 x
                return        m_bMute[no+1]?internal.GetFreq( no ):0;" q' O# @% _' a* J) X
        }
- m! \) T& i& D8 v3 v        // VRC65 }$ w. J8 Z2 ]& V' p" U- i0 F
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
' C+ i! I2 }1 o8 Z4 I7 |                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;# f, i, N" v& y  ^/ T
        }) K* Z4 {% c# L4 d
        // FDS7 Y0 k; t( t$ n5 o9 `5 K
        if( (exsound_select & 0x04) && no == 0x300 ) {1 g% o# C' ^, p% J
                return        m_bMute[6]?fds.GetFreq( 0 ):0;+ {1 w) @1 ~. n, l/ n( P) v5 w
        }
5 N1 @7 _! h5 d  i+ T0 e/ q. B        // MMC5; b) c9 O5 o+ {& u
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {: T  T+ d: v5 M1 @0 {7 r
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
, Y  o, {- e" P9 g        }7 x) `7 }4 ]2 a" ^; w8 p. l  s% a
        // N106
( @' b: X* d7 Q& l        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: D* H; x# v' }
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;# I  c+ n' k; k/ @9 w5 W
        }
8 G( u3 {& U8 w. O) j0 u        // FME7$ V/ r  S6 o( z8 E
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 ~5 [, q8 s+ ^7 ~5 d; v4 k: a                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
  K6 Q* u7 L4 B( G) F        }
7 v/ \6 ], `1 a& g6 |) A        // VRC79 _; e8 m6 l# P- D6 }- }( D1 K
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {! Z6 V8 y: a' M& s" P  ]
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;0 I( s7 s8 u" O. M- I
        }
6 C$ S4 }& Z: [" @# O        return        0;
) [8 S, \) }& I, u  @3 _& ?! V}  `8 x5 C. D2 f- B& F+ j" E

( }( H# E; U: L+ g: T// State Save/Load
( p: g0 \' a. \5 J& f% vvoid        APU::SaveState( LPBYTE p )* j1 F! X" w. y- N3 x2 T) E) A  A; q
{' i, \1 {( }9 F& a
#ifdef        _DEBUG
3 a/ n% Y8 J6 w/ ~+ VLPBYTE        pold = p;  e- r# p  @5 a  V7 R
#endif. C! b3 b6 r- }( h8 }" R1 l6 S  u

; G, [  ~( i5 I( r% N+ G6 s4 g        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞0 Q1 o4 y7 b* p8 S5 S7 D
        QueueFlush();) n7 v% g2 z, f! V3 w4 R
/ n2 w- D' j3 m
        internal.SaveState( p );& P. ]$ ]+ K( ~- ~4 r1 ~& J$ {
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding9 H% Y/ C* p& p
5 d* o- ^, F1 M8 g! y
        // VRC6
9 P' c! {3 ?4 `: {        if( exsound_select & 0x01 ) {
5 f/ z/ _# u6 h6 r! m                vrc6.SaveState( p );
; T0 f. v7 B6 m1 U& A0 o' }                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
2 c: H  L" n$ [3 M7 Q  Z$ c        }  q3 d3 F) ?. \' f- h9 O$ J5 e
        // VRC7 (not support)
; X0 s8 X6 C( ~: ^        if( exsound_select & 0x02 ) {. \3 X- @8 r% S' T$ o  ~
                vrc7.SaveState( p );
( j+ U% p6 G2 _- |! k                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: x* x3 k' X1 B. \" I( Z        }
# ^8 w, x; v( }) m- `" T3 X, k        // FDS+ v: p6 I/ L  ^: W! F
        if( exsound_select & 0x04 ) {% _' t$ Y' o8 ~- }: h* |0 U
                fds.SaveState( p );
1 G+ ~- H# y# z7 Y: ^1 h                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
$ ^4 a6 p+ i; t7 @3 X        }! a- K5 b0 U2 w) n; _& p8 |, u
        // MMC5
8 x7 R$ y7 \* w- ^& t        if( exsound_select & 0x08 ) {& @- ?* p0 @4 L7 J2 A( \
                mmc5.SaveState( p );# V0 o. L& V8 A5 q$ J" a  v) o
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding% y2 I2 o& L1 D" J9 x+ F
        }
8 c. E3 B  w- J: Y. F        // N1065 ^9 E. ^* F3 w5 m; [8 `
        if( exsound_select & 0x10 ) {
/ q, G- f; p8 a" ^/ v                n106.SaveState( p );2 c, r6 z, H# P' l$ m( D
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* d. Z) \. Q: J# O# q& \3 l  L
        }
, W8 k+ l; q# F1 [        // FME7
, ]7 O2 M) Z' {4 i0 N        if( exsound_select & 0x20 ) {! C0 ~' h( Q# i' \
                fme7.SaveState( p );
+ ^7 d0 E& }2 y7 m1 j( ?                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding  B# K6 G% T$ T
        }6 Y+ T  r( r% z: v
! Z8 U( \) f$ Z9 l- h
#ifdef        _DEBUG
. S' Z$ k9 _# IDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
6 @7 l" a" j" U# }9 V4 F* {: ?9 z#endif
% z8 ^# L) ~/ U- N% G4 O* c}$ E4 a+ T' M4 b  ?
" D7 p& t' B, G0 C+ j
void        APU::LoadState( LPBYTE p )
1 S. d6 h, o, W2 i/ V{5 C" |1 Z1 R* `0 q
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡  |- F% o; W" w; {( Q/ f2 [
        QueueClear();
* @) d4 ~3 G# M% _, Z& w& Y
3 x9 _! x" q8 R4 g! W        internal.LoadState( p );# Z; O, O/ ?% u+ A+ Q1 e  z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding  V" `" i" @/ P6 _

2 N9 G4 _# s5 r5 c4 {* n        // VRC6
5 X/ K/ v1 k9 e2 {+ H0 Z        if( exsound_select & 0x01 ) {9 t7 z# l1 R3 ~# o( b
                vrc6.LoadState( p );
7 g/ l: Y, n3 P3 H" r4 f                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
7 |' H/ ~7 m4 p9 R: o& V* C& P        }
4 n; q$ g9 a. |8 s  y' R, Z        // VRC7 (not support)/ v) q, ~6 ?9 [" a9 g1 i' a3 v
        if( exsound_select & 0x02 ) {
3 O& P) q) w- Y/ k( i$ b                vrc7.LoadState( p );$ ?/ X/ A  r- g& J4 a* ]
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 Z9 n" I0 G4 E# I& F  {  i
        }4 s4 _  ^! w+ a  }: [; v* o
        // FDS) h8 {" c2 `) L3 B+ w
        if( exsound_select & 0x04 ) {% v. u  t# j8 q$ D
                fds.LoadState( p );
' `8 K/ j5 ]$ K# n- J0 [1 @' @                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
3 j# }5 M. a+ ?$ P0 }: u! m        }% F, Z$ |1 I% T" w+ p4 N
        // MMC5
8 E2 R! W/ Y0 \5 D        if( exsound_select & 0x08 ) {" M7 T6 w6 a' S( c4 u
                mmc5.LoadState( p );$ D5 t9 {8 P; _6 U
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
+ ?1 A% ^. o) [5 I: V        }
1 H4 R5 x7 J% u$ f4 C9 P        // N106
2 N" F' z- x( D: L) J4 A        if( exsound_select & 0x10 ) {( h% c: B( D  Z  r$ ]8 Y+ q
                n106.LoadState( p );( u1 s1 C. z' |9 e7 ~- _( A( B9 m
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
4 ]2 x6 v, U( z8 C        }
7 D' M1 z$ C# I, _        // FME7
/ o  ]1 U' M8 a- H# \) f        if( exsound_select & 0x20 ) {; l& T- L) [% P% z" N2 j/ `3 f6 V
                fme7.LoadState( p );. o( O+ U; [$ n0 e
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
' \; F. G; o" v+ }        }4 D: V0 s6 V5 d) \- W
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
' u; o+ I6 ?% L! S可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。& P6 {1 Q( u0 }, b. Y$ f4 y4 \7 k
感激不尽~~
6 D& e5 Q* T; ]' G) ]" o* k' p
恩 我對模擬器不是很有研究,+ k0 D6 k; p4 X- A2 d
雖然要了解源碼內容,可能不是很困難,5 [5 Y3 _: o$ M# P
不過還是要花時間,個人目前蠻忙碌的。
& W0 h9 m$ M' X/ a* [9 ^8 y+ u! N' y: ?' ]
給你一個朋友的MSN,你可以跟他討論看看,3 ^7 l0 c$ q  w( c0 [3 T- F
他本身是程式設計師,也對FC模擬器很有興趣。. o0 K( Y$ }( u: V* q% ~/ o) C& }  Y7 W
. z: J/ O3 i% w3 M3 K
MSN我就PM到你的信箱了。
: T  v9 z* P; h+ l* \- ^" n3 m; y' b1 ]* K4 I' r' u- S$ T
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 & q; A5 x1 u3 J1 {. {! q
呵…… 谢过团长大人~~

+ b2 x& T# U+ }) I' A; v( ]% ]. S4 s
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 ) u1 K; j. Y4 X, w
团长的朋友都是神,那团长就是神的boss。
( b* F+ F  P9 ]$ b7 J3 J! J3 Y
哈 不敢當,我只是個平凡人,% q- i5 x- w& K! f  ~
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
/ |+ n9 L7 e% j9 h( hZYH* E' K1 n! g7 E# i) t( ]
QQ:414734306
: o" }" v9 F# N. q9 _" H& SMail:zyh-01@126.com
5 ^9 ^1 ]3 x+ h" w3 N# i" b! N1 [5 K- G8 h4 c! K
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) M/ i1 d. D. H3 d' J; \再次对团长大人和悠悠哥的无私帮助表示感谢~~

& ~, n/ C3 @& ^4 }3 D不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-4 20:24 , Processed in 1.081055 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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