EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。+ z2 J% ^7 J8 G6 N8 a) N1 t" l- d7 `
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
1 O! i( n+ H6 y这里有相应的模拟器源码,就当送给大侠了~~9 j, v* G6 O) i
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 i* `; F1 D8 q
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
' r0 P0 o" H" _7 u  r楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~$ ?2 ^1 X: k. F+ Y9 m" U' v' {3 f  r; ^
这里有相应的模拟器源码,就当送给大侠 ...

# N0 \$ t0 p* _' y聲音部分(Audoi Process Unit = APU):
5 m' H! i6 |$ K' g.\NES\APU.cpp- R7 z6 z5 s) C
.\NES\APU.h
- x' K4 l( b- ^3 u9 I* y4 P0 ~7 T0 _

" i! |) e( V$ A0 R$ Q, x- M影像處理部份(Picture Processing Unit = PPU):4 k( u6 T: B9 F5 @! n7 a
.\NES\PPU.cpp+ E; z0 _" {5 T* T# C1 \9 s
.\NES\PPU.h' k% N, i, s& t1 `

3 y/ m8 X* @$ A0 c7 Y  b9 M: l如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:38:21 | 显示全部楼层
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
5 d- k9 E6 p7 i, y; j+ D5 A感激不尽~~

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
. s4 K* ~- |$ B$ E(由于很多专用术语和算法机理都不明白,所以看不大懂……)
+ v: O$ }& {5 t+ |% _" l! Z( m8 m; F//////////////////////////////////////////////////////////////////////////
- t; U: Z/ ~# S2 k6 T! H& i+ x//                                                                      //2 C' L- O8 D/ h7 h$ o% r
//      NES APU core                                                    //
9 o% g- |3 _3 ]- I3 N. j  X//                                                           Norix      //' H4 ~1 W1 o- O1 K
//                                               written     2002/06/27 //8 L2 o1 E& K2 p! Z
//                                               last modify ----/--/-- //9 o& {' p! A+ c/ B0 }( L: ?9 o
//////////////////////////////////////////////////////////////////////////# u4 N4 a  K- b- D0 C7 |
#include "DebugOut.h"3 Y$ }/ H: x4 g# j" j# p# x& W1 U
#include "App.h"
8 U! j, `, p1 Y, ~& e; l#include "Config.h"
, Y! z" J! m' q* Y/ A! c' \& H3 ?" [  l9 h1 K  I/ Q
#include "nes.h"" j/ E) w+ u( |6 }; M& u+ A1 e& E
#include "mmu.h"
) Y7 {/ r% i6 s#include "cpu.h"
+ Q- x, G  ?; [. Z, d; z& [#include "ppu.h"3 N% O; g; W) |. O3 K4 M
#include "rom.h"
2 L2 t4 `0 I! k" _  j" A3 A#include "apu.h"
$ o; N) W5 Z* y* |
9 I! t! n  J% v+ ~+ q// Volume adjust
3 a( {* H: h6 V- M) y8 Z. L7 K6 F// Internal sounds
1 W+ a' l3 o! ^  R7 d) U/ w#define        RECTANGLE_VOL        (0x0F0)
5 C5 v* N% j) C, W% Q7 N#define        TRIANGLE_VOL        (0x130): r" Y0 c/ b  q7 E
#define        NOISE_VOL        (0x0C0)
" X$ T/ K5 z8 @' v: Y) M( X+ V, r#define        DPCM_VOL        (0x0F0)
: v: m; _" s  V# V" z// Extra sounds
1 o$ q) F* v* @& {2 R  t, N#define        VRC6_VOL        (0x0F0)
- X0 p# y' }6 S#define        VRC7_VOL        (0x130)
% ^7 }9 V% y1 J9 n% d#define        FDS_VOL                (0x0F0)6 u' ~; |$ r. ^8 B- F
#define        MMC5_VOL        (0x0F0)
9 L' i4 \% W0 ]8 Y#define        N106_VOL        (0x088)
$ x5 Q* h5 H1 U7 H#define        FME7_VOL        (0x130); u0 j5 `' \1 }
. X' c/ ~! N. E# K3 d4 d1 T5 T9 y
APU::APU( NES* parent )9 C: k( \. p0 t( W5 M
{# ^- S5 h1 G, N. I( P4 @( m
        exsound_select = 0;2 ?' k3 J; T. Z! N7 T; b

2 @3 n5 S( a1 }# {2 G        nes = parent;
5 y1 B2 f; K& }8 M; Y        internal.SetParent( parent );
' p, `( Y  g8 }; q1 d- V, e4 |8 q& c' N/ |5 H
        last_data = last_diff = 0;% q  m- T# Z/ {8 F9 M6 |8 W1 n

$ F8 I+ O1 j* ^! G  h6 S        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );$ C2 f* s2 s8 Z
- b" x& }" v# G2 O7 q8 k8 ~" g
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );. \/ }6 K6 v1 d6 q9 B, c
        ZEROMEMORY( &queue, sizeof(queue) );' e7 y2 p7 ?. `8 A" I# y/ V. k
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' v9 N6 ^# ^4 O2 y& g% ^& ^
, F, N; l: B; c* e1 Y1 t+ _        for( INT i = 0; i < 16; i++ ) {9 ?- a! G/ G$ F0 ]8 @. j7 S5 d. A7 [
                m_bMute = TRUE;
% K4 M6 R0 [/ F8 L8 D1 A        }$ v$ e+ ^2 }+ m: m# p' E
}
5 s& S" q* D* m" Y  s7 e
  `, w9 j' A  B  D. B5 W0 oAPU::~APU(): C1 c& v/ Y/ @, }0 |. Z- v# A
{
6 H% }7 d# B6 w' S; Q( `}
; a) J" B9 r7 }. z  J$ }+ x/ a! n
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )+ O( ^4 t0 u6 z7 C; }6 r# u* i
{
0 C# O/ r- L9 w1 C/ b# z        queue.data[queue.wrptr].time = writetime;
3 [. y4 w3 S+ m, _# j        queue.data[queue.wrptr].addr = addr;
: r( `) J% F& Z8 O8 B0 W2 I        queue.data[queue.wrptr].data = data;
! D0 z: K8 k3 x/ k* R) ]        queue.wrptr++;5 ?" Q& D) B, h4 R
        queue.wrptr&=QUEUE_LENGTH-1;
  ?7 j4 K# g! n- F. z0 ~$ j5 s        if( queue.wrptr == queue.rdptr ) {
: Q& {# ?2 K/ K                DEBUGOUT( "queue overflow.\n" );, E/ [. ~7 y0 H" D" _
        }% ~" V% U3 [* r' ~0 S
}2 F( `; w& d8 Y0 r# R* ^
5 o# i# U) b5 j" H1 p7 o8 \
BOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
' u/ E: |# T, v: w: y+ s{  ?$ W( J6 h. w) L
        if( queue.wrptr == queue.rdptr ) {
! T. v5 `, y  n' X$ W  F                return        FALSE;" @/ v- f. J7 J4 n  P; u0 \
        }
( R2 s$ O% Q0 R9 @( N: r; D0 h        if( queue.data[queue.rdptr].time <= writetime ) {
' e- C6 _# o( m8 W: F                ret = queue.data[queue.rdptr];
4 ~& R3 E" P/ P) R2 T3 \3 o                queue.rdptr++;9 K: h% y8 L* r# x/ B2 v
                queue.rdptr&=QUEUE_LENGTH-1;% x& g7 [" M% v) z
                return        TRUE;
1 ^4 F3 U7 B: Q" `        }0 m" d/ b8 P, }  d* h
        return        FALSE;! {* }8 F8 M8 A+ P) ?' n. s# Q7 g
}! p0 e& ]! S# {* U

