EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

发表于 2009-11-2 22:45:57 | 显示全部楼层 |阅读模式
求助:模拟器源码中通过哪段代码控制Rom背景音乐的播放?; i2 [( ?9 }$ A1 {# R9 A: U) ~
PS:看过一些模拟器的源码,大概都分为APU、PPU、NES那样几个版块。请大侠告知是哪个模块。感激不尽~~

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。$ k: v8 H7 F+ q. ]- W$ i5 x/ b
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~- C" F: ?1 }/ b/ X0 B( X3 W
这里有相应的模拟器源码,就当送给大侠了~~
5 k. m: r- W8 Y$ t1 \% khttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 ) B9 t1 B: s! x  Z
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
) D- v/ D, Q" A: ?, g8 W9 Y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~9 ~* y( h/ @# Y4 z1 t
这里有相应的模拟器源码,就当送给大侠 ...

- g1 ^9 Z/ E0 X$ ?( h+ C( @: a$ E聲音部分(Audoi Process Unit = APU):9 A: l" A* U. h8 n# X
.\NES\APU.cpp, V( i! m/ I4 w" I& {% k. w5 _2 D# g# p
.\NES\APU.h1 }9 B$ k1 x0 C7 n
4 |% |- ]! g) e( Y6 Z$ A9 Y% f' x

9 S7 F1 `( o" m0 s1 P- |影像處理部份(Picture Processing Unit = PPU):
( x" z% Y- s/ w/ O8 f.\NES\PPU.cpp# h4 O+ f! G3 n6 `7 P1 s2 Z
.\NES\PPU.h' h' ^0 g. P  Q

% T$ l* u. W' o$ V! u如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
: R' Q# \! I& d# b' Z(由于很多专用术语和算法机理都不明白,所以看不大懂……); _2 Y# j; ]- u, F' x3 b' z
//////////////////////////////////////////////////////////////////////////2 K! F$ K0 {: H' f9 S( I7 w0 F$ H
//                                                                      //5 B# D) r1 R" [1 P
//      NES APU core                                                    //
7 f/ ]8 f1 U' [2 f% n7 r& t% O6 c//                                                           Norix      //5 S3 b7 B( d/ i% H7 t
//                                               written     2002/06/27 //
2 C1 ]9 ^: {3 y/ |& [  T+ l, T) q//                                               last modify ----/--/-- //- ]) g# p1 r9 X% D% N0 x& D3 T
//////////////////////////////////////////////////////////////////////////9 |9 f3 X8 c4 R7 \
#include "DebugOut.h": O# x+ n, R3 ~5 U1 w1 E
#include "App.h"
3 e' Z  s6 y# Z7 y1 v#include "Config.h"3 N' r; d+ t: b: N" |* T0 a, f& R
; n6 b  d8 O# x0 w" |/ v. ]/ u
#include "nes.h"1 H; c/ c* {! O5 A8 _. _
#include "mmu.h"4 O8 `3 u% T2 ^9 u# Y
#include "cpu.h"
4 C* K6 ~/ w; r$ H7 b$ Z8 C#include "ppu.h". r* _/ E4 }) {" E- Q% b0 p5 D; L
#include "rom.h"! c4 J8 t8 C9 |$ e7 W# b" ?
#include "apu.h"
: U, }, S  |0 [
" {) |6 w' f  b4 F( n0 v// Volume adjust0 B: t- l: G/ f( p
// Internal sounds$ W0 ~: A1 N8 e8 B$ |' D+ ?3 ]2 H* O2 Q
#define        RECTANGLE_VOL        (0x0F0)& c1 d+ v0 v* B
#define        TRIANGLE_VOL        (0x130)
1 I& z: i$ s6 x#define        NOISE_VOL        (0x0C0)* R' {8 [9 M" J0 C* C" C5 e2 B
#define        DPCM_VOL        (0x0F0)
6 Y: w4 G9 H  H// Extra sounds; C( b" Z3 t2 h
#define        VRC6_VOL        (0x0F0)
8 B) }  `1 _) J( u* q#define        VRC7_VOL        (0x130)
# f/ i- _# o/ i/ O: N#define        FDS_VOL                (0x0F0)4 j# J' A* X; j6 n+ a2 R5 O% k" M
#define        MMC5_VOL        (0x0F0). Q0 e2 R# m0 ]  C
#define        N106_VOL        (0x088)- V0 {. \: P1 T( i9 t
#define        FME7_VOL        (0x130)
/ a1 }; l* n5 d) i
8 o! y6 M- {6 uAPU::APU( NES* parent )
6 k6 d4 m; m8 T7 K{
/ `7 M( q+ l+ ]2 m' V        exsound_select = 0;
/ g. C- o# y4 ]5 U. U) w
" [- i: K! Y% o% N  f' G        nes = parent;* a3 D% L1 V! d
        internal.SetParent( parent );
) q1 \: V& O. ~$ `" \& ?+ O  o' K" J
        last_data = last_diff = 0;  L/ p7 S& v2 h7 B% K- W0 K& G- u7 `

9 z" N! W; k% @* h2 ?- r- H: i        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
' ~5 ?, A" `1 ?; z5 q) h6 n/ [. N5 y4 h" ~3 U
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );4 ~* X7 X- a1 T# f; s6 f" l& n
        ZEROMEMORY( &queue, sizeof(queue) );4 b, Z0 W2 N# e1 F2 w  A/ D2 ~
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% W* O( L6 f' I! x: R( S# d
4 X: t9 B) ?" w" ~: K        for( INT i = 0; i < 16; i++ ) {
$ H7 ?8 }' m6 K: R, h                m_bMute = TRUE;5 }+ \0 c# P# g& p, o, @" C# J
        }
