EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。/ _: g* V) ~5 O, z/ _, [; R
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~& u) J' e4 N9 Y, W2 E3 A
这里有相应的模拟器源码,就当送给大侠了~~
5 {9 C2 S8 B* Z  o# U0 fhttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表
4 y) y( s1 k3 l, p1 M, h能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。1 c! C9 J& u) A) Y) P
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
7 X: K! F! M) w$ |5 M% O这里有相应的模拟器源码,就当送给大侠 ...
8 y: Z- }: z2 V6 |% h
聲音部分(Audoi Process Unit = APU):7 T7 R) g( x2 ^0 D
.\NES\APU.cpp
# Y" o; A8 m9 V  u. V7 d' s.\NES\APU.h) ^% z% s' d: g$ Q: Q: P
, S1 t2 l' _+ K6 j% z6 A" M

1 K- G! b! {) _# z影像處理部份(Picture Processing Unit = PPU):$ ~. h* f7 t5 F" `/ j7 f
.\NES\PPU.cpp+ X7 D. o9 X1 k. P% B1 H; q  U
.\NES\PPU.h: }' z# y! x/ i8 O  a  l& h

" w2 c8 n# @, F. ^" U7 o$ }如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:) E7 }% ^8 i  A3 F- d4 \* l7 ?' t
(由于很多专用术语和算法机理都不明白,所以看不大懂……): _; F9 r- r& O/ C5 _8 C7 S+ x
//////////////////////////////////////////////////////////////////////////6 l/ T; W: C* c  I8 @+ d
//                                                                      //5 M% h! h( C- H, C
//      NES APU core                                                    //% c* Z1 z4 s. z/ X8 n, j# L
//                                                           Norix      //. M# o6 v& r! k$ f4 X- U
//                                               written     2002/06/27 //
5 z: p) c; }& j* o9 }0 l' d4 e3 K//                                               last modify ----/--/-- //1 @& O! Z  ^* q) Q% p
//////////////////////////////////////////////////////////////////////////
+ J; l9 v8 l+ t# r3 a) P/ a3 Q#include "DebugOut.h"9 A9 }! F: T- p+ G# u/ b- S
#include "App.h"3 G; l. h% Q3 E8 X+ W4 A
#include "Config.h"9 ]2 L( ~8 E1 d  _
" R: \0 h# ^/ ^& F' R6 c
#include "nes.h"/ E5 C- G6 p0 Y% h$ e, ^
#include "mmu.h"
8 F+ B8 i6 k+ }0 }) c% T#include "cpu.h"3 f8 k3 ?4 @8 G: f
#include "ppu.h"
* o# t3 V# c! N# Q) y3 C#include "rom.h"+ C( ~. P9 a- Y
#include "apu.h"
  F0 b/ _8 Q! |
