EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ @) l" ?& Y( q6 I, p- e2 H+ |
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 Y$ H! n1 ]+ W5 j
这里有相应的模拟器源码,就当送给大侠了~~! @! {: Q* K' x) o( H6 F+ H: A
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 6 `; J; G: H8 y. Q8 y1 F  p* m+ U
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ D+ B3 b& {' Z) ^" N
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~% o' n3 e7 F6 \6 r5 g- f" H
这里有相应的模拟器源码,就当送给大侠 ...
  p. ^0 i/ f2 j) n  V% I" N( O
聲音部分(Audoi Process Unit = APU):
2 [& _# b' m! H/ U0 O; C.\NES\APU.cpp, E8 ], c% N2 v. c4 T3 K* \
.\NES\APU.h
6 A+ c- E! g/ Z% D, }% v  A' ?
! c+ ~# e3 X5 u
" N; A: @3 I! r/ }影像處理部份(Picture Processing Unit = PPU):) E1 g' h8 Q# W. z( f
.\NES\PPU.cpp( X. P. i) n$ A8 k
.\NES\PPU.h
0 p/ w+ M( `' U- u0 R% j7 B& u( [; \' w+ G
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:5 C( s! u6 B9 U  K- z; g
(由于很多专用术语和算法机理都不明白,所以看不大懂……)5 r  R2 }9 b! I+ O
//////////////////////////////////////////////////////////////////////////# \4 `, R( V% Q8 C
//                                                                      //
4 a- v; j, \3 W) x2 J4 ]//      NES APU core                                                    //
9 t8 z5 i5 j' |+ k5 m# V3 U//                                                           Norix      //" ~: c) I7 B8 w) i6 U' m% r
//                                               written     2002/06/27 //
: w; M- K% z( F* j" M//                                               last modify ----/--/-- //2 D1 A0 v% D6 F7 p
//////////////////////////////////////////////////////////////////////////
: T- S6 L/ w: b" L. Q6 [* W#include "DebugOut.h"5 F! x+ U' @+ b' P6 K
#include "App.h"
3 [& y. y8 S; w* E#include "Config.h"
- [* X# C* P/ X2 ]  h3 ~+ G& S9 ^" y0 q% U/ T" q$ M4 o* I
#include "nes.h"
2 L5 I, b( r8 M' r0 |  X#include "mmu.h"- l6 W, ?! ?0 T' V
#include "cpu.h"
/ W* K( s$ j! B1 O#include "ppu.h"2 m& N) X% z" z& X
#include "rom.h"$ h  N2 Q; `4 D6 l" A1 @
#include "apu.h"2 ~# M( F" z! J( G5 \; a" v4 K
& w2 ]1 K. R2 v$ P+ O
// Volume adjust0 [# ?5 Y8 A8 ~' d4 v, H
// Internal sounds
% ?9 e; l- \2 q#define        RECTANGLE_VOL        (0x0F0): V! P  h# I5 R! l( M9 {  M$ R/ o6 J
#define        TRIANGLE_VOL        (0x130)+ t' I- y, M# |
#define        NOISE_VOL        (0x0C0)
( Z* c& J  }8 ]4 N6 }#define        DPCM_VOL        (0x0F0)) n1 y0 N) R/ M! g3 _
// Extra sounds0 R$ c  n& s, G0 m0 P3 y/ v8 a! l
#define        VRC6_VOL        (0x0F0)
$ j$ O0 ?5 d9 a3 F#define        VRC7_VOL        (0x130)" }2 u. x) @# h  p
#define        FDS_VOL                (0x0F0), w2 Q* n6 A; ?' k
#define        MMC5_VOL        (0x0F0)1 R' u- U; K$ {& i4 b/ r
#define        N106_VOL        (0x088): P& D1 J8 H9 Z
#define        FME7_VOL        (0x130)
+ Q# t( R: d7 Z" n% Z! D
4 E; \- Q8 z7 I. B3 f) L( w0 OAPU::APU( NES* parent )
* D  r3 M5 {: A; _( J{
6 h/ T* f' Z8 f9 Y  @' X        exsound_select = 0;
7 i7 S; Q2 G' k5 L( {  R% P6 C7 `; n2 P/ R6 [9 W' M  b" S
        nes = parent;0 z. @2 M. u4 q6 _7 ^4 f1 D
        internal.SetParent( parent );, P: m  ~( X6 m% P' d( R2 a* v

& w/ J: `/ A$ @5 E% }        last_data = last_diff = 0;1 l. w2 {8 O' o; A
- v  k4 D3 _$ T: S
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
/ ^. W) Y9 i) j" T; O: O8 U) X7 |: n* U
! n3 K8 U' l; x        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
$ M* g' H7 I' T" s        ZEROMEMORY( &queue, sizeof(queue) );
2 K; Q7 D3 F" P2 B        ZEROMEMORY( &exqueue, sizeof(exqueue) );
( s6 `& ], {( Q6 ^; s4 W! y" l9 P) {& _; S) t. d
        for( INT i = 0; i < 16; i++ ) {* J$ X3 s9 j9 j: H( \: N
                m_bMute = TRUE;8 B3 f5 h5 t+ v4 _: j
        }
* o) U! s% n) F}% Q# n5 w" A; ]( k4 r6 v
5 m) _7 V2 O2 F( u5 y3 V& T( u( ]! I
APU::~APU()1 V7 a# q$ W8 m4 u+ e6 v% c$ B
{. z3 ^4 U/ T+ B9 M
}
: }' w0 }, m: {; y7 Y& K
+ W% _) x; q( d" P2 B: Tvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
" _0 Z$ N" V, o$ t{
8 i2 N1 |6 K( C8 k        queue.data[queue.wrptr].time = writetime;
$ }0 C8 V  z7 x        queue.data[queue.wrptr].addr = addr;! O0 D: d6 \9 I0 c0 U) ]; r5 u
        queue.data[queue.wrptr].data = data;1 ^5 {% g: H. ~7 k2 p! ?
        queue.wrptr++;
2 B4 D& U3 h$ f4 k0 d4 q1 N! I        queue.wrptr&=QUEUE_LENGTH-1;' N7 k1 z2 l0 ]! y
        if( queue.wrptr == queue.rdptr ) {
* D# k6 w$ I7 P                DEBUGOUT( "queue overflow.\n" );
9 g1 O7 z. X4 S, H0 `( ^        }
' P" a/ O7 x  s  V}
# v9 Q9 `- T6 }* P5 d; ]% J  D6 i( ^2 g0 ]0 g
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
: ^+ c+ Y' ]+ t$ ^( ^5 d+ I0 ^; m/ O2 b5 B{# [# u" m7 N% R' i5 P
        if( queue.wrptr == queue.rdptr ) {
0 S! `" Z0 e2 g                return        FALSE;" [, V5 [$ M' N6 j' s
        }
0 N: O1 d; F1 [2 q0 v7 I6 p2 a7 c9 @) W        if( queue.data[queue.rdptr].time <= writetime ) {) U1 P# m# h2 v# |& t1 I# [
                ret = queue.data[queue.rdptr];
6 }! `7 i4 R" m1 }# V( i                queue.rdptr++;
1 T9 Z; g; ^# x3 L  X                queue.rdptr&=QUEUE_LENGTH-1;
( f9 e* [! A4 f3 K3 ]8 a  B5 l                return        TRUE;
& [% ?1 x8 `- Z        }. r2 q, [$ c1 M0 N; b4 t
        return        FALSE;4 S0 f- f  E" o3 P9 ?2 E
}" B4 [9 d6 W2 u) _( Q

7 y) U, x$ V+ g* ^# p* b" avoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
* \7 Q1 z# P" n$ l/ |, c) O{1 }( r# E8 X' V6 y% N
        exqueue.data[exqueue.wrptr].time = writetime;
9 ^' s7 Q8 C( l5 x/ ?: P, n        exqueue.data[exqueue.wrptr].addr = addr;
  J0 ?  R# q7 [0 }0 r( g7 a6 c        exqueue.data[exqueue.wrptr].data = data;7 s4 K! P& k  s& s4 p! l3 N2 h5 C) B
        exqueue.wrptr++;
$ e/ I" M- A* [/ F: t4 h* H. L# D        exqueue.wrptr&=QUEUE_LENGTH-1;
% T/ \; @% e0 ?# v9 v6 c7 Z8 C- u        if( exqueue.wrptr == exqueue.rdptr ) {
, Z  a$ k  l" q$ q) m: [; w                DEBUGOUT( "exqueue overflow.\n" );- m: R! h9 y& m6 S1 H; s7 u
        }3 [8 h7 e( I8 Q& v2 k' ^! B
}
/ Z" a& _5 O" n5 H, x/ i" z2 q9 ~
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
6 Q" N; ~/ h' F6 Q{. E; U$ n% d# Z% b# Y
        if( exqueue.wrptr == exqueue.rdptr ) {
6 q8 M4 i* R5 w1 f# J3 K                return        FALSE;
# S' G+ ?. m, u" J' {* ~        }
9 `* P8 e1 @5 s' |& q, ~3 u" p        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
6 s# c1 [, s  H                ret = exqueue.data[exqueue.rdptr];
9 n8 a6 Z+ _0 ^& G: Y) h# h                exqueue.rdptr++;& Z4 {# R* M$ X5 p7 d. M; r
                exqueue.rdptr&=QUEUE_LENGTH-1;7 Z- a' H& q& o2 `
                return        TRUE;
0 }- ~* T. `. ?2 G+ }        }8 a1 e7 ?/ ^1 C  K4 o) \6 Q
        return        FALSE;
: z$ H, \, n: m1 ^3 Z1 r: a}
1 T; p7 g2 ^+ {3 M3 x1 J
, N! N( o. W5 H* h9 x4 Tvoid        APU::QueueClear()
6 J' S, F$ x7 p' t% a/ z2 I! s{
: X) g6 w% }9 S8 c        ZEROMEMORY( &queue, sizeof(queue) );4 Q4 k$ \( C% @8 e& u* X4 K+ Z! |
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
4 s- |2 H; d1 j}3 H/ B7 P/ ]" m( s
* P1 l6 u# C3 r# B" i7 {
void        APU::QueueFlush()
* {3 s8 I" i) ]5 N6 y+ L{
" A+ n% K, o1 x        while( queue.wrptr != queue.rdptr ) {
7 F9 m; `, S0 X. G, k6 u                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );/ t" m4 t3 H8 m) C! X
                queue.rdptr++;
- b7 Z/ h9 [% p: D! Y                queue.rdptr&=QUEUE_LENGTH-1;' X6 L4 @/ q% h: P0 |8 c" j& w( |
        }9 a, x5 s% a5 R; a8 k( b) d* B/ G
/ ?" ?! E5 s: j% x; S
        while( exqueue.wrptr != exqueue.rdptr ) {
, r/ `0 O2 s5 U0 w/ u! |( a                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
& |" _, k" A7 _/ a( r* j                exqueue.rdptr++;
, i# _( w7 x9 _$ g- o. A                exqueue.rdptr&=QUEUE_LENGTH-1;
9 y; E& z9 J; _! X: D        }
4 \. m- S7 T$ x1 Q8 S}
5 @& Z  Y% q9 t2 m  [! H, V/ v) Z2 D  D
void        APU::SoundSetup()* X5 ~( S) V' D9 B" W2 |# ?( H
{9 K- |6 B  n6 K5 b( f; D0 c
        FLOAT        fClock = nes->nescfg->CpuClock;
; B- K. S/ K& A  m6 w% g- w( j        INT        nRate = (INT)Config.sound.nRate;
7 s* S$ q& b5 p        internal.Setup( fClock, nRate );
# {+ A# C. {% S- F( V0 F        vrc6.Setup( fClock, nRate );
* G) h7 [6 T- O+ z. F        vrc7.Setup( fClock, nRate );
; P8 i  b7 s2 p2 H# q        mmc5.Setup( fClock, nRate );4 G# ?, J' p4 ?
        fds.Setup ( fClock, nRate );
, x; M  w% z# a. c        n106.Setup( fClock, nRate );5 m/ V' m7 ?4 h) w! l' W
        fme7.Setup( fClock, nRate );
1 S: I4 a4 M) A' _}
5 w/ V  q* G' O9 Z- c: }8 U2 A
0 P' t3 h/ D& x1 a3 Q% }8 P/ vvoid        APU::Reset()- z, s- M5 @9 y9 p. F; G
{
( ^* q. s5 t9 }6 u% M        ZEROMEMORY( &queue, sizeof(queue) );
7 B4 M( G% }1 _7 t; r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
. R2 |1 A3 {" o: E. A: Q6 _' c' r7 ?- @  D
        elapsed_time = 0;
2 h8 B7 K+ }/ h& \& c9 x0 Z  m8 N# Q
        FLOAT        fClock = nes->nescfg->CpuClock;7 o  k" A+ w4 ]# y) Q, o3 t# c
        INT        nRate = (INT)Config.sound.nRate;
* `# Y4 _0 p; g$ g$ E, I% \. l        internal.Reset( fClock, nRate );8 u: z# a8 k8 u/ y  X! @) Q, Q7 \
        vrc6.Reset( fClock, nRate );! i% O  }: g6 j& }9 k3 @- V
        vrc7.Reset( fClock, nRate );
" U# k/ e8 @( l1 a' E, Q        mmc5.Reset( fClock, nRate );# ?& \6 i8 j& v& I
        fds.Reset ( fClock, nRate );
  H* E1 u1 U, i/ f6 S        n106.Reset( fClock, nRate );' x' T) Y: W# u# o: Z
        fme7.Reset( fClock, nRate );
% @# B/ i  Q5 N6 ~" M7 k. ~: ~* C' G& c! z8 ?1 t6 v
        SoundSetup();0 |1 f3 C1 r$ v1 [
}$ g  A" J" r( n

  e+ Q' f  o2 f, J2 N; P8 Jvoid        APU::SelectExSound( BYTE data )
$ r; `$ T. L9 S& d: |8 ?6 A{* C) Y% s- x. V) u% m2 e4 f
        exsound_select = data;; p, [5 G  C+ H: T" W$ f) D
}
, P( R+ N7 i- h# B/ @$ D
( ~: K* m6 b9 P' D6 e) D9 S, _8 S6 u; ], ZBYTE        APU::Read( WORD addr )
3 {0 k9 k5 u* x{, P% S5 S0 @% H
        return        internal.SyncRead( addr );
' @" W  O4 @; I}5 |* i- X  }( E! }- z# }
+ q9 ?) z! J% |( T. Q2 o7 J
void        APU::Write( WORD addr, BYTE data )
0 K7 O" W) M, E/ r3 k{
  M7 ?. ?, Y: {        // $4018偼VirtuaNES屌桳億乕僩
# |7 M8 b. T' ~% w; V, u) \0 H3 h! G        if( addr >= 0x4000 && addr <= 0x401F ) {9 t& E% n5 W; i: o: R
                internal.SyncWrite( addr, data );
7 [2 ]& q3 p/ P/ P5 O" T2 w& S. j                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
$ Z+ H- K: V  u) v6 d3 K& _        }
+ O4 K3 P: Q  p4 Q" m/ R5 q! W}3 c$ O% e& T3 P4 K8 U' B

5 G  }: t  S, mBYTE        APU::ExRead( WORD addr )% F2 L# G' Z8 L3 W: w6 v' [( u
{
  a! N! H& I' {BYTE        data = 0;
/ O) Q; s4 }, g
. e; L2 z" d% s% S7 A        if( exsound_select & 0x10 ) {
: l, U5 ?- C+ e, ]1 ]6 M. Y                if( addr == 0x4800 ) {" A. @% E: u7 d& V* c; F  K
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );0 b/ v/ N4 a) X6 }$ Z' [
                }* Q  f) ]6 T  x2 Q+ g) j" h1 i
        }
' q& J9 v; ~( J, L" ?0 E( X0 \        if( exsound_select & 0x04 ) {- x4 e5 n8 r3 Q, U
                if( addr >= 0x4040 && addr < 0x4100 ) {
/ i. g, `+ |5 Y2 z; H! ]3 o7 P                        data = fds.SyncRead( addr );
6 v0 @' t! y+ k( }9 V; H                }
! p1 K8 u1 e: L1 S/ T        }) I9 H! N: D$ L$ P- ?  m; j
        if( exsound_select & 0x08 ) {" ?% t8 ~& e& [' }1 T
                if( addr >= 0x5000 && addr <= 0x5015 ) {
* o2 k% |( o  g! p5 G9 V7 H3 `; g  L/ G                        data = mmc5.SyncRead( addr );
* i* V& {+ O; U& z. C                }9 E  P6 r  Y; y( H
        }: I" u7 i* \; q* }  q

" |6 P; \. R/ m" p- y- o        return        data;; r" ~0 U# O/ L$ q; ]
}
: l$ u, H/ `0 w& q. t. Y( m! q: }) F9 L, e+ P$ K: A
void        APU::ExWrite( WORD addr, BYTE data )
3 g7 ?, b$ k( T# k/ `% y8 a{! o, k7 A1 E5 {
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );  v' I/ O' n- h! z7 j
5 Y8 m, M0 p, t& G# M
        if( exsound_select & 0x04 ) {
0 t) I; ]/ m% \1 }/ X7 {                if( addr >= 0x4040 && addr < 0x4100 ) {
6 b4 V+ t9 W4 F2 \                        fds.SyncWrite( addr, data );9 e! G- G, J* J6 F
                }
% E- L$ `# g" N        }" A4 B+ E  [, a7 L4 t5 |

/ j7 p  G# u2 Q; l" P# s$ ^        if( exsound_select & 0x08 ) {' g- z3 \, J# H# K( G* D9 b4 ~
                if( addr >= 0x5000 && addr <= 0x5015 ) {. O+ k* J* h3 f8 P8 A% m& V* d
                        mmc5.SyncWrite( addr, data );9 _/ N( p: u7 O' l$ \, ^
                }4 s) M( m3 ^" I
        }2 [. @+ Z- D" E/ V
}
2 d1 ]& O& T( S0 G( r5 k- T$ z4 n& p7 G* m: t. w/ G0 L4 Y
void        APU::Sync()
2 Z: J. F3 D' t* F" S" f( R{
- D/ @  A' E* \) `  |; I; ?& G}
# l% B( n, l  H, `
# U) H, v1 B5 z* rvoid        APU::SyncDPCM( INT cycles ). t( I: J$ t$ y" R8 w) ^
{
1 b2 l0 Z0 M, V) j$ j1 E( l        internal.Sync( cycles );8 ?& P* g/ g% d" p2 E5 M$ D
) L7 b  V/ @6 b; e
        if( exsound_select & 0x04 ) {
/ q5 m1 c9 ^' \" m. V: B                fds.Sync( cycles );2 Q& |$ Q3 ]9 w1 I
        }& i5 b8 Z4 J8 A6 B& }
        if( exsound_select & 0x08 ) {  z/ b1 l3 Z7 P  A/ T9 I. b4 [$ u
                mmc5.Sync( cycles );7 L) n9 z9 d  u$ v3 _  d
        }. X& R5 H. ]7 p; ]( j9 M0 |! ?
}3 l! j3 Q$ W! Z! B6 M# X
' a' n1 ?! W5 }, Y/ d$ T2 h
void        APU::WriteProcess( WORD addr, BYTE data )
) o6 ]  \! k0 ~; Z( r# f{* N& U( }  d4 z! a3 W
        // $4018偼VirtuaNES屌桳億乕僩
8 X- Q- S; k1 C! [: n" p5 N        if( addr >= 0x4000 && addr <= 0x401F ) {
3 h% p5 h$ i& A6 t                internal.Write( addr, data );
: G9 x# m: ]' a/ y8 z: w6 T        }! i$ r' B- M8 D! d! l- T
}
4 T7 r& h# C+ ^" G  Q7 _& D3 ]& g. M; o
void        APU::WriteExProcess( WORD addr, BYTE data )
9 t# D5 g( O  G( I7 N0 [{
* W4 o: Y8 {8 o: ?# x1 M2 Z        if( exsound_select & 0x01 ) {
+ w% b9 o0 m0 p- i                vrc6.Write( addr, data );
$ h* [9 ?8 e, \/ c0 a) q/ [  _1 u        }
7 B5 m9 I1 T  i        if( exsound_select & 0x02 ) {
, }! D3 d7 C/ c% I                vrc7.Write( addr, data );% c8 A( ?2 G3 ?: ~, ?5 x7 J" k
        }
! a' u$ L2 ^$ [( w) }/ E6 e0 k4 A        if( exsound_select & 0x04 ) {$ [; j! n: H# C
                fds.Write( addr, data );
6 i$ b7 y2 J1 z. A" Z: k3 Q# t5 E! |        }. q' L7 Q1 q6 f3 w" O  }1 T
        if( exsound_select & 0x08 ) {; C- @1 S* I' v6 h0 o$ c- b
                mmc5.Write( addr, data );$ H# f0 i6 L& P5 Y# d
        }) E1 I- o! n. P2 \5 J7 R4 \5 k9 f
        if( exsound_select & 0x10 ) {- j  U2 W% Q; Z5 F  j- _! b
                if( addr == 0x0000 ) {
" @+ s* B( K5 t" _/ P8 _8 l- Z& @- _                        BYTE        dummy = n106.Read( addr );
+ w# u8 i. l1 d1 B2 r                } else {
5 R% k  Q, N5 {" E                        n106.Write( addr, data );& _8 k) T: |7 W1 e
                }, E. p+ Y8 w# i6 s' R0 v5 S
        }  b2 ~2 k4 J- X9 w/ ?7 u. b  d
        if( exsound_select & 0x20 ) {
4 W4 W+ o! Y' ^- e+ Y1 C3 M8 y+ s                fme7.Write( addr, data );* H3 _4 A9 z5 g3 g' }
        }