. h2 b: e+ m( }0 `, m  S! x% _}
* U& I; Y( G) q5 T. D7 t. l
4 ^3 \1 K* v7 W" @7 }APU::~APU()
8 M& l1 h$ X  k+ z; z{
8 h0 }; W0 C9 ^! i1 ^: n' ]$ q' k}4 a1 }, c6 T5 F- A4 N

/ Q2 T* y7 Q( `+ ^/ V/ t, Q8 Jvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )
# @. |2 H; K0 _/ f5 S, ]! @{6 ?% K% |7 ~# }! t8 B' ~+ y
        queue.data[queue.wrptr].time = writetime;; K8 y1 x, o( F3 ?9 K9 H0 C
        queue.data[queue.wrptr].addr = addr;
1 f. \! r+ g6 r& c        queue.data[queue.wrptr].data = data;
5 f9 ~$ K6 X1 B        queue.wrptr++;8 k& B5 M* S) [% {6 X0 m  d
        queue.wrptr&=QUEUE_LENGTH-1;
6 ~; U, W6 @  F; P1 a* S3 X        if( queue.wrptr == queue.rdptr ) {8 ~0 J% _$ _' Y/ f' X
                DEBUGOUT( "queue overflow.\n" );6 x4 r  t' J5 p( L+ ?: a9 t
        }8 t# Y2 {- I" f- R# r
}
' B4 s2 Q! p  Z
, u) v6 s( V" H" @- gBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )8 M$ u+ j+ P( \, {0 U# V" j3 F" L
{- X, t% j6 V( l8 Q0 \
        if( queue.wrptr == queue.rdptr ) {- X/ Y) l4 @" c: O: c+ {( n: k) z
                return        FALSE;( W3 ]8 x9 N& a; v% _) Q7 \
        }9 |; H/ O" }, J' w$ J5 K, F5 x$ f: v
        if( queue.data[queue.rdptr].time <= writetime ) {
. Z6 F9 E& V5 }' N6 {                ret = queue.data[queue.rdptr];) Z' X. r- a8 v' f  X
                queue.rdptr++;1 a! C' d( s4 s) s  |
                queue.rdptr&=QUEUE_LENGTH-1;
8 x5 [. s0 ]2 w- V8 \  @9 l& x) j                return        TRUE;' g& ?. o$ |: _) U% ]$ j: }/ s
        }* C+ M. j0 c! H7 h! k& i4 L
        return        FALSE;* D) x: V1 L$ e& @1 W! F1 w# W
}
( Y+ y3 z6 c5 A9 w9 i" r0 Z) J
; p# f# i; u/ X; X, ~. P+ Kvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )  u% y8 t" u  L0 `6 K8 |" t
{7 i+ q$ G( i0 Z2 N/ S; a8 l. t
        exqueue.data[exqueue.wrptr].time = writetime;
8 Y+ Y! Z% E8 m  A8 I& u( K        exqueue.data[exqueue.wrptr].addr = addr;0 P; Y3 U" d6 w2 |
        exqueue.data[exqueue.wrptr].data = data;# Y2 S' |. l. X! J# p5 L) _: J* d
        exqueue.wrptr++;
& U) Y$ s# @) P) W        exqueue.wrptr&=QUEUE_LENGTH-1;& \- t1 s5 m9 t/ T
        if( exqueue.wrptr == exqueue.rdptr ) {+ H( E5 {* e9 @/ o
                DEBUGOUT( "exqueue overflow.\n" );
) P# ]) H1 c- P4 d        }; l& }0 B4 h+ S$ s0 t3 d3 F
}; X- `9 J* w4 A! o8 j

7 U3 u! x% W. S4 G5 ?% vBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )1 F! W  @$ @% ~! _1 @
{
! Z! j$ g# g' |/ R2 {4 m1 Y        if( exqueue.wrptr == exqueue.rdptr ) {
( ?; N1 Z1 X  \6 G! U. m                return        FALSE;
" t$ ]& s8 _& Y: {        }. i, P2 ?+ C: S6 d& ?0 ~; i
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
0 T9 N* H; i- \2 e; b7 G1 p* n$ |( l                ret = exqueue.data[exqueue.rdptr];
# [) w/ q0 _4 b: y                exqueue.rdptr++;! j% B/ g' H8 }3 ]  C4 A5 ^: Y% I
                exqueue.rdptr&=QUEUE_LENGTH-1;4 ^8 s& F  I% q0 E; s' j
                return        TRUE;
8 i/ g& X4 b/ Y        }
' d* T- _3 ]  q4 x1 S        return        FALSE;6 U- |: p3 p9 ~% x8 o! r1 T; g
}
1 P7 E' A  a* N" E8 a" t5 v* D' C8 v3 t
void        APU::QueueClear()
- S$ ^) M% w) T; E$ d3 F{% i' C8 b) E3 z) s' h
        ZEROMEMORY( &queue, sizeof(queue) );) D0 I0 h* i/ w5 ^' N/ b
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
+ X" y% `. M, k- `4 d7 q# P}7 S$ U7 m+ H" D" {- U$ p4 t& Q; [2 e

2 l/ F# f  H9 A0 {void        APU::QueueFlush(). P# B, F7 o/ T
{
$ H/ Y5 n  {3 t: c9 k        while( queue.wrptr != queue.rdptr ) {& _% Z- f6 N; P
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
$ Q% R  x4 C1 _: U                queue.rdptr++;6 O! @) g1 C1 ]" l2 O: V) \6 g
                queue.rdptr&=QUEUE_LENGTH-1;
$ f6 V/ I; s1 ]9 n$ [        }
. J6 a" @) Y3 k7 w! [9 U
3 u  e4 S- Z+ f        while( exqueue.wrptr != exqueue.rdptr ) {
2 x) \& k/ \* d7 i7 e                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
: j# M+ v- l8 W( o+ ?                exqueue.rdptr++;
4 ?/ b5 j* K% e6 U4 a                exqueue.rdptr&=QUEUE_LENGTH-1;
) ], l+ O4 W% ?        }: G) `# ]$ J% ~) s, ?2 ]9 |4 p
}. m( ?, b) M+ i6 C) o/ N8 ]
9 k4 X7 K" ]. g+ l3 \, S8 w# x9 E
void        APU::SoundSetup()
5 R, d# ~6 L9 j% g{
% \( Y1 R" `3 @/ ?3 Z        FLOAT        fClock = nes->nescfg->CpuClock;/ O7 ]' {& s, _' N$ y4 r  @
        INT        nRate = (INT)Config.sound.nRate;
+ x2 `6 P9 Q* g# d        internal.Setup( fClock, nRate );7 N- i4 z& _1 y/ ~. m
        vrc6.Setup( fClock, nRate );2 X2 y- X% u7 ^0 q4 h' r
        vrc7.Setup( fClock, nRate );; `. I! Q/ A& K9 y" P
        mmc5.Setup( fClock, nRate );5 d2 w( h: _( |. q6 S1 E
        fds.Setup ( fClock, nRate );
: U' R; Z* b7 r/ ^5 |. |5 o        n106.Setup( fClock, nRate );3 o! s! [! m) W. |4 X, Y
        fme7.Setup( fClock, nRate );/ W' b: |  u9 R- @" B; J
}4 L/ m/ T, a- j2 B8 x- O" M! [

: B7 Y! J, J% t2 ]7 ~- B) zvoid        APU::Reset()
' k/ q/ }3 L7 I{. x1 T& l& {" _7 G7 p- _6 z: R( ~+ |
        ZEROMEMORY( &queue, sizeof(queue) );& u+ W* V  a. A6 g6 s7 K
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
; D# [3 a6 S( [+ l: q! Q: m$ K0 E9 u4 e% [0 R( [  u3 Q
        elapsed_time = 0;& R. _' D! h  @1 ?; U# L) P1 a
0 ?* q" l! t+ X; `
        FLOAT        fClock = nes->nescfg->CpuClock;4 s! w' X/ j0 X, }; ^
        INT        nRate = (INT)Config.sound.nRate;+ E" J' {7 Z: c- d
        internal.Reset( fClock, nRate );
5 _4 _. Y% N1 ]2 u9 w' s        vrc6.Reset( fClock, nRate );
# N0 g- A  m2 m, j4 l6 B        vrc7.Reset( fClock, nRate );
/ h$ g2 [3 a6 G        mmc5.Reset( fClock, nRate );, T! E$ t1 }+ J: r+ S- |
        fds.Reset ( fClock, nRate );
