EMU618社区

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

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

 关闭 [复制链接]

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 09:56:34 | 显示全部楼层
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
6 {' b& t; y; Y* N, [, o, N楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~
, s6 f. }' R7 ]* F; z$ ]这里有相应的模拟器源码,就当送给大侠了~~
5 g4 M+ V. V/ J7 [- d) Z  ihttp://kenkao.qupan.com/5096520.html

该用户从未签到

发表于 2009-11-8 11:31:10 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 09:56 发表 : l' R5 q  s7 @# ?5 ~
能否再详细一些呢?本人比较熟悉上层的编程思想,但对于NES的底层算法机制基本是彻头彻尾的外行。
; z& K% R/ |! a8 ^9 R; {楼上的大侠可否帮我准确定位一下,是哪个.cpp文件中的哪个函数,感激不尽~~3 l' [' G0 T9 A! K3 d  a
这里有相应的模拟器源码,就当送给大侠 ...
5 _$ p+ n5 o/ Z8 K& N& e
聲音部分(Audoi Process Unit = APU):2 v' U& r2 m0 S: o: @  a
.\NES\APU.cpp$ G  ^2 s  x4 t3 e
.\NES\APU.h4 e  j7 S6 [1 Y; I

" r! b: I$ a( ]) m
3 j5 O3 G0 T- v8 U, H1 t- p影像處理部份(Picture Processing Unit = PPU):
. R; y) R* [" M* R2 t.\NES\PPU.cpp6 ~$ T9 w' g6 f# M! ^
.\NES\PPU.h4 I% e2 W7 G& T( @8 F% n+ G

7 x; ^* H0 I; K) v: c) H5 x! ~如果原碼用C跟ASM混搭也不錯

该用户从未签到

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

该用户从未签到

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

该用户从未签到

 楼主| 发表于 2009-11-8 14:47:50 | 显示全部楼层
这是我手中源码Apu.cpp的内容,敬请赐教:
6 `2 _, k; K* t. D% F' R(由于很多专用术语和算法机理都不明白,所以看不大懂……)4 _' m! g0 ?( g* u, l+ \- t' }
//////////////////////////////////////////////////////////////////////////
; g3 c* h: u6 Q//                                                                      //
; E/ ^, i  ~$ K( P8 h//      NES APU core                                                    //8 i) |. e( Z2 u" V  H0 i
//                                                           Norix      //& }/ J- s; I/ t4 @2 K" [
//                                               written     2002/06/27 //
) Q& _0 m4 _" J: v2 B  h//                                               last modify ----/--/-- //. t& j6 l1 ]$ O- ]9 h- G
//////////////////////////////////////////////////////////////////////////
4 G: D3 c" Z; v2 e* ~+ F  \#include "DebugOut.h"4 c* q0 ?4 x7 D
#include "App.h"! k& d3 O4 i0 z  o' [) f& A
#include "Config.h"
; l& b) L! p" Z9 D1 _/ X# [4 V; G
( T/ l8 f0 p! R$ |0 G1 z& K; ]/ K#include "nes.h"
6 l! [- T2 @7 d: g/ Y#include "mmu.h"
" {9 j% X# r4 {0 ~1 q  Z3 f0 m$ U2 u#include "cpu.h"7 Z! u, J: l( }( l7 ?6 a8 Y) [  _
#include "ppu.h"+ S- b# r# e  h& B
#include "rom.h"
; l0 }0 I7 h' c$ E8 O' w' G#include "apu.h"
5 P6 h2 ^! e. N' \. @. Z# I. L; V
// Volume adjust4 l- q+ M% j9 C5 Z5 N9 {7 E
// Internal sounds1 U, _- ^* z( `$ h2 {' p
#define        RECTANGLE_VOL        (0x0F0)( M/ L. n# A& R1 n
#define        TRIANGLE_VOL        (0x130); V. x1 ?& g8 n& H
#define        NOISE_VOL        (0x0C0)8 b' W3 t2 M6 @
#define        DPCM_VOL        (0x0F0)
' t9 U. a3 ]6 c, L. I1 x) {// Extra sounds2 H% X: B: o: s& C
#define        VRC6_VOL        (0x0F0)
3 N8 z7 F6 f. K#define        VRC7_VOL        (0x130)
/ i1 t& k+ ~5 ?6 l7 c. j. S#define        FDS_VOL                (0x0F0); n4 \' ?/ _/ N! T
#define        MMC5_VOL        (0x0F0)9 e# E$ v& n2 N+ F) v! ?
#define        N106_VOL        (0x088)) y& E% ?8 d+ ?+ v/ h5 g
#define        FME7_VOL        (0x130)
! E. c7 p' N* V% y) Y7 j1 g6 e0 [3 }) i9 t+ O
APU::APU( NES* parent )5 ?) v$ I! Z2 q1 c1 {& M2 a  Y
{5 ^7 X; {: L; B. p1 N8 }
        exsound_select = 0;
! `: l/ K" y- @6 Q' |# G
2 V; g+ r! v$ v* E+ F* t* P        nes = parent;
7 f( I# _1 s4 D' N1 a        internal.SetParent( parent );3 c" p; ^8 n! |: {

9 ?! s2 t, @- y# B        last_data = last_diff = 0;
+ `! Z7 M0 ~  @; D2 s
" H+ H1 j+ ~6 W! P* e3 X& N        ZEROMEMORY( m_SoundBuffer, sizeof(m_SoundBuffer) );
. F9 _; q% W8 t3 Q
% B7 N) k7 r8 m        ZEROMEMORY( lowpass_filter, sizeof(lowpass_filter) );9 C0 h4 a8 E9 M4 D  A+ I
        ZEROMEMORY( &queue, sizeof(queue) );
% j$ s' u% l+ x        ZEROMEMORY( &exqueue, sizeof(exqueue) );
5 m3 i: O$ N; X* r" o1 K, S$ {% K! l9 K
        for( INT i = 0; i < 16; i++ ) {
" t9 t+ g* S4 n3 E                m_bMute = TRUE;
. b' j2 \$ s, y/ z        }
+ b- I) s; ^: k# ^+ x3 ~, g& {}1 g( j9 F% D1 A. N) D
$ Y" j8 V1 y: j5 D/ |4 y9 }5 M
APU::~APU()
) x( Y' B+ t6 ?6 y$ G8 \  W3 x' k{
. [; f7 c, a, C: ]2 P}
4 p5 p# q/ Q' q: ]7 ^! D* i, |" p: _0 Q8 X' j7 X# ]2 ^
void        APU::SetQueue( INT writetime, WORD addr, BYTE data )
+ M$ G& g+ Z) o1 {  L' n' e; {{
& f. N! ]" f! W. W" r. M4 D8 }        queue.data[queue.wrptr].time = writetime;
0 A7 [4 T) F) x        queue.data[queue.wrptr].addr = addr;
  h; g, O- |: j; c; u        queue.data[queue.wrptr].data = data;% X* T4 U: x/ n* T
        queue.wrptr++;
' c, q: W' P) v# |& n$ M        queue.wrptr&=QUEUE_LENGTH-1;
7 [: g3 t) O# |! X  A; q9 o        if( queue.wrptr == queue.rdptr ) {
7 X) |9 q( E! @- e. W                DEBUGOUT( "queue overflow.\n" );
/ F4 O: f/ C/ y- e        }
; _+ O, {+ d& \}
" c+ I: Q6 ?0 u2 s
. l) J3 s5 y9 _4 A' i7 h: g3 XBOOL        APU::GetQueue( INT writetime, QUEUEDATA& ret )* U9 i" {+ ?5 `! \8 q
{5 Z4 p! V+ m9 ~7 q7 W/ T6 S
        if( queue.wrptr == queue.rdptr ) {) P/ |! |; }, X; X2 a8 a1 z6 ]5 |# k
                return        FALSE;