! E' e' C) V9 [6 d& r7 a// Volume adjust
" J; h$ z5 A1 K' h( f: A: c// Internal sounds$ Y& K7 t& e0 n; Q5 x: {3 m
#define        RECTANGLE_VOL        (0x0F0)# o  h9 a* y3 \. `3 \
#define        TRIANGLE_VOL        (0x130), a- D4 c( g9 t9 q/ ?
#define        NOISE_VOL        (0x0C0)
0 o+ S' ~6 D! _#define        DPCM_VOL        (0x0F0)
: o" r) Y* j; U8 ^% ?// Extra sounds
( p) X' G, y" {0 F#define        VRC6_VOL        (0x0F0), N+ n1 }7 Y1 a/ G* L
#define        VRC7_VOL        (0x130)- j' d( D9 O+ F9 b
#define        FDS_VOL                (0x0F0)
$ _& y( F0 v+ q#define        MMC5_VOL        (0x0F0)% W* B9 I, T: L! g" w' A/ F( }1 G
#define        N106_VOL        (0x088)
% p4 v  m% I  ~0 |#define        FME7_VOL        (0x130)9 p( l" n$ D1 I0 C
' M5 j  l6 ~% E
APU::APU( NES* parent )
$ O3 o+ \# O: ?. T* L& W- ^# `{
& C( G5 U; H- _" |. Y- W        exsound_select = 0;( e. @5 F8 Q- T9 A- M3 ~( [/ |

8 I. _! A9 ]! q# A3 K# s        nes = parent;
8 d2 }1 Q9 \( V8 A        internal.SetParent( parent );: ~' W! h3 [8 L2 g2 D
5 d  c6 F, k, p* C+ S, g6 ~
        last_data = last_diff = 0;9 _- @4 @- H% x5 q
) r0 W( _+ f6 X1 x$ E2 r; Y) X
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );, ~8 [% i, [- D7 Q! [
7 Q3 X$ b1 s- U2 {
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
' {& q  z6 L. _) Y  Y) u        ZEROMEMORY( &queue, sizeof(queue) );
; Z) Y* Q4 @" {. k        ZEROMEMORY( &exqueue, sizeof(exqueue) );
# m- j4 `7 o5 o0 k4 {5 \
- t. o! l' b1 l" ?& s6 ]        for( INT i = 0; i < 16; i++ ) {
0 [0 [" Z& b8 Z. x                m_bMute = TRUE;5 E/ Z. U7 f2 ]% |7 ~1 j0 D
        }
. }& o. k& Y6 s+ e5 m& B}- o0 ~8 R% U9 G* o
8 w+ x7 E2 h9 K$ y" k
APU::~APU()
0 N% Z* \% S, F- N0 Y! i% l; H{1 y$ U' ?: ]3 Q9 {" t3 q: }* E
}& F' l; O! [4 |; W6 E( \4 c0 u
! d+ O3 L, y* Y. U6 z: S
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
: l* r! C2 A+ }$ h{
/ i2 f2 c0 g2 Y- n0 d        queue.data[queue.wrptr].time = writetime;
" W4 a' ~1 A% n* _1 A! F        queue.data[queue.wrptr].addr = addr;
* M$ c3 i, R: R% ^. b# q- B# ], l        queue.data[queue.wrptr].data = data;
3 L0 i$ r4 N9 ]: v" Q        queue.wrptr++;4 L4 O3 _7 E9 [* O' j2 i
        queue.wrptr&=QUEUE_LENGTH-1;$ j) J5 H+ u$ G$ v0 o7 g$ }9 q1 K, t
        if( queue.wrptr == queue.rdptr ) {- k% Z4 ^( z  {* ~+ B- ]
                DEBUGOUT( "queue overflow.\n" );
' _6 W. \6 X% |3 k        }: s5 p- D6 R" I" L7 q9 _( A
}
$ @" O; d7 B- w7 K
2 E* [7 D& n9 UBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )# M; f4 W+ u" G8 b/ S3 v
{
( G6 o- }& H  `& c, \2 h        if( queue.wrptr == queue.rdptr ) {
8 L$ C+ g" P- A2 J! Q& f                return        FALSE;  K! L: g6 s8 K% _" i3 ]% g  K  ?
        }/ z# \8 _' x. R+ ^5 L' l8 {% A9 ]
        if( queue.data[queue.rdptr].time <= writetime ) {
# _  n. ~! A0 j  @& m  @# g+ ], A                ret = queue.data[queue.rdptr];. K, b4 H0 G. R+ Z
                queue.rdptr++;
- b# I% L" v  V6 N                queue.rdptr&=QUEUE_LENGTH-1;, K* j9 T) ]! G! }" G9 x
                return        TRUE;8 \8 v! {2 g: Q5 w
        }
% Q3 o4 }5 F; l& Z        return        FALSE;2 K2 n0 B( q  n& D; p9 g5 b
}1 ^! E) g! j6 A1 D% i# V4 Q
- a3 S/ h# L2 l
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )# L- |2 ]: ^8 O5 H" H/ n
{
& h9 {& Z* R8 |        exqueue.data[exqueue.wrptr].time = writetime;" v! w, S6 x4 s& a. c7 V% _, i
        exqueue.data[exqueue.wrptr].addr = addr;
$ ~, N" N. u& X. u        exqueue.data[exqueue.wrptr].data = data;! j5 U  b, k& |4 z
        exqueue.wrptr++;
* `6 w9 H6 ~- V& X2 [        exqueue.wrptr&=QUEUE_LENGTH-1;4 t$ X* M4 m6 u4 z# Y6 t
        if( exqueue.wrptr == exqueue.rdptr ) {" V3 g0 |9 ?1 Y) _& @, d- D' j& D
                DEBUGOUT( "exqueue overflow.\n" );1 G, V# }2 ?) J6 Y) {0 a5 p& ~
        }, _* `7 Z% e+ p1 ^* `
}4 Y* C1 ~' q: L' x, N. |

* X# e3 q' o5 C7 e. f0 {BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
! S9 K! F) O! s+ V$ {/ N/ b1 L{
+ s0 r5 Z  s7 Y( ^9 {: A' A3 z        if( exqueue.wrptr == exqueue.rdptr ) {+ a  H  A8 f  \* V3 ^
                return        FALSE;
2 {" D; I4 `8 r8 I/ S- o        }$ e; G$ e6 d( N
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {; s' u7 w* P9 [* X# W7 b' [1 F% @
                ret = exqueue.data[exqueue.rdptr];
$ @- k7 o8 }5 ]) {# ^. T) @                exqueue.rdptr++;
7 ]" x8 s3 i6 }# ^1 o' O8 a                exqueue.rdptr&=QUEUE_LENGTH-1;
0 z1 t4 T! J! _7 ~3 g: K4 `* `/ I                return        TRUE;  v( r% p' ^6 i
        }
% w( E8 V# R) C8 @6 a+ p3 G. H4 v& O        return        FALSE;" @* z! x7 W8 A; v
}
% b  n( J- s: D: c/ A4 m# e8 d3 \. ]2 V: K1 a9 u8 h/ g5 b% Q5 v
void        APU::QueueClear()
( M* r% I6 x9 V( G+ Y% G{' ~/ f! y, U8 A0 B* }' Y. V
        ZEROMEMORY( &queue, sizeof(queue) );
; h, _6 x9 k  ~' c4 \6 |        ZEROMEMORY( &exqueue, sizeof(exqueue) );
% X  K5 C0 ]9 U  ]; |}3 }& g( K2 `7 ]8 B! {8 ~& [

, F1 t0 n, I* rvoid        APU::QueueFlush()
5 ?9 J  Y1 O7 ?2 ^4 [{
# g& o2 {2 u9 D3 Y2 [2 N. A        while( queue.wrptr != queue.rdptr ) {6 |. j( I8 y9 B7 l3 G; _1 @
                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
2 e1 x' Q( l6 Z# c5 _                queue.rdptr++;
) U: n* P  C$ I, F6 h. {/ G                queue.rdptr&=QUEUE_LENGTH-1;
% v, d- d: x3 T; k( `$ d+ w        }1 h5 W% A5 d1 T

' r, y  P4 D. q" N- k. D5 p        while( exqueue.wrptr != exqueue.rdptr ) {
, ]$ {/ H% f$ t  v& L% Y0 u                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
* `3 X. ?9 i9 j+ Q                exqueue.rdptr++;
' E' `3 S/ b7 l8 P                exqueue.rdptr&=QUEUE_LENGTH-1;6 e2 J; Z& q. i  n
        }
4 g3 r6 m: Q& z, W4 v  z}
" I1 s8 ?6 F' w8 k/ s: [! A$ M, L/ e. p
void        APU::SoundSetup()* N7 s- s% O9 h: b8 T
{
" ^! ?) j( J/ P9 Z5 }. y% G        FLOAT        fClock = nes->nescfg->CpuClock;4 Z4 N4 s9 P- W0 n" A; R( D
        INT        nRate = (INT)Config.sound.nRate;
  G8 u; h: X. E* z        internal.Setup( fClock, nRate );
4 }- x8 a0 }+ O        vrc6.Setup( fClock, nRate );
4 E; M8 \! |* D5 m, A" r        vrc7.Setup( fClock, nRate );
! h$ W6 q6 K- p- N6 V. m; [        mmc5.Setup( fClock, nRate );6 d8 L5 v* Z4 B! `. L- j
        fds.Setup ( fClock, nRate );9 z" F: _. w% q- N, Q4 g
        n106.Setup( fClock, nRate );
7 T/ Z* I6 f" {$ s        fme7.Setup( fClock, nRate );
: ?/ p- J% O8 e- B, b  `& e( |}5 p* I  J4 h7 a: c! D

" U( W% z/ @2 F# m% w5 Z; evoid        APU::Reset()
* F' ]3 H' q$ Z* c: z{0 a6 y) ~' T+ i/ S/ f4 ^- {
        ZEROMEMORY( &queue, sizeof(queue) );
* H! M$ h6 V# C2 P1 ]        ZEROMEMORY( &exqueue, sizeof(exqueue) );) e1 `" M4 ]7 d4 e: {; }% c
1 _3 z6 M" s5 S( n! g- d
        elapsed_time = 0;
7 c% N8 d3 h% `+ W
5 Y, Y4 @% g1 ]% h+ Q6 H5 O        FLOAT        fClock = nes->nescfg->CpuClock;
" f. f4 A3 V% W        INT        nRate = (INT)Config.sound.nRate;* y( G8 L, o4 Q+ W9 X
        internal.Reset( fClock, nRate );
- P% q7 i4 l" |. R/ l+ d9 d. y        vrc6.Reset( fClock, nRate );2 r: t, F& K; f6 d
        vrc7.Reset( fClock, nRate );
7 {* A' d* L: q/ e, r        mmc5.Reset( fClock, nRate );
1 X- m" S/ O% S2 R% w# a3 R, ?        fds.Reset ( fClock, nRate );
& p! @# A4 _8 L: c/ F) I: J# t        n106.Reset( fClock, nRate );
8 M' ]0 X% g9 c8 m* t2 O        fme7.Reset( fClock, nRate );
+ Q7 A$ u' a2 M# K3 L5 n2 U2 ^' z' S
! c) N! Y5 H, L        SoundSetup();3 }5 E) h! s4 V6 V
}
4 B# u. d: X0 I0 E2 U
6 U9 {3 b. Q1 X5 Nvoid        APU::SelectExSound( BYTE data ); `* Y9 J- J8 N5 Y6 m
{
1 b7 J0 p2 f- t% v% D        exsound_select = data;
+ r; z! S% p6 R& _9 C+ j% k}
* u! Q' j9 W. {; Q) Y: q
6 y  n( a+ ~4 i8 qBYTE        APU::Read( WORD addr )
2 t8 c6 w# J* n# x6 |6 |6 K{
9 R% l9 k5 w& ?7 L7 i        return        internal.SyncRead( addr );9 N3 A) L; J" z* p' U" M
}# _0 K) q4 S, b( P
4 Q: D2 b/ I; n- ?
void        APU::Write( WORD addr, BYTE data )
5 ?5 d, K( x8 X/ q% i3 d( t{2 d) Q8 L% X6 ], [, A2 l& F
        // $4018偼VirtuaNES屌桳億乕僩% R% ]8 Y# \) X6 Y2 p: \$ m9 J, ^
        if( addr >= 0x4000 && addr <= 0x401F ) {
6 u, ^4 b% X% z+ B  {                internal.SyncWrite( addr, data );  W" h8 g1 |4 t9 N- M
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
' u% G/ H4 u( g; K. M, ~        }6 W1 Q) X5 A# Q& {
}; Z+ Z4 d% p2 P  W# m& T( q

- R5 @% _: K9 v8 kBYTE        APU::ExRead( WORD addr )! ~9 B  }0 m3 B3 C+ I% p
{% n1 U! j5 n2 r% K+ _% O* G  {
BYTE        data = 0;
; R/ }  ~, U/ S3 M3 D3 E. c
4 S& A6 P5 K; Z! x) i4 V" q        if( exsound_select & 0x10 ) {
  z- l' T( _. l0 x                if( addr == 0x4800 ) {+ \8 Z- L+ M" B
                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );( y7 D) L! f# c; f5 k
                }& N) ^$ o1 W5 `3 x, S
        }
: C7 F) a2 l2 Z) m- I0 B+ ]4 G  b        if( exsound_select & 0x04 ) {- H; |$ i0 W' O: c( ~1 @, K
                if( addr >= 0x4040 && addr < 0x4100 ) {
0 O- J4 n# M/ I! V1 n                        data = fds.SyncRead( addr );2 y2 K& f. g$ k& Y4 H- M2 Y% Z5 H
                }, ?! ]5 H/ U* h& P4 d
        }
8 `) c9 c+ s2 ~( V4 T! Q- w        if( exsound_select & 0x08 ) {
4 x# {7 v1 {& P: u- ?                if( addr >= 0x5000 && addr <= 0x5015 ) {
; A  u. ?8 V- h7 Q& q                        data = mmc5.SyncRead( addr );
+ j! ~7 S5 w  C$ ?! D$ a. p2 P! T                }$ F& s) u0 e9 U2 M# W3 o) z9 C, b9 z
        }