- v5 c: a5 F# |$ t  I+ P1 d. L        n106.Reset( fClock, nRate );
) X; H0 i" G% X0 e3 L0 a        fme7.Reset( fClock, nRate );0 r" c; w) H% w6 S% M) m
) E$ A$ R7 g: s4 m& R
        SoundSetup();
% B( }$ T5 l; U  Q( {7 j9 i0 T  S}
& o, [. A; ~' z* i7 e& G
) h6 w( T4 x' g/ Tvoid        APU::SelectExSound( BYTE data )) O' v7 v+ B0 D) F' g
{
/ L, _9 d3 b& S  [4 Y! J: ?        exsound_select = data;
7 K, s' ?- }7 _0 D}
4 e$ E1 c5 [' {3 [
% [7 {. J: \* p9 h/ g$ R1 CBYTE        APU::Read( WORD addr )2 C( j! X; W8 B+ N
{
6 d9 ^) p6 I5 ^) f0 e        return        internal.SyncRead( addr );
2 }  _) x; s% Y  C% @  t}
( \* {6 ]+ r! _$ k- b- S$ E( L* b& D3 u
void        APU::Write( WORD addr, BYTE data )+ T: y1 G& ^% r! P* x7 P
{5 v* a5 x* O" C% O) k5 |$ `5 _* Q
        // $4018偼VirtuaNES屌桳億乕僩
% v! j% E' W! r) _: _        if( addr >= 0x4000 && addr <= 0x401F ) {
8 Y; w8 M" t7 `- n7 o6 D                internal.SyncWrite( addr, data );9 n9 ^0 p: {8 H2 q
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );" Z, o4 J# s5 P  y" q: E* ^
        }( ~* E: Q! z8 ]# k
}
" C# m. z0 O3 s3 t  k) {+ _) Z
5 F; q+ l: `7 ^4 e" \9 a0 M' e) S( c; aBYTE        APU::ExRead( WORD addr )2 A1 X' e+ l6 _
{
0 H5 n5 C& |0 `& U8 j, kBYTE        data = 0;. o4 d7 ~  Z  T8 h1 o" V

$ J4 c; S$ `* s& f$ e" h' g1 G0 D$ ]        if( exsound_select & 0x10 ) {$ {9 O! {) Z" \& i9 v- ?" k
                if( addr == 0x4800 ) {
, F& Y9 Z5 j) p5 K, e                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );8 O7 D5 V% G2 x1 D" Y* [
                }) U* _' }3 m$ T% `! T7 E
        }
7 N6 U, \: a; e5 o        if( exsound_select & 0x04 ) {" H2 C* m$ D! [, ^* Q
                if( addr >= 0x4040 && addr < 0x4100 ) {5 A4 @& `5 K+ ^( p! }: c
                        data = fds.SyncRead( addr );0 i" }  ~/ l4 ~- a
                }
( [$ ^4 M2 w3 j; n+ Y6 e. I: {8 c  E        }! V: h" P7 r& l5 o+ g& w7 l8 ^
        if( exsound_select & 0x08 ) {4 t5 Q9 j% O% S" }7 U
                if( addr >= 0x5000 && addr <= 0x5015 ) {' }6 C2 v0 T5 C, t8 j
                        data = mmc5.SyncRead( addr );
$ u2 s- O# P, ]; X( w                }& Q/ b& c5 u6 B7 B6 B  C
        }
' h/ T* \- N3 ~  `' C/ r$ R& s$ y. C$ b5 w4 R0 i
        return        data;( d5 T: y3 _6 H8 z
}
6 ^9 x) M. L3 A/ ]' |9 B" _5 }& y- D
void        APU::ExWrite( WORD addr, BYTE data )) r4 P1 m; v# }+ F3 T
{
+ y) V2 |+ E9 A: B0 @# |4 }        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );3 Y& e& h* X, ~

0 t3 {! @  N% T3 s) p. @        if( exsound_select & 0x04 ) {* w" o  y6 x& U3 G
                if( addr >= 0x4040 && addr < 0x4100 ) {
" ~8 z- g: U; u. [& |: x: w                        fds.SyncWrite( addr, data );
+ \5 [0 Y7 M6 S1 w+ w. \                }- W  c0 I$ n, z4 ?: O
        }
5 {: g, l- D8 s# w7 R) ~# F% E( z
        if( exsound_select & 0x08 ) {5 O$ \+ H) _: `
                if( addr >= 0x5000 && addr <= 0x5015 ) {
$ Q4 j/ b, t, x! s                        mmc5.SyncWrite( addr, data );
- V$ W" ?; Z" \                }
# l$ R' {, E  T  Z1 v        }
$ i( o1 m* Q9 B5 s1 ~9 F}
: \7 P" f7 j$ e3 N( X5 m4 |4 A! l! z$ J# x2 z
void        APU::Sync()! a  c# y9 T! B# n+ U
{
) ?5 L5 v# P( f; D$ J}) O4 }+ l5 I7 k1 I

% R. f5 d7 M: l9 {8 g0 dvoid        APU::SyncDPCM( INT cycles )
) @+ P8 M7 Q' @2 a; P& c# p{
9 {4 R6 R) |& p1 T+ d' L        internal.Sync( cycles );
2 b- a* i" A- c4 |& |0 v) G0 c1 T* l# S5 h
        if( exsound_select & 0x04 ) {1 ~2 ~2 @8 W. J3 n7 ?
                fds.Sync( cycles );' @. K. x; J9 S- i! f, H
        }
1 b# [2 ?# T6 q" \1 G        if( exsound_select & 0x08 ) {+ C+ t' a$ v+ s4 l& H9 a$ Z
                mmc5.Sync( cycles );6 b3 J6 {4 A$ b) B9 O, o$ B
        }
' ~, I5 s4 p2 ]0 a/ E- z" W4 J8 K}% a# U0 M4 {; K( R/ O& K3 R* Z( y
" Y) z0 b# A. f5 u7 }( s, f5 T: x
void        APU::WriteProcess( WORD addr, BYTE data )- s+ k( P, I: n0 W- s, l3 E0 {
{/ L* }9 D& ]0 P; s0 a
        // $4018偼VirtuaNES屌桳億乕僩
! M( b4 L7 N! f3 K: s0 O6 \        if( addr >= 0x4000 && addr <= 0x401F ) {
6 H1 o4 I' y' C                internal.Write( addr, data );0 x& G2 R; z5 f, @0 ]% |  B
        }
; \, Z  o2 e# F# E}
' G# p7 c2 l) V9 Q1 r9 M5 o4 }, E2 O1 T) q, @: u/ ~
void        APU::WriteExProcess( WORD addr, BYTE data )
, R  S8 b( \$ Z, S& ~{
- f' B% a0 ?( B  z1 y' I1 q/ D! u3 C        if( exsound_select & 0x01 ) {
/ i2 v( T- q0 C% d+ O                vrc6.Write( addr, data );# X! T1 P; M) t  R! W. f0 Q% W( Y
        }/ v: U6 ~5 u2 x! A
        if( exsound_select & 0x02 ) {
  c! n4 y/ x' T. ?0 g  V' [                vrc7.Write( addr, data );3 o4 p" W& u: S1 q& t1 T, w. C
        }
& q9 d4 o0 ]6 T/ N        if( exsound_select & 0x04 ) {
; u: s( u" C6 ^( b9 n5 J9 t+ I                fds.Write( addr, data );2 s/ v$ f' y' x4 [. e$ P- |% h
        }3 z( F0 O9 w% Z: ~
        if( exsound_select & 0x08 ) {
9 P& X" Z* R0 J  J                mmc5.Write( addr, data );
7 ~; W) B* x+ c# `1 k        }7 @4 f4 R4 A8 r% |0 T- T
        if( exsound_select & 0x10 ) {
& \4 K# K: k- x* h; u3 H                if( addr == 0x0000 ) {
! Q: O8 U9 g" g# T  H/ Q                        BYTE        dummy = n106.Read( addr );# Q( }, k4 I5 v# W" w
                } else {- C, J" ]* F# q% k$ Z
                        n106.Write( addr, data );
$ m9 _7 A$ P% W/ t: H8 w3 A) X; u                }; ~) S% |7 Z1 N
        }% v. m' z. l& `, M7 h% }
        if( exsound_select & 0x20 ) {
% g+ v$ X0 y. g0 i' a; N5 t: ~& P                fme7.Write( addr, data );
; \/ u  D/ g  b5 @        }
+ `1 Z& z% I! `4 n* A}7 f- W5 d% s0 x; ^& r: y) U) Y
- Q' J/ ]( B2 G: W: n  ?
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )- y; T5 W1 ~, V! N) z9 l8 W
{
! [. D' J0 N- b8 R/ z% |" sINT        nBits = Config.sound.nBits;$ k2 ?+ y4 y' t# p4 x3 B6 }5 H) u
DWORD        dwLength = dwSize / (nBits/8);. F, ?6 b8 [. x6 w
INT        output;
7 r  f; y2 k  j# Q9 N7 nQUEUEDATA q;& b/ Y# ~' i* e) K7 a
DWORD        writetime;8 f3 y$ y. N4 {4 a
' g9 ^  r5 x, d0 x  O
LPSHORT        pSoundBuf = m_SoundBuffer;- x+ t2 I, F" e8 T
INT        nCcount = 0;9 `& _  |1 E; X

6 e# Y0 y: Q8 gINT        nFilterType = Config.sound.nFilterType;
/ M: C1 _0 R5 v5 T$ _' O$ o
- B% a& p! B# ?0 v( N        if( !Config.sound.bEnable ) {
8 K# p- e  G. A6 j7 S* L$ C                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );
5 u. P4 C$ M, [0 Y0 d; A: ^                return;% h1 `6 L4 l% p$ o2 U; C7 a2 k7 D
        }
) V0 S) \! t. N, `  P1 g
$ M) d7 Q, _& T- t8 \1 Q        // Volume setup
# n8 L9 W. y8 E$ O- ?. r. F  p        //  0:Master
8 ^% }$ ]5 {4 v        //  1:Rectangle 1
) e5 n. D% c2 Z5 M" w/ b        //  2:Rectangle 2
, ]% L/ S, `0 J' r+ `( @5 y" W7 Q+ ]        //  3:Triangle
& N$ g0 K" M8 t( {2 ?) T  ~  N        //  4:Noise$ d8 f9 M3 T/ ?/ s. f
        //  5:DPCM8 r, [/ q) b6 L% ~6 F
        //  6:VRC6
# m8 a) D0 {( @$ }; U        //  7:VRC79 g6 c. w) ], v# c9 P8 w, K4 [9 D& S
        //  8:FDS
6 `7 K- g' H0 t. n9 f* \7 U) ]+ O: U% s) ~        //  9:MMC5
9 V; s2 _' i7 D8 c        // 10:N106
- S0 p5 e" P) n4 @- d" O  }5 K2 b        // 11:FME7
+ N9 ?& W# g# B! K" T        INT        vol[24];
. O* y, l0 n4 r1 `        BOOL*        bMute = m_bMute;5 G/ a. a" s3 b6 C6 U: O/ W
        SHORT*        nVolume = Config.sound.nVolume;' [" V' I7 b; U$ H! b
; e( [- ?# ]/ G' c/ X
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
, f$ Z2 I( [4 j0 N0 p7 H
  x4 N6 t, y7 D1 h$ D+ [9 q        // Internal
( A+ h# @1 t; T$ l        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;, P' B( w- E8 e+ C+ z
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;3 s8 S9 `$ x" n3 N6 ], u
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
7 F, b( N* [# P0 E1 H; k+ x, e        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;  z# v% \  Q9 l9 X+ y6 S: K
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;$ ]3 s3 \! u. S

4 v- f/ k3 Y4 y! q7 a( [        // VRC6
# ^; O0 g7 h) [5 O. A        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 _3 I; j" L* l$ n        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- E( Q8 E: J& I- Y  c4 u
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;+ M5 [& ~& [( d8 z

0 k: e- f0 Z6 i/ W( W  n; z9 z        // VRC7
" X+ P/ J+ \% n+ a3 }8 l7 a        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
3 ~. D4 o. ]! @
3 r/ {- a( ~  m4 \5 j+ L* t        // FDS/ H8 [+ Q# I+ b' `0 R. R4 @
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;) Z6 R7 v# G4 b0 F" r4 j4 M

1 H( K2 U9 k1 v9 @( {2 @        // MMC5& r  G+ q& N% |8 L% E
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' s" }9 H  x: N) C/ l        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 L: T3 A* P+ j7 E/ t        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
. U% {  W' u% v: l" ]; s1 n
: N5 x, T! R* T2 e        // N106" N8 D4 d4 g- O' ?2 E% x
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# E: C+ n; G# }% w) @, U4 l
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' ~/ Y; q% J& Q- c
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
, \) p, k" [5 O( \- S6 c        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
! @2 m7 i0 M% V' G- g) o        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& P; \; o0 Q+ }/ m# y% v* n1 @6 O5 p
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" h' b- v4 @, E3 u9 B
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) o3 v) R  b5 I! O5 ~8 u        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;: i2 E9 l6 `' u: b8 e

9 Y5 j/ E% \+ {5 \        // FME7
6 i3 h; B, G' r) d        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ V0 D9 I# t0 B/ n* H        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
$ f4 v9 _+ a& L  P" l* g        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 r' v1 s6 ]% R. e8 j  J; o* i) i
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
2 H2 }3 z% _3 _/ s3 i$ e        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;; E3 m. z" m) K$ W- P% Y; R1 b
5 t/ [6 r8 \& Q. Q/ y8 v
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
9 i& P( V$ L: T  h        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
  K, l/ t8 \& H6 ~                QueueFlush();
' T2 b- ?2 r$ |+ U: T2 K- \        }- T4 _$ Q$ E' @: C2 X% f( @

; o# E3 F/ c0 |# D        while( dwLength-- ) {" Z  p9 e1 B/ R5 e( j5 W
                writetime = (DWORD)elapsed_time;9 a& x* ^( b9 F7 [0 C3 I

* W" M/ p, U2 C$ v/ j5 M* b3 s                while( GetQueue( writetime, q ) ) {
- c4 t( D2 \( \7 D5 f6 t; Z                        WriteProcess( q.addr, q.data );  v9 i* j( M/ l- t6 n) g$ M
                }
) h; U" t  h' K& `1 \
0 V# X( J5 t. D3 f                while( GetExQueue( writetime, q ) ) {
. Z3 |1 ~4 x# ~; G7 L" h                        WriteExProcess( q.addr, q.data );
$ Q+ @/ G. A0 o' S2 U                }
% {9 n& a. M3 g3 [8 E! j$ u5 H& \  g4 ~
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
8 p. n0 I) _% }0 s  b  a; a                output = 0;% b) n. `' n  Z4 ^+ \3 [
                output += internal.Process( 0 )*vol[0];
. |! [2 V8 m; K7 P: B. S9 b                output += internal.Process( 1 )*vol[1];) \5 j, F- U: X
                output += internal.Process( 2 )*vol[2];
1 W. z3 T. m1 z                output += internal.Process( 3 )*vol[3];
* }# u) r$ N" u                output += internal.Process( 4 )*vol[4];
. h1 r8 z! t( Y9 U& u, g0 ]+ G
: k1 Y( k3 k/ A; n8 R3 O$ K1 k                if( exsound_select & 0x01 ) {( J5 P- |$ t; u) K
                        output += vrc6.Process( 0 )*vol[5];% v' F/ H0 s5 f% r& _' w/ p8 d" _
                        output += vrc6.Process( 1 )*vol[6];
8 `* `2 @% Y1 J8 O* d* _4 }! L                        output += vrc6.Process( 2 )*vol[7];2 t  X$ l6 D) h) G6 H: p
                }
" }/ K, x  {8 C/ c0 O. ]& z                if( exsound_select & 0x02 ) {) d- J( @" J- I
                        output += vrc7.Process( 0 )*vol[8];
4 v. o) D  V0 |4 [  z                }
7 K2 L5 u  c6 }8 ^. t                if( exsound_select & 0x04 ) {# b, l) Z; t! V. F6 y
                        output += fds.Process( 0 )*vol[9];- L6 |# c1 d, k. @
                }/ K) d4 L# g/ I# B  N) ?8 Z
                if( exsound_select & 0x08 ) {
  i" o3 S. U6 W  b) Y- L                        output += mmc5.Process( 0 )*vol[10];
* |: ]! p& j, [                        output += mmc5.Process( 1 )*vol[11];( |; Z, B: B6 c* u$ Z
                        output += mmc5.Process( 2 )*vol[12];; i0 x$ x1 i! R0 |
                }" N. c9 z# v! {/ R) d
                if( exsound_select & 0x10 ) {
! I- k( y: x7 p: z% x* L- s                        output += n106.Process( 0 )*vol[13];
. {3 l' U7 ], T/ m! u0 o, J                        output += n106.Process( 1 )*vol[14];
! I: H- k' X0 _$ I                        output += n106.Process( 2 )*vol[15];. }5 h7 M! V/ v6 K5 U5 \# O# w
                        output += n106.Process( 3 )*vol[16];* _9 R2 t$ m' Y' H
                        output += n106.Process( 4 )*vol[17];
; C; }4 S3 c9 J$ O4 S8 f                        output += n106.Process( 5 )*vol[18];+ c* S$ f+ j1 L7 f( U
                        output += n106.Process( 6 )*vol[19];
. M  B- _; ^% t, A" m" q                        output += n106.Process( 7 )*vol[20];  ~5 G5 N, P6 m2 p4 [$ s: r3 O
                }$ @) Q# n1 T: T6 w8 f) E* R& }
                if( exsound_select & 0x20 ) {
. }7 p) U. e) l8 Z0 g, H                        fme7.Process( 3 );        // Envelope & Noise. h! ^5 m" J1 s# H1 b9 S
                        output += fme7.Process( 0 )*vol[21];9 ?( C# w  F/ H
                        output += fme7.Process( 1 )*vol[22];* x/ r$ t. `7 n- V! u4 F
                        output += fme7.Process( 2 )*vol[23];) o# ^0 y' H! O) h+ H
                }
4 Y* k. K9 Z4 Y+ K" {/ n* b2 z0 N8 D' u4 {0 Z/ m
                output >>= 8;
1 s/ g* e$ g7 R. f: h) ~
3 S( s7 C- u5 S' v' V                if( nFilterType == 1 ) {
7 B7 s- i; V# h* T                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
8 x7 o8 o( R/ d, T5 Q. u4 k                        output = (lowpass_filter[0]+output)/2;
) N! x: o2 M5 Y) c% N                        lowpass_filter[0] = output;; I" e/ a; N  ?9 ]+ o, s( G- e
                } else if( nFilterType == 2 ) {4 D" ^' C* c6 o2 `
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)" j; ^; X1 {: X  j6 R
                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
6 n1 v2 h$ S& @$ w  R                        lowpass_filter[1] = lowpass_filter[0];
* J, z( k' X0 w) J                        lowpass_filter[0] = output;
4 W1 e* c% ^  J& a& v                } else if( nFilterType == 3 ) {0 b2 g) o1 d2 T( T' E1 x) m
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
  o1 C* H* g4 x6 }                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;- d. L3 Y) n$ F; r' H
                        lowpass_filter[2] = lowpass_filter[1];
% i, Z% W$ g% k2 J; e9 ^  T/ y* |                        lowpass_filter[1] = lowpass_filter[0];
* C$ \% [) q7 D, b% E" F) w8 L0 `4 r                        lowpass_filter[0] = output;
8 o1 l2 Z! k- \                } else if( nFilterType == 4 ) {
, A) B. t; B: s- v& [                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)- P- A* x5 l6 Y( H* G- o
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;
0 {0 J% M: Z2 s  ?                        lowpass_filter[1] = lowpass_filter[0];
- w# d8 H% F! a; s' H( T9 ?% q( O                        lowpass_filter[0] = output;# J; P' ~1 Z. ?1 K6 u" ^
                }( T5 A8 k5 p' A* ^$ u3 K6 Y
7 ?5 X. i3 S! h
#if        0. o) X: |$ `- V. {
                // DC惉暘偺僇僢僩& W7 m3 G, j' w5 ]) U* j
                {: a2 Z4 B( P6 h# o% R. d
                static double ave = 0.0, max=0.0, min=0.0;
# d8 u. }4 h3 j                double delta;
* m; F0 t) p  \- D                delta = (max-min)/32768.0;
1 [! X% I4 d/ w4 X; g                max -= delta;
* p& |! [# J0 j                min += delta;- R$ u' M  n, z/ a
                if( output > max ) max = output;6 i' Z0 b  z+ q( R1 L) I6 \
                if( output < min ) min = output;
3 J$ k% V6 a) m3 a' D3 `                ave -= ave/1024.0;( |* e- {7 r( a
                ave += (max+min)/2048.0;
3 {" m4 l( S5 I5 m" D3 L$ q8 q; S                output -= (INT)ave;1 Y1 v. G; j$ a
                }
: Z$ }" k$ W  [2 R6 r. }5 p, }2 l  z#endif. _/ @- B7 ^' D4 U. r1 _- ?$ J
#if        1
7 ]$ Z' v: t& B. Y  v                // DC惉暘偺僇僢僩(HPF TEST)
# k1 @" y+ ?6 ^0 t: x8 _                {- ?+ l/ ]' B( _3 W
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);1 J. B7 ^+ n) L4 r( r; d$ `
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
: \0 j) E& y+ @& E* z# X' ?2 T/ [6 J                double        cutoff = cutofftemp/(double)Config.sound.nRate;, {% `" A5 H2 h9 ~6 G
                static        double        tmp = 0.0;
7 \0 {0 O) q$ d: ]                double        in, out;4 o2 ]7 E( l% F3 i6 |  [# s/ Z" [' ]
; Y% w$ o% ~, {
                in = (double)output;
0 m9 O3 d# h0 `) [( I                out = (in - tmp);
8 o+ g" K" I' V5 H                tmp = tmp + cutoff * out;! c$ `$ v1 V+ x- ?4 R1 {
( D: o7 F6 ^/ v3 b  Y8 e& K: K; y
                output = (INT)out;
- C7 `. {; }! @: i+ }  T0 t3 z                }
3 O- i$ M; R4 l. B#endif' u1 {  L. x' T6 j$ }
#if        0
9 |& d1 o0 L. X( i                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
$ k% M" s1 r+ ~- w, g                {: m7 _$ M7 |8 @0 @, F9 d5 }/ h
                INT        diff = abs(output-last_data);; E; S8 z: q2 u
                if( diff > 0x4000 ) {3 U1 `' x8 I& z* }1 L  v' u( r; L
                        output /= 4;
  a" a4 n) k2 G* c$ X                } else - @% M4 N' L3 ~4 J# [: [
                if( diff > 0x3000 ) {0 b- ~2 l5 _+ I$ e) Q
                        output /= 3;
- a$ l0 o8 [# t" t( i                } else
8 Y/ t! C1 ^, S6 E                if( diff > 0x2000 ) {
: S* n% G) U& N- u3 o6 u5 L                        output /= 2;( N/ J6 Z0 f8 c& [1 I! ^6 K3 W! z
                }: o8 S4 u) u3 W" l6 b
                last_data = output;
8 s' Z- i: c  m- P! P. M6 }                }: ^7 D+ l  A! V7 e3 ?: l- n
#endif* |# d$ M8 _/ K0 F: Q$ p0 ~
                // Limit
3 P3 i9 @( n+ a9 b" ~, u                if( output > 0x7FFF ) {* o6 u9 _$ |& u' y% w
                        output = 0x7FFF;- n0 R3 ~/ E) m: K3 u5 g- ]
                } else if( output < -0x8000 ) {
8 B- T( P! b& R8 L; E" S9 G7 I! G                        output = -0x8000;: P5 k( {. ^+ R* q) S) }4 E: l
                }
2 b$ {0 I- r' h
5 \: g  W6 o- ?                if( nBits != 8 ) {
$ q+ f' X! N& b6 Y7 h7 q( \                        *(SHORT*)lpBuffer = (SHORT)output;& {$ d  v  E, e6 R
                        lpBuffer += sizeof(SHORT);1 }% f  l! I3 E/ P1 q! G  U, p) T
                } else {
. v* d% Y- d  F( k4 b- J                        *lpBuffer++ = (output>>8)^0x80;
9 V; [$ @6 k+ O! p: O/ Q                }
; M8 g) L8 M; C3 Z8 ~& e7 B- [% ^) Y6 t' X. m5 f
                if( nCcount < 0x0100 )7 E) T, i5 K1 [0 d! @
                        pSoundBuf[nCcount++] = (SHORT)output;! `4 d) c) p( E( _
( _* ~3 S8 x" s9 z- O
//                elapsedtime += cycle_rate;! ~$ A( ~  y' h3 Q5 E  r+ e
                elapsed_time += cycle_rate;8 M9 J: k; ?% C( K
        }8 Q7 f$ |/ p* v7 }, E
6 m7 K* h: g5 }+ f0 M4 s
#if        1( A; e  ^8 J  R$ Z. y: M
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
1 ^" C# Z6 M& [                elapsed_time = nes->cpu->GetTotalCycles();9 @: v- T# m& r  \9 X& W
        }: t0 O8 B* |- _$ ^
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {" t& v& a3 A0 d
                elapsed_time = nes->cpu->GetTotalCycles();
$ J# R6 N" d, J8 V8 O( Q        }
& s& O( _7 j* L; y5 W9 M#else6 u6 k9 i( F$ G
        elapsed_time = nes->cpu->GetTotalCycles();% A( L" j0 ?: w1 f. Z! c
#endif7 q1 |: G2 e7 u& c6 |' b) k' C3 g
}
. v. o, P5 O; M2 w+ d- v. [$ b: Q7 t' Q( _
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)0 K2 o. p- [8 a. v. [& [
INT        APU::GetChannelFrequency( INT no )
8 }4 O  ~0 j1 O* P. M{
  H( a/ @; t* n$ L/ @        if( !m_bMute[0] )0 [, _/ \8 A! k
                return        0;
3 ?6 v1 J$ Y4 U/ f2 i* ?7 f( Q) X% _& b
6 \( d: H& J% g! B# Z, m        // Internal. ^" T( D2 x7 x. I! N( n
        if( no < 5 ) {
3 Z4 T4 X; m( M2 P9 H                return        m_bMute[no+1]?internal.GetFreq( no ):0;
1 G8 z. s% n( c$ ?2 j        }7 }* G: ^- r& K: q0 L
        // VRC6
6 {; w' V( i+ J, Q. D- J        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {6 Q: C9 ]. b5 O1 ~% F& k- O3 h/ k
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
3 F3 t! W( h$ l% r& g        }% t5 u% {6 C' d. v* ~5 v3 ?3 s. c! M' B
        // FDS
+ v" ^5 X" a8 w  B4 y- Y7 q/ ?# M        if( (exsound_select & 0x04) && no == 0x300 ) {
) E% \. o) ^) p                return        m_bMute[6]?fds.GetFreq( 0 ):0;1 v- F- O1 X& B0 W+ b8 d: y
        }
% ~0 ]+ b/ s4 Y: t( I3 w% f7 N        // MMC56 I7 w' \+ ?7 t5 G- \7 A" o
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
$ z3 [* I& O& f/ t, L- d9 h% ?/ ]                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;% T8 y( ^4 c" Z
        }+ z2 A/ ^. ], c; G, U8 K) F& q
        // N1065 ^% |" f9 z3 p/ P2 t
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {8 p& j; J' j1 n6 R4 {0 l8 |5 Z
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;  U9 e9 K) r  m3 z/ N2 K4 I
        }* G0 p- E! a: L
        // FME7" p& g/ U% t$ G0 G/ u
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
. d* b; g7 M# N7 J6 B                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
/ I8 a9 N; ^+ Y% E; o2 P3 t        }
2 r8 H# F# N" h2 S  @+ _8 [9 ?        // VRC7
# S" i+ _0 b- T  V) g& _9 Y. C2 t        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {$ k  |. B  i2 Z" Y( S/ S
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
8 {; n! n& B/ D        }$ Z, p0 F0 p" M  o5 I: p0 G
        return        0;
4 d3 _8 i$ p: S' c4 C: ?& c}
4 Y* }/ S1 o* Z; Y9 J  q/ V- f/ x( ~' E. o+ m, e
// State Save/Load
) F# H; b' [$ ~; Fvoid        APU::SaveState( LPBYTE p )
2 i7 @; }: X: ]8 @: Y( f, e{
. u  R% Z3 \/ @' |( `& a# _7 w& T#ifdef        _DEBUG
; V1 M- Q- M& F3 W, e; cLPBYTE        pold = p;/ R; E( s# ?- z4 z( t2 G5 b$ C
#endif
4 j2 I2 f7 A. a. R, F8 h9 S+ e4 K6 U# d6 v4 e2 M
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞! g2 h2 W2 P' l0 R7 `& a$ r& v7 I
        QueueFlush();# S1 n8 z# A; Y" w. _2 V( ]

) \, r6 s$ v0 K( s1 t1 O7 n" \        internal.SaveState( p );  W4 t# ~4 l' }8 g2 b2 X
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
' v$ u& c( V" n
0 Z/ {2 H3 @7 F3 M3 j2 i& l8 d3 e        // VRC68 Z" x% G6 p6 ]( B
        if( exsound_select & 0x01 ) {
# u5 F8 W" p: `* w2 F5 o1 ]" A                vrc6.SaveState( p );
  S1 b/ M! |( {8 w3 G. c1 r                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
) g4 X& M1 F+ C3 D  ]        }
0 f8 k& f; b) P. O9 m        // VRC7 (not support)* V! F/ |. X( i! g/ @0 t9 |: i
        if( exsound_select & 0x02 ) {: v0 G: N: D: G: r
                vrc7.SaveState( p );+ l" q- G- {) l* \, |' x2 P5 s  _
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding/ i9 `/ T0 Z' t
        }7 Q. a( z) f* x: b# f: y
        // FDS
3 v$ h6 p7 v8 t( h: a* }        if( exsound_select & 0x04 ) {
" t+ q  j6 k. W# z                fds.SaveState( p );
6 N9 X. u+ t* p) H# E5 p2 D                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding6 q' Q0 G/ c! z% {
        }
! q7 r! c8 R, B) ]$ W) L  l        // MMC59 z. t- l/ p% d! B& @
        if( exsound_select & 0x08 ) {
3 F; M7 u+ P3 F) c) n                mmc5.SaveState( p );
5 x/ H3 O! Q5 ]: Q- N) N                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
# P0 g# W; t% M        }
# S1 D# \% n9 u$ Z/ E        // N106# w7 E7 Y# ?! D; ~# z/ ]
        if( exsound_select & 0x10 ) {# E! v4 t( ?5 d! T- x
                n106.SaveState( p );' B" I' `# w) h+ _7 W# s8 E0 x2 q3 T4 c
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding* T+ T: h9 Z# V9 q# P9 R2 k) w
        }
/ f# U3 V7 t2 ]4 ]" a6 G1 z        // FME7
( {, k- U# F3 L% l1 r9 S        if( exsound_select & 0x20 ) {7 b; h7 W3 P# Z3 f6 g! D; b
                fme7.SaveState( p );
9 y5 q; k. j. t& I3 d# x  O; g                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding4 N# l9 J, ~: r# L) B. c
        }
8 T7 X/ {5 y; S* U* c- p: l% L; K/ Q+ b6 I6 ^* A3 h2 O. b
#ifdef        _DEBUG1 L& u& I2 f; i  ?+ m6 N
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% o& A( \4 h" b& _7 {8 z" s#endif( F3 n+ P* G+ r+ }  r
}+ P5 Q- w6 @) J- l6 U

  S% [8 u/ \0 \. V8 Pvoid        APU::LoadState( LPBYTE p )
- Z9 k2 _6 D* I, E/ K- j6 w( ~# s5 P{
4 s8 |$ j) P' f0 _' I3 B$ L        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
$ ?' _4 E! G$ e( R3 {& _& \* t        QueueClear();, B1 {  m& M) v* q) I' u; D- F

- }1 B* T, O* b0 e5 G2 a* q+ {3 i        internal.LoadState( p );1 t" D3 w% g0 E  \  s
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding( p, O( f1 ~* x3 Y

/ R) M) m/ Z3 {1 N7 ]" {        // VRC6
1 ]9 _8 C7 X7 U        if( exsound_select & 0x01 ) {
" r: p! U& \2 t- B% W                vrc6.LoadState( p );5 ], g. \, e6 E2 i, O4 O7 R2 l( f
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; c: L2 ]. ^% d0 M  Y( {% E        }
9 k. t4 Z; O! `2 J% j+ z) r) z        // VRC7 (not support)
  D  E4 N8 s0 X7 v( _        if( exsound_select & 0x02 ) {9 u; d& s" ~, C, X3 s
                vrc7.LoadState( p );% `, h9 |& U& V! I
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
8 {9 a' w  w5 r- e$ W6 s( n        }
$ z2 K1 }' {( R        // FDS6 @+ n& ~4 Y! G3 D' n
        if( exsound_select & 0x04 ) {
/ ~$ s4 M# n1 M+ O' k& ^                fds.LoadState( p );
! q/ c" m8 J' W, _% x) G- q7 ~                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding* d* p) e: d$ d, w8 }8 L. i
        }1 L7 F1 L8 |3 b  S
        // MMC52 J8 d; f4 y8 w! q  ^
        if( exsound_select & 0x08 ) {) p# Y' W6 O- M( P* V  x/ y
                mmc5.LoadState( p );* W$ {$ w7 N1 V9 W* R6 ]+ u
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding& v8 v: f) k( y4 J, d# U1 _+ ~
        }) h, b* g0 g8 B8 |: s7 s5 f/ \
        // N106; M' V) Q5 o6 {5 U
        if( exsound_select & 0x10 ) {
* K5 ]. @$ S! z% a                n106.LoadState( p );
8 l8 z! L7 [& n- T                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  u' B% V( S- P' R        }% ~- }( d  p8 J; T+ z2 |
        // FME7
% d  H4 {, f, X( A* E$ d& @        if( exsound_select & 0x20 ) {- c4 |0 J: S2 C! R
                fme7.LoadState( p );3 h) i4 M8 ?! O8 J  H" P
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding. T4 n7 o; }/ D9 q+ c/ Y6 ]
        }) g& b: d0 f) K$ X) A9 u) x& j
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 - e$ g$ }/ c' L+ ~- F) Z
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
% V' R- w# f/ i3 s* {& o感激不尽~~
! n8 j: e) o/ e. ~
恩 我對模擬器不是很有研究,
1 `! U& ~; I, K; E2 z) ]雖然要了解源碼內容,可能不是很困難,
$ ^. p: w( D- C' a# Z不過還是要花時間,個人目前蠻忙碌的。+ o4 `% I" ^* C, {! F0 i4 {5 }

