EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。3 l- O. Z: |* P' a, z$ j# R/ }6 D
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 {( }: y; v  J: W; J9 M7 B这里有相应的模拟器源码,就当送给大侠了~~$ p5 {: t2 K+ U+ E" p
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
/ \" _" j& ~0 s: ]2 X5 _能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 R: d& m1 G+ e0 q: i, I- U- v% x% X
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 c5 d8 O6 J) t* F; j0 B: }这里有相应的模拟器源码,就当送给大侠 ...

) I5 ]$ x& x' }! J聲音部分(Audoi Process Unit = APU):
. Y& n) m0 c, m/ [1 N7 o3 P) o.\NES\APU.cpp6 X0 H9 X& K% h. h+ z4 V6 \( g
.\NES\APU.h( _- G) o( x2 H! Z

6 }- R! O, ~; S
! z7 {  s7 |' X9 M2 K影像處理部份(Picture Processing Unit = PPU):$ m( G; W/ u% N# I
.\NES\PPU.cpp
% y& s( u/ v$ @& K8 M9 G, |.\NES\PPU.h  [) N9 @$ Y7 `: ]
2 ]+ Y4 |& l7 `( D0 u! b
如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
( u9 r: V+ e: B: ?& ~, C2 R(由于很多专用术语和算法机理都不明白,所以看不大懂……)
- f9 r" |3 b# Z//////////////////////////////////////////////////////////////////////////' x: w' X' \9 L/ p, o( @5 [3 X
//                                                                      //2 W" ]6 G+ ]1 f
//      NES APU core                                                    //
2 K/ Y# B5 N9 S; |& d//                                                           Norix      //( [3 e0 C! B/ ~- d
//                                               written     2002/06/27 //+ N$ o9 R- G3 Q0 W. h
//                                               last modify ----/--/-- //# W( k1 l( `% m0 Q# D! W! e, t
//////////////////////////////////////////////////////////////////////////8 [- W6 k! t6 ]( c' \/ d
#include "DebugOut.h"
2 }$ _1 N: t  F7 f#include "App.h"1 A& C" B3 J  `) n% [6 C8 v' }- l
#include "Config.h"/ A  J+ g& h0 f6 O' S4 q

9 ~3 h& v& _; T' V" ?#include "nes.h"
) o  O- V9 d5 ]  f9 M. @#include "mmu.h"
! P6 z9 C; J8 J0 Q#include "cpu.h"/ ?7 n' S. C/ k/ F& O$ _
#include "ppu.h"
; R5 ^+ D  k, [9 U2 p#include "rom.h"
7 z1 N9 l2 ~; @#include "apu.h"! N. m" s* Y# T  ~# H7 U

) O! l5 A$ \4 C" B; G" l# Y# I// Volume adjust& i& ?6 D& K$ b/ @5 @
// Internal sounds$ w) }4 m* y6 n7 s$ @0 {
#define        RECTANGLE_VOL        (0x0F0)
; `! S/ D. ^/ Q9 i#define        TRIANGLE_VOL        (0x130)
( W' T/ x* q4 ]2 G9 c#define        NOISE_VOL        (0x0C0)- T+ R& Z3 s* F" x; P
#define        DPCM_VOL        (0x0F0)' j% J7 E7 k9 C: t8 o1 F
// Extra sounds
3 C$ w. x0 r, f+ |7 ~- W" b#define        VRC6_VOL        (0x0F0)4 Q, W9 q; O6 h
#define        VRC7_VOL        (0x130)
' `2 b& T6 @/ l3 z: a; ]! A#define        FDS_VOL                (0x0F0)2 U/ x3 U# m0 o, v
#define        MMC5_VOL        (0x0F0)  k0 G: H# p7 T( ]
#define        N106_VOL        (0x088)' G, h7 b$ o1 k8 i! b; h8 Q
#define        FME7_VOL        (0x130)' h3 W- G; L0 e0 K
3 O+ J, W+ }# A1 X3 I
APU::APU( NES* parent )
5 g. u& B7 V+ v{# h6 ~) K! ~9 v7 M8 b8 E
        exsound_select = 0;
. B5 k) R" x! Y* D7 v3 m2 C
3 m, U1 X, `8 n1 O! q( w' j  o        nes = parent;
6 e4 L4 ?" \8 G        internal.SetParent( parent );
" a2 j1 v5 j* R" y8 a' R0 O$ b6 g# E  O5 g, a! r2 X$ g" y1 b
        last_data = last_diff = 0;
9 P5 m  ^! t* H" }4 E$ t: _$ B
6 G/ {$ L1 S' e9 g, N) j        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );! T& d/ t' l5 R6 T: V9 V
/ S8 Q' o4 n; @
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
0 E0 T+ S* [* y% l        ZEROMEMORY( &queue, sizeof(queue) );6 O4 B9 q: y5 P2 T
        ZEROMEMORY( &exqueue, sizeof(exqueue) );. [  s; l& N2 ^- @  b  @
& m. L1 N  Q7 A/ ~9 g$ g/ j3 V# s
        for( INT i = 0; i < 16; i++ ) {1 v3 B+ Z+ R. H8 n& h: k
                m_bMute = TRUE;
! Z: C% U: |7 Q        }, ~( S% ^( r7 ?
}
; I1 X& T) |  @% o) |0 f. x( Q6 K/ ]5 H0 H  J9 _5 W/ v5 H
APU::~APU()! @  N& M/ J; E' k" @: }2 Q+ V* f
{" N' j- |1 s* R: _
}& M" V& [. N, n$ z: u3 a" \

  Q" s; H& B# C& |+ \void        APU::SetQueue( INT writetime, WORD addr, BYTE data )# k) U7 S) c9 u. c0 d( h& \
{
$ R5 A" B9 q$ F8 j- B        queue.data[queue.wrptr].time = writetime;! a3 f5 h3 R6 q, {& p
        queue.data[queue.wrptr].addr = addr;/ o- ]5 n  @6 m
        queue.data[queue.wrptr].data = data;
* R2 R1 u7 q0 t( X; z        queue.wrptr++;7 {! X6 f5 m( Y( c
        queue.wrptr&=QUEUE_LENGTH-1;
/ \- W7 w; m% p; T, k        if( queue.wrptr == queue.rdptr ) {
! ^! ~5 U7 S4 m$ k4 b                DEBUGOUT( "queue overflow.\n" );
# v8 Z! Q* C$ v+ _% j2 \        }
! k5 b! a& j% M6 g}& \0 \  H7 \( m! _  `% N