' R+ f/ Z, s1 l4 [- s7 P1 K0 H        }
8 A, ]7 X/ P; |* E+ _4 }% g        if( queue.data[queue.rdptr].time <= writetime ) {
" q( R* m' p! t$ d- K                ret = queue.data[queue.rdptr];  P; [' {$ D. X' u# n1 x
                queue.rdptr++;
8 t2 u9 I. M0 P                queue.rdptr&=QUEUE_LENGTH-1;
0 d: b1 T! u, e( J5 u3 O9 p                return        TRUE;7 e0 e2 }1 I/ M  T- O& N
        }9 A' i; ^7 V9 H3 }: r
        return        FALSE;1 q; ?! K- C% X) k3 H
}; ?) E) @: l' q) E$ k" \3 l

  l+ C+ m/ m5 }" M/ B7 u7 `void        APU::SetExQueue( INT writetime, WORD addr, BYTE data ); U# Z% p' M$ T
{
* B- P0 w6 n! T% j7 W; C( V        exqueue.data[exqueue.wrptr].time = writetime;( h7 @* `+ ]. P1 q
        exqueue.data[exqueue.wrptr].addr = addr;; P9 l2 ^+ K& G  l
        exqueue.data[exqueue.wrptr].data = data;
- h* J! p6 s! j" K        exqueue.wrptr++;
$ Y  V4 ?) N; V% W" k        exqueue.wrptr&=QUEUE_LENGTH-1;1 M) Z# I& n# Z4 M
        if( exqueue.wrptr == exqueue.rdptr ) {+ u7 H, N- _3 N* T% _; Z9 K& P
                DEBUGOUT( "exqueue overflow.\n" );; m' x. i, Z" n/ F6 j
        }
2 [& k1 E; }" H2 T% p}$ {6 K5 R* |5 _1 h7 l
; \* @/ u6 R- V% l
BOOL        APU::GetExQueue( INT writetime, QUEUEDATA& ret )
; O+ ^" x4 D- I& m* ^- Y{
' Y/ m9 `; z9 X1 d        if( exqueue.wrptr == exqueue.rdptr ) {8 w5 `# I! ~  {( e2 M7 Z1 |
                return        FALSE;3 f: D4 J; d8 c" _1 g
        }; u1 r- u) Z7 F% `( s# p1 G
        if( exqueue.data[exqueue.rdptr].time <= writetime ) {# ]2 Q( h: A' z( `
                ret = exqueue.data[exqueue.rdptr];
7 O2 U5 A5 I) _& M: P! P5 s                exqueue.rdptr++;& R& l1 v  c3 {- D# u
                exqueue.rdptr&=QUEUE_LENGTH-1;0 C; h& H0 B" U. n% b' h/ `
                return        TRUE;
2 U  K/ P0 E) p4 s! ?4 {( T3 ~% B        }3 a6 B) P- W- i& m
        return        FALSE;5 b# `9 v& i6 I' j  ]5 B) W
}
0 M: |. a; ^$ F( D1 B5 F, M; t3 k
( T' @" }9 K8 _% }0 v( z9 gvoid        APU::QueueClear()) Y9 Z& p4 K7 H& W4 h# ^
{5 c0 |' U$ \' }
        ZEROMEMORY( &queue, sizeof(queue) );
, Y% ]- l9 \9 p. s- Y        ZEROMEMORY( &exqueue, sizeof(exqueue) );
& W5 G  e5 i4 m4 X; N  _4 h7 n}; J" U# y* ~3 H. M  J; w7 r
% Y( |% `" P. L9 t( k4 ]
void        APU::QueueFlush()+ j. X! M( I4 ?
{& z! @, J- F- f: j3 K: _
        while( queue.wrptr != queue.rdptr ) {
8 n0 F% M7 P! x( N# e1 u                WriteProcess( queue.data[queue.rdptr].addr, queue.data[queue.rdptr].data );
* W# F4 E& x' A+ G1 A) V* s                queue.rdptr++;: b" X" B: Z) m
                queue.rdptr&=QUEUE_LENGTH-1;7 V) `  b* V: _. P, ?5 z6 V1 }
        }
1 d$ u% s7 L; U' [# {6 ?& \: v4 ^) ~
        while( exqueue.wrptr != exqueue.rdptr ) {
! _2 r. X7 r7 h                WriteExProcess( exqueue.data[exqueue.rdptr].addr, exqueue.data[exqueue.rdptr].data );
$ v) o& t" ^, P' T5 L, ]                exqueue.rdptr++;" w" u5 ~6 z' h1 d# V. G8 J, U
                exqueue.rdptr&=QUEUE_LENGTH-1;$ x) t/ b" k8 \. \5 R
        }8 m$ V; a0 i7 n% ^8 J
}- d8 t: ]- u  G! g( h/ ]
) M; E( {1 g" R% d5 {4 h$ u. [
void        APU::SoundSetup()' h- Y- N  T& w2 ]
{
; l4 Q/ O2 W$ x' o; @  s% E        FLOAT        fClock = nes->nescfg->CpuClock;
) d5 _: {* V- Z! Y# c; Z        INT        nRate = (INT)Config.sound.nRate;$ S+ o) V' d* Y2 {2 Q. ^
        internal.Setup( fClock, nRate );
- Z5 k( ]$ w* D* S: Y/ i1 G7 S  v        vrc6.Setup( fClock, nRate );
' s2 L' g) M) l& s4 D. K" a+ F* o  x        vrc7.Setup( fClock, nRate );' K1 Z) R) `: E: c% m
        mmc5.Setup( fClock, nRate );
8 v5 i# N$ A' h" j        fds.Setup ( fClock, nRate );
8 a. [. @  C1 t+ F        n106.Setup( fClock, nRate );
* d8 g( O8 O' G* h$ ]/ H        fme7.Setup( fClock, nRate );
# U* b& \. T7 \}' ]) l3 }  T8 t: L

, C; B  m9 r3 n+ A/ U% I  tvoid        APU::Reset()
; T5 N5 I* R9 v$ a! Y5 D  m6 h{7 U6 [) U9 w: W7 O% v" l4 t
        ZEROMEMORY( &queue, sizeof(queue) );
3 a4 K. L5 y5 {# k4 H8 T! |% r        ZEROMEMORY( &exqueue, sizeof(exqueue) );
* P& B% }' |- g; J, k% z# {! t3 z/ @
        elapsed_time = 0;
- I( d6 d, k6 H6 {1 Z, d
2 T) T' t2 K, V8 S' a" e        FLOAT        fClock = nes->nescfg->CpuClock;
5 O& I4 f$ Z- q, @% K' d        INT        nRate = (INT)Config.sound.nRate;4 b: ?) b  y) \! L$ e6 ?
        internal.Reset( fClock, nRate );
; j# _  K$ d$ t; R  a: D        vrc6.Reset( fClock, nRate );
& o9 ]7 U* o6 d3 F/ w        vrc7.Reset( fClock, nRate );! B- S" ?, f% {4 D- U5 v
        mmc5.Reset( fClock, nRate );
' W& ]% h- F2 C. F5 e        fds.Reset ( fClock, nRate );+ O$ d! \8 X- o6 D1 j
        n106.Reset( fClock, nRate );" P2 o8 }0 z: i7 g  \
        fme7.Reset( fClock, nRate );4 u6 n) u" W3 t( w6 y& U
3 ]4 V- ?' }" R  a9 B2 I; ^
        SoundSetup();9 h. A* M- `2 Z% z9 J" z
}" w# H0 B- Y, a8 X, l/ r
  s. K: Y0 i/ U* o
void        APU::SelectExSound( BYTE data )
! k. N; T- V8 B+ b% v{
# g: R. b1 w- U% S5 Z6 F) H0 m9 V" p        exsound_select = data;; X& K+ @3 ?" Q- ]  r, A' \8 S
}' R, D' Y. ?; K3 n. b! m

- K+ Q+ b4 B3 E( cBYTE        APU::Read( WORD addr )8 `$ X' h8 ?  _1 }: [- \0 ]- X
{5 |" d; [! ?8 U9 J; h
        return        internal.SyncRead( addr );8 `8 R7 p* ?7 L" E0 ~/ S
}
" X, x) R4 ?) ?& r2 v& `' k1 u( S; d$ |$ c
void        APU::Write( WORD addr, BYTE data )0 r. g  q8 t* Z; O, g! K+ d( Q
{/ l3 r1 ]" s7 @
        // $4018偼VirtuaNES屌桳億乕僩
9 o  o" g* r( T4 q, v. w        if( addr >= 0x4000 && addr <= 0x401F ) {) t" `% S9 X# e
                internal.SyncWrite( addr, data );3 P' t4 A# g0 g! M2 |% p1 K/ ]
                SetQueue( nes->cpu->GetTotalCycles(), addr, data );3 d" \6 T; u- p7 f+ Y* p; r2 Z
        }  \, X2 e2 @  N8 J
}3 y1 l5 [$ ]3 t4 j5 c, f
1 N9 j) E5 D( L
BYTE        APU::ExRead( WORD addr )
. D* q; H0 {5 m: Q+ T{" Q! _* ?4 J7 Z7 H) c' G6 ]9 J2 ]
BYTE        data = 0;
( q: z- ^8 k3 `1 C; ?0 m6 ?% u
; M3 F1 M' f+ a( y6 V! }        if( exsound_select & 0x10 ) {" V6 G. P' Q% i1 y/ P2 {9 U# W
                if( addr == 0x4800 ) {
* [2 F4 h- }4 l% t                        SetExQueue( nes->cpu->GetTotalCycles(), 0, 0 );' }7 K7 O5 p+ a" r/ F+ a4 r
                }
, y* G$ x9 }6 i, H        }
' {3 ]# f8 a9 Q+ k$ \5 n# Z        if( exsound_select & 0x04 ) {( ~: [  C2 {2 e+ T4 K- U2 B
                if( addr >= 0x4040 && addr < 0x4100 ) {
3 d  r& v( N& y7 x  i/ p/ {  a                        data = fds.SyncRead( addr );
/ K0 x* v- j9 v- M4 Z6 t/ r0 ]& R7 ?5 \                }
5 J6 ~) C! i6 S. R% W        }
0 Y, Y; [+ Q: r# n, u        if( exsound_select & 0x08 ) {& F0 ]- e) b. \9 Q' C9 h( g
                if( addr >= 0x5000 && addr <= 0x5015 ) {
3 t# F0 v# ?5 Y# M! l9 ~& ^& F; \5 v% L0 g                        data = mmc5.SyncRead( addr );
: d' {4 ~! M) Z  m" @                }
( F* w2 u; \, s1 P4 q, E; S* p! k, _        }' n+ M  f* K" o2 g3 T% b1 T0 x
6 N* T' X5 t. y
        return        data;  N8 n3 _& }! W- I% [
}
! I  @* W  M, e6 I/ q( S& @! K
4 R  R9 m: d5 J. @* n/ W  yvoid        APU::ExWrite( WORD addr, BYTE data )
  x, k- ]- N5 l" o{8 ?, r* R6 K2 o6 a' ]; V
        SetExQueue( nes->cpu->GetTotalCycles(), addr, data );, f- y" x9 h$ ?; _" J; {
9 w; m8 f& a/ y2 i: Q% O
        if( exsound_select & 0x04 ) {
7 Y$ g: |: T7 y2 a7 i; i+ f                if( addr >= 0x4040 && addr < 0x4100 ) {' U  i  _, h* B2 _- o$ c6 w
                        fds.SyncWrite( addr, data );6 b2 W% V" b) k
                }2 o) _( P; Y5 d5 q- A- ~
        }4 A0 {( o% T7 [6 o9 M; h
5 \1 n9 o% ?  g
        if( exsound_select & 0x08 ) {
% C6 v$ X* B; [" n0 o                if( addr >= 0x5000 && addr <= 0x5015 ) {
: [" F7 p. w" b* }( A% q* }                        mmc5.SyncWrite( addr, data );/ G7 [# g& v3 v! U7 {; v; T+ o
                }
) A4 |, @$ U2 m        }
* r# d% p" c- o$ I% t9 p}) e# t' |! I# W4 J

& A! l% m5 j2 q$ Q) g6 Qvoid        APU::Sync()* Q& F$ ^9 T) R6 s' e4 O6 S
{: J8 ]9 o) T/ i- |* K! Y  @# \
}! [  Z8 O/ k+ q; ?6 n4 c
  o& [. M% E( B9 A. X$ ?
void        APU::SyncDPCM( INT cycles )! W; b" ]8 i" U- o% n5 m3 W) P7 U& t, ]
{
0 T* A: c* l. a        internal.Sync( cycles );1 Q6 ]5 P1 t; c' H- D, {. F

0 `- n* c* `' [6 p" p        if( exsound_select & 0x04 ) {
9 K" n0 z4 j$ T& e1 ]) t. \% {, t                fds.Sync( cycles );: G+ @# o/ q+ r
        }* ?. P) N" r# i! {6 V4 t9 d
        if( exsound_select & 0x08 ) {3 z$ t) }5 w/ y) D3 V! U+ w3 `
                mmc5.Sync( cycles );
+ i( j" ~" q' E- c; Y        }: C  u- m8 j" }. H1 W& [
}! x% C. x& t% h
; p% H9 f. j8 h7 J- S# Q, N5 @1 h  y
void        APU::WriteProcess( WORD addr, BYTE data )4 |& ^; B1 r. a$ m7 R- g
{
& o+ }2 `* J- }, R) `        // $4018偼VirtuaNES屌桳億乕僩" }! \. T3 X9 O6 ?, a+ g
        if( addr >= 0x4000 && addr <= 0x401F ) {
+ E& }1 _( E# Q1 P6 q7 _, l                internal.Write( addr, data );
1 j7 ?  [1 W/ Y$ W# ]        }
9 f1 \; @5 r' {: g}
6 U  s. n% O+ x# Q8 Z: w
. r3 X! s) j+ b& e, uvoid        APU::WriteExProcess( WORD addr, BYTE data )
9 p5 n4 p7 g2 h4 {# c  F{
0 K5 [+ x, ]1 Y& G$ K, Y& g        if( exsound_select & 0x01 ) {
+ D9 |1 D# Z  J8 W9 x' f; ?3 V                vrc6.Write( addr, data );
+ o+ x4 x8 p4 k6 ?+ b8 W" Q( y; Z        }$ u/ d, t* m5 l" S6 L( o% o5 C8 u
        if( exsound_select & 0x02 ) {% f+ K+ e/ v, _3 Y/ `& Q
                vrc7.Write( addr, data );
