EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。; a# c* R! I( h" i4 S
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
0 v7 L- _, X3 [9 \这里有相应的模拟器源码,就当送给大侠了~~! s! ]$ I  o+ s5 c8 l9 F
http://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 4 |2 O2 c8 Z: C$ U6 ^: Y2 C
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。0 ?6 }7 o8 p5 i5 e$ i
楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~1 k& b2 G0 Z' L* o2 o7 d% h
这里有相应的模拟器源码,就当送给大侠 ...

# ?: P/ D! @& e8 @+ f3 h聲音部分(Audoi Process Unit = APU):
' f  G. O; C$ i.\NES\APU.cpp
2 H# j; ?$ G: G$ W& e( o: |.\NES\APU.h
# {; M: g$ P& \+ g' M' d! K) m1 I. O" k7 b. q: ~- e+ x

7 S! h0 }8 {2 R4 E5 e# u, }影像處理部份(Picture Processing Unit = PPU):; D% q' ?- n8 o9 S
.\NES\PPU.cpp
: S; q- @' c8 u. p$ b$ R/ p* Q.\NES\PPU.h
! J8 U3 B  `! E6 }
& e% b3 E2 L* j) A8 V如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:2 B  N( {/ g' u# u: d+ v1 r* E
(由于很多专用术语和算法机理都不明白,所以看不大懂……), e3 e8 l6 O% U0 f
//////////////////////////////////////////////////////////////////////////
% n: ~1 V4 `9 R+ x7 j9 j* N//                                                                      //
) |9 P9 w& l: z9 x//      NES APU core                                                    //1 {; u9 b. A; n8 m% G1 N8 h
//                                                           Norix      //9 t5 Q7 ^* N- g, P
//                                               written     2002/06/27 //2 ?2 n$ t2 o' Y0 U$ G
//                                               last modify ----/--/-- //6 P9 Y8 `* i% M6 n" l' {: T1 A
//////////////////////////////////////////////////////////////////////////
9 `0 `2 P; z6 H#include "DebugOut.h"( S8 R% A1 `4 c; E( c2 Z# ]
#include "App.h"  }- W6 k+ B. }0 k/ P' i
#include "Config.h"" T( A) R* F: G$ p8 G3 F

3 U. L2 I9 |4 L4 I. m) m#include "nes.h"1 ~% e' ~  M& J- p% o: D2 H& O  g
#include "mmu.h"7 \/ |! _8 @* O, ^' v( n$ u2 t$ H
#include "cpu.h". Q3 h/ l& n( I. M+ e
#include "ppu.h"3 C8 @; f& v, f; L4 ^
#include "rom.h". A% \* l; U( k; o# a6 V3 n, G" b
#include "apu.h"2 p1 }' p" h, K9 m/ w, C/ D8 [