$ G; G! v) U2 J0 r5 _* fBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )& P! w; x9 N: ]: c5 b
{
2 H" c2 P) o4 U9 S# e  d        if( queue.wrptr == queue.rdptr ) {% x* a" R  O+ o' L
                return        FALSE;
6 f3 Y" w$ `% d4 T, ]        }
% D; ]* n2 }0 Q1 Z# D( ~8 @0 G        if( queue.data[queue.rdptr].time <= writetime ) {
3 ?* g6 H2 l) c: T                ret = queue.data[queue.rdptr];
$ H+ f: W2 O( i* I- s                queue.rdptr++;2 |% g9 K4 _5 T% J7 |
                queue.rdptr&=QUEUE_LENGTH-1;
; N" W: _, |' b; j: Z. W                return        TRUE;- z6 A, d8 d# y$ f; P: U1 M2 F( ~
        }( E! {9 P0 l# b& G1 u% i# U
        return        FALSE;# U) G7 Z0 g" n6 k0 K5 f( b( I0 b
}  D' O! [: ~7 l% }4 G8 K6 n7 d
6 O* l: }; l1 e1 b: K$ Q
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
! l# H1 W( Z5 ]{
# \2 W$ N0 Y8 }# N1 m        exqueue.data[exqueue.wrptr].time = writetime;! g& H7 K4 Z1 G& l. {  ?5 G* N
        exqueue.data[exqueue.wrptr].addr = addr;
* y/ x6 [8 Y! k" d1 S3 f2 R; a- `        exqueue.data[exqueue.wrptr].data = data;
; d. G  M1 o, W  v2 r! u# D1 `6 h& w        exqueue.wrptr++;
  s8 h4 K" D+ o- F        exqueue.wrptr&=QUEUE_LENGTH-1;
9 I6 r0 ]* i+ S        if( exqueue.wrptr == exqueue.rdptr ) {
4 O5 W: J, r' ?7 Q" C3 L( }- Y                DEBUGOUT( "exqueue overflow.\n" );* v* |% h2 i. s- \- y0 i
        }, Z; k! R% |$ _$ D3 j: ]- M
}
& k  W6 r5 c9 ~& V, N0 i8 v: G& i$ e
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )# @+ t" T0 P7 Y5 I) N
{
. O% M* ^2 a3 B$ L0 I$ ]$ g        if( exqueue.wrptr == exqueue.rdptr ) {# q: O4 {* b) ~' H
                return        FALSE;
8 b: W0 G$ G; ?& [6 ^' C3 @! D- t        }& f7 m. K$ i, ^' f+ ~' y
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {7 h8 D9 I% {7 v  Z: p
                ret = exqueue.data[exqueue.rdptr];
9 V2 Q2 z  t8 w3 }* D$ J; N6 @" P                exqueue.rdptr++;
' H. V* ?8 U. Z% a, j                exqueue.rdptr&=QUEUE_LENGTH-1;
7 m# d. \) z3 t/ V7 e  v' r                return        TRUE;. s: s! T- h8 \0 K+ _
        }
6 O% y) r4 r7 m% W. ~1 {        return        FALSE;+ {! s  A0 t3 ~0 A' ^; x& `
}
# x8 P2 J% l( n/ m$ o0 Q+ }+ d4 Q' \3 X: c2 T( C" B" h* i
void        APU::QueueClear()
5 w* e1 C2 g' j{  S# S, d9 i' C8 X0 a2 {2 b# `7 ?
        ZEROMEMORY( &queue, sizeof(queue) );3 T/ u) c4 L+ y" L9 O! j
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ n: j# q0 k8 j" r}- @9 E% ~) j- P; R& S3 V0 w
. |& f: k1 l) F  p2 Z1 R
void        APU::QueueFlush()5 _( E6 g: s, ~4 I3 d7 G" _$ \
{
, x4 _, z* o0 w2 m        while( queue.wrptr != queue.rdptr ) {
( I4 i( g& x8 o3 A8 j3 A                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );  k$ f3 f% H7 U! Z+ ]4 c- U# a* I7 \
                queue.rdptr++;% v  c  M6 ^+ R! B' N
                queue.rdptr&=QUEUE_LENGTH-1;8 L0 _0 v3 ]1 Q( m4 G: K' w
        }4 f7 d6 T' y( K9 W4 {
" V7 ]# h5 M* N! h
        while( exqueue.wrptr != exqueue.rdptr ) {6 B! q, }  L' ?# Z% y' b
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* a0 ~, R7 s; U                exqueue.rdptr++;
) e! B/ W! K2 Z+ Y1 M+ {) Z2 l                exqueue.rdptr&=QUEUE_LENGTH-1;. a! y9 L) e3 s* m6 B) m- x
        }
