EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ T7 ?4 Z7 m+ O$ c' F+ d6 I' H  K0 Q
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
# \) s3 Y7 o5 e这里有相应的模拟器源码,就当送给大侠了~~
. N' ]# x% K5 E9 E6 M) }: x) }/ khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 # O) c) J; i# p+ ~$ _. ?
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
( R, u3 t0 i3 i2 ^4 N) e) h% O6 R楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~2 l! l. z5 @3 o% g, \
这里有相应的模拟器源码,就当送给大侠 ...

. W0 V( t# \: Q聲音部分(Audoi Process Unit = APU):! r+ r3 ~: k4 R5 H/ |2 Z* r' G
.\NES\APU.cpp! \, w9 o4 u% ]+ {
.\NES\APU.h
$ N! M; o: k" O+ G* j5 Z3 {
; W3 C7 D& Q( X! V7 g- X2 m
' x6 y( F) x' y" R& N8 [2 e影像處理部份(Picture Processing Unit = PPU):
6 K8 G0 H, v2 W3 O. ?. F, w) g" b& d.\NES\PPU.cpp
+ S$ }( F7 S  p5 z" Q.\NES\PPU.h
9 @% n5 A6 e$ I/ I5 A7 n$ v" Y: Y1 j3 j3 C1 R$ O- Y( |1 v
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
+ I( \6 {6 w" P(由于很多专用术语和算法机理都不明白,所以看不大懂……)4 h  S/ X1 F" l8 [6 \
//////////////////////////////////////////////////////////////////////////
3 F& Y( q& l; h8 m( J//                                                                      //4 ]5 l+ U. Y% L1 i4 j* \8 p' h6 L
//      NES APU core                                                    //  S( K( D, W/ I
//                                                           Norix      //6 b+ c, j: @7 i: [8 [, @9 w
//                                               written     2002/06/27 //
) p2 ~# ~- l- H, n//                                               last modify ----/--/-- //
  t' M8 `. \7 e) s# Z//////////////////////////////////////////////////////////////////////////' J5 E* ]: p( ?
#include "DebugOut.h"9 S9 v# n& A; w
#include "App.h"- R9 R( |8 T4 O* p+ {" l
#include "Config.h"
5 [: K5 y2 ^3 _  J7 ]
, X7 P% K7 [9 N3 x/ p2 l% Y) _: d#include "nes.h"6 q* f5 j' q" Z6 W' u
#include "mmu.h"5 f$ l7 j( s$ U3 o6 K/ T: E
#include "cpu.h"$ y2 c5 ?- a3 ^) |* `
#include "ppu.h"
5 C" U4 ?0 k+ ~& U1 |5 c4 d- X/ J#include "rom.h"
; V1 l$ ?( c5 p! u; R#include "apu.h"3 `* {9 \: C9 N/ X& `( b/ z
2 h; |4 ^4 v2 a: S6 M$ j
// Volume adjust- P- Z9 v3 f6 c  e: n8 l' q
// Internal sounds
, ]- u, y/ B; s4 {9 J/ V#define        RECTANGLE_VOL        (0x0F0)* x1 c3 ^8 @! V+ @% v
#define        TRIANGLE_VOL        (0x130)
* x) _" I- j1 _' i7 E#define        NOISE_VOL        (0x0C0)
0 l/ N+ z6 t4 w( w& G$ J- N#define        DPCM_VOL        (0x0F0)- K9 O. L6 ^) D5 p- ~( u5 z( Q
// Extra sounds, Q/ W0 `9 _3 p6 h' m, [
#define        VRC6_VOL        (0x0F0)( n$ W4 g( X0 h. S/ C2 z& g  n: G4 ^
#define        VRC7_VOL        (0x130)
# a9 c% n( `" S5 s+ I0 X8 [#define        FDS_VOL                (0x0F0)/ i, e$ Z4 u. \: W* c
#define        MMC5_VOL        (0x0F0); [9 F( H3 Q% [: Y. Z' P& ?
#define        N106_VOL        (0x088)
+ `% t0 A) i! A; e. v* ^" ]#define        FME7_VOL        (0x130)
$ O+ @# e; |& l
# Y+ M& \  ?/ ^( z' C" g. iAPU::APU( NES* parent )1 f" v9 U6 g# a
{
5 Y8 s3 Q$ c, I0 T        exsound_select = 0;& C! P4 N6 G/ L7 g* h8 S
( \$ c) b  f. @  k7 S
        nes = parent;
8 U% h3 ]5 [3 p" z, O# |- t+ y        internal.SetParent( parent );  ^) c; x+ p& W2 \, ]4 Z

: }& Z& w6 `3 V2 p& ?8 y        last_data = last_diff = 0;8 V, |) \! n$ _9 n* d
8 X7 L/ Q4 G5 L7 d* K  E
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );) X2 e8 Z3 q+ s

$ ?: ]" m: P! O7 O/ U* J        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
  N* \1 A0 E" ^% l( }9 B  ~        ZEROMEMORY( &queue, sizeof(queue) );
# W9 [9 M( G: V4 N! u$ |        ZEROMEMORY( &exqueue, sizeof(exqueue) );  C1 j9 k; C* x: ^* P
4 r) H1 J/ j% F$ |
        for( INT i = 0; i < 16; i++ ) {, o; f! E- T; B' n2 U  s2 P  N) r) {
                m_bMute = TRUE;
/ S. L( @8 e' X' e& _+ x        }
7 d# R; w# r: h}! [$ ]8 C' L' L; r: ^; q0 n
& j9 U: S" ^5 V" ~$ H4 K
APU::~APU()
1 A" _+ z( N, m{
+ H5 L( Q) N3 {' M1 W}5 g4 Y1 B) M$ y& H- a* v
1 c7 s; T, H- V
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )2 s0 A& j/ I/ {$ Y+ V+ ?
{& q$ e7 d, S0 ]8 {5 u
        queue.data[queue.wrptr].time = writetime;, R9 J( Z7 I" V8 h
        queue.data[queue.wrptr].addr = addr;
, ~5 f) E# d" _        queue.data[queue.wrptr].data = data;
7 t  D( Z. j- Y$ \4 B8 ?: y' N( ^        queue.wrptr++;
, g, V  V) a# s, R        queue.wrptr&=QUEUE_LENGTH-1;/ F$ A! J/ {8 o+ A3 N+ k
        if( queue.wrptr == queue.rdptr ) {) @4 u0 P6 l: B8 r
                DEBUGOUT( "queue overflow.\n" );3 P$ ?' D0 T- b4 Q/ w+ f
        }
; r4 d6 x1 e  o6 [) o. N}1 l* N  T+ G! c6 j; I

: w; @5 E# C" z4 ~& d. I; N1 L8 J" lBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
+ |' b, E+ o% \& U) i{, n7 T3 x1 g$ i3 }; ?
        if( queue.wrptr == queue.rdptr ) {
1 A5 ~" X& z3 P, ~8 H                return        FALSE;0 J9 U1 @- d8 {0 B( r# z+ ?5 P
        }/ T) V( `7 Z+ U2 l
        if( queue.data[queue.rdptr].time <= writetime ) {
* e3 p8 z. m3 v                ret = queue.data[queue.rdptr];6 w0 z7 }6 S! B; A; P$ L7 a2 W
                queue.rdptr++;, ?- `. v8 j' B8 a8 u) J7 B# e
                queue.rdptr&=QUEUE_LENGTH-1;
: T  M2 E) E5 g; u" ~9 i. t                return        TRUE;
# Z, J+ p- c/ s5 z3 R7 y1 P! ]& Z9 y5 |2 n        }4 |/ y8 U3 J: G, V" ^9 k
        return        FALSE;, Y9 ~5 N, }7 s7 w
}( V5 F% O* {; a$ V% Z4 ?. n4 J
7 e2 |$ Q0 T7 t! ^/ s( h
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )7 |  |2 N( K- o
{! L* h* t, M. v. T& F
        exqueue.data[exqueue.wrptr].time = writetime;6 k3 Y0 D& Q$ a3 k
        exqueue.data[exqueue.wrptr].addr = addr;6 m, W8 D* O: o2 [# @
        exqueue.data[exqueue.wrptr].data = data;
4 k; O9 i5 q6 ~+ P2 j        exqueue.wrptr++;( P1 z9 _8 h6 t2 ^
        exqueue.wrptr&=QUEUE_LENGTH-1;! t% Y5 ~( f$ q% w& g, A
        if( exqueue.wrptr == exqueue.rdptr ) {
4 {8 j* v  H* ^# b" U( v1 w0 Z                DEBUGOUT( "exqueue overflow.\n" );
, s9 f$ ]" ^4 P' G& V        }
/ ~! }* b' \& F% c  h: y! T}8 t7 A8 N# v7 I2 n' N, X# V

; ?! y5 t  \  m. U$ Y) P9 I! PBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )( [# }6 B8 N/ u0 v
{, I7 V5 k% M# W& n  z$ t
        if( exqueue.wrptr == exqueue.rdptr ) {* |* O; i. _  [- j7 W0 _
                return        FALSE;
) v# @* }4 y/ L+ ~8 W& [5 u, H        }
$ J" ?4 k  t; f) N  t        if( exqueue.data[exqueue.rdptr].time <= writetime ) {- I) b) K  v2 q# n  _3 ~
                ret = exqueue.data[exqueue.rdptr];' l! o0 `* w7 s% W- r, I
                exqueue.rdptr++;! {  j% ^# D6 d. x( b2 C
                exqueue.rdptr&=QUEUE_LENGTH-1;( t: T, _/ J+ B; `' m- U
                return        TRUE;
1 }- y0 q- [2 e- C8 [- x        }
. K% {" x' n1 G' ~# ~        return        FALSE;
- c. R. F7 ]( F8 x/ u7 u7 [4 E, B}
% s' @8 _$ A6 u! O3 a9 s4 Y( N( ^4 f( x) K
void        APU::QueueClear()
2 f; i5 t5 N8 j0 q{3 Z- N' Z: x0 Y. ~, s  j
        ZEROMEMORY( &queue, sizeof(queue) );/ Q! j. D6 |, x5 d0 S; j9 [' I
        ZEROMEMORY( &exqueue, sizeof(exqueue) );) T4 ?6 g% M. t/ G5 X/ Q
}
4 n: T6 I; \8 h1 I& s* }! b% J) A5 Z$ u* V8 v: m$ p% v
void        APU::QueueFlush()7 F: L! |' Q# d
{5 a' N" d* n" y. Q5 ^2 {% F4 J$ O
        while( queue.wrptr != queue.rdptr ) {
7 f- Z. p; j8 K0 G7 D1 |                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );) E! i: t$ J2 p$ B1 U# m
                queue.rdptr++;4 K- B  {9 _5 r1 g% y) p
                queue.rdptr&=QUEUE_LENGTH-1;) i; C9 k. G( s- e) g
        }/ _/ d3 Q5 x+ ~# d5 v8 |9 `8 T  k. }

6 q1 e9 M6 h! U, {- E        while( exqueue.wrptr != exqueue.rdptr ) {% b. J0 {  x7 |, N6 g
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
7 e3 X- ~/ Y8 |                exqueue.rdptr++;
/ @: y0 [% h8 L5 S' K! m                exqueue.rdptr&=QUEUE_LENGTH-1;0 X9 w3 I$ X5 ?6 w
        }
9 u$ a/ o; Z0 Z: T- r! e}  Z/ j; v6 K, R4 k
+ ^4 A/ ^- L2 C  C! z4 `9 {
void        APU::SoundSetup()
7 S6 x5 p) T- d% Q3 c* [{
) o8 |$ h  q$ d0 ^7 `& n9 S        FLOAT        fClock = nes->nescfg->CpuClock;
+ e  z: v3 p, G  h        INT        nRate = (INT)Config.sound.nRate;: ?- V+ y0 I: |% _& k
        internal.Setup( fClock, nRate );4 _; I4 _0 b9 Z' j" {
        vrc6.Setup( fClock, nRate );9 j8 j3 x; k4 z8 j' \, q, a: }' V
        vrc7.Setup( fClock, nRate );
6 y( C' l8 l% O7 S9 A- i        mmc5.Setup( fClock, nRate );1 O8 p8 d1 }. x2 O
        fds.Setup ( fClock, nRate );1 o* I3 b9 H6 ~( Q# O
        n106.Setup( fClock, nRate );4 S- q; J, [8 C  `; B+ Q& t" y
        fme7.Setup( fClock, nRate );
" }2 V. A' u* j}  H1 @% m9 `+ H2 @9 U
1 g7 J0 _6 u2 y% k' ?
void        APU::Reset()
0 C6 ?9 w* g; r% k{- T2 T( Q) F4 B- H& }& N+ ?7 T
        ZEROMEMORY( &queue, sizeof(queue) );
- A" o" b- O* e0 b8 p# _& N+ q        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& j* Z4 T+ B3 l
( D1 C; @2 J* O: e        elapsed_time = 0;& z5 Y0 t, L$ T* T

/ U( ], ]1 s9 \$ W' C) @. D; X        FLOAT        fClock = nes->nescfg->CpuClock;7 x8 q4 z  r; K
        INT        nRate = (INT)Config.sound.nRate;
  g$ L: R& g4 u! j# v        internal.Reset( fClock, nRate );" W" p8 |; d8 Y3 p6 j+ v
        vrc6.Reset( fClock, nRate );. }# Z6 p* ^, b# J# ^- J0 q
        vrc7.Reset( fClock, nRate );0 @# q" y/ i  T1 O" T+ n
        mmc5.Reset( fClock, nRate );2 w- P! R: z5 Z
        fds.Reset ( fClock, nRate );
& K& ?1 ]& _; A        n106.Reset( fClock, nRate );; x5 W# ]' k0 W
        fme7.Reset( fClock, nRate );
7 s+ f) Z& e4 U, v! E) L7 V) Z: ~; \
        SoundSetup();
4 G* s, F2 }2 r( D- p3 Z}
; n4 K1 r* E. N. Y% F
# Z' n. V% V, ^8 K* X- U1 Xvoid        APU::SelectExSound( BYTE data )
; d# U! |. X/ |- @: Z{
0 |9 M% |3 T/ p3 y. O2 A9 d( E- x. r" B        exsound_select = data;4 ]* ]! P! H  w9 f0 |
}, }. e7 g+ {+ Y5 K* L4 @( H' {

) a. f: ?, r1 O5 ]" P' l; @BYTE        APU::Read( WORD addr )
( I+ N* d) M6 q+ R; W{
1 @/ a0 P1 a( F6 b5 ]        return        internal.SyncRead( addr );
& d0 K, q2 [. E) ?0 _6 Y+ y}
* b/ Y8 Q1 X, H6 R+ q8 r) o' _
+ p1 j9 J& q1 }4 D3 t! V' R+ yvoid        APU::Write( WORD addr, BYTE data )
: f, r+ x# f; f  X$ w0 z{
1 z/ ?; y1 `4 M% {3 x        // $4018偼VirtuaNES屌桳億乕僩
; A( Y  v5 T+ x' G) v        if( addr >= 0x4000 && addr <= 0x401F ) {
+ J# D0 O# V3 r6 D5 [9 v: a6 u                internal.SyncWrite( addr, data );
! T, Y$ ]. O5 j7 G                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; H7 M# i' @% H, f/ k' `
        }
! f, x1 t% k; W}
( q$ K' f( ?7 \% N. B& s. Q5 o, F  _" B7 f& X+ t! d+ {
BYTE        APU::ExRead( WORD addr )3 x: |, a; T: c6 o& R" ?+ P( E
{
) ~- C! E7 B8 h+ aBYTE        data = 0;. H3 M; x+ H4 ~8 k: w3 ?: B
: T2 z# O8 ]* b$ z5 r/ F
        if( exsound_select & 0x10 ) {
2 O' X8 E8 C0 f8 e8 u' T                if( addr == 0x4800 ) {
- j0 s9 f! t, S( o% L, L& l, E                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
$ z4 M( b' Y( y                }
$ ]+ B6 f8 `7 ^4 @/ V9 {9 K! v! V        }
4 I  C! R& p- [+ P        if( exsound_select & 0x04 ) {
* r# b, F0 {/ w' z( s                if( addr >= 0x4040 && addr < 0x4100 ) {
: p7 ]8 F8 ]3 i5 f/ T# K                        data = fds.SyncRead( addr );( R+ u( y$ U! O2 ]) w
                }
/ |+ O6 Y5 K4 H  L, f        }
7 \- O  k2 L5 z7 [        if( exsound_select & 0x08 ) {% j" e8 P% @5 c* l5 j& V6 h
                if( addr >= 0x5000 && addr <= 0x5015 ) {
" X! `3 W" a) S& Y& l                        data = mmc5.SyncRead( addr );1 u/ `3 k2 V( X( i
                }- A/ ^2 H7 L7 z' t/ d
        }
: @  \! P5 s3 \3 a4 o0 N( R
8 s% U5 n2 z4 F- R        return        data;5 C( r  v1 Q& A% T* q( P( F
}
5 ^! t, E5 Y" m% ]& U2 Z1 e+ y0 \6 F+ |. m
void        APU::ExWrite( WORD addr, BYTE data )! x9 E1 ^: h& `
{9 N9 Y% N1 f0 k. M) K1 g
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );4 u1 C  O! p  o0 V9 x
( |: k: t: o4 B. U
        if( exsound_select & 0x04 ) {
' L2 d  s# x+ h4 w/ v# C                if( addr >= 0x4040 && addr < 0x4100 ) {
  |/ D/ `* L/ `$ f0 m8 ^* ~# j9 C: Z                        fds.SyncWrite( addr, data );( k9 V9 l& y4 j- j: P# t7 E
                }- G! t( A% I# g, M' K" Q
        }# s" w2 i; Y8 P6 O( y( c
5 K, k8 g9 i# T- {2 D7 K# [
        if( exsound_select & 0x08 ) {
; o  b5 @! M% A/ {9 S! h. u                if( addr >= 0x5000 && addr <= 0x5015 ) {
0 `' i9 c, \: @- U% G: p9 ], L                        mmc5.SyncWrite( addr, data );
/ R# A, `1 _. R) @, Y( c                }
5 R( t: L1 S( O( o5 }        }6 Z) E6 m- T! H! [( t/ }% O
}
" a4 D: |& S, Q! ^* |. Y2 P" c% L# m! ]: j
void        APU::Sync()
# o* u+ m. c4 Z: F  ?8 X& N7 K7 J3 v{* C" z; j9 T5 N. W) a- _5 k
}1 z" h# ~' H9 ~
8 m9 q/ e* ^2 l# S4 y  H% F* a
void        APU::SyncDPCM( INT cycles )
# U, |8 e; ?* f6 ~1 }$ e, t{
( O9 x/ z$ O  D        internal.Sync( cycles );
# E/ T/ }  F, H7 e  K8 m* h, g8 ?1 ]; [+ A: v
        if( exsound_select & 0x04 ) {+ F) Q/ z3 O: }+ ?! ~
                fds.Sync( cycles );1 V1 o  U* x/ d
        }
* o. K1 @& X& X5 Q% Q/ w! {+ O        if( exsound_select & 0x08 ) {
  S4 [9 Y/ x8 J; Y) m; s$ ]                mmc5.Sync( cycles );* O  w* @0 X/ z% M9 i6 s
        }
$ T, W$ N! a  ~}6 t, D: R" a, s! e- j% @
; ~3 w) q4 G$ _0 x- o
void        APU::WriteProcess( WORD addr, BYTE data )
, _, e: m2 m; ~, Y+ X/ n: l) T{) ~$ R% b* `: o. K' r
        // $4018偼VirtuaNES屌桳億乕僩
1 w, V: w9 ~- p8 g. d& b        if( addr >= 0x4000 && addr <= 0x401F ) {  @/ A& M/ {2 [
                internal.Write( addr, data );% k/ ~8 }7 W, }/ A$ `; d
        }
/ L$ p' U6 @5 i5 J& |8 v}
2 o! A, O1 n& E" V- A
. I( E/ l" S# w0 ^- j. s* Q2 uvoid        APU::WriteExProcess( WORD addr, BYTE data )
3 M. V: t6 a2 p# q* @( b{  s3 }/ O: b0 ]! l* v8 {% v: A) R8 o
        if( exsound_select & 0x01 ) {
2 m4 I- J" A+ s9 H; @! |                vrc6.Write( addr, data );
. |: i: U: ~+ x9 Q. S# P        }
6 J7 v6 [4 K6 K) X' M        if( exsound_select & 0x02 ) {
  a3 ^( a4 l; a$ d                vrc7.Write( addr, data );
* B0 R7 V' s$ j( ~$ M        }
# T: R' D# w! a  l3 W- L5 ^        if( exsound_select & 0x04 ) {* Q7 ^% O5 j; B8 ^6 Y
                fds.Write( addr, data );
! ], ?9 H3 k  E        }
! U, b9 b8 o. H        if( exsound_select & 0x08 ) {
9 g, v& S# |" I8 u                mmc5.Write( addr, data );
+ F$ C* q0 k7 L" E        }4 E; b& `3 n/ b3 K3 _7 g  {- j
        if( exsound_select & 0x10 ) {
, A% U9 x( G# N1 x4 g: u                if( addr == 0x0000 ) {
  T) [9 D5 E8 D                        BYTE        dummy = n106.Read( addr );1 u! v/ y1 n3 G4 V
                } else {
3 J- M7 }8 w% J' Z3 ^6 x* C& N                        n106.Write( addr, data );
, X7 @$ z! @6 N4 ?( y                }
( d: H4 j) u2 L0 z/ ]        }3 P) A0 X  Z, X
        if( exsound_select & 0x20 ) {4 d, a0 I3 X- _$ C9 @8 z' `0 N9 E
                fme7.Write( addr, data );/ N# D& I; R9 p/ y% W
        }
8 c5 \' v- r3 R1 C0 R3 r* G}* d; I9 D% D" ]; K! K
' P3 r' m( L0 S5 U4 h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize ): x7 k" Q1 s2 k
{
/ o# T! ^5 m' `& z! gINT        nBits = Config.sound.nBits;/ C# x4 g$ j. q
DWORD        dwLength = dwSize / (nBits/8);
& n. N! U1 t# V7 N6 q+ H& `  PINT        output;
& K; M2 r/ J& k) h3 A) fQUEUEDATA q;
: @6 M3 C6 Y7 ^5 _: b3 [' hDWORD        writetime;
3 O( k: R/ K* `6 m9 y! T
" o) c4 A/ _3 z# l( ^) ZLPSHORT        pSoundBuf = m_SoundBuffer;$ B% G/ {0 R! R/ ~* a2 V) f
INT        nCcount = 0;
# ^. v% L$ E" ^( A& }
5 m% o, q3 s; K5 L* R% o) ^INT        nFilterType = Config.sound.nFilterType;" a0 s* Q) @( s/ }& N# l6 s  t
8 M+ H0 @% R& ?
        if( !Config.sound.bEnable ) {! Z& T4 {% M; {+ ]
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );- _0 M& b/ O1 u: H) k3 C: a9 W1 M
                return;: }2 E1 v! S; g! v9 y$ V- s8 v" q# M
        }
( x$ L! a1 }3 H% g3 y0 R' _" h0 Z
  d5 l9 p; i$ k$ v, Y% k' h        // Volume setup5 s2 q5 q4 r0 D$ r$ j1 f3 {
        //  0:Master
* i7 V0 K/ ^* Z* N0 o- Z0 F        //  1:Rectangle 1+ y$ @; L5 g9 E- u
        //  2:Rectangle 2
. o: B7 N1 }7 I0 S& m8 I, |        //  3:Triangle1 ?& F: `# O, a$ m: J. f# f
        //  4:Noise
/ W5 F6 ^) U: ?8 S: F1 H        //  5:DPCM) _" M& q" F1 K$ t2 @, o
        //  6:VRC6$ f- T' A7 E* _, ?  m
        //  7:VRC7' L$ r7 b2 M% n
        //  8:FDS
- U, z: s! v+ K; ~0 K( x. D3 Q( n8 [        //  9:MMC50 Q0 d7 ~; {0 o+ Z( [+ F- S
        // 10:N106) D, p, I+ A: |  n5 A* j* h; l; j
        // 11:FME7
* M, c5 }) V- m1 k        INT        vol[24];
$ V+ A+ \, e2 \1 `0 _& C        BOOL*        bMute = m_bMute;
) {1 \! M; \; s0 {; j8 b        SHORT*        nVolume = Config.sound.nVolume;
" p1 z' `' M- ~
4 d4 Z7 I4 T0 T& d9 T+ \* m        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ M4 n! ?& b  I/ m: L! v9 E0 i( a' [9 X8 P( Z) j" w# r
        // Internal
! x9 [# ], @  ~6 {% b" v        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;+ K: |* Z" A* b- ?) X* U
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
& `" ]& v% P% k* B9 P! }# I& x5 X        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 U7 W( [8 O9 |6 O% X* |1 Z
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
! m  l2 w8 o. A' i) `  o/ q        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
/ W0 e# q2 Q4 h) D1 l7 x( }+ Z- n) U) K) v8 \3 ~  N" f
        // VRC6' g" Y1 h8 h5 F: D# z$ D; Z/ w
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% }8 }% |1 t1 I% S9 t' A; C        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
6 ^4 Q0 i  R) ?1 ~, s        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;7 s( G; v2 S% t. C/ @+ }, O( r& t+ z

7 @6 q+ {6 ?$ M* T4 n        // VRC7
0 ~4 }! b7 P, C! s7 |        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;, V) C3 h. P* B0 s
, t9 [. K7 u* q# {. O1 v; G9 ?
        // FDS
, F( D& j/ r- @        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
: ?9 S* H9 D9 a5 Y9 r
. }' i$ K3 [& d2 R5 T7 ~+ I        // MMC5
6 A, d& Z6 n- D9 K* S: o/ \. T* W4 f4 x        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;! K8 w7 k/ z/ I! b) T
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
& B8 g: X" ]( B! Y  n4 b& p        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
$ S; t/ C/ o' S$ p) l/ S
  z" w" l+ ~4 _5 Q) F, r" H        // N106
. R3 F6 E, s% U) \  A        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
9 |* N8 |3 |  f* n        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" \# o  l, g( l& a        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- f8 x$ {* A/ `: U0 S        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 c6 {, J0 k9 J% t# G        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;1 c$ }7 Z" ]  k6 u
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- P& m, k% G# r% X$ h. \/ F+ P2 x3 f        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' b, q: v3 l/ q/ q) S6 ?1 P0 w        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- a6 X- ~/ G4 L' ?9 x. I. K# O2 y+ L+ u, S: @2 f$ E
        // FME79 `5 r1 |( r6 i2 w. _
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 i# D. J; Y# l
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# ]$ i1 O" J2 P2 r. G
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
: x' f# j; q3 S/ F9 H
2 X, ^0 e8 I( A//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
+ P: ?$ }& X  D" O# I9 h3 z        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;: b* o% `$ Z+ d3 Q- |
& z% {1 x5 t. m  i
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% q. n6 B& B4 F- _        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
, Z3 k# \. H! J* ]                QueueFlush();( X  C3 c, X% F
        }5 ~! f: E0 f9 `% C- v
- ~& ~$ N- y6 B4 k
        while( dwLength-- ) {
0 r- b. ?  [) Q/ h: V* g: q                writetime = (DWORD)elapsed_time;$ Z: K" {! s3 w6 @( x6 b
0 t5 u# z1 k; `2 V' r* A
                while( GetQueue( writetime, q ) ) {
. r7 x- R. g" V: N                        WriteProcess( q.addr, q.data );  ^9 ~" y8 Y7 h- t/ e# r* w0 P
                }