3 z0 Q! g/ d: ~* z1 |7 f
! o1 B- \& Y" y: z, `6 d4 ]        return        data;: ]% A, n9 n) z4 j$ x, M+ s0 U& u4 q; ~$ z
}
1 E0 t6 A* L$ @0 p- s" ^5 \: x
% M$ Y) I* l9 y8 {. g& r7 V5 wvoid        APU::ExWrite( WORD addr, BYTE data )
/ j' Q# t4 S1 t' T{
, E/ W' U* m* W        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
6 r8 [( L. O+ \. A! m+ i9 i, T: ]# l2 {
        if( exsound_select & 0x04 ) {
6 _% _1 T) n9 K3 a                if( addr >= 0x4040 && addr < 0x4100 ) {% D+ H$ U- s/ U7 m* I
                        fds.SyncWrite( addr, data );
$ K6 Y5 S4 W3 T5 [7 A. [; |                }
! b0 s0 W; g1 L        }
( A, v' J4 w3 B' f/ J6 Z* u! \) P0 u0 r: C  D2 P
        if( exsound_select & 0x08 ) {: g3 M! Q) t0 l' y
                if( addr >= 0x5000 && addr <= 0x5015 ) {
1 T! _! e  l- \7 b2 C4 ^                        mmc5.SyncWrite( addr, data );
  s) H" I& T# A; f% G                }
7 _: ^, G2 z& w6 d        }. k" ~, I  w* x9 u. `) s$ D6 n
}
" c8 K# J; ^! {1 p3 a: X2 F3 k: X# C& M# D4 a
void        APU::Sync()! _# |9 b0 c2 a
{+ w) K! m0 u  ?2 s; e. ]
}' y" j8 j1 I' b! s  x

  b* ]4 m* X1 D# |' j7 Cvoid        APU::SyncDPCM( INT cycles )