/ F$ U& B2 v& o: g) a5 l% {}7 m% E: Q( B- _+ \4 {' P

! F5 N; g3 K1 E5 ~void        APU::SoundSetup()
, ^$ V) M5 i- U* J% {{
1 I3 @1 i, X% k& m3 {        FLOAT        fClock = nes->nescfg->CpuClock;3 t1 I6 B) l# q; g2 |. [
        INT        nRate = (INT)Config.sound.nRate;
2 D5 K/ T6 U9 {9 }2 M' ]6 r        internal.Setup( fClock, nRate );. _3 L" O: o- x& e! U6 O7 K
        vrc6.Setup( fClock, nRate );4 y# X; a2 j4 m) G4 h* u
        vrc7.Setup( fClock, nRate );2 I3 Z# G" q# e" w3 @5 F) [
        mmc5.Setup( fClock, nRate );  y6 M. V- j* ~: ~
        fds.Setup ( fClock, nRate );
/ b, Z5 W" G) O9 J; k& o        n106.Setup( fClock, nRate );
" W1 m; n6 u5 W0 F( d* [        fme7.Setup( fClock, nRate );6 z' x  c" ]( d$ D  _+ u( e) r
}
4 p# B( k5 M$ t0 E  h, y
, {2 Q" \4 E! T  y- t: Hvoid        APU::Reset()3 w: g- w/ A8 T
{/ h: E+ G5 t  L5 k2 p6 ^9 S& H
        ZEROMEMORY( &queue, sizeof(queue) );
3 ]: {6 Z+ w) o4 h! h% g        ZEROMEMORY( &exqueue, sizeof(exqueue) );. S7 M6 o0 L6 b2 p

, {* n# W. s* l# r  c* y7 h        elapsed_time = 0;
) C4 s' _8 e! Z8 e6 |; ^; {! o
9 k  j# ~- a! y+ E: U) o( \        FLOAT        fClock = nes->nescfg->CpuClock;
( B0 i% {4 G2 W9 v. R/ x, \        INT        nRate = (INT)Config.sound.nRate;/ i0 i: h3 P5 o* b8 D4 c
        internal.Reset( fClock, nRate );
& _) N9 Y$ E: V! d% G% P        vrc6.Reset( fClock, nRate );( U) U# B. C) I6 k
        vrc7.Reset( fClock, nRate );, \9 W* Z1 Z+ S/ ]' b3 R# @2 r
        mmc5.Reset( fClock, nRate );
0 w( X" `6 A$ Y/ s        fds.Reset ( fClock, nRate );, ^  l. m6 h0 a+ q( y! ^$ D
        n106.Reset( fClock, nRate );# O6 I8 F7 d+ M" l+ o
        fme7.Reset( fClock, nRate );
0 k% R+ _& U: [5 o) R3 Q
* ]. G3 O' }0 z- M6 B* f        SoundSetup();, L' Y8 n6 G: |/ ]
}
, V* S1 s5 Q5 P* O6 T
; G' d  ?. c7 c( j. v) ~. Svoid        APU::SelectExSound( BYTE data )+ W. X( k, F2 s9 k+ B
{1 k6 |) w& Z% S/ I
        exsound_select = data;
" x- _5 X$ L+ N}
$ Z# W0 G7 C6 w" {: I
& t$ [! R0 Z7 L% ?8 z# f7 o5 D" fBYTE        APU::Read( WORD addr )* N- B$ I0 G  k. m4 A6 B+ S+ _* b5 a
{. n, M7 U2 m; s, v6 d
        return        internal.SyncRead( addr );+ s. R* }% a$ f7 y3 K' d+ B5 t
}) m9 Z3 m1 T+ x/ b

6 W! p; [6 t, `/ Q& \+ B8 gvoid        APU::Write( WORD addr, BYTE data )
' u( r/ `4 Q, [3 `{" W/ [: e0 O: F8 C# |* {- ]
        // $4018偼VirtuaNES屌桳億乕僩
; Q% I4 R: p8 v/ I1 f        if( addr >= 0x4000 && addr <= 0x401F ) {8 f% E7 Z& v9 z) [" y
                internal.SyncWrite( addr, data );7 P/ r( H' S$ `( K, @
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );# [" Q/ i0 G6 v# g
        }4 c! a# [. t. {9 O- T6 ?: V' u; x, X
}& w2 P. [  Z: g1 s& r$ ]. Q

4 X8 k  g9 |! KBYTE        APU::ExRead( WORD addr )
- h2 K8 ]9 u; x2 M7 T! o{- F- E& Q- h8 R+ O# h7 N- V+ n
BYTE        data = 0;
$ j2 E4 x; u3 n" b
, F: z+ x0 @4 w) M( \        if( exsound_select & 0x10 ) {7 z( d" P: |4 r* r
                if( addr == 0x4800 ) {
& q$ P9 I1 V7 o+ n1 ]' q                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
! J, S  g/ |! A. v                }
. B3 t5 a; Z9 O6 o        }$ x# c8 z0 h5 x, |0 e- w5 u
        if( exsound_select & 0x04 ) {
. F% S$ S5 f% S6 g! {% n# P                if( addr >= 0x4040 && addr < 0x4100 ) {6 |0 l* U+ J8 |; v+ `
                        data = fds.SyncRead( addr );8 Z- _7 x9 S  w8 z2 Z+ J
                }
1 }2 N. K' i* ~& d9 ^. t8 C9 I        }
8 ?0 S( f) W- s+ B* l7 _/ l# m        if( exsound_select & 0x08 ) {. \, o' B2 @9 E6 |& K/ D
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ k9 E4 ~% Q2 g" ]: ?8 `                        data = mmc5.SyncRead( addr );" `6 E% E- C$ l- ?" P
                }+ @% b  C2 y: N, c6 Q! G: c1 v5 M6 N
        }  O7 v3 p4 d$ o7 Z4 `% t
* j9 Q$ @# [$ A  A' n/ Y
        return        data;
! Y* k( B$ t9 I& \+ M/ q6 ~}8 U; K6 \5 J) b  M  c/ {$ q) w5 L1 d