$ r# k1 F# ]5 L; R. k6 ?// Volume adjust
8 d; @5 J% @. {/ r, S1 s// Internal sounds
. c) s% D) o& A# x2 M" c% h#define        RECTANGLE_VOL        (0x0F0)
! k  o( V& J$ [- a#define        TRIANGLE_VOL        (0x130)
6 o9 x" Y' C4 @#define        NOISE_VOL        (0x0C0)
* l: }5 h6 B3 N1 i#define        DPCM_VOL        (0x0F0)
; W  i. O9 P1 Z6 p& W" B; i// Extra sounds
+ f  M$ {: F8 k1 g  y#define        VRC6_VOL        (0x0F0); X# G- X  H3 K$ Q9 q+ }) F0 x
#define        VRC7_VOL        (0x130)
8 L& e+ W: W" v: M  b#define        FDS_VOL                (0x0F0)1 k& `# c6 c- D5 D( n
#define        MMC5_VOL        (0x0F0)
: J) |( u  E& T! F: q: \& ?, W#define        N106_VOL        (0x088)+ ]2 c. L* s3 M, S/ X( s
#define        FME7_VOL        (0x130)' L  `; g  s1 c8 d/ k9 D
# s2 k8 R+ Q& Q
APU::APU( NES* parent )9 ?  c, y$ o$ T& r
{
. P3 x# i1 o' u# P, Q0 ?: H. S/ x        exsound_select = 0;2 q# D/ g8 i3 z4 N

; k# _1 A/ |' d) r3 d4 \$ j        nes = parent;
$ m2 P# T. v. D: A. k  W% D        internal.SetParent( parent );
( V2 Q* _( U& I3 u, X5 b0 ?/ Q
/ j* q0 E8 D8 {; |        last_data = last_diff = 0;
- _; h: D# c4 x8 v* j& c* p9 k4 y: @' k* V2 j0 R" B
        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
. w3 G( {" Q& J- m* d  O$ }: a# s+ u1 F+ H; J4 g# x* M
        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );5 S/ }1 J  U6 s6 _7 p
        ZEROMEMORY( &queue, sizeof(queue) );4 N, V8 \3 O, A& w( N* X
        ZEROMEMORY( &exqueue, sizeof(exqueue) );' z% W3 K9 ^- t1 J9 ]& @/ U1 }- T5 H

' l+ [  Y1 _* w5 O! G        for( INT i = 0; i < 16; i++ ) {+ @, W: v) f6 S
                m_bMute = TRUE;3 ?: G3 R1 L. _0 `
        }
1 G& X" d& u7 n' O2 x, y}( t0 e+ Q' s4 C

. w6 N3 `7 t3 _2 PAPU::~APU()
) h9 N/ y8 `0 V  p7 a{) q$ H) ]8 j, V/ j# ^$ e
}
% k4 w. S0 K0 U4 o- j6 S7 h: e/ k( o2 `! f  ?9 T( h% Q
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )3 R/ J" i& z: ^  p- d" F
{
- p" M7 H; m' R( w; t, l        queue.data[queue.wrptr].time = writetime;2 w) h1 d) _0 T+ E* S2 M
        queue.data[queue.wrptr].addr = addr;( O: y. X# L- T7 Q+ ^" D. B% ]; Y
        queue.data[queue.wrptr].data = data;/ ^/ Z, ^. G) @# I  y4 b5 K
        queue.wrptr++;
  |3 E5 H6 t: n' h- E3 I7 f4 F$ E        queue.wrptr&=QUEUE_LENGTH-1;; \4 C3 ?3 J! J: t) t
        if( queue.wrptr == queue.rdptr ) {: G: y. R6 K+ C2 x( L6 ?
                DEBUGOUT( "queue overflow.\n" );& \$ a7 q$ Z! Q: i* T9 ]6 _  q
        }5 t& Q& N9 e7 w# W; s# _  [
}" o8 y/ f; o8 `2 Z$ g

( e% i1 x! |( ?1 F5 {) qBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )
$ y; }# }& J2 g2 U: G; o{) w' L2 d( L* ?8 o/ |" i& V! K
        if( queue.wrptr == queue.rdptr ) {
& ^8 k0 f  J7 X* @, T! H                return        FALSE;
1 R) H8 o8 m7 f2 W, Z! C& |        }4 @$ Y9 Q2 W  E) [1 \+ ~- [$ |
        if( queue.data[queue.rdptr].time <= writetime ) {
' @5 V" u  g: q                ret = queue.data[queue.rdptr];
8 Q) k; h$ w! t2 g6 j                queue.rdptr++;
- z9 L4 P4 n" f& ^) K/ N                queue.rdptr&=QUEUE_LENGTH-1;7 j# R+ \" g! {3 m4 I" E
                return        TRUE;1 s; |- R5 H. s3 T! d, B( v
        }8 K, c- _# n- o: o2 b; T
        return        FALSE;
& ]5 a6 u. m2 O  q% w; e& S% J}; `" {* Z8 T- d

9 K" G4 `2 g( w4 i6 [( Hvoid        APU::SetExQueue( INT writetime, WORD addr, BYTE data )
! ~. U8 {4 O4 X{& m6 f, O: h$ G6 z
        exqueue.data[exqueue.wrptr].time = writetime;
! m0 L2 D7 Y" n- L        exqueue.data[exqueue.wrptr].addr = addr;3 e( Q: f. A1 L$ w0 f
        exqueue.data[exqueue.wrptr].data = data;, L5 F( P6 h* k; |  X3 A
        exqueue.wrptr++;" U9 g* S# `  p* O
        exqueue.wrptr&=QUEUE_LENGTH-1;: G. {2 H; O# ?6 G; H, r! b2 V
        if( exqueue.wrptr == exqueue.rdptr ) {9 f$ `' j* C6 u
                DEBUGOUT( "exqueue overflow.\n" );& O+ W$ H6 B' ~, j, p/ F7 H
        }  w' i/ n5 R3 R3 L* ]+ J2 I! X) h+ x
}* i/ k7 h8 ?6 T# `, V
9 p1 k' q# e' d, i% I
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
3 ~2 h' N1 K- ], u{1 a/ k# o/ _' O
        if( exqueue.wrptr == exqueue.rdptr ) {% _/ J! y# ]: ]( q8 x, {5 W
                return        FALSE;
6 I( B8 s' k& r        }
# [" B; N7 M3 }  n. q, b        if( exqueue.data[exqueue.rdptr].time <= writetime ) {
* m; i" [1 w9 U                ret = exqueue.data[exqueue.rdptr];0 H1 {' t$ _8 C
                exqueue.rdptr++;
- W8 _0 a% G$ a, \) g                exqueue.rdptr&=QUEUE_LENGTH-1;
" f# ~% `( i, f+ [                return        TRUE;2 D1 f7 M2 y2 J4 N& ?
        }5 y8 V4 \# H* x& T# i& T
        return        FALSE;0 y8 q3 H# u7 a* c
}! k$ y5 q3 d2 ~9 f
( S' F5 k: U& K8 g& Z
void        APU::QueueClear()
0 A3 F; J0 U3 t- _  @5 q+ {{
3 u) `- s: Y: u$ ]$ R( c        ZEROMEMORY( &queue, sizeof(queue) );
8 q- i! B) V: `        ZEROMEMORY( &exqueue, sizeof(exqueue) );
0 Z" Y4 @0 h, d% Z& c( U9 R; T2 h+ S}+ k3 B- k( s  r9 P
# Z# [' A( {  S, E, d0 X0 G
void        APU::QueueFlush()
8 r8 _: }5 E/ C, r1 _{# k' X: {( }# u$ L! ~% H  N' d
        while( queue.wrptr != queue.rdptr ) {
$ ]( E) K, `& z1 o                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
3 p! G/ o" `. g& B2 C                queue.rdptr++;- N' U" Z7 m0 L
                queue.rdptr&=QUEUE_LENGTH-1;
, E% V* {9 w8 a1 C0 z. C6 d6 `        }
5 G: G; ?9 }. {( q# ]) S
, V# ]6 z, A  g8 \( S, g$ W        while( exqueue.wrptr != exqueue.rdptr ) {8 }' J  Q! o2 x* U) l& m
                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );% p& Z2 b3 Y+ `
                exqueue.rdptr++;4 S- N5 l  I6 Y' [2 T' ?' R
                exqueue.rdptr&=QUEUE_LENGTH-1;7 y6 u2 O9 z. u
        }
: z# C' r; ~  T& m}$ J( y) j( i! a
& l; J/ e8 o' E* [
void        APU::SoundSetup()* F- s( r% O* s- S
{6 _7 T- K' [! {; n( T# X) t$ O
        FLOAT        fClock = nes->nescfg->CpuClock;
& W3 x5 M" z' v# p        INT        nRate = (INT)Config.sound.nRate;3 I( g0 j, z: T. ], L; O; `" G
        internal.Setup( fClock, nRate );
* e2 l. ]8 d# K* `% s) z        vrc6.Setup( fClock, nRate );
/ U3 y, l. Q6 s: R        vrc7.Setup( fClock, nRate );! A  q7 p- o: e# \
        mmc5.Setup( fClock, nRate );
" ^, X: ]1 b$ s0 g( R        fds.Setup ( fClock, nRate );
% c4 I. N  B8 v& j  f% h        n106.Setup( fClock, nRate );
$ I$ G+ S3 N1 `# t$ r        fme7.Setup( fClock, nRate );
; v6 n% g- V: x+ [}+ T6 k+ a2 G5 t, z. I' p

: w8 e! a# q% A: ^/ Lvoid        APU::Reset()
; g; T6 E+ T# ]* n; H7 t' r, U' [" ?{
- z2 ?$ n& P# Y/ o0 O6 D        ZEROMEMORY( &queue, sizeof(queue) );; Q5 y6 C2 j; M3 l5 r, Y
        ZEROMEMORY( &exqueue, sizeof(exqueue) );
- |2 D- m6 H2 x: r$ }' i
5 B+ n. @4 G' X7 o( |: U6 ~0 b        elapsed_time = 0;; S* M2 ^+ o! y/ Z& q

7 X; ?) R% r- j9 T' R; M  J- f        FLOAT        fClock = nes->nescfg->CpuClock;
  r. [2 I$ u4 b# C$ u        INT        nRate = (INT)Config.sound.nRate;* q$ s+ R5 T& M5 }( L# W
        internal.Reset( fClock, nRate );' [4 G1 a" g; {+ u) ]$ Q
        vrc6.Reset( fClock, nRate );
  r7 t( d( n$ O- Y! \        vrc7.Reset( fClock, nRate );: r& W- r5 _& Y/ x3 ^8 ]
        mmc5.Reset( fClock, nRate );9 I" ^. E6 q, k7 e- W
        fds.Reset ( fClock, nRate );
+ Z9 y7 f" A6 ?% u  O        n106.Reset( fClock, nRate );; }+ s( W- p6 b) e+ `$ Q) t
        fme7.Reset( fClock, nRate );) k# O  ^/ o# y, x  U

0 \2 g, u0 A3 Y: V+ U1 q9 M        SoundSetup();
7 O$ y$ D$ H# g* F/ e& K! N7 d. s}. f+ Y4 E4 E' r! C1 s. A, {

! c7 T( {5 @- g" w# o9 bvoid        APU::SelectExSound( BYTE data ). z+ R5 F; d3 N( ^% V$ R/ Z
{
. m- W* {& h! _# q, T% z+ a        exsound_select = data;
6 j7 T$ }; u! F6 Y6 L" P8 r9 F* H}
  H1 G  t# F5 W- k* p
  j5 \6 t* j/ b$ L9 wBYTE        APU::Read( WORD addr )
2 U8 A! Y9 u  y{
8 @9 t  _9 i$ Z6 f4 w        return        internal.SyncRead( addr );/ ~1 K1 r( D& C8 @) \, t
}
; t; a  y- [) u' z: W) G8 r, ~- U4 D$ V) ~! H
void        APU::Write( WORD addr, BYTE data )7 C. I3 T1 d1 n( K+ p% T
{
$ J$ K8 Q0 t- L8 b; m3 S0 h        // $4018偼VirtuaNES屌桳億乕僩
3 P6 k4 P; q+ `: M        if( addr >= 0x4000 && addr <= 0x401F ) {
) h( A$ @6 ]% L# x: v$ E0 G# u                internal.SyncWrite( addr, data );
7 V. p6 j5 w8 X' P! E9 q# Q                SetQueue( nes->cpu->GetTotalCycles(), addr, data );
! d3 Z9 t2 Y" X        }
7 W# U) n3 r* i) Y7 J) O3 S5 r5 S}# u# [; d0 H4 n% \

# N( S' b( ]* Z4 I' hBYTE        APU::ExRead( WORD addr )  h$ {1 ]. ^% ^; y& ?$ y
{) N, ^! m& N, ^, h
BYTE        data = 0;: ~, x0 h( Y) o6 @0 l' p. e* U
3 |; S6 N; g" x9 h! L+ U, E
        if( exsound_select & 0x10 ) {
: C- V9 h/ w3 }% Q  @& n& r- J7 U                if( addr == 0x4800 ) {
$ |2 r1 o! a1 t                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );
" D7 G$ O/ w* P, F                }% A9 m5 _; ~, x8 Y! g
        }8 S: g) k6 B8 U: y% f) j4 d. A
        if( exsound_select & 0x04 ) {
8 Z1 w2 }  w; m# ]" Z5 S# z                if( addr >= 0x4040 && addr < 0x4100 ) {2 U: W2 M1 S" {; |6 D
                        data = fds.SyncRead( addr );% c1 _. T# a: h8 Y9 D, i& T
                }3 O. J. g9 l+ v% w
        }: V2 x+ L: ?3 R5 T$ \
        if( exsound_select & 0x08 ) {2 z/ |/ }/ \* D, c
                if( addr >= 0x5000 && addr <= 0x5015 ) {
! Q8 {  H8 S2 g$ R                        data = mmc5.SyncRead( addr );
  r- h5 S  I; y7 V1 U/ |                }
4 ?  P6 w( m9 N# K) l, N        }1 b. x, B( W7 R% w8 z% |3 ?

5 V; u$ \3 x+ J$ @: @        return        data;" N! E+ @: S$ g2 y
}
' F$ m4 q$ L1 X3 F' Q4 u- T/ k: Y2 B1 q. U& J5 X! Y
void        APU::ExWrite( WORD addr, BYTE data ); d  [0 d2 U* p2 K$ x
{- d% M: Y0 m) {. G- d
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );
0 K! Y& Z" F- C0 l  U
2 |, N/ a( e6 `% J8 s/ }        if( exsound_select & 0x04 ) {7 f1 {, f& X, n& b6 l& J! Y8 Z
                if( addr >= 0x4040 && addr < 0x4100 ) {
" _: c) U5 m' {! h1 V+ _                        fds.SyncWrite( addr, data );
+ f2 B/ I2 U  K- M$ X" k7 R+ o                }
  z* _$ A! Q. j& a" h        }, x0 O" C2 l0 ?$ m9 l4 T
) Q# ^/ J7 {+ E* L9 S7 b; q
        if( exsound_select & 0x08 ) {3 q6 ]1 {. h& w9 A5 C
                if( addr >= 0x5000 && addr <= 0x5015 ) {: |! _7 T0 O' [  T% E5 v5 d5 U
                        mmc5.SyncWrite( addr, data );% q0 E1 k  |% ?; N* X
                }
8 j7 |! N/ X6 y+ A7 R        }
1 z% m  T( ], H& [* x}
8 n5 J( P8 e+ A; g" q/ T! H; x$ {' a" ^/ f" p2 F
void        APU::Sync()
. ?9 m* g6 g4 \/ s% s; M) F{
9 r3 q0 C  L& {& i+ {( U: G}
/ B0 U3 z% f. q. s" T/ \3 z8 H$ U
0 @7 s( y+ [" p$ rvoid        APU::SyncDPCM( INT cycles )' D8 C6 U8 v# @* ~2 f4 F; U
{; W9 B0 I+ G5 ^. X3 C& ]
        internal.Sync( cycles );
: y. D- P! _% S5 P
) b& L" E1 F* f+ c' R  {- ?8 |* S        if( exsound_select & 0x04 ) {
! o6 ^+ s9 b% U% D1 K, i                fds.Sync( cycles );: H, P- K  s( A4 P8 o# t
        }$ p, o0 W8 d+ f  w: E- k
        if( exsound_select & 0x08 ) {
& M" i; N7 V( u  u; X' I* E/ I                mmc5.Sync( cycles );. x9 u  ~0 H4 @& U4 k
        }
( v! }4 c4 k9 h2 A: V5 Y% l- @}  o8 ?0 n, @: m* }+ c$ Y

) O% j* z6 x6 ~void        APU::WriteProcess( WORD addr, BYTE data )
+ U4 Q$ w1 ?: y+ T4 t{
. C; D7 S1 ^, q6 \' {; m; R        // $4018偼VirtuaNES屌桳億乕僩
* s. u& W% W$ |+ E% y        if( addr >= 0x4000 && addr <= 0x401F ) {
$ K; [. \5 m9 X                internal.Write( addr, data );9 w5 h) B, i0 V: N/ z
        }; l; h' D. N) V& ~, ?6 Z2 L5 ]
}
. S. r4 `) V4 G5 B9 C, q3 E0 C
7 D& u% Q7 n  Ovoid        APU::WriteExProcess( WORD addr, BYTE data )
4 f* O+ c. O# c4 j- B* |: P0 a; n  y$ \{0 _2 t& n4 H- p# J
        if( exsound_select & 0x01 ) {* L  A' b5 \% ?3 {2 R
                vrc6.Write( addr, data );3 S5 g* Y' g! J# e$ x  Z4 ~, J$ k" a
        }1 W* z3 D4 K$ W- T  @
        if( exsound_select & 0x02 ) {, b6 S, s6 B; G! x
                vrc7.Write( addr, data );
* G5 H2 _7 Y- p) H$ c$ T4 E+ K/ y        }; ^/ n( k, ]! V
        if( exsound_select & 0x04 ) {
8 c9 Q1 d" W( k  |% z                fds.Write( addr, data );
/ w" K  h3 |. g1 N5 v) n8 S9 P8 x        }. ~" u# [. s! g% r
        if( exsound_select & 0x08 ) {
( m! U9 S: j2 y                mmc5.Write( addr, data );, w0 {* j: @5 F5 m) L; @$ y
        }% }) V# |* t/ N/ l2 Y
        if( exsound_select & 0x10 ) {( }7 t4 l7 K5 ?
                if( addr == 0x0000 ) {: r: h) X# X, q8 j( l
                        BYTE        dummy = n106.Read( addr );: _4 [/ O% A% k/ p; x  w
                } else {
% ^. w9 `6 ~% t2 Q* I1 x                        n106.Write( addr, data );0 @" g6 P9 b1 n2 M$ w
                }! A* ?5 n- Z, x+ c' t8 H8 K8 q
        }
( Y: E* ^/ p, a; q& [2 T        if( exsound_select & 0x20 ) {" r2 I; O! o* _4 _9 k/ P, U- ?1 H
                fme7.Write( addr, data );
0 s+ Y6 ]' n- ]* Q, r        }
) z. w3 @- K& j6 O4 a}
5 z5 K1 q+ J) W& ~: W, |' _  O2 J' R- P3 e. S
void        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ a2 Z; f- [" j& v- g6 L5 `2 z{
' q# s0 L. C* HINT        nBits = Config.sound.nBits;- W$ u5 J0 h% d# K9 z
DWORD        dwLength = dwSize / (nBits/8);/ F% a  ?; `& P  O
INT        output;
  W( d* u% [" v6 IQUEUEDATA q;
  G. u7 R- W3 s" Z9 l; Y" b% C4 VDWORD        writetime;+ c3 m& K5 o+ _0 U# I7 {
: q2 ]& d" Y0 u, p7 J+ g/ i! Y
LPSHORT        pSoundBuf = m_SoundBuffer;
2 w; @/ X9 \4 }* UINT        nCcount = 0;$ r1 C6 r6 J8 e) e. G
, G( [; g$ M% o; p, z8 s) e4 k
INT        nFilterType = Config.sound.nFilterType;
9 b) p/ N4 o# W' j) c
0 ?3 n" A  t) j- U( b0 r5 o; \& `        if( !Config.sound.bEnable ) {& O$ l9 c) S' L- o) D, o1 U
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );5 `& z7 k  I) i1 B, U
                return;6 i8 u3 p% o- J: }0 m6 Q
        }
# k' |. }1 R8 C/ |( F+ u( V+ G2 i
8 T$ l7 c7 n$ q# ~; f# r        // Volume setup
1 |$ u, q% A  r        //  0:Master
: c: n( C7 h5 G7 Z        //  1:Rectangle 1
7 u% e0 F) _0 V8 z* N! N. O7 Y        //  2:Rectangle 2
; x1 V# @, [  x3 u- ^3 g% R3 A2 T        //  3:Triangle
2 A/ z, g% c0 ~7 }( N        //  4:Noise; `* x' ]& Z6 B7 H( V& Q
        //  5:DPCM2 m3 L* i1 X# n6 L$ R& \
        //  6:VRC6
* f+ z& D7 \2 L        //  7:VRC76 Q% ]5 r8 ?+ _! U1 d$ `/ k
        //  8:FDS
0 h! _8 G( e+ U) n- V" s1 p        //  9:MMC50 [  ~, H/ W( k
        // 10:N106
: J, }) E4 w1 u8 E2 ]+ x        // 11:FME77 [6 r& S- U- u
        INT        vol[24];
2 _6 f; u  {1 q1 y5 ^" {        BOOL*        bMute = m_bMute;
0 Y& b0 @# ~9 E# @$ \* q        SHORT*        nVolume = Config.sound.nVolume;- ]1 {; S5 ?9 D2 z9 Z$ D3 x
. G' L" ?! H1 O% |. P: t
        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
$ D$ g" X  d. m' _6 C) S2 `9 k2 f  Z0 y# x# R: P/ f+ p1 l7 S
        // Internal# b# J9 R, D+ `5 J+ V' p
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;$ e* t* ?  y% {* M( U
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;
7 F" v) \) l7 g7 _$ ^2 l        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;
' g# d; v3 ?3 P* ~. _3 o& j        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;9 s1 [7 c* Y& R, X: I4 E4 w$ N
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;
: u" `1 `8 q6 h$ q' j5 c, {8 S: f& G
        // VRC6+ x  D! Q" H. O) `1 ]7 A
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;! W2 I; Y8 g+ d% h
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
8 q5 l( x1 j' o& V        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;- G# h8 Q! ~5 \9 h* i1 m

6 P0 V# P$ J' L* n- `        // VRC7! A, N# @# k( c/ ^8 ]
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
* S( t1 d$ s0 `; T! Z  @! m6 a+ S6 z# \4 t; r, ~
        // FDS
+ u4 c2 \% |( R# t- @/ `7 ^+ B        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;' _. _! u/ Y- {8 i

1 f% e/ ^; T; W% q& N        // MMC5
5 J: Y( |8 O  r" \( @        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;
4 ^' D# r9 n4 U( I. a* {        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; o/ ]5 Q- a+ x: Q
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;3 I+ a6 M7 k0 r# Z; u0 y- i
! p. j, |8 J8 x8 F  X5 ?8 D) O5 E5 A
        // N106& ], u( N9 A" O) s5 |7 I1 L
        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
7 z4 s0 N; j0 |% s- s7 V4 m        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 d) E* T( y7 x% t' X4 H+ m        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
0 c* T5 G5 ~# e# Z- i0 @  U# V& E        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
) J8 z4 P7 w( }4 k# Z        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;# ?* m7 T6 a- N2 r( m/ S4 R, \
        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;' ~/ m2 r4 E. j. i- e, P
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;$ M0 R" R& x1 }& z1 b
        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;. ^4 x+ [1 [* e0 V- R/ F% S
8 \$ ]7 ~( C2 E6 {9 Z
        // FME75 A: q: V. ~/ u/ R
        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
4 ^( l1 m4 G4 @5 _% E; ^! l9 d        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;2 ~9 q! S0 ?% C6 t1 d; R
        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
% y9 y# C& T- m7 w) c) f. O% E5 s3 w: ?, o" j$ _; M7 t
//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;. w' }9 M) x. d  C* i5 u
        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;1 a1 c& H( x& X0 l

  _  p% ~, i% t$ o( T1 r5 h6 w        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟/ `# h" _, c3 j4 E) a* h0 ?' d
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {
6 ?# ?! }/ e! R; C- E                QueueFlush();
0 I" b2 t6 I6 B8 e8 l        }! W  S/ @& d4 l* }6 Y7 r) v$ ~
" `! P" O: t% \$ l6 @9 A9 b8 D2 z
        while( dwLength-- ) {* ~* h2 [+ F+ q$ W8 d
                writetime = (DWORD)elapsed_time;; {& o5 `+ j5 f- d8 r% e
5 P, B0 [/ W4 M) E, i" T. L" }
                while( GetQueue( writetime, q ) ) {' x0 P# _/ `, L8 g
                        WriteProcess( q.addr, q.data );0 p4 @$ a2 E* p  X4 ]. W" Q. P
                }; x$ _! _* m' `/ g
4 W8 z5 E$ q' }
                while( GetExQueue( writetime, q ) ) {7 G; E2 K5 f+ U' Q7 Y7 f$ C3 x( n
                        WriteExProcess( q.addr, q.data );; P3 e2 o- q. [9 }( r
                }
6 |9 u/ X; O! w  n6 u3 ~
3 X% ~5 o1 Q( E. B                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME7, X8 T$ G$ B: Y  s8 l, R  G
                output = 0;
( b' q5 f0 B+ J# X+ s5 O                output += internal.Process( 0 )*vol[0];% m6 K; }( y; J" i2 T. M4 I
                output += internal.Process( 1 )*vol[1];
3 Y* V+ K# E$ A% l9 w" B5 \                output += internal.Process( 2 )*vol[2];' [' M& Z) ^+ H
                output += internal.Process( 3 )*vol[3];
. F8 E6 w  _8 ^1 y' |2 _# B                output += internal.Process( 4 )*vol[4];
; _& v" i* W; B9 C7 a( u8 s1 G
& o# m) v1 |) ^9 j                if( exsound_select & 0x01 ) {
. h0 h# t# ~8 y' G                        output += vrc6.Process( 0 )*vol[5];, a7 `0 T5 v6 d- }$ N
                        output += vrc6.Process( 1 )*vol[6];/ W8 ?" g% c  _4 D* A5 w7 O* d
                        output += vrc6.Process( 2 )*vol[7];# I( o3 t, X& m8 ]/ x1 s! u- E/ i
                }
) _; K2 _" e2 C4 J                if( exsound_select & 0x02 ) {
/ W# |- G6 K. {( d& P! C                        output += vrc7.Process( 0 )*vol[8];
3 Z% h! }+ S  ?0 w                }& f% d( W) N3 c  _& J. B" U, f
                if( exsound_select & 0x04 ) {9 H; u9 n; t! J8 s% l8 E
                        output += fds.Process( 0 )*vol[9];
8 i% q- W! D9 Y+ {                }: ?) q3 u; A+ ~! s1 Y- P& M4 L
                if( exsound_select & 0x08 ) {
1 |0 _3 e. x3 M8 H3 q8 B- K                        output += mmc5.Process( 0 )*vol[10];4 w9 a; @9 k. d& a, x" A! ^
                        output += mmc5.Process( 1 )*vol[11];1 W3 m3 B) k& U+ v- |5 `, a- g
                        output += mmc5.Process( 2 )*vol[12];/ e6 D2 P5 L/ u: ?- q
                }: D, J4 t  {  j/ o. Q
                if( exsound_select & 0x10 ) {7 T) g8 E4 z; y6 L9 P" V
                        output += n106.Process( 0 )*vol[13];
: }- U2 K) N' ?) d( r. j% |: b                        output += n106.Process( 1 )*vol[14];5 C; t% t( Y) }: Y" S: p
                        output += n106.Process( 2 )*vol[15];. t( C. h% j& f3 m! _. [' [
                        output += n106.Process( 3 )*vol[16];
: C8 n8 A( |5 E. M' s" n                        output += n106.Process( 4 )*vol[17];
% W9 j6 m; S% B1 k                        output += n106.Process( 5 )*vol[18];, h5 \0 y  J& L" q- V
                        output += n106.Process( 6 )*vol[19];* Q. U0 d* D! f% A2 w" L
                        output += n106.Process( 7 )*vol[20];
9 `# e) j4 M9 S2 b9 ]( c                }( E" d4 M  h" l1 U7 b* L/ }
                if( exsound_select & 0x20 ) {3 x+ `+ C  G0 v# V0 @
                        fme7.Process( 3 );        // Envelope & Noise
& c: G, p: f! X2 }) R                        output += fme7.Process( 0 )*vol[21];
& e! V4 p/ \8 d6 K                        output += fme7.Process( 1 )*vol[22];
- l6 C9 H7 }' s. V3 @                        output += fme7.Process( 2 )*vol[23];9 i; {7 a1 m8 z% K( O/ p* j  c: M
                }( w: C8 Q# ], ~( ]" t
- z, P1 I5 m7 o% J( h
                output >>= 8;
: q% c: v4 B9 U/ l1 g
1 Y6 n( t) ~& Z4 Q' ?3 m                if( nFilterType == 1 ) {
" X: j5 g& ~3 Q. y4 X$ ]7 p2 B                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)
$ F& Q4 K7 ~# g                        output = (lowpass_filter[0]+output)/2;; m  F3 M3 u/ P  ?
                        lowpass_filter[0] = output;
8 L* w6 O4 d+ m                } else if( nFilterType == 2 ) {
  H7 V2 ^$ \9 C0 [                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
' q* F; A) d! q                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;
: C0 \* t( K3 q, T; ~                        lowpass_filter[1] = lowpass_filter[0];
" B! K; d4 }( K; {                        lowpass_filter[0] = output;4 q/ o% l% f% l
                } else if( nFilterType == 3 ) {2 |; p0 P; K+ }4 q& G! m; n9 Y' B) \
                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2)
" G8 B1 P! O% c7 w. ~                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;1 O! A7 ^( V* j  }. e
                        lowpass_filter[2] = lowpass_filter[1];
! b: e$ q9 q8 q6 F/ P# E; _9 J' \                        lowpass_filter[1] = lowpass_filter[0];0 g" l) a  B5 ?' k, b8 c
                        lowpass_filter[0] = output;
( s: A+ \% z, p/ f5 G! T1 w                } else if( nFilterType == 4 ) {
8 K7 `0 o2 G6 l                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)9 U9 d6 d* y5 k3 d
                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;1 @+ M9 C+ v4 ]( G
                        lowpass_filter[1] = lowpass_filter[0];! w! {( W  u" b7 n, G
                        lowpass_filter[0] = output;
$ \& Z4 z- ?6 h5 F3 t' r! g1 X% L# j                }
9 ~" `4 K2 [. {4 L
7 |7 x& r- [0 ]$ h+ \, t' W#if        0
1 C5 e" Q# J1 V! V1 J: B                // DC惉暘偺僇僢僩7 c; ^  s# t$ Z: Y  ~
                {
5 e; W! m9 M% R( s                static double ave = 0.0, max=0.0, min=0.0;2 P- g7 R9 c3 D) _: N9 d, R3 `! x
                double delta;: T& B) v1 F" J( N1 j# t' a7 x
                delta = (max-min)/32768.0;8 U( t3 {+ u; c  |7 o0 l
                max -= delta;
+ f% P) M2 b" g: O; v! J! \                min += delta;. x: ~" U  B; }# G9 ~0 x
                if( output > max ) max = output;
0 W! G! U0 n/ e( j5 Z- }( K                if( output < min ) min = output;
, ^7 p: G' L% G1 l0 G                ave -= ave/1024.0;9 h7 k1 J9 @% X4 B$ C; T/ O1 i
                ave += (max+min)/2048.0;: w* E; @7 E) D9 U
                output -= (INT)ave;# \$ [( Q$ y! Z6 B
                }
) m" d9 I1 o* t#endif7 A1 m) U3 d* W, V
#if        1( l2 G. {7 \6 |8 O/ J+ H& y0 [& [
                // DC惉暘偺僇僢僩(HPF TEST)
( w) {# E! D, ?9 ~8 }                {, B3 j+ Z/ j/ }1 F, F3 E
//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);+ P9 G4 s7 [' J& Y, h& W
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
* q% x+ [- _' H9 d                double        cutoff = cutofftemp/(double)Config.sound.nRate;
$ P2 k7 K! [- o7 O                static        double        tmp = 0.0;
' f& a1 V+ g3 i# C                double        in, out;
& s( v8 y, i9 e" A6 O) V0 w) C2 g; h9 E' d# A( `5 u, C
                in = (double)output;
8 K7 R& h. H  ^( q8 a                out = (in - tmp);5 E- c  Y4 `* p2 h& [
                tmp = tmp + cutoff * out;: b8 A( r' @: Z7 |% w
) a9 M- U1 H+ K; {
                output = (INT)out;, W* }2 s9 |2 U" t9 a: R
                }( ?$ T3 a: n: N5 X! e
#endif
5 c5 E7 @  n; H& [. }$ a#if        0, [# Y* S: t9 q+ G
                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)
. [4 g& p) r" w: ]$ `                {* N- `2 \2 j2 t* [: |6 M3 N& Q
                INT        diff = abs(output-last_data);7 ?6 a: M- M! z/ g! d
                if( diff > 0x4000 ) {
7 B  G$ ^# H6 P5 W' Q3 ~                        output /= 4;& Z( C3 \# Q& j& I! e  \  h
                } else / U4 K3 y" g( T2 Q) }' N- k' P# V% H  `
                if( diff > 0x3000 ) {
" |0 Y8 ^2 N+ B# X% G/ Z) Z3 M( d6 T                        output /= 3;  E: l& f/ p/ _- |$ v
                } else
& d& a% ^) r7 v                if( diff > 0x2000 ) {
" A6 B8 ]+ a0 J/ I+ O2 G5 N! d) D                        output /= 2;7 R" Z0 b8 M0 F7 u4 s+ ]
                }
1 K# _/ `# W: i4 u1 `* [9 C                last_data = output;/ v) @- o3 m7 Q' A
                }
- V- Q9 ~& l3 M, {#endif+ Y$ b: `+ x: Z& ?  G% j) C
                // Limit( w, c6 B  b+ K3 i1 }5 y
                if( output > 0x7FFF ) {, ~5 O$ t9 R2 B( }3 Z/ X
                        output = 0x7FFF;
  I# F2 }1 ~( j( r0 ?+ N) U& l                } else if( output < -0x8000 ) {% ?9 m5 [! b. W6 S
                        output = -0x8000;
& j7 I# |4 O6 Q8 B$ w                }) B3 {' D: i) t7 l1 P
8 l, n" A* Q# |
                if( nBits != 8 ) {
" D1 h. |- n$ r8 N6 r. W                        *(SHORT*)lpBuffer = (SHORT)output;1 {+ N/ s  w$ J# P
                        lpBuffer += sizeof(SHORT);7 }4 a7 e; N) Z
                } else {/ m$ ]" ~  T0 U. L* ^7 {% P1 f% R
                        *lpBuffer++ = (output>>8)^0x80;
7 f% d1 t- c% O" ~5 P+ a# Y  N                }2 _" m8 E4 G( B7 z- b% Y

5 J8 m2 r3 W$ K; U' ?, R                if( nCcount < 0x0100 )
1 O9 S/ c9 |. X9 p4 ]                        pSoundBuf[nCcount++] = (SHORT)output;6 l# e" V. d" ~) [; e

/ A& x: l% {$ i//                elapsedtime += cycle_rate;' W6 v! W4 z2 c% V! e: g/ U7 ]
                elapsed_time += cycle_rate;
- z( M% D* Q5 }* ?+ ?* P1 d5 P        }/ p0 ]* w7 m' a; y
0 K" {) w. T5 w6 M6 E& _/ ]) X; z
#if        1) D9 s7 {# K: r1 c( j& x
        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {
( t9 O4 j# I  R5 l# Z3 {                elapsed_time = nes->cpu->GetTotalCycles();3 z5 l( j* d# Z  `8 A- Y4 }
        }4 B# w7 S# Z1 q( Z4 s9 I! D5 u2 M
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {6 g, t8 @) T3 _" o$ u7 c4 x
                elapsed_time = nes->cpu->GetTotalCycles();
$ a" X- I$ ]4 @        }, a2 m1 C! ~3 Y' k0 K' P! Y
#else
, w8 \% h4 Y* e        elapsed_time = nes->cpu->GetTotalCycles();5 d' P3 P# P& W- g4 h
#endif* S7 D1 Z0 {" J6 Q
}
" n$ K% x. G! l, {: G! d# R/ f$ x. j" o
// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)' t% N9 w. p. F5 R' M9 y
INT        APU::GetChannelFrequency( INT no )
. J, q5 c$ ^  U" g: G, m{( L  W1 _7 \  ^% g6 M7 t6 ?2 T1 F
        if( !m_bMute[0] )
# V$ ~& y- i8 u$ A% s                return        0;( y' N- O8 s' A! T( d) Y* z
6 z! L- Q- K1 o: j: M) I
        // Internal: g! B0 R6 f5 b& o1 T, |. r; j
        if( no < 5 ) {
3 ?2 y+ A: ~% h2 X. d$ V/ s7 f$ X8 h                return        m_bMute[no+1]?internal.GetFreq( no ):0;+ J/ a1 c3 g/ X& o6 j% U1 `8 Q
        }" [! ?* G! p4 o. K% O
        // VRC6: a4 s. |/ g2 v
        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; [% A6 [3 r1 S  ~
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;6 Y/ D; w* L: t' p
        }
1 M# n5 i4 L2 \/ f3 ]  j        // FDS9 I4 Z% L/ z: G+ c# D/ m; O
        if( (exsound_select & 0x04) && no == 0x300 ) {& G) l. e! g7 \' s! H3 i% D' `
                return        m_bMute[6]?fds.GetFreq( 0 ):0;$ {; @! J$ O" V5 t1 o$ @* `3 [
        }
2 O2 ^/ f* ?  m+ ^/ k        // MMC5- S; C4 x* e4 t. y# h! b; _. y
        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
# C- |4 h2 z' R1 k) K4 ], c' U6 u                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;1 u' V2 S! \/ b! O9 |, U
        }
$ v( w3 f+ L; @) A3 g1 y) S        // N106, M4 p  M9 A9 Q9 m0 n& x
        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {) }- x& J+ \9 a  u. m
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;2 ?) C) F, x. l7 \
        }
/ u3 r) u' I8 }& x" ?. a% H        // FME72 |5 k3 Y3 q( u- i
        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {3 V) E. O" f* j: L$ E; j: J5 l
                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;
, k% }  W+ u5 w3 ]2 v9 k+ `        }
: [, ?0 P/ J0 Y0 @2 \1 c5 ]        // VRC7, X0 J, l$ T. ?- Y
        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {
5 A" ]- X0 ^1 C) n9 [# ?: }                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
  V; X; A! S8 o" H        }5 |  `6 O+ c* f0 }  y
        return        0;6 Q1 z. M- Z6 p, k7 W
}
7 b8 @: u% l4 Z; O6 g: C8 T) U* ~, m8 P
// State Save/Load. w9 ^' z2 m. @3 y
void        APU::SaveState( LPBYTE p )4 |( T) F) n2 O0 [9 i+ e$ J
{
: k" O1 Y# R) ?% s) W8 h#ifdef        _DEBUG
' e! @, D* S/ U6 P9 K" |LPBYTE        pold = p;
7 C5 ^2 W6 h0 f- S4 K- M" m  V0 n#endif5 |1 k5 c: \8 Y3 l

9 v2 i& |5 ^4 t2 X" X: ]        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
0 l/ v. E' r; s5 @        QueueFlush();
  u- V, X, J5 r! Z0 d( y9 ~
1 |4 [2 k. Y2 D( [. |6 y  z        internal.SaveState( p );& O1 C9 ^7 K! c4 g/ d
        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
; v- i: M$ `, t9 X; x& b1 J, C, r4 F0 ~$ ~% j4 w
        // VRC6
" Q8 y. ]' x8 W: w/ ]        if( exsound_select & 0x01 ) {+ Y- G4 |  u$ O8 _+ v" Q4 r
                vrc6.SaveState( p );
9 \- k7 ]( u3 c) ?# Q( [" p+ n/ O                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding1 \: B' B' b& \
        }5 r1 u7 n2 I1 u! N" C
        // VRC7 (not support)
. O% }" k" D0 V        if( exsound_select & 0x02 ) {
) z# B, o1 b. F; Q% r                vrc7.SaveState( p );
4 N) s& B: G% c9 i4 j( C                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding+ I4 U* \- L) v! _# p. |/ t8 W4 c
        }% y) V# n1 T; N% v; t. |6 `' Q: ]
        // FDS2 \: k1 z3 q' [
        if( exsound_select & 0x04 ) {
$ I' F! Z6 h# T0 N4 O5 y& c                fds.SaveState( p );
. w% t. I' V5 j6 Q4 k7 b                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
" E2 B' q4 O0 h; K        }
+ r( ], D+ \) w& u  v        // MMC53 m1 R  ?& b* N3 @1 @: @, C% s. J2 q
        if( exsound_select & 0x08 ) {# Z% B. j  \0 e8 D6 A
                mmc5.SaveState( p );
7 N& A; n( t& {: N. g4 V' q                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
7 \5 e$ v; \& \( ~- c5 M+ T        }, n" q/ Z+ S4 H0 f% B
        // N106+ N2 C7 @# Z; N( t9 b
        if( exsound_select & 0x10 ) {, S: j+ G7 u1 K! w( ?# ^
                n106.SaveState( p );
! O/ h' X3 L) o; \; g                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
( I$ s1 |. K  d  P- U        }
, t1 I' i4 N3 ~. {  F( T        // FME74 M$ k: E7 F+ Y
        if( exsound_select & 0x20 ) {( _: ?. m+ E2 K4 R, m
                fme7.SaveState( p );
: O- E+ L# l; z' U4 s                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding2 @' Q2 n/ i8 Q2 L8 Z. O
        }6 o  ?' X& e9 R9 O% C6 E, F

3 `. s& r  }' c+ @: \$ b& i) U+ a#ifdef        _DEBUG# [; T+ `0 K0 [5 h' L8 d) L
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
! z( J0 D4 a' V8 o#endif. q5 f9 e4 m6 w
}
! S2 a1 j- A4 z! y2 p' I, s
; f& |/ k. t% v6 u9 hvoid        APU::LoadState( LPBYTE p )
1 |2 V! _  K' [/ a5 M; ]{% t& A6 Q8 X3 f8 N' u* k
        // 帪娫幉傪摨婜偝偣傞堊偵徚偡  k: |! S6 G! T3 l) c( I
        QueueClear();
0 \' G1 N! |' _: j" k' ^2 b; j) S% O  o7 F/ n8 @
        internal.LoadState( p );
2 F8 i' k2 a; Z" O' N1 _/ K        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
6 k7 x& X  C( @1 V* V- g. |( L( T
% W: w/ \9 v5 p        // VRC6
# T- u) A/ ?: B        if( exsound_select & 0x01 ) {/ @$ k6 j8 ?9 \7 y4 y; b. s
                vrc6.LoadState( p );  O9 c, p2 u' e0 m
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding
5 v# X0 g& h. J0 [& M4 q: f        }
: ?8 }2 ^& c8 _5 E        // VRC7 (not support)
. `! T4 e- x; p! q& v        if( exsound_select & 0x02 ) {1 m6 o' @9 I) u. i' L# A
                vrc7.LoadState( p );
6 R+ U6 q; u! p                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding
; m& c5 n4 |/ }2 Z6 a2 C( U        }* _( [& q& ]/ ~1 L! B0 G
        // FDS1 x' P$ v. L4 F& N$ N
        if( exsound_select & 0x04 ) {
: i: P! j. \. s* x( m: E# E' |' B                fds.LoadState( p );
, g, d/ e8 {8 @% I                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding7 s# N6 V3 f$ ~) `+ A7 l0 Q
        }  B' _+ F" L' n
        // MMC5  [* {0 p" b( X+ b
        if( exsound_select & 0x08 ) {) F& L% Z0 X) _* l8 g6 F! l% M
                mmc5.LoadState( p );
1 F6 N* k, ~. [                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding' N& t( F" u9 q" ~, E2 H
        }1 Q# M1 s0 u7 t$ n0 H! v
        // N106
: g8 \) K1 f: r- M: T6 x        if( exsound_select & 0x10 ) {
1 Y) p: x, [+ M, {: _                n106.LoadState( p );
& p: a+ x9 T' {) R4 ~, h                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
8 C+ s0 y! }# |; P8 p" _0 @# v        }
7 |. C* b- S$ H9 e        // FME7* t* \- B4 q# g
        if( exsound_select & 0x20 ) {$ S1 z4 L# U0 ?8 G+ v2 H/ l. D* o
                fme7.LoadState( p );
0 j9 G) {: ]! I1 O' i# e                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
- g) o2 |2 F# G+ Q5 {) x( s! ]        }# K% G, w' R! N
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 3 O  v4 q  I4 T" T6 d
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 s! G7 L! V4 V
感激不尽~~

2 S. T7 ]# \2 o  y恩 我對模擬器不是很有研究,
5 {' G3 U* ^" I; w, C" s雖然要了解源碼內容,可能不是很困難,1 p  `+ s0 U# E5 [
不過還是要花時間,個人目前蠻忙碌的。
0 X4 N5 o! ?7 E. [. ~
/ X7 N1 ~2 _: D9 ?4 y5 k; b6 S給你一個朋友的MSN,你可以跟他討論看看," P# M) N( m. f7 Q. f
他本身是程式設計師,也對FC模擬器很有興趣。
) r# {' C2 ]( Z/ o! V, G& Z  _, E' s0 m6 F9 a* {" T
MSN我就PM到你的信箱了。
9 T0 r+ [1 f' b4 J' G6 ^2 n* X: R+ S, h  Y9 K% l9 ^: v6 C3 _
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表 9 |4 q5 s: C# j8 r) b7 v  X
呵…… 谢过团长大人~~

0 }4 X4 e2 P9 |9 a
$ L5 h. E/ E$ p1 m2 f+ m7 Q哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 3 y7 Q+ @& f: @6 z/ F- D
团长的朋友都是神,那团长就是神的boss。
; z& B$ F% ^% Z" k
哈 不敢當,我只是個平凡人,
# Y; C* c" m$ x2 n5 ]# Y* B* \要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙6 n6 B1 m/ }+ ^# m# ?  }
ZYH
- x& i6 L4 A3 N. O% T; B0 MQQ:414734306$ d& i6 g# s3 A$ x
Mail:zyh-01@126.com5 d* p- }, @" [( q4 S2 z, K
5 L  z  k7 t% d- \. N
他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表
2 L( b' J4 R8 x) p; r再次对团长大人和悠悠哥的无私帮助表示感谢~~

# {) X. D: q8 l; p/ a3 ^1 Y不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2025-12-7 09:01 , Processed in 1.092774 second(s), 19 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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