% s( A* G/ q' y{
) d4 n& G, ^/ y- {  p5 @& b/ X$ n        internal.Sync( cycles );  _5 R/ [0 m. G% L; V. D: r$ H/ }- o
. ]' U* s% b* J8 B$ e, A
        if( exsound_select & 0x04 ) {
" ?+ Z2 @% c5 e* @! T- _) o* C                fds.Sync( cycles );
4 D6 `! Z/ F, y- i' C+ y        }
0 C# P; p! l' ?$ u9 I- |& w        if( exsound_select & 0x08 ) {
' `( U) n! A8 X0 ?) g                mmc5.Sync( cycles );$ C3 P0 V; P5 @6 _
        }
# \1 j2 x/ a& Z1 g; {}
: {+ q, H& R8 t
. X  U, w8 u+ p& {void        APU::WriteProcess( WORD addr, BYTE data )
# f) I( y% J5 c  `. S# Q, s9 M( E4 `{. ^$ ?! b$ k) a- b
        // $4018偼VirtuaNES屌桳億乕僩, o$ l" _  l' S/ A
        if( addr >= 0x4000 && addr <= 0x401F ) {. L3 p9 u" U! Z$ `: @. w6 T
                internal.Write( addr, data );
  @4 p' @# N) c, r        }! s- _, \2 u( o
}; N9 E- Z6 `) C7 D& l

" c; B* E2 M/ ^- I" Avoid        APU::WriteExProcess( WORD addr, BYTE data )( p7 F& i8 e7 O
{
/ {0 B1 ?& I3 X8 A& {; U% |) `* A6 E        if( exsound_select & 0x01 ) {
6 @3 E$ B; V, }# W                vrc6.Write( addr, data );$ D: E( l9 o& K" r; B0 q
        }$ p  y5 c, D3 ]. Q) h; v
        if( exsound_select & 0x02 ) {- ?% q5 W! @0 s# r# G
                vrc7.Write( addr, data );
! {. i+ Z5 q. T6 M        }
7 V: d1 E& K# H7 ]* o3 p: A        if( exsound_select & 0x04 ) {
* e: t: G3 v8 z, q6 c                fds.Write( addr, data );
! f1 a6 h" \) t        }$ _+ N. v/ N, Q) d
        if( exsound_select & 0x08 ) {. W1 Q% B; f4 u2 ~) }4 z7 j% u
                mmc5.Write( addr, data );
, N9 N) S1 {( F        }" D% {6 l0 A: E5 W
        if( exsound_select & 0x10 ) {2 O2 W# J. q( q: I
                if( addr == 0x0000 ) {
( P* D- ^% C& T  s% S+ ]                        BYTE        dummy = n106.Read( addr );
. ^- K, P4 u' j: V/ H  z2 y                } else {
' t' x( R6 {- g4 t  u8 t                        n106.Write( addr, data );
. ^# x0 Q' S, b1 Q, Q2 Z, f& ~9 q% F) t                }0 Y: y. O% p' ?  f
        }
% F* `) o" M- ?: g! k# b7 f. h        if( exsound_select & 0x20 ) {
( s$ Z/ f7 c: B                fme7.Write( addr, data );( V( o/ W7 R5 B: x& l% l: ]# J" P
        }
2 {8 Z0 R6 X# c( ?, U}/ T- [6 E* ?* C9 g& e0 P
2 X' R& D/ p! W$ a. M
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )2 y* d% I- _  e* c
{
2 v9 Q! d( y4 I5 A  j& X, ]2 V6 ]- X3 \INT        nBits = Config.sound.nBits;
1 M5 N$ n/ Y  A! b  Y6 g6 _DWORD        dwLength = dwSize / (nBits/8);. x% H& m* E4 Y3 y* h, h) C
INT        output;
/ A/ F9 G0 B5 B/ SQUEUEDATA q;
" `# Y0 x; i- z7 gDWORD        writetime;
2 c0 ~) K& ]2 u2 U( y; f) o# U% H3 D1 V( e
LPSHORT        pSoundBuf = m_SoundBuffer;
4 ]. K- Q' z# A6 G( X+ WINT        nCcount = 0;
- f! p- R) m1 Z! a, E5 Y& k4 _3 c, _+ V
INT        nFilterType = Config.sound.nFilterType;( o2 Q6 L/ z& N& r

, J* l( Q: {0 U( F6 A" [        if( !Config.sound.bEnable ) {# K: E" i3 F% h: ~4 d
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );9 F, @+ K4 d7 t8 Z8 g+ l/ ^
                return;
- D: J( c' ]  @4 ]2 ^: N        }0 Q$ t6 U9 A* }
* o3 K# V" Q( h& j  \
        // Volume setup/ q3 }6 M/ J0 V0 C# _2 ]$ F
        //  0:Master
; n  H4 Z# p3 y( A+ z        //  1:Rectangle 1( |: }. ^' w  S" {# F! r% |
        //  2:Rectangle 28 n  p& C* Z2 O. \
        //  3:Triangle3 Y2 u" A" P& L7 ^
        //  4:Noise
4 {2 H, {& }6 X' w0 l$ _- {        //  5:DPCM
4 K3 S2 R' M2 U+ W        //  6:VRC6
) y% C% X) e+ m0 D6 I        //  7:VRC7. }* Y2 ~9 a% d* h9 a4 X9 ?
        //  8:FDS
" n$ x# L1 g6 E( p6 S0 n# S        //  9:MMC5
. d# \( |5 v; w& a        // 10:N106
5 q  v; D9 d. _        // 11:FME7) O. M) L. s7 d9 K  L
        INT        vol[24];3 o4 M) I" s9 P1 G/ H
        BOOL*        bMute = m_bMute;8 l6 I6 L, x; D2 j+ s* F2 _4 e' J
        SHORT*        nVolume = Config.sound.nVolume;
' \: w) {- W2 F% i9 Q- v2 m$ w" ?4 H
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;0 w* P* d* T/ Y+ o; T. T$ v- `& W5 A7 {

$ K0 Z! I1 S1 r( F' u9 P2 H        // Internal6 W' q; I5 p: G* o
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;! l) B% l$ B* i9 w0 I; u
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;; q+ j6 a2 i3 v, N0 ?2 W7 g# K' a
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
3 N' ?, V! o6 u        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;: b2 N6 M# e; g" I
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;. v# z5 q# {# D& h

: V% g( |; T2 x8 _2 L2 X        // VRC6
' X; q9 G. u5 i' {        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
/ a; ]. c. k, w# ]( g7 }: U        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
2 C7 ^0 D& Z9 ]6 N  L        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
: B# d" `+ m8 I! s/ E4 L+ c" u( G2 V3 G5 ^# Q2 `
        // VRC7
# V, @6 C' L0 O, b. W$ m  n1 m        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* h5 G! Q/ U4 E# {% L$ {6 W4 G) A
        // FDS2 u3 Z: f( D4 U
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
6 N0 a2 M, U  t! a) O4 f/ F/ P) ?: ?0 w8 e
        // MMC59 S! N( c+ s0 r6 Z6 M6 x
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
+ m+ e3 e9 u6 }3 D        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;7 a% B- L5 a9 }; v
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
; \% D: ^* P4 d) w0 F) K) r2 V' Z0 o9 P1 k* d
        // N1067 S' L. ?$ ?% D% U1 F
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. s2 c7 |/ g' z/ t6 t- z/ ]1 o3 l
        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