6 a1 z. l' a6 ~8 Lvoid        APU::ExWrite( WORD addr, BYTE data )
7 k; V9 I+ b! d- z( J{
3 l4 u" i% }; i3 e0 f        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
2 @8 r2 S& i: P% Q! G! h7 K8 i& ^9 k& r5 e2 r+ ^0 W+ v
        if( exsound_select & 0x04 ) {6 F  y- i& P7 n; S# ^+ g" n1 f
                if( addr >= 0x4040 && addr < 0x4100 ) {( |* o; q1 Y  s( u
                        fds.SyncWrite( addr, data );- N+ n8 R( t8 Q4 o0 n
                }& i$ ]% i/ O7 `- y' _
        }
& z' a2 T+ B9 n6 [6 m
- C/ J1 V: X, w% {        if( exsound_select & 0x08 ) {
. |7 y# r8 F7 A- s7 Z                if( addr >= 0x5000 && addr <= 0x5015 ) {
# ^$ w9 K$ y  [. |0 ~. I4 X% `                        mmc5.SyncWrite( addr, data );
$ t7 w5 X- H! Y* e! `                }
( A* b/ v1 s$ @, ^        }1 `% T8 s( [1 u& y
}' H4 Y& P0 Y( ?  [4 T
/ l- K# ]6 Z: o
void        APU::Sync()
6 T( `$ N1 D  Y0 z! g. k{% E, Q2 U: ^" a' }2 k! y
}0 `8 A- M4 N( n, c3 N; y. J

7 e, P" p& m4 r2 u. ~  o- lvoid        APU::SyncDPCM( INT cycles )) N! N" _" n( }6 f1 c2 P
{
' B3 k# k6 R1 }8 X' V6 l: g/ W        internal.Sync( cycles );
' V, l4 T* n0 }! _  b3 ^8 W; H3 k4 u/ G+ u9 ~6 L
        if( exsound_select & 0x04 ) {
' B8 n$ c6 g. f( g" k# C$ n" j                fds.Sync( cycles );! k- B) P! c* |$ h% L& U
        }
* _, \3 [  W) ]3 }- v" U, u; p3 w        if( exsound_select & 0x08 ) {
5 t0 t& G- T$ L                mmc5.Sync( cycles );/ V0 r; N0 v' w: V1 t5 \
        }$ O8 m8 O6 M, T# e* g
}9 T/ E. Q1 E- ?9 F& ?- H

, K/ R9 z# p; A% cvoid        APU::WriteProcess( WORD addr, BYTE data ). [/ _5 Z& o- D! Z. G
{' j% O% H$ k: D! v( T2 ~6 V
        // $4018偼VirtuaNES屌桳億乕僩. I6 v$ }1 N. y" V9 L. I* U5 ?. \
        if( addr >= 0x4000 && addr <= 0x401F ) {
( [- `. o; u+ d2 T) ~2 n; U' N* B                internal.Write( addr, data );+ d: t9 U6 z6 D$ y
        }0 |9 d5 k" b0 K6 ^! B. J8 ]
}
1 d* v+ R* f/ {% X. L6 [. \; l
0 ]8 m! M+ v; o$ mvoid        APU::WriteExProcess( WORD addr, BYTE data )* c! q: s* x: G
{
5 l! J7 \- k7 N        if( exsound_select & 0x01 ) {' O6 T6 s, A% a% J1 Y, d
                vrc6.Write( addr, data );9 F+ O. j! d: z: \8 G- Z. s  l- ~
        }0 u+ U( H0 t; j" s& p
        if( exsound_select & 0x02 ) {8 V  g8 ^8 K% d, \/ l
                vrc7.Write( addr, data );+ o1 A! r$ m: W$ h# e. a# `
        }4 C2 \" j5 ^) W8 f7 {2 d& ~# c/ g
        if( exsound_select & 0x04 ) {- J6 u6 m4 s0 l) l, `& c  a
                fds.Write( addr, data );
9 j) d: g4 m" ?: [2 [8 a        }
. `: Z  S: s: q0 o        if( exsound_select & 0x08 ) {% E- ~: i/ z( P7 h" L3 P
                mmc5.Write( addr, data );
4 m2 `) k) x- T6 a4 G, R6 g3 X        }
7 h) H1 s3 H; z        if( exsound_select & 0x10 ) {
7 b2 p4 a; K$ \, C) P* H                if( addr == 0x0000 ) {5 q, t+ Q) D( l& P/ T$ Q
                        BYTE        dummy = n106.Read( addr );9 @" Q, s7 }- O0 Y
                } else {
+ S! q- X9 q1 |$ S                        n106.Write( addr, data );" S* ]$ {/ R5 |0 u8 i9 R1 p( C) x7 `
                }
3 O; X" z" S6 M$ r/ C% i( \- j        }
3 A0 ?0 Y% {) ~0 ^, \        if( exsound_select & 0x20 ) {
0 I! t* ~" ]) P& S4 N* E( t                fme7.Write( addr, data );6 {# f, a" @1 m
        }
0 Y' C: \* S  O  l* E# ]! c' b1 }}
: H9 H% l- V/ L/ L. u" t3 A
- n% e- ~4 [1 ^) W  G) t1 Mvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )% S) Z5 M3 K  n/ S
{5 ^/ g) A# V+ y' T$ h
INT        nBits = Config.sound.nBits;
* N- `+ E; H# |: a( @' ZDWORD        dwLength = dwSize / (nBits/8);2 U7 x9 B" T2 t: J9 n
INT        output;0 h" N1 ~" T# a
QUEUEDATA q;
- j& n! }: w2 E/ K; b3 HDWORD        writetime;
$ J, C/ H" d$ L  E9 j$ R- L- ~/ F9 X+ G/ P3 e7 T
LPSHORT        pSoundBuf = m_SoundBuffer;! i1 g% a' ]0 i
INT        nCcount = 0;
3 a/ _" o5 v- K& G1 n- z
# d! f3 `( r: z6 B3 w+ _INT        nFilterType = Config.sound.nFilterType;" e7 u' B. o7 u) Z$ C

, v6 J" F. u, ]7 s* M: d2 k        if( !Config.sound.bEnable ) {! c. y9 C6 b9 p
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );0 j! \* u) J  g
                return;$ e: H8 N5 E: X( ~* ~
        }/ q, K& E+ h- u2 Z8 H

  E( M% C7 ?2 p& d) i+ I/ }        // Volume setup. E5 @8 k# R* b4 \! a& ]3 P- i
        //  0:Master
2 T' B% B  x6 l1 w4 @        //  1:Rectangle 1
9 }4 ]% k- q% T. P. k: H+ s% K        //  2:Rectangle 2
* m* O* i2 r( O: o        //  3:Triangle1 Z4 Q- c& V8 t& K% Z9 A3 k
        //  4:Noise  s; Z% L# \" j7 Y3 i; o2 X) K$ O  W
        //  5:DPCM# B0 j( _* a8 d
        //  6:VRC6: s  X: q# D0 ]1 Z, ?" V0 J
        //  7:VRC7: T8 u  S  S  e% |) c
        //  8:FDS
9 {* y7 M1 a' a4 y. p% t' ?. {        //  9:MMC5
: R# X$ e6 I+ T! C# L2 P        // 10:N106
0 a! v# y5 m) F# a        // 11:FME74 r( I& `3 c; U6 j! f6 S
        INT        vol[24];
/ v5 _0 U- L8 x. J        BOOL*        bMute = m_bMute;
7 F6 V# w) m' s) }5 g1 K# U0 d        SHORT*        nVolume = Config.sound.nVolume;
8 R! p1 R, ~# W& b( }. _. d2 Z$ E$ Q3 }
" O# I& Q8 n( g+ y" Z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;; Z( M! V8 _- i6 G- l# \
' c+ G/ ^" d' P
        // Internal
9 h( O* S/ N* k! z7 a- X6 I        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
! D# N$ R2 b9 k# h! b1 j        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
1 `2 v: k) x6 K; p        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
8 E' z6 b- X* h        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
2 e0 i% Z' y# ?( s' r        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
2 ?' N- r& W7 R: y( ~: S
1 {6 n' f7 k# N7 r3 u        // VRC6
$ |- G0 L% g1 j/ B$ Z. ?        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;5 U) H% W0 A3 ], w% U: `3 z/ o
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
' [9 I0 Q9 h( a. p' s  k3 T. y        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
  T  @3 I+ v% X+ J
: I; g6 }0 o) m0 Z8 y# n        // VRC71 Z5 z2 ?( P9 i6 D3 E6 f! O
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
3 h. m. Z& ?% a4 l7 m$ |3 G+ P- `, K
9 {- m/ p4 m* y3 g2 b8 M        // FDS
# ?# G" O- X, I        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;. e; |3 {5 t6 g! l' M; Y: W& h5 J5 `

) M* y6 l- u5 j) i, k3 |; W6 v& ]        // MMC5
9 a" y. i& T! P6 e        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;2 C- |0 @4 X2 G8 b) h5 a* d
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
3 m) F6 o, ?: g        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;+ S- q% t2 n) ^8 `
1 y9 H6 Z" Z3 b, o, ~1 I
        // N106
; z3 I. L0 T* ~8 x! k3 G        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;6 n$ W1 X! G& h2 m: m6 `8 M5 e
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
- n4 k, H9 H) q) m        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" L9 c; O# ?7 A8 U( x$ m
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;4 @2 H7 S9 ~- ]; t! L
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 e" v: ]6 T$ N8 ~" l+ U        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 e' B/ ^- G- j) M        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( f5 f% F1 H: a- q6 f' }        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" W8 C& }* I1 S# u; \