4 X( l$ _7 z1 j5 K+ Y/ F$ M給你一個朋友的MSN,你可以跟他討論看看,
6 u1 l" O, k8 ?, b- G5 ^他本身是程式設計師,也對FC模擬器很有興趣。
" |6 x1 B& s& W% T. q6 I. K) I
; r  z( I! v5 r7 v  K( N4 D* EMSN我就PM到你的信箱了。
! i9 B1 V' [! U0 P* }9 Z4 b: i4 K; d1 {3 ^6 r5 h# ?, U' Z* Y3 g6 ]
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
% F7 U( ?5 ]: q呵…… 谢过团长大人~~

* ], m/ Q- m$ M9 H5 v
4 m- ?# D2 R- @  @& U  a8 H  G哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
# f/ H5 S0 a( |- x团长的朋友都是神,那团长就是神的boss。

+ Q5 V/ r. D" e- K* ~% f/ f哈 不敢當,我只是個平凡人,8 ~6 k# }+ b( i/ \9 g3 V8 K
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
" {: b- n/ y' z2 C5 W/ o0 kZYH
3 o9 U6 d5 F4 y* p3 U0 G: YQQ:4147343066 u$ O1 h8 ^. ]" k
Mail:zyh-01@126.com
/ Z" D6 M/ W1 {8 f' A
- n: e: b" i1 T6 \/ T7 c3 s5 z9 Q他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
( a& t5 O6 G$ }再次对团长大人和悠悠哥的无私帮助表示感谢~~
' F5 }( I* G& P
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-2 09:11 , Processed in 1.077149 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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