4 k$ l/ X7 n! t1 l        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
3 l) ~. u9 K; F( n. B/ x# N  U7 P        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;* ]8 G+ z+ L  X/ ]4 W# Y3 F! X
        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;7 Z2 R: |4 j, a$ ~% D; H
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
; v- G- B/ R3 B. m# p9 `        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 o( `9 e5 q, d2 Y5 [
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;" y$ F2 f1 D/ V6 q5 _
3 P' B" y( m# Y0 I( e
        // FME7% y: o: r& c1 Q' U
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
5 @# {, C% c1 K7 h7 M/ \        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;, A7 W. T  X" H/ h; U( |4 q
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
8 j- c2 S/ y1 c* ^3 {
6 j/ @. R! o9 P! I/ b//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
3 n2 p* H. @5 e: w9 D/ J1 L9 I        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;& N2 J, ]8 ~! x1 }' W+ c% V

, L( y: X( R1 h3 V1 C        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟; c8 s4 {" I* G+ c# Q. z# l
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
7 ^/ m8 y" H; J3 C1 ]3 b0 r                QueueFlush();
2 {# S+ C7 P/ u. r- U7 p        }
  r" E: v! r3 h0 A. E" G5 X
0 a8 u" r" ^3 P. A3 {        while( dwLength-- ) {
0 U. ^$ x( u5 Y                writetime = (DWORD)elapsed_time;
2 {0 z/ w' w4 L! i  Q2 |3 ~5 w
5 H' V* w. J4 l4 ?8 G/ |* o                while( GetQueue( writetime, q ) ) {
. |  ?% v; ?9 c: V( u) A                        WriteProcess( q.addr, q.data );8 M5 B* L' r$ o4 N$ \5 n
                }
- v7 s! e# G" u+ d$ _! w
$ S* J3 c9 ^% X  Q' B                while( GetExQueue( writetime, q ) ) {
* F1 X% @8 |# [3 c! y" I' w                        WriteExProcess( q.addr, q.data );& M. v0 r9 o. g, E
                }5 d( s' i2 X2 ~0 s1 m6 e0 v& ]

" ]- X: Y* h) y  p" V& f5 V; R                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME70 P5 d2 s9 [% w. t1 \' c
                output = 0;1 ]+ T! X* j' x: Y: N/ c6 k
                output += internal.Process( 0 )*vol[0];* M% q3 D, m: N) j
                output += internal.Process( 1 )*vol[1];
  \- H+ T0 n5 i* O9 {/ G8 R                output += internal.Process( 2 )*vol[2];# O0 L) B% S  O( J- ?
                output += internal.Process( 3 )*vol[3];: S- W; x; W/ B: e, }/ ]. _/ m
                output += internal.Process( 4 )*vol[4];
9 M. }4 s! v5 V2 X5 s8 z& W
/ K, J, p# s/ ~. L+ A8 U" R                if( exsound_select & 0x01 ) {
7 D: O1 [" F! b1 ~                        output += vrc6.Process( 0 )*vol[5];9 g7 W- l1 `  a$ l
                        output += vrc6.Process( 1 )*vol[6];
+ @* T1 v9 M+ b! T                        output += vrc6.Process( 2 )*vol[7];
4 [/ N1 |9 B. W. c2 S                }' ?: j, {" Y7 [! ^7 f$ g0 t
                if( exsound_select & 0x02 ) {3 G  T7 Y9 f! Y# m6 u8 x$ R* H
                        output += vrc7.Process( 0 )*vol[8];6 j! j1 x! E6 h) v4 k& _
                }! v* j9 ]5 r  w& X0 G& @4 ?
                if( exsound_select & 0x04 ) {2 ]" E+ |1 {7 O8 `
                        output += fds.Process( 0 )*vol[9];
8 z8 Q- E. `  W6 c8 D                }
+ o/ R+ v. S  ?$ |' A3 k8 Y                if( exsound_select & 0x08 ) {6 b3 Q- V6 d/ H9 A1 K
                        output += mmc5.Process( 0 )*vol[10];
6 u  m0 E* F( Q0 V! b. n& G                        output += mmc5.Process( 1 )*vol[11];
( ?' v  }/ V- i2 F- j2 C                        output += mmc5.Process( 2 )*vol[12];  u- O# t$ ]* X" ~3 D: K
                }
2 P3 T5 V3 g% `! ^/ m                if( exsound_select & 0x10 ) {
) d3 H( c! \% O1 S9 M6 y9 ?                        output += n106.Process( 0 )*vol[13];% m0 m8 K  f# @& a1 u# _5 W& S
                        output += n106.Process( 1 )*vol[14];+ S; v; @3 g. B2 Q/ |
                        output += n106.Process( 2 )*vol[15];
# b+ d9 W8 a; E: Z8 t                        output += n106.Process( 3 )*vol[16];+ L& M# U$ J$ _& g- l
                        output += n106.Process( 4 )*vol[17];  W/ g- r" N- S, [: n6 |, e
                        output += n106.Process( 5 )*vol[18];
; |# u1 g( v8 W: V: S2 C0 ^# W( }                        output += n106.Process( 6 )*vol[19];& A) f$ N9 ]5 r1 O
                        output += n106.Process( 7 )*vol[20];# v% K# N: X  B8 H8 v) A
                }
; e9 p* k  ?) d                if( exsound_select & 0x20 ) {4 _4 U2 p, o1 c9 [/ r9 Z7 t
                        fme7.Process( 3 );        // Envelope & Noise  g% E5 t0 X' C6 @9 I* E0 e2 z
                        output += fme7.Process( 0 )*vol[21];+ l+ q" ~7 `! x+ d4 G
                        output += fme7.Process( 1 )*vol[22];+ N  m) Q6 ~' ~4 u+ @) A3 P
                        output += fme7.Process( 2 )*vol[23];
  B; }5 s- ]# p0 ^# ^; G$ K                }6 k# Z) g. n2 U- [

( X) I1 l% ]5 t/ O# b; R                output >>= 8;
6 C3 R  V7 N# J, O
6 ~4 O2 Z( K% \. g8 C* B) x                if( nFilterType == 1 ) {: z- ~& l) Q. {/ [
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
. j  @* s) ?! T$ L: J                        output = (lowpass_filter[0]+output)/2;9 |0 c3 `1 E  d$ C: Z3 H' q
                        lowpass_filter[0] = output;
# I7 }, O  n. S- [, Z                } else if( nFilterType == 2 ) {# L4 W3 C- s! A/ w
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
. t' p( A/ l/ o: ~9 }: [% x" |                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! C( q! U1 c- U5 C3 W" ?6 R                        lowpass_filter[1] = lowpass_filter[0];
) N2 F  T2 y0 L. e" {6 K                        lowpass_filter[0] = output;! [$ M  j9 m* V# o7 [! K0 U# z: ?) l
                } else if( nFilterType == 3 ) {8 c5 [. A/ f. z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
( ^. |) C. w$ `% [" C! _- R1 Q                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;" K* j' b) @- f. f
                        lowpass_filter[2] = lowpass_filter[1];  `$ [# D; _" F
                        lowpass_filter[1] = lowpass_filter[0];
4 r( R9 {! |: j' i; ^) b                        lowpass_filter[0] = output;; x! a: Z2 I+ P: Q1 M9 Q8 n
                } else if( nFilterType == 4 ) {
, a7 b3 _) I. r% Q. w                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)6 C+ Z" P5 b# I6 P) H
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 L2 {9 D% e) T6 v, ?
                        lowpass_filter[1] = lowpass_filter[0];) D/ l' }; E- b: ?& g
                        lowpass_filter[0] = output;( }+ }! m( `" y- }: v* X# d
                }6 E7 _5 t: g, l/ v

$ L8 H  j1 F- e/ q#if        0
" d/ j3 Q% `. d4 T$ Y                // DC惉暘偺僇僢僩
- Z$ I+ ?7 t9 K, y1 q3 o                {6 @3 l: f: Z' i& w, g6 Y. S
                static double ave = 0.0, max=0.0, min=0.0;
' i7 t( a4 r0 x! M                double delta;. m) |) E; Z4 M# a' }
                delta = (max-min)/32768.0;
% y0 j7 t" d3 p  @' r2 Q                max -= delta;1 J- E# E! O! ]7 F! ^" p0 Q
                min += delta;
9 k1 ?) u1 c, ~  n- r                if( output > max ) max = output;
+ g! G# k. G0 j9 }0 o                if( output < min ) min = output;
# W! y0 V9 r% w7 D$ K# Q                ave -= ave/1024.0;# S+ z8 {% c2 G+ u
                ave += (max+min)/2048.0;