! L" b$ Z/ \4 y% J- [' _        // FME7
8 O3 F/ c" @5 V        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
  x0 C3 y- F7 n% ?; f1 x( Z        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;5 N! T2 ^7 ^( e* O' H4 F8 l
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, y- m: T7 W- ]$ ~) t: R( k; I
. ~. N& O' m8 K, N" f9 O# u
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;  M, w) D7 C9 _& r
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
, W0 y# Q! M( [$ t1 o; w
% o: H; ^7 J/ Z) Z" E8 ?1 e% R+ }        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟. d8 X' h: \$ C9 j. T/ @+ Z
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
9 l" G, G& ^4 ^                QueueFlush();0 C4 u% i$ _' E+ G$ _* A2 m) x$ y
        }% A' e! y3 j# k( U* c

7 |) m5 Q' C+ v5 @- d$ h$ |8 s4 c        while( dwLength-- ) {( p/ _- ~" w9 L# {* F' l
                writetime = (DWORD)elapsed_time;: _+ |; s% L" P1 l  f* D

8 X' L. N4 K9 h* t6 D+ z                while( GetQueue( writetime, q ) ) {; k9 ?' |+ q! {" A
                        WriteProcess( q.addr, q.data );
2 Y- J5 {1 f, }# N( q- ^0 m                }
7 S: i$ b+ ?4 `; {! P% q4 ~# I3 ~
                while( GetExQueue( writetime, q ) ) {
, @; v  z; r/ v. K8 d# r1 s                        WriteExProcess( q.addr, q.data );. V2 Y' S0 N( ?. G
                }& x  C/ G7 U& G9 I/ Q* y: d( y
. }6 U) _& \1 S9 |+ f
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
# Q; o0 |7 a& Q& C2 p! G! a9 X& [- u                output = 0;+ q( B/ S5 s) `5 i2 k1 j% v
                output += internal.Process( 0 )*vol[0];) Q' i6 |* z+ |6 {4 Y6 u5 F$ J
                output += internal.Process( 1 )*vol[1];( w* G' x% y5 T  y: P% K
                output += internal.Process( 2 )*vol[2];
7 \; Z. [: o4 `' D4 K3 G                output += internal.Process( 3 )*vol[3];
. [* F: N' T2 e+ @) d* u                output += internal.Process( 4 )*vol[4];  z: @+ k# v( _5 i* n
2 z) F- M; T% Y; d6 m( x$ t
                if( exsound_select & 0x01 ) {
& k; t6 I' n: H/ b6 r                        output += vrc6.Process( 0 )*vol[5];
; i* _. j' H5 w, H1 {0 T4 o+ ]4 A                        output += vrc6.Process( 1 )*vol[6];
" m; I! T4 A% o9 e                        output += vrc6.Process( 2 )*vol[7];
+ W6 w$ t8 Q" P) h                }+ S. W9 l& {, Z1 d- R$ R- z* ~$ z
                if( exsound_select & 0x02 ) {% J8 J4 w1 ^1 y1 L# P
                        output += vrc7.Process( 0 )*vol[8];6 A5 b$ G$ o0 n0 B, U& N
                }
, G$ D1 B5 E% g: B) G- n6 B( A5 y                if( exsound_select & 0x04 ) {
! z( d7 ]: o- F# w  F                        output += fds.Process( 0 )*vol[9];# d# B, I& V5 c7 o  `/ A4 Y
                }# V3 E" p; L3 D# s  I$ y9 b
                if( exsound_select & 0x08 ) {9 [6 v( a2 H1 U: K  h: z; W& S
                        output += mmc5.Process( 0 )*vol[10];- }1 l% I, Y2 u5 [
                        output += mmc5.Process( 1 )*vol[11];+ b' u: s7 @" V, _; Z( f
                        output += mmc5.Process( 2 )*vol[12];1 _: l9 f+ z& Y1 ?
                }* ~$ ^- \( C) Z* [
                if( exsound_select & 0x10 ) {
8 U1 U5 `( g( N; h  o2 F; n: y                        output += n106.Process( 0 )*vol[13];, ^/ h  B1 b) o5 C& i9 M" @
                        output += n106.Process( 1 )*vol[14];! O: L- b" p9 L! H
                        output += n106.Process( 2 )*vol[15];; A5 r$ P, i: |0 r
                        output += n106.Process( 3 )*vol[16];3 \) G% u# s( T0 d
                        output += n106.Process( 4 )*vol[17];
5 U5 a! d9 S  O$ z$ H; }+ V; r                        output += n106.Process( 5 )*vol[18];0 R; x( b$ g- P0 N, {' H+ j
                        output += n106.Process( 6 )*vol[19];
3 r/ s: j" n1 q, M# q$ F: s+ P                        output += n106.Process( 7 )*vol[20];2 {8 Z* n/ ]3 [: y
                }' U- ?' G! y3 a2 ?2 s5 z# D) p. C
                if( exsound_select & 0x20 ) {
* J1 |3 f$ o# @2 m0 v: \% O& [" O  G+ P                        fme7.Process( 3 );        // Envelope & Noise
% P: r8 m/ b" _+ A1 H                        output += fme7.Process( 0 )*vol[21];
; _  [  W) c+ Y! |" o& F* `                        output += fme7.Process( 1 )*vol[22];
8 p6 m% i. r1 q4 r& H3 A$ s: R9 p                        output += fme7.Process( 2 )*vol[23];+ ^9 f; n: g# s/ u$ d
                }/ k% G) M3 B- ?/ D
/ U. u: F8 m4 k7 w2 m" d9 o
                output >>= 8;
. K; @1 p$ h' g6 ]: ~' a
- C: @+ X* |6 M0 @# r                if( nFilterType == 1 ) {
9 |3 @2 H! _. a, T                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)1 U) {; i6 Q% A* x1 R, V
                        output = (lowpass_filter[0]+output)/2;
6 d( U4 v3 E  Q) l. r4 s- u  ]# E: a                        lowpass_filter[0] = output;
/ z3 S" F6 k( O$ h: r                } else if( nFilterType == 2 ) {9 w) F; U. I2 O, y& ]: F
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)  A# M' F, s8 A
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;9 `" x! p0 ]4 x
                        lowpass_filter[1] = lowpass_filter[0];/ v; ?5 J4 C) R$ y" }$ i
                        lowpass_filter[0] = output;5 ^$ t8 `( x3 M- |& N8 G0 s+ f
                } else if( nFilterType == 3 ) {7 ]& |% }: L8 v
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)0 c- I2 n  H" S
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
: Y0 R0 |% A7 T/ S                        lowpass_filter[2] = lowpass_filter[1];
  f/ ^1 D! f* K  y3 D                        lowpass_filter[1] = lowpass_filter[0];