4 u# A8 G8 b& u% ?}
1 b( X+ X  r! `: v  D, b9 p/ Z5 W
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ). g' L; d' K5 ]5 A
{' W5 ]7 G% V0 @4 e# d! m2 w
INT        nBits = Config.sound.nBits;
( r1 D* |& A+ i9 KDWORD        dwLength = dwSize / (nBits/8);( G: c( A) [& t& K: `- L9 e3 |
INT        output;1 e3 K. ?7 O% |3 G1 Y# E: F; P
QUEUEDATA q;
; T: \8 W3 A- ?6 RDWORD        writetime;& x1 T( r9 r/ x

' b# D$ ~# r- E: ~3 o6 V" kLPSHORT        pSoundBuf = m_SoundBuffer;0 f) o. R/ @* T7 Y4 c; L
INT        nCcount = 0;
+ N0 y$ i. k& v, o, {- P# d/ d3 O- p& r( ^+ c1 B
INT        nFilterType = Config.sound.nFilterType;
  E: b5 |2 b6 J( W0 }' r9 e5 J% f' g
        if( !Config.sound.bEnable ) {
* R4 S7 S# `$ K( D5 C3 |. f                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );8 p3 G1 b2 Y9 r- T' x. p
                return;
: Q7 U! `7 Y/ w1 b* h' @        }
( E1 z, ?% f  [/ }$ _' p7 U* b9 w5 r; a+ s2 r5 Q
        // Volume setup- L" B! G! ^# W
        //  0:Master
7 P0 c, ?% g0 N; R) q' w  K* r5 \        //  1:Rectangle 1
1 ^: S- [1 x$ n- [        //  2:Rectangle 2
7 i4 x/ p' A+ C        //  3:Triangle
. {1 w# X7 `5 h        //  4:Noise
3 M6 ]0 h1 M; k: j7 t% F4 m        //  5:DPCM8 ~2 X* E. Q& @$ c' C0 x& g
        //  6:VRC6" o7 x4 ?9 h% Z& j" l
        //  7:VRC7
# p9 O+ W7 G" N2 p" L% E2 t        //  8:FDS3 D. h. B( D. j9 T" O' {7 v" f/ x
        //  9:MMC5
) V2 h+ L- u: s9 L0 ~        // 10:N106" c0 q3 q, m9 K; p
        // 11:FME78 n) _0 Y; E% p2 E; K" x& M  L
        INT        vol[24];) l9 g; G+ r) j8 r
        BOOL*        bMute = m_bMute;$ D# x, N( [: _  K
        SHORT*        nVolume = Config.sound.nVolume;0 f; q' M* Z* t+ L3 O. e0 h