$ m* s5 Q/ a% J9 L                output -= (INT)ave;0 d2 |) |+ Y# C$ m$ w9 f
                }5 [0 C& J, ^, X" ?1 q; ~
#endif
) c: M, B# x. c5 P& @#if        1! u' _& @+ ~2 X1 a" L: d5 H
                // DC惉暘偺僇僢僩(HPF TEST)
1 Q1 u- z6 Z6 J$ f% }7 t: i, E  M                {
: ~7 h  p  \  l) n//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);
# p" |, ~- ~0 {# N. z( P: N                static        double        cutofftemp = (2.0*3.141592653579*40.0);
7 @% i) x" F6 R( W7 e                double        cutoff = cutofftemp/(double)Config.sound.nRate;: Y+ g5 E$ K5 E# {0 E
                static        double        tmp = 0.0;/ y  o7 T$ T  q7 M
                double        in, out;7 I4 B( {& ]$ i* ~
1 }8 L. N( S* k" J4 Z
                in = (double)output;
! z# m. _' b. A: S" \                out = (in - tmp);% ~/ y& p; d7 |8 j
                tmp = tmp + cutoff * out;
2 \2 R9 w# O* N# o: h: o/ \2 e' @; W! R0 ^( P6 g
                output = (INT)out;
  w. b- @- X7 t  L4 v8 t# S$ Z- _                }, G4 W9 p" I- l; ?. w/ ^
#endif
0 F0 B, Q- i: h% z, b" q#if        0
: V* k1 X! q( q' h                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST); _% I4 T! Y4 I! z( a
                {3 K' g/ ?9 X+ V6 Y% v4 h" U7 F. t
                INT        diff = abs(output-last_data);
$ N& ]9 V9 p# Z/ J+ E5 ]+ e                if( diff > 0x4000 ) {
$ u  F+ ^3 P6 Q                        output /= 4;, `+ t/ t. W, M! a4 X
                } else # Z& d9 \% `7 c  K) U6 {5 x
                if( diff > 0x3000 ) {( W* R& s9 a( N, u$ k' {
                        output /= 3;  k  v' g# m4 w0 I, o9 m
                } else
# @- R# _9 Q! q1 d  x9 D( {6 P                if( diff > 0x2000 ) {, Z0 c$ f$ s' R$ \4 [$ J2 n0 Y
                        output /= 2;; g. Z. k, H$ z8 c5 T. A) p
                }9 w9 p' z7 F+ w& F( ?
                last_data = output;) j# y) \# C4 ]* R. a
                }# q' c2 g8 I  b( X