" m& `3 p- e+ _, m; ]6 S                        lowpass_filter[0] = output;+ _2 E! }/ v" u+ G+ \9 W. C+ S# b
                } else if( nFilterType == 4 ) {! l' m; W6 j. ?  H% A
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)2 l0 p' X5 A: A, r2 {& Y
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
9 L" w" ?- t( \. J! V: a                        lowpass_filter[1] = lowpass_filter[0];
$ N3 x7 N+ B2 i# [  M                        lowpass_filter[0] = output;$ e$ X. I7 M9 f  b7 a0 K: I
                }1 h, J& U! z, c$ d0 d" T5 G
7 M/ Q- o+ Q3 m  r* F( D% N
#if        0
3 e- ^" o1 q( l9 V8 c" c                // DC惉暘偺僇僢僩4 m4 _* ?5 ^' A7 n: v) b
                {% z& c7 z9 d) U& e' l
                static double ave = 0.0, max=0.0, min=0.0;
. K% r1 M( r8 |7 G( i/ o4 u                double delta;
( b* \" Y- _5 W+ r7 G9 w2 \$ I                delta = (max-min)/32768.0;
9 [0 A, w2 ?1 m( N3 S" C                max -= delta;' r' U% j: x1 j9 x. ]& t8 Z- L
                min += delta;
" }+ v- [- W# ^                if( output > max ) max = output;
% v' r5 P" T4 J8 E- `/ C7 _% U, M# k                if( output < min ) min = output;! ^2 r8 H& X. C! m, ~* Z- _+ w2 I
                ave -= ave/1024.0;
) q8 ]5 z! R9 V, I  I3 R9 d1 r  i- g                ave += (max+min)/2048.0;
: m* n/ g% q, j                output -= (INT)ave;
( L4 M5 X  o9 I7 U" `. ]  q                }
7 b8 y1 k8 K7 e+ d5 }#endif  e) R* h5 s" q4 U% @
#if        17 V/ y9 l, ]: Y/ z5 ^4 W1 h
                // DC惉暘偺僇僢僩(HPF TEST)* v/ F3 g7 Z% P' U9 K/ c3 W! x
                {; |! a+ f  @4 S' Y# W% D9 ^
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
* y" N( ?# S/ `( D6 B9 T                static        double        cutofftemp = (2.0*3.141592653579*40.0);3 U5 ~/ ~, x) |" o& V$ L" u9 o
                double        cutoff = cutofftemp/(double)Config.sound.nRate;
8 t; z# y" M( T- h7 G$ B                static        double        tmp = 0.0;2 C/ X- l6 T; O1 U
                double        in, out;
  r4 P4 ]- S0 u7 l. \+ u; j# i
, [2 f( T- F. W; z$ t% S. P                in = (double)output;( \: c& }% W9 ~% y0 k
                out = (in - tmp);+ F7 ~# \' w9 d) S7 I) Z& \1 D
                tmp = tmp + cutoff * out;7 w; R* Z3 k  {  o4 n

5 P( @' t$ n; w+ }- i                output = (INT)out;
% m$ s# u9 k; V3 ?  y                }8 H6 D, r8 }' e1 f: _
#endif7 _- R5 S2 h  Y7 U1 j9 K. E
#if        09 w% J. N$ ?3 M% O/ i" i
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
, c- Y( V# L. j. ~                {
! N  Y4 F1 w* T6 h3 l& r                INT        diff = abs(output-last_data);
4 H& U/ o/ P6 |                if( diff > 0x4000 ) {
, V4 H4 V8 |* g. @& }                        output /= 4;
7 g: t/ r# O" e" |3 }0 N/ x3 m$ U                } else $ P; L2 [5 T' n/ q
                if( diff > 0x3000 ) {
( z) Q2 ]2 N/ q5 q( @                        output /= 3;
) b$ Q, {3 |- W, C) C6 ?9 O                } else
3 b7 ?& r2 ?) P6 z" t                if( diff > 0x2000 ) {
) D# M$ t5 q7 ~. I                        output /= 2;
7 x' ~" e. n; s* P( [, s- ?4 }5 |                }
, @  r  C5 `% j! s                last_data = output;. y4 z) C5 B1 p( P. n8 [
                }5 u+ j) g4 q: _0 L  T* X$ R8 _6 K' f  g
#endif+ g# l7 J3 e& \( O2 O
                // Limit) E0 ]% x, Y9 V
                if( output > 0x7FFF ) {
! g" v/ K% Q4 Y# ?& S                        output = 0x7FFF;
% h+ }) \. r5 K' E                } else if( output < -0x8000 ) {
) X/ N2 \& R' t8 i                        output = -0x8000;
/ G" ]" a% [( h8 h                }
' U) e$ Y# i4 f9 d0 o' [0 D9 B! f* R2 k+ Z9 L, b. b0 G* {7 {
                if( nBits != 8 ) {
/ Z5 C7 Q9 L% P4 Y                        *(SHORT*)lpBuffer = (SHORT)output;$ a! G# s6 ~) g
                        lpBuffer += sizeof(SHORT);
  p+ b, S, S; G. V7 F1 [4 ?. W8 o                } else {4 D) w  P( G9 m# h, a# W
                        *lpBuffer++ = (output>>8)^0x80;
5 K, a  r6 F% K$ o                }& r/ c; q( y( M
. Q5 W- f7 W% K3 p' I5 ?! u. i/ |" z. e
                if( nCcount < 0x0100 )+ w' Y# x8 v; v2 Q
                        pSoundBuf[nCcount++] = (SHORT)output;
, z4 H6 e: {* R$ i9 b; l; }1 W( G: [  u9 J6 d
//                elapsedtime += cycle_rate;  K! [' J' q" p
                elapsed_time += cycle_rate;
9 }: Q- D1 j# J% M% Y. B        }- B. c) r) r! ]( H/ b
8 L, ^  a9 ]' l4 [4 r
#if        1" U6 u2 N  G8 K$ A" i" X6 W3 Z; c
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
$ b) k' u2 H' k                elapsed_time = nes->cpu->GetTotalCycles();& Z% L3 h3 m" _
        }
. n2 `+ z7 y) `* V" l( {2 H        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {3 y& [, y! H) A! I& T
                elapsed_time = nes->cpu->GetTotalCycles();
1 f4 {2 g" \8 V$ k( A4 t        }( d/ D7 T1 m& w5 N$ X
#else
- Q5 u( U7 V3 r1 {6 x* n. x        elapsed_time = nes->cpu->GetTotalCycles();
3 j1 K& y- U2 M% r# I; v: l9 ^#endif
/ Q+ S7 Y! v/ r' b}+ U* Q( a- n: z; V# c9 [' l, ?( {
4 d" Y/ X- D- @3 G
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
3 G5 o0 Q2 b( E+ dINT        APU::GetChannelFrequency( INT no )( a- [: o. r5 j* k
{
) w& @7 G4 M8 u  ?, Z% H        if( !m_bMute[0] )
5 Z, b3 q; C; K, K8 `& m. R6 k                return        0;$ {# t  @+ R1 a  S8 V: a
. l9 i- J, I, t% t# [3 b1 v
        // Internal. u2 x. G0 y6 F1 V
        if( no < 5 ) {
5 I2 ]  o/ x1 Y4 C: F( D2 l                return        m_bMute[no+1]?internal.GetFreq( no ):0;9 s8 v3 y. r# _7 S7 b# M- t/ b2 m
        }
& J* t* B. \. o% O& G9 Y: \        // VRC6
  r4 h8 g5 c. m1 D# c' D        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {4 s# v. u9 I/ W( w6 a
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
! J# q& f+ T9 p) V        }
+ r* o  o5 n, {* m        // FDS# ~, Q& z0 C" I8 J, [
        if( (exsound_select & 0x04) && no == 0x300 ) {
# J; ^% p4 b! k8 M4 m% z( E                return        m_bMute[6]?fds.GetFreq( 0 ):0;
! r* I, e5 i! @1 _+ j# ]        }
5 Z( M2 Y3 b2 \  E( `6 ]        // MMC55 F2 X. A. b; A5 I: Y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
- b* d- C/ N+ f" m' U                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;
9 A% k+ d' Y$ R* u. t+ H2 B! z        }, B8 [; O% U& g2 x& l  h
        // N1061 o5 \  I1 q: C
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
6 q/ ?2 J/ \9 r3 `0 y                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
" [# y8 D) J) X( q# w        }
& n& P! E7 l3 v5 V        // FME7
' N0 @. s4 L9 p3 U3 W1 I        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {& i2 L% w- S; S+ \( x9 A0 y
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;, ~6 }  e) c' y4 c
        }
1 l( I0 k6 g9 H8 y. i        // VRC7
0 y' U' y# M. ~! o        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
  Z! n/ n& V' ~                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;8 q5 \% q) i! q+ l: @  D+ ~0 S
        }: r- p) D7 ]- b
        return        0;6 F5 ^) l& `& N+ H) D
}9 {$ u5 k& k+ k7 R
- o. u1 V* E' G6 o1 i& g4 n* P
// State Save/Load
2 K5 e: i% G0 pvoid        APU::SaveState( LPBYTE p )
5 M/ R( e; D$ e6 \: t+ @{+ Z7 o( _$ d, y, u* D3 }  s
#ifdef        _DEBUG2 m, Y0 I/ e% n1 j; W7 ?
LPBYTE        pold = p;
& @* x9 c: Q6 ]5 i#endif
3 X1 U& v7 w5 l  b, N# n0 Q, Q* A! E" R3 R" N- s
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
5 U1 d$ N) w2 d, d' ~( u        QueueFlush();
' M4 q; a2 Y  v- v1 \" c7 T' c' P, U& X
        internal.SaveState( p );9 t6 l/ `2 ^& f7 P  z
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
# ], ]3 V" R# u+ d& R4 r/ ]
+ D! D* e4 z$ B% V& g6 K- t5 `        // VRC6- y0 |. W* M: V- R) l8 Y% F
        if( exsound_select & 0x01 ) {
# S8 q1 b+ m1 [, J  v/ X+ r+ ]. z' t                vrc6.SaveState( p );
( X1 C8 g5 a+ {/ Y; `% ^: U                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding4 _6 x9 A: b% n( M6 q
        }
5 f# u9 b' l0 C6 }        // VRC7 (not support)
$ ~% n- ]4 L4 K3 Q8 c" _9 L3 r        if( exsound_select & 0x02 ) {
6 M/ u/ A5 p1 R2 o. u2 l                vrc7.SaveState( p );
( l* `# _) ^1 b1 y                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
1 Y: ~% q4 E" |" g; d/ P        }9 I" `% m8 b6 e, l! M- V. I
        // FDS
9 ]! H. o4 Z6 k2 F3 l4 K6 w! K        if( exsound_select & 0x04 ) {
7 H/ K* X  f2 g9 u7 c! u- W                fds.SaveState( p );# h: ]2 B, M  @4 A
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding! \! d8 j* F3 h( P2 U' C% [
        }
! o, Y  [9 b7 Y4 O        // MMC5
0 C. B" u& s( s1 i        if( exsound_select & 0x08 ) {+ s0 [' c$ Q. N8 |" z& j* d
                mmc5.SaveState( p );, J# W/ I2 O% e' K4 m8 q" {" e1 O8 H3 @
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding7 B6 k/ R) G% d. ?$ E' K
        }
# Z4 a. s+ W% n% Q/ {) v1 h0 C2 |6 U        // N106
8 t  f" @9 U- A/ W$ ~* A- _        if( exsound_select & 0x10 ) {
$ Y" Z6 T& _" L- y" l: \3 ^                n106.SaveState( p );
1 M/ [# N, r! F( f/ x                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
/ t6 O, j) L1 N% B7 H. \        }  s( ^+ |. ^" `( Q' x& u
        // FME7) _* x( E. J3 f
        if( exsound_select & 0x20 ) {) a! f. |9 ?7 j
                fme7.SaveState( p );
7 |; e6 o& X4 b                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
! b9 ~% ~) k$ m7 E- A% h        }
- W1 U- F" B# |( v. G0 A
4 a7 c; W0 d' P- a  p1 J#ifdef        _DEBUG
& l) J4 [* w6 e" DDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
  ?$ f5 M& A5 U' t2 ?#endif
8 q* o6 }! o/ F' Y9 ^}! x6 p1 q2 Q0 f* y1 J- t
" D7 B5 x9 q; o% X
void        APU::LoadState( LPBYTE p )4 F% C9 d9 f" E9 ?, O
{
; x6 o& T' c  Y3 [        // 帪娫幉傪摨婜偝偣傞堊偵徚偡- N( a$ T" C  u# I% M
        QueueClear();: K0 g4 H. L) a) M