6 s2 d- `$ B2 ^( r8 o
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ t2 O8 V: t) `8 O+ F' I
* c6 `% g) V. X        // Internal! A  v  l* P* X) t& M2 \
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;/ `4 W$ Y" d3 k3 Q( {2 O6 \2 D
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
: U% g* \% E# D4 P        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
: H! w! V9 J  ^2 F8 ~7 ?        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;) U) X: m* N4 B0 Q) ~( D
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ j8 E9 s2 n: h9 X0 q( z

% c* x' k/ h' L% l        // VRC6- t# n) L( \6 l6 p
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;1 o; T: n/ R- P, E
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
) z& q# p6 Y; e; B" T        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;8 e. n) {4 q3 \! o5 |) G. I

0 z2 G7 B6 ?$ k) c) `$ L7 {        // VRC7
  z3 Z/ N) V7 v; q3 }        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
- M$ V0 a8 |+ r" m1 v1 Q% G- M. i: G) C% q2 J  e
        // FDS" T5 f3 ~6 I& e. D# c2 N5 N
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;: d3 |# U! }+ u; p  h0 K( J
$ S! j+ w. @6 q; V
        // MMC5
: T, J2 B0 y3 [# q8 s        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
5 Y# w* x  m3 v1 U- X) t        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;8 S+ U! f7 V! V' t& M+ [
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% \  v$ b! _1 }( ^: E# U* _: q, x3 J' Y% B- n- A
        // N106' R8 A; [  O4 c' |6 W( k1 c
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 h6 T! m' ^+ E" z  c' O- e        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 ]& H- }6 @+ \" I* _+ e        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
  o$ Y+ w, C) ]5 o" q! `4 T        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, i( [, S) C+ t/ J- ]6 G
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 X7 [& Q6 s/ {1 Z$ }' a4 }! i2 P
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 y: g( _0 P2 s# j* Q        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
1 q9 T1 j( i1 g' \3 E        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: J) J; l* n, g. g3 D1 u  B% }
* h8 T% e0 T. h0 t* c) T
        // FME7
/ x' V3 j6 Y- N; x        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
! X' e3 ^1 p( R2 t        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
& F# b9 x) U2 g1 h9 v        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;( S; P" f$ {& r8 n2 h

* |9 z0 Z7 J- y7 r5 l  E9 ]; l//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
' a' Q( |3 _8 `* C        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;# I. \+ i6 V9 X6 s% I

5 _# M8 r+ Q, j        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
$ ?& h0 q' }( m7 f1 `5 I! y& C9 \        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# @5 N. j. u5 `0 j$ _3 A/ w5 Q" P7 b
                QueueFlush();# i0 ~3 t" ~% x- b: A3 E5 g; k
        }9 P; W/ X) a2 `4 Z8 \4 r1 F' m
& M6 p6 B9 D$ u: w! E0 n! J0 g
        while( dwLength-- ) {  l& D' ?' a3 P7 O/ Y4 v( J
                writetime = (DWORD)elapsed_time;
  U3 c& @, H" N# F8 ?& s( w: d9 {% J7 O+ H! k1 M8 W8 O0 T
                while( GetQueue( writetime, q ) ) {+ j) }- D- b# w1 b# o5 @( b
                        WriteProcess( q.addr, q.data );" l, _2 m5 Q' s  T' A
                }1 i) w6 ~: P9 v8 g' s$ l

0 N8 h* E" }( T                while( GetExQueue( writetime, q ) ) {# y8 b- n/ X: e/ ~8 L6 g2 \& ?
                        WriteExProcess( q.addr, q.data );% l9 X: e* ?, `- A
                }
