EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。9 D* u& [+ B; }  ~9 j
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
4 p: f* M! U6 O% u8 V这里有相应的模拟器源码,就当送给大侠了~~; V0 b8 p( `( @/ c" S
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
" Q1 v+ K1 d, K+ `+ K能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
4 o. q2 s8 G7 V. W2 G; K$ ^6 I楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~4 U, F9 k9 C8 Z. j
这里有相应的模拟器源码,就当送给大侠 ...

. u/ w6 U& k0 W* Y7 ~7 |聲音部分(Audoi Process Unit = APU):: F6 \9 h  [+ I: m. k' }1 {& l
.\NES\APU.cpp
4 U, o7 j6 }1 J; r6 O" q$ ^.\NES\APU.h
- C; ?( r4 P% N8 l, u) z
0 |3 l6 i! L6 y. g( p5 i
' y, t3 d9 g# V/ r影像處理部份(Picture Processing Unit = PPU):$ z. Z6 }1 m: L0 T( D. O3 N
.\NES\PPU.cpp5 g1 y2 C+ j; {; g
.\NES\PPU.h) K% b7 \( n7 O2 g0 T
. {% C5 z2 S3 y6 `! r, `
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
2 Q3 G6 S: O3 ]* h7 ?(由于很多专用术语和算法机理都不明白,所以看不大懂……)$ t# ~- Z. T: s4 r# L
//////////////////////////////////////////////////////////////////////////& o, h9 E+ s* n6 [  {
//                                                                      //  \- K: q! H  M2 n
//      NES APU core                                                    //
  f6 q7 v0 W, Q6 A/ L' ?2 q//                                                           Norix      //; F( u  W- v* c8 ~
//                                               written     2002/06/27 //
& Y0 @" Q+ b- e" W//                                               last modify ----/--/-- //
! |" @& N1 W. S//////////////////////////////////////////////////////////////////////////
  e, d) O2 j3 z; X* u6 b( J! }6 A#include "DebugOut.h"
; O2 z5 d7 B  @: b#include "App.h"1 [' L. T* c7 L3 W4 z" b4 [1 H$ }
#include "Config.h"
2 y- |7 R+ ?% S. T# Z& ], U& u. A
6 d0 w- t' \1 O#include "nes.h"! q1 T, N% u. J! ?( I/ q
#include "mmu.h"6 T8 h" I; u. }% b% k
#include "cpu.h"
9 `# N4 h+ G! I+ S- u#include "ppu.h"
2 o* Y% @1 l( N: v0 T#include "rom.h"+ O- n) v4 ^6 V+ U3 S  e/ |  R" g% y
#include "apu.h"
# F7 g0 v. b$ Q, ?6 N9 {" d
* J  s9 H; L3 @; s, X// Volume adjust
3 ]* H# F! E& `! o5 m5 `  L. N; P// Internal sounds
8 u4 r* i5 U# p0 t8 O#define        RECTANGLE_VOL        (0x0F0)" k: a" i. s! s) G
#define        TRIANGLE_VOL        (0x130)
: i8 @$ O8 ]/ p2 n$ b* h+ {6 Z#define        NOISE_VOL        (0x0C0)! X7 r4 R) P. w$ ~6 k; t% K- a/ [
#define        DPCM_VOL        (0x0F0)$ P1 W6 D6 d1 z! z! G& [
// Extra sounds
' L! r* c! h* Y6 e/ I1 N#define        VRC6_VOL        (0x0F0)- b, R0 m: l6 Y- [* L3 `* v6 Y2 n
#define        VRC7_VOL        (0x130)9 k  x0 f: a: ?( L* P, M/ _6 `
#define        FDS_VOL                (0x0F0)
" ]; _/ Q: q: w1 Q# p+ Z#define        MMC5_VOL        (0x0F0)# n6 ?  M3 P( b! C3 Q) k
#define        N106_VOL        (0x088)& t. _/ |7 a! }% I
#define        FME7_VOL        (0x130)& {' n# s' D3 Z9 K* s

# O! Z6 c; \% D" x4 H6 Y2 Q: ?5 TAPU::APU( NES* parent )
/ e1 l  Q/ E) ^- R' Q{( r3 X4 ~  i1 R3 T
        exsound_select = 0;" z5 _9 `5 m5 ~/ H* F1 v

5 N, N6 a9 @7 @        nes = parent;
" Q! M6 A+ ^) ~$ v; U  H" q) ^* p        internal.SetParent( parent );3 [: a9 e/ W8 n0 d6 o5 @5 A

% ]$ j/ `! A% z8 B* \        last_data = last_diff = 0;
. O: O! P* R6 c8 t8 x8 x: l. T* F- ^, {/ Y) v- R+ R
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
" o1 m4 t; R* r+ Q- c# y8 a. g4 n
$ P3 ]! i" U; @# N" O5 {        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
. S2 n% x/ K: p# @( L# d2 B2 S        ZEROMEMORY( &queue, sizeof(queue) );# P) N$ t& D' T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# H8 R0 |, b6 B7 ?  v0 O7 E+ ~, Q; Q# R: K. w
        for( INT i = 0; i < 16; i++ ) {; \5 k# o0 W+ G  O
                m_bMute = TRUE;, @: ]5 |7 x$ h' l
        }
; ?+ ~( ^, B1 r% T3 J/ |7 W# y& G}! P" r" n+ ^2 r
" j7 @/ p% w8 v/ g) v9 R/ s( w
APU::~APU()# ]2 ^( n5 O5 N1 x7 p2 T
{
$ |% p) N& C9 J' _, B4 P2 I: Q- S3 t}
* H4 b$ \* J- s' R+ y2 {+ X/ [& I' D% H- h2 u- |5 J. Q5 t
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 B$ B8 F2 y8 G& f9 q, S( b
{
2 i) \, ^4 {% m7 n; T9 r8 I        queue.data[queue.wrptr].time = writetime;
, g5 D/ q& ^6 f/ E' L        queue.data[queue.wrptr].addr = addr;
3 k% u7 k! F! m' y$ s2 M8 e        queue.data[queue.wrptr].data = data;  _7 N2 g3 \+ y$ m3 @
        queue.wrptr++;/ F7 v" r* r% h" Y6 Y
        queue.wrptr&=QUEUE_LENGTH-1;. i1 k" ]: [/ [3 J" O' ~% ?
        if( queue.wrptr == queue.rdptr ) {
+ B' M  J7 X' P, w% C+ y                DEBUGOUT( "queue overflow.\n" );
8 @5 z1 k, r5 s5 r: b7 [# Y3 u$ X& I. w+ e        }
6 G& K( ?! _( r1 i" G0 R" V}
  ~2 @( q0 `" n0 B