# n% K8 U1 Q' [+ E& Y+ ^3 u        }. o) B3 \) `; |; V
        if( exsound_select & 0x04 ) {  ?* [* a$ v' k% B6 }3 \
                fds.Write( addr, data );$ L! P( {3 v, S, |6 E. ]5 f/ g
        }
/ s: d7 c. A4 S        if( exsound_select & 0x08 ) {# p0 t: C6 ?: I7 a) i- ]* _' @
                mmc5.Write( addr, data );; u; f% B0 i% c% X% J
        }
) N/ J1 X0 h+ l+ W, L        if( exsound_select & 0x10 ) {; K, m( K  ]2 K; M* M& s
                if( addr == 0x0000 ) {! {4 \8 P$ a' w: ~6 a" H' O
                        BYTE        dummy = n106.Read( addr );- a$ V9 `6 Z7 t
                } else {
1 j$ y5 ?6 t# c                        n106.Write( addr, data );
- G" p% L2 }- @) i( |7 n                }
: C, y( g) u+ O; N  \        }
" G0 H3 A8 X. ^2 w" H$ I6 k& w# f        if( exsound_select & 0x20 ) {9 s: k+ W8 c: n8 j  Z0 W5 l7 R
                fme7.Write( addr, data );. s" `& z3 ]) [; w/ p( r! C
        }- k; ]3 K+ P" d
}
! G9 H; s) ^& s! O* \
* C) J, |) }) A; |* Fvoid        APU::Process( LPBYTE lpBuffer, DWORD dwSize )
$ ~& R# H' I; D3 r{% {/ G- f* |, l* s  r
INT        nBits = Config.sound.nBits;% l. r. ?, b) t" c4 P+ W$ E1 D
DWORD        dwLength = dwSize / (nBits/8);/ }% @; ^! |  E8 ~5 z
INT        output;
  m7 `3 U1 W- y$ Y6 l. d% kQUEUEDATA q;: @# A2 Z0 F* s: u' D4 E3 ~4 y
DWORD        writetime;7 S  r% P# T4 u8 V8 u: Y  o
# C/ Z8 S) T7 b( O, h$ L; H
LPSHORT        pSoundBuf = m_SoundBuffer;
$ c; S* }: d1 {0 d0 bINT        nCcount = 0;
% ?& ~/ E& M% B6 \+ h, W9 \* V' O' w! Z0 C. a+ _9 V/ T1 v
INT        nFilterType = Config.sound.nFilterType;
9 m( o: g/ {; T! X3 B: O. N( y
2 r: A3 L8 H6 J) s- X        if( !Config.sound.bEnable ) {& {5 V' z; p& _- _- @$ Z8 q) k8 W
                ::FillMemory( lpBuffer, dwSize, (BYTE)(Config.sound.nRate==8?128:0) );+ p3 \0 F. r+ e
                return;
7 @+ _; X# P4 O& E( u% x- _        }. a3 {3 s* A. Z$ B

" z9 B% E  _. P( K' f2 f4 ?        // Volume setup
* O2 g6 K& j4 z3 m2 ]( U. e3 L        //  0:Master
/ j' i7 Q3 v6 ?: Z        //  1:Rectangle 1
: E6 y, y- d; f& W9 @9 K+ ~        //  2:Rectangle 2
% a* y# u. L* m; h# Z1 w        //  3:Triangle7 f7 z7 y# {8 ?% G' z: \. L
        //  4:Noise
8 u+ C7 \/ h* J( i        //  5:DPCM+ {+ x# g7 f( R
        //  6:VRC67 [/ n# B$ z5 c  o/ U
        //  7:VRC7
; g* e8 |: Z, M* O        //  8:FDS
+ P$ o4 f8 S" l" `; y$ t0 l/ {! n        //  9:MMC59 \0 v: J1 h5 ?, i, X; i
        // 10:N106) u' g/ k  x  M0 i1 X+ X
        // 11:FME7
9 Z1 z) i% U) W% N7 |6 T3 I' E        INT        vol[24];1 h9 k$ q' }( w; d( U7 w) r* Z
        BOOL*        bMute = m_bMute;" V- L7 U3 D1 o1 ^8 M( B6 c+ D# B
        SHORT*        nVolume = Config.sound.nVolume;
; K: L! |% D6 l8 x/ D* S0 h* L
: ^- r7 q" m) |* F  S/ W        INT        nMasterVolume = bMute[0]?nVolume[0]:0;
' k3 W# U+ I! ~0 L" m! i) y
5 q, X9 V: e9 V' ~' c6 z        // Internal4 h" s9 Y' m% c
        vol[ 0] = bMute[1]?(RECTANGLE_VOL*nVolume[1]*nMasterVolume)/(100*100):0;* `: U8 |9 N! r! h# F6 j
        vol[ 1] = bMute[2]?(RECTANGLE_VOL*nVolume[2]*nMasterVolume)/(100*100):0;! d& n3 g# Q+ b% Q+ T" Y
        vol[ 2] = bMute[3]?(TRIANGLE_VOL *nVolume[3]*nMasterVolume)/(100*100):0;8 D% t7 \' p9 `/ J& @+ Z8 O
        vol[ 3] = bMute[4]?(NOISE_VOL    *nVolume[4]*nMasterVolume)/(100*100):0;' t& `' z$ H% C6 q" g
        vol[ 4] = bMute[5]?(DPCM_VOL     *nVolume[5]*nMasterVolume)/(100*100):0;& N3 E/ h1 |) B: f; C7 a1 c) I