' _0 G. T9 P- T# o  [/ x; l; u4 g
                while( GetExQueue( writetime, q ) ) {
( ?' ]4 V+ O' b6 S                        WriteExProcess( q.addr, q.data );  _1 h: H9 {% U8 G7 m, r, m
                }3 ]% c6 E5 Q9 r% u
! D9 Y4 x+ Y5 X7 q: M' W
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
/ r  I- R5 U! t                output = 0;
" B3 r) @7 r4 F# H) s                output += internal.Process( 0 )*vol[0];, P% |8 |& f' O8 U& k8 ~
                output += internal.Process( 1 )*vol[1];
0 U1 V1 H" z) \4 \2 q: F( Z$ _                output += internal.Process( 2 )*vol[2];
* P+ N) y0 E2 Z- N                output += internal.Process( 3 )*vol[3];
$ o5 q% I! G& n" E, Q. c; w                output += internal.Process( 4 )*vol[4];
+ `" h2 v  C/ d/ U# Z& d+ [) m/ Z& w/ G1 r
                if( exsound_select & 0x01 ) {, f" R' F) }3 T9 P/ j* C3 N
                        output += vrc6.Process( 0 )*vol[5];
9 I( y- N. p5 {5 [. ?                        output += vrc6.Process( 1 )*vol[6];% o' }  L- n/ U. j4 ]1 x
                        output += vrc6.Process( 2 )*vol[7];
$ ]* R2 a7 I, q                }- D5 a+ {! p% j  o3 C9 [* @  }
                if( exsound_select & 0x02 ) {) J/ E' [4 h9 W! t2 ~/ x, J1 U0 n
                        output += vrc7.Process( 0 )*vol[8];
) r$ g1 v  ?# H/ s" |+ C                }  }! J1 i% }! J$ T6 x% M
                if( exsound_select & 0x04 ) {" e# [1 h& h  Y; ^- Y3 Z9 ~
                        output += fds.Process( 0 )*vol[9];6 F9 A+ N$ d  B7 T
                }
- _( c/ f. R% G                if( exsound_select & 0x08 ) {9 n5 B( A6 p; G% r
                        output += mmc5.Process( 0 )*vol[10];
& N9 c% `6 l/ v6 W0 l                        output += mmc5.Process( 1 )*vol[11];
8 l# q0 n. V' K                        output += mmc5.Process( 2 )*vol[12];
& o8 O3 D6 C" H4 _                }; T# s8 h( N; b
                if( exsound_select & 0x10 ) {
) O9 t- n% v6 J, J: B                        output += n106.Process( 0 )*vol[13];
: V, v! X1 T( b; O3 s                        output += n106.Process( 1 )*vol[14];
, M' \/ A( c/ n3 ^0 a                        output += n106.Process( 2 )*vol[15];0 x* g7 ?5 @7 n$ I0 }4 C/ w
                        output += n106.Process( 3 )*vol[16];% a9 g& D: H7 b4 a, t0 O' W
                        output += n106.Process( 4 )*vol[17];
) ?3 k4 a8 @9 Y1 e# S, N1 F                        output += n106.Process( 5 )*vol[18];
& s! t8 Q, w$ i. v8 u2 E                        output += n106.Process( 6 )*vol[19];
& V" p& S  s9 k: e- N                        output += n106.Process( 7 )*vol[20];
# A% V  t5 |: F3 c* o6 s                }
. w2 c3 \/ j7 {: q0 ~* C& \4 s  I3 p                if( exsound_select & 0x20 ) {# e  R+ V1 H8 L9 J
                        fme7.Process( 3 );        // Envelope & Noise& C' G! s  b  @" y: Q/ @
                        output += fme7.Process( 0 )*vol[21];
/ [" J* F5 d0 J9 O5 b) d2 m6 k6 B                        output += fme7.Process( 1 )*vol[22];3 ~$ j6 C; ~0 ?9 q+ |
                        output += fme7.Process( 2 )*vol[23];
/ B9 {6 b3 _! D9 f- d4 d                }
  X( r) k+ `0 _3 M- C) U8 x& L- I9 U7 }
                output >>= 8;
- p0 {& Q. y+ {2 M$ L) E# t) T
+ j, z  S- z! {7 v                if( nFilterType == 1 ) {
; @) l* m! F. X" h0 m/ q                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)3 ^; I/ [% P% T9 d3 W2 p- Y( `9 @
                        output = (lowpass_filter[0]+output)/2;
% O7 M% U, n  C7 X4 I                        lowpass_filter[0] = output;
! m" z+ M% e4 ~& j! b! a5 v                } else if( nFilterType == 2 ) {
& Y: |! D0 v! X7 ?* g                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)4 _0 q9 o/ z! a, S
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
2 v  z0 P+ K- O. d8 w                        lowpass_filter[1] = lowpass_filter[0];
& O: l+ f! x5 x/ i                        lowpass_filter[0] = output;
) P( o8 Z2 b0 q" `9 `) w& E                } else if( nFilterType == 3 ) {
4 H, _7 x5 \! P( m; n# _) `3 a                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
0 ]. N3 N; h$ E6 u. r                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
5 k& t7 I. W5 c6 R6 E/ o  l                        lowpass_filter[2] = lowpass_filter[1];
5 a# g3 n% c2 p4 @# J. Z! c                        lowpass_filter[1] = lowpass_filter[0];0 s3 A6 P  i7 I; E, j  d7 p, D
                        lowpass_filter[0] = output;
: Y) Q- o* Z, v2 ?! G9 h- M  o. E                } else if( nFilterType == 4 ) {
1 m& l) k; d' R: n                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
* F* ~7 K2 B' [9 |8 w# E+ q                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;5 R* R2 C; h2 B# C
                        lowpass_filter[1] = lowpass_filter[0];4 ~) F9 I2 v, ]' Y3 h
                        lowpass_filter[0] = output;