* P' o3 z: \5 P. I2 G! C, |9 `2 }4 k( Z0 T! z# e" s
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
1 L( w* Y8 r3 B7 x& G                output = 0;
) w! m- q  I1 ?; h$ a- K) a% o                output += internal.Process( 0 )*vol[0];
. {1 O4 I$ [. O" u$ B                output += internal.Process( 1 )*vol[1];; G1 p. N+ Q8 D. O6 n* b$ H8 O0 Z* p
                output += internal.Process( 2 )*vol[2];; U/ U' k7 q% L
                output += internal.Process( 3 )*vol[3];* H6 @) Q* R) n% k0 T' n
                output += internal.Process( 4 )*vol[4];9 ?' I5 A5 k1 T- z* D" @

5 n' |$ T% g0 @3 @                if( exsound_select & 0x01 ) {  q3 {% x2 T8 u+ y& z
                        output += vrc6.Process( 0 )*vol[5];& m, \# Q% j) p0 s7 C3 M
                        output += vrc6.Process( 1 )*vol[6];* R6 _9 l2 R, w0 V# t/ A7 P; I
                        output += vrc6.Process( 2 )*vol[7];
0 Y/ Z  I6 X: e1 g$ m' q4 ?                }& Z! E5 m" }% Z. \& w
                if( exsound_select & 0x02 ) {
6 J' P7 a  h" `6 a0 M1 s3 p                        output += vrc7.Process( 0 )*vol[8];4 M6 T/ p7 F0 D/ y& }" ^
                }