8 \. _8 \0 Q; _% R! I        // VRC6: ]0 \* u- n* A9 `0 i
        vol[ 5] = bMute[6]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;6 b3 G8 o7 I5 _/ z5 I
        vol[ 6] = bMute[7]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;  ?; }+ E/ ^1 ~
        vol[ 7] = bMute[8]?(VRC6_VOL*nVolume[6]*nMasterVolume)/(100*100):0;
7 A4 a+ F& O2 ?. J; x- S9 k9 ^7 d1 J0 x/ L& T4 L) D3 z
        // VRC70 a# n8 V; \* N4 c' ^8 j# n
        vol[ 8] = bMute[6]?(VRC7_VOL*nVolume[7]*nMasterVolume)/(100*100):0;
( \: J1 _6 `  n2 ]" X* y; ?3 r, X& [, U# ]  ~6 q
        // FDS. F. \1 ?" i, D. o7 q- M( Z2 @; b
        vol[ 9] = bMute[6]?(FDS_VOL*nVolume[8]*nMasterVolume)/(100*100):0;& g( q( t4 `" g6 s4 x5 q2 |
0 m3 k& A. |- n3 C3 }
        // MMC5
- X4 k% W4 a0 y' R, W2 u        vol[10] = bMute[6]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;$ g, z4 W8 q" I/ e8 h) |. S2 a
        vol[11] = bMute[7]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;4 H" }' ]( Q5 x/ G" Y9 K
        vol[12] = bMute[8]?(MMC5_VOL*nVolume[9]*nMasterVolume)/(100*100):0;; C: O7 a; @$ O3 [8 X* r* O- u; m
9 X! \, Y6 Y0 @3 U4 e6 ?
        // N106
% d1 \; ?& `( j" a0 c        vol[13] = bMute[ 6]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. r4 B& x, f6 ?6 \5 x: k        vol[14] = bMute[ 7]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;  W* s) Q" z" P1 d+ U7 [4 Y
        vol[15] = bMute[ 8]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
. `/ [" u" n$ ~9 k8 x        vol[16] = bMute[ 9]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
" W, `5 E) R) N4 M" K& a  O1 S        vol[17] = bMute[10]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
6 ?2 J8 `. o6 X9 P7 z+ k        vol[18] = bMute[11]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;/ L9 b8 l1 d1 u# {
        vol[19] = bMute[12]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
$ x: _) J% z- l; g' }' A0 n        vol[20] = bMute[13]?(N106_VOL*nVolume[10]*nMasterVolume)/(100*100):0;
% J' A& i1 U5 c6 |# e
" I1 b# q! Z* h) O$ g. @3 f4 G5 u        // FME7
, @' Q' p$ r+ G6 m' A        vol[21] = bMute[6]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;  l9 o: y& D' E( n- m' G& C% L! A
        vol[22] = bMute[7]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
0 U* K3 l$ e7 E, @; I        vol[23] = bMute[8]?(FME7_VOL*nVolume[11]*nMasterVolume)/(100*100):0;
3 i3 G0 o& q2 _$ V  s
; h3 [8 @9 N2 ~; @: v//        double        cycle_rate = ((double)FRAME_CYCLES*60.0/12.0)/(double)Config.sound.nRate;
% b: ~) v: ^0 b7 ~# e' S' m        double        cycle_rate = ((double)nes->nescfg->FrameCycles*60.0/12.0)/(double)Config.sound.nRate;7 a! E2 B: H7 U5 L( U
8 Y, w7 l" g1 z. ^; p. T  T
        // CPU僒僀僋儖悢偑儖乕僾偟偰偟傑偭偨帪偺懳嶔張棟+ [4 [2 X7 ^3 g7 Z) V- a. d+ h( @
        if( elapsed_time > nes->cpu->GetTotalCycles() ) {# ?& k1 f7 L: k( O' {% }- e
                QueueFlush();
/ z4 ?% J$ B* B: K: _9 C        }
- e! K- J+ B3 r/ I6 z4 O6 Y2 W+ M( D
        while( dwLength-- ) {$ c1 K( }0 S; p% l
                writetime = (DWORD)elapsed_time;
( K# L3 m# }% l  J& B
# C! f5 o/ i6 U5 n4 T                while( GetQueue( writetime, q ) ) {
. i: F: K9 g+ q" ^% X9 g- x6 v                        WriteProcess( q.addr, q.data );
( w' m7 |% d/ O* X                }
) S8 s$ G, V4 w8 g* X+ b0 W& A4 K5 ?, Z1 F) F  a
                while( GetExQueue( writetime, q ) ) {( A4 Q! t6 ?; _
                        WriteExProcess( q.addr, q.data );
2 V$ {' n0 f+ @1 _7 j  D                }! \5 G* v3 I+ K  ^$ H' _+ i9 s
& T6 ?" Z& i; O3 T0 [+ t, n
                // 0-4:internal 5-7:VRC6 8:VRC7 9:FDS 10-12:MMC5 13-20:N106 21-23:FME77 k% R* ~4 J8 w- S# S
                output = 0;
4 w- O% m: [. x# Y                output += internal.Process( 0 )*vol[0];4 V8 O8 ~* S6 |! W( k! Q0 Q
                output += internal.Process( 1 )*vol[1];
6 z  }' w( }+ c1 v                output += internal.Process( 2 )*vol[2];% @1 A! }& t. p( u
                output += internal.Process( 3 )*vol[3];) R7 c, R2 M! j9 i9 D4 S) }/ y
                output += internal.Process( 4 )*vol[4];
+ d( T) }8 @+ u1 A  T" T- o( A/ O' b" ]5 G" ^7 l; f' E9 x
                if( exsound_select & 0x01 ) {
4 m& |$ _+ V8 e0 v                        output += vrc6.Process( 0 )*vol[5];7 y+ r1 a8 \/ y/ X; z. ~0 _9 J+ @
                        output += vrc6.Process( 1 )*vol[6];* k2 p2 i+ [% E8 N$ U6 F
                        output += vrc6.Process( 2 )*vol[7];
; `0 B1 x9 T, t" E& K                }  s) ?' b2 t* k, Z: Z8 V) e
                if( exsound_select & 0x02 ) {
/ R% y3 u# {8 H& J                        output += vrc7.Process( 0 )*vol[8];
4 M5 f! m' H" {' i7 @6 W                }+ d) l! |1 u. X' R' ]
                if( exsound_select & 0x04 ) {
- ~3 {* a2 h7 F( s                        output += fds.Process( 0 )*vol[9];
, o  J. q; U1 s: ]3 [, c                }1 e& O, O5 Y! I8 D
                if( exsound_select & 0x08 ) {4 y* [2 Z. y  y# ?% e/ |
                        output += mmc5.Process( 0 )*vol[10];
; L7 g/ T" ]4 z0 M4 J+ f                        output += mmc5.Process( 1 )*vol[11];9 r2 K5 d! g5 C. ~/ {
                        output += mmc5.Process( 2 )*vol[12];
6 S# P( `2 X& O. C3 T4 T7 L3 W4 U                }
2 p2 n+ b0 D2 f  z5 `                if( exsound_select & 0x10 ) {
8 m3 o% ~$ X! E3 o                        output += n106.Process( 0 )*vol[13];
4 {1 L4 ]( U) j8 s: _, K' F. x0 F( t                        output += n106.Process( 1 )*vol[14];
; [6 S) m# z6 L" R4 a4 V2 A                        output += n106.Process( 2 )*vol[15];
0 n% K; C& ~( ?( r) e  J, r: Q# Y1 Y6 P                        output += n106.Process( 3 )*vol[16];
- v5 k, K% e% l3 ?( V) W                        output += n106.Process( 4 )*vol[17];0 P3 R0 p5 r$ B
                        output += n106.Process( 5 )*vol[18];
5 Z3 a# `) s  s/ Z                        output += n106.Process( 6 )*vol[19];+ |( H5 j( i7 \
                        output += n106.Process( 7 )*vol[20];8 D2 O5 Z8 Q& n  [/ Y+ A' P7 f
                }
6 {6 [/ h2 n0 n1 j                if( exsound_select & 0x20 ) {
' r; a8 E7 a9 L/ _4 {4 x( b, m                        fme7.Process( 3 );        // Envelope & Noise
" q8 I/ K/ F! g5 K! Y* K                        output += fme7.Process( 0 )*vol[21];2 Z9 W9 i/ M1 E! c) ~! r' F9 P
                        output += fme7.Process( 1 )*vol[22];
5 a$ Y' v8 U3 D% D% m                        output += fme7.Process( 2 )*vol[23];! Y/ c0 k; ^5 w! r, P! a
                }0 E" B/ K) H6 l4 H2 t
, I! O- |5 O, _: Q
                output >>= 8;
. |" v8 _# Q/ h* y/ _
: n( e% |2 {$ R                if( nFilterType == 1 ) {! ~+ u, W4 y8 P0 s  t. L
                        //儘乕僷僗僼傿儖僞乕TYPE 1(Simple)# J# ?4 h/ n- A- @  W; V
                        output = (lowpass_filter[0]+output)/2;" P* s' X2 K  z9 R' O
                        lowpass_filter[0] = output;6 A% l+ R* I4 N
                } else if( nFilterType == 2 ) {- p, x7 U3 h% t7 A' w, j
                        //儘乕僷僗僼傿儖僞乕TYPE 2(Weighted type 1)
& V) J( p: `1 \' p( o                        output = (lowpass_filter[1]+lowpass_filter[0]+output)/3;0 X5 o! @7 K' m% E/ v7 l% i8 d
                        lowpass_filter[1] = lowpass_filter[0];1 o( g) K6 a& e" H9 `+ _9 a7 d
                        lowpass_filter[0] = output;
! i2 D2 o. H. C9 k& [                } else if( nFilterType == 3 ) {
9 F9 u3 r6 j1 f  `                        //儘乕僷僗僼傿儖僞乕TYPE 3(Weighted type 2), d: h% h- A4 i' c2 X, D5 K- n# M
                        output = (lowpass_filter[2]+lowpass_filter[1]+lowpass_filter[0]+output)/4;
) e, C7 X7 J* e: A6 Q1 r                        lowpass_filter[2] = lowpass_filter[1];
& g( g1 S, ?% d% S, S6 W5 ^                        lowpass_filter[1] = lowpass_filter[0];: Q8 @$ [$ Y+ G) a4 z4 F
                        lowpass_filter[0] = output;
( Q$ R; Z: W5 X; ~  b1 ^                } else if( nFilterType == 4 ) {
+ r% x- K" ~+ z4 N9 t. n/ [                        //儘乕僷僗僼傿儖僞乕TYPE 4(Weighted type 3)
4 O+ A! _8 e7 `! V& X                        output = (lowpass_filter[1]+lowpass_filter[0]*2+output)/4;0 E- S& L$ C0 D" x, _* [
                        lowpass_filter[1] = lowpass_filter[0];) P. G9 Y; w+ p3 e
                        lowpass_filter[0] = output;
! z+ Y/ u2 F! L7 [* {3 m                }1 N( K3 T& V5 @
, G* R4 Q! \% o" |( s9 U) S
#if        0" ^' i# n2 ?% {$ T% f) C: H( P
                // DC惉暘偺僇僢僩
, o- f) q- l' S4 O: g" B                {) n3 ~1 C1 a: P& `" H. g
                static double ave = 0.0, max=0.0, min=0.0;
* K7 G. h8 e9 U& T* w. T                double delta;
& I$ ~5 s! ]7 I4 V! g& m                delta = (max-min)/32768.0;
/ m" D. i' F4 e6 S& y) p                max -= delta;& u2 [# V! S6 t* n5 A
                min += delta;6 k/ o' r' l* u: c6 Y
                if( output > max ) max = output;' {# X5 Y3 U( r# Q
                if( output < min ) min = output;
6 j$ u; F& a+ D4 F                ave -= ave/1024.0;
: s* z# _6 {, S% }$ I& c: l8 J                ave += (max+min)/2048.0;2 A5 j  O3 N& @# u4 g6 k
                output -= (INT)ave;9 l; H5 K( I# c$ n' O( h* s/ Q) v
                }* [& G' c; m' t" \
#endif
: T. X4 N; G$ p+ P; E! H$ Q#if        1* M1 |7 j5 r# g( R& R9 x
                // DC惉暘偺僇僢僩(HPF TEST)
+ p" E% q2 a; j4 ?" T* H. E                {
, r* X8 ?4 ]# ]$ Q, e' T! Y% Q  C//                static        double        cutoff = (2.0*3.141592653579*40.0/44100.0);! ~6 l% @! ~$ V# n) |
                static        double        cutofftemp = (2.0*3.141592653579*40.0);
" N! p$ r, C% X% k5 g5 G( {                double        cutoff = cutofftemp/(double)Config.sound.nRate;
' e. ?9 v$ ~$ M8 X" V- m                static        double        tmp = 0.0;
& a  H3 L; C- R) H+ D                double        in, out;
5 x/ K& S# ]# j/ \* H, o
) @0 L- l5 p( m9 @/ T  r                in = (double)output;1 i8 u# a6 \/ t
                out = (in - tmp);
& K8 d3 \. [# {2 b( ]                tmp = tmp + cutoff * out;
0 {; K' P* |* {; d! _" L* D2 ?# R* Z! g& F
                output = (INT)out;
" |: S. h9 n; }# x0 F                }3 F) J2 L8 L' {5 V7 u8 @1 ]
#endif& \# x1 y2 F5 O. ^. O7 d+ P  m$ ~
#if        0
' U6 H7 y, f0 o2 i" N! m( L2 \                // 僗僷僀僋僲僀僘偺彍嫀(AGC TEST)' |# [" J+ [; X7 g. Y
                {
  g% e  j3 [+ [                INT        diff = abs(output-last_data);
1 W( U6 x) s5 H  F3 I, t                if( diff > 0x4000 ) {& g8 b7 q6 l; u, i0 v& }
                        output /= 4;9 D! A  n8 Z5 a% j0 k) {
                } else
; g: h; I7 c- m7 Z. N& p2 {/ b                if( diff > 0x3000 ) {7 p* w! |6 ~6 a! K3 ]2 }
                        output /= 3;
( C4 `7 |) {1 |! z                } else
8 _$ X. F# w/ R' Z+ I) Q9 w                if( diff > 0x2000 ) {
, |1 {6 l) r' t' b                        output /= 2;2 |2 R4 ], f, T* X8 \- g
                }
7 j1 b$ J% I  ^3 U. r                last_data = output;1 \8 d5 J) C/ x4 F1 s8 |/ @5 q
                }
: B& x/ f2 b! ]6 I#endif8 Q0 z+ V$ b6 E6 K
                // Limit% Y% Y: R# b: n2 O
                if( output > 0x7FFF ) {3 F7 r( u7 R7 z3 o
                        output = 0x7FFF;
4 ?, S/ r. |8 X                } else if( output < -0x8000 ) {
3 H8 z1 P6 m' K+ m                        output = -0x8000;
: x+ e7 D' c  V4 b% ?                }, @6 P, _9 ^8 {2 e! e: {4 R' \' w$ U
8 X2 Q$ W  E0 w
                if( nBits != 8 ) {
, G4 q+ ~2 t# [' A) u9 w                        *(SHORT*)lpBuffer = (SHORT)output;, e7 Y( t4 ~0 k; l
                        lpBuffer += sizeof(SHORT);  m/ u% M! o2 H1 F
                } else {$ j7 f; q; }8 T  w" b
                        *lpBuffer++ = (output>>8)^0x80;
& g& G; k7 s& R. o" ?3 K9 \4 o                }( s$ u2 W) ^1 m2 N+ v" j. Z

4 ]: A  z$ x1 {  F( ^% @7 N                if( nCcount < 0x0100 )+ j9 O8 F0 Z9 T" u; q/ z
                        pSoundBuf[nCcount++] = (SHORT)output;
2 u# J  l* ]/ Y- H/ w+ `7 v( F" b8 t0 ]" T
//                elapsedtime += cycle_rate;/ r# H& {# [$ m# h
                elapsed_time += cycle_rate;/ G3 b( h% u& j' S/ o0 G
        }
/ ^2 o; A  _& c6 B' A( t+ U
% a  A$ g1 _, R#if        1
8 _: i% P- {6 C: n# q        if( elapsed_time > ((nes->nescfg->FrameCycles/24)+nes->cpu->GetTotalCycles()) ) {2 N* @. X8 o2 x  K
                elapsed_time = nes->cpu->GetTotalCycles();
3 b8 F. ]+ n! s; N* L        }+ s" D- W+ d4 H) @# Z& ?  r8 @
        if( (elapsed_time+(nes->nescfg->FrameCycles/6)) < nes->cpu->GetTotalCycles() ) {* W8 \( ]2 k  u; E. L/ C
                elapsed_time = nes->cpu->GetTotalCycles();
; t9 ^) M& ?5 D% K0 X% M9 p        }
" e7 M. M" P3 k3 o4 |#else
; Q2 a4 }8 I& i' A- \7 x        elapsed_time = nes->cpu->GetTotalCycles();
2 ]! P9 M: e& }9 |  T5 E#endif! H) d  c/ d4 Y1 I. k* `
}
# F6 K0 D, H# U2 U9 x& b" ^8 }: S6 y# h
6 c. g. [8 k2 v1 |4 r; G// 僠儍儞僱儖偺廃攇悢庢摼僒僽儖乕僠儞(NSF梡)5 v, E$ ?. b+ L4 I8 K
INT        APU::GetChannelFrequency( INT no )
5 c3 p4 _  w+ D  }5 t{
& y6 E8 m- p, l1 S+ ~3 `        if( !m_bMute[0] )
8 s+ g0 w( A5 V' l6 d& i+ E                return        0;% u$ l# t% A! T+ n. g' m& x) ]

' e: e) R0 u' f5 b6 B: I: K        // Internal  T+ f& r1 X0 N) Q3 c: H* J; }
        if( no < 5 ) {
( A9 u9 p  r8 S                return        m_bMute[no+1]?internal.GetFreq( no ):0;
- W  T, o+ h; W7 @: G0 S        }- ~2 g; L; I% Q' H/ N" A% a
        // VRC6
" M+ s, W7 L% k" n        if( (exsound_select & 0x01) && no >= 0x0100 && no < 0x0103 ) {; J9 l7 f( T- J. Y) E% i& {
                return        m_bMute[6+(no&0x03)]?vrc6.GetFreq( no & 0x03 ):0;7 F9 P8 _3 V4 ^# G: I
        }+ E3 R) w% |+ O
        // FDS
6 _# O/ e: d; b! b1 c$ ^0 N        if( (exsound_select & 0x04) && no == 0x300 ) {" H) K1 ]4 A. P3 g1 k" E" m, C2 I
                return        m_bMute[6]?fds.GetFreq( 0 ):0;
5 d; c9 u/ ]: u+ w- }+ `# ^) Z( G& x        }. D  G2 L: e* S( c( w
        // MMC5
( s- i/ q, a5 W  i- J8 S/ W8 s8 s        if( (exsound_select & 0x08) && no >= 0x0400 && no < 0x0402 ) {
6 l6 u- ?. N9 G/ i: i* Q                return        m_bMute[6+(no&0x03)]?mmc5.GetFreq( no & 0x03 ):0;! K+ z' ~0 N3 J( H; Z, ]
        }
: V8 Q$ F  o+ M        // N106
: N) K/ `5 [/ c+ z) _        if( (exsound_select & 0x10) && no >= 0x0500 && no < 0x0508 ) {* s6 ?( M- e2 H! p
                return        m_bMute[6+(no&0x07)]?n106.GetFreq( no & 0x07 ):0;
$ [# T6 g2 U! V$ @1 {4 d3 X$ t        }
( P" \' V2 R' ^6 E9 E        // FME7
8 j% H( w; I. O% |; I- @  y0 Q        if( (exsound_select & 0x20) && no >= 0x0600 && no < 0x0603 ) {
6 c: v$ z8 J0 r0 q9 U+ P  I                return        m_bMute[6+(no&0x03)]?fme7.GetFreq( no & 0x03 ):0;+ q! R9 a0 t% s
        }8 |0 u  m) |3 ?5 n. D5 w
        // VRC7
; }# s0 I# ], P" H$ C. k" e        if( (exsound_select & 0x02) && no >= 0x0700 && no < 0x0709 ) {  j- N% F; ^+ u9 C8 |0 w+ e6 U
                return        m_bMute[6]?vrc7.GetFreq(no&0x0F):0;
% X* T) D8 P  _6 e3 b        }2 i9 t3 ]: c- ~( R7 {9 E; w
        return        0;
: [6 u5 u$ q0 {9 ^}
2 z9 z/ J6 r8 l; P  m3 p. X3 q7 I( D' f; Y7 }: H
// State Save/Load( z" ^9 @: `7 y4 k$ V2 M+ D$ L$ s
void        APU::SaveState( LPBYTE p )& `, l0 h4 h, p( R# n% B
{
6 X" x8 \5 S$ b( L5 {2 j: ^#ifdef        _DEBUG
* `; z3 e) M6 B; u! h- j0 A/ K- _' P' F3 TLPBYTE        pold = p;
' J- ]1 B: x# T, g#endif
& C4 H9 l$ B& P3 b8 t8 h; \5 l" t: v; Y( q" A# u
        // 帪娫幉傪摨婜偝偣傞堊Flush偡傞
- t7 R5 |/ O5 {* l        QueueFlush();* x* Y: j7 r, X" q9 A# Q8 H4 O2 [0 e

9 o  m8 w) P" v4 n8 \# ?        internal.SaveState( p );
" R: C, H9 w* Y$ t3 a        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding
2 L- [, C) e- q. i; n. A/ n: a+ j* d1 L
        // VRC6  c3 u1 ?  A* ^* y5 ^1 _( ~2 B
        if( exsound_select & 0x01 ) {- E& `( @2 ~7 C3 @
                vrc6.SaveState( p );
$ S- z- ]& g8 s                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding# b* B8 j6 ^' {" F7 h
        }
! ^0 f6 j; j! O) m        // VRC7 (not support)
% v- K) H" [' X9 A: [' L+ k" b        if( exsound_select & 0x02 ) {
; e! Z7 m, r# @& ~+ m                vrc7.SaveState( p );
& r1 p3 j0 m! ?                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding7 T) T. A5 f) E  }. L
        }
4 M' |- Q! k- y, `- v) T. m        // FDS" S& c# F2 A  G% O% v9 b
        if( exsound_select & 0x04 ) {
( r1 @* d# w8 _; E, L# s                fds.SaveState( p );
$ N  \7 R- B' B+ J) v                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding+ e( C7 u1 {* t
        }+ a& f/ v) |% k$ l# i2 d5 l
        // MMC5/ P: o. D* K( L# H4 j
        if( exsound_select & 0x08 ) {9 ~7 w# s1 x% d0 @5 ^1 j  b
                mmc5.SaveState( p );
$ H0 ~' C; O& d8 C                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding$ ~" U( Y& C# _* H
        }; [9 `/ X, u: p: s: j
        // N106
+ T; T4 d1 P8 r" w        if( exsound_select & 0x10 ) {
4 G* p7 G: E2 O- [' w2 {9 m6 R                n106.SaveState( p );: \+ E! l) H" O. Y. S) M0 V+ E
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
; C! C" r: `; m2 e0 }        }$ L; L. \2 ?2 s) ~( T/ C
        // FME7
, R, e; f6 G! ?$ [$ T7 A& O# E        if( exsound_select & 0x20 ) {
3 |9 v6 E  o0 L- @( M( n# ^                fme7.SaveState( p );# S" q( X+ ]! I; m9 h
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding; |9 H1 Z  J: P9 s3 ]
        }
# o# u6 J( h6 z" t0 x) {9 E6 ~; ^9 @: D) X9 G- g" W
#ifdef        _DEBUG, I* S7 I4 f! ~
DEBUGOUT( "SAVE APU SIZE:%d\n", p-pold );
% J/ h; j0 i& }. w#endif3 ~0 o1 M5 c3 ~& l+ y
}
, }2 W5 j0 d8 ~5 l6 c" }% I9 y$ `
void        APU::LoadState( LPBYTE p )+ g, m% V5 ~3 P( d3 ]5 F
{
: Q# ~+ N9 ~* R  T4 f. i        // 帪娫幉傪摨婜偝偣傞堊偵徚偡. d; |3 {. a. j( ?8 P1 c
        QueueClear();
$ z! O8 ~# y- b( u
. a; Y3 J+ }9 X% ^6 r, Q9 m. j        internal.LoadState( p );
/ n+ `( y9 a' h' b* z        p += (internal.GetStateSize()+15)&(~0x0F);        // Padding2 E- V$ y- h3 C' h% M% u" P. I

# A! ~2 a* I7 K9 G0 L2 W        // VRC6
$ D$ G* G3 [% r( }6 t/ L( ^* e        if( exsound_select & 0x01 ) {. y# Z' M2 J3 F7 O  ]9 W. o" f- R
                vrc6.LoadState( p );4 B- O2 Y$ q# U/ G  X* K
                p += (vrc6.GetStateSize()+15)&(~0x0F);        // Padding3 _6 @; I  b8 c7 v$ I1 r$ _, m
        }& t) [: i, F! ~: p% Y5 v( ~/ e! B
        // VRC7 (not support)& K% Q3 m4 v/ r, k
        if( exsound_select & 0x02 ) {
# ]6 d. U- t" N/ l" q" |' A                vrc7.LoadState( p );
/ ^# v( K# s$ t0 j) U6 j5 l                p += (vrc7.GetStateSize()+15)&(~0x0F);        // Padding" J1 j  T1 b1 v; N
        }$ |, Y4 b! W* E* a" l
        // FDS8 O1 a# ]1 y5 _; B  L: X+ c8 Q" K
        if( exsound_select & 0x04 ) {
; }& X, T* Y3 ~! W$ L0 ^# d0 o7 ^                fds.LoadState( p );' S( U* @# B6 |& z+ R6 ^! R$ P, {
                p += (fds.GetStateSize()+15)&(~0x0F);        // Padding
+ Q+ B. L! m: H- [- |# P0 C' }% P  A        }7 H* J* u: i0 [" E$ @# y
        // MMC5' ~- c! @% V3 R8 N
        if( exsound_select & 0x08 ) {
4 R3 S! o. U8 F$ ~. S# u+ B/ i                mmc5.LoadState( p );$ Y# r4 A- D# d  k! T& \; A
                p += (mmc5.GetStateSize()+15)&(~0x0F);        // Padding
2 N7 w2 L+ |6 B& n        }* U$ C5 K9 O7 u  G: u- M* _
        // N106
! U* N0 z* S; v        if( exsound_select & 0x10 ) {
& g5 H/ [7 d* M, @" @/ x                n106.LoadState( p );( A. Y$ H* }6 k7 s& H  `
                p += (n106.GetStateSize()+15)&(~0x0F);        // Padding
  K: j& b& {# I! ?3 J        }
( ?' j; \" E& |        // FME7
+ D1 Q& B, L! p2 y8 x! y5 `+ b        if( exsound_select & 0x20 ) {
5 x' Z; {1 H, _4 k7 k/ u' \) e0 ?2 p                fme7.LoadState( p );5 o! S4 Q7 g  n- O7 Y
                p += (fme7.GetStateSize()+15)&(~0x0F);        // Padding
8 v7 W/ n+ A+ Q5 M# p) s( f        }6 ^0 ~# C1 B. X3 F. K; `: x
}

该用户从未签到

发表于 2009-11-8 17:25:37 | 显示全部楼层
原帖由 独孤残云 于 2009-11-8 14:38 发表 ( {. t* i* a2 u3 r
可以的话,希望可以得到krizal团长大人或者哪位大侠的详细赐教,就是指Apu模块下这些函数的具体含义和作用。我对这些NES机制的算法很感兴趣。5 C6 G6 _+ |1 d: s1 m/ i3 Z
感激不尽~~

; z/ x& x  g& m, Y  g- U2 b- J4 W恩 我對模擬器不是很有研究,
8 E1 u8 e8 K: ?雖然要了解源碼內容,可能不是很困難,; W% L& f  U( i
不過還是要花時間,個人目前蠻忙碌的。. w+ I5 b# _8 E8 F
, X& J6 i9 b3 }9 ~6 l
給你一個朋友的MSN,你可以跟他討論看看,
9 d4 J# G9 Z+ p! G他本身是程式設計師,也對FC模擬器很有興趣。
! S% G3 T/ |" u  v/ _' P
3 @; c9 n) @1 hMSN我就PM到你的信箱了。/ q# z: W+ E5 T  g6 V- W6 Q4 C
) I0 s$ w9 c# v" P' k3 O% r; X, \
希望你能有所得。

该用户从未签到

 楼主| 发表于 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 发表
0 f, k7 {0 M& L, J! S( h/ [  A呵…… 谢过团长大人~~

) _5 `! `! O1 v! D
& \0 |- w; W& T; R哈 不客氣,算是順便幫他找個伴,大家可以一起玩。

该用户从未签到

发表于 2009-11-20 13:14:53 | 显示全部楼层
原帖由 李伟 于 2009-11-9 16:02 发表 5 u0 j7 H) H7 k4 y5 k
团长的朋友都是神,那团长就是神的boss。
$ y+ B7 p0 L7 \7 a  F
哈 不敢當,我只是個平凡人,+ A* s0 O$ W1 u
要吃飯喝水,光吸空氣是不會飽的。。。。 :)

该用户从未签到

发表于 2009-11-20 13:32:35 | 显示全部楼层
FC模拟器的部分有个人可以帮你忙
* r' F! {4 G8 G. |+ \+ `, aZYH. M3 p6 M- U4 y, y5 }* \
QQ:414734306
) k1 V$ o# U7 oMail:zyh-01@126.com
9 M5 b6 Q) \/ `, X# T, Q, x3 W
' ?9 z+ }) n' l9 L* h1 P他是ZYH Emulator这个模拟器的作者,只是他用的开发平台是VB,不过就6502的实现原理来说是一样的

该用户从未签到

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

该用户从未签到

发表于 2009-11-27 19:09:06 | 显示全部楼层
原帖由 独孤残云 于 2009-11-27 09:48 发表 . T6 Q7 h+ u+ H0 [0 V& W
再次对团长大人和悠悠哥的无私帮助表示感谢~~
7 V- y8 E( v4 F& R& K+ D
不客氣  ^_^
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

GMT+8, 2026-1-13 17:47 , Processed in 1.100586 second(s), 18 queries , Gzip On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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