7 y) ?: t0 z1 V' s        internal.LoadState( p );' T6 |8 g3 G- Z/ ]$ Y
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding: `/ E- _/ r/ E: f$ C7 m/ r4 t

# T( b2 }1 q2 M2 D( q        // VRC6
0 i' [& ~4 {2 f1 _5 S        if( exsound_select & 0x01 ) {
6 k. Z: H$ \  t6 J& I: P( D                vrc6.LoadState( p );: Z+ v3 d7 {9 a5 r
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding( v& v" c; O5 h8 }; E( A6 x
        }, m& ~9 O2 N: B+ ^
        // VRC7 (not support)  f: y2 n" p  d, o6 T& t4 e5 W7 c# N6 N
        if( exsound_select & 0x02 ) {" Y3 e0 ~+ n9 m* P
                vrc7.LoadState( p );
; Z% V1 f  p5 ?7 p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
! X/ M, L8 B) E4 i$ \# W& w        }
5 N5 V0 j2 S1 `' O1 Y, Q3 Y; t* }        // FDS
5 s" b7 @  @4 F5 J* W$ t6 v        if( exsound_select & 0x04 ) {1 ~: A' _8 G- u/ J$ S* W
                fds.LoadState( p );& n+ G- O  P4 v5 j9 H# @8 _8 x9 p: m
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
* V- M6 Z% I7 ~0 _        }
7 U& K$ J0 G, i9 F' s; N        // MMC5
7 w9 U  V3 p+ y) t" ?        if( exsound_select & 0x08 ) {
8 M$ \) }7 }4 F" N/ v( W! d; v$ J                mmc5.LoadState( p );
( D2 h) U9 t9 F" X, ~1 S                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding/ u7 _1 x. E. J) `  W/ Z
        }
