EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
9 C/ x1 U. M' s- m9 \$ ~4 E" y楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
! S/ s& G: [' b9 `+ v/ a这里有相应的模拟器源码,就当送给大侠了~~8 [" E* B; U* S& b. K
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 9 P0 A) @* ~, ~2 e
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
5 x+ F/ z: M+ w0 g: e/ M楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 C% |) i1 V% `' h
这里有相应的模拟器源码,就当送给大侠 ...
2 Y* N& T. S4 @" O! F. H
聲音部分(Audoi Process Unit = APU):
! I7 E  D$ o7 L3 o+ z.\NES\APU.cpp
( _( q) @% ~8 e+ L.\NES\APU.h
" t/ O  m  A$ R# s  o. c  b$ s/ e$ |# s- q; z1 M

8 {  Q- U# ]  r0 I: M+ c影像處理部份(Picture Processing Unit = PPU):9 `* F! d- K+ w, r  e
.\NES\PPU.cpp
! G: \) F$ ]$ Z! M+ _+ d% m  K.\NES\PPU.h
/ Z- u# q1 A" p& T
. ?0 J2 t8 P1 I7 s9 Y如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
+ t/ h1 U+ e* ^* Z4 G6 X3 ^8 |% f( {(由于很多专用术语和算法机理都不明白,所以看不大懂……)
' X3 @, j/ V& [5 c; D* J2 t9 R/ Q//////////////////////////////////////////////////////////////////////////" B& R) x" A/ X3 b1 P
//                                                                      //
* e2 f  O) M, P% M: _3 Z//      NES APU core                                                    //
( i$ x0 @6 z* S% T7 H9 G//                                                           Norix      //6 P5 k- M0 f! x- e
//                                               written     2002/06/27 //! c# X3 ]% d% u* \! f2 O; }( M
//                                               last modify ----/--/-- //
; o0 w5 ?- c5 i% r8 R//////////////////////////////////////////////////////////////////////////
" l5 X/ g* M# X; i7 a, W& U#include "DebugOut.h"+ R! B. I: h/ {2 P1 A
#include "App.h"
) _2 `# o: T* ^$ G7 s#include "Config.h"
0 r. G7 E% G0 r+ ^" k, {* t( l( l/ B& S5 ^$ s
#include "nes.h". o8 q$ J1 Z0 c: r. T
#include "mmu.h"1 q3 w. D; Y- E
#include "cpu.h"8 |$ `' T% G/ B! _
#include "ppu.h"/ ]2 y8 w, m1 P7 ?  C
#include "rom.h"
5 H& T2 H- _1 f7 k#include "apu.h") ?* w; d# w, `- G5 i2 c

; d7 Q  W" A) j3 v( X1 w// Volume adjust5 P5 C( |! ^( l" A
// Internal sounds
# N) F( @+ d5 X( o#define        RECTANGLE_VOL        (0x0F0)
. n9 P- B- A! j2 m1 K4 P#define        TRIANGLE_VOL        (0x130): K' a- h+ \! L% p/ m6 k
#define        NOISE_VOL        (0x0C0)
  _! n9 G% Y: w- K0 U#define        DPCM_VOL        (0x0F0)
2 i8 C# T* r' p* D( k7 s// Extra sounds
4 L) N. u# v1 E1 u#define        VRC6_VOL        (0x0F0)
: _. O7 z9 N+ m" B* d9 @#define        VRC7_VOL        (0x130)
5 i3 y! v2 j9 p2 ^) `4 C5 A$ U: Q#define        FDS_VOL                (0x0F0)
+ e" Q. ]/ i$ U+ J#define        MMC5_VOL        (0x0F0)
5 c; u- Z# n0 O* Z9 g! L#define        N106_VOL        (0x088)
; K. c8 T, C1 W) w7 t#define        FME7_VOL        (0x130)
3 k4 U# k. X" r. |" M& N. U, ~( l
APU::APU( NES* parent )
  N1 j, }; k& }- k5 A' g9 D{3 u5 I+ K8 O8 `
        exsound_select = 0;
  r; R2 @; ^$ W% ?/ ^5 J. k- u- o! l, S3 C) d7 t  N
        nes = parent;
) R3 S% z" L  R$ X  k5 s/ [$ t5 \& _        internal.SetParent( parent );8 J% m: x6 I* p* V7 A5 h1 J
5 {  n7 M( V* g4 g
        last_data = last_diff = 0;, U8 b; ~  F: N! l

+ Q1 G: F4 I0 S: v5 v        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );7 E, Y8 B& W1 f3 c" \

( Y$ A& `0 [3 `  d        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );
$ q4 l0 N" i9 O; H: D3 c' U        ZEROMEMORY( &queue, sizeof(queue) );
2 W4 O9 q* a6 U) r; N        ZEROMEMORY( &exqueue, sizeof(exqueue) );
3 u" j9 C0 @0 w) x# P1 S3 X) z1 p" J& a0 J( U8 }
        for( INT i = 0; i < 16; i++ ) {8 `, U( F6 `& x, b8 o
                m_bMute = TRUE;
. S  G, R* c! `/ g        }, T  v- _6 h5 g, _: k  \6 q
}
1 l( F0 N* E9 S, }$ m
& R& P$ C! j; R; }# m* q( K& HAPU::~APU()" R4 H  D3 `& y# Z' T3 W
{
% D- O7 E$ v- @4 `1 E}  L9 Q1 v% q" q0 T

8 G1 z" |6 V0 ]4 j: E: vvoid        APU::SetQueue( INT writetime, WORD addr, BYTE data )" i2 N( t6 p2 q& I
{
% ?* R, c/ Q: Q/ o2 @  N        queue.data[queue.wrptr].time = writetime;
& y( M% A. O1 I) X        queue.data[queue.wrptr].addr = addr;( B+ Z5 w" q5 [& F7 Z
        queue.data[queue.wrptr].data = data;
- K% L7 f/ k6 B" G' x        queue.wrptr++;- K; s- m" M2 `; E) o' Y$ G, K: t
        queue.wrptr&=QUEUE_LENGTH-1;! C  O# O9 ~; H  N4 N1 s- G: }9 u
        if( queue.wrptr == queue.rdptr ) {3 B0 z7 O- _8 d, o1 N: K% c
                DEBUGOUT( "queue overflow.\n" );/ i$ u8 b4 s" S
        }
0 D/ k* V! ^' T# K8 F' J# W}) u1 U1 A2 I' |! g: o

4 Z3 O7 s# w% N3 O8 s( O. f* Q- t( WBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )5 |5 r4 a# W: `
{, ~( K& I# p/ B: C7 q5 z* e
        if( queue.wrptr == queue.rdptr ) {8 B) _- v2 c2 y1 j
                return        FALSE;* E: s) l- I$ k3 K
        }0 e# F0 b' d! U7 S' Q9 h
        if( queue.data[queue.rdptr].time <= writetime ) {
, K1 w1 @8 l- N* v7 `) ?8 V                ret = queue.data[queue.rdptr];
9 @( U. O. m$ C3 b                queue.rdptr++;6 a) l7 a8 [, Q3 v3 b4 }
                queue.rdptr&=QUEUE_LENGTH-1;8 ~# l1 k6 X- i
                return        TRUE;& H- j3 C0 I7 @1 W, I; M' Y( E
        }1 Q; M* D% j5 O+ s3 s
        return        FALSE;
6 i2 H- _( |% u+ K" y/ e/ d}2 h5 G" y0 o& Q# F: \
- a4 @. ~2 A+ K, o7 y
void        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
  E8 h8 D5 P# x9 q{
8 c6 \: f- [; G, x: n        exqueue.data[exqueue.wrptr].time = writetime;+ Y% f/ {+ h9 D0 q, H
        exqueue.data[exqueue.wrptr].addr = addr;" z: Q& M9 v, a- H& X
        exqueue.data[exqueue.wrptr].data = data;
: M! h. K8 g+ n7 }) p5 J8 ~0 R        exqueue.wrptr++;# s  l0 R& Y; p% I; s6 [+ `8 x
        exqueue.wrptr&=QUEUE_LENGTH-1;
; R# Y" v8 e& b! i        if( exqueue.wrptr == exqueue.rdptr ) {
* F. J$ \) g- c) e% N5 B8 `) n                DEBUGOUT( "exqueue overflow.\n" );( D. r9 A1 E8 S- `
        }4 ^; b! S8 v8 S9 [. p
}
; w# n4 W  |. R; _, e+ T$ P
1 A' U5 m  W1 E7 F) v$ w9 tBOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
7 V, k# U3 e/ D5 R{' J/ g+ H# i$ W. I. Z' r* |& t
        if( exqueue.wrptr == exqueue.rdptr ) {
7 Z) q' q6 d! D6 p, j& a- ?- [" C* M8 X                return        FALSE;: ?& ?  Q4 ?; q  A8 _5 M0 e
        }, a7 o6 Q/ j* O
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
8 k! |* u# V& g( ]# _* r                ret = exqueue.data[exqueue.rdptr];
9 A$ G# l6 \: v# _5 h6 }' X) b                exqueue.rdptr++;
' R; X3 ~, ^: z$ I) l$ @  a1 f                exqueue.rdptr&=QUEUE_LENGTH-1;
$ y2 G- z" f1 f6 K) d4 c, f                return        TRUE;
  T& U% J. c7 e3 l        }* E/ v8 ~( L% _" x: V
        return        FALSE;; G/ M4 u6 u: y. W
}
# C0 d6 }# u/ W8 i) {, }+ ]. z8 b! |: H
9 D* Z. r3 n) b  k! x. Jvoid        APU::QueueClear()# A9 A0 d9 i& B/ l0 V% q
{
" i  @" B' B- [# C$ R  {9 ~        ZEROMEMORY( &queue, sizeof(queue) );! C9 l" H/ o4 y) N. X# Q! C, m
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
: F4 p. w: Y' t5 j% c}: Y+ O6 T; R- T/ t7 K, i& T( e

/ J  T+ d& z- B! qvoid        APU::QueueFlush()) {' s/ l/ b5 U! r8 k9 ]4 H  k2 Q
{# D8 N: ?& c% O% B# R, p8 \( B$ k
        while( queue.wrptr != queue.rdptr ) {
! J6 V- ~1 O$ e: a                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
2 ?+ g6 l5 v7 c; ]; O0 y$ k                queue.rdptr++;
) ^6 E4 d% e" ?: Z                queue.rdptr&=QUEUE_LENGTH-1;4 H: p) f% Y% w( p5 w0 a5 e
        }7 M8 g. \4 \% p( N
' V4 I0 W' D& f" z
        while( exqueue.wrptr != exqueue.rdptr ) {9 x" M) ]7 q7 {. h% I6 O5 v
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );' y! N% @5 E/ J
                exqueue.rdptr++;
# D' j$ t% |) D2 A0 U; i6 k) o                exqueue.rdptr&=QUEUE_LENGTH-1;
* U0 x" c2 }# g- ^# m  C        }! F5 r# w. d; ~
}
' F, k7 h% V% i( Q! K# d# [" E0 ^8 x! K: f9 D9 D+ s
void        APU::SoundSetup()  A2 X* ~, |4 T2 |. N$ d- R, B  D
{
! L2 c  f: r- `8 O* }) Z  z3 f        FLOAT        fClock = nes->nescfg->CpuClock;
: n% x0 u4 q* f" Y) c4 u        INT        nRate = (INT)Config.sound.nRate;2 Y. d% q  v) v# b( [5 t- N& n
        internal.Setup( fClock, nRate );
" g5 u4 }8 j: `1 N        vrc6.Setup( fClock, nRate );
3 `( y7 G8 W- e* R$ @        vrc7.Setup( fClock, nRate );
; i' ]  g' ?* m6 z( E        mmc5.Setup( fClock, nRate );
0 r0 O+ p; x# u% t1 a        fds.Setup ( fClock, nRate );
  g0 @$ I  Z( [5 _7 b        n106.Setup( fClock, nRate );
9 g) k; H  Q) ~( {* _0 K% K2 ^        fme7.Setup( fClock, nRate );
2 t- d5 D7 T, X2 A}
. [- r* R( v; ~. I  O
7 Y' ?4 A* M+ e* R* h0 }7 V) ?void        APU::Reset()1 ?; m# X" ~8 Y$ y; C
{
2 r( l3 m& W& M( H- c$ _        ZEROMEMORY( &queue, sizeof(queue) );5 i# n2 s/ x9 T# G
        ZEROMEMORY( &exqueue, sizeof(exqueue) );3 A7 T$ A  e1 O4 |
* i% g: p8 D! B+ O
        elapsed_time = 0;3 h* T1 H, B& y! z2 u
) Z  _1 g- L! c9 ?. R) b/ ?
        FLOAT        fClock = nes->nescfg->CpuClock;
& \" [4 s" Q) K; J) E        INT        nRate = (INT)Config.sound.nRate;
+ ]6 Z0 G/ C* O/ z& ^( _: O        internal.Reset( fClock, nRate );- c# M. X, q  j* W- e
        vrc6.Reset( fClock, nRate );# P* ?% |" w9 I3 }2 F  @6 Z% {2 P
        vrc7.Reset( fClock, nRate );$ l" |6 E2 Y, L) S2 s1 p7 h! W
        mmc5.Reset( fClock, nRate );
+ O# N0 C7 B; E; p8 u) A3 P        fds.Reset ( fClock, nRate );% h0 e! I. G5 x3 u" {
        n106.Reset( fClock, nRate );
4 c# o% I* v4 I. m        fme7.Reset( fClock, nRate );
& G" v, j( O7 y& w  T9 d9 o8 ^7 u: ?5 {0 f5 Q
        SoundSetup();0 X9 J, H- X7 p# W/ D1 q$ `
}- d7 |* V; f. o2 Y5 {$ z

; s1 n- I7 m  l$ I5 }void        APU::SelectExSound( BYTE data )
) s) [$ n/ {) s. U{
" w9 {3 R! Y' {9 a* c& ~& l- a) K        exsound_select = data;
6 S( o  D; S: r! }/ R}& S3 a; \3 e9 R1 q9 D; n% w$ \  h5 z

7 A. Y/ y4 E; Q( D  ~BYTE        APU::Read( WORD addr )
1 s3 H2 k5 _$ P  Z7 @! d  I{, `5 ~  T# ]% m% u; L4 z
        return        internal.SyncRead( addr );0 R9 o+ {4 \  ^# M& s
}  J! K9 C, }& J  v+ z

  M1 v# H2 e4 `. }5 ~void        APU::Write( WORD addr, BYTE data )5 n* a+ Y* i1 M- ?  v4 I* d4 P
{
  T& L  N0 _3 c  D; A4 T' t% W        // $4018偼VirtuaNES屌桳億乕僩) b, e4 T/ ~: g" m0 F1 E( q
        if( addr >= 0x4000 && addr <= 0x401F ) {
. z$ [5 a5 a: D+ ?$ B2 l7 x                internal.SyncWrite( addr, data );
& @% n* A6 T3 D  M& U                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
/ J- h% i; _0 I        }
# b% u8 |& h0 n, ]# a}
# Y# }$ S1 d  v
6 ?: Z  n" D: f3 L: W" FBYTE        APU::ExRead( WORD addr )2 `' ~8 H* ]* {
{
- W0 t0 |* o% {% o: p( X/ d+ pBYTE        data = 0;
7 `9 X" V4 V* i8 Z0 q3 F; u( ^
! o  q6 b. }, u& s8 Q        if( exsound_select & 0x10 ) {: ~' d( F2 K. ?& c( P" O) L0 k
                if( addr == 0x4800 ) {
  l9 U9 z4 M2 s. B* J                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
1 H! Y* [( V/ _) \8 }! T                }7 p# [7 ^+ x& M8 B! n2 [9 C' ^
        }
& v+ a' }& k  @4 `% G' @        if( exsound_select & 0x04 ) {
. L6 U) o" p! [! G. D( D, Q$ ?                if( addr >= 0x4040 && addr < 0x4100 ) {! k0 u8 Q+ M+ B  v; g0 Y
                        data = fds.SyncRead( addr );4 q( X5 t  T$ B3 F
                }
7 W6 N; w% p6 o        }2 M( N) p) m; n' W. z/ S( R- E
        if( exsound_select & 0x08 ) {1 y' b, S( I( j# Y: A
                if( addr >= 0x5000 && addr <= 0x5015 ) {' @0 b5 M- m9 b  K/ c# W6 R; m
                        data = mmc5.SyncRead( addr );; W4 `( j5 M0 E, g6 h
                }
8 G9 S9 A. B0 K" M* K$ \+ T3 y        }
& x6 y& a) ]+ h& c: I. R- o1 T4 @! a$ i/ O
        return        data;0 I+ R% _+ S8 `  a9 g) A3 X7 p4 }
}9 Y! w0 P8 k" y5 s

) V# s) u3 r7 c) o& q2 Q' Lvoid        APU::ExWrite( WORD addr, BYTE data )
1 c3 w6 c2 b1 m8 ~3 g{
) I: w) e; D  C* {; _' f        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );+ o5 G# X/ Z; \  K3 I) V/ w$ o: F
! I# d# ]8 R4 p& s$ v( V# R
        if( exsound_select & 0x04 ) {
! @6 E- ?6 R$ g8 C1 U$ C/ z                if( addr >= 0x4040 && addr < 0x4100 ) {
" |2 y$ O5 D8 |3 X; s+ i6 {                        fds.SyncWrite( addr, data );2 k; [- l+ `1 R7 M- v& l
                }& G7 ~+ ?7 R& Q, ]) ^: Z+ [
        }