4 D3 Z& x! s; M5 p& c7 p                if( exsound_select & 0x04 ) {
; R2 i, D. I7 }4 B2 T                        output += fds.Process( 0 )*vol[9];8 t# @& X! W& g$ r( [
                }
, \4 o6 C+ k( Z! g: O' z                if( exsound_select & 0x08 ) {
  @. c: v9 L7 V. C2 b                        output += mmc5.Process( 0 )*vol[10];# |# u) l! M$ F0 Y* z4 v# J. b2 e
                        output += mmc5.Process( 1 )*vol[11];& G3 u! ?4 t& W) P& i; Q/ ?* Z
                        output += mmc5.Process( 2 )*vol[12];
: z$ U$ Z" N6 y0 t- e                }
! f3 M2 }1 ?% K9 t! {/ B                if( exsound_select & 0x10 ) {  M8 p7 w# @. s' l
                        output += n106.Process( 0 )*vol[13];9 _/ s+ D9 U9 |2 e1 J3 C! |
                        output += n106.Process( 1 )*vol[14];
! x5 W" @. o! ~  L                        output += n106.Process( 2 )*vol[15];
  B: e2 ]+ C% P5 l% w8 X7 I                        output += n106.Process( 3 )*vol[16];* n7 U# h3 F. Z9 b7 a3 F
                        output += n106.Process( 4 )*vol[17];3 D7 U2 p, B( t4 B
                        output += n106.Process( 5 )*vol[18];
4 |! b8 q; Z7 r' t3 O* {                        output += n106.Process( 6 )*vol[19];% @1 t8 F' p* c1 H
                        output += n106.Process( 7 )*vol[20];
5 {) u3 O  `8 O                }: j% Y; L( s9 i; c& t
                if( exsound_select & 0x20 ) {
& r* h& m" \& O8 U( D                        fme7.Process( 3 );        // Envelope & Noise
. }6 [$ P& Y) x/ }, e, I! n                        output += fme7.Process( 0 )*vol[21];
3 e7 w6 ^+ g9 X+ n                        output += fme7.Process( 1 )*vol[22];' x. Q4 M. I' R8 h8 i' y( t8 K$ _
                        output += fme7.Process( 2 )*vol[23];2 a7 B' N( w# i3 L" Y3 @
                }( X# \* A7 L+ S5 y2 U- Z
" _( Q4 t7 E! D' z/ Y1 f  j# X
                output >>= 8;; Z( O+ K/ j0 w0 j2 F1 N4 W
+ k0 t$ O% u$ T, [6 K
                if( nFilterType == 1 ) {
0 X' {% a" Q! u0 _' F) m                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)& R6 i# t  `' w. x: }, U! K; y6 l
                        output = (lowpass_filter[0]+output)/2;
! q$ Z1 O  j  z7 K8 p9 R1 B3 n                        lowpass_filter[0] = output;
7 a& _! Y) T9 |0 V/ W                } else if( nFilterType == 2 ) {
5 R4 k( Z& q1 l7 `( r0 S! q                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
" N) i  a- c8 E. s. q                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;% \/ F8 Q- E- P0 n4 |, X# ]/ G0 k4 G
                        lowpass_filter[1] = lowpass_filter[0];
/ a2 W# G% |( ~- G' e7 o                        lowpass_filter[0] = output;3 O& C# k9 O6 C( y+ ^
                } else if( nFilterType == 3 ) {) b) m4 `  Q4 j" g) d% S
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
4 u& [: O) q) ?/ c3 A9 M                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
' F  Z' A% R, Q% _/ x* K* N; V                        lowpass_filter[2] = lowpass_filter[1];
& {/ x2 J7 r% S& D; d  @  D                        lowpass_filter[1] = lowpass_filter[0];
, s- i9 q# a2 e# k8 T$ u                        lowpass_filter[0] = output;) M" T0 {! h, D  ~% j, D8 N
                } else if( nFilterType == 4 ) {
; B# e& J8 Q1 r                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 L0 I, W1 g& P8 F
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
2 ?- C3 c/ G5 [                        lowpass_filter[1] = lowpass_filter[0];- W4 _, z$ p' R6 ~
                        lowpass_filter[0] = output;: z3 o" C+ _% d% J4 H3 E- Y2 m
                }4 i2 F8 U" ]# o8 `

' Y* u0 g1 j; [" x3 x* {5 T#if        0
, E1 m- m( w* ~/ J                // DC惉暘偺僇僢僩
2 W% Y& Z+ b8 t0 h, Y3 z                {/ O/ ]0 E. Z: e5 W
                static double ave = 0.0, max=0.0, min=0.0;
- |3 Q5 ~$ ~6 A: _                double delta;% {/ i# o& x8 Q: w& m7 i
                delta = (max-min)/32768.0;
+ o7 x, M) r2 l  X# G                max -= delta;( P' L0 O2 u! C8 R/ `
                min += delta;3 ?- m  z& n5 q! u4 s. `
                if( output > max ) max = output;
* s+ b; V, I' t9 R: r* b3 p                if( output < min ) min = output;4 a" f. a3 T5 ~7 {6 v/ F" ~
                ave -= ave/1024.0;6 Q0 @& U. e: T, [0 v$ X, B
                ave += (max+min)/2048.0;
: N- J' h( m8 \7 B5 J                output -= (INT)ave;
  x8 s" |7 M/ K                }
4 ^/ i$ \. A7 J  ~1 M2 P- e6 K# Y#endif
; i: ^. H8 W* O  n#if        1
( N8 [' Y2 J1 X9 C- ]1 P3 X. r& m                // DC惉暘偺僇僢僩(HPF TEST)& z% S6 [: }1 b9 a" W0 t& S
                {
, n; A$ b' C; L# i//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);& F4 Q  s2 _: u* ~" e( _) k3 G; m
                static        double        cutofftemp = (2.0*3.141592653579*40.0);9 [8 D3 \* V' j, f& s) d9 C
                double        cutoff = cutofftemp/(double)Config.sound.nRate;) \" q* G0 [% U: w
                static        double        tmp = 0.0;
2 C) |' J- G2 w. c                double        in, out;
# `- A" A7 f( @2 D* s
( y  j2 E' f, \3 U7 W; l                in = (double)output;# s; \6 S) Z4 A0 E% S7 g
                out = (in - tmp);) U. l$ R0 w) V8 \0 l
                tmp = tmp + cutoff * out;
9 i" t1 I# |7 E5 `+ b( [7 A$ |, O# J$ s4 P0 ]& r( x5 o$ J
                output = (INT)out;1 e% ~5 p, ~! O9 n; g5 V
                }
) z& B: Z7 C! ^) O4 w; u#endif
+ Z3 n. f& @5 `! u#if        0
$ P! P1 V6 k% g' `+ w                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
5 p1 ^* _$ o" q% i                {* z1 J0 H1 p2 v( I' [
                INT        diff = abs(output-last_data);