- U4 V" j7 @( J7 S        // N106
1 e6 ^) n  B: ~# j# T5 D5 A        if( exsound_select & 0x10 ) {! F# G9 i8 j2 S/ c9 F8 v, m
                n106.LoadState( p );* e  n$ e% v3 l$ e
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding( |, R6 t  v2 _* Z" H4 q
        }
8 _" I5 w- T. b7 B* a3 f        // FME71 _* f& ~" [! u
        if( exsound_select & 0x20 ) {/ O7 Z$ g) T1 X  t# w7 h
                fme7.LoadState( p );
( K- |9 F2 J$ }) P) @                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding3 N7 n' s( o; d9 d# Y6 E
        }1 u6 p; K/ l) p) }
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
) V) t* T! a3 p2 A, [可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。2 z4 }4 l& v! U+ T0 G
感激不尽~~
+ |# p3 `# p) o% f. w; O
恩 我對模擬器不是很有研究,
) T5 I$ z9 t5 z2 Z* i( w雖然要了解源碼內容,可能不是很困難,* Q* i6 |. k3 P: e. r. k1 n# I4 K
不過還是要花時間,個人目前蠻忙碌的。  H8 n. {! S4 s0 ^1 S* P) p3 ~  N
& e. @2 B  Z! R3 P4 d
給你一個朋友的MSN,你可以跟他討論看看,
$ I) ], x( a4 u7 T: k( g他本身是程式設計師,也對FC模擬器很有興趣。& {' ?2 ]% X& w# ]

0 o8 o- y1 ?" X6 R, I9 l0 VMSN我就PM到你的信箱了。8 P% N; n$ w6 E& G8 o' p0 B2 ]

/ l# l% a( I/ {) \7 [: V/ Q- C& \( {希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
6 J- P( l  o- r* E! D* F1 D呵…… 谢过团长大人~~

1 c  E. f! C+ f- B" _# p( _9 s0 m; h# k  L  Y& T& J
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 1 Y7 n: I/ r) ?! Y5 y
团长的朋友都是神,那团长就是神的boss。
2 o' r3 {0 z. P) k0 f
哈 不敢當,我只是個平凡人,5 F7 F8 E3 \3 Y$ F
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙8 M& X6 e, h3 Q7 r
ZYH
7 C4 g. @6 o5 J8 f- O- D; L4 XQQ:414734306
/ o7 Y* T' T/ c) }6 z- z  K, OMail:zyh-01@126.com" \8 Z- @# g# K

# i$ {& A& ]1 @4 j. F他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
- w! ]3 `) `3 C' X( I* s5 w再次对团长大人和悠悠哥的无私帮助表示感谢~~
- n8 [  P; c; g: ^8 G# F
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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