#endif
, f$ _: t$ c) g% p) K- S+ ]2 e! X                // Limit7 ?! k! j7 O# p- ~: B" e
                if( output > 0x7FFF ) {
2 v" ?+ w4 [4 }9 S                        output = 0x7FFF;
( c# H' A! F* t" g- k. v% U                } else if( output < -0x8000 ) {  d: I/ D$ b, H, J* a
                        output = -0x8000;! K% G  X* h. X5 A
                }# a' d4 S* q6 a) I' k( f  R* N- J" ]( u
; U2 ?- B( a  m$ @! y* M
                if( nBits != 8 ) {! `& B* `. V8 j; W: P, }/ N& O
                        *(SHORT*)lpBuffer = (SHORT)output;
7 u; C6 Z1 X& X9 i                        lpBuffer += sizeof(SHORT);( _- ^, I) B5 ?$ S0 z
                } else {& h' I7 X/ Y3 q8 A. Z) ?1 F4 T
                        *lpBuffer++ = (output>>8)^0x80;
$ M8 \9 J1 N# E0 E1 o8 p& V& Y                }8 u' d' b% Q# L0 }3 ^- g+ o; l
6 _6 g3 a. v# F8 @( k3 k
                if( nCcount < 0x0100 )6 Y5 h* u  y  ~* j; |, I
                        pSoundBuf[nCcount++] = (SHORT)output;
; T9 n. I7 P+ z# R$ ?$ J* j, a# x, o  ^; E8 r. L& [
//                elapsedtime += cycle_rate;% E0 ~$ Z: i; c! T4 _& [9 l2 V
                elapsed_time += cycle_rate;2 u; R4 v% B$ {/ C) d, c
        }" n; f8 ~  ~7 p/ {; L+ O
- x2 n2 g; r# F5 j2 X
#if        1* d& Q/ q$ t- U
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
/ {" p& s: V2 `! z. H7 I9 u                elapsed_time = nes->cpu->GetTotalCycles();
& n0 Q# u) x8 u1 d% `. x        }- e+ ^! H0 l4 L( V# i% W
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {7 K: t& W% i$ Y& A! [7 d+ F6 y) H
                elapsed_time = nes->cpu->GetTotalCycles();
2 W5 |/ @/ v7 \% d        }( A2 S2 `* J% k/ Q4 U
#else
% C3 P2 e- l! c2 {6 x/ y" l        elapsed_time = nes->cpu->GetTotalCycles();/ ^: a9 O* u( {% ~1 U
#endif
3 r2 W1 K- T" A% X}
: J8 r5 ]2 ~) y4 i, S9 Q
) s; T2 X6 o" K6 z. }- s9 O# @// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)9 d1 l: G: n7 z& f5 I3 h, G9 M) A5 X
INT        APU::GetChannelFrequency( INT no )' s9 H9 }. i5 m8 R
{1 o4 n' t$ |/ \0 \
        if( !m_bMute[0] )8 @+ t; W. F$ g, r$ Q
                return        0;
* t% [/ e  B  C( T8 }$ E
, M6 j2 A/ F6 N6 Q7 u        // Internal
; o- g" e  J9 K0 z( w, w  s        if( no < 5 ) {; Z- K$ K+ b- P$ o* D$ @" g0 S
                return        m_bMute[no+1]?internal.GetFreq( no ):0;7 S3 N& X" {' ~7 i9 q1 M; k% w
        }
& h/ ?3 i7 x$ {/ H2 s: ^" ^        // VRC66 R9 P1 n" g! B7 @1 ]8 a; }
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {5 \3 X# y0 W# B6 R- w. U
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;4 `. r& u+ Y; n$ n
        }
  K: F2 T9 n; ~3 Q* c% C        // FDS" n9 q' g; F* ]1 `
        if( (exsound_select & 0x04) && no == 0x300 ) {. R; o; S/ z" _  ]4 r' a  F9 z, {
                return        m_bMute[6]?fds.GetFreq( 0 ):0;- X  v+ a- q1 H& g" m
        }, U7 o2 f# Y8 W) Q5 N: x8 k( L
        // MMC54 k4 X( k; q4 ]3 M0 F! [5 \& S$ K
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
: t4 c( x/ S; @$ e# [                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;) q7 ]$ V% x( L
        }
6 X5 L. Z5 w; H7 ~& A        // N106+ z, H: c7 N, w
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {- ^( B5 I2 u- s* {& d
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;; T7 d3 E5 G0 i0 E+ W& e
        }
+ T* o5 p3 O/ `$ X9 D9 C% @2 S        // FME7
4 x% q' g" E; y! ~2 r. k8 X- g        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {9 R/ S8 T% ~, |2 U2 L6 {
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;) h, g1 M/ s7 y3 j# L, s
        }
0 S: r& U- b7 `0 L/ Z- y        // VRC7: n( \) O8 r' F6 x
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {) Q, |5 S# w8 g5 {
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
; @, w0 w% x7 k. g+ A9 G/ v2 C/ r        }" @. t- E  I' \. O
        return        0;
2 \. _2 X3 c+ `5 x/ Q. j}) R+ ^5 v0 Q6 H0 w

( i* ]8 w# R/ {. @& J// State Save/Load
7 X: x( u* u* @void        APU::SaveState( LPBYTE p )/ s2 f% E( `6 r8 f. m3 ?; k
{
! V3 w& ~  f* [* x7 I* _1 U#ifdef        _DEBUG1 M8 L/ l- l9 E; L$ \, W  h' p
LPBYTE        pold = p;
6 o9 \0 e& I6 z# N  M" ]#endif
: y2 J6 a0 l$ K% u8 Y# m2 F- Y1 R  J7 X* A0 H
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞$ a! @5 z0 N: g$ g: k6 O; Y' M$ Z
        QueueFlush();3 z, E) k6 W7 e7 R0 Y( \
( a. J5 q( C7 _2 F4 l9 l7 a" a( E
        internal.SaveState( p );
: s. R8 M2 G' s" @: y% K        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding! C2 c0 Y& v+ v. r6 h

9 m1 ?; Y$ o# I7 E  r+ S        // VRC6
- p3 P3 G2 T% F8 l        if( exsound_select & 0x01 ) {2 p) Z+ ?$ L: c: z  F
                vrc6.SaveState( p );1 W/ ]$ [: T/ r. j
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding8 q/ O7 ~8 ^( b! b, ^8 m" f
        }
/ J% R( M+ E) g# J! I. a        // VRC7 (not support)( v+ @, a$ R: e0 _* J
        if( exsound_select & 0x02 ) {& [# V+ @* D! h0 O# `
                vrc7.SaveState( p );
" x7 h+ x) d: M5 Z                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding( S. ]& [6 h# R3 j* i2 H3 ^  {
        }+ A9 C. i9 I; B2 d* [- S
        // FDS- Z3 H. ^: z# G* }+ v9 C$ k) ]
        if( exsound_select & 0x04 ) {- L  J  B* @; d5 r! \
                fds.SaveState( p );3 |' B9 `  w8 \0 P. P7 H& |
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 ?& V0 R6 L& u- x        }
# T/ Y9 d" K' F" @4 m$ w; I, a' W        // MMC5
3 Y8 K" L/ h1 T) B" y; P        if( exsound_select & 0x08 ) {
. s) ]# ^) q% h5 A                mmc5.SaveState( p );$ Q! X7 L: b- a: r3 R9 [
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' c7 ^" |, u) y5 u* h7 V$ ~
        }
9 j5 ], i- P, \0 J, m8 x$ z        // N106
! S- B/ y% n  y7 w$ J% e9 z        if( exsound_select & 0x10 ) {( v  O3 c& i0 q0 U! M) `: m5 w' H0 J
                n106.SaveState( p );! n  e, ?$ Q' w, M! L# V; k' c
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; q4 p% t4 z" t. Q; I        }
3 c$ O3 t9 m5 Z* \# c0 J, ]: m' y( |        // FME7
5 h$ K9 U1 f. O8 r/ I7 T        if( exsound_select & 0x20 ) {. W) R$ c  w: W* Z) z
                fme7.SaveState( p );5 m6 g- L  N, E- D+ v
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
6 ]) r' H) E0 S9 L6 @+ K2 @& F        }
9 J/ Z" `$ F1 q* }( w& ]2 f, ?
8 S; V1 l# }  w3 J9 w$ x#ifdef        _DEBUG
: v- H$ `; t) e6 O4 n3 qDEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
5 G1 v* O  u) R8 V+ c5 e2 K#endif
- _% q1 i, c9 p, ^: d% @}9 F3 {: ?7 D7 f) a0 O' c

& x/ W; ]! V% r8 zvoid        APU::LoadState( LPBYTE p ). I9 h9 D4 v  u* X, v
{% `0 R6 S1 l# ~8 ~2 t
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
  W8 L. p: `8 c' V1 s& O! b2 ~        QueueClear();3 y& S/ u  U6 N4 U# c( x! O

) g) h; d% T2 a# h        internal.LoadState( p );
- u1 x% ^/ B) b8 M, m. u        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
4 }# G7 j0 J9 R+ t3 r$ h$ t- X$ Q. Y, D
        // VRC6% t$ O& z$ k8 B( L+ a  a; m
        if( exsound_select & 0x01 ) {7 s2 D8 B2 D0 i# J& h0 e1 L/ M
                vrc6.LoadState( p );
  Y( Q8 h% _. R6 V& H                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding  {6 |$ e# _! C) M  f
        }
( @9 H8 r) h( ?% z7 B- z8 g) P        // VRC7 (not support)' ^- H7 g* g: ~
        if( exsound_select & 0x02 ) {
: I5 V( u  `# T                vrc7.LoadState( p );3 P6 b" s" r& {& c
                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding9 L6 w* Y$ y2 W  S
        }
* C  P3 M' O: j4 o2 g7 ^4 N2 [        // FDS$ |2 V4 C1 P& g; [- R1 P. I0 k! b
        if( exsound_select & 0x04 ) {: Z/ h, `; k2 ~( a" N. w& W
                fds.LoadState( p );
" ~9 d# W/ M( h                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding( F$ r) x2 K2 J3 M
        }
4 v/ a2 k* N* ~4 q! G1 N        // MMC5
  `, @" j% S  F+ J        if( exsound_select & 0x08 ) {! d; g' a! x2 Z1 |7 ^
                mmc5.LoadState( p );4 f" Q8 R# I# T5 b* Q; p
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding) b7 c, P4 x$ ~* r8 R- C$ a
        }
& \5 v( a7 l$ Z+ ?        // N106. _8 ~' _: S8 y6 A
        if( exsound_select & 0x10 ) {' w) P2 C# k) B. [4 h$ g
                n106.LoadState( p );5 f1 v0 M( }- {+ Z5 y7 _
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
1 g3 r( |. B- q# T( r2 m0 A8 a        }
6 W# Z1 @: z% N  U$ A9 H9 T        // FME7
( g1 a9 E9 L% m. p/ Z; |        if( exsound_select & 0x20 ) {
( [% x* k. x9 B8 X4 K5 I0 `                fme7.LoadState( p );* e- L& o: f6 e3 a: ]4 h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
: L# ]; N( r' V( v* O9 J        }
" T" x% O' U' G* b2 ]% m}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 + x9 y; A  D( Y( w2 q8 D* K
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。8 H0 h0 o2 @; e5 X* o( ]4 o; @
感激不尽~~
( Y' H, r$ }% t* o( N( Y8 _
恩 我對模擬器不是很有研究,3 }2 L/ l- t  F
雖然要了解源碼內容,可能不是很困難,
- Y$ Y6 f( G3 n( S不過還是要花時間,個人目前蠻忙碌的。
2 z! C0 ~1 W4 N7 g4 }
1 j/ H# y- y2 }8 ^# ?. m" S給你一個朋友的MSN,你可以跟他討論看看,
+ L2 o# C9 i! N; l! h他本身是程式設計師,也對FC模擬器很有興趣。' g  Q6 N, q( f- `& d7 P4 A7 _% v
: E0 t3 l$ w! [# ~; w) b
MSN我就PM到你的信箱了。
- ]0 W# r) g# W- F
) B  d- w9 H/ u) F) `希望你能有所得。

该用户从未签到

 楼主| 发表于 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 n3 J2 |! Q! ~/ R7 d
呵…… 谢过团长大人~~

- N3 c# _6 l3 c* N0 j7 p1 A# Q/ U6 k3 K1 b( ]2 B% b, r
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 7 ~9 o8 B- I' n. I
团长的朋友都是神,那团长就是神的boss。
# @0 x8 Y. W& |- J5 q
哈 不敢當,我只是個平凡人,( D3 S* A& D" ]
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙( X+ e0 q9 ~2 R# K# x
ZYH9 }& V& f, J9 V' E7 T7 @
QQ:414734306
& K! g( ]! v" D9 q2 v. a9 ~" QMail:zyh-01@126.com
) N/ i$ w& P5 c, t! c  N% ]7 R. v3 H, u- G8 f2 W' h" l
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 2 D* \9 a3 E( p
再次对团长大人和悠悠哥的无私帮助表示感谢~~
$ T- `9 v/ B, O1 Q0 _
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-23 23:40 , Processed in 1.081054 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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