5 u* I+ h9 v- _2 X" o                if( diff > 0x4000 ) {
. z4 `( N) z& D6 d6 c" y                        output /= 4;8 v! C9 H* ^3 h' Q  d! i
                } else 3 P6 y& X* R/ k9 W: ?, k
                if( diff > 0x3000 ) {  K. a; ^) i6 v1 o6 Y
                        output /= 3;
$ B8 O( T9 ?8 ]: `                } else# Q% z3 L, ~3 K; i
                if( diff > 0x2000 ) {
/ Q$ w/ z( {& f$ E( Z                        output /= 2;
- l* w; ]* r1 o0 l# f4 l. m$ ?                }, Y. b- q; \% r/ J
                last_data = output;1 ]8 N3 W! J3 N7 ~3 O5 c, a
                }9 u: a/ R  P; b  s2 E# Z* ~
#endif' V6 n6 o! d: {% H5 A
                // Limit; D9 Y) U. [. `) `, H" R, _
                if( output > 0x7FFF ) {4 \' W# i+ G* t5 w5 k5 k8 b& N# J; R
                        output = 0x7FFF;7 P( r6 C- D& c% [( s
                } else if( output < -0x8000 ) {4 S: t* `6 ~8 W2 e
                        output = -0x8000;. N( s/ ~; B) h+ X  \
                }
" P6 {0 Q! Y+ S/ @# I# K7 k2 B2 B4 v3 H, O) g) K* p# D! w
                if( nBits != 8 ) {9 h% k! W7 e. v
                        *(SHORT*)lpBuffer = (SHORT)output;
% M) t' J5 q8 t+ X! \/ Z2 i                        lpBuffer += sizeof(SHORT);
- C3 t1 l# m1 C1 e+ U0 p1 Q6 i& E* g                } else {) G& P7 B" H3 {- @+ }" Z7 B( U) }
                        *lpBuffer++ = (output>>8)^0x80;
' {4 p5 W7 O0 W2 A- M+ x$ m                }6 F) P: p! [0 v* Q  `
# e* Z. t7 J! ]0 Z, m; ~3 s, z2 q) Q
                if( nCcount < 0x0100 )* |- x  N7 h. ?3 D6 _* q: l
                        pSoundBuf[nCcount++] = (SHORT)output;
4 T$ Z4 ^! J4 b/ ?. X9 j% b; D4 j3 |6 P$ D: X; m  Y/ D1 ~
//                elapsedtime += cycle_rate;
; I; i* |# ~/ p1 S& T6 T8 E                elapsed_time += cycle_rate;
5 ^! e  b9 e3 A  b& w+ Q% V        }
5 P; Z4 T  m. ~# k4 A# P
* h% w5 \: S- f#if        1/ b2 _0 g* X4 U" G4 f& x1 N  {8 @
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {' H( t2 _. y8 e# M/ }$ h
                elapsed_time = nes->cpu->GetTotalCycles();0 U% l. T+ k0 u9 _
        }
$ D9 k& Z6 T7 G/ g( k( [' c: N) t2 }        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
  x4 `2 E5 W4 ~# W* C8 r                elapsed_time = nes->cpu->GetTotalCycles();
2 g7 ~& l! x7 S! h$ y        }* M2 M3 i) t2 ~% _  ?
#else
5 A# u6 |! r4 Z7 b% R6 g        elapsed_time = nes->cpu->GetTotalCycles();% f, Q) K* }1 ^  m- v/ p- ]
#endif
. C* C; C6 ^6 G}) e% v6 P; z" h2 c+ o+ e; ?
7 {- i! T3 p9 F+ Z4 _& N3 ?
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
5 K& V) r& w' vINT        APU::GetChannelFrequency( INT no )
' V7 }' {" b0 n$ z+ I, w- X0 t{6 g* n( C: ~' b  E$ j+ g
        if( !m_bMute[0] )
- ~) }1 `% c9 Y6 u2 R                return        0;
0 N* |3 N! n3 E0 A4 o- K) Z/ i$ g) h
        // Internal; |0 ]- O* m3 O) u
        if( no < 5 ) {( X$ a: M. n' ]0 P- M9 \" x& s' }
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) R& F5 U" U7 V5 N( Z        }
, `3 o' x% j% i' S9 F4 J( V        // VRC64 s/ z! [# t. [& w% e
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {7 X% C1 Y0 m9 ^( q$ |9 ?! f
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
: ^" D+ f( s2 J1 V* l7 W( V        }
! y5 u' S; i( I9 ]* L8 M  q        // FDS
0 P# `% r2 R* q1 }' o) V5 t3 P        if( (exsound_select & 0x04) && no == 0x300 ) {
! d2 V. C7 x, L: m2 L1 h8 I; Q                return        m_bMute[6]?fds.GetFreq( 0 ):0;2 h  ~2 Q& x! U, a* W# s/ O4 e! H/ Z
        }3 ^0 g" z% C6 W1 F+ T& O
        // MMC5
% W+ T  h7 @0 D2 [        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {) ^, R# H2 y2 J6 ^. I# G# ~) |
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
& ~- E# h6 F! Q- v" k; y        }" i$ Y% f% h# v8 S, N1 m* k
        // N1067 m2 j0 e4 ~3 w3 \
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {: F6 @  j# g% A" ]5 U
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; @( e0 J& M5 f7 B( f" L
        }
# B8 i/ s8 V+ r2 s; {1 h. W        // FME7
/ o/ n& l4 J1 C2 ~        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
3 i% v8 V1 ?) N) m/ y                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;% M5 ]- N+ W# [1 n) Y2 z2 D
        }* ^" R- R( a7 p5 b+ G" b
        // VRC7
. g8 m6 r! R% j. e4 q        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {4 V! A  q% W. A+ ~3 w
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
9 {1 y7 r2 M- h" ^$ _( K* g        }
( N  Y* W( c) a$ O2 @% d        return        0;
$ Q, z$ o2 b7 I& T) a. X: {6 G}
$ t9 `6 Z. n2 L# V& }
0 M3 N; g  I9 e6 p. P- a, w// State Save/Load5 k5 C! q4 O) O, l1 f
void        APU::SaveState( LPBYTE p )
! k! i$ X- I' Z* S{  D7 H' _8 v7 n
#ifdef        _DEBUG5 \" T" o5 y$ \  z% S$ H  k* B
LPBYTE        pold = p;" V4 i. h. F; H  _, p/ ]! p, P  O- T* N
#endif% {, M9 _+ p2 n- ^+ ^7 O

, ]$ i& u5 I" W        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
4 k9 O" ~  N$ P& O; e+ e, b        QueueFlush();  I, d9 o: {' _7 Y

% P" Y" l7 t) Y5 F5 i( F9 V        internal.SaveState( p );
& n4 F" G7 X2 H! o! E+ C$ [# C- A        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
+ h+ k/ r- A' w2 M. ]% V  w, G* M; J- f9 u" I
        // VRC6, n% c% k! {0 b! ~
        if( exsound_select & 0x01 ) {+ r- J, C0 h4 N. o$ _: _$ d
                vrc6.SaveState( p );
; J0 \: P3 ], Y2 I: z0 ]                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; w9 h. F& S" B1 t
        }: |$ N0 ?' H" u1 Q1 t' T* j! D
        // VRC7 (not support)& x) {6 m! X+ Z* c) T7 ?
        if( exsound_select & 0x02 ) {
0 p8 R- n% g/ z1 U" [8 `; D, u* X                vrc7.SaveState( p );8 W5 D6 r3 l- \9 f" }6 i$ Q) l, [8 a' x
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 H: _0 F# x: [( J; ^! U
        }
+ T( E+ ?" b" H4 L, s, ?        // FDS
# X  j- f; |3 x0 N6 \* W3 t7 D        if( exsound_select & 0x04 ) {8 A- G& Z' A; w/ P9 G9 A
                fds.SaveState( p );
: L8 Z+ t1 @# N3 a# S! E( i) W. g8 }( z                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding2 `2 k7 r. U7 x4 T
        }
5 o7 m4 e+ k6 l  ?. I* f        // MMC5
2 P1 f2 W/ b, G        if( exsound_select & 0x08 ) {; P4 w( z* G/ i( C8 q9 ?
                mmc5.SaveState( p );
2 P: H# l+ i0 D! q/ e2 a4 R) [& A                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding4 }6 A% Z* w0 w2 d
        }7 n  Y0 `  C: A; [; K
        // N106
' a" R, J# E* _: k- T        if( exsound_select & 0x10 ) {
5 p. T2 p2 c! U0 n! _. e' Z6 W                n106.SaveState( p );
- a: b/ [6 A4 I# ]' g7 r& o                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
: o- r" |" X: u7 |4 A- {/ _        }# r& ?0 q" {# r/ |* C  H
        // FME77 ]: D; ~9 E* H: h
        if( exsound_select & 0x20 ) {
0 `0 |& t  G1 h                fme7.SaveState( p );0 }# r  H& k$ i; A$ Q
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 @! L9 H* _6 i! ^  a9 R1 ^        }" x# D" C# h4 {/ _; W5 \! w
* |5 R7 Z# K# z0 E3 P% M; k# R& S
#ifdef        _DEBUG0 G0 @% G5 D7 g' C8 U
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );1 I6 e: w, T$ k: k% I
#endif
6 w6 _0 V& I, B( a4 a4 t}
" n* |) V, Q7 e9 R0 m$ D
$ D+ F: |4 u1 N- p" E5 q# D" T9 Wvoid        APU::LoadState( LPBYTE p )4 {+ R$ u$ P/ r  Z1 j% a0 m; n
{
' x/ q/ h9 y) ~* ?& [( P        // 帪娫幉傪摨婜偝偣傞堊偵徚偡! f6 [2 N+ R6 U# L" T7 ]1 g; j
        QueueClear();
8 x0 U4 O/ X8 C" |6 o: z$ p% j
8 J( @& _2 N0 q: |7 s        internal.LoadState( p );
4 R6 K" G! t; H) v/ f8 ]& k  E        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
9 V$ o8 ?$ {: m% B) z* r: h) \) \& Y3 l2 e* i, b  Q
        // VRC67 \9 z/ E& f! G% O4 B
        if( exsound_select & 0x01 ) {
+ l6 I/ y  W* \. J; `  A( H3 Y/ S                vrc6.LoadState( p );
" n! ]8 \$ R; b9 L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
, c% U* b) a4 z& \7 l# t        }
4 @7 a$ G; F4 U" k( l: Y        // VRC7 (not support)- d( u4 C. u+ M# q
        if( exsound_select & 0x02 ) {
0 q5 w3 R2 y6 t$ x& q( `                vrc7.LoadState( p );
/ c7 x$ Y7 z: C! h5 d* H2 v. l1 D                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding1 Y% [# |5 v; [3 I
        }0 V  Q/ D8 p2 j
        // FDS
. D- D) @5 E& C0 n" ^  R        if( exsound_select & 0x04 ) {( ]+ I- ~3 V' j
                fds.LoadState( p );6 p0 z8 z, J1 H4 h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
7 S# S9 e' ^2 m% V        }9 b/ {; b6 ~& m1 u
        // MMC5
9 t3 m* m( s; M        if( exsound_select & 0x08 ) {
: Q' B7 J  ~  ]; m  h2 d( v                mmc5.LoadState( p );, j' X5 W+ F, n. L0 [8 f/ E0 O
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
- I8 p) \, U2 u: \& s        }
  L- {1 S2 Q! R  B& ^( ]        // N106
2 D* y& t4 j* S        if( exsound_select & 0x10 ) {
! ^- y- T* y5 o1 V: A/ Y( r  X8 ?  y                n106.LoadState( p );# _5 r0 w0 p0 i9 i, q
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding2 y8 o$ w/ K# O! B) y. D
        }/ H5 U% k9 ]; D
        // FME7
& c& P4 W  ]3 M5 a# }% b8 c$ z        if( exsound_select & 0x20 ) {6 \. e$ ~7 Z+ _7 j- f+ P, q
                fme7.LoadState( p );6 P: o" H# j' N/ d$ U+ y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
; h: |" y: Y1 d        }
$ M' ]# g7 p  R! d3 d}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
- W' a8 W7 C/ g  V可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。1 i, j( k/ M2 P; |% ^- C- _
感激不尽~~

/ p5 v9 P# V% P9 @: s) I恩 我對模擬器不是很有研究,' Y* t- |( v- C3 b
雖然要了解源碼內容,可能不是很困難,( t/ m3 U- h8 u1 B, Y
不過還是要花時間,個人目前蠻忙碌的。# A& j: m+ Y* j$ R; Y( r
( c5 k2 V- I$ W# L
給你一個朋友的MSN,你可以跟他討論看看,
9 a9 g1 t! }: V他本身是程式設計師,也對FC模擬器很有興趣。
: g8 ]# n* H/ }% g6 g1 `- H
: R% @4 ~) w8 s5 H6 AMSN我就PM到你的信箱了。* [6 o/ I9 e7 Q$ t
# b. k/ D1 F: F: c0 H' G
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
0 H( ]4 P$ z: D呵…… 谢过团长大人~~

2 q# c8 _2 }# ?* e* ^9 M9 T( E; z& t% l6 V' n: g' M# l4 O
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
" L- p& W% s# ^+ K团长的朋友都是神,那团长就是神的boss。

% @( I' _' l  e, b4 u哈 不敢當,我只是個平凡人,: U$ E" V. q4 j7 b4 N
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙" k2 F% M8 _' G9 m$ `  T
ZYH
4 W  e- u8 g0 |" z6 OQQ:414734306* X& U9 |% _" H6 S
Mail:zyh-01@126.com
7 I. f& q# Y: U8 ]8 K& ]4 a3 a: Z4 a
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . s/ R4 l! G" S! |. \" Y% H1 e
再次对团长大人和悠悠哥的无私帮助表示感谢~~
) W! Z( h3 N1 h. f
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-11-28 13:58 , Processed in 1.107421 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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