( p( F% p: l) b1 L* A6 S5 q. G                }
* V+ d9 N8 U/ B+ s- ]5 G; i2 R& W. H6 R0 }3 S+ o/ s) R
#if        0( p2 b+ B" v/ ~: v  M
                // DC惉暘偺僇僢僩* {% w- ^0 S0 @& o: |% d
                {
: X3 |4 L' A( P; i                static double ave = 0.0, max=0.0, min=0.0;
5 T  a  d* ^6 Q* i" E9 i5 {, z* s                double delta;
" `/ Y" T, ?1 t/ j                delta = (max-min)/32768.0;
) F+ w1 Y1 K5 p2 Y: R2 H  k6 e                max -= delta;+ l, R* E3 @' u: Y0 S: Z. e% x) n9 @
                min += delta;( r4 {+ V4 ^  [" D
                if( output > max ) max = output;
# ?& N6 v2 d" r8 X, L                if( output < min ) min = output;3 \5 Z5 y% ^  v$ V3 ^6 B$ j
                ave -= ave/1024.0;. [' ~, Y3 M: p9 M/ J0 G7 P' ~
                ave += (max+min)/2048.0;; j1 ?, d/ t' B% s* x
                output -= (INT)ave;1 {/ h% h* J; d% V) M; ?
                }$ q7 c6 H* `2 V6 G
#endif
* Q3 s# X! w8 H  P6 U  F/ G#if        1
+ ^3 p5 _" A0 A( \                // DC惉暘偺僇僢僩(HPF TEST)7 T( n" p. S- D
                {
8 y, ^, B. }$ ^$ |' y//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
  W8 ?$ D2 G; a' f                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# h2 l. l/ t3 {1 K$ P                double        cutoff = cutofftemp/(double)Config.sound.nRate;. v3 K  Q  s" B. F" i% [/ n1 K; P
                static        double        tmp = 0.0;7 X/ c0 y* r: p" M" R& n
                double        in, out;- c5 w6 Z% N' C1 I- @5 a

( z+ H& B3 i; J7 f9 E+ A8 A                in = (double)output;6 p, v+ c* k, {* t3 S4 G
                out = (in - tmp);
( X1 N/ |% e$ p+ M                tmp = tmp + cutoff * out;
/ L4 D. r9 p9 \7 v: i3 b. C. D# E6 T# b- l% r
                output = (INT)out;
1 P% S1 y1 r; a8 v4 m' J$ C                }
% @' C2 f- h# g* ?% ~- k7 k#endif
* U4 _1 L5 N/ U" _9 Y  [#if        00 }" j/ l4 c8 E4 k
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
  F4 p' \6 Q6 j1 r" W. q- @                {
/ T! s$ S" b: \" P                INT        diff = abs(output-last_data);
- T1 q5 [  R0 m4 |# m) n4 _$ y                if( diff > 0x4000 ) {
9 e6 s1 \8 q% ~# a8 U! r  N                        output /= 4;& p9 p6 `0 ]7 _
                } else ) C" S; b3 P2 I+ ~. T( y6 C8 P
                if( diff > 0x3000 ) {/ X# K- ]* x% V
                        output /= 3;! T( P: }( x0 M/ z$ k; M
                } else5 K/ V" e* V4 W" f/ _* X
                if( diff > 0x2000 ) {
6 P' |) Q, B  K: P/ ?                        output /= 2;- E& l. T- f2 M0 v. L
                }
7 j" ^' j8 H& K" n                last_data = output;
% f+ s# w: ?" X                }
  y4 W  z2 e7 E#endif
! U5 l4 Y0 b0 s9 S                // Limit2 D' S- A2 D; q* V0 |0 Z
                if( output > 0x7FFF ) {
* j: r& F" y  Y  G4 A* k5 f                        output = 0x7FFF;
! t1 V& D% s  U! m  z                } else if( output < -0x8000 ) {3 z& X# Y# i7 J; d" C/ Q- r
                        output = -0x8000;
7 o8 Q2 u3 e8 u0 f" J( a                }
, X( \( G; M: }+ I8 B8 D2 s
8 I. w8 p; [" I: U( p                if( nBits != 8 ) {& T) F1 H& X5 l1 \4 Y$ m9 H
                        *(SHORT*)lpBuffer = (SHORT)output;( L% C4 E0 H. x- U  a. r
                        lpBuffer += sizeof(SHORT);
# u' j1 _1 u: W. Q" q" u                } else {
8 j$ M9 S" z6 K6 v9 K+ ]0 d                        *lpBuffer++ = (output>>8)^0x80;
% w$ d$ K( {4 D& a                }% E" E( D: F. x& @+ v+ W
* |  h. r. ?' ?' G& W1 V# W
                if( nCcount < 0x0100 )+ S/ L+ p9 _: [7 O2 w/ ?, ^7 i
                        pSoundBuf[nCcount++] = (SHORT)output;* J+ ]. W+ C) H4 t% ^$ {

: U* l! _( x- V& V5 h0 @//                elapsedtime += cycle_rate;
3 Z0 J  W7 o' C9 a                elapsed_time += cycle_rate;! \, O* l( s' B. f/ |
        }
0 G1 E7 N6 h$ O  S1 U- Y: P* Q6 m5 [1 S4 H" e9 d+ u' L6 e  N3 |
#if        1
: O6 G7 k2 l; [7 Y; l1 D        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
7 v9 D7 j; u: j                elapsed_time = nes->cpu->GetTotalCycles();
2 M" Z8 L" {. m% I9 Y        }3 z# M: d  A2 ^, A
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {9 d- N( f; o" H& \$ N& d+ e
                elapsed_time = nes->cpu->GetTotalCycles();
$ N9 ~) x( K. @& j) F. i: _0 H. q        }( z+ _& y% Q% ?. I" t2 z3 I
#else4 @! p$ \5 ]8 x
        elapsed_time = nes->cpu->GetTotalCycles();
( z$ l. z8 l4 S8 E) B#endif
# Z* {: L4 |0 _1 e/ s}
$ K7 U5 q# V- k5 ^( m8 r8 u7 J: \2 z! z$ ^5 ?
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)* i" V) H5 X2 [% }/ Y+ Z+ q0 j
INT        APU::GetChannelFrequency( INT no )
+ P9 Z5 L2 b7 ?  L. K6 J{" r) J+ `6 C+ G3 p' e3 H8 y
        if( !m_bMute[0] )
7 r! W) D9 X$ [. x2 D6 H7 d1 c6 K                return        0;
: l" h  X6 C0 e0 n) Q, y/ k. S
# J0 Y& n6 r' s: d! W7 Y# G        // Internal2 r& x  G; j% S4 K- y! p# m
        if( no < 5 ) {2 H7 u% o6 R, ]" q: B: l
                return        m_bMute[no+1]?internal.GetFreq( no ):0;) C# `$ {( d0 B0 a7 n2 I( y/ p
        }
" s& [6 h6 C5 F# x6 E        // VRC6
0 b+ V3 z& H8 y1 r# E1 b4 p- M        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {! N# w! r8 c6 M8 g" @
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
+ a1 t, ?% Z3 v3 |5 F2 f        }
- V5 f0 N5 z; W5 H4 _$ u        // FDS
0 i2 B" b0 Z- T3 j' h        if( (exsound_select & 0x04) && no == 0x300 ) {
! L# j+ T+ V  `/ [1 V- q& d5 i                return        m_bMute[6]?fds.GetFreq( 0 ):0;
* O7 `/ Y; j9 x: X2 p        }3 u  T- @% P  c5 a* n' [7 N
        // MMC5
* g! I2 Z) [/ m% j        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
' w6 L' z2 ~  f2 w/ v2 m* R                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;' B$ W6 @4 e: q9 @* F
        }1 G' d  }. A; U+ l3 C
        // N106
- f# R0 w; @% T3 m& l' S        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {' n& E4 Q1 J9 k- \6 }
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
  W$ i2 c. A  }3 F9 W6 G' Z5 y7 p        }4 h) K& i, r" S8 {6 J8 k9 |
        // FME7
( l) O$ }* s( T        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {" n0 g0 Q8 H& M: N4 f; A7 n$ _
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
) l; q) \) f; F. k- {* w# c  N' K        }% R; K; @" w: v) h7 c0 I6 Y* I0 W
        // VRC7# x1 t( m! t# e, \: y9 _) A
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {7 ~6 `% H4 B5 d% f2 f8 D( j
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;$ e0 T7 j  v8 S* A  S( ]% @( u
        }, Z4 h1 j/ l$ b0 j2 k! Z
        return        0;1 n4 @$ ^3 b; Z+ v+ j
}
3 p/ ^. V1 y. @4 w8 y% S: F% A, b7 T1 p9 Z# g3 {
// State Save/Load
7 ?+ s* F7 ^; Z6 Q) jvoid        APU::SaveState( LPBYTE p )
! L; d# {; }- F+ D. A. w% r{
; c, q  H5 N- J6 M#ifdef        _DEBUG
- k: m( q9 G6 _, f+ F6 c7 @( N: Z/ C5 ALPBYTE        pold = p;
# s+ w+ q0 @. g9 @6 e- U#endif
( k/ `4 h% d0 F: X% T. W
1 L/ M: N& K- ]5 l        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
( u) V8 u6 u9 g/ l6 S        QueueFlush();5 e) }, A- W% y5 {- d

5 `6 ~3 X% V7 I. Z& k/ T        internal.SaveState( p );
+ E' ^* V) \, k        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
& m4 u7 T# \* d8 V0 |" Q# i
% D4 d2 h4 h! [: g        // VRC6) w, M+ u# T6 [: V; G5 W
        if( exsound_select & 0x01 ) {
2 h' e; W, f+ P                vrc6.SaveState( p );
  ]% `2 S6 \1 a* r: f6 F6 p                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding! n; T' G' v! ]8 B) b0 N$ e
        }/ i4 ]0 r/ l7 y6 Z+ P
        // VRC7 (not support). x- j, L; o5 h: ^5 u$ e. _
        if( exsound_select & 0x02 ) {
' a3 q6 R6 Q/ ?8 z' a                vrc7.SaveState( p );
0 i& A% d6 ~2 {& o  v% o0 Q& V  X                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
& }4 e# V4 \) L        }# K: @% B9 s; m) Z* m
        // FDS
7 k1 j6 L' l! H7 ?# J        if( exsound_select & 0x04 ) {
; d+ c5 Q+ ?' L/ @# h1 K; \                fds.SaveState( p );
- l6 _  R" ~6 U. C                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding" X! B) Q. V; ]7 K+ K, L
        }7 p0 d+ K, S' [- O1 G
        // MMC5
) m9 q% {# E8 g8 Z        if( exsound_select & 0x08 ) {
. M% G( {7 ~' _5 I, B2 ]                mmc5.SaveState( p );
' V6 v# H8 G8 p& z                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( \1 L9 o& d: W* C! S% V4 d
        }
4 }; q3 z" @7 F1 V& j, G3 I0 E/ j) R        // N106. v& N/ H$ x8 p  q% j8 y9 ?. W3 Y
        if( exsound_select & 0x10 ) {
% k3 q3 A3 M( P' ]                n106.SaveState( p );9 U2 e+ v. Q; i& n6 C: K
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
2 O" j; x: V/ @" q1 g* l% L# {        }& r: k$ h) t3 S! G
        // FME7+ @+ i; ~' [% e3 h- I3 z- [. `3 m" y; x
        if( exsound_select & 0x20 ) {
, i5 k3 q4 O4 L# D                fme7.SaveState( p );+ V9 U; @( u$ q( A; |
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
& P  s6 f% j! }/ u4 q        }3 I6 Z$ J- ^: y) P

8 ~( M7 X$ C4 T) \4 S0 p#ifdef        _DEBUG
! l$ O$ Q  n" ~9 xDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
0 n2 I1 U" U/ U+ L- M& f$ Y#endif
9 \8 O- c2 {- C6 B1 ^0 n}
+ _; d1 S7 }. z- M0 J& z8 l4 @  O7 E5 x2 d+ z
void        APU::LoadState( LPBYTE p )
% Z0 U/ Q$ z6 X* g- _4 Z  `, A% ]{
+ z$ r1 A% }8 |6 `: y; ~        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
7 i8 i, f- C3 _3 A        QueueClear();) W* x% J) n: m+ h( M5 y% p7 H: z

# Z7 b% ^: ~+ g0 N+ v        internal.LoadState( p );
; ~1 ], f. p5 x- O  k( Y+ W, |        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding, t% }8 M$ w2 r

8 i0 q) J- \# p- ?. N* b" Y        // VRC6& _- k7 L% S# w$ l, U$ g( A
        if( exsound_select & 0x01 ) {
  |& c4 e! |; @! c: A                vrc6.LoadState( p );
0 E" M# h2 e* s& _; o5 M# V* l7 c  L                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding$ M' X2 t/ T3 ]9 A3 R
        }
2 `: q5 _4 N+ [4 T4 n/ [2 t        // VRC7 (not support)
: F9 k( ^, A9 w0 @        if( exsound_select & 0x02 ) {) O0 a, C- H' ^
                vrc7.LoadState( p );) ]8 @' _" M% b" w
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
7 t* r: o! S; L9 o7 r$ Y" S5 k        }. M' {* m, H, T- ^/ T4 r# o
        // FDS
" R& U# C# M8 i- s' t1 V7 Y" w        if( exsound_select & 0x04 ) {7 q' G* Y' s: L+ W+ \( ^8 T
                fds.LoadState( p );
7 w% O5 |. U5 u. }( ^                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ y& _5 T  M6 [5 c! Y& H, t
        }
$ s, ^* n9 Z. d/ e/ _: l9 z        // MMC5
3 C* k0 p+ j' ^8 l# |  T, u        if( exsound_select & 0x08 ) {4 y8 O  t& A, _: f: l# V
                mmc5.LoadState( p );! r7 _: k" j0 D3 T1 p
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 a' N3 \3 u" p        }( q2 ?5 x! D' c; K9 J, w9 p
        // N106
) Y9 V5 G( Z4 E: ^5 r        if( exsound_select & 0x10 ) {
7 d: Q% e* \6 m                n106.LoadState( p );0 G9 b9 F" _- ?$ Z
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& x2 {2 l% x$ I* k
        }
2 q0 ^1 @! h( V. M, g        // FME7
; x! P; j+ n/ ^0 `        if( exsound_select & 0x20 ) {6 {7 _" T( f* T5 b  W8 M# @
                fme7.LoadState( p );. N+ F( i( G3 r
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 V4 `, ?, Q8 T* c/ `% f0 G
        }
9 B( q5 l) C; f4 o( K}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 V9 L8 \$ ~/ G可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。! c5 j! k. i: x- l; y4 ]
感激不尽~~
* j( \+ i" O0 r3 S
恩 我對模擬器不是很有研究,
4 I9 n1 X0 E$ Q% N  {3 V) L雖然要了解源碼內容,可能不是很困難,
* o* }' X" Z% t" }不過還是要花時間,個人目前蠻忙碌的。
5 L. g% _2 G5 k6 X0 W4 K1 d" D2 i% i4 |) M, }* `/ ?, ]
給你一個朋友的MSN,你可以跟他討論看看,
1 w, j& F0 [9 `# J+ |& O% ^0 `他本身是程式設計師,也對FC模擬器很有興趣。
- P- J+ \- |/ W9 s
! _4 I. w( z9 A& o  s7 _MSN我就PM到你的信箱了。
6 E8 I  U" [7 t
' P" r9 e: A4 m& P+ T& J/ d: U2 E希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 / c) H' z& e0 v  I+ T9 G& x. c5 P
呵…… 谢过团长大人~~

( G% M! w# q# ]1 p$ Y$ e2 e) ]* N$ F& y. O, K4 h" s1 w
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
2 B3 n# l5 ?( M: ?! [* U; M# `3 y团长的朋友都是神,那团长就是神的boss。

& D. C2 ?0 s% d$ }哈 不敢當,我只是個平凡人,
! }. M# V1 x/ e$ P要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙& E' G  ]- O9 H  ]( U
ZYH
. j8 f* i6 ^/ k/ BQQ:414734306
% B' a" v3 o5 x- ?( m1 V( gMail:zyh-01@126.com3 x0 Y. V! t5 B( ^+ s
) s, n! n. t5 i9 _4 I+ n
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 ' j) P/ \( A0 ~) w8 s
再次对团长大人和悠悠哥的无私帮助表示感谢~~

# k0 r0 X2 s# ?9 l0 z" r不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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