- U0 y% K- b2 I& qvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )% A( S: x# b& w5 q! F" t8 v+ r- M) u
{
' H7 G0 V/ a* k, q9 c        exqueue.data[exqueue.wrptr].time = writetime;
5 k) Y* I, N- L# ^% K        exqueue.data[exqueue.wrptr].addr = addr;9 g( x3 e) M/ }+ x% C% s/ \  \
        exqueue.data[exqueue.wrptr].data = data;# C6 n* X2 Y- [- Y+ o' r
        exqueue.wrptr++;
8 ?" u: @* H6 U0 W& M- i, Q        exqueue.wrptr&=QUEUE_LENGTH-1;
' J2 g( y7 U. ~6 v; `* f4 _        if( exqueue.wrptr == exqueue.rdptr ) {
6 x+ F0 a% ?0 y3 t* d                DEBUGOUT( "exqueue overflow.\n" );# q5 u. {7 }5 ?* G, M
        }
2 t/ K% x" q8 C/ |, D& C}
1 s9 \4 ?1 }4 V. t; _& N" }9 o" M% t5 z$ f* f, G0 G6 m7 Z3 J! K
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )* H" O- n. o5 N. L+ i! o, _. |1 a/ A
{
( r$ ^* _+ D% v! b        if( exqueue.wrptr == exqueue.rdptr ) {/ i+ G4 y% S8 S: y0 J
                return        FALSE;2 o- n- r( ?/ b$ s) Y5 H
        }' |* M& U+ J9 \) g( H, }% H/ v
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {& _7 m: o/ B" L$ y7 \
                ret = exqueue.data[exqueue.rdptr];& [, l& ^, g( {! `" P' q  L0 a
                exqueue.rdptr++;
* @; {) A1 [2 D4 e3 c! S7 c$ o                exqueue.rdptr&=QUEUE_LENGTH-1;5 I, @! a# K' ?- `: d- }* z2 z
                return        TRUE;
/ d5 c- X* y  @% W* u+ O  {  w) H& F        }1 v/ e- w- \' Q" }! S1 a
        return        FALSE;& O+ p* N8 Y# O) o- y2 l5 c2 I4 L
}
, T/ h0 s; w% D; o% M. N. Q: s1 A; e
  V" L0 H; C2 v7 \, l7 Wvoid        APU::QueueClear(), ~; M6 i% y  h& h; D
{
' I5 E4 J+ o4 N" X& s, M8 E% h        ZEROMEMORY( &queue, sizeof(queue) );! `8 S6 W) x) d, S7 ]* q6 o
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' }. H; U+ J6 ^8 q}; b: c8 y5 ^( b  E4 S: b
, L3 }+ [0 X/ ]! C# ^
void        APU::QueueFlush()& @1 o0 ]: M9 u0 _, k8 k( Z" l6 V
{' b" F7 h( I" h4 }( f" b
        while( queue.wrptr != queue.rdptr ) {6 q* b0 T5 w1 `
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );4 R6 B; E4 z7 Z/ D! `+ n
                queue.rdptr++;1 Y3 K' ^5 _) T8 {
                queue.rdptr&=QUEUE_LENGTH-1;1 m/ M7 M; |! P& f+ E1 e, q
        }: @& W  D% F0 I0 c6 |& F
- z8 t( J: D. X
        while( exqueue.wrptr != exqueue.rdptr ) {& I( x% F' O  V5 r) T) p" O
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% v8 ?  D6 C" u, z6 G2 u7 ~) [# m
                exqueue.rdptr++;
- b7 ]0 R+ j3 ?# T: o3 i7 [, N                exqueue.rdptr&=QUEUE_LENGTH-1;0 J, z7 T+ i0 ]
        }  S) h, T5 Z& ^+ \% Q
}
- ]8 N$ s4 `" x# G0 U0 C# F# n6 C# q8 `1 T
void        APU::SoundSetup()& {4 _) A: T0 j" ]' ]4 a0 w
{
, g% _+ {; R+ t: x7 T* k- Z        FLOAT        fClock = nes->nescfg->CpuClock;+ F' ^  R7 G; h. T; @7 H
        INT        nRate = (INT)Config.sound.nRate;
, o6 Z4 r! u& V! j        internal.Setup( fClock, nRate );
& w$ ?5 c# \1 c+ ^- y& b        vrc6.Setup( fClock, nRate );  p  w* T& \, \
        vrc7.Setup( fClock, nRate );
  w$ z# O' {* |: ?        mmc5.Setup( fClock, nRate );3 d* }. Q2 n; x/ k" r& g& v6 P
        fds.Setup ( fClock, nRate );; ~9 h8 F. D1 a
        n106.Setup( fClock, nRate );' K' s. {9 g  H8 }( i9 }
        fme7.Setup( fClock, nRate );
) T% T: b, m; |2 V! a: y9 W}
: |' T/ v- o$ L! [3 L, o4 n$ W/ m; ?/ ~; F0 h. l
void        APU::Reset()- t$ _; y8 x; a, ^
{* V3 Y5 A4 j9 g$ Q% S7 m. H1 H4 h
        ZEROMEMORY( &queue, sizeof(queue) );9 {6 K  Y3 o; D+ {
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
' Z) C0 }- m2 @. w/ Q. _' U' c) C) n# M  ^4 g5 _( A& s
        elapsed_time = 0;
5 U7 i/ k3 P2 C& u( N0 g! R6 J7 D( O$ \8 x2 E( e
        FLOAT        fClock = nes->nescfg->CpuClock;
& T) p3 S$ A% u+ [2 q% J1 a% [        INT        nRate = (INT)Config.sound.nRate;$ r( Q" h9 `# G( f! x7 u
        internal.Reset( fClock, nRate );
" F3 ?5 h! K# {% L, z        vrc6.Reset( fClock, nRate );) ]4 T2 n0 l- L7 r' n
        vrc7.Reset( fClock, nRate );% V, }, J- s# `! w" h1 G6 W  B. J# n
        mmc5.Reset( fClock, nRate );
- a9 i, U' H6 ^* G7 z% E. S1 Q        fds.Reset ( fClock, nRate );$ }/ b" e2 l7 P) i
        n106.Reset( fClock, nRate );$ d2 ?5 P" `1 u5 h
        fme7.Reset( fClock, nRate );
- u8 M- Z& L# w# j. ^8 p& o8 T1 i# h
        SoundSetup();
1 Z# t- `5 D! V( b. J/ s# T}
+ k. i1 t% E& {) c* V2 r- l/ W3 m3 M% P8 H+ [
void        APU::SelectExSound( BYTE data )
2 c0 Q4 k$ X8 m8 W{
  P: J; C% S4 R  o0 D9 ]4 C' [2 U        exsound_select = data;
# i6 c7 Z7 R. D( v}6 z  N, T3 u' @6 @* R+ a
2 @+ v: b  C8 c& r4 }
BYTE        APU::Read( WORD addr )
  ]' G# L+ D( R0 F{& Y/ P4 }& K( L& v6 Z' `
        return        internal.SyncRead( addr );+ W% S& |" Y( X4 H
}
& H1 P' a# e* ~( Q, o5 F$ i- c& `8 _8 o3 d( i, C) ~8 a& e
void        APU::Write( WORD addr, BYTE data )) V: y# S. O- q5 ^5 |2 V
{' z3 F  ~5 R8 K2 R2 V
        // $4018偼VirtuaNES屌桳億乕僩9 z& g) K' H# T; d
        if( addr >= 0x4000 && addr <= 0x401F ) {: M6 \/ ~; k/ S+ K; |+ d1 S) M
                internal.SyncWrite( addr, data );8 g. {* B8 a3 n  D) E
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );; e% ^! u7 b: a" g! `: x$ ]
        }
) T+ v4 G% c( K}& q+ g4 ?6 B0 V7 ~  x
; T- O2 y' g* V( t7 A
BYTE        APU::ExRead( WORD addr )
0 ?) B/ J$ ~& H+ U- I# C( M; F( |{% S1 p7 L1 y, p* @$ `/ Z
BYTE        data = 0;
! u7 r! s; n5 G. M+ m" y4 R7 K8 m; o! W5 P0 ]- Z) K
        if( exsound_select & 0x10 ) {
0 a5 E& w4 j% O) ]. c                if( addr == 0x4800 ) {/ m' k5 |1 c1 ]1 @. a& {- ?+ t* r
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
) R: U5 Q$ y$ ~& E: a) a9 H                }' u: r$ r/ ?& j( D
        }* Y, U/ O7 `4 s: b
        if( exsound_select & 0x04 ) {
" @' D) u4 |1 p0 v                if( addr >= 0x4040 && addr < 0x4100 ) {
. A) X, C" y# J1 x! o                        data = fds.SyncRead( addr );: ~9 F; |1 L, R! ~/ p
                }5 l9 e# y# l# q1 b9 \/ F
        }
" I* I* v7 `5 X/ o9 \% z        if( exsound_select & 0x08 ) {
. ~5 y- D1 i1 r: \/ ^; D                if( addr >= 0x5000 && addr <= 0x5015 ) {
9 u' s$ j- s* B# u. H9 N* m  S; ^                        data = mmc5.SyncRead( addr );
0 o5 _! X- z- z9 [$ p9 e# G                }3 A" e1 S7 Z  x. l3 N) r& {+ n+ y
        }
: d' y8 C- |" E2 g! w
+ J& }- q4 s) i- i" t        return        data;& S0 ~: f- }- R8 u6 V6 e+ D
}
4 b: [2 H$ x' Y& k* `& p9 e# M) H
& r& U* z$ ^* D  dvoid        APU::ExWrite( WORD addr, BYTE data )
% f6 ~- p, [: X{
- {! G+ y1 b5 A% e        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );9 ?, ~6 A0 Y3 X1 O: s0 n8 U
* p, ^* E3 z; f7 l" A
        if( exsound_select & 0x04 ) {
( w2 h2 ^& M1 L5 |                if( addr >= 0x4040 && addr < 0x4100 ) {
; [; r2 e% R  r1 E  ^                        fds.SyncWrite( addr, data );
: M/ g/ i3 e& x- e                }
: s" U" _( l8 @* e" Q3 I2 a$ T        }  W: Q5 D7 L, ?% E2 ^4 I

9 b6 V: [: d0 {7 ]+ k2 }        if( exsound_select & 0x08 ) {" L1 C7 C( n2 P; Z5 A- @, r  F
                if( addr >= 0x5000 && addr <= 0x5015 ) {0 U# V. Y' @  b, T! ^
                        mmc5.SyncWrite( addr, data );
0 o: N  `( |* N0 s                }
( M7 k. J6 |" f+ s' o, u4 I        }
. w1 Y2 G( K3 b2 W9 {- M5 o# \}
( I6 {2 }+ x+ `0 J8 s6 z" I3 ?1 N5 W; q! J
void        APU::Sync()
  k  H* S" }! I- P{0 r+ _" `. G" _* h  O3 }7 u* ]/ X
}
& B+ ^! x# x. D1 k. O* v0 q! }( I; ~2 r; x
void        APU::SyncDPCM( INT cycles )8 f1 v  o/ l% ~% w6 l
{
6 s. z* j% F# `$ S' m        internal.Sync( cycles );& S% F" Q6 v7 Z: q
  K+ ?4 t& g) J5 I, Y9 Y
        if( exsound_select & 0x04 ) {
7 m% \& O4 h/ X2 t                fds.Sync( cycles );3 K- `1 H4 u' d% G
        }8 L9 u! n/ o% \2 _( O
        if( exsound_select & 0x08 ) {: p$ u4 V6 \! ]  ^7 e# m
                mmc5.Sync( cycles );
/ X2 ^' @8 ~& x8 G& B/ V        }4 t- u8 b6 x/ o/ f
}
7 S3 _' m+ I8 C
0 z# [7 x1 X) p& W$ O* f# Tvoid        APU::WriteProcess( WORD addr, BYTE data ), g! y( G6 ^1 H/ b$ v0 y1 P1 s! ?
{
3 e4 o* ~8 r  Z  ]" X        // $4018偼VirtuaNES屌桳億乕僩( \% v! Y3 Y. x% G* ?) R
        if( addr >= 0x4000 && addr <= 0x401F ) {
, F9 p2 |- S/ \5 W4 g1 f                internal.Write( addr, data );% n9 [$ [  R. ~# H( C. u6 G
        }! o8 {/ k; g# J, L! t2 o2 m
}
/ Q# G+ M  G7 _& f1 Q( F# P3 V! c% k2 x( L8 `/ P8 _7 p
void        APU::WriteExProcess( WORD addr, BYTE data )
& O% i# g3 A8 {{
* J' l, z: f$ h/ E4 ]1 t        if( exsound_select & 0x01 ) {- u% }: n2 ^" E4 e7 V& p5 l+ ]
                vrc6.Write( addr, data );
! o7 m; a2 i  e6 p0 H        }% o. u# r8 w5 n" X; V8 B; }
        if( exsound_select & 0x02 ) {
6 t& R  v- C' r  a3 f* E9 _' b                vrc7.Write( addr, data );
  ^& T+ D) Z: X% c# C$ a3 c3 ?6 X; ?        }
. N  B% y% q- n2 _% X& S. e# f% P$ A        if( exsound_select & 0x04 ) {
' o# Q1 f" x/ F! p) A: p& d                fds.Write( addr, data );
, ~  W2 z7 M" V* f: U, C2 o( O2 `        }8 N1 {# F) ]5 w) F% x  M
        if( exsound_select & 0x08 ) {- M1 V' ^3 p# Z3 t& q; }. c
                mmc5.Write( addr, data );
' O* ]% q0 I9 a% A" s( \' E& Z        }  {, L0 u3 d  U- r8 I0 K. x, A
        if( exsound_select & 0x10 ) {7 [4 g5 S* Z! q% K
                if( addr == 0x0000 ) {% L& Y4 r9 p3 m0 ?, b7 e
                        BYTE        dummy = n106.Read( addr );+ F; _  \) e: @7 `
                } else {
7 I$ E+ v! k5 P! s: x' z7 d8 g' a                        n106.Write( addr, data );
6 K" m8 s  V0 k/ u                }
0 s: s: w. P) g        }5 W9 ?+ z( k; {% E, n( Q
        if( exsound_select & 0x20 ) {
+ {' [( E! }0 l6 d5 ?. n                fme7.Write( addr, data );) \! _) o. F  p/ L3 s
        }
. O+ n/ K1 P% u. |* O" r}
+ r3 i, l7 {3 g/ Z
4 X9 I4 E) ?- vvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )9 Y, G& S0 y) @6 S6 I$ B: V7 x# l2 R
{! f! Q9 E& U& B  s. g
INT        nBits = Config.sound.nBits;
% L) }- c: Z) ]9 l; l* u9 y* nDWORD        dwLength = dwSize / (nBits/8);0 W2 T4 x  L% A/ e; e+ n
INT        output;
" Z* |4 ~: N  H* J- ]QUEUEDATA q;1 H/ o6 u8 O$ ]) X
DWORD        writetime;
% E, z; y6 Q$ J/ ?5 a
% i6 b! E$ b9 JLPSHORT        pSoundBuf = m_SoundBuffer;
3 k$ ]$ {4 a; r3 r6 b+ k6 ^, O: xINT        nCcount = 0;( w6 @% \- e& N4 D( V- j, A; t8 n
/ i' A/ ~) u/ X0 m! w, ]
INT        nFilterType = Config.sound.nFilterType;
, A( [3 p- l& g* Y
' \; K9 V- b' l        if( !Config.sound.bEnable ) {) W# Y1 k$ k% Y% c! d8 \
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );5 q" W4 v4 W$ C4 X3 z  P+ B+ c2 G, u
                return;9 a0 }* G9 R& ?* R
        }
* X8 h& Z5 k! n% Z
4 Q# R  h  C# A" ~* F        // Volume setup
7 A' ?4 O% w; y4 r) l: x9 {        //  0:Master
6 h) a: v( D3 ^; r9 N6 u! M' D        //  1:Rectangle 14 i8 r( b, I- U7 m
        //  2:Rectangle 2
/ u. K1 B% a1 |5 G        //  3:Triangle
6 l% i; [: Y. T" p1 [* e4 A. I        //  4:Noise
* e0 e  c6 ^- _        //  5:DPCM
& z% |' k4 l) O6 N7 `  P        //  6:VRC6
+ t8 i" J8 f7 g' i7 A& g        //  7:VRC72 E, Z' }6 w# P5 f6 ^* L. k
        //  8:FDS
# g/ a3 }1 P6 G% U& T9 q3 s6 l& C        //  9:MMC5) l$ K! p9 I' ^# a5 q
        // 10:N106
$ f1 J0 J7 A$ Y        // 11:FME7
6 Z1 G' r$ l5 J6 ~3 z; a8 l        INT        vol[24];" E8 @3 W  z8 _, `2 p+ `
        BOOL*        bMute = m_bMute;# K9 Q# ?5 S8 Q/ V
        SHORT*        nVolume = Config.sound.nVolume;1 Z! c% P. I& f

7 ^9 X  H) k+ U* f. E  z        INT        nMasterVolume = bMute[0]?nVolume[0]:0;" |2 e1 k" v6 ~! y
& p6 S: [1 A9 V- D' m, w) r
        // Internal4 g8 z/ A! P) G. @4 S4 V/ S( b
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;
. t! H! @7 z% x% q& f9 k& J2 s  R$ u        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;  I( i  f& y0 q( L# u
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;) [+ x3 f- Z" W1 }1 W. C( b. a3 ^1 s
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
& V  O5 p: z2 D2 W) W0 g% G        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
: k8 m- e) d* c; p+ {
# i( q# K  Q2 r" n3 m% K        // VRC6
% \9 k$ h0 g" c2 ^: a6 u9 F! @        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;& k& ?, o* ^* `2 F
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ C1 S2 G* H" u, R$ m" j        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
& l& @: _- K/ j) p* z  \: H$ I1 l7 _6 s4 Y- J
        // VRC7
) e$ {! H: [' M+ g$ n        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* d5 \2 Q& O  L" _5 ^, @! a9 R5 Q% S: |! a
        // FDS! D( [- U$ \8 @. C5 L
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
$ U# u/ g$ _% C- E" I8 b8 ]4 \8 \! M7 Z8 I. {
        // MMC51 J* A! l  W( @! U% m! X; n- H" I
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;0 r6 O" J  e* {1 C1 j- T
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
' W2 n: F+ [* s: x        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;1 F, x. t! ]3 c' e8 H
) K# J9 r; Y. i( E3 k6 a/ Y* C% f
        // N106
( u! _% ]" }4 ?! g! A- q        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ o+ k. s4 M3 ~6 E4 l
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
( g) A+ M0 t  [8 l. {# h7 H        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
/ }1 T: c5 l- w        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;; N, A" V, o' [  u& S! z8 F; Z- T
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;, P! f/ l5 q0 F: H- n
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;5 t* N0 ?: }/ G% B& q
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" [* x. l+ Y, D  R% u
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;+ {2 G+ B1 b: P7 g' W

& a7 z- t5 k- I; K6 S* c        // FME7. [7 X, T5 T( Z- I7 S
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
. `5 E: I) y4 g& e        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;0 s) G1 `$ G, j0 q; J
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;4 [( ?- U& s: t

9 x$ d* x/ V9 }  M; U7 k8 D2 E; c//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;, ^: Z* k9 ~  x6 ~( l
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;
/ j! K! I. b' ^( J$ s% O) @- N8 r4 C+ n: K% n; g, e
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
4 Z! Z/ j/ Z" l# @( {) N        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
) k( M6 C( ]* u+ n2 M- Y! `                QueueFlush();. D, w; u  I) k& G
        }
6 x' g: U6 a8 X2 Y& S& H  {% H, ]: B7 Z4 s! ?$ f- g3 p+ [# ?$ q+ O
        while( dwLength-- ) {# {, j+ S, e- U3 x! R7 s
                writetime = (DWORD)elapsed_time;4 F5 \7 H. @; y  L

3 O, i+ _% U+ h: l' M0 B  X: z                while( GetQueue( writetime, q ) ) {: D- b; a2 o# E, o; u
                        WriteProcess( q.addr, q.data );
  s( C# n5 ^! y, u& C                }
1 R/ Y6 v6 X, I/ W9 K6 Z3 r7 f3 Y) T3 T5 [% b( l
                while( GetExQueue( writetime, q ) ) {# f5 n0 [$ f" K2 c9 p; Y' ~
                        WriteExProcess( q.addr, q.data );
. D. o9 w) R/ j2 r- t                }6 w& f' P  _) d) m( C" t

; ^! v" v% X5 H5 A  d2 b4 }                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7
+ P; X5 }: w+ Q1 m) l: W: O                output = 0;  u- ?0 v/ X: g5 f; E- P
                output += internal.Process( 0 )*vol[0];
6 e* j1 B  |% V                output += internal.Process( 1 )*vol[1];
  k7 }; A6 l5 Z# E! j" x                output += internal.Process( 2 )*vol[2];
+ V- w* j7 `  `, P, e                output += internal.Process( 3 )*vol[3];
$ e6 x  v& W  R$ q                output += internal.Process( 4 )*vol[4];
# P  T7 f* a) V1 P% s
; n; l* v9 T% c+ k                if( exsound_select & 0x01 ) {$ q4 @/ _! i  H; v+ X! w
                        output += vrc6.Process( 0 )*vol[5];
# f- P* M- h! n8 O/ ?# h% J                        output += vrc6.Process( 1 )*vol[6];- E% l5 T" e  V) Q; f# m
                        output += vrc6.Process( 2 )*vol[7];
- |/ a4 _! C2 ?9 b6 _. g                }- \3 F  u( ]- h) B1 `8 b
                if( exsound_select & 0x02 ) {
, x1 G$ X+ m8 o' Q, ^* x# n                        output += vrc7.Process( 0 )*vol[8];
+ v' E- Z8 f# n) i8 j                }6 u  p5 C! {: g$ u! f
                if( exsound_select & 0x04 ) {
' J2 P# |2 L3 f+ \, _& h/ {+ g" a# B                        output += fds.Process( 0 )*vol[9];
& v" ^3 u* x' _, W3 y- q; i- v                }
& ]8 Q5 @. d) n+ r7 o+ k& u                if( exsound_select & 0x08 ) {
6 b/ B- k" h7 S: S( F4 l                        output += mmc5.Process( 0 )*vol[10];
" F3 |+ G) J$ o: p7 P                        output += mmc5.Process( 1 )*vol[11];) B9 u3 V+ D3 o
                        output += mmc5.Process( 2 )*vol[12];- v& A, k( V- b( A8 H0 _% R6 B
                }
" c6 f' r& K  D" g# s: ~2 x; N% _                if( exsound_select & 0x10 ) {
* @, h$ e9 {* Y0 P# g8 a                        output += n106.Process( 0 )*vol[13];
* h1 I0 u# M1 q6 t$ J                        output += n106.Process( 1 )*vol[14];
! Z* r- q2 R! j" m; o! O0 _                        output += n106.Process( 2 )*vol[15];
- a6 |% V! @& l5 _  [6 V                        output += n106.Process( 3 )*vol[16];
; z( M$ |3 t0 J' b3 d1 ]                        output += n106.Process( 4 )*vol[17];- _% I; j) p4 D: }( B3 G6 v5 e
                        output += n106.Process( 5 )*vol[18];
1 [0 L6 b1 @0 c                        output += n106.Process( 6 )*vol[19];
" Q; e) Y5 g& O                        output += n106.Process( 7 )*vol[20];2 P" t. F7 }8 s. D; @2 u8 d
                }
6 f! T/ [/ i# {* S2 C* C                if( exsound_select & 0x20 ) {
$ J  o& ?6 \: D  Z3 z2 z                        fme7.Process( 3 );        // Envelope & Noise) o1 U% N0 r  a% o
                        output += fme7.Process( 0 )*vol[21];' w4 |- @3 r2 E% ^. N* }0 b6 Z
                        output += fme7.Process( 1 )*vol[22];7 k: f) J; }, L0 P9 o5 j' B( y
                        output += fme7.Process( 2 )*vol[23];
4 e; ?/ Z( T* G& X1 z7 o5 t0 d( ~; c) w                }
" b- g( C  v* c: i  j8 n- r  @2 Z& L: A! b- u3 Z
                output >>= 8;3 \* x7 X2 i! }6 u' B& y( `
. W. @% ?: I& @: c
                if( nFilterType == 1 ) {
6 y% i5 z- C2 C7 N: B( o                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
6 W# K5 `6 g6 F6 d7 V                        output = (lowpass_filter[0]+output)/2;
% ^; z% P$ n5 E2 i6 a/ Y                        lowpass_filter[0] = output;: R% j+ s/ E  N: [1 a# x
                } else if( nFilterType == 2 ) {6 ]* P( f4 |- t( q; d
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
% @; m8 s* U5 d                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;; ], v. d. E3 T
                        lowpass_filter[1] = lowpass_filter[0];* K% n* B9 w! g
                        lowpass_filter[0] = output;
; h$ k- }$ u4 f; a9 q9 T                } else if( nFilterType == 3 ) {( `3 U2 s! h) v' L
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2); b+ f  N7 P" G0 P& d
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
  b+ K" u7 k) D1 ?                        lowpass_filter[2] = lowpass_filter[1];. z1 y5 x0 i4 a! ?9 U$ V2 b
                        lowpass_filter[1] = lowpass_filter[0];
+ q7 t7 J" _) o0 C! U                        lowpass_filter[0] = output;
' S0 |1 ~+ I' U% x1 j                } else if( nFilterType == 4 ) {0 t. M* }5 _' _/ T/ V( w0 G
                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
# o* l- I( Y$ k( }. ]0 _$ c/ K. B                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;, ^" r+ f; M8 Y$ P( l2 e& A
                        lowpass_filter[1] = lowpass_filter[0];/ e1 c' h2 q/ y+ x9 M/ X3 p5 M
                        lowpass_filter[0] = output;; @3 m8 j3 B) o
                }
1 _. Y+ x, U9 k7 t: a% V4 H
; _: N8 L8 D7 ]' }) O$ T0 D4 W#if        0
- y" x0 E( }, g% ^                // DC惉暘偺僇僢僩( ?( D& \" j  y
                {4 P- R2 \8 p4 Z+ q
                static double ave = 0.0, max=0.0, min=0.0;* B" E% |# ^! L' o8 N# S
                double delta;
/ N( O, z( ]7 Y8 I) |# S                delta = (max-min)/32768.0;% a. [4 w6 ^7 p4 t+ l
                max -= delta;* }* C+ ]% g. Q9 h8 @/ |, [. f! f
                min += delta;$ v  J$ H3 ?# W1 M$ _8 F0 P/ z
                if( output > max ) max = output;2 _# H& u+ v( \- b7 P
                if( output < min ) min = output;5 _1 I% h! ^! H$ ^: u
                ave -= ave/1024.0;7 [+ x4 C  D2 [
                ave += (max+min)/2048.0;
1 `) \) x/ J) C  U: g                output -= (INT)ave;
- J, {% O7 i. C) c; M3 ]3 ~: _                }
3 f( B5 T( F8 [, x# N' z#endif6 U8 X0 b# p# O3 d( }: M
#if        1
! l% q4 D  _3 b3 G' _                // DC惉暘偺僇僢僩(HPF TEST)* n9 H. Z) f8 v' O* y( j
                {
8 P& t5 Q! g. k//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);. \0 O3 ]5 K$ K& P$ q( y; Q  a
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
# C' W* V# H4 I$ i; e                double        cutoff = cutofftemp/(double)Config.sound.nRate;+ s) ^! s/ \4 v0 H
                static        double        tmp = 0.0;2 {) y1 F& B3 [3 Y" D6 t
                double        in, out;7 l4 }; N' q0 u5 y  N! ?2 w7 [7 R

6 Z  e$ N/ k4 s                in = (double)output;
/ |3 ^2 ]3 s& f1 S9 M                out = (in - tmp);) O0 R0 z+ C: Y% ?
                tmp = tmp + cutoff * out;
% g0 x! s- i8 k0 G3 V; ?
5 B% w$ y+ o$ ]                output = (INT)out;( [5 }4 ?6 {& J
                }
" V! R+ G! T4 b) D0 n#endif
0 K) K- ]. y3 }6 v; V; a% R, S0 ?#if        0& H. @2 _8 Q& P! z. Y7 E# U) p
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)9 T' U- T. b, L% _
                {5 e( F" T1 n+ H5 {) j
                INT        diff = abs(output-last_data);3 S. y" {9 Y+ w0 M% ~
                if( diff > 0x4000 ) {
. A+ `& }3 r2 G4 `) G                        output /= 4;. Z- I* \: y% c$ K8 z( b  Z
                } else & z2 C" z$ H6 m1 z
                if( diff > 0x3000 ) {
: p' k! V1 J: B. J6 }# b                        output /= 3;7 [- t, o& @  ?$ p0 n: C
                } else
; |+ W. j- Y2 g$ U                if( diff > 0x2000 ) {' @' Q  z4 P4 S8 g5 U; i1 c
                        output /= 2;
# E( w& i3 T9 O+ q7 ^                }9 Z" j4 W- o* [  L6 p
                last_data = output;
) j  d1 H2 o6 q& h% O) T* K                }1 w: K7 P  q$ B, t- e4 Y: c
#endif
; A- m4 U) }( c8 W2 \& E                // Limit
# x; l, Y" s- z( Q/ l                if( output > 0x7FFF ) {# ]( a+ ~. |( T
                        output = 0x7FFF;
9 u& f/ K$ v  f( _3 K                } else if( output < -0x8000 ) {
& k6 W& l' e2 j8 ]6 X0 R                        output = -0x8000;
7 q% F3 y8 y  a. Y' c2 J- _# o0 |                }
. i) o/ M. P8 }+ e7 h0 m8 p: B! S2 X/ y% X$ O) _. ?
                if( nBits != 8 ) {" I4 U3 ^2 ?  p+ f8 m, ?
                        *(SHORT*)lpBuffer = (SHORT)output;
1 {& i6 X% Z8 @                        lpBuffer += sizeof(SHORT);4 ?7 l& N3 @% ^) U1 d$ I
                } else {) V6 w- S5 a. }9 E
                        *lpBuffer++ = (output>>8)^0x80;' H) P6 |7 S$ y% u
                }& `9 N3 `0 P7 X2 x) j  N" _: C

+ t: M$ |  @* I1 O) ?! ~+ H; |* ]( n7 g                if( nCcount < 0x0100 )
) j" L5 s, T& O$ G; P                        pSoundBuf[nCcount++] = (SHORT)output;
# i& y& K( j2 @& k0 A
* B$ O1 Y0 P* Q8 M  p6 J//                elapsedtime += cycle_rate;5 I/ v% X* c( s2 \0 T/ c
                elapsed_time += cycle_rate;
7 x' @9 e: ]; ~6 J  z        }
. [$ g- O) ~% Q& A; }; g) g1 G  [2 |4 M( _9 W
#if        1) s& h9 l3 }- w. `
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
: g- r0 ~. y' T. L% l2 F0 e0 g( X                elapsed_time = nes->cpu->GetTotalCycles();: d7 s7 ^" ]+ ^5 K' W
        }0 Y0 @, {! q/ g
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
& ~' a* s5 Q: Q, J4 X, Y6 C6 A                elapsed_time = nes->cpu->GetTotalCycles();# J# }( [5 T/ s$ Z; y  B% b
        }0 S2 s! d, u0 H4 w- g" r' P
#else
6 ]( R+ W4 {4 P) }        elapsed_time = nes->cpu->GetTotalCycles();
6 y3 _! ^2 Q! O: X#endif
& G& ?! k1 k# k" O5 s}( O+ h6 ~8 @$ [

' J3 U9 V5 w8 w3 R7 P: B! Y// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)- d$ i& ^! {! R% T' Y& G
INT        APU::GetChannelFrequency( INT no )# u2 G5 [' R5 \: m" X" u. a$ U
{* K& s" y7 j  G3 v
        if( !m_bMute[0] )1 Q( i" P, R/ M
                return        0;
2 w# u( J5 s- U
. O5 p( T0 Q9 \, g4 @( g        // Internal0 m2 L) F3 p% A( ?5 ^5 B. p: l* o) V
        if( no < 5 ) {6 l) f6 l% _5 S0 ~! N3 k9 q  X
                return        m_bMute[no+1]?internal.GetFreq( no ):0;
) }+ W" i' `: g        }( c: V/ [' ^" C1 Y4 S
        // VRC6
/ L$ g3 K( R1 _0 D, h) a3 N. g; H% o5 e        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {
2 \5 r$ l2 I' ]8 l/ V                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;( p+ w# d' C, }' p, x! u
        }+ [' j4 O, ~& I* m
        // FDS
( i8 [& F& x( G, h( M( I        if( (exsound_select & 0x04) && no == 0x300 ) {
# S/ C( w7 V' X" s( H$ O                return        m_bMute[6]?fds.GetFreq( 0 ):0;
0 i8 ^! ]& I, ^, v( m        }1 E$ u1 J" ^8 h1 I) Z
        // MMC5
* D0 ]0 D" D3 I        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {% ]( g! Z) Z: B2 a  F
                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;9 u  A; K3 b" P$ K* u
        }8 ?4 R$ B; t" m* Y( E  Q
        // N1069 J6 D! X- Q# g# W6 ?4 @  L, t
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {3 B4 v1 N2 ^: f$ U+ m# W
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;5 G) T: |/ f5 q; A) E& s1 @6 O3 R
        }
$ n: Z+ w7 g( [% x# X# P% E8 y        // FME7
# M+ p& v3 v9 f+ b        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
1 x- @% K8 j) o4 l9 M4 q' `9 ?4 C                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
. H1 ^, \8 q( k9 i" W* e2 D) R8 `        }/ Y5 p: K9 `: s: Z* I$ a% Y2 i( h
        // VRC7
  k- Z' D2 \7 m. C/ o! n        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
: u( h% V3 b7 G8 b0 a                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
$ c, j' Y* O7 z/ h        }
1 y7 v* _% `# A( W+ _1 o1 V        return        0;
. X9 R- J3 ~1 L}% L. S7 [. J2 ~

; C, K) @8 z2 E% \) e+ x// State Save/Load
- }4 i+ z; k: e& ?; G( zvoid        APU::SaveState( LPBYTE p )+ i. j: C* L" a$ o9 ^0 i
{
4 }  p6 f, d( l6 z" m* S9 M#ifdef        _DEBUG3 w/ y" T' d2 @0 L
LPBYTE        pold = p;* v% Q+ \1 N: v/ p( o
#endif
% U6 y5 [4 M5 a! o: [0 i& Y+ i( b/ d
) r+ J% {2 U2 q+ x2 f8 o* Z        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
8 X! N- h. n8 R9 U9 i        QueueFlush();
6 d, D$ A. c0 `7 y
& ]" ]+ d: q& h3 e5 G: a        internal.SaveState( p );
) h2 r( ~+ v. a9 S- @/ d        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding* @* L5 X  q. t( C7 d' [& y4 a9 {

: l+ a6 p/ y: j* J5 f& j        // VRC6' o4 }1 T: }- d2 L5 I. }) @" U
        if( exsound_select & 0x01 ) {
, B4 B. ?) B1 r! j, P# }+ x                vrc6.SaveState( p );
8 C: K6 M. V7 w; ]                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# ^5 ?; ]: X1 i* x3 o5 y
        }
1 w4 K6 {+ Z3 y* H8 C1 E        // VRC7 (not support)5 f0 z$ V  o# p6 |
        if( exsound_select & 0x02 ) {, i1 T5 C0 s/ ^8 e
                vrc7.SaveState( p );* V% ^) G* p  _
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
: ~, K& e0 L" C7 T6 }        }
  m+ K+ @8 T+ E* y, [0 ~        // FDS9 ], m+ H9 j3 k/ w
        if( exsound_select & 0x04 ) {
5 Y2 F- r/ O/ L+ o9 m( F                fds.SaveState( p );* |7 o  O* Z! j% j) V" C
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding% G$ r4 h/ D4 l% I& ^4 k
        }
. a# d9 j" X8 A1 e3 J- T        // MMC5/ C) q2 r9 |- g
        if( exsound_select & 0x08 ) {, }' V$ N0 p* C: L
                mmc5.SaveState( p );
5 m/ \( k0 g. s, N                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
& o/ F0 l1 s2 w: f' T6 ]4 r        }
; K5 U5 n- `6 j  h        // N1069 H. W* z# T" w* S: e: h: Y9 E( J
        if( exsound_select & 0x10 ) {
) _) u( N9 m& |+ e  w                n106.SaveState( p );
3 Z6 m  p$ {9 s( W0 f                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding, `" H* [* U' W+ T( S8 W7 w
        }8 d# A8 G+ o# w% V( A* j
        // FME72 {: D. p+ g. `
        if( exsound_select & 0x20 ) {8 X& f; ^5 ~8 j3 x4 t
                fme7.SaveState( p );( R7 m( B0 F$ W
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 |+ ^, ?9 y7 L) f% t: ]
        }
( b9 k$ Q8 a" z  l/ ]: Q3 q$ @9 f
" A/ K6 c* z' T9 \) h  ^#ifdef        _DEBUG4 d8 q& q. X' F; H+ Y& H& U
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
7 f; {: e2 y2 e/ _3 @% W#endif+ ?8 a7 {5 L+ B3 \6 v" T' k
}
, q/ L( ?3 h* ^; R8 Y) I  `# T# z, ^4 T9 G8 \. A3 P& P& R( c
void        APU::LoadState( LPBYTE p )
2 A! G& \' Q; x5 L{# v; b2 v/ [, D* D+ |# }1 ^2 X$ t, _
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡$ `& D( W: D. ]
        QueueClear();
2 U8 i9 m* M9 g; I: y6 ]+ d: z: \* L1 y, \: z% J
        internal.LoadState( p );
9 g' ~0 j9 D( |! Q& f3 y( _; s- H        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 _$ s9 z* _  \: q6 q8 {
; t' Q/ m7 F( n# Z: r7 [        // VRC6
5 O5 f$ c2 L  Z4 I, i4 C2 r  w        if( exsound_select & 0x01 ) {
+ p% N( i( Y+ i; j                vrc6.LoadState( p );* L- d  Y' U! d4 c: e. E
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  o0 L! {5 p, s# E; ^8 S" {6 y
        }
" N2 I; }$ D4 L7 J" e        // VRC7 (not support)
: W& m+ n  q9 b2 r1 ?5 o) m; ~        if( exsound_select & 0x02 ) {
6 W8 j& f% W& @$ |3 g                vrc7.LoadState( p );/ c( ~2 @* |+ m* e2 ?8 [
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding: x6 F. b5 Q) F/ ?
        }
0 M( x7 a& w9 T1 W* e" f        // FDS+ q, h% i0 l! {+ r
        if( exsound_select & 0x04 ) {( M+ q' j3 S% D
                fds.LoadState( p );( x; x3 Q9 L" R- h
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ T; W5 h% f! D9 t' h
        }/ h% N* ]% @9 K( X* p  @
        // MMC5
5 U; H5 b; H0 z: t        if( exsound_select & 0x08 ) {
: g0 c  k' q" Z# e% ^                mmc5.LoadState( p );8 H* c, `( C) J, q/ S- X
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
) @4 C; P5 Y1 `% D! J5 a7 }        }
+ o, x) `* U5 k: W9 }! x        // N106
7 O! K: p( s1 Z* d0 \        if( exsound_select & 0x10 ) {
) U2 a5 j2 {$ t- }5 O                n106.LoadState( p );8 K; o2 z: y$ m: }4 w1 l, v
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
$ q( z6 Q, X* t" y        }0 Y& Q" [; t9 r# X/ O: ]  U
        // FME77 M5 P! B  p/ f# w3 h8 b
        if( exsound_select & 0x20 ) {
( x/ a$ C% L6 F* \9 n9 I7 _4 a                fme7.LoadState( p );# `+ ~, f$ h1 Q1 l
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) }' M: H7 o( A3 Y        }
7 T2 m! D+ m# B8 E9 W}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表
0 i8 u4 b* s2 _可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
2 V& ^1 M% z. B" \+ V9 s感激不尽~~
$ O* {- X2 J1 x9 P2 \. H- s
恩 我對模擬器不是很有研究,
% \$ q9 O& u3 F# ]% M& C雖然要了解源碼內容,可能不是很困難,
# w$ |) k2 X8 U( \, C5 J" i不過還是要花時間,個人目前蠻忙碌的。
. h$ }+ ]0 g# z- }  u
; z% v' `, d' l3 f給你一個朋友的MSN,你可以跟他討論看看,
9 ?! b* S# ]- {  }2 V他本身是程式設計師,也對FC模擬器很有興趣。8 [% B" c) @* {$ V; p5 z2 y

  i6 `7 q- B% p1 zMSN我就PM到你的信箱了。
7 r. E) n$ J: t8 T$ G  }% R
$ w7 X, @! Q5 U/ s/ b希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' U' l7 D7 j- E9 V" {. n
呵…… 谢过团长大人~~
4 t+ G5 v$ x! G8 a, t& T
! e5 s% O7 x) P, ]( J* b' t
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
: D4 |! |8 p* E* E团长的朋友都是神,那团长就是神的boss。
8 `; r! N: j, o% a( ^. T
哈 不敢當,我只是個平凡人,% D8 y* o: d7 g  r( g
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
1 r" N/ z, t1 N, F7 I* {ZYH
" R! b. a6 a/ S+ I! r# O' uQQ:414734306
, f7 p, c: N! b' ^* A0 e0 xMail:zyh-01@126.com: U/ H# G* I& S, P" U
- P) Y- j2 A! q0 d2 r
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
) u* Y9 e, U, ^) |1 V再次对团长大人和悠悠哥的无私帮助表示感谢~~

. h& y) \+ C; h) s4 ~不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-25 14:41 , Processed in 1.114258 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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