; ?0 t5 {% F0 W: T- N0 i1 |* p* W4 j0 R2 o
        if( exsound_select & 0x08 ) {1 z3 t6 G3 j6 F
                if( addr >= 0x5000 && addr <= 0x5015 ) {5 `- f6 G+ g3 i" G
                        mmc5.SyncWrite( addr, data );* M: o3 G5 p% }; p+ c
                }
/ \, B; G7 V5 f7 Q        }: a6 ]+ P! D" B# C* n, ]2 i  K
}
6 s4 m" d1 B$ U* P
7 }, V! x6 X0 c$ `- M# K0 jvoid        APU::Sync()
9 b; t7 k8 I- s9 f# h/ ?% e/ y# R{' i# a" D$ y& m, g2 N4 \7 D
}
  l6 X2 A* M9 l4 a" j4 i/ ~* v. s' ~. W& `
void        APU::SyncDPCM( INT cycles )/ n! I# l# a: n  j0 @, J/ n
{$ f) F. {2 B! X# v( y% r  @
        internal.Sync( cycles );) _0 P* |) {4 N' @! r! O
; k" w0 U) g) X' W
        if( exsound_select & 0x04 ) {
( n  @( Y" K; I                fds.Sync( cycles );7 d8 W1 g  ^/ W9 e& W2 M
        }
; }5 `9 b; e8 r  y3 c8 C        if( exsound_select & 0x08 ) {" H$ }# X! z- @( X
                mmc5.Sync( cycles );
8 z) a9 Q5 ?" y0 O: c: d        }
9 d% H) U- E/ G# P7 G}& L$ B/ m: `2 C1 `- c

- s+ n0 Z2 O1 H4 S  N. Y6 e% uvoid        APU::WriteProcess( WORD addr, BYTE data )! v$ m9 ^+ M' z0 N1 F1 A6 A
{! g& u4 h  _5 V6 {, {; h2 }
        // $4018偼VirtuaNES屌桳億乕僩
0 \/ H0 j- b) c+ ?  S0 I* F& y        if( addr >= 0x4000 && addr <= 0x401F ) {* B0 t2 s6 t2 K. S0 G& }- T- Q
                internal.Write( addr, data );8 _9 F/ Q' W# m
        }
; N# u2 D5 R0 c8 o0 H" O# l}1 h5 G2 k2 C* ^; {# \

" O( l2 }; }# F3 f5 cvoid        APU::WriteExProcess( WORD addr, BYTE data ); I* F+ _* Y) Y5 f
{
' T, h$ C( w$ H. G        if( exsound_select & 0x01 ) {
) Z# u2 g& Y- g4 m, N                vrc6.Write( addr, data );" d6 g' v, w4 v6 E  z! c
        }
9 C! Y9 S/ B( L        if( exsound_select & 0x02 ) {
$ x+ u6 s7 B7 l% x: X- X0 ~                vrc7.Write( addr, data );- G4 {+ x1 }, z. b6 B# ?* z
        }7 B; a( y3 K+ L4 G
        if( exsound_select & 0x04 ) {4 h) q9 R7 Y7 \# }0 g- a6 l$ Y
                fds.Write( addr, data );7 }7 \6 e9 l# c% t8 G
        }
3 p/ h2 `* q; k5 r5 e# l, F        if( exsound_select & 0x08 ) {
, C/ _- @. f  \& O8 ^( N( B                mmc5.Write( addr, data );) _" B5 |: ]$ A6 U8 l
        }3 s0 Y( f, N% R3 n) H: b6 n* S
        if( exsound_select & 0x10 ) {
1 p' J2 [" A  l- I                if( addr == 0x0000 ) {! {9 Z* a  S7 X' _
                        BYTE        dummy = n106.Read( addr );
- M- t2 m% B6 D$ s( `1 J( C; _3 X                } else {; N" F/ y+ e2 O2 I* q
                        n106.Write( addr, data );
% J: @1 r7 X* h1 I                }) O; q0 }- ]8 h3 e
        }; J9 v" `8 Z8 Z( a5 M+ f
        if( exsound_select & 0x20 ) {
  P* E$ J8 }* _5 A+ \                fme7.Write( addr, data );
! d) Q3 [1 N2 Z- J/ L        }% y! l$ f3 R4 f& e; P
}: O1 B' F& Z* n5 G4 j7 P
+ c% W4 a" Q9 [, h
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )) X/ V* }( v& E2 ]
{/ o* W) ^  {& z" E4 j; \* }
INT        nBits = Config.sound.nBits;
! J# Z0 m! s' G8 ]DWORD        dwLength = dwSize / (nBits/8);
# I* @! @! I3 k5 P& NINT        output;2 ~& \6 G9 B- w1 Z8 f
QUEUEDATA q;( q/ o" u! D/ \( ~- l5 J
DWORD        writetime;
+ O8 B8 g3 T; ~6 G* H3 Y0 A6 ?6 {& T7 R2 z4 T
LPSHORT        pSoundBuf = m_SoundBuffer;
% x- q1 J- l# ?  o  p! zINT        nCcount = 0;/ u6 m6 ~0 a/ Q6 ]0 l  M

/ V' F; g8 j' {: h5 G. TINT        nFilterType = Config.sound.nFilterType;4 f2 c. ~3 A8 J" i9 _0 }3 ]" S
6 K8 x. l: N* T
        if( !Config.sound.bEnable ) {% i4 H5 }: b$ m0 H& t
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );9 E3 a$ ^/ Z) l/ X7 z
                return;8 o4 E6 f2 X  v( x9 [/ v3 h& f
        }
" b/ g$ n. e6 [6 _+ Z- z( r
# s* H: Z# F. C6 w) ?* t        // Volume setup' i; S. w# \  I- Q$ t& I
        //  0:Master% @# m  r& H: X! \" T. ]
        //  1:Rectangle 1. g, ~' ~# u& L8 B; T
        //  2:Rectangle 26 E3 j, v, q# q8 [. O/ [/ s, L7 F) P9 O+ p
        //  3:Triangle- R: {' R( r9 M# Y8 \# ~
        //  4:Noise& R- z" O% a( _7 T; C8 i
        //  5:DPCM
/ ?' _& B5 Z! l' r7 s% r        //  6:VRC64 k, d0 ~9 b! Z8 f9 T0 A
        //  7:VRC7/ r  m- Y9 F7 R
        //  8:FDS
+ R/ i% z- B0 S        //  9:MMC5
" a, d$ F. D2 F# |  {' T        // 10:N106
- a( v" c: n* K# R        // 11:FME7. X) ?. N) Z8 d1 g. I* I+ e
        INT        vol[24];
# M) N( i* L/ r6 h, q& ~) i# n9 i        BOOL*        bMute = m_bMute;
& z5 g. s. ]4 V& r        SHORT*        nVolume = Config.sound.nVolume;, Y9 u  A7 G7 ^
! U5 D. G- H3 w& {; O; J& X
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
- r# E' J) L" t4 G8 Y3 t7 P1 ^+ W) b- K# w
        // Internal; m3 L: A; @! c. x. D& J$ g+ S6 r
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;& _, G7 p$ A% I4 j9 e
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
7 u5 y( D% v# L        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;6 n' m. J3 Q8 d! I6 z# B4 ~
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;
7 J, S' \( }7 _  u        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;/ X) X( Z/ y- c6 c% Y: ]) x5 v

% I2 d' `$ g6 _5 {3 F        // VRC6
2 D& j. I* [+ Q. Q, i        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 n4 j4 k3 r# z! o4 M        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
% g) ^# J& a. J$ u        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;$ T  a* y! C8 o) O" t& a! T, g
1 k6 z& s4 [2 D' G7 X
        // VRC7! H$ v7 b4 {2 x& D" c( f7 X
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;4 k2 c+ l  u, H. J9 M+ e( Z3 {  ]0 p
+ f4 x+ v# s' f# |7 A
        // FDS
& ?! G0 k7 k3 y$ r9 w% n; ?1 a        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;
# C. D" W3 H! U+ }8 V( ~' [& n: J, M$ ?8 S8 C% T: i) v
        // MMC5- q( F; {; N6 s" a2 A3 h3 J  V- Q
        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
7 v9 }$ y% o6 g2 I/ ]: d        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
% q/ D8 c. [+ ]  n5 Z        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
2 @* I8 u7 ?6 x* k8 p! ]2 u/ o6 W1 X3 G$ f8 Q9 M1 d- _* ^! Q
        // N106
$ Q/ F1 B1 W( |2 S        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
' [7 t# J! c6 k        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;3 z2 i* m; P2 d- J! u+ I) O
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! H6 t* f- T" Y+ O; A4 h1 e
        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 }$ v. ^! ]+ N# @' D) F        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
# g- [- N8 B+ F8 L  L: L        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  {/ Q1 V: Y/ h9 C5 ~+ @! h
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;& {* {6 ]3 t7 b  Q
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;! D, W% L: m6 e% F

" y/ A$ Z+ J8 N$ f1 Z        // FME7
: H; {+ q9 _6 H& P        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;7 |, l2 ~7 D9 @$ r' S: M( A
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;- b3 ~. t9 I) e/ Q  U8 a  A* W
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;# A8 J. j  Q/ E( j- G! {9 g

# P  g. e2 [# \0 g3 N) X//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
  _& O* x) K! b" [. j  J        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;! t' @' m1 ~4 ~+ {# n! |
8 a# f3 v$ V; U. [0 ?( A
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟
% h6 a* ]: w. n        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
+ e7 R" s+ \6 I                QueueFlush();$ m+ b  U* r! @2 v
        }
' S' f9 g2 J' e4 a2 U8 ]0 P
1 g# Y5 ^5 r! a9 D' d* c        while( dwLength-- ) {
' d' J  }( ?  Y- O' z) L                writetime = (DWORD)elapsed_time;4 S( ]3 f0 m; L  ~1 E
: k" h0 C" F+ ~% v$ d& K
                while( GetQueue( writetime, q ) ) {
8 V& [* m7 T8 ^- ~% N( ~% x  w                        WriteProcess( q.addr, q.data );' h" t! S0 a$ j
                }
* b4 w5 j; x3 H+ G3 ~& n) h% o! n2 ~1 V* {
                while( GetExQueue( writetime, q ) ) {0 D* ^1 I* B( S8 I% P
                        WriteExProcess( q.addr, q.data );
$ o/ G" V+ d! o% r; ?4 ]6 h                }; E( u2 [( g' i5 P$ z/ g, _& g

2 B3 H  A4 k; X! o2 T% }6 q                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7$ u5 g7 O# C9 M4 X1 V9 V' ]
                output = 0;( q1 @4 v. a% C" j  V: t4 s8 z5 ^( i
                output += internal.Process( 0 )*vol[0];
. {' `8 M* ]' d5 G0 C                output += internal.Process( 1 )*vol[1];- L& k; `% ^" ^& D
                output += internal.Process( 2 )*vol[2];% D. R8 B, d, L6 F' ]
                output += internal.Process( 3 )*vol[3];
* r6 V! D3 M9 |; v                output += internal.Process( 4 )*vol[4];
/ j: i, p0 z' W9 Q3 ^+ S& n. j1 p) l+ N
                if( exsound_select & 0x01 ) {+ i# J4 @* b$ V* c  g7 H
                        output += vrc6.Process( 0 )*vol[5];! Y" v) ^+ i' V2 `
                        output += vrc6.Process( 1 )*vol[6];; _+ l& r: y2 {+ u7 T
                        output += vrc6.Process( 2 )*vol[7];
4 h6 e) _( |' `' J2 b, x: T                }
( r1 U  [( Y) Y5 A                if( exsound_select & 0x02 ) {
/ M& d: ]% W9 A+ s0 y9 p& }                        output += vrc7.Process( 0 )*vol[8];9 G0 ?8 |  [9 w7 I
                }
) j( Y2 j1 E# X% W/ a- R+ }                if( exsound_select & 0x04 ) {8 N. C8 k9 {$ F! ]7 G
                        output += fds.Process( 0 )*vol[9];
$ h& `* k  u6 \" a6 @% e: o* y, z7 f                }
6 R$ S7 F' ~/ X5 @* ]6 b                if( exsound_select & 0x08 ) {, e( C; y, q) }7 r9 U* W. s! @
                        output += mmc5.Process( 0 )*vol[10];
( x* q7 ?: @0 \+ r- A, v" X/ |                        output += mmc5.Process( 1 )*vol[11];# R* R+ S( |2 r3 L8 A9 ?* ~
                        output += mmc5.Process( 2 )*vol[12];% O. _+ z' R# e, W2 X5 Z
                }& @) z! d% y% I/ b' }& ^
                if( exsound_select & 0x10 ) {$ W3 }6 ^6 U0 L/ _1 W! q0 a4 F7 B0 A
                        output += n106.Process( 0 )*vol[13];) D$ e" A; l; j  x6 T1 i
                        output += n106.Process( 1 )*vol[14];! y7 \, O( b0 i
                        output += n106.Process( 2 )*vol[15];0 f  L7 k4 F; S) ]3 G9 v
                        output += n106.Process( 3 )*vol[16];
# t. k, X3 G  u+ W4 T7 T6 E                        output += n106.Process( 4 )*vol[17];
9 J! u9 q$ X; s                        output += n106.Process( 5 )*vol[18];. I2 s/ r  i1 ]( A1 N* A5 B
                        output += n106.Process( 6 )*vol[19];
* e4 Z8 [; W* w8 B                        output += n106.Process( 7 )*vol[20];& ~% j- l- l2 t: k8 G
                }- ]2 N1 f. C- V; K* N3 F! C2 ~
                if( exsound_select & 0x20 ) {
$ W/ C0 O5 H+ j* T9 j+ ~1 N6 ~                        fme7.Process( 3 );        // Envelope & Noise
7 \9 ~+ \! A+ N4 G& X                        output += fme7.Process( 0 )*vol[21];. Z! F; I/ i* h3 o1 x% \
                        output += fme7.Process( 1 )*vol[22];
+ U! Z+ s4 P0 n3 |( p                        output += fme7.Process( 2 )*vol[23];% Y3 j0 k: Z; J, K1 T" i. D$ ]
                }
( ~  o, R( x/ g6 a3 J4 D* X& p$ W! {( W; `
                output >>= 8;
8 q' s+ _9 a0 a3 h0 h: Y. l
! l# y: @! m% Y- E2 i# z7 F                if( nFilterType == 1 ) {
% T% }5 q1 X$ s/ ~( w3 x                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)( ?% b, f6 {, v9 e1 x) `  k$ n
                        output = (lowpass_filter[0]+output)/2;. a- a* s5 z+ o0 \1 m4 ?4 s, K, x# P
                        lowpass_filter[0] = output;
  ]- L, [) @0 W9 T+ c& C& t                } else if( nFilterType == 2 ) {  u1 K5 V* a0 _
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
4 n5 i4 |$ R+ i" r! m# Q1 A3 V                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
! W$ B7 V6 n1 X2 x                        lowpass_filter[1] = lowpass_filter[0];7 A+ G3 T9 E' \; Q- I
                        lowpass_filter[0] = output;
+ g& a9 c' B) K, ]. `                } else if( nFilterType == 3 ) {" |$ ~1 u, J' z
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
* I  M7 n+ w2 W2 _/ k! O: x# f                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;9 [  C# a+ p2 D
                        lowpass_filter[2] = lowpass_filter[1];
1 l7 }- {3 r- d) D                        lowpass_filter[1] = lowpass_filter[0];
+ w( t% a0 [  O8 k! H: x                        lowpass_filter[0] = output;, K+ n# u7 a2 X* V9 I) ^& ~7 `0 J
                } else if( nFilterType == 4 ) {
5 i" z/ C1 z6 C                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
$ W4 x- L, O6 c5 a: \' ]% _                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;4 n: |0 |/ y* q+ u* o
                        lowpass_filter[1] = lowpass_filter[0];
. o% g9 E* p3 C* d/ _                        lowpass_filter[0] = output;
2 L" @  D, \8 [* W                }
% y' V4 d8 J, @; Q- N5 S8 q
+ k7 l) v# j2 Q' Z#if        0( \0 P- e- h" y. T  s1 [
                // DC惉暘偺僇僢僩3 |/ z0 h! V  _" `" I: C6 T
                {9 A& }3 E5 W! J
                static double ave = 0.0, max=0.0, min=0.0;% O& v. X5 I: h4 l
                double delta;) D+ `+ Y5 C/ \* u9 ]  F/ }
                delta = (max-min)/32768.0;
. J( d& C% W* F6 l8 r! i- O                max -= delta;
, o. S2 S; ]2 k* g1 l  u                min += delta;
6 _' f7 S+ T+ P                if( output > max ) max = output;% R  y0 f4 \6 x8 Y+ K9 j
                if( output < min ) min = output;1 X5 z& o5 I+ N
                ave -= ave/1024.0;
3 s% o' q7 L7 s0 Y3 L5 ?                ave += (max+min)/2048.0;
! J1 v3 Y, e5 \                output -= (INT)ave;' ]( w: h) Z  `# {
                }( m( E  P4 |8 h  I8 F) p
#endif
; q' ?- R4 A, b; K, Q  Q+ I& a1 A#if        1
" g' T( C' l# i  u8 W" k8 d                // DC惉暘偺僇僢僩(HPF TEST)' r* ]9 ~3 Q$ ^1 w
                {
( O! m9 i* Z2 a" ~: ?4 X//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);( |/ i- h  j5 p" ^, r4 P& V. A" Q6 q
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
6 M9 u2 l+ a' }) V! M  e/ r9 p6 G                double        cutoff = cutofftemp/(double)Config.sound.nRate;
  ]; p; t3 o4 j/ u                static        double        tmp = 0.0;
* G5 ^% `2 [7 d( m" c                double        in, out;4 \% s0 r; @& u' g1 e" i; {6 h

: H2 J2 X6 F' W" c8 ?. F- [                in = (double)output;) Q! Q, L0 Y3 k9 d9 Z
                out = (in - tmp);+ a8 ^/ C. I$ a4 Q/ c6 ?
                tmp = tmp + cutoff * out;% L! D0 ]( j/ N2 F, d

, Z# A! v+ L& n/ u! a                output = (INT)out;" i6 X/ @. `9 k2 y$ Y7 h4 Y
                }
9 K' r) @, s4 J9 m4 N* f; G#endif. R2 }, E, ]$ J) [1 X
#if        0
7 l& c8 f" i, F3 ]4 o                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)9 ~5 V. U& Z' d* v  [
                {
$ v4 B, }+ |8 J) l& l6 W) s5 \                INT        diff = abs(output-last_data);6 D0 A/ V1 `; p$ H
                if( diff > 0x4000 ) {
2 W" Z  ]1 _; j; \0 P                        output /= 4;- q# @8 j. p& `) `6 L
                } else
. S% }" R7 d% K/ U  M; A                if( diff > 0x3000 ) {6 t- \8 S1 C7 o; j, w  ?
                        output /= 3;
) ~' q' f' E, X; C4 D                } else% X% d3 W3 p; |: C
                if( diff > 0x2000 ) {
4 u, e; G" n. n# E5 T& K" x$ @$ j0 L1 K                        output /= 2;' C/ g3 \( ^8 ]" n$ R  `
                }
# n( o& i% _3 r; G" ^/ Q                last_data = output;
& T1 i! S4 h* t; t9 q1 D                }
+ @# B; f( C. Z& D- ?$ W5 m#endif
/ d! p; x( A- x( f3 x! I) J) q* ~  Y                // Limit7 a6 j0 K7 b7 ~$ h
                if( output > 0x7FFF ) {+ s# x, ~3 |4 V1 @
                        output = 0x7FFF;+ V( o6 P4 i+ _; d- S
                } else if( output < -0x8000 ) {+ g4 m, `7 r- S7 U
                        output = -0x8000;# v( ~( N/ @( D
                }
+ D; U( J' {$ f# o$ N$ ?7 H, x" ~$ H# h5 K1 r/ l- T! K, k
                if( nBits != 8 ) {
) s" d1 d9 Q9 e$ f! ~7 S# i) H( o                        *(SHORT*)lpBuffer = (SHORT)output;4 `; q% y4 A' q3 x0 ~
                        lpBuffer += sizeof(SHORT);
- T4 v2 M! P# ~1 X: Z. s, ?" A                } else {3 H- J/ g: a; Z( w3 u2 r
                        *lpBuffer++ = (output>>8)^0x80;, ~, n4 s2 F' J+ h. G* p+ w
                }1 c7 C( Z! \2 x/ q7 G

7 @# Q; {* g/ O; q                if( nCcount < 0x0100 )# J" x( S+ t3 _0 ]0 Z% I
                        pSoundBuf[nCcount++] = (SHORT)output;
  H# N; R( I  e: Z& x
" r( \9 b' l2 I9 G( j6 h1 F: D! @+ X//                elapsedtime += cycle_rate;
# f1 C0 S7 o: q4 G                elapsed_time += cycle_rate;6 H# j+ q1 q- v  G
        }
0 t/ z# Z" y+ Q) `+ W0 r
0 h4 N! W4 J- S1 e  r7 u! F1 z#if        1: S; A% V! z2 r6 u  Q& p
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
9 X# W# V0 [; `$ T$ p: S                elapsed_time = nes->cpu->GetTotalCycles();8 p$ e- M# [0 D# y8 e/ B  N
        }# n( k: }  O% b! O* p3 E2 f
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {
" M7 ~( I, c. |. |* R2 A2 s. r8 }                elapsed_time = nes->cpu->GetTotalCycles();
8 M( x) p% k1 J4 ~. d2 k4 b        }% _  x* I5 U$ G. ^" R: c+ l4 `
#else
. s* [5 j! [7 l* d/ t& \        elapsed_time = nes->cpu->GetTotalCycles();
* k; B; f& z* x5 x4 \5 K: g#endif
+ [- b# c8 W2 B3 P* u/ y}
6 a, s  J& F8 T/ q  h
$ k1 L# z: b" ]( w! `// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)
' L4 i& Q& N% q: r+ y. VINT        APU::GetChannelFrequency( INT no )5 b& w. x& L* K6 s# E3 A
{
/ T# a8 n# H2 X& Z        if( !m_bMute[0] )
% F) U7 V2 m- ]2 r/ V8 r4 c                return        0;: L. r+ z3 w" ~
* n) H) z$ Y# M( [
        // Internal
$ G' m3 ~7 w1 t1 h        if( no < 5 ) {
, Q! [9 `7 @% Z; w3 s* g5 A                return        m_bMute[no+1]?internal.GetFreq( no ):0;3 F9 |1 O, a0 k$ Y
        }
1 v" ]/ |# \; [9 Y: |* E        // VRC6! q, ?, {! H- \! p
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {, p" y& v* H6 k2 ]' T$ a8 z
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;
# J. Q  _9 p" z        }& v0 l' t- y2 t  C  O
        // FDS
" u9 _$ Q* O* s" ?0 H3 W9 j, ^  W        if( (exsound_select & 0x04) && no == 0x300 ) {) X: w1 ?3 Q% D- E+ x
                return        m_bMute[6]?fds.GetFreq( 0 ):0;( g" S5 d3 a" S/ |
        }
$ V0 |+ B! l6 n8 h9 E$ V7 @        // MMC59 ?4 ?& \# l$ h! v( G2 i
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
2 _  t! X5 w" U( {( R                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;# N+ M+ G( u! q. n
        }
0 O' S) m& k+ Q9 e' @8 z/ f        // N106
6 A7 {) \+ D$ q0 y1 p. A6 g" y7 S        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {
4 |* x  K' h/ T) X5 o                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;  Y) X, E- g, A: ~
        }$ ~3 F1 t% F3 R# {$ P2 X' B
        // FME7$ d8 P) Z# l/ G$ P3 p
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {% ]9 n2 ~# H( d- G4 q$ m
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;* \" r: Z/ W5 a( U# r, A
        }1 m/ n3 b1 O2 y: a/ f. v% Q- q
        // VRC7. @" x, K8 d+ E/ U0 y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
" i# E$ }4 I; W! o1 ]                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
8 W& H5 D% a. _8 l) Y0 j2 ?3 p" p        }
' o. z$ ]2 v+ [  P7 q# i. Y. X        return        0;" z1 t! M* {. v! j% S, [
}
& [6 L" D/ Z" P( E& H) |3 r" ]; I" v4 ?7 J9 Z
// State Save/Load
, g6 l7 A1 M1 G# H8 lvoid        APU::SaveState( LPBYTE p )$ G4 _0 P5 x2 ^! U0 g
{( w5 z6 U$ c2 z. Q4 i8 b
#ifdef        _DEBUG4 `+ ?8 X) i( H
LPBYTE        pold = p;3 d, D: r. D* `: H) |
#endif
3 N& O( T/ ?9 p0 J# a- {; a, K+ e7 P. a2 [2 B$ W
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞& g4 X: b+ k! z; K0 r
        QueueFlush();
2 z  z; F# d  ]3 ~+ X" Z* Q, c1 n5 y7 r. I3 g4 C/ x
        internal.SaveState( p );
# ~+ c( Y' m' i2 s( b  \' U) D        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
, }5 o+ q# u+ q- @' V7 h! ~, x+ M! h$ M# s; ?4 s
        // VRC6
7 G. v( w3 a( y' i+ M* C        if( exsound_select & 0x01 ) {$ [1 J( J# n5 ~
                vrc6.SaveState( p );$ ?1 w9 U. q) J! D" `" A% I9 U8 \
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
; J$ w: u0 V( x' G+ {$ R        }
. A# X! K6 g" a0 ~7 O0 l        // VRC7 (not support)
$ d; w9 x" X2 ]        if( exsound_select & 0x02 ) {
9 l/ B  l" T5 z5 r  Y( D: }                vrc7.SaveState( p );
3 y. z9 K% j. T                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding. k5 D" X* V& u0 w2 p
        }
0 a- e& u9 \  r1 n        // FDS
' F5 B2 b' U8 b2 l3 w5 d        if( exsound_select & 0x04 ) {
# a$ K5 w1 T  [+ A. w                fds.SaveState( p );
6 @$ C* K: a" K# x8 o1 \                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding4 D, d/ X/ J$ C& u. J% R* p
        }
/ X" Y1 k3 F: _" a1 v. ~. V        // MMC5
+ p6 ^' p- M8 U) j% T0 T        if( exsound_select & 0x08 ) {
/ O0 @( r) \" r6 h                mmc5.SaveState( p );) {% ~2 K) k) x7 E5 Z
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
6 }! [. @& j$ h+ ~. X        }3 S7 m: `4 N5 V/ c$ y) P
        // N106" Q. }8 c9 D3 w* i
        if( exsound_select & 0x10 ) {
. y8 O: P# M7 V, q7 |  r" C                n106.SaveState( p );
1 \6 |* O- a  J. F, G! K                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding& A2 o( Y# H& N8 H3 L8 Y8 }
        }
! H8 m% M4 C3 m3 }* `        // FME7
2 o: c* R* R. |- D        if( exsound_select & 0x20 ) {3 `6 l; H! X" v6 k1 g
                fme7.SaveState( p );
8 i+ g0 V2 |& z) n                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
3 c! V% c2 m4 U1 N1 l* i5 A        }
) C- t3 V9 S* Z# m7 u# g2 N% u9 L2 y$ v" E! A
#ifdef        _DEBUG* T  \7 C4 `% i3 a; b3 D6 S
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );1 U  a" o, Z$ L" R( f* _' H
#endif4 Z0 B* N/ c. q$ d( E
}$ u0 f4 H9 }1 V% A; F1 Z+ a- i

. n5 [' i7 ?5 `& ^- ^4 H1 j. lvoid        APU::LoadState( LPBYTE p )
2 _" @) Q8 R) p( }. W{
4 r* H# z  ^9 s( m. O; K        // 帪娫幉傪摨婜偝偣傞堊偵徚偡
, u( r' ~. U! }  q        QueueClear();& V1 ]4 Q0 D% _: A
- l! P+ m: X3 G; p7 P
        internal.LoadState( p );
) ^& {& Q4 r1 P0 m3 j( a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding- B+ K3 h% M( C: w+ e8 ]' x) Z

+ r9 e; g8 N, K8 i; [1 G        // VRC68 S5 r2 Q  Y- L- I$ p" ]( u
        if( exsound_select & 0x01 ) {
$ q1 V* T* y2 c/ T8 w                vrc6.LoadState( p );( p8 z2 M+ I4 V# O0 `
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding; X& l8 z9 l: D  I* Q# P# t2 i
        }' U, v5 ^% L. [1 F9 k& x
        // VRC7 (not support)
+ k% ]$ W" U( |( `) {        if( exsound_select & 0x02 ) {
! `5 U! N( O. j$ K7 q. @                vrc7.LoadState( p );
- m, e. q2 q- j6 t                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" S0 }- q  ~7 ^* W# E% o5 k
        }; _. u$ k: e0 g: |( e+ ?
        // FDS
5 E' j0 {' R  j        if( exsound_select & 0x04 ) {& O5 V" [8 [/ t9 [0 T/ I
                fds.LoadState( p );
5 q% c- A( u( H9 J0 B0 X                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
2 x4 z2 T! ?) e: N" u  G        }. p1 v. W0 U7 P1 t+ I5 I0 w% M! Z9 o
        // MMC59 R& Y. T" v3 A9 H
        if( exsound_select & 0x08 ) {' r5 m8 u3 U7 W  H2 z( r, O
                mmc5.LoadState( p );, f6 ^/ C9 ~* b% U1 S! J
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding( i( I# t0 w! n4 ^0 m5 Z
        }
5 X+ @3 @  N# g3 w        // N106  b5 x9 T8 W8 ]3 {
        if( exsound_select & 0x10 ) {( b" `& U0 R  G, c9 G0 f
                n106.LoadState( p );
* r/ |; v1 I$ D; [" R                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding) I& m5 x9 N$ v! P% v
        }) f& k! D5 M5 K+ f2 |5 h) z
        // FME7
* l* j& S4 o/ t1 D        if( exsound_select & 0x20 ) {
4 `" u% e; |& ]                fme7.LoadState( p );
% A- q0 {4 n4 n5 {* l- m                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
) p, _( s/ D2 b, Q! J        }
& C' b) n; w' M. x& V, s}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 - F6 e3 g+ D# N# d9 @, y
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。
. d2 Y- x1 K8 I  V3 M; v感激不尽~~

0 l0 l' \$ t4 l2 ~& X. E: Q恩 我對模擬器不是很有研究,5 W" h& B  v. b9 p
雖然要了解源碼內容,可能不是很困難,
8 x" l0 P" e/ H7 |不過還是要花時間,個人目前蠻忙碌的。
/ I! ~* ]- B" u* D
* v& ^+ ~0 W! M2 w  k0 Z( q4 Z/ P給你一個朋友的MSN,你可以跟他討論看看,' r* S! e  t# o! b- k; W
他本身是程式設計師,也對FC模擬器很有興趣。! I8 o) t6 v  A; Q* O
3 {/ W* R1 c$ q6 _1 Q
MSN我就PM到你的信箱了。
3 g: B0 ]- \& }/ d0 N4 S/ j3 Z7 B, u; F- _! i; D2 y2 {+ d
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 ' C1 U) r# e8 _
呵…… 谢过团长大人~~

- a" {7 g$ t/ H. G( y8 K5 z( W5 M: n9 i. Q; n! L
哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表
1 i' y) [: g, j团长的朋友都是神,那团长就是神的boss。
7 `& I' U+ m4 P7 S
哈 不敢當,我只是個平凡人,( R% w* p( n1 @) O3 N% L4 ?
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
3 p) I3 ?- |% k" OZYH- V) Y% w: p8 `" q
QQ:414734306
0 a+ d0 c5 A$ A* r& o9 }6 @! r& {7 p7 eMail:zyh-01@126.com; ~1 i2 q, d& K# O: N0 l: B+ H

. z$ E) O# U( T4 T/ d% ~; z1 I他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
& s5 e& z0 ^! Y+ u0 i/ D7 G再次对团长大人和悠悠哥的无私帮助表示感谢~~

: w& ^3 G5 S5 z不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-3 02:13 , Processed in 1.080078 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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