+ r1 D& [. [9 ^* [  N( n! g# g; ABOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )/ [" E; ]3 I6 A0 l" [
{3 f3 i! A% k" N, v
        if( queue.wrptr == queue.rdptr ) {
* ^; U7 x) }' x5 O" ^3 M0 k                return        FALSE;/ u. n& P) n% f; C: j! D
        }" E/ n: g$ B7 P6 I# E
        if( queue.data[queue.rdptr].time <= writetime ) {
2 [1 y* `! |: a; t2 C$ `! K9 i                ret = queue.data[queue.rdptr];' \" g" a: ?2 ^
                queue.rdptr++;' j5 h0 d) }4 Z& q( s" E4 G
                queue.rdptr&=QUEUE_LENGTH-1;
2 n" N" R2 h/ `$ I. z9 \                return        TRUE;) ~% @9 Y) P& r/ y9 h' u
        }
% R+ [6 }) E& N' u5 ^7 ~  q        return        FALSE;
' j, V8 m5 U' M# A}. b& \! D  u4 R
1 q5 A3 Y% a) k, _1 e6 e* B0 ^
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% i- @9 n9 p2 G$ c  ?" I
{
( b/ m# |1 T: k! L; r) D; A        exqueue.data[exqueue.wrptr].time = writetime;
9 H) x' G# X& ?        exqueue.data[exqueue.wrptr].addr = addr;* Z/ \: ~9 x- I
        exqueue.data[exqueue.wrptr].data = data;
; [: k/ Z+ I  F        exqueue.wrptr++;
0 t$ E' p' m" v$ g# T        exqueue.wrptr&=QUEUE_LENGTH-1;
  ~9 D* g( M) g! I        if( exqueue.wrptr == exqueue.rdptr ) {
6 ~3 R: @9 r% B( r/ m                DEBUGOUT( "exqueue overflow.\n" );2 e$ X; o* P' u, ^
        }& F* K$ `% w" {, X1 y, r
}. v7 c- |6 ^7 K* K# F5 q

( ?, e( |1 l: O9 xBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
/ B. ~! F, S% W5 M( D{
* x( Y7 F5 U1 V' n        if( exqueue.wrptr == exqueue.rdptr ) {, y" \; y9 R: T; m
                return        FALSE;' x( h* J5 }; Q
        }9 Z( ?4 @- U- O
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
0 _2 |7 O/ m5 \7 k7 D8 c                ret = exqueue.data[exqueue.rdptr];
# @% N6 R' Q- b- t" L" ~7 d                exqueue.rdptr++;
4 ~( l4 T4 q; i$ [# i                exqueue.rdptr&=QUEUE_LENGTH-1;4 u) g3 I9 w8 j! A; m( O+ y
                return        TRUE;
# h' a# D$ z) Y        }
3 c" i( \% Y7 x        return        FALSE;8 x( ]2 E, V" ]1 s: ]% a
}
' R# L; s( T( I! }' [% j3 |' Z* Z2 a2 q$ P& c4 q( O2 d
void        APU::QueueClear()
' a0 E- W. k) I{1 N0 ?3 R8 `* ^7 ^6 `4 v4 C& H+ u; _
        ZEROMEMORY( &queue, sizeof(queue) );& z. m, O. b+ @3 i
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
  {/ r* P9 \$ J/ G  V}' ], l% j8 b% K, z

* c! j' ~& G  D" x" bvoid        APU::QueueFlush()) N* i6 Q; i2 k: a1 B
{2 ?& M7 p& j$ j6 y- M
        while( queue.wrptr != queue.rdptr ) {. Z2 B; q6 S' |7 X7 F
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* j  @* t8 K; t: b                queue.rdptr++;2 r7 a* h1 A3 d! C- d6 \" k0 |
                queue.rdptr&=QUEUE_LENGTH-1;7 e+ _, X& a9 r3 o3 G% K
        }/ G8 l6 b2 l- \; ]; J) @& Q* f( ^
6 V1 u( T* D/ y. g! C
        while( exqueue.wrptr != exqueue.rdptr ) {
  S2 S  T- A! q5 s! ?+ R6 U% x                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
$ K! ~4 Q3 a* s3 ~& G6 P                exqueue.rdptr++;  \; a6 P( P: p
                exqueue.rdptr&=QUEUE_LENGTH-1;$ V, q* A* s- d& ?! C# T
        }
; X9 L1 g( c/ f: {}1 X/ G3 N4 a4 f# G& T$ q

0 |5 d5 K  q( }. x: Avoid        APU::SoundSetup()
) g0 f2 J, P. z4 l  o% H6 t4 P- m; V{
  P3 b, V: Q+ K% N, p9 S* `" N! b        FLOAT        fClock = nes->nescfg->CpuClock;
+ \! l: c2 o& S: G4 {7 r        INT        nRate = (INT)Config.sound.nRate;
( d4 c. R6 T6 E# A; u        internal.Setup( fClock, nRate );
1 u/ ~2 p4 ^: a, h        vrc6.Setup( fClock, nRate );
1 n  \' C- z  n$ a' n: V        vrc7.Setup( fClock, nRate );
! z2 B1 l: t' p6 W( j- U) V7 D' Z        mmc5.Setup( fClock, nRate );
# E% z4 ]/ F6 f; G" L' M6 G        fds.Setup ( fClock, nRate );
: X. P; J7 N; q% N, _1 x+ l* w        n106.Setup( fClock, nRate );
! }$ j1 g  S. y2 K% B+ @6 ]' ^3 }        fme7.Setup( fClock, nRate );2 i: {3 v  z0 g+ ]0 b/ k! {$ c' F
}. b! j9 m$ s- _$ H: C: M. G

! E& x& w. o# d8 e# S3 {void        APU::Reset()
, h3 D" H% Y* x: q4 K{) o$ \; K& Q! h" l# ^
        ZEROMEMORY( &queue, sizeof(queue) );
) b+ z- N9 E" v: g        ZEROMEMORY( &exqueue, sizeof(exqueue) );+ h6 _  c2 E9 ^
/ }& h7 Z2 m5 Q4 b) C- N" N8 S, D
        elapsed_time = 0;+ B4 S! R& V( e( y+ u0 Q8 Q
2 D( X/ u0 i- Z: G3 z
        FLOAT        fClock = nes->nescfg->CpuClock;$ g+ V5 r$ P% [$ y6 q& M* v7 F
        INT        nRate = (INT)Config.sound.nRate;8 T0 D3 p$ U( a. D7 l( T2 \! g; R
        internal.Reset( fClock, nRate );
5 m. R; E2 J) W        vrc6.Reset( fClock, nRate );
( V9 O% s. {" q* y* ?/ [1 I        vrc7.Reset( fClock, nRate );& ^8 `: H8 R( n' m2 n
        mmc5.Reset( fClock, nRate );. w5 N( U  c6 z( _2 g
        fds.Reset ( fClock, nRate );. E7 B  E# D! m5 l: h" ^
        n106.Reset( fClock, nRate );
! N3 e1 T5 R1 v4 O$ B3 u* W3 v        fme7.Reset( fClock, nRate );; T% b0 h$ B+ m. ~  V3 r6 s: P# |# q

$ I* N# q5 `. B; ?0 ]- v        SoundSetup();
0 S0 h( U% }- V# S$ D% S9 c, N}3 F, E) T+ m" v. [

; T) H9 _$ u7 Pvoid        APU::SelectExSound( BYTE data )& t: R( H0 |8 c$ ?
{
2 t$ `7 T! \( h( l5 f        exsound_select = data;
7 ~' q6 D5 `: h! ]# Y& e9 I5 w}3 L% d/ B. y* I8 y( \; G

0 ^0 g! P8 k# v3 q9 F4 b2 ~BYTE        APU::Read( WORD addr )% O4 M0 h! s% o& m; d( _0 d8 K
{) `* w$ P9 r: x8 L6 b1 z0 E7 b
        return        internal.SyncRead( addr );1 G, d: `  M( D- f' G
}! V3 T3 x9 Q' v2 `- F% d1 `9 j& r

1 K+ Y; l. i3 R0 _- y1 z- tvoid        APU::Write( WORD addr, BYTE data )
3 h& \* f1 z  e1 O{: M3 s; o! a! m% m5 `% M
        // $4018偼VirtuaNES屌桳億乕僩6 w$ g: T! O( Y2 |/ g
        if( addr >= 0x4000 && addr <= 0x401F ) {  ]( Y4 b9 W% G! v& f) h4 f
                internal.SyncWrite( addr, data );, b; l# }+ \/ T8 V$ m, p4 u2 U
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 k- N8 ~0 i9 K/ `4 I
        }/ J" ~& s! ]4 E( }% e& `% w: j0 x
}- m7 i& _5 A* z

/ `. N$ H& V, y, U+ M! M1 t1 gBYTE        APU::ExRead( WORD addr )
0 U5 e0 L) i% C{. l' W. H7 ^$ c
BYTE        data = 0;# I' }8 |2 H1 e% _

  {; O2 z7 b7 h/ [/ a        if( exsound_select & 0x10 ) {
9 }; @9 _- U4 L! P4 b, B$ y# Z                if( addr == 0x4800 ) {
9 D2 X. d+ X: B/ |. R) @# S8 V                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );0 w+ U" p' `3 i9 k; d9 q
                }
/ f+ N' s6 u8 `5 T; F( V8 L& c9 n        }
) F, V0 n  e3 m" J        if( exsound_select & 0x04 ) {
$ d3 C' W1 d3 M                if( addr >= 0x4040 && addr < 0x4100 ) {5 }: e# k+ _3 y3 b1 W: ?& k. i3 H  J
                        data = fds.SyncRead( addr );, F$ ~8 k9 l! O
                }4 ?7 f+ g7 ^2 o$ q& a1 e
        }
3 U8 l1 N# d# w9 J8 f0 o/ j. n        if( exsound_select & 0x08 ) {- o1 q  E1 n% t( U# `
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" @5 @2 v; h$ }/ ^6 r. p                        data = mmc5.SyncRead( addr );
' [! d* }. p6 a8 B                }$ R9 G) u# Z) ]
        }
/ a' G! l9 B. Q; `. z2 z" o7 g
& l. G2 L% {& z# a        return        data;
& L) b5 }1 ?% S/ |% v; r}
& c7 S' K5 F; j- B. J0 A4 L9 F' Y& H/ n
void        APU::ExWrite( WORD addr, BYTE data )
  [( ]; U' M% {5 I1 r5 z{
3 M9 j* e; s. ^% x( [        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );! P! j; l, i8 w" H. W. D* c2 E

( D- k. W, P& [1 f7 A& l% G        if( exsound_select & 0x04 ) {' e8 R. i! `5 C8 E  u# L
                if( addr >= 0x4040 && addr < 0x4100 ) {/ S/ u- w& k) t9 L" I
                        fds.SyncWrite( addr, data );
* u7 Z! Y% a2 J1 @( y$ k7 z, |                }- O; D0 X+ N' M0 F
        }
* s! ?7 {! u8 J3 I" y6 e0 _0 }  ?7 P- C2 S, n7 ~% n
        if( exsound_select & 0x08 ) {; M- T3 {5 @3 E) N9 y) _; D
                if( addr >= 0x5000 && addr <= 0x5015 ) {, K8 r% T) k& k$ r7 y
                        mmc5.SyncWrite( addr, data );
5 _: l" w  f& M  L4 U                }/ K% U" `6 E1 p( h# B, a7 w6 T
        }4 W1 f8 _' r2 P- K
}
( i7 X* N- k7 e! v: `7 D( T; v0 Z. k3 {; }4 g  B+ q
void        APU::Sync()9 |/ N' W; u# m/ O' i, S1 x$ M  G) s# k
{/ S# q1 h# U$ x% C8 N1 I
}) M: _0 A( b7 U0 L' @3 I7 K/ ~

0 M4 v1 ?8 R; svoid        APU::SyncDPCM( INT cycles )8 q/ ^9 Q! r8 q/ r+ a
{- X; \4 {; K1 N
        internal.Sync( cycles );
& y, d" u0 C+ h2 i- s( w! z2 g9 N# ~6 }8 P9 P* N9 x' G% S
        if( exsound_select & 0x04 ) {
$ D' m# b- L4 S- }                fds.Sync( cycles );1 e6 b7 S: A: m* D! [3 o3 y1 v2 R# G
        }( ?3 Q: f9 \* ?2 ?7 w  R
        if( exsound_select & 0x08 ) {
& L+ T1 ]( z! u6 L# }                mmc5.Sync( cycles );
; ~% F' P! w9 K& M- M) E        }3 K2 z  x7 y# C, @4 f0 i. H  N
}! x/ n* G. f9 {7 B' R3 f/ k' i
. _- h, T& n. R- f$ w
void        APU::WriteProcess( WORD addr, BYTE data )
6 @4 ~2 L5 y+ d2 ^4 K{
  I0 m: n$ s+ Q        // $4018偼VirtuaNES屌桳億乕僩; c% `% g8 C) R5 ]* R. i
        if( addr >= 0x4000 && addr <= 0x401F ) {
( v- C: I6 e" H* v. p1 L- K                internal.Write( addr, data );2 P0 ^8 H; f& D0 c1 G' `3 @0 Z2 c
        }
$ P0 S: N5 l. x( h1 H6 i  n5 N# O}+ P& o; `# Z  A3 A6 Q* N% H
2 l: ?# v  q8 v# K% i3 V7 ]
void        APU::WriteExProcess( WORD addr, BYTE data )
# J# G+ S& ~. E8 \3 i2 A{( T" w# m7 F2 g3 a% Q
        if( exsound_select & 0x01 ) {
  `- g/ I; W, Q9 H                vrc6.Write( addr, data );  y0 h, Y  t1 N) T9 p
        }2 H  A# s% u! S8 u
        if( exsound_select & 0x02 ) {$ Y0 v: V. F7 ^
                vrc7.Write( addr, data );% i- `" b2 G/ V- O# j( h! ]" [
        }
: ]# k. S# c# N0 P1 m2 h! Z        if( exsound_select & 0x04 ) {
" o& ^' e( F' V! W0 ?& y                fds.Write( addr, data );
8 r, V1 {' k: p% `$ J        }
, A4 X6 \8 @$ _+ q2 a5 [        if( exsound_select & 0x08 ) {
9 [0 D# ?. T; {                mmc5.Write( addr, data );
. N) _  ?7 o0 n% F* T7 r        }9 U# p$ T; L6 }3 Q2 |# g( z
        if( exsound_select & 0x10 ) {
* h: L3 I" e2 K$ p/ w) _                if( addr == 0x0000 ) {
9 \/ K2 u! q# j4 r( R- R' o' L                        BYTE        dummy = n106.Read( addr );( D, P9 T$ E& C2 o' d* m* ]8 @
                } else {5 j- `5 o2 b) h" C% k' C' T
                        n106.Write( addr, data );
! K" @$ c4 M" N4 |" [$ {: r5 R                }& o  X5 I( t5 W6 N; ?0 ]7 H
        }0 n6 D; o' l% |# t, S& ^
        if( exsound_select & 0x20 ) {+ ]8 \% d' {  s' i7 s( a1 @, a
                fme7.Write( addr, data );
. v3 o  }0 X; m" S- g1 v        }. D' K  x3 a" G  M9 c/ C' G
}# J# h6 e8 z* z# M7 q6 f

% `5 j( e7 {' n8 y0 Kvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
" e" R$ \$ s6 E2 {5 ^5 x{/ u4 \* z% f. ^' n) V% U# L7 M
INT        nBits = Config.sound.nBits;, t. n/ v6 j$ q' ^# x% C6 C( S; C2 ^
DWORD        dwLength = dwSize / (nBits/8);
5 [4 |  V6 w3 o( N0 gINT        output;# [  [# k  Z# Z3 u
QUEUEDATA q;2 F1 e& s2 J0 p( v# W& W: g! U
DWORD        writetime;
, D( k/ O# [7 i! U  j% G+ H) p- ]$ B, K2 V+ u
LPSHORT        pSoundBuf = m_SoundBuffer;
/ ?: e9 A4 d6 {8 `! V3 v+ _0 DINT        nCcount = 0;. ^' _2 O9 J% m9 }
1 t# J* L' u/ w4 Y7 r, j
INT        nFilterType = Config.sound.nFilterType;& q; U- A3 n" p4 J

" v1 ^1 A4 _7 a5 O8 i8 p' ^        if( !Config.sound.bEnable ) {& z6 }0 K6 {" ?4 T5 l
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
3 o  p1 `1 e0 ]. s                return;' N3 x0 q% C* F$ k" Z; K5 V; B( L
        }
% E3 a8 L# b) K! v: d4 h4 s& U0 ~, ^5 u4 [! L) h1 |2 ^
        // Volume setup
( f8 J; d9 R+ `( ?+ }        //  0:Master
! O+ l. [- K6 k( R2 @2 Z; |' ?        //  1:Rectangle 1/ l0 w2 B; c/ d
        //  2:Rectangle 2! P& X; j( D; Z: {+ V- ]
        //  3:Triangle7 T. R- l1 ^7 M, \  O5 W
        //  4:Noise
' ^* X0 C7 k: O        //  5:DPCM
% b, K: I& P% v- q' d3 D8 R: C        //  6:VRC6* E) [$ a1 F- H/ ]. w5 D" d
        //  7:VRC7
0 J" p+ O" p2 P  P3 ]. P, D        //  8:FDS
; J5 e0 P; P+ u: [' d        //  9:MMC5' H' [+ T5 q" P$ @' n2 \% h3 k0 s
        // 10:N106% Z+ m& h5 {* C% n
        // 11:FME7" t7 R% k; e. c0 O5 e1 i
        INT        vol[24];
' w9 p3 h% @" S7 H+ F6 U        BOOL*        bMute = m_bMute;
1 t/ Y9 r  |* d$ ~# |5 w& o        SHORT*        nVolume = Config.sound.nVolume;& A1 n# G4 v+ M, q
6 k- B* o# a$ ?9 D+ Y9 X
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;! v0 a" p* P; N9 p

6 H$ Q" R! \6 F        // Internal
0 _+ i- d& v6 V! h- u  o6 I2 R4 }        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
( p. D1 C: [; A$ W        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;2 I/ F6 ^( _" F$ y9 U1 `4 V6 z+ G2 a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;. E3 Q) T; b7 p0 Z# `
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
% I% b( O1 ~1 ]" J        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;4 K: L" I! _# V, f, ]) p

" U: r/ M: L/ S% h$ j3 I        // VRC6
, P0 q" l) Q7 ?2 @# C" D- \        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
# F9 V& F! z$ [" t7 ~( u1 \        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
( f! X' C" R* S/ z8 n        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' [: I3 `2 f7 A4 f2 K
- j1 S. [- N7 t8 t) C1 A        // VRC73 M1 |  j& [: c
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;& p, Z; l9 D% g
* R& @$ d+ d+ _" r( W+ B: Z
        // FDS6 b! g9 s9 j5 J9 F8 g. X
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;1 |1 i- b; i' Y" g; B
7 J: [3 B" @9 n; Q
        // MMC5# ?$ v* c# e2 D- i# _& ^
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
( ~! t4 t0 C: y5 Z1 C2 D/ u5 P        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
, e0 G( |( B$ A        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
! b  k- d, ^$ r4 a. M* q
1 }0 x9 k3 t- G+ F' Z        // N1065 J/ ?7 m% @) v
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 }: |) j$ E* D( W7 \2 [1 v$ G        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 w, o: l! s3 N' e- J# A0 M        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. d: D0 b9 u5 v
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
& c+ n: _  L& [* `/ ^! g" L/ }2 R; x1 o        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
2 V0 E  w5 w. N2 b8 \        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( G3 x( g3 K. U        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
+ Q0 \3 ]4 a8 N' C: P+ t        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;0 _4 I: l5 u8 Z) O

; d& J6 ?3 x) P  w, f- R- ^; n        // FME73 g# \; S0 T9 I( Q/ g; _) T
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  Z3 A- r3 D5 X0 ]3 F3 e
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
9 O* T4 J1 Q3 s" L% @2 T0 K        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( R, |% F; m  }- F0 L
3 e% v% R9 I  F9 b
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;$ e" F2 N& X8 U2 Y- b6 ^
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;6 `7 ^5 ?  `% J

7 Q6 h5 G8 G& ]' w/ W5 w- K; \        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. z: V" ^- t- {4 T* B, v6 L' _
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {7 D. F3 T/ G  m, D" d
                QueueFlush();6 }5 w7 q: x" m/ z: j
        }6 I. G" r+ f/ o% y
0 B9 S7 j! `) _- w1 Z0 K
        while( dwLength-- ) {, ~+ l2 h" V. U0 C$ U. \
                writetime = (DWORD)elapsed_time;' U# u  I7 U, m
' K. ^. s, ]9 h1 K+ N
                while( GetQueue( writetime, q ) ) {: ?+ z0 Y, b2 B1 A( q
                        WriteProcess( q.addr, q.data );
8 m7 q) L& l; g" R9 s                }
. U# d& p- `! v0 R) h' i: ~% B3 q
                while( GetExQueue( writetime, q ) ) {
* `; V$ P7 Z5 O; ~+ f" @* n, l  l                        WriteExProcess( q.addr, q.data );
* M: r+ e* k7 T+ p( p$ i" p, |+ A  d$ T                }8 c+ ^4 G: Z4 e; D

8 k3 i( w7 x- Y                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
7 c0 y; ^, G, \, M' C" g                output = 0;# r6 T! G3 R" s. x. I% f" ]
                output += internal.Process( 0 )*vol[0];
% u, C3 U7 M, C                output += internal.Process( 1 )*vol[1];
% z& r% ?0 D2 j                output += internal.Process( 2 )*vol[2];" X) Z% w& J1 G: h% L' l0 G
                output += internal.Process( 3 )*vol[3];: ]; n+ K! `3 x' M& R
                output += internal.Process( 4 )*vol[4];6 Y( M% N( E1 y" K: _7 a
0 @# P; W! e9 U* V$ X- }& M
                if( exsound_select & 0x01 ) {; `) u0 d6 l: G$ t- N
                        output += vrc6.Process( 0 )*vol[5];: r- {; k. E! [; n  J
                        output += vrc6.Process( 1 )*vol[6];! x' O7 S/ w  q' T+ ]; Z
                        output += vrc6.Process( 2 )*vol[7];3 m+ E9 m- a; ?$ I( s
                }3 @: c" v" D$ J  Y
                if( exsound_select & 0x02 ) {6 [- n1 e" h8 _" H% J
                        output += vrc7.Process( 0 )*vol[8];
9 D( r: |3 u' G! q                }7 }1 [$ t& U7 w3 F( ?
                if( exsound_select & 0x04 ) {
8 }5 U# Y6 u$ |$ g6 J6 w                        output += fds.Process( 0 )*vol[9];
3 ^+ H0 p9 b0 r' k, Z                }
; F9 V0 h' o+ n+ v1 s                if( exsound_select & 0x08 ) {4 {% I: j8 w. R; Q* V
                        output += mmc5.Process( 0 )*vol[10];
: W9 ~8 r- N) r0 S# b                        output += mmc5.Process( 1 )*vol[11];
( }5 }" T/ H* W0 |% w3 M* [- u                        output += mmc5.Process( 2 )*vol[12];/ |' Z. i  h, t+ p
                }
$ V  ]+ e6 o7 m: Y. K! }                if( exsound_select & 0x10 ) {
; M' A% T6 h8 k, k, T3 @& |. r                        output += n106.Process( 0 )*vol[13];
% ~9 N& h" [5 `! Y" C9 X                        output += n106.Process( 1 )*vol[14];
  L% L4 H3 ^% y  C                        output += n106.Process( 2 )*vol[15];3 f1 v2 G+ ~) ?) e
                        output += n106.Process( 3 )*vol[16];, k2 `$ r  H: w1 N- M4 V- W
                        output += n106.Process( 4 )*vol[17];
7 K6 H* _/ L5 z  z& {                        output += n106.Process( 5 )*vol[18];; V/ ^" p# l0 H0 x/ I% D4 C
                        output += n106.Process( 6 )*vol[19];
+ {/ K4 s" D/ ]# Y7 Z6 X                        output += n106.Process( 7 )*vol[20];
6 b- w+ B/ ~& Q! l& R& x                }$ h# p, l$ P, ~5 r3 l) K
                if( exsound_select & 0x20 ) {% B# O7 j; i% ^  i+ K: B, ~
                        fme7.Process( 3 );        // Envelope & Noise
. N" \+ e6 i" ^# F6 F! N                        output += fme7.Process( 0 )*vol[21];
3 z+ L& a$ S8 w8 I* Q3 n                        output += fme7.Process( 1 )*vol[22];
) \% Z8 f* M' }8 ?2 p                        output += fme7.Process( 2 )*vol[23];& b! ^8 E6 h& g! c
                }
8 ]3 y; [/ {; Z# {: V/ w3 q
# Y1 A: d( W: W! p" {; ^/ Z% e                output >>= 8;
/ ?' ?. v6 r, ^# A1 D* F# h) C3 t$ R
                if( nFilterType == 1 ) {
' n; M# C6 M0 K6 g& }                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple), _, z, x% P. z' t+ N( A; P
                        output = (lowpass_filter[0]+output)/2;
5 Z" i; ~& n/ f3 {1 H3 R; s                        lowpass_filter[0] = output;
7 ?  a# D. Z  Q8 z4 O. N4 E: p                } else if( nFilterType == 2 ) {+ Z6 w& l$ s. l  ?6 ~
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
& h6 m) r3 P; G* B4 k                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;& \% c! r( M2 O# r8 J3 R6 c
                        lowpass_filter[1] = lowpass_filter[0];3 b8 r. W8 T. {$ F
                        lowpass_filter[0] = output;5 v9 c* u2 P( i3 a% @
                } else if( nFilterType == 3 ) {- v  |" K+ m. x) B0 O, q
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 e0 _( ~" z2 f  \/ g! @
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
  ^0 X  l+ {+ C4 }. Y. d5 o/ V                        lowpass_filter[2] = lowpass_filter[1];
" J% g) R3 m* O5 p                        lowpass_filter[1] = lowpass_filter[0];% h  |5 Q6 j( p7 |* R  T( d4 E$ p
                        lowpass_filter[0] = output;
! z8 n5 C# x. L  U                } else if( nFilterType == 4 ) {/ z, [; r/ ]7 W0 Q1 @' a
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)+ l. X! C) y) F. y4 Q2 d
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;1 a7 s; y5 u. P$ y7 m/ t4 v
                        lowpass_filter[1] = lowpass_filter[0];: w: l" T) V' G& q, ^# m$ p
                        lowpass_filter[0] = output;* c8 W, h: R7 w, P- S6 A
                }
# g1 C7 G1 y- {0 l5 v+ {. n9 F9 y1 J7 J: \+ \! q
#if        0
' D" L9 M: m9 P" |4 @                // DC惉暘偺僇僢僩
1 O9 r+ Z' D7 _+ o                {
, w- T+ O3 a7 a6 V, V7 C7 S# }                static double ave = 0.0, max=0.0, min=0.0;, U  T( v, ^2 c4 g
                double delta;) y" w. n2 o8 J- z6 Q: o3 }. x* \
                delta = (max-min)/32768.0;
9 X3 [, Z& S. U: O5 Y' I& n                max -= delta;
; P2 N! f. B8 u& {# X" F2 ?" Z                min += delta;3 C9 \) A7 c- N' g  u' x
                if( output > max ) max = output;6 a6 [8 U) s& f, z( c7 @! U
                if( output < min ) min = output;
3 _; m& a( W$ ?* u: g- C                ave -= ave/1024.0;4 D2 {, d6 I6 ~, P
                ave += (max+min)/2048.0;7 _- K& B+ l( w! ~3 H- V
                output -= (INT)ave;$ v  U: |7 X5 c+ N/ h0 B/ K
                }
4 |5 A# d( `7 r: S! e& F- L- n5 E#endif
- k1 q0 Q4 Z4 P" g, S7 h#if        16 g  y+ w# g7 N" q  B8 r# ^& q
                // DC惉暘偺僇僢僩(HPF TEST)
& K1 Q% ~7 K9 {                {
7 [9 P: a/ P% C) k//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
" g4 r$ _# R# k( r                static        double        cutofftemp = (2.0*3.141592653579*40.0);
) X* h8 a8 [1 A5 W2 }9 W                double        cutoff = cutofftemp/(double)Config.sound.nRate;7 s8 N+ H( B7 y" N* F$ c2 ~2 F
                static        double        tmp = 0.0;
8 i! [' k% A7 {                double        in, out;
9 p- U+ q6 J" ]% Z# \
0 F) u- S$ u' O8 s8 d7 ]3 d/ S# k                in = (double)output;
, x& q/ j. l4 \/ `- j. z                out = (in - tmp);
! A0 ^  o& \$ c/ D1 x  G                tmp = tmp + cutoff * out;2 ^9 }- [/ o" U4 N& j

1 L/ ^& m  ~9 ~( ~6 X4 h! H                output = (INT)out;# i4 \+ ]" x  T7 t# `
                }
" U4 A; k3 ]2 L, Q* a: h8 O#endif
/ h' d& l  w1 b' p2 Q#if        0
: O: }$ B. i/ B$ i                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
* p3 @# i% i2 h3 n. f$ H: k0 G, y0 Y                {* Z( D+ b0 Q! j$ X2 B
                INT        diff = abs(output-last_data);
* n4 h) ]7 Y3 c! C  }                if( diff > 0x4000 ) {
9 j3 a0 p* P2 d8 x/ I) Y* b                        output /= 4;* K4 _' B2 q. Y5 h1 h' ]- S- d
                } else
% G% h; V+ \0 F& p4 G* s                if( diff > 0x3000 ) {
* A& ~6 \/ c7 k" i) H                        output /= 3;- ?( t+ p" u* ?3 G" z8 x' J. N
                } else2 `- U" r  t  l! ^
                if( diff > 0x2000 ) {& X7 N5 b- ^6 _: i8 S! O
                        output /= 2;/ b5 u, m3 w8 X3 K, M$ u! ?3 I
                }2 }9 e1 Y  M* h. Y( V. ^" f% Z( ?
                last_data = output;
: P$ z+ f/ d, G9 q* u* S                }5 s& }( g& u( O# p5 i& J
#endif4 _# p5 x$ F& c8 F4 `2 @/ W3 |
                // Limit
5 ?+ q2 t  c) `- Z- i                if( output > 0x7FFF ) {
& C, |' \- A2 Q0 }- ~" t$ b  j                        output = 0x7FFF;0 _- |1 \% n0 ]/ M( c0 s8 C7 s
                } else if( output < -0x8000 ) {/ S# g9 r4 n" i$ z
                        output = -0x8000;
3 v7 f8 u; K  y* o# g                }, ]# |+ i6 x, ?* V% O  c9 m4 w
* x& `2 T* \8 b9 N
                if( nBits != 8 ) {
! o* y. a. I; ?& b! c4 p9 t                        *(SHORT*)lpBuffer = (SHORT)output;  B8 O3 L, F( p
                        lpBuffer += sizeof(SHORT);
8 L5 ~* a- f7 B0 z5 n: |                } else {% b, U: X6 R; C
                        *lpBuffer++ = (output>>8)^0x80;' a0 v$ ?& q: P
                }
8 s, U' e+ _" d6 D( I8 {4 @. A6 J
                if( nCcount < 0x0100 )
7 n- L6 D5 W3 z1 j. n6 T                        pSoundBuf[nCcount++] = (SHORT)output;8 f' {' n2 Q+ w( \
$ `) K5 x4 m8 z& [1 N, h+ ], T
//                elapsedtime += cycle_rate;* r' [1 l9 y9 c/ f9 U
                elapsed_time += cycle_rate;
0 [2 g$ A. D, @3 H8 U        }0 m6 w- D4 P" t0 h

$ m5 [8 S1 w3 R6 O: ?/ h#if        12 q2 c6 u) a* }5 f
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
% O* N+ z5 `1 z! `0 m  x                elapsed_time = nes->cpu->GetTotalCycles();+ Q* X* h" p  K
        }
2 f6 O( i* e* B5 g* D        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {: c. i3 Z. e' k  C& l2 j
                elapsed_time = nes->cpu->GetTotalCycles();
' q/ s% h- P7 H7 L) E8 l5 B        }
# t/ I5 H- N) q( N7 U! `, i#else
' @( }6 U, w) @# ^: w& l7 V        elapsed_time = nes->cpu->GetTotalCycles();8 i; R- O, H3 r  G) o8 j
#endif9 B: s) a- H# W" ?; Z
}
, e4 y6 ~/ g  k
3 |" w# a9 x* B* x) _' L4 e// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
" T( Q: Y* ]% _INT        APU::GetChannelFrequency( INT no )& {3 t" v; ~  `1 g
{, f& b; C% K  \: y5 K
        if( !m_bMute[0] )- c6 y! j3 m4 u3 Q( g
                return        0;
" a% \7 h2 J% b" P0 Z( K5 O, r/ I1 [3 A; A0 D7 p
        // Internal0 {! l; o% q/ O7 L* \! i7 V' n
        if( no < 5 ) {' I3 E5 J) x1 t* `- ~9 S+ I
                return        m_bMute[no+1]?internal.GetFreq( no ):0;& ]' H9 V8 y' N6 _3 Q) y5 r
        }5 [1 t9 h; [$ J. J$ z
        // VRC6
; F# q5 d/ ~! [7 g2 h! W: V( L2 Z, R        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {0 _) L8 m8 r9 j  F
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;$ k- [1 m# m0 V7 H' w7 q0 i2 a* ^& p" j
        }
1 w1 e1 T3 J* i: m/ G        // FDS
) {/ m5 J$ }- E9 V+ o& W' f        if( (exsound_select & 0x04) && no == 0x300 ) {, u$ r( S, S: m, k2 m
                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 q! S$ F& X' d
        }
0 u) m) F$ Z9 \- Y        // MMC5
0 a. p" v3 B, G4 P        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {1 U- u4 W5 W. P4 C2 X6 K" q
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
$ a- D( ~  }/ J( L        }+ n2 L7 R% N0 H$ Z& L
        // N106/ A. k4 ?, z4 F- }! u; d
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {1 P+ a" ~- Y1 U3 C/ B# A( r6 }
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 c( s- C) i* M. Y, D2 ?
        }
" r4 G# y# ?/ `, O! n# {+ ~        // FME7/ G- P5 p5 F! \6 |& ?3 d: [
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
8 x1 k9 N+ [8 \3 j, x  O/ U                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
5 K( r7 \1 I+ F. T' k" R- w6 `        }
; f* D. v" ^2 x* }% }5 {        // VRC7/ {( E8 T) |9 G3 ~- t) k
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {: y+ l4 l- b  }9 E9 w. _" g) d
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;+ @; [) W0 f$ o" A: B% S: R6 K
        }
1 M0 A$ K, z0 A# {; d3 X+ u- T        return        0;* P; P4 ~: H% i8 M4 K8 y/ M0 j/ J
}5 j: D8 a  `# A! l: Z1 i

3 r7 f1 _: u$ C8 z5 n3 |// State Save/Load( `; |- S$ v* m3 W3 t
void        APU::SaveState( LPBYTE p )$ A& w9 R* p9 K# F8 a9 b$ m
{
4 W+ h2 y" K( F. Z; I. f$ f#ifdef        _DEBUG* ?0 v* t5 H- W. ~7 Z' O* p, j
LPBYTE        pold = p;; r: ~  c' Y3 P, w
#endif
& R0 I2 o+ Q% ], Q) X. y" [! m" |$ n7 d" ]+ t( d  j6 {
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞5 T8 _' I; Q6 y9 w+ e. |
        QueueFlush();
) C/ b; {' g5 Q0 l" J, O& B/ t, B' n& g4 R  u+ }
        internal.SaveState( p );
0 A+ l: ^$ R# I( f% y% X& S        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
! M. S' V4 q6 h& z2 l! L7 C
/ S( |4 W. V  o) P; [        // VRC6
! y6 J3 R- {; [, x" t        if( exsound_select & 0x01 ) {0 v9 f$ C9 F6 M. F" a6 h
                vrc6.SaveState( p );
, N& R2 j$ s" v  M9 \' ?                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ a) {7 A: Y* Q- b. g# m
        }! {" {$ K  h! R; C! l- C' Z
        // VRC7 (not support)
5 K, @4 r  P; {# ]3 e7 E* J3 t4 L+ [& s        if( exsound_select & 0x02 ) {9 k! n2 {+ _3 _3 F' Y0 J
                vrc7.SaveState( p );
* Y# k) {* X3 k) \$ M                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding# u; K: ~; o( u" \( E4 A7 D, S
        }, Y' U9 @" t! h
        // FDS
7 U, r7 {. a- Q& D( \7 J: D        if( exsound_select & 0x04 ) {
' i' |0 s; K# T. @                fds.SaveState( p );3 e' r$ Q$ R+ y7 E+ D( S1 |
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
! j3 b3 l; x1 J+ M        }
6 W) j% m4 e  j8 |        // MMC5/ d& F2 u1 w3 z  F
        if( exsound_select & 0x08 ) {
4 p# r: Q0 j( F# Q8 @                mmc5.SaveState( p );
5 \( B4 r5 B& {' y1 v: p% m, n                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 r" ^  K7 w: }8 F        }& |- }: l- L4 \/ L6 x$ U# A
        // N106- h( {2 C, ~8 e
        if( exsound_select & 0x10 ) {
) {% I' z' f% E1 H6 m                n106.SaveState( p );
1 c5 f4 ^- p% M  q0 y; s7 n1 M- W; g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding' j7 _* U, q6 m# m, s0 O
        }
! p! k! Z9 |; M) d3 _        // FME7" U3 [0 @, }9 f( |" |3 S
        if( exsound_select & 0x20 ) {
! j$ ]/ _" y2 E7 y                fme7.SaveState( p );' o  z3 _7 Y/ g! p6 S; [
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
" D$ m' i) i" ]& u' N4 C5 Q4 l        }/ ?! L' H# E" I) ~* h

" |7 |5 _$ W/ a$ a#ifdef        _DEBUG
! h4 Y. H0 y' RDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
# H, y$ X5 Y7 A) U2 s#endif
# J- O! P2 ^0 ?4 O9 X}( @& P. {6 S" Z" B
! e6 |2 d: y1 s! b' n2 m" B) V9 C/ t
void        APU::LoadState( LPBYTE p )% Z6 e( q% h- D/ ~0 q) q
{2 u3 e; l: h8 Y+ ?: _. Q5 w
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
  E( Z3 p% i4 ]: @' w9 J        QueueClear();
9 d+ A' e+ t1 I, h* i0 W1 o! g8 t) R; r# X+ C
        internal.LoadState( p );& n9 N2 {7 F) t6 ?" t
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( t% x% z* N$ D
, v' q& w3 l) A: S" _
        // VRC6* I! J! e$ c, N/ A9 a7 F
        if( exsound_select & 0x01 ) {" `" g4 F' d. }8 j: x( M
                vrc6.LoadState( p );0 {! Q. K" f* D1 d. z, h
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding+ D$ V# D$ ]4 P0 W5 [9 X" n3 q
        }
/ L7 ^3 r* J% V) D& l( i7 I- W3 v        // VRC7 (not support)
" N' ~5 R5 Z5 d        if( exsound_select & 0x02 ) {! T% x% Q* v' j2 L; u9 U6 w& c
                vrc7.LoadState( p );
# \3 O# j( H4 F# \4 g) u! s  r3 c                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
/ o  g- O) s; l/ [        }
' A, \  c3 V( F6 d1 ?        // FDS; t; [" I2 Z; u& f! x/ r
        if( exsound_select & 0x04 ) {1 |2 T; R" f% j
                fds.LoadState( p );6 ?( P, G( m1 r( H& o9 P
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
, d; a3 @* J8 Q5 T        }* \6 q9 }6 I$ ^
        // MMC53 K8 k6 C* H9 X$ @' h8 N( u
        if( exsound_select & 0x08 ) {) b3 U! ]# a. l8 Z
                mmc5.LoadState( p );
- i  @: Z! Z2 ]" b" I/ G                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding8 }3 S. X% b( ]7 C
        }
+ J2 ^  Z. s' C  V        // N1066 P5 g; N% ^1 F' |
        if( exsound_select & 0x10 ) {
1 s8 o1 X" z6 r  i. C                n106.LoadState( p );
9 C, K8 r6 Q* u, \5 s/ ]                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( M" Y( X" }+ e& w: d# g% |1 {        }/ C$ M9 W; k7 }
        // FME7- a1 _% B5 R+ i* r
        if( exsound_select & 0x20 ) {
) L2 h7 S" A2 J% y1 B& ?3 P( e( I                fme7.LoadState( p );
  Y  W+ ~- m% ?- B, P# I$ A                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
7 i- R1 y9 n# ?/ n6 K; w7 k        }$ w+ S& z- s8 Z6 F% C
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
; X6 b8 B% u- m( u! o) C可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
# ]3 K# Z4 d" K感激不尽~~
! D* S, u8 v/ C
恩 我對模擬器不是很有研究,
# }1 t; v- t0 c8 _5 [3 i9 a雖然要了解源碼內容,可能不是很困難,6 n' f) {% k4 N& f8 V( r* ]5 z- {
不過還是要花時間,個人目前蠻忙碌的。
6 A% J1 Q: T" ?; x- C' G, ], I1 B7 Q& W/ C% {
給你一個朋友的MSN,你可以跟他討論看看,* d, I* d* I8 ^# o$ h" v- d
他本身是程式設計師,也對FC模擬器很有興趣。
( _' i+ _7 i5 P0 q8 h$ D7 j$ R
" y5 z+ S5 b3 a) ]3 LMSN我就PM到你的信箱了。
) f8 i- w3 r4 ^& ^: u( P
. T% G( Q0 T" A& a5 h0 x" p0 T' L8 S7 {希望你能有所得。

该用户从未签到

 楼主| 发表于 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- E7 c( }  p4 Y6 Z# A
呵…… 谢过团长大人~~
+ B+ {$ i5 |+ {7 Q% c  ^7 o( I
; g1 c! Q! I# L3 h* f
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 + K4 ?* X$ c2 ]
团长的朋友都是神,那团长就是神的boss。

# ?) ?, }% [# d1 z哈 不敢當,我只是個平凡人,
" h8 q9 ~) z( t" O6 G' Z. {- p要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 N" {8 @& N' r" a1 g) }ZYH/ P) b' n) F+ W" F. e3 f
QQ:4147343067 f7 J7 P) a+ Y& V! H
Mail:zyh-01@126.com  C" r( ]! C2 O0 ?+ J( T
6 L: q# c, f7 k$ F, y
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 0 U2 ?* ?0 h9 \' U, S% Z* e
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ p/ U! U# _/ @7 T. Y: B
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-21 08:53 , Processed in 1.098633 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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